From: Patrick Farrell Date: Wed, 18 Oct 2017 10:24:41 +0000 (-0500) Subject: LU-10131 llite: Update i_nlink on unlink X-Git-Tag: 2.10.55~24 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=947b22b08d3725852a811a9e330562dd986d7336;p=fs%2Flustre-release.git LU-10131 llite: Update i_nlink on unlink Currently, the client inode link count is not updated on last unlink. This is fine because the dentries are all gone and the inode is eligible for reclaim, but it's still incorrect. This causes two problems: 1. Inode is not immediately reclaimed 2. i_nlink count is > 0 for a fully unlinked file, which confuses wrapfs On last unlink, the MDT sends back attributes. Use the nlink count from these to update the client inode. Remove null check inherited from ll_get_child_fid, because the inode should never be null on an unlink. Re-enabled test 76, which passes with this patch. Removed slab allocator tuning from test_76, because slab is no longer the default Linux allocator. Signed-off-by: Patrick Farrell Change-Id: Ib253b5cf3d35188554cf8fc33a8a3d4b8bb237e8 Reviewed-on: https://review.whamcloud.com/29651 Tested-by: Jenkins Reviewed-by: Ben Evans Reviewed-by: Alexey Lyashkov Tested-by: Maloo Reviewed-by: Andrew Perepechko Reviewed-by: Oleg Drokin --- diff --git a/lustre/llite/namei.c b/lustre/llite/namei.c index f008826..ef18c1d 100644 --- a/lustre/llite/namei.c +++ b/lustre/llite/namei.c @@ -1386,17 +1386,18 @@ int ll_rmdir_entry(struct inode *dir, char *name, int namelen) static int ll_unlink(struct inode *dir, struct dentry *dchild) { struct qstr *name = &dchild->d_name; - struct ptlrpc_request *request = NULL; - struct md_op_data *op_data; - int rc; - ENTRY; + struct ptlrpc_request *request = NULL; + struct md_op_data *op_data; + struct mdt_body *body; + int rc; + ENTRY; CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s, dir="DFID"(%p)\n", name->len, name->name, PFID(ll_inode2fid(dir)), dir); - /* - * XXX: unlink bind mountpoint maybe call to here, - * just check it as vfs_unlink does. - */ + /* + * XXX: unlink bind mountpoint maybe call to here, + * just check it as vfs_unlink does. + */ if (unlikely(d_mountpoint(dchild))) RETURN(-EBUSY); @@ -1405,8 +1406,7 @@ static int ll_unlink(struct inode *dir, struct dentry *dchild) if (IS_ERR(op_data)) RETURN(PTR_ERR(op_data)); - if (dchild->d_inode != NULL) - op_data->op_fid3 = *ll_inode2fid(dchild->d_inode); + op_data->op_fid3 = *ll_inode2fid(dchild->d_inode); op_data->op_fid2 = op_data->op_fid3; rc = md_unlink(ll_i2sbi(dir)->ll_md_exp, op_data, &request); @@ -1414,12 +1414,20 @@ static int ll_unlink(struct inode *dir, struct dentry *dchild) if (rc) GOTO(out, rc); - ll_update_times(request, dir); - ll_stats_ops_tally(ll_i2sbi(dir), LPROC_LL_UNLINK, 1); + /* + * The server puts attributes in on the last unlink, use them to update + * the link count so the inode can be freed immediately. + */ + body = req_capsule_server_get(&request->rq_pill, &RMF_MDT_BODY); + if (body->mbo_valid & OBD_MD_FLNLINK) + set_nlink(dchild->d_inode, body->mbo_nlink); - out: - ptlrpc_req_finished(request); - RETURN(rc); + ll_update_times(request, dir); + ll_stats_ops_tally(ll_i2sbi(dir), LPROC_LL_UNLINK, 1); + +out: + ptlrpc_req_finished(request); + RETURN(rc); } static int ll_rename(struct inode *src, struct dentry *src_dchild, diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index c80bdab..a1063007 100755 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -12,8 +12,8 @@ ONLY=${ONLY:-"$*"} ALWAYS_EXCEPT=" 42a 42b 42c 45 68b $SANITY_EXCEPT" # UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT! -# skipped tests: LU-2036 LU-8411 LU-9096 LU-9054 -ALWAYS_EXCEPT=" 76 407 253 312 $ALWAYS_EXCEPT" +# skipped tests: LU-8411 LU-9096 LU-9054 +ALWAYS_EXCEPT=" 407 253 312 $ALWAYS_EXCEPT" # Check Grants after these tests GRANT_CHECK_LIST="$GRANT_CHECK_LIST 42a 42b 42c 42d 42e 63a 63b 64a 64b 64c" @@ -6007,21 +6007,9 @@ num_inodes() { awk '/lustre_inode_cache/ {print $2; exit}' /proc/slabinfo } -get_inode_slab_tunables() { - awk '/lustre_inode_cache/ {print $9," ",$10," ",$11; exit}' /proc/slabinfo -} - -set_inode_slab_tunables() { - echo "lustre_inode_cache $1" > /proc/slabinfo -} - test_76() { # Now for bug 20433, added originally in bug 1443 [ $PARALLEL == "yes" ] && skip "skip parallel run" && return - local SLAB_SETTINGS=$(get_inode_slab_tunables) local CPUS=$(getconf _NPROCESSORS_ONLN 2>/dev/null) - # we cannot set limit below 1 which means 1 inode in each - # per-cpu cache is still allowed - set_inode_slab_tunables "1 1 0" cancel_lru_locks osc BEFORE_INODES=$(num_inodes) echo "before inodes: $BEFORE_INODES" @@ -6044,7 +6032,6 @@ test_76() { # Now for bug 20433, added originally in bug 1443 error "inode slab grew from $BEFORE_INODES to $AFTER_INODES" fi done - set_inode_slab_tunables "$SLAB_SETTINGS" } run_test 76 "confirm clients recycle inodes properly ===="