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_open: * Open a regular file for reading/writing its data content. * * \param filehandle (input): * Handle of the file to be read/modified. * \param cred (input): * Authentication context for the operation (user,...). * \param openflags (input): * 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_descriptor (output): * The file descriptor to be used for FSAL_read/write operations. * \param file_attributes (optionnal input/output): * Post operation attributes. * 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). * * \return Major error codes: * - ERR_FSAL_NO_ERROR: no error. * - Another error code if an error occured during this call. */ fsal_status_t GPFSFSAL_open(fsal_handle_t * p_filehandle, /* IN */ fsal_op_context_t * p_context, /* IN */ fsal_openflags_t openflags, /* IN */ fsal_file_t * file_desc, /* OUT */ fsal_attrib_list_t * p_file_attributes /* [ IN/OUT ] */ ) { int rc, errsv; fsal_status_t status; int fd; int posix_flags = 0; gpfsfsal_file_t * p_file_descriptor = (gpfsfsal_file_t *)file_desc; /* sanity checks. * note : file_attributes is optional. */ if(!p_filehandle || !p_context || !p_file_descriptor) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_open); /* convert fsal open flags to posix open flags */ rc = fsal2posix_openflags(openflags, &posix_flags); /* flags conflicts. */ if(rc) { LogWarn(COMPONENT_FSAL, "Invalid/conflicting flags : %#X", openflags); Return(rc, 0, INDEX_FSAL_open); } TakeTokenFSCall(); status = fsal_internal_handle2fd(p_context, p_filehandle, &fd, posix_flags); ReleaseTokenFSCall(); if(FSAL_IS_ERROR(status)) ReturnStatus(status, INDEX_FSAL_open); /* output attributes */ if(p_file_attributes) { p_file_attributes->asked_attributes = GPFS_SUPPORTED_ATTRIBUTES; status = GPFSFSAL_getattrs(p_filehandle, p_context, p_file_attributes); if(FSAL_IS_ERROR(status)) ReturnStatus(status, INDEX_FSAL_open); } TakeTokenFSCall(); p_file_descriptor->fd = fd; errsv = errno; ReleaseTokenFSCall(); /* set the read-only flag of the file descriptor */ p_file_descriptor->ro = openflags & FSAL_O_RDONLY; Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_open); }
static fsal_status_t vfs_open_func(struct fsal_obj_handle *obj_hdl, fsal_openflags_t openflags, struct fsal_fd *fd) { struct vfs_fsal_obj_handle *myself; int posix_flags = 0; myself = container_of(obj_hdl, struct vfs_fsal_obj_handle, obj_handle); fsal2posix_openflags(openflags, &posix_flags); return vfs_open_my_fd(myself, openflags, posix_flags, (struct vfs_fd *)fd); }
static fsal_status_t file_open(struct fsal_obj_handle *obj_hdl, const struct req_op_context *opctx, fsal_openflags_t openflags) { int rc = 0; fsal_status_t status = { ERR_FSAL_NO_ERROR, 0 }; struct glfs_fd *glfd = NULL; int p_flags = 0; struct glusterfs_export *glfs_export = container_of(obj_hdl->export, struct glusterfs_export, export); struct glusterfs_handle *objhandle = container_of(obj_hdl, struct glusterfs_handle, handle); #ifdef GLTIMING struct timespec s_time, e_time; now(&s_time); #endif if (objhandle->openflags != FSAL_O_CLOSED) { return fsalstat(ERR_FSAL_SERVERFAULT, 0); } rc = fsal2posix_openflags(openflags, &p_flags); if (rc != 0) { status.major = rc; goto out; } glfd = glfs_h_open(glfs_export->gl_fs, objhandle->glhandle, p_flags); if (glfd == NULL) { status = gluster2fsal_error(errno); goto out; } objhandle->openflags = openflags; objhandle->glfd = glfd; out: #ifdef GLTIMING now(&e_time); latency_update(&s_time, &e_time, lat_file_open); #endif return status; }
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; }
fsal_status_t vfs_open(struct fsal_obj_handle *obj_hdl, fsal_openflags_t openflags) { struct vfs_fsal_obj_handle *myself; int fd; fsal_errors_t fsal_error = ERR_FSAL_NO_ERROR; int posix_flags = 0; int retval = 0; 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); retval = EXDEV; fsal_error = posix2fsal_error(retval); return fsalstat(fsal_error, retval); } /* Take write lock on object to protect file descriptor. */ PTHREAD_RWLOCK_wrlock(&obj_hdl->lock); assert(myself->u.file.fd == -1 && myself->u.file.openflags == FSAL_O_CLOSED && openflags != 0); fsal2posix_openflags(openflags, &posix_flags); LogFullDebug(COMPONENT_FSAL, "open_by_handle_at flags from %x to %x", openflags, posix_flags); fd = vfs_fsal_open(myself, posix_flags, &fsal_error); if (fd < 0) { retval = -fd; } else { myself->u.file.fd = fd; myself->u.file.openflags = openflags; } PTHREAD_RWLOCK_unlock(&obj_hdl->lock); return fsalstat(fsal_error, retval); }
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; }
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; }
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); }
/** * @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; }
/** * FSAL_open: * Open a regular file for reading/writing its data content. * * \param filehandle (input): * Handle of the file to be read/modified. * \param cred (input): * Authentication context for the operation (user,...). * \param openflags (input): * 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_descriptor (output): * The file descriptor to be used for FSAL_read/write operations. * \param file_attributes (optionnal input/output): * Post operation attributes. * 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). * * \return Major error codes: * - ERR_FSAL_NO_ERROR (no error) * - ERR_FSAL_ACCESS (user doesn't have the permissions for opening the file) * - ERR_FSAL_STALE (filehandle does not address an existing object) * - ERR_FSAL_INVAL (filehandle does not address a regular file, * or open flags are conflicting) * - ERR_FSAL_FAULT (a NULL pointer was passed as mandatory argument) * - Other error codes can be returned : * ERR_FSAL_IO, ... */ fsal_status_t ZFSFSAL_open(zfsfsal_handle_t * filehandle, /* IN */ zfsfsal_op_context_t * p_context, /* IN */ fsal_openflags_t openflags, /* IN */ zfsfsal_file_t * file_descriptor, /* OUT */ fsal_attrib_list_t * file_attributes /* [ IN/OUT ] */ ) { int rc; /* sanity checks. * note : file_attributes is optional. */ if(!filehandle || !p_context || !file_descriptor) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_open); /* >> you can check if this is a file if the information * is stored into the handle << */ if(filehandle->data.type != FSAL_TYPE_FILE) Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_open); /* >> convert fsal open flags to your FS open flags * Take care of conflicting flags << */ int posix_flags; rc = fsal2posix_openflags(openflags, &posix_flags); if(rc) Return(rc, 0, INDEX_FSAL_open); TakeTokenFSCall(); /* >> call your FS open function << */ libzfswrap_vnode_t *p_vnode; rc = libzfswrap_open(p_context->export_context->p_vfs, &p_context->user_credential.cred, filehandle->data.zfs_handle, posix_flags, &p_vnode); ReleaseTokenFSCall(); /* >> interpret returned status << */ if(rc) Return(posix2fsal_error(rc), rc, INDEX_FSAL_open); /* >> fill output struct << */ file_descriptor->p_vfs = p_context->export_context->p_vfs; file_descriptor->flags = posix_flags; file_descriptor->current_offset = 0; file_descriptor->p_vnode = p_vnode; file_descriptor->zfs_handle = filehandle->data.zfs_handle; file_descriptor->cred = p_context->user_credential.cred; file_descriptor->is_closed = 0; if(file_attributes) { fsal_status_t status = ZFSFSAL_getattrs(filehandle, p_context, file_attributes); /* On error, we set a flag in the returned attributes */ if(FSAL_IS_ERROR(status)) { FSAL_CLEAR_MASK(file_attributes->asked_attributes); FSAL_SET_MASK(file_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); } } Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_open); }
/** * FSAL_open: * Open a regular file for reading/writing its data content. * * \param filehandle (input): * Handle of the file to be read/modified. * \param cred (input): * Authentication context for the operation (user,...). * \param openflags (input): * 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_descriptor (output): * The file descriptor to be used for FSAL_read/write operations. * \param file_attributes (optionnal input/output): * Post operation attributes. * 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). * * \return Major error codes: * - ERR_FSAL_NO_ERROR: no error. * - Another error code if an error occured during this call. */ fsal_status_t LUSTREFSAL_open(lustrefsal_handle_t * p_filehandle, /* IN */ lustrefsal_op_context_t * p_context, /* IN */ fsal_openflags_t openflags, /* IN */ lustrefsal_file_t * p_file_descriptor, /* OUT */ fsal_attrib_list_t * p_file_attributes /* [ IN/OUT ] */ ) { int rc, errsv; fsal_status_t status; fsal_path_t fsalpath; struct stat buffstat; int posix_flags = 0; /* sanity checks. * note : file_attributes is optional. */ if(!p_filehandle || !p_context || !p_file_descriptor) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_open); status = fsal_internal_Handle2FidPath(p_context, p_filehandle, &fsalpath); if(FSAL_IS_ERROR(status)) ReturnStatus(status, INDEX_FSAL_open); /* retrieve file attributes for checking access rights */ TakeTokenFSCall(); rc = lstat(fsalpath.path, &buffstat); errsv = errno; ReleaseTokenFSCall(); if(rc) { if(errsv == ENOENT) Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_open); else Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_open); } status = fsal_internal_testAccess(p_context, openflags & FSAL_O_RDONLY ? FSAL_R_OK : FSAL_W_OK, &buffstat, NULL); if(FSAL_IS_ERROR(status)) ReturnStatus(status, INDEX_FSAL_open); /* convert fsal open flags to posix open flags */ rc = fsal2posix_openflags(openflags, &posix_flags); /* flags conflicts. */ if(rc) { LogEvent(COMPONENT_FSAL, "Invalid/conflicting flags : %#X", openflags); Return(rc, 0, INDEX_FSAL_open); } TakeTokenFSCall(); p_file_descriptor->fd = open(fsalpath.path, posix_flags, 0644); errsv = errno; ReleaseTokenFSCall(); if(p_file_descriptor->fd == -1) Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_open); /* set the read-only flag of the file descriptor */ p_file_descriptor->ro = openflags & FSAL_O_RDONLY; /* output attributes */ if(p_file_attributes) { status = posix2fsal_attributes(&buffstat, p_file_attributes); if(FSAL_IS_ERROR(status)) { FSAL_CLEAR_MASK(p_file_attributes->asked_attributes); FSAL_SET_MASK(p_file_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); } } Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_open); }
/** * FSAL_open: * Open a regular file for reading/writing its data content. * * \param filehandle (input): * Handle of the file to be read/modified. * \param cred (input): * Authentication context for the operation (user,...). * \param openflags (input): * 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_descriptor (output): * The file descriptor to be used for FSAL_read/write operations. * \param file_attributes (optionnal input/output): * Post operation attributes. * 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). * * \return Major error codes: * - ERR_FSAL_NO_ERROR (no error) * - ERR_FSAL_ACCESS (user doesn't have the permissions for opening the file) * - ERR_FSAL_STALE (filehandle does not address an existing object) * - ERR_FSAL_INVAL (filehandle does not address a regular file, * or open flags are conflicting) * - ERR_FSAL_FAULT (a NULL pointer was passed as mandatory argument) * - Other error codes can be returned : * ERR_FSAL_IO, ... */ fsal_status_t ZFSFSAL_open(fsal_handle_t * file_hdl, /* IN */ fsal_op_context_t * p_context, /* IN */ fsal_openflags_t openflags, /* IN */ fsal_file_t * file_desc, /* OUT */ fsal_attrib_list_t * file_attributes /* [ IN/OUT ] */ ) { int rc; creden_t cred; zfsfsal_handle_t * filehandle = (zfsfsal_handle_t *)file_hdl; zfsfsal_file_t * file_descriptor = ( zfsfsal_file_t *)file_desc; /* sanity checks. * note : file_attributes is optional. */ if(!filehandle || !p_context || !file_descriptor) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_open); /* Check if this is a file */ if(filehandle->data.type != FSAL_TYPE_FILE) Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_open); /* Get the right VFS */ ZFSFSAL_VFS_RDLock(); libzfswrap_vfs_t *p_vfs = ZFSFSAL_GetVFS(filehandle); if(!p_vfs) { ZFSFSAL_VFS_Unlock(); Return(ERR_FSAL_NOENT, 0, INDEX_FSAL_open); } /* >> convert fsal open flags to your FS open flags * Take care of conflicting flags << */ int posix_flags; rc = fsal2posix_openflags(openflags, &posix_flags); if(rc) Return(rc, 0, INDEX_FSAL_open); cred.uid = p_context->credential.user; cred.gid = p_context->credential.group; TakeTokenFSCall(); /* >> call your FS open function << */ libzfswrap_vnode_t *p_vnode; rc = libzfswrap_open(p_vfs, &cred, filehandle->data.zfs_handle, posix_flags, &p_vnode); ReleaseTokenFSCall(); ZFSFSAL_VFS_Unlock(); /* >> interpret returned status << */ if(rc) Return(posix2fsal_error(rc), 0, INDEX_FSAL_open); /* >> fill output struct << */ file_descriptor->flags = posix_flags; file_descriptor->current_offset = 0; file_descriptor->p_vnode = p_vnode; file_descriptor->handle = *filehandle; file_descriptor->cred = cred; file_descriptor->is_closed = 0; if(file_attributes) { fsal_status_t status = ZFSFSAL_getattrs(file_hdl, p_context, file_attributes); /* On error, we set a flag in the returned attributes */ if(FSAL_IS_ERROR(status)) { FSAL_CLEAR_MASK(file_attributes->asked_attributes); FSAL_SET_MASK(file_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); } } Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_open); }
/** * FSAL_open: * Open a regular file for reading/writing its data content. * * \param filehandle (input): * Handle of the file to be read/modified. * \param cred (input): * Authentication context for the operation (user,...). * \param openflags (input): * 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_descriptor (output): * The file descriptor to be used for FSAL_read/write operations. * \param file_attributes (optionnal input/output): * Post operation attributes. * 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). * * \return Major error codes: * - ERR_FSAL_NO_ERROR: no error. * - Another error code if an error occured during this call. */ fsal_status_t POSIXFSAL_open(fsal_handle_t * filehandle, /* IN */ fsal_op_context_t * context, /* IN */ fsal_openflags_t openflags, /* IN */ fsal_file_t * file_descriptor, /* OUT */ fsal_attrib_list_t * p_file_attributes /* [ IN/OUT ] */ ) { posixfsal_handle_t * p_filehandle = (posixfsal_handle_t *) filehandle; posixfsal_op_context_t * p_context = (posixfsal_op_context_t *) context; posixfsal_file_t * p_file_descriptor = (posixfsal_file_t *) file_descriptor; int rc, errsv; fsal_status_t status; fsal_path_t fsalpath; struct stat buffstat; #ifdef _FSAL_POSIX_USE_STREAM char posix_flags[4]; /* stores r, r+, w, w+, a, or a+ */ #else int posix_flags; #endif /* sanity checks. * note : file_attributes is optional. */ if(!p_filehandle || !p_context || !p_file_descriptor) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_open); status = fsal_internal_getPathFromHandle(p_context, p_filehandle, 0, &fsalpath, &buffstat); if(FSAL_IS_ERROR(status)) Return(status.major, status.minor, INDEX_FSAL_open); status = fsal_internal_testAccess(p_context, (openflags & FSAL_O_RDONLY ? FSAL_R_OK : FSAL_W_OK) | FSAL_OWNER_OK, &buffstat, NULL); if(FSAL_IS_ERROR(status)) Return(status.major, status.minor, INDEX_FSAL_open); /* convert fsal open flags to posix open flags */ rc = fsal2posix_openflags(openflags, &posix_flags); /* flags conflicts. */ if(rc) { LogEvent(COMPONENT_FSAL, "Invalid/conflicting flags : %#X", openflags); Return(rc, 0, INDEX_FSAL_open); } TakeTokenFSCall(); #ifdef _FSAL_POSIX_USE_STREAM p_file_descriptor->p_file = fopen(fsalpath.path, posix_flags); errsv = errno; ReleaseTokenFSCall(); if(!(p_file_descriptor->p_file)) Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_open); #else p_file_descriptor->filefd = open(fsalpath.path, posix_flags); errsv = errno; ReleaseTokenFSCall(); #endif /* set the read-only flag of the file descriptor */ p_file_descriptor->ro = openflags & FSAL_O_RDONLY; /* output attributes */ if(p_file_attributes) { status = posix2fsal_attributes(&buffstat, p_file_attributes); if(FSAL_IS_ERROR(status)) { FSAL_CLEAR_MASK(p_file_attributes->asked_attributes); FSAL_SET_MASK(p_file_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); } } Return(ERR_FSAL_NO_ERROR, errsv, INDEX_FSAL_open); /* use the error... */ }
/** * FSAL_open: * Open a regular file for reading/writing its data content. * * \param filehandle (input): * Handle of the file to be read/modified. * \param cred (input): * Authentication context for the operation (user,...). * \param openflags (input): * 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_descriptor (output): * The file descriptor to be used for FSAL_read/write operations. * \param file_attributes (optionnal input/output): * Post operation attributes. * 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). * * \return Major error codes: * - ERR_FSAL_NO_ERROR: no error. * - Another error code if an error occured during this call. */ fsal_status_t XFSFSAL_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 ] */ ) { int rc, errsv; fsal_status_t status; int fd = 0 ; struct stat buffstat; int posix_flags = 0; /* sanity checks. * note : file_attributes is optional. */ if(!p_filehandle || !p_context || !p_file_descriptor) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_open); /* convert fsal open flags to posix open flags */ rc = fsal2posix_openflags(openflags, &posix_flags); /* flags conflicts. */ if(rc) { LogEvent(COMPONENT_FSAL, "Invalid/conflicting flags : %#X", openflags); Return(rc, 0, INDEX_FSAL_open); } TakeTokenFSCall(); status = fsal_internal_handle2fd(p_context, p_filehandle, &fd, posix_flags); ReleaseTokenFSCall(); if(FSAL_IS_ERROR(status)) ReturnStatus(status, INDEX_FSAL_open); /* retrieve file attributes for checking access rights */ TakeTokenFSCall(); rc = fstat(fd, &buffstat); errsv = errno; ReleaseTokenFSCall(); if(rc) { close(fd); if(errsv == ENOENT) Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_open); else Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_open); } #if 0 /* No required, the open would have failed if not permitted */ status = fsal_check_access(p_context, openflags & FSAL_O_RDONLY ? FSAL_R_OK : FSAL_W_OK, &buffstat, NULL); if(FSAL_IS_ERROR(status)) { close(fd); ReturnStatus(status, INDEX_FSAL_open); } #endif TakeTokenFSCall(); ((xfsfsal_file_t *)p_file_descriptor)->fd = fd; errsv = errno; ReleaseTokenFSCall(); /* set the read-only flag of the file descriptor */ ((xfsfsal_file_t *)p_file_descriptor)->ro = openflags & FSAL_O_RDONLY; /* output attributes */ if(p_file_attributes) { status = posix2fsal_attributes(&buffstat, p_file_attributes); if(FSAL_IS_ERROR(status)) { FSAL_CLEAR_MASK(p_file_attributes->asked_attributes); FSAL_SET_MASK(p_file_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); } } Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_open); }
/** * FSAL_open: * Open a regular file for reading/writing its data content. * * \param filehandle (input): * Handle of the file to be read/modified. * \param cred (input): * Authentication context for the operation (user,...). * \param openflags (input): * 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_descriptor (output): * The file descriptor to be used for FSAL_read/write operations. * \param file_attributes (optionnal input/output): * Post operation attributes. * 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). * * \return Major error codes: * - ERR_FSAL_NO_ERROR: no error. * - Another error code if an error occured during this call. */ fsal_status_t GPFSFSAL_open(fsal_handle_t * p_filehandle, /* IN */ fsal_op_context_t * p_context, /* IN */ fsal_openflags_t openflags, /* IN */ fsal_file_t * file_desc, /* OUT */ fsal_attrib_list_t * p_file_attributes /* [ IN/OUT ] */ ) { int rc, errsv; fsal_status_t status; int fd; int posix_flags = 0; fsal_accessflags_t access_mask = 0; fsal_attrib_list_t file_attrs; gpfsfsal_file_t * p_file_descriptor = (gpfsfsal_file_t *)file_desc; /* sanity checks. * note : file_attributes is optional. */ if(!p_filehandle || !p_context || !p_file_descriptor) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_open); /* convert fsal open flags to posix open flags */ rc = fsal2posix_openflags(openflags, &posix_flags); /* flags conflicts. */ if(rc) { LogWarn(COMPONENT_FSAL, "Invalid/conflicting flags : %#X", openflags); Return(rc, 0, INDEX_FSAL_open); } TakeTokenFSCall(); status = fsal_internal_handle2fd(p_context, p_filehandle, &fd, posix_flags); ReleaseTokenFSCall(); if(FSAL_IS_ERROR(status)) ReturnStatus(status, INDEX_FSAL_open); /* retrieve file attributes for checking access rights */ file_attrs.asked_attributes = GPFS_SUPPORTED_ATTRIBUTES; status = GPFSFSAL_getattrs(p_filehandle, p_context, &file_attrs); if(FSAL_IS_ERROR(status)) ReturnStatus(status, INDEX_FSAL_open); /* Set both mode and ace4 mask */ if(openflags & FSAL_O_RDONLY) access_mask = FSAL_MODE_MASK_SET(FSAL_R_OK | FSAL_OWNER_OK) | FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_READ_DATA); else access_mask = FSAL_MODE_MASK_SET(FSAL_W_OK | FSAL_OWNER_OK) | FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_WRITE_DATA | FSAL_ACE_PERM_APPEND_DATA); status = fsal_internal_testAccess(p_context, access_mask, NULL, &file_attrs); if(FSAL_IS_ERROR(status)) { close(fd); ReturnStatus(status, INDEX_FSAL_open); } TakeTokenFSCall(); p_file_descriptor->fd = fd; errsv = errno; ReleaseTokenFSCall(); /* set the read-only flag of the file descriptor */ p_file_descriptor->ro = openflags & FSAL_O_RDONLY; /* output attributes */ if(p_file_attributes) *p_file_attributes = file_attrs; Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_open); }