From 83a074415d72e5dae0a7836fbe1f8b6b8cd3a098 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Tue, 30 Nov 2004 18:25:20 +0000 Subject: [PATCH] cleanup --- ChangeLog | 4 + kernel/dev.c | 52 +++++-- kernel/dir.c | 17 +- kernel/file.c | 401 ++++++++++++++++++------------------------------ kernel/fuse_i.h | 61 ++++---- kernel/inode.c | 10 +- kernel/util.c | 4 +- 7 files changed, 234 insertions(+), 315 deletions(-) diff --git a/ChangeLog b/ChangeLog index c9a090d..441669b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2004-11-30 Miklos Szeredi + + * kernel: clean up reading functions + 2004-11-29 Miklos Szeredi * kernel: make readpage() uninterruptible diff --git a/kernel/dev.c b/kernel/dev.c index 0eebd31..aca602f 100644 --- a/kernel/dev.c +++ b/kernel/dev.c @@ -17,6 +17,7 @@ #include #endif #include +#include #include static kmem_cache_t *fuse_req_cachep; @@ -169,10 +170,9 @@ void request_send_noreply(struct fuse_conn *fc, struct fuse_req *req) } void request_send_async(struct fuse_conn *fc, struct fuse_req *req, - fuse_reqend_t end, void *data) + fuse_reqend_t end) { req->end = end; - req->data = data; req->isreply = 1; spin_lock(&fuse_lock); @@ -289,7 +289,7 @@ static ssize_t fuse_dev_read(struct file *file, char __user *buf, return ret; } -static struct fuse_req *request_find(struct fuse_conn *fc, unsigned int unique) +static struct fuse_req *request_find(struct fuse_conn *fc, unsigned unique) { struct list_head *entry; struct fuse_req *req = NULL; @@ -312,6 +312,37 @@ 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) +{ + 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); + 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; + nbytes -= count; + buf += count; + count = min(nbytes, (unsigned) PAGE_CACHE_SIZE); + page_offset = 0; + } + return 0; +} + static inline int copy_out_one(struct fuse_out_arg *arg, const char __user **srcp, size_t *srclenp, int allowvar) @@ -346,9 +377,10 @@ static inline int copy_out_args(struct fuse_req *req, const char __user *buf, nbytes -= sizeof(struct fuse_out_header); if (!out->h.error) { - if (req->copy_out) - return req->copy_out(req, buf, nbytes); - else { + 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; @@ -489,17 +521,17 @@ static ssize_t fuse_dev_write(struct file *file, const char __user *buf, /* Unlocks fuse_lock: */ request_end(fc, req); - out: + out: if (!err) return nbytes; else return err; } -static unsigned int fuse_dev_poll(struct file *file, poll_table *wait) +static unsigned fuse_dev_poll(struct file *file, poll_table *wait) { struct fuse_conn *fc = fuse_get_conn(file); - unsigned int mask = POLLOUT | POLLWRNORM; + unsigned mask = POLLOUT | POLLWRNORM; if (!fc) return -ENODEV; @@ -605,7 +637,7 @@ static void fuse_version_clean(void) static struct proc_dir_entry *proc_fs_fuse; static int read_version(char *page, char **start, off_t off, int count, - int *eof, void *data) + int *eof, void *data) { char *s = page; s += sprintf(s, "%i.%i\n", FUSE_KERNEL_VERSION, diff --git a/kernel/dir.c b/kernel/dir.c index 19834b4..412ffc8 100644 --- a/kernel/dir.c +++ b/kernel/dir.c @@ -389,7 +389,7 @@ static int fuse_symlink(struct inode *dir, struct dentry *entry, struct fuse_inode *fi = INO_FI(dir); struct fuse_req *req; struct fuse_entry_out outarg; - unsigned int len = strlen(link) + 1; + unsigned len = strlen(link) + 1; int err; if (len > FUSE_SYMLINK_MAX) @@ -619,7 +619,7 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd) #ifdef KERNEL_2_6_10_PLUS err = generic_permission(inode, mask, NULL); #else - err = vfs_permission(inode, mask); + err = vfs_permission(inode, mask); #endif } @@ -659,7 +659,7 @@ static int parse_dirfile(char *buf, size_t nbytes, struct file *file, break; over = filldir(dstbuf, dirent->name, dirent->namelen, - file->f_pos, dirent->ino, dirent->type); + file->f_pos, dirent->ino, dirent->type); if (over) break; @@ -820,11 +820,10 @@ static int fuse_dir_release(struct inode *inode, struct file *file) return 0; } -static unsigned int iattr_to_fattr(struct iattr *iattr, - struct fuse_attr *fattr) +static unsigned iattr_to_fattr(struct iattr *iattr, struct fuse_attr *fattr) { - unsigned int ivalid = iattr->ia_valid; - unsigned int fvalid = 0; + unsigned ivalid = iattr->ia_valid; + unsigned fvalid = 0; memset(fattr, 0, sizeof(*fattr)); @@ -962,7 +961,7 @@ static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry, } static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, - struct nameidata *nd) + struct nameidata *nd) { struct inode *inode; int err = fuse_lookup_iget(dir, entry, &inode); @@ -993,7 +992,7 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry) } static int fuse_mknod_2_4(struct inode *dir, struct dentry *entry, int mode, - int rdev) + int rdev) { return fuse_mknod(dir, entry, mode, rdev); } diff --git a/kernel/file.c b/kernel/file.c index 0676135..2d15c5b 100644 --- a/kernel/file.c +++ b/kernel/file.c @@ -5,6 +5,7 @@ This program can be distributed under the terms of the GNU GPL. See the file COPYING. */ + #include "fuse_i.h" #include @@ -221,104 +222,58 @@ static int fuse_fsync(struct file *file, struct dentry *de, int datasync) return err; } -static ssize_t fuse_send_read(struct file *file, struct inode *inode, - char *buf, loff_t pos, size_t count) +static void fuse_read_init(struct fuse_req *req, struct file *file, + struct inode *inode, loff_t pos, size_t count) { - struct fuse_conn *fc = INO_FC(inode); struct fuse_inode *fi = INO_FI(inode); struct fuse_file *ff = file->private_data; - struct fuse_req *req; - struct fuse_read_in inarg; - ssize_t res; - - req = fuse_get_request_nonint(fc); - memset(&inarg, 0, sizeof(inarg)); - inarg.fh = ff->fh; - inarg.offset = pos; - inarg.size = count; + struct fuse_read_in *inarg = &req->misc.read_in; + + inarg->fh = ff->fh; + inarg->offset = pos; + inarg->size = count; req->in.h.opcode = FUSE_READ; req->in.h.nodeid = fi->nodeid; req->in.numargs = 1; - req->in.args[0].size = sizeof(inarg); - req->in.args[0].value = &inarg; + req->in.args[0].size = sizeof(struct fuse_read_in); + req->in.args[0].value = inarg; req->out.argvar = 1; req->out.numargs = 1; req->out.args[0].size = count; - req->out.args[0].value = buf; - request_send(fc, req); - res = req->out.h.error; - if (!res) - res = req->out.args[0].size; - fuse_put_request(fc, req); - return res; } static int fuse_readpage(struct file *file, struct page *page) { struct inode *inode = page->mapping->host; - char *buffer; - ssize_t res; - loff_t pos; - - pos = (loff_t) page->index << PAGE_CACHE_SHIFT; - buffer = kmap(page); - res = fuse_send_read(file, inode, buffer, pos, PAGE_CACHE_SIZE); - if (res >= 0) { - if (res < PAGE_CACHE_SIZE) - memset(buffer + res, 0, PAGE_CACHE_SIZE - res); - flush_dcache_page(page); + struct fuse_conn *fc = INO_FC(inode); + struct fuse_req *req = fuse_get_request_nonint(fc); + loff_t pos = (loff_t) page->index << PAGE_CACHE_SHIFT; + int err; + + fuse_read_init(req, file, inode, pos, PAGE_CACHE_SIZE); + req->out.argpages = 1; + req->out.page_zeroing = 1; + req->num_pages = 1; + req->pages[0] = page; + request_send(fc, req); + err = req->out.h.error; + fuse_put_request(fc, req); + if (!err) SetPageUptodate(page); - res = 0; - } - kunmap(page); unlock_page(page); - return res; + return err; } #ifdef KERNEL_2_6 -static int read_pages_copyout(struct fuse_req *req, const char __user *buf, - size_t nbytes) +static void read_pages_end(struct fuse_conn *fc, struct fuse_req *req) { unsigned i; - unsigned long base_index = req->pages[0]->index; for (i = 0; i < req->num_pages; i++) { struct page *page = req->pages[i]; - unsigned long offset; - unsigned count; - char *tmpbuf; - int err; - - offset = (page->index - base_index) * PAGE_CACHE_SIZE; - if (offset >= nbytes) - count = 0; - else if (offset + PAGE_CACHE_SIZE <= nbytes) - count = PAGE_CACHE_SIZE; - else - count = nbytes - offset; - - tmpbuf = kmap(page); - err = 0; - if (count) - err = copy_from_user(tmpbuf, buf + offset, count); - if (count < PAGE_CACHE_SIZE) - memset(tmpbuf + count, 0, PAGE_CACHE_SIZE - count); - kunmap(page); - if (err) - return -EFAULT; - - flush_dcache_page(page); - SetPageUptodate(page); + if (!req->out.h.error) + SetPageUptodate(page); + unlock_page(page); } - return 0; -} - -static void read_pages_end(struct fuse_conn *fc, struct fuse_req *req) -{ - unsigned i; - - for (i = 0; i < req->num_pages; i++) - unlock_page(req->pages[i]); - fuse_put_request(fc, req); } @@ -326,28 +281,12 @@ static void fuse_send_readpages(struct fuse_req *req, struct file *file, struct inode *inode) { struct fuse_conn *fc = INO_FC(inode); - struct fuse_inode *fi = INO_FI(inode); - struct fuse_file *ff = file->private_data; - struct fuse_read_in *inarg; - loff_t pos; - unsigned numpages; - - pos = (loff_t) req->pages[0]->index << PAGE_CACHE_SHIFT; - /* Allow for holes between the pages */ - numpages = req->pages[req->num_pages - 1]->index + 1 - - req->pages[0]->index; - - inarg = &req->misc.read_in; - inarg->fh = ff->fh; - inarg->offset = pos; - inarg->size = numpages * PAGE_CACHE_SIZE; - req->in.h.opcode = FUSE_READ; - req->in.h.nodeid = fi->nodeid; - req->in.numargs = 1; - req->in.args[0].size = sizeof(struct fuse_read_in); - req->in.args[0].value = inarg; - req->copy_out = read_pages_copyout; - request_send_async(fc, req, read_pages_end, NULL); + loff_t pos = (loff_t) req->pages[0]->index << PAGE_CACHE_SHIFT; + size_t count = req->num_pages << PAGE_CACHE_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); } struct fuse_readpages_data { @@ -396,133 +335,105 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, return 0; } #else /* KERNEL_2_6 */ -static int fuse_is_block_uptodate(struct inode *inode, size_t bl_index) -{ - size_t index = bl_index << FUSE_BLOCK_PAGE_SHIFT; - size_t end_index = ((bl_index + 1) << FUSE_BLOCK_PAGE_SHIFT) - 1; - size_t file_end_index = i_size_read(inode) >> PAGE_CACHE_SHIFT; +#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 +#error FUSE_BLOCK_SHIFT too large +#endif - if (end_index > file_end_index) - end_index = file_end_index; +static int fuse_is_block_uptodate(struct inode *inode, unsigned start, + unsigned end) +{ + int index; - for (; index <= end_index; index++) { + for (index = start; index < end; index++) { struct page *page = find_get_page(inode->i_mapping, index); - if (!page) return 0; - if (!PageUptodate(page)) { page_cache_release(page); return 0; } - page_cache_release(page); } - return 1; } - -static int fuse_cache_block(struct inode *inode, char *bl_buf, - size_t bl_index) +static void fuse_file_read_block(struct fuse_req *req, struct file *file, + struct inode *inode, unsigned start, + unsigned end) { - size_t start_index = bl_index << FUSE_BLOCK_PAGE_SHIFT; - size_t end_index = ((bl_index + 1) << FUSE_BLOCK_PAGE_SHIFT) - 1; - size_t file_end_index = i_size_read(inode) >> PAGE_CACHE_SHIFT; - + struct fuse_conn *fc = INO_FC(inode); + loff_t pos; + size_t count; + int index; + int err = 1; int i; - if (end_index > file_end_index) - end_index = file_end_index; - - for (i = 0; start_index + i <= end_index; i++) { - size_t index = start_index + i; - struct page *page; - char *buffer; - - page = grab_cache_page(inode->i_mapping, index); + for (index = start; index < end; index++) { + struct page *page = grab_cache_page(inode->i_mapping, index); if (!page) - return -1; - - if (!PageUptodate(page)) { - buffer = kmap(page); - memcpy(buffer, bl_buf + i * PAGE_CACHE_SIZE, - PAGE_CACHE_SIZE); - flush_dcache_page(page); + goto out; + req->pages[req->num_pages++] = page; + } + pos = (loff_t) start << PAGE_CACHE_SHIFT; + count = req->num_pages << PAGE_CACHE_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); - kunmap(page); - } - unlock_page(page); page_cache_release(page); } - - return 0; -} - -static int fuse_file_read_block(struct file *file, struct inode *inode, - char *bl_buf, size_t bl_index) -{ - ssize_t res; - loff_t offset; - - offset = (loff_t) bl_index << FUSE_BLOCK_SHIFT; - res = fuse_send_read(file, inode, bl_buf, offset, FUSE_BLOCK_SIZE); - if (res >= 0) { - if (res < FUSE_BLOCK_SIZE) - memset(bl_buf + res, 0, FUSE_BLOCK_SIZE - res); - res = 0; - } - return res; } -static void fuse_file_bigread(struct file *file, struct inode *inode, - loff_t pos, size_t count) +static int fuse_file_bigread(struct file *file, struct inode *inode, + loff_t pos, size_t count) { - size_t bl_index = pos >> FUSE_BLOCK_SHIFT; - size_t bl_end_index = (pos + count) >> FUSE_BLOCK_SHIFT; - size_t bl_file_end_index = i_size_read(inode) >> FUSE_BLOCK_SHIFT; + struct fuse_conn *fc = INO_FC(inode); + unsigned starti; + unsigned endi; + unsigned nexti; + struct fuse_req *req; + loff_t size = i_size_read(inode); + loff_t end = (pos + count + FUSE_BLOCK_SIZE - 1) & FUSE_BLOCK_MASK; + end = min(end, size); + if (end <= pos) + return 0; + + starti = (pos & FUSE_BLOCK_MASK) >> PAGE_CACHE_SHIFT; + endi = (end + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; - if (bl_end_index > bl_file_end_index) - bl_end_index = bl_file_end_index; + req = fuse_get_request(fc); + if (!req) + return -ERESTARTSYS; - while (bl_index <= bl_end_index) { - int res; - char *bl_buf = kmalloc(FUSE_BLOCK_SIZE, GFP_KERNEL); - if (!bl_buf) - break; - res = fuse_is_block_uptodate(inode, bl_index); - if (!res) - res = fuse_file_read_block(file, inode, bl_buf, - bl_index); - if (!res) - fuse_cache_block(inode, bl_buf, bl_index); - kfree(bl_buf); - bl_index++; + for (; starti < endi; starti = nexti) { + nexti = starti + (FUSE_BLOCK_SIZE >> PAGE_CACHE_SHIFT); + nexti = min(nexti, endi); + if (!fuse_is_block_uptodate(inode, starti, nexti)) { + fuse_file_read_block(req, file, inode, starti, nexti); + fuse_reset_request(req); + } } + fuse_put_request(fc, req); + return 0; } #endif /* KERNEL_2_6 */ -static int fuse_read_copyout(struct fuse_req *req, const char __user *buf, - size_t nbytes) +static void fuse_release_user_pages(struct fuse_req *req) { - struct fuse_read_in *inarg = &req->misc.read_in; - unsigned count; - unsigned page_offset; unsigned i; - if (nbytes > inarg->size) { - printk("fuse: long read\n"); - return -EPROTO; - } - req->out.args[0].size = nbytes; - page_offset = req->page_offset; - count = min(nbytes, (unsigned) PAGE_SIZE - page_offset); - for (i = 0; i < req->num_pages && nbytes; i++) { - struct page *page = req->pages[i]; - char *buffer = kmap(page); - int err = copy_from_user(buffer + page_offset, buf, count); - flush_dcache_page(page); - kunmap(page); + + for (i = 0; i < req->num_pages; i++) { + struct page *page = req->pages[i]; #ifdef KERNEL_2_6 set_page_dirty_lock(page); #else @@ -530,80 +441,59 @@ static int fuse_read_copyout(struct fuse_req *req, const char __user *buf, set_page_dirty(page); unlock_page(page); #endif - if (err) - return -EFAULT; - nbytes -= count; - buf += count; - count = min(nbytes, (unsigned) PAGE_SIZE); - page_offset = 0; + page_cache_release(page); } - return 0; } -static int fuse_send_read_multi(struct file *file, struct fuse_req *req, - size_t size, off_t pos) +static int fuse_get_user_pages(struct fuse_req *req, char __user *buf, + unsigned nbytes) { - struct inode *inode = file->f_dentry->d_inode; - struct fuse_conn *fc = INO_FC(inode); - struct fuse_inode *fi = INO_FI(inode); - struct fuse_file *ff = file->private_data; - struct fuse_read_in *inarg; - - inarg = &req->misc.read_in; - inarg->fh = ff->fh; - inarg->offset = pos; - inarg->size = size; - req->in.h.opcode = FUSE_READ; - req->in.h.nodeid = fi->nodeid; - req->in.numargs = 1; - req->in.args[0].size = sizeof(struct fuse_read_in); - req->in.args[0].value = inarg; - req->copy_out = fuse_read_copyout; - request_send(fc, req); - return req->out.h.error; + unsigned long user_addr = (unsigned long) buf; + unsigned offset = user_addr & ~PAGE_CACHE_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; + npages = min(npages, FUSE_MAX_PAGES_PER_REQ); + npages = get_user_pages(current, current->mm, user_addr, npages, 1, 0, + req->pages, NULL); + if (npages < 0) + return npages; + + req->num_pages = npages; + req->page_offset = offset; + return 0; } -static ssize_t fuse_read(struct file *file, char __user *buf, size_t count, - loff_t *ppos) +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); loff_t pos = *ppos; - struct fuse_req *req; - ssize_t res; - - req = fuse_get_request(fc); + ssize_t res = 0; + struct fuse_req *req = fuse_get_request(fc); if (!req) return -ERESTARTSYS; - res = 0; while (count) { unsigned nbytes = min(count, fc->max_read); unsigned nread; - unsigned long user_addr = (unsigned long) buf; - unsigned offset = user_addr & ~PAGE_MASK; - int npages; - int err; - int i; - - nbytes = min(nbytes, (unsigned) (FUSE_MAX_PAGES_PER_REQ * PAGE_SIZE)); - 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); - if (npages < 0) { - res = npages; + unsigned ntmp; + int err = fuse_get_user_pages(req, buf, nbytes); + if (err) { + res = err; break; } - req->num_pages = npages; - req->page_offset = offset; - nbytes = min(nbytes, (unsigned) (npages * PAGE_SIZE - offset)); - err = fuse_send_read_multi(file, req, nbytes, pos); - for (i = 0; i < npages; i++) - page_cache_release(req->pages[i]); - if (err) { + ntmp = (req->num_pages << PAGE_CACHE_SHIFT) - req->page_offset; + nbytes = min(nbytes, ntmp); + fuse_read_init(req, file, inode, pos, nbytes); + req->out.argpages = 1; + request_send(fc, req); + fuse_release_user_pages(req); + if (req->out.h.error) { if (!res) - res = err; + res = req->out.h.error; break; } nread = req->out.args[0].size; @@ -629,20 +519,20 @@ static ssize_t fuse_file_read(struct file *file, char __user *buf, struct fuse_conn *fc = INO_FC(inode); ssize_t res; - if (fc->flags & FUSE_DIRECT_IO) { - res = fuse_read(file, buf, count, ppos); - } + if (fc->flags & FUSE_DIRECT_IO) + res = fuse_direct_read(file, buf, count, ppos); else { #ifndef KERNEL_2_6 if (fc->flags & FUSE_LARGE_READ) { down(&inode->i_sem); - fuse_file_bigread(file, inode, *ppos, count); + res = fuse_file_bigread(file, inode, *ppos, count); up(&inode->i_sem); + if (res) + return res; } #endif res = generic_file_read(file, buf, count, ppos); } - return res; } @@ -734,7 +624,7 @@ static int get_write_count(struct inode *inode, struct page *page) #ifdef KERNEL_2_6 static void write_page_end(struct fuse_conn *fc, struct fuse_req *req) { - struct page *page = req->data; + struct page *page = req->pages[0]; struct inode *inode = page->mapping->host; struct fuse_inode *fi = INO_FI(inode); struct fuse_write_out *outarg = req->out.args[0].value; @@ -788,7 +678,8 @@ static void fuse_send_writepage(struct fuse_req *req, struct inode *inode, req->out.numargs = 1; req->out.args[0].size = sizeof(struct fuse_write_out); req->out.args[0].value = &req->misc.write.out; - request_send_async(fc, req, write_page_end, page); + req->pages[0] = page; + request_send_async(fc, req, write_page_end); } static int fuse_writepage(struct page *page, struct writeback_control *wbc) @@ -956,8 +847,8 @@ static int fuse_commit_write(struct file *file, struct page *page, return err; } -static ssize_t fuse_write(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) +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); @@ -1021,7 +912,7 @@ static ssize_t fuse_file_write(struct file *file, const char __user *buf, if (fc->flags & FUSE_DIRECT_IO) { ssize_t res; down(&inode->i_sem); - res = fuse_write(file, buf, count, ppos); + res = fuse_direct_write(file, buf, count, ppos); up(&inode->i_sem); return res; } diff --git a/kernel/fuse_i.h b/kernel/fuse_i.h index 9dbe3f3..37d8cad 100644 --- a/kernel/fuse_i.h +++ b/kernel/fuse_i.h @@ -6,7 +6,6 @@ See the file COPYING. */ - #include #ifndef FUSE_MAINLINE #include @@ -54,13 +53,6 @@ #ifndef __user #define __user #endif -#ifndef KERNEL_2_6 -/** Read combining parameters */ -#define FUSE_BLOCK_SHIFT 16 -#define FUSE_BLOCK_SIZE 65536 -#define FUSE_BLOCK_MASK 0xffff0000 -#define FUSE_BLOCK_PAGE_SHIFT (FUSE_BLOCK_SHIFT - PAGE_CACHE_SHIFT) -#endif /* Max number of pages that can be used in a single read request */ #define FUSE_MAX_PAGES_PER_REQ 32 @@ -69,8 +61,8 @@ /** If the FUSE_DEFAULT_PERMISSIONS flag is given, the filesystem -module will check permissions based on the file mode. Otherwise no -permission checking is done in the kernel */ + module will check permissions based on the file mode. Otherwise no + permission checking is done in the kernel */ #define FUSE_DEFAULT_PERMISSIONS (1 << 0) /** If the FUSE_ALLOW_OTHER flag is given, then not only the user @@ -115,28 +107,30 @@ struct fuse_file { /** One input argument of a request */ struct fuse_in_arg { - unsigned int size; + unsigned size; const void *value; }; /** The request input */ struct fuse_in { struct fuse_in_header h; - unsigned int numargs; + unsigned numargs; struct fuse_in_arg args[3]; }; /** One output argument of a request */ struct fuse_out_arg { - unsigned int size; + unsigned size; void *value; }; /** The request output */ struct fuse_out { struct fuse_out_header h; - unsigned int argvar; - unsigned int numargs; + unsigned argvar:1; + unsigned argpages:1; + unsigned page_zeroing:1; + unsigned numargs; struct fuse_out_arg args[3]; }; @@ -154,13 +148,13 @@ struct fuse_req { struct list_head list; /** True if the request has reply */ - unsigned int isreply:1; + unsigned isreply:1; /* The request is preallocated */ - unsigned int preallocated:1; + unsigned preallocated:1; /* The request is finished */ - unsigned int finished; + unsigned finished; /** The request input */ struct fuse_in in; @@ -174,12 +168,6 @@ struct fuse_req { /** Request completion callback */ fuse_reqend_t end; - /** Request copy out function */ - fuse_copyout_t copy_out; - - /** User data */ - void *data; - /** Data for asynchronous requests */ union { struct { @@ -191,8 +179,13 @@ struct fuse_req { struct fuse_forget_in forget_in; } misc; + /** page vector */ struct page *pages[FUSE_MAX_PAGES_PER_REQ]; + + /** number of pages in vector */ unsigned num_pages; + + /** offset of data on first page */ unsigned page_offset; }; @@ -214,13 +207,13 @@ struct fuse_conn { uid_t uid; /** The fuse mount flags for this mount */ - unsigned int flags; + unsigned flags; /** Maximum read size */ - unsigned int max_read; + unsigned max_read; /** Maximum write size */ - unsigned int max_write; + unsigned max_write; /** Readers of the connection are waiting on this */ wait_queue_head_t waitq; @@ -244,22 +237,22 @@ struct fuse_conn { int reqctr; /** Is fsync not implemented by fs? */ - unsigned int no_fsync : 1; + unsigned no_fsync : 1; /** Is flush not implemented by fs? */ - unsigned int no_flush : 1; + unsigned no_flush : 1; /** Is setxattr not implemented by fs? */ - unsigned int no_setxattr : 1; + unsigned no_setxattr : 1; /** Is getxattr not implemented by fs? */ - unsigned int no_getxattr : 1; + unsigned no_getxattr : 1; /** Is listxattr not implemented by fs? */ - unsigned int no_listxattr : 1; + unsigned no_listxattr : 1; /** Is removexattr not implemented by fs? */ - unsigned int no_removexattr : 1; + unsigned no_removexattr : 1; #ifdef KERNEL_2_6 /** Backing dev info */ @@ -395,7 +388,7 @@ void request_send_noreply(struct fuse_conn *fc, struct fuse_req *req); * Send asynchronous request */ void request_send_async(struct fuse_conn *fc, struct fuse_req *req, - fuse_reqend_t end, void *data); + fuse_reqend_t end); /** * Get the attributes of a file diff --git a/kernel/inode.c b/kernel/inode.c index 8cae834..0a70d02 100644 --- a/kernel/inode.c +++ b/kernel/inode.c @@ -46,10 +46,10 @@ MODULE_PARM_DESC(user_allow_other, "Allow non root user to specify the \"allow_o #endif struct fuse_mount_data { int fd; - unsigned int rootmode; - unsigned int uid; - unsigned int flags; - unsigned int max_read; + unsigned rootmode; + unsigned uid; + unsigned flags; + unsigned max_read; }; static struct inode *fuse_alloc_inode(struct super_block *sb) @@ -392,7 +392,7 @@ static struct fuse_conn *get_conn(struct file *file, struct super_block *sb) return fc; } -static struct inode *get_root_inode(struct super_block *sb, unsigned int mode) +static struct inode *get_root_inode(struct super_block *sb, unsigned mode) { struct fuse_attr attr; memset(&attr, 0, sizeof(attr)); diff --git a/kernel/util.c b/kernel/util.c index fa5b082..003f8b2 100644 --- a/kernel/util.c +++ b/kernel/util.c @@ -40,9 +40,9 @@ int __init fuse_init(void) return 0; - err_fs_cleanup: + err_fs_cleanup: fuse_fs_cleanup(); - err: + err: return res; } -- 2.30.2