diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-25 12:18:27 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-25 12:18:27 -0500 |
commit | 53846a21c1766326bb14ce8ab6e997a0c120675d (patch) | |
tree | 37b04485e29844b4e734479181276a2f4d2447e4 /fs/lockd/clntlock.c | |
parent | 2e9abdd9bad485970b37cd53a82f92702054984c (diff) | |
parent | 1ebbe2b20091d306453a5cf480a87e6cd28ae76f (diff) |
Merge git://git.linux-nfs.org/pub/linux/nfs-2.6
* git://git.linux-nfs.org/pub/linux/nfs-2.6: (103 commits)
SUNRPC,RPCSEC_GSS: spkm3--fix config dependencies
SUNRPC,RPCSEC_GSS: spkm3: import contexts using NID_cast5_cbc
LOCKD: Make nlmsvc_traverse_shares return void
LOCKD: nlmsvc_traverse_blocks return is unused
SUNRPC,RPCSEC_GSS: fix krb5 sequence numbers.
NFSv4: Dont list system.nfs4_acl for filesystems that don't support it.
SUNRPC,RPCSEC_GSS: remove unnecessary kmalloc of a checksum
SUNRPC: Ensure rpc_call_async() always calls tk_ops->rpc_release()
SUNRPC: Fix memory barriers for req->rq_received
NFS: Fix a race in nfs_sync_inode()
NFS: Clean up nfs_flush_list()
NFS: Fix a race with PG_private and nfs_release_page()
NFSv4: Ensure the callback daemon flushes signals
SUNRPC: Fix a 'Busy inodes' error in rpc_pipefs
NFS, NLM: Allow blocking locks to respect signals
NFS: Make nfs_fhget() return appropriate error values
NFSv4: Fix an oops in nfs4_fill_super
lockd: blocks should hold a reference to the nlm_file
NFSv4: SETCLIENTID_CONFIRM should handle NFS4ERR_DELAY/NFS4ERR_RESOURCE
NFSv4: Send the delegation stateid for SETATTR calls
...
Diffstat (limited to 'fs/lockd/clntlock.c')
-rw-r--r-- | fs/lockd/clntlock.c | 112 |
1 files changed, 37 insertions, 75 deletions
diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c index da6354baa0b8..bce744468708 100644 --- a/fs/lockd/clntlock.c +++ b/fs/lockd/clntlock.c | |||
@@ -44,32 +44,25 @@ static LIST_HEAD(nlm_blocked); | |||
44 | /* | 44 | /* |
45 | * Queue up a lock for blocking so that the GRANTED request can see it | 45 | * Queue up a lock for blocking so that the GRANTED request can see it |
46 | */ | 46 | */ |
47 | int nlmclnt_prepare_block(struct nlm_rqst *req, struct nlm_host *host, struct file_lock *fl) | 47 | struct nlm_wait *nlmclnt_prepare_block(struct nlm_host *host, struct file_lock *fl) |
48 | { | 48 | { |
49 | struct nlm_wait *block; | 49 | struct nlm_wait *block; |
50 | 50 | ||
51 | BUG_ON(req->a_block != NULL); | ||
52 | block = kmalloc(sizeof(*block), GFP_KERNEL); | 51 | block = kmalloc(sizeof(*block), GFP_KERNEL); |
53 | if (block == NULL) | 52 | if (block != NULL) { |
54 | return -ENOMEM; | 53 | block->b_host = host; |
55 | block->b_host = host; | 54 | block->b_lock = fl; |
56 | block->b_lock = fl; | 55 | init_waitqueue_head(&block->b_wait); |
57 | init_waitqueue_head(&block->b_wait); | 56 | block->b_status = NLM_LCK_BLOCKED; |
58 | block->b_status = NLM_LCK_BLOCKED; | 57 | list_add(&block->b_list, &nlm_blocked); |
59 | 58 | } | |
60 | list_add(&block->b_list, &nlm_blocked); | 59 | return block; |
61 | req->a_block = block; | ||
62 | |||
63 | return 0; | ||
64 | } | 60 | } |
65 | 61 | ||
66 | void nlmclnt_finish_block(struct nlm_rqst *req) | 62 | void nlmclnt_finish_block(struct nlm_wait *block) |
67 | { | 63 | { |
68 | struct nlm_wait *block = req->a_block; | ||
69 | |||
70 | if (block == NULL) | 64 | if (block == NULL) |
71 | return; | 65 | return; |
72 | req->a_block = NULL; | ||
73 | list_del(&block->b_list); | 66 | list_del(&block->b_list); |
74 | kfree(block); | 67 | kfree(block); |
75 | } | 68 | } |
@@ -77,15 +70,14 @@ void nlmclnt_finish_block(struct nlm_rqst *req) | |||
77 | /* | 70 | /* |
78 | * Block on a lock | 71 | * Block on a lock |
79 | */ | 72 | */ |
80 | long nlmclnt_block(struct nlm_rqst *req, long timeout) | 73 | int nlmclnt_block(struct nlm_wait *block, struct nlm_rqst *req, long timeout) |
81 | { | 74 | { |
82 | struct nlm_wait *block = req->a_block; | ||
83 | long ret; | 75 | long ret; |
84 | 76 | ||
85 | /* A borken server might ask us to block even if we didn't | 77 | /* A borken server might ask us to block even if we didn't |
86 | * request it. Just say no! | 78 | * request it. Just say no! |
87 | */ | 79 | */ |
88 | if (!req->a_args.block) | 80 | if (block == NULL) |
89 | return -EAGAIN; | 81 | return -EAGAIN; |
90 | 82 | ||
91 | /* Go to sleep waiting for GRANT callback. Some servers seem | 83 | /* Go to sleep waiting for GRANT callback. Some servers seem |
@@ -99,13 +91,10 @@ long nlmclnt_block(struct nlm_rqst *req, long timeout) | |||
99 | ret = wait_event_interruptible_timeout(block->b_wait, | 91 | ret = wait_event_interruptible_timeout(block->b_wait, |
100 | block->b_status != NLM_LCK_BLOCKED, | 92 | block->b_status != NLM_LCK_BLOCKED, |
101 | timeout); | 93 | timeout); |
102 | 94 | if (ret < 0) | |
103 | if (block->b_status != NLM_LCK_BLOCKED) { | 95 | return -ERESTARTSYS; |
104 | req->a_res.status = block->b_status; | 96 | req->a_res.status = block->b_status; |
105 | block->b_status = NLM_LCK_BLOCKED; | 97 | return 0; |
106 | } | ||
107 | |||
108 | return ret; | ||
109 | } | 98 | } |
110 | 99 | ||
111 | /* | 100 | /* |
@@ -125,7 +114,15 @@ u32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *lock) | |||
125 | list_for_each_entry(block, &nlm_blocked, b_list) { | 114 | list_for_each_entry(block, &nlm_blocked, b_list) { |
126 | struct file_lock *fl_blocked = block->b_lock; | 115 | struct file_lock *fl_blocked = block->b_lock; |
127 | 116 | ||
128 | if (!nlm_compare_locks(fl_blocked, fl)) | 117 | if (fl_blocked->fl_start != fl->fl_start) |
118 | continue; | ||
119 | if (fl_blocked->fl_end != fl->fl_end) | ||
120 | continue; | ||
121 | /* | ||
122 | * Careful! The NLM server will return the 32-bit "pid" that | ||
123 | * we put on the wire: in this case the lockowner "pid". | ||
124 | */ | ||
125 | if (fl_blocked->fl_u.nfs_fl.owner->pid != lock->svid) | ||
129 | continue; | 126 | continue; |
130 | if (!nlm_cmp_addr(&block->b_host->h_addr, addr)) | 127 | if (!nlm_cmp_addr(&block->b_host->h_addr, addr)) |
131 | continue; | 128 | continue; |
@@ -147,34 +144,6 @@ u32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *lock) | |||
147 | */ | 144 | */ |
148 | 145 | ||
149 | /* | 146 | /* |
150 | * Mark the locks for reclaiming. | ||
151 | * FIXME: In 2.5 we don't want to iterate through any global file_lock_list. | ||
152 | * Maintain NLM lock reclaiming lists in the nlm_host instead. | ||
153 | */ | ||
154 | static | ||
155 | void nlmclnt_mark_reclaim(struct nlm_host *host) | ||
156 | { | ||
157 | struct file_lock *fl; | ||
158 | struct inode *inode; | ||
159 | struct list_head *tmp; | ||
160 | |||
161 | list_for_each(tmp, &file_lock_list) { | ||
162 | fl = list_entry(tmp, struct file_lock, fl_link); | ||
163 | |||
164 | inode = fl->fl_file->f_dentry->d_inode; | ||
165 | if (inode->i_sb->s_magic != NFS_SUPER_MAGIC) | ||
166 | continue; | ||
167 | if (fl->fl_u.nfs_fl.owner == NULL) | ||
168 | continue; | ||
169 | if (fl->fl_u.nfs_fl.owner->host != host) | ||
170 | continue; | ||
171 | if (!(fl->fl_u.nfs_fl.flags & NFS_LCK_GRANTED)) | ||
172 | continue; | ||
173 | fl->fl_u.nfs_fl.flags |= NFS_LCK_RECLAIM; | ||
174 | } | ||
175 | } | ||
176 | |||
177 | /* | ||
178 | * Someone has sent us an SM_NOTIFY. Ensure we bind to the new port number, | 147 | * Someone has sent us an SM_NOTIFY. Ensure we bind to the new port number, |
179 | * that we mark locks for reclaiming, and that we bump the pseudo NSM state. | 148 | * that we mark locks for reclaiming, and that we bump the pseudo NSM state. |
180 | */ | 149 | */ |
@@ -186,7 +155,12 @@ void nlmclnt_prepare_reclaim(struct nlm_host *host, u32 newstate) | |||
186 | host->h_state++; | 155 | host->h_state++; |
187 | host->h_nextrebind = 0; | 156 | host->h_nextrebind = 0; |
188 | nlm_rebind_host(host); | 157 | nlm_rebind_host(host); |
189 | nlmclnt_mark_reclaim(host); | 158 | |
159 | /* | ||
160 | * Mark the locks for reclaiming. | ||
161 | */ | ||
162 | list_splice_init(&host->h_granted, &host->h_reclaim); | ||
163 | |||
190 | dprintk("NLM: reclaiming locks for host %s", host->h_name); | 164 | dprintk("NLM: reclaiming locks for host %s", host->h_name); |
191 | } | 165 | } |
192 | 166 | ||
@@ -215,9 +189,7 @@ reclaimer(void *ptr) | |||
215 | { | 189 | { |
216 | struct nlm_host *host = (struct nlm_host *) ptr; | 190 | struct nlm_host *host = (struct nlm_host *) ptr; |
217 | struct nlm_wait *block; | 191 | struct nlm_wait *block; |
218 | struct list_head *tmp; | 192 | struct file_lock *fl, *next; |
219 | struct file_lock *fl; | ||
220 | struct inode *inode; | ||
221 | 193 | ||
222 | daemonize("%s-reclaim", host->h_name); | 194 | daemonize("%s-reclaim", host->h_name); |
223 | allow_signal(SIGKILL); | 195 | allow_signal(SIGKILL); |
@@ -229,23 +201,13 @@ reclaimer(void *ptr) | |||
229 | 201 | ||
230 | /* First, reclaim all locks that have been marked. */ | 202 | /* First, reclaim all locks that have been marked. */ |
231 | restart: | 203 | restart: |
232 | list_for_each(tmp, &file_lock_list) { | 204 | list_for_each_entry_safe(fl, next, &host->h_reclaim, fl_u.nfs_fl.list) { |
233 | fl = list_entry(tmp, struct file_lock, fl_link); | 205 | list_del_init(&fl->fl_u.nfs_fl.list); |
234 | 206 | ||
235 | inode = fl->fl_file->f_dentry->d_inode; | ||
236 | if (inode->i_sb->s_magic != NFS_SUPER_MAGIC) | ||
237 | continue; | ||
238 | if (fl->fl_u.nfs_fl.owner == NULL) | ||
239 | continue; | ||
240 | if (fl->fl_u.nfs_fl.owner->host != host) | ||
241 | continue; | ||
242 | if (!(fl->fl_u.nfs_fl.flags & NFS_LCK_RECLAIM)) | ||
243 | continue; | ||
244 | |||
245 | fl->fl_u.nfs_fl.flags &= ~NFS_LCK_RECLAIM; | ||
246 | nlmclnt_reclaim(host, fl); | ||
247 | if (signalled()) | 207 | if (signalled()) |
248 | break; | 208 | continue; |
209 | if (nlmclnt_reclaim(host, fl) == 0) | ||
210 | list_add_tail(&fl->fl_u.nfs_fl.list, &host->h_granted); | ||
249 | goto restart; | 211 | goto restart; |
250 | } | 212 | } |
251 | 213 | ||