mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-28 11:25:21 +01:00
renameat2(2): implement AT_RENAME_NOREPLACE flag
For msdosfs, tmpfs, and ufs. 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:
1 parent
28599a1e5f
commit
7aaec5f3fa
5 files changed
+43
-9
No files matched your search
@@ -49,12 +49,12 @@
|
||||
* October 1992
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bio.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/clock.h>
|
||||
#include <sys/dirent.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/lockf.h>
|
||||
#include <sys/malloc.h>
|
||||
@@ -970,7 +970,7 @@ msdosfs_rename(struct vop_rename_args *ap)
|
||||
goto abortit;
|
||||
}
|
||||
|
||||
if (ap->a_flags != 0) {
|
||||
if ((ap->a_flags & ~(AT_RENAME_NOREPLACE)) != 0) {
|
||||
error = EOPNOTSUPP;
|
||||
goto abortit;
|
||||
}
|
||||
@@ -1041,6 +1041,11 @@ relock:
|
||||
vrele(tvp);
|
||||
tvp = NULL;
|
||||
}
|
||||
if (error == 0 && tvp != NULL &&
|
||||
(ap->a_flags & AT_RENAME_NOREPLACE) != 0) {
|
||||
error = EEXIST;
|
||||
goto unlock;
|
||||
}
|
||||
if (error == 0) {
|
||||
nip = NULL;
|
||||
error = deget(pmp, scn, blkoff, LK_EXCLUSIVE | LK_NOWAIT,
|
||||
|
||||
@@ -993,7 +993,7 @@ tmpfs_rename(struct vop_rename_args *v)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (v->a_flags != 0) {
|
||||
if ((v->a_flags & ~(AT_RENAME_NOREPLACE)) != 0) {
|
||||
error = EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
@@ -1018,9 +1018,14 @@ tmpfs_rename(struct vop_rename_args *v)
|
||||
"tmpfs_rename: fdvp not locked");
|
||||
ASSERT_VOP_ELOCKED(tdvp,
|
||||
"tmpfs_rename: tdvp not locked");
|
||||
if (tvp != NULL)
|
||||
if (tvp != NULL) {
|
||||
ASSERT_VOP_ELOCKED(tvp,
|
||||
"tmpfs_rename: tvp not locked");
|
||||
if ((v->a_flags & AT_RENAME_NOREPLACE) != 0) {
|
||||
error = EEXIST;
|
||||
goto out_locked;
|
||||
}
|
||||
}
|
||||
if (fvp == tvp) {
|
||||
error = 0;
|
||||
goto out_locked;
|
||||
|
||||
+20
-4
@@ -3783,7 +3783,7 @@ kern_renameat(struct thread *td, int oldfd, const char *old, int newfd,
|
||||
int error;
|
||||
short irflag;
|
||||
|
||||
if (flags != 0)
|
||||
if ((flags & ~(AT_RENAME_NOREPLACE)) != 0)
|
||||
return (EINVAL);
|
||||
again:
|
||||
tmp = mp = NULL;
|
||||
@@ -3820,6 +3820,19 @@ again:
|
||||
}
|
||||
tdvp = tond.ni_dvp;
|
||||
tvp = tond.ni_vp;
|
||||
if (tvp != NULL && (flags & AT_RENAME_NOREPLACE) != 0) {
|
||||
/*
|
||||
* Often filesystems need to relock the vnodes in
|
||||
* VOP_RENAME(), which opens a window for invalidation
|
||||
* of this check. Then, not all filesystems might
|
||||
* implement AT_RENAME_NOREPLACE. This leads to
|
||||
* situation where sometimes EOPNOTSUPP might be
|
||||
* returned from the VOP due to race, while most of
|
||||
* the time this check works.
|
||||
*/
|
||||
error = EEXIST;
|
||||
goto out;
|
||||
}
|
||||
error = vn_start_write(fvp, &mp, V_NOWAIT);
|
||||
if (error != 0) {
|
||||
again1:
|
||||
@@ -3912,9 +3925,12 @@ out:
|
||||
vrele(fromnd.ni_dvp);
|
||||
vrele(fvp);
|
||||
}
|
||||
lockmgr(&tmp->mnt_renamelock, LK_RELEASE, 0);
|
||||
vfs_rel(tmp);
|
||||
vn_finished_write(mp);
|
||||
if (tmp != NULL) {
|
||||
lockmgr(&tmp->mnt_renamelock, LK_RELEASE, 0);
|
||||
vfs_rel(tmp);
|
||||
}
|
||||
if (mp != NULL)
|
||||
vn_finished_write(mp);
|
||||
out1:
|
||||
if (error == ERESTART)
|
||||
return (0);
|
||||
|
||||
@@ -245,6 +245,9 @@ typedef __pid_t pid_t;
|
||||
#define AT_RESOLVE_BENEATH 0x2000 /* Do not allow name resolution
|
||||
to walk out of dirfd */
|
||||
#define AT_EMPTY_PATH 0x4000 /* Operate on dirfd if path is empty */
|
||||
|
||||
#define AT_RENAME_NOREPLACE 0x0001 /* Fail rename if target exists */
|
||||
#define RENAME_NOREPLACE AT_RENAME_NOREPLACE
|
||||
#endif /* __BSD_VISIBLE */
|
||||
|
||||
/*
|
||||
|
||||
@@ -1294,7 +1294,7 @@ ufs_rename(
|
||||
goto releout;
|
||||
}
|
||||
|
||||
if (ap->a_flags != 0) {
|
||||
if ((ap->a_flags & ~(AT_RENAME_NOREPLACE)) != 0) {
|
||||
error = EOPNOTSUPP;
|
||||
mp = NULL;
|
||||
goto releout;
|
||||
@@ -1394,6 +1394,11 @@ relock:
|
||||
}
|
||||
}
|
||||
|
||||
if (tvp != NULL && (ap->a_flags & AT_RENAME_NOREPLACE) != 0) {
|
||||
error = EEXIST;
|
||||
goto unlockout;
|
||||
}
|
||||
|
||||
if (DOINGSUJ(fdvp) &&
|
||||
(seqc_in_modify(fdvp_s) || !vn_seqc_consistent(fdvp, fdvp_s) ||
|
||||
seqc_in_modify(fvp_s) || !vn_seqc_consistent(fvp, fvp_s) ||
|
||||
|
||||
Reference in new issue
Block a user