4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License version 2 for more details. A copy is
14 * included in the COPYING file that accompanied this code.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * (C) Copyright 2012 Commissariat a l'energie atomique et aux energies
26 * Copyright (c) 2013, 2017, Intel Corporation.
29 * lustre/mdt/mdt_hsm_cdt_actions.c
33 * Author: Jacques-Charles Lafoucriere <jacques-charles.lafoucriere@cea.fr>
34 * Author: Aurelien Degremont <aurelien.degremont@cea.fr>
37 #define DEBUG_SUBSYSTEM S_MDS
39 #include <libcfs/libcfs.h>
40 #include <libcfs/libcfs_hash.h>
41 #include <obd_support.h>
42 #include <lustre_export.h>
44 #include <lprocfs_status.h>
45 #include <lustre_log.h>
46 #include "mdt_internal.h"
48 struct cdt_agent_record_loc {
49 struct hlist_node carl_hnode;
50 atomic_t carl_refcount;
56 static inline void cdt_agent_record_loc_get(struct cdt_agent_record_loc *carl)
58 LASSERT(atomic_read(&carl->carl_refcount) > 0);
59 atomic_inc(&carl->carl_refcount);
62 static inline void cdt_agent_record_loc_put(struct cdt_agent_record_loc *carl)
64 LASSERT(atomic_read(&carl->carl_refcount) > 0);
65 if (atomic_dec_and_test(&carl->carl_refcount))
70 cdt_agent_record_hash(struct cfs_hash *hs, const void *key, unsigned int mask)
72 return cfs_hash_djb2_hash(key, sizeof(u64), mask);
75 static void *cdt_agent_record_object(struct hlist_node *hnode)
77 return hlist_entry(hnode, struct cdt_agent_record_loc, carl_hnode);
80 static void *cdt_agent_record_key(struct hlist_node *hnode)
82 struct cdt_agent_record_loc *carl = cdt_agent_record_object(hnode);
84 return &carl->carl_cookie;
87 static int cdt_agent_record_keycmp(const void *key, struct hlist_node *hnode)
89 const u64 *cookie2 = cdt_agent_record_key(hnode);
91 return *(const u64 *)key == *cookie2;
94 static void cdt_agent_record_get(struct cfs_hash *hs, struct hlist_node *hnode)
96 struct cdt_agent_record_loc *carl = cdt_agent_record_object(hnode);
98 cdt_agent_record_loc_get(carl);
101 static void cdt_agent_record_put(struct cfs_hash *hs, struct hlist_node *hnode)
103 struct cdt_agent_record_loc *carl = cdt_agent_record_object(hnode);
105 cdt_agent_record_loc_put(carl);
108 struct cfs_hash_ops cdt_agent_record_hash_ops = {
109 .hs_hash = cdt_agent_record_hash,
110 .hs_key = cdt_agent_record_key,
111 .hs_keycmp = cdt_agent_record_keycmp,
112 .hs_object = cdt_agent_record_object,
113 .hs_get = cdt_agent_record_get,
114 .hs_put_locked = cdt_agent_record_put,
117 void cdt_agent_record_hash_add(struct coordinator *cdt, u64 cookie, u32 cat_idx,
120 struct cdt_agent_record_loc *carl0;
121 struct cdt_agent_record_loc *carl1;
123 OBD_ALLOC_PTR(carl1);
127 INIT_HLIST_NODE(&carl1->carl_hnode);
128 atomic_set(&carl1->carl_refcount, 1);
129 carl1->carl_cookie = cookie;
130 carl1->carl_cat_idx = cat_idx;
131 carl1->carl_rec_idx = rec_idx;
133 carl0 = cfs_hash_findadd_unique(cdt->cdt_agent_record_hash,
137 LASSERT(carl0->carl_cookie == carl1->carl_cookie);
138 LASSERT(carl0->carl_cat_idx == carl1->carl_cat_idx);
139 LASSERT(carl0->carl_rec_idx == carl1->carl_rec_idx);
142 cdt_agent_record_loc_put(carl0);
144 cdt_agent_record_loc_put(carl1);
147 void cdt_agent_record_hash_lookup(struct coordinator *cdt, u64 cookie,
148 u32 *cat_idx, u32 *rec_idx)
150 struct cdt_agent_record_loc *carl;
152 carl = cfs_hash_lookup(cdt->cdt_agent_record_hash, &cookie);
154 LASSERT(carl->carl_cookie == cookie);
155 *cat_idx = carl->carl_cat_idx;
156 *rec_idx = carl->carl_rec_idx;
157 cdt_agent_record_loc_put(carl);
164 void cdt_agent_record_hash_del(struct coordinator *cdt, u64 cookie)
166 cfs_hash_del_key(cdt->cdt_agent_record_hash, &cookie);
169 void dump_llog_agent_req_rec(const char *prefix,
170 const struct llog_agent_req_rec *larr)
175 sz = larr->arr_hai.hai_len - sizeof(larr->arr_hai);
176 CDEBUG(D_HSM, "%slrh=[type=%X len=%d idx=%d] fid="DFID
179 " status=%s action=%s archive#=%d flags=%#llx"
180 " create=%llu change=%llu"
181 " extent=%#llx-%#llx gid=%#llx datalen=%d"
184 larr->arr_hdr.lrh_type,
185 larr->arr_hdr.lrh_len, larr->arr_hdr.lrh_index,
186 PFID(&larr->arr_hai.hai_fid),
187 PFID(&larr->arr_hai.hai_dfid),
188 larr->arr_hai.hai_cookie,
189 agent_req_status2name(larr->arr_status),
190 hsm_copytool_action2name(larr->arr_hai.hai_action),
191 larr->arr_archive_id,
193 larr->arr_req_create, larr->arr_req_change,
194 larr->arr_hai.hai_extent.offset,
195 larr->arr_hai.hai_extent.length,
196 larr->arr_hai.hai_gid, sz,
197 hai_dump_data_field(&larr->arr_hai, buf, sizeof(buf)));
201 * process the actions llog
202 * \param env [IN] environment
203 * \param mdt [IN] MDT device
204 * \param cb [IN] llog callback funtion
205 * \param data [IN] llog callback data
206 * \param rw [IN] cdt_llog_lock mode (READ or WRITE)
207 * \param start_cat_idx first catalog index to examine
208 * \param start_rec_idx first record index to examine
210 * \retval -ve failure
212 int cdt_llog_process(const struct lu_env *env, struct mdt_device *mdt,
213 llog_cb_t cb, void *data, u32 start_cat_idx,
214 u32 start_rec_idx, int rw)
216 struct obd_device *obd = mdt2obd_dev(mdt);
217 struct llog_ctxt *lctxt = NULL;
218 struct coordinator *cdt = &mdt->mdt_coordinator;
222 lctxt = llog_get_context(obd, LLOG_AGENT_ORIG_CTXT);
223 if (lctxt == NULL || lctxt->loc_handle == NULL)
227 down_read(&cdt->cdt_llog_lock);
229 down_write(&cdt->cdt_llog_lock);
231 rc = llog_cat_process(env, lctxt->loc_handle, cb, data, start_cat_idx,
234 CERROR("%s: failed to process HSM_ACTIONS llog (rc=%d)\n",
235 mdt_obd_name(mdt), rc);
239 llog_ctxt_put(lctxt);
242 up_read(&cdt->cdt_llog_lock);
244 up_write(&cdt->cdt_llog_lock);
250 * add an entry in agent llog
251 * \param env [IN] environment
252 * \param mdt [IN] PDT device
253 * \param archive_id [IN] backend archive number
254 * \param hai [IN] record to register
256 * \retval -ve failure
258 int mdt_agent_record_add(const struct lu_env *env, struct mdt_device *mdt,
259 __u32 archive_id, __u64 flags,
260 struct hsm_action_item *hai)
262 struct obd_device *obd = mdt2obd_dev(mdt);
263 struct coordinator *cdt = &mdt->mdt_coordinator;
264 struct llog_ctxt *lctxt = NULL;
265 struct llog_agent_req_rec *larr;
270 sz = llog_data_len(sizeof(*larr) + hai->hai_len - sizeof(*hai));
274 larr->arr_hdr.lrh_len = sz;
275 larr->arr_hdr.lrh_type = HSM_AGENT_REC;
276 larr->arr_status = ARS_WAITING;
277 larr->arr_archive_id = archive_id;
278 larr->arr_flags = flags;
279 larr->arr_req_create = ktime_get_real_seconds();
280 larr->arr_req_change = larr->arr_req_create;
281 memcpy(&larr->arr_hai, hai, hai->hai_len);
283 lctxt = llog_get_context(obd, LLOG_AGENT_ORIG_CTXT);
284 if (lctxt == NULL || lctxt->loc_handle == NULL)
285 GOTO(free, rc = -ENOENT);
287 down_write(&cdt->cdt_llog_lock);
289 /* in case of cancel request, the cookie is already set to the
290 * value of the request cookie to be cancelled
291 * so we do not change it */
292 if (hai->hai_action == HSMA_CANCEL)
293 larr->arr_hai.hai_cookie = hai->hai_cookie;
295 larr->arr_hai.hai_cookie = cdt->cdt_last_cookie++;
297 rc = llog_cat_add(env, lctxt->loc_handle, &larr->arr_hdr, NULL);
301 up_write(&cdt->cdt_llog_lock);
302 llog_ctxt_put(lctxt);
311 * data passed to llog_cat_process() callback
314 struct data_update_cb {
315 struct mdt_device *mdt;
316 struct hsm_record_update *updates;
317 unsigned int updates_count;
318 unsigned int updates_done;
319 time64_t change_time;
323 * llog_cat_process() callback, used to update a record
324 * \param env [IN] environment
325 * \param llh [IN] llog handle
326 * \param hdr [IN] llog record
327 * \param data [IN] cb data = data_update_cb
329 * \retval -ve failure
331 static int mdt_agent_record_update_cb(const struct lu_env *env,
332 struct llog_handle *llh,
333 struct llog_rec_hdr *hdr,
336 struct llog_agent_req_rec *larr;
337 struct data_update_cb *ducb;
341 larr = (struct llog_agent_req_rec *)hdr;
344 /* check if all done */
345 if (ducb->updates_count == ducb->updates_done)
346 RETURN(LLOG_PROC_BREAK);
348 /* if record is in final state, never change */
349 if (agent_req_in_final_state(larr->arr_status))
353 for (i = 0 ; i < ducb->updates_count ; i++) {
354 struct hsm_record_update *update = &ducb->updates[i];
356 CDEBUG(D_HSM, "%s: search %#llx, found %#llx\n",
357 mdt_obd_name(ducb->mdt), update->cookie,
358 larr->arr_hai.hai_cookie);
359 if (larr->arr_hai.hai_cookie == update->cookie) {
361 /* If record is a cancel request, it cannot be
362 * canceled. This is to manage the following
363 * case: when a request is canceled, we have 2
364 * records with the the same cookie: the one
365 * to cancel and the cancel request the 1st
366 * has to be set to ARS_CANCELED and the 2nd
369 if (larr->arr_hai.hai_action == HSMA_CANCEL &&
370 update->status == ARS_CANCELED)
373 larr->arr_status = update->status;
374 larr->arr_req_change = ducb->change_time;
375 rc = llog_write(env, llh, hdr, hdr->lrh_index);
376 ducb->updates_done++;
382 CERROR("%s: mdt_agent_llog_update_rec() failed, rc = %d\n",
383 mdt_obd_name(ducb->mdt), rc);
389 * update an entry in agent llog
391 * \param env [IN] environment
392 * \param mdt [IN] MDT device
393 * \param updates [IN] array of entries to update
394 * \param updates_count [IN] number of entries in updates
396 * \retval 0 on success
397 * \retval negative on failure
399 int mdt_agent_record_update(const struct lu_env *env, struct mdt_device *mdt,
400 struct hsm_record_update *updates,
401 unsigned int updates_count)
403 struct data_update_cb ducb;
404 u32 start_cat_idx = -1;
405 u32 start_rec_idx = -1;
412 /* Find the first location (start_cat_idx, start_rec_idx)
413 * among the records corresponding to cookies. */
414 for (i = 0; i < updates_count; i++) {
415 /* If we cannot find a cached location for a cookie
416 * (perhaps because the MDT was restart then we must
417 * start from the beginning. In this case
418 * mdt_agent_record_hash_get() sets both of cat_idx and
420 cdt_agent_record_hash_lookup(&mdt->mdt_coordinator,
423 if (cat_idx < start_cat_idx) {
424 start_cat_idx = cat_idx;
425 start_rec_idx = rec_idx;
426 } else if (cat_idx == start_cat_idx &&
427 rec_idx < start_rec_idx) {
428 start_rec_idx = rec_idx;
432 /* Fixup starting record index for llog_cat_process(). */
433 if (start_rec_idx != 0)
437 ducb.updates = updates;
438 ducb.updates_count = updates_count;
439 ducb.updates_done = 0;
440 ducb.change_time = ktime_get_real_seconds();
442 rc = cdt_llog_process(env, mdt, mdt_agent_record_update_cb, &ducb,
443 start_cat_idx, start_rec_idx, WRITE);
445 CERROR("%s: cdt_llog_process() failed, rc=%d, cannot update "
446 "status for %u cookies, done %u\n",
447 mdt_obd_name(mdt), rc,
448 updates_count, ducb.updates_done);
453 * Agent actions /proc seq_file methods
454 * As llog processing uses a callback for each entry, we cannot do a sequential
455 * read. To limit calls to llog_cat_process (it spawns a thread), we fill
456 * multiple record in seq_file buffer in one show call.
457 * op->start() sets the iterator up and returns the first element of sequence
458 * op->stop() shuts it down.
459 * op->show() iterate llog and print element into the buffer.
460 * In case of error ->start() and ->next() return ERR_PTR(error)
461 * In the end of sequence they return %NULL
462 * op->show() returns 0 in case of success and negative number in case of error.
466 * seq_file iterator for agent_action entry
468 #define AGENT_ACTIONS_IT_MAGIC 0x19660426
469 struct agent_action_iterator {
470 int aai_magic; /**< magic number */
471 bool aai_eof; /**< all done */
472 struct lu_env aai_env; /**< lustre env for llog */
473 struct mdt_device *aai_mdt; /**< metadata device */
474 struct llog_ctxt *aai_ctxt; /**< llog context */
475 int aai_cat_index; /**< cata idx already shown */
476 int aai_index; /**< idx in cata shown */
480 * seq_file method called to start access to /proc file
481 * get llog context + llog handle
483 static void *mdt_hsm_actions_debugfs_start(struct seq_file *s, loff_t *pos)
485 struct agent_action_iterator *aai = s->private;
488 LASSERTF(aai->aai_magic == AGENT_ACTIONS_IT_MAGIC, "%08X\n",
491 aai->aai_ctxt = llog_get_context(mdt2obd_dev(aai->aai_mdt),
492 LLOG_AGENT_ORIG_CTXT);
493 if (aai->aai_ctxt == NULL || aai->aai_ctxt->loc_handle == NULL) {
494 CERROR("llog_get_context() failed\n");
495 RETURN(ERR_PTR(-ENOENT));
498 CDEBUG(D_HSM, "llog successfully initialized, start from %lld\n",
500 /* first call = rewind */
502 aai->aai_cat_index = 0;
504 aai->aai_eof = false;
514 static void *mdt_hsm_actions_debugfs_next(struct seq_file *s, void *v,
521 * llog_cat_process() callback, used to fill a seq_file buffer
523 static int hsm_actions_show_cb(const struct lu_env *env,
524 struct llog_handle *llh,
525 struct llog_rec_hdr *hdr,
528 struct llog_agent_req_rec *larr = (struct llog_agent_req_rec *)hdr;
529 struct seq_file *s = data;
530 struct agent_action_iterator *aai;
536 LASSERTF(aai->aai_magic == AGENT_ACTIONS_IT_MAGIC, "%08X\n",
539 /* if rec already printed => skip */
540 if (unlikely(llh->lgh_hdr->llh_cat_idx < aai->aai_cat_index))
543 if (unlikely(llh->lgh_hdr->llh_cat_idx == aai->aai_cat_index &&
544 hdr->lrh_index <= aai->aai_index))
547 sz = larr->arr_hai.hai_len - sizeof(larr->arr_hai);
548 seq_printf(s, "lrh=[type=%X len=%d idx=%d/%d] fid="DFID
549 " dfid="DFID" compound/cookie=%#llx/%#llx"
550 " action=%s archive#=%d flags=%#llx"
551 " extent=%#llx-%#llx"
552 " gid=%#llx datalen=%d status=%s data=[%s]\n",
553 hdr->lrh_type, hdr->lrh_len,
554 llh->lgh_hdr->llh_cat_idx, hdr->lrh_index,
555 PFID(&larr->arr_hai.hai_fid),
556 PFID(&larr->arr_hai.hai_dfid),
557 0ULL /* compound_id */, larr->arr_hai.hai_cookie,
558 hsm_copytool_action2name(larr->arr_hai.hai_action),
559 larr->arr_archive_id,
561 larr->arr_hai.hai_extent.offset,
562 larr->arr_hai.hai_extent.length,
563 larr->arr_hai.hai_gid, sz,
564 agent_req_status2name(larr->arr_status),
565 hai_dump_data_field(&larr->arr_hai, buf, sizeof(buf)));
567 aai->aai_cat_index = llh->lgh_hdr->llh_cat_idx;
568 aai->aai_index = hdr->lrh_index;
574 * mdt_hsm_actions_debugfs_show() is called at for each seq record
575 * process the llog, with a cb which fill the file_seq buffer
576 * to be faster, one show will fill multiple records
578 static int mdt_hsm_actions_debugfs_show(struct seq_file *s, void *v)
580 struct agent_action_iterator *aai = s->private;
581 struct coordinator *cdt = &aai->aai_mdt->mdt_coordinator;
585 LASSERTF(aai->aai_magic == AGENT_ACTIONS_IT_MAGIC, "%08X\n",
588 CDEBUG(D_HSM, "show from cat %d index %d eof=%d\n",
589 aai->aai_cat_index, aai->aai_index, aai->aai_eof);
593 down_read(&cdt->cdt_llog_lock);
594 rc = llog_cat_process(&aai->aai_env, aai->aai_ctxt->loc_handle,
595 hsm_actions_show_cb, s,
596 aai->aai_cat_index, aai->aai_index);
597 up_read(&cdt->cdt_llog_lock);
598 if (rc == 0) /* all llog parsed */
600 if (rc == LLOG_PROC_BREAK) /* buffer full */
606 * seq_file method called to stop access to /proc file
607 * clean + put llog context
609 static void mdt_hsm_actions_debugfs_stop(struct seq_file *s, void *v)
611 struct agent_action_iterator *aai = s->private;
614 LASSERTF(aai->aai_magic == AGENT_ACTIONS_IT_MAGIC, "%08X\n",
618 llog_ctxt_put(aai->aai_ctxt);
623 static const struct seq_operations mdt_hsm_actions_debugfs_ops = {
624 .start = mdt_hsm_actions_debugfs_start,
625 .next = mdt_hsm_actions_debugfs_next,
626 .show = mdt_hsm_actions_debugfs_show,
627 .stop = mdt_hsm_actions_debugfs_stop,
630 static int ldebugfs_open_hsm_actions(struct inode *inode, struct file *file)
632 struct agent_action_iterator *aai;
635 struct mdt_device *mdt;
638 rc = seq_open(file, &mdt_hsm_actions_debugfs_ops);
644 GOTO(err, rc = -ENOMEM);
646 aai->aai_magic = AGENT_ACTIONS_IT_MAGIC;
647 rc = lu_env_init(&aai->aai_env, LCT_LOCAL);
651 /* mdt is saved in seq_file->data by
652 * mdt_coordinator_tunables_init() calling
655 mdt = inode->i_private;
657 s = file->private_data;
663 seq_release(inode, file);
664 if (aai && aai->aai_env.le_ses)
665 OBD_FREE_PTR(aai->aai_env.le_ses);
673 * ldebugfs_release_hsm_actions() is called at end of /proc access.
674 * It frees allocated resources and calls cleanup lprocfs methods.
676 static int ldebugfs_release_hsm_actions(struct inode *inode, struct file *file)
678 struct seq_file *seq = file->private_data;
679 struct agent_action_iterator *aai = seq->private;
682 lu_env_fini(&aai->aai_env);
686 return seq_release(inode, file);
689 /* Methods to access HSM action list LLOG through /proc */
690 const struct file_operations mdt_hsm_actions_fops = {
691 .owner = THIS_MODULE,
692 .open = ldebugfs_open_hsm_actions,
695 .release = ldebugfs_release_hsm_actions,