/* common code gpfs_open and gpfs_reopen */ fsal_status_t gpfs_open2(struct fsal_obj_handle *obj_hdl, fsal_openflags_t openflags, bool reopen) { struct gpfs_fsal_obj_handle *myself; int fd; fsal_status_t status; myself = container_of(obj_hdl, struct gpfs_fsal_obj_handle, obj_handle); if (reopen) { assert((myself->u.file.fd >= 0 && myself->u.file.openflags != FSAL_O_CLOSED)); fd = myself->u.file.fd; } else { assert(myself->u.file.fd == -1 && myself->u.file.openflags == FSAL_O_CLOSED); } status = GPFSFSAL_open(obj_hdl, op_ctx, openflags, &fd, NULL, reopen); if (FSAL_IS_ERROR(status)) return status; myself->u.file.fd = fd; myself->u.file.openflags = openflags; return fsalstat(ERR_FSAL_NO_ERROR, 0); }
static fsal_status_t gpfs_open_again(struct fsal_obj_handle *obj_hdl, fsal_openflags_t openflags, bool reopen) { struct gpfs_fsal_obj_handle *myself = container_of(obj_hdl, struct gpfs_fsal_obj_handle, obj_handle); fsal_status_t status; int posix_flags = 0; int fd = -1; if (reopen) { assert(myself->u.file.fd.fd >= 0 && myself->u.file.fd.openflags != FSAL_O_CLOSED); fd = myself->u.file.fd.fd; } else { assert(myself->u.file.fd.fd == -1 && myself->u.file.fd.openflags == FSAL_O_CLOSED); } fsal2posix_openflags(openflags, &posix_flags); status = GPFSFSAL_open(obj_hdl, op_ctx, posix_flags, &fd, reopen); if (FSAL_IS_ERROR(status) == false) { myself->u.file.fd.fd = fd; myself->u.file.fd.openflags = openflags; } return status; }
fsal_status_t WRAP_GPFSFSAL_open(fsal_handle_t * p_filehandle, /* IN */ fsal_op_context_t * p_context, /* IN */ fsal_openflags_t openflags, /* IN */ fsal_file_t * p_file_descriptor, /* OUT */ fsal_attrib_list_t * p_file_attributes /* [ IN/OUT ] */ ) { return GPFSFSAL_open((gpfsfsal_handle_t *) p_filehandle, (gpfsfsal_op_context_t *) p_context, openflags, (gpfsfsal_file_t *) p_file_descriptor, p_file_attributes); }
static fsal_status_t gpfs_open_func(struct fsal_obj_handle *obj_hdl, fsal_openflags_t openflags, struct fsal_fd *fd) { fsal_status_t status; struct gpfs_fd *my_fd = (struct gpfs_fd *)fd; int posix_flags = 0; my_fd->fd = -1; fsal2posix_openflags(openflags, &posix_flags); status = GPFSFSAL_open(obj_hdl, op_ctx, posix_flags, &my_fd->fd, false); if (FSAL_IS_ERROR(status) == false) my_fd->openflags = openflags; LogFullDebug(COMPONENT_FSAL, "new fd %d", my_fd->fd); return status; }
/** * @brief Open a file descriptor for read or write and possibly create * * This function opens a file for read or write, possibly creating it. * If the caller is passing a state, it must hold the state_lock * exclusive. * * state can be NULL which indicates a stateless open (such as via the * NFS v3 CREATE operation), in which case the FSAL must assure protection * of any resources. If the file is being created, such protection is * simple since no one else will have access to the object yet, however, * in the case of an exclusive create, the common resources may still need * protection. * * If Name is NULL, obj_hdl is the file itself, otherwise obj_hdl is the * parent directory. * * On an exclusive create, the upper layer may know the object handle * already, so it MAY call with name == NULL. In this case, the caller * expects just to check the verifier. * * On a call with an existing object handle for an UNCHECKED create, * we can set the size to 0. * * At least the mode attribute must be set if createmode is not FSAL_NO_CREATE. * Some FSALs may still have to pass a mode on a create call for exclusive, * and even with FSAL_NO_CREATE, and empty set of attributes MUST be passed. * * If an open by name succeeds and did not result in Ganesha creating a file, * the caller will need to do a subsequent permission check to confirm the * open. This is because the permission attributes were not available * beforehand. * * @param[in] obj_hdl File to open or parent directory * @param[in,out] state state_t to use for this operation * @param[in] openflags Mode for open * @param[in] createmode Mode for create * @param[in] name Name for file if being created or opened * @param[in] attrib_set Attributes to set on created file * @param[in] verifier Verifier to use for exclusive create * @param[in,out] new_obj Newly created object * @param[in,out] attrs_out Newly created object attributes * @param[in,out] caller_perm_check The caller must do a permission check * * @return FSAL status. */ fsal_status_t gpfs_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; mode_t unix_mode; fsal_status_t status = {0, 0}; struct gpfs_fd *my_fd = NULL; struct gpfs_fsal_obj_handle *myself; struct gpfs_fsal_obj_handle *hdl = NULL; struct gpfs_file_handle fh; bool truncated; bool created = false; struct fsal_export *export = op_ctx->fsal_export; struct gpfs_filesystem *gpfs_fs = obj_hdl->fs->private_data; int *fd = NULL; myself = container_of(obj_hdl, struct gpfs_fsal_obj_handle, obj_handle); if (name) LogFullDebug(COMPONENT_FSAL, "got name %s", name); else LogFullDebug(COMPONENT_FSAL, "no name"); LogAttrlist(COMPONENT_FSAL, NIV_FULL_DEBUG, "attrs ", attrib_set, false); if (state != NULL) my_fd = (struct gpfs_fd *)(state + 1); fsal2posix_openflags(openflags, &posix_flags); truncated = (posix_flags & O_TRUNC) != 0; 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 */ 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); fd = &my_fd->fd; my_fd->openflags = openflags; } else { /* We need to use the global fd to continue, and take * the lock to protect it. */ fd = &myself->u.file.fd.fd; myself->u.file.fd.openflags = openflags; PTHREAD_RWLOCK_wrlock(&obj_hdl->lock); } status = GPFSFSAL_open(obj_hdl, op_ctx, posix_flags, fd, false); 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; } /* Error - need to release the share */ goto undo_share; } if (attrs_out && (createmode >= FSAL_EXCLUSIVE || truncated)) { /* Refresh the attributes */ status = GPFSFSAL_getattrs(export, gpfs_fs, op_ctx, myself->handle, attrs_out); if (!FSAL_IS_ERROR(status)) { LogFullDebug(COMPONENT_FSAL, "New size = %"PRIx64, attrs_out->filesize); } /* 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_attrlist(attrs_out, 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) fsal_internal_close(*fd, state->state_owner, 0); 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; }