aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfsctl.c
diff options
context:
space:
mode:
authorWendy Cheng <wcheng@redhat.com>2008-01-17 11:10:12 -0500
committerJ. Bruce Fields <bfields@citi.umich.edu>2008-04-25 13:00:10 -0400
commit4373ea84c84d8a96e99d3da99e813d3e36d1bd11 (patch)
tree956fb92c4501cf2ed0f21a8942dfc31d4621711f /fs/nfsd/nfsctl.c
parent9d91cdcc0cce3186742f38e7352459b2087fbb86 (diff)
lockd: unlock lockd locks associated with a given server ip
For high-availability NFS service, we generally need to be able to drop file locks held on the exported filesystem before moving clients to a new server. Currently the only way to do that is by shutting down lockd entirely, which is often undesireable (for example, if you want to continue exporting other filesystems). This patch allows the administrator to release all locks held by clients accessing the client through a given server ip address, by echoing that address to a new file, /proc/fs/nfsd/unlock_ip, as in: shell> echo 10.1.1.2 > /proc/fs/nfsd/unlock_ip The expected sequence of events can be: 1. Tear down the IP address 2. Unexport the path 3. Write IP to /proc/fs/nfsd/unlock_ip to unlock files 4. Signal peer to begin take-over. For now we only support IPv4 addresses and NFSv2/v3 (NFSv4 locks are not affected). Also, if unmounting the filesystem is required, we assume at step 3 that clients using the given server ip are the only clients holding locks on the given filesystem; otherwise, an additional patch is required to allow revoking all locks held by lockd on a given filesystem. Signed-off-by: S. Wendy Cheng <wcheng@redhat.com> Cc: Lon Hohberger <lhh@redhat.com> Cc: Christoph Hellwig <hch@lst.de> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu> fs/lockd/svcsubs.c | 66 +++++++++++++++++++++++++++++++++++++++----- fs/nfsd/nfsctl.c | 65 +++++++++++++++++++++++++++++++++++++++++++ include/linux/lockd/lockd.h | 7 ++++ 3 files changed, 131 insertions(+), 7 deletions(-)
Diffstat (limited to 'fs/nfsd/nfsctl.c')
-rw-r--r--fs/nfsd/nfsctl.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 613bcb8171a..7706f6c9ab8 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -22,6 +22,7 @@
22#include <linux/seq_file.h> 22#include <linux/seq_file.h>
23#include <linux/pagemap.h> 23#include <linux/pagemap.h>
24#include <linux/init.h> 24#include <linux/init.h>
25#include <linux/inet.h>
25#include <linux/string.h> 26#include <linux/string.h>
26#include <linux/smp_lock.h> 27#include <linux/smp_lock.h>
27#include <linux/ctype.h> 28#include <linux/ctype.h>
@@ -35,6 +36,7 @@
35#include <linux/nfsd/cache.h> 36#include <linux/nfsd/cache.h>
36#include <linux/nfsd/xdr.h> 37#include <linux/nfsd/xdr.h>
37#include <linux/nfsd/syscall.h> 38#include <linux/nfsd/syscall.h>
39#include <linux/lockd/lockd.h>
38 40
39#include <asm/uaccess.h> 41#include <asm/uaccess.h>
40#include <net/ipv6.h> 42#include <net/ipv6.h>
@@ -53,6 +55,7 @@ enum {
53 NFSD_Getfs, 55 NFSD_Getfs,
54 NFSD_List, 56 NFSD_List,
55 NFSD_Fh, 57 NFSD_Fh,
58 NFSD_FO_UnlockIP,
56 NFSD_Threads, 59 NFSD_Threads,
57 NFSD_Pool_Threads, 60 NFSD_Pool_Threads,
58 NFSD_Versions, 61 NFSD_Versions,
@@ -89,6 +92,8 @@ static ssize_t write_leasetime(struct file *file, char *buf, size_t size);
89static ssize_t write_recoverydir(struct file *file, char *buf, size_t size); 92static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
90#endif 93#endif
91 94
95static ssize_t failover_unlock_ip(struct file *file, char *buf, size_t size);
96
92static ssize_t (*write_op[])(struct file *, char *, size_t) = { 97static ssize_t (*write_op[])(struct file *, char *, size_t) = {
93 [NFSD_Svc] = write_svc, 98 [NFSD_Svc] = write_svc,
94 [NFSD_Add] = write_add, 99 [NFSD_Add] = write_add,
@@ -98,6 +103,7 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
98 [NFSD_Getfd] = write_getfd, 103 [NFSD_Getfd] = write_getfd,
99 [NFSD_Getfs] = write_getfs, 104 [NFSD_Getfs] = write_getfs,
100 [NFSD_Fh] = write_filehandle, 105 [NFSD_Fh] = write_filehandle,
106 [NFSD_FO_UnlockIP] = failover_unlock_ip,
101 [NFSD_Threads] = write_threads, 107 [NFSD_Threads] = write_threads,
102 [NFSD_Pool_Threads] = write_pool_threads, 108 [NFSD_Pool_Threads] = write_pool_threads,
103 [NFSD_Versions] = write_versions, 109 [NFSD_Versions] = write_versions,
@@ -298,6 +304,31 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size)
298 return err; 304 return err;
299} 305}
300 306
307static ssize_t failover_unlock_ip(struct file *file, char *buf, size_t size)
308{
309 __be32 server_ip;
310 char *fo_path, c;
311 int b1, b2, b3, b4;
312
313 /* sanity check */
314 if (size == 0)
315 return -EINVAL;
316
317 if (buf[size-1] != '\n')
318 return -EINVAL;
319
320 fo_path = buf;
321 if (qword_get(&buf, fo_path, size) < 0)
322 return -EINVAL;
323
324 /* get ipv4 address */
325 if (sscanf(fo_path, "%u.%u.%u.%u%c", &b1, &b2, &b3, &b4, &c) != 4)
326 return -EINVAL;
327 server_ip = htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
328
329 return nlmsvc_unlock_all_by_ip(server_ip);
330}
331
301static ssize_t write_filehandle(struct file *file, char *buf, size_t size) 332static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
302{ 333{
303 /* request is: 334 /* request is:
@@ -700,6 +731,8 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
700 [NFSD_Getfd] = {".getfd", &transaction_ops, S_IWUSR|S_IRUSR}, 731 [NFSD_Getfd] = {".getfd", &transaction_ops, S_IWUSR|S_IRUSR},
701 [NFSD_Getfs] = {".getfs", &transaction_ops, S_IWUSR|S_IRUSR}, 732 [NFSD_Getfs] = {".getfs", &transaction_ops, S_IWUSR|S_IRUSR},
702 [NFSD_List] = {"exports", &exports_operations, S_IRUGO}, 733 [NFSD_List] = {"exports", &exports_operations, S_IRUGO},
734 [NFSD_FO_UnlockIP] = {"unlock_ip",
735 &transaction_ops, S_IWUSR|S_IRUSR},
703 [NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR}, 736 [NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR},
704 [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR}, 737 [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR},
705 [NFSD_Pool_Threads] = {"pool_threads", &transaction_ops, S_IWUSR|S_IRUSR}, 738 [NFSD_Pool_Threads] = {"pool_threads", &transaction_ops, S_IWUSR|S_IRUSR},