/** * * @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; }
/** * @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; }
/** * @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; }
/** * @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; }
/** * @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; }
/** * * @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; }
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; }
/** * * @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; }
/** * @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; }
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; }