aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorGravatar Miklos Szeredi <miklos@szeredi.hu>2009-07-02 12:26:36 +0000
committerGravatar Miklos Szeredi <miklos@szeredi.hu>2009-07-02 12:26:36 +0000
commit24b35c3d97ffdbf0a1f8e8b4e94ed892343603a6 (patch)
tree0ebcdf18f18a07ab444c4707f8091b615fd23171 /lib
parent5bd3ba41e55e8c52e04d730d1e8a924b23b21591 (diff)
* The context is extended with a 'umask' field. The umask is sent
for mknod, mkdir and create requests by linux kernel version 2.6.31 or later, otherwise the umask is set to zero. Also introduce a new feature flag: FUSE_CAP_DONT_MASK. If the kernel supports this feature, then this flag will be set in conn->capable in the ->init() method. If the filesystem sets this flag in in conn->want, then the create modes will not be masked. * Add low level interfaces for lookup cache and attribute invalidation. This feature is available in linux kernels 2.6.31 or later. Patch by John Muir * Kernel interface version is now 7.12
Diffstat (limited to 'lib')
-rw-r--r--lib/fuse.c15
-rw-r--r--lib/fuse_lowlevel.c88
-rw-r--r--lib/fuse_session.c5
-rw-r--r--lib/fuse_versionscript6
4 files changed, 104 insertions, 10 deletions
diff --git a/lib/fuse.c b/lib/fuse.c
index dad9a71..68cb603 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -1422,8 +1422,10 @@ int fuse_fs_create(struct fuse_fs *fs, const char *path, mode_t mode,
int err;
if (fs->debug)
- fprintf(stderr, "create flags: 0x%x %s\n", fi->flags,
- path);
+ fprintf(stderr,
+ "create flags: 0x%x %s 0%o umask=0%03o\n",
+ fi->flags, path, mode,
+ fuse_get_context()->umask);
err = fs->op.create(path, mode, fi);
@@ -1572,8 +1574,9 @@ int fuse_fs_mknod(struct fuse_fs *fs, const char *path, mode_t mode,
fuse_get_context()->private_data = fs->user_data;
if (fs->op.mknod) {
if (fs->debug)
- fprintf(stderr, "mknod %s 0%o 0x%llx\n", path,
- mode, (unsigned long long) rdev);
+ fprintf(stderr, "mknod %s 0%o 0x%llx umask=0%03o\n",
+ path, mode, (unsigned long long) rdev,
+ fuse_get_context()->umask);
return fs->op.mknod(path, mode, rdev);
} else {
@@ -1586,7 +1589,8 @@ int fuse_fs_mkdir(struct fuse_fs *fs, const char *path, mode_t mode)
fuse_get_context()->private_data = fs->user_data;
if (fs->op.mkdir) {
if (fs->debug)
- fprintf(stderr, "mkdir %s 0%o\n", path, mode);
+ fprintf(stderr, "mkdir %s 0%o umask=0%03o\n",
+ path, mode, fuse_get_context()->umask);
return fs->op.mkdir(path, mode);
} else {
@@ -1909,6 +1913,7 @@ static struct fuse *req_fuse_prepare(fuse_req_t req)
c->ctx.uid = ctx->uid;
c->ctx.gid = ctx->gid;
c->ctx.pid = ctx->pid;
+ c->ctx.umask = ctx->umask;
return c->ctx.fuse;
}
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
index 89e8f2f..32b9db3 100644
--- a/lib/fuse_lowlevel.c
+++ b/lib/fuse_lowlevel.c
@@ -606,9 +606,15 @@ static void do_readlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
static void do_mknod(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
{
struct fuse_mknod_in *arg = (struct fuse_mknod_in *) inarg;
+ char *name = PARAM(arg);
+
+ if (req->f->conn.proto_minor >= 12)
+ req->ctx.umask = arg->umask;
+ else
+ name = (char *) inarg + FUSE_COMPAT_MKNOD_IN_SIZE;
if (req->f->op.mknod)
- req->f->op.mknod(req, nodeid, PARAM(arg), arg->mode, arg->rdev);
+ req->f->op.mknod(req, nodeid, name, arg->mode, arg->rdev);
else
fuse_reply_err(req, ENOSYS);
}
@@ -617,6 +623,9 @@ static void do_mkdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
{
struct fuse_mkdir_in *arg = (struct fuse_mkdir_in *) inarg;
+ if (req->f->conn.proto_minor >= 12)
+ req->ctx.umask = arg->umask;
+
if (req->f->op.mkdir)
req->f->op.mkdir(req, nodeid, PARAM(arg), arg->mode);
else
@@ -678,15 +687,21 @@ static void do_link(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
static void do_create(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
{
- struct fuse_open_in *arg = (struct fuse_open_in *) inarg;
+ struct fuse_create_in *arg = (struct fuse_create_in *) inarg;
if (req->f->op.create) {
struct fuse_file_info fi;
+ char *name = PARAM(arg);
memset(&fi, 0, sizeof(fi));
fi.flags = arg->flags;
- req->f->op.create(req, nodeid, PARAM(arg), arg->mode, &fi);
+ if (req->f->conn.proto_minor >= 12)
+ req->ctx.umask = arg->umask;
+ else
+ name = (char *) inarg + sizeof(struct fuse_open_in);
+
+ req->f->op.create(req, nodeid, name, arg->mode, &fi);
} else
fuse_reply_err(req, ENOSYS);
}
@@ -1168,6 +1183,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
f->conn.capable |= FUSE_CAP_EXPORT_SUPPORT;
if (arg->flags & FUSE_BIG_WRITES)
f->conn.capable |= FUSE_CAP_BIG_WRITES;
+ if (arg->flags & FUSE_DONT_MASK)
+ f->conn.capable |= FUSE_CAP_DONT_MASK;
} else {
f->conn.async_read = 0;
f->conn.max_readahead = 0;
@@ -1207,6 +1224,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
outarg.flags |= FUSE_EXPORT_SUPPORT;
if (f->conn.want & FUSE_CAP_BIG_WRITES)
outarg.flags |= FUSE_BIG_WRITES;
+ if (f->conn.want & FUSE_CAP_DONT_MASK)
+ outarg.flags |= FUSE_DONT_MASK;
outarg.max_readahead = f->conn.max_readahead;
outarg.max_write = f->conn.max_write;
@@ -1270,6 +1289,56 @@ int fuse_lowlevel_notify_poll(struct fuse_pollhandle *ph)
}
}
+int fuse_lowlevel_notify_inval_inode(struct fuse_chan *ch, fuse_ino_t ino,
+ off_t off, off_t len)
+{
+ struct fuse_notify_inval_inode_out outarg;
+ struct fuse_ll *f;
+ struct iovec iov[2];
+
+ if (!ch)
+ return -EINVAL;
+
+ f = (struct fuse_ll *)fuse_session_data(fuse_chan_session(ch));
+ if (!f)
+ return -ENODEV;
+
+ outarg.ino = ino;
+ outarg.off = off;
+ outarg.len = len;
+
+ iov[1].iov_base = &outarg;
+ iov[1].iov_len = sizeof(outarg);
+
+ return send_notify_iov(f, ch, FUSE_NOTIFY_INVAL_INODE, iov, 2);
+}
+
+int fuse_lowlevel_notify_inval_entry(struct fuse_chan *ch, fuse_ino_t parent,
+ const char *name, size_t namelen)
+{
+ struct fuse_notify_inval_entry_out outarg;
+ struct fuse_ll *f;
+ struct iovec iov[3];
+
+ if (!ch)
+ return -EINVAL;
+
+ f = (struct fuse_ll *)fuse_session_data(fuse_chan_session(ch));
+ if (!f)
+ return -ENODEV;
+
+ outarg.parent = parent;
+ outarg.namelen = namelen;
+ outarg.padding = 0;
+
+ iov[1].iov_base = &outarg;
+ iov[1].iov_len = sizeof(outarg);
+ iov[2].iov_base = (void *)name;
+ iov[2].iov_len = namelen + 1;
+
+ return send_notify_iov(f, ch, FUSE_NOTIFY_INVAL_ENTRY, iov, 3);
+}
+
void *fuse_req_userdata(fuse_req_t req)
{
return req->f->userdata;
@@ -1280,6 +1349,19 @@ const struct fuse_ctx *fuse_req_ctx(fuse_req_t req)
return &req->ctx;
}
+/*
+ * The size of fuse_ctx got extended, so need to be careful about
+ * incompatibility (i.e. a new binary cannot work with an old
+ * library).
+ */
+const struct fuse_ctx *fuse_req_ctx_compat24(fuse_req_t req);
+const struct fuse_ctx *fuse_req_ctx_compat24(fuse_req_t req)
+{
+ return fuse_req_ctx(req);
+}
+FUSE_SYMVER(".symver fuse_req_ctx_compat24,fuse_req_ctx@FUSE_2.4");
+
+
void fuse_req_interrupt_func(fuse_req_t req, fuse_interrupt_func_t func,
void *data)
{
diff --git a/lib/fuse_session.c b/lib/fuse_session.c
index 7df4795..3758627 100644
--- a/lib/fuse_session.c
+++ b/lib/fuse_session.c
@@ -111,6 +111,11 @@ int fuse_session_exited(struct fuse_session *se)
return se->exited;
}
+void *fuse_session_data(struct fuse_session *se)
+{
+ return se->data;
+}
+
static struct fuse_chan *fuse_chan_new_common(struct fuse_chan_ops *op, int fd,
size_t bufsize, void *data,
int compat)
diff --git a/lib/fuse_versionscript b/lib/fuse_versionscript
index 463c74f..4ab0291 100644
--- a/lib/fuse_versionscript
+++ b/lib/fuse_versionscript
@@ -3,7 +3,6 @@ FUSE_2.2 {
fuse_destroy;
fuse_exit;
fuse_exited;
- fuse_get_context;
fuse_invalidate;
fuse_is_lib_option;
fuse_loop;
@@ -43,7 +42,6 @@ FUSE_2.4 {
fuse_reply_readlink;
fuse_reply_write;
fuse_reply_xattr;
- fuse_req_ctx;
fuse_req_userdata;
fuse_session_add_chan;
fuse_session_destroy;
@@ -176,6 +174,10 @@ FUSE_2.8 {
fuse_reply_poll;
fuse_req_getgroups;
fuse_getgroups;
+ fuse_req_ctx;
+ fuse_get_context;
+ fuse_lowlevel_notify_inval_inode;
+ fuse_lowlevel_notify_inval_entry;
local:
*;