]> git.sesse.net Git - bcachefs-tools-debian/blob - bcache.c
5274551992e2c1120a14fa57b09048306ef6c47e
[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                                 bool writeback, uint64_t data_offset,
456                                 const char *label,
457                                 uuid_le set_uuid)
458 {
459         char uuid_str[40], set_uuid_str[40];
460         struct cache_sb sb;
461
462         memset(&sb, 0, sizeof(struct cache_sb));
463
464         sb.offset       = SB_SECTOR;
465         sb.version      = BCACHE_SB_VERSION_BDEV;
466         sb.magic        = BCACHE_MAGIC;
467         uuid_generate(sb.uuid.b);
468         sb.set_uuid     = set_uuid;
469         sb.bucket_size  = bucket_sizes[0];
470         sb.block_size   = block_size;
471
472         uuid_unparse(sb.uuid.b, uuid_str);
473         uuid_unparse(sb.set_uuid.b, set_uuid_str);
474         if (label)
475                 memcpy(sb.label, label, SB_LABEL_SIZE);
476
477         SET_BDEV_CACHE_MODE(&sb, writeback
478                             ? CACHE_MODE_WRITEBACK
479                             : CACHE_MODE_WRITETHROUGH);
480
481         if (data_offset != BDEV_DATA_START_DEFAULT) {
482                 sb.version = BCACHE_SB_VERSION_BDEV_WITH_OFFSET;
483                 sb.data_offset = data_offset;
484         }
485
486         sb.csum = csum_set(&sb, BCH_CSUM_CRC64);
487
488         printf("UUID:                   %s\n"
489                "Set UUID:               %s\n"
490                "version:                %u\n"
491                "block_size:             %u\n"
492                "data_offset:            %ju\n",
493                uuid_str, set_uuid_str,
494                (unsigned) sb.version,
495                sb.block_size,
496                data_offset);
497
498         do_write_sb(fd, &sb);
499 }
500
501 int dev_open(const char *dev, bool wipe_bcache)
502 {
503         struct cache_sb sb;
504         blkid_probe pr;
505         int fd;
506         char err[MAX_PATH];
507
508         if ((fd = open(dev, O_RDWR|O_EXCL)) == -1) {
509                 sprintf(err, "Can't open dev %s: %s\n", dev, strerror(errno));
510                 goto err;
511         }
512
513         if (pread(fd, &sb, sizeof(sb), SB_START) != sizeof(sb)) {
514                 sprintf(err, "Failed to read superblock");
515                 goto err;
516         }
517
518         if (!memcmp(&sb.magic, &BCACHE_MAGIC, 16) && !wipe_bcache) {
519                 sprintf(err, "Already a bcache device on %s, "
520                         "overwrite with --wipe-bcache\n", dev);
521                 goto err;
522         }
523
524         if (!(pr = blkid_new_probe())) {
525                 sprintf(err, "Failed to create a new probe");
526                 goto err;
527         }
528         if (blkid_probe_set_device(pr, fd, 0, 0)) {
529                 sprintf(err, "failed to set probe to device");
530                 goto err;
531         }
532         /* enable ptable probing; superblock probing is enabled by default */
533         if (blkid_probe_enable_partitions(pr, true)) {
534                 sprintf(err, "Failed to enable partitions on probe");
535                 goto err;
536         }
537         if (!blkid_do_probe(pr)) {
538                 /* XXX wipefs doesn't know how to remove partition tables */
539                 sprintf(err, "Device %s already has a non-bcache superblock, "
540                         "remove it using wipefs and wipefs -a\n", dev);
541                 goto err;
542         }
543
544         return fd;
545
546         err:
547                 fprintf(stderr, "dev_open failed with: %s", err);
548                 exit(EXIT_FAILURE);
549 }
550
551 static unsigned min_bucket_size(int num_bucket_sizes, unsigned *bucket_sizes)
552 {
553         int i;
554         unsigned min = bucket_sizes[0];
555
556         for (i = 0; i < num_bucket_sizes; i++)
557                 min = bucket_sizes[i] < min ? bucket_sizes[i] : min;
558
559         return min;
560 }
561
562 static unsigned node_size(unsigned bucket_size) {
563
564         if (bucket_size <= 256)
565                 return bucket_size;
566         else if (bucket_size <= 512)
567                 return bucket_size / 2;
568         else
569                 return bucket_size / 4;
570 }
571
572 void write_cache_sbs(int *fds, struct cache_sb *sb,
573                             unsigned block_size, unsigned *bucket_sizes,
574                                 int num_bucket_sizes)
575 {
576         char uuid_str[40], set_uuid_str[40];
577         size_t i;
578         unsigned min_size = min_bucket_size(num_bucket_sizes, bucket_sizes);
579
580         sb->offset      = SB_SECTOR;
581         sb->version     = BCACHE_SB_VERSION_CDEV_V3;
582         sb->magic       = BCACHE_MAGIC;
583         sb->block_size  = block_size;
584         sb->keys        = bch_journal_buckets_offset(sb);
585
586         /*
587          * don't have a userspace crc32c implementation handy, just always use
588          * crc64
589          */
590         SET_CACHE_SB_CSUM_TYPE(sb, BCH_CSUM_CRC64);
591
592         for (i = 0; i < sb->nr_in_set; i++) {
593                 struct cache_member *m = sb->members + i;
594
595                 if (num_bucket_sizes <= 1)
596                         sb->bucket_size = bucket_sizes[0];
597                 else
598                         sb->bucket_size = bucket_sizes[i];
599                 SET_CACHE_BTREE_NODE_SIZE(sb, node_size(min_size));
600
601                 sb->uuid = m->uuid;
602                 sb->nbuckets            = getblocks(fds[i]) / sb->bucket_size;
603                 sb->nr_this_dev         = i;
604                 sb->first_bucket        = (23 / sb->bucket_size) + 1;
605
606                 if (sb->nbuckets < 1 << 7) {
607                         fprintf(stderr, "Not enough buckets: %llu, need %u\n",
608                                 sb->nbuckets, 1 << 7);
609                         exit(EXIT_FAILURE);
610                 }
611
612                 sb->csum = csum_set(sb, CACHE_SB_CSUM_TYPE(sb));
613
614                 uuid_unparse(sb->uuid.b, uuid_str);
615                 uuid_unparse(sb->set_uuid.b, set_uuid_str);
616                 printf("UUID:                   %s\n"
617                        "Set UUID:               %s\n"
618                        "version:                %u\n"
619                        "nbuckets:               %llu\n"
620                        "block_size:             %u\n"
621                        "bucket_size:            %u\n"
622                        "nr_in_set:              %u\n"
623                        "nr_this_dev:            %u\n"
624                        "first_bucket:           %u\n",
625                        uuid_str, set_uuid_str,
626                        (unsigned) sb->version,
627                        sb->nbuckets,
628                        sb->block_size,
629                        sb->bucket_size,
630                        sb->nr_in_set,
631                        sb->nr_this_dev,
632                        sb->first_bucket);
633
634                 do_write_sb(fds[i], sb);
635         }
636 }
637
638 void next_cache_device(struct cache_sb *sb,
639                               unsigned replication_set,
640                               int tier,
641                               unsigned replacement_policy,
642                               bool discard)
643 {
644         struct cache_member *m = sb->members + sb->nr_in_set;
645
646         SET_CACHE_REPLICATION_SET(m, replication_set);
647         SET_CACHE_TIER(m, tier);
648         SET_CACHE_REPLACEMENT(m, replacement_policy);
649         SET_CACHE_DISCARD(m, discard);
650         uuid_generate(m->uuid.b);
651
652         sb->nr_in_set++;
653 }
654
655 unsigned get_blocksize(const char *path)
656 {
657         struct stat statbuf;
658
659         if (stat(path, &statbuf)) {
660                 fprintf(stderr, "Error statting %s: %s\n",
661                         path, strerror(errno));
662                 exit(EXIT_FAILURE);
663         }
664
665         if (S_ISBLK(statbuf.st_mode)) {
666                 /* check IO limits:
667                  * BLKALIGNOFF: alignment_offset
668                  * BLKPBSZGET: physical_block_size
669                  * BLKSSZGET: logical_block_size
670                  * BLKIOMIN: minimum_io_size
671                  * BLKIOOPT: optimal_io_size
672                  *
673                  * It may be tempting to use physical_block_size,
674                  * or even minimum_io_size.
675                  * But to be as transparent as possible,
676                  * we want to use logical_block_size.
677                  */
678                 unsigned int logical_block_size;
679                 int fd = open(path, O_RDONLY);
680
681                 if (fd < 0) {
682                         fprintf(stderr, "open(%s) failed: %m\n", path);
683                         exit(EXIT_FAILURE);
684                 }
685                 if (ioctl(fd, BLKSSZGET, &logical_block_size)) {
686                         fprintf(stderr, "ioctl(%s, BLKSSZGET) failed: %m\n", path);
687                         exit(EXIT_FAILURE);
688                 }
689                 close(fd);
690                 return logical_block_size / 512;
691
692         }
693         /* else: not a block device.
694          * Why would we even want to write a bcache super block there? */
695
696         return statbuf.st_blksize / 512;
697 }
698
699 long strtoul_or_die(const char *p, size_t max, const char *msg)
700 {
701         errno = 0;
702         long v = strtol(p, NULL, 10);
703         if (errno || v < 0 || v >= max) {
704                 fprintf(stderr, "Invalid %s %zi\n", msg, v);
705                 exit(EXIT_FAILURE);
706         }
707
708         return v;
709 }
710
711 static void print_encode(char *in)
712 {
713     char *pos;
714         for (pos = in; *pos; pos++)
715                 if (isalnum(*pos) || strchr(".-_", *pos))
716                         putchar(*pos);
717                 else
718                         printf("%%%x", *pos);
719 }
720
721 static void show_uuid_only(struct cache_sb *sb, char *dev_uuid) {
722         uuid_unparse(sb->uuid.b, dev_uuid);
723 }
724
725 static void show_super_common(struct cache_sb *sb, bool force_csum)
726 {
727         char uuid[40];
728         char label[SB_LABEL_SIZE + 1];
729         uint64_t expected_csum;
730
731         printf("sb.magic\t\t");
732         if (!memcmp(&sb->magic, &BCACHE_MAGIC, sizeof(sb->magic))) {
733                 printf("ok\n");
734         } else {
735                 printf("bad magic\n");
736                 fprintf(stderr, "Invalid superblock (bad magic)\n");
737                 exit(2);
738         }
739
740         printf("sb.first_sector\t\t%ju", (uint64_t) sb->offset);
741         if (sb->offset == SB_SECTOR) {
742                 printf(" [match]\n");
743         } else {
744                 printf(" [expected %ds]\n", SB_SECTOR);
745                 fprintf(stderr, "Invalid superblock (bad sector)\n");
746                 exit(2);
747         }
748
749         printf("sb.csum\t\t\t%ju", (uint64_t) sb->csum);
750         expected_csum = csum_set(sb,
751                                  sb->version < BCACHE_SB_VERSION_CDEV_V3
752                                  ? BCH_CSUM_CRC64
753                                  : CACHE_SB_CSUM_TYPE(sb));
754         if (sb->csum == expected_csum) {
755                 printf(" [match]\n");
756         } else {
757                 printf(" [expected %" PRIX64 "]\n", expected_csum);
758                 if (!force_csum) {
759                         fprintf(stderr, "Corrupt superblock (bad csum)\n");
760                         exit(2);
761                 }
762         }
763
764         printf("sb.version\t\t%ju", (uint64_t) sb->version);
765         switch (sb->version) {
766                 // These are handled the same by the kernel
767                 case BCACHE_SB_VERSION_CDEV:
768                 case BCACHE_SB_VERSION_CDEV_WITH_UUID:
769                         printf(" [cache device]\n");
770                         break;
771
772                 // The second adds data offset support
773                 case BCACHE_SB_VERSION_BDEV:
774                 case BCACHE_SB_VERSION_BDEV_WITH_OFFSET:
775                         printf(" [backing device]\n");
776                         break;
777
778                 default:
779                         printf(" [unknown]\n");
780                         // exit code?
781                         exit(EXIT_SUCCESS);
782         }
783
784         putchar('\n');
785
786         strncpy(label, (char *) sb->label, SB_LABEL_SIZE);
787         label[SB_LABEL_SIZE] = '\0';
788         printf("dev.label\t\t");
789         if (*label)
790                 print_encode(label);
791         else
792                 printf("(empty)");
793         putchar('\n');
794
795         uuid_unparse(sb->uuid.b, uuid);
796         printf("dev.uuid\t\t%s\n", uuid);
797
798         uuid_unparse(sb->set_uuid.b, uuid);
799         printf("cset.uuid\t\t%s\n", uuid);
800 }
801
802 void show_super_backingdev(struct cache_sb *sb, bool force_csum)
803 {
804         uint64_t first_sector;
805
806         show_super_common(sb, force_csum);
807
808         if (sb->version == BCACHE_SB_VERSION_BDEV) {
809                 first_sector = BDEV_DATA_START_DEFAULT;
810         } else {
811                 if (sb->keys == 1 || sb->d[0]) {
812                         fprintf(stderr,
813                                 "Possible experimental format detected, bailing\n");
814                         exit(3);
815                 }
816                 first_sector = sb->data_offset;
817         }
818
819         printf("dev.data.first_sector\t%ju\n"
820                "dev.data.cache_mode\t%s"
821                "dev.data.cache_state\t%s\n",
822                first_sector,
823                bdev_cache_mode[BDEV_CACHE_MODE(sb)],
824                bdev_state[BDEV_STATE(sb)]);
825 }
826
827 static void show_cache_member(struct cache_sb *sb, unsigned i)
828 {
829         struct cache_member *m = ((struct cache_member *) sb->d) + i;
830
831         printf("cache.state\t%s\n",             cache_state[CACHE_STATE(m)]);
832         printf("cache.tier\t%llu\n",            CACHE_TIER(m));
833
834         printf("cache.replication_set\t%llu\n", CACHE_REPLICATION_SET(m));
835         printf("cache.cur_meta_replicas\t%llu\n", REPLICATION_SET_CUR_META_REPLICAS(m));
836         printf("cache.cur_data_replicas\t%llu\n", REPLICATION_SET_CUR_DATA_REPLICAS(m));
837
838         printf("cache.has_metadata\t%llu\n",    CACHE_HAS_METADATA(m));
839         printf("cache.has_data\t%llu\n",        CACHE_HAS_DATA(m));
840
841         printf("cache.replacement\t%s\n",       replacement_policies[CACHE_REPLACEMENT(m)]);
842         printf("cache.discard\t%llu\n",         CACHE_DISCARD(m));
843 }
844
845 void show_super_cache(struct cache_sb *sb, bool force_csum)
846 {
847         show_super_common(sb, force_csum);
848
849         printf("dev.sectors_per_block\t%u\n"
850                "dev.sectors_per_bucket\t%u\n",
851                sb->block_size,
852                sb->bucket_size);
853
854         // total_sectors includes the superblock;
855         printf("dev.cache.first_sector\t%u\n"
856                "dev.cache.cache_sectors\t%llu\n"
857                "dev.cache.total_sectors\t%llu\n"
858                "dev.cache.ordered\t%s\n"
859                "dev.cache.pos\t\t%u\n"
860                "dev.cache.setsize\t\t%u\n",
861                sb->bucket_size * sb->first_bucket,
862                sb->bucket_size * (sb->nbuckets - sb->first_bucket),
863                sb->bucket_size * sb->nbuckets,
864                CACHE_SYNC(sb) ? "yes" : "no",
865                sb->nr_this_dev,
866                sb->nr_in_set);
867
868         show_cache_member(sb, sb->nr_this_dev);
869 }
870
871 static int __sysfs_attr_type(char *attr, const char **attr_arr) {
872         int i, j;
873         for(i = 0; attr_arr[i] != NULL; i++)
874                 if(!strcmp(attr, attr_arr[i]))
875                         return 1;
876         return 0;
877 }
878
879 enum sysfs_attr sysfs_attr_type(char *attr) {
880         int ret;
881         if(__sysfs_attr_type(attr, set_attrs))
882                 return SET_ATTR;
883         if(__sysfs_attr_type(attr, cache_attrs))
884                 return CACHE_ATTR;
885         if(__sysfs_attr_type(attr, internal_attrs))
886                 return INTERNAL_ATTR;
887
888         printf("No attribute called %s, try --list to see options\n", attr);
889
890         return -1;
891 }
892
893 static void __sysfs_attr_list(const char **attr_arr) {
894         int i, j;
895         for (i = 0; attr_arr[i] != NULL; i++)
896                 printf("%s\n", attr_arr[i]);
897 }
898
899 void sysfs_attr_list() {
900         __sysfs_attr_list(set_attrs);
901         __sysfs_attr_list(cache_attrs);
902         __sysfs_attr_list(internal_attrs);
903 }
904
905 struct cache_sb *query_dev(char *dev, bool force_csum,
906                 bool print_sb, bool uuid_only, char *dev_uuid)
907 {
908         struct cache_sb sb_stack, *sb = &sb_stack;
909         size_t bytes = sizeof(*sb);
910
911         int fd = open(dev, O_RDONLY);
912         if (fd < 0) {
913                 printf("Can't open dev %s: %s\n", dev, strerror(errno));
914                 return NULL;
915         }
916
917         if (pread(fd, sb, bytes, SB_START) != bytes) {
918                 fprintf(stderr, "Couldn't read\n");
919                 return NULL;
920         }
921
922         if (sb->keys) {
923                 bytes = sizeof(*sb) + sb->keys * sizeof(uint64_t);
924                 sb = malloc(bytes);
925
926                 if (pread(fd, sb, bytes, SB_START) != bytes) {
927                         fprintf(stderr, "Couldn't read\n");
928                         return NULL;
929                 }
930         }
931
932         if(uuid_only) {
933                 show_uuid_only(sb, dev_uuid);
934                 return sb;
935         }
936
937         if(print_sb) {
938                 if (!SB_IS_BDEV(sb))
939                         show_super_cache(sb, force_csum);
940                 else
941                         show_super_backingdev(sb, force_csum);
942         }
943
944         return sb;
945 }
946
947 static void dev_name(const char *ugly_path) {
948         char buf[32];
949         int i, end = strlen(ugly_path);
950
951         //Chop off "/bcache", then look for the next '/' from the end
952         for (i = end - 8; ; i--)
953                 if(ugly_path[i] == '/')
954                         break;
955
956         strcpy(buf, ugly_path + i);
957         buf[end - i - 7] = 0;
958
959         // Is the dev guaranteed to be in /dev?
960         // This is needed for finding the superblock with a query-dev
961         printf("/dev%s\n", buf);
962 }
963
964 static void list_cacheset_devs(char *cset_dir, char *cset_name, bool parse_dev_name) {
965         int i = 0;
966         DIR *cachedir;
967         struct stat cache_stat;
968         char intbuf[4];
969         char entry[MAX_PATH];
970
971         snprintf(entry, MAX_PATH, "%s/%s/cache0", cset_dir, cset_name);
972         snprintf(intbuf, 4, "%d", i);
973
974         while(true) {
975                 char buf[MAX_PATH];
976                 int len;
977
978                 if((cachedir = opendir(entry)) == NULL)
979                         break;
980
981                 if(stat(entry, &cache_stat))
982                         break;
983
984                 if((len = readlink(entry, buf, sizeof(buf) - 1)) != -1) {
985                         buf[len] = '\0';
986                         if(parse_dev_name)
987                                 dev_name(buf);
988                         else
989                                 printf("\t%s\n", buf);
990                 }
991
992                 /* remove i from end and append i++ */
993                 entry[strlen(entry)-strlen(intbuf)] = 0;
994                 i++;
995                 snprintf(intbuf, 4, "%d", i);
996                 strcat(entry, intbuf);
997         }
998 }
999
1000 char *find_matching_uuid(char *stats_dir, char *subdir, const char *stats_dev_uuid) {
1001         /* Do a query-dev --uuid only to get the uuid
1002          * repeat on each dev until we find a matching one
1003          * append that cache# to subdir and return
1004          */
1005
1006         int i = 0;
1007         DIR *cachedir;
1008         struct stat cache_stat;
1009         char intbuf[4];
1010         char entry[MAX_PATH];
1011         char *err = NULL;
1012
1013         snprintf(entry, MAX_PATH, "%s%s", stats_dir, subdir);
1014         snprintf(intbuf, 4, "%d", i);
1015         strcat(entry, intbuf);
1016
1017         while(true) {
1018                 char buf[MAX_PATH];
1019                 int len;
1020
1021                 if((cachedir = opendir(entry)) == NULL)
1022                         break;
1023
1024                 if(stat(entry, &cache_stat))
1025                         break;
1026
1027                 if((len = readlink(entry, buf, sizeof(buf) - 1)) != -1) {
1028                         char dev_uuid[40];
1029                         buf[len] = '\0';
1030                         int i, end = strlen(buf);
1031                         char tmp[32], devname[32];
1032                         struct cache_sb *sb;
1033
1034                         /* Chop off "/bcache", then look for the
1035                          * next '/' from the end
1036                          */
1037                         for (i = end - 8; ; i--)
1038                                 if(buf[i] == '/')
1039                                         break;
1040
1041                         strcpy(tmp, buf + i);
1042                         tmp[end - i - 7] = 0;
1043                         strcpy(devname, "/dev");
1044                         strcat(devname, tmp);
1045
1046                         err = "Unable to open superblock";
1047                         sb = query_dev(devname, false, false, true, dev_uuid);
1048                         if(!sb)
1049                                 return err;
1050
1051                         if(!strcmp(stats_dev_uuid, dev_uuid)) {
1052                                 strcat(subdir, intbuf);
1053                                 return NULL;
1054                         }
1055                 }
1056
1057                 /* remove i from end and append i++ */
1058                 entry[strlen(entry)-strlen(intbuf)] = 0;
1059                 i++;
1060                 snprintf(intbuf, 4, "%d", i);
1061                 strcat(entry, intbuf);
1062         }
1063
1064
1065         err = "dev uuid doesn't exist in cache_set";
1066         return err;
1067 }
1068
1069 char *list_cachesets(char *cset_dir, bool list_devs)
1070 {
1071         struct dirent *ent;
1072         DIR *dir;
1073         char *err = NULL;
1074
1075         dir = opendir(cset_dir);
1076         if (!dir) {
1077                 err = "Failed to open cacheset dir";
1078                 goto err;
1079         }
1080
1081         while ((ent = readdir(dir)) != NULL) {
1082                 struct stat statbuf;
1083                 char entry[MAX_PATH];
1084
1085                 if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
1086                         continue;
1087
1088                 snprintf(entry, MAX_PATH, "%s/%s", cset_dir, ent->d_name);
1089                 if(stat(entry, &statbuf) == -1) {
1090                         err = "Failed to stat cacheset subdir";
1091                         goto err;
1092                 }
1093
1094                 if (S_ISDIR(statbuf.st_mode)) {
1095                         printf("%s\n", ent->d_name);
1096
1097                         if(list_devs) {
1098                                 list_cacheset_devs(cset_dir, ent->d_name, true);
1099                         }
1100                 }
1101         }
1102
1103 err:
1104         closedir(dir);
1105         return err;
1106 }
1107
1108 char *register_bcache(char *const *devs)
1109 {
1110         int ret, bcachefd;
1111         char *err = NULL;
1112
1113         bcachefd = open("/dev/bcache", O_RDWR);
1114         if (bcachefd < 0) {
1115                 err = "Can't open bcache device";
1116                 goto err;
1117         }
1118
1119         ret = ioctl(bcachefd, BCH_IOCTL_REGISTER, devs);
1120         if (ret < 0) {
1121                 char tmp[64];
1122                 snprintf(tmp, 64, "ioctl register error: %s\n",
1123                                 strerror(ret));
1124                 err = strdup(tmp);
1125                 goto err;
1126         }
1127
1128 err:
1129         if (bcachefd)
1130                 close(bcachefd);
1131         return err;
1132 }
1133
1134 char *unregister_bcache(char *const *devs)
1135 {
1136         int ret, bcachefd;
1137         char *err = NULL;
1138
1139         bcachefd = open("/dev/bcache", O_RDWR);
1140         if (bcachefd < 0) {
1141                 err = "Can't open bcache device";
1142                 goto err;
1143         }
1144
1145         ret = ioctl(bcachefd, BCH_IOCTL_UNREGISTER, devs);
1146         if (ret < 0) {
1147                 char tmp[64];
1148                 snprintf(tmp, 64, "ioctl unregister error: %s\n",
1149                                 strerror(ret));
1150                 err = strdup(tmp);
1151                 goto err;
1152         }
1153
1154 err:
1155         close(bcachefd);
1156         return err;
1157 }
1158
1159 char *add_devices(char *const *devs, char *uuid)
1160 {
1161         int ret, bcachefd;
1162         char *err = NULL;
1163
1164         bcachefd = open("/dev/bcache", O_RDWR);
1165         if (bcachefd < 0) {
1166                 err = "Can't open bcache device";
1167                 goto err;
1168         }
1169
1170         struct bch_ioctl_add_disks ia;
1171         ia.devs = devs;
1172         ia.uuid = uuid;
1173
1174         ret = ioctl(bcachefd, BCH_IOCTL_ADD_DISKS, &ia);
1175         if (ret < 0) {
1176                 char tmp[128];
1177                 snprintf(tmp, 128, "ioctl add disk error: %s\n",
1178                                 strerror(ret));
1179                 err = strdup(tmp);
1180         }
1181
1182 err:
1183         close(bcachefd);
1184         return err;
1185 }
1186
1187 char *remove_device(const char *dev, bool force)
1188 {
1189         int ret, bcachefd;
1190         char *err = NULL;
1191
1192         bcachefd = open("/dev/bcache", O_RDWR);
1193         if (bcachefd < 0) {
1194                 err = "Can't open bcache device";
1195                 goto err;
1196         }
1197
1198         struct bch_ioctl_rm_disk ir;
1199         ir.dev = dev;
1200         ir.force = force ? 1 : 0;
1201
1202         ret = ioctl(bcachefd, BCH_IOCTL_RM_DISK, &ir);
1203         if (ret < 0) {
1204                 char tmp[128];
1205                 snprintf(tmp, 128, "ioctl add disk error: %s\n",
1206                                 strerror(ret));
1207                 err = strdup(tmp);
1208         }
1209
1210 err:
1211         close(bcachefd);
1212         return err;
1213 }
1214
1215 char *probe(char *dev, int udev)
1216 {
1217         struct cache_sb sb;
1218         char uuid[40];
1219         blkid_probe pr;
1220         char *err = NULL;
1221
1222         int fd = open(dev, O_RDONLY);
1223         if (fd == -1) {
1224                 err = "Got file descriptor -1 trying to open dev";
1225                 goto err;
1226         }
1227
1228         if (!(pr = blkid_new_probe())) {
1229                 err = "Failed trying to get a blkid for new probe";
1230                 goto err;
1231         }
1232
1233         if (blkid_probe_set_device(pr, fd, 0, 0)) {
1234                 err = "Failed blkid probe set device";
1235                 goto err;
1236         }
1237
1238         /* probe partitions too */
1239         if (blkid_probe_enable_partitions(pr, true)) {
1240                 err = "Enable probe partitions";
1241                 goto err;
1242         }
1243
1244         /* bail if anything was found
1245          * probe-bcache isn't needed once blkid recognizes bcache */
1246         if (!blkid_do_probe(pr)) {
1247                 err = "blkid recognizes bcache";
1248                 goto err;
1249         }
1250
1251         if (pread(fd, &sb, sizeof(sb), SB_START) != sizeof(sb)) {
1252                 err = "Failed to read superblock";
1253                 goto err;
1254         }
1255
1256         if (memcmp(&sb.magic, &BCACHE_MAGIC, sizeof(sb.magic))) {
1257                 err = "Bcache magic incorrect";
1258                 goto err;
1259         }
1260
1261         uuid_unparse(sb.uuid.b, uuid);
1262
1263         if (udev)
1264                 printf("ID_FS_UUID=%s\n"
1265                        "ID_FS_UUID_ENC=%s\n"
1266                        "ID_FS_TYPE=bcache\n",
1267                        uuid, uuid);
1268         else
1269                 printf("%s: UUID=\"\" TYPE=\"bcache\"\n", uuid);
1270
1271         return 0;
1272
1273 err:
1274         return err;
1275 }
1276
1277 char *read_stat_dir(DIR *dir, char *stats_dir, char *stat_name, bool print_val)
1278 {
1279         struct stat statbuf;
1280         char entry[MAX_PATH];
1281         char *err = NULL;
1282
1283         snprintf(entry, MAX_PATH, "%s/%s", stats_dir, stat_name);
1284         if(stat(entry, &statbuf) == -1) {
1285                 char tmp[MAX_PATH];
1286                 snprintf(tmp, MAX_PATH, "Failed to stat %s\n", entry);
1287                 err = strdup(tmp);
1288                 goto err;
1289         }
1290
1291         if (S_ISREG(statbuf.st_mode)) {
1292                 char buf[MAX_PATH];
1293                 FILE *fp = NULL;
1294
1295                 fp = fopen(entry, "r");
1296                 if(!fp) {
1297                         /* If we can't open the file, this is probably because
1298                          * of permissions, just move to the next file */
1299                         return NULL;
1300                 }
1301
1302                 while(fgets(buf, MAX_PATH, fp));
1303
1304                 if(print_val)
1305                         printf("%s\n", buf);
1306                 else
1307                         printf("%s\n", stat_name);
1308                 fclose(fp);
1309         }
1310 err:
1311         return err;
1312 }