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