Beispiel #1
0
/* @brief Initialize the configuration
 *
 * Given the root of the Ganesha configuration structure, initialize
 * the FSAL parameters.
 *
 * @param[in] fsal_hdl      The FSAL module
 * @param[in] config_struct Parsed ganesha configuration file
 *
 * @return FSAL status.
 */
static fsal_status_t init_config(struct fsal_module *fsal_hdl,
                                 config_file_t /*config_struct*/)
{
    struct this_fsal_module *module_me =
        container_of(fsal_hdl, struct this_fsal_module, fsal);

    /* Get a copy of the defaults */
    module_me->fs_info = default_ovs_info;
    display_fsinfo(&module_me->fs_info);
    try
    {
        initialize_logging();
    }
    CATCH_STD_ALL_EWHAT({
            std::stringstream ss;
            ss << EWHAT;
            LogMajor(COMPONENT_FSAL,
                     const_cast<char*>("VFS FSAL: failed to initialize logging: %s"),
                     ss.str().c_str());
            return fsalstat(ERR_FSAL_BAD_INIT, 0);
    });
Beispiel #2
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);
}
Beispiel #3
0
/** @fn fsal_status_t
 *       GPFSFSAL_open(struct fsal_obj_handle *obj_hdl,
 *                     const struct req_op_context *op_ctx,
 *                     fsal_openflags_t openflags, int *file_desc,
 *                     struct attrlist *fsal_attr, bool reopen)
 *
 *  @brief Open a regular file for reading/writing its data content.
 *
 * @param obj_hdl Handle of the file to be read/modified.
 * @param op_ctx Authentication context for the operation (user,...).
 * @param openflags Flags that indicates behavior for file opening and access.
 *        This is an inclusive OR of the following values
 *        ( such of them are not compatible) :
 *        - FSAL_O_RDONLY: opening file for reading only.
 *        - FSAL_O_RDWR: opening file for reading and writing.
 *        - FSAL_O_WRONLY: opening file for writting only.
 *        - FSAL_O_APPEND: always write at the end of the file.
 *        - FSAL_O_TRUNC: truncate the file to 0 on opening.
 * @param file_desc The file descriptor to be used for FSAL_read/write ops.
 *
 * @return ERR_FSAL_NO_ERROR on success, error otherwise
 */
fsal_status_t
GPFSFSAL_open(struct fsal_obj_handle *obj_hdl,
	      const struct req_op_context *op_ctx, int posix_flags,
	      int *file_desc, bool reopen)
{
	struct gpfs_fsal_obj_handle *myself;
	struct gpfs_filesystem *gpfs_fs;
	fsal_status_t status;

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

	myself = container_of(obj_hdl, struct gpfs_fsal_obj_handle, obj_handle);
	gpfs_fs = obj_hdl->fs->private_data;

	LogFullDebug(COMPONENT_FSAL, "posix_flags 0x%X", posix_flags);

	status = fsal_internal_handle2fd(gpfs_fs->root_fd, myself->handle,
					 file_desc, posix_flags, reopen);

	if (FSAL_IS_ERROR(status)) {
		/** In some environments, "root" is denied write access,
		 * so try with the request credentials if the above call
		 * fails.
		 */
		fsal_set_credentials(op_ctx->creds);
		status = fsal_internal_handle2fd(gpfs_fs->root_fd,
						 myself->handle,
						 file_desc, posix_flags,
						 reopen);
		fsal_restore_ganesha_credentials();
	}

	return status;
}
Beispiel #4
0
/** @fn fsal_status_t
 *       GPFSFSAL_open(struct fsal_obj_handle *obj_hdl,
 *                     const struct req_op_context *op_ctx,
 *                     fsal_openflags_t openflags, int *file_desc,
 *                     struct attrlist *fsal_attr)
 *
 *  @brief Open a regular file for reading/writing its data content.
 *
 * @param obj_hdl Handle of the file to be read/modified.
 * @param op_ctx Authentication context for the operation (user,...).
 * @param openflags Flags that indicates behavior for file opening and access.
 *        This is an inclusive OR of the following values
 *        ( such of them are not compatible) :
 *        - FSAL_O_RDONLY: opening file for reading only.
 *        - FSAL_O_RDWR: opening file for reading and writing.
 *        - FSAL_O_WRONLY: opening file for writting only.
 *        - FSAL_O_APPEND: always write at the end of the file.
 *        - FSAL_O_TRUNC: truncate the file to 0 on opening.
 * @param file_desc The file descriptor to be used for FSAL_read/write ops.
 *
 * @return ERR_FSAL_NO_ERROR on success, error otherwise
 */
fsal_status_t
GPFSFSAL_open(struct fsal_obj_handle *obj_hdl,
	      const struct req_op_context *op_ctx, int posix_flags,
	      int *file_desc)
{
	struct gpfs_fsal_obj_handle *myself;
	fsal_status_t status;
	struct gpfs_fsal_export *exp = container_of(op_ctx->fsal_export,
					struct gpfs_fsal_export, export);
	int export_fd = exp->export_fd;

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

	myself = container_of(obj_hdl, struct gpfs_fsal_obj_handle,
								obj_handle);
	LogFullDebug(COMPONENT_FSAL, "posix_flags 0x%X export_fd %d",
						posix_flags, export_fd);

	fsal_set_credentials(op_ctx->creds);
	status = fsal_internal_handle2fd(export_fd, myself->handle,
					 file_desc, posix_flags);
	fsal_restore_ganesha_credentials();

	if (FSAL_IS_ERROR(status)) {
		/** Try open as root access if the above call fails,
		 * permission will be checked somewhere else in the code.
		 */
		status = fsal_internal_handle2fd(export_fd,
						 myself->handle,
						 file_desc, posix_flags);
	}

	return status;
}
Beispiel #5
0
/**
 * @brief Set file attributes into PanFS
 *
 * Convert attributes into PanFS format and set them
 *
 * @param[in] panfs_hdl	PanFS Object handle to operate on
 * @param[in] fd	Open FD to operate on
 * @param[in,out] attrib	Attributes to get / storage for attributes
 * @return ERR_FSAL_NO_ERROR on success, other error code on failure
 */
fsal_status_t PanFS_setattrs(struct panfs_fsal_obj_handle *panfs_hdl,
		int fd,
		struct attrlist *attrib)
{
	fsal_status_t st;
	struct pan_attrs pattrs;
	struct pan_fs_ace_s paces[PAN_FS_ACL_LEN_MAX];

	pattrs.acls.naces = PAN_FS_ACL_LEN_MAX;
	pattrs.acls.aces = paces;

	st = fsal_acl_2_panfs_acl(attrib, &pattrs.acls);
	if (FSAL_IS_ERROR(st)) {
		FSAL_CLEAR_MASK(attrib->mask);
		FSAL_SET_MASK(attrib->mask, ATTR_RDATTR_ERR);
		return st;
	}

	st = panfs_um_set_attr(fd, &pattrs);
	if (FSAL_IS_ERROR(st))
		return st;

	return fsalstat(ERR_FSAL_NO_ERROR, 0);
}
Beispiel #6
0
/**
 *  @brief Create a directory.
 *
 *  @param dir_hdl Handle of the parent directory
 *  @param dir_name Pointer to the name of the directory to be created.
 *  @param op_ctx Authentication context for the operation (user,...).
 *  @param accessmode Mode for the directory to be created.
 *  @param gpfs_fh Pointer to the handle of the created directory.
 *  @param fsal_attr Attributes of the created directory.
 *  @return ERR_FSAL_NO_ERROR on success, error otherwise
 *
 */
fsal_status_t
GPFSFSAL_mkdir(struct fsal_obj_handle *dir_hdl, const char *dir_name,
               const struct req_op_context *op_ctx, uint32_t accessmode,
               struct gpfs_file_handle *gpfs_fh, struct attrlist *obj_attr)
{
    mode_t unix_mode;
    fsal_status_t status;

    /* note : obj_attr is optional. */
    if (!dir_hdl || !op_ctx || !gpfs_fh || !dir_name)
        return fsalstat(ERR_FSAL_FAULT, 0);

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

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

    /* build new entry path */

    /* creates the directory and get its handle */

    fsal_set_credentials(op_ctx->creds);
    status = fsal_internal_create(dir_hdl, dir_name, unix_mode | S_IFDIR,
                                  0, gpfs_fh, NULL);
    fsal_restore_ganesha_credentials();

    if (FSAL_IS_ERROR(status))
        return status;

    /* retrieve file attributes */
    return GPFSFSAL_getattrs(op_ctx->fsal_export,
                             dir_hdl->fs->private_data,
                             op_ctx, gpfs_fh, obj_attr);
}
Beispiel #7
0
fsal_status_t hpss_setextattr_value_by_id(struct fsal_obj_handle *fsal_obj_hdl,
					  unsigned int xattr_id,
					  caddr_t buffer_addr,
					  size_t buffer_size)
{
	struct hpss_fsal_obj_handle *obj_hdl;
	int rc, index, listlen;
	sec_cred_t ucreds;
	hpss_userattr_list_t attr_list;

	if (!fsal_obj_hdl || !buffer_addr)
		return fsalstat(ERR_FSAL_FAULT, 0);

	if (attr_is_read_only(xattr_id))
		return fsalstat(ERR_FSAL_PERM, 0);

	if (((char *)buffer_addr)[0] == '\0')
		return fsalstat(ERR_FSAL_NO_ERROR, 0);

	obj_hdl = container_of(fsal_obj_hdl,
			       struct hpss_fsal_obj_handle,
			       obj_handle);
	HPSSFSAL_ucreds_from_opctx(op_ctx, &ucreds);

	if (xattr_id < XATTR_COUNT)
		rc = xattr_list[xattr_id].set_func(fsal_obj_hdl,
						   buffer_addr,
						   buffer_size,
						   0,
						   &ucreds);
	else {
		memset(&attr_list, 0, sizeof(hpss_userattr_list_t));

		LogFullDebug(COMPONENT_FSAL, "Setting value for UDA #%u",
			     xattr_id - XATTR_COUNT);

		/* get list of UDAs for this entry, and return the good value */
		rc = hpss_UserAttrListAttrHandle(&(obj_hdl->handle->ns_handle),
						 NULL,
						 &ucreds,
						 &attr_list,
						 XML_ATTR);

		if (rc != 0)
			return fsalstat(hpss2fsal_error(rc), rc);

		else
			if (xattr_id - XATTR_COUNT >= attr_list.len)
				return fsalstat(ERR_FSAL_STALE, 0);

		listlen = attr_list.len;

		attr_list.Pair[0].Key =
			 attr_list.Pair[xattr_id - XATTR_COUNT].Key;
		attr_list.Pair[0].Value = buffer_addr;
		attr_list.len = 1;

		rc = hpss_UserAttrSetAttrHandle(&(obj_hdl->handle->ns_handle),
						NULL,
						&ucreds,
						&attr_list,
						UDA_API_VALUE);

		/* Allocated by hpss - use free */
		for (index = 0; index < listlen; index++) {
			free(attr_list.Pair[index].Key);
			free(attr_list.Pair[index].Value);
		}
		free(attr_list.Pair);

		if (rc)
			rc = hpss2fsal_error(rc);
	}

	  return fsalstat(rc, 0);
}
Beispiel #8
0
fsal_status_t hpss_getextattr_value_by_name(
				struct fsal_obj_handle *fsal_obj_hdl,
				const char *xattr_name,
				caddr_t buffer_addr,
				size_t buffer_size,
				size_t *p_output_size)
{
	struct hpss_fsal_obj_handle *obj_hdl;
	int rc, index;
	sec_cred_t ucreds;
	hpss_userattr_list_t attr;
	char attrpath[MAXNAMLEN];
	char attrval[MAXPATHLEN];

	if (!fsal_obj_hdl || !p_output_size)
		return fsalstat(ERR_FSAL_FAULT, 0);

	/* check if this is an indexed fake xattr */
	for (index = 0; index < XATTR_COUNT; index++)
		if (do_match_type(xattr_list[index].flags,
				  fsal_obj_hdl->type)
		    && !strcmp(xattr_list[index].xattr_name, xattr_name))
			return hpss_getextattr_value_by_id(fsal_obj_hdl,
							   index,
							   buffer_addr,
							   buffer_size,
							   p_output_size);

	obj_hdl =
		 container_of(fsal_obj_hdl,
			      struct hpss_fsal_obj_handle,
			      obj_handle);
	HPSSFSAL_ucreds_from_opctx(op_ctx, &ucreds);


	if (fsal_xattr_name_2_uda(xattr_name, attrpath) == 0) {
		attr.len = 1;
		/* use malloc because HPSS may free it */
		attr.Pair = malloc(sizeof(hpss_userattr_t));
		if (attr.Pair == NULL)
			return fsalstat(ERR_FSAL_NOMEM, errno);

		attr.Pair[0].Key = attrpath;
		attr.Pair[0].Value = attrval;

		rc = hpss_UserAttrGetAttrHandle(&(obj_hdl->handle->ns_handle),
						NULL,
						&ucreds,
						&attr,
						UDA_API_VALUE);
		if (rc) {
			free(attr.Pair);
			return fsalstat(hpss2fsal_error(rc), rc);
		}

		if (attr.len > 0) {
			if (attr.Pair[0].Value != NULL) {
				char *noxml = hpss_ChompXMLHeader(
							attr.Pair[0].Value,
							NULL);
				strcpy(attrval, noxml);
				free(noxml);
				strncpy((char *)buffer_addr,
					 attrval,
					 buffer_size);
				*p_output_size = strlen(attrval) + 1;
			} else {
				strcpy((char *)buffer_addr, "");
				*p_output_size = 1;
			}

			free(attr.Pair);
			rc = 0;
		} else {
			free(attr.Pair);
			rc = ERR_FSAL_NOENT;
		}
	}

	return fsalstat(rc, 0);
}
Beispiel #9
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);
}
Beispiel #10
0
fsal_status_t posix2fsal_attributes(const struct stat *buffstat,
				    struct attrlist *fsalattr)
{
	/* sanity checks */
	if (!buffstat || !fsalattr)
		return fsalstat(ERR_FSAL_FAULT, 0);

	FSAL_CLEAR_MASK(fsalattr->mask);

	/* Fills the output struct */
	fsalattr->type = posix2fsal_type(buffstat->st_mode);
	FSAL_SET_MASK(fsalattr->mask, ATTR_TYPE);

	fsalattr->filesize = buffstat->st_size;
	FSAL_SET_MASK(fsalattr->mask, ATTR_SIZE);

	fsalattr->fsid = posix2fsal_fsid(buffstat->st_dev);
	FSAL_SET_MASK(fsalattr->mask, ATTR_FSID);

	fsalattr->fileid = buffstat->st_ino;
	FSAL_SET_MASK(fsalattr->mask, ATTR_FILEID);

	fsalattr->mode = unix2fsal_mode(buffstat->st_mode);
	FSAL_SET_MASK(fsalattr->mask, ATTR_MODE);

	fsalattr->numlinks = buffstat->st_nlink;
	FSAL_SET_MASK(fsalattr->mask, ATTR_NUMLINKS);

	fsalattr->owner = buffstat->st_uid;
	FSAL_SET_MASK(fsalattr->mask, ATTR_OWNER);

	fsalattr->group = buffstat->st_gid;
	FSAL_SET_MASK(fsalattr->mask, ATTR_GROUP);

	/* Use full timer resolution */
#ifdef LINUX
	fsalattr->atime = buffstat->st_atim;
	fsalattr->ctime = buffstat->st_ctim;
	fsalattr->mtime = buffstat->st_mtim;
	fsalattr->chgtime =
	    (gsh_time_cmp(&buffstat->st_mtim, &buffstat->st_ctim) >
	     0) ? fsalattr->mtime : fsalattr->ctime;
#elif FREEBSD
	fsalattr->atime = buffstat->st_atimespec;
	fsalattr->ctime = buffstat->st_ctimespec;
	fsalattr->mtime = buffstat->st_mtimespec;
	fsalattr->chgtime =
	    (gsh_time_cmp(&buffstat->st_mtimespec, &buffstat->st_ctimespec) >
	     0) ? fsalattr->mtime : fsalattr->ctime;
#endif
	FSAL_SET_MASK(fsalattr->mask, ATTR_ATIME);
	FSAL_SET_MASK(fsalattr->mask, ATTR_CTIME);
	FSAL_SET_MASK(fsalattr->mask, ATTR_MTIME);

	fsalattr->change = timespec_to_nsecs(&fsalattr->chgtime);
	FSAL_SET_MASK(fsalattr->mask, ATTR_CHGTIME);

	fsalattr->spaceused = buffstat->st_blocks * S_BLKSIZE;
	FSAL_SET_MASK(fsalattr->mask, ATTR_SPACEUSED);

	fsalattr->rawdev = posix2fsal_devt(buffstat->st_rdev);
	FSAL_SET_MASK(fsalattr->mask, ATTR_RAWDEV);

	return fsalstat(ERR_FSAL_NO_ERROR, 0);
}
Beispiel #11
0
int nfs3_remove(nfs_arg_t *arg, struct svc_req *req, nfs_res_t *res)
{
	struct fsal_obj_handle *parent_obj = NULL;
	struct fsal_obj_handle *child_obj = NULL;
	pre_op_attr pre_parent = {
		.attributes_follow = false
	};
	fsal_status_t fsal_status;
	const char *name = arg->arg_remove3.object.name;
	int rc = NFS_REQ_OK;

	if (isDebug(COMPONENT_NFSPROTO)) {
		char str[LEN_FH_STR];

		nfs_FhandleToStr(req->rq_msg.cb_vers,
				 &arg->arg_create3.where.dir,
				 NULL,
				 str);

		LogDebug(COMPONENT_NFSPROTO,
			 "REQUEST PROCESSING: Calling nfs_Remove handle: %s name: %s",
			 str, name);
	}

	/* Convert file handle into a pentry */
	/* to avoid setting it on each error case */
	res->res_remove3.REMOVE3res_u.resfail.dir_wcc.before.attributes_follow =
	    FALSE;
	res->res_remove3.REMOVE3res_u.resfail.dir_wcc.after.attributes_follow =
	    FALSE;

	parent_obj = nfs3_FhandleToCache(&arg->arg_remove3.object.dir,
					   &res->res_remove3.status,
					   &rc);

	if (parent_obj == NULL) {
		/* Status and rc have been set by nfs3_FhandleToCache */
		goto out;
	}

	nfs_SetPreOpAttr(parent_obj, &pre_parent);

	/* Sanity checks: file name must be non-null; parent must be a
	 * directory.
	 */
	if (parent_obj->type != DIRECTORY) {
		res->res_remove3.status = NFS3ERR_NOTDIR;
		rc = NFS_REQ_OK;
		goto out;
	}

	if (name == NULL || *name == '\0') {
		fsal_status = fsalstat(ERR_FSAL_INVAL, 0);
		goto out_fail;
	}

	/* Lookup the child entry to verify that it is not a directory */
	fsal_status = fsal_lookup(parent_obj, name, &child_obj, NULL);

	if (!FSAL_IS_ERROR(fsal_status)) {
		/* Sanity check: make sure we are not removing a
		 * directory
		 */
		if (child_obj->type == DIRECTORY) {
			res->res_remove3.status = NFS3ERR_ISDIR;
			rc = NFS_REQ_OK;
			goto out;
		}
	}

	LogFullDebug(COMPONENT_NFSPROTO, "Trying to remove file %s", name);

	/* Remove the entry. */
	fsal_status = fsal_remove(parent_obj, name);

	if (FSAL_IS_ERROR(fsal_status))
		goto out_fail;

	/* Build Weak Cache Coherency data */
	nfs_SetWccData(&pre_parent, parent_obj,
		       &res->res_remove3.REMOVE3res_u.resok.dir_wcc);

	res->res_remove3.status = NFS3_OK;
	rc = NFS_REQ_OK;

	goto out;

 out_fail:
	res->res_remove3.status = nfs3_Errno_status(fsal_status);
	nfs_SetWccData(&pre_parent, parent_obj,
		       &res->res_remove3.REMOVE3res_u.resfail.dir_wcc);

	if (nfs_RetryableError(fsal_status.major))
		rc = NFS_REQ_DROP;

 out:
	/* return references */
	if (child_obj)
		child_obj->obj_ops.put_ref(child_obj);

	if (parent_obj)
		parent_obj->obj_ops.put_ref(parent_obj);

	return rc;

}				/* nfs3_remove */

/**
 * @brief Free the result structure allocated for nfs3_remove.
 *
 * This function frees the result structure allocated for nfs3_remove.
 *
 * @param[in,out] res Result structure
 *
 */
void nfs3_remove_free(nfs_res_t *res)
{
	/* Nothing to do here */
}
Beispiel #12
0
fsal_status_t vfs_read2(struct fsal_obj_handle *obj_hdl,
			bool bypass,
			struct state_t *state,
			uint64_t offset,
			size_t buffer_size,
			void *buffer,
			size_t *read_amount,
			bool *end_of_file,
			struct io_info *info)
{
	int my_fd = -1;
	ssize_t nb_read;
	fsal_status_t status;
	int retval = 0;
	bool has_lock = false;
	bool need_fsync = false;
	bool closefd = false;

	if (info != NULL) {
		/* Currently we don't support READ_PLUS */
		return fsalstat(ERR_FSAL_NOTSUPP, 0);
	}

	if (obj_hdl->fsal != obj_hdl->fs->fsal) {
		LogDebug(COMPONENT_FSAL,
			 "FSAL %s operation for handle belonging to FSAL %s, return EXDEV",
			 obj_hdl->fsal->name, obj_hdl->fs->fsal->name);
		return fsalstat(posix2fsal_error(EXDEV), EXDEV);
	}

	/* Get a usable file descriptor */
	status = find_fd(&my_fd, obj_hdl, bypass, state, FSAL_O_READ,
			 &has_lock, &need_fsync, &closefd, false);

	if (FSAL_IS_ERROR(status))
		goto out;

	nb_read = pread(my_fd, buffer, buffer_size, offset);

	if (offset == -1 || nb_read == -1) {
		retval = errno;
		status = fsalstat(posix2fsal_error(retval), retval);
		goto out;
	}

	*read_amount = nb_read;

	*end_of_file = (nb_read == 0);

#if 0
	/** @todo
	 *
	 * Is this all we really need to do to support READ_PLUS? Will anyone
	 * ever get upset that we don't return holes, even for blocks of all
	 * zeroes?
	 *
	 */
	if (info != NULL) {
		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;
	}
#endif

 out:

	if (closefd)
		close(my_fd);

	if (has_lock)
		PTHREAD_RWLOCK_unlock(&obj_hdl->lock);

	return status;
}
Beispiel #13
0
fsal_status_t find_fd(int *fd,
		      struct fsal_obj_handle *obj_hdl,
		      bool bypass,
		      struct state_t *state,
		      fsal_openflags_t openflags,
		      bool *has_lock,
		      bool *need_fsync,
		      bool *closefd,
		      bool open_for_locks)
{
	struct vfs_fsal_obj_handle *myself;
	struct vfs_filesystem *vfs_fs;
	struct vfs_fd temp_fd = {0, -1}, *out_fd = &temp_fd;
	fsal_status_t status = {ERR_FSAL_NO_ERROR, 0};
	int rc, posix_flags;

	myself = container_of(obj_hdl, struct vfs_fsal_obj_handle, obj_handle);
	vfs_fs = myself->obj_handle.fs->private_data;

	fsal2posix_openflags(openflags, &posix_flags);

	/* Handle nom-regular files */
	switch (obj_hdl->type) {
	case SOCKET_FILE:
	case CHARACTER_FILE:
	case BLOCK_FILE:
		rc = vfs_open_by_handle(vfs_fs,
					myself->u.unopenable.dir,
					O_PATH | O_NOACCESS,
					&status.major);
		if (rc < 0) {
			LogDebug(COMPONENT_FSAL,
				 "Failed with %s openflags 0x%08x",
				 strerror(-rc), O_PATH | O_NOACCESS);
			return fsalstat(posix2fsal_error(-rc), -rc);
		}
		*fd = rc;
		*closefd = true;
		return status;

	case REGULAR_FILE:
		status = fsal_find_fd((struct fsal_fd **)&out_fd, obj_hdl,
				      (struct fsal_fd *)&myself->u.file.fd,
				      &myself->u.file.share,
				      bypass, state, openflags,
				      vfs_open_func, vfs_close_func,
				      has_lock, need_fsync,
				      closefd, open_for_locks);

		*fd = out_fd->fd;
		return status;

	case SYMBOLIC_LINK:
		posix_flags |= (O_PATH | O_RDWR | O_NOFOLLOW);
		break;

	case FIFO_FILE:
		posix_flags |= O_NONBLOCK;
		break;

	case DIRECTORY:
		break;

	case NO_FILE_TYPE:
	case EXTENDED_ATTR:
		return fsalstat(posix2fsal_error(EINVAL), EINVAL);
	}

	/* Open file descriptor for non-regular files. */
	rc = vfs_fsal_open(myself, posix_flags, &status.major);

	if (rc < 0) {
		LogDebug(COMPONENT_FSAL,
			 "Failed with %s openflags 0x%08x",
			 strerror(-rc), openflags);
		return fsalstat(posix2fsal_error(-rc), -rc);
	}

	LogFullDebug(COMPONENT_FSAL,
		     "Opened fd=%d for file of type %s",
		     rc, object_file_type_to_str(obj_hdl->type));

	*fd = rc;
	*closefd = true;

	return status;
}
Beispiel #14
0
fsal_status_t vfs_reopen2(struct fsal_obj_handle *obj_hdl,
			  struct state_t *state,
			  fsal_openflags_t openflags)
{
	struct vfs_fd fd, *my_fd = &fd, *my_share_fd;
	struct vfs_fsal_obj_handle *myself;
	fsal_status_t status = {0, 0};
	int posix_flags = 0;
	fsal_openflags_t old_openflags;

	my_share_fd = (struct vfs_fd *)(state + 1);

	fsal2posix_openflags(openflags, &posix_flags);

	LogFullDebug(COMPONENT_FSAL,
		     posix_flags & O_TRUNC ? "Truncate" : "No truncate");

	memset(my_fd, 0, sizeof(*my_fd));
	fd.fd = -1;

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

	if (obj_hdl->fsal != obj_hdl->fs->fsal) {
		LogDebug(COMPONENT_FSAL,
			 "FSAL %s operation for handle belonging to FSAL %s, return EXDEV",
			 obj_hdl->fsal->name, obj_hdl->fs->fsal->name);
		return fsalstat(posix2fsal_error(EXDEV), EXDEV);
	}

	/* This can block over an I/O operation. */
	PTHREAD_RWLOCK_wrlock(&obj_hdl->lock);

	old_openflags = my_share_fd->openflags;

	/* We can conflict with old share, so go ahead and check now. */
	status = check_share_conflict(&myself->u.file.share, openflags, false);

	if (FSAL_IS_ERROR(status)) {
		PTHREAD_RWLOCK_unlock(&obj_hdl->lock);

		return status;
	}

	/* Set up the new share so we can drop the lock and not have a
	 * conflicting share be asserted, updating the share counters.
	 */
	update_share_counters(&myself->u.file.share, old_openflags, openflags);

	PTHREAD_RWLOCK_unlock(&obj_hdl->lock);

	status = vfs_open_my_fd(myself, openflags, posix_flags, my_fd);

	if (!FSAL_IS_ERROR(status)) {
		/* Close the existing file descriptor and copy the new
		 * one over.
		 */
		vfs_close_my_fd(my_share_fd);
		*my_share_fd = fd;
	} else {
		/* We had a failure on open - we need to revert the share.
		 * This can block over an I/O operation.
		 */
		PTHREAD_RWLOCK_wrlock(&obj_hdl->lock);

		update_share_counters(&myself->u.file.share,
				      openflags,
				      old_openflags);

		PTHREAD_RWLOCK_unlock(&obj_hdl->lock);
	}

	return status;
}
Beispiel #15
0
fsal_status_t vfs_open2(struct fsal_obj_handle *obj_hdl,
			struct state_t *state,
			fsal_openflags_t openflags,
			enum fsal_create_mode createmode,
			const char *name,
			struct attrlist *attrib_set,
			fsal_verifier_t verifier,
			struct fsal_obj_handle **new_obj,
			struct attrlist *attrs_out,
			bool *caller_perm_check)
{
	int posix_flags = 0;
	int fd, dir_fd;
	int retval = 0;
	mode_t unix_mode;
	fsal_status_t status = {0, 0};
	struct vfs_fd *my_fd = NULL;
	struct vfs_fsal_obj_handle *myself, *hdl = NULL;
	struct stat stat;
	vfs_file_handle_t *fh = NULL;
	bool truncated;
	bool created = false;

	if (state != NULL)
		my_fd = (struct vfs_fd *)(state + 1);

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

	LogAttrlist(COMPONENT_FSAL, NIV_FULL_DEBUG,
		    "attrib_set ", attrib_set, false);

	fsal2posix_openflags(openflags, &posix_flags);

	truncated = (posix_flags & O_TRUNC) != 0;

	LogFullDebug(COMPONENT_FSAL,
		     truncated ? "Truncate" : "No truncate");

	if (createmode >= FSAL_EXCLUSIVE) {
		/* Now fixup attrs for verifier if exclusive create */
		set_common_verifier(attrib_set, verifier);
	}

	if (name == NULL) {
		/* This is an open by handle */
		struct vfs_fsal_obj_handle *myself;

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

		if (obj_hdl->fsal != obj_hdl->fs->fsal) {
			LogDebug(COMPONENT_FSAL,
				 "FSAL %s operation for handle belonging to FSAL %s, return EXDEV",
				 obj_hdl->fsal->name, obj_hdl->fs->fsal->name);
			return fsalstat(posix2fsal_error(EXDEV), EXDEV);
		}

		if (state != NULL) {
			/* Prepare to take the share reservation, but only if we
			 * are called with a valid state (if state is NULL the
			 * caller is a stateless create such as NFS v3 CREATE).
			 */

			/* This can block over an I/O operation. */
			PTHREAD_RWLOCK_wrlock(&obj_hdl->lock);

			/* Check share reservation conflicts. */
			status = check_share_conflict(&myself->u.file.share,
						      openflags,
						      false);

			if (FSAL_IS_ERROR(status)) {
				PTHREAD_RWLOCK_unlock(&obj_hdl->lock);
				return status;
			}

			/* Take the share reservation now by updating the
			 * counters.
			 */
			update_share_counters(&myself->u.file.share,
					      FSAL_O_CLOSED,
					      openflags);

			PTHREAD_RWLOCK_unlock(&obj_hdl->lock);
		} else {
			/* We need to use the global fd to continue, and take
			 * the lock to protect it.
			 */
			my_fd = &hdl->u.file.fd;
			PTHREAD_RWLOCK_wrlock(&obj_hdl->lock);
		}

		status = vfs_open_my_fd(myself, openflags, posix_flags, my_fd);

		if (FSAL_IS_ERROR(status)) {
			if (state == NULL) {
				/* Release the lock taken above, and return
				 * since there is nothing to undo.
				 */
				PTHREAD_RWLOCK_unlock(&obj_hdl->lock);
				return status;
			} else {
				/* Error - need to release the share */
				goto undo_share;
			}
		}

		if (createmode >= FSAL_EXCLUSIVE || truncated) {
			/* Refresh the attributes */
			struct stat stat;

			retval = fstat(my_fd->fd, &stat);

			if (retval == 0) {
				LogFullDebug(COMPONENT_FSAL,
					     "New size = %" PRIx64,
					     stat.st_size);
			} else {
				if (errno == EBADF)
					errno = ESTALE;
				status = fsalstat(posix2fsal_error(errno),
						  errno);
			}

			/* Now check verifier for exclusive, but not for
			 * FSAL_EXCLUSIVE_9P.
			 */
			if (!FSAL_IS_ERROR(status) &&
			    createmode >= FSAL_EXCLUSIVE &&
			    createmode != FSAL_EXCLUSIVE_9P &&
			    !check_verifier_stat(&stat, verifier)) {
				/* Verifier didn't match, return EEXIST */
				status =
				    fsalstat(posix2fsal_error(EEXIST), EEXIST);
			}
		}

		if (state == NULL) {
			/* If no state, release the lock taken above and return
			 * status.
			 */
			PTHREAD_RWLOCK_unlock(&obj_hdl->lock);
			return status;
		}

		if (!FSAL_IS_ERROR(status)) {
			/* Return success. */
			return status;
		}

		(void) vfs_close_my_fd(my_fd);

 undo_share:

		/* Can only get here with state not NULL and an error */

		/* On error we need to release our share reservation
		 * and undo the update of the share counters.
		 * This can block over an I/O operation.
		 */
		PTHREAD_RWLOCK_wrlock(&obj_hdl->lock);

		update_share_counters(&myself->u.file.share,
				      openflags,
				      FSAL_O_CLOSED);

		PTHREAD_RWLOCK_unlock(&obj_hdl->lock);

		return status;
	}

	/* In this path where we are opening by name, we can't check share
	 * reservation yet since we don't have an object_handle yet. If we
	 * indeed create the object handle (there is no race with another
	 * open by name), then there CAN NOT be a share conflict, otherwise
	 * the share conflict will be resolved when the object handles are
	 * merged.
	 */

#ifdef ENABLE_VFS_DEBUG_ACL
	if (createmode != FSAL_NO_CREATE) {
		/* Need to ammend attributes for inherited ACL, these will be
		 * set later. We also need to test for permission to create
		 * since there might be an ACL.
		 */
		struct attrlist attrs;
		fsal_accessflags_t access_type;

		access_type = FSAL_MODE_MASK_SET(FSAL_W_OK) |
			FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_ADD_FILE);
		status = obj_hdl->obj_ops.test_access(obj_hdl, access_type,
						      NULL, NULL, false);

		if (FSAL_IS_ERROR(status))
			return status;

		fsal_prepare_attrs(&attrs, ATTR_ACL);

		status = obj_hdl->obj_ops.getattrs(obj_hdl, &attrs);

		if (FSAL_IS_ERROR(status))
			return status;

		status.major = fsal_inherit_acls(attrib_set, attrs.acl,
						 FSAL_ACE_FLAG_FILE_INHERIT);

		/* Done with the attrs */
		fsal_release_attrs(&attrs);

		if (FSAL_IS_ERROR(status))
			return status;
	}
#endif /* ENABLE_VFS_DEBUG_ACL */

	if (createmode != FSAL_NO_CREATE) {
		/* Now add in O_CREAT and O_EXCL. */
		posix_flags |= O_CREAT;

		/* And if we are at least FSAL_GUARDED, do an O_EXCL create. */
		if (createmode >= FSAL_GUARDED)
			posix_flags |= O_EXCL;

		/* Fetch the mode attribute to use in the openat system call. */
		unix_mode = fsal2unix_mode(attrib_set->mode) &
		    ~op_ctx->fsal_export->exp_ops.fs_umask(op_ctx->fsal_export);

		/* Don't set the mode if we later set the attributes */
		FSAL_UNSET_MASK(attrib_set->mask, ATTR_MODE);
	}

	if (createmode == FSAL_UNCHECKED && (attrib_set->mask != 0)) {
		/* If we have FSAL_UNCHECKED and want to set more attributes
		 * than the mode, we attempt an O_EXCL create first, if that
		 * succeeds, then we will be allowed to set the additional
		 * attributes, otherwise, we don't know we created the file
		 * and this can NOT set the attributes.
		 */
		posix_flags |= O_EXCL;
	}

	dir_fd = vfs_fsal_open(myself, O_PATH | O_NOACCESS, &status.major);

	if (dir_fd < 0)
		return fsalstat(status.major, -dir_fd);

	/** @todo: not sure what this accomplishes... */
	retval = vfs_stat_by_handle(dir_fd, &stat);

	if (retval < 0) {
		retval = errno;
		status = fsalstat(posix2fsal_error(retval), retval);
		goto direrr;
	}

	/* Become the user because we are creating an object in this dir.
	 */
	if (createmode != FSAL_NO_CREATE)
		fsal_set_credentials(op_ctx->creds);

	if ((posix_flags & O_CREAT) != 0)
		fd = openat(dir_fd, name, posix_flags, unix_mode);
	else
		fd = openat(dir_fd, name, posix_flags);

	if (fd == -1 && errno == EEXIST && createmode == FSAL_UNCHECKED) {
		/* We tried to create O_EXCL to set attributes and failed.
		 * Remove O_EXCL and retry. We still try O_CREAT again just in
		 * case file disappears out from under us.
		 *
		 * Note that because we have dropped O_EXCL, later on we will
		 * not assume we created the file, and thus will not set
		 * additional attributes. We don't need to separately track
		 * the condition of not wanting to set attributes.
		 */
		posix_flags &= ~O_EXCL;
		fd = openat(dir_fd, name, posix_flags, unix_mode);
	}

	/* Preserve errno */
	retval = errno;

	/* If we were creating, restore credentials now. */
	if (createmode != FSAL_NO_CREATE)
		fsal_restore_ganesha_credentials();

	if (fd < 0) {
		status = fsalstat(posix2fsal_error(retval), retval);
		goto direrr;
	}

	/* Remember if we were responsible for creating the file.
	 * Note that in an UNCHECKED retry we MIGHT have re-created the
	 * file and won't remember that. Oh well, so in that rare case we
	 * leak a partially created file if we have a subsequent error in here.
	 * Also notify caller to do permission check if we DID NOT create the
	 * file. Note it IS possible in the case of a race between an UNCHECKED
	 * open and an external unlink, we did create the file, but we will
	 * still force a permission check. Of course that permission check
	 * SHOULD succeed since we also won't set the mode the caller requested
	 * and the default file create permissions SHOULD allow the owner
	 * read/write.
	 */
	created = (posix_flags & O_EXCL) != 0;
	*caller_perm_check = !created;

	vfs_alloc_handle(fh);

	retval = vfs_name_to_handle(dir_fd, obj_hdl->fs, name, fh);

	if (retval < 0) {
		retval = errno;
		status = fsalstat(posix2fsal_error(retval), retval);
		goto fileerr;
	}

	retval = fstat(fd, &stat);

	if (retval < 0) {
		retval = errno;
		status = fsalstat(posix2fsal_error(retval), retval);
		goto fileerr;
	}

	/* allocate an obj_handle and fill it up */
	hdl = alloc_handle(dir_fd, fh, obj_hdl->fs, &stat, myself->handle, name,
			   op_ctx->fsal_export);

	if (hdl == NULL) {
		status = fsalstat(posix2fsal_error(ENOMEM), ENOMEM);
		goto fileerr;
	}

	/* If we didn't have a state above, use the global fd. At this point,
	 * since we just created the global fd, no one else can have a
	 * reference to it, and thus we can mamnipulate unlocked which is
	 * handy since we can then call setattr2 which WILL take the lock
	 * without a double locking deadlock.
	 */
	if (my_fd == NULL)
		my_fd = &hdl->u.file.fd;

	my_fd->fd = fd;
	my_fd->openflags = openflags;

	*new_obj = &hdl->obj_handle;

	if (created && attrib_set->mask != 0) {
		/* Set attributes using our newly opened file descriptor as the
		 * share_fd if there are any left to set (mode and truncate
		 * have already been handled).
		 *
		 * Note that we only set the attributes if we were responsible
		 * for creating the file and we have attributes to set.
		 *
		 * Note if we have ENABLE_VFS_DEBUG_ACL an inherited ACL might
		 * be part of the attributes we are setting here.
		 */
		status = (*new_obj)->obj_ops.setattr2(*new_obj,
						      false,
						      state,
						      attrib_set);

		if (FSAL_IS_ERROR(status)) {
			/* Release the handle we just allocated. */
			(*new_obj)->obj_ops.release(*new_obj);
			*new_obj = NULL;
			goto fileerr;
		}

		if (attrs_out != NULL) {
			status = (*new_obj)->obj_ops.getattrs(*new_obj,
							      attrs_out);
			if (FSAL_IS_ERROR(status) &&
			    (attrs_out->mask & ATTR_RDATTR_ERR) == 0) {
				/* Get attributes failed and caller expected
				 * to get the attributes. Otherwise continue
				 * with attrs_out indicating ATTR_RDATTR_ERR.
				 */
				goto fileerr;
			}
		}
	} else if (attrs_out != NULL) {
		/* Since we haven't set any attributes other than what was set
		 * on create (if we even created), just use the stat results
		 * we used to create the fsal_obj_handle.
		 */
		posix2fsal_attributes(&stat, attrs_out);

		/* Make sure ATTR_RDATTR_ERR is cleared on success. */
		attrs_out->mask &= ~ATTR_RDATTR_ERR;
	}

	close(dir_fd);

	if (state != NULL) {
		/* Prepare to take the share reservation, but only if we are
		 * called with a valid state (if state is NULL the caller is
		 * a stateless create such as NFS v3 CREATE).
		 */

		/* This can block over an I/O operation. */
		PTHREAD_RWLOCK_wrlock(&(*new_obj)->lock);

		/* Take the share reservation now by updating the counters. */
		update_share_counters(&hdl->u.file.share,
				      FSAL_O_CLOSED,
				      openflags);

		PTHREAD_RWLOCK_unlock(&(*new_obj)->lock);
	}

	return fsalstat(ERR_FSAL_NO_ERROR, 0);

 fileerr:

	close(fd);

	/* Delete the file if we actually created it. */
	if (created)
		unlinkat(dir_fd, name, 0);

 direrr:

	close(dir_fd);
	return fsalstat(posix2fsal_error(retval), retval);
}
Beispiel #16
0
/**
 * @brief Set attributes on an object
 *
 * This function sets attributes on an object.  Which attributes are
 * set is determined by attrib_set->mask. The FSAL must manage bypass
 * or not of share reservations, and a state may be passed.
 *
 * @param[in] obj_hdl    File on which to operate
 * @param[in] state      state_t to use for this operation
 * @param[in] attrib_set Attributes to set
 *
 * @return FSAL status.
 */
fsal_status_t vfs_setattr2(struct fsal_obj_handle *obj_hdl,
			   bool bypass,
			   struct state_t *state,
			   struct attrlist *attrib_set)
{
	struct vfs_fsal_obj_handle *myself;
	fsal_status_t status = {0, 0};
	int retval = 0;
	fsal_openflags_t openflags = FSAL_O_ANY;
	bool has_lock = false;
	bool need_fsync = false;
	bool closefd = false;
	int my_fd;
	const char *func;

	/* apply umask, if mode attribute is to be changed */
	if (FSAL_TEST_MASK(attrib_set->mask, ATTR_MODE))
		attrib_set->mode &=
		    ~op_ctx->fsal_export->exp_ops.fs_umask(op_ctx->fsal_export);

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

	if (obj_hdl->fsal != obj_hdl->fs->fsal) {
		LogDebug(COMPONENT_FSAL,
			 "FSAL %s operation for handle belonging to FSAL %s, return EXDEV",
			 obj_hdl->fsal->name,
			 obj_hdl->fs->fsal != NULL
				? obj_hdl->fs->fsal->name
				: "(none)");
		return fsalstat(posix2fsal_error(EXDEV), EXDEV);
	}

#ifdef ENABLE_VFS_DEBUG_ACL
#ifdef ENABLE_RFC_ACL
	if (FSAL_TEST_MASK(attrib_set->mask, ATTR_MODE) &&
	    !FSAL_TEST_MASK(attrib_set->mask, ATTR_ACL)) {
		/* Set ACL from MODE */
		struct attrlist attrs;

		fsal_prepare_attrs(&attrs, ATTR_ACL);

		status = obj_hdl->obj_ops.getattrs(obj_hdl, &attrs);

		if (FSAL_IS_ERROR(status))
			return status;

		status = fsal_mode_to_acl(attrib_set, attrs.acl);

		/* Done with the attrs */
		fsal_release_attrs(&attrs);
	} else {
		/* If ATTR_ACL is set, mode needs to be adjusted no matter what.
		 * See 7530 s 6.4.1.3 */
		if (!FSAL_TEST_MASK(attrib_set->mask, ATTR_MODE))
			attrib_set->mode = myself->mode;
		status = fsal_acl_to_mode(attrib_set);
	}

	if (FSAL_IS_ERROR(status))
		return status;
#endif /* ENABLE_RFC_ACL */
#endif

	/* This is yet another "you can't get there from here".  If this object
	 * is a socket (AF_UNIX), an fd on the socket s useless _period_.
	 * If it is for a symlink, without O_PATH, you will get an ELOOP error
	 * and (f)chmod doesn't work for a symlink anyway - not that it matters
	 * because access checking is not done on the symlink but the final
	 * target.
	 * AF_UNIX sockets are also ozone material.  If the socket is already
	 * active listeners et al, you can manipulate the mode etc.  If it is
	 * just sitting there as in you made it with a mknod.
	 * (one of those leaky abstractions...)
	 * or the listener forgot to unlink it, it is lame duck.
	 */

	/* Test if size is being set, make sure file is regular and if so,
	 * require a read/write file descriptor.
	 */
	if (FSAL_TEST_MASK(attrib_set->mask, ATTR_SIZE)) {
		if (obj_hdl->type != REGULAR_FILE) {
			LogFullDebug(COMPONENT_FSAL,
				     "Setting size on non-regular file");
			return fsalstat(ERR_FSAL_INVAL, EINVAL);
		}
		openflags = FSAL_O_RDWR;
	}

	/* Get a usable file descriptor. Share conflict is only possible if
	 * size is being set.
	 */
	status = find_fd(&my_fd, obj_hdl, bypass, state, openflags,
			 &has_lock, &need_fsync, &closefd, false);

	if (FSAL_IS_ERROR(status)) {
		if (obj_hdl->type == SYMBOLIC_LINK &&
		    status.major == ERR_FSAL_PERM) {
			/* You cannot open_by_handle (XFS) a symlink and it
			 * throws an EPERM error for it.  open_by_handle_at
			 * does not throw that error for symlinks so we play a
			 * game here.  Since there is not much we can do with
			 * symlinks anyway, say that we did it
			 * but don't actually do anything.
			 * If you *really* want to tweek things
			 * like owners, get a modern linux kernel...
			 */
			status = fsalstat(ERR_FSAL_NO_ERROR, 0);
		}
		LogFullDebug(COMPONENT_FSAL,
			     "find_fd status=%s",
			     fsal_err_txt(status));
		goto out;
	}

	/** TRUNCATE **/
	if (FSAL_TEST_MASK(attrib_set->mask, ATTR_SIZE)) {
		retval = ftruncate(my_fd, attrib_set->filesize);
		if (retval != 0) {
			/** @todo FSF: is this still necessary?
			 *
			 * XXX ESXi volume creation pattern reliably
			 * reached this point in the past, however now that we
			 * only use the already open file descriptor if it is
			 * open read/write, this may no longer fail.
			 * If there is some other error from ftruncate, then
			 * we will needlessly retry, but without more detail
			 * of the original failure, we can't be sure.
			 * Fortunately permission checking is done by
			 * Ganesha before calling here, so we won't get an
			 * EACCES since this call is done as root. We could
			 * get EFBIG, EPERM, or EINVAL.
			 */
			/** @todo FSF: re-open if we really still need this
			 */

			retval = ftruncate(my_fd, attrib_set->filesize);
			if (retval != 0) {
				func = "truncate";
				goto fileerr;
			}
		}
	}

	/** CHMOD **/
	if (FSAL_TEST_MASK(attrib_set->mask, ATTR_MODE)) {
		/* The POSIX chmod call doesn't affect the symlink object, but
		 * the entry it points to. So we must ignore it.
		 */
		if (obj_hdl->type != SYMBOLIC_LINK) {
			if (vfs_unopenable_type(obj_hdl->type))
				retval = fchmodat(
					my_fd,
					myself->u.unopenable.name,
					fsal2unix_mode(attrib_set->mode),
					0);
			else
				retval = fchmod(
					my_fd,
					fsal2unix_mode(attrib_set->mode));

			if (retval != 0) {
				func = "chmod";
				goto fileerr;
			}
		}
	}

	/**  CHOWN  **/
	if (FSAL_TEST_MASK(attrib_set->mask, ATTR_OWNER | ATTR_GROUP)) {
		uid_t user = FSAL_TEST_MASK(attrib_set->mask, ATTR_OWNER)
		    ? (int)attrib_set->owner : -1;
		gid_t group = FSAL_TEST_MASK(attrib_set->mask, ATTR_GROUP)
		    ? (int)attrib_set->group : -1;

		if (vfs_unopenable_type(obj_hdl->type))
			retval = fchownat(my_fd, myself->u.unopenable.name,
					  user, group, AT_SYMLINK_NOFOLLOW);
		else if (obj_hdl->type == SYMBOLIC_LINK)
			retval = fchownat(my_fd, "", user, group,
					  AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH);
		else
			retval = fchown(my_fd, user, group);

		if (retval) {
			func = "chown";
			goto fileerr;
		}
	}

	/**  UTIME  **/
	if (FSAL_TEST_MASK(attrib_set->mask, ATTRS_SET_TIME)) {
		struct timespec timebuf[2];

		if (obj_hdl->type == SYMBOLIC_LINK)
			goto out; /* Setting time on symlinks is illegal */
		/* Atime */
		if (FSAL_TEST_MASK(attrib_set->mask, ATTR_ATIME_SERVER)) {
			timebuf[0].tv_sec = 0;
			timebuf[0].tv_nsec = UTIME_NOW;
		} else if (FSAL_TEST_MASK(attrib_set->mask, ATTR_ATIME)) {
			timebuf[0] = attrib_set->atime;
		} else {
			timebuf[0].tv_sec = 0;
			timebuf[0].tv_nsec = UTIME_OMIT;
		}

		/* Mtime */
		if (FSAL_TEST_MASK(attrib_set->mask, ATTR_MTIME_SERVER)) {
			timebuf[1].tv_sec = 0;
			timebuf[1].tv_nsec = UTIME_NOW;
		} else if (FSAL_TEST_MASK(attrib_set->mask, ATTR_MTIME)) {
			timebuf[1] = attrib_set->mtime;
		} else {
			timebuf[1].tv_sec = 0;
			timebuf[1].tv_nsec = UTIME_OMIT;
		}
		if (vfs_unopenable_type(obj_hdl->type))
			retval = vfs_utimesat(my_fd, myself->u.unopenable.name,
					      timebuf, AT_SYMLINK_NOFOLLOW);
		else
			retval = vfs_utimes(my_fd, timebuf);
		if (retval != 0) {
			func = "utimes";
			goto fileerr;
		}
	}

	/** SUBFSAL **/
	if (myself->sub_ops && myself->sub_ops->setattrs) {
		status = myself->sub_ops->setattrs(
					myself,
					my_fd,
					attrib_set->mask, attrib_set);
		if (FSAL_IS_ERROR(status))
			goto out;
	}

	errno = 0;

 fileerr:

	retval = errno;

	if (retval != 0) {
		LogDebug(COMPONENT_FSAL,
			 "%s returned %s",
			 func, strerror(retval));
	}

	status = fsalstat(posix2fsal_error(retval), retval);

 out:

	if (closefd)
		close(my_fd);

	if (has_lock)
		PTHREAD_RWLOCK_unlock(&obj_hdl->lock);

	return status;
}
Beispiel #17
0
fsal_status_t fetch_attrs(struct vfs_fsal_obj_handle *myself,
			  int my_fd, struct attrlist *attrs)
{
	struct stat stat;
	int retval = 0;
	fsal_status_t status = {0, 0};
	const char *func = "unknown";

	/* Now stat the file as appropriate */
	switch (myself->obj_handle.type) {
	case SOCKET_FILE:
	case CHARACTER_FILE:
	case BLOCK_FILE:
		retval = fstatat(my_fd, myself->u.unopenable.name, &stat,
				 AT_SYMLINK_NOFOLLOW);
		func = "fstatat";
		break;

	case REGULAR_FILE:
		retval = fstat(my_fd, &stat);
		func = "fstat";
		break;

	case SYMBOLIC_LINK:
	case FIFO_FILE:
	case DIRECTORY:
		retval = vfs_stat_by_handle(my_fd, &stat);
		func = "vfs_stat_by_handle";
		break;

	case NO_FILE_TYPE:
	case EXTENDED_ATTR:
		/* Caught during open with EINVAL */
		break;
	}

	if (retval < 0) {
		if (errno == ENOENT)
			retval = ESTALE;
		else
			retval = errno;

		LogDebug(COMPONENT_FSAL, "%s failed with %s", func,
			 strerror(retval));

		if (attrs->mask & ATTR_RDATTR_ERR) {
			/* Caller asked for error to be visible. */
			attrs->mask = ATTR_RDATTR_ERR;
		}

		return fsalstat(posix2fsal_error(retval), retval);
	}

	posix2fsal_attributes(&stat, attrs);
	attrs->fsid = myself->obj_handle.fs->fsid;

	if (myself->sub_ops && myself->sub_ops->getattrs) {
		status =
		   myself->sub_ops->getattrs(myself, my_fd, attrs->mask, attrs);

		if (FSAL_IS_ERROR(status) &&
		    (attrs->mask & ATTR_RDATTR_ERR) != 0) {
			/* Caller asked for error to be visible. */
			attrs->mask = ATTR_RDATTR_ERR;
		}
	}

	if (!FSAL_IS_ERROR(status)) {
		/* Make sure ATTR_RDATTR_ERR is cleared on success. */
		attrs->mask &= ~ATTR_RDATTR_ERR;
	}

	return status;
}
Beispiel #18
0
/* Covert FSAL ACLs to GPFS NFS4 ACLs. */
fsal_status_t fsal_acl_2_gpfs_acl(struct fsal_obj_handle *dir_hdl,
				  fsal_acl_t *p_fsalacl,
				  gpfsfsal_xstat_t *p_buffxstat)
{
	int i;
	fsal_ace_t *pace;
	gpfs_acl_t *p_gpfsacl;

	p_gpfsacl = (gpfs_acl_t *) p_buffxstat->buffacl;

	p_gpfsacl->acl_level = 0;
	p_gpfsacl->acl_version = GPFS_ACL_VERSION_NFS4;
	p_gpfsacl->acl_type = GPFS_ACL_TYPE_NFS4;
	p_gpfsacl->acl_nace = p_fsalacl->naces;
	p_gpfsacl->acl_len =
	    ((int)(signed long)&(((gpfs_acl_t *) 0)->ace_v1)) +
	    p_gpfsacl->acl_nace * sizeof(gpfs_ace_v4_t);

	for (pace = p_fsalacl->aces, i = 0;
	     pace < p_fsalacl->aces + p_fsalacl->naces; pace++, i++) {
		p_gpfsacl->ace_v4[i].aceType = pace->type;
		p_gpfsacl->ace_v4[i].aceFlags = pace->flag;
		p_gpfsacl->ace_v4[i].aceIFlags = pace->iflag;
		p_gpfsacl->ace_v4[i].aceMask = pace->perm;

		if (IS_FSAL_ACE_SPECIAL_ID(*pace))
			p_gpfsacl->ace_v4[i].aceWho = pace->who.uid;
		else {
			if (IS_FSAL_ACE_GROUP_ID(*pace))
				p_gpfsacl->ace_v4[i].aceWho = pace->who.gid;
			else
				p_gpfsacl->ace_v4[i].aceWho = pace->who.uid;
		}

		LogMidDebug(COMPONENT_FSAL,
			 "fsal_acl_2_gpfs_acl: gpfs ace: type = 0x%x, flag = 0x%x, perm = 0x%x, special = %d, %s = 0x%x",
			 p_gpfsacl->ace_v4[i].aceType,
			 p_gpfsacl->ace_v4[i].aceFlags,
			 p_gpfsacl->ace_v4[i].aceMask,
			 (p_gpfsacl->ace_v4[i].
			  aceIFlags & FSAL_ACE_IFLAG_SPECIAL_ID) ? 1 : 0,
			 (p_gpfsacl->ace_v4[i].
			  aceFlags & FSAL_ACE_FLAG_GROUP_ID) ? "gid" : "uid",
			 p_gpfsacl->ace_v4[i].aceWho);

		/* It is invalid to set inherit flags on non dir objects */
		if (dir_hdl->type != DIRECTORY &&
		    (p_gpfsacl->ace_v4[i].aceFlags &
		    FSAL_ACE_FLAG_INHERIT) != 0) {
			LogMidDebug(COMPONENT_FSAL,
			   "attempt to set inherit flag to non dir object");
			return fsalstat(ERR_FSAL_INVAL, 0);
		}

		/* It is invalid to set inherit only with
		 * out an actual inherit flag */
		if ((p_gpfsacl->ace_v4[i].aceFlags & FSAL_ACE_FLAG_INHERIT) ==
			FSAL_ACE_FLAG_INHERIT_ONLY) {
			LogMidDebug(COMPONENT_FSAL,
			   "attempt to set inherit only without an inherit flag");
			return fsalstat(ERR_FSAL_INVAL, 0);
		}

	}

	return fsalstat(ERR_FSAL_NO_ERROR, 0);
}
Beispiel #19
0
/* Same function as posixstat64_2_fsal_attributes. When NFS4 ACL support
 * is enabled, this will replace posixstat64_2_fsal_attributes. */
fsal_status_t gpfsfsal_xstat_2_fsal_attributes(gpfsfsal_xstat_t *p_buffxstat,
					       struct attrlist *p_fsalattr_out,
					       bool use_acl)
{
	struct stat *p_buffstat;

	/* sanity checks */
	if (!p_buffxstat || !p_fsalattr_out)
		return fsalstat(ERR_FSAL_FAULT, 0);

	p_buffstat = &p_buffxstat->buffstat;

	LogDebug(COMPONENT_FSAL, "inode %ld", p_buffstat->st_ino);

	/* Fills the output struct */
	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_TYPE)) {
		p_fsalattr_out->type = posix2fsal_type(p_buffstat->st_mode);
		LogFullDebug(COMPONENT_FSAL, "type = 0x%x",
			     p_fsalattr_out->type);
	}
	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_SIZE)) {
		p_fsalattr_out->filesize = p_buffstat->st_size;
		LogFullDebug(COMPONENT_FSAL, "filesize = %llu",
			     (unsigned long long)p_fsalattr_out->filesize);
	}
	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_FSID)) {
		p_fsalattr_out->fsid = p_buffxstat->fsal_fsid;
		LogFullDebug(COMPONENT_FSAL,
			     "fsid=0x%016"PRIx64".0x%016"PRIx64,
			     p_fsalattr_out->fsid.major,
			     p_fsalattr_out->fsid.minor);
	}
	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_ACL)) {
		p_fsalattr_out->acl = NULL;
		if (use_acl && p_buffxstat->attr_valid & XATTR_ACL) {
			/* ACL is valid, so try to convert fsal acl. */
			gpfs_acl_2_fsal_acl(p_fsalattr_out,
					    (gpfs_acl_t *) p_buffxstat->
					    buffacl);
		}
		LogFullDebug(COMPONENT_FSAL, "acl = %p", p_fsalattr_out->acl);
	}
	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_FILEID)) {
		p_fsalattr_out->fileid = (uint64_t) (p_buffstat->st_ino);
		LogFullDebug(COMPONENT_FSAL, "fileid = %lu",
			     p_fsalattr_out->fileid);
	}

	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_MODE)) {
		p_fsalattr_out->mode = unix2fsal_mode(p_buffstat->st_mode);
		LogFullDebug(COMPONENT_FSAL, "mode = %"PRIu32,
			     p_fsalattr_out->mode);
	}
	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_NUMLINKS)) {
		p_fsalattr_out->numlinks = p_buffstat->st_nlink;
		LogFullDebug(COMPONENT_FSAL, "numlinks = %u",
			     p_fsalattr_out->numlinks);
	}
	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_OWNER)) {
		p_fsalattr_out->owner = p_buffstat->st_uid;
		LogFullDebug(COMPONENT_FSAL, "owner = %lu",
			     p_fsalattr_out->owner);
	}
	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_GROUP)) {
		p_fsalattr_out->group = p_buffstat->st_gid;
		LogFullDebug(COMPONENT_FSAL, "group = %lu",
			     p_fsalattr_out->group);
	}
	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_ATIME)) {
		p_fsalattr_out->atime =
		    posix2fsal_time(p_buffstat->st_atime,
				    p_buffstat->st_atim.tv_nsec);
		LogFullDebug(COMPONENT_FSAL, "atime = %lu",
			     p_fsalattr_out->atime.tv_sec);
	}

	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_CTIME)) {
		p_fsalattr_out->ctime =
		    posix2fsal_time(p_buffstat->st_ctime,
				    p_buffstat->st_ctim.tv_nsec);
		LogFullDebug(COMPONENT_FSAL, "ctime = %lu",
			     p_fsalattr_out->ctime.tv_sec);
	}
	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_MTIME)) {
		p_fsalattr_out->mtime =
		    posix2fsal_time(p_buffstat->st_mtime,
				    p_buffstat->st_mtim.tv_nsec);
		LogFullDebug(COMPONENT_FSAL, "mtime = %lu",
			     p_fsalattr_out->mtime.tv_sec);
	}

	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_CHGTIME)) {
		if (p_buffstat->st_mtime == p_buffstat->st_ctime) {
			if (p_buffstat->st_mtim.tv_nsec >
			    p_buffstat->st_ctim.tv_nsec)
				p_fsalattr_out->chgtime =
				    posix2fsal_time(p_buffstat->st_mtime,
						    p_buffstat->st_mtim.
						    tv_nsec);
			else
				p_fsalattr_out->chgtime =
				    posix2fsal_time(p_buffstat->st_ctime,
						    p_buffstat->st_ctim.
						    tv_nsec);
		} else if (p_buffstat->st_mtime > p_buffstat->st_ctime) {
			p_fsalattr_out->chgtime =
			    posix2fsal_time(p_buffstat->st_mtime,
					    p_buffstat->st_mtim.tv_nsec);
		} else {
			p_fsalattr_out->chgtime =
			    posix2fsal_time(p_buffstat->st_ctime,
					    p_buffstat->st_ctim.tv_nsec);
		}
		p_fsalattr_out->change =
		    (uint64_t) p_fsalattr_out->chgtime.tv_sec +
		    (uint64_t) p_fsalattr_out->chgtime.tv_nsec;
		LogFullDebug(COMPONENT_FSAL, "chgtime = %lu",
			     p_fsalattr_out->chgtime.tv_sec);

	}

	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_SPACEUSED)) {
		p_fsalattr_out->spaceused = p_buffstat->st_blocks * S_BLKSIZE;
		LogFullDebug(COMPONENT_FSAL, "spaceused = %llu",
			     (unsigned long long)p_fsalattr_out->spaceused);
	}

	if (FSAL_TEST_MASK(p_fsalattr_out->mask, ATTR_RAWDEV)) {
		p_fsalattr_out->rawdev = posix2fsal_devt(p_buffstat->st_rdev);
		LogFullDebug(COMPONENT_FSAL, "rawdev major = %u, minor = %u",
			     (unsigned int)p_fsalattr_out->rawdev.major,
			     (unsigned int)p_fsalattr_out->rawdev.minor);
	}

	/* everything has been copied ! */

	return fsalstat(ERR_FSAL_NO_ERROR, 0);
}
Beispiel #20
0
fsal_status_t hpss_remove_extattr_by_id(struct fsal_obj_handle *obj_hdl,
					unsigned int xattr_id)
{
	return fsalstat(ERR_FSAL_NOTSUPP, 0);
}
Beispiel #21
0
static fsal_status_t init_config(struct fsal_module *fsal_hdl,
				 config_file_t config_struct)
{
	return fsalstat(ERR_FSAL_NO_ERROR, 0);
}
Beispiel #22
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);

}
Beispiel #23
0
fsal_status_t hpss_remove_extattr_by_name(struct fsal_obj_handle *obj_hdl,
					  const char *xattr_name)
{
	return fsalstat(ERR_FSAL_NOTSUPP, 0);
}
Beispiel #24
0
fsal_status_t GPFSFSAL_unlink(struct fsal_obj_handle *dir_hdl,	/* IN */
			      const char *p_object_name,	/* IN */
			      const struct req_op_context *p_context,	/* IN */
			      struct attrlist *p_parent_attributes)
{				/* IN/OUT */

	fsal_status_t status;
	gpfsfsal_xstat_t buffxstat;
	int mount_fd;
	struct gpfs_fsal_obj_handle *gpfs_hdl;

	/* sanity checks. */
	if (!dir_hdl || !p_context || !p_object_name)
		return fsalstat(ERR_FSAL_FAULT, 0);

	gpfs_hdl =
	    container_of(dir_hdl, struct gpfs_fsal_obj_handle, obj_handle);
	mount_fd = gpfs_get_root_fd(dir_hdl->export);

	/* build the child path */

	/* get file metadata */
	status =
	    fsal_internal_stat_name(mount_fd, gpfs_hdl->handle, p_object_name,
				    &buffxstat.buffstat);
	if (FSAL_IS_ERROR(status))
		return status;

  /******************************
   * DELETE FROM THE FILESYSTEM *
   ******************************/
	fsal_set_credentials(p_context->creds);

	status =
	    fsal_internal_unlink(mount_fd, gpfs_hdl->handle, p_object_name,
				 &buffxstat.buffstat);

	fsal_restore_ganesha_credentials();

	if (FSAL_IS_ERROR(status))
		return status;

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

	if (p_parent_attributes) {
		buffxstat.attr_valid = XATTR_STAT;
		status =
		    gpfsfsal_xstat_2_fsal_attributes(&buffxstat,
						     p_parent_attributes);
		if (FSAL_IS_ERROR(status)) {
			FSAL_CLEAR_MASK(p_parent_attributes->mask);
			FSAL_SET_MASK(p_parent_attributes->mask,
				      ATTR_RDATTR_ERR);
		}
	}
	/* OK */
	return fsalstat(ERR_FSAL_NO_ERROR, 0);

}
Beispiel #25
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);

}
Beispiel #26
0
fsal_status_t hpss_list_ext_attrs(struct fsal_obj_handle *fsal_obj_hdl,
				  unsigned int cookie,
				  fsal_xattrent_t *xattrs_tab,
				  unsigned int xattrs_tabsize,
				  unsigned int *p_nb_returned,
				  int *end_of_list)
{
	struct hpss_fsal_obj_handle *obj_hdl;
	int index, out_index, rc;
	sec_cred_t ucreds;
	hpss_userattr_list_t attr_list;

	if (!fsal_obj_hdl || !xattrs_tab || !p_nb_returned || !end_of_list)
		return fsalstat(ERR_FSAL_FAULT, 0);

	obj_hdl = container_of(fsal_obj_hdl,
			       struct hpss_fsal_obj_handle,
			       obj_handle);
	HPSSFSAL_ucreds_from_opctx(op_ctx, &ucreds);

	for (index = cookie,
	     out_index = 0;
	     index < XATTR_COUNT && out_index < xattrs_tabsize; index++) {
		if (do_match_type(xattr_list[index].flags,
				  fsal_obj_hdl->type)) {

			/* fills an xattr entry */
			xattrs_tab[out_index].xattr_id = index;
			memcpy(xattrs_tab[out_index].xattr_name,
			       xattr_list[index].xattr_name,
			       strlen(xattr_list[index].xattr_name)+1);
			xattrs_tab[out_index].xattr_cookie = index + 1;

			/* set asked attributes */
			file_attributes_to_xattr_attrs(
					&obj_hdl->attributes,
					&xattrs_tab[out_index].attributes,
					index);

			/* 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 list of UDAs for this entry */
	memset(&attr_list, 0, sizeof(hpss_userattr_list_t));

	rc = hpss_UserAttrListAttrHandle(&(obj_hdl->handle->ns_handle),
					 NULL,
					 &ucreds,
					 &attr_list,
					 XML_ATTR);

	if (rc == -ENOENT)
		attr_list.len = 0;
	else
		if (rc)
			return fsalstat(hpss2fsal_error(rc), -rc);

	unsigned int i;

	for (i = 0; (i < attr_list.len) && (out_index < xattrs_tabsize); i++) {
		char attr_name[MAXNAMLEN];

		/* the id is XATTR_COUNT + index of HPSS UDA */
		index = XATTR_COUNT + i;

		/* continue while index < cookie */
		if (index < cookie)
			continue;

		xattrs_tab[out_index].xattr_id = index;

		if (strlen(attr_list.Pair[i].Key) >= MAXNAMLEN)
			return fsalstat(ERR_FSAL_NAMETOOLONG, 0);

		/* HPSS UDAs namespace is slash-separated.
		 * we convert '/' to '.'
		 */
		rc = hpss_uda_name_2_fsal(attr_list.Pair[i].Key, attr_name);

		if (rc != ERR_FSAL_NO_ERROR)
			return fsalstat(rc, 0);

		memcpy(xattrs_tab[out_index].xattr_name,
		       attr_name,
		       strlen(attr_name)+1);
		xattrs_tab[out_index].xattr_cookie = index + 1;

		/* set asked attributes */
		file_attributes_to_xattr_attrs(
					&obj_hdl->attributes,
					&xattrs_tab[out_index].attributes,
					index);

		/* we know the size here (+2 for \n\0) */
		if (attr_list.Pair[i].Value != NULL)
			xattrs_tab[out_index].attributes.filesize =
				 strlen(attr_list.Pair[i].Value) + 2;

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

	/* Allocated by hpss - use free */
	for (index = 0; index < attr_list.len; index++) {
		free(attr_list.Pair[index].Key);
		free(attr_list.Pair[index].Value);
	}
	free(attr_list.Pair);

	/* not end of list if there is more UDAs */
	if (i < attr_list.len)
		*end_of_list = FALSE;
	else
		*end_of_list = TRUE;

	*p_nb_returned = out_index;

	return fsalstat(ERR_FSAL_NO_ERROR, 0);
}
Beispiel #27
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;
}
Beispiel #28
0
fsal_status_t hpss_getextattr_id_by_name(struct fsal_obj_handle *fsal_obj_hdl,
					 const char *xattr_name,
					 unsigned int *pxattr_id)
{
	struct hpss_fsal_obj_handle *obj_hdl;
	unsigned int index;
	int found = FALSE;

	if (!fsal_obj_hdl || !xattr_name || !pxattr_id)
		return fsalstat(ERR_FSAL_FAULT, 0);

	obj_hdl = container_of(fsal_obj_hdl,
			       struct hpss_fsal_obj_handle,
			       obj_handle);

	for (index = 0; index < XATTR_COUNT; index++) {
		if (do_match_type(xattr_list[index].flags,
				  fsal_obj_hdl->type) &&
		    !strcmp(xattr_list[index].xattr_name,
			    xattr_name)) {
			found = TRUE;
			break;
		}
	}

	if (!found) {
		/* search for name in UDAs */
		hpss_userattr_list_t attr_list;
		unsigned int i;
		int rc;
		char attrpath[MAXNAMLEN];
		sec_cred_t ucreds;

		HPSSFSAL_ucreds_from_opctx(op_ctx, &ucreds);

		/* convert FSAL xattr name to HPSS attr path.
		 * returns error if it is not a UDA name.
		 */
		if (fsal_xattr_name_2_uda(xattr_name,
					  attrpath) == 0) {
			memset(&attr_list, 0, sizeof(hpss_userattr_list_t));

			LogFullDebug(COMPONENT_FSAL,
				     "looking for xattr '%s' in UDAs",
				     xattr_name);

		/* get list of UDAs, and return the good index*/

		rc = hpss_UserAttrListAttrHandle(&(obj_hdl->handle->ns_handle),
						 NULL,
						 &ucreds,
						 &attr_list,
						 XML_ATTR);

		if (rc == 0)
			for (i = 0; i < attr_list.len; i++)
				if (!strcmp(attr_list.Pair[i].Key, attrpath)) {
					/* xattr index is XATTR_COUNT +
					 * UDA index */
					index = XATTR_COUNT + i;
					found = TRUE;
					break;
				}

		/* Allocated by hpss - use free */
		for (i = 0; i < attr_list.len; i++) {
			free(attr_list.Pair[i].Key);
			free(attr_list.Pair[i].Value);
		}
		free(attr_list.Pair);
		}
	}

	if (found) {
		*pxattr_id = index;
		return fsalstat(ERR_FSAL_NO_ERROR, 0);
	} else
		return fsalstat(ERR_FSAL_NOENT, ENOENT);
}
Beispiel #29
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);
	}
}
Beispiel #30
0
fsal_status_t hpss_getextattr_value_by_id(struct fsal_obj_handle *fsal_obj_hdl,
					  unsigned int xattr_id,
					  caddr_t buffer_addr,
					  size_t buffer_size,
					  size_t *p_output_size)
{
	struct hpss_fsal_obj_handle *obj_hdl;
	int rc, i;
	sec_cred_t ucreds;
	hpss_userattr_list_t attr_list;

	if (!fsal_obj_hdl || !p_output_size)
		return fsalstat(ERR_FSAL_FAULT, 0);

	obj_hdl = container_of(fsal_obj_hdl,
			       struct hpss_fsal_obj_handle,
			       obj_handle);
	HPSSFSAL_ucreds_from_opctx(op_ctx, &ucreds);

	/* check that this index match the type of entry */
	if (xattr_id < XATTR_COUNT) {
		if (!do_match_type(xattr_list[xattr_id].flags,
				   fsal_obj_hdl->type))
			return fsalstat(ERR_FSAL_INVAL, 0);

	rc = xattr_list[xattr_id].get_func(fsal_obj_hdl,
					   buffer_addr,
					   buffer_size,
					   p_output_size,
					   &ucreds);
	} else
		if (xattr_id >= XATTR_COUNT) {
			memset(&attr_list, 0, sizeof(hpss_userattr_list_t));

			LogFullDebug(COMPONENT_FSAL,
				     "Getting value for UDA #%u",
				     xattr_id - XATTR_COUNT);

		/* get list of UDAs for this entry, and
		 * return the good value */
		rc = hpss_UserAttrListAttrHandle(&(obj_hdl->handle->ns_handle),
						 NULL,
						 &ucreds,
						 &attr_list,
						 XML_ATTR);

		if (rc != 0)
			return fsalstat(hpss2fsal_error(rc), rc);

		else
			if (xattr_id - XATTR_COUNT >= attr_list.len)
				return fsalstat(ERR_FSAL_STALE, 0);

		if ((attr_list.Pair[xattr_id - XATTR_COUNT].Value != NULL) &&
		    (attr_list.Pair[xattr_id - XATTR_COUNT].Value[0] != '\0'))
			*p_output_size =
				 snprintf((char *)buffer_addr,
					  buffer_size, "%s\n",
			attr_list.Pair[xattr_id - XATTR_COUNT].Value);
		else {
			((char *)buffer_addr)[0] = '\0';
			*p_output_size = 0;
		}

		/* Allocated by hpss - use free */
		for (i = 0; i < attr_list.len; i++) {
			free(attr_list.Pair[i].Key);
			free(attr_list.Pair[i].Value);
		}
		free(attr_list.Pair);

		return fsalstat(ERR_FSAL_NO_ERROR, 0);
	}
	return fsalstat(rc, 0);
}