Skip to content

Commit

Permalink
FreeBSD: libspl: Add locking around statfs globals
Browse files Browse the repository at this point in the history
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 openzfs#13484
  • Loading branch information
Ryan Moeller authored and andrewc12 committed Sep 23, 2022
1 parent f987374 commit e596c1b
Showing 1 changed file with 15 additions and 1 deletion.
16 changes: 15 additions & 1 deletion lib/libspl/os/freebsd/mnttab.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");

#include <ctype.h>
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Expand Down Expand Up @@ -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;

Expand All @@ -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;
Expand All @@ -162,13 +166,15 @@ 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;
if (gsfs != NULL)
free(gsfs);
gsfs = NULL;
allfs = 0;
(void) pthread_rwlock_unlock(&gsfs_lock);
return (error);
}

Expand All @@ -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) {
Expand All @@ -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);
}

Expand All @@ -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);
Expand Down

0 comments on commit e596c1b

Please sign in to comment.