Пример #1
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 ;
}
Пример #2
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 ;
}
Пример #3
0
int nfs_Create(nfs_arg_t *parg,
               exportlist_t *pexport,
               fsal_op_context_t *pcontext,
               nfs_worker_data_t *pworker,
               struct svc_req *preq,
               nfs_res_t *pres)
{
  char *str_file_name = NULL;
  fsal_name_t file_name;
  fsal_accessmode_t mode = 0;
  cache_entry_t *file_pentry = NULL;
  cache_entry_t *parent_pentry = NULL;
  fsal_attrib_list_t parent_attr;
  fsal_attrib_list_t attr;
  fsal_attrib_list_t attr_parent_after;
  fsal_attrib_list_t attr_newfile;
  fsal_attrib_list_t attributes_create;
  fsal_attrib_list_t *ppre_attr;
  cache_inode_status_t cache_status = CACHE_INODE_SUCCESS;
  cache_inode_status_t cache_status_lookup;
  cache_inode_file_type_t parent_filetype;
  int rc = NFS_REQ_OK;
#ifdef _USE_QUOTA
  fsal_status_t fsal_status ;
#endif

  if(isDebug(COMPONENT_NFSPROTO))
    {
      char str[LEN_FH_STR];

      switch (preq->rq_vers)
        {
        case NFS_V2:
          str_file_name = parg->arg_create2.where.name;
          break;
        case NFS_V3:
          str_file_name = parg->arg_create3.where.name;
          break;
        }

      nfs_FhandleToStr(preq->rq_vers,
                       &(parg->arg_create2.where.dir),
                       &(parg->arg_create3.where.dir),
                       NULL,
                       str);
      LogDebug(COMPONENT_NFSPROTO,
               "REQUEST PROCESSING: Calling nfs_Create handle: %s name: %s",
               str, str_file_name);
    }

  if((preq->rq_vers == NFS_V3) && (nfs3_Is_Fh_Xattr(&(parg->arg_create3.where.dir))))
    {
      rc = nfs3_Create_Xattr(parg, pexport, pcontext, preq, pres);
      goto out;
    }

  if(preq->rq_vers == NFS_V3)
    {
      /* to avoid setting it on each error case */
      pres->res_create3.CREATE3res_u.resfail.dir_wcc.before.attributes_follow = FALSE;
      pres->res_create3.CREATE3res_u.resfail.dir_wcc.after.attributes_follow = FALSE;
      ppre_attr = NULL;
    }

  if((parent_pentry = nfs_FhandleToCache(preq->rq_vers,
                                         &(parg->arg_create2.where.dir),
                                         &(parg->arg_create3.where.dir),
                                         NULL,
                                         &(pres->res_dirop2.status),
                                         &(pres->res_create3.status),
                                         NULL,
                                         &parent_attr,
                                         pcontext, &rc)) == NULL)
    {
      /* Stale NFS FH ? */
      goto out;
    }

  /* get directory attributes before action (for V3 reply) */
  ppre_attr = &parent_attr;

  /* Extract the filetype */
  parent_filetype = cache_inode_fsal_type_convert(parent_attr.type);

  /*
   * Sanity checks: new file name must be non-null; parent must be a
   * directory. 
   */
  if(parent_filetype != DIRECTORY)
    {
      switch (preq->rq_vers)
        {
        case NFS_V2:
          pres->res_dirop2.status = NFSERR_NOTDIR;
          break;

        case NFS_V3:
          pres->res_create3.status = NFS3ERR_NOTDIR;
          break;
        }

      rc = NFS_REQ_OK;
      goto out;
    }

  switch (preq->rq_vers)
    {
    case NFS_V2:
      str_file_name = parg->arg_create2.where.name;

      if(parg->arg_create2.attributes.mode != (unsigned int)-1)
        {
          mode = unix2fsal_mode(parg->arg_create2.attributes.mode);
        }
      else
        {
          mode = 0;
        }

      break;

    case NFS_V3:
      str_file_name = parg->arg_create3.where.name;
      if(parg->arg_create3.how.mode == EXCLUSIVE)
        {
          /*
           * Client has not provided mode information.
           * If the create works, the client will issue
           * a separate setattr request to fix up the
           * file's mode, so pick arbitrary value for now.
           */

          mode = 0;
        }
      else if(parg->arg_create3.how.createhow3_u.obj_attributes.mode.set_it == TRUE)
        mode =
            unix2fsal_mode(parg->arg_create3.how.createhow3_u.obj_attributes.mode.
                           set_mode3_u.mode);
      else
        mode = 0;
      break;
    }

#ifdef _USE_QUOTA
    /* if quota support is active, then we should check is the FSAL allows inode creation or not */
    fsal_status = FSAL_check_quota( pexport->fullpath, 
                                    FSAL_QUOTA_INODES,
                                    FSAL_OP_CONTEXT_TO_UID( pcontext ) ) ;
    if( FSAL_IS_ERROR( fsal_status ) )
     {

       switch (preq->rq_vers)
         {
           case NFS_V2:
             pres->res_dirop2.status = NFSERR_DQUOT ;
             break;

           case NFS_V3:
             pres->res_create3.status = NFS3ERR_DQUOT;
             break;
         }

       rc = NFS_REQ_OK ;
       goto out;
     }
#endif /* _USE_QUOTA */

  // if(str_file_name == NULL || strlen(str_file_name) == 0)
  if(str_file_name == NULL || *str_file_name == '\0' )
    {
      if(preq->rq_vers == NFS_V2)
        pres->res_dirop2.status = NFSERR_IO;
      if(preq->rq_vers == NFS_V3)
        pres->res_create3.status = NFS3ERR_INVAL;
    }
  else
    {
      if((cache_status = cache_inode_error_convert(FSAL_str2name(str_file_name,
                                                                 FSAL_MAX_NAME_LEN,
                                                                 &file_name))) ==
         CACHE_INODE_SUCCESS)
        {
          /*
           * Lookup file to see if it exists.  If so, use it.  Otherwise
           * create a new one.
           */
          file_pentry = cache_inode_lookup(parent_pentry,
                                           &file_name,
                                           &attr,
                                           pcontext,
                                           &cache_status_lookup);

          if((cache_status_lookup == CACHE_INODE_NOT_FOUND) ||
             ((cache_status_lookup == CACHE_INODE_SUCCESS)
              && (parg->arg_create3.how.mode == UNCHECKED)))
            {
              /* Create the file */
              if((parg->arg_create3.how.mode == UNCHECKED)
                 && (cache_status_lookup == CACHE_INODE_SUCCESS))
                {
                  cache_status = CACHE_INODE_SUCCESS;
                  attr_newfile = attr;
                }
              else
                file_pentry = cache_inode_create(parent_pentry,
                                                 &file_name,
                                                 REGULAR_FILE,
                                                 mode,
                                                 NULL,
                                                 &attr_newfile,
                                                 pcontext, &cache_status);

              if(file_pentry != NULL)
                {
                  /*
                   * Look at sattr to see if some attributes are to be set at creation time 
                   */
                  attributes_create.asked_attributes = 0ULL;

                  switch (preq->rq_vers)
                    {
                    case NFS_V2:

                      if(nfs2_Sattr_To_FSALattr(&attributes_create,
                                                &parg->arg_create2.attributes) == 0)
                        {
                          pres->res_dirop2.status = NFSERR_IO;
                          rc = NFS_REQ_OK;
                          goto out;
                          break;
                        }
                      break;

                    case NFS_V3:

                      if(nfs3_Sattr_To_FSALattr(&attributes_create,
                                                &parg->arg_create3.how.createhow3_u.
                                                obj_attributes) == 0)
                        {
                          pres->res_create3.status = NFS3ERR_INVAL;
                          rc = NFS_REQ_OK;
                          goto out;
                        }
                      break;
                    }

                  /* Mode is managed above (in cache_inode_create), there is no need 
                   * to manage it */
                  if(attributes_create.asked_attributes & FSAL_ATTR_MODE)
                    attributes_create.asked_attributes &= ~FSAL_ATTR_MODE;

                  /* Some clients (like Solaris 10) try to set the size of the file to 0
                   * at creation time. The FSAL create empty file, so we ignore this */
                  if(attributes_create.asked_attributes & FSAL_ATTR_SIZE)
                    attributes_create.asked_attributes &= ~FSAL_ATTR_SIZE;

                  if(attributes_create.asked_attributes & FSAL_ATTR_SPACEUSED)
                    attributes_create.asked_attributes &= ~FSAL_ATTR_SPACEUSED;

                  /* Are there attributes to be set (additional to the mode) ? */
                  if(attributes_create.asked_attributes != 0ULL &&
                     attributes_create.asked_attributes != FSAL_ATTR_MODE)
                    {
                      /* A call to cache_inode_setattr is required */
                      if(cache_inode_setattr(file_pentry,
                                             &attributes_create,
                                             pcontext,
                                             &cache_status) != CACHE_INODE_SUCCESS)
                        {
                          /* If we are here, there was an error */
                          nfs_SetFailedStatus(pcontext, pexport,
                                              preq->rq_vers,
                                              cache_status,
                                              &pres->res_dirop2.status,
                                              &pres->res_create3.status,
                                              NULL, NULL,
                                              parent_pentry,
                                              ppre_attr,
                                              &(pres->res_create3.CREATE3res_u.resfail.
                                                dir_wcc), NULL, NULL, NULL);

                          if(nfs_RetryableError(cache_status)) {
                              rc = NFS_REQ_DROP;
                              goto out;
                          }

                          rc = NFS_REQ_OK;
                          goto out;
                        }

                      /* Get the resulting attributes from the Cache Inode */
                      if(cache_inode_getattr(file_pentry,
                                             &attr_newfile,
                                             pcontext,
                                             &cache_status) != CACHE_INODE_SUCCESS)
                        {
                          /* If we are here, there was an error */

                          nfs_SetFailedStatus(pcontext, pexport,
                                              preq->rq_vers,
                                              cache_status,
                                              &pres->res_dirop2.status,
                                              &pres->res_create3.status,
                                              NULL, NULL,
                                              parent_pentry,
                                              ppre_attr,
                                              &(pres->res_create3.CREATE3res_u.resfail.
                                                dir_wcc), NULL, NULL, NULL);

                          if(nfs_RetryableError(cache_status)) {
                            rc = NFS_REQ_DROP;
                            goto out;
                          }

                          rc = NFS_REQ_OK;
                          goto out;
                        }

                    }

                  switch (preq->rq_vers)
                    {
                    case NFS_V2:
                      /* Build file handle */
                      if(nfs2_FSALToFhandle(
                              &(pres->res_dirop2.DIROP2res_u.diropok.file),
                              &file_pentry->handle,
                              pexport) == 0)
                        pres->res_dirop2.status = NFSERR_IO;
                      else
                        {
                          if(!nfs2_FSALattr_To_Fattr(
                                  pexport, &attr_newfile,
                                  &(pres->res_dirop2.DIROP2res_u.
                                    diropok.attributes)))
                            pres->res_dirop2.status = NFSERR_IO;
                          else
                            pres->res_dirop2.status = NFS_OK;
                        }
                      break;

                    case NFS_V3:
                      /* Build file handle */
                      pres->res_create3.status =
                        nfs3_AllocateFH(&pres->res_create3.CREATE3res_u
                                        .resok.obj.post_op_fh3_u.handle);
                      if (pres->res_create3.status != NFS3_OK)
                        {
                          rc = NFS_REQ_OK;
                          goto out;
                        }

                      /* Set Post Op Fh3 structure */
                      if(nfs3_FSALToFhandle(
                              &(pres->res_create3.CREATE3res_u.resok
                                .obj.post_op_fh3_u.handle),
                              &file_pentry->handle, pexport) == 0)
                        {
                          gsh_free(pres->res_create3.CREATE3res_u.resok.obj.
                                   post_op_fh3_u.handle.data.data_val);

                          pres->res_create3.status = NFS3ERR_BADHANDLE;
                          rc = NFS_REQ_OK;
                          goto out;
                        }

                      /* Set Post Op Fh3 structure */
                      pres->res_create3.CREATE3res_u.resok.obj.handle_follows
                        = TRUE;

                      /* Get the attributes of the parent after the
                         operation */
                      attr_parent_after = parent_pentry->attributes;

                      /* Build entry attributes */
                      nfs_SetPostOpAttr(pexport,
                                        &attr_newfile,
                                        &(pres->res_create3.CREATE3res_u.resok.
                                          obj_attributes));

                      /*
                       * Build Weak Cache Coherency data
                       */
                      nfs_SetWccData(pexport,
                                     ppre_attr,
                                     &attr_parent_after,
                                     &(pres->res_create3.CREATE3res_u
                                       .resok.dir_wcc));

                      pres->res_create3.status = NFS3_OK;
                      break;
                    }       /* switch */
                  rc = NFS_REQ_OK;
                  goto out;
                }
            }
          else
            {
              if(cache_status_lookup == CACHE_INODE_SUCCESS)
                {
                  /* Trying to create a file that already exists */
                  cache_status = CACHE_INODE_ENTRY_EXISTS;

                  switch (preq->rq_vers)
                    {
                    case NFS_V2:
                      pres->res_dirop2.status = NFSERR_EXIST;
                      break;

                    case NFS_V3:
                      pres->res_create3.status = NFS3ERR_EXIST;
                      break;
                    }
                }
              else
                {
                  /* Server fault */
                  cache_status = cache_status_lookup;

                  switch (preq->rq_vers)
                    {
                    case NFS_V2:
                      pres->res_dirop2.status = NFSERR_IO;
                      break;

                    case NFS_V3:
                      pres->res_create3.status = NFS3ERR_INVAL;
                      break;
                    }
                }

              nfs_SetFailedStatus(pcontext, pexport,
                                  preq->rq_vers,
                                  cache_status,
                                  &pres->res_dirop2.status,
                                  &pres->res_create3.status,
                                  NULL, NULL,
                                  parent_pentry,
                                  ppre_attr,
                                  &(pres->res_create3.CREATE3res_u.resfail.dir_wcc),
                                  NULL, NULL, NULL);

              rc = NFS_REQ_OK;
              goto out;
            } /* if( cache_status_lookup == CACHE_INODE_NOT_FOUND ) */
        }
    }

  /* Set the exit status */
  nfs_SetFailedStatus(pcontext, pexport,
                      preq->rq_vers,
                      cache_status,
                      &pres->res_dirop2.status,
                      &pres->res_create3.status,
                      NULL, NULL,
                      parent_pentry,
                      ppre_attr,
                      &(pres->res_create3.CREATE3res_u.resfail.dir_wcc),
                      NULL, NULL, NULL);

  /* If we are here, there was an error */
  if(nfs_RetryableError(cache_status))
    {
      rc = NFS_REQ_DROP;
      goto out;
    }

  rc = NFS_REQ_OK;

out:
  /* return references */
  if (file_pentry)
      cache_inode_put(file_pentry);

  if (parent_pentry)
      cache_inode_put(parent_pentry);

  return (rc);

}                               /* nfs_Create */
Пример #4
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;
}
Пример #5
0
int nfs_Mkdir(nfs_arg_t *parg,
              exportlist_t *pexport,
              fsal_op_context_t *pcontext,
              nfs_worker_data_t *pworker,
              struct svc_req *preq,
              nfs_res_t *pres)
{
  char *str_dir_name = NULL;
  fsal_accessmode_t mode = 0;
  cache_entry_t *dir_pentry = NULL;
  cache_entry_t *parent_pentry = NULL;
  fsal_attrib_list_t parent_attr;
  fsal_attrib_list_t attr;
  fsal_attrib_list_t *ppre_attr;
  fsal_attrib_list_t attr_parent_after;
  cache_inode_file_type_t parent_filetype;
  fsal_handle_t *pfsal_handle;
  fsal_name_t dir_name;
  cache_inode_status_t cache_status = CACHE_INODE_SUCCESS;
  cache_inode_status_t cache_status_lookup;
  cache_inode_create_arg_t create_arg;
  int rc = NFS_REQ_OK;
#ifdef _USE_QUOTA
  fsal_status_t fsal_status ;
#endif

  memset(&create_arg, 0, sizeof(create_arg));

  if(isDebug(COMPONENT_NFSPROTO))
    {
      char str[LEN_FH_STR];

      switch (preq->rq_vers)
        {
        case NFS_V2:
          str_dir_name = parg->arg_mkdir2.where.name;
          break;
        case NFS_V3:
          str_dir_name = parg->arg_mkdir3.where.name;
          break;
        }

      nfs_FhandleToStr(preq->rq_vers,
                       &(parg->arg_mkdir2.where.dir),
                       &(parg->arg_mkdir3.where.dir),
                       NULL,
                       str);
      LogDebug(COMPONENT_NFSPROTO,
               "REQUEST PROCESSING: Calling nfs_Mkdir handle: %s name: %s",
               str, str_dir_name);
    }

  if(preq->rq_vers == NFS_V3)
    {
      /* to avoid setting it on each error case */
      pres->res_mkdir3.MKDIR3res_u.resfail.dir_wcc.before.attributes_follow = FALSE;
      pres->res_mkdir3.MKDIR3res_u.resfail.dir_wcc.after.attributes_follow = FALSE;
      ppre_attr = NULL;
    }

  if((parent_pentry = nfs_FhandleToCache(preq->rq_vers,
                                         &(parg->arg_mkdir2.where.dir),
                                         &(parg->arg_mkdir3.where.dir),
                                         NULL,
                                         &(pres->res_dirop2.status),
                                         &(pres->res_mkdir3.status),
                                         NULL,
                                         &parent_attr,
                                         pcontext, &rc)) == NULL)
    {
      /* Stale NFS FH ? */
      goto out;
    }

  /* get directory attributes before action (for V3 reply) */
  ppre_attr = &parent_attr;

  /* Extract the filetype */
  parent_filetype = cache_inode_fsal_type_convert(parent_attr.type);

  /*
   * Sanity checks: 
   */
  if(parent_filetype != DIRECTORY)
    {
      switch (preq->rq_vers)
        {
        case NFS_V2:
          pres->res_dirop2.status = NFSERR_NOTDIR;
          break;

        case NFS_V3:
          pres->res_mkdir3.status = NFS3ERR_NOTDIR;
          break;
        }

      rc = NFS_REQ_OK;
      goto out;
    }


#ifdef _USE_QUOTA
    /* if quota support is active, then we should check is the FSAL allows inode creation or not */
    fsal_status = FSAL_check_quota( pexport->fullpath, 
                                    FSAL_QUOTA_INODES,
                                    FSAL_OP_CONTEXT_TO_UID( pcontext ) ) ;
    if( FSAL_IS_ERROR( fsal_status ) )
     {

       switch (preq->rq_vers)
         {
           case NFS_V2:
             pres->res_dirop2.status = NFSERR_DQUOT;
             break;

           case NFS_V3:
             pres->res_mkdir3.status = NFS3ERR_DQUOT;
             break;
         }

       rc = NFS_REQ_OK ;
       goto out;
     }
#endif /* _USE_QUOTA */


  switch (preq->rq_vers)
    {
    case NFS_V2:
      str_dir_name = parg->arg_mkdir2.where.name;

      if(parg->arg_mkdir2.attributes.mode != (unsigned int)-1)
        {
          mode = (fsal_accessmode_t) parg->arg_mkdir2.attributes.mode;
        }
      else
        {
          mode = (fsal_accessmode_t) 0;
        }
      break;

    case NFS_V3:
      str_dir_name = parg->arg_mkdir3.where.name;

      if(parg->arg_mkdir3.attributes.mode.set_it == TRUE)
        mode = (fsal_accessmode_t) parg->arg_mkdir3.attributes.mode.set_mode3_u.mode;
      else
        mode = (fsal_accessmode_t) 0;
      break;
    }

  //if(str_dir_name == NULL || strlen(str_dir_name) == 0)
  if(str_dir_name == NULL || *str_dir_name == '\0' )
    {
      if(preq->rq_vers == NFS_V2)
        pres->res_dirop2.status = NFSERR_IO;
      if(preq->rq_vers == NFS_V3)
        pres->res_mkdir3.status = NFS3ERR_INVAL;
    }
  else
    {
      /* Make the directory */
      if((cache_status = cache_inode_error_convert(FSAL_str2name(str_dir_name,
                                                                 0,
                                                                 &dir_name))) ==
         CACHE_INODE_SUCCESS)
        {
          /*
           * Lookup file to see if it exists.  If so, use it.  Otherwise
           * create a new one.
           */
          dir_pentry = cache_inode_lookup(parent_pentry,
                                          &dir_name,
                                          &attr,
                                          pcontext,
                                          &cache_status_lookup);

          if(cache_status_lookup == CACHE_INODE_NOT_FOUND)
            {
              /* The create_arg structure contains the information "newly created directory"
               * to be passed to cache_inode_new_entry from cache_inode_create */
              create_arg.newly_created_dir = TRUE;

              /* Create the directory */
              if((dir_pentry = cache_inode_create(parent_pentry,
                                                  &dir_name,
                                                  DIRECTORY,
                                                  mode,
                                                  &create_arg,
                                                  &attr,
                                                  pcontext, &cache_status)) != NULL)
                {
                  /*
                   * Get the FSAL handle for this entry
                   */
                  pfsal_handle = &dir_pentry->handle;

                  if(preq->rq_vers == NFS_V2)
                    {
                      DIROP2resok *d2ok = &pres->res_dirop2.DIROP2res_u.diropok;

                      /* Build file handle */
                      if(!nfs2_FSALToFhandle(&d2ok->file, pfsal_handle, pexport))
                        pres->res_dirop2.status = NFSERR_IO;
                      else
                        {
                          /*
                           * Build entry
                           * attributes
                           */
                          if(nfs2_FSALattr_To_Fattr(pexport, &attr,
                                                    &d2ok->attributes) == 0)
                            pres->res_dirop2.status = NFSERR_IO;
                          else
                            pres->res_dirop2.status = NFS_OK;
                        }
                    }
                  else
                    {
                      MKDIR3resok *d3ok = &pres->res_mkdir3.MKDIR3res_u.resok;

                      /* Build file handle */
                      pres->res_mkdir3.status =
                          nfs3_AllocateFH(&d3ok->obj.post_op_fh3_u.handle);
                      if(pres->res_mkdir3.status !=  NFS3_OK)
                        {
                          rc = NFS_REQ_OK;
                          goto out;
                        }

                      if(nfs3_FSALToFhandle(&d3ok->obj.post_op_fh3_u.handle,
                                            pfsal_handle, pexport) == 0)
                        {
                          gsh_free(d3ok->obj.post_op_fh3_u.handle.data.data_val);
                          pres->res_mkdir3.status = NFS3ERR_INVAL;
                          rc = NFS_REQ_OK;
                          goto out;
                        }

                      /* Set Post Op Fh3 structure */
                      d3ok->obj.handle_follows = TRUE;

                      /*
                       * Build entry attributes 
                       */
                      nfs_SetPostOpAttr(pexport, &attr, &d3ok->obj_attributes);

                      /* Get the attributes of the parent after the operation */
                      if(cache_inode_getattr(parent_pentry,
                                             &attr_parent_after,
                                             pcontext, &cache_status) != CACHE_INODE_SUCCESS)
                        {
                          pres->res_mkdir3.status = nfs3_Errno(cache_status);
                          rc = NFS_REQ_OK;
                          goto out;
                        }


                      /*
                       * Build Weak Cache Coherency data 
                       */
                      nfs_SetWccData(pexport, ppre_attr, &attr_parent_after,
                                     &d3ok->dir_wcc);

                      pres->res_mkdir3.status = NFS3_OK;
                    }
                  rc = NFS_REQ_OK;
                  goto out;
                }
            }                   /* If( cache_status_lookup == CACHE_INODE_NOT_FOUND ) */
          else
            {
              switch (preq->rq_vers)
                {
                case NFS_V2:
                  if(cache_status_lookup == CACHE_INODE_SUCCESS)
                      pres->res_dirop2.status = NFSERR_EXIST;
                  else
                     pres->res_dirop2.status = NFSERR_IO;
                  break;

                case NFS_V3:
                  if(cache_status_lookup == CACHE_INODE_SUCCESS)
                      pres->res_mkdir3.status = NFS3ERR_EXIST;
                  else
                      pres->res_mkdir3.status = NFS3ERR_INVAL;
                  nfs_SetWccData(pexport, ppre_attr, NULL,
                                 &(pres->res_mkdir3.MKDIR3res_u.resfail.dir_wcc));
                  break;
                }
              rc = NFS_REQ_OK;
              goto out;
            }
        }
    }

  /* If we are here, there was an error */
  rc = nfs_SetFailedStatus(pexport, preq->rq_vers, cache_status,
                           &pres->res_dirop2.status, &pres->res_mkdir3.status,
                           NULL, ppre_attr,
                           &(pres->res_mkdir3.MKDIR3res_u.resfail.dir_wcc),
                           NULL, NULL);
out:
  /* return references */
  if (dir_pentry)
      cache_inode_put(dir_pentry);

  if (parent_pentry)
      cache_inode_put(parent_pentry);

  return (rc);
}
Пример #6
0
int nfs3_Mknod(nfs_arg_t *parg,
               exportlist_t *pexport,
               fsal_op_context_t *pcontext,
               nfs_worker_data_t *pworker,
               struct svc_req *preq,
               nfs_res_t * pres)
{
  cache_entry_t *parent_pentry = NULL;
  fsal_attrib_list_t parent_attr;
  fsal_attrib_list_t *ppre_attr;
  fsal_attrib_list_t attr_parent_after;
  cache_inode_file_type_t parent_filetype;
  cache_inode_file_type_t nodetype;
  char *str_file_name = NULL;
  fsal_name_t file_name;
  cache_inode_status_t cache_status;
  cache_inode_status_t cache_status_lookup;
  fsal_accessmode_t mode = 0;
  cache_entry_t *node_pentry = NULL;
  fsal_attrib_list_t attr;
  cache_inode_create_arg_t create_arg;
  fsal_handle_t *pfsal_handle;
  int rc = NFS_REQ_OK;

#ifdef _USE_QUOTA
  fsal_status_t fsal_status ;
#endif

  memset(&create_arg, 0, sizeof(create_arg));
  if(isDebug(COMPONENT_NFSPROTO))
    {
      char str[LEN_FH_STR];
      sprint_fhandle3(str, &(parg->arg_mknod3.where.dir));
      LogDebug(COMPONENT_NFSPROTO,
               "REQUEST PROCESSING: Calling nfs3_Mknod handle: %s name: %s",
               str, parg->arg_mknod3.where.name);
    }

  /* to avoid setting them on each error case */

  pres->res_mknod3.MKNOD3res_u.resfail.dir_wcc.before.attributes_follow = FALSE;
  pres->res_mknod3.MKNOD3res_u.resfail.dir_wcc.after.attributes_follow = FALSE;
  ppre_attr = NULL;

  /* retrieve parent entry */

  if((parent_pentry = nfs_FhandleToCache(preq->rq_vers,
                                         NULL,
                                         &(parg->arg_mknod3.where.dir),
                                         NULL,
                                         NULL,
                                         &(pres->res_mknod3.status),
                                         NULL,
                                         &parent_attr,
                                         pcontext, &rc)) == NULL)
    {
      /* Stale NFS FH ? */
      return rc;
    }

  /* get directory attributes before action (for V3 reply) */
  ppre_attr = &parent_attr;

  /* Extract the filetype */
  parent_filetype = cache_inode_fsal_type_convert(parent_attr.type);

  /*
   * Sanity checks: new node name must be non-null; parent must be a
   * directory. 
   */
  if(parent_filetype != DIRECTORY)
    {
      pres->res_mknod3.status = NFS3ERR_NOTDIR;
      rc = NFS_REQ_OK;
      goto out;
    }

  str_file_name = parg->arg_mknod3.where.name;

  switch (parg->arg_mknod3.what.type)
    {
    case NF3CHR:
    case NF3BLK:

      if(parg->arg_mknod3.what.mknoddata3_u.device.dev_attributes.mode.set_it)
        mode =
            (fsal_accessmode_t) parg->arg_mknod3.what.mknoddata3_u.device.dev_attributes.
            mode.set_mode3_u.mode;
      else
        mode = (fsal_accessmode_t) 0;

      create_arg.dev_spec.major =
          parg->arg_mknod3.what.mknoddata3_u.device.spec.specdata1;
      create_arg.dev_spec.minor =
          parg->arg_mknod3.what.mknoddata3_u.device.spec.specdata2;

      break;

    case NF3FIFO:
    case NF3SOCK:

      if(parg->arg_mknod3.what.mknoddata3_u.pipe_attributes.mode.set_it)
        mode =
            (fsal_accessmode_t) parg->arg_mknod3.what.mknoddata3_u.pipe_attributes.mode.
            set_mode3_u.mode;
      else
        mode = (fsal_accessmode_t) 0;

      create_arg.dev_spec.major = 0;
      create_arg.dev_spec.minor = 0;

      break;

    default:
      pres->res_mknod3.status = NFS3ERR_BADTYPE;
      rc = NFS_REQ_OK;
      goto out;
    }

  switch (parg->arg_mknod3.what.type)
    {
    case NF3CHR:
      nodetype = CHARACTER_FILE;
      break;
    case NF3BLK:
      nodetype = BLOCK_FILE;
      break;
    case NF3FIFO:
      nodetype = FIFO_FILE;
      break;
    case NF3SOCK:
      nodetype = SOCKET_FILE;
      break;
    default:
      pres->res_mknod3.status = NFS3ERR_BADTYPE;
      rc = NFS_REQ_OK;
      goto out;
    }

  //if(str_file_name == NULL || strlen(str_file_name) == 0)
  if(str_file_name == NULL || *str_file_name == '\0' )
    {
      pres->res_mknod3.status = NFS3ERR_INVAL;
      rc = NFS_REQ_OK;
      goto out;
    }

#ifdef _USE_QUOTA
    /* if quota support is active, then we should check is the FSAL allows inode creation or not */
    fsal_status = FSAL_check_quota( pexport->fullpath, 
                                    FSAL_QUOTA_INODES,
                                    FSAL_OP_CONTEXT_TO_UID( pcontext ) ) ;
    if( FSAL_IS_ERROR( fsal_status ) )
     {
        pres->res_mknod3.status = NFS3ERR_DQUOT;
       return NFS_REQ_OK;
     }
#endif /* _USE_QUOTA */


  /* convert node name */

  if((cache_status = cache_inode_error_convert(FSAL_str2name(str_file_name,
                                                             0,
                                                             &file_name))) ==
     CACHE_INODE_SUCCESS)
    {
      /*
       * Lookup node to see if it exists.  If so, use it.  Otherwise
       * create a new one.
       */
      node_pentry = cache_inode_lookup(parent_pentry,
                                       &file_name,
                                       &attr,
                                       pcontext,
                                       &cache_status_lookup);

      if(cache_status_lookup == CACHE_INODE_NOT_FOUND)
        {

          /* Create the node */

          if((node_pentry = cache_inode_create(parent_pentry,
                                               &file_name,
                                               nodetype,
                                               mode,
                                               &create_arg,
                                               &attr,
                                               pcontext,
                                               &cache_status)) != NULL)
            {
              MKNOD3resok *rok = &pres->res_mknod3.MKNOD3res_u.resok;
              /*
               * Get the FSAL handle for this entry
               */
              pfsal_handle = &node_pentry->handle;

              /* Build file handle */
              pres->res_mknod3.status =
                    nfs3_AllocateFH(&rok->obj.post_op_fh3_u.handle);
              if(pres->res_mknod3.status !=  NFS3_OK)
                return NFS_REQ_OK;

              if(nfs3_FSALToFhandle(&rok->obj.post_op_fh3_u.handle,
                                    pfsal_handle, pexport) == 0)
                {
                  gsh_free(rok->obj.post_op_fh3_u.handle.data.data_val);
                  pres->res_mknod3.status = NFS3ERR_INVAL;
                  rc = NFS_REQ_OK;
                  goto out;
                }

              /* Set Post Op Fh3 structure */
              rok->obj.handle_follows = TRUE;

              /* Build entry attributes */
              nfs_SetPostOpAttr(pexport, &attr, &rok->obj_attributes);

              /* Get the attributes of the parent after the operation */
              if(cache_inode_getattr(parent_pentry,
                         &attr_parent_after,
                         pcontext, &cache_status) != CACHE_INODE_SUCCESS)
                {
                  pres->res_mknod3.status = nfs3_Errno(cache_status);
                  rc = NFS_REQ_OK;
                  goto out;
                }


              /* Build Weak Cache Coherency data */
              nfs_SetWccData(pexport, ppre_attr, &attr_parent_after,
                             &rok->dir_wcc);

              pres->res_mknod3.status = NFS3_OK;

              rc = NFS_REQ_OK;
              goto out;
            }
          /* mknod sucess */
        }                       /* not found */
      else
        {
          /* object already exists or failure during lookup */
          if(cache_status_lookup == CACHE_INODE_SUCCESS)
            {
              /* Trying to create an entry that already exists */
              pres->res_mknod3.status = NFS3ERR_EXIST;
            }
          else
            {
              /* Server fault */
              pres->res_mknod3.status = NFS3ERR_INVAL;
            }

          nfs_SetWccData(pexport, NULL, NULL, 
                         &(pres->res_mknod3.MKNOD3res_u.resfail.dir_wcc));
          rc = NFS_REQ_OK;
          goto out;
        }
    }

  /* If we are here, there was an error */
  rc = nfs_SetFailedStatus(pexport, preq->rq_vers, cache_status, NULL,
                           &pres->res_mknod3.status, NULL, ppre_attr,
                           &(pres->res_mknod3.MKNOD3res_u.resfail.dir_wcc),
                           NULL, NULL);

out:
  /* return references */
  if (parent_pentry)
      cache_inode_put(parent_pentry);

  if (node_pentry)
      cache_inode_put(node_pentry);

  return (rc);

}                               /* nfs3_Mknod */
Пример #7
0
int nfs4_op_create(struct nfs_argop4 *op, compound_data_t * data, struct nfs_resop4 *resp)
{
  cache_entry_t *pentry_parent = NULL;
  cache_entry_t *pentry_new = NULL;

  fsal_attrib_list_t attr_parent;
  fsal_attrib_list_t attr_new;
  fsal_attrib_list_t sattr;

  fsal_handle_t *pnewfsal_handle = NULL;

  nfs_fh4 newfh4;
  cache_inode_status_t cache_status;
  int convrc = 0;

  fsal_accessmode_t mode = 0600;
  fsal_name_t name;

  cache_inode_create_arg_t create_arg;

  char __attribute__ ((__unused__)) funcname[] = "nfs4_op_create";
  unsigned int i = 0;

  resp->resop = NFS4_OP_CREATE;
  res_CREATE4.status = NFS4_OK;

  /* If the filehandle is Empty */
  if(nfs4_Is_Fh_Empty(&(data->currentFH)))
    {
      res_CREATE4.status = NFS4ERR_NOFILEHANDLE;
      return res_CREATE4.status;
    }

  /* If the filehandle is invalid */
  if(nfs4_Is_Fh_Invalid(&(data->currentFH)))
    {
      res_CREATE4.status = NFS4ERR_BADHANDLE;
      return res_CREATE4.status;
    }

  /* Tests if the Filehandle is expired (for volatile filehandle) */
  if(nfs4_Is_Fh_Expired(&(data->currentFH)))
    {
      res_CREATE4.status = NFS4ERR_FHEXPIRED;
      return res_CREATE4.status;
    }

  /* Pseudo Fs is explictely a Read-Only File system */
  if(nfs4_Is_Fh_Pseudo(&(data->currentFH)))
    {
      res_CREATE4.status = NFS4ERR_ROFS;
      return res_CREATE4.status;
    }

  /* Ask only for supported attributes */
  if(!nfs4_Fattr_Supported(&arg_CREATE4.createattrs))
    {
      res_CREATE4.status = NFS4ERR_ATTRNOTSUPP;
      return res_CREATE4.status;
    }

  /* Do not use READ attr, use WRITE attr */
  if(!nfs4_Fattr_Check_Access(&arg_CREATE4.createattrs, FATTR4_ATTR_WRITE))
    {
      res_CREATE4.status = NFS4ERR_INVAL;
      return res_CREATE4.status;
    }

  /* Check for name to long */
  if(arg_CREATE4.objname.utf8string_len > FSAL_MAX_NAME_LEN)
    {
      res_CREATE4.status = NFS4ERR_NAMETOOLONG;
      return res_CREATE4.status;
    }

  /* 
   * This operation is used to create a non-regular file, 
   * this means: - a symbolic link
   *             - a block device file
   *             - a character device file
   *             - a socket file
   *             - a fifo
   *             - a directory 
   *
   * You can't use this operation to create a regular file, you have to use NFS4_OP_OPEN for this
   */

  /* Convert the UFT8 objname to a regular string */
  if(arg_CREATE4.objname.utf8string_len == 0)
    {
      res_CREATE4.status = NFS4ERR_INVAL;
      return res_CREATE4.status;
    }

  if(utf82str(name.name, &arg_CREATE4.objname) == -1)
    {
      res_CREATE4.status = NFS4ERR_INVAL;
      return res_CREATE4.status;
    }
  name.len = strlen(name.name);

  /* Sanuty check: never create a directory named '.' or '..' */
  if(arg_CREATE4.objtype.type == NF4DIR)
    {
      if(!FSAL_namecmp(&name, (fsal_name_t *) & FSAL_DOT)
         || !FSAL_namecmp(&name, (fsal_name_t *) & FSAL_DOT_DOT))
        {
          res_CREATE4.status = NFS4ERR_BADNAME;
          return res_CREATE4.status;
        }

    }

  /* Filename should contain not slash */
  for(i = 0; i < name.len; i++)
    {
      if(name.name[i] == '/')
        {
          res_CREATE4.status = NFS4ERR_BADCHAR;
          return res_CREATE4.status;
        }
    }
  /* Convert current FH into a cached entry, the current_pentry (assocated with the current FH will be used for this */
  pentry_parent = data->current_entry;

  /* The currentFH must point to a directory (objects are always created within a directory) */
  if(data->current_filetype != DIR_BEGINNING && data->current_filetype != DIR_CONTINUE)
    {
      res_CREATE4.status = NFS4ERR_NOTDIR;
      return res_CREATE4.status;
    }

  /* get attributes of parent directory, for 'change4' info replyed */
  if((cache_status = cache_inode_getattr(pentry_parent,
                                         &attr_parent,
                                         data->ht,
                                         data->pclient,
                                         data->pcontext,
                                         &cache_status)) != CACHE_INODE_SUCCESS)
    {
      res_CREATE4.status = nfs4_Errno(cache_status);
      return res_CREATE4.status;
    }
  /* Change info for client cache coherency, pentry internal_md is used for that */
  memset(&(res_CREATE4.CREATE4res_u.resok4.cinfo.before), 0, sizeof(changeid4));
  res_CREATE4.CREATE4res_u.resok4.cinfo.before =
      (changeid4) pentry_parent->internal_md.mod_time;

  /* Convert the incoming fattr4 to a vattr structure, if such arguments are supplied */
  if(arg_CREATE4.createattrs.attrmask.bitmap4_len != 0)
    {
      /* Arguments were supplied, extract them */
      convrc = nfs4_Fattr_To_FSAL_attr(&sattr, &(arg_CREATE4.createattrs));

      if(convrc == 0)
        {
          res_CREATE4.status = NFS4ERR_ATTRNOTSUPP;
          return res_CREATE4.status;
        }

      if(convrc == -1)
        {
          res_CREATE4.status = NFS4ERR_BADXDR;
          return res_CREATE4.status;
        }
    }

  /* Create either a symbolic link or a directory */
  switch (arg_CREATE4.objtype.type)
    {
    case NF4LNK:
      /* Convert the name to link from into a regular string */
      if(arg_CREATE4.objtype.createtype4_u.linkdata.utf8string_len == 0)
        {
          res_CREATE4.status = NFS4ERR_INVAL;
          return res_CREATE4.status;
        }
      else
        {
          if(utf82str
             (create_arg.link_content.path,
              &arg_CREATE4.objtype.createtype4_u.linkdata) == -1)
            {
              res_CREATE4.status = NFS4ERR_INVAL;
              return res_CREATE4.status;
            }
          create_arg.link_content.len = strlen(create_arg.link_content.path);
        }

      /* do the symlink operation */
      if((pentry_new = cache_inode_create(pentry_parent,
                                          &name,
                                          SYMBOLIC_LINK,
                                          mode,
                                          &create_arg,
                                          &attr_new,
                                          data->ht,
                                          data->pclient,
                                          data->pcontext, &cache_status)) == NULL)
        {
          res_CREATE4.status = nfs4_Errno(cache_status);
          return res_CREATE4.status;
        }

      /* If entry exists pentry_new is not null but cache_status was set */
      if(cache_status == CACHE_INODE_ENTRY_EXISTS)
        {
          res_CREATE4.status = NFS4ERR_EXIST;
          return res_CREATE4.status;
        }

      break;
    case NF4DIR:
      /* Create a new directory */
      /* do the symlink operation */
      if((pentry_new = cache_inode_create(pentry_parent,
                                          &name,
                                          DIR_BEGINNING,
                                          mode,
                                          &create_arg,
                                          &attr_new,
                                          data->ht,
                                          data->pclient,
                                          data->pcontext, &cache_status)) == NULL)
        {
          res_CREATE4.status = nfs4_Errno(cache_status);
          return res_CREATE4.status;
        }

      /* If entry exists pentry_new is not null but cache_status was set */
      if(cache_status == CACHE_INODE_ENTRY_EXISTS)
        {
          res_CREATE4.status = NFS4ERR_EXIST;
          return res_CREATE4.status;
        }
      break;

    case NF4SOCK:

      /* Create a new socket file */
      if((pentry_new = cache_inode_create(pentry_parent,
                                          &name,
                                          SOCKET_FILE,
                                          mode,
                                          NULL,
                                          &attr_new,
                                          data->ht,
                                          data->pclient,
                                          data->pcontext, &cache_status)) == NULL)
        {
          res_CREATE4.status = nfs4_Errno(cache_status);
          return res_CREATE4.status;
        }

      /* If entry exists pentry_new is not null but cache_status was set */
      if(cache_status == CACHE_INODE_ENTRY_EXISTS)
        {
          res_CREATE4.status = NFS4ERR_EXIST;
          return res_CREATE4.status;
        }
      break;

    case NF4FIFO:

      /* Create a new socket file */
      if((pentry_new = cache_inode_create(pentry_parent,
                                          &name,
                                          FIFO_FILE,
                                          mode,
                                          NULL,
                                          &attr_new,
                                          data->ht,
                                          data->pclient,
                                          data->pcontext, &cache_status)) == NULL)
        {
          res_CREATE4.status = nfs4_Errno(cache_status);
          return res_CREATE4.status;
        }

      /* If entry exists pentry_new is not null but cache_status was set */
      if(cache_status == CACHE_INODE_ENTRY_EXISTS)
        {
          res_CREATE4.status = NFS4ERR_EXIST;
          return res_CREATE4.status;
        }
      break;

    case NF4CHR:

      create_arg.dev_spec.major = arg_CREATE4.objtype.createtype4_u.devdata.specdata1;
      create_arg.dev_spec.minor = arg_CREATE4.objtype.createtype4_u.devdata.specdata2;

      /* Create a new socket file */
      if((pentry_new = cache_inode_create(pentry_parent,
                                          &name,
                                          CHARACTER_FILE,
                                          mode,
                                          &create_arg,
                                          &attr_new,
                                          data->ht,
                                          data->pclient,
                                          data->pcontext, &cache_status)) == NULL)
        {
          res_CREATE4.status = nfs4_Errno(cache_status);
          return res_CREATE4.status;
        }

      /* If entry exists pentry_new is not null but cache_status was set */
      if(cache_status == CACHE_INODE_ENTRY_EXISTS)
        {
          res_CREATE4.status = NFS4ERR_EXIST;
          return res_CREATE4.status;
        }
      break;

    case NF4BLK:

      create_arg.dev_spec.major = arg_CREATE4.objtype.createtype4_u.devdata.specdata1;
      create_arg.dev_spec.minor = arg_CREATE4.objtype.createtype4_u.devdata.specdata2;

      /* Create a new socket file */
      if((pentry_new = cache_inode_create(pentry_parent,
                                          &name,
                                          BLOCK_FILE,
                                          mode,
                                          &create_arg,
                                          &attr_new,
                                          data->ht,
                                          data->pclient,
                                          data->pcontext, &cache_status)) == NULL)
        {
          res_CREATE4.status = nfs4_Errno(cache_status);
          return res_CREATE4.status;
        }

      /* If entry exists pentry_new is not null but cache_status was set */
      if(cache_status == CACHE_INODE_ENTRY_EXISTS)
        {
          res_CREATE4.status = NFS4ERR_EXIST;
          return res_CREATE4.status;
        }
      break;

    default:
      /* Should never happen, but return NFS4ERR_BADTYPE in this case */
      res_CREATE4.status = NFS4ERR_BADTYPE;
      return res_CREATE4.status;
      break;
    }                           /* switch( arg_CREATE4.objtype.type ) */

  /* Now produce the filehandle to this file */
  if((pnewfsal_handle = cache_inode_get_fsal_handle(pentry_new, &cache_status)) == NULL)
    {
      res_CREATE4.status = nfs4_Errno(cache_status);
      return res_CREATE4.status;
    }

  /* Allocation of a new file handle */
  if(nfs4_AllocateFH(&newfh4) != NFS4_OK)
    {
      res_CREATE4.status = NFS4ERR_SERVERFAULT;
      return res_CREATE4.status;
    }

  /* Building the new file handle */
  if(!nfs4_FSALToFhandle(&newfh4, pnewfsal_handle, data))
    {
      res_CREATE4.status = NFS4ERR_SERVERFAULT;
      return res_CREATE4.status;
    }

  /* This new fh replaces the current FH */
  data->currentFH.nfs_fh4_len = newfh4.nfs_fh4_len;
  memcpy(data->currentFH.nfs_fh4_val, newfh4.nfs_fh4_val, newfh4.nfs_fh4_len);

  /* No do not need newfh any more */
  Mem_Free((char *)newfh4.nfs_fh4_val);

  /* Set the mode if requested */
  /* Use the same fattr mask for reply, if one attribute was not settable, NFS4ERR_ATTRNOTSUPP was replyied */
  res_CREATE4.CREATE4res_u.resok4.attrset.bitmap4_len =
      arg_CREATE4.createattrs.attrmask.bitmap4_len;

  if(arg_CREATE4.createattrs.attrmask.bitmap4_len != 0)
    {
      if((cache_status = cache_inode_setattr(pentry_new,
                                             &sattr,
                                             data->ht,
                                             data->pclient,
                                             data->pcontext,
                                             &cache_status)) != CACHE_INODE_SUCCESS)

        {
          res_CREATE4.status = nfs4_Errno(cache_status);
          return res_CREATE4.status;
        }

      /* Allocate a new bitmap */
      res_CREATE4.CREATE4res_u.resok4.attrset.bitmap4_val =
          (unsigned int *)Mem_Alloc(res_CREATE4.CREATE4res_u.resok4.attrset.bitmap4_len *
                                    sizeof(u_int));

      if(res_CREATE4.CREATE4res_u.resok4.attrset.bitmap4_val == NULL)
        {
          res_CREATE4.status = NFS4ERR_SERVERFAULT;
          return res_CREATE4.status;
        }
      memset(res_CREATE4.CREATE4res_u.resok4.attrset.bitmap4_val, 0,
             res_CREATE4.CREATE4res_u.resok4.attrset.bitmap4_len);

      memcpy(res_CREATE4.CREATE4res_u.resok4.attrset.bitmap4_val,
             arg_CREATE4.createattrs.attrmask.bitmap4_val,
             res_CREATE4.CREATE4res_u.resok4.attrset.bitmap4_len * sizeof(u_int));
    }

  /* Get the change info on parent directory after the operation was successfull */
  if((cache_status = cache_inode_getattr(pentry_parent,
                                         &attr_parent,
                                         data->ht,
                                         data->pclient,
                                         data->pcontext,
                                         &cache_status)) != CACHE_INODE_SUCCESS)
    {
      res_CREATE4.status = nfs4_Errno(cache_status);
      return res_CREATE4.status;
    }
  memset(&(res_CREATE4.CREATE4res_u.resok4.cinfo.after), 0, sizeof(changeid4));
  res_CREATE4.CREATE4res_u.resok4.cinfo.after =
      (changeid4) pentry_parent->internal_md.mod_time;

  /* Operation is supposed to be atomic .... */
  res_CREATE4.CREATE4res_u.resok4.cinfo.atomic = TRUE;

  LogFullDebug(COMPONENT_NFS_V4, "           CREATE CINFO before = %llu  after = %llu  atomic = %d\n",
         res_CREATE4.CREATE4res_u.resok4.cinfo.before,
         res_CREATE4.CREATE4res_u.resok4.cinfo.after,
         res_CREATE4.CREATE4res_u.resok4.cinfo.atomic);

  /* @todo : BUGAZOMEU: fair ele free dans cette fonction */

  /* Keep the vnode entry for the file in the compound data */
  data->current_entry = pentry_new;
  data->current_filetype = pentry_new->internal_md.type;

  /* If you reach this point, then no error occured */
  res_CREATE4.status = NFS4_OK;

  return res_CREATE4.status;
}                               /* nfs4_op_create */
Пример #8
0
int nfs_Symlink(nfs_arg_t *parg,
                exportlist_t *pexport,
                fsal_op_context_t *pcontext,
                nfs_worker_data_t *pworker,
                struct svc_req *preq,
                nfs_res_t *pres)
{
  char *str_symlink_name = NULL;
  fsal_name_t symlink_name;
  char *str_target_path = NULL;
  cache_inode_create_arg_t create_arg;
  fsal_accessmode_t mode = 0777;
  cache_entry_t *symlink_pentry = NULL;
  cache_entry_t *parent_pentry;
  cache_inode_file_type_t parent_filetype;
  fsal_attrib_list_t parent_attr;
  fsal_attrib_list_t attr_symlink;
  fsal_attrib_list_t attributes_symlink;
  fsal_attrib_list_t attr_parent_after;
  fsal_attrib_list_t *ppre_attr;
  cache_inode_status_t cache_status;
  cache_inode_status_t cache_status_parent;
  fsal_handle_t *pfsal_handle;
  int rc = NFS_REQ_OK;
#ifdef _USE_QUOTA
  fsal_status_t fsal_status ;
#endif

  memset(&create_arg, 0, sizeof(create_arg));

  if(isDebug(COMPONENT_NFSPROTO))
    {
      char str[LEN_FH_STR];

      switch (preq->rq_vers)
        {
        case NFS_V2:
          str_symlink_name = parg->arg_symlink2.from.name;
          str_target_path = parg->arg_symlink2.to;
          break;
        case NFS_V3:
          str_symlink_name = parg->arg_symlink3.where.name;
          str_target_path = parg->arg_symlink3.symlink.symlink_data;
          break;
        }

      nfs_FhandleToStr(preq->rq_vers,
                       &(parg->arg_symlink2.from.dir),
                       &(parg->arg_symlink3.where.dir),
                       NULL,
                       str);
      LogDebug(COMPONENT_NFSPROTO,
               "REQUEST PROCESSING: Calling nfs_Symlink handle: %s name: %s target: %s",
               str, str_symlink_name, str_target_path);
    }

  if(preq->rq_vers == NFS_V3)
    {
      /* to avoid setting it on each error case */
      pres->res_symlink3.SYMLINK3res_u.resfail.dir_wcc.before.attributes_follow = FALSE;
      pres->res_symlink3.SYMLINK3res_u.resfail.dir_wcc.after.attributes_follow = FALSE;
      ppre_attr = NULL;
    }

  /* Convert directory file handle into a vnode */
  if((parent_pentry = nfs_FhandleToCache(preq->rq_vers,
                                         &(parg->arg_symlink2.from.dir),
                                         &(parg->arg_symlink3.where.dir),
                                         NULL,
                                         &(pres->res_stat2),
                                         &(pres->res_symlink3.status),
                                         NULL,
                                         &parent_attr,
                                         pcontext, &rc)) == NULL)
    {
      /* Stale NFS FH ? */
      goto out;;
    }

  /* get directory attributes before action (for V3 reply) */
  ppre_attr = &parent_attr;

  /* Extract the filetype */
  parent_filetype = cache_inode_fsal_type_convert(parent_attr.type);

  /*
   * Sanity checks: new directory name must be non-null; parent must be
   * a directory. 
   */
  if(parent_filetype != DIRECTORY)
    {
      switch (preq->rq_vers)
        {
        case NFS_V2:
          pres->res_stat2 = NFSERR_NOTDIR;
          break;

        case NFS_V3:
          pres->res_symlink3.status = NFS3ERR_NOTDIR;
          break;
        }

      rc = NFS_REQ_OK;
      goto out;
    }

#ifdef _USE_QUOTA
    /* if quota support is active, then we should check is the FSAL allows inode creation or not */
    fsal_status = FSAL_check_quota( pexport->fullpath, 
                                    FSAL_QUOTA_INODES,
                                    FSAL_OP_CONTEXT_TO_UID( pcontext ) ) ;
    if( FSAL_IS_ERROR( fsal_status ) )
     {

       switch (preq->rq_vers)
         {
           case NFS_V2:
             pres->res_stat2 = NFSERR_DQUOT ;
             break;

           case NFS_V3:
             pres->res_symlink3.status = NFS3ERR_DQUOT;
             break;
         }

       rc = NFS_REQ_OK;
       goto out;
     }
#endif /* _USE_QUOTA */


  switch (preq->rq_vers)
    {
    case NFS_V2:
      str_symlink_name = parg->arg_symlink2.from.name;
      str_target_path = parg->arg_symlink2.to;
      break;

    case NFS_V3:
      str_symlink_name = parg->arg_symlink3.where.name;
      str_target_path = parg->arg_symlink3.symlink.symlink_data;
      break;
    }

  if(str_symlink_name == NULL ||
     *str_symlink_name == '\0'||
     str_target_path == NULL  ||
     *str_target_path == '\0' ||
     FSAL_IS_ERROR(FSAL_str2name(str_symlink_name, 0, &symlink_name)) ||
     FSAL_IS_ERROR(FSAL_str2path(str_target_path, 0, &create_arg.link_content)))
    {
      cache_status = CACHE_INODE_INVALID_ARGUMENT;
    }
  else
    {
      /* Make the symlink */
      if((symlink_pentry = cache_inode_create(parent_pentry,
                                              &symlink_name,
                                              SYMBOLIC_LINK,
                                              mode,
                                              &create_arg,
                                              &attr_symlink,
                                              pcontext, &cache_status)) != NULL)
        {
          switch (preq->rq_vers)
            {
            case NFS_V2:
              pres->res_stat2 = NFS_OK;
              break;

            case NFS_V3:
              /* Build file handle */
              pfsal_handle = &symlink_pentry->handle;

              /* Some clients (like the Spec NFS benchmark) set attributes with the NFSPROC3_SYMLINK request */
              if(nfs3_Sattr_To_FSALattr(&attributes_symlink,
                                        &parg->arg_symlink3.symlink.symlink_attributes) == 0)
                {
                  pres->res_create3.status = NFS3ERR_INVAL;
                  rc = NFS_REQ_OK;
                  goto out;
                }

              /* Mode is managed above (in cache_inode_create), there is no need 
               * to manage it */
              if(attributes_symlink.asked_attributes & FSAL_ATTR_MODE)
                attributes_symlink.asked_attributes &= ~FSAL_ATTR_MODE;

              /* Some clients (like Solaris 10) try to set the size of the file to 0
               * at creation time. The FSAL create empty file, so we ignore this */
              if(attributes_symlink.asked_attributes & FSAL_ATTR_SIZE)
                attributes_symlink.asked_attributes &= ~FSAL_ATTR_SIZE;

              if(attributes_symlink.asked_attributes & FSAL_ATTR_SPACEUSED)
                attributes_symlink.asked_attributes &= ~FSAL_ATTR_SPACEUSED;

              /* If owner or owner_group are set, and the credential was
               * squashed, then we must squash the set owner and owner_group.
               */
              squash_setattr(&pworker->export_perms,
                             &pworker->user_credentials,
                             &attributes_symlink);

              /* Are there attributes to be set (additional to the mode) ? */
              if(attributes_symlink.asked_attributes != 0ULL &&
                 attributes_symlink.asked_attributes != FSAL_ATTR_MODE)
                {
                  /* A call to cache_inode_setattr is required */
                  if(cache_inode_setattr(symlink_pentry,
                                         &attributes_symlink,
                                         pcontext,
                                         FALSE,
                                         &cache_status) != CACHE_INODE_SUCCESS)
                    {
                      goto out_error;
                    }
                }

              if ((pres->res_symlink3.status =
                   (nfs3_AllocateFH(&pres->res_symlink3.SYMLINK3res_u
                                    .resok.obj.post_op_fh3_u.handle)))
                  != NFS3_OK) {
                   pres->res_symlink3.status = NFS3ERR_IO;
                   rc = NFS_REQ_OK;
                   goto out;
              }

              if(nfs3_FSALToFhandle
                 (&pres->res_symlink3.SYMLINK3res_u.resok.obj.post_op_fh3_u.handle,
                  pfsal_handle, pexport) == 0)
                {
                  gsh_free(pres->res_symlink3.SYMLINK3res_u.resok.obj.
                           post_op_fh3_u.handle.data.data_val);

                  pres->res_symlink3.status = NFS3ERR_BADHANDLE;
                  rc = NFS_REQ_OK;
                  goto out;
                }

              /* The the parent pentry attributes for building Wcc Data */
              if(cache_inode_getattr(parent_pentry,
                                     &attr_parent_after,
                                     pcontext,
                                     &cache_status_parent)
                 != CACHE_INODE_SUCCESS)
                {
                  gsh_free(pres->res_symlink3.SYMLINK3res_u.resok.obj.
                           post_op_fh3_u.handle.data.data_val);

                  pres->res_symlink3.status = NFS3ERR_BADHANDLE;
                  rc = NFS_REQ_OK;
                  goto out;
                }

              /* Set Post Op Fh3 structure */
              pres->res_symlink3.SYMLINK3res_u.resok.obj.handle_follows = TRUE;

              /* Build entry attributes */
              nfs_SetPostOpAttr(pexport,
                                &attr_symlink,
                                &(pres->res_symlink3.SYMLINK3res_u
                                  .resok.obj_attributes));

              /* Build Weak Cache Coherency data */
              nfs_SetWccData(pexport,
                             ppre_attr,
                             &attr_parent_after,
                             &(pres->res_symlink3.SYMLINK3res_u.resok.dir_wcc));

              pres->res_symlink3.status = NFS3_OK;
              break;
            }                   /* switch */

          rc = NFS_REQ_OK;
          goto out;
        }
    }

out_error:
  rc = nfs_SetFailedStatus(pexport, preq->rq_vers, cache_status,
                           &pres->res_stat2, &pres->res_symlink3.status,
                           NULL, ppre_attr,
                           &(pres->res_symlink3.SYMLINK3res_u.resfail.dir_wcc),
                           NULL, NULL);
out:
  /* return references */
  if (parent_pentry)
      cache_inode_put(parent_pentry);

  if (symlink_pentry)
      cache_inode_put(symlink_pentry);

  return (rc);

}                               /* nfs_Symlink */
Пример #9
0
int nfs41_op_open(struct nfs_argop4 *op, compound_data_t * data, struct nfs_resop4 *resp)
{
    cache_entry_t *pentry_parent = NULL;
    cache_entry_t *pentry_lookup = NULL;
    cache_entry_t *pentry_newfile = NULL;
    fsal_handle_t *pnewfsal_handle = NULL;
    fsal_attrib_list_t attr_parent;
    fsal_attrib_list_t attr;
    fsal_attrib_list_t attr_newfile;
    fsal_attrib_list_t sattr;
    fsal_openflags_t openflags = 0;
    cache_inode_status_t cache_status;
    nfsstat4 rc;
    int retval;
    fsal_name_t filename;
    bool_t AttrProvided = FALSE;
    fsal_accessmode_t mode = 0600;
    nfs_fh4 newfh4;
    nfs_client_id_t nfs_clientid;
    nfs_worker_data_t *pworker = NULL;
    int convrc = 0;
    char __attribute__ ((__unused__)) funcname[] = "nfs4_op_open";

    cache_inode_state_data_t candidate_data;
    cache_inode_state_type_t candidate_type;
    cache_inode_state_t *pfile_state = NULL;
    cache_inode_state_t *pstate_found_iterate = NULL;
    cache_inode_state_t *pstate_previous_iterate = NULL;
    cache_inode_state_t *pstate_found_same_owner = NULL;

    cache_inode_open_owner_name_t owner_name;
    cache_inode_open_owner_name_t *powner_name = NULL;
    cache_inode_open_owner_t *powner = NULL;
    bool_t open_owner_known = FALSE;

    resp->resop = NFS4_OP_OPEN;
    res_OPEN4.status = NFS4_OK;

    uint32_t tmp_attr[2];
    uint_t tmp_int = 2;

    int pnfs_status;
    cache_inode_create_arg_t create_arg;

    pworker = (nfs_worker_data_t *) data->pclient->pworker;

    /* If there is no FH */
    if(nfs4_Is_Fh_Empty(&(data->currentFH)))
    {
        res_OPEN4.status = NFS4ERR_NOFILEHANDLE;
        return res_OPEN4.status;
    }

    /* If the filehandle is invalid */
    if(nfs4_Is_Fh_Invalid(&(data->currentFH)))
    {
        res_OPEN4.status = NFS4ERR_BADHANDLE;
        return res_OPEN4.status;
    }

    /* Tests if the Filehandle is expired (for volatile filehandle) */
    if(nfs4_Is_Fh_Expired(&(data->currentFH)))
    {
        res_OPEN4.status = NFS4ERR_FHEXPIRED;
        return res_OPEN4.status;
    }

    /* This can't be done on the pseudofs */
    if(nfs4_Is_Fh_Pseudo(&(data->currentFH)))
    {
        res_OPEN4.status = NFS4ERR_ROFS;
        return res_OPEN4.status;
    }

    /* If Filehandle points to a xattr object, manage it via the xattrs specific functions */
    if(nfs4_Is_Fh_Xattr(&(data->currentFH)))
        return nfs4_op_open_xattr(op, data, resp);

    /* If data->current_entry is empty, repopulate it */
    if(data->current_entry == NULL)
    {
        if((data->current_entry = nfs_FhandleToCache(NFS_V4,
                                  NULL,
                                  NULL,
                                  &(data->currentFH),
                                  NULL,
                                  NULL,
                                  &(res_OPEN4.status),
                                  &attr,
                                  data->pcontext,
                                  data->pclient,
                                  data->ht, &retval)) == NULL)
        {
            res_OPEN4.status = NFS4ERR_SERVERFAULT;
            return res_OPEN4.status;
        }
    }

    /* Set parent */
    pentry_parent = data->current_entry;

    /* First switch is based upon claim type */
    switch (arg_OPEN4.claim.claim)
    {
    case CLAIM_DELEGATE_CUR:
    case CLAIM_DELEGATE_PREV:
        /* Check for name length */
        if(arg_OPEN4.claim.open_claim4_u.file.utf8string_len > FSAL_MAX_NAME_LEN)
        {
            res_OPEN4.status = NFS4ERR_NAMETOOLONG;
            return res_OPEN4.status;
        }

        /* get the filename from the argument, it should not be empty */
        if(arg_OPEN4.claim.open_claim4_u.file.utf8string_len == 0)
        {
            res_OPEN4.status = NFS4ERR_INVAL;
            return res_OPEN4.status;
        }

        res_OPEN4.status = NFS4ERR_NOTSUPP;
        return res_OPEN4.status;
        break;

    case CLAIM_NULL:
        /* Check for name length */
        if(arg_OPEN4.claim.open_claim4_u.file.utf8string_len > FSAL_MAX_NAME_LEN)
        {
            res_OPEN4.status = NFS4ERR_NAMETOOLONG;
            return res_OPEN4.status;
        }

        /* get the filename from the argument, it should not be empty */
        if(arg_OPEN4.claim.open_claim4_u.file.utf8string_len == 0)
        {
            res_OPEN4.status = NFS4ERR_INVAL;
            return res_OPEN4.status;
        }

        /* Check if asked attributes are correct */
        if(arg_OPEN4.openhow.openflag4_u.how.mode == GUARDED4 ||
                arg_OPEN4.openhow.openflag4_u.how.mode == UNCHECKED4)
        {
            if(!nfs4_Fattr_Supported
                    (&arg_OPEN4.openhow.openflag4_u.how.createhow4_u.createattrs))
            {
                res_OPEN4.status = NFS4ERR_ATTRNOTSUPP;
                return res_OPEN4.status;
            }

            /* Do not use READ attr, use WRITE attr */
            if(!nfs4_Fattr_Check_Access
                    (&arg_OPEN4.openhow.openflag4_u.how.createhow4_u.createattrs,
                     FATTR4_ATTR_WRITE))
            {
                res_OPEN4.status = NFS4ERR_INVAL;
                return res_OPEN4.status;
            }
        }

        /* Check if filename is correct */
        if((cache_status =
                    cache_inode_error_convert(FSAL_buffdesc2name
                                              ((fsal_buffdesc_t *) & arg_OPEN4.claim.open_claim4_u.
                                               file, &filename))) != CACHE_INODE_SUCCESS)
        {
            res_OPEN4.status = nfs4_Errno(cache_status);
            return res_OPEN4.status;
        }

        /* Check parent */
        pentry_parent = data->current_entry;

        /* Parent must be a directory */
        if((pentry_parent->internal_md.type != DIR_BEGINNING) &&
                (pentry_parent->internal_md.type != DIR_CONTINUE))
        {
            /* Parent object is not a directory... */
            if(pentry_parent->internal_md.type == SYMBOLIC_LINK)
                res_OPEN4.status = NFS4ERR_SYMLINK;
            else
                res_OPEN4.status = NFS4ERR_NOTDIR;

            return res_OPEN4.status;
        }

        /* What kind of open is it ? */

        LogFullDebug(COMPONENT_NFS_V4,
                     "     OPEN: Claim type = %d   Open Type = %d  Share Deny = %d   Share Access = %d \n",
                     arg_OPEN4.claim.claim, arg_OPEN4.openhow.opentype, arg_OPEN4.share_deny,
                     arg_OPEN4.share_access);


        /* It this a known client id ? */
        LogDebug(COMPONENT_NFS_V4, "OPEN Client id = %llx", arg_OPEN4.owner.clientid);

        /* Is this open_owner known ? */
        if(!nfs_convert_open_owner(&arg_OPEN4.owner, &owner_name))
        {
            res_OPEN4.status = NFS4ERR_SERVERFAULT;
            return res_OPEN4.status;
        }

        if(!nfs_open_owner_Get_Pointer(&owner_name, &powner))
        {
            /* This open owner is not known yet, allocated and set up a new one */
            GET_PREALLOC(powner,
                         data->pclient->pool_open_owner,
                         data->pclient->nb_pre_state_v4, cache_inode_open_owner_t, next);

            GET_PREALLOC(powner_name,
                         data->pclient->pool_open_owner_name,
                         data->pclient->nb_pre_state_v4,
                         cache_inode_open_owner_name_t, next);

            if(powner == NULL || powner_name == NULL)
            {
                res_OPEN4.status = NFS4ERR_SERVERFAULT;
                return res_OPEN4.status;
            }

            memcpy((char *)powner_name, (char *)&owner_name,
                   sizeof(cache_inode_open_owner_name_t));

            /* set up the content of the open_owner */
            powner->confirmed = FALSE;
            powner->seqid = 1;    /* NFSv4.1 specific, initial seqid is 1 */
            powner->related_owner = NULL;
            powner->next = NULL;
            powner->clientid = arg_OPEN4.owner.clientid;
            powner->owner_len = arg_OPEN4.owner.owner.owner_len;
            memcpy((char *)powner->owner_val, (char *)arg_OPEN4.owner.owner.owner_val,
                   arg_OPEN4.owner.owner.owner_len);
            powner->owner_val[powner->owner_len] = '\0';

            pthread_mutex_init(&powner->lock, NULL);

            if(!nfs_open_owner_Set(powner_name, powner))
            {
                res_OPEN4.status = NFS4ERR_SERVERFAULT;
                return res_OPEN4.status;
            }

        }

        /* Status of parent directory before the operation */
        if((cache_status = cache_inode_getattr(pentry_parent,
                                               &attr_parent,
                                               data->ht,
                                               data->pclient,
                                               data->pcontext,
                                               &cache_status)) != CACHE_INODE_SUCCESS)
        {
            res_OPEN4.status = nfs4_Errno(cache_status);
            return res_OPEN4.status;
        }
        memset(&(res_OPEN4.OPEN4res_u.resok4.cinfo.before), 0, sizeof(changeid4));
        res_OPEN4.OPEN4res_u.resok4.cinfo.before =
            (changeid4) pentry_parent->internal_md.mod_time;

        /* CLient may have provided fattr4 to set attributes at creation time */
        if(arg_OPEN4.openhow.openflag4_u.how.mode == GUARDED4 ||
                arg_OPEN4.openhow.openflag4_u.how.mode == UNCHECKED4)
        {
            if(arg_OPEN4.openhow.openflag4_u.how.createhow4_u.createattrs.attrmask.
                    bitmap4_len != 0)
            {
                /* Convert fattr4 so nfs4_sattr */
                convrc =
                    nfs4_Fattr_To_FSAL_attr(&sattr,
                                            &(arg_OPEN4.openhow.openflag4_u.how.
                                              createhow4_u.createattrs));

                if(convrc == 0)
                {
                    res_OPEN4.status = NFS4ERR_ATTRNOTSUPP;
                    return res_OPEN4.status;
                }

                if(convrc == -1)
                {
                    res_OPEN4.status = NFS4ERR_BADXDR;
                    return res_OPEN4.status;
                }

                AttrProvided = TRUE;
            }

        }

        /* Second switch is based upon "openhow" */
        switch (arg_OPEN4.openhow.opentype)
        {
        case OPEN4_CREATE:
            /* a new file is to be created */

            /* Does a file with this name already exist ? */
            pentry_lookup = cache_inode_lookup(pentry_parent,
                                               &filename,
                                               &attr_newfile,
                                               data->ht,
                                               data->pclient,
                                               data->pcontext, &cache_status);

            if(cache_status != CACHE_INODE_NOT_FOUND)
            {
                /* if open is UNCHECKED, return NFS4_OK (RFC3530 page 172) */
                if(arg_OPEN4.openhow.openflag4_u.how.mode == UNCHECKED4
                        && (cache_status == CACHE_INODE_SUCCESS))
                {
                    /* If the file is opened for write, OPEN4 while deny share write access,
                     * in this case, check caller has write access to the file */
                    if(arg_OPEN4.share_deny & OPEN4_SHARE_DENY_WRITE)
                    {
                        if(cache_inode_access(pentry_lookup,
                                              FSAL_W_OK,
                                              data->ht,
                                              data->pclient,
                                              data->pcontext,
                                              &cache_status) != CACHE_INODE_SUCCESS)
                        {
                            res_OPEN4.status = NFS4ERR_ACCESS;
                            return res_OPEN4.status;
                        }
                        openflags = FSAL_O_WRONLY;
                    }

                    /* Same check on read: check for readability of a file before opening it for read */
                    if(arg_OPEN4.share_access & OPEN4_SHARE_ACCESS_READ)
                    {
                        if(cache_inode_access(pentry_lookup,
                                              FSAL_R_OK,
                                              data->ht,
                                              data->pclient,
                                              data->pcontext,
                                              &cache_status) != CACHE_INODE_SUCCESS)
                        {
                            res_OPEN4.status = NFS4ERR_ACCESS;
                            return res_OPEN4.status;
                        }
                        openflags = FSAL_O_RDONLY;
                    }

                    if(AttrProvided == TRUE)      /* Set the attribute if provided */
                    {
                        if((cache_status = cache_inode_setattr(pentry_lookup,
                                                               &sattr,
                                                               data->ht,
                                                               data->pclient,
                                                               data->pcontext,
                                                               &cache_status)) !=
                                CACHE_INODE_SUCCESS)
                        {
                            res_OPEN4.status = nfs4_Errno(cache_status);
                            return res_OPEN4.status;
                        }

                        res_OPEN4.OPEN4res_u.resok4.attrset =
                            arg_OPEN4.openhow.openflag4_u.how.createhow4_u.createattrs.
                            attrmask;
                    }
                    else
                        res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_len = 0;

                    /* Same check on write */
                    if(arg_OPEN4.share_access & OPEN4_SHARE_ACCESS_WRITE)
                    {
                        if(cache_inode_access(pentry_lookup,
                                              FSAL_W_OK,
                                              data->ht,
                                              data->pclient,
                                              data->pcontext,
                                              &cache_status) != CACHE_INODE_SUCCESS)
                        {
                            res_OPEN4.status = NFS4ERR_ACCESS;
                            return res_OPEN4.status;
                        }
                        openflags = FSAL_O_RDWR;
                    }

                    /* Set the state for the related file */

                    /* Prepare state management structure */
                    candidate_type = CACHE_INODE_STATE_SHARE;
                    candidate_data.share.share_deny = arg_OPEN4.share_deny;
                    candidate_data.share.share_access = arg_OPEN4.share_access;

                    if(cache_inode_add_state(pentry_lookup,
                                             candidate_type,
                                             &candidate_data,
                                             powner,
                                             data->pclient,
                                             data->pcontext,
                                             &pfile_state,
                                             &cache_status) != CACHE_INODE_SUCCESS)
                    {
                        /* Seqid has to be incremented even in this case */
                        P(powner->lock);
                        powner->seqid += 1;
                        V(powner->lock);

                        res_OPEN4.status = NFS4ERR_SHARE_DENIED;
                        return res_OPEN4.status;
                    }

                    /* Open the file */
                    if(cache_inode_open_by_name(pentry_parent,
                                                &filename,
                                                pentry_lookup,
                                                data->pclient,
                                                openflags,
                                                data->pcontext,
                                                &cache_status) != CACHE_INODE_SUCCESS)
                    {
                        /* Seqid has to be incremented even in this case */
                        P(powner->lock);
                        powner->seqid += 1;
                        V(powner->lock);

                        res_OPEN4.status = NFS4ERR_SHARE_DENIED;
                        res_OPEN4.status = NFS4ERR_ACCESS;
                        return res_OPEN4.status;
                    }

                    res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_len = 2;
                    if((res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_val =
                                (uint32_t *) Mem_Alloc(res_OPEN4.OPEN4res_u.resok4.attrset.
                                                       bitmap4_len * sizeof(uint32_t))) == NULL)
                    {
                        res_OPEN4.status = NFS4ERR_SERVERFAULT;
                        return res_OPEN4.status;
                    }

                    memset(&(res_OPEN4.OPEN4res_u.resok4.cinfo.after), 0,
                           sizeof(changeid4));
                    res_OPEN4.OPEN4res_u.resok4.cinfo.after =
                        (changeid4) pentry_parent->internal_md.mod_time;
                    res_OPEN4.OPEN4res_u.resok4.cinfo.atomic = TRUE;

                    res_OPEN4.OPEN4res_u.resok4.stateid.seqid = pfile_state->seqid;
                    memcpy(res_OPEN4.OPEN4res_u.resok4.stateid.other,
                           pfile_state->stateid_other, 12);

                    /* No delegation */
                    res_OPEN4.OPEN4res_u.resok4.delegation.delegation_type =
                        OPEN_DELEGATE_NONE;
                    res_OPEN4.OPEN4res_u.resok4.rflags = OPEN4_RESULT_LOCKTYPE_POSIX;

                    /* Now produce the filehandle to this file */
                    if((pnewfsal_handle =
                                cache_inode_get_fsal_handle(pentry_lookup, &cache_status)) == NULL)
                    {
                        res_OPEN4.status = nfs4_Errno(cache_status);
                        return res_OPEN4.status;
                    }

                    /* Allocation of a new file handle */
                    if((rc = nfs4_AllocateFH(&newfh4)) != NFS4_OK)
                    {
                        res_OPEN4.status = rc;
                        return res_OPEN4.status;
                    }

                    /* Building a new fh */
                    if(!nfs4_FSALToFhandle(&newfh4, pnewfsal_handle, data))
                    {
                        res_OPEN4.status = NFS4ERR_SERVERFAULT;
                        return res_OPEN4.status;
                    }

                    /* This new fh replaces the current FH */
                    data->currentFH.nfs_fh4_len = newfh4.nfs_fh4_len;
                    memcpy(data->currentFH.nfs_fh4_val, newfh4.nfs_fh4_val,
                           newfh4.nfs_fh4_len);

                    data->current_entry = pentry_lookup;
                    data->current_filetype = REGULAR_FILE;

                    res_OPEN4.status = NFS4_OK;
                    return res_OPEN4.status;
                }

                /* if open is EXCLUSIVE, but verifier is the same, return NFS4_OK (RFC3530 page 173) */
                if(arg_OPEN4.openhow.openflag4_u.how.mode == EXCLUSIVE4)
                {
                    if((pentry_lookup != NULL)
                            && (pentry_lookup->internal_md.type == REGULAR_FILE))
                    {
                        pstate_found_iterate = NULL;
                        pstate_previous_iterate = NULL;

                        do
                        {
                            cache_inode_state_iterate(pentry_lookup,
                                                      &pstate_found_iterate,
                                                      pstate_previous_iterate,
                                                      data->pclient,
                                                      data->pcontext, &cache_status);
                            if(cache_status == CACHE_INODE_STATE_ERROR)
                                break;

                            if(cache_status == CACHE_INODE_INVALID_ARGUMENT)
                            {
                                /* Seqid has to be incremented even in this case */
                                P(powner->lock);
                                powner->seqid += 1;
                                V(powner->lock);

                                res_OPEN4.status = NFS4ERR_INVAL;
                                return res_OPEN4.status;
                            }

                            /* Check is open_owner is the same */
                            if(pstate_found_iterate != NULL)
                            {
                                if((pstate_found_iterate->state_type ==
                                        CACHE_INODE_STATE_SHARE)
                                        && !memcmp(arg_OPEN4.owner.owner.owner_val,
                                                   pstate_found_iterate->powner->owner_val,
                                                   pstate_found_iterate->powner->owner_len)
                                        && !memcmp(pstate_found_iterate->state_data.share.
                                                   oexcl_verifier,
                                                   arg_OPEN4.openhow.openflag4_u.how.
                                                   createhow4_u.createverf, NFS4_VERIFIER_SIZE))
                                {

                                    /* A former open EXCLUSIVE with same owner and verifier was found, resend it */
                                    res_OPEN4.OPEN4res_u.resok4.stateid.seqid =
                                        pstate_found_iterate->seqid;
                                    memcpy(res_OPEN4.OPEN4res_u.resok4.stateid.other,
                                           pstate_found_iterate->stateid_other, 12);

                                    memset(&(res_OPEN4.OPEN4res_u.resok4.cinfo.after), 0,
                                           sizeof(changeid4));
                                    res_OPEN4.OPEN4res_u.resok4.cinfo.after =
                                        (changeid4) pentry_parent->internal_md.mod_time;
                                    res_OPEN4.OPEN4res_u.resok4.cinfo.atomic = TRUE;

                                    /* No delegation */
                                    res_OPEN4.OPEN4res_u.resok4.delegation.delegation_type =
                                        OPEN_DELEGATE_NONE;
                                    res_OPEN4.OPEN4res_u.resok4.rflags =
                                        OPEN4_RESULT_LOCKTYPE_POSIX;

                                    /* Now produce the filehandle to this file */
                                    if((pnewfsal_handle =
                                                cache_inode_get_fsal_handle(pentry_lookup,
                                                                            &cache_status)) == NULL)
                                    {
                                        res_OPEN4.status = nfs4_Errno(cache_status);
                                        return res_OPEN4.status;
                                    }

                                    /* Allocation of a new file handle */
                                    if((rc = nfs4_AllocateFH(&newfh4)) != NFS4_OK)
                                    {
                                        res_OPEN4.status = rc;
                                        return res_OPEN4.status;
                                    }

                                    /* Building a new fh */
                                    if(!nfs4_FSALToFhandle(&newfh4, pnewfsal_handle, data))
                                    {
                                        res_OPEN4.status = NFS4ERR_SERVERFAULT;
                                        return res_OPEN4.status;
                                    }

                                    /* This new fh replaces the current FH */
                                    data->currentFH.nfs_fh4_len = newfh4.nfs_fh4_len;
                                    memcpy(data->currentFH.nfs_fh4_val, newfh4.nfs_fh4_val,
                                           newfh4.nfs_fh4_len);

                                    data->current_entry = pentry_lookup;
                                    data->current_filetype = REGULAR_FILE;

                                    /* regular exit */
                                    res_OPEN4.status = NFS4_OK;
                                    return res_OPEN4.status;
                                }

                            }
                            /* if( pstate_found_iterate != NULL ) */
                            pstate_previous_iterate = pstate_found_iterate;
                        }
                        while(pstate_found_iterate != NULL);
                    }
                }

                /* Managing GUARDED4 mode */
                if(cache_status != CACHE_INODE_SUCCESS)
                    res_OPEN4.status = nfs4_Errno(cache_status);
                else
                    res_OPEN4.status = NFS4ERR_EXIST;       /* File already exists */
                return res_OPEN4.status;
            }

            /*  if( cache_status != CACHE_INODE_NOT_FOUND ), if file already exists basically */
            LogFullDebug(COMPONENT_NFS_V4, "    OPEN open.how = %d\n", arg_OPEN4.openhow.openflag4_u.how.mode);

            create_arg.use_pnfs = FALSE;
#ifdef _USE_PNFS
            /*  set the file has "managed via pNFS" */
            if(data->pexport->options & EXPORT_OPTION_USE_PNFS)
                create_arg.use_pnfs = TRUE;
#endif                          /* _USE_PNFS */

            /* Create the file, if we reach this point, it does not exist, we can create it */
            if((pentry_newfile = cache_inode_create(pentry_parent,
                                                    &filename,
                                                    REGULAR_FILE,
                                                    mode,
                                                    &create_arg,
                                                    &attr_newfile,
                                                    data->ht,
                                                    data->pclient,
                                                    data->pcontext, &cache_status)) == NULL)
            {
                /* If the file already exists, this is not an error if open mode is UNCHECKED */
                if(cache_status != CACHE_INODE_ENTRY_EXISTS)
                {
                    res_OPEN4.status = nfs4_Errno(cache_status);
                    return res_OPEN4.status;
                }
                else
                {
                    /* If this point is reached, then the file already exists, cache_status == CACHE_INODE_ENTRY_EXISTS and pentry_newfile == NULL
                       This probably means EXCLUSIVE4 mode is used and verifier matches. pentry_newfile is then set to pentry_lookup */
                    pentry_newfile = pentry_lookup;
                }
            }

            /* Prepare state management structure */
            candidate_type = CACHE_INODE_STATE_SHARE;
            candidate_data.share.share_deny = arg_OPEN4.share_deny;
            candidate_data.share.share_access = arg_OPEN4.share_access;
            candidate_data.share.lockheld = 0;

            /* If file is opened under mode EXCLUSIVE4, open verifier should be kept to detect non vicious double open */
            if(arg_OPEN4.openhow.openflag4_u.how.mode == EXCLUSIVE4)
            {
                strncpy(candidate_data.share.oexcl_verifier,
                        arg_OPEN4.openhow.openflag4_u.how.createhow4_u.createverf,
                        NFS4_VERIFIER_SIZE);
            }

            if(cache_inode_add_state(pentry_newfile,
                                     candidate_type,
                                     &candidate_data,
                                     powner,
                                     data->pclient,
                                     data->pcontext,
                                     &pfile_state, &cache_status) != CACHE_INODE_SUCCESS)
            {
                /* Seqid has to be incremented even in this case */
                P(powner->lock);
                powner->seqid += 1;
                V(powner->lock);

                res_OPEN4.status = NFS4ERR_SHARE_DENIED;
                return res_OPEN4.status;
            }

            if(AttrProvided == TRUE)      /* Set the attribute if provided */
            {
                if((cache_status = cache_inode_setattr(pentry_newfile,
                                                       &sattr,
                                                       data->ht,
                                                       data->pclient,
                                                       data->pcontext,
                                                       &cache_status)) !=
                        CACHE_INODE_SUCCESS)
                {
                    res_OPEN4.status = nfs4_Errno(cache_status);
                    return res_OPEN4.status;
                }

            }

            /* Set the openflags variable */
            if(arg_OPEN4.share_deny & OPEN4_SHARE_DENY_WRITE)
                openflags |= FSAL_O_RDONLY;
            if(arg_OPEN4.share_deny & OPEN4_SHARE_DENY_READ)
                openflags |= FSAL_O_WRONLY;
            if(arg_OPEN4.share_access & OPEN4_SHARE_ACCESS_WRITE)
                openflags = FSAL_O_RDWR;
            if(arg_OPEN4.share_access != 0)
                openflags = FSAL_O_RDWR;    /* @todo : BUGAZOMEU : Something better later */

            /* Open the file */
            if(cache_inode_open_by_name(pentry_parent,
                                        &filename,
                                        pentry_newfile,
                                        data->pclient,
                                        openflags,
                                        data->pcontext,
                                        &cache_status) != CACHE_INODE_SUCCESS)
            {
                /* Seqid has to be incremented even in this case */
                P(powner->lock);
                powner->seqid += 1;
                V(powner->lock);

                res_OPEN4.status = NFS4ERR_ACCESS;
                return res_OPEN4.status;
            }

            break;

        case OPEN4_NOCREATE:
            /* It was not a creation, but a regular open */
            /* The filehandle to the new file replaces the current filehandle */
            if(pentry_newfile == NULL)
            {
                if((pentry_newfile = cache_inode_lookup(pentry_parent,
                                                        &filename,
                                                        &attr_newfile,
                                                        data->ht,
                                                        data->pclient,
                                                        data->pcontext,
                                                        &cache_status)) == NULL)
                {
                    res_OPEN4.status = nfs4_Errno(cache_status);
                    return res_OPEN4.status;
                }
            }

            /* OPEN4 is to be done on a file */
            if(pentry_newfile->internal_md.type != REGULAR_FILE)
            {
                if(pentry_newfile->internal_md.type == DIR_BEGINNING
                        || pentry_newfile->internal_md.type == DIR_CONTINUE)
                {
                    res_OPEN4.status = NFS4ERR_ISDIR;
                    return res_OPEN4.status;
                }
                else if(pentry_newfile->internal_md.type == SYMBOLIC_LINK)
                {
                    res_OPEN4.status = NFS4ERR_SYMLINK;
                    return res_OPEN4.status;
                }
                else
                {
                    res_OPEN4.status = NFS4ERR_INVAL;
                    return res_OPEN4.status;
                }
            }

            /* If the file is opened for write, OPEN4 while deny share write access,
             * in this case, check caller has write access to the file */
            if(arg_OPEN4.share_deny & OPEN4_SHARE_DENY_WRITE)
            {
                if(cache_inode_access(pentry_newfile,
                                      FSAL_W_OK,
                                      data->ht,
                                      data->pclient,
                                      data->pcontext, &cache_status) != CACHE_INODE_SUCCESS)
                {
                    res_OPEN4.status = NFS4ERR_ACCESS;
                    return res_OPEN4.status;
                }
                openflags = FSAL_O_WRONLY;
            }

            /* Same check on read: check for readability of a file before opening it for read */
            if(arg_OPEN4.share_access & OPEN4_SHARE_ACCESS_READ)
            {
                if(cache_inode_access(pentry_newfile,
                                      FSAL_R_OK,
                                      data->ht,
                                      data->pclient,
                                      data->pcontext, &cache_status) != CACHE_INODE_SUCCESS)
                {
                    res_OPEN4.status = NFS4ERR_ACCESS;
                    return res_OPEN4.status;
                }
                openflags = FSAL_O_RDONLY;
            }

            /* Same check on write */
            if(arg_OPEN4.share_access & OPEN4_SHARE_ACCESS_WRITE)
            {
                if(cache_inode_access(pentry_newfile,
                                      FSAL_W_OK,
                                      data->ht,
                                      data->pclient,
                                      data->pcontext, &cache_status) != CACHE_INODE_SUCCESS)
                {
                    res_OPEN4.status = NFS4ERR_ACCESS;
                    return res_OPEN4.status;
                }
                openflags = FSAL_O_RDWR;
            }

            /* Try to find if the same open_owner already has acquired a stateid for this file */
            pstate_found_iterate = NULL;
            pstate_previous_iterate = NULL;
            do
            {
                cache_inode_state_iterate(pentry_newfile,
                                          &pstate_found_iterate,
                                          pstate_previous_iterate,
                                          data->pclient, data->pcontext, &cache_status);
                if(cache_status == CACHE_INODE_STATE_ERROR)
                    break;          /* Get out of the loop */

                if(cache_status == CACHE_INODE_INVALID_ARGUMENT)
                {
                    res_OPEN4.status = NFS4ERR_INVAL;
                    return res_OPEN4.status;
                }

                /* Check is open_owner is the same */
                if(pstate_found_iterate != NULL)
                {
                    if((pstate_found_iterate->state_type == CACHE_INODE_STATE_SHARE) &&
                            (pstate_found_iterate->powner->clientid == arg_OPEN4.owner.clientid)
                            &&
                            ((pstate_found_iterate->powner->owner_len ==
                              arg_OPEN4.owner.owner.owner_len)
                             &&
                             (!memcmp
                              (arg_OPEN4.owner.owner.owner_val,
                               pstate_found_iterate->powner->owner_val,
                               pstate_found_iterate->powner->owner_len))))
                    {
                        /* We'll be re-using the found state */
                        pstate_found_same_owner = pstate_found_iterate;
                    }
                    else
                    {

                        /* This is a different owner, check for possible conflicts */

                        if(memcmp(arg_OPEN4.owner.owner.owner_val,
                                  pstate_found_iterate->powner->owner_val,
                                  pstate_found_iterate->powner->owner_len))
                        {
                            switch (pstate_found_iterate->state_type)
                            {
                            case CACHE_INODE_STATE_SHARE:
                                if((pstate_found_iterate->state_data.share.
                                        share_access & OPEN4_SHARE_ACCESS_WRITE)
                                        && (arg_OPEN4.share_deny & OPEN4_SHARE_DENY_WRITE))
                                {
                                    res_OPEN4.status = NFS4ERR_SHARE_DENIED;
                                    return res_OPEN4.status;
                                }

                                break;
                            }
                        }

                    }

                    /* In all cases opening in read access a read denied file or write access to a write denied file
                     * should fail, even if the owner is the same, see discussion in 14.2.16 and 8.9 */
                    if(pstate_found_iterate->state_type == CACHE_INODE_STATE_SHARE)
                    {
                        /* deny read access on read denied file */
                        if((pstate_found_iterate->state_data.share.
                                share_deny & OPEN4_SHARE_DENY_READ)
                                && (arg_OPEN4.share_access & OPEN4_SHARE_ACCESS_READ))
                        {
                            /* Seqid has to be incremented even in this case */
                            P(powner->lock);
                            powner->seqid += 1;
                            V(powner->lock);

                            powner->seqid += 1;
                            res_OPEN4.status = NFS4ERR_SHARE_DENIED;
                            return res_OPEN4.status;
                        }

                        /* deny write access on write denied file */
                        if((pstate_found_iterate->state_data.share.
                                share_deny & OPEN4_SHARE_DENY_WRITE)
                                && (arg_OPEN4.share_access & OPEN4_SHARE_ACCESS_WRITE))
                        {
                            /* Seqid has to be incremented even in this case */
                            P(powner->lock);
                            powner->seqid += 1;
                            V(powner->lock);

                            res_OPEN4.status = NFS4ERR_SHARE_DENIED;
                            return res_OPEN4.status;
                        }

                    }

                }
                /*  if( pstate_found_iterate != NULL ) */
                pstate_previous_iterate = pstate_found_iterate;
            }
            while(pstate_found_iterate != NULL);

            if(pstate_found_same_owner != NULL)
            {
                pfile_state = pstate_found_same_owner;
                pfile_state->seqid += 1;

                P(powner->lock);
                powner->seqid += 1;
                V(powner->lock);

            }
            else
            {
                /* Set the state for the related file */
                /* Prepare state management structure */
                candidate_type = CACHE_INODE_STATE_SHARE;
                candidate_data.share.share_deny = arg_OPEN4.share_deny;
                candidate_data.share.share_access = arg_OPEN4.share_access;

                if(cache_inode_add_state(pentry_newfile,
                                         candidate_type,
                                         &candidate_data,
                                         powner,
                                         data->pclient,
                                         data->pcontext,
                                         &pfile_state,
                                         &cache_status) != CACHE_INODE_SUCCESS)
                {
                    /* Seqid has to be incremented even in this case */
                    P(powner->lock);
                    powner->seqid += 1;
                    V(powner->lock);

                    res_OPEN4.status = NFS4ERR_SHARE_DENIED;
                    return res_OPEN4.status;
                }
            }

            /* Open the file */
            if(cache_inode_open_by_name(pentry_parent,
                                        &filename,
                                        pentry_newfile,
                                        data->pclient,
                                        openflags,
                                        data->pcontext,
                                        &cache_status) != CACHE_INODE_SUCCESS)
            {
                /* Seqid has to be incremented even in this case */
                P(powner->lock);
                powner->seqid += 1;
                V(powner->lock);

                res_OPEN4.status = NFS4ERR_ACCESS;
                return res_OPEN4.status;
            }
            break;

        default:
            /* Seqid has to be incremented even in this case */
            if(powner != NULL)
            {
                P(powner->lock);
                powner->seqid += 1;
                V(powner->lock);
            }

            res_OPEN4.status = NFS4ERR_INVAL;
            return res_OPEN4.status;
            break;
        }                       /* switch( arg_OPEN4.openhow.opentype ) */

        break;

    case CLAIM_PREVIOUS:
        break;

    default:
        /* Seqid has to be incremented even in this case */
        if(powner != NULL)
        {
            P(powner->lock);
            powner->seqid += 1;
            V(powner->lock);
        }

        res_OPEN4.status = NFS4ERR_INVAL;
        return res_OPEN4.status;
        break;
    }                           /*  switch(  arg_OPEN4.claim.claim ) */

    /* Now produce the filehandle to this file */
    if((pnewfsal_handle =
                cache_inode_get_fsal_handle(pentry_newfile, &cache_status)) == NULL)
    {
        res_OPEN4.status = nfs4_Errno(cache_status);
        return res_OPEN4.status;
    }

    /* Allocation of a new file handle */
    if((rc = nfs4_AllocateFH(&newfh4)) != NFS4_OK)
    {
        res_OPEN4.status = rc;
        return res_OPEN4.status;
    }

    /* Building a new fh */
    if(!nfs4_FSALToFhandle(&newfh4, pnewfsal_handle, data))
    {
        res_OPEN4.status = NFS4ERR_SERVERFAULT;
        return res_OPEN4.status;
    }

    /* This new fh replaces the current FH */
    data->currentFH.nfs_fh4_len = newfh4.nfs_fh4_len;
    memcpy(data->currentFH.nfs_fh4_val, newfh4.nfs_fh4_val, newfh4.nfs_fh4_len);

    data->current_entry = pentry_newfile;
    data->current_filetype = REGULAR_FILE;

    /* No do not need newfh any more */
    Mem_Free((char *)newfh4.nfs_fh4_val);

    /* Status of parent directory after the operation */
    if((cache_status = cache_inode_getattr(pentry_parent,
                                           &attr_parent,
                                           data->ht,
                                           data->pclient,
                                           data->pcontext,
                                           &cache_status)) != CACHE_INODE_SUCCESS)
    {
        res_OPEN4.status = nfs4_Errno(cache_status);
        return res_OPEN4.status;
    }

    res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_len = 2;
    if((res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_val =
                (uint32_t *) Mem_Alloc(res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_len *
                                       sizeof(uint32_t))) == NULL)
    {
        res_OPEN4.status = NFS4ERR_SERVERFAULT;
        return res_OPEN4.status;
    }
    res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_val[0] = 0;       /* No Attributes set */
    res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_val[1] = 0;       /* No Attributes set */

    if(arg_OPEN4.openhow.opentype == OPEN4_CREATE)
    {
        tmp_int = 2;
        tmp_attr[0] = FATTR4_SIZE;
        tmp_attr[1] = FATTR4_MODE;
        nfs4_list_to_bitmap4(&(res_OPEN4.OPEN4res_u.resok4.attrset), &tmp_int, tmp_attr);
        res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_len = 2;
    }

    res_OPEN4.OPEN4res_u.resok4.cinfo.after =
        (changeid4) pentry_parent->internal_md.mod_time;
    res_OPEN4.OPEN4res_u.resok4.cinfo.atomic = TRUE;

    res_OPEN4.OPEN4res_u.resok4.stateid.seqid = powner->seqid;
    memcpy(res_OPEN4.OPEN4res_u.resok4.stateid.other, pfile_state->stateid_other, 12);

    /* No delegation */
    res_OPEN4.OPEN4res_u.resok4.delegation.delegation_type = OPEN_DELEGATE_NONE;

    res_OPEN4.OPEN4res_u.resok4.rflags = OPEN4_RESULT_LOCKTYPE_POSIX;

    /* regular exit */
    res_OPEN4.status = NFS4_OK;
    return res_OPEN4.status;
}                               /* nfs41_op_open */
Пример #10
0
int _9p_mkdir(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 *mode = NULL;
	u32 *gid = NULL;
	u16 *name_len = NULL;
	char *name_str = NULL;

	struct _9p_fid *pfid = NULL;
	struct _9p_qid qid_newdir;

	cache_entry_t *pentry_newdir = NULL;
	char dir_name[MAXNAMLEN];
	uint64_t fileid;
	cache_inode_status_t cache_status;

	/* 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, 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);
	}

	snprintf(dir_name, MAXNAMLEN, "%.*s", *name_len, name_str);

	op_ctx = &pfid->op_context;
	/* Create the directory */
	/* BUGAZOMEU: @todo : the gid parameter is not used yet */
	cache_status =
	    cache_inode_create(pfid->pentry, dir_name, DIRECTORY, *mode, NULL,
			       &pentry_newdir);
	if (pentry_newdir == 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_newdir, &fileid);

	/* put the entry:
	 * we don't want to remember it even if cache_inode_fileid fails. */
	cache_inode_put(pentry_newdir);

	if (cache_status != CACHE_INODE_SUCCESS)
		return _9p_rerror(req9p, worker_data, msgtag,
				  _9p_tools_errno(cache_status), plenout,
				  preply);

	/* Build the qid */
	qid_newdir.type = _9P_QTDIR;
	qid_newdir.version = 0;
	qid_newdir.path = 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;
}
Пример #11
0
int nfs_Mkdir(nfs_arg_t * parg,
              exportlist_t * pexport,
              fsal_op_context_t * pcontext,
              cache_inode_client_t * pclient,
              hash_table_t * ht, struct svc_req *preq, nfs_res_t * pres)
{
  static char __attribute__ ((__unused__)) funcName[] = "nfs_Mkdir";

  char *str_dir_name = NULL;
  fsal_accessmode_t mode = 0;
  cache_entry_t *dir_pentry = NULL;
  cache_entry_t *parent_pentry = NULL;
  int rc = 0;
  fsal_attrib_list_t parent_attr;
  fsal_attrib_list_t attr;
  fsal_attrib_list_t *ppre_attr;
  fsal_attrib_list_t attr_parent_after;
  cache_inode_file_type_t parent_filetype;
  fsal_handle_t *pfsal_handle;
  fsal_name_t dir_name;
  cache_inode_status_t cache_status = CACHE_INODE_SUCCESS;
  cache_inode_status_t cache_status_lookup;

  if(isDebug(COMPONENT_NFSPROTO))
    {
      char str[LEN_FH_STR];

      switch (preq->rq_vers)
        {
        case NFS_V2:
          str_dir_name = parg->arg_mkdir2.where.name;
          break;
        case NFS_V3:
          str_dir_name = parg->arg_mkdir3.where.name;
          break;
        }

      nfs_FhandleToStr(preq->rq_vers,
                       &(parg->arg_mkdir2.where.dir),
                       &(parg->arg_mkdir3.where.dir),
                       NULL,
                       str);
      LogDebug(COMPONENT_NFSPROTO,
               "REQUEST PROCESSING: Calling nfs_Mkdir handle: %s name: %s",
               str, str_dir_name);
    }

  if(preq->rq_vers == NFS_V3)
    {
      /* to avoid setting it on each error case */
      pres->res_mkdir3.MKDIR3res_u.resfail.dir_wcc.before.attributes_follow = FALSE;
      pres->res_mkdir3.MKDIR3res_u.resfail.dir_wcc.after.attributes_follow = FALSE;
      ppre_attr = NULL;
    }

  if((parent_pentry = nfs_FhandleToCache(preq->rq_vers,
                                         &(parg->arg_mkdir2.where.dir),
                                         &(parg->arg_mkdir3.where.dir),
                                         NULL,
                                         &(pres->res_dirop2.status),
                                         &(pres->res_mkdir3.status),
                                         NULL,
                                         &parent_attr,
                                         pcontext, pclient, ht, &rc)) == NULL)
    {
      /* Stale NFS FH ? */
      return rc;
    }

  /* get directory attributes before action (for V3 reply) */
  ppre_attr = &parent_attr;

  /* Extract the filetype */
  parent_filetype = cache_inode_fsal_type_convert(parent_attr.type);

  /*
   * Sanity checks: 
   */
  if(parent_filetype != DIRECTORY)
    {
      switch (preq->rq_vers)
        {
        case NFS_V2:
          pres->res_dirop2.status = NFSERR_NOTDIR;
          break;

        case NFS_V3:
          pres->res_mkdir3.status = NFS3ERR_NOTDIR;
          break;
        }

      return NFS_REQ_OK;
    }

  switch (preq->rq_vers)
    {
    case NFS_V2:
      str_dir_name = parg->arg_mkdir2.where.name;

      if(parg->arg_mkdir2.attributes.mode != (unsigned int)-1)
        {
          mode = (fsal_accessmode_t) parg->arg_mkdir2.attributes.mode;
        }
      else
        {
          mode = (fsal_accessmode_t) 0;
        }
      break;

    case NFS_V3:
      str_dir_name = parg->arg_mkdir3.where.name;

      if(parg->arg_mkdir3.attributes.mode.set_it == TRUE)
        mode = (fsal_accessmode_t) parg->arg_mkdir3.attributes.mode.set_mode3_u.mode;
      else
        mode = (fsal_accessmode_t) 0;
      break;
    }

  //if(str_dir_name == NULL || strlen(str_dir_name) == 0)
  if(str_dir_name == NULL || *str_dir_name == '\0' )
    {
      if(preq->rq_vers == NFS_V2)
        pres->res_dirop2.status = NFSERR_IO;
      if(preq->rq_vers == NFS_V3)
        pres->res_mkdir3.status = NFS3ERR_INVAL;
    }
  else
    {
      /* Make the directory */
      if((cache_status = cache_inode_error_convert(FSAL_str2name(str_dir_name,
                                                                 FSAL_MAX_NAME_LEN,
                                                                 &dir_name))) ==
         CACHE_INODE_SUCCESS)
        {
          /*
           * Lookup file to see if it exists.  If so, use it.  Otherwise
           * create a new one.  
           */
          dir_pentry = cache_inode_lookup( parent_pentry,
                                           &dir_name,
                                           pexport->cache_inode_policy,
                                           &attr,
                                           ht, 
                                           pclient, 
                                           pcontext, 
                                           &cache_status_lookup);

          if(cache_status_lookup == CACHE_INODE_NOT_FOUND)
            {
              /* Create the directory */
              if((dir_pentry = cache_inode_create(parent_pentry,
                                                  &dir_name,
                                                  DIRECTORY,
                                                  pexport->cache_inode_policy,
                                                  mode,
                                                  NULL,
                                                  &attr,
                                                  ht,
                                                  pclient,
                                                  pcontext, &cache_status)) != NULL)
                {
                  /*
                   * Get the FSAL handle for this entry 
                   */
                  pfsal_handle = cache_inode_get_fsal_handle(dir_pentry, &cache_status);

                  if(cache_status == CACHE_INODE_SUCCESS)
                    {
                      switch (preq->rq_vers)
                        {
                        case NFS_V2:
                          /* Build file handle */
                          if(!nfs2_FSALToFhandle
                             (&(pres->res_dirop2.DIROP2res_u.diropok.file), pfsal_handle,
                              pexport))
                            pres->res_dirop2.status = NFSERR_IO;
                          else
                            {
                              /*
                               * Build entry
                               * attributes 
                               */
                              if(nfs2_FSALattr_To_Fattr(pexport, &attr,
                                                        &(pres->res_dirop2.DIROP2res_u.
                                                          diropok.attributes)) == 0)
                                pres->res_dirop2.status = NFSERR_IO;
                              else
                                pres->res_dirop2.status = NFS_OK;
                            }
                          break;

                        case NFS_V3:
                          /* Build file handle */
                          if((pres->res_mkdir3.MKDIR3res_u.resok.obj.post_op_fh3_u.
                              handle.data.data_val = Mem_Alloc_Label(NFS3_FHSIZE,
                                                                     "Filehandle V3 in nfs3_mkdir")) == NULL)
                            {
                              pres->res_mkdir3.status = NFS3ERR_IO;
                              return NFS_REQ_OK;
                            }

                          if(nfs3_FSALToFhandle
                             (&pres->res_mkdir3.MKDIR3res_u.resok.obj.post_op_fh3_u.
                              handle, pfsal_handle, pexport) == 0)
                            {
                              Mem_Free((char *)pres->res_mkdir3.MKDIR3res_u.resok.obj.
                                       post_op_fh3_u.handle.data.data_val);
                              pres->res_mkdir3.status = NFS3ERR_INVAL;
                              return NFS_REQ_OK;
                            }
                          else
                            {
                              /* Set Post Op Fh3 structure */
                              pres->res_mkdir3.MKDIR3res_u.resok.obj.handle_follows =
                                  TRUE;
                              pres->res_mkdir3.MKDIR3res_u.resok.obj.post_op_fh3_u.handle.
                                  data.data_len = sizeof(file_handle_v3_t);

                              /*
                               * Build entry
                               * attributes 
                               */
                              nfs_SetPostOpAttr(pcontext, pexport,
                                                dir_pentry,
                                                &attr,
                                                &(pres->res_mkdir3.MKDIR3res_u.resok.
                                                  obj_attributes));

                              /* Get the attributes of the parent after the operation */
                              cache_inode_get_attributes(parent_pentry,
                                                         &attr_parent_after);

                              /*
                               * Build Weak Cache
                               * Coherency data 
                               */
                              nfs_SetWccData(pcontext, pexport,
                                             parent_pentry,
                                             ppre_attr,
                                             &attr_parent_after,
                                             &(pres->res_mkdir3.MKDIR3res_u.resok.
                                               dir_wcc));

                              pres->res_mkdir3.status = NFS3_OK;
                            }

                          break;
                        }
                      return NFS_REQ_OK;
                    }
                }
            }                   /* If( cache_status_lookup == CACHE_INODE_NOT_FOUND ) */
          else
            {
              /* object already exists or failure during lookup */
              if(cache_status_lookup == CACHE_INODE_SUCCESS)
                {
                  /* Trying to create a file that already exists */
                  cache_status = CACHE_INODE_ENTRY_EXISTS;

                  switch (preq->rq_vers)
                    {
                    case NFS_V2:
                      pres->res_dirop2.status = NFSERR_EXIST;
                      break;

                    case NFS_V3:
                      pres->res_mkdir3.status = NFS3ERR_EXIST;
                      break;
                    }
                }
              else
                {
                  /* Server fault */
                  cache_status = cache_status_lookup;

                  switch (preq->rq_vers)
                    {
                    case NFS_V2:
                      pres->res_dirop2.status = NFSERR_IO;
                      break;

                    case NFS_V3:
                      pres->res_mkdir3.status = NFS3ERR_INVAL;
                      break;
                    }
                }

              nfs_SetFailedStatus(pcontext, pexport,
                                  preq->rq_vers,
                                  cache_status,
                                  &pres->res_dirop2.status,
                                  &pres->res_mkdir3.status,
                                  NULL, NULL,
                                  parent_pentry,
                                  ppre_attr,
                                  &(pres->res_mkdir3.MKDIR3res_u.resfail.dir_wcc),
                                  NULL, NULL, NULL);

              return NFS_REQ_OK;
            }
        }
    }

  /* If we are here, there was an error */
  if(nfs_RetryableError(cache_status))
    {
      return NFS_REQ_DROP;

    }
  nfs_SetFailedStatus(pcontext, pexport,
                      preq->rq_vers,
                      cache_status,
                      &pres->res_dirop2.status,
                      &pres->res_mkdir3.status,
                      NULL, NULL,
                      parent_pentry,
                      ppre_attr,
                      &(pres->res_mkdir3.MKDIR3res_u.resfail.dir_wcc), NULL, NULL, NULL);

  return NFS_REQ_OK;

}