aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jffs2/readinode.c
diff options
context:
space:
mode:
authorArtem B. Bityuckiy <dedekind@infradead.org>2005-03-01 05:50:52 -0500
committerThomas Gleixner <tglx@mtd.linutronix.de>2005-05-23 06:48:15 -0400
commit32f1a95d505b99b1f01b6aeea36ec3f97245b357 (patch)
tree5da0e8b01362cf6b0cc79f11e5e9b3fd4ad169d6 /fs/jffs2/readinode.c
parent20a6c211903dce92a0db7f19c221cfa3f2cb4c32 (diff)
[JFFS2] Add symlink caching support.
Signed-off-by: Artem B. Bityuckiy <dedekind@infradead.org> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'fs/jffs2/readinode.c')
-rw-r--r--fs/jffs2/readinode.c54
1 files changed, 48 insertions, 6 deletions
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index a1980a9da531..ef552477c813 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -7,7 +7,7 @@
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: readinode.c,v 1.118 2005/02/27 23:01:33 dwmw2 Exp $ 10 * $Id: readinode.c,v 1.119 2005/03/01 10:34:03 dedekind Exp $
11 * 11 *
12 */ 12 */
13 13
@@ -623,6 +623,40 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c,
623 case. */ 623 case. */
624 if (!je32_to_cpu(latest_node->isize)) 624 if (!je32_to_cpu(latest_node->isize))
625 latest_node->isize = latest_node->dsize; 625 latest_node->isize = latest_node->dsize;
626
627 if (f->inocache->state != INO_STATE_CHECKING) {
628 /* Symlink's inode data is the target path. Read it and
629 * keep in RAM to facilitate quick follow symlink operation.
630 * We use f->dents field to store the target path, which
631 * is somewhat ugly. */
632 f->dents = kmalloc(je32_to_cpu(latest_node->csize) + 1, GFP_KERNEL);
633 if (!f->dents) {
634 printk(KERN_WARNING "Can't allocate %d bytes of memory "
635 "for the symlink target path cache\n",
636 je32_to_cpu(latest_node->csize));
637 up(&f->sem);
638 jffs2_do_clear_inode(c, f);
639 return -ENOMEM;
640 }
641
642 ret = jffs2_flash_read(c, ref_offset(fn->raw) + sizeof(*latest_node),
643 je32_to_cpu(latest_node->csize), &retlen, (char *)f->dents);
644
645 if (ret || retlen != je32_to_cpu(latest_node->csize)) {
646 if (retlen != je32_to_cpu(latest_node->csize))
647 ret = -EIO;
648 kfree(f->dents);
649 f->dents = NULL;
650 up(&f->sem);
651 jffs2_do_clear_inode(c, f);
652 return -ret;
653 }
654
655 ((char *)f->dents)[je32_to_cpu(latest_node->csize)] = '\0';
656 D1(printk(KERN_DEBUG "jffs2_do_read_inode(): symlink's target '%s' cached\n",
657 (char *)f->dents));
658 }
659
626 /* fall through... */ 660 /* fall through... */
627 661
628 case S_IFBLK: 662 case S_IFBLK:
@@ -683,12 +717,20 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f)
683 717
684 jffs2_kill_fragtree(&f->fragtree, deleted?c:NULL); 718 jffs2_kill_fragtree(&f->fragtree, deleted?c:NULL);
685 719
686 fds = f->dents; 720 /* For symlink inodes we us f->dents to store the target path name */
721 if (S_ISLNK(OFNI_EDONI_2SFFJ(f)->i_mode)) {
722 if (f->dents) {
723 kfree(f->dents);
724 f->dents = NULL;
725 }
726 } else {
727 fds = f->dents;
687 728
688 while(fds) { 729 while(fds) {
689 fd = fds; 730 fd = fds;
690 fds = fd->next; 731 fds = fd->next;
691 jffs2_free_full_dirent(fd); 732 jffs2_free_full_dirent(fd);
733 }
692 } 734 }
693 735
694 if (f->inocache && f->inocache->state != INO_STATE_CHECKING) { 736 if (f->inocache && f->inocache->state != INO_STATE_CHECKING) {