Loading fs/9p/v9fs_vfs.h +0 −4 Original line number Diff line number Diff line Loading @@ -68,14 +68,10 @@ int v9fs_file_open(struct inode *inode, struct file *file); void v9fs_inode2stat(struct inode *inode, struct p9_wstat *stat); int v9fs_uflags2omode(int uflags, int extended); ssize_t v9fs_file_readn(struct file *, char *, char __user *, u32, u64); ssize_t v9fs_fid_readn(struct p9_fid *, char *, char __user *, u32, u64); void v9fs_blank_wstat(struct p9_wstat *wstat); int v9fs_vfs_setattr_dotl(struct dentry *, struct iattr *); int v9fs_file_fsync_dotl(struct file *filp, loff_t start, loff_t end, int datasync); ssize_t v9fs_file_write_internal(struct inode *, struct p9_fid *, const char __user *, size_t, loff_t *, int); int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode); int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode); static inline void v9fs_invalidate_inode_attr(struct inode *inode) Loading fs/9p/vfs_addr.c +37 −43 Original line number Diff line number Diff line Loading @@ -51,12 +51,11 @@ */ static int v9fs_fid_readpage(struct p9_fid *fid, struct page *page) { int retval; loff_t offset; char *buffer; struct inode *inode; struct inode *inode = page->mapping->host; struct bio_vec bvec = {.bv_page = page, .bv_len = PAGE_SIZE}; struct iov_iter to; int retval, err; inode = page->mapping->host; p9_debug(P9_DEBUG_VFS, "\n"); BUG_ON(!PageLocked(page)); Loading @@ -65,16 +64,16 @@ static int v9fs_fid_readpage(struct p9_fid *fid, struct page *page) if (retval == 0) return retval; buffer = kmap(page); offset = page_offset(page); iov_iter_bvec(&to, ITER_BVEC | READ, &bvec, 1, PAGE_SIZE); retval = v9fs_fid_readn(fid, buffer, NULL, PAGE_CACHE_SIZE, offset); if (retval < 0) { retval = p9_client_read(fid, page_offset(page), &to, &err); if (err) { v9fs_uncache_page(inode, page); retval = err; goto done; } memset(buffer + retval, 0, PAGE_CACHE_SIZE - retval); zero_user(page, retval, PAGE_SIZE - retval); flush_dcache_page(page); SetPageUptodate(page); Loading @@ -82,7 +81,6 @@ static int v9fs_fid_readpage(struct p9_fid *fid, struct page *page) retval = 0; done: kunmap(page); unlock_page(page); return retval; } Loading Loading @@ -161,41 +159,32 @@ static void v9fs_invalidate_page(struct page *page, unsigned int offset, static int v9fs_vfs_writepage_locked(struct page *page) { char *buffer; int retval, len; loff_t offset, size; mm_segment_t old_fs; struct v9fs_inode *v9inode; struct inode *inode = page->mapping->host; struct v9fs_inode *v9inode = V9FS_I(inode); loff_t size = i_size_read(inode); struct iov_iter from; struct bio_vec bvec; int err, len; v9inode = V9FS_I(inode); size = i_size_read(inode); if (page->index == size >> PAGE_CACHE_SHIFT) len = size & ~PAGE_CACHE_MASK; else len = PAGE_CACHE_SIZE; set_page_writeback(page); buffer = kmap(page); offset = page_offset(page); bvec.bv_page = page; bvec.bv_offset = 0; bvec.bv_len = len; iov_iter_bvec(&from, ITER_BVEC | WRITE, &bvec, 1, len); old_fs = get_fs(); set_fs(get_ds()); /* We should have writeback_fid always set */ BUG_ON(!v9inode->writeback_fid); retval = v9fs_file_write_internal(inode, v9inode->writeback_fid, (__force const char __user *)buffer, len, &offset, 0); if (retval > 0) retval = 0; set_page_writeback(page); p9_client_write(v9inode->writeback_fid, page_offset(page), &from, &err); set_fs(old_fs); kunmap(page); end_page_writeback(page); return retval; return err; } static int v9fs_vfs_writepage(struct page *page, struct writeback_control *wbc) Loading Loading @@ -261,16 +250,21 @@ static int v9fs_launder_page(struct page *page) static ssize_t v9fs_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, loff_t pos) { /* * FIXME * Now that we do caching with cache mode enabled, We need * to support direct IO */ p9_debug(P9_DEBUG_VFS, "v9fs_direct_IO: v9fs_direct_IO (%pD) off/no(%lld/%lu) EINVAL\n", iocb->ki_filp, (long long)pos, iter->nr_segs); return -EINVAL; struct file *file = iocb->ki_filp; ssize_t n; int err = 0; if (rw & WRITE) { n = p9_client_write(file->private_data, pos, iter, &err); if (n) { struct inode *inode = file_inode(file); loff_t i_size = i_size_read(inode); if (pos + n > i_size) inode_add_bytes(inode, pos + n - i_size); } } else { n = p9_client_read(file->private_data, pos, iter, &err); } return n ? n : err; } static int v9fs_write_begin(struct file *filp, struct address_space *mapping, Loading fs/9p/vfs_dir.c +11 −4 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ #include <linux/inet.h> #include <linux/idr.h> #include <linux/slab.h> #include <linux/uio.h> #include <net/9p/9p.h> #include <net/9p/client.h> Loading Loading @@ -115,6 +116,7 @@ static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx) int buflen; int reclen = 0; struct p9_rdir *rdir; struct kvec kvec; p9_debug(P9_DEBUG_VFS, "name %pD\n", file); fid = file->private_data; Loading @@ -124,16 +126,21 @@ static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx) rdir = v9fs_alloc_rdir_buf(file, buflen); if (!rdir) return -ENOMEM; kvec.iov_base = rdir->buf; kvec.iov_len = buflen; while (1) { if (rdir->tail == rdir->head) { err = v9fs_file_readn(file, rdir->buf, NULL, buflen, ctx->pos); if (err <= 0) struct iov_iter to; int n; iov_iter_kvec(&to, READ | ITER_KVEC, &kvec, 1, buflen); n = p9_client_read(file->private_data, ctx->pos, &to, &err); if (err) return err; rdir->head = 0; rdir->tail = err; rdir->tail = n; } while (rdir->head < rdir->tail) { p9stat_init(&st); Loading fs/9p/vfs_file.c +66 −260 Original line number Diff line number Diff line Loading @@ -36,6 +36,8 @@ #include <linux/utsname.h> #include <asm/uaccess.h> #include <linux/idr.h> #include <linux/uio.h> #include <linux/slab.h> #include <net/9p/9p.h> #include <net/9p/client.h> Loading Loading @@ -285,6 +287,7 @@ static int v9fs_file_getlock(struct file *filp, struct file_lock *fl) fl->fl_end = glock.start + glock.length - 1; fl->fl_pid = glock.proc_id; } kfree(glock.client_id); return res; } Loading Loading @@ -363,63 +366,6 @@ static int v9fs_file_flock_dotl(struct file *filp, int cmd, return ret; } /** * v9fs_fid_readn - read from a fid * @fid: fid to read * @data: data buffer to read data into * @udata: user data buffer to read data into * @count: size of buffer * @offset: offset at which to read data * */ ssize_t v9fs_fid_readn(struct p9_fid *fid, char *data, char __user *udata, u32 count, u64 offset) { int n, total, size; p9_debug(P9_DEBUG_VFS, "fid %d offset %llu count %d\n", fid->fid, (long long unsigned)offset, count); n = 0; total = 0; size = fid->iounit ? fid->iounit : fid->clnt->msize - P9_IOHDRSZ; do { n = p9_client_read(fid, data, udata, offset, count); if (n <= 0) break; if (data) data += n; if (udata) udata += n; offset += n; count -= n; total += n; } while (count > 0 && n == size); if (n < 0) total = n; return total; } /** * v9fs_file_readn - read from a file * @filp: file pointer to read * @data: data buffer to read data into * @udata: user data buffer to read data into * @count: size of buffer * @offset: offset at which to read data * */ ssize_t v9fs_file_readn(struct file *filp, char *data, char __user *udata, u32 count, u64 offset) { return v9fs_fid_readn(filp->private_data, data, udata, count, offset); } /** * v9fs_file_read - read from a file * @filp: file pointer to read Loading @@ -430,69 +376,22 @@ v9fs_file_readn(struct file *filp, char *data, char __user *udata, u32 count, */ static ssize_t v9fs_file_read(struct file *filp, char __user *udata, size_t count, loff_t * offset) v9fs_file_read_iter(struct kiocb *iocb, struct iov_iter *to) { int ret; struct p9_fid *fid; size_t size; p9_debug(P9_DEBUG_VFS, "count %zu offset %lld\n", count, *offset); fid = filp->private_data; struct p9_fid *fid = iocb->ki_filp->private_data; int ret, err; size = fid->iounit ? fid->iounit : fid->clnt->msize - P9_IOHDRSZ; if (count > size) ret = v9fs_file_readn(filp, NULL, udata, count, *offset); else ret = p9_client_read(fid, NULL, udata, *offset, count); p9_debug(P9_DEBUG_VFS, "count %zu offset %lld\n", iov_iter_count(to), iocb->ki_pos); if (ret > 0) *offset += ret; ret = p9_client_read(fid, iocb->ki_pos, to, &err); if (!ret) return err; iocb->ki_pos += ret; return ret; } ssize_t v9fs_file_write_internal(struct inode *inode, struct p9_fid *fid, const char __user *data, size_t count, loff_t *offset, int invalidate) { int n; loff_t i_size; size_t total = 0; loff_t origin = *offset; unsigned long pg_start, pg_end; p9_debug(P9_DEBUG_VFS, "data %p count %d offset %x\n", data, (int)count, (int)*offset); do { n = p9_client_write(fid, NULL, data+total, origin+total, count); if (n <= 0) break; count -= n; total += n; } while (count > 0); if (invalidate && (total > 0)) { pg_start = origin >> PAGE_CACHE_SHIFT; pg_end = (origin + total - 1) >> PAGE_CACHE_SHIFT; if (inode->i_mapping && inode->i_mapping->nrpages) invalidate_inode_pages2_range(inode->i_mapping, pg_start, pg_end); *offset += total; i_size = i_size_read(inode); if (*offset > i_size) { inode_add_bytes(inode, *offset - i_size); i_size_write(inode, *offset); } } if (n < 0) return n; return total; } /** * v9fs_file_write - write to a file * @filp: file pointer to write Loading @@ -502,34 +401,44 @@ v9fs_file_write_internal(struct inode *inode, struct p9_fid *fid, * */ static ssize_t v9fs_file_write(struct file *filp, const char __user * data, size_t count, loff_t *offset) v9fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) { struct file *file = iocb->ki_filp; ssize_t retval = 0; loff_t origin = *offset; loff_t origin = iocb->ki_pos; size_t count = iov_iter_count(from); int err = 0; retval = generic_write_checks(filp, &origin, &count, 0); retval = generic_write_checks(file, &origin, &count, 0); if (retval) goto out; return retval; iov_iter_truncate(from, count); retval = -EINVAL; if ((ssize_t) count < 0) goto out; retval = 0; if (!count) goto out; return 0; retval = v9fs_file_write_internal(file_inode(filp), filp->private_data, data, count, &origin, 1); /* update offset on successful write */ if (retval > 0) *offset = origin; out: retval = p9_client_write(file->private_data, origin, from, &err); if (retval > 0) { struct inode *inode = file_inode(file); loff_t i_size; unsigned long pg_start, pg_end; pg_start = origin >> PAGE_CACHE_SHIFT; pg_end = (origin + retval - 1) >> PAGE_CACHE_SHIFT; if (inode->i_mapping && inode->i_mapping->nrpages) invalidate_inode_pages2_range(inode->i_mapping, pg_start, pg_end); origin += retval; i_size = i_size_read(inode); iocb->ki_pos = origin; if (origin > i_size) { inode_add_bytes(inode, origin - i_size); i_size_write(inode, origin); } return retval; } return err; } static int v9fs_file_fsync(struct file *filp, loff_t start, loff_t end, int datasync) Loading Loading @@ -657,44 +566,6 @@ v9fs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) return VM_FAULT_NOPAGE; } static ssize_t v9fs_direct_read(struct file *filp, char __user *udata, size_t count, loff_t *offsetp) { loff_t size, offset; struct inode *inode; struct address_space *mapping; offset = *offsetp; mapping = filp->f_mapping; inode = mapping->host; if (!count) return 0; size = i_size_read(inode); if (offset < size) filemap_write_and_wait_range(mapping, offset, offset + count - 1); return v9fs_file_read(filp, udata, count, offsetp); } /** * v9fs_cached_file_read - read from a file * @filp: file pointer to read * @data: user data buffer to read data into * @count: size of buffer * @offset: offset at which to read data * */ static ssize_t v9fs_cached_file_read(struct file *filp, char __user *data, size_t count, loff_t *offset) { if (filp->f_flags & O_DIRECT) return v9fs_direct_read(filp, data, count, offset); return new_sync_read(filp, data, count, offset); } /** * v9fs_mmap_file_read - read from a file * @filp: file pointer to read Loading @@ -704,84 +575,12 @@ v9fs_cached_file_read(struct file *filp, char __user *data, size_t count, * */ static ssize_t v9fs_mmap_file_read(struct file *filp, char __user *data, size_t count, loff_t *offset) v9fs_mmap_file_read_iter(struct kiocb *iocb, struct iov_iter *to) { /* TODO: Check if there are dirty pages */ return v9fs_file_read(filp, data, count, offset); } static ssize_t v9fs_direct_write(struct file *filp, const char __user * data, size_t count, loff_t *offsetp) { loff_t offset; ssize_t retval; struct inode *inode; struct address_space *mapping; offset = *offsetp; mapping = filp->f_mapping; inode = mapping->host; if (!count) return 0; mutex_lock(&inode->i_mutex); retval = filemap_write_and_wait_range(mapping, offset, offset + count - 1); if (retval) goto err_out; /* * After a write we want buffered reads to be sure to go to disk to get * the new data. We invalidate clean cached page from the region we're * about to write. We do this *before* the write so that if we fail * here we fall back to buffered write */ if (mapping->nrpages) { pgoff_t pg_start = offset >> PAGE_CACHE_SHIFT; pgoff_t pg_end = (offset + count - 1) >> PAGE_CACHE_SHIFT; retval = invalidate_inode_pages2_range(mapping, pg_start, pg_end); /* * If a page can not be invalidated, fall back * to buffered write. */ if (retval) { if (retval == -EBUSY) goto buff_write; goto err_out; } } retval = v9fs_file_write(filp, data, count, offsetp); err_out: mutex_unlock(&inode->i_mutex); return retval; buff_write: mutex_unlock(&inode->i_mutex); return new_sync_write(filp, data, count, offsetp); return v9fs_file_read_iter(iocb, to); } /** * v9fs_cached_file_write - write to a file * @filp: file pointer to write * @data: data buffer to write data from * @count: size of buffer * @offset: offset at which to write data * */ static ssize_t v9fs_cached_file_write(struct file *filp, const char __user * data, size_t count, loff_t *offset) { if (filp->f_flags & O_DIRECT) return v9fs_direct_write(filp, data, count, offset); return new_sync_write(filp, data, count, offset); } /** * v9fs_mmap_file_write - write to a file * @filp: file pointer to write Loading @@ -791,14 +590,13 @@ v9fs_cached_file_write(struct file *filp, const char __user * data, * */ static ssize_t v9fs_mmap_file_write(struct file *filp, const char __user *data, size_t count, loff_t *offset) v9fs_mmap_file_write_iter(struct kiocb *iocb, struct iov_iter *from) { /* * TODO: invalidate mmaps on filp's inode between * offset and offset+count */ return v9fs_file_write(filp, data, count, offset); return v9fs_file_write_iter(iocb, from); } static void v9fs_mmap_vm_close(struct vm_area_struct *vma) Loading Loading @@ -843,8 +641,8 @@ static const struct vm_operations_struct v9fs_mmap_file_vm_ops = { const struct file_operations v9fs_cached_file_operations = { .llseek = generic_file_llseek, .read = v9fs_cached_file_read, .write = v9fs_cached_file_write, .read = new_sync_read, .write = new_sync_write, .read_iter = generic_file_read_iter, .write_iter = generic_file_write_iter, .open = v9fs_file_open, Loading @@ -856,8 +654,8 @@ const struct file_operations v9fs_cached_file_operations = { const struct file_operations v9fs_cached_file_operations_dotl = { .llseek = generic_file_llseek, .read = v9fs_cached_file_read, .write = v9fs_cached_file_write, .read = new_sync_read, .write = new_sync_write, .read_iter = generic_file_read_iter, .write_iter = generic_file_write_iter, .open = v9fs_file_open, Loading @@ -870,8 +668,10 @@ const struct file_operations v9fs_cached_file_operations_dotl = { const struct file_operations v9fs_file_operations = { .llseek = generic_file_llseek, .read = v9fs_file_read, .write = v9fs_file_write, .read = new_sync_read, .write = new_sync_write, .read_iter = v9fs_file_read_iter, .write_iter = v9fs_file_write_iter, .open = v9fs_file_open, .release = v9fs_dir_release, .lock = v9fs_file_lock, Loading @@ -881,8 +681,10 @@ const struct file_operations v9fs_file_operations = { const struct file_operations v9fs_file_operations_dotl = { .llseek = generic_file_llseek, .read = v9fs_file_read, .write = v9fs_file_write, .read = new_sync_read, .write = new_sync_write, .read_iter = v9fs_file_read_iter, .write_iter = v9fs_file_write_iter, .open = v9fs_file_open, .release = v9fs_dir_release, .lock = v9fs_file_lock_dotl, Loading @@ -893,8 +695,10 @@ const struct file_operations v9fs_file_operations_dotl = { const struct file_operations v9fs_mmap_file_operations = { .llseek = generic_file_llseek, .read = v9fs_mmap_file_read, .write = v9fs_mmap_file_write, .read = new_sync_read, .write = new_sync_write, .read_iter = v9fs_mmap_file_read_iter, .write_iter = v9fs_mmap_file_write_iter, .open = v9fs_file_open, .release = v9fs_dir_release, .lock = v9fs_file_lock, Loading @@ -904,8 +708,10 @@ const struct file_operations v9fs_mmap_file_operations = { const struct file_operations v9fs_mmap_file_operations_dotl = { .llseek = generic_file_llseek, .read = v9fs_mmap_file_read, .write = v9fs_mmap_file_write, .read = new_sync_read, .write = new_sync_write, .read_iter = v9fs_mmap_file_read_iter, .write_iter = v9fs_mmap_file_write_iter, .open = v9fs_file_open, .release = v9fs_dir_release, .lock = v9fs_file_lock_dotl, Loading fs/9p/xattr.c +25 −55 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ #include <linux/module.h> #include <linux/fs.h> #include <linux/sched.h> #include <linux/uio.h> #include <net/9p/9p.h> #include <net/9p/client.h> Loading @@ -25,50 +26,34 @@ ssize_t v9fs_fid_xattr_get(struct p9_fid *fid, const char *name, void *buffer, size_t buffer_size) { ssize_t retval; int msize, read_count; u64 offset = 0, attr_size; u64 attr_size; struct p9_fid *attr_fid; struct kvec kvec = {.iov_base = buffer, .iov_len = buffer_size}; struct iov_iter to; int err; iov_iter_kvec(&to, READ | ITER_KVEC, &kvec, 1, buffer_size); attr_fid = p9_client_xattrwalk(fid, name, &attr_size); if (IS_ERR(attr_fid)) { retval = PTR_ERR(attr_fid); p9_debug(P9_DEBUG_VFS, "p9_client_attrwalk failed %zd\n", retval); attr_fid = NULL; goto error; } if (!buffer_size) { /* request to get the attr_size */ retval = attr_size; goto error; return retval; } if (attr_size > buffer_size) { retval = -ERANGE; goto error; } msize = attr_fid->clnt->msize; while (attr_size) { if (attr_size > (msize - P9_IOHDRSZ)) read_count = msize - P9_IOHDRSZ; if (!buffer_size) /* request to get the attr_size */ retval = attr_size; else read_count = attr_size; read_count = p9_client_read(attr_fid, ((char *)buffer)+offset, NULL, offset, read_count); if (read_count < 0) { /* error in xattr read */ retval = read_count; goto error; } offset += read_count; attr_size -= read_count; retval = -ERANGE; } else { iov_iter_truncate(&to, attr_size); retval = p9_client_read(attr_fid, 0, &to, &err); if (err) retval = err; } /* Total read xattr bytes */ retval = offset; error: if (attr_fid) p9_client_clunk(attr_fid); return retval; } Loading Loading @@ -120,8 +105,11 @@ int v9fs_xattr_set(struct dentry *dentry, const char *name, int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name, const void *value, size_t value_len, int flags) { u64 offset = 0; int retval, msize, write_count; struct kvec kvec = {.iov_base = (void *)value, .iov_len = value_len}; struct iov_iter from; int retval; iov_iter_kvec(&from, WRITE | ITER_KVEC, &kvec, 1, value_len); p9_debug(P9_DEBUG_VFS, "name = %s value_len = %zu flags = %d\n", name, value_len, flags); Loading @@ -135,29 +123,11 @@ int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name, * On success fid points to xattr */ retval = p9_client_xattrcreate(fid, name, value_len, flags); if (retval < 0) { if (retval < 0) p9_debug(P9_DEBUG_VFS, "p9_client_xattrcreate failed %d\n", retval); goto err; } msize = fid->clnt->msize; while (value_len) { if (value_len > (msize - P9_IOHDRSZ)) write_count = msize - P9_IOHDRSZ; else write_count = value_len; write_count = p9_client_write(fid, ((char *)value)+offset, NULL, offset, write_count); if (write_count < 0) { /* error in xattr write */ retval = write_count; goto err; } offset += write_count; value_len -= write_count; } retval = 0; err: p9_client_write(fid, 0, &from, &retval); p9_client_clunk(fid); return retval; } Loading Loading
fs/9p/v9fs_vfs.h +0 −4 Original line number Diff line number Diff line Loading @@ -68,14 +68,10 @@ int v9fs_file_open(struct inode *inode, struct file *file); void v9fs_inode2stat(struct inode *inode, struct p9_wstat *stat); int v9fs_uflags2omode(int uflags, int extended); ssize_t v9fs_file_readn(struct file *, char *, char __user *, u32, u64); ssize_t v9fs_fid_readn(struct p9_fid *, char *, char __user *, u32, u64); void v9fs_blank_wstat(struct p9_wstat *wstat); int v9fs_vfs_setattr_dotl(struct dentry *, struct iattr *); int v9fs_file_fsync_dotl(struct file *filp, loff_t start, loff_t end, int datasync); ssize_t v9fs_file_write_internal(struct inode *, struct p9_fid *, const char __user *, size_t, loff_t *, int); int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode); int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode); static inline void v9fs_invalidate_inode_attr(struct inode *inode) Loading
fs/9p/vfs_addr.c +37 −43 Original line number Diff line number Diff line Loading @@ -51,12 +51,11 @@ */ static int v9fs_fid_readpage(struct p9_fid *fid, struct page *page) { int retval; loff_t offset; char *buffer; struct inode *inode; struct inode *inode = page->mapping->host; struct bio_vec bvec = {.bv_page = page, .bv_len = PAGE_SIZE}; struct iov_iter to; int retval, err; inode = page->mapping->host; p9_debug(P9_DEBUG_VFS, "\n"); BUG_ON(!PageLocked(page)); Loading @@ -65,16 +64,16 @@ static int v9fs_fid_readpage(struct p9_fid *fid, struct page *page) if (retval == 0) return retval; buffer = kmap(page); offset = page_offset(page); iov_iter_bvec(&to, ITER_BVEC | READ, &bvec, 1, PAGE_SIZE); retval = v9fs_fid_readn(fid, buffer, NULL, PAGE_CACHE_SIZE, offset); if (retval < 0) { retval = p9_client_read(fid, page_offset(page), &to, &err); if (err) { v9fs_uncache_page(inode, page); retval = err; goto done; } memset(buffer + retval, 0, PAGE_CACHE_SIZE - retval); zero_user(page, retval, PAGE_SIZE - retval); flush_dcache_page(page); SetPageUptodate(page); Loading @@ -82,7 +81,6 @@ static int v9fs_fid_readpage(struct p9_fid *fid, struct page *page) retval = 0; done: kunmap(page); unlock_page(page); return retval; } Loading Loading @@ -161,41 +159,32 @@ static void v9fs_invalidate_page(struct page *page, unsigned int offset, static int v9fs_vfs_writepage_locked(struct page *page) { char *buffer; int retval, len; loff_t offset, size; mm_segment_t old_fs; struct v9fs_inode *v9inode; struct inode *inode = page->mapping->host; struct v9fs_inode *v9inode = V9FS_I(inode); loff_t size = i_size_read(inode); struct iov_iter from; struct bio_vec bvec; int err, len; v9inode = V9FS_I(inode); size = i_size_read(inode); if (page->index == size >> PAGE_CACHE_SHIFT) len = size & ~PAGE_CACHE_MASK; else len = PAGE_CACHE_SIZE; set_page_writeback(page); buffer = kmap(page); offset = page_offset(page); bvec.bv_page = page; bvec.bv_offset = 0; bvec.bv_len = len; iov_iter_bvec(&from, ITER_BVEC | WRITE, &bvec, 1, len); old_fs = get_fs(); set_fs(get_ds()); /* We should have writeback_fid always set */ BUG_ON(!v9inode->writeback_fid); retval = v9fs_file_write_internal(inode, v9inode->writeback_fid, (__force const char __user *)buffer, len, &offset, 0); if (retval > 0) retval = 0; set_page_writeback(page); p9_client_write(v9inode->writeback_fid, page_offset(page), &from, &err); set_fs(old_fs); kunmap(page); end_page_writeback(page); return retval; return err; } static int v9fs_vfs_writepage(struct page *page, struct writeback_control *wbc) Loading Loading @@ -261,16 +250,21 @@ static int v9fs_launder_page(struct page *page) static ssize_t v9fs_direct_IO(int rw, struct kiocb *iocb, struct iov_iter *iter, loff_t pos) { /* * FIXME * Now that we do caching with cache mode enabled, We need * to support direct IO */ p9_debug(P9_DEBUG_VFS, "v9fs_direct_IO: v9fs_direct_IO (%pD) off/no(%lld/%lu) EINVAL\n", iocb->ki_filp, (long long)pos, iter->nr_segs); return -EINVAL; struct file *file = iocb->ki_filp; ssize_t n; int err = 0; if (rw & WRITE) { n = p9_client_write(file->private_data, pos, iter, &err); if (n) { struct inode *inode = file_inode(file); loff_t i_size = i_size_read(inode); if (pos + n > i_size) inode_add_bytes(inode, pos + n - i_size); } } else { n = p9_client_read(file->private_data, pos, iter, &err); } return n ? n : err; } static int v9fs_write_begin(struct file *filp, struct address_space *mapping, Loading
fs/9p/vfs_dir.c +11 −4 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ #include <linux/inet.h> #include <linux/idr.h> #include <linux/slab.h> #include <linux/uio.h> #include <net/9p/9p.h> #include <net/9p/client.h> Loading Loading @@ -115,6 +116,7 @@ static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx) int buflen; int reclen = 0; struct p9_rdir *rdir; struct kvec kvec; p9_debug(P9_DEBUG_VFS, "name %pD\n", file); fid = file->private_data; Loading @@ -124,16 +126,21 @@ static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx) rdir = v9fs_alloc_rdir_buf(file, buflen); if (!rdir) return -ENOMEM; kvec.iov_base = rdir->buf; kvec.iov_len = buflen; while (1) { if (rdir->tail == rdir->head) { err = v9fs_file_readn(file, rdir->buf, NULL, buflen, ctx->pos); if (err <= 0) struct iov_iter to; int n; iov_iter_kvec(&to, READ | ITER_KVEC, &kvec, 1, buflen); n = p9_client_read(file->private_data, ctx->pos, &to, &err); if (err) return err; rdir->head = 0; rdir->tail = err; rdir->tail = n; } while (rdir->head < rdir->tail) { p9stat_init(&st); Loading
fs/9p/vfs_file.c +66 −260 Original line number Diff line number Diff line Loading @@ -36,6 +36,8 @@ #include <linux/utsname.h> #include <asm/uaccess.h> #include <linux/idr.h> #include <linux/uio.h> #include <linux/slab.h> #include <net/9p/9p.h> #include <net/9p/client.h> Loading Loading @@ -285,6 +287,7 @@ static int v9fs_file_getlock(struct file *filp, struct file_lock *fl) fl->fl_end = glock.start + glock.length - 1; fl->fl_pid = glock.proc_id; } kfree(glock.client_id); return res; } Loading Loading @@ -363,63 +366,6 @@ static int v9fs_file_flock_dotl(struct file *filp, int cmd, return ret; } /** * v9fs_fid_readn - read from a fid * @fid: fid to read * @data: data buffer to read data into * @udata: user data buffer to read data into * @count: size of buffer * @offset: offset at which to read data * */ ssize_t v9fs_fid_readn(struct p9_fid *fid, char *data, char __user *udata, u32 count, u64 offset) { int n, total, size; p9_debug(P9_DEBUG_VFS, "fid %d offset %llu count %d\n", fid->fid, (long long unsigned)offset, count); n = 0; total = 0; size = fid->iounit ? fid->iounit : fid->clnt->msize - P9_IOHDRSZ; do { n = p9_client_read(fid, data, udata, offset, count); if (n <= 0) break; if (data) data += n; if (udata) udata += n; offset += n; count -= n; total += n; } while (count > 0 && n == size); if (n < 0) total = n; return total; } /** * v9fs_file_readn - read from a file * @filp: file pointer to read * @data: data buffer to read data into * @udata: user data buffer to read data into * @count: size of buffer * @offset: offset at which to read data * */ ssize_t v9fs_file_readn(struct file *filp, char *data, char __user *udata, u32 count, u64 offset) { return v9fs_fid_readn(filp->private_data, data, udata, count, offset); } /** * v9fs_file_read - read from a file * @filp: file pointer to read Loading @@ -430,69 +376,22 @@ v9fs_file_readn(struct file *filp, char *data, char __user *udata, u32 count, */ static ssize_t v9fs_file_read(struct file *filp, char __user *udata, size_t count, loff_t * offset) v9fs_file_read_iter(struct kiocb *iocb, struct iov_iter *to) { int ret; struct p9_fid *fid; size_t size; p9_debug(P9_DEBUG_VFS, "count %zu offset %lld\n", count, *offset); fid = filp->private_data; struct p9_fid *fid = iocb->ki_filp->private_data; int ret, err; size = fid->iounit ? fid->iounit : fid->clnt->msize - P9_IOHDRSZ; if (count > size) ret = v9fs_file_readn(filp, NULL, udata, count, *offset); else ret = p9_client_read(fid, NULL, udata, *offset, count); p9_debug(P9_DEBUG_VFS, "count %zu offset %lld\n", iov_iter_count(to), iocb->ki_pos); if (ret > 0) *offset += ret; ret = p9_client_read(fid, iocb->ki_pos, to, &err); if (!ret) return err; iocb->ki_pos += ret; return ret; } ssize_t v9fs_file_write_internal(struct inode *inode, struct p9_fid *fid, const char __user *data, size_t count, loff_t *offset, int invalidate) { int n; loff_t i_size; size_t total = 0; loff_t origin = *offset; unsigned long pg_start, pg_end; p9_debug(P9_DEBUG_VFS, "data %p count %d offset %x\n", data, (int)count, (int)*offset); do { n = p9_client_write(fid, NULL, data+total, origin+total, count); if (n <= 0) break; count -= n; total += n; } while (count > 0); if (invalidate && (total > 0)) { pg_start = origin >> PAGE_CACHE_SHIFT; pg_end = (origin + total - 1) >> PAGE_CACHE_SHIFT; if (inode->i_mapping && inode->i_mapping->nrpages) invalidate_inode_pages2_range(inode->i_mapping, pg_start, pg_end); *offset += total; i_size = i_size_read(inode); if (*offset > i_size) { inode_add_bytes(inode, *offset - i_size); i_size_write(inode, *offset); } } if (n < 0) return n; return total; } /** * v9fs_file_write - write to a file * @filp: file pointer to write Loading @@ -502,34 +401,44 @@ v9fs_file_write_internal(struct inode *inode, struct p9_fid *fid, * */ static ssize_t v9fs_file_write(struct file *filp, const char __user * data, size_t count, loff_t *offset) v9fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) { struct file *file = iocb->ki_filp; ssize_t retval = 0; loff_t origin = *offset; loff_t origin = iocb->ki_pos; size_t count = iov_iter_count(from); int err = 0; retval = generic_write_checks(filp, &origin, &count, 0); retval = generic_write_checks(file, &origin, &count, 0); if (retval) goto out; return retval; iov_iter_truncate(from, count); retval = -EINVAL; if ((ssize_t) count < 0) goto out; retval = 0; if (!count) goto out; return 0; retval = v9fs_file_write_internal(file_inode(filp), filp->private_data, data, count, &origin, 1); /* update offset on successful write */ if (retval > 0) *offset = origin; out: retval = p9_client_write(file->private_data, origin, from, &err); if (retval > 0) { struct inode *inode = file_inode(file); loff_t i_size; unsigned long pg_start, pg_end; pg_start = origin >> PAGE_CACHE_SHIFT; pg_end = (origin + retval - 1) >> PAGE_CACHE_SHIFT; if (inode->i_mapping && inode->i_mapping->nrpages) invalidate_inode_pages2_range(inode->i_mapping, pg_start, pg_end); origin += retval; i_size = i_size_read(inode); iocb->ki_pos = origin; if (origin > i_size) { inode_add_bytes(inode, origin - i_size); i_size_write(inode, origin); } return retval; } return err; } static int v9fs_file_fsync(struct file *filp, loff_t start, loff_t end, int datasync) Loading Loading @@ -657,44 +566,6 @@ v9fs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) return VM_FAULT_NOPAGE; } static ssize_t v9fs_direct_read(struct file *filp, char __user *udata, size_t count, loff_t *offsetp) { loff_t size, offset; struct inode *inode; struct address_space *mapping; offset = *offsetp; mapping = filp->f_mapping; inode = mapping->host; if (!count) return 0; size = i_size_read(inode); if (offset < size) filemap_write_and_wait_range(mapping, offset, offset + count - 1); return v9fs_file_read(filp, udata, count, offsetp); } /** * v9fs_cached_file_read - read from a file * @filp: file pointer to read * @data: user data buffer to read data into * @count: size of buffer * @offset: offset at which to read data * */ static ssize_t v9fs_cached_file_read(struct file *filp, char __user *data, size_t count, loff_t *offset) { if (filp->f_flags & O_DIRECT) return v9fs_direct_read(filp, data, count, offset); return new_sync_read(filp, data, count, offset); } /** * v9fs_mmap_file_read - read from a file * @filp: file pointer to read Loading @@ -704,84 +575,12 @@ v9fs_cached_file_read(struct file *filp, char __user *data, size_t count, * */ static ssize_t v9fs_mmap_file_read(struct file *filp, char __user *data, size_t count, loff_t *offset) v9fs_mmap_file_read_iter(struct kiocb *iocb, struct iov_iter *to) { /* TODO: Check if there are dirty pages */ return v9fs_file_read(filp, data, count, offset); } static ssize_t v9fs_direct_write(struct file *filp, const char __user * data, size_t count, loff_t *offsetp) { loff_t offset; ssize_t retval; struct inode *inode; struct address_space *mapping; offset = *offsetp; mapping = filp->f_mapping; inode = mapping->host; if (!count) return 0; mutex_lock(&inode->i_mutex); retval = filemap_write_and_wait_range(mapping, offset, offset + count - 1); if (retval) goto err_out; /* * After a write we want buffered reads to be sure to go to disk to get * the new data. We invalidate clean cached page from the region we're * about to write. We do this *before* the write so that if we fail * here we fall back to buffered write */ if (mapping->nrpages) { pgoff_t pg_start = offset >> PAGE_CACHE_SHIFT; pgoff_t pg_end = (offset + count - 1) >> PAGE_CACHE_SHIFT; retval = invalidate_inode_pages2_range(mapping, pg_start, pg_end); /* * If a page can not be invalidated, fall back * to buffered write. */ if (retval) { if (retval == -EBUSY) goto buff_write; goto err_out; } } retval = v9fs_file_write(filp, data, count, offsetp); err_out: mutex_unlock(&inode->i_mutex); return retval; buff_write: mutex_unlock(&inode->i_mutex); return new_sync_write(filp, data, count, offsetp); return v9fs_file_read_iter(iocb, to); } /** * v9fs_cached_file_write - write to a file * @filp: file pointer to write * @data: data buffer to write data from * @count: size of buffer * @offset: offset at which to write data * */ static ssize_t v9fs_cached_file_write(struct file *filp, const char __user * data, size_t count, loff_t *offset) { if (filp->f_flags & O_DIRECT) return v9fs_direct_write(filp, data, count, offset); return new_sync_write(filp, data, count, offset); } /** * v9fs_mmap_file_write - write to a file * @filp: file pointer to write Loading @@ -791,14 +590,13 @@ v9fs_cached_file_write(struct file *filp, const char __user * data, * */ static ssize_t v9fs_mmap_file_write(struct file *filp, const char __user *data, size_t count, loff_t *offset) v9fs_mmap_file_write_iter(struct kiocb *iocb, struct iov_iter *from) { /* * TODO: invalidate mmaps on filp's inode between * offset and offset+count */ return v9fs_file_write(filp, data, count, offset); return v9fs_file_write_iter(iocb, from); } static void v9fs_mmap_vm_close(struct vm_area_struct *vma) Loading Loading @@ -843,8 +641,8 @@ static const struct vm_operations_struct v9fs_mmap_file_vm_ops = { const struct file_operations v9fs_cached_file_operations = { .llseek = generic_file_llseek, .read = v9fs_cached_file_read, .write = v9fs_cached_file_write, .read = new_sync_read, .write = new_sync_write, .read_iter = generic_file_read_iter, .write_iter = generic_file_write_iter, .open = v9fs_file_open, Loading @@ -856,8 +654,8 @@ const struct file_operations v9fs_cached_file_operations = { const struct file_operations v9fs_cached_file_operations_dotl = { .llseek = generic_file_llseek, .read = v9fs_cached_file_read, .write = v9fs_cached_file_write, .read = new_sync_read, .write = new_sync_write, .read_iter = generic_file_read_iter, .write_iter = generic_file_write_iter, .open = v9fs_file_open, Loading @@ -870,8 +668,10 @@ const struct file_operations v9fs_cached_file_operations_dotl = { const struct file_operations v9fs_file_operations = { .llseek = generic_file_llseek, .read = v9fs_file_read, .write = v9fs_file_write, .read = new_sync_read, .write = new_sync_write, .read_iter = v9fs_file_read_iter, .write_iter = v9fs_file_write_iter, .open = v9fs_file_open, .release = v9fs_dir_release, .lock = v9fs_file_lock, Loading @@ -881,8 +681,10 @@ const struct file_operations v9fs_file_operations = { const struct file_operations v9fs_file_operations_dotl = { .llseek = generic_file_llseek, .read = v9fs_file_read, .write = v9fs_file_write, .read = new_sync_read, .write = new_sync_write, .read_iter = v9fs_file_read_iter, .write_iter = v9fs_file_write_iter, .open = v9fs_file_open, .release = v9fs_dir_release, .lock = v9fs_file_lock_dotl, Loading @@ -893,8 +695,10 @@ const struct file_operations v9fs_file_operations_dotl = { const struct file_operations v9fs_mmap_file_operations = { .llseek = generic_file_llseek, .read = v9fs_mmap_file_read, .write = v9fs_mmap_file_write, .read = new_sync_read, .write = new_sync_write, .read_iter = v9fs_mmap_file_read_iter, .write_iter = v9fs_mmap_file_write_iter, .open = v9fs_file_open, .release = v9fs_dir_release, .lock = v9fs_file_lock, Loading @@ -904,8 +708,10 @@ const struct file_operations v9fs_mmap_file_operations = { const struct file_operations v9fs_mmap_file_operations_dotl = { .llseek = generic_file_llseek, .read = v9fs_mmap_file_read, .write = v9fs_mmap_file_write, .read = new_sync_read, .write = new_sync_write, .read_iter = v9fs_mmap_file_read_iter, .write_iter = v9fs_mmap_file_write_iter, .open = v9fs_file_open, .release = v9fs_dir_release, .lock = v9fs_file_lock_dotl, Loading
fs/9p/xattr.c +25 −55 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ #include <linux/module.h> #include <linux/fs.h> #include <linux/sched.h> #include <linux/uio.h> #include <net/9p/9p.h> #include <net/9p/client.h> Loading @@ -25,50 +26,34 @@ ssize_t v9fs_fid_xattr_get(struct p9_fid *fid, const char *name, void *buffer, size_t buffer_size) { ssize_t retval; int msize, read_count; u64 offset = 0, attr_size; u64 attr_size; struct p9_fid *attr_fid; struct kvec kvec = {.iov_base = buffer, .iov_len = buffer_size}; struct iov_iter to; int err; iov_iter_kvec(&to, READ | ITER_KVEC, &kvec, 1, buffer_size); attr_fid = p9_client_xattrwalk(fid, name, &attr_size); if (IS_ERR(attr_fid)) { retval = PTR_ERR(attr_fid); p9_debug(P9_DEBUG_VFS, "p9_client_attrwalk failed %zd\n", retval); attr_fid = NULL; goto error; } if (!buffer_size) { /* request to get the attr_size */ retval = attr_size; goto error; return retval; } if (attr_size > buffer_size) { retval = -ERANGE; goto error; } msize = attr_fid->clnt->msize; while (attr_size) { if (attr_size > (msize - P9_IOHDRSZ)) read_count = msize - P9_IOHDRSZ; if (!buffer_size) /* request to get the attr_size */ retval = attr_size; else read_count = attr_size; read_count = p9_client_read(attr_fid, ((char *)buffer)+offset, NULL, offset, read_count); if (read_count < 0) { /* error in xattr read */ retval = read_count; goto error; } offset += read_count; attr_size -= read_count; retval = -ERANGE; } else { iov_iter_truncate(&to, attr_size); retval = p9_client_read(attr_fid, 0, &to, &err); if (err) retval = err; } /* Total read xattr bytes */ retval = offset; error: if (attr_fid) p9_client_clunk(attr_fid); return retval; } Loading Loading @@ -120,8 +105,11 @@ int v9fs_xattr_set(struct dentry *dentry, const char *name, int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name, const void *value, size_t value_len, int flags) { u64 offset = 0; int retval, msize, write_count; struct kvec kvec = {.iov_base = (void *)value, .iov_len = value_len}; struct iov_iter from; int retval; iov_iter_kvec(&from, WRITE | ITER_KVEC, &kvec, 1, value_len); p9_debug(P9_DEBUG_VFS, "name = %s value_len = %zu flags = %d\n", name, value_len, flags); Loading @@ -135,29 +123,11 @@ int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name, * On success fid points to xattr */ retval = p9_client_xattrcreate(fid, name, value_len, flags); if (retval < 0) { if (retval < 0) p9_debug(P9_DEBUG_VFS, "p9_client_xattrcreate failed %d\n", retval); goto err; } msize = fid->clnt->msize; while (value_len) { if (value_len > (msize - P9_IOHDRSZ)) write_count = msize - P9_IOHDRSZ; else write_count = value_len; write_count = p9_client_write(fid, ((char *)value)+offset, NULL, offset, write_count); if (write_count < 0) { /* error in xattr write */ retval = write_count; goto err; } offset += write_count; value_len -= write_count; } retval = 0; err: p9_client_write(fid, 0, &from, &retval); p9_client_clunk(fid); return retval; } Loading