summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorRyan Moeller <[email protected]>2022-05-24 12:40:20 -0400
committerBrian Behlendorf <[email protected]>2022-05-27 09:19:37 -0700
commitfde66e583d9b9fc2c5ee53a1995157482ace35d3 (patch)
treef6bff20be55de80f5a6729724900acb8f067ea24 /lib
parented16dd763579baeca6b7bdc04c14fc9cd2902f4a (diff)
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 <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Ryan Moeller <[email protected]> Closes #13484
Diffstat (limited to 'lib')
-rw-r--r--lib/libspl/os/freebsd/mnttab.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/lib/libspl/os/freebsd/mnttab.c b/lib/libspl/os/freebsd/mnttab.c
index d830257fb..a240ca70b 100644
--- a/lib/libspl/os/freebsd/mnttab.c
+++ b/lib/libspl/os/freebsd/mnttab.c
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
#include <ctype.h>
#include <errno.h>
+#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -136,6 +137,7 @@ statfs2mnttab(struct statfs *sfs, struct mnttab *mp)
mp->mnt_mntopts = gmntopts;
}
+static pthread_rwlock_t gsfs_lock = PTHREAD_RWLOCK_INITIALIZER;
static struct statfs *gsfs = NULL;
static int allfs = 0;
@@ -145,6 +147,8 @@ statfs_init(void)
struct statfs *sfs;
int error;
+ (void) pthread_rwlock_wrlock(&gsfs_lock);
+
if (gsfs != NULL) {
free(gsfs);
gsfs = NULL;
@@ -162,6 +166,7 @@ statfs_init(void)
sfs = realloc(gsfs, allfs * sizeof (gsfs[0]));
if (sfs != NULL)
gsfs = sfs;
+ (void) pthread_rwlock_unlock(&gsfs_lock);
return (0);
fail:
error = errno;
@@ -169,6 +174,7 @@ fail:
free(gsfs);
gsfs = NULL;
allfs = 0;
+ (void) pthread_rwlock_unlock(&gsfs_lock);
return (error);
}
@@ -181,6 +187,8 @@ getmntany(FILE *fd __unused, struct mnttab *mgetp, struct mnttab *mrefp)
if (error != 0)
return (error);
+ (void) pthread_rwlock_rdlock(&gsfs_lock);
+
for (i = 0; i < allfs; i++) {
if (mrefp->mnt_special != NULL &&
strcmp(mrefp->mnt_special, gsfs[i].f_mntfromname) != 0) {
@@ -195,8 +203,10 @@ getmntany(FILE *fd __unused, struct mnttab *mgetp, struct mnttab *mrefp)
continue;
}
statfs2mnttab(&gsfs[i], mgetp);
+ (void) pthread_rwlock_unlock(&gsfs_lock);
return (0);
}
+ (void) pthread_rwlock_unlock(&gsfs_lock);
return (-1);
}
@@ -214,9 +224,13 @@ getmntent(FILE *fp, struct mnttab *mp)
if (error != 0)
return (error);
}
- if (nfs >= allfs)
+ (void) pthread_rwlock_rdlock(&gsfs_lock);
+ if (nfs >= allfs) {
+ (void) pthread_rwlock_unlock(&gsfs_lock);
return (-1);
+ }
statfs2mnttab(&gsfs[nfs], mp);
+ (void) pthread_rwlock_unlock(&gsfs_lock);
if (lseek(fileno(fp), 1, SEEK_CUR) == -1)
return (errno);
return (0);