]> git.sesse.net Git - bcachefs-tools-debian/blob - bcache.c
bcacheadm: fix status command
[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 struct cache_sb *query_dev(char *dev, bool force_csum,
872                 bool print_sb, bool uuid_only, char *dev_uuid)
873 {
874         struct cache_sb sb_stack, *sb = &sb_stack;
875         size_t bytes = sizeof(*sb);
876
877         int fd = open(dev, O_RDONLY);
878         if (fd < 0) {
879                 printf("Can't open dev %s: %s\n", dev, strerror(errno));
880                 exit(2);
881         }
882         printf("opened sb for %s\n", dev);
883
884         if (pread(fd, sb, bytes, SB_START) != bytes) {
885                 fprintf(stderr, "Couldn't read\n");
886                 exit(2);
887         }
888
889         if (sb->keys) {
890                 bytes = sizeof(*sb) + sb->keys * sizeof(uint64_t);
891                 sb = malloc(bytes);
892
893                 if (pread(fd, sb, bytes, SB_START) != bytes) {
894                         fprintf(stderr, "Couldn't read\n");
895                         exit(2);
896                 }
897         }
898
899         if(uuid_only) {
900                 show_uuid_only(sb, dev_uuid);
901                 return sb;
902         }
903
904         if(print_sb) {
905                 if (!SB_IS_BDEV(sb))
906                         show_super_cache(sb, force_csum);
907                 else
908                         show_super_backingdev(sb, force_csum);
909         }
910
911         return sb;
912 }
913
914 static void dev_name(const char *ugly_path) {
915         char buf[32];
916         int i, end = strlen(ugly_path);
917
918         //Chop off "/bcache", then look for the next '/' from the end
919         for (i = end - 8; ; i--)
920                 if(ugly_path[i] == '/')
921                         break;
922
923         strcpy(buf, ugly_path + i);
924         buf[end - i - 7] = 0;
925
926         // Is the dev guaranteed to be in /dev?
927         // This is needed for finding the superblock with a query-dev
928         printf("/dev%s\n", buf);
929 }
930
931 static void list_cacheset_devs(char *cset_dir, char *cset_name, bool parse_dev_name) {
932         int i = 0;
933         DIR *cachedir;
934         struct stat cache_stat;
935         char intbuf[4];
936         char entry[MAX_PATH];
937
938         snprintf(entry, MAX_PATH, "%s/%s/cache0", cset_dir, cset_name);
939         snprintf(intbuf, 4, "%d", i);
940
941         while(true) {
942                 char buf[MAX_PATH];
943                 int len;
944
945                 if((cachedir = opendir(entry)) == NULL)
946                         break;
947
948                 if(stat(entry, &cache_stat))
949                         break;
950
951                 if((len = readlink(entry, buf, sizeof(buf) - 1)) != -1) {
952                         buf[len] = '\0';
953                         if(parse_dev_name)
954                                 dev_name(buf);
955                         else
956                                 printf("\t%s\n", buf);
957                 }
958
959                 /* remove i from end and append i++ */
960                 entry[strlen(entry)-strlen(intbuf)] = 0;
961                 i++;
962                 snprintf(intbuf, 4, "%d", i);
963                 strcat(entry, intbuf);
964         }
965 }
966
967 char *find_matching_uuid(char *stats_dir, char *subdir, const char *stats_dev_uuid) {
968         /* Do a query-dev --uuid only to get the uuid
969          * repeat on each dev until we find a matching one
970          * append that cache# to subdir and return
971          */
972
973         int i = 0;
974         DIR *cachedir;
975         struct stat cache_stat;
976         char intbuf[4];
977         char entry[MAX_PATH];
978         char *err = NULL;
979
980         snprintf(entry, MAX_PATH, "%s%s", stats_dir, subdir);
981         snprintf(intbuf, 4, "%d", i);
982         strcat(entry, intbuf);
983
984         while(true) {
985                 char buf[MAX_PATH];
986                 int len;
987
988                 if((cachedir = opendir(entry)) == NULL)
989                         break;
990
991                 if(stat(entry, &cache_stat))
992                         break;
993
994                 if((len = readlink(entry, buf, sizeof(buf) - 1)) != -1) {
995                         char dev_uuid[40];
996                         buf[len] = '\0';
997                         int i, end = strlen(buf);
998                         char tmp[32], devname[32];
999
1000                         /* Chop off "/bcache", then look for the
1001                          * next '/' from the end
1002                          */
1003                         for (i = end - 8; ; i--)
1004                                 if(buf[i] == '/')
1005                                         break;
1006
1007                         strcpy(tmp, buf + i);
1008                         tmp[end - i - 7] = 0;
1009                         strcpy(devname, "/dev");
1010                         strcat(devname, tmp);
1011
1012                         query_dev(devname, false, false, true, dev_uuid);
1013                         if(!strcmp(stats_dev_uuid, dev_uuid)) {
1014                                 strcat(subdir, intbuf);
1015                                 return err;
1016                         }
1017                 }
1018
1019                 /* remove i from end and append i++ */
1020                 entry[strlen(entry)-strlen(intbuf)] = 0;
1021                 i++;
1022                 snprintf(intbuf, 4, "%d", i);
1023                 strcat(entry, intbuf);
1024         }
1025
1026
1027         err = "dev uuid doesn't exist in cache_set";
1028         return err;
1029 }
1030
1031 char *list_cachesets(char *cset_dir, bool list_devs)
1032 {
1033         struct dirent *ent;
1034         DIR *dir;
1035         char *err = NULL;
1036
1037         dir = opendir(cset_dir);
1038         if (!dir) {
1039                 err = "Failed to open cacheset dir";
1040                 goto err;
1041         }
1042
1043         while ((ent = readdir(dir)) != NULL) {
1044                 struct stat statbuf;
1045                 char entry[MAX_PATH];
1046
1047                 if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
1048                         continue;
1049
1050                 snprintf(entry, MAX_PATH, "%s/%s", cset_dir, ent->d_name);
1051                 if(stat(entry, &statbuf) == -1) {
1052                         err = "Failed to stat cacheset subdir";
1053                         goto err;
1054                 }
1055
1056                 if (S_ISDIR(statbuf.st_mode)) {
1057                         printf("%s\n", ent->d_name);
1058
1059                         if(list_devs) {
1060                                 list_cacheset_devs(cset_dir, ent->d_name, true);
1061                         }
1062                 }
1063         }
1064
1065 err:
1066         closedir(dir);
1067         return err;
1068 }
1069
1070 char *register_bcache(char *const *devs)
1071 {
1072         int ret, bcachefd;
1073         char *err = NULL;
1074
1075         bcachefd = open("/dev/bcache", O_RDWR);
1076         if (bcachefd < 0) {
1077                 err = "Can't open bcache device";
1078                 goto err;
1079         }
1080
1081         ret = ioctl(bcachefd, BCH_IOCTL_REGISTER, devs);
1082         if (ret < 0) {
1083                 char tmp[64];
1084                 snprintf(tmp, 64, "ioctl register error: %s\n",
1085                                 strerror(ret));
1086                 err = strdup(tmp);
1087                 goto err;
1088         }
1089
1090 err:
1091         if (bcachefd)
1092                 close(bcachefd);
1093         return err;
1094 }
1095
1096 char *unregister_bcache(char *const *devs)
1097 {
1098         int ret, bcachefd;
1099         char *err = NULL;
1100
1101         bcachefd = open("/dev/bcache", O_RDWR);
1102         if (bcachefd < 0) {
1103                 err = "Can't open bcache device";
1104                 goto err;
1105         }
1106
1107         ret = ioctl(bcachefd, BCH_IOCTL_UNREGISTER, devs);
1108         if (ret < 0) {
1109                 char tmp[64];
1110                 snprintf(tmp, 64, "ioctl unregister error: %s\n",
1111                                 strerror(ret));
1112                 err = strdup(tmp);
1113                 goto err;
1114         }
1115
1116 err:
1117         close(bcachefd);
1118         return err;
1119 }
1120
1121 char *add_devices(char *const *devs, char *uuid)
1122 {
1123         int ret, bcachefd;
1124         char *err = NULL;
1125
1126         bcachefd = open("/dev/bcache", O_RDWR);
1127         if (bcachefd < 0) {
1128                 err = "Can't open bcache device";
1129                 goto err;
1130         }
1131
1132         struct bch_ioctl_add_disks ia;
1133         ia.devs = devs;
1134         ia.uuid = uuid;
1135
1136         ret = ioctl(bcachefd, BCH_IOCTL_ADD_DISKS, &ia);
1137         if (ret < 0) {
1138                 char tmp[128];
1139                 snprintf(tmp, 128, "ioctl add disk error: %s\n",
1140                                 strerror(ret));
1141                 err = strdup(tmp);
1142         }
1143
1144 err:
1145         close(bcachefd);
1146         return err;
1147 }
1148
1149 char *remove_device(const char *dev, bool force)
1150 {
1151         int ret, bcachefd;
1152         char *err = NULL;
1153
1154         bcachefd = open("/dev/bcache", O_RDWR);
1155         if (bcachefd < 0) {
1156                 err = "Can't open bcache device";
1157                 goto err;
1158         }
1159
1160         struct bch_ioctl_rm_disk ir;
1161         ir.dev = dev;
1162         ir.force = force ? 1 : 0;
1163
1164         ret = ioctl(bcachefd, BCH_IOCTL_RM_DISK, &ir);
1165         if (ret < 0) {
1166                 char tmp[128];
1167                 snprintf(tmp, 128, "ioctl add disk error: %s\n",
1168                                 strerror(ret));
1169                 err = strdup(tmp);
1170         }
1171
1172 err:
1173         close(bcachefd);
1174         return err;
1175 }
1176
1177 char *probe(char *dev, int udev)
1178 {
1179         struct cache_sb sb;
1180         char uuid[40];
1181         blkid_probe pr;
1182         char *err = NULL;
1183
1184         int fd = open(dev, O_RDONLY);
1185         if (fd == -1) {
1186                 err = "Got file descriptor -1 trying to open dev";
1187                 goto err;
1188         }
1189
1190         if (!(pr = blkid_new_probe())) {
1191                 err = "Failed trying to get a blkid for new probe";
1192                 goto err;
1193         }
1194
1195         if (blkid_probe_set_device(pr, fd, 0, 0)) {
1196                 err = "Failed blkid probe set device";
1197                 goto err;
1198         }
1199
1200         /* probe partitions too */
1201         if (blkid_probe_enable_partitions(pr, true)) {
1202                 err = "Enable probe partitions";
1203                 goto err;
1204         }
1205
1206         /* bail if anything was found
1207          * probe-bcache isn't needed once blkid recognizes bcache */
1208         if (!blkid_do_probe(pr)) {
1209                 err = "blkid recognizes bcache";
1210                 goto err;
1211         }
1212
1213         if (pread(fd, &sb, sizeof(sb), SB_START) != sizeof(sb)) {
1214                 err = "Failed to read superblock";
1215                 goto err;
1216         }
1217
1218         if (memcmp(&sb.magic, &BCACHE_MAGIC, sizeof(sb.magic))) {
1219                 err = "Bcache magic incorrect";
1220                 goto err;
1221         }
1222
1223         uuid_unparse(sb.uuid.b, uuid);
1224
1225         if (udev)
1226                 printf("ID_FS_UUID=%s\n"
1227                        "ID_FS_UUID_ENC=%s\n"
1228                        "ID_FS_TYPE=bcache\n",
1229                        uuid, uuid);
1230         else
1231                 printf("%s: UUID=\"\" TYPE=\"bcache\"\n", uuid);
1232
1233         return 0;
1234
1235 err:
1236         return err;
1237 }
1238
1239 char *read_stat_dir(DIR *dir, char *stats_dir, char *stat_name, bool print_val)
1240 {
1241         struct stat statbuf;
1242         char entry[MAX_PATH];
1243         char *err = NULL;
1244
1245         snprintf(entry, MAX_PATH, "%s/%s", stats_dir, stat_name);
1246         if(stat(entry, &statbuf) == -1) {
1247                 char tmp[MAX_PATH];
1248                 snprintf(tmp, MAX_PATH, "Failed to stat %s\n", entry);
1249                 err = strdup(tmp);
1250                 goto err;
1251         }
1252
1253         if (S_ISREG(statbuf.st_mode)) {
1254                 char buf[MAX_PATH];
1255                 FILE *fp = NULL;
1256
1257                 fp = fopen(entry, "r");
1258                 if(!fp) {
1259                         /* If we can't open the file, this is probably because
1260                          * of permissions, just move to the next file */
1261                         return NULL;
1262                 }
1263
1264                 while(fgets(buf, MAX_PATH, fp));
1265
1266                 if(print_val)
1267                         printf("%s\n", buf);
1268                 else
1269                         printf("%s\n", stat_name);
1270                 fclose(fp);
1271         }
1272 err:
1273         return err;
1274 }