From efad78260379f0ca836e8a2327b97dd620acd098 Mon Sep 17 00:00:00 2001 From: Susant Palai Date: Tue, 22 Aug 2017 13:44:52 +0530 Subject: rio/everywhere: add icreate/namelink fop icreate creates inode, while namelink links the basename to it's parent gfid. For now mkdir is the primary user of these fops. Better distribution is acheived by creating the inode on ,(say) mds1 and linking the basename to it's parent gfid on mds2. The inode serves readdirp, stat etc. More details about the fops are present at: https://review.gluster.org/#/c/13395/3/design/DHT2/DHT2_Icreate_Namelink_Notes.md This backport of three patches from experimental branch. 1- https://review.gluster.org/#/c/18085/ 2- https://review.gluster.org/#/c/18086/ 3- https://review.gluster.org/#/c/18094/ Updates gluster/glusterfs#243 Change-Id: I1bd3d5a441a3cfab1acfeb52f15c6c867d362592 Signed-off-by: Susant Palai --- libglusterfs/src/call-stub.c | 120 ++++++++++++ libglusterfs/src/call-stub.h | 24 +++ libglusterfs/src/common-utils.c | 3 +- libglusterfs/src/default-args.c | 23 +++ libglusterfs/src/default-args.h | 8 + libglusterfs/src/defaults-tmpl.c | 2 + libglusterfs/src/defaults.h | 32 ++++ libglusterfs/src/generator.py | 17 ++ libglusterfs/src/globals.c | 2 + libglusterfs/src/glusterfs.h | 1 + libglusterfs/src/syncop.c | 76 ++++++++ libglusterfs/src/syncop.h | 10 + libglusterfs/src/xlator.c | 2 + libglusterfs/src/xlator.h | 20 ++ rpc/rpc-lib/src/protocol-common.h | 2 + rpc/xdr/src/glusterfs-fops.x | 2 + rpc/xdr/src/glusterfs4-xdr.x | 27 +++ xlators/performance/io-threads/src/io-threads.c | 2 + xlators/protocol/client/src/client-rpc-fops.c | 198 ++++++++++++++++++++ xlators/protocol/client/src/client.c | 56 ++++++ xlators/protocol/server/src/server-rpc-fops.c | 234 ++++++++++++++++++++++++ 21 files changed, 860 insertions(+), 1 deletion(-) diff --git a/libglusterfs/src/call-stub.c b/libglusterfs/src/call-stub.c index 74a64294528..d5c4f1365e8 100644 --- a/libglusterfs/src/call-stub.c +++ b/libglusterfs/src/call-stub.c @@ -2009,6 +2009,126 @@ out: return stub; } +call_stub_t * +fop_icreate_stub (call_frame_t *frame, fop_icreate_t fn, + loc_t *loc, mode_t mode, dict_t *xdata) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", fn, out); + + stub = stub_new (frame, 1, GF_FOP_ICREATE); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->fn.icreate = fn; + + stub->args.mode = mode; + if (loc) + loc_copy (&stub->args.loc, loc); + if (xdata) + stub->args.xdata = dict_ref (xdata); + + out: + return stub; +} + +static void +args_icreate_store_cbk (default_args_cbk_t *args, + int32_t op_ret, int32_t op_errno, + inode_t *inode, struct iatt *buf, dict_t *xdata) +{ + args->op_ret = op_ret; + args->op_errno = op_errno; + if (inode) + args->inode = inode_ref (inode); + if (buf) + args->stat = *buf; + if (xdata) + args->xdata = dict_ref (xdata); +} + +call_stub_t * +fop_icreate_cbk_stub (call_frame_t *frame, + fop_icreate_cbk_t fn, + int32_t op_ret, int32_t op_errno, + inode_t *inode, struct iatt *buf, dict_t *xdata) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_ICREATE); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->fn_cbk.icreate = fn; + args_icreate_store_cbk (&stub->args_cbk, + op_ret, op_errno, inode, buf, xdata); + + out: + return stub; +} + +call_stub_t * +fop_namelink_stub (call_frame_t *frame, + fop_namelink_t fn, loc_t *loc, dict_t *xdata) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + GF_VALIDATE_OR_GOTO ("call-stub", fn, out); + + stub = stub_new (frame, 1, GF_FOP_NAMELINK); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->fn.namelink = fn; + + if (loc) + loc_copy (&stub->args.loc, loc); + if (xdata) + stub->args.xdata = dict_ref (xdata); + + out: + return stub; +} + +static void +args_namelink_store_cbk (default_args_cbk_t *args, + int32_t op_ret, int32_t op_errno, + struct iatt *prebuf, struct iatt *postbuf, dict_t *xdata) +{ + args->op_ret = op_ret; + args->op_errno = op_errno; + + if (prebuf) + args->prestat = *prebuf; + if (postbuf) + args->poststat = *postbuf; + if (xdata) + args->xdata = dict_ref (xdata); +} + +call_stub_t * +fop_namelink_cbk_stub (call_frame_t *frame, + fop_namelink_cbk_t fn, + int32_t op_ret, int32_t op_errno, + struct iatt *prebuf, struct iatt *postbuf, dict_t *xdata) +{ + call_stub_t *stub = NULL; + + GF_VALIDATE_OR_GOTO ("call-stub", frame, out); + + stub = stub_new (frame, 0, GF_FOP_NAMELINK); + GF_VALIDATE_OR_GOTO ("call-stub", stub, out); + + stub->fn_cbk.namelink = fn; + args_namelink_store_cbk (&stub->args_cbk, + op_ret, op_errno, prebuf, postbuf, xdata); + + out: + return stub; +} + void call_resume_wind (call_stub_t *stub) { diff --git a/libglusterfs/src/call-stub.h b/libglusterfs/src/call-stub.h index 4d86a517537..e20f6a5a096 100644 --- a/libglusterfs/src/call-stub.h +++ b/libglusterfs/src/call-stub.h @@ -78,6 +78,8 @@ typedef struct _call_stub { fop_getactivelk_t getactivelk; fop_setactivelk_t setactivelk; fop_put_t put; + fop_icreate_t icreate; + fop_namelink_t namelink; } fn; union { @@ -131,6 +133,8 @@ typedef struct _call_stub { fop_getactivelk_cbk_t getactivelk; fop_setactivelk_cbk_t setactivelk; fop_put_cbk_t put; + fop_icreate_cbk_t icreate; + fop_namelink_cbk_t namelink; } fn_cbk; default_args_t args; @@ -776,6 +780,26 @@ fop_put_cbk_stub (call_frame_t *frame, fop_put_cbk_t fn, int32_t op_ret, struct iatt *preparent, struct iatt *postparent, dict_t *xdata); +call_stub_t * +fop_icreate_stub (call_frame_t *frame, fop_icreate_t fn, + loc_t *loc, mode_t mode, dict_t *xdata); + +call_stub_t * +fop_namelink_stub (call_frame_t *frame, + fop_namelink_t fn, loc_t *loc, dict_t *xdata); + +call_stub_t * +fop_icreate_cbk_stub (call_frame_t *frame, + fop_icreate_cbk_t fn, + int32_t op_ret, int32_t op_errno, + inode_t *inode, struct iatt *buf, dict_t *xdata); + +call_stub_t * +fop_namelink_cbk_stub (call_frame_t *frame, + fop_namelink_cbk_t fn, + int32_t op_ret, int32_t op_errno, + struct iatt *prebuf, struct iatt *postbuf, dict_t *xdata); + void call_resume (call_stub_t *stub); void call_resume_keep_stub (call_stub_t *stub); void call_stub_destroy (call_stub_t *stub); diff --git a/libglusterfs/src/common-utils.c b/libglusterfs/src/common-utils.c index 68d2e243f58..ad0359d7cb2 100644 --- a/libglusterfs/src/common-utils.c +++ b/libglusterfs/src/common-utils.c @@ -4591,6 +4591,8 @@ fop_enum_to_pri_string (glusterfs_fop_t fop) case GF_FOP_READDIRP: case GF_FOP_GETACTIVELK: case GF_FOP_SETACTIVELK: + case GF_FOP_ICREATE: + case GF_FOP_NAMELINK: return "HIGH"; case GF_FOP_CREATE: @@ -4940,4 +4942,3 @@ get_struct_variable (int mem_num, gf_gsync_status_t *sts_val) out: return NULL; } - diff --git a/libglusterfs/src/default-args.c b/libglusterfs/src/default-args.c index 9ac0f400493..20cd05e68cb 100644 --- a/libglusterfs/src/default-args.c +++ b/libglusterfs/src/default-args.c @@ -1580,6 +1580,29 @@ args_lease_cbk_store (default_args_cbk_t *args, args->xdata = dict_ref (xdata); } +int +args_icreate_store (default_args_t *args, + loc_t *loc, mode_t mode, dict_t *xdata) +{ + loc_copy (&args->loc, loc); + args->mode = mode; + + if (xdata) + args->xdata = dict_ref (xdata); + return 0; +} + +int +args_namelink_store (default_args_t *args, + loc_t *loc, dict_t *xdata) +{ + loc_copy (&args->loc, loc); + + if (xdata) + args->xdata = dict_ref (xdata); + return 0; +} + void args_cbk_wipe (default_args_cbk_t *args_cbk) { diff --git a/libglusterfs/src/default-args.h b/libglusterfs/src/default-args.h index f97d8830de9..7d46fefa663 100644 --- a/libglusterfs/src/default-args.h +++ b/libglusterfs/src/default-args.h @@ -488,6 +488,14 @@ args_getactivelk_cbk_store (default_args_cbk_t *args, int args_setactivelk_store (default_args_t *args, loc_t *loc, lock_migration_info_t *locklist, dict_t *xdata); + +int +args_icreate_store (default_args_t *args, + loc_t *loc, mode_t mode, dict_t *xdata); + +int +args_namelink_store (default_args_t *args, loc_t *loc, dict_t *xdata); + void args_cbk_init (default_args_cbk_t *args_cbk); #endif /* _DEFAULT_ARGS_H */ diff --git a/libglusterfs/src/defaults-tmpl.c b/libglusterfs/src/defaults-tmpl.c index 21b99d9566c..b9f6274800e 100644 --- a/libglusterfs/src/defaults-tmpl.c +++ b/libglusterfs/src/defaults-tmpl.c @@ -82,6 +82,8 @@ struct xlator_fops _default_fops = { .getactivelk = default_getactivelk, .setactivelk = default_setactivelk, .put = default_put, + .icreate = default_icreate, + .namelink = default_namelink, }; struct xlator_fops *default_fops = &_default_fops; diff --git a/libglusterfs/src/defaults.h b/libglusterfs/src/defaults.h index c202dbe4941..5e56cc2c9f9 100644 --- a/libglusterfs/src/defaults.h +++ b/libglusterfs/src/defaults.h @@ -359,6 +359,12 @@ default_put (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode, mode_t umask, uint32_t flags, struct iovec *vector, int32_t count, off_t off, struct iobref *iobref, dict_t *xattr, dict_t *xdata); +int32_t default_icreate (call_frame_t *frame, xlator_t *this, + loc_t *loc, mode_t mode, dict_t *xdata); + +int32_t default_namelink (call_frame_t *frame, + xlator_t *this, loc_t *loc, dict_t *xdata); + /* Resume */ int32_t default_getspec_resume (call_frame_t *frame, xlator_t *this, @@ -912,6 +918,14 @@ default_put_cbk_resume (call_frame_t *frame, void *cookie, xlator_t *this, struct iatt *buf, struct iatt *preparent, struct iatt *postparent, dict_t *xdata); +int32_t +default_icreate_resume (call_frame_t *frame, xlator_t *this, + loc_t *loc, mode_t mode, dict_t *xdata); + +int32_t +default_namelink_resume (call_frame_t *frame, + xlator_t *this, loc_t *loc, dict_t *xdata); + /* _CBK */ int32_t default_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, @@ -1165,6 +1179,18 @@ default_put_cbk (call_frame_t *frame, void *cookie, xlator_t *this, struct iatt *buf, struct iatt *preparent, struct iatt *postparent, dict_t *xdata); +int32_t +default_icreate_cbk (call_frame_t *frame, + void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, + inode_t *inode, struct iatt *buf, dict_t *xdata); + +int32_t +default_namelink_cbk (call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata); + int32_t default_lookup_failure_cbk (call_frame_t *frame, int32_t op_errno); @@ -1320,6 +1346,12 @@ default_setactivelk_failure_cbk (call_frame_t *frame, int32_t op_errno); int32_t default_put_failure_cbk (call_frame_t *frame, int32_t op_errno); +int32_t +default_icreate_failure_cbk (call_frame_t *frame, int32_t op_errno); + +int32_t +default_namelink_failure_cbk (call_frame_t *frame, int32_t op_errno); + int32_t default_mem_acct_init (xlator_t *this); diff --git a/libglusterfs/src/generator.py b/libglusterfs/src/generator.py index d9262e473b7..7fa5f433501 100755 --- a/libglusterfs/src/generator.py +++ b/libglusterfs/src/generator.py @@ -575,6 +575,23 @@ ops['put'] = ( ('cbk-arg', 'xdata', 'dict_t *'), ) +ops['icreate'] = ( + ('fop-arg', 'loc', 'loc_t *'), + ('fop-arg', 'mode', 'mode_t'), + ('fop-arg', 'xdata', 'dict_t *'), + ('cbk-arg', 'inode', 'inode_t *'), + ('cbk-arg', 'buf', 'struct iatt *'), + ('cbk-arg', 'xdata', 'dict_t *'), +) + +ops['namelink'] = ( + ('fop-arg', 'loc', 'loc_t *'), + ('fop-arg', 'xdata', 'dict_t *'), + ('cbk-arg', 'prebuf', 'struct iatt *'), + ('cbk-arg', 'postbuf', 'struct iatt *'), + ('cbk-arg', 'xdata', 'dict_t *'), +) + ##################################################################### xlator_cbks['forget'] = ( ('fn-arg', 'this', 'xlator_t *'), diff --git a/libglusterfs/src/globals.c b/libglusterfs/src/globals.c index 1c574463123..6bed1b546ee 100644 --- a/libglusterfs/src/globals.c +++ b/libglusterfs/src/globals.c @@ -75,6 +75,8 @@ const char *gf_fop_list[GF_FOP_MAXVALUE] = { [GF_FOP_GETACTIVELK] = "GETACTIVELK", [GF_FOP_SETACTIVELK] = "SETACTIVELK", [GF_FOP_PUT] = "PUT", + [GF_FOP_ICREATE] = "ICREATE", + [GF_FOP_NAMELINK] = "NAMELINK", }; const char *gf_upcall_list[GF_UPCALL_FLAGS_MAXVALUE] = { diff --git a/libglusterfs/src/glusterfs.h b/libglusterfs/src/glusterfs.h index ad8e396fde5..aa28b80222e 100644 --- a/libglusterfs/src/glusterfs.h +++ b/libglusterfs/src/glusterfs.h @@ -306,6 +306,7 @@ const char *fop_enum_to_pri_string (glusterfs_fop_t fop); #define GF_SET_OVERWRITE 0x2 /* Overwrite with the buf given */ #define GF_SET_DIR_ONLY 0x4 #define GF_SET_EPOCH_TIME 0x8 /* used by afr dir lookup selfheal */ +#define GF_AUXILLARY_PARGFID 0xd /* RIO dummy parent gfid */ /* key value which quick read uses to get small files in lookup cbk */ #define GF_CONTENT_KEY "glusterfs.content" diff --git a/libglusterfs/src/syncop.c b/libglusterfs/src/syncop.c index a4882f5eef2..58c606b238f 100644 --- a/libglusterfs/src/syncop.c +++ b/libglusterfs/src/syncop.c @@ -3251,3 +3251,79 @@ syncop_setactivelk (xlator_t *subvol, loc_t *loc, return args.op_ret; } + +int +syncop_icreate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, inode_t *inode, + struct iatt *buf, dict_t *xdata) +{ + struct syncargs *args = NULL; + + args = cookie; + + args->op_ret = op_ret; + args->op_errno = op_errno; + if (xdata) + args->xdata = dict_ref (xdata); + + if (buf) + args->iatt1 = *buf; + + __wake (args); + + return 0; +} + +int +syncop_namelink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata) +{ + struct syncargs *args = NULL; + + args = cookie; + + args->op_ret = op_ret; + args->op_errno = op_errno; + + if (xdata) + args->xdata = dict_ref (xdata); + + __wake (args); + + return 0; +} + +int +syncop_icreate (xlator_t *subvol, loc_t *loc, mode_t mode, dict_t *xdata) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_icreate_cbk, subvol->fops->icreate, + loc, mode, xdata); + + if (xdata) + xdata = args.xdata; + else if (args.xdata) + dict_unref (args.xdata); + + errno = args.op_errno; + return args.op_ret; +} + +int +syncop_namelink (xlator_t *subvol, loc_t *loc, dict_t *xdata) +{ + struct syncargs args = {0, }; + + SYNCOP (subvol, (&args), syncop_namelink_cbk, subvol->fops->namelink, + loc, xdata); + + if (xdata) + xdata = args.xdata; + else if (args.xdata) + dict_unref (args.xdata); + + errno = args.op_errno; + return args.op_ret; +} diff --git a/libglusterfs/src/syncop.h b/libglusterfs/src/syncop.h index 8f84cb7c4a4..3b2556535b7 100644 --- a/libglusterfs/src/syncop.h +++ b/libglusterfs/src/syncop.h @@ -569,4 +569,14 @@ syncop_put (xlator_t *subvol, loc_t *loc, mode_t mode, mode_t umask, off_t offset, struct iobref *iobref, dict_t *xattr, struct iatt *iatt, dict_t *xdata_in, dict_t **xdata_out); +int +syncop_setactivelk_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, dict_t *xdata); + +int +syncop_icreate (xlator_t *subvol, loc_t *loc, mode_t mode, dict_t *xdata_out); + +int +syncop_namelink (xlator_t *subvol, loc_t *loc, dict_t *xdata_out); + #endif /* _SYNCOP_H */ diff --git a/libglusterfs/src/xlator.c b/libglusterfs/src/xlator.c index 677dd6ce80f..3e108312d60 100644 --- a/libglusterfs/src/xlator.c +++ b/libglusterfs/src/xlator.c @@ -106,6 +106,8 @@ fill_defaults (xlator_t *xl) SET_DEFAULT_FOP (put); SET_DEFAULT_FOP (getspec); + SET_DEFAULT_FOP (icreate); + SET_DEFAULT_FOP (namelink); if (!xl->cbks) xl->cbks = &default_cbks; diff --git a/libglusterfs/src/xlator.h b/libglusterfs/src/xlator.h index a3115f09c52..81199bd1809 100644 --- a/libglusterfs/src/xlator.h +++ b/libglusterfs/src/xlator.h @@ -471,6 +471,16 @@ typedef int32_t (*fop_put_cbk_t) (call_frame_t *frame, void *cookie, struct iatt *buf, struct iatt *preparent, struct iatt *postparent, dict_t *xdata); +typedef int32_t (*fop_icreate_cbk_t) (call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, inode_t *inode, + struct iatt *buf, dict_t *xdata); + +typedef int32_t (*fop_namelink_cbk_t) (call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata); + typedef int32_t (*fop_lookup_t) (call_frame_t *frame, xlator_t *this, loc_t *loc, @@ -737,6 +747,12 @@ typedef int32_t (*fop_put_t) (call_frame_t *frame, xlator_t *this, loc_t *loc, struct iobref *iobref, dict_t *xattr, dict_t *xdata); +typedef int32_t (*fop_icreate_t) (call_frame_t *frame, xlator_t *this, + loc_t *loc, mode_t mode, dict_t *xdata); + +typedef int32_t (*fop_namelink_t) (call_frame_t *frame, xlator_t *this, + loc_t *loc, dict_t *xdata); + /* WARNING: make sure the list is in order with FOP definition in `rpc/xdr/src/glusterfs-fops.x`. If it is not in order, mainly the metrics related feature would be broken */ @@ -799,6 +815,8 @@ struct xlator_fops { fop_getactivelk_t getactivelk; fop_setactivelk_t setactivelk; fop_put_t put; + fop_icreate_t icreate; + fop_namelink_t namelink; /* these entries are used for a typechecking hack in STACK_WIND _only_ */ /* make sure to add _cbk variables only after defining regular fops as @@ -861,6 +879,8 @@ struct xlator_fops { fop_getactivelk_cbk_t getactivelk_cbk; fop_setactivelk_cbk_t setactivelk_cbk; fop_put_cbk_t put_cbk; + fop_icreate_cbk_t icreate_cbk; + fop_namelink_cbk_t namelink_cbk; }; typedef int32_t (*cbk_forget_t) (xlator_t *this, diff --git a/rpc/rpc-lib/src/protocol-common.h b/rpc/rpc-lib/src/protocol-common.h index ccb3c5002b4..ebfb651c96e 100644 --- a/rpc/rpc-lib/src/protocol-common.h +++ b/rpc/rpc-lib/src/protocol-common.h @@ -65,6 +65,8 @@ enum gf_fop_procnum { GFS3_OP_LEASE, GFS3_OP_GETACTIVELK, GFS3_OP_SETACTIVELK, + GFS3_OP_ICREATE, + GFS3_OP_NAMELINK, GFS3_OP_MAXVALUE, }; diff --git a/rpc/xdr/src/glusterfs-fops.x b/rpc/xdr/src/glusterfs-fops.x index b14a6e6f2e1..5b5c5904678 100644 --- a/rpc/xdr/src/glusterfs-fops.x +++ b/rpc/xdr/src/glusterfs-fops.x @@ -75,6 +75,8 @@ enum glusterfs_fop_t { GF_FOP_GETACTIVELK, GF_FOP_SETACTIVELK, GF_FOP_PUT, + GF_FOP_ICREATE, + GF_FOP_NAMELINK, GF_FOP_MAXVALUE }; diff --git a/rpc/xdr/src/glusterfs4-xdr.x b/rpc/xdr/src/glusterfs4-xdr.x index 6d0c500096b..a4fc9b22850 100644 --- a/rpc/xdr/src/glusterfs4-xdr.x +++ b/rpc/xdr/src/glusterfs4-xdr.x @@ -31,3 +31,30 @@ unsigned int len; opaque xdata<>; /* Extra data */ } ; + +struct gfs4_icreate_rsp { + int op_ret; + int op_errno; + gf_iatt stat; + opaque xdata<>; +}; + +struct gfs4_icreate_req { + opaque gfid[16]; + unsigned int mode; + opaque xdata<>; +}; + +struct gfs4_namelink_rsp { + int op_ret; + int op_errno; + gf_iatt preparent; + gf_iatt postparent; + opaque xdata<>; +}; + +struct gfs4_namelink_req { + opaque pargfid[16]; + string bname<>; + opaque xdata<>; +}; diff --git a/xlators/performance/io-threads/src/io-threads.c b/xlators/performance/io-threads/src/io-threads.c index 7c020e2efc1..7aafc8accf5 100644 --- a/xlators/performance/io-threads/src/io-threads.c +++ b/xlators/performance/io-threads/src/io-threads.c @@ -299,6 +299,8 @@ iot_schedule (call_frame_t *frame, xlator_t *this, call_stub_t *stub) case GF_FOP_READDIRP: case GF_FOP_GETACTIVELK: case GF_FOP_SETACTIVELK: + case GF_FOP_ICREATE: + case GF_FOP_NAMELINK: pri = IOT_PRI_HI; break; diff --git a/xlators/protocol/client/src/client-rpc-fops.c b/xlators/protocol/client/src/client-rpc-fops.c index 9f0a752ccf6..30e0699d446 100644 --- a/xlators/protocol/client/src/client-rpc-fops.c +++ b/xlators/protocol/client/src/client-rpc-fops.c @@ -3150,6 +3150,102 @@ out: return 0; } +int32_t +client3_3_namelink_cbk (struct rpc_req *req, + struct iovec *iov, int count, void *myframe) +{ + int32_t ret = 0; + xlator_t *this = NULL; + struct iatt prebuf = {0,}; + struct iatt postbuf = {0,}; + dict_t *xdata = NULL; + call_frame_t *frame = NULL; + gfs4_namelink_rsp rsp = {0,}; + + this = THIS; + frame = myframe; + + if (req->rpc_status == -1) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + + ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gfs4_namelink_rsp); + if (ret < 0) { + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + + if (rsp.op_ret != -1) { + gf_stat_to_iatt (&rsp.preparent, &prebuf); + gf_stat_to_iatt (&rsp.postparent, &postbuf); + } + + GF_PROTOCOL_DICT_UNSERIALIZE (this, xdata, (rsp.xdata.xdata_val), + (rsp.xdata.xdata_len), ret, + rsp.op_errno, out); + + out: + CLIENT_STACK_UNWIND (namelink, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno), + &prebuf, &postbuf, xdata); + free (rsp.xdata.xdata_val); + if (xdata) + dict_unref (xdata); + return 0; +} + +int32_t +client3_3_icreate_cbk (struct rpc_req *req, + struct iovec *iov, int count, void *myframe) +{ + int32_t ret = 0; + inode_t *inode = NULL; + clnt_local_t *local = NULL; + xlator_t *this = NULL; + struct iatt stbuf = {0,}; + dict_t *xdata = NULL; + call_frame_t *frame = NULL; + gfs4_icreate_rsp rsp = {0,}; + + this = THIS; + frame = myframe; + local = frame->local; + + inode = local->loc.inode; + + if (req->rpc_status == -1) { + rsp.op_ret = -1; + rsp.op_errno = ENOTCONN; + goto out; + } + + ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gfs4_icreate_rsp); + if (ret < 0) { + rsp.op_ret = -1; + rsp.op_errno = EINVAL; + goto out; + } + + if (rsp.op_ret != -1) + gf_stat_to_iatt (&rsp.stat, &stbuf); + + GF_PROTOCOL_DICT_UNSERIALIZE (this, xdata, (rsp.xdata.xdata_val), + (rsp.xdata.xdata_len), ret, + rsp.op_errno, out); + + out: + CLIENT_STACK_UNWIND (icreate, frame, rsp.op_ret, + gf_error_to_errno (rsp.op_errno), + inode, &stbuf, xdata); + free (rsp.xdata.xdata_val); + if (xdata) + dict_unref (xdata); + return 0; +} + int client_fdctx_destroy (xlator_t *this, clnt_fd_ctx_t *fdctx) { @@ -6249,6 +6345,104 @@ unwind: return 0; } +int32_t +client3_3_namelink (call_frame_t *frame, xlator_t *this, void *data) +{ + int32_t ret = 0; + int32_t op_errno = EINVAL; + clnt_conf_t *conf = NULL; + clnt_args_t *args = NULL; + gfs4_namelink_req req = {{0,},}; + + GF_ASSERT (frame); + + args = data; + conf = this->private; + + if (!(args->loc && args->loc->parent)) + goto unwind; + + if (!gf_uuid_is_null (args->loc->parent->gfid)) + memcpy (req.pargfid, args->loc->parent->gfid, sizeof (uuid_t)); + else + memcpy (req.pargfid, args->loc->pargfid, sizeof (uuid_t)); + + GF_ASSERT_AND_GOTO_WITH_ERROR (this->name, + !gf_uuid_is_null (*((uuid_t *)req.pargfid)), + unwind, op_errno, EINVAL); + + req.bname = (char *)args->loc->name; + + GF_PROTOCOL_DICT_SERIALIZE (this, args->xdata, (&req.xdata.xdata_val), + req.xdata.xdata_len, op_errno, unwind); + + ret = client_submit_request (this, &req, frame, conf->fops, + GFS3_OP_NAMELINK, client3_3_namelink_cbk, + NULL, NULL, 0, NULL, 0, NULL, + (xdrproc_t)xdr_gfs4_namelink_req); + if (ret) { + gf_msg (this->name, GF_LOG_WARNING, 0, PC_MSG_FOP_SEND_FAILED, + "failed to send the fop"); + } + + GF_FREE (req.xdata.xdata_val); + return 0; + + unwind: + CLIENT_STACK_UNWIND (namelink, frame, -1, op_errno, NULL, NULL, NULL); + return 0; +} + +int32_t +client3_3_icreate (call_frame_t *frame, xlator_t *this, void *data) +{ + int32_t ret = 0; + int32_t op_errno = EINVAL; + clnt_conf_t *conf = NULL; + clnt_args_t *args = NULL; + clnt_local_t *local = NULL; + gfs4_icreate_req req = {{0,},}; + + GF_ASSERT (frame); + + args = data; + conf = this->private; + + if (!(args->loc && args->loc->inode)) + goto unwind; + + local = mem_get0 (this->local_pool); + if (!local) { + op_errno = ENOMEM; + goto unwind; + } + frame->local = local; + + loc_copy (&local->loc, args->loc); + + req.mode = args->mode; + memcpy (req.gfid, args->loc->gfid, sizeof (uuid_t)); + + op_errno = ESTALE; + GF_PROTOCOL_DICT_SERIALIZE (this, args->xdata, (&req.xdata.xdata_val), + req.xdata.xdata_len, op_errno, unwind); + ret = client_submit_request (this, &req, frame, conf->fops, + GFS3_OP_ICREATE, client3_3_icreate_cbk, + NULL, NULL, 0, NULL, 0, NULL, + (xdrproc_t) xdr_gfs4_icreate_req); + if (ret) + goto free_reqdata; + GF_FREE (req.xdata.xdata_val); + return 0; + + free_reqdata: + GF_FREE (req.xdata.xdata_val); + unwind: + CLIENT_STACK_UNWIND (icreate, frame, + -1, op_errno, NULL, NULL, NULL); + return 0; +} + int32_t client4_0_fsetattr (call_frame_t *frame, xlator_t *this, void *data) { @@ -6456,6 +6650,8 @@ char *clnt3_3_fop_names[GFS3_OP_MAXVALUE] = { [GFS3_OP_GETACTIVELK] = "GETACTIVELK", [GFS3_OP_SETACTIVELK] = "SETACTIVELK", [GFS3_OP_COMPOUND] = "COMPOUND", + [GFS3_OP_ICREATE] = "ICREATE", + [GFS3_OP_NAMELINK] = "NAMELINK", }; rpc_clnt_prog_t clnt3_3_fop_prog = { @@ -6522,6 +6718,8 @@ rpc_clnt_procedure_t clnt4_0_fop_actors[GF_FOP_MAXVALUE] = { [GF_FOP_GETACTIVELK] = { "GETACTIVELK", client3_3_getactivelk}, [GF_FOP_SETACTIVELK] = { "SETACTIVELK", client3_3_setactivelk}, [GF_FOP_COMPOUND] = { "COMPOUND", client3_3_compound }, + [GF_FOP_ICREATE] = { "ICREATE", client3_3_icreate}, + [GF_FOP_NAMELINK] = { "NAMELINK", client3_3_namelink}, }; diff --git a/xlators/protocol/client/src/client.c b/xlators/protocol/client/src/client.c index b8b0ddbbfe9..8df697ed883 100644 --- a/xlators/protocol/client/src/client.c +++ b/xlators/protocol/client/src/client.c @@ -2181,6 +2181,60 @@ out: return 0; } +int32_t +client_namelink (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) +{ + int32_t ret = -1; + clnt_conf_t *conf = NULL; + clnt_args_t args = {0,}; + rpc_clnt_procedure_t *proc = NULL; + + conf = this->private; + if (!conf || !conf->fops || !conf->handshake) + goto out; + + args.loc = loc; + args.xdata = xdata; + + proc = &conf->fops->proctable[GF_FOP_NAMELINK]; + if (proc->fn) + ret = proc->fn (frame, this, &args); + + out: + if (ret) + STACK_UNWIND_STRICT (namelink, frame, + -1, EINVAL, NULL, NULL, NULL); + return 0; +} + +int32_t +client_icreate (call_frame_t *frame, + xlator_t *this, loc_t *loc, mode_t mode, dict_t *xdata) +{ + int32_t ret = -1; + clnt_conf_t *conf = NULL; + clnt_args_t args = {0,}; + rpc_clnt_procedure_t *proc = NULL; + + conf = this->private; + if (!conf || !conf->fops || !conf->handshake) + goto out; + + args.loc = loc; + args.mode = mode; + args.xdata = xdata; + + proc = &conf->fops->proctable[GF_FOP_ICREATE]; + if (proc->fn) + ret = proc->fn (frame, this, &args); + + out: + if (ret) + STACK_UNWIND_STRICT (icreate, frame, + -1, EINVAL, NULL, NULL, NULL); + return 0; +} + int client_mark_fd_bad (xlator_t *this) { @@ -2960,6 +3014,8 @@ struct xlator_fops fops = { .compound = client_compound, .getactivelk = client_getactivelk, .setactivelk = client_setactivelk, + .icreate = client_icreate, + .namelink = client_namelink, }; diff --git a/xlators/protocol/server/src/server-rpc-fops.c b/xlators/protocol/server/src/server-rpc-fops.c index 1adb262af7f..1b87abaafda 100644 --- a/xlators/protocol/server/src/server-rpc-fops.c +++ b/xlators/protocol/server/src/server-rpc-fops.c @@ -2207,6 +2207,97 @@ out: return 0; } +int +server_namelink_cbk (call_frame_t *frame, + void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, + struct iatt *prebuf, struct iatt *postbuf, dict_t *xdata) +{ + gfs4_namelink_rsp rsp = {0,}; + rpcsvc_request_t *req = NULL; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + if (op_ret < 0) + goto out; + + gf_stat_from_iatt (&rsp.preparent, prebuf); + gf_stat_from_iatt (&rsp.postparent, postbuf); + + /** + * no point in linking inode here -- there's no stbuf anyway and a + * lookup() for this name entry would be a negative lookup. + */ + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gfs4_namelink_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + +int +server_icreate_cbk (call_frame_t *frame, + void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, + inode_t *inode, struct iatt *stbuf, dict_t *xdata) +{ + server_state_t *state = NULL; + inode_t *link_inode = NULL; + rpcsvc_request_t *req = NULL; + gfs3_create_rsp rsp = {0,}; + + GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val, + rsp.xdata.xdata_len, op_errno, out); + + state = CALL_STATE (frame); + + if (op_ret < 0) { + gf_msg (this->name, GF_LOG_INFO, op_errno, PS_MSG_CREATE_INFO, + "%"PRId64": ICREATE [%s] ==> (%s)", + frame->root->unique, uuid_utoa (state->resolve.gfid), + strerror (op_errno)); + goto out; + } + + gf_msg_trace (frame->root->client->bound_xl->name, 0, "%"PRId64": " + "ICREATE [%s]", frame->root->unique, + uuid_utoa (stbuf->ia_gfid)); + + link_inode = inode_link (inode, + state->loc.parent, state->loc.name, stbuf); + + if (!link_inode) { + op_ret = -1; + op_errno = ENOENT; + goto out; + } + + inode_lookup (link_inode); + inode_unref (link_inode); + + gf_stat_from_iatt (&rsp.stat, stbuf); + +out: + rsp.op_ret = op_ret; + rsp.op_errno = gf_errno_to_error (op_errno); + + req = frame->local; + server_submit_reply (frame, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gfs4_icreate_rsp); + + GF_FREE (rsp.xdata.xdata_val); + + return 0; +} + /* Resume function section */ int @@ -3452,6 +3543,53 @@ err: return ret; } +int +server_namelink_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + state->loc.inode = inode_new (state->itable); + + STACK_WIND (frame, server_namelink_cbk, + bound_xl, bound_xl->fops->namelink, + &(state->loc), state->xdata); + return 0; + + err: + server_namelink_cbk (frame, NULL, + frame->this, + state->resolve.op_ret, + state->resolve.op_errno, NULL, NULL, NULL); + return 0; +} + +int +server_icreate_resume (call_frame_t *frame, xlator_t *bound_xl) +{ + server_state_t *state = NULL; + + state = CALL_STATE (frame); + + if (state->resolve.op_ret != 0) + goto err; + + state->loc.inode = inode_new (state->itable); + + STACK_WIND (frame, server_icreate_cbk, + bound_xl, bound_xl->fops->icreate, + &(state->loc), state->mode, state->xdata); + + return 0; +err: + server_icreate_cbk (frame, NULL, frame->this, state->resolve.op_ret, + state->resolve.op_errno, NULL, NULL, NULL); + return 0; +} /* Fop section */ static inline int @@ -6090,6 +6228,100 @@ out: return ret; } +int +server3_3_namelink (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs4_namelink_req args = {{0,},}; + int ret = -1; + int op_errno = 0; + + if (!req) + return ret; + + ret = rpc_receive_common (req, &frame, &state, NULL, &args, + xdr_gfs4_namelink_req, GF_FOP_NAMELINK); + + if (ret != 0) + goto out; + + state->resolve.bname = gf_strdup (args.bname); + memcpy (state->resolve.pargfid, args.pargfid, sizeof (uuid_t)); + + state->resolve.type = RESOLVE_NOT; + + /* TODO: can do alloca for xdata field instead of stdalloc */ + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_namelink_resume); + +out: + /* memory allocated by libc, don't use GF_FREE */ + free (args.xdata.xdata_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + return ret; + +} + +int +server3_3_icreate (rpcsvc_request_t *req) +{ + server_state_t *state = NULL; + call_frame_t *frame = NULL; + gfs4_icreate_req args = {{0,},}; + int ret = -1; + int op_errno = 0; + uuid_t gfid = {0,}; + + if (!req) + return ret; + + ret = rpc_receive_common (req, &frame, &state, NULL, &args, + xdr_gfs4_icreate_req, GF_FOP_ICREATE); + + if (ret != 0) + goto out; + + memcpy (gfid, args.gfid, sizeof (uuid_t)); + + state->mode = args.mode; + gf_asprintf (&state->resolve.bname, INODE_PATH_FMT, uuid_utoa (gfid)); + + /* parent is an auxillary inode number */ + memset (state->resolve.pargfid, 0, sizeof (uuid_t)); + state->resolve.pargfid[15] = GF_AUXILLARY_PARGFID; + + state->resolve.type = RESOLVE_NOT; + + /* TODO: can do alloca for xdata field instead of stdalloc */ + GF_PROTOCOL_DICT_UNSERIALIZE (frame->root->client->bound_xl, + state->xdata, + args.xdata.xdata_val, + args.xdata.xdata_len, ret, + op_errno, out); + + ret = 0; + resolve_and_resume (frame, server_icreate_resume); + +out: + /* memory allocated by libc, don't use GF_FREE */ + free (args.xdata.xdata_val); + + if (op_errno) + SERVER_REQ_SET_ERROR (req, ret); + + return ret; +} + int server4_0_fsetattr (rpcsvc_request_t *req) { @@ -6297,6 +6529,8 @@ rpcsvc_actor_t glusterfs4_0_fop_actors[] = { [GFS3_OP_GETACTIVELK] = {"GETACTIVELK", GFS3_OP_GETACTIVELK, server3_3_getactivelk, NULL, 0, DRC_NA}, [GFS3_OP_SETACTIVELK] = {"SETACTIVELK", GFS3_OP_SETACTIVELK, server3_3_setactivelk, NULL, 0, DRC_NA}, [GFS3_OP_COMPOUND] = {"COMPOUND", GFS3_OP_COMPOUND, server3_3_compound, NULL, 0, DRC_NA}, + [GFS3_OP_ICREATE] = {"ICREATE", GFS3_OP_ICREATE, server3_3_icreate, NULL, 0, DRC_NA}, + [GFS3_OP_NAMELINK] = {"NAMELINK", GFS3_OP_NAMELINK, server3_3_namelink, NULL, 0, DRC_NA}, }; -- cgit