Whamcloud - gitweb
LU-16463 llite: replace lld_nfs_dentry flag with opencache handling 37/49237/11
authorJames Simmons <jsimmons@infradead.org>
Tue, 7 Feb 2023 15:08:13 +0000 (10:08 -0500)
committerOleg Drokin <green@whamcloud.com>
Thu, 23 Feb 2023 06:27:46 +0000 (06:27 +0000)
The lld_nfs_dentry flag was created for the case of caching the
open lock (opencache) when fetching fhandles for NFSv3. This same
path is used by the fhandle APIs. This lighter open changes key
behaviors since the open lock is always cached which we don't
want. Lustre introduced a way to modify caching the open lock
based on the number of opens done on a file within a certain
span of time. We can replace lld_nfs_dentry flag with the
new open lock caching. This way for fhandle handling we match
the open lock caching behavior of a normal file open.

In the case of NFS this code path will always be called with the
internal kernel thread 'nfsd'. If we are called by this kernel
thread set the open threshold to zero which means always cache the
open lock. Once Lustre is only supported on Linux kernels above
5.5 we can remove this special NFSv3 work around.

Change-Id: Iba27f7ad4579fdd1f34e1e35c2cbd547e15f129a
Signed-off-by: James Simmons <jsimmons@infradead.org>
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/49237
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Etienne AUJAMES <eaujames@ddn.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/llite/file.c
lustre/llite/llite_internal.h
lustre/llite/llite_nfs.c
lustre/llite/namei.c
lustre/llite/super25.c

index 15e5bb1..2d70c2a 100644 (file)
@@ -917,7 +917,7 @@ restart:
                if (!it->it_disposition) {
                        struct dentry *dentry = file_dentry(file);
                        struct ll_sb_info *sbi = ll_i2sbi(inode);
-                       struct ll_dentry_data *ldd;
+                       int open_threshold = sbi->ll_oc_thrsh_count;
 
                        /* We cannot just request lock handle now, new ELC code
                         * means that one of other OPEN locks for this file
@@ -928,23 +928,23 @@ restart:
                        mutex_unlock(&lli->lli_och_mutex);
                        /*
                         * Normally called under two situations:
-                        * 1. NFS export.
+                        * 1. fhandle / NFS export.
                         * 2. A race/condition on MDS resulting in no open
                         *    handle to be returned from LOOKUP|OPEN request,
                         *    for example if the target entry was a symlink.
                         *
-                        * In NFS path we know there's pathologic behavior
-                        * so we always enable open lock caching when coming
-                        * from there. It's detected by setting a flag in
-                        * ll_iget_for_nfs.
+                        * For NFSv3 we need to always cache the open lock
+                        * for pre 5.5 Linux kernels.
                         *
                         * After reaching number of opens of this inode
                         * we always ask for an open lock on it to handle
                         * bad userspace actors that open and close files
                         * in a loop for absolutely no good reason
                         */
+                       /* fhandle / NFS path. */
+                       if (lli->lli_open_thrsh_count != UINT_MAX)
+                               open_threshold = lli->lli_open_thrsh_count;
 
-                       ldd = ll_d2d(dentry);
                        if (filename_is_volatile(dentry->d_name.name,
                                                 dentry->d_name.len,
                                                 NULL)) {
@@ -953,17 +953,9 @@ restart:
                                 * We do not want openlock for volatile
                                 * files under any circumstances
                                 */
-                       } else if (ldd && ldd->lld_nfs_dentry) {
-                               /* NFS path. This also happens to catch
-                                * open by fh files I guess
-                                */
-                               it->it_flags |= MDS_OPEN_LOCK;
-                               /* clear the flag for future lookups */
-                               ldd->lld_nfs_dentry = 0;
-                       } else if (sbi->ll_oc_thrsh_count > 0) {
+                       } else if (open_threshold > 0) {
                                /* Take MDS_OPEN_LOCK with many opens */
-                               if (lli->lli_open_fd_count >=
-                                   sbi->ll_oc_thrsh_count)
+                               if (lli->lli_open_fd_count >= open_threshold)
                                        it->it_flags |= MDS_OPEN_LOCK;
 
                                /* If this is open after we just closed */
index d0e7840..198271c 100644 (file)
@@ -84,7 +84,6 @@
 struct ll_dentry_data {
        unsigned int                    lld_sa_generation;
        unsigned int                    lld_invalid:1;
-       unsigned int                    lld_nfs_dentry:1;
        struct rcu_head                 lld_rcu_head;
 };
 
@@ -140,11 +139,6 @@ struct ll_inode_info {
        __u64                           lli_open_fd_write_count;
        __u64                           lli_open_fd_exec_count;
 
-       /* Number of times this inode was opened */
-       u64                             lli_open_fd_count;
-       /* When last close was performed on this inode */
-       ktime_t                         lli_close_fd_time;
-
        /* Protects access to och pointers and their usage counters */
        struct mutex                    lli_och_mutex;
 
@@ -157,6 +151,13 @@ struct ll_inode_info {
        s64                             lli_btime;
        spinlock_t                      lli_agl_lock;
 
+       /* inode specific open lock caching threshold */
+       u32                             lli_open_thrsh_count;
+       /* Number of times this inode was opened */
+       u64                             lli_open_fd_count;
+       /* When last close was performed on this inode */
+       ktime_t                         lli_close_fd_time;
+
        /* Try to make the d::member and f::member are aligned. Before using
         * these members, make clear whether it is directory or not. */
        union {
index 644aac2..744f4f9 100644 (file)
@@ -136,22 +136,24 @@ ll_iget_for_nfs(struct super_block *sb, struct lu_fid *fid, struct lu_fid *paren
 
        /* N.B. d_obtain_alias() drops inode ref on error */
        result = d_obtain_alias(inode);
-       if (!IS_ERR(result)) {
-               struct ll_dentry_data *ldd;
+       if (IS_ERR(result))
+               RETURN(result);
 
-               if (!ll_d_setup(result, true))
-                       RETURN(ERR_PTR(-ENOMEM));
-               ldd = ll_d2d(result);
-               /*
-                * Need to signal to the ll_file_open that
-                * we came from NFS and so opencache needs to be
-                * enabled for this one
-                */
-               spin_lock(&result->d_lock);
-               ldd->lld_nfs_dentry = 1;
-               spin_unlock(&result->d_lock);
-       }
+       if (!ll_d_setup(result, true))
+               RETURN(ERR_PTR(-ENOMEM));
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 5, 0)
+       /* If we are called by nfsd kthread set lli_open_thrsh_count
+        * to one. This will force caching the open lock. To be
+        * removed once oldest supported Linux kernel is 5.5
+        */
+       if ((current->flags & PF_KTHREAD) &&
+           strcmp(current->comm, "nfsd") == 0) {
+               struct ll_inode_info *lli = ll_i2info(inode);
+
+               lli->lli_open_thrsh_count = 1;
+       }
+#endif
        RETURN(result);
 }
 
index 2681bf6..810b9e9 100644 (file)
@@ -1155,9 +1155,10 @@ static int ll_atomic_open(struct inode *dir, struct dentry *dentry,
        struct ll_sb_info *sbi = NULL;
        struct pcc_create_attach pca = { NULL, NULL };
        bool encrypt = false;
+       int open_threshold;
        int rc = 0;
-       ENTRY;
 
+       ENTRY;
        CDEBUG(D_VFSTRACE,
               "VFS Op:name=%pd, dir="DFID"(%p), file %p, open_flags %x, mode %x opened %d\n",
               dentry, PFID(ll_inode2fid(dir)), dir, file, open_flags, mode,
@@ -1236,7 +1237,12 @@ static int ll_atomic_open(struct inode *dir, struct dentry *dentry,
         * we only need to request open lock if it was requested
         * for every open
         */
-       if (ll_i2sbi(dir)->ll_oc_thrsh_count == 1 &&
+       if (ll_i2info(dir)->lli_open_thrsh_count != UINT_MAX)
+               open_threshold = ll_i2info(dir)->lli_open_thrsh_count;
+       else
+               open_threshold = ll_i2sbi(dir)->ll_oc_thrsh_count;
+
+       if (open_threshold == 1 &&
            exp_connect_flags2(ll_i2mdexp(dir)) &
            OBD_CONNECT2_ATOMIC_OPEN_LOCK)
                it->it_flags |= MDS_OPEN_LOCK;
index 71b45b9..6622625 100644 (file)
@@ -62,6 +62,8 @@ static struct inode *ll_alloc_inode(struct super_block *sb)
                return NULL;
 #endif
        inode_init_once(&lli->lli_vfs_inode);
+       lli->lli_open_thrsh_count = UINT_MAX;
+
        return &lli->lli_vfs_inode;
 }