/** * @brief Compare two NFSv4 owners * * @param[in] owner1 One owner * @param[in] owner2 Another owner * * @retval 0 on equality. * @retval 1 on inequality. */ int compare_nfs4_owner(state_owner_t *owner1, state_owner_t *owner2) { if (isFullDebug(COMPONENT_STATE) && isDebug(COMPONENT_HASHTABLE)) { char str1[LOG_BUFF_LEN / 2]; char str2[LOG_BUFF_LEN / 2]; struct display_buffer dspbuf1 = {sizeof(str1), str1, str1}; struct display_buffer dspbuf2 = {sizeof(str2), str2, str2}; display_nfs4_owner(&dspbuf1, owner1); display_nfs4_owner(&dspbuf2, owner2); LogFullDebug(COMPONENT_STATE, "{%s} vs {%s}", str1, str2); } if (owner1 == NULL || owner2 == NULL) return 1; if (owner1 == owner2) return 0; if (owner1->so_type != owner2->so_type) return 1; if (owner1->so_owner.so_nfs4_owner.so_clientid != owner2->so_owner.so_nfs4_owner.so_clientid) return 1; if (owner1->so_owner_len != owner2->so_owner_len) return 1; return memcmp(owner1->so_owner_val, owner2->so_owner_val, owner1->so_owner_len); }
int display_nfs4_owner(state_owner_t *powner, char *str) { char * strtmp = str; strtmp += sprintf(strtmp, "%s %p:", state_owner_type_to_str(powner->so_type), powner); strtmp += sprintf(strtmp, " clientid={%"PRIx64"} owner=", powner->so_owner.so_nfs4_owner.so_clientid); strtmp += DisplayOpaqueValue(powner->so_owner_val, powner->so_owner_len, strtmp); strtmp += sprintf(strtmp, " confirmed=%u counter=%u seqid=%u refcount=%d", powner->so_owner.so_nfs4_owner.so_confirmed, powner->so_owner.so_nfs4_owner.so_counter, powner->so_owner.so_nfs4_owner.so_seqid, powner->so_refcount); if(powner->so_owner.so_nfs4_owner.so_related_owner != NULL) { strtmp += sprintf(strtmp, " related_owner={"); strtmp += display_nfs4_owner(powner->so_owner.so_nfs4_owner.so_related_owner, strtmp); strtmp += sprintf(strtmp, "}"); } return strtmp - str; }
/** * @brief Display an NFSv4 owner key * * @param[in] buff Key to display * @param[out] str Output buffer * * @return Length of output string. */ int display_nfs4_owner_key(struct gsh_buffdesc *buff, char *str) { struct display_buffer dspbuf = {HASHTABLE_DISPLAY_STRLEN, str, str}; display_nfs4_owner(&dspbuf, buff->addr); return display_buffer_len(&dspbuf); }
/** * @brief Display NFSv4 owner * * @param[in] owner The state owner * @param[out] str Output string * * @return The length of the output string. */ int display_nfs4_owner(state_owner_t *owner, char *str) { char *strtmp = str; strtmp += sprintf(strtmp, "%s %p:", state_owner_type_to_str(owner->so_type), owner); strtmp += sprintf(strtmp, " clientid={"); strtmp += display_client_id_rec(owner->so_owner.so_nfs4_owner.so_clientrec, strtmp); strtmp += sprintf(strtmp, "} owner="); strtmp += DisplayOpaqueValue(owner->so_owner_val, owner->so_owner_len, strtmp); strtmp += sprintf(strtmp, " confirmed=%u seqid=%u", owner->so_owner.so_nfs4_owner.so_confirmed, owner->so_owner.so_nfs4_owner.so_seqid); if(owner->so_owner.so_nfs4_owner.so_related_owner != NULL) { strtmp += sprintf(strtmp, " related_owner={"); strtmp += display_nfs4_owner(owner->so_owner.so_nfs4_owner.so_related_owner, strtmp); strtmp += sprintf(strtmp, "}"); } strtmp += sprintf(strtmp, " refcount=%d", atomic_fetch_int32_t(&owner->so_refcount)); return strtmp - str; }
int compare_nfs4_owner(state_owner_t * powner1, state_owner_t * powner2) { if(isFullDebug(COMPONENT_STATE) && isDebug(COMPONENT_HASHTABLE)) { char str1[HASHTABLE_DISPLAY_STRLEN]; char str2[HASHTABLE_DISPLAY_STRLEN]; display_nfs4_owner(powner1, str1); display_nfs4_owner(powner2, str2); LogFullDebug(COMPONENT_STATE, "{%s} vs {%s}", str1, str2); } if(powner1 == NULL || powner2 == NULL) return 1; if(powner1 == powner2) return 0; if(powner1->so_type == STATE_LOCK_OWNER_NFSV4 && powner2->so_type == STATE_OPEN_OWNER_NFSV4) return compare_nfs4_owner(powner1->so_owner.so_nfs4_owner.so_related_owner, powner2); if(powner2->so_type == STATE_LOCK_OWNER_NFSV4 && powner1->so_type == STATE_OPEN_OWNER_NFSV4) return compare_nfs4_owner(powner2->so_owner.so_nfs4_owner.so_related_owner, powner1); if(powner1->so_type != powner2->so_type) return 1; if(powner1->so_owner.so_nfs4_owner.so_clientid != powner2->so_owner.so_nfs4_owner.so_clientid) return 1; if(powner1->so_owner_len != powner2->so_owner_len) return 1; return memcmp(powner1->so_owner_val, powner2->so_owner_val, powner1->so_owner_len); }
int display_nfs4_owner_val(hash_buffer_t * pbuff, char *str) { return display_nfs4_owner((state_owner_t *) (pbuff->pdata), str); }
/** * @brief Display NFSv4 owner * * @param[in] owner The state owner * @param[out] str Output string * * @return the bytes remaining in the buffer. */ int display_nfs4_owner(struct display_buffer *dspbuf, state_owner_t *owner) { int b_left; if (owner == NULL) return display_cat(dspbuf, "<NULL>"); b_left = display_printf(dspbuf, "%s %p:", state_owner_type_to_str(owner->so_type), owner); if (b_left <= 0) return b_left; b_left = display_printf(dspbuf, " clientid={"); if (b_left <= 0) return b_left; b_left = display_client_id_rec(dspbuf, owner->so_owner.so_nfs4_owner .so_clientrec); if (b_left <= 0) return b_left; b_left = display_printf(dspbuf, "} owner="); if (b_left <= 0) return b_left; b_left = display_opaque_value(dspbuf, owner->so_owner_val, owner->so_owner_len); if (b_left <= 0) return b_left; b_left = display_printf(dspbuf, " confirmed=%u seqid=%u", owner->so_owner.so_nfs4_owner.so_confirmed, owner->so_owner.so_nfs4_owner.so_seqid); if (b_left <= 0) return b_left; if (owner->so_owner.so_nfs4_owner.so_related_owner != NULL) { b_left = display_printf(dspbuf, " related_owner={"); if (b_left <= 0) return b_left; b_left = display_nfs4_owner(dspbuf, owner->so_owner .so_nfs4_owner.so_related_owner); if (b_left <= 0) return b_left; b_left = display_printf(dspbuf, "}"); if (b_left <= 0) return b_left; } return display_printf(dspbuf, " refcount=%d", atomic_fetch_int32_t(&owner->so_refcount)); }
/** * @brief Display an NFSv4 owner key * * @param[in] buff Key to display * @param[out] str Output buffer * * @return Length of output string. */ int display_nfs4_owner_key(struct gsh_buffdesc *buff, char *str) { return display_nfs4_owner((state_owner_t *) (buff->addr), str); }
/** * @brief Display owner from hash table * * @param[in] buff Buffer * @param[out] str Output buffer * * @return Length of the output string. */ int display_nfs4_owner_val(struct gsh_buffdesc *buff, char *str) { return display_nfs4_owner(buff->addr, str); }
/** * @brief Create a new delegation state then get the delegation. * * Create a new delegation state for this client and file. * Then attempt to get a LEASE lock to delegate the file * according to whether the client opened READ or READ/WRITE. * * @note state_lock must be held for WRITE * * @param[in] data Compound data for this request * @param[in] op NFS arguments for the request * @param[in] open_state Open state for the inode to be delegated. * @param[in] openowner Open owner of the open state. * @param[in] client Client that will own the delegation. * @param[in/out] resok Delegation attempt result to be returned to client. * @param[in] prerecall flag for reclaims. */ static void get_delegation(compound_data_t *data, OPEN4args *args, state_t *open_state, state_owner_t *openowner, nfs_client_id_t *client, OPEN4resok *resok, bool prerecall) { state_status_t state_status; union state_data state_data; open_delegation_type4 deleg_type; state_owner_t *clientowner = &client->cid_owner; struct state_refer refer; state_t *new_state = NULL; struct state_hdl *ostate; open_write_delegation4 *writeres = &resok->delegation.open_delegation4_u.write; open_read_delegation4 *readres = &resok->delegation.open_delegation4_u.read; open_none_delegation4 *whynone = &resok->delegation.open_delegation4_u.od_whynone; ostate = data->current_obj->state_hdl; if (!ostate) { LogFullDebug(COMPONENT_NFS_V4_LOCK, "Could not get file state"); whynone->ond_why = WND4_RESOURCE; return; } /* Record the sequence info */ if (data->minorversion > 0) { memcpy(refer.session, data->session->session_id, sizeof(sessionid4)); refer.sequence = data->sequence; refer.slot = data->slot; } if (args->share_access & OPEN4_SHARE_ACCESS_WRITE) { deleg_type = OPEN_DELEGATE_WRITE; } else { assert(args->share_access & OPEN4_SHARE_ACCESS_READ); deleg_type = OPEN_DELEGATE_READ; } LogDebug(COMPONENT_STATE, "Attempting to grant %s delegation", deleg_type == OPEN_DELEGATE_WRITE ? "WRITE" : "READ"); init_new_deleg_state(&state_data, deleg_type, client); /* Add the delegation state */ state_status = state_add_impl(data->current_obj, STATE_TYPE_DELEG, &state_data, clientowner, &new_state, data->minorversion > 0 ? &refer : NULL); if (state_status != STATE_SUCCESS) { LogDebug(COMPONENT_NFS_V4_LOCK, "get delegation call failed to add state with status %s", state_err_str(state_status)); whynone->ond_why = WND4_RESOURCE; return; } new_state->state_seqid++; LogFullDebugOpaque(COMPONENT_STATE, "delegation state added, stateid: %s", 100, new_state->stateid_other, OTHERSIZE); /* acquire_lease_lock() gets the delegation from FSAL */ state_status = acquire_lease_lock(ostate, clientowner, new_state); if (state_status != STATE_SUCCESS) { if (args->claim.claim != CLAIM_PREVIOUS) { LogDebug(COMPONENT_NFS_V4_LOCK, "get delegation call added state but failed to lock with status %s", state_err_str(state_status)); state_del_locked(new_state); dec_state_t_ref(new_state); if (state_status == STATE_LOCK_CONFLICT) whynone->ond_why = WND4_CONTENTION; else whynone->ond_why = WND4_RESOURCE; return; } prerecall = true; } resok->delegation.delegation_type = deleg_type; ostate->file.fdeleg_stats.fds_deleg_type = deleg_type; if (deleg_type == OPEN_DELEGATE_WRITE) { nfs_space_limit4 *space_limit = &writeres->space_limit; space_limit->limitby = NFS_LIMIT_SIZE; space_limit->nfs_space_limit4_u.filesize = DELEG_SPACE_LIMIT_FILESZ; COPY_STATEID(&writeres->stateid, new_state); writeres->recall = prerecall; get_deleg_perm(&writeres->permissions, deleg_type); } else { assert(deleg_type == OPEN_DELEGATE_READ); COPY_STATEID(&readres->stateid, new_state); readres->recall = prerecall; get_deleg_perm(&readres->permissions, deleg_type); } if (isDebug(COMPONENT_NFS_V4_LOCK)) { char str1[LOG_BUFF_LEN / 2] = "\0"; char str2[LOG_BUFF_LEN / 2] = "\0"; struct display_buffer dspbuf1 = {sizeof(str1), str1, str1}; struct display_buffer dspbuf2 = {sizeof(str2), str2, str2}; display_nfs4_owner(&dspbuf1, openowner); display_nfs4_owner(&dspbuf2, clientowner); LogDebug(COMPONENT_NFS_V4_LOCK, "get delegation openowner %s clientowner %s status %s", str1, str2, state_err_str(state_status)); } dec_state_t_ref(new_state); }
/** * @brief Display NFSv4 owner * * @param[in] owner The state owner * @param[out] str Output string * * @return the bytes remaining in the buffer. */ int display_nfs4_owner(struct display_buffer *dspbuf, state_owner_t *owner) { int b_left; time_t texpire; struct state_nfs4_owner_t *nfs4_owner = &owner->so_owner.so_nfs4_owner; if (owner == NULL) return display_cat(dspbuf, "<NULL>"); b_left = display_printf(dspbuf, "%s %p:", state_owner_type_to_str(owner->so_type), owner); if (b_left <= 0) return b_left; b_left = display_printf(dspbuf, " clientid={"); if (b_left <= 0) return b_left; b_left = display_client_id_rec(dspbuf, nfs4_owner->so_clientrec); if (b_left <= 0) return b_left; b_left = display_printf(dspbuf, "} owner="); if (b_left <= 0) return b_left; b_left = display_opaque_value(dspbuf, owner->so_owner_val, owner->so_owner_len); if (b_left <= 0) return b_left; b_left = display_printf(dspbuf, " confirmed=%u seqid=%u", nfs4_owner->so_confirmed, nfs4_owner->so_seqid); if (b_left <= 0) return b_left; if (nfs4_owner->so_related_owner != NULL) { b_left = display_printf(dspbuf, " related_owner={"); if (b_left <= 0) return b_left; b_left = display_nfs4_owner(dspbuf, nfs4_owner->so_related_owner); if (b_left <= 0) return b_left; b_left = display_printf(dspbuf, "}"); if (b_left <= 0) return b_left; } texpire = atomic_fetch_time_t(&nfs4_owner->so_cache_expire); if (texpire != 0) { b_left = display_printf(dspbuf, " cached(expires in %d secs)", texpire - time(NULL)); if (b_left <= 0) return b_left; } return display_printf(dspbuf, " refcount=%d", atomic_fetch_int32_t(&owner->so_refcount)); }