diff options
Diffstat (limited to 'libglusterfsclient/src/libglusterfsclient.c')
-rwxr-xr-x | libglusterfsclient/src/libglusterfsclient.c | 156 |
1 files changed, 123 insertions, 33 deletions
diff --git a/libglusterfsclient/src/libglusterfsclient.c b/libglusterfsclient/src/libglusterfsclient.c index 7ef55393d90..24e73a82703 100755 --- a/libglusterfsclient/src/libglusterfsclient.c +++ b/libglusterfsclient/src/libglusterfsclient.c @@ -1330,46 +1330,96 @@ libgf_free_vmp_entry (struct vmp_entry *entry) FREE (entry); } -/* Returns the number of characters that match between an entry - * and the path. Assumes string1 is vmp entry. +int +libgf_count_path_components (char *path) +{ + int compos = 0; + char *pathdup = NULL; + int len = 0; + + if (!path) + return -1; + + pathdup = strdup (path); + if (!pathdup) + return -1; + + len = strlen (pathdup); + if (pathdup[len - 1] == '/') + pathdup[len - 1] = '\0'; + + path = pathdup; + while ((path = strchr (path, '/'))) { + compos++; + ++path; + } + + free (pathdup); + return compos; +} + +/* Returns the number of components that match between + * the VMP and the path. Assumes string1 is vmp entry. * Assumes both are absolute paths. */ int -libgf_strmatchcount (char *string1, int s1len, char *string2, int s2len) +libgf_strmatchcount (char *string1, char *string2) { - int i = 0; - int tosearch = 0; int matchcount = 0; + char *s1dup = NULL, *s2dup = NULL; + char *tok1 = NULL, *saveptr1 = NULL; + char *tok2 = NULL, *saveptr2 = NULL; - if (s1len <= s2len) - tosearch = s1len; - else - tosearch = s2len; + if ((!string1) || (!string2)) + return 0; - for (;i < tosearch; i++) { - if (string1[i] == string2[i]) - matchcount++; - else + s1dup = strdup (string1); + if (!s1dup) + return 0; + + s2dup = strdup (string2); + if (!s2dup) + goto free_s1; + + string1 = s1dup; + string2 = s2dup; + + tok1 = strtok_r(string1, "/", &saveptr1); + tok2 = strtok_r (string2, "/", &saveptr2); + while (tok1) { + if (!tok2) break; + + if (strcmp (tok1, tok2) != 0) + break; + + matchcount++; + tok1 = strtok_r(NULL, "/", &saveptr1); + tok2 = strtok_r (NULL, "/", &saveptr2); } + free (s2dup); +free_s1: + free (s1dup); return matchcount; } int libgf_vmp_entry_match (struct vmp_entry *entry, char *path) { - return libgf_strmatchcount (entry->vmp, (entry->vmplen - 1), path, - strlen(path)); + return libgf_strmatchcount (entry->vmp, path); } +#define LIBGF_VMP_EXACT 1 +#define LIBGF_VMP_LONGESTPREFIX 0 struct vmp_entry * -_libgf_vmp_search_entry (char *path) +_libgf_vmp_search_entry (char *path, int searchtype) { struct vmp_entry *entry = NULL; int matchcount = 0; struct vmp_entry *maxentry = NULL; int maxcount = 0; + int vmpcompcount = 0; if (vmplist.entries == 0) { gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "Virtual Mount Point " @@ -1379,17 +1429,56 @@ _libgf_vmp_search_entry (char *path) list_for_each_entry(entry, &vmplist.list, list) { matchcount = libgf_vmp_entry_match (entry, path); - if ((matchcount == (entry->vmplen - 1)) && - (matchcount > maxcount)) { + if (matchcount > maxcount) { maxcount = matchcount; maxentry = entry; } } + /* To ensure that the longest prefix matched entry is also an exact + * match, this is used to check whether duplicate entries are present + * in the vmplist. + */ + if ((searchtype == LIBGF_VMP_EXACT) && (maxentry)) { + vmpcompcount = libgf_count_path_components (maxentry->vmp); + if (vmpcompcount != matchcount) + maxentry = NULL; + } + out: return maxentry; } +/* Used to search for a exactly matching VMP entry. + */ +struct vmp_entry * +libgf_vmp_search_exact_entry (char *path) +{ + struct vmp_entry *entry = NULL; + + if (!path) + goto out; + + pthread_mutex_lock (&vmplock); + { + entry = _libgf_vmp_search_entry (path, LIBGF_VMP_EXACT); + } + pthread_mutex_unlock (&vmplock); + +out: + if (entry) + gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "VMP Entry found: path :%s" + " vmp: %s", path, entry->vmp); + else + gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "VMP Entry not found: path" + ": %s", path); + + return entry; +} + + +/* Used to search for a longest prefix matching VMP entry. + */ struct vmp_entry * libgf_vmp_search_entry (char *path) { @@ -1400,16 +1489,17 @@ libgf_vmp_search_entry (char *path) pthread_mutex_lock (&vmplock); { - entry = _libgf_vmp_search_entry (path); + entry = _libgf_vmp_search_entry (path, LIBGF_VMP_LONGESTPREFIX); } pthread_mutex_unlock (&vmplock); out: if (entry) - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "VMP Entry found: %s: %s", - path, entry->vmp); + gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "VMP Entry found: path :%s" + " vmp: %s", path, entry->vmp); else - gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "VMP Entry not found"); + gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "VMP Entry not found: path" + ": %s", path); return entry; } @@ -1424,16 +1514,16 @@ libgf_vmp_map_ghandle (char *vmp, glusterfs_handle_t *vmphandle) if (!vmpentry) goto out; - /* - FIXME: this is not thread-safe, but I couldn't find other place to - do initialization. - */ - if (vmplist.entries == 0) { - INIT_LIST_HEAD (&vmplist.list); - } + pthread_mutex_lock (&vmplock); + { + if (vmplist.entries == 0) { + INIT_LIST_HEAD (&vmplist.list); + } - list_add_tail (&vmpentry->list, &vmplist.list); - ++vmplist.entries; + list_add_tail (&vmpentry->list, &vmplist.list); + ++vmplist.entries; + } + pthread_mutex_unlock (&vmplock); ret = 0; out: @@ -1473,7 +1563,7 @@ glusterfs_mount (char *vmp, glusterfs_init_params_t *ipars) vmphash = (dev_t)ReallySimpleHash (vmp, strlen (vmp)); pthread_mutex_lock (&mountlock); { - vmp_entry = _libgf_vmp_search_entry (vmp); + vmp_entry = libgf_vmp_search_exact_entry (vmp); if (vmp_entry) { ret = 0; goto unlock; @@ -1506,7 +1596,7 @@ _libgf_umount (char *vmp) struct vmp_entry *entry= NULL; int ret = -1; - entry = _libgf_vmp_search_entry (vmp); + entry = libgf_vmp_search_exact_entry (vmp); if (entry == NULL) { gf_log ("libglusterfsclient", GF_LOG_ERROR, "path (%s) not mounted", vmp); |