nfsd: add a v4_end_grace file to /proc/fs/nfsd
authorJeff Layton <jlayton@primarydata.com>
Fri, 12 Sep 2014 20:40:21 +0000 (16:40 -0400)
committerJ. Bruce Fields <bfields@redhat.com>
Wed, 17 Sep 2014 20:33:14 +0000 (16:33 -0400)
Allow a privileged userland process to end the v4 grace period early.
Writing "Y", "y", or "1" to the file will cause the v4 grace period to
be lifted.  The basic idea with this will be to allow the userland
client tracking program to lift the grace period once it knows that no
more clients will be reclaiming state.

Signed-off-by: Jeff Layton <jlayton@primarydata.com>
fs/nfsd/nfs4state.c
fs/nfsd/nfsctl.c
fs/nfsd/state.h

index 08fb273ad4e066100e8b2eecf14313d81507b126..8f7ace5942be61f03a932140314c0d5bf851da4e 100644 (file)
@@ -4113,7 +4113,7 @@ out:
        return status;
 }
 
-static void
+void
 nfsd4_end_grace(struct nfsd_net *nn)
 {
        /* do nothing if grace period already ended */
index 4e042105fb6e3dc81595649bdfeff51d2d16a65c..ca73ca79a0ee40998a7b0a8d7afc5c81eb2440ba 100644 (file)
@@ -49,6 +49,7 @@ enum {
        NFSD_Leasetime,
        NFSD_Gracetime,
        NFSD_RecoveryDir,
+       NFSD_V4EndGrace,
 #endif
 };
 
@@ -68,6 +69,7 @@ static ssize_t write_maxconn(struct file *file, char *buf, size_t size);
 static ssize_t write_leasetime(struct file *file, char *buf, size_t size);
 static ssize_t write_gracetime(struct file *file, char *buf, size_t size);
 static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
+static ssize_t write_v4_end_grace(struct file *file, char *buf, size_t size);
 #endif
 
 static ssize_t (*write_op[])(struct file *, char *, size_t) = {
@@ -84,6 +86,7 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
        [NFSD_Leasetime] = write_leasetime,
        [NFSD_Gracetime] = write_gracetime,
        [NFSD_RecoveryDir] = write_recoverydir,
+       [NFSD_V4EndGrace] = write_v4_end_grace,
 #endif
 };
 
@@ -1077,6 +1080,47 @@ static ssize_t write_recoverydir(struct file *file, char *buf, size_t size)
        return rv;
 }
 
+/**
+ * write_v4_end_grace - release grace period for nfsd's v4.x lock manager
+ *
+ * Input:
+ *                     buf:            ignored
+ *                     size:           zero
+ * OR
+ *
+ * Input:
+ *                     buf:            any value
+ *                     size:           non-zero length of C string in @buf
+ * Output:
+ *                     passed-in buffer filled with "Y" or "N" with a newline
+ *                     and NULL-terminated C string. This indicates whether
+ *                     the grace period has ended in the current net
+ *                     namespace. Return code is the size in bytes of the
+ *                     string. Writing a string that starts with 'Y', 'y', or
+ *                     '1' to the file will end the grace period for nfsd's v4
+ *                     lock manager.
+ */
+static ssize_t write_v4_end_grace(struct file *file, char *buf, size_t size)
+{
+       struct net *net = file->f_dentry->d_sb->s_fs_info;
+       struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+
+       if (size > 0) {
+               switch(buf[0]) {
+               case 'Y':
+               case 'y':
+               case '1':
+                       nfsd4_end_grace(nn);
+                       break;
+               default:
+                       return -EINVAL;
+               }
+       }
+
+       return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%c\n",
+                        nn->grace_ended ? 'Y' : 'N');
+}
+
 #endif
 
 /*----------------------------------------------------------------------------*/
@@ -1110,6 +1154,7 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
                [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR},
                [NFSD_Gracetime] = {"nfsv4gracetime", &transaction_ops, S_IWUSR|S_IRUSR},
                [NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR},
+               [NFSD_V4EndGrace] = {"v4_end_grace", &transaction_ops, S_IWUSR|S_IRUGO},
 #endif
                /* last one */ {""}
        };
index a5fa6909501e07b2006555c69744acd65dbcb04c..854f0c574ccf887ad1259c03dd319883a5762b71 100644 (file)
@@ -545,6 +545,9 @@ extern struct nfs4_client_reclaim *nfs4_client_to_reclaim(const char *name,
                                                        struct nfsd_net *nn);
 extern bool nfs4_has_reclaimed_state(const char *name, struct nfsd_net *nn);
 
+/* grace period management */
+void nfsd4_end_grace(struct nfsd_net *nn);
+
 /* nfs4recover operations */
 extern int nfsd4_client_tracking_init(struct net *net);
 extern void nfsd4_client_tracking_exit(struct net *net);