aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2007-10-18 06:07:04 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-18 17:37:31 -0400
commitf33321141b273d60cbb3a8f56a5489baad82ba5e (patch)
treeb6443b674600dcdb8c33aa6d44b7a673edc255b4 /fs/fuse
parentb25e82e5673c750116e8b01a4fc7d09be7809f8c (diff)
fuse: add support for mandatory locking
For mandatory locking the userspace filesystem needs to know the lock ownership for read, write and truncate operations. This patch adds the necessary fields to the protocol. Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/fuse')
-rw-r--r--fs/fuse/dir.c5
-rw-r--r--fs/fuse/file.c37
-rw-r--r--fs/fuse/fuse_i.h2
3 files changed, 36 insertions, 8 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 052327bd6c9d..6c83ed052026 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -1108,6 +1108,11 @@ static int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
1108 inarg.valid |= FATTR_FH; 1108 inarg.valid |= FATTR_FH;
1109 inarg.fh = ff->fh; 1109 inarg.fh = ff->fh;
1110 } 1110 }
1111 if (attr->ia_valid & ATTR_SIZE) {
1112 /* For mandatory locking in truncate */
1113 inarg.valid |= FATTR_LOCKOWNER;
1114 inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
1115 }
1111 req->in.h.opcode = FUSE_SETATTR; 1116 req->in.h.opcode = FUSE_SETATTR;
1112 req->in.h.nodeid = get_node_id(inode); 1117 req->in.h.nodeid = get_node_id(inode);
1113 req->in.numargs = 1; 1118 req->in.numargs = 1;
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 2b589de044e8..0fcdba9d47c0 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -189,7 +189,7 @@ static int fuse_release(struct inode *inode, struct file *file)
189 * Scramble the ID space with XTEA, so that the value of the files_struct 189 * Scramble the ID space with XTEA, so that the value of the files_struct
190 * pointer is not exposed to userspace. 190 * pointer is not exposed to userspace.
191 */ 191 */
192static u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id) 192u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id)
193{ 193{
194 u32 *k = fc->scramble_key; 194 u32 *k = fc->scramble_key;
195 u64 v = (unsigned long) id; 195 u64 v = (unsigned long) id;
@@ -308,11 +308,19 @@ void fuse_read_fill(struct fuse_req *req, struct fuse_file *ff,
308} 308}
309 309
310static size_t fuse_send_read(struct fuse_req *req, struct file *file, 310static size_t fuse_send_read(struct fuse_req *req, struct file *file,
311 struct inode *inode, loff_t pos, size_t count) 311 struct inode *inode, loff_t pos, size_t count,
312 fl_owner_t owner)
312{ 313{
313 struct fuse_conn *fc = get_fuse_conn(inode); 314 struct fuse_conn *fc = get_fuse_conn(inode);
314 struct fuse_file *ff = file->private_data; 315 struct fuse_file *ff = file->private_data;
316
315 fuse_read_fill(req, ff, inode, pos, count, FUSE_READ); 317 fuse_read_fill(req, ff, inode, pos, count, FUSE_READ);
318 if (owner != NULL) {
319 struct fuse_read_in *inarg = &req->misc.read_in;
320
321 inarg->read_flags |= FUSE_READ_LOCKOWNER;
322 inarg->lock_owner = fuse_lock_owner_id(fc, owner);
323 }
316 request_send(fc, req); 324 request_send(fc, req);
317 return req->out.args[0].size; 325 return req->out.args[0].size;
318} 326}
@@ -336,7 +344,8 @@ static int fuse_readpage(struct file *file, struct page *page)
336 req->out.page_zeroing = 1; 344 req->out.page_zeroing = 1;
337 req->num_pages = 1; 345 req->num_pages = 1;
338 req->pages[0] = page; 346 req->pages[0] = page;
339 fuse_send_read(req, file, inode, page_offset(page), PAGE_CACHE_SIZE); 347 fuse_send_read(req, file, inode, page_offset(page), PAGE_CACHE_SIZE,
348 NULL);
340 err = req->out.h.error; 349 err = req->out.h.error;
341 fuse_put_request(fc, req); 350 fuse_put_request(fc, req);
342 if (!err) 351 if (!err)
@@ -447,6 +456,7 @@ static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff,
447 struct inode *inode, loff_t pos, size_t count, 456 struct inode *inode, loff_t pos, size_t count,
448 int writepage) 457 int writepage)
449{ 458{
459 struct fuse_conn *fc = get_fuse_conn(inode);
450 struct fuse_write_in *inarg = &req->misc.write.in; 460 struct fuse_write_in *inarg = &req->misc.write.in;
451 struct fuse_write_out *outarg = &req->misc.write.out; 461 struct fuse_write_out *outarg = &req->misc.write.out;
452 462
@@ -459,7 +469,10 @@ static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff,
459 req->in.h.nodeid = get_node_id(inode); 469 req->in.h.nodeid = get_node_id(inode);
460 req->in.argpages = 1; 470 req->in.argpages = 1;
461 req->in.numargs = 2; 471 req->in.numargs = 2;
462 req->in.args[0].size = sizeof(struct fuse_write_in); 472 if (fc->minor < 9)
473 req->in.args[0].size = FUSE_COMPAT_WRITE_IN_SIZE;
474 else
475 req->in.args[0].size = sizeof(struct fuse_write_in);
463 req->in.args[0].value = inarg; 476 req->in.args[0].value = inarg;
464 req->in.args[1].size = count; 477 req->in.args[1].size = count;
465 req->out.numargs = 1; 478 req->out.numargs = 1;
@@ -468,10 +481,16 @@ static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff,
468} 481}
469 482
470static size_t fuse_send_write(struct fuse_req *req, struct file *file, 483static size_t fuse_send_write(struct fuse_req *req, struct file *file,
471 struct inode *inode, loff_t pos, size_t count) 484 struct inode *inode, loff_t pos, size_t count,
485 fl_owner_t owner)
472{ 486{
473 struct fuse_conn *fc = get_fuse_conn(inode); 487 struct fuse_conn *fc = get_fuse_conn(inode);
474 fuse_write_fill(req, file->private_data, inode, pos, count, 0); 488 fuse_write_fill(req, file->private_data, inode, pos, count, 0);
489 if (owner != NULL) {
490 struct fuse_write_in *inarg = &req->misc.write.in;
491 inarg->write_flags |= FUSE_WRITE_LOCKOWNER;
492 inarg->lock_owner = fuse_lock_owner_id(fc, owner);
493 }
475 request_send(fc, req); 494 request_send(fc, req);
476 return req->misc.write.out.size; 495 return req->misc.write.out.size;
477} 496}
@@ -508,7 +527,7 @@ static int fuse_buffered_write(struct file *file, struct inode *inode,
508 req->num_pages = 1; 527 req->num_pages = 1;
509 req->pages[0] = page; 528 req->pages[0] = page;
510 req->page_offset = offset; 529 req->page_offset = offset;
511 nres = fuse_send_write(req, file, inode, pos, count); 530 nres = fuse_send_write(req, file, inode, pos, count, NULL);
512 err = req->out.h.error; 531 err = req->out.h.error;
513 fuse_put_request(fc, req); 532 fuse_put_request(fc, req);
514 if (!err && !nres) 533 if (!err && !nres)
@@ -609,9 +628,11 @@ static ssize_t fuse_direct_io(struct file *file, const char __user *buf,
609 nbytes = (req->num_pages << PAGE_SHIFT) - req->page_offset; 628 nbytes = (req->num_pages << PAGE_SHIFT) - req->page_offset;
610 nbytes = min(count, nbytes); 629 nbytes = min(count, nbytes);
611 if (write) 630 if (write)
612 nres = fuse_send_write(req, file, inode, pos, nbytes); 631 nres = fuse_send_write(req, file, inode, pos, nbytes,
632 current->files);
613 else 633 else
614 nres = fuse_send_read(req, file, inode, pos, nbytes); 634 nres = fuse_send_read(req, file, inode, pos, nbytes,
635 current->files);
615 fuse_release_user_pages(req, !write); 636 fuse_release_user_pages(req, !write);
616 if (req->out.h.error) { 637 if (req->out.h.error) {
617 if (!res) 638 if (!res)
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 8b64a630e758..6c5461de1a5f 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -591,3 +591,5 @@ int fuse_valid_type(int m);
591 * Is task allowed to perform filesystem operation? 591 * Is task allowed to perform filesystem operation?
592 */ 592 */
593int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task); 593int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task);
594
595u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id);