X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Fmdt%2Fmdt_hsm_cdt_actions.c;h=7ae376262c1af42faf5d55601e8361a21174fbbd;hp=8c5f504f07b5f8fc1fdbd109fa8f3d5dd3b08061;hb=d5d0ff24a84f64e5196341f5ce946952d7fff8b7;hpb=d10200a80770f0029d1d665af954187b9ad883df diff --git a/lustre/mdt/mdt_hsm_cdt_actions.c b/lustre/mdt/mdt_hsm_cdt_actions.c index 8c5f504..7ae3762 100644 --- a/lustre/mdt/mdt_hsm_cdt_actions.c +++ b/lustre/mdt/mdt_hsm_cdt_actions.c @@ -23,7 +23,7 @@ * (C) Copyright 2012 Commissariat a l'energie atomique et aux energies * alternatives * - * Copyright (c) 2013, 2016, Intel Corporation. + * Copyright (c) 2013, 2017, Intel Corporation. */ /* * lustre/mdt/mdt_hsm_cdt_actions.c @@ -36,14 +36,136 @@ #define DEBUG_SUBSYSTEM S_MDS +#include +#include #include -#include #include #include #include #include #include "mdt_internal.h" +struct cdt_agent_record_loc { + struct hlist_node carl_hnode; + atomic_t carl_refcount; + u64 carl_cookie; + u32 carl_cat_idx; + u32 carl_rec_idx; +}; + +static inline void cdt_agent_record_loc_get(struct cdt_agent_record_loc *carl) +{ + LASSERT(atomic_read(&carl->carl_refcount) > 0); + atomic_inc(&carl->carl_refcount); +} + +static inline void cdt_agent_record_loc_put(struct cdt_agent_record_loc *carl) +{ + LASSERT(atomic_read(&carl->carl_refcount) > 0); + if (atomic_dec_and_test(&carl->carl_refcount)) + OBD_FREE_PTR(carl); +} + +static unsigned int +cdt_agent_record_hash(struct cfs_hash *hs, const void *key, unsigned int mask) +{ + return cfs_hash_djb2_hash(key, sizeof(u64), mask); +} + +static void *cdt_agent_record_object(struct hlist_node *hnode) +{ + return hlist_entry(hnode, struct cdt_agent_record_loc, carl_hnode); +} + +static void *cdt_agent_record_key(struct hlist_node *hnode) +{ + struct cdt_agent_record_loc *carl = cdt_agent_record_object(hnode); + + return &carl->carl_cookie; +} + +static int cdt_agent_record_keycmp(const void *key, struct hlist_node *hnode) +{ + const u64 *cookie2 = cdt_agent_record_key(hnode); + + return *(const u64 *)key == *cookie2; +} + +static void cdt_agent_record_get(struct cfs_hash *hs, struct hlist_node *hnode) +{ + struct cdt_agent_record_loc *carl = cdt_agent_record_object(hnode); + + cdt_agent_record_loc_get(carl); +} + +static void cdt_agent_record_put(struct cfs_hash *hs, struct hlist_node *hnode) +{ + struct cdt_agent_record_loc *carl = cdt_agent_record_object(hnode); + + cdt_agent_record_loc_put(carl); +} + +struct cfs_hash_ops cdt_agent_record_hash_ops = { + .hs_hash = cdt_agent_record_hash, + .hs_key = cdt_agent_record_key, + .hs_keycmp = cdt_agent_record_keycmp, + .hs_object = cdt_agent_record_object, + .hs_get = cdt_agent_record_get, + .hs_put_locked = cdt_agent_record_put, +}; + +void cdt_agent_record_hash_add(struct coordinator *cdt, u64 cookie, u32 cat_idx, + u32 rec_idx) +{ + struct cdt_agent_record_loc *carl0; + struct cdt_agent_record_loc *carl1; + + OBD_ALLOC_PTR(carl1); + if (carl1 == NULL) + return; + + INIT_HLIST_NODE(&carl1->carl_hnode); + atomic_set(&carl1->carl_refcount, 1); + carl1->carl_cookie = cookie; + carl1->carl_cat_idx = cat_idx; + carl1->carl_rec_idx = rec_idx; + + carl0 = cfs_hash_findadd_unique(cdt->cdt_agent_record_hash, + &carl1->carl_cookie, + &carl1->carl_hnode); + + LASSERT(carl0->carl_cookie == carl1->carl_cookie); + LASSERT(carl0->carl_cat_idx == carl1->carl_cat_idx); + LASSERT(carl0->carl_rec_idx == carl1->carl_rec_idx); + + if (carl0 != carl1) + cdt_agent_record_loc_put(carl0); + + cdt_agent_record_loc_put(carl1); +} + +void cdt_agent_record_hash_lookup(struct coordinator *cdt, u64 cookie, + u32 *cat_idx, u32 *rec_idx) +{ + struct cdt_agent_record_loc *carl; + + carl = cfs_hash_lookup(cdt->cdt_agent_record_hash, &cookie); + if (carl != NULL) { + LASSERT(carl->carl_cookie == cookie); + *cat_idx = carl->carl_cat_idx; + *rec_idx = carl->carl_rec_idx; + cdt_agent_record_loc_put(carl); + } else { + *cat_idx = 0; + *rec_idx = 0; + } +} + +void cdt_agent_record_hash_del(struct coordinator *cdt, u64 cookie) +{ + cfs_hash_del_key(cdt->cdt_agent_record_hash, &cookie); +} + void dump_llog_agent_req_rec(const char *prefix, const struct llog_agent_req_rec *larr) { @@ -53,7 +175,7 @@ void dump_llog_agent_req_rec(const char *prefix, sz = larr->arr_hai.hai_len - sizeof(larr->arr_hai); CDEBUG(D_HSM, "%slrh=[type=%X len=%d idx=%d] fid="DFID " dfid="DFID - " compound/cookie=%#llx/%#llx" + " cookie=%#llx" " status=%s action=%s archive#=%d flags=%#llx" " create=%llu change=%llu" " extent=%#llx-%#llx gid=%#llx datalen=%d" @@ -63,7 +185,7 @@ void dump_llog_agent_req_rec(const char *prefix, larr->arr_hdr.lrh_len, larr->arr_hdr.lrh_index, PFID(&larr->arr_hai.hai_fid), PFID(&larr->arr_hai.hai_dfid), - larr->arr_compound_id, larr->arr_hai.hai_cookie, + larr->arr_hai.hai_cookie, agent_req_status2name(larr->arr_status), hsm_copytool_action2name(larr->arr_hai.hai_action), larr->arr_archive_id, @@ -81,11 +203,15 @@ void dump_llog_agent_req_rec(const char *prefix, * \param mdt [IN] MDT device * \param cb [IN] llog callback funtion * \param data [IN] llog callback data + * \param rw [IN] cdt_llog_lock mode (READ or WRITE) + * \param start_cat_idx first catalog index to examine + * \param start_rec_idx first record index to examine * \retval 0 success * \retval -ve failure */ int cdt_llog_process(const struct lu_env *env, struct mdt_device *mdt, - llog_cb_t cb, void *data) + llog_cb_t cb, void *data, u32 start_cat_idx, + u32 start_rec_idx, int rw) { struct obd_device *obd = mdt2obd_dev(mdt); struct llog_ctxt *lctxt = NULL; @@ -97,9 +223,13 @@ int cdt_llog_process(const struct lu_env *env, struct mdt_device *mdt, if (lctxt == NULL || lctxt->loc_handle == NULL) RETURN(-ENOENT); - mutex_lock(&cdt->cdt_llog_lock); + if (rw == READ) + down_read(&cdt->cdt_llog_lock); + else + down_write(&cdt->cdt_llog_lock); - rc = llog_cat_process(env, lctxt->loc_handle, cb, data, 0, 0); + rc = llog_cat_process(env, lctxt->loc_handle, cb, data, start_cat_idx, + start_rec_idx); if (rc < 0) CERROR("%s: failed to process HSM_ACTIONS llog (rc=%d)\n", mdt_obd_name(mdt), rc); @@ -107,7 +237,12 @@ int cdt_llog_process(const struct lu_env *env, struct mdt_device *mdt, rc = 0; llog_ctxt_put(lctxt); - mutex_unlock(&cdt->cdt_llog_lock); + + if (rw == READ) + up_read(&cdt->cdt_llog_lock); + else + up_write(&cdt->cdt_llog_lock); + RETURN(rc); } @@ -115,16 +250,14 @@ int cdt_llog_process(const struct lu_env *env, struct mdt_device *mdt, * add an entry in agent llog * \param env [IN] environment * \param mdt [IN] PDT device - * \param compound_id [IN] global id associated with the record * \param archive_id [IN] backend archive number * \param hai [IN] record to register * \retval 0 success * \retval -ve failure */ -int mdt_agent_record_add(const struct lu_env *env, - struct mdt_device *mdt, - __u64 compound_id, __u32 archive_id, - __u64 flags, struct hsm_action_item *hai) +int mdt_agent_record_add(const struct lu_env *env, struct mdt_device *mdt, + __u32 archive_id, __u64 flags, + struct hsm_action_item *hai) { struct obd_device *obd = mdt2obd_dev(mdt); struct coordinator *cdt = &mdt->mdt_coordinator; @@ -141,10 +274,9 @@ int mdt_agent_record_add(const struct lu_env *env, larr->arr_hdr.lrh_len = sz; larr->arr_hdr.lrh_type = HSM_AGENT_REC; larr->arr_status = ARS_WAITING; - larr->arr_compound_id = compound_id; larr->arr_archive_id = archive_id; larr->arr_flags = flags; - larr->arr_req_create = cfs_time_current_sec(); + larr->arr_req_create = ktime_get_real_seconds(); larr->arr_req_change = larr->arr_req_create; memcpy(&larr->arr_hai, hai, hai->hai_len); @@ -152,23 +284,21 @@ int mdt_agent_record_add(const struct lu_env *env, if (lctxt == NULL || lctxt->loc_handle == NULL) GOTO(free, rc = -ENOENT); - mutex_lock(&cdt->cdt_llog_lock); + down_write(&cdt->cdt_llog_lock); /* in case of cancel request, the cookie is already set to the * value of the request cookie to be cancelled * so we do not change it */ - if (hai->hai_action == HSMA_CANCEL) { + if (hai->hai_action == HSMA_CANCEL) larr->arr_hai.hai_cookie = hai->hai_cookie; - } else { - cdt->cdt_last_cookie++; - larr->arr_hai.hai_cookie = cdt->cdt_last_cookie; - } + else + larr->arr_hai.hai_cookie = cdt->cdt_last_cookie++; rc = llog_cat_add(env, lctxt->loc_handle, &larr->arr_hdr, NULL); if (rc > 0) rc = 0; - mutex_unlock(&cdt->cdt_llog_lock); + up_write(&cdt->cdt_llog_lock); llog_ctxt_put(lctxt); EXIT; @@ -183,11 +313,10 @@ free: */ struct data_update_cb { struct mdt_device *mdt; - __u64 *cookies; - int cookies_count; - int cookies_done; - enum agent_req_status status; - cfs_time_t change_time; + struct hsm_record_update *updates; + unsigned int updates_count; + unsigned int updates_done; + time64_t change_time; }; /** @@ -213,32 +342,38 @@ static int mdt_agent_record_update_cb(const struct lu_env *env, ducb = data; /* check if all done */ - if (ducb->cookies_count == ducb->cookies_done) + if (ducb->updates_count == ducb->updates_done) RETURN(LLOG_PROC_BREAK); /* if record is in final state, never change */ - /* if record is a cancel request, it cannot be canceled - * this is to manage the following case: - * when a request is canceled, we have 2 records with the - * the same cookie : the one to cancel and the cancel request - * the 1st has to be set to ARS_CANCELED and the 2nd to ARS_SUCCEED - */ - if (agent_req_in_final_state(larr->arr_status) || - (larr->arr_hai.hai_action == HSMA_CANCEL && - ducb->status == ARS_CANCELED)) + if (agent_req_in_final_state(larr->arr_status)) RETURN(0); rc = 0; - for (i = 0 ; i < ducb->cookies_count ; i++) { + for (i = 0 ; i < ducb->updates_count ; i++) { + struct hsm_record_update *update = &ducb->updates[i]; + CDEBUG(D_HSM, "%s: search %#llx, found %#llx\n", - mdt_obd_name(ducb->mdt), ducb->cookies[i], + mdt_obd_name(ducb->mdt), update->cookie, larr->arr_hai.hai_cookie); - if (larr->arr_hai.hai_cookie == ducb->cookies[i]) { - - larr->arr_status = ducb->status; + if (larr->arr_hai.hai_cookie == update->cookie) { + + /* If record is a cancel request, it cannot be + * canceled. This is to manage the following + * case: when a request is canceled, we have 2 + * records with the the same cookie: the one + * to cancel and the cancel request the 1st + * has to be set to ARS_CANCELED and the 2nd + * to ARS_SUCCEED + */ + if (larr->arr_hai.hai_action == HSMA_CANCEL && + update->status == ARS_CANCELED) + RETURN(0); + + larr->arr_status = update->status; larr->arr_req_change = ducb->change_time; rc = llog_write(env, llh, hdr, hdr->lrh_index); - ducb->cookies_done++; + ducb->updates_done++; break; } } @@ -252,36 +387,65 @@ static int mdt_agent_record_update_cb(const struct lu_env *env, /** * update an entry in agent llog + * * \param env [IN] environment * \param mdt [IN] MDT device - * \param cookie [IN] entries to update - * log cookie are returned by register - * \param status [IN] new status of the request - * \retval 0 success - * \retval -ve failure + * \param updates [IN] array of entries to update + * \param updates_count [IN] number of entries in updates + * + * \retval 0 on success + * \retval negative on failure */ int mdt_agent_record_update(const struct lu_env *env, struct mdt_device *mdt, - __u64 *cookies, int cookies_count, - enum agent_req_status status) + struct hsm_record_update *updates, + unsigned int updates_count) { struct data_update_cb ducb; - int rc; + u32 start_cat_idx = -1; + u32 start_rec_idx = -1; + u32 cat_idx; + u32 rec_idx; + int i; + int rc; ENTRY; + /* Find the first location (start_cat_idx, start_rec_idx) + * among the records corresponding to cookies. */ + for (i = 0; i < updates_count; i++) { + /* If we cannot find a cached location for a cookie + * (perhaps because the MDT was restart then we must + * start from the beginning. In this case + * mdt_agent_record_hash_get() sets both of cat_idx and + * rec_idx to 0. */ + cdt_agent_record_hash_lookup(&mdt->mdt_coordinator, + updates[i].cookie, + &cat_idx, &rec_idx); + if (cat_idx < start_cat_idx) { + start_cat_idx = cat_idx; + start_rec_idx = rec_idx; + } else if (cat_idx == start_cat_idx && + rec_idx < start_rec_idx) { + start_rec_idx = rec_idx; + } + } + + /* Fixup starting record index for llog_cat_process(). */ + if (start_rec_idx != 0) + start_rec_idx -= 1; + ducb.mdt = mdt; - ducb.cookies = cookies; - ducb.cookies_count = cookies_count; - ducb.cookies_done = 0; - ducb.status = status; - ducb.change_time = cfs_time_current_sec(); + ducb.updates = updates; + ducb.updates_count = updates_count; + ducb.updates_done = 0; + ducb.change_time = ktime_get_real_seconds(); - rc = cdt_llog_process(env, mdt, mdt_agent_record_update_cb, &ducb); + rc = cdt_llog_process(env, mdt, mdt_agent_record_update_cb, &ducb, + start_cat_idx, start_rec_idx, WRITE); if (rc < 0) CERROR("%s: cdt_llog_process() failed, rc=%d, cannot update " - "status to %s for %d cookies, done %d\n", + "status for %u cookies, done %u\n", mdt_obd_name(mdt), rc, - agent_req_status2name(status), - cookies_count, ducb.cookies_done); + updates_count, ducb.updates_done); RETURN(rc); } @@ -316,9 +480,10 @@ struct agent_action_iterator { * seq_file method called to start access to /proc file * get llog context + llog handle */ -static void *mdt_hsm_actions_proc_start(struct seq_file *s, loff_t *pos) +static void *mdt_hsm_actions_debugfs_start(struct seq_file *s, loff_t *pos) { - struct agent_action_iterator *aai = s->private; + struct agent_action_iterator *aai = s->private; + ENTRY; LASSERTF(aai->aai_magic == AGENT_ACTIONS_IT_MAGIC, "%08X\n", @@ -338,7 +503,6 @@ static void *mdt_hsm_actions_proc_start(struct seq_file *s, loff_t *pos) aai->aai_cat_index = 0; aai->aai_index = 0; aai->aai_eof = false; - *pos = 1; } if (aai->aai_eof) @@ -347,10 +511,15 @@ static void *mdt_hsm_actions_proc_start(struct seq_file *s, loff_t *pos) RETURN(aai); } -static void *mdt_hsm_actions_proc_next(struct seq_file *s, void *v, +static void *mdt_hsm_actions_debugfs_next(struct seq_file *s, void *v, loff_t *pos) { - RETURN(NULL); + struct agent_action_iterator *aai = s->private; + + (*pos)++; + if (aai->aai_eof) + RETURN(NULL); + RETURN(aai); } /** @@ -361,14 +530,14 @@ static int hsm_actions_show_cb(const struct lu_env *env, struct llog_rec_hdr *hdr, void *data) { - struct llog_agent_req_rec *larr = (struct llog_agent_req_rec *)hdr; - struct seq_file *s = data; - struct agent_action_iterator *aai; - int sz; - char buf[12]; + struct llog_agent_req_rec *larr = (struct llog_agent_req_rec *)hdr; + struct seq_file *s = data; + struct agent_action_iterator *aai = s->private; + int sz; + char buf[12]; + ENTRY; - aai = s->private; LASSERTF(aai->aai_magic == AGENT_ACTIONS_IT_MAGIC, "%08X\n", aai->aai_magic); @@ -390,7 +559,7 @@ static int hsm_actions_show_cb(const struct lu_env *env, llh->lgh_hdr->llh_cat_idx, hdr->lrh_index, PFID(&larr->arr_hai.hai_fid), PFID(&larr->arr_hai.hai_dfid), - larr->arr_compound_id, larr->arr_hai.hai_cookie, + 0ULL /* compound_id */, larr->arr_hai.hai_cookie, hsm_copytool_action2name(larr->arr_hai.hai_action), larr->arr_archive_id, larr->arr_flags, @@ -407,15 +576,16 @@ static int hsm_actions_show_cb(const struct lu_env *env, } /** - * mdt_hsm_actions_proc_show() is called at for each seq record + * mdt_hsm_actions_debugfs_show() is called at for each seq record * process the llog, with a cb which fill the file_seq buffer * to be faster, one show will fill multiple records */ -static int mdt_hsm_actions_proc_show(struct seq_file *s, void *v) +static int mdt_hsm_actions_debugfs_show(struct seq_file *s, void *v) { - struct agent_action_iterator *aai = s->private; - struct coordinator *cdt = &aai->aai_mdt->mdt_coordinator; - int rc; + struct agent_action_iterator *aai = s->private; + struct coordinator *cdt = &aai->aai_mdt->mdt_coordinator; + int rc; + ENTRY; LASSERTF(aai->aai_magic == AGENT_ACTIONS_IT_MAGIC, "%08X\n", @@ -426,15 +596,16 @@ static int mdt_hsm_actions_proc_show(struct seq_file *s, void *v) if (aai->aai_eof) RETURN(0); - mutex_lock(&cdt->cdt_llog_lock); + down_read(&cdt->cdt_llog_lock); rc = llog_cat_process(&aai->aai_env, aai->aai_ctxt->loc_handle, hsm_actions_show_cb, s, aai->aai_cat_index, aai->aai_index); - mutex_unlock(&cdt->cdt_llog_lock); + up_read(&cdt->cdt_llog_lock); if (rc == 0) /* all llog parsed */ aai->aai_eof = true; if (rc == LLOG_PROC_BREAK) /* buffer full */ rc = 0; + RETURN(rc); } @@ -442,9 +613,10 @@ static int mdt_hsm_actions_proc_show(struct seq_file *s, void *v) * seq_file method called to stop access to /proc file * clean + put llog context */ -static void mdt_hsm_actions_proc_stop(struct seq_file *s, void *v) +static void mdt_hsm_actions_debugfs_stop(struct seq_file *s, void *v) { struct agent_action_iterator *aai = s->private; + ENTRY; LASSERTF(aai->aai_magic == AGENT_ACTIONS_IT_MAGIC, "%08X\n", @@ -454,17 +626,16 @@ static void mdt_hsm_actions_proc_stop(struct seq_file *s, void *v) llog_ctxt_put(aai->aai_ctxt); EXIT; - return; } -static const struct seq_operations mdt_hsm_actions_proc_ops = { - .start = mdt_hsm_actions_proc_start, - .next = mdt_hsm_actions_proc_next, - .show = mdt_hsm_actions_proc_show, - .stop = mdt_hsm_actions_proc_stop, +static const struct seq_operations mdt_hsm_actions_debugfs_ops = { + .start = mdt_hsm_actions_debugfs_start, + .next = mdt_hsm_actions_debugfs_next, + .show = mdt_hsm_actions_debugfs_show, + .stop = mdt_hsm_actions_debugfs_stop, }; -static int lprocfs_open_hsm_actions(struct inode *inode, struct file *file) +static int ldebugfs_open_hsm_actions(struct inode *inode, struct file *file) { struct agent_action_iterator *aai; struct seq_file *s; @@ -472,7 +643,7 @@ static int lprocfs_open_hsm_actions(struct inode *inode, struct file *file) struct mdt_device *mdt; ENTRY; - rc = seq_open(file, &mdt_hsm_actions_proc_ops); + rc = seq_open(file, &mdt_hsm_actions_debugfs_ops); if (rc) RETURN(rc); @@ -485,10 +656,11 @@ static int lprocfs_open_hsm_actions(struct inode *inode, struct file *file) if (rc) GOTO(err, rc); - /* mdt is saved in proc_dir_entry->data by - * mdt_coordinator_procfs_init() calling lprocfs_register() + /* mdt is saved in seq_file->data by + * mdt_coordinator_tunables_init() calling + * debugfs_register() */ - mdt = (struct mdt_device *)PDE_DATA(inode); + mdt = inode->i_private; aai->aai_mdt = mdt; s = file->private_data; s->private = aai; @@ -496,7 +668,7 @@ static int lprocfs_open_hsm_actions(struct inode *inode, struct file *file) GOTO(out, rc = 0); err: - lprocfs_seq_release(inode, file); + seq_release(inode, file); if (aai && aai->aai_env.le_ses) OBD_FREE_PTR(aai->aai_env.le_ses); if (aai) @@ -506,10 +678,10 @@ out: } /** - * lprocfs_release_hsm_actions() is called at end of /proc access. + * ldebugfs_release_hsm_actions() is called at end of /proc access. * It frees allocated resources and calls cleanup lprocfs methods. */ -static int lprocfs_release_hsm_actions(struct inode *inode, struct file *file) +static int ldebugfs_release_hsm_actions(struct inode *inode, struct file *file) { struct seq_file *seq = file->private_data; struct agent_action_iterator *aai = seq->private; @@ -519,15 +691,14 @@ static int lprocfs_release_hsm_actions(struct inode *inode, struct file *file) OBD_FREE_PTR(aai); } - return lprocfs_seq_release(inode, file); + return seq_release(inode, file); } /* Methods to access HSM action list LLOG through /proc */ const struct file_operations mdt_hsm_actions_fops = { .owner = THIS_MODULE, - .open = lprocfs_open_hsm_actions, + .open = ldebugfs_open_hsm_actions, .read = seq_read, .llseek = seq_lseek, - .release = lprocfs_release_hsm_actions, + .release = ldebugfs_release_hsm_actions, }; -