]> git.sesse.net Git - bcachefs-tools-debian/blob - linux/blkdev.c
cmd_migrate
[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                 ret = fdatasync(bio->bi_bdev->bd_fd);
25                 if (ret) {
26                         fprintf(stderr, "fsync error: %s\n",
27                                 strerror(errno));
28                         return -EIO;
29                 }
30         }
31
32         i = 0;
33         bio_for_each_segment(bv, bio, iter)
34                 i++;
35
36         iov = alloca(sizeof(*iov) * i);
37
38         i = 0;
39         bio_for_each_segment(bv, bio, iter)
40                 iov[i++] = (struct iovec) {
41                         .iov_base = page_address(bv.bv_page) + bv.bv_offset,
42                         .iov_len = bv.bv_len,
43                 };
44
45         switch (bio_op(bio)) {
46         case REQ_OP_READ:
47                 ret = preadv(bio->bi_bdev->bd_fd, iov, i,
48                              bio->bi_iter.bi_sector << 9);
49                 break;
50         case REQ_OP_WRITE:
51                 ret = pwritev(bio->bi_bdev->bd_fd, iov, i,
52                               bio->bi_iter.bi_sector << 9);
53                 break;
54         default:
55                 BUG();
56         }
57
58         if (ret != bio->bi_iter.bi_size) {
59                 fprintf(stderr, "IO error: %li (%s)\n",
60                         ret, strerror(errno));
61                 return -EIO;
62         }
63
64         if (bio->bi_opf & REQ_FUA) {
65                 ret = fdatasync(bio->bi_bdev->bd_fd);
66                 if (ret) {
67                         fprintf(stderr, "fsync error: %s\n",
68                                 strerror(errno));
69                         return -EIO;
70                 }
71         }
72
73         return 0;
74 }
75
76 void generic_make_request(struct bio *bio)
77 {
78         bio->bi_error = submit_bio_wait(bio);
79         bio_endio(bio);
80 }
81
82 int blkdev_issue_discard(struct block_device *bdev,
83                          sector_t sector, sector_t nr_sects,
84                          gfp_t gfp_mask, unsigned long flags)
85 {
86         return 0;
87 }
88
89 unsigned bdev_logical_block_size(struct block_device *bdev)
90 {
91         struct stat statbuf;
92         unsigned blksize;
93         int ret;
94
95         ret = fstat(bdev->bd_fd, &statbuf);
96         BUG_ON(ret);
97
98         if (!S_ISBLK(statbuf.st_mode))
99                 return statbuf.st_blksize >> 9;
100
101         ret = ioctl(bdev->bd_fd, BLKPBSZGET, &blksize);
102         BUG_ON(ret);
103
104         return blksize >> 9;
105 }
106
107 sector_t get_capacity(struct gendisk *disk)
108 {
109         struct block_device *bdev =
110                 container_of(disk, struct block_device, __bd_disk);
111         struct stat statbuf;
112         u64 bytes;
113         int ret;
114
115         ret = fstat(bdev->bd_fd, &statbuf);
116         BUG_ON(ret);
117
118         if (!S_ISBLK(statbuf.st_mode))
119                 return statbuf.st_size >> 9;
120
121         ret = ioctl(bdev->bd_fd, BLKGETSIZE64, &bytes);
122         BUG_ON(ret);
123
124         return bytes >> 9;
125 }
126
127 void blkdev_put(struct block_device *bdev, fmode_t mode)
128 {
129         fdatasync(bdev->bd_fd);
130         close(bdev->bd_fd);
131         free(bdev);
132 }
133
134 struct block_device *blkdev_get_by_path(const char *path, fmode_t mode,
135                                         void *holder)
136 {
137         struct block_device *bdev;
138         int fd, flags = O_DIRECT;
139
140         if ((mode & (FMODE_READ|FMODE_WRITE)) == (FMODE_READ|FMODE_WRITE))
141                 flags = O_RDWR;
142         else if (mode & FMODE_READ)
143                 flags = O_RDONLY;
144         else if (mode & FMODE_WRITE)
145                 flags = O_WRONLY;
146
147         if (mode & FMODE_EXCL)
148                 flags |= O_EXCL;
149
150         fd = open(path, flags);
151         if (fd < 0)
152                 return ERR_PTR(-errno);
153
154         bdev = malloc(sizeof(*bdev));
155         memset(bdev, 0, sizeof(*bdev));
156
157         strncpy(bdev->name, path, sizeof(bdev->name));
158         bdev->name[sizeof(bdev->name) - 1] = '\0';
159
160         bdev->bd_fd     = fd;
161         bdev->bd_holder = holder;
162         bdev->bd_disk   = &bdev->__bd_disk;
163
164         return bdev;
165 }
166
167 void bdput(struct block_device *bdev)
168 {
169         BUG();
170 }
171
172 struct block_device *lookup_bdev(const char *path)
173 {
174         return ERR_PTR(-EINVAL);
175 }