15 #include <sys/ioctl.h>
16 #include <sys/types.h>
20 #include <uuid/uuid.h>
26 #include <linux/bcache-ioctl.h>
29 const char * const cache_state[] = {
37 const char * const replacement_policies[] = {
44 const char * const csum_types[] = {
51 const char * const bdev_cache_mode[] = {
59 const char * const bdev_state[] = {
67 const char * const set_attrs[] = {
69 "btree_scan_ratelimit",
70 "bucket_reserve_percent",
71 "cache_reserve_percent",
73 "congested_read_threshold_us",
74 "congested_write_threshold_us",
77 "foreground_target_percent",
81 "sector_reserve_percent",
86 const char * const cache_attrs[] = {
87 "cache_replacement_policy",
94 const char * const internal_attrs[] = {
95 "btree_shrinker_disabled",
97 "foreground_write_rate",
103 char *skip_spaces(const char *str)
105 while (isspace(*str))
121 while (end >= s && isspace(*end))
128 ssize_t read_string_list(const char *buf, const char * const list[])
131 char *s, *d = strdup(buf);
137 for (i = 0; list[i]; i++)
138 if (!strcmp(list[i], s))
149 ssize_t read_string_list_or_die(const char *opt, const char * const list[],
152 ssize_t v = read_string_list(opt, list);
154 fprintf(stderr, "Bad %s %s\n", msg, opt);
162 void print_string_list(const char * const list[], size_t selected)
166 for (i = 0; list[i]; i++) {
169 printf(i == selected ? "[%s] ": "%s", list[i]);
174 * This is the CRC-32C table
178 * reflect input bytes = true
179 * reflect output bytes = true
182 static const u32 crc32c_table[256] = {
183 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
184 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
185 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
186 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
187 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
188 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
189 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
190 0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
191 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
192 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
193 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
194 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
195 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
196 0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
197 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
198 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
199 0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
200 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
201 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
202 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
203 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
204 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
205 0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
206 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
207 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
208 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
209 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
210 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
211 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
212 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
213 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
214 0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
215 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
216 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
217 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
218 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
219 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
220 0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
221 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
222 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
223 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
224 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
225 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
226 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
227 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
228 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
229 0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
230 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
231 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
232 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
233 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
234 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
235 0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
236 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
237 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
238 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
239 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
240 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
241 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
242 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
243 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
244 0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
245 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
246 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L
250 * Steps through buffer one byte at at time, calculates reflected
254 static u32 crc32c(u32 crc, unsigned char const *data, size_t length)
258 crc32c_table[(crc ^ *data++) & 0xFFL] ^ (crc >> 8);
263 * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group (Any
264 * use permitted, subject to terms of PostgreSQL license; see.)
266 * If we have a 64-bit integer type, then a 64-bit CRC looks just like the
267 * usual sort of implementation. (See Ross Williams' excellent introduction
268 * A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS, available from
269 * ftp://ftp.rocksoft.com/papers/crc_v3.txt or several other net sites.)
270 * If we have no working 64-bit type, then fake it with two 32-bit registers.
272 * The present implementation is a normal (not "reflected", in Williams'
273 * terms) 64-bit CRC, using initial all-ones register contents and a final
274 * bit inversion. The chosen polynomial is borrowed from the DLT1 spec
275 * (ECMA-182, available from http://www.ecma.ch/ecma1/STAND/ECMA-182.HTM):
277 * x^64 + x^62 + x^57 + x^55 + x^54 + x^53 + x^52 + x^47 + x^46 + x^45 +
278 * x^40 + x^39 + x^38 + x^37 + x^35 + x^33 + x^32 + x^31 + x^29 + x^27 +
279 * x^24 + x^23 + x^22 + x^21 + x^19 + x^17 + x^13 + x^12 + x^10 + x^9 +
283 static const uint64_t crc_table[256] = {
284 0x0000000000000000ULL, 0x42F0E1EBA9EA3693ULL, 0x85E1C3D753D46D26ULL,
285 0xC711223CFA3E5BB5ULL, 0x493366450E42ECDFULL, 0x0BC387AEA7A8DA4CULL,
286 0xCCD2A5925D9681F9ULL, 0x8E224479F47CB76AULL, 0x9266CC8A1C85D9BEULL,
287 0xD0962D61B56FEF2DULL, 0x17870F5D4F51B498ULL, 0x5577EEB6E6BB820BULL,
288 0xDB55AACF12C73561ULL, 0x99A54B24BB2D03F2ULL, 0x5EB4691841135847ULL,
289 0x1C4488F3E8F96ED4ULL, 0x663D78FF90E185EFULL, 0x24CD9914390BB37CULL,
290 0xE3DCBB28C335E8C9ULL, 0xA12C5AC36ADFDE5AULL, 0x2F0E1EBA9EA36930ULL,
291 0x6DFEFF5137495FA3ULL, 0xAAEFDD6DCD770416ULL, 0xE81F3C86649D3285ULL,
292 0xF45BB4758C645C51ULL, 0xB6AB559E258E6AC2ULL, 0x71BA77A2DFB03177ULL,
293 0x334A9649765A07E4ULL, 0xBD68D2308226B08EULL, 0xFF9833DB2BCC861DULL,
294 0x388911E7D1F2DDA8ULL, 0x7A79F00C7818EB3BULL, 0xCC7AF1FF21C30BDEULL,
295 0x8E8A101488293D4DULL, 0x499B3228721766F8ULL, 0x0B6BD3C3DBFD506BULL,
296 0x854997BA2F81E701ULL, 0xC7B97651866BD192ULL, 0x00A8546D7C558A27ULL,
297 0x4258B586D5BFBCB4ULL, 0x5E1C3D753D46D260ULL, 0x1CECDC9E94ACE4F3ULL,
298 0xDBFDFEA26E92BF46ULL, 0x990D1F49C77889D5ULL, 0x172F5B3033043EBFULL,
299 0x55DFBADB9AEE082CULL, 0x92CE98E760D05399ULL, 0xD03E790CC93A650AULL,
300 0xAA478900B1228E31ULL, 0xE8B768EB18C8B8A2ULL, 0x2FA64AD7E2F6E317ULL,
301 0x6D56AB3C4B1CD584ULL, 0xE374EF45BF6062EEULL, 0xA1840EAE168A547DULL,
302 0x66952C92ECB40FC8ULL, 0x2465CD79455E395BULL, 0x3821458AADA7578FULL,
303 0x7AD1A461044D611CULL, 0xBDC0865DFE733AA9ULL, 0xFF3067B657990C3AULL,
304 0x711223CFA3E5BB50ULL, 0x33E2C2240A0F8DC3ULL, 0xF4F3E018F031D676ULL,
305 0xB60301F359DBE0E5ULL, 0xDA050215EA6C212FULL, 0x98F5E3FE438617BCULL,
306 0x5FE4C1C2B9B84C09ULL, 0x1D14202910527A9AULL, 0x93366450E42ECDF0ULL,
307 0xD1C685BB4DC4FB63ULL, 0x16D7A787B7FAA0D6ULL, 0x5427466C1E109645ULL,
308 0x4863CE9FF6E9F891ULL, 0x0A932F745F03CE02ULL, 0xCD820D48A53D95B7ULL,
309 0x8F72ECA30CD7A324ULL, 0x0150A8DAF8AB144EULL, 0x43A04931514122DDULL,
310 0x84B16B0DAB7F7968ULL, 0xC6418AE602954FFBULL, 0xBC387AEA7A8DA4C0ULL,
311 0xFEC89B01D3679253ULL, 0x39D9B93D2959C9E6ULL, 0x7B2958D680B3FF75ULL,
312 0xF50B1CAF74CF481FULL, 0xB7FBFD44DD257E8CULL, 0x70EADF78271B2539ULL,
313 0x321A3E938EF113AAULL, 0x2E5EB66066087D7EULL, 0x6CAE578BCFE24BEDULL,
314 0xABBF75B735DC1058ULL, 0xE94F945C9C3626CBULL, 0x676DD025684A91A1ULL,
315 0x259D31CEC1A0A732ULL, 0xE28C13F23B9EFC87ULL, 0xA07CF2199274CA14ULL,
316 0x167FF3EACBAF2AF1ULL, 0x548F120162451C62ULL, 0x939E303D987B47D7ULL,
317 0xD16ED1D631917144ULL, 0x5F4C95AFC5EDC62EULL, 0x1DBC74446C07F0BDULL,
318 0xDAAD56789639AB08ULL, 0x985DB7933FD39D9BULL, 0x84193F60D72AF34FULL,
319 0xC6E9DE8B7EC0C5DCULL, 0x01F8FCB784FE9E69ULL, 0x43081D5C2D14A8FAULL,
320 0xCD2A5925D9681F90ULL, 0x8FDAB8CE70822903ULL, 0x48CB9AF28ABC72B6ULL,
321 0x0A3B7B1923564425ULL, 0x70428B155B4EAF1EULL, 0x32B26AFEF2A4998DULL,
322 0xF5A348C2089AC238ULL, 0xB753A929A170F4ABULL, 0x3971ED50550C43C1ULL,
323 0x7B810CBBFCE67552ULL, 0xBC902E8706D82EE7ULL, 0xFE60CF6CAF321874ULL,
324 0xE224479F47CB76A0ULL, 0xA0D4A674EE214033ULL, 0x67C58448141F1B86ULL,
325 0x253565A3BDF52D15ULL, 0xAB1721DA49899A7FULL, 0xE9E7C031E063ACECULL,
326 0x2EF6E20D1A5DF759ULL, 0x6C0603E6B3B7C1CAULL, 0xF6FAE5C07D3274CDULL,
327 0xB40A042BD4D8425EULL, 0x731B26172EE619EBULL, 0x31EBC7FC870C2F78ULL,
328 0xBFC9838573709812ULL, 0xFD39626EDA9AAE81ULL, 0x3A28405220A4F534ULL,
329 0x78D8A1B9894EC3A7ULL, 0x649C294A61B7AD73ULL, 0x266CC8A1C85D9BE0ULL,
330 0xE17DEA9D3263C055ULL, 0xA38D0B769B89F6C6ULL, 0x2DAF4F0F6FF541ACULL,
331 0x6F5FAEE4C61F773FULL, 0xA84E8CD83C212C8AULL, 0xEABE6D3395CB1A19ULL,
332 0x90C79D3FEDD3F122ULL, 0xD2377CD44439C7B1ULL, 0x15265EE8BE079C04ULL,
333 0x57D6BF0317EDAA97ULL, 0xD9F4FB7AE3911DFDULL, 0x9B041A914A7B2B6EULL,
334 0x5C1538ADB04570DBULL, 0x1EE5D94619AF4648ULL, 0x02A151B5F156289CULL,
335 0x4051B05E58BC1E0FULL, 0x87409262A28245BAULL, 0xC5B073890B687329ULL,
336 0x4B9237F0FF14C443ULL, 0x0962D61B56FEF2D0ULL, 0xCE73F427ACC0A965ULL,
337 0x8C8315CC052A9FF6ULL, 0x3A80143F5CF17F13ULL, 0x7870F5D4F51B4980ULL,
338 0xBF61D7E80F251235ULL, 0xFD913603A6CF24A6ULL, 0x73B3727A52B393CCULL,
339 0x31439391FB59A55FULL, 0xF652B1AD0167FEEAULL, 0xB4A25046A88DC879ULL,
340 0xA8E6D8B54074A6ADULL, 0xEA16395EE99E903EULL, 0x2D071B6213A0CB8BULL,
341 0x6FF7FA89BA4AFD18ULL, 0xE1D5BEF04E364A72ULL, 0xA3255F1BE7DC7CE1ULL,
342 0x64347D271DE22754ULL, 0x26C49CCCB40811C7ULL, 0x5CBD6CC0CC10FAFCULL,
343 0x1E4D8D2B65FACC6FULL, 0xD95CAF179FC497DAULL, 0x9BAC4EFC362EA149ULL,
344 0x158E0A85C2521623ULL, 0x577EEB6E6BB820B0ULL, 0x906FC95291867B05ULL,
345 0xD29F28B9386C4D96ULL, 0xCEDBA04AD0952342ULL, 0x8C2B41A1797F15D1ULL,
346 0x4B3A639D83414E64ULL, 0x09CA82762AAB78F7ULL, 0x87E8C60FDED7CF9DULL,
347 0xC51827E4773DF90EULL, 0x020905D88D03A2BBULL, 0x40F9E43324E99428ULL,
348 0x2CFFE7D5975E55E2ULL, 0x6E0F063E3EB46371ULL, 0xA91E2402C48A38C4ULL,
349 0xEBEEC5E96D600E57ULL, 0x65CC8190991CB93DULL, 0x273C607B30F68FAEULL,
350 0xE02D4247CAC8D41BULL, 0xA2DDA3AC6322E288ULL, 0xBE992B5F8BDB8C5CULL,
351 0xFC69CAB42231BACFULL, 0x3B78E888D80FE17AULL, 0x7988096371E5D7E9ULL,
352 0xF7AA4D1A85996083ULL, 0xB55AACF12C735610ULL, 0x724B8ECDD64D0DA5ULL,
353 0x30BB6F267FA73B36ULL, 0x4AC29F2A07BFD00DULL, 0x08327EC1AE55E69EULL,
354 0xCF235CFD546BBD2BULL, 0x8DD3BD16FD818BB8ULL, 0x03F1F96F09FD3CD2ULL,
355 0x41011884A0170A41ULL, 0x86103AB85A2951F4ULL, 0xC4E0DB53F3C36767ULL,
356 0xD8A453A01B3A09B3ULL, 0x9A54B24BB2D03F20ULL, 0x5D45907748EE6495ULL,
357 0x1FB5719CE1045206ULL, 0x919735E51578E56CULL, 0xD367D40EBC92D3FFULL,
358 0x1476F63246AC884AULL, 0x568617D9EF46BED9ULL, 0xE085162AB69D5E3CULL,
359 0xA275F7C11F7768AFULL, 0x6564D5FDE549331AULL, 0x279434164CA30589ULL,
360 0xA9B6706FB8DFB2E3ULL, 0xEB46918411358470ULL, 0x2C57B3B8EB0BDFC5ULL,
361 0x6EA7525342E1E956ULL, 0x72E3DAA0AA188782ULL, 0x30133B4B03F2B111ULL,
362 0xF7021977F9CCEAA4ULL, 0xB5F2F89C5026DC37ULL, 0x3BD0BCE5A45A6B5DULL,
363 0x79205D0E0DB05DCEULL, 0xBE317F32F78E067BULL, 0xFCC19ED95E6430E8ULL,
364 0x86B86ED5267CDBD3ULL, 0xC4488F3E8F96ED40ULL, 0x0359AD0275A8B6F5ULL,
365 0x41A94CE9DC428066ULL, 0xCF8B0890283E370CULL, 0x8D7BE97B81D4019FULL,
366 0x4A6ACB477BEA5A2AULL, 0x089A2AACD2006CB9ULL, 0x14DEA25F3AF9026DULL,
367 0x562E43B4931334FEULL, 0x913F6188692D6F4BULL, 0xD3CF8063C0C759D8ULL,
368 0x5DEDC41A34BBEEB2ULL, 0x1F1D25F19D51D821ULL, 0xD80C07CD676F8394ULL,
369 0x9AFCE626CE85B507ULL
372 static uint64_t bch_crc64_update(uint64_t crc, const void *_data, size_t len)
374 const unsigned char *data = _data;
377 int i = ((int) (crc >> 56) ^ *data++) & 0xFF;
378 crc = crc_table[i] ^ (crc << 8);
384 static uint64_t bch_checksum_update(unsigned type, uint64_t crc, const void *data, size_t len)
389 case BCH_CSUM_CRC32C:
390 return crc32c(crc, data, len);
392 return bch_crc64_update(crc, data, len);
394 fprintf(stderr, "Unknown checksum type %u\n", type);
399 uint64_t bch_checksum(unsigned type, const void *data, size_t len)
401 uint64_t crc = 0xffffffffffffffffULL;
403 crc = bch_checksum_update(type, crc, data, len);
405 return crc ^ 0xffffffffffffffffULL;
408 uint64_t getblocks(int fd)
412 if (fstat(fd, &statbuf)) {
413 perror("getblocks: stat error\n");
416 ret = statbuf.st_size / 512;
417 if (S_ISBLK(statbuf.st_mode))
418 if (ioctl(fd, BLKGETSIZE, &ret)) {
419 perror("ioctl error getting blksize");
425 uint64_t hatoi(const char *s)
428 long long i = strtoll(s, &e, 10);
446 unsigned hatoi_validate(const char *s, const char *msg)
448 uint64_t v = hatoi(s);
451 fprintf(stderr, "%s must be a power of two\n", msg);
458 fprintf(stderr, "%s too large\n", msg);
463 fprintf(stderr, "%s too small\n", msg);
470 static void do_write_sb(int fd, struct cache_sb *sb)
472 char zeroes[SB_START] = {0};
473 size_t bytes = ((void *) __bset_bkey_last(sb)) - (void *) sb;
475 /* Zero start of disk */
476 if (pwrite(fd, zeroes, SB_START, 0) != SB_START) {
477 perror("write error trying to zero start of disk\n");
480 /* Write superblock */
481 if (pwrite(fd, sb, bytes, SB_START) != bytes) {
482 perror("write error trying to write superblock\n");
490 void write_backingdev_sb(int fd, unsigned block_size, unsigned *bucket_sizes,
491 unsigned mode, uint64_t data_offset, const char *label,
492 uuid_le user_uuid, uuid_le set_uuid)
494 char uuid_str[40], set_uuid_str[40];
497 memset(&sb, 0, sizeof(struct cache_sb));
499 sb.offset = SB_SECTOR;
500 sb.version = BCACHE_SB_VERSION_BDEV;
501 sb.magic = BCACHE_MAGIC;
502 uuid_generate(sb.disk_uuid.b);
503 sb.user_uuid = user_uuid;
504 sb.set_uuid = set_uuid;
505 sb.block_size = block_size;
507 uuid_unparse(sb.disk_uuid.b, uuid_str);
508 uuid_unparse(sb.set_uuid.b, set_uuid_str);
510 memcpy(sb.label, label, SB_LABEL_SIZE);
512 SET_BDEV_CACHE_MODE(&sb, mode);
514 if (data_offset != BDEV_DATA_START_DEFAULT) {
515 sb.version = BCACHE_SB_VERSION_BDEV_WITH_OFFSET;
516 sb.bdev_data_offset = data_offset;
519 sb.csum = csum_set(&sb, BCH_CSUM_CRC64);
525 "data_offset: %ju\n",
526 uuid_str, set_uuid_str,
527 (unsigned) sb.version,
531 do_write_sb(fd, &sb);
534 int dev_open(const char *dev, bool wipe_bcache)
541 if ((fd = open(dev, O_RDWR|O_EXCL)) == -1) {
542 sprintf(err, "Can't open dev %s: %s\n", dev, strerror(errno));
546 if (pread(fd, &sb, sizeof(sb), SB_START) != sizeof(sb)) {
547 sprintf(err, "Failed to read superblock");
551 if (!memcmp(&sb.magic, &BCACHE_MAGIC, 16) && !wipe_bcache) {
552 sprintf(err, "Already a bcache device on %s, "
553 "overwrite with --wipe-bcache\n", dev);
557 if (!(pr = blkid_new_probe())) {
558 sprintf(err, "Failed to create a new probe");
561 if (blkid_probe_set_device(pr, fd, 0, 0)) {
562 sprintf(err, "failed to set probe to device");
565 /* enable ptable probing; superblock probing is enabled by default */
566 if (blkid_probe_enable_partitions(pr, true)) {
567 sprintf(err, "Failed to enable partitions on probe");
570 if (!blkid_do_probe(pr)) {
571 /* XXX wipefs doesn't know how to remove partition tables */
572 sprintf(err, "Device %s already has a non-bcache superblock, "
573 "remove it using wipefs and wipefs -a\n", dev);
580 fprintf(stderr, "dev_open failed with: %s", err);
584 static unsigned min_bucket_size(int num_bucket_sizes, unsigned *bucket_sizes)
587 unsigned min = bucket_sizes[0];
589 for (i = 0; i < num_bucket_sizes; i++)
590 min = bucket_sizes[i] < min ? bucket_sizes[i] : min;
595 void write_cache_sbs(int *fds, struct cache_sb *sb,
596 unsigned block_size, unsigned *bucket_sizes,
597 int num_bucket_sizes)
599 char uuid_str[40], set_uuid_str[40];
601 unsigned min_size = min_bucket_size(num_bucket_sizes, bucket_sizes);
603 sb->offset = SB_SECTOR;
604 sb->version = BCACHE_SB_VERSION_CDEV_V3;
605 sb->magic = BCACHE_MAGIC;
606 sb->block_size = block_size;
607 sb->u64s = bch_journal_buckets_offset(sb);
610 * don't have a userspace crc32c implementation handy, just always use
613 SET_CACHE_SB_CSUM_TYPE(sb, BCH_CSUM_CRC64);
615 for (i = 0; i < sb->nr_in_set; i++) {
616 struct cache_member *m = sb->members + i;
618 if (num_bucket_sizes <= 1) {
619 m->bucket_size = bucket_sizes[0];
621 if (!bucket_sizes[i]) {
622 printf("No bucket size specified for cache %zu,"
623 " using the default of %u",
625 m->bucket_size = bucket_sizes[0];
627 m->bucket_size = bucket_sizes[i];
631 m->nbuckets = getblocks(fds[i]) / m->bucket_size;
632 m->first_bucket = (23 / m->bucket_size) + 1;
634 if (m->nbuckets < 1 << 7) {
635 fprintf(stderr, "Not enough buckets: %llu, need %u\n",
636 m->nbuckets, 1 << 7);
641 for (i = 0; i < sb->nr_in_set; i++) {
642 struct cache_member *m = sb->members + i;
644 SET_CACHE_BTREE_NODE_SIZE(sb, min_size);
647 sb->disk_uuid = m->uuid;
650 sb->csum = csum_set(sb, CACHE_SB_CSUM_TYPE(sb));
652 uuid_unparse(sb->disk_uuid.b, uuid_str);
653 uuid_unparse(sb->set_uuid.b, set_uuid_str);
662 "first_bucket: %u\n",
663 uuid_str, set_uuid_str,
664 (unsigned) sb->version,
672 do_write_sb(fds[i], sb);
676 void next_cache_device(struct cache_sb *sb,
677 unsigned replication_set,
679 unsigned replacement_policy,
682 struct cache_member *m = sb->members + sb->nr_in_set;
684 SET_CACHE_REPLICATION_SET(m, replication_set);
685 SET_CACHE_TIER(m, tier);
686 SET_CACHE_REPLACEMENT(m, replacement_policy);
687 SET_CACHE_DISCARD(m, discard);
688 uuid_generate(m->uuid.b);
693 unsigned get_blocksize(const char *path)
697 if (stat(path, &statbuf)) {
698 fprintf(stderr, "Error statting %s: %s\n",
699 path, strerror(errno));
703 if (S_ISBLK(statbuf.st_mode)) {
705 * BLKALIGNOFF: alignment_offset
706 * BLKPBSZGET: physical_block_size
707 * BLKSSZGET: logical_block_size
708 * BLKIOMIN: minimum_io_size
709 * BLKIOOPT: optimal_io_size
711 * It may be tempting to use physical_block_size,
712 * or even minimum_io_size.
713 * But to be as transparent as possible,
714 * we want to use logical_block_size.
716 unsigned int logical_block_size;
717 int fd = open(path, O_RDONLY);
720 fprintf(stderr, "open(%s) failed: %m\n", path);
723 if (ioctl(fd, BLKSSZGET, &logical_block_size)) {
724 fprintf(stderr, "ioctl(%s, BLKSSZGET) failed: %m\n", path);
728 return logical_block_size / 512;
731 /* else: not a block device.
732 * Why would we even want to write a bcache super block there? */
734 return statbuf.st_blksize / 512;
737 long strtoul_or_die(const char *p, size_t max, const char *msg)
740 long v = strtol(p, NULL, 10);
741 if (errno || v < 0 || v >= max) {
742 fprintf(stderr, "Invalid %s %zi\n", msg, v);
749 static void print_encode(char *in)
752 for (pos = in; *pos; pos++)
753 if (isalnum(*pos) || strchr(".-_", *pos))
756 printf("%%%x", *pos);
759 static void show_uuid_only(struct cache_sb *sb, char *dev_uuid) {
760 uuid_unparse(sb->disk_uuid.b, dev_uuid);
763 static void show_super_common(struct cache_sb *sb, bool force_csum)
766 char label[SB_LABEL_SIZE + 1];
767 uint64_t expected_csum;
769 printf("sb.magic\t\t");
770 if (!memcmp(&sb->magic, &BCACHE_MAGIC, sizeof(sb->magic))) {
773 printf("bad magic\n");
774 fprintf(stderr, "Invalid superblock (bad magic)\n");
778 printf("sb.first_sector\t\t%ju", (uint64_t) sb->offset);
779 if (sb->offset == SB_SECTOR) {
780 printf(" [match]\n");
782 printf(" [expected %ds]\n", SB_SECTOR);
783 fprintf(stderr, "Invalid superblock (bad sector)\n");
787 printf("sb.csum\t\t\t%ju", (uint64_t) sb->csum);
788 expected_csum = csum_set(sb,
789 sb->version < BCACHE_SB_VERSION_CDEV_V3
791 : CACHE_SB_CSUM_TYPE(sb));
792 if (sb->csum == expected_csum) {
793 printf(" [match]\n");
795 printf(" [expected %" PRIX64 "]\n", expected_csum);
797 fprintf(stderr, "Corrupt superblock (bad csum)\n");
802 printf("sb.version\t\t%ju", (uint64_t) sb->version);
803 switch (sb->version) {
804 // These are handled the same by the kernel
805 case BCACHE_SB_VERSION_CDEV:
806 case BCACHE_SB_VERSION_CDEV_WITH_UUID:
807 printf(" [cache device]\n");
810 // The second adds data offset support
811 case BCACHE_SB_VERSION_BDEV:
812 case BCACHE_SB_VERSION_BDEV_WITH_OFFSET:
813 printf(" [backing device]\n");
817 printf(" [unknown]\n");
824 strncpy(label, (char *) sb->label, SB_LABEL_SIZE);
825 label[SB_LABEL_SIZE] = '\0';
826 printf("dev.label\t\t");
833 uuid_unparse(sb->disk_uuid.b, uuid);
834 printf("dev.uuid\t\t%s\n", uuid);
836 uuid_unparse(sb->set_uuid.b, uuid);
837 printf("cset.uuid\t\t%s\n", uuid);
840 void show_super_backingdev(struct cache_sb *sb, bool force_csum)
842 uint64_t first_sector;
844 show_super_common(sb, force_csum);
846 if (sb->version == BCACHE_SB_VERSION_BDEV) {
847 first_sector = BDEV_DATA_START_DEFAULT;
849 first_sector = sb->bdev_data_offset;
852 printf("dev.data.first_sector\t%ju\n"
853 "dev.data.cache_mode\t%s"
854 "dev.data.cache_state\t%s\n",
856 bdev_cache_mode[BDEV_CACHE_MODE(sb)],
857 bdev_state[BDEV_STATE(sb)]);
860 void show_super_cache(struct cache_sb *sb, bool force_csum)
862 struct cache_member *m = sb->members + sb->nr_this_dev;
864 show_super_common(sb, force_csum);
866 printf("dev.sectors_per_block\t%u\n"
867 "dev.sectors_per_bucket\t%u\n",
871 // total_sectors includes the superblock;
872 printf("dev.cache.first_sector\t%u\n"
873 "dev.cache.cache_sectors\t%llu\n"
874 "dev.cache.total_sectors\t%llu\n"
875 "dev.cache.ordered\t%s\n"
876 "dev.cache.pos\t\t%u\n"
877 "dev.cache.setsize\t\t%u\n",
878 m->bucket_size * m->first_bucket,
879 m->bucket_size * (m->nbuckets - m->first_bucket),
880 m->bucket_size * m->nbuckets,
881 CACHE_SYNC(sb) ? "yes" : "no",
885 printf("cache.state\t%s\n", cache_state[CACHE_STATE(m)]);
887 printf("cache.tier\t%llu\n", CACHE_TIER(m));
889 printf("cache.replication_set\t%llu\n", CACHE_REPLICATION_SET(m));
890 printf("cache.cur_meta_replicas\t%llu\n", REPLICATION_SET_CUR_META_REPLICAS(m));
891 printf("cache.cur_data_replicas\t%llu\n", REPLICATION_SET_CUR_DATA_REPLICAS(m));
893 printf("cache.has_metadata\t%llu\n", CACHE_HAS_METADATA(m));
894 printf("cache.has_data\t%llu\n", CACHE_HAS_DATA(m));
896 printf("cache.replacement\t%s\n", replacement_policies[CACHE_REPLACEMENT(m)]);
897 printf("cache.discard\t%llu\n", CACHE_DISCARD(m));
900 static int __sysfs_attr_type(const char *attr, const char * const *attr_arr)
902 for (unsigned i = 0; attr_arr[i] != NULL; i++)
903 if(!strcmp(attr, attr_arr[i]))
908 enum sysfs_attr sysfs_attr_type(const char *attr)
910 if(__sysfs_attr_type(attr, set_attrs))
912 if(__sysfs_attr_type(attr, cache_attrs))
914 if(__sysfs_attr_type(attr, internal_attrs))
915 return INTERNAL_ATTR;
917 printf("No attribute called %s, try --list to see options\n", attr);
922 static void __sysfs_attr_list(const char * const *attr_arr)
924 for (unsigned i = 0; attr_arr[i] != NULL; i++)
925 printf("%s\n", attr_arr[i]);
928 void sysfs_attr_list()
930 __sysfs_attr_list(set_attrs);
931 __sysfs_attr_list(cache_attrs);
932 __sysfs_attr_list(internal_attrs);
935 struct cache_sb *query_dev(char *dev, bool force_csum,
936 bool print_sb, bool uuid_only, char *dev_uuid)
939 struct cache_sb *sb = aligned_alloc(bytes, bytes);
941 int fd = open(dev, O_RDONLY|O_DIRECT);
943 printf("Can't open dev %s: %s\n", dev, strerror(errno));
948 int ret = pread(fd, sb, bytes, SB_START);
950 fprintf(stderr, "Couldn't read superblock: %s\n",
955 } else if (bytes > sizeof(sb) + sb->u64s * sizeof(u64)) {
956 /* We read the whole superblock */
961 * otherwise double the size of our dest
966 sb = aligned_alloc(4096, bytes);
972 show_uuid_only(sb, dev_uuid);
978 show_super_cache(sb, force_csum);
980 show_super_backingdev(sb, force_csum);
986 char *dev_name(const char *ugly_path) {
988 int i, end = strlen(ugly_path);
990 //Chop off "/bcache", then look for the next '/' from the end
991 for (i = end - 8; ; i--)
992 if(ugly_path[i] == '/')
995 strcpy(buf, ugly_path + i);
996 buf[end - i - 7] = 0;
998 // Is the dev guaranteed to be in /dev?
999 // This is needed for finding the superblock with a query-dev
1003 static void list_cacheset_devs(char *cset_dir, char *cset_name, bool parse_dev_name)
1005 DIR *cachedir, *dir;
1006 struct stat cache_stat;
1007 char entry[MAX_PATH];
1009 snprintf(entry, MAX_PATH, "%s/%s", cset_dir, cset_name);
1011 if((dir = opendir(entry)) != NULL) {
1012 while((ent = readdir(dir)) != NULL) {
1018 * We are looking for all cache# directories
1019 * do a strlen < 9 to skip over other entries
1020 * that also start with "cache"
1022 if(strncmp(ent->d_name, "cache", 5) ||
1023 !(strlen(ent->d_name) < 9))
1026 snprintf(entry, MAX_PATH, "%s/%s/%s",
1031 if((cachedir = opendir(entry)) == NULL)
1034 if(stat(entry, &cache_stat))
1037 if((len = readlink(entry, buf, sizeof(buf) - 1)) !=
1040 if(parse_dev_name) {
1041 tmp = dev_name(buf);
1042 printf("/dev%s\n", tmp);
1045 printf("\t%s\n", buf);
1052 char *find_matching_uuid(char *stats_dir, char *subdir, const char *stats_dev_uuid)
1054 /* Do a query-dev --uuid only to get the uuid
1055 * repeat on each dev until we find a matching one
1056 * append that cache# to subdir and return
1061 struct stat cache_stat;
1063 char entry[MAX_PATH];
1066 snprintf(entry, MAX_PATH, "%s%s", stats_dir, subdir);
1067 snprintf(intbuf, 4, "%d", i);
1068 strcat(entry, intbuf);
1074 if((cachedir = opendir(entry)) == NULL)
1077 if(stat(entry, &cache_stat))
1080 if((len = readlink(entry, buf, sizeof(buf) - 1)) != -1) {
1083 int i, end = strlen(buf);
1084 char tmp[32], devname[32];
1085 struct cache_sb *sb;
1087 /* Chop off "/bcache", then look for the
1088 * next '/' from the end
1090 for (i = end - 8; ; i--)
1094 strcpy(tmp, buf + i);
1095 tmp[end - i - 7] = 0;
1096 strcpy(devname, "/dev");
1097 strcat(devname, tmp);
1099 err = "Unable to open superblock";
1100 sb = query_dev(devname, false, false, true, dev_uuid);
1106 if(!strcmp(stats_dev_uuid, dev_uuid)) {
1107 strcat(subdir, intbuf);
1112 /* remove i from end and append i++ */
1113 entry[strlen(entry)-strlen(intbuf)] = 0;
1115 snprintf(intbuf, 4, "%d", i);
1116 strcat(entry, intbuf);
1120 err = "dev uuid doesn't exist in cache_set";
1124 char *list_cachesets(char *cset_dir, bool list_devs)
1130 dir = opendir(cset_dir);
1132 err = "Failed to open cacheset dir";
1136 while ((ent = readdir(dir)) != NULL) {
1137 struct stat statbuf;
1138 char entry[MAX_PATH];
1140 if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
1143 snprintf(entry, MAX_PATH, "%s/%s", cset_dir, ent->d_name);
1144 if(stat(entry, &statbuf) == -1) {
1145 err = "Failed to stat cacheset subdir";
1149 if (S_ISDIR(statbuf.st_mode)) {
1150 printf("%s\n", ent->d_name);
1153 list_cacheset_devs(cset_dir, ent->d_name, true);
1163 char *register_bcache(char *const *devs)
1168 bcachefd = open("/dev/bcache", O_RDWR);
1170 err = "Can't open bcache device";
1174 ret = ioctl(bcachefd, BCH_IOCTL_REGISTER, devs);
1177 snprintf(tmp, 64, "ioctl register error: %s\n",
1189 char *unregister_bcache(char *const *devs)
1194 bcachefd = open("/dev/bcache_extent0", O_RDWR);
1196 err = "Can't open bcache device";
1200 ret = ioctl(bcachefd, BCH_IOCTL_STOP);
1203 snprintf(tmp, 64, "ioctl unregister error: %s\n",
1214 char *add_devices(char *const *devs)
1219 bcachefd = open("/dev/bcache_extent0", O_RDWR);
1221 err = "Can't open bcache device";
1225 struct bch_ioctl_add_disks ia;
1228 ret = ioctl(bcachefd, BCH_IOCTL_ADD_DISKS, &ia);
1231 snprintf(tmp, 128, "ioctl add disk error: %s\n",
1241 char *remove_device(const char *dev, bool force)
1246 bcachefd = open("/dev/bcache_extent0", O_RDWR);
1248 err = "Can't open bcache device";
1252 struct bch_ioctl_rm_disk ir;
1254 ir.force = force ? 1 : 0;
1256 ret = ioctl(bcachefd, BCH_IOCTL_RM_DISK, &ir);
1259 snprintf(tmp, 128, "ioctl add disk error: %s\n",
1269 char *device_set_failed(const char *dev_uuid) {
1273 struct bch_ioctl_disk_failed df;
1275 bcachefd = open("/dev/bcache_extent0", O_RDWR);
1277 err = "Can't open bcache device";
1281 uuid_parse(dev_uuid, dev.b);
1284 ret = ioctl(bcachefd, BCH_IOCTL_SET_DISK_FAILED, &df);
1287 snprintf(tmp, 128, "ioctl set disk failed error %s\n",
1297 char *probe(char *dev, int udev)
1304 int fd = open(dev, O_RDONLY);
1306 err = "Got file descriptor -1 trying to open dev";
1310 if (!(pr = blkid_new_probe())) {
1311 err = "Failed trying to get a blkid for new probe";
1315 if (blkid_probe_set_device(pr, fd, 0, 0)) {
1316 err = "Failed blkid probe set device";
1320 /* probe partitions too */
1321 if (blkid_probe_enable_partitions(pr, true)) {
1322 err = "Enable probe partitions";
1326 /* bail if anything was found
1327 * probe-bcache isn't needed once blkid recognizes bcache */
1328 if (!blkid_do_probe(pr)) {
1329 err = "blkid recognizes bcache";
1333 if (pread(fd, &sb, sizeof(sb), SB_START) != sizeof(sb)) {
1334 err = "Failed to read superblock";
1338 if (memcmp(&sb.magic, &BCACHE_MAGIC, sizeof(sb.magic))) {
1339 err = "Bcache magic incorrect";
1343 uuid_unparse(sb.disk_uuid.b, uuid);
1346 printf("ID_FS_UUID=%s\n"
1347 "ID_FS_UUID_ENC=%s\n"
1348 "ID_FS_TYPE=bcache\n",
1351 printf("%s: UUID=\"\" TYPE=\"bcache\"\n", uuid);
1359 char *read_stat_dir(DIR *dir, char *stats_dir, char *stat_name, char *ret)
1361 struct stat statbuf;
1362 char entry[MAX_PATH];
1365 snprintf(entry, MAX_PATH, "%s/%s", stats_dir, stat_name);
1366 if(stat(entry, &statbuf) == -1) {
1368 snprintf(tmp, MAX_PATH, "Failed to stat %s\n", entry);
1373 if (S_ISREG(statbuf.st_mode)) {
1376 fp = fopen(entry, "r");
1378 /* If we can't open the file, this is probably because
1379 * of permissions, just move to the next file */
1383 while(fgets(ret, MAX_PATH, fp));
1390 char *bcache_get_capacity(const char *cset_dir, const char *capacity_uuid,
1394 char bucket_size_path[MAX_PATH];
1395 char nbuckets_path[MAX_PATH];
1396 char avail_buckets_path[MAX_PATH];
1397 char cache_path[MAX_PATH];
1399 double bucket_sizes[MAX_DEVS];
1400 double nbuckets[MAX_DEVS];
1401 double avail_buckets[MAX_DEVS];
1402 char *dev_names[MAX_DEVS];
1403 int dev_count = 0, i;
1405 double total_cap = 0, total_free = 0;
1408 snprintf(bucket_size_path, MAX_PATH, "%s/%s/%s/%s", cset_dir,
1409 capacity_uuid, "cache0", "bucket_size_bytes");
1410 snprintf(nbuckets_path, MAX_PATH, "%s/%s/%s/%s", cset_dir,
1411 capacity_uuid, "cache0", "nbuckets");
1412 snprintf(avail_buckets_path, MAX_PATH, "%s/%s/%s/%s", cset_dir,
1413 capacity_uuid, "cache0", "available_buckets");
1414 snprintf(cache_path, MAX_PATH, "%s/%s/%s", cset_dir, capacity_uuid,
1422 if((cache_dir = opendir(cache_path)) == NULL)
1425 err = read_stat_dir(cache_dir, cache_path,
1426 "bucket_size_bytes", buf);
1430 bucket_sizes[dev_count] = atof(buf);
1432 err = read_stat_dir(cache_dir, cache_path,
1437 nbuckets[dev_count] = atof(buf);
1439 err = read_stat_dir(cache_dir, cache_path,
1440 "available_buckets", buf);
1444 avail_buckets[dev_count] = atof(buf);
1446 if((len = readlink(cache_path, buf, sizeof(buf) - 1)) != -1) {
1448 dev_names[dev_count] = dev_name(buf);
1451 snprintf(intbuf, 4, "%d", dev_count);
1453 /* remove i/stat and append i++/stat */
1454 bucket_size_path[strlen(cache_path) - strlen(intbuf)] = 0;
1455 nbuckets_path[strlen(cache_path) - strlen(intbuf)] = 0;
1456 avail_buckets_path[strlen(cache_path) - strlen(intbuf)] = 0;
1457 cache_path[strlen(cache_path) - strlen(intbuf)] = 0;
1461 strcat(cache_path, intbuf);
1462 strcat(bucket_size_path, intbuf);
1463 strcat(nbuckets_path, intbuf);
1464 strcat(avail_buckets_path, intbuf);
1467 printf("%-15s%-25s%-25s\n", "Device Name", "Capacity (512 Blocks)", "Free (512 Blocks)");
1470 for (i = 0; i < dev_count; i++) {
1471 printf("%s%-11s%-25.*f%-25.*f\n", "/dev", dev_names[i],
1473 (bucket_sizes[i] * nbuckets[i]) / 512,
1475 (bucket_sizes[i] * avail_buckets[i]) / 512);
1479 for (i = 0; i < dev_count; i++) {
1480 total_cap += (bucket_sizes[i] * nbuckets[i]) / 512;
1481 total_free += (bucket_sizes[i] * avail_buckets[i]) / 512;
1485 printf("%-15s%-25.*f%-25.*f\n", "Total", precision, total_cap,
1486 precision, total_free);
1489 for (i = 0; i < dev_count; i++)