1 | /* |
---|
2 | * JFFS2 -- Journalling Flash File System, Version 2. |
---|
3 | * |
---|
4 | * Copyright © 2001-2007 Red Hat, Inc. |
---|
5 | * |
---|
6 | * Created by David Woodhouse <dwmw2@infradead.org> |
---|
7 | * |
---|
8 | * For licensing information, see the file 'LICENCE' in this directory. |
---|
9 | * |
---|
10 | */ |
---|
11 | |
---|
12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
---|
13 | |
---|
14 | #include <linux/kernel.h> |
---|
15 | #include <linux/fs.h> |
---|
16 | #include <linux/crc32.h> |
---|
17 | #include <linux/pagemap.h> |
---|
18 | #include <linux/mtd/mtd.h> |
---|
19 | #include "nodelist.h" |
---|
20 | #include "compr.h" |
---|
21 | |
---|
22 | |
---|
23 | int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, |
---|
24 | uint32_t mode, struct jffs2_raw_inode *ri) |
---|
25 | { |
---|
26 | struct jffs2_inode_cache *ic; |
---|
27 | |
---|
28 | ic = jffs2_alloc_inode_cache(); |
---|
29 | if (!ic) { |
---|
30 | return -ENOMEM; |
---|
31 | } |
---|
32 | |
---|
33 | memset(ic, 0, sizeof(*ic)); |
---|
34 | |
---|
35 | f->inocache = ic; |
---|
36 | f->inocache->pino_nlink = 1; /* Will be overwritten shortly for directories */ |
---|
37 | f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache; |
---|
38 | f->inocache->state = INO_STATE_PRESENT; |
---|
39 | |
---|
40 | jffs2_add_ino_cache(c, f->inocache); |
---|
41 | jffs2_dbg(1, "%s(): Assigned ino# %d\n", __func__, f->inocache->ino); |
---|
42 | ri->ino = cpu_to_je32(f->inocache->ino); |
---|
43 | |
---|
44 | ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); |
---|
45 | ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); |
---|
46 | ri->totlen = cpu_to_je32(PAD(sizeof(*ri))); |
---|
47 | ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)); |
---|
48 | ri->mode = cpu_to_jemode(mode); |
---|
49 | |
---|
50 | f->highest_version = 1; |
---|
51 | ri->version = cpu_to_je32(f->highest_version); |
---|
52 | |
---|
53 | return 0; |
---|
54 | } |
---|
55 | |
---|
56 | /* jffs2_write_dnode - given a raw_inode, allocate a full_dnode for it, |
---|
57 | write it to the flash, link it into the existing inode/fragment list */ |
---|
58 | |
---|
59 | struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, |
---|
60 | struct jffs2_raw_inode *ri, const unsigned char *data, |
---|
61 | uint32_t datalen, int alloc_mode) |
---|
62 | |
---|
63 | { |
---|
64 | struct jffs2_full_dnode *fn; |
---|
65 | size_t retlen; |
---|
66 | uint32_t flash_ofs; |
---|
67 | struct kvec vecs[2]; |
---|
68 | int ret; |
---|
69 | int retried = 0; |
---|
70 | unsigned long cnt = 2; |
---|
71 | |
---|
72 | D1(if(je32_to_cpu(ri->hdr_crc) != crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)) { |
---|
73 | pr_crit("Eep. CRC not correct in jffs2_write_dnode()\n"); |
---|
74 | BUG(); |
---|
75 | } |
---|
76 | ); |
---|
77 | vecs[0].iov_base = ri; |
---|
78 | vecs[0].iov_len = sizeof(*ri); |
---|
79 | vecs[1].iov_base = (unsigned char *)data; |
---|
80 | vecs[1].iov_len = datalen; |
---|
81 | |
---|
82 | if (je32_to_cpu(ri->totlen) != sizeof(*ri) + datalen) { |
---|
83 | pr_warn("%s(): ri->totlen (0x%08x) != sizeof(*ri) (0x%08zx) + datalen (0x%08x)\n", |
---|
84 | __func__, je32_to_cpu(ri->totlen), |
---|
85 | sizeof(*ri), datalen); |
---|
86 | } |
---|
87 | |
---|
88 | fn = jffs2_alloc_full_dnode(); |
---|
89 | if (!fn) |
---|
90 | return ERR_PTR(-ENOMEM); |
---|
91 | |
---|
92 | /* check number of valid vecs */ |
---|
93 | if (!datalen || !data) |
---|
94 | cnt = 1; |
---|
95 | retry: |
---|
96 | flash_ofs = write_ofs(c); |
---|
97 | |
---|
98 | jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len); |
---|
99 | |
---|
100 | if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(ri->version) < f->highest_version)) { |
---|
101 | BUG_ON(!retried); |
---|
102 | jffs2_dbg(1, "%s(): dnode_version %d, highest version %d -> updating dnode\n", |
---|
103 | __func__, |
---|
104 | je32_to_cpu(ri->version), f->highest_version); |
---|
105 | ri->version = cpu_to_je32(++f->highest_version); |
---|
106 | ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); |
---|
107 | } |
---|
108 | |
---|
109 | ret = jffs2_flash_writev(c, vecs, cnt, flash_ofs, &retlen, |
---|
110 | (alloc_mode==ALLOC_GC)?0:f->inocache->ino); |
---|
111 | |
---|
112 | if (ret || (retlen != sizeof(*ri) + datalen)) { |
---|
113 | pr_notice("Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n", |
---|
114 | sizeof(*ri) + datalen, flash_ofs, ret, retlen); |
---|
115 | |
---|
116 | /* Mark the space as dirtied */ |
---|
117 | if (retlen) { |
---|
118 | /* Don't change raw->size to match retlen. We may have |
---|
119 | written the node header already, and only the data will |
---|
120 | seem corrupted, in which case the scan would skip over |
---|
121 | any node we write before the original intended end of |
---|
122 | this node */ |
---|
123 | jffs2_add_physical_node_ref(c, flash_ofs | REF_OBSOLETE, PAD(sizeof(*ri)+datalen), NULL); |
---|
124 | } else { |
---|
125 | pr_notice("Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", |
---|
126 | flash_ofs); |
---|
127 | } |
---|
128 | if (!retried && alloc_mode != ALLOC_NORETRY) { |
---|
129 | /* Try to reallocate space and retry */ |
---|
130 | uint32_t dummy; |
---|
131 | struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size]; |
---|
132 | |
---|
133 | retried = 1; |
---|
134 | |
---|
135 | jffs2_dbg(1, "Retrying failed write.\n"); |
---|
136 | |
---|
137 | jffs2_dbg_acct_sanity_check(c,jeb); |
---|
138 | jffs2_dbg_acct_paranoia_check(c, jeb); |
---|
139 | |
---|
140 | if (alloc_mode == ALLOC_GC) { |
---|
141 | ret = jffs2_reserve_space_gc(c, sizeof(*ri) + datalen, &dummy, |
---|
142 | JFFS2_SUMMARY_INODE_SIZE); |
---|
143 | } else { |
---|
144 | /* Locking pain */ |
---|
145 | mutex_unlock(&f->sem); |
---|
146 | jffs2_complete_reservation(c); |
---|
147 | |
---|
148 | ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &dummy, |
---|
149 | alloc_mode, JFFS2_SUMMARY_INODE_SIZE); |
---|
150 | mutex_lock(&f->sem); |
---|
151 | } |
---|
152 | |
---|
153 | if (!ret) { |
---|
154 | flash_ofs = write_ofs(c); |
---|
155 | jffs2_dbg(1, "Allocated space at 0x%08x to retry failed write.\n", |
---|
156 | flash_ofs); |
---|
157 | |
---|
158 | jffs2_dbg_acct_sanity_check(c,jeb); |
---|
159 | jffs2_dbg_acct_paranoia_check(c, jeb); |
---|
160 | |
---|
161 | goto retry; |
---|
162 | } |
---|
163 | jffs2_dbg(1, "Failed to allocate space to retry failed write: %d!\n", |
---|
164 | ret); |
---|
165 | } |
---|
166 | /* Release the full_dnode which is now useless, and return */ |
---|
167 | jffs2_free_full_dnode(fn); |
---|
168 | return ERR_PTR(ret?ret:-EIO); |
---|
169 | } |
---|
170 | /* Mark the space used */ |
---|
171 | /* If node covers at least a whole page, or if it starts at the |
---|
172 | beginning of a page and runs to the end of the file, or if |
---|
173 | it's a hole node, mark it REF_PRISTINE, else REF_NORMAL. |
---|
174 | */ |
---|
175 | if ((je32_to_cpu(ri->dsize) >= PAGE_CACHE_SIZE) || |
---|
176 | ( ((je32_to_cpu(ri->offset)&(PAGE_CACHE_SIZE-1))==0) && |
---|
177 | (je32_to_cpu(ri->dsize)+je32_to_cpu(ri->offset) == je32_to_cpu(ri->isize)))) { |
---|
178 | flash_ofs |= REF_PRISTINE; |
---|
179 | } else { |
---|
180 | flash_ofs |= REF_NORMAL; |
---|
181 | } |
---|
182 | fn->raw = jffs2_add_physical_node_ref(c, flash_ofs, PAD(sizeof(*ri)+datalen), f->inocache); |
---|
183 | if (IS_ERR(fn->raw)) { |
---|
184 | void *hold_err = fn->raw; |
---|
185 | /* Release the full_dnode which is now useless, and return */ |
---|
186 | jffs2_free_full_dnode(fn); |
---|
187 | return ERR_CAST(hold_err); |
---|
188 | } |
---|
189 | fn->ofs = je32_to_cpu(ri->offset); |
---|
190 | fn->size = je32_to_cpu(ri->dsize); |
---|
191 | fn->frags = 0; |
---|
192 | |
---|
193 | jffs2_dbg(1, "jffs2_write_dnode wrote node at 0x%08x(%d) with dsize 0x%x, csize 0x%x, node_crc 0x%08x, data_crc 0x%08x, totlen 0x%08x\n", |
---|
194 | flash_ofs & ~3, flash_ofs & 3, je32_to_cpu(ri->dsize), |
---|
195 | je32_to_cpu(ri->csize), je32_to_cpu(ri->node_crc), |
---|
196 | je32_to_cpu(ri->data_crc), je32_to_cpu(ri->totlen)); |
---|
197 | |
---|
198 | if (retried) { |
---|
199 | jffs2_dbg_acct_sanity_check(c,NULL); |
---|
200 | } |
---|
201 | |
---|
202 | return fn; |
---|
203 | } |
---|
204 | |
---|
205 | struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f, |
---|
206 | struct jffs2_raw_dirent *rd, const unsigned char *name, |
---|
207 | uint32_t namelen, int alloc_mode) |
---|
208 | { |
---|
209 | struct jffs2_full_dirent *fd; |
---|
210 | size_t retlen; |
---|
211 | struct kvec vecs[2]; |
---|
212 | uint32_t flash_ofs; |
---|
213 | int retried = 0; |
---|
214 | int ret; |
---|
215 | |
---|
216 | jffs2_dbg(1, "%s(ino #%u, name at *0x%p \"%s\"->ino #%u, name_crc 0x%08x)\n", |
---|
217 | __func__, |
---|
218 | je32_to_cpu(rd->pino), name, name, je32_to_cpu(rd->ino), |
---|
219 | je32_to_cpu(rd->name_crc)); |
---|
220 | |
---|
221 | D1(if(je32_to_cpu(rd->hdr_crc) != crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)) { |
---|
222 | pr_crit("Eep. CRC not correct in jffs2_write_dirent()\n"); |
---|
223 | BUG(); |
---|
224 | }); |
---|
225 | |
---|
226 | if (strnlen(name, namelen) != namelen) { |
---|
227 | /* This should never happen, but seems to have done on at least one |
---|
228 | occasion: https://dev.laptop.org/ticket/4184 */ |
---|
229 | pr_crit("Error in jffs2_write_dirent() -- name contains zero bytes!\n"); |
---|
230 | pr_crit("Directory inode #%u, name at *0x%p \"%s\"->ino #%u, name_crc 0x%08x\n", |
---|
231 | je32_to_cpu(rd->pino), name, name, je32_to_cpu(rd->ino), |
---|
232 | je32_to_cpu(rd->name_crc)); |
---|
233 | WARN_ON(1); |
---|
234 | return ERR_PTR(-EIO); |
---|
235 | } |
---|
236 | |
---|
237 | vecs[0].iov_base = rd; |
---|
238 | vecs[0].iov_len = sizeof(*rd); |
---|
239 | vecs[1].iov_base = (unsigned char *)name; |
---|
240 | vecs[1].iov_len = namelen; |
---|
241 | |
---|
242 | fd = jffs2_alloc_full_dirent(namelen+1); |
---|
243 | if (!fd) |
---|
244 | return ERR_PTR(-ENOMEM); |
---|
245 | |
---|
246 | fd->version = je32_to_cpu(rd->version); |
---|
247 | fd->ino = je32_to_cpu(rd->ino); |
---|
248 | fd->nhash = full_name_hash(name, namelen); |
---|
249 | fd->type = rd->type; |
---|
250 | memcpy(fd->name, name, namelen); |
---|
251 | fd->name[namelen]=0; |
---|
252 | |
---|
253 | retry: |
---|
254 | flash_ofs = write_ofs(c); |
---|
255 | |
---|
256 | jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len); |
---|
257 | |
---|
258 | if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(rd->version) < f->highest_version)) { |
---|
259 | BUG_ON(!retried); |
---|
260 | jffs2_dbg(1, "%s(): dirent_version %d, highest version %d -> updating dirent\n", |
---|
261 | __func__, |
---|
262 | je32_to_cpu(rd->version), f->highest_version); |
---|
263 | rd->version = cpu_to_je32(++f->highest_version); |
---|
264 | fd->version = je32_to_cpu(rd->version); |
---|
265 | rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); |
---|
266 | } |
---|
267 | |
---|
268 | ret = jffs2_flash_writev(c, vecs, 2, flash_ofs, &retlen, |
---|
269 | (alloc_mode==ALLOC_GC)?0:je32_to_cpu(rd->pino)); |
---|
270 | if (ret || (retlen != sizeof(*rd) + namelen)) { |
---|
271 | pr_notice("Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n", |
---|
272 | sizeof(*rd) + namelen, flash_ofs, ret, retlen); |
---|
273 | /* Mark the space as dirtied */ |
---|
274 | if (retlen) { |
---|
275 | jffs2_add_physical_node_ref(c, flash_ofs | REF_OBSOLETE, PAD(sizeof(*rd)+namelen), NULL); |
---|
276 | } else { |
---|
277 | pr_notice("Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", |
---|
278 | flash_ofs); |
---|
279 | } |
---|
280 | if (!retried) { |
---|
281 | /* Try to reallocate space and retry */ |
---|
282 | uint32_t dummy; |
---|
283 | struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size]; |
---|
284 | |
---|
285 | retried = 1; |
---|
286 | |
---|
287 | jffs2_dbg(1, "Retrying failed write.\n"); |
---|
288 | |
---|
289 | jffs2_dbg_acct_sanity_check(c,jeb); |
---|
290 | jffs2_dbg_acct_paranoia_check(c, jeb); |
---|
291 | |
---|
292 | if (alloc_mode == ALLOC_GC) { |
---|
293 | ret = jffs2_reserve_space_gc(c, sizeof(*rd) + namelen, &dummy, |
---|
294 | JFFS2_SUMMARY_DIRENT_SIZE(namelen)); |
---|
295 | } else { |
---|
296 | /* Locking pain */ |
---|
297 | mutex_unlock(&f->sem); |
---|
298 | jffs2_complete_reservation(c); |
---|
299 | |
---|
300 | ret = jffs2_reserve_space(c, sizeof(*rd) + namelen, &dummy, |
---|
301 | alloc_mode, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); |
---|
302 | mutex_lock(&f->sem); |
---|
303 | } |
---|
304 | |
---|
305 | if (!ret) { |
---|
306 | flash_ofs = write_ofs(c); |
---|
307 | jffs2_dbg(1, "Allocated space at 0x%08x to retry failed write\n", |
---|
308 | flash_ofs); |
---|
309 | jffs2_dbg_acct_sanity_check(c,jeb); |
---|
310 | jffs2_dbg_acct_paranoia_check(c, jeb); |
---|
311 | goto retry; |
---|
312 | } |
---|
313 | jffs2_dbg(1, "Failed to allocate space to retry failed write: %d!\n", |
---|
314 | ret); |
---|
315 | } |
---|
316 | /* Release the full_dnode which is now useless, and return */ |
---|
317 | jffs2_free_full_dirent(fd); |
---|
318 | return ERR_PTR(ret?ret:-EIO); |
---|
319 | } |
---|
320 | /* Mark the space used */ |
---|
321 | fd->raw = jffs2_add_physical_node_ref(c, flash_ofs | dirent_node_state(rd), |
---|
322 | PAD(sizeof(*rd)+namelen), f->inocache); |
---|
323 | if (IS_ERR(fd->raw)) { |
---|
324 | void *hold_err = fd->raw; |
---|
325 | /* Release the full_dirent which is now useless, and return */ |
---|
326 | jffs2_free_full_dirent(fd); |
---|
327 | return ERR_CAST(hold_err); |
---|
328 | } |
---|
329 | |
---|
330 | if (retried) { |
---|
331 | jffs2_dbg_acct_sanity_check(c,NULL); |
---|
332 | } |
---|
333 | |
---|
334 | return fd; |
---|
335 | } |
---|
336 | |
---|
337 | /* The OS-specific code fills in the metadata in the jffs2_raw_inode for us, so that |
---|
338 | we don't have to go digging in struct inode or its equivalent. It should set: |
---|
339 | mode, uid, gid, (starting)isize, atime, ctime, mtime */ |
---|
340 | int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, |
---|
341 | struct jffs2_raw_inode *ri, unsigned char *buf, |
---|
342 | uint32_t offset, uint32_t writelen, uint32_t *retlen) |
---|
343 | { |
---|
344 | int ret = 0; |
---|
345 | uint32_t writtenlen = 0; |
---|
346 | |
---|
347 | jffs2_dbg(1, "%s(): Ino #%u, ofs 0x%x, len 0x%x\n", |
---|
348 | __func__, f->inocache->ino, offset, writelen); |
---|
349 | |
---|
350 | while(writelen) { |
---|
351 | struct jffs2_full_dnode *fn; |
---|
352 | unsigned char *comprbuf = NULL; |
---|
353 | uint16_t comprtype = JFFS2_COMPR_NONE; |
---|
354 | uint32_t alloclen; |
---|
355 | uint32_t datalen, cdatalen; |
---|
356 | int retried = 0; |
---|
357 | |
---|
358 | retry: |
---|
359 | jffs2_dbg(2, "jffs2_commit_write() loop: 0x%x to write to 0x%x\n", |
---|
360 | writelen, offset); |
---|
361 | |
---|
362 | ret = jffs2_reserve_space(c, sizeof(*ri) + JFFS2_MIN_DATA_LEN, |
---|
363 | &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); |
---|
364 | if (ret) { |
---|
365 | jffs2_dbg(1, "jffs2_reserve_space returned %d\n", ret); |
---|
366 | break; |
---|
367 | } |
---|
368 | mutex_lock(&f->sem); |
---|
369 | datalen = min_t(uint32_t, writelen, PAGE_CACHE_SIZE - (offset & (PAGE_CACHE_SIZE-1))); |
---|
370 | cdatalen = min_t(uint32_t, alloclen - sizeof(*ri), datalen); |
---|
371 | |
---|
372 | comprtype = jffs2_compress(c, f, buf, &comprbuf, &datalen, &cdatalen); |
---|
373 | |
---|
374 | ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); |
---|
375 | ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); |
---|
376 | ri->totlen = cpu_to_je32(sizeof(*ri) + cdatalen); |
---|
377 | ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)); |
---|
378 | |
---|
379 | ri->ino = cpu_to_je32(f->inocache->ino); |
---|
380 | ri->version = cpu_to_je32(++f->highest_version); |
---|
381 | ri->isize = cpu_to_je32(max(je32_to_cpu(ri->isize), offset + datalen)); |
---|
382 | ri->offset = cpu_to_je32(offset); |
---|
383 | ri->csize = cpu_to_je32(cdatalen); |
---|
384 | ri->dsize = cpu_to_je32(datalen); |
---|
385 | ri->compr = comprtype & 0xff; |
---|
386 | ri->usercompr = (comprtype >> 8 ) & 0xff; |
---|
387 | ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); |
---|
388 | ri->data_crc = cpu_to_je32(crc32(0, comprbuf, cdatalen)); |
---|
389 | |
---|
390 | fn = jffs2_write_dnode(c, f, ri, comprbuf, cdatalen, ALLOC_NORETRY); |
---|
391 | |
---|
392 | jffs2_free_comprbuf(comprbuf, buf); |
---|
393 | |
---|
394 | if (IS_ERR(fn)) { |
---|
395 | ret = PTR_ERR(fn); |
---|
396 | mutex_unlock(&f->sem); |
---|
397 | jffs2_complete_reservation(c); |
---|
398 | if (!retried) { |
---|
399 | /* Write error to be retried */ |
---|
400 | retried = 1; |
---|
401 | jffs2_dbg(1, "Retrying node write in jffs2_write_inode_range()\n"); |
---|
402 | goto retry; |
---|
403 | } |
---|
404 | break; |
---|
405 | } |
---|
406 | ret = jffs2_add_full_dnode_to_inode(c, f, fn); |
---|
407 | if (f->metadata) { |
---|
408 | jffs2_mark_node_obsolete(c, f->metadata->raw); |
---|
409 | jffs2_free_full_dnode(f->metadata); |
---|
410 | f->metadata = NULL; |
---|
411 | } |
---|
412 | if (ret) { |
---|
413 | /* Eep */ |
---|
414 | jffs2_dbg(1, "Eep. add_full_dnode_to_inode() failed in commit_write, returned %d\n", |
---|
415 | ret); |
---|
416 | jffs2_mark_node_obsolete(c, fn->raw); |
---|
417 | jffs2_free_full_dnode(fn); |
---|
418 | |
---|
419 | mutex_unlock(&f->sem); |
---|
420 | jffs2_complete_reservation(c); |
---|
421 | break; |
---|
422 | } |
---|
423 | mutex_unlock(&f->sem); |
---|
424 | jffs2_complete_reservation(c); |
---|
425 | if (!datalen) { |
---|
426 | pr_warn("Eep. We didn't actually write any data in jffs2_write_inode_range()\n"); |
---|
427 | ret = -EIO; |
---|
428 | break; |
---|
429 | } |
---|
430 | jffs2_dbg(1, "increasing writtenlen by %d\n", datalen); |
---|
431 | writtenlen += datalen; |
---|
432 | offset += datalen; |
---|
433 | writelen -= datalen; |
---|
434 | buf += datalen; |
---|
435 | } |
---|
436 | *retlen = writtenlen; |
---|
437 | return ret; |
---|
438 | } |
---|
439 | |
---|
440 | int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, |
---|
441 | struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, |
---|
442 | const struct qstr *qstr) |
---|
443 | { |
---|
444 | struct jffs2_raw_dirent *rd; |
---|
445 | struct jffs2_full_dnode *fn; |
---|
446 | struct jffs2_full_dirent *fd; |
---|
447 | uint32_t alloclen; |
---|
448 | int ret; |
---|
449 | |
---|
450 | /* Try to reserve enough space for both node and dirent. |
---|
451 | * Just the node will do for now, though |
---|
452 | */ |
---|
453 | ret = jffs2_reserve_space(c, sizeof(*ri), &alloclen, ALLOC_NORMAL, |
---|
454 | JFFS2_SUMMARY_INODE_SIZE); |
---|
455 | jffs2_dbg(1, "%s(): reserved 0x%x bytes\n", __func__, alloclen); |
---|
456 | if (ret) |
---|
457 | return ret; |
---|
458 | |
---|
459 | mutex_lock(&f->sem); |
---|
460 | |
---|
461 | ri->data_crc = cpu_to_je32(0); |
---|
462 | ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); |
---|
463 | |
---|
464 | fn = jffs2_write_dnode(c, f, ri, NULL, 0, ALLOC_NORMAL); |
---|
465 | |
---|
466 | jffs2_dbg(1, "jffs2_do_create created file with mode 0x%x\n", |
---|
467 | jemode_to_cpu(ri->mode)); |
---|
468 | |
---|
469 | if (IS_ERR(fn)) { |
---|
470 | jffs2_dbg(1, "jffs2_write_dnode() failed\n"); |
---|
471 | /* Eeek. Wave bye bye */ |
---|
472 | mutex_unlock(&f->sem); |
---|
473 | jffs2_complete_reservation(c); |
---|
474 | return PTR_ERR(fn); |
---|
475 | } |
---|
476 | /* No data here. Only a metadata node, which will be |
---|
477 | obsoleted by the first data write |
---|
478 | */ |
---|
479 | f->metadata = fn; |
---|
480 | |
---|
481 | mutex_unlock(&f->sem); |
---|
482 | jffs2_complete_reservation(c); |
---|
483 | |
---|
484 | ret = jffs2_init_security(&f->vfs_inode, &dir_f->vfs_inode, qstr); |
---|
485 | if (ret) |
---|
486 | return ret; |
---|
487 | ret = jffs2_init_acl_post(&f->vfs_inode); |
---|
488 | if (ret) |
---|
489 | return ret; |
---|
490 | |
---|
491 | ret = jffs2_reserve_space(c, sizeof(*rd)+qstr->len, &alloclen, |
---|
492 | ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(qstr->len)); |
---|
493 | |
---|
494 | if (ret) { |
---|
495 | /* Eep. */ |
---|
496 | jffs2_dbg(1, "jffs2_reserve_space() for dirent failed\n"); |
---|
497 | return ret; |
---|
498 | } |
---|
499 | |
---|
500 | rd = jffs2_alloc_raw_dirent(); |
---|
501 | if (!rd) { |
---|
502 | /* Argh. Now we treat it like a normal delete */ |
---|
503 | jffs2_complete_reservation(c); |
---|
504 | return -ENOMEM; |
---|
505 | } |
---|
506 | |
---|
507 | mutex_lock(&dir_f->sem); |
---|
508 | |
---|
509 | rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); |
---|
510 | rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); |
---|
511 | rd->totlen = cpu_to_je32(sizeof(*rd) + qstr->len); |
---|
512 | rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); |
---|
513 | |
---|
514 | rd->pino = cpu_to_je32(dir_f->inocache->ino); |
---|
515 | rd->version = cpu_to_je32(++dir_f->highest_version); |
---|
516 | rd->ino = ri->ino; |
---|
517 | rd->mctime = ri->ctime; |
---|
518 | rd->nsize = qstr->len; |
---|
519 | rd->type = DT_REG; |
---|
520 | rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); |
---|
521 | rd->name_crc = cpu_to_je32(crc32(0, qstr->name, qstr->len)); |
---|
522 | |
---|
523 | fd = jffs2_write_dirent(c, dir_f, rd, qstr->name, qstr->len, ALLOC_NORMAL); |
---|
524 | |
---|
525 | jffs2_free_raw_dirent(rd); |
---|
526 | |
---|
527 | if (IS_ERR(fd)) { |
---|
528 | /* dirent failed to write. Delete the inode normally |
---|
529 | as if it were the final unlink() */ |
---|
530 | jffs2_complete_reservation(c); |
---|
531 | mutex_unlock(&dir_f->sem); |
---|
532 | return PTR_ERR(fd); |
---|
533 | } |
---|
534 | |
---|
535 | /* Link the fd into the inode's list, obsoleting an old |
---|
536 | one if necessary. */ |
---|
537 | jffs2_add_fd_to_list(c, fd, &dir_f->dents); |
---|
538 | |
---|
539 | jffs2_complete_reservation(c); |
---|
540 | mutex_unlock(&dir_f->sem); |
---|
541 | |
---|
542 | return 0; |
---|
543 | } |
---|
544 | |
---|
545 | |
---|
546 | int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, |
---|
547 | const char *name, int namelen, struct jffs2_inode_info *dead_f, |
---|
548 | uint32_t time) |
---|
549 | { |
---|
550 | struct jffs2_raw_dirent *rd; |
---|
551 | struct jffs2_full_dirent *fd; |
---|
552 | uint32_t alloclen; |
---|
553 | int ret; |
---|
554 | |
---|
555 | if (!jffs2_can_mark_obsolete(c)) { |
---|
556 | /* We can't mark stuff obsolete on the medium. We need to write a deletion dirent */ |
---|
557 | |
---|
558 | rd = jffs2_alloc_raw_dirent(); |
---|
559 | if (!rd) |
---|
560 | return -ENOMEM; |
---|
561 | |
---|
562 | ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, |
---|
563 | ALLOC_DELETION, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); |
---|
564 | if (ret) { |
---|
565 | jffs2_free_raw_dirent(rd); |
---|
566 | return ret; |
---|
567 | } |
---|
568 | |
---|
569 | mutex_lock(&dir_f->sem); |
---|
570 | |
---|
571 | /* Build a deletion node */ |
---|
572 | rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); |
---|
573 | rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); |
---|
574 | rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); |
---|
575 | rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); |
---|
576 | |
---|
577 | rd->pino = cpu_to_je32(dir_f->inocache->ino); |
---|
578 | rd->version = cpu_to_je32(++dir_f->highest_version); |
---|
579 | rd->ino = cpu_to_je32(0); |
---|
580 | rd->mctime = cpu_to_je32(time); |
---|
581 | rd->nsize = namelen; |
---|
582 | rd->type = DT_UNKNOWN; |
---|
583 | rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); |
---|
584 | rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); |
---|
585 | |
---|
586 | fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, ALLOC_DELETION); |
---|
587 | |
---|
588 | jffs2_free_raw_dirent(rd); |
---|
589 | |
---|
590 | if (IS_ERR(fd)) { |
---|
591 | jffs2_complete_reservation(c); |
---|
592 | mutex_unlock(&dir_f->sem); |
---|
593 | return PTR_ERR(fd); |
---|
594 | } |
---|
595 | |
---|
596 | /* File it. This will mark the old one obsolete. */ |
---|
597 | jffs2_add_fd_to_list(c, fd, &dir_f->dents); |
---|
598 | mutex_unlock(&dir_f->sem); |
---|
599 | } else { |
---|
600 | uint32_t nhash = full_name_hash(name, namelen); |
---|
601 | |
---|
602 | fd = dir_f->dents; |
---|
603 | /* We don't actually want to reserve any space, but we do |
---|
604 | want to be holding the alloc_sem when we write to flash */ |
---|
605 | mutex_lock(&c->alloc_sem); |
---|
606 | mutex_lock(&dir_f->sem); |
---|
607 | |
---|
608 | for (fd = dir_f->dents; fd; fd = fd->next) { |
---|
609 | if (fd->nhash == nhash && |
---|
610 | !memcmp(fd->name, name, namelen) && |
---|
611 | !fd->name[namelen]) { |
---|
612 | |
---|
613 | jffs2_dbg(1, "Marking old dirent node (ino #%u) @%08x obsolete\n", |
---|
614 | fd->ino, ref_offset(fd->raw)); |
---|
615 | jffs2_mark_node_obsolete(c, fd->raw); |
---|
616 | /* We don't want to remove it from the list immediately, |
---|
617 | because that screws up getdents()/seek() semantics even |
---|
618 | more than they're screwed already. Turn it into a |
---|
619 | node-less deletion dirent instead -- a placeholder */ |
---|
620 | fd->raw = NULL; |
---|
621 | fd->ino = 0; |
---|
622 | break; |
---|
623 | } |
---|
624 | } |
---|
625 | mutex_unlock(&dir_f->sem); |
---|
626 | } |
---|
627 | |
---|
628 | /* dead_f is NULL if this was a rename not a real unlink */ |
---|
629 | /* Also catch the !f->inocache case, where there was a dirent |
---|
630 | pointing to an inode which didn't exist. */ |
---|
631 | if (dead_f && dead_f->inocache) { |
---|
632 | |
---|
633 | mutex_lock(&dead_f->sem); |
---|
634 | |
---|
635 | if (S_ISDIR(OFNI_EDONI_2SFFJ(dead_f)->i_mode)) { |
---|
636 | while (dead_f->dents) { |
---|
637 | /* There can be only deleted ones */ |
---|
638 | fd = dead_f->dents; |
---|
639 | |
---|
640 | dead_f->dents = fd->next; |
---|
641 | |
---|
642 | if (fd->ino) { |
---|
643 | pr_warn("Deleting inode #%u with active dentry \"%s\"->ino #%u\n", |
---|
644 | dead_f->inocache->ino, |
---|
645 | fd->name, fd->ino); |
---|
646 | } else { |
---|
647 | jffs2_dbg(1, "Removing deletion dirent for \"%s\" from dir ino #%u\n", |
---|
648 | fd->name, |
---|
649 | dead_f->inocache->ino); |
---|
650 | } |
---|
651 | if (fd->raw) |
---|
652 | jffs2_mark_node_obsolete(c, fd->raw); |
---|
653 | jffs2_free_full_dirent(fd); |
---|
654 | } |
---|
655 | dead_f->inocache->pino_nlink = 0; |
---|
656 | } else |
---|
657 | dead_f->inocache->pino_nlink--; |
---|
658 | /* NB: Caller must set inode nlink if appropriate */ |
---|
659 | mutex_unlock(&dead_f->sem); |
---|
660 | } |
---|
661 | |
---|
662 | jffs2_complete_reservation(c); |
---|
663 | |
---|
664 | return 0; |
---|
665 | } |
---|
666 | |
---|
667 | |
---|
668 | int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino, uint8_t type, const char *name, int namelen, uint32_t time) |
---|
669 | { |
---|
670 | struct jffs2_raw_dirent *rd; |
---|
671 | struct jffs2_full_dirent *fd; |
---|
672 | uint32_t alloclen; |
---|
673 | int ret; |
---|
674 | |
---|
675 | rd = jffs2_alloc_raw_dirent(); |
---|
676 | if (!rd) |
---|
677 | return -ENOMEM; |
---|
678 | |
---|
679 | ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, |
---|
680 | ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); |
---|
681 | if (ret) { |
---|
682 | jffs2_free_raw_dirent(rd); |
---|
683 | return ret; |
---|
684 | } |
---|
685 | |
---|
686 | mutex_lock(&dir_f->sem); |
---|
687 | |
---|
688 | /* Build a deletion node */ |
---|
689 | rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); |
---|
690 | rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); |
---|
691 | rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); |
---|
692 | rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); |
---|
693 | |
---|
694 | rd->pino = cpu_to_je32(dir_f->inocache->ino); |
---|
695 | rd->version = cpu_to_je32(++dir_f->highest_version); |
---|
696 | rd->ino = cpu_to_je32(ino); |
---|
697 | rd->mctime = cpu_to_je32(time); |
---|
698 | rd->nsize = namelen; |
---|
699 | |
---|
700 | rd->type = type; |
---|
701 | |
---|
702 | rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); |
---|
703 | rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); |
---|
704 | |
---|
705 | fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, ALLOC_NORMAL); |
---|
706 | |
---|
707 | jffs2_free_raw_dirent(rd); |
---|
708 | |
---|
709 | if (IS_ERR(fd)) { |
---|
710 | jffs2_complete_reservation(c); |
---|
711 | mutex_unlock(&dir_f->sem); |
---|
712 | return PTR_ERR(fd); |
---|
713 | } |
---|
714 | |
---|
715 | /* File it. This will mark the old one obsolete. */ |
---|
716 | jffs2_add_fd_to_list(c, fd, &dir_f->dents); |
---|
717 | |
---|
718 | jffs2_complete_reservation(c); |
---|
719 | mutex_unlock(&dir_f->sem); |
---|
720 | |
---|
721 | return 0; |
---|
722 | } |
---|