aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/file.c')
-rw-r--r--kernel/file.c284
1 files changed, 142 insertions, 142 deletions
diff --git a/kernel/file.c b/kernel/file.c
index 2067bd7..128c1b8 100644
--- a/kernel/file.c
+++ b/kernel/file.c
@@ -17,7 +17,9 @@
#ifndef KERNEL_2_6
#define PageUptodate(page) Page_Uptodate(page)
#ifndef NO_MM
+#ifndef filemap_fdatawrite
#define filemap_fdatawrite filemap_fdatasync
+#endif
#else
#define filemap_fdatawrite do {} while (0)
#endif
@@ -26,8 +28,7 @@
static int fuse_open(struct inode *inode, struct file *file)
{
struct fuse_conn *fc = INO_FC(inode);
- struct fuse_in in = FUSE_IN_INIT;
- struct fuse_out out = FUSE_OUT_INIT;
+ struct fuse_req *req;
struct fuse_open_in inarg;
int err;
@@ -43,52 +44,50 @@ static int fuse_open(struct inode *inode, struct file *file)
return err;
}
+ req = fuse_get_request(fc);
+ if (!req)
+ return -ERESTARTSYS;
+
memset(&inarg, 0, sizeof(inarg));
inarg.flags = file->f_flags & ~O_EXCL;
-
- in.h.opcode = FUSE_OPEN;
- in.h.ino = inode->i_ino;
- in.numargs = 1;
- in.args[0].size = sizeof(inarg);
- in.args[0].value = &inarg;
- request_send(fc, &in, &out);
- if (!out.h.error && !(fc->flags & FUSE_KERNEL_CACHE)) {
+ req->in.h.opcode = FUSE_OPEN;
+ req->in.h.ino = inode->i_ino;
+ req->in.numargs = 1;
+ req->in.args[0].size = sizeof(inarg);
+ req->in.args[0].value = &inarg;
+ request_send(fc, req);
+ err = req->out.h.error;
+ if (!err && !(fc->flags & FUSE_KERNEL_CACHE)) {
#ifdef KERNEL_2_6
invalidate_inode_pages(inode->i_mapping);
#else
invalidate_inode_pages(inode);
#endif
}
-
- return out.h.error;
+ fuse_put_request(fc, req);
+ return err;
}
static int fuse_release(struct inode *inode, struct file *file)
{
struct fuse_conn *fc = INO_FC(inode);
- struct fuse_in *in = NULL;
- struct fuse_open_in *inarg = NULL;
- unsigned int s = sizeof(struct fuse_in) + sizeof(struct fuse_open_in);
-
+ struct fuse_open_in *inarg;
+ struct fuse_req *req;
+
if (file->f_mode & FMODE_WRITE)
filemap_fdatawrite(inode->i_mapping);
- in = kmalloc(s, GFP_NOFS);
- if (!in)
- return -ENOMEM;
- memset(in, 0, s);
- inarg = (struct fuse_open_in *) (in + 1);
+ req = fuse_get_request_nonint(fc);
+ inarg = &req->misc.open_in;
inarg->flags = file->f_flags & ~O_EXCL;
-
- in->h.opcode = FUSE_RELEASE;
- in->h.ino = inode->i_ino;
- in->numargs = 1;
- in->args[0].size = sizeof(struct fuse_open_in);
- in->args[0].value = inarg;
- if (!request_send_noreply(fc, in))
- return 0;
-
- kfree(in);
+ req->in.h.opcode = FUSE_RELEASE;
+ req->in.h.ino = inode->i_ino;
+ req->in.numargs = 1;
+ req->in.args[0].size = sizeof(struct fuse_open_in);
+ req->in.args[0].value = inarg;
+ request_send_noreply(fc, req);
+
+ /* Return value is ignored by VFS */
return 0;
}
@@ -96,49 +95,58 @@ static int fuse_flush(struct file *file)
{
struct inode *inode = file->f_dentry->d_inode;
struct fuse_conn *fc = INO_FC(inode);
- struct fuse_in in = FUSE_IN_INIT;
- struct fuse_out out = FUSE_OUT_INIT;
+ struct fuse_req *req;
+ int err;
if (fc->no_flush)
return 0;
- in.h.opcode = FUSE_FLUSH;
- in.h.ino = inode->i_ino;
- request_send(fc, &in, &out);
- if (out.h.error == -ENOSYS) {
+ req = fuse_get_request(fc);
+ if (!req)
+ return -EINTR;
+
+ req->in.h.opcode = FUSE_FLUSH;
+ req->in.h.ino = inode->i_ino;
+ request_send(fc, req);
+ err = req->out.h.error;
+ if (err == -ENOSYS) {
fc->no_flush = 1;
- return 0;
+ err = 0;
}
- else
- return out.h.error;
+ fuse_put_request(fc, req);
+ return err;
}
static int fuse_fsync(struct file *file, struct dentry *de, int datasync)
{
struct inode *inode = de->d_inode;
struct fuse_conn *fc = INO_FC(inode);
- struct fuse_in in = FUSE_IN_INIT;
- struct fuse_out out = FUSE_OUT_INIT;
+ struct fuse_req *req;
struct fuse_fsync_in inarg;
+ int err;
if (fc->no_fsync)
return 0;
+ req = fuse_get_request(fc);
+ if (!req)
+ return -ERESTARTSYS;
+
memset(&inarg, 0, sizeof(inarg));
inarg.datasync = datasync;
-
- in.h.opcode = FUSE_FSYNC;
- in.h.ino = inode->i_ino;
- in.numargs = 1;
- in.args[0].size = sizeof(inarg);
- in.args[0].value = &inarg;
- request_send(fc, &in, &out);
-
- if (out.h.error == -ENOSYS) {
+ req->in.h.opcode = FUSE_FSYNC;
+ req->in.h.ino = inode->i_ino;
+ req->in.numargs = 1;
+ req->in.args[0].size = sizeof(inarg);
+ req->in.args[0].value = &inarg;
+ request_send(fc, req);
+ err = req->out.h.error;
+ if (err == -ENOSYS) {
fc->no_fsync = 1;
- return 0;
+ err = 0;
}
- return out.h.error;
+ fuse_put_request(fc, req);
+ return err;
/* FIXME: need to ensure, that all write requests issued
before this request are completed. Should userspace take
@@ -149,40 +157,42 @@ 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_in in = FUSE_IN_INIT;
- struct fuse_out out = FUSE_OUT_INIT;
+ struct fuse_req *req;
struct fuse_read_in inarg;
char *buffer;
+ int err;
buffer = kmap(page);
+ req = fuse_get_request(fc);
+ if (!req)
+ return -ERESTARTSYS;
+
memset(&inarg, 0, sizeof(inarg));
inarg.offset = (unsigned long long) page->index << PAGE_CACHE_SHIFT;
inarg.size = PAGE_CACHE_SIZE;
-
- in.h.opcode = FUSE_READ;
- in.h.ino = inode->i_ino;
- in.numargs = 1;
- in.args[0].size = sizeof(inarg);
- in.args[0].value = &inarg;
- out.argvar = 1;
- out.numargs = 1;
- out.args[0].size = PAGE_CACHE_SIZE;
- out.args[0].value = buffer;
-
- request_send(fc, &in, &out);
- if (!out.h.error) {
- size_t outsize = out.args[0].size;
+ req->in.h.opcode = FUSE_READ;
+ req->in.h.ino = inode->i_ino;
+ req->in.numargs = 1;
+ req->in.args[0].size = sizeof(inarg);
+ req->in.args[0].value = &inarg;
+ req->out.argvar = 1;
+ req->out.numargs = 1;
+ req->out.args[0].size = PAGE_CACHE_SIZE;
+ req->out.args[0].value = buffer;
+ request_send(fc, req);
+ err = req->out.h.error;
+ if (!err) {
+ size_t outsize = req->out.args[0].size;
if (outsize < PAGE_CACHE_SIZE)
memset(buffer + outsize, 0, PAGE_CACHE_SIZE - outsize);
flush_dcache_page(page);
SetPageUptodate(page);
}
-
+ fuse_put_request(fc, req);
kunmap(page);
unlock_page(page);
-
- return out.h.error;
+ return err;
}
static int fuse_is_block_uptodate(struct address_space *mapping,
@@ -255,33 +265,34 @@ static int fuse_file_read_block(struct inode *inode, char *bl_buf,
size_t bl_index)
{
struct fuse_conn *fc = INO_FC(inode);
- struct fuse_in in = FUSE_IN_INIT;
- struct fuse_out out = FUSE_OUT_INIT;
+ struct fuse_req *req = fuse_get_request(fc);
struct fuse_read_in inarg;
+ int err;
+
+ if (!req)
+ return -ERESTARTSYS;
memset(&inarg, 0, sizeof(inarg));
inarg.offset = bl_index << FUSE_BLOCK_SHIFT;
inarg.size = FUSE_BLOCK_SIZE;
-
- in.h.opcode = FUSE_READ;
- in.h.ino = inode->i_ino;
- in.numargs = 1;
- in.args[0].size = sizeof(inarg);
- in.args[0].value = &inarg;
- out.argvar = 1;
- out.numargs = 1;
- out.args[0].size = FUSE_BLOCK_SIZE;
- out.args[0].value = bl_buf;
-
- request_send(fc, &in, &out);
-
- if (!out.h.error) {
- size_t outsize = out.args[0].size;
+ req->in.h.opcode = FUSE_READ;
+ req->in.h.ino = inode->i_ino;
+ req->in.numargs = 1;
+ req->in.args[0].size = sizeof(inarg);
+ req->in.args[0].value = &inarg;
+ req->out.argvar = 1;
+ req->out.numargs = 1;
+ req->out.args[0].size = FUSE_BLOCK_SIZE;
+ req->out.args[0].value = bl_buf;
+ request_send(fc, req);
+ err = req->out.h.error;
+ if (!err) {
+ size_t outsize = req->out.args[0].size;
if (outsize < FUSE_BLOCK_SIZE)
memset(bl_buf + outsize, 0, FUSE_BLOCK_SIZE - outsize);
}
-
- return out.h.error;
+ fuse_put_request(fc, req);
+ return err;
}
static void fuse_file_bigread(struct address_space *mapping,
@@ -296,7 +307,7 @@ static void fuse_file_bigread(struct address_space *mapping,
while (bl_index <= bl_end_index) {
int res;
- char *bl_buf = kmalloc(FUSE_BLOCK_SIZE, GFP_NOFS);
+ char *bl_buf = kmalloc(FUSE_BLOCK_SIZE, GFP_KERNEL);
if (!bl_buf)
break;
res = fuse_is_block_uptodate(mapping, inode, bl_index);
@@ -326,31 +337,35 @@ static int write_buffer(struct inode *inode, struct page *page,
unsigned offset, size_t count)
{
struct fuse_conn *fc = INO_FC(inode);
- struct fuse_in in = FUSE_IN_INIT;
- struct fuse_out out = FUSE_OUT_INIT;
+ struct fuse_req *req;
struct fuse_write_in inarg;
char *buffer;
+ int err;
buffer = kmap(page);
+ req = fuse_get_request(fc);
+ if (!req)
+ return -ERESTARTSYS;
+
memset(&inarg, 0, sizeof(inarg));
inarg.offset = ((unsigned long long) page->index << PAGE_CACHE_SHIFT) +
offset;
inarg.size = count;
-
- in.h.opcode = FUSE_WRITE;
- in.h.ino = inode->i_ino;
- in.numargs = 2;
- in.args[0].size = sizeof(inarg);
- in.args[0].value = &inarg;
- in.args[1].size = count;
- in.args[1].value = buffer + offset;
- request_send(fc, &in, &out);
+ req->in.h.opcode = FUSE_WRITE;
+ req->in.h.ino = inode->i_ino;
+ 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 = buffer + offset;
+ request_send(fc, req);
+ err = req->out.h.error;
+ fuse_put_request(fc, req);
kunmap(page);
- if (out.h.error)
+ if (err)
SetPageError(page);
-
- return out.h.error;
+ return err;
}
static int get_write_count(struct inode *inode, struct page *page)
@@ -372,15 +387,14 @@ static int get_write_count(struct inode *inode, struct page *page)
#ifdef KERNEL_2_6
-static void write_buffer_end(struct fuse_conn *fc, struct fuse_in *in,
- struct fuse_out *out, void *_page)
+static void write_buffer_end(struct fuse_conn *fc, struct fuse_req *req)
{
- struct page *page = (struct page *) _page;
+ struct page *page = (struct page *) req->data;
lock_page(page);
- if (out->h.error) {
+ if (req->out.h.error) {
SetPageError(page);
- if (out->h.error == -ENOSPC)
+ if (req->out.h.error == -ENOSPC)
set_bit(AS_ENOSPC, &page->mapping->flags);
else
set_bit(AS_EIO, &page->mapping->flags);
@@ -388,48 +402,34 @@ static void write_buffer_end(struct fuse_conn *fc, struct fuse_in *in,
end_page_writeback(page);
kunmap(page);
unlock_page(page);
- kfree(in);
+ fuse_put_request(fc, req);
}
static int write_buffer_nonblock(struct inode *inode, struct page *page,
unsigned offset, size_t count)
{
- int err;
struct fuse_conn *fc = INO_FC(inode);
- struct fuse_in *in = NULL;
- struct fuse_out *out = NULL;
+ struct fuse_req *req;
struct fuse_write_in *inarg = NULL;
char *buffer;
- unsigned int s = sizeof(struct fuse_in) + sizeof(struct fuse_out) +
- sizeof(struct fuse_write_in);
-
- in = kmalloc(s, GFP_NOFS);
- if (!in)
- return -ENOMEM;
- memset(in, 0, s);
- out = (struct fuse_out *)(in + 1);
- inarg = (struct fuse_write_in *)(out + 1);
-
- buffer = kmap(page);
+ req = fuse_get_request_nonblock(fc);
+ if (!req)
+ return -EWOULDBLOCK;
+
+ inarg = &req->misc.write_in;
+ buffer = kmap(page);
inarg->offset = ((unsigned long long) page->index << PAGE_CACHE_SHIFT) + offset;
inarg->size = count;
-
- in->h.opcode = FUSE_WRITE;
- in->h.ino = inode->i_ino;
- in->numargs = 2;
- in->args[0].size = sizeof(struct fuse_write_in);
- in->args[0].value = inarg;
- in->args[1].size = count;
- in->args[1].value = buffer + offset;
- err = request_send_nonblock(fc, in, out, write_buffer_end, page);
- if (err) {
- if (err != -EWOULDBLOCK)
- SetPageError(page);
- kunmap(page);
- kfree(in);
- }
- return err;
+ req->in.h.opcode = FUSE_WRITE;
+ req->in.h.ino = inode->i_ino;
+ 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 + offset;
+ request_send_nonblock(fc, req, write_buffer_end, page);
+ return 0;
}
static int fuse_writepage(struct page *page, struct writeback_control *wbc)