aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArtem B. Bityutskiy <dedekind@infradead.org>2005-07-17 07:13:51 -0400
committerThomas Gleixner <tglx@mtd.linutronix.de>2005-11-06 10:25:55 -0500
commit2b79adcca147c9f8fd1094ab4cb342d7e1790d70 (patch)
tree11238349e1e7861d8d4bb290719fc52269b78e65
parent730554d94607572ef8300c5c9848540b42394897 (diff)
[JFFS2] Use f->target instead of f->dents for symlink target
JFFS2 uses f->dents to store the pointer to the symlink target string (in case the inode is symlink). This is somewhat ugly to use the same field for different reasons. Introduce distinct field f->target for this purpose. Note, f->fragtree, f->dents, f->target may probably be put in a union. Signed-off-by: Artem B. Bityutskiy <dedekind@infradead.org> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--fs/jffs2/dir.c12
-rw-r--r--fs/jffs2/os-linux.h3
-rw-r--r--fs/jffs2/readinode.c45
-rw-r--r--fs/jffs2/symlink.c26
-rw-r--r--include/linux/jffs2_fs_i.h5
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 =
30static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd) 30static 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