aboutsummaryrefslogtreecommitdiffstats
path: root/fs/lockd/svcsubs.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/lockd/svcsubs.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/lockd/svcsubs.c')
-rw-r--r--fs/lockd/svcsubs.c36
1 files changed, 31 insertions, 5 deletions
diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
index dbbefbcd6712..1adcf93cb6e6 100644
--- a/fs/lockd/svcsubs.c
+++ b/fs/lockd/svcsubs.c
@@ -18,6 +18,8 @@
18#include <linux/lockd/lockd.h> 18#include <linux/lockd/lockd.h>
19#include <linux/lockd/share.h> 19#include <linux/lockd/share.h>
20#include <linux/lockd/sm_inter.h> 20#include <linux/lockd/sm_inter.h>
21#include <linux/module.h>
22#include <linux/mount.h>
21 23
22#define NLMDBG_FACILITY NLMDBG_SVCSUBS 24#define NLMDBG_FACILITY NLMDBG_SVCSUBS
23 25
@@ -230,7 +232,7 @@ nlm_file_inuse(struct nlm_file *file)
230 * Loop over all files in the file table. 232 * Loop over all files in the file table.
231 */ 233 */
232static int 234static int
233nlm_traverse_files(struct nlm_host *host, nlm_host_match_fn_t match) 235nlm_traverse_files(void *data, nlm_host_match_fn_t match)
234{ 236{
235 struct hlist_node *pos, *next; 237 struct hlist_node *pos, *next;
236 struct nlm_file *file; 238 struct nlm_file *file;
@@ -244,7 +246,7 @@ nlm_traverse_files(struct nlm_host *host, nlm_host_match_fn_t match)
244 246
245 /* Traverse locks, blocks and shares of this file 247 /* Traverse locks, blocks and shares of this file
246 * and update file->f_locks count */ 248 * and update file->f_locks count */
247 if (nlm_inspect_file(host, file, match)) 249 if (nlm_inspect_file(data, file, match))
248 ret = 1; 250 ret = 1;
249 251
250 mutex_lock(&nlm_file_mutex); 252 mutex_lock(&nlm_file_mutex);
@@ -303,21 +305,27 @@ nlm_release_file(struct nlm_file *file)
303 * Used by nlmsvc_invalidate_all 305 * Used by nlmsvc_invalidate_all
304 */ 306 */
305static int 307static int
306nlmsvc_mark_host(struct nlm_host *host, struct nlm_host *dummy) 308nlmsvc_mark_host(void *data, struct nlm_host *dummy)
307{ 309{
310 struct nlm_host *host = data;
311
308 host->h_inuse = 1; 312 host->h_inuse = 1;
309 return 0; 313 return 0;
310} 314}
311 315
312static int 316static int
313nlmsvc_same_host(struct nlm_host *host, struct nlm_host *other) 317nlmsvc_same_host(void *data, struct nlm_host *other)
314{ 318{
319 struct nlm_host *host = data;
320
315 return host == other; 321 return host == other;
316} 322}
317 323
318static int 324static int
319nlmsvc_is_client(struct nlm_host *host, struct nlm_host *dummy) 325nlmsvc_is_client(void *data, struct nlm_host *dummy)
320{ 326{
327 struct nlm_host *host = data;
328
321 if (host->h_server) { 329 if (host->h_server) {
322 /* we are destroying locks even though the client 330 /* we are destroying locks even though the client
323 * hasn't asked us too, so don't unmonitor the 331 * hasn't asked us too, so don't unmonitor the
@@ -370,3 +378,21 @@ nlmsvc_invalidate_all(void)
370 */ 378 */
371 nlm_traverse_files(NULL, nlmsvc_is_client); 379 nlm_traverse_files(NULL, nlmsvc_is_client);
372} 380}
381
382static int
383nlmsvc_match_ip(void *datap, struct nlm_host *host)
384{
385 __be32 *server_addr = datap;
386
387 return host->h_saddr.sin_addr.s_addr == *server_addr;
388}
389
390int
391nlmsvc_unlock_all_by_ip(__be32 server_addr)
392{
393 int ret;
394 ret = nlm_traverse_files(&server_addr, nlmsvc_match_ip);
395 return ret ? -EIO : 0;
396
397}
398EXPORT_SYMBOL_GPL(nlmsvc_unlock_all_by_ip);