[Cluster-devel] cluster/group/gfs_controld lock_dlm.h recover.c

rpeterso at sourceware.org rpeterso at sourceware.org
Tue Dec 19 01:42:39 UTC 2006


CVSROOT:	/cvs/cluster
Module name:	cluster
Changes by:	rpeterso at sourceware.org	2006-12-19 01:42:38

Modified files:
	group/gfs_controld: lock_dlm.h recover.c 

Log message:
	Resolves: bz 218560: multiple mount points fail with gfs and gfs2

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/group/gfs_controld/lock_dlm.h.diff?cvsroot=cluster&r1=1.24&r2=1.25
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/group/gfs_controld/recover.c.diff?cvsroot=cluster&r1=1.24&r2=1.25

--- cluster/group/gfs_controld/lock_dlm.h	2006/12/05 22:19:17	1.24
+++ cluster/group/gfs_controld/lock_dlm.h	2006/12/19 01:42:37	1.25
@@ -113,6 +113,11 @@
         } \
 }
 
+struct mountpoint {
+	struct list_head	list;
+	char			dir[MAXNAME+1];
+};
+
 struct mountgroup {
 	struct list_head	list;
 	uint32_t		id;
@@ -124,7 +129,7 @@
 	char			name[MAXNAME+1];
 	char			table[MAXNAME+1];
 	char			type[5];
-	char			dir[PATH_MAX+1];
+	struct list_head mntpoints;
 	char			options[MAX_OPTIONS_LEN+1];
 	char			dev[PATH_MAX+1];
 
--- cluster/group/gfs_controld/recover.c	2006/12/05 22:19:17	1.24
+++ cluster/group/gfs_controld/recover.c	2006/12/19 01:42:37	1.25
@@ -28,6 +28,8 @@
 void start_spectator_init_2(struct mountgroup *mg);
 void start_spectator_2(struct mountgroup *mg);
 void notify_mount_client(struct mountgroup *mg);
+int do_finish(struct mountgroup *mg);
+int do_terminate(struct mountgroup *mg);
 
 int set_sysfs(struct mountgroup *mg, char *field, int val)
 {
@@ -1468,10 +1470,13 @@
 struct mountgroup *find_mg_dir(char *dir)
 {
 	struct mountgroup *mg;
+	struct mountpoint *mt_point;
 
 	list_for_each_entry(mg, &mounts, list) {
-		if (!strcmp(mg->dir, dir))
-			return mg;
+		list_for_each_entry(mt_point, &mg->mntpoints, list) {
+			if (!strcmp(mt_point->dir, dir))
+				return mg;
+		}
 	}
 	return NULL;
 }
@@ -1496,7 +1501,8 @@
 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, *new_mg = NULL;
+	struct mountpoint *mp;
 	char table2[MAXLINE];
 	char *cluster = NULL, *name = NULL;
 	int rv;
@@ -1538,24 +1544,33 @@
 		goto fail;
 	}
 
-	mg = find_mg(name);
-	if (mg) {
-		rv = -EEXIST;
+	/* Allocate and populate a new mountpoint entry */
+	mp = malloc(sizeof(struct mountpoint));
+	if (!mp) {
+		rv = -ENOMEM;
 		goto fail;
 	}
+	strncpy(mp->dir, dir, sizeof(mp->dir));
 
-	mg = create_mg(name);
+	/* Check if we already have a mount group or need a new one */
+	mg = find_mg(name);
 	if (!mg) {
-		rv = -ENOMEM;
-		goto fail;
+		mg = new_mg = create_mg(name);
+		if (!mg) {
+			free(mp);
+			rv = -ENOMEM;
+			goto fail;
+		}
+		strncpy(mg->type, type, sizeof(mg->type));
+		strncpy(mg->table, table, sizeof(mg->table));
+		strncpy(mg->options, options, sizeof(mg->options));
+		strncpy(mg->dev, dev, sizeof(mg->dev));
+		INIT_LIST_HEAD(&mg->mntpoints);
 	}
 
 	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));
-	strncpy(mg->dev, dev, sizeof(mg->dev));
+	/* Add the mount point to the list in the mountgroup. */
+	list_add(&mp->list, &mg->mntpoints);
 
 	if (strlen(cluster) != strlen(clustername) ||
 	    strlen(cluster) == 0 || strcmp(cluster, clustername)) {
@@ -1566,38 +1581,42 @@
 	} else
 		log_group(mg, "cluster name matches: %s", clustername);
 
-	if (strstr(options, "spectator")) {
-		log_group(mg, "spectator mount");
-		mg->spectator = 1;
-	} else {
-		if (!we_are_in_fence_domain()) {
-			rv = -EINVAL;
-			log_error("mount: not in default fence domain");
-			goto fail;
+	if (new_mg) {
+		if (strstr(options, "spectator")) {
+			log_group(mg, "spectator mount");
+			mg->spectator = 1;
+		} else {
+			if (!we_are_in_fence_domain()) {
+				rv = -EINVAL;
+				log_error("mount: not in default fence domain");
+				goto fail;
+			}
+		}
+
+		if (!mg->spectator && strstr(options, "rw"))
+			mg->rw = 1;
+		else if (strstr(options, "ro")) {
+			if (mg->spectator) {
+				rv = -EINVAL;
+				log_error("mount: readonly invalid with spectator");
+				goto fail;
+			}
+			mg->readonly = 1;
 		}
-	}
 
-	if (!mg->spectator && strstr(options, "rw"))
-		mg->rw = 1;
-	else if (strstr(options, "ro")) {
-		if (mg->spectator) {
+		if (strlen(options) > MAX_OPTIONS_LEN-1) {
 			rv = -EINVAL;
-			log_error("mount: readonly invalid with spectator");
+			log_error("mount: options too long %d", strlen(options));
 			goto fail;
 		}
-		mg->readonly = 1;
+		list_add(&mg->list, &mounts);
 	}
-
-	if (strlen(options) > MAX_OPTIONS_LEN-1) {
-		rv = -EINVAL;
-		log_error("mount: options too long %d", strlen(options));
-		goto fail;
-	}
-
-	list_add(&mg->list, &mounts);
 	*mg_ret = mg;
 
-	group_join(gh, name);
+	if (new_mg)
+		group_join(gh, name);
+	else
+		notify_mount_client(mg);
 	return 0;
 
  fail:
@@ -1883,14 +1902,27 @@
 int do_unmount(int ci, char *dir, int mnterr)
 {
 	struct mountgroup *mg;
+	struct mountpoint *mt_point, *safe;
 
 	list_for_each_entry(mg, &withdrawn_mounts, list) {
-		if (!strcmp(mg->dir, dir)) {
+		int is_withdrawn = FALSE;
+
+		list_for_each_entry(mt_point, &mg->mntpoints, list) {
+			if (!strcmp(mt_point->dir, dir)) {
+				is_withdrawn = TRUE;
+				break;
+			}
+		}
+		if (is_withdrawn) {
+			list_for_each_entry_safe(mt_point, safe, &mg->mntpoints, list) {
+				list_del(&mt_point->list);
+				free(mt_point);
+			}
 			log_group(mg, "unmount withdrawn fs");
 			list_del(&mg->list);
 			free(mg);
-			return 0;
 		}
+		return 0;
 	}
 
 	mg = find_mg_dir(dir);
@@ -1910,7 +1942,6 @@
 			mg->kernel_mount_error = mnterr;
 			mg->kernel_mount_done = 1;
 		}
-		goto out;
 	}
 
 	if (mg->withdraw) {
@@ -1918,16 +1949,26 @@
 		return -1;
 	}
 
+	/* Delete this mount point out of the list */
+	list_for_each_entry(mt_point, &mg->mntpoints, list) {
+		if (!strcmp(mt_point->dir, dir)) {
+			list_del(&mt_point->list);
+			free(mt_point);
+			break;
+		}
+	}
 	/* 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. */
 
-	if (need_kernel_recovery_done(mg)) {
+	if (!mg->kernel_mount_error &&
+		list_empty(&mg->mntpoints) && need_kernel_recovery_done(mg)) {
 		log_group(mg, "do_unmount: fill in start_done");
 		start_done(mg);
 	}
- out:
-	group_leave(gh, mg->name);
+
+	if (list_empty(&mg->mntpoints))
+		group_leave(gh, mg->name);
 	return 0;
 }
 




More information about the Cluster-devel mailing list