Whamcloud - gitweb
* add a bit in ptlrpc_request to indicate ptlrpcs error, gss recovery
authorericm <ericm>
Wed, 25 May 2005 18:08:29 +0000 (18:08 +0000)
committerericm <ericm>
Wed, 25 May 2005 18:08:29 +0000 (18:08 +0000)
  fixes, need new nfsutils patches version 8.
* more precise error notify between kernel and lgssd.
* minor gss api param fix. and various minor gss fixes.

lustre/include/linux/lustre_net.h
lustre/include/linux/lustre_sec.h
lustre/mds/mds_lib.c
lustre/ptlrpc/client.c
lustre/ptlrpc/niobuf.c
lustre/sec/gss/sec_gss.c
lustre/sec/gss/svcsec_gss.c
lustre/sec/sec.c
lustre/sec/sec_null.c

index 85ddfca..f577bf1 100644 (file)
@@ -292,7 +292,7 @@ struct ptlrpc_request {
                 rq_timedout:1, rq_resend:1, rq_restart:1, rq_replay:1,
                 rq_no_resend:1, rq_waiting:1, rq_receiving_reply:1,
                 rq_no_delay:1, rq_net_err:1, rq_req_wrapped:1,
-                rq_ptlrpcs_restart:1;
+                rq_ptlrpcs_restart:1, rq_ptlrpcs_err:1;
         int rq_phase;
         /* client-side refcount for SENT race */
         atomic_t rq_refcount;
index e1e866c..94028b4 100644 (file)
@@ -120,26 +120,29 @@ struct vfs_cred {
 };
 
 struct ptlrpc_credops {
+        int     (*match)  (struct ptlrpc_cred *cred, struct vfs_cred *vcred);
         int     (*refresh)(struct ptlrpc_cred *cred);
-        int     (*match)  (struct ptlrpc_cred *cred,
-                           struct ptlrpc_request *req,
-                           struct vfs_cred *vcred);
-        int     (*sign)   (struct ptlrpc_cred *cred, struct ptlrpc_request *req);
-        int     (*verify) (struct ptlrpc_cred *cred, struct ptlrpc_request *req);
-        int     (*seal)   (struct ptlrpc_cred *cred, struct ptlrpc_request *req);
-        int     (*unseal) (struct ptlrpc_cred *cred, struct ptlrpc_request *req);
         void    (*destroy)(struct ptlrpc_cred *cred);
+        int     (*sign)   (struct ptlrpc_cred *cred,
+                           struct ptlrpc_request *req);
+        int     (*verify) (struct ptlrpc_cred *cred,
+                           struct ptlrpc_request *req);
+        int     (*seal)   (struct ptlrpc_cred *cred,
+                           struct ptlrpc_request *req);
+        int     (*unseal) (struct ptlrpc_cred *cred,
+                           struct ptlrpc_request *req);
 };
 
-#define PTLRPC_CRED_UPTODATE    0x00000001
-#define PTLRPC_CRED_DEAD        0x00000002
+#define PTLRPC_CRED_UPTODATE    0x00000001 /* uptodate */
+#define PTLRPC_CRED_DEAD        0x00000002 /* mark expired gracefully */
+#define PTLRPC_CRED_ERROR       0x00000004 /* fatal error (refresh, etc.) */
+#define PTLRPC_CRED_FLAGS_MASK  0x00000007
 
 struct ptlrpc_cred {
         struct list_head        pc_hash;   /* linked into hash table */
         atomic_t                pc_refcount;
         struct ptlrpc_sec      *pc_sec;
         struct ptlrpc_credops  *pc_ops;
-        struct ptlrpc_request  *pc_req;
         unsigned long           pc_expire;
         int                     pc_flags;
         /* XXX maybe should not be here */
@@ -153,7 +156,6 @@ struct ptlrpc_secops {
                                                 void *pipe_data);
         void                  (*destroy_sec)   (struct ptlrpc_sec *sec);
         struct ptlrpc_cred *  (*create_cred)   (struct ptlrpc_sec *sec,
-                                                struct ptlrpc_request *req,
                                                 struct vfs_cred *vcred);
         /* buffer manipulation */
         int                   (*alloc_reqbuf)  (struct ptlrpc_sec *sec,
@@ -224,7 +226,8 @@ static inline int ptlrpcs_cred_is_uptodate(struct ptlrpc_cred *cred)
 {
         LASSERT(cred);
         LASSERT(atomic_read(&cred->pc_refcount));
-        return (cred->pc_flags & PTLRPC_CRED_UPTODATE);
+        return ((cred->pc_flags & PTLRPC_CRED_FLAGS_MASK) ==
+                PTLRPC_CRED_UPTODATE);
 }
 static inline int ptlrpcs_cred_refresh(struct ptlrpc_cred *cred)
 {
index a073ec7..2da62bf 100644 (file)
@@ -890,6 +890,15 @@ int mds_init_ucred(struct lvfs_ucred *ucred,
         LASSERT(rsd);
         LASSERT(rsd->rsd_ngroups <= LUSTRE_MAX_GROUPS);
 
+        /* XXX We'v no dedicated bits indicating whether GSS is used,
+         * and authenticated/mapped uid is valid. currently we suppose
+         * gss must initialize rq_sec_svcdata.
+         */
+        if (req->rq_sec_svcdata && req->rq_auth_uid == -1) {
+                CWARN("user not authenticated, deny access\n");
+                RETURN(-EPERM);
+        }
+
         strong_sec = (req->rq_auth_uid != -1);
         LASSERT(!(req->rq_remote_realm && !strong_sec));
 
index ce0eddc..a289751 100644 (file)
@@ -209,12 +209,13 @@ struct ptlrpc_request *ptlrpc_prep_req(struct obd_import *imp, __u32 version,
                 GOTO(out_free, rc);
         }
 
-        /* just a try on refresh, but we proceed even if it failed */
-        rc = ptlrpcs_cred_refresh(request->rq_cred);
-        if (!ptlrpcs_cred_is_uptodate(request->rq_cred)) {
-                CERROR("req %p: failed to refresh cred %p, rc %d, continue\n",
-                       request, request->rq_cred, rc);
-        }
+        /* try to refresh the cred. we do this here in order to let fewer
+         * refresh be performed in ptlrpcd context (which might block ptlrpcd).
+         * fail out only if a fatal ptlrpcs error occured.
+         */
+        ptlrpcs_req_refresh_cred(request);
+        if (request->rq_ptlrpcs_err)
+                GOTO(out_cred, rc = -EPERM);
 
         rc = lustre_pack_request(request, count, lengths, bufs);
         if (rc) {
@@ -666,10 +667,10 @@ int ptlrpc_check_set(struct ptlrpc_request_set *set)
                 if (req->rq_net_err && !req->rq_timedout)
                         ptlrpc_expire_one_request(req); 
 
-                if (req->rq_err) {
+                if (req->rq_err || req->rq_ptlrpcs_err) {
                         ptlrpc_unregister_reply(req);
                         if (req->rq_status == 0)
-                                req->rq_status = -EIO;
+                                req->rq_status = req->rq_err ? -EIO : -EPERM;
                         req->rq_phase = RQ_PHASE_INTERPRET;
 
                         spin_lock_irqsave(&imp->imp_lock, flags);
@@ -1495,6 +1496,9 @@ repeat:
         if (req->rq_err)
                 GOTO(out, rc = -EIO);
 
+        if (req->rq_ptlrpcs_err)
+                GOTO(out, rc = -EPERM);
+
         /* Resend if we need to, unless we were interrupted. */
         if (req->rq_resend && !req->rq_intr) {
                 /* ...unless we were specifically told otherwise. */
index f883a48..7cdb908 100644 (file)
@@ -450,8 +450,9 @@ int ptl_send_rpc(struct ptlrpc_request *request)
         request->rq_timedout = 0;
         request->rq_net_err = 0;
         request->rq_resend = 0;
-        request->rq_ptlrpcs_restart = 0;
         request->rq_restart = 0;
+        request->rq_ptlrpcs_restart = 0;
+        request->rq_ptlrpcs_err = 0;
         spin_unlock_irqrestore (&request->rq_lock, flags);
 
         reply_md.start     = request->rq_repbuf;
@@ -693,10 +694,13 @@ int ptlrpc_do_rawrpc(struct obd_import *imp,
         if (request.rq_err || request.rq_resend || request.rq_intr ||
             request.rq_timedout || !request.rq_replied) {
                 CERROR("secinit rpc error: err %d, resend %d, "
-                       "intr %d, timeout %d, replied %d\n",
+                       "intr %d, timedout %d, replied %d\n",
                         request.rq_err, request.rq_resend, request.rq_intr,
                         request.rq_timedout, request.rq_replied);
-                rc = -EINVAL;
+                if (request.rq_timedout)
+                        rc = -ETIMEDOUT;
+                else
+                        rc = -EINVAL;
         } else {
                 *replenp = request.rq_nob_received;
                 rc = 0;
index 8b98364..b811f00 100644 (file)
@@ -305,7 +305,8 @@ static int gss_send_secinit_rpc(__user char *buffer, unsigned long count)
 
         if (!reqbuf || !repbuf) {
                 CERROR("Can't alloc buffer: %p/%p\n", reqbuf, repbuf);
-                GOTO(out_free, rc = -ENOMEM);
+                param.status = -ENOMEM;
+                goto out_copy;
         }
 
         /* get token */
@@ -313,34 +314,42 @@ static int gss_send_secinit_rpc(__user char *buffer, unsigned long count)
                                          param.uid, param.gid,
                                          param.send_token_size,
                                          param.send_token);
-        if (reqlen < 0)
-                GOTO(out_free, rc = reqlen);
+        if (reqlen < 0) {
+                param.status = reqlen;
+                goto out_copy;
+        }
 
         replen = repbuf_size;
         rc = ptlrpc_do_rawrpc(imp, reqbuf, reqlen,
                               repbuf, &replen, SECINIT_RPC_TIMEOUT);
-        if (rc)
-                GOTO(out_free, rc);
+        if (rc) {
+                param.status = rc;
+                goto out_copy;
+        }
 
         if (replen > param.reply_buf_size) {
                 CERROR("output buffer size %ld too small, need %d\n",
                         param.reply_buf_size, replen);
-                GOTO(out_free, rc = -EINVAL);
+                param.status = -EINVAL;
+                goto out_copy;
         }
 
         lsize = secinit_parse_reply(repbuf, replen,
                                     param.reply_buf, param.reply_buf_size);
-        if (lsize < 0)
-                GOTO(out_free, rc = (int)lsize);
+        if (lsize < 0) {
+                param.status = (int) lsize;
+                goto out_copy;
+        }
 
         param.status = 0;
         param.reply_length = lsize;
 
+out_copy:
         if (copy_to_user(buffer, &param, sizeof(param)))
                 rc = -EFAULT;
         else
                 rc = 0;
-out_free:
+
         class_import_put(imp);
         if (repbuf)
                 OBD_FREE(repbuf, repbuf_size);
@@ -620,10 +629,11 @@ int gss_parse_init_downcall(struct gss_api_mech *gm, rawobj_t *buf,
         struct gss_cl_ctx *ctx;
         rawobj_t tmp_buf;
         unsigned int timeout;
-        int err = -EIO;
+        int err = -EPERM;
         ENTRY;
 
         *gc = NULL;
+        *gss_err = 0;
 
         OBD_ALLOC(ctx, sizeof(*ctx));
         if (!ctx)
@@ -635,45 +645,56 @@ int gss_parse_init_downcall(struct gss_api_mech *gm, rawobj_t *buf,
         atomic_set(&ctx->gc_refcount,1);
 
         if (simple_get_bytes(&p, &len, &gmd->gum_uid, sizeof(gmd->gum_uid)))
-                GOTO(err_free_ctx, err);
+                goto err_free_ctx;
         if (simple_get_bytes(&p, &len, &gmd->gum_svc, sizeof(gmd->gum_svc)))
-                GOTO(err_free_ctx, err);
+                goto err_free_ctx;
         if (simple_get_bytes(&p, &len, &gmd->gum_nal, sizeof(gmd->gum_nal)))
-                GOTO(err_free_ctx, err);
+                goto err_free_ctx;
         if (simple_get_bytes(&p, &len, &gmd->gum_netid, sizeof(gmd->gum_netid)))
-                GOTO(err_free_ctx, err);
+                goto err_free_ctx;
         if (simple_get_bytes(&p, &len, &gmd->gum_nid, sizeof(gmd->gum_nid)))
-                GOTO(err_free_ctx, err);
+                goto err_free_ctx;
         /* FIXME: discarded timeout for now */
         if (simple_get_bytes(&p, &len, &timeout, sizeof(timeout)))
-                GOTO(err_free_ctx, err);
-        *gss_err = 0;
+                goto err_free_ctx;
         if (simple_get_bytes(&p, &len, &ctx->gc_win, sizeof(ctx->gc_win)))
-                GOTO(err_free_ctx, err);
-        /* gssd signals an error by passing ctx->gc_win = 0: */
+                goto err_free_ctx;
+
+        /* lgssd signals an error by passing ctx->gc_win = 0: */
         if (!ctx->gc_win) {
-                /* in which case the next int is an error code: */
-                if (simple_get_bytes(&p, &len, gss_err, sizeof(*gss_err)))
-                        GOTO(err_free_ctx, err);
-                if (*gss_err == 0) {
-                        CERROR("error downcall pass no gss error\n");
-                        GOTO(err_free_ctx, err);
+                /* in which case the next 2 int are:
+                 * - rpc error
+                 * - gss error
+                 */
+                if (simple_get_bytes(&p, &len, &err, sizeof(err))) {
+                        err = -EPERM;
+                        goto err_free_ctx;
                 }
-                GOTO(err_free_ctx, err = 0);
+                if (simple_get_bytes(&p, &len, gss_err, sizeof(*gss_err))) {
+                        err = -EPERM;
+                        goto err_free_ctx;
+                }
+                if (err == 0 && *gss_err == 0) {
+                        CERROR("no error passed from downcall\n");
+                        err = -EPERM;
+                }
+                goto err_free_ctx;
         }
+
         if (rawobj_extract_local(&tmp_buf, (__u32 **) ((void *)&p), &len))
-                GOTO(err_free_ctx, err);
+                goto err_free_ctx;
         if (rawobj_dup(&ctx->gc_wire_ctx, &tmp_buf)) {
-                GOTO(err_free_ctx, err = -ENOMEM);
+                err = -ENOMEM;
+                goto err_free_ctx;
         }
         if (rawobj_extract_local(&tmp_buf, (__u32 **) ((void *)&p), &len))
-                GOTO(err_free_wire_ctx, err);
+                goto err_free_wire_ctx;
         if (len) {
                 CERROR("unexpected trailing %u bytes\n", len);
-                GOTO(err_free_wire_ctx, err);
+                goto err_free_wire_ctx;
         }
         if (kgss_import_sec_context(&tmp_buf, gm, &ctx->gc_gss_ctx))
-                GOTO(err_free_wire_ctx, err);
+                goto err_free_wire_ctx;
 
         *gc = ctx;
         RETURN(0);
@@ -747,16 +768,18 @@ again:
         spin_lock(&gsec->gs_lock);
         gss_msg = gss_find_upcall(gsec, obdname, &gmd);
         if (gss_msg) {
-                spin_unlock(&gsec->gs_lock);
+                if (gss_new) {
+                        OBD_FREE(gss_new, sizeof(*gss_new));
+                        gss_new = NULL;
+                }
                 GOTO(waiting, res);
         }
+
         if (!gss_new) {
                 spin_unlock(&gsec->gs_lock);
                 OBD_ALLOC(gss_new, sizeof(*gss_new));
-                if (!gss_new) {
-                        CERROR("fail to alloc memory\n");
+                if (!gss_new)
                         RETURN(-ENOMEM);
-                }
                 goto again;
         }
         /* so far we'v created gss_new */
@@ -781,30 +804,45 @@ again:
                 CERROR("rpc_queue_upcall failed: %d\n", res);
                 gss_unhash_msg(gss_new);
                 gss_release_msg(gss_new);
+                cred->pc_flags |= PTLRPC_CRED_ERROR;
                 RETURN(res);
         }
         gss_msg = gss_new;
+        spin_lock(&gsec->gs_lock);
 
 waiting:
+        /* upcall might finish quickly */
+        if (list_empty(&gss_msg->gum_list)) {
+                spin_unlock(&gsec->gs_lock);
+                res = 0;
+                goto out;
+        }
+
         init_waitqueue_entry(&wait, current);
-        spin_lock(&gsec->gs_lock);
-        add_wait_queue(&gss_msg->gum_waitq, &wait);
         set_current_state(TASK_INTERRUPTIBLE);
+        add_wait_queue(&gss_msg->gum_waitq, &wait);
         spin_unlock(&gsec->gs_lock);
 
         res = schedule_timeout(CRED_REFRESH_UPCALL_TIMEOUT * HZ);
-
         remove_wait_queue(&gss_msg->gum_waitq, &wait);
+
         if (signal_pending(current)) {
-                CERROR("interrupted gss upcall: cred %p\n", cred);
+                CERROR("cred %p: interrupted upcall\n", cred);
+                if (gss_new)
+                        cred->pc_flags |= PTLRPC_CRED_DEAD | PTLRPC_CRED_ERROR;
                 res = -EINTR;
         } else if (res == 0) {
-                CERROR("gss upcall timeout: cred %p\n", cred);
+                CERROR("cred %p: upcall timedout\n", cred);
+                cred->pc_flags |= PTLRPC_CRED_DEAD | PTLRPC_CRED_ERROR;
                 res = -ETIMEDOUT;
         } else
                 res = 0;
 
+out:
+        spin_lock(&gsec->gs_lock);
         gss_release_msg(gss_msg);
+        spin_unlock(&gsec->gs_lock);
+
         RETURN(res);
 }
 #else /* !__KERNEL__ */
@@ -861,14 +899,12 @@ static int gss_cred_refresh(struct ptlrpc_cred *cred)
         LASSERT(mech);
         rc = gss_parse_init_downcall(mech, &obj, &ctx, &vcred, &dest_ip,
                                      &gss_err);
-        if (rc) {
-                CERROR("parse init downcall error %d\n", rc);
-                goto err_out;
-        }
-
-        if (gss_err) {
-                CERROR("cred fresh got gss error %x\n", gss_err);
-                rc = -EINVAL;
+        if (rc || gss_err) {
+                CERROR("parse init downcall: rpc %d, gss 0x%x\n", rc, gss_err);
+                if (rc != -ERESTART || gss_err != 0)
+                        cred->pc_flags |= PTLRPC_CRED_ERROR;
+                if (rc == 0)
+                        rc = -EPERM;
                 goto err_out;
         }
 
@@ -884,7 +920,6 @@ err_out:
 #endif
 
 static int gss_cred_match(struct ptlrpc_cred *cred,
-                          struct ptlrpc_request *req,
                           struct vfs_cred *vcred)
 {
         RETURN(cred->pc_pag == vcred->vc_pag);
@@ -1451,12 +1486,16 @@ gss_pipe_downcall(struct file *filp, const char *src, size_t mlen)
         cred = ptlrpcs_cred_lookup(sec, &vcred);
         if (!cred) {
                 CWARN("didn't find cred for uid %u\n", vcred.vc_uid);
-                GOTO(err, err);
+                GOTO(err, err = -EINVAL);
         }
+
         if (err || gss_err) {
-                CERROR("got err %d, gss err %d, set cred %p dead\n",
-                        err, gss_err, cred);
                 cred->pc_flags |= PTLRPC_CRED_DEAD;
+                if (err != -ERESTART || gss_err != 0)
+                        cred->pc_flags |= PTLRPC_CRED_ERROR;
+                CERROR("cred %p: rpc err %d, gss err 0x%x, fatal %d\n",
+                        cred, err, gss_err,
+                        ((cred->pc_flags & PTLRPC_CRED_ERROR) != 0));
         } else {
                 CDEBUG(D_SEC, "get initial ctx:\n");
                 gss_cred_set_ctx(cred, ctx);
@@ -1676,7 +1715,6 @@ void gss_destroy_sec(struct ptlrpc_sec *sec)
 
 static
 struct ptlrpc_cred * gss_create_cred(struct ptlrpc_sec *sec,
-                                     struct ptlrpc_request *req,
                                      struct vfs_cred *vcred)
 {
         struct gss_cred *gcred;
@@ -1692,7 +1730,6 @@ struct ptlrpc_cred * gss_create_cred(struct ptlrpc_sec *sec,
         atomic_set(&cred->pc_refcount, 0);
         cred->pc_sec = sec;
         cred->pc_ops = &gss_credops;
-        cred->pc_req = req;
         cred->pc_expire = get_seconds() + GSS_CRED_EXPIRE;
         cred->pc_flags = 0;
         cred->pc_pag = vcred->vc_pag;
index 14ddd73..fda3d01 100644 (file)
@@ -923,7 +923,13 @@ gss_svcsec_handle_init(struct ptlrpc_request *req,
         rsci = gss_svc_searchbyctx(&rsip->out_handle);
         if (!rsci) {
                 CERROR("rsci still not mature yet?\n");
-                GOTO(out_rsip, rc = SVC_DROP);
+
+                if (gss_pack_err_notify(req, GSS_S_FAILURE, 0))
+                        rc = SVC_DROP;
+                else
+                        rc = SVC_COMPLETE;
+
+                GOTO(out_rsip, rc);
         }
         CWARN("svcsec create gss context %p(%u@%s)\n",
                rsci, rsci->cred.vc_uid,
index bf09bf7..2d0c364 100644 (file)
@@ -238,7 +238,6 @@ int ptlrpcs_cred_get_hash(__u64 pag)
 static
 struct ptlrpc_cred * cred_cache_lookup(struct ptlrpc_sec *sec,
                                        struct vfs_cred *vcred,
-                                       struct ptlrpc_request *req,
                                        int create)
 {
         struct ptlrpc_cred *cred, *new = NULL, *n;
@@ -259,7 +258,7 @@ retry:
                         continue;
                 if (ptlrpcs_cred_unlink_expired(cred, &freelist))
                         continue;
-                if (cred->pc_ops->match(cred, req, vcred)) {
+                if (cred->pc_ops->match(cred, vcred)) {
                         found = 1;
                         break;
                 }
@@ -277,7 +276,7 @@ retry:
                         cred = new;
                 } else if (create) {
                         spin_unlock(&sec->ps_lock);
-                        new = sec->ps_type->pst_ops->create_cred(sec, req, vcred);
+                        new = sec->ps_type->pst_ops->create_cred(sec, vcred);
                         if (new) {
                                 atomic_inc(&sec->ps_credcount);
                                 goto retry;
@@ -302,7 +301,7 @@ struct ptlrpc_cred * ptlrpcs_cred_lookup(struct ptlrpc_sec *sec,
         struct ptlrpc_cred *cred;
         ENTRY;
 
-        cred = cred_cache_lookup(sec, vcred, NULL, 0);
+        cred = cred_cache_lookup(sec, vcred, 0);
         RETURN(cred);
 }
 
@@ -322,7 +321,7 @@ int ptlrpcs_req_get_cred(struct ptlrpc_request *req)
         vcred.vc_pag = (__u64) current->uid;
         vcred.vc_uid = current->uid;
 
-        req->rq_cred = cred_cache_lookup(imp->imp_sec, &vcred, req, 1);
+        req->rq_cred = cred_cache_lookup(imp->imp_sec, &vcred, 1);
 
         if (!req->rq_cred) {
                 CERROR("req %p: fail to get cred from cache\n", req);
@@ -407,21 +406,27 @@ int ptlrpcs_req_replace_dead_cred(struct ptlrpc_request *req)
         RETURN(rc);
 }
 
+/*
+ * since there's no lock on the cred, its status could be changed
+ * by other threads at any time, we allow this race.
+ */
 int ptlrpcs_req_refresh_cred(struct ptlrpc_request *req)
 {
         struct ptlrpc_cred *cred = req->rq_cred;
-        int rc;
         ENTRY;
 
         LASSERT(cred);
 
-        if ((cred->pc_flags & (PTLRPC_CRED_UPTODATE | PTLRPC_CRED_DEAD)) ==
-            PTLRPC_CRED_UPTODATE)
+        if (ptlrpcs_cred_is_uptodate(cred))
                 RETURN(0);
 
+        if (cred->pc_flags & PTLRPC_CRED_ERROR) {
+                req->rq_ptlrpcs_err = 1;
+                RETURN(-EPERM);
+        }
+
         if (cred->pc_flags & PTLRPC_CRED_DEAD) {
-                rc = ptlrpcs_req_replace_dead_cred(req);
-                if (!rc) {
+                if (ptlrpcs_req_replace_dead_cred(req) == 0) {
                         LASSERT(cred != req->rq_cred);
                         CWARN("req %p: replace cred %p => %p\n",
                                req, cred, req->rq_cred);
@@ -434,14 +439,16 @@ int ptlrpcs_req_refresh_cred(struct ptlrpc_request *req)
                 }
         }
 
-        rc = ptlrpcs_cred_refresh(cred);
-        if (!(cred->pc_flags & PTLRPC_CRED_UPTODATE)) {
-                CERROR("req %p: failed to refresh cred %p, rc %d\n",
-                        req, cred, rc);
-                if (!rc)
-                        rc = -EACCES;
-        }
-        RETURN(rc);
+        ptlrpcs_cred_refresh(cred);
+        if (!ptlrpcs_cred_is_uptodate(cred)) {
+                if (cred->pc_flags & PTLRPC_CRED_ERROR)
+                        req->rq_ptlrpcs_err = 1;
+
+                CERROR("req %p: failed to refresh cred %p, fatal %d\n",
+                        req, cred, req->rq_ptlrpcs_err);
+                RETURN(-EPERM);
+        } else
+                RETURN(0);
 }
 
 int ptlrpcs_cli_wrap_request(struct ptlrpc_request *req)
index 3d9d908..3761be5 100644 (file)
@@ -44,7 +44,6 @@ static int null_cred_refresh(struct ptlrpc_cred *cred)
 }
 
 static int null_cred_match(struct ptlrpc_cred *cred,
-                           struct ptlrpc_request *req,
                            struct vfs_cred *vcred)
 {
         ENTRY;
@@ -133,7 +132,6 @@ void null_destroy_sec(struct ptlrpc_sec *sec)
 
 static
 struct ptlrpc_cred* null_create_cred(struct ptlrpc_sec *sec,
-                                     struct ptlrpc_request *req,
                                      struct vfs_cred *vcred)
 {
         struct ptlrpc_cred *cred;
@@ -147,7 +145,6 @@ struct ptlrpc_cred* null_create_cred(struct ptlrpc_sec *sec,
         atomic_set(&cred->pc_refcount, 0);
         cred->pc_sec = sec;
         cred->pc_ops = &null_credops;
-        cred->pc_req = req;
         cred->pc_expire = (-1UL >> 1); /* never expire */
         cred->pc_flags = PTLRPC_CRED_UPTODATE;
         cred->pc_pag = vcred->vc_pag;