aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOleg Drokin <green@linuxhacker.ru>2016-07-14 23:40:21 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-08-15 12:25:10 -0400
commit99f1c013194e64d4b67d5d318148303b0e1585e1 (patch)
treea47877fd40dd6ca0135b7ef3b18a15ba31906917
parent694d0d0bb2030d2e36df73e2d23d5770511dbc8d (diff)
staging/lustre/llite: Close atomic_open race with several openers
Right now, if it's an open of a negative dentry, a race is possible with several openers who all try to instantiate/rehash the same dentry and would hit a BUG_ON in d_add. But in fact if we got a negative dentry in atomic_open, that means we just revalidated it so no point in talking to MDS at all, just return ENOENT and make the race go away completely. Signed-off-by: Oleg Drokin <green@linuxhacker.ru> Cc: stable <stable@vger.kernel.org> # 4.7+ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/staging/lustre/lustre/llite/namei.c43
1 files changed, 24 insertions, 19 deletions
diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c
index 3664bfd0178b..2c4dc69731e8 100644
--- a/drivers/staging/lustre/lustre/llite/namei.c
+++ b/drivers/staging/lustre/lustre/llite/namei.c
@@ -388,6 +388,7 @@ static int ll_lookup_it_finish(struct ptlrpc_request *request,
388 struct inode *inode = NULL; 388 struct inode *inode = NULL;
389 __u64 bits = 0; 389 __u64 bits = 0;
390 int rc = 0; 390 int rc = 0;
391 struct dentry *alias;
391 392
392 /* NB 1 request reference will be taken away by ll_intent_lock() 393 /* NB 1 request reference will be taken away by ll_intent_lock()
393 * when I return 394 * when I return
@@ -412,26 +413,12 @@ static int ll_lookup_it_finish(struct ptlrpc_request *request,
412 */ 413 */
413 } 414 }
414 415
415 /* Only hash *de if it is unhashed (new dentry). 416 alias = ll_splice_alias(inode, *de);
416 * Atoimc_open may passing hashed dentries for open. 417 if (IS_ERR(alias)) {
417 */ 418 rc = PTR_ERR(alias);
418 if (d_unhashed(*de)) { 419 goto out;
419 struct dentry *alias;
420
421 alias = ll_splice_alias(inode, *de);
422 if (IS_ERR(alias)) {
423 rc = PTR_ERR(alias);
424 goto out;
425 }
426 *de = alias;
427 } else if (!it_disposition(it, DISP_LOOKUP_NEG) &&
428 !it_disposition(it, DISP_OPEN_CREATE)) {
429 /* With DISP_OPEN_CREATE dentry will be
430 * instantiated in ll_create_it.
431 */
432 LASSERT(!d_inode(*de));
433 d_instantiate(*de, inode);
434 } 420 }
421 *de = alias;
435 422
436 if (!it_disposition(it, DISP_LOOKUP_NEG)) { 423 if (!it_disposition(it, DISP_LOOKUP_NEG)) {
437 /* we have lookup look - unhide dentry */ 424 /* we have lookup look - unhide dentry */
@@ -587,6 +574,24 @@ static int ll_atomic_open(struct inode *dir, struct dentry *dentry,
587 dentry, PFID(ll_inode2fid(dir)), dir, file, open_flags, mode, 574 dentry, PFID(ll_inode2fid(dir)), dir, file, open_flags, mode,
588 *opened); 575 *opened);
589 576
577 /* Only negative dentries enter here */
578 LASSERT(!d_inode(dentry));
579
580 if (!d_in_lookup(dentry)) {
581 /* A valid negative dentry that just passed revalidation,
582 * there's little point to try and open it server-side,
583 * even though there's a minuscle chance it might succeed.
584 * Either way it's a valid race to just return -ENOENT here.
585 */
586 if (!(open_flags & O_CREAT))
587 return -ENOENT;
588
589 /* Otherwise we just unhash it to be rehashed afresh via
590 * lookup if necessary
591 */
592 d_drop(dentry);
593 }
594
590 it = kzalloc(sizeof(*it), GFP_NOFS); 595 it = kzalloc(sizeof(*it), GFP_NOFS);
591 if (!it) 596 if (!it)
592 return -ENOMEM; 597 return -ENOMEM;