]> git.sesse.net Git - bcachefs-tools-debian/blob - linux/blkdev.c
bcache in userspace; userspace fsck
[bcachefs-tools-debian] / linux / blkdev.c
1
2 #include <alloca.h>
3 #include <errno.h>
4 #include <fcntl.h>
5 #include <sys/ioctl.h>
6 #include <sys/stat.h>
7 #include <sys/types.h>
8 #include <sys/uio.h>
9 #include <unistd.h>
10
11 #include <linux/bio.h>
12 #include <linux/blkdev.h>
13 #include <linux/fs.h>
14
15 int submit_bio_wait(struct bio *bio)
16 {
17         struct iovec *iov;
18         struct bvec_iter iter;
19         struct bio_vec bv;
20         ssize_t ret;
21         unsigned i;
22
23         if (bio->bi_opf & REQ_PREFLUSH)
24                 fdatasync(bio->bi_bdev->bd_fd);
25
26         i = 0;
27         bio_for_each_segment(bv, bio, iter)
28                 i++;
29
30         iov = alloca(sizeof(*iov) * i);
31
32         i = 0;
33         bio_for_each_segment(bv, bio, iter)
34                 iov[i++] = (struct iovec) {
35                         .iov_base = page_address(bv.bv_page) + bv.bv_offset,
36                         .iov_len = bv.bv_len,
37                 };
38
39         switch (bio_op(bio)) {
40         case REQ_OP_READ:
41                 ret = preadv(bio->bi_bdev->bd_fd, iov, i,
42                              bio->bi_iter.bi_sector << 9);
43                 break;
44         case REQ_OP_WRITE:
45                 ret = pwritev(bio->bi_bdev->bd_fd, iov, i,
46                               bio->bi_iter.bi_sector << 9);
47                 break;
48         default:
49                 BUG();
50         }
51
52         if (bio->bi_opf & REQ_FUA)
53                 fdatasync(bio->bi_bdev->bd_fd);
54
55         return ret == bio->bi_iter.bi_size ? 0 : -EIO;
56 }
57
58 void generic_make_request(struct bio *bio)
59 {
60         bio->bi_error = submit_bio_wait(bio);
61         bio_endio(bio);
62 }
63
64 int blkdev_issue_discard(struct block_device *bdev,
65                          sector_t sector, sector_t nr_sects,
66                          gfp_t gfp_mask, unsigned long flags)
67 {
68         return 0;
69 }
70
71 unsigned bdev_logical_block_size(struct block_device *bdev)
72 {
73         struct stat statbuf;
74         unsigned blksize;
75         int ret;
76
77         ret = fstat(bdev->bd_fd, &statbuf);
78         BUG_ON(ret);
79
80         if (!S_ISBLK(statbuf.st_mode))
81                 return statbuf.st_blksize >> 9;
82
83         ret = ioctl(bdev->bd_fd, BLKPBSZGET, &blksize);
84         BUG_ON(ret);
85
86         return blksize >> 9;
87 }
88
89 sector_t get_capacity(struct gendisk *disk)
90 {
91         struct block_device *bdev =
92                 container_of(disk, struct block_device, __bd_disk);
93         struct stat statbuf;
94         u64 bytes;
95         int ret;
96
97         ret = fstat(bdev->bd_fd, &statbuf);
98         BUG_ON(ret);
99
100         if (!S_ISBLK(statbuf.st_mode))
101                 return statbuf.st_size >> 9;
102
103         ret = ioctl(bdev->bd_fd, BLKGETSIZE64, &bytes);
104         BUG_ON(ret);
105
106         return bytes >> 9;
107 }
108
109 void blkdev_put(struct block_device *bdev, fmode_t mode)
110 {
111         fdatasync(bdev->bd_fd);
112         close(bdev->bd_fd);
113         free(bdev);
114 }
115
116 struct block_device *blkdev_get_by_path(const char *path, fmode_t mode,
117                                         void *holder)
118 {
119         struct block_device *bdev;
120         int flags = O_DIRECT;
121
122         if ((mode & (FMODE_READ|FMODE_WRITE)) == (FMODE_READ|FMODE_WRITE))
123                 flags = O_RDWR;
124         else if (mode & FMODE_READ)
125                 flags = O_RDONLY;
126         else if (mode & FMODE_WRITE)
127                 flags = O_WRONLY;
128
129         if (mode & FMODE_EXCL)
130                 flags |= O_EXCL;
131
132         bdev = malloc(sizeof(*bdev));
133         memset(bdev, 0, sizeof(*bdev));
134
135         strncpy(bdev->name, path, sizeof(bdev->name));
136         bdev->name[sizeof(bdev->name) - 1] = '\0';
137
138         bdev->bd_fd = open(path, flags);
139         bdev->bd_holder = holder;
140         bdev->bd_disk = &bdev->__bd_disk;
141
142         BUG_ON(bdev->bd_fd < 0);
143
144         return bdev;
145 }
146
147 void bdput(struct block_device *bdev)
148 {
149         BUG();
150 }
151
152 struct block_device *lookup_bdev(const char *path)
153 {
154         return ERR_PTR(-EINVAL);
155 }