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 cdt->cdt_last_cookie++;
296 larr->arr_hai.hai_cookie = cdt->cdt_last_cookie;
299 rc = llog_cat_add(env, lctxt->loc_handle, &larr->arr_hdr, NULL);
303 up_write(&cdt->cdt_llog_lock);
304 llog_ctxt_put(lctxt);
313 * data passed to llog_cat_process() callback
316 struct data_update_cb {
317 struct mdt_device *mdt;
318 struct hsm_record_update *updates;
319 unsigned int updates_count;
320 unsigned int updates_done;
321 time64_t change_time;
325 * llog_cat_process() callback, used to update a record
326 * \param env [IN] environment
327 * \param llh [IN] llog handle
328 * \param hdr [IN] llog record
329 * \param data [IN] cb data = data_update_cb
331 * \retval -ve failure
333 static int mdt_agent_record_update_cb(const struct lu_env *env,
334 struct llog_handle *llh,
335 struct llog_rec_hdr *hdr,
338 struct llog_agent_req_rec *larr;
339 struct data_update_cb *ducb;
343 larr = (struct llog_agent_req_rec *)hdr;
346 /* check if all done */
347 if (ducb->updates_count == ducb->updates_done)
348 RETURN(LLOG_PROC_BREAK);
350 /* if record is in final state, never change */
351 if (agent_req_in_final_state(larr->arr_status))
355 for (i = 0 ; i < ducb->updates_count ; i++) {
356 struct hsm_record_update *update = &ducb->updates[i];
358 CDEBUG(D_HSM, "%s: search %#llx, found %#llx\n",
359 mdt_obd_name(ducb->mdt), update->cookie,
360 larr->arr_hai.hai_cookie);
361 if (larr->arr_hai.hai_cookie == update->cookie) {
363 /* If record is a cancel request, it cannot be
364 * canceled. This is to manage the following
365 * case: when a request is canceled, we have 2
366 * records with the the same cookie: the one
367 * to cancel and the cancel request the 1st
368 * has to be set to ARS_CANCELED and the 2nd
371 if (larr->arr_hai.hai_action == HSMA_CANCEL &&
372 update->status == ARS_CANCELED)
375 larr->arr_status = update->status;
376 larr->arr_req_change = ducb->change_time;
377 rc = llog_write(env, llh, hdr, hdr->lrh_index);
378 ducb->updates_done++;
384 CERROR("%s: mdt_agent_llog_update_rec() failed, rc = %d\n",
385 mdt_obd_name(ducb->mdt), rc);
391 * update an entry in agent llog
393 * \param env [IN] environment
394 * \param mdt [IN] MDT device
395 * \param updates [IN] array of entries to update
396 * \param updates_count [IN] number of entries in updates
398 * \retval 0 on success
399 * \retval negative on failure
401 int mdt_agent_record_update(const struct lu_env *env, struct mdt_device *mdt,
402 struct hsm_record_update *updates,
403 unsigned int updates_count)
405 struct data_update_cb ducb;
406 u32 start_cat_idx = -1;
407 u32 start_rec_idx = -1;
414 /* Find the first location (start_cat_idx, start_rec_idx)
415 * among the records corresponding to cookies. */
416 for (i = 0; i < updates_count; i++) {
417 /* If we cannot find a cached location for a cookie
418 * (perhaps because the MDT was restart then we must
419 * start from the beginning. In this case
420 * mdt_agent_record_hash_get() sets both of cat_idx and
422 cdt_agent_record_hash_lookup(&mdt->mdt_coordinator,
425 if (cat_idx < start_cat_idx) {
426 start_cat_idx = cat_idx;
427 start_rec_idx = rec_idx;
428 } else if (cat_idx == start_cat_idx &&
429 rec_idx < start_rec_idx) {
430 start_rec_idx = rec_idx;
434 /* Fixup starting record index for llog_cat_process(). */
435 if (start_rec_idx != 0)
439 ducb.updates = updates;
440 ducb.updates_count = updates_count;
441 ducb.updates_done = 0;
442 ducb.change_time = ktime_get_real_seconds();
444 rc = cdt_llog_process(env, mdt, mdt_agent_record_update_cb, &ducb,
445 start_cat_idx, start_rec_idx, WRITE);
447 CERROR("%s: cdt_llog_process() failed, rc=%d, cannot update "
448 "status for %u cookies, done %u\n",
449 mdt_obd_name(mdt), rc,
450 updates_count, ducb.updates_done);
455 * Agent actions /proc seq_file methods
456 * As llog processing uses a callback for each entry, we cannot do a sequential
457 * read. To limit calls to llog_cat_process (it spawns a thread), we fill
458 * multiple record in seq_file buffer in one show call.
459 * op->start() sets the iterator up and returns the first element of sequence
460 * op->stop() shuts it down.
461 * op->show() iterate llog and print element into the buffer.
462 * In case of error ->start() and ->next() return ERR_PTR(error)
463 * In the end of sequence they return %NULL
464 * op->show() returns 0 in case of success and negative number in case of error.
468 * seq_file iterator for agent_action entry
470 #define AGENT_ACTIONS_IT_MAGIC 0x19660426
471 struct agent_action_iterator {
472 int aai_magic; /**< magic number */
473 bool aai_eof; /**< all done */
474 struct lu_env aai_env; /**< lustre env for llog */
475 struct mdt_device *aai_mdt; /**< metadata device */
476 struct llog_ctxt *aai_ctxt; /**< llog context */
477 int aai_cat_index; /**< cata idx already shown */
478 int aai_index; /**< idx in cata shown */
482 * seq_file method called to start access to /proc file
483 * get llog context + llog handle
485 static void *mdt_hsm_actions_proc_start(struct seq_file *s, loff_t *pos)
487 struct agent_action_iterator *aai = s->private;
490 LASSERTF(aai->aai_magic == AGENT_ACTIONS_IT_MAGIC, "%08X\n",
493 aai->aai_ctxt = llog_get_context(mdt2obd_dev(aai->aai_mdt),
494 LLOG_AGENT_ORIG_CTXT);
495 if (aai->aai_ctxt == NULL || aai->aai_ctxt->loc_handle == NULL) {
496 CERROR("llog_get_context() failed\n");
497 RETURN(ERR_PTR(-ENOENT));
500 CDEBUG(D_HSM, "llog successfully initialized, start from %lld\n",
502 /* first call = rewind */
504 aai->aai_cat_index = 0;
506 aai->aai_eof = false;
516 static void *mdt_hsm_actions_proc_next(struct seq_file *s, void *v,
523 * llog_cat_process() callback, used to fill a seq_file buffer
525 static int hsm_actions_show_cb(const struct lu_env *env,
526 struct llog_handle *llh,
527 struct llog_rec_hdr *hdr,
530 struct llog_agent_req_rec *larr = (struct llog_agent_req_rec *)hdr;
531 struct seq_file *s = data;
532 struct agent_action_iterator *aai;
538 LASSERTF(aai->aai_magic == AGENT_ACTIONS_IT_MAGIC, "%08X\n",
541 /* if rec already printed => skip */
542 if (unlikely(llh->lgh_hdr->llh_cat_idx < aai->aai_cat_index))
545 if (unlikely(llh->lgh_hdr->llh_cat_idx == aai->aai_cat_index &&
546 hdr->lrh_index <= aai->aai_index))
549 sz = larr->arr_hai.hai_len - sizeof(larr->arr_hai);
550 seq_printf(s, "lrh=[type=%X len=%d idx=%d/%d] fid="DFID
551 " dfid="DFID" compound/cookie=%#llx/%#llx"
552 " action=%s archive#=%d flags=%#llx"
553 " extent=%#llx-%#llx"
554 " gid=%#llx datalen=%d status=%s data=[%s]\n",
555 hdr->lrh_type, hdr->lrh_len,
556 llh->lgh_hdr->llh_cat_idx, hdr->lrh_index,
557 PFID(&larr->arr_hai.hai_fid),
558 PFID(&larr->arr_hai.hai_dfid),
559 0ULL /* compound_id */, larr->arr_hai.hai_cookie,
560 hsm_copytool_action2name(larr->arr_hai.hai_action),
561 larr->arr_archive_id,
563 larr->arr_hai.hai_extent.offset,
564 larr->arr_hai.hai_extent.length,
565 larr->arr_hai.hai_gid, sz,
566 agent_req_status2name(larr->arr_status),
567 hai_dump_data_field(&larr->arr_hai, buf, sizeof(buf)));
569 aai->aai_cat_index = llh->lgh_hdr->llh_cat_idx;
570 aai->aai_index = hdr->lrh_index;
576 * mdt_hsm_actions_proc_show() is called at for each seq record
577 * process the llog, with a cb which fill the file_seq buffer
578 * to be faster, one show will fill multiple records
580 static int mdt_hsm_actions_proc_show(struct seq_file *s, void *v)
582 struct agent_action_iterator *aai = s->private;
583 struct coordinator *cdt = &aai->aai_mdt->mdt_coordinator;
587 LASSERTF(aai->aai_magic == AGENT_ACTIONS_IT_MAGIC, "%08X\n",
590 CDEBUG(D_HSM, "show from cat %d index %d eof=%d\n",
591 aai->aai_cat_index, aai->aai_index, aai->aai_eof);
595 down_read(&cdt->cdt_llog_lock);
596 rc = llog_cat_process(&aai->aai_env, aai->aai_ctxt->loc_handle,
597 hsm_actions_show_cb, s,
598 aai->aai_cat_index, aai->aai_index);
599 up_read(&cdt->cdt_llog_lock);
600 if (rc == 0) /* all llog parsed */
602 if (rc == LLOG_PROC_BREAK) /* buffer full */
608 * seq_file method called to stop access to /proc file
609 * clean + put llog context
611 static void mdt_hsm_actions_proc_stop(struct seq_file *s, void *v)
613 struct agent_action_iterator *aai = s->private;
616 LASSERTF(aai->aai_magic == AGENT_ACTIONS_IT_MAGIC, "%08X\n",
620 llog_ctxt_put(aai->aai_ctxt);
626 static const struct seq_operations mdt_hsm_actions_proc_ops = {
627 .start = mdt_hsm_actions_proc_start,
628 .next = mdt_hsm_actions_proc_next,
629 .show = mdt_hsm_actions_proc_show,
630 .stop = mdt_hsm_actions_proc_stop,
633 static int lprocfs_open_hsm_actions(struct inode *inode, struct file *file)
635 struct agent_action_iterator *aai;
638 struct mdt_device *mdt;
641 rc = seq_open(file, &mdt_hsm_actions_proc_ops);
647 GOTO(err, rc = -ENOMEM);
649 aai->aai_magic = AGENT_ACTIONS_IT_MAGIC;
650 rc = lu_env_init(&aai->aai_env, LCT_LOCAL);
654 /* mdt is saved in proc_dir_entry->data by
655 * mdt_coordinator_procfs_init() calling lprocfs_register()
657 mdt = (struct mdt_device *)PDE_DATA(inode);
659 s = file->private_data;
665 lprocfs_seq_release(inode, file);
666 if (aai && aai->aai_env.le_ses)
667 OBD_FREE_PTR(aai->aai_env.le_ses);
675 * lprocfs_release_hsm_actions() is called at end of /proc access.
676 * It frees allocated resources and calls cleanup lprocfs methods.
678 static int lprocfs_release_hsm_actions(struct inode *inode, struct file *file)
680 struct seq_file *seq = file->private_data;
681 struct agent_action_iterator *aai = seq->private;
684 lu_env_fini(&aai->aai_env);
688 return lprocfs_seq_release(inode, file);
691 /* Methods to access HSM action list LLOG through /proc */
692 const struct file_operations mdt_hsm_actions_fops = {
693 .owner = THIS_MODULE,
694 .open = lprocfs_open_hsm_actions,
697 .release = lprocfs_release_hsm_actions,