From: Wendy Cheng <[email protected]>
GFS2 lookup code doesn't ask for inode shared glock. This implies during
in-memory inode creation for existing file, GFS2 will not disk-read in
the inode contents. This leaves no_formal_ino un-initialized during
lookup time. The un-initialized no_formal_ino is subsequently encoded
into file handle. Clients will get ESTALE error whenever it tries to
access these files.
Signed-off-by: S. Wendy Cheng <[email protected]>
Signed-off-by: Steven Whitehouse <[email protected]>
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index f793e31..2beb2f4 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -1498,9 +1498,10 @@ struct inode *gfs2_dir_search(struct inode *dir, const struct qstr *name)
if (dent) {
if (IS_ERR(dent))
return ERR_PTR(PTR_ERR(dent));
- inode = gfs2_inode_lookup(dir->i_sb,
- be64_to_cpu(dent->de_inum.no_addr),
- be16_to_cpu(dent->de_type));
+ inode = gfs2_inode_lookup(dir->i_sb,
+ be16_to_cpu(dent->de_type),
+ be64_to_cpu(dent->de_inum.no_addr),
+ be64_to_cpu(dent->de_inum.no_formal_ino));
brelse(bh);
return inode;
}
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 792d64f..26aaf54 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -86,7 +86,10 @@ static struct inode *gfs2_iget(struct super_block *sb, u64 no_addr)
* Returns: A VFS inode, or an error
*/
-struct inode *gfs2_inode_lookup(struct super_block *sb, u64 no_addr, unsigned int type)
+struct inode *gfs2_inode_lookup(struct super_block *sb,
+ unsigned int type,
+ u64 no_addr,
+ u64 no_formal_ino)
{
struct inode *inode = gfs2_iget(sb, no_addr);
struct gfs2_inode *ip = GFS2_I(inode);
@@ -100,6 +103,7 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, u64 no_addr, unsigned in
struct gfs2_sbd *sdp = GFS2_SB(inode);
umode_t mode;
inode->i_private = ip;
+ ip->i_no_formal_ino = no_formal_ino;
error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl);
if (unlikely(error))
@@ -915,7 +919,9 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
if (error)
goto fail_gunlock2;
- inode = gfs2_inode_lookup(dir->i_sb, inum.no_addr, IF2DT(mode));
+ inode = gfs2_inode_lookup(dir->i_sb, IF2DT(mode),
+ inum.no_addr,
+ inum.no_formal_ino);
if (IS_ERR(inode))
goto fail_gunlock2;
diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h
index 35375fc..3268a2f 100644
--- a/fs/gfs2/inode.h
+++ b/fs/gfs2/inode.h
@@ -47,7 +47,8 @@ static inline void gfs2_inum_out(const struct gfs2_inode *ip,
void gfs2_inode_attr_in(struct gfs2_inode *ip);
-struct inode *gfs2_inode_lookup(struct super_block *sb, u64 no_addr, unsigned type);
+struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned type,
+ u64 no_addr, u64 no_formal_ino);
struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr);
int gfs2_inode_refresh(struct gfs2_inode *ip);
diff --git a/fs/gfs2/ops_export.c b/fs/gfs2/ops_export.c
index d07230e..0fe1447 100644
--- a/fs/gfs2/ops_export.c
+++ b/fs/gfs2/ops_export.c
@@ -245,7 +245,9 @@ static struct dentry *gfs2_get_dentry(struct super_block *sb, void *inum_obj)
gfs2_glock_dq_uninit(&rgd_gh);
gfs2_glock_dq_uninit(&ri_gh);
- inode = gfs2_inode_lookup(sb, inum->no_addr, fh_obj->imode);
+ inode = gfs2_inode_lookup(sb, fh_obj->imode,
+ inum->no_addr,
+ inum->no_formal_ino);
if (!inode)
goto fail;
if (IS_ERR(inode)) {
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index dae1d71..cf5aa50 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -236,7 +236,7 @@ fail:
static inline struct inode *gfs2_lookup_root(struct super_block *sb,
u64 no_addr)
{
- return gfs2_inode_lookup(sb, no_addr, DT_DIR);
+ return gfs2_inode_lookup(sb, DT_DIR, no_addr, 0);
}
static int init_sb(struct gfs2_sbd *sdp, int silent, int undo)
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 36c523d..7fb7448 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -860,18 +860,19 @@ static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked)
{
struct inode *inode;
u32 goal = 0;
- u64 ino;
+ u64 no_addr;
for(;;) {
goal = rgblk_search(rgd, goal, GFS2_BLKST_UNLINKED,
GFS2_BLKST_UNLINKED);
if (goal == 0)
return 0;
- ino = goal + rgd->rd_data0;
- if (ino <= *last_unlinked)
+ no_addr = goal + rgd->rd_data0;
+ if (no_addr <= *last_unlinked)
continue;
- *last_unlinked = ino;
- inode = gfs2_inode_lookup(rgd->rd_sbd->sd_vfs, ino, DT_UNKNOWN);
+ *last_unlinked = no_addr;
+ inode = gfs2_inode_lookup(rgd->rd_sbd->sd_vfs, DT_UNKNOWN,
+ no_addr, 0);
if (!IS_ERR(inode))
return inode;
}
--
1.5.1.2
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[Index of Archives]
[Kernel Newbies]
[Netfilter]
[Bugtraq]
[Photo]
[Stuff]
[Gimp]
[Yosemite News]
[MIPS Linux]
[ARM Linux]
[Linux Security]
[Linux RAID]
[Video 4 Linux]
[Linux for the blind]
[Linux Resources]