Blame view
fs/lockd/clntlock.c
6.88 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 7 8 9 10 |
/* * linux/fs/lockd/clntlock.c * * Lock handling for the client side NLM implementation * * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de> */ #include <linux/module.h> #include <linux/types.h> |
5a0e3ad6a include cleanup: ... |
11 |
#include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
12 13 14 15 16 |
#include <linux/time.h> #include <linux/nfs_fs.h> #include <linux/sunrpc/clnt.h> #include <linux/sunrpc/svc.h> #include <linux/lockd/lockd.h> |
df94f000c lockd: convert re... |
17 |
#include <linux/kthread.h> |
1da177e4c Linux-2.6.12-rc2 |
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
#define NLMDBG_FACILITY NLMDBG_CLIENT /* * Local function prototypes */ static int reclaimer(void *ptr); /* * The following functions handle blocking and granting from the * client perspective. */ /* * This is the representation of a blocked client lock. */ struct nlm_wait { |
4f15e2b1f [PATCH] NLM: clea... |
35 |
struct list_head b_list; /* linked list */ |
1da177e4c Linux-2.6.12-rc2 |
36 37 38 39 |
wait_queue_head_t b_wait; /* where to wait on */ struct nlm_host * b_host; struct file_lock * b_lock; /* local file lock */ unsigned short b_reclaim; /* got to reclaim lock */ |
e8c5c045d [PATCH] lockd end... |
40 |
__be32 b_status; /* grant callback status */ |
1da177e4c Linux-2.6.12-rc2 |
41 |
}; |
4f15e2b1f [PATCH] NLM: clea... |
42 |
static LIST_HEAD(nlm_blocked); |
63185942c lockd: Remove BKL... |
43 |
static DEFINE_SPINLOCK(nlm_blocked_lock); |
1da177e4c Linux-2.6.12-rc2 |
44 |
|
52c4044d0 NLM: Introduce ex... |
45 46 |
/** * nlmclnt_init - Set up per-NFS mount point lockd data structures |
883bb163f NLM: Introduce an... |
47 |
* @nlm_init: pointer to arguments structure |
52c4044d0 NLM: Introduce ex... |
48 49 50 51 |
* * Returns pointer to an appropriate nlm_host struct, * or an ERR_PTR value. */ |
883bb163f NLM: Introduce an... |
52 |
struct nlm_host *nlmclnt_init(const struct nlmclnt_initdata *nlm_init) |
52c4044d0 NLM: Introduce ex... |
53 54 |
{ struct nlm_host *host; |
883bb163f NLM: Introduce an... |
55 |
u32 nlm_version = (nlm_init->nfs_version == 2) ? 1 : 4; |
52c4044d0 NLM: Introduce ex... |
56 |
int status; |
26a414092 NLM: Remove "prot... |
57 |
status = lockd_up(); |
52c4044d0 NLM: Introduce ex... |
58 59 |
if (status < 0) return ERR_PTR(status); |
d7d204403 lockd: Adjust nlm... |
60 |
host = nlmclnt_lookup_host(nlm_init->address, nlm_init->addrlen, |
883bb163f NLM: Introduce an... |
61 |
nlm_init->protocol, nlm_version, |
0cb2659b8 NLM: allow lockd ... |
62 |
nlm_init->hostname, nlm_init->noresvport); |
52c4044d0 NLM: Introduce ex... |
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
if (host == NULL) { lockd_down(); return ERR_PTR(-ENOLCK); } return host; } EXPORT_SYMBOL_GPL(nlmclnt_init); /** * nlmclnt_done - Release resources allocated by nlmclnt_init() * @host: nlm_host structure reserved by nlmclnt_init() * */ void nlmclnt_done(struct nlm_host *host) { |
8ea6ecc8b lockd: Create cli... |
79 |
nlmclnt_release_host(host); |
52c4044d0 NLM: Introduce ex... |
80 81 82 |
lockd_down(); } EXPORT_SYMBOL_GPL(nlmclnt_done); |
1da177e4c Linux-2.6.12-rc2 |
83 |
/* |
ecdbf769b [PATCH] NLM: fix ... |
84 |
* Queue up a lock for blocking so that the GRANTED request can see it |
1da177e4c Linux-2.6.12-rc2 |
85 |
*/ |
3a649b884 NLM: Simplify cli... |
86 |
struct nlm_wait *nlmclnt_prepare_block(struct nlm_host *host, struct file_lock *fl) |
ecdbf769b [PATCH] NLM: fix ... |
87 88 |
{ struct nlm_wait *block; |
ecdbf769b [PATCH] NLM: fix ... |
89 |
block = kmalloc(sizeof(*block), GFP_KERNEL); |
3a649b884 NLM: Simplify cli... |
90 91 92 93 |
if (block != NULL) { block->b_host = host; block->b_lock = fl; init_waitqueue_head(&block->b_wait); |
e8c5c045d [PATCH] lockd end... |
94 |
block->b_status = nlm_lck_blocked; |
63185942c lockd: Remove BKL... |
95 96 |
spin_lock(&nlm_blocked_lock); |
3a649b884 NLM: Simplify cli... |
97 |
list_add(&block->b_list, &nlm_blocked); |
63185942c lockd: Remove BKL... |
98 |
spin_unlock(&nlm_blocked_lock); |
3a649b884 NLM: Simplify cli... |
99 100 |
} return block; |
ecdbf769b [PATCH] NLM: fix ... |
101 |
} |
3a649b884 NLM: Simplify cli... |
102 |
void nlmclnt_finish_block(struct nlm_wait *block) |
1da177e4c Linux-2.6.12-rc2 |
103 |
{ |
ecdbf769b [PATCH] NLM: fix ... |
104 105 |
if (block == NULL) return; |
63185942c lockd: Remove BKL... |
106 |
spin_lock(&nlm_blocked_lock); |
ecdbf769b [PATCH] NLM: fix ... |
107 |
list_del(&block->b_list); |
63185942c lockd: Remove BKL... |
108 |
spin_unlock(&nlm_blocked_lock); |
ecdbf769b [PATCH] NLM: fix ... |
109 110 |
kfree(block); } |
1da177e4c Linux-2.6.12-rc2 |
111 |
|
ecdbf769b [PATCH] NLM: fix ... |
112 113 114 |
/* * Block on a lock */ |
3a649b884 NLM: Simplify cli... |
115 |
int nlmclnt_block(struct nlm_wait *block, struct nlm_rqst *req, long timeout) |
ecdbf769b [PATCH] NLM: fix ... |
116 |
{ |
ecdbf769b [PATCH] NLM: fix ... |
117 |
long ret; |
1da177e4c Linux-2.6.12-rc2 |
118 |
|
ecdbf769b [PATCH] NLM: fix ... |
119 120 121 |
/* A borken server might ask us to block even if we didn't * request it. Just say no! */ |
3a649b884 NLM: Simplify cli... |
122 |
if (block == NULL) |
ecdbf769b [PATCH] NLM: fix ... |
123 |
return -EAGAIN; |
1da177e4c Linux-2.6.12-rc2 |
124 125 126 127 128 129 130 131 132 |
/* Go to sleep waiting for GRANT callback. Some servers seem * to lose callbacks, however, so we're going to poll from * time to time just to make sure. * * For now, the retry frequency is pretty high; normally * a 1 minute timeout would do. See the comment before * nlmclnt_lock for an explanation. */ |
ecdbf769b [PATCH] NLM: fix ... |
133 |
ret = wait_event_interruptible_timeout(block->b_wait, |
e8c5c045d [PATCH] lockd end... |
134 |
block->b_status != nlm_lck_blocked, |
ecdbf769b [PATCH] NLM: fix ... |
135 |
timeout); |
3a649b884 NLM: Simplify cli... |
136 137 138 139 |
if (ret < 0) return -ERESTARTSYS; req->a_res.status = block->b_status; return 0; |
1da177e4c Linux-2.6.12-rc2 |
140 141 142 143 144 |
} /* * The server lockd has called us back to tell us the lock was granted */ |
dcff09f12 lockd: change nlm... |
145 |
__be32 nlmclnt_grant(const struct sockaddr *addr, const struct nlm_lock *lock) |
1da177e4c Linux-2.6.12-rc2 |
146 |
{ |
5ac5f9d1c [PATCH] NLM: Fix ... |
147 148 |
const struct file_lock *fl = &lock->fl; const struct nfs_fh *fh = &lock->fh; |
1da177e4c Linux-2.6.12-rc2 |
149 |
struct nlm_wait *block; |
52921e02a [PATCH] lockd end... |
150 |
__be32 res = nlm_lck_denied; |
1da177e4c Linux-2.6.12-rc2 |
151 152 153 154 155 |
/* * Look up blocked request based on arguments. * Warning: must not use cookie to match it! */ |
63185942c lockd: Remove BKL... |
156 |
spin_lock(&nlm_blocked_lock); |
4f15e2b1f [PATCH] NLM: clea... |
157 |
list_for_each_entry(block, &nlm_blocked, b_list) { |
5ac5f9d1c [PATCH] NLM: Fix ... |
158 |
struct file_lock *fl_blocked = block->b_lock; |
7bab377fc lockd: Don't expo... |
159 160 161 162 163 164 165 166 167 |
if (fl_blocked->fl_start != fl->fl_start) continue; if (fl_blocked->fl_end != fl->fl_end) continue; /* * Careful! The NLM server will return the 32-bit "pid" that * we put on the wire: in this case the lockowner "pid". */ if (fl_blocked->fl_u.nfs_fl.owner->pid != lock->svid) |
5ac5f9d1c [PATCH] NLM: Fix ... |
168 |
continue; |
4516fc045 sunrpc: add routi... |
169 |
if (!rpc_cmp_addr(nlm_addr(block->b_host), addr)) |
5ac5f9d1c [PATCH] NLM: Fix ... |
170 |
continue; |
225a719f7 [PATCH] struct pa... |
171 |
if (nfs_compare_fh(NFS_FH(fl_blocked->fl_file->f_path.dentry->d_inode) ,fh) != 0) |
5ac5f9d1c [PATCH] NLM: Fix ... |
172 173 174 175 |
continue; /* Alright, we found a lock. Set the return status * and wake up the caller */ |
e8c5c045d [PATCH] lockd end... |
176 |
block->b_status = nlm_granted; |
5ac5f9d1c [PATCH] NLM: Fix ... |
177 178 |
wake_up(&block->b_wait); res = nlm_granted; |
1da177e4c Linux-2.6.12-rc2 |
179 |
} |
63185942c lockd: Remove BKL... |
180 |
spin_unlock(&nlm_blocked_lock); |
ecdbf769b [PATCH] NLM: fix ... |
181 |
return res; |
1da177e4c Linux-2.6.12-rc2 |
182 183 184 185 186 187 188 189 |
} /* * The following procedures deal with the recovery of locks after a * server crash. */ /* |
1da177e4c Linux-2.6.12-rc2 |
190 191 192 193 |
* Reclaim all locks on server host. We do this by spawning a separate * reclaimer thread. */ void |
5c8dd29ca [PATCH] knfsd: lo... |
194 |
nlmclnt_recovery(struct nlm_host *host) |
1da177e4c Linux-2.6.12-rc2 |
195 |
{ |
df94f000c lockd: convert re... |
196 |
struct task_struct *task; |
28df955a2 NLM: Fix reclaim ... |
197 |
if (!host->h_reclaiming++) { |
1da177e4c Linux-2.6.12-rc2 |
198 |
nlm_get_host(host); |
df94f000c lockd: convert re... |
199 200 201 202 203 204 |
task = kthread_run(reclaimer, host, "%s-reclaim", host->h_name); if (IS_ERR(task)) printk(KERN_ERR "lockd: unable to spawn reclaimer " "thread. Locks for %s won't be reclaimed! " "(%ld) ", host->h_name, PTR_ERR(task)); |
1da177e4c Linux-2.6.12-rc2 |
205 206 207 208 209 210 211 212 |
} } static int reclaimer(void *ptr) { struct nlm_host *host = (struct nlm_host *) ptr; struct nlm_wait *block; |
26bcbf965 lockd: stop abusi... |
213 |
struct file_lock *fl, *next; |
28df955a2 NLM: Fix reclaim ... |
214 |
u32 nsmstate; |
1da177e4c Linux-2.6.12-rc2 |
215 |
|
1da177e4c Linux-2.6.12-rc2 |
216 |
allow_signal(SIGKILL); |
5c8dd29ca [PATCH] knfsd: lo... |
217 |
down_write(&host->h_rwsem); |
26a414092 NLM: Remove "prot... |
218 |
lockd_up(); /* note: this cannot fail as lockd is already running */ |
1da177e4c Linux-2.6.12-rc2 |
219 |
|
d019bcf0e [PATCH] fs/lockd/... |
220 221 |
dprintk("lockd: reclaiming locks for host %s ", host->h_name); |
5c8dd29ca [PATCH] knfsd: lo... |
222 |
|
1da177e4c Linux-2.6.12-rc2 |
223 |
restart: |
28df955a2 NLM: Fix reclaim ... |
224 |
nsmstate = host->h_nsmstate; |
5c8dd29ca [PATCH] knfsd: lo... |
225 226 227 228 |
/* Force a portmap getport - the peer's lockd will * most likely end up on a different port. */ |
0ade060ee [PATCH] knfsd: lo... |
229 |
host->h_nextrebind = jiffies; |
5c8dd29ca [PATCH] knfsd: lo... |
230 231 232 233 |
nlm_rebind_host(host); /* First, reclaim all locks that have been granted. */ list_splice_init(&host->h_granted, &host->h_reclaim); |
26bcbf965 lockd: stop abusi... |
234 |
list_for_each_entry_safe(fl, next, &host->h_reclaim, fl_u.nfs_fl.list) { |
4c060b531 lockd: Fix Oopses... |
235 |
list_del_init(&fl->fl_u.nfs_fl.list); |
1da177e4c Linux-2.6.12-rc2 |
236 |
|
df94f000c lockd: convert re... |
237 238 239 240 241 242 |
/* * sending this thread a SIGKILL will result in any unreclaimed * locks being removed from the h_granted list. This means that * the kernel will not attempt to reclaim them again if a new * reclaimer thread is spawned for this host. */ |
1da177e4c Linux-2.6.12-rc2 |
243 |
if (signalled()) |
4c060b531 lockd: Fix Oopses... |
244 |
continue; |
28df955a2 NLM: Fix reclaim ... |
245 246 247 248 249 |
if (nlmclnt_reclaim(host, fl) != 0) continue; list_add_tail(&fl->fl_u.nfs_fl.list, &host->h_granted); if (host->h_nsmstate != nsmstate) { /* Argh! The server rebooted again! */ |
28df955a2 NLM: Fix reclaim ... |
250 251 |
goto restart; } |
1da177e4c Linux-2.6.12-rc2 |
252 |
} |
5c8dd29ca [PATCH] knfsd: lo... |
253 254 255 |
host->h_reclaiming = 0; up_write(&host->h_rwsem); |
d019bcf0e [PATCH] fs/lockd/... |
256 257 |
dprintk("NLM: done reclaiming locks for host %s ", host->h_name); |
1da177e4c Linux-2.6.12-rc2 |
258 259 |
/* Now, wake up all processes that sleep on a blocked lock */ |
63185942c lockd: Remove BKL... |
260 |
spin_lock(&nlm_blocked_lock); |
4f15e2b1f [PATCH] NLM: clea... |
261 |
list_for_each_entry(block, &nlm_blocked, b_list) { |
1da177e4c Linux-2.6.12-rc2 |
262 |
if (block->b_host == host) { |
e8c5c045d [PATCH] lockd end... |
263 |
block->b_status = nlm_lck_denied_grace_period; |
1da177e4c Linux-2.6.12-rc2 |
264 265 266 |
wake_up(&block->b_wait); } } |
63185942c lockd: Remove BKL... |
267 |
spin_unlock(&nlm_blocked_lock); |
1da177e4c Linux-2.6.12-rc2 |
268 269 |
/* Release host handle after use */ |
8ea6ecc8b lockd: Create cli... |
270 |
nlmclnt_release_host(host); |
1da177e4c Linux-2.6.12-rc2 |
271 |
lockd_down(); |
df94f000c lockd: convert re... |
272 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
273 |
} |