]> git.sesse.net Git - bcachefs-tools-debian/blob - bcache.c
bcacheadm: fix status and query-devs
[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
833         printf("cache.tier\t%llu\n",            CACHE_TIER(m));
834
835         printf("cache.replication_set\t%llu\n", CACHE_REPLICATION_SET(m));
836         printf("cache.cur_meta_replicas\t%llu\n", REPLICATION_SET_CUR_META_REPLICAS(m));
837         printf("cache.cur_data_replicas\t%llu\n", REPLICATION_SET_CUR_DATA_REPLICAS(m));
838
839         printf("cache.has_metadata\t%llu\n",    CACHE_HAS_METADATA(m));
840         printf("cache.has_data\t%llu\n",        CACHE_HAS_DATA(m));
841
842         printf("cache.replacement\t%s\n",       replacement_policies[CACHE_REPLACEMENT(m)]);
843         printf("cache.discard\t%llu\n",         CACHE_DISCARD(m));
844 }
845
846 void show_super_cache(struct cache_sb *sb, bool force_csum)
847 {
848         show_super_common(sb, force_csum);
849
850         printf("dev.sectors_per_block\t%u\n"
851                "dev.sectors_per_bucket\t%u\n",
852                sb->block_size,
853                sb->bucket_size);
854
855         // total_sectors includes the superblock;
856         printf("dev.cache.first_sector\t%u\n"
857                "dev.cache.cache_sectors\t%llu\n"
858                "dev.cache.total_sectors\t%llu\n"
859                "dev.cache.ordered\t%s\n"
860                "dev.cache.pos\t\t%u\n"
861                "dev.cache.setsize\t\t%u\n",
862                sb->bucket_size * sb->first_bucket,
863                sb->bucket_size * (sb->nbuckets - sb->first_bucket),
864                sb->bucket_size * sb->nbuckets,
865                CACHE_SYNC(sb) ? "yes" : "no",
866                sb->nr_this_dev,
867                sb->nr_in_set);
868
869         show_cache_member(sb, sb->nr_this_dev);
870 }
871
872 static int __sysfs_attr_type(char *attr, const char **attr_arr) {
873         int i, j;
874         for(i = 0; attr_arr[i] != NULL; i++)
875                 if(!strcmp(attr, attr_arr[i]))
876                         return 1;
877         return 0;
878 }
879
880 enum sysfs_attr sysfs_attr_type(char *attr) {
881         int ret;
882         if(__sysfs_attr_type(attr, set_attrs))
883                 return SET_ATTR;
884         if(__sysfs_attr_type(attr, cache_attrs))
885                 return CACHE_ATTR;
886         if(__sysfs_attr_type(attr, internal_attrs))
887                 return INTERNAL_ATTR;
888
889         printf("No attribute called %s, try --list to see options\n", attr);
890
891         return -1;
892 }
893
894 static void __sysfs_attr_list(const char **attr_arr) {
895         int i, j;
896         for (i = 0; attr_arr[i] != NULL; i++)
897                 printf("%s\n", attr_arr[i]);
898 }
899
900 void sysfs_attr_list() {
901         __sysfs_attr_list(set_attrs);
902         __sysfs_attr_list(cache_attrs);
903         __sysfs_attr_list(internal_attrs);
904 }
905
906 struct cache_sb *query_dev(char *dev, bool force_csum,
907                 bool print_sb, bool uuid_only, char *dev_uuid)
908 {
909         size_t bytes = 4096;
910         struct cache_sb *sb = aligned_alloc(bytes, bytes);
911
912         int fd = open(dev, O_RDONLY|O_DIRECT);
913         if (fd < 0) {
914                 printf("Can't open dev %s: %s\n", dev, strerror(errno));
915                 return NULL;
916         }
917
918         while (true) {
919                 int ret = pread(fd, sb, bytes, SB_START);
920                 if (ret < 0) {
921                         fprintf(stderr, "Couldn't read superblock: %s\n",
922                                         strerror(errno));
923                         close(fd);
924                         free(sb);
925                         return NULL;
926                 } else if (bytes > sizeof(sb) + sb->keys * sizeof(u64)) {
927                         /* We read the whole superblock */
928                         break;
929                 }
930
931                 /*
932                  * otherwise double the size of our dest
933                  * and read again
934                  */
935                 free(sb);
936                 bytes *= 2;
937                 sb = aligned_alloc(4096, bytes);
938         }
939
940         close(fd);
941
942         if(uuid_only) {
943                 show_uuid_only(sb, dev_uuid);
944                 return sb;
945         }
946
947         if(print_sb) {
948                 if (!SB_IS_BDEV(sb))
949                         show_super_cache(sb, force_csum);
950                 else
951                         show_super_backingdev(sb, force_csum);
952         }
953
954         return sb;
955 }
956
957 static char *dev_name(const char *ugly_path) {
958         char buf[32];
959         int i, end = strlen(ugly_path);
960
961         //Chop off "/bcache", then look for the next '/' from the end
962         for (i = end - 8; ; i--)
963                 if(ugly_path[i] == '/')
964                         break;
965
966         strcpy(buf, ugly_path + i);
967         buf[end - i - 7] = 0;
968
969         // Is the dev guaranteed to be in /dev?
970         // This is needed for finding the superblock with a query-dev
971         return strdup(buf);
972 }
973
974 static void list_cacheset_devs(char *cset_dir, char *cset_name, bool parse_dev_name) {
975         int i = 0;
976         DIR *cachedir, *dir;
977         struct stat cache_stat;
978         char entry[MAX_PATH];
979         struct dirent *ent;
980         snprintf(entry, MAX_PATH, "%s/%s", cset_dir, cset_name);
981
982         if((dir = opendir(entry)) != NULL) {
983                 while((ent = readdir(dir)) != NULL) {
984                         char buf[MAX_PATH];
985                         int len;
986                         char *tmp;
987
988                         /*
989                          * We are looking for all cache# directories
990                          * do a strlen < 9 to skip over other entries
991                          * that also start with "cache"
992                          */
993                         if(strncmp(ent->d_name, "cache", 5) ||
994                                         !(strlen(ent->d_name) < 9))
995                                 continue;
996
997                         snprintf(entry, MAX_PATH, "%s/%s/%s",
998                                         cset_dir,
999                                         cset_name,
1000                                         ent->d_name);
1001
1002                         if((cachedir = opendir(entry)) == NULL)
1003                                 continue;
1004
1005                         if(stat(entry, &cache_stat))
1006                                 continue;
1007
1008                         if((len = readlink(entry, buf, sizeof(buf) - 1)) !=
1009                                         -1) {
1010                                 buf[len] = '\0';
1011                                 if(parse_dev_name) {
1012                                         tmp = dev_name(buf);
1013                                         printf("/dev%s\n", tmp);
1014                                         free(tmp);
1015                                 } else {
1016                                         printf("\t%s\n", buf);
1017                                 }
1018                         }
1019                 }
1020         }
1021 }
1022
1023 char *find_matching_uuid(char *stats_dir, char *subdir, const char *stats_dev_uuid) {
1024         /* Do a query-dev --uuid only to get the uuid
1025          * repeat on each dev until we find a matching one
1026          * append that cache# to subdir and return
1027          */
1028
1029         int i = 0;
1030         DIR *cachedir;
1031         struct stat cache_stat;
1032         char intbuf[4];
1033         char entry[MAX_PATH];
1034         char *err = NULL;
1035
1036         snprintf(entry, MAX_PATH, "%s%s", stats_dir, subdir);
1037         snprintf(intbuf, 4, "%d", i);
1038         strcat(entry, intbuf);
1039
1040         while(true) {
1041                 char buf[MAX_PATH];
1042                 int len;
1043
1044                 if((cachedir = opendir(entry)) == NULL)
1045                         break;
1046
1047                 if(stat(entry, &cache_stat))
1048                         break;
1049
1050                 if((len = readlink(entry, buf, sizeof(buf) - 1)) != -1) {
1051                         char dev_uuid[40];
1052                         buf[len] = '\0';
1053                         int i, end = strlen(buf);
1054                         char tmp[32], devname[32];
1055                         struct cache_sb *sb;
1056
1057                         /* Chop off "/bcache", then look for the
1058                          * next '/' from the end
1059                          */
1060                         for (i = end - 8; ; i--)
1061                                 if(buf[i] == '/')
1062                                         break;
1063
1064                         strcpy(tmp, buf + i);
1065                         tmp[end - i - 7] = 0;
1066                         strcpy(devname, "/dev");
1067                         strcat(devname, tmp);
1068
1069                         err = "Unable to open superblock";
1070                         sb = query_dev(devname, false, false, true, dev_uuid);
1071                         if(!sb)
1072                                 return err;
1073                         else
1074                                 free(sb);
1075
1076                         if(!strcmp(stats_dev_uuid, dev_uuid)) {
1077                                 strcat(subdir, intbuf);
1078                                 return NULL;
1079                         }
1080                 }
1081
1082                 /* remove i from end and append i++ */
1083                 entry[strlen(entry)-strlen(intbuf)] = 0;
1084                 i++;
1085                 snprintf(intbuf, 4, "%d", i);
1086                 strcat(entry, intbuf);
1087         }
1088
1089
1090         err = "dev uuid doesn't exist in cache_set";
1091         return err;
1092 }
1093
1094 char *list_cachesets(char *cset_dir, bool list_devs)
1095 {
1096         struct dirent *ent;
1097         DIR *dir;
1098         char *err = NULL;
1099
1100         dir = opendir(cset_dir);
1101         if (!dir) {
1102                 err = "Failed to open cacheset dir";
1103                 goto err;
1104         }
1105
1106         while ((ent = readdir(dir)) != NULL) {
1107                 struct stat statbuf;
1108                 char entry[MAX_PATH];
1109
1110                 if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
1111                         continue;
1112
1113                 snprintf(entry, MAX_PATH, "%s/%s", cset_dir, ent->d_name);
1114                 if(stat(entry, &statbuf) == -1) {
1115                         err = "Failed to stat cacheset subdir";
1116                         goto err;
1117                 }
1118
1119                 if (S_ISDIR(statbuf.st_mode)) {
1120                         printf("%s\n", ent->d_name);
1121
1122                         if(list_devs) {
1123                                 list_cacheset_devs(cset_dir, ent->d_name, true);
1124                         }
1125                 }
1126         }
1127
1128 err:
1129         closedir(dir);
1130         return err;
1131 }
1132
1133 char *register_bcache(char *const *devs)
1134 {
1135         int ret, bcachefd;
1136         char *err = NULL;
1137
1138         bcachefd = open("/dev/bcache", O_RDWR);
1139         if (bcachefd < 0) {
1140                 err = "Can't open bcache device";
1141                 goto err;
1142         }
1143
1144         ret = ioctl(bcachefd, BCH_IOCTL_REGISTER, devs);
1145         if (ret < 0) {
1146                 char tmp[64];
1147                 snprintf(tmp, 64, "ioctl register error: %s\n",
1148                                 strerror(ret));
1149                 err = strdup(tmp);
1150                 goto err;
1151         }
1152
1153 err:
1154         if (bcachefd)
1155                 close(bcachefd);
1156         return err;
1157 }
1158
1159 char *unregister_bcache(char *const *devs)
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         ret = ioctl(bcachefd, BCH_IOCTL_UNREGISTER, devs);
1171         if (ret < 0) {
1172                 char tmp[64];
1173                 snprintf(tmp, 64, "ioctl unregister error: %s\n",
1174                                 strerror(ret));
1175                 err = strdup(tmp);
1176                 goto err;
1177         }
1178
1179 err:
1180         close(bcachefd);
1181         return err;
1182 }
1183
1184 char *add_devices(char *const *devs, char *uuid)
1185 {
1186         int ret, bcachefd;
1187         char *err = NULL;
1188
1189         bcachefd = open("/dev/bcache", O_RDWR);
1190         if (bcachefd < 0) {
1191                 err = "Can't open bcache device";
1192                 goto err;
1193         }
1194
1195         struct bch_ioctl_add_disks ia;
1196         ia.devs = devs;
1197         ia.uuid = uuid;
1198
1199         ret = ioctl(bcachefd, BCH_IOCTL_ADD_DISKS, &ia);
1200         if (ret < 0) {
1201                 char tmp[128];
1202                 snprintf(tmp, 128, "ioctl add disk error: %s\n",
1203                                 strerror(ret));
1204                 err = strdup(tmp);
1205         }
1206
1207 err:
1208         close(bcachefd);
1209         return err;
1210 }
1211
1212 char *remove_device(const char *dev, bool force)
1213 {
1214         int ret, bcachefd;
1215         char *err = NULL;
1216
1217         bcachefd = open("/dev/bcache", O_RDWR);
1218         if (bcachefd < 0) {
1219                 err = "Can't open bcache device";
1220                 goto err;
1221         }
1222
1223         struct bch_ioctl_rm_disk ir;
1224         ir.dev = dev;
1225         ir.force = force ? 1 : 0;
1226
1227         ret = ioctl(bcachefd, BCH_IOCTL_RM_DISK, &ir);
1228         if (ret < 0) {
1229                 char tmp[128];
1230                 snprintf(tmp, 128, "ioctl add disk error: %s\n",
1231                                 strerror(ret));
1232                 err = strdup(tmp);
1233         }
1234
1235 err:
1236         close(bcachefd);
1237         return err;
1238 }
1239
1240 char *probe(char *dev, int udev)
1241 {
1242         struct cache_sb sb;
1243         char uuid[40];
1244         blkid_probe pr;
1245         char *err = NULL;
1246
1247         int fd = open(dev, O_RDONLY);
1248         if (fd == -1) {
1249                 err = "Got file descriptor -1 trying to open dev";
1250                 goto err;
1251         }
1252
1253         if (!(pr = blkid_new_probe())) {
1254                 err = "Failed trying to get a blkid for new probe";
1255                 goto err;
1256         }
1257
1258         if (blkid_probe_set_device(pr, fd, 0, 0)) {
1259                 err = "Failed blkid probe set device";
1260                 goto err;
1261         }
1262
1263         /* probe partitions too */
1264         if (blkid_probe_enable_partitions(pr, true)) {
1265                 err = "Enable probe partitions";
1266                 goto err;
1267         }
1268
1269         /* bail if anything was found
1270          * probe-bcache isn't needed once blkid recognizes bcache */
1271         if (!blkid_do_probe(pr)) {
1272                 err = "blkid recognizes bcache";
1273                 goto err;
1274         }
1275
1276         if (pread(fd, &sb, sizeof(sb), SB_START) != sizeof(sb)) {
1277                 err = "Failed to read superblock";
1278                 goto err;
1279         }
1280
1281         if (memcmp(&sb.magic, &BCACHE_MAGIC, sizeof(sb.magic))) {
1282                 err = "Bcache magic incorrect";
1283                 goto err;
1284         }
1285
1286         uuid_unparse(sb.uuid.b, uuid);
1287
1288         if (udev)
1289                 printf("ID_FS_UUID=%s\n"
1290                        "ID_FS_UUID_ENC=%s\n"
1291                        "ID_FS_TYPE=bcache\n",
1292                        uuid, uuid);
1293         else
1294                 printf("%s: UUID=\"\" TYPE=\"bcache\"\n", uuid);
1295
1296         return 0;
1297
1298 err:
1299         return err;
1300 }
1301
1302 char *read_stat_dir(DIR *dir, char *stats_dir, char *stat_name, char *ret)
1303 {
1304         struct stat statbuf;
1305         char entry[MAX_PATH];
1306         char *err = NULL;
1307
1308         snprintf(entry, MAX_PATH, "%s/%s", stats_dir, stat_name);
1309         if(stat(entry, &statbuf) == -1) {
1310                 char tmp[MAX_PATH];
1311                 snprintf(tmp, MAX_PATH, "Failed to stat %s\n", entry);
1312                 err = strdup(tmp);
1313                 goto err;
1314         }
1315
1316         if (S_ISREG(statbuf.st_mode)) {
1317                 char buf[MAX_PATH];
1318                 FILE *fp = NULL;
1319
1320                 fp = fopen(entry, "r");
1321                 if(!fp) {
1322                         /* If we can't open the file, this is probably because
1323                          * of permissions, just move to the next file */
1324                         return NULL;
1325                 }
1326
1327                 while(fgets(ret, MAX_PATH, fp));
1328                 fclose(fp);
1329         }
1330 err:
1331         return err;
1332 }
1333
1334 char *bcache_get_capacity(const char *cset_dir, const char *capacity_uuid,
1335                 bool show_devs)
1336 {
1337         char *err = NULL;
1338         char bucket_size_path[MAX_PATH];
1339         char nbuckets_path[MAX_PATH];
1340         char avail_buckets_path[MAX_PATH];
1341         char cache_path[MAX_PATH];
1342
1343         double bucket_sizes[MAX_DEVS];
1344         double nbuckets[MAX_DEVS];
1345         double avail_buckets[MAX_DEVS];
1346         char *dev_names[MAX_DEVS];
1347         int dev_count = 0, i;
1348         char intbuf[4];
1349         double total_cap = 0, total_free = 0;
1350         int precision = 2;
1351
1352         snprintf(intbuf, 4, "%d", i);
1353         snprintf(bucket_size_path, MAX_PATH, "%s/%s/%s/%s", cset_dir,
1354                         capacity_uuid, "cache0", "bucket_size_bytes");
1355         snprintf(nbuckets_path, MAX_PATH, "%s/%s/%s/%s", cset_dir,
1356                         capacity_uuid, "cache0", "nbuckets");
1357         snprintf(avail_buckets_path, MAX_PATH, "%s/%s/%s/%s", cset_dir,
1358                         capacity_uuid, "cache0", "available_buckets");
1359         snprintf(cache_path, MAX_PATH, "%s/%s/%s", cset_dir, capacity_uuid,
1360                         "cache0");
1361
1362         while(true) {
1363                 char buf[MAX_PATH];
1364                 int len;
1365                 DIR *cache_dir;
1366
1367                 if((cache_dir = opendir(cache_path)) == NULL)
1368                         break;
1369
1370                 err = read_stat_dir(cache_dir, cache_path,
1371                                 "bucket_size_bytes", buf);
1372                 if (err)
1373                         goto err;
1374                 else
1375                         bucket_sizes[dev_count] = atof(buf);
1376
1377                 err = read_stat_dir(cache_dir, cache_path,
1378                                 "nbuckets", buf);
1379                 if (err)
1380                         goto err;
1381                 else
1382                         nbuckets[dev_count] = atof(buf);
1383
1384                 err = read_stat_dir(cache_dir, cache_path,
1385                                 "available_buckets", buf);
1386                 if (err)
1387                         goto err;
1388                 else
1389                         avail_buckets[dev_count] = atof(buf);
1390
1391                 if((len = readlink(cache_path, buf, sizeof(buf) - 1)) != -1) {
1392                         buf[len] = '\0';
1393                         dev_names[dev_count] = dev_name(buf);
1394                 }
1395
1396                 /* remove i/stat and append i++/stat */
1397                 bucket_size_path[strlen(cache_path) - strlen(intbuf)] = 0;
1398                 nbuckets_path[strlen(cache_path) - strlen(intbuf)] = 0;
1399                 avail_buckets_path[strlen(cache_path) - strlen(intbuf)] = 0;
1400                 cache_path[strlen(cache_path) - strlen(intbuf)] = 0;
1401
1402                 dev_count++;
1403
1404                 snprintf(intbuf, 4, "%d", dev_count);
1405                 strcat(cache_path, intbuf);
1406                 strcat(bucket_size_path, intbuf);
1407                 strcat(nbuckets_path, intbuf);
1408                 strcat(avail_buckets_path, intbuf);
1409         }
1410
1411         printf("%-15s%-25s%-25s\n", "Device Name", "Capacity (512 Blocks)", "Free (512 Blocks)");
1412
1413         if (show_devs) {
1414                 for (i = 0; i < dev_count; i++) {
1415                         printf("%s%-11s%-25.*f%-25.*f\n", "/dev", dev_names[i],
1416                                 precision,
1417                                 (bucket_sizes[i] * nbuckets[i]) / 512,
1418                                 precision,
1419                                 (bucket_sizes[i] * avail_buckets[i]) / 512);
1420                 }
1421         }
1422
1423         for (i = 0; i < dev_count; i++) {
1424                 total_cap += (bucket_sizes[i] * nbuckets[i]) / 512;
1425                 total_free += (bucket_sizes[i] * avail_buckets[i]) / 512;
1426
1427         }
1428
1429         printf("%-15s%-25.*f%-25.*f\n", "Total", precision, total_cap,
1430                         precision, total_free);
1431
1432 err:
1433         for (i = 0; i < dev_count; i++)
1434                 if (dev_names[i])
1435                         free(dev_names[i]);
1436         return err;
1437 }