From: teigland@sourceware.org <teigland@sourceware.org>
To: cluster-devel.redhat.com
Subject: [Cluster-devel] cluster/group/gfs_controld lock_dlm.h main.c r ...
Date: 20 Dec 2006 19:13:14 -0000 [thread overview]
Message-ID: <20061220191314.3845.qmail@sourceware.org> (raw)
CVSROOT: /cvs/cluster
Module name: cluster
Changes by: teigland at sourceware.org 2006-12-20 19:13:13
Modified files:
group/gfs_controld: lock_dlm.h main.c recover.c
Log message:
Support mounting a single fs on multiple mount points.
bz 218560
Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/group/gfs_controld/lock_dlm.h.diff?cvsroot=cluster&r1=1.26&r2=1.27
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/group/gfs_controld/main.c.diff?cvsroot=cluster&r1=1.27&r2=1.28
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/group/gfs_controld/recover.c.diff?cvsroot=cluster&r1=1.27&r2=1.28
--- cluster/group/gfs_controld/lock_dlm.h 2006/12/19 17:05:59 1.26
+++ cluster/group/gfs_controld/lock_dlm.h 2006/12/20 19:13:13 1.27
@@ -113,6 +113,12 @@
} \
}
+struct mountpoint {
+ struct list_head list;
+ char dir[PATH_MAX+1];
+ int client;
+};
+
struct mountgroup {
struct list_head list;
uint32_t id;
@@ -120,11 +126,11 @@
struct list_head members_gone;
int memb_count;
struct list_head resources; /* for plocks */
+ struct list_head mountpoints;
char name[MAXNAME+1];
char table[MAXNAME+1];
char type[5];
- char dir[PATH_MAX+1];
char options[MAX_OPTIONS_LEN+1];
char dev[PATH_MAX+1];
@@ -280,7 +286,7 @@
int kernel_recovery_done(char *name);
void ping_kernel_mount(char *table);
void save_message(struct mountgroup *mg, char *buf, int len, int from, int type);
-void got_mount_result(struct mountgroup *mg, int result);
+void got_mount_result(struct mountgroup *mg, int result, int ci, int another);
int client_send(int ci, char *buf, int len);
--- cluster/group/gfs_controld/main.c 2006/12/05 22:19:17 1.27
+++ cluster/group/gfs_controld/main.c 2006/12/20 19:13:13 1.28
@@ -21,6 +21,7 @@
int fd;
char type[32];
struct mountgroup *mg;
+ int another_mount;
};
static int client_maxi;
@@ -298,14 +299,15 @@
argv[6], &mg);
fd = client[ci].fd;
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
- if (!rv) {
+ if (!rv || rv == -EALREADY) {
+ client[ci].another_mount = rv;
client[ci].mg = mg;
mg->mount_client_fd = fd;
}
goto reply;
} else if (!strcmp(cmd, "mount_result")) {
- got_mount_result(client[ci].mg, atoi(argv[3]));
-
+ got_mount_result(client[ci].mg, atoi(argv[3]), ci,
+ client[ci].another_mount);
} else if (!strcmp(cmd, "leave")) {
rv = do_unmount(ci, argv[1], atoi(argv[3]));
goto reply;
--- cluster/group/gfs_controld/recover.c 2006/12/19 22:19:01 1.27
+++ cluster/group/gfs_controld/recover.c 2006/12/20 19:13:13 1.28
@@ -1430,23 +1430,36 @@
}
}
-struct mountgroup *create_mg(char *name)
+struct mountgroup *create_mg(char *name, char *dir)
{
struct mountgroup *mg;
+ struct mountpoint *mp;
mg = malloc(sizeof(struct mountgroup));
+ if (!mg)
+ return NULL;
memset(mg, 0, sizeof(struct mountgroup));
INIT_LIST_HEAD(&mg->members);
INIT_LIST_HEAD(&mg->members_gone);
INIT_LIST_HEAD(&mg->resources);
INIT_LIST_HEAD(&mg->saved_messages);
+ INIT_LIST_HEAD(&mg->mountpoints);
mg->init = 1;
mg->master_nodeid = -1;
mg->low_nodeid = -1;
strncpy(mg->name, name, MAXNAME);
+ mp = malloc(sizeof(struct mountpoint));
+ if (!mp) {
+ free(mg);
+ return NULL;
+ }
+ memset(mp, 0, sizeof(struct mountpoint));
+ strncpy(mp->dir, dir, sizeof(mp->dir));
+ list_add(&mp->list, &mg->mountpoints);
+
return mg;
}
@@ -1473,12 +1486,23 @@
return NULL;
}
+struct mountpoint *find_mountpoint(struct mountgroup *mg, char *dir)
+{
+ struct mountpoint *mp;
+
+ list_for_each_entry(mp, &mg->mountpoints, list) {
+ if (!strcmp(mp->dir, dir))
+ return mp;
+ }
+ return NULL;
+}
+
struct mountgroup *find_mg_dir(char *dir)
{
struct mountgroup *mg;
list_for_each_entry(mg, &mounts, list) {
- if (!strcmp(mg->dir, dir))
+ if (find_mountpoint(mg, dir))
return mg;
}
return NULL;
@@ -1501,10 +1525,54 @@
return 0;
}
+int add_another_mountpoint(struct mountgroup *mg, char *dir, char *dev, int ci)
+{
+ struct mountpoint *mp;
+
+ log_group(mg, "add_another_mountpoint dir %s dev %s ci %d",
+ dir, dev, ci);
+
+ /* check if this is the same fs mounted on another dir or a different
+ fs with the same name (which is an error) */
+
+ if (strcmp(mg->dev, dev)) {
+ log_group(mg, "different fs dev %s with same name", mg->dev);
+ return -EINVAL;
+ }
+
+ if (find_mountpoint(mg, dir)) {
+ log_group(mg, "mount point %s already used", dir);
+ return -EBUSY;
+ }
+
+ /* we only really need to check one of these */
+ if (mg->mount_client || mg->mount_client_fd || !mg->kernel_mount_done) {
+ log_group(mg, "other mount in progress client %d fd %d done %d",
+ mg->mount_client, mg->mount_client_fd,
+ mg->kernel_mount_done);
+ return -EBUSY;
+ }
+
+ mp = malloc(sizeof(struct mountpoint));
+ if (!mp)
+ return -ENOMEM;
+
+ memset(mp, 0, sizeof(struct mountpoint));
+ strncpy(mp->dir, dir, sizeof(mp->dir));
+ list_add(&mp->list, &mg->mountpoints);
+ mg->mount_client = ci;
+
+ /* we return this special error to mount.gfs which mount.gfs will
+ recognize as meaning the fs is already mounted, so it shouldn't
+ read any hostdata from us, but just go ahead and mount(2) */
+
+ return -EALREADY;
+}
+
int do_mount(int ci, char *dir, char *type, char *proto, char *table,
char *options, char *dev, struct mountgroup **mg_ret)
{
- struct mountgroup *mg;
+ struct mountgroup *mg = NULL;
char table2[MAXLINE];
char *cluster = NULL, *name = NULL;
int rv;
@@ -1515,7 +1583,7 @@
if (strcmp(proto, "lock_dlm")) {
log_error("mount: lockproto %s not supported", proto);
rv = -EINVAL;
- goto fail;
+ goto out;
}
if (strstr(options, "jid=") ||
@@ -1523,7 +1591,7 @@
strstr(options, "id=")) {
log_error("mount: jid, first and id are reserved options");
rv = -EINVAL;
- goto fail;
+ goto out;
}
/* table is <cluster>:<name> */
@@ -1534,7 +1602,7 @@
name = strstr(table2, ":");
if (!name) {
rv = -EINVAL;
- goto fail;
+ goto out;
}
*name = '\0';
@@ -1543,23 +1611,22 @@
if (strlen(name) > MAXNAME) {
rv = -ENAMETOOLONG;
- goto fail;
+ goto out;
}
mg = find_mg(name);
if (mg) {
- rv = -EEXIST;
- goto fail;
+ rv = add_another_mountpoint(mg, dir, dev, ci);
+ goto out;
}
- mg = create_mg(name);
+ mg = create_mg(name, dir);
if (!mg) {
rv = -ENOMEM;
- goto fail;
+ goto out;
}
mg->mount_client = ci;
- strncpy(mg->dir, dir, sizeof(mg->dir));
strncpy(mg->type, type, sizeof(mg->type));
strncpy(mg->table, table, sizeof(mg->table));
strncpy(mg->options, options, sizeof(mg->options));
@@ -1570,7 +1637,7 @@
rv = -1;
log_error("mount: fs requires cluster=\"%s\" current=\"%s\"",
cluster, clustername);
- goto fail;
+ goto out;
} else
log_group(mg, "cluster name matches: %s", clustername);
@@ -1581,7 +1648,7 @@
if (!we_are_in_fence_domain()) {
rv = -EINVAL;
log_error("mount: not in default fence domain");
- goto fail;
+ goto out;
}
}
@@ -1591,7 +1658,7 @@
if (mg->spectator) {
rv = -EINVAL;
log_error("mount: readonly invalid with spectator");
- goto fail;
+ goto out;
}
mg->readonly = 1;
}
@@ -1599,17 +1666,15 @@
if (strlen(options) > MAX_OPTIONS_LEN-1) {
rv = -EINVAL;
log_error("mount: options too long %d", strlen(options));
- goto fail;
+ goto out;
}
list_add(&mg->list, &mounts);
- *mg_ret = mg;
-
group_join(gh, name);
- return 0;
-
- fail:
- log_error("mount: failed %d", rv);
+ rv = 0;
+ out:
+ *mg_ret = mg;
+ log_group(mg, "do_mount: rv %d", rv);
return rv;
}
@@ -1891,14 +1956,20 @@
int do_unmount(int ci, char *dir, int mnterr)
{
struct mountgroup *mg;
+ struct mountpoint *mp;
list_for_each_entry(mg, &withdrawn_mounts, list) {
- if (!strcmp(mg->dir, dir)) {
- log_group(mg, "unmount withdrawn fs");
+ mp = find_mountpoint(mg, dir);
+ if (!mp)
+ continue;
+ log_group(mg, "unmount %s for withdrawn fs", dir);
+ list_del(&mp->list);
+ free(mp);
+ if (list_empty(&mg->mountpoints)) {
list_del(&mg->list);
free(mg);
- return 0;
}
+ return 0;
}
mg = find_mg_dir(dir);
@@ -1922,10 +1993,27 @@
}
if (mg->withdraw) {
- log_error("do_unmount: fs on %s is withdrawing", dir);
+ log_error("%s do_unmount: fs on %s is withdrawing",
+ mg->name, dir);
+ return -1;
+ }
+
+ if (!mg->kernel_mount_done) {
+ log_error("%s do_unmount: fs on %s is still mounting",
+ mg->name, dir);
return -1;
}
+ mp = find_mountpoint(mg, dir);
+ ASSERT(mp);
+ list_del(&mp->list);
+ free(mp);
+
+ if (!list_empty(&mg->mountpoints)) {
+ log_group(mg, "removed mountpoint %s, more remaining", dir);
+ return 0;
+ }
+
/* Check to see if we're waiting for a kernel recovery_done to do a
start_done(). If so, call the start_done() here because we won't be
getting anything else from gfs-kernel which is now gone. */
@@ -1934,6 +2022,7 @@
log_group(mg, "do_unmount: fill in start_done");
start_done(mg);
}
+
out:
group_leave(gh, mg->name);
return 0;
@@ -1972,8 +2061,6 @@
if (rv < 0)
log_error("notify_mount_client: send failed %d", rv);
- mg->mount_client = 0;
-
if (error) {
log_group(mg, "leaving due to mount error: %s", mg->error_msg);
if (memb->finished)
@@ -2003,14 +2090,42 @@
log_group(mg, "ping_kernel_mount %d", rv);
}
-void got_mount_result(struct mountgroup *mg, int result)
+/* remove the mountpoint that this client added */
+void remove_failed_mountpoint(struct mountgroup *mg, int ci)
+{
+ struct mountpoint *mp;
+ int found = 0;
+
+ list_for_each_entry(mp, &mg->mountpoints, list) {
+ if (mp->client == ci) {
+ list_del(&mp->list);
+ free(mp);
+ found = 1;
+ break;
+ }
+ }
+ ASSERT(found);
+ ASSERT(!list_empty(&mg->mountpoints));
+}
+
+void got_mount_result(struct mountgroup *mg, int result, int ci, int another)
{
struct mg_member *memb;
memb = find_memb_nodeid(mg, our_nodeid);
- log_group(mg, "mount_result: kernel_mount_error %d first_mounter %d "
- "opts %x", result, mg->first_mounter, memb->opts);
+ log_group(mg, "got_mount_result: ci %d result %d another %d "
+ "first_mounter %d opts %x",
+ ci, result, another, mg->first_mounter, memb->opts);
+
+ mg->mount_client = 0;
+ mg->mount_client_fd = 0;
+
+ if (another) {
+ if (result)
+ remove_failed_mountpoint(mg, ci);
+ return;
+ }
mg->kernel_mount_done = 1;
mg->kernel_mount_error = result;
next reply other threads:[~2006-12-20 19:13 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-12-20 19:13 teigland [this message]
-- strict thread matches above, loose matches on Subject: below --
2006-12-20 19:16 [Cluster-devel] cluster/group/gfs_controld lock_dlm.h main.c r teigland
2006-12-20 19:14 teigland
2006-12-05 22:24 teigland
2006-12-05 22:24 teigland
2006-12-05 22:19 teigland
2006-07-20 20:19 teigland
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20061220191314.3845.qmail@sourceware.org \
--to=teigland@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.