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 ;
}
Exemple #2
0
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;
}
Exemple #4
0
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 ;
}
Exemple #6
0
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 ;
}
Exemple #7
0
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 ;
}
Exemple #8
0
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;
}
Exemple #9
0
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 ;
}
Exemple #10
0
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;
}
Exemple #11
0
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 */
Exemple #13
0
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;
}
Exemple #14
0
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 ;
}
Exemple #15
0
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;

}
Exemple #17
0
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;
}
Exemple #18
0
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;
}
Exemple #19
0
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 ;
}
Exemple #20
0
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;
}
Exemple #21
0
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;
}
Exemple #22
0
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;
}
Exemple #23
0
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;
}
Exemple #24
0
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 ;
}
Exemple #25
0
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 ;
}
Exemple #26
0
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 ;
}
Exemple #27
0
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 ;
}
Exemple #29
0
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 */
Exemple #30
0
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 ;
}