Commit a9ff4f87 authored by Miklos Szeredi's avatar Miklos Szeredi Committed by Linus Torvalds

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: default avatarMiklos Szeredi <mszeredi@suse.cz>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 6ff958ed
...@@ -699,7 +699,8 @@ static int convert_fuse_file_lock(const struct fuse_file_lock *ffl, ...@@ -699,7 +699,8 @@ static int convert_fuse_file_lock(const struct fuse_file_lock *ffl,
} }
static void fuse_lk_fill(struct fuse_req *req, struct file *file, static void fuse_lk_fill(struct fuse_req *req, struct file *file,
const struct file_lock *fl, int opcode, pid_t pid) const struct file_lock *fl, int opcode, pid_t pid,
int flock)
{ {
struct inode *inode = file->f_path.dentry->d_inode; struct inode *inode = file->f_path.dentry->d_inode;
struct fuse_conn *fc = get_fuse_conn(inode); 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,6 +713,8 @@ static void fuse_lk_fill(struct fuse_req *req, struct file *file,
arg->lk.end = fl->fl_end; arg->lk.end = fl->fl_end;
arg->lk.type = fl->fl_type; arg->lk.type = fl->fl_type;
arg->lk.pid = pid; arg->lk.pid = pid;
if (flock)
arg->lk_flags |= FUSE_LK_FLOCK;
req->in.h.opcode = opcode; req->in.h.opcode = opcode;
req->in.h.nodeid = get_node_id(inode); req->in.h.nodeid = get_node_id(inode);
req->in.numargs = 1; req->in.numargs = 1;
...@@ -731,7 +734,7 @@ static int fuse_getlk(struct file *file, struct file_lock *fl) ...@@ -731,7 +734,7 @@ static int fuse_getlk(struct file *file, struct file_lock *fl)
if (IS_ERR(req)) if (IS_ERR(req))
return PTR_ERR(req); return PTR_ERR(req);
fuse_lk_fill(req, file, fl, FUSE_GETLK, 0); fuse_lk_fill(req, file, fl, FUSE_GETLK, 0, 0);
req->out.numargs = 1; req->out.numargs = 1;
req->out.args[0].size = sizeof(outarg); req->out.args[0].size = sizeof(outarg);
req->out.args[0].value = &outarg; req->out.args[0].value = &outarg;
...@@ -744,7 +747,7 @@ static int fuse_getlk(struct file *file, struct file_lock *fl) ...@@ -744,7 +747,7 @@ static int fuse_getlk(struct file *file, struct file_lock *fl)
return err; return err;
} }
static int fuse_setlk(struct file *file, struct file_lock *fl) static int fuse_setlk(struct file *file, struct file_lock *fl, int flock)
{ {
struct inode *inode = file->f_path.dentry->d_inode; struct inode *inode = file->f_path.dentry->d_inode;
struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_conn *fc = get_fuse_conn(inode);
...@@ -761,7 +764,7 @@ static int fuse_setlk(struct file *file, struct file_lock *fl) ...@@ -761,7 +764,7 @@ static int fuse_setlk(struct file *file, struct file_lock *fl)
if (IS_ERR(req)) if (IS_ERR(req))
return PTR_ERR(req); return PTR_ERR(req);
fuse_lk_fill(req, file, fl, opcode, pid); fuse_lk_fill(req, file, fl, opcode, pid, flock);
request_send(fc, req); request_send(fc, req);
err = req->out.h.error; err = req->out.h.error;
/* locking is restartable */ /* locking is restartable */
...@@ -787,11 +790,28 @@ static int fuse_file_lock(struct file *file, int cmd, struct file_lock *fl) ...@@ -787,11 +790,28 @@ static int fuse_file_lock(struct file *file, int cmd, struct file_lock *fl)
if (fc->no_lock) if (fc->no_lock)
err = posix_lock_file_wait(file, fl); err = posix_lock_file_wait(file, fl);
else else
err = fuse_setlk(file, fl); err = fuse_setlk(file, fl, 0);
} }
return err; return err;
} }
static int fuse_file_flock(struct file *file, int cmd, struct file_lock *fl)
{
struct inode *inode = file->f_path.dentry->d_inode;
struct fuse_conn *fc = get_fuse_conn(inode);
int err;
if (fc->no_lock) {
err = flock_lock_file_wait(file, fl);
} else {
/* emulate flock with POSIX locks */
fl->fl_owner = (fl_owner_t) file;
err = fuse_setlk(file, fl, 1);
}
return err;
}
static sector_t fuse_bmap(struct address_space *mapping, sector_t block) static sector_t fuse_bmap(struct address_space *mapping, sector_t block)
{ {
struct inode *inode = mapping->host; struct inode *inode = mapping->host;
...@@ -840,6 +860,7 @@ static const struct file_operations fuse_file_operations = { ...@@ -840,6 +860,7 @@ static const struct file_operations fuse_file_operations = {
.release = fuse_release, .release = fuse_release,
.fsync = fuse_fsync, .fsync = fuse_fsync,
.lock = fuse_file_lock, .lock = fuse_file_lock,
.flock = fuse_file_flock,
.splice_read = generic_file_splice_read, .splice_read = generic_file_splice_read,
}; };
...@@ -852,6 +873,7 @@ static const struct file_operations fuse_direct_io_file_operations = { ...@@ -852,6 +873,7 @@ static const struct file_operations fuse_direct_io_file_operations = {
.release = fuse_release, .release = fuse_release,
.fsync = fuse_fsync, .fsync = fuse_fsync,
.lock = fuse_file_lock, .lock = fuse_file_lock,
.flock = fuse_file_flock,
/* no mmap and splice_read */ /* no mmap and splice_read */
}; };
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
* *
* 7.9: * 7.9:
* - new fuse_getattr_in input argument of GETATTR * - new fuse_getattr_in input argument of GETATTR
* - add lk_flags in fuse_lk_in
*/ */
#include <asm/types.h> #include <asm/types.h>
...@@ -113,6 +114,11 @@ struct fuse_file_lock { ...@@ -113,6 +114,11 @@ struct fuse_file_lock {
*/ */
#define FUSE_GETATTR_FH (1 << 0) #define FUSE_GETATTR_FH (1 << 0)
/**
* Lock flags
*/
#define FUSE_LK_FLOCK (1 << 0)
enum fuse_opcode { enum fuse_opcode {
FUSE_LOOKUP = 1, FUSE_LOOKUP = 1,
FUSE_FORGET = 2, /* no reply */ FUSE_FORGET = 2, /* no reply */
...@@ -295,6 +301,8 @@ struct fuse_lk_in { ...@@ -295,6 +301,8 @@ struct fuse_lk_in {
__u64 fh; __u64 fh;
__u64 owner; __u64 owner;
struct fuse_file_lock lk; struct fuse_file_lock lk;
__u32 lk_flags;
__u32 padding;
}; };
struct fuse_lk_out { struct fuse_lk_out {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment