summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNiels de Vos <ndevos@redhat.com>2013-03-15 10:34:45 +0100
committerVijay Bellur <vbellur@redhat.com>2013-08-02 02:14:09 -0700
commitc95db3046c672473611d9ac0ab6cd93bd8211347 (patch)
tree072bfcd45c8c86fec44fce6bd443532c6184300f
parent423aa0d57a031e865374d18cdcc489273317d785 (diff)
store: Add (un)locking functionality
Some configuration/cache files (like the NFS rmtab) can be stored on a GlusterFS volume and be used by multiple storage servers. This requires suitable locking for the gf_store_handle_t structure. Introduce gf_store_lock() and gf_store_unlock() for this purpose. The gf_store_locked_local() function can be used to check if the gf_store_handle_t has been locked by the current process. This change also includes an unrelated correction where a FILE* was getting leaked. Krishnan Parthasarathi identified this while reviewing the new locking functionality. Change-Id: I431b7510801841d4bad64480b4bb99d87e2ad347 BUG: 904065 Signed-off-by: Niels de Vos <ndevos@redhat.com> Reviewed-on: http://review.gluster.org/4677 Reviewed-by: Rajesh Joseph <rjoseph@redhat.com> Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Vijay Bellur <vbellur@redhat.com>
-rw-r--r--libglusterfs/src/store.c67
-rw-r--r--libglusterfs/src/store.h10
2 files changed, 73 insertions, 4 deletions
diff --git a/libglusterfs/src/store.c b/libglusterfs/src/store.c
index 8642538cefa..621146bea67 100644
--- a/libglusterfs/src/store.c
+++ b/libglusterfs/src/store.c
@@ -221,7 +221,12 @@ gf_store_retrieve_value (gf_store_handle_t *handle, char *key, char **value)
GF_ASSERT (handle);
- handle->fd = open (handle->path, O_RDWR);
+ if (handle->locked == F_ULOCK)
+ /* no locking is used handle->fd gets closed() after usage */
+ handle->fd = open (handle->path, O_RDWR);
+ else
+ /* handle->fd is valid already, kept open for lockf() */
+ lseek (handle->fd, 0, SEEK_SET);
if (handle->fd == -1) {
gf_log ("", GF_LOG_ERROR, "Unable to open file %s errno: %s",
@@ -229,7 +234,9 @@ gf_store_retrieve_value (gf_store_handle_t *handle, char *key, char **value)
goto out;
}
if (!handle->read)
- handle->read = fdopen (handle->fd, "r");
+ handle->read = fdopen (dup(handle->fd), "r");
+ else
+ fseek (handle->read, 0, SEEK_SET);
if (!handle->read) {
gf_log ("", GF_LOG_ERROR, "Unable to open file %s errno: %s",
@@ -278,11 +285,16 @@ gf_store_retrieve_value (gf_store_handle_t *handle, char *key, char **value)
}
} while (1);
out:
- if (handle->fd > 0) {
- close (handle->fd);
+ if (handle->read) {
+ fclose (handle->read);
handle->read = NULL;
}
+ if (handle->fd > 0 && handle->locked == F_ULOCK) {
+ /* only invalidate handle->fd if not locked */
+ close (handle->fd);
+ }
+
GF_FREE (free_str);
return ret;
@@ -366,6 +378,7 @@ gf_store_handle_new (char *path, gf_store_handle_t **handle)
goto out;
shandle->path = spath;
+ shandle->locked = F_ULOCK;
*handle = shandle;
ret = 0;
@@ -630,3 +643,49 @@ gf_store_strerror (gf_store_op_errno_t op_errno)
}
return "Invalid errno";
}
+
+int
+gf_store_lock (gf_store_handle_t *sh)
+{
+ int ret;
+
+ GF_ASSERT (sh);
+ GF_ASSERT (sh->path);
+ GF_ASSERT (sh->locked == F_ULOCK);
+
+ sh->fd = open (sh->path, O_RDWR);
+ if (sh->fd == -1) {
+ gf_log ("", GF_LOG_ERROR, "Failed to open '%s': %s", sh->path,
+ strerror (errno));
+ return -1;
+ }
+
+ ret = lockf (sh->fd, F_LOCK, 0);
+ if (ret)
+ gf_log ("", GF_LOG_ERROR, "Failed to gain lock on '%s': %s",
+ sh->path, strerror (errno));
+ else
+ /* sh->locked is protected by the lockf(sh->fd) above */
+ sh->locked = F_LOCK;
+
+ return ret;
+}
+
+void
+gf_store_unlock (gf_store_handle_t *sh)
+{
+ GF_ASSERT (sh);
+ GF_ASSERT (sh->locked == F_LOCK);
+
+ sh->locked = F_ULOCK;
+ lockf (sh->fd, F_ULOCK, 0);
+ close (sh->fd);
+}
+
+int
+gf_store_locked_local (gf_store_handle_t *sh)
+{
+ GF_ASSERT (sh);
+
+ return (sh->locked == F_LOCK);
+}
diff --git a/libglusterfs/src/store.h b/libglusterfs/src/store.h
index 4fe432e56de..337103ff73e 100644
--- a/libglusterfs/src/store.h
+++ b/libglusterfs/src/store.h
@@ -21,6 +21,7 @@ struct gf_store_handle_ {
char *path;
int fd;
FILE *read;
+ int locked; /* state of lockf() */
};
typedef struct gf_store_handle_ gf_store_handle_t;
@@ -99,4 +100,13 @@ gf_store_iter_destroy (gf_store_iter_t *iter);
char*
gf_store_strerror (gf_store_op_errno_t op_errno);
+int
+gf_store_lock (gf_store_handle_t *sh);
+
+void
+gf_store_unlock (gf_store_handle_t *sh);
+
+int
+gf_store_locked_local (gf_store_handle_t *sh);
+
#endif