diff options
Diffstat (limited to 'xlators/cluster/ec/src')
-rw-r--r-- | xlators/cluster/ec/src/ec-common.c | 69 | ||||
-rw-r--r-- | xlators/cluster/ec/src/ec-common.h | 28 | ||||
-rw-r--r-- | xlators/cluster/ec/src/ec.c | 1 |
3 files changed, 66 insertions, 32 deletions
diff --git a/xlators/cluster/ec/src/ec-common.c b/xlators/cluster/ec/src/ec-common.c index 27ea5c93d63..e3e34811395 100644 --- a/xlators/cluster/ec/src/ec-common.c +++ b/xlators/cluster/ec/src/ec-common.c @@ -22,9 +22,6 @@ #include "ec-messages.h" #define EC_INVALID_INDEX UINT32_MAX -#define EC_XATTROP_ALL_WAITING_FLAGS (EC_FLAG_WAITING_XATTROP |\ - EC_FLAG_WAITING_DATA_DIRTY |\ - EC_FLAG_WAITING_METADATA_DIRTY) void ec_update_fd_status (fd_t *fd, xlator_t *xl, int idx, @@ -161,6 +158,8 @@ ec_is_range_conflict (ec_lock_link_t *l1, ec_lock_link_t *l2) static gf_boolean_t ec_lock_conflict (ec_lock_link_t *l1, ec_lock_link_t *l2) { + ec_t *ec = l1->fop->xl->private; + /* Fops like access/stat won't have to worry what the other fops are * modifying as the fop is wound only to one brick. So it can be * executed in parallel*/ @@ -172,6 +171,10 @@ ec_lock_conflict (ec_lock_link_t *l1, ec_lock_link_t *l2) (l2->fop->flags & EC_FLAG_LOCK_SHARED)) return _gf_false; + if (!ec->parallel_writes) { + return _gf_true; + } + return ec_is_range_conflict (l1, l2); } @@ -1130,7 +1133,7 @@ ec_prepare_update_cbk (call_frame_t *frame, void *cookie, ec_lock_t *lock = NULL; ec_inode_t *ctx; gf_boolean_t release = _gf_false; - uint64_t waiting_flags = 0; + uint64_t provided_flags = 0; uint64_t dirty[EC_VERSION_SIZE] = {0, 0}; lock = parent_link->lock; @@ -1138,14 +1141,14 @@ ec_prepare_update_cbk (call_frame_t *frame, void *cookie, ctx = lock->ctx; INIT_LIST_HEAD(&list); - waiting_flags = parent_link->waiting_flags & EC_XATTROP_ALL_WAITING_FLAGS; + provided_flags = EC_PROVIDED_FLAGS(parent_link->waiting_flags); LOCK(&lock->loc.inode->lock); list_for_each_entry(link, &lock->owners, owner_list) { - if ((link->waiting_flags & waiting_flags) != 0) { - link->waiting_flags ^= (link->waiting_flags & waiting_flags); - if ((link->waiting_flags & EC_XATTROP_ALL_WAITING_FLAGS) == 0) + if ((link->waiting_flags & provided_flags) != 0) { + link->waiting_flags ^= (link->waiting_flags & provided_flags); + if (EC_NEEDED_FLAGS(link->waiting_flags) == 0) list_add_tail(&link->fop->cbk_list, &list); } } @@ -1158,7 +1161,7 @@ ec_prepare_update_cbk (call_frame_t *frame, void *cookie, goto unlock; } - if (waiting_flags & EC_FLAG_WAITING_XATTROP) { + if (EC_FLAGS_HAVE(provided_flags, EC_FLAG_XATTROP)) { op_errno = -ec_dict_del_array(dict, EC_XATTR_VERSION, ctx->pre_version, EC_VERSION_SIZE); @@ -1219,20 +1222,20 @@ ec_prepare_update_cbk (call_frame_t *frame, void *cookie, ec_set_dirty_flag (fop->data, ctx, dirty); if (dirty[EC_METADATA_TXN] && - (waiting_flags & EC_FLAG_WAITING_METADATA_DIRTY)) { + (EC_FLAGS_HAVE(provided_flags, EC_FLAG_METADATA_DIRTY))) { GF_ASSERT (!ctx->dirty[EC_METADATA_TXN]); ctx->dirty[EC_METADATA_TXN] = 1; } if (dirty[EC_DATA_TXN] && - (waiting_flags & EC_FLAG_WAITING_DATA_DIRTY)) { + (EC_FLAGS_HAVE(provided_flags, EC_FLAG_DATA_DIRTY))) { GF_ASSERT (!ctx->dirty[EC_DATA_TXN]); ctx->dirty[EC_DATA_TXN] = 1; } op_errno = 0; unlock: - lock->waiting_flags ^= waiting_flags; + lock->waiting_flags ^= provided_flags; if (op_errno == 0) { /* If the fop fails on any of the good bricks, it is important to mark @@ -1279,6 +1282,24 @@ unlock: return 0; } +static gf_boolean_t +ec_set_needed_flag(ec_lock_t *lock, ec_lock_link_t *link, uint64_t flag) +{ + uint64_t current; + + link->waiting_flags |= EC_FLAG_NEEDS(flag); + + current = EC_NEEDED_FLAGS(lock->waiting_flags); + if (!EC_FLAGS_HAVE(current, flag)) { + lock->waiting_flags |= EC_FLAG_NEEDS(flag); + link->waiting_flags |= EC_FLAG_PROVIDES(flag); + + return _gf_true; + } + + return _gf_false; +} + static uint64_t ec_set_xattrop_flags_and_params (ec_lock_t *lock, ec_lock_link_t *link, uint64_t *dirty) @@ -1287,31 +1308,25 @@ ec_set_xattrop_flags_and_params (ec_lock_t *lock, ec_lock_link_t *link, uint64_t newflags = 0; ec_inode_t *ctx = lock->ctx; - oldflags = lock->waiting_flags & EC_XATTROP_ALL_WAITING_FLAGS; + oldflags = EC_NEEDED_FLAGS(lock->waiting_flags); if (lock->query && !ctx->have_info) { - lock->waiting_flags |= EC_FLAG_WAITING_XATTROP; - link->waiting_flags |= EC_FLAG_WAITING_XATTROP; + ec_set_needed_flag(lock, link, EC_FLAG_XATTROP); } if (dirty[EC_DATA_TXN]) { - if (oldflags & EC_FLAG_WAITING_DATA_DIRTY) { + if (!ec_set_needed_flag(lock, link, EC_FLAG_DATA_DIRTY)) { dirty[EC_DATA_TXN] = 0; - } else { - lock->waiting_flags |= EC_FLAG_WAITING_DATA_DIRTY; } - link->waiting_flags |= EC_FLAG_WAITING_DATA_DIRTY; } if (dirty[EC_METADATA_TXN]) { - if (oldflags & EC_FLAG_WAITING_METADATA_DIRTY) { + if (!ec_set_needed_flag(lock, link, EC_FLAG_METADATA_DIRTY)) { dirty[EC_METADATA_TXN] = 0; - } else { - lock->waiting_flags |= EC_FLAG_WAITING_METADATA_DIRTY; } - link->waiting_flags |= EC_FLAG_WAITING_METADATA_DIRTY; } - newflags = lock->waiting_flags & EC_XATTROP_ALL_WAITING_FLAGS; + newflags = EC_NEEDED_FLAGS(lock->waiting_flags); + return oldflags ^ newflags; } @@ -1381,7 +1396,7 @@ void ec_get_size_version(ec_lock_link_t *link) goto out; } - if (changed_flags & EC_FLAG_WAITING_XATTROP) { + if (EC_FLAGS_HAVE(changed_flags, EC_FLAG_XATTROP)) { /* Once we know that an xattrop will be needed, * we try to get all available information in a * single call. */ @@ -1676,10 +1691,6 @@ static gf_boolean_t ec_link_has_lock_conflict (ec_lock_link_t *link, gf_boolean_t waitlist_check) { ec_lock_link_t *trav_link = NULL; - ec_t *ec = link->fop->xl->private; - - if (!ec->parallel_writes) - return _gf_true; list_for_each_entry (trav_link, &link->lock->owners, owner_list) { if (ec_lock_conflict (trav_link, link)) diff --git a/xlators/cluster/ec/src/ec-common.h b/xlators/cluster/ec/src/ec-common.h index 99e2f0653be..372be52470c 100644 --- a/xlators/cluster/ec/src/ec-common.h +++ b/xlators/cluster/ec/src/ec-common.h @@ -29,9 +29,31 @@ typedef enum { #define EC_FLAG_LOCK_SHARED 0x0001 -#define EC_FLAG_WAITING_XATTROP 0x0001 -#define EC_FLAG_WAITING_DATA_DIRTY 0x0002 -#define EC_FLAG_WAITING_METADATA_DIRTY 0x0004 +enum _ec_xattrop_flags { + EC_FLAG_XATTROP, + EC_FLAG_DATA_DIRTY, + EC_FLAG_METADATA_DIRTY, + + /* Add any new flag here, before EC_FLAG_MAX. The maximum number of + * flags that can be defined is 16. */ + + EC_FLAG_MAX +}; + +/* We keep two sets of flags. One to determine what's really providing the + * currect xattrop and the other to know what the parent fop of the xattrop + * needs to proceed. It might happen that a fop needs some information that + * is being already requested by a previous fop. The two sets are stored + * contiguously. */ + +#define EC_FLAG_NEEDS(_flag) (1 << (_flag)) +#define EC_FLAG_PROVIDES(_flag) (1 << ((_flag) + EC_FLAG_MAX)) + +#define EC_NEEDED_FLAGS(_flags) ((_flags) & ((1 << EC_FLAG_MAX) - 1)) + +#define EC_PROVIDED_FLAGS(_flags) EC_NEEDED_FLAGS((_flags) >> EC_FLAG_MAX) + +#define EC_FLAGS_HAVE(_flags, _flag) (((_flags) & (1 << (_flag))) != 0) #define EC_SELFHEAL_BIT 62 diff --git a/xlators/cluster/ec/src/ec.c b/xlators/cluster/ec/src/ec.c index ac7e8492133..31e9c0ec584 100644 --- a/xlators/cluster/ec/src/ec.c +++ b/xlators/cluster/ec/src/ec.c @@ -1384,6 +1384,7 @@ int32_t ec_dump_private(xlator_t *this) gf_proc_dump_write("healers", "%d", ec->healers); gf_proc_dump_write("heal-waiters", "%d", ec->heal_waiters); gf_proc_dump_write("read-policy", "%s", ec_read_policies[ec->read_policy]); + gf_proc_dump_write("parallel-writes", "%d", ec->parallel_writes); snprintf(key_prefix, GF_DUMP_MAX_BUF_LEN, "%s.%s.stats.stripe_cache", this->type, this->name); |