]> git.sesse.net Git - bcachefs-tools-debian/blob - make-bcache.c
UUIDs
[bcachefs-tools-debian] / make-bcache.c
1 #define _FILE_OFFSET_BITS       64
2 #define __USE_FILE_OFFSET64
3 #define _XOPEN_SOURCE 500
4
5 #include <fcntl.h>
6 #include <linux/fs.h>
7 #include <stdint.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <sys/ioctl.h>
12 #include <sys/types.h>
13 #include <sys/stat.h>
14 #include <unistd.h>
15 #include <uuid/uuid.h>
16
17 #include "bcache.h"
18
19 char zero[4096];
20
21 long getblocks(int fd)
22 {
23         long ret;
24         struct stat statbuf;
25         if (fstat(fd, &statbuf)) {
26                 perror("stat error\n");
27                 exit(EXIT_FAILURE);
28         }
29         ret = statbuf.st_size / 512;
30         if (S_ISBLK(statbuf.st_mode))
31                 if (ioctl(fd, BLKGETSIZE, &ret)) {
32                         perror("ioctl error");
33                         exit(EXIT_FAILURE);
34                 }
35         return ret;
36 }
37
38 long hatoi(const char *s)
39 {
40         char *e;
41         long long i = strtol(s, &e, 10);
42         switch (*e) {
43                 case 't':
44                 case 'T':
45                         i *= 1024;
46                 case 'g':
47                 case 'G':
48                         i *= 1024;
49                 case 'm':
50                 case 'M':
51                         i *= 1024;
52                 case 'k':
53                 case 'K':
54                         i *= 1024;
55         }
56         return i;
57 }
58
59 void usage()
60 {
61         printf("");
62         exit(EXIT_FAILURE);
63 }
64
65 int main(int argc, char **argv)
66 {
67         int64_t nblocks, bucketsize = 32, blocksize = 8;
68         int fd, i, c;
69         struct cache_sb sb;
70         char uuid[40];
71
72         uuid_generate(sb.uuid);
73
74         while ((c = getopt(argc, argv, "U:b:")) != -1)
75                 switch (c) {
76                 case 'b':
77                         bucketsize = hatoi(optarg) / 512;
78                         break;
79                 case 'U':
80                         if (uuid_parse(optarg, sb.uuid)) {
81                                 printf("Bad uuid\n");
82                                 exit(EXIT_FAILURE);
83                         }
84                         break;
85                 }
86
87         if (argc <= optind) {
88                 printf("Please supply a device\n");
89                 exit(EXIT_FAILURE);
90         }
91
92         fd = open(argv[optind], O_RDWR);
93         if (fd == -1) {
94                 perror("Can't open dev\n");
95                 exit(EXIT_FAILURE);
96         }
97         nblocks = getblocks(fd);
98         printf("device is %li sectors\n", nblocks);
99
100         if (bucketsize < blocksize ||
101             bucketsize > nblocks / 8) {
102                 printf("Bad bucket size %li\n", bucketsize);
103                 exit(EXIT_FAILURE);
104         }
105
106         memcpy(sb.magic, bcache_magic, 16);
107         sb.version = 0;
108         sb.block_size = blocksize;
109         sb.bucket_size = bucketsize;
110         sb.nbuckets = nblocks / sb.bucket_size;
111         uuid_unparse(sb.uuid, uuid);
112
113         do
114                 sb.first_bucket = ((--sb.nbuckets * sizeof(struct bucket_disk)) + (24 << 9)) / (sb.bucket_size << 9) + 1;
115         while ((sb.nbuckets + sb.first_bucket) * sb.bucket_size > nblocks);
116
117         sb.journal_start = sb.first_bucket;
118
119         sb.btree_root = sb.first_bucket * sb.bucket_size;
120         sb.btree_level = 0;
121
122         printf("block_size:             %u\n"
123                "bucket_size:            %u\n"
124                "journal_start:          %u\n"
125                "first_bucket:           %u\n"
126                "nbuckets:               %ju\n"
127                "UUID:                   %s\n",
128                sb.block_size,
129                sb.bucket_size,
130                sb.journal_start,
131                sb.first_bucket,
132                sb.nbuckets,
133                uuid);
134
135         /* Zero out priorities */
136         lseek(fd, 4096, SEEK_SET);
137         for (i = 8; i < sb.first_bucket * sb.bucket_size; i++)
138                 if (write(fd, zero, 512) != 512)
139                         goto err;
140
141         if (pwrite(fd, &sb, sizeof(sb), 4096) != sizeof(sb))
142                 goto err;
143
144         fsync(fd);
145         exit(EXIT_SUCCESS);
146 err:
147         perror("write error\n");
148         return 1;
149 }