From b4c9b7b1a59ade6d81fa69d5b748f3b19a2bef03 Mon Sep 17 00:00:00 2001 From: "Tom.Wang" Date: Mon, 21 Dec 2009 08:05:46 -0500 Subject: [PATCH] b=20607 Use refcount on lov_request_set to prevent memory corruption. Correct the refcount of lov_request_set to make sure the set will only be freed after all the references have been released. i=adilger i=ericm --- lustre/lov/lov_internal.h | 15 ++++++++++++++ lustre/lov/lov_request.c | 50 ++++++++++++++++++++--------------------------- 2 files changed, 36 insertions(+), 29 deletions(-) diff --git a/lustre/lov/lov_internal.h b/lustre/lov/lov_internal.h index b76627f..e35162d 100644 --- a/lustre/lov/lov_internal.h +++ b/lustre/lov/lov_internal.h @@ -110,6 +110,21 @@ static inline struct lov_lock_handles *lov_llh_new(struct lov_stripe_md *lsm) return llh; } +void lov_finish_set(struct lov_request_set *set); + +static inline void lov_get_reqset(struct lov_request_set *set) +{ + LASSERT(set != NULL); + LASSERT(atomic_read(&set->set_refcount) > 0); + atomic_inc(&set->set_refcount); +} + +static inline void lov_put_reqset(struct lov_request_set *set) +{ + if (atomic_dec_and_test(&set->set_refcount)) + lov_finish_set(set); +} + static inline struct lov_lock_handles * lov_handle2llh(struct lustre_handle *handle) { diff --git a/lustre/lov/lov_request.c b/lustre/lov/lov_request.c index a16eca1..b84551a 100644 --- a/lustre/lov/lov_request.c +++ b/lustre/lov/lov_request.c @@ -63,7 +63,7 @@ static void lov_init_set(struct lov_request_set *set) spin_lock_init(&set->set_lock); } -static void lov_finish_set(struct lov_request_set *set) +void lov_finish_set(struct lov_request_set *set) { struct list_head *pos, *n; ENTRY; @@ -264,8 +264,7 @@ int lov_fini_enqueue_set(struct lov_request_set *set, __u32 mode, int rc, } else if (set->set_lockh) lov_llh_put(set->set_lockh); - if (atomic_dec_and_test(&set->set_refcount)) - lov_finish_set(set); + lov_put_reqset(set); RETURN(rc ? rc : ret); } @@ -388,8 +387,7 @@ int lov_fini_match_set(struct lov_request_set *set, __u32 mode, int flags) (flags & LDLM_FL_TEST_LOCK)) lov_llh_put(set->set_lockh); - if (atomic_dec_and_test(&set->set_refcount)) - lov_finish_set(set); + lov_put_reqset(set); RETURN(rc); } @@ -480,8 +478,7 @@ int lov_fini_cancel_set(struct lov_request_set *set) if (set->set_lockh) lov_llh_put(set->set_lockh); - if (atomic_dec_and_test(&set->set_refcount)) - lov_finish_set(set); + lov_put_reqset(set); RETURN(rc); } @@ -658,9 +655,7 @@ int lov_fini_create_set(struct lov_request_set *set,struct lov_stripe_md **lsmp) if (set->set_completes) rc = create_done(set->set_exp, set, lsmp); - if (atomic_dec_and_test(&set->set_refcount)) - lov_finish_set(set); - + lov_put_reqset(set); RETURN(rc); } @@ -718,7 +713,10 @@ int cb_create_update(void *cookie, int rc) struct lov_request *lovreq; lovreq = container_of(oinfo, struct lov_request, rq_oi); - return lov_update_create_set(lovreq->rq_rqset, lovreq, rc); + rc= lov_update_create_set(lovreq->rq_rqset, lovreq, rc); + if (lov_finished_set(lovreq->rq_rqset)) + lov_put_reqset(lovreq->rq_rqset); + return rc; } @@ -741,14 +739,17 @@ int lov_prep_create_set(struct obd_export *exp, struct obd_info *oinfo, set->set_oi->oi_md = *lsmp; set->set_oi->oi_oa = src_oa; set->set_oti = oti; + lov_get_reqset(set); rc = qos_prep_create(exp, set); /* qos_shrink_lsm() may have allocated a new lsm */ *lsmp = oinfo->oi_md; - if (rc) + if (rc) { lov_fini_create_set(set, lsmp); - else + lov_put_reqset(set); + } else { *reqset = set; + } RETURN(rc); } @@ -831,8 +832,7 @@ int lov_fini_brw_set(struct lov_request_set *set) rc = brw_done(set); /* FIXME update qos data here */ } - if (atomic_dec_and_test(&set->set_refcount)) - lov_finish_set(set); + lov_put_reqset(set); RETURN(rc); } @@ -970,8 +970,7 @@ int lov_fini_getattr_set(struct lov_request_set *set) if (set->set_completes) rc = common_attr_done(set); - if (atomic_dec_and_test(&set->set_refcount)) - lov_finish_set(set); + lov_put_reqset(set); RETURN(rc); } @@ -1053,8 +1052,7 @@ int lov_fini_destroy_set(struct lov_request_set *set) /* FIXME update qos data here */ } - if (atomic_dec_and_test(&set->set_refcount)) - lov_finish_set(set); + lov_put_reqset(set); RETURN(0); } @@ -1131,8 +1129,7 @@ int lov_fini_setattr_set(struct lov_request_set *set) /* FIXME update qos data here */ } - if (atomic_dec_and_test(&set->set_refcount)) - lov_finish_set(set); + lov_put_reqset(set); RETURN(rc); } @@ -1261,8 +1258,7 @@ int lov_fini_punch_set(struct lov_request_set *set) rc = common_attr_done(set); } - if (atomic_dec_and_test(&set->set_refcount)) - lov_finish_set(set); + lov_put_reqset(set); RETURN(rc); } @@ -1390,8 +1386,7 @@ int lov_fini_sync_set(struct lov_request_set *set) /* FIXME update qos data here */ } - if (atomic_dec_and_test(&set->set_refcount)) - lov_finish_set(set); + lov_put_reqset(set); RETURN(rc); } @@ -1503,10 +1498,7 @@ int lov_fini_statfs_set(struct lov_request_set *set) rc = lov_fini_statfs(set->set_obd, set->set_oi->oi_osfs, set->set_success); } - - if (atomic_dec_and_test(&set->set_refcount)) - lov_finish_set(set); - + lov_put_reqset(set); RETURN(rc); } -- 1.8.3.1