Whamcloud - gitweb
LU-16566 sptlrpc: remove rq_sepol from ptlrpc_request 45/52845/9
authorEtienne AUJAMES <etienne.aujames@cea.fr>
Thu, 26 Oct 2023 19:28:55 +0000 (21:28 +0200)
committerOleg Drokin <green@whamcloud.com>
Sun, 4 Feb 2024 08:28:11 +0000 (08:28 +0000)
This patch remove rq_sepol from ptlrpc_request to reduce the memory
consumption on the servers.

rq_sepol field is 327 bytes long allocated for each request and this
is rarely used (it needs SELinux activated with the send_sepol
feature).

The patch store the SELinux policy status string in a separate object.
The pointer is stored in ptlrpc_sec->ps_sepol and protected by RCU
(mostly read-only, the SELinux policy should rarely change).

When the policy status needs to be packed in a request, we take a
reference to the current ps_sepol object and release it after the
packing. If the policy has changed in the meantime, the object used
will be free after.

A read operation is added to srpc_sepol parameter to return the
SELinux policy string cached in Lustre.

Test-Parameters: testlist=sanity-selinux env=ONLY=21,ONLY_REPEAT=50
Test-Parameters: testlist=sanity-selinux env=ONLY=21,ONLY_REPEAT=50
Signed-off-by: Etienne AUJAMES <eaujames@ddn.com>
Change-Id: I80fb76c97885c4b2987eb7f91a9bfe6e0e6e6c70
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/52845
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
Reviewed-by: Sebastien Buisson <sbuisson@ddn.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
13 files changed:
lustre/include/lustre_net.h
lustre/include/lustre_sec.h
lustre/mdc/mdc_internal.h
lustre/mdc/mdc_lib.c
lustre/mdc/mdc_locks.c
lustre/mdc/mdc_reint.c
lustre/mdc/mdc_request.c
lustre/ptlrpc/gss/gss_keyring.c
lustre/ptlrpc/gss/sec_gss.c
lustre/ptlrpc/import.c
lustre/ptlrpc/sec.c
lustre/ptlrpc/sec_lproc.c
lustre/ptlrpc/sec_null.c

index 4b12182..33063ee 100644 (file)
@@ -1061,13 +1061,6 @@ struct ptlrpc_request {
        /** description of flavors for client & server */
        struct sptlrpc_flavor            rq_flvr;
 
-       /**
-        * SELinux policy info at the time of the request
-        * sepol string format is:
-        * <mode>:<policy name>:<policy version>:<policy hash>
-        */
-       char rq_sepol[LUSTRE_NODEMAP_SEPOL_LENGTH + 1];
-
        /* client/server security flags */
        unsigned int
                                  rq_ctx_init:1,      /* context initiation */
index 44e6dd6..936939e 100644 (file)
@@ -846,6 +846,20 @@ struct ptlrpc_sec_policy {
 #define PTLRPC_SEC_FL_BULK              0x0008 /* intensive bulk i/o expected */
 #define PTLRPC_SEC_FL_PAG               0x0010 /* PAG mode */
 
+struct sptlrpc_sepol {
+       struct rcu_head ssp_rcu;
+       struct kref     ssp_ref;
+       /** mtime of SELinux policy file */
+       ktime_t         ssp_mtime;
+       /**
+        * SELinux policy info
+        * sepol string format is:
+        * <mode>:<policy name>:<policy version>:<policy hash>
+        */
+       __u32           ssp_sepol_size;
+       char            ssp_sepol[0];
+};
+
 /**
  * The ptlrpc_sec represents the client side ptlrpc security facilities,
  * each obd_import (both regular and reverse import) must associate with
@@ -867,17 +881,10 @@ struct ptlrpc_sec {
         /** owning import */
         struct obd_import              *ps_import;
        spinlock_t                      ps_lock;
-       /** mtime of SELinux policy file */
-       ktime_t                         ps_sepol_mtime;
        /** next check time of SELinux policy file */
        ktime_t                         ps_sepol_checknext;
-       /**
-        * SELinux policy info
-        * sepol string format is:
-        * <mode>:<policy name>:<policy version>:<policy hash>
-        */
-       char                            ps_sepol[LUSTRE_NODEMAP_SEPOL_LENGTH
-                                                + 1];
+       /** SELinux policy file information */
+       struct sptlrpc_sepol            *ps_sepol;
 
        /*
         * garbage collection
@@ -1095,9 +1102,16 @@ int sptlrpc_cli_enlarge_reqbuf(struct ptlrpc_request *req,
 int  sptlrpc_cli_unwrap_early_reply(struct ptlrpc_request *req,
                                     struct ptlrpc_request **req_ret);
 void sptlrpc_cli_finish_early_reply(struct ptlrpc_request *early_req);
-
 void sptlrpc_request_out_callback(struct ptlrpc_request *req);
-int sptlrpc_get_sepol(struct ptlrpc_request *req);
+
+static inline size_t sptlrpc_sepol_size(struct sptlrpc_sepol *sepol)
+{
+       return sepol ? sepol->ssp_sepol_size : 0;
+}
+
+void sptlrpc_sepol_put(struct sptlrpc_sepol *pol);
+struct sptlrpc_sepol *sptlrpc_sepol_get_cached(struct ptlrpc_sec *imp_sec);
+struct sptlrpc_sepol *sptlrpc_sepol_get(struct ptlrpc_request *req);
 
 /*
  * exported higher interface of import & request
index 82da07a..15bac99 100644 (file)
@@ -48,22 +48,26 @@ void mdc_setattr_pack(struct req_capsule *pill, struct md_op_data *op_data,
                      void *ea, size_t ealen);
 void mdc_create_pack(struct req_capsule *pill, struct md_op_data *op_data,
                     const void *data, size_t datalen, umode_t mode,
-                    uid_t uid, gid_t gid, kernel_cap_t capability, u64 rdev);
+                    uid_t uid, gid_t gid, kernel_cap_t cap_effective, u64 rdev,
+                    struct sptlrpc_sepol *sepol);
 void mdc_open_pack(struct req_capsule *pill, struct md_op_data *op_data,
-                  umode_t mode, __u64 rdev, __u64 flags,
-                  const void *data, size_t datalen);
+                  umode_t mode, __u64 rdev, __u64 flags, const void *lmm,
+                  size_t lmmlen, struct sptlrpc_sepol *sepol);
 void mdc_file_secctx_pack(struct req_capsule *pill,
                          const char *secctx_name,
                          const void *secctx, size_t secctx_size);
 void mdc_file_encctx_pack(struct req_capsule *pill,
                          const void *encctx, size_t encctx_size);
-void mdc_file_sepol_pack(struct req_capsule *pill);
+void mdc_file_sepol_pack(struct req_capsule *pill, struct sptlrpc_sepol *p);
 
-void mdc_unlink_pack(struct req_capsule *pill, struct md_op_data *op_data);
-void mdc_link_pack(struct req_capsule *pill, struct md_op_data *op_data);
+void mdc_unlink_pack(struct req_capsule *pill, struct md_op_data *op_data,
+                    struct sptlrpc_sepol *sepol);
+void mdc_link_pack(struct req_capsule *pill, struct md_op_data *op_data,
+                  struct sptlrpc_sepol *sepol);
 void mdc_rename_pack(struct req_capsule *pill, struct md_op_data *op_data,
                     const char *old, size_t oldlen,
-                    const char *new, size_t newlen);
+                    const char *new, size_t newlen,
+                    struct sptlrpc_sepol *sepol);
 void mdc_migrate_pack(struct req_capsule *pill, struct md_op_data *op_data,
                        const char *name, size_t namelen);
 void mdc_close_pack(struct req_capsule *pill, struct md_op_data *op_data);
index d9bdeeb..ff56a6f 100644 (file)
@@ -162,21 +162,20 @@ void mdc_file_encctx_pack(struct req_capsule *pill,
        memcpy(buf, encctx, buf_size);
 }
 
-void mdc_file_sepol_pack(struct req_capsule *pill)
+void mdc_file_sepol_pack(struct req_capsule *pill, struct sptlrpc_sepol *p)
 {
        void *buf;
        size_t buf_size;
-       struct ptlrpc_request *req = pill->rc_req;
 
-       if (strlen(req->rq_sepol) == 0)
+       if (!p || !p->ssp_sepol_size)
                return;
 
        buf = req_capsule_client_get(pill, &RMF_SELINUX_POL);
        buf_size = req_capsule_get_size(pill, &RMF_SELINUX_POL,
                                        RCL_CLIENT);
 
-       LASSERT(buf_size == strlen(req->rq_sepol) + 1);
-       snprintf(buf, strlen(req->rq_sepol) + 1, "%s", req->rq_sepol);
+       LASSERT(buf_size == p->ssp_sepol_size);
+       strlcpy(buf, p->ssp_sepol, p->ssp_sepol_size);
 }
 
 void mdc_readdir_pack(struct req_capsule *pill, __u64 pgoff, size_t size,
@@ -195,7 +194,8 @@ void mdc_readdir_pack(struct req_capsule *pill, __u64 pgoff, size_t size,
 /* packing of MDS records */
 void mdc_create_pack(struct req_capsule *pill, struct md_op_data *op_data,
                     const void *data, size_t datalen, umode_t mode,
-                    uid_t uid, gid_t gid, kernel_cap_t cap_effective, u64 rdev)
+                    uid_t uid, gid_t gid, kernel_cap_t cap_effective, u64 rdev,
+                    struct sptlrpc_sepol *sepol)
 {
        struct mdt_rec_create *rec;
        char *tmp;
@@ -252,7 +252,7 @@ void mdc_create_pack(struct req_capsule *pill, struct md_op_data *op_data,
                             op_data->op_file_encctx_size);
 
        /* pack SELinux policy info if any */
-       mdc_file_sepol_pack(pill);
+       mdc_file_sepol_pack(pill, sepol);
 }
 
 static inline __u64 mds_pack_open_flags(__u64 flags)
@@ -291,7 +291,7 @@ static inline __u64 mds_pack_open_flags(__u64 flags)
 /* packing of MDS records */
 void mdc_open_pack(struct req_capsule *pill, struct md_op_data *op_data,
                   umode_t mode, __u64 rdev, __u64 flags, const void *lmm,
-                  size_t lmmlen)
+                  size_t lmmlen, struct sptlrpc_sepol *sepol)
 {
        struct mdt_rec_create *rec;
        char *tmp;
@@ -335,7 +335,7 @@ void mdc_open_pack(struct req_capsule *pill, struct md_op_data *op_data,
                                     op_data->op_file_encctx_size);
 
                /* pack SELinux policy info if any */
-               mdc_file_sepol_pack(pill);
+               mdc_file_sepol_pack(pill, sepol);
        }
 
        if (lmm) {
@@ -468,7 +468,8 @@ void mdc_setattr_pack(struct req_capsule *pill, struct md_op_data *op_data,
        }
 }
 
-void mdc_unlink_pack(struct req_capsule *pill, struct md_op_data *op_data)
+void mdc_unlink_pack(struct req_capsule *pill, struct md_op_data *op_data,
+                    struct sptlrpc_sepol *sepol)
 {
        struct mdt_rec_unlink *rec;
 
@@ -493,10 +494,11 @@ void mdc_unlink_pack(struct req_capsule *pill, struct md_op_data *op_data)
        mdc_pack_name(pill, &RMF_NAME, op_data->op_name, op_data->op_namelen);
 
        /* pack SELinux policy info if any */
-       mdc_file_sepol_pack(pill);
+       mdc_file_sepol_pack(pill, sepol);
 }
 
-void mdc_link_pack(struct req_capsule *pill, struct md_op_data *op_data)
+void mdc_link_pack(struct req_capsule *pill, struct md_op_data *op_data,
+                  struct sptlrpc_sepol *sepol)
 {
        struct mdt_rec_link *rec;
 
@@ -519,7 +521,7 @@ void mdc_link_pack(struct req_capsule *pill, struct md_op_data *op_data)
        mdc_pack_name(pill, &RMF_NAME, op_data->op_name, op_data->op_namelen);
 
        /* pack SELinux policy info if any */
-       mdc_file_sepol_pack(pill);
+       mdc_file_sepol_pack(pill, sepol);
 }
 
 static void mdc_close_intent_pack(struct req_capsule *pill,
@@ -569,7 +571,8 @@ static void mdc_close_intent_pack(struct req_capsule *pill,
 
 void mdc_rename_pack(struct req_capsule *pill, struct md_op_data *op_data,
                     const char *old, size_t oldlen,
-                    const char *new, size_t newlen)
+                    const char *new, size_t newlen,
+                    struct sptlrpc_sepol *sepol)
 {
        struct mdt_rec_rename *rec;
 
@@ -596,7 +599,7 @@ void mdc_rename_pack(struct req_capsule *pill, struct md_op_data *op_data,
                mdc_pack_name(pill, &RMF_SYMTGT, new, newlen);
 
        /* pack SELinux policy info if any */
-       mdc_file_sepol_pack(pill);
+       mdc_file_sepol_pack(pill, sepol);
 }
 
 void mdc_migrate_pack(struct req_capsule *pill, struct md_op_data *op_data,
index 85bc771..12fd55c 100644 (file)
@@ -258,6 +258,7 @@ mdc_intent_open_pack(struct obd_export *exp, struct lookup_intent *it,
        int count = 0;
        enum ldlm_mode mode;
        int repsize, repsize_estimate;
+       struct sptlrpc_sepol *sepol;
        int rc;
 
        ENTRY;
@@ -327,20 +328,16 @@ mdc_intent_open_pack(struct obd_export *exp, struct lookup_intent *it,
                             op_data->op_file_encctx_size);
 
        /* get SELinux policy info if any */
-       rc = sptlrpc_get_sepol(req);
-       if (rc < 0) {
-               ptlrpc_request_free(req);
-               RETURN(ERR_PTR(rc));
-       }
+       sepol = sptlrpc_sepol_get(req);
+       if (IS_ERR(sepol))
+               GOTO(err_free_rq, rc = PTR_ERR(sepol));
+
        req_capsule_set_size(&req->rq_pill, &RMF_SELINUX_POL, RCL_CLIENT,
-                            strlen(req->rq_sepol) ?
-                            strlen(req->rq_sepol) + 1 : 0);
+                            sptlrpc_sepol_size(sepol));
 
        rc = ldlm_prep_enqueue_req(exp, req, &cancels, count);
-       if (rc < 0) {
-               ptlrpc_request_free(req);
-               RETURN(ERR_PTR(rc));
-       }
+       if (rc < 0)
+               GOTO(err_put_sepol, rc);
 
        spin_lock(&req->rq_lock);
        req->rq_replay = req->rq_import->imp_replayable;
@@ -352,7 +349,9 @@ mdc_intent_open_pack(struct obd_export *exp, struct lookup_intent *it,
 
        /* pack the intended request */
        mdc_open_pack(&req->rq_pill, op_data, it->it_create_mode, 0,
-                     it->it_flags, lmm, lmmsize);
+                     it->it_flags, lmm, lmmsize, sepol);
+
+       sptlrpc_sepol_put(sepol);
 
        req_capsule_set_size(&req->rq_pill, &RMF_MDT_MD, RCL_SERVER,
                             mdt_md_capsule_size);
@@ -432,6 +431,12 @@ mdc_intent_open_pack(struct obd_export *exp, struct lookup_intent *it,
         */
        req->rq_reqmsg->lm_repsize = repsize;
        RETURN(req);
+
+err_put_sepol:
+       sptlrpc_sepol_put(sepol);
+err_free_rq:
+       ptlrpc_request_free(req);
+       return ERR_PTR(rc);
 }
 
 #define GA_DEFAULT_EA_NAME_LEN  20
@@ -444,6 +449,7 @@ mdc_intent_getxattr_pack(struct obd_export *exp, struct lookup_intent *it,
 {
        struct ptlrpc_request *req;
        struct ldlm_intent *lit;
+       struct sptlrpc_sepol *sepol;
        int rc, count = 0;
        LIST_HEAD(cancels);
        u32 ea_vals_buf_size = GA_DEFAULT_EA_VAL_LEN * GA_DEFAULT_EA_NUM;
@@ -455,20 +461,16 @@ mdc_intent_getxattr_pack(struct obd_export *exp, struct lookup_intent *it,
                RETURN(ERR_PTR(-ENOMEM));
 
        /* get SELinux policy info if any */
-       rc = sptlrpc_get_sepol(req);
-       if (rc < 0) {
-               ptlrpc_request_free(req);
-               RETURN(ERR_PTR(rc));
-       }
+       sepol = sptlrpc_sepol_get(req);
+       if (IS_ERR(sepol))
+               GOTO(err_free_rq, rc = PTR_ERR(sepol));
+
        req_capsule_set_size(&req->rq_pill, &RMF_SELINUX_POL, RCL_CLIENT,
-                            strlen(req->rq_sepol) ?
-                            strlen(req->rq_sepol) + 1 : 0);
+                            sptlrpc_sepol_size(sepol));
 
        rc = ldlm_prep_enqueue_req(exp, req, &cancels, count);
-       if (rc) {
-               ptlrpc_request_free(req);
-               RETURN(ERR_PTR(rc));
-       }
+       if (rc)
+               GOTO(err_put_sepol, rc);
 
        /* pack the intent */
        lit = req_capsule_client_get(&req->rq_pill, &RMF_LDLM_INTENT);
@@ -498,7 +500,8 @@ mdc_intent_getxattr_pack(struct obd_export *exp, struct lookup_intent *it,
                      ea_vals_buf_size, -1, 0);
 
        /* get SELinux policy info if any */
-       mdc_file_sepol_pack(&req->rq_pill);
+       mdc_file_sepol_pack(&req->rq_pill, sepol);
+       sptlrpc_sepol_put(sepol);
 
        req_capsule_set_size(&req->rq_pill, &RMF_EADATA, RCL_SERVER,
                             GA_DEFAULT_EA_NAME_LEN * GA_DEFAULT_EA_NUM);
@@ -514,6 +517,12 @@ mdc_intent_getxattr_pack(struct obd_export *exp, struct lookup_intent *it,
        ptlrpc_request_set_replen(req);
 
        RETURN(req);
+
+err_put_sepol:
+       sptlrpc_sepol_put(sepol);
+err_free_rq:
+       ptlrpc_request_free(req);
+       RETURN(ERR_PTR(rc));
 }
 
 static struct ptlrpc_request *
index 5d61dbe..017f619 100644 (file)
@@ -164,6 +164,7 @@ int mdc_create(struct obd_export *exp, struct md_op_data *op_data,
                struct ptlrpc_request **request)
 {
        struct ptlrpc_request *req;
+       struct sptlrpc_sepol *sepol;
        int level, rc;
        int count, resends = 0;
        struct obd_import *import = exp->exp_obd->u.cli.cl_import;
@@ -214,27 +215,25 @@ rebuild:
                             op_data->op_file_encctx_size);
 
        /* get SELinux policy info if any */
-       rc = sptlrpc_get_sepol(req);
-       if (rc < 0) {
-               ptlrpc_request_free(req);
-               RETURN(rc);
-       }
+       sepol = sptlrpc_sepol_get(req);
+       if (IS_ERR(sepol))
+               GOTO(err_free_rq, rc = PTR_ERR(sepol));
+
        req_capsule_set_size(&req->rq_pill, &RMF_SELINUX_POL, RCL_CLIENT,
-                            strlen(req->rq_sepol) ?
-                            strlen(req->rq_sepol) + 1 : 0);
+                            sptlrpc_sepol_size(sepol));
 
        rc = mdc_prep_elc_req(exp, req, MDS_REINT, &cancels, count);
-       if (rc) {
-               ptlrpc_request_free(req);
-               RETURN(rc);
-       }
+       if (rc)
+               GOTO(err_put_sepol, rc);
 
        /*
         * mdc_create_pack() fills msg->bufs[1] with name and msg->bufs[2] with
         * tgt, for symlinks or lov MD data.
         */
        mdc_create_pack(&req->rq_pill, op_data, data, datalen, mode, uid,
-                       gid, cap_effective, rdev);
+                       gid, cap_effective, rdev, sepol);
+
+       sptlrpc_sepol_put(sepol);
 
        req_capsule_set_size(&req->rq_pill, &RMF_MDT_MD, RCL_SERVER,
                             exp->exp_obd->u.cli.cl_default_mds_easize);
@@ -312,19 +311,28 @@ rebuild:
        }
 
        *request = req;
+
+       RETURN(rc);
+
+err_put_sepol:
+       sptlrpc_sepol_put(sepol);
+err_free_rq:
+       ptlrpc_request_free(req);
+
        RETURN(rc);
 }
 
 int mdc_unlink(struct obd_export *exp, struct md_op_data *op_data,
-               struct ptlrpc_request **request)
+              struct ptlrpc_request **request)
 {
        LIST_HEAD(cancels);
-        struct obd_device *obd = class_exp2obd(exp);
-        struct ptlrpc_request *req = *request;
-        int count = 0, rc;
-        ENTRY;
+       struct obd_device *obd = class_exp2obd(exp);
+       struct ptlrpc_request *req = *request;
+       struct sptlrpc_sepol *sepol;
+       int count = 0, rc;
+       ENTRY;
 
-        LASSERT(req == NULL);
+       LASSERT(req == NULL);
 
        if ((op_data->op_flags & MF_MDC_CANCEL_FID1) &&
            (fid_is_sane(&op_data->op_fid1)))
@@ -340,99 +348,110 @@ int mdc_unlink(struct obd_export *exp, struct md_op_data *op_data,
                                                 CLI_DIRTY_DATA ?
                                                 MDS_INODELOCK_ELC :
                                                 MDS_INODELOCK_FULL);
-        req = ptlrpc_request_alloc(class_exp2cliimp(exp),
-                                   &RQF_MDS_REINT_UNLINK);
-        if (req == NULL) {
-                ldlm_lock_list_put(&cancels, l_bl_ast, count);
-                RETURN(-ENOMEM);
-        }
+       req = ptlrpc_request_alloc(class_exp2cliimp(exp),
+                                  &RQF_MDS_REINT_UNLINK);
+       if (req == NULL) {
+               ldlm_lock_list_put(&cancels, l_bl_ast, count);
+               RETURN(-ENOMEM);
+       }
 
-        req_capsule_set_size(&req->rq_pill, &RMF_NAME, RCL_CLIENT,
-                             op_data->op_namelen + 1);
+       req_capsule_set_size(&req->rq_pill, &RMF_NAME, RCL_CLIENT,
+                            op_data->op_namelen + 1);
 
        /* get SELinux policy info if any */
-       rc = sptlrpc_get_sepol(req);
-       if (rc < 0) {
-               ptlrpc_request_free(req);
-               RETURN(rc);
-       }
+       sepol = sptlrpc_sepol_get(req);
+       if (IS_ERR(sepol))
+               GOTO(err_free_rq, rc = PTR_ERR(sepol));
+
        req_capsule_set_size(&req->rq_pill, &RMF_SELINUX_POL, RCL_CLIENT,
-                            strlen(req->rq_sepol) ?
-                            strlen(req->rq_sepol) + 1 : 0);
+                            sptlrpc_sepol_size(sepol));
 
        rc = mdc_prep_elc_req(exp, req, MDS_REINT, &cancels, count);
-       if (rc) {
-               ptlrpc_request_free(req);
-               RETURN(rc);
-       }
+       if (rc)
+               GOTO(err_put_sepol, rc);
 
-       mdc_unlink_pack(&req->rq_pill, op_data);
+       mdc_unlink_pack(&req->rq_pill, op_data, sepol);
+       sptlrpc_sepol_put(sepol);
 
        req_capsule_set_size(&req->rq_pill, &RMF_MDT_MD, RCL_SERVER,
                             obd->u.cli.cl_default_mds_easize);
        ptlrpc_request_set_replen(req);
 
-        *request = req;
+       *request = req;
 
        rc = mdc_reint(req, LUSTRE_IMP_FULL);
-        if (rc == -ERESTARTSYS)
-                rc = 0;
-        RETURN(rc);
+       if (rc == -ERESTARTSYS)
+               rc = 0;
+
+       RETURN(rc);
+
+err_put_sepol:
+       sptlrpc_sepol_put(sepol);
+err_free_rq:
+       ptlrpc_request_free(req);
+
+       RETURN(rc);
 }
 
 int mdc_link(struct obd_export *exp, struct md_op_data *op_data,
-             struct ptlrpc_request **request)
+            struct ptlrpc_request **request)
 {
        LIST_HEAD(cancels);
-        struct ptlrpc_request *req;
-        int count = 0, rc;
-        ENTRY;
+       struct ptlrpc_request *req;
+       struct sptlrpc_sepol *sepol;
+       int count = 0, rc;
+       ENTRY;
 
-        if ((op_data->op_flags & MF_MDC_CANCEL_FID2) &&
-            (fid_is_sane(&op_data->op_fid2)))
-                count = mdc_resource_get_unused(exp, &op_data->op_fid2,
-                                                &cancels, LCK_EX,
-                                                MDS_INODELOCK_UPDATE);
-        if ((op_data->op_flags & MF_MDC_CANCEL_FID1) &&
-            (fid_is_sane(&op_data->op_fid1)))
-                count += mdc_resource_get_unused(exp, &op_data->op_fid1,
-                                                 &cancels, LCK_EX,
-                                                 MDS_INODELOCK_UPDATE);
-
-        req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_MDS_REINT_LINK);
-        if (req == NULL) {
-                ldlm_lock_list_put(&cancels, l_bl_ast, count);
-                RETURN(-ENOMEM);
-        }
+       if ((op_data->op_flags & MF_MDC_CANCEL_FID2) &&
+           (fid_is_sane(&op_data->op_fid2)))
+               count = mdc_resource_get_unused(exp, &op_data->op_fid2,
+                                               &cancels, LCK_EX,
+                                               MDS_INODELOCK_UPDATE);
+       if ((op_data->op_flags & MF_MDC_CANCEL_FID1) &&
+           (fid_is_sane(&op_data->op_fid1)))
+               count += mdc_resource_get_unused(exp, &op_data->op_fid1,
+                                                &cancels, LCK_EX,
+                                                MDS_INODELOCK_UPDATE);
 
-        req_capsule_set_size(&req->rq_pill, &RMF_NAME, RCL_CLIENT,
-                             op_data->op_namelen + 1);
+       req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_MDS_REINT_LINK);
+       if (req == NULL) {
+               ldlm_lock_list_put(&cancels, l_bl_ast, count);
+               RETURN(-ENOMEM);
+       }
+
+       req_capsule_set_size(&req->rq_pill, &RMF_NAME, RCL_CLIENT,
+                            op_data->op_namelen + 1);
 
        /* get SELinux policy info if any */
-       rc = sptlrpc_get_sepol(req);
-       if (rc < 0) {
-               ptlrpc_request_free(req);
-               RETURN(rc);
-       }
+       sepol = sptlrpc_sepol_get(req);
+       if (IS_ERR(sepol))
+               GOTO(err_free_rq, rc = PTR_ERR(sepol));
+
        req_capsule_set_size(&req->rq_pill, &RMF_SELINUX_POL, RCL_CLIENT,
-                            strlen(req->rq_sepol) ?
-                            strlen(req->rq_sepol) + 1 : 0);
+                            sptlrpc_sepol_size(sepol));
 
        rc = mdc_prep_elc_req(exp, req, MDS_REINT, &cancels, count);
-       if (rc) {
-               ptlrpc_request_free(req);
-               RETURN(rc);
-       }
+       if (rc)
+               GOTO(err_put_sepol, rc);
+
+       mdc_link_pack(&req->rq_pill, op_data, sepol);
+       sptlrpc_sepol_put(sepol);
 
-       mdc_link_pack(&req->rq_pill, op_data);
        ptlrpc_request_set_replen(req);
 
        rc = mdc_reint(req, LUSTRE_IMP_FULL);
-        *request = req;
-        if (rc == -ERESTARTSYS)
-                rc = 0;
+       *request = req;
+       if (rc == -ERESTARTSYS)
+               rc = 0;
+
+       RETURN(rc);
+
+err_put_sepol:
+       sptlrpc_sepol_put(sepol);
+err_free_rq:
+       ptlrpc_request_free(req);
 
-        RETURN(rc);
+       RETURN(rc);
 }
 
 int mdc_rename(struct obd_export *exp, struct md_op_data *op_data,
@@ -442,6 +461,7 @@ int mdc_rename(struct obd_export *exp, struct md_op_data *op_data,
        LIST_HEAD(cancels);
        struct obd_device *obd = exp->exp_obd;
        struct ptlrpc_request *req;
+       struct sptlrpc_sepol *sepol;
        int count = 0, rc;
 
        ENTRY;
@@ -482,20 +502,16 @@ int mdc_rename(struct obd_export *exp, struct md_op_data *op_data,
                                     op_data->op_data_size);
 
        /* get SELinux policy info if any */
-       rc = sptlrpc_get_sepol(req);
-       if (rc < 0) {
-               ptlrpc_request_free(req);
-               RETURN(rc);
-       }
+       sepol = sptlrpc_sepol_get(req);
+       if (IS_ERR(sepol))
+               GOTO(err_free_rq, rc = PTR_ERR(sepol));
+
        req_capsule_set_size(&req->rq_pill, &RMF_SELINUX_POL, RCL_CLIENT,
-                            strlen(req->rq_sepol) ?
-                            strlen(req->rq_sepol) + 1 : 0);
+                            sptlrpc_sepol_size(sepol));
 
        rc = mdc_prep_elc_req(exp, req, MDS_REINT, &cancels, count);
-       if (rc) {
-               ptlrpc_request_free(req);
-               RETURN(rc);
-       }
+       if (rc)
+               GOTO(err_put_sepol, rc);
 
        if (exp_connect_cancelset(exp) && req)
                ldlm_cli_cancel_list(&cancels, count, req, 0);
@@ -504,7 +520,9 @@ int mdc_rename(struct obd_export *exp, struct md_op_data *op_data,
                mdc_migrate_pack(&req->rq_pill, op_data, old, oldlen);
        else
                mdc_rename_pack(&req->rq_pill, op_data, old, oldlen,
-                               new, newlen);
+                               new, newlen, sepol);
+
+       sptlrpc_sepol_put(sepol);
 
        req_capsule_set_size(&req->rq_pill, &RMF_MDT_MD, RCL_SERVER,
                             obd->u.cli.cl_default_mds_easize);
@@ -516,6 +534,13 @@ int mdc_rename(struct obd_export *exp, struct md_op_data *op_data,
                rc = 0;
 
        RETURN(rc);
+
+err_put_sepol:
+       sptlrpc_sepol_put(sepol);
+err_free_rq:
+       ptlrpc_request_free(req);
+
+       RETURN(rc);
 }
 
 int mdc_file_resync(struct obd_export *exp, struct md_op_data *op_data)
index a54260b..5ecf780 100644 (file)
@@ -352,16 +352,17 @@ static int mdc_xattr_common(struct obd_export *exp,const struct req_format *fmt,
                            int input_size, int output_size, int flags,
                            __u32 suppgid, struct ptlrpc_request **request)
 {
-        struct ptlrpc_request *req;
-        int   xattr_namelen = 0;
-        char *tmp;
-        int   rc;
-        ENTRY;
+       struct ptlrpc_request *req;
+       struct sptlrpc_sepol *sepol;
+       int   xattr_namelen = 0;
+       char *tmp;
+       int   rc;
+       ENTRY;
 
-        *request = NULL;
-        req = ptlrpc_request_alloc(class_exp2cliimp(exp), fmt);
-        if (req == NULL)
-                RETURN(-ENOMEM);
+       *request = NULL;
+       req = ptlrpc_request_alloc(class_exp2cliimp(exp), fmt);
+       if (req == NULL)
+               RETURN(-ENOMEM);
 
        if (xattr_name) {
                xattr_namelen = strlen(xattr_name) + 1;
@@ -374,14 +375,12 @@ static int mdc_xattr_common(struct obd_export *exp,const struct req_format *fmt,
                             input_size);
 
        /* get SELinux policy info if any */
-       rc = sptlrpc_get_sepol(req);
-       if (rc < 0) {
-               ptlrpc_request_free(req);
-               RETURN(rc);
-       }
+       sepol = sptlrpc_sepol_get(req);
+       if (IS_ERR(sepol))
+               GOTO(err_free_rq, rc = PTR_ERR(sepol));
+
        req_capsule_set_size(&req->rq_pill, &RMF_SELINUX_POL, RCL_CLIENT,
-                            strlen(req->rq_sepol) ?
-                            strlen(req->rq_sepol) + 1 : 0);
+                            sptlrpc_sepol_size(sepol));
 
        /* Flush local XATTR locks to get rid of a possible cancel RPC */
        if (opcode == MDS_REINT && fid_is_sane(fid) &&
@@ -399,16 +398,12 @@ static int mdc_xattr_common(struct obd_export *exp,const struct req_format *fmt,
                                                MDS_INODELOCK_XATTR);
 
                rc = mdc_prep_elc_req(exp, req, MDS_REINT, &cancels, count);
-               if (rc) {
-                       ptlrpc_request_free(req);
-                       RETURN(rc);
-               }
+               if (rc)
+                       GOTO(err_put_sepol, rc);
        } else {
                rc = ptlrpc_request_pack(req, LUSTRE_MDS_VERSION, opcode);
-               if (rc) {
-                       ptlrpc_request_free(req);
-                       RETURN(rc);
-               }
+               if (rc)
+                       GOTO(err_put_sepol, rc);
        }
 
        if (opcode == MDS_REINT) {
@@ -437,36 +432,44 @@ static int mdc_xattr_common(struct obd_export *exp,const struct req_format *fmt,
                req->rq_request_portal = MDS_READPAGE_PORTAL;
        }
 
-        if (xattr_name) {
-                tmp = req_capsule_client_get(&req->rq_pill, &RMF_NAME);
-                memcpy(tmp, xattr_name, xattr_namelen);
-        }
-        if (input_size) {
-                tmp = req_capsule_client_get(&req->rq_pill, &RMF_EADATA);
-                memcpy(tmp, input, input_size);
-        }
+       if (xattr_name) {
+               tmp = req_capsule_client_get(&req->rq_pill, &RMF_NAME);
+               memcpy(tmp, xattr_name, xattr_namelen);
+       }
+       if (input_size) {
+               tmp = req_capsule_client_get(&req->rq_pill, &RMF_EADATA);
+               memcpy(tmp, input, input_size);
+       }
 
-       mdc_file_sepol_pack(&req->rq_pill);
+       mdc_file_sepol_pack(&req->rq_pill, sepol);
+       sptlrpc_sepol_put(sepol);
 
-        if (req_capsule_has_field(&req->rq_pill, &RMF_EADATA, RCL_SERVER))
-                req_capsule_set_size(&req->rq_pill, &RMF_EADATA,
-                                     RCL_SERVER, output_size);
-        ptlrpc_request_set_replen(req);
+       if (req_capsule_has_field(&req->rq_pill, &RMF_EADATA, RCL_SERVER))
+               req_capsule_set_size(&req->rq_pill, &RMF_EADATA,
+                                    RCL_SERVER, output_size);
+       ptlrpc_request_set_replen(req);
 
-        /* make rpc */
-        if (opcode == MDS_REINT)
+       /* make rpc */
+       if (opcode == MDS_REINT)
                ptlrpc_get_mod_rpc_slot(req);
 
-        rc = ptlrpc_queue_wait(req);
+       rc = ptlrpc_queue_wait(req);
 
        if (opcode == MDS_REINT)
                ptlrpc_put_mod_rpc_slot(req);
 
-        if (rc)
-                ptlrpc_req_finished(req);
-        else
-                *request = req;
-        RETURN(rc);
+       if (rc)
+               ptlrpc_req_finished(req);
+       else
+               *request = req;
+       RETURN(rc);
+
+err_put_sepol:
+       sptlrpc_sepol_put(sepol);
+err_free_rq:
+       ptlrpc_request_free(req);
+       RETURN(rc);
+
 }
 
 static int mdc_setxattr(struct obd_export *exp, const struct lu_fid *fid,
index 3530607..a4b5948 100644 (file)
@@ -611,6 +611,7 @@ void gss_sec_destroy_kr(struct ptlrpc_sec *sec)
 
         CDEBUG(D_SEC, "destroy %s@%p\n", sec->ps_policy->sp_name, sec);
 
+       LASSERT(atomic_read(&sec->ps_nctx) == 0);
        LASSERT(hlist_empty(&gsec_kr->gsk_clist));
         LASSERT(gsec_kr->gsk_root_ctx == NULL);
 
index 28cea38..cfc23f1 100644 (file)
@@ -1106,9 +1106,6 @@ int gss_sec_create_common(struct gss_sec *gsec,
        sec->ps_import = class_import_get(imp);
        spin_lock_init(&sec->ps_lock);
        INIT_LIST_HEAD(&sec->ps_gc_list);
-       sec->ps_sepol_mtime = ktime_set(0, 0);
-       sec->ps_sepol_checknext = ktime_set(0, 0);
-       sec->ps_sepol[0] = '\0';
 
         if (!svcctx) {
                 sec->ps_gc_interval = GSS_GC_INTERVAL;
index 3a6bcac..334ef29 100644 (file)
@@ -656,6 +656,7 @@ int ptlrpc_connect_import_locked(struct obd_import *imp)
        int set_transno = 0;
        __u64 committed_before_reconnect = 0;
        struct ptlrpc_request *request;
+       struct sptlrpc_sepol *sepol;
        struct obd_connect_data ocd;
        char *bufs[] = { NULL,
                         obd2cli_tgt(imp->imp_obd),
@@ -727,20 +728,21 @@ int ptlrpc_connect_import_locked(struct obd_import *imp)
                GOTO(out, rc = -ENOMEM);
 
        /* get SELinux policy info if any */
-       rc = sptlrpc_get_sepol(request);
-       if (rc < 0) {
+       sepol = sptlrpc_sepol_get(request);
+       if (IS_ERR(sepol)) {
                ptlrpc_request_free(request);
-               GOTO(out, rc);
+               GOTO(out, rc = PTR_ERR(sepol));
        }
 
-       bufs[5] = request->rq_sepol;
+       bufs[5] = sepol->ssp_sepol;
 
        req_capsule_set_size(&request->rq_pill, &RMF_SELINUX_POL, RCL_CLIENT,
-                            strlen(request->rq_sepol) ?
-                            strlen(request->rq_sepol) + 1 : 0);
+                            sptlrpc_sepol_size(sepol));
 
        rc = ptlrpc_request_bufs_pack(request, LUSTRE_OBD_VERSION,
                                      imp->imp_connect_op, bufs, NULL);
+
+       sptlrpc_sepol_put(sepol);
        if (rc) {
                ptlrpc_request_free(request);
                GOTO(out, rc);
index 50905f2..725a71f 100644 (file)
@@ -1290,13 +1290,21 @@ static int sec_cop_flush_ctx_cache(struct ptlrpc_sec *sec, uid_t uid,
 static void sec_cop_destroy_sec(struct ptlrpc_sec *sec)
 {
        struct ptlrpc_sec_policy *policy = sec->ps_policy;
+       struct sptlrpc_sepol *sepol;
 
        LASSERT(atomic_read(&sec->ps_refcount) == 0);
-       LASSERT(atomic_read(&sec->ps_nctx) == 0);
        LASSERT(policy->sp_cops->destroy_sec);
 
        CDEBUG(D_SEC, "%s@%p: being destroyed\n", sec->ps_policy->sp_name, sec);
 
+       spin_lock(&sec->ps_lock);
+       sec->ps_sepol_checknext = ktime_set(0, 0);
+       sepol = rcu_dereference_protected(sec->ps_sepol, 1);
+       rcu_assign_pointer(sec->ps_sepol, NULL);
+       spin_unlock(&sec->ps_lock);
+
+       sptlrpc_sepol_put(sepol);
+
        policy->sp_cops->destroy_sec(sec);
        sptlrpc_policy_put(policy);
 }
@@ -1775,6 +1783,7 @@ int sptlrpc_svc_install_rvs_ctx(struct obd_import *imp,
        return policy->sp_sops->install_rctx(imp, ctx);
 }
 
+
 /* Get SELinux policy info from userspace */
 static int sepol_helper(struct obd_import *imp)
 {
@@ -1791,6 +1800,7 @@ static int sepol_helper(struct obd_import *imp)
                [8] = mode_str,     /* enforcing mode */
                [9] = NULL
        };
+       struct sptlrpc_sepol *sepol;
        char *envp[] = {
                [0] = "HOME=/",
                [1] = "PATH=/sbin:/usr/sbin",
@@ -1800,29 +1810,31 @@ static int sepol_helper(struct obd_import *imp)
        int rc = 0;
 
        if (imp == NULL || imp->imp_obd == NULL ||
-           imp->imp_obd->obd_type == NULL) {
-               rc = -EINVAL;
+           imp->imp_obd->obd_type == NULL)
+               RETURN(-EINVAL);
+
+       argv[2] = (char *)imp->imp_obd->obd_type->typ_name;
+       argv[4] = imp->imp_obd->obd_name;
+
+       rcu_read_lock();
+       sepol = rcu_dereference(imp->imp_sec->ps_sepol);
+       if (!sepol) {
+               /* ps_sepol has not been initialized */
+               argv[5] = NULL;
+               argv[7] = NULL;
        } else {
-               argv[2] = (char *)imp->imp_obd->obd_type->typ_name;
-               argv[4] = imp->imp_obd->obd_name;
-               spin_lock(&imp->imp_sec->ps_lock);
-               if (ktime_to_ns(imp->imp_sec->ps_sepol_mtime) == 0 &&
-                   imp->imp_sec->ps_sepol[0] == '\0') {
-                       /* ps_sepol has not been initialized */
-                       argv[5] = NULL;
-                       argv[7] = NULL;
-               } else {
-                       time64_t mtime_ms;
+               time64_t mtime_ms;
 
-                       mtime_ms = ktime_to_ms(imp->imp_sec->ps_sepol_mtime);
-                       snprintf(mtime_str, sizeof(mtime_str), "%lld",
-                                mtime_ms / MSEC_PER_SEC);
-                       mode_str[0] = imp->imp_sec->ps_sepol[0];
-               }
-               spin_unlock(&imp->imp_sec->ps_lock);
-               ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
-               rc = ret>>8;
+               mtime_ms = ktime_to_ms(sepol->ssp_mtime);
+               snprintf(mtime_str, sizeof(mtime_str), "%lld",
+                        mtime_ms / MSEC_PER_SEC);
+               if (sepol->ssp_sepol_size > 1)
+                       mode_str[0] = sepol->ssp_sepol[0];
        }
+       rcu_read_unlock();
+
+       ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
+       rc = ret>>8;
 
        return rc;
 }
@@ -1861,45 +1873,78 @@ setnext:
        return 1;
 }
 
-int sptlrpc_get_sepol(struct ptlrpc_request *req)
+static void sptlrpc_sepol_release(struct kref *ref)
+{
+       struct sptlrpc_sepol *p = container_of(ref, struct sptlrpc_sepol,
+                                             ssp_ref);
+       kfree_rcu(p, ssp_rcu);
+}
+
+void sptlrpc_sepol_put(struct sptlrpc_sepol *pol)
+{
+       if (!pol)
+               return;
+       kref_put(&pol->ssp_ref, sptlrpc_sepol_release);
+}
+EXPORT_SYMBOL(sptlrpc_sepol_put);
+
+struct sptlrpc_sepol *sptlrpc_sepol_get_cached(struct ptlrpc_sec *imp_sec)
+{
+       struct sptlrpc_sepol *p;
+
+retry:
+       rcu_read_lock();
+       p = rcu_dereference(imp_sec->ps_sepol);
+       if (p && !kref_get_unless_zero(&p->ssp_ref)) {
+               rcu_read_unlock();
+               goto retry;
+       }
+       rcu_read_unlock();
+
+       return p;
+}
+EXPORT_SYMBOL(sptlrpc_sepol_get_cached);
+
+struct sptlrpc_sepol *sptlrpc_sepol_get(struct ptlrpc_request *req)
 {
        struct ptlrpc_sec *imp_sec = req->rq_import->imp_sec;
+       struct sptlrpc_sepol *out;
        int rc = 0;
 
        ENTRY;
 
-       (req->rq_sepol)[0] = '\0';
-
 #ifndef HAVE_SELINUX
        if (unlikely(send_sepol != 0))
                CDEBUG(D_SEC,
                       "Client cannot report SELinux status, it was not built against libselinux.\n");
-       RETURN(0);
+       RETURN(NULL);
 #endif
 
        if (send_sepol == 0)
-               RETURN(0);
+               RETURN(NULL);
 
        if (imp_sec == NULL)
-               RETURN(-EINVAL);
+               RETURN(ERR_PTR(-EINVAL));
 
        /* Retrieve SELinux status info */
        if (sptlrpc_sepol_needs_check(imp_sec))
                rc = sepol_helper(req->rq_import);
-       if (likely(rc == 0)) {
-               spin_lock(&imp_sec->ps_lock);
-               memcpy(req->rq_sepol, imp_sec->ps_sepol,
-                      sizeof(req->rq_sepol));
-               spin_unlock(&imp_sec->ps_lock);
-       } else if (rc == -ENODEV) {
+
+       if (unlikely(rc == -ENODEV)) {
                CDEBUG(D_SEC,
                       "Client cannot report SELinux status, SELinux is disabled.\n");
-               rc = 0;
+               RETURN(NULL);
        }
+       if (unlikely(rc))
+               RETURN(ERR_PTR(rc));
 
-       RETURN(rc);
+       out = sptlrpc_sepol_get_cached(imp_sec);
+       if (!out)
+               RETURN(ERR_PTR(-ENODATA));
+
+       RETURN(out);
 }
-EXPORT_SYMBOL(sptlrpc_get_sepol);
+EXPORT_SYMBOL(sptlrpc_sepol_get);
 
 /*
  * server side security
index 44ad372..597036a 100644 (file)
@@ -135,6 +135,62 @@ out:
 
 LDEBUGFS_SEQ_FOPS_RO(sptlrpc_ctxs_lprocfs);
 
+static inline
+bool sptlrpc_sepol_update_needed(struct ptlrpc_sec *imp_sec,
+                                ktime_t mtime, char *pol, size_t pol_len)
+{
+       struct sptlrpc_sepol *old;
+       bool rc;
+
+       rcu_read_lock();
+       old = rcu_dereference(imp_sec->ps_sepol);
+       if (!old)
+               rc = true;
+       else if (!kref_read(&old->ssp_ref))
+               rc = false;
+       else if (ktime_compare(old->ssp_mtime, mtime) != 0)
+               rc = true;
+       else
+               rc = false;
+       rcu_read_unlock();
+
+       return rc;
+}
+static int sptlrpc_sepol_update(struct obd_import *imp,
+                               ktime_t mtime, char *pol, size_t pol_len)
+{
+       struct sptlrpc_sepol *old;
+       struct sptlrpc_sepol *new;
+       struct ptlrpc_sec *imp_sec;
+       int rc = 0;
+
+       imp_sec = sptlrpc_import_sec_ref(imp);
+       if (!imp_sec)
+               RETURN(-ENODEV);
+
+       if (!sptlrpc_sepol_update_needed(imp_sec, mtime, pol, pol_len))
+               GOTO(out, rc);
+
+       new = kmalloc(sizeof(typeof(*new)) + pol_len + 1, GFP_KERNEL);
+       if (!new)
+               GOTO(out, rc = -ENOMEM);
+
+       kref_init(&new->ssp_ref);
+       new->ssp_sepol_size = pol_len + 1;
+       new->ssp_mtime = mtime;
+       strlcpy(new->ssp_sepol, pol, new->ssp_sepol_size);
+
+       spin_lock(&imp_sec->ps_lock);
+       old = rcu_dereference_protected(imp_sec->ps_sepol, 1);
+       rcu_assign_pointer(imp_sec->ps_sepol, new);
+       spin_unlock(&imp_sec->ps_lock);
+       sptlrpc_sepol_put(old);
+out:
+       sptlrpc_sec_put(imp_sec);
+
+       return rc;
+}
+
 #if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 16, 53, 0)
 static ssize_t sepol_seq_write_old(struct obd_device *obd,
                                   const char __user *buffer, size_t count)
@@ -142,7 +198,7 @@ static ssize_t sepol_seq_write_old(struct obd_device *obd,
        struct client_obd *cli = &obd->u.cli;
        struct obd_import *imp = cli->cl_import;
        struct sepol_downcall_data_old *param;
-       size_t maxlen = sizeof(imp->imp_sec->ps_sepol);
+       size_t maxlen = LUSTRE_NODEMAP_SEPOL_LENGTH + 1;
        size_t size = sizeof(*param);
        size_t maxparam = sizeof(*param) + maxlen;
        int len;
@@ -189,12 +245,8 @@ static ssize_t sepol_seq_write_old(struct obd_device *obd,
                GOTO(out, rc);
        }
 
-       spin_lock(&imp->imp_sec->ps_lock);
-       memcpy(imp->imp_sec->ps_sepol, param->sdd_sepol, len);
-       imp->imp_sec->ps_sepol[len + 1] = '\0';
-       imp->imp_sec->ps_sepol_mtime = ktime_set(param->sdd_sepol_mtime, 0);
-       spin_unlock(&imp->imp_sec->ps_lock);
-
+       rc = sptlrpc_sepol_update(imp, ktime_set(param->sdd_sepol_mtime, 0),
+                                 param->sdd_sepol, len);
 out:
        OBD_FREE(param, maxparam);
 
@@ -211,7 +263,7 @@ ldebugfs_sptlrpc_sepol_seq_write(struct file *file, const char __user *buffer,
        struct client_obd *cli = &obd->u.cli;
        struct obd_import *imp = cli->cl_import;
        struct sepol_downcall_data *param;
-       size_t maxlen = sizeof(imp->imp_sec->ps_sepol);
+       size_t maxlen = LUSTRE_NODEMAP_SEPOL_LENGTH + 1;
        size_t size = sizeof(*param);
        size_t maxparam = size + maxlen;
        int len;
@@ -274,18 +326,44 @@ ldebugfs_sptlrpc_sepol_seq_write(struct file *file, const char __user *buffer,
                GOTO(out, rc);
        }
 
-       spin_lock(&imp->imp_sec->ps_lock);
-       memcpy(imp->imp_sec->ps_sepol, param->sdd_sepol, len);
-       imp->imp_sec->ps_sepol[len + 1] = '\0';
-       imp->imp_sec->ps_sepol_mtime = ktime_set(param->sdd_sepol_mtime, 0);
-       spin_unlock(&imp->imp_sec->ps_lock);
-
+       rc = sptlrpc_sepol_update(imp, ktime_set(param->sdd_sepol_mtime, 0),
+                                 param->sdd_sepol, len);
 out:
        OBD_FREE(param, maxparam);
 
        return rc ?: count;
 }
-LDEBUGFS_FOPS_WR_ONLY(srpc, sptlrpc_sepol);
+
+static int lprocfs_sptlrpc_sepol_seq_show(struct seq_file *seq, void *v)
+{
+       struct obd_device *obd = seq->private;
+       struct client_obd *cli = &obd->u.cli;
+       struct obd_import *imp = cli->cl_import;
+       struct ptlrpc_sec *imp_sec;
+       struct sptlrpc_sepol *sepol;
+       struct timespec64 ts;
+       int rc = 0;
+
+       imp_sec = sptlrpc_import_sec_ref(imp);
+       if (!imp_sec)
+               RETURN(-ENODEV);
+
+       rcu_read_lock();
+       sepol = rcu_dereference(imp->imp_sec->ps_sepol);
+       if (sepol) {
+               ts = ktime_to_timespec64(sepol->ssp_mtime);
+               seq_printf(seq, "mtime: %lld\n", (long long int) ts.tv_sec);
+               seq_printf(seq, "sepol: %.*s\n",
+                          sepol->ssp_sepol_size, sepol->ssp_sepol);
+       } else {
+               seq_puts(seq, "uninitialized\n");
+       }
+       rcu_read_unlock();
+       sptlrpc_sec_put(imp_sec);
+
+       return rc;
+}
+LDEBUGFS_SEQ_FOPS_RW_TYPE(srpc, sptlrpc_sepol);
 
 int sptlrpc_lprocfs_cliobd_attach(struct obd_device *obd)
 {
index f56c356..b965cb4 100644 (file)
@@ -115,9 +115,13 @@ struct ptlrpc_sec *null_create_sec(struct obd_import *imp,
 
        /*
         * general layer has take a module reference for us, because we never
-        * really destroy the sec, simply release the reference here.
+        * really destroy the sec, take only 1 module reference for all the
+        * imports. This reference will be released by sec_cop_destroy_sec().
+        * The additional ps_refcount will be released in null_kill_sec().
         */
-       sptlrpc_policy_put(&null_policy);
+       if (atomic_inc_return(&null_sec.ps_refcount) != 1)
+               sptlrpc_policy_put(&null_policy);
+
        return &null_sec;
 }
 
@@ -128,6 +132,13 @@ void null_destroy_sec(struct ptlrpc_sec *sec)
 }
 
 static
+void null_kill_sec(struct ptlrpc_sec *sec)
+{
+       /* release the ref taken by null_create_sec() */
+       sptlrpc_sec_put(sec);
+}
+
+static
 struct ptlrpc_cli_ctx *null_lookup_ctx(struct ptlrpc_sec *sec,
                                       struct vfs_cred *vcred,
                                       int create, int remove_dead)
@@ -372,6 +383,7 @@ static struct ptlrpc_ctx_ops null_ctx_ops = {
 static struct ptlrpc_sec_cops null_sec_cops = {
        .create_sec             = null_create_sec,
        .destroy_sec            = null_destroy_sec,
+       .kill_sec               = null_kill_sec,
        .lookup_ctx             = null_lookup_ctx,
        .flush_ctx_cache        = null_flush_ctx_cache,
        .alloc_reqbuf           = null_alloc_reqbuf,
@@ -401,7 +413,7 @@ static void null_init_internal(void)
        static HLIST_HEAD(__list);
 
        null_sec.ps_policy = &null_policy;
-       atomic_set(&null_sec.ps_refcount, 1);   /* always busy */
+       atomic_set(&null_sec.ps_refcount, 0);
        null_sec.ps_id = -1;
        null_sec.ps_import = NULL;
        null_sec.ps_flvr.sf_rpc = SPTLRPC_FLVR_NULL;