Пример #1
0
/* copied from lov/lov_ea.c, just for debugging, will be removed later */
void mdt_dump_lmm(int level, const struct lov_mds_md *lmm, __u64 valid)
{
	const struct lov_ost_data_v1	*lod;
	int				 i;
	__u16				 count;

	if (likely(!cfs_cdebug_show(level, DEBUG_SUBSYSTEM)))
		return;

	count = le16_to_cpu(((struct lov_user_md *)lmm)->lmm_stripe_count);

	CDEBUG(level, "objid "DOSTID", magic 0x%08X, pattern %#X\n",
	       POSTID(&lmm->lmm_oi), le32_to_cpu(lmm->lmm_magic),
	       le32_to_cpu(lmm->lmm_pattern));
	CDEBUG(level, "stripe_size=0x%x, stripe_count=0x%x\n",
	       le32_to_cpu(lmm->lmm_stripe_size), count);

	/* If it's a directory or a released file, then there are
	 * no actual objects to print, so bail out. */
	if (valid & OBD_MD_FLDIREA ||
	    le32_to_cpu(lmm->lmm_pattern) & LOV_PATTERN_F_RELEASED)
		return;

	LASSERT(count <= LOV_MAX_STRIPE_COUNT);
	for (i = 0, lod = lmm->lmm_objects; i < count; i++, lod++) {
		struct ost_id oi;

		ostid_le_to_cpu(&lod->l_ost_oi, &oi);
		CDEBUG(level, "stripe %u idx %u subobj "DOSTID"\n",
		       i, le32_to_cpu(lod->l_ost_idx), POSTID(&oi));
	}
}
Пример #2
0
/* returns negative on error; 0 if success; 1 if success & log destroyed */
int llog_cancel_rec(const struct lu_env *env, struct llog_handle *loghandle,
		    int index)
{
        struct llog_log_hdr *llh = loghandle->lgh_hdr;
        int rc = 0;
        ENTRY;

        CDEBUG(D_RPCTRACE, "Canceling %d in log "DOSTID"\n",
               index, POSTID(&loghandle->lgh_id.lgl_oi));

        if (index == 0) {
                CERROR("Can't cancel index 0 which is header\n");
                RETURN(-EINVAL);
        }

	spin_lock(&loghandle->lgh_hdr_lock);
	if (!ext2_clear_bit(index, llh->llh_bitmap)) {
		spin_unlock(&loghandle->lgh_hdr_lock);
		CDEBUG(D_RPCTRACE, "Catalog index %u already clear?\n", index);
		RETURN(-ENOENT);
	}

	llh->llh_count--;

	if ((llh->llh_flags & LLOG_F_ZAP_WHEN_EMPTY) &&
	    (llh->llh_count == 1) &&
	    (loghandle->lgh_last_idx == (LLOG_BITMAP_BYTES * 8) - 1)) {
		spin_unlock(&loghandle->lgh_hdr_lock);
		rc = llog_destroy(env, loghandle);
		if (rc < 0) {
			CERROR("%s: can't destroy empty llog #"DOSTID
			       "#%08x: rc = %d\n",
			       loghandle->lgh_ctxt->loc_obd->obd_name,
			       POSTID(&loghandle->lgh_id.lgl_oi),
			       loghandle->lgh_id.lgl_ogen, rc);
			GOTO(out_err, rc);
		}
		RETURN(1);
	}
	spin_unlock(&loghandle->lgh_hdr_lock);

	rc = llog_write(env, loghandle, &llh->llh_hdr, NULL, 0, NULL, 0);
	if (rc < 0) {
		CERROR("%s: fail to write header for llog #"DOSTID
		       "#%08x: rc = %d\n",
		       loghandle->lgh_ctxt->loc_obd->obd_name,
		       POSTID(&loghandle->lgh_id.lgl_oi),
		       loghandle->lgh_id.lgl_ogen, rc);
		GOTO(out_err, rc);
	}
	RETURN(0);
out_err:
	spin_lock(&loghandle->lgh_hdr_lock);
	ext2_set_bit(index, llh->llh_bitmap);
	llh->llh_count++;
	spin_unlock(&loghandle->lgh_hdr_lock);
	return rc;
}
Пример #3
0
static int llog_remove_log(const struct lu_env *env, struct llog_handle *cat,
			   struct llog_logid *logid)
{
	struct llog_handle	*log;
	int			 rc;

	ENTRY;

	rc = llog_cat_id2handle(env, cat, &log, logid);
	if (rc) {
		CDEBUG(D_IOCTL, "cannot find log #"DOSTID"#%08x\n",
		       POSTID(&logid->lgl_oi), logid->lgl_ogen);
		RETURN(-ENOENT);
	}

	rc = llog_destroy(env, log);
	if (rc) {
		CDEBUG(D_IOCTL, "cannot destroy log\n");
		GOTO(out, rc);
	}
	llog_cat_cleanup(env, cat, log, log->u.phd.phd_cookie.lgc_index);
out:
	llog_handle_put(log);
	RETURN(rc);

}
Пример #4
0
void dump_lsm(unsigned int level, const struct lov_stripe_md *lsm)
{
	CDEBUG(level, "lsm %p, objid " DOSTID ", maxbytes %#llx, magic 0x%08X, stripe_size %u, stripe_count %u, refc: %d, layout_gen %u, pool [" LOV_POOLNAMEF "]\n",
	       lsm,
	       POSTID(&lsm->lsm_oi), lsm->lsm_maxbytes, lsm->lsm_magic,
	       lsm->lsm_stripe_size, lsm->lsm_stripe_count,
	       atomic_read(&lsm->lsm_refc), lsm->lsm_layout_gen,
	       lsm->lsm_pool_name);
}
Пример #5
0
void obdo_cpy_md(struct obdo *dst, struct obdo *src, obd_flag valid)
{
	CDEBUG(D_INODE, "src obdo "DOSTID" valid "LPX64", dst obdo "DOSTID"\n",
	       POSTID(&src->o_oi), src->o_valid, POSTID(&dst->o_oi));
	if (valid & OBD_MD_FLATIME)
		dst->o_atime = src->o_atime;
	if (valid & OBD_MD_FLMTIME)
		dst->o_mtime = src->o_mtime;
	if (valid & OBD_MD_FLCTIME)
		dst->o_ctime = src->o_ctime;
	if (valid & OBD_MD_FLSIZE)
		dst->o_size = src->o_size;
	if (valid & OBD_MD_FLBLOCKS) /* allocation of space */
		dst->o_blocks = src->o_blocks;
	if (valid & OBD_MD_FLBLKSZ)
		dst->o_blksize = src->o_blksize;
	if (valid & OBD_MD_FLTYPE)
		dst->o_mode = (dst->o_mode & ~S_IFMT) | (src->o_mode & S_IFMT);
	if (valid & OBD_MD_FLMODE)
		dst->o_mode = (dst->o_mode & S_IFMT) | (src->o_mode & ~S_IFMT);
	if (valid & OBD_MD_FLUID)
		dst->o_uid = src->o_uid;
	if (valid & OBD_MD_FLGID)
		dst->o_gid = src->o_gid;
	if (valid & OBD_MD_FLFLAGS)
		dst->o_flags = src->o_flags;
	if (valid & OBD_MD_FLFID) {
		dst->o_parent_seq = src->o_parent_seq;
		dst->o_parent_ver = src->o_parent_ver;
	}
	if (valid & OBD_MD_FLGENER)
		dst->o_parent_oid = src->o_parent_oid;
	if (valid & OBD_MD_FLHANDLE)
		dst->o_handle = src->o_handle;
	if (valid & OBD_MD_FLCOOKIE)
		dst->o_lcookie = src->o_lcookie;

	dst->o_valid |= valid;
}
Пример #6
0
static void print_llogd_body(struct llogd_body *d)
{
	CDEBUG(D_OTHER, "llogd body: %p\n", d);
	CDEBUG(D_OTHER, "\tlgd_logid.lgl_oi: "DOSTID"\n",
	       POSTID(&d->lgd_logid.lgl_oi));
	CDEBUG(D_OTHER, "\tlgd_logid.lgl_ogen: %#x\n", d->lgd_logid.lgl_ogen);
	CDEBUG(D_OTHER, "\tlgd_ctxt_idx: %#x\n", d->lgd_ctxt_idx);
	CDEBUG(D_OTHER, "\tlgd_llh_flags: %#x\n", d->lgd_llh_flags);
	CDEBUG(D_OTHER, "\tlgd_index: %#x\n", d->lgd_index);
	CDEBUG(D_OTHER, "\tlgd_saved_index: %#x\n", d->lgd_saved_index);
	CDEBUG(D_OTHER, "\tlgd_len: %#x\n", d->lgd_len);
	CDEBUG(D_OTHER, "\tlgd_cur_offset: %#llx\n", d->lgd_cur_offset);
}
Пример #7
0
/* the replicators commit callback */
static int lov_llog_repl_cancel(const struct lu_env *env,
				struct llog_ctxt *ctxt,
				struct lov_stripe_md *lsm,
				int count, struct llog_cookie *cookies,
				int flags)
{
        struct lov_obd *lov;
        struct obd_device *obd = ctxt->loc_obd;
        int rc = 0, i;
        ENTRY;

        LASSERT(lsm != NULL);
        LASSERT(count == lsm->lsm_stripe_count);

        lov = &obd->u.lov;
        obd_getref(obd);
        for (i = 0; i < count; i++, cookies++) {
                struct lov_oinfo *loi = lsm->lsm_oinfo[i];
                struct obd_device *child =
                        lov->lov_tgts[loi->loi_ost_idx]->ltd_exp->exp_obd;
                struct llog_ctxt *cctxt =
                        llog_get_context(child, ctxt->loc_idx);
                int err;

		err = llog_cancel(env, cctxt, NULL, 1, cookies, flags);
		llog_ctxt_put(cctxt);
		if (err && lov->lov_tgts[loi->loi_ost_idx]->ltd_active) {
			CERROR("%s: objid "DOSTID" subobj "DOSTID
			       " on OST idx %d: rc = %d\n",
			       obd->obd_name, POSTID(&lsm->lsm_oi),
			       POSTID(&loi->loi_oi), loi->loi_ost_idx, err);
			if (!rc)
				rc = err;
		}
	}
	obd_putref(obd);
	RETURN(rc);
}
Пример #8
0
static int osc_object_print(const struct lu_env *env, void *cookie,
			    lu_printer_t p, const struct lu_object *obj)
{
	struct osc_object   *osc   = lu2osc(obj);
	struct lov_oinfo    *oinfo = osc->oo_oinfo;
	struct osc_async_rc *ar    = &oinfo->loi_ar;

	(*p)(env, cookie, "id: " DOSTID " idx: %d gen: %d kms_valid: %u kms %llu rc: %d force_sync: %d min_xid: %llu ",
	     POSTID(&oinfo->loi_oi), oinfo->loi_ost_idx,
	     oinfo->loi_ost_gen, oinfo->loi_kms_valid, oinfo->loi_kms,
	     ar->ar_rc, ar->ar_force_sync, ar->ar_min_xid);
	osc_lvb_print(env, cookie, p, &oinfo->loi_lvb);
	return 0;
}
Пример #9
0
void lov_dump_lmm_common(int level, void *lmmp)
{
	struct lov_mds_md *lmm = lmmp;
	struct ost_id	oi;

	lmm_oi_le_to_cpu(&oi, &lmm->lmm_oi);
	CDEBUG(level, "objid "DOSTID", magic 0x%08x, pattern %#x\n",
	       POSTID(&oi), le32_to_cpu(lmm->lmm_magic),
	       le32_to_cpu(lmm->lmm_pattern));
	CDEBUG(level, "stripe_size %u, stripe_count %u, layout_gen %u\n",
	       le32_to_cpu(lmm->lmm_stripe_size),
	       le16_to_cpu(lmm->lmm_stripe_count),
	       le16_to_cpu(lmm->lmm_layout_gen));
}
Пример #10
0
/* copied from lov/lov_ea.c, just for debugging, will be removed later */
void mdt_dump_lmm(int level, const struct lov_mds_md *lmm)
{
        const struct lov_ost_data_v1 *lod;
        int                           i;
        __u16                         count;

        count = le16_to_cpu(((struct lov_user_md*)lmm)->lmm_stripe_count);

	CDEBUG(level, "objid "DOSTID", magic 0x%08X, pattern %#X\n",
	       POSTID(&lmm->lmm_oi), le32_to_cpu(lmm->lmm_magic),
	       le32_to_cpu(lmm->lmm_pattern));
        CDEBUG(level,"stripe_size=0x%x, stripe_count=0x%x\n",
               le32_to_cpu(lmm->lmm_stripe_size), count);
        if (count == LOV_ALL_STRIPES)
                return;

	LASSERT(count <= LOV_MAX_STRIPE_COUNT);
	for (i = 0, lod = lmm->lmm_objects; i < count; i++, lod++) {
		struct ost_id	oi;
		ostid_le_to_cpu((struct ost_id *)&lod->l_ost_oi, &oi);
		CDEBUG(level, "stripe %u idx %u subobj "DOSTID"\n",
		       i, le32_to_cpu(lod->l_ost_idx), POSTID(&oi));
	}
}
Пример #11
0
int llog_catalog_list(const struct lu_env *env, struct dt_device *d,
		      int count, struct obd_ioctl_data *data,
		      const struct lu_fid *fid)
{
	int			 size, i;
	struct llog_catid	*idarray;
	struct llog_logid	*id;
	char			*out;
	int			 l, remains, rc = 0;

	ENTRY;

	if (count == 0) { /* get total number of logs */
		rc = llog_osd_get_cat_list(env, d, 0, 0, NULL, fid);
		if (rc < 0)
			RETURN(rc);
		count = rc;
	}

	size = sizeof(*idarray) * count;

	OBD_ALLOC_LARGE(idarray, size);
	if (!idarray)
		RETURN(-ENOMEM);

	rc = llog_osd_get_cat_list(env, d, 0, count, idarray, fid);
	if (rc)
		GOTO(out, rc);

	out = data->ioc_bulk;
	remains = data->ioc_inllen1;
	for (i = 0; i < count; i++) {
		id = &idarray[i].lci_logid;
		l = snprintf(out, remains,
			     "catalog log: #"DOSTID"#%08x\n",
			     POSTID(&id->lgl_oi),
			     id->lgl_ogen);
		out += l;
		remains -= l;
		if (remains <= 0)
			break;
	}
out:
	OBD_FREE_LARGE(idarray, size);
	RETURN(rc);
}
Пример #12
0
static int changelog_init_cb(const struct lu_env *env, struct llog_handle *llh,
			     struct llog_rec_hdr *hdr, void *data)
{
	struct mdd_device *mdd = (struct mdd_device *)data;
	struct llog_changelog_rec *rec = (struct llog_changelog_rec *)hdr;

	LASSERT(llh->lgh_hdr->llh_flags & LLOG_F_IS_PLAIN);
	LASSERT(rec->cr_hdr.lrh_type == CHANGELOG_REC);

	CDEBUG(D_INFO,
	       "seeing record at index %d/%d/"LPU64" t=%x %.*s in log"
	       DOSTID"\n", hdr->lrh_index, rec->cr_hdr.lrh_index,
	       rec->cr.cr_index, rec->cr.cr_type, rec->cr.cr_namelen,
	       changelog_rec_name(&rec->cr), POSTID(&llh->lgh_id.lgl_oi));

	mdd->mdd_cl.mc_index = rec->cr.cr_index;
	return LLOG_PROC_BREAK;
}
Пример #13
0
/** Merge the lock value block(&lvb) attributes from each of the stripes in a
 * file into a single lvb. It is expected that the caller initializes the
 * current atime, mtime, ctime to avoid regressing a more uptodate time on
 * the local client.
 *
 * If \a kms_only is set then we do not consider the recently seen size (rss)
 * when updating the known minimum size (kms).  Even when merging RSS, we will
 * take the KMS value if it's larger.  This prevents getattr from stomping on
 * dirty cached pages which extend the file size. */
int lov_merge_lvb(struct obd_export *exp,
		  struct lov_stripe_md *lsm, struct ost_lvb *lvb, int kms_only)
{
	int   rc;
	__u64 kms;

	ENTRY;
	lov_stripe_lock(lsm);
	rc = lov_merge_lvb_kms(lsm, lvb, &kms);
	lov_stripe_unlock(lsm);
	if (kms_only)
		lvb->lvb_size = kms;

	CDEBUG(D_INODE, "merged for ID "DOSTID" s="LPU64" m="LPU64" a="LPU64
	       " c="LPU64" b="LPU64"\n", POSTID(&lsm->lsm_oi), lvb->lvb_size,
	       lvb->lvb_mtime, lvb->lvb_atime, lvb->lvb_ctime, lvb->lvb_blocks);
	RETURN(rc);
}
Пример #14
0
int lov_setea(struct obd_export *exp, struct lov_stripe_md **lsmp,
              struct lov_user_md *lump)
{
        int i;
        int rc;
        struct obd_export *oexp;
        struct lov_obd *lov = &exp->exp_obd->u.lov;
        obd_id last_id = 0;
        struct lov_user_ost_data_v1 *lmm_objects;

        ENTRY;

        if (lump->lmm_magic == LOV_USER_MAGIC_V3)
                lmm_objects = ((struct lov_user_md_v3 *)lump)->lmm_objects;
        else
                lmm_objects = lump->lmm_objects;

        for (i = 0; i < lump->lmm_stripe_count; i++) {
                __u32 len = sizeof(last_id);
                oexp = lov->lov_tgts[lmm_objects[i].l_ost_idx]->ltd_exp;
                rc = obd_get_info(NULL, oexp, sizeof(KEY_LAST_ID), KEY_LAST_ID,
                                  &len, &last_id, NULL);
                if (rc)
                        RETURN(rc);
		if (ostid_id(&lmm_objects[i].l_ost_oi) > last_id) {
			CERROR("Setting EA for object > than last id on"
			       " ost idx %d "DOSTID" > "LPD64" \n",
			       lmm_objects[i].l_ost_idx,
			       POSTID(&lmm_objects[i].l_ost_oi), last_id);
			RETURN(-EINVAL);
		}
        }

        rc = lov_setstripe(exp, 0, lsmp, lump);
        if (rc)
                RETURN(rc);

        for (i = 0; i < lump->lmm_stripe_count; i++) {
                (*lsmp)->lsm_oinfo[i]->loi_ost_idx =
                        lmm_objects[i].l_ost_idx;
		(*lsmp)->lsm_oinfo[i]->loi_oi = lmm_objects[i].l_ost_oi;
        }
        RETURN(0);
}
Пример #15
0
static void lov_dump_lmm_objects(int level, struct lov_ost_data *lod,
				 int stripe_count)
{
	int i;

	if (stripe_count > LOV_V1_INSANE_STRIPE_COUNT) {
		CDEBUG(level, "bad stripe_count %u > max_stripe_count %u\n",
		       stripe_count, LOV_V1_INSANE_STRIPE_COUNT);
		return;
	}

	for (i = 0; i < stripe_count; ++i, ++lod) {
		struct ost_id oi;

		ostid_le_to_cpu(&lod->l_ost_oi, &oi);
		CDEBUG(level, "stripe %u idx %u subobj "DOSTID"\n", i,
		       le32_to_cpu(lod->l_ost_idx), POSTID(&oi));
	}
}
Пример #16
0
static int llog_lvfs_close(const struct lu_env *env,
			   struct llog_handle *handle)
{
	int rc;

	if (handle->lgh_file == NULL)
		return 0;
	rc = filp_close(handle->lgh_file, 0);
	if (rc)
		CERROR("%s: error closing llog #"DOSTID"#%08x: "
		       "rc = %d\n", handle->lgh_ctxt->loc_obd->obd_name,
		       POSTID(&handle->lgh_id.lgl_oi),
		       handle->lgh_id.lgl_ogen, rc);
	handle->lgh_file = NULL;
	if (handle->lgh_name) {
		OBD_FREE(handle->lgh_name, strlen(handle->lgh_name) + 1);
		handle->lgh_name = NULL;
	}
	return rc;
}
Пример #17
0
void obdo_to_inode(struct inode *dst, struct obdo *src, obd_flag valid)
{
	valid &= src->o_valid;

	LASSERTF(!(valid & (OBD_MD_FLTYPE | OBD_MD_FLGENER | OBD_MD_FLFID |
			    OBD_MD_FLID | OBD_MD_FLGROUP)),
		 "object "DOSTID", valid %x\n", POSTID(&src->o_oi), valid);

	if (valid & (OBD_MD_FLCTIME | OBD_MD_FLMTIME))
		CDEBUG(D_INODE,
		       "valid %#llx, cur time %lu/%lu, new %llu/%llu\n",
		       src->o_valid, LTIME_S(dst->i_mtime),
		       LTIME_S(dst->i_ctime), src->o_mtime, src->o_ctime);

	if (valid & OBD_MD_FLATIME)
		LTIME_S(dst->i_atime) = src->o_atime;
	if (valid & OBD_MD_FLMTIME)
		LTIME_S(dst->i_mtime) = src->o_mtime;
	if (valid & OBD_MD_FLCTIME && src->o_ctime > LTIME_S(dst->i_ctime))
		LTIME_S(dst->i_ctime) = src->o_ctime;
	if (valid & OBD_MD_FLSIZE)
		i_size_write(dst, src->o_size);
	if (valid & OBD_MD_FLBLOCKS) { /* allocation of space */
		dst->i_blocks = src->o_blocks;
		if (dst->i_blocks < src->o_blocks) /* overflow */
			dst->i_blocks = -1;

	}
	if (valid & OBD_MD_FLBLKSZ)
		dst->i_blkbits = ffs(src->o_blksize)-1;
	if (valid & OBD_MD_FLMODE)
		dst->i_mode = (dst->i_mode & S_IFMT) | (src->o_mode & ~S_IFMT);
	if (valid & OBD_MD_FLUID)
		dst->i_uid = make_kuid(&init_user_ns, src->o_uid);
	if (valid & OBD_MD_FLGID)
		dst->i_gid = make_kgid(&init_user_ns, src->o_gid);
	if (valid & OBD_MD_FLFLAGS)
		dst->i_flags = src->o_flags;
}
Пример #18
0
static int changelog_user_init_cb(const struct lu_env *env,
				  struct llog_handle *llh,
				  struct llog_rec_hdr *hdr, void *data)
{
        struct mdd_device *mdd = (struct mdd_device *)data;
        struct llog_changelog_user_rec *rec =
                (struct llog_changelog_user_rec *)hdr;

        LASSERT(llh->lgh_hdr->llh_flags & LLOG_F_IS_PLAIN);
        LASSERT(rec->cur_hdr.lrh_type == CHANGELOG_USER_REC);

        CDEBUG(D_INFO, "seeing user at index %d/%d id=%d endrec="LPU64
               " in log "DOSTID"\n", hdr->lrh_index, rec->cur_hdr.lrh_index,
               rec->cur_id, rec->cur_endrec, POSTID(&llh->lgh_id.lgl_oi));

	spin_lock(&mdd->mdd_cl.mc_user_lock);
	mdd->mdd_cl.mc_lastuser = rec->cur_id;
	if (rec->cur_endrec > mdd->mdd_cl.mc_index)
		mdd->mdd_cl.mc_index = rec->cur_endrec;
	spin_unlock(&mdd->mdd_cl.mc_user_lock);

	return LLOG_PROC_BREAK;
}
Пример #19
0
static int llog_changelog_cancel(const struct lu_env *env,
				 struct llog_ctxt *ctxt,
				 struct llog_cookie *cookies, int flags)
{
	struct llog_handle	*cathandle = ctxt->loc_handle;
	int			 rc;

	ENTRY;

	/* This should only be called with the catalog handle */
	LASSERT(cathandle->lgh_hdr->llh_flags & LLOG_F_IS_CAT);

	rc = llog_cat_process(env, cathandle, llog_changelog_cancel_cb,
			      (void *)cookies, 0, 0);
	if (rc >= 0)
		/* 0 or 1 means we're done */
		rc = 0;
	else
		CERROR("%s: cancel idx %u of catalog "DOSTID" rc=%d\n",
		       ctxt->loc_obd->obd_name, cathandle->lgh_last_idx,
		       POSTID(&cathandle->lgh_id.lgl_oi), rc);

	RETURN(rc);
}
Пример #20
0
/**
 * Implementation of the llog_operations::lop_prev_block
 *
 * This function finds the llog block to return which contains
 * record with required index but in reverse order - from end of llog
 * to the beginning.
 * It is main part of reverse llog processing.
 *
 * \param[in] env	execution environment
 * \param[in] loghandle	llog handle of the current llog
 * \param[in] prev_idx	target index to find
 * \param[in] buf	pointer to data buffer to fill
 * \param[in] len	required len to read, it is LLOG_CHUNK_SIZE usually.
 *
 * \retval		0 on successful buffer read
 * \retval		negative value on error
 */
static int llog_osd_prev_block(const struct lu_env *env,
			       struct llog_handle *loghandle,
			       int prev_idx, void *buf, int len)
{
	struct llog_thread_info	*lgi = llog_info(env);
	struct dt_object	*o;
	struct dt_device	*dt;
	loff_t			 cur_offset;
	int			 rc;

	ENTRY;

	if (len == 0 || len & (LLOG_CHUNK_SIZE - 1))
		RETURN(-EINVAL);

	CDEBUG(D_OTHER, "looking for log index %u\n", prev_idx);

	LASSERT(loghandle);
	LASSERT(loghandle->lgh_ctxt);

	o = loghandle->lgh_obj;
	LASSERT(o);
	LASSERT(dt_object_exists(o));
	dt = lu2dt_dev(o->do_lu.lo_dev);
	LASSERT(dt);

	cur_offset = LLOG_CHUNK_SIZE;
	llog_skip_over(&cur_offset, 0, prev_idx);

	rc = dt_attr_get(env, o, &lgi->lgi_attr, BYPASS_CAPA);
	if (rc)
		GOTO(out, rc);

	while (cur_offset < lgi->lgi_attr.la_size) {
		struct llog_rec_hdr	*rec, *last_rec;
		struct llog_rec_tail	*tail;

		lgi->lgi_buf.lb_len = len;
		lgi->lgi_buf.lb_buf = buf;
		rc = dt_read(env, o, &lgi->lgi_buf, &cur_offset);
		if (rc < 0) {
			CERROR("%s: can't read llog block from log "DFID
			       " offset "LPU64": rc = %d\n",
			       o->do_lu.lo_dev->ld_obd->obd_name,
			       PFID(lu_object_fid(&o->do_lu)), cur_offset, rc);
			GOTO(out, rc);
		}

		if (rc == 0) /* end of file, nothing to do */
			GOTO(out, rc);

		if (rc < sizeof(*tail)) {
			CERROR("%s: invalid llog block at log id "DOSTID"/%u "
			       "offset "LPU64"\n",
			       o->do_lu.lo_dev->ld_obd->obd_name,
			       POSTID(&loghandle->lgh_id.lgl_oi),
			       loghandle->lgh_id.lgl_ogen, cur_offset);
			GOTO(out, rc = -EINVAL);
		}

		rec = buf;
		if (LLOG_REC_HDR_NEEDS_SWABBING(rec))
			lustre_swab_llog_rec(rec);

		tail = (struct llog_rec_tail *)((char *)buf + rc -
						sizeof(struct llog_rec_tail));
		/* get the last record in block */
		last_rec = (struct llog_rec_hdr *)((char *)buf + rc -
						   le32_to_cpu(tail->lrt_len));

		if (LLOG_REC_HDR_NEEDS_SWABBING(last_rec))
			lustre_swab_llog_rec(last_rec);
		LASSERT(last_rec->lrh_index == tail->lrt_index);

		/* this shouldn't happen */
		if (tail->lrt_index == 0) {
			CERROR("%s: invalid llog tail at log id "DOSTID"/%u "
			       "offset "LPU64"\n",
			       o->do_lu.lo_dev->ld_obd->obd_name,
			       POSTID(&loghandle->lgh_id.lgl_oi),
			       loghandle->lgh_id.lgl_ogen, cur_offset);
			GOTO(out, rc = -EINVAL);
		}
		if (tail->lrt_index < prev_idx)
			continue;

		/* sanity check that the start of the new buffer is no farther
		 * than the record that we wanted.  This shouldn't happen. */
		if (rec->lrh_index > prev_idx) {
			CERROR("%s: missed desired record? %u > %u\n",
			       o->do_lu.lo_dev->ld_obd->obd_name,
			       rec->lrh_index, prev_idx);
			GOTO(out, rc = -ENOENT);
		}
		GOTO(out, rc = 0);
	}
	GOTO(out, rc = -EIO);
out:
	return rc;
}
Пример #21
0
/**
 * Implementation of the llog_operations::lop_write
 *
 * This function writes the new record in the llog or modify the existed one.
 *
 * \param[in]  env		execution environment
 * \param[in]  loghandle	llog handle of the current llog
 * \param[in]  rec		llog record header. This is a real header of
 *				the full llog record to write. This is
 *				the beginning of buffer to write, the length
 *				of buffer is stored in \a rec::lrh_len
 * \param[out] reccookie	pointer to the cookie to return back if needed.
 *				It is used for further cancel of this llog
 *				record.
 * \param[in]  idx		index of the llog record. If \a idx == -1 then
 *				this is append case, otherwise \a idx is
 *				the index of record to modify
 * \param[in]  th		current transaction handle
 *
 * \retval			0 on successful write && \a reccookie == NULL
 *				1 on successful write && \a reccookie != NULL
 * \retval			negative error if write failed
 */
static int llog_osd_write_rec(const struct lu_env *env,
			      struct llog_handle *loghandle,
			      struct llog_rec_hdr *rec,
			      struct llog_cookie *reccookie,
			      int idx, struct thandle *th)
{
	struct llog_thread_info	*lgi = llog_info(env);
	struct llog_log_hdr	*llh;
	int			 reclen = rec->lrh_len;
	int			 index, rc;
	struct llog_rec_tail	*lrt;
	struct dt_object	*o;
	size_t			 left;
	bool			 header_is_updated = false;

	ENTRY;

	LASSERT(env);
	llh = loghandle->lgh_hdr;
	LASSERT(llh);
	o = loghandle->lgh_obj;
	LASSERT(o);
	LASSERT(th);

	CDEBUG(D_OTHER, "new record %x to "DFID"\n",
	       rec->lrh_type, PFID(lu_object_fid(&o->do_lu)));

	/* record length should not bigger than LLOG_CHUNK_SIZE */
	if (reclen > LLOG_CHUNK_SIZE)
		RETURN(-E2BIG);

	rc = dt_attr_get(env, o, &lgi->lgi_attr, NULL);
	if (rc)
		RETURN(rc);

	/**
	 * The modification case.
	 * If idx set then the record with that index must be modified.
	 * There are three cases possible:
	 * 1) the common case is the llog header update (idx == 0)
	 * 2) the llog record modification during llog process.
	 *    This is indicated by the \a loghandle::lgh_cur_idx > 0.
	 *    In that case the \a loghandle::lgh_cur_offset
	 * 3) otherwise this is assumed that llog consist of records of
	 *    fixed size, i.e. catalog. The llog header must has llh_size
	 *    field equal to record size. The record offset is calculated
	 *    just by /a idx value
	 *
	 * During modification we don't need extra header update because
	 * the bitmap and record count are not changed. The record header
	 * and tail remains the same too.
	 */
	if (idx != LLOG_NEXT_IDX) {
		/* llog can be empty only when first record is being written */
		LASSERT(ergo(idx > 0, lgi->lgi_attr.la_size > 0));

		if (!ext2_test_bit(idx, llh->llh_bitmap)) {
			CERROR("%s: modify unset record %u\n",
			       o->do_lu.lo_dev->ld_obd->obd_name, idx);
			RETURN(-ENOENT);
		}

		if (idx != rec->lrh_index) {
			CERROR("%s: modify index mismatch %d %u\n",
			       o->do_lu.lo_dev->ld_obd->obd_name, idx,
			       rec->lrh_index);
			RETURN(-EFAULT);
		}

		if (idx == LLOG_HEADER_IDX) {
			/* llog header update */
			LASSERT(reclen == sizeof(struct llog_log_hdr));
			LASSERT(rec == &llh->llh_hdr);

			lgi->lgi_off = 0;
			lgi->lgi_buf.lb_len = reclen;
			lgi->lgi_buf.lb_buf = rec;
			rc = dt_record_write(env, o, &lgi->lgi_buf,
					     &lgi->lgi_off, th);
			RETURN(rc);
		} else if (loghandle->lgh_cur_idx > 0) {
			/**
			 * The lgh_cur_offset can be used only if index is
			 * the same.
			 */
			if (idx != loghandle->lgh_cur_idx) {
				CERROR("%s: modify index mismatch %d %d\n",
				       o->do_lu.lo_dev->ld_obd->obd_name, idx,
				       loghandle->lgh_cur_idx);
				RETURN(-EFAULT);
			}

			lgi->lgi_off = loghandle->lgh_cur_offset;
			CDEBUG(D_OTHER, "modify record "DOSTID": idx:%d, "
			       "len:%u offset %llu\n",
			       POSTID(&loghandle->lgh_id.lgl_oi), idx,
			       rec->lrh_len, (long long)lgi->lgi_off);
		} else if (llh->llh_size > 0) {
			if (llh->llh_size != rec->lrh_len) {
				CERROR("%s: wrong record size, llh_size is %u"
				       " but record size is %u\n",
				       o->do_lu.lo_dev->ld_obd->obd_name,
				       llh->llh_size, rec->lrh_len);
				RETURN(-EINVAL);
			}
			lgi->lgi_off = sizeof(*llh) + (idx - 1) * reclen;
		} else {
			/* This can be result of lgh_cur_idx is not set during
			 * llog processing or llh_size is not set to proper
			 * record size for fixed records llog. Therefore it is
			 * impossible to get record offset. */
			CERROR("%s: can't get record offset, idx:%d, "
			       "len:%u.\n", o->do_lu.lo_dev->ld_obd->obd_name,
			       idx, rec->lrh_len);
			RETURN(-EFAULT);
		}

		/* update only data, header and tail remain the same */
		lgi->lgi_off += sizeof(struct llog_rec_hdr);
		lgi->lgi_buf.lb_len = REC_DATA_LEN(rec);
		lgi->lgi_buf.lb_buf = REC_DATA(rec);
		rc = dt_record_write(env, o, &lgi->lgi_buf, &lgi->lgi_off, th);
		if (rc == 0 && reccookie) {
			reccookie->lgc_lgl = loghandle->lgh_id;
			reccookie->lgc_index = idx;
			rc = 1;
		}
		RETURN(rc);
	}

	/**
	 * The append case.
	 * The most common case of using llog. The new index is assigned to
	 * the new record, new bit is set in llog bitmap and llog count is
	 * incremented.
	 *
	 * Make sure that records don't cross a chunk boundary, so we can
	 * process them page-at-a-time if needed.  If it will cross a chunk
	 * boundary, write in a fake (but referenced) entry to pad the chunk.
	 */
	LASSERT(lgi->lgi_attr.la_valid & LA_SIZE);
	lgi->lgi_off = lgi->lgi_attr.la_size;
	left = LLOG_CHUNK_SIZE - (lgi->lgi_off & (LLOG_CHUNK_SIZE - 1));
	/* NOTE: padding is a record, but no bit is set */
	if (left != 0 && left != reclen &&
	    left < (reclen + LLOG_MIN_REC_SIZE)) {
		index = loghandle->lgh_last_idx + 1;
		rc = llog_osd_pad(env, o, &lgi->lgi_off, left, index, th);
		if (rc)
			RETURN(rc);
		loghandle->lgh_last_idx++; /* for pad rec */
	}
	/* if it's the last idx in log file, then return -ENOSPC */
	if (loghandle->lgh_last_idx >= LLOG_BITMAP_SIZE(llh) - 1)
		RETURN(-ENOSPC);

	/* increment the last_idx along with llh_tail index, they should
	 * be equal for a llog lifetime */
	loghandle->lgh_last_idx++;
	index = loghandle->lgh_last_idx;
	llh->llh_tail.lrt_index = index;
	/**
	 * NB: the caller should make sure only 1 process access
	 * the lgh_last_idx, e.g. append should be exclusive.
	 * Otherwise it might hit the assert.
	 */
	LASSERT(index < LLOG_BITMAP_SIZE(llh));
	rec->lrh_index = index;
	lrt = rec_tail(rec);
	lrt->lrt_len = rec->lrh_len;
	lrt->lrt_index = rec->lrh_index;

	/* the lgh_hdr_lock protects llog header data from concurrent
	 * update/cancel, the llh_count and llh_bitmap are protected */
	spin_lock(&loghandle->lgh_hdr_lock);
	if (ext2_set_bit(index, llh->llh_bitmap)) {
		CERROR("%s: index %u already set in log bitmap\n",
		       o->do_lu.lo_dev->ld_obd->obd_name, index);
		spin_unlock(&loghandle->lgh_hdr_lock);
		LBUG(); /* should never happen */
	}
	llh->llh_count++;
	spin_unlock(&loghandle->lgh_hdr_lock);

	lgi->lgi_off = 0;
	lgi->lgi_buf.lb_len = llh->llh_hdr.lrh_len;
	lgi->lgi_buf.lb_buf = &llh->llh_hdr;
	rc = dt_record_write(env, o, &lgi->lgi_buf, &lgi->lgi_off, th);
	if (rc)
		GOTO(out, rc);

	header_is_updated = true;
	rc = dt_attr_get(env, o, &lgi->lgi_attr, NULL);
	if (rc)
		GOTO(out, rc);

	LASSERT(lgi->lgi_attr.la_valid & LA_SIZE);
	lgi->lgi_off = lgi->lgi_attr.la_size;
	lgi->lgi_buf.lb_len = reclen;
	lgi->lgi_buf.lb_buf = rec;
	rc = dt_record_write(env, o, &lgi->lgi_buf, &lgi->lgi_off, th);
	if (rc < 0)
		GOTO(out, rc);

	CDEBUG(D_OTHER, "added record "DOSTID": idx: %u, %u\n",
	       POSTID(&loghandle->lgh_id.lgl_oi), index, rec->lrh_len);
	if (reccookie != NULL) {
		reccookie->lgc_lgl = loghandle->lgh_id;
		reccookie->lgc_index = index;
		if ((rec->lrh_type == MDS_UNLINK_REC) ||
		    (rec->lrh_type == MDS_SETATTR64_REC))
			reccookie->lgc_subsys = LLOG_MDS_OST_ORIG_CTXT;
		else if (rec->lrh_type == OST_SZ_REC)
			reccookie->lgc_subsys = LLOG_SIZE_ORIG_CTXT;
		else
			reccookie->lgc_subsys = -1;
		rc = 1;
	}
	RETURN(rc);
out:
	/* cleanup llog for error case */
	spin_lock(&loghandle->lgh_hdr_lock);
	ext2_clear_bit(index, llh->llh_bitmap);
	llh->llh_count--;
	spin_unlock(&loghandle->lgh_hdr_lock);

	/* restore llog last_idx */
	loghandle->lgh_last_idx--;
	llh->llh_tail.lrt_index = loghandle->lgh_last_idx;

	/* restore the header on disk if it was written */
	if (header_is_updated) {
		lgi->lgi_off = 0;
		lgi->lgi_buf.lb_len = llh->llh_hdr.lrh_len;
		lgi->lgi_buf.lb_buf = &llh->llh_hdr;
		dt_record_write(env, o, &lgi->lgi_buf, &lgi->lgi_off, th);
	}

	RETURN(rc);
}
Пример #22
0
static int llog_print_cb(const struct lu_env *env, struct llog_handle *handle,
			 struct llog_rec_hdr *rec, void *data)
{
	struct obd_ioctl_data *ioc_data = (struct obd_ioctl_data *)data;
	static int l, remains, from, to;
	static char *out;
	char *endp;
	int cur_index;

	if (ioc_data != NULL && ioc_data->ioc_inllen1 > 0) {
		l = 0;
		remains = ioc_data->ioc_inllen4 +
			cfs_size_round(ioc_data->ioc_inllen1) +
			cfs_size_round(ioc_data->ioc_inllen2) +
			cfs_size_round(ioc_data->ioc_inllen3);
		from = simple_strtol(ioc_data->ioc_inlbuf2, &endp, 0);
		if (*endp != '\0')
			return -EINVAL;
		to = simple_strtol(ioc_data->ioc_inlbuf3, &endp, 0);
		if (*endp != '\0')
			return -EINVAL;
		out = ioc_data->ioc_bulk;
		ioc_data->ioc_inllen1 = 0;
	}

	cur_index = rec->lrh_index;
	if (cur_index < from)
		return 0;
	if (to > 0 && cur_index > to)
		return -LLOG_EEMPTY;

	if (handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT) {
		struct llog_logid_rec *lir = (struct llog_logid_rec *)rec;

		if (rec->lrh_type != LLOG_LOGID_MAGIC) {
			CERROR("invalid record in catalog\n");
			return -EINVAL;
		}

		l = snprintf(out, remains,
			     "[index]: %05d  [logid]: #"DOSTID"#%08x\n",
			     cur_index, POSTID(&lir->lid_id.lgl_oi),
			     lir->lid_id.lgl_ogen);
	} else if (rec->lrh_type == OBD_CFG_REC) {
		int rc;

		rc = class_config_parse_rec(rec, out, remains);
		if (rc < 0)
			return rc;
		l = rc;
	} else {
		l = snprintf(out, remains,
			     "[index]: %05d  [type]: %02x  [len]: %04d\n",
			     cur_index, rec->lrh_type, rec->lrh_len);
	}
	out += l;
	remains -= l;
	if (remains <= 0) {
		CERROR("not enough space for print log records\n");
		return -LLOG_EEMPTY;
	}

	return 0;
}
Пример #23
0
int llog_ioctl(const struct lu_env *env, struct llog_ctxt *ctxt, int cmd,
	       struct obd_ioctl_data *data)
{
	struct llog_logid	 logid;
	int			 rc = 0;
	struct llog_handle	*handle = NULL;

	if (*data->ioc_inlbuf1 == '#') {
		rc = str2logid(&logid, data->ioc_inlbuf1, data->ioc_inllen1);
		if (rc)
			return rc;
		rc = llog_open(env, ctxt, &handle, &logid, NULL,
			       LLOG_OPEN_EXISTS);
		if (rc)
			return rc;
	} else if (*data->ioc_inlbuf1 == '$') {
		char *name = data->ioc_inlbuf1 + 1;

		rc = llog_open(env, ctxt, &handle, NULL, name,
			       LLOG_OPEN_EXISTS);
		if (rc)
			return rc;
	} else {
		return -EINVAL;
	}

	rc = llog_init_handle(env, handle, 0, NULL);
	if (rc)
		GOTO(out_close, rc = -ENOENT);

	switch (cmd) {
	case OBD_IOC_LLOG_INFO: {
		int	 l;
		int	 remains = data->ioc_inllen2 +
				   cfs_size_round(data->ioc_inllen1);
		char	*out = data->ioc_bulk;

		l = snprintf(out, remains,
			     "logid:	    #"DOSTID"#%08x\n"
			     "flags:	    %x (%s)\n"
			     "records count:    %d\n"
			     "last index:       %d\n",
			     POSTID(&handle->lgh_id.lgl_oi),
			     handle->lgh_id.lgl_ogen,
			     handle->lgh_hdr->llh_flags,
			     handle->lgh_hdr->llh_flags &
			     LLOG_F_IS_CAT ? "cat" : "plain",
			     handle->lgh_hdr->llh_count,
			     handle->lgh_last_idx);
		out += l;
		remains -= l;
		if (remains <= 0) {
			CERROR("%s: not enough space for log header info\n",
			       ctxt->loc_obd->obd_name);
			rc = -ENOSPC;
		}
		break;
	}
	case OBD_IOC_LLOG_CHECK:
		LASSERT(data->ioc_inllen1 > 0);
		rc = llog_process(env, handle, llog_check_cb, data, NULL);
		if (rc == -LLOG_EEMPTY)
			rc = 0;
		else if (rc)
			GOTO(out_close, rc);
		break;
	case OBD_IOC_LLOG_PRINT:
		LASSERT(data->ioc_inllen1 > 0);
		rc = llog_process(env, handle, llog_print_cb, data, NULL);
		if (rc == -LLOG_EEMPTY)
			rc = 0;
		else if (rc)
			GOTO(out_close, rc);
		break;
	case OBD_IOC_LLOG_CANCEL: {
		struct llog_cookie cookie;
		struct llog_logid plain;
		char *endp;

		cookie.lgc_index = simple_strtoul(data->ioc_inlbuf3, &endp, 0);
		if (*endp != '\0')
			GOTO(out_close, rc = -EINVAL);

		if (handle->lgh_hdr->llh_flags & LLOG_F_IS_PLAIN) {
			rc = llog_cancel_rec(NULL, handle, cookie.lgc_index);
			GOTO(out_close, rc);
		} else if (!(handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT)) {
			GOTO(out_close, rc = -EINVAL);
		}

		if (data->ioc_inlbuf2 == NULL) /* catalog but no logid */
			GOTO(out_close, rc = -ENOTTY);

		rc = str2logid(&plain, data->ioc_inlbuf2, data->ioc_inllen2);
		if (rc)
			GOTO(out_close, rc);
		cookie.lgc_lgl = plain;
		rc = llog_cat_cancel_records(env, handle, 1, &cookie);
		if (rc)
			GOTO(out_close, rc);
		break;
	}
	case OBD_IOC_LLOG_REMOVE: {
		struct llog_logid plain;

		if (handle->lgh_hdr->llh_flags & LLOG_F_IS_PLAIN) {
			rc = llog_destroy(env, handle);
			GOTO(out_close, rc);
		} else if (!(handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT)) {
			GOTO(out_close, rc = -EINVAL);
		}

		if (data->ioc_inlbuf2 > 0) {
			/* remove indicate log from the catalog */
			rc = str2logid(&plain, data->ioc_inlbuf2,
				       data->ioc_inllen2);
			if (rc)
				GOTO(out_close, rc);
			rc = llog_remove_log(env, handle, &plain);
		} else {
			/* remove all the log of the catalog */
			rc = llog_process(env, handle, llog_delete_cb, NULL,
					  NULL);
			if (rc)
				GOTO(out_close, rc);
		}
		break;
	}
	default:
		CERROR("%s: Unknown ioctl cmd %#x\n",
		       ctxt->loc_obd->obd_name, cmd);
		GOTO(out_close, rc = -ENOTTY);
	}

out_close:
	if (handle->lgh_hdr &&
	    handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT)
		llog_cat_close(env, handle);
	else
		llog_close(env, handle);
	return rc;
}
Пример #24
0
/* Pack LOV object metadata for disk storage.  It is packed in LE byte
 * order and is opaque to the networking layer.
 *
 * XXX In the future, this will be enhanced to get the EA size from the
 *     underlying OSC device(s) to get their EA sizes so we can stack
 *     LOVs properly.  For now lov_mds_md_size() just assumes one obd_id
 *     per stripe.
 */
int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmmp,
	       struct lov_stripe_md *lsm)
{
	struct obd_device *obd = class_exp2obd(exp);
	struct lov_obd *lov = &obd->u.lov;
	struct lov_mds_md_v1 *lmmv1;
	struct lov_mds_md_v3 *lmmv3;
	__u16 stripe_count;
	struct lov_ost_data_v1 *lmm_objects;
	int lmm_size, lmm_magic;
	int i;
	int cplen = 0;

	if (lsm) {
		lmm_magic = lsm->lsm_magic;
	} else {
		if (lmmp && *lmmp)
			lmm_magic = le32_to_cpu((*lmmp)->lmm_magic);
		else
			/* lsm == NULL and lmmp == NULL */
			lmm_magic = LOV_MAGIC;
	}

	if ((lmm_magic != LOV_MAGIC_V1) &&
	    (lmm_magic != LOV_MAGIC_V3)) {
		CERROR("bad mem LOV MAGIC: 0x%08X != 0x%08X nor 0x%08X\n",
			lmm_magic, LOV_MAGIC_V1, LOV_MAGIC_V3);
		return -EINVAL;

	}

	if (lsm) {
		/* If we are just sizing the EA, limit the stripe count
		 * to the actual number of OSTs in this filesystem. */
		if (!lmmp) {
			stripe_count = lov_get_stripecnt(lov, lmm_magic,
							lsm->lsm_stripe_count);
			lsm->lsm_stripe_count = stripe_count;
		} else if (!lsm_is_released(lsm)) {
			stripe_count = lsm->lsm_stripe_count;
		} else {
			stripe_count = 0;
		}
	} else {
		/* No need to allocate more than maximum supported stripes.
		 * Anyway, this is pretty inaccurate since ld_tgt_count now
		 * represents max index and we should rely on the actual number
		 * of OSTs instead */
		stripe_count = lov_mds_md_max_stripe_count(
			lov->lov_ocd.ocd_max_easize, lmm_magic);

		if (stripe_count > lov->desc.ld_tgt_count)
			stripe_count = lov->desc.ld_tgt_count;
	}

	/* XXX LOV STACKING call into osc for sizes */
	lmm_size = lov_mds_md_size(stripe_count, lmm_magic);

	if (!lmmp)
		return lmm_size;

	if (*lmmp && !lsm) {
		stripe_count = le16_to_cpu((*lmmp)->lmm_stripe_count);
		lmm_size = lov_mds_md_size(stripe_count, lmm_magic);
		OBD_FREE_LARGE(*lmmp, lmm_size);
		*lmmp = NULL;
		return 0;
	}

	if (!*lmmp) {
		OBD_ALLOC_LARGE(*lmmp, lmm_size);
		if (!*lmmp)
			return -ENOMEM;
	}

	CDEBUG(D_INFO, "lov_packmd: LOV_MAGIC 0x%08X, lmm_size = %d \n",
	       lmm_magic, lmm_size);

	lmmv1 = *lmmp;
	lmmv3 = (struct lov_mds_md_v3 *)*lmmp;
	if (lmm_magic == LOV_MAGIC_V3)
		lmmv3->lmm_magic = cpu_to_le32(LOV_MAGIC_V3);
	else
		lmmv1->lmm_magic = cpu_to_le32(LOV_MAGIC_V1);

	if (!lsm)
		return lmm_size;

	/* lmmv1 and lmmv3 point to the same struct and have the
	 * same first fields
	 */
	lmm_oi_cpu_to_le(&lmmv1->lmm_oi, &lsm->lsm_oi);
	lmmv1->lmm_stripe_size = cpu_to_le32(lsm->lsm_stripe_size);
	lmmv1->lmm_stripe_count = cpu_to_le16(stripe_count);
	lmmv1->lmm_pattern = cpu_to_le32(lsm->lsm_pattern);
	lmmv1->lmm_layout_gen = cpu_to_le16(lsm->lsm_layout_gen);
	if (lsm->lsm_magic == LOV_MAGIC_V3) {
		cplen = strlcpy(lmmv3->lmm_pool_name, lsm->lsm_pool_name,
				sizeof(lmmv3->lmm_pool_name));
		if (cplen >= sizeof(lmmv3->lmm_pool_name))
			return -E2BIG;
		lmm_objects = lmmv3->lmm_objects;
	} else {
		lmm_objects = lmmv1->lmm_objects;
	}

	for (i = 0; i < stripe_count; i++) {
		struct lov_oinfo *loi = lsm->lsm_oinfo[i];
		/* XXX LOV STACKING call down to osc_packmd() to do packing */
		LASSERTF(ostid_id(&loi->loi_oi) != 0, "lmm_oi "DOSTID
			 " stripe %u/%u idx %u\n", POSTID(&lmmv1->lmm_oi),
			 i, stripe_count, loi->loi_ost_idx);
		ostid_cpu_to_le(&loi->loi_oi, &lmm_objects[i].l_ost_oi);
		lmm_objects[i].l_ost_gen = cpu_to_le32(loi->loi_ost_gen);
		lmm_objects[i].l_ost_idx = cpu_to_le32(loi->loi_ost_idx);
	}

	return lmm_size;
}
Пример #25
0
static int llog_check_cb(const struct lu_env *env, struct llog_handle *handle,
			 struct llog_rec_hdr *rec, void *data)
{
	struct obd_ioctl_data *ioc_data = (struct obd_ioctl_data *)data;
	static int l, remains, from, to;
	static char *out;
	char *endp;
	int cur_index, rc = 0;

	if (ioc_data && ioc_data->ioc_inllen1 > 0) {
		l = 0;
		remains = ioc_data->ioc_inllen4 +
			cfs_size_round(ioc_data->ioc_inllen1) +
			cfs_size_round(ioc_data->ioc_inllen2) +
			cfs_size_round(ioc_data->ioc_inllen3);
		from = simple_strtol(ioc_data->ioc_inlbuf2, &endp, 0);
		if (*endp != '\0')
			return -EINVAL;
		to = simple_strtol(ioc_data->ioc_inlbuf3, &endp, 0);
		if (*endp != '\0')
			return -EINVAL;
		ioc_data->ioc_inllen1 = 0;
		out = ioc_data->ioc_bulk;
	}

	cur_index = rec->lrh_index;
	if (cur_index < from)
		return 0;
	if (to > 0 && cur_index > to)
		return -LLOG_EEMPTY;

	if (handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT) {
		struct llog_logid_rec	*lir = (struct llog_logid_rec *)rec;
		struct llog_handle	*loghandle;

		if (rec->lrh_type != LLOG_LOGID_MAGIC) {
			l = snprintf(out, remains, "[index]: %05d  [type]: "
				     "%02x  [len]: %04d failed\n",
				     cur_index, rec->lrh_type,
				     rec->lrh_len);
		}
		if (handle->lgh_ctxt == NULL)
			return -EOPNOTSUPP;
		rc = llog_cat_id2handle(env, handle, &loghandle, &lir->lid_id);
		if (rc) {
			CDEBUG(D_IOCTL, "cannot find log #"DOSTID"#%08x\n",
			       POSTID(&lir->lid_id.lgl_oi),
			       lir->lid_id.lgl_ogen);
			return rc;
		}
		rc = llog_process(env, loghandle, llog_check_cb, NULL, NULL);
		llog_handle_put(loghandle);
	} else {
		bool ok;

		switch (rec->lrh_type) {
		case OST_SZ_REC:
		case MDS_UNLINK_REC:
		case MDS_UNLINK64_REC:
		case MDS_SETATTR64_REC:
		case OBD_CFG_REC:
		case LLOG_GEN_REC:
		case LLOG_HDR_MAGIC:
			ok = true;
			break;
		default:
			ok = false;
		}

		l = snprintf(out, remains, "[index]: %05d  [type]: "
			     "%02x  [len]: %04d %s\n",
			     cur_index, rec->lrh_type, rec->lrh_len,
			     ok ? "ok" : "failed");
		out += l;
		remains -= l;
		if (remains <= 0) {
			CERROR("%s: no space to print log records\n",
			       handle->lgh_ctxt->loc_obd->obd_name);
			return -LLOG_EEMPTY;
		}
	}
	return rc;
}
Пример #26
0
/** Merge the lock value block(&lvb) attributes and KMS from each of the
 * stripes in a file into a single lvb. It is expected that the caller
 * initializes the current atime, mtime, ctime to avoid regressing a more
 * uptodate time on the local client.
 */
int lov_merge_lvb_kms(struct lov_stripe_md *lsm,
		      struct ost_lvb *lvb, __u64 *kms_place)
{
	__u64 size = 0;
	__u64 kms = 0;
	__u64 blocks = 0;
	s64 current_mtime = lvb->lvb_mtime;
	s64 current_atime = lvb->lvb_atime;
	s64 current_ctime = lvb->lvb_ctime;
	int i;
	int rc = 0;

	assert_spin_locked(&lsm->lsm_lock);
	LASSERT(lsm->lsm_lock_owner == current_pid());

	CDEBUG(D_INODE, "MDT ID "DOSTID" initial value: s=%llu m=%llu a=%llu c=%llu b=%llu\n",
	       POSTID(&lsm->lsm_oi), lvb->lvb_size, lvb->lvb_mtime,
	       lvb->lvb_atime, lvb->lvb_ctime, lvb->lvb_blocks);
	for (i = 0; i < lsm->lsm_stripe_count; i++) {
		struct lov_oinfo *loi = lsm->lsm_oinfo[i];
		u64 lov_size, tmpsize;

		if (OST_LVB_IS_ERR(loi->loi_lvb.lvb_blocks)) {
			rc = OST_LVB_GET_ERR(loi->loi_lvb.lvb_blocks);
			continue;
		}

		tmpsize = loi->loi_kms;
		lov_size = lov_stripe_size(lsm, tmpsize, i);
		if (lov_size > kms)
			kms = lov_size;

		if (loi->loi_lvb.lvb_size > tmpsize)
			tmpsize = loi->loi_lvb.lvb_size;

		lov_size = lov_stripe_size(lsm, tmpsize, i);
		if (lov_size > size)
			size = lov_size;
		/* merge blocks, mtime, atime */
		blocks += loi->loi_lvb.lvb_blocks;
		if (loi->loi_lvb.lvb_mtime > current_mtime)
			current_mtime = loi->loi_lvb.lvb_mtime;
		if (loi->loi_lvb.lvb_atime > current_atime)
			current_atime = loi->loi_lvb.lvb_atime;
		if (loi->loi_lvb.lvb_ctime > current_ctime)
			current_ctime = loi->loi_lvb.lvb_ctime;

		CDEBUG(D_INODE, "MDT ID "DOSTID" on OST[%u]: s=%llu m=%llu a=%llu c=%llu b=%llu\n",
		       POSTID(&lsm->lsm_oi), loi->loi_ost_idx,
		       loi->loi_lvb.lvb_size, loi->loi_lvb.lvb_mtime,
		       loi->loi_lvb.lvb_atime, loi->loi_lvb.lvb_ctime,
		       loi->loi_lvb.lvb_blocks);
	}

	*kms_place = kms;
	lvb->lvb_size = size;
	lvb->lvb_blocks = blocks;
	lvb->lvb_mtime = current_mtime;
	lvb->lvb_atime = current_atime;
	lvb->lvb_ctime = current_ctime;
	return rc;
}
Пример #27
0
/**
 * Prepare bulk IO requests for processing.
 *
 * This function does initial checks of IO and calls corresponding
 * functions for read/write processing.
 *
 * \param[in] env	execution environment
 * \param[in] cmd	IO type (read/write)
 * \param[in] exp	OBD export of client
 * \param[in] oa	OBDO structure from request
 * \param[in] objcount	always 1
 * \param[in] obj	object data
 * \param[in] rnb	remote buffers
 * \param[in] nr_local	number of local buffers
 * \param[in] lnb	local buffers
 *
 * \retval		0 on successful prepare
 * \retval		negative value on error
 */
int ofd_preprw(const struct lu_env *env, int cmd, struct obd_export *exp,
	       struct obdo *oa, int objcount, struct obd_ioobj *obj,
	       struct niobuf_remote *rnb, int *nr_local,
	       struct niobuf_local *lnb)
{
	struct tgt_session_info	*tsi = tgt_ses_info(env);
	struct ofd_device	*ofd = ofd_exp(exp);
	struct ofd_thread_info	*info;
	char			*jobid;
	const struct lu_fid	*fid = &oa->o_oi.oi_fid;
	int			 rc = 0;

	if (*nr_local > PTLRPC_MAX_BRW_PAGES) {
		CERROR("%s: bulk has too many pages %d, which exceeds the"
		       "maximum pages per RPC of %d\n",
		       exp->exp_obd->obd_name, *nr_local, PTLRPC_MAX_BRW_PAGES);
		RETURN(-EPROTO);
	}

	if (tgt_ses_req(tsi) == NULL) { /* echo client case */
		info = ofd_info_init(env, exp);
		jobid = NULL;
	} else {
		info = tsi2ofd_info(tsi);
		jobid = tsi->tsi_jobid;
	}

	LASSERT(oa != NULL);

	if (OBD_FAIL_CHECK(OBD_FAIL_SRV_ENOENT)) {
		struct ofd_seq		*oseq;

		oseq = ofd_seq_load(env, ofd, ostid_seq(&oa->o_oi));
		if (IS_ERR(oseq)) {
			CERROR("%s: Can not find seq for "DOSTID
			       ": rc = %ld\n", ofd_name(ofd), POSTID(&oa->o_oi),
			       PTR_ERR(oseq));
			RETURN(-EINVAL);
		}

		if (oseq->os_destroys_in_progress == 0) {
			/* don't fail lookups for orphan recovery, it causes
			 * later LBUGs when objects still exist during
			 * precreate */
			ofd_seq_put(env, oseq);
			RETURN(-ENOENT);
		}
		ofd_seq_put(env, oseq);
	}

	LASSERT(objcount == 1);
	LASSERT(obj->ioo_bufcnt > 0);

	if (cmd == OBD_BRW_WRITE) {
		la_from_obdo(&info->fti_attr, oa, OBD_MD_FLGETATTR);
		rc = ofd_preprw_write(env, exp, ofd, fid, &info->fti_attr, oa,
				      objcount, obj, rnb, nr_local, lnb, jobid);
	} else if (cmd == OBD_BRW_READ) {
		ofd_grant_prepare_read(env, exp, oa);
		rc = ofd_preprw_read(env, exp, ofd, fid, &info->fti_attr, oa,
				     obj->ioo_bufcnt, rnb, nr_local, lnb,
				     jobid);
		obdo_from_la(oa, &info->fti_attr, LA_ATIME);
	} else {
		CERROR("%s: wrong cmd %d received!\n",
		       exp->exp_obd->obd_name, cmd);
		rc = -EPROTO;
	}
	RETURN(rc);
}
Пример #28
0
/**
 * Prepare buffers for write request processing.
 *
 * This function converts remote buffers from client to local buffers
 * and prepares the latter. If there is recovery in progress and required
 * object is missing then it can be re-created before write.
 *
 * \param[in] env	execution environment
 * \param[in] exp	OBD export of client
 * \param[in] ofd	OFD device
 * \param[in] fid	FID of object
 * \param[in] la	object attributes
 * \param[in] oa	OBDO structure from client
 * \param[in] objcount	always 1
 * \param[in] obj	object data
 * \param[in] rnb	remote buffers
 * \param[in] nr_local	number of local buffers
 * \param[in] lnb	local buffers
 * \param[in] jobid	job ID name
 *
 * \retval		0 on successful prepare
 * \retval		negative value on error
 */
static int ofd_preprw_write(const struct lu_env *env, struct obd_export *exp,
			    struct ofd_device *ofd, const struct lu_fid *fid,
			    struct lu_attr *la, struct obdo *oa,
			    int objcount, struct obd_ioobj *obj,
			    struct niobuf_remote *rnb, int *nr_local,
			    struct niobuf_local *lnb, char *jobid)
{
	struct ofd_object	*fo;
	int			 i, j, k, rc = 0, tot_bytes = 0;

	ENTRY;
	LASSERT(env != NULL);
	LASSERT(objcount == 1);

	if (unlikely(exp->exp_obd->obd_recovering)) {
		u64 seq = fid_seq(fid);
		u64 oid = fid_oid(fid);
		struct ofd_seq *oseq;

		oseq = ofd_seq_load(env, ofd, seq);
		if (IS_ERR(oseq)) {
			CERROR("%s: Can't find FID Sequence "LPX64": rc = %d\n",
			       ofd_name(ofd), seq, (int)PTR_ERR(oseq));
			GOTO(out, rc = -EINVAL);
		}

		if (oid > ofd_seq_last_oid(oseq)) {
			int sync = 0;
			int diff;

			mutex_lock(&oseq->os_create_lock);
			diff = oid - ofd_seq_last_oid(oseq);

			/* Do sync create if the seq is about to used up */
			if (fid_seq_is_idif(seq) || fid_seq_is_mdt0(seq)) {
				if (unlikely(oid >= IDIF_MAX_OID - 1))
					sync = 1;
			} else if (fid_seq_is_norm(seq)) {
				if (unlikely(oid >=
					     LUSTRE_DATA_SEQ_MAX_WIDTH - 1))
					sync = 1;
			} else {
				CERROR("%s : invalid o_seq "DOSTID"\n",
				       ofd_name(ofd), POSTID(&oa->o_oi));
				mutex_unlock(&oseq->os_create_lock);
				ofd_seq_put(env, oseq);
				GOTO(out, rc = -EINVAL);
			}

			while (diff > 0) {
				u64 next_id = ofd_seq_last_oid(oseq) + 1;
				int count = ofd_precreate_batch(ofd, diff);

				rc = ofd_precreate_objects(env, ofd, next_id,
							   oseq, count, sync);
				if (rc < 0) {
					mutex_unlock(&oseq->os_create_lock);
					ofd_seq_put(env, oseq);
					GOTO(out, rc);
				}

				diff -= rc;
			}

			mutex_unlock(&oseq->os_create_lock);
		}

		ofd_seq_put(env, oseq);
	}

	fo = ofd_object_find(env, ofd, fid);
	if (IS_ERR(fo))
		GOTO(out, rc = PTR_ERR(fo));
	LASSERT(fo != NULL);

	ofd_read_lock(env, fo);
	if (!ofd_object_exists(fo)) {
		CERROR("%s: BRW to missing obj "DOSTID"\n",
		       exp->exp_obd->obd_name, POSTID(&obj->ioo_oid));
		ofd_read_unlock(env, fo);
		ofd_object_put(env, fo);
		GOTO(out, rc = -ENOENT);
	}

	if (ofd->ofd_lfsck_verify_pfid && oa->o_valid & OBD_MD_FLFID) {
		rc = ofd_verify_ff(env, fo, oa);
		if (rc != 0) {
			ofd_read_unlock(env, fo);
			ofd_object_put(env, fo);
			GOTO(out, rc);
		}
	}

	/* Process incoming grant info, set OBD_BRW_GRANTED flag and grant some
	 * space back if possible */
	ofd_grant_prepare_write(env, exp, oa, rnb, obj->ioo_bufcnt);

	/* parse remote buffers to local buffers and prepare the latter */
	*nr_local = 0;
	for (i = 0, j = 0; i < obj->ioo_bufcnt; i++) {
		rc = dt_bufs_get(env, ofd_object_child(fo),
				 rnb + i, lnb + j, 1);
		if (unlikely(rc < 0))
			GOTO(err, rc);
		LASSERT(rc <= PTLRPC_MAX_BRW_PAGES);
		/* correct index for local buffers to continue with */
		for (k = 0; k < rc; k++) {
			lnb[j+k].lnb_flags = rnb[i].rnb_flags;
			if (!(rnb[i].rnb_flags & OBD_BRW_GRANTED))
				lnb[j+k].lnb_rc = -ENOSPC;
		}
		j += rc;
		*nr_local += rc;
		LASSERT(j <= PTLRPC_MAX_BRW_PAGES);
		tot_bytes += rnb[i].rnb_len;
	}
	LASSERT(*nr_local > 0 && *nr_local <= PTLRPC_MAX_BRW_PAGES);

	rc = dt_write_prep(env, ofd_object_child(fo), lnb, *nr_local);
	if (unlikely(rc != 0))
		GOTO(err, rc);

	ofd_counter_incr(exp, LPROC_OFD_STATS_WRITE, jobid, tot_bytes);
	RETURN(0);
err:
	dt_bufs_put(env, ofd_object_child(fo), lnb, *nr_local);
	ofd_read_unlock(env, fo);
	ofd_object_put(env, fo);
	/* ofd_grant_prepare_write() was called, so we must commit */
	ofd_grant_commit(exp, oa->o_grant_used, rc);
out:
	/* let's still process incoming grant information packed in the oa,
	 * but without enforcing grant since we won't proceed with the write.
	 * Just like a read request actually. */
	ofd_grant_prepare_read(env, exp, oa);
	return rc;
}
Пример #29
0
static int lov_init_sub(const struct lu_env *env, struct lov_object *lov,
			struct cl_object *stripe, struct lov_layout_raid0 *r0,
			int idx)
{
	struct cl_object_header *hdr;
	struct cl_object_header *subhdr;
	struct cl_object_header *parent;
	struct lov_oinfo	*oinfo;
	int result;

	if (OBD_FAIL_CHECK(OBD_FAIL_LOV_INIT)) {
		/* For sanity:test_206.
		 * Do not leave the object in cache to avoid accessing
		 * freed memory. This is because osc_object is referring to
		 * lov_oinfo of lsm_stripe_data which will be freed due to
		 * this failure. */
		cl_object_kill(env, stripe);
		cl_object_put(env, stripe);
		return -EIO;
	}

	hdr    = cl_object_header(lov2cl(lov));
	subhdr = cl_object_header(stripe);

	oinfo = lov->lo_lsm->lsm_oinfo[idx];
	CDEBUG(D_INODE, DFID"@%p[%d] -> "DFID"@%p: ostid: "DOSTID
	       " idx: %d gen: %d\n",
	       PFID(&subhdr->coh_lu.loh_fid), subhdr, idx,
	       PFID(&hdr->coh_lu.loh_fid), hdr, POSTID(&oinfo->loi_oi),
	       oinfo->loi_ost_idx, oinfo->loi_ost_gen);

	/* reuse ->coh_attr_guard to protect coh_parent change */
	spin_lock(&subhdr->coh_attr_guard);
	parent = subhdr->coh_parent;
	if (parent == NULL) {
		subhdr->coh_parent = hdr;
		spin_unlock(&subhdr->coh_attr_guard);
		subhdr->coh_nesting = hdr->coh_nesting + 1;
		lu_object_ref_add(&stripe->co_lu, "lov-parent", lov);
		r0->lo_sub[idx] = cl2lovsub(stripe);
		r0->lo_sub[idx]->lso_super = lov;
		r0->lo_sub[idx]->lso_index = idx;
		result = 0;
	} else {
		struct lu_object  *old_obj;
		struct lov_object *old_lov;
		unsigned int mask = D_INODE;

		spin_unlock(&subhdr->coh_attr_guard);
		old_obj = lu_object_locate(&parent->coh_lu, &lov_device_type);
		LASSERT(old_obj != NULL);
		old_lov = cl2lov(lu2cl(old_obj));
		if (old_lov->lo_layout_invalid) {
			/* the object's layout has already changed but isn't
			 * refreshed */
			lu_object_unhash(env, &stripe->co_lu);
			result = -EAGAIN;
		} else {
			mask = D_ERROR;
			result = -EIO;
		}

		LU_OBJECT_DEBUG(mask, env, &stripe->co_lu,
				"stripe %d is already owned.\n", idx);
		LU_OBJECT_DEBUG(mask, env, old_obj, "owned.\n");
		LU_OBJECT_HEADER(mask, env, lov2lu(lov), "try to own.\n");
		cl_object_put(env, stripe);
	}
	return result;
}
Пример #30
0
static void print_logid(struct llog_logid_rec *lid)
{
	printf("ogen=%X name="DOSTID"\n",
		lid->lid_id.lgl_ogen,
		POSTID(&lid->lid_id.lgl_oi));
}