X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fofd%2Fofd_fmd.c;h=e98ac42930aae1542524a9a584baa2aa9af18222;hb=f3ea0cea6bb6766eaa55571774b9ae942a6bf297;hp=ab2a5a8f1ab2a5377fc1b39d52bab10461b48998;hpb=08aa217ce49aba1ded52e0f7adb8a607035123fd;p=fs%2Flustre-release.git diff --git a/lustre/ofd/ofd_fmd.c b/lustre/ofd/ofd_fmd.c index ab2a5a8..e98ac42 100644 --- a/lustre/ofd/ofd_fmd.c +++ b/lustre/ofd/ofd_fmd.c @@ -15,11 +15,7 @@ * * You should have received a copy of the GNU General Public License * version 2 along with this program; If not, see - * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. + * http://www.gnu.org/licenses/gpl-2.0.html * * GPL HEADER END */ @@ -27,38 +23,64 @@ * Copyright 2008 Sun Microsystems, Inc. All rights reserved * Use is subject to license terms. * - * Copyright (c) 2012, Intel Corporation. + * Copyright (c) 2014 Intel Corporation. */ /* * This file is part of Lustre, http://www.lustre.org/ * Lustre is a trademark of Sun Microsystems, Inc. * - * lustre/ofd/filter_fmd.c + * lustre/ofd/ofd_fmd.c + * + * This file provides functions to handle Filter Modification Data (FMD). + * The FMD is responsible for file attributes to be applied in + * Transaction ID (XID) order, so older requests can't re-write newer + * attributes. + * + * FMD is organized as per-client list and identified by FID of object. Each + * FMD stores FID of object and the highest received XID of modification + * request for this object. + * + * FMD can expire if there are no updates for a long time to keep the list + * reasonably small. + * + * Author: Andreas Dilger */ #define DEBUG_SUBSYSTEM S_FILTER #include "ofd_internal.h" -static cfs_mem_cache_t *ll_fmd_cachep; +static struct kmem_cache *ll_fmd_cachep; -/* drop fmd reference, free it if last ref. must be called with fed_lock held.*/ +/** + * Drop FMD reference and free it if reference drops to zero. + * + * Must be called with fed_lock held. + * + * \param[in] exp OBD export + * \param[in] fmd FMD to put + */ static inline void ofd_fmd_put_nolock(struct obd_export *exp, struct ofd_mod_data *fmd) { struct filter_export_data *fed = &exp->exp_filter_data; - LASSERT_SPIN_LOCKED(&fed->fed_lock); + assert_spin_locked(&fed->fed_lock); if (--fmd->fmd_refcount == 0) { /* XXX when we have persistent reservations and the handle * is stored herein we need to drop it here. */ fed->fed_mod_count--; - cfs_list_del(&fmd->fmd_list); + list_del(&fmd->fmd_list); OBD_SLAB_FREE(fmd, ll_fmd_cachep, sizeof(*fmd)); } } -/* drop fmd reference, free it if last ref */ +/** + * Wrapper to drop FMD reference with fed_lock held. + * + * \param[in] exp OBD export + * \param[in] fmd FMD to put + */ void ofd_fmd_put(struct obd_export *exp, struct ofd_mod_data *fmd) { struct filter_export_data *fed = &exp->exp_filter_data; @@ -71,8 +93,21 @@ void ofd_fmd_put(struct obd_export *exp, struct ofd_mod_data *fmd) spin_unlock(&fed->fed_lock); } -/* expire entries from the end of the list if there are too many - * or they are too old */ +/** + * Expire FMD entries. + * + * Expire entries from the FMD list if there are too many + * of them or they are too old. + * + * This function must be called with fed_lock held. + * + * The \a keep FMD is not to be expired in any case. This parameter is used + * by ofd_fmd_find_nolock() to prohibit a FMD that was just found from + * expiring. + * + * \param[in] exp OBD export + * \param[in] keep FMD to keep always + */ static void ofd_fmd_expire_nolock(struct obd_export *exp, struct ofd_mod_data *keep) { @@ -82,7 +117,7 @@ static void ofd_fmd_expire_nolock(struct obd_export *exp, cfs_time_t now = cfs_time_current(); - cfs_list_for_each_entry_safe(fmd, tmp, &fed->fed_mod_list, fmd_list) { + list_for_each_entry_safe(fmd, tmp, &fed->fed_mod_list, fmd_list) { if (fmd == keep) break; @@ -90,11 +125,18 @@ static void ofd_fmd_expire_nolock(struct obd_export *exp, fed->fed_mod_count < ofd->ofd_fmd_max_num) break; - cfs_list_del_init(&fmd->fmd_list); + list_del_init(&fmd->fmd_list); ofd_fmd_put_nolock(exp, fmd); /* list reference */ } } +/** + * Expire FMD entries. + * + * This is a wrapper to call ofd_fmd_expire_nolock() with the required lock. + * + * \param[in] exp OBD export + */ void ofd_fmd_expire(struct obd_export *exp) { struct filter_export_data *fed = &exp->exp_filter_data; @@ -104,8 +146,19 @@ void ofd_fmd_expire(struct obd_export *exp) spin_unlock(&fed->fed_lock); } -/* find specified fid in fed_fmd_list. - * caller must hold fed_lock and take fmd reference itself */ +/** + * Find FMD by specified FID. + * + * Function finds FMD entry by FID in the filter_export_data::fed_fmd_list. + * + * Caller must hold filter_export_data::fed_lock and take FMD reference. + * + * \param[in] exp OBD export + * \param[in] fid FID of FMD to find + * + * \retval struct ofd_mod_data found by FID + * \retval NULL is FMD is not found + */ static struct ofd_mod_data *ofd_fmd_find_nolock(struct obd_export *exp, const struct lu_fid *fid) { @@ -115,13 +168,13 @@ static struct ofd_mod_data *ofd_fmd_find_nolock(struct obd_export *exp, cfs_time_t now = cfs_time_current(); - LASSERT_SPIN_LOCKED(&fed->fed_lock); + assert_spin_locked(&fed->fed_lock); - cfs_list_for_each_entry_reverse(fmd, &fed->fed_mod_list, fmd_list) { + list_for_each_entry_reverse(fmd, &fed->fed_mod_list, fmd_list) { if (lu_fid_eq(&fmd->fmd_fid, fid)) { found = fmd; - cfs_list_del(&fmd->fmd_list); - cfs_list_add_tail(&fmd->fmd_list, &fed->fed_mod_list); + list_del(&fmd->fmd_list); + list_add_tail(&fmd->fmd_list, &fed->fed_mod_list); fmd->fmd_expire = cfs_time_add(now, ofd->ofd_fmd_max_age); break; } @@ -132,9 +185,19 @@ static struct ofd_mod_data *ofd_fmd_find_nolock(struct obd_export *exp, return found; } -/* Find fmd based on fid or return NULL if not found. */ +/** + * Find FMD by specified FID with locking. + * + * Wrapper to the ofd_fmd_find_nolock() with correct locks. + * + * \param[in] exp OBD export + * \param[in] fid FID of FMD to find + * + * \retval struct ofd_mod_data found by FID + * \retval NULL indicates FMD is not found + */ struct ofd_mod_data *ofd_fmd_find(struct obd_export *exp, - struct lu_fid *fid) + const struct lu_fid *fid) { struct filter_export_data *fed = &exp->exp_filter_data; struct ofd_mod_data *fmd; @@ -148,12 +211,21 @@ struct ofd_mod_data *ofd_fmd_find(struct obd_export *exp, return fmd; } -/* Find fmd based on FID, or create a new one if none is found. +/** + * Find FMD by FID or create a new one if none is found. + * * It is possible for this function to return NULL under memory pressure, - * or if fid = 0 is passed (which will only cause old entries to expire). - * Currently this is not fatal because any fmd state is transient and - * may also be freed when it gets sufficiently old. */ -struct ofd_mod_data *ofd_fmd_get(struct obd_export *exp, struct lu_fid *fid) + * or if the passed FID is zero (which will only cause old entries to expire). + * Currently this is not fatal because any FMD state is transient and + * may also be freed when it gets sufficiently old. + * + * \param[in] exp OBD export + * \param[in] fid FID of FMD to find + * + * \retval struct ofd_mod_data found by FID + * \retval NULL indicates FMD is not found + */ +struct ofd_mod_data *ofd_fmd_get(struct obd_export *exp, const struct lu_fid *fid) { struct filter_export_data *fed = &exp->exp_filter_data; struct ofd_device *ofd = ofd_exp(exp); @@ -167,8 +239,8 @@ struct ofd_mod_data *ofd_fmd_get(struct obd_export *exp, struct lu_fid *fid) found = ofd_fmd_find_nolock(exp, fid); if (fmd_new) { if (found == NULL) { - cfs_list_add_tail(&fmd_new->fmd_list, - &fed->fed_mod_list); + list_add_tail(&fmd_new->fmd_list, + &fed->fed_mod_list); fmd_new->fmd_fid = *fid; fmd_new->fmd_refcount++; /* list reference */ found = fmd_new; @@ -188,11 +260,22 @@ struct ofd_mod_data *ofd_fmd_get(struct obd_export *exp, struct lu_fid *fid) } #ifdef DO_FMD_DROP -/* drop fmd list reference so it will disappear when last reference is put. - * This isn't so critical because it would in fact only affect the one client - * that is doing the unlink and at worst we have an stale entry referencing - * an object that should never be used again. */ -void ofd_fmd_drop(struct obd_export *exp, struct lu_fid *fid) +/** + * Drop FMD list reference so it will disappear when last reference is dropped + * to zero. + * + * This function is called from ofd_object_destroy() and may only affect + * the one client that is doing the unlink and at worst we have an stale entry + * referencing an object that should never be used again. + * + * NB: this function is used only if DO_FMD_DROP is defined. It is not + * currently defined, so FMD drop doesn't happen and FMD are dropped only + * when expired. + * + * \param[in] exp OBD export + * \param[in] fid FID of FMD to drop + */ +void ofd_fmd_drop(struct obd_export *exp, const struct lu_fid *fid) { struct filter_export_data *fed = &exp->exp_filter_data; struct ofd_mod_data *found = NULL; @@ -200,22 +283,28 @@ void ofd_fmd_drop(struct obd_export *exp, struct lu_fid *fid) spin_lock(&fed->fed_lock); found = ofd_fmd_find_nolock(exp, fid); if (found) { - cfs_list_del_init(&found->fmd_list); + list_del_init(&found->fmd_list); ofd_fmd_put_nolock(exp, found); } spin_unlock(&fed->fed_lock); } #endif -/* remove all entries from fmd list */ +/** + * Remove all entries from FMD list. + * + * Cleanup function to free all FMD enries on the given export. + * + * \param[in] exp OBD export + */ void ofd_fmd_cleanup(struct obd_export *exp) { struct filter_export_data *fed = &exp->exp_filter_data; struct ofd_mod_data *fmd = NULL, *tmp; spin_lock(&fed->fed_lock); - cfs_list_for_each_entry_safe(fmd, tmp, &fed->fed_mod_list, fmd_list) { - cfs_list_del_init(&fmd->fmd_list); + list_for_each_entry_safe(fmd, tmp, &fed->fed_mod_list, fmd_list) { + list_del_init(&fmd->fmd_list); if (fmd->fmd_refcount > 1) { CDEBUG(D_INFO, "fmd %p still referenced (refcount = %d)\n", fmd, fmd->fmd_refcount); @@ -225,23 +314,33 @@ void ofd_fmd_cleanup(struct obd_export *exp) spin_unlock(&fed->fed_lock); } +/** + * Initialize FMD subsystem. + * + * This function is called upon OFD setup and initialize memory to be used + * by FMD entries. + */ int ofd_fmd_init(void) { - ll_fmd_cachep = cfs_mem_cache_create("ll_fmd_cache", - sizeof(struct ofd_mod_data), - 0, 0); + ll_fmd_cachep = kmem_cache_create("ll_fmd_cache", + sizeof(struct ofd_mod_data), + 0, 0, NULL); if (!ll_fmd_cachep) return -ENOMEM; else return 0; } +/** + * Stop FMD subsystem. + * + * This function is called upon OFD cleanup and destroy memory used + * by FMD entries. + */ void ofd_fmd_exit(void) { if (ll_fmd_cachep) { - int rc = cfs_mem_cache_destroy(ll_fmd_cachep); - - LASSERTF(rc == 0, "Cannot destroy ll_fmd_cachep: rc %d\n", rc); + kmem_cache_destroy(ll_fmd_cachep); ll_fmd_cachep = NULL; } }