aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Miklos Szeredi <miklos@szeredi.hu>2004-12-01 18:39:12 +0000
committerGravatar Miklos Szeredi <miklos@szeredi.hu>2004-12-01 18:39:12 +0000
commit039322d8f1295bf20057303882bf1202a03d125e (patch)
tree67d8e3b3a3daf2d55705eaa4ab88a3042b317190
parent83a074415d72e5dae0a7836fbe1f8b6b8cd3a098 (diff)
cleanup
-rw-r--r--ChangeLog6
-rwxr-xr-xkernel/cleanup.sh2
-rw-r--r--kernel/configure.ac11
-rw-r--r--kernel/dev.c179
-rw-r--r--kernel/dir.c123
-rw-r--r--kernel/file.c454
-rw-r--r--kernel/fuse_i.h59
-rw-r--r--kernel/inode.c28
8 files changed, 399 insertions, 463 deletions
diff --git a/ChangeLog b/ChangeLog
index 441669b..63f8b58 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2004-12-01 Miklos Szeredi <miklos@szeredi.hu>
+
+ * kernel: clean up writing functions
+
+ * kernel: no allocation on write in direct_io mode
+
2004-11-30 Miklos Szeredi <miklos@szeredi.hu>
* kernel: clean up reading functions
diff --git a/kernel/cleanup.sh b/kernel/cleanup.sh
index 6255cb2..fb0807e 100755
--- a/kernel/cleanup.sh
+++ b/kernel/cleanup.sh
@@ -12,5 +12,5 @@ if test "$destdir" = "."; then
fi
for f in dev.c dir.c file.c inode.c util.c fuse_i.h; do
- unifdef -DKERNEL_2_6 -DKERNEL_2_6_6_PLUS -DKERNEL_2_6_10_PLUS -DHAVE_KERNEL_XATTR -DFS_SAFE -DMAX_LFS_FILESIZE -DFUSE_MAINLINE -DBUG_ON -D__user -DMODULE_LICENSE $f > $destdir/$f
+ unifdef -DKERNEL_2_6 -DKERNEL_2_6_6_PLUS -DKERNEL_2_6_10_PLUS -DHAVE_KERNEL_XATTR -DFS_SAFE -DMAX_LFS_FILESIZE -DFUSE_MAINLINE -DBUG_ON -DHAVE_FS_SUBSYS -D__user -DMODULE_LICENSE $f > $destdir/$f
done
diff --git a/kernel/configure.ac b/kernel/configure.ac
index 3b06f46..f078427 100644
--- a/kernel/configure.ac
+++ b/kernel/configure.ac
@@ -49,9 +49,18 @@ if echo "$kernsrcver" | grep -q "^2.4"; then
[#include <linux/fs.h>])
CFLAGS="$old_cflags"
fi
+
+AC_MSG_CHECKING([whether fs_subsys is declared])
+if grep -q fs_subsys $kernelsrc/include/linux/fs.h; then
+ AC_DEFINE(HAVE_FS_SUBSYS, 1, [Kernel defines fs_subsys])
+ AC_MSG_RESULT([yes])
+else
+ AC_MSG_RESULT([no])
+fi
+
AC_MSG_CHECKING([if kernel has extended attribute support])
if test -f $kernelsrc/include/linux/xattr.h; then
- AC_DEFINE(HAVE_KERNEL_XATTR, 1, [Kernel has xattr support],,)
+ AC_DEFINE(HAVE_KERNEL_XATTR, 1, [Kernel has xattr support])
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
diff --git a/kernel/dev.c b/kernel/dev.c
index aca602f..70a0013 100644
--- a/kernel/dev.c
+++ b/kernel/dev.c
@@ -205,39 +205,74 @@ static void request_wait(struct fuse_conn *fc)
remove_wait_queue(&fc->waitq, &wait);
}
-static inline int copy_in_one(const void *src, size_t srclen,
- char __user **dstp, size_t *dstlenp)
+static inline int copy_in_page(char __user *buf, struct page *page,
+ unsigned offset, unsigned count)
{
- if (*dstlenp < srclen) {
+ char *tmpbuf = kmap(page);
+ int err = copy_to_user(buf, tmpbuf + offset, count);
+ kunmap(page);
+ return err;
+}
+
+static int copy_in_pages(struct fuse_req *req, size_t nbytes, char __user *buf)
+{
+ unsigned i;
+ unsigned offset = req->page_offset;
+ unsigned count = min(nbytes, (unsigned) PAGE_SIZE - offset);
+ for (i = 0; i < req->num_pages && nbytes; i++) {
+ struct page *page = req->pages[i];
+ if (page && copy_in_page(buf, page, offset, count))
+ return -EFAULT;
+ nbytes -= count;
+ buf += count;
+ count = min(nbytes, (unsigned) PAGE_SIZE);
+ offset = 0;
+ }
+ return 0;
+}
+
+static inline int copy_in_one(struct fuse_req *req, size_t argsize,
+ const void *val, int islast, char __user *buf,
+ size_t nbytes)
+{
+ if (nbytes < argsize) {
printk("fuse_dev_read: buffer too small\n");
return -EINVAL;
}
-
- if (srclen && copy_to_user(*dstp, src, srclen))
+ if (islast && req->in.argpages)
+ return copy_in_pages(req, argsize, buf);
+ else if (argsize && copy_to_user(buf, val, argsize))
return -EFAULT;
-
- *dstp += srclen;
- *dstlenp -= srclen;
-
- return 0;
+ else
+ return 0;
}
-static inline int copy_in_args(struct fuse_in *in, char __user *buf,
- size_t nbytes)
+static int copy_in_args(struct fuse_req *req, char __user *buf, size_t nbytes)
{
- int err;
int i;
+ int err;
+ struct fuse_in *in = &req->in;
size_t orignbytes = nbytes;
-
- err = copy_in_one(&in->h, sizeof(in->h), &buf, &nbytes);
+ unsigned argsize;
+
+ argsize = sizeof(in->h);
+ err = copy_in_one(req, argsize, &in->h, 0, buf, nbytes);
if (err)
return err;
+ buf += argsize;
+ nbytes -= argsize;
+
for (i = 0; i < in->numargs; i++) {
struct fuse_in_arg *arg = &in->args[i];
- err = copy_in_one(arg->value, arg->size, &buf, &nbytes);
+ int islast = (i == in->numargs - 1);
+ err = copy_in_one(req, arg->size, arg->value, islast, buf,
+ nbytes);
if (err)
return err;
+
+ buf += arg->size;
+ nbytes -= arg->size;
}
return orignbytes - nbytes;
@@ -269,7 +304,7 @@ static ssize_t fuse_dev_read(struct file *file, char __user *buf,
if (req == NULL)
return -EINTR;
- ret = copy_in_args(&req->in, buf, nbytes);
+ ret = copy_in_args(req, buf, nbytes);
spin_lock(&fuse_lock);
if (req->isreply) {
if (ret < 0) {
@@ -312,91 +347,78 @@ static void process_getdir(struct fuse_req *req)
arg->file = fget(arg->fd);
}
-static int copy_out_pages(struct fuse_req *req, const char __user *buf,
- size_t nbytes)
+static inline int copy_out_page(const char __user *buf, struct page *page,
+ unsigned offset, unsigned count, int zeroing)
+{
+ int err = 0;
+ char *tmpbuf = kmap(page);
+ if (count < PAGE_SIZE && zeroing)
+ memset(tmpbuf, 0, PAGE_SIZE);
+ if (count)
+ err = copy_from_user(tmpbuf + offset, buf, count);
+ flush_dcache_page(page);
+ kunmap(page);
+ return err;
+}
+
+static int copy_out_pages(struct fuse_req *req, size_t nbytes,
+ const char __user *buf)
{
- unsigned count;
- unsigned page_offset;
- unsigned zeroing = req->out.page_zeroing;
unsigned i;
-
- req->out.args[0].size = nbytes;
- page_offset = req->page_offset;
- count = min(nbytes, (unsigned) PAGE_CACHE_SIZE - page_offset);
+ unsigned offset = req->page_offset;
+ unsigned zeroing = req->out.page_zeroing;
+ unsigned count = min(nbytes, (unsigned) PAGE_SIZE - offset);
+
for (i = 0; i < req->num_pages && (zeroing || nbytes); i++) {
struct page *page = req->pages[i];
- char *tmpbuf = kmap(page);
- int err = 0;
- if (count < PAGE_CACHE_SIZE && zeroing)
- memset(tmpbuf, 0, PAGE_CACHE_SIZE);
- if (count)
- err = copy_from_user(tmpbuf + page_offset, buf, count);
- flush_dcache_page(page);
- kunmap(page);
- if (err)
- return -EFAULT;
+ if (page && copy_out_page(buf, page, offset, count, zeroing))
+ return -EFAULT;
nbytes -= count;
buf += count;
- count = min(nbytes, (unsigned) PAGE_CACHE_SIZE);
- page_offset = 0;
+ count = min(nbytes, (unsigned) PAGE_SIZE);
+ offset = 0;
}
return 0;
}
-static inline int copy_out_one(struct fuse_out_arg *arg,
- const char __user **srcp,
- size_t *srclenp, int allowvar)
+static inline int copy_out_one(struct fuse_req *req, struct fuse_out_arg *arg,
+ int islast, const char __user *buf, size_t nbytes)
{
- size_t dstlen = arg->size;
- if (*srclenp < dstlen) {
- if (!allowvar) {
+ if (nbytes < arg->size) {
+ if (!islast || !req->out.argvar) {
printk("fuse_dev_write: write is short\n");
return -EINVAL;
}
- dstlen = *srclenp;
+ arg->size = nbytes;
}
-
- if (dstlen && copy_from_user(arg->value, *srcp, dstlen))
+ if (islast && req->out.argpages)
+ return copy_out_pages(req, arg->size, buf);
+ else if (arg->size && copy_from_user(arg->value, buf, arg->size))
return -EFAULT;
-
- *srcp += dstlen;
- *srclenp -= dstlen;
- arg->size = dstlen;
-
- return 0;
+ else
+ return 0;
}
-static inline int copy_out_args(struct fuse_req *req, const char __user *buf,
- size_t nbytes)
+static int copy_out_args(struct fuse_req *req, const char __user *buf,
+ size_t nbytes)
{
struct fuse_out *out = &req->out;
- int err;
int i;
buf += sizeof(struct fuse_out_header);
nbytes -= sizeof(struct fuse_out_header);
if (!out->h.error) {
- if (out->argpages) {
- if (nbytes <= out->args[0].size)
- return copy_out_pages(req, buf, nbytes);
- } else {
- for (i = 0; i < out->numargs; i++) {
- struct fuse_out_arg *arg = &out->args[i];
- int allowvar;
-
- if (out->argvar && i == out->numargs - 1)
- allowvar = 1;
- else
- allowvar = 0;
-
- err = copy_out_one(arg, &buf, &nbytes, allowvar);
- if (err)
- return err;
- }
+ for (i = 0; i < out->numargs; i++) {
+ struct fuse_out_arg *arg = &out->args[i];
+ int islast = (i == out->numargs - 1);
+ int err = copy_out_one(req, arg, islast, buf, nbytes);
+ if (err)
+ return err;
+ buf += arg->size;
+ nbytes -= arg->size;
}
}
-
if (nbytes != 0) {
printk("fuse_dev_write: write is long\n");
return -EINVAL;
@@ -412,7 +434,6 @@ static inline int copy_out_header(struct fuse_out_header *oh,
printk("fuse_dev_write: write is short\n");
return -EINVAL;
}
-
if (copy_from_user(oh, buf, sizeof(struct fuse_out_header)))
return -EFAULT;
@@ -591,7 +612,7 @@ struct file_operations fuse_dev_operations = {
};
#ifdef KERNEL_2_6
-#ifndef FUSE_MAINLINE
+#ifndef HAVE_FS_SUBSYS
static decl_subsys(fs, NULL, NULL);
#endif
static decl_subsys(fuse, NULL, NULL);
@@ -607,7 +628,7 @@ static int __init fuse_version_init(void)
{
int err;
-#ifndef FUSE_MAINLINE
+#ifndef HAVE_FS_SUBSYS
subsystem_register(&fs_subsys);
#endif
kset_set_kset_s(&fuse_subsys, fs_subsys);
@@ -617,7 +638,7 @@ static int __init fuse_version_init(void)
err = subsys_create_file(&fuse_subsys, &fuse_attr_version);
if (err) {
subsystem_unregister(&fuse_subsys);
-#ifndef FUSE_MAINLINE
+#ifndef HAVE_FS_SUBSYS
subsystem_unregister(&fs_subsys);
#endif
return err;
@@ -629,7 +650,7 @@ static void fuse_version_clean(void)
{
subsys_remove_file(&fuse_subsys, &fuse_attr_version);
subsystem_unregister(&fuse_subsys);
-#ifndef FUSE_MAINLINE
+#ifndef HAVE_FS_SUBSYS
subsystem_unregister(&fs_subsys);
#endif
}
diff --git a/kernel/dir.c b/kernel/dir.c
index 412ffc8..a56f513 100644
--- a/kernel/dir.c
+++ b/kernel/dir.c
@@ -92,8 +92,7 @@ static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr)
static int fuse_inode_eq(struct inode *inode, void *_nodeidp)
{
unsigned long nodeid = *(unsigned long *) _nodeidp;
- struct fuse_inode *fi = INO_FI(inode);
- if (fi->nodeid == nodeid)
+ if (get_node_id(inode) == nodeid)
return 1;
else
return 0;
@@ -102,8 +101,7 @@ static int fuse_inode_eq(struct inode *inode, void *_nodeidp)
static int fuse_inode_set(struct inode *inode, void *_nodeidp)
{
unsigned long nodeid = *(unsigned long *) _nodeidp;
- struct fuse_inode *fi = INO_FI(inode);
- fi->nodeid = nodeid;
+ get_fuse_inode(inode)->nodeid = nodeid;
return 0;
}
@@ -111,7 +109,7 @@ struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
int generation, struct fuse_attr *attr, int version)
{
struct inode *inode;
- struct fuse_conn *fc = SB_FC(sb);
+ struct fuse_conn *fc = get_fuse_conn_super(sb);
inode = iget5_locked(sb, nodeid, fuse_inode_eq, fuse_inode_set, &nodeid);
if (!inode)
@@ -137,8 +135,7 @@ struct inode *fuse_ilookup(struct super_block *sb, unsigned long nodeid)
#else
static int fuse_inode_eq(struct inode *inode, unsigned long ino, void *_nodeidp){
unsigned long nodeid = *(unsigned long *) _nodeidp;
- struct fuse_inode *fi = INO_FI(inode);
- if (inode->u.generic_ip && fi->nodeid == nodeid)
+ if (inode->u.generic_ip && get_node_id(inode) == nodeid)
return 1;
else
return 0;
@@ -154,8 +151,7 @@ struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
return NULL;
if (!inode->u.generic_ip) {
- struct fuse_inode *fi = INO_FI(inode);
- fi->nodeid = nodeid;
+ get_fuse_inode(inode)->nodeid = nodeid;
inode->u.generic_ip = inode;
inode->i_generation = generation;
fuse_init_inode(inode, attr);
@@ -182,9 +178,8 @@ static int fuse_send_lookup(struct fuse_conn *fc, struct fuse_req *req,
struct inode *dir, struct dentry *entry,
struct fuse_entry_out *outarg, int *version)
{
- struct fuse_inode *fi = INO_FI(dir);
req->in.h.opcode = FUSE_LOOKUP;
- req->in.h.nodeid = fi->nodeid;
+ req->in.h.nodeid = get_node_id(dir);
req->in.numargs = 1;
req->in.args[0].size = entry->d_name.len + 1;
req->in.args[0].value = entry->d_name.name;
@@ -199,7 +194,7 @@ static int fuse_send_lookup(struct fuse_conn *fc, struct fuse_req *req,
static int fuse_do_lookup(struct inode *dir, struct dentry *entry,
struct fuse_entry_out *outarg, int *version)
{
- struct fuse_conn *fc = INO_FC(dir);
+ struct fuse_conn *fc = get_fuse_conn(dir);
struct fuse_req *req;
int err;
@@ -227,7 +222,7 @@ static inline unsigned long time_to_jiffies(unsigned long sec,
static int fuse_lookup_iget(struct inode *dir, struct dentry *entry,
struct inode **inodep)
{
- struct fuse_conn *fc = INO_FC(dir);
+ struct fuse_conn *fc = get_fuse_conn(dir);
int err;
struct fuse_entry_out outarg;
int version;
@@ -254,7 +249,7 @@ static int fuse_lookup_iget(struct inode *dir, struct dentry *entry,
return err;
if (inode) {
- struct fuse_inode *fi = INO_FI(inode);
+ struct fuse_inode *fi = get_fuse_inode(inode);
entry->d_time = time_to_jiffies(outarg.entry_valid,
outarg.entry_valid_nsec);
fi->i_time = time_to_jiffies(outarg.attr_valid,
@@ -268,8 +263,7 @@ static int fuse_lookup_iget(struct inode *dir, struct dentry *entry,
static void fuse_invalidate_attr(struct inode *inode)
{
- struct fuse_inode *fi = INO_FI(inode);
- fi->i_time = jiffies - 1;
+ get_fuse_inode(inode)->i_time = jiffies - 1;
}
static int lookup_new_entry(struct fuse_conn *fc, struct fuse_req *req,
@@ -297,7 +291,7 @@ static int lookup_new_entry(struct fuse_conn *fc, struct fuse_req *req,
entry->d_time = time_to_jiffies(outarg->entry_valid,
outarg->entry_valid_nsec);
- fi = INO_FI(inode);
+ fi = get_fuse_inode(inode);
fi->i_time = time_to_jiffies(outarg->attr_valid,
outarg->attr_valid_nsec);
@@ -309,8 +303,7 @@ static int lookup_new_entry(struct fuse_conn *fc, struct fuse_req *req,
static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
dev_t rdev)
{
- struct fuse_conn *fc = INO_FC(dir);
- struct fuse_inode *fi = INO_FI(dir);
+ struct fuse_conn *fc = get_fuse_conn(dir);
struct fuse_req *req = fuse_get_request(fc);
struct fuse_mknod_in inarg;
struct fuse_entry_out outarg;
@@ -323,7 +316,7 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
inarg.mode = mode;
inarg.rdev = new_encode_dev(rdev);
req->in.h.opcode = FUSE_MKNOD;
- req->in.h.nodeid = fi->nodeid;
+ req->in.h.nodeid = get_node_id(dir);
req->in.numargs = 2;
req->in.args[0].size = sizeof(inarg);
req->in.args[0].value = &inarg;
@@ -350,8 +343,7 @@ static int fuse_create(struct inode *dir, struct dentry *entry, int mode,
static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode)
{
- struct fuse_conn *fc = INO_FC(dir);
- struct fuse_inode *fi = INO_FI(dir);
+ struct fuse_conn *fc = get_fuse_conn(dir);
struct fuse_req *req = fuse_get_request(fc);
struct fuse_mkdir_in inarg;
struct fuse_entry_out outarg;
@@ -363,7 +355,7 @@ static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode)
memset(&inarg, 0, sizeof(inarg));
inarg.mode = mode;
req->in.h.opcode = FUSE_MKDIR;
- req->in.h.nodeid = fi->nodeid;
+ req->in.h.nodeid = get_node_id(dir);
req->in.numargs = 2;
req->in.args[0].size = sizeof(inarg);
req->in.args[0].value = &inarg;
@@ -385,8 +377,7 @@ static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode)
static int fuse_symlink(struct inode *dir, struct dentry *entry,
const char *link)
{
- struct fuse_conn *fc = INO_FC(dir);
- struct fuse_inode *fi = INO_FI(dir);
+ struct fuse_conn *fc = get_fuse_conn(dir);
struct fuse_req *req;
struct fuse_entry_out outarg;
unsigned len = strlen(link) + 1;
@@ -400,7 +391,7 @@ static int fuse_symlink(struct inode *dir, struct dentry *entry,
return -ERESTARTSYS;
req->in.h.opcode = FUSE_SYMLINK;
- req->in.h.nodeid = fi->nodeid;
+ req->in.h.nodeid = get_node_id(dir);
req->in.numargs = 2;
req->in.args[0].size = entry->d_name.len + 1;
req->in.args[0].value = entry->d_name.name;
@@ -421,8 +412,7 @@ static int fuse_symlink(struct inode *dir, struct dentry *entry,
static int fuse_unlink(struct inode *dir, struct dentry *entry)
{
- struct fuse_conn *fc = INO_FC(dir);
- struct fuse_inode *fi = INO_FI(dir);
+ struct fuse_conn *fc = get_fuse_conn(dir);
struct fuse_req *req = fuse_get_request(fc);
int err;
@@ -430,7 +420,7 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry)
return -ERESTARTSYS;
req->in.h.opcode = FUSE_UNLINK;
- req->in.h.nodeid = fi->nodeid;
+ req->in.h.nodeid = get_node_id(dir);
req->in.numargs = 1;
req->in.args[0].size = entry->d_name.len + 1;
req->in.args[0].value = entry->d_name.name;
@@ -452,8 +442,7 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry)
static int fuse_rmdir(struct inode *dir, struct dentry *entry)
{
- struct fuse_conn *fc = INO_FC(dir);
- struct fuse_inode *fi = INO_FI(dir);
+ struct fuse_conn *fc = get_fuse_conn(dir);
struct fuse_req *req = fuse_get_request(fc);
int err;
@@ -461,7 +450,7 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry)
return -ERESTARTSYS;
req->in.h.opcode = FUSE_RMDIR;
- req->in.h.nodeid = fi->nodeid;
+ req->in.h.nodeid = get_node_id(dir);
req->in.numargs = 1;
req->in.args[0].size = entry->d_name.len + 1;
req->in.args[0].value = entry->d_name.name;
@@ -478,9 +467,7 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry)
static int fuse_rename(struct inode *olddir, struct dentry *oldent,
struct inode *newdir, struct dentry *newent)
{
- struct fuse_conn *fc = INO_FC(olddir);
- struct fuse_inode *oldfi = INO_FI(olddir);
- struct fuse_inode *newfi = INO_FI(newdir);
+ struct fuse_conn *fc = get_fuse_conn(olddir);
struct fuse_req *req = fuse_get_request(fc);
struct fuse_rename_in inarg;
int err;
@@ -489,9 +476,9 @@ static int fuse_rename(struct inode *olddir, struct dentry *oldent,
return -ERESTARTSYS;
memset(&inarg, 0, sizeof(inarg));
- inarg.newdir = newfi->nodeid;
+ inarg.newdir = get_node_id(newdir);
req->in.h.opcode = FUSE_RENAME;
- req->in.h.nodeid = oldfi->nodeid;
+ req->in.h.nodeid = get_node_id(olddir);
req->in.numargs = 3;
req->in.args[0].size = sizeof(inarg);
req->in.args[0].value = &inarg;
@@ -514,9 +501,7 @@ static int fuse_link(struct dentry *entry, struct inode *newdir,
struct dentry *newent)
{
struct inode *inode = entry->d_inode;
- struct fuse_conn *fc = INO_FC(inode);
- struct fuse_inode *fi = INO_FI(inode);
- struct fuse_inode *newfi = INO_FI(newdir);
+ struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_req *req = fuse_get_request(fc);
struct fuse_link_in inarg;
struct fuse_entry_out outarg;
@@ -526,9 +511,9 @@ static int fuse_link(struct dentry *entry, struct inode *newdir,
return -ERESTARTSYS;
memset(&inarg, 0, sizeof(inarg));
- inarg.newdir = newfi->nodeid;
+ inarg.newdir = get_node_id(newdir);
req->in.h.opcode = FUSE_LINK;
- req->in.h.nodeid = fi->nodeid;
+ req->in.h.nodeid = get_node_id(inode);
req->in.numargs = 2;
req->in.args[0].size = sizeof(inarg);
req->in.args[0].value = &inarg;
@@ -551,8 +536,7 @@ static int fuse_link(struct dentry *entry, struct inode *newdir,
int fuse_do_getattr(struct inode *inode)
{
- struct fuse_inode *fi = INO_FI(inode);
- struct fuse_conn *fc = INO_FC(inode);
+ struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_req *req = fuse_get_request(fc);
struct fuse_attr_out arg;
int err;
@@ -561,13 +545,14 @@ int fuse_do_getattr(struct inode *inode)
return -ERESTARTSYS;
req->in.h.opcode = FUSE_GETATTR;
- req->in.h.nodeid = fi->nodeid;
+ req->in.h.nodeid = get_node_id(inode);
req->out.numargs = 1;
req->out.args[0].size = sizeof(arg);
req->out.args[0].value = &arg;
request_send(fc, req);
err = req->out.h.error;
if (!err) {
+ struct fuse_inode *fi = get_fuse_inode(inode);
change_attributes(inode, &arg.attr);
fi->i_time = time_to_jiffies(arg.attr_valid,
arg.attr_valid_nsec);
@@ -579,10 +564,10 @@ int fuse_do_getattr(struct inode *inode)
static int fuse_revalidate(struct dentry *entry)
{
struct inode *inode = entry->d_inode;
- struct fuse_inode *fi = INO_FI(inode);
- struct fuse_conn *fc = INO_FC(inode);
+ struct fuse_inode *fi = get_fuse_inode(inode);
+ struct fuse_conn *fc = get_fuse_conn(inode);
- if (fi->nodeid == FUSE_ROOT_ID) {
+ if (get_node_id(inode) == FUSE_ROOT_ID) {
if (!(fc->flags & FUSE_ALLOW_OTHER) &&
current->fsuid != fc->uid &&
(!(fc->flags & FUSE_ALLOW_ROOT) ||
@@ -596,7 +581,7 @@ static int fuse_revalidate(struct dentry *entry)
static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
{
- struct fuse_conn *fc = INO_FC(inode);
+ struct fuse_conn *fc = get_fuse_conn(inode);
if (!(fc->flags & FUSE_ALLOW_OTHER) && current->fsuid != fc->uid &&
(!(fc->flags & FUSE_ALLOW_ROOT) || current->fsuid != 0))
@@ -692,8 +677,7 @@ static int fuse_checkdir(struct file *cfile, struct file *file)
static int fuse_getdir(struct file *file)
{
struct inode *inode = file->f_dentry->d_inode;
- struct fuse_conn *fc = INO_FC(inode);
- struct fuse_inode *fi = INO_FI(inode);
+ struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_req *req = fuse_get_request(fc);
struct fuse_getdir_out_i outarg;
int err;
@@ -702,7 +686,7 @@ static int fuse_getdir(struct file *file)
return -ERESTARTSYS;
req->in.h.opcode = FUSE_GETDIR;
- req->in.h.nodeid = fi->nodeid;
+ req->in.h.nodeid = get_node_id(inode);
req->out.numargs = 1;
req->out.args[0].size = sizeof(struct fuse_getdir_out);
req->out.args[0].value = &outarg;
@@ -745,8 +729,7 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
static char *read_link(struct dentry *dentry)
{
struct inode *inode = dentry->d_inode;
- struct fuse_conn *fc = INO_FC(inode);
- struct fuse_inode *fi = INO_FI(inode);
+ struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_req *req = fuse_get_request(fc);
char *link;
@@ -759,7 +742,7 @@ static char *read_link(struct dentry *dentry)
goto out;
}
req->in.h.opcode = FUSE_READLINK;
- req->in.h.nodeid = fi->nodeid;
+ req->in.h.nodeid = get_node_id(inode);
req->out.argvar = 1;
req->out.numargs = 1;
req->out.args[0].size = PAGE_SIZE - 1;
@@ -853,8 +836,8 @@ static unsigned iattr_to_fattr(struct iattr *iattr, struct fuse_attr *fattr)
static int fuse_setattr(struct dentry *entry, struct iattr *attr)
{
struct inode *inode = entry->d_inode;
- struct fuse_conn *fc = INO_FC(inode);
- struct fuse_inode *fi = INO_FI(inode);
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ struct fuse_inode *fi = get_fuse_inode(inode);
struct fuse_req *req;
struct fuse_setattr_in inarg;
struct fuse_attr_out outarg;
@@ -891,7 +874,7 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr)
memset(&inarg, 0, sizeof(inarg));
inarg.valid = iattr_to_fattr(attr, &inarg.attr);
req->in.h.opcode = FUSE_SETATTR;
- req->in.h.nodeid = fi->nodeid;
+ req->in.h.nodeid = get_node_id(inode);
req->in.numargs = 1;
req->in.args[0].size = sizeof(inarg);
req->in.args[0].value = &inarg;
@@ -925,7 +908,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
return 0;
else if (entry->d_time && time_after(jiffies, entry->d_time)) {
struct inode *inode = entry->d_inode;
- struct fuse_inode *fi = INO_FI(inode);
+ struct fuse_inode *fi = get_fuse_inode(inode);
struct fuse_entry_out outarg;
int version;
int ret;
@@ -935,7 +918,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
if (ret)
return 0;
- if (outarg.nodeid != fi->nodeid)
+ if (outarg.nodeid != get_node_id(inode))
return 0;
change_attributes(inode, &outarg.attr);
@@ -1023,8 +1006,7 @@ static int fuse_setxattr(struct dentry *entry, const char *name,
#endif
{
struct inode *inode = entry->d_inode;
- struct fuse_conn *fc = INO_FC(inode);
- struct fuse_inode *fi = INO_FI(inode);
+ struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_req *req;
struct fuse_setxattr_in inarg;
int err;
@@ -1043,7 +1025,7 @@ static int fuse_setxattr(struct dentry *entry, const char *name,
inarg.size = size;
inarg.flags = flags;
req->in.h.opcode = FUSE_SETXATTR;
- req->in.h.nodeid = fi->nodeid;
+ req->in.h.nodeid = get_node_id(inode);
req->in.numargs = 3;
req->in.args[0].size = sizeof(inarg);
req->in.args[0].value = &inarg;
@@ -1065,8 +1047,7 @@ static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
void *value, size_t size)
{
struct inode *inode = entry->d_inode;
- struct fuse_conn *fc = INO_FC(inode);
- struct fuse_inode *fi = INO_FI(inode);
+ struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_req *req;
struct fuse_getxattr_in inarg;
struct fuse_getxattr_out outarg;
@@ -1082,7 +1063,7 @@ static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
memset(&inarg, 0, sizeof(inarg));
inarg.size = size;
req->in.h.opcode = FUSE_GETXATTR;
- req->in.h.nodeid = fi->nodeid;
+ req->in.h.nodeid = get_node_id(inode);
req->in.numargs = 2;
req->in.args[0].size = sizeof(inarg);
req->in.args[0].value = &inarg;
@@ -1115,8 +1096,7 @@ static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
{
struct inode *inode = entry->d_inode;
- struct fuse_conn *fc = INO_FC(inode);
- struct fuse_inode *fi = INO_FI(inode);
+ struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_req *req;
struct fuse_getxattr_in inarg;
struct fuse_getxattr_out outarg;
@@ -1132,7 +1112,7 @@ static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
memset(&inarg, 0, sizeof(inarg));
inarg.size = size;
req->in.h.opcode = FUSE_LISTXATTR;
- req->in.h.nodeid = fi->nodeid;
+ req->in.h.nodeid = get_node_id(inode);
req->in.numargs = 1;
req->in.args[0].size = sizeof(inarg);
req->in.args[0].value = &inarg;
@@ -1163,8 +1143,7 @@ static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
static int fuse_removexattr(struct dentry *entry, const char *name)
{
struct inode *inode = entry->d_inode;
- struct fuse_conn *fc = INO_FC(inode);
- struct fuse_inode *fi = INO_FI(inode);
+ struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_req *req;
int err;
@@ -1176,7 +1155,7 @@ static int fuse_removexattr(struct dentry *entry, const char *name)
return -ERESTARTSYS;
req->in.h.opcode = FUSE_REMOVEXATTR;
- req->in.h.nodeid = fi->nodeid;
+ req->in.h.nodeid = get_node_id(inode);
req->in.numargs = 1;
req->in.args[0].size = strlen(name) + 1;
req->in.args[0].value = name;
diff --git a/kernel/file.c b/kernel/file.c
index 2d15c5b..da0fbb8 100644
--- a/kernel/file.c
+++ b/kernel/file.c
@@ -29,8 +29,7 @@ MODULE_PARM_DESC(user_mmap, "Allow non root user to create a shared writable map
static int fuse_open(struct inode *inode, struct file *file)
{
- struct fuse_conn *fc = INO_FC(inode);
- struct fuse_inode *fi = INO_FI(inode);
+ struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_req *req;
struct fuse_open_in inarg;
struct fuse_open_out outarg;
@@ -43,7 +42,7 @@ static int fuse_open(struct inode *inode, struct file *file)
/* If opening the root node, no lookup has been performed on
it, so the attributes must be refreshed */
- if (fi->nodeid == FUSE_ROOT_ID) {
+ if (get_node_id(inode) == FUSE_ROOT_ID) {
int err = fuse_do_getattr(inode);
if (err)
return err;
@@ -69,7 +68,7 @@ static int fuse_open(struct inode *inode, struct file *file)
memset(&inarg, 0, sizeof(inarg));
inarg.flags = file->f_flags & ~O_EXCL;
req->in.h.opcode = FUSE_OPEN;
- req->in.h.nodeid = fi->nodeid;
+ req->in.h.nodeid = get_node_id(inode);
req->in.numargs = 1;
req->in.args[0].size = sizeof(inarg);
req->in.args[0].value = &inarg;
@@ -117,8 +116,7 @@ void fuse_sync_inode(struct inode *inode)
static int fuse_release(struct inode *inode, struct file *file)
{
- struct fuse_conn *fc = INO_FC(inode);
- struct fuse_inode *fi = INO_FI(inode);
+ struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_file *ff = file->private_data;
struct fuse_req *req = ff->release_req;
struct fuse_release_in inarg;
@@ -128,6 +126,7 @@ static int fuse_release(struct inode *inode, struct file *file)
fuse_sync_inode(inode);
if (!list_empty(&ff->ff_list)) {
+ struct fuse_inode *fi = get_fuse_inode(inode);
down_write(&fi->write_sem);
list_del(&ff->ff_list);
up_write(&fi->write_sem);
@@ -137,7 +136,7 @@ static int fuse_release(struct inode *inode, struct file *file)
inarg.fh = ff->fh;
inarg.flags = file->f_flags & ~O_EXCL;
req->in.h.opcode = FUSE_RELEASE;
- req->in.h.nodeid = fi->nodeid;
+ req->in.h.nodeid = get_node_id(inode);
req->in.numargs = 1;
req->in.args[0].size = sizeof(inarg);
req->in.args[0].value = &inarg;
@@ -153,8 +152,7 @@ static int fuse_release(struct inode *inode, struct file *file)
static int fuse_flush(struct file *file)
{
struct inode *inode = file->f_dentry->d_inode;
- struct fuse_conn *fc = INO_FC(inode);
- struct fuse_inode *fi = INO_FI(inode);
+ struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_file *ff = file->private_data;
struct fuse_req *req = ff->release_req;
struct fuse_flush_in inarg;
@@ -167,7 +165,7 @@ static int fuse_flush(struct file *file)
memset(&inarg, 0, sizeof(inarg));
inarg.fh = ff->fh;
req->in.h.opcode = FUSE_FLUSH;
- req->in.h.nodeid = fi->nodeid;
+ req->in.h.nodeid = get_node_id(inode);
req->in.numargs = 1;
req->in.args[0].size = sizeof(inarg);
req->in.args[0].value = &inarg;
@@ -185,8 +183,8 @@ static int fuse_flush(struct file *file)
static int fuse_fsync(struct file *file, struct dentry *de, int datasync)
{
struct inode *inode = de->d_inode;
- struct fuse_inode *fi = INO_FI(inode);
- struct fuse_conn *fc = INO_FC(inode);
+ struct fuse_inode *fi = get_fuse_inode(inode);
+ struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_file *ff = file->private_data;
struct fuse_req *req;
struct fuse_fsync_in inarg;
@@ -208,7 +206,7 @@ static int fuse_fsync(struct file *file, struct dentry *de, int datasync)
inarg.fh = ff->fh;
inarg.datasync = datasync;
req->in.h.opcode = FUSE_FSYNC;
- req->in.h.nodeid = fi->nodeid;
+ req->in.h.nodeid = get_node_id(inode);
req->in.numargs = 1;
req->in.args[0].size = sizeof(inarg);
req->in.args[0].value = &inarg;
@@ -225,7 +223,6 @@ static int fuse_fsync(struct file *file, struct dentry *de, int datasync)
static void fuse_read_init(struct fuse_req *req, struct file *file,
struct inode *inode, loff_t pos, size_t count)
{
- struct fuse_inode *fi = INO_FI(inode);
struct fuse_file *ff = file->private_data;
struct fuse_read_in *inarg = &req->misc.read_in;
@@ -233,11 +230,13 @@ static void fuse_read_init(struct fuse_req *req, struct file *file,
inarg->offset = pos;
inarg->size = count;
req->in.h.opcode = FUSE_READ;
- req->in.h.nodeid = fi->nodeid;
+ req->in.h.nodeid = get_node_id(inode);
req->in.numargs = 1;
req->in.args[0].size = sizeof(struct fuse_read_in);
req->in.args[0].value = inarg;
+ req->out.argpages = 1;
req->out.argvar = 1;
+ req->out.page_zeroing = 1;
req->out.numargs = 1;
req->out.args[0].size = count;
}
@@ -245,14 +244,12 @@ static void fuse_read_init(struct fuse_req *req, struct file *file,
static int fuse_readpage(struct file *file, struct page *page)
{
struct inode *inode = page->mapping->host;
- struct fuse_conn *fc = INO_FC(inode);
+ struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_req *req = fuse_get_request_nonint(fc);
- loff_t pos = (loff_t) page->index << PAGE_CACHE_SHIFT;
+ loff_t pos = (loff_t) page->index << PAGE_SHIFT;
int err;
- fuse_read_init(req, file, inode, pos, PAGE_CACHE_SIZE);
- req->out.argpages = 1;
- req->out.page_zeroing = 1;
+ fuse_read_init(req, file, inode, pos, PAGE_SIZE);
req->num_pages = 1;
req->pages[0] = page;
request_send(fc, req);
@@ -280,12 +277,10 @@ static void read_pages_end(struct fuse_conn *fc, struct fuse_req *req)
static void fuse_send_readpages(struct fuse_req *req, struct file *file,
struct inode *inode)
{
- struct fuse_conn *fc = INO_FC(inode);
- loff_t pos = (loff_t) req->pages[0]->index << PAGE_CACHE_SHIFT;
- size_t count = req->num_pages << PAGE_CACHE_SHIFT;
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ loff_t pos = (loff_t) req->pages[0]->index << PAGE_SHIFT;
+ size_t count = req->num_pages << PAGE_SHIFT;
fuse_read_init(req, file, inode, pos, count);
- req->out.argpages = 1;
- req->out.page_zeroing = 1;
request_send_async(fc, req, read_pages_end);
}
@@ -300,13 +295,13 @@ static int fuse_readpages_fill(void *_data, struct page *page)
struct fuse_readpages_data *data = _data;
struct fuse_req *req = data->req;
struct inode *inode = data->inode;
- struct fuse_conn *fc = INO_FC(inode);
+ struct fuse_conn *fc = get_fuse_conn(inode);
if (req->num_pages &&
(req->num_pages == FUSE_MAX_PAGES_PER_REQ ||
- (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read ||
+ (req->num_pages + 1) * PAGE_SIZE > fc->max_read ||
req->pages[req->num_pages - 1]->index + 1 != page->index)) {
- struct fuse_conn *fc = INO_FC(page->mapping->host);
+ struct fuse_conn *fc = get_fuse_conn(page->mapping->host);
fuse_send_readpages(req, data->file, inode);
data->req = req = fuse_get_request_nonint(fc);
}
@@ -319,7 +314,7 @@ static int fuse_readpages(struct file *file, struct address_space *mapping,
struct list_head *pages, unsigned nr_pages)
{
struct inode *inode = mapping->host;
- struct fuse_conn *fc = INO_FC(inode);
+ struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_readpages_data data;
data.req = fuse_get_request_nonint(fc);
@@ -338,7 +333,7 @@ static int fuse_readpages(struct file *file, struct address_space *mapping,
#define FUSE_BLOCK_SHIFT 16
#define FUSE_BLOCK_SIZE (1UL << FUSE_BLOCK_SHIFT)
#define FUSE_BLOCK_MASK (~(FUSE_BLOCK_SIZE-1))
-#if (1UL << (FUSE_BLOCK_SHIFT - PAGE_CACHE_SHIFT)) > FUSE_MAX_PAGES_PER_REQ
+#if (1UL << (FUSE_BLOCK_SHIFT - PAGE_SHIFT)) > FUSE_MAX_PAGES_PER_REQ
#error FUSE_BLOCK_SHIFT too large
#endif
@@ -364,7 +359,7 @@ static void fuse_file_read_block(struct fuse_req *req, struct file *file,
struct inode *inode, unsigned start,
unsigned end)
{
- struct fuse_conn *fc = INO_FC(inode);
+ struct fuse_conn *fc = get_fuse_conn(inode);
loff_t pos;
size_t count;
int index;
@@ -375,29 +370,34 @@ static void fuse_file_read_block(struct fuse_req *req, struct file *file,
struct page *page = grab_cache_page(inode->i_mapping, index);
if (!page)
goto out;
+ if (PageUptodate(page)) {
+ unlock_page(page);
+ page_cache_release(page);
+ page = NULL;
+ }
req->pages[req->num_pages++] = page;
}
- pos = (loff_t) start << PAGE_CACHE_SHIFT;
- count = req->num_pages << PAGE_CACHE_SHIFT;
+ pos = (loff_t) start << PAGE_SHIFT;
+ count = req->num_pages << PAGE_SHIFT;
fuse_read_init(req, file, inode, pos, count);
- req->out.argpages = 1;
- req->out.page_zeroing = 1;
request_send(fc, req);
err = req->out.h.error;
out:
for (i = 0; i < req->num_pages; i++) {
struct page *page = req->pages[i];
- if (!err)
- SetPageUptodate(page);
- unlock_page(page);
- page_cache_release(page);
+ if (page) {
+ if (!err)
+ SetPageUptodate(page);
+ unlock_page(page);
+ page_cache_release(page);
+ }
}
}
static int fuse_file_bigread(struct file *file, struct inode *inode,
loff_t pos, size_t count)
{
- struct fuse_conn *fc = INO_FC(inode);
+ struct fuse_conn *fc = get_fuse_conn(inode);
unsigned starti;
unsigned endi;
unsigned nexti;
@@ -408,15 +408,15 @@ static int fuse_file_bigread(struct file *file, struct inode *inode,
if (end <= pos)
return 0;
- starti = (pos & FUSE_BLOCK_MASK) >> PAGE_CACHE_SHIFT;
- endi = (end + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+ starti = (pos & FUSE_BLOCK_MASK) >> PAGE_SHIFT;
+ endi = (end + PAGE_SIZE - 1) >> PAGE_SHIFT;
req = fuse_get_request(fc);
if (!req)
return -ERESTARTSYS;
for (; starti < endi; starti = nexti) {
- nexti = starti + (FUSE_BLOCK_SIZE >> PAGE_CACHE_SHIFT);
+ nexti = starti + (FUSE_BLOCK_SIZE >> PAGE_SHIFT);
nexti = min(nexti, endi);
if (!fuse_is_block_uptodate(inode, starti, nexti)) {
fuse_file_read_block(req, file, inode, starti, nexti);
@@ -428,35 +428,37 @@ static int fuse_file_bigread(struct file *file, struct inode *inode,
}
#endif /* KERNEL_2_6 */
-static void fuse_release_user_pages(struct fuse_req *req)
+static void fuse_release_user_pages(struct fuse_req *req, int write)
{
unsigned i;
for (i = 0; i < req->num_pages; i++) {
- struct page *page = req->pages[i];
+ struct page *page = req->pages[i];
+ if (write) {
#ifdef KERNEL_2_6
- set_page_dirty_lock(page);
+ set_page_dirty_lock(page);
#else
- lock_page(page);
- set_page_dirty(page);
- unlock_page(page);
+ lock_page(page);
+ set_page_dirty(page);
+ unlock_page(page);
#endif
+ }
page_cache_release(page);
}
}
-static int fuse_get_user_pages(struct fuse_req *req, char __user *buf,
- unsigned nbytes)
+static int fuse_get_user_pages(struct fuse_req *req, const char __user *buf,
+ unsigned nbytes, int write)
{
unsigned long user_addr = (unsigned long) buf;
- unsigned offset = user_addr & ~PAGE_CACHE_MASK;
+ unsigned offset = user_addr & ~PAGE_MASK;
int npages;
- nbytes = min(nbytes, (unsigned) FUSE_MAX_PAGES_PER_REQ << PAGE_CACHE_SHIFT);
- npages = (nbytes + offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+ nbytes = min(nbytes, (unsigned) FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT);
+ npages = (nbytes + offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
npages = min(npages, FUSE_MAX_PAGES_PER_REQ);
- npages = get_user_pages(current, current->mm, user_addr, npages, 1, 0,
- req->pages, NULL);
+ npages = get_user_pages(current, current->mm, user_addr, npages, write,
+ 0, req->pages, NULL);
if (npages < 0)
return npages;
@@ -469,7 +471,7 @@ static ssize_t fuse_direct_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
struct inode *inode = file->f_dentry->d_inode;
- struct fuse_conn *fc = INO_FC(inode);
+ struct fuse_conn *fc = get_fuse_conn(inode);
loff_t pos = *ppos;
ssize_t res = 0;
struct fuse_req *req = fuse_get_request(fc);
@@ -477,20 +479,20 @@ static ssize_t fuse_direct_read(struct file *file, char __user *buf,
return -ERESTARTSYS;
while (count) {
- unsigned nbytes = min(count, fc->max_read);
unsigned nread;
unsigned ntmp;
- int err = fuse_get_user_pages(req, buf, nbytes);
+ unsigned nbytes = min(count, fc->max_read);
+ int err = fuse_get_user_pages(req, buf, nbytes, 1);
if (err) {
res = err;
break;
}
- ntmp = (req->num_pages << PAGE_CACHE_SHIFT) - req->page_offset;
+ ntmp = (req->num_pages << PAGE_SHIFT) - req->page_offset;
nbytes = min(nbytes, ntmp);
fuse_read_init(req, file, inode, pos, nbytes);
- req->out.argpages = 1;
+ req->out.page_zeroing = 0; /* set to 1 by default */
request_send(fc, req);
- fuse_release_user_pages(req);
+ fuse_release_user_pages(req, 1);
if (req->out.h.error) {
if (!res)
res = req->out.h.error;
@@ -503,7 +505,8 @@ static ssize_t fuse_direct_read(struct file *file, char __user *buf,
buf += nread;
if (nread != nbytes)
break;
- fuse_reset_request(req);
+ if (count)
+ fuse_reset_request(req);
}
fuse_put_request(fc, req);
if (res > 0)
@@ -516,7 +519,7 @@ static ssize_t fuse_file_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
struct inode *inode = file->f_dentry->d_inode;
- struct fuse_conn *fc = INO_FC(inode);
+ struct fuse_conn *fc = get_fuse_conn(inode);
ssize_t res;
if (fc->flags & FUSE_DIRECT_IO)
@@ -536,72 +539,31 @@ static ssize_t fuse_file_read(struct file *file, char __user *buf,
return res;
}
-static ssize_t fuse_send_write(struct fuse_req *req, struct fuse_file *ff,
- struct inode *inode, const char *buf,
- loff_t pos, size_t count)
+static void fuse_write_init(struct fuse_req *req, struct fuse_file *ff,
+ struct inode *inode, loff_t pos, size_t count,
+ int iswritepage)
{
- struct fuse_conn *fc = INO_FC(inode);
- struct fuse_inode *fi = INO_FI(inode);
- struct fuse_write_in inarg;
- struct fuse_write_out outarg;
- ssize_t res;
-
- memset(&inarg, 0, sizeof(inarg));
- inarg.writepage = 0;
- inarg.fh = ff->fh;
- inarg.offset = pos;
- inarg.size = count;
+ struct fuse_write_in *inarg = &req->misc.write.in;
+
+ inarg->writepage = iswritepage;
+ inarg->fh = ff->fh;
+ inarg->offset = pos;
+ inarg->size = count;
req->in.h.opcode = FUSE_WRITE;
- req->in.h.nodeid = fi->nodeid;
+ req->in.h.nodeid = get_node_id(inode);
+ if (iswritepage) {
+ req->in.h.uid = 0;
+ req->in.h.gid = 0;
+ req->in.h.pid = 0;
+ }
+ req->in.argpages = 1;
req->in.numargs = 2;
- req->in.args[0].size = sizeof(inarg);
- req->in.args[0].value = &inarg;
+ req->in.args[0].size = sizeof(struct fuse_write_in);
+ req->in.args[0].value = inarg;
req->in.args[1].size = count;
- req->in.args[1].value = buf;
req->out.numargs = 1;
- req->out.args[0].size = sizeof(outarg);
- req->out.args[0].value = &outarg;
- request_send(fc, req);
- res = req->out.h.error;
- if (!res) {
- if (outarg.size > count)
- return -EPROTO;
- else
- return outarg.size;
- }
- else
- return res;
-}
-
-static int write_buffer(struct inode *inode, struct file *file,
- struct page *page, unsigned offset, size_t count)
-{
- struct fuse_conn *fc = INO_FC(inode);
- struct fuse_file *ff = file->private_data;
- char *buffer;
- ssize_t res;
- loff_t pos;
- struct fuse_req *req;
-
- req = fuse_get_request(fc);
- if (!req)
- return -ERESTARTSYS;
-
- pos = ((loff_t) page->index << PAGE_CACHE_SHIFT) + offset;
- buffer = kmap(page);
- res = fuse_send_write(req, ff, inode, buffer + offset, pos, count);
- fuse_put_request(fc, req);
- if (res >= 0) {
- if (res < count) {
- printk("fuse: short write\n");
- res = -EPROTO;
- } else
- res = 0;
- }
- kunmap(page);
- if (res)
- SetPageError(page);
- return res;
+ req->out.args[0].size = sizeof(struct fuse_write_out);
+ req->out.args[0].value = &req->misc.write.out;
}
static int get_write_count(struct inode *inode, struct page *page)
@@ -610,28 +572,32 @@ static int get_write_count(struct inode *inode, struct page *page)
loff_t size = i_size_read(inode);
int count;
- end_index = size >> PAGE_CACHE_SHIFT;
+ end_index = size >> PAGE_SHIFT;
if (page->index < end_index)
- count = PAGE_CACHE_SIZE;
+ count = PAGE_SIZE;
else {
- count = size & (PAGE_CACHE_SIZE - 1);
+ count = size & (PAGE_SIZE - 1);
if (page->index > end_index || count == 0)
return 0;
}
return count;
}
+static inline struct fuse_file *get_write_file(struct fuse_inode *fi)
+{
+ BUG_ON(list_empty(&fi->write_files));
+ return list_entry(fi->write_files.next, struct fuse_file, ff_list);
+}
+
#ifdef KERNEL_2_6
static void write_page_end(struct fuse_conn *fc, struct fuse_req *req)
{
struct page *page = req->pages[0];
struct inode *inode = page->mapping->host;
- struct fuse_inode *fi = INO_FI(inode);
+ struct fuse_inode *fi = get_fuse_inode(inode);
struct fuse_write_out *outarg = req->out.args[0].value;
- if (!req->out.h.error && outarg->size != req->in.args[1].size) {
- printk("fuse: short write\n");
+ if (!req->out.h.error && outarg->size != req->in.args[1].size)
req->out.h.error = -EPROTO;
- }
if (req->out.h.error) {
SetPageError(page);
@@ -641,52 +607,15 @@ static void write_page_end(struct fuse_conn *fc, struct fuse_req *req)
set_bit(AS_EIO, &page->mapping->flags);
}
up_read(&fi->write_sem);
-
end_page_writeback(page);
- kunmap(page);
fuse_put_request(fc, req);
}
-static void fuse_send_writepage(struct fuse_req *req, struct inode *inode,
- struct page *page, unsigned count)
-{
- struct fuse_conn *fc = INO_FC(inode);
- struct fuse_inode *fi = INO_FI(inode);
- struct fuse_write_in *inarg;
- struct fuse_file *ff;
- char *buffer;
-
- BUG_ON(list_empty(&fi->write_files));
- ff = list_entry(fi->write_files.next, struct fuse_file, ff_list);
-
- inarg = &req->misc.write.in;
- buffer = kmap(page);
- inarg->writepage = 1;
- inarg->fh = ff->fh;
- inarg->offset = ((loff_t) page->index << PAGE_CACHE_SHIFT);
- inarg->size = count;
- req->in.h.opcode = FUSE_WRITE;
- req->in.h.nodeid = fi->nodeid;
- req->in.h.uid = 0;
- req->in.h.gid = 0;
- req->in.h.pid = 0;
- req->in.numargs = 2;
- req->in.args[0].size = sizeof(struct fuse_write_in);
- req->in.args[0].value = inarg;
- req->in.args[1].size = count;
- req->in.args[1].value = buffer;
- req->out.numargs = 1;
- req->out.args[0].size = sizeof(struct fuse_write_out);
- req->out.args[0].value = &req->misc.write.out;
- req->pages[0] = page;
- request_send_async(fc, req, write_page_end);
-}
-
static int fuse_writepage(struct page *page, struct writeback_control *wbc)
{
struct inode *inode = page->mapping->host;
- struct fuse_conn *fc = INO_FC(inode);
- struct fuse_inode *fi = INO_FI(inode);
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ struct fuse_inode *fi = get_fuse_inode(inode);
struct fuse_req *req;
int err;
@@ -702,12 +631,16 @@ static int fuse_writepage(struct page *page, struct writeback_control *wbc)
else
down_read(&fi->write_sem);
if (locked) {
- unsigned count;
+ unsigned count = get_write_count(inode, page);
+ loff_t pos = (loff_t) page->index << PAGE_SHIFT;
err = 0;
- count = get_write_count(inode, page);
if (count) {
- SetPageWriteback(page);
- fuse_send_writepage(req, inode, page, count);
+ struct fuse_file *ff = get_write_file(fi);
+ SetPageWriteback(page);
+ fuse_write_init(req, ff, inode, pos, count, 1);
+ req->num_pages = 1;
+ req->pages[0] = page;
+ request_send_async(fc, req, write_page_end);
goto out;
}
up_read(&fi->write_sem);
@@ -727,89 +660,34 @@ static int fuse_writepage(struct page *page, struct writeback_control *wbc)
return err;
}
#else
-static ssize_t fuse_send_writepage(struct fuse_req *req, struct fuse_file *ff,
- struct inode *inode, const char *buf,
- loff_t pos, size_t count)
-{
- struct fuse_conn *fc = INO_FC(inode);
- struct fuse_inode *fi = INO_FI(inode);
- struct fuse_write_in inarg;
- struct fuse_write_out outarg;
- ssize_t res;
-
- memset(&inarg, 0, sizeof(inarg));
- inarg.writepage = 1;
- inarg.fh = ff->fh;
- inarg.offset = pos;
- inarg.size = count;
- req->in.h.opcode = FUSE_WRITE;
- req->in.h.nodeid = fi->nodeid;
- req->in.h.uid = 0;
- req->in.h.gid = 0;
- req->in.h.pid = 0;
- req->in.numargs = 2;
- req->in.args[0].size = sizeof(inarg);
- req->in.args[0].value = &inarg;
- req->in.args[1].size = count;
- req->in.args[1].value = buf;
- req->out.numargs = 1;
- req->out.args[0].size = sizeof(outarg);
- req->out.args[0].value = &outarg;
- request_send(fc, req);
- res = req->out.h.error;
- if (!res) {
- if (outarg.size > count)
- return -EPROTO;
- else
- return outarg.size;
- }
- else
- return res;
-}
-
-static int write_page_block(struct inode *inode, struct page *page)
+static int fuse_writepage(struct page *page)
{
- struct fuse_conn *fc = INO_FC(inode);
- struct fuse_inode *fi = INO_FI(inode);
- char *buffer;
- ssize_t res;
- loff_t pos;
+ int err;
unsigned count;
- struct fuse_req *req;
+ struct inode *inode = page->mapping->host;
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ struct fuse_inode *fi = get_fuse_inode(inode);
+ struct fuse_req *req = fuse_get_request_nonint(fc);
- req = fuse_get_request(fc);
- if (!req)
- return -ERESTARTSYS;
-
down_read(&fi->write_sem);
count = get_write_count(inode, page);
- res = 0;
+ err = 0;
if (count) {
- struct fuse_file *ff;
- BUG_ON(list_empty(&fi->write_files));
- ff = list_entry(fi->write_files.next, struct fuse_file, ff_list);
- pos = ((loff_t) page->index << PAGE_CACHE_SHIFT);
- buffer = kmap(page);
- res = fuse_send_writepage(req, ff, inode, buffer, pos, count);
- if (res >= 0) {
- if (res < count) {
- printk("fuse: short write\n");
- res = -EPROTO;
- } else
- res = 0;
- }
+ struct fuse_file *ff = get_write_file(fi);
+ loff_t pos = ((loff_t) page->index << PAGE_SHIFT);
+
+ fuse_write_init(req, ff, inode, pos, count, 1);
+ req->num_pages = 1;
+ req->pages[0] = page;
+ request_send(fc, req);
+ err = req->out.h.error;
+ if (!err && req->misc.write.out.size != count)
+ err = -EPROTO;
}
up_read(&fi->write_sem);
fuse_put_request(fc, req);
- kunmap(page);
- if (res)
+ if (err)
SetPageError(page);
- return res;
-}
-
-static int fuse_writepage(struct page *page)
-{
- int err = write_page_block(page->mapping->host, page);
unlock_page(page);
return err;
}
@@ -826,15 +704,29 @@ static int fuse_commit_write(struct file *file, struct page *page,
unsigned offset, unsigned to)
{
int err;
+ unsigned count = to - offset;
struct inode *inode = page->mapping->host;
+ struct fuse_file *ff = file->private_data;
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ struct fuse_req *req = fuse_get_request(fc);
+ loff_t pos = ((loff_t) page->index << PAGE_SHIFT) + offset;
+ if (!req)
+ return -ERESTARTSYS;
- err = write_buffer(inode, file, page, offset, to - offset);
+ fuse_write_init(req, ff, inode, pos, count, 0);
+ req->num_pages = 1;
+ req->pages[0] = page;
+ req->page_offset = offset;
+ request_send(fc, req);
+ err = req->out.h.error;
+ if (!err && req->misc.write.out.size != count)
+ err = -EPROTO;
if (!err) {
- loff_t pos = (page->index << PAGE_CACHE_SHIFT) + to;
+ pos += count;
if (pos > i_size_read(inode))
i_size_write(inode, pos);
- if (offset == 0 && to == PAGE_CACHE_SIZE) {
+ if (offset == 0 && to == PAGE_SIZE) {
#ifdef KERNEL_2_6
clear_page_dirty(page);
#else
@@ -842,8 +734,8 @@ static int fuse_commit_write(struct file *file, struct page *page,
#endif
SetPageUptodate(page);
}
-
}
+ fuse_put_request(fc, req);
return err;
}
@@ -851,49 +743,44 @@ static ssize_t fuse_direct_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
struct inode *inode = file->f_dentry->d_inode;
- struct fuse_conn *fc = INO_FC(inode);
+ struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_file *ff = file->private_data;
- char *tmpbuf;
- ssize_t res = 0;
loff_t pos = *ppos;
- struct fuse_req *req;
- size_t max_write = min(fc->max_write, (unsigned) PAGE_SIZE);
-
- req = fuse_get_request(fc);
+ ssize_t res = 0;
+ struct fuse_req *req = fuse_get_request(fc);
if (!req)
return -ERESTARTSYS;
- tmpbuf = (char *) __get_free_page(GFP_KERNEL);
- if (!tmpbuf) {
- fuse_put_request(fc, req);
- return -ENOMEM;
- }
-
while (count) {
- size_t nbytes = min(max_write, count);
- ssize_t res1;
- if (copy_from_user(tmpbuf, buf, nbytes)) {
- res = -EFAULT;
+ unsigned ntmp;
+ unsigned nwritten;
+ size_t nbytes = min(count, fc->max_write);
+ int err = fuse_get_user_pages(req, buf, nbytes, 0);
+ if (err) {
+ res = err;
break;
}
- res1 = fuse_send_write(req, ff, inode, tmpbuf, pos, nbytes);
- if (res1 < 0) {
- res = res1;
+ ntmp = (req->num_pages << PAGE_SHIFT) - req->page_offset;
+ nbytes = min(nbytes, ntmp);
+ fuse_write_init(req, ff, inode, pos, nbytes, 0);
+ request_send(fc, req);
+ fuse_release_user_pages(req, 0);
+ if (req->out.h.error) {
+ if (!res)
+ res = req->out.h.error;
break;
}
- res += res1;
- count -= res1;
- buf += res1;
- pos += res1;
- if (res1 < nbytes)
+ nwritten = req->misc.write.out.size;
+ count -= nwritten;
+ res += nwritten;
+ pos += nwritten;
+ buf += nwritten;
+ if (nwritten != nbytes)
break;
-
if (count)
fuse_reset_request(req);
}
- free_page((unsigned long) tmpbuf);
fuse_put_request(fc, req);
-
if (res > 0) {
if (pos > i_size_read(inode))
i_size_write(inode, pos);
@@ -907,7 +794,7 @@ static ssize_t fuse_file_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
struct inode *inode = file->f_dentry->d_inode;
- struct fuse_conn *fc = INO_FC(inode);
+ struct fuse_conn *fc = get_fuse_conn(inode);
if (fc->flags & FUSE_DIRECT_IO) {
ssize_t res;
@@ -915,6 +802,7 @@ static ssize_t fuse_file_write(struct file *file, const char __user *buf,
res = fuse_direct_write(file, buf, count, ppos);
up(&inode->i_sem);
return res;
+ return -EPERM;
}
else
return generic_file_write(file, buf, count, ppos);
@@ -923,14 +811,14 @@ static ssize_t fuse_file_write(struct file *file, const char __user *buf,
static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma)
{
struct inode *inode = file->f_dentry->d_inode;
- struct fuse_conn *fc = INO_FC(inode);
+ struct fuse_conn *fc = get_fuse_conn(inode);
if (fc->flags & FUSE_DIRECT_IO)
return -ENODEV;
else {
if ((vma->vm_flags & (VM_WRITE | VM_SHARED)) ==
(VM_WRITE | VM_SHARED)) {
- struct fuse_inode *fi = INO_FI(inode);
+ struct fuse_inode *fi = get_fuse_inode(inode);
struct fuse_file *ff = file->private_data;
if (!user_mmap && current->uid != 0)
diff --git a/kernel/fuse_i.h b/kernel/fuse_i.h
index 37d8cad..b9dd4b8 100644
--- a/kernel/fuse_i.h
+++ b/kernel/fuse_i.h
@@ -69,15 +69,13 @@
doing the mount will be allowed to access the filesystem */
#define FUSE_ALLOW_OTHER (1 << 1)
-/** If the FUSE_KERNEL_CACHE flag is given, then files will be cached
- until the INVALIDATE operation is invoked */
+/** If the FUSE_KERNEL_CACHE flag is given, then cached data will not
+ be flushed on open */
#define FUSE_KERNEL_CACHE (1 << 2)
#ifndef KERNEL_2_6
/** Allow FUSE to combine reads into 64k chunks. This is useful if
- the filesystem is better at handling large chunks. NOTE: in
- current implementation the raw throughput is worse for large reads
- than for small. */
+ the filesystem is better at handling large chunks */
#define FUSE_LARGE_READ (1 << 31)
#endif
/** Bypass the page cache for read and write operations */
@@ -89,12 +87,22 @@
/** FUSE specific inode data */
struct fuse_inode {
+ /** Unique ID, which identifies the inode between userspace
+ * and kernel */
unsigned long nodeid;
+
+ /** The request used for sending the FORGET message */
struct fuse_req *forget_req;
+
+ /** Semaphore protects the 'write_files' list, and against
+ truncate racing with async writeouts */
struct rw_semaphore write_sem;
+
+ /** Time in jiffies until the file attributes are valid */
unsigned long i_time;
- /* Files which can provide file handles in writepage.
- Protected by write_sem */
+
+ /* List of fuse_files which can provide file handles in
+ * writepage, protected by write_sem */
struct list_head write_files;
};
@@ -113,8 +121,16 @@ struct fuse_in_arg {
/** The request input */
struct fuse_in {
+ /** The request header */
struct fuse_in_header h;
+
+ /** True if the data for the last argument is in req->pages */
+ unsigned argpages:1;
+
+ /** Number of arguments */
unsigned numargs;
+
+ /** Array of arguments */
struct fuse_in_arg args[3];
};
@@ -265,13 +281,34 @@ struct fuse_getdir_out_i {
void *file; /* Used by kernel only */
};
+static inline struct fuse_conn **get_fuse_conn_super_p(struct super_block *sb)
+{
#ifdef KERNEL_2_6
-#define SB_FC(sb) ((sb)->s_fs_info)
+ return (struct fuse_conn **) &sb->s_fs_info;
#else
-#define SB_FC(sb) ((sb)->u.generic_sbp)
+ return (struct fuse_conn **) &sb->u.generic_sbp;
#endif
-#define INO_FC(inode) SB_FC((inode)->i_sb)
-#define INO_FI(i) ((struct fuse_inode *) (((struct inode *)(i))+1))
+}
+
+static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb)
+{
+ return *get_fuse_conn_super_p(sb);
+}
+
+static inline struct fuse_conn *get_fuse_conn(struct inode *inode)
+{
+ return get_fuse_conn_super(inode->i_sb);
+}
+
+static inline struct fuse_inode *get_fuse_inode(struct inode *inode)
+{
+ return (struct fuse_inode *) (&inode[1]);
+}
+
+static inline unsigned long get_node_id(struct inode *inode)
+{
+ return get_fuse_inode(inode)->nodeid;
+}
/** Device operations */
extern struct file_operations fuse_dev_operations;
diff --git a/kernel/inode.c b/kernel/inode.c
index 0a70d02..e0a3902 100644
--- a/kernel/inode.c
+++ b/kernel/inode.c
@@ -65,7 +65,7 @@ static struct inode *fuse_alloc_inode(struct super_block *sb)
inode->u.generic_ip = NULL;
#endif
- fi = INO_FI(inode);
+ fi = get_fuse_inode(inode);
memset(fi, 0, sizeof(*fi));
fi->forget_req = fuse_request_alloc();
if (!fi->forget_req) {
@@ -80,7 +80,7 @@ static struct inode *fuse_alloc_inode(struct super_block *sb)
static void fuse_destroy_inode(struct inode *inode)
{
- struct fuse_inode *fi = INO_FI(inode);
+ struct fuse_inode *fi = get_fuse_inode(inode);
BUG_ON(!list_empty(&fi->write_files));
if (fi->forget_req)
fuse_request_free(fi->forget_req);
@@ -107,10 +107,9 @@ void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req,
static void fuse_clear_inode(struct inode *inode)
{
- struct fuse_conn *fc = INO_FC(inode);
-
+ struct fuse_conn *fc = get_fuse_conn(inode);
if (fc) {
- struct fuse_inode *fi = INO_FI(inode);
+ struct fuse_inode *fi = get_fuse_inode(inode);
fuse_send_forget(fc, fi->forget_req, fi->nodeid, inode->i_version);
fi->forget_req = NULL;
}
@@ -118,7 +117,7 @@ static void fuse_clear_inode(struct inode *inode)
static void fuse_put_super(struct super_block *sb)
{
- struct fuse_conn *fc = SB_FC(sb);
+ struct fuse_conn *fc = get_fuse_conn_super(sb);
down(&fc->sb_sem);
spin_lock(&fuse_lock);
@@ -129,7 +128,7 @@ static void fuse_put_super(struct super_block *sb)
/* Flush all readers on this fs */
wake_up_all(&fc->waitq);
fuse_release_conn(fc);
- SB_FC(sb) = NULL;
+ *get_fuse_conn_super_p(sb) = NULL;
spin_unlock(&fuse_lock);
}
@@ -148,7 +147,7 @@ static void convert_fuse_statfs(struct kstatfs *stbuf, struct fuse_kstatfs *attr
static int fuse_statfs(struct super_block *sb, struct kstatfs *buf)
{
- struct fuse_conn *fc = SB_FC(sb);
+ struct fuse_conn *fc = get_fuse_conn_super(sb);
struct fuse_req *req;
struct fuse_statfs_out outarg;
int err;
@@ -289,7 +288,7 @@ static int parse_fuse_opt(char *opt, struct fuse_mount_data *d)
static int fuse_show_options(struct seq_file *m, struct vfsmount *mnt)
{
- struct fuse_conn *fc = SB_FC(mnt->mnt_sb);
+ struct fuse_conn *fc = get_fuse_conn_super(mnt->mnt_sb);
seq_printf(m, ",uid=%u", fc->uid);
if (fc->flags & FUSE_DEFAULT_PERMISSIONS)
@@ -431,7 +430,6 @@ static int fuse_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
int connectable)
{
struct inode *inode = dentry->d_inode;
- struct fuse_inode *fi = INO_FI(inode);
int len = *max_len;
int type = 1;
@@ -439,16 +437,14 @@ static int fuse_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
return 255;
len = 2;
- fh[0] = fi->nodeid;
+ fh[0] = get_fuse_inode(inode)->nodeid;
fh[1] = inode->i_generation;
if (connectable && !S_ISDIR(inode->i_mode)) {
struct inode *parent;
- struct fuse_inode *parent_fi;
spin_lock(&dentry->d_lock);
parent = dentry->d_parent->d_inode;
- parent_fi = INO_FI(parent);
- fh[2] = parent_fi->nodeid;
+ fh[2] = get_fuse_inode(parent)->nodeid;
fh[3] = parent->i_generation;
spin_unlock(&dentry->d_lock);
len = 4;
@@ -517,7 +513,7 @@ static int fuse_read_super(struct super_block *sb, void *data, int silent)
#endif
fc->max_write = FUSE_MAX_IN / 2;
- SB_FC(sb) = fc;
+ *get_fuse_conn_super_p(sb) = fc;
root = get_root_inode(sb, d.rootmode);
if (root == NULL) {
@@ -540,7 +536,7 @@ static int fuse_read_super(struct super_block *sb, void *data, int silent)
up(&fc->sb_sem);
fuse_release_conn(fc);
spin_unlock(&fuse_lock);
- SB_FC(sb) = NULL;
+ *get_fuse_conn_super_p(sb) = NULL;
return -EINVAL;
}