Пример #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);
}
Пример #2
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);
}
Пример #3
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);
}
Пример #4
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);

}
Пример #5
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);

}
Пример #6
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 */
Пример #7
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 */
Пример #8
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);
}
Пример #9
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);
}
Пример #10
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);
}