From 3129537c7f5da328abdc1cbd9cf5419ff8e2530c Mon Sep 17 00:00:00 2001 From: Johann Lombardi Date: Fri, 5 Mar 2010 23:17:53 +0100 Subject: [PATCH] b=22177 inc nlink by 2 instead of 1 in mds_orphan_add_link() i=adilger i=dmitry Fix regression introduced by 19640. ext3_inc_count() can reset nlink to 1 when the directory is indexed and inode->i_nlink == 2. Work around the problem by incrementing nlink by 2 instead of 1. --- lustre/mds/mds_reint.c | 50 +++++++++++++++++++++++++++++++++++--------------- lustre/tests/sanity.sh | 19 +++++++++++++++++++ 2 files changed, 54 insertions(+), 15 deletions(-) diff --git a/lustre/mds/mds_reint.c b/lustre/mds/mds_reint.c index e71fe2c..1added0 100644 --- a/lustre/mds/mds_reint.c +++ b/lustre/mds/mds_reint.c @@ -1757,31 +1757,37 @@ static int mds_orphan_add_link(struct mds_update_record *rec, * for linking and return real mode back then -bzzz */ mode = inode->i_mode; inode->i_mode = S_IFREG; - /* avoid vfs_link upon 0 nlink inode */ - ++inode->i_nlink; + /* avoid vfs_link upon 0 nlink inode, inc by 2 instead of 1 because + * ext3_inc_count() can reset i_nlink for indexed directory */ + inode->i_nlink += 2; rc = ll_vfs_link(dentry, mds->mds_vfsmnt, pending_dir, pending_child, mds->mds_vfsmnt); if (rc) - CERROR("error linking orphan %s to PENDING: rc = %d\n", + CERROR("error linking orphan %s %s to PENDING: rc = %d\n", + S_ISDIR(mode) ? "dir" : S_ISREG(mode) ? "file" : "other", rec->ur_name, rc); else mds_inode_set_orphan(inode); /* return mode and correct i_nlink if inode is directory */ inode->i_mode = mode; - LASSERTF(inode->i_nlink == 2, "%s nlink == %d\n", + LASSERTF(rc || inode->i_nlink == 3, "%s nlink == %d\n", S_ISDIR(mode) ? "dir" : S_ISREG(mode) ? "file" : "other", inode->i_nlink); + if (S_ISDIR(mode)) { pending_dir->i_nlink++; if (pending_dir->i_sb->s_op->dirty_inode) pending_dir->i_sb->s_op->dirty_inode(pending_dir); - } else { - --inode->i_nlink; - if (inode->i_sb->s_op->dirty_inode) - inode->i_sb->s_op->dirty_inode(inode); } + inode->i_nlink -= 2; + if (inode->i_sb->s_op->dirty_inode) + inode->i_sb->s_op->dirty_inode(inode); + + if (rc) + GOTO(out_dput, rc); + GOTO(out_dput, rc = 1); out_dput: l_dput(pending_child); @@ -2050,11 +2056,18 @@ static int mds_reint_unlink(struct mds_update_record *rec, int offset, } if (rc == 0 && child_inode->i_nlink == 0) { - if (mds_orphan_needed(obd, child_inode)) + if (mds_orphan_needed(obd, child_inode)) { rc = mds_orphan_add_link(rec, obd, dchild); - - if (rc == 1) - GOTO(cleanup, rc = 0); + if (rc == 1) + /* child inode was successfully linked + * to PENDING */ + GOTO(cleanup, rc = 0); + else + /* we failed to move the file to PENDING, + * really unlink the file as if there were + * no more openers */ + rc = 0; + } if (!S_ISREG(child_inode->i_mode)) GOTO(cleanup, rc); @@ -2740,11 +2753,18 @@ no_unlink: } if (rc == 0 && new_inode != NULL && new_inode->i_nlink == 0) { - if (mds_orphan_needed(obd, new_inode)) + if (mds_orphan_needed(obd, new_inode)) { rc = mds_orphan_add_link(rec, obd, de_new); - if (rc == 1) - GOTO(cleanup, rc = 0); + if (rc == 1) + /* inode successfully linked to PENDING */ + GOTO(cleanup, rc = 0); + else + /* we failed to move the file to PENDING, + * really unlink the file as if there were + * no more openers */ + rc = 0; + } if (!S_ISREG(new_inode->i_mode)) GOTO(cleanup, rc); diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index 4241a6b..553ecac 100644 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -6275,6 +6275,25 @@ test_180() { } run_test 180 "test obdecho ============================================" +test_181() { # bug 22177 + mkdir -p $DIR/$tdir || error "creating dir $DIR/$tdir" + # create enough files to index the directory + createmany -o $DIR/$tdir/foobar 4000 + # print attributes for debug purpose + lsattr -d . + # open dir + multiop_bg_pause $DIR/$tdir D_Sc || return 1 + MULTIPID=$! + # remove the files & current working dir + unlinkmany $DIR/$tdir/foobar 4000 + rmdir $DIR/$tdir + kill -USR1 $MULTIPID + wait $MULTIPID + stat $DIR/$tdir && error "open-unlinked dir was not removed!" + return 0 +} +run_test 181 "Test open-unlinked dir ========================" + POOL=${POOL:-cea1} TGT_COUNT=$OSTCOUNT TGTPOOL_FIRST=1 -- 1.8.3.1