1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41#include <linux/kernel.h>
42#include <linux/slab.h>
43#include <linux/fs.h>
44#include <linux/mtd/mtd.h>
45#include <linux/jffs2.h>
46#include "nodelist.h"
47#include <linux/crc32.h>
48
49
50D1(void jffs2_print_frag_list(struct jffs2_inode_info *f)
51{
52 struct jffs2_node_frag *this = f->fraglist;
53
54 while(this) {
55 if (this->node)
56 printk(KERN_DEBUG "frag %04x-%04x: 0x%08x on flash (*%p->%p)\n", this->ofs, this->ofs+this->size, this->node->raw->flash_offset &~3, this, this->next);
57 else
58 printk(KERN_DEBUG "frag %04x-%04x: hole (*%p->%p)\n", this->ofs, this->ofs+this->size, this, this->next);
59 this = this->next;
60 }
61 if (f->metadata) {
62 printk(KERN_DEBUG "metadata at 0x%08x\n", f->metadata->raw->flash_offset &~3);
63 }
64})
65
66
67int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn)
68{
69 int ret;
70 D1(printk(KERN_DEBUG "jffs2_add_full_dnode_to_inode(ino #%u, f %p, fn %p)\n", f->inocache->ino, f, fn));
71
72 ret = jffs2_add_full_dnode_to_fraglist(c, &f->fraglist, fn);
73
74 D2(jffs2_print_frag_list(f));
75 return ret;
76}
77
78static void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *this)
79{
80 if (this->node) {
81 this->node->frags--;
82 if (!this->node->frags) {
83
84 D2(printk(KERN_DEBUG "Marking old node @0x%08x (0x%04x-0x%04x) obsolete\n",
85 this->node->raw->flash_offset &~3, this->node->ofs, this->node->ofs+this->node->size));
86 jffs2_mark_node_obsolete(c, this->node->raw);
87 jffs2_free_full_dnode(this->node);
88 } else {
89 D2(printk(KERN_DEBUG "Not marking old node @0x%08x (0x%04x-0x%04x) obsolete. frags is %d\n",
90 this->node->raw->flash_offset &~3, this->node->ofs, this->node->ofs+this->node->size,
91 this->node->frags));
92 }
93
94 }
95 jffs2_free_node_frag(this);
96}
97
98
99int jffs2_add_full_dnode_to_fraglist(struct jffs2_sb_info *c, struct jffs2_node_frag **list, struct jffs2_full_dnode *fn)
100{
101
102 struct jffs2_node_frag *this, **prev, *old;
103 struct jffs2_node_frag *newfrag, *newfrag2;
104 __u32 lastend = 0;
105
106
107 newfrag = jffs2_alloc_node_frag();
108 if (!newfrag) {
109 return -ENOMEM;
110 }
111
112 D2(if (fn->raw)
113 printk(KERN_DEBUG "adding node %04x-%04x @0x%08x on flash, newfrag *%p\n", fn->ofs, fn->ofs+fn->size, fn->raw->flash_offset &~3, newfrag);
114 else
115 printk(KERN_DEBUG "adding hole node %04x-%04x on flash, newfrag *%p\n", fn->ofs, fn->ofs+fn->size, newfrag));
116
117 prev = list;
118 this = *list;
119
120 if (!fn->size) {
121 jffs2_free_node_frag(newfrag);
122 return 0;
123 }
124
125 newfrag->ofs = fn->ofs;
126 newfrag->size = fn->size;
127 newfrag->node = fn;
128 newfrag->node->frags = 1;
129 newfrag->next = (void *)0xdeadbeef;
130
131
132 while(this && fn->ofs >= this->ofs+this->size) {
133 lastend = this->ofs + this->size;
134
135 D2(printk(KERN_DEBUG "j_a_f_d_t_f: skipping frag 0x%04x-0x%04x; phys 0x%08x (*%p->%p)\n",
136 this->ofs, this->ofs+this->size, this->node?(this->node->raw->flash_offset &~3):0xffffffff, this, this->next));
137 prev = &this->next;
138 this = this->next;
139 }
140
141
142 if (!this) {
143
144 if (lastend < fn->ofs) {
145
146 struct jffs2_node_frag *holefrag = jffs2_alloc_node_frag();
147 if (!holefrag)
148 return -ENOMEM;
149 holefrag->ofs = lastend;
150 holefrag->size = fn->ofs - lastend;
151 holefrag->next = NULL;
152 holefrag->node = NULL;
153 *prev = holefrag;
154 prev = &holefrag->next;
155 }
156 newfrag->next = NULL;
157 *prev = newfrag;
158 return 0;
159 }
160
161 D2(printk(KERN_DEBUG "j_a_f_d_t_f: dealing with frag 0x%04x-0x%04x; phys 0x%08x (*%p->%p)\n",
162 this->ofs, this->ofs+this->size, this->node?(this->node->raw->flash_offset &~3):0xffffffff, this, this->next));
163
164
165
166
167 if (fn->ofs > this->ofs) {
168
169 if (this->ofs + this->size > fn->ofs + fn->size) {
170
171 newfrag2 = jffs2_alloc_node_frag();
172 if (!newfrag2) {
173 jffs2_free_node_frag(newfrag);
174 return -ENOMEM;
175 }
176 D1(printk(KERN_DEBUG "split old frag 0x%04x-0x%04x -->", this->ofs, this->ofs+this->size);
177 if (this->node)
178 printk("phys 0x%08x\n", this->node->raw->flash_offset &~3);
179 else
180 printk("hole\n");
181 )
182 newfrag2->ofs = fn->ofs + fn->size;
183 newfrag2->size = (this->ofs+this->size) - newfrag2->ofs;
184 newfrag2->next = this->next;
185 newfrag2->node = this->node;
186 if (this->node)
187 this->node->frags++;
188 newfrag->next = newfrag2;
189 this->next = newfrag;
190 this->size = newfrag->ofs - this->ofs;
191 return 0;
192 }
193
194 this->size = fn->ofs - this->ofs;
195 newfrag->next = this->next;
196 this->next = newfrag;
197 this = newfrag->next;
198 } else {
199 D2(printk(KERN_DEBUG "Inserting newfrag (*%p) in before 'this' (*%p)\n", newfrag, this));
200 *prev = newfrag;
201 newfrag->next = this;
202 }
203
204
205
206 while (this && newfrag->ofs + newfrag->size >= this->ofs + this->size) {
207
208 old = this;
209 this = old->next;
210 jffs2_obsolete_node_frag(c, old);
211 }
212
213
214 newfrag->next = this;
215
216 if (!this || newfrag->ofs + newfrag->size == this->ofs) {
217 return 0;
218 }
219
220 this->size = (this->ofs + this->size) - (newfrag->ofs + newfrag->size);
221 this->ofs = newfrag->ofs + newfrag->size;
222 return 0;
223}
224
225void jffs2_truncate_fraglist (struct jffs2_sb_info *c, struct jffs2_node_frag **list, __u32 size)
226{
227 D1(printk(KERN_DEBUG "Truncating fraglist to 0x%08x bytes\n", size));
228
229 while (*list) {
230 if ((*list)->ofs >= size) {
231 struct jffs2_node_frag *this = *list;
232 *list = this->next;
233 D1(printk(KERN_DEBUG "Removing frag 0x%08x-0x%08x\n", this->ofs, this->ofs+this->size));
234 jffs2_obsolete_node_frag(c, this);
235 continue;
236 } else if ((*list)->ofs + (*list)->size > size) {
237 D1(printk(KERN_DEBUG "Truncating frag 0x%08x-0x%08x\n", (*list)->ofs, (*list)->ofs + (*list)->size));
238 (*list)->size = size - (*list)->ofs;
239 }
240 list = &(*list)->next;
241 }
242}
243
244
245
246void jffs2_read_inode (struct inode *inode)
247{
248 struct jffs2_tmp_dnode_info *tn_list, *tn;
249 struct jffs2_full_dirent *fd_list;
250 struct jffs2_inode_info *f;
251 struct jffs2_full_dnode *fn = NULL;
252 struct jffs2_sb_info *c;
253 struct jffs2_raw_inode latest_node;
254 __u32 latest_mctime, mctime_ver;
255 __u32 mdata_ver = 0;
256 int ret;
257 ssize_t retlen;
258
259 D1(printk(KERN_DEBUG "jffs2_read_inode(): inode->i_ino == %lu\n", inode->i_ino));
260
261 f = JFFS2_INODE_INFO(inode);
262 c = JFFS2_SB_INFO(inode->i_sb);
263
264 memset(f, 0, sizeof(*f));
265 D2(printk(KERN_DEBUG "getting inocache\n"));
266 init_MUTEX(&f->sem);
267 f->inocache = jffs2_get_ino_cache(c, inode->i_ino);
268 D2(printk(KERN_DEBUG "jffs2_read_inode(): Got inocache at %p\n", f->inocache));
269
270 if (!f->inocache && inode->i_ino == 1) {
271
272 f->inocache = jffs2_alloc_inode_cache();
273 if (!f->inocache) {
274 printk(KERN_CRIT "jffs2_read_inode(): Cannot allocate inocache for root inode\n");
275 make_bad_inode(inode);
276 return;
277 }
278 D1(printk(KERN_DEBUG "jffs2_read_inode(): Creating inocache for root inode\n"));
279 memset(f->inocache, 0, sizeof(struct jffs2_inode_cache));
280 f->inocache->ino = f->inocache->nlink = 1;
281 f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
282 jffs2_add_ino_cache(c, f->inocache);
283 }
284 if (!f->inocache) {
285 printk(KERN_WARNING "jffs2_read_inode() on nonexistent ino %lu\n", (unsigned long)inode->i_ino);
286 make_bad_inode(inode);
287 return;
288 }
289 D1(printk(KERN_DEBUG "jffs2_read_inode(): ino #%lu nlink is %d\n", (unsigned long)inode->i_ino, f->inocache->nlink));
290 inode->i_nlink = f->inocache->nlink;
291
292
293 ret = jffs2_get_inode_nodes(c, inode->i_ino, f, &tn_list, &fd_list, &f->highest_version, &latest_mctime, &mctime_ver);
294
295 if (ret) {
296 printk(KERN_CRIT "jffs2_get_inode_nodes() for ino %lu returned %d\n", inode->i_ino, ret);
297 make_bad_inode(inode);
298 return;
299 }
300 f->dents = fd_list;
301
302 while (tn_list) {
303 tn = tn_list;
304
305 fn = tn->fn;
306
307 if (f->metadata && tn->version > mdata_ver) {
308 D1(printk(KERN_DEBUG "Obsoleting old metadata at 0x%08x\n", f->metadata->raw->flash_offset &~3));
309 jffs2_mark_node_obsolete(c, f->metadata->raw);
310 jffs2_free_full_dnode(f->metadata);
311 f->metadata = NULL;
312
313 mdata_ver = 0;
314 }
315
316 if (fn->size) {
317 jffs2_add_full_dnode_to_inode(c, f, fn);
318 } else {
319
320 D1(printk(KERN_DEBUG "metadata @%08x: ver %d\n", fn->raw->flash_offset &~3, tn->version));
321 f->metadata = fn;
322 mdata_ver = tn->version;
323 }
324 tn_list = tn->next;
325 jffs2_free_tmp_dnode_info(tn);
326 }
327 if (!fn) {
328
329 if (inode->i_ino != 1) {
330 printk(KERN_WARNING "jffs2_read_inode(): No data nodes found for ino #%lu\n", inode->i_ino);
331 if (!fd_list) {
332 make_bad_inode(inode);
333 return;
334 }
335 printk(KERN_WARNING "jffs2_read_inode(): But it has children so we fake some modes for it\n");
336 }
337 inode->i_mode = S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO;
338 latest_node.version = 0;
339 inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME;
340 inode->i_nlink = f->inocache->nlink;
341 inode->i_size = 0;
342 } else {
343 __u32 crc;
344
345 ret = c->mtd->read(c->mtd, fn->raw->flash_offset & ~3, sizeof(latest_node), &retlen, (void *)&latest_node);
346 if (ret || retlen != sizeof(latest_node)) {
347 printk(KERN_NOTICE "MTD read in jffs2_read_inode() failed: Returned %d, %ld of %d bytes read\n",
348 ret, (long)retlen, sizeof(latest_node));
349 jffs2_clear_inode(inode);
350 make_bad_inode(inode);
351 return;
352 }
353
354 crc = crc32(0, &latest_node, sizeof(latest_node)-8);
355 if (crc != latest_node.node_crc) {
356 printk(KERN_NOTICE "CRC failed for read_inode of inode %ld at physical location 0x%x\n", inode->i_ino, fn->raw->flash_offset & ~3);
357 jffs2_clear_inode(inode);
358 make_bad_inode(inode);
359 return;
360 }
361
362 inode->i_mode = latest_node.mode;
363 inode->i_uid = latest_node.uid;
364 inode->i_gid = latest_node.gid;
365 inode->i_size = latest_node.isize;
366 if (S_ISREG(inode->i_mode))
367 jffs2_truncate_fraglist(c, &f->fraglist, latest_node.isize);
368 inode->i_atime = latest_node.atime;
369 inode->i_mtime = latest_node.mtime;
370 inode->i_ctime = latest_node.ctime;
371 }
372
373
374
375
376 if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode) ||
377 S_ISLNK(inode->i_mode)) {
378 if (f->metadata) {
379 printk(KERN_WARNING "Argh. Special inode #%lu with mode 0%o had metadata node\n", inode->i_ino, inode->i_mode);
380 jffs2_clear_inode(inode);
381 make_bad_inode(inode);
382 return;
383 }
384 if (!f->fraglist) {
385 printk(KERN_WARNING "Argh. Special inode #%lu with mode 0%o has no fragments\n", inode->i_ino, inode->i_mode);
386 jffs2_clear_inode(inode);
387 make_bad_inode(inode);
388 return;
389 }
390
391 if (f->fraglist->next) {
392 printk(KERN_WARNING "Argh. Special inode #%lu with mode 0%o had more than one node\n", inode->i_ino, inode->i_mode);
393
394 jffs2_clear_inode(inode);
395 make_bad_inode(inode);
396 return;
397 }
398
399 f->metadata = f->fraglist->node;
400 jffs2_free_node_frag(f->fraglist);
401 f->fraglist = NULL;
402 }
403
404 inode->i_blksize = PAGE_SIZE;
405 inode->i_blocks = (inode->i_size + 511) >> 9;
406
407 switch (inode->i_mode & S_IFMT) {
408 unsigned short rdev;
409
410 case S_IFLNK:
411 inode->i_op = &jffs2_symlink_inode_operations;
412
413
414
415
416 if (!inode->i_size)
417 inode->i_size = latest_node.dsize;
418 break;
419
420 case S_IFDIR:
421 if (mctime_ver > latest_node.version) {
422
423
424 inode->i_mtime = inode->i_ctime = inode->i_atime =
425 latest_mctime;
426 }
427 inode->i_op = &jffs2_dir_inode_operations;
428 inode->i_fop = &jffs2_dir_operations;
429 break;
430
431 case S_IFREG:
432 inode->i_op = &jffs2_file_inode_operations;
433 inode->i_fop = &jffs2_file_operations;
434 inode->i_mapping->a_ops = &jffs2_file_address_operations;
435 inode->i_mapping->nrpages = 0;
436 break;
437
438 case S_IFBLK:
439 case S_IFCHR:
440
441 D1(printk(KERN_DEBUG "Reading device numbers from flash\n"));
442 if (jffs2_read_dnode(c, f->metadata, (char *)&rdev, 0, sizeof(rdev)) < 0) {
443
444 printk(KERN_NOTICE "Read device numbers for inode %lu failed\n", (unsigned long)inode->i_ino);
445 jffs2_clear_inode(inode);
446 make_bad_inode(inode);
447 return;
448 }
449
450 case S_IFSOCK:
451 case S_IFIFO:
452 inode->i_op = &jffs2_file_inode_operations;
453 init_special_inode(inode, inode->i_mode, kdev_t_to_nr(MKDEV(rdev>>8, rdev&0xff)));
454 break;
455
456 default:
457 printk(KERN_WARNING "jffs2_read_inode(): Bogus imode %o for ino %lu", inode->i_mode, (unsigned long)inode->i_ino);
458 }
459 D1(printk(KERN_DEBUG "jffs2_read_inode() returning\n"));
460}
461
462void jffs2_clear_inode (struct inode *inode)
463{
464
465
466
467 struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
468 struct jffs2_node_frag *frag, *frags;
469 struct jffs2_full_dirent *fd, *fds;
470 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
471 int deleted;
472
473 D1(printk(KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n", inode->i_ino, inode->i_mode));
474
475 down(&f->sem);
476 deleted = f->inocache && !f->inocache->nlink;
477
478 frags = f->fraglist;
479 fds = f->dents;
480 if (f->metadata) {
481 if (deleted)
482 jffs2_mark_node_obsolete(c, f->metadata->raw);
483 jffs2_free_full_dnode(f->metadata);
484 }
485
486 while (frags) {
487 frag = frags;
488 frags = frag->next;
489 D2(printk(KERN_DEBUG "jffs2_clear_inode: frag at 0x%x-0x%x: node %p, frags %d--\n", frag->ofs, frag->ofs+frag->size, frag->node, frag->node?frag->node->frags:0));
490
491 if (frag->node && !(--frag->node->frags)) {
492
493 if (deleted)
494 jffs2_mark_node_obsolete(c, frag->node->raw);
495
496 jffs2_free_full_dnode(frag->node);
497 }
498 jffs2_free_node_frag(frag);
499 }
500 while(fds) {
501 fd = fds;
502 fds = fd->next;
503 jffs2_free_full_dirent(fd);
504 }
505
506 up(&f->sem);
507};
508
509