]> git.sesse.net Git - bcachefs-tools-debian/blob - bcache.c
Update for bcache superblock changes
[bcachefs-tools-debian] / bcache.c
1 #define _GNU_SOURCE
2
3 #include <ctype.h>
4 #include <errno.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <stdint.h>
8 #include <fcntl.h>
9 #include <inttypes.h>
10 #include <getopt.h>
11 #include <limits.h>
12 #include <linux/fs.h>
13 #include <stdbool.h>
14 #include <string.h>
15 #include <sys/ioctl.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <dirent.h>
19 #include <unistd.h>
20 #include <uuid/uuid.h>
21 #include <blkid.h>
22
23 #include "bcache.h"
24
25 #define __KERNEL__
26 #include <linux/bcache-ioctl.h>
27 #undef __KERNEL__
28
29 const char * const cache_state[] = {
30         "active",
31         "ro",
32         "failed",
33         "spare",
34         NULL
35 };
36
37 const char * const replacement_policies[] = {
38         "lru",
39         "fifo",
40         "random",
41         NULL
42 };
43
44 const char * const csum_types[] = {
45         "none",
46         "crc32c",
47         "crc64",
48         NULL
49 };
50
51 const char * const bdev_cache_mode[] = {
52         "writethrough",
53         "writeback",
54         "writearound",
55         "none",
56         NULL
57 };
58
59 const char * const bdev_state[] = {
60         "detached",
61         "clean",
62         "dirty",
63         "inconsistent",
64         NULL
65 };
66
67 char *skip_spaces(const char *str)
68 {
69         while (isspace(*str))
70                 ++str;
71         return (char *)str;
72 }
73
74 char *strim(char *s)
75 {
76         size_t size;
77         char *end;
78
79         s = skip_spaces(s);
80         size = strlen(s);
81         if (!size)
82                 return s;
83
84         end = s + size - 1;
85         while (end >= s && isspace(*end))
86                 end--;
87         *(end + 1) = '\0';
88
89         return s;
90 }
91
92 ssize_t read_string_list(const char *buf, const char * const list[])
93 {
94         size_t i;
95         char *s, *d = strdup(buf);
96         if (!d)
97                 return -ENOMEM;
98
99         s = strim(d);
100
101         for (i = 0; list[i]; i++)
102                 if (!strcmp(list[i], s))
103                         break;
104
105         free(d);
106
107         if (!list[i])
108                 return -EINVAL;
109
110         return i;
111 }
112
113 ssize_t read_string_list_or_die(const char *opt, const char * const list[],
114                                 const char *msg)
115 {
116         ssize_t v = read_string_list(opt, list);
117         if (v < 0) {
118                 fprintf(stderr, "Bad %s %s\n", msg, opt);
119                 exit(EXIT_FAILURE);
120
121         }
122
123         return v;
124 }
125
126 void print_string_list(const char * const list[], size_t selected)
127 {
128         size_t i;
129
130         for (i = 0; list[i]; i++) {
131                 if (i)
132                         putchar(' ');
133                 printf(i == selected ? "[%s] ": "%s", list[i]);
134         }
135 }
136
137 /*
138  * This is the CRC-32C table
139  * Generated with:
140  * width = 32 bits
141  * poly = 0x1EDC6F41
142  * reflect input bytes = true
143  * reflect output bytes = true
144  */
145
146 static const u32 crc32c_table[256] = {
147         0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
148         0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
149         0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
150         0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
151         0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
152         0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
153         0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
154         0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
155         0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
156         0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
157         0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
158         0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
159         0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
160         0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
161         0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
162         0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
163         0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
164         0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
165         0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
166         0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
167         0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
168         0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
169         0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
170         0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
171         0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
172         0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
173         0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
174         0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
175         0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
176         0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
177         0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
178         0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
179         0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
180         0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
181         0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
182         0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
183         0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
184         0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
185         0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
186         0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
187         0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
188         0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
189         0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
190         0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
191         0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
192         0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
193         0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
194         0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
195         0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
196         0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
197         0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
198         0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
199         0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
200         0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
201         0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
202         0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
203         0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
204         0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
205         0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
206         0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
207         0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
208         0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
209         0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
210         0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L
211 };
212
213 /*
214  * Steps through buffer one byte at at time, calculates reflected
215  * crc using table.
216  */
217
218 static u32 crc32c(u32 crc, unsigned char const *data, size_t length)
219 {
220         while (length--)
221                 crc =
222                     crc32c_table[(crc ^ *data++) & 0xFFL] ^ (crc >> 8);
223         return crc;
224 }
225
226 /*
227  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group (Any
228  * use permitted, subject to terms of PostgreSQL license; see.)
229
230  * If we have a 64-bit integer type, then a 64-bit CRC looks just like the
231  * usual sort of implementation. (See Ross Williams' excellent introduction
232  * A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS, available from
233  * ftp://ftp.rocksoft.com/papers/crc_v3.txt or several other net sites.)
234  * If we have no working 64-bit type, then fake it with two 32-bit registers.
235  *
236  * The present implementation is a normal (not "reflected", in Williams'
237  * terms) 64-bit CRC, using initial all-ones register contents and a final
238  * bit inversion. The chosen polynomial is borrowed from the DLT1 spec
239  * (ECMA-182, available from http://www.ecma.ch/ecma1/STAND/ECMA-182.HTM):
240  *
241  * x^64 + x^62 + x^57 + x^55 + x^54 + x^53 + x^52 + x^47 + x^46 + x^45 +
242  * x^40 + x^39 + x^38 + x^37 + x^35 + x^33 + x^32 + x^31 + x^29 + x^27 +
243  * x^24 + x^23 + x^22 + x^21 + x^19 + x^17 + x^13 + x^12 + x^10 + x^9 +
244  * x^7 + x^4 + x + 1
245 */
246
247 static const uint64_t crc_table[256] = {
248         0x0000000000000000ULL, 0x42F0E1EBA9EA3693ULL, 0x85E1C3D753D46D26ULL,
249         0xC711223CFA3E5BB5ULL, 0x493366450E42ECDFULL, 0x0BC387AEA7A8DA4CULL,
250         0xCCD2A5925D9681F9ULL, 0x8E224479F47CB76AULL, 0x9266CC8A1C85D9BEULL,
251         0xD0962D61B56FEF2DULL, 0x17870F5D4F51B498ULL, 0x5577EEB6E6BB820BULL,
252         0xDB55AACF12C73561ULL, 0x99A54B24BB2D03F2ULL, 0x5EB4691841135847ULL,
253         0x1C4488F3E8F96ED4ULL, 0x663D78FF90E185EFULL, 0x24CD9914390BB37CULL,
254         0xE3DCBB28C335E8C9ULL, 0xA12C5AC36ADFDE5AULL, 0x2F0E1EBA9EA36930ULL,
255         0x6DFEFF5137495FA3ULL, 0xAAEFDD6DCD770416ULL, 0xE81F3C86649D3285ULL,
256         0xF45BB4758C645C51ULL, 0xB6AB559E258E6AC2ULL, 0x71BA77A2DFB03177ULL,
257         0x334A9649765A07E4ULL, 0xBD68D2308226B08EULL, 0xFF9833DB2BCC861DULL,
258         0x388911E7D1F2DDA8ULL, 0x7A79F00C7818EB3BULL, 0xCC7AF1FF21C30BDEULL,
259         0x8E8A101488293D4DULL, 0x499B3228721766F8ULL, 0x0B6BD3C3DBFD506BULL,
260         0x854997BA2F81E701ULL, 0xC7B97651866BD192ULL, 0x00A8546D7C558A27ULL,
261         0x4258B586D5BFBCB4ULL, 0x5E1C3D753D46D260ULL, 0x1CECDC9E94ACE4F3ULL,
262         0xDBFDFEA26E92BF46ULL, 0x990D1F49C77889D5ULL, 0x172F5B3033043EBFULL,
263         0x55DFBADB9AEE082CULL, 0x92CE98E760D05399ULL, 0xD03E790CC93A650AULL,
264         0xAA478900B1228E31ULL, 0xE8B768EB18C8B8A2ULL, 0x2FA64AD7E2F6E317ULL,
265         0x6D56AB3C4B1CD584ULL, 0xE374EF45BF6062EEULL, 0xA1840EAE168A547DULL,
266         0x66952C92ECB40FC8ULL, 0x2465CD79455E395BULL, 0x3821458AADA7578FULL,
267         0x7AD1A461044D611CULL, 0xBDC0865DFE733AA9ULL, 0xFF3067B657990C3AULL,
268         0x711223CFA3E5BB50ULL, 0x33E2C2240A0F8DC3ULL, 0xF4F3E018F031D676ULL,
269         0xB60301F359DBE0E5ULL, 0xDA050215EA6C212FULL, 0x98F5E3FE438617BCULL,
270         0x5FE4C1C2B9B84C09ULL, 0x1D14202910527A9AULL, 0x93366450E42ECDF0ULL,
271         0xD1C685BB4DC4FB63ULL, 0x16D7A787B7FAA0D6ULL, 0x5427466C1E109645ULL,
272         0x4863CE9FF6E9F891ULL, 0x0A932F745F03CE02ULL, 0xCD820D48A53D95B7ULL,
273         0x8F72ECA30CD7A324ULL, 0x0150A8DAF8AB144EULL, 0x43A04931514122DDULL,
274         0x84B16B0DAB7F7968ULL, 0xC6418AE602954FFBULL, 0xBC387AEA7A8DA4C0ULL,
275         0xFEC89B01D3679253ULL, 0x39D9B93D2959C9E6ULL, 0x7B2958D680B3FF75ULL,
276         0xF50B1CAF74CF481FULL, 0xB7FBFD44DD257E8CULL, 0x70EADF78271B2539ULL,
277         0x321A3E938EF113AAULL, 0x2E5EB66066087D7EULL, 0x6CAE578BCFE24BEDULL,
278         0xABBF75B735DC1058ULL, 0xE94F945C9C3626CBULL, 0x676DD025684A91A1ULL,
279         0x259D31CEC1A0A732ULL, 0xE28C13F23B9EFC87ULL, 0xA07CF2199274CA14ULL,
280         0x167FF3EACBAF2AF1ULL, 0x548F120162451C62ULL, 0x939E303D987B47D7ULL,
281         0xD16ED1D631917144ULL, 0x5F4C95AFC5EDC62EULL, 0x1DBC74446C07F0BDULL,
282         0xDAAD56789639AB08ULL, 0x985DB7933FD39D9BULL, 0x84193F60D72AF34FULL,
283         0xC6E9DE8B7EC0C5DCULL, 0x01F8FCB784FE9E69ULL, 0x43081D5C2D14A8FAULL,
284         0xCD2A5925D9681F90ULL, 0x8FDAB8CE70822903ULL, 0x48CB9AF28ABC72B6ULL,
285         0x0A3B7B1923564425ULL, 0x70428B155B4EAF1EULL, 0x32B26AFEF2A4998DULL,
286         0xF5A348C2089AC238ULL, 0xB753A929A170F4ABULL, 0x3971ED50550C43C1ULL,
287         0x7B810CBBFCE67552ULL, 0xBC902E8706D82EE7ULL, 0xFE60CF6CAF321874ULL,
288         0xE224479F47CB76A0ULL, 0xA0D4A674EE214033ULL, 0x67C58448141F1B86ULL,
289         0x253565A3BDF52D15ULL, 0xAB1721DA49899A7FULL, 0xE9E7C031E063ACECULL,
290         0x2EF6E20D1A5DF759ULL, 0x6C0603E6B3B7C1CAULL, 0xF6FAE5C07D3274CDULL,
291         0xB40A042BD4D8425EULL, 0x731B26172EE619EBULL, 0x31EBC7FC870C2F78ULL,
292         0xBFC9838573709812ULL, 0xFD39626EDA9AAE81ULL, 0x3A28405220A4F534ULL,
293         0x78D8A1B9894EC3A7ULL, 0x649C294A61B7AD73ULL, 0x266CC8A1C85D9BE0ULL,
294         0xE17DEA9D3263C055ULL, 0xA38D0B769B89F6C6ULL, 0x2DAF4F0F6FF541ACULL,
295         0x6F5FAEE4C61F773FULL, 0xA84E8CD83C212C8AULL, 0xEABE6D3395CB1A19ULL,
296         0x90C79D3FEDD3F122ULL, 0xD2377CD44439C7B1ULL, 0x15265EE8BE079C04ULL,
297         0x57D6BF0317EDAA97ULL, 0xD9F4FB7AE3911DFDULL, 0x9B041A914A7B2B6EULL,
298         0x5C1538ADB04570DBULL, 0x1EE5D94619AF4648ULL, 0x02A151B5F156289CULL,
299         0x4051B05E58BC1E0FULL, 0x87409262A28245BAULL, 0xC5B073890B687329ULL,
300         0x4B9237F0FF14C443ULL, 0x0962D61B56FEF2D0ULL, 0xCE73F427ACC0A965ULL,
301         0x8C8315CC052A9FF6ULL, 0x3A80143F5CF17F13ULL, 0x7870F5D4F51B4980ULL,
302         0xBF61D7E80F251235ULL, 0xFD913603A6CF24A6ULL, 0x73B3727A52B393CCULL,
303         0x31439391FB59A55FULL, 0xF652B1AD0167FEEAULL, 0xB4A25046A88DC879ULL,
304         0xA8E6D8B54074A6ADULL, 0xEA16395EE99E903EULL, 0x2D071B6213A0CB8BULL,
305         0x6FF7FA89BA4AFD18ULL, 0xE1D5BEF04E364A72ULL, 0xA3255F1BE7DC7CE1ULL,
306         0x64347D271DE22754ULL, 0x26C49CCCB40811C7ULL, 0x5CBD6CC0CC10FAFCULL,
307         0x1E4D8D2B65FACC6FULL, 0xD95CAF179FC497DAULL, 0x9BAC4EFC362EA149ULL,
308         0x158E0A85C2521623ULL, 0x577EEB6E6BB820B0ULL, 0x906FC95291867B05ULL,
309         0xD29F28B9386C4D96ULL, 0xCEDBA04AD0952342ULL, 0x8C2B41A1797F15D1ULL,
310         0x4B3A639D83414E64ULL, 0x09CA82762AAB78F7ULL, 0x87E8C60FDED7CF9DULL,
311         0xC51827E4773DF90EULL, 0x020905D88D03A2BBULL, 0x40F9E43324E99428ULL,
312         0x2CFFE7D5975E55E2ULL, 0x6E0F063E3EB46371ULL, 0xA91E2402C48A38C4ULL,
313         0xEBEEC5E96D600E57ULL, 0x65CC8190991CB93DULL, 0x273C607B30F68FAEULL,
314         0xE02D4247CAC8D41BULL, 0xA2DDA3AC6322E288ULL, 0xBE992B5F8BDB8C5CULL,
315         0xFC69CAB42231BACFULL, 0x3B78E888D80FE17AULL, 0x7988096371E5D7E9ULL,
316         0xF7AA4D1A85996083ULL, 0xB55AACF12C735610ULL, 0x724B8ECDD64D0DA5ULL,
317         0x30BB6F267FA73B36ULL, 0x4AC29F2A07BFD00DULL, 0x08327EC1AE55E69EULL,
318         0xCF235CFD546BBD2BULL, 0x8DD3BD16FD818BB8ULL, 0x03F1F96F09FD3CD2ULL,
319         0x41011884A0170A41ULL, 0x86103AB85A2951F4ULL, 0xC4E0DB53F3C36767ULL,
320         0xD8A453A01B3A09B3ULL, 0x9A54B24BB2D03F20ULL, 0x5D45907748EE6495ULL,
321         0x1FB5719CE1045206ULL, 0x919735E51578E56CULL, 0xD367D40EBC92D3FFULL,
322         0x1476F63246AC884AULL, 0x568617D9EF46BED9ULL, 0xE085162AB69D5E3CULL,
323         0xA275F7C11F7768AFULL, 0x6564D5FDE549331AULL, 0x279434164CA30589ULL,
324         0xA9B6706FB8DFB2E3ULL, 0xEB46918411358470ULL, 0x2C57B3B8EB0BDFC5ULL,
325         0x6EA7525342E1E956ULL, 0x72E3DAA0AA188782ULL, 0x30133B4B03F2B111ULL,
326         0xF7021977F9CCEAA4ULL, 0xB5F2F89C5026DC37ULL, 0x3BD0BCE5A45A6B5DULL,
327         0x79205D0E0DB05DCEULL, 0xBE317F32F78E067BULL, 0xFCC19ED95E6430E8ULL,
328         0x86B86ED5267CDBD3ULL, 0xC4488F3E8F96ED40ULL, 0x0359AD0275A8B6F5ULL,
329         0x41A94CE9DC428066ULL, 0xCF8B0890283E370CULL, 0x8D7BE97B81D4019FULL,
330         0x4A6ACB477BEA5A2AULL, 0x089A2AACD2006CB9ULL, 0x14DEA25F3AF9026DULL,
331         0x562E43B4931334FEULL, 0x913F6188692D6F4BULL, 0xD3CF8063C0C759D8ULL,
332         0x5DEDC41A34BBEEB2ULL, 0x1F1D25F19D51D821ULL, 0xD80C07CD676F8394ULL,
333         0x9AFCE626CE85B507ULL
334 };
335
336 static uint64_t bch_crc64_update(uint64_t crc, const void *_data, size_t len)
337 {
338         const unsigned char *data = _data;
339
340         while (len--) {
341                 int i = ((int) (crc >> 56) ^ *data++) & 0xFF;
342                 crc = crc_table[i] ^ (crc << 8);
343         }
344
345         return crc;
346 }
347
348 static uint64_t bch_checksum_update(unsigned type, uint64_t crc, const void *data, size_t len)
349 {
350         switch (type) {
351         case BCH_CSUM_NONE:
352                 return 0;
353         case BCH_CSUM_CRC32C:
354                 return crc32c(crc, data, len);
355         case BCH_CSUM_CRC64:
356                 return bch_crc64_update(crc, data, len);
357         default:
358                 fprintf(stderr, "Unknown checksum type %u\n", type);
359                 exit(EXIT_FAILURE);
360         }
361 }
362
363 uint64_t bch_checksum(unsigned type, const void *data, size_t len)
364 {
365         uint64_t crc = 0xffffffffffffffffULL;
366
367         crc = bch_checksum_update(type, crc, data, len);
368
369         return crc ^ 0xffffffffffffffffULL;
370 }
371
372 uint64_t getblocks(int fd)
373 {
374         uint64_t ret;
375         struct stat statbuf;
376         if (fstat(fd, &statbuf)) {
377                 perror("getblocks: stat error\n");
378                 exit(EXIT_FAILURE);
379         }
380         ret = statbuf.st_size / 512;
381         if (S_ISBLK(statbuf.st_mode))
382                 if (ioctl(fd, BLKGETSIZE, &ret)) {
383                         perror("ioctl error getting blksize");
384                         exit(EXIT_FAILURE);
385                 }
386         return ret;
387 }
388
389 uint64_t hatoi(const char *s)
390 {
391         char *e;
392         long long i = strtoll(s, &e, 10);
393         switch (*e) {
394                 case 't':
395                 case 'T':
396                         i *= 1024;
397                 case 'g':
398                 case 'G':
399                         i *= 1024;
400                 case 'm':
401                 case 'M':
402                         i *= 1024;
403                 case 'k':
404                 case 'K':
405                         i *= 1024;
406         }
407         return i;
408 }
409
410 unsigned hatoi_validate(const char *s, const char *msg)
411 {
412         uint64_t v = hatoi(s);
413
414         if (v & (v - 1)) {
415                 fprintf(stderr, "%s must be a power of two\n", msg);
416                 exit(EXIT_FAILURE);
417         }
418
419         v /= 512;
420
421         if (v > USHRT_MAX) {
422                 fprintf(stderr, "%s too large\n", msg);
423                 exit(EXIT_FAILURE);
424         }
425
426         if (!v) {
427                 fprintf(stderr, "%s too small\n", msg);
428                 exit(EXIT_FAILURE);
429         }
430
431         return v;
432 }
433
434 static void do_write_sb(int fd, struct cache_sb *sb)
435 {
436         char zeroes[SB_START] = {0};
437         size_t bytes = ((void *) __bset_bkey_last(sb)) - (void *) sb;
438
439         /* Zero start of disk */
440         if (pwrite(fd, zeroes, SB_START, 0) != SB_START) {
441                 perror("write error trying to zero start of disk\n");
442                 exit(EXIT_FAILURE);
443         }
444         /* Write superblock */
445         if (pwrite(fd, sb, bytes, SB_START) != bytes) {
446                 perror("write error trying to write superblock\n");
447                 exit(EXIT_FAILURE);
448         }
449
450         fsync(fd);
451         close(fd);
452 }
453
454 void write_backingdev_sb(int fd, unsigned block_size, unsigned *bucket_sizes,
455                          unsigned mode, uint64_t data_offset, const char *label,
456                          uuid_le user_uuid, uuid_le set_uuid)
457 {
458         char uuid_str[40], set_uuid_str[40];
459         struct cache_sb sb;
460
461         memset(&sb, 0, sizeof(struct cache_sb));
462
463         sb.offset       = SB_SECTOR;
464         sb.version      = BCACHE_SB_VERSION_BDEV;
465         sb.magic        = BCACHE_MAGIC;
466         uuid_generate(sb.disk_uuid.b);
467         sb.user_uuid    = user_uuid;
468         sb.set_uuid     = set_uuid;
469         sb.block_size   = block_size;
470
471         uuid_unparse(sb.disk_uuid.b, uuid_str);
472         uuid_unparse(sb.set_uuid.b, set_uuid_str);
473         if (label)
474                 memcpy(sb.label, label, SB_LABEL_SIZE);
475
476         SET_BDEV_CACHE_MODE(&sb, mode);
477
478         if (data_offset != BDEV_DATA_START_DEFAULT) {
479                 sb.version = BCACHE_SB_VERSION_BDEV_WITH_OFFSET;
480                 sb.bdev_data_offset = data_offset;
481         }
482
483         sb.csum = csum_set(&sb, BCH_CSUM_CRC64);
484
485         printf("UUID:                   %s\n"
486                "Set UUID:               %s\n"
487                "version:                %u\n"
488                "block_size:             %u\n"
489                "data_offset:            %ju\n",
490                uuid_str, set_uuid_str,
491                (unsigned) sb.version,
492                sb.block_size,
493                data_offset);
494
495         do_write_sb(fd, &sb);
496 }
497
498 int dev_open(const char *dev, bool wipe_bcache)
499 {
500         struct cache_sb sb;
501         blkid_probe pr;
502         int fd;
503         char err[MAX_PATH];
504
505         if ((fd = open(dev, O_RDWR|O_EXCL)) == -1) {
506                 sprintf(err, "Can't open dev %s: %s\n", dev, strerror(errno));
507                 goto err;
508         }
509
510         if (pread(fd, &sb, sizeof(sb), SB_START) != sizeof(sb)) {
511                 sprintf(err, "Failed to read superblock");
512                 goto err;
513         }
514
515         if (!memcmp(&sb.magic, &BCACHE_MAGIC, 16) && !wipe_bcache) {
516                 sprintf(err, "Already a bcache device on %s, "
517                         "overwrite with --wipe-bcache\n", dev);
518                 goto err;
519         }
520
521         if (!(pr = blkid_new_probe())) {
522                 sprintf(err, "Failed to create a new probe");
523                 goto err;
524         }
525         if (blkid_probe_set_device(pr, fd, 0, 0)) {
526                 sprintf(err, "failed to set probe to device");
527                 goto err;
528         }
529         /* enable ptable probing; superblock probing is enabled by default */
530         if (blkid_probe_enable_partitions(pr, true)) {
531                 sprintf(err, "Failed to enable partitions on probe");
532                 goto err;
533         }
534         if (!blkid_do_probe(pr)) {
535                 /* XXX wipefs doesn't know how to remove partition tables */
536                 sprintf(err, "Device %s already has a non-bcache superblock, "
537                         "remove it using wipefs and wipefs -a\n", dev);
538                 goto err;
539         }
540
541         return fd;
542
543         err:
544                 fprintf(stderr, "dev_open failed with: %s", err);
545                 exit(EXIT_FAILURE);
546 }
547
548 static unsigned min_bucket_size(int num_bucket_sizes, unsigned *bucket_sizes)
549 {
550         int i;
551         unsigned min = bucket_sizes[0];
552
553         for (i = 0; i < num_bucket_sizes; i++)
554                 min = bucket_sizes[i] < min ? bucket_sizes[i] : min;
555
556         return min;
557 }
558
559 void write_cache_sbs(int *fds, struct cache_sb *sb,
560                      unsigned block_size, unsigned *bucket_sizes,
561                      int num_bucket_sizes)
562 {
563         char uuid_str[40], set_uuid_str[40];
564         size_t i;
565         unsigned min_size = min_bucket_size(num_bucket_sizes, bucket_sizes);
566
567         sb->offset      = SB_SECTOR;
568         sb->version     = BCACHE_SB_VERSION_CDEV_V3;
569         sb->magic       = BCACHE_MAGIC;
570         sb->block_size  = block_size;
571         sb->u64s        = bch_journal_buckets_offset(sb);
572
573         /*
574          * don't have a userspace crc32c implementation handy, just always use
575          * crc64
576          */
577         SET_CACHE_SB_CSUM_TYPE(sb, BCH_CSUM_CRC64);
578
579         for (i = 0; i < sb->nr_in_set; i++) {
580                 struct cache_member *m = sb->members + i;
581
582                 if (num_bucket_sizes <= 1) {
583                         m->bucket_size = bucket_sizes[0];
584                 } else {
585                         if (!bucket_sizes[i]) {
586                                 printf("No bucket size specified for cache %d,"
587                                        " using the default of %d",
588                                        i, bucket_sizes[0]);
589                                 m->bucket_size = bucket_sizes[0];
590                         } else {
591                                 m->bucket_size  = bucket_sizes[i];
592                         }
593                 }
594
595                 m->nbuckets             = getblocks(fds[i]) / m->bucket_size;
596                 m->first_bucket         = (23 / m->bucket_size) + 1;
597
598                 if (m->nbuckets < 1 << 7) {
599                         fprintf(stderr, "Not enough buckets: %llu, need %u\n",
600                                 m->nbuckets, 1 << 7);
601                         exit(EXIT_FAILURE);
602                 }
603         }
604
605         for (i = 0; i < sb->nr_in_set; i++) {
606                 struct cache_member *m = sb->members + i;
607
608                 SET_CACHE_BTREE_NODE_SIZE(sb, min_size);
609
610
611                 sb->disk_uuid = m->uuid;
612                 sb->nr_this_dev         = i;
613
614                 sb->csum = csum_set(sb, CACHE_SB_CSUM_TYPE(sb));
615
616                 uuid_unparse(sb->disk_uuid.b, uuid_str);
617                 uuid_unparse(sb->set_uuid.b, set_uuid_str);
618                 printf("UUID:                   %s\n"
619                        "Set UUID:               %s\n"
620                        "version:                %u\n"
621                        "nbuckets:               %llu\n"
622                        "block_size:             %u\n"
623                        "bucket_size:            %u\n"
624                        "nr_in_set:              %u\n"
625                        "nr_this_dev:            %u\n"
626                        "first_bucket:           %u\n",
627                        uuid_str, set_uuid_str,
628                        (unsigned) sb->version,
629                        m->nbuckets,
630                        sb->block_size,
631                        m->bucket_size,
632                        sb->nr_in_set,
633                        sb->nr_this_dev,
634                        m->first_bucket);
635
636                 do_write_sb(fds[i], sb);
637         }
638 }
639
640 void next_cache_device(struct cache_sb *sb,
641                               unsigned replication_set,
642                               int tier,
643                               unsigned replacement_policy,
644                               bool discard)
645 {
646         struct cache_member *m = sb->members + sb->nr_in_set;
647
648         SET_CACHE_REPLICATION_SET(m, replication_set);
649         SET_CACHE_TIER(m, tier);
650         SET_CACHE_REPLACEMENT(m, replacement_policy);
651         SET_CACHE_DISCARD(m, discard);
652         uuid_generate(m->uuid.b);
653
654         sb->nr_in_set++;
655 }
656
657 unsigned get_blocksize(const char *path)
658 {
659         struct stat statbuf;
660
661         if (stat(path, &statbuf)) {
662                 fprintf(stderr, "Error statting %s: %s\n",
663                         path, strerror(errno));
664                 exit(EXIT_FAILURE);
665         }
666
667         if (S_ISBLK(statbuf.st_mode)) {
668                 /* check IO limits:
669                  * BLKALIGNOFF: alignment_offset
670                  * BLKPBSZGET: physical_block_size
671                  * BLKSSZGET: logical_block_size
672                  * BLKIOMIN: minimum_io_size
673                  * BLKIOOPT: optimal_io_size
674                  *
675                  * It may be tempting to use physical_block_size,
676                  * or even minimum_io_size.
677                  * But to be as transparent as possible,
678                  * we want to use logical_block_size.
679                  */
680                 unsigned int logical_block_size;
681                 int fd = open(path, O_RDONLY);
682
683                 if (fd < 0) {
684                         fprintf(stderr, "open(%s) failed: %m\n", path);
685                         exit(EXIT_FAILURE);
686                 }
687                 if (ioctl(fd, BLKSSZGET, &logical_block_size)) {
688                         fprintf(stderr, "ioctl(%s, BLKSSZGET) failed: %m\n", path);
689                         exit(EXIT_FAILURE);
690                 }
691                 close(fd);
692                 return logical_block_size / 512;
693
694         }
695         /* else: not a block device.
696          * Why would we even want to write a bcache super block there? */
697
698         return statbuf.st_blksize / 512;
699 }
700
701 long strtoul_or_die(const char *p, size_t max, const char *msg)
702 {
703         errno = 0;
704         long v = strtol(p, NULL, 10);
705         if (errno || v < 0 || v >= max) {
706                 fprintf(stderr, "Invalid %s %zi\n", msg, v);
707                 exit(EXIT_FAILURE);
708         }
709
710         return v;
711 }
712
713 static void print_encode(char *in)
714 {
715     char *pos;
716         for (pos = in; *pos; pos++)
717                 if (isalnum(*pos) || strchr(".-_", *pos))
718                         putchar(*pos);
719                 else
720                         printf("%%%x", *pos);
721 }
722
723 static void show_uuid_only(struct cache_sb *sb, char *dev_uuid) {
724         uuid_unparse(sb->disk_uuid.b, dev_uuid);
725 }
726
727 static void show_super_common(struct cache_sb *sb, bool force_csum)
728 {
729         char uuid[40];
730         char label[SB_LABEL_SIZE + 1];
731         uint64_t expected_csum;
732
733         printf("sb.magic\t\t");
734         if (!memcmp(&sb->magic, &BCACHE_MAGIC, sizeof(sb->magic))) {
735                 printf("ok\n");
736         } else {
737                 printf("bad magic\n");
738                 fprintf(stderr, "Invalid superblock (bad magic)\n");
739                 exit(2);
740         }
741
742         printf("sb.first_sector\t\t%ju", (uint64_t) sb->offset);
743         if (sb->offset == SB_SECTOR) {
744                 printf(" [match]\n");
745         } else {
746                 printf(" [expected %ds]\n", SB_SECTOR);
747                 fprintf(stderr, "Invalid superblock (bad sector)\n");
748                 exit(2);
749         }
750
751         printf("sb.csum\t\t\t%ju", (uint64_t) sb->csum);
752         expected_csum = csum_set(sb,
753                                  sb->version < BCACHE_SB_VERSION_CDEV_V3
754                                  ? BCH_CSUM_CRC64
755                                  : CACHE_SB_CSUM_TYPE(sb));
756         if (sb->csum == expected_csum) {
757                 printf(" [match]\n");
758         } else {
759                 printf(" [expected %" PRIX64 "]\n", expected_csum);
760                 if (force_csum) {
761                         fprintf(stderr, "Corrupt superblock (bad csum)\n");
762                         exit(2);
763                 }
764         }
765
766         printf("sb.version\t\t%ju", (uint64_t) sb->version);
767         switch (sb->version) {
768                 // These are handled the same by the kernel
769                 case BCACHE_SB_VERSION_CDEV:
770                 case BCACHE_SB_VERSION_CDEV_WITH_UUID:
771                         printf(" [cache device]\n");
772                         break;
773
774                 // The second adds data offset support
775                 case BCACHE_SB_VERSION_BDEV:
776                 case BCACHE_SB_VERSION_BDEV_WITH_OFFSET:
777                         printf(" [backing device]\n");
778                         break;
779
780                 default:
781                         printf(" [unknown]\n");
782                         // exit code?
783                         exit(EXIT_SUCCESS);
784         }
785
786         putchar('\n');
787
788         strncpy(label, (char *) sb->label, SB_LABEL_SIZE);
789         label[SB_LABEL_SIZE] = '\0';
790         printf("dev.label\t\t");
791         if (*label)
792                 print_encode(label);
793         else
794                 printf("(empty)");
795         putchar('\n');
796
797         uuid_unparse(sb->disk_uuid.b, uuid);
798         printf("dev.uuid\t\t%s\n", uuid);
799
800         uuid_unparse(sb->set_uuid.b, uuid);
801         printf("cset.uuid\t\t%s\n", uuid);
802 }
803
804 void show_super_backingdev(struct cache_sb *sb, bool force_csum)
805 {
806         uint64_t first_sector;
807
808         show_super_common(sb, force_csum);
809
810         if (sb->version == BCACHE_SB_VERSION_BDEV) {
811                 first_sector = BDEV_DATA_START_DEFAULT;
812         } else {
813                 first_sector = sb->bdev_data_offset;
814         }
815
816         printf("dev.data.first_sector\t%ju\n"
817                "dev.data.cache_mode\t%s"
818                "dev.data.cache_state\t%s\n",
819                first_sector,
820                bdev_cache_mode[BDEV_CACHE_MODE(sb)],
821                bdev_state[BDEV_STATE(sb)]);
822 }
823
824 static void show_cache_member(struct cache_sb *sb, unsigned i)
825 {
826
827 }
828
829 void show_super_cache(struct cache_sb *sb, bool force_csum)
830 {
831         struct cache_member *m = sb->members + sb->nr_this_dev;
832
833         show_super_common(sb, force_csum);
834
835         printf("dev.sectors_per_block\t%u\n"
836                "dev.sectors_per_bucket\t%u\n",
837                sb->block_size,
838                m->bucket_size);
839
840         // total_sectors includes the superblock;
841         printf("dev.cache.first_sector\t%u\n"
842                "dev.cache.cache_sectors\t%llu\n"
843                "dev.cache.total_sectors\t%llu\n"
844                "dev.cache.ordered\t%s\n"
845                "dev.cache.pos\t\t%u\n"
846                "dev.cache.setsize\t\t%u\n",
847                m->bucket_size * m->first_bucket,
848                m->bucket_size * (m->nbuckets - m->first_bucket),
849                m->bucket_size * m->nbuckets,
850                CACHE_SYNC(sb) ? "yes" : "no",
851                sb->nr_this_dev,
852                sb->nr_in_set);
853
854         printf("cache.state\t%s\n",             cache_state[CACHE_STATE(m)]);
855
856         printf("cache.tier\t%llu\n",            CACHE_TIER(m));
857
858         printf("cache.replication_set\t%llu\n", CACHE_REPLICATION_SET(m));
859         printf("cache.cur_meta_replicas\t%llu\n", REPLICATION_SET_CUR_META_REPLICAS(m));
860         printf("cache.cur_data_replicas\t%llu\n", REPLICATION_SET_CUR_DATA_REPLICAS(m));
861
862         printf("cache.has_metadata\t%llu\n",    CACHE_HAS_METADATA(m));
863         printf("cache.has_data\t%llu\n",        CACHE_HAS_DATA(m));
864
865         printf("cache.replacement\t%s\n",       replacement_policies[CACHE_REPLACEMENT(m)]);
866         printf("cache.discard\t%llu\n",         CACHE_DISCARD(m));
867 }
868
869 static int __sysfs_attr_type(char *attr, const char **attr_arr) {
870         int i, j;
871         for(i = 0; attr_arr[i] != NULL; i++)
872                 if(!strcmp(attr, attr_arr[i]))
873                         return 1;
874         return 0;
875 }
876
877 enum sysfs_attr sysfs_attr_type(char *attr) {
878         int ret;
879         if(__sysfs_attr_type(attr, set_attrs))
880                 return SET_ATTR;
881         if(__sysfs_attr_type(attr, cache_attrs))
882                 return CACHE_ATTR;
883         if(__sysfs_attr_type(attr, internal_attrs))
884                 return INTERNAL_ATTR;
885
886         printf("No attribute called %s, try --list to see options\n", attr);
887
888         return -1;
889 }
890
891 static void __sysfs_attr_list(const char **attr_arr) {
892         int i, j;
893         for (i = 0; attr_arr[i] != NULL; i++)
894                 printf("%s\n", attr_arr[i]);
895 }
896
897 void sysfs_attr_list() {
898         __sysfs_attr_list(set_attrs);
899         __sysfs_attr_list(cache_attrs);
900         __sysfs_attr_list(internal_attrs);
901 }
902
903 struct cache_sb *query_dev(char *dev, bool force_csum,
904                 bool print_sb, bool uuid_only, char *dev_uuid)
905 {
906         size_t bytes = 4096;
907         struct cache_sb *sb = aligned_alloc(bytes, bytes);
908
909         int fd = open(dev, O_RDONLY|O_DIRECT);
910         if (fd < 0) {
911                 printf("Can't open dev %s: %s\n", dev, strerror(errno));
912                 return NULL;
913         }
914
915         while (true) {
916                 int ret = pread(fd, sb, bytes, SB_START);
917                 if (ret < 0) {
918                         fprintf(stderr, "Couldn't read superblock: %s\n",
919                                         strerror(errno));
920                         close(fd);
921                         free(sb);
922                         return NULL;
923                 } else if (bytes > sizeof(sb) + sb->u64s * sizeof(u64)) {
924                         /* We read the whole superblock */
925                         break;
926                 }
927
928                 /*
929                  * otherwise double the size of our dest
930                  * and read again
931                  */
932                 free(sb);
933                 bytes *= 2;
934                 sb = aligned_alloc(4096, bytes);
935         }
936
937         close(fd);
938
939         if(uuid_only) {
940                 show_uuid_only(sb, dev_uuid);
941                 return sb;
942         }
943
944         if(print_sb) {
945                 if (!SB_IS_BDEV(sb))
946                         show_super_cache(sb, force_csum);
947                 else
948                         show_super_backingdev(sb, force_csum);
949         }
950
951         return sb;
952 }
953
954 char *dev_name(const char *ugly_path) {
955         char buf[32];
956         int i, end = strlen(ugly_path);
957
958         //Chop off "/bcache", then look for the next '/' from the end
959         for (i = end - 8; ; i--)
960                 if(ugly_path[i] == '/')
961                         break;
962
963         strcpy(buf, ugly_path + i);
964         buf[end - i - 7] = 0;
965
966         // Is the dev guaranteed to be in /dev?
967         // This is needed for finding the superblock with a query-dev
968         return strdup(buf);
969 }
970
971 static void list_cacheset_devs(char *cset_dir, char *cset_name, bool parse_dev_name) {
972         int i = 0;
973         DIR *cachedir, *dir;
974         struct stat cache_stat;
975         char entry[MAX_PATH];
976         struct dirent *ent;
977         snprintf(entry, MAX_PATH, "%s/%s", cset_dir, cset_name);
978
979         if((dir = opendir(entry)) != NULL) {
980                 while((ent = readdir(dir)) != NULL) {
981                         char buf[MAX_PATH];
982                         int len;
983                         char *tmp;
984
985                         /*
986                          * We are looking for all cache# directories
987                          * do a strlen < 9 to skip over other entries
988                          * that also start with "cache"
989                          */
990                         if(strncmp(ent->d_name, "cache", 5) ||
991                                         !(strlen(ent->d_name) < 9))
992                                 continue;
993
994                         snprintf(entry, MAX_PATH, "%s/%s/%s",
995                                         cset_dir,
996                                         cset_name,
997                                         ent->d_name);
998
999                         if((cachedir = opendir(entry)) == NULL)
1000                                 continue;
1001
1002                         if(stat(entry, &cache_stat))
1003                                 continue;
1004
1005                         if((len = readlink(entry, buf, sizeof(buf) - 1)) !=
1006                                         -1) {
1007                                 buf[len] = '\0';
1008                                 if(parse_dev_name) {
1009                                         tmp = dev_name(buf);
1010                                         printf("/dev%s\n", tmp);
1011                                         free(tmp);
1012                                 } else {
1013                                         printf("\t%s\n", buf);
1014                                 }
1015                         }
1016                 }
1017         }
1018 }
1019
1020 char *find_matching_uuid(char *stats_dir, char *subdir, const char *stats_dev_uuid) {
1021         /* Do a query-dev --uuid only to get the uuid
1022          * repeat on each dev until we find a matching one
1023          * append that cache# to subdir and return
1024          */
1025
1026         int i = 0;
1027         DIR *cachedir;
1028         struct stat cache_stat;
1029         char intbuf[4];
1030         char entry[MAX_PATH];
1031         char *err = NULL;
1032
1033         snprintf(entry, MAX_PATH, "%s%s", stats_dir, subdir);
1034         snprintf(intbuf, 4, "%d", i);
1035         strcat(entry, intbuf);
1036
1037         while(true) {
1038                 char buf[MAX_PATH];
1039                 int len;
1040
1041                 if((cachedir = opendir(entry)) == NULL)
1042                         break;
1043
1044                 if(stat(entry, &cache_stat))
1045                         break;
1046
1047                 if((len = readlink(entry, buf, sizeof(buf) - 1)) != -1) {
1048                         char dev_uuid[40];
1049                         buf[len] = '\0';
1050                         int i, end = strlen(buf);
1051                         char tmp[32], devname[32];
1052                         struct cache_sb *sb;
1053
1054                         /* Chop off "/bcache", then look for the
1055                          * next '/' from the end
1056                          */
1057                         for (i = end - 8; ; i--)
1058                                 if(buf[i] == '/')
1059                                         break;
1060
1061                         strcpy(tmp, buf + i);
1062                         tmp[end - i - 7] = 0;
1063                         strcpy(devname, "/dev");
1064                         strcat(devname, tmp);
1065
1066                         err = "Unable to open superblock";
1067                         sb = query_dev(devname, false, false, true, dev_uuid);
1068                         if(!sb)
1069                                 return err;
1070                         else
1071                                 free(sb);
1072
1073                         if(!strcmp(stats_dev_uuid, dev_uuid)) {
1074                                 strcat(subdir, intbuf);
1075                                 return NULL;
1076                         }
1077                 }
1078
1079                 /* remove i from end and append i++ */
1080                 entry[strlen(entry)-strlen(intbuf)] = 0;
1081                 i++;
1082                 snprintf(intbuf, 4, "%d", i);
1083                 strcat(entry, intbuf);
1084         }
1085
1086
1087         err = "dev uuid doesn't exist in cache_set";
1088         return err;
1089 }
1090
1091 char *list_cachesets(char *cset_dir, bool list_devs)
1092 {
1093         struct dirent *ent;
1094         DIR *dir;
1095         char *err = NULL;
1096
1097         dir = opendir(cset_dir);
1098         if (!dir) {
1099                 err = "Failed to open cacheset dir";
1100                 goto err;
1101         }
1102
1103         while ((ent = readdir(dir)) != NULL) {
1104                 struct stat statbuf;
1105                 char entry[MAX_PATH];
1106
1107                 if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
1108                         continue;
1109
1110                 snprintf(entry, MAX_PATH, "%s/%s", cset_dir, ent->d_name);
1111                 if(stat(entry, &statbuf) == -1) {
1112                         err = "Failed to stat cacheset subdir";
1113                         goto err;
1114                 }
1115
1116                 if (S_ISDIR(statbuf.st_mode)) {
1117                         printf("%s\n", ent->d_name);
1118
1119                         if(list_devs) {
1120                                 list_cacheset_devs(cset_dir, ent->d_name, true);
1121                         }
1122                 }
1123         }
1124
1125 err:
1126         closedir(dir);
1127         return err;
1128 }
1129
1130 char *register_bcache(char *const *devs)
1131 {
1132         int ret, bcachefd;
1133         char *err = NULL;
1134
1135         bcachefd = open("/dev/bcache", O_RDWR);
1136         if (bcachefd < 0) {
1137                 err = "Can't open bcache device";
1138                 goto err;
1139         }
1140
1141         ret = ioctl(bcachefd, BCH_IOCTL_REGISTER, devs);
1142         if (ret < 0) {
1143                 char tmp[64];
1144                 snprintf(tmp, 64, "ioctl register error: %s\n",
1145                                 strerror(ret));
1146                 err = strdup(tmp);
1147                 goto err;
1148         }
1149
1150 err:
1151         if (bcachefd)
1152                 close(bcachefd);
1153         return err;
1154 }
1155
1156 char *unregister_bcache(char *const *devs)
1157 {
1158         int ret, bcachefd;
1159         char *err = NULL;
1160
1161         bcachefd = open("/dev/bcache", O_RDWR);
1162         if (bcachefd < 0) {
1163                 err = "Can't open bcache device";
1164                 goto err;
1165         }
1166
1167         ret = ioctl(bcachefd, BCH_IOCTL_UNREGISTER, devs);
1168         if (ret < 0) {
1169                 char tmp[64];
1170                 snprintf(tmp, 64, "ioctl unregister error: %s\n",
1171                                 strerror(ret));
1172                 err = strdup(tmp);
1173                 goto err;
1174         }
1175
1176 err:
1177         close(bcachefd);
1178         return err;
1179 }
1180
1181 char *add_devices(char *const *devs)
1182 {
1183         int ret, bcachefd;
1184         char *err = NULL;
1185
1186         bcachefd = open("/dev/bcache_extent0", O_RDWR);
1187         if (bcachefd < 0) {
1188                 err = "Can't open bcache device";
1189                 goto err;
1190         }
1191
1192         struct bch_ioctl_add_disks ia;
1193         ia.devs = devs;
1194
1195         ret = ioctl(bcachefd, BCH_IOCTL_ADD_DISKS, &ia);
1196         if (ret < 0) {
1197                 char tmp[128];
1198                 snprintf(tmp, 128, "ioctl add disk error: %s\n",
1199                                 strerror(ret));
1200                 err = strdup(tmp);
1201         }
1202
1203 err:
1204         close(bcachefd);
1205         return err;
1206 }
1207
1208 char *remove_device(const char *dev, bool force)
1209 {
1210         int ret, bcachefd;
1211         char *err = NULL;
1212
1213         bcachefd = open("/dev/bcache_extent0", O_RDWR);
1214         if (bcachefd < 0) {
1215                 err = "Can't open bcache device";
1216                 goto err;
1217         }
1218
1219         struct bch_ioctl_rm_disk ir;
1220         ir.dev = dev;
1221         ir.force = force ? 1 : 0;
1222
1223         ret = ioctl(bcachefd, BCH_IOCTL_RM_DISK, &ir);
1224         if (ret < 0) {
1225                 char tmp[128];
1226                 snprintf(tmp, 128, "ioctl add disk error: %s\n",
1227                                 strerror(ret));
1228                 err = strdup(tmp);
1229         }
1230
1231 err:
1232         close(bcachefd);
1233         return err;
1234 }
1235
1236 char *device_set_failed(const char *dev_uuid) {
1237         int ret, bcachefd;
1238         char *err = NULL;
1239         uuid_le dev;
1240         struct bch_ioctl_disk_failed df;
1241
1242         bcachefd = open("/dev/bcache_extent0", O_RDWR);
1243         if (bcachefd < 0) {
1244                 err = "Can't open bcache device";
1245                 goto err;
1246         }
1247
1248         uuid_parse(dev_uuid, dev.b);
1249         df.dev_uuid = dev;
1250
1251         ret = ioctl(bcachefd, BCH_IOCTL_SET_DISK_FAILED, &df);
1252         if (ret < 0) {
1253                 char tmp[128];
1254                 snprintf(tmp, 128, "ioctl set disk failed error %s\n",
1255                                 strerror(ret));
1256                 err = strdup(tmp);
1257         }
1258
1259 err:
1260         close(bcachefd);
1261         return err;
1262 }
1263
1264 char *probe(char *dev, int udev)
1265 {
1266         struct cache_sb sb;
1267         char uuid[40];
1268         blkid_probe pr;
1269         char *err = NULL;
1270
1271         int fd = open(dev, O_RDONLY);
1272         if (fd == -1) {
1273                 err = "Got file descriptor -1 trying to open dev";
1274                 goto err;
1275         }
1276
1277         if (!(pr = blkid_new_probe())) {
1278                 err = "Failed trying to get a blkid for new probe";
1279                 goto err;
1280         }
1281
1282         if (blkid_probe_set_device(pr, fd, 0, 0)) {
1283                 err = "Failed blkid probe set device";
1284                 goto err;
1285         }
1286
1287         /* probe partitions too */
1288         if (blkid_probe_enable_partitions(pr, true)) {
1289                 err = "Enable probe partitions";
1290                 goto err;
1291         }
1292
1293         /* bail if anything was found
1294          * probe-bcache isn't needed once blkid recognizes bcache */
1295         if (!blkid_do_probe(pr)) {
1296                 err = "blkid recognizes bcache";
1297                 goto err;
1298         }
1299
1300         if (pread(fd, &sb, sizeof(sb), SB_START) != sizeof(sb)) {
1301                 err = "Failed to read superblock";
1302                 goto err;
1303         }
1304
1305         if (memcmp(&sb.magic, &BCACHE_MAGIC, sizeof(sb.magic))) {
1306                 err = "Bcache magic incorrect";
1307                 goto err;
1308         }
1309
1310         uuid_unparse(sb.disk_uuid.b, uuid);
1311
1312         if (udev)
1313                 printf("ID_FS_UUID=%s\n"
1314                        "ID_FS_UUID_ENC=%s\n"
1315                        "ID_FS_TYPE=bcache\n",
1316                        uuid, uuid);
1317         else
1318                 printf("%s: UUID=\"\" TYPE=\"bcache\"\n", uuid);
1319
1320         return 0;
1321
1322 err:
1323         return err;
1324 }
1325
1326 char *read_stat_dir(DIR *dir, char *stats_dir, char *stat_name, char *ret)
1327 {
1328         struct stat statbuf;
1329         char entry[MAX_PATH];
1330         char *err = NULL;
1331
1332         snprintf(entry, MAX_PATH, "%s/%s", stats_dir, stat_name);
1333         if(stat(entry, &statbuf) == -1) {
1334                 char tmp[MAX_PATH];
1335                 snprintf(tmp, MAX_PATH, "Failed to stat %s\n", entry);
1336                 err = strdup(tmp);
1337                 goto err;
1338         }
1339
1340         if (S_ISREG(statbuf.st_mode)) {
1341                 char buf[MAX_PATH];
1342                 FILE *fp = NULL;
1343
1344                 fp = fopen(entry, "r");
1345                 if(!fp) {
1346                         /* If we can't open the file, this is probably because
1347                          * of permissions, just move to the next file */
1348                         return NULL;
1349                 }
1350
1351                 while(fgets(ret, MAX_PATH, fp));
1352                 fclose(fp);
1353         }
1354 err:
1355         return err;
1356 }
1357
1358 char *bcache_get_capacity(const char *cset_dir, const char *capacity_uuid,
1359                 bool show_devs)
1360 {
1361         char *err = NULL;
1362         char bucket_size_path[MAX_PATH];
1363         char nbuckets_path[MAX_PATH];
1364         char avail_buckets_path[MAX_PATH];
1365         char cache_path[MAX_PATH];
1366
1367         double bucket_sizes[MAX_DEVS];
1368         double nbuckets[MAX_DEVS];
1369         double avail_buckets[MAX_DEVS];
1370         char *dev_names[MAX_DEVS];
1371         int dev_count = 0, i;
1372         char intbuf[4];
1373         double total_cap = 0, total_free = 0;
1374         int precision = 2;
1375
1376         snprintf(intbuf, 4, "%d", i);
1377         snprintf(bucket_size_path, MAX_PATH, "%s/%s/%s/%s", cset_dir,
1378                         capacity_uuid, "cache0", "bucket_size_bytes");
1379         snprintf(nbuckets_path, MAX_PATH, "%s/%s/%s/%s", cset_dir,
1380                         capacity_uuid, "cache0", "nbuckets");
1381         snprintf(avail_buckets_path, MAX_PATH, "%s/%s/%s/%s", cset_dir,
1382                         capacity_uuid, "cache0", "available_buckets");
1383         snprintf(cache_path, MAX_PATH, "%s/%s/%s", cset_dir, capacity_uuid,
1384                         "cache0");
1385
1386         while(true) {
1387                 char buf[MAX_PATH];
1388                 int len;
1389                 DIR *cache_dir;
1390
1391                 if((cache_dir = opendir(cache_path)) == NULL)
1392                         break;
1393
1394                 err = read_stat_dir(cache_dir, cache_path,
1395                                 "bucket_size_bytes", buf);
1396                 if (err)
1397                         goto err;
1398                 else
1399                         bucket_sizes[dev_count] = atof(buf);
1400
1401                 err = read_stat_dir(cache_dir, cache_path,
1402                                 "nbuckets", buf);
1403                 if (err)
1404                         goto err;
1405                 else
1406                         nbuckets[dev_count] = atof(buf);
1407
1408                 err = read_stat_dir(cache_dir, cache_path,
1409                                 "available_buckets", buf);
1410                 if (err)
1411                         goto err;
1412                 else
1413                         avail_buckets[dev_count] = atof(buf);
1414
1415                 if((len = readlink(cache_path, buf, sizeof(buf) - 1)) != -1) {
1416                         buf[len] = '\0';
1417                         dev_names[dev_count] = dev_name(buf);
1418                 }
1419
1420                 /* remove i/stat and append i++/stat */
1421                 bucket_size_path[strlen(cache_path) - strlen(intbuf)] = 0;
1422                 nbuckets_path[strlen(cache_path) - strlen(intbuf)] = 0;
1423                 avail_buckets_path[strlen(cache_path) - strlen(intbuf)] = 0;
1424                 cache_path[strlen(cache_path) - strlen(intbuf)] = 0;
1425
1426                 dev_count++;
1427
1428                 snprintf(intbuf, 4, "%d", dev_count);
1429                 strcat(cache_path, intbuf);
1430                 strcat(bucket_size_path, intbuf);
1431                 strcat(nbuckets_path, intbuf);
1432                 strcat(avail_buckets_path, intbuf);
1433         }
1434
1435         printf("%-15s%-25s%-25s\n", "Device Name", "Capacity (512 Blocks)", "Free (512 Blocks)");
1436
1437         if (show_devs) {
1438                 for (i = 0; i < dev_count; i++) {
1439                         printf("%s%-11s%-25.*f%-25.*f\n", "/dev", dev_names[i],
1440                                 precision,
1441                                 (bucket_sizes[i] * nbuckets[i]) / 512,
1442                                 precision,
1443                                 (bucket_sizes[i] * avail_buckets[i]) / 512);
1444                 }
1445         }
1446
1447         for (i = 0; i < dev_count; i++) {
1448                 total_cap += (bucket_sizes[i] * nbuckets[i]) / 512;
1449                 total_free += (bucket_sizes[i] * avail_buckets[i]) / 512;
1450
1451         }
1452
1453         printf("%-15s%-25.*f%-25.*f\n", "Total", precision, total_cap,
1454                         precision, total_free);
1455
1456 err:
1457         for (i = 0; i < dev_count; i++)
1458                 if (dev_names[i])
1459                         free(dev_names[i]);
1460         return err;
1461 }