1/* 2 * TRIM/DISCARD support 3 */ 4#include <unistd.h> 5#include <fcntl.h> 6#include <string.h> 7#include <assert.h> 8#include <pthread.h> 9 10#include "fio.h" 11#include "trim.h" 12 13#ifdef FIO_HAVE_TRIM 14int get_next_trim(struct thread_data *td, struct io_u *io_u) 15{ 16 struct io_piece *ipo; 17 18 /* 19 * this io_u is from a requeue, we already filled the offsets 20 */ 21 if (io_u->file) 22 return 0; 23 if (flist_empty(&td->trim_list)) 24 return 1; 25 26 assert(td->trim_entries); 27 ipo = flist_entry(td->trim_list.next, struct io_piece, trim_list); 28 remove_trim_entry(td, ipo); 29 30 io_u->offset = ipo->offset; 31 io_u->buflen = ipo->len; 32 io_u->file = ipo->file; 33 34 /* 35 * If not verifying that trimmed ranges return zeroed data, 36 * remove this from the to-read verify lists 37 */ 38 if (!td->o.trim_zero) { 39 if (ipo->flags & IP_F_ONLIST) 40 flist_del(&ipo->list); 41 else { 42 assert(ipo->flags & IP_F_ONRB); 43 rb_erase(&ipo->rb_node, &td->io_hist_tree); 44 } 45 td->io_hist_len--; 46 free(ipo); 47 } else 48 ipo->flags |= IP_F_TRIMMED; 49 50 if (!fio_file_open(io_u->file)) { 51 int r = td_io_open_file(td, io_u->file); 52 53 if (r) { 54 dprint(FD_VERIFY, "failed file %s open\n", 55 io_u->file->file_name); 56 return 1; 57 } 58 } 59 60 get_file(io_u->file); 61 assert(fio_file_open(io_u->file)); 62 io_u->ddir = DDIR_TRIM; 63 io_u->xfer_buf = NULL; 64 io_u->xfer_buflen = io_u->buflen; 65 66 dprint(FD_VERIFY, "get_next_trim: ret io_u %p\n", io_u); 67 return 0; 68} 69 70int io_u_should_trim(struct thread_data *td, struct io_u *io_u) 71{ 72 unsigned long long val; 73 unsigned long r; 74 75 if (!td->o.trim_percentage) 76 return 0; 77 78 if (td->o.use_os_rand) { 79 r = os_random_long(&td->trim_state); 80 val = (OS_RAND_MAX / 100ULL); 81 } else { 82 r = __rand(&td->__trim_state); 83 val = (FRAND_MAX / 100ULL); 84 } 85 86 val *= (unsigned long long) td->o.trim_percentage; 87 return r <= val; 88} 89#endif 90