Path: blob/main/sys/contrib/openzfs/module/os/linux/zfs/zpl_inode.c
48774 views
// SPDX-License-Identifier: CDDL-1.01/*2* CDDL HEADER START3*4* The contents of this file are subject to the terms of the5* Common Development and Distribution License (the "License").6* You may not use this file except in compliance with the License.7*8* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE9* or https://opensource.org/licenses/CDDL-1.0.10* See the License for the specific language governing permissions11* and limitations under the License.12*13* When distributing Covered Code, include this CDDL HEADER in each14* file and include the License file at usr/src/OPENSOLARIS.LICENSE.15* If applicable, add the following below this CDDL HEADER, with the16* fields enclosed by brackets "[]" replaced with your own identifying17* information: Portions Copyright [yyyy] [name of copyright owner]18*19* CDDL HEADER END20*/21/*22* Copyright (c) 2011, Lawrence Livermore National Security, LLC.23* Copyright (c) 2015 by Chunwei Chen. All rights reserved.24* Copyright (c) 2025, Rob Norris <[email protected]>25*/262728#include <sys/sysmacros.h>29#include <sys/zfs_ctldir.h>30#include <sys/zfs_vfsops.h>31#include <sys/zfs_vnops.h>32#include <sys/zfs_znode.h>33#include <sys/dmu_objset.h>34#include <sys/spa_impl.h>35#include <sys/vfs.h>36#include <sys/zpl.h>37#include <sys/file.h>3839static struct dentry *40zpl_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)41{42cred_t *cr = CRED();43struct inode *ip;44znode_t *zp;45int error;46fstrans_cookie_t cookie;47pathname_t *ppn = NULL;48pathname_t pn;49int zfs_flags = 0;50zfsvfs_t *zfsvfs = dentry->d_sb->s_fs_info;51dsl_dataset_t *ds = dmu_objset_ds(zfsvfs->z_os);52size_t dlen = dlen(dentry);5354/*55* If z_longname is disabled, disallow create or rename of names56* longer than ZAP_MAXNAMELEN.57*58* This is needed in cases where longname was enabled first and some59* files/dirs with names > ZAP_MAXNAMELEN were created. And later60* longname was disabled. In such a case allow access to existing61* longnames. But disallow creation newer longnamed entities.62*/63if (!zfsvfs->z_longname && (dlen >= ZAP_MAXNAMELEN)) {64/*65* If this is for create or rename fail it.66*/67if (!dsl_dataset_feature_is_active(ds, SPA_FEATURE_LONGNAME) ||68(flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET)))69return (ERR_PTR(-ENAMETOOLONG));70}71if (dlen >= ZAP_MAXNAMELEN_NEW) {72return (ERR_PTR(-ENAMETOOLONG));73}7475crhold(cr);76cookie = spl_fstrans_mark();7778/* If we are a case insensitive fs, we need the real name */79if (zfsvfs->z_case == ZFS_CASE_INSENSITIVE) {80zfs_flags = FIGNORECASE;81pn_alloc(&pn);82ppn = &pn;83}8485error = -zfs_lookup(ITOZ(dir), dname(dentry), &zp,86zfs_flags, cr, NULL, ppn);87spl_fstrans_unmark(cookie);88ASSERT3S(error, <=, 0);89crfree(cr);9091spin_lock(&dentry->d_lock);92dentry->d_time = jiffies;93spin_unlock(&dentry->d_lock);9495if (error) {96/*97* If we have a case sensitive fs, we do not want to98* insert negative entries, so return NULL for ENOENT.99* Fall through if the error is not ENOENT. Also free memory.100*/101if (ppn) {102pn_free(ppn);103if (error == -ENOENT)104return (NULL);105}106107if (error == -ENOENT)108return (d_splice_alias(NULL, dentry));109else110return (ERR_PTR(error));111}112ip = ZTOI(zp);113114/*115* If we are case insensitive, call the correct function116* to install the name.117*/118if (ppn) {119struct dentry *new_dentry;120struct qstr ci_name;121122if (strcmp(dname(dentry), pn.pn_buf) == 0) {123new_dentry = d_splice_alias(ip, dentry);124} else {125ci_name.name = pn.pn_buf;126ci_name.len = strlen(pn.pn_buf);127new_dentry = d_add_ci(dentry, ip, &ci_name);128}129pn_free(ppn);130return (new_dentry);131} else {132return (d_splice_alias(ip, dentry));133}134}135136void137zpl_vap_init(vattr_t *vap, struct inode *dir, umode_t mode, cred_t *cr,138zidmap_t *mnt_ns)139{140vap->va_mask = ATTR_MODE;141vap->va_mode = mode;142143vap->va_uid = zfs_vfsuid_to_uid(mnt_ns,144zfs_i_user_ns(dir), crgetuid(cr));145146if (dir->i_mode & S_ISGID) {147vap->va_gid = KGID_TO_SGID(dir->i_gid);148if (S_ISDIR(mode))149vap->va_mode |= S_ISGID;150} else {151vap->va_gid = zfs_vfsgid_to_gid(mnt_ns,152zfs_i_user_ns(dir), crgetgid(cr));153}154}155156static inline bool157is_nametoolong(struct dentry *dentry)158{159zfsvfs_t *zfsvfs = dentry->d_sb->s_fs_info;160size_t dlen = dlen(dentry);161162return ((!zfsvfs->z_longname && dlen >= ZAP_MAXNAMELEN) ||163dlen >= ZAP_MAXNAMELEN_NEW);164}165166static int167#ifdef HAVE_IOPS_CREATE_USERNS168zpl_create(struct user_namespace *user_ns, struct inode *dir,169struct dentry *dentry, umode_t mode, bool flag)170#elif defined(HAVE_IOPS_CREATE_IDMAP)171zpl_create(struct mnt_idmap *user_ns, struct inode *dir,172struct dentry *dentry, umode_t mode, bool flag)173#else174zpl_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool flag)175#endif176{177cred_t *cr = CRED();178znode_t *zp;179vattr_t *vap;180int error;181fstrans_cookie_t cookie;182#if !(defined(HAVE_IOPS_CREATE_USERNS) || defined(HAVE_IOPS_CREATE_IDMAP))183zidmap_t *user_ns = kcred->user_ns;184#endif185186if (is_nametoolong(dentry)) {187return (-ENAMETOOLONG);188}189190crhold(cr);191vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP);192zpl_vap_init(vap, dir, mode, cr, user_ns);193194cookie = spl_fstrans_mark();195error = -zfs_create(ITOZ(dir), dname(dentry), vap, 0,196mode, &zp, cr, 0, NULL, user_ns);197if (error == 0) {198error = zpl_xattr_security_init(ZTOI(zp), dir, &dentry->d_name);199if (error == 0)200error = zpl_init_acl(ZTOI(zp), dir);201202if (error) {203(void) zfs_remove(ITOZ(dir), dname(dentry), cr, 0);204remove_inode_hash(ZTOI(zp));205iput(ZTOI(zp));206} else {207d_instantiate(dentry, ZTOI(zp));208}209}210211spl_fstrans_unmark(cookie);212kmem_free(vap, sizeof (vattr_t));213crfree(cr);214ASSERT3S(error, <=, 0);215216return (error);217}218219static int220#ifdef HAVE_IOPS_MKNOD_USERNS221zpl_mknod(struct user_namespace *user_ns, struct inode *dir,222struct dentry *dentry, umode_t mode,223#elif defined(HAVE_IOPS_MKNOD_IDMAP)224zpl_mknod(struct mnt_idmap *user_ns, struct inode *dir,225struct dentry *dentry, umode_t mode,226#else227zpl_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,228#endif229dev_t rdev)230{231cred_t *cr = CRED();232znode_t *zp;233vattr_t *vap;234int error;235fstrans_cookie_t cookie;236#if !(defined(HAVE_IOPS_MKNOD_USERNS) || defined(HAVE_IOPS_MKNOD_IDMAP))237zidmap_t *user_ns = kcred->user_ns;238#endif239240if (is_nametoolong(dentry)) {241return (-ENAMETOOLONG);242}243244/*245* We currently expect Linux to supply rdev=0 for all sockets246* and fifos, but we want to know if this behavior ever changes.247*/248if (S_ISSOCK(mode) || S_ISFIFO(mode))249ASSERT0(rdev);250251crhold(cr);252vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP);253zpl_vap_init(vap, dir, mode, cr, user_ns);254vap->va_rdev = rdev;255256cookie = spl_fstrans_mark();257error = -zfs_create(ITOZ(dir), dname(dentry), vap, 0,258mode, &zp, cr, 0, NULL, user_ns);259if (error == 0) {260error = zpl_xattr_security_init(ZTOI(zp), dir, &dentry->d_name);261if (error == 0)262error = zpl_init_acl(ZTOI(zp), dir);263264if (error) {265(void) zfs_remove(ITOZ(dir), dname(dentry), cr, 0);266remove_inode_hash(ZTOI(zp));267iput(ZTOI(zp));268} else {269d_instantiate(dentry, ZTOI(zp));270}271}272273spl_fstrans_unmark(cookie);274kmem_free(vap, sizeof (vattr_t));275crfree(cr);276ASSERT3S(error, <=, 0);277278return (error);279}280281static int282#ifdef HAVE_TMPFILE_IDMAP283zpl_tmpfile(struct mnt_idmap *userns, struct inode *dir,284struct file *file, umode_t mode)285#elif !defined(HAVE_TMPFILE_DENTRY)286zpl_tmpfile(struct user_namespace *userns, struct inode *dir,287struct file *file, umode_t mode)288#else289#ifdef HAVE_TMPFILE_USERNS290zpl_tmpfile(struct user_namespace *userns, struct inode *dir,291struct dentry *dentry, umode_t mode)292#else293zpl_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)294#endif295#endif296{297cred_t *cr = CRED();298struct inode *ip;299vattr_t *vap;300int error;301fstrans_cookie_t cookie;302#if !(defined(HAVE_TMPFILE_USERNS) || defined(HAVE_TMPFILE_IDMAP))303zidmap_t *userns = kcred->user_ns;304#endif305306crhold(cr);307vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP);308/*309* The VFS does not apply the umask, therefore it is applied here310* when POSIX ACLs are not enabled.311*/312if (!IS_POSIXACL(dir))313mode &= ~current_umask();314zpl_vap_init(vap, dir, mode, cr, userns);315316cookie = spl_fstrans_mark();317error = -zfs_tmpfile(dir, vap, 0, mode, &ip, cr, 0, NULL, userns);318if (error == 0) {319/* d_tmpfile will do drop_nlink, so we should set it first */320set_nlink(ip, 1);321#ifndef HAVE_TMPFILE_DENTRY322d_tmpfile(file, ip);323324error = zpl_xattr_security_init(ip, dir,325&file->f_path.dentry->d_name);326#else327d_tmpfile(dentry, ip);328329error = zpl_xattr_security_init(ip, dir, &dentry->d_name);330#endif331if (error == 0)332error = zpl_init_acl(ip, dir);333#ifndef HAVE_TMPFILE_DENTRY334error = finish_open_simple(file, error);335#endif336/*337* don't need to handle error here, file is already in338* unlinked set.339*/340}341342spl_fstrans_unmark(cookie);343kmem_free(vap, sizeof (vattr_t));344crfree(cr);345ASSERT3S(error, <=, 0);346347return (error);348}349350static int351zpl_unlink(struct inode *dir, struct dentry *dentry)352{353cred_t *cr = CRED();354int error;355fstrans_cookie_t cookie;356zfsvfs_t *zfsvfs = dentry->d_sb->s_fs_info;357358crhold(cr);359cookie = spl_fstrans_mark();360error = -zfs_remove(ITOZ(dir), dname(dentry), cr, 0);361362/*363* For a CI FS we must invalidate the dentry to prevent the364* creation of negative entries.365*/366if (error == 0 && zfsvfs->z_case == ZFS_CASE_INSENSITIVE)367d_invalidate(dentry);368369spl_fstrans_unmark(cookie);370crfree(cr);371ASSERT3S(error, <=, 0);372373return (error);374}375376#if defined(HAVE_IOPS_MKDIR_USERNS)377static int378zpl_mkdir(struct user_namespace *user_ns, struct inode *dir,379struct dentry *dentry, umode_t mode)380#elif defined(HAVE_IOPS_MKDIR_IDMAP)381static int382zpl_mkdir(struct mnt_idmap *user_ns, struct inode *dir,383struct dentry *dentry, umode_t mode)384#elif defined(HAVE_IOPS_MKDIR_DENTRY)385static struct dentry *386zpl_mkdir(struct mnt_idmap *user_ns, struct inode *dir,387struct dentry *dentry, umode_t mode)388#else389static int390zpl_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)391#endif392{393cred_t *cr = CRED();394vattr_t *vap;395znode_t *zp;396int error;397fstrans_cookie_t cookie;398#if !(defined(HAVE_IOPS_MKDIR_USERNS) || \399defined(HAVE_IOPS_MKDIR_IDMAP) || defined(HAVE_IOPS_MKDIR_DENTRY))400zidmap_t *user_ns = kcred->user_ns;401#endif402403if (is_nametoolong(dentry)) {404error = -ENAMETOOLONG;405goto err;406}407408crhold(cr);409vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP);410zpl_vap_init(vap, dir, mode | S_IFDIR, cr, user_ns);411412cookie = spl_fstrans_mark();413error = -zfs_mkdir(ITOZ(dir), dname(dentry), vap, &zp, cr, 0, NULL,414user_ns);415if (error == 0) {416error = zpl_xattr_security_init(ZTOI(zp), dir, &dentry->d_name);417if (error == 0)418error = zpl_init_acl(ZTOI(zp), dir);419420if (error) {421(void) zfs_rmdir(ITOZ(dir), dname(dentry), NULL, cr, 0);422remove_inode_hash(ZTOI(zp));423iput(ZTOI(zp));424} else {425d_instantiate(dentry, ZTOI(zp));426}427}428429spl_fstrans_unmark(cookie);430kmem_free(vap, sizeof (vattr_t));431crfree(cr);432433err:434ASSERT3S(error, <=, 0);435#if defined(HAVE_IOPS_MKDIR_DENTRY)436return (error != 0 ? ERR_PTR(error) : NULL);437#else438return (error);439#endif440}441442static int443zpl_rmdir(struct inode *dir, struct dentry *dentry)444{445cred_t *cr = CRED();446int error;447fstrans_cookie_t cookie;448zfsvfs_t *zfsvfs = dentry->d_sb->s_fs_info;449450crhold(cr);451cookie = spl_fstrans_mark();452error = -zfs_rmdir(ITOZ(dir), dname(dentry), NULL, cr, 0);453454/*455* For a CI FS we must invalidate the dentry to prevent the456* creation of negative entries.457*/458if (error == 0 && zfsvfs->z_case == ZFS_CASE_INSENSITIVE)459d_invalidate(dentry);460461spl_fstrans_unmark(cookie);462crfree(cr);463ASSERT3S(error, <=, 0);464465return (error);466}467468static int469#ifdef HAVE_USERNS_IOPS_GETATTR470zpl_getattr_impl(struct user_namespace *user_ns,471const struct path *path, struct kstat *stat, u32 request_mask,472unsigned int query_flags)473#elif defined(HAVE_IDMAP_IOPS_GETATTR)474zpl_getattr_impl(struct mnt_idmap *user_ns,475const struct path *path, struct kstat *stat, u32 request_mask,476unsigned int query_flags)477#else478zpl_getattr_impl(const struct path *path, struct kstat *stat, u32 request_mask,479unsigned int query_flags)480#endif481{482int error;483fstrans_cookie_t cookie;484struct inode *ip = path->dentry->d_inode;485znode_t *zp __maybe_unused = ITOZ(ip);486487cookie = spl_fstrans_mark();488489/*490* XXX query_flags currently ignored.491*/492493#ifdef HAVE_GENERIC_FILLATTR_IDMAP_REQMASK494error = -zfs_getattr_fast(user_ns, request_mask, ip, stat);495#elif (defined(HAVE_USERNS_IOPS_GETATTR) || defined(HAVE_IDMAP_IOPS_GETATTR))496error = -zfs_getattr_fast(user_ns, ip, stat);497#else498error = -zfs_getattr_fast(kcred->user_ns, ip, stat);499#endif500501#ifdef STATX_BTIME502if (request_mask & STATX_BTIME) {503stat->btime = zp->z_btime;504stat->result_mask |= STATX_BTIME;505}506#endif507508#ifdef STATX_DIOALIGN509if (request_mask & STATX_DIOALIGN) {510uint64_t align;511if (zfs_get_direct_alignment(zp, &align) == 0) {512stat->dio_mem_align = PAGE_SIZE;513stat->dio_offset_align = align;514stat->result_mask |= STATX_DIOALIGN;515}516}517#endif518519#ifdef STATX_ATTR_IMMUTABLE520if (zp->z_pflags & ZFS_IMMUTABLE)521stat->attributes |= STATX_ATTR_IMMUTABLE;522stat->attributes_mask |= STATX_ATTR_IMMUTABLE;523#endif524525#ifdef STATX_ATTR_APPEND526if (zp->z_pflags & ZFS_APPENDONLY)527stat->attributes |= STATX_ATTR_APPEND;528stat->attributes_mask |= STATX_ATTR_APPEND;529#endif530531#ifdef STATX_ATTR_NODUMP532if (zp->z_pflags & ZFS_NODUMP)533stat->attributes |= STATX_ATTR_NODUMP;534stat->attributes_mask |= STATX_ATTR_NODUMP;535#endif536537spl_fstrans_unmark(cookie);538ASSERT3S(error, <=, 0);539540return (error);541}542ZPL_GETATTR_WRAPPER(zpl_getattr);543544static int545#ifdef HAVE_USERNS_IOPS_SETATTR546zpl_setattr(struct user_namespace *user_ns, struct dentry *dentry,547struct iattr *ia)548#elif defined(HAVE_IDMAP_IOPS_SETATTR)549zpl_setattr(struct mnt_idmap *user_ns, struct dentry *dentry,550struct iattr *ia)551#else552zpl_setattr(struct dentry *dentry, struct iattr *ia)553#endif554{555struct inode *ip = dentry->d_inode;556cred_t *cr = CRED();557vattr_t *vap;558int error;559fstrans_cookie_t cookie;560561#ifdef HAVE_SETATTR_PREPARE_USERNS562error = zpl_setattr_prepare(user_ns, dentry, ia);563#elif defined(HAVE_SETATTR_PREPARE_IDMAP)564error = zpl_setattr_prepare(user_ns, dentry, ia);565#else566error = zpl_setattr_prepare(zfs_init_idmap, dentry, ia);567#endif568if (error)569return (error);570571crhold(cr);572vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP);573vap->va_mask = ia->ia_valid & ATTR_IATTR_MASK;574vap->va_mode = ia->ia_mode;575if (ia->ia_valid & ATTR_UID)576#ifdef HAVE_IATTR_VFSID577vap->va_uid = zfs_vfsuid_to_uid(user_ns, zfs_i_user_ns(ip),578__vfsuid_val(ia->ia_vfsuid));579#else580vap->va_uid = KUID_TO_SUID(ia->ia_uid);581#endif582if (ia->ia_valid & ATTR_GID)583#ifdef HAVE_IATTR_VFSID584vap->va_gid = zfs_vfsgid_to_gid(user_ns, zfs_i_user_ns(ip),585__vfsgid_val(ia->ia_vfsgid));586#else587vap->va_gid = KGID_TO_SGID(ia->ia_gid);588#endif589vap->va_size = ia->ia_size;590vap->va_atime = ia->ia_atime;591vap->va_mtime = ia->ia_mtime;592vap->va_ctime = ia->ia_ctime;593594if (vap->va_mask & ATTR_ATIME)595zpl_inode_set_atime_to_ts(ip,596zpl_inode_timestamp_truncate(ia->ia_atime, ip));597598cookie = spl_fstrans_mark();599#ifdef HAVE_USERNS_IOPS_SETATTR600error = -zfs_setattr(ITOZ(ip), vap, 0, cr, user_ns);601#elif defined(HAVE_IDMAP_IOPS_SETATTR)602error = -zfs_setattr(ITOZ(ip), vap, 0, cr, user_ns);603#else604error = -zfs_setattr(ITOZ(ip), vap, 0, cr, zfs_init_idmap);605#endif606if (!error && (ia->ia_valid & ATTR_MODE))607error = zpl_chmod_acl(ip);608609spl_fstrans_unmark(cookie);610kmem_free(vap, sizeof (vattr_t));611crfree(cr);612ASSERT3S(error, <=, 0);613614return (error);615}616617static int618#ifdef HAVE_IOPS_RENAME_USERNS619zpl_rename2(struct user_namespace *user_ns, struct inode *sdip,620struct dentry *sdentry, struct inode *tdip, struct dentry *tdentry,621unsigned int rflags)622#elif defined(HAVE_IOPS_RENAME_IDMAP)623zpl_rename2(struct mnt_idmap *user_ns, struct inode *sdip,624struct dentry *sdentry, struct inode *tdip, struct dentry *tdentry,625unsigned int rflags)626#else627zpl_rename2(struct inode *sdip, struct dentry *sdentry,628struct inode *tdip, struct dentry *tdentry, unsigned int rflags)629#endif630{631cred_t *cr = CRED();632vattr_t *wo_vap = NULL;633int error;634fstrans_cookie_t cookie;635#if !(defined(HAVE_IOPS_RENAME_USERNS) || defined(HAVE_IOPS_RENAME_IDMAP))636zidmap_t *user_ns = kcred->user_ns;637#endif638639if (is_nametoolong(tdentry)) {640return (-ENAMETOOLONG);641}642643crhold(cr);644if (rflags & RENAME_WHITEOUT) {645wo_vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP);646zpl_vap_init(wo_vap, sdip, S_IFCHR, cr, user_ns);647wo_vap->va_rdev = makedevice(0, 0);648}649650cookie = spl_fstrans_mark();651error = -zfs_rename(ITOZ(sdip), dname(sdentry), ITOZ(tdip),652dname(tdentry), cr, 0, rflags, wo_vap, user_ns);653spl_fstrans_unmark(cookie);654if (wo_vap)655kmem_free(wo_vap, sizeof (vattr_t));656crfree(cr);657ASSERT3S(error, <=, 0);658659return (error);660}661662#if !defined(HAVE_IOPS_RENAME_USERNS) && \663!defined(HAVE_RENAME_WANTS_FLAGS) && \664!defined(HAVE_IOPS_RENAME_IDMAP)665static int666zpl_rename(struct inode *sdip, struct dentry *sdentry,667struct inode *tdip, struct dentry *tdentry)668{669return (zpl_rename2(sdip, sdentry, tdip, tdentry, 0));670}671#endif672673static int674#ifdef HAVE_IOPS_SYMLINK_USERNS675zpl_symlink(struct user_namespace *user_ns, struct inode *dir,676struct dentry *dentry, const char *name)677#elif defined(HAVE_IOPS_SYMLINK_IDMAP)678zpl_symlink(struct mnt_idmap *user_ns, struct inode *dir,679struct dentry *dentry, const char *name)680#else681zpl_symlink(struct inode *dir, struct dentry *dentry, const char *name)682#endif683{684cred_t *cr = CRED();685vattr_t *vap;686znode_t *zp;687int error;688fstrans_cookie_t cookie;689#if !(defined(HAVE_IOPS_SYMLINK_USERNS) || defined(HAVE_IOPS_SYMLINK_IDMAP))690zidmap_t *user_ns = kcred->user_ns;691#endif692693if (is_nametoolong(dentry)) {694return (-ENAMETOOLONG);695}696697crhold(cr);698vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP);699zpl_vap_init(vap, dir, S_IFLNK | S_IRWXUGO, cr, user_ns);700701cookie = spl_fstrans_mark();702error = -zfs_symlink(ITOZ(dir), dname(dentry), vap,703(char *)name, &zp, cr, 0, user_ns);704if (error == 0) {705error = zpl_xattr_security_init(ZTOI(zp), dir, &dentry->d_name);706if (error) {707(void) zfs_remove(ITOZ(dir), dname(dentry), cr, 0);708remove_inode_hash(ZTOI(zp));709iput(ZTOI(zp));710} else {711d_instantiate(dentry, ZTOI(zp));712}713}714715spl_fstrans_unmark(cookie);716kmem_free(vap, sizeof (vattr_t));717crfree(cr);718ASSERT3S(error, <=, 0);719720return (error);721}722723static void724zpl_put_link(void *ptr)725{726kmem_free(ptr, MAXPATHLEN);727}728729static int730zpl_get_link_common(struct dentry *dentry, struct inode *ip, char **link)731{732fstrans_cookie_t cookie;733cred_t *cr = CRED();734int error;735736crhold(cr);737*link = NULL;738739struct iovec iov;740iov.iov_len = MAXPATHLEN;741iov.iov_base = kmem_zalloc(MAXPATHLEN, KM_SLEEP);742743zfs_uio_t uio;744zfs_uio_iovec_init(&uio, &iov, 1, 0, UIO_SYSSPACE, MAXPATHLEN - 1, 0);745746cookie = spl_fstrans_mark();747error = -zfs_readlink(ip, &uio, cr);748spl_fstrans_unmark(cookie);749crfree(cr);750751if (error)752kmem_free(iov.iov_base, MAXPATHLEN);753else754*link = iov.iov_base;755756return (error);757}758759static const char *760zpl_get_link(struct dentry *dentry, struct inode *inode,761struct delayed_call *done)762{763char *link = NULL;764int error;765766if (!dentry)767return (ERR_PTR(-ECHILD));768769error = zpl_get_link_common(dentry, inode, &link);770if (error)771return (ERR_PTR(error));772773set_delayed_call(done, zpl_put_link, link);774775return (link);776}777778static int779zpl_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)780{781cred_t *cr = CRED();782struct inode *ip = old_dentry->d_inode;783int error;784fstrans_cookie_t cookie;785786if (is_nametoolong(dentry)) {787return (-ENAMETOOLONG);788}789790if (ip->i_nlink >= ZFS_LINK_MAX)791return (-EMLINK);792793crhold(cr);794zpl_inode_set_ctime_to_ts(ip, current_time(ip));795/* Must have an existing ref, so igrab() cannot return NULL */796VERIFY3P(igrab(ip), !=, NULL);797798cookie = spl_fstrans_mark();799error = -zfs_link(ITOZ(dir), ITOZ(ip), dname(dentry), cr, 0);800if (error) {801iput(ip);802goto out;803}804805d_instantiate(dentry, ip);806out:807spl_fstrans_unmark(cookie);808crfree(cr);809ASSERT3S(error, <=, 0);810811return (error);812}813814const struct inode_operations zpl_inode_operations = {815.setattr = zpl_setattr,816.getattr = zpl_getattr,817.listxattr = zpl_xattr_list,818#if defined(CONFIG_FS_POSIX_ACL)819.set_acl = zpl_set_acl,820#if defined(HAVE_GET_INODE_ACL)821.get_inode_acl = zpl_get_acl,822#else823.get_acl = zpl_get_acl,824#endif /* HAVE_GET_INODE_ACL */825#endif /* CONFIG_FS_POSIX_ACL */826};827828const struct inode_operations zpl_dir_inode_operations = {829.create = zpl_create,830.lookup = zpl_lookup,831.link = zpl_link,832.unlink = zpl_unlink,833.symlink = zpl_symlink,834.mkdir = zpl_mkdir,835.rmdir = zpl_rmdir,836.mknod = zpl_mknod,837#if defined(HAVE_RENAME_WANTS_FLAGS) || defined(HAVE_IOPS_RENAME_USERNS)838.rename = zpl_rename2,839#elif defined(HAVE_IOPS_RENAME_IDMAP)840.rename = zpl_rename2,841#else842.rename = zpl_rename,843#endif844.tmpfile = zpl_tmpfile,845.setattr = zpl_setattr,846.getattr = zpl_getattr,847.listxattr = zpl_xattr_list,848#if defined(CONFIG_FS_POSIX_ACL)849.set_acl = zpl_set_acl,850#if defined(HAVE_GET_INODE_ACL)851.get_inode_acl = zpl_get_acl,852#else853.get_acl = zpl_get_acl,854#endif /* HAVE_GET_INODE_ACL */855#endif /* CONFIG_FS_POSIX_ACL */856};857858const struct inode_operations zpl_symlink_inode_operations = {859.get_link = zpl_get_link,860.setattr = zpl_setattr,861.getattr = zpl_getattr,862.listxattr = zpl_xattr_list,863};864865const struct inode_operations zpl_special_inode_operations = {866.setattr = zpl_setattr,867.getattr = zpl_getattr,868.listxattr = zpl_xattr_list,869#if defined(CONFIG_FS_POSIX_ACL)870.set_acl = zpl_set_acl,871#if defined(HAVE_GET_INODE_ACL)872.get_inode_acl = zpl_get_acl,873#else874.get_acl = zpl_get_acl,875#endif /* HAVE_GET_INODE_ACL */876#endif /* CONFIG_FS_POSIX_ACL */877};878879880