diff options
| -rw-r--r-- | libglusterfs/src/syncop.c | 174 | ||||
| -rw-r--r-- | libglusterfs/src/syncop.h | 26 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-mgmt.c | 18 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-op-sm.c | 2 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-syncop.c | 12 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.c | 4 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd.c | 2 | 
7 files changed, 151 insertions, 87 deletions
diff --git a/libglusterfs/src/syncop.c b/libglusterfs/src/syncop.c index 20d4d00561c..cb08b03d44b 100644 --- a/libglusterfs/src/syncop.c +++ b/libglusterfs/src/syncop.c @@ -827,16 +827,20 @@ syncenv_new (size_t stacksize, int procmin, int procmax)  int -synclock_init (synclock_t *lock) +synclock_init (synclock_t *lock, lock_attr_t attr)  { -	if (!lock) -		return -1; +        if (!lock) +               return -1; -	pthread_cond_init (&lock->cond, 0); -	lock->lock = 0; -	INIT_LIST_HEAD (&lock->waitq); +        pthread_cond_init (&lock->cond, 0); +        lock->type = LOCK_NULL; +        lock->owner = NULL; +        lock->owner_tid = 0; +        lock->lock = 0; +        lock->attr = attr; +        INIT_LIST_HEAD (&lock->waitq); -	return pthread_mutex_init (&lock->guard, 0); +        return pthread_mutex_init (&lock->guard, 0);  } @@ -854,32 +858,70 @@ synclock_destroy (synclock_t *lock)  static int  __synclock_lock (struct synclock *lock)  { -	struct synctask *task = NULL; +        struct synctask *task = NULL; -	if (!lock) -		return -1; +        if (!lock) +                return -1; -	task = synctask_get (); +        task = synctask_get (); -	while (lock->lock) { -		if (task) { -			/* called within a synctask */ -			list_add_tail (&task->waitq, &lock->waitq); +        if (lock->lock && (lock->attr == SYNC_LOCK_RECURSIVE)) { +                /*Recursive lock (if same owner requested for lock again then +                 *increment lock count and return success). +                 *Note:same number of unlocks required. +                 */ +                switch (lock->type) { +                case LOCK_TASK: +                        if (task == lock->owner) { +                                lock->lock++; +                                gf_log ("", GF_LOG_TRACE, "Recursive lock called by " +                                        "sync task.owner= %p,lock=%d", lock->owner, lock->lock); +                                return 0; +                        } +                        break; +                case LOCK_THREAD: +                        if (pthread_self () == lock->owner_tid) { +                                lock->lock++; +                                gf_log ("", GF_LOG_TRACE, "Recursive lock called by " +                                        "thread ,owner=%u lock=%d", (unsigned int) lock->owner_tid, +                                         lock->lock); +                                return 0; +                        } +                        break; +                default: +                        gf_log ("", GF_LOG_CRITICAL, "unknown lock type"); +                        break; +                } +        } + + +        while (lock->lock) { +                if (task) { +                        /* called within a synctask */ +                        list_add_tail (&task->waitq, &lock->waitq);                          pthread_mutex_unlock (&lock->guard);                          synctask_yield (task);                          /* task is removed from waitq in unlock,                           * under lock->guard.*/                          pthread_mutex_lock (&lock->guard); -		} else { -			/* called by a non-synctask */ -			pthread_cond_wait (&lock->cond, &lock->guard); -		} -	} +                } else { +                        /* called by a non-synctask */ +                        pthread_cond_wait (&lock->cond, &lock->guard); +                } +        } -	lock->lock = _gf_true; -	lock->owner = task; +        if (task) { +                lock->type = LOCK_TASK; +                lock->owner = task;    /* for synctask*/ -	return 0; +        } else { +                lock->type = LOCK_THREAD; +                lock->owner_tid = pthread_self (); /* for non-synctask */ + +        } +        lock->lock = 1; + +        return 0;  } @@ -925,37 +967,73 @@ unlock:  static int  __synclock_unlock (synclock_t *lock)  { -	struct synctask *task = NULL; -	struct synctask *curr = NULL; +        struct synctask *task = NULL; +        struct synctask *curr = NULL; -	if (!lock) -		return -1; +        if (!lock) +               return -1; + +        if (lock->lock == 0) { +                gf_log ("", GF_LOG_CRITICAL, "Unlock called  before lock "); +                return -1; +        } +        curr = synctask_get (); +        /*unlock should be called by lock owner +         *i.e this will not allow the lock in nonsync task and unlock +         * in sync task and vice-versa +         */ +        switch (lock->type) { +        case LOCK_TASK: +                if (curr == lock->owner) { +                        lock->lock--; +                        gf_log ("", GF_LOG_TRACE, "Unlock success %p, remaining" +                                " locks=%d", lock->owner, lock->lock); +                } else { +                        gf_log ("", GF_LOG_WARNING, "Unlock called by %p, but" +                               " lock held by %p", curr, lock->owner); +                } -	curr = synctask_get (); +                break; +        case LOCK_THREAD: +                if (pthread_self () == lock->owner_tid) { +                        lock->lock--; +                        gf_log ("", GF_LOG_TRACE, "Unlock success %u, remaining" +                                " locks=%d", (unsigned int)lock->owner_tid, lock->lock); +                } else { +                        gf_log ("", GF_LOG_WARNING, "Unlock called by %u, but" +                                " lock held by %u", (unsigned int) pthread_self(), +                                 (unsigned int) lock->owner_tid); +                } -	if (lock->owner != curr) { -		/* warn ? */ -	} +                break; +        default: +                break; +        } -	lock->lock = _gf_false; - -	/* There could be both synctasks and non synctasks -	   waiting (or none, or either). As a mid-approach -	   between maintaining too many waiting counters -	   at one extreme and a thundering herd on unlock -	   at the other, call a cond_signal (which wakes -	   one waiter) and first synctask waiter. So at -	   most we have two threads waking up to grab the -	   just released lock. -	*/ -	pthread_cond_signal (&lock->cond); -	if (!list_empty (&lock->waitq)) { -		task = list_entry (lock->waitq.next, struct synctask, waitq); +        if (lock->lock > 0) { +                 return 0; +        } +        lock->type = LOCK_NULL; +        lock->owner = NULL; +        lock->owner_tid = 0; +        lock->lock = 0; +        /* There could be both synctasks and non synctasks +           waiting (or none, or either). As a mid-approach +           between maintaining too many waiting counters +           at one extreme and a thundering herd on unlock +           at the other, call a cond_signal (which wakes +           one waiter) and first synctask waiter. So at +           most we have two threads waking up to grab the +           just released lock. +        */ +        pthread_cond_signal (&lock->cond); +        if (!list_empty (&lock->waitq)) { +                task = list_entry (lock->waitq.next, struct synctask, waitq);                  list_del_init (&task->waitq); -		synctask_wake (task); -	} +                synctask_wake (task); +        } -	return 0; +        return 0;  } diff --git a/libglusterfs/src/syncop.h b/libglusterfs/src/syncop.h index 3a7798fa17e..f41706a9d37 100644 --- a/libglusterfs/src/syncop.h +++ b/libglusterfs/src/syncop.h @@ -114,12 +114,26 @@ struct syncenv {  }; +typedef enum { +        LOCK_NULL = 0, +        LOCK_TASK, +        LOCK_THREAD +} lock_type_t; + +typedef enum { +        SYNC_LOCK_DEFAULT = 0, +        SYNC_LOCK_RECURSIVE,   /*it allows recursive locking*/ +} lock_attr_t; +  struct synclock { -	pthread_mutex_t     guard; /* guard the remaining members, pair @cond */ -	pthread_cond_t      cond;  /* waiting non-synctasks */ -	struct list_head    waitq; /* waiting synctasks */ -	gf_boolean_t        lock;  /* _gf_true or _gf_false, lock status */ -	struct synctask    *owner; /* NULL if current owner is not a synctask */ +        pthread_mutex_t     guard; /* guard the remaining members, pair @cond */ +        pthread_cond_t      cond;  /* waiting non-synctasks */ +        struct list_head    waitq; /* waiting synctasks */ +        volatile int        lock;  /* true(non zero) or false(zero), lock status */ +        lock_attr_t         attr; +        struct synctask    *owner; /* NULL if current owner is not a synctask */ +        pthread_t           owner_tid; +        lock_type_t         type;  };  typedef struct synclock synclock_t; @@ -336,7 +350,7 @@ syncop_create_frame (xlator_t *this)  	return frame;  } -int synclock_init (synclock_t *lock); +int synclock_init (synclock_t *lock, lock_attr_t attr);  int synclock_destroy (synclock_t *lock);  int synclock_lock (synclock_t *lock);  int synclock_trylock (synclock_t *lock); diff --git a/xlators/mgmt/glusterd/src/glusterd-mgmt.c b/xlators/mgmt/glusterd/src/glusterd-mgmt.c index e07d4100d00..539efb5900d 100644 --- a/xlators/mgmt/glusterd/src/glusterd-mgmt.c +++ b/xlators/mgmt/glusterd/src/glusterd-mgmt.c @@ -378,14 +378,11 @@ gd_mgmt_v3_lock (glusterd_op_t op, dict_t *op_ctx,          gf_uuid_copy (peerid, peerinfo->uuid); -        synclock_unlock (&conf->big_lock); -          ret = gd_syncop_submit_request (peerinfo->rpc, &req, args, &peerid,                                          &gd_mgmt_v3_prog,                                          GLUSTERD_MGMT_V3_LOCK,                                          gd_mgmt_v3_lock_cbk,                                          (xdrproc_t) xdr_gd1_mgmt_v3_lock_req); -        synclock_lock (&conf->big_lock);  out:          GF_FREE (req.dict.dict_val);          gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); @@ -653,14 +650,11 @@ gd_mgmt_v3_pre_validate_req (glusterd_op_t op, dict_t *op_ctx,          gf_uuid_copy (peerid, peerinfo->uuid); -        synclock_unlock (&conf->big_lock); -          ret = gd_syncop_submit_request (peerinfo->rpc, &req, args, &peerid,                                          &gd_mgmt_v3_prog,                                          GLUSTERD_MGMT_V3_PRE_VALIDATE,                                          gd_mgmt_v3_pre_validate_cbk,                                          (xdrproc_t) xdr_gd1_mgmt_v3_pre_val_req); -        synclock_lock (&conf->big_lock);  out:          GF_FREE (req.dict.dict_val);          gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); @@ -911,14 +905,11 @@ gd_mgmt_v3_brick_op_req (glusterd_op_t op, dict_t *op_ctx,          gf_uuid_copy (peerid, peerinfo->uuid); -        synclock_unlock (&conf->big_lock); -          ret = gd_syncop_submit_request (peerinfo->rpc, &req, args, &peerid,                                          &gd_mgmt_v3_prog,                                          GLUSTERD_MGMT_V3_BRICK_OP,                                          gd_mgmt_v3_brick_op_cbk,                                          (xdrproc_t) xdr_gd1_mgmt_v3_brick_op_req); -        synclock_lock (&conf->big_lock);  out:          GF_FREE (req.dict.dict_val);          gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); @@ -1154,14 +1145,11 @@ gd_mgmt_v3_commit_req (glusterd_op_t op, dict_t *op_ctx,          gf_uuid_copy (peerid, peerinfo->uuid); -        synclock_unlock (&conf->big_lock); -          ret = gd_syncop_submit_request (peerinfo->rpc, &req, args, &peerid,                                          &gd_mgmt_v3_prog,                                          GLUSTERD_MGMT_V3_COMMIT,                                          gd_mgmt_v3_commit_cbk,                                          (xdrproc_t) xdr_gd1_mgmt_v3_commit_req); -        synclock_lock (&conf->big_lock);  out:          GF_FREE (req.dict.dict_val);          gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); @@ -1376,14 +1364,11 @@ gd_mgmt_v3_post_validate_req (glusterd_op_t op, int32_t op_ret, dict_t *op_ctx,          gf_uuid_copy (peerid, peerinfo->uuid); -        synclock_unlock (&conf->big_lock); -          ret = gd_syncop_submit_request (peerinfo->rpc, &req, args, &peerid,                                          &gd_mgmt_v3_prog,                                          GLUSTERD_MGMT_V3_POST_VALIDATE,                                          gd_mgmt_v3_post_validate_cbk,                                          (xdrproc_t) xdr_gd1_mgmt_v3_post_val_req); -        synclock_lock (&conf->big_lock);  out:          GF_FREE (req.dict.dict_val);          gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); @@ -1588,14 +1573,11 @@ gd_mgmt_v3_unlock (glusterd_op_t op, dict_t *op_ctx,          gf_uuid_copy (peerid, peerinfo->uuid); -        synclock_unlock (&conf->big_lock); -          ret = gd_syncop_submit_request (peerinfo->rpc, &req, args, &peerid,                                          &gd_mgmt_v3_prog,                                          GLUSTERD_MGMT_V3_UNLOCK,                                          gd_mgmt_v3_unlock_cbk,                                          (xdrproc_t) xdr_gd1_mgmt_v3_unlock_req); -        synclock_lock (&conf->big_lock);  out:          GF_FREE (req.dict.dict_val);          gf_log (this->name, GF_LOG_TRACE, "Returning %d", ret); diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c index 33df2c31d8a..42477ebf6cd 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c @@ -6924,6 +6924,6 @@ int  glusterd_op_sm_init ()  {          CDS_INIT_LIST_HEAD (&gd_op_sm_queue); -        synclock_init (&gd_op_sm_lock); +        synclock_init (&gd_op_sm_lock, SYNC_LOCK_DEFAULT);          return 0;  } diff --git a/xlators/mgmt/glusterd/src/glusterd-syncop.c b/xlators/mgmt/glusterd/src/glusterd-syncop.c index ee8f1eadf2e..e049e2e15e9 100644 --- a/xlators/mgmt/glusterd/src/glusterd-syncop.c +++ b/xlators/mgmt/glusterd/src/glusterd-syncop.c @@ -406,14 +406,12 @@ gd_syncop_mgmt_v3_lock (glusterd_op_t op, dict_t *op_ctx,          gf_uuid_copy (peerid, peerinfo->uuid); -        synclock_unlock (&conf->big_lock);          ret = gd_syncop_submit_request (peerinfo->rpc, &req, args, &peerid,                                          &gd_mgmt_v3_prog,                                          GLUSTERD_MGMT_V3_LOCK,                                          gd_syncop_mgmt_v3_lock_cbk,                                          (xdrproc_t)                                          xdr_gd1_mgmt_v3_lock_req); -        synclock_lock (&conf->big_lock);  out:          gf_log ("", GF_LOG_DEBUG, "Returning %d", ret);          return ret; @@ -503,14 +501,12 @@ gd_syncop_mgmt_v3_unlock (dict_t *op_ctx, glusterd_peerinfo_t *peerinfo,          gf_uuid_copy (peerid, peerinfo->uuid); -        synclock_unlock (&conf->big_lock);          ret = gd_syncop_submit_request (peerinfo->rpc, &req, args, &peerid,                                          &gd_mgmt_v3_prog,                                          GLUSTERD_MGMT_V3_UNLOCK,                                          gd_syncop_mgmt_v3_unlock_cbk,                                          (xdrproc_t)                                          xdr_gd1_mgmt_v3_unlock_req); -        synclock_lock (&conf->big_lock);  out:          gf_log ("", GF_LOG_DEBUG, "Returning %d", ret);          return ret; @@ -598,13 +594,11 @@ gd_syncop_mgmt_lock (glusterd_peerinfo_t *peerinfo, struct syncargs *args,          gf_uuid_copy (req.uuid, my_uuid);          gf_uuid_copy (peerid, peerinfo->uuid); -        synclock_unlock (&conf->big_lock);          ret = gd_syncop_submit_request (peerinfo->rpc, &req, args, &peerid,                                          &gd_mgmt_prog,                                          GLUSTERD_MGMT_CLUSTER_LOCK,                                          gd_syncop_mgmt_lock_cbk,                                          (xdrproc_t) xdr_gd1_mgmt_cluster_lock_req); -        synclock_lock (&conf->big_lock);          return ret;  } @@ -689,13 +683,11 @@ gd_syncop_mgmt_unlock (glusterd_peerinfo_t *peerinfo, struct syncargs *args,          gf_uuid_copy (req.uuid, my_uuid);          gf_uuid_copy (peerid, peerinfo->uuid); -        synclock_unlock (&conf->big_lock);          ret = gd_syncop_submit_request (peerinfo->rpc, &req, args, &peerid,                                          &gd_mgmt_prog,                                          GLUSTERD_MGMT_CLUSTER_UNLOCK,                                          gd_syncop_mgmt_unlock_cbk,                                          (xdrproc_t) xdr_gd1_mgmt_cluster_lock_req); -        synclock_lock (&conf->big_lock);          return ret;  } @@ -826,12 +818,10 @@ gd_syncop_mgmt_stage_op (glusterd_peerinfo_t *peerinfo, struct syncargs *args,          gf_uuid_copy (peerid, peerinfo->uuid); -        synclock_unlock (&conf->big_lock);          ret = gd_syncop_submit_request (peerinfo->rpc, req, args, &peerid,                                          &gd_mgmt_prog, GLUSTERD_MGMT_STAGE_OP,                                          gd_syncop_stage_op_cbk,                                          (xdrproc_t) xdr_gd1_mgmt_stage_op_req); -        synclock_lock (&conf->big_lock);  out:          gd_stage_op_req_free (req);          return ret; @@ -1108,12 +1098,10 @@ gd_syncop_mgmt_commit_op (glusterd_peerinfo_t *peerinfo, struct syncargs *args,          gf_uuid_copy (peerid, peerinfo->uuid); -        synclock_unlock (&conf->big_lock);          ret = gd_syncop_submit_request (peerinfo->rpc, req, args, &peerid,                                          &gd_mgmt_prog, GLUSTERD_MGMT_COMMIT_OP,                                          gd_syncop_commit_op_cbk,                                          (xdrproc_t) xdr_gd1_mgmt_commit_op_req); -        synclock_lock (&conf->big_lock);  out:          gd_commit_op_req_free (req);          return ret; diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c index 2103fd62e03..3025cd6f118 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-utils.c @@ -2730,6 +2730,7 @@ glusterd_spawn_daemons (void *opaque)          gf_boolean_t    start_bricks = !conf->restart_done;          int             ret             = -1; +        synclock_lock (&conf->big_lock);          if (start_bricks) {                  glusterd_restart_bricks (conf);                  conf->restart_done = _gf_true; @@ -9096,7 +9097,8 @@ glusterd_launch_synctask (synctask_fn_t fn, void *opaque)          this = THIS;          priv = this->private; -        synclock_lock (&priv->big_lock); +        /* synclock_lock must be called from within synctask, @fn must call it before +         * it starts with its work*/          ret = synctask_new (this->ctx->env, fn, gd_default_synctask_cbk, NULL,                              opaque);          if (ret) diff --git a/xlators/mgmt/glusterd/src/glusterd.c b/xlators/mgmt/glusterd/src/glusterd.c index 361cc007327..3735c62abc1 100644 --- a/xlators/mgmt/glusterd/src/glusterd.c +++ b/xlators/mgmt/glusterd/src/glusterd.c @@ -1554,7 +1554,7 @@ init (xlator_t *this)          conf->gfs_mgmt = &gd_brick_prog;          strncpy (conf->workdir, workdir, PATH_MAX); -        synclock_init (&conf->big_lock); +        synclock_init (&conf->big_lock, SYNC_LOCK_RECURSIVE);          pthread_mutex_init (&conf->xprt_lock, NULL);          INIT_LIST_HEAD (&conf->xprt_list);  | 
