1eda14cbcSMatt Macy /* 2eda14cbcSMatt Macy * CDDL HEADER START 3eda14cbcSMatt Macy * 4eda14cbcSMatt Macy * The contents of this file are subject to the terms of the 5eda14cbcSMatt Macy * Common Development and Distribution License (the "License"). 6eda14cbcSMatt Macy * You may not use this file except in compliance with the License. 7eda14cbcSMatt Macy * 8eda14cbcSMatt Macy * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9271171e0SMartin Matuska * or https://opensource.org/licenses/CDDL-1.0. 10eda14cbcSMatt Macy * See the License for the specific language governing permissions 11eda14cbcSMatt Macy * and limitations under the License. 12eda14cbcSMatt Macy * 13eda14cbcSMatt Macy * When distributing Covered Code, include this CDDL HEADER in each 14eda14cbcSMatt Macy * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15eda14cbcSMatt Macy * If applicable, add the following below this CDDL HEADER, with the 16eda14cbcSMatt Macy * fields enclosed by brackets "[]" replaced with your own identifying 17eda14cbcSMatt Macy * information: Portions Copyright [yyyy] [name of copyright owner] 18eda14cbcSMatt Macy * 19eda14cbcSMatt Macy * CDDL HEADER END 20eda14cbcSMatt Macy */ 21eda14cbcSMatt Macy /* 22eda14cbcSMatt Macy * Copyright (c) 2011, Lawrence Livermore National Security, LLC. 23eda14cbcSMatt Macy * 24eda14cbcSMatt Macy * Extended attributes (xattr) on Solaris are implemented as files 25eda14cbcSMatt Macy * which exist in a hidden xattr directory. These extended attributes 26eda14cbcSMatt Macy * can be accessed using the attropen() system call which opens 27eda14cbcSMatt Macy * the extended attribute. It can then be manipulated just like 28eda14cbcSMatt Macy * a standard file descriptor. This has a couple advantages such 29eda14cbcSMatt Macy * as practically no size limit on the file, and the extended 30eda14cbcSMatt Macy * attributes permissions may differ from those of the parent file. 31eda14cbcSMatt Macy * This interface is really quite clever, but it's also completely 32eda14cbcSMatt Macy * different than what is supported on Linux. It also comes with a 33eda14cbcSMatt Macy * steep performance penalty when accessing small xattrs because they 34eda14cbcSMatt Macy * are not stored with the parent file. 35eda14cbcSMatt Macy * 36eda14cbcSMatt Macy * Under Linux extended attributes are manipulated by the system 37eda14cbcSMatt Macy * calls getxattr(2), setxattr(2), and listxattr(2). They consider 38eda14cbcSMatt Macy * extended attributes to be name/value pairs where the name is a 39eda14cbcSMatt Macy * NULL terminated string. The name must also include one of the 40eda14cbcSMatt Macy * following namespace prefixes: 41eda14cbcSMatt Macy * 42eda14cbcSMatt Macy * user - No restrictions and is available to user applications. 43eda14cbcSMatt Macy * trusted - Restricted to kernel and root (CAP_SYS_ADMIN) use. 44eda14cbcSMatt Macy * system - Used for access control lists (system.nfs4_acl, etc). 45eda14cbcSMatt Macy * security - Used by SELinux to store a files security context. 46eda14cbcSMatt Macy * 47eda14cbcSMatt Macy * The value under Linux to limited to 65536 bytes of binary data. 48eda14cbcSMatt Macy * In practice, individual xattrs tend to be much smaller than this 49eda14cbcSMatt Macy * and are typically less than 100 bytes. A good example of this 50eda14cbcSMatt Macy * are the security.selinux xattrs which are less than 100 bytes and 51eda14cbcSMatt Macy * exist for every file when xattr labeling is enabled. 52eda14cbcSMatt Macy * 53eda14cbcSMatt Macy * The Linux xattr implementation has been written to take advantage of 54eda14cbcSMatt Macy * this typical usage. When the dataset property 'xattr=sa' is set, 55eda14cbcSMatt Macy * then xattrs will be preferentially stored as System Attributes (SA). 56eda14cbcSMatt Macy * This allows tiny xattrs (~100 bytes) to be stored with the dnode and 57eda14cbcSMatt Macy * up to 64k of xattrs to be stored in the spill block. If additional 58eda14cbcSMatt Macy * xattr space is required, which is unlikely under Linux, they will 59eda14cbcSMatt Macy * be stored using the traditional directory approach. 60eda14cbcSMatt Macy * 61eda14cbcSMatt Macy * This optimization results in roughly a 3x performance improvement 62eda14cbcSMatt Macy * when accessing xattrs because it avoids the need to perform a seek 63eda14cbcSMatt Macy * for every xattr value. When multiple xattrs are stored per-file 64eda14cbcSMatt Macy * the performance improvements are even greater because all of the 65eda14cbcSMatt Macy * xattrs stored in the spill block will be cached. 66eda14cbcSMatt Macy * 67eda14cbcSMatt Macy * However, by default SA based xattrs are disabled in the Linux port 68eda14cbcSMatt Macy * to maximize compatibility with other implementations. If you do 69eda14cbcSMatt Macy * enable SA based xattrs then they will not be visible on platforms 70eda14cbcSMatt Macy * which do not support this feature. 71eda14cbcSMatt Macy * 72eda14cbcSMatt Macy * NOTE: One additional consequence of the xattr directory implementation 73eda14cbcSMatt Macy * is that when an extended attribute is manipulated an inode is created. 74eda14cbcSMatt Macy * This inode will exist in the Linux inode cache but there will be no 75eda14cbcSMatt Macy * associated entry in the dentry cache which references it. This is 76eda14cbcSMatt Macy * safe but it may result in some confusion. Enabling SA based xattrs 77eda14cbcSMatt Macy * largely avoids the issue except in the overflow case. 78eda14cbcSMatt Macy */ 79eda14cbcSMatt Macy 80eda14cbcSMatt Macy #include <sys/zfs_znode.h> 81eda14cbcSMatt Macy #include <sys/zfs_vfsops.h> 82eda14cbcSMatt Macy #include <sys/zfs_vnops.h> 83eda14cbcSMatt Macy #include <sys/zap.h> 84eda14cbcSMatt Macy #include <sys/vfs.h> 85eda14cbcSMatt Macy #include <sys/zpl.h> 861f1e2261SMartin Matuska #include <linux/vfs_compat.h> 87eda14cbcSMatt Macy 88c03c5b1cSMartin Matuska enum xattr_permission { 89c03c5b1cSMartin Matuska XAPERM_DENY, 90c03c5b1cSMartin Matuska XAPERM_ALLOW, 91c03c5b1cSMartin Matuska XAPERM_COMPAT, 92c03c5b1cSMartin Matuska }; 93c03c5b1cSMartin Matuska 94eda14cbcSMatt Macy typedef struct xattr_filldir { 95eda14cbcSMatt Macy size_t size; 96eda14cbcSMatt Macy size_t offset; 97eda14cbcSMatt Macy char *buf; 98eda14cbcSMatt Macy struct dentry *dentry; 99eda14cbcSMatt Macy } xattr_filldir_t; 100eda14cbcSMatt Macy 101c03c5b1cSMartin Matuska static enum xattr_permission zpl_xattr_permission(xattr_filldir_t *, 102c03c5b1cSMartin Matuska const char *, int); 103eda14cbcSMatt Macy 104c03c5b1cSMartin Matuska static int zfs_xattr_compat = 0; 105eda14cbcSMatt Macy 106eda14cbcSMatt Macy /* 107eda14cbcSMatt Macy * Determine is a given xattr name should be visible and if so copy it 108eda14cbcSMatt Macy * in to the provided buffer (xf->buf). 109eda14cbcSMatt Macy */ 110eda14cbcSMatt Macy static int 111eda14cbcSMatt Macy zpl_xattr_filldir(xattr_filldir_t *xf, const char *name, int name_len) 112eda14cbcSMatt Macy { 113c03c5b1cSMartin Matuska enum xattr_permission perm; 114c03c5b1cSMartin Matuska 115eda14cbcSMatt Macy /* Check permissions using the per-namespace list xattr handler. */ 116c03c5b1cSMartin Matuska perm = zpl_xattr_permission(xf, name, name_len); 117c03c5b1cSMartin Matuska if (perm == XAPERM_DENY) 118eda14cbcSMatt Macy return (0); 119eda14cbcSMatt Macy 120c03c5b1cSMartin Matuska /* Prefix the name with "user." if it does not have a namespace. */ 121c03c5b1cSMartin Matuska if (perm == XAPERM_COMPAT) { 122c03c5b1cSMartin Matuska if (xf->buf) { 123c03c5b1cSMartin Matuska if (xf->offset + XATTR_USER_PREFIX_LEN + 1 > xf->size) 124c03c5b1cSMartin Matuska return (-ERANGE); 125c03c5b1cSMartin Matuska 126c03c5b1cSMartin Matuska memcpy(xf->buf + xf->offset, XATTR_USER_PREFIX, 127c03c5b1cSMartin Matuska XATTR_USER_PREFIX_LEN); 128c03c5b1cSMartin Matuska xf->buf[xf->offset + XATTR_USER_PREFIX_LEN] = '\0'; 129c03c5b1cSMartin Matuska } 130c03c5b1cSMartin Matuska 131c03c5b1cSMartin Matuska xf->offset += XATTR_USER_PREFIX_LEN; 132c03c5b1cSMartin Matuska } 133c03c5b1cSMartin Matuska 134eda14cbcSMatt Macy /* When xf->buf is NULL only calculate the required size. */ 135eda14cbcSMatt Macy if (xf->buf) { 136eda14cbcSMatt Macy if (xf->offset + name_len + 1 > xf->size) 137eda14cbcSMatt Macy return (-ERANGE); 138eda14cbcSMatt Macy 139eda14cbcSMatt Macy memcpy(xf->buf + xf->offset, name, name_len); 140eda14cbcSMatt Macy xf->buf[xf->offset + name_len] = '\0'; 141eda14cbcSMatt Macy } 142eda14cbcSMatt Macy 143eda14cbcSMatt Macy xf->offset += (name_len + 1); 144eda14cbcSMatt Macy 145eda14cbcSMatt Macy return (0); 146eda14cbcSMatt Macy } 147eda14cbcSMatt Macy 148eda14cbcSMatt Macy /* 149eda14cbcSMatt Macy * Read as many directory entry names as will fit in to the provided buffer, 150eda14cbcSMatt Macy * or when no buffer is provided calculate the required buffer size. 151eda14cbcSMatt Macy */ 152eda14cbcSMatt Macy static int 153eda14cbcSMatt Macy zpl_xattr_readdir(struct inode *dxip, xattr_filldir_t *xf) 154eda14cbcSMatt Macy { 155eda14cbcSMatt Macy zap_cursor_t zc; 156*7a7741afSMartin Matuska zap_attribute_t *zap = zap_attribute_alloc(); 157eda14cbcSMatt Macy int error; 158eda14cbcSMatt Macy 159eda14cbcSMatt Macy zap_cursor_init(&zc, ITOZSB(dxip)->z_os, ITOZ(dxip)->z_id); 160eda14cbcSMatt Macy 161*7a7741afSMartin Matuska while ((error = -zap_cursor_retrieve(&zc, zap)) == 0) { 162eda14cbcSMatt Macy 163*7a7741afSMartin Matuska if (zap->za_integer_length != 8 || zap->za_num_integers != 1) { 164eda14cbcSMatt Macy error = -ENXIO; 165eda14cbcSMatt Macy break; 166eda14cbcSMatt Macy } 167eda14cbcSMatt Macy 168*7a7741afSMartin Matuska error = zpl_xattr_filldir(xf, zap->za_name, 169*7a7741afSMartin Matuska strlen(zap->za_name)); 170eda14cbcSMatt Macy if (error) 171eda14cbcSMatt Macy break; 172eda14cbcSMatt Macy 173eda14cbcSMatt Macy zap_cursor_advance(&zc); 174eda14cbcSMatt Macy } 175eda14cbcSMatt Macy 176eda14cbcSMatt Macy zap_cursor_fini(&zc); 177*7a7741afSMartin Matuska zap_attribute_free(zap); 178eda14cbcSMatt Macy 179eda14cbcSMatt Macy if (error == -ENOENT) 180eda14cbcSMatt Macy error = 0; 181eda14cbcSMatt Macy 182eda14cbcSMatt Macy return (error); 183eda14cbcSMatt Macy } 184eda14cbcSMatt Macy 185eda14cbcSMatt Macy static ssize_t 186eda14cbcSMatt Macy zpl_xattr_list_dir(xattr_filldir_t *xf, cred_t *cr) 187eda14cbcSMatt Macy { 188eda14cbcSMatt Macy struct inode *ip = xf->dentry->d_inode; 189eda14cbcSMatt Macy struct inode *dxip = NULL; 190eda14cbcSMatt Macy znode_t *dxzp; 191eda14cbcSMatt Macy int error; 192eda14cbcSMatt Macy 193eda14cbcSMatt Macy /* Lookup the xattr directory */ 194eda14cbcSMatt Macy error = -zfs_lookup(ITOZ(ip), NULL, &dxzp, LOOKUP_XATTR, 195eda14cbcSMatt Macy cr, NULL, NULL); 196eda14cbcSMatt Macy if (error) { 197eda14cbcSMatt Macy if (error == -ENOENT) 198eda14cbcSMatt Macy error = 0; 199eda14cbcSMatt Macy 200eda14cbcSMatt Macy return (error); 201eda14cbcSMatt Macy } 202eda14cbcSMatt Macy 203eda14cbcSMatt Macy dxip = ZTOI(dxzp); 204eda14cbcSMatt Macy error = zpl_xattr_readdir(dxip, xf); 205eda14cbcSMatt Macy iput(dxip); 206eda14cbcSMatt Macy 207eda14cbcSMatt Macy return (error); 208eda14cbcSMatt Macy } 209eda14cbcSMatt Macy 210eda14cbcSMatt Macy static ssize_t 211eda14cbcSMatt Macy zpl_xattr_list_sa(xattr_filldir_t *xf) 212eda14cbcSMatt Macy { 213eda14cbcSMatt Macy znode_t *zp = ITOZ(xf->dentry->d_inode); 214eda14cbcSMatt Macy nvpair_t *nvp = NULL; 215eda14cbcSMatt Macy int error = 0; 216eda14cbcSMatt Macy 217eda14cbcSMatt Macy mutex_enter(&zp->z_lock); 218eda14cbcSMatt Macy if (zp->z_xattr_cached == NULL) 219eda14cbcSMatt Macy error = -zfs_sa_get_xattr(zp); 220eda14cbcSMatt Macy mutex_exit(&zp->z_lock); 221eda14cbcSMatt Macy 222eda14cbcSMatt Macy if (error) 223eda14cbcSMatt Macy return (error); 224eda14cbcSMatt Macy 225eda14cbcSMatt Macy ASSERT(zp->z_xattr_cached); 226eda14cbcSMatt Macy 227eda14cbcSMatt Macy while ((nvp = nvlist_next_nvpair(zp->z_xattr_cached, nvp)) != NULL) { 228eda14cbcSMatt Macy ASSERT3U(nvpair_type(nvp), ==, DATA_TYPE_BYTE_ARRAY); 229eda14cbcSMatt Macy 230eda14cbcSMatt Macy error = zpl_xattr_filldir(xf, nvpair_name(nvp), 231eda14cbcSMatt Macy strlen(nvpair_name(nvp))); 232eda14cbcSMatt Macy if (error) 233eda14cbcSMatt Macy return (error); 234eda14cbcSMatt Macy } 235eda14cbcSMatt Macy 236eda14cbcSMatt Macy return (0); 237eda14cbcSMatt Macy } 238eda14cbcSMatt Macy 239eda14cbcSMatt Macy ssize_t 240eda14cbcSMatt Macy zpl_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size) 241eda14cbcSMatt Macy { 242eda14cbcSMatt Macy znode_t *zp = ITOZ(dentry->d_inode); 243eda14cbcSMatt Macy zfsvfs_t *zfsvfs = ZTOZSB(zp); 244eda14cbcSMatt Macy xattr_filldir_t xf = { buffer_size, 0, buffer, dentry }; 245eda14cbcSMatt Macy cred_t *cr = CRED(); 246eda14cbcSMatt Macy fstrans_cookie_t cookie; 247eda14cbcSMatt Macy int error = 0; 248eda14cbcSMatt Macy 249eda14cbcSMatt Macy crhold(cr); 250eda14cbcSMatt Macy cookie = spl_fstrans_mark(); 251c7046f76SMartin Matuska if ((error = zpl_enter_verify_zp(zfsvfs, zp, FTAG)) != 0) 252c7046f76SMartin Matuska goto out1; 253eda14cbcSMatt Macy rw_enter(&zp->z_xattr_lock, RW_READER); 254eda14cbcSMatt Macy 255eda14cbcSMatt Macy if (zfsvfs->z_use_sa && zp->z_is_sa) { 256eda14cbcSMatt Macy error = zpl_xattr_list_sa(&xf); 257eda14cbcSMatt Macy if (error) 258eda14cbcSMatt Macy goto out; 259eda14cbcSMatt Macy } 260eda14cbcSMatt Macy 261eda14cbcSMatt Macy error = zpl_xattr_list_dir(&xf, cr); 262eda14cbcSMatt Macy if (error) 263eda14cbcSMatt Macy goto out; 264eda14cbcSMatt Macy 265eda14cbcSMatt Macy error = xf.offset; 266eda14cbcSMatt Macy out: 267eda14cbcSMatt Macy 268eda14cbcSMatt Macy rw_exit(&zp->z_xattr_lock); 269c7046f76SMartin Matuska zpl_exit(zfsvfs, FTAG); 270c7046f76SMartin Matuska out1: 271eda14cbcSMatt Macy spl_fstrans_unmark(cookie); 272eda14cbcSMatt Macy crfree(cr); 273eda14cbcSMatt Macy 274eda14cbcSMatt Macy return (error); 275eda14cbcSMatt Macy } 276eda14cbcSMatt Macy 277eda14cbcSMatt Macy static int 278eda14cbcSMatt Macy zpl_xattr_get_dir(struct inode *ip, const char *name, void *value, 279eda14cbcSMatt Macy size_t size, cred_t *cr) 280eda14cbcSMatt Macy { 2817877fdebSMatt Macy fstrans_cookie_t cookie; 282eda14cbcSMatt Macy struct inode *xip = NULL; 283eda14cbcSMatt Macy znode_t *dxzp = NULL; 284eda14cbcSMatt Macy znode_t *xzp = NULL; 285eda14cbcSMatt Macy int error; 286eda14cbcSMatt Macy 287eda14cbcSMatt Macy /* Lookup the xattr directory */ 288eda14cbcSMatt Macy error = -zfs_lookup(ITOZ(ip), NULL, &dxzp, LOOKUP_XATTR, 289eda14cbcSMatt Macy cr, NULL, NULL); 290eda14cbcSMatt Macy if (error) 291eda14cbcSMatt Macy goto out; 292eda14cbcSMatt Macy 293eda14cbcSMatt Macy /* Lookup a specific xattr name in the directory */ 294eda14cbcSMatt Macy error = -zfs_lookup(dxzp, (char *)name, &xzp, 0, cr, NULL, NULL); 295eda14cbcSMatt Macy if (error) 296eda14cbcSMatt Macy goto out; 297eda14cbcSMatt Macy 298eda14cbcSMatt Macy xip = ZTOI(xzp); 299eda14cbcSMatt Macy if (!size) { 300eda14cbcSMatt Macy error = i_size_read(xip); 301eda14cbcSMatt Macy goto out; 302eda14cbcSMatt Macy } 303eda14cbcSMatt Macy 304eda14cbcSMatt Macy if (size < i_size_read(xip)) { 305eda14cbcSMatt Macy error = -ERANGE; 306eda14cbcSMatt Macy goto out; 307eda14cbcSMatt Macy } 308eda14cbcSMatt Macy 3097877fdebSMatt Macy struct iovec iov; 3107877fdebSMatt Macy iov.iov_base = (void *)value; 3117877fdebSMatt Macy iov.iov_len = size; 3127877fdebSMatt Macy 313184c1b94SMartin Matuska zfs_uio_t uio; 314184c1b94SMartin Matuska zfs_uio_iovec_init(&uio, &iov, 1, 0, UIO_SYSSPACE, size, 0); 3157877fdebSMatt Macy 3167877fdebSMatt Macy cookie = spl_fstrans_mark(); 3177877fdebSMatt Macy error = -zfs_read(ITOZ(xip), &uio, 0, cr); 3187877fdebSMatt Macy spl_fstrans_unmark(cookie); 3197877fdebSMatt Macy 3207877fdebSMatt Macy if (error == 0) 321184c1b94SMartin Matuska error = size - zfs_uio_resid(&uio); 322eda14cbcSMatt Macy out: 323eda14cbcSMatt Macy if (xzp) 324eda14cbcSMatt Macy zrele(xzp); 325eda14cbcSMatt Macy 326eda14cbcSMatt Macy if (dxzp) 327eda14cbcSMatt Macy zrele(dxzp); 328eda14cbcSMatt Macy 329eda14cbcSMatt Macy return (error); 330eda14cbcSMatt Macy } 331eda14cbcSMatt Macy 332eda14cbcSMatt Macy static int 333eda14cbcSMatt Macy zpl_xattr_get_sa(struct inode *ip, const char *name, void *value, size_t size) 334eda14cbcSMatt Macy { 335eda14cbcSMatt Macy znode_t *zp = ITOZ(ip); 336eda14cbcSMatt Macy uchar_t *nv_value; 337eda14cbcSMatt Macy uint_t nv_size; 338eda14cbcSMatt Macy int error = 0; 339eda14cbcSMatt Macy 340eda14cbcSMatt Macy ASSERT(RW_LOCK_HELD(&zp->z_xattr_lock)); 341eda14cbcSMatt Macy 342eda14cbcSMatt Macy mutex_enter(&zp->z_lock); 343eda14cbcSMatt Macy if (zp->z_xattr_cached == NULL) 344eda14cbcSMatt Macy error = -zfs_sa_get_xattr(zp); 345eda14cbcSMatt Macy mutex_exit(&zp->z_lock); 346eda14cbcSMatt Macy 347eda14cbcSMatt Macy if (error) 348eda14cbcSMatt Macy return (error); 349eda14cbcSMatt Macy 350eda14cbcSMatt Macy ASSERT(zp->z_xattr_cached); 351eda14cbcSMatt Macy error = -nvlist_lookup_byte_array(zp->z_xattr_cached, name, 352eda14cbcSMatt Macy &nv_value, &nv_size); 353eda14cbcSMatt Macy if (error) 354eda14cbcSMatt Macy return (error); 355eda14cbcSMatt Macy 356eda14cbcSMatt Macy if (size == 0 || value == NULL) 357eda14cbcSMatt Macy return (nv_size); 358eda14cbcSMatt Macy 359eda14cbcSMatt Macy if (size < nv_size) 360eda14cbcSMatt Macy return (-ERANGE); 361eda14cbcSMatt Macy 362eda14cbcSMatt Macy memcpy(value, nv_value, nv_size); 363eda14cbcSMatt Macy 364eda14cbcSMatt Macy return (nv_size); 365eda14cbcSMatt Macy } 366eda14cbcSMatt Macy 367eda14cbcSMatt Macy static int 368eda14cbcSMatt Macy __zpl_xattr_get(struct inode *ip, const char *name, void *value, size_t size, 369eda14cbcSMatt Macy cred_t *cr) 370eda14cbcSMatt Macy { 371eda14cbcSMatt Macy znode_t *zp = ITOZ(ip); 372eda14cbcSMatt Macy zfsvfs_t *zfsvfs = ZTOZSB(zp); 373eda14cbcSMatt Macy int error; 374eda14cbcSMatt Macy 375eda14cbcSMatt Macy ASSERT(RW_LOCK_HELD(&zp->z_xattr_lock)); 376eda14cbcSMatt Macy 377eda14cbcSMatt Macy if (zfsvfs->z_use_sa && zp->z_is_sa) { 378eda14cbcSMatt Macy error = zpl_xattr_get_sa(ip, name, value, size); 379eda14cbcSMatt Macy if (error != -ENOENT) 380eda14cbcSMatt Macy goto out; 381eda14cbcSMatt Macy } 382eda14cbcSMatt Macy 383eda14cbcSMatt Macy error = zpl_xattr_get_dir(ip, name, value, size, cr); 384eda14cbcSMatt Macy out: 385eda14cbcSMatt Macy if (error == -ENOENT) 386eda14cbcSMatt Macy error = -ENODATA; 387eda14cbcSMatt Macy 388eda14cbcSMatt Macy return (error); 389eda14cbcSMatt Macy } 390eda14cbcSMatt Macy 391eda14cbcSMatt Macy #define XATTR_NOENT 0x0 392eda14cbcSMatt Macy #define XATTR_IN_SA 0x1 393eda14cbcSMatt Macy #define XATTR_IN_DIR 0x2 394eda14cbcSMatt Macy /* check where the xattr resides */ 395eda14cbcSMatt Macy static int 396eda14cbcSMatt Macy __zpl_xattr_where(struct inode *ip, const char *name, int *where, cred_t *cr) 397eda14cbcSMatt Macy { 398eda14cbcSMatt Macy znode_t *zp = ITOZ(ip); 399eda14cbcSMatt Macy zfsvfs_t *zfsvfs = ZTOZSB(zp); 400eda14cbcSMatt Macy int error; 401eda14cbcSMatt Macy 402eda14cbcSMatt Macy ASSERT(where); 403eda14cbcSMatt Macy ASSERT(RW_LOCK_HELD(&zp->z_xattr_lock)); 404eda14cbcSMatt Macy 405eda14cbcSMatt Macy *where = XATTR_NOENT; 406eda14cbcSMatt Macy if (zfsvfs->z_use_sa && zp->z_is_sa) { 407eda14cbcSMatt Macy error = zpl_xattr_get_sa(ip, name, NULL, 0); 408eda14cbcSMatt Macy if (error >= 0) 409eda14cbcSMatt Macy *where |= XATTR_IN_SA; 410eda14cbcSMatt Macy else if (error != -ENOENT) 411eda14cbcSMatt Macy return (error); 412eda14cbcSMatt Macy } 413eda14cbcSMatt Macy 414eda14cbcSMatt Macy error = zpl_xattr_get_dir(ip, name, NULL, 0, cr); 415eda14cbcSMatt Macy if (error >= 0) 416eda14cbcSMatt Macy *where |= XATTR_IN_DIR; 417eda14cbcSMatt Macy else if (error != -ENOENT) 418eda14cbcSMatt Macy return (error); 419eda14cbcSMatt Macy 420eda14cbcSMatt Macy if (*where == (XATTR_IN_SA|XATTR_IN_DIR)) 421eda14cbcSMatt Macy cmn_err(CE_WARN, "ZFS: inode %p has xattr \"%s\"" 422eda14cbcSMatt Macy " in both SA and dir", ip, name); 423eda14cbcSMatt Macy if (*where == XATTR_NOENT) 424eda14cbcSMatt Macy error = -ENODATA; 425eda14cbcSMatt Macy else 426eda14cbcSMatt Macy error = 0; 427eda14cbcSMatt Macy return (error); 428eda14cbcSMatt Macy } 429eda14cbcSMatt Macy 430eda14cbcSMatt Macy static int 431eda14cbcSMatt Macy zpl_xattr_get(struct inode *ip, const char *name, void *value, size_t size) 432eda14cbcSMatt Macy { 433eda14cbcSMatt Macy znode_t *zp = ITOZ(ip); 434eda14cbcSMatt Macy zfsvfs_t *zfsvfs = ZTOZSB(zp); 435eda14cbcSMatt Macy cred_t *cr = CRED(); 436eda14cbcSMatt Macy fstrans_cookie_t cookie; 437eda14cbcSMatt Macy int error; 438eda14cbcSMatt Macy 439eda14cbcSMatt Macy crhold(cr); 440eda14cbcSMatt Macy cookie = spl_fstrans_mark(); 441c7046f76SMartin Matuska if ((error = zpl_enter_verify_zp(zfsvfs, zp, FTAG)) != 0) 442c7046f76SMartin Matuska goto out; 443eda14cbcSMatt Macy rw_enter(&zp->z_xattr_lock, RW_READER); 444eda14cbcSMatt Macy error = __zpl_xattr_get(ip, name, value, size, cr); 445eda14cbcSMatt Macy rw_exit(&zp->z_xattr_lock); 446c7046f76SMartin Matuska zpl_exit(zfsvfs, FTAG); 447c7046f76SMartin Matuska out: 448eda14cbcSMatt Macy spl_fstrans_unmark(cookie); 449eda14cbcSMatt Macy crfree(cr); 450eda14cbcSMatt Macy 451eda14cbcSMatt Macy return (error); 452eda14cbcSMatt Macy } 453eda14cbcSMatt Macy 454eda14cbcSMatt Macy static int 455eda14cbcSMatt Macy zpl_xattr_set_dir(struct inode *ip, const char *name, const void *value, 456eda14cbcSMatt Macy size_t size, int flags, cred_t *cr) 457eda14cbcSMatt Macy { 458eda14cbcSMatt Macy znode_t *dxzp = NULL; 459eda14cbcSMatt Macy znode_t *xzp = NULL; 460eda14cbcSMatt Macy vattr_t *vap = NULL; 461eda14cbcSMatt Macy int lookup_flags, error; 462eda14cbcSMatt Macy const int xattr_mode = S_IFREG | 0644; 463eda14cbcSMatt Macy loff_t pos = 0; 464eda14cbcSMatt Macy 465eda14cbcSMatt Macy /* 466eda14cbcSMatt Macy * Lookup the xattr directory. When we're adding an entry pass 467eda14cbcSMatt Macy * CREATE_XATTR_DIR to ensure the xattr directory is created. 468eda14cbcSMatt Macy * When removing an entry this flag is not passed to avoid 469eda14cbcSMatt Macy * unnecessarily creating a new xattr directory. 470eda14cbcSMatt Macy */ 471eda14cbcSMatt Macy lookup_flags = LOOKUP_XATTR; 472eda14cbcSMatt Macy if (value != NULL) 473eda14cbcSMatt Macy lookup_flags |= CREATE_XATTR_DIR; 474eda14cbcSMatt Macy 475eda14cbcSMatt Macy error = -zfs_lookup(ITOZ(ip), NULL, &dxzp, lookup_flags, 476eda14cbcSMatt Macy cr, NULL, NULL); 477eda14cbcSMatt Macy if (error) 478eda14cbcSMatt Macy goto out; 479eda14cbcSMatt Macy 480eda14cbcSMatt Macy /* Lookup a specific xattr name in the directory */ 481eda14cbcSMatt Macy error = -zfs_lookup(dxzp, (char *)name, &xzp, 0, cr, NULL, NULL); 482eda14cbcSMatt Macy if (error && (error != -ENOENT)) 483eda14cbcSMatt Macy goto out; 484eda14cbcSMatt Macy 485eda14cbcSMatt Macy error = 0; 486eda14cbcSMatt Macy 487eda14cbcSMatt Macy /* Remove a specific name xattr when value is set to NULL. */ 488eda14cbcSMatt Macy if (value == NULL) { 489eda14cbcSMatt Macy if (xzp) 490eda14cbcSMatt Macy error = -zfs_remove(dxzp, (char *)name, cr, 0); 491eda14cbcSMatt Macy 492eda14cbcSMatt Macy goto out; 493eda14cbcSMatt Macy } 494eda14cbcSMatt Macy 495eda14cbcSMatt Macy /* Lookup failed create a new xattr. */ 496eda14cbcSMatt Macy if (xzp == NULL) { 497eda14cbcSMatt Macy vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP); 498eda14cbcSMatt Macy vap->va_mode = xattr_mode; 499eda14cbcSMatt Macy vap->va_mask = ATTR_MODE; 500da5137abSMartin Matuska vap->va_uid = crgetuid(cr); 501da5137abSMartin Matuska vap->va_gid = crgetgid(cr); 502eda14cbcSMatt Macy 503eda14cbcSMatt Macy error = -zfs_create(dxzp, (char *)name, vap, 0, 0644, &xzp, 504d411c1d6SMartin Matuska cr, ATTR_NOACLCHECK, NULL, zfs_init_idmap); 505eda14cbcSMatt Macy if (error) 506eda14cbcSMatt Macy goto out; 507eda14cbcSMatt Macy } 508eda14cbcSMatt Macy 509eda14cbcSMatt Macy ASSERT(xzp != NULL); 510eda14cbcSMatt Macy 511eda14cbcSMatt Macy error = -zfs_freesp(xzp, 0, 0, xattr_mode, TRUE); 512eda14cbcSMatt Macy if (error) 513eda14cbcSMatt Macy goto out; 514eda14cbcSMatt Macy 5157877fdebSMatt Macy error = -zfs_write_simple(xzp, value, size, pos, NULL); 516eda14cbcSMatt Macy out: 517eda14cbcSMatt Macy if (error == 0) { 518abcdc1b9SMartin Matuska zpl_inode_set_ctime_to_ts(ip, current_time(ip)); 519eda14cbcSMatt Macy zfs_mark_inode_dirty(ip); 520eda14cbcSMatt Macy } 521eda14cbcSMatt Macy 522eda14cbcSMatt Macy if (vap) 523eda14cbcSMatt Macy kmem_free(vap, sizeof (vattr_t)); 524eda14cbcSMatt Macy 525eda14cbcSMatt Macy if (xzp) 526eda14cbcSMatt Macy zrele(xzp); 527eda14cbcSMatt Macy 528eda14cbcSMatt Macy if (dxzp) 529eda14cbcSMatt Macy zrele(dxzp); 530eda14cbcSMatt Macy 531eda14cbcSMatt Macy if (error == -ENOENT) 532eda14cbcSMatt Macy error = -ENODATA; 533eda14cbcSMatt Macy 534eda14cbcSMatt Macy ASSERT3S(error, <=, 0); 535eda14cbcSMatt Macy 536eda14cbcSMatt Macy return (error); 537eda14cbcSMatt Macy } 538eda14cbcSMatt Macy 539eda14cbcSMatt Macy static int 540eda14cbcSMatt Macy zpl_xattr_set_sa(struct inode *ip, const char *name, const void *value, 541eda14cbcSMatt Macy size_t size, int flags, cred_t *cr) 542eda14cbcSMatt Macy { 543eda14cbcSMatt Macy znode_t *zp = ITOZ(ip); 544eda14cbcSMatt Macy nvlist_t *nvl; 545eda14cbcSMatt Macy size_t sa_size; 546eda14cbcSMatt Macy int error = 0; 547eda14cbcSMatt Macy 548eda14cbcSMatt Macy mutex_enter(&zp->z_lock); 549eda14cbcSMatt Macy if (zp->z_xattr_cached == NULL) 550eda14cbcSMatt Macy error = -zfs_sa_get_xattr(zp); 551eda14cbcSMatt Macy mutex_exit(&zp->z_lock); 552eda14cbcSMatt Macy 553eda14cbcSMatt Macy if (error) 554eda14cbcSMatt Macy return (error); 555eda14cbcSMatt Macy 556eda14cbcSMatt Macy ASSERT(zp->z_xattr_cached); 557eda14cbcSMatt Macy nvl = zp->z_xattr_cached; 558eda14cbcSMatt Macy 559eda14cbcSMatt Macy if (value == NULL) { 560eda14cbcSMatt Macy error = -nvlist_remove(nvl, name, DATA_TYPE_BYTE_ARRAY); 561eda14cbcSMatt Macy if (error == -ENOENT) 562eda14cbcSMatt Macy error = zpl_xattr_set_dir(ip, name, NULL, 0, flags, cr); 563eda14cbcSMatt Macy } else { 564eda14cbcSMatt Macy /* Limited to 32k to keep nvpair memory allocations small */ 565eda14cbcSMatt Macy if (size > DXATTR_MAX_ENTRY_SIZE) 566eda14cbcSMatt Macy return (-EFBIG); 567eda14cbcSMatt Macy 568eda14cbcSMatt Macy /* Prevent the DXATTR SA from consuming the entire SA region */ 569eda14cbcSMatt Macy error = -nvlist_size(nvl, &sa_size, NV_ENCODE_XDR); 570eda14cbcSMatt Macy if (error) 571eda14cbcSMatt Macy return (error); 572eda14cbcSMatt Macy 573eda14cbcSMatt Macy if (sa_size > DXATTR_MAX_SA_SIZE) 574eda14cbcSMatt Macy return (-EFBIG); 575eda14cbcSMatt Macy 576eda14cbcSMatt Macy error = -nvlist_add_byte_array(nvl, name, 577eda14cbcSMatt Macy (uchar_t *)value, size); 578eda14cbcSMatt Macy } 579eda14cbcSMatt Macy 580eda14cbcSMatt Macy /* 581eda14cbcSMatt Macy * Update the SA for additions, modifications, and removals. On 582eda14cbcSMatt Macy * error drop the inconsistent cached version of the nvlist, it 583eda14cbcSMatt Macy * will be reconstructed from the ARC when next accessed. 584eda14cbcSMatt Macy */ 585eda14cbcSMatt Macy if (error == 0) 586c03c5b1cSMartin Matuska error = -zfs_sa_set_xattr(zp, name, value, size); 587eda14cbcSMatt Macy 588eda14cbcSMatt Macy if (error) { 589eda14cbcSMatt Macy nvlist_free(nvl); 590eda14cbcSMatt Macy zp->z_xattr_cached = NULL; 591eda14cbcSMatt Macy } 592eda14cbcSMatt Macy 593eda14cbcSMatt Macy ASSERT3S(error, <=, 0); 594eda14cbcSMatt Macy 595eda14cbcSMatt Macy return (error); 596eda14cbcSMatt Macy } 597eda14cbcSMatt Macy 598eda14cbcSMatt Macy static int 599eda14cbcSMatt Macy zpl_xattr_set(struct inode *ip, const char *name, const void *value, 600eda14cbcSMatt Macy size_t size, int flags) 601eda14cbcSMatt Macy { 602eda14cbcSMatt Macy znode_t *zp = ITOZ(ip); 603eda14cbcSMatt Macy zfsvfs_t *zfsvfs = ZTOZSB(zp); 604eda14cbcSMatt Macy cred_t *cr = CRED(); 605eda14cbcSMatt Macy fstrans_cookie_t cookie; 606eda14cbcSMatt Macy int where; 607eda14cbcSMatt Macy int error; 608eda14cbcSMatt Macy 609eda14cbcSMatt Macy crhold(cr); 610eda14cbcSMatt Macy cookie = spl_fstrans_mark(); 611c7046f76SMartin Matuska if ((error = zpl_enter_verify_zp(zfsvfs, zp, FTAG)) != 0) 612c7046f76SMartin Matuska goto out1; 61316038816SMartin Matuska rw_enter(&zp->z_xattr_lock, RW_WRITER); 614eda14cbcSMatt Macy 615eda14cbcSMatt Macy /* 616eda14cbcSMatt Macy * Before setting the xattr check to see if it already exists. 617eda14cbcSMatt Macy * This is done to ensure the following optional flags are honored. 618eda14cbcSMatt Macy * 619eda14cbcSMatt Macy * XATTR_CREATE: fail if xattr already exists 620eda14cbcSMatt Macy * XATTR_REPLACE: fail if xattr does not exist 621eda14cbcSMatt Macy * 622eda14cbcSMatt Macy * We also want to know if it resides in sa or dir, so we can make 623eda14cbcSMatt Macy * sure we don't end up with duplicate in both places. 624eda14cbcSMatt Macy */ 625eda14cbcSMatt Macy error = __zpl_xattr_where(ip, name, &where, cr); 626eda14cbcSMatt Macy if (error < 0) { 627eda14cbcSMatt Macy if (error != -ENODATA) 628eda14cbcSMatt Macy goto out; 629eda14cbcSMatt Macy if (flags & XATTR_REPLACE) 630eda14cbcSMatt Macy goto out; 631eda14cbcSMatt Macy 632eda14cbcSMatt Macy /* The xattr to be removed already doesn't exist */ 633eda14cbcSMatt Macy error = 0; 634eda14cbcSMatt Macy if (value == NULL) 635eda14cbcSMatt Macy goto out; 636eda14cbcSMatt Macy } else { 637eda14cbcSMatt Macy error = -EEXIST; 638eda14cbcSMatt Macy if (flags & XATTR_CREATE) 639eda14cbcSMatt Macy goto out; 640eda14cbcSMatt Macy } 641eda14cbcSMatt Macy 642eda14cbcSMatt Macy /* Preferentially store the xattr as a SA for better performance */ 643eda14cbcSMatt Macy if (zfsvfs->z_use_sa && zp->z_is_sa && 644eda14cbcSMatt Macy (zfsvfs->z_xattr_sa || (value == NULL && where & XATTR_IN_SA))) { 645eda14cbcSMatt Macy error = zpl_xattr_set_sa(ip, name, value, size, flags, cr); 646eda14cbcSMatt Macy if (error == 0) { 647eda14cbcSMatt Macy /* 648eda14cbcSMatt Macy * Successfully put into SA, we need to clear the one 649eda14cbcSMatt Macy * in dir. 650eda14cbcSMatt Macy */ 651eda14cbcSMatt Macy if (where & XATTR_IN_DIR) 652eda14cbcSMatt Macy zpl_xattr_set_dir(ip, name, NULL, 0, 0, cr); 653eda14cbcSMatt Macy goto out; 654eda14cbcSMatt Macy } 655eda14cbcSMatt Macy } 656eda14cbcSMatt Macy 657eda14cbcSMatt Macy error = zpl_xattr_set_dir(ip, name, value, size, flags, cr); 658eda14cbcSMatt Macy /* 659eda14cbcSMatt Macy * Successfully put into dir, we need to clear the one in SA. 660eda14cbcSMatt Macy */ 661eda14cbcSMatt Macy if (error == 0 && (where & XATTR_IN_SA)) 662eda14cbcSMatt Macy zpl_xattr_set_sa(ip, name, NULL, 0, 0, cr); 663eda14cbcSMatt Macy out: 66416038816SMartin Matuska rw_exit(&zp->z_xattr_lock); 665c7046f76SMartin Matuska zpl_exit(zfsvfs, FTAG); 666c7046f76SMartin Matuska out1: 667eda14cbcSMatt Macy spl_fstrans_unmark(cookie); 668eda14cbcSMatt Macy crfree(cr); 669eda14cbcSMatt Macy ASSERT3S(error, <=, 0); 670eda14cbcSMatt Macy 671eda14cbcSMatt Macy return (error); 672eda14cbcSMatt Macy } 673eda14cbcSMatt Macy 674eda14cbcSMatt Macy /* 675eda14cbcSMatt Macy * Extended user attributes 676eda14cbcSMatt Macy * 677eda14cbcSMatt Macy * "Extended user attributes may be assigned to files and directories for 678eda14cbcSMatt Macy * storing arbitrary additional information such as the mime type, 679eda14cbcSMatt Macy * character set or encoding of a file. The access permissions for user 680eda14cbcSMatt Macy * attributes are defined by the file permission bits: read permission 681eda14cbcSMatt Macy * is required to retrieve the attribute value, and writer permission is 682eda14cbcSMatt Macy * required to change it. 683eda14cbcSMatt Macy * 684eda14cbcSMatt Macy * The file permission bits of regular files and directories are 685eda14cbcSMatt Macy * interpreted differently from the file permission bits of special 686eda14cbcSMatt Macy * files and symbolic links. For regular files and directories the file 687eda14cbcSMatt Macy * permission bits define access to the file's contents, while for 688eda14cbcSMatt Macy * device special files they define access to the device described by 689eda14cbcSMatt Macy * the special file. The file permissions of symbolic links are not 690eda14cbcSMatt Macy * used in access checks. These differences would allow users to 691eda14cbcSMatt Macy * consume filesystem resources in a way not controllable by disk quotas 692eda14cbcSMatt Macy * for group or world writable special files and directories. 693eda14cbcSMatt Macy * 694eda14cbcSMatt Macy * For this reason, extended user attributes are allowed only for 695eda14cbcSMatt Macy * regular files and directories, and access to extended user attributes 696eda14cbcSMatt Macy * is restricted to the owner and to users with appropriate capabilities 697eda14cbcSMatt Macy * for directories with the sticky bit set (see the chmod(1) manual page 698eda14cbcSMatt Macy * for an explanation of the sticky bit)." - xattr(7) 699eda14cbcSMatt Macy * 700eda14cbcSMatt Macy * ZFS allows extended user attributes to be disabled administratively 701eda14cbcSMatt Macy * by setting the 'xattr=off' property on the dataset. 702eda14cbcSMatt Macy */ 703eda14cbcSMatt Macy static int 704eda14cbcSMatt Macy __zpl_xattr_user_list(struct inode *ip, char *list, size_t list_size, 705eda14cbcSMatt Macy const char *name, size_t name_len) 706eda14cbcSMatt Macy { 707eda14cbcSMatt Macy return (ITOZSB(ip)->z_flags & ZSB_XATTR); 708eda14cbcSMatt Macy } 709eda14cbcSMatt Macy ZPL_XATTR_LIST_WRAPPER(zpl_xattr_user_list); 710eda14cbcSMatt Macy 711eda14cbcSMatt Macy static int 712eda14cbcSMatt Macy __zpl_xattr_user_get(struct inode *ip, const char *name, 713eda14cbcSMatt Macy void *value, size_t size) 714eda14cbcSMatt Macy { 715eda14cbcSMatt Macy int error; 716eda14cbcSMatt Macy /* xattr_resolve_name will do this for us if this is defined */ 717c03c5b1cSMartin Matuska if (ZFS_XA_NS_PREFIX_FORBIDDEN(name)) 718c03c5b1cSMartin Matuska return (-EINVAL); 719eda14cbcSMatt Macy if (!(ITOZSB(ip)->z_flags & ZSB_XATTR)) 720eda14cbcSMatt Macy return (-EOPNOTSUPP); 721eda14cbcSMatt Macy 722c03c5b1cSMartin Matuska /* 723c03c5b1cSMartin Matuska * Try to look up the name with the namespace prefix first for 724c03c5b1cSMartin Matuska * compatibility with xattrs from this platform. If that fails, 725c03c5b1cSMartin Matuska * try again without the namespace prefix for compatibility with 726c03c5b1cSMartin Matuska * other platforms. 727c03c5b1cSMartin Matuska */ 728c03c5b1cSMartin Matuska char *xattr_name = kmem_asprintf("%s%s", XATTR_USER_PREFIX, name); 729eda14cbcSMatt Macy error = zpl_xattr_get(ip, xattr_name, value, size); 730eda14cbcSMatt Macy kmem_strfree(xattr_name); 731c03c5b1cSMartin Matuska if (error == -ENODATA) 732c03c5b1cSMartin Matuska error = zpl_xattr_get(ip, name, value, size); 733eda14cbcSMatt Macy 734eda14cbcSMatt Macy return (error); 735eda14cbcSMatt Macy } 736eda14cbcSMatt Macy ZPL_XATTR_GET_WRAPPER(zpl_xattr_user_get); 737eda14cbcSMatt Macy 738eda14cbcSMatt Macy static int 739d411c1d6SMartin Matuska __zpl_xattr_user_set(zidmap_t *user_ns, 740dbd5678dSMartin Matuska struct inode *ip, const char *name, 741eda14cbcSMatt Macy const void *value, size_t size, int flags) 742eda14cbcSMatt Macy { 743dbd5678dSMartin Matuska (void) user_ns; 744c03c5b1cSMartin Matuska int error = 0; 745eda14cbcSMatt Macy /* xattr_resolve_name will do this for us if this is defined */ 746c03c5b1cSMartin Matuska if (ZFS_XA_NS_PREFIX_FORBIDDEN(name)) 747c03c5b1cSMartin Matuska return (-EINVAL); 748eda14cbcSMatt Macy if (!(ITOZSB(ip)->z_flags & ZSB_XATTR)) 749eda14cbcSMatt Macy return (-EOPNOTSUPP); 750eda14cbcSMatt Macy 751c03c5b1cSMartin Matuska /* 752c03c5b1cSMartin Matuska * Remove alternate compat version of the xattr so we only set the 753c03c5b1cSMartin Matuska * version specified by the zfs_xattr_compat tunable. 754c03c5b1cSMartin Matuska * 755c03c5b1cSMartin Matuska * The following flags must be handled correctly: 756c03c5b1cSMartin Matuska * 757c03c5b1cSMartin Matuska * XATTR_CREATE: fail if xattr already exists 758c03c5b1cSMartin Matuska * XATTR_REPLACE: fail if xattr does not exist 759c03c5b1cSMartin Matuska */ 760c03c5b1cSMartin Matuska char *prefixed_name = kmem_asprintf("%s%s", XATTR_USER_PREFIX, name); 761c03c5b1cSMartin Matuska const char *clear_name, *set_name; 762c03c5b1cSMartin Matuska if (zfs_xattr_compat) { 763c03c5b1cSMartin Matuska clear_name = prefixed_name; 764c03c5b1cSMartin Matuska set_name = name; 765c03c5b1cSMartin Matuska } else { 766c03c5b1cSMartin Matuska clear_name = name; 767c03c5b1cSMartin Matuska set_name = prefixed_name; 768c03c5b1cSMartin Matuska } 769c03c5b1cSMartin Matuska /* 770c03c5b1cSMartin Matuska * Clear the old value with the alternative name format, if it exists. 771c03c5b1cSMartin Matuska */ 772c03c5b1cSMartin Matuska error = zpl_xattr_set(ip, clear_name, NULL, 0, flags); 773c03c5b1cSMartin Matuska /* 774c03c5b1cSMartin Matuska * XATTR_CREATE was specified and we failed to clear the xattr 775c03c5b1cSMartin Matuska * because it already exists. Stop here. 776c03c5b1cSMartin Matuska */ 777c03c5b1cSMartin Matuska if (error == -EEXIST) 778c03c5b1cSMartin Matuska goto out; 779c03c5b1cSMartin Matuska /* 780c03c5b1cSMartin Matuska * If XATTR_REPLACE was specified and we succeeded to clear 781c03c5b1cSMartin Matuska * an xattr, we don't need to replace anything when setting 782c03c5b1cSMartin Matuska * the new value. If we failed with -ENODATA that's fine, 783c03c5b1cSMartin Matuska * there was nothing to be cleared and we can ignore the error. 784c03c5b1cSMartin Matuska */ 785c03c5b1cSMartin Matuska if (error == 0) 786c03c5b1cSMartin Matuska flags &= ~XATTR_REPLACE; 787c03c5b1cSMartin Matuska /* 788c03c5b1cSMartin Matuska * Set the new value with the configured name format. 789c03c5b1cSMartin Matuska */ 790c03c5b1cSMartin Matuska error = zpl_xattr_set(ip, set_name, value, size, flags); 791c03c5b1cSMartin Matuska out: 792c03c5b1cSMartin Matuska kmem_strfree(prefixed_name); 793eda14cbcSMatt Macy return (error); 794eda14cbcSMatt Macy } 795eda14cbcSMatt Macy ZPL_XATTR_SET_WRAPPER(zpl_xattr_user_set); 796eda14cbcSMatt Macy 797e92ffd9bSMartin Matuska static xattr_handler_t zpl_xattr_user_handler = 798eda14cbcSMatt Macy { 799eda14cbcSMatt Macy .prefix = XATTR_USER_PREFIX, 800eda14cbcSMatt Macy .list = zpl_xattr_user_list, 801eda14cbcSMatt Macy .get = zpl_xattr_user_get, 802eda14cbcSMatt Macy .set = zpl_xattr_user_set, 803eda14cbcSMatt Macy }; 804eda14cbcSMatt Macy 805eda14cbcSMatt Macy /* 806eda14cbcSMatt Macy * Trusted extended attributes 807eda14cbcSMatt Macy * 808eda14cbcSMatt Macy * "Trusted extended attributes are visible and accessible only to 809eda14cbcSMatt Macy * processes that have the CAP_SYS_ADMIN capability. Attributes in this 810eda14cbcSMatt Macy * class are used to implement mechanisms in user space (i.e., outside 811eda14cbcSMatt Macy * the kernel) which keep information in extended attributes to which 812eda14cbcSMatt Macy * ordinary processes should not have access." - xattr(7) 813eda14cbcSMatt Macy */ 814eda14cbcSMatt Macy static int 815eda14cbcSMatt Macy __zpl_xattr_trusted_list(struct inode *ip, char *list, size_t list_size, 816eda14cbcSMatt Macy const char *name, size_t name_len) 817eda14cbcSMatt Macy { 818eda14cbcSMatt Macy return (capable(CAP_SYS_ADMIN)); 819eda14cbcSMatt Macy } 820eda14cbcSMatt Macy ZPL_XATTR_LIST_WRAPPER(zpl_xattr_trusted_list); 821eda14cbcSMatt Macy 822eda14cbcSMatt Macy static int 823eda14cbcSMatt Macy __zpl_xattr_trusted_get(struct inode *ip, const char *name, 824eda14cbcSMatt Macy void *value, size_t size) 825eda14cbcSMatt Macy { 826eda14cbcSMatt Macy char *xattr_name; 827eda14cbcSMatt Macy int error; 828eda14cbcSMatt Macy 829eda14cbcSMatt Macy if (!capable(CAP_SYS_ADMIN)) 830eda14cbcSMatt Macy return (-EACCES); 831eda14cbcSMatt Macy /* xattr_resolve_name will do this for us if this is defined */ 832eda14cbcSMatt Macy xattr_name = kmem_asprintf("%s%s", XATTR_TRUSTED_PREFIX, name); 833eda14cbcSMatt Macy error = zpl_xattr_get(ip, xattr_name, value, size); 834eda14cbcSMatt Macy kmem_strfree(xattr_name); 835eda14cbcSMatt Macy 836eda14cbcSMatt Macy return (error); 837eda14cbcSMatt Macy } 838eda14cbcSMatt Macy ZPL_XATTR_GET_WRAPPER(zpl_xattr_trusted_get); 839eda14cbcSMatt Macy 840eda14cbcSMatt Macy static int 841d411c1d6SMartin Matuska __zpl_xattr_trusted_set(zidmap_t *user_ns, 842dbd5678dSMartin Matuska struct inode *ip, const char *name, 843eda14cbcSMatt Macy const void *value, size_t size, int flags) 844eda14cbcSMatt Macy { 845dbd5678dSMartin Matuska (void) user_ns; 846eda14cbcSMatt Macy char *xattr_name; 847eda14cbcSMatt Macy int error; 848eda14cbcSMatt Macy 849eda14cbcSMatt Macy if (!capable(CAP_SYS_ADMIN)) 850eda14cbcSMatt Macy return (-EACCES); 851eda14cbcSMatt Macy /* xattr_resolve_name will do this for us if this is defined */ 852eda14cbcSMatt Macy xattr_name = kmem_asprintf("%s%s", XATTR_TRUSTED_PREFIX, name); 853eda14cbcSMatt Macy error = zpl_xattr_set(ip, xattr_name, value, size, flags); 854eda14cbcSMatt Macy kmem_strfree(xattr_name); 855eda14cbcSMatt Macy 856eda14cbcSMatt Macy return (error); 857eda14cbcSMatt Macy } 858eda14cbcSMatt Macy ZPL_XATTR_SET_WRAPPER(zpl_xattr_trusted_set); 859eda14cbcSMatt Macy 860e92ffd9bSMartin Matuska static xattr_handler_t zpl_xattr_trusted_handler = { 861eda14cbcSMatt Macy .prefix = XATTR_TRUSTED_PREFIX, 862eda14cbcSMatt Macy .list = zpl_xattr_trusted_list, 863eda14cbcSMatt Macy .get = zpl_xattr_trusted_get, 864eda14cbcSMatt Macy .set = zpl_xattr_trusted_set, 865eda14cbcSMatt Macy }; 866eda14cbcSMatt Macy 867eda14cbcSMatt Macy /* 868eda14cbcSMatt Macy * Extended security attributes 869eda14cbcSMatt Macy * 870eda14cbcSMatt Macy * "The security attribute namespace is used by kernel security modules, 871eda14cbcSMatt Macy * such as Security Enhanced Linux, and also to implement file 872eda14cbcSMatt Macy * capabilities (see capabilities(7)). Read and write access 873eda14cbcSMatt Macy * permissions to security attributes depend on the policy implemented 874eda14cbcSMatt Macy * for each security attribute by the security module. When no security 875eda14cbcSMatt Macy * module is loaded, all processes have read access to extended security 876eda14cbcSMatt Macy * attributes, and write access is limited to processes that have the 877eda14cbcSMatt Macy * CAP_SYS_ADMIN capability." - xattr(7) 878eda14cbcSMatt Macy */ 879eda14cbcSMatt Macy static int 880eda14cbcSMatt Macy __zpl_xattr_security_list(struct inode *ip, char *list, size_t list_size, 881eda14cbcSMatt Macy const char *name, size_t name_len) 882eda14cbcSMatt Macy { 883eda14cbcSMatt Macy return (1); 884eda14cbcSMatt Macy } 885eda14cbcSMatt Macy ZPL_XATTR_LIST_WRAPPER(zpl_xattr_security_list); 886eda14cbcSMatt Macy 887eda14cbcSMatt Macy static int 888eda14cbcSMatt Macy __zpl_xattr_security_get(struct inode *ip, const char *name, 889eda14cbcSMatt Macy void *value, size_t size) 890eda14cbcSMatt Macy { 891eda14cbcSMatt Macy char *xattr_name; 892eda14cbcSMatt Macy int error; 893eda14cbcSMatt Macy /* xattr_resolve_name will do this for us if this is defined */ 894eda14cbcSMatt Macy xattr_name = kmem_asprintf("%s%s", XATTR_SECURITY_PREFIX, name); 895eda14cbcSMatt Macy error = zpl_xattr_get(ip, xattr_name, value, size); 896eda14cbcSMatt Macy kmem_strfree(xattr_name); 897eda14cbcSMatt Macy 898eda14cbcSMatt Macy return (error); 899eda14cbcSMatt Macy } 900eda14cbcSMatt Macy ZPL_XATTR_GET_WRAPPER(zpl_xattr_security_get); 901eda14cbcSMatt Macy 902eda14cbcSMatt Macy static int 903d411c1d6SMartin Matuska __zpl_xattr_security_set(zidmap_t *user_ns, 904dbd5678dSMartin Matuska struct inode *ip, const char *name, 905eda14cbcSMatt Macy const void *value, size_t size, int flags) 906eda14cbcSMatt Macy { 907dbd5678dSMartin Matuska (void) user_ns; 908eda14cbcSMatt Macy char *xattr_name; 909eda14cbcSMatt Macy int error; 910eda14cbcSMatt Macy /* xattr_resolve_name will do this for us if this is defined */ 911eda14cbcSMatt Macy xattr_name = kmem_asprintf("%s%s", XATTR_SECURITY_PREFIX, name); 912eda14cbcSMatt Macy error = zpl_xattr_set(ip, xattr_name, value, size, flags); 913eda14cbcSMatt Macy kmem_strfree(xattr_name); 914eda14cbcSMatt Macy 915eda14cbcSMatt Macy return (error); 916eda14cbcSMatt Macy } 917eda14cbcSMatt Macy ZPL_XATTR_SET_WRAPPER(zpl_xattr_security_set); 918eda14cbcSMatt Macy 919eda14cbcSMatt Macy static int 920eda14cbcSMatt Macy zpl_xattr_security_init_impl(struct inode *ip, const struct xattr *xattrs, 921eda14cbcSMatt Macy void *fs_info) 922eda14cbcSMatt Macy { 923eda14cbcSMatt Macy const struct xattr *xattr; 924eda14cbcSMatt Macy int error = 0; 925eda14cbcSMatt Macy 926eda14cbcSMatt Macy for (xattr = xattrs; xattr->name != NULL; xattr++) { 927dbd5678dSMartin Matuska error = __zpl_xattr_security_set(NULL, ip, 928eda14cbcSMatt Macy xattr->name, xattr->value, xattr->value_len, 0); 929eda14cbcSMatt Macy 930eda14cbcSMatt Macy if (error < 0) 931eda14cbcSMatt Macy break; 932eda14cbcSMatt Macy } 933eda14cbcSMatt Macy 934eda14cbcSMatt Macy return (error); 935eda14cbcSMatt Macy } 936eda14cbcSMatt Macy 937eda14cbcSMatt Macy int 938eda14cbcSMatt Macy zpl_xattr_security_init(struct inode *ip, struct inode *dip, 939eda14cbcSMatt Macy const struct qstr *qstr) 940eda14cbcSMatt Macy { 941eda14cbcSMatt Macy return security_inode_init_security(ip, dip, qstr, 942eda14cbcSMatt Macy &zpl_xattr_security_init_impl, NULL); 943eda14cbcSMatt Macy } 944eda14cbcSMatt Macy 945eda14cbcSMatt Macy /* 946eda14cbcSMatt Macy * Security xattr namespace handlers. 947eda14cbcSMatt Macy */ 948e92ffd9bSMartin Matuska static xattr_handler_t zpl_xattr_security_handler = { 949eda14cbcSMatt Macy .prefix = XATTR_SECURITY_PREFIX, 950eda14cbcSMatt Macy .list = zpl_xattr_security_list, 951eda14cbcSMatt Macy .get = zpl_xattr_security_get, 952eda14cbcSMatt Macy .set = zpl_xattr_security_set, 953eda14cbcSMatt Macy }; 954eda14cbcSMatt Macy 955eda14cbcSMatt Macy /* 956eda14cbcSMatt Macy * Extended system attributes 957eda14cbcSMatt Macy * 958eda14cbcSMatt Macy * "Extended system attributes are used by the kernel to store system 959eda14cbcSMatt Macy * objects such as Access Control Lists. Read and write access permissions 960eda14cbcSMatt Macy * to system attributes depend on the policy implemented for each system 961eda14cbcSMatt Macy * attribute implemented by filesystems in the kernel." - xattr(7) 962eda14cbcSMatt Macy */ 963eda14cbcSMatt Macy #ifdef CONFIG_FS_POSIX_ACL 96416038816SMartin Matuska static int 96516038816SMartin Matuska zpl_set_acl_impl(struct inode *ip, struct posix_acl *acl, int type) 966eda14cbcSMatt Macy { 967eda14cbcSMatt Macy char *name, *value = NULL; 968eda14cbcSMatt Macy int error = 0; 969eda14cbcSMatt Macy size_t size = 0; 970eda14cbcSMatt Macy 971eda14cbcSMatt Macy if (S_ISLNK(ip->i_mode)) 972eda14cbcSMatt Macy return (-EOPNOTSUPP); 973eda14cbcSMatt Macy 974eda14cbcSMatt Macy switch (type) { 975eda14cbcSMatt Macy case ACL_TYPE_ACCESS: 976eda14cbcSMatt Macy name = XATTR_NAME_POSIX_ACL_ACCESS; 977eda14cbcSMatt Macy if (acl) { 978eda14cbcSMatt Macy umode_t mode = ip->i_mode; 979eda14cbcSMatt Macy error = posix_acl_equiv_mode(acl, &mode); 980eda14cbcSMatt Macy if (error < 0) { 981eda14cbcSMatt Macy return (error); 982eda14cbcSMatt Macy } else { 983eda14cbcSMatt Macy /* 984eda14cbcSMatt Macy * The mode bits will have been set by 985eda14cbcSMatt Macy * ->zfs_setattr()->zfs_acl_chmod_setattr() 986eda14cbcSMatt Macy * using the ZFS ACL conversion. If they 987eda14cbcSMatt Macy * differ from the Posix ACL conversion dirty 988eda14cbcSMatt Macy * the inode to write the Posix mode bits. 989eda14cbcSMatt Macy */ 990eda14cbcSMatt Macy if (ip->i_mode != mode) { 991a0b956f5SMartin Matuska ip->i_mode = ITOZ(ip)->z_mode = mode; 992abcdc1b9SMartin Matuska zpl_inode_set_ctime_to_ts(ip, 993abcdc1b9SMartin Matuska current_time(ip)); 994eda14cbcSMatt Macy zfs_mark_inode_dirty(ip); 995eda14cbcSMatt Macy } 996eda14cbcSMatt Macy 997eda14cbcSMatt Macy if (error == 0) 998eda14cbcSMatt Macy acl = NULL; 999eda14cbcSMatt Macy } 1000eda14cbcSMatt Macy } 1001eda14cbcSMatt Macy break; 1002eda14cbcSMatt Macy 1003eda14cbcSMatt Macy case ACL_TYPE_DEFAULT: 1004eda14cbcSMatt Macy name = XATTR_NAME_POSIX_ACL_DEFAULT; 1005eda14cbcSMatt Macy if (!S_ISDIR(ip->i_mode)) 1006eda14cbcSMatt Macy return (acl ? -EACCES : 0); 1007eda14cbcSMatt Macy break; 1008eda14cbcSMatt Macy 1009eda14cbcSMatt Macy default: 1010eda14cbcSMatt Macy return (-EINVAL); 1011eda14cbcSMatt Macy } 1012eda14cbcSMatt Macy 1013eda14cbcSMatt Macy if (acl) { 1014eda14cbcSMatt Macy size = posix_acl_xattr_size(acl->a_count); 1015eda14cbcSMatt Macy value = kmem_alloc(size, KM_SLEEP); 1016eda14cbcSMatt Macy 1017eda14cbcSMatt Macy error = zpl_acl_to_xattr(acl, value, size); 1018eda14cbcSMatt Macy if (error < 0) { 1019eda14cbcSMatt Macy kmem_free(value, size); 1020eda14cbcSMatt Macy return (error); 1021eda14cbcSMatt Macy } 1022eda14cbcSMatt Macy } 1023eda14cbcSMatt Macy 1024eda14cbcSMatt Macy error = zpl_xattr_set(ip, name, value, size, 0); 1025eda14cbcSMatt Macy if (value) 1026eda14cbcSMatt Macy kmem_free(value, size); 1027eda14cbcSMatt Macy 1028eda14cbcSMatt Macy if (!error) { 1029eda14cbcSMatt Macy if (acl) 1030*7a7741afSMartin Matuska set_cached_acl(ip, type, acl); 1031eda14cbcSMatt Macy else 1032*7a7741afSMartin Matuska forget_cached_acl(ip, type); 1033eda14cbcSMatt Macy } 1034eda14cbcSMatt Macy 1035eda14cbcSMatt Macy return (error); 1036eda14cbcSMatt Macy } 1037eda14cbcSMatt Macy 103816038816SMartin Matuska int 103916038816SMartin Matuska #ifdef HAVE_SET_ACL_USERNS 104016038816SMartin Matuska zpl_set_acl(struct user_namespace *userns, struct inode *ip, 104116038816SMartin Matuska struct posix_acl *acl, int type) 1042d411c1d6SMartin Matuska #elif defined(HAVE_SET_ACL_IDMAP_DENTRY) 1043d411c1d6SMartin Matuska zpl_set_acl(struct mnt_idmap *userns, struct dentry *dentry, 1044d411c1d6SMartin Matuska struct posix_acl *acl, int type) 104515f0b8c3SMartin Matuska #elif defined(HAVE_SET_ACL_USERNS_DENTRY_ARG2) 104615f0b8c3SMartin Matuska zpl_set_acl(struct user_namespace *userns, struct dentry *dentry, 104715f0b8c3SMartin Matuska struct posix_acl *acl, int type) 104816038816SMartin Matuska #else 104916038816SMartin Matuska zpl_set_acl(struct inode *ip, struct posix_acl *acl, int type) 105016038816SMartin Matuska #endif /* HAVE_SET_ACL_USERNS */ 105116038816SMartin Matuska { 105215f0b8c3SMartin Matuska #ifdef HAVE_SET_ACL_USERNS_DENTRY_ARG2 105315f0b8c3SMartin Matuska return (zpl_set_acl_impl(d_inode(dentry), acl, type)); 1054d411c1d6SMartin Matuska #elif defined(HAVE_SET_ACL_IDMAP_DENTRY) 1055d411c1d6SMartin Matuska return (zpl_set_acl_impl(d_inode(dentry), acl, type)); 105615f0b8c3SMartin Matuska #else 105716038816SMartin Matuska return (zpl_set_acl_impl(ip, acl, type)); 105815f0b8c3SMartin Matuska #endif /* HAVE_SET_ACL_USERNS_DENTRY_ARG2 */ 105916038816SMartin Matuska } 106016038816SMartin Matuska 106153b70c86SMartin Matuska static struct posix_acl * 106253b70c86SMartin Matuska zpl_get_acl_impl(struct inode *ip, int type) 1063eda14cbcSMatt Macy { 1064eda14cbcSMatt Macy struct posix_acl *acl; 1065eda14cbcSMatt Macy void *value = NULL; 1066eda14cbcSMatt Macy char *name; 1067eda14cbcSMatt Macy 1068eda14cbcSMatt Macy switch (type) { 1069eda14cbcSMatt Macy case ACL_TYPE_ACCESS: 1070eda14cbcSMatt Macy name = XATTR_NAME_POSIX_ACL_ACCESS; 1071eda14cbcSMatt Macy break; 1072eda14cbcSMatt Macy case ACL_TYPE_DEFAULT: 1073eda14cbcSMatt Macy name = XATTR_NAME_POSIX_ACL_DEFAULT; 1074eda14cbcSMatt Macy break; 1075eda14cbcSMatt Macy default: 1076eda14cbcSMatt Macy return (ERR_PTR(-EINVAL)); 1077eda14cbcSMatt Macy } 1078eda14cbcSMatt Macy 107953b70c86SMartin Matuska int size = zpl_xattr_get(ip, name, NULL, 0); 1080eda14cbcSMatt Macy if (size > 0) { 1081eda14cbcSMatt Macy value = kmem_alloc(size, KM_SLEEP); 1082eda14cbcSMatt Macy size = zpl_xattr_get(ip, name, value, size); 1083eda14cbcSMatt Macy } 1084eda14cbcSMatt Macy 1085eda14cbcSMatt Macy if (size > 0) { 1086eda14cbcSMatt Macy acl = zpl_acl_from_xattr(value, size); 1087eda14cbcSMatt Macy } else if (size == -ENODATA || size == -ENOSYS) { 1088eda14cbcSMatt Macy acl = NULL; 1089eda14cbcSMatt Macy } else { 1090eda14cbcSMatt Macy acl = ERR_PTR(-EIO); 1091eda14cbcSMatt Macy } 1092eda14cbcSMatt Macy 1093eda14cbcSMatt Macy if (size > 0) 1094eda14cbcSMatt Macy kmem_free(value, size); 1095eda14cbcSMatt Macy 1096eda14cbcSMatt Macy return (acl); 1097eda14cbcSMatt Macy } 1098eda14cbcSMatt Macy 109915f0b8c3SMartin Matuska #if defined(HAVE_GET_ACL_RCU) || defined(HAVE_GET_INODE_ACL) 110053b70c86SMartin Matuska struct posix_acl * 110153b70c86SMartin Matuska zpl_get_acl(struct inode *ip, int type, bool rcu) 110253b70c86SMartin Matuska { 110353b70c86SMartin Matuska if (rcu) 110453b70c86SMartin Matuska return (ERR_PTR(-ECHILD)); 110553b70c86SMartin Matuska 110653b70c86SMartin Matuska return (zpl_get_acl_impl(ip, type)); 110753b70c86SMartin Matuska } 110853b70c86SMartin Matuska #elif defined(HAVE_GET_ACL) 110953b70c86SMartin Matuska struct posix_acl * 111053b70c86SMartin Matuska zpl_get_acl(struct inode *ip, int type) 111153b70c86SMartin Matuska { 111253b70c86SMartin Matuska return (zpl_get_acl_impl(ip, type)); 111353b70c86SMartin Matuska } 111453b70c86SMartin Matuska #else 111553b70c86SMartin Matuska #error "Unsupported iops->get_acl() implementation" 111653b70c86SMartin Matuska #endif /* HAVE_GET_ACL_RCU */ 111753b70c86SMartin Matuska 1118eda14cbcSMatt Macy int 1119eda14cbcSMatt Macy zpl_init_acl(struct inode *ip, struct inode *dir) 1120eda14cbcSMatt Macy { 1121eda14cbcSMatt Macy struct posix_acl *acl = NULL; 1122eda14cbcSMatt Macy int error = 0; 1123eda14cbcSMatt Macy 11242c48331dSMatt Macy if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIX) 1125eda14cbcSMatt Macy return (0); 1126eda14cbcSMatt Macy 1127eda14cbcSMatt Macy if (!S_ISLNK(ip->i_mode)) { 112853b70c86SMartin Matuska acl = zpl_get_acl_impl(dir, ACL_TYPE_DEFAULT); 1129eda14cbcSMatt Macy if (IS_ERR(acl)) 1130eda14cbcSMatt Macy return (PTR_ERR(acl)); 1131eda14cbcSMatt Macy if (!acl) { 1132a0b956f5SMartin Matuska ITOZ(ip)->z_mode = (ip->i_mode &= ~current_umask()); 1133abcdc1b9SMartin Matuska zpl_inode_set_ctime_to_ts(ip, current_time(ip)); 1134eda14cbcSMatt Macy zfs_mark_inode_dirty(ip); 1135eda14cbcSMatt Macy return (0); 1136eda14cbcSMatt Macy } 1137eda14cbcSMatt Macy } 1138eda14cbcSMatt Macy 1139eda14cbcSMatt Macy if (acl) { 1140eda14cbcSMatt Macy umode_t mode; 1141eda14cbcSMatt Macy 1142eda14cbcSMatt Macy if (S_ISDIR(ip->i_mode)) { 114316038816SMartin Matuska error = zpl_set_acl_impl(ip, acl, ACL_TYPE_DEFAULT); 1144eda14cbcSMatt Macy if (error) 1145eda14cbcSMatt Macy goto out; 1146eda14cbcSMatt Macy } 1147eda14cbcSMatt Macy 1148eda14cbcSMatt Macy mode = ip->i_mode; 1149eda14cbcSMatt Macy error = __posix_acl_create(&acl, GFP_KERNEL, &mode); 1150eda14cbcSMatt Macy if (error >= 0) { 1151a0b956f5SMartin Matuska ip->i_mode = ITOZ(ip)->z_mode = mode; 1152eda14cbcSMatt Macy zfs_mark_inode_dirty(ip); 115316038816SMartin Matuska if (error > 0) { 115416038816SMartin Matuska error = zpl_set_acl_impl(ip, acl, 115516038816SMartin Matuska ACL_TYPE_ACCESS); 115616038816SMartin Matuska } 1157eda14cbcSMatt Macy } 1158eda14cbcSMatt Macy } 1159eda14cbcSMatt Macy out: 1160eda14cbcSMatt Macy zpl_posix_acl_release(acl); 1161eda14cbcSMatt Macy 1162eda14cbcSMatt Macy return (error); 1163eda14cbcSMatt Macy } 1164eda14cbcSMatt Macy 1165eda14cbcSMatt Macy int 1166eda14cbcSMatt Macy zpl_chmod_acl(struct inode *ip) 1167eda14cbcSMatt Macy { 1168eda14cbcSMatt Macy struct posix_acl *acl; 1169eda14cbcSMatt Macy int error; 1170eda14cbcSMatt Macy 11712c48331dSMatt Macy if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIX) 1172eda14cbcSMatt Macy return (0); 1173eda14cbcSMatt Macy 1174eda14cbcSMatt Macy if (S_ISLNK(ip->i_mode)) 1175eda14cbcSMatt Macy return (-EOPNOTSUPP); 1176eda14cbcSMatt Macy 117753b70c86SMartin Matuska acl = zpl_get_acl_impl(ip, ACL_TYPE_ACCESS); 1178eda14cbcSMatt Macy if (IS_ERR(acl) || !acl) 1179eda14cbcSMatt Macy return (PTR_ERR(acl)); 1180eda14cbcSMatt Macy 1181eda14cbcSMatt Macy error = __posix_acl_chmod(&acl, GFP_KERNEL, ip->i_mode); 1182eda14cbcSMatt Macy if (!error) 118316038816SMartin Matuska error = zpl_set_acl_impl(ip, acl, ACL_TYPE_ACCESS); 1184eda14cbcSMatt Macy 1185eda14cbcSMatt Macy zpl_posix_acl_release(acl); 1186eda14cbcSMatt Macy 1187eda14cbcSMatt Macy return (error); 1188eda14cbcSMatt Macy } 1189eda14cbcSMatt Macy 1190eda14cbcSMatt Macy static int 1191eda14cbcSMatt Macy __zpl_xattr_acl_list_access(struct inode *ip, char *list, size_t list_size, 1192eda14cbcSMatt Macy const char *name, size_t name_len) 1193eda14cbcSMatt Macy { 1194eda14cbcSMatt Macy char *xattr_name = XATTR_NAME_POSIX_ACL_ACCESS; 1195eda14cbcSMatt Macy size_t xattr_size = sizeof (XATTR_NAME_POSIX_ACL_ACCESS); 1196eda14cbcSMatt Macy 11972c48331dSMatt Macy if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIX) 1198eda14cbcSMatt Macy return (0); 1199eda14cbcSMatt Macy 1200eda14cbcSMatt Macy if (list && xattr_size <= list_size) 1201eda14cbcSMatt Macy memcpy(list, xattr_name, xattr_size); 1202eda14cbcSMatt Macy 1203eda14cbcSMatt Macy return (xattr_size); 1204eda14cbcSMatt Macy } 1205eda14cbcSMatt Macy ZPL_XATTR_LIST_WRAPPER(zpl_xattr_acl_list_access); 1206eda14cbcSMatt Macy 1207eda14cbcSMatt Macy static int 1208eda14cbcSMatt Macy __zpl_xattr_acl_list_default(struct inode *ip, char *list, size_t list_size, 1209eda14cbcSMatt Macy const char *name, size_t name_len) 1210eda14cbcSMatt Macy { 1211eda14cbcSMatt Macy char *xattr_name = XATTR_NAME_POSIX_ACL_DEFAULT; 1212eda14cbcSMatt Macy size_t xattr_size = sizeof (XATTR_NAME_POSIX_ACL_DEFAULT); 1213eda14cbcSMatt Macy 12142c48331dSMatt Macy if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIX) 1215eda14cbcSMatt Macy return (0); 1216eda14cbcSMatt Macy 1217eda14cbcSMatt Macy if (list && xattr_size <= list_size) 1218eda14cbcSMatt Macy memcpy(list, xattr_name, xattr_size); 1219eda14cbcSMatt Macy 1220eda14cbcSMatt Macy return (xattr_size); 1221eda14cbcSMatt Macy } 1222eda14cbcSMatt Macy ZPL_XATTR_LIST_WRAPPER(zpl_xattr_acl_list_default); 1223eda14cbcSMatt Macy 1224eda14cbcSMatt Macy static int 1225eda14cbcSMatt Macy __zpl_xattr_acl_get_access(struct inode *ip, const char *name, 1226eda14cbcSMatt Macy void *buffer, size_t size) 1227eda14cbcSMatt Macy { 1228eda14cbcSMatt Macy struct posix_acl *acl; 1229eda14cbcSMatt Macy int type = ACL_TYPE_ACCESS; 1230eda14cbcSMatt Macy int error; 1231eda14cbcSMatt Macy /* xattr_resolve_name will do this for us if this is defined */ 12322c48331dSMatt Macy if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIX) 1233eda14cbcSMatt Macy return (-EOPNOTSUPP); 1234eda14cbcSMatt Macy 123553b70c86SMartin Matuska acl = zpl_get_acl_impl(ip, type); 1236eda14cbcSMatt Macy if (IS_ERR(acl)) 1237eda14cbcSMatt Macy return (PTR_ERR(acl)); 1238eda14cbcSMatt Macy if (acl == NULL) 1239eda14cbcSMatt Macy return (-ENODATA); 1240eda14cbcSMatt Macy 1241eda14cbcSMatt Macy error = zpl_acl_to_xattr(acl, buffer, size); 1242eda14cbcSMatt Macy zpl_posix_acl_release(acl); 1243eda14cbcSMatt Macy 1244eda14cbcSMatt Macy return (error); 1245eda14cbcSMatt Macy } 1246eda14cbcSMatt Macy ZPL_XATTR_GET_WRAPPER(zpl_xattr_acl_get_access); 1247eda14cbcSMatt Macy 1248eda14cbcSMatt Macy static int 1249eda14cbcSMatt Macy __zpl_xattr_acl_get_default(struct inode *ip, const char *name, 1250eda14cbcSMatt Macy void *buffer, size_t size) 1251eda14cbcSMatt Macy { 1252eda14cbcSMatt Macy struct posix_acl *acl; 1253eda14cbcSMatt Macy int type = ACL_TYPE_DEFAULT; 1254eda14cbcSMatt Macy int error; 1255eda14cbcSMatt Macy /* xattr_resolve_name will do this for us if this is defined */ 12562c48331dSMatt Macy if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIX) 1257eda14cbcSMatt Macy return (-EOPNOTSUPP); 1258eda14cbcSMatt Macy 125953b70c86SMartin Matuska acl = zpl_get_acl_impl(ip, type); 1260eda14cbcSMatt Macy if (IS_ERR(acl)) 1261eda14cbcSMatt Macy return (PTR_ERR(acl)); 1262eda14cbcSMatt Macy if (acl == NULL) 1263eda14cbcSMatt Macy return (-ENODATA); 1264eda14cbcSMatt Macy 1265eda14cbcSMatt Macy error = zpl_acl_to_xattr(acl, buffer, size); 1266eda14cbcSMatt Macy zpl_posix_acl_release(acl); 1267eda14cbcSMatt Macy 1268eda14cbcSMatt Macy return (error); 1269eda14cbcSMatt Macy } 1270eda14cbcSMatt Macy ZPL_XATTR_GET_WRAPPER(zpl_xattr_acl_get_default); 1271eda14cbcSMatt Macy 1272eda14cbcSMatt Macy static int 1273d411c1d6SMartin Matuska __zpl_xattr_acl_set_access(zidmap_t *mnt_ns, 1274dbd5678dSMartin Matuska struct inode *ip, const char *name, 1275eda14cbcSMatt Macy const void *value, size_t size, int flags) 1276eda14cbcSMatt Macy { 1277eda14cbcSMatt Macy struct posix_acl *acl; 1278eda14cbcSMatt Macy int type = ACL_TYPE_ACCESS; 1279eda14cbcSMatt Macy int error = 0; 1280eda14cbcSMatt Macy /* xattr_resolve_name will do this for us if this is defined */ 12812c48331dSMatt Macy if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIX) 1282eda14cbcSMatt Macy return (-EOPNOTSUPP); 1283eda14cbcSMatt Macy 1284d411c1d6SMartin Matuska #if defined(HAVE_XATTR_SET_USERNS) || defined(HAVE_XATTR_SET_IDMAP) 1285dbd5678dSMartin Matuska if (!zpl_inode_owner_or_capable(mnt_ns, ip)) 1286dbd5678dSMartin Matuska return (-EPERM); 1287dbd5678dSMartin Matuska #else 1288dbd5678dSMartin Matuska (void) mnt_ns; 1289d411c1d6SMartin Matuska if (!zpl_inode_owner_or_capable(zfs_init_idmap, ip)) 1290eda14cbcSMatt Macy return (-EPERM); 1291dbd5678dSMartin Matuska #endif 1292eda14cbcSMatt Macy 1293eda14cbcSMatt Macy if (value) { 1294eda14cbcSMatt Macy acl = zpl_acl_from_xattr(value, size); 1295eda14cbcSMatt Macy if (IS_ERR(acl)) 1296eda14cbcSMatt Macy return (PTR_ERR(acl)); 1297eda14cbcSMatt Macy else if (acl) { 1298*7a7741afSMartin Matuska error = posix_acl_valid(ip->i_sb->s_user_ns, acl); 1299eda14cbcSMatt Macy if (error) { 1300eda14cbcSMatt Macy zpl_posix_acl_release(acl); 1301eda14cbcSMatt Macy return (error); 1302eda14cbcSMatt Macy } 1303eda14cbcSMatt Macy } 1304eda14cbcSMatt Macy } else { 1305eda14cbcSMatt Macy acl = NULL; 1306eda14cbcSMatt Macy } 130716038816SMartin Matuska error = zpl_set_acl_impl(ip, acl, type); 1308eda14cbcSMatt Macy zpl_posix_acl_release(acl); 1309eda14cbcSMatt Macy 1310eda14cbcSMatt Macy return (error); 1311eda14cbcSMatt Macy } 1312eda14cbcSMatt Macy ZPL_XATTR_SET_WRAPPER(zpl_xattr_acl_set_access); 1313eda14cbcSMatt Macy 1314eda14cbcSMatt Macy static int 1315d411c1d6SMartin Matuska __zpl_xattr_acl_set_default(zidmap_t *mnt_ns, 1316dbd5678dSMartin Matuska struct inode *ip, const char *name, 1317eda14cbcSMatt Macy const void *value, size_t size, int flags) 1318eda14cbcSMatt Macy { 1319eda14cbcSMatt Macy struct posix_acl *acl; 1320eda14cbcSMatt Macy int type = ACL_TYPE_DEFAULT; 1321eda14cbcSMatt Macy int error = 0; 1322eda14cbcSMatt Macy /* xattr_resolve_name will do this for us if this is defined */ 13232c48331dSMatt Macy if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIX) 1324eda14cbcSMatt Macy return (-EOPNOTSUPP); 1325eda14cbcSMatt Macy 1326d411c1d6SMartin Matuska #if defined(HAVE_XATTR_SET_USERNS) || defined(HAVE_XATTR_SET_IDMAP) 1327dbd5678dSMartin Matuska if (!zpl_inode_owner_or_capable(mnt_ns, ip)) 1328dbd5678dSMartin Matuska return (-EPERM); 1329dbd5678dSMartin Matuska #else 1330dbd5678dSMartin Matuska (void) mnt_ns; 1331d411c1d6SMartin Matuska if (!zpl_inode_owner_or_capable(zfs_init_idmap, ip)) 1332eda14cbcSMatt Macy return (-EPERM); 1333dbd5678dSMartin Matuska #endif 1334eda14cbcSMatt Macy 1335eda14cbcSMatt Macy if (value) { 1336eda14cbcSMatt Macy acl = zpl_acl_from_xattr(value, size); 1337eda14cbcSMatt Macy if (IS_ERR(acl)) 1338eda14cbcSMatt Macy return (PTR_ERR(acl)); 1339eda14cbcSMatt Macy else if (acl) { 1340*7a7741afSMartin Matuska error = posix_acl_valid(ip->i_sb->s_user_ns, acl); 1341eda14cbcSMatt Macy if (error) { 1342eda14cbcSMatt Macy zpl_posix_acl_release(acl); 1343eda14cbcSMatt Macy return (error); 1344eda14cbcSMatt Macy } 1345eda14cbcSMatt Macy } 1346eda14cbcSMatt Macy } else { 1347eda14cbcSMatt Macy acl = NULL; 1348eda14cbcSMatt Macy } 1349eda14cbcSMatt Macy 135016038816SMartin Matuska error = zpl_set_acl_impl(ip, acl, type); 1351eda14cbcSMatt Macy zpl_posix_acl_release(acl); 1352eda14cbcSMatt Macy 1353eda14cbcSMatt Macy return (error); 1354eda14cbcSMatt Macy } 1355eda14cbcSMatt Macy ZPL_XATTR_SET_WRAPPER(zpl_xattr_acl_set_default); 1356eda14cbcSMatt Macy 1357eda14cbcSMatt Macy /* 1358eda14cbcSMatt Macy * ACL access xattr namespace handlers. 1359eda14cbcSMatt Macy * 1360eda14cbcSMatt Macy * Use .name instead of .prefix when available. xattr_resolve_name will match 1361eda14cbcSMatt Macy * whole name and reject anything that has .name only as prefix. 1362eda14cbcSMatt Macy */ 1363e92ffd9bSMartin Matuska static xattr_handler_t zpl_xattr_acl_access_handler = { 1364eda14cbcSMatt Macy .name = XATTR_NAME_POSIX_ACL_ACCESS, 1365eda14cbcSMatt Macy .list = zpl_xattr_acl_list_access, 1366eda14cbcSMatt Macy .get = zpl_xattr_acl_get_access, 1367eda14cbcSMatt Macy .set = zpl_xattr_acl_set_access, 1368eda14cbcSMatt Macy .flags = ACL_TYPE_ACCESS, 1369eda14cbcSMatt Macy }; 1370eda14cbcSMatt Macy 1371eda14cbcSMatt Macy /* 1372eda14cbcSMatt Macy * ACL default xattr namespace handlers. 1373eda14cbcSMatt Macy * 1374*7a7741afSMartin Matuska * Use .name instead of .prefix. xattr_resolve_name will match whole name and 1375*7a7741afSMartin Matuska * reject anything that has .name only as prefix. 1376eda14cbcSMatt Macy */ 1377e92ffd9bSMartin Matuska static xattr_handler_t zpl_xattr_acl_default_handler = { 1378eda14cbcSMatt Macy .name = XATTR_NAME_POSIX_ACL_DEFAULT, 1379eda14cbcSMatt Macy .list = zpl_xattr_acl_list_default, 1380eda14cbcSMatt Macy .get = zpl_xattr_acl_get_default, 1381eda14cbcSMatt Macy .set = zpl_xattr_acl_set_default, 1382eda14cbcSMatt Macy .flags = ACL_TYPE_DEFAULT, 1383eda14cbcSMatt Macy }; 1384eda14cbcSMatt Macy 1385eda14cbcSMatt Macy #endif /* CONFIG_FS_POSIX_ACL */ 1386eda14cbcSMatt Macy 1387eda14cbcSMatt Macy xattr_handler_t *zpl_xattr_handlers[] = { 1388eda14cbcSMatt Macy &zpl_xattr_security_handler, 1389eda14cbcSMatt Macy &zpl_xattr_trusted_handler, 1390eda14cbcSMatt Macy &zpl_xattr_user_handler, 1391eda14cbcSMatt Macy #ifdef CONFIG_FS_POSIX_ACL 1392eda14cbcSMatt Macy &zpl_xattr_acl_access_handler, 1393eda14cbcSMatt Macy &zpl_xattr_acl_default_handler, 1394eda14cbcSMatt Macy #endif /* CONFIG_FS_POSIX_ACL */ 1395eda14cbcSMatt Macy NULL 1396eda14cbcSMatt Macy }; 1397eda14cbcSMatt Macy 1398eda14cbcSMatt Macy static const struct xattr_handler * 1399eda14cbcSMatt Macy zpl_xattr_handler(const char *name) 1400eda14cbcSMatt Macy { 1401eda14cbcSMatt Macy if (strncmp(name, XATTR_USER_PREFIX, 1402eda14cbcSMatt Macy XATTR_USER_PREFIX_LEN) == 0) 1403eda14cbcSMatt Macy return (&zpl_xattr_user_handler); 1404eda14cbcSMatt Macy 1405eda14cbcSMatt Macy if (strncmp(name, XATTR_TRUSTED_PREFIX, 1406eda14cbcSMatt Macy XATTR_TRUSTED_PREFIX_LEN) == 0) 1407eda14cbcSMatt Macy return (&zpl_xattr_trusted_handler); 1408eda14cbcSMatt Macy 1409eda14cbcSMatt Macy if (strncmp(name, XATTR_SECURITY_PREFIX, 1410eda14cbcSMatt Macy XATTR_SECURITY_PREFIX_LEN) == 0) 1411eda14cbcSMatt Macy return (&zpl_xattr_security_handler); 1412eda14cbcSMatt Macy 1413eda14cbcSMatt Macy #ifdef CONFIG_FS_POSIX_ACL 1414eda14cbcSMatt Macy if (strncmp(name, XATTR_NAME_POSIX_ACL_ACCESS, 1415eda14cbcSMatt Macy sizeof (XATTR_NAME_POSIX_ACL_ACCESS)) == 0) 1416eda14cbcSMatt Macy return (&zpl_xattr_acl_access_handler); 1417eda14cbcSMatt Macy 1418eda14cbcSMatt Macy if (strncmp(name, XATTR_NAME_POSIX_ACL_DEFAULT, 1419eda14cbcSMatt Macy sizeof (XATTR_NAME_POSIX_ACL_DEFAULT)) == 0) 1420eda14cbcSMatt Macy return (&zpl_xattr_acl_default_handler); 1421eda14cbcSMatt Macy #endif /* CONFIG_FS_POSIX_ACL */ 1422eda14cbcSMatt Macy 1423eda14cbcSMatt Macy return (NULL); 1424eda14cbcSMatt Macy } 1425eda14cbcSMatt Macy 1426c03c5b1cSMartin Matuska static enum xattr_permission 1427c03c5b1cSMartin Matuska zpl_xattr_permission(xattr_filldir_t *xf, const char *name, int name_len) 1428c03c5b1cSMartin Matuska { 1429c03c5b1cSMartin Matuska const struct xattr_handler *handler; 1430c03c5b1cSMartin Matuska struct dentry *d __maybe_unused = xf->dentry; 1431c03c5b1cSMartin Matuska enum xattr_permission perm = XAPERM_ALLOW; 1432c03c5b1cSMartin Matuska 1433c03c5b1cSMartin Matuska handler = zpl_xattr_handler(name); 1434c03c5b1cSMartin Matuska if (handler == NULL) { 1435c03c5b1cSMartin Matuska /* Do not expose FreeBSD system namespace xattrs. */ 1436c03c5b1cSMartin Matuska if (ZFS_XA_NS_PREFIX_MATCH(FREEBSD, name)) 1437c03c5b1cSMartin Matuska return (XAPERM_DENY); 1438c03c5b1cSMartin Matuska /* 1439c03c5b1cSMartin Matuska * Anything that doesn't match a known namespace gets put in the 1440c03c5b1cSMartin Matuska * user namespace for compatibility with other platforms. 1441c03c5b1cSMartin Matuska */ 1442c03c5b1cSMartin Matuska perm = XAPERM_COMPAT; 1443c03c5b1cSMartin Matuska handler = &zpl_xattr_user_handler; 1444c03c5b1cSMartin Matuska } 1445c03c5b1cSMartin Matuska 1446c03c5b1cSMartin Matuska if (handler->list) { 1447c03c5b1cSMartin Matuska if (!handler->list(d)) 1448c03c5b1cSMartin Matuska return (XAPERM_DENY); 1449c03c5b1cSMartin Matuska } 1450c03c5b1cSMartin Matuska 1451c03c5b1cSMartin Matuska return (perm); 1452c03c5b1cSMartin Matuska } 1453c03c5b1cSMartin Matuska 1454*7a7741afSMartin Matuska #ifdef CONFIG_FS_POSIX_ACL 1455*7a7741afSMartin Matuska 1456eda14cbcSMatt Macy struct acl_rel_struct { 1457eda14cbcSMatt Macy struct acl_rel_struct *next; 1458eda14cbcSMatt Macy struct posix_acl *acl; 1459eda14cbcSMatt Macy clock_t time; 1460eda14cbcSMatt Macy }; 1461eda14cbcSMatt Macy 1462eda14cbcSMatt Macy #define ACL_REL_GRACE (60*HZ) 1463eda14cbcSMatt Macy #define ACL_REL_WINDOW (1*HZ) 1464eda14cbcSMatt Macy #define ACL_REL_SCHED (ACL_REL_GRACE+ACL_REL_WINDOW) 1465eda14cbcSMatt Macy 1466eda14cbcSMatt Macy /* 1467eda14cbcSMatt Macy * Lockless multi-producer single-consumer fifo list. 1468eda14cbcSMatt Macy * Nodes are added to tail and removed from head. Tail pointer is our 1469eda14cbcSMatt Macy * synchronization point. It always points to the next pointer of the last 1470eda14cbcSMatt Macy * node, or head if list is empty. 1471eda14cbcSMatt Macy */ 1472eda14cbcSMatt Macy static struct acl_rel_struct *acl_rel_head = NULL; 1473eda14cbcSMatt Macy static struct acl_rel_struct **acl_rel_tail = &acl_rel_head; 1474eda14cbcSMatt Macy 1475eda14cbcSMatt Macy static void 1476eda14cbcSMatt Macy zpl_posix_acl_free(void *arg) 1477eda14cbcSMatt Macy { 1478eda14cbcSMatt Macy struct acl_rel_struct *freelist = NULL; 1479eda14cbcSMatt Macy struct acl_rel_struct *a; 1480eda14cbcSMatt Macy clock_t new_time; 1481eda14cbcSMatt Macy boolean_t refire = B_FALSE; 1482eda14cbcSMatt Macy 1483eda14cbcSMatt Macy ASSERT3P(acl_rel_head, !=, NULL); 1484eda14cbcSMatt Macy while (acl_rel_head) { 1485eda14cbcSMatt Macy a = acl_rel_head; 1486eda14cbcSMatt Macy if (ddi_get_lbolt() - a->time >= ACL_REL_GRACE) { 1487eda14cbcSMatt Macy /* 1488eda14cbcSMatt Macy * If a is the last node we need to reset tail, but we 1489eda14cbcSMatt Macy * need to use cmpxchg to make sure it is still the 1490eda14cbcSMatt Macy * last node. 1491eda14cbcSMatt Macy */ 1492eda14cbcSMatt Macy if (acl_rel_tail == &a->next) { 1493eda14cbcSMatt Macy acl_rel_head = NULL; 1494eda14cbcSMatt Macy if (cmpxchg(&acl_rel_tail, &a->next, 1495eda14cbcSMatt Macy &acl_rel_head) == &a->next) { 1496eda14cbcSMatt Macy ASSERT3P(a->next, ==, NULL); 1497eda14cbcSMatt Macy a->next = freelist; 1498eda14cbcSMatt Macy freelist = a; 1499eda14cbcSMatt Macy break; 1500eda14cbcSMatt Macy } 1501eda14cbcSMatt Macy } 1502eda14cbcSMatt Macy /* 1503eda14cbcSMatt Macy * a is not last node, make sure next pointer is set 1504eda14cbcSMatt Macy * by the adder and advance the head. 1505eda14cbcSMatt Macy */ 1506eda14cbcSMatt Macy while (READ_ONCE(a->next) == NULL) 1507eda14cbcSMatt Macy cpu_relax(); 1508eda14cbcSMatt Macy acl_rel_head = a->next; 1509eda14cbcSMatt Macy a->next = freelist; 1510eda14cbcSMatt Macy freelist = a; 1511eda14cbcSMatt Macy } else { 1512eda14cbcSMatt Macy /* 1513eda14cbcSMatt Macy * a is still in grace period. We are responsible to 1514eda14cbcSMatt Macy * reschedule the free task, since adder will only do 1515eda14cbcSMatt Macy * so if list is empty. 1516eda14cbcSMatt Macy */ 1517eda14cbcSMatt Macy new_time = a->time + ACL_REL_SCHED; 1518eda14cbcSMatt Macy refire = B_TRUE; 1519eda14cbcSMatt Macy break; 1520eda14cbcSMatt Macy } 1521eda14cbcSMatt Macy } 1522eda14cbcSMatt Macy 1523eda14cbcSMatt Macy if (refire) 1524eda14cbcSMatt Macy taskq_dispatch_delay(system_delay_taskq, zpl_posix_acl_free, 1525eda14cbcSMatt Macy NULL, TQ_SLEEP, new_time); 1526eda14cbcSMatt Macy 1527eda14cbcSMatt Macy while (freelist) { 1528eda14cbcSMatt Macy a = freelist; 1529eda14cbcSMatt Macy freelist = a->next; 1530eda14cbcSMatt Macy kfree(a->acl); 1531eda14cbcSMatt Macy kmem_free(a, sizeof (struct acl_rel_struct)); 1532eda14cbcSMatt Macy } 1533eda14cbcSMatt Macy } 1534eda14cbcSMatt Macy 1535eda14cbcSMatt Macy void 1536eda14cbcSMatt Macy zpl_posix_acl_release_impl(struct posix_acl *acl) 1537eda14cbcSMatt Macy { 1538eda14cbcSMatt Macy struct acl_rel_struct *a, **prev; 1539eda14cbcSMatt Macy 1540eda14cbcSMatt Macy a = kmem_alloc(sizeof (struct acl_rel_struct), KM_SLEEP); 1541eda14cbcSMatt Macy a->next = NULL; 1542eda14cbcSMatt Macy a->acl = acl; 1543eda14cbcSMatt Macy a->time = ddi_get_lbolt(); 1544eda14cbcSMatt Macy /* atomically points tail to us and get the previous tail */ 1545eda14cbcSMatt Macy prev = xchg(&acl_rel_tail, &a->next); 1546eda14cbcSMatt Macy ASSERT3P(*prev, ==, NULL); 1547eda14cbcSMatt Macy *prev = a; 1548eda14cbcSMatt Macy /* if it was empty before, schedule the free task */ 1549eda14cbcSMatt Macy if (prev == &acl_rel_head) 1550eda14cbcSMatt Macy taskq_dispatch_delay(system_delay_taskq, zpl_posix_acl_free, 1551eda14cbcSMatt Macy NULL, TQ_SLEEP, ddi_get_lbolt() + ACL_REL_SCHED); 1552eda14cbcSMatt Macy } 1553eda14cbcSMatt Macy #endif 1554c03c5b1cSMartin Matuska 1555c03c5b1cSMartin Matuska ZFS_MODULE_PARAM(zfs, zfs_, xattr_compat, INT, ZMOD_RW, 1556c03c5b1cSMartin Matuska "Use legacy ZFS xattr naming for writing new user namespace xattrs"); 1557