Пример #1
0
/*
 * Finish the current sequence due to disconnect.
 * See mdc_import_event()
 */
void seq_client_flush(struct lu_client_seq *seq)
{
	wait_queue_t link;

	LASSERT(seq != NULL);
	init_waitqueue_entry_current(&link);
	mutex_lock(&seq->lcs_mutex);

	while (seq->lcs_update) {
		add_wait_queue(&seq->lcs_waitq, &link);
		set_current_state(TASK_UNINTERRUPTIBLE);
		mutex_unlock(&seq->lcs_mutex);

		waitq_wait(&link, TASK_UNINTERRUPTIBLE);

		mutex_lock(&seq->lcs_mutex);
		remove_wait_queue(&seq->lcs_waitq, &link);
		set_current_state(TASK_RUNNING);
	}

        fid_zero(&seq->lcs_fid);
        /**
         * this id shld not be used for seq range allocation.
         * set to -1 for dgb check.
         */

        seq->lcs_space.lsr_index = -1;

        range_init(&seq->lcs_space);
	mutex_unlock(&seq->lcs_mutex);
}
Пример #2
0
void libcfs_debug_dumplog(void)
{
	wait_queue_t wait;
	struct task_struct    *dumper;
	ENTRY;

	/* we're being careful to ensure that the kernel thread is
	 * able to set our state to running as it exits before we
	 * get to schedule() */
	init_waitqueue_entry_current(&wait);
	set_current_state(TASK_INTERRUPTIBLE);
	add_wait_queue(&debug_ctlwq, &wait);

	dumper = kthread_run(libcfs_debug_dumplog_thread,
			     (void *)(long)current_pid(),
			     "libcfs_debug_dumper");
	if (IS_ERR(dumper))
		printk(KERN_ERR "LustreError: cannot start log dump thread:"
		       " %ld\n", PTR_ERR(dumper));
	else
		waitq_wait(&wait, TASK_INTERRUPTIBLE);

	/* be sure to teardown if cfs_create_thread() failed */
	remove_wait_queue(&debug_ctlwq, &wait);
	set_current_state(TASK_RUNNING);
}
Пример #3
0
/**
 * Allocate the whole seq to the caller.
 **/
int seq_client_get_seq(const struct lu_env *env,
		       struct lu_client_seq *seq, u64 *seqnr)
{
	wait_queue_t link;
	int rc;

	LASSERT(seqnr != NULL);
	mutex_lock(&seq->lcs_mutex);
	init_waitqueue_entry_current(&link);

        while (1) {
                rc = seq_fid_alloc_prep(seq, &link);
                if (rc == 0)
                        break;
        }

        rc = seq_client_alloc_seq(env, seq, seqnr);
        if (rc) {
                CERROR("%s: Can't allocate new sequence, "
                       "rc %d\n", seq->lcs_name, rc);
                seq_fid_alloc_fini(seq);
		mutex_unlock(&seq->lcs_mutex);
                return rc;
        }

        CDEBUG(D_INFO, "%s: allocate sequence "
               "[0x%16.16"LPF64"x]\n", seq->lcs_name, *seqnr);

	/* Since the caller require the whole seq,
	 * so marked this seq to be used */
	if (seq->lcs_type == LUSTRE_SEQ_METADATA)
		seq->lcs_fid.f_oid = LUSTRE_METADATA_SEQ_MAX_WIDTH;
	else
		seq->lcs_fid.f_oid = LUSTRE_DATA_SEQ_MAX_WIDTH;

	seq->lcs_fid.f_seq = *seqnr;
	seq->lcs_fid.f_ver = 0;
        /*
         * Inform caller that sequence switch is performed to allow it
         * to setup FLD for it.
         */
        seq_fid_alloc_fini(seq);
	mutex_unlock(&seq->lcs_mutex);

        return rc;
}
Пример #4
0
static void lov_subobject_kill(const struct lu_env *env, struct lov_object *lov,
			       struct lovsub_object *los, int idx)
{
	struct cl_object        *sub;
	struct lov_layout_raid0 *r0;
	struct lu_site          *site;
	struct lu_site_bkt_data *bkt;
	wait_queue_t          *waiter;

        r0  = &lov->u.raid0;
        LASSERT(r0->lo_sub[idx] == los);

        sub  = lovsub2cl(los);
        site = sub->co_lu.lo_dev->ld_site;
        bkt  = lu_site_bkt_from_fid(site, &sub->co_lu.lo_header->loh_fid);

        cl_object_kill(env, sub);
        /* release a reference to the sub-object and ... */
        lu_object_ref_del(&sub->co_lu, "lov-parent", lov);
        cl_object_put(env, sub);

        /* ... wait until it is actually destroyed---sub-object clears its
         * ->lo_sub[] slot in lovsub_object_fini() */
	if (r0->lo_sub[idx] == los) {
		waiter = &lov_env_info(env)->lti_waiter;
		init_waitqueue_entry_current(waiter);
		add_wait_queue(&bkt->lsb_marche_funebre, waiter);
		set_current_state(TASK_UNINTERRUPTIBLE);
		while (1) {
			/* this wait-queue is signaled at the end of
			 * lu_object_free(). */
			set_current_state(TASK_UNINTERRUPTIBLE);
			spin_lock(&r0->lo_sub_lock);
			if (r0->lo_sub[idx] == los) {
				spin_unlock(&r0->lo_sub_lock);
				waitq_wait(waiter, TASK_UNINTERRUPTIBLE);
			} else {
				spin_unlock(&r0->lo_sub_lock);
				set_current_state(TASK_RUNNING);
				break;
			}
		}
		remove_wait_queue(&bkt->lsb_marche_funebre, waiter);
	}
	LASSERT(r0->lo_sub[idx] == NULL);
}
Пример #5
0
/* Allocate new fid on passed client @seq and save it to @fid. */
int seq_client_alloc_fid(const struct lu_env *env,
			 struct lu_client_seq *seq, struct lu_fid *fid)
{
	wait_queue_t link;
	int rc;
	ENTRY;

	LASSERT(seq != NULL);
	LASSERT(fid != NULL);

	init_waitqueue_entry_current(&link);
	mutex_lock(&seq->lcs_mutex);

	if (OBD_FAIL_CHECK(OBD_FAIL_SEQ_EXHAUST))
		seq->lcs_fid.f_oid = seq->lcs_width;

        while (1) {
		u64 seqnr;

                if (!fid_is_zero(&seq->lcs_fid) &&
                    fid_oid(&seq->lcs_fid) < seq->lcs_width) {
                        /* Just bump last allocated fid and return to caller. */
                        seq->lcs_fid.f_oid += 1;
                        rc = 0;
                        break;
                }

                rc = seq_fid_alloc_prep(seq, &link);
                if (rc)
                        continue;

                rc = seq_client_alloc_seq(env, seq, &seqnr);
                if (rc) {
                        CERROR("%s: Can't allocate new sequence, "
                               "rc %d\n", seq->lcs_name, rc);
                        seq_fid_alloc_fini(seq);
			mutex_unlock(&seq->lcs_mutex);
                        RETURN(rc);
                }

                CDEBUG(D_INFO, "%s: Switch to sequence "
                       "[0x%16.16"LPF64"x]\n", seq->lcs_name, seqnr);

                seq->lcs_fid.f_oid = LUSTRE_FID_INIT_OID;
                seq->lcs_fid.f_seq = seqnr;
                seq->lcs_fid.f_ver = 0;

                /*
                 * Inform caller that sequence switch is performed to allow it
                 * to setup FLD for it.
                 */
                rc = 1;

                seq_fid_alloc_fini(seq);
                break;
        }

        *fid = seq->lcs_fid;
	mutex_unlock(&seq->lcs_mutex);

        CDEBUG(D_INFO, "%s: Allocated FID "DFID"\n", seq->lcs_name,  PFID(fid));
        RETURN(rc);
}
Пример #6
0
/*
 * we allocate the requested pages atomically.
 */
int sptlrpc_enc_pool_get_pages(struct ptlrpc_bulk_desc *desc)
{
	wait_queue_t  waitlink;
	unsigned long   this_idle = -1;
	cfs_time_t      tick = 0;
	long            now;
	int             p_idx, g_idx;
	int             i;

	LASSERT(desc->bd_iov_count > 0);
	LASSERT(desc->bd_iov_count <= page_pools.epp_max_pages);

	/* resent bulk, enc iov might have been allocated previously */
	if (desc->bd_enc_iov != NULL)
		return 0;

	OBD_ALLOC(desc->bd_enc_iov,
		  desc->bd_iov_count * sizeof(*desc->bd_enc_iov));
	if (desc->bd_enc_iov == NULL)
		return -ENOMEM;

	spin_lock(&page_pools.epp_lock);

	page_pools.epp_st_access++;
again:
	if (unlikely(page_pools.epp_free_pages < desc->bd_iov_count)) {
		if (tick == 0)
			tick = cfs_time_current();

		now = cfs_time_current_sec();

		page_pools.epp_st_missings++;
		page_pools.epp_pages_short += desc->bd_iov_count;

		if (enc_pools_should_grow(desc->bd_iov_count, now)) {
			page_pools.epp_growing = 1;

			spin_unlock(&page_pools.epp_lock);
			enc_pools_add_pages(page_pools.epp_pages_short / 2);
			spin_lock(&page_pools.epp_lock);

			page_pools.epp_growing = 0;

			enc_pools_wakeup();
		} else {
			if (++page_pools.epp_waitqlen >
			    page_pools.epp_st_max_wqlen)
				page_pools.epp_st_max_wqlen =
						page_pools.epp_waitqlen;

			set_current_state(TASK_UNINTERRUPTIBLE);
			init_waitqueue_entry_current(&waitlink);
			add_wait_queue(&page_pools.epp_waitq, &waitlink);

			spin_unlock(&page_pools.epp_lock);
			waitq_wait(&waitlink, TASK_UNINTERRUPTIBLE);
			remove_wait_queue(&page_pools.epp_waitq, &waitlink);
			LASSERT(page_pools.epp_waitqlen > 0);
			spin_lock(&page_pools.epp_lock);
			page_pools.epp_waitqlen--;
		}

		LASSERT(page_pools.epp_pages_short >= desc->bd_iov_count);
		page_pools.epp_pages_short -= desc->bd_iov_count;

		this_idle = 0;
		goto again;
	}

        /* record max wait time */
        if (unlikely(tick != 0)) {
                tick = cfs_time_current() - tick;
                if (tick > page_pools.epp_st_max_wait)
                        page_pools.epp_st_max_wait = tick;
        }

        /* proceed with rest of allocation */
        page_pools.epp_free_pages -= desc->bd_iov_count;

        p_idx = page_pools.epp_free_pages / PAGES_PER_POOL;
        g_idx = page_pools.epp_free_pages % PAGES_PER_POOL;

        for (i = 0; i < desc->bd_iov_count; i++) {
                LASSERT(page_pools.epp_pools[p_idx][g_idx] != NULL);
                desc->bd_enc_iov[i].kiov_page =
                                        page_pools.epp_pools[p_idx][g_idx];
                page_pools.epp_pools[p_idx][g_idx] = NULL;

                if (++g_idx == PAGES_PER_POOL) {
                        p_idx++;
                        g_idx = 0;
                }
        }

        if (page_pools.epp_free_pages < page_pools.epp_st_lowfree)
                page_pools.epp_st_lowfree = page_pools.epp_free_pages;

        /*
         * new idle index = (old * weight + new) / (weight + 1)
         */
        if (this_idle == -1) {
                this_idle = page_pools.epp_free_pages * IDLE_IDX_MAX /
                            page_pools.epp_total_pages;
        }
        page_pools.epp_idle_idx = (page_pools.epp_idle_idx * IDLE_IDX_WEIGHT +
                                   this_idle) /
                                  (IDLE_IDX_WEIGHT + 1);

        page_pools.epp_last_access = cfs_time_current_sec();

	spin_unlock(&page_pools.epp_lock);
	return 0;
}