From: Dinu-Razvan Chis-Serban <justc...@gmail.com>

[ Upstream commit 5e172f75e51e3de1b4274146d9b990f803cb5c2a ]

The default P9_LOCK_TIMEOUT can be too long for some users exporting
a local file system to a guest VM (30s), make this configurable at
mount time.

Link: 
http://lkml.kernel.org/r/1536295827-3181-1-git-send-email-asmad...@codewreck.org
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=195727
Signed-off-by: Dinu-Razvan Chis-Serban <justc...@gmail.com>
Signed-off-by: Dominique Martinet <dominique.marti...@cea.fr>
Signed-off-by: Sasha Levin <sas...@kernel.org>
---
 fs/9p/v9fs.c     | 21 +++++++++++++++++++++
 fs/9p/v9fs.h     |  1 +
 fs/9p/vfs_file.c |  6 +++++-
 3 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
index 072e7599583a..a8ff43068619 100644
--- a/fs/9p/v9fs.c
+++ b/fs/9p/v9fs.c
@@ -59,6 +59,8 @@ enum {
        Opt_cache_loose, Opt_fscache, Opt_mmap,
        /* Access options */
        Opt_access, Opt_posixacl,
+       /* Lock timeout option */
+       Opt_locktimeout,
        /* Error token */
        Opt_err
 };
@@ -78,6 +80,7 @@ static const match_table_t tokens = {
        {Opt_cachetag, "cachetag=%s"},
        {Opt_access, "access=%s"},
        {Opt_posixacl, "posixacl"},
+       {Opt_locktimeout, "locktimeout=%u"},
        {Opt_err, NULL}
 };
 
@@ -126,6 +129,7 @@ static int v9fs_parse_options(struct v9fs_session_info 
*v9ses, char *opts)
 #ifdef CONFIG_9P_FSCACHE
        v9ses->cachetag = NULL;
 #endif
+       v9ses->session_lock_timeout = P9_LOCK_TIMEOUT;
 
        if (!opts)
                return 0;
@@ -298,6 +302,23 @@ static int v9fs_parse_options(struct v9fs_session_info 
*v9ses, char *opts)
 #endif
                        break;
 
+               case Opt_locktimeout:
+                       r = match_int(&args[0], &option);
+                       if (r < 0) {
+                               p9_debug(P9_DEBUG_ERROR,
+                                        "integer field, but no integer?\n");
+                               ret = r;
+                               continue;
+                       }
+                       if (option < 1) {
+                               p9_debug(P9_DEBUG_ERROR,
+                                        "locktimeout must be a greater than 
zero integer.\n");
+                               ret = -EINVAL;
+                               continue;
+                       }
+                       v9ses->session_lock_timeout = (long)option * HZ;
+                       break;
+
                default:
                        continue;
                }
diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h
index 443d12e02043..ce6ca9f4f683 100644
--- a/fs/9p/v9fs.h
+++ b/fs/9p/v9fs.h
@@ -116,6 +116,7 @@ struct v9fs_session_info {
        struct list_head slist; /* list of sessions registered with v9fs */
        struct backing_dev_info bdi;
        struct rw_semaphore rename_sem;
+       long session_lock_timeout; /* retry interval for blocking locks */
 };
 
 /* cache_validity flags */
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index 2f035b15180e..79ff727254bb 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -154,6 +154,7 @@ static int v9fs_file_do_lock(struct file *filp, int cmd, 
struct file_lock *fl)
        uint8_t status = P9_LOCK_ERROR;
        int res = 0;
        unsigned char fl_type;
+       struct v9fs_session_info *v9ses;
 
        fid = filp->private_data;
        BUG_ON(fid == NULL);
@@ -189,6 +190,8 @@ static int v9fs_file_do_lock(struct file *filp, int cmd, 
struct file_lock *fl)
        if (IS_SETLKW(cmd))
                flock.flags = P9_LOCK_FLAGS_BLOCK;
 
+       v9ses = v9fs_inode2v9ses(file_inode(filp));
+
        /*
         * if its a blocked request and we get P9_LOCK_BLOCKED as the status
         * for lock request, keep on trying
@@ -202,7 +205,8 @@ static int v9fs_file_do_lock(struct file *filp, int cmd, 
struct file_lock *fl)
                        break;
                if (status == P9_LOCK_BLOCKED && !IS_SETLKW(cmd))
                        break;
-               if (schedule_timeout_interruptible(P9_LOCK_TIMEOUT) != 0)
+               if (schedule_timeout_interruptible(v9ses->session_lock_timeout)
+                               != 0)
                        break;
                /*
                 * p9_client_lock_dotl overwrites flock.client_id with the
-- 
2.19.1

Reply via email to