Commit 549ae0ac authored by Wendy Cheng's avatar Wendy Cheng Committed by Steven Whitehouse

[GFS2] nfsd readdirplus assertion failure

Glock assertion failure found in '07 NFS connectathon. One of the NFSDs
is doing a "readdirplus" procedure call. It passes the logic into
gfs2_readdir() where it obtains its directory inode glock. This is then
followed by filehandle construction that invokes lookup code. It hits
the assertion failure while trying to obtain the inode glock again
inside gfs2_drevalidate().

This patch bypasses the recursive glock call if caller already holds the
lock.
Signed-off-by: default avatarS. Wendy Cheng <wcheng@redhat.com>
Signed-off-by: default avatarSteven Whitehouse <swhiteho@redhat.com>
parent a34fbc63
...@@ -46,6 +46,7 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd) ...@@ -46,6 +46,7 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd)
struct gfs2_inum_host inum; struct gfs2_inum_host inum;
unsigned int type; unsigned int type;
int error; int error;
int had_lock=0;
if (inode && is_bad_inode(inode)) if (inode && is_bad_inode(inode))
goto invalid; goto invalid;
...@@ -53,9 +54,12 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd) ...@@ -53,9 +54,12 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd)
if (sdp->sd_args.ar_localcaching) if (sdp->sd_args.ar_localcaching)
goto valid; goto valid;
had_lock = gfs2_glock_is_locked_by_me(dip->i_gl);
if (!had_lock) {
error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh); error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh);
if (error) if (error)
goto fail; goto fail;
}
error = gfs2_dir_search(parent->d_inode, &dentry->d_name, &inum, &type); error = gfs2_dir_search(parent->d_inode, &dentry->d_name, &inum, &type);
switch (error) { switch (error) {
...@@ -82,12 +86,14 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd) ...@@ -82,12 +86,14 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd)
} }
valid_gunlock: valid_gunlock:
if (!had_lock)
gfs2_glock_dq_uninit(&d_gh); gfs2_glock_dq_uninit(&d_gh);
valid: valid:
dput(parent); dput(parent);
return 1; return 1;
invalid_gunlock: invalid_gunlock:
if (!had_lock)
gfs2_glock_dq_uninit(&d_gh); gfs2_glock_dq_uninit(&d_gh);
invalid: invalid:
if (inode && S_ISDIR(inode->i_mode)) { if (inode && S_ISDIR(inode->i_mode)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment