diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/fuse.c | 44 | ||||
-rw-r--r-- | lib/fuse_i.h | 3 | ||||
-rw-r--r-- | lib/fuse_lowlevel.c | 52 | ||||
-rw-r--r-- | lib/modules/iconv.c | 13 | ||||
-rw-r--r-- | lib/modules/subdir.c | 13 |
5 files changed, 117 insertions, 8 deletions
@@ -1933,6 +1933,27 @@ int fuse_fs_lock(struct fuse_fs *fs, const char *path, } } +int fuse_fs_flock(struct fuse_fs *fs, const char *path, + struct fuse_file_info *fi, int op) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.flock) { + if (fs->debug) { + int xop = op & ~LOCK_NB; + + fprintf(stderr, "lock[%llu] %s%s\n", + (unsigned long long) fi->fh, + xop == LOCK_SH ? "LOCK_SH" : + (xop == LOCK_EX ? "LOCK_EX" : + (xop == LOCK_UN ? "LOCK_UN" : "???")), + (op & LOCK_NB) ? "|LOCK_NB" : ""); + } + return fs->op.flock(path, fi, op); + } else { + return -ENOSYS; + } +} + int fuse_fs_chown(struct fuse_fs *fs, const char *path, uid_t uid, gid_t gid) { fuse_get_context()->private_data = fs->user_data; @@ -2410,6 +2431,10 @@ void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn) fuse_get_context()->private_data = fs->user_data; if (!fs->op.write_buf) conn->want &= ~FUSE_CAP_SPLICE_READ; + if (!fs->op.lock) + conn->want &= ~FUSE_CAP_POSIX_LOCKS; + if (!fs->op.flock) + conn->want &= ~FUSE_CAP_FLOCK_LOCKS; if (fs->op.init) fs->user_data = fs->op.init(conn); } @@ -3754,6 +3779,24 @@ static void fuse_lib_setlk(fuse_req_t req, fuse_ino_t ino, reply_err(req, err); } +static void fuse_lib_flock(fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi, int op) +{ + struct fuse *f = req_fuse_prepare(req); + char *path; + int err; + + err = get_path_nullok(f, ino, &path); + if (err == 0) { + struct fuse_intr_data d; + fuse_prepare_interrupt(f, req, &d); + err = fuse_fs_flock(f->fs, path, fi, op); + fuse_finish_interrupt(f, req, &d); + free_path(f, ino, path); + } + reply_err(req, err); +} + static void fuse_lib_bmap(fuse_req_t req, fuse_ino_t ino, size_t blocksize, uint64_t idx) { @@ -3939,6 +3982,7 @@ static struct fuse_lowlevel_ops fuse_path_ops = { .removexattr = fuse_lib_removexattr, .getlk = fuse_lib_getlk, .setlk = fuse_lib_setlk, + .flock = fuse_lib_flock, .bmap = fuse_lib_bmap, .ioctl = fuse_lib_ioctl, .poll = fuse_lib_poll, diff --git a/lib/fuse_i.h b/lib/fuse_i.h index dd98737..78f1467 100644 --- a/lib/fuse_i.h +++ b/lib/fuse_i.h @@ -62,7 +62,8 @@ struct fuse_ll { int debug; int allow_root; int atomic_o_trunc; - int no_remote_lock; + int no_remote_posix_lock; + int no_remote_flock; int big_writes; int splice_write; int splice_move; diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c index 3cf747d..b101523 100644 --- a/lib/fuse_lowlevel.c +++ b/lib/fuse_lowlevel.c @@ -1322,6 +1322,10 @@ static void do_release(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) fi.flush = (arg->release_flags & FUSE_RELEASE_FLUSH) ? 1 : 0; fi.lock_owner = arg->lock_owner; } + if (arg->release_flags & FUSE_RELEASE_FLOCK_UNLOCK) { + fi.flock_release = 1; + fi.lock_owner = arg->lock_owner; + } if (req->f->op.release) req->f->op.release(req, nodeid, &fi); @@ -1505,11 +1509,34 @@ static void do_setlk_common(fuse_req_t req, fuse_ino_t nodeid, fi.fh = arg->fh; fi.lock_owner = arg->owner; - convert_fuse_file_lock(&arg->lk, &flock); - if (req->f->op.setlk) - req->f->op.setlk(req, nodeid, &fi, &flock, sleep); - else - fuse_reply_err(req, ENOSYS); + if (arg->lk_flags & FUSE_LK_FLOCK) { + int op = 0; + + switch (arg->lk.type) { + case F_RDLCK: + op = LOCK_SH; + break; + case F_WRLCK: + op = LOCK_EX; + break; + case F_UNLCK: + op = LOCK_UN; + break; + } + if (!sleep) + op |= LOCK_NB; + + if (req->f->op.flock) + req->f->op.flock(req, nodeid, &fi, op); + else + fuse_reply_err(req, ENOSYS); + } else { + convert_fuse_file_lock(&arg->lk, &flock); + if (req->f->op.setlk) + req->f->op.setlk(req, nodeid, &fi, &flock, sleep); + else + fuse_reply_err(req, ENOSYS); + } } static void do_setlk(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) @@ -1726,6 +1753,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) f->conn.capable |= FUSE_CAP_BIG_WRITES; if (arg->flags & FUSE_DONT_MASK) f->conn.capable |= FUSE_CAP_DONT_MASK; + if (arg->flags & FUSE_FLOCK_LOCKS) + f->conn.capable |= FUSE_CAP_FLOCK_LOCKS; } else { f->conn.async_read = 0; f->conn.max_readahead = 0; @@ -1748,8 +1777,10 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) if (f->atomic_o_trunc) f->conn.want |= FUSE_CAP_ATOMIC_O_TRUNC; - if (f->op.getlk && f->op.setlk && !f->no_remote_lock) + if (f->op.getlk && f->op.setlk && !f->no_remote_posix_lock) f->conn.want |= FUSE_CAP_POSIX_LOCKS; + if (f->op.flock && !f->no_remote_flock) + f->conn.want |= FUSE_CAP_FLOCK_LOCKS; if (f->big_writes) f->conn.want |= FUSE_CAP_BIG_WRITES; @@ -1786,6 +1817,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) outarg.flags |= FUSE_BIG_WRITES; if (f->conn.want & FUSE_CAP_DONT_MASK) outarg.flags |= FUSE_DONT_MASK; + if (f->conn.want & FUSE_CAP_FLOCK_LOCKS) + outarg.flags |= FUSE_FLOCK_LOCKS; outarg.max_readahead = f->conn.max_readahead; outarg.max_write = f->conn.max_write; if (f->conn.proto_minor >= 13) { @@ -2360,7 +2393,10 @@ static struct fuse_opt fuse_ll_opts[] = { { "async_read", offsetof(struct fuse_ll, conn.async_read), 1 }, { "sync_read", offsetof(struct fuse_ll, conn.async_read), 0 }, { "atomic_o_trunc", offsetof(struct fuse_ll, atomic_o_trunc), 1}, - { "no_remote_lock", offsetof(struct fuse_ll, no_remote_lock), 1}, + { "no_remote_lock", offsetof(struct fuse_ll, no_remote_posix_lock), 1}, + { "no_remote_lock", offsetof(struct fuse_ll, no_remote_flock), 1}, + { "no_remote_flock", offsetof(struct fuse_ll, no_remote_flock), 1}, + { "no_remote_posix_lock", offsetof(struct fuse_ll, no_remote_posix_lock), 1}, { "big_writes", offsetof(struct fuse_ll, big_writes), 1}, { "splice_write", offsetof(struct fuse_ll, splice_write), 1}, { "no_splice_write", offsetof(struct fuse_ll, no_splice_write), 1}, @@ -2394,6 +2430,8 @@ static void fuse_ll_help(void) " -o atomic_o_trunc enable atomic open+truncate support\n" " -o big_writes enable larger than 4kB writes\n" " -o no_remote_lock disable remote file locking\n" +" -o no_remote_flock disable remote file locking (BSD)\n" +" -o no_remote_posix_lock disable remove file locking (POSIX)\n" " -o [no_]splice_write use splice to write to the fuse device\n" " -o [no_]splice_move move data while splicing to the fuse device\n" " -o [no_]splice_read use splice to read from the fuse device\n" diff --git a/lib/modules/iconv.c b/lib/modules/iconv.c index b9946d9..1b78192 100644 --- a/lib/modules/iconv.c +++ b/lib/modules/iconv.c @@ -549,6 +549,18 @@ static int iconv_lock(const char *path, struct fuse_file_info *fi, int cmd, return err; } +static int iconv_flock(const char *path, struct fuse_file_info *fi, int op) +{ + struct iconv *ic = iconv_get(); + char *newpath; + int err = iconv_convpath(ic, path, &newpath, 0); + if (!err) { + err = fuse_fs_flock(ic->next, newpath, fi, op); + free(newpath); + } + return err; +} + static int iconv_bmap(const char *path, size_t blocksize, uint64_t *idx) { struct iconv *ic = iconv_get(); @@ -616,6 +628,7 @@ static struct fuse_operations iconv_oper = { .listxattr = iconv_listxattr, .removexattr = iconv_removexattr, .lock = iconv_lock, + .flock = iconv_flock, .bmap = iconv_bmap, .flag_nullpath_ok = 1, diff --git a/lib/modules/subdir.c b/lib/modules/subdir.c index 6d9ac89..24dede6 100644 --- a/lib/modules/subdir.c +++ b/lib/modules/subdir.c @@ -536,6 +536,18 @@ static int subdir_lock(const char *path, struct fuse_file_info *fi, int cmd, return err; } +static int subdir_flock(const char *path, struct fuse_file_info *fi, int op) +{ + struct subdir *d = subdir_get(); + char *newpath; + int err = subdir_addpath(d, path, &newpath); + if (!err) { + err = fuse_fs_flock(d->next, newpath, fi, op); + free(newpath); + } + return err; +} + static int subdir_bmap(const char *path, size_t blocksize, uint64_t *idx) { struct subdir *d = subdir_get(); @@ -599,6 +611,7 @@ static struct fuse_operations subdir_oper = { .listxattr = subdir_listxattr, .removexattr = subdir_removexattr, .lock = subdir_lock, + .flock = subdir_flock, .bmap = subdir_bmap, .flag_nullpath_ok = 1, |