1 /*
2 * JFFS2 -- Journalling Flash File System, Version 2.
3 *
4 * Copyright (C) 2001 Red Hat, Inc.
5 *
6 * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
7 *
8 * The original JFFS, from which the design for JFFS2 was derived,
9 * was designed and implemented by Axis Communications AB.
10 *
11 * The contents of this file are subject to the Red Hat eCos Public
12 * License Version 1.1 (the "Licence"); you may not use this file
13 * except in compliance with the Licence. You may obtain a copy of
14 * the Licence at http://www.redhat.com/
15 *
16 * Software distributed under the Licence is distributed on an "AS IS"
17 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
18 * See the Licence for the specific language governing rights and
19 * limitations under the Licence.
20 *
21 * The Original Code is JFFS2 - Journalling Flash File System, version 2
22 *
23 * Alternatively, the contents of this file may be used under the
24 * terms of the GNU General Public License version 2 (the "GPL"), in
25 * which case the provisions of the GPL are applicable instead of the
26 * above. If you wish to allow the use of your version of this file
27 * only under the terms of the GPL and not to allow others to use your
28 * version of this file under the RHEPL, indicate your decision by
29 * deleting the provisions above and replace them with the notice and
30 * other provisions required by the GPL. If you do not delete the
31 * provisions above, a recipient may use your version of this file
32 * under either the RHEPL or the GPL.
33 *
34 * $Id: readinode.c,v 1.58.2.8 2003/11/02 13:54:20 dwmw2 Exp $
35 *
36 */
37
38 /* Given an inode, probably with existing list of fragments, add the new node
39 * to the fragment list.
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
D1(void jffs2_print_frag_list (struct jffs2_inode_info * f){ struct jffs2_node_frag *this = f->fraglist; while(this) { if (this->node) 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); else printk(KERN_DEBUG "frag %04x-%04x: hole (*%p->%p)\\n", this->ofs, this->ofs+this->size, this, this->next); this = this->next; } if (f->metadata) { printk(KERN_DEBUG "metadata at 0x%08x\\n", f->metadata->raw->flash_offset &~3); } })50 D1(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
67 int 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
jffs2_obsolete_node_frag(struct jffs2_sb_info * c,struct jffs2_node_frag * this)78 static 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 /* The node has no valid frags left. It's totally obsoleted */
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 /* Doesn't set inode->i_size */
jffs2_add_full_dnode_to_fraglist(struct jffs2_sb_info * c,struct jffs2_node_frag ** list,struct jffs2_full_dnode * fn)99 int 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 /* Skip all the nodes which are completed before this one starts */
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 /* See if we ran off the end of the list */
142 if (!this) {
143 /* We did */
144 if (lastend < fn->ofs) {
145 /* ... and we need to put a hole in before the new node */
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 /* OK. 'this' is pointing at the first frag that fn->ofs at least partially obsoletes,
165 * - i.e. fn->ofs < this->ofs+this->size && fn->ofs >= this->ofs
166 */
167 if (fn->ofs > this->ofs) {
168 /* This node isn't completely obsoleted. The start of it remains valid */
169 if (this->ofs + this->size > fn->ofs + fn->size) {
170 /* The new node splits 'this' frag into two */
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 /* New node just reduces 'this' frag in size, doesn't split it */
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 /* OK, now we have newfrag added in the correct place in the list, but
204 newfrag->next points to a fragment which may be overlapping it
205 */
206 while (this && newfrag->ofs + newfrag->size >= this->ofs + this->size) {
207 /* 'this' frag is obsoleted. */
208 old = this;
209 this = old->next;
210 jffs2_obsolete_node_frag(c, old);
211 }
212 /* Now we're pointing at the first frag which isn't totally obsoleted by
213 the new frag */
214 newfrag->next = this;
215
216 if (!this || newfrag->ofs + newfrag->size == this->ofs) {
217 return 0;
218 }
219 /* Still some overlap */
220 this->size = (this->ofs + this->size) - (newfrag->ofs + newfrag->size);
221 this->ofs = newfrag->ofs + newfrag->size;
222 return 0;
223 }
224
jffs2_truncate_fraglist(struct jffs2_sb_info * c,struct jffs2_node_frag ** list,__u32 size)225 void 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 /* Scan the list of all nodes present for this ino, build map of versions, etc. */
245
jffs2_read_inode(struct inode * inode)246 void 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 /* Special case - no root inode on medium */
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 /* Grab all nodes relevant to this ino */
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 /* Zero-sized node at end of version list. Just a metadata update */
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 /* No data nodes for this inode. */
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 /* OK, now the special cases. Certain inode types should
374 have only one data node, and it's kept as the metadata
375 node */
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 /* ASSERT: f->fraglist != NULL */
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 /* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */
394 jffs2_clear_inode(inode);
395 make_bad_inode(inode);
396 return;
397 }
398 /* OK. We're happy */
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 /* Hack to work around broken isize in old symlink code.
413 Remove this when dwmw2 comes to his senses and stops
414 symlinks from being an entirely gratuitous special
415 case. */
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 /* The times in the latest_node are actually older than
423 mctime in the latest dirent. Cheat. */
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 /* Read the device numbers from the media */
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 /* Eep */
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
jffs2_clear_inode(struct inode * inode)462 void jffs2_clear_inode (struct inode *inode)
463 {
464 /* We can forget about this inode for now - drop all
465 * the nodelists associated with it, etc.
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 /* Not a hole, and it's the final remaining frag of this node. Free the node */
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