Beispiel #1
0
/**
 * FSAL_link:
 * Create a hardlink.
 *
 * \param exttarget (input):
 *        Handle of the target object.
 * \param extdir (input):
 *        Pointer to the directory handle where
 *        the hardlink is to be created.
 * \param link_name (input):
 *        Pointer to the name of the hardlink to be created.
 * \param extcontext (input):
 *        Authentication context for the operation (user,...).
 * \param accessmode (input):
 *        Mode for the directory to be created.
 *        (the umask defined into the FSAL configuration file
 *        will be applied on it).
 * \param attributes (optionnal input/output):
 *        The post_operation attributes of the linked object.
 *        As input, it defines the attributes that the caller
 *        wants to retrieve (by positioning flags into this structure)
 *        and the output is built considering this input
 *        (it fills the structure according to the flags it contains).
 *        May be NULL.
 *
 * \return Major error codes :
 *        - ERR_FSAL_NO_ERROR     (no error)
 *        - ERR_FSAL_STALE        (target or dir does not address an existing object)
 *        - ERR_FSAL_FAULT        (a NULL pointer was passed as mandatory argument)
 *        - Other error codes can be returned :
 *          ERR_FSAL_ACCESS, ERR_FSAL_EXIST, ERR_FSAL_IO, ...
 *
 *        NB: if getting postop attributes failed,
 *        the function does not return an error
 *        but the FSAL_ATTR_RDATTR_ERR bit is set in
 *        the attributes->asked_attributes field.
 */
fsal_status_t CEPHFSAL_link(fsal_handle_t * exttarget,
                            fsal_handle_t * extdir,
                            fsal_name_t * link_name,
                            fsal_op_context_t * extcontext,
                            fsal_attrib_list_t * attributes)
{
  int rc;
  struct stat st;
  char strname[FSAL_MAX_NAME_LEN];
  cephfsal_handle_t* target = (cephfsal_handle_t*) exttarget;
  cephfsal_handle_t* dir = (cephfsal_handle_t*) extdir;
  cephfsal_op_context_t* context = (cephfsal_op_context_t*) context;
  struct ceph_mount_info *cmount = context->export_context->cmount;
  int uid = FSAL_OP_CONTEXT_TO_UID(context);
  int gid = FSAL_OP_CONTEXT_TO_GID(context);

  /* sanity checks.
   * note : attributes is optional.
   */
  if(!target || !dir || !context || !link_name)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_link);

  memset(target, 0, sizeof(cephfsal_handle_t));

  /* Tests if hardlinking is allowed by configuration. */

  if(!global_fs_info.link_support)
    Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_link);

  FSAL_name2str(link_name, strname, FSAL_MAX_NAME_LEN);

  TakeTokenFSCall();
  rc = ceph_ll_link(cmount, VINODE(target), VINODE(dir), strname, &st,
                    uid, gid);
  ReleaseTokenFSCall();

  if (rc < 0)
    Return(posix2fsal_error(rc), 0, INDEX_FSAL_link);

  if(attributes)
    {
      fsal_status_t status;
      status = posix2fsal_attributes(&st, attributes);
      if(FSAL_IS_ERROR(status))
        {
          FSAL_CLEAR_MASK(attributes->asked_attributes);
          FSAL_SET_MASK(attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
          Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_link);
        }
    }

  /* OK */
  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_link);
}
Beispiel #2
0
fsal_status_t FSAL_rename_access_default(fsal_op_context_t  * pcontext,  /* IN */
                                         fsal_attrib_list_t * pattrsrc,  /* IN */
                                         fsal_attrib_list_t * pattrdest, /* IN */
					 fsal_attrib_list_t * pattrobj)  /* IN */
{
	fsal_status_t fsal_status;

	if(!pcontext || !pattrsrc || !pattrdest || !pattrobj)
		Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_rename_access);

	/* Sticky Bit on the parent directory? */
	if(pattrsrc->mode & FSAL_MODE_SVTX)
	{
          /* The user must own the file or the parent directory. */
	  if(    ( pattrsrc->owner != FSAL_OP_CONTEXT_TO_UID(pcontext) )
              || ( pattrobj->owner != FSAL_OP_CONTEXT_TO_UID(pcontext) ) )
		  Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_rename_access);
	}

	/* Sticky Bit on the destination directory? */
	if(pattrdest->mode & FSAL_MODE_SVTX)
	{
          /* The user must own the file or the destination directory. */
	  if(    ( pattrdest->owner != FSAL_OP_CONTEXT_TO_UID(pcontext) )
              || ( pattrobj->owner != FSAL_OP_CONTEXT_TO_UID(pcontext) ) )
		  Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_rename_access);
	}

	/* The user must be able to lookup and write the parent directory. */
	fsal_status = FSAL_test_access_default(pcontext, ( FSAL_W_OK | FSAL_X_OK ), pattrsrc);
	if(FSAL_IS_ERROR(fsal_status))
		Return(fsal_status.major, fsal_status.minor, INDEX_FSAL_rename_access);

	/* The user must be able to lookup and write the destination directory. */
	fsal_status = FSAL_test_access_default(pcontext, ( FSAL_W_OK | FSAL_X_OK ), pattrdest);
	if(FSAL_IS_ERROR(fsal_status))
		Return(fsal_status.major, fsal_status.minor, INDEX_FSAL_rename_access);

	/* If this point is reached, then access is granted */
	Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_rename_access);
}                               /* FSAL_rename_access */
Beispiel #3
0
/**
 * FSAL_opendir :
 *     Opens a directory for reading its content.
 *
 * \param exthandle (input)
 *         the handle of the directory to be opened.
 * \param extcontext (input)
 *         Permission context for the operation (user, export context...).
 * \param extdescriptor (output)
 *         pointer to an allocated structure that will receive
 *         directory stream informations, on successfull completion.
 * \param attributes (optional output)
 *         On successfull completion,the structure pointed
 *         by dir_attributes receives the new directory attributes.
 *         Can be NULL.
 *
 * \return Major error codes :
 *        - ERR_FSAL_NO_ERROR     (no error)
 *        - ERR_FSAL_ACCESS       (user does not have read permission on directory)
 *        - ERR_FSAL_STALE        (exthandle does not address an existing object)
 *        - ERR_FSAL_FAULT        (a NULL pointer was passed as mandatory argument)
 *        - Other error codes can be returned :
 *          ERR_FSAL_IO, ...
 */
fsal_status_t CEPHFSAL_opendir(fsal_handle_t * exthandle,
                               fsal_op_context_t * extcontext,
                               fsal_dir_t * extdescriptor,
                               fsal_attrib_list_t * dir_attributes)
{
  cephfsal_handle_t* handle = (cephfsal_handle_t*) exthandle;
  cephfsal_op_context_t* context = (cephfsal_op_context_t*) extcontext;
  cephfsal_dir_t* descriptor = (cephfsal_dir_t*) extdescriptor;
  fsal_status_t status;
  int rc;
  int uid = FSAL_OP_CONTEXT_TO_UID(context);
  int gid = FSAL_OP_CONTEXT_TO_GID(context);
  struct ceph_dir_result *dh;

  /* sanity checks
   * note : dir_attributes is optional.
   */
  if(!handle || !context || !descriptor)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_opendir);

  TakeTokenFSCall();
  /* XXX ceph_ll_opendir has void in the interface, but Client::ll_opendir
   * is using dir_result_t. */
  rc = ceph_ll_opendir(context->export_context->cmount, VINODE(handle),
                       (void *) &dh, uid, gid);
  ReleaseTokenFSCall();

  if (rc < 0)
    Return(posix2fsal_error(rc), 0, INDEX_FSAL_opendir);

  descriptor->dh = dh;
  descriptor->vi = VINODE(handle);
  descriptor->ctx = *context;

  if(dir_attributes)
    {
      status = CEPHFSAL_getattrs(exthandle, extcontext, dir_attributes);

      if(FSAL_IS_ERROR(status))
        {
          FSAL_CLEAR_MASK(dir_attributes->asked_attributes);
          FSAL_SET_MASK(dir_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
        }
    }

  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_opendir);
}
Beispiel #4
0
/**
 * FSAL_getattrs:
 * Get attributes for the object specified by its filehandle.
 *
 * \param filehandle (input):
 *        The handle of the object to get parameters.
 * \param context (input):
 *        Authentication context for the operation (user, export...).
 * \param object_attributes (mandatory input/output):
 *        The retrieved attributes for the object.
 *        As input, it defines the attributes that the caller
 *        wants to retrieve (by positioning flags into this structure)
 *        and the output is built considering this input
 *        (it fills the structure according to the flags it contains).
 *
 * \return Major error codes :
 *        - ERR_FSAL_NO_ERROR     (no error)
 *        - ERR_FSAL_STALE        (object_handle does not address an existing object)
 *        - ERR_FSAL_FAULT        (a NULL pointer was passed as mandatory argument) 
 *        - Another error code if an error occured.
 */
fsal_status_t CEPHFSAL_getattrs(fsal_handle_t * exthandle,
                                fsal_op_context_t * extcontext,
                                fsal_attrib_list_t * object_attributes)
{
  int rc;
  struct stat st;
  fsal_status_t status;
  cephfsal_handle_t* filehandle = (cephfsal_handle_t*) exthandle;
  cephfsal_op_context_t* context = (cephfsal_op_context_t*) extcontext;
  int uid = FSAL_OP_CONTEXT_TO_UID(context);
  int gid = FSAL_OP_CONTEXT_TO_GID(context);

  /* sanity checks.
   * note : object_attributes is mandatory in FSAL_getattrs.
   */
  if(!filehandle || !context || !object_attributes)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_getattrs);

  TakeTokenFSCall();

  rc = ceph_ll_getattr(context->export_context->cmount, VINODE(filehandle),
                       &st, uid, gid);

  ReleaseTokenFSCall();

  if (rc < 0)
    Return(posix2fsal_error(rc), 0, INDEX_FSAL_getattrs);

  /* convert attributes */
  status = posix2fsal_attributes(&st, object_attributes);
  if(FSAL_IS_ERROR(status))
    {
      FSAL_CLEAR_MASK(object_attributes->asked_attributes);
      FSAL_SET_MASK(object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
      Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_getattrs);
    }

  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_getattrs);
}
Beispiel #5
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 */
Beispiel #6
0
/**
 * FSAL_lookup :
 * Looks up for an object into a directory.
 *
 * Note : if parent handle and filename are NULL,
 *        this retrieves root's handle.
 *
 * \param parent_directory_handle (input)
 *        Handle of the parent directory to search the object in.
 * \param filename (input)
 *        The name of the object to find.
 * \param p_context (input)
 *        Authentication context for the operation (user,...).
 * \param object_handle (output)
 *        The handle of the object corresponding to filename.
 * \param object_attributes (optional input/output)
 *        Pointer to the attributes of the object we found.
 *        As input, it defines the attributes that the caller
 *        wants to retrieve (by positioning flags into this structure)
 *        and the output is built considering this input
 *        (it fills the structure according to the flags it contains).
 *        It can be NULL (increases performances).
 *
 * \return Major error codes :
 *        - ERR_FSAL_NO_ERROR     (no error)
 *        - ERR_FSAL_STALE        (parent_directory_handle does not address an existing object)
 *        - ERR_FSAL_NOTDIR       (parent_directory_handle does not address a directory)
 *        - ERR_FSAL_NOENT        (the object designated by p_filename does not exist)
 *        - ERR_FSAL_XDEV         (tried to operate a lookup on a filesystem junction.
 *                                 Use FSAL_lookupJunction instead)
 *        - ERR_FSAL_FAULT        (a NULL pointer was passed as mandatory argument)
 *        - Other error codes can be returned :
 *          ERR_FSAL_ACCESS, ERR_FSAL_IO, ...
 *
 */
fsal_status_t CEPHFSAL_lookup(fsal_handle_t * extparent,
                              fsal_name_t * filename,
                              fsal_op_context_t * extcontext,
                              fsal_handle_t * exthandle,
                              fsal_attrib_list_t * object_attributes)
{
  int rc;
  struct stat st;
  fsal_status_t status;
  cephfsal_handle_t* parent = (cephfsal_handle_t*) extparent;
  cephfsal_op_context_t* context = (cephfsal_op_context_t*) extcontext;
  cephfsal_handle_t* handle = (cephfsal_handle_t*) exthandle;
  char str[FSAL_MAX_NAME_LEN+1];
  struct ceph_mount_info *cmount = context->export_context->cmount;

  /* sanity checks
   * note : object_attributes is optionnal
   *        parent_directory_handle may be null for getting FS root.
   */
  if(!handle || !context)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lookup);

  memset(handle, 0, sizeof(cephfsal_handle_t));

  /* retrieves root handle */

  if(!parent)
    {
      /* check that filename is NULL,
       * else, parent should not
       * be NULL.
       */
      if(filename != NULL)
        Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lookup);

      /* Ceph seems to have a constant identifying the root inode.
	 Possible source of bugs, so check here if trouble */

      VINODE(handle).ino.val = CEPH_INO_ROOT;
      VINODE(handle).snapid.val = CEPH_NOSNAP;

      if(object_attributes)
        {
          status = CEPHFSAL_getattrs(exthandle, extcontext, object_attributes);

          if(FSAL_IS_ERROR(status))
            {
              FSAL_CLEAR_MASK(object_attributes->asked_attributes);
              FSAL_SET_MASK(object_attributes->asked_attributes,
                            FSAL_ATTR_RDATTR_ERR);
            }
        }
    }
  else                          /* this is a real lookup(parent, name)  */
    {
      /* the filename should not be null */
      if(filename == NULL)
        Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lookup);

      FSAL_name2str(filename, str, FSAL_MAX_NAME_LEN);

      /* Ceph returns POSIX errors, so let's use them */

      rc = ceph_ll_lookup(cmount,
                          VINODE(parent), str, &st,
                          FSAL_OP_CONTEXT_TO_UID(context),
                          FSAL_OP_CONTEXT_TO_GID(context));

      if(rc)
        {
          Return(posix2fsal_error(rc), 0, INDEX_FSAL_lookup);
        }

      rc = stat2fsal_fh(cmount, &st, handle);

      if (rc < 0)
        Return(posix2fsal_error(rc), 0, INDEX_FSAL_create);

      if(object_attributes)
        {
          /* convert attributes */
          status = posix2fsal_attributes(&st, object_attributes);
          if(FSAL_IS_ERROR(status))
            {
              FSAL_CLEAR_MASK(object_attributes->asked_attributes);
              FSAL_SET_MASK(object_attributes->asked_attributes,
                            FSAL_ATTR_RDATTR_ERR);
              Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_lookup);
            }
        }
    }

  /* lookup complete ! */
  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_lookup);

}
Beispiel #7
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 */
Beispiel #8
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);
}
Beispiel #9
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 */
Beispiel #10
0
/**
 * FSAL_test_access_default :
 * Tests whether the user identified by the p_context structure
 * can access the object as indicated by the access_type parameter.
 * This function tests access rights using cached attributes
 * given as parameter (no calls to filesystem).
 * Thus, it cannot test FSAL_F_OK flag, and asking such a flag
 * will result in a ERR_FSAL_INVAL error.
 *
 * \param p_context (input):
 *        Authentication context for the operation (user,...).
 * \param access_type (input):
 *        Indicates the permissions to test.
 *        This is an inclusive OR of the permissions
 *        to be checked for the user identified by cred.
 *        Permissions constants are :
 *        - FSAL_R_OK : test for read permission
 *        - FSAL_W_OK : test for write permission
 *        - FSAL_X_OK : test for exec permission
 *        - FSAL_F_OK : test for file existence
 * \param object_attributes (mandatory input):
 *        The cached attributes for the object to test rights on.
 *        The following attributes MUST be filled :
 *        owner, group, mode, ACLs.
 *
 * \return Major error codes :
 *        - ERR_FSAL_NO_ERROR     (no error, permission granted)
 *        - ERR_FSAL_ACCESS       (object permissions doesn't fit asked access type)
 *        - ERR_FSAL_INVAL        (FSAL_test_access is not able to test such a permission)
 *        - ERR_FSAL_FAULT        (a NULL pointer was passed as mandatory argument)
 *        - Another error code if an error occured.
 */
fsal_status_t FSAL_test_access_default(fsal_op_context_t  * p_context,        /* IN */
                                       fsal_accessflags_t   access_type,      /* IN */
                                       fsal_attrib_list_t * object_attributes /* IN */
    )
{
  fsal_accessflags_t missing_access;
  int is_grp;
  fsal_count_t i;
  gid_t * alt_groups;
  fsal_count_t nb_alt_groups;

  /* sanity checks. */

  if(!object_attributes || !p_context)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_test_access);

  /* If the FSAL_F_OK flag is set, returns ERR INVAL */

  if(access_type & FSAL_F_OK)
    Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_test_access);

  /* ----- here is a code sample for this function ---- */

  /* test root access */

  if(FSAL_OP_CONTEXT_TO_UID(p_context) == 0)
    Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_test_access);

  /* unsatisfied permissions */

  missing_access = access_type;

  /* Test if file belongs to user. */

  if(FSAL_OP_CONTEXT_TO_UID(p_context) == object_attributes->owner)
    {

      if(object_attributes->mode & FSAL_MODE_RUSR)
        missing_access &= ~FSAL_R_OK;

      if(object_attributes->mode & FSAL_MODE_WUSR)
        missing_access &= ~FSAL_W_OK;

      if(object_attributes->mode & FSAL_MODE_XUSR)
        missing_access &= ~FSAL_X_OK;

      if(missing_access == 0)
        Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_test_access);
      else
        Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_test_access);

    }

  /* Test if the file belongs to user's group. */

  is_grp = (FSAL_OP_CONTEXT_TO_GID(p_context) == object_attributes->group);

  if(!is_grp && FSAL_OP_CONTEXT_TO_ALT_GROUPS(p_context) != NULL)
    {
      nb_alt_groups = FSAL_OP_CONTEXT_TO_NBGROUPS(p_context);
      alt_groups = FSAL_OP_CONTEXT_TO_ALT_GROUPS(p_context);

      /* Test if file belongs to user's alt groups */
      for(i = 0; i < nb_alt_groups; i++)
      {
        is_grp = (alt_groups[i] == object_attributes->group);
        if(is_grp)
          break;
      }
    }

  /* finally apply group rights */

  if(is_grp)
    {
      if(object_attributes->mode & FSAL_MODE_RGRP)
        missing_access &= ~FSAL_R_OK;

      if(object_attributes->mode & FSAL_MODE_WGRP)
        missing_access &= ~FSAL_W_OK;

      if(object_attributes->mode & FSAL_MODE_XGRP)
        missing_access &= ~FSAL_X_OK;

      if(missing_access == 0)
        Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_test_access);
      else
        Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_test_access);

    }

  /* test other perms */

  if(object_attributes->mode & FSAL_MODE_ROTH)
    missing_access &= ~FSAL_R_OK;

  if(object_attributes->mode & FSAL_MODE_WOTH)
    missing_access &= ~FSAL_W_OK;

  if(object_attributes->mode & FSAL_MODE_XOTH)
    missing_access &= ~FSAL_X_OK;

  /** @todo: ACLs. */

  if(missing_access == 0)
    Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_test_access);
  else
    Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_test_access);

}
Beispiel #11
0
/**
 * FSAL_test_setattr_access_default :
 * test if a client identified by cred can access setattr on the object
 * knowing its attributes and parent's attributes.
 * The following fields of the object_attributes structures MUST be filled :
 * acls (if supported), mode, owner, group.
 * This doesn't make any call to the filesystem,
 * as a result, this doesn't ensure that the file exists, nor that
 * the permissions given as parameters are the actual file permissions :
 * this must be ensured by the cache_inode layer, using FSAL_getattrs,
 * for example.
 *
 * \param cred (in zfsfsal_cred_t *) user's identifier.
 * \param candidate_attributes the attributes we want to set on the object
 * \param object_attributes (in fsal_attrib_list_t *) the cached attributes
 *        for the object.
 *
 * \return Major error codes :
 *        - ERR_FSAL_NO_ERROR     (no error)
 *        - ERR_FSAL_ACCESS       (Permission denied)
 *        - ERR_FSAL_FAULT        (null pointer parameter)
 *        - ERR_FSAL_INVAL        (missing attributes : mode, group, user,...)
 *        - ERR_FSAL_SERVERFAULT  (unexpected error)
 */
fsal_status_t FSAL_setattr_access_default(fsal_op_context_t  * p_context,            /* IN */
                                          fsal_attrib_list_t * candidate_attributes, /* IN */
                                          fsal_attrib_list_t * object_attributes     /* IN */
    )
{
	fsal_status_t fsal_status;

	int in_grp;
	int i;
	fsal_count_t nb_alt_groups;
	gid_t * alt_groups;

	in_grp = 0;

	/*
	 * CHMOD
	 * */

	/* We just ignore symlinks. */
	if(FSAL_TEST_MASK(candidate_attributes->asked_attributes, FSAL_ATTR_MODE) 
	   && (object_attributes->type != FSAL_TYPE_LNK))
	{
		/* User must be root or owner of the file */
		if( (FSAL_OP_CONTEXT_TO_UID(p_context) != 0) 
		    && (FSAL_OP_CONTEXT_TO_UID(p_context) =! object_attributes->owner) )
			Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_setattr_access);
	}

	/*
	 * CHOWN
	 * */

	if(FSAL_TEST_MASK(candidate_attributes->asked_attributes, FSAL_ATTR_OWNER))
	{
		/* User must be root or (be the owner and the user he wants to set) */
		if( (FSAL_OP_CONTEXT_TO_UID(p_context) != 0) 
		    && ( ( FSAL_OP_CONTEXT_TO_UID(p_context) != object_attributes->owner ) 
		    	   || ( FSAL_OP_CONTEXT_TO_UID(p_context) != candidate_attributes->owner ) ) )
			Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_setattr_access);
	}

	if(FSAL_TEST_MASK(candidate_attributes->asked_attributes, FSAL_ATTR_GROUP))
	{
		/* User must ( be root or owner ) */
		if( (FSAL_OP_CONTEXT_TO_UID(p_context) != 0) && (FSAL_OP_CONTEXT_TO_UID(p_context) != object_attributes->owner) )
			Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_setattr_access);

		/* He must also be in the group he wants to set */
		in_grp = ( FSAL_OP_CONTEXT_TO_GID(p_context) == candidate_attributes->group );
		
		if(!in_grp && FSAL_OP_CONTEXT_TO_ALT_GROUPS(p_context) != NULL)
		{
			nb_alt_groups = FSAL_OP_CONTEXT_TO_NBGROUPS(p_context);
			alt_groups = FSAL_OP_CONTEXT_TO_ALT_GROUPS(p_context);

			/* Test user's alt groups */
			for(i = 0; i < nb_alt_groups; i++)
			{
				in_grp = (alt_groups[i] == object_attributes->group);
				if(in_grp)
					break;
			}
		}

		if(!in_grp)
			Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_setattr_access);

	}

	/* 
	 * UTIME 
	 * */

	/* Is it allowed to change time? */
	if(FSAL_TEST_MASK(candidate_attributes->asked_attributes, 
                          FSAL_ATTR_ATIME | FSAL_ATTR_CREATION | FSAL_ATTR_CTIME | FSAL_ATTR_MTIME)
	   && !global_fs_info.cansettime)
		Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_setattr_access);

	/* Atime: user must be owner or be root or have read access */
	if( FSAL_TEST_MASK(candidate_attributes->asked_attributes, FSAL_ATTR_ATIME)
	    && (FSAL_OP_CONTEXT_TO_UID(p_context) != 0)
	    && (FSAL_OP_CONTEXT_TO_UID(p_context) != object_attributes->owner))
	{
		fsal_status = FSAL_test_access_default(p_context, FSAL_R_OK, object_attributes);
		if(FSAL_IS_ERROR(fsal_status))
			Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_setattr_access);
	}

	/* Mtime: user must be owner or be root or have write access */
	if( FSAL_TEST_MASK(candidate_attributes->asked_attributes, FSAL_ATTR_MTIME)
	    && (FSAL_OP_CONTEXT_TO_UID(p_context) != 0)
	    && (FSAL_OP_CONTEXT_TO_UID(p_context) != object_attributes->owner))
	{
		fsal_status = FSAL_test_access_default(p_context, FSAL_W_OK, object_attributes);
		if(FSAL_IS_ERROR(fsal_status))
			Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_setattr_access);
	}

	/* If this point is reached, then access is granted. */
	Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_setattr_access);
}                               /* FSAL_test_setattr_access */
Beispiel #12
0
/**
 *
 * MFSL_mkdir : posts an asynchronous mkdir and sets the cached attributes in return.
 *
 * Posts an asynchronous setattr and sets the cached attributes in return.
 * If an object is not asynchronous, then the content of object attributes structure for result will be used to populate it.
 *
 * @param target_handle     [IN]    mfsl object to be operated on (object to be hard linked).
 * @param dir_handle        [IN]    mfsl object to be operated on (destination directory for the link).
 * @param p_context         [IN]    associated fsal context
 * @param p_mfsl_context    [INOUT] associated mfsl context
 * @param attrib_set        [IN]    attributes to be set 
 * @param tgt_attributes    [INOUT] resulting attributes for target
 * @param dir_attributes    [INOUT] resulting attributes for directory 
 *
 * @return the same as FSAL_link
 */
fsal_status_t MFSL_mkdir(mfsl_object_t * parent_directory_handle,       /* IN */
                         fsal_name_t * p_dirname,       /* IN */
                         fsal_op_context_t * p_context, /* IN */
                         mfsl_context_t * p_mfsl_context,       /* IN */
                         fsal_accessmode_t accessmode,  /* IN */
                         mfsl_object_t * object_handle, /* OUT */
                         fsal_attrib_list_t * object_attributes,        /* [ IN/OUT ] */
                         fsal_attrib_list_t * parent_attributes /* IN */ )
{
  fsal_status_t fsal_status;
  mfsl_async_op_desc_t *pasyncopdesc = NULL;
  mfsl_object_specific_data_t *newdir_pasyncdata = NULL;
  mfsl_object_t *pnewdir_handle = NULL;
  mfsl_precreated_object_t *pprecreated = NULL;

  fsal_status = MFSAL_mkdir_check_perms(parent_directory_handle,
                                        p_dirname,
                                        p_context, p_mfsl_context, parent_attributes);

  if(FSAL_IS_ERROR(fsal_status))
    return fsal_status;

  P(p_mfsl_context->lock);

  GetFromPool(pasyncopdesc, &p_mfsl_context->pool_async_op, mfsl_async_op_desc_t);

  GetFromPool(newdir_pasyncdata, &p_mfsl_context->pool_spec_data, mfsl_object_specific_data_t);

  V(p_mfsl_context->lock);

  if(pasyncopdesc == NULL)
    MFSL_return(ERR_FSAL_INVAL, 0);

  if(gettimeofday(&pasyncopdesc->op_time, NULL) != 0)
    {
      /* Could'not get time of day... Stopping, this may need a major failure */
      LogMajor(COMPONENT_MFSL, "MFSL_link: cannot get time of day... exiting");
      exit(1);
    }

  /* Now get a pre-allocated directory from the synclet data */
  P(p_mfsl_context->lock);
  GetFromPool(pprecreated, &p_mfsl_context->pool_dirs, mfsl_precreated_object_t);
  V(p_mfsl_context->lock);

  pnewdir_handle = &(pprecreated->mobject);

  LogDebug(COMPONENT_MFSL,  "Creating asyncop %p",
                    pasyncopdesc);

  pasyncopdesc->op_type = MFSL_ASYNC_OP_MKDIR;
  pasyncopdesc->op_args.mkdir.pmfsl_obj_dirdest = parent_directory_handle;
  pasyncopdesc->op_args.mkdir.precreate_name = pprecreated->name;
  pasyncopdesc->op_args.mkdir.dirname = *p_dirname;
  pasyncopdesc->op_args.mkdir.mode = accessmode;
  pasyncopdesc->op_args.mkdir.owner = FSAL_OP_CONTEXT_TO_UID(p_context);
  pasyncopdesc->op_args.mkdir.group = FSAL_OP_CONTEXT_TO_GID(p_context);
  pasyncopdesc->op_res.mkdir.attr.asked_attributes = object_attributes->asked_attributes;
  pasyncopdesc->op_res.mkdir.attr.supported_attributes =
      object_attributes->supported_attributes;

  if(FSAL_IS_ERROR(fsal_status))
    return fsal_status;

  pasyncopdesc->op_func = MFSL_mkdir_async_op;
  //pasyncopdesc->fsal_op_context = p_context ;
  pasyncopdesc->fsal_op_context =
      synclet_data[pasyncopdesc->related_synclet_index].root_fsal_context;

  pasyncopdesc->ptr_mfsl_context = (caddr_t) p_mfsl_context;

  fsal_status = MFSL_async_post(pasyncopdesc);
  if(FSAL_IS_ERROR(fsal_status))
    return fsal_status;

  /* Update the asynchronous metadata */
  newdir_pasyncdata->async_attr = pprecreated->attr;

  newdir_pasyncdata->async_attr.type = FSAL_TYPE_DIR;
  newdir_pasyncdata->async_attr.filesize = DEV_BSIZE;
  newdir_pasyncdata->async_attr.spaceused = DEV_BSIZE;
  newdir_pasyncdata->async_attr.numlinks = 2;

  newdir_pasyncdata->async_attr.owner = pasyncopdesc->op_args.mkdir.owner;
  newdir_pasyncdata->async_attr.group = pasyncopdesc->op_args.mkdir.group;

  newdir_pasyncdata->async_attr.ctime.seconds = pasyncopdesc->op_time.tv_sec;
  newdir_pasyncdata->async_attr.ctime.nseconds = pasyncopdesc->op_time.tv_usec;  /** @todo: there may be a coefficient to be applied here */

  newdir_pasyncdata->deleted = FALSE;

  if(!mfsl_async_set_specdata(pnewdir_handle, newdir_pasyncdata))
    MFSL_return(ERR_FSAL_SERVERFAULT, 0);

  /* Return the correct attributes */
  *object_attributes = newdir_pasyncdata->async_attr;
  *object_handle = pprecreated->mobject;
  object_handle->health = MFSL_ASYNC_NEVER_SYNCED;

  /* Do not forget that the parent directory becomes asynchronous too */
  parent_directory_handle->health = MFSL_ASYNC_ASYNCHRONOUS;

  MFSL_return(ERR_FSAL_NO_ERROR, 0);
}                               /* MFSL_mkdir */
Beispiel #13
0
fsal_status_t CEPHFSAL_setattrs(fsal_handle_t * exthandle,
                                fsal_op_context_t * extcontext,
                                fsal_attrib_list_t * attrib_set,
                                fsal_attrib_list_t * object_attributes)
{
  cephfsal_handle_t* filehandle = (cephfsal_handle_t*) exthandle;
  cephfsal_op_context_t* context = (cephfsal_op_context_t*) extcontext;
  struct stat st;
  fsal_attrib_list_t attrs;
  int rc, mask=0;
  int uid = FSAL_OP_CONTEXT_TO_UID(context);
  int gid = FSAL_OP_CONTEXT_TO_GID(context);

  /* sanity checks.
   * note : object_attributes is optional.
   */
  if(!filehandle || !context || !attrib_set)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_setattrs);

  /* local copy of attributes */
  attrs = *attrib_set;

  /* First, check that FSAL attributes changes are allowed. */

  /* Is it allowed to change times ? */

  if(!global_fs_info.cansettime)
    {
      if(attrs.asked_attributes &
         (FSAL_ATTR_ATIME |
          FSAL_ATTR_CREATION |
          FSAL_ATTR_CTIME |
          FSAL_ATTR_MTIME))
        {

          /* handled as an unsettable attribute. */
          Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_setattrs);
        }

    }

  /* apply umask, if mode attribute is to be changed */

  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MODE))
    {
      attrs.mode &= (~global_fs_info.umask);
    }

  /* Build flags and struct stat */

  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MODE))
    {
      mask |= CEPH_SETATTR_MODE;
      st.st_mode = fsal2unix_mode(attrs.mode);
    }
  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_OWNER))
    {
      mask |= CEPH_SETATTR_UID;
      st.st_uid = attrs.owner;
    }
  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_GROUP))
    {
      mask |= CEPH_SETATTR_UID;
      st.st_gid = attrs.group;
    }
  if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_ATIME))
    {
      mask |= CEPH_SETATTR_ATIME;
      st.st_atime = attrs.atime.seconds;
    }
  if (FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MTIME))
    {
      mask |= CEPH_SETATTR_MTIME;
      st.st_mtime = attrs.mtime.seconds;
    }
  if (FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_CTIME))
    {
      mask |= CEPH_SETATTR_CTIME;
      st.st_ctime = attrs.ctime.seconds;
    }

  TakeTokenFSCall();

  rc = ceph_ll_setattr(context->export_context->cmount, VINODE(filehandle),
                       &st, mask, uid, gid);

  ReleaseTokenFSCall();

  if (rc < 0)
    Return(posix2fsal_error(rc), 0, INDEX_FSAL_getattrs);

  if(object_attributes)
    {
      fsal_status_t status;
      status = CEPHFSAL_getattrs(exthandle, extcontext, object_attributes);

      /* on error, we set a special bit in the mask. */
      if(FSAL_IS_ERROR(status))
        {
          FSAL_CLEAR_MASK(object_attributes->asked_attributes);
          FSAL_SET_MASK(object_attributes->asked_attributes,
                        FSAL_ATTR_RDATTR_ERR);
        }

    }

  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_setattrs);
}
Beispiel #14
0
fsal_status_t CEPHFSAL_rename(fsal_handle_t * extold_parent,
                              fsal_name_t * old_name,
                              fsal_handle_t * extnew_parent,
                              fsal_name_t * new_name,
                              fsal_op_context_t * extcontext,
                              fsal_attrib_list_t * src_dir_attributes,
                              fsal_attrib_list_t * tgt_dir_attributes)
{
  int rc;
  cephfsal_handle_t* old_parent = (cephfsal_handle_t*) extold_parent;
  cephfsal_handle_t* new_parent = (cephfsal_handle_t*) extnew_parent;
  cephfsal_op_context_t* context = (cephfsal_op_context_t*) extcontext;
  char oldstr[FSAL_MAX_NAME_LEN+1];
  char newstr[FSAL_MAX_NAME_LEN+1];
  int uid = FSAL_OP_CONTEXT_TO_UID(context);
  int gid = FSAL_OP_CONTEXT_TO_GID(context);

  /* sanity checks.
   * note : src/tgt_dir_attributes are optional.
   */
  if(!old_parent || !new_parent || !old_name || !new_name || !context)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_rename);

  if(src_dir_attributes)
    {
      fsal_status_t status =
        CEPHFSAL_getattrs(extold_parent, extcontext, src_dir_attributes);

      if(FSAL_IS_ERROR(status))
        {
          FSAL_CLEAR_MASK(src_dir_attributes->asked_attributes);
          FSAL_SET_MASK(src_dir_attributes->asked_attributes,
                        FSAL_ATTR_RDATTR_ERR);
        }
    }

  if(tgt_dir_attributes)
    {
      fsal_status_t status;

      /* optimization when src=tgt : */

      if(!CEPHFSAL_handlecmp(extold_parent, extnew_parent, &status)
         && src_dir_attributes)
        {
          /* If source dir = target dir, we just copy the attributes.
           * to avoid doing another getattr.
           */
          (*tgt_dir_attributes) = (*src_dir_attributes);
        }
      else
        {
          status = CEPHFSAL_getattrs(extnew_parent, extcontext,
                                     tgt_dir_attributes);

          if(FSAL_IS_ERROR(status))
            {
              FSAL_CLEAR_MASK(tgt_dir_attributes->asked_attributes);
              FSAL_SET_MASK(tgt_dir_attributes->asked_attributes,
                            FSAL_ATTR_RDATTR_ERR);
            }
        }
    }

  FSAL_name2str(old_name, oldstr, FSAL_MAX_NAME_LEN);
  FSAL_name2str(new_name, newstr, FSAL_MAX_NAME_LEN);
  rc = ceph_ll_rename(context->export_context->cmount,
                      VINODE(old_parent), oldstr,
                      VINODE(new_parent), newstr,
                      uid, gid);

  if (rc < 0)
    Return(posix2fsal_error(rc), 0, INDEX_FSAL_rename);

  /* OK */
  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_rename);
}
Beispiel #15
0
/**
 * FSAL_create:
 * Create a regular file.
 *
 * \param extparent (input):
 *        Handle of the parent directory where the file is to be created.
 * \param filename (input):
 *        Pointer to the name of the file to be created.
 * \param context (input):
 *        Authentication context for the operation (user, export...).
 * \param accessmode (input):
 *        Mode for the file to be created.
 *        (the umask defined into the FSAL configuration file
 *        will be applied on it).
 * \param object_handle (output):
 *        Pointer to the handle of the created file.
 * \param object_attributes (optionnal input/output):
 *        The postop attributes of the created file.
 *        As input, it defines the attributes that the caller
 *        wants to retrieve (by positioning flags into this structure)
 *        and the output is built considering this input
 *        (it fills the structure according to the flags it contains).
 *        Can be NULL.
 *
 * \return Major error codes :
 *        - ERR_FSAL_NO_ERROR     (no error)
 *        - ERR_FSAL_STALE        (parent_directory_handle does not address an existing object)
 *        - ERR_FSAL_FAULT        (a NULL pointer was passed as mandatory argument)
 *        - Other error codes can be returned :
 *          ERR_FSAL_ACCESS, ERR_FSAL_EXIST, ERR_FSAL_IO, ...
 *
 *        NB: if getting postop attributes failed,
 *        the function does not return an error
 *        but the FSAL_ATTR_RDATTR_ERR bit is set in
 *        the object_attributes->asked_attributes field.
 */
fsal_status_t CEPHFSAL_create(fsal_handle_t * extparent,
                              fsal_name_t * filename,
                              fsal_op_context_t * extcontext,
                              fsal_accessmode_t accessmode,
                              fsal_handle_t * object_handle,
                              fsal_attrib_list_t * object_attributes)
{
  int rc;
  mode_t mode;
  struct Fh *fd;
  struct stat st;
  char strname[FSAL_MAX_NAME_LEN];
  cephfsal_handle_t* parent = (cephfsal_handle_t*) extparent;
  cephfsal_op_context_t* context = (cephfsal_op_context_t*) extcontext;
  struct ceph_mount_info *cmount = context->export_context->cmount;
  int uid = FSAL_OP_CONTEXT_TO_UID(context);
  int gid = FSAL_OP_CONTEXT_TO_GID(context);

  /* sanity checks.
   * note : object_attributes is optional.
   */
  if(!parent || !context || !object_handle || !filename)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_create);

  memset(object_handle, 0, sizeof(cephfsal_handle_t));

  mode = fsal2unix_mode(accessmode);
  mode = mode & ~global_fs_info.umask;

  FSAL_name2str(filename, strname, FSAL_MAX_NAME_LEN);

  TakeTokenFSCall();

  rc = ceph_ll_create(cmount, VINODE(parent), strname,
                      mode, 0, &fd, &st, uid, gid);
  ceph_ll_close(cmount, fd);

  ReleaseTokenFSCall();

  if (rc < 0)
    Return(posix2fsal_error(rc), 0, INDEX_FSAL_create);

  rc = stat2fsal_fh(cmount,
                    &st,
                    (cephfsal_handle_t*) object_handle);

  if (rc < 0)
    Return(posix2fsal_error(rc), 0, INDEX_FSAL_create);

  if(object_attributes)
    {
      fsal_status_t status;
      status = posix2fsal_attributes(&st, object_attributes);
      if(FSAL_IS_ERROR(status))
        {
          FSAL_CLEAR_MASK(object_attributes->asked_attributes);
          FSAL_SET_MASK(object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
          Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_create);
        }
    }

  /* OK */
  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_create);
}