summaryrefslogtreecommitdiffstats
path: root/libglusterfsclient/src/libglusterfsclient.c
diff options
context:
space:
mode:
Diffstat (limited to 'libglusterfsclient/src/libglusterfsclient.c')
-rwxr-xr-xlibglusterfsclient/src/libglusterfsclient.c156
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);