int nlm4_Test(nfs_arg_t * parg /* IN */ , exportlist_t * pexport /* IN */ , fsal_op_context_t * pcontext /* IN */ , cache_inode_client_t * pclient /* INOUT */ , hash_table_t * ht /* INOUT */ , struct svc_req *preq /* IN */ , nfs_res_t * pres /* OUT */ ) { nlm4_testargs *arg; cache_entry_t *pentry; fsal_attrib_list_t attr; nlm_lock_entry_t *nlm_entry; cache_inode_status_t cache_status; cache_inode_fsal_data_t fsal_data; LogFullDebug(COMPONENT_NFSPROTO, "REQUEST PROCESSING: Calling nlm_Test"); if(in_nlm_grace_period()) { pres->res_nlm4test.test_stat.stat = NLM4_DENIED_GRACE_PERIOD; return NFS_REQ_OK; } /* Convert file handle into a cache entry */ arg = &parg->arg_nlm4_test; if(!nfs3_FhandleToFSAL((nfs_fh3 *) & (arg->alock.fh), &fsal_data.handle, pcontext)) { /* handle is not valid */ pres->res_nlm4test.test_stat.stat = NLM4_STALE_FH; /* * Should we do a REQ_OK so that the client get * a response ? FIXME!! */ return NFS_REQ_DROP; } /* Now get the cached inode attributes */ fsal_data.cookie = DIR_START; if((pentry = cache_inode_get(&fsal_data, &attr, ht, pclient, pcontext, &cache_status)) == NULL) { /* handle is not valid */ pres->res_nlm4test.test_stat.stat = NLM4_STALE_FH; return NFS_REQ_OK; } nlm_entry = nlm_overlapping_entry(&(arg->alock), arg->exclusive); if(!nlm_entry) { pres->res_nlm4test.test_stat.stat = NLM4_GRANTED; } else { pres->res_nlm4test.test_stat.stat = NLM4_DENIED; nlm_lock_entry_to_nlm_holder(nlm_entry, &pres->res_nlm4test.test_stat.nlm4_testrply_u.holder); nlm_lock_entry_dec_ref(nlm_entry); } return NFS_REQ_OK; }
int nfs3_Pathconf(nfs_arg_t * parg, exportlist_t * pexport, fsal_op_context_t * pcontext, cache_inode_client_t * pclient, hash_table_t * ht, struct svc_req *preq, nfs_res_t * pres) { static char __attribute__ ((__unused__)) funcName[] = "nfs3_Pathconf"; cache_inode_status_t cache_status; cache_entry_t *pentry = NULL; cache_inode_fsal_data_t fsal_data; fsal_attrib_list_t attr; fsal_staticfsinfo_t * pstaticinfo = pcontext->export_context->fe_static_fs_info; if(isDebug(COMPONENT_NFSPROTO)) { char str[LEN_FH_STR]; sprint_fhandle3(str, &(parg->arg_pathconf3.object)); LogDebug(COMPONENT_NFSPROTO, "REQUEST PROCESSING: Calling nfs3_Pathconf handle: %s", str); } /* to avoid setting it on each error case */ pres->res_pathconf3.PATHCONF3res_u.resfail.obj_attributes.attributes_follow = FALSE; /* Convert file handle into a fsal_handle */ if(nfs3_FhandleToFSAL(&(parg->arg_pathconf3.object), &fsal_data.handle, pcontext) == 0) return NFS_REQ_DROP; /* Set cookie to zero */ fsal_data.cookie = DIR_START; /* Get the entry in the cache_inode */ if((pentry = cache_inode_get( &fsal_data, pexport->cache_inode_policy, &attr, ht, pclient, pcontext, &cache_status)) == NULL) { /* Stale NFS FH ? */ pres->res_pathconf3.status = NFS3ERR_STALE; return NFS_REQ_OK; } /* Build post op file attributes */ nfs_SetPostOpAttr(pcontext, pexport, pentry, &attr, &(pres->res_pathconf3.PATHCONF3res_u.resok.obj_attributes)); pres->res_pathconf3.PATHCONF3res_u.resok.linkmax = pstaticinfo->maxlink; pres->res_pathconf3.PATHCONF3res_u.resok.name_max = pstaticinfo->maxnamelen; pres->res_pathconf3.PATHCONF3res_u.resok.no_trunc = pstaticinfo->no_trunc; pres->res_pathconf3.PATHCONF3res_u.resok.chown_restricted = pstaticinfo->chown_restricted; pres->res_pathconf3.PATHCONF3res_u.resok.case_insensitive = pstaticinfo->case_insensitive; pres->res_pathconf3.PATHCONF3res_u.resok.case_preserving = pstaticinfo->case_preserving; return NFS_REQ_OK; } /* nfs3_Pathconf */
int nfs3_Pathconf(nfs_arg_t * parg, exportlist_t * pexport, fsal_op_context_t * pcontext, cache_inode_client_t * pclient, hash_table_t * ht, struct svc_req *preq, nfs_res_t * pres) { static char __attribute__ ((__unused__)) funcName[] = "nfs3_Pathconf"; cache_inode_status_t cache_status; cache_entry_t *pentry = NULL; cache_inode_fsal_data_t fsal_data; fsal_attrib_list_t attr; fsal_staticfsinfo_t staticinfo; fsal_dynamicfsinfo_t dynamicinfo; /* to avoid setting it on each error case */ pres->res_pathconf3.PATHCONF3res_u.resfail.obj_attributes.attributes_follow = FALSE; /* Convert file handle into a fsal_handle */ if(nfs3_FhandleToFSAL(&(parg->arg_access3.object), &fsal_data.handle, pcontext) == 0) return NFS_REQ_DROP; /* Set cookie to zero */ fsal_data.cookie = DIR_START; /* Get the entry in the cache_inode */ if((pentry = cache_inode_get(&fsal_data, &attr, ht, pclient, pcontext, &cache_status)) == NULL) { /* Stale NFS FH ? */ pres->res_pathconf3.status = NFS3ERR_STALE; return NFS_REQ_OK; } /* Get the filesystem information */ if(cache_inode_statfs(pentry, &staticinfo, &dynamicinfo, pcontext, &cache_status) != CACHE_INODE_SUCCESS) { pres->res_pathconf3.status = nfs3_Errno(cache_status); return NFS_REQ_OK; } /* Build post op file attributes */ nfs_SetPostOpAttr(pcontext, pexport, pentry, &attr, &(pres->res_pathconf3.PATHCONF3res_u.resok.obj_attributes)); pres->res_pathconf3.PATHCONF3res_u.resok.linkmax = staticinfo.maxlink; pres->res_pathconf3.PATHCONF3res_u.resok.name_max = staticinfo.maxnamelen; pres->res_pathconf3.PATHCONF3res_u.resok.no_trunc = staticinfo.no_trunc; pres->res_pathconf3.PATHCONF3res_u.resok.chown_restricted = staticinfo.chown_restricted; pres->res_pathconf3.PATHCONF3res_u.resok.case_insensitive = staticinfo.case_insensitive; pres->res_pathconf3.PATHCONF3res_u.resok.case_preserving = staticinfo.case_preserving; return NFS_REQ_OK; } /* nfs3_Pathconf */
fsal_status_t dumb_fsal_up_invalidate(fsal_up_event_data_t * pevdata) { cache_inode_status_t cache_status; cache_entry_t *pentry = NULL; fsal_attrib_list_t attr; memset(&attr, 0, sizeof(fsal_attrib_list_t)); /* Avoid dir cont check in cache_inode_get() */ pevdata->event_context.fsal_data.cookie = DIR_START; LogDebug(COMPONENT_FSAL_UP, "FSAL_UP_DUMB: calling cache_inode_get()"); pentry = cache_inode_get(&pevdata->event_context.fsal_data, cachepol, &attr, pevdata->event_context.ht, NULL, NULL, &cache_status); if(pentry == NULL) { LogDebug(COMPONENT_FSAL_UP, "FSAL_UP_DUMB: cache inode get failed."); /* Not an error. Expecting some nodes will not have it in cache in * a cluster. */ ReturnCode(ERR_FSAL_NO_ERROR, 0); } LogDebug(COMPONENT_FSAL_UP, "FSAL_UP_DUMB: Invalidate cache found entry %p type %u", pentry, pentry->internal_md.type); /* Lock the entry */ P_w(&pentry->lock); LogDebug(COMPONENT_FSAL_UP, "FSAL_UP_DUMB: setting state to STALE"); pentry->internal_md.valid_state = STALE; if(pentry->internal_md.type == DIRECTORY) { pentry->object.dir.has_been_readdir = CACHE_INODE_RENEW_NEEDED; LogDebug(COMPONENT_FSAL_UP, "FSAL_CB_DUMB: Invalidate reset directory."); } V_w(&pentry->lock); ReturnCode(ERR_FSAL_NO_ERROR, 0); }
fsal_status_t dumb_fsal_up_lock_avail(fsal_up_event_data_t * pevdata) { #ifdef _USE_BLOCKING_LOCKS cache_inode_status_t cache_status; cache_entry_t * pentry = NULL; fsal_attrib_list_t attr; /* Avoid dir cont check in cache_inode_get() */ pevdata->event_context.fsal_data.cookie = DIR_START; LogDebug(COMPONENT_FSAL_UP, "FSAL_UP_DUMB: calling cache_inode_get()"); pentry = cache_inode_get(&pevdata->event_context.fsal_data, cachepol, &attr, pevdata->event_context.ht, NULL, NULL, &cache_status); if(pentry == NULL) { LogDebug(COMPONENT_FSAL_UP, "FSAL_UP_DUMB: cache inode get failed."); /* Not an error. Expecting some nodes will not have it in cache in * a cluster. */ ReturnCode(ERR_FSAL_NO_ERROR, 0); } LogDebug(COMPONENT_FSAL_UP, "FSAL_UP_DUMB: Lock Available found entry %p", pentry); available_blocked_lock_upcall(pentry, pevdata->type.lock_grant.lock_owner, &pevdata->type.lock_grant.lock_param, NULL); ReturnCode(ERR_FSAL_NO_ERROR, 0); #else INVALIDATE_STUB; #endif }
fsal_status_t dumb_fsal_up_lock_grant(fsal_up_event_data_t * pevdata) { #ifdef _USE_BLOCKING_LOCKS cache_inode_status_t cache_status; cache_entry_t * pentry = NULL; fsal_attrib_list_t attr; LogFullDebug(COMPONENT_FSAL_UP, "FSAL_UP_DUMB: calling cache_inode_get()"); pentry = cache_inode_get(&pevdata->event_context.fsal_data, &attr, NULL, NULL, &cache_status); if(pentry == NULL) { LogDebug(COMPONENT_FSAL_UP, "FSAL_UP_DUMB: cache inode get failed."); /* Not an error. Expecting some nodes will not have it in cache in * a cluster. */ ReturnCode(ERR_FSAL_NO_ERROR, 0); } LogDebug(COMPONENT_FSAL_UP, "FSAL_UP_DUMB: Lock Grant found entry %p", pentry); grant_blocked_lock_upcall(pentry, pevdata->type.lock_grant.lock_owner, &pevdata->type.lock_grant.lock_param); if(pentry) cache_inode_put(pentry); ReturnCode(ERR_FSAL_NO_ERROR, 0); #else INVALIDATE_STUB; #endif }
/** * * cache_content_crash_recover: recovers the data cache and the associated inode after a crash. * * @param pclient [IN] ressource allocated by the client for the nfs management. * @pstatus [OUT] returned status. * * @return CACHE_CONTENT_SUCCESS is successful. * */ cache_content_status_t cache_content_crash_recover(unsigned short exportid, unsigned int index, unsigned int mod, cache_content_client_t * pclient_data, cache_inode_client_t * pclient_inode, hash_table_t * ht, fsal_op_context_t * pcontext, cache_content_status_t * pstatus) { DIR *cache_directory; cache_content_dirinfo_t export_directory; char cache_exportdir[MAXPATHLEN]; char fullpath[MAXPATHLEN]; struct dirent *direntp; struct dirent dirent_export; int found_export_id; u_int64_t inum; off_t size_in_cache; cache_entry_t inode_entry; cache_entry_t *pentry = NULL; cache_content_entry_t *pentry_content = NULL; cache_inode_status_t cache_inode_status; cache_content_status_t cache_content_status; fsal_attrib_list_t fsal_attr; cache_inode_fsal_data_t fsal_data; *pstatus = CACHE_CONTENT_SUCCESS; /* Open the cache directory */ if((cache_directory = opendir(pclient_data->cache_dir)) == NULL) { *pstatus = CACHE_CONTENT_LOCAL_CACHE_ERROR; return *pstatus; } /* read the cache directory */ while((direntp = readdir(cache_directory)) != NULL) { /* . and .. are of no interest */ if(!strcmp(direntp->d_name, ".") || !strcmp(direntp->d_name, "..")) continue; if((found_export_id = cache_content_get_export_id(direntp->d_name)) >= 0) { LogEvent(COMPONENT_CACHE_CONTENT, "Directory cache for Export ID %d has been found", found_export_id); snprintf(cache_exportdir, MAXPATHLEN, "%s/%s", pclient_data->cache_dir, direntp->d_name); if(cache_content_local_cache_opendir(cache_exportdir, &(export_directory)) == FALSE) { *pstatus = CACHE_CONTENT_LOCAL_CACHE_ERROR; closedir(cache_directory); return *pstatus; } /* Reads the directory content (a single thread for the moment) */ while(cache_content_local_cache_dir_iter (&export_directory, &dirent_export, index, mod)) { /* . and .. are of no interest */ if(!strcmp(dirent_export.d_name, ".") || !strcmp(dirent_export.d_name, "..")) continue; if((inum = cache_content_get_inum(dirent_export.d_name)) > 0) { LogEvent(COMPONENT_CACHE_CONTENT, "Cache entry for File ID %llx has been found", inum); /* Get the content of the file */ sprintf(fullpath, "%s/%s/%s", pclient_data->cache_dir, direntp->d_name, dirent_export.d_name); if((cache_inode_status = cache_inode_reload_content(fullpath, &inode_entry)) != CACHE_INODE_SUCCESS) { LogMajor(COMPONENT_CACHE_CONTENT, "File Content Cache record for File ID %llx is unreadable", inum); continue; } else LogMajor(COMPONENT_CACHE_CONTENT, "File Content Cache record for File ID %llx : READ OK", inum); /* Populating the cache_inode... */ fsal_data.handle = inode_entry.object.file.handle; fsal_data.cookie = 0; if((pentry = cache_inode_get(&fsal_data, &fsal_attr, ht, pclient_inode, pcontext, &cache_inode_status)) == NULL) { LogCrit(COMPONENT_CACHE_CONTENT, "Error adding cached inode for file ID %llx, error=%d", inum, cache_inode_status); continue; } else LogEvent(COMPONENT_CACHE_CONTENT, "Cached inode added successfully for file ID %llx", inum); /* Get the size from the cache */ if((size_in_cache = cache_content_recover_size(cache_exportdir, inum)) == -1) { LogCrit(COMPONENT_CACHE_CONTENT, "Error when recovering size for file ID %llx", inum); } else pentry->object.file.attributes.filesize = (fsal_size_t) size_in_cache; /* Adding the cached entry to the data cache */ if((pentry_content = cache_content_new_entry(pentry, NULL, pclient_data, RECOVER_ENTRY, pcontext, &cache_content_status)) == NULL) { LogCrit(COMPONENT_CACHE_CONTENT, "Error adding cached data for file ID %llx, error=%d", inum, cache_inode_status); continue; } else LogEvent(COMPONENT_CACHE_CONTENT, "Cached data added successfully for file ID %llx", inum); if((cache_content_status = cache_content_valid(pentry_content, CACHE_CONTENT_OP_GET, pclient_data)) != CACHE_CONTENT_SUCCESS) { *pstatus = cache_content_status; return *pstatus; } } } /* while( ( dirent_export = readdir( export_directory ) ) != NULL ) */ /* Close the export cache directory */ cache_content_local_cache_closedir(&export_directory); } /* if( ( found_export_id = cache_content_get_export_id( direntp->d_name ) ) > 0 ) */ } /* while( ( direntp = readdir( cache_directory ) ) != NULL ) */ /* Close the cache directory */ closedir(cache_directory); return *pstatus; } /* cache_content_crash_recover */
int _9p_auth( _9p_request_data_t * preq9p, void * pworker_data, u32 * plenout, char * preply) { char * cursor = preq9p->_9pmsg + _9P_HDR_SIZE + _9P_TYPE_SIZE ; nfs_worker_data_t * pwkrdata = (nfs_worker_data_t *)pworker_data ; u16 * msgtag = NULL ; u32 * afid = NULL ; u16 * uname_len = NULL ; char * uname_str = NULL ; u16 * aname_len = NULL ; char * aname_str = NULL ; u32 * n_aname = NULL ; fsal_attrib_list_t fsalattr ; u32 err = 0 ; _9p_fid_t * pfid = NULL ; exportlist_t * pexport = NULL; unsigned int found = FALSE; cache_inode_status_t cache_status ; cache_inode_fsal_data_t fsdata ; if ( !preq9p || !pworker_data || !plenout || !preply ) return -1 ; /* Get data */ _9p_getptr( cursor, msgtag, u16 ) ; _9p_getptr( cursor, afid, u32 ) ; _9p_getstr( cursor, uname_len, uname_str ) ; _9p_getstr( cursor, aname_len, aname_str ) ; _9p_getptr( cursor, n_aname, u32 ) ; LogDebug( COMPONENT_9P, "TAUTH: tag=%u afid=%d uname='%.*s' aname='%.*s' n_uname=%d", (u32)*msgtag, *afid, (int)*uname_len, uname_str, (int)*aname_len, aname_str, *n_aname ) ; /* * Find the export for the aname (using as well Path or Tag ) */ for( pexport = nfs_param.pexportlist; pexport != NULL; pexport = pexport->next) { if(aname_str[0] != '/') { /* The input value may be a "Tag" */ if(!strncmp(aname_str, pexport->FS_tag, strlen( pexport->FS_tag ) ) ) { found = TRUE ; break; } } else { if(!strncmp(aname_str, pexport->fullpath, strlen( pexport->fullpath ) ) ) { found = TRUE ; break; } } } /* for */ /* Did we find something ? */ if( found == FALSE ) return _9p_rerror( preq9p, msgtag, ENOENT, plenout, preply ) ; if( *afid >= _9P_FID_PER_CONN ) return _9p_rerror( preq9p, msgtag, ERANGE, plenout, preply ) ; /* Set pexport and fid id in fid */ pfid= &preq9p->pconn->fids[*afid] ; pfid->pexport = pexport ; pfid->fid = *afid ; memcpy( &pfid->fsal_op_context, &pwkrdata->thread_fsal_context, sizeof( fsal_op_context_t ) ) ; /* Is user name provided as a string or as an uid ? */ if( *uname_len != 0 ) { /* Build the fid creds */ if( ( err = _9p_tools_get_fsal_op_context_by_name( *uname_len, uname_str, pfid ) ) != 0 ) return _9p_rerror( preq9p, msgtag, -err, plenout, preply ) ; } else { /* Build the fid creds */ if( ( err = _9p_tools_get_fsal_op_context_by_uid( *n_aname, pfid ) ) != 0 ) return _9p_rerror( preq9p, msgtag, -err, plenout, preply ) ; } /* Get the related pentry */ fsdata.fh_desc.start = (char *)pexport->proot_handle ; fsdata.fh_desc.len = sizeof( fsal_handle_t ) ; pfid->pentry = cache_inode_get( &fsdata, &fsalattr, &pfid->fsal_op_context, NULL, &cache_status ) ; if( pfid->pentry == NULL ) return _9p_rerror( preq9p, msgtag, _9p_tools_errno( cache_status ), plenout, preply ) ; /* Compute the qid */ pfid->qid.type = _9P_QTDIR ; pfid->qid.version = 0 ; /* No cache, we want the client to stay synchronous with the server */ pfid->qid.path = fsalattr.fileid ; /* Build the reply */ _9p_setinitptr( cursor, preply, _9P_RATTACH ) ; _9p_setptr( cursor, msgtag, u16 ) ; _9p_setqid( cursor, pfid->qid ) ; _9p_setendptr( cursor, preply ) ; _9p_checkbound( cursor, preply, plenout ) ; LogDebug( COMPONENT_9P, "RAUTH: tag=%u afid=%u qid=(type=%u,version=%u,path=%llu)", *msgtag, *afid, (u32)pfid->qid.type, pfid->qid.version, (unsigned long long)pfid->qid.path ) ; return 1 ; }
int nfs3_Fsinfo(nfs_arg_t * parg, exportlist_t * pexport, fsal_op_context_t * pcontext, cache_inode_client_t * pclient, hash_table_t * ht, struct svc_req *preq, nfs_res_t * pres) { static char __attribute__ ((__unused__)) funcName[] = "nfs3_Fsinfo"; cache_inode_status_t cache_status; cache_entry_t *pentry = NULL; cache_inode_fsal_data_t fsal_data; fsal_attrib_list_t attr; if(isDebug(COMPONENT_NFSPROTO)) { char str[LEN_FH_STR]; sprint_fhandle3(str, &(parg->arg_fsinfo3.fsroot)); LogDebug(COMPONENT_NFSPROTO, "REQUEST PROCESSING: Calling nfs3_Fsinfo handle: %s", str); } /* to avoid setting it on each error case */ pres->res_fsinfo3.FSINFO3res_u.resfail.obj_attributes.attributes_follow = FALSE; /* Convert file handle into a fsal_handle */ if(nfs3_FhandleToFSAL(&(parg->arg_fsinfo3.fsroot), &fsal_data.handle, pcontext) == 0) return NFS_REQ_DROP; /* Set the cookie */ fsal_data.cookie = DIR_START; /* Get the entry in the cache_inode */ if((pentry = cache_inode_get( &fsal_data, pexport->cache_inode_policy, &attr, ht, pclient, pcontext, &cache_status)) == NULL) { /* Stale NFS FH ? */ pres->res_fsinfo3.status = NFS3ERR_STALE; return NFS_REQ_OK; } /* * New fields were added to nfs_config_t to handle this value. We use * them */ #define FSINFO_FIELD pres->res_fsinfo3.FSINFO3res_u.resok FSINFO_FIELD.rtmax = pexport->MaxRead; FSINFO_FIELD.rtpref = pexport->PrefRead; /* This field is generally unused, it will be removed in V4 */ FSINFO_FIELD.rtmult = DEV_BSIZE; FSINFO_FIELD.wtmax = pexport->MaxWrite; FSINFO_FIELD.wtpref = pexport->PrefWrite; /* This field is generally unused, it will be removed in V4 */ FSINFO_FIELD.wtmult = DEV_BSIZE; FSINFO_FIELD.dtpref = pexport->PrefReaddir; FSINFO_FIELD.maxfilesize = FSINFO_MAX_FILESIZE; FSINFO_FIELD.time_delta.seconds = 1; FSINFO_FIELD.time_delta.nseconds = 0; LogFullDebug(COMPONENT_NFSPROTO, "rtmax = %d | rtpref = %d | trmult = %d", FSINFO_FIELD.rtmax, FSINFO_FIELD.rtpref, FSINFO_FIELD.rtmult); LogFullDebug(COMPONENT_NFSPROTO, "wtmax = %d | wtpref = %d | wrmult = %d", FSINFO_FIELD.wtmax, FSINFO_FIELD.wtpref, FSINFO_FIELD.wtmult); LogFullDebug(COMPONENT_NFSPROTO, "dtpref = %d | maxfilesize = %llu ", FSINFO_FIELD.dtpref, FSINFO_FIELD.maxfilesize); /* * Allow all kinds of operations to be performed on the server * through NFS v3 */ FSINFO_FIELD.properties = FSF3_LINK | FSF3_SYMLINK | FSF3_HOMOGENEOUS | FSF3_CANSETTIME; nfs_SetPostOpAttr(pcontext, pexport, pentry, &attr, &(pres->res_fsinfo3.FSINFO3res_u.resok.obj_attributes)); pres->res_fsinfo3.status = NFS3_OK; return NFS_REQ_OK; } /* nfs3_Fsinfo */
cache_entry_t *cache_inode_get_located(cache_inode_fsal_data_t * pfsdata, cache_entry_t * plocation, cache_inode_policy_t policy, fsal_attrib_list_t * pattr, hash_table_t * ht, cache_inode_client_t * pclient, fsal_op_context_t * pcontext, cache_inode_status_t * pstatus) { hash_buffer_t key, value; cache_entry_t *pentry = NULL; fsal_status_t fsal_status; cache_inode_create_arg_t create_arg; cache_inode_file_type_t type; int hrc = 0; fsal_attrib_list_t fsal_attributes; cache_inode_fsal_data_t *ppoolfsdata = NULL; memset(&create_arg, 0, sizeof(create_arg)); /* Set the return default to CACHE_INODE_SUCCESS */ *pstatus = CACHE_INODE_SUCCESS; /* stats */ /* cache_invalidate calls this with no context or client */ if (pclient) { pclient->stat.nb_call_total += 1; pclient->stat.func_stats.nb_call[CACHE_INODE_GET] += 1; } /* Turn the input to a hash key */ if(cache_inode_fsaldata_2_key(&key, pfsdata, pclient)) { *pstatus = CACHE_INODE_UNAPPROPRIATED_KEY; /* stats */ /* cache_invalidate calls this with no context or client */ if (pclient) { pclient->stat.func_stats.nb_err_unrecover[CACHE_INODE_GET] += 1; ppoolfsdata = (cache_inode_fsal_data_t *) key.pdata; ReleaseToPool(ppoolfsdata, &pclient->pool_key); } return NULL; } switch (hrc = HashTable_Get(ht, &key, &value)) { case HASHTABLE_SUCCESS: /* Entry exists in the cache and was found */ pentry = (cache_entry_t *) value.pdata; /* return attributes additionally */ *pattr = pentry->attributes; if ( !pclient ) { /* invalidate. Just return it to mark it stale and go on. */ return( pentry ); } break; case HASHTABLE_ERROR_NO_SUCH_KEY: if ( !pclient ) { /* invalidate. Just return */ return( NULL ); } /* Cache miss, allocate a new entry */ /* XXX I do not think this can happen with avl dirent cache */ if(pfsdata->cookie != DIR_START) { /* added for sanity check */ LogDebug(COMPONENT_CACHE_INODE, "cache_inode_get: pfsdata->cookie != DIR_START (=%"PRIu64") on object whose type is %u", pfsdata->cookie, cache_inode_fsal_type_convert(fsal_attributes.type)); pfsdata->cookie = DIR_START; /* Free this key */ cache_inode_release_fsaldata_key(&key, pclient); /* redo the call */ return cache_inode_get(pfsdata, policy, pattr, ht, pclient, pcontext, pstatus); } /* First, call FSAL to know what the object is */ fsal_attributes.asked_attributes = pclient->attrmask; fsal_status = FSAL_getattrs(&pfsdata->handle, pcontext, &fsal_attributes); if(FSAL_IS_ERROR(fsal_status)) { *pstatus = cache_inode_error_convert(fsal_status); LogDebug(COMPONENT_CACHE_INODE, "cache_inode_get: cache_inode_status=%u fsal_status=%u,%u ", *pstatus, fsal_status.major, fsal_status.minor); if(fsal_status.major == ERR_FSAL_STALE) { char handle_str[256]; snprintHandle(handle_str, 256, &pfsdata->handle); LogEvent(COMPONENT_CACHE_INODE, "cache_inode_get: Stale FSAL File Handle %s, fsal_status=(%u,%u)", handle_str, fsal_status.major, fsal_status.minor); *pstatus = CACHE_INODE_FSAL_ESTALE; } /* stats */ pclient->stat.func_stats.nb_err_unrecover[CACHE_INODE_GET] += 1; /* Free this key */ cache_inode_release_fsaldata_key(&key, pclient); return NULL; } /* The type has to be set in the attributes */ if(!FSAL_TEST_MASK(fsal_attributes.supported_attributes, FSAL_ATTR_TYPE)) { *pstatus = CACHE_INODE_FSAL_ERROR; /* stats */ pclient->stat.func_stats.nb_err_unrecover[CACHE_INODE_GET] += 1; /* Free this key */ cache_inode_release_fsaldata_key(&key, pclient); return NULL; } /* Get the cache_inode file type */ type = cache_inode_fsal_type_convert(fsal_attributes.type); if(type == SYMBOLIC_LINK) { if( CACHE_INODE_KEEP_CONTENT( policy ) ) { FSAL_CLEAR_MASK(fsal_attributes.asked_attributes); FSAL_SET_MASK(fsal_attributes.asked_attributes, pclient->attrmask); fsal_status = FSAL_readlink(&pfsdata->handle, pcontext, &create_arg.link_content, &fsal_attributes); } else { fsal_status.major = ERR_FSAL_NO_ERROR ; fsal_status.minor = 0 ; } if(FSAL_IS_ERROR(fsal_status)) { *pstatus = cache_inode_error_convert(fsal_status); /* stats */ pclient->stat.func_stats.nb_err_unrecover[CACHE_INODE_GET] += 1; /* Free this key */ cache_inode_release_fsaldata_key(&key, pclient); if(fsal_status.major == ERR_FSAL_STALE) { cache_inode_status_t kill_status; LogEvent(COMPONENT_CACHE_INODE, "cache_inode_get: Stale FSAL File Handle detected for pentry = %p, fsal_status=(%u,%u)", pentry, fsal_status.major, fsal_status.minor); if(cache_inode_kill_entry(pentry, NO_LOCK, ht, pclient, &kill_status) != CACHE_INODE_SUCCESS) LogCrit(COMPONENT_CACHE_INODE, "cache_inode_get: Could not kill entry %p, status = %u, fsal_status=(%u,%u)", pentry, kill_status, fsal_status.major, fsal_status.minor); *pstatus = CACHE_INODE_FSAL_ESTALE; } return NULL; } } /* Add the entry to the cache */ if ( type == 1) LogCrit(COMPONENT_CACHE_INODE,"inode get"); if((pentry = cache_inode_new_entry( pfsdata, &fsal_attributes, type, policy, &create_arg, NULL, /* never used to add a new DIR_CONTINUE within this function */ ht, pclient, pcontext, FALSE, /* This is a population, not a creation */ pstatus ) ) == NULL ) { /* stats */ pclient->stat.func_stats.nb_err_unrecover[CACHE_INODE_GET] += 1; /* Free this key */ cache_inode_release_fsaldata_key(&key, pclient); return NULL; } /* Set the returned attributes */ *pattr = fsal_attributes; /* Now, exit the switch/case and returns */ break; default: /* This should not happened */ *pstatus = CACHE_INODE_INVALID_ARGUMENT; LogCrit(COMPONENT_CACHE_INODE, "cache_inode_get returning CACHE_INODE_INVALID_ARGUMENT - this should not have happened"); if ( !pclient ) { /* invalidate. Just return */ return( NULL ); } /* stats */ pclient->stat.func_stats.nb_err_unrecover[CACHE_INODE_GET] += 1; /* Free this key */ cache_inode_release_fsaldata_key(&key, pclient); return NULL; break; } /* Want to ASSERT pclient at this point */ *pstatus = CACHE_INODE_SUCCESS; if (pentry->object.symlink != NULL) { int stop_here; stop_here = 1; if (stop_here) { stop_here = 2; } } /* valid the found entry, if this is not feasable, returns nothing to the client */ if( plocation != NULL ) { if( plocation != pentry ) { P_w(&pentry->lock); if((*pstatus = cache_inode_valid(pentry, CACHE_INODE_OP_GET, pclient)) != CACHE_INODE_SUCCESS) { V_w(&pentry->lock); pentry = NULL; } V_w(&pentry->lock); } } /* stats */ pclient->stat.func_stats.nb_success[CACHE_INODE_GET] += 1; /* Free this key */ cache_inode_release_fsaldata_key(&key, pclient); return pentry; } /* cache_inode_get_located */
int nlm_process_parameters(struct svc_req * preq, bool_t exclusive, nlm4_lock * alock, fsal_lock_param_t * plock, cache_entry_t ** ppentry, fsal_op_context_t * pcontext, care_t care, state_nsm_client_t ** ppnsm_client, state_nlm_client_t ** ppnlm_client, state_owner_t ** ppowner, state_block_data_t ** ppblock_data) { cache_inode_fsal_data_t fsal_data; fsal_attrib_list_t attr; cache_inode_status_t cache_status; SVCXPRT *ptr_svc = preq->rq_xprt; int rc; *ppnsm_client = NULL; *ppnlm_client = NULL; *ppowner = NULL; /* Convert file handle into a cache entry */ if(alock->fh.n_len > MAX_NETOBJ_SZ || !nfs3_FhandleToFSAL((nfs_fh3 *) &alock->fh, &fsal_data.fh_desc, pcontext)) { /* handle is not valid */ return NLM4_STALE_FH; } /* Now get the cached inode attributes */ *ppentry = cache_inode_get(&fsal_data, &attr, pcontext, NULL, &cache_status); if(*ppentry == NULL) { /* handle is not valid */ return NLM4_STALE_FH; } *ppnsm_client = get_nsm_client(care, ptr_svc, alock->caller_name); if(*ppnsm_client == NULL) { /* If NSM Client is not found, and we don't care (such as unlock), * just return GRANTED (the unlock must succeed, there can't be * any locks). */ if(care != CARE_NOT) rc = NLM4_DENIED_NOLOCKS; else rc = NLM4_GRANTED; goto out_put; } *ppnlm_client = get_nlm_client(care, ptr_svc, *ppnsm_client, alock->caller_name); if(*ppnlm_client == NULL) { /* If NLM Client is not found, and we don't care (such as unlock), * just return GRANTED (the unlock must succeed, there can't be * any locks). */ dec_nsm_client_ref(*ppnsm_client); if(care != CARE_NOT) rc = NLM4_DENIED_NOLOCKS; else rc = NLM4_GRANTED; goto out_put; } *ppowner = get_nlm_owner(care, *ppnlm_client, &alock->oh, alock->svid); if(*ppowner == NULL) { LogDebug(COMPONENT_NLM, "Could not get NLM Owner"); dec_nsm_client_ref(*ppnsm_client); dec_nlm_client_ref(*ppnlm_client); *ppnlm_client = NULL; /* If owner is not found, and we don't care (such as unlock), * just return GRANTED (the unlock must succeed, there can't be * any locks). */ if(care != CARE_NOT) rc = NLM4_DENIED_NOLOCKS; else rc = NLM4_GRANTED; goto out_put; } if(ppblock_data != NULL) { *ppblock_data = gsh_calloc(1, sizeof(**ppblock_data)); /* Fill in the block data, if we don't get one, we will just proceed * without (which will mean the lock doesn't block. */ if(*ppblock_data != NULL) { if(copy_xprt_addr(&(*ppblock_data)->sbd_block_data.sbd_nlm_block_data.sbd_nlm_hostaddr, ptr_svc) == 0) { LogFullDebug(COMPONENT_NLM, "copy_xprt_addr failed for Program %d, Version %d, Function %d", (int)preq->rq_prog, (int)preq->rq_vers, (int)preq->rq_proc); gsh_free(*ppblock_data); *ppblock_data = NULL; rc = NLM4_FAILED; goto out_put; } (*ppblock_data)->sbd_granted_callback = nlm_granted_callback; (*ppblock_data)->sbd_block_data.sbd_nlm_block_data.sbd_nlm_fh.n_bytes = (*ppblock_data)->sbd_block_data.sbd_nlm_block_data.sbd_nlm_fh_buf; (*ppblock_data)->sbd_block_data.sbd_nlm_block_data.sbd_nlm_fh.n_len = alock->fh.n_len; memcpy((*ppblock_data)->sbd_block_data.sbd_nlm_block_data.sbd_nlm_fh_buf, alock->fh.n_bytes, alock->fh.n_len); /* FSF TODO: Ultimately I think the following will go away, we won't need the context, just the export */ /* Copy credentials from pcontext */ #ifdef _USE_HPSS /** @todo : PhD: Think about removing hpsscred_t from FSAL */ (*ppblock_data)->sbd_credential.user = pcontext->credential.hpss_usercred.Uid ; (*ppblock_data)->sbd_credential.group = pcontext->credential.hpss_usercred.Gid ; #else (*ppblock_data)->sbd_credential = pcontext->credential; /* Copy the alt groups list */ if(pcontext->credential.nbgroups != 0) { (*ppblock_data)->sbd_credential.alt_groups = gsh_malloc(sizeof(gid_t) * pcontext->credential.nbgroups); if((*ppblock_data)->sbd_credential.alt_groups == NULL) { gsh_free(*ppblock_data); *ppblock_data = NULL; rc = NLM4_FAILED; goto out_put; } memcpy((*ppblock_data)->sbd_credential.alt_groups, pcontext->credential.alt_groups, pcontext->credential.nbgroups); } #endif } } /* Fill in plock */ plock->lock_type = exclusive ? FSAL_LOCK_W : FSAL_LOCK_R; plock->lock_start = alock->l_offset; plock->lock_length = alock->l_len; LogFullDebug(COMPONENT_NLM, "Parameters Processed"); return -1; out_put: cache_inode_put(*ppentry); *ppentry = NULL; return rc; }
int nlm4_Unlock(nfs_arg_t * parg /* IN */ , exportlist_t * pexport /* IN */ , fsal_op_context_t * pcontext /* IN */ , cache_inode_client_t * pclient /* INOUT */ , hash_table_t * ht /* INOUT */ , struct svc_req *preq /* IN */ , nfs_res_t * pres /* OUT */ ) { int lck_cnt, lck_state; nlm4_unlockargs *arg; cache_entry_t *pentry; fsal_attrib_list_t attr; nlm_lock_entry_t *nlm_entry; cache_inode_status_t cache_status; cache_inode_fsal_data_t fsal_data; LogFullDebug(COMPONENT_NFSPROTO, "REQUEST PROCESSING: Calling nlm4_Lock"); if(in_nlm_grace_period()) { pres->res_nlm4test.test_stat.stat = NLM4_DENIED_GRACE_PERIOD; return NFS_REQ_OK; } /* Convert file handle into a cache entry */ arg = &parg->arg_nlm4_unlock; if(!nfs3_FhandleToFSAL((nfs_fh3 *) & (arg->alock.fh), &fsal_data.handle, pcontext)) { /* handle is not valid */ pres->res_nlm4.stat.stat = NLM4_STALE_FH; /* * Should we do a REQ_OK so that the client get * a response ? FIXME!! */ return NFS_REQ_DROP; } /* Now get the cached inode attributes */ fsal_data.cookie = DIR_START; if((pentry = cache_inode_get(&fsal_data, &attr, ht, pclient, pcontext, &cache_status)) == NULL) { /* handle is not valid */ pres->res_nlm4.stat.stat = NLM4_STALE_FH; return NFS_REQ_OK; } /* * nlm_find_lock_entry with state NLM4_GRANTED will search for lock * in both blocked and granted state. We can get an unlock request * even for a lock in blocked state because grant rpc response could * get dropped and the client can think that lock is granted but the * server still consider it locked. */ nlm_entry = nlm_find_lock_entry(&(arg->alock), 0, NLM4_GRANTED); if(!nlm_entry) { pres->res_nlm4.stat.stat = NLM4_DENIED_NOLOCKS; return NFS_REQ_OK; } lck_state = nlm_lock_entry_get_state(nlm_entry); pres->res_nlm4.stat.stat = NLM4_GRANTED; lck_cnt = nlm_delete_lock_entry(&(arg->alock)); nlm_unmonitor_host(arg->alock.caller_name); /* * Now check whether we have blocked locks. * if found grant them the lock */ if(lck_state == NLM4_GRANTED) nlm_grant_blocked_locks(&(arg->alock.fh)); nlm_lock_entry_dec_ref(nlm_entry); return NFS_REQ_OK; }
/** * * cache_inode_get: Gets an entry by using its fsdata as a key and caches it if needed. * * Gets an entry by using its fsdata as a key and caches it if needed. * ASSUMPTION: DIR_CONT entries are always garbabbaged before their related DIR_BEGINNG * * @param fsdata [IN] file system data * @param pattr [OUT] pointer to the attributes for the result. * @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 the pointer to the entry is successfull, NULL otherwise. * */ cache_entry_t *cache_inode_get(cache_inode_fsal_data_t * pfsdata, fsal_attrib_list_t * pattr, hash_table_t * ht, cache_inode_client_t * pclient, fsal_op_context_t * pcontext, cache_inode_status_t * pstatus) { hash_buffer_t key, value; cache_entry_t *pentry = NULL; fsal_status_t fsal_status; cache_inode_create_arg_t create_arg; cache_inode_file_type_t type; int hrc = 0; fsal_attrib_list_t fsal_attributes; cache_inode_fsal_data_t *ppoolfsdata = NULL; /* 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_GET] += 1; /* Turn the input to a hash key */ if(cache_inode_fsaldata_2_key(&key, pfsdata, pclient)) { *pstatus = CACHE_INODE_UNAPPROPRIATED_KEY; /* stats */ pclient->stat.func_stats.nb_err_unrecover[CACHE_INODE_GET] += 1; ppoolfsdata = (cache_inode_fsal_data_t *) key.pdata; RELEASE_PREALLOC(ppoolfsdata, pclient->pool_key, next_alloc); return NULL; } switch (hrc = HashTable_Get(ht, &key, &value)) { case HASHTABLE_SUCCESS: /* Entry exists in the cache and was found */ pentry = (cache_entry_t *) value.pdata; /* return attributes additionally */ cache_inode_get_attributes(pentry, pattr); break; case HASHTABLE_ERROR_NO_SUCH_KEY: /* Cache miss, allocate a new entry */ /* If we ask for a dir cont (in this case pfsdata.cookie != FSAL_DIR_BEGINNING, we have * a client who performs a readdir in the middle of a directory, when the direcctories * have been garbbage. we must search for the DIR_BEGIN related to this DIR_CONT */ if(pfsdata->cookie != DIR_START) { /* added for sanity check */ LogDebug(COMPONENT_CACHE_INODE_GC, "=======> Pb cache_inode_get: line %u pfsdata->cookie != DIR_START (=%u) on object whose type is %u", __LINE__, pfsdata->cookie, cache_inode_fsal_type_convert(fsal_attributes.type)); pfsdata->cookie = DIR_START; /* Free this key */ cache_inode_release_fsaldata_key(&key, pclient); /* redo the call */ return cache_inode_get(pfsdata, pattr, ht, pclient, pcontext, pstatus); } /* First, call FSAL to know what the object is */ fsal_attributes.asked_attributes = pclient->attrmask; fsal_status = FSAL_getattrs(&pfsdata->handle, pcontext, &fsal_attributes); if(FSAL_IS_ERROR(fsal_status)) { *pstatus = cache_inode_error_convert(fsal_status); LogDebug(COMPONENT_CACHE_INODE_GC, "cache_inode_get: line %u cache_inode_status=%u fsal_status=%u,%u ", __LINE__, *pstatus, fsal_status.major, fsal_status.minor); if(fsal_status.major == ERR_FSAL_STALE) { char handle_str[256]; snprintHandle(handle_str, 256, &pfsdata->handle); LogEvent(COMPONENT_CACHE_INODE_GC,"cache_inode_get: Stale FSAL File Handle %s", handle_str); *pstatus = CACHE_INODE_FSAL_ESTALE; } /* stats */ pclient->stat.func_stats.nb_err_unrecover[CACHE_INODE_GET] += 1; /* Free this key */ cache_inode_release_fsaldata_key(&key, pclient); return NULL; } /* The type has to be set in the attributes */ if(!FSAL_TEST_MASK(fsal_attributes.supported_attributes, FSAL_ATTR_TYPE)) { *pstatus = CACHE_INODE_FSAL_ERROR; /* stats */ pclient->stat.func_stats.nb_err_unrecover[CACHE_INODE_GET] += 1; /* Free this key */ cache_inode_release_fsaldata_key(&key, pclient); return NULL; } /* Get the cache_inode file type */ type = cache_inode_fsal_type_convert(fsal_attributes.type); if(type == SYMBOLIC_LINK) { FSAL_CLEAR_MASK(fsal_attributes.asked_attributes); FSAL_SET_MASK(fsal_attributes.asked_attributes, pclient->attrmask); fsal_status = FSAL_readlink(&pfsdata->handle, pcontext, &create_arg.link_content, &fsal_attributes); if(FSAL_IS_ERROR(fsal_status)) { *pstatus = cache_inode_error_convert(fsal_status); /* stats */ pclient->stat.func_stats.nb_err_unrecover[CACHE_INODE_GET] += 1; /* Free this key */ cache_inode_release_fsaldata_key(&key, pclient); if(fsal_status.major == ERR_FSAL_STALE) { cache_inode_status_t kill_status; LogDebug(COMPONENT_CACHE_INODE_GC, "cache_inode_get: 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_GC,"cache_inode_get: Could not kill entry %p, status = %u", pentry, kill_status); *pstatus = CACHE_INODE_FSAL_ESTALE; } return NULL; } } /* Add the entry to the cache */ if((pentry = cache_inode_new_entry(pfsdata, &fsal_attributes, type, &create_arg, NULL, /* never used to add a new DIR_CONTINUE within the scope of this function */ ht, pclient, pcontext, FALSE, /* This is a population, not a creation */ pstatus)) == NULL) { /* stats */ pclient->stat.func_stats.nb_err_unrecover[CACHE_INODE_GET] += 1; /* Free this key */ cache_inode_release_fsaldata_key(&key, pclient); return NULL; } /* Set the returned attributes */ *pattr = fsal_attributes; /* Now, exit the switch/case and returns */ break; default: /* This should not happened */ *pstatus = CACHE_INODE_INVALID_ARGUMENT; /* stats */ pclient->stat.func_stats.nb_err_unrecover[CACHE_INODE_GET] += 1; /* Free this key */ cache_inode_release_fsaldata_key(&key, pclient); return NULL; break; } *pstatus = CACHE_INODE_SUCCESS; /* valid the found entry, if this is not feasable, returns nothing to the client */ P_w(&pentry->lock); if((*pstatus = cache_inode_valid(pentry, CACHE_INODE_OP_GET, pclient)) != CACHE_INODE_SUCCESS) { V_w(&pentry->lock); pentry = NULL; } V_w(&pentry->lock); /* stats */ pclient->stat.func_stats.nb_success[CACHE_INODE_GET] += 1; /* Free this key */ cache_inode_release_fsaldata_key(&key, pclient); return pentry; } /* cache_inode_get */
int _9p_attach( _9p_request_data_t * preq9p, void * pworker_data, u32 * plenout, char * preply) { char * cursor = preq9p->_9pmsg + _9P_HDR_SIZE + _9P_TYPE_SIZE ; nfs_worker_data_t * pwkrdata = (nfs_worker_data_t *)pworker_data ; u16 * msgtag = NULL ; u32 * fid = NULL ; u32 * afid = NULL ; u16 * uname_len = NULL ; char * uname_str = NULL ; u16 * aname_len = NULL ; char * aname_str = NULL ; u32 * n_aname = NULL ; fsal_attrib_list_t fsalattr ; int rc = 0 ; u32 err = 0 ; _9p_fid_t * pfid = NULL ; exportlist_t * pexport = NULL; unsigned int found = FALSE; cache_inode_status_t cache_status ; cache_inode_fsal_data_t fsdata ; if ( !preq9p || !pworker_data || !plenout || !preply ) return -1 ; /* Get data */ _9p_getptr( cursor, msgtag, u16 ) ; _9p_getptr( cursor, fid, u32 ) ; _9p_getptr( cursor, afid, u32 ) ; _9p_getstr( cursor, uname_len, uname_str ) ; _9p_getstr( cursor, aname_len, aname_str ) ; _9p_getptr( cursor, n_aname, u32 ) ; LogDebug( COMPONENT_9P, "TATTACH: tag=%u fid=%u afid=%d uname='%.*s' aname='%.*s' n_uname=%d", (u32)*msgtag, *fid, *afid, (int)*uname_len, uname_str, (int)*aname_len, aname_str, *n_aname ) ; /* * Find the export for the aname (using as well Path or Tag ) */ for( pexport = nfs_param.pexportlist; pexport != NULL; pexport = pexport->next) { if(aname_str[0] != '/') { /* The input value may be a "Tag" */ if(!strncmp(aname_str, pexport->FS_tag, strlen( pexport->FS_tag ) ) ) { found = TRUE ; break; } } else { if(!strncmp(aname_str, pexport->fullpath, strlen( pexport->fullpath ) ) ) { found = TRUE ; break; } } } /* for */ /* Did we find something ? */ if( found == FALSE ) { err = ENOENT ; rc = _9p_rerror( preq9p, msgtag, &err, plenout, preply ) ; return rc ; } if( *fid >= _9P_FID_PER_CONN ) { err = ERANGE ; rc = _9p_rerror( preq9p, msgtag, &err, plenout, preply ) ; return rc ; } /* Set pexport and fid id in fid */ pfid= &preq9p->pconn->fids[*fid] ; pfid->pexport = pexport ; pfid->fid = *fid ; #ifdef _USE_SHARED_FSAL /* At this step, the export entry is known and it's required to use the right fsalid */ FSAL_SetId( pexport->fsalid ) ; memcpy( &pfid->fsal_op_context, &pwkrdata->thread_fsal_context[pexport->fsalid], sizeof( fsal_op_context_t ) ) ; #else memcpy( &pfid->fsal_op_context, &pwkrdata->thread_fsal_context, sizeof( fsal_op_context_t ) ) ; #endif /* Is user name provided as a string or as an uid ? */ if( *uname_len != 0 ) { /* Build the fid creds */ if( ( err = _9p_tools_get_fsal_op_context_by_name( *uname_len, uname_str, pfid ) ) != 0 ) { err = -err ; /* The returned value from 9p service functions is always negative is case of errors */ rc = _9p_rerror( preq9p, msgtag, &err, plenout, preply ) ; return rc ; } } else { /* Build the fid creds */ if( ( err = _9p_tools_get_fsal_op_context_by_uid( *n_aname, pfid ) ) != 0 ) { err = -err ; /* The returned value from 9p service functions is always negative is case of errors */ rc = _9p_rerror( preq9p, msgtag, &err, plenout, preply ) ; return rc ; } } /* Get the related pentry */ memcpy( (char *)&fsdata.handle, (char *)pexport->proot_handle, sizeof( fsal_handle_t ) ) ; fsdata.cookie = 0; pfid->pentry = cache_inode_get( &fsdata, pexport->cache_inode_policy, &fsalattr, pwkrdata->ht, &pwkrdata->cache_inode_client, &pfid->fsal_op_context, &cache_status ) ; if( pfid->pentry == NULL ) { err = _9p_tools_errno( cache_status ) ; ; rc = _9p_rerror( preq9p, msgtag, &err, plenout, preply ) ; return rc ; } /* Compute the qid */ pfid->qid.type = _9P_QTDIR ; pfid->qid.version = 0 ; /* No cache, we want the client to stay synchronous with the server */ pfid->qid.path = fsalattr.fileid ; /* Cache the attr */ _9p_tools_fsal_attr2stat( &fsalattr, &pfid->attr ) ; /* Build the reply */ _9p_setinitptr( cursor, preply, _9P_RATTACH ) ; _9p_setptr( cursor, msgtag, u16 ) ; _9p_setqid( cursor, pfid->qid ) ; _9p_setendptr( cursor, preply ) ; _9p_checkbound( cursor, preply, plenout ) ; LogDebug( COMPONENT_9P, "RATTACH: tag=%u fid=%u qid=(type=%u,version=%u,path=%llu)", *msgtag, *fid, (u32)pfid->qid.type, pfid->qid.version, (unsigned long long)pfid->qid.path ) ; return 1 ; }
int nlm_process_parameters(struct svc_req * preq, bool_t exclusive, nlm4_lock * alock, state_lock_desc_t * plock, hash_table_t * ht, cache_entry_t ** ppentry, fsal_op_context_t * pcontext, cache_inode_client_t * pclient, care_t care, state_nsm_client_t ** ppnsm_client, state_nlm_client_t ** ppnlm_client, state_owner_t ** ppowner, state_block_data_t ** ppblock_data) { cache_inode_fsal_data_t fsal_data; fsal_attrib_list_t attr; cache_inode_status_t cache_status; SVCXPRT *ptr_svc = preq->rq_xprt; *ppnsm_client = NULL; *ppnlm_client = NULL; *ppowner = NULL; /* Convert file handle into a cache entry */ if(alock->fh.n_len > MAX_NETOBJ_SZ || !nfs3_FhandleToFSAL((nfs_fh3 *) &alock->fh, &fsal_data.handle, pcontext)) { /* handle is not valid */ return NLM4_STALE_FH; } /* Now get the cached inode attributes */ fsal_data.cookie = DIR_START; *ppentry = cache_inode_get(&fsal_data, CACHE_INODE_JOKER_POLICY, &attr, ht, pclient, pcontext, &cache_status); if(*ppentry == NULL) { /* handle is not valid */ return NLM4_STALE_FH; } *ppnsm_client = get_nsm_client(care, ptr_svc, alock->caller_name); if(*ppnsm_client == NULL) { /* If NSM Client is not found, and we don't care (such as unlock), * just return GRANTED (the unlock must succeed, there can't be * any locks). */ if(care != CARE_NOT) return NLM4_DENIED_NOLOCKS; else return NLM4_GRANTED; } *ppnlm_client = get_nlm_client(care, ptr_svc, *ppnsm_client, alock->caller_name); if(*ppnlm_client == NULL) { /* If NLM Client is not found, and we don't care (such as unlock), * just return GRANTED (the unlock must succeed, there can't be * any locks). */ dec_nsm_client_ref(*ppnsm_client); if(care != CARE_NOT) return NLM4_DENIED_NOLOCKS; else return NLM4_GRANTED; } *ppowner = get_nlm_owner(care, *ppnlm_client, &alock->oh, alock->svid); if(*ppowner == NULL) { LogDebug(COMPONENT_NLM, "Could not get NLM Owner"); dec_nsm_client_ref(*ppnsm_client); dec_nlm_client_ref(*ppnlm_client); *ppnlm_client = NULL; /* If owner is not found, and we don't care (such as unlock), * just return GRANTED (the unlock must succeed, there can't be * any locks). */ if(care) return NLM4_DENIED_NOLOCKS; else return NLM4_GRANTED; } if(ppblock_data != NULL) { *ppblock_data = (state_block_data_t *) Mem_Alloc_Label(sizeof(**ppblock_data), "NLM_Block_Data"); /* Fill in the block data, if we don't get one, we will just proceed * without (which will mean the lock doesn't block. */ if(*ppblock_data != NULL) { memset(*ppblock_data, 0, sizeof(**ppblock_data)); if(copy_xprt_addr(&(*ppblock_data)->sbd_block_data.sbd_nlm_block_data.sbd_nlm_hostaddr, ptr_svc) == 0) { LogFullDebug(COMPONENT_NLM, "copy_xprt_addr failed for Program %d, Version %d, Function %d", (int)preq->rq_prog, (int)preq->rq_vers, (int)preq->rq_proc); Mem_Free(*ppblock_data); *ppblock_data = NULL; return NLM4_FAILED; } (*ppblock_data)->sbd_granted_callback = nlm_granted_callback; (*ppblock_data)->sbd_block_data.sbd_nlm_block_data.sbd_nlm_fh.n_bytes = (*ppblock_data)->sbd_block_data.sbd_nlm_block_data.sbd_nlm_fh_buf; (*ppblock_data)->sbd_block_data.sbd_nlm_block_data.sbd_nlm_fh.n_len = alock->fh.n_len; memcpy((*ppblock_data)->sbd_block_data.sbd_nlm_block_data.sbd_nlm_fh_buf, alock->fh.n_bytes, alock->fh.n_len); /* FSF TODO: Ultimately I think the following will go away, we won't need the context, just the export */ /* Copy credentials from pcontext */ (*ppblock_data)->sbd_block_data.sbd_nlm_block_data.sbd_credential = pcontext->credential; } } /* Fill in plock */ plock->sld_type = exclusive ? STATE_LOCK_W : STATE_LOCK_R; plock->sld_offset = alock->l_offset; plock->sld_length = alock->l_len; LogFullDebug(COMPONENT_NLM, "Parameters Processed"); return -1; }
/** * * 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_readdir_nonamecache: Reads a directory without populating the name cache (no dirents created). * * Reads a directory without populating the name cache (no dirents created). * * @param pentry [IN] entry for the parent directory to be read. * @param cookie [IN] cookie for the readdir operation (basically the offset). * @param nbwanted [IN] Maximum number of directory entries wanted. * @param peod_met [OUT] A flag to know if end of directory was met during this call. * @param dirent_array [OUT] the resulting array of found directory entries. * @param ht [IN] hash table used for the cache, unused in this call. * @param unlock [OUT] the caller shall release read-lock on pentry when done * @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 * */ static cache_inode_status_t cache_inode_readdir_nonamecache( cache_entry_t * pentry_dir, cache_inode_policy_t policy, uint64_t cookie, unsigned int nbwanted, unsigned int *pnbfound, uint64_t *pend_cookie, cache_inode_endofdir_t *peod_met, cache_inode_dir_entry_t **dirent_array, hash_table_t *ht, int *unlock, cache_inode_client_t *pclient, fsal_op_context_t *pcontext, cache_inode_status_t *pstatus) { fsal_dir_t fsal_dirhandle; fsal_status_t fsal_status; fsal_attrib_list_t dir_attributes; fsal_cookie_t begin_cookie; fsal_cookie_t end_cookie; fsal_count_t iter; fsal_boolean_t fsal_eod; fsal_dirent_t fsal_dirent_array[FSAL_READDIR_SIZE + 20]; cache_inode_fsal_data_t entry_fsdata; /* Set the return default to CACHE_INODE_SUCCESS */ *pstatus = CACHE_INODE_SUCCESS; /* Only DIRECTORY entries are concerned */ if(pentry_dir->internal_md.type != DIRECTORY) { *pstatus = CACHE_INODE_BAD_TYPE; return *pstatus; } LogFullDebug(COMPONENT_NFS_READDIR, "About to readdir in cache_inode_readdir_nonamecache: pentry=%p " "cookie=%"PRIu64, pentry_dir, cookie ) ; /* Open the directory */ dir_attributes.asked_attributes = pclient->attrmask; #ifdef _USE_MFSL fsal_status = MFSL_opendir(&pentry_dir->mobject, pcontext, &pclient->mfsl_context, &fsal_dirhandle, &dir_attributes, NULL); #else fsal_status = FSAL_opendir(&pentry_dir->object.dir.handle, pcontext, &fsal_dirhandle, &dir_attributes); #endif if(FSAL_IS_ERROR(fsal_status)) { *pstatus = cache_inode_error_convert(fsal_status); if(fsal_status.major == ERR_FSAL_STALE) { cache_inode_status_t kill_status; LogEvent(COMPONENT_CACHE_INODE, "cache_inode_readdir: Stale FSAL File Handle detected for pentry = %p, fsal_status=(%u,%u)", pentry_dir, fsal_status.major, fsal_status.minor); if(cache_inode_kill_entry(pentry_dir, WT_LOCK, ht, pclient, &kill_status) != CACHE_INODE_SUCCESS) LogCrit(COMPONENT_CACHE_INODE, "cache_inode_readdir: Could not kill entry %p, status = %u", pentry_dir, kill_status); *pstatus = CACHE_INODE_FSAL_ESTALE; } return *pstatus; } /* Loop for readding the directory */ // memcpy( &(begin_cookie.data), &cookie, sizeof( uint64_t ) ) ; FSAL_SET_COOKIE_BY_OFFSET( begin_cookie, cookie ) ; fsal_eod = FALSE; #ifdef _USE_MFSL fsal_status = MFSL_readdir( &fsal_dirhandle, begin_cookie, pclient->attrmask, nbwanted * sizeof(fsal_dirent_t), fsal_dirent_array, &end_cookie, (fsal_count_t *)pnbfound, &fsal_eod, &pclient->mfsl_context, NULL); #else fsal_status = FSAL_readdir( &fsal_dirhandle, begin_cookie, pclient->attrmask, nbwanted * sizeof(fsal_dirent_t), fsal_dirent_array, &end_cookie, (fsal_count_t *)pnbfound, &fsal_eod); #endif if(FSAL_IS_ERROR(fsal_status)) { *pstatus = cache_inode_error_convert(fsal_status); return *pstatus; } for( iter = 0 ; iter < *pnbfound ; iter ++ ) { /* cache_inode_readdir does not return . or .. */ if(!FSAL_namecmp(&(fsal_dirent_array[iter].name), (fsal_name_t *) & FSAL_DOT) || !FSAL_namecmp(&(fsal_dirent_array[iter].name), (fsal_name_t *) & FSAL_DOT_DOT)) continue; /* Get the related pentry without populating the name cache (but eventually populating the attrs cache */ entry_fsdata.handle = fsal_dirent_array[iter].handle; entry_fsdata.cookie = 0; /* XXX needed? */ /* Allocate a dirent to be returned to the client */ /** @todo Make sure this piece of memory once the data are used */ GetFromPool( dirent_array[iter], &pclient->pool_dir_entry, cache_inode_dir_entry_t); if( dirent_array[iter] == NULL ) { *pstatus = CACHE_INODE_MALLOC_ERROR; return *pstatus; } /* fills in the dirent_array */ if( ( dirent_array[iter]->pentry= cache_inode_get( &entry_fsdata, policy, &fsal_dirent_array[iter].attributes, ht, pclient, pcontext, pstatus ) ) == NULL ) return *pstatus ; fsal_status = FSAL_namecpy( &dirent_array[iter]->name, &fsal_dirent_array[iter].name ) ; if(FSAL_IS_ERROR(fsal_status)) { *pstatus = cache_inode_error_convert(fsal_status); return *pstatus; } (void) FSAL_cookie_to_uint64( &fsal_dirent_array[iter].handle, pcontext, &fsal_dirent_array[iter].cookie, &dirent_array[iter]->fsal_cookie); dirent_array[iter]->cookie = dirent_array[iter]->fsal_cookie ; } /* for( iter = 0 ; iter < nbfound ; iter ++ ) */ if( fsal_eod == TRUE ) *peod_met = END_OF_DIR ; else *peod_met = TO_BE_CONTINUED ; /* Do not forget to set returned end cookie */ //memcpy( pend_cookie, &(end_cookie.data), sizeof( uint64_t ) ) ; FSAL_SET_POFFSET_BY_COOKIE( end_cookie, pend_cookie ) ; LogFullDebug(COMPONENT_NFS_READDIR, "End of readdir in cache_inode_readdir_nonamecache: pentry=%p " "cookie=%"PRIu64, pentry_dir, *pend_cookie ) ; /* Close the directory */ #ifdef _USE_MFSL fsal_status = MFSL_closedir(&fsal_dirhandle, &pclient->mfsl_context, NULL); #else fsal_status = FSAL_closedir(&fsal_dirhandle); #endif if(FSAL_IS_ERROR(fsal_status)) { *pstatus = cache_inode_error_convert(fsal_status); return *pstatus; } return CACHE_INODE_SUCCESS ; } /* cache_inode_readdir_nomanecache */
int nlm_process_share_parms(struct svc_req * preq, nlm4_share * share, cache_entry_t ** ppentry, fsal_op_context_t * pcontext, care_t care, state_nsm_client_t ** ppnsm_client, state_nlm_client_t ** ppnlm_client, state_owner_t ** ppowner) { cache_inode_fsal_data_t fsal_data; fsal_attrib_list_t attr; cache_inode_status_t cache_status; SVCXPRT *ptr_svc = preq->rq_xprt; int rc; *ppnsm_client = NULL; *ppnlm_client = NULL; *ppowner = NULL; /* Convert file handle into a cache entry */ if(share->fh.n_len > MAX_NETOBJ_SZ || !nfs3_FhandleToFSAL((nfs_fh3 *) &share->fh, &fsal_data.fh_desc, pcontext)) { /* handle is not valid */ return NLM4_STALE_FH; } /* Now get the cached inode attributes */ *ppentry = cache_inode_get(&fsal_data, &attr, pcontext, NULL, &cache_status); if(*ppentry == NULL) { /* handle is not valid */ return NLM4_STALE_FH; } *ppnsm_client = get_nsm_client(care, ptr_svc, share->caller_name); if(*ppnsm_client == NULL) { /* If NSM Client is not found, and we don't care (for unshare), * just return GRANTED (the unshare must succeed, there can't be * any shares). */ if(care != CARE_NOT) rc = NLM4_DENIED_NOLOCKS; else rc = NLM4_GRANTED; goto out_put; } *ppnlm_client = get_nlm_client(care, ptr_svc, *ppnsm_client, share->caller_name); if(*ppnlm_client == NULL) { /* If NLM Client is not found, and we don't care (such as unlock), * just return GRANTED (the unlock must succeed, there can't be * any locks). */ dec_nsm_client_ref(*ppnsm_client); if(care != CARE_NOT) rc = NLM4_DENIED_NOLOCKS; else rc = NLM4_GRANTED; goto out_put; } *ppowner = get_nlm_owner(care, *ppnlm_client, &share->oh, 0); if(*ppowner == NULL) { LogDebug(COMPONENT_NLM, "Could not get NLM Owner"); dec_nsm_client_ref(*ppnsm_client); dec_nlm_client_ref(*ppnlm_client); *ppnlm_client = NULL; /* If owner is not found, and we don't care (such as unlock), * just return GRANTED (the unlock must succeed, there can't be * any locks). */ if(care != CARE_NOT) rc = NLM4_DENIED_NOLOCKS; else rc = NLM4_GRANTED; goto out_put; } LogFullDebug(COMPONENT_NLM, "Parameters Processed"); return -1; out_put: cache_inode_put(*ppentry); *ppentry = NULL; return rc; }
int nfs3_Commit(nfs_arg_t * parg, exportlist_t * pexport, fsal_op_context_t * pcontext, cache_inode_client_t * pclient, hash_table_t * ht, struct svc_req *preq, nfs_res_t * pres) { static char __attribute__ ((__unused__)) funcName[] = "nfs3_Access"; cache_inode_status_t cache_status; cache_entry_t *pentry = NULL; cache_inode_fsal_data_t fsal_data; fsal_attrib_list_t pre_attr; fsal_attrib_list_t *ppre_attr; uint64_t typeofcommit; if(isDebug(COMPONENT_NFSPROTO)) { char str[LEN_FH_STR]; sprint_fhandle3(str, &(parg->arg_commit3.file)); LogDebug(COMPONENT_NFSPROTO, "REQUEST PROCESSING: Calling nfs3_Commit handle: %s", str); } /* to avoid setting it on each error case */ pres->res_commit3.COMMIT3res_u.resfail.file_wcc.before.attributes_follow = FALSE; pres->res_commit3.COMMIT3res_u.resfail.file_wcc.after.attributes_follow = FALSE; ppre_attr = NULL; /* Convert file handle into a fsal_handle */ if(nfs3_FhandleToFSAL(&(parg->arg_commit3.file), &fsal_data.handle, pcontext) == 0) return NFS_REQ_DROP; /* Set cookie to 0 */ fsal_data.cookie = DIR_START; /* Get the entry in the cache_inode */ if((pentry = cache_inode_get( &fsal_data, pexport->cache_inode_policy, &pre_attr, ht, pclient, pcontext, &cache_status)) == NULL) { /* Stale NFS FH ? */ pres->res_commit3.status = NFS3ERR_STALE; return NFS_REQ_OK; } if((pexport->use_commit == TRUE) && (pexport->use_ganesha_write_buffer == FALSE)) typeofcommit = FSAL_UNSAFE_WRITE_TO_FS_BUFFER; else if((pexport->use_commit == TRUE) && (pexport->use_ganesha_write_buffer == TRUE)) typeofcommit = FSAL_UNSAFE_WRITE_TO_GANESHA_BUFFER; else /* We only do stable writes with this export so no need to execute a commit */ return NFS_REQ_OK; /* Do not use DC if data cache is enabled, the data is kept synchronous is the DC */ if(cache_inode_commit(pentry, parg->arg_commit3.offset, parg->arg_commit3.count, &pre_attr, ht, pclient, pcontext, typeofcommit, &cache_status) != CACHE_INODE_SUCCESS) { pres->res_commit3.status = NFS3ERR_IO;; nfs_SetWccData(pcontext, pexport, pentry, ppre_attr, ppre_attr, &(pres->res_commit3.COMMIT3res_u.resfail.file_wcc)); return NFS_REQ_OK; } /* Set the pre_attr */ ppre_attr = &pre_attr; nfs_SetWccData(pcontext, pexport, pentry, ppre_attr, ppre_attr, &(pres->res_commit3.COMMIT3res_u.resok.file_wcc)); /* Set the write verifier */ memcpy(pres->res_commit3.COMMIT3res_u.resok.verf, NFS3_write_verifier, sizeof(writeverf3)); pres->res_commit3.status = NFS3_OK; return NFS_REQ_OK; } /* nfs3_Commit */