Пример #1
0
/**
 *
 * @brief Write to a data-server handle.
 *
 * This performs a DS write not going through the data server unless
 * FILE_SYNC4 is specified, in which case it connects the filehandle
 * and performs an MDS write.
 *
 * @param[in]  ds_pub           FSAL DS handle
 * @param[in]  req_ctx          Credentials
 * @param[in]  stateid          The stateid supplied with the READ operation,
 *                              for validation
 * @param[in]  offset           The offset at which to read
 * @param[in]  write_length     Length of write requested (and size of buffer)
 * @param[out] buffer           The buffer to which to store read data
 * @param[in]  stability wanted Stability of write
 * @param[out] written_length   Length of data written
 * @param[out] writeverf        Write verifier
 * @param[out] stability_got    Stability used for write (must be as
 *                              or more stable than request)
 *
 * @return An NFSv4.1 status code.
 */
static nfsstat4
lustre_ds_write(struct fsal_ds_handle *const ds_pub,
		struct req_op_context *const req_ctx,
		const stateid4 *stateid,
		const offset4 offset,
		const count4 write_length,
		const void *buffer,
		const stable_how4 stability_wanted,
		count4 *written_length,
		verifier4 *writeverf,
		stable_how4 *stability_got)
{
	/* The amount actually read */
	int32_t amount_written = 0;
	struct lustre_file_handle *lustre_handle;
	/* The private 'full' DS handle */
	struct lustre_ds *ds = container_of(ds_pub, struct lustre_ds, ds);
	lustre_handle = &ds->wire;
	char mypath[MAXPATHLEN];
	int fd = 0;

	memset(writeverf, 0, NFS4_VERIFIER_SIZE);

	/** @todo Add some debug code here about the fh to be used */

	/* get the path of the file in Lustre */
	lustre_handle_to_path(ds->lustre_fs->fs->path,
			      lustre_handle, mypath);

	/* @todo: we could take care of parameter stability_wanted here */
	fd = open(mypath, O_WRONLY|O_NOFOLLOW|O_SYNC);
	if (fd < 0)
		return posix2nfs4_error(errno);

	/* write the data */
	amount_written = pwrite(fd, buffer, write_length, offset);
	if (amount_written < 0) {
		close(fd);
		return posix2nfs4_error(-amount_written);
	}

	if (close(fd) < 0)
		return posix2nfs4_error(errno);

	*written_length = amount_written;
	*stability_got = stability_wanted;

	return NFS4_OK;
}
Пример #2
0
/**
 * @brief Read from a data-server handle.
 *
 * NFSv4.1 data server handles are disjount from normal
 * filehandles (in Ganesha, there is a ds_flag in the filehandle_v4_t
 * structure) and do not get loaded into cache_inode or processed the
 * normal way.
 *
 * @param[in]  ds_pub           FSAL DS handle
 * @param[in]  req_ctx          Credentials
 * @param[in]  stateid          The stateid supplied with the READ operation,
 *                              for validation
 * @param[in]  offset           The offset at which to read
 * @param[in]  requested_length Length of read requested (and size of buffer)
 * @param[out] buffer           The buffer to which to store read data
 * @param[out] supplied_length  Length of data read
 * @param[out] eof              True on end of file
 *
 * @return An NFSv4.1 status code.
 */
static nfsstat4 ds_read(struct fsal_ds_handle *const ds_pub,
			struct req_op_context *const req_ctx,
			const stateid4 *stateid, const offset4 offset,
			const count4 requested_length, void *const buffer,
			count4 * const supplied_length,
			bool * const end_of_file)
{
	/* The private DS handle */
	struct glfs_ds_handle *ds =
		container_of(ds_pub, struct glfs_ds_handle, ds);
	int    rc = 0;
	struct glusterfs_export *glfs_export =
	container_of(ds_pub->pds->mds_fsal_export,
		     struct glusterfs_export, export);

	if (ds->glhandle == NULL)
		LogDebug(COMPONENT_PNFS, "ds_read glhandle NULL");

	rc = glfs_h_anonymous_read(glfs_export->gl_fs->fs, ds->glhandle,
				   buffer, requested_length, offset);
	if (rc < 0) {
		LogMajor(COMPONENT_PNFS, "Read failed on DS");
		return posix2nfs4_error(-rc);
	}

	*supplied_length = rc;
	if (rc == 0 || rc < requested_length)
		*end_of_file = true;


	return NFS4_OK;
}
Пример #3
0
/**
 * @brief Read from a data-server handle.
 *
 * NFSv4.1 data server handles are disjount from normal
 * filehandles (in Ganesha, there is a ds_flag in the filehandle_v4_t
 * structure) and do not get loaded into cache_inode or processed the
 * normal way.
 *
 * @param[in]  ds_pub           FSAL DS handle
 * @param[in]  req_ctx          Credentials
 * @param[in]  stateid          The stateid supplied with the READ operation,
 *                              for validation
 * @param[in]  offset           The offset at which to read
 * @param[in]  requested_length Length of read requested (and size of buffer)
 * @param[out] buffer           The buffer to which to store read data
 * @param[out] supplied_length  Length of data read
 * @param[out] eof              True on end of file
 *
 * @return An NFSv4.1 status code.
 */
static nfsstat4
lustre_ds_read(struct fsal_ds_handle *const ds_pub,
		struct req_op_context *const req_ctx,
		const stateid4 *stateid,
		const offset4 offset,
		const count4 requested_length,
		void *const buffer,
		count4 *const supplied_length,
		bool *const end_of_file)
{
	struct lustre_file_handle *lustre_handle;
	/* The amount actually read */
	int amount_read = 0;
	char mypath[MAXPATHLEN];
	int fd = 0;

	/* The private 'full' DS handle */
	struct lustre_ds *ds = container_of(ds_pub, struct lustre_ds, ds);
	lustre_handle = &ds->wire;

	/* get the path of the file in Lustre */
	lustre_handle_to_path(ds->lustre_fs->fs->path,
			      lustre_handle, mypath);

	/* @todo: we could take care of parameter stability_wanted here */
	fd = open(mypath, O_RDONLY|O_NOFOLLOW|O_SYNC);
	if (fd < 0)
		return posix2nfs4_error(errno);

	/* write the data */
	amount_read = pread(fd, buffer, requested_length, offset);
	if (amount_read < 0) {
		/* ignore any potential error on close if read failed? */
		close(fd);
		return posix2nfs4_error(-amount_read);
	}

	if (close(fd) < 0)
		return posix2nfs4_error(errno);


	*supplied_length = amount_read;
	*end_of_file = amount_read == 0 ? true : false;

	return NFS4_OK;
}
Пример #4
0
/**
 * @brief Commit a segment of a layout
 *
 * Update the size and time for a file accessed through a layout.
 *
 * @param[in]     obj_pub  Public object handle
 * @param[in]     req_ctx  Request context
 * @param[in]     lou_body An XDR stream containing the layout
 *                         type-specific portion of the LAYOUTCOMMIT
 *                         arguments.
 * @param[in]     arg      Input arguments of the function
 * @param[in,out] res      In/out and output arguments of the function
 *
 * @return Valid error codes in RFC 5661, p. 366.
 */
static nfsstat4 layoutcommit(struct fsal_obj_handle *obj_hdl,
			     struct req_op_context *req_ctx, XDR *lou_body,
			     const struct fsal_layoutcommit_arg *arg,
			     struct fsal_layoutcommit_res *res)
{
	struct gpfs_fsal_obj_handle *myself;
	/* The private 'full' object handle */
	struct gpfs_file_handle *gpfs_handle;

	int rc = 0;
	struct layoutcommit_arg targ;
	int errsv = 0;
	struct gpfs_filesystem *gpfs_fs = obj_hdl->fs->private_data;

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

	myself = container_of(obj_hdl, struct gpfs_fsal_obj_handle, obj_handle);
	gpfs_handle = myself->handle;

	targ.mountdirfd = gpfs_fs->root_fd;
	targ.handle = gpfs_handle;
	targ.xdr = NULL;
	targ.offset = arg->segment.offset;
	targ.length = arg->segment.length;

	targ.reclaim = arg->reclaim;	/* True if this is a reclaim commit */
	targ.new_offset = arg->new_offset; /* True if the client has suggested a
						new offset */
	if (arg->new_offset)
		targ.last_write = arg->last_write; /* The offset of the last
							byte written */
	targ.time_changed = arg->time_changed; /*True if provided a new mtime*/
	if (arg->time_changed) {
		targ.new_time.t_sec = arg->new_time.seconds;
		targ.new_time.t_nsec = arg->new_time.nseconds;
	}
	rc = gpfs_ganesha(OPENHANDLE_LAYOUT_COMMIT, &targ);
	errsv = errno;
	if (rc != 0) {
		LogDebug(COMPONENT_PNFS, "GPFSFSAL_layoutcommit rc %d", rc);
		if (errsv == EUNATCH)
			LogFatal(COMPONENT_PNFS, "GPFS Returned EUNATCH");
		return posix2nfs4_error(-rc);
	}
	res->size_supplied = false;
	res->commit_done = true;

	return NFS4_OK;
}
Пример #5
0
/**
 * @brief Read from a data-server handle.
 *
 * NFSv4.1 data server handles are disjount from normal
 * filehandles (in Ganesha, there is a ds_flag in the filehandle_v4_t
 * structure) and do not get loaded into cache_inode or processed the
 * normal way.
 *
 * @param[in]  ds_pub           FSAL DS handle
 * @param[in]  req_ctx          Credentials
 * @param[in]  stateid          The stateid supplied with the READ operation,
 *                              for validation
 * @param[in]  offset           The offset at which to read
 * @param[in]  requested_length Length of read requested (and size of buffer)
 * @param[out] buffer           The buffer to which to store read data
 * @param[out] supplied_length  Length of data read
 * @param[out] eof              True on end of file
 *
 * @return An NFSv4.1 status code.
 */
static nfsstat4 ds_read(struct fsal_ds_handle *const ds_pub,
			struct req_op_context *const req_ctx,
			const stateid4 *stateid, const offset4 offset,
			const count4 requested_length, void *const buffer,
			count4 * const supplied_length,
			bool * const end_of_file)
{
	/* The private 'full' DS handle */
	struct gpfs_ds *ds = container_of(ds_pub, struct gpfs_ds, ds);
	struct gpfs_file_handle *gpfs_handle = &ds->wire;
	/* The amount actually read */
	int amount_read = 0;
	struct dsread_arg rarg;
	unsigned int *fh;
	int errsv = 0;


	fh = (int *)&(gpfs_handle->f_handle);

	rarg.mountdirfd = ds->gpfs_fs->root_fd;
	rarg.handle = gpfs_handle;
	rarg.bufP = buffer;
	rarg.offset = offset;
	rarg.length = requested_length;
	rarg.options = 0;

	LogDebug(COMPONENT_PNFS,
		 "fh len %d type %d key %d: %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x\n",
		 gpfs_handle->handle_size, gpfs_handle->handle_type,
		 gpfs_handle->handle_key_size, fh[0], fh[1], fh[2], fh[3],
		 fh[4], fh[5], fh[6], fh[7], fh[8], fh[9]);

	amount_read = gpfs_ganesha(OPENHANDLE_DS_READ, &rarg);
	errsv = errno;
	if (amount_read < 0) {
		if (errsv == EUNATCH)
			LogFatal(COMPONENT_PNFS, "GPFS Returned EUNATCH");
		return posix2nfs4_error(errsv);
	}

	*supplied_length = amount_read;

	if (amount_read == 0 || amount_read < requested_length)
		*end_of_file = true;

	return NFS4_OK;
}
Пример #6
0
/**
 *
 * @brief Write to a data-server handle.
 *
 * @param[in]  ds_pub           FSAL DS handle
 * @param[in]  req_ctx          Credentials
 * @param[in]  stateid          The stateid supplied with the READ operation,
 *                              for validation
 * @param[in]  offset           The offset at which to read
 * @param[in]  write_length     Length of write requested (and size of buffer)
 * @param[out] buffer           The buffer to which to store read data
 * @param[in]  stability wanted Stability of write
 * @param[out] written_length   Length of data written
 * @param[out] writeverf        Write verifier
 * @param[out] stability_got    Stability used for write (must be as
 *                              or more stable than request)
 *
 * @return An NFSv4.1 status code.
 */
static nfsstat4 ds_write(struct fsal_ds_handle *const ds_pub,
			 struct req_op_context *const req_ctx,
			 const stateid4 *stateid, const offset4 offset,
			 const count4 write_length, const void *buffer,
			 const stable_how4 stability_wanted,
			 count4 * const written_length,
			 verifier4 * const writeverf,
			 stable_how4 * const stability_got)
{
	struct glfs_ds_handle *ds =
		container_of(ds_pub, struct glfs_ds_handle, ds);
	struct glusterfs_export *glfs_export =
	container_of(ds_pub->pds->mds_fsal_export,
		     struct glusterfs_export, export);
	int    rc = 0;

	memset(writeverf, 0, NFS4_VERIFIER_SIZE);

	if (ds->glhandle == NULL)
		LogDebug(COMPONENT_PNFS, "ds_write glhandle NULL");

	rc = glfs_h_anonymous_write(glfs_export->gl_fs->fs, ds->glhandle,
				    buffer, write_length, offset);
	if (rc < 0) {
		LogMajor(COMPONENT_PNFS, "status after write %d", -rc);
		return posix2nfs4_error(-rc);
	}

	/** @todo:Here DS is performing the write operation, so the MDS is not
	 *      aware of the change.We should inform MDS through upcalls about
	 *      change in file attributes such as size and time.
	 */
	*written_length = rc;

	*stability_got = stability_wanted;
	ds->stability_got = stability_wanted;

	/* Incase of MDS being DS, there shall not be upcalls sent from
	 * backend. Hence invalidate the entry here */
	(void)upcall_inode_invalidate(glfs_export->gl_fs, ds->glhandle);

	return NFS4_OK;
}
Пример #7
0
static nfsstat4 layoutget(struct fsal_obj_handle *obj_pub,
			  struct req_op_context *req_ctx, XDR *loc_body,
			  const struct fsal_layoutget_arg *arg,
			  struct fsal_layoutget_res *res)
{
	/* The private 'full' export */
	struct export *export =
	    container_of(req_ctx->fsal_export, struct export, export);
	/* The private 'full' object handle */
	struct handle *handle = container_of(obj_pub, struct handle, handle);
	/* Structure containing the storage parameters of the file within
	   the Ceph cluster. */
	struct ceph_file_layout file_layout;
	/* Width of each stripe on the file */
	uint32_t stripe_width = 0;
	/* Utility parameter */
	nfl_util4 util = 0;
	/* The last byte that can be accessed through pNFS */
	uint64_t last_possible_byte = 0;
	/* The deviceid for this layout */
	struct pnfs_deviceid deviceid = DEVICE_ID_INIT_ZERO(FSAL_ID_CEPH);
	/* NFS Status */
	nfsstat4 nfs_status = 0;
	/* DS wire handle */
	struct ds_wire ds_wire;
	/* Descriptor for DS handle */
	struct gsh_buffdesc ds_desc = {.addr = &ds_wire,
		.len = sizeof(struct ds_wire)
	};
	/* The smallest layout the client will accept */
	struct pnfs_segment smallest_acceptable = {
		.io_mode = res->segment.io_mode,
		.offset = res->segment.offset,
		.length = arg->minlength
	};
	struct pnfs_segment forbidden_area = {
		.io_mode = res->segment.io_mode,
		.length = NFS4_UINT64_MAX
	};

	/* We support only LAYOUT4_NFSV4_1_FILES layouts */

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

	/* Get basic information on the file and calculate the dimensions
	   of the layout we can support. */

	memset(&file_layout, 0, sizeof(struct ceph_file_layout));

	ceph_ll_file_layout(export->cmount, handle->wire.vi, &file_layout);
	stripe_width = file_layout.fl_stripe_unit;
	last_possible_byte = (BIGGEST_PATTERN * stripe_width) - 1;
	forbidden_area.offset = last_possible_byte + 1;

	/* Since the Linux kernel refuses to work with any layout that
	   doesn't cover the whole file, if a whole file layout is
	   requested, lie.

	   Otherwise, make sure the required layout doesn't go beyond
	   what can be accessed through pNFS. This is a preliminary
	   check before even talking to Ceph. */
	if (!
	    ((res->segment.offset == 0)
	     && (res->segment.length == NFS4_UINT64_MAX))) {
		if (pnfs_segments_overlap
		    (&smallest_acceptable, &forbidden_area)) {
			LogCrit(COMPONENT_PNFS,
				"Required layout extends beyond allowed region. offset: %"
				PRIu64 ", minlength: %" PRIu64 ".",
				res->segment.offset, arg->minlength);
			return NFS4ERR_BADLAYOUT;
		}
		res->segment.offset = 0;
		res->segment.length = stripe_width * BIGGEST_PATTERN;
	}

	LogFullDebug(COMPONENT_PNFS,
		     "will issue layout offset: %" PRIu64 " length: %" PRIu64,
		     res->segment.offset, res->segment.length);

	/* We are using sparse layouts with commit-through-DS, so our
	   utility word contains only the stripe width, our first
	   stripe is always at the beginning of the layout, and there
	   is no pattern offset. */

	if ((stripe_width & ~NFL4_UFLG_STRIPE_UNIT_SIZE_MASK) != 0) {
		LogCrit(COMPONENT_PNFS,
			"Ceph returned stripe width that is disallowed by NFS: %"
			PRIu32 ".", stripe_width);
		return NFS4ERR_SERVERFAULT;
	}
	util = stripe_width;

	/* If we have a cached capbility, use that.  Otherwise, call
	   in to Ceph. */

	PTHREAD_RWLOCK_wrlock(&handle->handle.lock);
	if (res->segment.io_mode == LAYOUTIOMODE4_READ) {
		int32_t r = 0;

		if (handle->rd_issued == 0) {
#if 0
			/* (ceph part might be here: thunderbeast mbarrier1) */
			r = ceph_ll_hold_rw(export->cmount, handle->wire.vi,
					    false, initiate_recall, handle,
					    &handle->rd_serial, NULL);
#endif
			if (r < 0) {
				PTHREAD_RWLOCK_unlock(&handle->handle.lock);
				return posix2nfs4_error(-r);
			}
		}
		++handle->rd_issued;
	} else {
		int32_t r = 0;

		if (handle->rw_issued == 0) {
#if 0
			r = ceph_ll_hold_rw(export->cmount, handle->wire.vi,
					    true, initiate_recall, handle,
					    &handle->rw_serial,
					    &handle->rw_max_len);
#endif
			if (r < 0) {
				PTHREAD_RWLOCK_unlock(&handle->handle.lock);
				return posix2nfs4_error(-r);
			}
		}
		forbidden_area.offset = handle->rw_max_len;
		if (pnfs_segments_overlap
		    (&smallest_acceptable, &forbidden_area)) {
			PTHREAD_RWLOCK_unlock(&handle->handle.lock);
			return NFS4ERR_BADLAYOUT;
		}
#if CLIENTS_WILL_ACCEPT_SEGMENTED_LAYOUTS	/* sigh */
		res->segment.length =
		    (handle->rw_max_len - res->segment.offset);
#endif
		++handle->rw_issued;
	}
Пример #8
0
/**
 *
 * @brief Write plus to a data-server handle.
 *
 * This performs a DS write not going through the data server unless
 * FILE_SYNC4 is specified, in which case it connects the filehandle
 * and performs an MDS write.
 *
 * @param[in]  ds_pub           FSAL DS handle
 * @param[in]  req_ctx          Credentials
 * @param[in]  stateid          The stateid supplied with the READ operation,
 *                              for validation
 * @param[in]  offset           The offset at which to read
 * @param[in]  write_length     Length of write requested (and size of buffer)
 * @param[out] buffer           The buffer to which to store read data
 * @param[in]  stability wanted Stability of write
 * @param[out] written_length   Length of data written
 * @param[out] writeverf        Write verifier
 * @param[out] stability_got    Stability used for write (must be as
 *                              or more stable than request)
 * @param[in/out] info          IO info
 *
 * @return An NFSv4.2 status code.
 */
static nfsstat4 ds_write_plus(struct fsal_ds_handle *const ds_pub,
			 struct req_op_context *const req_ctx,
			 const stateid4 *stateid, const offset4 offset,
			 const count4 write_length, const void *buffer,
			 const stable_how4 stability_wanted,
			 count4 * const written_length,
			 verifier4 * const writeverf,
			 stable_how4 * const stability_got,
			 struct io_info *info)
{
	/* The private 'full' DS handle */
	struct gpfs_ds *ds = container_of(ds_pub, struct gpfs_ds, ds);
	struct gpfs_file_handle *gpfs_handle = &ds->wire;
	/* The amount actually read */
	int32_t amount_written = 0;
	struct dswrite_arg warg;
	unsigned int *fh;
	struct gsh_buffdesc key;
	int errsv = 0;

	fh = (int *)&(gpfs_handle->f_handle);

	memset(writeverf, 0, NFS4_VERIFIER_SIZE);

	warg.mountdirfd = ds->gpfs_fs->root_fd;
	warg.handle = gpfs_handle;
	warg.bufP = (char *)buffer;
	warg.offset = offset;
	warg.length = write_length;
	warg.stability_wanted = stability_wanted;
	warg.stability_got = stability_got;
	warg.verifier4 = (int32_t *) writeverf;
	warg.options = 0;

	if (info->io_content.what == NFS4_CONTENT_HOLE)
		warg.options = IO_SKIP_HOLE;

	LogDebug(COMPONENT_PNFS,
		 "fh len %d type %d key %d: %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x\n",
		 gpfs_handle->handle_size, gpfs_handle->handle_type,
		 gpfs_handle->handle_key_size, fh[0], fh[1], fh[2], fh[3],
		 fh[4], fh[5], fh[6], fh[7], fh[8], fh[9]);

	amount_written = gpfs_ganesha(OPENHANDLE_DS_WRITE, &warg);
	errsv = errno;
	if (amount_written < 0) {
		if (errsv == EUNATCH)
			LogFatal(COMPONENT_PNFS, "GPFS Returned EUNATCH");
		return posix2nfs4_error(errsv);
	}

	LogDebug(COMPONENT_PNFS, "write verifier %d-%d\n",
				warg.verifier4[0], warg.verifier4[1]);

	key.addr = gpfs_handle;
	key.len = gpfs_handle->handle_key_size;
	req_ctx->fsal_export->up_ops->invalidate(
			req_ctx->fsal_export, &key,
			FSAL_UP_INVALIDATE_CACHE);

	set_gpfs_verifier(writeverf);

	*written_length = amount_written;

	return NFS4_OK;
}
Пример #9
0
/**
 * @brief Read plus from a data-server handle.
 *
 * NFSv4.2 data server handles are disjount from normal
 * filehandles (in Ganesha, there is a ds_flag in the filehandle_v4_t
 * structure) and do not get loaded into cache_inode or processed the
 * normal way.
 *
 * @param[in]  ds_pub           FSAL DS handle
 * @param[in]  req_ctx          Credentials
 * @param[in]  stateid          The stateid supplied with the READ operation,
 *                              for validation
 * @param[in]  offset           The offset at which to read
 * @param[in]  requested_length Length of read requested (and size of buffer)
 * @param[out] buffer           The buffer to which to store read data
 * @param[out] supplied_length  Length of data read
 * @param[out] eof              True on end of file
 * @param[out] info             IO info
 *
 * @return An NFSv4.2 status code.
 */
static nfsstat4 ds_read_plus(struct fsal_ds_handle *const ds_pub,
			struct req_op_context *const req_ctx,
			const stateid4 *stateid, const offset4 offset,
			const count4 requested_length, void *const buffer,
			const count4 supplied_length,
			bool * const end_of_file,
			struct io_info *info)
{
	/* The private 'full' DS handle */
	struct gpfs_ds *ds = container_of(ds_pub, struct gpfs_ds, ds);
	struct gpfs_file_handle *gpfs_handle = &ds->wire;
	/* The amount actually read */
	int amount_read = 0;
	struct dsread_arg rarg;
	unsigned int *fh;
	uint64_t filesize;
	int errsv = 0;

	fh = (int *)&(gpfs_handle->f_handle);

	rarg.mountdirfd = ds->gpfs_fs->root_fd;
	rarg.handle = gpfs_handle;
	rarg.bufP = buffer;
	rarg.offset = offset;
	rarg.length = requested_length;
	rarg.filesize = &filesize;
	rarg.options = IO_SKIP_HOLE;

	LogDebug(COMPONENT_PNFS,
		 "fh len %d type %d key %d: %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x\n",
		 gpfs_handle->handle_size, gpfs_handle->handle_type,
		 gpfs_handle->handle_key_size, fh[0], fh[1], fh[2], fh[3],
		 fh[4], fh[5], fh[6], fh[7], fh[8], fh[9]);

	amount_read = gpfs_ganesha(OPENHANDLE_DS_READ, &rarg);
	errsv = errno;
	if (amount_read < 0) {
		if (errsv == EUNATCH)
			LogFatal(COMPONENT_PNFS, "GPFS Returned EUNATCH");
		if (errsv != ENODATA)
			return posix2nfs4_error(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 = requested_length;/*hole len*/

		if ((requested_length + offset) > filesize) {
			amount_read = filesize - offset;
			if (amount_read < 0) {
				amount_read = 0;
				*end_of_file = true;
			} else if (amount_read < requested_length)
				*end_of_file = true;
			info->io_content.hole.di_length = amount_read;
		}
	} else {
		info->io_content.what = NFS4_CONTENT_DATA;
		info->io_content.data.d_offset = offset + amount_read;
		info->io_content.data.d_data.data_len = amount_read;
		info->io_content.data.d_data.data_val = buffer;
		if (amount_read == 0 || amount_read < requested_length)
			*end_of_file = true;
	}

	return NFS4_OK;
}
Пример #10
0
static nfsstat4 pnfs_layout_get(struct fsal_obj_handle          *obj_pub,
				struct req_op_context           *req_ctx,
				XDR                             *loc_body,
				const struct fsal_layoutget_arg *arg,
				struct fsal_layoutget_res       *res)
{

	struct glusterfs_export *export =
		container_of(req_ctx->fsal_export,
			     struct glusterfs_export, export);

	struct glusterfs_handle *handle =
		container_of(obj_pub, struct glusterfs_handle, handle);
	int    rc = 0;
	/* Structure containing the storage parameters of the file within
	   glusterfs. */
	struct glfs_file_layout file_layout;
	/* Utility parameter */
	nfl_util4               util = 0;
	/* Stores Data server address */
	struct pnfs_deviceid    deviceid = DEVICE_ID_INIT_ZERO(FSAL_ID_GLUSTER);
	nfsstat4                nfs_status = NFS4_OK;
	/* Descriptor for DS handle */
	struct gsh_buffdesc     ds_desc;
	/* DS wire handle send to client */
	struct glfs_ds_wire     ds_wire;

	/* Supports only LAYOUT4_NFSV4_1_FILES layouts */
	if (arg->type != LAYOUT4_NFSV4_1_FILES) {
		LogMajor(COMPONENT_PNFS, "Unsupported layout type: %x",
			 arg->type);

		return NFS4ERR_UNKNOWN_LAYOUTTYPE;
	}

	memset(&file_layout, 0, sizeof(struct glfs_file_layout));

	/**
	 * Currently whole file is given as file layout,
	 *
	 * Stripe type is dense which is supported right now.
	 * Stripe length is max possible length of file that
	 * can be accessed by the client to perform a read or
	 * write.
	 */

	file_layout.stripe_type  = NFL4_UFLG_DENSE;

	file_layout.stripe_length = 0x100000;

	util |= file_layout.stripe_type | file_layout.stripe_length;

	rc = glfs_get_ds_addr(export->gl_fs, handle->glhandle,
				&deviceid.device_id4);

	if (rc) {
		LogMajor(COMPONENT_PNFS, "Invalid hostname for DS");
		return NFS4ERR_INVAL;
	}

	/** @todo: When more than one client tries access the same layout
	 *       for the write operation, then last write will overwrite
	 *       for the write operation, then last write will overwrite
	 *       the previous ones, the MDS should intelligently deal
	 *       those scenarios
	 */



	/* We return exactly one wirehandle, filling in the necessary
	 * information for the DS server to speak to the gluster bricks
	 * For this, wire handle stores gfid and file layout
	 */

	rc = glfs_h_extract_handle(handle->glhandle, ds_wire.gfid,
				   GFAPI_HANDLE_LENGTH);
	if (rc < 0) {
		LogMajor(COMPONENT_PNFS, "Invalid glfs_object");
		return posix2nfs4_error(-rc);
	}

	ds_wire.layout   = file_layout;
	ds_desc.addr     = &ds_wire;
	ds_desc.len      = sizeof(struct glfs_ds_wire);
	nfs_status = FSAL_encode_file_layout(loc_body, &deviceid, util, 0, 0,
					     &req_ctx->ctx_export->export_id, 1,
					     &ds_desc);
	if (nfs_status) {
		LogMajor(COMPONENT_PNFS,
			  "Failed to encode nfsv4_1_file_layout.");
		goto out;
	}

	/* We grant only one segment, and we want it back
	 * when the file is closed.
	 */
	res->return_on_close    = true;
	res->last_segment       = true;

out:
	return nfs_status;
}