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