Example #1
0
/*
 * XDR the MSG_ACCEPTED part of a reply message union
 */
bool
xdr_naccepted_reply(XDR *xdrs, struct accepted_reply *ar)
{
	assert(xdrs != NULL);
	assert(ar != NULL);

	/* personalized union, rather than calling xdr_union */
	if (!inline_xdr_opaque_auth(xdrs, &(ar->ar_verf)))
		return (false);
	if (!inline_xdr_enum(xdrs, (enum_t *) &(ar->ar_stat)))
		return (false);
	switch (ar->ar_stat) {

	case SUCCESS:
		return ((*(ar->ar_results.proc)) (xdrs, ar->ar_results.where));

	case PROG_MISMATCH:
		if (!inline_xdr_u_int32_t(xdrs, &(ar->ar_vers.low)))
			return (false);
		return (inline_xdr_u_int32_t(xdrs, &(ar->ar_vers.high)));

	case GARBAGE_ARGS:
	case SYSTEM_ERR:
	case PROC_UNAVAIL:
	case PROG_UNAVAIL:
		break;
	}
	return (true);		/* true => open ended set of problems */
}
Example #2
0
/*
 * Serializes the "static part" of a call message header.
 * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers.
 * The rm_xid is not really static, but the user can easily munge on the fly.
 */
bool
xdr_ncallhdr(XDR *xdrs, struct rpc_msg *cmsg)
{
	assert(xdrs != NULL);
	assert(cmsg != NULL);

	cmsg->rm_direction = CALL;
	cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION;
	if ((xdrs->x_op == XDR_ENCODE)
	    && inline_xdr_u_int32_t(xdrs, &(cmsg->rm_xid))
	    && inline_xdr_enum(xdrs, (enum_t *) &(cmsg->rm_direction))
	    && inline_xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_rpcvers))
	    && inline_xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_prog)))
		return (inline_xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_vers)));
	return (false);
}
Example #3
0
/*
 * XDR the MSG_DENIED part of a reply message union
 */
bool
xdr_nrejected_reply(XDR *xdrs, struct rejected_reply *rr)
{
	assert(xdrs != NULL);
	assert(rr != NULL);

	/* personalized union, rather than calling xdr_union */
	if (!inline_xdr_enum(xdrs, (enum_t *) &(rr->rj_stat)))
		return (false);
	switch (rr->rj_stat) {

	case RPC_MISMATCH:
		if (!inline_xdr_u_int32_t(xdrs, &(rr->rj_vers.low)))
			return (false);
		return (inline_xdr_u_int32_t(xdrs, &(rr->rj_vers.high)));

	case AUTH_ERROR:
		return (inline_xdr_enum(xdrs, (enum_t *) &(rr->rj_why)));
	}
	/* NOTREACHED */
	assert(0);
	return (false);
}
Example #4
0
/*
 * XDR a reply message
 */
bool
xdr_nreplymsg(XDR *xdrs, struct rpc_msg *rmsg)
{
	assert(xdrs != NULL);
	assert(rmsg != NULL);

	if (inline_xdr_u_int32_t(xdrs, &(rmsg->rm_xid))
	    && inline_xdr_enum(xdrs, (enum_t *) &(rmsg->rm_direction))
	    && (rmsg->rm_direction == REPLY))
		return (inline_xdr_union
			(xdrs, (enum_t *) &(rmsg->rm_reply.rp_stat),
			 (caddr_t) (void *)&(rmsg->rm_reply.ru), reply_dscrm,
			 NULL_xdrproc_t));
	return (false);
}
Example #5
0
static bool initiate_recall(vinodeno_t vi, bool write, void *opaque)
{
	/* The private 'full' object handle */
	struct handle *handle = (struct handle *)opaque;
	/* Return code from upcall operation */
	state_status_t status = STATE_SUCCESS;
	struct gsh_buffdesc key = {
		.addr = &handle->vi,
		.len = sizeof(vinodeno_t)
	};
	struct pnfs_segment segment = {
		.offset = 0,
		.length = UINT64_MAX,
		.io_mode = (write ? LAYOUTIOMODE4_RW : LAYOUTIOMODE4_READ)
	};

	status = handle->up_ops->layoutrecall(&key, LAYOUT4_NFSV4_1_FILES,
					      false, &segment, NULL, NULL);

	if (status != STATE_SUCCESS)
		return false;

	return true;
}

/**
 * @brief Describe a Ceph striping pattern
 *
 * At present, we support a files based layout only.  The CRUSH
 * striping pattern is a-periodic
 *
 * @param[in]  export_pub   Public export handle
 * @param[out] da_addr_body Stream we write the result to
 * @param[in]  type         Type of layout that gave the device
 * @param[in]  deviceid     The device to look up
 *
 * @return Valid error codes in RFC 5661, p. 365.
 */

static nfsstat4 getdeviceinfo(struct fsal_export *export_pub,
			      XDR *da_addr_body, const layouttype4 type,
			      const struct pnfs_deviceid *deviceid)
{
	/* Full 'private' export */
	struct export *export = container_of(export_pub, struct export, export);
	/* The number of Ceph OSDs in the cluster */
	unsigned num_osds = ceph_ll_num_osds(export->cmount);
	/* Minimal information needed to get layout info */
	vinodeno_t vinode;
	/* Structure containing the storage parameters of the file within
	   the Ceph cluster. */
	struct ceph_file_layout file_layout;
	/* Currently, all layouts have the same number of stripes */
	uint32_t stripes = BIGGEST_PATTERN;
	/* Index for iterating over stripes */
	size_t stripe = 0;
	/* Index for iterating over OSDs */
	size_t osd = 0;
	/* NFSv4 status code */
	nfsstat4 nfs_status = 0;

	vinode.ino.val = deviceid->devid;
	vinode.snapid.val = CEPH_NOSNAP;

	/* Sanity check on type */
	if (type != LAYOUT4_NFSV4_1_FILES) {
		LogCrit(COMPONENT_PNFS, "Unsupported layout type: %x", type);
		return NFS4ERR_UNKNOWN_LAYOUTTYPE;
	}

	/* Retrieve and calculate storage parameters of layout */
	memset(&file_layout, 0, sizeof(struct ceph_file_layout));
	if (ceph_ll_file_layout(export->cmount, vinode, &file_layout) != 0) {
		LogCrit(COMPONENT_PNFS, "Failed to get Ceph layout for inode");
		return NFS4ERR_SERVERFAULT;
	}

	/* As this is large, we encode as we go rather than building a
	   structure and encoding it all at once. */

	/* The first entry in the nfsv4_1_file_ds_addr4 is the array
	   of stripe indices. First we encode the count of stripes.
	   Since our pattern doesn't repeat, we have as many indices
	   as we do stripes. */

	if (!inline_xdr_u_int32_t(da_addr_body, &stripes)) {
		LogCrit(COMPONENT_PNFS,
			"Failed to encode length of stripe_indices array: %"
			PRIu32 ".", stripes);
		return NFS4ERR_SERVERFAULT;
	}

	for (stripe = 0; stripe < stripes; stripe++) {
		uint32_t stripe_osd = stripe_osd =
		    ceph_ll_get_stripe_osd(export->cmount,
					   vinode,
					   stripe,
					   &file_layout);
		if (stripe_osd < 0) {
			LogCrit(COMPONENT_PNFS,
				"Failed to retrieve OSD for stripe %lu of file %"
				PRIu64 ".  Error: %u",
				stripe, deviceid->devid, -stripe_osd);
			return NFS4ERR_SERVERFAULT;
		}
		if (!inline_xdr_u_int32_t(da_addr_body, &stripe_osd)) {
			LogCrit(COMPONENT_PNFS,
				"Failed to encode OSD for stripe %lu.", stripe);
			return NFS4ERR_SERVERFAULT;
		}
	}

	/* The number of OSDs in our cluster is the length of our
	   array of multipath_lists */

	if (!inline_xdr_u_int32_t(da_addr_body, &num_osds)) {
		LogCrit(COMPONENT_PNFS,
			"Failed to encode length of multipath_ds_list array: %u",
			num_osds);
		return NFS4ERR_SERVERFAULT;
	}

	/* Since our index is the OSD number itself, we have only one
	   host per multipath_list. */

	for (osd = 0; osd < num_osds; osd++) {
		fsal_multipath_member_t host;

		memset(&host, 0, sizeof(fsal_multipath_member_t));
		host.proto = 6;
		if (ceph_ll_osdaddr(export->cmount, osd, &host.addr) < 0) {
			LogCrit(COMPONENT_PNFS,
				"Unable to get IP address for OSD %lu.", osd);
			return NFS4ERR_SERVERFAULT;
		}
		host.port = 2049;
		nfs_status = FSAL_encode_v4_multipath(da_addr_body, 1, &host);
		if (nfs_status != NFS4_OK)
			return nfs_status;
	}

	return NFS4_OK;
}

/**
 * @brief Get list of available devices
 *
 * We do not support listing devices and just set EOF without doing
 * anything.
 *
 * @param[in]     export_pub Export handle
 * @param[in]     type      Type of layout to get devices for
 * @param[in]     cb        Function taking device ID halves
 * @param[in,out] res       In/out and output arguments of the function
 *
 * @return Valid error codes in RFC 5661, pp. 365-6.
 */

static nfsstat4 getdevicelist(struct fsal_export *export_pub, layouttype4 type,
			      void *opaque, bool(*cb) (void *opaque,
						       const uint64_t id),
			      struct fsal_getdevicelist_res *res)
{
	res->eof = true;
	return NFS4_OK;
}

/**
 * @brief Get layout types supported by export
 *
 * We just return a pointer to the single type and set the count to 1.
 *
 * @param[in]  export_pub Public export handle
 * @param[out] count      Number of layout types in array
 * @param[out] types      Static array of layout types that must not be
 *                        freed or modified and must not be dereferenced
 *                        after export reference is relinquished
 */

static void fs_layouttypes(struct fsal_export *export_pub, int32_t *count,
			   const layouttype4 **types)
{
	static const layouttype4 supported_layout_type = LAYOUT4_NFSV4_1_FILES;
	*types = &supported_layout_type;
	*count = 1;
}

/**
 * @brief Get layout block size for export
 *
 * This function just returns the Ceph default.
 *
 * @param[in] export_pub Public export handle
 *
 * @return 4 MB.
 */

static uint32_t fs_layout_blocksize(struct fsal_export *export_pub)
{
	return 0x400000;
}

/**
 * @brief Maximum number of segments we will use
 *
 * Since current clients only support 1, that's what we'll use.
 *
 * @param[in] export_pub Public export handle
 *
 * @return 1
 */
static uint32_t fs_maximum_segments(struct fsal_export *export_pub)
{
	return 1;
}

/**
 * @brief Size of the buffer needed for a loc_body
 *
 * Just a handle plus a bit.
 *
 * @param[in] export_pub Public export handle
 *
 * @return Size of the buffer needed for a loc_body
 */
static size_t fs_loc_body_size(struct fsal_export *export_pub)
{
	return 0x100;
}

/**
 * @brief Size of the buffer needed for a ds_addr
 *
 * This one is huge, due to the striping pattern.
 *
 * @param[in] export_pub Public export handle
 *
 * @return Size of the buffer needed for a ds_addr
 */
static size_t fs_da_addr_size(struct fsal_export *export_pub)
{
	return 0x1400;
}

void export_ops_pnfs(struct export_ops *ops)
{
	ops->getdeviceinfo = getdeviceinfo;
	ops->getdevicelist = getdevicelist;
	ops->fs_layouttypes = fs_layouttypes;
	ops->fs_layout_blocksize = fs_layout_blocksize;
	ops->fs_maximum_segments = fs_maximum_segments;
	ops->fs_loc_body_size = fs_loc_body_size;
	ops->fs_da_addr_size = fs_da_addr_size;
}
Example #6
0
/**
 * @brief Describes the DS information for the client
 *
 * @param[in]  export_pub   Public export handle
 * @param[out] da_addr_body Stream we write the result to
 * @param[in]  type         Type of layout that gave the device
 * @param[in]  deviceid     The device to look up
 *
 * @return Valid error codes in RFC 5661, p. 365.
 */
nfsstat4 getdeviceinfo(struct fsal_module *fsal_hdl,
		       XDR *da_addr_body, const layouttype4 type,
		       const struct pnfs_deviceid *deviceid)
{
	nfsstat4                    nfs_status = 0;
	/* Stores IP address of DS */
	fsal_multipath_member_t     host;

	/* Entire file layout will be situated inside ONE DS
	 * And whole file is provided to the DS, so the starting
	 * index for that file is zero
	 */
	unsigned num_ds                  = 1;
	uint32_t stripes                 = 1;
	uint32_t stripe_ind              = 0;


	if (type != LAYOUT4_NFSV4_1_FILES) {
		LogMajor(COMPONENT_PNFS, "Unsupported layout type: %x", type);
		return NFS4ERR_UNKNOWN_LAYOUTTYPE;
	}

	if (!inline_xdr_u_int32_t(da_addr_body, &stripes)) {
		LogMajor(COMPONENT_PNFS,
			 "Failed to encode length of stripe_indices array: %"
			  PRIu32 ".", stripes);
		return NFS4ERR_SERVERFAULT;
	}

	if (!inline_xdr_u_int32_t(da_addr_body, &stripe_ind)) {
		LogMajor(COMPONENT_PNFS,
			 "Failed to encode ds for the stripe:  %"
			 PRIu32 ".", stripe_ind);
		return NFS4ERR_SERVERFAULT;
	}

	if (!inline_xdr_u_int32_t(da_addr_body, &num_ds)) {
		LogMajor(COMPONENT_PNFS,
			 "Failed to encode length of multipath_ds_list array: %u",
			 num_ds);
		return NFS4ERR_SERVERFAULT;
	}
	memset(&host, 0, sizeof(fsal_multipath_member_t));
	host.addr = ntohl(deviceid->device_id4);
	host.port = 2049;
	host.proto = 6;
	nfs_status = FSAL_encode_v4_multipath(da_addr_body, 1, &host);

	if (nfs_status != NFS4_OK) {
		LogMajor(COMPONENT_PNFS,
			 "Failed to encode data server address");
	return nfs_status;
	}

	/** @todo: Here information about Data-Server where file resides
	 *        is only send from MDS.If that Data-Server is down then
	 *        read or write will performed through MDS.
	 *        Instead should we send the information about all
	 *        the available data-servers, so that these fops will
	 *        always performed through Data-Servers.
	 *        (Like in replicated volume contains more than ONE DS)
	 */
	return NFS4_OK;
}