16ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya/* 26ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya * Custom fio(1) engine that submits synchronous atomic writes to file. 36ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya * 4b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya * Copyright (C) 2013 Fusion-io, Inc. 5b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya * Author: Santhosh Kumar Koundinya (skoundinya@fusionio.com). 66ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya * 76ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya * This program is free software; you can redistribute it and/or modify it 86ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya * under the terms of the GNU General Public License as published by the Free 915a6f166ed6fe0f221539b8ffea55905ed25b440Jens Axboe * Software Foundation; under version 2 of the License. 106ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya * 116ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya * This program is distributed in the hope that it will be useful, but WITHOUT 126ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 136ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License version 146ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya * 2 for more details. 156ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya * 166ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya * You should have received a copy of the GNU General Public License Version 2 176ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya * along with this program; if not see <http://www.gnu.org/licenses/> 186ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya */ 196ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya 206ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya#include <stdlib.h> 216ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya#include <stdint.h> 226ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya 236ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya#include "../fio.h" 246ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya 25b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya#include <nvm/nvm_primitives.h> 266ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya 274728b3c82f07612d64b79a67adc31dd9ca3c79fcChandra Mallarapu#define NUM_ATOMIC_CAPABILITIES (5) 284728b3c82f07612d64b79a67adc31dd9ca3c79fcChandra Mallarapu 29b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinyastruct fas_data { 30b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya nvm_handle_t nvm_handle; 31b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya size_t xfer_buf_align; 32b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya size_t xfer_buflen_align; 33b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya size_t xfer_buflen_max; 34b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya size_t sector_size; 356ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya}; 366ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya 376ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinyastatic int queue(struct thread_data *td, struct io_u *io_u) 386ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya{ 396ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya int rc; 40b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya struct fas_data *d = (struct fas_data *) io_u->file->engine_data; 416ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya 426ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya if (io_u->ddir != DDIR_WRITE) { 43b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya td_vmsg(td, EINVAL, "only writes supported", "io_u->ddir"); 44b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya rc = -EINVAL; 456ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya goto out; 466ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya } 47b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya 48b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya if ((size_t) io_u->xfer_buf % d->xfer_buf_align) { 49b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya td_vmsg(td, EINVAL, "unaligned data buffer", "io_u->xfer_buf"); 50b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya rc = -EINVAL; 516ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya goto out; 526ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya } 53b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya 54b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya if (io_u->xfer_buflen % d->xfer_buflen_align) { 55b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya td_vmsg(td, EINVAL, "unaligned data size", "io_u->xfer_buflen"); 56b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya rc = -EINVAL; 576ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya goto out; 586ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya } 596ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya 60b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya if (io_u->xfer_buflen > d->xfer_buflen_max) { 61b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya td_vmsg(td, EINVAL, "data too big", "io_u->xfer_buflen"); 62b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya rc = -EINVAL; 63b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya goto out; 646ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya } 656ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya 66b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya rc = nvm_atomic_write(d->nvm_handle, (uint64_t) io_u->xfer_buf, 67b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya io_u->xfer_buflen, io_u->offset / d->sector_size); 686ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya if (rc == -1) { 69b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya td_verror(td, errno, "nvm_atomic_write"); 70b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya rc = -errno; 716ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya goto out; 726ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya } 73b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya rc = FIO_Q_COMPLETED; 746ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinyaout: 756ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya if (rc < 0) 76b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya io_u->error = -rc; 776ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya 786ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya return rc; 796ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya} 806ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya 816ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinyastatic int open_file(struct thread_data *td, struct fio_file *f) 826ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya{ 836ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya int rc; 84b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya int fio_unused close_file_rc; 85b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya struct fas_data *d; 86b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya nvm_version_t nvm_version; 874728b3c82f07612d64b79a67adc31dd9ca3c79fcChandra Mallarapu nvm_capability_t nvm_capability[NUM_ATOMIC_CAPABILITIES]; 88b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya 896ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya 906ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya d = malloc(sizeof(*d)); 916ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya if (!d) { 92b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya td_verror(td, ENOMEM, "malloc"); 93b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya rc = ENOMEM; 946ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya goto error; 956ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya } 96b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya d->nvm_handle = -1; 97c11a9ddfb9a53f9faa78b72fc79be2f46addc8aaJens Axboe f->engine_data = (uintptr_t) d; 986ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya 996ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya rc = generic_open_file(td, f); 1006ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya 101b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya if (rc) 102b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya goto free_engine_data; 103b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya 104b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya /* Set the version of the library as seen when engine is compiled */ 105b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya nvm_version.major = NVM_PRIMITIVES_API_MAJOR; 106b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya nvm_version.minor = NVM_PRIMITIVES_API_MINOR; 107b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya nvm_version.micro = NVM_PRIMITIVES_API_MICRO; 108b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya 109b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya d->nvm_handle = nvm_get_handle(f->fd, &nvm_version); 110b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya if (d->nvm_handle == -1) { 111b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya td_vmsg(td, errno, "nvm_get_handle failed", "nvm_get_handle"); 112b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya rc = errno; 113b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya goto close_file; 114b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya } 115b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya 116b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya nvm_capability[0].cap_id = NVM_CAP_ATOMIC_WRITE_START_ALIGN_ID; 117b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya nvm_capability[1].cap_id = NVM_CAP_ATOMIC_WRITE_MULTIPLICITY_ID; 118b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya nvm_capability[2].cap_id = NVM_CAP_ATOMIC_WRITE_MAX_VECTOR_SIZE_ID; 119b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya nvm_capability[3].cap_id = NVM_CAP_SECTOR_SIZE_ID; 1204728b3c82f07612d64b79a67adc31dd9ca3c79fcChandra Mallarapu nvm_capability[4].cap_id = NVM_CAP_ATOMIC_MAX_IOV_ID; 1214728b3c82f07612d64b79a67adc31dd9ca3c79fcChandra Mallarapu rc = nvm_get_capabilities(d->nvm_handle, nvm_capability, 1224728b3c82f07612d64b79a67adc31dd9ca3c79fcChandra Mallarapu NUM_ATOMIC_CAPABILITIES, false); 123b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya if (rc == -1) { 124b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya td_vmsg(td, errno, "error in getting atomic write capabilities", "nvm_get_capabilities"); 125b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya rc = errno; 126b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya goto close_file; 1274728b3c82f07612d64b79a67adc31dd9ca3c79fcChandra Mallarapu } else if (rc < NUM_ATOMIC_CAPABILITIES) { 128b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya td_vmsg(td, EINVAL, "couldn't get all the atomic write capabilities" , "nvm_get_capabilities"); 129b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya rc = ECANCELED; 130b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya goto close_file; 131b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya } 132b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya /* Reset rc to 0 because we got all capabilities we needed */ 133b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya rc = 0; 134b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya d->xfer_buf_align = nvm_capability[0].cap_value; 135b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya d->xfer_buflen_align = nvm_capability[1].cap_value; 1364728b3c82f07612d64b79a67adc31dd9ca3c79fcChandra Mallarapu d->xfer_buflen_max = d->xfer_buflen_align * nvm_capability[2].cap_value * nvm_capability[4].cap_value; 137b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya d->sector_size = nvm_capability[3].cap_value; 138b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya 1396ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinyaout: 1406ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya return rc; 141b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinyaclose_file: 142b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya close_file_rc = generic_close_file(td, f); 143b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinyafree_engine_data: 144b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya free(d); 1456ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinyaerror: 1466ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya f->fd = -1; 147c11a9ddfb9a53f9faa78b72fc79be2f46addc8aaJens Axboe f->engine_data = 0; 1486ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya goto out; 1496ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya} 1506ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya 1516ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinyastatic int close_file(struct thread_data *td, struct fio_file *f) 1526ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya{ 153b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya struct fas_data *d = (struct fas_data *) f->engine_data; 154b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya 155b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya if (d) { 156b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya if (d->nvm_handle != -1) 157b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya nvm_release_handle(d->nvm_handle); 158b2c77c25cac5eb49f6966c46aeef7a17d831e5b1Santhosh Koundinya free(d); 159c11a9ddfb9a53f9faa78b72fc79be2f46addc8aaJens Axboe f->engine_data = 0; 1606ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya } 1616ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya 1626ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya return generic_close_file(td, f); 1636ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya} 1646ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya 1656ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinyastatic struct ioengine_ops ioengine = { 1666ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya .name = "fusion-aw-sync", 1676ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya .version = FIO_IOOPS_VERSION, 1686ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya .queue = queue, 1696ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya .open_file = open_file, 1706ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya .close_file = close_file, 1716ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya .get_file_size = generic_get_file_size, 1726ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya .flags = FIO_SYNCIO | FIO_RAWIO | FIO_MEMALIGN 1736ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya}; 1746ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya 1756ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinyastatic void fio_init fio_fusion_aw_init(void) 1766ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya{ 1776ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya register_ioengine(&ioengine); 1786ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya} 1796ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya 1806ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinyastatic void fio_exit fio_fusion_aw_exit(void) 1816ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya{ 1826ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya unregister_ioengine(&ioengine); 1836ef63580ab6e3d73f205d05b126dbeb33e0508bcSanthosh Koundinya} 184