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 /fs/fuse/file.c | |
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>
Diffstat (limited to 'fs/fuse/file.c')
-rw-r--r-- | fs/fuse/file.c | 32 |
1 files changed, 27 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 | ||