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