mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-27 11:55:06 +00:00
vfs: Add IGNOREWHITEOUT flag and adopt it in UFS/unionfs
This flag is meant to request that the VOP implementation ignore whiteout entries when processing directory contents. Employ this flag (initially) in UFS when determining whether a directory is empty for the purpose of deleting it or renaming another directory over it. The previous UFS behavior was to always ignore whiteouts and to therefore always allow directories containing only whiteouts to be deleted or overwritten. This makes sense when the directory in question is being accessed through a unionfs view in which the whiteouts produce a unionfs directory that is logically empty, but it makes less sense when directly operating against the UFS directory in which case silently discarding the whiteouts may produce unexpected behavior in a current or future unionfs view. IGNOREWHITEOUT is therefore treated as opt-in and only specified by unionfs_rmdir() when invoking VOP_RMDIR() against the upper filesystem. IGNOREWHITEOUT is not currently used for unionfs rename operations, as the current implementation of unionfs_rename() simply forbids renaming over any existing upper filesystem directory in the first place. Differential Revision: https://reviews.freebsd.org/D45987 Reviewed by: olce Tested by: pho
This commit is contained in:
parent
44328abfb7
commit
2ed053cde5
@ -1732,7 +1732,7 @@ unionfs_rmdir(struct vop_rmdir_args *ap)
|
||||
}
|
||||
ump = MOUNTTOUNIONFSMOUNT(ap->a_vp->v_mount);
|
||||
if (ump->um_whitemode == UNIONFS_WHITE_ALWAYS || lvp != NULLVP)
|
||||
cnp->cn_flags |= DOWHITEOUT;
|
||||
cnp->cn_flags |= (DOWHITEOUT | IGNOREWHITEOUT);
|
||||
int udvp_lkflags, uvp_lkflags;
|
||||
unionfs_forward_vop_start_pair(udvp, &udvp_lkflags,
|
||||
uvp, &uvp_lkflags);
|
||||
|
@ -159,7 +159,7 @@ int cache_fplookup(struct nameidata *ndp, enum cache_fpl_status *status,
|
||||
*/
|
||||
#define RDONLY 0x00000200 /* lookup with read-only semantics */
|
||||
#define ISRESTARTED 0x00000400 /* restarted namei */
|
||||
/* UNUSED 0x00000800 */
|
||||
#define IGNOREWHITEOUT 0x00000800 /* ignore whiteouts, e.g. when checking if a dir is empty */
|
||||
#define ISWHITEOUT 0x00001000 /* found whiteout */
|
||||
#define DOWHITEOUT 0x00002000 /* do whiteouts */
|
||||
#define WILLBEDIR 0x00004000 /* new files will be dirs; allow trailing / */
|
||||
|
@ -59,7 +59,7 @@ int ufs_bmap_seekdata(struct vnode *, off_t *);
|
||||
int ufs_checkpath(ino_t, ino_t, struct inode *, struct ucred *, ino_t *);
|
||||
void ufs_dirbad(struct inode *, doff_t, char *);
|
||||
int ufs_dirbadentry(struct vnode *, struct direct *, int);
|
||||
int ufs_dirempty(struct inode *, ino_t, struct ucred *);
|
||||
int ufs_dirempty(struct inode *, ino_t, struct ucred *, int);
|
||||
int ufs_extread(struct vop_read_args *);
|
||||
int ufs_extwrite(struct vop_write_args *);
|
||||
void ufs_makedirentry(struct inode *, struct componentname *,
|
||||
|
@ -1298,7 +1298,8 @@ ufs_dirrewrite(struct inode *dp, struct inode *oip, ino_t newinum, int newtype,
|
||||
* NB: does not handle corrupted directories.
|
||||
*/
|
||||
int
|
||||
ufs_dirempty(struct inode *ip, ino_t parentino, struct ucred *cred)
|
||||
ufs_dirempty(struct inode *ip, ino_t parentino, struct ucred *cred,
|
||||
int skipwhiteout)
|
||||
{
|
||||
doff_t off;
|
||||
struct dirtemplate dbuf;
|
||||
@ -1321,7 +1322,8 @@ ufs_dirempty(struct inode *ip, ino_t parentino, struct ucred *cred)
|
||||
if (dp->d_reclen == 0)
|
||||
return (0);
|
||||
/* skip empty entries */
|
||||
if (dp->d_ino == 0 || dp->d_ino == UFS_WINO)
|
||||
if (dp->d_ino == 0 ||
|
||||
(skipwhiteout != 0 && dp->d_ino == UFS_WINO))
|
||||
continue;
|
||||
/* accept only "." and ".." */
|
||||
# if (BYTE_ORDER == LITTLE_ENDIAN)
|
||||
|
@ -1625,7 +1625,8 @@ ufs_rename(
|
||||
*/
|
||||
if ((tip->i_mode & IFMT) == IFDIR) {
|
||||
if ((tip->i_effnlink > 2) ||
|
||||
!ufs_dirempty(tip, tdp->i_number, tcnp->cn_cred)) {
|
||||
!ufs_dirempty(tip, tdp->i_number, tcnp->cn_cred,
|
||||
(tcnp->cn_flags & IGNOREWHITEOUT) != 0)) {
|
||||
error = ENOTEMPTY;
|
||||
goto bad;
|
||||
}
|
||||
@ -2281,7 +2282,8 @@ ufs_rmdir(
|
||||
error = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (!ufs_dirempty(ip, dp->i_number, cnp->cn_cred)) {
|
||||
if (!ufs_dirempty(ip, dp->i_number, cnp->cn_cred,
|
||||
(cnp->cn_flags & IGNOREWHITEOUT) != 0)) {
|
||||
error = ENOTEMPTY;
|
||||
goto out;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user