[GFS2] Obtaining no_formal_ino from directory entry
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 <wcheng@redhat.com> Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
This commit is contained in:
Родитель
f4fadb23ca
Коммит
bb9bcf0616
|
@ -1499,8 +1499,9 @@ struct inode *gfs2_dir_search(struct inode *dir, const struct qstr *name)
|
|||
if (IS_ERR(dent))
|
||||
return ERR_PTR(PTR_ERR(dent));
|
||||
inode = gfs2_inode_lookup(dir->i_sb,
|
||||
be16_to_cpu(dent->de_type),
|
||||
be64_to_cpu(dent->de_inum.no_addr),
|
||||
be16_to_cpu(dent->de_type));
|
||||
be64_to_cpu(dent->de_inum.no_formal_ino));
|
||||
brelse(bh);
|
||||
return inode;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче