Example #1
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);
}
Example #2
0
fsal_status_t tank_remove_extattr_by_name(struct fsal_obj_handle *obj_hdl,
					  const char *xattr_name)
{
	struct zfs_fsal_obj_handle *obj_handle = NULL;
	int retval = 0;
	creden_t cred;

	obj_handle =
	    container_of(obj_hdl, struct zfs_fsal_obj_handle, obj_handle);

	cred.uid = op_ctx->creds->caller_uid;
	cred.gid = op_ctx->creds->caller_gid;

	retval = libzfswrap_removexattr(ZFSFSAL_GetVFS(obj_handle->handle),
					&cred,
					obj_handle->handle->zfs_handle,
					xattr_name);
	if (retval != 0)
		return fsalstat(posix2fsal_error(retval), retval);
	return fsalstat(ERR_FSAL_NO_ERROR, 0);

}
Example #3
0
static int xattr_id_to_name(libzfswrap_vfs_t *p_vfs, creden_t *pcred,
			    inogen_t object, unsigned int xattr_id, char *name)
{
	unsigned int index;
	unsigned int curr_idx;
	char names[MAXPATHLEN], *ptr;
	size_t namesize;
	size_t len = 0;
	int retval = 0;

	if (xattr_id < XATTR_COUNT)
		return ERR_FSAL_INVAL;

	index = xattr_id - XATTR_COUNT;

	/* get xattrs */

	retval =
	    libzfswrap_listxattr(p_vfs, pcred, object, (char **)&names,
				 &namesize);
	if (retval)
		return posix2fsal_error(retval);

	if (namesize == 0)
		return ERR_FSAL_NOENT;

	errno = 0;

	for (ptr = names, curr_idx = 0;
	     ptr < names + namesize;
	     curr_idx++, ptr += len + 1) {
		len = strlen(ptr);
		if (curr_idx == index) {
			strcpy(name, ptr);
			return ERR_FSAL_NO_ERROR;
		}
	}
	return ERR_FSAL_NOENT;
}
Example #4
0
/** @fn fsal_status_t
 *	GPFSFSAL_write(int fd, uint64_t offset, size_t buf_size, caddr_t buf,
 *		       size_t *write_amount, bool *fsal_stable,
 *		       const struct req_op_context *op_ctx)
 *  @brief Perform a write operation on an opened file.
 *
 *  @param fd The file descriptor returned by FSAL_open.
 *  @param buf_size Amount (in bytes) of data to be written.
 *  @param buf Address where the data is in memory.
 *  @param write_amount Pointer to the amount of data (in bytes) that have been written
 *        during this call.
 *
 * @return ERR_FSAL_NO_ERROR on success, error otherwise
 */
fsal_status_t
GPFSFSAL_write(int fd, uint64_t offset, size_t buf_size, caddr_t buf,
	       size_t *write_amount, bool *fsal_stable,
	       const struct req_op_context *op_ctx, int expfd)
{
	struct write_arg warg = {0};
	uint32_t stability_got = 0;
	ssize_t nb_write;
	int errsv;

	/* sanity checks. */
	if (!buf || !write_amount)
		return fsalstat(ERR_FSAL_FAULT, 0);

	warg.mountdirfd = expfd;
	warg.fd = fd;
	warg.bufP = buf;
	warg.offset = offset;
	warg.length = buf_size;
	warg.stability_wanted = *fsal_stable;
	warg.stability_got = &stability_got;
	warg.options = 0;

	fsal_set_credentials(op_ctx->creds);
	nb_write = gpfs_ganesha(OPENHANDLE_WRITE_BY_FD, &warg);
	errsv = errno;
	fsal_restore_ganesha_credentials();

	if (nb_write == -1) {
		if (errsv == EUNATCH)
			LogFatal(COMPONENT_FSAL, "GPFS Returned EUNATCH");
		return fsalstat(posix2fsal_error(errsv), errsv);
	}

	*write_amount = nb_write;
	*fsal_stable = (stability_got) ? true : false;

	return fsalstat(ERR_FSAL_NO_ERROR, 0);
}
Example #5
0
static fsal_status_t getxattrs(struct fsal_obj_handle *obj_hdl,
				xattrname4 *xa_name,
				xattrvalue4 *xa_value)
{
	int rc;
	int errsv;
	struct getxattr_arg gxarg;
	struct gpfs_fsal_obj_handle *myself;
	struct gpfs_filesystem *gpfs_fs = obj_hdl->fs->private_data;

	myself = container_of(obj_hdl, struct gpfs_fsal_obj_handle,
				obj_handle);

	gxarg.mountdirfd = gpfs_fs->root_fd;
	gxarg.handle = myself->handle;
	gxarg.name_len = xa_name->utf8string_len;
	gxarg.name = xa_name->utf8string_val;
	gxarg.value_len = xa_value->utf8string_len;
	gxarg.value = xa_value->utf8string_val;

	rc = gpfs_ganesha(OPENHANDLE_GETXATTRS, &gxarg);
	if (rc < 0) {
		errsv = errno;
		LogDebug(COMPONENT_FSAL,
			"GETXATTRS returned rc %d errsv %d", rc, errsv);

		if (errsv == ERANGE)
			return fsalstat(ERR_FSAL_TOOSMALL, 0);
		if (errsv == ENODATA)
			return fsalstat(ERR_FSAL_NOENT, 0);
		return fsalstat(posix2fsal_error(errsv), errsv);
	}
	LogDebug(COMPONENT_FSAL,
		"GETXATTRS returned value %.*s len %d rc %d",
		gxarg.value_len, (char *)gxarg.value, gxarg.value_len, rc);

	xa_value->utf8string_len = gxarg.value_len;
	return fsalstat(ERR_FSAL_NO_ERROR, 0);
}
Example #6
0
static fsal_status_t makedir(struct fsal_obj_handle *dir_hdl,
			     const char *name, struct attrlist *attrib,
			     struct fsal_obj_handle **handle)
{
	fsal_errors_t fsal_error = ERR_FSAL_NO_ERROR;
	int retval = 0;
	struct pt_fsal_obj_handle *hdl;
	fsal_status_t status;
	ptfsal_handle_t *fh = alloca(sizeof(ptfsal_handle_t));

	*handle = NULL;		/* poison it */
	if (!dir_hdl->ops->handle_is(dir_hdl, DIRECTORY)) {
		LogCrit(COMPONENT_FSAL,
			"Parent handle is not a directory. hdl = 0x%p",
			dir_hdl);
		return fsalstat(ERR_FSAL_NOTDIR, 0);
	}
	memset(fh, 0, sizeof(ptfsal_handle_t));
	fh->data.handle.handle_size = FSI_CCL_PERSISTENT_HANDLE_N_BYTES;

	attrib->mask =
	    op_ctx->fsal_export->ops->fs_supported_attrs(op_ctx->fsal_export);
	status = PTFSAL_mkdir(dir_hdl, name, op_ctx, attrib->mode, fh, attrib);
	if (FSAL_IS_ERROR(status))
		return status;

	/* allocate an obj_handle and fill it up */
	hdl = alloc_handle(fh, attrib, NULL, NULL, NULL, op_ctx->fsal_export);
	if (hdl == NULL) {
		retval = ENOMEM;
		goto fileerr;
	}
	*handle = &hdl->obj_handle;
	return fsalstat(ERR_FSAL_NO_ERROR, 0);

 fileerr:
	fsal_error = posix2fsal_error(retval);
	return fsalstat(fsal_error, retval);
}
Example #7
0
/**
 * FSAL_dynamic_fsinfo:
 * Return dynamic filesystem info such as
 * used size, free size, number of objects...
 *
 * \param filehandle (input):
 *        Handle of an object in the filesystem
 *        whom info is to be retrieved.
 * \param cred (input):
 *        Authentication context for the operation (user,...).
 * \param dynamicinfo (output):
 *        Pointer to the static info of the filesystem.
 *
 * \return Major error codes:
 *      - ERR_FSAL_NO_ERROR: no error.
 *      - ERR_FSAL_FAULT: NULL pointer passed as input parameter.
 *      - ERR_FSAL_SERVERFAULT: Unexpected error.
 */
fsal_status_t LUSTREFSAL_dynamic_fsinfo(fsal_handle_t * p_filehandle,     /* IN */
                                        fsal_op_context_t * p_context,    /* IN */
                                        fsal_dynamicfsinfo_t * p_dynamicinfo    /* OUT */
    )
{
  fsal_path_t pathfsal;
  fsal_status_t status;
  struct statvfs buffstatvfs;
  int rc, errsv;
  /* sanity checks. */
  if(!p_filehandle || !p_dynamicinfo || !p_context)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_dynamic_fsinfo);

  status = fsal_internal_Handle2FidPath(p_context, p_filehandle, &pathfsal);
  if(FSAL_IS_ERROR(status))
    Return(status.major, status.minor, INDEX_FSAL_dynamic_fsinfo);

  TakeTokenFSCall();
  rc = statvfs(pathfsal.path, &buffstatvfs);
  errsv = errno;
  ReleaseTokenFSCall();
  if(rc)
    Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_dynamic_fsinfo);

  p_dynamicinfo->total_bytes = buffstatvfs.f_frsize * buffstatvfs.f_blocks;
  p_dynamicinfo->free_bytes = buffstatvfs.f_frsize * buffstatvfs.f_bfree;
  p_dynamicinfo->avail_bytes = buffstatvfs.f_frsize * buffstatvfs.f_bavail;

  p_dynamicinfo->total_files = buffstatvfs.f_files;
  p_dynamicinfo->free_files = buffstatvfs.f_ffree;
  p_dynamicinfo->avail_files = buffstatvfs.f_favail;

  p_dynamicinfo->time_delta.seconds = 1;
  p_dynamicinfo->time_delta.nseconds = 0;

  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_dynamic_fsinfo);

}
Example #8
0
fsal_status_t ZFSFSAL_close(fsal_file_t * file_desc  /* IN */
    )
{
  int rc = 0;
  zfsfsal_file_t * file_descriptor = (zfsfsal_file_t *)file_desc;

  /* sanity checks. */
  if(!file_descriptor)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_close);

  TakeTokenFSCall();

  if(!file_descriptor->is_closed)
  {
    /* Test that the vfs still exist */
    ZFSFSAL_VFS_RDLock();
    libzfswrap_vfs_t *p_vfs = ZFSFSAL_GetVFS(&file_descriptor->handle);
    if(!p_vfs)
    {
      ZFSFSAL_VFS_Unlock();
      ReleaseTokenFSCall();
      Return(ERR_FSAL_NOENT, 0, INDEX_FSAL_close);
    }

    rc = libzfswrap_close(p_vfs, &file_descriptor->cred, file_descriptor->p_vnode,
                          file_descriptor->flags);
    ZFSFSAL_VFS_Unlock();
    file_descriptor->is_closed = 1;
  }

  ReleaseTokenFSCall();

  if(rc)
    Return(posix2fsal_error(rc), rc, INDEX_FSAL_close);

  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_close);

}
Example #9
0
fsal_status_t gpfs_seek(struct fsal_obj_handle *obj_hdl,
				struct io_info *info)
{
	struct fseek_arg arg;
	struct gpfs_fsal_obj_handle *myself;
	fsal_errors_t fsal_error = ERR_FSAL_NO_ERROR;
	struct gpfs_io_info io_info;
	int retval = 0;

	myself = container_of(obj_hdl, struct gpfs_fsal_obj_handle, obj_handle);

	assert(myself->u.file.fd >= 0
	       && myself->u.file.openflags != FSAL_O_CLOSED);

	arg.mountdirfd = myself->u.file.fd;
	arg.openfd = myself->u.file.fd;
	arg.info = &io_info;
	io_info.io_offset = info->io_content.hole.di_offset;
	if (info->io_content.what == NFS4_CONTENT_DATA)
		io_info.io_what = SEEK_DATA;
	else if (info->io_content.what == NFS4_CONTENT_HOLE)
		io_info.io_what = SEEK_HOLE;
	else
		return fsalstat(ERR_FSAL_UNION_NOTSUPP, 0);

	retval = gpfs_ganesha(OPENHANDLE_SEEK_BY_FD, &arg);
	if (retval == -1) {
		retval = errno;
		if (retval == EUNATCH)
			LogFatal(COMPONENT_FSAL, "GPFS Returned EUNATCH");
		fsal_error = posix2fsal_error(retval);
	} else {
		info->io_eof = io_info.io_eof;
		info->io_content.hole.di_offset = io_info.io_offset;
		info->io_content.hole.di_length = io_info.io_len;
	}
	return fsalstat(fsal_error, 0);
}
Example #10
0
fsal_status_t XFSFSAL_check_quota( char              * path,  /* IN */
                                   fsal_quota_type_t   quota_type,
                                   fsal_uid_t          fsal_uid)      /* IN */
{
  struct dqblk fs_quota;
  char fs_spec[MAXPATHLEN];
  
  if(!path )
    ReturnCode(ERR_FSAL_FAULT, 0);

  if(fsal_internal_path2fsname( path, fs_spec) == -1)
    ReturnCode(ERR_FSAL_INVAL, 0);

  if( fsal_uid == 0 ) /* No quota for root */
    ReturnCode(ERR_FSAL_NO_ERROR, 0) ;
  
  memset((char *)&fs_quota, 0, sizeof(struct dqblk));

  if(quotactl(FSAL_QCMD(Q_GETQUOTA, USRQUOTA), fs_spec, fsal_uid, (caddr_t) & fs_quota) < 0 )
    ReturnCode(posix2fsal_error(errno), errno);
  
  switch( quota_type )
   {
        case FSAL_QUOTA_BLOCKS:
          if( fs_quota.dqb_curspace > fs_quota.dqb_bhardlimit )
            ReturnCode( ERR_FSAL_DQUOT, EDQUOT ) ;
          
          break ;

        case FSAL_QUOTA_INODES:
          if( fs_quota.dqb_curinodes > fs_quota.dqb_ihardlimit )
            ReturnCode( ERR_FSAL_DQUOT, EDQUOT ) ;
          
          break ;
   } /* switch( quota_type ) */
 
  ReturnCode(ERR_FSAL_NO_ERROR, 0) ;
} /* XFSFSAL_check_quota */
Example #11
0
/**
 * VFSFSAL_getattrs:
 * Get attributes for the object specified by its filehandle.
 *
 * \param filehandle (input):
 *        The handle of the object to get parameters.
 * \param cred (input):
 *        Authentication context for the operation (user,...).
 * \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)
 *        - Another error code if an error occured.
 */
fsal_status_t VFSFSAL_getattrs(fsal_handle_t * p_filehandle,       /* IN */
                            fsal_op_context_t * p_context,      /* IN */
                            fsal_attrib_list_t * p_object_attributes    /* IN/OUT */
    )
{
  fsal_status_t st;
  int rc = 0 ;
  int errsv;
  struct stat buffstat;

  /* sanity checks.
   * note : object_attributes is mandatory in VFSFSAL_getattrs.
   */
  if(!p_filehandle || !p_context || !p_object_attributes)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_getattrs);

  TakeTokenFSCall();
  rc = vfs_stat_by_handle( ((vfsfsal_op_context_t *)p_context)->export_context->mount_root_fd,
                           &((vfsfsal_handle_t *)p_filehandle)->data.vfs_handle,
                           &buffstat ) ;
  errsv = errno;
  ReleaseTokenFSCall();

  if( rc == -1 )
    Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_getattrs);

  /* convert attributes */
  st = posix2fsal_attributes(&buffstat, p_object_attributes);
  if(FSAL_IS_ERROR(st))
    {
      FSAL_CLEAR_MASK(p_object_attributes->asked_attributes);
      FSAL_SET_MASK(p_object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
      ReturnStatus(st, INDEX_FSAL_getattrs);
    }

  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_getattrs);

}
Example #12
0
fsal_status_t fsal_internal_get_handle_at(int dfd,      /* IN */
                                          const char *name,     /* IN */
                                          fsal_handle_t *p_handle      /* OUT
                                                                         */ )
{
  int errsrv = 0 ;

  if( !name || !p_handle )
    ReturnCode(ERR_FSAL_FAULT, 0);

  memset(p_handle, 0, sizeof(vfsfsal_handle_t));

  LogFullDebug(COMPONENT_FSAL, "get handle at for %s", name);

  ((vfsfsal_handle_t *)p_handle)->data.vfs_handle.handle_bytes = VFS_HANDLE_LEN ;
  if( vfs_name_by_handle_at( dfd, name, &((vfsfsal_handle_t *)p_handle)->data.vfs_handle ) != 0 )
   {
      errsrv = errno;
      ReturnCode(posix2fsal_error(errsrv), errsrv);
   }

  ReturnCode(ERR_FSAL_NO_ERROR, 0);
} /* fsal_internal_get_handle_at */
Example #13
0
/**
 *  Removes a xattr by Name
 *
 * \param p_objecthandle Handle of the object you want to get attribute for.
 * \param p_context pointer to the current security context.
 * \param xattr_name xattr's name
 */
fsal_status_t ZFSFSAL_RemoveXAttrByName(fsal_handle_t * obj_handle,    /* IN */
                                     fsal_op_context_t * p_context,     /* IN */
                                     const fsal_name_t * xattr_name)    /* IN */
{
  int rc;
  creden_t cred;
  zfsfsal_handle_t * p_objecthandle = (zfsfsal_handle_t *)obj_handle;

  /* Hook to prevent any modification in the snapshots */
  if(p_objecthandle->data.i_snap != 0)
    Return(ERR_FSAL_ROFS, 0, INDEX_FSAL_SetXAttrValue);
  cred.uid = p_context->credential.user;
  cred.gid = p_context->credential.group;

  TakeTokenFSCall();
  rc = libzfswrap_removexattr(((zfsfsal_op_context_t *)p_context)->export_context->p_vfs, &cred,
                              p_objecthandle->data.zfs_handle, xattr_name->name);
  ReleaseTokenFSCall();

  if(rc)
    Return(posix2fsal_error(rc), 0, INDEX_FSAL_SetXAttrValue);
  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_SetXAttrValue);
}
Example #14
0
static fsal_status_t lustre_linkfile(struct fsal_obj_handle *obj_hdl,
				     struct fsal_obj_handle *destdir_hdl,
				     const char *name)
{
	struct lustre_fsal_obj_handle *myself, *destdir;
	char srcpath[MAXPATHLEN];
	char destdirpath[MAXPATHLEN];
	char destnamepath[MAXPATHLEN];
	int rc = 0;
	fsal_errors_t fsal_error = ERR_FSAL_NO_ERROR;

	if (!op_ctx->fsal_export->ops->
	    fs_supports(op_ctx->fsal_export, fso_link_support)) {
		fsal_error = ERR_FSAL_NOTSUPP;
		goto out;
	}
	myself =
	    container_of(obj_hdl, struct lustre_fsal_obj_handle, obj_handle);
	lustre_handle_to_path(obj_hdl->fs->path,
			      myself->handle, srcpath);

	destdir =
	    container_of(destdir_hdl, struct lustre_fsal_obj_handle,
			 obj_handle);
	lustre_handle_to_path(obj_hdl->fs->path,
			      destdir->handle, destdirpath);

	snprintf(destnamepath, MAXPATHLEN, "%s/%s", destdirpath, name);

	rc = CRED_WRAP(op_ctx->creds, int, link, srcpath, destnamepath);
	if (rc == -1) {
		rc = errno;
		fsal_error = posix2fsal_error(rc);
	}
 out:
	return fsalstat(fsal_error, rc);
}
Example #15
0
/** @fn fsal_status_t
 *	GPFSFSAL_alloc(int fd, uint64_t offset, uint64_t length, bool allocate)
 *  @brief Perform a de/allocc operation on an opened file.
 *  @param fd The file descriptor returned by FSAL_open.
 *  @param offset Offset
 *  @param length Length
 *  @param allocate Allocate
 *
 *  @return ERR_FSAL_NO_ERROR on success, error otherwise
 */
fsal_status_t
GPFSFSAL_alloc(int fd, uint64_t offset, uint64_t length, bool allocate)
{
	struct alloc_arg aarg = {0};
	int errsv;
	int rc;

	aarg.fd = fd;
	aarg.offset = offset;
	aarg.length = length;
	aarg.options = (allocate) ? IO_ALLOCATE : IO_DEALLOCATE;

	fsal_set_credentials(op_ctx->creds);
	rc = gpfs_ganesha(OPENHANDLE_ALLOCATE_BY_FD, &aarg);
	errsv = errno;
	fsal_restore_ganesha_credentials();

	if (rc == -1) {
		if (errsv == EUNATCH)
			LogFatal(COMPONENT_FSAL, "GPFS Returned EUNATCH");
		return fsalstat(posix2fsal_error(errsv), errsv);
	}
	return fsalstat(ERR_FSAL_NO_ERROR, 0);
}
Example #16
0
/**
 * FSAL_dynamic_fsinfo:
 * Return dynamic filesystem info such as
 * used size, free size, number of objects...
 *
 * \param filehandle (input):
 *        Handle of an object in the filesystem
 *        whom info is to be retrieved.
 * \param p_context (input):
 *        Authentication context for the operation (user,...).
 * \param dynamicinfo (output):
 *        Pointer to the static info of the filesystem.
 *
 * \return Major error codes:
 *      - ERR_FSAL_NO_ERROR     (no error)
 *      - ERR_FSAL_FAULT        (a NULL pointer was passed as mandatory argument)
 *      - Other error codes can be returned :
 *        ERR_FSAL_IO, ...
 */
fsal_status_t ZFSFSAL_dynamic_fsinfo(fsal_handle_t * filehandle,   /* IN */
                                  fsal_op_context_t * p_context,        /* IN */
                                  fsal_dynamicfsinfo_t * dynamicinfo    /* OUT */
    )
{

  /* sanity checks. */
  if(!filehandle || !dynamicinfo || !p_context)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_dynamic_fsinfo);

  TakeTokenFSCall();

  struct statvfs statfs;
  int rc = libzfswrap_statfs(((zfsfsal_op_context_t *)p_context)->export_context->p_vfs,
			     &statfs);

  ReleaseTokenFSCall();

  /* >> interpret returned status << */
  if(rc)
    Return(posix2fsal_error(rc), 0, INDEX_FSAL_dynamic_fsinfo);

  dynamicinfo->total_bytes = statfs.f_frsize * statfs.f_blocks;
  dynamicinfo->free_bytes = statfs.f_frsize * statfs.f_bfree;
  dynamicinfo->avail_bytes = statfs.f_frsize * statfs.f_bavail;

  dynamicinfo->total_files = statfs.f_files;
  dynamicinfo->free_files = statfs.f_ffree;
  dynamicinfo->avail_files = statfs.f_favail;

  dynamicinfo->time_delta.seconds = 1;
  dynamicinfo->time_delta.nseconds = 0;


  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_dynamic_fsinfo);
}
Example #17
0
fsal_status_t fsal_internal_fd2handle( vfsfsal_op_context_t * p_context,
                                       int fd, 
				       vfsfsal_handle_t * phandle)
{
  int rc = 0 ;
  int errsv = 0 ; 
  int mnt_id = 0 ;


  phandle->data.vfs_handle.handle_bytes = VFS_HANDLE_LEN ;
  if( ( rc = vfs_fd_to_handle( fd, &phandle->data.vfs_handle, &mnt_id ) ) )
   ReturnCode(posix2fsal_error(errsv), errsv);

#if 0 
  {
    char str[1024] ;
    sprint_mem( str, phandle->data.vfs_handle.handle, phandle->data.vfs_handle.handle_bytes ) ;
    printf( "=====> fsal_internal_fd2handle: type=%u bytes=%u|%s\n",  
            phandle->data.vfs_handle.handle_type, phandle->data.vfs_handle.handle_bytes, str ) ;
  }
#endif

  ReturnCode(ERR_FSAL_NO_ERROR, 0);
}                               /* fsal_internal_fd2handle */
Example #18
0
/**
 * VFSFSAL_getattrs_descriptor:
 * Get attributes for the object specified by its descriptor or by it's filehandle.
 *
 * \param p_file_descriptor (input):
 *        The file descriptor of the object to get parameters.
 * \param p_filehandle (input):
 *        The handle of the object to get parameters.
 * \param p_context (input):
 *        Authentication context for the operation (user,...).
 * \param p_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)
 *        - Another error code if an error occured.
 */
fsal_status_t VFSFSAL_getattrs_descriptor(fsal_file_t * p_file_descriptor,     /* IN */
                                           fsal_handle_t * p_filehandle,        /* IN */
                                           fsal_op_context_t * p_context,       /* IN */
                                           fsal_attrib_list_t * p_object_attributes /* IN/OUT */
    )
{
  fsal_status_t st;
  struct stat64 buffstat;
  int rc, errsv;

  /* sanity checks.
   * note : object_attributes is mandatory in VFSFSAL_getattrs.
   */
  if(!p_file_descriptor || !p_filehandle || !p_context || !p_object_attributes)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_getattrs_descriptor);

  TakeTokenFSCall();
  rc = fstat64(((vfsfsal_file_t *)p_file_descriptor)->fd, &buffstat);
  errsv = errno;
  ReleaseTokenFSCall();

  if(rc == -1)
    Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_getattrs_descriptor);

  /* convert attributes */
  st = posixstat64_2_fsal_attributes(&buffstat, p_object_attributes);
  if(FSAL_IS_ERROR(st))
    {
      FSAL_CLEAR_MASK(p_object_attributes->asked_attributes);
      FSAL_SET_MASK(p_object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
      ReturnStatus(st, INDEX_FSAL_getattrs_descriptor);
    }

  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_getattrs_descriptor);

}
Example #19
0
/**
 * FSAL_closedir :
 * Free the resources allocated for reading directory entries.
 *     
 * \param dir_descriptor (input):
 *        Pointer to a directory descriptor filled by FSAL_opendir.
 * 
 * \return Major error codes :
 *        - ERR_FSAL_NO_ERROR     (no error)
 *        - Another error code if an error occured.
 */
fsal_status_t POSIXFSAL_closedir(fsal_dir_t * dir_descriptor     /* IN */  )
{
  posixfsal_dir_t * p_dir_descriptor = (posixfsal_dir_t *) dir_descriptor;
  int rc;

  /* sanity checks */
  if(!p_dir_descriptor)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_closedir);

#ifdef _USE_POSIXDB_READDIR_BLOCK
  if(p_dir_descriptor->p_dbentries)
    Mem_Free(p_dir_descriptor->p_dbentries);
#endif

  rc = closedir(p_dir_descriptor->p_dir);
  if(rc != 0)
    Return(posix2fsal_error(errno), errno, INDEX_FSAL_closedir);

  /* fill dir_descriptor with zeros */
  memset(p_dir_descriptor, 0, sizeof(posixfsal_dir_t));

  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_closedir);

}
Example #20
0
fsal_status_t tank_list_ext_attrs(struct fsal_obj_handle *obj_hdl,
				  unsigned int argcookie,
				  fsal_xattrent_t *xattrs_tab,
				  unsigned int xattrs_tabsize,
				  unsigned int *p_nb_returned, int *end_of_list)
{
	unsigned int index;
	unsigned int out_index;
	unsigned int cookie = argcookie;
	struct zfs_fsal_obj_handle *obj_handle = NULL;

	char names[MAXPATHLEN], *ptr;
	size_t namesize;
	int xattr_idx;
	int retval;
	creden_t cred;

	/* sanity checks */
	if (!obj_hdl || !xattrs_tab || !p_nb_returned || !end_of_list)
		return fsalstat(ERR_FSAL_FAULT, 0);

	obj_handle =
	    container_of(obj_hdl, struct zfs_fsal_obj_handle, obj_handle);

	cred.uid = op_ctx->creds->caller_uid;
	cred.gid = op_ctx->creds->caller_gid;

	/* Deal with special cookie */
	if (cookie == XATTR_RW_COOKIE)
		cookie = XATTR_COUNT;

	for (index = cookie, out_index = 0;
	     index < XATTR_COUNT && out_index < xattrs_tabsize; index++) {
		if (do_match_type(xattr_list[index].flags,
				  obj_hdl->attributes.type)) {
			/* fills an xattr entry */
			xattrs_tab[out_index].xattr_id = index;
			strncpy(xattr_list[index].xattr_name,
				xattrs_tab[out_index].xattr_name, MAXNAMLEN);
			xattr_list[index].xattr_name[MAXNAMLEN] = '\0';
			xattrs_tab[out_index].xattr_cookie = index + 1;

			/* set asked attributes (all supported) */
			xattrs_tab[out_index].attributes.mask =
			    obj_hdl->attributes.mask;

			if (file_attributes_to_xattr_attrs(&obj_hdl->attributes,
							   &xattrs_tab
							   [out_index]
							   .attributes,
							   index)) {
				/* set error flag */
				xattrs_tab[out_index].attributes.mask =
				    ATTR_RDATTR_ERR;
			}

			/* next output slot */
			out_index++;
		}
	}

	/* save a call if output array is full */
	if (out_index == xattrs_tabsize) {
		*end_of_list = false;
		*p_nb_returned = out_index;
		return fsalstat(ERR_FSAL_NO_ERROR, 0);
	}

	/* get the path of the file in Lustre */

	/* get xattrs */

	retval = libzfswrap_listxattr(ZFSFSAL_GetVFS(obj_handle->handle),
				      &cred,
				      obj_handle->handle->zfs_handle,
				      (char **)&names, &namesize);
	if (retval)
		return fsalstat(posix2fsal_error(retval), retval);

	if (namesize > 0) {
		size_t len = 0;

		errno = 0;

		for (ptr = names, xattr_idx = 0;
		     (ptr < names + namesize) && (out_index < xattrs_tabsize);
		     xattr_idx++, ptr += len + 1) {
			len = strlen(ptr);
			index = XATTR_COUNT + xattr_idx;

			/* skip if index is before cookie */
			if (index < cookie)
				continue;

			/* fills an xattr entry */
			xattrs_tab[out_index].xattr_id = index;
			strncpy(xattrs_tab[out_index].xattr_name, ptr, len + 1);
			xattrs_tab[out_index].xattr_cookie = index + 1;

			/* set asked attributes (all supported) */
			xattrs_tab[out_index].attributes.mask =
			    obj_hdl->attributes.mask;

			if (file_attributes_to_xattr_attrs
			    (&obj_hdl->attributes,
			     &xattrs_tab[out_index].attributes, index)) {
				/* set error flag */
				xattrs_tab[out_index].attributes.mask =
				    ATTR_RDATTR_ERR;
			}

			/* next output slot */
			out_index++;
		}
		/* all xattrs are in the output array */
		if (ptr >= names + namesize)
			*end_of_list = true;
		else
			*end_of_list = false;
	} else			/* no xattrs */
		*end_of_list = true;

	*p_nb_returned = out_index;

	return fsalstat(ERR_FSAL_NO_ERROR, 0);
}
Example #21
0
fsal_status_t tank_getextattr_value_by_id(struct fsal_obj_handle *obj_hdl,
					  unsigned int xattr_id,
					  caddr_t buffer_addr,
					  size_t buffer_size,
					  size_t *p_output_size)
{
	struct zfs_fsal_obj_handle *obj_handle = NULL;
	int retval = -1;
	creden_t cred;

	obj_handle =
	    container_of(obj_hdl, struct zfs_fsal_obj_handle, obj_handle);

	/* sanity checks */
	if (!obj_hdl || !p_output_size || !buffer_addr)
		return fsalstat(ERR_FSAL_FAULT, 0);

	cred.uid = op_ctx->creds->caller_uid;
	cred.gid = op_ctx->creds->caller_gid;

	/* check that this index match the type of entry */
	if ((xattr_id < XATTR_COUNT)
	    && !do_match_type(xattr_list[xattr_id].flags,
			      obj_hdl->attributes.type)) {
		return fsalstat(ERR_FSAL_INVAL, 0);
	} else if (xattr_id >= XATTR_COUNT) {
		char attr_name[MAXPATHLEN];

		/* get the name for this attr */
		retval = xattr_id_to_name(ZFSFSAL_GetVFS(obj_handle->handle),
					  &cred,
					  obj_handle->handle->zfs_handle,
					  xattr_id,
					  attr_name);
		if (retval)
			return fsalstat(retval, 0);
		retval = libzfswrap_getxattr(ZFSFSAL_GetVFS(obj_handle->handle),
					     &cred,
					     obj_handle->handle->zfs_handle,
					     attr_name, &buffer_addr);
		if (retval)
			return fsalstat(posix2fsal_error(retval), retval);

		/* the xattr value can be a binary, or a string.
		 * trying to determine its type...
		 */
		*p_output_size = strnlen(buffer_addr, buffer_size);
		xattr_format_value(buffer_addr, p_output_size, buffer_size);

		return fsalstat(ERR_FSAL_NO_ERROR, 0);
	} else {		/* built-in attr */

		/* get the value */
		retval = xattr_list[xattr_id].get_func(obj_hdl, buffer_addr,
						       buffer_size,
						       p_output_size,
						       xattr_list[xattr_id]
						       .arg);
		return fsalstat(retval, 0);
	}
}
Example #22
0
/**
 * FSAL_create:
 * Create a regular file.
 *
 * \param parent_directory_handle (input):
 *        Handle of the parent directory where the file is to be created.
 * \param p_filename (input):
 *        Pointer to the name of the file to be created.
 * \param cred (input):
 *        Authentication context for the operation (user,...).
 * \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 (optional input/output): 
 *        The 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).
 *        May be NULL.
 *
 * \return Major error codes :
 *        - ERR_FSAL_NO_ERROR     (no error)
 *        - Another error code if an error occurred.
 */
fsal_status_t GPFSFSAL_create(fsal_handle_t * p_parent_directory_handle,    /* IN */
                          fsal_name_t * p_filename,     /* IN */
                          fsal_op_context_t * p_context,        /* IN */
                          fsal_accessmode_t accessmode, /* IN */
                          fsal_handle_t * p_object_handle,      /* OUT */
                          fsal_attrib_list_t * p_object_attributes      /* [ IN/OUT ] */
    )
{

  int rc = 0, errsv;
  int setgid_bit = 0;
  fsal_status_t status;

  int fd, newfd;
  mode_t unix_mode;
  fsal_accessflags_t access_mask = 0;
  fsal_attrib_list_t parent_dir_attrs;

  /* sanity checks.
   * note : object_attributes is optional.
   */
  if(!p_parent_directory_handle || !p_context || !p_object_handle || !p_filename)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_create);

  /* convert fsal mode to unix mode. */
  unix_mode = fsal2unix_mode(accessmode);

  /* Apply umask */
  unix_mode = unix_mode & ~global_fs_info.umask;

  LogFullDebug(COMPONENT_FSAL, "Creation mode: 0%o", accessmode);

  TakeTokenFSCall();
  status =
      fsal_internal_handle2fd(p_context, p_parent_directory_handle, &fd,
                              O_RDONLY | O_DIRECTORY);
  ReleaseTokenFSCall();
  if(FSAL_IS_ERROR(status))
    ReturnStatus(status, INDEX_FSAL_create);

  /* retrieve directory metadata */
  parent_dir_attrs.asked_attributes = GPFS_SUPPORTED_ATTRIBUTES;
  status = GPFSFSAL_getattrs(p_parent_directory_handle, p_context, &parent_dir_attrs);
  if(FSAL_IS_ERROR(status))
    ReturnStatus(status, INDEX_FSAL_create);

  /* Check the user can write in the directory, and check the setgid bit on the directory */

  if(fsal2unix_mode(parent_dir_attrs.mode) & S_ISGID)
    setgid_bit = 1;

  /* Set both mode and ace4 mask */
  access_mask = FSAL_MODE_MASK_SET(FSAL_W_OK | FSAL_X_OK) |
                FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_ADD_FILE);

  status = fsal_internal_testAccess(p_context, access_mask, NULL, &parent_dir_attrs);
  if(FSAL_IS_ERROR(status))
    ReturnStatus(status, INDEX_FSAL_create);

  /* call to filesystem */

  TakeTokenFSCall();
  /* create the file.
   * O_EXCL=>  error if the file already exists */
  newfd = openat(fd, p_filename->name, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, unix_mode);
  errsv = errno;

  if(newfd < 0)
    {
      close(fd);
      ReleaseTokenFSCall();
      Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_create);
    }

  /* we no longer need the parent directory open any more */
  close(fd);

  /* close the file descriptor */
  /*** 
   * Previously the file handle was closed here.  I don't think that
   we need that, but leaving the commented out logic just in case.
   rc = close(newfd);
   
   errsv = errno;
   if(rc)
   {
   close(fd);
   ReleaseTokenFSCall();
   Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_create);
   }
  */

  /* get a handle for this new fd, doing this directly ensures no race
     because we still have the fd open until the end of this function */
  status = fsal_internal_fd2handle(newfd, p_object_handle);
  ReleaseTokenFSCall();

  if(FSAL_IS_ERROR(status))
    {
      close(newfd);
      ReturnStatus(status, INDEX_FSAL_create);
    }

  /* the file has been created */
  /* chown the file to the current user */

  if(p_context->credential.user != geteuid())
    {
      TakeTokenFSCall();
      /* if the setgid_bit was set on the parent directory, do not change the group of the created file, because it's already the parentdir's group */
      rc = fchown(newfd, p_context->credential.user,
                  setgid_bit ? -1 : (int)p_context->credential.group);
      errsv = errno;
      ReleaseTokenFSCall();
      if(rc)
        {
          close(newfd);
          Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_create);
        }
    }

  /* if we got this far successfully, but the file close fails, we've
     got a problem, possibly a disk full problem. */
  close(newfd);
  if(rc)
    Return(posix2fsal_error(errno), errno, INDEX_FSAL_create);

  /* retrieve file attributes */
  if(p_object_attributes)
    {
      status = GPFSFSAL_getattrs(p_object_handle, p_context, p_object_attributes);

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

    }

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

}
Example #23
0
/**
 * FSAL_mknode:
 * Create a special object in the filesystem.
 * Not supported upon HPSS.
 *
 * \return ERR_FSAL_NOTSUPP.
 */
fsal_status_t GPFSFSAL_mknode(fsal_handle_t * parentdir_handle,     /* IN */
                          fsal_name_t * p_node_name,    /* IN */
                          fsal_op_context_t * p_context,        /* IN */
                          fsal_accessmode_t accessmode, /* IN */
                          fsal_nodetype_t nodetype,     /* IN */
                          fsal_dev_t * dev,     /* IN */
                          fsal_handle_t * p_object_handle,      /* OUT (handle to the created node) */
                          fsal_attrib_list_t * node_attributes  /* [ IN/OUT ] */
    )
{
  int rc, errsv;
  int setgid_bit = 0;
  fsal_status_t status;
  int fd, newfd;

  mode_t unix_mode = 0;
  dev_t unix_dev = 0;
  fsal_accessflags_t access_mask = 0;
  fsal_attrib_list_t parent_dir_attrs;

  /* sanity checks.
   * note : link_attributes is optional.
   */
  if(!parentdir_handle || !p_context || !p_node_name)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_mknode);

  unix_mode = fsal2unix_mode(accessmode);

  /* Apply umask */
  unix_mode = unix_mode & ~global_fs_info.umask;

  switch (nodetype)
    {
    case FSAL_TYPE_BLK:
      if(!dev)
        Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_mknode);
      unix_mode |= S_IFBLK;
      unix_dev = (dev->major << 8) | (dev->minor & 0xFF);
      break;

    case FSAL_TYPE_CHR:
      if(!dev)
        Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_mknode);
      unix_mode |= S_IFCHR;
      unix_dev = (dev->major << 8) | (dev->minor & 0xFF);
      break;

    case FSAL_TYPE_SOCK:
      unix_mode |= S_IFSOCK;
      break;

    case FSAL_TYPE_FIFO:
      unix_mode |= S_IFIFO;
      break;

    default:
      LogMajor(COMPONENT_FSAL,
               "Invalid node type in FSAL_mknode: %d", nodetype);
      Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_mknode);
    }

  /* build the directory path */
  status =
      fsal_internal_handle2fd(p_context, parentdir_handle, &fd, O_RDONLY | O_DIRECTORY);

  if(FSAL_IS_ERROR(status))
    ReturnStatus(status, INDEX_FSAL_mknode);

  /* retrieve directory attributes */
  parent_dir_attrs.asked_attributes = GPFS_SUPPORTED_ATTRIBUTES;
  status = GPFSFSAL_getattrs(parentdir_handle, p_context, &parent_dir_attrs);
  if(FSAL_IS_ERROR(status))
    ReturnStatus(status, INDEX_FSAL_mknode);

  /* Check the user can write in the directory, and check weither the setgid bit on the directory */
  if(fsal2unix_mode(parent_dir_attrs.mode) & S_ISGID)
    setgid_bit = 1;

  /* Set both mode and ace4 mask */
  access_mask = FSAL_MODE_MASK_SET(FSAL_W_OK | FSAL_X_OK) |
                FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_ADD_FILE);

  status = fsal_internal_testAccess(p_context, access_mask, NULL, &parent_dir_attrs);
  if(FSAL_IS_ERROR(status))
    ReturnStatus(status, INDEX_FSAL_mknode);

  /* creates the node, then stats it */
  rc = mknodat(fd, p_node_name->name, unix_mode, unix_dev);
  errsv = errno;

  if(rc)
    {
      close(fd);
      Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_mknode);
    }

  /* WARNING:
   * After creating the new node, the node name could have been changed.
   * This is a race condition. However only root creates new nodes. This
   * is an unlikely race condition, but hopefully can be fixed someday.
   */

  if(FSAL_IS_ERROR(status = fsal_internal_get_handle_at(fd, p_node_name,
                                                        p_object_handle)))
    {
      close(fd);
      ReturnStatus(status, INDEX_FSAL_mknode);
    }

  if(FSAL_IS_ERROR(status = fsal_internal_handle2fd_at(fd,
                                                       p_object_handle, &newfd,
                                                       O_RDONLY | O_NOFOLLOW)))
    {
      close(fd);
      ReturnStatus(status, INDEX_FSAL_mknode);
    }

  /* the node has been created */
  /* chown the file to the current user/group */

  if(p_context->credential.user != geteuid())
    {
      /* if the setgid_bit was set on the parent directory, do not change the group of the created file, because it's already the parentdir's group */
      rc = fchown(newfd, p_context->credential.user,
                  setgid_bit ? -1 : (int)p_context->credential.group);
      errsv = errno;

      if(rc)
        {
          close(fd);
          close(newfd);
          Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_mknode);
        }
    }

  close(fd);
  close(newfd);

  /* Fills the attributes if needed */
  if(node_attributes)
    {

      status = GPFSFSAL_getattrs(p_object_handle, p_context, node_attributes);

      /* on error, we set a special bit in the mask. */

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

    }

  /* Finished */
  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_mknode);

}
Example #24
0
fsal_status_t LUSTREFSAL_unlink(fsal_handle_t * p_parent_directory_handle,        /* IN */
                                fsal_name_t * p_object_name,    /* IN */
                                fsal_op_context_t * p_context,    /* IN */
                                fsal_attrib_list_t * p_parent_directory_attributes      /* [IN/OUT ] */
    )
{

  fsal_status_t status;
  int rc, errsv;
  struct stat buffstat, buffstat_parent;
  fsal_path_t fsalpath;

  /* sanity checks. */
  if(!p_parent_directory_handle || !p_context || !p_object_name)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_unlink);

  /* build the FID path */
  status = fsal_internal_Handle2FidPath(p_context, p_parent_directory_handle, &fsalpath);
  if(FSAL_IS_ERROR(status))
    ReturnStatus(status, INDEX_FSAL_unlink);

  /* get directory metadata */
  TakeTokenFSCall();
  rc = lstat(fsalpath.path, &buffstat_parent);
  errsv = errno;
  ReleaseTokenFSCall();
  if(rc)
    {
      if(errsv == ENOENT)
        Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_unlink);
      else
        Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_unlink);
    }

  /* build the child path */
  status = fsal_internal_appendNameToPath(&fsalpath, p_object_name);
  if(FSAL_IS_ERROR(status))
    ReturnStatus(status, INDEX_FSAL_unlink);

  /* get file metadata */
  TakeTokenFSCall();
  rc = lstat(fsalpath.path, &buffstat);
  errsv = errno;
  ReleaseTokenFSCall();
  if(rc)
    Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_unlink);

  /* check access rights */

  /* Sticky bit on the directory => the user who wants to delete the file must own it or its parent dir */
  if((buffstat_parent.st_mode & S_ISVTX)
     && buffstat_parent.st_uid != p_context->credential.user
     && buffstat.st_uid != p_context->credential.user && p_context->credential.user != 0)
    {
      Return(ERR_FSAL_ACCESS, 0, INDEX_FSAL_unlink);
    }

  /* client must be able to lookup the parent directory and modify it */
  status =
      fsal_internal_testAccess(p_context, FSAL_W_OK | FSAL_X_OK, &buffstat_parent, NULL);
  if(FSAL_IS_ERROR(status))
    ReturnStatus(status, INDEX_FSAL_unlink);

  /******************************
   * DELETE FROM THE FILESYSTEM *
   ******************************/
  TakeTokenFSCall();
  /* If the object to delete is a directory, use 'rmdir' to delete the object, else use 'unlink' */
  rc = (S_ISDIR(buffstat.st_mode)) ? rmdir(fsalpath.path) : unlink(fsalpath.path);
  errsv = errno;
  ReleaseTokenFSCall();
  if(rc)
    Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_unlink);

  /***********************
   * FILL THE ATTRIBUTES *
   ***********************/

  if(p_parent_directory_attributes)
    {
      status =
          LUSTREFSAL_getattrs(p_parent_directory_handle, p_context,
                              p_parent_directory_attributes);
      if(FSAL_IS_ERROR(status))
        {
          FSAL_CLEAR_MASK(p_parent_directory_attributes->asked_attributes);
          FSAL_SET_MASK(p_parent_directory_attributes->asked_attributes,
                        FSAL_ATTR_RDATTR_ERR);
        }
    }
  /* OK */
  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_unlink);

}
Example #25
0
fsal_status_t gpfs_read_plus(struct fsal_obj_handle *obj_hdl,
			uint64_t offset,
			size_t buffer_size, void *buffer, size_t *read_amount,
			bool *end_of_file, struct io_info *info)
{
	struct gpfs_fsal_obj_handle *myself;
	fsal_status_t status = { ERR_FSAL_NO_ERROR, 0 };
	struct read_arg rarg;
	ssize_t nb_read;
	int errsv = 0;

	if (!buffer || !read_amount || !end_of_file || !info)
		return fsalstat(ERR_FSAL_FAULT, 0);

	myself = container_of(obj_hdl, struct gpfs_fsal_obj_handle, obj_handle);

	assert(myself->u.file.fd >= 0
	       && myself->u.file.openflags != FSAL_O_CLOSED);

	rarg.mountdirfd = myself->u.file.fd;
	rarg.fd = myself->u.file.fd;
	rarg.bufP = buffer;
	rarg.offset = offset;
	rarg.length = buffer_size;
	rarg.options = IO_SKIP_HOLE;

	nb_read = gpfs_ganesha(OPENHANDLE_READ_BY_FD, &rarg);
	errsv = errno;

	if (nb_read < 0) {
		if (errsv == EUNATCH)
			LogFatal(COMPONENT_FSAL, "GPFS Returned EUNATCH");
		if (errsv != ENODATA)
			return fsalstat(posix2fsal_error(errsv), errsv);

		/* errsv == ENODATA */
		info->io_content.what = NFS4_CONTENT_HOLE;
		info->io_content.hole.di_offset = offset;     /*offset of hole*/
		info->io_content.hole.di_length = buffer_size;/*length of hole*/
		*read_amount = buffer_size;
		if ((buffer_size + offset) > myself->attributes.filesize) {
			if (offset > myself->attributes.filesize)
				*read_amount = 0;
			else
				*read_amount =
					myself->attributes.filesize - offset;
			info->io_content.hole.di_length = *read_amount;
		}
	} else {
		info->io_content.what = NFS4_CONTENT_DATA;
		info->io_content.data.d_offset = offset + nb_read;
		info->io_content.data.d_data.data_len = nb_read;
		info->io_content.data.d_data.data_val = buffer;
		*read_amount = nb_read;
	}
	if (nb_read != -1 &&
		(nb_read == 0 || nb_read < buffer_size ||
		((offset + nb_read) >= myself->attributes.filesize)))
		*end_of_file = true;
	else
		*end_of_file = false;

	return status;
}
Example #26
0
/**
 * FSAL_create:
 * Create a regular file.
 *
 * \param parent_hdl (input):
 *        Handle of the parent directory where the file is to be created.
 * \param p_filename (input):
 *        Pointer to the name of the file to be created.
 * \param p_context (input):
 *        Authentication context for the operation (user,...).
 * \param accessmode (input):
 *        Mode for the file to be created.
 *        (the umask defined into the FSAL configuration file
 *        will be applied on it).
 * \param p_object_handle (output):
 *        Pointer to the handle of the created file.
 * \param p_object_attributes (optional input/output):
 *        The 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).
 *        May be NULL.
 *
 * \return Major error codes :
 *        - ERR_FSAL_NO_ERROR     (no error)
 *        - Another error code if an error occurred.
 */
fsal_status_t PTFSAL_create(struct fsal_obj_handle *dir_hdl,	/* IN */
			    const char *p_filename,	/* IN */
			    const struct req_op_context *p_context,	/* IN */
			    uint32_t accessmode,	/* IN */
			    ptfsal_handle_t *p_object_handle,	/* OUT */
			    struct attrlist *p_object_attributes)
{				/* IN/OUT */

	int errsv;
	fsal_status_t status;
	struct pt_fsal_obj_handle *pt_hdl;
	mode_t unix_mode;
	int open_rc;
	ptfsal_handle_t *p_fsi_handle = (ptfsal_handle_t *) p_object_handle;

	FSI_TRACE(FSI_DEBUG, "Begin to create file************************\n");

	/* sanity checks.
	 * note : object_attributes is optional.
	 */
	if (!dir_hdl || !p_context || !p_object_handle || !p_filename)
		return fsalstat(ERR_FSAL_FAULT, 0);

	pt_hdl = container_of(dir_hdl, struct pt_fsal_obj_handle, obj_handle);

	/* convert fsal mode to unix mode. */
	unix_mode = fsal2unix_mode(accessmode);

	/* Apply umask */
	unix_mode = unix_mode & ~p_context->fsal_export->exp_ops.
			fs_umask(p_context->fsal_export);

	LogFullDebug(COMPONENT_FSAL, "Creation mode: 0%o", accessmode);

	open_rc =
	    ptfsal_open(pt_hdl, p_filename, p_context, unix_mode,
			p_object_handle);
	if (open_rc < 0) {
		errsv = errno;
		return fsalstat(posix2fsal_error(errsv), errsv);
	}

	FSI_TRACE(FSI_DEBUG, "New Handle = %s",
		  (char *)p_fsi_handle->data.handle.f_handle);

	/* retrieve file attributes */
	if (p_object_attributes) {
		status = PTFSAL_getattrs(p_context->fsal_export, p_context,
					 p_object_handle,
					 p_object_attributes);

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

	}

	FSI_TRACE(FSI_DEBUG, "End to create file************************\n");

	/* OK */
	return fsalstat(ERR_FSAL_NO_ERROR, 0);

}
Example #27
0
/**
 * FSAL_mkdir:
 * Create a directory.
 *
 * \param dir_hdl (input):
 *        Handle of the parent directory where
 *        the subdirectory is to be created.
 * \param p_context (input):
 *        Pointer to the name of the directory to be created.
 * \param cred (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 p_object_handle (output):
 *        Pointer to the handle of the created directory.
 * \param p_object_attributes (optionnal input/output):
 *        The attributes of the created directory.
 *        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)
 *        - Another error code if an error occured.
 */
fsal_status_t PTFSAL_mkdir(struct fsal_obj_handle *dir_hdl,	/* IN */
			   const char *p_dirname,	/* IN */
			   const struct req_op_context *p_context,	/* IN */
			   uint32_t accessmode,	/* IN */
			   ptfsal_handle_t *p_object_handle,	/* OUT */
			   struct attrlist *p_object_attributes)
{				/* IN/OUT */

	int rc, errsv;
	int setgid_bit = 0;
	mode_t unix_mode;
	fsal_status_t status;
	struct attrlist parent_dir_attrs;
	char newPath[PATH_MAX];
	struct pt_fsal_obj_handle *pt_hdl;

	FSI_TRACE(FSI_INFO, "MKDIR BEGIN-------------------------\n");

	/* sanity checks.
	 * note : object_attributes is optional.
	 */
	if (!dir_hdl || !p_context || !p_object_handle || !p_dirname)
		return fsalstat(ERR_FSAL_FAULT, 0);

	pt_hdl = container_of(dir_hdl, struct pt_fsal_obj_handle, obj_handle);

	/* convert FSAL mode to unix mode. */
	unix_mode = fsal2unix_mode(accessmode);

	/* Apply umask */
	unix_mode = unix_mode & ~p_context->fsal_export->exp_ops.
			fs_umask(p_context->fsal_export);

	/* get directory metadata */
	parent_dir_attrs.mask = p_context->fsal_export->exp_ops.
				fs_supported_attrs(p_context->fsal_export);
	status =
	    PTFSAL_getattrs(p_context->fsal_export, p_context, pt_hdl->handle,
			    &parent_dir_attrs);

	if (FSAL_IS_ERROR(status))
		return status;

	/* Check the user can write in the directory, and check the
	 * setgid bit on the directory
	 */

	if (fsal2unix_mode(parent_dir_attrs.mode) & S_ISGID)
		setgid_bit = 1;

	rc = ptfsal_mkdir(pt_hdl, p_dirname, p_context, unix_mode,
			  p_object_handle);
	errsv = errno;
	if (rc)
		return fsalstat(posix2fsal_error(errsv), errsv);

	if (FSAL_IS_ERROR(status))
		return status;

	/* the directory has been created */
	/* chown the dir to the current user/group */

	if (p_context->creds->caller_uid != geteuid()) {
		FSI_TRACE(FSI_DEBUG, "MKDIR %d", __LINE__);
		/* if the setgid_bit was set on the parent directory, do not
		 * change the group of the created file, because it's already
		 * the parentdir's group
		 */

		if (fsi_get_name_from_handle
		    (p_context, p_context->fsal_export, pt_hdl->handle,
		     (char *)newPath, NULL) < 0) {
			FSI_TRACE(FSI_DEBUG,
				  "Failed to get name from handle %s",
				  (char *)p_object_handle->data.handle.
				  f_handle);
			return fsalstat(posix2fsal_error(errsv), errsv);
		}
		rc = ptfsal_chown(p_context, p_context->fsal_export, newPath,
				  p_context->creds->caller_uid,
				  setgid_bit ? -1 : (int)p_context->creds->
				  caller_gid);
		errsv = errno;
		if (rc)
			return fsalstat(posix2fsal_error(errsv), errsv);
	}

	/* retrieve file attributes */
	if (p_object_attributes) {
		FSI_TRACE(FSI_DEBUG, "MKDIR %d", __LINE__);
		status = PTFSAL_getattrs(p_context->fsal_export, p_context,
					 p_object_handle,
					 p_object_attributes);

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

	}
	FSI_TRACE(FSI_INFO, "MKDIR END ------------------\n");
	FSI_TRACE(FSI_DEBUG, "MKDIR %d", __LINE__);
	/* OK */
	return fsalstat(ERR_FSAL_NO_ERROR, 0);

}
Example #28
0
/**
 * FSAL_write:
 * Perform a write operation on an opened file.
 *
 * \param file_descriptor (input):
 *        The file descriptor returned by FSAL_open.
 * \param seek_descriptor (optional input):
 *        Specifies the position where data is to be written.
 *        If not specified, data will be written at the current position.
 * \param buffer_size (input):
 *        Amount (in bytes) of data to be written.
 * \param buffer (input):
 *        Address in memory of the data to write to file.
 * \param write_amount (output):
 *        Pointer to the amount of data (in bytes) that have been written
 *        during this call.
 *
 * \return Major error codes:
 *      - ERR_FSAL_NO_ERROR: no error.
 *      - Another error code if an error occured during this call.
 */
fsal_status_t GPFSFSAL_write(fsal_file_t * file_desc,       /* IN */
                         fsal_seek_t * p_seek_descriptor,       /* IN */
                         fsal_size_t buffer_size,       /* IN */
                         caddr_t buffer,        /* IN */
                         fsal_size_t * p_write_amount   /* OUT */
    )
{

  ssize_t nb_written;
  size_t i_size;
  int rc = 0, errsv = 0;
  int pcall = FALSE;
  gpfsfsal_file_t * p_file_descriptor = (gpfsfsal_file_t *)file_desc;

  /* sanity checks. */
  if(!p_file_descriptor || !buffer || !p_write_amount)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_write);

  if(p_file_descriptor->ro)
    Return(ERR_FSAL_PERM, 0, INDEX_FSAL_write);

  /** @todo: manage fsal_size_t to size_t convertion */
  i_size = (size_t) buffer_size;

  *p_write_amount = 0;

  /* positioning */

  if(p_seek_descriptor)
    {

      switch (p_seek_descriptor->whence)
        {
        case FSAL_SEEK_CUR:
          /* set position plus offset */
          pcall = FALSE;

          TakeTokenFSCall();
          rc = lseek(p_file_descriptor->fd, p_seek_descriptor->offset, SEEK_CUR);
          errsv = errno;
          ReleaseTokenFSCall();
          break;

        case FSAL_SEEK_SET:
          /* set absolute position to offset */
          pcall = TRUE;
          rc = 0;
          break;

        case FSAL_SEEK_END:
          /* set end of file plus offset */
          pcall = FALSE;

          TakeTokenFSCall();
          rc = lseek(p_file_descriptor->fd, p_seek_descriptor->offset, SEEK_END);
          errsv = errno;
          ReleaseTokenFSCall();

          break;
        }

      if(rc)
        {
          LogFullDebug(COMPONENT_FSAL,
                       "Error in posix fseek operation (whence=%s, offset=%lld)",
                       (p_seek_descriptor->whence == FSAL_SEEK_CUR ? "SEEK_CUR" :
                        (p_seek_descriptor->whence == FSAL_SEEK_SET ? "SEEK_SET" :
                         (p_seek_descriptor->whence ==
                          FSAL_SEEK_END ? "SEEK_END" : "ERROR"))),
                       (long long) p_seek_descriptor->offset);

          Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_write);

        }

      LogFullDebug(COMPONENT_FSAL,
                   "Write operation (whence=%s, offset=%lld, size=%lld)",
                   (p_seek_descriptor->whence ==
                    FSAL_SEEK_CUR ? "SEEK_CUR" : (p_seek_descriptor->whence ==
                                                  FSAL_SEEK_SET ? "SEEK_SET"
                                                  : (p_seek_descriptor->whence ==
                                                     FSAL_SEEK_END ? "SEEK_END" :
                                                     "ERROR"))),
                   (long long) p_seek_descriptor->offset, buffer_size);

    }

  /* write operation */

  TakeTokenFSCall();

  if(pcall)
    nb_written = pwrite(p_file_descriptor->fd, buffer, i_size, p_seek_descriptor->offset);
  else
    nb_written = write(p_file_descriptor->fd, buffer, i_size);
  errsv = errno;

  ReleaseTokenFSCall();

  /** @todo: manage ssize_t to fsal_size_t convertion */
  if(nb_written <= 0)
    {
      if (p_seek_descriptor)
        LogDebug(COMPONENT_FSAL,
                 "Write operation of size %llu at offset %lld failed. fd=%d, errno=%d.",
                 (unsigned long long) i_size,
                 (long long) p_seek_descriptor->offset,
                 p_file_descriptor->fd,
                 errsv);
      else
        LogDebug(COMPONENT_FSAL,
                 "Write operation of size %llu at offset 0. fd=%d, errno=%d.",
                 (unsigned long long) i_size,
                 p_file_descriptor->fd,
                 errsv);

      Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_write);
    }

  /* set output vars */

  *p_write_amount = (fsal_size_t) nb_written;

  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_write);

}
Example #29
0
/**
 * FSAL_read:
 * Perform a read operation on an opened file.
 *
 * \param file_descriptor (input):
 *        The file descriptor returned by FSAL_open.
 * \param seek_descriptor (optional input):
 *        Specifies the position where data is to be read.
 *        If not specified, data will be read at the current position.
 * \param buffer_size (input):
 *        Amount (in bytes) of data to be read.
 * \param buffer (output):
 *        Address where the read data is to be stored in memory.
 * \param read_amount (output):
 *        Pointer to the amount of data (in bytes) that have been read
 *        during this call.
 * \param end_of_file (output):
 *        Pointer to a boolean that indicates whether the end of file
 *        has been reached during this call.
 *
 * \return Major error codes:
 *      - ERR_FSAL_NO_ERROR: no error.
 *      - Another error code if an error occured during this call.
 */
fsal_status_t GPFSFSAL_read(fsal_file_t * file_desc,        /* IN */
                        fsal_seek_t * p_seek_descriptor,        /* [IN] */
                        fsal_size_t buffer_size,        /* IN */
                        caddr_t buffer, /* OUT */
                        fsal_size_t * p_read_amount,    /* OUT */
                        fsal_boolean_t * p_end_of_file  /* OUT */
    )
{

  size_t i_size;
  ssize_t nb_read;
  int rc = 0, errsv = 0;
  int pcall = FALSE;
  gpfsfsal_file_t * p_file_descriptor = (gpfsfsal_file_t *)file_desc;

  /* sanity checks. */

  if(!p_file_descriptor || !buffer || !p_read_amount || !p_end_of_file)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_read);

  /** @todo: manage fsal_size_t to size_t convertion */
  i_size = (size_t) buffer_size;

  /* positioning */

  if(p_seek_descriptor)
    {

      switch (p_seek_descriptor->whence)
        {
        case FSAL_SEEK_CUR:
          /* set position plus offset */
          pcall = FALSE;
          TakeTokenFSCall();
          rc = lseek(p_file_descriptor->fd, p_seek_descriptor->offset, SEEK_CUR);
          errsv = errno;
          ReleaseTokenFSCall();
          break;

        case FSAL_SEEK_SET:
          /* use pread/pwrite call */
          pcall = TRUE;
          rc = 0;
          break;

        case FSAL_SEEK_END:
          /* set end of file plus offset */
          pcall = FALSE;

          TakeTokenFSCall();
          rc = lseek(p_file_descriptor->fd, p_seek_descriptor->offset, SEEK_END);
          errsv = errno;
          ReleaseTokenFSCall();

          break;
        }

      if(rc)
        {
          LogFullDebug(COMPONENT_FSAL,
                       "Error in posix fseek operation (whence=%s, offset=%lld)",
                       (p_seek_descriptor->whence == FSAL_SEEK_CUR ? "SEEK_CUR" :
                        (p_seek_descriptor->whence == FSAL_SEEK_SET ? "SEEK_SET" :
                         (p_seek_descriptor->whence ==
                          FSAL_SEEK_END ? "SEEK_END" : "ERROR"))),
                       (long long) p_seek_descriptor->offset);

          Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_read);
        }

    }

  /* read operation */

  TakeTokenFSCall();

  if(pcall)
    nb_read = pread(p_file_descriptor->fd, buffer, i_size, p_seek_descriptor->offset);
  else
    nb_read = read(p_file_descriptor->fd, buffer, i_size);
  errsv = errno;
  ReleaseTokenFSCall();

  /** @todo: manage ssize_t to fsal_size_t convertion */

  if(nb_read == -1)
    Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_read);
  else if(nb_read == 0)
    *p_end_of_file = 1;

  *p_read_amount = nb_read;

  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_read);

}
Example #30
0
/**
 * GPFSFSAL_lock_op:
 * Lock/unlock/test an owner independent (anonymous) lock for a region in a file.
 *
 * \param p_file_descriptor (input):
 *        File descriptor of the file to lock.
 * \param p_filehandle (input):
 *        File handle of the file to lock.
 * \param p_context (input):
 *        Context
 * \param p_owner (input):
 *        Owner for the requested lock; Opaque to FSAL.
 * \param lock_op (input):
 *        Can be either FSAL_OP_LOCKT, FSAL_OP_LOCK, FSAL_OP_UNLOCK.
 *        The operations are test if a file region is locked, lock a
 *        file region, unlock a file region.
 * \param lock_type (input):
 *        Can be either FSAL_LOCK_R, FSAL_LOCK_W.
 *        Either a read lock or write lock.
 * \param lock_start (input):
 *        Start of lock region measured as offset of bytes from start of file.
 * \param lock_length (input):
 *        Number of bytes to lock.
 *
 * \return Major error codes:
 *      - ERR_FSAL_NO_ERROR: no error.
 *      - ERR_FSAL_FAULT: One of the in put parameters is NULL.
 *      - ERR_FSAL_PERM: lock_op was FSAL_OP_LOCKT and the result was that the operation would not be possible.
 */
fsal_status_t GPFSFSAL_lock_op( fsal_file_t       * p_file_descriptor, /* IN */
                                fsal_handle_t     * p_filehandle,      /* IN */
                                fsal_op_context_t * p_context,         /* IN */
                                void              * p_owner,           /* IN */
                                fsal_lock_op_t      lock_op,           /* IN */
                                fsal_lock_param_t   request_lock,      /* IN */
                                fsal_lock_param_t * conflicting_lock)  /* OUT */
{
  int retval;
  struct glock glock_args;
  struct set_get_lock_arg gpfs_sg_arg;
  glock_args.lfd = ((gpfsfsal_file_t *)p_file_descriptor)->fd;
  gpfsfsal_op_context_t *gpfs_op_cxt = (gpfsfsal_op_context_t *)p_context;
  gpfsfsal_file_t * pfd = (gpfsfsal_file_t *) p_file_descriptor;

  if(p_file_descriptor == NULL)
    {
      LogDebug(COMPONENT_FSAL, "p_file_descriptor arg is NULL.");
      Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lock_op);
    }
  if(p_filehandle == NULL)
    {
      LogDebug(COMPONENT_FSAL, "p_filehandle arg is NULL.");
      Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lock_op);
    }
  if(p_context == NULL)
    {
        LogDebug(COMPONENT_FSAL, "p_context arg is NULL.");
        Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lock_op);
    }
  if(p_owner == NULL)
    {
        LogDebug(COMPONENT_FSAL, "p_owner arg is NULL.");
        Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lock_op);
    }

  if(conflicting_lock == NULL && lock_op == FSAL_OP_LOCKT)
    {
      LogDebug(COMPONENT_FSAL,
               "Conflicting_lock argument can't be NULL with lock_op  = LOCKT");
      Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lock_op);
    }

  LogFullDebug(COMPONENT_FSAL,
               "Locking: op:%d type:%d start:%llu length:%llu owner:%p",
               lock_op, request_lock.lock_type, request_lock.lock_start,
               request_lock.lock_length, p_owner);

  if(lock_op == FSAL_OP_LOCKT)
    glock_args.cmd = F_GETLK;
  else if(lock_op == FSAL_OP_LOCK || lock_op == FSAL_OP_UNLOCK)
    glock_args.cmd = F_SETLK;
  else if(lock_op == FSAL_OP_LOCKB)
    glock_args.cmd = F_SETLKW; /*TODO: Handle FSAL_OP_CANCEL */
  else
    {
      LogDebug(COMPONENT_FSAL,
               "ERROR: Lock operation requested was not TEST, GET, or SET.");
      Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_lock_op);      
    }

  if(request_lock.lock_type == FSAL_LOCK_R)
    glock_args.flock.l_type = F_RDLCK;
  else if(request_lock.lock_type == FSAL_LOCK_W)
    glock_args.flock.l_type = F_WRLCK;
  else
    {
      LogDebug(COMPONENT_FSAL,
               "ERROR: The requested lock type was not read or write.");
      Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_lock_op);
    }

  if(lock_op == FSAL_OP_UNLOCK)
    glock_args.flock.l_type = F_UNLCK;

  glock_args.flock.l_len = request_lock.lock_length;
  glock_args.flock.l_start = request_lock.lock_start;
  glock_args.flock.l_whence = SEEK_SET;

  glock_args.lfd = pfd->fd;
  glock_args.lock_owner = p_owner;
  gpfs_sg_arg.mountdirfd = gpfs_op_cxt->export_context->mount_root_fd;
  gpfs_sg_arg.lock = &glock_args;

  errno = 0;

  retval = gpfs_ganesha(lock_op == FSAL_OP_LOCKT ?
      OPENHANDLE_GET_LOCK : OPENHANDLE_SET_LOCK, &gpfs_sg_arg);

  if(retval && lock_op == FSAL_OP_LOCK)
    {
      if(conflicting_lock != NULL)
        {
          glock_args.cmd = F_GETLK;
          retval = gpfs_ganesha(OPENHANDLE_GET_LOCK, &gpfs_sg_arg);
          if(retval)
            {
              LogCrit(COMPONENT_FSAL,
                      "After failing a set lock request, An attempt to get the current owner details also failed.");
              Return(posix2fsal_error(errno), errno, INDEX_FSAL_lock_op);
            }
          conflicting_lock->lock_owner = glock_args.flock.l_pid;
          conflicting_lock->lock_length = glock_args.flock.l_len;
          conflicting_lock->lock_start = glock_args.flock.l_start;
          conflicting_lock->lock_type = glock_args.flock.l_type;
        }
      Return(posix2fsal_error(errno), errno, INDEX_FSAL_lock_op);
    }

  /* F_UNLCK is returned then the tested operation would be possible. */
  if(conflicting_lock != NULL)
    {
      if(lock_op == FSAL_OP_LOCKT && glock_args.flock.l_type != F_UNLCK)
        {
          conflicting_lock->lock_owner = glock_args.flock.l_pid;
          conflicting_lock->lock_length = glock_args.flock.l_len;
          conflicting_lock->lock_start = glock_args.flock.l_start;
          conflicting_lock->lock_type = glock_args.flock.l_type;
        }
      else
        {
          conflicting_lock->lock_owner = 0;
          conflicting_lock->lock_length = 0;
          conflicting_lock->lock_start = 0;
          conflicting_lock->lock_type = FSAL_NO_LOCK;
        }
    }

  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_lock_op);
}