Ejemplo n.º 1
0
void linkea_entry_unpack(const struct link_ea_entry *lee, int *reclen,
			 struct lu_name *lname, struct lu_fid *pfid)
{
	*reclen = (lee->lee_reclen[0] << 8) | lee->lee_reclen[1];
	memcpy(pfid, &lee->lee_parent_fid, sizeof(*pfid));
	fid_be_to_cpu(pfid, pfid);
	lname->ln_name = lee->lee_name;
	lname->ln_namelen = *reclen - sizeof(struct link_ea_entry);
}
Ejemplo n.º 2
0
/** get (name+parent_id) for an entry
 * \param linkno hardlink index
 * \retval -ENODATA after last link
 * \retval -ERANGE if namelen is too small
 */
int Lustre_GetNameParent(const char *path, int linkno,
                         lustre_fid *pfid, char *name,
                         int namelen)
{
    int rc, i, len;
    char buf[4096];
    struct linkea_data     ldata      = { 0 };
    struct lu_buf          lb = { 0 };

    rc = lgetxattr(path, XATTR_NAME_LINK, buf, sizeof(buf));
    if (rc < 0)
        return -errno;

    lb.lb_buf = buf;
    lb.lb_len = sizeof(buf);
    ldata.ld_buf = &lb;
    ldata.ld_leh = (struct link_ea_header *)buf;

    ldata.ld_lee = LINKEA_FIRST_ENTRY(ldata);
    ldata.ld_reclen = (ldata.ld_lee->lee_reclen[0] << 8)
               | ldata.ld_lee->lee_reclen[1];

    if (linkno >= ldata.ld_leh->leh_reccount)
        /* beyond last link */
        return -ENODATA;

    for (i = 0; i < linkno; i++) {
        ldata.ld_lee = LINKEA_NEXT_ENTRY(ldata);
        ldata.ld_reclen = (ldata.ld_lee->lee_reclen[0] << 8)
                   | ldata.ld_lee->lee_reclen[1];
    }

    memcpy(pfid, &ldata.ld_lee->lee_parent_fid, sizeof(*pfid));
    fid_be_to_cpu(pfid, pfid);

    if (!fid_is_sane(pfid))
    {
        DisplayLog(LVL_MAJOR, __func__, "insane fid: "DFID, PFID(pfid));
        return -EPROTO;
    }

    len = ldata.ld_reclen - sizeof(struct link_ea_entry);
    if (len >= namelen)
        return -ERANGE;

    strncpy(name, ldata.ld_lee->lee_name, len);
    name[len] = '\0';
    return 0;
}
Ejemplo n.º 3
0
static int osd_find_parent_fid(const struct lu_env *env, struct dt_object *o,
			       struct lu_fid *fid)
{
	struct link_ea_header  *leh;
	struct link_ea_entry   *lee;
	struct lu_buf		buf;
	int			rc;
	ENTRY;

	buf.lb_buf = osd_oti_get(env)->oti_buf;
	buf.lb_len = sizeof(osd_oti_get(env)->oti_buf);

	rc = osd_xattr_get(env, o, &buf, XATTR_NAME_LINK, BYPASS_CAPA);
	if (rc == -ERANGE) {
		rc = osd_xattr_get(env, o, &LU_BUF_NULL,
				   XATTR_NAME_LINK, BYPASS_CAPA);
		if (rc < 0)
			RETURN(rc);
		LASSERT(rc > 0);
		OBD_ALLOC(buf.lb_buf, rc);
		if (buf.lb_buf == NULL)
			RETURN(-ENOMEM);
		buf.lb_len = rc;
		rc = osd_xattr_get(env, o, &buf, XATTR_NAME_LINK, BYPASS_CAPA);
	}
	if (rc < 0)
		GOTO(out, rc);
	if (rc < sizeof(*leh) + sizeof(*lee))
		GOTO(out, rc = -EINVAL);

	leh = buf.lb_buf;
	if (leh->leh_magic == __swab32(LINK_EA_MAGIC)) {
		leh->leh_magic = LINK_EA_MAGIC;
		leh->leh_reccount = __swab32(leh->leh_reccount);
		leh->leh_len = __swab64(leh->leh_len);
	}
	if (leh->leh_magic != LINK_EA_MAGIC)
		GOTO(out, rc = -EINVAL);
	if (leh->leh_reccount == 0)
		GOTO(out, rc = -ENODATA);

	lee = (struct link_ea_entry *)(leh + 1);
	fid_be_to_cpu(fid, (const struct lu_fid *)&lee->lee_parent_fid);
	rc = 0;

out:
	if (buf.lb_buf != osd_oti_get(env)->oti_buf)
		OBD_FREE(buf.lb_buf, buf.lb_len);

#if 0
	/* this block can be enabled for additional verification
	 * it's trying to match FID from LinkEA vs. FID from LMA */
	if (rc == 0) {
		struct lu_fid fid2;
		int rc2;
		rc2 = osd_find_parent_by_dnode(env, o, &fid2);
		if (rc2 == 0)
			if (lu_fid_eq(fid, &fid2) == 0)
				CERROR("wrong parent: "DFID" != "DFID"\n",
				       PFID(fid), PFID(&fid2));
	}
#endif

	/* no LinkEA is found, let's try to find the fid in parent's LMA */
	if (unlikely(rc != 0))
		rc = osd_find_parent_by_dnode(env, o, fid);

	RETURN(rc);
}
Ejemplo n.º 4
0
int decode_linkea(const char *fname)
{
	char buf[BUFFER_SIZE];
	struct link_ea_header *leh;
	ssize_t size;
	struct link_ea_entry *lee;
	int i;
	__u64 length;
	int reclen;
	struct lu_fid pfid;

	size = getxattr(fname, "trusted.link", buf, BUFFER_SIZE);
	if (size < 0) {
		if (errno == ERANGE) {
			fprintf(stderr, "%s: failed to read trusted.link "
				"xattr, the buffer size %u might be too "
				"small\n", fname, BUFFER_SIZE);
		} else {
			fprintf(stderr,
				"%s: failed to read trusted.link xattr: %s\n",
				fname, strerror(errno));
		}
		return -1;
	}

	leh = (struct link_ea_header *)buf;
	if (leh->leh_magic == __swab32(LINK_EA_MAGIC)) {
		leh->leh_magic = LINK_EA_MAGIC;
		leh->leh_reccount = __swab32(leh->leh_reccount);
		leh->leh_len = __swab64(leh->leh_len);
	}
	if (leh->leh_magic != LINK_EA_MAGIC) {
		fprintf(stderr,
			"%s: magic mismatch, expected 0x%lx, got 0x%x\n",
			fname, LINK_EA_MAGIC, leh->leh_magic);
		return -1;
	}
	if (leh->leh_reccount == 0) {
		fprintf(stderr, "%s: empty record count\n", fname);
		return -1;
	}
	if (leh->leh_len > size) {
		fprintf(stderr,
			"%s: invalid length %llu, should smaller than %zd\n",
			fname, leh->leh_len, size);
		return -1;
	}

	length = sizeof(struct link_ea_header);
	lee = (struct link_ea_entry *)(leh + 1);
	printf("%s: count %u\n", fname, leh->leh_reccount);
	for (i = 0; i < leh->leh_reccount; i++) {
		reclen = (lee->lee_reclen[0] << 8) | lee->lee_reclen[1];
		length += reclen;
		if (length > leh->leh_len) {
			fprintf(stderr,
				"%s: length exceeded, expected %lld, got %lld\n",
				fname, leh->leh_len, length);
			return -1;
		}
		memcpy(&pfid, &lee->lee_parent_fid, sizeof(pfid));
		fid_be_to_cpu(&pfid, &pfid);

		printf("    %d: pfid "DFID", name '%s'\n", i, PFID(&pfid),
		       lee->lee_name);
		lee = (struct link_ea_entry *)((char *)lee + reclen);
	}

	if (length != leh->leh_len) {
		fprintf(stderr,
			"%s: length mismatch, expected %lld, got %lld\n",
			fname, leh->leh_len, length);
		return -1;
	}

	return 0;
}
Ejemplo n.º 5
0
static int lfsck_namespace_double_scan_main(void *args)
{
	struct lfsck_thread_args *lta	= args;
	const struct lu_env	*env	= &lta->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;
}