From: Namjae Jeon <linkinjeon@gmail.com>
To: hirofumi@mail.parknet.co.jp, akpm@linux-foundation.org
Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org,
Namjae Jeon <linkinjeon@gmail.com>,
Namjae Jeon <namjae.jeon@samsung.com>,
Ravishankar N <ravi.n1@samsung.com>,
Amit Sahrawat <a.sahrawat@samsung.com>
Subject: [PATCH v5 7/8] fat (exportfs): rebuild directory-inode if fat_dget() fails
Date: Wed, 21 Nov 2012 22:25:11 +0900 [thread overview]
Message-ID: <1353504311-6020-1-git-send-email-linkinjeon@gmail.com> (raw)
From: Namjae Jeon <namjae.jeon@samsung.com>
This patch enables rebuilding of directory inodes which are not present
in the cache.This is done by traversing the disk clusters to find the
directory entry of the parent directory and using its i_pos to build the
inode.
Do this only if the "nostale_ro" nfs mount option is specified.
Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>
Signed-off-by: Ravishankar N <ravi.n1@samsung.com>
Signed-off-by: Amit Sahrawat <a.sahrawat@samsung.com>
---
fs/fat/nfs.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 118 insertions(+), 1 deletion(-)
diff --git a/fs/fat/nfs.c b/fs/fat/nfs.c
index 898bef4..6a9933a 100644
--- a/fs/fat/nfs.c
+++ b/fs/fat/nfs.c
@@ -211,6 +211,120 @@ static struct dentry *fat_fh_to_parent_nostale(struct super_block *sb,
}
/*
+ * Read the directory entries of 'search_clus' and find the entry
+ * which contains 'match_ipos' for the starting cluster.If the entry
+ * is found, rebuild its inode.
+ */
+static struct inode *fat_traverse_cluster(struct super_block *sb,
+ int search_clus, int match_ipos)
+{
+ struct msdos_sb_info *sbi = MSDOS_SB(sb);
+ struct buffer_head *bh;
+ sector_t blknr;
+ int parent_ipos, search_ipos;
+ int i;
+ struct msdos_dir_entry *de;
+ struct inode *inode = NULL;
+ int iterations = sbi->cluster_size >> sb->s_blocksize_bits;
+ blknr = fat_clus_to_blknr(sbi, search_clus);
+
+ do {
+ bh = sb_bread(sb, blknr);
+ if (!bh) {
+ fat_msg(sb, KERN_ERR,
+ "NFS:unable to read block(%llu) while traversing cluster(%d)",
+ (llu)blknr, search_clus);
+ inode = ERR_PTR(-EIO);
+ goto out;
+ }
+ de = (struct msdos_dir_entry *)bh->b_data;
+ for (i = 0; i < sbi->dir_per_block; i++) {
+ if (de[i].name[0] == FAT_ENT_FREE) {
+ /*Reached end of directory*/
+ brelse(bh);
+ inode = ERR_PTR(-ENODATA);
+ goto out;
+ }
+ if (de[i].name[0] == DELETED_FLAG)
+ continue;
+ if (de[i].attr == ATTR_EXT)
+ continue;
+ if (!(de[i].attr & ATTR_DIR))
+ continue;
+ else {
+ search_ipos = fat_get_start(sbi, &de[i]);
+ if (search_ipos == match_ipos) {
+ /*Success.Now build the inode*/
+ parent_ipos = (loff_t)i +
+ (blknr << sbi->dir_per_block_bits);
+ inode = fat_build_inode(sb, &de[i],
+ parent_ipos);
+ brelse(bh);
+ goto out;
+ }
+ }
+ }
+ brelse(bh);
+ blknr += 1;
+ } while (--iterations > 0);
+out:
+ return inode;
+}
+
+/*
+ * Rebuild the parent for a directory that is not connected
+ * to the filesystem root
+ */
+static
+struct inode *fat_rebuild_parent(struct super_block *sb, int parent_logstart)
+{
+ int search_clus, clus_to_match;
+ struct msdos_dir_entry *de;
+ struct inode *parent;
+ struct fat_entry fatent;
+ struct msdos_sb_info *sbi = MSDOS_SB(sb);
+ sector_t blknr = fat_clus_to_blknr(sbi, parent_logstart);
+ struct buffer_head *parent_bh = sb_bread(sb, blknr);
+
+ if (!parent_bh) {
+ fat_msg(sb, KERN_ERR,
+ "NFS:unable to read cluster of parent directory");
+ return NULL;
+ }
+ de = (struct msdos_dir_entry *) parent_bh->b_data;
+ clus_to_match = fat_get_start(sbi, &de[0]);
+ search_clus = fat_get_start(sbi, &de[1]);
+ if (!search_clus) {
+ if (sbi->fat_bits == 32)
+ search_clus = sbi->root_cluster;
+ else
+ /* sbi->root_cluster is valid only for FAT32.
+ * Compute search_cluster such that when
+ * fat_traverse_cluster() is called for FAT 12/16,
+ * fat_clus_to_blknr() in it gives us sbi->dir_start
+ */
+ search_clus = ((int)(sbi->dir_start - sbi->data_start)
+ >> ilog2(sbi->sec_per_clus))
+ + FAT_START_ENT;
+ }
+ brelse(parent_bh);
+ do {
+ parent = fat_traverse_cluster(sb,
+ search_clus, clus_to_match);
+ if (IS_ERR(parent) || parent)
+ break;
+ fatent_init(&fatent);
+ search_clus = fat_ent_read(sb, &fatent, search_clus);
+ fatent_brelse(&fatent);
+ if (search_clus < 0 || search_clus == FAT_ENT_FREE)
+ break;
+ } while (search_clus != FAT_ENT_EOF);
+
+ return parent;
+
+}
+
+/*
* Find the parent for a directory that is not currently connected to
* the filesystem root.
*
@@ -222,10 +336,13 @@ static struct dentry *fat_get_parent(struct dentry *child_dir)
struct buffer_head *bh = NULL;
struct msdos_dir_entry *de;
struct inode *parent_inode = NULL;
+ struct msdos_sb_info *sbi = MSDOS_SB(sb);
if (!fat_get_dotdot_entry(child_dir->d_inode, &bh, &de)) {
- int parent_logstart = fat_get_start(MSDOS_SB(sb), de);
+ int parent_logstart = fat_get_start(sbi, de);
parent_inode = fat_dget(sb, parent_logstart);
+ if (!parent_inode && sbi->options.nfs == FAT_NFS_NOSTALE_RO)
+ parent_inode = fat_rebuild_parent(sb, parent_logstart);
}
brelse(bh);
--
1.7.9.5
next reply other threads:[~2012-11-21 13:25 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-11-21 13:25 Namjae Jeon [this message]
2012-12-03 9:57 ` [PATCH v5 7/8] fat (exportfs): rebuild directory-inode if fat_dget() fails OGAWA Hirofumi
2012-12-04 6:27 ` Namjae Jeon
2012-12-04 9:31 ` OGAWA Hirofumi
2012-12-05 6:01 ` Namjae Jeon
2012-12-05 9:02 ` OGAWA Hirofumi
2012-12-05 11:56 ` Namjae Jeon
2012-12-15 10:52 ` Namjae Jeon
2012-12-19 16:10 ` OGAWA Hirofumi
2012-12-21 5:03 ` Namjae Jeon
2012-12-21 5:08 ` Namjae Jeon
2012-12-21 8:19 ` OGAWA Hirofumi
2012-12-21 10:15 ` Namjae Jeon
2012-12-21 10:35 ` OGAWA Hirofumi
2012-12-21 10:36 ` OGAWA Hirofumi
2013-01-09 6:24 ` Namjae Jeon
2013-01-20 11:06 ` OGAWA Hirofumi
2013-01-22 10:31 ` Namjae Jeon
2013-01-26 4:22 ` OGAWA Hirofumi
2013-01-28 7:43 ` Namjae Jeon
2013-01-28 13:51 ` OGAWA Hirofumi
2013-01-29 5:05 ` Namjae Jeon
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1353504311-6020-1-git-send-email-linkinjeon@gmail.com \
--to=linkinjeon@gmail.com \
--cc=a.sahrawat@samsung.com \
--cc=akpm@linux-foundation.org \
--cc=hirofumi@mail.parknet.co.jp \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=namjae.jeon@samsung.com \
--cc=ravi.n1@samsung.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).