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 * Copyright (c) 2015 by Chunwei Chen. All rights reserved. 24eda14cbcSMatt Macy */ 25eda14cbcSMatt Macy 26eda14cbcSMatt Macy 27dbd5678dSMartin Matuska #include <sys/sysmacros.h> 28eda14cbcSMatt Macy #include <sys/zfs_ctldir.h> 29eda14cbcSMatt Macy #include <sys/zfs_vfsops.h> 30eda14cbcSMatt Macy #include <sys/zfs_vnops.h> 31eda14cbcSMatt Macy #include <sys/zfs_znode.h> 32eda14cbcSMatt Macy #include <sys/dmu_objset.h> 33eda14cbcSMatt Macy #include <sys/vfs.h> 34eda14cbcSMatt Macy #include <sys/zpl.h> 35eda14cbcSMatt Macy #include <sys/file.h> 36eda14cbcSMatt Macy 37eda14cbcSMatt Macy static struct dentry * 38eda14cbcSMatt Macy zpl_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) 39eda14cbcSMatt Macy { 40eda14cbcSMatt Macy cred_t *cr = CRED(); 41eda14cbcSMatt Macy struct inode *ip; 42eda14cbcSMatt Macy znode_t *zp; 43eda14cbcSMatt Macy int error; 44eda14cbcSMatt Macy fstrans_cookie_t cookie; 45eda14cbcSMatt Macy pathname_t *ppn = NULL; 46eda14cbcSMatt Macy pathname_t pn; 47eda14cbcSMatt Macy int zfs_flags = 0; 48eda14cbcSMatt Macy zfsvfs_t *zfsvfs = dentry->d_sb->s_fs_info; 49*7a7741afSMartin Matuska dsl_dataset_t *ds = dmu_objset_ds(zfsvfs->z_os); 50*7a7741afSMartin Matuska size_t dlen = dlen(dentry); 51eda14cbcSMatt Macy 52*7a7741afSMartin Matuska /* 53*7a7741afSMartin Matuska * If z_longname is disabled, disallow create or rename of names 54*7a7741afSMartin Matuska * longer than ZAP_MAXNAMELEN. 55*7a7741afSMartin Matuska * 56*7a7741afSMartin Matuska * This is needed in cases where longname was enabled first and some 57*7a7741afSMartin Matuska * files/dirs with names > ZAP_MAXNAMELEN were created. And later 58*7a7741afSMartin Matuska * longname was disabled. In such a case allow access to existing 59*7a7741afSMartin Matuska * longnames. But disallow creation newer longnamed entities. 60*7a7741afSMartin Matuska */ 61*7a7741afSMartin Matuska if (!zfsvfs->z_longname && (dlen >= ZAP_MAXNAMELEN)) { 62*7a7741afSMartin Matuska /* 63*7a7741afSMartin Matuska * If this is for create or rename fail it. 64*7a7741afSMartin Matuska */ 65*7a7741afSMartin Matuska if (!dsl_dataset_feature_is_active(ds, SPA_FEATURE_LONGNAME) || 66*7a7741afSMartin Matuska (flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))) 67eda14cbcSMatt Macy return (ERR_PTR(-ENAMETOOLONG)); 68*7a7741afSMartin Matuska } 69*7a7741afSMartin Matuska if (dlen >= ZAP_MAXNAMELEN_NEW) { 70*7a7741afSMartin Matuska return (ERR_PTR(-ENAMETOOLONG)); 71*7a7741afSMartin Matuska } 72eda14cbcSMatt Macy 73eda14cbcSMatt Macy crhold(cr); 74eda14cbcSMatt Macy cookie = spl_fstrans_mark(); 75eda14cbcSMatt Macy 76eda14cbcSMatt Macy /* If we are a case insensitive fs, we need the real name */ 77eda14cbcSMatt Macy if (zfsvfs->z_case == ZFS_CASE_INSENSITIVE) { 78eda14cbcSMatt Macy zfs_flags = FIGNORECASE; 79eda14cbcSMatt Macy pn_alloc(&pn); 80eda14cbcSMatt Macy ppn = &pn; 81eda14cbcSMatt Macy } 82eda14cbcSMatt Macy 83eda14cbcSMatt Macy error = -zfs_lookup(ITOZ(dir), dname(dentry), &zp, 84eda14cbcSMatt Macy zfs_flags, cr, NULL, ppn); 85eda14cbcSMatt Macy spl_fstrans_unmark(cookie); 86eda14cbcSMatt Macy ASSERT3S(error, <=, 0); 87eda14cbcSMatt Macy crfree(cr); 88eda14cbcSMatt Macy 89eda14cbcSMatt Macy spin_lock(&dentry->d_lock); 90eda14cbcSMatt Macy dentry->d_time = jiffies; 91eda14cbcSMatt Macy spin_unlock(&dentry->d_lock); 92eda14cbcSMatt Macy 93eda14cbcSMatt Macy if (error) { 94eda14cbcSMatt Macy /* 95eda14cbcSMatt Macy * If we have a case sensitive fs, we do not want to 96eda14cbcSMatt Macy * insert negative entries, so return NULL for ENOENT. 97eda14cbcSMatt Macy * Fall through if the error is not ENOENT. Also free memory. 98eda14cbcSMatt Macy */ 99eda14cbcSMatt Macy if (ppn) { 100eda14cbcSMatt Macy pn_free(ppn); 101eda14cbcSMatt Macy if (error == -ENOENT) 102eda14cbcSMatt Macy return (NULL); 103eda14cbcSMatt Macy } 104eda14cbcSMatt Macy 105eda14cbcSMatt Macy if (error == -ENOENT) 106eda14cbcSMatt Macy return (d_splice_alias(NULL, dentry)); 107eda14cbcSMatt Macy else 108eda14cbcSMatt Macy return (ERR_PTR(error)); 109eda14cbcSMatt Macy } 110eda14cbcSMatt Macy ip = ZTOI(zp); 111eda14cbcSMatt Macy 112eda14cbcSMatt Macy /* 113eda14cbcSMatt Macy * If we are case insensitive, call the correct function 114eda14cbcSMatt Macy * to install the name. 115eda14cbcSMatt Macy */ 116eda14cbcSMatt Macy if (ppn) { 117eda14cbcSMatt Macy struct dentry *new_dentry; 118eda14cbcSMatt Macy struct qstr ci_name; 119eda14cbcSMatt Macy 120eda14cbcSMatt Macy if (strcmp(dname(dentry), pn.pn_buf) == 0) { 121eda14cbcSMatt Macy new_dentry = d_splice_alias(ip, dentry); 122eda14cbcSMatt Macy } else { 123eda14cbcSMatt Macy ci_name.name = pn.pn_buf; 124eda14cbcSMatt Macy ci_name.len = strlen(pn.pn_buf); 125eda14cbcSMatt Macy new_dentry = d_add_ci(dentry, ip, &ci_name); 126eda14cbcSMatt Macy } 127eda14cbcSMatt Macy pn_free(ppn); 128eda14cbcSMatt Macy return (new_dentry); 129eda14cbcSMatt Macy } else { 130eda14cbcSMatt Macy return (d_splice_alias(ip, dentry)); 131eda14cbcSMatt Macy } 132eda14cbcSMatt Macy } 133eda14cbcSMatt Macy 134eda14cbcSMatt Macy void 135dbd5678dSMartin Matuska zpl_vap_init(vattr_t *vap, struct inode *dir, umode_t mode, cred_t *cr, 136d411c1d6SMartin Matuska zidmap_t *mnt_ns) 137eda14cbcSMatt Macy { 138eda14cbcSMatt Macy vap->va_mask = ATTR_MODE; 139eda14cbcSMatt Macy vap->va_mode = mode; 140eda14cbcSMatt Macy 141d411c1d6SMartin Matuska vap->va_uid = zfs_vfsuid_to_uid(mnt_ns, 142dbd5678dSMartin Matuska zfs_i_user_ns(dir), crgetuid(cr)); 143dbd5678dSMartin Matuska 144dbd5678dSMartin Matuska if (dir->i_mode & S_ISGID) { 145eda14cbcSMatt Macy vap->va_gid = KGID_TO_SGID(dir->i_gid); 146eda14cbcSMatt Macy if (S_ISDIR(mode)) 147eda14cbcSMatt Macy vap->va_mode |= S_ISGID; 148eda14cbcSMatt Macy } else { 149d411c1d6SMartin Matuska vap->va_gid = zfs_vfsgid_to_gid(mnt_ns, 150dbd5678dSMartin Matuska zfs_i_user_ns(dir), crgetgid(cr)); 151eda14cbcSMatt Macy } 152eda14cbcSMatt Macy } 153eda14cbcSMatt Macy 154*7a7741afSMartin Matuska static inline bool 155*7a7741afSMartin Matuska is_nametoolong(struct dentry *dentry) 156*7a7741afSMartin Matuska { 157*7a7741afSMartin Matuska zfsvfs_t *zfsvfs = dentry->d_sb->s_fs_info; 158*7a7741afSMartin Matuska size_t dlen = dlen(dentry); 159*7a7741afSMartin Matuska 160*7a7741afSMartin Matuska return ((!zfsvfs->z_longname && dlen >= ZAP_MAXNAMELEN) || 161*7a7741afSMartin Matuska dlen >= ZAP_MAXNAMELEN_NEW); 162*7a7741afSMartin Matuska } 163*7a7741afSMartin Matuska 164eda14cbcSMatt Macy static int 165f9693befSMartin Matuska #ifdef HAVE_IOPS_CREATE_USERNS 166f9693befSMartin Matuska zpl_create(struct user_namespace *user_ns, struct inode *dir, 167f9693befSMartin Matuska struct dentry *dentry, umode_t mode, bool flag) 168d411c1d6SMartin Matuska #elif defined(HAVE_IOPS_CREATE_IDMAP) 169d411c1d6SMartin Matuska zpl_create(struct mnt_idmap *user_ns, struct inode *dir, 170d411c1d6SMartin Matuska struct dentry *dentry, umode_t mode, bool flag) 171f9693befSMartin Matuska #else 172eda14cbcSMatt Macy zpl_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool flag) 173f9693befSMartin Matuska #endif 174eda14cbcSMatt Macy { 175eda14cbcSMatt Macy cred_t *cr = CRED(); 176eda14cbcSMatt Macy znode_t *zp; 177eda14cbcSMatt Macy vattr_t *vap; 178eda14cbcSMatt Macy int error; 179eda14cbcSMatt Macy fstrans_cookie_t cookie; 180d411c1d6SMartin Matuska #if !(defined(HAVE_IOPS_CREATE_USERNS) || defined(HAVE_IOPS_CREATE_IDMAP)) 181d411c1d6SMartin Matuska zidmap_t *user_ns = kcred->user_ns; 182dbd5678dSMartin Matuska #endif 183eda14cbcSMatt Macy 184*7a7741afSMartin Matuska if (is_nametoolong(dentry)) { 185*7a7741afSMartin Matuska return (-ENAMETOOLONG); 186*7a7741afSMartin Matuska } 187*7a7741afSMartin Matuska 188eda14cbcSMatt Macy crhold(cr); 189eda14cbcSMatt Macy vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP); 190dbd5678dSMartin Matuska zpl_vap_init(vap, dir, mode, cr, user_ns); 191eda14cbcSMatt Macy 192eda14cbcSMatt Macy cookie = spl_fstrans_mark(); 193eda14cbcSMatt Macy error = -zfs_create(ITOZ(dir), dname(dentry), vap, 0, 194dbd5678dSMartin Matuska mode, &zp, cr, 0, NULL, user_ns); 195eda14cbcSMatt Macy if (error == 0) { 196eda14cbcSMatt Macy error = zpl_xattr_security_init(ZTOI(zp), dir, &dentry->d_name); 197eda14cbcSMatt Macy if (error == 0) 198eda14cbcSMatt Macy error = zpl_init_acl(ZTOI(zp), dir); 199eda14cbcSMatt Macy 20016038816SMartin Matuska if (error) { 201eda14cbcSMatt Macy (void) zfs_remove(ITOZ(dir), dname(dentry), cr, 0); 20216038816SMartin Matuska remove_inode_hash(ZTOI(zp)); 20316038816SMartin Matuska iput(ZTOI(zp)); 20416038816SMartin Matuska } else { 20516038816SMartin Matuska d_instantiate(dentry, ZTOI(zp)); 20616038816SMartin Matuska } 207eda14cbcSMatt Macy } 208eda14cbcSMatt Macy 209eda14cbcSMatt Macy spl_fstrans_unmark(cookie); 210eda14cbcSMatt Macy kmem_free(vap, sizeof (vattr_t)); 211eda14cbcSMatt Macy crfree(cr); 212eda14cbcSMatt Macy ASSERT3S(error, <=, 0); 213eda14cbcSMatt Macy 214eda14cbcSMatt Macy return (error); 215eda14cbcSMatt Macy } 216eda14cbcSMatt Macy 217eda14cbcSMatt Macy static int 218f9693befSMartin Matuska #ifdef HAVE_IOPS_MKNOD_USERNS 219f9693befSMartin Matuska zpl_mknod(struct user_namespace *user_ns, struct inode *dir, 220f9693befSMartin Matuska struct dentry *dentry, umode_t mode, 221d411c1d6SMartin Matuska #elif defined(HAVE_IOPS_MKNOD_IDMAP) 222d411c1d6SMartin Matuska zpl_mknod(struct mnt_idmap *user_ns, struct inode *dir, 223d411c1d6SMartin Matuska struct dentry *dentry, umode_t mode, 224f9693befSMartin Matuska #else 225eda14cbcSMatt Macy zpl_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, 226f9693befSMartin Matuska #endif 227eda14cbcSMatt Macy dev_t rdev) 228eda14cbcSMatt Macy { 229eda14cbcSMatt Macy cred_t *cr = CRED(); 230eda14cbcSMatt Macy znode_t *zp; 231eda14cbcSMatt Macy vattr_t *vap; 232eda14cbcSMatt Macy int error; 233eda14cbcSMatt Macy fstrans_cookie_t cookie; 234d411c1d6SMartin Matuska #if !(defined(HAVE_IOPS_MKNOD_USERNS) || defined(HAVE_IOPS_MKNOD_IDMAP)) 235d411c1d6SMartin Matuska zidmap_t *user_ns = kcred->user_ns; 236dbd5678dSMartin Matuska #endif 237eda14cbcSMatt Macy 238*7a7741afSMartin Matuska if (is_nametoolong(dentry)) { 239*7a7741afSMartin Matuska return (-ENAMETOOLONG); 240*7a7741afSMartin Matuska } 241*7a7741afSMartin Matuska 242eda14cbcSMatt Macy /* 243eda14cbcSMatt Macy * We currently expect Linux to supply rdev=0 for all sockets 244eda14cbcSMatt Macy * and fifos, but we want to know if this behavior ever changes. 245eda14cbcSMatt Macy */ 246eda14cbcSMatt Macy if (S_ISSOCK(mode) || S_ISFIFO(mode)) 247eda14cbcSMatt Macy ASSERT(rdev == 0); 248eda14cbcSMatt Macy 249eda14cbcSMatt Macy crhold(cr); 250eda14cbcSMatt Macy vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP); 251dbd5678dSMartin Matuska zpl_vap_init(vap, dir, mode, cr, user_ns); 252eda14cbcSMatt Macy vap->va_rdev = rdev; 253eda14cbcSMatt Macy 254eda14cbcSMatt Macy cookie = spl_fstrans_mark(); 255eda14cbcSMatt Macy error = -zfs_create(ITOZ(dir), dname(dentry), vap, 0, 256dbd5678dSMartin Matuska mode, &zp, cr, 0, NULL, user_ns); 257eda14cbcSMatt Macy if (error == 0) { 258eda14cbcSMatt Macy error = zpl_xattr_security_init(ZTOI(zp), dir, &dentry->d_name); 259eda14cbcSMatt Macy if (error == 0) 260eda14cbcSMatt Macy error = zpl_init_acl(ZTOI(zp), dir); 261eda14cbcSMatt Macy 26216038816SMartin Matuska if (error) { 263eda14cbcSMatt Macy (void) zfs_remove(ITOZ(dir), dname(dentry), cr, 0); 26416038816SMartin Matuska remove_inode_hash(ZTOI(zp)); 26516038816SMartin Matuska iput(ZTOI(zp)); 26616038816SMartin Matuska } else { 26716038816SMartin Matuska d_instantiate(dentry, ZTOI(zp)); 26816038816SMartin Matuska } 269eda14cbcSMatt Macy } 270eda14cbcSMatt Macy 271eda14cbcSMatt Macy spl_fstrans_unmark(cookie); 272eda14cbcSMatt Macy kmem_free(vap, sizeof (vattr_t)); 273eda14cbcSMatt Macy crfree(cr); 274eda14cbcSMatt Macy ASSERT3S(error, <=, 0); 275eda14cbcSMatt Macy 276eda14cbcSMatt Macy return (error); 277eda14cbcSMatt Macy } 278eda14cbcSMatt Macy 279eda14cbcSMatt Macy static int 280d411c1d6SMartin Matuska #ifdef HAVE_TMPFILE_IDMAP 281d411c1d6SMartin Matuska zpl_tmpfile(struct mnt_idmap *userns, struct inode *dir, 282d411c1d6SMartin Matuska struct file *file, umode_t mode) 283d411c1d6SMartin Matuska #elif !defined(HAVE_TMPFILE_DENTRY) 28415f0b8c3SMartin Matuska zpl_tmpfile(struct user_namespace *userns, struct inode *dir, 28515f0b8c3SMartin Matuska struct file *file, umode_t mode) 28615f0b8c3SMartin Matuska #else 28716038816SMartin Matuska #ifdef HAVE_TMPFILE_USERNS 28816038816SMartin Matuska zpl_tmpfile(struct user_namespace *userns, struct inode *dir, 28916038816SMartin Matuska struct dentry *dentry, umode_t mode) 29016038816SMartin Matuska #else 291eda14cbcSMatt Macy zpl_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) 29216038816SMartin Matuska #endif 29315f0b8c3SMartin Matuska #endif 294eda14cbcSMatt Macy { 295eda14cbcSMatt Macy cred_t *cr = CRED(); 296eda14cbcSMatt Macy struct inode *ip; 297eda14cbcSMatt Macy vattr_t *vap; 298eda14cbcSMatt Macy int error; 299eda14cbcSMatt Macy fstrans_cookie_t cookie; 300d411c1d6SMartin Matuska #if !(defined(HAVE_TMPFILE_USERNS) || defined(HAVE_TMPFILE_IDMAP)) 301d411c1d6SMartin Matuska zidmap_t *userns = kcred->user_ns; 302dbd5678dSMartin Matuska #endif 303eda14cbcSMatt Macy 304eda14cbcSMatt Macy crhold(cr); 305eda14cbcSMatt Macy vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP); 306eda14cbcSMatt Macy /* 307eda14cbcSMatt Macy * The VFS does not apply the umask, therefore it is applied here 308eda14cbcSMatt Macy * when POSIX ACLs are not enabled. 309eda14cbcSMatt Macy */ 310eda14cbcSMatt Macy if (!IS_POSIXACL(dir)) 311eda14cbcSMatt Macy mode &= ~current_umask(); 312dbd5678dSMartin Matuska zpl_vap_init(vap, dir, mode, cr, userns); 313eda14cbcSMatt Macy 314eda14cbcSMatt Macy cookie = spl_fstrans_mark(); 315dbd5678dSMartin Matuska error = -zfs_tmpfile(dir, vap, 0, mode, &ip, cr, 0, NULL, userns); 316eda14cbcSMatt Macy if (error == 0) { 317eda14cbcSMatt Macy /* d_tmpfile will do drop_nlink, so we should set it first */ 318eda14cbcSMatt Macy set_nlink(ip, 1); 31915f0b8c3SMartin Matuska #ifndef HAVE_TMPFILE_DENTRY 32015f0b8c3SMartin Matuska d_tmpfile(file, ip); 32115f0b8c3SMartin Matuska 32215f0b8c3SMartin Matuska error = zpl_xattr_security_init(ip, dir, 32315f0b8c3SMartin Matuska &file->f_path.dentry->d_name); 32415f0b8c3SMartin Matuska #else 325eda14cbcSMatt Macy d_tmpfile(dentry, ip); 326eda14cbcSMatt Macy 327eda14cbcSMatt Macy error = zpl_xattr_security_init(ip, dir, &dentry->d_name); 32815f0b8c3SMartin Matuska #endif 329eda14cbcSMatt Macy if (error == 0) 330eda14cbcSMatt Macy error = zpl_init_acl(ip, dir); 33115f0b8c3SMartin Matuska #ifndef HAVE_TMPFILE_DENTRY 33215f0b8c3SMartin Matuska error = finish_open_simple(file, error); 33315f0b8c3SMartin Matuska #endif 334eda14cbcSMatt Macy /* 335eda14cbcSMatt Macy * don't need to handle error here, file is already in 336eda14cbcSMatt Macy * unlinked set. 337eda14cbcSMatt Macy */ 338eda14cbcSMatt Macy } 339eda14cbcSMatt Macy 340eda14cbcSMatt Macy spl_fstrans_unmark(cookie); 341eda14cbcSMatt Macy kmem_free(vap, sizeof (vattr_t)); 342eda14cbcSMatt Macy crfree(cr); 343eda14cbcSMatt Macy ASSERT3S(error, <=, 0); 344eda14cbcSMatt Macy 345eda14cbcSMatt Macy return (error); 346eda14cbcSMatt Macy } 347eda14cbcSMatt Macy 348eda14cbcSMatt Macy static int 349eda14cbcSMatt Macy zpl_unlink(struct inode *dir, struct dentry *dentry) 350eda14cbcSMatt Macy { 351eda14cbcSMatt Macy cred_t *cr = CRED(); 352eda14cbcSMatt Macy int error; 353eda14cbcSMatt Macy fstrans_cookie_t cookie; 354eda14cbcSMatt Macy zfsvfs_t *zfsvfs = dentry->d_sb->s_fs_info; 355eda14cbcSMatt Macy 356eda14cbcSMatt Macy crhold(cr); 357eda14cbcSMatt Macy cookie = spl_fstrans_mark(); 358eda14cbcSMatt Macy error = -zfs_remove(ITOZ(dir), dname(dentry), cr, 0); 359eda14cbcSMatt Macy 360eda14cbcSMatt Macy /* 361eda14cbcSMatt Macy * For a CI FS we must invalidate the dentry to prevent the 362eda14cbcSMatt Macy * creation of negative entries. 363eda14cbcSMatt Macy */ 364eda14cbcSMatt Macy if (error == 0 && zfsvfs->z_case == ZFS_CASE_INSENSITIVE) 365eda14cbcSMatt Macy d_invalidate(dentry); 366eda14cbcSMatt Macy 367eda14cbcSMatt Macy spl_fstrans_unmark(cookie); 368eda14cbcSMatt Macy crfree(cr); 369eda14cbcSMatt Macy ASSERT3S(error, <=, 0); 370eda14cbcSMatt Macy 371eda14cbcSMatt Macy return (error); 372eda14cbcSMatt Macy } 373eda14cbcSMatt Macy 374eda14cbcSMatt Macy static int 375f9693befSMartin Matuska #ifdef HAVE_IOPS_MKDIR_USERNS 376f9693befSMartin Matuska zpl_mkdir(struct user_namespace *user_ns, struct inode *dir, 377f9693befSMartin Matuska struct dentry *dentry, umode_t mode) 378d411c1d6SMartin Matuska #elif defined(HAVE_IOPS_MKDIR_IDMAP) 379d411c1d6SMartin Matuska zpl_mkdir(struct mnt_idmap *user_ns, struct inode *dir, 380d411c1d6SMartin Matuska struct dentry *dentry, umode_t mode) 381f9693befSMartin Matuska #else 382eda14cbcSMatt Macy zpl_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) 383f9693befSMartin Matuska #endif 384eda14cbcSMatt Macy { 385eda14cbcSMatt Macy cred_t *cr = CRED(); 386eda14cbcSMatt Macy vattr_t *vap; 387eda14cbcSMatt Macy znode_t *zp; 388eda14cbcSMatt Macy int error; 389eda14cbcSMatt Macy fstrans_cookie_t cookie; 390d411c1d6SMartin Matuska #if !(defined(HAVE_IOPS_MKDIR_USERNS) || defined(HAVE_IOPS_MKDIR_IDMAP)) 391d411c1d6SMartin Matuska zidmap_t *user_ns = kcred->user_ns; 392dbd5678dSMartin Matuska #endif 393eda14cbcSMatt Macy 394*7a7741afSMartin Matuska if (is_nametoolong(dentry)) { 395*7a7741afSMartin Matuska return (-ENAMETOOLONG); 396*7a7741afSMartin Matuska } 397*7a7741afSMartin Matuska 398eda14cbcSMatt Macy crhold(cr); 399eda14cbcSMatt Macy vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP); 400dbd5678dSMartin Matuska zpl_vap_init(vap, dir, mode | S_IFDIR, cr, user_ns); 401eda14cbcSMatt Macy 402eda14cbcSMatt Macy cookie = spl_fstrans_mark(); 403dbd5678dSMartin Matuska error = -zfs_mkdir(ITOZ(dir), dname(dentry), vap, &zp, cr, 0, NULL, 404dbd5678dSMartin Matuska user_ns); 405eda14cbcSMatt Macy if (error == 0) { 406eda14cbcSMatt Macy error = zpl_xattr_security_init(ZTOI(zp), dir, &dentry->d_name); 407eda14cbcSMatt Macy if (error == 0) 408eda14cbcSMatt Macy error = zpl_init_acl(ZTOI(zp), dir); 409eda14cbcSMatt Macy 41016038816SMartin Matuska if (error) { 411eda14cbcSMatt Macy (void) zfs_rmdir(ITOZ(dir), dname(dentry), NULL, cr, 0); 41216038816SMartin Matuska remove_inode_hash(ZTOI(zp)); 41316038816SMartin Matuska iput(ZTOI(zp)); 41416038816SMartin Matuska } else { 41516038816SMartin Matuska d_instantiate(dentry, ZTOI(zp)); 41616038816SMartin Matuska } 417eda14cbcSMatt Macy } 418eda14cbcSMatt Macy 419eda14cbcSMatt Macy spl_fstrans_unmark(cookie); 420eda14cbcSMatt Macy kmem_free(vap, sizeof (vattr_t)); 421eda14cbcSMatt Macy crfree(cr); 422eda14cbcSMatt Macy ASSERT3S(error, <=, 0); 423eda14cbcSMatt Macy 424eda14cbcSMatt Macy return (error); 425eda14cbcSMatt Macy } 426eda14cbcSMatt Macy 427eda14cbcSMatt Macy static int 428eda14cbcSMatt Macy zpl_rmdir(struct inode *dir, struct dentry *dentry) 429eda14cbcSMatt Macy { 430eda14cbcSMatt Macy cred_t *cr = CRED(); 431eda14cbcSMatt Macy int error; 432eda14cbcSMatt Macy fstrans_cookie_t cookie; 433eda14cbcSMatt Macy zfsvfs_t *zfsvfs = dentry->d_sb->s_fs_info; 434eda14cbcSMatt Macy 435eda14cbcSMatt Macy crhold(cr); 436eda14cbcSMatt Macy cookie = spl_fstrans_mark(); 437eda14cbcSMatt Macy error = -zfs_rmdir(ITOZ(dir), dname(dentry), NULL, cr, 0); 438eda14cbcSMatt Macy 439eda14cbcSMatt Macy /* 440eda14cbcSMatt Macy * For a CI FS we must invalidate the dentry to prevent the 441eda14cbcSMatt Macy * creation of negative entries. 442eda14cbcSMatt Macy */ 443eda14cbcSMatt Macy if (error == 0 && zfsvfs->z_case == ZFS_CASE_INSENSITIVE) 444eda14cbcSMatt Macy d_invalidate(dentry); 445eda14cbcSMatt Macy 446eda14cbcSMatt Macy spl_fstrans_unmark(cookie); 447eda14cbcSMatt Macy crfree(cr); 448eda14cbcSMatt Macy ASSERT3S(error, <=, 0); 449eda14cbcSMatt Macy 450eda14cbcSMatt Macy return (error); 451eda14cbcSMatt Macy } 452eda14cbcSMatt Macy 453eda14cbcSMatt Macy static int 454f9693befSMartin Matuska #ifdef HAVE_USERNS_IOPS_GETATTR 455f9693befSMartin Matuska zpl_getattr_impl(struct user_namespace *user_ns, 456f9693befSMartin Matuska const struct path *path, struct kstat *stat, u32 request_mask, 457f9693befSMartin Matuska unsigned int query_flags) 458d411c1d6SMartin Matuska #elif defined(HAVE_IDMAP_IOPS_GETATTR) 459d411c1d6SMartin Matuska zpl_getattr_impl(struct mnt_idmap *user_ns, 460d411c1d6SMartin Matuska const struct path *path, struct kstat *stat, u32 request_mask, 461d411c1d6SMartin Matuska unsigned int query_flags) 462f9693befSMartin Matuska #else 463eda14cbcSMatt Macy zpl_getattr_impl(const struct path *path, struct kstat *stat, u32 request_mask, 464eda14cbcSMatt Macy unsigned int query_flags) 465f9693befSMartin Matuska #endif 466eda14cbcSMatt Macy { 467eda14cbcSMatt Macy int error; 468eda14cbcSMatt Macy fstrans_cookie_t cookie; 4692faf504dSMartin Matuska struct inode *ip = path->dentry->d_inode; 4702faf504dSMartin Matuska znode_t *zp __maybe_unused = ITOZ(ip); 471eda14cbcSMatt Macy 472eda14cbcSMatt Macy cookie = spl_fstrans_mark(); 473eda14cbcSMatt Macy 474eda14cbcSMatt Macy /* 4752faf504dSMartin Matuska * XXX query_flags currently ignored. 476eda14cbcSMatt Macy */ 477eda14cbcSMatt Macy 478abcdc1b9SMartin Matuska #ifdef HAVE_GENERIC_FILLATTR_IDMAP_REQMASK 479abcdc1b9SMartin Matuska error = -zfs_getattr_fast(user_ns, request_mask, ip, stat); 480abcdc1b9SMartin Matuska #elif (defined(HAVE_USERNS_IOPS_GETATTR) || defined(HAVE_IDMAP_IOPS_GETATTR)) 4812faf504dSMartin Matuska error = -zfs_getattr_fast(user_ns, ip, stat); 482f9693befSMartin Matuska #else 4832faf504dSMartin Matuska error = -zfs_getattr_fast(kcred->user_ns, ip, stat); 484f9693befSMartin Matuska #endif 4852faf504dSMartin Matuska 4862faf504dSMartin Matuska #ifdef STATX_BTIME 4872faf504dSMartin Matuska if (request_mask & STATX_BTIME) { 4882faf504dSMartin Matuska stat->btime = zp->z_btime; 4892faf504dSMartin Matuska stat->result_mask |= STATX_BTIME; 4902faf504dSMartin Matuska } 4912faf504dSMartin Matuska #endif 4922faf504dSMartin Matuska 4932faf504dSMartin Matuska #ifdef STATX_ATTR_IMMUTABLE 4942faf504dSMartin Matuska if (zp->z_pflags & ZFS_IMMUTABLE) 4952faf504dSMartin Matuska stat->attributes |= STATX_ATTR_IMMUTABLE; 4962faf504dSMartin Matuska stat->attributes_mask |= STATX_ATTR_IMMUTABLE; 4972faf504dSMartin Matuska #endif 4982faf504dSMartin Matuska 4992faf504dSMartin Matuska #ifdef STATX_ATTR_APPEND 5002faf504dSMartin Matuska if (zp->z_pflags & ZFS_APPENDONLY) 5012faf504dSMartin Matuska stat->attributes |= STATX_ATTR_APPEND; 5022faf504dSMartin Matuska stat->attributes_mask |= STATX_ATTR_APPEND; 5032faf504dSMartin Matuska #endif 5042faf504dSMartin Matuska 5052faf504dSMartin Matuska #ifdef STATX_ATTR_NODUMP 5062faf504dSMartin Matuska if (zp->z_pflags & ZFS_NODUMP) 5072faf504dSMartin Matuska stat->attributes |= STATX_ATTR_NODUMP; 5082faf504dSMartin Matuska stat->attributes_mask |= STATX_ATTR_NODUMP; 5092faf504dSMartin Matuska #endif 5102faf504dSMartin Matuska 511eda14cbcSMatt Macy spl_fstrans_unmark(cookie); 512eda14cbcSMatt Macy ASSERT3S(error, <=, 0); 513eda14cbcSMatt Macy 514eda14cbcSMatt Macy return (error); 515eda14cbcSMatt Macy } 516eda14cbcSMatt Macy ZPL_GETATTR_WRAPPER(zpl_getattr); 517eda14cbcSMatt Macy 518eda14cbcSMatt Macy static int 519d411c1d6SMartin Matuska #ifdef HAVE_USERNS_IOPS_SETATTR 520f9693befSMartin Matuska zpl_setattr(struct user_namespace *user_ns, struct dentry *dentry, 521f9693befSMartin Matuska struct iattr *ia) 522d411c1d6SMartin Matuska #elif defined(HAVE_IDMAP_IOPS_SETATTR) 523d411c1d6SMartin Matuska zpl_setattr(struct mnt_idmap *user_ns, struct dentry *dentry, 524d411c1d6SMartin Matuska struct iattr *ia) 525f9693befSMartin Matuska #else 526eda14cbcSMatt Macy zpl_setattr(struct dentry *dentry, struct iattr *ia) 527f9693befSMartin Matuska #endif 528eda14cbcSMatt Macy { 529eda14cbcSMatt Macy struct inode *ip = dentry->d_inode; 530eda14cbcSMatt Macy cred_t *cr = CRED(); 531eda14cbcSMatt Macy vattr_t *vap; 532eda14cbcSMatt Macy int error; 533eda14cbcSMatt Macy fstrans_cookie_t cookie; 534eda14cbcSMatt Macy 535dbd5678dSMartin Matuska #ifdef HAVE_SETATTR_PREPARE_USERNS 536dbd5678dSMartin Matuska error = zpl_setattr_prepare(user_ns, dentry, ia); 537d411c1d6SMartin Matuska #elif defined(HAVE_SETATTR_PREPARE_IDMAP) 538d411c1d6SMartin Matuska error = zpl_setattr_prepare(user_ns, dentry, ia); 539dbd5678dSMartin Matuska #else 540d411c1d6SMartin Matuska error = zpl_setattr_prepare(zfs_init_idmap, dentry, ia); 541dbd5678dSMartin Matuska #endif 542eda14cbcSMatt Macy if (error) 543eda14cbcSMatt Macy return (error); 544eda14cbcSMatt Macy 545eda14cbcSMatt Macy crhold(cr); 546eda14cbcSMatt Macy vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP); 547eda14cbcSMatt Macy vap->va_mask = ia->ia_valid & ATTR_IATTR_MASK; 548eda14cbcSMatt Macy vap->va_mode = ia->ia_mode; 549dbd5678dSMartin Matuska if (ia->ia_valid & ATTR_UID) 550dbd5678dSMartin Matuska #ifdef HAVE_IATTR_VFSID 551dbd5678dSMartin Matuska vap->va_uid = zfs_vfsuid_to_uid(user_ns, zfs_i_user_ns(ip), 552dbd5678dSMartin Matuska __vfsuid_val(ia->ia_vfsuid)); 553dbd5678dSMartin Matuska #else 554eda14cbcSMatt Macy vap->va_uid = KUID_TO_SUID(ia->ia_uid); 555dbd5678dSMartin Matuska #endif 556dbd5678dSMartin Matuska if (ia->ia_valid & ATTR_GID) 557dbd5678dSMartin Matuska #ifdef HAVE_IATTR_VFSID 558dbd5678dSMartin Matuska vap->va_gid = zfs_vfsgid_to_gid(user_ns, zfs_i_user_ns(ip), 559dbd5678dSMartin Matuska __vfsgid_val(ia->ia_vfsgid)); 560dbd5678dSMartin Matuska #else 561eda14cbcSMatt Macy vap->va_gid = KGID_TO_SGID(ia->ia_gid); 562dbd5678dSMartin Matuska #endif 563eda14cbcSMatt Macy vap->va_size = ia->ia_size; 564eda14cbcSMatt Macy vap->va_atime = ia->ia_atime; 565eda14cbcSMatt Macy vap->va_mtime = ia->ia_mtime; 566eda14cbcSMatt Macy vap->va_ctime = ia->ia_ctime; 567eda14cbcSMatt Macy 568eda14cbcSMatt Macy if (vap->va_mask & ATTR_ATIME) 569b356da80SMartin Matuska zpl_inode_set_atime_to_ts(ip, 570b356da80SMartin Matuska zpl_inode_timestamp_truncate(ia->ia_atime, ip)); 571eda14cbcSMatt Macy 572eda14cbcSMatt Macy cookie = spl_fstrans_mark(); 573d411c1d6SMartin Matuska #ifdef HAVE_USERNS_IOPS_SETATTR 574d411c1d6SMartin Matuska error = -zfs_setattr(ITOZ(ip), vap, 0, cr, user_ns); 575d411c1d6SMartin Matuska #elif defined(HAVE_IDMAP_IOPS_SETATTR) 576dbd5678dSMartin Matuska error = -zfs_setattr(ITOZ(ip), vap, 0, cr, user_ns); 577dbd5678dSMartin Matuska #else 578d411c1d6SMartin Matuska error = -zfs_setattr(ITOZ(ip), vap, 0, cr, zfs_init_idmap); 579dbd5678dSMartin Matuska #endif 580eda14cbcSMatt Macy if (!error && (ia->ia_valid & ATTR_MODE)) 581eda14cbcSMatt Macy error = zpl_chmod_acl(ip); 582eda14cbcSMatt Macy 583eda14cbcSMatt Macy spl_fstrans_unmark(cookie); 584eda14cbcSMatt Macy kmem_free(vap, sizeof (vattr_t)); 585eda14cbcSMatt Macy crfree(cr); 586eda14cbcSMatt Macy ASSERT3S(error, <=, 0); 587eda14cbcSMatt Macy 588eda14cbcSMatt Macy return (error); 589eda14cbcSMatt Macy } 590eda14cbcSMatt Macy 591eda14cbcSMatt Macy static int 592f9693befSMartin Matuska #ifdef HAVE_IOPS_RENAME_USERNS 593f9693befSMartin Matuska zpl_rename2(struct user_namespace *user_ns, struct inode *sdip, 594f9693befSMartin Matuska struct dentry *sdentry, struct inode *tdip, struct dentry *tdentry, 595dbd5678dSMartin Matuska unsigned int rflags) 596d411c1d6SMartin Matuska #elif defined(HAVE_IOPS_RENAME_IDMAP) 597d411c1d6SMartin Matuska zpl_rename2(struct mnt_idmap *user_ns, struct inode *sdip, 598d411c1d6SMartin Matuska struct dentry *sdentry, struct inode *tdip, struct dentry *tdentry, 599d411c1d6SMartin Matuska unsigned int rflags) 600f9693befSMartin Matuska #else 601eda14cbcSMatt Macy zpl_rename2(struct inode *sdip, struct dentry *sdentry, 602dbd5678dSMartin Matuska struct inode *tdip, struct dentry *tdentry, unsigned int rflags) 603f9693befSMartin Matuska #endif 604eda14cbcSMatt Macy { 605eda14cbcSMatt Macy cred_t *cr = CRED(); 606dbd5678dSMartin Matuska vattr_t *wo_vap = NULL; 607eda14cbcSMatt Macy int error; 608eda14cbcSMatt Macy fstrans_cookie_t cookie; 609d411c1d6SMartin Matuska #if !(defined(HAVE_IOPS_RENAME_USERNS) || defined(HAVE_IOPS_RENAME_IDMAP)) 610d411c1d6SMartin Matuska zidmap_t *user_ns = kcred->user_ns; 611dbd5678dSMartin Matuska #endif 612eda14cbcSMatt Macy 613*7a7741afSMartin Matuska if (is_nametoolong(tdentry)) { 614*7a7741afSMartin Matuska return (-ENAMETOOLONG); 615*7a7741afSMartin Matuska } 616*7a7741afSMartin Matuska 617eda14cbcSMatt Macy crhold(cr); 618dbd5678dSMartin Matuska if (rflags & RENAME_WHITEOUT) { 619dbd5678dSMartin Matuska wo_vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP); 620dbd5678dSMartin Matuska zpl_vap_init(wo_vap, sdip, S_IFCHR, cr, user_ns); 621dbd5678dSMartin Matuska wo_vap->va_rdev = makedevice(0, 0); 622dbd5678dSMartin Matuska } 623dbd5678dSMartin Matuska 624eda14cbcSMatt Macy cookie = spl_fstrans_mark(); 625eda14cbcSMatt Macy error = -zfs_rename(ITOZ(sdip), dname(sdentry), ITOZ(tdip), 626dbd5678dSMartin Matuska dname(tdentry), cr, 0, rflags, wo_vap, user_ns); 627eda14cbcSMatt Macy spl_fstrans_unmark(cookie); 628dbd5678dSMartin Matuska if (wo_vap) 629dbd5678dSMartin Matuska kmem_free(wo_vap, sizeof (vattr_t)); 630eda14cbcSMatt Macy crfree(cr); 631eda14cbcSMatt Macy ASSERT3S(error, <=, 0); 632eda14cbcSMatt Macy 633eda14cbcSMatt Macy return (error); 634eda14cbcSMatt Macy } 635eda14cbcSMatt Macy 636dbd5678dSMartin Matuska #if !defined(HAVE_IOPS_RENAME_USERNS) && \ 637dbd5678dSMartin Matuska !defined(HAVE_RENAME_WANTS_FLAGS) && \ 638d411c1d6SMartin Matuska !defined(HAVE_IOPS_RENAME_IDMAP) 639eda14cbcSMatt Macy static int 640eda14cbcSMatt Macy zpl_rename(struct inode *sdip, struct dentry *sdentry, 641eda14cbcSMatt Macy struct inode *tdip, struct dentry *tdentry) 642eda14cbcSMatt Macy { 643eda14cbcSMatt Macy return (zpl_rename2(sdip, sdentry, tdip, tdentry, 0)); 644eda14cbcSMatt Macy } 645eda14cbcSMatt Macy #endif 646eda14cbcSMatt Macy 647eda14cbcSMatt Macy static int 648f9693befSMartin Matuska #ifdef HAVE_IOPS_SYMLINK_USERNS 649f9693befSMartin Matuska zpl_symlink(struct user_namespace *user_ns, struct inode *dir, 650f9693befSMartin Matuska struct dentry *dentry, const char *name) 651d411c1d6SMartin Matuska #elif defined(HAVE_IOPS_SYMLINK_IDMAP) 652d411c1d6SMartin Matuska zpl_symlink(struct mnt_idmap *user_ns, struct inode *dir, 653d411c1d6SMartin Matuska struct dentry *dentry, const char *name) 654f9693befSMartin Matuska #else 655eda14cbcSMatt Macy zpl_symlink(struct inode *dir, struct dentry *dentry, const char *name) 656f9693befSMartin Matuska #endif 657eda14cbcSMatt Macy { 658eda14cbcSMatt Macy cred_t *cr = CRED(); 659eda14cbcSMatt Macy vattr_t *vap; 660eda14cbcSMatt Macy znode_t *zp; 661eda14cbcSMatt Macy int error; 662eda14cbcSMatt Macy fstrans_cookie_t cookie; 663d411c1d6SMartin Matuska #if !(defined(HAVE_IOPS_SYMLINK_USERNS) || defined(HAVE_IOPS_SYMLINK_IDMAP)) 664d411c1d6SMartin Matuska zidmap_t *user_ns = kcred->user_ns; 665dbd5678dSMartin Matuska #endif 666eda14cbcSMatt Macy 667*7a7741afSMartin Matuska if (is_nametoolong(dentry)) { 668*7a7741afSMartin Matuska return (-ENAMETOOLONG); 669*7a7741afSMartin Matuska } 670*7a7741afSMartin Matuska 671eda14cbcSMatt Macy crhold(cr); 672eda14cbcSMatt Macy vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP); 673dbd5678dSMartin Matuska zpl_vap_init(vap, dir, S_IFLNK | S_IRWXUGO, cr, user_ns); 674eda14cbcSMatt Macy 675eda14cbcSMatt Macy cookie = spl_fstrans_mark(); 676eda14cbcSMatt Macy error = -zfs_symlink(ITOZ(dir), dname(dentry), vap, 677dbd5678dSMartin Matuska (char *)name, &zp, cr, 0, user_ns); 678eda14cbcSMatt Macy if (error == 0) { 679eda14cbcSMatt Macy error = zpl_xattr_security_init(ZTOI(zp), dir, &dentry->d_name); 68016038816SMartin Matuska if (error) { 681eda14cbcSMatt Macy (void) zfs_remove(ITOZ(dir), dname(dentry), cr, 0); 68216038816SMartin Matuska remove_inode_hash(ZTOI(zp)); 68316038816SMartin Matuska iput(ZTOI(zp)); 68416038816SMartin Matuska } else { 68516038816SMartin Matuska d_instantiate(dentry, ZTOI(zp)); 68616038816SMartin Matuska } 687eda14cbcSMatt Macy } 688eda14cbcSMatt Macy 689eda14cbcSMatt Macy spl_fstrans_unmark(cookie); 690eda14cbcSMatt Macy kmem_free(vap, sizeof (vattr_t)); 691eda14cbcSMatt Macy crfree(cr); 692eda14cbcSMatt Macy ASSERT3S(error, <=, 0); 693eda14cbcSMatt Macy 694eda14cbcSMatt Macy return (error); 695eda14cbcSMatt Macy } 696eda14cbcSMatt Macy 697eda14cbcSMatt Macy static void 698eda14cbcSMatt Macy zpl_put_link(void *ptr) 699eda14cbcSMatt Macy { 700eda14cbcSMatt Macy kmem_free(ptr, MAXPATHLEN); 701eda14cbcSMatt Macy } 702eda14cbcSMatt Macy 703eda14cbcSMatt Macy static int 704eda14cbcSMatt Macy zpl_get_link_common(struct dentry *dentry, struct inode *ip, char **link) 705eda14cbcSMatt Macy { 706eda14cbcSMatt Macy fstrans_cookie_t cookie; 707eda14cbcSMatt Macy cred_t *cr = CRED(); 708eda14cbcSMatt Macy int error; 709eda14cbcSMatt Macy 710eda14cbcSMatt Macy crhold(cr); 711eda14cbcSMatt Macy *link = NULL; 7127877fdebSMatt Macy 7137877fdebSMatt Macy struct iovec iov; 714eda14cbcSMatt Macy iov.iov_len = MAXPATHLEN; 715eda14cbcSMatt Macy iov.iov_base = kmem_zalloc(MAXPATHLEN, KM_SLEEP); 716eda14cbcSMatt Macy 717184c1b94SMartin Matuska zfs_uio_t uio; 718184c1b94SMartin Matuska zfs_uio_iovec_init(&uio, &iov, 1, 0, UIO_SYSSPACE, MAXPATHLEN - 1, 0); 719eda14cbcSMatt Macy 720eda14cbcSMatt Macy cookie = spl_fstrans_mark(); 721eda14cbcSMatt Macy error = -zfs_readlink(ip, &uio, cr); 722eda14cbcSMatt Macy spl_fstrans_unmark(cookie); 723eda14cbcSMatt Macy crfree(cr); 724eda14cbcSMatt Macy 725eda14cbcSMatt Macy if (error) 726eda14cbcSMatt Macy kmem_free(iov.iov_base, MAXPATHLEN); 727eda14cbcSMatt Macy else 728eda14cbcSMatt Macy *link = iov.iov_base; 729eda14cbcSMatt Macy 730eda14cbcSMatt Macy return (error); 731eda14cbcSMatt Macy } 732eda14cbcSMatt Macy 733eda14cbcSMatt Macy static const char * 734eda14cbcSMatt Macy zpl_get_link(struct dentry *dentry, struct inode *inode, 735eda14cbcSMatt Macy struct delayed_call *done) 736eda14cbcSMatt Macy { 737eda14cbcSMatt Macy char *link = NULL; 738eda14cbcSMatt Macy int error; 739eda14cbcSMatt Macy 740eda14cbcSMatt Macy if (!dentry) 741eda14cbcSMatt Macy return (ERR_PTR(-ECHILD)); 742eda14cbcSMatt Macy 743eda14cbcSMatt Macy error = zpl_get_link_common(dentry, inode, &link); 744eda14cbcSMatt Macy if (error) 745eda14cbcSMatt Macy return (ERR_PTR(error)); 746eda14cbcSMatt Macy 747eda14cbcSMatt Macy set_delayed_call(done, zpl_put_link, link); 748eda14cbcSMatt Macy 749eda14cbcSMatt Macy return (link); 750eda14cbcSMatt Macy } 751eda14cbcSMatt Macy 752eda14cbcSMatt Macy static int 753eda14cbcSMatt Macy zpl_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) 754eda14cbcSMatt Macy { 755eda14cbcSMatt Macy cred_t *cr = CRED(); 756eda14cbcSMatt Macy struct inode *ip = old_dentry->d_inode; 757eda14cbcSMatt Macy int error; 758eda14cbcSMatt Macy fstrans_cookie_t cookie; 759eda14cbcSMatt Macy 760*7a7741afSMartin Matuska if (is_nametoolong(dentry)) { 761*7a7741afSMartin Matuska return (-ENAMETOOLONG); 762*7a7741afSMartin Matuska } 763*7a7741afSMartin Matuska 764eda14cbcSMatt Macy if (ip->i_nlink >= ZFS_LINK_MAX) 765eda14cbcSMatt Macy return (-EMLINK); 766eda14cbcSMatt Macy 767eda14cbcSMatt Macy crhold(cr); 768abcdc1b9SMartin Matuska zpl_inode_set_ctime_to_ts(ip, current_time(ip)); 769f9693befSMartin Matuska /* Must have an existing ref, so igrab() cannot return NULL */ 770f9693befSMartin Matuska VERIFY3P(igrab(ip), !=, NULL); 771eda14cbcSMatt Macy 772eda14cbcSMatt Macy cookie = spl_fstrans_mark(); 773eda14cbcSMatt Macy error = -zfs_link(ITOZ(dir), ITOZ(ip), dname(dentry), cr, 0); 774eda14cbcSMatt Macy if (error) { 775eda14cbcSMatt Macy iput(ip); 776eda14cbcSMatt Macy goto out; 777eda14cbcSMatt Macy } 778eda14cbcSMatt Macy 779eda14cbcSMatt Macy d_instantiate(dentry, ip); 780eda14cbcSMatt Macy out: 781eda14cbcSMatt Macy spl_fstrans_unmark(cookie); 782eda14cbcSMatt Macy crfree(cr); 783eda14cbcSMatt Macy ASSERT3S(error, <=, 0); 784eda14cbcSMatt Macy 785eda14cbcSMatt Macy return (error); 786eda14cbcSMatt Macy } 787eda14cbcSMatt Macy 788eda14cbcSMatt Macy const struct inode_operations zpl_inode_operations = { 789eda14cbcSMatt Macy .setattr = zpl_setattr, 790eda14cbcSMatt Macy .getattr = zpl_getattr, 791eda14cbcSMatt Macy .listxattr = zpl_xattr_list, 792eda14cbcSMatt Macy #if defined(CONFIG_FS_POSIX_ACL) 793eda14cbcSMatt Macy .set_acl = zpl_set_acl, 79415f0b8c3SMartin Matuska #if defined(HAVE_GET_INODE_ACL) 79515f0b8c3SMartin Matuska .get_inode_acl = zpl_get_acl, 79615f0b8c3SMartin Matuska #else 797eda14cbcSMatt Macy .get_acl = zpl_get_acl, 79815f0b8c3SMartin Matuska #endif /* HAVE_GET_INODE_ACL */ 799eda14cbcSMatt Macy #endif /* CONFIG_FS_POSIX_ACL */ 800eda14cbcSMatt Macy }; 801eda14cbcSMatt Macy 802eda14cbcSMatt Macy const struct inode_operations zpl_dir_inode_operations = { 803eda14cbcSMatt Macy .create = zpl_create, 804eda14cbcSMatt Macy .lookup = zpl_lookup, 805eda14cbcSMatt Macy .link = zpl_link, 806eda14cbcSMatt Macy .unlink = zpl_unlink, 807eda14cbcSMatt Macy .symlink = zpl_symlink, 808eda14cbcSMatt Macy .mkdir = zpl_mkdir, 809eda14cbcSMatt Macy .rmdir = zpl_rmdir, 810eda14cbcSMatt Macy .mknod = zpl_mknod, 811*7a7741afSMartin Matuska #if defined(HAVE_RENAME_WANTS_FLAGS) || defined(HAVE_IOPS_RENAME_USERNS) 812eda14cbcSMatt Macy .rename = zpl_rename2, 813d411c1d6SMartin Matuska #elif defined(HAVE_IOPS_RENAME_IDMAP) 814d411c1d6SMartin Matuska .rename = zpl_rename2, 815eda14cbcSMatt Macy #else 816eda14cbcSMatt Macy .rename = zpl_rename, 817eda14cbcSMatt Macy #endif 818eda14cbcSMatt Macy .tmpfile = zpl_tmpfile, 819eda14cbcSMatt Macy .setattr = zpl_setattr, 820eda14cbcSMatt Macy .getattr = zpl_getattr, 821eda14cbcSMatt Macy .listxattr = zpl_xattr_list, 822eda14cbcSMatt Macy #if defined(CONFIG_FS_POSIX_ACL) 823eda14cbcSMatt Macy .set_acl = zpl_set_acl, 82415f0b8c3SMartin Matuska #if defined(HAVE_GET_INODE_ACL) 82515f0b8c3SMartin Matuska .get_inode_acl = zpl_get_acl, 82615f0b8c3SMartin Matuska #else 827eda14cbcSMatt Macy .get_acl = zpl_get_acl, 82815f0b8c3SMartin Matuska #endif /* HAVE_GET_INODE_ACL */ 829eda14cbcSMatt Macy #endif /* CONFIG_FS_POSIX_ACL */ 830eda14cbcSMatt Macy }; 831eda14cbcSMatt Macy 832eda14cbcSMatt Macy const struct inode_operations zpl_symlink_inode_operations = { 833eda14cbcSMatt Macy .get_link = zpl_get_link, 834eda14cbcSMatt Macy .setattr = zpl_setattr, 835eda14cbcSMatt Macy .getattr = zpl_getattr, 836eda14cbcSMatt Macy .listxattr = zpl_xattr_list, 837eda14cbcSMatt Macy }; 838eda14cbcSMatt Macy 839eda14cbcSMatt Macy const struct inode_operations zpl_special_inode_operations = { 840eda14cbcSMatt Macy .setattr = zpl_setattr, 841eda14cbcSMatt Macy .getattr = zpl_getattr, 842eda14cbcSMatt Macy .listxattr = zpl_xattr_list, 843eda14cbcSMatt Macy #if defined(CONFIG_FS_POSIX_ACL) 844eda14cbcSMatt Macy .set_acl = zpl_set_acl, 84515f0b8c3SMartin Matuska #if defined(HAVE_GET_INODE_ACL) 84615f0b8c3SMartin Matuska .get_inode_acl = zpl_get_acl, 84715f0b8c3SMartin Matuska #else 848eda14cbcSMatt Macy .get_acl = zpl_get_acl, 84915f0b8c3SMartin Matuska #endif /* HAVE_GET_INODE_ACL */ 850eda14cbcSMatt Macy #endif /* CONFIG_FS_POSIX_ACL */ 851eda14cbcSMatt Macy }; 852