/** * v9fs_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_file_write_iter(struct kiocb *iocb, struct iov_iter *from) { struct file *file = iocb->ki_filp; ssize_t retval; loff_t origin; int err = 0; retval = generic_write_checks(iocb, from); if (retval <= 0) return retval; origin = iocb->ki_pos; retval = p9_client_write(file->private_data, iocb->ki_pos, 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_SHIFT; pg_end = (origin + retval - 1) >> PAGE_SHIFT; if (inode->i_mapping && inode->i_mapping->nrpages) invalidate_inode_pages2_range(inode->i_mapping, pg_start, pg_end); iocb->ki_pos += retval; i_size = i_size_read(inode); if (iocb->ki_pos > i_size) { inode_add_bytes(inode, iocb->ki_pos - i_size); i_size_write(inode, iocb->ki_pos); } return retval; } return err; }
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); } }
/* * v9fs_xattr_set() * * Create, replace or remove an extended attribute for this inode. Buffer * is NULL to remove an existing extended attribute, and non-NULL to * either replace an existing extended attribute, or create a new extended * attribute. The flags XATTR_REPLACE and XATTR_CREATE * specify that an extended attribute must exist and must not exist * previous to the call, respectively. * * Returns 0, or a negative error number on failure. */ int v9fs_xattr_set(struct dentry *dentry, const char *name, const void *value, size_t value_len, int flags) { u64 offset = 0; int retval, msize, write_count; struct p9_fid *fid = NULL; P9_DPRINTK(P9_DEBUG_VFS, "%s: name = %s value_len = %zu flags = %d\n", __func__, name, value_len, flags); fid = v9fs_fid_clone(dentry); if (IS_ERR(fid)) { retval = PTR_ERR(fid); fid = NULL; goto error; } /* * On success fid points to xattr */ retval = p9_client_xattrcreate(fid, name, value_len, flags); if (retval < 0) { P9_DPRINTK(P9_DEBUG_VFS, "p9_client_xattrcreate failed %d\n", retval); goto error; } 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 error; } offset += write_count; value_len -= write_count; } /* Total read xattr bytes */ retval = offset; error: if (fid) retval = p9_client_clunk(fid); return retval; }
int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name, const void *value, size_t value_len, int flags) { 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); /* Clone it */ fid = p9_client_walk(fid, 0, NULL, 1); if (IS_ERR(fid)) return PTR_ERR(fid); /* * On success fid points to xattr */ retval = p9_client_xattrcreate(fid, name, value_len, flags); if (retval < 0) p9_debug(P9_DEBUG_VFS, "p9_client_xattrcreate failed %d\n", retval); else p9_client_write(fid, 0, &from, &retval); p9_client_clunk(fid); return retval; } ssize_t v9fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size) { return v9fs_xattr_get(dentry, NULL, buffer, buffer_size); } const struct xattr_handler *v9fs_xattr_handlers[] = { &v9fs_xattr_user_handler, &v9fs_xattr_trusted_handler, #ifdef CONFIG_9P_FS_POSIX_ACL &v9fs_xattr_acl_access_handler, &v9fs_xattr_acl_default_handler, #endif #ifdef CONFIG_9P_FS_SECURITY &v9fs_xattr_security_handler, #endif NULL };
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; p9_debug(P9_DEBUG_VFS, "name = %s value_len = %zu flags = %d\n", name, value_len, flags); /* Clone it */ fid = p9_client_walk(fid, 0, NULL, 1); if (IS_ERR(fid)) return PTR_ERR(fid); /* * On success fid points to xattr */ retval = p9_client_xattrcreate(fid, name, value_len, flags); 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_clunk(fid); return retval; }
static ssize_t v9fs_file_write(struct file *filp, const char __user * data, size_t count, loff_t * offset) { int n, rsize, total = 0; struct p9_fid *fid; struct p9_client *clnt; struct inode *inode = filp->f_path.dentry->d_inode; loff_t origin = *offset; unsigned long pg_start, pg_end; P9_DPRINTK(P9_DEBUG_VFS, "data %p count %d offset %x\n", data, (int)count, (int)*offset); fid = filp->private_data; clnt = fid->clnt; rsize = fid->iounit; if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) rsize = clnt->msize - P9_IOHDRSZ; do { if (count < rsize) rsize = count; n = p9_client_write(fid, NULL, data+total, origin+total, rsize); if (n <= 0) break; count -= n; total += n; } while (count > 0); if (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_write(inode, i_size_read(inode) + total); inode->i_blocks = (i_size_read(inode) + 512 - 1) >> 9; }
/** * v9fs_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_file_write_iter(struct kiocb *iocb, struct iov_iter *from) { struct file *file = iocb->ki_filp; ssize_t retval = 0; loff_t origin = iocb->ki_pos; size_t count = iov_iter_count(from); int err = 0; retval = generic_write_checks(file, &origin, &count, 0); if (retval) return retval; iov_iter_truncate(from, count); if (!count) return 0; 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; }