示例#1
0
int nfs4_op_link(struct nfs_argop4 *op, compound_data_t * data, struct nfs_resop4 *resp)
{
  char __attribute__ ((__unused__)) funcname[] = "nfs4_op_link";

  cache_entry_t        * dir_pentry = NULL;
  cache_entry_t        * file_pentry = NULL;
  cache_inode_status_t   cache_status;
  fsal_attrib_list_t     attr;
  fsal_name_t            newname;

  resp->resop = NFS4_OP_LINK;
  res_LINK4.status = NFS4_OK;

  /* Do basic checks on a filehandle */
  res_LINK4.status = nfs4_sanity_check_FH(data, 0LL);
  if(res_LINK4.status != NFS4_OK)
    return res_LINK4.status;

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

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

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

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

  /* If data->exportp is null, a junction from pseudo fs was traversed, credp and exportp have to be updated */
  if(data->pexport == NULL)
    {
      res_LINK4.status = nfs4_SetCompoundExport(data);
      if(res_LINK4.status != NFS4_OK)
        return res_LINK4.status;
    }

  /*
   * This operation creates a hard link, for the file represented by the saved FH, in directory represented by currentFH under the 
   * name arg_LINK4.target 
   */

  /* Crossing device is not allowed */
  if(((file_handle_v4_t *) (data->currentFH.nfs_fh4_val))->exportid !=
     ((file_handle_v4_t *) (data->savedFH.nfs_fh4_val))->exportid)
    {
      res_LINK4.status = NFS4ERR_XDEV;
      return res_LINK4.status;
    }

  /* If name is empty, return EINVAL */
  if(arg_LINK4.newname.utf8string_len == 0)
    {
      res_LINK4.status = NFS4ERR_INVAL;
      return res_LINK4.status;
    }

  /* Check for name to long */
  if(arg_LINK4.newname.utf8string_len > FSAL_MAX_NAME_LEN)
    {
      res_LINK4.status = NFS4ERR_NAMETOOLONG;
      return res_LINK4.status;
    }

  /* Convert the UFT8 objname to a regular string */
  if((cache_status =
      cache_inode_error_convert(FSAL_buffdesc2name
                                ((fsal_buffdesc_t *) & arg_LINK4.newname,
                                 &newname))) != CACHE_INODE_SUCCESS)
    {
      res_LINK4.status = nfs4_Errno(cache_status);
      return res_LINK4.status;
    }

  /* Sanity check: never create a link named '.' or '..' */
  if(!FSAL_namecmp(&newname, (fsal_name_t *) & FSAL_DOT)
     || !FSAL_namecmp(&newname, (fsal_name_t *) & FSAL_DOT_DOT))
    {
      res_LINK4.status = NFS4ERR_BADNAME;
      return res_LINK4.status;
    }

  /* get info from compound data */
  dir_pentry = data->current_entry;

  /* Destination FH (the currentFH) must be a directory */
  if(data->current_filetype != DIRECTORY)
    {
      res_LINK4.status = NFS4ERR_NOTDIR;
      return res_LINK4.status;
    }

  /* Target object (the savedFH) must not be a directory */
  if(data->saved_filetype == DIRECTORY)
    {
      res_LINK4.status = NFS4ERR_ISDIR;
      return res_LINK4.status;
    }

  /* We have to keep track of the 'change' file attribute for reply structure */
  if((cache_status = cache_inode_getattr(dir_pentry,
                                         &attr,
                                         data->pcontext,
                                         &cache_status)) != CACHE_INODE_SUCCESS)
    {
      res_LINK4.status = nfs4_Errno(cache_status);
      return res_LINK4.status;
    }
  res_LINK4.LINK4res_u.resok4.cinfo.before
       = cache_inode_get_changeid4(dir_pentry);

  /* Convert savedFH into a vnode */
  file_pentry = data->saved_entry;

  /* make the link */
  if(cache_inode_link(file_pentry,
                      dir_pentry,
                      &newname,
                      &attr,
                      data->pcontext, &cache_status) != CACHE_INODE_SUCCESS)
    {
      res_LINK4.status = nfs4_Errno(cache_status);
      return res_LINK4.status;
    }

  res_LINK4.LINK4res_u.resok4.cinfo.after
       = cache_inode_get_changeid4(dir_pentry);
  res_LINK4.LINK4res_u.resok4.cinfo.atomic = FALSE;

  res_LINK4.status = NFS4_OK;
  return NFS4_OK;
}                               /* nfs4_op_link */
示例#2
0
int nfs4_op_putfh(struct nfs_argop4 *op, compound_data_t * data, struct nfs_resop4 *resp)
{
  int rc;
  int error;
  fsal_attrib_list_t attr;
  char outstr[1024];

  char __attribute__ ((__unused__)) funcname[] = "nfs4_op_putfh";

  resp->resop = NFS4_OP_PUTFH;
  res_PUTFH4.status = NFS4_OK;

  /* If there is no FH */
  if(nfs4_Is_Fh_Empty(&(arg_PUTFH4.object)))
    {
      res_PUTFH4.status = NFS4ERR_NOFILEHANDLE;
      return res_PUTFH4.status;
    }

  /* If the filehandle is invalid */
  if(nfs4_Is_Fh_Invalid(&(arg_PUTFH4.object)))
    {
      res_PUTFH4.status = NFS4ERR_BADHANDLE;
      return res_PUTFH4.status;
    }

  /* Tests if teh Filehandle is expired (for volatile filehandle) */
  if(nfs4_Is_Fh_Expired(&(arg_PUTFH4.object)))
    {
      res_PUTFH4.status = NFS4ERR_FHEXPIRED;
      return res_PUTFH4.status;
    }

  /* If no currentFH were set, allocate one */
  if(data->currentFH.nfs_fh4_len == 0)
    {
      if((error = nfs4_AllocateFH(&(data->currentFH))) != NFS4_OK)
        {
          res_PUTFH4.status = error;
          return res_PUTFH4.status;
        }
    }

  /* The same is to be done with mounted_on_FH */
  if(data->mounted_on_FH.nfs_fh4_len == 0)
    {
      if((error = nfs4_AllocateFH(&(data->mounted_on_FH))) != NFS4_OK)
        {
          res_PUTFH4.status = error;
          return res_PUTFH4.status;
        }
    }

  /* Copy the filehandle from the reply structure */
  data->currentFH.nfs_fh4_len = arg_PUTFH4.object.nfs_fh4_len;
  data->mounted_on_FH.nfs_fh4_len = arg_PUTFH4.object.nfs_fh4_len;

  /* Put the data in place */
  memcpy(data->currentFH.nfs_fh4_val, arg_PUTFH4.object.nfs_fh4_val,
         arg_PUTFH4.object.nfs_fh4_len);
  memcpy(data->mounted_on_FH.nfs_fh4_val, arg_PUTFH4.object.nfs_fh4_val,
         arg_PUTFH4.object.nfs_fh4_len);

  nfs4_sprint_fhandle(&arg_PUTFH4.object, outstr);
  LogDebug(COMPONENT_NFS_V4, "NFS4_OP_PUTFH CURRENTFH BEFORE: File handle = %s", outstr);

  /* If the filehandle is not pseudo hs file handle, get the entry related to it, otherwise use fake values */
  if(nfs4_Is_Fh_Pseudo(&(data->currentFH)))
    {
      data->current_entry = NULL;
      data->current_filetype = DIR_BEGINNING;
      data->pexport = NULL;     /* No exportlist is related to pseudo fs */
    }
  else
    {
      /* If data->exportp is null, a junction from pseudo fs was traversed, credp and exportp have to be updated */
      if(data->pexport == NULL)
        {
          if((error = nfs4_SetCompoundExport(data)) != NFS4_OK)
            {
              res_PUTFH4.status = error;
              return res_PUTFH4.status;
            }
        }

      /* Build the pentry */
      if((data->current_entry = nfs_FhandleToCache(NFS_V4,
                                                   NULL,
                                                   NULL,
                                                   &(data->currentFH),
                                                   NULL,
                                                   NULL,
                                                   &(res_PUTFH4.status),
                                                   &attr,
                                                   data->pcontext,
                                                   data->pclient, data->ht, &rc)) == NULL)
        {
          res_PUTFH4.status = NFS4ERR_BADHANDLE;
          return res_PUTFH4.status;
        }

      /* Extract the filetype */
      data->current_filetype = cache_inode_fsal_type_convert(attr.type);

    }

  /* Trace */

  return NFS4_OK;
}                               /* nfs4_op_putfh */
int nfs4_op_restorefh(struct nfs_argop4 *op,
                      compound_data_t * data, struct nfs_resop4 *resp)
{
  char __attribute__ ((__unused__)) funcname[] = "nfs4_op_restorefh";

  /* First of all, set the reply to zero to make sure it contains no
     parasite information */
  memset(resp, 0, sizeof(struct nfs_resop4));

  resp->resop = NFS4_OP_RESTOREFH;
  res_RESTOREFH.status = NFS4_OK;

  /* If there is no currentFH, teh return an error */
  if(nfs4_Is_Fh_Empty(&(data->savedFH)))
    {
      /* There is no current FH, return NFS4ERR_RESTOREFH (cg RFC3530,
         page 202) */
      res_RESTOREFH.status = NFS4ERR_RESTOREFH;
      return res_RESTOREFH.status;
    }

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

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

  /* If data->exportp is null, a junction from pseudo fs was
     traversed, credp and exportp have to be updated */
  if(data->pexport == NULL)
    {
      res_RESTOREFH.status = nfs4_SetCompoundExport(data);
      if(res_RESTOREFH.status != NFS4_OK)
        {
          LogCrit(COMPONENT_NFS_V4,
                  "Error %d in nfs4_SetCompoundExport", res_RESTOREFH.status);
          return res_RESTOREFH.status;
        }
    }

  /* Copy the data from current FH to saved FH */
  memcpy(data->currentFH.nfs_fh4_val,
         data->savedFH.nfs_fh4_val,
         data->savedFH.nfs_fh4_len);

  data->currentFH.nfs_fh4_len = data->savedFH.nfs_fh4_len;

  /* If current and saved entry are identical, get no references and
     make no changes. */

  if (data->current_entry == data->saved_entry) {
      goto out;
  }

  if (data->current_entry) {
      cache_inode_put(data->current_entry);
      data->current_entry = NULL;
  }

  data->current_entry = data->saved_entry;
  data->current_filetype = data->saved_filetype;

  /* Take another reference.  As of now the filehandle is both saved
     and current and both must be counted.  Protect in case of
     pseudofs handle. */

  if (data->current_entry) {
       if (cache_inode_lru_ref(data->current_entry,
                               LRU_FLAG_NONE) != CACHE_INODE_SUCCESS) {
            resp->nfs_resop4_u.opgetfh.status = NFS4ERR_STALE;
            data->current_entry = NULL;
            return resp->nfs_resop4_u.opgetfh.status;
       }
  }

 out:

  if(isFullDebug(COMPONENT_NFS_V4))
    {
      char str[LEN_FH_STR];
      sprint_fhandle4(str, &data->currentFH);
      LogFullDebug(COMPONENT_NFS_V4,
                   "RESTORE FH: Current FH %s", str);
    }


  return NFS4_OK;
}                               /* nfs4_op_restorefh */
示例#4
0
int nfs4_op_lookupp(struct nfs_argop4 *op,
                    compound_data_t * data, struct nfs_resop4 *resp)
{
  fsal_name_t name;
  cache_entry_t *dir_pentry = NULL;
  cache_entry_t *file_pentry = NULL;
  fsal_attrib_list_t attrlookup;
  cache_inode_status_t cache_status;
  int error = 0;
  fsal_handle_t *pfsal_handle = NULL;

  char __attribute__ ((__unused__)) funcname[] = "nfs4_op_lookupp";

  resp->resop = NFS4_OP_LOOKUPP;
  resp->nfs_resop4_u.oplookupp.status = NFS4_OK;

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

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

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

  /* looking up for parent directory from ROOTFH return NFS4ERR_NOENT (RFC3530, page 166) */
  if(data->currentFH.nfs_fh4_len == data->rootFH.nfs_fh4_len
     && memcmp(data->currentFH.nfs_fh4_val, data->rootFH.nfs_fh4_val,
               data->currentFH.nfs_fh4_len) == 0)
    {
      /* Nothing to do, just reply with success */
      res_LOOKUPP4.status = NFS4ERR_NOENT;
      return res_LOOKUPP4.status;
    }

  /* If in pseudoFS, proceed with pseudoFS specific functions */
  if(nfs4_Is_Fh_Pseudo(&(data->currentFH)))
    return nfs4_op_lookupp_pseudo(op, data, resp);

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

  /* If data->exportp is null, a junction from pseudo fs was traversed, credp and exportp have to be updated */
  if(data->pexport == NULL)
    {
      if((error = nfs4_SetCompoundExport(data)) != NFS4_OK)
        {
          res_LOOKUPP4.status = error;
          return res_LOOKUPP4.status;
        }
    }

  /* Preparying for cache_inode_lookup ".." */
  file_pentry = NULL;
  dir_pentry = data->current_entry;
  name = FSAL_DOT_DOT;

  /* BUGAZOMEU: Faire la gestion des cross junction traverse */
  if((file_pentry = cache_inode_lookup(dir_pentry,
                                       &name,
                                       data->pexport->cache_inode_policy,
                                       &attrlookup,
                                       data->ht,
                                       data->pclient,
                                       data->pcontext, &cache_status)) != NULL)
    {
      /* Extract the fsal attributes from the cache inode pentry */
      pfsal_handle = cache_inode_get_fsal_handle(file_pentry, &cache_status);
      if(cache_status != CACHE_INODE_SUCCESS)
        {
          res_LOOKUPP4.status = NFS4ERR_SERVERFAULT;
          return res_LOOKUPP4.status;
        }

      /* Convert it to a file handle */
      if(!nfs4_FSALToFhandle(&data->currentFH, pfsal_handle, data))
        {
          res_LOOKUPP4.status = NFS4ERR_SERVERFAULT;
          return res_LOOKUPP4.status;
        }

      /* Copy this to the mounted on FH (if no junction is traversed */
      memcpy((char *)(data->mounted_on_FH.nfs_fh4_val),
             (char *)(data->currentFH.nfs_fh4_val), data->currentFH.nfs_fh4_len);
      data->mounted_on_FH.nfs_fh4_len = data->currentFH.nfs_fh4_len;

      /* Keep the pointer within the compound data */
      data->current_entry = file_pentry;
      data->current_filetype = file_pentry->internal_md.type;

      /* Return successfully */
      res_LOOKUPP4.status = NFS4_OK;
      return NFS4_OK;

    }

  /* If the part of the code is reached, then something wrong occured in the lookup process, status is not HPSS_E_NOERROR 
   * and contains the code for the error */

  /* If NFS4ERR_SYMLINK should be returned for a symlink instead of ENOTDIR */
  if((cache_status == CACHE_INODE_NOT_A_DIRECTORY) &&
     (dir_pentry->internal_md.type == SYMBOLIC_LINK))
    res_LOOKUPP4.status = NFS4ERR_SYMLINK;
  else
    res_LOOKUPP4.status = nfs4_Errno(cache_status);

  return res_LOOKUPP4.status;
}                               /* nfs4_op_lookupp */