diff options
Diffstat (limited to '0517-gfapi-glfs_h_creat_open-new-API-to-create-handle-and.patch')
-rw-r--r-- | 0517-gfapi-glfs_h_creat_open-new-API-to-create-handle-and.patch | 388 |
1 files changed, 388 insertions, 0 deletions
diff --git a/0517-gfapi-glfs_h_creat_open-new-API-to-create-handle-and.patch b/0517-gfapi-glfs_h_creat_open-new-API-to-create-handle-and.patch new file mode 100644 index 0000000..bc1b263 --- /dev/null +++ b/0517-gfapi-glfs_h_creat_open-new-API-to-create-handle-and.patch @@ -0,0 +1,388 @@ +From da75c2857fd8b173d47fb7fc3b925ffd14105f64 Mon Sep 17 00:00:00 2001 +From: "Kaleb S. KEITHLEY" <kkeithle@rhel7x.kkeithle.usersys.redhat.com> +Date: Wed, 23 Dec 2020 07:39:13 -0500 +Subject: [PATCH 517/517] gfapi: 'glfs_h_creat_open' - new API to create handle + and open fd + +Right now we have two separate APIs, one +- 'glfs_h_creat_handle' to create handle & another +- 'glfs_h_open' to create a glfd to return to application + +Having two separate routines can result in access errors +while trying to create and write into a read-only file. + +Since a fd is opened even during file/directory creation, +introducing a new API to make these two operations atomic i.e, +which can create both handle & fd and pass them to application + +This is backport of below mainline patch - +- https://review.gluster.org/#/c/glusterfs/+/23448/ +- bz#1753569 + +> Signed-off-by: Soumya Koduri <skoduri@redhat.com> +> Change-Id: Ibf513fcfcdad175f4d7eb6fa7a61b8feec6d33b5 +> release-6: commit 5a2af2fd06356f6fc79d591c352caffd4c511c9e +> master: commit 41a0f2aa755ec7162facd30209f2fa3f40308766 + +BUG: 1910119 +Change-Id: Ib397dbe82a6928d8f24251809d30febddd007bfc +Signed-off-by: Kaleb S. KEITHLEY <kkeithle@redhat.com> +Reviewed-on: https://code.engineering.redhat.com/gerrit/222083 +Reviewed-by: Soumya Koduri <skoduri@redhat.com> +Tested-by: RHGS Build Bot <nigelb@redhat.com> +Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com> +--- + api/src/gfapi.aliases | 1 + + api/src/gfapi.map | 5 ++ + api/src/glfs-handleops.c | 135 ++++++++++++++++++++++++++++++++++ + api/src/glfs-handles.h | 5 ++ + tests/basic/gfapi/glfs_h_creat_open.c | 118 +++++++++++++++++++++++++++++ + tests/basic/gfapi/glfs_h_creat_open.t | 27 +++++++ + 6 files changed, 291 insertions(+) + create mode 100644 tests/basic/gfapi/glfs_h_creat_open.c + create mode 100755 tests/basic/gfapi/glfs_h_creat_open.t + +diff --git a/api/src/gfapi.aliases b/api/src/gfapi.aliases +index 692ae13..3d3415c 100644 +--- a/api/src/gfapi.aliases ++++ b/api/src/gfapi.aliases +@@ -197,3 +197,4 @@ _pub_glfs_fsetattr _glfs_fsetattr$GFAPI_6.0 + _pub_glfs_setattr _glfs_setattr$GFAPI_6.0 + + _pub_glfs_set_statedump_path _glfs_set_statedump_path@GFAPI_6.4 ++_pub_glfs_h_creat_open _glfs_h_creat_open@GFAPI_6.6 +diff --git a/api/src/gfapi.map b/api/src/gfapi.map +index df65837..614f3f6 100644 +--- a/api/src/gfapi.map ++++ b/api/src/gfapi.map +@@ -276,3 +276,8 @@ GFAPI_6.4 { + global: + glfs_set_statedump_path; + } GFAPI_PRIVATE_6.1; ++ ++GFAPI_6.6 { ++ global: ++ glfs_h_creat_open; ++} GFAPI_6.4; +diff --git a/api/src/glfs-handleops.c b/api/src/glfs-handleops.c +index d4e1545..7b8ff14 100644 +--- a/api/src/glfs-handleops.c ++++ b/api/src/glfs-handleops.c +@@ -843,6 +843,141 @@ invalid_fs: + GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_creat, 3.4.2); + + struct glfs_object * ++pub_glfs_h_creat_open(struct glfs *fs, struct glfs_object *parent, ++ const char *path, int flags, mode_t mode, ++ struct stat *stat, struct glfs_fd **out_fd) ++{ ++ int ret = -1; ++ struct glfs_fd *glfd = NULL; ++ xlator_t *subvol = NULL; ++ inode_t *inode = NULL; ++ loc_t loc = { ++ 0, ++ }; ++ struct iatt iatt = { ++ 0, ++ }; ++ uuid_t gfid; ++ dict_t *xattr_req = NULL; ++ struct glfs_object *object = NULL; ++ dict_t *fop_attr = NULL; ++ ++ /* validate in args */ ++ if ((fs == NULL) || (parent == NULL) || (path == NULL) || ++ (out_fd == NULL)) { ++ errno = EINVAL; ++ return NULL; ++ } ++ ++ DECLARE_OLD_THIS; ++ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs); ++ ++ /* get the active volume */ ++ subvol = glfs_active_subvol(fs); ++ if (!subvol) { ++ ret = -1; ++ goto out; ++ } ++ ++ /* get/refresh the in arg objects inode in correlation to the xlator */ ++ inode = glfs_resolve_inode(fs, subvol, parent); ++ if (!inode) { ++ ret = -1; ++ goto out; ++ } ++ ++ xattr_req = dict_new(); ++ if (!xattr_req) { ++ ret = -1; ++ errno = ENOMEM; ++ goto out; ++ } ++ ++ gf_uuid_generate(gfid); ++ ret = dict_set_gfuuid(xattr_req, "gfid-req", gfid, true); ++ if (ret) { ++ ret = -1; ++ errno = ENOMEM; ++ goto out; ++ } ++ ++ GLFS_LOC_FILL_PINODE(inode, loc, ret, errno, out, path); ++ ++ glfd = glfs_fd_new(fs); ++ if (!glfd) { ++ ret = -1; ++ errno = ENOMEM; ++ goto out; ++ } ++ ++ glfd->fd = fd_create(loc.inode, getpid()); ++ if (!glfd->fd) { ++ ret = -1; ++ errno = ENOMEM; ++ goto out; ++ } ++ glfd->fd->flags = flags; ++ ++ ret = get_fop_attr_thrd_key(&fop_attr); ++ if (ret) ++ gf_msg_debug("gfapi", 0, "Getting leaseid from thread failed"); ++ ++ /* fop/op */ ++ ret = syncop_create(subvol, &loc, flags, mode, glfd->fd, &iatt, xattr_req, ++ NULL); ++ DECODE_SYNCOP_ERR(ret); ++ ++ /* populate out args */ ++ if (ret == 0) { ++ glfd->fd->flags = flags; ++ ++ ret = glfs_loc_link(&loc, &iatt); ++ if (ret != 0) { ++ goto out; ++ } ++ ++ if (stat) ++ glfs_iatt_to_stat(fs, &iatt, stat); ++ ++ ret = glfs_create_object(&loc, &object); ++ } ++ ++out: ++ if (ret && object != NULL) { ++ /* Release the held reference */ ++ glfs_h_close(object); ++ object = NULL; ++ } ++ ++ loc_wipe(&loc); ++ ++ if (inode) ++ inode_unref(inode); ++ ++ if (fop_attr) ++ dict_unref(fop_attr); ++ ++ if (xattr_req) ++ dict_unref(xattr_req); ++ ++ if (ret && glfd) { ++ GF_REF_PUT(glfd); ++ } else if (glfd) { ++ glfd_set_state_bind(glfd); ++ *out_fd = glfd; ++ } ++ ++ glfs_subvol_done(fs, subvol); ++ ++ __GLFS_EXIT_FS; ++ ++invalid_fs: ++ return object; ++} ++ ++GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_creat_open, 6.6); ++ ++struct glfs_object * + pub_glfs_h_mkdir(struct glfs *fs, struct glfs_object *parent, const char *path, + mode_t mode, struct stat *stat) + { +diff --git a/api/src/glfs-handles.h b/api/src/glfs-handles.h +index f7e6a06..4d039b9 100644 +--- a/api/src/glfs-handles.h ++++ b/api/src/glfs-handles.h +@@ -250,6 +250,11 @@ int + glfs_h_access(glfs_t *fs, glfs_object_t *object, int mask) __THROW + GFAPI_PUBLIC(glfs_h_access, 3.6.0); + ++struct glfs_object * ++glfs_h_creat_open(struct glfs *fs, struct glfs_object *parent, const char *path, ++ int flags, mode_t mode, struct stat *stat, ++ struct glfs_fd **out_fd) __THROW ++ GFAPI_PUBLIC(glfs_h_creat_open, 6.6); + /* + SYNOPSIS + +diff --git a/tests/basic/gfapi/glfs_h_creat_open.c b/tests/basic/gfapi/glfs_h_creat_open.c +new file mode 100644 +index 0000000..7672561 +--- /dev/null ++++ b/tests/basic/gfapi/glfs_h_creat_open.c +@@ -0,0 +1,118 @@ ++#include <fcntl.h> ++#include <unistd.h> ++#include <time.h> ++#include <limits.h> ++#include <string.h> ++#include <stdio.h> ++#include <errno.h> ++#include <stdlib.h> ++#include <glusterfs/api/glfs.h> ++#include <glusterfs/api/glfs-handles.h> ++ ++#define LOG_ERR(func, ret) \ ++ do { \ ++ if (ret != 0) { \ ++ fprintf(stderr, "%s : returned error ret(%d), errno(%d)\n", func, \ ++ ret, errno); \ ++ exit(1); \ ++ } else { \ ++ fprintf(stderr, "%s : returned %d\n", func, ret); \ ++ } \ ++ } while (0) ++#define LOG_IF_NO_ERR(func, ret) \ ++ do { \ ++ if (ret == 0) { \ ++ fprintf(stderr, "%s : hasn't returned error %d\n", func, ret); \ ++ exit(1); \ ++ } else { \ ++ fprintf(stderr, "%s : returned %d\n", func, ret); \ ++ } \ ++ } while (0) ++int ++main(int argc, char *argv[]) ++{ ++ glfs_t *fs = NULL; ++ int ret = 0; ++ struct glfs_object *root = NULL, *leaf = NULL; ++ glfs_fd_t *fd = NULL; ++ char *filename = "/ro-file"; ++ struct stat sb = { ++ 0, ++ }; ++ char *logfile = NULL; ++ char *volname = NULL; ++ char *hostname = NULL; ++ char buf[32] = "abcdefghijklmnopqrstuvwxyz012345"; ++ ++ fprintf(stderr, "Starting glfs_h_creat_open\n"); ++ ++ if (argc != 4) { ++ fprintf(stderr, "Invalid argument\n"); ++ exit(1); ++ } ++ ++ hostname = argv[1]; ++ volname = argv[2]; ++ logfile = argv[3]; ++ ++ fs = glfs_new(volname); ++ if (!fs) { ++ fprintf(stderr, "glfs_new: returned NULL\n"); ++ return 1; ++ } ++ ++ ret = glfs_set_volfile_server(fs, "tcp", hostname, 24007); ++ LOG_ERR("glfs_set_volfile_server", ret); ++ ++ ret = glfs_set_logging(fs, logfile, 7); ++ LOG_ERR("glfs_set_logging", ret); ++ ++ ret = glfs_init(fs); ++ LOG_ERR("glfs_init", ret); ++ ++ sleep(2); ++ root = glfs_h_lookupat(fs, NULL, "/", &sb, 0); ++ if (!root) { ++ ret = -1; ++ LOG_ERR("glfs_h_lookupat root", ret); ++ } ++ leaf = glfs_h_lookupat(fs, root, filename, &sb, 0); ++ if (!leaf) { ++ ret = -1; ++ LOG_IF_NO_ERR("glfs_h_lookupat leaf", ret); ++ } ++ ++ leaf = glfs_h_creat_open(fs, root, filename, O_RDONLY, 00444, &sb, &fd); ++ if (!leaf || !fd) { ++ ret = -1; ++ LOG_ERR("glfs_h_creat leaf", ret); ++ } ++ fprintf(stderr, "glfs_h_create_open leaf - %p\n", leaf); ++ ++ ret = glfs_write(fd, buf, 32, 0); ++ if (ret < 0) { ++ fprintf(stderr, "glfs_write: error writing to file %s, %s\n", filename, ++ strerror(errno)); ++ goto out; ++ } ++ ++ ret = glfs_h_getattrs(fs, leaf, &sb); ++ LOG_ERR("glfs_h_getattrs", ret); ++ ++ if (sb.st_size != 32) { ++ fprintf(stderr, "glfs_write: post size mismatch\n"); ++ goto out; ++ } ++ ++ fprintf(stderr, "Successfully opened and written to a read-only file \n"); ++out: ++ if (fd) ++ glfs_close(fd); ++ ++ ret = glfs_fini(fs); ++ LOG_ERR("glfs_fini", ret); ++ ++ fprintf(stderr, "End of libgfapi_fini\n"); ++ ++ exit(0); ++} +diff --git a/tests/basic/gfapi/glfs_h_creat_open.t b/tests/basic/gfapi/glfs_h_creat_open.t +new file mode 100755 +index 0000000..f24ae73 +--- /dev/null ++++ b/tests/basic/gfapi/glfs_h_creat_open.t +@@ -0,0 +1,27 @@ ++#!/bin/bash ++ ++. $(dirname $0)/../../include.rc ++. $(dirname $0)/../../volume.rc ++ ++cleanup; ++ ++TEST glusterd ++ ++TEST $CLI volume create $V0 $H0:$B0/brick1; ++EXPECT 'Created' volinfo_field $V0 'Status'; ++ ++TEST $CLI volume start $V0; ++EXPECT 'Started' volinfo_field $V0 'Status'; ++ ++logdir=`gluster --print-logdir` ++ ++TEST build_tester $(dirname $0)/glfs_h_creat_open.c -lgfapi ++ ++TEST ./$(dirname $0)/glfs_h_creat_open $H0 $V0 $logdir/glfs.log ++ ++cleanup_tester $(dirname $0)/glfs_h_creat_open ++ ++TEST $CLI volume stop $V0 ++TEST $CLI volume delete $V0 ++ ++cleanup; +-- +1.8.3.1 + |