diff options
author | Miklos Szeredi <mszeredi@suse.cz> | 2007-10-18 06:07:02 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-18 17:37:31 -0400 |
commit | a9ff4f87056cd31a8232b88d013dc6c9ad719c18 (patch) | |
tree | 8ddcc01ae8b6615a9a530fb51c52825b315ee266 | |
parent | 6ff958edbf39c014eb06b65ad25b736be08c4e63 (diff) |
fuse: support BSD locking semantics
It is trivial to add support for flock(2) semantics to the existing protocol,
by setting the lock owner field to the file pointer, and passing a new
FUSE_LK_FLOCK flag with the locking request.
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>
-rw-r--r-- | fs/fuse/file.c | 32 | ||||
-rw-r--r-- | include/linux/fuse.h | 8 |
2 files changed, 35 insertions, 5 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 6726378661da..471ea70be48d 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -699,7 +699,8 @@ static int convert_fuse_file_lock(const struct fuse_file_lock *ffl, | |||
699 | } | 699 | } |
700 | 700 | ||
701 | static void fuse_lk_fill(struct fuse_req *req, struct file *file, | 701 | static void fuse_lk_fill(struct fuse_req *req, struct file *file, |
702 | const struct file_lock *fl, int opcode, pid_t pid) | 702 | const struct file_lock *fl, int opcode, pid_t pid, |
703 | int flock) | ||
703 | { | 704 | { |
704 | struct inode *inode = file->f_path.dentry->d_inode; | 705 | struct inode *inode = file->f_path.dentry->d_inode; |
705 | struct fuse_conn *fc = get_fuse_conn(inode); | 706 | struct fuse_conn *fc = get_fuse_conn(inode); |
@@ -712,6 +713,8 @@ static void fuse_lk_fill(struct fuse_req *req, struct file *file, | |||
712 | arg->lk.end = fl->fl_end; | 713 | arg->lk.end = fl->fl_end; |
713 | arg->lk.type = fl->fl_type; | 714 | arg->lk.type = fl->fl_type; |
714 | arg->lk.pid = pid; | 715 | arg->lk.pid = pid; |
716 | if (flock) | ||
717 | arg->lk_flags |= FUSE_LK_FLOCK; | ||
715 | req->in.h.opcode = opcode; | 718 | req->in.h.opcode = opcode; |
716 | req->in.h.nodeid = get_node_id(inode); | 719 | req->in.h.nodeid = get_node_id(inode); |
717 | req->in.numargs = 1; | 720 | req->in.numargs = 1; |
@@ -731,7 +734,7 @@ static int fuse_getlk(struct file *file, struct file_lock *fl) | |||
731 | if (IS_ERR(req)) | 734 | if (IS_ERR(req)) |
732 | return PTR_ERR(req); | 735 | return PTR_ERR(req); |
733 | 736 | ||
734 | fuse_lk_fill(req, file, fl, FUSE_GETLK, 0); | 737 | fuse_lk_fill(req, file, fl, FUSE_GETLK, 0, 0); |
735 | req->out.numargs = 1; | 738 | req->out.numargs = 1; |
736 | req->out.args[0].size = sizeof(outarg); | 739 | req->out.args[0].size = sizeof(outarg); |
737 | req->out.args[0].value = &outarg; | 740 | req->out.args[0].value = &outarg; |
@@ -744,7 +747,7 @@ static int fuse_getlk(struct file *file, struct file_lock *fl) | |||
744 | return err; | 747 | return err; |
745 | } | 748 | } |
746 | 749 | ||
747 | static int fuse_setlk(struct file *file, struct file_lock *fl) | 750 | static int fuse_setlk(struct file *file, struct file_lock *fl, int flock) |
748 | { | 751 | { |
749 | struct inode *inode = file->f_path.dentry->d_inode; | 752 | struct inode *inode = file->f_path.dentry->d_inode; |
750 | struct fuse_conn *fc = get_fuse_conn(inode); | 753 | struct fuse_conn *fc = get_fuse_conn(inode); |
@@ -761,7 +764,7 @@ static int fuse_setlk(struct file *file, struct file_lock *fl) | |||
761 | if (IS_ERR(req)) | 764 | if (IS_ERR(req)) |
762 | return PTR_ERR(req); | 765 | return PTR_ERR(req); |
763 | 766 | ||
764 | fuse_lk_fill(req, file, fl, opcode, pid); | 767 | fuse_lk_fill(req, file, fl, opcode, pid, flock); |
765 | request_send(fc, req); | 768 | request_send(fc, req); |
766 | err = req->out.h.error; | 769 | err = req->out.h.error; |
767 | /* locking is restartable */ | 770 | /* locking is restartable */ |
@@ -787,11 +790,28 @@ static int fuse_file_lock(struct file *file, int cmd, struct file_lock *fl) | |||
787 | if (fc->no_lock) | 790 | if (fc->no_lock) |
788 | err = posix_lock_file_wait(file, fl); | 791 | err = posix_lock_file_wait(file, fl); |
789 | else | 792 | else |
790 | err = fuse_setlk(file, fl); | 793 | err = fuse_setlk(file, fl, 0); |
791 | } | 794 | } |
792 | return err; | 795 | return err; |
793 | } | 796 | } |
794 | 797 | ||
798 | static int fuse_file_flock(struct file *file, int cmd, struct file_lock *fl) | ||
799 | { | ||
800 | struct inode *inode = file->f_path.dentry->d_inode; | ||
801 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
802 | int err; | ||
803 | |||
804 | if (fc->no_lock) { | ||
805 | err = flock_lock_file_wait(file, fl); | ||
806 | } else { | ||
807 | /* emulate flock with POSIX locks */ | ||
808 | fl->fl_owner = (fl_owner_t) file; | ||
809 | err = fuse_setlk(file, fl, 1); | ||
810 | } | ||
811 | |||
812 | return err; | ||
813 | } | ||
814 | |||
795 | static sector_t fuse_bmap(struct address_space *mapping, sector_t block) | 815 | static sector_t fuse_bmap(struct address_space *mapping, sector_t block) |
796 | { | 816 | { |
797 | struct inode *inode = mapping->host; | 817 | struct inode *inode = mapping->host; |
@@ -840,6 +860,7 @@ static const struct file_operations fuse_file_operations = { | |||
840 | .release = fuse_release, | 860 | .release = fuse_release, |
841 | .fsync = fuse_fsync, | 861 | .fsync = fuse_fsync, |
842 | .lock = fuse_file_lock, | 862 | .lock = fuse_file_lock, |
863 | .flock = fuse_file_flock, | ||
843 | .splice_read = generic_file_splice_read, | 864 | .splice_read = generic_file_splice_read, |
844 | }; | 865 | }; |
845 | 866 | ||
@@ -852,6 +873,7 @@ static const struct file_operations fuse_direct_io_file_operations = { | |||
852 | .release = fuse_release, | 873 | .release = fuse_release, |
853 | .fsync = fuse_fsync, | 874 | .fsync = fuse_fsync, |
854 | .lock = fuse_file_lock, | 875 | .lock = fuse_file_lock, |
876 | .flock = fuse_file_flock, | ||
855 | /* no mmap and splice_read */ | 877 | /* no mmap and splice_read */ |
856 | }; | 878 | }; |
857 | 879 | ||
diff --git a/include/linux/fuse.h b/include/linux/fuse.h index 436047093bc4..015a8b15a388 100644 --- a/include/linux/fuse.h +++ b/include/linux/fuse.h | |||
@@ -13,6 +13,7 @@ | |||
13 | * | 13 | * |
14 | * 7.9: | 14 | * 7.9: |
15 | * - new fuse_getattr_in input argument of GETATTR | 15 | * - new fuse_getattr_in input argument of GETATTR |
16 | * - add lk_flags in fuse_lk_in | ||
16 | */ | 17 | */ |
17 | 18 | ||
18 | #include <asm/types.h> | 19 | #include <asm/types.h> |
@@ -113,6 +114,11 @@ struct fuse_file_lock { | |||
113 | */ | 114 | */ |
114 | #define FUSE_GETATTR_FH (1 << 0) | 115 | #define FUSE_GETATTR_FH (1 << 0) |
115 | 116 | ||
117 | /** | ||
118 | * Lock flags | ||
119 | */ | ||
120 | #define FUSE_LK_FLOCK (1 << 0) | ||
121 | |||
116 | enum fuse_opcode { | 122 | enum fuse_opcode { |
117 | FUSE_LOOKUP = 1, | 123 | FUSE_LOOKUP = 1, |
118 | FUSE_FORGET = 2, /* no reply */ | 124 | FUSE_FORGET = 2, /* no reply */ |
@@ -295,6 +301,8 @@ struct fuse_lk_in { | |||
295 | __u64 fh; | 301 | __u64 fh; |
296 | __u64 owner; | 302 | __u64 owner; |
297 | struct fuse_file_lock lk; | 303 | struct fuse_file_lock lk; |
304 | __u32 lk_flags; | ||
305 | __u32 padding; | ||
298 | }; | 306 | }; |
299 | 307 | ||
300 | struct fuse_lk_out { | 308 | struct fuse_lk_out { |