int _9p_getlock(struct _9p_request_data *req9p, u32 *plenout, char *preply) { char *cursor = req9p->_9pmsg + _9P_HDR_SIZE + _9P_TYPE_SIZE; u16 *msgtag = NULL; u32 *fid = NULL; u8 *type = NULL; u64 *start = NULL; u64 *length = NULL; u32 *proc_id = NULL; u16 *client_id_len = NULL; char *client_id_str = NULL; /* struct _9p_fid * pfid = NULL ; */ /* Get data */ _9p_getptr(cursor, msgtag, u16); _9p_getptr(cursor, fid, u32); _9p_getptr(cursor, type, u8); _9p_getptr(cursor, start, u64); _9p_getptr(cursor, length, u64); _9p_getptr(cursor, proc_id, u32); _9p_getstr(cursor, client_id_len, client_id_str); LogDebug(COMPONENT_9P, "TGETLOCK: tag=%u fid=%u type=%u start=%llu length=%llu proc_id=%u client=%.*s", (u32) *msgtag, *fid, *type, (unsigned long long) *start, (unsigned long long)*length, *proc_id, *client_id_len, client_id_str); if (*fid >= _9P_FID_PER_CONN) return _9p_rerror(req9p, msgtag, ERANGE, plenout, preply); /* pfid = req9p->pconn->fids[*fid] ; */ /** @todo This function does nothing for the moment. * Make it compliant with fcntl( F_GETLCK, ... */ /* Build the reply */ _9p_setinitptr(cursor, preply, _9P_RGETLOCK); _9p_setptr(cursor, msgtag, u16); _9p_setptr(cursor, type, u8); _9p_setptr(cursor, start, u64); _9p_setptr(cursor, length, u64); _9p_setptr(cursor, proc_id, u32); _9p_setstr(cursor, *client_id_len, client_id_str); _9p_setendptr(cursor, preply); _9p_checkbound(cursor, preply, plenout); LogDebug(COMPONENT_9P, "RGETLOCK: tag=%u fid=%u type=%u start=%llu length=%llu proc_id=%u client=%.*s", (u32) *msgtag, *fid, *type, (unsigned long long) *start, (unsigned long long)*length, *proc_id, *client_id_len, client_id_str); return 1; }
int _9p_readlink(struct _9p_request_data *req9p, u32 *plenout, char *preply) { char *cursor = req9p->_9pmsg + _9P_HDR_SIZE + _9P_TYPE_SIZE; u16 *msgtag = NULL; u32 *fid = NULL; struct _9p_fid *pfid = NULL; cache_inode_status_t cache_status; struct gsh_buffdesc link_buffer = {.addr = NULL, .len = 0 }; /* Get data */ _9p_getptr(cursor, msgtag, u16); _9p_getptr(cursor, fid, u32); LogDebug(COMPONENT_9P, "TREADLINK: tag=%u fid=%u", (u32) *msgtag, *fid); if (*fid >= _9P_FID_PER_CONN) return _9p_rerror(req9p, msgtag, ERANGE, plenout, preply); pfid = req9p->pconn->fids[*fid]; /* Check that it is a valid fid */ if (pfid == NULL || pfid->pentry == NULL) { LogDebug(COMPONENT_9P, "request on invalid fid=%u", *fid); return _9p_rerror(req9p, msgtag, EIO, plenout, preply); } _9p_init_opctx(pfid, req9p); /* let's do the job */ cache_status = cache_inode_readlink(pfid->pentry, &link_buffer); if (cache_status != CACHE_INODE_SUCCESS) return _9p_rerror(req9p, msgtag, _9p_tools_errno(cache_status), plenout, preply); /* Build the reply */ _9p_setinitptr(cursor, preply, _9P_RREADLINK); _9p_setptr(cursor, msgtag, u16); _9p_setstr(cursor, link_buffer.len - 1, link_buffer.addr); _9p_setendptr(cursor, preply); _9p_checkbound(cursor, preply, plenout); LogDebug(COMPONENT_9P, "RREADLINK: tag=%u fid=%u link=%s", *msgtag, (u32) *fid, (char *) link_buffer.addr); gsh_free(link_buffer.addr); return 1; }
int _9p_version( _9p_request_data_t * preq9p, void * pworker_data, u32 * plenout, char * preply) { char * cursor = preq9p->_9pmsg + _9P_HDR_SIZE + _9P_TYPE_SIZE ; u16 * msgtag = NULL ; u32 * msize = NULL ; u16 * version_len = NULL ; char * version_str = NULL ; if ( !preq9p || !plenout || !preply ) return -1 ; /* Get data */ _9p_getptr( cursor, msgtag, u16 ) ; _9p_getptr( cursor, msize, u32 ) ; _9p_getstr( cursor, version_len, version_str ) ; LogDebug( COMPONENT_9P, "TVERSION: tag=%u msize=%u version='%.*s'", (u32)*msgtag, *msize, (int)*version_len, version_str ) ; if( strncmp( version_str, version_9p200l, *version_len ) ) { LogEvent( COMPONENT_9P, "RVERSION: BAD VERSION" ) ; return _9p_rerror( preq9p, msgtag, ENOENT, plenout, preply ) ; } /* Good version, build the reply */ _9p_setinitptr( cursor, preply, _9P_RVERSION ) ; _9p_setptr( cursor, msgtag, u16 ) ; _9p_setptr( cursor, msize, u32 ) ; _9p_setstr( cursor, *version_len, version_str ) ; _9p_setendptr( cursor, preply ) ; _9p_checkbound( cursor, preply, plenout ) ; LogDebug( COMPONENT_9P, "RVERSION: msize=%u version='%.*s'", *msize, (int)*version_len, version_str ) ; return 1 ; }
int _9p_readdir( _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 ; int rc = 0 ; u32 err = 0 ; u16 * msgtag = NULL ; u32 * fid = NULL ; u64 * offset = NULL ; u32 * count = NULL ; u32 dcount = 0 ; u32 recsize = 0 ; u16 name_len = 0 ; char * name_str = NULL ; u8 * qid_type = NULL ; u64 * qid_path = NULL ; char * dcount_pos = NULL ; cache_inode_status_t cache_status; cache_inode_dir_entry_t **dirent_array = NULL; cache_inode_endofdir_t eod_met; cache_entry_t * pentry_dot_dot = NULL ; cache_inode_dir_entry_t dirent_dot ; cache_inode_dir_entry_t dirent_dot_dot ; unsigned int cookie = 0; unsigned int end_cookie = 0; unsigned int estimated_num_entries = 0 ; unsigned int num_entries = 0 ; unsigned int delta = 0 ; int unlock = FALSE ; u64 i = 0LL ; if ( !preq9p || !pworker_data || !plenout || !preply ) return -1 ; _9p_fid_t * pfid = NULL ; /* Get data */ _9p_getptr( cursor, msgtag, u16 ) ; _9p_getptr( cursor, fid, u32 ) ; _9p_getptr( cursor, offset, u64 ) ; _9p_getptr( cursor, count, u32 ) ; LogDebug( COMPONENT_9P, "TREADDIR: tag=%u fid=%u offset=%llu count=%u", (u32)*msgtag, *fid, (unsigned long long)*offset, *count ) ; if( *fid >= _9P_FID_PER_CONN ) { err = ERANGE ; rc = _9p_rerror( preq9p, msgtag, &err, plenout, preply ) ; return rc ; } pfid = &preq9p->pconn->fids[*fid] ; /* Use Cache Inode to read the directory's content */ cookie = (unsigned int)*offset ; /* For each entry, returns: * qid = 13 bytes * offset = 8 bytes * type = 1 byte * namelen = 2 bytes * namestr = ~16 bytes (average size) * ------------------- * total = ~40 bytes (average size) per dentry */ estimated_num_entries = (unsigned int)( *count / 40 ) ; if((dirent_array = (cache_inode_dir_entry_t **) Mem_Alloc_Label( estimated_num_entries * sizeof(cache_inode_dir_entry_t*), "cache_inode_dir_entry_t in _9p_readdir")) == NULL) { err = EIO ; rc = _9p_rerror( preq9p, msgtag, &err, plenout, preply ) ; return rc ; } /* Is this the first request ? */ if( *offset == 0 ) { /* compute the parent entry */ if( ( pentry_dot_dot = cache_inode_lookupp( pfid->pentry, pwkrdata->ht, &pwkrdata->cache_inode_client, &pfid->fsal_op_context, &cache_status) ) == NULL ) { err = _9p_tools_errno( cache_status ) ; ; rc = _9p_rerror( preq9p, msgtag, &err, plenout, preply ) ; return rc ; } /* Deal with "." and ".." */ dirent_dot.pentry = pfid->pentry ; strcpy( dirent_dot.name.name, "." ) ; dirent_dot.name.len = strlen( dirent_dot.name.name ) ; dirent_array[0] = &dirent_dot ; dirent_dot_dot.pentry = pentry_dot_dot ; strcpy( dirent_dot_dot.name.name, ".." ) ; dirent_dot_dot.name.len = strlen( dirent_dot_dot.name.name ) ; dirent_array[1] = &dirent_dot_dot ; delta = 2 ; } else delta = 0 ; if( *offset == 2 ) { /* offset == 2 as an input as one and only reason: * - a former call with offset=0 was made and the dir was empty * - '.' and '..' were returned and nothing else * - the client makes a new call, expecting it to have empty return */ num_entries = 0 ; /* Empty return */ unlock = FALSE ; } else if(cache_inode_readdir( pfid->pentry, pfid->pexport->cache_inode_policy, cookie, estimated_num_entries - delta, &num_entries, (uint64_t *)&end_cookie, &eod_met, &dirent_array[delta], pwkrdata->ht, &unlock, &pwkrdata->cache_inode_client, &pfid->fsal_op_context, &cache_status) != CACHE_INODE_SUCCESS) { if( unlock ) V_r( &pfid->pentry->lock ) ; err = _9p_tools_errno( cache_status ) ; ; rc = _9p_rerror( preq9p, msgtag, &err, plenout, preply ) ; return rc ; } /* Unlock the directory if needed */ if( unlock ) V_r( &pfid->pentry->lock ) ; /* Never go behind _9P_MAXDIRCOUNT */ if( num_entries > _9P_MAXDIRCOUNT ) num_entries = _9P_MAXDIRCOUNT ; /* Build the reply */ _9p_setinitptr( cursor, preply, _9P_RREADDIR ) ; _9p_setptr( cursor, msgtag, u16 ) ; /* Remember dcount position for later use */ _9p_savepos( cursor, dcount_pos, u32 ) ; /* fills in the dentry in 9P marshalling */ for( i = 0 ; i < num_entries + delta ; i++ ) { recsize = 0 ; /* Build qid */ switch( dirent_array[i]->pentry->internal_md.type ) { case REGULAR_FILE: qid_path = (u64 *)&dirent_array[i]->pentry->object.file.attributes.fileid ; qid_type = &qid_type_file ; break ; case CHARACTER_FILE: case BLOCK_FILE: case SOCKET_FILE: case FIFO_FILE: qid_path = (u64 *)&dirent_array[i]->pentry->object.special_obj.attributes.fileid ; qid_type = &qid_type_file ; break ; case SYMBOLIC_LINK: qid_path = (u64 *)&dirent_array[i]->pentry->object.symlink->attributes.fileid ; qid_type = &qid_type_symlink; break ; case DIRECTORY: case FS_JUNCTION: qid_path = (u64 *)&dirent_array[i]->pentry->object.dir.attributes.fileid ; qid_type = &qid_type_dir ; break ; case UNASSIGNED: case RECYCLED: default: LogMajor( COMPONENT_9P, "implementation error, you should not see this message !!!!!!" ) ; err = EINVAL ; rc = _9p_rerror( preq9p, msgtag, &err, plenout, preply ) ; return rc ; break ; } /* Get dirent name information */ name_str = dirent_array[i]->name.name ; name_len = dirent_array[i]->name.len ; /* Add 13 bytes in recsize for qid + 8 bytes for offset + 1 for type + 2 for strlen = 24 bytes*/ recsize = 24 + name_len ; /* Check if there is room left for another dentry */ if( dcount + recsize > *count ) break ; /* exit for loop */ else dcount += recsize ; /* qid in 3 parts */ _9p_setptr( cursor, qid_type, u8 ) ; _9p_setvalue( cursor, 0, u32 ) ; /* qid_version set to 0 to prevent the client from caching */ _9p_setptr( cursor, qid_path, u64 ) ; /* offset */ _9p_setvalue( cursor, i+cookie+1, u64 ) ; /* Type (again ?) */ _9p_setptr( cursor, qid_type, u8 ) ; /* name */ _9p_setstr( cursor, name_len, name_str ) ; LogDebug( COMPONENT_9P, "RREADDIR dentry: recsize=%u dentry={ off=%llu,qid=(type=%u,version=%u,path=%llu),type=%u,name=%s,pentry=%p", recsize, (unsigned long long)i+cookie+1, *qid_type, 0, (unsigned long long)*qid_path, *qid_type, name_str, dirent_array[i]->pentry ) ; } /* for( i = 0 , ... ) */ if( !CACHE_INODE_KEEP_CONTENT( pfid->pentry->policy ) ) cache_inode_release_dirent( dirent_array, num_entries, &pwkrdata->cache_inode_client ) ; Mem_Free((char *)dirent_array); /* Set buffsize in previously saved position */ _9p_setvalue( dcount_pos, dcount, u32 ) ; _9p_setendptr( cursor, preply ) ; _9p_checkbound( cursor, preply, plenout ) ; LogDebug( COMPONENT_9P, "RREADDIR: tag=%u fid=%u dcount=%u", (u32)*msgtag, *fid , dcount ) ; return 1 ; }
int _9p_readlink( _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 ; _9p_fid_t * pfid = NULL ; int rc = 0 ; int err = 0 ; fsal_path_t symlink_data; cache_inode_status_t cache_status ; if ( !preq9p || !pworker_data || !plenout || !preply ) return -1 ; /* Get data */ _9p_getptr( cursor, msgtag, u16 ) ; _9p_getptr( cursor, fid, u32 ) ; LogDebug( COMPONENT_9P, "TREADLINK: tag=%u fid=%u",(u32)*msgtag, *fid ) ; if( *fid >= _9P_FID_PER_CONN ) { err = ERANGE ; rc = _9p_rerror( preq9p, msgtag, &err, plenout, preply ) ; return rc ; } pfid = &preq9p->pconn->fids[*fid] ; /* let's do the job */ if( cache_inode_readlink( pfid->pentry, &symlink_data, pwkrdata->ht, &pwkrdata->cache_inode_client, &pfid->fsal_op_context, &cache_status ) != CACHE_INODE_SUCCESS ) { err = _9p_tools_errno( cache_status ) ; ; rc = _9p_rerror( preq9p, msgtag, &err, plenout, preply ) ; return rc ; } /* Build the reply */ _9p_setinitptr( cursor, preply, _9P_RREADLINK ) ; _9p_setptr( cursor, msgtag, u16 ) ; _9p_setstr( cursor, strlen( symlink_data.path ), symlink_data.path ) ; _9p_setendptr( cursor, preply ) ; _9p_checkbound( cursor, preply, plenout ) ; LogDebug( COMPONENT_9P, "RREADLINK: tag=%u fid=%u link=%s", *msgtag, (u32)*fid, symlink_data.path ) ; return 1 ; }