Whamcloud - gitweb
LU-10131 llite: Update i_nlink on unlink 51/29651/4
authorPatrick Farrell <paf@cray.com>
Wed, 18 Oct 2017 10:24:41 +0000 (05:24 -0500)
committerOleg Drokin <oleg.drokin@intel.com>
Wed, 25 Oct 2017 00:54:35 +0000 (00:54 +0000)
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 <paf@cray.com>
Change-Id: Ib253b5cf3d35188554cf8fc33a8a3d4b8bb237e8
Reviewed-on: https://review.whamcloud.com/29651
Tested-by: Jenkins
Reviewed-by: Ben Evans <bevans@cray.com>
Reviewed-by: Alexey Lyashkov <c17817@cray.com>
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Andrew Perepechko <c17827@cray.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/llite/namei.c
lustre/tests/sanity.sh

index f008826..ef18c1d 100644 (file)
@@ -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,
index c80bdab..a106300 100755 (executable)
@@ -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 ===="