/* retrieve last informations about a handle */ int fsal_posixdb_GetInodeCache(posixfsal_handle_t * p_handle) /* IN/OUT */ { #ifdef _ENABLE_CACHE_PATH unsigned int i; i = hash_cache_path(p_handle->id, p_handle->ts); /* in the handle in cache ? */ P_r(&cache_array[i].entry_lock); if(cache_array[i].is_set && cache_array[i].handle.id == p_handle->id && cache_array[i].handle.ts == p_handle->ts) { if(cache_array[i].info_is_set) { p_handle->info = cache_array[i].handle.info; LogDebug(COMPONENT_FSAL, "fsal_posixdb_GetInodeCache(%u, %u)", (unsigned int)(p_handle->id), (unsigned int)(p_handle->ts)); V_r(&cache_array[i].entry_lock); return TRUE; } } V_r(&cache_array[i].entry_lock); #endif return FALSE; }
int fsal_posixdb_GetPathCache(posixfsal_handle_t * p_handle, /* IN */ fsal_path_t * p_path /* OUT */ ) { #ifdef _ENABLE_CACHE_PATH unsigned int i; i = hash_cache_path(p_handle->id, p_handle->ts); /* in the handle in cache ? */ P_r(&cache_array[i].entry_lock); if(cache_array[i].is_set && cache_array[i].handle.id == p_handle->id && cache_array[i].handle.ts == p_handle->ts) { if(cache_array[i].path_is_set) { /* return path it */ memcpy(p_path, &cache_array[i].path, sizeof(fsal_path_t)); V_r(&cache_array[i].entry_lock); LogDebug(COMPONENT_FSAL, "fsal_posixdb_GetPathCache(%u, %u)=%s", (unsigned int)p_handle->id, (unsigned int)p_handle->ts, p_path->path); return TRUE; } } V_r(&cache_array[i].entry_lock); #endif return FALSE; }
/** * * cache_inode_is_dir_empty_WithLock: checks if a directory is empty or not, BUT has lock management. * * Checks if a directory is empty or not, BUT has lock management. * * @param pentry [IN] entry to be checked (should be of type DIRECTORY) * * @return CACHE_INODE_SUCCESS is directory is empty\n * @return CACHE_INODE_BAD_TYPE is pentry is not of type DIRECTORY\n * @return CACHE_INODE_DIR_NOT_EMPTY if pentry is not empty * */ cache_inode_status_t cache_inode_is_dir_empty_WithLock(cache_entry_t * pentry) { cache_inode_status_t status; P_r(&pentry->lock); status = cache_inode_is_dir_empty(pentry); V_r(&pentry->lock); return status; } /* cache_inode_is_dir_empty_WithLock */
static void nfs4_acls_test() { int i = 0; fsal_acl_data_t acldata; fsal_ace_t *pace = NULL; fsal_acl_t *pacl = NULL; fsal_acl_status_t status; acldata.naces = 3; acldata.aces = nfs4_ace_alloc(3); LogDebug(COMPONENT_NFS_V4_ACL, "&acldata.aces = %p", &acldata.aces); pace = acldata.aces; for(i = 0; i < 3; i++) { pace->type = i; pace->perm = i; pace->flag = i; pace->who.uid = i; pace++; } pacl = nfs4_acl_new_entry(&acldata, &status); nfs4_acl_entry_inc_ref(pacl); P_r(&pacl->lock); LogDebug(COMPONENT_NFS_V4_ACL, "pacl = %p, ref = %u, status = %u", pacl, pacl->ref, status); V_r(&pacl->lock); pacl = nfs4_acl_new_entry(&acldata, &status); nfs4_acl_entry_inc_ref(pacl); P_r(&pacl->lock); LogDebug(COMPONENT_NFS_V4_ACL, "re-access: pacl = %p, ref = %u, status = %u", pacl, pacl->ref, status); V_r(&pacl->lock); nfs4_acl_release_entry(pacl, &status); P_r(&pacl->lock); LogDebug(COMPONENT_NFS_V4_ACL, "release: pacl = %p, ref = %u, status = %u", pacl, pacl->ref, status); V_r(&pacl->lock); nfs4_acl_release_entry(pacl, &status); }
void *thread_reader(void *arg) { int duree_sleep = 1; int nb_iter = NB_ITER; while(nb_iter > 0) { P_r(&lock); sleep(duree_sleep); V_r(&lock); nb_iter -= 1; } OkRead = 1; /* Ecriture concurrente ici, mais on s'en fout (pas d'impact) */ return NULL; } /* thread_writter */
int HashTable_Get(hash_table_t * ht, hash_buffer_t * buffkey, hash_buffer_t * buffval) { unsigned int hashval; struct rbt_node *pn; struct rbt_head *tete_rbt; hash_data_t *pdata = NULL; int rbt_value = 0; int rc = 0; /* Sanity check */ if(ht == NULL || buffkey == NULL || buffval == NULL) return HASHTABLE_ERROR_INVALID_ARGUMENT; /* Find the RB Tree to be processed */ hashval = (*(ht->parameter.hash_func_key)) (&ht->parameter, buffkey); tete_rbt = &(ht->array_rbt[hashval]); /* Seek into the RB Tree */ rbt_value = (*(ht->parameter.hash_func_rbt)) (&ht->parameter, buffkey); /* Acquire mutex */ P_r(&(ht->array_lock[hashval])); /* I get the node with this value that is located on the left (first with this value in the rbtree) */ if((rc = Key_Locate(ht, buffkey, hashval, rbt_value, &pn)) != HASHTABLE_SUCCESS) { ht->stat_dynamic[hashval].notfound.nb_get += 1; V_r(&(ht->array_lock[hashval])); return rc; } /* Key was found */ pdata = (hash_data_t *) RBT_OPAQ(pn); buffval->pdata = pdata->buffval.pdata; buffval->len = pdata->buffval.len; ht->stat_dynamic[hashval].ok.nb_get += 1; /* Release mutex */ V_r(&(ht->array_lock[hashval])); return HASHTABLE_SUCCESS; } /* HashTable_Get */
/** * * cache_inode_create: creates an entry through the cache. * * Creates an entry through the cache. * * @param pentry_parent [IN] pointer to the pentry parent * @param pname [IN] pointer to the name of the object in the destination directory. * @param type [IN] type of the object to be created. * @param mode [IN] mode to be used at file creation * @param pcreate_arg [IN] additional argument for object creation * @param pattr [OUT] attributes for the new object. * @param ht [INOUT] hash table used for the cache. * @param pclient [INOUT] ressource allocated by the client for the nfs management. * @param pcontext [IN] FSAL credentials * @param pstatus [OUT] returned status. * * @return CACHE_INODE_SUCCESS if operation is a success \n * @return CACHE_INODE_LRU_ERROR if allocation error occured when validating the entry\n * @return CACHE_INODE_BAD_TYPE either source or destination have incorrect type\n * @return CACHE_INODE_ENTRY_EXISTS entry of that name already exists in destination. * */ cache_entry_t * cache_inode_create(cache_entry_t * pentry_parent, fsal_name_t * pname, cache_inode_file_type_t type, fsal_accessmode_t mode, cache_inode_create_arg_t * pcreate_arg, fsal_attrib_list_t * pattr, hash_table_t * ht, cache_inode_client_t * pclient, fsal_op_context_t * pcontext, cache_inode_status_t * pstatus) { cache_entry_t *pentry = NULL; fsal_status_t fsal_status; #ifdef _USE_MFSL mfsl_object_t object_handle; #else fsal_handle_t object_handle; #endif fsal_attrib_list_t parent_attributes; fsal_attrib_list_t object_attributes; fsal_handle_t dir_handle; cache_inode_fsal_data_t fsal_data; cache_inode_status_t status; struct cache_inode_dir_begin__ *dir_begin; int pnfs_status; /* Set the return default to CACHE_INODE_SUCCESS */ *pstatus = CACHE_INODE_SUCCESS; /* stats */ pclient->stat.nb_call_total += 1; inc_func_call(pclient, CACHE_INODE_CREATE); /* * Check if the required type is correct, with this * function, we manage file, dir and symlink */ if(type != REGULAR_FILE && type != DIR_BEGINNING && type != SYMBOLIC_LINK && type != SOCKET_FILE && type != FIFO_FILE && type != CHARACTER_FILE && type != BLOCK_FILE) { *pstatus = CACHE_INODE_BAD_TYPE; /* stats */ inc_func_err_unrecover(pclient, CACHE_INODE_CREATE); return NULL; } /* * Check if caller is allowed to perform the operation */ status = cache_inode_access(pentry_parent, FSAL_W_OK, ht, pclient, pcontext, &status); if (status != CACHE_INODE_SUCCESS) { *pstatus = status; /* stats */ inc_func_err_unrecover(pclient, CACHE_INODE_CREATE); /* pentry is a directory */ return NULL; } /* * Check if an entry of the same name exists */ pentry = cache_inode_lookup(pentry_parent, pname, &object_attributes, ht, pclient, pcontext, pstatus); if (pentry != NULL) { *pstatus = CACHE_INODE_ENTRY_EXISTS; if(pentry->internal_md.type != type) { /* * Incompatible types, returns NULL */ /* stats */ inc_func_err_unrecover(pclient, CACHE_INODE_CREATE); return NULL; } else { /* stats */ inc_func_success(pclient, CACHE_INODE_CREATE); /* * redondant creation, returned the * previously created entry */ return pentry; } } /* * At this point, the entry was not found, this means * that is doesn't exist is FSAL, we can create it */ /* Get the lock for the parent */ P_w(&pentry_parent->lock); if(pentry_parent->internal_md.type == DIR_BEGINNING) dir_handle = pentry_parent->object.dir_begin.handle; if(pentry_parent->internal_md.type == DIR_CONTINUE) { P_r(&pentry_parent->object.dir_cont.pdir_begin->lock); dir_handle = pentry_parent->object.dir_cont.pdir_begin->object.dir_begin.handle; V_r(&pentry_parent->object.dir_cont.pdir_begin->lock); } object_attributes.asked_attributes = pclient->attrmask; switch (type) { case REGULAR_FILE: #ifdef _USE_MFSL cache_inode_get_attributes(pentry_parent, &parent_attributes); fsal_status = MFSL_create(&pentry_parent->mobject, pname, pcontext, &pclient->mfsl_context, mode, &object_handle, &object_attributes, &parent_attributes); #else fsal_status = FSAL_create(&dir_handle, pname, pcontext, mode, &object_handle, &object_attributes); #endif break; case DIR_BEGINNING: #ifdef _USE_MFSL cache_inode_get_attributes(pentry_parent, &parent_attributes); fsal_status = MFSL_mkdir(&pentry_parent->mobject, pname, pcontext, &pclient->mfsl_context, mode, &object_handle, &object_attributes, &parent_attributes); #else fsal_status = FSAL_mkdir(&dir_handle, pname, pcontext, mode, &object_handle, &object_attributes); #endif break; case SYMBOLIC_LINK: #ifdef _USE_MFSL cache_inode_get_attributes(pentry_parent, &object_attributes); fsal_status = MFSL_symlink(&pentry_parent->mobject, pname, &pcreate_arg->link_content, pcontext, &pclient->mfsl_context, mode, &object_handle, &object_attributes); #else fsal_status = FSAL_symlink(&dir_handle, pname, &pcreate_arg->link_content, pcontext, mode, &object_handle, &object_attributes); #endif break; case SOCKET_FILE: #ifdef _USE_MFSL fsal_status = MFSL_mknode(&pentry_parent->mobject, pname, pcontext, &pclient->mfsl_context, mode, FSAL_TYPE_SOCK, NULL, /* no dev_t needed for socket file */ &object_handle, &object_attributes); #else fsal_status = FSAL_mknode(&dir_handle, pname, pcontext, mode, FSAL_TYPE_SOCK, NULL, /* no dev_t needed for socket file */ &object_handle, &object_attributes); #endif break; case FIFO_FILE: #ifdef _USE_MFSL fsal_status = MFSL_mknode(&pentry_parent->mobject, pname, pcontext, &pclient->mfsl_context, mode, FSAL_TYPE_FIFO, NULL, /* no dev_t needed for FIFO file */ &object_handle, &object_attributes); #else fsal_status = FSAL_mknode(&dir_handle, pname, pcontext, mode, FSAL_TYPE_FIFO, NULL, /* no dev_t needed for FIFO file */ &object_handle, &object_attributes); #endif break; case BLOCK_FILE: #ifdef _USE_MFSL fsal_status = MFSL_mknode(&pentry_parent->mobject, pname, pcontext, &pclient->mfsl_context, mode, FSAL_TYPE_BLK, &pcreate_arg->dev_spec, &object_handle, &object_attributes); #else fsal_status = FSAL_mknode(&dir_handle, pname, pcontext, mode, FSAL_TYPE_BLK, &pcreate_arg->dev_spec, &object_handle, &object_attributes); #endif break; case CHARACTER_FILE: #ifdef _USE_MFSL fsal_status = MFSL_mknode(&pentry_parent->mobject, pname, pcontext, &pclient->mfsl_context, mode, FSAL_TYPE_CHR, &pcreate_arg->dev_spec, &object_handle, &object_attributes); #else fsal_status = FSAL_mknode(&dir_handle, pname, pcontext, mode, FSAL_TYPE_CHR, &pcreate_arg->dev_spec, &object_handle, &object_attributes); #endif break; default: /* we should never go there */ *pstatus = CACHE_INODE_INCONSISTENT_ENTRY; V_w(&pentry_parent->lock); /* stats */ inc_func_err_unrecover(pclient, CACHE_INODE_CREATE); return NULL; break; } /* Check for the result */ if(FSAL_IS_ERROR(fsal_status)) { *pstatus = cache_inode_error_convert(fsal_status); V_w(&pentry_parent->lock); if(fsal_status.major == ERR_FSAL_STALE) { cache_inode_status_t kill_status; LogEvent(COMPONENT_CACHE_INODE, "cache_inode_create: Stale FSAL File Handle " "detected for pentry = %p", pentry_parent); cache_inode_kill_entry(pentry_parent, ht, pclient, &kill_status); if(kill_status != CACHE_INODE_SUCCESS) LogCrit(COMPONENT_CACHE_INODE, "cache_inode_create: " "Could not kill entry %p, status = %u", pentry_parent, kill_status); *pstatus = CACHE_INODE_FSAL_ESTALE; } /* stats */ inc_func_err_unrecover(pclient, CACHE_INODE_CREATE); return NULL; } else { #ifdef _USE_MFSL fsal_data.handle = object_handle.handle; #else fsal_data.handle = object_handle; #endif fsal_data.cookie = DIR_START; pentry = cache_inode_new_entry(&fsal_data, &object_attributes, type, pcreate_arg, NULL, ht, pclient, pcontext, TRUE, /* This is a creation and not a population */ pstatus); if (pentry == NULL) { *pstatus = CACHE_INODE_INSERT_ERROR; V_w(&pentry_parent->lock); /* stats */ inc_func_err_unrecover(pclient, CACHE_INODE_CREATE); return NULL; } #ifdef _USE_MFSL /* Copy the MFSL object to the cache */ memcpy((char *)&(pentry->mobject), (char *)&object_handle, sizeof(mfsl_object_t)); #endif /* Add this entry to the directory */ status = cache_inode_add_cached_dirent(pentry_parent, pname, pentry, NULL, ht, pclient, pcontext, pstatus); if (status != CACHE_INODE_SUCCESS) { V_w(&pentry_parent->lock); /* stats */ inc_func_err_unrecover(pclient, CACHE_INODE_CREATE); return NULL; } } #ifdef _USE_PNFS if((type == REGULAR_FILE) && (pcreate_arg != NULL) && (pcreate_arg->use_pnfs == TRUE)) { pnfs_status = pnfs_create_ds_file(&pclient->pnfsclient, pentry->object.file.attributes.fileid, &pentry->object.file.pnfs_file.ds_file); if (pnfs_status != NFS4_OK) { V_w(&pentry_parent->lock); LogDebug(COMPONENT_CACHE_INODE, "OPEN PNFS CREATE DS FILE : Error %u", pnfs_status); *pstatus = CACHE_INODE_IO_ERROR; return NULL; } } #endif /* Update the parent cached attributes */ if(pentry_parent->internal_md.type == DIR_BEGINNING) dir_begin = &pentry_parent->object.dir_begin; else dir_begin = &pentry_parent->object.dir_cont.pdir_begin->object.dir_begin; dir_begin->attributes.mtime.seconds = time(NULL); dir_begin->attributes.mtime.nseconds = 0; dir_begin->attributes.ctime = dir_begin->attributes.mtime; /* * if the created object is a directory, it contains a link * to its parent : '..'. Thus the numlink attr must be increased. */ if(type == DIR_BEGINNING) { dir_begin->attributes.numlinks++; } /* Get the attributes in return */ *pattr = object_attributes; /* valid the parent */ *pstatus = cache_inode_valid(pentry_parent, CACHE_INODE_OP_SET, pclient); /* release the lock for the parent */ V_w(&pentry_parent->lock); /* stat */ if(*pstatus != CACHE_INODE_SUCCESS) inc_func_err_retryable(pclient, CACHE_INODE_CREATE); else inc_func_success(pclient, CACHE_INODE_CREATE); return pentry; }
/** * * cache_inode_lookupp_sw: looks up (and caches) the parent directory for a directory. A switches tells is mutex are use. * * Looks up (and caches) the parent directory for a directory. * * @param pentry [IN] entry whose parent is to be obtained. * @param ht [IN] hash table used for the cache, unused in this call. * @param pclient [INOUT] ressource allocated by the client for the nfs management. * @param pcontext [IN] FSAL credentials * @param pstatus [OUT] returned status. * @param use_mutex [IN] if TRUE mutex are use, not otherwise. * * @return CACHE_INODE_SUCCESS if operation is a success \n * @return CACHE_INODE_LRU_ERROR if allocation error occured when validating the entry * */ cache_entry_t *cache_inode_lookupp_sw(cache_entry_t * pentry, hash_table_t * ht, cache_inode_client_t * pclient, fsal_op_context_t * pcontext, cache_inode_status_t * pstatus, int use_mutex) { cache_entry_t *pentry_parent = NULL; fsal_status_t fsal_status; fsal_attrib_list_t object_attributes; cache_inode_fsal_data_t fsdata; /* Set the return default to CACHE_INODE_SUCCESS */ *pstatus = CACHE_INODE_SUCCESS; /* stats */ pclient->stat.nb_call_total += 1; pclient->stat.func_stats.nb_call[CACHE_INODE_LOOKUP] += 1; /* The entry should be a directory */ if(use_mutex) P_r(&pentry->lock); if(pentry->internal_md.type != DIR_BEGINNING) { if(use_mutex) V_r(&pentry->lock); *pstatus = CACHE_INODE_BAD_TYPE; /* stats */ pclient->stat.func_stats.nb_err_unrecover[CACHE_INODE_LOOKUPP] += 1; return NULL; } /* Renew the entry (to avoid having it being garbagged */ if(cache_inode_renew_entry(pentry, NULL, ht, pclient, pcontext, pstatus) != CACHE_INODE_SUCCESS) { pclient->stat.func_stats.nb_err_retryable[CACHE_INODE_GETATTR] += 1; return NULL; } /* Does the parent belongs to the cache ? */ if(pentry->parent_list && pentry->parent_list->parent) { /* YES, the parent is cached, use the pentry that we have found */ pentry_parent = pentry->parent_list->parent; } else { /* NO, the parent is not cached, query FSAL to get it and cache the result */ object_attributes.asked_attributes = pclient->attrmask; fsal_status = FSAL_lookup(&pentry->object.dir_begin.handle, (fsal_name_t *) & FSAL_DOT_DOT, pcontext, &fsdata.handle, &object_attributes); if(FSAL_IS_ERROR(fsal_status)) { *pstatus = cache_inode_error_convert(fsal_status); if(use_mutex) V_r(&pentry->lock); /* Stale File Handle to be detected and managed */ if(fsal_status.major == ERR_FSAL_STALE) { cache_inode_status_t kill_status; LogEvent(COMPONENT_CACHE_INODE,"cache_inode_lookupp: Stale FSAL FH detected for pentry %p", pentry); if(cache_inode_kill_entry(pentry, ht, pclient, &kill_status) != CACHE_INODE_SUCCESS) LogCrit(COMPONENT_CACHE_INODE,"cache_inode_remove: Could not kill entry %p, status = %u", pentry, kill_status); *pstatus = CACHE_INODE_FSAL_ESTALE; } /* stats */ pclient->stat.func_stats.nb_err_unrecover[CACHE_INODE_LOOKUPP] += 1; return NULL; } /* Call cache_inode_get to populate the cache with the parent entry */ fsdata.cookie = 0; if((pentry_parent = cache_inode_get(&fsdata, &object_attributes, ht, pclient, pcontext, pstatus)) == NULL) { if(use_mutex) V_r(&pentry->lock); /* stats */ pclient->stat.func_stats.nb_err_unrecover[CACHE_INODE_LOOKUPP] += 1; return NULL; } } *pstatus = cache_inode_valid(pentry_parent, CACHE_INODE_OP_GET, pclient); if(use_mutex) V_r(&pentry->lock); /* stat */ if(*pstatus != CACHE_INODE_SUCCESS) pclient->stat.func_stats.nb_err_retryable[CACHE_INODE_LOOKUPP] += 1; else pclient->stat.func_stats.nb_success[CACHE_INODE_LOOKUPP] += 1; return pentry_parent; } /* cache_inode_lookupp_sw */
/** * * cache_inode_link: hardlinks a pentry to another. * * Hard links a pentry to another. This is basically a equivalent of FSAL_link in the cache inode layer. * * @param pentry_src [IN] entry pointer the entry to be linked. This can't be a directory. * @param pentry_dir_dest [INOUT] entry pointer for the destination directory in which the link will be created. * @param plink_name [IN] pointer to the name of the object in the destination directory. * @param pattr [OUT] attributes for the linked attributes after the operation. * @param ht [INOUT] hash table used for the cache. * @param pclient [INOUT] ressource allocated by the client for the nfs management. * @param pcontext [IN] FSAL credentials * @param pstatus [OUT] returned status. * * @return CACHE_INODE_SUCCESS if operation is a success \n * @return CACHE_INODE_LRU_ERROR if allocation error occured when validating the entry\n * @return CACHE_INODE_BAD_TYPE either source or destination have incorrect type\n * @return CACHE_INODE_ENTRY_EXISTS entry of that name already exists in destination. * */ cache_inode_status_t cache_inode_link(cache_entry_t * pentry_src, cache_entry_t * pentry_dir_dest, fsal_name_t * plink_name, fsal_attrib_list_t * pattr, hash_table_t * ht, cache_inode_client_t * pclient, fsal_op_context_t * pcontext, cache_inode_status_t * pstatus) { fsal_status_t fsal_status; fsal_handle_t handle_src; fsal_handle_t handle_dest; fsal_attrib_list_t link_attributes; #ifdef _USE_MFSL fsal_attrib_list_t dirdest_attributes; #endif cache_inode_status_t status; cache_entry_t *pentry_lookup = NULL; fsal_attrib_list_t lookup_attributes; fsal_size_t save_size = 0; fsal_size_t save_spaceused = 0; fsal_time_t save_mtime = { .seconds = 0, .nseconds = 0 }; fsal_accessflags_t access_mask = 0; /* Set the return default to CACHE_INODE_SUCCESS */ *pstatus = CACHE_INODE_SUCCESS; /* stats */ pclient->stat.nb_call_total += 1; pclient->stat.func_stats.nb_call[CACHE_INODE_LINK] += 1; /* Is the destination a directory ? */ if(pentry_dir_dest->internal_md.type != DIR_BEGINNING && pentry_dir_dest->internal_md.type != DIR_CONTINUE) { /* Bad type .... */ *pstatus = CACHE_INODE_BAD_TYPE; pclient->stat.func_stats.nb_err_unrecover[CACHE_INODE_LINK] += 1; return *pstatus; } /* Check if caller is allowed to perform the operation */ access_mask = FSAL_MODE_MASK_SET(FSAL_W_OK) | FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_ADD_FILE); if((status = cache_inode_access(pentry_dir_dest, access_mask, ht, pclient, pcontext, &status)) != CACHE_INODE_SUCCESS) { *pstatus = status; /* stats */ pclient->stat.func_stats.nb_err_unrecover[CACHE_INODE_LINK] += 1; /* pentry is a directory */ return *pstatus; } /* Check if an entry of the same name doesn't exist in the destination directory */ if((pentry_lookup = cache_inode_lookup(pentry_dir_dest, plink_name, &lookup_attributes, ht, pclient, pcontext, pstatus)) != NULL) { /* There exists such an entry... */ *pstatus = CACHE_INODE_ENTRY_EXISTS; pclient->stat.func_stats.nb_err_unrecover[CACHE_INODE_LINK] += 1; return *pstatus; } /* The pentry to be hardlinked can't be a DIR_BEGINNING or a DIR_CONTINUE */ if(pentry_src->internal_md.type == DIR_BEGINNING || pentry_src->internal_md.type == DIR_CONTINUE) { /* Bad type .... */ *pstatus = CACHE_INODE_BAD_TYPE; pclient->stat.func_stats.nb_err_unrecover[CACHE_INODE_LINK] += 1; return *pstatus; } #if 0 if( pentry_src->internal_md.type == REGULAR_FILE ) printf( "=== link === %p | inode=%llu\n", pentry_src, pentry_src->object.file.attributes.fileid ) ; #endif /* At this point, we know that the entry does not exist in destination directory, we know that the * destination is actually a directory and that the source is no directory */ /* Lock the source */ P_w(&pentry_src->lock); /* Lock the target dir */ P_w(&pentry_dir_dest->lock); /* Get the handles */ switch (pentry_src->internal_md.type) { case REGULAR_FILE: handle_src = pentry_src->object.file.handle; break; case SYMBOLIC_LINK: handle_src = pentry_src->object.symlink.handle; break; case FS_JUNCTION: case DIR_BEGINNING: handle_src = pentry_src->object.dir_begin.handle; break; case DIR_CONTINUE: /* lock the related dir_begin (dir begin are garbagge collected AFTER their related dir_cont) * this means that if a DIR_CONTINUE exists, its pdir pointer is not endless */ P_r(&pentry_src->object.dir_cont.pdir_begin->lock); handle_src = pentry_src->object.dir_cont.pdir_begin->object.dir_begin.handle; V_r(&pentry_src->object.dir_cont.pdir_begin->lock); break; case CHARACTER_FILE: case BLOCK_FILE: case SOCKET_FILE: case FIFO_FILE: handle_src = pentry_src->object.special_obj.handle; break; case UNASSIGNED: case RECYCLED: LogCrit(COMPONENT_CACHE_INODE, "WARNING: unknown source pentry type: internal_md.type=%d, line %d in file %s", pentry_src->internal_md.type, __LINE__, __FILE__); *pstatus = CACHE_INODE_BAD_TYPE; pclient->stat.func_stats.nb_err_unrecover[CACHE_INODE_LINK] += 1; return *pstatus; } switch (pentry_dir_dest->internal_md.type) { case FS_JUNCTION: case DIR_BEGINNING: handle_dest = pentry_dir_dest->object.dir_begin.handle; break; case DIR_CONTINUE: /* lock the related dir_begin (dir begin are garbagge collected AFTER their related dir_cont) * this means that if a DIR_CONTINUE exists, its pdir pointer is not endless */ P_r(&pentry_dir_dest->object.dir_cont.pdir_begin->lock); handle_dest = pentry_src->object.dir_cont.pdir_begin->object.dir_begin.handle; V_r(&pentry_dir_dest->object.dir_cont.pdir_begin->lock); break; default: LogCrit(COMPONENT_CACHE_INODE, "WARNING: unknown source pentry type: internal_md.type=%d, line %d in file %s", pentry_src->internal_md.type, __LINE__, __FILE__); *pstatus = CACHE_INODE_BAD_TYPE; pclient->stat.func_stats.nb_err_unrecover[CACHE_INODE_LINK] += 1; return *pstatus; } /* If object is a data cached regular file, keeps it mtime and size, STEP 1 */ if((pentry_src->internal_md.type == REGULAR_FILE) && (pentry_src->object.file.pentry_content != NULL)) { save_mtime = pentry_src->object.file.attributes.mtime; save_size = pentry_src->object.file.attributes.filesize; save_spaceused = pentry_src->object.file.attributes.spaceused; } /* Do the link at FSAL level */ link_attributes.asked_attributes = pclient->attrmask; #ifdef _USE_MFSL cache_inode_get_attributes(pentry_src, &link_attributes); cache_inode_get_attributes(pentry_dir_dest, &dirdest_attributes); fsal_status = MFSL_link(&pentry_src->mobject, &pentry_dir_dest->mobject, plink_name, pcontext, &pclient->mfsl_context, &link_attributes, NULL); #else fsal_status = FSAL_link(&handle_src, &handle_dest, plink_name, pcontext, &link_attributes); #endif if(FSAL_IS_ERROR(fsal_status)) { *pstatus = cache_inode_error_convert(fsal_status); V_w(&pentry_dir_dest->lock); V_w(&pentry_src->lock); if(fsal_status.major == ERR_FSAL_STALE) { cache_inode_status_t kill_status; fsal_status_t getattr_status; LogEvent(COMPONENT_CACHE_INODE, "cache_inode_link: Stale FSAL File Handle detected for at least one in pentry = %p and pentry = %p", pentry_src, pentry_dir_dest); /* Use FSAL_getattrs to find which entry is staled */ getattr_status = FSAL_getattrs(&handle_src, pcontext, &link_attributes); if(getattr_status.major == ERR_FSAL_ACCESS) { LogEvent(COMPONENT_CACHE_INODE, "cache_inode_link: Stale FSAL File Handle detected for pentry = %p", pentry_src); if(cache_inode_kill_entry(pentry_src, ht, pclient, &kill_status) != CACHE_INODE_SUCCESS) LogCrit(COMPONENT_CACHE_INODE, "cache_inode_link: Could not kill entry %p, status = %u", pentry_src, kill_status); } getattr_status = FSAL_getattrs(&handle_dest, pcontext, &link_attributes); if(getattr_status.major == ERR_FSAL_ACCESS) { LogEvent(COMPONENT_CACHE_INODE, "cache_inode_link: Stale FSAL File Handle detected for pentry = %p", pentry_dir_dest); if(cache_inode_kill_entry(pentry_dir_dest, ht, pclient, &kill_status) != CACHE_INODE_SUCCESS) LogCrit(COMPONENT_CACHE_INODE, "cache_inode_link: Could not kill entry %p, status = %u", pentry_dir_dest, kill_status); } } *pstatus = CACHE_INODE_FSAL_ESTALE; return *pstatus; } /* If object is a data cached regular file, keeps it mtime and size, STEP 2 */ if((pentry_src->internal_md.type == REGULAR_FILE) && (pentry_src->object.file.pentry_content != NULL)) { link_attributes.mtime = save_mtime; link_attributes.filesize = save_size; link_attributes.spaceused = save_spaceused; } /* Update cached attributes */ cache_inode_set_attributes(pentry_src, &link_attributes); /* Add the new entry in the destination directory */ if(cache_inode_add_cached_dirent(pentry_dir_dest, plink_name, pentry_src, NULL, ht, pclient, pcontext, &status) != CACHE_INODE_SUCCESS) { V_w(&pentry_dir_dest->lock); V_w(&pentry_src->lock); return *pstatus; } /* Regular exit */ /* return the attributes */ *pattr = link_attributes; /* Validate the entries */ *pstatus = cache_inode_valid(pentry_src, CACHE_INODE_OP_SET, pclient); /* Release the target dir */ V_w(&pentry_dir_dest->lock); /* Release the source */ V_w(&pentry_src->lock); /* stats */ if(*pstatus != CACHE_INODE_SUCCESS) pclient->stat.func_stats.nb_err_retryable[CACHE_INODE_LINK] += 1; else pclient->stat.func_stats.nb_success[CACHE_INODE_LINK] += 1; return *pstatus; }
/** * * cache_inode_setattrs: set the attributes for an entry located in the cache by its address. * * Sets the attributes for an entry located in the cache by its address. Attributes are provided * with compliance to the underlying FSAL semantics. Attributes that are set are returned in "*pattr". * * @param pentry_parent [IN] entry for the parent directory to be managed. * @param pattr [INOUT] attributes for the entry that we have found. Out: attributes set. * @param ht [INOUT] hash table used for the cache, unused in this call. * @param pclient [INOUT] ressource allocated by the client for the nfs management. * @param pcontext [IN] FSAL credentials * @param pstatus [OUT] returned status. * * @return CACHE_INODE_SUCCESS if operation is a success \n * @return CACHE_INODE_LRU_ERROR if allocation error occured when validating the entry * */ cache_inode_status_t cache_inode_setattr(cache_entry_t * pentry, fsal_attrib_list_t * pattr, hash_table_t * ht, /* Unused, kept for protototype's homogeneity */ cache_inode_client_t * pclient, fsal_op_context_t * pcontext, cache_inode_status_t * pstatus) { fsal_handle_t *pfsal_handle = NULL; fsal_status_t fsal_status; fsal_attrib_list_t *p_object_attributes = NULL; fsal_attrib_list_t result_attributes; fsal_attrib_list_t truncate_attributes; /* Set the return default to CACHE_INODE_SUCCESS */ *pstatus = CACHE_INODE_SUCCESS; /* stat */ pclient->stat.nb_call_total += 1; pclient->stat.func_stats.nb_call[CACHE_INODE_SETATTR] += 1; /* Lock the entry */ P_w(&pentry->lock); switch (pentry->internal_md.type) { case REGULAR_FILE: pfsal_handle = &pentry->object.file.handle; break; case SYMBOLIC_LINK: pfsal_handle = &pentry->object.symlink.handle; break; case FS_JUNCTION: case DIR_BEGINNING: pfsal_handle = &pentry->object.dir_begin.handle; break; case DIR_CONTINUE: /* lock the related dir_begin (dir begin are garbagge collected AFTER their related dir_cont) * this means that if a DIR_CONTINUE exists, its pdir pointer is not endless */ P_r(&pentry->object.dir_cont.pdir_begin->lock); pfsal_handle = &pentry->object.dir_cont.pdir_begin->object.dir_begin.handle; V_r(&pentry->object.dir_cont.pdir_begin->lock); break; case CHARACTER_FILE: case BLOCK_FILE: case SOCKET_FILE: case FIFO_FILE: pfsal_handle = &pentry->object.special_obj.handle; break; case UNASSIGNED: case RECYCLED: LogCrit(COMPONENT_CACHE_INODE, "WARNING: unknown source pentry type: internal_md.type=%d, line %d in file %s", pentry->internal_md.type, __LINE__, __FILE__); *pstatus = CACHE_INODE_BAD_TYPE; return *pstatus; } /* Call FSAL to set the attributes */ /* result_attributes.asked_attributes = pattr->asked_attributes ; */ /* mod Th.Leibovici on 2006/02/13 * We ask back all standard attributes, in case they have been modified * by another program (pftp, rcpd...) */ result_attributes.asked_attributes = pclient->attrmask; /* end of mod */ #ifdef _USE_MFSL fsal_status = MFSL_setattrs(&pentry->mobject, pcontext, &pclient->mfsl_context, pattr, &result_attributes, NULL); #else cache_inode_get_attributes(pentry, &result_attributes); fsal_status = FSAL_setattrs(pfsal_handle, pcontext, pattr, &result_attributes); #endif if(FSAL_IS_ERROR(fsal_status)) { *pstatus = cache_inode_error_convert(fsal_status); V_w(&pentry->lock); /* stat */ pclient->stat.func_stats.nb_err_unrecover[CACHE_INODE_SETATTR] += 1; if(fsal_status.major == ERR_FSAL_STALE) { cache_inode_status_t kill_status; LogEvent(COMPONENT_CACHE_INODE, "cache_inode_setattr: Stale FSAL File Handle detected for pentry = %p", pentry); if(cache_inode_kill_entry(pentry, ht, pclient, &kill_status) != CACHE_INODE_SUCCESS) LogCrit(COMPONENT_CACHE_INODE, "cache_inode_setattr: Could not kill entry %p, status = %u", pentry, kill_status); *pstatus = CACHE_INODE_FSAL_ESTALE; } return *pstatus; } if(pattr->asked_attributes & FSAL_ATTR_SIZE) { truncate_attributes.asked_attributes = pclient->attrmask; fsal_status = FSAL_truncate(pfsal_handle, pcontext, pattr->filesize, NULL, &truncate_attributes); if(FSAL_IS_ERROR(fsal_status)) { *pstatus = cache_inode_error_convert(fsal_status); V_w(&pentry->lock); /* stat */ pclient->stat.func_stats.nb_err_unrecover[CACHE_INODE_SETATTR] += 1; if(fsal_status.major == ERR_FSAL_STALE) { cache_inode_status_t kill_status; LogEvent(COMPONENT_CACHE_INODE, "cache_inode_setattr: Stale FSAL File Handle detected for pentry = %p", pentry); if(cache_inode_kill_entry(pentry, ht, pclient, &kill_status) != CACHE_INODE_SUCCESS) LogCrit(COMPONENT_CACHE_INODE, "cache_inode_setattr: Could not kill entry %p, status = %u", pentry, kill_status); *pstatus = CACHE_INODE_FSAL_ESTALE; } return *pstatus; } } /* Keep the new attribute in cache */ switch (pentry->internal_md.type) { case REGULAR_FILE: p_object_attributes = &(pentry->object.file.attributes); break; case SYMBOLIC_LINK: p_object_attributes = &(pentry->object.symlink.attributes); break; case FS_JUNCTION: case DIR_BEGINNING: p_object_attributes = &(pentry->object.dir_begin.attributes); break; case DIR_CONTINUE: /* lock the related dir_begin (dir begin are garbagge collected AFTER their related dir_cont) * this means that if a DIR_CONTINUE exists, its pdir pointer is not endless */ P_r(&pentry->object.dir_cont.pdir_begin->lock); p_object_attributes = &(pentry->object.dir_cont.pdir_begin->object.dir_begin.attributes); V_r(&pentry->object.dir_cont.pdir_begin->lock); break; case CHARACTER_FILE: case BLOCK_FILE: case SOCKET_FILE: case FIFO_FILE: p_object_attributes = &(pentry->object.special_obj.attributes); break; case UNASSIGNED: case RECYCLED: LogCrit(COMPONENT_CACHE_INODE, "WARNING: unknown source pentry type: internal_md.type=%d, line %d in file %s", pentry->internal_md.type, __LINE__, __FILE__); *pstatus = CACHE_INODE_BAD_TYPE; return *pstatus; } /* Update the cached attributes */ if((result_attributes.asked_attributes & FSAL_ATTR_SIZE) || (result_attributes.asked_attributes & FSAL_ATTR_SPACEUSED)) { if(pentry->internal_md.type == REGULAR_FILE) { if(pentry->object.file.pentry_content == NULL) { /* Operation on a non data cached file */ p_object_attributes->filesize = result_attributes.filesize; p_object_attributes->spaceused = result_attributes.filesize; /* Unclear hook here. BUGAZOMEU */ } else { /* Data cached file */ /* Do not set the p_object_attributes->filesize and p_object_attributes->spaceused in this case * This will lead to a situation where (for example) untar-ing a file will produced invalid files * with a size of 0 despite the fact that they are not empty */ LogFullDebug(COMPONENT_CACHE_INODE, "cache_inode_setattr with FSAL_ATTR_SIZE on data cached entry"); } } else if(pattr->asked_attributes & FSAL_ATTR_SIZE) LogCrit(COMPONENT_CACHE_INODE, "WARNING !!! cache_inode_setattr tried to set size on a non REGULAR_FILE type=%d", pentry->internal_md.type); } if(result_attributes.asked_attributes & (FSAL_ATTR_MODE | FSAL_ATTR_OWNER | FSAL_ATTR_GROUP)) { if(result_attributes.asked_attributes & FSAL_ATTR_MODE) p_object_attributes->mode = result_attributes.mode; if(result_attributes.asked_attributes & FSAL_ATTR_OWNER) p_object_attributes->owner = result_attributes.owner; if(result_attributes.asked_attributes & FSAL_ATTR_GROUP) p_object_attributes->group = result_attributes.group; } if(result_attributes.asked_attributes & (FSAL_ATTR_ATIME | FSAL_ATTR_CTIME | FSAL_ATTR_MTIME)) { if(result_attributes.asked_attributes & FSAL_ATTR_ATIME) p_object_attributes->atime = result_attributes.atime; if(result_attributes.asked_attributes & FSAL_ATTR_CTIME) p_object_attributes->ctime = result_attributes.ctime; if(result_attributes.asked_attributes & FSAL_ATTR_MTIME) p_object_attributes->mtime = result_attributes.mtime; } #ifdef _USE_NFS4_ACL if(result_attributes.asked_attributes & FSAL_ATTR_ACL) { LogDebug(COMPONENT_CACHE_INODE, "cache_inode_setattr: old acl = %p, new acl = %p", p_object_attributes->acl, result_attributes.acl); /* Release previous acl entry. */ if(p_object_attributes->acl) { fsal_acl_status_t status; nfs4_acl_release_entry(p_object_attributes->acl, &status); if(status != NFS_V4_ACL_SUCCESS) LogEvent(COMPONENT_CACHE_INODE, "cache_inode_setattr: Failed to release old acl:" " status = %d", status); } /* Update with new acl entry. */ p_object_attributes->acl = result_attributes.acl; } #endif /* _USE_NFS4_ACL */ /* Return the attributes as set */ *pattr = *p_object_attributes; /* validate the entry */ *pstatus = cache_inode_valid(pentry, CACHE_INODE_OP_SET, pclient); /* Release the entry */ V_w(&pentry->lock); /* stat */ if(*pstatus != CACHE_INODE_SUCCESS) pclient->stat.func_stats.nb_err_retryable[CACHE_INODE_SETATTR] += 1; else pclient->stat.func_stats.nb_success[CACHE_INODE_SETATTR] += 1; return *pstatus; } /* cache_inode_setattr */
/* Get a possible full path for an entry */ int NamespacePath(ino_t entry, dev_t dev, unsigned int gen, char *path) { fsnode_t *p_node; int rc; char tmp_path[FSAL_MAX_PATH_LEN]; inode_t curr_inode; /* initialize paths */ path[0] = '\0'; tmp_path[0] = '\0'; /* lock the namespace read-only */ P_r(&ns_lock); curr_inode.inum = entry; curr_inode.dev = dev; curr_inode.generation = gen; do { /* get entry from hash */ p_node = h_get_node(curr_inode.inum, curr_inode.dev, &rc); if(!p_node) { V_r(&ns_lock); if(rc == HASHTABLE_ERROR_NO_SUCH_KEY) { LogFullDebug(COMPONENT_FSAL, "namespace: %lX.%ld not found", (unsigned long)dev, (unsigned long)entry); return ENOENT; } else return EFAULT; } else if(p_node->inode.generation != curr_inode.generation) { V_r(&ns_lock); return ESTALE; } if(!p_node->parent_list) { /* this is the root entry, just add '/' at the begining and return */ LogFullDebug(COMPONENT_FSAL, "namespace: root entry reached"); snprintf(path, FSAL_MAX_PATH_LEN, "/%s", tmp_path); break; } else if(path[0] == '\0') { /* nothing in path for the moment, just copy entry name in it */ strncpy(path, p_node->parent_list->name, FSAL_MAX_NAME_LEN); curr_inode = p_node->parent_list->parent; } else { /* this is a parent dir, path is now <dirname>/<subpath> */ snprintf(path, FSAL_MAX_PATH_LEN, "%s/%s", p_node->parent_list->name, tmp_path); LogFullDebug(COMPONENT_FSAL, "lookup peer found: (%lX.%ld,%s)", p_node->parent_list->parent.dev, p_node->parent_list->parent.inum, p_node->parent_list->name); /* loop detection */ if((curr_inode.inum == p_node->parent_list->parent.inum) && (curr_inode.dev == p_node->parent_list->parent.dev)) { LogCrit(COMPONENT_FSAL, "NAMESPACE MANAGER: loop detected in namespace: %lX.%ld/%s = %lX.%ld", p_node->parent_list->parent.dev, p_node->parent_list->parent.inum, p_node->parent_list->name, curr_inode.dev, curr_inode.inum); V_r(&ns_lock); return ELOOP; } curr_inode = p_node->parent_list->parent; } /* backup path to tmp_path for next loop */ strcpy(tmp_path, path); } while(1); LogFullDebug(COMPONENT_FSAL, "inode=%lX.%ld (gen %u), path='%s'", dev, entry, gen, path); /* reverse lookup succeeded */ V_r(&ns_lock); return 0; }
/** * * cache_inode_getattr: Gets the attributes for a cached entry. * * Gets the attributes for a cached entry. The FSAL attributes are kept in a structure when the entry * is added to the cache. * * @param pentry [IN] entry to be managed. * @param pattr [OUT] pointer to the results * @param ht [IN] hash table used for the cache, unused in this call. * @param pclient [INOUT] ressource allocated by the client for the nfs management. * @param pcontext [IN] FSAL credentials * @param pstatus [OUT] returned status. * * @return CACHE_INODE_SUCCESS if operation is a success \n * @return CACHE_INODE_LRU_ERROR if allocation error occured when validating the entry * */ cache_inode_status_t cache_inode_getattr(cache_entry_t * pentry, fsal_attrib_list_t * pattr, hash_table_t * ht, /* Unused, kept for protototype's homogeneity */ cache_inode_client_t * pclient, fsal_op_context_t * pcontext, cache_inode_status_t * pstatus) { cache_inode_status_t status; fsal_handle_t *pfsal_handle = NULL; fsal_status_t fsal_status; /* sanity check */ if(pentry == NULL || pattr == NULL || ht == NULL || pclient == NULL || pcontext == NULL) { *pstatus = CACHE_INODE_INVALID_ARGUMENT; LogDebug(COMPONENT_CACHE_INODE, "cache_inode_getattr: returning CACHE_INODE_INVALID_ARGUMENT because of bad arg"); return *pstatus; } /* Set the return default to CACHE_INODE_SUCCESS */ *pstatus = CACHE_INODE_SUCCESS; /* stats */ pclient->stat.nb_call_total += 1; inc_func_call(pclient, CACHE_INODE_GETATTR); /* Lock the entry */ P_w(&pentry->lock); status = cache_inode_renew_entry(pentry, pattr, ht, pclient, pcontext, pstatus); if(status != CACHE_INODE_SUCCESS) { V_w(&pentry->lock); inc_func_err_retryable(pclient, CACHE_INODE_GETATTR); LogFullDebug(COMPONENT_CACHE_INODE, "cache_inode_getattr: returning %d(%s) from cache_inode_renew_entry", *pstatus, cache_inode_err_str(*pstatus)); return *pstatus; } /* RW Lock goes for writer to reader */ rw_lock_downgrade(&pentry->lock); cache_inode_get_attributes(pentry, pattr); if(FSAL_TEST_MASK(pattr->asked_attributes, FSAL_ATTR_RDATTR_ERR)) { switch (pentry->internal_md.type) { case REGULAR_FILE: pfsal_handle = &pentry->object.file.handle; break; case SYMBOLIC_LINK: assert(pentry->object.symlink); pfsal_handle = &pentry->object.symlink->handle; break; case DIR_BEGINNING: pfsal_handle = &pentry->object.dir_begin.handle; break; case DIR_CONTINUE: /* * lock the related dir_begin (dir begin are garbagge * collected AFTER their related dir_cont) * this means that if a DIR_CONTINUE exists, * its pdir pointer is not endless */ P_r(&pentry->object.dir_cont.pdir_begin->lock); pfsal_handle = &pentry->object.dir_cont.pdir_begin->object.dir_begin.handle; V_r(&pentry->object.dir_cont.pdir_begin->lock); break; case SOCKET_FILE: case FIFO_FILE: case BLOCK_FILE: case CHARACTER_FILE: pfsal_handle = &pentry->object.special_obj.handle; break; case FS_JUNCTION: case UNASSIGNED: case RECYCLED: *pstatus = CACHE_INODE_INVALID_ARGUMENT; LogFullDebug(COMPONENT_CACHE_INODE, "cache_inode_getattr: returning %d(%s) from cache_inode_renew_entry - unexpected md_type", *pstatus, cache_inode_err_str(*pstatus)); return *pstatus; } /* * An error occured when trying to get * the attributes, they have to be renewed */ #ifdef _USE_MFSL fsal_status = FSAL_getattrs_descriptor(&(cache_inode_fd(pentry)->fsal_file), pfsal_handle, pcontext, pattr); #else fsal_status = FSAL_getattrs_descriptor(cache_inode_fd(pentry), pfsal_handle, pcontext, pattr); #endif if(FSAL_IS_ERROR(fsal_status)) { *pstatus = cache_inode_error_convert(fsal_status); V_r(&pentry->lock); if(fsal_status.major == ERR_FSAL_STALE) { cache_inode_status_t kill_status; LogEvent(COMPONENT_CACHE_INODE, "cache_inode_getattr: Stale FSAL File Handle detected for pentry = %p", pentry); cache_inode_kill_entry(pentry, ht, pclient, &kill_status); if(kill_status != CACHE_INODE_SUCCESS) LogCrit(COMPONENT_CACHE_INODE, "cache_inode_getattr: Could not kill entry %p, status = %u", pentry, kill_status); *pstatus = CACHE_INODE_FSAL_ESTALE; } /* stat */ inc_func_err_unrecover(pclient, CACHE_INODE_GETATTR); LogDebug(COMPONENT_CACHE_INODE, "cache_inode_getattr: returning %d(%s) from FSAL_getattrs_descriptor", *pstatus, cache_inode_err_str(*pstatus)); return *pstatus; } /* Set the new attributes */ cache_inode_set_attributes(pentry, pattr); } *pstatus = cache_inode_valid(pentry, CACHE_INODE_OP_GET, pclient); V_r(&pentry->lock); /* stat */ if(*pstatus != CACHE_INODE_SUCCESS) inc_func_err_retryable(pclient, CACHE_INODE_GETATTR); else inc_func_success(pclient, CACHE_INODE_GETATTR); #ifdef _USE_NFS4_ACL if(isDebug(COMPONENT_NFS_V4_ACL)) { LogDebug(COMPONENT_CACHE_INODE, "cache_inode_getattr: pentry = %p, acl = %p", pentry, pattr->acl); if(pattr->acl) { fsal_ace_t *pace; for(pace = pattr->acl->aces; pace < pattr->acl->aces + pattr->acl->naces; pace++) { LogDebug(COMPONENT_CACHE_INODE, "cache_inode_getattr: ace type = 0x%x, flag = 0x%x, perm = 0x%x, special = %d, %s = 0x%x", pace->type, pace->flag, pace->perm, IS_FSAL_ACE_SPECIAL_ID(*pace), GET_FSAL_ACE_WHO_TYPE(*pace), GET_FSAL_ACE_WHO(*pace)); } } } #endif /* _USE_NFS4_ACL */ LogFullDebug(COMPONENT_CACHE_INODE, "cache_inode_getattr: returning %d(%s) from cache_inode_valid", *pstatus, cache_inode_err_str(*pstatus)); return *pstatus; }
/** * * cache_inode_getattr: Gets the attributes for a cached entry. * * Gets the attributes for a cached entry. The FSAL attributes are kept in a structure when the entry * is added to the cache. * * @param pentry [IN] entry to be managed. * @param pattr [OUT] pointer to the results * @param ht [IN] hash table used for the cache, unused in this call. * @param pclient [INOUT] ressource allocated by the client for the nfs management. * @param pcontext [IN] FSAL credentials * @param pstatus [OUT] returned status. * * @return CACHE_INODE_SUCCESS if operation is a success \n * @return CACHE_INODE_LRU_ERROR if allocation error occured when validating the entry * */ cache_inode_status_t cache_inode_getattr(cache_entry_t * pentry, fsal_attrib_list_t * pattr, hash_table_t * ht, /* Unused, kept for protototype's homogeneity */ cache_inode_client_t * pclient, fsal_op_context_t * pcontext, cache_inode_status_t * pstatus) { cache_inode_status_t status; fsal_handle_t *pfsal_handle; fsal_status_t fsal_status; /* sanity check */ if(pentry == NULL || pattr == NULL || ht == NULL || pclient == NULL || pcontext == NULL) { *pstatus = CACHE_INODE_INVALID_ARGUMENT; return *pstatus; } /* Set the return default to CACHE_INODE_SUCCESS */ *pstatus = CACHE_INODE_SUCCESS; /* stats */ pclient->stat.nb_call_total += 1; inc_func_call(pclient, CACHE_INODE_GETATTR); /* Lock the entry */ P_w(&pentry->lock); status = cache_inode_renew_entry(pentry, pattr, ht, pclient, pcontext, pstatus); if(status != CACHE_INODE_SUCCESS) { V_w(&pentry->lock); inc_func_err_retryable(pclient, CACHE_INODE_GETATTR); return *pstatus; } /* RW Lock goes for writer to reader */ rw_lock_downgrade(&pentry->lock); cache_inode_get_attributes(pentry, pattr); if(FSAL_TEST_MASK(pattr->asked_attributes, FSAL_ATTR_RDATTR_ERR)) { switch (pentry->internal_md.type) { case REGULAR_FILE: pfsal_handle = &pentry->object.file.handle; break; case SYMBOLIC_LINK: pfsal_handle = &pentry->object.symlink.handle; break; case DIR_BEGINNING: pfsal_handle = &pentry->object.dir_begin.handle; break; case DIR_CONTINUE: /* * lock the related dir_begin (dir begin are garbagge * collected AFTER their related dir_cont) * this means that if a DIR_CONTINUE exists, * its pdir pointer is not endless */ P_r(&pentry->object.dir_cont.pdir_begin->lock); pfsal_handle = &pentry->object.dir_cont.pdir_begin->object.dir_begin.handle; V_r(&pentry->object.dir_cont.pdir_begin->lock); break; case SOCKET_FILE: case FIFO_FILE: case BLOCK_FILE: case CHARACTER_FILE: pfsal_handle = &pentry->object.special_obj.handle; break; } /* * An error occured when trying to get * the attributes, they have to be renewed */ fsal_status = FSAL_getattrs(pfsal_handle, pcontext, pattr); if(FSAL_IS_ERROR(fsal_status)) { *pstatus = cache_inode_error_convert(fsal_status); V_r(&pentry->lock); if(fsal_status.major == ERR_FSAL_STALE) { cache_inode_status_t kill_status; LogDebug(COMPONENT_CACHE_INODE_GC, "cache_inode_getattr: Stale FSAL File " "Handle detected for pentry = %p", pentry); cache_inode_kill_entry(pentry, ht, pclient, &kill_status); if(kill_status != CACHE_INODE_SUCCESS) LogCrit(COMPONENT_CACHE_INODE_GC, "cache_inode_getattr: Could not kill " "entry %p, status = %u", pentry, kill_status); *pstatus = CACHE_INODE_FSAL_ESTALE; } /* stat */ inc_func_err_unrecover(pclient, CACHE_INODE_GETATTR); return *pstatus; } /* Set the new attributes */ cache_inode_set_attributes(pentry, pattr); } *pstatus = cache_inode_valid(pentry, CACHE_INODE_OP_GET, pclient); V_r(&pentry->lock); /* stat */ if(*pstatus != CACHE_INODE_SUCCESS) inc_func_err_retryable(pclient, CACHE_INODE_GETATTR); else inc_func_success(pclient, CACHE_INODE_GETATTR); return *pstatus; }