void lc_watchdog_delete(struct lc_watchdog *lcw) { int dead; ENTRY; LASSERT(lcw != NULL); cfs_timer_disarm(&lcw->lcw_timer); lcw_update_time(lcw, "stopped"); cfs_spin_lock_bh(&lcw->lcw_lock); cfs_spin_lock_bh(&lcw_pending_timers_lock); if (unlikely(!cfs_list_empty(&lcw->lcw_list))) { cfs_list_del_init(&lcw->lcw_list); lcw->lcw_refcount--; /* -1 ref for pending list */ } lcw->lcw_refcount--; /* -1 ref for owner */ dead = lcw->lcw_refcount == 0; cfs_spin_unlock_bh(&lcw_pending_timers_lock); cfs_spin_unlock_bh(&lcw->lcw_lock); if (dead) LIBCFS_FREE(lcw, sizeof(*lcw)); cfs_down(&lcw_refcount_sem); if (--lcw_refcount == 0) lcw_dispatch_stop(); cfs_up(&lcw_refcount_sem); EXIT; }
/** * cancel a workitem: */ int cfs_wi_cancel (cfs_workitem_t *wi) { cfs_wi_sched_t *sched = cfs_wi_to_sched(wi); int rc; LASSERT (!cfs_in_interrupt()); /* because we use plain spinlock */ LASSERT (!sched->ws_shuttingdown); cfs_wi_sched_lock(sched); /* * return 0 if it's running already, otherwise return 1, which * means the workitem will not be scheduled and will not have * any race with wi_action. */ rc = !(wi->wi_running); if (wi->wi_scheduled) { /* cancel pending schedules */ LASSERT (!cfs_list_empty(&wi->wi_list)); cfs_list_del_init(&wi->wi_list); wi->wi_scheduled = 0; } LASSERT (cfs_list_empty(&wi->wi_list)); cfs_wi_sched_unlock(sched); return rc; }
int cfs_wi_check_events (void) { int n = 0; cfs_workitem_t *wi; cfs_list_t *q; cfs_spin_lock(&cfs_wi_data.wi_glock); for (;;) { /** rerunq is always empty for userspace */ if (!cfs_list_empty(&cfs_wi_data.wi_scheds[1].ws_runq)) q = &cfs_wi_data.wi_scheds[1].ws_runq; else if (!cfs_list_empty(&cfs_wi_data.wi_scheds[0].ws_runq)) q = &cfs_wi_data.wi_scheds[0].ws_runq; else break; wi = cfs_list_entry(q->next, cfs_workitem_t, wi_list); cfs_list_del_init(&wi->wi_list); LASSERT (wi->wi_scheduled); wi->wi_scheduled = 0; cfs_spin_unlock(&cfs_wi_data.wi_glock); n++; (*wi->wi_action) (wi); cfs_spin_lock(&cfs_wi_data.wi_glock); } cfs_spin_unlock(&cfs_wi_data.wi_glock); return n; }
static struct ll_inode_info *ll_close_next_lli(struct ll_close_queue *lcq) { struct ll_inode_info *lli = NULL; spin_lock(&lcq->lcq_lock); if (!cfs_list_empty(&lcq->lcq_head)) { lli = cfs_list_entry(lcq->lcq_head.next, struct ll_inode_info, lli_close_list); cfs_list_del_init(&lli->lli_close_list); } else if (cfs_atomic_read(&lcq->lcq_stop))
static void lc_watchdog_del_pending(struct lc_watchdog *lcw) { cfs_spin_lock_bh(&lcw->lcw_lock); if (unlikely(!cfs_list_empty(&lcw->lcw_list))) { cfs_spin_lock_bh(&lcw_pending_timers_lock); cfs_list_del_init(&lcw->lcw_list); lcw->lcw_refcount--; /* -1 ref for pending list */ cfs_spin_unlock_bh(&lcw_pending_timers_lock); } cfs_spin_unlock_bh(&lcw->lcw_lock); }
int libcfs_deregister_ioctl(struct libcfs_ioctl_handler *hand) { int rc = 0; down_write(&ioctl_list_sem); if (cfs_list_empty(&hand->item)) rc = -ENOENT; else cfs_list_del_init(&hand->item); up_write(&ioctl_list_sem); return rc; }
/* * Release spill block dbuf hold for all dirty SAs. */ void osd_object_sa_dirty_rele(struct osd_thandle *oh) { struct osd_object *obj; down(&oh->ot_sa_lock); while (!cfs_list_empty(&oh->ot_sa_list)) { obj = cfs_list_entry(oh->ot_sa_list.next, struct osd_object, oo_sa_linkage); sa_spill_rele(obj->oo_sa_hdl); write_lock(&obj->oo_attr_lock); cfs_list_del_init(&obj->oo_sa_linkage); write_unlock(&obj->oo_attr_lock); } up(&oh->ot_sa_lock); }
/** records that a write has completed */ void vvp_write_complete(struct ccc_object *club, struct ccc_page *page) { struct ll_inode_info *lli = ll_i2info(club->cob_inode); int rc = 0; ENTRY; spin_lock(&lli->lli_lock); if (page != NULL && !cfs_list_empty(&page->cpg_pending_linkage)) { cfs_list_del_init(&page->cpg_pending_linkage); rc = 1; } spin_unlock(&lli->lli_lock); if (rc) ll_queue_done_writing(club->cob_inode, 0); EXIT; }
/* return a page that has 'len' bytes left at the end */ static struct cfs_trace_page * cfs_trace_get_tage_try(struct cfs_trace_cpu_data *tcd, unsigned long len) { struct cfs_trace_page *tage; if (tcd->tcd_cur_pages > 0) { __LASSERT(!cfs_list_empty(&tcd->tcd_pages)); tage = cfs_tage_from_list(tcd->tcd_pages.prev); if (tage->used + len <= CFS_PAGE_SIZE) return tage; } if (tcd->tcd_cur_pages < tcd->tcd_max_pages) { if (tcd->tcd_cur_stock_pages > 0) { tage = cfs_tage_from_list(tcd->tcd_stock_pages.prev); -- tcd->tcd_cur_stock_pages; cfs_list_del_init(&tage->linkage); } else { tage = cfs_tage_alloc(CFS_ALLOC_ATOMIC); if (tage == NULL) { if (printk_ratelimit()) printk(CFS_KERN_WARNING "cannot allocate a tage (%ld)\n", tcd->tcd_cur_pages); return NULL; } } tage->used = 0; tage->cpu = cfs_smp_processor_id(); tage->type = tcd->tcd_type; cfs_list_add_tail(&tage->linkage, &tcd->tcd_pages); tcd->tcd_cur_pages++; if (tcd->tcd_cur_pages > 8 && thread_running) { struct tracefiled_ctl *tctl = &trace_tctl; /* * wake up tracefiled to process some pages. */ cfs_waitq_signal(&tctl->tctl_waitq); } return tage; } return NULL; }
static int lfsck_namespace_post(const struct lu_env *env, struct lfsck_component *com, int result, bool init) { struct lfsck_instance *lfsck = com->lc_lfsck; struct lfsck_namespace *ns = com->lc_file_ram; int rc; down_write(&com->lc_sem); spin_lock(&lfsck->li_lock); if (!init) ns->ln_pos_last_checkpoint = lfsck->li_pos_current; if (result > 0) { ns->ln_status = LS_SCANNING_PHASE2; ns->ln_flags |= LF_SCANNED_ONCE; ns->ln_flags &= ~LF_UPGRADE; cfs_list_del_init(&com->lc_link); cfs_list_del_init(&com->lc_link_dir); cfs_list_add_tail(&com->lc_link, &lfsck->li_list_double_scan); } else if (result == 0) { ns->ln_status = lfsck->li_status; if (ns->ln_status == 0) ns->ln_status = LS_STOPPED; if (ns->ln_status != LS_PAUSED) { cfs_list_del_init(&com->lc_link); cfs_list_del_init(&com->lc_link_dir); cfs_list_add_tail(&com->lc_link, &lfsck->li_list_idle); } } else { ns->ln_status = LS_FAILED; cfs_list_del_init(&com->lc_link); cfs_list_del_init(&com->lc_link_dir); cfs_list_add_tail(&com->lc_link, &lfsck->li_list_idle); } spin_unlock(&lfsck->li_lock); if (!init) { ns->ln_run_time_phase1 += cfs_duration_sec(cfs_time_current() + HALF_SEC - lfsck->li_time_last_checkpoint); ns->ln_time_last_checkpoint = cfs_time_current_sec(); ns->ln_items_checked += com->lc_new_checked; com->lc_new_checked = 0; } rc = lfsck_namespace_store(env, com, false); up_write(&com->lc_sem); return rc; }
/* must be called with lnet_res_lock held */ void lnet_md_unlink(lnet_libmd_t *md) { if ((md->md_flags & LNET_MD_FLAG_ZOMBIE) == 0) { /* first unlink attempt... */ lnet_me_t *me = md->md_me; md->md_flags |= LNET_MD_FLAG_ZOMBIE; /* Disassociate from ME (if any), and unlink it if it was created * with LNET_UNLINK */ if (me != NULL) { /* detach MD from portal */ lnet_ptl_detach_md(me, md); if (me->me_unlink == LNET_UNLINK) lnet_me_unlink(me); } /* ensure all future handle lookups fail */ lnet_res_lh_invalidate(&md->md_lh); } if (md->md_refcount != 0) { CDEBUG(D_NET, "Queueing unlink of md %p\n", md); return; } CDEBUG(D_NET, "Unlinking md %p\n", md); if (md->md_eq != NULL) { int cpt = lnet_cpt_of_cookie(md->md_lh.lh_cookie); LASSERT(*md->md_eq->eq_refs[cpt] > 0); (*md->md_eq->eq_refs[cpt])--; } LASSERT(!cfs_list_empty(&md->md_list)); cfs_list_del_init(&md->md_list); lnet_md_free_locked(md); }
/* XXX: * 0. it only works when called from wi->wi_action. * 1. when it returns no one shall try to schedule the workitem. */ void cfs_wi_exit(cfs_workitem_t *wi) { cfs_wi_sched_t *sched = cfs_wi_to_sched(wi); LASSERT (!cfs_in_interrupt()); /* because we use plain spinlock */ LASSERT (!sched->ws_shuttingdown); cfs_wi_sched_lock(sched); #ifdef __KERNEL__ LASSERT (wi->wi_running); #endif if (wi->wi_scheduled) { /* cancel pending schedules */ LASSERT (!cfs_list_empty(&wi->wi_list)); cfs_list_del_init(&wi->wi_list); } LASSERT (cfs_list_empty(&wi->wi_list)); wi->wi_scheduled = 1; /* LBUG future schedule attempts */ cfs_wi_sched_unlock(sched); return; }
static int lfsck_namespace_prep(const struct lu_env *env, struct lfsck_component *com, struct lfsck_start_param *lsp) { struct lfsck_instance *lfsck = com->lc_lfsck; struct lfsck_namespace *ns = com->lc_file_ram; struct lfsck_position *pos = &com->lc_pos_start; if (ns->ln_status == LS_COMPLETED) { int rc; rc = lfsck_namespace_reset(env, com, false); if (rc != 0) return rc; } down_write(&com->lc_sem); ns->ln_time_latest_start = cfs_time_current_sec(); spin_lock(&lfsck->li_lock); if (ns->ln_flags & LF_SCANNED_ONCE) { if (!lfsck->li_drop_dryrun || lfsck_pos_is_zero(&ns->ln_pos_first_inconsistent)) { ns->ln_status = LS_SCANNING_PHASE2; cfs_list_del_init(&com->lc_link); cfs_list_add_tail(&com->lc_link, &lfsck->li_list_double_scan); if (!cfs_list_empty(&com->lc_link_dir)) cfs_list_del_init(&com->lc_link_dir); lfsck_pos_set_zero(pos); } else { ns->ln_status = LS_SCANNING_PHASE1; ns->ln_run_time_phase1 = 0; ns->ln_run_time_phase2 = 0; ns->ln_items_checked = 0; ns->ln_items_repaired = 0; ns->ln_items_failed = 0; ns->ln_dirs_checked = 0; ns->ln_mlinked_checked = 0; ns->ln_objs_checked_phase2 = 0; ns->ln_objs_repaired_phase2 = 0; ns->ln_objs_failed_phase2 = 0; ns->ln_objs_nlink_repaired = 0; ns->ln_objs_lost_found = 0; fid_zero(&ns->ln_fid_latest_scanned_phase2); if (cfs_list_empty(&com->lc_link_dir)) cfs_list_add_tail(&com->lc_link_dir, &lfsck->li_list_dir); *pos = ns->ln_pos_first_inconsistent; } } else { ns->ln_status = LS_SCANNING_PHASE1; if (cfs_list_empty(&com->lc_link_dir)) cfs_list_add_tail(&com->lc_link_dir, &lfsck->li_list_dir); if (!lfsck->li_drop_dryrun || lfsck_pos_is_zero(&ns->ln_pos_first_inconsistent)) { *pos = ns->ln_pos_last_checkpoint; pos->lp_oit_cookie++; } else { *pos = ns->ln_pos_first_inconsistent; } } spin_unlock(&lfsck->li_lock); up_write(&com->lc_sem); return 0; }
static int mdt_reint_setattr(struct mdt_thread_info *info, struct mdt_lock_handle *lhc) { struct md_attr *ma = &info->mti_attr; struct mdt_reint_record *rr = &info->mti_rr; struct ptlrpc_request *req = mdt_info_req(info); struct mdt_export_data *med = &req->rq_export->exp_mdt_data; struct mdt_file_data *mfd; struct mdt_object *mo; struct mdt_body *repbody; int som_au, rc, rc2; ENTRY; DEBUG_REQ(D_INODE, req, "setattr "DFID" %x", PFID(rr->rr_fid1), (unsigned int)ma->ma_attr.la_valid); if (info->mti_dlm_req) ldlm_request_cancel(req, info->mti_dlm_req, 0); repbody = req_capsule_server_get(info->mti_pill, &RMF_MDT_BODY); mo = mdt_object_find(info->mti_env, info->mti_mdt, rr->rr_fid1); if (IS_ERR(mo)) GOTO(out, rc = PTR_ERR(mo)); if (mdt_object_obf(mo)) GOTO(out_put, rc = -EPERM); /* start a log jounal handle if needed */ if (!(mdt_conn_flags(info) & OBD_CONNECT_SOM)) { if ((ma->ma_attr.la_valid & LA_SIZE) || (rr->rr_flags & MRF_OPEN_TRUNC)) { /* Check write access for the O_TRUNC case */ if (mdt_write_read(mo) < 0) GOTO(out_put, rc = -ETXTBSY); } } else if (info->mti_ioepoch && (info->mti_ioepoch->flags & MF_EPOCH_OPEN)) { /* Truncate case. IOEpoch is opened. */ rc = mdt_write_get(mo); if (rc) GOTO(out_put, rc); mfd = mdt_mfd_new(); if (mfd == NULL) { mdt_write_put(mo); GOTO(out_put, rc = -ENOMEM); } mdt_ioepoch_open(info, mo, 0); repbody->ioepoch = mo->mot_ioepoch; mdt_object_get(info->mti_env, mo); mdt_mfd_set_mode(mfd, MDS_FMODE_TRUNC); mfd->mfd_object = mo; mfd->mfd_xid = req->rq_xid; spin_lock(&med->med_open_lock); cfs_list_add(&mfd->mfd_list, &med->med_open_head); spin_unlock(&med->med_open_lock); repbody->handle.cookie = mfd->mfd_handle.h_cookie; } som_au = info->mti_ioepoch && info->mti_ioepoch->flags & MF_SOM_CHANGE; if (som_au) { /* SOM Attribute update case. Find the proper mfd and update * SOM attributes on the proper object. */ LASSERT(mdt_conn_flags(info) & OBD_CONNECT_SOM); LASSERT(info->mti_ioepoch); spin_lock(&med->med_open_lock); mfd = mdt_handle2mfd(info, &info->mti_ioepoch->handle); if (mfd == NULL) { spin_unlock(&med->med_open_lock); CDEBUG(D_INODE, "no handle for file close: " "fid = "DFID": cookie = "LPX64"\n", PFID(info->mti_rr.rr_fid1), info->mti_ioepoch->handle.cookie); GOTO(out_put, rc = -ESTALE); } LASSERT(mfd->mfd_mode == MDS_FMODE_SOM); LASSERT(!(info->mti_ioepoch->flags & MF_EPOCH_CLOSE)); class_handle_unhash(&mfd->mfd_handle); cfs_list_del_init(&mfd->mfd_list); spin_unlock(&med->med_open_lock); mdt_mfd_close(info, mfd); } else if ((ma->ma_valid & MA_INODE) && ma->ma_attr.la_valid) { LASSERT((ma->ma_valid & MA_LOV) == 0); rc = mdt_attr_set(info, mo, ma, rr->rr_flags); if (rc) GOTO(out_put, rc); } else if ((ma->ma_valid & MA_LOV) && (ma->ma_valid & MA_INODE)) { struct lu_buf *buf = &info->mti_buf; LASSERT(ma->ma_attr.la_valid == 0); buf->lb_buf = ma->ma_lmm; buf->lb_len = ma->ma_lmm_size; rc = mo_xattr_set(info->mti_env, mdt_object_child(mo), buf, XATTR_NAME_LOV, 0); if (rc) GOTO(out_put, rc); } else LBUG(); /* If file data is modified, add the dirty flag */ if (ma->ma_attr_flags & MDS_DATA_MODIFIED) rc = mdt_add_dirty_flag(info, mo, ma); ma->ma_need = MA_INODE; ma->ma_valid = 0; rc = mdt_attr_get_complex(info, mo, ma); if (rc != 0) GOTO(out_put, rc); mdt_pack_attr2body(info, repbody, &ma->ma_attr, mdt_object_fid(mo)); if (info->mti_mdt->mdt_opts.mo_oss_capa && exp_connect_flags(info->mti_exp) & OBD_CONNECT_OSS_CAPA && S_ISREG(lu_object_attr(&mo->mot_obj.mo_lu)) && (ma->ma_attr.la_valid & LA_SIZE) && !som_au) { struct lustre_capa *capa; capa = req_capsule_server_get(info->mti_pill, &RMF_CAPA2); LASSERT(capa); capa->lc_opc = CAPA_OPC_OSS_DEFAULT | CAPA_OPC_OSS_TRUNC; rc = mo_capa_get(info->mti_env, mdt_object_child(mo), capa, 0); if (rc) GOTO(out_put, rc); repbody->valid |= OBD_MD_FLOSSCAPA; } EXIT; out_put: mdt_object_put(info->mti_env, mo); out: if (rc == 0) mdt_counter_incr(req, LPROC_MDT_SETATTR); mdt_client_compatibility(info); rc2 = mdt_fix_reply(info); if (rc == 0) rc = rc2; return rc; }
static int cfs_wi_scheduler (void *arg) { int id = (int)(long_ptr_t) arg; int serial = (id == -1); char name[24]; cfs_wi_sched_t *sched; if (serial) { sched = &cfs_wi_data.wi_scheds[cfs_wi_data.wi_nsched - 1]; cfs_daemonize("wi_serial_sd"); } else { /* will be sched = &cfs_wi_data.wi_scheds[id] in the future */ sched = &cfs_wi_data.wi_scheds[0]; snprintf(name, sizeof(name), "cfs_wi_sd%03d", id); cfs_daemonize(name); } cfs_block_allsigs(); cfs_wi_sched_lock(sched); while (!sched->ws_shuttingdown) { int nloops = 0; int rc; cfs_workitem_t *wi; while (!cfs_list_empty(&sched->ws_runq) && nloops < CFS_WI_RESCHED) { wi = cfs_list_entry(sched->ws_runq.next, cfs_workitem_t, wi_list); LASSERT (wi->wi_scheduled && !wi->wi_running); cfs_list_del_init(&wi->wi_list); wi->wi_running = 1; wi->wi_scheduled = 0; cfs_wi_sched_unlock(sched); nloops++; rc = (*wi->wi_action) (wi); cfs_wi_sched_lock(sched); if (rc != 0) /* WI should be dead, even be freed! */ continue; wi->wi_running = 0; if (cfs_list_empty(&wi->wi_list)) continue; LASSERT (wi->wi_scheduled); /* wi is rescheduled, should be on rerunq now, we * move it to runq so it can run action now */ cfs_list_move_tail(&wi->wi_list, &sched->ws_runq); } if (!cfs_list_empty(&sched->ws_runq)) { cfs_wi_sched_unlock(sched); /* don't sleep because some workitems still * expect me to come back soon */ cfs_cond_resched(); cfs_wi_sched_lock(sched); continue; } cfs_wi_sched_unlock(sched); cfs_wait_event_interruptible_exclusive(sched->ws_waitq, !cfs_wi_sched_cansleep(sched), rc); cfs_wi_sched_lock(sched); } cfs_wi_sched_unlock(sched); cfs_spin_lock(&cfs_wi_data.wi_glock); cfs_wi_data.wi_nthreads--; cfs_spin_unlock(&cfs_wi_data.wi_glock); return 0; }
static int lcw_dispatch_main(void *data) { int rc = 0; unsigned long flags; struct lc_watchdog *lcw; CFS_LIST_HEAD (zombies); ENTRY; cfs_daemonize("lc_watchdogd"); SIGNAL_MASK_LOCK(current, flags); sigfillset(¤t->blocked); RECALC_SIGPENDING; SIGNAL_MASK_UNLOCK(current, flags); cfs_complete(&lcw_start_completion); while (1) { int dumplog = 1; cfs_wait_event_interruptible(lcw_event_waitq, is_watchdog_fired(), rc); CDEBUG(D_INFO, "Watchdog got woken up...\n"); if (cfs_test_bit(LCW_FLAG_STOP, &lcw_flags)) { CDEBUG(D_INFO, "LCW_FLAG_STOP was set, shutting down...\n"); cfs_spin_lock_bh(&lcw_pending_timers_lock); rc = !cfs_list_empty(&lcw_pending_timers); cfs_spin_unlock_bh(&lcw_pending_timers_lock); if (rc) { CERROR("pending timers list was not empty at " "time of watchdog dispatch shutdown\n"); } break; } cfs_spin_lock_bh(&lcw_pending_timers_lock); while (!cfs_list_empty(&lcw_pending_timers)) { int is_dumplog; lcw = cfs_list_entry(lcw_pending_timers.next, struct lc_watchdog, lcw_list); /* +1 ref for callback to make sure lwc wouldn't be * deleted after releasing lcw_pending_timers_lock */ lcw->lcw_refcount++; cfs_spin_unlock_bh(&lcw_pending_timers_lock); /* lock ordering */ cfs_spin_lock_bh(&lcw->lcw_lock); cfs_spin_lock_bh(&lcw_pending_timers_lock); if (cfs_list_empty(&lcw->lcw_list)) { /* already removed from pending list */ lcw->lcw_refcount--; /* -1 ref for callback */ if (lcw->lcw_refcount == 0) cfs_list_add(&lcw->lcw_list, &zombies); cfs_spin_unlock_bh(&lcw->lcw_lock); /* still hold lcw_pending_timers_lock */ continue; } cfs_list_del_init(&lcw->lcw_list); lcw->lcw_refcount--; /* -1 ref for pending list */ cfs_spin_unlock_bh(&lcw_pending_timers_lock); cfs_spin_unlock_bh(&lcw->lcw_lock); CDEBUG(D_INFO, "found lcw for pid " LPPID "\n", lcw->lcw_pid); lcw_dump_stack(lcw); is_dumplog = lcw->lcw_callback == lc_watchdog_dumplog; if (lcw->lcw_state != LC_WATCHDOG_DISABLED && (dumplog || !is_dumplog)) { lcw->lcw_callback(lcw->lcw_pid, lcw->lcw_data); if (dumplog && is_dumplog) dumplog = 0; } cfs_spin_lock_bh(&lcw_pending_timers_lock); lcw->lcw_refcount--; /* -1 ref for callback */ if (lcw->lcw_refcount == 0) cfs_list_add(&lcw->lcw_list, &zombies); } cfs_spin_unlock_bh(&lcw_pending_timers_lock); while (!cfs_list_empty(&zombies)) { lcw = cfs_list_entry(lcw_pending_timers.next, struct lc_watchdog, lcw_list); cfs_list_del(&lcw->lcw_list); LIBCFS_FREE(lcw, sizeof(*lcw)); } } cfs_complete(&lcw_stop_completion); RETURN(rc); }
/* All actions that we need after sending hello on passive conn: * 1) Cope with 1st easy case: conn is already linked to a peer * 2) Cope with 2nd easy case: remove zombie conn * 3) Resolve race: * a) find the peer * b) link the conn to the peer if conn[idx] is empty * c) if the conn[idx] isn't empty and is in READY state, * remove the conn as duplicated * d) if the conn[idx] isn't empty and isn't in READY state, * override conn[idx] with the conn */ int usocklnd_passiveconn_hellosent(usock_conn_t *conn) { usock_conn_t *conn2; usock_peer_t *peer; cfs_list_t tx_list; cfs_list_t zcack_list; int idx; int rc = 0; /* almost nothing to do if conn is already linked to peer hash table */ if (conn->uc_peer != NULL) goto passive_hellosent_done; /* conn->uc_peer == NULL, so the conn isn't accessible via * peer hash list, so nobody can touch the conn but us */ if (conn->uc_ni == NULL) /* remove zombie conn */ goto passive_hellosent_connkill; /* all code below is race resolution, because normally * passive conn is linked to peer just after receiving hello */ CFS_INIT_LIST_HEAD (&tx_list); CFS_INIT_LIST_HEAD (&zcack_list); /* conn is passive and isn't linked to any peer, so its tx and zc_ack lists have to be empty */ LASSERT (cfs_list_empty(&conn->uc_tx_list) && cfs_list_empty(&conn->uc_zcack_list) && conn->uc_sending == 0); rc = usocklnd_find_or_create_peer(conn->uc_ni, conn->uc_peerid, &peer); if (rc) return rc; idx = usocklnd_type2idx(conn->uc_type); /* try to link conn to peer */ pthread_mutex_lock(&peer->up_lock); if (peer->up_conns[idx] == NULL) { usocklnd_link_conn_to_peer(conn, peer, idx); usocklnd_conn_addref(conn); conn->uc_peer = peer; usocklnd_peer_addref(peer); } else { conn2 = peer->up_conns[idx]; pthread_mutex_lock(&conn2->uc_lock); if (conn2->uc_state == UC_READY) { /* conn2 is in READY state, so conn is "duplicated" */ pthread_mutex_unlock(&conn2->uc_lock); pthread_mutex_unlock(&peer->up_lock); usocklnd_peer_decref(peer); goto passive_hellosent_connkill; } /* uc_state != UC_READY => switch conn and conn2 */ /* Relink txs and zc_acks from conn2 to conn. * We're sure that nobody but us can access to conn, * nevertheless we use mutex (if we're wrong yet, * deadlock is easy to see that corrupted list */ cfs_list_add(&tx_list, &conn2->uc_tx_list); cfs_list_del_init(&conn2->uc_tx_list); cfs_list_add(&zcack_list, &conn2->uc_zcack_list); cfs_list_del_init(&conn2->uc_zcack_list); pthread_mutex_lock(&conn->uc_lock); cfs_list_add_tail(&conn->uc_tx_list, &tx_list); cfs_list_del_init(&tx_list); cfs_list_add_tail(&conn->uc_zcack_list, &zcack_list); cfs_list_del_init(&zcack_list); conn->uc_peer = peer; pthread_mutex_unlock(&conn->uc_lock); conn2->uc_peer = NULL; /* make conn2 zombie */ pthread_mutex_unlock(&conn2->uc_lock); usocklnd_conn_decref(conn2); usocklnd_link_conn_to_peer(conn, peer, idx); usocklnd_conn_addref(conn); conn->uc_peer = peer; } lnet_ni_decref(conn->uc_ni); conn->uc_ni = NULL; pthread_mutex_unlock(&peer->up_lock); usocklnd_peer_decref(peer); passive_hellosent_done: /* safely transit to UC_READY state */ /* rc == 0 */ pthread_mutex_lock(&conn->uc_lock); if (conn->uc_state != UC_DEAD) { usocklnd_rx_ksmhdr_state_transition(conn); /* we're ready to recive incoming packets and maybe already have smth. to transmit */ LASSERT (conn->uc_sending == 0); if ( cfs_list_empty(&conn->uc_tx_list) && cfs_list_empty(&conn->uc_zcack_list) ) { conn->uc_tx_flag = 0; rc = usocklnd_add_pollrequest(conn, POLL_SET_REQUEST, POLLIN); } else { conn->uc_tx_deadline = cfs_time_shift(usock_tuns.ut_timeout); conn->uc_tx_flag = 1; rc = usocklnd_add_pollrequest(conn, POLL_SET_REQUEST, POLLIN | POLLOUT); } if (rc == 0) conn->uc_state = UC_READY; } pthread_mutex_unlock(&conn->uc_lock); return rc; passive_hellosent_connkill: usocklnd_conn_kill(conn); return 0; }
static int lfsck_namespace_double_scan_main(void *args) { struct lfsck_thread_args *lta = args; const struct lu_env *env = <a->lta_env; struct lfsck_component *com = lta->lta_com; struct lfsck_instance *lfsck = com->lc_lfsck; struct ptlrpc_thread *thread = &lfsck->li_thread; struct lfsck_bookmark *bk = &lfsck->li_bookmark_ram; struct lfsck_namespace *ns = com->lc_file_ram; struct dt_object *obj = com->lc_obj; const struct dt_it_ops *iops = &obj->do_index_ops->dio_it; struct dt_object *target; struct dt_it *di; struct dt_key *key; struct lu_fid fid; int rc; __u8 flags = 0; ENTRY; com->lc_new_checked = 0; com->lc_new_scanned = 0; com->lc_time_last_checkpoint = cfs_time_current(); com->lc_time_next_checkpoint = com->lc_time_last_checkpoint + cfs_time_seconds(LFSCK_CHECKPOINT_INTERVAL); di = iops->init(env, obj, 0, BYPASS_CAPA); if (IS_ERR(di)) GOTO(out, rc = PTR_ERR(di)); fid_cpu_to_be(&fid, &ns->ln_fid_latest_scanned_phase2); rc = iops->get(env, di, (const struct dt_key *)&fid); if (rc < 0) GOTO(fini, rc); /* Skip the start one, which either has been processed or non-exist. */ rc = iops->next(env, di); if (rc != 0) GOTO(put, rc); if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_NO_DOUBLESCAN)) GOTO(put, rc = 0); do { if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_DELAY3) && 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); } key = iops->key(env, di); fid_be_to_cpu(&fid, (const struct lu_fid *)key); target = lfsck_object_find(env, lfsck, &fid); down_write(&com->lc_sem); if (target == NULL) { rc = 0; goto checkpoint; } else if (IS_ERR(target)) { rc = PTR_ERR(target); 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)) { rc = iops->rec(env, di, (struct dt_rec *)&flags, 0); if (rc == 0) rc = lfsck_namespace_double_scan_one(env, com, target, flags); } lfsck_object_put(env, target); checkpoint: com->lc_new_checked++; com->lc_new_scanned++; ns->ln_fid_latest_scanned_phase2 = fid; if (rc > 0) ns->ln_objs_repaired_phase2++; else if (rc < 0) ns->ln_objs_failed_phase2++; up_write(&com->lc_sem); if ((rc == 0) || ((rc > 0) && !(bk->lb_param & LPF_DRYRUN))) { lfsck_namespace_delete(env, com, &fid); } else if (rc < 0) { flags |= LLF_REPAIR_FAILED; lfsck_namespace_update(env, com, &fid, flags, true); } if (rc < 0 && bk->lb_param & LPF_FAILOUT) GOTO(put, rc); if (unlikely(cfs_time_beforeq(com->lc_time_next_checkpoint, cfs_time_current())) && com->lc_new_checked != 0) { down_write(&com->lc_sem); ns->ln_run_time_phase2 += cfs_duration_sec(cfs_time_current() + HALF_SEC - com->lc_time_last_checkpoint); ns->ln_time_last_checkpoint = cfs_time_current_sec(); ns->ln_objs_checked_phase2 += com->lc_new_checked; com->lc_new_checked = 0; rc = lfsck_namespace_store(env, com, false); up_write(&com->lc_sem); if (rc != 0) GOTO(put, rc); com->lc_time_last_checkpoint = cfs_time_current(); com->lc_time_next_checkpoint = com->lc_time_last_checkpoint + cfs_time_seconds(LFSCK_CHECKPOINT_INTERVAL); } lfsck_control_speed_by_self(com); if (unlikely(!thread_is_running(thread))) GOTO(put, rc = 0); rc = iops->next(env, di); } while (rc == 0); GOTO(put, rc); put: iops->put(env, di); fini: iops->fini(env, di); out: down_write(&com->lc_sem); ns->ln_run_time_phase2 += cfs_duration_sec(cfs_time_current() + HALF_SEC - lfsck->li_time_last_checkpoint); ns->ln_time_last_checkpoint = cfs_time_current_sec(); ns->ln_objs_checked_phase2 += com->lc_new_checked; com->lc_new_checked = 0; if (rc > 0) { com->lc_journal = 0; ns->ln_status = LS_COMPLETED; if (!(bk->lb_param & LPF_DRYRUN)) ns->ln_flags &= ~(LF_SCANNED_ONCE | LF_INCONSISTENT); ns->ln_time_last_complete = ns->ln_time_last_checkpoint; ns->ln_success_count++; } else if (rc == 0) { ns->ln_status = lfsck->li_status; if (ns->ln_status == 0) ns->ln_status = LS_STOPPED; } else { ns->ln_status = LS_FAILED; } if (ns->ln_status != LS_PAUSED) { spin_lock(&lfsck->li_lock); cfs_list_del_init(&com->lc_link); cfs_list_add_tail(&com->lc_link, &lfsck->li_list_idle); spin_unlock(&lfsck->li_lock); } rc = lfsck_namespace_store(env, com, false); up_write(&com->lc_sem); if (atomic_dec_and_test(&lfsck->li_double_scan_count)) wake_up_all(&thread->t_ctl_waitq); lfsck_thread_args_fini(lta); return rc; }
/* * Release a qsd_instance. Companion of qsd_init(). This releases all data * structures associated with the quota slave (on-disk objects, lquota entry * tables, ...). * This function should be called when the OSD is shutting down. * * \param env - is the environment passed by the caller * \param qsd - is the qsd instance to shutdown */ void qsd_fini(const struct lu_env *env, struct qsd_instance *qsd) { int qtype; ENTRY; if (unlikely(qsd == NULL)) RETURN_EXIT; CDEBUG(D_QUOTA, "%s: initiating QSD shutdown\n", qsd->qsd_svname); write_lock(&qsd->qsd_lock); qsd->qsd_stopping = true; write_unlock(&qsd->qsd_lock); /* remove qsd proc entry */ if (qsd->qsd_proc != NULL) { lprocfs_remove(&qsd->qsd_proc); qsd->qsd_proc = NULL; } /* stop the writeback thread */ qsd_stop_upd_thread(qsd); /* shutdown the reintegration threads */ for (qtype = USRQUOTA; qtype < MAXQUOTAS; qtype++) { if (qsd->qsd_type_array[qtype] == NULL) continue; qsd_stop_reint_thread(qsd->qsd_type_array[qtype]); } if (qsd->qsd_ns != NULL) { qsd->qsd_ns = NULL; } /* free per-quota type data */ for (qtype = USRQUOTA; qtype < MAXQUOTAS; qtype++) qsd_qtype_fini(env, qsd, qtype); /* deregister connection to the quota master */ qsd->qsd_exp_valid = false; lustre_deregister_lwp_item(&qsd->qsd_exp); /* release per-filesystem information */ if (qsd->qsd_fsinfo != NULL) { mutex_lock(&qsd->qsd_fsinfo->qfs_mutex); /* remove from the list of fsinfo */ cfs_list_del_init(&qsd->qsd_link); mutex_unlock(&qsd->qsd_fsinfo->qfs_mutex); qsd_put_fsinfo(qsd->qsd_fsinfo); qsd->qsd_fsinfo = NULL; } /* release quota root directory */ if (qsd->qsd_root != NULL) { lu_object_put(env, &qsd->qsd_root->do_lu); qsd->qsd_root = NULL; } /* release reference on dt_device */ if (qsd->qsd_dev != NULL) { lu_ref_del(&qsd->qsd_dev->dd_lu_dev.ld_reference, "qsd", qsd); lu_device_put(&qsd->qsd_dev->dd_lu_dev); qsd->qsd_dev = NULL; } CDEBUG(D_QUOTA, "%s: QSD shutdown completed\n", qsd->qsd_svname); OBD_FREE_PTR(qsd); EXIT; }
/* All actions that we need after receiving hello on active conn: * 1) Schedule removing if we're zombie * 2) Restart active conn if we lost the race * 3) Else: update RX part to receive KSM header */ int usocklnd_activeconn_hellorecv(usock_conn_t *conn) { int rc = 0; ksock_hello_msg_t *hello = conn->uc_rx_hello; usock_peer_t *peer = conn->uc_peer; /* Active conn with peer==NULL is zombie. * Don't try to link it to peer because the conn * has already had a chance to proceed at the beginning */ if (peer == NULL) { LASSERT(cfs_list_empty(&conn->uc_tx_list) && cfs_list_empty(&conn->uc_zcack_list)); usocklnd_conn_kill(conn); return 0; } peer->up_last_alive = cfs_time_current(); /* peer says that we lost the race */ if (hello->kshm_ctype == SOCKLND_CONN_NONE) { /* Start new active conn, relink txs and zc_acks from * the conn to new conn, schedule removing the conn. * Actually, we're expecting that a passive conn will * make us zombie soon and take care of our txs and * zc_acks */ cfs_list_t tx_list, zcack_list; usock_conn_t *conn2; int idx = usocklnd_type2idx(conn->uc_type); CFS_INIT_LIST_HEAD (&tx_list); CFS_INIT_LIST_HEAD (&zcack_list); /* Block usocklnd_send() to check peer->up_conns[idx] * and to enqueue more txs */ pthread_mutex_lock(&peer->up_lock); pthread_mutex_lock(&conn->uc_lock); /* usocklnd_shutdown() could kill us */ if (conn->uc_state == UC_DEAD) { pthread_mutex_unlock(&conn->uc_lock); pthread_mutex_unlock(&peer->up_lock); return 0; } LASSERT (peer == conn->uc_peer); LASSERT (peer->up_conns[idx] == conn); rc = usocklnd_create_active_conn(peer, conn->uc_type, &conn2); if (rc) { conn->uc_errored = 1; pthread_mutex_unlock(&conn->uc_lock); pthread_mutex_unlock(&peer->up_lock); return rc; } usocklnd_link_conn_to_peer(conn2, peer, idx); conn2->uc_peer = peer; /* unlink txs and zcack from the conn */ cfs_list_add(&tx_list, &conn->uc_tx_list); cfs_list_del_init(&conn->uc_tx_list); cfs_list_add(&zcack_list, &conn->uc_zcack_list); cfs_list_del_init(&conn->uc_zcack_list); /* link they to the conn2 */ cfs_list_add(&conn2->uc_tx_list, &tx_list); cfs_list_del_init(&tx_list); cfs_list_add(&conn2->uc_zcack_list, &zcack_list); cfs_list_del_init(&zcack_list); /* make conn zombie */ conn->uc_peer = NULL; usocklnd_peer_decref(peer); /* schedule conn2 for processing */ rc = usocklnd_add_pollrequest(conn2, POLL_ADD_REQUEST, POLLOUT); if (rc) { peer->up_conns[idx] = NULL; usocklnd_conn_decref(conn2); /* should destroy conn */ } else { usocklnd_conn_kill_locked(conn); } pthread_mutex_unlock(&conn->uc_lock); pthread_mutex_unlock(&peer->up_lock); usocklnd_conn_decref(conn); } else { /* hello->kshm_ctype != SOCKLND_CONN_NONE */ if (conn->uc_type != usocklnd_invert_type(hello->kshm_ctype)) return -EPROTO; pthread_mutex_lock(&peer->up_lock); usocklnd_cleanup_stale_conns(peer, hello->kshm_src_incarnation, conn); pthread_mutex_unlock(&peer->up_lock); /* safely transit to UC_READY state */ /* rc == 0 */ pthread_mutex_lock(&conn->uc_lock); if (conn->uc_state != UC_DEAD) { usocklnd_rx_ksmhdr_state_transition(conn); /* POLLIN is already set because we just * received hello, but maybe we've smth. to * send? */ LASSERT (conn->uc_sending == 0); if ( !cfs_list_empty(&conn->uc_tx_list) || !cfs_list_empty(&conn->uc_zcack_list) ) { conn->uc_tx_deadline = cfs_time_shift(usock_tuns.ut_timeout); conn->uc_tx_flag = 1; rc = usocklnd_add_pollrequest(conn, POLL_SET_REQUEST, POLLIN | POLLOUT); } if (rc == 0) conn->uc_state = UC_READY; } pthread_mutex_unlock(&conn->uc_lock); } return rc; }