diff options
-rw-r--r-- | fs/jffs2/dir.c | 12 | ||||
-rw-r--r-- | fs/jffs2/os-linux.h | 3 | ||||
-rw-r--r-- | fs/jffs2/readinode.c | 45 | ||||
-rw-r--r-- | fs/jffs2/symlink.c | 26 | ||||
-rw-r--r-- | include/linux/jffs2_fs_i.h | 5 |
5 files changed, 44 insertions, 47 deletions
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index 3ca0d25eef1d..5738df223775 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.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: dir.c,v 1.86 2005/07/06 12:13:09 dwmw2 Exp $ | 10 | * $Id: dir.c,v 1.87 2005/07/17 11:13:46 dedekind Exp $ |
11 | * | 11 | * |
12 | */ | 12 | */ |
13 | 13 | ||
@@ -344,9 +344,9 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char | |||
344 | return PTR_ERR(fn); | 344 | return PTR_ERR(fn); |
345 | } | 345 | } |
346 | 346 | ||
347 | /* We use f->dents field to store the target path. */ | 347 | /* We use f->target field to store the target path. */ |
348 | f->dents = kmalloc(targetlen + 1, GFP_KERNEL); | 348 | f->target = kmalloc(targetlen + 1, GFP_KERNEL); |
349 | if (!f->dents) { | 349 | if (!f->target) { |
350 | printk(KERN_WARNING "Can't allocate %d bytes of memory\n", targetlen + 1); | 350 | printk(KERN_WARNING "Can't allocate %d bytes of memory\n", targetlen + 1); |
351 | up(&f->sem); | 351 | up(&f->sem); |
352 | jffs2_complete_reservation(c); | 352 | jffs2_complete_reservation(c); |
@@ -354,8 +354,8 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char | |||
354 | return -ENOMEM; | 354 | return -ENOMEM; |
355 | } | 355 | } |
356 | 356 | ||
357 | memcpy(f->dents, target, targetlen + 1); | 357 | memcpy(f->target, target, targetlen + 1); |
358 | D1(printk(KERN_DEBUG "jffs2_symlink: symlink's target '%s' cached\n", (char *)f->dents)); | 358 | D1(printk(KERN_DEBUG "jffs2_symlink: symlink's target '%s' cached\n", (char *)f->target)); |
359 | 359 | ||
360 | /* No data here. Only a metadata node, which will be | 360 | /* No data here. Only a metadata node, which will be |
361 | obsoleted by the first data write | 361 | obsoleted by the first data write |
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index d900c8929b09..0fc952eaf8c8 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h | |||
@@ -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: os-linux.h,v 1.58 2005/07/12 02:34:35 tpoynor Exp $ | 10 | * $Id: os-linux.h,v 1.59 2005/07/17 11:13:46 dedekind Exp $ |
11 | * | 11 | * |
12 | */ | 12 | */ |
13 | 13 | ||
@@ -57,6 +57,7 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) | |||
57 | f->fragtree = RB_ROOT; | 57 | f->fragtree = RB_ROOT; |
58 | f->metadata = NULL; | 58 | f->metadata = NULL; |
59 | f->dents = NULL; | 59 | f->dents = NULL; |
60 | f->target = NULL; | ||
60 | f->flags = 0; | 61 | f->flags = 0; |
61 | f->usercompr = 0; | 62 | f->usercompr = 0; |
62 | } | 63 | } |
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index cf39bcf3e3cf..49da1a6cfc81 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.126 2005/07/17 06:56:21 dedekind Exp $ | 10 | * $Id: readinode.c,v 1.127 2005/07/17 11:13:46 dedekind Exp $ |
11 | * | 11 | * |
12 | */ | 12 | */ |
13 | 13 | ||
@@ -547,11 +547,10 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, | |||
547 | 547 | ||
548 | if (f->inocache->state != INO_STATE_CHECKING) { | 548 | if (f->inocache->state != INO_STATE_CHECKING) { |
549 | /* Symlink's inode data is the target path. Read it and | 549 | /* Symlink's inode data is the target path. Read it and |
550 | * keep in RAM to facilitate quick follow symlink operation. | 550 | * keep in RAM to facilitate quick follow symlink |
551 | * We use f->dents field to store the target path, which | 551 | * operation. */ |
552 | * is somewhat ugly. */ | 552 | f->target = kmalloc(je32_to_cpu(latest_node->csize) + 1, GFP_KERNEL); |
553 | f->dents = kmalloc(je32_to_cpu(latest_node->csize) + 1, GFP_KERNEL); | 553 | if (!f->target) { |
554 | if (!f->dents) { | ||
555 | printk(KERN_WARNING "Can't allocate %d bytes of memory " | 554 | printk(KERN_WARNING "Can't allocate %d bytes of memory " |
556 | "for the symlink target path cache\n", | 555 | "for the symlink target path cache\n", |
557 | je32_to_cpu(latest_node->csize)); | 556 | je32_to_cpu(latest_node->csize)); |
@@ -561,21 +560,21 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, | |||
561 | } | 560 | } |
562 | 561 | ||
563 | ret = jffs2_flash_read(c, ref_offset(fn->raw) + sizeof(*latest_node), | 562 | ret = jffs2_flash_read(c, ref_offset(fn->raw) + sizeof(*latest_node), |
564 | je32_to_cpu(latest_node->csize), &retlen, (char *)f->dents); | 563 | je32_to_cpu(latest_node->csize), &retlen, (char *)f->target); |
565 | 564 | ||
566 | if (ret || retlen != je32_to_cpu(latest_node->csize)) { | 565 | if (ret || retlen != je32_to_cpu(latest_node->csize)) { |
567 | if (retlen != je32_to_cpu(latest_node->csize)) | 566 | if (retlen != je32_to_cpu(latest_node->csize)) |
568 | ret = -EIO; | 567 | ret = -EIO; |
569 | kfree(f->dents); | 568 | kfree(f->target); |
570 | f->dents = NULL; | 569 | f->target = NULL; |
571 | up(&f->sem); | 570 | up(&f->sem); |
572 | jffs2_do_clear_inode(c, f); | 571 | jffs2_do_clear_inode(c, f); |
573 | return -ret; | 572 | return -ret; |
574 | } | 573 | } |
575 | 574 | ||
576 | ((char *)f->dents)[je32_to_cpu(latest_node->csize)] = '\0'; | 575 | f->target[je32_to_cpu(latest_node->csize)] = '\0'; |
577 | D1(printk(KERN_DEBUG "jffs2_do_read_inode(): symlink's target '%s' cached\n", | 576 | D1(printk(KERN_DEBUG "jffs2_do_read_inode(): symlink's target '%s' cached\n", |
578 | (char *)f->dents)); | 577 | f->target)); |
579 | } | 578 | } |
580 | 579 | ||
581 | /* fall through... */ | 580 | /* fall through... */ |
@@ -638,20 +637,16 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f) | |||
638 | 637 | ||
639 | jffs2_kill_fragtree(&f->fragtree, deleted?c:NULL); | 638 | jffs2_kill_fragtree(&f->fragtree, deleted?c:NULL); |
640 | 639 | ||
641 | /* For symlink inodes we us f->dents to store the target path name */ | 640 | if (f->target) { |
642 | if (S_ISLNK(OFNI_EDONI_2SFFJ(f)->i_mode)) { | 641 | kfree(f->target); |
643 | if (f->dents) { | 642 | f->target = NULL; |
644 | kfree(f->dents); | 643 | } |
645 | f->dents = NULL; | 644 | |
646 | } | 645 | fds = f->dents; |
647 | } else { | 646 | while(fds) { |
648 | fds = f->dents; | 647 | fd = fds; |
649 | 648 | fds = fd->next; | |
650 | while(fds) { | 649 | jffs2_free_full_dirent(fd); |
651 | fd = fds; | ||
652 | fds = fd->next; | ||
653 | jffs2_free_full_dirent(fd); | ||
654 | } | ||
655 | } | 650 | } |
656 | 651 | ||
657 | if (f->inocache && f->inocache->state != INO_STATE_CHECKING) { | 652 | if (f->inocache && f->inocache->state != INO_STATE_CHECKING) { |
diff --git a/fs/jffs2/symlink.c b/fs/jffs2/symlink.c index 82ef484f5e12..6fd5ee4f90b7 100644 --- a/fs/jffs2/symlink.c +++ b/fs/jffs2/symlink.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: symlink.c,v 1.16 2005/03/01 10:50:48 dedekind Exp $ | 10 | * $Id: symlink.c,v 1.18 2005/11/06 11:03:27 gleixner Exp $ |
11 | * | 11 | * |
12 | */ | 12 | */ |
13 | 13 | ||
@@ -30,35 +30,33 @@ struct inode_operations jffs2_symlink_inode_operations = | |||
30 | static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd) | 30 | static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd) |
31 | { | 31 | { |
32 | struct jffs2_inode_info *f = JFFS2_INODE_INFO(dentry->d_inode); | 32 | struct jffs2_inode_info *f = JFFS2_INODE_INFO(dentry->d_inode); |
33 | char *p = (char *)f->dents; | 33 | char *p = (char *)f->target; |
34 | 34 | ||
35 | /* | 35 | /* |
36 | * We don't acquire the f->sem mutex here since the only data we | 36 | * We don't acquire the f->sem mutex here since the only data we |
37 | * use is f->dents which in case of the symlink inode points to the | 37 | * use is f->target. |
38 | * symlink's target path. | ||
39 | * | 38 | * |
40 | * 1. If we are here the inode has already built and f->dents has | 39 | * 1. If we are here the inode has already built and f->target has |
41 | * to point to the target path. | 40 | * to point to the target path. |
42 | * 2. Nobody uses f->dents (if the inode is symlink's inode). The | 41 | * 2. Nobody uses f->target (if the inode is symlink's inode). The |
43 | * exception is inode freeing function which frees f->dents. But | 42 | * exception is inode freeing function which frees f->target. But |
44 | * it can't be called while we are here and before VFS has | 43 | * it can't be called while we are here and before VFS has |
45 | * stopped using our f->dents string which we provide by means of | 44 | * stopped using our f->target string which we provide by means of |
46 | * nd_set_link() call. | 45 | * nd_set_link() call. |
47 | */ | 46 | */ |
48 | 47 | ||
49 | if (!p) { | 48 | if (!p) { |
50 | printk(KERN_ERR "jffs2_follow_link(): can't find symlink taerget\n"); | 49 | printk(KERN_ERR "jffs2_follow_link(): can't find symlink taerget\n"); |
51 | p = ERR_PTR(-EIO); | 50 | p = ERR_PTR(-EIO); |
52 | } else { | ||
53 | D1(printk(KERN_DEBUG "jffs2_follow_link(): target path is '%s'\n", (char *) f->dents)); | ||
54 | } | 51 | } |
52 | D1(printk(KERN_DEBUG "jffs2_follow_link(): target path is '%s'\n", (char *) f->target)); | ||
55 | 53 | ||
56 | nd_set_link(nd, p); | 54 | nd_set_link(nd, p); |
57 | 55 | ||
58 | /* | 56 | /* |
59 | * We unlock the f->sem mutex but VFS will use the f->dents string. This is safe | 57 | * We will unlock the f->sem mutex but VFS will use the f->target string. This is safe |
60 | * since the only way that may cause f->dents to be changed is iput() operation. | 58 | * since the only way that may cause f->target to be changed is iput() operation. |
61 | * But VFS will not use f->dents after iput() has been called. | 59 | * But VFS will not use f->target after iput() has been called. |
62 | */ | 60 | */ |
63 | return NULL; | 61 | return NULL; |
64 | } | 62 | } |
diff --git a/include/linux/jffs2_fs_i.h b/include/linux/jffs2_fs_i.h index 6dbb1cce6646..a5db884ec607 100644 --- a/include/linux/jffs2_fs_i.h +++ b/include/linux/jffs2_fs_i.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $Id: jffs2_fs_i.h,v 1.17 2004/11/11 23:51:27 dwmw2 Exp $ */ | 1 | /* $Id: jffs2_fs_i.h,v 1.18 2005/07/17 11:13:48 dedekind Exp $ */ |
2 | 2 | ||
3 | #ifndef _JFFS2_FS_I | 3 | #ifndef _JFFS2_FS_I |
4 | #define _JFFS2_FS_I | 4 | #define _JFFS2_FS_I |
@@ -32,6 +32,9 @@ struct jffs2_inode_info { | |||
32 | /* Directory entries */ | 32 | /* Directory entries */ |
33 | struct jffs2_full_dirent *dents; | 33 | struct jffs2_full_dirent *dents; |
34 | 34 | ||
35 | /* The target path if this is the inode of a symlink */ | ||
36 | unsigned char *target; | ||
37 | |||
35 | /* Some stuff we just have to keep in-core at all times, for each inode. */ | 38 | /* Some stuff we just have to keep in-core at all times, for each inode. */ |
36 | struct jffs2_inode_cache *inocache; | 39 | struct jffs2_inode_cache *inocache; |
37 | 40 | ||