コード例 #1
0
ファイル: nfs_Mkdir.c プロジェクト: fmarsch/nfs-ganesha-1
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);
}
コード例 #2
0
ファイル: nfs_Create.c プロジェクト: ShyamsundarR/nfs-ganesha
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 */
コード例 #3
0
ファイル: nfs_Mkdir.c プロジェクト: bwelch/nfs-ganesha
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;

}