Esempio n. 1
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;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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 ;
}
Esempio n. 4
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 ;
}
Esempio n. 5
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 ;
}