#include #include #include #include #include #include #include #include #include #include #include int submit_bio_wait(struct bio *bio) { struct iovec *iov; struct bvec_iter iter; struct bio_vec bv; ssize_t ret; unsigned i; if (bio->bi_opf & REQ_PREFLUSH) { ret = fdatasync(bio->bi_bdev->bd_fd); if (ret) { fprintf(stderr, "fsync error: %s\n", strerror(errno)); return -EIO; } } i = 0; bio_for_each_segment(bv, bio, iter) i++; iov = alloca(sizeof(*iov) * i); i = 0; bio_for_each_segment(bv, bio, iter) iov[i++] = (struct iovec) { .iov_base = page_address(bv.bv_page) + bv.bv_offset, .iov_len = bv.bv_len, }; switch (bio_op(bio)) { case REQ_OP_READ: ret = preadv(bio->bi_bdev->bd_fd, iov, i, bio->bi_iter.bi_sector << 9); break; case REQ_OP_WRITE: ret = pwritev(bio->bi_bdev->bd_fd, iov, i, bio->bi_iter.bi_sector << 9); break; default: BUG(); } if (ret != bio->bi_iter.bi_size) { fprintf(stderr, "IO error: %li (%s)\n", ret, strerror(errno)); return -EIO; } if (bio->bi_opf & REQ_FUA) { ret = fdatasync(bio->bi_bdev->bd_fd); if (ret) { fprintf(stderr, "fsync error: %s\n", strerror(errno)); return -EIO; } } return 0; } void generic_make_request(struct bio *bio) { bio->bi_error = submit_bio_wait(bio); bio_endio(bio); } int blkdev_issue_discard(struct block_device *bdev, sector_t sector, sector_t nr_sects, gfp_t gfp_mask, unsigned long flags) { return 0; } unsigned bdev_logical_block_size(struct block_device *bdev) { struct stat statbuf; unsigned blksize; int ret; ret = fstat(bdev->bd_fd, &statbuf); BUG_ON(ret); if (!S_ISBLK(statbuf.st_mode)) return statbuf.st_blksize >> 9; ret = ioctl(bdev->bd_fd, BLKPBSZGET, &blksize); BUG_ON(ret); return blksize >> 9; } sector_t get_capacity(struct gendisk *disk) { struct block_device *bdev = container_of(disk, struct block_device, __bd_disk); struct stat statbuf; u64 bytes; int ret; ret = fstat(bdev->bd_fd, &statbuf); BUG_ON(ret); if (!S_ISBLK(statbuf.st_mode)) return statbuf.st_size >> 9; ret = ioctl(bdev->bd_fd, BLKGETSIZE64, &bytes); BUG_ON(ret); return bytes >> 9; } void blkdev_put(struct block_device *bdev, fmode_t mode) { fdatasync(bdev->bd_fd); close(bdev->bd_fd); free(bdev); } struct block_device *blkdev_get_by_path(const char *path, fmode_t mode, void *holder) { struct block_device *bdev; int fd, flags = O_DIRECT; if ((mode & (FMODE_READ|FMODE_WRITE)) == (FMODE_READ|FMODE_WRITE)) flags = O_RDWR; else if (mode & FMODE_READ) flags = O_RDONLY; else if (mode & FMODE_WRITE) flags = O_WRONLY; if (mode & FMODE_EXCL) flags |= O_EXCL; fd = open(path, flags); if (fd < 0) return ERR_PTR(-errno); bdev = malloc(sizeof(*bdev)); memset(bdev, 0, sizeof(*bdev)); strncpy(bdev->name, path, sizeof(bdev->name)); bdev->name[sizeof(bdev->name) - 1] = '\0'; bdev->bd_fd = fd; bdev->bd_holder = holder; bdev->bd_disk = &bdev->__bd_disk; return bdev; } void bdput(struct block_device *bdev) { BUG(); } struct block_device *lookup_bdev(const char *path) { return ERR_PTR(-EINVAL); }