These guys at ‘backblaze’ claim to be able to provide 67TB for $7,867 based on 45 SATA drives, RAID6 (Linux) and JFS. The hardware design which is presented in the blog as a how-to uses vertically stacked drives and looks very much like the Sun ‘Thumper’ (X4500) device which I first saw when I was still at Sun around 2006. No performance numbers are given, and whilst the capacity is much cheaper than ‘real’ storage, I doubt that write performance is much to write home about.
Hardware design for high density storage pod
Map MAC to NIC vendor.
Not sure how well known this trick is, but it is possible to figure out the vendor of a particular NIC by looking at the first few digits of the MAC address. We used to use this when I worked at Sun to figure out if the customers were using pukka Sun NICs and what might be at the other end. In the modern world there is a web tool that will do the lookup for you. Mac Find
List binary objects by size.
Sometimes you will want to know what a binary file contains (functions, arrays, objects) etc. The ‘nm’ command will do that for you, and the following 1-liner will sort the output by size. I use this to determine why some source compiled on Solaris is larger than when compiled in linux.
e.g.
nm| sort -n -t \| +2
Here is a small binary I happen to have.
$ nm write_random | sort -n -t \| +2 write_random: [Index] Value Size Type Bind Other Shndx Name .... [72] | 134520544| 60|OBJT |GLOB |0 |23 |tstr [85] | 0| 60|FUNC |GLOB |0 |UNDEF |lseek@@GLIBC_2.0 [58] | 134515432| 66|FUNC |GLOB |0 |12 |__libc_csu_fini [66] | 0| 67|FUNC |GLOB |0 |UNDEF |getopt@@GLIBC_2.0 [74] | 134515348| 82|FUNC |GLOB |0 |12 |__libc_csu_init [51] | 0| 113|FUNC |GLOB |0 |UNDEF |close@@GLIBC_2.0 [76] | 0| 113|FUNC |GLOB |0 |UNDEF |fsync@@GLIBC_2.0 [50] | 0| 124|FUNC |GLOB |0 |UNDEF |write@@GLIBC_2.0 [88] | 0| 124|FUNC |GLOB |0 |UNDEF |open@@GLIBC_2.0 [55] | 134514968| 163|FUNC |GLOB |0 |12 |getSizeInBlocks [68] | 134515131| 214|FUNC |GLOB |0 |12 |do_writes [89] | 0| 217|FUNC |GLOB |0 |UNDEF |exit@@GLIBC_2.0 [79] | 0| 221|FUNC |GLOB |0 |UNDEF |__libc_start_main@@GLIBC_2.0 [67] | 0| 344|FUNC |GLOB |0 |UNDEF |__fxstat@@GLIBC_2.0 [53] | 0| 523|FUNC |GLOB |0 |UNDEF |perror@@GLIBC_2.0 [62] | 0| 539|FUNC |GLOB |0 |UNDEF |malloc@@GLIBC_2.0 [77] | 134514424| 544|FUNC |GLOB |0 |12 |main
Here’s the source code for the same binary, notice in the output of nm the size of the object tstr is 60 bytes, and in the code it’s specified as char[60].
$ cat write_random.c #include#include #include #include #include #include #define ARRAYSIZE 16*1024 #define NUMTOWRITE 10 int getSizeInBlocks(int,int, char *); void do_writes(int,int, int); int loopsToDo=1; int limitLoops=0; /*Default to doing loops forever*/ int msPause=0; int iostart,iostop,iotimeMS,ioThresh; struct tm *tm_ptr; time_t tm; char tstr[60]; int IOoverThresh=1,TotalIOs=1,dofsync=0,forcesize=0; double badpct; int main(argc, argv) int argc; char *argv[]; { int i,n,count=0,SizeInBlocks; int appBlockSize=8192,key; /*Default IO size is 8k*/ int mode=O_RDWR; int dsync=0; char *array,c,filename[255]; int fd; if (argc == 1) { fprintf(stderr,"Usage: [-d -f | -b |-s | -l | -o st_size; */ FileSize=lseek(fd,0,SEEK_END); if (forcesize) FileSize=forcesize*1024*1024; appBlocks = (int) FileSize/appBlockSize; printf("file %s is %d bytes %d application blocks blocksize = %d\n",filename,FileSize,appBlocks,appBlockSize); return appBlocks; } void do_writes(int fd,int appBlockSize, int appBlocks) { char *array; array=malloc(appBlockSize); while (loopsToDo >0 ){ /*generate a random number 0-appBlocks*/ int seek_val=rand()%appBlocks; lseek(fd,appBlockSize * seek_val, SEEK_SET); write(fd,array, appBlockSize); if (dofsync) fsync(fd); TotalIOs++; if (limitLoops) loopsToDo--; if (msPause) usleep(msPause*1000); } return; }