示例#1
0
void
identify(int argc, char *argv[])
{
	char	*target;

	if (argc < 2)
		identify_usage();

	while (getopt(argc, argv, "vx") != -1) ;

	/* Check that a controller or namespace was specified. */
	if (optind >= argc)
		identify_usage();

	target = argv[optind];

	optreset = 1;
	optind = 1;

	/*
	 * If device node contains "ns", we consider it a namespace,
	 *  otherwise, consider it a controller.
	 */
	if (strstr(target, NVME_NS_PREFIX) == NULL)
		identify_ctrlr(argc, argv);
	else
		identify_ns(argc, argv);
}
示例#2
0
static void
identify_ctrlr(int argc, char *argv[])
{
	struct nvme_controller_data	cdata;
	int				ch, fd, hexflag = 0, hexlength;
	int				verboseflag = 0;

	while ((ch = getopt(argc, argv, "vx")) != -1) {
		switch ((char)ch) {
		case 'v':
			verboseflag = 1;
			break;
		case 'x':
			hexflag = 1;
			break;
		default:
			identify_usage();
		}
	}

	/* Check that a controller was specified. */
	if (optind >= argc)
		identify_usage();

	open_dev(argv[optind], &fd, 1, 1);
	read_controller_data(fd, &cdata);
	close(fd);

	if (hexflag == 1) {
		if (verboseflag == 1)
			hexlength = sizeof(struct nvme_controller_data);
		else
			hexlength = offsetof(struct nvme_controller_data,
			    reserved5);
		print_hex(&cdata, hexlength);
		exit(0);
	}

	if (verboseflag == 1) {
		fprintf(stderr, "-v not currently supported without -x\n");
		identify_usage();
	}

	print_controller(&cdata);
	exit(0);
}
示例#3
0
static void
identify_ns(int argc, char *argv[])
{
	struct nvme_namespace_data	nsdata;
	char				path[64];
	int				ch, fd, hexflag = 0, hexlength, nsid;
	int				verboseflag = 0;

	while ((ch = getopt(argc, argv, "vx")) != -1) {
		switch ((char)ch) {
		case 'v':
			verboseflag = 1;
			break;
		case 'x':
			hexflag = 1;
			break;
		default:
			identify_usage();
		}
	}

	/* Check that a namespace was specified. */
	if (optind >= argc)
		identify_usage();

	/*
	 * Check if the specified device node exists before continuing.
	 *  This is a cleaner check for cases where the correct controller
	 *  is specified, but an invalid namespace on that controller.
	 */
	open_dev(argv[optind], &fd, 1, 1);
	close(fd);

	/*
	 * We send IDENTIFY commands to the controller, not the namespace,
	 *  since it is an admin cmd.  The namespace ID will be specified in
	 *  the IDENTIFY command itself.  So parse the namespace's device node
	 *  string to get the controller substring and namespace ID.
	 */
	parse_ns_str(argv[optind], path, &nsid);
	open_dev(path, &fd, 1, 1);
	read_namespace_data(fd, nsid, &nsdata);
	close(fd);

	if (hexflag == 1) {
		if (verboseflag == 1)
			hexlength = sizeof(struct nvme_namespace_data);
		else
			hexlength = offsetof(struct nvme_namespace_data,
			    reserved6);
		print_hex(&nsdata, hexlength);
		exit(0);
	}

	if (verboseflag == 1) {
		fprintf(stderr, "-v not currently supported without -x\n");
		identify_usage();
	}

	print_namespace(&nsdata);
	exit(0);
}
示例#4
0
void ot_recover(void *nvm_start) {
    int i=0;
    uint16_t n;
    uint64_t current_slot = 0;
    uint64_t last_used_slot = 0;
    nvm_chunk_header_t *chunk_hdr = (nvm_chunk_header_t*) first_chunk;
    nvm_object_table_entry_t *nvm_entry = NULL;
    object_table_entry_t *entry = NULL;
    nvm_huge_header_t *nvm_huge = NULL;
    nvm_block_header_t *nvm_block = NULL;
    nvm_run_header_t *nvm_run = NULL;
    uint16_t bit_idx = 0;
    uint8_t bitmap_idx = 0;
    char bitmask = 0;
    char state = -1;
    int keep = 0;
    void *ptr = NULL;

    while (1) {
        for (i=0; i<63; ++i) {
            keep = 0;
            nvm_entry = &chunk_hdr->object_table[i];
            if (nvm_entry->state == STATE_INITIALIZED) {
                /* entry is marked as initialized, so we can keep it */
                keep = 1;
            } else if (nvm_entry->state == STATE_INITIALIZING) {
                /* crash occurred during activation but after writing the entry, check corresponding header */
                /* if header is in state PREFREE, ACTIVATING or INITIALIZED, it is/will be recovered and the entry can persist */
                ptr = (void*) ((uintptr_t)nvm_start + nvm_entry->ptr);
                state = identify_usage(ptr);
                if (state == USAGE_HUGE) {
                    nvm_huge = (nvm_huge_header_t*) ((uintptr_t)ptr - sizeof(nvm_huge_header_t));
                    if (nvm_huge->state == STATE_PREFREE ||
                        nvm_huge->state == STATE_ACTIVATING ||
                        nvm_huge->state == STATE_INITIALIZED) {
                        keep = 1;
                    }
                } else if (state == USAGE_BLOCK) {
                    nvm_block = (nvm_block_header_t*) ((uintptr_t)ptr - sizeof(nvm_block_header_t));
                    if (nvm_block->state == STATE_PREFREE ||
                        nvm_block->state == STATE_ACTIVATING ||
                        nvm_block->state == STATE_INITIALIZED) {
                        keep = 1;
                    }
                } else if (state == USAGE_RUN) {
                    /* for runs, we also need to check that the bit index is the correct one */
                    nvm_run = (nvm_run_header_t*) ((uintptr_t)ptr & ~(BLOCK_SIZE-1));
                    bit_idx = ((uintptr_t)ptr - (uintptr_t)(nvm_run+1)) / nvm_run->n_bytes;
                    bitmask = 1 << (bit_idx % 8);
                    bitmap_idx = bit_idx / 8;
                    if ((nvm_run->state == STATE_PREFREE && (nvm_run->bitmap[bitmap_idx] & bitmask) != 0) ||
                        (nvm_run->state == STATE_ACTIVATING && nvm_run->bit_idx == bit_idx) ||
                        (nvm_run->state == STATE_INITIALIZED && (nvm_run->bitmap[bitmap_idx] & bitmask) != 0)) {
                        keep = 1;
                    }
                }
                if (keep) {
                    nvm_entry->state = STATE_INITIALIZED;
                } else {
                    memset(nvm_entry, 0, sizeof(nvm_object_table_entry_t));
                }
                PERSIST(nvm_entry);
            }

            if (keep) {
                /* if we keep the entry, create its volatile counterpart */
                entry = malloc(sizeof(object_table_entry_t));
                memcpy(entry->id, nvm_entry->id, MAX_ID_LENGTH);
                entry->slot = current_slot;
                entry->data_ptr = NVM_REL_TO_ABS(first_chunk, nvm_entry->ptr);
                entry->nvm_entry = nvm_entry;
                /* add the unused slots we found since the last valid entry to the slot buffer */
                for (n=last_used_slot+1; n<current_slot; ++n) {
                    slot_buffer[slot_buffer_next_idx++] = n;
                    ++slot_buffer_tail_idx;
                    ++slot_buffer_n_free;
                }
                last_used_slot = current_slot;
                HASHMAP_INSERT(entry->id, entry);
            }
            ++current_slot;
        }
        if (chunk_hdr->next_ot_chunk) {
            chunk_hdr = (nvm_chunk_header_t*) NVM_REL_TO_ABS(first_chunk, chunk_hdr->next_ot_chunk);
        } else {
            break;
        }
    }

    next_nvm_slot = last_used_slot+1;
}