zfs: implement AT_RENAME_NOREPLACE

Reviewed by:	markj
Tested by:	pho
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
Differential revision:	https://reviews.freebsd.org/D55539
This commit is contained in:
Konstantin Belousov
2026-03-01 15:16:55 +02:00
parent 7aaec5f3fa
commit 7a1217ff3b
3 changed files with 20 additions and 11 deletions
@@ -42,8 +42,8 @@ extern int zfs_rmdir(znode_t *dzp, const char *name, znode_t *cwd,
extern int zfs_setattr(znode_t *zp, vattr_t *vap, int flag, cred_t *cr,
zidmap_t *mnt_ns);
extern int zfs_rename(znode_t *sdzp, const char *snm, znode_t *tdzp,
const char *tnm, cred_t *cr, int flags, uint64_t rflags, vattr_t *wo_vap,
zidmap_t *mnt_ns);
const char *tnm, cred_t *cr, int flags, uint64_t rflags, u_int at_flags,
vattr_t *wo_vap, zidmap_t *mnt_ns);
extern int zfs_symlink(znode_t *dzp, const char *name, vattr_t *vap,
const char *link, znode_t **zpp, cred_t *cr, int flags, zidmap_t *mnt_ns);
extern int zfs_link(znode_t *tdzp, znode_t *sp,
@@ -3256,7 +3256,7 @@ zfs_rename_check(znode_t *szp, znode_t *sdzp, znode_t *tdzp)
static int
zfs_do_rename_impl(vnode_t *sdvp, vnode_t **svpp, struct componentname *scnp,
vnode_t *tdvp, vnode_t **tvpp, struct componentname *tcnp,
cred_t *cr);
cred_t *cr, u_int at_flags);
/*
* Move an entry from the provided source directory to the target
@@ -3267,6 +3267,7 @@ zfs_do_rename_impl(vnode_t *sdvp, vnode_t **svpp, struct componentname *scnp,
* tdvp - Target directory to contain the "new entry".
* tcnp - New entry name.
* cr - credentials of caller.
* at_flags - AT_RENAME_*
* INOUT: svpp - Source file
* tvpp - Target file, may point to NULL initially
*
@@ -3278,7 +3279,7 @@ zfs_do_rename_impl(vnode_t *sdvp, vnode_t **svpp, struct componentname *scnp,
static int
zfs_do_rename(vnode_t *sdvp, vnode_t **svpp, struct componentname *scnp,
vnode_t *tdvp, vnode_t **tvpp, struct componentname *tcnp,
cred_t *cr)
cred_t *cr, u_int at_flags)
{
int error;
@@ -3307,7 +3308,8 @@ zfs_do_rename(vnode_t *sdvp, vnode_t **svpp, struct componentname *scnp,
return (error);
}
error = zfs_do_rename_impl(sdvp, svpp, scnp, tdvp, tvpp, tcnp, cr);
error = zfs_do_rename_impl(sdvp, svpp, scnp, tdvp, tvpp, tcnp, cr,
at_flags);
VOP_UNLOCK(sdvp);
VOP_UNLOCK(*svpp);
out:
@@ -3322,7 +3324,7 @@ zfs_do_rename(vnode_t *sdvp, vnode_t **svpp, struct componentname *scnp,
static int
zfs_do_rename_impl(vnode_t *sdvp, vnode_t **svpp, struct componentname *scnp,
vnode_t *tdvp, vnode_t **tvpp, struct componentname *tcnp,
cred_t *cr)
cred_t *cr, u_int at_flags)
{
dmu_tx_t *tx;
zfsvfs_t *zfsvfs;
@@ -3431,6 +3433,11 @@ zfs_do_rename_impl(vnode_t *sdvp, vnode_t **svpp, struct componentname *scnp,
* Does target exist?
*/
if (tzp) {
if ((at_flags & AT_RENAME_NOREPLACE) != 0) {
error = SET_ERROR(EEXIST);
goto out;
}
/*
* Source and target must be the same type.
*/
@@ -3551,7 +3558,8 @@ zfs_do_rename_impl(vnode_t *sdvp, vnode_t **svpp, struct componentname *scnp,
int
zfs_rename(znode_t *sdzp, const char *sname, znode_t *tdzp, const char *tname,
cred_t *cr, int flags, uint64_t rflags, vattr_t *wo_vap, zidmap_t *mnt_ns)
cred_t *cr, int flags, uint64_t rflags, u_int at_flags, vattr_t *wo_vap,
zidmap_t *mnt_ns)
{
struct componentname scn, tcn;
vnode_t *sdvp, *tdvp;
@@ -3583,7 +3591,8 @@ zfs_rename(znode_t *sdzp, const char *sname, znode_t *tdzp, const char *tname,
goto fail;
}
error = zfs_do_rename(sdvp, &svp, &scn, tdvp, &tvp, &tcn, cr);
error = zfs_do_rename(sdvp, &svp, &scn, tdvp, &tvp, &tcn, cr,
at_flags);
fail:
if (svp != NULL)
vrele(svp);
@@ -5527,12 +5536,12 @@ zfs_freebsd_rename(struct vop_rename_args *ap)
}
#endif
if (error == 0 && ap->a_flags != 0)
if (error == 0 && (ap->a_flags & ~(AT_RENAME_NOREPLACE)) != 0)
error = EOPNOTSUPP;
if (error == 0) {
error = zfs_do_rename(fdvp, &fvp, ap->a_fcnp, tdvp, &tvp,
ap->a_tcnp, ap->a_fcnp->cn_cred);
ap->a_tcnp, ap->a_fcnp->cn_cred, ap->a_flags);
vrele(fdvp);
vrele(fvp);
vrele(tdvp);
+1 -1
View File
@@ -710,7 +710,7 @@ do_zfs_replay_rename(zfsvfs_t *zfsvfs, _lr_rename_t *lr, char *sname,
wo_vap, zfs_init_idmap);
#else
error = zfs_rename(sdzp, sname, tdzp, tname, kcred, vflg, rflags,
wo_vap, NULL);
0, wo_vap, NULL);
#endif
zrele(tdzp);