fsal_status_t MFSL_mknode(mfsl_object_t * parentdir_handle, /* IN */ fsal_name_t * p_node_name, /* IN */ fsal_op_context_t * p_context, /* IN */ mfsl_context_t * p_mfsl_context, /* IN */ fsal_accessmode_t accessmode, /* IN */ fsal_nodetype_t nodetype, /* IN */ fsal_dev_t * dev, /* IN */ mfsl_object_t * p_object_handle, /* OUT */ fsal_attrib_list_t * node_attributes, /* [ IN/OUT ] */ void * pextra ) { struct timeval start, stop, delta ; fsal_status_t fsal_status = { ERR_FSAL_NO_ERROR, 0 } ; gettimeofday( &start, 0 ) ; fsal_status = FSAL_mknode(&parentdir_handle->handle, p_node_name, p_context, accessmode, nodetype, dev, &p_object_handle->handle, node_attributes); gettimeofday( &stop, 0 ) ; delta = mfsl_timer_diff( &stop, &start ) ; LogFullDebug( COMPONENT_MFSL, "%s: duration=%ld.%06ld", __FUNCTION__, delta.tv_sec, delta.tv_usec ) ; return fsal_status ; } /* MFSL_mknode */
fsal_status_t MFSL_mknode(mfsl_object_t * parentdir_handle, /* IN */ fsal_name_t * p_node_name, /* IN */ fsal_op_context_t * p_context, /* IN */ mfsl_context_t * p_mfsl_context, /* IN */ fsal_accessmode_t accessmode, /* IN */ fsal_nodetype_t nodetype, /* IN */ fsal_dev_t * dev, /* IN */ mfsl_object_t * p_object_handle, /* OUT */ fsal_attrib_list_t * node_attributes /* [ IN/OUT ] */ ) { return FSAL_mknode(&parentdir_handle->handle, p_node_name, p_context, accessmode, nodetype, dev, &p_object_handle->handle, node_attributes); } /* MFSL_mknode */
/** * * 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_entry_t * cache_inode_create(cache_entry_t *parent, fsal_name_t *name, cache_inode_file_type_t type, fsal_accessmode_t mode, cache_inode_create_arg_t *create_arg, fsal_attrib_list_t *attr, fsal_op_context_t *context, cache_inode_status_t *status) { cache_entry_t *entry = NULL; fsal_status_t fsal_status = {0, 0}; fsal_handle_t object_handle; fsal_attrib_list_t object_attributes; cache_inode_fsal_data_t fsal_data; cache_inode_create_arg_t zero_create_arg; memset(&zero_create_arg, 0, sizeof(zero_create_arg)); memset(&fsal_data, 0, sizeof(fsal_data)); memset(&object_handle, 0, sizeof(object_handle)); if (create_arg == NULL) { create_arg = &zero_create_arg; } /* Set the return default to CACHE_INODE_SUCCESS */ *status = CACHE_INODE_SUCCESS; if ((type != REGULAR_FILE) && (type != DIRECTORY) && (type != SYMBOLIC_LINK) && (type != SOCKET_FILE) && (type != FIFO_FILE) && (type != CHARACTER_FILE) && (type != BLOCK_FILE)) { *status = CACHE_INODE_BAD_TYPE; entry = NULL; goto out; } /* Check if an entry of the same name exists */ entry = cache_inode_lookup(parent, name, attr, context, status); if (entry != NULL) { *status = CACHE_INODE_ENTRY_EXISTS; if (entry->type != type) { /* Incompatible types, returns NULL */ cache_inode_lru_unref(entry, LRU_FLAG_NONE); entry = NULL; goto out; } else { goto out; } } /* The entry doesn't exist, so we can create it. */ object_attributes.asked_attributes = cache_inode_params.attrmask; switch (type) { case REGULAR_FILE: fsal_status = FSAL_create(&parent->handle, name, context, mode, &object_handle, &object_attributes); break; case DIRECTORY: fsal_status = FSAL_mkdir(&parent->handle, name, context, mode, &object_handle, &object_attributes); break; case SYMBOLIC_LINK: fsal_status = FSAL_symlink(&parent->handle, name, &create_arg->link_content, context, mode, &object_handle, &object_attributes); break; case SOCKET_FILE: fsal_status = FSAL_mknode(&parent->handle, name, context, mode, FSAL_TYPE_SOCK, NULL, &object_handle, &object_attributes); break; case FIFO_FILE: fsal_status = FSAL_mknode(&parent->handle, name, context, mode, FSAL_TYPE_FIFO, NULL, &object_handle, &object_attributes); break; case BLOCK_FILE: fsal_status = FSAL_mknode(&parent->handle, name, context, mode, FSAL_TYPE_BLK, &create_arg->dev_spec, &object_handle, &object_attributes); break; case CHARACTER_FILE: fsal_status = FSAL_mknode(&parent->handle, name, context, mode, FSAL_TYPE_CHR, &create_arg->dev_spec, &object_handle, &object_attributes); break; default: /* we should never go there */ *status = CACHE_INODE_INCONSISTENT_ENTRY; entry = NULL; goto out; break; } /* Check for the result */ if (FSAL_IS_ERROR(fsal_status)) { if (fsal_status.major == ERR_FSAL_STALE) { LogEvent(COMPONENT_CACHE_INODE, "FSAL returned STALE on create type %d", type); cache_inode_kill_entry(parent); } *status = cache_inode_error_convert(fsal_status); entry = NULL; goto out; } fsal_data.fh_desc.start = (caddr_t) &object_handle; fsal_data.fh_desc.len = 0; FSAL_ExpandHandle(context->export_context, FSAL_DIGEST_SIZEOF, &fsal_data.fh_desc); entry = cache_inode_new_entry(&fsal_data, &object_attributes, type, create_arg, status); if (entry == NULL) { *status = CACHE_INODE_INSERT_ERROR; return NULL; } PTHREAD_RWLOCK_WRLOCK(&parent->content_lock); /* Add this entry to the directory (also takes an internal ref) */ cache_inode_add_cached_dirent(parent, name, entry, NULL, status); PTHREAD_RWLOCK_UNLOCK(&parent->content_lock); if (*status != CACHE_INODE_SUCCESS) { cache_inode_lru_unref(entry, LRU_FLAG_NONE); entry = NULL; goto out; } PTHREAD_RWLOCK_WRLOCK(&parent->attr_lock); /* Update the parent cached attributes */ cache_inode_set_time_current(&parent->attributes.mtime); parent->attributes.ctime = parent->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 == DIRECTORY) { ++(parent->attributes.numlinks); } PTHREAD_RWLOCK_UNLOCK(&parent->attr_lock); /* Copy up the child attributes */ *attr = object_attributes; *status = CACHE_INODE_SUCCESS; out: return entry; }