[Cluster-devel] [PATCH 1/3] libgfs2: Add lgfs2_open_mnt* functions
Steven Whitehouse
swhiteho at redhat.com
Mon Nov 18 10:04:53 UTC 2013
Hi,
That looks much better I than what we had before I think. Thanks for
sorting that out,
Steve.
On Sat, 2013-11-16 at 20:11 +0000, Andrew Price wrote:
> lgfs2_open_mnt is a replacement for is_pathname_mounted which tries to reduce
> races by opening paths speculatively and passing back the open fds once they're
> known to be correct. lgfs2_open_mnt_{dev,dir} build on this to provide a
> convenient way to open just the device or mount directory relating to a path
> which could be either.
>
> Signed-off-by: Andrew Price <anprice at redhat.com>
> ---
> gfs2/libgfs2/libgfs2.h | 4 +++
> gfs2/libgfs2/misc.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 98 insertions(+)
>
> diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
> index f864a08..3e5d09c 100644
> --- a/gfs2/libgfs2/libgfs2.h
> +++ b/gfs2/libgfs2/libgfs2.h
> @@ -12,6 +12,7 @@
> #include <linux/limits.h>
> #include <endian.h>
> #include <byteswap.h>
> +#include <mntent.h>
>
> #include <linux/gfs2_ondisk.h>
> #include "osi_list.h"
> @@ -715,6 +716,9 @@ extern int compute_heightsize(struct gfs2_sbd *sdp, uint64_t *heightsize,
> uint32_t *maxheight, uint32_t bsize1, int diptrs, int inptrs);
> extern int compute_constants(struct gfs2_sbd *sdp);
> extern int is_pathname_mounted(char *path_name, char *device_name, int *ro_mount);
> +extern int lgfs2_open_mnt(const char *path, int dirflags, int *dirfd, int devflags, int *devfd, struct mntent **mnt);
> +extern int lgfs2_open_mnt_dev(const char *path, int flags, struct mntent **mnt);
> +extern int lgfs2_open_mnt_dir(const char *path, int flags, struct mntent **mnt);
> extern int find_gfs2_meta(struct gfs2_sbd *sdp);
> extern int dir_exists(const char *dir);
> extern int mount_gfs2_meta(struct gfs2_sbd *sdp);
> diff --git a/gfs2/libgfs2/misc.c b/gfs2/libgfs2/misc.c
> index 7f500e6..195b983 100644
> --- a/gfs2/libgfs2/misc.c
> +++ b/gfs2/libgfs2/misc.c
> @@ -163,6 +163,100 @@ int is_pathname_mounted(char *path_name, char *device_name, int *ro_mount)
> return 1; /* mounted */
> }
>
> +/* Returns 0 if fd1 and fd2 refer to the same device/file, 1 otherwise, or -1 on error */
> +static int fdcmp(int fd1, int fd2)
> +{
> + struct stat st1, st2;
> + if ((fstat(fd1, &st1) != 0) || (fstat(fd2, &st2) != 0))
> + return -1;
> + if (S_ISBLK(st1.st_mode) && S_ISBLK(st2.st_mode)) {
> + if (st1.st_rdev == st2.st_rdev) {
> + return 0;
> + }
> + } else if ((st1.st_dev == st2.st_dev) && (st1.st_ino == st2.st_ino)) {
> + return 0;
> + }
> + return 1;
> +}
> +
> +int lgfs2_open_mnt(const char *path, int dirflags, int *dirfd, int devflags, int *devfd, struct mntent **mnt)
> +{
> + FILE *fp = setmntent("/proc/mounts", "r");
> + if (fp == NULL) {
> + perror("open: /proc/mounts");
> + return 1;
> + }
> + /* Assume path is mount point until we know better. */
> + *dirfd = open(path, dirflags);
> + if (*dirfd < 0)
> + return 1;
> +
> + while ((*mnt = getmntent(fp)) != NULL) {
> + int fd;
> + if (strcmp((*mnt)->mnt_type, "gfs2") != 0)
> + continue;
> + *devfd = open((*mnt)->mnt_fsname, devflags);
> + /* Defer checking *devfd until later: whether it's ok to ignore
> + * the error depends on whether we find the mount point. */
> +
> + if (strcmp(path, (*mnt)->mnt_dir) == 0)
> + break;
> + if (strcmp(path, (*mnt)->mnt_fsname) == 0 || fdcmp(*dirfd, *devfd) == 0) {
> + /* We have a match but our above assumption was
> + incorrect and *dirfd is actually the device. */
> + close(*dirfd);
> + *dirfd = open((*mnt)->mnt_dir, dirflags);
> + break;
> + }
> +
> + fd = open((*mnt)->mnt_dir, dirflags);
> + if (fd >= 0) {
> + int diff = fdcmp(*dirfd, fd);
> + close(fd);
> + if (diff == 0)
> + break;
> + }
> + if (*devfd >= 0)
> + close(*devfd);
> + }
> + endmntent(fp);
> + if (*mnt == NULL) {
> + close(*dirfd);
> + return 0; /* Success. Answer is no. Both fds closed. */
> + }
> + if (*dirfd < 0) {
> + close(*devfd);
> + return 1;
> + }
> + if (*devfd < 0) {
> + close(*dirfd);
> + return 1;
> + }
> + return 0; /* Success. Answer is yes. Both fds open. */
> +}
> +
> +int lgfs2_open_mnt_dev(const char *path, int flags, struct mntent **mnt)
> +{
> + int dirfd = -1;
> + int devfd = -1;
> + if (lgfs2_open_mnt(path, O_RDONLY, &dirfd, flags, &devfd, mnt) != 0)
> + return -1;
> + if (*mnt != NULL)
> + close(dirfd);
> + return devfd;
> +}
> +
> +int lgfs2_open_mnt_dir(const char *path, int flags, struct mntent **mnt)
> +{
> + int dirfd = -1;
> + int devfd = -1;
> + if (lgfs2_open_mnt(path, flags, &dirfd, O_RDONLY, &devfd, mnt) != 0)
> + return -1;
> + if (*mnt != NULL)
> + close(devfd);
> + return dirfd;
> +}
> +
> static int lock_for_admin(struct gfs2_sbd *sdp)
> {
> int error;
More information about the Cluster-devel
mailing list