Exemplo n.º 1
0
int ofd_trans_start(const struct lu_env *env, struct ofd_device *ofd,
		    struct ofd_object *obj, struct thandle *th)
{
	struct ofd_thread_info	*info = ofd_info(env);
	int			 rc;

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

	/* declare last_rcvd update */
	rc = dt_declare_record_write(env, ofd->ofd_lut.lut_last_rcvd,
				     sizeof(struct lsd_client_data),
				     info->fti_exp->exp_target_data.ted_lr_off,
				     th);
	if (rc)
		RETURN(rc);

	/* declare last_rcvd header update */
	rc = dt_declare_record_write(env, ofd->ofd_lut.lut_last_rcvd,
				     sizeof(ofd->ofd_lut.lut_lsd), 0, th);
	if (rc)
		RETURN(rc);

	/* version change is required for this object */
	if (obj) {
		ofd_info(env)->fti_obj = obj;
		rc = dt_declare_version_set(env, ofd_object_child(obj), th);
		if (rc)
			RETURN(rc);
	}

	return dt_trans_start(env, ofd->ofd_osd, th);
}
Exemplo n.º 2
0
static int out_trans_start(const struct lu_env *env,
			   struct thandle_exec_args *ta)
{
	/* Always do sync commit for Phase I */
	LASSERT(ta->ta_handle->th_sync != 0);
	return dt_trans_start(env, ta->ta_dev, ta->ta_handle);
}
Exemplo n.º 3
0
static int out_trans_start(const struct lu_env *env, struct dt_device *dt,
			   struct thandle *th)
{
	/* Always do sync commit for Phase I */
	LASSERT(th->th_sync != 0);
	return dt_trans_start(env, dt, th);
}
Exemplo n.º 4
0
/**
 * Start transaction in OFD.
 *
 * This function updates the given \a obj object version and calls
 * dt_trans_start().
 *
 * \param[in] env	execution environment
 * \param[in] ofd	OFD device
 * \param[in] obj	OFD object affected by this transaction
 * \param[in] th	transaction handle
 *
 * \retval		0 if successful
 * \retval		negative value in case of error
 */
int ofd_trans_start(const struct lu_env *env, struct ofd_device *ofd,
		    struct ofd_object *obj, struct thandle *th)
{
	/* version change is required for this object */
	if (obj != NULL)
		tgt_vbr_obj_set(env, ofd_object_child(obj));

	return dt_trans_start(env, ofd->ofd_osd, th);
}
Exemplo n.º 5
0
static int lfsck_update_lma(const struct lu_env *env,
			    struct lfsck_instance *lfsck, struct dt_object *obj)
{
	struct lfsck_thread_info	*info	= lfsck_env_info(env);
	struct lfsck_bookmark		*bk	= &lfsck->li_bookmark_ram;
	struct dt_device		*dt	= lfsck->li_bottom;
	struct lustre_mdt_attrs 	*lma	= &info->lti_lma;
	struct lu_buf			*buf;
	struct thandle			*th;
	int				 fl;
	int				 rc;
	ENTRY;

	if (bk->lb_param & LPF_DRYRUN)
		RETURN(0);

	buf = lfsck_buf_get(env, info->lti_lma_old, LMA_OLD_SIZE);
	rc = dt_xattr_get(env, obj, buf, XATTR_NAME_LMA, BYPASS_CAPA);
	if (rc < 0) {
		if (rc != -ENODATA)
			RETURN(rc);

		fl = LU_XATTR_CREATE;
		lustre_lma_init(lma, lfsck_dto2fid(obj), LMAC_FID_ON_OST, 0);
	} else {
		if (rc != LMA_OLD_SIZE && rc != sizeof(struct lustre_mdt_attrs))
			RETURN(-EINVAL);

		fl = LU_XATTR_REPLACE;
		lustre_lma_swab(lma);
		lustre_lma_init(lma, lfsck_dto2fid(obj),
				lma->lma_compat | LMAC_FID_ON_OST,
				lma->lma_incompat);
	}
	lustre_lma_swab(lma);

	th = dt_trans_create(env, dt);
	if (IS_ERR(th))
		RETURN(PTR_ERR(th));

	buf = lfsck_buf_get(env, lma, sizeof(*lma));
	rc = dt_declare_xattr_set(env, obj, buf, XATTR_NAME_LMA, fl, th);
	if (rc != 0)
		GOTO(stop, rc);

	rc = dt_trans_start(env, dt, th);
	if (rc != 0)
		GOTO(stop, rc);

	rc = dt_xattr_set(env, obj, buf, XATTR_NAME_LMA, fl, th, BYPASS_CAPA);

	GOTO(stop, rc);

stop:
	dt_trans_stop(env, dt, th);
	return rc;
}
Exemplo n.º 6
0
static int out_trans_start(const struct lu_env *env,
			   struct thandle_exec_args *ta)
{
	return dt_trans_start(env, ta->ta_handle->th_dev, ta->ta_handle);
}
Exemplo n.º 7
0
static int lfsck_namespace_exec_dir(const struct lu_env *env,
				    struct lfsck_component *com,
				    struct dt_object *obj,
				    struct lu_dirent *ent)
{
	struct lfsck_thread_info   *info     = lfsck_env_info(env);
	struct lu_attr		   *la	     = &info->lti_la;
	struct lfsck_instance	   *lfsck    = com->lc_lfsck;
	struct lfsck_bookmark	   *bk	     = &lfsck->li_bookmark_ram;
	struct lfsck_namespace	   *ns	     = com->lc_file_ram;
	struct linkea_data	    ldata    = { 0 };
	const struct lu_fid	   *pfid     = lfsck_dto2fid(lfsck->li_obj_dir);
	const struct lu_fid	   *cfid     = lfsck_dto2fid(obj);
	const struct lu_name	   *cname;
	struct thandle		   *handle   = NULL;
	bool			    repaired = false;
	bool			    locked   = false;
	bool			    remove;
	bool			    newdata;
	int			    count    = 0;
	int			    rc;
	ENTRY;

	cname = lfsck_name_get_const(env, ent->lde_name, ent->lde_namelen);
	down_write(&com->lc_sem);
	com->lc_new_checked++;

	if (ent->lde_attrs & LUDA_UPGRADE) {
		ns->ln_flags |= LF_UPGRADE;
		repaired = true;
	} else if (ent->lde_attrs & LUDA_REPAIR) {
		ns->ln_flags |= LF_INCONSISTENT;
		repaired = true;
	}

	if (ent->lde_name[0] == '.' &&
	    (ent->lde_namelen == 1 ||
	     (ent->lde_namelen == 2 && ent->lde_name[1] == '.') ||
	     fid_is_dot_lustre(&ent->lde_fid)))
		GOTO(out, rc = 0);

	if (!(bk->lb_param & LPF_DRYRUN) &&
	    (com->lc_journal || repaired)) {

again:
		LASSERT(!locked);

		com->lc_journal = 1;
		handle = dt_trans_create(env, lfsck->li_next);
		if (IS_ERR(handle))
			GOTO(out, rc = PTR_ERR(handle));

		rc = lfsck_declare_namespace_exec_dir(env, obj, handle);
		if (rc != 0)
			GOTO(stop, rc);

		rc = dt_trans_start(env, lfsck->li_next, handle);
		if (rc != 0)
			GOTO(stop, rc);

		dt_write_lock(env, obj, MOR_TGT_CHILD);
		locked = true;
	}

	rc = lfsck_namespace_check_exist(env, lfsck, obj, ent->lde_name);
	if (rc != 0)
		GOTO(stop, rc);

	rc = lfsck_links_read(env, obj, &ldata);
	if (rc == 0) {
		count = ldata.ld_leh->leh_reccount;
		rc = linkea_links_find(&ldata, cname, pfid);
		if ((rc == 0) &&
		    (count == 1 || !S_ISDIR(lfsck_object_type(obj))))
			goto record;

		ns->ln_flags |= LF_INCONSISTENT;
		/* For dir, if there are more than one linkea entries, or the
		 * linkea entry does not match the name entry, then remove all
		 * and add the correct one. */
		if (S_ISDIR(lfsck_object_type(obj))) {
			remove = true;
			newdata = true;
		} else {
			remove = false;
			newdata = false;
		}
		goto nodata;
	} else if (unlikely(rc == -EINVAL)) {
		count = 1;
		ns->ln_flags |= LF_INCONSISTENT;
		/* The magic crashed, we are not sure whether there are more
		 * corrupt data in the linkea, so remove all linkea entries. */
		remove = true;
		newdata = true;
		goto nodata;
	} else if (rc == -ENODATA) {
		count = 1;
		ns->ln_flags |= LF_UPGRADE;
		remove = false;
		newdata = true;

nodata:
		if (bk->lb_param & LPF_DRYRUN) {
			repaired = true;
			goto record;
		}

		if (!com->lc_journal)
			goto again;

		if (remove) {
			LASSERT(newdata);

			rc = dt_xattr_del(env, obj, XATTR_NAME_LINK, handle,
					  BYPASS_CAPA);
			if (rc != 0)
				GOTO(stop, rc);
		}

		if (newdata) {
			rc = linkea_data_new(&ldata,
					&lfsck_env_info(env)->lti_linkea_buf);
			if (rc != 0)
				GOTO(stop, rc);
		}

		rc = linkea_add_buf(&ldata, cname, pfid);
		if (rc != 0)
			GOTO(stop, rc);

		rc = lfsck_links_write(env, obj, &ldata, handle);
		if (rc != 0)
			GOTO(stop, rc);

		count = ldata.ld_leh->leh_reccount;
		repaired = true;
	} else {
		GOTO(stop, rc);
	}

record:
	LASSERT(count > 0);

	rc = dt_attr_get(env, obj, la, BYPASS_CAPA);
	if (rc != 0)
		GOTO(stop, rc);

	if ((count == 1) &&
	    (la->la_nlink == 1 || S_ISDIR(lfsck_object_type(obj))))
		/* Usually, it is for single linked object or dir, do nothing.*/
		GOTO(stop, rc);

	/* Following modification will be in another transaction.  */
	if (handle != NULL) {
		LASSERT(dt_write_locked(env, obj));

		dt_write_unlock(env, obj);
		locked = false;

		dt_trans_stop(env, lfsck->li_next, handle);
		handle = NULL;
	}

	ns->ln_mlinked_checked++;
	rc = lfsck_namespace_update(env, com, cfid,
			count != la->la_nlink ? LLF_UNMATCH_NLINKS : 0, false);

	GOTO(out, rc);

stop:
	if (locked)
		dt_write_unlock(env, obj);

	if (handle != NULL)
		dt_trans_stop(env, lfsck->li_next, handle);

out:
	if (rc < 0) {
		ns->ln_items_failed++;
		if (lfsck_pos_is_zero(&ns->ln_pos_first_inconsistent))
			lfsck_pos_fill(env, lfsck,
				       &ns->ln_pos_first_inconsistent, false);
		if (!(bk->lb_param & LPF_FAILOUT))
			rc = 0;
	} else {
		if (repaired) {
			ns->ln_items_repaired++;
			if (bk->lb_param & LPF_DRYRUN &&
			    lfsck_pos_is_zero(&ns->ln_pos_first_inconsistent))
				lfsck_pos_fill(env, lfsck,
					       &ns->ln_pos_first_inconsistent,
					       false);
		} else {
			com->lc_journal = 0;
		}
		rc = 0;
	}
	up_write(&com->lc_sem);
	return rc;
}
Exemplo n.º 8
0
/**
 * \retval +ve	repaired
 * \retval 0	no need to repair
 * \retval -ve	error cases
 */
static int lfsck_namespace_double_scan_one(const struct lu_env *env,
					   struct lfsck_component *com,
					   struct dt_object *child, __u8 flags)
{
	struct lfsck_thread_info *info	  = lfsck_env_info(env);
	struct lu_attr		 *la	  = &info->lti_la;
	struct lu_name		 *cname	  = &info->lti_name;
	struct lu_fid		 *pfid	  = &info->lti_fid;
	struct lu_fid		 *cfid	  = &info->lti_fid2;
	struct lfsck_instance	*lfsck	  = com->lc_lfsck;
	struct lfsck_bookmark	*bk	  = &lfsck->li_bookmark_ram;
	struct lfsck_namespace	*ns	  = com->lc_file_ram;
	struct linkea_data	 ldata	  = { 0 };
	struct thandle		*handle   = NULL;
	bool			 locked   = false;
	bool			 update	  = false;
	int			 rc;
	ENTRY;

	if (com->lc_journal) {

again:
		LASSERT(!locked);

		update = false;
		com->lc_journal = 1;
		handle = dt_trans_create(env, lfsck->li_next);
		if (IS_ERR(handle))
			RETURN(rc = PTR_ERR(handle));

		rc = dt_declare_xattr_set(env, child,
			lfsck_buf_get_const(env, NULL, DEFAULT_LINKEA_SIZE),
			XATTR_NAME_LINK, 0, handle);
		if (rc != 0)
			GOTO(stop, rc);

		rc = dt_trans_start(env, lfsck->li_next, handle);
		if (rc != 0)
			GOTO(stop, rc);

		dt_write_lock(env, child, MOR_TGT_CHILD);
		locked = true;
	}

	if (unlikely(lfsck_is_dead_obj(child)))
		GOTO(stop, rc = 0);

	rc = dt_attr_get(env, child, la, BYPASS_CAPA);
	if (rc == 0)
		rc = lfsck_links_read(env, child, &ldata);
	if (rc != 0) {
		if ((bk->lb_param & LPF_DRYRUN) &&
		    (rc == -EINVAL || rc == -ENODATA))
			rc = 1;

		GOTO(stop, rc);
	}

	linkea_first_entry(&ldata);
	while (ldata.ld_lee != NULL) {
		struct dt_object *parent = NULL;

		rc = lfsck_linkea_entry_unpack(lfsck, &ldata, cname, pfid);
		if (rc > 0)
			update = true;

		if (!fid_is_sane(pfid))
			goto shrink;

		parent = lfsck_object_find(env, lfsck, pfid);
		if (parent == NULL)
			goto shrink;
		else if (IS_ERR(parent))
			GOTO(stop, rc = PTR_ERR(parent));

		if (!dt_object_exists(parent))
			goto shrink;

		/* XXX: Currently, skip remote object, the consistency for
		 *	remote object will be processed in LFSCK phase III. */
		if (dt_object_remote(parent)) {
			lfsck_object_put(env, parent);
			linkea_next_entry(&ldata);
			continue;
		}

		if (unlikely(!dt_try_as_dir(env, parent)))
			goto shrink;

		/* To guarantee the 'name' is terminated with '0'. */
		memcpy(info->lti_key, cname->ln_name, cname->ln_namelen);
		info->lti_key[cname->ln_namelen] = 0;
		cname->ln_name = info->lti_key;
		rc = dt_lookup(env, parent, (struct dt_rec *)cfid,
			       (const struct dt_key *)cname->ln_name,
			       BYPASS_CAPA);
		if (rc != 0 && rc != -ENOENT) {
			lfsck_object_put(env, parent);
			GOTO(stop, rc);
		}

		if (rc == 0) {
			if (lu_fid_eq(cfid, lfsck_dto2fid(child))) {
				lfsck_object_put(env, parent);
				linkea_next_entry(&ldata);
				continue;
			}

			goto shrink;
		}

		/* If there is no name entry in the parent dir and the object
		 * link count is less than the linkea entries count, then the
		 * linkea entry should be removed. */
		if (ldata.ld_leh->leh_reccount > la->la_nlink)
			goto shrink;

		/* XXX: For the case of there is a linkea entry, but without
		 *	name entry pointing to the object and its hard links
		 *	count is not less than the object name entries count,
		 *	then seems we should add the 'missed' name entry back
		 *	to namespace, but before LFSCK phase III finished, we
		 *	do not know whether the object has some inconsistency
		 *	on other MDTs. So now, do NOT add the name entry back
		 *	to the namespace, but keep the linkEA entry. LU-2914 */
		lfsck_object_put(env, parent);
		linkea_next_entry(&ldata);
		continue;

shrink:
		if (parent != NULL)
			lfsck_object_put(env, parent);
		if (bk->lb_param & LPF_DRYRUN)
			RETURN(1);

		CDEBUG(D_LFSCK, "Remove linkEA: "DFID"[%.*s], "DFID"\n",
		       PFID(lfsck_dto2fid(child)), cname->ln_namelen, cname->ln_name,
		       PFID(pfid));
		linkea_del_buf(&ldata, cname);
		update = true;
	}

	if (update) {
		if (!com->lc_journal) {
			com->lc_journal = 1;
			goto again;
		}

		rc = lfsck_links_write(env, child, &ldata, handle);
	}

	GOTO(stop, rc);

stop:
	if (locked) {
	/* XXX: For the case linkea entries count does not match the object hard
	 *	links count, we cannot update the later one simply. Before LFSCK
	 *	phase III finished, we cannot know whether there are some remote
	 *	name entries to be repaired or not. LU-2914 */
		if (rc == 0 && !lfsck_is_dead_obj(child) &&
		    ldata.ld_leh != NULL &&
		    ldata.ld_leh->leh_reccount != la->la_nlink)
			CWARN("%s: the object "DFID" linkEA entry count %u "
			      "may not match its hardlink count %u\n",
			      lfsck_lfsck2name(lfsck), PFID(cfid),
			      ldata.ld_leh->leh_reccount, la->la_nlink);

		dt_write_unlock(env, child);
	}

	if (handle != NULL)
		dt_trans_stop(env, lfsck->li_next, handle);

	if (rc == 0 && update) {
		ns->ln_objs_nlink_repaired++;
		rc = 1;
	}

	return rc;
}