From: Etienne AUJAMES Date: Thu, 26 Oct 2023 19:28:55 +0000 (+0200) Subject: LU-16566 sptlrpc: remove rq_sepol from ptlrpc_request X-Git-Tag: 2.15.61~76 X-Git-Url: https://git.whamcloud.com/gitweb?a=commitdiff_plain;h=3f70481c93dcabbb30267608a0054f4d7092e0db;p=fs%2Flustre-release.git LU-16566 sptlrpc: remove rq_sepol from ptlrpc_request 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 Change-Id: I80fb76c97885c4b2987eb7f91a9bfe6e0e6e6c70 Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/52845 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Oleg Drokin Reviewed-by: Sebastien Buisson Reviewed-by: Andreas Dilger --- diff --git a/lustre/include/lustre_net.h b/lustre/include/lustre_net.h index 4b12182..33063ee 100644 --- a/lustre/include/lustre_net.h +++ b/lustre/include/lustre_net.h @@ -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: - * ::: - */ - char rq_sepol[LUSTRE_NODEMAP_SEPOL_LENGTH + 1]; - /* client/server security flags */ unsigned int rq_ctx_init:1, /* context initiation */ diff --git a/lustre/include/lustre_sec.h b/lustre/include/lustre_sec.h index 44e6dd6..936939e 100644 --- a/lustre/include/lustre_sec.h +++ b/lustre/include/lustre_sec.h @@ -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: + * ::: + */ + __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: - * ::: - */ - 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 diff --git a/lustre/mdc/mdc_internal.h b/lustre/mdc/mdc_internal.h index 82da07a..15bac99 100644 --- a/lustre/mdc/mdc_internal.h +++ b/lustre/mdc/mdc_internal.h @@ -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); diff --git a/lustre/mdc/mdc_lib.c b/lustre/mdc/mdc_lib.c index d9bdeeb..ff56a6f 100644 --- a/lustre/mdc/mdc_lib.c +++ b/lustre/mdc/mdc_lib.c @@ -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, diff --git a/lustre/mdc/mdc_locks.c b/lustre/mdc/mdc_locks.c index 85bc771..12fd55c 100644 --- a/lustre/mdc/mdc_locks.c +++ b/lustre/mdc/mdc_locks.c @@ -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 * diff --git a/lustre/mdc/mdc_reint.c b/lustre/mdc/mdc_reint.c index 5d61dbe..017f619 100644 --- a/lustre/mdc/mdc_reint.c +++ b/lustre/mdc/mdc_reint.c @@ -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) diff --git a/lustre/mdc/mdc_request.c b/lustre/mdc/mdc_request.c index a54260b..5ecf780 100644 --- a/lustre/mdc/mdc_request.c +++ b/lustre/mdc/mdc_request.c @@ -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, diff --git a/lustre/ptlrpc/gss/gss_keyring.c b/lustre/ptlrpc/gss/gss_keyring.c index 3530607..a4b5948 100644 --- a/lustre/ptlrpc/gss/gss_keyring.c +++ b/lustre/ptlrpc/gss/gss_keyring.c @@ -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); diff --git a/lustre/ptlrpc/gss/sec_gss.c b/lustre/ptlrpc/gss/sec_gss.c index 28cea38d..cfc23f1 100644 --- a/lustre/ptlrpc/gss/sec_gss.c +++ b/lustre/ptlrpc/gss/sec_gss.c @@ -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; diff --git a/lustre/ptlrpc/import.c b/lustre/ptlrpc/import.c index 3a6bcac..334ef29 100644 --- a/lustre/ptlrpc/import.c +++ b/lustre/ptlrpc/import.c @@ -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); diff --git a/lustre/ptlrpc/sec.c b/lustre/ptlrpc/sec.c index 50905f2..725a71f 100644 --- a/lustre/ptlrpc/sec.c +++ b/lustre/ptlrpc/sec.c @@ -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 diff --git a/lustre/ptlrpc/sec_lproc.c b/lustre/ptlrpc/sec_lproc.c index 44ad372..597036a 100644 --- a/lustre/ptlrpc/sec_lproc.c +++ b/lustre/ptlrpc/sec_lproc.c @@ -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) { diff --git a/lustre/ptlrpc/sec_null.c b/lustre/ptlrpc/sec_null.c index f56c356..b965cb4 100644 --- a/lustre/ptlrpc/sec_null.c +++ b/lustre/ptlrpc/sec_null.c @@ -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;