[Ocfs2-tools-devel] [PATCH 2/6] libo2dlm: Add support for BASTs
Sunil Mushran
sunil.mushran at oracle.com
Fri Apr 16 13:29:02 PDT 2010
Signed-off-by: Sunil Mushran <sunil.mushran at oracle.com>
Joel Becker wrote:
> ocfs2_dlmfs can now notify userspace of BASTs via poll(2) or select(2).
> We need a way for libo2dlm users to actually access this information.
>
> This change introduces two new functions. The first,
> o2dlm_lock_with_bast(), is exactly like o2dlm_lock() except that it
> takes a BAST function and returns a file descriptor to poll on. When
> that file descriptor signals data is ready, the program calls the second
> new function, o2dlm_process_bast(). This will fire off the appropriate
> BAST.
>
> If dlmfs isn't BAST capable, we'll get an error.
>
> Signed-off-by: Joel Becker <joel.becker at oracle.com>
> ---
> include/o2dlm/o2dlm.h | 25 +++++++-
> libo2dlm/o2dlm.c | 162 +++++++++++++++++++++++++++++++++++++++++++++++-
> libo2dlm/o2dlm_err.et | 3 +
> 3 files changed, 184 insertions(+), 6 deletions(-)
>
> diff --git a/include/o2dlm/o2dlm.h b/include/o2dlm/o2dlm.h
> index eada3fb..bb9aca8 100644
> --- a/include/o2dlm/o2dlm.h
> +++ b/include/o2dlm/o2dlm.h
> @@ -74,12 +74,25 @@ errcode_t o2dlm_initialize(const char *dlmfs_path,
> */
> errcode_t o2dlm_lock(struct o2dlm_ctxt *ctxt,
> const char *lockid,
> - int flags,
> + int lockflags,
> enum o2dlm_lock_level level);
>
> +/*
> + * Like o2dlm_lock, but also registers a BAST function for this lock. This
> + * returns a file descriptor in poll_fd that can be fed to select(2) or
> + * poll(2). When there is POLLIN on the descriptor, call o2dlm_process_bast().
> + */
> +errcode_t o2dlm_lock_with_bast(struct o2dlm_ctxt *ctxt,
> + const char *lockid,
> + int lockflags,
> + enum o2dlm_lock_level level,
> + void (*bast_func)(void *bast_arg),
> + void *bast_arg,
> + int *poll_fd);
> +
> /* returns 0 on success */
> errcode_t o2dlm_unlock(struct o2dlm_ctxt *ctxt,
> - char *lockid);
> + const char *lockid);
>
> /* Read the LVB out of a lock.
> * 'len' is the amount to read into 'lvb'
> @@ -102,6 +115,14 @@ errcode_t o2dlm_write_lvb(struct o2dlm_ctxt *ctxt,
> unsigned int len,
> unsigned int *bytes_written);
>
> +
> +/*
> + * Call this when select(2) or poll(2) says there is data on poll_fd. It
> + * will fire off the BAST associated with poll_fd.
> + */
> +void o2dlm_process_bast(struct o2dlm_ctxt *ctxt, int poll_fd);
> +
> +
> /*
> * Unlocks all pending locks and frees the lock context.
> */
> diff --git a/libo2dlm/o2dlm.c b/libo2dlm/o2dlm.c
> index 49d98ff..bf708e7 100644
> --- a/libo2dlm/o2dlm.c
> +++ b/libo2dlm/o2dlm.c
> @@ -46,6 +46,13 @@
>
> #define USER_DLMFS_MAGIC 0x76a9f425
>
> +struct o2dlm_lock_bast
> +{
> + struct list_head b_bucket; /* to hang us off of the bast list */
> + int b_fd; /* the fd of the lock file */
> + void (*b_bast)(void *);
> + void *b_arg; /* Argument to ->b_bast() */
> +};
>
> struct o2dlm_lock_res
> {
> @@ -66,7 +73,9 @@ struct o2dlm_lock_res
> struct o2dlm_ctxt
> {
> int ct_classic;
> + int ct_supports_bast;
> struct list_head *ct_hash;
> + struct list_head *ct_bast_hash;
> unsigned int ct_hash_size;
> char ct_domain_path[O2DLM_MAX_FULL_DOMAIN_PATH]; /* domain
> * dir */
> @@ -105,6 +114,8 @@ static void o2dlm_free_ctxt(struct o2dlm_ctxt *ctxt)
> {
> if (ctxt->ct_hash)
> free(ctxt->ct_hash);
> + if (ctxt->ct_bast_hash)
> + free(ctxt->ct_bast_hash);
> free(ctxt);
> }
>
> @@ -128,16 +139,21 @@ static errcode_t o2dlm_alloc_ctxt(const char *mnt_path,
> return O2DLM_ET_NO_MEMORY;
>
> memset(ctxt, 0, sizeof(*ctxt));
> + ctxt->ct_supports_bast = -1;
> ctxt->ct_hash_size = O2DLM_DEFAULT_HASH_SIZE;
>
> ctxt->ct_hash = calloc(ctxt->ct_hash_size, sizeof(struct list_head));
> - if (!ctxt->ct_hash) {
> + ctxt->ct_bast_hash = calloc(ctxt->ct_hash_size,
> + sizeof(struct list_head));
> + if (!ctxt->ct_hash || !ctxt->ct_bast_hash) {
> err = O2DLM_ET_NO_MEMORY;
> goto exit_and_free;
> }
>
> - for(i = 0; i < ctxt->ct_hash_size; i++)
> + for(i = 0; i < ctxt->ct_hash_size; i++) {
> INIT_LIST_HEAD(&ctxt->ct_hash[i]);
> + INIT_LIST_HEAD(&ctxt->ct_bast_hash[i]);
> + }
>
> len = snprintf(ctxt->ct_ctxt_lock_name, O2DLM_LOCK_ID_MAX_LEN,
> ".%016"PRIx64, rand);
> @@ -378,6 +394,63 @@ static struct o2dlm_lock_res *o2dlm_new_lock_res(const char *id,
> return lockres;
> }
>
> +
> +static inline unsigned int o2dlm_hash_bast(struct o2dlm_ctxt *ctxt, int fd)
> +{
> + return fd % ctxt->ct_hash_size;
> +}
> +
> +static struct o2dlm_lock_bast *o2dlm_find_bast(struct o2dlm_ctxt *ctxt, int fd)
> +{
> + struct o2dlm_lock_bast *bast;
> + struct list_head *p;
> + unsigned int bucket;
> +
> + bucket = o2dlm_hash_bast(ctxt, fd);
> +
> + list_for_each(p, &ctxt->ct_bast_hash[bucket]) {
> + bast = list_entry(p, struct o2dlm_lock_bast, b_bucket);
> + if (fd == bast->b_fd)
> + return bast;
> + }
> + return NULL;
> +}
> +
> +static void o2dlm_insert_bast(struct o2dlm_ctxt *ctxt,
> + struct o2dlm_lock_bast *bast)
> +{
> + unsigned int bucket;
> +
> + bucket = o2dlm_hash_bast(ctxt, bast->b_fd);
> +
> + list_add_tail(&bast->b_bucket, &ctxt->ct_bast_hash[bucket]);
> +}
> +
> +static inline void o2dlm_remove_bast(struct o2dlm_lock_bast *bast)
> +{
> + list_del(&bast->b_bucket);
> + INIT_LIST_HEAD(&bast->b_bucket);
> +}
> +
> +static struct o2dlm_lock_bast *o2dlm_new_bast(int fd,
> + void (*bast_func)(void *),
> + void *bastarg)
> +{
> + struct o2dlm_lock_bast *bast;
> +
> + bast = malloc(sizeof(*bast));
> + if (bast) {
> + memset(bast, 0, sizeof(*bast));
> +
> + INIT_LIST_HEAD(&bast->b_bucket);
> +
> + bast->b_bast = bast_func;
> + bast->b_arg = bastarg;
> + bast->b_fd = fd;
> + }
> + return bast;
> +}
> +
> #define O2DLM_OPEN_MODE 0664
>
>
> @@ -584,11 +657,19 @@ static errcode_t o2dlm_destroy_classic(struct o2dlm_ctxt *ctxt)
> int ret, i;
> int error = 0;
> struct o2dlm_lock_res *lockres;
> + struct o2dlm_lock_bast *bast;
> struct list_head *p, *n, *bucket;
>
> for(i = 0; i < ctxt->ct_hash_size; i++) {
> - bucket = &ctxt->ct_hash[i];
> + bucket = &ctxt->ct_bast_hash[i];
> + list_for_each_safe(p, n, bucket) {
> + bast = list_entry(p, struct o2dlm_lock_bast,
> + b_bucket);
> + o2dlm_remove_bast(bast);
> + free(bast);
> + }
>
> + bucket = &ctxt->ct_hash[i];
> list_for_each_safe(p, n, bucket) {
> lockres = list_entry(p, struct o2dlm_lock_res,
> l_bucket);
> @@ -1109,6 +1190,65 @@ errcode_t o2dlm_lock(struct o2dlm_ctxt *ctxt,
> return o2dlm_lock_nochecks(ctxt, lockid, lockflags, level);
> }
>
> +static errcode_t o2dlm_ctxt_supports_bast(struct o2dlm_ctxt *ctxt)
> +{
> + int support;
> + errcode_t ret = 0;
> +
> + if (ctxt->ct_supports_bast == -1) {
> + ret = o2dlm_supports_bast(&support);
> + if (!ret) {
> + ctxt->ct_supports_bast = support;
> + }
> + }
> +
> + if (!ret && !ctxt->ct_supports_bast)
> + ret = O2DLM_ET_BAST_UNSUPPORTED;
> + return ret;
> +}
> +
> +errcode_t o2dlm_lock_with_bast(struct o2dlm_ctxt *ctxt,
> + const char *lockid,
> + int lockflags,
> + enum o2dlm_lock_level level,
> + void (*bast_func)(void *bast_arg),
> + void *bast_arg,
> + int *poll_fd)
> +{
> + errcode_t ret;
> + struct o2dlm_lock_res *lockres;
> + struct o2dlm_lock_bast *bast;
> +
> + if (!ctxt->ct_classic)
> + return O2DLM_ET_BAST_UNSUPPORTED;
> + if (!bast_func || !poll_fd)
> + return O2DLM_ET_INVALID_ARGS;
> +
> + ret = o2dlm_ctxt_supports_bast(ctxt);
> + if (ret)
> + return ret;
> +
> + ret = o2dlm_lock(ctxt, lockid, lockflags, level);
> + if (ret)
> + return ret;
> +
> + lockres = o2dlm_find_lock_res(ctxt, lockid);
> + if (!lockres) {
> + o2dlm_unlock(ctxt, lockid);
> + return O2DLM_ET_INTERNAL_FAILURE;
> + }
> +
> + bast = o2dlm_new_bast(lockres->l_fd, bast_func, bast_arg);
> + if (!bast) {
> + o2dlm_unlock(ctxt, lockid);
> + return O2DLM_ET_NO_MEMORY;
> + }
> +
> + o2dlm_insert_bast(ctxt, bast);
> + *poll_fd = lockres->l_fd;
> + return 0;
> +}
> +
> static errcode_t o2dlm_unlock_lock_res(struct o2dlm_ctxt *ctxt,
> struct o2dlm_lock_res *lockres)
> {
> @@ -1119,10 +1259,11 @@ static errcode_t o2dlm_unlock_lock_res(struct o2dlm_ctxt *ctxt,
> }
>
> errcode_t o2dlm_unlock(struct o2dlm_ctxt *ctxt,
> - char *lockid)
> + const char *lockid)
> {
> int ret;
> struct o2dlm_lock_res *lockres;
> + struct o2dlm_lock_bast *bast;
>
> if (!ctxt || !lockid)
> return O2DLM_ET_INVALID_ARGS;
> @@ -1131,6 +1272,10 @@ errcode_t o2dlm_unlock(struct o2dlm_ctxt *ctxt,
> if (!lockres)
> return O2DLM_ET_UNKNOWN_LOCK;
>
> + bast = o2dlm_find_bast(ctxt, lockres->l_fd);
> + if (bast)
> + o2dlm_remove_bast(bast);
> +
> o2dlm_remove_lock_res(lockres);
>
> ret = o2dlm_unlock_lock_res(ctxt, lockres);
> @@ -1176,6 +1321,15 @@ errcode_t o2dlm_write_lvb(struct o2dlm_ctxt *ctxt,
> bytes_written);
> }
>
> +void o2dlm_process_bast(struct o2dlm_ctxt *ctxt, int poll_fd)
> +{
> + struct o2dlm_lock_bast *bast;
> +
> + bast = o2dlm_find_bast(ctxt, poll_fd);
> + if (bast)
> + bast->b_bast(bast->b_arg);
> +}
> +
> /* NULL dlmfs_path means fsdlm */
> errcode_t o2dlm_initialize(const char *dlmfs_path,
> const char *domain_name,
> diff --git a/libo2dlm/o2dlm_err.et b/libo2dlm/o2dlm_err.et
> index 528a6e6..184e295 100644
> --- a/libo2dlm/o2dlm_err.et
> +++ b/libo2dlm/o2dlm_err.et
> @@ -111,4 +111,7 @@ ec O2DLM_ET_SEEK,
> ec O2DLM_ET_DOMAIN_BUSY,
> "The domain is busy and cannot be accessed"
>
> +ec O2DLM_ET_BAST_UNSUPPORTED,
> + "This environment does not support BASTs"
> +
> end
>
More information about the Ocfs2-tools-devel
mailing list