Beispiel #1
0
/**
 * Disconnect a connected client.
 *
 * This function terminates the client connection. The client export is
 * disconnected (cleaned up) and client data on persistent storage is removed.
 *
 * \param[in] exp	OBD export
 *
 * \retval		0 if successful
 * \retval		negative value on error
 */
int ofd_obd_disconnect(struct obd_export *exp)
{
	struct ofd_device	*ofd = ofd_exp(exp);
	struct lu_env		 env;
	int			 rc;

	ENTRY;

	LASSERT(exp);
	class_export_get(exp);

	if (!(exp->exp_flags & OBD_OPT_FORCE))
		ofd_grant_sanity_check(ofd_obd(ofd), __FUNCTION__);

	nodemap_del_member(exp);
	rc = server_disconnect_export(exp);

	ofd_grant_discard(exp);

	/* Do not erase record for recoverable client. */
	if (exp->exp_obd->obd_replayable &&
	    (!exp->exp_obd->obd_fail || exp->exp_failed)) {
		rc = lu_env_init(&env, LCT_DT_THREAD);
		if (rc)
			GOTO(out, rc);

		tgt_client_del(&env, exp);
		lu_env_fini(&env);
	}
out:
	class_export_put(exp);
	RETURN(rc);
}
Beispiel #2
0
/* Update last_rcvd records with the latest transaction data */
int ofd_txn_stop_cb(const struct lu_env *env, struct thandle *txn,
		    void *cookie)
{
	struct ofd_device *ofd = cookie;
	struct ofd_thread_info *info;

	ENTRY;

	info = lu_context_key_get(&env->le_ctx, &ofd_thread_key);

	if (info->fti_exp == NULL)
		 RETURN(0);

	LASSERT(ofd_exp(info->fti_exp) == ofd);
	if (info->fti_has_trans) {
		if (info->fti_mult_trans == 0) {
			CERROR("More than one transaction "LPU64"\n",
			       info->fti_transno);
			RETURN(0);
		}
		/* we need another transno to be assigned */
		info->fti_transno = 0;
	} else if (txn->th_result == 0) {
		info->fti_has_trans = 1;
	}

	spin_lock(&ofd->ofd_lut.lut_translock);
	if (txn->th_result != 0) {
		if (info->fti_transno != 0) {
			CERROR("Replay transno "LPU64" failed: rc %d\n",
			       info->fti_transno, txn->th_result);
			info->fti_transno = 0;
		}
	} else if (info->fti_transno == 0) {
		info->fti_transno = ++ofd->ofd_lut.lut_last_transno;
	} else {
		/* should be replay */
		if (info->fti_transno > ofd->ofd_lut.lut_last_transno)
			ofd->ofd_lut.lut_last_transno = info->fti_transno;
	}
	spin_unlock(&ofd->ofd_lut.lut_translock);

	/** VBR: set new versions */
	if (txn->th_result == 0 && info->fti_obj != NULL) {
		dt_version_set(env, ofd_object_child(info->fti_obj),
			       info->fti_transno, txn);
		info->fti_obj = NULL;
	}

	/* filling reply data */
	CDEBUG(D_INODE, "transno = %llu, last_committed = %llu\n",
	       info->fti_transno, ofd_obd(ofd)->obd_last_committed);

	/* if can't add callback, do sync write */
	txn->th_sync |= !!tgt_last_commit_cb_add(txn, &ofd->ofd_lut,
						 info->fti_exp,
						 info->fti_transno);

	return ofd_last_rcvd_update(info, txn);
}
Beispiel #3
0
/**
 * Initialize OFD per-export statistics.
 *
 * This function sets up procfs entries for various OFD export counters. These
 * counters are for per-client statistics tracked on the server.
 *
 * \param[in] ofd	 OFD device
 * \param[in] exp	 OBD export
 * \param[in] client_nid NID of client
 *
 * \retval		0 if successful
 * \retval		negative value on error
 */
static int ofd_export_stats_init(struct ofd_device *ofd,
				 struct obd_export *exp,
				 lnet_nid_t *client_nid)
{
	struct obd_device	*obd = ofd_obd(ofd);
	struct nid_stat		*stats;
	int			 rc;
	ENTRY;

	LASSERT(obd->obd_uses_nid_stats);

	if (obd_uuid_equals(&exp->exp_client_uuid, &obd->obd_uuid))
		/* Self-export gets no proc entry */
		RETURN(0);

	rc = lprocfs_exp_setup(exp, client_nid);
	if (rc != 0)
		/* Mask error for already created /proc entries */
		RETURN(rc == -EALREADY ? 0 : rc);

	stats = exp->exp_nid_stats;
	stats->nid_stats = lprocfs_alloc_stats(NUM_OBD_STATS +
						LPROC_OFD_STATS_LAST,
						LPROCFS_STATS_FLAG_NOPERCPU);
	if (stats->nid_stats == NULL)
		RETURN(-ENOMEM);

	lprocfs_init_ops_stats(LPROC_OFD_STATS_LAST, stats->nid_stats);

	ofd_stats_counter_init(stats->nid_stats);

	rc = lprocfs_register_stats(stats->nid_proc, "stats", stats->nid_stats);
	if (rc != 0) {
		lprocfs_free_stats(&stats->nid_stats);
		GOTO(out, rc);
	}

	rc = lprocfs_nid_ldlm_stats_init(stats);
	if (rc != 0)
		GOTO(out, rc);

out:
	RETURN(rc);
}
Beispiel #4
0
 *
 * Author: Lai Siyao <*****@*****.**>
 */

#define DEBUG_SUBSYSTEM S_FILTER

#include "ofd_internal.h"

static inline __u32 ofd_ck_keyid(struct filter_capa_key *key)
{
	return key->k_key.lk_keyid;
}

int ofd_update_capa_key(struct ofd_device *ofd, struct lustre_capa_key *new)
{
	struct obd_device	*obd = ofd_obd(ofd);
	struct filter_capa_key	*k, *keys[2] = { NULL, NULL };
	int			 i;

	spin_lock(&capa_lock);
	cfs_list_for_each_entry(k, &obd->u.filter.fo_capa_keys, k_list) {
		if (k->k_key.lk_seq != new->lk_seq)
			continue;

		if (keys[0]) {
			keys[1] = k;
			if (ofd_ck_keyid(keys[1]) > ofd_ck_keyid(keys[0]))
				keys[1] = keys[0], keys[0] = k;
		} else {
			keys[0] = k;
		}
Beispiel #5
0
/* This will be called in two ways:
 *
 *   r != NULL : called by the DLM itself after a glimpse callback
 *   r == NULL : called by the ofd after a disk write
 *
 *   If 'increase_only' is true, don't allow values to move backwards.
 */
static int ofd_lvbo_update(struct ldlm_resource *res,
			   struct ptlrpc_request *req, int increase_only)
{
	struct ofd_device	*ofd;
	struct ofd_object	*fo;
	struct ofd_thread_info	*info;
	struct ost_lvb		*lvb;
	struct lu_env		 env;
	int			 rc = 0;

	ENTRY;

	LASSERT(res != NULL);

	ofd = ldlm_res_to_ns(res)->ns_lvbp;
	LASSERT(ofd != NULL);

	rc = lu_env_init(&env, LCT_DT_THREAD);
	if (rc)
		RETURN(rc);

	info = ofd_info_init(&env, NULL);
	fid_extract_from_res_name(&info->fti_fid, &res->lr_name);

	lvb = res->lr_lvb_data;
	if (lvb == NULL) {
		CERROR("%s: no LVB data for "DFID"\n",
		       ofd_obd(ofd)->obd_name, PFID(&info->fti_fid));
		GOTO(out_env, rc = 0);
	}

	/* Update the LVB from the network message */
	if (req != NULL) {
		struct ost_lvb *rpc_lvb;
		bool lvb_type;

		if (req->rq_import != NULL)
			lvb_type = imp_connect_lvb_type(req->rq_import);
		else
			lvb_type = exp_connect_lvb_type(req->rq_export);

		if (!lvb_type) {
			struct ost_lvb_v1 *lvb_v1;

			lvb_v1 = req_capsule_server_swab_get(&req->rq_pill,
					&RMF_DLM_LVB, lustre_swab_ost_lvb_v1);
			if (lvb_v1 == NULL)
				goto disk_update;

			rpc_lvb = &info->fti_lvb;
			memcpy(rpc_lvb, lvb_v1, sizeof *lvb_v1);
			rpc_lvb->lvb_mtime_ns = 0;
			rpc_lvb->lvb_atime_ns = 0;
			rpc_lvb->lvb_ctime_ns = 0;
		} else {
			rpc_lvb = req_capsule_server_swab_get(&req->rq_pill,
							      &RMF_DLM_LVB,
							lustre_swab_ost_lvb);
			if (rpc_lvb == NULL)
				goto disk_update;
		}

		lock_res(res);
		if (rpc_lvb->lvb_size > lvb->lvb_size || !increase_only) {
			CDEBUG(D_DLMTRACE, "res: "DFID" updating lvb size: "
			       LPU64" -> "LPU64"\n", PFID(&info->fti_fid),
			       lvb->lvb_size, rpc_lvb->lvb_size);
			lvb->lvb_size = rpc_lvb->lvb_size;
		}
		if (rpc_lvb->lvb_mtime > lvb->lvb_mtime || !increase_only) {
			CDEBUG(D_DLMTRACE, "res: "DFID" updating lvb mtime: "
			       LPU64" -> "LPU64"\n", PFID(&info->fti_fid),
			       lvb->lvb_mtime, rpc_lvb->lvb_mtime);
			lvb->lvb_mtime = rpc_lvb->lvb_mtime;
		}
		if (rpc_lvb->lvb_atime > lvb->lvb_atime || !increase_only) {
			CDEBUG(D_DLMTRACE, "res: "DFID" updating lvb atime: "
			       LPU64" -> "LPU64"\n", PFID(&info->fti_fid),
			       lvb->lvb_atime, rpc_lvb->lvb_atime);
			lvb->lvb_atime = rpc_lvb->lvb_atime;
		}
		if (rpc_lvb->lvb_ctime > lvb->lvb_ctime || !increase_only) {
			CDEBUG(D_DLMTRACE, "res: "DFID" updating lvb ctime: "
			       LPU64" -> "LPU64"\n", PFID(&info->fti_fid),
			       lvb->lvb_ctime, rpc_lvb->lvb_ctime);
			lvb->lvb_ctime = rpc_lvb->lvb_ctime;
		}
		if (rpc_lvb->lvb_blocks > lvb->lvb_blocks || !increase_only) {
			CDEBUG(D_DLMTRACE, "res: "DFID" updating lvb blocks: "
			       LPU64" -> "LPU64"\n", PFID(&info->fti_fid),
			       lvb->lvb_blocks, rpc_lvb->lvb_blocks);
			lvb->lvb_blocks = rpc_lvb->lvb_blocks;
		}
		unlock_res(res);
	}

disk_update:
	/* Update the LVB from the disk inode */
	ost_fid_from_resid(&info->fti_fid, &res->lr_name,
			   ofd->ofd_lut.lut_lsd.lsd_osd_index);
	fo = ofd_object_find(&env, ofd, &info->fti_fid);
	if (IS_ERR(fo))
		GOTO(out_env, rc = PTR_ERR(fo));

	rc = ofd_attr_get(&env, fo, &info->fti_attr);
	if (rc)
		GOTO(out_obj, rc);

	lock_res(res);
	if (info->fti_attr.la_size > lvb->lvb_size || !increase_only) {
		CDEBUG(D_DLMTRACE, "res: "DFID" updating lvb size from disk: "
		       LPU64" -> %llu\n", PFID(&info->fti_fid),
		       lvb->lvb_size, info->fti_attr.la_size);
		lvb->lvb_size = info->fti_attr.la_size;
	}

	if (info->fti_attr.la_mtime >lvb->lvb_mtime || !increase_only) {
		CDEBUG(D_DLMTRACE, "res: "DFID" updating lvb mtime from disk: "
		       LPU64" -> "LPU64"\n", PFID(&info->fti_fid),
		       lvb->lvb_mtime, info->fti_attr.la_mtime);
		lvb->lvb_mtime = info->fti_attr.la_mtime;
	}
	if (info->fti_attr.la_atime >lvb->lvb_atime || !increase_only) {
		CDEBUG(D_DLMTRACE, "res: "DFID" updating lvb atime from disk: "
		       LPU64" -> "LPU64"\n", PFID(&info->fti_fid),
		       lvb->lvb_atime, info->fti_attr.la_atime);
		lvb->lvb_atime = info->fti_attr.la_atime;
	}
	if (info->fti_attr.la_ctime >lvb->lvb_ctime || !increase_only) {
		CDEBUG(D_DLMTRACE, "res: "DFID" updating lvb ctime from disk: "
		       LPU64" -> "LPU64"\n", PFID(&info->fti_fid),
		       lvb->lvb_ctime, info->fti_attr.la_ctime);
		lvb->lvb_ctime = info->fti_attr.la_ctime;
	}
	if (info->fti_attr.la_blocks > lvb->lvb_blocks || !increase_only) {
		CDEBUG(D_DLMTRACE, "res: "DFID" updating lvb blocks from disk: "
		       LPU64" -> %llu\n", PFID(&info->fti_fid), lvb->lvb_blocks,
		       (unsigned long long)info->fti_attr.la_blocks);
		lvb->lvb_blocks = info->fti_attr.la_blocks;
	}
	unlock_res(res);

out_obj:
	ofd_object_put(&env, fo);
out_env:
	lu_env_fini(&env);
	return rc;
}