void nfs4_acl_release_entry(fsal_acl_t *acl, fsal_acl_status_t *status) { struct gsh_buffdesc key, old_key; struct gsh_buffdesc old_value; int rc; struct hash_latch latch; /* Set the return default to NFS_V4_ACL_SUCCESS */ *status = NFS_V4_ACL_SUCCESS; if (!acl) return; PTHREAD_RWLOCK_wrlock(&acl->lock); if (acl->ref > 1) { nfs4_acl_entry_dec_ref(acl); PTHREAD_RWLOCK_unlock(&acl->lock); return; } else LogDebug(COMPONENT_NFS_V4_ACL, "Free ACL %p", acl); key.addr = acl->aces; key.len = acl->naces * sizeof(fsal_ace_t); PTHREAD_RWLOCK_unlock(&acl->lock); /* Get the hash table entry and hold latch */ rc = hashtable_getlatch(fsal_acl_hash, &key, &old_value, true, &latch); switch (rc) { case HASHTABLE_ERROR_NO_SUCH_KEY: hashtable_releaselatched(fsal_acl_hash, &latch); return; case HASHTABLE_SUCCESS: PTHREAD_RWLOCK_wrlock(&acl->lock); nfs4_acl_entry_dec_ref(acl); if (acl->ref != 0) { /* Did not actually release last reference */ hashtable_releaselatched(fsal_acl_hash, &latch); PTHREAD_RWLOCK_unlock(&acl->lock); return; } /* use the key to delete the entry */ hashtable_deletelatched(fsal_acl_hash, &key, &latch, &old_key, &old_value); /* Release the latch */ hashtable_releaselatched(fsal_acl_hash, &latch); break; default: LogCrit(COMPONENT_NFS_V4_ACL, "ACL entry could not be deleted, status=%s", hash_table_err_to_str(rc)); return; } /* Sanity check: old_value.addr is expected to be equal to acl, * and is released later in this function */ assert(old_value.addr == acl); PTHREAD_RWLOCK_unlock(&acl->lock); /* Release acl */ nfs4_acl_free(acl); }
/** * @brief Relinquish a reference on an NSM client * * @param[in] client The client to release */ void dec_nsm_client_ref(state_nsm_client_t *client) { char str[LOG_BUFF_LEN]; struct display_buffer dspbuf = {sizeof(str), str, str}; bool str_valid = false; struct hash_latch latch; hash_error_t rc; struct gsh_buffdesc buffkey; struct gsh_buffdesc old_value; struct gsh_buffdesc old_key; int32_t refcount; if (isDebug(COMPONENT_STATE)) { display_nsm_client(&dspbuf, client); str_valid = true; } refcount = atomic_dec_int32_t(&client->ssc_refcount); if (refcount > 0) { if (str_valid) LogFullDebug(COMPONENT_STATE, "Decrement refcount now=%" PRId32 " {%s}", refcount, str); return; } if (str_valid) LogFullDebug(COMPONENT_STATE, "Try to remove {%s}", str); buffkey.addr = client; buffkey.len = sizeof(*client); /* Get the hash table entry and hold latch */ rc = hashtable_getlatch(ht_nsm_client, &buffkey, &old_value, true, &latch); if (rc != HASHTABLE_SUCCESS) { if (rc == HASHTABLE_ERROR_NO_SUCH_KEY) hashtable_releaselatched(ht_nsm_client, &latch); if (!str_valid) display_nsm_client(&dspbuf, client); LogCrit(COMPONENT_STATE, "Error %s, could not find {%s}", hash_table_err_to_str(rc), str); return; } refcount = atomic_fetch_int32_t(&client->ssc_refcount); if (refcount > 0) { if (str_valid) LogDebug(COMPONENT_STATE, "Did not release refcount now=%"PRId32" {%s}", refcount, str); hashtable_releaselatched(ht_nsm_client, &latch); return; } /* use the key to delete the entry */ rc = hashtable_deletelatched(ht_nsm_client, &buffkey, &latch, &old_key, &old_value); if (rc != HASHTABLE_SUCCESS) { if (rc == HASHTABLE_ERROR_NO_SUCH_KEY) hashtable_releaselatched(ht_nsm_client, &latch); if (!str_valid) display_nsm_client(&dspbuf, client); LogCrit(COMPONENT_STATE, "Error %s, could not remove {%s}", hash_table_err_to_str(rc), str); return; } LogFullDebug(COMPONENT_STATE, "Free {%s}", str); nsm_unmonitor(old_value.addr); free_nsm_client(old_value.addr); }