[PATCH 5/5] f2fs: Fix for parent inode information during server cache eviction

From: Namjae Jeon
Date: Sat Dec 08 2012 - 00:55:48 EST


From: Namjae Jeon <namjae.jeon@xxxxxxxxxxx>

Test Case:
[NFS Client]
ls -lR .

[NFS Server]
while [ 1 ]
do
echo 3 > /proc/sys/vm/drop_caches
done

Error: "No such file or directory"

When cache is dropped at the server, it results in lookup failure at the
NFS client. Even though the file exists. Looking at the code to rebuild
the inode in case of cache eviction. It tries to initiate a lookup operation
for ".." to get the parent information using the on-disk inode number.

But, in case of f2fs we do not need to perform a lookup based upon name.
As for f2fs layout - the f2fs inode already has reference to the parent
inode number. So, like a normal inode build-up, parent inode can also be
regenerated by reading parent inode number.

f2fs_inode_info represents the in-memory inode, while f2fs_inode represents
the on-disk. So, we introduce the parent inode number in the f2fs_inode_info also.
Whild doing do_read_inode() reading on-disk information, we populate the parent
inode number also.This way whenever we reference f2fs_inode using F2FS_I over
VFS inode. We are sure to get the parent inode in the inode.

Signed-off-by: Namjae Jeon <namjae.jeon@xxxxxxxxxxx>
Signed-off-by: Amit Sahrawat <a.sahrawat@xxxxxxxxxxx>
---
fs/f2fs/dir.c | 16 ----------------
fs/f2fs/f2fs.h | 1 +
fs/f2fs/inode.c | 1 +
fs/f2fs/namei.c | 5 +++--
4 files changed, 5 insertions(+), 18 deletions(-)

diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index d900c08..a4c9c9d 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -226,22 +226,6 @@ struct f2fs_dir_entry *f2fs_parent_dir(struct inode *dir, struct page **p)
return de;
}

-ino_t f2fs_inode_by_name(struct inode *dir, struct qstr *qstr)
-{
- ino_t res = 0;
- struct f2fs_dir_entry *de;
- struct page *page;
-
- de = f2fs_find_entry(dir, qstr, &page);
- if (de) {
- res = le32_to_cpu(de->ino);
- kunmap(page);
- f2fs_put_page(page, 0);
- }
-
- return res;
-}
-
void f2fs_set_link(struct inode *dir, struct f2fs_dir_entry *de,
struct page *page, struct inode *inode)
{
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 8c3f1ef..0b56cbb 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -146,6 +146,7 @@ struct f2fs_inode_info {
unsigned int clevel; /* maximum level of given file name */
nid_t i_xattr_nid; /* node id that contains xattrs */
struct extent_info ext; /* in-memory extent cache entry */
+ unsigned long parent_ino;
};

static inline void get_extent_info(struct extent_info *ext,
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index aa4ef4f..1880d8a 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -107,6 +107,7 @@ static int do_read_inode(struct inode *inode)
fi->flags = 0;
fi->data_version = le64_to_cpu(F2FS_CKPT(sbi)->checkpoint_ver) - 1;
fi->i_advise = ri->i_advise;
+ fi->parent_ino = le32_to_cpu(ri->i_pino);
get_extent_info(&fi->ext, ri->i_ext);
f2fs_put_page(node_page, 1);
return 0;
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
index 89b7675..ab021cc 100644
--- a/fs/f2fs/namei.c
+++ b/fs/f2fs/namei.c
@@ -183,8 +183,9 @@ out:

struct dentry *f2fs_get_parent(struct dentry *child)
{
- struct qstr dotdot = QSTR_INIT("..", 2);
- unsigned long ino = f2fs_inode_by_name(child->d_inode, &dotdot);
+ unsigned long ino;
+ struct f2fs_inode_info *fi = F2FS_I(child->d_inode);
+ ino = fi->parent_ino;
if (!ino)
return ERR_PTR(-ENOENT);
return d_obtain_alias(f2fs_iget(child->d_inode->i_sb, ino));
--
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/