vfs: depessimize getfsstat when only the count is requested
This avoids relocking mountlist_mtx for each entry.
This commit is contained in:
parent
8c1f410c19
commit
6c69e69724
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=363069
@ -441,7 +441,46 @@ kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize,
|
|||||||
tofree = sfsp = *buf = malloc(maxcount * sizeof(struct statfs),
|
tofree = sfsp = *buf = malloc(maxcount * sizeof(struct statfs),
|
||||||
M_STATFS, M_WAITOK);
|
M_STATFS, M_WAITOK);
|
||||||
}
|
}
|
||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If there is no target buffer they only want the count.
|
||||||
|
*
|
||||||
|
* This could be TAILQ_FOREACH but it is open-coded to match the original
|
||||||
|
* code below.
|
||||||
|
*/
|
||||||
|
if (sfsp == NULL) {
|
||||||
|
mtx_lock(&mountlist_mtx);
|
||||||
|
for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
|
||||||
|
if (prison_canseemount(td->td_ucred, mp) != 0) {
|
||||||
|
nmp = TAILQ_NEXT(mp, mnt_list);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#ifdef MAC
|
||||||
|
if (mac_mount_check_stat(td->td_ucred, mp) != 0) {
|
||||||
|
nmp = TAILQ_NEXT(mp, mnt_list);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
count++;
|
||||||
|
nmp = TAILQ_NEXT(mp, mnt_list);
|
||||||
|
}
|
||||||
|
mtx_unlock(&mountlist_mtx);
|
||||||
|
*countp = count;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* They want the entire thing.
|
||||||
|
*
|
||||||
|
* Short-circuit the corner case of no room for anything, avoids
|
||||||
|
* relocking below.
|
||||||
|
*/
|
||||||
|
if (maxcount < 1) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
mtx_lock(&mountlist_mtx);
|
mtx_lock(&mountlist_mtx);
|
||||||
for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
|
for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
|
||||||
if (prison_canseemount(td->td_ucred, mp) != 0) {
|
if (prison_canseemount(td->td_ucred, mp) != 0) {
|
||||||
@ -473,53 +512,55 @@ kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sfsp != NULL && count < maxcount) {
|
sp = &mp->mnt_stat;
|
||||||
sp = &mp->mnt_stat;
|
/*
|
||||||
/*
|
* If MNT_NOWAIT is specified, do not refresh
|
||||||
* If MNT_NOWAIT is specified, do not refresh
|
* the fsstat cache.
|
||||||
* the fsstat cache.
|
*/
|
||||||
*/
|
if (mode != MNT_NOWAIT) {
|
||||||
if (mode != MNT_NOWAIT) {
|
error = VFS_STATFS(mp, sp);
|
||||||
error = VFS_STATFS(mp, sp);
|
if (error != 0) {
|
||||||
if (error != 0) {
|
mtx_lock(&mountlist_mtx);
|
||||||
mtx_lock(&mountlist_mtx);
|
nmp = TAILQ_NEXT(mp, mnt_list);
|
||||||
nmp = TAILQ_NEXT(mp, mnt_list);
|
vfs_unbusy(mp);
|
||||||
vfs_unbusy(mp);
|
continue;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (priv_check_cred_vfs_generation(td->td_ucred)) {
|
|
||||||
sptmp = malloc(sizeof(struct statfs), M_STATFS,
|
|
||||||
M_WAITOK);
|
|
||||||
*sptmp = *sp;
|
|
||||||
sptmp->f_fsid.val[0] = sptmp->f_fsid.val[1] = 0;
|
|
||||||
prison_enforce_statfs(td->td_ucred, mp, sptmp);
|
|
||||||
sp = sptmp;
|
|
||||||
} else
|
|
||||||
sptmp = NULL;
|
|
||||||
if (bufseg == UIO_SYSSPACE) {
|
|
||||||
bcopy(sp, sfsp, sizeof(*sp));
|
|
||||||
free(sptmp, M_STATFS);
|
|
||||||
} else /* if (bufseg == UIO_USERSPACE) */ {
|
|
||||||
error = copyout(sp, sfsp, sizeof(*sp));
|
|
||||||
free(sptmp, M_STATFS);
|
|
||||||
if (error != 0) {
|
|
||||||
vfs_unbusy(mp);
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sfsp++;
|
|
||||||
}
|
}
|
||||||
|
if (priv_check_cred_vfs_generation(td->td_ucred)) {
|
||||||
|
sptmp = malloc(sizeof(struct statfs), M_STATFS,
|
||||||
|
M_WAITOK);
|
||||||
|
*sptmp = *sp;
|
||||||
|
sptmp->f_fsid.val[0] = sptmp->f_fsid.val[1] = 0;
|
||||||
|
prison_enforce_statfs(td->td_ucred, mp, sptmp);
|
||||||
|
sp = sptmp;
|
||||||
|
} else
|
||||||
|
sptmp = NULL;
|
||||||
|
if (bufseg == UIO_SYSSPACE) {
|
||||||
|
bcopy(sp, sfsp, sizeof(*sp));
|
||||||
|
free(sptmp, M_STATFS);
|
||||||
|
} else /* if (bufseg == UIO_USERSPACE) */ {
|
||||||
|
error = copyout(sp, sfsp, sizeof(*sp));
|
||||||
|
free(sptmp, M_STATFS);
|
||||||
|
if (error != 0) {
|
||||||
|
vfs_unbusy(mp);
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sfsp++;
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
|
if (count == maxcount) {
|
||||||
|
vfs_unbusy(mp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
mtx_lock(&mountlist_mtx);
|
mtx_lock(&mountlist_mtx);
|
||||||
nmp = TAILQ_NEXT(mp, mnt_list);
|
nmp = TAILQ_NEXT(mp, mnt_list);
|
||||||
vfs_unbusy(mp);
|
vfs_unbusy(mp);
|
||||||
}
|
}
|
||||||
mtx_unlock(&mountlist_mtx);
|
mtx_unlock(&mountlist_mtx);
|
||||||
if (sfsp != NULL && count > maxcount)
|
out:
|
||||||
*countp = maxcount;
|
*countp = count;
|
||||||
else
|
|
||||||
*countp = count;
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user