diff options
Diffstat (limited to 'fs/fuse')
-rw-r--r-- | fs/fuse/dir.c | 5 | ||||
-rw-r--r-- | fs/fuse/file.c | 37 | ||||
-rw-r--r-- | fs/fuse/fuse_i.h | 2 |
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 | */ |
192 | static u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id) | 192 | u64 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 | ||
310 | static size_t fuse_send_read(struct fuse_req *req, struct file *file, | 310 | static 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 | ||
470 | static size_t fuse_send_write(struct fuse_req *req, struct file *file, | 483 | static 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 | */ |
593 | int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task); | 593 | int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task); |
594 | |||
595 | u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id); | ||