/** * efi_partition(struct parsed_partitions *state, struct block_device *bdev) * @state * @bdev * * Description: called from check.c, if the disk contains GPT * partitions, sets up partition entries in the kernel. * * If the first block on the disk is a legacy MBR, * it will get handled by msdos_partition(). * If it's a Protective MBR, we'll handle it here. * * We do not create a Linux partition for GPT, but * only for the actual data partitions. * Returns: * -1 if unable to read the partition table * 0 if this isn't our partition table * 1 if successful * */ int efi_partition(struct parsed_partitions *state, struct block_device *bdev) { gpt_header *gpt = NULL; gpt_entry *ptes = NULL; u32 i; unsigned ssz = bdev_logical_block_size(bdev) / 512; if (!find_valid_gpt(bdev, &gpt, &ptes) || !gpt || !ptes) { kfree(gpt); kfree(ptes); return 0; } pr_debug("GUID Partition Table is valid! Yea!\n"); for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) { u64 start = le64_to_cpu(ptes[i].starting_lba); u64 size = le64_to_cpu(ptes[i].ending_lba) - le64_to_cpu(ptes[i].starting_lba) + 1ULL; if (!is_pte_valid(&ptes[i], last_lba(bdev))) continue; put_partition(state, i+1, start * ssz, size * ssz); /* If this is a RAID volume, tell md */ if (!efi_guidcmp(ptes[i].partition_type_guid, PARTITION_LINUX_RAID_GUID)) state->parts[i+1].flags = 1; } kfree(ptes); kfree(gpt); printk("\n"); return 1; }
/* * Write the physical details regarding the block device to the store, and * switch to Connected state. */ static void connect(struct backend_info *be) { struct xenbus_transaction xbt; int err; struct xenbus_device *dev = be->dev; DPRINTK("%s", dev->otherend); /* Supply the information about the device the frontend needs */ again: err = xenbus_transaction_start(&xbt); if (err) { xenbus_dev_fatal(dev, err, "starting transaction"); return; } err = xen_blkbk_flush_diskcache(xbt, be, be->blkif->vbd.flush_support); if (err) goto abort; err = xenbus_printf(xbt, dev->nodename, "sectors", "%llu", (unsigned long long)vbd_sz(&be->blkif->vbd)); if (err) { xenbus_dev_fatal(dev, err, "writing %s/sectors", dev->nodename); goto abort; } /* FIXME: use a typename instead */ err = xenbus_printf(xbt, dev->nodename, "info", "%u", be->blkif->vbd.type | (be->blkif->vbd.readonly ? VDISK_READONLY : 0)); if (err) { xenbus_dev_fatal(dev, err, "writing %s/info", dev->nodename); goto abort; } err = xenbus_printf(xbt, dev->nodename, "sector-size", "%lu", (unsigned long) bdev_logical_block_size(be->blkif->vbd.bdev)); if (err) { xenbus_dev_fatal(dev, err, "writing %s/sector-size", dev->nodename); goto abort; } err = xenbus_transaction_end(xbt, 0); if (err == -EAGAIN) goto again; if (err) xenbus_dev_fatal(dev, err, "ending transaction"); err = xenbus_switch_state(dev, XenbusStateConnected); if (err) xenbus_dev_fatal(dev, err, "switching to Connected state", dev->nodename); return; abort: xenbus_transaction_end(xbt, 1); }
/** * efi_partition(struct parsed_partitions *state) * @state * * Description: called from check.c, if the disk contains GPT * partitions, sets up partition entries in the kernel. * * If the first block on the disk is a legacy MBR, * it will get handled by msdos_partition(). * If it's a Protective MBR, we'll handle it here. * * We do not create a Linux partition for GPT, but * only for the actual data partitions. * Returns: * -1 if unable to read the partition table * 0 if this isn't our partition table * 1 if successful * */ int efi_partition(struct parsed_partitions *state) { gpt_header *gpt = NULL; gpt_entry *ptes = NULL; u32 i; unsigned ssz = bdev_logical_block_size(state->bdev) / 512; u8 unparsed_guid[37]; if (!find_valid_gpt(state, &gpt, &ptes) || !gpt || !ptes) { kfree(gpt); kfree(ptes); return 0; } pr_debug("GUID Partition Table is valid! Yea!\n"); for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) { struct partition_meta_info *info; unsigned label_count = 0; unsigned label_max; u64 start = le64_to_cpu(ptes[i].starting_lba); u64 size = le64_to_cpu(ptes[i].ending_lba) - le64_to_cpu(ptes[i].starting_lba) + 1ULL; if (!is_pte_valid(&ptes[i], last_lba(state->bdev))) continue; put_partition(state, i+1, start * ssz, size * ssz); /* If this is a RAID volume, tell md */ if (!efi_guidcmp(ptes[i].partition_type_guid, PARTITION_LINUX_RAID_GUID)) state->parts[i + 1].flags = ADDPART_FLAG_RAID; info = &state->parts[i + 1].info; /* Instead of doing a manual swap to big endian, reuse the * common ASCII hex format as the interim. */ efi_guid_unparse(&ptes[i].unique_partition_guid, unparsed_guid); part_pack_uuid(unparsed_guid, info->uuid); /* Naively convert UTF16-LE to 7 bits. */ label_max = min(sizeof(info->volname) - 1, sizeof(ptes[i].partition_name)); info->volname[label_max] = 0; while (label_count < label_max) { u8 c = ptes[i].partition_name[label_count] & 0xff; if (c && !isprint(c)) c = '!'; info->volname[label_count] = c; label_count++; } state->parts[i + 1].has_info = true; } /* Add static partitions for SOS and LNX if specified in kernel config (Tegra platform) */ #ifdef CONFIG_TEGRA_BOOTBLOCK_EXPOSE printk(KERN_NOTICE "Adding SOS as MMC partition %i: offset %i bytes, size: %i bytes\n", i+1, CONFIG_BOOTBLOCK_EXPOSE_SOS_OFFSET * 512, CONFIG_BOOTBLOCK_EXPOSE_SOS_SIZE * 512); put_partition(state, i+1, CONFIG_BOOTBLOCK_EXPOSE_SOS_OFFSET * ssz, CONFIG_BOOTBLOCK_EXPOSE_SOS_SIZE * ssz); printk(KERN_NOTICE "Adding LNX as MMC partition %i: offset %i bytes, size: %i bytes\n", i+2, CONFIG_BOOTBLOCK_EXPOSE_LNX_OFFSET * 512, CONFIG_BOOTBLOCK_EXPOSE_LNX_SIZE * 512); put_partition(state, i+2, CONFIG_BOOTBLOCK_EXPOSE_LNX_OFFSET * ssz, CONFIG_BOOTBLOCK_EXPOSE_LNX_SIZE * ssz); #endif kfree(ptes); kfree(gpt); strlcat(state->pp_buf, "\n", PAGE_SIZE); return 1; }
int msdos_partition(struct parsed_partitions *state) { sector_t sector_size = bdev_logical_block_size(state->bdev) / 512; Sector sect; unsigned char *data; struct partition *p; struct fat_boot_sector *fb; int slot; data = read_part_sector(state, 0, §); if (!data) return -1; if (!msdos_magic_present(data + 510)) { put_dev_sector(sect); return 0; } if (aix_magic_present(state, data)) { put_dev_sector(sect); printk( " [AIX]"); return 0; } /* * Now that the 55aa signature is present, this is probably * either the boot sector of a FAT filesystem or a DOS-type * partition table. Reject this in case the boot indicator * is not 0 or 0x80. */ p = (struct partition *) (data + 0x1be); for (slot = 1; slot <= 4; slot++, p++) { if (p->boot_ind != 0 && p->boot_ind != 0x80) { /* * Even without a valid boot inidicator value * its still possible this is valid FAT filesystem * without a partition table. */ fb = (struct fat_boot_sector *) data; if (slot == 1 && fb->reserved && fb->fats && fat_valid_media(fb->media)) { printk("\n"); put_dev_sector(sect); return 1; } else { put_dev_sector(sect); return 0; } } } #ifdef CONFIG_EFI_PARTITION p = (struct partition *) (data + 0x1be); for (slot = 1 ; slot <= 4 ; slot++, p++) { /* If this is an EFI GPT disk, msdos should ignore it. */ if (SYS_IND(p) == EFI_PMBR_OSTYPE_EFI_GPT) { put_dev_sector(sect); return 0; } } #endif p = (struct partition *) (data + 0x1be); /* * Look for partitions in two passes: * First find the primary and DOS-type extended partitions. * On the second pass look inside *BSD, Unixware and Solaris partitions. */ state->next = 5; for (slot = 1 ; slot <= 4 ; slot++, p++) { sector_t start = start_sect(p)*sector_size; sector_t size = nr_sects(p)*sector_size; if (!size) continue; if (is_extended_partition(p)) { /* * prevent someone doing mkfs or mkswap on an * extended partition, but leave room for LILO * FIXME: this uses one logical sector for > 512b * sector, although it may not be enough/proper. */ sector_t n = 2; n = min(size, max(sector_size, n)); put_partition(state, slot, start, n); printk(" <"); parse_extended(state, start, size); printk(" >"); continue; } put_partition(state, slot, start, size); if (SYS_IND(p) == LINUX_RAID_PARTITION) state->parts[slot].flags = ADDPART_FLAG_RAID; if (SYS_IND(p) == DM6_PARTITION) printk("[DM]"); if (SYS_IND(p) == EZD_PARTITION) printk("[EZD]"); } printk("\n"); /* second pass - output for each on a separate line */ p = (struct partition *) (0x1be + data); for (slot = 1 ; slot <= 4 ; slot++, p++) { unsigned char id = SYS_IND(p); int n; if (!nr_sects(p)) continue; for (n = 0; subtypes[n].parse && id != subtypes[n].id; n++) ; if (!subtypes[n].parse) continue; subtypes[n].parse(state, start_sect(p) * sector_size, nr_sects(p) * sector_size, slot); } put_dev_sector(sect); return 1; }
/** * is_gpt_valid() - tests one GPT header and PTEs for validity * @state * @lba is the logical block address of the GPT header to test * @gpt is a GPT header ptr, filled on return. * @ptes is a PTEs ptr, filled on return. * * Description: returns 1 if valid, 0 on error. * If valid, returns pointers to newly allocated GPT header and PTEs. */ static int is_gpt_valid(struct parsed_partitions *state, u64 lba, gpt_header **gpt, gpt_entry **ptes) { u32 crc, origcrc; u64 lastlba; if (!ptes) return 0; if (!(*gpt = alloc_read_gpt_header(state, lba))) return 0; /* Check the GUID Partition Table signature */ if (le64_to_cpu((*gpt)->signature) != GPT_HEADER_SIGNATURE) { pr_debug("GUID Partition Table Header signature is wrong:" "%lld != %lld\n", (unsigned long long)le64_to_cpu((*gpt)->signature), (unsigned long long)GPT_HEADER_SIGNATURE); goto fail; } /* Check the GUID Partition Table header size is too big */ if (le32_to_cpu((*gpt)->header_size) > bdev_logical_block_size(state->bdev)) { pr_debug("GUID Partition Table Header size is too large: %u > %u\n", le32_to_cpu((*gpt)->header_size), bdev_logical_block_size(state->bdev)); goto fail; } /* Check the GUID Partition Table header size is too small */ if (le32_to_cpu((*gpt)->header_size) < sizeof(gpt_header)) { pr_debug("GUID Partition Table Header size is too small: %u < %zu\n", le32_to_cpu((*gpt)->header_size), sizeof(gpt_header)); goto fail; } /* Check the GUID Partition Table CRC */ origcrc = le32_to_cpu((*gpt)->header_crc32); (*gpt)->header_crc32 = 0; crc = efi_crc32((const unsigned char *) (*gpt), le32_to_cpu((*gpt)->header_size)); if (crc != origcrc) { pr_debug("GUID Partition Table Header CRC is wrong: %x != %x\n", crc, origcrc); goto fail; } (*gpt)->header_crc32 = cpu_to_le32(origcrc); /* Check that the my_lba entry points to the LBA that contains * the GUID Partition Table */ if (le64_to_cpu((*gpt)->my_lba) != lba) { pr_debug("GPT my_lba incorrect: %lld != %lld\n", (unsigned long long)le64_to_cpu((*gpt)->my_lba), (unsigned long long)lba); goto fail; } /* Check the first_usable_lba and last_usable_lba are * within the disk. */ lastlba = last_lba(state->bdev); if (le64_to_cpu((*gpt)->first_usable_lba) > lastlba) { pr_debug("GPT: first_usable_lba incorrect: %lld > %lld\n", (unsigned long long)le64_to_cpu((*gpt)->first_usable_lba), (unsigned long long)lastlba); goto fail; } if (le64_to_cpu((*gpt)->last_usable_lba) > lastlba) { pr_debug("GPT: last_usable_lba incorrect: %lld > %lld\n", (unsigned long long)le64_to_cpu((*gpt)->last_usable_lba), (unsigned long long)lastlba); goto fail; } /* Check that sizeof_partition_entry has the correct value */ if (le32_to_cpu((*gpt)->sizeof_partition_entry) != sizeof(gpt_entry)) { pr_debug("GUID Partitition Entry Size check failed.\n"); goto fail; } if (!(*ptes = alloc_read_gpt_entries(state, *gpt))) goto fail; /* Check the GUID Partition Entry Array CRC */ crc = efi_crc32((const unsigned char *) (*ptes), le32_to_cpu((*gpt)->num_partition_entries) * le32_to_cpu((*gpt)->sizeof_partition_entry)); if (crc != le32_to_cpu((*gpt)->partition_entry_array_crc32)) { pr_debug("GUID Partitition Entry Array CRC check failed.\n"); goto fail_ptes; } /* We're done, all's well */ return 1; fail_ptes: kfree(*ptes); *ptes = NULL; fail: kfree(*gpt); *gpt = NULL; if (!force_gpt) BUG_ON(1); return 0; }
int atari_partition(struct parsed_partitions *state) { Sector sect; struct rootsector *rs; struct partition_info *pi; u32 extensect; u32 hd_size; int slot; #ifdef ICD_PARTS int part_fmt = 0; /* 0:unknown, 1:AHDI, 2:ICD/Supra */ #endif /* * ATARI partition scheme supports 512 lba only. If this is not * the case, bail early to avoid miscalculating hd_size. */ if (bdev_logical_block_size(state->bdev) != 512) return 0; rs = read_part_sector(state, 0, §); if (!rs) return -1; /* Verify this is an Atari rootsector: */ hd_size = state->bdev->bd_inode->i_size >> 9; if (!VALID_PARTITION(&rs->part[0], hd_size) && !VALID_PARTITION(&rs->part[1], hd_size) && !VALID_PARTITION(&rs->part[2], hd_size) && !VALID_PARTITION(&rs->part[3], hd_size)) { /* * if there's no valid primary partition, assume that no Atari * format partition table (there's no reliable magic or the like * :-() */ put_dev_sector(sect); return 0; } pi = &rs->part[0]; strlcat(state->pp_buf, " AHDI", PAGE_SIZE); for (slot = 1; pi < &rs->part[4] && slot < state->limit; slot++, pi++) { struct rootsector *xrs; Sector sect2; ulong partsect; if ( !(pi->flg & 1) ) continue; /* active partition */ if (memcmp (pi->id, "XGM", 3) != 0) { /* we don't care about other id's */ put_partition (state, slot, be32_to_cpu(pi->st), be32_to_cpu(pi->siz)); continue; } /* extension partition */ #ifdef ICD_PARTS part_fmt = 1; #endif strlcat(state->pp_buf, " XGM<", PAGE_SIZE); partsect = extensect = be32_to_cpu(pi->st); while (1) { xrs = read_part_sector(state, partsect, §2); if (!xrs) { printk (" block %ld read failed\n", partsect); put_dev_sector(sect); return -1; } /* ++roman: sanity check: bit 0 of flg field must be set */ if (!(xrs->part[0].flg & 1)) { printk( "\nFirst sub-partition in extended partition is not valid!\n" ); put_dev_sector(sect2); break; } put_partition(state, slot, partsect + be32_to_cpu(xrs->part[0].st), be32_to_cpu(xrs->part[0].siz)); if (!(xrs->part[1].flg & 1)) { /* end of linked partition list */ put_dev_sector(sect2); break; } if (memcmp( xrs->part[1].id, "XGM", 3 ) != 0) { printk("\nID of extended partition is not XGM!\n"); put_dev_sector(sect2); break; } partsect = be32_to_cpu(xrs->part[1].st) + extensect; put_dev_sector(sect2); if (++slot == state->limit) { printk( "\nMaximum number of partitions reached!\n" ); break; } } strlcat(state->pp_buf, " >", PAGE_SIZE); } #ifdef ICD_PARTS if ( part_fmt!=1 ) { /* no extended partitions -> test ICD-format */ pi = &rs->icdpart[0]; /* sanity check: no ICD format if first partition invalid */ if (OK_id(pi->id)) { strlcat(state->pp_buf, " ICD<", PAGE_SIZE); for (; pi < &rs->icdpart[8] && slot < state->limit; slot++, pi++) { /* accept only GEM,BGM,RAW,LNX,SWP partitions */ if (!((pi->flg & 1) && OK_id(pi->id))) continue; part_fmt = 2; put_partition (state, slot, be32_to_cpu(pi->st), be32_to_cpu(pi->siz)); } strlcat(state->pp_buf, " >", PAGE_SIZE); } } #endif put_dev_sector(sect); strlcat(state->pp_buf, "\n", PAGE_SIZE); return 1; }
int drbd_md_sync_page_io(struct drbd_conf *mdev, struct drbd_backing_dev *bdev, sector_t sector, int rw) { int logical_block_size, mask, ok; int offset = 0; struct page *iop = mdev->md_io_page; D_ASSERT(mutex_is_locked(&mdev->md_io_mutex)); if (!bdev->md_bdev) { if (DRBD_ratelimit(5*HZ, 5)) { dev_err(DEV, "bdev->md_bdev==NULL\n"); dump_stack(); } return 0; } logical_block_size = bdev_logical_block_size(bdev->md_bdev); if (logical_block_size == 0) logical_block_size = MD_SECTOR_SIZE; /* in case logical_block_size != 512 [ s390 only? ] */ if (logical_block_size != MD_SECTOR_SIZE) { mask = (logical_block_size / MD_SECTOR_SIZE) - 1; D_ASSERT(mask == 1 || mask == 3 || mask == 7); D_ASSERT(logical_block_size == (mask+1) * MD_SECTOR_SIZE); offset = sector & mask; sector = sector & ~mask; iop = mdev->md_io_tmpp; if (rw & WRITE) { /* these are GFP_KERNEL pages, pre-allocated * on device initialization */ void *p = page_address(mdev->md_io_page); void *hp = page_address(mdev->md_io_tmpp); ok = _drbd_md_sync_page_io(mdev, bdev, iop, sector, READ, logical_block_size); if (unlikely(!ok)) { dev_err(DEV, "drbd_md_sync_page_io(,%llus," "READ [logical_block_size!=512]) failed!\n", (unsigned long long)sector); return 0; } memcpy(hp + offset*MD_SECTOR_SIZE, p, MD_SECTOR_SIZE); } } #if DUMP_MD >= 3 dev_info(DEV, "%s [%d]:%s(,%llus,%s)\n", current->comm, current->pid, __func__, (unsigned long long)sector, (rw & WRITE) ? "WRITE" : "READ"); #endif if (sector < drbd_md_first_sector(bdev) || sector > drbd_md_last_sector(bdev)) dev_alert(DEV, "%s [%d]:%s(,%llus,%s) out of range md access!\n", current->comm, current->pid, __func__, (unsigned long long)sector, (rw & WRITE) ? "WRITE" : "READ"); ok = _drbd_md_sync_page_io(mdev, bdev, iop, sector, rw, logical_block_size); if (unlikely(!ok)) { dev_err(DEV, "drbd_md_sync_page_io(,%llus,%s) failed!\n", (unsigned long long)sector, (rw & WRITE) ? "WRITE" : "READ"); return 0; } if (logical_block_size != MD_SECTOR_SIZE && !(rw & WRITE)) { void *p = page_address(mdev->md_io_page); void *hp = page_address(mdev->md_io_tmpp); memcpy(p, hp + offset*MD_SECTOR_SIZE, MD_SECTOR_SIZE); } return ok; }
int parse_tegrapart(struct parsed_partitions *state) { char *ptr; char *pstart; int pstate; char name[8]; u64 offset, size, blocksize, kblocksize; int done; int ret=0; printk(KERN_INFO "parse_tegrapart: tegrapart=%s\n", partition_list); kblocksize = bdev_logical_block_size(state->bdev); ptr = partition_list; pstart = ptr; pstate = STATE_NAME; name[0] = '\0'; offset = 0; size = 0; blocksize = 0; done = 0; do { switch(pstate) { case STATE_NAME: if (*ptr==':') { int len=ptr-pstart; if (len>7) len=7; memcpy(name, pstart, len); name[len] = '\0'; pstate++; pstart = ptr+1; } break; case STATE_OFFSET: if (*ptr==':') { offset=strtohex(pstart); pstate++; pstart = ptr+1; } break; case STATE_SIZE: if (*ptr==':') { size=strtohex(pstart); pstate++; pstart = ptr+1; } break; case STATE_BLOCKSIZE: if (*ptr=='\0') done = 1; if ((*ptr==',') || (*ptr=='\0')) { blocksize=strtohex(pstart); pstate = STATE_NAME; pstart = ptr+1; offset = offset*blocksize; size = size*blocksize; do_div(offset, kblocksize); do_div(size, kblocksize); if (!strcasecmp(name, "mbr")) { printk(KERN_INFO "parse_tegrapart: mbr start=%llu\n", offset); return tegra_msdos_parse(state, state->bdev, offset); } printk(KERN_INFO "parse_tegrapart: part #%d [%s] start=%llu size=%llu\n", state->next, name, offset, size); put_partition(state, state->next++, offset, size); ret = 1; } break; } ptr++; } while (!done); printk(KERN_INFO "parse_tegrapart: done without mbr\n"); return ret; }
/** * efi_partition(struct parsed_partitions *state) * @state * * Description: called from check.c, if the disk contains GPT * partitions, sets up partition entries in the kernel. * * If the first block on the disk is a legacy MBR, * it will get handled by msdos_partition(). * If it's a Protective MBR, we'll handle it here. * * We do not create a Linux partition for GPT, but * only for the actual data partitions. * Returns: * -1 if unable to read the partition table * 0 if this isn't our partition table * 1 if successful * */ int efi_partition(struct parsed_partitions *state) { char* partition_name = NULL; gpt_header *gpt = NULL; gpt_entry *ptes = NULL; u32 i; unsigned ssz = bdev_logical_block_size(state->bdev) / 512; u8 unparsed_guid[37]; partition_name = kzalloc(sizeof(ptes->partition_name), GFP_KERNEL); if (!partition_name) return 0; if (!find_valid_gpt(state, &gpt, &ptes) || !gpt || !ptes) { kfree(gpt); kfree(ptes); kfree(partition_name); return 0; } pr_debug("GUID Partition Table is valid! Yea!\n"); for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) { int partition_name_len; struct partition_meta_info *info; unsigned label_count = 0; unsigned label_max; u64 start = le64_to_cpu(ptes[i].starting_lba); u64 size = le64_to_cpu(ptes[i].ending_lba) - le64_to_cpu(ptes[i].starting_lba) + 1ULL; if (!is_pte_valid(&ptes[i], last_lba(state->bdev))) continue; partition_name_len = utf16s_to_utf8s(ptes[i].partition_name, sizeof(ptes[i].partition_name), UTF16_LITTLE_ENDIAN, partition_name, sizeof(ptes[i].partition_name)); #ifdef CONFIG_APANIC_ON_MMC if(strncmp(partition_name,CONFIG_APANIC_PLABEL,partition_name_len) == 0) { apanic_partition_start = start * ssz; apanic_partition_size = size * ssz; pr_debug("apanic partition found starts at %lu \r\n", apanic_partition_start); pr_debug("apanic partition size = %lu\n", apanic_partition_size); } #endif put_partition(state, i+1, start * ssz, size * ssz); /* If this is a RAID volume, tell md */ if (!efi_guidcmp(ptes[i].partition_type_guid, PARTITION_LINUX_RAID_GUID)) state->parts[i + 1].flags = ADDPART_FLAG_RAID; info = &state->parts[i + 1].info; /* Instead of doing a manual swap to big endian, reuse the * common ASCII hex format as the interim. */ efi_guid_unparse(&ptes[i].unique_partition_guid, unparsed_guid); part_pack_uuid(unparsed_guid, info->uuid); /* Naively convert UTF16-LE to 7 bits. */ label_max = min(sizeof(info->volname) - 1, sizeof(ptes[i].partition_name)); info->volname[label_max] = 0; while (label_count < label_max) { u8 c = ptes[i].partition_name[label_count] & 0xff; if (c && !isprint(c)) c = '!'; info->volname[label_count] = c; label_count++; } state->parts[i + 1].has_info = true; #ifdef CONFIG_APANIC_ON_MMC if(strncmp(info->volname,CONFIG_APANIC_PLABEL,label_count) == 0) { apanic_partition_start = start * ssz; pr_debug("apanic partition found starts at %lu \r\n", apanic_partition_start); } #endif } kfree(ptes); kfree(gpt); kfree(partition_name); strlcat(state->pp_buf, "\n", PAGE_SIZE); return 1; }
/* fd_create_virtdevice(): (Part of se_subsystem_api_t template) * * */ static struct se_device *fd_create_virtdevice( struct se_hba *hba, struct se_subsystem_dev *se_dev, void *p) { char *dev_p = NULL; struct se_device *dev; struct se_dev_limits dev_limits; struct queue_limits *limits; struct fd_dev *fd_dev = p; struct fd_host *fd_host = hba->hba_ptr; mm_segment_t old_fs; struct file *file; struct inode *inode = NULL; int dev_flags = 0, flags, ret = -EINVAL; memset(&dev_limits, 0, sizeof(struct se_dev_limits)); old_fs = get_fs(); set_fs(get_ds()); dev_p = getname(fd_dev->fd_dev_name); set_fs(old_fs); if (IS_ERR(dev_p)) { pr_err("getname(%s) failed: %lu\n", fd_dev->fd_dev_name, IS_ERR(dev_p)); ret = PTR_ERR(dev_p); goto fail; } /* * Use O_DSYNC by default instead of O_SYNC to forgo syncing * of pure timestamp updates. */ flags = O_RDWR | O_CREAT | O_LARGEFILE | O_DSYNC; file = filp_open(dev_p, flags, 0600); if (IS_ERR(file)) { pr_err("filp_open(%s) failed\n", dev_p); ret = PTR_ERR(file); goto fail; } if (!file || !file->f_dentry) { pr_err("filp_open(%s) failed\n", dev_p); goto fail; } fd_dev->fd_file = file; /* * If using a block backend with this struct file, we extract * fd_dev->fd_[block,dev]_size from struct block_device. * * Otherwise, we use the passed fd_size= from configfs */ inode = file->f_mapping->host; if (S_ISBLK(inode->i_mode)) { struct request_queue *q; unsigned long long dev_size; /* * Setup the local scope queue_limits from struct request_queue->limits * to pass into transport_add_device_to_core_hba() as struct se_dev_limits. */ q = bdev_get_queue(inode->i_bdev); limits = &dev_limits.limits; limits->logical_block_size = bdev_logical_block_size(inode->i_bdev); limits->max_hw_sectors = queue_max_hw_sectors(q); limits->max_sectors = queue_max_sectors(q); /* * Determine the number of bytes from i_size_read() minus * one (1) logical sector from underlying struct block_device */ fd_dev->fd_block_size = bdev_logical_block_size(inode->i_bdev); dev_size = (i_size_read(file->f_mapping->host) - fd_dev->fd_block_size); pr_debug("FILEIO: Using size: %llu bytes from struct" " block_device blocks: %llu logical_block_size: %d\n", dev_size, div_u64(dev_size, fd_dev->fd_block_size), fd_dev->fd_block_size); } else { if (!(fd_dev->fbd_flags & FBDF_HAS_SIZE)) { pr_err("FILEIO: Missing fd_dev_size=" " parameter, and no backing struct" " block_device\n"); goto fail; } limits = &dev_limits.limits; limits->logical_block_size = FD_BLOCKSIZE; limits->max_hw_sectors = FD_MAX_SECTORS; limits->max_sectors = FD_MAX_SECTORS; fd_dev->fd_block_size = FD_BLOCKSIZE; } dev_limits.hw_queue_depth = FD_MAX_DEVICE_QUEUE_DEPTH; dev_limits.queue_depth = FD_DEVICE_QUEUE_DEPTH; dev = transport_add_device_to_core_hba(hba, &fileio_template, se_dev, dev_flags, fd_dev, &dev_limits, "FILEIO", FD_VERSION); if (!dev) goto fail; fd_dev->fd_dev_id = fd_host->fd_host_dev_id_count++; fd_dev->fd_queue_depth = dev->queue_depth; pr_debug("CORE_FILE[%u] - Added TCM FILEIO Device ID: %u at %s," " %llu total bytes\n", fd_host->fd_host_id, fd_dev->fd_dev_id, fd_dev->fd_dev_name, fd_dev->fd_dev_size); putname(dev_p); return dev; fail: if (fd_dev->fd_file) { filp_close(fd_dev->fd_file, NULL); fd_dev->fd_file = NULL; } putname(dev_p); return ERR_PTR(ret); }
/** * efi_partition(struct parsed_partitions *state) * @state * * Description: called from check.c, if the disk contains GPT * partitions, sets up partition entries in the kernel. * * If the first block on the disk is a legacy MBR, * it will get handled by msdos_partition(). * If it's a Protective MBR, we'll handle it here. * * We do not create a Linux partition for GPT, but * only for the actual data partitions. * Returns: * -1 if unable to read the partition table * 0 if this isn't our partition table * 1 if successful * */ int efi_partition(struct parsed_partitions *state) { gpt_header *gpt = NULL; gpt_entry *ptes = NULL; u32 i; unsigned ssz = bdev_logical_block_size(state->bdev) / 512; if (!find_valid_gpt(state, &gpt, &ptes) || !gpt || !ptes) { kfree(gpt); kfree(ptes); return 0; } pr_debug("GUID Partition Table is valid! Yea!\n"); for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) { u64 start = le64_to_cpu(ptes[i].starting_lba); u64 size = le64_to_cpu(ptes[i].ending_lba) - le64_to_cpu(ptes[i].starting_lba) + 1ULL; u8 name[sizeof(ptes->partition_name) / sizeof(efi_char16_t)]; int len; if (!is_pte_valid(&ptes[i], last_lba(state->bdev))) continue; len = utf16s_to_utf8s(ptes[i].partition_name, sizeof(ptes[i].partition_name) / sizeof(efi_char16_t), UTF16_LITTLE_ENDIAN, name, sizeof(name)); put_named_partition(state, i+1, start * ssz, size * ssz, name, len); { #define ADDPART_FLAG_QISDA_READONLY 32 u64 *attributes = (u64 *) &ptes[i].attributes; if (*attributes & 0xD000000000000000ULL) { pr_debug("guid partition attributes! set attributes by Qisda backdoor!\n"); if (*attributes & 0x1000000000000000ULL) state->parts[i+1].flags |= ADDPART_FLAG_QISDA_READONLY; } } /* If this is a RAID volume, tell md */ if (!efi_guidcmp(ptes[i].partition_type_guid, PARTITION_LINUX_RAID_GUID)) state->parts[i + 1].flags = ADDPART_FLAG_RAID; } kfree(ptes); kfree(gpt); strlcat(state->pp_buf, "\n", PAGE_SIZE); return 1; }
unsigned long vbd_secsize(struct vbd *vbd) { return bdev_logical_block_size(vbd->bdev); }
/** * efi_partition(struct parsed_partitions *state, struct block_device *bdev) * @state * @bdev * * Description: called from check.c, if the disk contains GPT * partitions, sets up partition entries in the kernel. * * If the first block on the disk is a legacy MBR, * it will get handled by msdos_partition(). * If it's a Protective MBR, we'll handle it here. * * We do not create a Linux partition for GPT, but * only for the actual data partitions. * Returns: * -1 if unable to read the partition table * 0 if this isn't our partition table * 1 if successful * */ int efi_partition(struct parsed_partitions *state, struct block_device *bdev) { gpt_header *gpt = NULL; gpt_entry *ptes = NULL; u32 i; unsigned ssz = bdev_logical_block_size(bdev) / 512; u8 unparsed_guid[37]; if (!find_valid_gpt(bdev, &gpt, &ptes) || !gpt || !ptes) { kfree(gpt); kfree(ptes); return 0; } pr_debug("GUID Partition Table is valid! Yea!\n"); for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) { struct partition_meta_info *info; unsigned label_count = 0; unsigned label_max; u64 start = le64_to_cpu(ptes[i].starting_lba); u64 size = le64_to_cpu(ptes[i].ending_lba) - le64_to_cpu(ptes[i].starting_lba) + 1ULL; if (!is_pte_valid(&ptes[i], last_lba(bdev))) continue; put_partition(state, i+1, start * ssz, size * ssz); /* If this is a RAID volume, tell md */ if (!efi_guidcmp(ptes[i].partition_type_guid, PARTITION_LINUX_RAID_GUID)) state->parts[i+1].flags = 1; info = &state->parts[i + 1].info; /* The EFI specification diverges from RFC 4122 with respect to * the packed storage of its UUIDs. efi_guid_unparse unpacks to * a common ASCII representation, which allows part_pack_uuid to * pack it in the standard big endian layout for use by the rest * of the kernel. */ efi_guid_unparse(&ptes[i].unique_partition_guid, unparsed_guid); part_pack_uuid(unparsed_guid, info->uuid); /* Naively convert UTF16-LE to 7 bits. */ label_max = min(sizeof(info->volname) - 1, sizeof(ptes[i].partition_name)); info->volname[label_max] = 0; while (label_count < label_max) { u8 c = ptes[i].partition_name[label_count] & 0xff; if (c && !isprint(c)) c = '!'; info->volname[label_count] = c; label_count++; } state->parts[i + 1].has_info = true; } kfree(ptes); kfree(gpt); printk("\n"); return 1; }
static int iblock_configure_device(struct se_device *dev) { struct iblock_dev *ib_dev = IBLOCK_DEV(dev); struct request_queue *q; struct block_device *bd = NULL; fmode_t mode; int ret = -ENOMEM; if (!(ib_dev->ibd_flags & IBDF_HAS_UDEV_PATH)) { pr_err("Missing udev_path= parameters for IBLOCK\n"); return -EINVAL; } ib_dev->ibd_bio_set = bioset_create(IBLOCK_BIO_POOL_SIZE, 0); if (!ib_dev->ibd_bio_set) { pr_err("IBLOCK: Unable to create bioset\n"); goto out; } pr_debug( "IBLOCK: Claiming struct block_device: %s\n", ib_dev->ibd_udev_path); mode = FMODE_READ|FMODE_EXCL; if (!ib_dev->ibd_readonly) mode |= FMODE_WRITE; bd = blkdev_get_by_path(ib_dev->ibd_udev_path, mode, ib_dev); if (IS_ERR(bd)) { ret = PTR_ERR(bd); goto out_free_bioset; } ib_dev->ibd_bd = bd; q = bdev_get_queue(bd); dev->dev_attrib.hw_block_size = bdev_logical_block_size(bd); dev->dev_attrib.hw_max_sectors = queue_max_hw_sectors(q); dev->dev_attrib.hw_queue_depth = q->nr_requests; /* * Check if the underlying struct block_device request_queue supports * the QUEUE_FLAG_DISCARD bit for UNMAP/WRITE_SAME in SCSI + TRIM * in ATA and we need to set TPE=1 */ if (blk_queue_discard(q)) { dev->dev_attrib.max_unmap_lba_count = q->limits.max_discard_sectors; /* * Currently hardcoded to 1 in Linux/SCSI code.. */ dev->dev_attrib.max_unmap_block_desc_count = 1; dev->dev_attrib.unmap_granularity = q->limits.discard_granularity >> 9; dev->dev_attrib.unmap_granularity_alignment = q->limits.discard_alignment; pr_debug("IBLOCK: BLOCK Discard support available," " disabled by default\n"); } /* * Enable write same emulation for IBLOCK and use 0xFFFF as * the smaller WRITE_SAME(10) only has a two-byte block count. */ dev->dev_attrib.max_write_same_len = 0xFFFF; if (blk_queue_nonrot(q)) dev->dev_attrib.is_nonrot = 1; return 0; out_free_bioset: bioset_free(ib_dev->ibd_bio_set); ib_dev->ibd_bio_set = NULL; out: return ret; }
/** * find_valid_gpt() - Search disk for valid GPT headers and PTEs * @state * @gpt is a GPT header ptr, filled on return. * @ptes is a PTEs ptr, filled on return. * Description: Returns 1 if valid, 0 on error. * If valid, returns pointers to newly allocated GPT header and PTEs. * Validity depends on PMBR being valid (or being overridden by the * 'gpt' kernel command line option) and finding either the Primary * GPT header and PTEs valid, or the Alternate GPT header and PTEs * valid. If the Primary GPT header is not valid, the Alternate GPT header * is not checked unless the 'gpt' kernel command line option is passed. * This protects against devices which misreport their size, and forces * the user to decide to use the Alternate GPT. */ static int find_valid_gpt(struct parsed_partitions *state, gpt_header **gpt, gpt_entry **ptes) { int good_pgpt = 0, good_agpt = 0, good_pmbr = 0; gpt_header *pgpt = NULL, *agpt = NULL; gpt_entry *pptes = NULL, *aptes = NULL; legacy_mbr *legacymbr; u64 lastlba; if (!ptes) return 0; lastlba = last_lba(state->bdev); #if 0 // merged from msm8960-gb by ZTE_BOOT_JIA_20120105 jia.jia if (!force_gpt) { #else if (force_gpt) { #endif /* This will be added to the EFI Spec. per Intel after v1.02. */ legacymbr = kzalloc(sizeof (*legacymbr), GFP_KERNEL); if (legacymbr) { read_lba(state, 0, (u8 *) legacymbr, sizeof (*legacymbr)); good_pmbr = is_pmbr_valid(legacymbr); kfree(legacymbr); } if (!good_pmbr) goto fail; } good_pgpt = is_gpt_valid(state, GPT_PRIMARY_PARTITION_TABLE_LBA, &pgpt, &pptes); if (good_pgpt) good_agpt = is_gpt_valid(state, le64_to_cpu(pgpt->alternate_lba), &agpt, &aptes); if (!good_agpt && force_gpt) good_agpt = is_gpt_valid(state, lastlba, &agpt, &aptes); /* The obviously unsuccessful case */ if (!good_pgpt && !good_agpt) goto fail; compare_gpts(pgpt, agpt, lastlba); /* The good cases */ if (good_pgpt) { *gpt = pgpt; *ptes = pptes; kfree(agpt); kfree(aptes); if (!good_agpt) { printk(KERN_WARNING "Alternate GPT is invalid, " "using primary GPT.\n"); } return 1; } else if (good_agpt) { *gpt = agpt; *ptes = aptes; kfree(pgpt); kfree(pptes); printk(KERN_WARNING "Primary GPT is invalid, using alternate GPT.\n"); return 1; } fail: kfree(pgpt); kfree(agpt); kfree(pptes); kfree(aptes); *gpt = NULL; *ptes = NULL; return 0; } /** * efi_partition(struct parsed_partitions *state) * @state * * Description: called from check.c, if the disk contains GPT * partitions, sets up partition entries in the kernel. * * If the first block on the disk is a legacy MBR, * it will get handled by msdos_partition(). * If it's a Protective MBR, we'll handle it here. * * We do not create a Linux partition for GPT, but * only for the actual data partitions. * Returns: * -1 if unable to read the partition table * 0 if this isn't our partition table * 1 if successful * */ int efi_partition(struct parsed_partitions *state) { gpt_header *gpt = NULL; gpt_entry *ptes = NULL; u32 i; unsigned ssz = bdev_logical_block_size(state->bdev) / 512; u8 unparsed_guid[37]; if (!find_valid_gpt(state, &gpt, &ptes) || !gpt || !ptes) { kfree(gpt); kfree(ptes); return 0; } pr_debug("GUID Partition Table is valid! Yea!\n"); for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) { struct partition_meta_info *info; unsigned label_count = 0; unsigned label_max; u64 start = le64_to_cpu(ptes[i].starting_lba); u64 size = le64_to_cpu(ptes[i].ending_lba) - le64_to_cpu(ptes[i].starting_lba) + 1ULL; if (!is_pte_valid(&ptes[i], last_lba(state->bdev))) continue; put_partition(state, i+1, start * ssz, size * ssz); /* If this is a RAID volume, tell md */ if (!efi_guidcmp(ptes[i].partition_type_guid, PARTITION_LINUX_RAID_GUID)) state->parts[i + 1].flags = ADDPART_FLAG_RAID; info = &state->parts[i + 1].info; /* Instead of doing a manual swap to big endian, reuse the * common ASCII hex format as the interim. */ efi_guid_unparse(&ptes[i].unique_partition_guid, unparsed_guid); part_pack_uuid(unparsed_guid, info->uuid); /* Naively convert UTF16-LE to 7 bits. */ label_max = min(sizeof(info->volname) - 1, sizeof(ptes[i].partition_name)); info->volname[label_max] = 0; while (label_count < label_max) { u8 c = ptes[i].partition_name[label_count] & 0xff; if (c && !isprint(c)) c = '!'; info->volname[label_count] = c; label_count++; } state->parts[i + 1].has_info = true; } kfree(ptes); kfree(gpt); strlcat(state->pp_buf, "\n", PAGE_SIZE); return 1; }
/** * nilfs_sufile_trim_fs() - trim ioctl handle function * @sufile: inode of segment usage file * @range: fstrim_range structure * * start: First Byte to trim * len: number of Bytes to trim from start * minlen: minimum extent length in Bytes * * Decription: nilfs_sufile_trim_fs goes through all segments containing bytes * from start to start+len. start is rounded up to the next block boundary * and start+len is rounded down. For each clean segment blkdev_issue_discard * function is invoked. * * Return Value: On success, 0 is returned or negative error code, otherwise. */ int nilfs_sufile_trim_fs(struct inode *sufile, struct fstrim_range *range) { struct the_nilfs *nilfs = sufile->i_sb->s_fs_info; struct buffer_head *su_bh; struct nilfs_segment_usage *su; void *kaddr; size_t n, i, susz = NILFS_MDT(sufile)->mi_entry_size; sector_t seg_start, seg_end, start_block, end_block; sector_t start = 0, nblocks = 0; u64 segnum, segnum_end, minlen, len, max_blocks, ndiscarded = 0; int ret = 0; unsigned int sects_per_block; sects_per_block = (1 << nilfs->ns_blocksize_bits) / bdev_logical_block_size(nilfs->ns_bdev); len = range->len >> nilfs->ns_blocksize_bits; minlen = range->minlen >> nilfs->ns_blocksize_bits; max_blocks = ((u64)nilfs->ns_nsegments * nilfs->ns_blocks_per_segment); if (!len || range->start >= max_blocks << nilfs->ns_blocksize_bits) return -EINVAL; start_block = (range->start + nilfs->ns_blocksize - 1) >> nilfs->ns_blocksize_bits; /* * range->len can be very large (actually, it is set to * ULLONG_MAX by default) - truncate upper end of the range * carefully so as not to overflow. */ if (max_blocks - start_block < len) end_block = max_blocks - 1; else end_block = start_block + len - 1; segnum = nilfs_get_segnum_of_block(nilfs, start_block); segnum_end = nilfs_get_segnum_of_block(nilfs, end_block); down_read(&NILFS_MDT(sufile)->mi_sem); while (segnum <= segnum_end) { n = nilfs_sufile_segment_usages_in_block(sufile, segnum, segnum_end); ret = nilfs_sufile_get_segment_usage_block(sufile, segnum, 0, &su_bh); if (ret < 0) { if (ret != -ENOENT) goto out_sem; /* hole */ segnum += n; continue; } kaddr = kmap_atomic(su_bh->b_page, KM_USER0); su = nilfs_sufile_block_get_segment_usage(sufile, segnum, su_bh, kaddr); for (i = 0; i < n; ++i, ++segnum, su = (void *)su + susz) { if (!nilfs_segment_usage_clean(su)) continue; nilfs_get_segment_range(nilfs, segnum, &seg_start, &seg_end); if (!nblocks) { /* start new extent */ start = seg_start; nblocks = seg_end - seg_start + 1; continue; } if (start + nblocks == seg_start) { /* add to previous extent */ nblocks += seg_end - seg_start + 1; continue; } /* discard previous extent */ if (start < start_block) { nblocks -= start_block - start; start = start_block; } if (nblocks >= minlen) { kunmap_atomic(kaddr, KM_USER0); ret = compat_blkdev_issue_discard( nilfs->ns_bdev, start * sects_per_block, nblocks * sects_per_block, GFP_NOFS, 0); if (ret < 0) { put_bh(su_bh); goto out_sem; } ndiscarded += nblocks; kaddr = kmap_atomic(su_bh->b_page, KM_USER0); su = nilfs_sufile_block_get_segment_usage( sufile, segnum, su_bh, kaddr); } /* start new extent */ start = seg_start; nblocks = seg_end - seg_start + 1; } kunmap_atomic(kaddr, KM_USER0); put_bh(su_bh); } if (nblocks) { /* discard last extent */ if (start < start_block) { nblocks -= start_block - start; start = start_block; } if (start + nblocks > end_block + 1) nblocks = end_block - start + 1; if (nblocks >= minlen) { ret = compat_blkdev_issue_discard( nilfs->ns_bdev, start * sects_per_block, nblocks * sects_per_block, GFP_NOFS, 0); if (!ret) ndiscarded += nblocks; } } out_sem: up_read(&NILFS_MDT(sufile)->mi_sem); range->len = ndiscarded << nilfs->ns_blocksize_bits; return ret; }
/** * efi_partition(struct parsed_partitions *state) * @state * * Description: called from check.c, if the disk contains GPT * partitions, sets up partition entries in the kernel. * * If the first block on the disk is a legacy MBR, * it will get handled by msdos_partition(). * If it's a Protective MBR, we'll handle it here. * * We do not create a Linux partition for GPT, but * only for the actual data partitions. * Returns: * -1 if unable to read the partition table * 0 if this isn't our partition table * 1 if successful * */ int efi_partition(struct parsed_partitions *state) { char* partition_name = NULL; gpt_header *gpt = NULL; gpt_entry *ptes = NULL; u32 i; unsigned ssz = bdev_logical_block_size(state->bdev) / 512; partition_name = kzalloc(sizeof(ptes->partition_name), GFP_KERNEL); if (!partition_name) return 0; if (!find_valid_gpt(state, &gpt, &ptes) || !gpt || !ptes) { kfree(gpt); kfree(ptes); kfree(partition_name); return 0; } pr_debug("GUID Partition Table is valid! Yea!\n"); proc_create("emmc", 0666, NULL, &emmc_partition_fops); gpt_info.num_of_partitions = le32_to_cpu(gpt->num_partition_entries); gpt_info.erase_size = bdev_erase_size(state->bdev) * ssz; /* * Not certain if there is a chance this function is called again with * a different GPT. In case there is, free previously allocated memory */ kfree(gpt_info.partitions); gpt_info.partitions = kzalloc(gpt_info.num_of_partitions * sizeof(*gpt_info.partitions), GFP_KERNEL); for (i = 0; i < le32_to_cpu(gpt->num_partition_entries) && i < state->limit-1; i++) { int partition_name_len; struct partition_meta_info *info; unsigned label_count = 0; unsigned label_max; u64 start = le64_to_cpu(ptes[i].starting_lba); u64 size = le64_to_cpu(ptes[i].ending_lba) - le64_to_cpu(ptes[i].starting_lba) + 1ULL; gpt_info.partitions[i].size = size * ssz; if (!is_pte_valid(&ptes[i], last_lba(state->bdev))) continue; partition_name_len = utf16s_to_utf8s(ptes[i].partition_name, sizeof(ptes[i].partition_name), UTF16_LITTLE_ENDIAN, partition_name, sizeof(ptes[i].partition_name)); #ifdef CONFIG_APANIC_ON_MMC if(strncmp(partition_name,CONFIG_APANIC_PLABEL,partition_name_len) == 0) { apanic_partition_start = start * ssz; apanic_partition_size = size * ssz; pr_debug("apanic partition found starts at %lu \r\n", apanic_partition_start); pr_debug("apanic partition size = %lu\n", apanic_partition_size); } #endif put_partition(state, i+1, start * ssz, size * ssz); /* If this is a RAID volume, tell md */ if (!efi_guidcmp(ptes[i].partition_type_guid, PARTITION_LINUX_RAID_GUID)) state->parts[i + 1].flags = ADDPART_FLAG_RAID; info = &state->parts[i + 1].info; efi_guid_unparse(&ptes[i].unique_partition_guid, info->uuid); /* Naively convert UTF16-LE to 7 bits. */ label_max = min(sizeof(info->volname) - 1, sizeof(ptes[i].partition_name)); info->volname[label_max] = 0; while (label_count < label_max) { u8 c = ptes[i].partition_name[label_count] & 0xff; if (c && !isprint(c)) c = '!'; info->volname[label_count] = c; if (label_count <= partition_name_len) gpt_info.partitions[i].volname[label_count] = c; label_count++; } state->parts[i + 1].has_info = true; #ifdef CONFIG_APANIC_ON_MMC if(strncmp(info->volname,CONFIG_APANIC_PLABEL,label_count) == 0) { apanic_partition_start = start * ssz; pr_debug("apanic partition found starts at %lu \r\n", apanic_partition_start); } #endif } kfree(ptes); kfree(gpt); kfree(partition_name); strlcat(state->pp_buf, "\n", PAGE_SIZE); return 1; }
static void tegra_msdos_parse_extended(struct parsed_partitions *state, struct block_device *bdev, u64 mbr_offset, u64 first_sector, u64 first_size) { struct partition *p; Sector sect; unsigned char *data; u64 this_sector, this_size; int sector_size = bdev_logical_block_size(bdev) / 512; int loopct = 0; /* number of links followed without finding a data partition */ int i; this_sector = first_sector; this_size = first_size; while (1) { if (++loopct > 2) { printk(KERN_INFO "tegra_msdos_parse_extended: loopcnt>2. exit\n"); return; } printk(KERN_INFO "tegra_msdos_parse_extended: read part sector, start=%llu+%llu size=%llu\n", mbr_offset, this_sector, this_size); data = read_dev_sector(bdev, mbr_offset+this_sector, §); if (!data) { printk(KERN_INFO "tegra_msdos_parse_extended: read error. exit\n"); return; } if (!msdos_magic_present(data + 510)) { printk(KERN_INFO "tegra_msdos_parse_extended: no msdos magic. exit\n"); goto done; } p = (struct partition *) (data + 0x1be); /* * First process the data partition(s) */ for (i=0; i<4; i++, p++) { u64 offs, size, next; if (!NR_SECTS(p) || is_extended_partition(p)) continue; offs = START_SECT(p)*sector_size; size = NR_SECTS(p)*sector_size; next = this_sector + offs; if (i >= 2) { if (offs + size > this_size) continue; if (next < first_sector) continue; if (next + size > first_sector + first_size) continue; } printk(KERN_INFO "tegra_msdos_parse_extended: put_partition %d start=%llu+%llu size=%llu\n", state->next, mbr_offset, next, size); put_partition(state, state->next++, mbr_offset+next, size); loopct = 0; } printk(KERN_INFO "tegra_msdos_parse_extended: done with this sector\n"); p -= 4; for (i=0; i<4; i++, p++) if (NR_SECTS(p) && is_extended_partition(p)) { printk(KERN_INFO "tegra_msdos_parse_extended: extended part slot %d\n", i+1); break; } if (i == 4) goto done; /* nothing left to do */ this_sector = first_sector + START_SECT(p) * sector_size; this_size = NR_SECTS(p) * sector_size; put_dev_sector(sect); } done: printk(KERN_INFO "tegra_msdos_parse_extended: done\n"); put_dev_sector(sect); }
static int fsg_lun_open(struct fsg_lun *curlun, const char *filename) { int ro; struct file *filp = NULL; int rc = -EINVAL; struct inode *inode = NULL; struct backing_dev_info *bdi; loff_t size; loff_t num_sectors; loff_t min_sectors; unsigned int blkbits; unsigned int blksize; /* R/W if we can, R/O if we must */ ro = curlun->initially_ro; if (!ro) { filp = filp_open(filename, O_RDWR | O_LARGEFILE, 0); if (PTR_ERR(filp) == -EROFS || PTR_ERR(filp) == -EACCES) ro = 1; } if (ro) filp = filp_open(filename, O_RDONLY | O_LARGEFILE, 0); if (IS_ERR(filp)) { LINFO(curlun, "unable to open backing file: %s\n", filename); return PTR_ERR(filp); } if (!(filp->f_mode & FMODE_WRITE)) ro = 1; inode = file_inode(filp); if ((!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode))) { LINFO(curlun, "invalid file type: %s\n", filename); goto out; } /* * If we can't read the file, it's no good. * If we can't write the file, use it read-only. */ if (!(filp->f_op->read || filp->f_op->aio_read)) { LINFO(curlun, "file not readable: %s\n", filename); goto out; } if (!(filp->f_op->write || filp->f_op->aio_write)) ro = 1; size = i_size_read(inode->i_mapping->host); if (size < 0) { LINFO(curlun, "unable to find file size: %s\n", filename); rc = (int) size; goto out; } if (curlun->cdrom) { blksize = 2048; blkbits = 11; } else if (inode->i_bdev) { blksize = bdev_logical_block_size(inode->i_bdev); blkbits = blksize_bits(blksize); bdi = &inode->i_bdev->bd_queue->backing_dev_info; if (bdi->capabilities & BDI_CAP_STRICTLIMIT) { curlun->max_ratio = bdi->max_ratio; curlun->nofua = 1; if (bdi_set_max_ratio(bdi, uicc_ums_max_ratio)) pr_debug("%s, error in setting max_ratio\n", __func__); } } else { blksize = 512; blkbits = 9; } num_sectors = size >> blkbits; /* File size in logic-block-size blocks */ min_sectors = 1; if (curlun->cdrom) { min_sectors = 300; /* Smallest track is 300 frames */ if (num_sectors >= 256*60*75) { num_sectors = 256*60*75 - 1; LINFO(curlun, "file too big: %s\n", filename); LINFO(curlun, "using only first %d blocks\n", (int) num_sectors); } } if (num_sectors < min_sectors) { LINFO(curlun, "file too small: %s\n", filename); rc = -ETOOSMALL; goto out; } if (fsg_lun_is_open(curlun)) fsg_lun_close(curlun); curlun->blksize = blksize; curlun->blkbits = blkbits; curlun->ro = ro; curlun->filp = filp; curlun->file_length = size; curlun->num_sectors = num_sectors; LDBG(curlun, "open backing file: %s\n", filename); return 0; out: fput(filp); return rc; }
static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti, unsigned int argc, char **argv, struct dm_dev *dev) { enum sync sync = DEFAULTSYNC; struct log_c *lc; uint32_t region_size; unsigned int region_count; size_t bitset_size, buf_size; int r; char dummy; if (argc < 1 || argc > 2) { DMWARN("wrong number of arguments to dirty region log"); return -EINVAL; } if (argc > 1) { if (!strcmp(argv[1], "sync")) sync = FORCESYNC; else if (!strcmp(argv[1], "nosync")) sync = NOSYNC; else { DMWARN("unrecognised sync argument to " "dirty region log: %s", argv[1]); return -EINVAL; } } if (sscanf(argv[0], "%u%c", ®ion_size, &dummy) != 1 || !_check_region_size(ti, region_size)) { DMWARN("invalid region size %s", argv[0]); return -EINVAL; } region_count = dm_sector_div_up(ti->len, region_size); lc = kmalloc(sizeof(*lc), GFP_KERNEL); if (!lc) { DMWARN("couldn't allocate core log"); return -ENOMEM; } lc->ti = ti; lc->touched_dirtied = 0; lc->touched_cleaned = 0; lc->flush_failed = 0; lc->region_size = region_size; lc->region_count = region_count; lc->sync = sync; /* * Work out how many "unsigned long"s we need to hold the bitset. */ bitset_size = dm_round_up(region_count, sizeof(*lc->clean_bits) << BYTE_SHIFT); bitset_size >>= BYTE_SHIFT; lc->bitset_uint32_count = bitset_size / sizeof(*lc->clean_bits); /* * Disk log? */ if (!dev) { lc->clean_bits = vmalloc(bitset_size); if (!lc->clean_bits) { DMWARN("couldn't allocate clean bitset"); kfree(lc); return -ENOMEM; } lc->disk_header = NULL; } else { lc->log_dev = dev; lc->log_dev_failed = 0; lc->log_dev_flush_failed = 0; lc->header_location.bdev = lc->log_dev->bdev; lc->header_location.sector = 0; /* * Buffer holds both header and bitset. */ buf_size = dm_round_up((LOG_OFFSET << SECTOR_SHIFT) + bitset_size, bdev_logical_block_size(lc->header_location. bdev)); if (buf_size > i_size_read(dev->bdev->bd_inode)) { DMWARN("log device %s too small: need %llu bytes", dev->name, (unsigned long long)buf_size); kfree(lc); return -EINVAL; } lc->header_location.count = buf_size >> SECTOR_SHIFT; lc->io_req.mem.type = DM_IO_VMA; lc->io_req.notify.fn = NULL; lc->io_req.client = dm_io_client_create(); if (IS_ERR(lc->io_req.client)) { r = PTR_ERR(lc->io_req.client); DMWARN("couldn't allocate disk io client"); kfree(lc); return r; } lc->disk_header = vmalloc(buf_size); if (!lc->disk_header) { DMWARN("couldn't allocate disk log buffer"); dm_io_client_destroy(lc->io_req.client); kfree(lc); return -ENOMEM; } lc->io_req.mem.ptr.vma = lc->disk_header; lc->clean_bits = (void *)lc->disk_header + (LOG_OFFSET << SECTOR_SHIFT); } memset(lc->clean_bits, -1, bitset_size); lc->sync_bits = vmalloc(bitset_size); if (!lc->sync_bits) { DMWARN("couldn't allocate sync bitset"); if (!dev) vfree(lc->clean_bits); else dm_io_client_destroy(lc->io_req.client); vfree(lc->disk_header); kfree(lc); return -ENOMEM; } memset(lc->sync_bits, (sync == NOSYNC) ? -1 : 0, bitset_size); lc->sync_count = (sync == NOSYNC) ? region_count : 0; lc->recovering_bits = vzalloc(bitset_size); if (!lc->recovering_bits) { DMWARN("couldn't allocate sync bitset"); vfree(lc->sync_bits); if (!dev) vfree(lc->clean_bits); else dm_io_client_destroy(lc->io_req.client); vfree(lc->disk_header); kfree(lc); return -ENOMEM; } lc->sync_search = 0; log->context = lc; return 0; }
/* fd_create_virtdevice(): (Part of se_subsystem_api_t template) * * */ static struct se_device *fd_create_virtdevice( struct se_hba *hba, struct se_subsystem_dev *se_dev, void *p) { char *dev_p = NULL; struct se_device *dev; struct se_dev_limits dev_limits; struct queue_limits *limits; struct fd_dev *fd_dev = p; struct fd_host *fd_host = hba->hba_ptr; mm_segment_t old_fs; struct file *file; struct inode *inode = NULL; int dev_flags = 0, flags, ret = -EINVAL; memset(&dev_limits, 0, sizeof(struct se_dev_limits)); old_fs = get_fs(); set_fs(get_ds()); dev_p = getname(fd_dev->fd_dev_name); set_fs(old_fs); if (IS_ERR(dev_p)) { pr_err("getname(%s) failed: %lu\n", fd_dev->fd_dev_name, IS_ERR(dev_p)); ret = PTR_ERR(dev_p); goto fail; } /* * Use O_DSYNC by default instead of O_SYNC to forgo syncing * of pure timestamp updates. */ flags = O_RDWR | O_CREAT | O_LARGEFILE | O_DSYNC; /* * Optionally allow fd_buffered_io=1 to be enabled for people * who want use the fs buffer cache as an WriteCache mechanism. * * This means that in event of a hard failure, there is a risk * of silent data-loss if the SCSI client has *not* performed a * forced unit access (FUA) write, or issued SYNCHRONIZE_CACHE * to write-out the entire device cache. */ if (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) { pr_debug("FILEIO: Disabling O_DSYNC, using buffered FILEIO\n"); flags &= ~O_DSYNC; } file = filp_open(dev_p, flags, 0600); if (IS_ERR(file)) { pr_err("filp_open(%s) failed\n", dev_p); ret = PTR_ERR(file); goto fail; } if (!file || !file->f_dentry) { pr_err("filp_open(%s) failed\n", dev_p); goto fail; } fd_dev->fd_file = file; /* * If using a block backend with this struct file, we extract * fd_dev->fd_[block,dev]_size from struct block_device. * * Otherwise, we use the passed fd_size= from configfs */ inode = file->f_mapping->host; if (S_ISBLK(inode->i_mode)) { struct request_queue *q; unsigned long long dev_size; /* * Setup the local scope queue_limits from struct request_queue->limits * to pass into transport_add_device_to_core_hba() as struct se_dev_limits. */ q = bdev_get_queue(inode->i_bdev); limits = &dev_limits.limits; limits->logical_block_size = bdev_logical_block_size(inode->i_bdev); limits->max_hw_sectors = queue_max_hw_sectors(q); limits->max_sectors = queue_max_sectors(q); /* * Determine the number of bytes from i_size_read() minus * one (1) logical sector from underlying struct block_device */ fd_dev->fd_block_size = bdev_logical_block_size(inode->i_bdev); dev_size = (i_size_read(file->f_mapping->host) - fd_dev->fd_block_size); pr_debug("FILEIO: Using size: %llu bytes from struct" " block_device blocks: %llu logical_block_size: %d\n", dev_size, div_u64(dev_size, fd_dev->fd_block_size), fd_dev->fd_block_size); } else { if (!(fd_dev->fbd_flags & FBDF_HAS_SIZE)) { pr_err("FILEIO: Missing fd_dev_size=" " parameter, and no backing struct" " block_device\n"); goto fail; } limits = &dev_limits.limits; limits->logical_block_size = FD_BLOCKSIZE; limits->max_hw_sectors = FD_MAX_SECTORS; limits->max_sectors = FD_MAX_SECTORS; fd_dev->fd_block_size = FD_BLOCKSIZE; } dev_limits.hw_queue_depth = FD_MAX_DEVICE_QUEUE_DEPTH; dev_limits.queue_depth = FD_DEVICE_QUEUE_DEPTH; dev = transport_add_device_to_core_hba(hba, &fileio_template, se_dev, dev_flags, fd_dev, &dev_limits, "FILEIO", FD_VERSION); if (!dev) goto fail; if (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) { pr_debug("FILEIO: Forcing setting of emulate_write_cache=1" " with FDBD_HAS_BUFFERED_IO_WCE\n"); dev->se_sub_dev->se_dev_attrib.emulate_write_cache = 1; } fd_dev->fd_dev_id = fd_host->fd_host_dev_id_count++; fd_dev->fd_queue_depth = dev->queue_depth; pr_debug("CORE_FILE[%u] - Added TCM FILEIO Device ID: %u at %s," " %llu total bytes\n", fd_host->fd_host_id, fd_dev->fd_dev_id, fd_dev->fd_dev_name, fd_dev->fd_dev_size); putname(dev_p); return dev; fail: if (fd_dev->fd_file) { filp_close(fd_dev->fd_file, NULL); fd_dev->fd_file = NULL; } putname(dev_p); return ERR_PTR(ret); }
static int fd_configure_device(struct se_device *dev) { struct fd_dev *fd_dev = FD_DEV(dev); struct fd_host *fd_host = dev->se_hba->hba_ptr; struct file *file; struct inode *inode = NULL; int flags, ret = -EINVAL; if (!(fd_dev->fbd_flags & FBDF_HAS_PATH)) { pr_err("Missing fd_dev_name=\n"); return -EINVAL; } /* * Use O_DSYNC by default instead of O_SYNC to forgo syncing * of pure timestamp updates. */ flags = O_RDWR | O_CREAT | O_LARGEFILE | O_DSYNC; /* * Optionally allow fd_buffered_io=1 to be enabled for people * who want use the fs buffer cache as an WriteCache mechanism. * * This means that in event of a hard failure, there is a risk * of silent data-loss if the SCSI client has *not* performed a * forced unit access (FUA) write, or issued SYNCHRONIZE_CACHE * to write-out the entire device cache. */ if (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) { pr_debug("FILEIO: Disabling O_DSYNC, using buffered FILEIO\n"); flags &= ~O_DSYNC; } file = filp_open(fd_dev->fd_dev_name, flags, 0600); if (IS_ERR(file)) { pr_err("filp_open(%s) failed\n", fd_dev->fd_dev_name); ret = PTR_ERR(file); goto fail; } fd_dev->fd_file = file; /* * If using a block backend with this struct file, we extract * fd_dev->fd_[block,dev]_size from struct block_device. * * Otherwise, we use the passed fd_size= from configfs */ inode = file->f_mapping->host; if (S_ISBLK(inode->i_mode)) { struct request_queue *q = bdev_get_queue(inode->i_bdev); unsigned long long dev_size; fd_dev->fd_block_size = bdev_logical_block_size(inode->i_bdev); /* * Determine the number of bytes from i_size_read() minus * one (1) logical sector from underlying struct block_device */ dev_size = (i_size_read(file->f_mapping->host) - fd_dev->fd_block_size); pr_debug("FILEIO: Using size: %llu bytes from struct" " block_device blocks: %llu logical_block_size: %d\n", dev_size, div_u64(dev_size, fd_dev->fd_block_size), fd_dev->fd_block_size); /* * Check if the underlying struct block_device request_queue supports * the QUEUE_FLAG_DISCARD bit for UNMAP/WRITE_SAME in SCSI + TRIM * in ATA and we need to set TPE=1 */ if (blk_queue_discard(q)) { dev->dev_attrib.max_unmap_lba_count = q->limits.max_discard_sectors; /* * Currently hardcoded to 1 in Linux/SCSI code.. */ dev->dev_attrib.max_unmap_block_desc_count = 1; dev->dev_attrib.unmap_granularity = q->limits.discard_granularity >> 9; dev->dev_attrib.unmap_granularity_alignment = q->limits.discard_alignment; pr_debug("IFILE: BLOCK Discard support available," " disabled by default\n"); } /* * Enable write same emulation for IBLOCK and use 0xFFFF as * the smaller WRITE_SAME(10) only has a two-byte block count. */ dev->dev_attrib.max_write_same_len = 0xFFFF; if (blk_queue_nonrot(q)) dev->dev_attrib.is_nonrot = 1; } else { if (!(fd_dev->fbd_flags & FBDF_HAS_SIZE)) {
static unsigned long long iblock_emulate_read_cap_with_block_size( struct se_device *dev, struct block_device *bd, struct request_queue *q) { unsigned long long blocks_long = (div_u64(i_size_read(bd->bd_inode), bdev_logical_block_size(bd)) - 1); u32 block_size = bdev_logical_block_size(bd); if (block_size == dev->se_sub_dev->se_dev_attrib.block_size) return blocks_long; switch (block_size) { case 4096: switch (dev->se_sub_dev->se_dev_attrib.block_size) { case 2048: blocks_long <<= 1; break; case 1024: blocks_long <<= 2; break; case 512: blocks_long <<= 3; default: break; } break; case 2048: switch (dev->se_sub_dev->se_dev_attrib.block_size) { case 4096: blocks_long >>= 1; break; case 1024: blocks_long <<= 1; break; case 512: blocks_long <<= 2; break; default: break; } break; case 1024: switch (dev->se_sub_dev->se_dev_attrib.block_size) { case 4096: blocks_long >>= 2; break; case 2048: blocks_long >>= 1; break; case 512: blocks_long <<= 1; break; default: break; } break; case 512: switch (dev->se_sub_dev->se_dev_attrib.block_size) { case 4096: blocks_long >>= 3; break; case 2048: blocks_long >>= 2; break; case 1024: blocks_long >>= 1; break; default: break; } break; default: break; } return blocks_long; }
static int fsg_lun_open(struct fsg_lun *curlun, const char *filename) { int ro; struct file *filp = NULL; int rc = -EINVAL; struct inode *inode = NULL; loff_t size; loff_t num_sectors; loff_t min_sectors; unsigned int blkbits; unsigned int blksize; /* R/W if we can, R/O if we must */ ro = curlun->initially_ro; if (!ro) { filp = filp_open(filename, O_RDWR | O_LARGEFILE, 0); if (PTR_ERR(filp) == -EROFS || PTR_ERR(filp) == -EACCES) ro = 1; } if (ro) filp = filp_open(filename, O_RDONLY | O_LARGEFILE, 0); if (IS_ERR(filp)) { LINFO(curlun, "unable to open backing file: %s\n", filename); return PTR_ERR(filp); } if (!(filp->f_mode & FMODE_WRITE)) ro = 1; inode = file_inode(filp); if ((!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode))) { LINFO(curlun, "invalid file type: %s\n", filename); goto out; } /* * If we can't read the file, it's no good. * If we can't write the file, use it read-only. */ if (!(filp->f_op->read || filp->f_op->aio_read)) { LINFO(curlun, "file not readable: %s\n", filename); goto out; } if (!(filp->f_op->write || filp->f_op->aio_write)) ro = 1; size = i_size_read(inode->i_mapping->host); if (size < 0) { LINFO(curlun, "unable to find file size: %s\n", filename); rc = (int) size; goto out; } /* * curlun->blksize remains the old value when switch from cdrom to udisk * so use the same blksie in cdrom and udisk */ #ifdef CONFIG_HUAWEI_USB if (inode->i_bdev) { blksize = bdev_logical_block_size(inode->i_bdev); blkbits = blksize_bits(blksize); } else { blksize = 512; blkbits = 9; } #else if (curlun->cdrom) { blksize = 2048; blkbits = 11; } else if (inode->i_bdev) { blksize = bdev_logical_block_size(inode->i_bdev); blkbits = blksize_bits(blksize); } else { blksize = 512; blkbits = 9; } #endif num_sectors = size >> blkbits; /* File size in logic-block-size blocks */ min_sectors = 1; #ifndef CONFIG_HUAWEI_USB if (curlun->cdrom) { min_sectors = 300; /* Smallest track is 300 frames */ if (num_sectors >= 256*60*75) { num_sectors = 256*60*75 - 1; LINFO(curlun, "file too big: %s\n", filename); LINFO(curlun, "using only first %d blocks\n", (int) num_sectors); } } #endif if (num_sectors < min_sectors) { LINFO(curlun, "file too small: %s\n", filename); rc = -ETOOSMALL; goto out; } if (fsg_lun_is_open(curlun)) fsg_lun_close(curlun); curlun->blksize = blksize; curlun->blkbits = blkbits; curlun->ro = ro; curlun->filp = filp; curlun->file_length = size; curlun->num_sectors = num_sectors; LDBG(curlun, "open backing file: %s\n", filename); return 0; out: fput(filp); return rc; }
static struct se_device *iblock_create_virtdevice( struct se_hba *hba, struct se_subsystem_dev *se_dev, void *p) { struct iblock_dev *ib_dev = p; struct se_device *dev; struct se_dev_limits dev_limits; struct block_device *bd = NULL; struct request_queue *q; struct queue_limits *limits; u32 dev_flags = 0; fmode_t mode; int ret = -EINVAL; if (!ib_dev) { pr_err("Unable to locate struct iblock_dev parameter\n"); return ERR_PTR(ret); } memset(&dev_limits, 0, sizeof(struct se_dev_limits)); ib_dev->ibd_bio_set = bioset_create(IBLOCK_BIO_POOL_SIZE, 0); if (!ib_dev->ibd_bio_set) { pr_err("IBLOCK: Unable to create bioset()\n"); return ERR_PTR(-ENOMEM); } pr_debug("IBLOCK: Created bio_set()\n"); /* * iblock_check_configfs_dev_params() ensures that ib_dev->ibd_udev_path * must already have been set in order for echo 1 > $HBA/$DEV/enable to run. */ pr_debug( "IBLOCK: Claiming struct block_device: %s\n", ib_dev->ibd_udev_path); mode = FMODE_READ|FMODE_EXCL; if (!ib_dev->ibd_readonly) mode |= FMODE_WRITE; bd = blkdev_get_by_path(ib_dev->ibd_udev_path, mode, ib_dev); if (IS_ERR(bd)) { ret = PTR_ERR(bd); goto failed; } /* * Setup the local scope queue_limits from struct request_queue->limits * to pass into transport_add_device_to_core_hba() as struct se_dev_limits. */ q = bdev_get_queue(bd); limits = &dev_limits.limits; limits->logical_block_size = bdev_logical_block_size(bd); limits->max_hw_sectors = UINT_MAX; limits->max_sectors = UINT_MAX; dev_limits.hw_queue_depth = q->nr_requests; dev_limits.queue_depth = q->nr_requests; ib_dev->ibd_bd = bd; dev = transport_add_device_to_core_hba(hba, &iblock_template, se_dev, dev_flags, ib_dev, &dev_limits, "IBLOCK", IBLOCK_VERSION); if (!dev) goto failed; /* * Check if the underlying struct block_device request_queue supports * the QUEUE_FLAG_DISCARD bit for UNMAP/WRITE_SAME in SCSI + TRIM * in ATA and we need to set TPE=1 */ if (blk_queue_discard(q)) { dev->se_sub_dev->se_dev_attrib.max_unmap_lba_count = q->limits.max_discard_sectors; /* * Currently hardcoded to 1 in Linux/SCSI code.. */ dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count = 1; dev->se_sub_dev->se_dev_attrib.unmap_granularity = q->limits.discard_granularity >> 9; dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment = q->limits.discard_alignment; pr_debug("IBLOCK: BLOCK Discard support available," " disabled by default\n"); } if (blk_queue_nonrot(q)) dev->se_sub_dev->se_dev_attrib.is_nonrot = 1; return dev; failed: if (ib_dev->ibd_bio_set) { bioset_free(ib_dev->ibd_bio_set); ib_dev->ibd_bio_set = NULL; } ib_dev->ibd_bd = NULL; return ERR_PTR(ret); }
static void parse_extended(struct parsed_partitions *state, sector_t first_sector, sector_t first_size) { struct partition *p; Sector sect; unsigned char *data; sector_t this_sector, this_size; sector_t sector_size = bdev_logical_block_size(state->bdev) / 512; int loopct = 0; /* number of links followed without finding a data partition */ int i; this_sector = first_sector; this_size = first_size; while (1) { if (++loopct > 100) return; if (state->next == state->limit) return; data = read_part_sector(state, this_sector, §); if (!data) return; if (!msdos_magic_present(data + 510)) goto done; p = (struct partition *) (data + 0x1be); /* * Usually, the first entry is the real data partition, * the 2nd entry is the next extended partition, or empty, * and the 3rd and 4th entries are unused. * However, DRDOS sometimes has the extended partition as * the first entry (when the data partition is empty), * and OS/2 seems to use all four entries. */ /* * First process the data partition(s) */ for (i=0; i<4; i++, p++) { sector_t offs, size, next; if (!nr_sects(p) || is_extended_partition(p)) continue; /* Check the 3rd and 4th entries - these sometimes contain random garbage */ offs = start_sect(p)*sector_size; size = nr_sects(p)*sector_size; next = this_sector + offs; if (i >= 2) { if (offs + size > this_size) continue; if (next < first_sector) continue; if (next + size > first_sector + first_size) continue; } put_partition(state, state->next, next, size); if (SYS_IND(p) == LINUX_RAID_PARTITION) state->parts[state->next].flags = ADDPART_FLAG_RAID; loopct = 0; if (++state->next == state->limit) goto done; } /* * Next, process the (first) extended partition, if present. * (So far, there seems to be no reason to make * parse_extended() recursive and allow a tree * of extended partitions.) * It should be a link to the next logical partition. */ p -= 4; for (i=0; i<4; i++, p++) if (nr_sects(p) && is_extended_partition(p)) break; if (i == 4) goto done; /* nothing left to do */ this_sector = first_sector + start_sect(p) * sector_size; this_size = nr_sects(p) * sector_size; put_dev_sector(sect); } done: put_dev_sector(sect); }
static int fd_configure_device(struct se_device *dev) { struct fd_dev *fd_dev = FD_DEV(dev); struct fd_host *fd_host = dev->se_hba->hba_ptr; struct file *file; struct inode *inode = NULL; int flags, ret = -EINVAL; if (!(fd_dev->fbd_flags & FBDF_HAS_PATH)) { pr_err("Missing fd_dev_name=\n"); return -EINVAL; } /* * Use O_DSYNC by default instead of O_SYNC to forgo syncing * of pure timestamp updates. */ flags = O_RDWR | O_CREAT | O_LARGEFILE | O_DSYNC; /* * Optionally allow fd_buffered_io=1 to be enabled for people * who want use the fs buffer cache as an WriteCache mechanism. * * This means that in event of a hard failure, there is a risk * of silent data-loss if the SCSI client has *not* performed a * forced unit access (FUA) write, or issued SYNCHRONIZE_CACHE * to write-out the entire device cache. */ if (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) { pr_debug("FILEIO: Disabling O_DSYNC, using buffered FILEIO\n"); flags &= ~O_DSYNC; } file = filp_open(fd_dev->fd_dev_name, flags, 0600); if (IS_ERR(file)) { pr_err("filp_open(%s) failed\n", fd_dev->fd_dev_name); ret = PTR_ERR(file); goto fail; } fd_dev->fd_file = file; /* * If using a block backend with this struct file, we extract * fd_dev->fd_[block,dev]_size from struct block_device. * * Otherwise, we use the passed fd_size= from configfs */ inode = file->f_mapping->host; if (S_ISBLK(inode->i_mode)) { unsigned long long dev_size; fd_dev->fd_block_size = bdev_logical_block_size(inode->i_bdev); /* * Determine the number of bytes from i_size_read() minus * one (1) logical sector from underlying struct block_device */ dev_size = (i_size_read(file->f_mapping->host) - fd_dev->fd_block_size); pr_debug("FILEIO: Using size: %llu bytes from struct" " block_device blocks: %llu logical_block_size: %d\n", dev_size, div_u64(dev_size, fd_dev->fd_block_size), fd_dev->fd_block_size); } else { if (!(fd_dev->fbd_flags & FBDF_HAS_SIZE)) { pr_err("FILEIO: Missing fd_dev_size=" " parameter, and no backing struct" " block_device\n"); goto fail; } fd_dev->fd_block_size = FD_BLOCKSIZE; } dev->dev_attrib.hw_block_size = fd_dev->fd_block_size; dev->dev_attrib.hw_max_sectors = FD_MAX_SECTORS; dev->dev_attrib.hw_queue_depth = FD_MAX_DEVICE_QUEUE_DEPTH; if (fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) { pr_debug("FILEIO: Forcing setting of emulate_write_cache=1" " with FDBD_HAS_BUFFERED_IO_WCE\n"); dev->dev_attrib.emulate_write_cache = 1; } fd_dev->fd_dev_id = fd_host->fd_host_dev_id_count++; fd_dev->fd_queue_depth = dev->queue_depth; /* * Limit WRITE_SAME w/ UNMAP=0 emulation to 8k Number of LBAs (NoLB) * based upon struct iovec limit for vfs_writev() */ dev->dev_attrib.max_write_same_len = 0x1000; pr_debug("CORE_FILE[%u] - Added TCM FILEIO Device ID: %u at %s," " %llu total bytes\n", fd_host->fd_host_id, fd_dev->fd_dev_id, fd_dev->fd_dev_name, fd_dev->fd_dev_size); return 0; fail: if (fd_dev->fd_file) { filp_close(fd_dev->fd_file, NULL); fd_dev->fd_file = NULL; } return ret; }