Whamcloud - gitweb
LU-17015 gss: support large kerberos token for rpc sec ctxt 05/52305/23
authorSebastien Buisson <sbuisson@ddn.com>
Thu, 7 Sep 2023 07:33:36 +0000 (09:33 +0200)
committerOleg Drokin <green@whamcloud.com>
Sat, 18 Nov 2023 21:43:56 +0000 (21:43 +0000)
If the current Kerberos setup is using large token, like when PAC
feature is enabled for Kerberos, authentication can fail due to server
side unable to exchange token between kernel and userspace.
This limitation is inherent to the sunrpc cache mechanism, that can
only handle tokens up to PAGE_SIZE.

For RPC sec context phase, use Lustre's upcall cache mechanism
instead of deprecated kernel's sunrpc cache. Note this phase does not
involve a proper upcall, only the downcall part is relevant to
populate the context computed in userspace.

Test-Parameters: kerberos=true testlist=sanity-krb5
Signed-off-by: Sebastien Buisson <sbuisson@ddn.com>
Change-Id: I94e945a99cab60d5b6a4c40076c40fffede217ab
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/52305
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Aurelien Degremont <adegremont@nvidia.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
12 files changed:
lustre/include/uapi/linux/lustre/lgss.h
lustre/include/upcall_cache.h
lustre/ptlrpc/gss/gss_internal.h
lustre/ptlrpc/gss/gss_svc_upcall.c
lustre/ptlrpc/gss/lproc_gss.c
lustre/ptlrpc/wiretest.c
lustre/tests/recovery-small.sh
lustre/tests/sanity-sec.sh
lustre/tests/sanity.sh
lustre/utils/gss/svcgssd_proc.c
lustre/utils/wirecheck.c
lustre/utils/wiretest.c

index 8386fec..154d678 100644 (file)
@@ -90,6 +90,33 @@ struct rsi_downcall_data {
        char      sid_val[0];
 };
 
+#define RSC_DOWNCALL_MAGIC     0x6d6dd62b
+#define RSC_DOWNCALL_PATH      "sptlrpc/gss/rsc_info"
+#define RSC_CACHE_NAME         "rsccache"
+
+/* rsc_downcall_data flags */
+enum scd_flag_bits {
+       RSC_DATA_FLAG_REMOTE    = 0x0001,
+       RSC_DATA_FLAG_ROOT      = 0x0002,
+       RSC_DATA_FLAG_MDS       = 0x0004,
+       RSC_DATA_FLAG_OSS       = 0x0008,
+};
+
+struct rsc_downcall_data {
+       __u32           scd_magic;
+       __u32           scd_err;
+       __u32           scd_flags;
+       __u32           scd_mapped_uid;
+       __u32           scd_uid;
+       __u32           scd_gid;
+       char            scd_mechname[8];
+       __s64           scd_offset;
+       __u32           scd_len;
+       __u32           scd_padding;
+       /* scd_val contains handle and context token */
+       char            scd_val[0];
+};
+
 /*
  * gss_string_write() - write some string
  *
index f333c0f..3530eda 100644 (file)
@@ -93,6 +93,13 @@ struct gss_rsi {
        int                        si_minor_status;
 };
 
+struct gss_rsc {
+       struct upcall_cache_entry *sc_uc_entry;
+       struct obd_device         *sc_target;
+       rawobj_t                   sc_handle;
+       struct gss_svc_ctx         sc_ctx;
+};
+
 struct upcall_cache_entry {
        struct list_head        ue_hash;
        uint64_t                ue_key;
@@ -104,6 +111,7 @@ struct upcall_cache_entry {
        union {
                struct md_identity      identity;
                struct gss_rsi          rsi;
+               struct gss_rsc          rsc;
        } u;
 };
 
index abc511d..f1904e9 100644 (file)
@@ -445,11 +445,18 @@ static inline unsigned int ll_read_key_usage(struct key *key)
 
 #define RSI_UPCALL_PATH "/usr/sbin/l_getauth"
 #define UC_RSICACHE_HASH_SIZE 64
-
 extern struct upcall_cache_ops rsi_upcall_cache_ops;
 extern struct upcall_cache *rsicache;
 struct gss_rsi *rsi_entry_get(struct upcall_cache *cache, struct gss_rsi *rsi);
 void rsi_entry_put(struct upcall_cache *cache, struct gss_rsi *rsi);
 void rsi_flush(struct upcall_cache *cache, int hash);
+#define RSC_UPCALL_PATH "NONE"
+#define UC_RSCCACHE_HASH_SIZE 1024
+extern struct upcall_cache_ops rsc_upcall_cache_ops;
+extern struct upcall_cache *rsccache;
+struct gss_rsc *rsc_entry_get(struct upcall_cache *cache, struct gss_rsc *rsc);
+void rsc_entry_put(struct upcall_cache *cache, struct gss_rsc *rsc);
+void rsc_flush(struct upcall_cache *cache, int hash);
+void __rsc_free(struct gss_rsc *rsc);
 
 #endif /* __PTLRPC_GSS_GSS_INTERNAL_H_ */
index d7f2c8c..9adcfdc 100644 (file)
@@ -785,13 +785,213 @@ static struct rsi *rsi_update(struct rsi *new, struct rsi *old)
 }
 
 /****************************************
- * rpc sec context (rsc) cache                            *
+ * rpc sec context (rsc) cache         *
  ****************************************/
 
 #define RSC_HASHBITS    (10)
 #define RSC_HASHMAX     (1 << RSC_HASHBITS)
 #define RSC_HASHMASK    (RSC_HASHMAX - 1)
 
+static void rsc_entry_init(struct upcall_cache_entry *entry,
+                          void *args)
+{
+       struct gss_rsc *rsc = &entry->u.rsc;
+       struct gss_rsc *tmp = args;
+
+       rsc->sc_uc_entry = entry;
+       rawobj_dup(&rsc->sc_handle, &tmp->sc_handle);
+
+       rsc->sc_target = NULL;
+       memset(&rsc->sc_ctx, 0, sizeof(rsc->sc_ctx));
+       rsc->sc_ctx.gsc_rvs_hdl = RAWOBJ_EMPTY;
+
+       memset(&rsc->sc_ctx.gsc_seqdata, 0, sizeof(rsc->sc_ctx.gsc_seqdata));
+       spin_lock_init(&rsc->sc_ctx.gsc_seqdata.ssd_lock);
+}
+
+void __rsc_free(struct gss_rsc *rsc)
+{
+       rawobj_free(&rsc->sc_handle);
+       rawobj_free(&rsc->sc_ctx.gsc_rvs_hdl);
+       lgss_delete_sec_context(&rsc->sc_ctx.gsc_mechctx);
+}
+
+static void rsc_entry_free(struct upcall_cache *cache,
+                          struct upcall_cache_entry *entry)
+{
+       struct gss_rsc *rsc = &entry->u.rsc;
+
+       __rsc_free(rsc);
+}
+
+static inline int rsc_entry_hash(struct gss_rsc *rsc)
+{
+#if BITS_PER_LONG == 64
+       return hash_mem_64((char *)rsc->sc_handle.data,
+                          rsc->sc_handle.len, RSC_HASHBITS);
+#else
+       return hash_mem((char *)rsc->sc_handle.data,
+                       rsc->sc_handle.len, RSC_HASHBITS);
+#endif
+}
+
+static inline int __rsc_entry_match(rawobj_t *h1, rawobj_t *h2)
+{
+       return !(rawobj_equal(h1, h2));
+}
+
+static inline int rsc_entry_match(struct gss_rsc *rsc, struct gss_rsc *tmp)
+{
+       return __rsc_entry_match(&rsc->sc_handle, &tmp->sc_handle);
+}
+
+/* Returns 0 to tell this is a match */
+static inline int rsc_upcall_compare(struct upcall_cache *cache,
+                                    struct upcall_cache_entry *entry,
+                                    __u64 key, void *args)
+{
+       struct gss_rsc *rsc1 = &entry->u.rsc;
+       struct gss_rsc *rsc2 = args;
+
+       return rsc_entry_match(rsc1, rsc2);
+}
+
+/* rsc upcall is a no-op, we just need a valid entry */
+static inline int rsc_do_upcall(struct upcall_cache *cache,
+                               struct upcall_cache_entry *entry)
+{
+       upcall_cache_update_entry(cache, entry,
+                                 ktime_get_seconds() + cache->uc_entry_expire,
+                                 0);
+       return 0;
+}
+
+static inline int rsc_downcall_compare(struct upcall_cache *cache,
+                                      struct upcall_cache_entry *entry,
+                                      __u64 key, void *args)
+{
+       struct gss_rsc *rsc = &entry->u.rsc;
+       struct rsc_downcall_data *scd = args;
+       char *mesg = scd->scd_val;
+       rawobj_t handle;
+       int len;
+
+       /* scd_val starts with handle */
+       len = gss_buffer_get(&mesg, &handle.len, &handle.data);
+       scd->scd_offset = mesg - scd->scd_val;
+
+       return __rsc_entry_match(&rsc->sc_handle, &handle);
+}
+
+static int rsc_parse_downcall(struct upcall_cache *cache,
+                             struct upcall_cache_entry *entry,
+                             void *args)
+{
+       struct gss_api_mech *gm = NULL;
+       struct gss_rsc *rsc = &entry->u.rsc;
+       struct rsc_downcall_data *scd = args;
+       int mlen = scd->scd_len;
+       char *mesg = scd->scd_val + scd->scd_offset;
+       char *buf = scd->scd_val;
+       int status = -EINVAL;
+       time64_t ctx_expiry;
+       rawobj_t tmp_buf;
+       int len;
+
+       ENTRY;
+
+       if (mlen <= 0)
+               goto out;
+
+       rsc->sc_ctx.gsc_remote = !!(scd->scd_flags & RSC_DATA_FLAG_REMOTE);
+       rsc->sc_ctx.gsc_usr_root = !!(scd->scd_flags & RSC_DATA_FLAG_ROOT);
+       rsc->sc_ctx.gsc_usr_mds = !!(scd->scd_flags & RSC_DATA_FLAG_MDS);
+       rsc->sc_ctx.gsc_usr_oss = !!(scd->scd_flags & RSC_DATA_FLAG_OSS);
+       rsc->sc_ctx.gsc_mapped_uid = scd->scd_mapped_uid;
+       rsc->sc_ctx.gsc_uid = scd->scd_uid;
+
+       rsc->sc_ctx.gsc_gid = scd->scd_gid;
+       gm = lgss_name_to_mech(scd->scd_mechname);
+       if (!gm) {
+               status = -EOPNOTSUPP;
+               goto out;
+       }
+
+       /* handle has already been consumed in rsc_downcall_compare().
+        * scd_offset gives next field.
+        */
+
+       /* context token */
+       len = gss_buffer_read(&mesg, buf, mlen);
+       if (len < 0)
+               goto out;
+       tmp_buf.len = len;
+       tmp_buf.data = (unsigned char *)buf;
+       if (lgss_import_sec_context(&tmp_buf, gm,
+                                   &rsc->sc_ctx.gsc_mechctx))
+               goto out;
+
+       if (lgss_inquire_context(rsc->sc_ctx.gsc_mechctx, &ctx_expiry))
+               goto out;
+
+       /* ctx_expiry is the number of seconds since Jan 1 1970.
+        * We just want the number of seconds into the future.
+        */
+       entry->ue_expire = ktime_get_seconds() +
+               (ctx_expiry - ktime_get_real_seconds());
+       status = 0;
+
+out:
+       if (gm)
+               lgss_mech_put(gm);
+       CDEBUG(D_OTHER, "rsc parse %p: %d\n", rsc, status);
+       RETURN(status);
+}
+
+struct gss_rsc *rsc_entry_get(struct upcall_cache *cache, struct gss_rsc *rsc)
+{
+       struct upcall_cache_entry *entry;
+       int hash = rsc_entry_hash(rsc);
+
+       if (!cache)
+               return ERR_PTR(-ENOENT);
+
+       entry = upcall_cache_get_entry(cache, (__u64)hash, rsc);
+       if (unlikely(!entry))
+               return ERR_PTR(-ENOENT);
+       if (IS_ERR(entry))
+               return ERR_CAST(entry);
+
+       return &entry->u.rsc;
+}
+
+void rsc_entry_put(struct upcall_cache *cache, struct gss_rsc *rsc)
+{
+       if (!cache || !rsc)
+               return;
+
+       upcall_cache_put_entry(cache, rsc->sc_uc_entry);
+}
+
+void rsc_flush(struct upcall_cache *cache, int hash)
+{
+       if (hash < 0)
+               upcall_cache_flush_idle(cache);
+       else
+               upcall_cache_flush_one(cache, (__u64)hash, NULL);
+}
+
+struct upcall_cache_ops rsc_upcall_cache_ops = {
+       .init_entry       = rsc_entry_init,
+       .free_entry       = rsc_entry_free,
+       .upcall_compare   = rsc_upcall_compare,
+       .downcall_compare = rsc_downcall_compare,
+       .do_upcall        = rsc_do_upcall,
+       .parse_downcall   = rsc_parse_downcall,
+};
+
+struct upcall_cache *rsccache;
+
 struct rsc {
         struct cache_head       h;
         struct obd_device      *target;
@@ -1105,132 +1305,138 @@ static struct rsc *rsc_update(struct rsc *new, struct rsc *old)
  * rsc cache flush                      *
  ****************************************/
 
-static struct rsc *gss_svc_searchbyctx(rawobj_t *handle)
+static struct gss_rsc *gss_svc_searchbyctx(rawobj_t *handle)
 {
-        struct rsc  rsci;
-        struct rsc *found;
+       struct gss_rsc rsc;
+       struct gss_rsc *found;
 
-        memset(&rsci, 0, sizeof(rsci));
-        if (rawobj_dup(&rsci.handle, handle))
-                return NULL;
+       memset(&rsc, 0, sizeof(rsc));
+       if (rawobj_dup(&rsc.sc_handle, handle))
+               return NULL;
 
-        found = rsc_lookup(&rsci);
-        rsc_free(&rsci);
-        if (!found)
-                return NULL;
-        if (cache_check(&rsc_cache, &found->h, NULL))
-                return NULL;
-        return found;
+       found = rsc_entry_get(rsccache, &rsc);
+       __rsc_free(&rsc);
+       if (IS_ERR_OR_NULL(found))
+               return found;
+       if (!found->sc_ctx.gsc_mechctx) {
+               rsc_entry_put(rsccache, found);
+               return ERR_PTR(-ENOENT);
+       }
+       return found;
 }
 
 int gss_svc_upcall_install_rvs_ctx(struct obd_import *imp,
-                                   struct gss_sec *gsec,
-                                   struct gss_cli_ctx *gctx)
+                                  struct gss_sec *gsec,
+                                  struct gss_cli_ctx *gctx)
 {
-        struct rsc      rsci, *rscp = NULL;
+       struct gss_rsc rsc, *rscp = NULL;
        time64_t ctx_expiry;
-        __u32           major;
-        int             rc;
-        ENTRY;
+       __u32 major;
+       int rc;
 
-        memset(&rsci, 0, sizeof(rsci));
+       ENTRY;
+       memset(&rsc, 0, sizeof(rsc));
 
-        if (rawobj_alloc(&rsci.handle, (char *) &gsec->gs_rvs_hdl,
-                         sizeof(gsec->gs_rvs_hdl)))
-                GOTO(out, rc = -ENOMEM);
+       if (!imp || !imp->imp_obd) {
+               CERROR("invalid imp, drop\n");
+               RETURN(-EPROTO);
+       }
 
-        rscp = rsc_lookup(&rsci);
-        if (rscp == NULL)
-                GOTO(out, rc = -ENOMEM);
+       if (rawobj_alloc(&rsc.sc_handle, (char *)&gsec->gs_rvs_hdl,
+                        sizeof(gsec->gs_rvs_hdl)))
+               GOTO(out, rc = -ENOMEM);
 
-        major = lgss_copy_reverse_context(gctx->gc_mechctx,
-                                          &rsci.ctx.gsc_mechctx);
-        if (major != GSS_S_COMPLETE)
-                GOTO(out, rc = -ENOMEM);
+       rscp = rsc_entry_get(rsccache, &rsc);
+       __rsc_free(&rsc);
+       if (IS_ERR_OR_NULL(rscp))
+               GOTO(out, rc = -ENOMEM);
 
-        if (lgss_inquire_context(rsci.ctx.gsc_mechctx, &ctx_expiry)) {
-                CERROR("unable to get expire time, drop it\n");
-                GOTO(out, rc = -EINVAL);
-        }
-       rsci.h.expiry_time = ctx_expiry;
+       major = lgss_copy_reverse_context(gctx->gc_mechctx,
+                                         &rscp->sc_ctx.gsc_mechctx);
+       if (major != GSS_S_COMPLETE)
+               GOTO(out, rc = -ENOMEM);
+
+       if (lgss_inquire_context(rscp->sc_ctx.gsc_mechctx, &ctx_expiry)) {
+               CERROR("%s: unable to get expire time, drop\n",
+                      imp->imp_obd->obd_name);
+               GOTO(out, rc = -EINVAL);
+       }
+       rscp->sc_uc_entry->ue_expire = ktime_get_seconds() +
+               (ctx_expiry - ktime_get_real_seconds());
 
        switch (imp->imp_obd->u.cli.cl_sp_to) {
        case LUSTRE_SP_MDT:
-               rsci.ctx.gsc_usr_mds = 1;
+               rscp->sc_ctx.gsc_usr_mds = 1;
                break;
        case LUSTRE_SP_OST:
-               rsci.ctx.gsc_usr_oss = 1;
+               rscp->sc_ctx.gsc_usr_oss = 1;
                break;
        case LUSTRE_SP_CLI:
-               rsci.ctx.gsc_usr_root = 1;
+               rscp->sc_ctx.gsc_usr_root = 1;
                break;
        case LUSTRE_SP_MGS:
                /* by convention, all 3 set to 1 means MGS */
-               rsci.ctx.gsc_usr_mds = 1;
-               rsci.ctx.gsc_usr_oss = 1;
-               rsci.ctx.gsc_usr_root = 1;
+               rscp->sc_ctx.gsc_usr_mds = 1;
+               rscp->sc_ctx.gsc_usr_oss = 1;
+               rscp->sc_ctx.gsc_usr_root = 1;
                break;
        default:
                break;
        }
 
-        rscp = rsc_update(&rsci, rscp);
-        if (rscp == NULL)
-                GOTO(out, rc = -ENOMEM);
+       rscp->sc_target = imp->imp_obd;
+       rawobj_dup(&gctx->gc_svc_handle, &rscp->sc_handle);
 
-        rscp->target = imp->imp_obd;
-        rawobj_dup(&gctx->gc_svc_handle, &rscp->handle);
-
-       CDEBUG(D_SEC, "create reverse svc ctx %p to %s: idx %#llx\n",
-              &rscp->ctx, obd2cli_tgt(imp->imp_obd), gsec->gs_rvs_hdl);
+       CDEBUG(D_SEC, "%s: create reverse svc ctx %p to %s: idx %#llx\n",
+              imp->imp_obd->obd_name, &rscp->sc_ctx, obd2cli_tgt(imp->imp_obd),
+              gsec->gs_rvs_hdl);
        rc = 0;
 out:
-        if (rscp)
-                cache_put(&rscp->h, &rsc_cache);
-        rsc_free(&rsci);
-
-        if (rc)
-               CERROR("create reverse svc ctx: idx %#llx, rc %d\n",
-                       gsec->gs_rvs_hdl, rc);
-        RETURN(rc);
+       if (!IS_ERR_OR_NULL(rscp))
+               rsc_entry_put(rsccache, rscp);
+       if (rc)
+               CERROR("%s: can't create reverse svc ctx idx %#llx: rc = %d\n",
+                      imp->imp_obd->obd_name, gsec->gs_rvs_hdl, rc);
+       RETURN(rc);
 }
 
 int gss_svc_upcall_expire_rvs_ctx(rawobj_t *handle)
 {
        const time64_t expire = 20;
-       struct rsc *rscp;
+       struct gss_rsc *rscp;
 
-        rscp = gss_svc_searchbyctx(handle);
-        if (rscp) {
-                CDEBUG(D_SEC, "reverse svcctx %p (rsc %p) expire soon\n",
-                       &rscp->ctx, rscp);
+       rscp = gss_svc_searchbyctx(handle);
+       if (!IS_ERR_OR_NULL(rscp)) {
+               CDEBUG(D_SEC,
+                      "reverse svcctx %p (rsc %p) expire in %lld seconds\n",
+                      &rscp->sc_ctx, rscp, expire);
 
-               rscp->h.expiry_time = ktime_get_real_seconds() + expire;
-                COMPAT_RSC_PUT(&rscp->h, &rsc_cache);
-        }
-        return 0;
+               rscp->sc_uc_entry->ue_expire = ktime_get_seconds() + expire;
+               rsc_entry_put(rsccache, rscp);
+       }
+       return 0;
 }
 
 int gss_svc_upcall_dup_handle(rawobj_t *handle, struct gss_svc_ctx *ctx)
 {
-        struct rsc *rscp = container_of(ctx, struct rsc, ctx);
+       struct gss_rsc *rscp = container_of(ctx, struct gss_rsc, sc_ctx);
 
-        return rawobj_dup(handle, &rscp->handle);
+       return rawobj_dup(handle, &rscp->sc_handle);
 }
 
 int gss_svc_upcall_update_sequence(rawobj_t *handle, __u32 seq)
 {
-        struct rsc             *rscp;
+       struct gss_rsc *rscp;
 
-        rscp = gss_svc_searchbyctx(handle);
-        if (rscp) {
-                CDEBUG(D_SEC, "reverse svcctx %p (rsc %p) update seq to %u\n",
-                       &rscp->ctx, rscp, seq + 1);
+       rscp = gss_svc_searchbyctx(handle);
+       if (!IS_ERR_OR_NULL(rscp)) {
+               CDEBUG(D_SEC, "reverse svcctx %p (rsc %p) update seq to %u\n",
+                      &rscp->sc_ctx, rscp, seq + 1);
 
-                rscp->ctx.gsc_rvs_seq = seq + 1;
-                COMPAT_RSC_PUT(&rscp->h, &rsc_cache);
-        }
-        return 0;
+               rscp->sc_ctx.gsc_rvs_seq = seq + 1;
+               rsc_entry_put(rsccache, rscp);
+       }
+       return 0;
 }
 
 int gss_svc_upcall_handle_init(struct ptlrpc_request *req,
@@ -1243,10 +1449,10 @@ int gss_svc_upcall_handle_init(struct ptlrpc_request *req,
 {
        struct gss_rsi rsi = { 0 }, *rsip = NULL;
        struct ptlrpc_reply_state *rs;
-       struct rsc *rsci = NULL;
+       struct gss_rsc *rscp = NULL;
        int replen = sizeof(struct ptlrpc_body);
        struct gss_rep_header *rephdr;
-       int rc = SECSVC_DROP, rc2;
+       int rc, rc2;
 
        ENTRY;
 
@@ -1265,7 +1471,7 @@ int gss_svc_upcall_handle_init(struct ptlrpc_request *req,
        if (rc2) {
                CERROR("%s: failed to duplicate context handle: rc = %d\n",
                       target->obd_name, rc2);
-               GOTO(out, rc);
+               GOTO(out, rc = SECSVC_DROP);
        }
 
        rc2 = rawobj_dup(&rsi.si_in_token, in_token);
@@ -1273,38 +1479,49 @@ int gss_svc_upcall_handle_init(struct ptlrpc_request *req,
                CERROR("%s: failed to duplicate token: rc = %d\n",
                       target->obd_name, rc2);
                rawobj_free(&rsi.si_in_handle);
-               GOTO(out, rc);
+               GOTO(out, rc = SECSVC_DROP);
        }
 
        rsip = rsi_entry_get(rsicache, &rsi);
        __rsi_free(&rsi);
-       if (IS_ERR(rsip)) {
-               CERROR("%s: failed to get entry from rsi cache (nid %s): rc = %ld\n",
+       if (IS_ERR_OR_NULL(rsip)) {
+               if (IS_ERR(rsip))
+                       rc2 = PTR_ERR(rsip);
+               else
+                       rc2 = -EINVAL;
+               CERROR("%s: failed to get entry from rsi cache (nid %s): rc = %d\n",
                       target->obd_name,
                       libcfs_nid2str(lnet_nid_to_nid4(&req->rq_source.nid)),
-                      PTR_ERR(rsip));
+                      rc2);
 
                if (!gss_pack_err_notify(req, GSS_S_FAILURE, 0))
                        rc = SECSVC_COMPLETE;
+               else
+                       rc = SECSVC_DROP;
 
                GOTO(out, rc);
        }
 
-       rc = SECSVC_DROP;
-       rsci = gss_svc_searchbyctx(&rsip->si_out_handle);
-       if (!rsci) {
+       rscp = gss_svc_searchbyctx(&rsip->si_out_handle);
+       if (IS_ERR_OR_NULL(rscp)) {
                /* gss mechanism returned major and minor code so we return
                 * those in error message */
+
                if (!gss_pack_err_notify(req, rsip->si_major_status,
                                         rsip->si_minor_status))
                        rc = SECSVC_COMPLETE;
+               else
+                       rc = SECSVC_DROP;
 
                CERROR("%s: authentication failed: rc = %d\n",
                       target->obd_name, rc);
                GOTO(out, rc);
        } else {
-               cache_get(&rsci->h);
-               grctx->src_ctx = &rsci->ctx;
+               /* we need to take an extra ref on the cache entry,
+                * as a pointer to sc_ctx is stored in grctx
+                */
+               upcall_cache_get_entry_raw(rscp->sc_uc_entry);
+               grctx->src_ctx = &rscp->sc_ctx;
        }
 
        if (gw->gw_flags & LUSTRE_GSS_PACK_KCSUM) {
@@ -1321,16 +1538,16 @@ int gss_svc_upcall_handle_init(struct ptlrpc_request *req,
                        gss_digest_hash_compat;
        }
 
-       if (rawobj_dup(&rsci->ctx.gsc_rvs_hdl, rvs_hdl)) {
+       if (rawobj_dup(&rscp->sc_ctx.gsc_rvs_hdl, rvs_hdl)) {
                CERROR("%s: failed duplicate reverse handle\n",
                       target->obd_name);
-               GOTO(out, rc);
+               GOTO(out, rc = SECSVC_DROP);
        }
 
-       rsci->target = target;
+       rscp->sc_target = target;
 
        CDEBUG(D_SEC, "%s: server create rsc %p(%u->%s)\n",
-              target->obd_name, rsci, rsci->ctx.gsc_uid,
+              target->obd_name, rscp, rscp->sc_ctx.gsc_uid,
               libcfs_nidstr(&req->rq_peer.nid));
 
        if (rsip->si_out_handle.len > PTLRPC_GSS_MAX_HANDLE_SIZE) {
@@ -1377,16 +1594,16 @@ int gss_svc_upcall_handle_init(struct ptlrpc_request *req,
 out:
        if (!IS_ERR_OR_NULL(rsip))
                rsi_entry_put(rsicache, rsip);
-       if (rsci) {
+       if (!IS_ERR_OR_NULL(rscp)) {
                /* if anything went wrong, we don't keep the context too */
                if (rc != SECSVC_OK)
-                       set_bit(CACHE_NEGATIVE, &rsci->h.flags);
+                       UC_CACHE_SET_INVALID(rscp->sc_uc_entry);
                else
                        CDEBUG(D_SEC, "%s: create rsc with idx %#llx\n",
                               target->obd_name,
-                              gss_handle_to_u64(&rsci->handle));
+                              gss_handle_to_u64(&rscp->sc_handle));
 
-               COMPAT_RSC_PUT(&rsci->h, &rsc_cache);
+               rsc_entry_put(rsccache, rscp);
        }
        RETURN(rc);
 }
@@ -1394,34 +1611,32 @@ out:
 struct gss_svc_ctx *gss_svc_upcall_get_ctx(struct ptlrpc_request *req,
                                           struct gss_wire_ctx *gw)
 {
-       struct rsc *rsc;
+       struct gss_rsc *rscp;
 
-       rsc = gss_svc_searchbyctx(&gw->gw_handle);
-       if (!rsc) {
+       rscp = gss_svc_searchbyctx(&gw->gw_handle);
+       if (IS_ERR_OR_NULL(rscp)) {
                CWARN("Invalid gss ctx idx %#llx from %s\n",
                      gss_handle_to_u64(&gw->gw_handle),
                      libcfs_nidstr(&req->rq_peer.nid));
                return NULL;
        }
 
-       return &rsc->ctx;
+       return &rscp->sc_ctx;
 }
 
 void gss_svc_upcall_put_ctx(struct gss_svc_ctx *ctx)
 {
-        struct rsc *rsc = container_of(ctx, struct rsc, ctx);
+       struct gss_rsc *rscp = container_of(ctx, struct gss_rsc, sc_ctx);
 
-        COMPAT_RSC_PUT(&rsc->h, &rsc_cache);
+       rsc_entry_put(rsccache, rscp);
 }
 
 void gss_svc_upcall_destroy_ctx(struct gss_svc_ctx *ctx)
 {
-        struct rsc *rsc = container_of(ctx, struct rsc, ctx);
+       struct gss_rsc *rscp = container_of(ctx, struct gss_rsc, sc_ctx);
 
-        /* can't be found */
-       set_bit(CACHE_NEGATIVE, &rsc->h.flags);
-        /* to be removed at next scan */
-        rsc->h.expiry_time = 1;
+       UC_CACHE_SET_INVALID(rscp->sc_uc_entry);
+       rscp->sc_uc_entry->ue_expire = 1;
 }
 
 /* Wait for userspace daemon to open socket, approx 1.5 s.
@@ -1512,6 +1727,18 @@ int __init gss_init_svc_upcall(void)
                rsicache = NULL;
                return rc;
        }
+       rsccache = upcall_cache_init(RSC_CACHE_NAME, RSC_UPCALL_PATH,
+                                    UC_RSCCACHE_HASH_SIZE,
+                                    3600, /* replaced with one from mech */
+                                    100, /* arbitrary, not used */
+                                    &rsc_upcall_cache_ops);
+       if (IS_ERR(rsccache)) {
+               upcall_cache_cleanup(rsicache);
+               rsicache = NULL;
+               rc = PTR_ERR(rsccache);
+               rsccache = NULL;
+               return rc;
+       }
 
        if (check_gssd_socket())
                CDEBUG(D_SEC,
@@ -1529,4 +1756,5 @@ void gss_exit_svc_upcall(void)
        cache_unregister_net(&rsc_cache, &init_net);
 
        upcall_cache_cleanup(rsicache);
+       upcall_cache_cleanup(rsccache);
 }
index de0e404..6d8eaf3 100644 (file)
@@ -336,6 +336,116 @@ static ssize_t rsi_acquire_expire_seq_write(struct file *file,
 }
 LPROC_SEQ_FOPS(rsi_acquire_expire);
 
+static ssize_t lprocfs_rsc_flush_seq_write(struct file *file,
+                                          const char __user *buffer,
+                                          size_t count, void *data)
+{
+       int hash, rc;
+
+       rc = kstrtoint_from_user(buffer, count, 0, &hash);
+       if (rc)
+               return rc;
+
+       rsc_flush(rsccache, hash);
+       return count;
+}
+LPROC_SEQ_FOPS_WR_ONLY(gss, rsc_flush);
+
+static ssize_t lprocfs_rsc_info_seq_write(struct file *file,
+                                         const char __user *buffer,
+                                         size_t count, void *data)
+{
+       struct rsc_downcall_data *param;
+       int size = sizeof(*param), rc, checked = 0;
+       struct gss_rsc rsc = { 0 }, *rscp = NULL;
+       char *mesg, *handle_buf;
+
+again:
+       if (count < size) {
+               CERROR("%s: invalid data count = %lu, size = %d\n",
+                      rsccache->uc_name, (unsigned long)count, size);
+               return -EINVAL;
+       }
+
+       OBD_ALLOC_LARGE(param, size);
+       if (param == NULL)
+               return -ENOMEM;
+
+       if (copy_from_user(param, buffer, size)) {
+               CERROR("%s: bad rsc data\n", rsccache->uc_name);
+               GOTO(out, rc = -EFAULT);
+       }
+
+       if (checked == 0) {
+               checked = 1;
+               if (param->scd_magic != RSC_DOWNCALL_MAGIC) {
+                       CERROR("%s: rsc downcall bad params\n",
+                              rsccache->uc_name);
+                       GOTO(out, rc = -EINVAL);
+               }
+
+               rc = param->scd_len; /* save scd_len */
+               OBD_FREE_LARGE(param, size);
+               size = offsetof(struct rsc_downcall_data, scd_val[rc]);
+               goto again;
+       }
+
+       /* scd_val starts with handle.
+        * Use it to create cache entry.
+        */
+       mesg = param->scd_val;
+       gss_u32_read(&mesg, &rsc.sc_handle.len);
+       if (!rsc.sc_handle.len) {
+               rc = -EINVAL;
+               goto out;
+       }
+       OBD_ALLOC_LARGE(handle_buf, rsc.sc_handle.len);
+       if (!handle_buf) {
+               rc = -ENOMEM;
+               goto out;
+       }
+       memset(handle_buf, 0, rsc.sc_handle.len);
+       mesg = param->scd_val;
+       rc = gss_buffer_read(&mesg, handle_buf, rsc.sc_handle.len);
+       if (rc < 0) {
+               OBD_FREE_LARGE(handle_buf, rsc.sc_handle.len);
+               rc = -EINVAL;
+               goto out;
+       }
+       rsc.sc_handle.data = handle_buf;
+
+       /* create cache entry on-the-fly */
+       rscp = rsc_entry_get(rsccache, &rsc);
+       __rsc_free(&rsc);
+
+       if (IS_ERR_OR_NULL(rscp)) {
+               if (IS_ERR(rscp))
+                       rc = PTR_ERR(rscp);
+               else
+                       rc = -EINVAL;
+               CERROR("%s: error in rsc_entry_get: rc = %d\n",
+                      param->scd_mechname, rc);
+               goto out;
+       }
+
+       /* now that entry has been created, downcall can be done,
+        * but we have to tell acquiring is in progress
+        */
+       upcall_cache_update_entry(rsccache, rscp->sc_uc_entry,
+                                 0, UC_CACHE_ACQUIRING);
+       rc = upcall_cache_downcall(rsccache, param->scd_err,
+                                  rscp->sc_uc_entry->ue_key, param);
+
+out:
+       if (!IS_ERR_OR_NULL(rscp))
+               rsc_entry_put(rsccache, rscp);
+       if (param)
+               OBD_FREE_LARGE(param, size);
+
+       return rc ? rc : count;
+}
+LPROC_SEQ_FOPS_WR_ONLY(gss, rsc_info);
+
 static struct ldebugfs_vars gss_debugfs_vars[] = {
        { .name =       "replays",
          .fops =       &gss_proc_oos_fops      },
@@ -362,6 +472,10 @@ static struct lprocfs_vars gss_lprocfs_vars[] = {
          .fops =       &rsi_entry_expire_fops },
        { .name =       "rsi_acquire_expire",
          .fops =       &rsi_acquire_expire_fops },
+       { .name =       "rsc_flush",
+         .fops =       &gss_rsc_flush_fops },
+       { .name =       "rsc_info",
+         .fops =       &gss_rsc_info_fops },
        { NULL }
 };
 
index 3a67e93..cf2d72d 100644 (file)
@@ -4427,6 +4427,62 @@ void lustre_assert_wire_constants(void)
        LASSERTF((int)sizeof(((struct rsi_downcall_data *)0)->sid_val) == 0, "found %lld\n",
                 (long long)(int)sizeof(((struct rsi_downcall_data *)0)->sid_val));
 
+       /* Checks for struct rsc_downcall_data */
+       LASSERTF((int)sizeof(struct rsc_downcall_data) == 48, "found %lld\n",
+                (long long)(int)sizeof(struct rsc_downcall_data));
+       LASSERTF((int)offsetof(struct rsc_downcall_data, scd_magic) == 0, "found %lld\n",
+                (long long)(int)offsetof(struct rsc_downcall_data, scd_magic));
+       LASSERTF((int)sizeof(((struct rsc_downcall_data *)0)->scd_magic) == 4, "found %lld\n",
+                (long long)(int)sizeof(((struct rsc_downcall_data *)0)->scd_magic));
+       LASSERTF((int)offsetof(struct rsc_downcall_data, scd_err) == 4, "found %lld\n",
+                (long long)(int)offsetof(struct rsc_downcall_data, scd_err));
+       LASSERTF((int)sizeof(((struct rsc_downcall_data *)0)->scd_err) == 4, "found %lld\n",
+                (long long)(int)sizeof(((struct rsc_downcall_data *)0)->scd_err));
+       LASSERTF((int)offsetof(struct rsc_downcall_data, scd_flags) == 8, "found %lld\n",
+                (long long)(int)offsetof(struct rsc_downcall_data, scd_flags));
+       LASSERTF((int)sizeof(((struct rsc_downcall_data *)0)->scd_flags) == 4, "found %lld\n",
+                (long long)(int)sizeof(((struct rsc_downcall_data *)0)->scd_flags));
+       LASSERTF((int)offsetof(struct rsc_downcall_data, scd_mapped_uid) == 12, "found %lld\n",
+                (long long)(int)offsetof(struct rsc_downcall_data, scd_mapped_uid));
+       LASSERTF((int)sizeof(((struct rsc_downcall_data *)0)->scd_mapped_uid) == 4, "found %lld\n",
+                (long long)(int)sizeof(((struct rsc_downcall_data *)0)->scd_mapped_uid));
+       LASSERTF((int)offsetof(struct rsc_downcall_data, scd_uid) == 16, "found %lld\n",
+                (long long)(int)offsetof(struct rsc_downcall_data, scd_uid));
+       LASSERTF((int)sizeof(((struct rsc_downcall_data *)0)->scd_uid) == 4, "found %lld\n",
+                (long long)(int)sizeof(((struct rsc_downcall_data *)0)->scd_uid));
+       LASSERTF((int)offsetof(struct rsc_downcall_data, scd_gid) == 20, "found %lld\n",
+                (long long)(int)offsetof(struct rsc_downcall_data, scd_gid));
+       LASSERTF((int)sizeof(((struct rsc_downcall_data *)0)->scd_gid) == 4, "found %lld\n",
+                (long long)(int)sizeof(((struct rsc_downcall_data *)0)->scd_gid));
+       LASSERTF((int)offsetof(struct rsc_downcall_data, scd_mechname) == 24, "found %lld\n",
+                (long long)(int)offsetof(struct rsc_downcall_data, scd_mechname));
+       LASSERTF((int)sizeof(((struct rsc_downcall_data *)0)->scd_mechname) == 8, "found %lld\n",
+                (long long)(int)sizeof(((struct rsc_downcall_data *)0)->scd_mechname));
+       LASSERTF((int)offsetof(struct rsc_downcall_data, scd_offset) == 32, "found %lld\n",
+                (long long)(int)offsetof(struct rsc_downcall_data, scd_offset));
+       LASSERTF((int)sizeof(((struct rsc_downcall_data *)0)->scd_offset) == 8, "found %lld\n",
+                (long long)(int)sizeof(((struct rsc_downcall_data *)0)->scd_offset));
+       LASSERTF((int)offsetof(struct rsc_downcall_data, scd_len) == 40, "found %lld\n",
+                (long long)(int)offsetof(struct rsc_downcall_data, scd_len));
+       LASSERTF((int)sizeof(((struct rsc_downcall_data *)0)->scd_len) == 4, "found %lld\n",
+                (long long)(int)sizeof(((struct rsc_downcall_data *)0)->scd_len));
+       LASSERTF((int)offsetof(struct rsc_downcall_data, scd_padding) == 44, "found %lld\n",
+                (long long)(int)offsetof(struct rsc_downcall_data, scd_padding));
+       LASSERTF((int)sizeof(((struct rsc_downcall_data *)0)->scd_padding) == 4, "found %lld\n",
+                (long long)(int)sizeof(((struct rsc_downcall_data *)0)->scd_padding));
+       LASSERTF((int)offsetof(struct rsc_downcall_data, scd_val) == 48, "found %lld\n",
+                (long long)(int)offsetof(struct rsc_downcall_data, scd_val));
+       LASSERTF((int)sizeof(((struct rsc_downcall_data *)0)->scd_val) == 0, "found %lld\n",
+                (long long)(int)sizeof(((struct rsc_downcall_data *)0)->scd_val));
+       LASSERTF(RSC_DATA_FLAG_REMOTE == 0x00000001UL, "found 0x%.8xUL\n",
+                (unsigned)RSC_DATA_FLAG_REMOTE);
+       LASSERTF(RSC_DATA_FLAG_ROOT == 0x00000002UL, "found 0x%.8xUL\n",
+                (unsigned)RSC_DATA_FLAG_ROOT);
+       LASSERTF(RSC_DATA_FLAG_MDS == 0x00000004UL, "found 0x%.8xUL\n",
+                (unsigned)RSC_DATA_FLAG_MDS);
+       LASSERTF(RSC_DATA_FLAG_OSS == 0x00000008UL, "found 0x%.8xUL\n",
+                (unsigned)RSC_DATA_FLAG_OSS);
+
        /* Checks for struct llog_gen */
        LASSERTF((int)sizeof(struct llog_gen) == 16, "found %lld\n",
                 (long long)(int)sizeof(struct llog_gen));
index 003f549..bba1987 100755 (executable)
@@ -10,6 +10,10 @@ init_logging
 
 ALWAYS_EXCEPT="$RECOVERY_SMALL_EXCEPT "
 
+if $SHARED_KEY; then
+       always_except LU-17141 133
+fi
+
 build_test_filter
 
 require_dsh_mds || exit 0
index 2f49e43..70a4a70 100755 (executable)
@@ -1737,12 +1737,21 @@ nodemap_acl_test() {
        sleep 5
 
        do_node $set_client $RUNAS_USER touch $testfile
+       # remove from cache, otherwise ACLs will not be fetched from server
+       do_rpc_nodes $set_client cancel_lru_locks
+       do_node $set_client "sync ; echo 3 > /proc/sys/vm/drop_caches"
 
        # ACL masks aren't filtered by nodemap code, so we ignore them
        acl_count=$(do_node $get_client getfacl $testfile | grep -v mask |
                wc -l)
+       # remove from cache, otherwise ACLs will not be fetched from server
+       do_rpc_nodes $get_client cancel_lru_locks
+       do_node $get_client "sync ; echo 3 > /proc/sys/vm/drop_caches"
        do_node $set_client $RUNAS_USER setfacl -m $user:rwx $testfile ||
                setfacl_error=1
+       # remove from cache, otherwise ACLs will not be fetched from server
+       do_rpc_nodes $set_client cancel_lru_locks
+       do_node $set_client "sync ; echo 3 > /proc/sys/vm/drop_caches"
 
        # if check setfacl is set to 1, then it's supposed to error
        if [ "$check_setfacl" == "1" ]; then
@@ -1753,6 +1762,9 @@ nodemap_acl_test() {
 
        acl_count_post=$(do_node $get_client getfacl $testfile | grep -v mask |
                wc -l)
+       # remove from cache, otherwise ACLs will not be fetched from server
+       do_rpc_nodes $get_client cancel_lru_locks
+       do_node $get_client "sync ; echo 3 > /proc/sys/vm/drop_caches"
        [ $acl_count -eq $acl_count_post ] && return 0
        return 1
 }
index 7719047..d7b09bd 100755 (executable)
@@ -44,6 +44,7 @@ always_except LU-8411  407
 
 if $SHARED_KEY; then
        always_except LU-14181 64e 64f
+       always_except LU-17127 39o
 fi
 
 # skip the grant tests for ARM until they are fixed
index a21b81c..0ae8301 100644 (file)
@@ -95,43 +95,87 @@ struct svc_nego_data {
        gss_buffer_desc         ctx_token;
 };
 
-static int
-do_svc_downcall(gss_buffer_desc *out_handle, struct svc_cred *cred,
-               gss_OID mechoid, gss_buffer_desc *context_token)
+static int do_svc_downcall(gss_buffer_desc *out_handle, struct svc_cred *cred,
+                          gss_OID mechoid, gss_buffer_desc *ctx_token)
 {
-       FILE *f;
+       struct rsc_downcall_data *rsc_dd;
+       int blen, fd, size, rc = -1;
        const char *mechname;
-       int err;
+       glob_t path;
+       char *bp;
 
        printerr(LL_INFO, "doing downcall\n");
+
+       size = out_handle->length + sizeof(__u32) +
+               ctx_token->length + sizeof(__u32);
+       blen = size;
+
+       size += offsetof(struct rsc_downcall_data, scd_val[0]);
+       rsc_dd = calloc(1, size);
+       if (!rsc_dd) {
+               printerr(LL_ERR, "malloc downcall data (%d) failed\n", size);
+               return -ENOMEM;
+       }
+       rsc_dd->scd_magic = RSC_DOWNCALL_MAGIC;
+       rsc_dd->scd_err = 0;
+
+       rsc_dd->scd_flags =
+               (cred->cr_remote ? RSC_DATA_FLAG_REMOTE : 0) |
+               (cred->cr_usr_root ? RSC_DATA_FLAG_ROOT : 0) |
+               (cred->cr_usr_mds ? RSC_DATA_FLAG_MDS : 0) |
+               (cred->cr_usr_oss ? RSC_DATA_FLAG_OSS : 0);
+       rsc_dd->scd_mapped_uid = cred->cr_mapped_uid;
+       rsc_dd->scd_uid = cred->cr_uid;
+       rsc_dd->scd_gid = cred->cr_gid;
        mechname = gss_OID_mech_name(mechoid);
        if (mechname == NULL)
-               goto out_err;
-       f = fopen(SVCGSSD_CONTEXT_CHANNEL, "w");
-       if (f == NULL) {
-               printerr(LL_ERR, "ERROR: unable to open downcall channel "
-                            "%s: %s\n",
-                            SVCGSSD_CONTEXT_CHANNEL, strerror(errno));
-               goto out_err;
+               goto out;
+       if (snprintf(rsc_dd->scd_mechname, sizeof(rsc_dd->scd_mechname),
+                    "%s", mechname) >= sizeof(rsc_dd->scd_mechname))
+               goto out;
+
+       bp = rsc_dd->scd_val;
+       gss_buffer_write(&bp, &blen, out_handle->value, out_handle->length);
+       gss_buffer_write(&bp, &blen, ctx_token->value, ctx_token->length);
+       if (blen < 0) {
+               printerr(LL_ERR, "ERROR: %s: message too long > %d\n",
+                        __func__, size);
+               rc = -EMSGSIZE;
+               goto out;
        }
-       qword_printhex(f, out_handle->value, out_handle->length);
-       /* XXX are types OK for the rest of this? */
-       qword_printint(f, time(NULL) + 3600);   /* 1 hour should be ok */
-       qword_printint(f, cred->cr_remote);
-       qword_printint(f, cred->cr_usr_root);
-       qword_printint(f, cred->cr_usr_mds);
-       qword_printint(f, cred->cr_usr_oss);
-       qword_printint(f, cred->cr_mapped_uid);
-       qword_printint(f, cred->cr_uid);
-       qword_printint(f, cred->cr_gid);
-       qword_print(f, mechname);
-       qword_printhex(f, context_token->value, context_token->length);
-       err = qword_eol(f);
-       fclose(f);
-       return err;
-out_err:
-       printerr(LL_ERR, "ERROR: downcall failed\n");
-       return -1;
+       rsc_dd->scd_len = bp - rsc_dd->scd_val;
+
+       rc = cfs_get_param_paths(&path, RSC_DOWNCALL_PATH);
+       if (rc != 0) {
+               rc = -errno;
+               goto out;
+       }
+
+       fd = open(path.gl_pathv[0], O_WRONLY);
+       if (fd == -1) {
+               rc = -errno;
+               printerr(LL_ERR, "ERROR: %s: open %s failed: %s\n",
+                        __func__, RSC_DOWNCALL_PATH, strerror(-rc));
+               goto out_path;
+       }
+       size = offsetof(struct rsc_downcall_data,
+                       scd_val[bp - rsc_dd->scd_val]);
+       printerr(LL_DEBUG, "writing downcall data, size %d\n", size);
+       if (write(fd, rsc_dd, size) == -1) {
+               rc = -errno;
+               printerr(LL_ERR, "ERROR: %s: failed to write message: %s\n",
+                        __func__, strerror(-rc));
+       }
+       printerr(LL_DEBUG, "downcall data written ok\n");
+
+       close(fd);
+out_path:
+       cfs_free_param_data(&path);
+out:
+       free(rsc_dd);
+       if (rc)
+               printerr(LL_ERR, "ERROR: downcall failed\n");
+       return rc;
 }
 
 struct gss_verifier {
index afdc7e0..10cb139 100644 (file)
@@ -2061,6 +2061,29 @@ check_rsi_downcall_data(void)
 }
 
 static void
+check_rsc_downcall_data(void)
+{
+       BLANK_LINE();
+       CHECK_STRUCT(rsc_downcall_data);
+       CHECK_MEMBER(rsc_downcall_data, scd_magic);
+       CHECK_MEMBER(rsc_downcall_data, scd_err);
+       CHECK_MEMBER(rsc_downcall_data, scd_flags);
+       CHECK_MEMBER(rsc_downcall_data, scd_mapped_uid);
+       CHECK_MEMBER(rsc_downcall_data, scd_uid);
+       CHECK_MEMBER(rsc_downcall_data, scd_gid);
+       CHECK_MEMBER(rsc_downcall_data, scd_mechname);
+       CHECK_MEMBER(rsc_downcall_data, scd_offset);
+       CHECK_MEMBER(rsc_downcall_data, scd_len);
+       CHECK_MEMBER(rsc_downcall_data, scd_padding);
+       CHECK_MEMBER(rsc_downcall_data, scd_val);
+
+       CHECK_VALUE_X(RSC_DATA_FLAG_REMOTE);
+       CHECK_VALUE_X(RSC_DATA_FLAG_ROOT);
+       CHECK_VALUE_X(RSC_DATA_FLAG_MDS);
+       CHECK_VALUE_X(RSC_DATA_FLAG_OSS);
+}
+
+static void
 check_llog_gen(void)
 {
        BLANK_LINE();
@@ -3592,6 +3615,7 @@ main(int argc, char **argv)
        check_llog_changelog_user_rec();
 #endif /* !HAVE_NATIVE_LINUX_CLIENT */
        check_rsi_downcall_data();
+       check_rsc_downcall_data();
        check_llog_gen();
        check_llog_gen_rec();
        check_llog_log_hdr();
index ed3b7c3..2fe67a4 100644 (file)
@@ -4488,6 +4488,62 @@ void lustre_assert_wire_constants(void)
        LASSERTF((int)sizeof(((struct rsi_downcall_data *)0)->sid_val) == 0, "found %lld\n",
                 (long long)(int)sizeof(((struct rsi_downcall_data *)0)->sid_val));
 
+       /* Checks for struct rsc_downcall_data */
+       LASSERTF((int)sizeof(struct rsc_downcall_data) == 48, "found %lld\n",
+                (long long)(int)sizeof(struct rsc_downcall_data));
+       LASSERTF((int)offsetof(struct rsc_downcall_data, scd_magic) == 0, "found %lld\n",
+                (long long)(int)offsetof(struct rsc_downcall_data, scd_magic));
+       LASSERTF((int)sizeof(((struct rsc_downcall_data *)0)->scd_magic) == 4, "found %lld\n",
+                (long long)(int)sizeof(((struct rsc_downcall_data *)0)->scd_magic));
+       LASSERTF((int)offsetof(struct rsc_downcall_data, scd_err) == 4, "found %lld\n",
+                (long long)(int)offsetof(struct rsc_downcall_data, scd_err));
+       LASSERTF((int)sizeof(((struct rsc_downcall_data *)0)->scd_err) == 4, "found %lld\n",
+                (long long)(int)sizeof(((struct rsc_downcall_data *)0)->scd_err));
+       LASSERTF((int)offsetof(struct rsc_downcall_data, scd_flags) == 8, "found %lld\n",
+                (long long)(int)offsetof(struct rsc_downcall_data, scd_flags));
+       LASSERTF((int)sizeof(((struct rsc_downcall_data *)0)->scd_flags) == 4, "found %lld\n",
+                (long long)(int)sizeof(((struct rsc_downcall_data *)0)->scd_flags));
+       LASSERTF((int)offsetof(struct rsc_downcall_data, scd_mapped_uid) == 12, "found %lld\n",
+                (long long)(int)offsetof(struct rsc_downcall_data, scd_mapped_uid));
+       LASSERTF((int)sizeof(((struct rsc_downcall_data *)0)->scd_mapped_uid) == 4, "found %lld\n",
+                (long long)(int)sizeof(((struct rsc_downcall_data *)0)->scd_mapped_uid));
+       LASSERTF((int)offsetof(struct rsc_downcall_data, scd_uid) == 16, "found %lld\n",
+                (long long)(int)offsetof(struct rsc_downcall_data, scd_uid));
+       LASSERTF((int)sizeof(((struct rsc_downcall_data *)0)->scd_uid) == 4, "found %lld\n",
+                (long long)(int)sizeof(((struct rsc_downcall_data *)0)->scd_uid));
+       LASSERTF((int)offsetof(struct rsc_downcall_data, scd_gid) == 20, "found %lld\n",
+                (long long)(int)offsetof(struct rsc_downcall_data, scd_gid));
+       LASSERTF((int)sizeof(((struct rsc_downcall_data *)0)->scd_gid) == 4, "found %lld\n",
+                (long long)(int)sizeof(((struct rsc_downcall_data *)0)->scd_gid));
+       LASSERTF((int)offsetof(struct rsc_downcall_data, scd_mechname) == 24, "found %lld\n",
+                (long long)(int)offsetof(struct rsc_downcall_data, scd_mechname));
+       LASSERTF((int)sizeof(((struct rsc_downcall_data *)0)->scd_mechname) == 8, "found %lld\n",
+                (long long)(int)sizeof(((struct rsc_downcall_data *)0)->scd_mechname));
+       LASSERTF((int)offsetof(struct rsc_downcall_data, scd_offset) == 32, "found %lld\n",
+                (long long)(int)offsetof(struct rsc_downcall_data, scd_offset));
+       LASSERTF((int)sizeof(((struct rsc_downcall_data *)0)->scd_offset) == 8, "found %lld\n",
+                (long long)(int)sizeof(((struct rsc_downcall_data *)0)->scd_offset));
+       LASSERTF((int)offsetof(struct rsc_downcall_data, scd_len) == 40, "found %lld\n",
+                (long long)(int)offsetof(struct rsc_downcall_data, scd_len));
+       LASSERTF((int)sizeof(((struct rsc_downcall_data *)0)->scd_len) == 4, "found %lld\n",
+                (long long)(int)sizeof(((struct rsc_downcall_data *)0)->scd_len));
+       LASSERTF((int)offsetof(struct rsc_downcall_data, scd_padding) == 44, "found %lld\n",
+                (long long)(int)offsetof(struct rsc_downcall_data, scd_padding));
+       LASSERTF((int)sizeof(((struct rsc_downcall_data *)0)->scd_padding) == 4, "found %lld\n",
+                (long long)(int)sizeof(((struct rsc_downcall_data *)0)->scd_padding));
+       LASSERTF((int)offsetof(struct rsc_downcall_data, scd_val) == 48, "found %lld\n",
+                (long long)(int)offsetof(struct rsc_downcall_data, scd_val));
+       LASSERTF((int)sizeof(((struct rsc_downcall_data *)0)->scd_val) == 0, "found %lld\n",
+                (long long)(int)sizeof(((struct rsc_downcall_data *)0)->scd_val));
+       LASSERTF(RSC_DATA_FLAG_REMOTE == 0x00000001UL, "found 0x%.8xUL\n",
+                (unsigned)RSC_DATA_FLAG_REMOTE);
+       LASSERTF(RSC_DATA_FLAG_ROOT == 0x00000002UL, "found 0x%.8xUL\n",
+                (unsigned)RSC_DATA_FLAG_ROOT);
+       LASSERTF(RSC_DATA_FLAG_MDS == 0x00000004UL, "found 0x%.8xUL\n",
+                (unsigned)RSC_DATA_FLAG_MDS);
+       LASSERTF(RSC_DATA_FLAG_OSS == 0x00000008UL, "found 0x%.8xUL\n",
+                (unsigned)RSC_DATA_FLAG_OSS);
+
        /* Checks for struct llog_gen */
        LASSERTF((int)sizeof(struct llog_gen) == 16, "found %lld\n",
                 (long long)(int)sizeof(struct llog_gen));