Exemplo n.º 1
0
static void fill_initiator_context(char *subsys, struct boot_context *context)
{
	sysfs_get_str("initiator", subsys, "initiator-name",
		      context->initiatorname,
		      sizeof(context->initiatorname));
	sysfs_get_str("initiator", subsys, "isid", context->isid,
		      sizeof(context->isid));

	strlcpy(context->boot_root, subsys, sizeof(context->boot_root));
}
Exemplo n.º 2
0
/* Not really Monitor but ... */
int Wait(char *dev)
{
	struct stat stb;
	char devnm[32];
	int rv = 1;
	int frozen_remaining = 3;

	if (stat(dev, &stb) != 0) {
		pr_err("Cannot find %s: %s\n", dev,
			strerror(errno));
		return 2;
	}
	strcpy(devnm, stat2devnm(&stb));

	while(1) {
		struct mdstat_ent *ms = mdstat_read(1, 0);
		struct mdstat_ent *e;

		for (e=ms ; e; e=e->next)
			if (strcmp(e->devnm, devnm) == 0)
				break;

		if (e && e->percent == RESYNC_NONE) {
			/* We could be in the brief pause before something
			 * starts. /proc/mdstat doesn't show that, but
			 * sync_action does.
			 */
			struct mdinfo mdi;
			char buf[21];
			sysfs_init(&mdi, -1, devnm);
			if (sysfs_get_str(&mdi, NULL, "sync_action",
					  buf, 20) > 0 &&
			    strcmp(buf,"idle\n") != 0) {
				e->percent = RESYNC_UNKNOWN;
				if (strcmp(buf, "frozen\n") == 0) {
					if (frozen_remaining == 0)
						e->percent = RESYNC_NONE;
					else
						frozen_remaining -= 1;
				}
			}
		}
		if (!e || e->percent == RESYNC_NONE) {
			if (e && e->metadata_version &&
			    strncmp(e->metadata_version, "external:", 9) == 0) {
				if (is_subarray(&e->metadata_version[9]))
					ping_monitor(&e->metadata_version[9]);
				else
					ping_monitor(devnm);
			}
			free_mdstat(ms);
			return rv;
		}
		free_mdstat(ms);
		rv = 0;
		mdstat_wait(5);
	}
}
Exemplo n.º 3
0
static int fill_tgt_context(char *subsys, char *id,
			    struct boot_context *context)
{
	int rc;

	rc = sysfs_get_int(id, subsys, "flags", &context->target_flags);
	/*
	 * Per spec we would need to check against Bit 0
	 * (Block Valid Flag), but some firmware only
	 * sets Bit 1 (Firmware Booting Selected).
	 * So any setting is deemed okay.
	 */
	if (!rc && (context->nic_flags == 0))
		rc = ENODEV;
	if (rc)
		return rc;

	rc = sysfs_get_str(id, subsys, "target-name", context->targetname,
			   sizeof(context->targetname));
	if (rc)
		return rc;

	rc = sysfs_get_str(id, subsys, "ip-addr", context->target_ipaddr,
			   sizeof(context->target_ipaddr));
	if (rc)
		return rc;

	memset(&context->boot_target, 0, sizeof(context->boot_target));
	snprintf(context->boot_target, sizeof(context->boot_target), "%s", id);

	/*
	 * We can live without the rest of they do not exist. If we
	 * failed to get them we will figure it out when we login.
	 */
	if (sysfs_get_int(id, subsys, "port", &context->target_port))
		context->target_port = ISCSI_LISTEN_PORT;

	sysfs_get_str(id, subsys, "lun", context->lun,
		      sizeof(context->lun));
	sysfs_get_str(id, subsys, "chap-name", context->chap_name,
		      sizeof(context->chap_name));
	sysfs_get_str(id, subsys, "chap-secret", context->chap_password,
		      sizeof(context->chap_password));
	sysfs_get_str(id, subsys, "rev-chap-name", context->chap_name_in,
		      sizeof(context->chap_name_in));
	sysfs_get_str(id, subsys, "rev-chap-name-secret",
		      context->chap_password_in,
		      sizeof(context->chap_password_in));
	return 0;
}
Exemplo n.º 4
0
int sysfs_freeze_array(struct mdinfo *sra)
{
    /* Try to freeze resync/rebuild on this array/container.
     * Return -1 if the array is busy,
     * return 0 if this kernel doesn't support 'frozen'
     * return 1 if it worked.
     */
    char buf[20];

    if (!sysfs_attribute_available(sra, NULL, "sync_action"))
        return 1; /* no sync_action == frozen */
    if (sysfs_get_str(sra, NULL, "sync_action", buf, 20) <= 0)
        return 0;
    if (strcmp(buf, "frozen\n") == 0)
        /* Already frozen */
        return 0;
    if (strcmp(buf, "idle\n") != 0 && strcmp(buf, "recover\n") != 0)
        return -1;
    if (sysfs_set_str(sra, NULL, "sync_action", "frozen") < 0)
        return 0;
    return 1;
}
Exemplo n.º 5
0
/*
 * Routines to fill in the context values.
 */
static int fill_nic_context(char *subsys, char *id,
			    struct boot_context *context)
{
	int rc;

	rc = sysfs_get_int(id, subsys, "flags", &context->nic_flags);
	/*
	 * Per spec we would need to check against Bit 0
	 * (Block Valid Flag), but some firmware only
	 * sets Bit 1 (Firmware Booting Selected).
	 * So any setting is deemed okay.
	 */
	if (!rc && (context->nic_flags == 0))
		rc = ENODEV;
	if (rc)
		return rc;

	rc = sysfs_get_str(id, subsys, "mac", context->mac,
			   sizeof(context->mac));
	if (rc)
		return rc;

	/*
	 * Some offload cards like bnx2i use different MACs for the net and
	 * iscsi functions, so we have to follow the sysfs links.
	 *
	 * Other ibft implementations may not be tied to a pci function,
	 * so there will not be any device/net link, so we drop down to
	 * the MAC matching.
	 *
	 * And finally, some cards like be2iscsi and qla4xxx do not have
	 * any linux network subsys representation. These hosts will
	 * not have the ibft subsys. Instead the subsys is the scsi host
	 * number.
	 */
	if (!strcmp(IBFT_SUBSYS, subsys)) {
		rc = get_iface_from_device(id, context);
		if (rc) {
			rc = net_get_netdev_from_hwaddress(context->mac,
							   context->iface);
			if (rc)
				return rc;
		}
	} else
		strlcpy(context->scsi_host_name, subsys,
			sizeof(context->scsi_host_name));

	memset(&context->boot_nic, 0, sizeof(context->boot_nic));
	snprintf(context->boot_nic, sizeof(context->boot_nic), "%s", id);

	sysfs_get_str(id, subsys, "ip-addr", context->ipaddr,
		      sizeof(context->ipaddr));
	sysfs_get_str(id, subsys, "vlan", context->vlan,
		      sizeof(context->vlan));
	sysfs_get_str(id, subsys, "subnet-mask", context->mask,
		      sizeof(context->mask));
	sysfs_get_str(id, subsys, "gateway", context->gateway,
		      sizeof(context->gateway));
	sysfs_get_str(id, subsys, "primary-dns", context->primary_dns,
		      sizeof(context->primary_dns));
	sysfs_get_str(id, subsys, "secondary-dns", context->secondary_dns,
		      sizeof(context->secondary_dns));
	sysfs_get_str(id, subsys, "dhcp", context->dhcp,
		      sizeof(context->dhcp));
	sysfs_get_int(id, subsys, "origin", (int *)&context->origin);
	return 0;
}
Exemplo n.º 6
0
/**
 * block_monitor - prevent mdmon spare assignment
 * @container - container to block
 * @freeze - flag to additionally freeze sync_action
 *
 * This is used by the reshape code to freeze the container, and the
 * auto-rebuild implementation to atomically move spares.
 * In both cases we need to stop mdmon from assigning spares to replace
 * failed devices as we might have other plans for the spare.
 * For the reshape case we also need to 'freeze' sync_action so that
 * no recovery happens until we have fully prepared for the reshape.
 *
 * We tell mdmon that the array is frozen by marking the 'metadata' name
 * with a leading '-'.  The previously told mdmon "Don't make this array
 * read/write, leave it readonly".  Now it means a more general "Don't
 * reconfigure this array at all".
 * As older versions of mdmon (which might run from initrd) don't understand
 * this, we first check that the running mdmon is new enough.
 */
int block_monitor(char *container, const int freeze)
{
	int devnum = devname2devnum(container);
	struct mdstat_ent *ent, *e, *e2;
	struct mdinfo *sra = NULL;
	char *version = NULL;
	char buf[64];
	int rv = 0;

	if (!mdmon_running(devnum)) {
		/* if mdmon is not active we assume that any instance that is
		 * later started will match the current mdadm version, if this
		 * assumption is violated we may inadvertantly rebuild an array
		 * that was meant for reshape, or start rebuild on a spare that
		 * was to be moved to another container
		 */
		/* pass */;
	} else {
		int ver;

		version = ping_monitor_version(container);
		ver = version ? mdadm_version(version) : -1;
		free(version);
		if (ver < 3002000) {
			fprintf(stderr, Name
				": mdmon instance for %s cannot be disabled\n",
				container);
			return -1;
		}
	}

	ent = mdstat_read(0, 0);
	if (!ent) {
		fprintf(stderr, Name
			": failed to read /proc/mdstat while disabling mdmon\n");
		return -1;
	}

	/* freeze container contents */
	for (e = ent; e; e = e->next) {
		if (!is_container_member(e, container))
			continue;
		sysfs_free(sra);
		sra = sysfs_read(-1, e->devnum, GET_VERSION);
		if (!sra) {
			fprintf(stderr, Name
				": failed to read sysfs for subarray%s\n",
				to_subarray(e, container));
			break;
		}
		/* can't reshape an array that we can't monitor */
		if (sra->text_version[0] == '-')
			break;

		if (freeze && sysfs_freeze_array(sra) < 1)
			break;
		/* flag this array to not be modified by mdmon (close race with
		 * takeover in reshape case and spare reassignment in the
		 * auto-rebuild case)
		 */
		if (block_subarray(sra))
			break;
		ping_monitor(container);

		/* check that we did not race with recovery */
		if ((freeze &&
		     !sysfs_attribute_available(sra, NULL, "sync_action")) ||
		    (freeze &&
		     sysfs_attribute_available(sra, NULL, "sync_action") &&
		     sysfs_get_str(sra, NULL, "sync_action", buf, 20) > 0 &&
		     strcmp(buf, "frozen\n") == 0))
			/* pass */;
		else {
			unblock_subarray(sra, 0);
			break;
		}
		/* Double check against races - there should be no spares
		 * or part-spares
		 */
		sysfs_free(sra);
		sra = sysfs_read(-1, e->devnum, GET_DEVS | GET_STATE);
		if (sra && sra->array.spare_disks > 0) {
			unblock_subarray(sra, freeze);
			break;
		}
	}

	if (e) {
		fprintf(stderr, Name ": failed to freeze subarray%s\n",
			to_subarray(e, container));

		/* thaw the partially frozen container */
		for (e2 = ent; e2 && e2 != e; e2 = e2->next) {
			if (!is_container_member(e2, container))
				continue;
			sysfs_free(sra);
			sra = sysfs_read(-1, e2->devnum, GET_VERSION);
			if (unblock_subarray(sra, freeze))
				fprintf(stderr, Name ": Failed to unfreeze %s\n", e2->dev);
		}

		ping_monitor(container); /* cleared frozen */
		rv = -1;
	}

	sysfs_free(sra);
	free_mdstat(ent);

	return rv;
}
Exemplo n.º 7
0
int sysfs_set_array(struct mdinfo *info, int vers)
{
    int rv = 0;
    char ver[100];
    int raid_disks = info->array.raid_disks;

    ver[0] = 0;
    if (info->array.major_version == -1 &&
            info->array.minor_version == -2) {
        char buf[1024];

        strcat(strcpy(ver, "external:"), info->text_version);

        /* meta version might already be set if we are setting
         * new geometry for a reshape.  In that case we don't
         * want to over-write the 'readonly' flag that is
         * stored in the metadata version.  So read the current
         * version first, and preserve the flag
         */
        if (sysfs_get_str(info, NULL, "metadata_version",
                          buf, 1024) > 0)
            if (strlen(buf) >= 9 && buf[9] == '-')
                ver[9] = '-';

        if ((vers % 100) < 2 ||
                sysfs_set_str(info, NULL, "metadata_version",
                              ver) < 0) {
            pr_err("This kernel does not support external metadata.\n");
            return 1;
        }
    }
    if (info->array.level < 0)
        return 0; /* FIXME */
    rv |= sysfs_set_str(info, NULL, "level",
                        map_num(pers, info->array.level));
    if (info->reshape_active && info->delta_disks != UnSet)
        raid_disks -= info->delta_disks;
    rv |= sysfs_set_num(info, NULL, "raid_disks", raid_disks);
    rv |= sysfs_set_num(info, NULL, "chunk_size", info->array.chunk_size);
    rv |= sysfs_set_num(info, NULL, "layout", info->array.layout);
    rv |= sysfs_set_num(info, NULL, "component_size", info->component_size/2);
    if (info->custom_array_size) {
        int rc;

        rc = sysfs_set_num(info, NULL, "array_size",
                           info->custom_array_size/2);
        if (rc && errno == ENOENT) {
            pr_err("This kernel does not have the md/array_size attribute, the array may be larger than expected\n");
            rc = 0;
        }
        rv |= rc;
    }

    if (info->array.level > 0)
        rv |= sysfs_set_num(info, NULL, "resync_start", info->resync_start);

    if (info->reshape_active) {
        rv |= sysfs_set_num(info, NULL, "reshape_position",
                            info->reshape_progress);
        rv |= sysfs_set_num(info, NULL, "chunk_size", info->new_chunk);
        rv |= sysfs_set_num(info, NULL, "layout", info->new_layout);
        rv |= sysfs_set_num(info, NULL, "raid_disks",
                            info->array.raid_disks);
        /* We don't set 'new_level' here.  That can only happen
         * once the reshape completes.
         */
    }
    return rv;
}