diff options
author | Steve Dickson <steved@redhat.com> | 2012-03-12 13:17:15 -0400 |
---|---|---|
committer | Steve Dickson <steved@redhat.com> | 2012-03-12 15:12:06 -0400 |
commit | 36931bf93d4316608c0f5935cf489c9b3d15e921 (patch) | |
tree | 8e826b2642de609d21684eedffddf27c1665c391 /utils/exportfs | |
parent | bc3c8b3496598b6f7a2d0692f3351c3704cb4b9d (diff) | |
download | nfs-utils-36931bf93d4316608c0f5935cf489c9b3d15e921.tar.gz nfs-utils-36931bf93d4316608c0f5935cf489c9b3d15e921.tar.xz nfs-utils-36931bf93d4316608c0f5935cf489c9b3d15e921.zip |
exportfs: Stop racing exportfs on clusters
This problem can occur when multiple cluster services fail over
at the same time, causing missing high-available exports.
Having a lot of nfs-exports will trigger this issue easier.
https://bugzilla.linux-nfs.org/show_bug.cgi?id=224
Signed-off-by: Steve Dickson <steved@redhat.com>
Diffstat (limited to 'utils/exportfs')
-rw-r--r-- | utils/exportfs/exportfs.c | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c index 7432a65..7326802 100644 --- a/utils/exportfs/exportfs.c +++ b/utils/exportfs/exportfs.c @@ -16,6 +16,7 @@ #include <sys/stat.h> #include <sys/vfs.h> #include <sys/stat.h> +#include <sys/file.h> #include <unistd.h> #include <stdbool.h> #include <stdlib.h> @@ -44,6 +45,39 @@ static void validate_export(nfs_export *exp); static int matchhostname(const char *hostname1, const char *hostname2); static void export_d_read(const char *dname); +static const char *lockfile = EXP_LOCKFILE; +static int _lockfd = -1; + +/* + * If we aren't careful, changes made by exportfs can be lost + * when multiple exports process run at once: + * + * exportfs process 1 exportfs process 2 + * ------------------------------------------ + * reads etab version A reads etab version A + * adds new export B adds new export C + * writes A+B writes A+C + * + * The locking in support/export/xtab.c will prevent mountd from + * seeing a partially written version of etab, and will prevent + * the two writers above from writing simultaneously and + * corrupting etab, but to prevent problems like the above we + * need these additional lockfile() routines. + */ +void +grab_lockfile() +{ + _lockfd = open(lockfile, O_CREAT|O_RDWR, 0666); + if (_lockfd != -1) + lockf(_lockfd, F_LOCK, 0); +} +void +release_lockfile() +{ + if (_lockfd != -1) + lockf(_lockfd, F_ULOCK, 0); +} + int main(int argc, char **argv) { @@ -129,6 +163,13 @@ main(int argc, char **argv) return 0; } } + + /* + * Serialize things as best we can + */ + grab_lockfile(); + atexit(release_lockfile); + if (f_export && ! f_ignore) { export_read(_PATH_EXPORTS); export_d_read(_PATH_EXPORTS_D); |