readinode.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:17k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  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.6 2002/10/10 13:18:38 dwmw2 Exp $
  35.  *
  36.  */
  37. /* Given an inode, probably with existing list of fragments, add the new node
  38.  * to the fragment list.
  39.  */
  40. #include <linux/kernel.h>
  41. #include <linux/slab.h>
  42. #include <linux/fs.h>
  43. #include <linux/mtd/mtd.h>
  44. #include <linux/jffs2.h>
  45. #include "nodelist.h"
  46. #include "crc32.h"
  47. D1(void jffs2_print_frag_list(struct jffs2_inode_info *f)
  48. {
  49. struct jffs2_node_frag *this = f->fraglist;
  50. while(this) {
  51. if (this->node)
  52. 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);
  53. else 
  54. printk(KERN_DEBUG "frag %04x-%04x: hole (*%p->%p)n", this->ofs, this->ofs+this->size, this, this->next);
  55. this = this->next;
  56. }
  57. if (f->metadata) {
  58. printk(KERN_DEBUG "metadata at 0x%08xn", f->metadata->raw->flash_offset &~3);
  59. }
  60. })
  61. int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn)
  62. {
  63. int ret;
  64. D1(printk(KERN_DEBUG "jffs2_add_full_dnode_to_inode(ino #%u, f %p, fn %p)n", f->inocache->ino, f, fn));
  65. ret = jffs2_add_full_dnode_to_fraglist(c, &f->fraglist, fn);
  66. D2(jffs2_print_frag_list(f));
  67. return ret;
  68. }
  69. static void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *this)
  70. {
  71. if (this->node) {
  72. this->node->frags--;
  73. if (!this->node->frags) {
  74. /* The node has no valid frags left. It's totally obsoleted */
  75. D2(printk(KERN_DEBUG "Marking old node @0x%08x (0x%04x-0x%04x) obsoleten",
  76.   this->node->raw->flash_offset &~3, this->node->ofs, this->node->ofs+this->node->size));
  77. jffs2_mark_node_obsolete(c, this->node->raw);
  78. jffs2_free_full_dnode(this->node);
  79. } else {
  80. D2(printk(KERN_DEBUG "Not marking old node @0x%08x (0x%04x-0x%04x) obsolete. frags is %dn",
  81.   this->node->raw->flash_offset &~3, this->node->ofs, this->node->ofs+this->node->size,
  82.   this->node->frags));
  83. }
  84. }
  85. jffs2_free_node_frag(this);
  86. }
  87. /* Doesn't set inode->i_size */
  88. int jffs2_add_full_dnode_to_fraglist(struct jffs2_sb_info *c, struct jffs2_node_frag **list, struct jffs2_full_dnode *fn)
  89. {
  90. struct jffs2_node_frag *this, **prev, *old;
  91. struct jffs2_node_frag *newfrag, *newfrag2;
  92. __u32 lastend = 0;
  93. newfrag = jffs2_alloc_node_frag();
  94. if (!newfrag) {
  95. return -ENOMEM;
  96. }
  97. D2(if (fn->raw)
  98. printk(KERN_DEBUG "adding node %04x-%04x @0x%08x on flash, newfrag *%pn", fn->ofs, fn->ofs+fn->size, fn->raw->flash_offset &~3, newfrag);
  99. else
  100. printk(KERN_DEBUG "adding hole node %04x-%04x on flash, newfrag *%pn", fn->ofs, fn->ofs+fn->size, newfrag));
  101. prev = list;
  102. this = *list;
  103. if (!fn->size) {
  104. jffs2_free_node_frag(newfrag);
  105. return 0;
  106. }
  107. newfrag->ofs = fn->ofs;
  108. newfrag->size = fn->size;
  109. newfrag->node = fn;
  110. newfrag->node->frags = 1;
  111. newfrag->next = (void *)0xdeadbeef;
  112. /* Skip all the nodes which are completed before this one starts */
  113. while(this && fn->ofs >= this->ofs+this->size) {
  114. lastend = this->ofs + this->size;
  115. D2(printk(KERN_DEBUG "j_a_f_d_t_f: skipping frag 0x%04x-0x%04x; phys 0x%08x (*%p->%p)n", 
  116.   this->ofs, this->ofs+this->size, this->node?(this->node->raw->flash_offset &~3):0xffffffff, this, this->next));
  117. prev = &this->next;
  118. this = this->next;
  119. }
  120. /* See if we ran off the end of the list */
  121. if (!this) {
  122. /* We did */
  123. if (lastend < fn->ofs) {
  124. /* ... and we need to put a hole in before the new node */
  125. struct jffs2_node_frag *holefrag = jffs2_alloc_node_frag();
  126. if (!holefrag)
  127. return -ENOMEM;
  128. holefrag->ofs = lastend;
  129. holefrag->size = fn->ofs - lastend;
  130. holefrag->next = NULL;
  131. holefrag->node = NULL;
  132. *prev = holefrag;
  133. prev = &holefrag->next;
  134. }
  135. newfrag->next = NULL;
  136. *prev = newfrag;
  137. return 0;
  138. }
  139. D2(printk(KERN_DEBUG "j_a_f_d_t_f: dealing with frag 0x%04x-0x%04x; phys 0x%08x (*%p->%p)n", 
  140.   this->ofs, this->ofs+this->size, this->node?(this->node->raw->flash_offset &~3):0xffffffff, this, this->next));
  141. /* OK. 'this' is pointing at the first frag that fn->ofs at least partially obsoletes,
  142.  * - i.e. fn->ofs < this->ofs+this->size && fn->ofs >= this->ofs  
  143.  */
  144. if (fn->ofs > this->ofs) {
  145. /* This node isn't completely obsoleted. The start of it remains valid */
  146. if (this->ofs + this->size > fn->ofs + fn->size) {
  147. /* The new node splits 'this' frag into two */
  148. newfrag2 = jffs2_alloc_node_frag();
  149. if (!newfrag2) {
  150. jffs2_free_node_frag(newfrag);
  151. return -ENOMEM;
  152. }
  153. D1(printk(KERN_DEBUG "split old frag 0x%04x-0x%04x -->", this->ofs, this->ofs+this->size);
  154. if (this->node)
  155. printk("phys 0x%08xn", this->node->raw->flash_offset &~3);
  156. else 
  157. printk("holen");
  158.    )
  159. newfrag2->ofs = fn->ofs + fn->size;
  160. newfrag2->size = (this->ofs+this->size) - newfrag2->ofs;
  161. newfrag2->next = this->next;
  162. newfrag2->node = this->node;
  163. if (this->node)
  164. this->node->frags++;
  165. newfrag->next = newfrag2;
  166. this->next = newfrag;
  167. this->size = newfrag->ofs - this->ofs;
  168. return 0;
  169. }
  170. /* New node just reduces 'this' frag in size, doesn't split it */
  171. this->size = fn->ofs - this->ofs;
  172. newfrag->next = this->next;
  173. this->next = newfrag;
  174. this = newfrag->next;
  175. } else {
  176. D2(printk(KERN_DEBUG "Inserting newfrag (*%p) in before 'this' (*%p)n", newfrag, this));
  177. *prev = newfrag;
  178.         newfrag->next = this;
  179. }
  180. /* OK, now we have newfrag added in the correct place in the list, but
  181.    newfrag->next points to a fragment which may be overlapping it
  182. */
  183. while (this && newfrag->ofs + newfrag->size >= this->ofs + this->size) {
  184. /* 'this' frag is obsoleted. */
  185. old = this;
  186. this = old->next;
  187. jffs2_obsolete_node_frag(c, old);
  188. }
  189. /* Now we're pointing at the first frag which isn't totally obsoleted by 
  190.    the new frag */
  191. newfrag->next = this;
  192. if (!this || newfrag->ofs + newfrag->size == this->ofs) {
  193. return 0;
  194. }
  195. /* Still some overlap */
  196. this->size = (this->ofs + this->size) - (newfrag->ofs + newfrag->size);
  197. this->ofs = newfrag->ofs + newfrag->size;
  198. return 0;
  199. }
  200. void jffs2_truncate_fraglist (struct jffs2_sb_info *c, struct jffs2_node_frag **list, __u32 size)
  201. {
  202. D1(printk(KERN_DEBUG "Truncating fraglist to 0x%08x bytesn", size));
  203. while (*list) {
  204. if ((*list)->ofs >= size) {
  205. struct jffs2_node_frag *this = *list;
  206. *list = this->next;
  207. D1(printk(KERN_DEBUG "Removing frag 0x%08x-0x%08xn", this->ofs, this->ofs+this->size));
  208. jffs2_obsolete_node_frag(c, this);
  209. continue;
  210. } else if ((*list)->ofs + (*list)->size > size) {
  211. D1(printk(KERN_DEBUG "Truncating frag 0x%08x-0x%08xn", (*list)->ofs, (*list)->ofs + (*list)->size));
  212. (*list)->size = size - (*list)->ofs;
  213. }
  214. list = &(*list)->next;
  215. }
  216. }
  217. /* Scan the list of all nodes present for this ino, build map of versions, etc. */
  218. void jffs2_read_inode (struct inode *inode)
  219. {
  220. struct jffs2_tmp_dnode_info *tn_list, *tn;
  221. struct jffs2_full_dirent *fd_list;
  222. struct jffs2_inode_info *f;
  223. struct jffs2_full_dnode *fn = NULL;
  224. struct jffs2_sb_info *c;
  225. struct jffs2_raw_inode latest_node;
  226. __u32 latest_mctime, mctime_ver;
  227. __u32 mdata_ver = 0;
  228. int ret;
  229. ssize_t retlen;
  230. D1(printk(KERN_DEBUG "jffs2_read_inode(): inode->i_ino == %lun", inode->i_ino));
  231. f = JFFS2_INODE_INFO(inode);
  232. c = JFFS2_SB_INFO(inode->i_sb);
  233. memset(f, 0, sizeof(*f));
  234. D2(printk(KERN_DEBUG "getting inocachen"));
  235. init_MUTEX(&f->sem);
  236. f->inocache = jffs2_get_ino_cache(c, inode->i_ino);
  237. D2(printk(KERN_DEBUG "jffs2_read_inode(): Got inocache at %pn", f->inocache));
  238. if (!f->inocache && inode->i_ino == 1) {
  239. /* Special case - no root inode on medium */
  240. f->inocache = jffs2_alloc_inode_cache();
  241. if (!f->inocache) {
  242. printk(KERN_CRIT "jffs2_read_inode(): Cannot allocate inocache for root inoden");
  243. make_bad_inode(inode);
  244. return;
  245. }
  246. D1(printk(KERN_DEBUG "jffs2_read_inode(): Creating inocache for root inoden"));
  247. memset(f->inocache, 0, sizeof(struct jffs2_inode_cache));
  248. f->inocache->ino = f->inocache->nlink = 1;
  249. f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
  250. jffs2_add_ino_cache(c, f->inocache);
  251. }
  252. if (!f->inocache) {
  253. printk(KERN_WARNING "jffs2_read_inode() on nonexistent ino %lun", (unsigned long)inode->i_ino);
  254. make_bad_inode(inode);
  255. return;
  256. }
  257. D1(printk(KERN_DEBUG "jffs2_read_inode(): ino #%lu nlink is %dn", (unsigned long)inode->i_ino, f->inocache->nlink));
  258. inode->i_nlink = f->inocache->nlink;
  259. /* Grab all nodes relevant to this ino */
  260. ret = jffs2_get_inode_nodes(c, inode->i_ino, f, &tn_list, &fd_list, &f->highest_version, &latest_mctime, &mctime_ver);
  261. if (ret) {
  262. printk(KERN_CRIT "jffs2_get_inode_nodes() for ino %lu returned %dn", inode->i_ino, ret);
  263. make_bad_inode(inode);
  264. return;
  265. }
  266. f->dents = fd_list;
  267. while (tn_list) {
  268. tn = tn_list;
  269. fn = tn->fn;
  270. if (f->metadata && tn->version > mdata_ver) {
  271. D1(printk(KERN_DEBUG "Obsoleting old metadata at 0x%08xn", f->metadata->raw->flash_offset &~3));
  272. jffs2_mark_node_obsolete(c, f->metadata->raw);
  273. jffs2_free_full_dnode(f->metadata);
  274. f->metadata = NULL;
  275. mdata_ver = 0;
  276. }
  277. if (fn->size) {
  278. jffs2_add_full_dnode_to_inode(c, f, fn);
  279. } else {
  280. /* Zero-sized node at end of version list. Just a metadata update */
  281. D1(printk(KERN_DEBUG "metadata @%08x: ver %dn", fn->raw->flash_offset &~3, tn->version));
  282. f->metadata = fn;
  283. mdata_ver = tn->version;
  284. }
  285. tn_list = tn->next;
  286. jffs2_free_tmp_dnode_info(tn);
  287. }
  288. if (!fn) {
  289. /* No data nodes for this inode. */
  290. if (inode->i_ino != 1) {
  291. printk(KERN_WARNING "jffs2_read_inode(): No data nodes found for ino #%lun", inode->i_ino);
  292. if (!fd_list) {
  293. make_bad_inode(inode);
  294. return;
  295. }
  296. printk(KERN_WARNING "jffs2_read_inode(): But it has children so we fake some modes for itn");
  297. }
  298. inode->i_mode = S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO;
  299. latest_node.version = 0;
  300. inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME;
  301. inode->i_nlink = f->inocache->nlink;
  302. inode->i_size = 0;
  303. } else {
  304. __u32 crc;
  305. ret = c->mtd->read(c->mtd, fn->raw->flash_offset & ~3, sizeof(latest_node), &retlen, (void *)&latest_node);
  306. if (ret || retlen != sizeof(latest_node)) {
  307. printk(KERN_NOTICE "MTD read in jffs2_read_inode() failed: Returned %d, %ld of %d bytes readn",
  308.        ret, (long)retlen, sizeof(latest_node));
  309. jffs2_clear_inode(inode);
  310. make_bad_inode(inode);
  311. return;
  312. }
  313. crc = crc32(0, &latest_node, sizeof(latest_node)-8);
  314. if (crc != latest_node.node_crc) {
  315. printk(KERN_NOTICE "CRC failed for read_inode of inode %ld at physical location 0x%xn", inode->i_ino, fn->raw->flash_offset & ~3);
  316. jffs2_clear_inode(inode);
  317. make_bad_inode(inode);
  318. return;
  319. }
  320. inode->i_mode = latest_node.mode;
  321. inode->i_uid = latest_node.uid;
  322. inode->i_gid = latest_node.gid;
  323. inode->i_size = latest_node.isize;
  324. if (S_ISREG(inode->i_mode))
  325. jffs2_truncate_fraglist(c, &f->fraglist, latest_node.isize);
  326. inode->i_atime = latest_node.atime;
  327. inode->i_mtime = latest_node.mtime;
  328. inode->i_ctime = latest_node.ctime;
  329. }
  330. /* OK, now the special cases. Certain inode types should
  331.    have only one data node, and it's kept as the metadata
  332.    node */
  333. if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode) ||
  334.     S_ISLNK(inode->i_mode)) {
  335. if (f->metadata) {
  336. printk(KERN_WARNING "Argh. Special inode #%lu with mode 0%o had metadata noden", inode->i_ino, inode->i_mode);
  337. jffs2_clear_inode(inode);
  338. make_bad_inode(inode);
  339. return;
  340. }
  341. if (!f->fraglist) {
  342. printk(KERN_WARNING "Argh. Special inode #%lu with mode 0%o has no fragmentsn", inode->i_ino, inode->i_mode);
  343. jffs2_clear_inode(inode);
  344. make_bad_inode(inode);
  345. return;
  346. }
  347. /* ASSERT: f->fraglist != NULL */
  348. if (f->fraglist->next) {
  349. printk(KERN_WARNING "Argh. Special inode #%lu with mode 0%o had more than one noden", inode->i_ino, inode->i_mode);
  350. /* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */
  351. jffs2_clear_inode(inode);
  352. make_bad_inode(inode);
  353. return;
  354. }
  355. /* OK. We're happy */
  356. f->metadata = f->fraglist->node;
  357. jffs2_free_node_frag(f->fraglist);
  358. f->fraglist = NULL;
  359. }
  360.     
  361. inode->i_blksize = PAGE_SIZE;
  362. inode->i_blocks = (inode->i_size + 511) >> 9;
  363. switch (inode->i_mode & S_IFMT) {
  364. unsigned short rdev;
  365. case S_IFLNK:
  366. inode->i_op = &jffs2_symlink_inode_operations;
  367. /* Hack to work around broken isize in old symlink code.
  368.    Remove this when dwmw2 comes to his senses and stops
  369.    symlinks from being an entirely gratuitous special
  370.    case. */
  371. if (!inode->i_size)
  372. inode->i_size = latest_node.dsize;
  373. break;
  374. case S_IFDIR:
  375. if (mctime_ver > latest_node.version) {
  376. /* The times in the latest_node are actually older than
  377.    mctime in the latest dirent. Cheat. */
  378. inode->i_mtime = inode->i_ctime = inode->i_atime = 
  379. latest_mctime;
  380. }
  381. inode->i_op = &jffs2_dir_inode_operations;
  382. inode->i_fop = &jffs2_dir_operations;
  383. break;
  384. case S_IFREG:
  385. inode->i_op = &jffs2_file_inode_operations;
  386. inode->i_fop = &jffs2_file_operations;
  387. inode->i_mapping->a_ops = &jffs2_file_address_operations;
  388. inode->i_mapping->nrpages = 0;
  389. break;
  390. case S_IFBLK:
  391. case S_IFCHR:
  392. /* Read the device numbers from the media */
  393. D1(printk(KERN_DEBUG "Reading device numbers from flashn"));
  394. if (jffs2_read_dnode(c, f->metadata, (char *)&rdev, 0, sizeof(rdev)) < 0) {
  395. /* Eep */
  396. printk(KERN_NOTICE "Read device numbers for inode %lu failedn", (unsigned long)inode->i_ino);
  397. jffs2_clear_inode(inode);
  398. make_bad_inode(inode);
  399. return;
  400. }
  401. case S_IFSOCK:
  402. case S_IFIFO:
  403. inode->i_op = &jffs2_file_inode_operations;
  404. init_special_inode(inode, inode->i_mode, kdev_t_to_nr(MKDEV(rdev>>8, rdev&0xff)));
  405. break;
  406. default:
  407. printk(KERN_WARNING "jffs2_read_inode(): Bogus imode %o for ino %lu", inode->i_mode, (unsigned long)inode->i_ino);
  408. }
  409. D1(printk(KERN_DEBUG "jffs2_read_inode() returningn"));
  410. }
  411. void jffs2_clear_inode (struct inode *inode)
  412. {
  413. /* We can forget about this inode for now - drop all 
  414.  *  the nodelists associated with it, etc.
  415.  */
  416. struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
  417. struct jffs2_node_frag *frag, *frags;
  418. struct jffs2_full_dirent *fd, *fds;
  419. struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
  420.         /* I don't think we care about the potential race due to reading this
  421.            without f->sem. It can never get undeleted. */
  422.         int deleted = f->inocache && !f->inocache->nlink;
  423. D1(printk(KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %on", inode->i_ino, inode->i_mode));
  424. /* If it's a deleted inode, grab the alloc_sem. This prevents
  425.    jffs2_garbage_collect_pass() from deciding that it wants to
  426.    garbage collect one of the nodes we're just about to mark 
  427.    obsolete -- by the time we drop alloc_sem and return, all
  428.    the nodes are marked obsolete, and jffs2_g_c_pass() won't
  429.    call iget() for the inode in question.
  430. */
  431. if (deleted)
  432. down(&c->alloc_sem);
  433. down(&f->sem);
  434. frags = f->fraglist;
  435. fds = f->dents;
  436. if (f->metadata) {
  437. if (deleted)
  438. jffs2_mark_node_obsolete(c, f->metadata->raw);
  439. jffs2_free_full_dnode(f->metadata);
  440. }
  441. while (frags) {
  442. frag = frags;
  443. frags = frag->next;
  444. 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));
  445. if (frag->node && !(--frag->node->frags)) {
  446. /* Not a hole, and it's the final remaining frag of this node. Free the node */
  447. if (deleted)
  448. jffs2_mark_node_obsolete(c, frag->node->raw);
  449. jffs2_free_full_dnode(frag->node);
  450. }
  451. jffs2_free_node_frag(frag);
  452. }
  453. while(fds) {
  454. fd = fds;
  455. fds = fd->next;
  456. jffs2_free_full_dirent(fd);
  457. }
  458. up(&f->sem);
  459. if(deleted)
  460. up(&c->alloc_sem);
  461. };