vfs: Rename vfs_emptydir() to vn_dir_check_empty()
No functional change. While here, adapt comments to style(9). Reviewed by: kib MFC after: 1 week
This commit is contained in:
parent
c21d87a88c
commit
2544b8e00c
@ -1160,7 +1160,7 @@ vfs_domount_first(
|
||||
error = ENOTDIR;
|
||||
}
|
||||
if (error == 0 && (fsflags & MNT_EMPTYDIR) != 0)
|
||||
error = vfs_emptydir(vp);
|
||||
error = vn_dir_check_empty(vp);
|
||||
if (error == 0) {
|
||||
VI_LOCK(vp);
|
||||
if ((vp->v_iflag & VI_MOUNT) == 0 && vp->v_mountedhere == NULL)
|
||||
|
@ -6382,96 +6382,6 @@ filt_vfsvnode(struct knote *kn, long hint)
|
||||
return (res);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns whether the directory is empty or not.
|
||||
* If it is empty, the return value is 0; otherwise
|
||||
* the return value is an error value (which may
|
||||
* be ENOTEMPTY).
|
||||
*/
|
||||
int
|
||||
vfs_emptydir(struct vnode *vp)
|
||||
{
|
||||
struct thread *const td = curthread;
|
||||
char *dirbuf;
|
||||
size_t dirbuflen, len;
|
||||
off_t off;
|
||||
int eofflag, error;
|
||||
struct dirent *dp;
|
||||
struct vattr va;
|
||||
|
||||
ASSERT_VOP_LOCKED(vp, "vfs_emptydir");
|
||||
VNPASS(vp->v_type == VDIR, vp);
|
||||
|
||||
error = VOP_GETATTR(vp, &va, td->td_ucred);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
dirbuflen = max(DEV_BSIZE, GENERIC_MAXDIRSIZ);
|
||||
if (dirbuflen < va.va_blocksize)
|
||||
dirbuflen = va.va_blocksize;
|
||||
dirbuf = malloc(dirbuflen, M_TEMP, M_WAITOK);
|
||||
|
||||
len = 0;
|
||||
off = 0;
|
||||
eofflag = 0;
|
||||
|
||||
for (;;) {
|
||||
error = vn_dir_next_dirent(vp, td, dirbuf, dirbuflen,
|
||||
&dp, &len, &off, &eofflag);
|
||||
if (error != 0)
|
||||
goto end;
|
||||
|
||||
if (len == 0) {
|
||||
/* EOF */
|
||||
error = 0;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip whiteouts. Unionfs operates on filesystems only and not
|
||||
* on hierarchies, so these whiteouts would be shadowed on the
|
||||
* system hierarchy but not for a union using the filesystem of
|
||||
* their directories as the upper layer. Additionally, unionfs
|
||||
* currently transparently exposes union-specific metadata of
|
||||
* its upper layer, meaning that whiteouts can be seen through
|
||||
* the union view in empty directories. Taking into account
|
||||
* these whiteouts would then prevent mounting another
|
||||
* filesystem on such effectively empty directories.
|
||||
*/
|
||||
if (dp->d_type == DT_WHT)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Any file in the directory which is not '.' or '..' indicates
|
||||
* the directory is not empty.
|
||||
*/
|
||||
switch (dp->d_namlen) {
|
||||
case 2:
|
||||
if (dp->d_name[1] != '.') {
|
||||
/* Can't be '..' (nor '.') */
|
||||
error = ENOTEMPTY;
|
||||
goto end;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case 1:
|
||||
if (dp->d_name[0] != '.') {
|
||||
/* Can't be '..' nor '.' */
|
||||
error = ENOTEMPTY;
|
||||
goto end;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
error = ENOTEMPTY;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
free(dirbuf, M_TEMP);
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
vfs_read_dirent(struct vop_readdir_args *ap, struct dirent *dp, off_t off)
|
||||
{
|
||||
|
@ -3897,6 +3897,97 @@ vn_dir_next_dirent(struct vnode *vp, struct thread *td,
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks whether a directory is empty or not.
|
||||
*
|
||||
* If the directory is empty, returns 0, and if it is not, ENOTEMPTY. Other
|
||||
* values are genuine errors preventing the check.
|
||||
*/
|
||||
int
|
||||
vn_dir_check_empty(struct vnode *vp)
|
||||
{
|
||||
struct thread *const td = curthread;
|
||||
char *dirbuf;
|
||||
size_t dirbuflen, len;
|
||||
off_t off;
|
||||
int eofflag, error;
|
||||
struct dirent *dp;
|
||||
struct vattr va;
|
||||
|
||||
ASSERT_VOP_LOCKED(vp, "vfs_emptydir");
|
||||
VNPASS(vp->v_type == VDIR, vp);
|
||||
|
||||
error = VOP_GETATTR(vp, &va, td->td_ucred);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
dirbuflen = max(DEV_BSIZE, GENERIC_MAXDIRSIZ);
|
||||
if (dirbuflen < va.va_blocksize)
|
||||
dirbuflen = va.va_blocksize;
|
||||
dirbuf = malloc(dirbuflen, M_TEMP, M_WAITOK);
|
||||
|
||||
len = 0;
|
||||
off = 0;
|
||||
eofflag = 0;
|
||||
|
||||
for (;;) {
|
||||
error = vn_dir_next_dirent(vp, td, dirbuf, dirbuflen,
|
||||
&dp, &len, &off, &eofflag);
|
||||
if (error != 0)
|
||||
goto end;
|
||||
|
||||
if (len == 0) {
|
||||
/* EOF */
|
||||
error = 0;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip whiteouts. Unionfs operates on filesystems only and
|
||||
* not on hierarchies, so these whiteouts would be shadowed on
|
||||
* the system hierarchy but not for a union using the
|
||||
* filesystem of their directories as the upper layer.
|
||||
* Additionally, unionfs currently transparently exposes
|
||||
* union-specific metadata of its upper layer, meaning that
|
||||
* whiteouts can be seen through the union view in empty
|
||||
* directories. Taking into account these whiteouts would then
|
||||
* prevent mounting another filesystem on such effectively
|
||||
* empty directories.
|
||||
*/
|
||||
if (dp->d_type == DT_WHT)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Any file in the directory which is not '.' or '..' indicates
|
||||
* the directory is not empty.
|
||||
*/
|
||||
switch (dp->d_namlen) {
|
||||
case 2:
|
||||
if (dp->d_name[1] != '.') {
|
||||
/* Can't be '..' (nor '.') */
|
||||
error = ENOTEMPTY;
|
||||
goto end;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case 1:
|
||||
if (dp->d_name[0] != '.') {
|
||||
/* Can't be '..' nor '.' */
|
||||
error = ENOTEMPTY;
|
||||
goto end;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
error = ENOTEMPTY;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
free(dirbuf, M_TEMP);
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
||||
static u_long vn_lock_pair_pause_cnt;
|
||||
SYSCTL_ULONG(_debug, OID_AUTO, vn_lock_pair_pause, CTLFLAG_RD,
|
||||
|
@ -1102,8 +1102,8 @@ struct dirent;
|
||||
int vn_dir_next_dirent(struct vnode *vp, struct thread *td,
|
||||
char *dirbuf, size_t dirbuflen,
|
||||
struct dirent **dpp, size_t *len, off_t *off, int *eofflag);
|
||||
int vn_dir_check_empty(struct vnode *vp);
|
||||
int vfs_read_dirent(struct vop_readdir_args *ap, struct dirent *dp, off_t off);
|
||||
int vfs_emptydir(struct vnode *vp);
|
||||
|
||||
int vfs_unixify_accmode(accmode_t *accmode);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user