From 5142d04ad6dd0c3b2a2a93571b7e2d4d4d647372 Mon Sep 17 00:00:00 2001 From: bobijam <bobijam> Date: Wed, 19 Nov 2008 01:39:07 +0000 Subject: [PATCH] Branch b1_6 b=16992 o=johann i=oleg.drokin (green) i=zhenyu.xu (bobijam) During ll_intent_lock(), server looks up parent and child, lock them, between these events parent could be deleted, then vfs_create may_access() fails with -ENOENT. Then client intent disposition got DISP_OPEN_CREATE | DISP_LOOKUP_NEG | DISP_LOOKUP_EXECD | DISP_IT_EXECD, and the request got double free. Solution: Clear DISP_ENQ_COMPLETE when we are going to release the intent (request cannot be reused anyway) --- lustre/llite/dcache.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/lustre/llite/dcache.c b/lustre/llite/dcache.c index e1b9445f46..82146baf0e 100644 --- a/lustre/llite/dcache.c +++ b/lustre/llite/dcache.c @@ -213,7 +213,7 @@ int ll_drop_dentry(struct dentry *dentry) spin_lock(&dcache_lock); return 1; } - /* disconected dentry can not be find without lookup, because we + /* disconected dentry can not be find without lookup, because we * not need his to unhash or mark invalid. */ if (dentry->d_flags & DCACHE_DISCONNECTED) { unlock_dentry(dentry); @@ -239,7 +239,7 @@ int ll_drop_dentry(struct dentry *dentry) if (dentry->d_inode) { /* Put positive dentries to orphan list */ list_add(&dentry->d_hash, - &ll_i2sbi(dentry->d_inode)->ll_orphan_dentry_list); + &ll_i2sbi(dentry->d_inode)->ll_orphan_dentry_list); } #endif #else @@ -488,11 +488,14 @@ do_lock: revalidate_finish: rc = revalidate_it_finish(req, DLM_REPLY_REC_OFF, it, de); if (rc != 0) { + /* we are going release the intent, so clear DISP_ENQ_COMPLETE + * to prevent a double free of the request */ + it_clear_disposition(it, DISP_ENQ_COMPLETE); ll_intent_release(it); GOTO(out, rc = 0); } - if ((it->it_op & IT_OPEN) && de->d_inode && - !S_ISREG(de->d_inode->i_mode) && + if ((it->it_op & IT_OPEN) && de->d_inode && + !S_ISREG(de->d_inode->i_mode) && !S_ISDIR(de->d_inode->i_mode)) { ll_release_openhandle(de, it); } @@ -572,6 +575,9 @@ do_lookup: /* see if we got same inode, if not - return error */ if(!memcmp(&fid, &mds_body->fid1, sizeof(struct ll_fid))) goto revalidate_finish; + /* we are going release the intent, so clear DISP_ENQ_COMPLETE + * to prevent a double free of the request */ + it_clear_disposition(it, DISP_ENQ_COMPLETE); ll_intent_release(it); } GOTO(out, rc = 0); @@ -703,7 +709,8 @@ int ll_revalidate_nd(struct dentry *dentry, struct nameidata *nd) RETURN(0); if (it->it_op == (IT_OPEN|IT_CREAT)) if (nd->intent.open.flags & O_EXCL) { - CDEBUG(D_VFSTRACE, "create O_EXCL, returning 0\n"); + CDEBUG(D_VFSTRACE, + "create O_EXCL, returning 0\n"); rc = 0; goto out_it; } @@ -747,7 +754,7 @@ int ll_revalidate_nd(struct dentry *dentry, struct nameidata *nd) ll_d2d(dentry)->lld_it = it; it = NULL; /* avoid freeing */ } - + out_it: if (it) { ll_intent_release(it); -- GitLab