1ebf46264SAneesh Kumar K.V /* 2ebf46264SAneesh Kumar K.V * Copyright IBM Corporation, 2010 3ebf46264SAneesh Kumar K.V * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> 4ebf46264SAneesh Kumar K.V * 5ebf46264SAneesh Kumar K.V * This program is free software; you can redistribute it and/or modify it 6ebf46264SAneesh Kumar K.V * under the terms of version 2.1 of the GNU Lesser General Public License 7ebf46264SAneesh Kumar K.V * as published by the Free Software Foundation. 8ebf46264SAneesh Kumar K.V * 9ebf46264SAneesh Kumar K.V * This program is distributed in the hope that it would be useful, but 10ebf46264SAneesh Kumar K.V * WITHOUT ANY WARRANTY; without even the implied warranty of 11ebf46264SAneesh Kumar K.V * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12ebf46264SAneesh Kumar K.V * 13ebf46264SAneesh Kumar K.V */ 14ebf46264SAneesh Kumar K.V 15ebf46264SAneesh Kumar K.V #include <linux/module.h> 16ebf46264SAneesh Kumar K.V #include <linux/fs.h> 17ebf46264SAneesh Kumar K.V #include <linux/sched.h> 18070b3656SAl Viro #include <linux/uio.h> 19ebf46264SAneesh Kumar K.V #include <net/9p/9p.h> 20ebf46264SAneesh Kumar K.V #include <net/9p/client.h> 21ebf46264SAneesh Kumar K.V 22ebf46264SAneesh Kumar K.V #include "fid.h" 23ebf46264SAneesh Kumar K.V #include "xattr.h" 24ebf46264SAneesh Kumar K.V 2585ff872dSAneesh Kumar K.V ssize_t v9fs_fid_xattr_get(struct p9_fid *fid, const char *name, 26ebf46264SAneesh Kumar K.V void *buffer, size_t buffer_size) 27ebf46264SAneesh Kumar K.V { 28ebf46264SAneesh Kumar K.V ssize_t retval; 29e1200fe6SAl Viro u64 attr_size; 3085ff872dSAneesh Kumar K.V struct p9_fid *attr_fid; 31e1200fe6SAl Viro struct kvec kvec = {.iov_base = buffer, .iov_len = buffer_size}; 32e1200fe6SAl Viro struct iov_iter to; 33e1200fe6SAl Viro int err; 34e1200fe6SAl Viro 35e1200fe6SAl Viro iov_iter_kvec(&to, READ | ITER_KVEC, &kvec, 1, buffer_size); 36ebf46264SAneesh Kumar K.V 37ebf46264SAneesh Kumar K.V attr_fid = p9_client_xattrwalk(fid, name, &attr_size); 38ebf46264SAneesh Kumar K.V if (IS_ERR(attr_fid)) { 39ebf46264SAneesh Kumar K.V retval = PTR_ERR(attr_fid); 405d385153SJoe Perches p9_debug(P9_DEBUG_VFS, "p9_client_attrwalk failed %zd\n", 415d385153SJoe Perches retval); 42e1200fe6SAl Viro return retval; 43ebf46264SAneesh Kumar K.V } 44ebf46264SAneesh Kumar K.V if (attr_size > buffer_size) { 45e1200fe6SAl Viro if (!buffer_size) /* request to get the attr_size */ 46e1200fe6SAl Viro retval = attr_size; 47ebf46264SAneesh Kumar K.V else 48e1200fe6SAl Viro retval = -ERANGE; 49e1200fe6SAl Viro } else { 50e1200fe6SAl Viro iov_iter_truncate(&to, attr_size); 51e1200fe6SAl Viro retval = p9_client_read(attr_fid, 0, &to, &err); 52e1200fe6SAl Viro if (err) 53e1200fe6SAl Viro retval = err; 54ebf46264SAneesh Kumar K.V } 55ebf46264SAneesh Kumar K.V p9_client_clunk(attr_fid); 56ebf46264SAneesh Kumar K.V return retval; 57ebf46264SAneesh Kumar K.V } 58ebf46264SAneesh Kumar K.V 5985ff872dSAneesh Kumar K.V 6085ff872dSAneesh Kumar K.V /* 6185ff872dSAneesh Kumar K.V * v9fs_xattr_get() 6285ff872dSAneesh Kumar K.V * 6385ff872dSAneesh Kumar K.V * Copy an extended attribute into the buffer 6485ff872dSAneesh Kumar K.V * provided, or compute the buffer size required. 6585ff872dSAneesh Kumar K.V * Buffer is NULL to compute the size of the buffer required. 6685ff872dSAneesh Kumar K.V * 6785ff872dSAneesh Kumar K.V * Returns a negative error number on failure, or the number of bytes 6885ff872dSAneesh Kumar K.V * used / required on success. 6985ff872dSAneesh Kumar K.V */ 7085ff872dSAneesh Kumar K.V ssize_t v9fs_xattr_get(struct dentry *dentry, const char *name, 7185ff872dSAneesh Kumar K.V void *buffer, size_t buffer_size) 7285ff872dSAneesh Kumar K.V { 7385ff872dSAneesh Kumar K.V struct p9_fid *fid; 7485ff872dSAneesh Kumar K.V 755d385153SJoe Perches p9_debug(P9_DEBUG_VFS, "name = %s value_len = %zu\n", 765d385153SJoe Perches name, buffer_size); 7785ff872dSAneesh Kumar K.V fid = v9fs_fid_lookup(dentry); 7885ff872dSAneesh Kumar K.V if (IS_ERR(fid)) 7985ff872dSAneesh Kumar K.V return PTR_ERR(fid); 8085ff872dSAneesh Kumar K.V 8185ff872dSAneesh Kumar K.V return v9fs_fid_xattr_get(fid, name, buffer, buffer_size); 8285ff872dSAneesh Kumar K.V } 8385ff872dSAneesh Kumar K.V 84ebf46264SAneesh Kumar K.V /* 85ebf46264SAneesh Kumar K.V * v9fs_xattr_set() 86ebf46264SAneesh Kumar K.V * 87ebf46264SAneesh Kumar K.V * Create, replace or remove an extended attribute for this inode. Buffer 88ebf46264SAneesh Kumar K.V * is NULL to remove an existing extended attribute, and non-NULL to 89ebf46264SAneesh Kumar K.V * either replace an existing extended attribute, or create a new extended 90ebf46264SAneesh Kumar K.V * attribute. The flags XATTR_REPLACE and XATTR_CREATE 91ebf46264SAneesh Kumar K.V * specify that an extended attribute must exist and must not exist 92ebf46264SAneesh Kumar K.V * previous to the call, respectively. 93ebf46264SAneesh Kumar K.V * 94ebf46264SAneesh Kumar K.V * Returns 0, or a negative error number on failure. 95ebf46264SAneesh Kumar K.V */ 96ebf46264SAneesh Kumar K.V int v9fs_xattr_set(struct dentry *dentry, const char *name, 97ebf46264SAneesh Kumar K.V const void *value, size_t value_len, int flags) 98ebf46264SAneesh Kumar K.V { 9938baba9eSAl Viro struct p9_fid *fid = v9fs_fid_lookup(dentry); 10038baba9eSAl Viro if (IS_ERR(fid)) 10138baba9eSAl Viro return PTR_ERR(fid); 10238baba9eSAl Viro return v9fs_fid_xattr_set(fid, name, value, value_len, flags); 10338baba9eSAl Viro } 10438baba9eSAl Viro 10538baba9eSAl Viro int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name, 10638baba9eSAl Viro const void *value, size_t value_len, int flags) 10738baba9eSAl Viro { 108070b3656SAl Viro struct kvec kvec = {.iov_base = (void *)value, .iov_len = value_len}; 109070b3656SAl Viro struct iov_iter from; 110070b3656SAl Viro int retval; 111070b3656SAl Viro 112070b3656SAl Viro iov_iter_kvec(&from, WRITE | ITER_KVEC, &kvec, 1, value_len); 113ebf46264SAneesh Kumar K.V 1145d385153SJoe Perches p9_debug(P9_DEBUG_VFS, "name = %s value_len = %zu flags = %d\n", 1155d385153SJoe Perches name, value_len, flags); 116ebf46264SAneesh Kumar K.V 11738baba9eSAl Viro /* Clone it */ 11838baba9eSAl Viro fid = p9_client_walk(fid, 0, NULL, 1); 11938baba9eSAl Viro if (IS_ERR(fid)) 12038baba9eSAl Viro return PTR_ERR(fid); 12138baba9eSAl Viro 122ebf46264SAneesh Kumar K.V /* 123ebf46264SAneesh Kumar K.V * On success fid points to xattr 124ebf46264SAneesh Kumar K.V */ 125ebf46264SAneesh Kumar K.V retval = p9_client_xattrcreate(fid, name, value_len, flags); 126070b3656SAl Viro if (retval < 0) 1275d385153SJoe Perches p9_debug(P9_DEBUG_VFS, "p9_client_xattrcreate failed %d\n", 1285d385153SJoe Perches retval); 129ebf46264SAneesh Kumar K.V else 130070b3656SAl Viro p9_client_write(fid, 0, &from, &retval); 131bdd5c28dSGeyslan G. Bem p9_client_clunk(fid); 132bdd5c28dSGeyslan G. Bem return retval; 133ebf46264SAneesh Kumar K.V } 134ebf46264SAneesh Kumar K.V 135ebf46264SAneesh Kumar K.V ssize_t v9fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size) 136ebf46264SAneesh Kumar K.V { 137ebf46264SAneesh Kumar K.V return v9fs_xattr_get(dentry, NULL, buffer, buffer_size); 138ebf46264SAneesh Kumar K.V } 139ebf46264SAneesh Kumar K.V 140e409de99SAndreas Gruenbacher static int v9fs_xattr_handler_get(const struct xattr_handler *handler, 141b296821aSAl Viro struct dentry *dentry, struct inode *inode, 142b296821aSAl Viro const char *name, void *buffer, size_t size) 143e409de99SAndreas Gruenbacher { 144e409de99SAndreas Gruenbacher const char *full_name = xattr_full_name(handler, name); 145e409de99SAndreas Gruenbacher 146e409de99SAndreas Gruenbacher return v9fs_xattr_get(dentry, full_name, buffer, size); 147e409de99SAndreas Gruenbacher } 148e409de99SAndreas Gruenbacher 149e409de99SAndreas Gruenbacher static int v9fs_xattr_handler_set(const struct xattr_handler *handler, 150*59301226SAl Viro struct dentry *dentry, struct inode *inode, 151*59301226SAl Viro const char *name, const void *value, 152*59301226SAl Viro size_t size, int flags) 153e409de99SAndreas Gruenbacher { 154e409de99SAndreas Gruenbacher const char *full_name = xattr_full_name(handler, name); 155e409de99SAndreas Gruenbacher 156e409de99SAndreas Gruenbacher return v9fs_xattr_set(dentry, full_name, value, size, flags); 157e409de99SAndreas Gruenbacher } 158e409de99SAndreas Gruenbacher 159e409de99SAndreas Gruenbacher static struct xattr_handler v9fs_xattr_user_handler = { 160e409de99SAndreas Gruenbacher .prefix = XATTR_USER_PREFIX, 161e409de99SAndreas Gruenbacher .get = v9fs_xattr_handler_get, 162e409de99SAndreas Gruenbacher .set = v9fs_xattr_handler_set, 163e409de99SAndreas Gruenbacher }; 164e409de99SAndreas Gruenbacher 165e409de99SAndreas Gruenbacher static struct xattr_handler v9fs_xattr_trusted_handler = { 166e409de99SAndreas Gruenbacher .prefix = XATTR_TRUSTED_PREFIX, 167e409de99SAndreas Gruenbacher .get = v9fs_xattr_handler_get, 168e409de99SAndreas Gruenbacher .set = v9fs_xattr_handler_set, 169e409de99SAndreas Gruenbacher }; 170e409de99SAndreas Gruenbacher 171e409de99SAndreas Gruenbacher #ifdef CONFIG_9P_FS_SECURITY 172e409de99SAndreas Gruenbacher static struct xattr_handler v9fs_xattr_security_handler = { 173e409de99SAndreas Gruenbacher .prefix = XATTR_SECURITY_PREFIX, 174e409de99SAndreas Gruenbacher .get = v9fs_xattr_handler_get, 175e409de99SAndreas Gruenbacher .set = v9fs_xattr_handler_set, 176e409de99SAndreas Gruenbacher }; 177e409de99SAndreas Gruenbacher #endif 178e409de99SAndreas Gruenbacher 179ebf46264SAneesh Kumar K.V const struct xattr_handler *v9fs_xattr_handlers[] = { 180ebf46264SAneesh Kumar K.V &v9fs_xattr_user_handler, 181d9a73859SJim Garlick &v9fs_xattr_trusted_handler, 1827a4566b0SAneesh Kumar K.V #ifdef CONFIG_9P_FS_POSIX_ACL 1837a4566b0SAneesh Kumar K.V &v9fs_xattr_acl_access_handler, 1847a4566b0SAneesh Kumar K.V &v9fs_xattr_acl_default_handler, 1857a4566b0SAneesh Kumar K.V #endif 186d9a73859SJim Garlick #ifdef CONFIG_9P_FS_SECURITY 187d9a73859SJim Garlick &v9fs_xattr_security_handler, 188d9a73859SJim Garlick #endif 189ebf46264SAneesh Kumar K.V NULL 190ebf46264SAneesh Kumar K.V }; 191