C program Assignment that Tests HDDs Internal and External and Get the Results-133790

TASK –

write a C program that tests HDDs internal and external and get the results of :-
sequential read speed, sequential write speed, random read speed, random write speed , IOPS score, all of that in relation to Blocksize. also outputs any delays

please use C to do so.

inputs:- the directory of the drive and the Blocksize to get the speed of read and write

/*

**   Compile:    gcc -o hddbench -O2 -march=x86-64 try2.c -pthread

**   Run:        hddbench <device> <timeout_seconds> [number_of_threads]

**   Example:    ./hddbench /dev/sda 30 4

*/

 

#define _LARGEFILE64_SOURCE

 

#ifndef _REENTRANT

#define _REENTRANT

#endif

 

#include <pthread.h>

#include <stdio.h>

#include <stdlib.h>

#include <sys/types.h>

#include <unistd.h>

#include <errno.h>

#include <time.h>

#include <signal.h>

#include <sys/fcntl.h>

#include <sys/ioctl.h>

#include <linux/fs.h>

 

#define BLOCKSIZE 512 //constant for block size

#define O_DIRECT 00040000

 

pthread_mutex_t muteks = PTHREAD_MUTEX_INITIALIZER; //Initilize the pthread mutex

 

//variable declarations

int count;

int TIMEOUT;

time_t start; //variable to keep a track of time

 

//offset values

off64_t maxoffset = 0;

off64_t minoffset = 249994674176000uLL;

 

int threads; //count of pthreads

 

//data structure to be used in the program

//variables are defined for id, filename, number of bytes, offset, buffer size and seeds.

typedef struct {

int id;

int fd;

int run;

char* filename;

unsigned int seed;

unsigned long long numbytes;

char* buffer;

int count;

off64_t maxoffset;

off64_t minoffset;

} parm;

 

parm *p;

 

//function to calculate the time taken

//here, the time_t is ended, and value is calculated and printed for pthreads

void done() {

int i;

time_t end;

time(&end);

 

if (end < start + TIMEOUT) {

printf(“.”);

alarm(1);

return;

}

for (i = 0; i < threads; i++) {

p[i].run = 0;

}

}

 

//here, the final report is generated and printed

void report() {

if (count) {

printf(“.\nResults IOPS Score: %d \n %.3f”

“Time:\n         (%llu < offsets < %llu)\n”,

count / TIMEOUT, 1000.0 * TIMEOUT / count,

(unsigned long long)minoffset,

(unsigned long long)maxoffset);

}

exit(EXIT_SUCCESS); //for a clean exit

}

 

//function for error handling

void handle(const char *string, int error) {

if (error) {

perror(string);

exit(EXIT_FAILURE);//exit wwith error message

}

}

 

//function to seed the memory, set offsets, align the seeks according to block size

//pthread processes are unlocked for system process, and started

void* f(void *arg) {

int retval;

off64_t offset;

parm *p = (parm*)arg;

srand(p->seed);

 

/* wait for all processes */

pthread_mutex_lock(&muteks);

pthread_mutex_unlock(&muteks);

 

while (p->run) {

offset = (off64_t) ( (unsigned long long) (p->numbytes *

(rand_r(&(p->seed)) / (RAND_MAX + 1.0) )));

/* do blocksize aligned seeks */

offset = offset & (~((off64_t) 0) & (~(BLOCKSIZE-1))) ;

/* printf(“%d %x\n”, p->id, (unsigned long long )offset); */ //used for debugging

//read/write process done, handled using system header file

retval = lseek64(p->fd, offset, SEEK_SET);

handle(“lseek64”, retval == (off64_t) -1); //for error handling

retval = read(p->fd, p->buffer, BLOCKSIZE);

handle(“read”, retval < 0);//for error handling

p->count++;

//check offset

if (offset > p->maxoffset) {

p->maxoffset = offset;

} else if (offset < p->minoffset) {

p->minoffset = offset;

}

}

 

return NULL;

}

 

//main function

int main(int argc, char **argv) {

int fd, retval;

int physical_sector_size = 0;//physical sector size initialization

size_t logical_sector_size = 0ULL; //logical sector size initialization

unsigned long long numblocks, numbytes; //variables for number of blocks and bytes

unsigned long long ull;

unsigned long ul;

pthread_t *t_id;  //pthread ID

pthread_attr_t pthread_custom_attr; //pthread attribute setup

int i;

 

setvbuf(stdout, NULL, _IONBF, 0);

//usage argument help prompt if input is incorrect

if (!(argc == 3 || argc == 4)) {

printf(“Usage: %s device seconds [threads]\n”, argv[0]);

exit(1);

}

 

TIMEOUT = atoi(argv[2]); //getting the timeut value from user input

//starting the thread

threads = 1;

if (argc == 4) {

threads = atoi(argv[3]); //starting thread according to user input

}

//open file for read only for operation

fd = open(argv[1], O_RDONLY | O_LARGEFILE | O_DIRECT);

handle(“open”, fd < 0);//for error handling

//ioctl operation of opened file using system header file, according to system procesor (32 bit or 64 bit)

#ifdef BLKGETSIZE64

retval = ioctl(fd, BLKGETSIZE64, &ull); //for 64 bit

numbytes = (unsigned long long)ull;

#else

retval = ioctl(fd, BLKGETSIZE, &ul); //for 32 bit

numbytes = (unsigned long long)ul;

#endif

 

//get the desired values from ioctl and store in specific variables

handle(“ioctl”, retval == -1);//for error handling

retval = ioctl(fd, BLKBSZGET, &logical_sector_size);

handle(“ioctl”, retval == -1 && logical_sector_size > 0);//for error handling

retval = ioctl(fd, BLKSSZGET, &physical_sector_size);

handle(“ioctl”, retval == -1 && physical_sector_size > 0);//for error handling

numblocks = ((unsigned long long) numbytes) /

(unsigned long long)BLOCKSIZE;

//print result of benchmarking

printf(“Benchmarking %s\n[%llu blocks, %llu bytes,\n In Format: Sequential Read and Write, Random Read and Write\n”

“%llu GBpers, %llu MBpers, %llu GiBpers, %llu MiBpers]\n”,

argv[1], numblocks, numbytes,

numbytes/(1024uLL*1024uLL*1024uLL*TIMEOUT),

numbytes / (1024uLL*1024uLL*TIMEOUT),

numbytes/(1000uLL*1000uLL*1000uLL*TIMEOUT),

numbytes / (1000uLL*1000uLL*TIMEOUT));

printf(“Delay %d seconds\n”, TIMEOUT);

//start pthread with memory allocation

t_id = (pthread_t *)malloc(threads*sizeof(pthread_t)); //memory allocation

handle(“malloc”, t_id == NULL);//for error handling

pthread_attr_init(&pthread_custom_attr); //attribute initialization

p = (parm *)malloc(sizeof(parm)*threads);

handle(“malloc”, p == NULL);//for error handling

//start timer for timed test

time(&start);

//pthread operation

pthread_mutex_lock(&muteks);

 

srand((unsigned int)start*(unsigned int)getpid());

//pthread creation loop for all threads (user input)

for (i = 0; i < threads; i++) {

p[i].id = i;

p[i].filename = argv[1]; //filename from user input

p[i].seed = rand()+i;

p[i].fd = dup(fd);

handle(“dup”, p[i].fd < 0);//for error handling

p[i].buffer = (char *) memalign(512*8, sizeof(char)*BLOCKSIZE);

/* printf(“%x\n”, (int)(&(p[i].buffer))); */ //used for debugging

p[i].numbytes = numbytes;

handle(“malloc”, p[i].buffer == NULL);//for error handling

p[i].run = 1;

p[i].count = 0;

p[i].minoffset = minoffset;

p[i].maxoffset = maxoffset;

 

retval = pthread_create(&(t_id[i]), NULL, f, (void*)(p+i));

handle(“pthread_create”, retval != 0);

}

//delay

sleep(1);

time(&start);

signal(SIGALRM, &done);

alarm(1);

 

pthread_mutex_unlock(&muteks);

//join threads

for (i = 0; i < threads; i++) {

pthread_join(t_id[i], NULL);

}

//get offset values (sorting)

for (i = 0; i < threads; i++) {

count += p[i].count;

if (p[i].maxoffset > maxoffset) {

maxoffset = p[i].maxoffset;

}

if (p[i].minoffset < minoffset) {

minoffset = p[i].minoffset;

}

}

//report result

report();

 

/* notreached */

return 0;

}