summaryrefslogtreecommitdiffstats
path: root/libglusterfsclient
diff options
context:
space:
mode:
authorShehjar Tikoo <shehjart@gluster.com>2009-08-13 02:57:16 +0000
committerAnand V. Avati <avati@dev.gluster.com>2009-08-17 14:37:31 -0700
commite3a4b55920bf6620f5635a6785ae6f2eaf6eba2d (patch)
tree880cb0dbd9f61fb8a58807ad3d62234bc865fa5a /libglusterfsclient
parent53430bbd47dd61544e10596ca490e64cb2a4e85f (diff)
libglusterfsclient: Use components for VMP searches
Till now, we've been doing a character by character comparison between a given path and the VMP, to search for the glusterfs handle for the given path. This does not work for all cases and has been a known bug. This commit changes the byte-by-byte comparison into a more accurate component based comparison to fix search failures. Signed-off-by: Anand V. Avati <avati@dev.gluster.com> BUG: 209 (VMP parsing through fstab has issues) URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=209
Diffstat (limited to 'libglusterfsclient')
-rwxr-xr-xlibglusterfsclient/src/libglusterfsclient.c130
1 files changed, 109 insertions, 21 deletions
diff --git a/libglusterfsclient/src/libglusterfsclient.c b/libglusterfsclient/src/libglusterfsclient.c
index 7ef55393d90..1bf0db705c3 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,55 @@ _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: %s: %s",
+ path, entry->vmp);
+ else
+ gf_log (LIBGF_XL_NAME, GF_LOG_DEBUG, "VMP Entry not found");
+
+ return entry;
+}
+
+
+/* Used to search for a longest prefix matching VMP entry.
+ */
struct vmp_entry *
libgf_vmp_search_entry (char *path)
{
@@ -1400,7 +1488,7 @@ 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);
@@ -1473,7 +1561,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 +1594,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);