/** * read_lba(): Read bytes from disk, starting at given LBA * @bdev * @lba * @buffer * @size_t * * Description: Reads @count bytes from @bdev into @buffer. * Returns number of bytes read on success, 0 on error. */ static size_t read_lba(struct block_device *bdev, u64 lba, u8 * buffer, size_t count) { size_t totalreadcount = 0; sector_t n = lba * (bdev_hardsect_size(bdev) / 512); if (!bdev || !buffer || lba > last_lba(bdev)) return 0; while (count) { int copied = 512; Sector sect; unsigned char *data = read_dev_sector(bdev, n++, §); if (!data) break; if (copied > count) copied = count; memcpy(buffer, data, copied); put_dev_sector(sect); buffer += copied; totalreadcount +=copied; count -= copied; } return totalreadcount; }
static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait) { mdk_rdev_t *rdev; struct list_head *tmp; mddev_t *mddev = bitmap->mddev; ITERATE_RDEV(mddev, rdev, tmp) if (test_bit(In_sync, &rdev->flags) && !test_bit(Faulty, &rdev->flags)) { int size = PAGE_SIZE; if (page->index == bitmap->file_pages-1) size = roundup(bitmap->last_page_size, bdev_hardsect_size(rdev->bdev)); /* Just make sure we aren't corrupting data or * metadata */ if (bitmap->offset < 0) { /* DATA BITMAP METADATA */ if (bitmap->offset + page->index * (PAGE_SIZE/512) + size/512 > 0) /* bitmap runs in to metadata */ return -EINVAL; if (rdev->data_offset + mddev->size*2 > rdev->sb_offset*2 + bitmap->offset) /* data runs in to bitmap */ return -EINVAL; } else if (rdev->sb_offset*2 < rdev->data_offset) { /* METADATA BITMAP DATA */ if (rdev->sb_offset*2 + bitmap->offset + page->index*(PAGE_SIZE/512) + size/512 > rdev->data_offset) /* bitmap runs in to data */ return -EINVAL; } else { /* DATA METADATA BITMAP - no problems */ } md_super_write(mddev, rdev, (rdev->sb_offset<<1) + bitmap->offset + page->index * (PAGE_SIZE/512), size, page); } if (wait) md_super_wait(mddev); return 0; }
/** * last_lba(): return number of last logical block of device * @bdev: block device * * Description: Returns last LBA value on success, 0 on error. * This is stored (by sd and ide-geometry) in * the part[0] entry for this disk, and is the number of * physical sectors available on the disk. */ static u64 last_lba(struct block_device *bdev) { unsigned ssz = bdev_hardsect_size(bdev) / 512; unsigned loop = 0; if (!bdev || !bdev->bd_inode) return 0; do { loop++; ssz >>= 1; } while(ssz > 1); return ((bdev->bd_inode->i_size >> 9) >> loop) - 1ULL; }
xfs_buftarg_t * xfs_alloc_buftarg( struct block_device *bdev) { xfs_buftarg_t *btp; btp = kmem_zalloc(sizeof(*btp), KM_SLEEP); btp->pbr_dev = bdev->bd_dev; btp->pbr_bdev = bdev; btp->pbr_mapping = bdev->bd_inode->i_mapping; xfs_setsize_buftarg(btp, PAGE_CACHE_SIZE, bdev_hardsect_size(bdev)); return btp; }
/* * Open/close code for raw IO. * * We just rewrite the i_mapping for the /dev/raw/rawN file descriptor to * point at the blockdev's address_space and set the file handle to use * O_DIRECT. * * Set the device's soft blocksize to the minimum possible. This gives the * finest possible alignment and has no adverse impact on performance. */ static int raw_open(struct inode *inode, struct file *filp) { const int minor = iminor(inode); struct block_device *bdev; int err; if (minor == 0) { /* It is the control device */ filp->f_op = &raw_ctl_fops; return 0; } down(&raw_mutex); /* * All we need to do on open is check that the device is bound. */ bdev = raw_devices[minor].binding; err = -ENODEV; if (!bdev) goto out; igrab(bdev->bd_inode); err = blkdev_get(bdev, filp->f_mode, 0); if (err) goto out; err = bd_claim(bdev, raw_open); if (err) goto out1; err = set_blocksize(bdev, bdev_hardsect_size(bdev)); if (err) goto out2; filp->f_flags |= O_DIRECT; filp->f_mapping = bdev->bd_inode->i_mapping; if (++raw_devices[minor].inuse == 1) filp->f_dentry->d_inode->i_mapping = bdev->bd_inode->i_mapping; filp->private_data = bdev; up(&raw_mutex); return 0; out2: bd_release(bdev); out1: blkdev_put(bdev); out: up(&raw_mutex); return err; }
/** * 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_hardsect_size(bdev) / 512; if (!find_valid_gpt(bdev, &gpt, &ptes) || !gpt || !ptes) { kfree(gpt); kfree(ptes); return 0; } Dprintk("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; /* If this is a EFI System partition, tell hotplug */ if (!efi_guidcmp(ptes[i].partition_type_guid, PARTITION_SYSTEM_GUID)) state->parts[i+1].is_efi_system_partition = 1; } kfree(ptes); kfree(gpt); printk("\n"); return 1; }
/** * alloc_read_gpt_header(): Allocates GPT header, reads into it from disk * @bdev * @lba is the Logical Block Address of the partition table * * Description: returns GPT header on success, NULL on error. Allocates * and fills a GPT header starting at @ from @bdev. * Note: remember to free gpt when finished with it. */ static gpt_header * alloc_read_gpt_header(struct block_device *bdev, u64 lba) { gpt_header *gpt; unsigned ssz = bdev_hardsect_size(bdev); if (!bdev) return NULL; gpt = kmalloc(ssz, GFP_KERNEL); if (!gpt) return NULL; memset(gpt, 0, sizeof (gpt_header)); if (read_lba(bdev, lba, (u8 *) gpt, ssz) < ssz) { kfree(gpt); gpt=NULL; return NULL; } return gpt; }
static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait) { mdk_rdev_t *rdev; struct list_head *tmp; mddev_t *mddev = bitmap->mddev; ITERATE_RDEV(mddev, rdev, tmp) if (test_bit(In_sync, &rdev->flags) && !test_bit(Faulty, &rdev->flags)) { int size = PAGE_SIZE; if (page->index == bitmap->file_pages-1) size = roundup(bitmap->last_page_size, bdev_hardsect_size(rdev->bdev)); md_super_write(mddev, rdev, (rdev->sb_offset<<1) + bitmap->offset + page->index * (PAGE_SIZE/512), size, page); } if (wait) md_super_wait(mddev); return 0; }
int msdos_partition(struct parsed_partitions *state, struct block_device *bdev) { int sector_size = bdev_hardsect_size(bdev) / 512; Sector sect; unsigned char *data; struct partition *p; int slot; data = read_dev_sector(bdev, 0, §); if (!data) return -1; if (!msdos_magic_present(data + 510)) { put_dev_sector(sect); return 0; } if (aix_magic_present(data, bdev)) { 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) { 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++) { u32 start = START_SECT(p)*sector_size; u32 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 */ put_partition(state, slot, start, size == 1 ? 1 : 2); printk(" <"); parse_extended(state, bdev, start, size); printk(" >"); continue; } put_partition(state, slot, start, size); if (SYS_IND(p) == LINUX_RAID_PARTITION) state->parts[slot].flags = 1; 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, bdev, START_SECT(p)*sector_size, NR_SECTS(p)*sector_size, slot); } put_dev_sector(sect); return 1; }
static void parse_extended(struct parsed_partitions *state, struct block_device *bdev, u32 first_sector, u32 first_size) { struct partition *p; Sector sect; unsigned char *data; u32 this_sector, this_size; int sector_size = bdev_hardsect_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 > 100) return; if (state->next == state->limit) return; data = read_dev_sector(bdev, 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++) { u32 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); }
int msdos_partition(struct parsed_partitions *state, struct block_device *bdev) { int sector_size = bdev_hardsect_size(bdev) / 512; Sector sect; unsigned char *data; struct partition *p; int slot; #ifdef HACK_PARTITION_TABLE_BOOT_IND int check_times = 0; #endif data = read_dev_sector(bdev, 0, §); if (!data) return -1; if (!msdos_magic_present(data + 510)) { put_dev_sector(sect); 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) { #ifdef HACK_PARTITION_TABLE_BOOT_IND // hack for boot_ind != 0 && boot_ind != 0x80 printk("\n[cfyeh-hack] %s(%d) partition->boot_ind = 0x%.2x (should be 0x0 or 0x80)\n", __func__, __LINE__, p->boot_ind); check_times++; #else put_dev_sector(sect); return 0; #endif } } #ifdef HACK_PARTITION_TABLE_BOOT_IND // hack for boot_ind != 0 && boot_ind != 0x80 if(check_times > 1) { printk("[cfyeh-hack] %s(%d) partition->boot_ind fail %d times !!!\n", __func__, __LINE__, check_times); put_dev_sector(sect); return 0; } #endif #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++) { u32 start = START_SECT(p)*sector_size; u32 size = NR_SECTS(p)*sector_size; if (!size) continue; if (is_extended_partition(p)) { // add to know which partition is a extended partition // by cfyeh 2007/11/13 + state->parts[slot].is_part_extended = 1; // by cfyeh 2007/11/13 - /* prevent someone doing mkfs or mkswap on an extended partition, but leave room for LILO */ put_partition(state, slot, start, size == 1 ? 1 : 2); printk(" <"); parse_extended(state, bdev, start, size); printk(" >"); continue; } put_partition(state, slot, start, size); if (SYS_IND(p) == LINUX_RAID_PARTITION) state->parts[slot].flags = 1; 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, bdev, START_SECT(p)*sector_size, NR_SECTS(p)*sector_size, slot); } put_dev_sector(sect); return 1; }
static int lab4fs_fill_super(struct super_block * sb, void * data, int silent) { struct buffer_head * bh; int blocksize = BLOCK_SIZE; unsigned long logic_sb_block; unsigned offset = 0; unsigned long sb_block = 1; struct lab4fs_super_block *es; struct lab4fs_sb_info *sbi; struct inode *root; int hblock; int err = 0; sbi = kmalloc(sizeof(*sbi), GFP_KERNEL); if (!sbi) return -ENOMEM; sb->s_fs_info = sbi; memset(sbi, 0, sizeof(*sbi)); blocksize = sb_min_blocksize(sb, BLOCK_SIZE); if (!blocksize) { LAB4ERROR("unable to set blocksize\n"); err = -EIO; goto out_fail; } /* * If the superblock doesn't start on a hardware sector boundary, * calculate the offset. */ if (blocksize != BLOCK_SIZE) { logic_sb_block = (sb_block * BLOCK_SIZE) / blocksize; offset = (sb_block * BLOCK_SIZE) % blocksize; } else { logic_sb_block = sb_block; } if (!(bh = sb_bread(sb, logic_sb_block))) { LAB4ERROR("unable to read super block\n"); goto out_fail; } es = (struct lab4fs_super_block *) (((char *)bh->b_data) + offset); sb->s_magic = le32_to_cpu(es->s_magic); if (sb->s_magic != LAB4FS_SUPER_MAGIC) { if (!silent) LAB4ERROR("VFS: Can't find lab4fs filesystem on dev %s.\n", sb->s_id); goto failed_mount; } sbi->s_sb = es; blocksize = le32_to_cpu(es->s_block_size); hblock = bdev_hardsect_size(sb->s_bdev); if (sb->s_blocksize != blocksize) { /* * Make sure the blocksize for the filesystem is larger * than the hardware sectorsize for the machine. */ if (blocksize < hblock) { LAB4ERROR("blocksize %d too small for " "device blocksize %d.\n", blocksize, hblock); goto failed_mount; } brelse (bh); sb_set_blocksize(sb, blocksize); logic_sb_block = (sb_block * BLOCK_SIZE) / blocksize; offset = (sb_block * BLOCK_SIZE) % blocksize; bh = sb_bread(sb, logic_sb_block); if (!bh) { LAB4ERROR("Can't read superblock on 2nd try.\n"); goto failed_mount; } es = (struct lab4fs_super_block *)(((char *)bh->b_data) + offset); sbi->s_sb = es; if (es->s_magic != cpu_to_le32(LAB4FS_SUPER_MAGIC)) { LAB4ERROR("Magic mismatch, very weird !\n"); goto failed_mount; } } sb->s_maxbytes = lab4fs_max_size(es); sbi->s_sbh = bh; sbi->s_log_block_size = log2(sb->s_blocksize); sbi->s_first_ino = le32_to_cpu(es->s_first_inode); sbi->s_inode_size = le32_to_cpu(es->s_inode_size); sbi->s_log_inode_size = log2(sbi->s_inode_size); sbi->s_inode_table = le32_to_cpu(es->s_inode_table); sbi->s_data_blocks = le32_to_cpu(es->s_data_blocks); sbi->s_next_generation = 0; sbi->s_free_inodes_count = le32_to_cpu(es->s_free_inodes_count); sbi->s_free_data_blocks_count = le32_to_cpu(es->s_free_data_blocks_count); sbi->s_inodes_count = le32_to_cpu(es->s_inodes_count); sbi->s_blocks_count = le32_to_cpu(es->s_blocks_count); sbi->s_inode_bitmap.nr_valid_bits = le32_to_cpu(es->s_inodes_count); sbi->s_data_bitmap.nr_valid_bits = le32_to_cpu(es->s_blocks_count) - le32_to_cpu(es->s_data_blocks); rwlock_init(&sbi->rwlock); sb->s_op = &lab4fs_super_ops; err = bitmap_setup(&sbi->s_inode_bitmap, sb, le32_to_cpu(es->s_inode_bitmap)); if (err) goto out_fail; err = bitmap_setup(&sbi->s_data_bitmap, sb, le32_to_cpu(es->s_data_bitmap)); if (err) goto out_fail; sbi->s_root_inode = le32_to_cpu(es->s_root_inode); root = iget(sb, sbi->s_root_inode); LAB4DEBUG("I can get the root inode\n"); print_inode(root); LAB4DEBUG("END\n"); sb->s_root = d_alloc_root(root); if (!sb->s_root) { iput(root); kfree(sbi); return -ENOMEM; } return 0; failed_mount: out_fail: kfree(sbi); return err; }
int msdos_partition(struct parsed_partitions *state, struct block_device *bdev) { sector_t sector_size = bdev_hardsect_size(bdev) / 512; Sector sect; unsigned char *data; struct partition *p; struct fat_boot_sector *fb; int slot; data = read_dev_sector(bdev, 0, §); if (!data) return -1; if (!msdos_magic_present(data + 510)) { put_dev_sector(sect); return 0; } if (aix_magic_present(data, bdev)) { 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, bdev, start, size); printk(" >"); continue; } put_partition(state, slot, start, size); if (SYS_IND(p) == LINUX_RAID_PARTITION) state->parts[slot].flags = 1; 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, bdev, start_sect(p)*sector_size, nr_sects(p)*sector_size, slot); } put_dev_sector(sect); return 1; }