/** * Start parent FID verification thread. * * See ofd_inconsistency_verification_main(). * * \param[in] ofd OFD device * * \retval 0 on successful start of thread * \retval negative value on error */ int ofd_start_inconsistency_verification_thread(struct ofd_device *ofd) { struct ptlrpc_thread *thread = &ofd->ofd_inconsistency_thread; struct l_wait_info lwi = { 0 }; struct task_struct *task; int rc; spin_lock(&ofd->ofd_inconsistency_lock); if (unlikely(thread_is_running(thread))) { spin_unlock(&ofd->ofd_inconsistency_lock); return -EALREADY; } thread_set_flags(thread, 0); spin_unlock(&ofd->ofd_inconsistency_lock); task = kthread_run(ofd_inconsistency_verification_main, ofd, "inconsistency_verification"); if (IS_ERR(task)) { rc = PTR_ERR(task); CERROR("%s: cannot start self_repair thread: rc = %d\n", ofd_name(ofd), rc); } else { rc = 0; l_wait_event(thread->t_ctl_waitq, thread_is_running(thread) || thread_is_stopped(thread), &lwi); } return rc; }
static int osd_scrub_next(const struct lu_env *env, struct osd_device *dev, struct lu_fid *fid, uint64_t *oid) { struct l_wait_info lwi = { 0 }; struct lustre_scrub *scrub = &dev->od_scrub; struct ptlrpc_thread *thread = &scrub->os_thread; struct osd_otable_it *it = dev->od_otable_it; struct lustre_mdt_attrs *lma = NULL; nvlist_t *nvbuf = NULL; int size = 0; int rc = 0; ENTRY; if (OBD_FAIL_CHECK(OBD_FAIL_OSD_SCRUB_DELAY) && cfs_fail_val > 0) { lwi = LWI_TIMEOUT(cfs_time_seconds(cfs_fail_val), NULL, NULL); if (likely(lwi.lwi_timeout > 0)) { l_wait_event(thread->t_ctl_waitq, !list_empty(&scrub->os_inconsistent_items) || !thread_is_running(thread), &lwi); if (unlikely(!thread_is_running(thread))) RETURN(SCRUB_NEXT_EXIT); } } if (OBD_FAIL_CHECK(OBD_FAIL_OSD_SCRUB_CRASH)) { spin_lock(&scrub->os_lock); thread_set_flags(thread, SVC_STOPPING); spin_unlock(&scrub->os_lock); RETURN(SCRUB_NEXT_CRASH); } if (OBD_FAIL_CHECK(OBD_FAIL_OSD_SCRUB_FATAL)) RETURN(SCRUB_NEXT_FATAL); again: if (nvbuf) { nvlist_free(nvbuf); nvbuf = NULL; lma = NULL; } if (!list_empty(&scrub->os_inconsistent_items)) { spin_lock(&scrub->os_lock); if (likely(!list_empty(&scrub->os_inconsistent_items))) { struct osd_inconsistent_item *oii; oii = list_entry(scrub->os_inconsistent_items.next, struct osd_inconsistent_item, oii_list); *fid = oii->oii_cache.oic_fid; *oid = oii->oii_cache.oic_dnode; scrub->os_in_prior = 1; spin_unlock(&scrub->os_lock); GOTO(out, rc = 0); } spin_unlock(&scrub->os_lock); }
void mdt_ck_thread_stop(struct mdt_device *mdt) { struct ptlrpc_thread *thread = &mdt->mdt_ck_thread; if (!thread_is_running(thread)) return; thread_set_flags(thread, SVC_STOPPING); wake_up(&thread->t_ctl_waitq); l_wait_condition(thread->t_ctl_waitq, thread_is_stopped(thread)); }
static int osd_scrub_post(const struct lu_env *env, struct osd_device *dev, int result) { struct lustre_scrub *scrub = &dev->od_scrub; struct scrub_file *sf = &scrub->os_file; int rc; ENTRY; CDEBUG(D_LFSCK, "%s: OI scrub post with result = %d\n", scrub->os_name, result); down_write(&scrub->os_rwsem); spin_lock(&scrub->os_lock); thread_set_flags(&scrub->os_thread, SVC_STOPPING); spin_unlock(&scrub->os_lock); if (scrub->os_new_checked > 0) { sf->sf_items_checked += scrub->os_new_checked; scrub->os_new_checked = 0; sf->sf_pos_last_checkpoint = scrub->os_pos_current; } sf->sf_time_last_checkpoint = ktime_get_real_seconds(); if (result > 0) { sf->sf_status = SS_COMPLETED; if (!(sf->sf_param & SP_DRYRUN)) { memset(sf->sf_oi_bitmap, 0, SCRUB_OI_BITMAP_SIZE); sf->sf_flags &= ~(SF_RECREATED | SF_INCONSISTENT | SF_UPGRADE | SF_AUTO); } sf->sf_time_last_complete = sf->sf_time_last_checkpoint; sf->sf_success_count++; } else if (result == 0) { if (scrub->os_paused) sf->sf_status = SS_PAUSED; else sf->sf_status = SS_STOPPED; } else { sf->sf_status = SS_FAILED; } sf->sf_run_time += ktime_get_seconds() - scrub->os_time_last_checkpoint; rc = scrub_file_store(env, scrub); up_write(&scrub->os_rwsem); RETURN(rc < 0 ? rc : result); }
/** * Stop parent FID verification thread. * * \param[in] ofd OFD device * * \retval 0 on successful start of thread * \retval -EALREADY if thread is already stopped */ int ofd_stop_inconsistency_verification_thread(struct ofd_device *ofd) { struct ptlrpc_thread *thread = &ofd->ofd_inconsistency_thread; struct l_wait_info lwi = { 0 }; spin_lock(&ofd->ofd_inconsistency_lock); if (thread_is_init(thread) || thread_is_stopped(thread)) { spin_unlock(&ofd->ofd_inconsistency_lock); return -EALREADY; } thread_set_flags(thread, SVC_STOPPING); spin_unlock(&ofd->ofd_inconsistency_lock); wake_up_all(&thread->t_ctl_waitq); l_wait_event(thread->t_ctl_waitq, thread_is_stopped(thread), &lwi); return 0; }
/* * Create a new qsd_instance to be associated with backend osd device * identified by \dev. * * \param env - the environment passed by the caller * \param svname - is the service name of the OSD device creating this instance * \param dev - is the dt_device where to store quota index files * \param osd_proc - is the procfs parent directory where to create procfs file * related to this new qsd instance * * \retval - pointer to new qsd_instance associated with dev \dev on success, * appropriate error on failure */ struct qsd_instance *qsd_init(const struct lu_env *env, char *svname, struct dt_device *dev, cfs_proc_dir_entry_t *osd_proc) { struct qsd_thread_info *qti = qsd_info(env); struct qsd_instance *qsd; int rc, type, idx; ENTRY; /* only configure qsd for MDT & OST */ type = server_name2index(svname, &idx, NULL); if (type != LDD_F_SV_TYPE_MDT && type != LDD_F_SV_TYPE_OST) RETURN(NULL); /* allocate qsd instance */ OBD_ALLOC_PTR(qsd); if (qsd == NULL) RETURN(ERR_PTR(-ENOMEM)); /* generic initializations */ rwlock_init(&qsd->qsd_lock); CFS_INIT_LIST_HEAD(&qsd->qsd_link); thread_set_flags(&qsd->qsd_upd_thread, SVC_STOPPED); init_waitqueue_head(&qsd->qsd_upd_thread.t_ctl_waitq); CFS_INIT_LIST_HEAD(&qsd->qsd_upd_list); spin_lock_init(&qsd->qsd_adjust_lock); CFS_INIT_LIST_HEAD(&qsd->qsd_adjust_list); qsd->qsd_prepared = false; qsd->qsd_started = false; /* copy service name */ if (strlcpy(qsd->qsd_svname, svname, sizeof(qsd->qsd_svname)) >= sizeof(qsd->qsd_svname)) GOTO(out, rc = -E2BIG); /* grab reference on osd device */ lu_device_get(&dev->dd_lu_dev); lu_ref_add(&dev->dd_lu_dev.ld_reference, "qsd", qsd); qsd->qsd_dev = dev; /* we only support pool ID 0 (default data or metadata pool) for the * time being. A different pool ID could be assigned to this target via * the configuration log in the future */ qsd->qsd_pool_id = 0; /* get fsname from svname */ rc = server_name2fsname(svname, qti->qti_buf, NULL); if (rc) { CERROR("%s: fail to extract filesystem name\n", svname); GOTO(out, rc); } /* look up quota setting for the filesystem the target belongs to */ qsd->qsd_fsinfo = qsd_get_fsinfo(qti->qti_buf, 1); if (qsd->qsd_fsinfo == NULL) { CERROR("%s: failed to locate filesystem information\n", svname); GOTO(out, rc = -EINVAL); } /* add in the list of lquota_fsinfo */ mutex_lock(&qsd->qsd_fsinfo->qfs_mutex); list_add_tail(&qsd->qsd_link, &qsd->qsd_fsinfo->qfs_qsd_list); mutex_unlock(&qsd->qsd_fsinfo->qfs_mutex); /* register procfs directory */ qsd->qsd_proc = lprocfs_seq_register(QSD_DIR, osd_proc, lprocfs_quota_qsd_vars, qsd); if (IS_ERR(qsd->qsd_proc)) { rc = PTR_ERR(qsd->qsd_proc); qsd->qsd_proc = NULL; CERROR("%s: fail to create quota slave proc entry (%d)\n", svname, rc); GOTO(out, rc); } EXIT; out: if (rc) { qsd_fini(env, qsd); return ERR_PTR(rc); } RETURN(qsd); }
/* * Allocate and initialize a qsd_qtype_info structure for quota type \qtype. * This opens the accounting object and initializes the proc file. * It's called on OSD start when the qsd_prepare() is invoked on the qsd * instance. * * \param env - the environment passed by the caller * \param qsd - is the qsd instance which will be in charge of the new * qsd_qtype_info instance. * \param qtype - is quota type to set up * * \retval - 0 on success and qsd->qsd_type_array[qtype] is allocated, * appropriate error on failure */ static int qsd_qtype_init(const struct lu_env *env, struct qsd_instance *qsd, int qtype) { struct qsd_qtype_info *qqi; int rc; struct obd_uuid uuid; ENTRY; LASSERT(qsd->qsd_type_array[qtype] == NULL); /* allocate structure for this quota type */ OBD_ALLOC_PTR(qqi); if (qqi == NULL) RETURN(-ENOMEM); qsd->qsd_type_array[qtype] = qqi; atomic_set(&qqi->qqi_ref, 1); /* referenced from qsd */ /* set backpointer and other parameters */ qqi->qqi_qsd = qsd; qqi->qqi_qtype = qtype; lu_ref_init(&qqi->qqi_reference); lquota_generate_fid(&qqi->qqi_fid, qsd->qsd_pool_id, QSD_RES_TYPE(qsd), qtype); qqi->qqi_glb_uptodate = false; qqi->qqi_slv_uptodate = false; qqi->qqi_reint = false; init_waitqueue_head(&qqi->qqi_reint_thread.t_ctl_waitq); thread_set_flags(&qqi->qqi_reint_thread, SVC_STOPPED); CFS_INIT_LIST_HEAD(&qqi->qqi_deferred_glb); CFS_INIT_LIST_HEAD(&qqi->qqi_deferred_slv); /* open accounting object */ LASSERT(qqi->qqi_acct_obj == NULL); qqi->qqi_acct_obj = acct_obj_lookup(env, qsd->qsd_dev, qtype); if (IS_ERR(qqi->qqi_acct_obj)) { CDEBUG(D_QUOTA, "%s: no %s space accounting support rc:%ld\n", qsd->qsd_svname, QTYPE_NAME(qtype), PTR_ERR(qqi->qqi_acct_obj)); qqi->qqi_acct_obj = NULL; qsd->qsd_acct_failed = true; } /* open global index copy */ LASSERT(qqi->qqi_glb_obj == NULL); qqi->qqi_glb_obj = lquota_disk_glb_find_create(env, qsd->qsd_dev, qsd->qsd_root, &qqi->qqi_fid, true); if (IS_ERR(qqi->qqi_glb_obj)) { CERROR("%s: can't open global index copy "DFID" %ld\n", qsd->qsd_svname, PFID(&qqi->qqi_fid), PTR_ERR(qqi->qqi_glb_obj)); GOTO(out, rc = PTR_ERR(qqi->qqi_glb_obj)); } qqi->qqi_glb_ver = dt_version_get(env, qqi->qqi_glb_obj); /* open slave index copy */ LASSERT(qqi->qqi_slv_obj == NULL); obd_str2uuid(&uuid, qsd->qsd_svname); qqi->qqi_slv_obj = lquota_disk_slv_find_create(env, qsd->qsd_dev, qsd->qsd_root, &qqi->qqi_fid, &uuid, true); if (IS_ERR(qqi->qqi_slv_obj)) { CERROR("%s: can't open slave index copy "DFID" %ld\n", qsd->qsd_svname, PFID(&qqi->qqi_fid), PTR_ERR(qqi->qqi_slv_obj)); GOTO(out, rc = PTR_ERR(qqi->qqi_slv_obj)); } qqi->qqi_slv_ver = dt_version_get(env, qqi->qqi_slv_obj); /* allocate site */ qqi->qqi_site = lquota_site_alloc(env, qqi, false, qtype, &qsd_lqe_ops); if (IS_ERR(qqi->qqi_site)) { CERROR("%s: can't allocate site "DFID" %ld\n", qsd->qsd_svname, PFID(&qqi->qqi_fid), PTR_ERR(qqi->qqi_site)); GOTO(out, rc = PTR_ERR(qqi->qqi_site)); } /* register proc entry for accounting & global index copy objects */ rc = lprocfs_seq_create(qsd->qsd_proc, qtype == USRQUOTA ? "acct_user" : "acct_group", 0444, &lprocfs_quota_seq_fops, qqi->qqi_acct_obj); if (rc) { CERROR("%s: can't add procfs entry for accounting file %d\n", qsd->qsd_svname, rc); GOTO(out, rc); } rc = lprocfs_seq_create(qsd->qsd_proc, qtype == USRQUOTA ? "limit_user" : "limit_group", 0444, &lprocfs_quota_seq_fops, qqi->qqi_glb_obj); if (rc) { CERROR("%s: can't add procfs entry for global index copy %d\n", qsd->qsd_svname, rc); GOTO(out, rc); } EXIT; out: if (rc) qsd_qtype_fini(env, qsd, qtype); return rc; }
/** * Verification thread to check parent FID consistency. * * Kernel thread to check consistency of parent FID for any * new item added for checking by ofd_add_inconsistency_item(). * * \param[in] args OFD device * * \retval 0 on successful thread termination * \retval negative value if thread can't start */ static int ofd_inconsistency_verification_main(void *args) { struct lu_env env; struct ofd_device *ofd = args; struct ptlrpc_thread *thread = &ofd->ofd_inconsistency_thread; struct ofd_inconsistency_item *oii; struct lfsck_request *lr = NULL; struct l_wait_info lwi = { 0 }; int rc; ENTRY; rc = lu_env_init(&env, LCT_DT_THREAD); spin_lock(&ofd->ofd_inconsistency_lock); thread_set_flags(thread, rc != 0 ? SVC_STOPPED : SVC_RUNNING); wake_up_all(&thread->t_ctl_waitq); spin_unlock(&ofd->ofd_inconsistency_lock); if (rc != 0) RETURN(rc); OBD_ALLOC_PTR(lr); if (unlikely(lr == NULL)) GOTO(out_unlocked, rc = -ENOMEM); lr->lr_event = LE_PAIRS_VERIFY; lr->lr_active = LFSCK_TYPE_LAYOUT; spin_lock(&ofd->ofd_inconsistency_lock); while (1) { if (unlikely(!thread_is_running(thread))) break; while (!list_empty(&ofd->ofd_inconsistency_list)) { oii = list_entry(ofd->ofd_inconsistency_list.next, struct ofd_inconsistency_item, oii_list); list_del_init(&oii->oii_list); spin_unlock(&ofd->ofd_inconsistency_lock); ofd_inconsistency_verify_one(&env, ofd, oii, lr); spin_lock(&ofd->ofd_inconsistency_lock); } spin_unlock(&ofd->ofd_inconsistency_lock); l_wait_event(thread->t_ctl_waitq, !list_empty(&ofd->ofd_inconsistency_list) || !thread_is_running(thread), &lwi); spin_lock(&ofd->ofd_inconsistency_lock); } while (!list_empty(&ofd->ofd_inconsistency_list)) { struct ofd_object *fo; oii = list_entry(ofd->ofd_inconsistency_list.next, struct ofd_inconsistency_item, oii_list); list_del_init(&oii->oii_list); fo = oii->oii_obj; spin_unlock(&ofd->ofd_inconsistency_lock); ofd_write_lock(&env, fo); fo->ofo_pfid_checking = 0; ofd_write_unlock(&env, fo); lu_object_put(&env, &fo->ofo_obj.do_lu); OBD_FREE_PTR(oii); spin_lock(&ofd->ofd_inconsistency_lock); } OBD_FREE_PTR(lr); GOTO(out, rc = 0); out_unlocked: spin_lock(&ofd->ofd_inconsistency_lock); out: thread_set_flags(thread, SVC_STOPPED); wake_up_all(&thread->t_ctl_waitq); spin_unlock(&ofd->ofd_inconsistency_lock); lu_env_fini(&env); return rc; }
/* * Initialize quota master target device. This includers connecting to * the backend OSD device, initializing the pool configuration and creating the * root procfs directory dedicated to this quota target. * The rest of the initialization is done when the stack is fully configured * (i.e. when ->ldo_start is called across the stack). * * This function is called on MDT0 setup. * * \param env - is the environment passed by the caller * \param qmt - is the quota master target to be initialized * \param ldt - is the device type structure associated with the qmt device * \param cfg - is the configuration record used to configure the qmt device * * \retval - 0 on success, appropriate error on failure */ static int qmt_device_init0(const struct lu_env *env, struct qmt_device *qmt, struct lu_device_type *ldt, struct lustre_cfg *cfg) { struct lu_device *ld = qmt2lu_dev(qmt); struct obd_device *obd, *mdt_obd; struct obd_type *type; int rc; ENTRY; /* record who i am, it might be useful ... */ strncpy(qmt->qmt_svname, lustre_cfg_string(cfg, 0), sizeof(qmt->qmt_svname) - 1); /* look-up the obd_device associated with the qmt */ obd = class_name2obd(qmt->qmt_svname); if (obd == NULL) RETURN(-ENOENT); /* reference each other */ obd->obd_lu_dev = ld; ld->ld_obd = obd; /* look-up the parent MDT to steal its ldlm namespace ... */ mdt_obd = class_name2obd(lustre_cfg_string(cfg, 2)); if (mdt_obd == NULL) RETURN(-ENOENT); /* borrow MDT namespace. kind of a hack until we have our own namespace * & service threads */ LASSERT(mdt_obd->obd_namespace != NULL); obd->obd_namespace = mdt_obd->obd_namespace; qmt->qmt_ns = obd->obd_namespace; /* connect to backend osd device */ rc = qmt_connect_to_osd(env, qmt, cfg); if (rc) GOTO(out, rc); /* set up and start rebalance thread */ thread_set_flags(&qmt->qmt_reba_thread, SVC_STOPPED); init_waitqueue_head(&qmt->qmt_reba_thread.t_ctl_waitq); CFS_INIT_LIST_HEAD(&qmt->qmt_reba_list); spin_lock_init(&qmt->qmt_reba_lock); rc = qmt_start_reba_thread(qmt); if (rc) { CERROR("%s: failed to start rebalance thread (%d)\n", qmt->qmt_svname, rc); GOTO(out, rc); } /* at the moment there is no linkage between lu_type and obd_type, so * we lookup obd_type this way */ type = class_search_type(LUSTRE_QMT_NAME); LASSERT(type != NULL); /* register proc directory associated with this qmt */ qmt->qmt_proc = lprocfs_register(qmt->qmt_svname, type->typ_procroot, NULL, NULL); if (IS_ERR(qmt->qmt_proc)) { rc = PTR_ERR(qmt->qmt_proc); CERROR("%s: failed to create qmt proc entry (%d)\n", qmt->qmt_svname, rc); GOTO(out, rc); } /* initialize pool configuration */ rc = qmt_pool_init(env, qmt); if (rc) GOTO(out, rc); EXIT; out: if (rc) qmt_device_fini(env, ld); return rc; }
static int osd_scrub_prep(const struct lu_env *env, struct osd_device *dev) { struct lustre_scrub *scrub = &dev->od_scrub; struct ptlrpc_thread *thread = &scrub->os_thread; struct scrub_file *sf = &scrub->os_file; __u32 flags = scrub->os_start_flags; int rc; bool drop_dryrun = false; ENTRY; CDEBUG(D_LFSCK, "%s: OI scrub prep, flags = 0x%x\n", scrub->os_name, flags); down_write(&scrub->os_rwsem); if (flags & SS_SET_FAILOUT) sf->sf_param |= SP_FAILOUT; else if (flags & SS_CLEAR_FAILOUT) sf->sf_param &= ~SP_FAILOUT; if (flags & SS_SET_DRYRUN) { sf->sf_param |= SP_DRYRUN; } else if (flags & SS_CLEAR_DRYRUN && sf->sf_param & SP_DRYRUN) { sf->sf_param &= ~SP_DRYRUN; drop_dryrun = true; } if (flags & SS_RESET) scrub_file_reset(scrub, dev->od_uuid, 0); scrub->os_partial_scan = 0; if (flags & SS_AUTO_FULL) { scrub->os_full_speed = 1; sf->sf_flags |= SF_AUTO; } else if (sf->sf_flags & (SF_RECREATED | SF_INCONSISTENT | SF_UPGRADE)) { scrub->os_full_speed = 1; } else { scrub->os_full_speed = 0; } spin_lock(&scrub->os_lock); scrub->os_in_prior = 0; scrub->os_waiting = 0; scrub->os_paused = 0; scrub->os_in_join = 0; scrub->os_full_scrub = 0; spin_unlock(&scrub->os_lock); scrub->os_new_checked = 0; if (drop_dryrun && sf->sf_pos_first_inconsistent != 0) sf->sf_pos_latest_start = sf->sf_pos_first_inconsistent; else if (sf->sf_pos_last_checkpoint != 0) sf->sf_pos_latest_start = sf->sf_pos_last_checkpoint + 1; else sf->sf_pos_latest_start = 1; scrub->os_pos_current = sf->sf_pos_latest_start; sf->sf_status = SS_SCANNING; sf->sf_time_latest_start = ktime_get_real_seconds(); sf->sf_time_last_checkpoint = sf->sf_time_latest_start; sf->sf_pos_last_checkpoint = sf->sf_pos_latest_start - 1; rc = scrub_file_store(env, scrub); if (!rc) { spin_lock(&scrub->os_lock); thread_set_flags(thread, SVC_RUNNING); spin_unlock(&scrub->os_lock); wake_up_all(&thread->t_ctl_waitq); } up_write(&scrub->os_rwsem); RETURN(rc); }
int lfsck_master_engine(void *args) { struct lfsck_thread_args *lta = args; struct lu_env *env = <a->lta_env; struct lfsck_instance *lfsck = lta->lta_lfsck; struct ptlrpc_thread *thread = &lfsck->li_thread; struct dt_object *oit_obj = lfsck->li_obj_oit; const struct dt_it_ops *oit_iops = &oit_obj->do_index_ops->dio_it; struct dt_it *oit_di; struct l_wait_info lwi = { 0 }; int rc; ENTRY; oit_di = oit_iops->init(env, oit_obj, lfsck->li_args_oit, BYPASS_CAPA); if (IS_ERR(oit_di)) { rc = PTR_ERR(oit_di); CERROR("%s: LFSCK, fail to init iteration: rc = %d\n", lfsck_lfsck2name(lfsck), rc); GOTO(fini_args, rc); } spin_lock(&lfsck->li_lock); lfsck->li_di_oit = oit_di; spin_unlock(&lfsck->li_lock); rc = lfsck_prep(env, lfsck, lta->lta_lsp); if (rc != 0) GOTO(fini_oit, rc); CDEBUG(D_LFSCK, "LFSCK entry: oit_flags = %#x, dir_flags = %#x, " "oit_cookie = "LPU64", dir_cookie = "LPU64", parent = "DFID ", pid = %d\n", lfsck->li_args_oit, lfsck->li_args_dir, lfsck->li_pos_current.lp_oit_cookie, lfsck->li_pos_current.lp_dir_cookie, PFID(&lfsck->li_pos_current.lp_dir_parent), current_pid()); spin_lock(&lfsck->li_lock); thread_set_flags(thread, SVC_RUNNING); spin_unlock(&lfsck->li_lock); wake_up_all(&thread->t_ctl_waitq); l_wait_event(thread->t_ctl_waitq, lfsck->li_start_unplug || !thread_is_running(thread), &lwi); if (!thread_is_running(thread)) GOTO(fini_oit, rc = 0); if (!cfs_list_empty(&lfsck->li_list_scan) || cfs_list_empty(&lfsck->li_list_double_scan)) rc = lfsck_master_oit_engine(env, lfsck); else rc = 1; CDEBUG(D_LFSCK, "LFSCK exit: oit_flags = %#x, dir_flags = %#x, " "oit_cookie = "LPU64", dir_cookie = "LPU64", parent = "DFID ", pid = %d, rc = %d\n", lfsck->li_args_oit, lfsck->li_args_dir, lfsck->li_pos_current.lp_oit_cookie, lfsck->li_pos_current.lp_dir_cookie, PFID(&lfsck->li_pos_current.lp_dir_parent), current_pid(), rc); if (!OBD_FAIL_CHECK(OBD_FAIL_LFSCK_CRASH)) rc = lfsck_post(env, lfsck, rc); if (lfsck->li_di_dir != NULL) lfsck_close_dir(env, lfsck); fini_oit: lfsck_di_oit_put(env, lfsck); oit_iops->fini(env, oit_di); if (rc == 1) { if (!cfs_list_empty(&lfsck->li_list_double_scan)) rc = lfsck_double_scan(env, lfsck); else rc = 0; } else { lfsck_quit(env, lfsck); } /* XXX: Purge the pinned objects in the future. */ fini_args: spin_lock(&lfsck->li_lock); thread_set_flags(thread, SVC_STOPPED); spin_unlock(&lfsck->li_lock); wake_up_all(&thread->t_ctl_waitq); lfsck_thread_args_fini(lta); return rc; }
static int lfsck_master_oit_engine(const struct lu_env *env, struct lfsck_instance *lfsck) { struct lfsck_thread_info *info = lfsck_env_info(env); const struct dt_it_ops *iops = &lfsck->li_obj_oit->do_index_ops->dio_it; struct dt_it *di = lfsck->li_di_oit; struct lu_fid *fid = &info->lti_fid; struct lfsck_bookmark *bk = &lfsck->li_bookmark_ram; struct ptlrpc_thread *thread = &lfsck->li_thread; __u32 idx = lfsck_dev_idx(lfsck->li_bottom); int rc; ENTRY; do { struct dt_object *target; bool update_lma = false; if (lfsck->li_di_dir != NULL) { rc = lfsck_master_dir_engine(env, lfsck); if (rc <= 0) RETURN(rc); } if (unlikely(lfsck->li_oit_over)) RETURN(1); if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_DELAY1) && cfs_fail_val > 0) { struct l_wait_info lwi; lwi = LWI_TIMEOUT(cfs_time_seconds(cfs_fail_val), NULL, NULL); l_wait_event(thread->t_ctl_waitq, !thread_is_running(thread), &lwi); } if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_CRASH)) RETURN(0); lfsck->li_current_oit_processed = 1; lfsck->li_new_scanned++; rc = iops->rec(env, di, (struct dt_rec *)fid, 0); if (rc != 0) { lfsck_fail(env, lfsck, true); if (rc < 0 && bk->lb_param & LPF_FAILOUT) RETURN(rc); else goto checkpoint; } if (fid_is_idif(fid)) { __u32 idx1 = fid_idif_ost_idx(fid); LASSERT(!lfsck->li_master); /* It is an old format device, update the LMA. */ if (idx != idx1) { struct ost_id *oi = &info->lti_oi; fid_to_ostid(fid, oi); ostid_to_fid(fid, oi, idx); update_lma = true; } } else if (!fid_is_norm(fid) && !fid_is_igif(fid) && !fid_is_last_id(fid) && !fid_is_root(fid) && !fid_seq_is_dot(fid_seq(fid))) { /* If the FID/object is only used locally and invisible * to external nodes, then LFSCK will not handle it. */ goto checkpoint; } target = lfsck_object_find(env, lfsck, fid); if (target == NULL) { goto checkpoint; } else if (IS_ERR(target)) { lfsck_fail(env, lfsck, true); if (bk->lb_param & LPF_FAILOUT) RETURN(PTR_ERR(target)); else goto checkpoint; } /* XXX: Currently, skip remote object, the consistency for * remote object will be processed in LFSCK phase III. */ if (dt_object_exists(target) && !dt_object_remote(target)) { if (update_lma) rc = lfsck_update_lma(env, lfsck, target); if (rc == 0) rc = lfsck_exec_oit(env, lfsck, target); } lfsck_object_put(env, target); if (rc != 0 && bk->lb_param & LPF_FAILOUT) RETURN(rc); checkpoint: rc = lfsck_checkpoint(env, lfsck); if (rc != 0 && bk->lb_param & LPF_FAILOUT) RETURN(rc); /* Rate control. */ lfsck_control_speed(lfsck); if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_FATAL1)) { spin_lock(&lfsck->li_lock); thread_set_flags(thread, SVC_STOPPING); spin_unlock(&lfsck->li_lock); RETURN(-EINVAL); } rc = iops->next(env, di); if (unlikely(rc > 0)) lfsck->li_oit_over = 1; else if (likely(rc == 0)) lfsck->li_current_oit_processed = 0; if (unlikely(!thread_is_running(thread))) RETURN(0); } while (rc == 0 || lfsck->li_di_dir != NULL); RETURN(rc); }
static int lfsck_master_dir_engine(const struct lu_env *env, struct lfsck_instance *lfsck) { struct lfsck_thread_info *info = lfsck_env_info(env); const struct dt_it_ops *iops = &lfsck->li_obj_dir->do_index_ops->dio_it; struct dt_it *di = lfsck->li_di_dir; struct lu_dirent *ent = &info->lti_ent; struct lu_fid *fid = &info->lti_fid; struct lfsck_bookmark *bk = &lfsck->li_bookmark_ram; struct ptlrpc_thread *thread = &lfsck->li_thread; int rc; ENTRY; do { struct dt_object *child; if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_DELAY2) && cfs_fail_val > 0) { struct l_wait_info lwi; lwi = LWI_TIMEOUT(cfs_time_seconds(cfs_fail_val), NULL, NULL); l_wait_event(thread->t_ctl_waitq, !thread_is_running(thread), &lwi); } lfsck->li_new_scanned++; rc = iops->rec(env, di, (struct dt_rec *)ent, lfsck->li_args_dir); lfsck_unpack_ent(ent, &lfsck->li_cookie_dir); if (rc != 0) { lfsck_fail(env, lfsck, true); if (bk->lb_param & LPF_FAILOUT) RETURN(rc); else goto checkpoint; } if (ent->lde_attrs & LUDA_IGNORE) goto checkpoint; *fid = ent->lde_fid; child = lfsck_object_find(env, lfsck, fid); if (child == NULL) { goto checkpoint; } else if (IS_ERR(child)) { lfsck_fail(env, lfsck, true); if (bk->lb_param & LPF_FAILOUT) RETURN(PTR_ERR(child)); else goto checkpoint; } /* XXX: Currently, skip remote object, the consistency for * remote object will be processed in LFSCK phase III. */ if (dt_object_exists(child) && !dt_object_remote(child)) rc = lfsck_exec_dir(env, lfsck, child, ent); lfsck_object_put(env, child); if (rc != 0 && bk->lb_param & LPF_FAILOUT) RETURN(rc); checkpoint: rc = lfsck_checkpoint(env, lfsck); if (rc != 0 && bk->lb_param & LPF_FAILOUT) RETURN(rc); /* Rate control. */ lfsck_control_speed(lfsck); if (unlikely(!thread_is_running(thread))) RETURN(0); if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_FATAL2)) { spin_lock(&lfsck->li_lock); thread_set_flags(thread, SVC_STOPPING); spin_unlock(&lfsck->li_lock); RETURN(-EINVAL); } rc = iops->next(env, di); } while (rc == 0); if (rc > 0 && !lfsck->li_oit_over) lfsck_close_dir(env, lfsck); RETURN(rc); }
static int mdt_ck_thread_main(void *args) { struct mdt_device *mdt = args; struct ptlrpc_thread *thread = &mdt->mdt_ck_thread; struct lustre_capa_key *bkey = &mdt->mdt_capa_keys[0], *rkey = &mdt->mdt_capa_keys[1]; struct lustre_capa_key *tmp; struct lu_env env; struct mdt_thread_info *info; struct md_device *next; struct l_wait_info lwi = { 0 }; mdsno_t mdsnum; int rc; ENTRY; unshare_fs_struct(); cfs_block_allsigs(); thread_set_flags(thread, SVC_RUNNING); wake_up(&thread->t_ctl_waitq); rc = lu_env_init(&env, LCT_MD_THREAD|LCT_REMEMBER|LCT_NOREF); if (rc) RETURN(rc); thread->t_env = &env; env.le_ctx.lc_thread = thread; env.le_ctx.lc_cookie = 0x1; info = lu_context_key_get(&env.le_ctx, &mdt_thread_key); LASSERT(info != NULL); tmp = &info->mti_capa_key; mdsnum = mdt_seq_site(mdt)->ss_node_id; while (1) { l_wait_event(thread->t_ctl_waitq, thread_is_stopping(thread) || thread_is_event(thread), &lwi); if (thread_is_stopping(thread)) break; thread_clear_flags(thread, SVC_EVENT); if (cfs_time_before(cfs_time_current(), mdt->mdt_ck_expiry)) break; *tmp = *rkey; make_capa_key(tmp, mdsnum, rkey->lk_keyid); next = mdt->mdt_child; rc = next->md_ops->mdo_update_capa_key(&env, next, tmp); if (!rc) { spin_lock(&capa_lock); *bkey = *rkey; *rkey = *tmp; spin_unlock(&capa_lock); rc = write_capa_keys(&env, mdt, mdt->mdt_capa_keys); if (rc) { spin_lock(&capa_lock); *rkey = *bkey; memset(bkey, 0, sizeof(*bkey)); spin_unlock(&capa_lock); } else { set_capa_key_expiry(mdt); DEBUG_CAPA_KEY(D_SEC, rkey, "new"); } } if (rc) { DEBUG_CAPA_KEY(D_ERROR, rkey, "update failed for"); /* next retry is in 300 sec */ mdt->mdt_ck_expiry = jiffies + 300 * HZ; } cfs_timer_arm(&mdt->mdt_ck_timer, mdt->mdt_ck_expiry); CDEBUG(D_SEC, "mdt_ck_timer %lu\n", mdt->mdt_ck_expiry); } lu_env_fini(&env); thread_set_flags(thread, SVC_STOPPED); wake_up(&thread->t_ctl_waitq); RETURN(0); }