Caching of reads
David Woodhouse
dwmw2 at infradead.org
Wed Nov 21 10:46:40 EST 2001
icampbell at arcom.co.uk said:
> I've instrumented my kernel a bit and found that the reads are being
> caused by calls to jffs2_follow_link (in order to resolve the sym
> links for the libraries needed to load sleep)...
> It's been pointed out to me that the jffs list might be a better place
> so I'll take this there...
Try this.
Index: include/linux/jffs2_fs_i.h
===================================================================
RCS file: /home/cvs/mtd/include/linux/jffs2_fs_i.h,v
retrieving revision 1.8
diff -u -r1.8 jffs2_fs_i.h
--- include/linux/jffs2_fs_i.h 2001/04/18 13:05:28 1.8
+++ include/linux/jffs2_fs_i.h 2001/11/21 15:45:43
@@ -44,6 +44,7 @@
/* Some stuff we just have to keep in-core at all times, for each inode. */
struct jffs2_inode_cache *inocache;
+ unsigned char *symlink_target;
/* Keep a pointer to the last physical node in the list. We don't
use the doubly-linked lists because we don't want to increase
the memory usage that much. This is simpler */
Index: fs/jffs2/readinode.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/readinode.c,v
retrieving revision 1.56
diff -u -r1.56 readinode.c
--- fs/jffs2/readinode.c 2001/07/26 20:32:39 1.56
+++ fs/jffs2/readinode.c 2001/11/21 15:45:44
@@ -458,6 +458,9 @@
D1(printk(KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n", inode->i_ino, inode->i_mode));
+ if (f->symlink_target)
+ kfree(f->symlink_target);
+
frags = f->fraglist;
fds = f->dents;
if (f->metadata) {
Index: fs/jffs2/symlink.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/symlink.c,v
retrieving revision 1.5
diff -u -r1.5 symlink.c
--- fs/jffs2/symlink.c 2001/03/15 15:38:24 1.5
+++ fs/jffs2/symlink.c 2001/11/21 15:45:44
@@ -52,7 +52,7 @@
setattr: jffs2_setattr
};
-static char *jffs2_getlink(struct dentry *dentry)
+static int jffs2_get_link_target(struct dentry *dentry)
{
struct jffs2_inode_info *f = JFFS2_INODE_INFO(dentry->d_inode);
char *buf;
@@ -60,46 +60,45 @@
if (!f->metadata) {
printk(KERN_NOTICE "No metadata for symlink inode #%lu\n", dentry->d_inode->i_ino);
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
}
buf = kmalloc(f->metadata->size+1, GFP_USER);
if (!buf)
- return ERR_PTR(-ENOMEM);
+ return -ENOMEM;
buf[f->metadata->size]=0;
ret = jffs2_read_dnode(JFFS2_SB_INFO(dentry->d_inode->i_sb), f->metadata, buf, 0, f->metadata->size);
if (ret) {
kfree(buf);
- return ERR_PTR(ret);
+ return ret;
}
- return buf;
+ f->symlink_target = buf;
+ return 0;
}
+
int jffs2_readlink(struct dentry *dentry, char *buffer, int buflen)
{
- unsigned char *kbuf;
- int ret;
+ struct jffs2_inode_info *f = JFFS2_INODE_INFO(dentry->d_inode);
+
+ if (!f->symlink_target) {
+ int ret = jffs2_get_link_target(dentry);
+ if (ret)
+ return ret;
+ }
- kbuf = jffs2_getlink(dentry);
- if (IS_ERR(kbuf))
- return PTR_ERR(kbuf);
-
- ret = vfs_readlink(dentry, buffer, buflen, kbuf);
- kfree(kbuf);
- return ret;
+ return vfs_readlink(dentry, buffer, buflen, f->symlink_target);
}
int jffs2_follow_link(struct dentry *dentry, struct nameidata *nd)
{
- unsigned char *buf;
- int ret;
-
- buf = jffs2_getlink(dentry);
+ struct jffs2_inode_info *f = JFFS2_INODE_INFO(dentry->d_inode);
- if (IS_ERR(buf))
- return PTR_ERR(buf);
+ if (!f->symlink_target) {
+ int ret = jffs2_get_link_target(dentry);
+ if (ret)
+ return ret;
+ }
- ret = vfs_follow_link(nd, buf);
- kfree(buf);
- return ret;
+ return vfs_follow_link(nd, f->symlink_target);
}
--
dwmw2
More information about the linux-mtd
mailing list