diff options
author | M. Mohan Kumar <mohan@in.ibm.com> | 2010-09-27 02:04:24 -0400 |
---|---|---|
committer | Eric Van Hensbergen <ericvh@gmail.com> | 2010-10-28 10:08:47 -0400 |
commit | a099027c779068b834f335cfdc3f2bf10f531dd9 (patch) | |
tree | eee43443cce85a03c13b1cfdd25bf451445cf78f /fs/9p/vfs_file.c | |
parent | 920e65dc6911da28a58e17f4b683302636fc6d8e (diff) |
9p: Implement TLOCK
Synopsis
size[4] TLock tag[2] fid[4] flock[n]
size[4] RLock tag[2] status[1]
Description
Tlock is used to acquire/release byte range posix locks on a file
identified by given fid. The reply contains status of the lock request
flock structure:
type[1] - Type of lock: F_RDLCK, F_WRLCK, F_UNLCK
flags[4] - Flags could be either of
P9_LOCK_FLAGS_BLOCK - Blocked lock request, if there is a
conflicting lock exists, wait for that lock to be released.
P9_LOCK_FLAGS_RECLAIM - Reclaim lock request, used when client is
trying to reclaim a lock after a server restrart (due to crash)
start[8] - Starting offset for lock
length[8] - Number of bytes to lock
If length is 0, lock all bytes starting at the location 'start'
through to the end of file
pid[4] - PID of the process that wants to take lock
client_id[4] - Unique client id
status[1] - Status of the lock request, can be
P9_LOCK_SUCCESS(0), P9_LOCK_BLOCKED(1), P9_LOCK_ERROR(2) or
P9_LOCK_GRACE(3)
P9_LOCK_SUCCESS - Request was successful
P9_LOCK_BLOCKED - A conflicting lock is held by another process
P9_LOCK_ERROR - Error while processing the lock request
P9_LOCK_GRACE - Server is in grace period, it can't accept new lock
requests in this period (except locks with
P9_LOCK_FLAGS_RECLAIM flag set)
Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com>
Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
Diffstat (limited to 'fs/9p/vfs_file.c')
-rw-r--r-- | fs/9p/vfs_file.c | 160 |
1 files changed, 158 insertions, 2 deletions
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index fdf303207c72..6f77abd23184 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/inet.h> | 33 | #include <linux/inet.h> |
34 | #include <linux/list.h> | 34 | #include <linux/list.h> |
35 | #include <linux/pagemap.h> | 35 | #include <linux/pagemap.h> |
36 | #include <linux/utsname.h> | ||
36 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
37 | #include <linux/idr.h> | 38 | #include <linux/idr.h> |
38 | #include <net/9p/9p.h> | 39 | #include <net/9p/9p.h> |
@@ -133,6 +134,159 @@ static int v9fs_file_lock(struct file *filp, int cmd, struct file_lock *fl) | |||
133 | return res; | 134 | return res; |
134 | } | 135 | } |
135 | 136 | ||
137 | static int v9fs_file_do_lock(struct file *filp, int cmd, struct file_lock *fl) | ||
138 | { | ||
139 | struct p9_flock flock; | ||
140 | struct p9_fid *fid; | ||
141 | uint8_t status; | ||
142 | int res = 0; | ||
143 | unsigned char fl_type; | ||
144 | |||
145 | fid = filp->private_data; | ||
146 | BUG_ON(fid == NULL); | ||
147 | |||
148 | if ((fl->fl_flags & FL_POSIX) != FL_POSIX) | ||
149 | BUG(); | ||
150 | |||
151 | res = posix_lock_file_wait(filp, fl); | ||
152 | if (res < 0) | ||
153 | goto out; | ||
154 | |||
155 | /* convert posix lock to p9 tlock args */ | ||
156 | memset(&flock, 0, sizeof(flock)); | ||
157 | flock.type = fl->fl_type; | ||
158 | flock.start = fl->fl_start; | ||
159 | if (fl->fl_end == OFFSET_MAX) | ||
160 | flock.length = 0; | ||
161 | else | ||
162 | flock.length = fl->fl_end - fl->fl_start + 1; | ||
163 | flock.proc_id = fl->fl_pid; | ||
164 | flock.client_id = utsname()->nodename; | ||
165 | if (IS_SETLKW(cmd)) | ||
166 | flock.flags = P9_LOCK_FLAGS_BLOCK; | ||
167 | |||
168 | /* | ||
169 | * if its a blocked request and we get P9_LOCK_BLOCKED as the status | ||
170 | * for lock request, keep on trying | ||
171 | */ | ||
172 | for (;;) { | ||
173 | res = p9_client_lock_dotl(fid, &flock, &status); | ||
174 | if (res < 0) | ||
175 | break; | ||
176 | |||
177 | if (status != P9_LOCK_BLOCKED) | ||
178 | break; | ||
179 | if (status == P9_LOCK_BLOCKED && !IS_SETLKW(cmd)) | ||
180 | break; | ||
181 | schedule_timeout_interruptible(P9_LOCK_TIMEOUT); | ||
182 | } | ||
183 | |||
184 | /* map 9p status to VFS status */ | ||
185 | switch (status) { | ||
186 | case P9_LOCK_SUCCESS: | ||
187 | res = 0; | ||
188 | break; | ||
189 | case P9_LOCK_BLOCKED: | ||
190 | res = -EAGAIN; | ||
191 | break; | ||
192 | case P9_LOCK_ERROR: | ||
193 | case P9_LOCK_GRACE: | ||
194 | res = -ENOLCK; | ||
195 | break; | ||
196 | default: | ||
197 | BUG(); | ||
198 | } | ||
199 | |||
200 | /* | ||
201 | * incase server returned error for lock request, revert | ||
202 | * it locally | ||
203 | */ | ||
204 | if (res < 0 && fl->fl_type != F_UNLCK) { | ||
205 | fl_type = fl->fl_type; | ||
206 | fl->fl_type = F_UNLCK; | ||
207 | res = posix_lock_file_wait(filp, fl); | ||
208 | fl->fl_type = fl_type; | ||
209 | } | ||
210 | out: | ||
211 | return res; | ||
212 | } | ||
213 | |||
214 | /** | ||
215 | * v9fs_file_lock_dotl - lock a file (or directory) | ||
216 | * @filp: file to be locked | ||
217 | * @cmd: lock command | ||
218 | * @fl: file lock structure | ||
219 | * | ||
220 | */ | ||
221 | |||
222 | static int v9fs_file_lock_dotl(struct file *filp, int cmd, struct file_lock *fl) | ||
223 | { | ||
224 | struct inode *inode = filp->f_path.dentry->d_inode; | ||
225 | int ret = -ENOLCK; | ||
226 | |||
227 | P9_DPRINTK(P9_DEBUG_VFS, "filp: %p cmd:%d lock: %p name: %s\n", filp, | ||
228 | cmd, fl, filp->f_path.dentry->d_name.name); | ||
229 | |||
230 | /* No mandatory locks */ | ||
231 | if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK) | ||
232 | goto out_err; | ||
233 | |||
234 | if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) { | ||
235 | filemap_write_and_wait(inode->i_mapping); | ||
236 | invalidate_mapping_pages(&inode->i_data, 0, -1); | ||
237 | } | ||
238 | |||
239 | if (IS_SETLK(cmd) || IS_SETLKW(cmd)) | ||
240 | ret = v9fs_file_do_lock(filp, cmd, fl); | ||
241 | else | ||
242 | ret = -EINVAL; | ||
243 | out_err: | ||
244 | return ret; | ||
245 | } | ||
246 | |||
247 | /** | ||
248 | * v9fs_file_flock_dotl - lock a file | ||
249 | * @filp: file to be locked | ||
250 | * @cmd: lock command | ||
251 | * @fl: file lock structure | ||
252 | * | ||
253 | */ | ||
254 | |||
255 | static int v9fs_file_flock_dotl(struct file *filp, int cmd, | ||
256 | struct file_lock *fl) | ||
257 | { | ||
258 | struct inode *inode = filp->f_path.dentry->d_inode; | ||
259 | int ret = -ENOLCK; | ||
260 | |||
261 | P9_DPRINTK(P9_DEBUG_VFS, "filp: %p cmd:%d lock: %p name: %s\n", filp, | ||
262 | cmd, fl, filp->f_path.dentry->d_name.name); | ||
263 | |||
264 | /* No mandatory locks */ | ||
265 | if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK) | ||
266 | goto out_err; | ||
267 | |||
268 | if (!(fl->fl_flags & FL_FLOCK)) | ||
269 | goto out_err; | ||
270 | |||
271 | if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) { | ||
272 | filemap_write_and_wait(inode->i_mapping); | ||
273 | invalidate_mapping_pages(&inode->i_data, 0, -1); | ||
274 | } | ||
275 | /* Convert flock to posix lock */ | ||
276 | fl->fl_owner = (fl_owner_t)filp; | ||
277 | fl->fl_start = 0; | ||
278 | fl->fl_end = OFFSET_MAX; | ||
279 | fl->fl_flags |= FL_POSIX; | ||
280 | fl->fl_flags ^= FL_FLOCK; | ||
281 | |||
282 | if (IS_SETLK(cmd) | IS_SETLKW(cmd)) | ||
283 | ret = v9fs_file_do_lock(filp, cmd, fl); | ||
284 | else | ||
285 | ret = -EINVAL; | ||
286 | out_err: | ||
287 | return ret; | ||
288 | } | ||
289 | |||
136 | /** | 290 | /** |
137 | * v9fs_file_readn - read from a file | 291 | * v9fs_file_readn - read from a file |
138 | * @filp: file pointer to read | 292 | * @filp: file pointer to read |
@@ -323,7 +477,8 @@ static const struct file_operations v9fs_cached_file_operations_dotl = { | |||
323 | .write = v9fs_file_write, | 477 | .write = v9fs_file_write, |
324 | .open = v9fs_file_open, | 478 | .open = v9fs_file_open, |
325 | .release = v9fs_dir_release, | 479 | .release = v9fs_dir_release, |
326 | .lock = v9fs_file_lock, | 480 | .lock = v9fs_file_lock_dotl, |
481 | .flock = v9fs_file_flock_dotl, | ||
327 | .mmap = generic_file_readonly_mmap, | 482 | .mmap = generic_file_readonly_mmap, |
328 | .fsync = v9fs_file_fsync_dotl, | 483 | .fsync = v9fs_file_fsync_dotl, |
329 | }; | 484 | }; |
@@ -345,7 +500,8 @@ const struct file_operations v9fs_file_operations_dotl = { | |||
345 | .write = v9fs_file_write, | 500 | .write = v9fs_file_write, |
346 | .open = v9fs_file_open, | 501 | .open = v9fs_file_open, |
347 | .release = v9fs_dir_release, | 502 | .release = v9fs_dir_release, |
348 | .lock = v9fs_file_lock, | 503 | .lock = v9fs_file_lock_dotl, |
504 | .flock = v9fs_file_flock_dotl, | ||
349 | .mmap = generic_file_readonly_mmap, | 505 | .mmap = generic_file_readonly_mmap, |
350 | .fsync = v9fs_file_fsync_dotl, | 506 | .fsync = v9fs_file_fsync_dotl, |
351 | }; | 507 | }; |