int _9p_flush( _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 ; u16 * oldtag = NULL ; if ( !preq9p || !pworker_data || !plenout || !preply ) return -1 ; /* Get data */ _9p_getptr( cursor, msgtag, u16 ) ; _9p_getptr( cursor, oldtag, u16 ) ; LogDebug( COMPONENT_9P, "TFLUSH: tag=%u oldtag=%u", (u32)*msgtag, (u32)*oldtag ) ; _9p_FlushFlushHook(preq9p->pconn, (int) *oldtag, preq9p->flush_hook.sequence); /* Build the reply */ _9p_setinitptr( cursor, preply, _9P_RFLUSH ) ; _9p_setptr( cursor, msgtag, u16 ) ; _9p_setendptr( cursor, preply ) ; _9p_checkbound( cursor, preply, plenout ) ; LogDebug( COMPONENT_9P, "RFLUSH: tag=%u oldtag=%u", (u32)*msgtag, (u32)*oldtag ) ; return 1 ; }
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_fsync(struct _9p_request_data *req9p, void *worker_data, 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 = CACHE_INODE_SUCCESS; /* Get data */ _9p_getptr(cursor, msgtag, u16); _9p_getptr(cursor, fid, u32); LogDebug(COMPONENT_9P, "TFSYNC: tag=%u fid=%u", (u32) *msgtag, *fid); if (*fid >= _9P_FID_PER_CONN) return _9p_rerror(req9p, worker_data, msgtag, ERANGE, plenout, preply); pfid = req9p->pconn->fids[*fid]; /* Check that it is a valid open file */ if (pfid == NULL || pfid->pentry == NULL) { LogDebug(COMPONENT_9P, "request on invalid fid=%u", *fid); return _9p_rerror(req9p, worker_data, msgtag, EIO, plenout, preply); } cache_status = cache_inode_commit(pfid->pentry, 0LL, /* start at beginning of file */ 0LL, /* Mimic sync_file_range's behavior: * count=0 means "whole file" */ &pfid->op_context); if (cache_status != CACHE_INODE_SUCCESS) return _9p_rerror(req9p, worker_data, msgtag, _9p_tools_errno(cache_status), plenout, preply); /* Build the reply */ _9p_setinitptr(cursor, preply, _9P_RFSYNC); _9p_setptr(cursor, msgtag, u16); _9p_setendptr(cursor, preply); _9p_checkbound(cursor, preply, plenout); LogDebug(COMPONENT_9P, "RFSYNC: tag=%u fid=%u", (u32) *msgtag, *fid); 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_statfs( _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 ; u64 * request_mask = NULL ; _9p_fid_t * pfid = NULL ; u32 type = 0x6969 ; /* NFS_SUPER_MAGIC for wanting of better, FSAL do not return this information */ u32 bsize = DEV_BSIZE ; u64 * blocks = NULL ; u64 * bfree = NULL ; u64 * bavail = NULL ; u64 * files = NULL ; u64 * ffree = NULL ; u64 fsid = 0LL ; u32 namelen = MAXNAMLEN ; int rc = 0 ; int err = 0 ; fsal_dynamicfsinfo_t dynamicinfo; 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, "TSTATFS: 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] ; /* Get the FS's stats */ if( cache_inode_statfs( pfid->pentry, &dynamicinfo, &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 ; } blocks = (u64 *)&dynamicinfo.total_bytes ; bfree = (u64 *)&dynamicinfo.free_bytes ; bavail = (u64 *)&dynamicinfo.avail_bytes ; files = (u64 *)&dynamicinfo.total_files ; ffree = (u64 *)&dynamicinfo.free_files ; fsid = (u64 )pfid->attr.st_dev ; /* Build the reply */ _9p_setinitptr( cursor, preply, _9P_RSTATFS ) ; _9p_setptr( cursor, msgtag, u16 ) ; _9p_setvalue( cursor, type, u32 ) ; _9p_setvalue( cursor, bsize, u32 ) ; _9p_setptr( cursor, blocks, u64 ) ; _9p_setptr( cursor, bfree, u64 ) ; _9p_setptr( cursor, bavail, u64 ) ; _9p_setptr( cursor, files, u64 ) ; _9p_setptr( cursor, ffree, u64 ) ; _9p_setvalue( cursor, fsid, u64 ) ; _9p_setvalue( cursor, namelen, u32 ) ; _9p_setendptr( cursor, preply ) ; _9p_checkbound( cursor, preply, plenout ) ; LogDebug( COMPONENT_9P, "RSTATFS: tag=%u fid=%u", (u32)*msgtag, *fid ) ; return 1 ; }
int _9p_mknod( _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 * mode = NULL ; u32 * gid = NULL ; u32 * major = NULL ; u32 * minor = NULL ; u16 * name_len = NULL ; char * name_str = NULL ; _9p_fid_t * pfid = NULL ; _9p_qid_t qid_newobj ; cache_entry_t * pentry_newobj = NULL ; fsal_name_t obj_name ; fsal_attrib_list_t fsalattr ; cache_inode_status_t cache_status ; cache_inode_file_type_t nodetype; cache_inode_create_arg_t create_arg; int rc = 0 ; int err = 0 ; if ( !preq9p || !pworker_data || !plenout || !preply ) return -1 ; memset(&create_arg, 0, sizeof(create_arg)); /* Get data */ _9p_getptr( cursor, msgtag, u16 ) ; _9p_getptr( cursor, fid, u32 ) ; _9p_getstr( cursor, name_len, name_str ) ; _9p_getptr( cursor, mode, u32 ) ; _9p_getptr( cursor, major, u32 ) ; _9p_getptr( cursor, minor, u32 ) ; _9p_getptr( cursor, gid, u32 ) ; LogDebug( COMPONENT_9P, "TMKNOD: tag=%u fid=%u name=%.*s mode=0%o major=%u minor=%u gid=%u", (u32)*msgtag, *fid, *name_len, name_str, *mode, *major, *minor, *gid ) ; if( *fid >= _9P_FID_PER_CONN ) { err = ERANGE ; rc = _9p_rerror( preq9p, msgtag, &err, plenout, preply ) ; return rc ; } pfid = &preq9p->pconn->fids[*fid] ; snprintf( obj_name.name, FSAL_MAX_NAME_LEN, "%.*s", *name_len, name_str ) ; /* Check for bad type */ if( !( *mode & (S_IFCHR|S_IFBLK|S_IFIFO|S_IFSOCK) ) ) { err = ERANGE ; rc = _9p_rerror( preq9p, msgtag, &err, plenout, preply ) ; return rc ; } /* Set the nodetype */ if( *mode & S_IFCHR ) nodetype = CHARACTER_FILE ; if( *mode & S_IFBLK ) nodetype = BLOCK_FILE ; if( *mode & S_IFIFO ) nodetype = FIFO_FILE ; if( *mode & S_IFSOCK ) nodetype = SOCKET_FILE ; create_arg.dev_spec.major = *major ; create_arg.dev_spec.minor = *minor ; /* Create the directory */ /** @todo BUGAZOMEU the gid parameter is not used yet */ if( ( pentry_newobj = cache_inode_create( pfid->pentry, &obj_name, nodetype, pfid->pexport->cache_inode_policy, *mode, &create_arg, &fsalattr, 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 ; } /* Build the qid */ qid_newobj.type = _9P_QTTMP ; /** @todo BUGAZOMEU For wanting of something better */ qid_newobj.version = 0 ; qid_newobj.path = fsalattr.fileid ; /* Build the reply */ _9p_setinitptr( cursor, preply, _9P_RMKNOD ) ; _9p_setptr( cursor, msgtag, u16 ) ; _9p_setqid( cursor, qid_newobj ) ; _9p_setendptr( cursor, preply ) ; _9p_checkbound( cursor, preply, plenout ) ; LogDebug( COMPONENT_9P, "TMKNOD: tag=%u fid=%u name=%.*s major=%u minor=%u qid=(type=%u,version=%u,path=%llu)", (u32)*msgtag, *fid, *name_len, name_str, *major, *minor, qid_newobj.type, qid_newobj.version, (unsigned long long)qid_newobj.path ) ; return 1 ; }
int _9p_lcreate(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; u32 *flags = NULL; u32 *mode = NULL; u32 *gid = NULL; u16 *name_len = NULL; char *name_str = NULL; struct _9p_fid *pfid = NULL; struct _9p_qid qid_newfile; u32 iounit = _9P_IOUNIT; struct fsal_obj_handle *pentry_newfile = NULL; char file_name[MAXNAMLEN+1]; fsal_status_t fsal_status; fsal_openflags_t openflags = 0; struct attrlist sattr; fsal_verifier_t verifier; enum fsal_create_mode createmode = FSAL_UNCHECKED; /* Get data */ _9p_getptr(cursor, msgtag, u16); _9p_getptr(cursor, fid, u32); _9p_getstr(cursor, name_len, name_str); _9p_getptr(cursor, flags, u32); _9p_getptr(cursor, mode, u32); _9p_getptr(cursor, gid, u32); LogDebug(COMPONENT_9P, "TLCREATE: tag=%u fid=%u name=%.*s flags=0%o mode=0%o gid=%u", (u32) *msgtag, *fid, *name_len, name_str, *flags, *mode, *gid); 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); if ((op_ctx->export_perms->options & EXPORT_OPTION_WRITE_ACCESS) == 0) return _9p_rerror(req9p, msgtag, EROFS, plenout, preply); if (*name_len >= sizeof(file_name)) { LogDebug(COMPONENT_9P, "request with name too long (%u)", *name_len); return _9p_rerror(req9p, msgtag, ENAMETOOLONG, plenout, preply); } snprintf(file_name, sizeof(file_name), "%.*s", *name_len, name_str); _9p_openflags2FSAL(flags, &openflags); pfid->state->state_data.fid.share_access = _9p_openflags_to_share_access(flags); memset(&verifier, 0, sizeof(verifier)); memset(&sattr, 0, sizeof(sattr)); sattr.valid_mask = ATTR_MODE | ATTR_GROUP; sattr.mode = *mode; sattr.group = *gid; if (*flags & 0x10) { /* Filesize is already 0. */ sattr.valid_mask |= ATTR_SIZE; } if (*flags & 0x1000) { /* If OEXCL, use FSAL_EXCLUSIVE_9P create mode * so that we can pass the attributes specified * above. Verifier is ignored for this create mode * because we don't have to deal with retry. */ createmode = FSAL_EXCLUSIVE_9P; } fsal_status = fsal_open2(pfid->pentry, pfid->state, openflags, createmode, file_name, &sattr, verifier, &pentry_newfile, NULL); /* Release the attributes (may release an inherited ACL) */ fsal_release_attrs(&sattr); if (FSAL_IS_ERROR(fsal_status)) return _9p_rerror(req9p, msgtag, _9p_tools_errno(fsal_status), plenout, preply); /* put parent directory entry */ pfid->pentry->obj_ops->put_ref(pfid->pentry); /* Build the qid */ qid_newfile.type = _9P_QTFILE; qid_newfile.version = 0; qid_newfile.path = pentry_newfile->fileid; /* The fid will represent the new file now - we can't fail anymore */ pfid->pentry = pentry_newfile; pfid->qid = qid_newfile; pfid->xattr = NULL; pfid->opens = 1; /* Build the reply */ _9p_setinitptr(cursor, preply, _9P_RLCREATE); _9p_setptr(cursor, msgtag, u16); _9p_setqid(cursor, qid_newfile); _9p_setvalue(cursor, iounit, u32); _9p_setendptr(cursor, preply); _9p_checkbound(cursor, preply, plenout); LogDebug(COMPONENT_9P, "RLCREATE: tag=%u fid=%u name=%.*s qid=(type=%u,version=%u,path=%llu) iounit=%u pentry=%p", (u32) *msgtag, *fid, *name_len, name_str, qid_newfile.type, qid_newfile.version, (unsigned long long)qid_newfile.path, iounit, pfid->pentry); 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_lopen(struct _9p_request_data *req9p, void *worker_data, u32 *plenout, char *preply) { char *cursor = req9p->_9pmsg + _9P_HDR_SIZE + _9P_TYPE_SIZE; u16 *msgtag = NULL; u32 *fid = NULL; u32 *flags = NULL; cache_inode_status_t cache_status; fsal_openflags_t openflags = 0; struct _9p_fid *pfid = NULL; /* Get data */ _9p_getptr(cursor, msgtag, u16); _9p_getptr(cursor, fid, u32); _9p_getptr(cursor, flags, u32); LogDebug(COMPONENT_9P, "TLOPEN: tag=%u fid=%u flags=0x%x", (u32) *msgtag, *fid, *flags); if (*fid >= _9P_FID_PER_CONN) return _9p_rerror(req9p, worker_data, 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, worker_data, msgtag, EIO, plenout, preply); } _9p_openflags2FSAL(flags, &openflags); op_ctx = &pfid->op_context; if (pfid->pentry->type == REGULAR_FILE) { /** @todo: Maybe other types (FIFO, SOCKET,...) require * to be opened too */ if (!atomic_postinc_uint32_t(&pfid->opens)) { cache_status = cache_inode_inc_pin_ref(pfid->pentry); if (cache_status != CACHE_INODE_SUCCESS) return _9p_rerror(req9p, worker_data, msgtag, _9p_tools_errno(cache_status), plenout, preply); } cache_status = cache_inode_open(pfid->pentry, openflags, 0); if (cache_status != CACHE_INODE_SUCCESS) return _9p_rerror(req9p, worker_data, msgtag, _9p_tools_errno(cache_status), plenout, preply); } /* iounit = 0 by default */ pfid->specdata.iounit = _9P_IOUNIT; /* Build the reply */ _9p_setinitptr(cursor, preply, _9P_RLOPEN); _9p_setptr(cursor, msgtag, u16); _9p_setqid(cursor, pfid->qid); _9p_setptr(cursor, &pfid->specdata.iounit, u32); _9p_setendptr(cursor, preply); _9p_checkbound(cursor, preply, plenout); LogDebug(COMPONENT_9P, "RLOPEN: tag=%u fid=%u qid=(type=%u,version=%u,path=%llu) iounit=%u", *msgtag, *fid, (u32) pfid->qid.type, pfid->qid.version, (unsigned long long)pfid->qid.path, pfid->specdata.iounit); return 1; }
int _9p_read(struct _9p_request_data *req9p, u32 *plenout, char *preply) { char *cursor = req9p->_9pmsg + _9P_HDR_SIZE + _9P_TYPE_SIZE; char *databuffer; u16 *msgtag = NULL; u32 *fid = NULL; u64 *offset = NULL; u32 *count = NULL; u32 outcount = 0; struct _9p_fid *pfid = NULL; size_t read_size = 0; bool eof_met; fsal_status_t fsal_status; /* uint64_t stable_flag = CACHE_INODE_SAFE_WRITE_TO_FS; */ bool sync = false; /* 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, "TREAD: tag=%u fid=%u offset=%llu count=%u", (u32) *msgtag, *fid, (unsigned long long)*offset, *count); if (*fid >= _9P_FID_PER_CONN) return _9p_rerror(req9p, msgtag, ERANGE, plenout, preply); pfid = req9p->pconn->fids[*fid]; /* Make sure the requested amount of data respects negotiated msize */ if (*count + _9P_ROOM_RREAD > req9p->pconn->msize) return _9p_rerror(req9p, msgtag, ERANGE, plenout, preply); /* 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); /* Start building the reply already * So we don't need to use an intermediate data buffer */ _9p_setinitptr(cursor, preply, _9P_RREAD); _9p_setptr(cursor, msgtag, u16); databuffer = _9p_getbuffertofill(cursor); /* Do the job */ if (pfid->xattr != NULL) { /* Copy the value cached during xattrwalk */ if (*offset > pfid->xattr->xattr_size) return _9p_rerror(req9p, msgtag, EINVAL, plenout, preply); if (pfid->xattr->xattr_write != _9P_XATTR_READ_ONLY) return _9p_rerror(req9p, msgtag, EINVAL, plenout, preply); read_size = MIN(*count, pfid->xattr->xattr_size - *offset); memcpy(databuffer, pfid->xattr->xattr_content + *offset, read_size); outcount = read_size; } else { if (pfid->pentry->fsal->m_ops.support_ex(pfid->pentry)) { /* Call the new fsal_read */ fsal_status = fsal_read2(pfid->pentry, false, pfid->state, *offset, *count, &read_size, databuffer, &eof_met, NULL); } else { /* Call legacy fsal_rdwr */ fsal_status = fsal_rdwr(pfid->pentry, FSAL_IO_READ, *offset, *count, &read_size, databuffer, &eof_met, &sync, NULL); } /* Get the handle, for stats */ struct gsh_client *client = req9p->pconn->client; if (client == NULL) { LogDebug(COMPONENT_9P, "Cannot get client block for 9P request"); } else { op_ctx->client = client; server_stats_io_done(*count, read_size, FSAL_IS_ERROR(fsal_status), false); } if (FSAL_IS_ERROR(fsal_status)) return _9p_rerror(req9p, msgtag, _9p_tools_errno(fsal_status), plenout, preply); outcount = (u32) read_size; } _9p_setfilledbuffer(cursor, outcount); _9p_setendptr(cursor, preply); _9p_checkbound(cursor, preply, plenout); LogDebug(COMPONENT_9P, "RREAD: tag=%u fid=%u offset=%llu count=%u", (u32) *msgtag, *fid, (unsigned long long)*offset, *count); /** * @todo read statistics accounting goes here * modeled on nfs I/O statistics */ return 1; }
int _9p_xattrwalk(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; u32 *attrfid = NULL; u16 *name_len; char *name_str; size_t attrsize = 0; fsal_status_t fsal_status; char name[MAXNAMLEN]; fsal_xattrent_t xattrs_arr[XATTRS_ARRAY_LEN]; int eod_met = false; unsigned int nb_xattrs_read = 0; unsigned int i = 0; char *xattr_cursor = NULL; unsigned int tmplen = 0; struct _9p_fid *pfid = NULL; struct _9p_fid *pxattrfid = NULL; /* Get data */ _9p_getptr(cursor, msgtag, u16); _9p_getptr(cursor, fid, u32); _9p_getptr(cursor, attrfid, u32); LogDebug(COMPONENT_9P, "TXATTRWALK: tag=%u fid=%u attrfid=%u", (u32) *msgtag, *fid, *attrfid); _9p_getstr(cursor, name_len, name_str); if (*name_len == 0) LogDebug(COMPONENT_9P, "TXATTRWALK (component): tag=%u fid=%u attrfid=%u name=(LIST XATTR)", (u32) *msgtag, *fid, *attrfid); else LogDebug(COMPONENT_9P, "TXATTRWALK (component): tag=%u fid=%u attrfid=%u name=%.*s", (u32) *msgtag, *fid, *attrfid, *name_len, name_str); if (*fid >= _9P_FID_PER_CONN) return _9p_rerror(req9p, msgtag, ERANGE, plenout, preply); if (*attrfid >= _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); } pxattrfid = gsh_calloc(1, sizeof(struct _9p_fid)); if (pxattrfid == NULL) return _9p_rerror(req9p, msgtag, ENOMEM, plenout, preply); /* set op_ctx, it will be useful if FSAL is later called */ _9p_init_opctx(pfid, req9p); /* Initiate xattr's fid by copying file's fid in it */ memcpy((char *)pxattrfid, (char *)pfid, sizeof(struct _9p_fid)); snprintf(name, MAXNAMLEN, "%.*s", *name_len, name_str); pxattrfid->specdata.xattr.xattr_content = gsh_malloc(XATTR_BUFFERSIZE); if (pxattrfid->specdata.xattr.xattr_content == NULL) { gsh_free(pxattrfid); return _9p_rerror(req9p, msgtag, ENOMEM, plenout, preply); } if (*name_len == 0) { /* xattrwalk is used with an empty name, * this is a listxattr request */ fsal_status = pxattrfid->pentry->obj_handle->obj_ops.list_ext_attrs( pxattrfid->pentry->obj_handle, FSAL_XATTR_RW_COOKIE, /* Start with RW cookie, * hiding RO ones */ xattrs_arr, XATTRS_ARRAY_LEN, /** @todo fix static length */ &nb_xattrs_read, &eod_met); if (FSAL_IS_ERROR(fsal_status)) { gsh_free(pxattrfid->specdata.xattr.xattr_content); gsh_free(pxattrfid); return _9p_rerror(req9p, msgtag, _9p_tools_errno (cache_inode_error_convert (fsal_status)), plenout, preply); } /* if all xattrent are not read, * returns ERANGE as listxattr does */ if (eod_met != true) { gsh_free(pxattrfid->specdata.xattr.xattr_content); gsh_free(pxattrfid); return _9p_rerror(req9p, msgtag, ERANGE, plenout, preply); } xattr_cursor = pxattrfid->specdata.xattr.xattr_content; attrsize = 0; for (i = 0; i < nb_xattrs_read; i++) { tmplen = snprintf(xattr_cursor, MAXNAMLEN, "%s", xattrs_arr[i].xattr_name); xattr_cursor[tmplen] = '\0'; /* Just to be sure */ /* +1 for trailing '\0' */ xattr_cursor += tmplen + 1; attrsize += tmplen + 1; /* Make sure not to go beyond the buffer */ if (attrsize > XATTR_BUFFERSIZE) { gsh_free(pxattrfid->specdata.xattr. xattr_content); gsh_free(pxattrfid); return _9p_rerror(req9p, msgtag, ERANGE, plenout, preply); } } } else { /* xattrwalk has a non-empty name, use regular setxattr */ fsal_status = pxattrfid->pentry->obj_handle->obj_ops. getextattr_id_by_name(pxattrfid->pentry->obj_handle, name, &pxattrfid->specdata.xattr.xattr_id); if (FSAL_IS_ERROR(fsal_status)) { gsh_free(pxattrfid->specdata.xattr.xattr_content); gsh_free(pxattrfid); /* ENOENT for xattr is ENOATTR */ if (fsal_status.major == ERR_FSAL_NOENT) return _9p_rerror(req9p, msgtag, ENOATTR, plenout, preply); else return _9p_rerror(req9p, msgtag, _9p_tools_errno (cache_inode_error_convert (fsal_status)), plenout, preply); } fsal_status = pxattrfid->pentry->obj_handle->obj_ops. getextattr_value_by_name(pxattrfid->pentry->obj_handle, name, pxattrfid->specdata.xattr. xattr_content, XATTR_BUFFERSIZE, &attrsize); if (FSAL_IS_ERROR(fsal_status)) { gsh_free(pxattrfid->specdata.xattr.xattr_content); gsh_free(pxattrfid); /* fsal_status.minor is a valid errno code */ return _9p_rerror(req9p, msgtag, fsal_status.minor, plenout, preply); } } req9p->pconn->fids[*attrfid] = pxattrfid; /* Increments refcount as we're manually making a new copy */ (void) cache_inode_lru_ref(pfid->pentry, LRU_REQ_STALE_OK); /* hold reference on gdata */ uid2grp_hold_group_data(pxattrfid->gdata); get_gsh_export_ref(pfid->export); get_9p_user_cred_ref(pfid->ucred); /* Build the reply */ _9p_setinitptr(cursor, preply, _9P_RXATTRWALK); _9p_setptr(cursor, msgtag, u16); _9p_setvalue(cursor, attrsize, u64); _9p_setendptr(cursor, preply); _9p_checkbound(cursor, preply, plenout); LogDebug(COMPONENT_9P, "RXATTRWALK: tag=%u fid=%u attrfid=%u name=%.*s size=%llu", (u32) *msgtag, *fid, *attrfid, *name_len, name_str, (unsigned long long)attrsize); return 1; } /* _9p_xattrwalk */
int _9p_statfs(struct _9p_request_data *req9p, void *worker_data, 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; u32 type = 0x6969; /* NFS_SUPER_MAGIC for wanting of better, * FSAL do not return this information */ u32 bsize = 1; /* cache_inode_statfs and * FSAL already care for blocksize */ u64 *blocks = NULL; u64 *bfree = NULL; u64 *bavail = NULL; u64 *files = NULL; u64 *ffree = NULL; u64 fsid = 0LL; u32 namelen = MAXNAMLEN; fsal_dynamicfsinfo_t dynamicinfo; cache_inode_status_t cache_status; /* Get data */ _9p_getptr(cursor, msgtag, u16); _9p_getptr(cursor, fid, u32); LogDebug(COMPONENT_9P, "TSTATFS: tag=%u fid=%u", (u32) *msgtag, *fid); if (*fid >= _9P_FID_PER_CONN) return _9p_rerror(req9p, worker_data, msgtag, ERANGE, plenout, preply); pfid = req9p->pconn->fids[*fid]; if (pfid == NULL) return _9p_rerror(req9p, worker_data, msgtag, EINVAL, plenout, preply); /* Get the FS's stats */ cache_status = cache_inode_statfs(pfid->pentry, &dynamicinfo, &pfid->op_context); if (cache_status != CACHE_INODE_SUCCESS) return _9p_rerror(req9p, worker_data, msgtag, _9p_tools_errno(cache_status), plenout, preply); blocks = (u64 *) &dynamicinfo.total_bytes; bfree = (u64 *) &dynamicinfo.free_bytes; bavail = (u64 *) &dynamicinfo.avail_bytes; files = (u64 *) &dynamicinfo.total_files; ffree = (u64 *) &dynamicinfo.free_files; fsid = (u64) pfid->pentry->obj_handle->attributes.rawdev.major; /* Build the reply */ _9p_setinitptr(cursor, preply, _9P_RSTATFS); _9p_setptr(cursor, msgtag, u16); _9p_setvalue(cursor, type, u32); _9p_setvalue(cursor, bsize, u32); _9p_setptr(cursor, blocks, u64); _9p_setptr(cursor, bfree, u64); _9p_setptr(cursor, bavail, u64); _9p_setptr(cursor, files, u64); _9p_setptr(cursor, ffree, u64); _9p_setvalue(cursor, fsid, u64); _9p_setvalue(cursor, namelen, u32); _9p_setendptr(cursor, preply); _9p_checkbound(cursor, preply, plenout); LogDebug(COMPONENT_9P, "RSTATFS: tag=%u fid=%u", (u32) *msgtag, *fid); return 1; }
int _9p_lopen( _9p_request_data_t * preq9p, void * pworker_data, u32 * plenout, char * preply) { char * cursor = preq9p->_9pmsg + _9P_HDR_SIZE + _9P_TYPE_SIZE ; int rc = 0 ; u32 err = 0 ; nfs_worker_data_t * pwkrdata = (nfs_worker_data_t *)pworker_data ; u16 * msgtag = NULL ; u32 * fid = NULL ; u32 * mode = NULL ; fsal_accessflags_t fsalaccess ; cache_inode_status_t cache_status ; 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, mode, u32 ) ; LogDebug( COMPONENT_9P, "TLOPEN: tag=%u fid=%u mode=0x%x", (u32)*msgtag, *fid, *mode ) ; if( *fid >= _9P_FID_PER_CONN ) { err = ERANGE ; rc = _9p_rerror( preq9p, msgtag, &err, plenout, preply ) ; return rc ; } pfid = &preq9p->pconn->fids[*fid] ; _9p_tools_acess2fsal( mode, &fsalaccess ) ; /* Perform the 'access' call */ if(cache_inode_access( pfid->pentry, fsalaccess, pwkrdata->ht, &pwkrdata->cache_inode_client, &pfid->fsal_op_context, &cache_status ) != CACHE_INODE_SUCCESS ) { err = EPERM ; rc = _9p_rerror( preq9p, msgtag, &err, plenout, preply ) ; return rc ; } /* iounit = 0 by default */ pfid->specdata.iounit = 0 ; /* Build the reply */ _9p_setinitptr( cursor, preply, _9P_RLOPEN ) ; _9p_setptr( cursor, msgtag, u16 ) ; _9p_setqid( cursor, pfid->qid ) ; _9p_setptr( cursor, &pfid->specdata.iounit, u32 ) ; _9p_setendptr( cursor, preply ) ; _9p_checkbound( cursor, preply, plenout ) ; LogDebug( COMPONENT_9P, "RLOPEN: tag=%u fid=%u qid=(type=%u,version=%u,path=%llu) iounit=%u", *msgtag, *fid, (u32)pfid->qid.type, pfid->qid.version, (unsigned long long)pfid->qid.path, pfid->specdata.iounit ) ; return 1 ; }
int _9p_xattrwalk( _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 * attrfid = NULL ; u16 * wnames_len ; char * wnames_str ; int rc = 0 ; u32 err = 0 ; if ( !preq9p || !pworker_data || !plenout || !preply ) return -1 ; /* Get data */ _9p_getptr( cursor, msgtag, u16 ) ; _9p_getptr( cursor, fid, u32 ) ; _9p_getptr( cursor, attrfid, u32 ) ; LogDebug( COMPONENT_9P, "TXATTRWALK: tag=%u fid=%u attrfid=%u" , (u32)*msgtag, *fid, *attrfid ) ; _9p_getstr( cursor, wnames_len, wnames_str ) ; LogDebug( COMPONENT_9P, "TXATTRWALK (component): tag=%u fid=%u attrfid=%u nwnames=%.*s", (u32)*msgtag, *fid, *attrfid, *wnames_len, wnames_str ) ; if( *fid >= _9P_FID_PER_CONN ) { err = ERANGE ; rc = _9p_rerror( preq9p, msgtag, &err, plenout, preply ) ; return rc ; } if( *attrfid >= _9P_FID_PER_CONN ) { err = ERANGE ; rc = _9p_rerror( preq9p, msgtag, &err, plenout, preply ) ; return rc ; } /* Build the reply */ _9p_setinitptr( cursor, preply, _9P_RXATTRWALK ) ; _9p_setptr( cursor, msgtag, u16 ) ; _9p_setvalue( cursor, 0LL, u64 ) ; /* No xattr for now */ _9p_setendptr( cursor, preply ) ; _9p_checkbound( cursor, preply, plenout ) ; LogDebug( COMPONENT_9P, "RXATTRWALK: tag=%u fid=%u attrfid=%u nwnames=%.*s", (u32)*msgtag, *fid, *attrfid, *wnames_len, wnames_str ) ; return 1 ; } /* _9p_xattrwalk */
int _9p_remove(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; /* Get data */ _9p_getptr(cursor, msgtag, u16); _9p_getptr(cursor, fid, u32); LogDebug(COMPONENT_9P, "TREMOVE: 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); if ((op_ctx->export_perms->options & EXPORT_OPTION_WRITE_ACCESS) == 0) return _9p_rerror(req9p, msgtag, EROFS, plenout, preply); cache_status = cache_inode_remove(pfid->ppentry, pfid->name); if (cache_status != CACHE_INODE_SUCCESS) return _9p_rerror(req9p, msgtag, _9p_tools_errno(cache_status), plenout, preply); /* If object is an opened file, close it */ if ((pfid->pentry->type == REGULAR_FILE) && is_open(pfid->pentry)) { if (pfid->opens) { cache_inode_dec_pin_ref(pfid->pentry, false); pfid->opens = 0; /* dead */ /* Under this flag, pin ref is still checked */ cache_status = cache_inode_close(pfid->pentry, CACHE_INODE_FLAG_REALLYCLOSE); if (cache_status != CACHE_INODE_SUCCESS) { FREE_FID(pfid, fid, req9p); return _9p_rerror(req9p, msgtag, _9p_tools_errno(cache_status), plenout, preply); } } } /* Clean the fid */ FREE_FID(pfid, fid, req9p); /* Build the reply */ _9p_setinitptr(cursor, preply, _9P_RREMOVE); _9p_setptr(cursor, msgtag, u16); _9p_setendptr(cursor, preply); _9p_checkbound(cursor, preply, plenout); LogDebug(COMPONENT_9P, "TREMOVE: tag=%u fid=%u", (u32) *msgtag, *fid); /* _9p_stat_update( *pmsgtype, TRUE, &pwkrdata->stats._9p_stat_req); */ return 1; }
int _9p_walk(struct _9p_request_data *req9p, void *worker_data, u32 *plenout, char *preply) { char *cursor = req9p->_9pmsg + _9P_HDR_SIZE + _9P_TYPE_SIZE; unsigned int i = 0; u16 *msgtag = NULL; u32 *fid = NULL; u32 *newfid = NULL; u16 *nwname = NULL; u16 *wnames_len; char *wnames_str; uint64_t fileid; cache_inode_status_t cache_status; cache_entry_t *pentry = NULL; char name[MAXNAMLEN]; u16 *nwqid; struct _9p_fid *pfid = NULL; struct _9p_fid *pnewfid = NULL; /* Now Get data */ _9p_getptr(cursor, msgtag, u16); _9p_getptr(cursor, fid, u32); _9p_getptr(cursor, newfid, u32); _9p_getptr(cursor, nwname, u16); LogDebug(COMPONENT_9P, "TWALK: tag=%u fid=%u newfid=%u nwname=%u", (u32) *msgtag, *fid, *newfid, *nwname); if (*fid >= _9P_FID_PER_CONN) return _9p_rerror(req9p, worker_data, msgtag, ERANGE, plenout, preply); if (*newfid >= _9P_FID_PER_CONN) return _9p_rerror(req9p, worker_data, 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, worker_data, msgtag, EIO, plenout, preply); } op_ctx = &pfid->op_context; pnewfid = gsh_calloc(1, sizeof(struct _9p_fid)); if (pnewfid == NULL) return _9p_rerror(req9p, worker_data, msgtag, ERANGE, plenout, preply); /* Is this a lookup or a fid cloning operation ? */ if (*nwname == 0) { /* Cloning operation */ memcpy((char *)pnewfid, (char *)pfid, sizeof(struct _9p_fid)); /* Set the new fid id */ pnewfid->fid = *newfid; /* This is not a TATTACH fid */ pnewfid->from_attach = false; /* Increments refcount */ (void) cache_inode_lru_ref(pnewfid->pentry, LRU_REQ_STALE_OK); } else { /* the walk is in fact a lookup */ pentry = pfid->pentry; for (i = 0; i < *nwname; i++) { _9p_getstr(cursor, wnames_len, wnames_str); snprintf(name, MAXNAMLEN, "%.*s", *wnames_len, wnames_str); LogDebug(COMPONENT_9P, "TWALK (lookup): tag=%u fid=%u newfid=%u (component %u/%u :%s)", (u32) *msgtag, *fid, *newfid, i + 1, *nwname, name); if (pnewfid->pentry == pentry) pnewfid->pentry = NULL; /* refcount +1 */ cache_status = cache_inode_lookup(pentry, name, &pnewfid->pentry); if (pnewfid->pentry == NULL) { gsh_free(pnewfid); return _9p_rerror(req9p, worker_data, msgtag, _9p_tools_errno(cache_status), plenout, preply); } if (pentry != pfid->pentry) cache_inode_put(pentry); pentry = pnewfid->pentry; } pnewfid->fid = *newfid; pnewfid->op_context = pfid->op_context; pnewfid->ppentry = pfid->pentry; strncpy(pnewfid->name, name, MAXNAMLEN-1); /* gdata ref is not hold : the pfid, which use same gdata */ /* will be clunked after pnewfid */ /* This clunk release the gdata */ pnewfid->gdata = pfid->gdata; /* This is not a TATTACH fid */ pnewfid->from_attach = false; cache_status = cache_inode_fileid(pnewfid->pentry, &fileid); if (cache_status != CACHE_INODE_SUCCESS) { gsh_free(pnewfid); return _9p_rerror(req9p, worker_data, msgtag, _9p_tools_errno(cache_status), plenout, preply); } /* Build the qid */ /* No cache, we want the client to stay synchronous * with the server */ pnewfid->qid.version = 0; pnewfid->qid.path = fileid; pnewfid->specdata.xattr.xattr_id = 0; pnewfid->specdata.xattr.xattr_content = NULL; switch (pnewfid->pentry->type) { case REGULAR_FILE: case CHARACTER_FILE: case BLOCK_FILE: case SOCKET_FILE: case FIFO_FILE: pnewfid->qid.type = _9P_QTFILE; break; case SYMBOLIC_LINK: pnewfid->qid.type = _9P_QTSYMLINK; break; case DIRECTORY: pnewfid->qid.type = _9P_QTDIR; break; default: LogMajor(COMPONENT_9P, "implementation error, you should not see this message !!!!!!"); gsh_free(pnewfid); return _9p_rerror(req9p, worker_data, msgtag, EINVAL, plenout, preply); break; } } /* keep info on new fid */ req9p->pconn->fids[*newfid] = pnewfid; /* As much qid as requested fid */ nwqid = nwname; /* Hold refcount on gdata */ uid2grp_hold_group_data(pnewfid->gdata); /* Build the reply */ _9p_setinitptr(cursor, preply, _9P_RWALK); _9p_setptr(cursor, msgtag, u16); _9p_setptr(cursor, nwqid, u16); for (i = 0; i < *nwqid; i++) { /** @todo: should be different qids * for each directory walked through */ _9p_setqid(cursor, pnewfid->qid); } _9p_setendptr(cursor, preply); _9p_checkbound(cursor, preply, plenout); LogDebug(COMPONENT_9P, "RWALK: tag=%u fid=%u newfid=%u nwqid=%u fileid=%llu pentry=%p refcount=%i", (u32) *msgtag, *fid, *newfid, *nwqid, (unsigned long long)pnewfid->qid.path, pnewfid->pentry, pnewfid->pentry->lru.refcnt); return 1; }
int _9p_setattr(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; u32 *valid = NULL; u32 *mode = NULL; u32 *uid = NULL; u32 *gid = NULL; u64 *size = NULL; u64 *atime_sec = NULL; u64 *atime_nsec = NULL; u64 *mtime_sec = NULL; u64 *mtime_nsec = NULL; struct _9p_fid *pfid = NULL; struct attrlist fsalattr; fsal_status_t fsal_status; struct timeval t; /* Get data */ _9p_getptr(cursor, msgtag, u16); _9p_getptr(cursor, fid, u32); _9p_getptr(cursor, valid, u32); _9p_getptr(cursor, mode, u32); _9p_getptr(cursor, uid, u32); _9p_getptr(cursor, gid, u32); _9p_getptr(cursor, size, u64); _9p_getptr(cursor, atime_sec, u64); _9p_getptr(cursor, atime_nsec, u64); _9p_getptr(cursor, mtime_sec, u64); _9p_getptr(cursor, mtime_nsec, u64); LogDebug(COMPONENT_9P, "TSETATTR: tag=%u fid=%u valid=0x%x mode=0%o uid=%u gid=%u size=%" PRIu64 " atime=(%llu|%llu) mtime=(%llu|%llu)", (u32) *msgtag, *fid, *valid, *mode, *uid, *gid, *size, (unsigned long long)*atime_sec, (unsigned long long)*atime_nsec, (unsigned long long)*mtime_sec, (unsigned long long)*mtime_nsec); 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); if ((op_ctx->export_perms->options & EXPORT_OPTION_WRITE_ACCESS) == 0) return _9p_rerror(req9p, msgtag, EROFS, plenout, preply); /* If a "time" change is required, but not with the "_set" suffix, * use gettimeofday */ if (*valid & (_9P_SETATTR_ATIME | _9P_SETATTR_CTIME | _9P_SETATTR_MTIME)) { if (gettimeofday(&t, NULL) == -1) { LogMajor(COMPONENT_9P, "TSETATTR: tag=%u fid=%u ERROR !! gettimeofday returned -1 with errno=%u", (u32) *msgtag, *fid, errno); return _9p_rerror(req9p, msgtag, errno, plenout, preply); } } /* Let's do the job */ memset((char *)&fsalattr, 0, sizeof(fsalattr)); if (*valid & _9P_SETATTR_MODE) { FSAL_SET_MASK(fsalattr.mask, ATTR_MODE); fsalattr.mode = *mode; } if (*valid & _9P_SETATTR_UID) { FSAL_SET_MASK(fsalattr.mask, ATTR_OWNER); fsalattr.owner = *uid; } if (*valid & _9P_SETATTR_GID) { FSAL_SET_MASK(fsalattr.mask, ATTR_GROUP); fsalattr.group = *gid; } if (*valid & _9P_SETATTR_SIZE) { FSAL_SET_MASK(fsalattr.mask, ATTR_SIZE); fsalattr.filesize = *size; } if (*valid & _9P_SETATTR_ATIME) { FSAL_SET_MASK(fsalattr.mask, ATTR_ATIME); fsalattr.atime.tv_sec = t.tv_sec; fsalattr.atime.tv_nsec = t.tv_usec * 1000; } if (*valid & _9P_SETATTR_MTIME) { FSAL_SET_MASK(fsalattr.mask, ATTR_MTIME); fsalattr.mtime.tv_sec = t.tv_sec; fsalattr.mtime.tv_nsec = t.tv_usec * 1000; } if (*valid & _9P_SETATTR_CTIME) { FSAL_SET_MASK(fsalattr.mask, ATTR_CTIME); fsalattr.ctime.tv_sec = t.tv_sec; fsalattr.ctime.tv_nsec = t.tv_usec * 1000; } if (*valid & _9P_SETATTR_ATIME_SET) { FSAL_SET_MASK(fsalattr.mask, ATTR_ATIME); fsalattr.atime.tv_sec = *atime_sec; fsalattr.atime.tv_nsec = *atime_nsec; } if (*valid & _9P_SETATTR_MTIME_SET) { FSAL_SET_MASK(fsalattr.mask, ATTR_MTIME); fsalattr.mtime.tv_sec = *mtime_sec; fsalattr.mtime.tv_nsec = *mtime_nsec; } /* Now set the attr */ fsal_status = fsal_setattr(pfid->pentry, false, pfid->state, &fsalattr); /* Release the attributes (may release an inherited ACL) */ fsal_release_attrs(&fsalattr); if (FSAL_IS_ERROR(fsal_status)) return _9p_rerror(req9p, msgtag, _9p_tools_errno(fsal_status), plenout, preply); /* Build the reply */ _9p_setinitptr(cursor, preply, _9P_RSETATTR); _9p_setptr(cursor, msgtag, u16); _9p_setendptr(cursor, preply); _9p_checkbound(cursor, preply, plenout); LogDebug(COMPONENT_9P, "RSETATTR: tag=%u fid=%u valid=0x%x mode=0%o uid=%u gid=%u size=%" PRIu64 " atime=(%llu|%llu) mtime=(%llu|%llu)", (u32) *msgtag, *fid, *valid, *mode, *uid, *gid, *size, (unsigned long long)*atime_sec, (unsigned long long)*atime_nsec, (unsigned long long)*mtime_sec, (unsigned long long)*mtime_nsec); /* _9p_stat_update(*pmsgtype, TRUE, &pwkrdata->stats._9p_stat_req); */ 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 ; }
int _9p_write(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; u64 *offset = NULL; u32 *count = NULL; u32 outcount = 0; struct _9p_fid *pfid = NULL; size_t size; size_t written_size = 0; char *databuffer = NULL; /* Get data */ _9p_getptr(cursor, msgtag, u16); _9p_getptr(cursor, fid, u32); _9p_getptr(cursor, offset, u64); _9p_getptr(cursor, count, u32); databuffer = cursor; LogDebug(COMPONENT_9P, "TWRITE: tag=%u fid=%u offset=%llu count=%u", (u32) *msgtag, *fid, (unsigned long long)*offset, *count); if (*fid >= _9P_FID_PER_CONN) return _9p_rerror(req9p, msgtag, ERANGE, plenout, preply); pfid = req9p->pconn->fids[*fid]; /* Make sure the requested amount of data respects negotiated msize */ if (*count + _9P_ROOM_TWRITE > req9p->pconn->msize) return _9p_rerror(req9p, msgtag, ERANGE, plenout, preply); /* 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); if ((op_ctx->export_perms->options & EXPORT_OPTION_WRITE_ACCESS) == 0) return _9p_rerror(req9p, msgtag, EROFS, plenout, preply); /* Do the job */ size = *count; if (pfid->xattr != NULL) { if (*offset > pfid->xattr->xattr_size) return _9p_rerror(req9p, msgtag, EINVAL, plenout, preply); if (pfid->xattr->xattr_write != _9P_XATTR_CAN_WRITE && pfid->xattr->xattr_write != _9P_XATTR_DID_WRITE) return _9p_rerror(req9p, msgtag, EINVAL, plenout, preply); written_size = MIN(*count, pfid->xattr->xattr_size - *offset); memcpy(pfid->xattr->xattr_content + *offset, databuffer, written_size); pfid->xattr->xattr_offset += size; pfid->xattr->xattr_write = _9P_XATTR_DID_WRITE; /* ADD CODE TO DETECT GAP */ #if 0 fsal_status = pfid->pentry->ops->setextattr_value_by_id( pfid->pentry, &pfid->op_context, pfid->xattr->xattr_id, xattrval, size + 1); if (FSAL_IS_ERROR(fsal_status)) return _9p_rerror(req9p, msgtag, _9p_tools_errno(fsal_status), plenout, preply); #endif outcount = written_size; } else { struct _9p_write_data write_data; struct fsal_io_arg *write_arg = alloca(sizeof(*write_arg) + sizeof(struct iovec)); write_arg->info = NULL; write_arg->state = pfid->state; write_arg->offset = *offset; write_arg->iov_count = 1; write_arg->iov[0].iov_len = size; write_arg->iov[0].iov_base = databuffer; write_arg->io_amount = 0; write_arg->fsal_stable = false; write_data.client = req9p->pconn->client; /* Do the actual write */ pfid->pentry->obj_ops->write2(pfid->pentry, true, _9p_write_cb, write_arg, &write_data); if (FSAL_IS_ERROR(write_data.ret)) return _9p_rerror(req9p, msgtag, _9p_tools_errno(write_data.ret), plenout, preply); outcount = (u32) write_arg->io_amount; } /* Build the reply */ _9p_setinitptr(cursor, preply, _9P_RWRITE); _9p_setptr(cursor, msgtag, u16); _9p_setvalue(cursor, outcount, u32); _9p_setendptr(cursor, preply); _9p_checkbound(cursor, preply, plenout); LogDebug(COMPONENT_9P, "RWRITE: tag=%u fid=%u offset=%llu input count=%u output count=%u", (u32) *msgtag, *fid, (unsigned long long)*offset, *count, outcount); /** * @todo write statistics accounting goes here * modeled on nfs I/O stats */ return 1; }
int _9p_rename(struct _9p_request_data *req9p, void *worker_data, u32 *plenout, char *preply) { char *cursor = req9p->_9pmsg + _9P_HDR_SIZE + _9P_TYPE_SIZE; u16 *msgtag = NULL; u32 *fid = NULL; u32 *dfid = NULL; u16 *name_len = NULL; char *name_str = NULL; /* for unused-but-set-variable */ struct _9p_fid *pfid = NULL; struct _9p_fid *pdfid = NULL; char newname[MAXNAMLEN]; cache_inode_status_t cache_status; /* Get data */ _9p_getptr(cursor, msgtag, u16); _9p_getptr(cursor, fid, u32); _9p_getptr(cursor, dfid, u32); _9p_getstr(cursor, name_len, name_str); LogDebug(COMPONENT_9P, "TRENAME: tag=%u fid=%u dfid=%u name=%.*s", (u32) *msgtag, *fid, *dfid, *name_len, name_str); if (*fid >= _9P_FID_PER_CONN) return _9p_rerror(req9p, worker_data, 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, worker_data, msgtag, EIO, plenout, preply); } if (*dfid >= _9P_FID_PER_CONN) return _9p_rerror(req9p, worker_data, msgtag, ERANGE, plenout, preply); pdfid = req9p->pconn->fids[*dfid]; /* Check that it is a valid fid */ if (pdfid == NULL || pdfid->pentry == NULL) { LogDebug(COMPONENT_9P, "request on invalid fid=%u", *fid); return _9p_rerror(req9p, worker_data, msgtag, EIO, plenout, preply); } snprintf(newname, MAXNAMLEN, "%.*s", *name_len, name_str); cache_status = cache_inode_rename(pfid->ppentry, pfid->name, pdfid->pentry, newname, &pfid->op_context); if (cache_status != CACHE_INODE_SUCCESS) return _9p_rerror(req9p, worker_data, msgtag, _9p_tools_errno(cache_status), plenout, preply); /* Build the reply */ _9p_setinitptr(cursor, preply, _9P_RRENAME); _9p_setptr(cursor, msgtag, u16); _9p_setendptr(cursor, preply); _9p_checkbound(cursor, preply, plenout); LogDebug(COMPONENT_9P, "RRENAMEAT: tag=%u fid=%u dfid=%u newname=%.*s", (u32) *msgtag, *fid, *dfid, *name_len, name_str); /* _9p_stat_update(*pmsgtype, TRUE, &pwkrdata->stats._9p_stat_req); */ return 1; }
int _9p_mkdir(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; u32 *mode = NULL; u32 *gid = NULL; u16 *name_len = NULL; char *name_str = NULL; struct _9p_fid *pfid = NULL; struct _9p_qid qid_newdir; struct fsal_obj_handle *pentry_newdir = NULL; char dir_name[MAXNAMLEN+1]; fsal_status_t fsal_status; struct attrlist sattr; /* Get data */ _9p_getptr(cursor, msgtag, u16); _9p_getptr(cursor, fid, u32); _9p_getstr(cursor, name_len, name_str); _9p_getptr(cursor, mode, u32); _9p_getptr(cursor, gid, u32); LogDebug(COMPONENT_9P, "TMKDIR: tag=%u fid=%u name=%.*s mode=0%o gid=%u", (u32) *msgtag, *fid, *name_len, name_str, *mode, *gid); 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); if ((op_ctx->export_perms->options & EXPORT_OPTION_WRITE_ACCESS) == 0) return _9p_rerror(req9p, msgtag, EROFS, plenout, preply); if (*name_len >= sizeof(dir_name)) { LogDebug(COMPONENT_9P, "request with name too long (%u)", *name_len); return _9p_rerror(req9p, msgtag, ENAMETOOLONG, plenout, preply); } snprintf(dir_name, sizeof(dir_name), "%.*s", *name_len, name_str); fsal_prepare_attrs(&sattr, ATTR_MODE); sattr.mode = *mode; sattr.valid_mask = ATTR_MODE; /* Create the directory */ /* BUGAZOMEU: @todo : the gid parameter is not used yet */ fsal_status = fsal_create(pfid->pentry, dir_name, DIRECTORY, &sattr, NULL, &pentry_newdir, NULL); /* Release the attributes (may release an inherited ACL) */ fsal_release_attrs(&sattr); if (FSAL_IS_ERROR(fsal_status)) return _9p_rerror(req9p, msgtag, _9p_tools_errno(fsal_status), plenout, preply); pentry_newdir->obj_ops.put_ref(pentry_newdir); /* Build the qid */ qid_newdir.type = _9P_QTDIR; qid_newdir.version = 0; qid_newdir.path = pentry_newdir->fileid; /* Build the reply */ _9p_setinitptr(cursor, preply, _9P_RMKDIR); _9p_setptr(cursor, msgtag, u16); _9p_setqid(cursor, qid_newdir); _9p_setendptr(cursor, preply); _9p_checkbound(cursor, preply, plenout); LogDebug(COMPONENT_9P, "RMKDIR: tag=%u fid=%u name=%.*s qid=(type=%u,version=%u,path=%llu)", (u32) *msgtag, *fid, *name_len, name_str, qid_newdir.type, qid_newdir.version, (unsigned long long)qid_newdir.path); return 1; }
int _9p_symlink(struct _9p_request_data *req9p, void *worker_data, u32 *plenout, char *preply) { char *cursor = req9p->_9pmsg + _9P_HDR_SIZE + _9P_TYPE_SIZE; u16 *msgtag = NULL; u32 *fid = NULL; u16 *name_len = NULL; char *name_str = NULL; u16 *linkcontent_len = NULL; char *linkcontent_str = NULL; u32 *gid = NULL; struct _9p_fid *pfid = NULL; struct _9p_qid qid_symlink; cache_entry_t *pentry_symlink = NULL; char symlink_name[MAXNAMLEN]; uint64_t fileid; cache_inode_status_t cache_status; uint32_t mode = 0777; cache_inode_create_arg_t create_arg; memset(&create_arg, 0, sizeof(create_arg)); /* Get data */ _9p_getptr(cursor, msgtag, u16); _9p_getptr(cursor, fid, u32); _9p_getstr(cursor, name_len, name_str); _9p_getstr(cursor, linkcontent_len, linkcontent_str); _9p_getptr(cursor, gid, u32); LogDebug(COMPONENT_9P, "TSYMLINK: tag=%u fid=%u name=%.*s linkcontent=%.*s gid=%u", (u32) *msgtag, *fid, *name_len, name_str, *linkcontent_len, linkcontent_str, *gid); if (*fid >= _9P_FID_PER_CONN) return _9p_rerror(req9p, worker_data, 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, worker_data, msgtag, EIO, plenout, preply); } if ((pfid->op_context.export_perms->options & EXPORT_OPTION_WRITE_ACCESS) == 0) return _9p_rerror(req9p, worker_data, msgtag, EROFS, plenout, preply); op_ctx = &pfid->op_context; snprintf(symlink_name, MAXNAMLEN, "%.*s", *name_len, name_str); create_arg.link_content = gsh_malloc(MAXPATHLEN); if (create_arg.link_content == NULL) return _9p_rerror(req9p, worker_data, msgtag, EFAULT, plenout, preply); snprintf(create_arg.link_content, MAXPATHLEN, "%.*s", *linkcontent_len, linkcontent_str); /* Let's do the job */ /* BUGAZOMEU: @todo : the gid parameter is not used yet, * flags is not yet used */ cache_status = cache_inode_create(pfid->pentry, symlink_name, SYMBOLIC_LINK, mode, &create_arg, &pentry_symlink); if (create_arg.link_content != NULL) gsh_free(create_arg.link_content); if (pentry_symlink == NULL) { return _9p_rerror(req9p, worker_data, msgtag, _9p_tools_errno(cache_status), plenout, preply); } /* This is not a TATTACH fid */ pfid->from_attach = false; cache_status = cache_inode_fileid(pentry_symlink, &fileid); /* put the entry: * we don't want to remember it even if cache_inode_fileid fails. */ cache_inode_put(pentry_symlink); if (cache_status != CACHE_INODE_SUCCESS) { return _9p_rerror(req9p, worker_data, msgtag, _9p_tools_errno(cache_status), plenout, preply); } /* Build the qid */ qid_symlink.type = _9P_QTSYMLINK; qid_symlink.version = 0; qid_symlink.path = fileid; /* Build the reply */ _9p_setinitptr(cursor, preply, _9P_RSYMLINK); _9p_setptr(cursor, msgtag, u16); _9p_setqid(cursor, qid_symlink); _9p_setendptr(cursor, preply); _9p_checkbound(cursor, preply, plenout); LogDebug(COMPONENT_9P, "RSYMLINK: tag=%u fid=%u name=%.*s qid=(type=%u,version=%u,path=%llu)", (u32) *msgtag, *fid, *name_len, name_str, qid_symlink.type, qid_symlink.version, (unsigned long long)qid_symlink.path); return 1; }
int _9p_link( _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 * dfid = NULL ; u32 * targetfid = NULL ; u16 * name_len = NULL ; char * name_str = NULL ; _9p_fid_t * pdfid = NULL ; _9p_fid_t * ptargetfid = NULL ; cache_entry_t * pentry= NULL ; fsal_attrib_list_t fsalattr ; cache_inode_status_t cache_status ; fsal_name_t link_name ; int rc = 0 ; int err = 0 ; if ( !preq9p || !pworker_data || !plenout || !preply ) return -1 ; /* Get data */ _9p_getptr( cursor, msgtag, u16 ) ; _9p_getptr( cursor, dfid, u32 ) ; _9p_getptr( cursor, targetfid, u32 ) ; _9p_getstr( cursor, name_len, name_str ) ; LogDebug( COMPONENT_9P, "TLINK: tag=%u dfid=%u targetfid=%u name=%.*s", (u32)*msgtag, *dfid, *targetfid, *name_len, name_str ) ; if( *dfid >= _9P_FID_PER_CONN ) { err = ERANGE ; rc = _9p_rerror( preq9p, msgtag, &err, plenout, preply ) ; return rc ; } pdfid = &preq9p->pconn->fids[*dfid] ; if( *targetfid >= _9P_FID_PER_CONN ) { err = ERANGE ; rc = _9p_rerror( preq9p, msgtag, &err, plenout, preply ) ; return rc ; } ptargetfid = &preq9p->pconn->fids[*targetfid] ; /* Let's do the job */ snprintf( link_name.name, FSAL_MAX_NAME_LEN, "%.*s", *name_len, name_str ) ; if( cache_inode_link( ptargetfid->pentry, pdfid->pentry, &link_name, ptargetfid->pexport->cache_inode_policy, &fsalattr, pwkrdata->ht, &pwkrdata->cache_inode_client, &pdfid->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_RLINK ) ; _9p_setptr( cursor, msgtag, u16 ) ; _9p_setendptr( cursor, preply ) ; _9p_checkbound( cursor, preply, plenout ) ; LogDebug( COMPONENT_9P, "TLINK: tag=%u dfid=%u targetfid=%u name=%.*s", (u32)*msgtag, *dfid, *targetfid, *name_len, name_str ) ; return 1 ; }
int _9p_lopen( _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 * fid = NULL ; u32 * flags = NULL ; cache_inode_status_t cache_status ; fsal_openflags_t openflags = 0 ; 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, flags, u32 ) ; LogDebug( COMPONENT_9P, "TLOPEN: tag=%u fid=%u flags=0x%x", (u32)*msgtag, *fid, *flags ) ; if( *fid >= _9P_FID_PER_CONN ) return _9p_rerror( preq9p, msgtag, ERANGE, plenout, preply ) ; pfid = &preq9p->pconn->fids[*fid] ; _9p_openflags2FSAL( flags, &openflags ) ; if( pfid->pentry->type == REGULAR_FILE ) /** @todo: Maybe other types (FIFO, sOCKET,...) may require to be opened too */ { if(cache_inode_open( pfid->pentry, openflags, &pfid->fsal_op_context, 0, &cache_status) != CACHE_INODE_SUCCESS) return _9p_rerror( preq9p, msgtag, _9p_tools_errno( cache_status ), plenout, preply ) ; } /* iounit = 0 by default */ pfid->specdata.iounit = 0 ; /* Build the reply */ _9p_setinitptr( cursor, preply, _9P_RLOPEN ) ; _9p_setptr( cursor, msgtag, u16 ) ; _9p_setqid( cursor, pfid->qid ) ; _9p_setptr( cursor, &pfid->specdata.iounit, u32 ) ; _9p_setendptr( cursor, preply ) ; _9p_checkbound( cursor, preply, plenout ) ; LogDebug( COMPONENT_9P, "RLOPEN: tag=%u fid=%u qid=(type=%u,version=%u,path=%llu) iounit=%u", *msgtag, *fid, (u32)pfid->qid.type, pfid->qid.version, (unsigned long long)pfid->qid.path, pfid->specdata.iounit ) ; return 1 ; }
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 _9p_symlink( _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 ; u16 * name_len = NULL ; char * name_str = NULL ; u16 * linkcontent_len = NULL ; char * linkcontent_str = NULL ; u32 * gid = NULL ; _9p_fid_t * pfid = NULL ; _9p_qid_t qid_symlink ; cache_entry_t * pentry_symlink = NULL ; fsal_name_t symlink_name ; fsal_attrib_list_t fsalattr ; cache_inode_status_t cache_status ; fsal_accessmode_t mode = 0777; cache_inode_create_arg_t create_arg; int rc = 0 ; int err = 0 ; if ( !preq9p || !pworker_data || !plenout || !preply ) return -1 ; memset(&create_arg, 0, sizeof(create_arg)); /* Get data */ _9p_getptr( cursor, msgtag, u16 ) ; _9p_getptr( cursor, fid, u32 ) ; _9p_getstr( cursor, name_len, name_str ) ; _9p_getstr( cursor, linkcontent_len, linkcontent_str ) ; _9p_getptr( cursor, gid, u32 ) ; LogDebug( COMPONENT_9P, "TSYMLINK: tag=%u fid=%u name=%.*s linkcontent=%.*s gid=%u", (u32)*msgtag, *fid, *name_len, name_str, *linkcontent_len, linkcontent_str, *gid ) ; if( *fid >= _9P_FID_PER_CONN ) { err = ERANGE ; rc = _9p_rerror( preq9p, msgtag, &err, plenout, preply ) ; return rc ; } pfid = &preq9p->pconn->fids[*fid] ; snprintf( symlink_name.name, FSAL_MAX_NAME_LEN, "%.*s", *name_len, name_str ) ; snprintf( create_arg.link_content.path, FSAL_MAX_PATH_LEN, "%.*s", *linkcontent_len, linkcontent_str ) ; /* Let's do the job */ /* BUGAZOMEU: @todo : the gid parameter is not used yet, flags is not yet used */ if( ( pentry_symlink = cache_inode_create( pfid->pentry, &symlink_name, SYMBOLIC_LINK, pfid->pexport->cache_inode_policy, mode, &create_arg, &fsalattr, 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 ; } /* Build the qid */ qid_symlink.type = _9P_QTSYMLINK ; qid_symlink.version = 0 ; qid_symlink.path = fsalattr.fileid ; /* Build the reply */ _9p_setinitptr( cursor, preply, _9P_RSYMLINK ) ; _9p_setptr( cursor, msgtag, u16 ) ; _9p_setqid( cursor, qid_symlink ) ; _9p_setendptr( cursor, preply ) ; _9p_checkbound( cursor, preply, plenout ) ; LogDebug( COMPONENT_9P, "RSYMLINK: tag=%u fid=%u name=%.*s qid=(type=%u,version=%u,path=%llu)", (u32)*msgtag, *fid, *name_len, name_str, qid_symlink.type, qid_symlink.version, (unsigned long long)qid_symlink.path ) ; return 1 ; }
int _9p_renameat( _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 * oldfid = NULL ; u16 * oldname_len = NULL ; char * oldname_str = NULL ; u32 * newfid = NULL ; u16 * newname_len = NULL ; char * newname_str = NULL ; _9p_fid_t * poldfid = NULL ; _9p_fid_t * pnewfid = NULL ; fsal_attrib_list_t oldfsalattr ; fsal_attrib_list_t newfsalattr ; cache_inode_status_t cache_status ; fsal_name_t oldname ; fsal_name_t newname ; if ( !preq9p || !pworker_data || !plenout || !preply ) return -1 ; /* Get data */ _9p_getptr( cursor, msgtag, u16 ) ; _9p_getptr( cursor, oldfid, u32 ) ; _9p_getstr( cursor, oldname_len, oldname_str ) ; _9p_getptr( cursor, newfid, u32 ) ; _9p_getstr( cursor, newname_len, newname_str ) ; LogDebug( COMPONENT_9P, "TRENAMEAT: tag=%u oldfid=%u oldname=%.*s newfid=%u newname=%.*s", (u32)*msgtag, *oldfid, *oldname_len, oldname_str, *newfid, *newname_len, newname_str ) ; if( *oldfid >= _9P_FID_PER_CONN ) return _9p_rerror( preq9p, msgtag, ERANGE, plenout, preply ) ; poldfid = &preq9p->pconn->fids[*oldfid] ; if( *newfid >= _9P_FID_PER_CONN ) return _9p_rerror( preq9p, msgtag, ERANGE, plenout, preply ) ; pnewfid = &preq9p->pconn->fids[*newfid] ; /* Let's do the job */ snprintf( oldname.name, FSAL_MAX_NAME_LEN, "%.*s", *oldname_len, oldname_str ) ; oldname.len = *oldname_len + 1 ; snprintf( newname.name, FSAL_MAX_NAME_LEN, "%.*s", *newname_len, newname_str ) ; newname.len = *newname_len + 1 ; if( cache_inode_rename( poldfid->pentry, &oldname, pnewfid->pentry, &newname, &oldfsalattr, &newfsalattr, &poldfid->fsal_op_context, &cache_status) != CACHE_INODE_SUCCESS ) return _9p_rerror( preq9p, msgtag, _9p_tools_errno( cache_status ), plenout, preply ) ; /* Build the reply */ _9p_setinitptr( cursor, preply, _9P_RRENAMEAT ) ; _9p_setptr( cursor, msgtag, u16 ) ; _9p_setendptr( cursor, preply ) ; _9p_checkbound( cursor, preply, plenout ) ; LogDebug( COMPONENT_9P, "RRENAMEAT: tag=%u oldfid=%u oldname=%.*s newfid=%u newname=%.*s", (u32)*msgtag, *oldfid, *oldname_len, oldname_str, *newfid, *newname_len, newname_str ) ; return 1 ; }
int _9p_xattrcreate(struct _9p_request_data *req9p, u32 *plenout, char *preply) { char *cursor = req9p->_9pmsg + _9P_HDR_SIZE + _9P_TYPE_SIZE; int create; u16 *msgtag = NULL; u32 *fid = NULL; u64 *size; u32 *flag; u16 *name_len; char *name_str; struct _9p_fid *pfid = NULL; fsal_status_t fsal_status = { .major = ERR_FSAL_NO_ERROR, .minor = 0 }; char name[MAXNAMLEN+1]; /* Get data */ _9p_getptr(cursor, msgtag, u16); _9p_getptr(cursor, fid, u32); _9p_getstr(cursor, name_len, name_str); _9p_getptr(cursor, size, u64); _9p_getptr(cursor, flag, u32); LogDebug(COMPONENT_9P, "TXATTRCREATE: tag=%u fid=%u name=%.*s size=%llu flag=%u", (u32) *msgtag, *fid, *name_len, name_str, (unsigned long long)*size, *flag); if (*fid >= _9P_FID_PER_CONN) return _9p_rerror(req9p, msgtag, ERANGE, plenout, preply); if (*size > _9P_XATTR_MAX_SIZE) return _9p_rerror(req9p, msgtag, ENOSPC, 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); } /* set op_ctx, it will be useful if FSAL is later called */ _9p_init_opctx(pfid, req9p); if ((op_ctx->export_perms->options & EXPORT_OPTION_WRITE_ACCESS) == 0) return _9p_rerror(req9p, msgtag, EROFS, plenout, preply); if (*name_len >= sizeof(name)) { LogDebug(COMPONENT_9P, "request with name too long (%u)", *name_len); return _9p_rerror(req9p, msgtag, ENAMETOOLONG, plenout, preply); } snprintf(name, sizeof(name), "%.*s", *name_len, name_str); if (*size == 0LL) { /* Size == 0 : this is in fact a call to removexattr */ LogDebug(COMPONENT_9P, "TXATTRCREATE: tag=%u fid=%u : will remove xattr %s", (u32) *msgtag, *fid, name); fsal_status = pfid->pentry->obj_ops.remove_extattr_by_name(pfid->pentry, name); if (FSAL_IS_ERROR(fsal_status)) return _9p_rerror(req9p, msgtag, _9p_tools_errno(fsal_status), plenout, preply); } else { /* Size != 0 , this is a creation/replacement of xattr */ /* Create the xattr at the FSAL level and cache result */ pfid->xattr = gsh_malloc(sizeof(*pfid->xattr) + *size); pfid->xattr->xattr_size = *size; pfid->xattr->xattr_offset = 0LL; pfid->xattr->xattr_write = _9P_XATTR_CAN_WRITE; strncpy(pfid->xattr->xattr_name, name, MAXNAMLEN); /* /!\ POSIX_ACL RELATED HOOK * Setting a POSIX ACL (using setfacl for example) means * settings a xattr named system.posix_acl_access BUT this * attribute is to be used and should not be created * (it exists already since acl feature is on) */ if (!strncmp(name, "system.posix_acl_access", MAXNAMLEN)) goto skip_create; /* try to create if flag doesn't have REPLACE bit */ if ((*flag & XATTR_REPLACE) == 0) create = true; else create = false; fsal_status = pfid->pentry->obj_ops.setextattr_value(pfid->pentry, name, pfid->xattr->xattr_content, *size, create); /* Try again with create = false if flag was set to 0 * and create failed because attribute already exists */ if (FSAL_IS_ERROR(fsal_status) && fsal_status.major == ERR_FSAL_EXIST && (*flag == 0)) { fsal_status = pfid->pentry->obj_ops.setextattr_value(pfid->pentry, name, pfid->xattr->xattr_content, *size, false); } if (FSAL_IS_ERROR(fsal_status)) { gsh_free(pfid->xattr); return _9p_rerror(req9p, msgtag, _9p_tools_errno(fsal_status), plenout, preply); } } skip_create: /* Build the reply */ _9p_setinitptr(cursor, preply, _9P_RXATTRCREATE); _9p_setptr(cursor, msgtag, u16); _9p_setendptr(cursor, preply); _9p_checkbound(cursor, preply, plenout); LogDebug(COMPONENT_9P, "RXATTRCREATE: tag=%u fid=%u name=%.*s size=%llu flag=%u", (u32) *msgtag, *fid, *name_len, name_str, (unsigned long long)*size, *flag); return 1; } /* _9p_xattrcreate */
int _9p_setattr( _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 * valid = NULL ; u32 * mode = NULL ; u32 * uid = NULL ; u32 * gid = NULL ; u64 * size = NULL ; u64 * atime_sec = NULL ; u64 * atime_nsec = NULL ; u64 * mtime_sec = NULL ; u64 * mtime_nsec = NULL ; _9p_fid_t * pfid = NULL ; fsal_attrib_list_t fsalattr ; cache_inode_status_t cache_status ; struct timeval t; int rc = 0 ; int err = 0 ; if ( !preq9p || !pworker_data || !plenout || !preply ) return -1 ; /* Get data */ _9p_getptr( cursor, msgtag, u16 ) ; _9p_getptr( cursor, fid, u32 ) ; _9p_getptr( cursor, valid, u32 ) ; _9p_getptr( cursor, mode, u32 ) ; _9p_getptr( cursor, uid, u32 ) ; _9p_getptr( cursor, gid, u32 ) ; _9p_getptr( cursor, size, u64 ) ; _9p_getptr( cursor, atime_sec, u64 ) ; _9p_getptr( cursor, atime_nsec, u64 ) ; _9p_getptr( cursor, mtime_sec, u64 ) ; _9p_getptr( cursor, mtime_nsec, u64 ) ; LogDebug( COMPONENT_9P, "TSETATTR: tag=%u fid=%u mode=0%o uid=%u gid=%u size=%llu atime=(%llu|%llu) mtime=(%llu|%llu)", (u32)*msgtag, *fid, *mode, *uid, *gid, *size, (unsigned long long)*atime_sec, (unsigned long long)*atime_nsec, (unsigned long long)*mtime_sec, (unsigned long long)*mtime_nsec ) ; if( *fid >= _9P_FID_PER_CONN ) { err = ERANGE ; rc = _9p_rerror( preq9p, msgtag, &err, plenout, preply ) ; return rc ; } pfid = &preq9p->pconn->fids[*fid] ; /* If a "time" change is required, but not with the "_set" suffix, use gettimeofday */ if( *valid & (_9P_SETATTR_ATIME|_9P_SETATTR_CTIME|_9P_SETATTR_MTIME) ) { if( gettimeofday( &t, NULL ) == -1 ) { LogMajor( COMPONENT_9P, "TSETATTR: tag=%u fid=%u ERROR !! gettimeofday returned -1 with errno=%u", (u32)*msgtag, *fid, errno ) ; err = errno ; rc = _9p_rerror( preq9p, msgtag, &err, plenout, preply ) ; return rc ; } } /* Let's do the job */ memset( (char *)&fsalattr, 0, sizeof( fsalattr ) ) ; if( *valid & _9P_SETATTR_MODE ) { fsalattr.asked_attributes |= FSAL_ATTR_MODE ; fsalattr.mode = *mode ; } if( *valid & _9P_SETATTR_UID ) { fsalattr.asked_attributes |= FSAL_ATTR_OWNER ; fsalattr.owner = *uid ; } if( *valid & _9P_SETATTR_GID ) { fsalattr.asked_attributes |= FSAL_ATTR_GROUP ; fsalattr.group = *gid ; } if( *valid & _9P_SETATTR_SIZE ) { fsalattr.asked_attributes |= FSAL_ATTR_SIZE ; fsalattr.filesize = *size ; } if( *valid & _9P_SETATTR_ATIME ) { fsalattr.asked_attributes |= FSAL_ATTR_ATIME ; fsalattr.atime.seconds = t.tv_sec ; fsalattr.atime.nseconds = t.tv_usec * 1000 ; } if( *valid & _9P_SETATTR_MTIME ) { fsalattr.asked_attributes |= FSAL_ATTR_MTIME ; fsalattr.mtime.seconds = t.tv_sec ; fsalattr.mtime.nseconds = t.tv_usec * 1000 ; } if( *valid & _9P_SETATTR_CTIME ) { fsalattr.asked_attributes |= FSAL_ATTR_CTIME ; fsalattr.ctime.seconds = t.tv_sec ; fsalattr.ctime.nseconds = t.tv_usec * 1000 ; } if( *valid & _9P_SETATTR_ATIME_SET ) { fsalattr.asked_attributes |= FSAL_ATTR_ATIME ; fsalattr.atime.seconds = *atime_sec ; fsalattr.atime.nseconds = *atime_nsec ; } if( *valid & _9P_SETATTR_MTIME_SET ) { fsalattr.asked_attributes |= FSAL_ATTR_MTIME ; fsalattr.mtime.seconds = *mtime_sec ; fsalattr.mtime.nseconds = *mtime_nsec ; } /* Now set the attr */ if( cache_inode_setattr( pfid->pentry, &fsalattr, 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_RSETATTR ) ; _9p_setptr( cursor, msgtag, u16 ) ; _9p_setendptr( cursor, preply ) ; _9p_checkbound( cursor, preply, plenout ) ; return 1 ; }