FreeBSD: libspl: Add locking around statfs globals
Makes getmntent and getmntany thread-safe for external consumers of libzfs zpool_disable_datasets, zfs_iter_mounted, libzfs_mnttab_update, libzfs_mnttab_find. Reviewed-by: Alexander Motin <mav@FreeBSD.org> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Ryan Moeller <freqlabs@FreeBSD.org> Closes #13484
This commit is contained in:
parent
ed16dd7635
commit
fde66e583d
|
@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <pthread.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -136,6 +137,7 @@ statfs2mnttab(struct statfs *sfs, struct mnttab *mp)
|
||||||
mp->mnt_mntopts = gmntopts;
|
mp->mnt_mntopts = gmntopts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static pthread_rwlock_t gsfs_lock = PTHREAD_RWLOCK_INITIALIZER;
|
||||||
static struct statfs *gsfs = NULL;
|
static struct statfs *gsfs = NULL;
|
||||||
static int allfs = 0;
|
static int allfs = 0;
|
||||||
|
|
||||||
|
@ -145,6 +147,8 @@ statfs_init(void)
|
||||||
struct statfs *sfs;
|
struct statfs *sfs;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
(void) pthread_rwlock_wrlock(&gsfs_lock);
|
||||||
|
|
||||||
if (gsfs != NULL) {
|
if (gsfs != NULL) {
|
||||||
free(gsfs);
|
free(gsfs);
|
||||||
gsfs = NULL;
|
gsfs = NULL;
|
||||||
|
@ -162,6 +166,7 @@ statfs_init(void)
|
||||||
sfs = realloc(gsfs, allfs * sizeof (gsfs[0]));
|
sfs = realloc(gsfs, allfs * sizeof (gsfs[0]));
|
||||||
if (sfs != NULL)
|
if (sfs != NULL)
|
||||||
gsfs = sfs;
|
gsfs = sfs;
|
||||||
|
(void) pthread_rwlock_unlock(&gsfs_lock);
|
||||||
return (0);
|
return (0);
|
||||||
fail:
|
fail:
|
||||||
error = errno;
|
error = errno;
|
||||||
|
@ -169,6 +174,7 @@ fail:
|
||||||
free(gsfs);
|
free(gsfs);
|
||||||
gsfs = NULL;
|
gsfs = NULL;
|
||||||
allfs = 0;
|
allfs = 0;
|
||||||
|
(void) pthread_rwlock_unlock(&gsfs_lock);
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,6 +187,8 @@ getmntany(FILE *fd __unused, struct mnttab *mgetp, struct mnttab *mrefp)
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
|
(void) pthread_rwlock_rdlock(&gsfs_lock);
|
||||||
|
|
||||||
for (i = 0; i < allfs; i++) {
|
for (i = 0; i < allfs; i++) {
|
||||||
if (mrefp->mnt_special != NULL &&
|
if (mrefp->mnt_special != NULL &&
|
||||||
strcmp(mrefp->mnt_special, gsfs[i].f_mntfromname) != 0) {
|
strcmp(mrefp->mnt_special, gsfs[i].f_mntfromname) != 0) {
|
||||||
|
@ -195,8 +203,10 @@ getmntany(FILE *fd __unused, struct mnttab *mgetp, struct mnttab *mrefp)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
statfs2mnttab(&gsfs[i], mgetp);
|
statfs2mnttab(&gsfs[i], mgetp);
|
||||||
|
(void) pthread_rwlock_unlock(&gsfs_lock);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
(void) pthread_rwlock_unlock(&gsfs_lock);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,9 +224,13 @@ getmntent(FILE *fp, struct mnttab *mp)
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
if (nfs >= allfs)
|
(void) pthread_rwlock_rdlock(&gsfs_lock);
|
||||||
|
if (nfs >= allfs) {
|
||||||
|
(void) pthread_rwlock_unlock(&gsfs_lock);
|
||||||
return (-1);
|
return (-1);
|
||||||
|
}
|
||||||
statfs2mnttab(&gsfs[nfs], mp);
|
statfs2mnttab(&gsfs[nfs], mp);
|
||||||
|
(void) pthread_rwlock_unlock(&gsfs_lock);
|
||||||
if (lseek(fileno(fp), 1, SEEK_CUR) == -1)
|
if (lseek(fileno(fp), 1, SEEK_CUR) == -1)
|
||||||
return (errno);
|
return (errno);
|
||||||
return (0);
|
return (0);
|
||||||
|
|
Loading…
Reference in New Issue