2013-03-23 16:11:31 -07:00
/*
* random utiility code , for bcache but in theory not specific to bcache
*
* Copyright 2010 , 2011 Kent Overstreet < kent . overstreet @ gmail . com >
* Copyright 2012 Google , Inc .
*/
# include <linux/bio.h>
# include <linux/blkdev.h>
# include <linux/ctype.h>
# include <linux/debugfs.h>
# include <linux/module.h>
# include <linux/seq_file.h>
# include <linux/types.h>
# include "util.h"
# define simple_strtoint(c, end, base) simple_strtol(c, end, base)
# define simple_strtouint(c, end, base) simple_strtoul(c, end, base)
# define STRTO_H(name, type) \
2013-03-28 12:50:55 -06:00
int bch_ # # name # # _h ( const char * cp , type * res ) \
2013-03-23 16:11:31 -07:00
{ \
int u = 0 ; \
char * e ; \
type i = simple_ # # name ( cp , & e , 10 ) ; \
\
switch ( tolower ( * e ) ) { \
default : \
return - EINVAL ; \
case ' y ' : \
case ' z ' : \
u + + ; \
case ' e ' : \
u + + ; \
case ' p ' : \
u + + ; \
case ' t ' : \
u + + ; \
case ' g ' : \
u + + ; \
case ' m ' : \
u + + ; \
case ' k ' : \
u + + ; \
if ( e + + = = cp ) \
return - EINVAL ; \
case ' \n ' : \
case ' \0 ' : \
if ( * e = = ' \n ' ) \
e + + ; \
} \
\
if ( * e ) \
return - EINVAL ; \
\
while ( u - - ) { \
if ( ( type ) ~ 0 > 0 & & \
( type ) ~ 0 / 1024 < = i ) \
return - EINVAL ; \
if ( ( i > 0 & & ANYSINT_MAX ( type ) / 1024 < i ) | | \
( i < 0 & & - ANYSINT_MAX ( type ) / 1024 > i ) ) \
return - EINVAL ; \
i * = 1024 ; \
} \
\
* res = i ; \
return 0 ; \
} \
STRTO_H ( strtoint , int )
STRTO_H ( strtouint , unsigned int )
STRTO_H ( strtoll , long long )
STRTO_H ( strtoull , unsigned long long )
2013-03-28 12:50:55 -06:00
ssize_t bch_hprint ( char * buf , int64_t v )
2013-03-23 16:11:31 -07:00
{
static const char units [ ] = " ?kMGTPEZY " ;
2013-04-05 14:12:28 -07:00
char dec [ 4 ] = " " ;
2013-03-23 16:11:31 -07:00
int u , t = 0 ;
for ( u = 0 ; v > = 1024 | | v < = - 1024 ; u + + ) {
t = v & ~ ( ~ 0 < < 10 ) ;
v > > = 10 ;
}
if ( ! u )
return sprintf ( buf , " %llu " , v ) ;
if ( v < 100 & & v > - 100 )
2013-04-05 14:12:28 -07:00
snprintf ( dec , sizeof ( dec ) , " .%i " , t / 100 ) ;
2013-03-23 16:11:31 -07:00
return sprintf ( buf , " %lli%s%c " , v , dec , units [ u ] ) ;
}
2013-03-28 12:50:55 -06:00
ssize_t bch_snprint_string_list ( char * buf , size_t size , const char * const list [ ] ,
2013-03-23 16:11:31 -07:00
size_t selected )
{
char * out = buf ;
size_t i ;
for ( i = 0 ; list [ i ] ; i + + )
out + = snprintf ( out , buf + size - out ,
i = = selected ? " [%s] " : " %s " , list [ i ] ) ;
out [ - 1 ] = ' \n ' ;
return out - buf ;
}
2013-03-28 12:50:55 -06:00
ssize_t bch_read_string_list ( const char * buf , const char * const list [ ] )
2013-03-23 16:11:31 -07:00
{
size_t i ;
char * s , * d = kstrndup ( buf , PAGE_SIZE - 1 , GFP_KERNEL ) ;
if ( ! d )
return - ENOMEM ;
s = strim ( d ) ;
for ( i = 0 ; list [ i ] ; i + + )
if ( ! strcmp ( list [ i ] , s ) )
break ;
kfree ( d ) ;
if ( ! list [ i ] )
return - EINVAL ;
return i ;
}
2013-03-28 12:50:55 -06:00
bool bch_is_zero ( const char * p , size_t n )
2013-03-23 16:11:31 -07:00
{
size_t i ;
for ( i = 0 ; i < n ; i + + )
if ( p [ i ] )
return false ;
return true ;
}
2013-03-28 12:50:55 -06:00
int bch_parse_uuid ( const char * s , char * uuid )
2013-03-23 16:11:31 -07:00
{
size_t i , j , x ;
memset ( uuid , 0 , 16 ) ;
for ( i = 0 , j = 0 ;
i < strspn ( s , " -0123456789:ABCDEFabcdef " ) & & j < 32 ;
i + + ) {
x = s [ i ] | 32 ;
switch ( x ) {
case ' 0 ' . . . ' 9 ' :
x - = ' 0 ' ;
break ;
case ' a ' . . . ' f ' :
x - = ' a ' - 10 ;
break ;
default :
continue ;
}
if ( ! ( j & 1 ) )
x < < = 4 ;
uuid [ j + + > > 1 ] | = x ;
}
return i ;
}
2013-03-28 12:50:55 -06:00
void bch_time_stats_update ( struct time_stats * stats , uint64_t start_time )
2013-03-23 16:11:31 -07:00
{
2013-07-31 00:03:54 -07:00
uint64_t now , duration , last ;
spin_lock ( & stats - > lock ) ;
now = local_clock ( ) ;
duration = time_after64 ( now , start_time )
2013-03-23 16:11:31 -07:00
? now - start_time : 0 ;
2013-07-31 00:03:54 -07:00
last = time_after64 ( now , stats - > last )
2013-03-23 16:11:31 -07:00
? now - stats - > last : 0 ;
stats - > max_duration = max ( stats - > max_duration , duration ) ;
if ( stats - > last ) {
ewma_add ( stats - > average_duration , duration , 8 , 8 ) ;
if ( stats - > average_frequency )
ewma_add ( stats - > average_frequency , last , 8 , 8 ) ;
else
stats - > average_frequency = last < < 8 ;
} else {
stats - > average_duration = duration < < 8 ;
}
stats - > last = now ? : 1 ;
2013-07-31 00:03:54 -07:00
spin_unlock ( & stats - > lock ) ;
2013-03-23 16:11:31 -07:00
}
2013-09-23 23:17:31 -07:00
/**
* bch_next_delay ( ) - increment @ d by the amount of work done , and return how
* long to delay until the next time to do some work .
*
* @ d - the struct bch_ratelimit to update
* @ done - the amount of work done , in arbitrary units
*
* Returns the amount of time to delay by , in jiffies
*/
uint64_t bch_next_delay ( struct bch_ratelimit * d , uint64_t done )
2013-03-23 16:11:31 -07:00
{
uint64_t now = local_clock ( ) ;
d - > next + = div_u64 ( done , d - > rate ) ;
return time_after64 ( d - > next , now )
? div_u64 ( d - > next - now , NSEC_PER_SEC / HZ )
: 0 ;
}
2013-03-28 12:50:55 -06:00
void bch_bio_map ( struct bio * bio , void * base )
2013-03-23 16:11:31 -07:00
{
size_t size = bio - > bi_size ;
struct bio_vec * bv = bio - > bi_io_vec ;
BUG_ON ( ! bio - > bi_size ) ;
BUG_ON ( bio - > bi_vcnt ) ;
bv - > bv_offset = base ? ( ( unsigned long ) base ) % PAGE_SIZE : 0 ;
goto start ;
for ( ; size ; bio - > bi_vcnt + + , bv + + ) {
bv - > bv_offset = 0 ;
start : bv - > bv_len = min_t ( size_t , PAGE_SIZE - bv - > bv_offset ,
size ) ;
if ( base ) {
bv - > bv_page = is_vmalloc_addr ( base )
? vmalloc_to_page ( base )
: virt_to_page ( base ) ;
base + = bv - > bv_len ;
}
size - = bv - > bv_len ;
}
}
/*
* Portions Copyright ( c ) 1996 - 2001 , PostgreSQL Global Development Group ( Any
* use permitted , subject to terms of PostgreSQL license ; see . )
* If we have a 64 - bit integer type , then a 64 - bit CRC looks just like the
* usual sort of implementation . ( See Ross Williams ' excellent introduction
* A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS , available from
* ftp : //ftp.rocksoft.com/papers/crc_v3.txt or several other net sites.)
* If we have no working 64 - bit type , then fake it with two 32 - bit registers .
*
* The present implementation is a normal ( not " reflected " , in Williams '
* terms ) 64 - bit CRC , using initial all - ones register contents and a final
* bit inversion . The chosen polynomial is borrowed from the DLT1 spec
* ( ECMA - 182 , available from http : //www.ecma.ch/ecma1/STAND/ECMA-182.HTM):
*
* x ^ 64 + x ^ 62 + x ^ 57 + x ^ 55 + x ^ 54 + x ^ 53 + x ^ 52 + x ^ 47 + x ^ 46 + x ^ 45 +
* x ^ 40 + x ^ 39 + x ^ 38 + x ^ 37 + x ^ 35 + x ^ 33 + x ^ 32 + x ^ 31 + x ^ 29 + x ^ 27 +
* x ^ 24 + x ^ 23 + x ^ 22 + x ^ 21 + x ^ 19 + x ^ 17 + x ^ 13 + x ^ 12 + x ^ 10 + x ^ 9 +
* x ^ 7 + x ^ 4 + x + 1
*/
static const uint64_t crc_table [ 256 ] = {
2013-03-26 13:49:02 -07:00
0x0000000000000000ULL , 0x42F0E1EBA9EA3693ULL , 0x85E1C3D753D46D26ULL ,
0xC711223CFA3E5BB5ULL , 0x493366450E42ECDFULL , 0x0BC387AEA7A8DA4CULL ,
0xCCD2A5925D9681F9ULL , 0x8E224479F47CB76AULL , 0x9266CC8A1C85D9BEULL ,
0xD0962D61B56FEF2DULL , 0x17870F5D4F51B498ULL , 0x5577EEB6E6BB820BULL ,
0xDB55AACF12C73561ULL , 0x99A54B24BB2D03F2ULL , 0x5EB4691841135847ULL ,
0x1C4488F3E8F96ED4ULL , 0x663D78FF90E185EFULL , 0x24CD9914390BB37CULL ,
0xE3DCBB28C335E8C9ULL , 0xA12C5AC36ADFDE5AULL , 0x2F0E1EBA9EA36930ULL ,
0x6DFEFF5137495FA3ULL , 0xAAEFDD6DCD770416ULL , 0xE81F3C86649D3285ULL ,
0xF45BB4758C645C51ULL , 0xB6AB559E258E6AC2ULL , 0x71BA77A2DFB03177ULL ,
0x334A9649765A07E4ULL , 0xBD68D2308226B08EULL , 0xFF9833DB2BCC861DULL ,
0x388911E7D1F2DDA8ULL , 0x7A79F00C7818EB3BULL , 0xCC7AF1FF21C30BDEULL ,
0x8E8A101488293D4DULL , 0x499B3228721766F8ULL , 0x0B6BD3C3DBFD506BULL ,
0x854997BA2F81E701ULL , 0xC7B97651866BD192ULL , 0x00A8546D7C558A27ULL ,
0x4258B586D5BFBCB4ULL , 0x5E1C3D753D46D260ULL , 0x1CECDC9E94ACE4F3ULL ,
0xDBFDFEA26E92BF46ULL , 0x990D1F49C77889D5ULL , 0x172F5B3033043EBFULL ,
0x55DFBADB9AEE082CULL , 0x92CE98E760D05399ULL , 0xD03E790CC93A650AULL ,
0xAA478900B1228E31ULL , 0xE8B768EB18C8B8A2ULL , 0x2FA64AD7E2F6E317ULL ,
0x6D56AB3C4B1CD584ULL , 0xE374EF45BF6062EEULL , 0xA1840EAE168A547DULL ,
0x66952C92ECB40FC8ULL , 0x2465CD79455E395BULL , 0x3821458AADA7578FULL ,
0x7AD1A461044D611CULL , 0xBDC0865DFE733AA9ULL , 0xFF3067B657990C3AULL ,
0x711223CFA3E5BB50ULL , 0x33E2C2240A0F8DC3ULL , 0xF4F3E018F031D676ULL ,
0xB60301F359DBE0E5ULL , 0xDA050215EA6C212FULL , 0x98F5E3FE438617BCULL ,
0x5FE4C1C2B9B84C09ULL , 0x1D14202910527A9AULL , 0x93366450E42ECDF0ULL ,
0xD1C685BB4DC4FB63ULL , 0x16D7A787B7FAA0D6ULL , 0x5427466C1E109645ULL ,
0x4863CE9FF6E9F891ULL , 0x0A932F745F03CE02ULL , 0xCD820D48A53D95B7ULL ,
0x8F72ECA30CD7A324ULL , 0x0150A8DAF8AB144EULL , 0x43A04931514122DDULL ,
0x84B16B0DAB7F7968ULL , 0xC6418AE602954FFBULL , 0xBC387AEA7A8DA4C0ULL ,
0xFEC89B01D3679253ULL , 0x39D9B93D2959C9E6ULL , 0x7B2958D680B3FF75ULL ,
0xF50B1CAF74CF481FULL , 0xB7FBFD44DD257E8CULL , 0x70EADF78271B2539ULL ,
0x321A3E938EF113AAULL , 0x2E5EB66066087D7EULL , 0x6CAE578BCFE24BEDULL ,
0xABBF75B735DC1058ULL , 0xE94F945C9C3626CBULL , 0x676DD025684A91A1ULL ,
0x259D31CEC1A0A732ULL , 0xE28C13F23B9EFC87ULL , 0xA07CF2199274CA14ULL ,
0x167FF3EACBAF2AF1ULL , 0x548F120162451C62ULL , 0x939E303D987B47D7ULL ,
0xD16ED1D631917144ULL , 0x5F4C95AFC5EDC62EULL , 0x1DBC74446C07F0BDULL ,
0xDAAD56789639AB08ULL , 0x985DB7933FD39D9BULL , 0x84193F60D72AF34FULL ,
0xC6E9DE8B7EC0C5DCULL , 0x01F8FCB784FE9E69ULL , 0x43081D5C2D14A8FAULL ,
0xCD2A5925D9681F90ULL , 0x8FDAB8CE70822903ULL , 0x48CB9AF28ABC72B6ULL ,
0x0A3B7B1923564425ULL , 0x70428B155B4EAF1EULL , 0x32B26AFEF2A4998DULL ,
0xF5A348C2089AC238ULL , 0xB753A929A170F4ABULL , 0x3971ED50550C43C1ULL ,
0x7B810CBBFCE67552ULL , 0xBC902E8706D82EE7ULL , 0xFE60CF6CAF321874ULL ,
0xE224479F47CB76A0ULL , 0xA0D4A674EE214033ULL , 0x67C58448141F1B86ULL ,
0x253565A3BDF52D15ULL , 0xAB1721DA49899A7FULL , 0xE9E7C031E063ACECULL ,
0x2EF6E20D1A5DF759ULL , 0x6C0603E6B3B7C1CAULL , 0xF6FAE5C07D3274CDULL ,
0xB40A042BD4D8425EULL , 0x731B26172EE619EBULL , 0x31EBC7FC870C2F78ULL ,
0xBFC9838573709812ULL , 0xFD39626EDA9AAE81ULL , 0x3A28405220A4F534ULL ,
0x78D8A1B9894EC3A7ULL , 0x649C294A61B7AD73ULL , 0x266CC8A1C85D9BE0ULL ,
0xE17DEA9D3263C055ULL , 0xA38D0B769B89F6C6ULL , 0x2DAF4F0F6FF541ACULL ,
0x6F5FAEE4C61F773FULL , 0xA84E8CD83C212C8AULL , 0xEABE6D3395CB1A19ULL ,
0x90C79D3FEDD3F122ULL , 0xD2377CD44439C7B1ULL , 0x15265EE8BE079C04ULL ,
0x57D6BF0317EDAA97ULL , 0xD9F4FB7AE3911DFDULL , 0x9B041A914A7B2B6EULL ,
0x5C1538ADB04570DBULL , 0x1EE5D94619AF4648ULL , 0x02A151B5F156289CULL ,
0x4051B05E58BC1E0FULL , 0x87409262A28245BAULL , 0xC5B073890B687329ULL ,
0x4B9237F0FF14C443ULL , 0x0962D61B56FEF2D0ULL , 0xCE73F427ACC0A965ULL ,
0x8C8315CC052A9FF6ULL , 0x3A80143F5CF17F13ULL , 0x7870F5D4F51B4980ULL ,
0xBF61D7E80F251235ULL , 0xFD913603A6CF24A6ULL , 0x73B3727A52B393CCULL ,
0x31439391FB59A55FULL , 0xF652B1AD0167FEEAULL , 0xB4A25046A88DC879ULL ,
0xA8E6D8B54074A6ADULL , 0xEA16395EE99E903EULL , 0x2D071B6213A0CB8BULL ,
0x6FF7FA89BA4AFD18ULL , 0xE1D5BEF04E364A72ULL , 0xA3255F1BE7DC7CE1ULL ,
0x64347D271DE22754ULL , 0x26C49CCCB40811C7ULL , 0x5CBD6CC0CC10FAFCULL ,
0x1E4D8D2B65FACC6FULL , 0xD95CAF179FC497DAULL , 0x9BAC4EFC362EA149ULL ,
0x158E0A85C2521623ULL , 0x577EEB6E6BB820B0ULL , 0x906FC95291867B05ULL ,
0xD29F28B9386C4D96ULL , 0xCEDBA04AD0952342ULL , 0x8C2B41A1797F15D1ULL ,
0x4B3A639D83414E64ULL , 0x09CA82762AAB78F7ULL , 0x87E8C60FDED7CF9DULL ,
0xC51827E4773DF90EULL , 0x020905D88D03A2BBULL , 0x40F9E43324E99428ULL ,
0x2CFFE7D5975E55E2ULL , 0x6E0F063E3EB46371ULL , 0xA91E2402C48A38C4ULL ,
0xEBEEC5E96D600E57ULL , 0x65CC8190991CB93DULL , 0x273C607B30F68FAEULL ,
0xE02D4247CAC8D41BULL , 0xA2DDA3AC6322E288ULL , 0xBE992B5F8BDB8C5CULL ,
0xFC69CAB42231BACFULL , 0x3B78E888D80FE17AULL , 0x7988096371E5D7E9ULL ,
0xF7AA4D1A85996083ULL , 0xB55AACF12C735610ULL , 0x724B8ECDD64D0DA5ULL ,
0x30BB6F267FA73B36ULL , 0x4AC29F2A07BFD00DULL , 0x08327EC1AE55E69EULL ,
0xCF235CFD546BBD2BULL , 0x8DD3BD16FD818BB8ULL , 0x03F1F96F09FD3CD2ULL ,
0x41011884A0170A41ULL , 0x86103AB85A2951F4ULL , 0xC4E0DB53F3C36767ULL ,
0xD8A453A01B3A09B3ULL , 0x9A54B24BB2D03F20ULL , 0x5D45907748EE6495ULL ,
0x1FB5719CE1045206ULL , 0x919735E51578E56CULL , 0xD367D40EBC92D3FFULL ,
0x1476F63246AC884AULL , 0x568617D9EF46BED9ULL , 0xE085162AB69D5E3CULL ,
0xA275F7C11F7768AFULL , 0x6564D5FDE549331AULL , 0x279434164CA30589ULL ,
0xA9B6706FB8DFB2E3ULL , 0xEB46918411358470ULL , 0x2C57B3B8EB0BDFC5ULL ,
0x6EA7525342E1E956ULL , 0x72E3DAA0AA188782ULL , 0x30133B4B03F2B111ULL ,
0xF7021977F9CCEAA4ULL , 0xB5F2F89C5026DC37ULL , 0x3BD0BCE5A45A6B5DULL ,
0x79205D0E0DB05DCEULL , 0xBE317F32F78E067BULL , 0xFCC19ED95E6430E8ULL ,
0x86B86ED5267CDBD3ULL , 0xC4488F3E8F96ED40ULL , 0x0359AD0275A8B6F5ULL ,
0x41A94CE9DC428066ULL , 0xCF8B0890283E370CULL , 0x8D7BE97B81D4019FULL ,
0x4A6ACB477BEA5A2AULL , 0x089A2AACD2006CB9ULL , 0x14DEA25F3AF9026DULL ,
0x562E43B4931334FEULL , 0x913F6188692D6F4BULL , 0xD3CF8063C0C759D8ULL ,
0x5DEDC41A34BBEEB2ULL , 0x1F1D25F19D51D821ULL , 0xD80C07CD676F8394ULL ,
0x9AFCE626CE85B507ULL ,
2013-03-23 16:11:31 -07:00
} ;
2013-03-28 12:50:55 -06:00
uint64_t bch_crc64_update ( uint64_t crc , const void * _data , size_t len )
2013-03-23 16:11:31 -07:00
{
const unsigned char * data = _data ;
while ( len - - ) {
int i = ( ( int ) ( crc > > 56 ) ^ * data + + ) & 0xFF ;
crc = crc_table [ i ] ^ ( crc < < 8 ) ;
}
return crc ;
}
2013-03-28 12:50:55 -06:00
uint64_t bch_crc64 ( const void * data , size_t len )
2013-03-23 16:11:31 -07:00
{
2013-03-26 13:49:02 -07:00
uint64_t crc = 0xffffffffffffffffULL ;
2013-03-23 16:11:31 -07:00
2013-03-28 12:50:55 -06:00
crc = bch_crc64_update ( crc , data , len ) ;
2013-03-23 16:11:31 -07:00
2013-03-26 13:49:02 -07:00
return crc ^ 0xffffffffffffffffULL ;
2013-03-23 16:11:31 -07:00
}