Skip to content

Commit

Permalink
fuse: support BSD locking semantics
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Miklos Szeredi authored and Linus Torvalds committed Oct 18, 2007
1 parent 6ff958e commit a9ff4f8
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 5 deletions.
32 changes: 27 additions & 5 deletions fs/fuse/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
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 fuse_conn *fc = get_fuse_conn(inode);
Expand All @@ -712,6 +713,8 @@ static void fuse_lk_fill(struct fuse_req *req, struct file *file,
arg->lk.end = fl->fl_end;
arg->lk.type = fl->fl_type;
arg->lk.pid = pid;
if (flock)
arg->lk_flags |= FUSE_LK_FLOCK;
req->in.h.opcode = opcode;
req->in.h.nodeid = get_node_id(inode);
req->in.numargs = 1;
Expand All @@ -731,7 +734,7 @@ static int fuse_getlk(struct file *file, struct file_lock *fl)
if (IS_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.args[0].size = sizeof(outarg);
req->out.args[0].value = &outarg;
Expand All @@ -744,7 +747,7 @@ static int fuse_getlk(struct file *file, struct file_lock *fl)
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 fuse_conn *fc = get_fuse_conn(inode);
Expand All @@ -761,7 +764,7 @@ static int fuse_setlk(struct file *file, struct file_lock *fl)
if (IS_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);
err = req->out.h.error;
/* locking is restartable */
Expand All @@ -787,11 +790,28 @@ static int fuse_file_lock(struct file *file, int cmd, struct file_lock *fl)
if (fc->no_lock)
err = posix_lock_file_wait(file, fl);
else
err = fuse_setlk(file, fl);
err = fuse_setlk(file, fl, 0);
}
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)
{
struct inode *inode = mapping->host;
Expand Down Expand Up @@ -840,6 +860,7 @@ static const struct file_operations fuse_file_operations = {
.release = fuse_release,
.fsync = fuse_fsync,
.lock = fuse_file_lock,
.flock = fuse_file_flock,
.splice_read = generic_file_splice_read,
};

Expand All @@ -852,6 +873,7 @@ static const struct file_operations fuse_direct_io_file_operations = {
.release = fuse_release,
.fsync = fuse_fsync,
.lock = fuse_file_lock,
.flock = fuse_file_flock,
/* no mmap and splice_read */
};

Expand Down
8 changes: 8 additions & 0 deletions include/linux/fuse.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
*
* 7.9:
* - new fuse_getattr_in input argument of GETATTR
* - add lk_flags in fuse_lk_in
*/

#include <asm/types.h>
Expand Down Expand Up @@ -113,6 +114,11 @@ struct fuse_file_lock {
*/
#define FUSE_GETATTR_FH (1 << 0)

/**
* Lock flags
*/
#define FUSE_LK_FLOCK (1 << 0)

enum fuse_opcode {
FUSE_LOOKUP = 1,
FUSE_FORGET = 2, /* no reply */
Expand Down Expand Up @@ -295,6 +301,8 @@ struct fuse_lk_in {
__u64 fh;
__u64 owner;
struct fuse_file_lock lk;
__u32 lk_flags;
__u32 padding;
};

struct fuse_lk_out {
Expand Down

0 comments on commit a9ff4f8

Please sign in to comment.