1*e21c39aaSAnton Nayshtut /* SPDX-License-Identifier: BSD-3-Clause 2*e21c39aaSAnton Nayshtut * Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3*e21c39aaSAnton Nayshtut */ 4*e21c39aaSAnton Nayshtut #include "spdk/stdinc.h" 5*e21c39aaSAnton Nayshtut #include "spdk/event.h" 6*e21c39aaSAnton Nayshtut #include "spdk/log.h" 7*e21c39aaSAnton Nayshtut #include "spdk/string.h" 8*e21c39aaSAnton Nayshtut #include "spdk/config.h" 9*e21c39aaSAnton Nayshtut #include "spdk/util.h" 10*e21c39aaSAnton Nayshtut #include "spdk/thread.h" 11*e21c39aaSAnton Nayshtut #include "aio_mgr.h" 12*e21c39aaSAnton Nayshtut #include "fsdev_aio.h" 13*e21c39aaSAnton Nayshtut 14*e21c39aaSAnton Nayshtut #define IO_STATUS_ASYNC INT_MIN 15*e21c39aaSAnton Nayshtut 16*e21c39aaSAnton Nayshtut #ifndef UNUSED 17*e21c39aaSAnton Nayshtut #define UNUSED(x) (void)(x) 18*e21c39aaSAnton Nayshtut #endif 19*e21c39aaSAnton Nayshtut 20*e21c39aaSAnton Nayshtut /* See https://libfuse.github.io/doxygen/structfuse__conn__info.html */ 21*e21c39aaSAnton Nayshtut #define MAX_BACKGROUND (100) 22*e21c39aaSAnton Nayshtut #define TIME_GRAN (1) 23*e21c39aaSAnton Nayshtut #define MAX_AIOS 256 24*e21c39aaSAnton Nayshtut #define DEFAULT_WRITEBACK_CACHE true 25*e21c39aaSAnton Nayshtut #define DEFAULT_MAX_WRITE 0x00020000 26*e21c39aaSAnton Nayshtut #define DEFAULT_XATTR_ENABLED false 27*e21c39aaSAnton Nayshtut #define DEFAULT_TIMEOUT_MS 0 /* to prevent the attribute caching */ 28*e21c39aaSAnton Nayshtut 29*e21c39aaSAnton Nayshtut #ifdef SPDK_CONFIG_HAVE_STRUCT_STAT_ST_ATIM 30*e21c39aaSAnton Nayshtut /* Linux */ 31*e21c39aaSAnton Nayshtut #define ST_ATIM_NSEC(stbuf) ((stbuf)->st_atim.tv_nsec) 32*e21c39aaSAnton Nayshtut #define ST_CTIM_NSEC(stbuf) ((stbuf)->st_ctim.tv_nsec) 33*e21c39aaSAnton Nayshtut #define ST_MTIM_NSEC(stbuf) ((stbuf)->st_mtim.tv_nsec) 34*e21c39aaSAnton Nayshtut #define ST_ATIM_NSEC_SET(stbuf, val) (stbuf)->st_atim.tv_nsec = (val) 35*e21c39aaSAnton Nayshtut #define ST_CTIM_NSEC_SET(stbuf, val) (stbuf)->st_ctim.tv_nsec = (val) 36*e21c39aaSAnton Nayshtut #define ST_MTIM_NSEC_SET(stbuf, val) (stbuf)->st_mtim.tv_nsec = (val) 37*e21c39aaSAnton Nayshtut #elif defined(SPDK_CONFIG_HAVE_STRUCT_STAT_ST_ATIMESPEC) 38*e21c39aaSAnton Nayshtut /* FreeBSD */ 39*e21c39aaSAnton Nayshtut #define ST_ATIM_NSEC(stbuf) ((stbuf)->st_atimespec.tv_nsec) 40*e21c39aaSAnton Nayshtut #define ST_CTIM_NSEC(stbuf) ((stbuf)->st_ctimespec.tv_nsec) 41*e21c39aaSAnton Nayshtut #define ST_MTIM_NSEC(stbuf) ((stbuf)->st_mtimespec.tv_nsec) 42*e21c39aaSAnton Nayshtut #define ST_ATIM_NSEC_SET(stbuf, val) (stbuf)->st_atimespec.tv_nsec = (val) 43*e21c39aaSAnton Nayshtut #define ST_CTIM_NSEC_SET(stbuf, val) (stbuf)->st_ctimespec.tv_nsec = (val) 44*e21c39aaSAnton Nayshtut #define ST_MTIM_NSEC_SET(stbuf, val) (stbuf)->st_mtimespec.tv_nsec = (val) 45*e21c39aaSAnton Nayshtut #else 46*e21c39aaSAnton Nayshtut #define ST_ATIM_NSEC(stbuf) 0 47*e21c39aaSAnton Nayshtut #define ST_CTIM_NSEC(stbuf) 0 48*e21c39aaSAnton Nayshtut #define ST_MTIM_NSEC(stbuf) 0 49*e21c39aaSAnton Nayshtut #define ST_ATIM_NSEC_SET(stbuf, val) do { } while (0) 50*e21c39aaSAnton Nayshtut #define ST_CTIM_NSEC_SET(stbuf, val) do { } while (0) 51*e21c39aaSAnton Nayshtut #define ST_MTIM_NSEC_SET(stbuf, val) do { } while (0) 52*e21c39aaSAnton Nayshtut #endif 53*e21c39aaSAnton Nayshtut 54*e21c39aaSAnton Nayshtut struct lo_cred { 55*e21c39aaSAnton Nayshtut uid_t euid; 56*e21c39aaSAnton Nayshtut gid_t egid; 57*e21c39aaSAnton Nayshtut }; 58*e21c39aaSAnton Nayshtut 59*e21c39aaSAnton Nayshtut /** Inode number type */ 60*e21c39aaSAnton Nayshtut typedef uint64_t spdk_ino_t; 61*e21c39aaSAnton Nayshtut 62*e21c39aaSAnton Nayshtut struct lo_key { 63*e21c39aaSAnton Nayshtut ino_t ino; 64*e21c39aaSAnton Nayshtut dev_t dev; 65*e21c39aaSAnton Nayshtut }; 66*e21c39aaSAnton Nayshtut 67*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_handle { 68*e21c39aaSAnton Nayshtut int fd; 69*e21c39aaSAnton Nayshtut struct { 70*e21c39aaSAnton Nayshtut DIR *dp; 71*e21c39aaSAnton Nayshtut struct dirent *entry; 72*e21c39aaSAnton Nayshtut off_t offset; 73*e21c39aaSAnton Nayshtut } dir; 74*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *fobject; 75*e21c39aaSAnton Nayshtut TAILQ_ENTRY(spdk_fsdev_file_handle) link; 76*e21c39aaSAnton Nayshtut }; 77*e21c39aaSAnton Nayshtut 78*e21c39aaSAnton Nayshtut #define FOBJECT_FMT "ino=%" PRIu64 " dev=%" PRIu64 79*e21c39aaSAnton Nayshtut #define FOBJECT_ARGS(fo) ((uint64_t)(fo)->key.ino), ((uint64_t)(fo)->key.dev) 80*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object { 81*e21c39aaSAnton Nayshtut uint32_t is_symlink : 1; 82*e21c39aaSAnton Nayshtut uint32_t is_dir : 1; 83*e21c39aaSAnton Nayshtut uint32_t reserved : 30; 84*e21c39aaSAnton Nayshtut int fd; 85*e21c39aaSAnton Nayshtut char *fd_str; 86*e21c39aaSAnton Nayshtut struct lo_key key; 87*e21c39aaSAnton Nayshtut uint64_t refcount; 88*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *parent_fobject; 89*e21c39aaSAnton Nayshtut TAILQ_ENTRY(spdk_fsdev_file_object) link; 90*e21c39aaSAnton Nayshtut TAILQ_HEAD(, spdk_fsdev_file_object) leafs; 91*e21c39aaSAnton Nayshtut TAILQ_HEAD(, spdk_fsdev_file_handle) handles; 92*e21c39aaSAnton Nayshtut struct spdk_spinlock lock; 93*e21c39aaSAnton Nayshtut char name[]; 94*e21c39aaSAnton Nayshtut }; 95*e21c39aaSAnton Nayshtut 96*e21c39aaSAnton Nayshtut struct aio_fsdev { 97*e21c39aaSAnton Nayshtut struct spdk_fsdev fsdev; 98*e21c39aaSAnton Nayshtut char *root_path; 99*e21c39aaSAnton Nayshtut int proc_self_fd; 100*e21c39aaSAnton Nayshtut pthread_mutex_t mutex; 101*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *root; 102*e21c39aaSAnton Nayshtut TAILQ_ENTRY(aio_fsdev) tailq; 103*e21c39aaSAnton Nayshtut bool xattr_enabled; 104*e21c39aaSAnton Nayshtut }; 105*e21c39aaSAnton Nayshtut 106*e21c39aaSAnton Nayshtut struct aio_fsdev_io { 107*e21c39aaSAnton Nayshtut struct spdk_aio_mgr_io *aio; 108*e21c39aaSAnton Nayshtut struct aio_io_channel *ch; 109*e21c39aaSAnton Nayshtut TAILQ_ENTRY(aio_fsdev_io) link; 110*e21c39aaSAnton Nayshtut }; 111*e21c39aaSAnton Nayshtut 112*e21c39aaSAnton Nayshtut struct aio_io_channel { 113*e21c39aaSAnton Nayshtut struct spdk_poller *poller; 114*e21c39aaSAnton Nayshtut struct spdk_aio_mgr *mgr; 115*e21c39aaSAnton Nayshtut TAILQ_HEAD(, aio_fsdev_io) ios_in_progress; 116*e21c39aaSAnton Nayshtut }; 117*e21c39aaSAnton Nayshtut 118*e21c39aaSAnton Nayshtut static TAILQ_HEAD(, aio_fsdev) g_aio_fsdev_head = TAILQ_HEAD_INITIALIZER( 119*e21c39aaSAnton Nayshtut g_aio_fsdev_head); 120*e21c39aaSAnton Nayshtut 121*e21c39aaSAnton Nayshtut static inline struct aio_fsdev * 122*e21c39aaSAnton Nayshtut fsdev_to_aio_fsdev(struct spdk_fsdev *fsdev) 123*e21c39aaSAnton Nayshtut { 124*e21c39aaSAnton Nayshtut return SPDK_CONTAINEROF(fsdev, struct aio_fsdev, fsdev); 125*e21c39aaSAnton Nayshtut } 126*e21c39aaSAnton Nayshtut 127*e21c39aaSAnton Nayshtut static inline struct spdk_fsdev_io * 128*e21c39aaSAnton Nayshtut aio_to_fsdev_io(const struct aio_fsdev_io *aio_io) 129*e21c39aaSAnton Nayshtut { 130*e21c39aaSAnton Nayshtut return SPDK_CONTAINEROF(aio_io, struct spdk_fsdev_io, driver_ctx); 131*e21c39aaSAnton Nayshtut } 132*e21c39aaSAnton Nayshtut 133*e21c39aaSAnton Nayshtut static inline struct aio_fsdev_io * 134*e21c39aaSAnton Nayshtut fsdev_to_aio_io(const struct spdk_fsdev_io *fsdev_io) 135*e21c39aaSAnton Nayshtut { 136*e21c39aaSAnton Nayshtut return (struct aio_fsdev_io *)fsdev_io->driver_ctx; 137*e21c39aaSAnton Nayshtut } 138*e21c39aaSAnton Nayshtut 139*e21c39aaSAnton Nayshtut static inline bool 140*e21c39aaSAnton Nayshtut fsdev_aio_is_valid_fobject(struct aio_fsdev *vfsdev, struct spdk_fsdev_file_object *fobject) 141*e21c39aaSAnton Nayshtut { 142*e21c39aaSAnton Nayshtut return fobject != NULL; 143*e21c39aaSAnton Nayshtut } 144*e21c39aaSAnton Nayshtut 145*e21c39aaSAnton Nayshtut static inline bool 146*e21c39aaSAnton Nayshtut fsdev_aio_is_valid_fhandle(struct aio_fsdev *vfsdev, struct spdk_fsdev_file_handle *fhandle) 147*e21c39aaSAnton Nayshtut { 148*e21c39aaSAnton Nayshtut return fhandle != NULL; 149*e21c39aaSAnton Nayshtut } 150*e21c39aaSAnton Nayshtut 151*e21c39aaSAnton Nayshtut static int 152*e21c39aaSAnton Nayshtut is_dot_or_dotdot(const char *name) 153*e21c39aaSAnton Nayshtut { 154*e21c39aaSAnton Nayshtut return name[0] == '.' && (name[1] == '\0' || 155*e21c39aaSAnton Nayshtut (name[1] == '.' && name[2] == '\0')); 156*e21c39aaSAnton Nayshtut } 157*e21c39aaSAnton Nayshtut 158*e21c39aaSAnton Nayshtut /* Is `path` a single path component that is not "." or ".."? */ 159*e21c39aaSAnton Nayshtut static int 160*e21c39aaSAnton Nayshtut is_safe_path_component(const char *path) 161*e21c39aaSAnton Nayshtut { 162*e21c39aaSAnton Nayshtut if (strchr(path, '/')) { 163*e21c39aaSAnton Nayshtut return 0; 164*e21c39aaSAnton Nayshtut } 165*e21c39aaSAnton Nayshtut 166*e21c39aaSAnton Nayshtut return !is_dot_or_dotdot(path); 167*e21c39aaSAnton Nayshtut } 168*e21c39aaSAnton Nayshtut 169*e21c39aaSAnton Nayshtut static struct spdk_fsdev_file_object * 170*e21c39aaSAnton Nayshtut lo_find_leaf_unsafe(struct spdk_fsdev_file_object *fobject, ino_t ino, dev_t dev) 171*e21c39aaSAnton Nayshtut { 172*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *leaf_fobject; 173*e21c39aaSAnton Nayshtut 174*e21c39aaSAnton Nayshtut TAILQ_FOREACH(leaf_fobject, &fobject->leafs, link) { 175*e21c39aaSAnton Nayshtut if (leaf_fobject->key.ino == ino && leaf_fobject->key.dev == dev) { 176*e21c39aaSAnton Nayshtut return leaf_fobject; 177*e21c39aaSAnton Nayshtut } 178*e21c39aaSAnton Nayshtut } 179*e21c39aaSAnton Nayshtut 180*e21c39aaSAnton Nayshtut return NULL; 181*e21c39aaSAnton Nayshtut } 182*e21c39aaSAnton Nayshtut 183*e21c39aaSAnton Nayshtut /* This function returns: 184*e21c39aaSAnton Nayshtut * 1 if the refcount is still non zero 185*e21c39aaSAnton Nayshtut * a negative error number if the refcount became zero, the file object was deleted but the defered underlying file deletion failed 186*e21c39aaSAnton Nayshtut * 0 if the refcount became zero, the file object was deleted and eithr the underlying file deletion wasn't defered or succeeded 187*e21c39aaSAnton Nayshtut */ 188*e21c39aaSAnton Nayshtut static int 189*e21c39aaSAnton Nayshtut file_object_unref(struct spdk_fsdev_file_object *fobject, uint32_t count) 190*e21c39aaSAnton Nayshtut { 191*e21c39aaSAnton Nayshtut int res = 0; 192*e21c39aaSAnton Nayshtut 193*e21c39aaSAnton Nayshtut spdk_spin_lock(&fobject->lock); 194*e21c39aaSAnton Nayshtut assert(fobject->refcount >= count); 195*e21c39aaSAnton Nayshtut fobject->refcount -= count; 196*e21c39aaSAnton Nayshtut spdk_spin_unlock(&fobject->lock); 197*e21c39aaSAnton Nayshtut 198*e21c39aaSAnton Nayshtut if (!fobject->refcount) { 199*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *parent_fobject = fobject->parent_fobject; 200*e21c39aaSAnton Nayshtut 201*e21c39aaSAnton Nayshtut if (parent_fobject) { 202*e21c39aaSAnton Nayshtut spdk_spin_lock(&parent_fobject->lock); 203*e21c39aaSAnton Nayshtut TAILQ_REMOVE(&parent_fobject->leafs, fobject, link); 204*e21c39aaSAnton Nayshtut spdk_spin_unlock(&parent_fobject->lock); 205*e21c39aaSAnton Nayshtut file_object_unref(parent_fobject, 1); /* unref by the leaf */ 206*e21c39aaSAnton Nayshtut } 207*e21c39aaSAnton Nayshtut 208*e21c39aaSAnton Nayshtut spdk_spin_destroy(&fobject->lock); 209*e21c39aaSAnton Nayshtut close(fobject->fd); 210*e21c39aaSAnton Nayshtut free(fobject->fd_str); 211*e21c39aaSAnton Nayshtut free(fobject); 212*e21c39aaSAnton Nayshtut } 213*e21c39aaSAnton Nayshtut 214*e21c39aaSAnton Nayshtut return res; 215*e21c39aaSAnton Nayshtut } 216*e21c39aaSAnton Nayshtut 217*e21c39aaSAnton Nayshtut static void 218*e21c39aaSAnton Nayshtut file_object_ref(struct spdk_fsdev_file_object *fobject) 219*e21c39aaSAnton Nayshtut { 220*e21c39aaSAnton Nayshtut spdk_spin_lock(&fobject->lock); 221*e21c39aaSAnton Nayshtut fobject->refcount++; 222*e21c39aaSAnton Nayshtut spdk_spin_unlock(&fobject->lock); 223*e21c39aaSAnton Nayshtut } 224*e21c39aaSAnton Nayshtut 225*e21c39aaSAnton Nayshtut static struct spdk_fsdev_file_object * 226*e21c39aaSAnton Nayshtut file_object_create_unsafe(struct spdk_fsdev_file_object *parent_fobject, int fd, ino_t ino, 227*e21c39aaSAnton Nayshtut dev_t dev, mode_t mode) 228*e21c39aaSAnton Nayshtut { 229*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *fobject; 230*e21c39aaSAnton Nayshtut 231*e21c39aaSAnton Nayshtut fobject = calloc(1, sizeof(*fobject)); 232*e21c39aaSAnton Nayshtut if (!fobject) { 233*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Cannot alloc fobject\n"); 234*e21c39aaSAnton Nayshtut return NULL; 235*e21c39aaSAnton Nayshtut } 236*e21c39aaSAnton Nayshtut 237*e21c39aaSAnton Nayshtut fobject->fd_str = spdk_sprintf_alloc("%d", fd); 238*e21c39aaSAnton Nayshtut if (!fobject->fd_str) { 239*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Cannot alloc fd_str\n"); 240*e21c39aaSAnton Nayshtut free(fobject); 241*e21c39aaSAnton Nayshtut return NULL; 242*e21c39aaSAnton Nayshtut } 243*e21c39aaSAnton Nayshtut 244*e21c39aaSAnton Nayshtut fobject->fd = fd; 245*e21c39aaSAnton Nayshtut fobject->key.ino = ino; 246*e21c39aaSAnton Nayshtut fobject->key.dev = dev; 247*e21c39aaSAnton Nayshtut fobject->refcount = 1; 248*e21c39aaSAnton Nayshtut fobject->is_symlink = S_ISLNK(mode) ? 1 : 0; 249*e21c39aaSAnton Nayshtut fobject->is_dir = S_ISDIR(mode) ? 1 : 0; 250*e21c39aaSAnton Nayshtut 251*e21c39aaSAnton Nayshtut TAILQ_INIT(&fobject->handles); 252*e21c39aaSAnton Nayshtut TAILQ_INIT(&fobject->leafs); 253*e21c39aaSAnton Nayshtut spdk_spin_init(&fobject->lock); 254*e21c39aaSAnton Nayshtut 255*e21c39aaSAnton Nayshtut if (parent_fobject) { 256*e21c39aaSAnton Nayshtut fobject->parent_fobject = parent_fobject; 257*e21c39aaSAnton Nayshtut TAILQ_INSERT_TAIL(&parent_fobject->leafs, fobject, link); 258*e21c39aaSAnton Nayshtut parent_fobject->refcount++; 259*e21c39aaSAnton Nayshtut } 260*e21c39aaSAnton Nayshtut 261*e21c39aaSAnton Nayshtut return fobject; 262*e21c39aaSAnton Nayshtut } 263*e21c39aaSAnton Nayshtut 264*e21c39aaSAnton Nayshtut static struct spdk_fsdev_file_handle * 265*e21c39aaSAnton Nayshtut file_handle_create(struct spdk_fsdev_file_object *fobject, int fd) 266*e21c39aaSAnton Nayshtut { 267*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_handle *fhandle; 268*e21c39aaSAnton Nayshtut 269*e21c39aaSAnton Nayshtut fhandle = calloc(1, sizeof(*fhandle)); 270*e21c39aaSAnton Nayshtut if (!fhandle) { 271*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Cannot alloc fhandle\n"); 272*e21c39aaSAnton Nayshtut return NULL; 273*e21c39aaSAnton Nayshtut } 274*e21c39aaSAnton Nayshtut 275*e21c39aaSAnton Nayshtut fhandle->fobject = fobject; 276*e21c39aaSAnton Nayshtut fhandle->fd = fd; 277*e21c39aaSAnton Nayshtut 278*e21c39aaSAnton Nayshtut spdk_spin_lock(&fobject->lock); 279*e21c39aaSAnton Nayshtut fobject->refcount++; 280*e21c39aaSAnton Nayshtut TAILQ_INSERT_TAIL(&fobject->handles, fhandle, link); 281*e21c39aaSAnton Nayshtut spdk_spin_unlock(&fobject->lock); 282*e21c39aaSAnton Nayshtut 283*e21c39aaSAnton Nayshtut return fhandle; 284*e21c39aaSAnton Nayshtut } 285*e21c39aaSAnton Nayshtut 286*e21c39aaSAnton Nayshtut static void 287*e21c39aaSAnton Nayshtut file_handle_delete(struct spdk_fsdev_file_handle *fhandle) 288*e21c39aaSAnton Nayshtut { 289*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *fobject = fhandle->fobject; 290*e21c39aaSAnton Nayshtut 291*e21c39aaSAnton Nayshtut spdk_spin_lock(&fobject->lock); 292*e21c39aaSAnton Nayshtut fobject->refcount--; 293*e21c39aaSAnton Nayshtut TAILQ_REMOVE(&fobject->handles, fhandle, link); 294*e21c39aaSAnton Nayshtut spdk_spin_unlock(&fobject->lock); 295*e21c39aaSAnton Nayshtut 296*e21c39aaSAnton Nayshtut if (fhandle->dir.dp) { 297*e21c39aaSAnton Nayshtut closedir(fhandle->dir.dp); 298*e21c39aaSAnton Nayshtut } 299*e21c39aaSAnton Nayshtut 300*e21c39aaSAnton Nayshtut close(fhandle->fd); 301*e21c39aaSAnton Nayshtut free(fhandle); 302*e21c39aaSAnton Nayshtut } 303*e21c39aaSAnton Nayshtut 304*e21c39aaSAnton Nayshtut static int 305*e21c39aaSAnton Nayshtut file_object_fill_attr(struct spdk_fsdev_file_object *fobject, struct spdk_fsdev_file_attr *attr) 306*e21c39aaSAnton Nayshtut { 307*e21c39aaSAnton Nayshtut struct stat stbuf; 308*e21c39aaSAnton Nayshtut int res; 309*e21c39aaSAnton Nayshtut 310*e21c39aaSAnton Nayshtut res = fstatat(fobject->fd, "", &stbuf, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW); 311*e21c39aaSAnton Nayshtut if (res == -1) { 312*e21c39aaSAnton Nayshtut res = -errno; 313*e21c39aaSAnton Nayshtut SPDK_ERRLOG("fstatat() failed with %d\n", res); 314*e21c39aaSAnton Nayshtut return res; 315*e21c39aaSAnton Nayshtut } 316*e21c39aaSAnton Nayshtut 317*e21c39aaSAnton Nayshtut memset(attr, 0, sizeof(*attr)); 318*e21c39aaSAnton Nayshtut 319*e21c39aaSAnton Nayshtut attr->ino = stbuf.st_ino; 320*e21c39aaSAnton Nayshtut attr->size = stbuf.st_size; 321*e21c39aaSAnton Nayshtut attr->blocks = stbuf.st_blocks; 322*e21c39aaSAnton Nayshtut attr->atime = stbuf.st_atime; 323*e21c39aaSAnton Nayshtut attr->mtime = stbuf.st_mtime; 324*e21c39aaSAnton Nayshtut attr->ctime = stbuf.st_ctime; 325*e21c39aaSAnton Nayshtut attr->atimensec = ST_ATIM_NSEC(&stbuf); 326*e21c39aaSAnton Nayshtut attr->mtimensec = ST_MTIM_NSEC(&stbuf); 327*e21c39aaSAnton Nayshtut attr->ctimensec = ST_CTIM_NSEC(&stbuf); 328*e21c39aaSAnton Nayshtut attr->mode = stbuf.st_mode; 329*e21c39aaSAnton Nayshtut attr->nlink = stbuf.st_nlink; 330*e21c39aaSAnton Nayshtut attr->uid = stbuf.st_uid; 331*e21c39aaSAnton Nayshtut attr->gid = stbuf.st_gid; 332*e21c39aaSAnton Nayshtut attr->rdev = stbuf.st_rdev; 333*e21c39aaSAnton Nayshtut attr->blksize = stbuf.st_blksize; 334*e21c39aaSAnton Nayshtut attr->valid_ms = DEFAULT_TIMEOUT_MS; 335*e21c39aaSAnton Nayshtut 336*e21c39aaSAnton Nayshtut return 0; 337*e21c39aaSAnton Nayshtut } 338*e21c39aaSAnton Nayshtut 339*e21c39aaSAnton Nayshtut static int 340*e21c39aaSAnton Nayshtut utimensat_empty(struct aio_fsdev *vfsdev, struct spdk_fsdev_file_object *fobject, 341*e21c39aaSAnton Nayshtut const struct timespec *tv) 342*e21c39aaSAnton Nayshtut { 343*e21c39aaSAnton Nayshtut int res; 344*e21c39aaSAnton Nayshtut 345*e21c39aaSAnton Nayshtut if (fobject->is_symlink) { 346*e21c39aaSAnton Nayshtut res = utimensat(fobject->fd, "", tv, AT_EMPTY_PATH); 347*e21c39aaSAnton Nayshtut if (res == -1 && errno == EINVAL) { 348*e21c39aaSAnton Nayshtut /* Sorry, no race free way to set times on symlink. */ 349*e21c39aaSAnton Nayshtut errno = EPERM; 350*e21c39aaSAnton Nayshtut } 351*e21c39aaSAnton Nayshtut } else { 352*e21c39aaSAnton Nayshtut res = utimensat(vfsdev->proc_self_fd, fobject->fd_str, tv, 0); 353*e21c39aaSAnton Nayshtut } 354*e21c39aaSAnton Nayshtut 355*e21c39aaSAnton Nayshtut return res; 356*e21c39aaSAnton Nayshtut } 357*e21c39aaSAnton Nayshtut 358*e21c39aaSAnton Nayshtut static int 359*e21c39aaSAnton Nayshtut lo_getattr(struct spdk_io_channel *ch, struct spdk_fsdev_io *fsdev_io) 360*e21c39aaSAnton Nayshtut { 361*e21c39aaSAnton Nayshtut int res; 362*e21c39aaSAnton Nayshtut struct aio_fsdev *vfsdev = fsdev_to_aio_fsdev(fsdev_io->fsdev); 363*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *fobject = fsdev_io->u_in.getattr.fobject; 364*e21c39aaSAnton Nayshtut 365*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fobject(vfsdev, fobject)) { 366*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid fobject: %p\n", fobject); 367*e21c39aaSAnton Nayshtut return -EINVAL; 368*e21c39aaSAnton Nayshtut } 369*e21c39aaSAnton Nayshtut 370*e21c39aaSAnton Nayshtut res = file_object_fill_attr(fobject, &fsdev_io->u_out.getattr.attr); 371*e21c39aaSAnton Nayshtut if (res) { 372*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Cannot fill attr for " FOBJECT_FMT " (err=%d)\n", FOBJECT_ARGS(fobject), res); 373*e21c39aaSAnton Nayshtut return res; 374*e21c39aaSAnton Nayshtut } 375*e21c39aaSAnton Nayshtut 376*e21c39aaSAnton Nayshtut SPDK_DEBUGLOG(fsdev_aio, "GETATTR succeeded for " FOBJECT_FMT "\n", FOBJECT_ARGS(fobject)); 377*e21c39aaSAnton Nayshtut return 0; 378*e21c39aaSAnton Nayshtut } 379*e21c39aaSAnton Nayshtut 380*e21c39aaSAnton Nayshtut static int 381*e21c39aaSAnton Nayshtut lo_opendir(struct spdk_io_channel *ch, struct spdk_fsdev_io *fsdev_io) 382*e21c39aaSAnton Nayshtut { 383*e21c39aaSAnton Nayshtut struct aio_fsdev *vfsdev = fsdev_to_aio_fsdev(fsdev_io->fsdev); 384*e21c39aaSAnton Nayshtut int error; 385*e21c39aaSAnton Nayshtut int fd; 386*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *fobject = fsdev_io->u_in.opendir.fobject; 387*e21c39aaSAnton Nayshtut uint32_t flags = fsdev_io->u_in.opendir.flags; 388*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_handle *fhandle = NULL; 389*e21c39aaSAnton Nayshtut 390*e21c39aaSAnton Nayshtut UNUSED(flags); 391*e21c39aaSAnton Nayshtut 392*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fobject(vfsdev, fobject)) { 393*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid fobject: %p\n", fobject); 394*e21c39aaSAnton Nayshtut return -EINVAL; 395*e21c39aaSAnton Nayshtut } 396*e21c39aaSAnton Nayshtut 397*e21c39aaSAnton Nayshtut fd = openat(fobject->fd, ".", O_RDONLY); 398*e21c39aaSAnton Nayshtut if (fd == -1) { 399*e21c39aaSAnton Nayshtut error = -errno; 400*e21c39aaSAnton Nayshtut SPDK_ERRLOG("openat failed for " FOBJECT_FMT " (err=%d)\n", FOBJECT_ARGS(fobject), error); 401*e21c39aaSAnton Nayshtut goto out_err; 402*e21c39aaSAnton Nayshtut } 403*e21c39aaSAnton Nayshtut 404*e21c39aaSAnton Nayshtut fhandle = file_handle_create(fobject, fd); 405*e21c39aaSAnton Nayshtut if (fd == -1) { 406*e21c39aaSAnton Nayshtut error = -ENOMEM; 407*e21c39aaSAnton Nayshtut SPDK_ERRLOG("file_handle_create failed for " FOBJECT_FMT " (err=%d)\n", FOBJECT_ARGS(fobject), 408*e21c39aaSAnton Nayshtut error); 409*e21c39aaSAnton Nayshtut goto out_err; 410*e21c39aaSAnton Nayshtut } 411*e21c39aaSAnton Nayshtut 412*e21c39aaSAnton Nayshtut fhandle->dir.dp = fdopendir(fd); 413*e21c39aaSAnton Nayshtut if (fhandle->dir.dp == NULL) { 414*e21c39aaSAnton Nayshtut error = -errno; 415*e21c39aaSAnton Nayshtut SPDK_ERRLOG("fdopendir failed for " FOBJECT_FMT " (err=%d)\n", FOBJECT_ARGS(fobject), error); 416*e21c39aaSAnton Nayshtut goto out_err; 417*e21c39aaSAnton Nayshtut } 418*e21c39aaSAnton Nayshtut 419*e21c39aaSAnton Nayshtut fhandle->dir.offset = 0; 420*e21c39aaSAnton Nayshtut fhandle->dir.entry = NULL; 421*e21c39aaSAnton Nayshtut 422*e21c39aaSAnton Nayshtut SPDK_DEBUGLOG(fsdev_aio, "OPENDIR succeeded for " FOBJECT_FMT " (fh=%p)\n", 423*e21c39aaSAnton Nayshtut FOBJECT_ARGS(fobject), fhandle); 424*e21c39aaSAnton Nayshtut 425*e21c39aaSAnton Nayshtut fsdev_io->u_out.opendir.fhandle = fhandle; 426*e21c39aaSAnton Nayshtut 427*e21c39aaSAnton Nayshtut return 0; 428*e21c39aaSAnton Nayshtut 429*e21c39aaSAnton Nayshtut out_err: 430*e21c39aaSAnton Nayshtut if (fhandle) { 431*e21c39aaSAnton Nayshtut file_handle_delete(fhandle); 432*e21c39aaSAnton Nayshtut } else if (fd != -1) { 433*e21c39aaSAnton Nayshtut close(fd); 434*e21c39aaSAnton Nayshtut } 435*e21c39aaSAnton Nayshtut 436*e21c39aaSAnton Nayshtut return error; 437*e21c39aaSAnton Nayshtut } 438*e21c39aaSAnton Nayshtut 439*e21c39aaSAnton Nayshtut static int 440*e21c39aaSAnton Nayshtut lo_releasedir(struct spdk_io_channel *ch, struct spdk_fsdev_io *fsdev_io) 441*e21c39aaSAnton Nayshtut { 442*e21c39aaSAnton Nayshtut struct aio_fsdev *vfsdev = fsdev_to_aio_fsdev(fsdev_io->fsdev); 443*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *fobject = fsdev_io->u_in.releasedir.fobject; 444*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_handle *fhandle = fsdev_io->u_in.releasedir.fhandle; 445*e21c39aaSAnton Nayshtut 446*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fobject(vfsdev, fobject)) { 447*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid fobject: %p\n", fobject); 448*e21c39aaSAnton Nayshtut return -EINVAL; 449*e21c39aaSAnton Nayshtut } 450*e21c39aaSAnton Nayshtut 451*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fhandle(vfsdev, fhandle)) { 452*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid fhandle: %p\n", fhandle); 453*e21c39aaSAnton Nayshtut return -EINVAL; 454*e21c39aaSAnton Nayshtut } 455*e21c39aaSAnton Nayshtut 456*e21c39aaSAnton Nayshtut file_handle_delete(fhandle); 457*e21c39aaSAnton Nayshtut 458*e21c39aaSAnton Nayshtut /* 459*e21c39aaSAnton Nayshtut * scan-build doesn't understand that we only print the value of an already 460*e21c39aaSAnton Nayshtut * freed pointer and falsely reports "Use of memory after it is freed" here. 461*e21c39aaSAnton Nayshtut */ 462*e21c39aaSAnton Nayshtut #ifndef __clang_analyzer__ 463*e21c39aaSAnton Nayshtut SPDK_DEBUGLOG(fsdev_aio, "RELEASEDIR succeeded for " FOBJECT_FMT " (fh=%p)\n", 464*e21c39aaSAnton Nayshtut FOBJECT_ARGS(fobject), fhandle); 465*e21c39aaSAnton Nayshtut #endif 466*e21c39aaSAnton Nayshtut 467*e21c39aaSAnton Nayshtut return 0; 468*e21c39aaSAnton Nayshtut } 469*e21c39aaSAnton Nayshtut 470*e21c39aaSAnton Nayshtut static int 471*e21c39aaSAnton Nayshtut lo_do_lookup(struct aio_fsdev *vfsdev, struct spdk_fsdev_file_object *parent_fobject, 472*e21c39aaSAnton Nayshtut const char *name, struct spdk_fsdev_file_object **pfobject, 473*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_attr *attr) 474*e21c39aaSAnton Nayshtut { 475*e21c39aaSAnton Nayshtut int newfd; 476*e21c39aaSAnton Nayshtut int res; 477*e21c39aaSAnton Nayshtut struct stat stat; 478*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *fobject; 479*e21c39aaSAnton Nayshtut 480*e21c39aaSAnton Nayshtut /* Do not allow escaping root directory */ 481*e21c39aaSAnton Nayshtut if (parent_fobject == vfsdev->root && strcmp(name, "..") == 0) { 482*e21c39aaSAnton Nayshtut name = "."; 483*e21c39aaSAnton Nayshtut } 484*e21c39aaSAnton Nayshtut 485*e21c39aaSAnton Nayshtut newfd = openat(parent_fobject->fd, name, O_PATH | O_NOFOLLOW); 486*e21c39aaSAnton Nayshtut if (newfd == -1) { 487*e21c39aaSAnton Nayshtut res = -errno; 488*e21c39aaSAnton Nayshtut SPDK_DEBUGLOG(fsdev_aio, "openat( " FOBJECT_FMT " %s) failed with %d\n", 489*e21c39aaSAnton Nayshtut FOBJECT_ARGS(parent_fobject), name, res); 490*e21c39aaSAnton Nayshtut return res; 491*e21c39aaSAnton Nayshtut } 492*e21c39aaSAnton Nayshtut 493*e21c39aaSAnton Nayshtut res = fstatat(newfd, "", &stat, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW); 494*e21c39aaSAnton Nayshtut if (res == -1) { 495*e21c39aaSAnton Nayshtut res = -errno; 496*e21c39aaSAnton Nayshtut SPDK_ERRLOG("fstatat(%s) failed with %d\n", name, res); 497*e21c39aaSAnton Nayshtut close(newfd); 498*e21c39aaSAnton Nayshtut return res; 499*e21c39aaSAnton Nayshtut } 500*e21c39aaSAnton Nayshtut 501*e21c39aaSAnton Nayshtut spdk_spin_lock(&parent_fobject->lock); 502*e21c39aaSAnton Nayshtut fobject = lo_find_leaf_unsafe(parent_fobject, stat.st_ino, stat.st_dev); 503*e21c39aaSAnton Nayshtut if (fobject) { 504*e21c39aaSAnton Nayshtut close(newfd); 505*e21c39aaSAnton Nayshtut file_object_ref(fobject); /* reference by a lo_do_lookup caller */ 506*e21c39aaSAnton Nayshtut } else { 507*e21c39aaSAnton Nayshtut fobject = file_object_create_unsafe(parent_fobject, newfd, stat.st_ino, stat.st_dev, stat.st_mode); 508*e21c39aaSAnton Nayshtut } 509*e21c39aaSAnton Nayshtut spdk_spin_unlock(&parent_fobject->lock); 510*e21c39aaSAnton Nayshtut 511*e21c39aaSAnton Nayshtut if (!fobject) { 512*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Cannot create file object\n"); 513*e21c39aaSAnton Nayshtut close(newfd); 514*e21c39aaSAnton Nayshtut return -ENOMEM; 515*e21c39aaSAnton Nayshtut } 516*e21c39aaSAnton Nayshtut 517*e21c39aaSAnton Nayshtut if (attr) { 518*e21c39aaSAnton Nayshtut res = file_object_fill_attr(fobject, attr); 519*e21c39aaSAnton Nayshtut if (res) { 520*e21c39aaSAnton Nayshtut SPDK_ERRLOG("fill_attr(%s) failed with %d\n", name, res); 521*e21c39aaSAnton Nayshtut file_object_unref(fobject, 1); 522*e21c39aaSAnton Nayshtut close(newfd); 523*e21c39aaSAnton Nayshtut return res; 524*e21c39aaSAnton Nayshtut } 525*e21c39aaSAnton Nayshtut } 526*e21c39aaSAnton Nayshtut 527*e21c39aaSAnton Nayshtut *pfobject = fobject; 528*e21c39aaSAnton Nayshtut 529*e21c39aaSAnton Nayshtut SPDK_DEBUGLOG(fsdev_aio, "lookup(%s) in dir " FOBJECT_FMT ": " FOBJECT_FMT " fd=%d\n", 530*e21c39aaSAnton Nayshtut name, FOBJECT_ARGS(parent_fobject), FOBJECT_ARGS(fobject), fobject->fd); 531*e21c39aaSAnton Nayshtut return 0; 532*e21c39aaSAnton Nayshtut } 533*e21c39aaSAnton Nayshtut 534*e21c39aaSAnton Nayshtut static int 535*e21c39aaSAnton Nayshtut lo_lookup(struct spdk_io_channel *ch, struct spdk_fsdev_io *fsdev_io) 536*e21c39aaSAnton Nayshtut { 537*e21c39aaSAnton Nayshtut struct aio_fsdev *vfsdev = fsdev_to_aio_fsdev(fsdev_io->fsdev); 538*e21c39aaSAnton Nayshtut int err; 539*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *parent_fobject = fsdev_io->u_in.lookup.parent_fobject; 540*e21c39aaSAnton Nayshtut char *name = fsdev_io->u_in.lookup.name; 541*e21c39aaSAnton Nayshtut 542*e21c39aaSAnton Nayshtut if (!parent_fobject) { 543*e21c39aaSAnton Nayshtut err = file_object_fill_attr(vfsdev->root, &fsdev_io->u_out.lookup.attr); 544*e21c39aaSAnton Nayshtut if (err) { 545*e21c39aaSAnton Nayshtut SPDK_DEBUGLOG(fsdev_aio, "file_object_fill_attr(root) failed with err=%d\n", err); 546*e21c39aaSAnton Nayshtut return err; 547*e21c39aaSAnton Nayshtut } 548*e21c39aaSAnton Nayshtut 549*e21c39aaSAnton Nayshtut file_object_ref(vfsdev->root); 550*e21c39aaSAnton Nayshtut fsdev_io->u_out.lookup.fobject = vfsdev->root; 551*e21c39aaSAnton Nayshtut return 0; 552*e21c39aaSAnton Nayshtut } 553*e21c39aaSAnton Nayshtut 554*e21c39aaSAnton Nayshtut SPDK_DEBUGLOG(fsdev_aio, " name %s\n", name); 555*e21c39aaSAnton Nayshtut 556*e21c39aaSAnton Nayshtut /* Don't use is_safe_path_component(), allow "." and ".." for NFS export 557*e21c39aaSAnton Nayshtut * support. 558*e21c39aaSAnton Nayshtut */ 559*e21c39aaSAnton Nayshtut if (strchr(name, '/')) { 560*e21c39aaSAnton Nayshtut return -EINVAL; 561*e21c39aaSAnton Nayshtut } 562*e21c39aaSAnton Nayshtut 563*e21c39aaSAnton Nayshtut err = lo_do_lookup(vfsdev, parent_fobject, name, &fsdev_io->u_out.lookup.fobject, 564*e21c39aaSAnton Nayshtut &fsdev_io->u_out.lookup.attr); 565*e21c39aaSAnton Nayshtut if (err) { 566*e21c39aaSAnton Nayshtut SPDK_DEBUGLOG(fsdev_aio, "lo_do_lookup(%s) failed with err=%d\n", name, err); 567*e21c39aaSAnton Nayshtut return err; 568*e21c39aaSAnton Nayshtut } 569*e21c39aaSAnton Nayshtut 570*e21c39aaSAnton Nayshtut return 0; 571*e21c39aaSAnton Nayshtut } 572*e21c39aaSAnton Nayshtut 573*e21c39aaSAnton Nayshtut /* 574*e21c39aaSAnton Nayshtut * Change to uid/gid of caller so that file is created with ownership of caller. 575*e21c39aaSAnton Nayshtut */ 576*e21c39aaSAnton Nayshtut static int 577*e21c39aaSAnton Nayshtut lo_change_cred(const struct lo_cred *new, struct lo_cred *old) 578*e21c39aaSAnton Nayshtut { 579*e21c39aaSAnton Nayshtut int res; 580*e21c39aaSAnton Nayshtut 581*e21c39aaSAnton Nayshtut old->euid = geteuid(); 582*e21c39aaSAnton Nayshtut old->egid = getegid(); 583*e21c39aaSAnton Nayshtut 584*e21c39aaSAnton Nayshtut res = syscall(SYS_setresgid, -1, new->egid, -1); 585*e21c39aaSAnton Nayshtut if (res == -1) { 586*e21c39aaSAnton Nayshtut return -errno; 587*e21c39aaSAnton Nayshtut } 588*e21c39aaSAnton Nayshtut 589*e21c39aaSAnton Nayshtut res = syscall(SYS_setresuid, -1, new->euid, -1); 590*e21c39aaSAnton Nayshtut if (res == -1) { 591*e21c39aaSAnton Nayshtut int errno_save = -errno; 592*e21c39aaSAnton Nayshtut 593*e21c39aaSAnton Nayshtut syscall(SYS_setresgid, -1, old->egid, -1); 594*e21c39aaSAnton Nayshtut return errno_save; 595*e21c39aaSAnton Nayshtut } 596*e21c39aaSAnton Nayshtut 597*e21c39aaSAnton Nayshtut return 0; 598*e21c39aaSAnton Nayshtut } 599*e21c39aaSAnton Nayshtut 600*e21c39aaSAnton Nayshtut /* Regain Privileges */ 601*e21c39aaSAnton Nayshtut static void 602*e21c39aaSAnton Nayshtut lo_restore_cred(struct lo_cred *old) 603*e21c39aaSAnton Nayshtut { 604*e21c39aaSAnton Nayshtut int res; 605*e21c39aaSAnton Nayshtut 606*e21c39aaSAnton Nayshtut res = syscall(SYS_setresuid, -1, old->euid, -1); 607*e21c39aaSAnton Nayshtut if (res == -1) { 608*e21c39aaSAnton Nayshtut SPDK_ERRLOG("seteuid(%u)", old->euid); 609*e21c39aaSAnton Nayshtut } 610*e21c39aaSAnton Nayshtut 611*e21c39aaSAnton Nayshtut res = syscall(SYS_setresgid, -1, old->egid, -1); 612*e21c39aaSAnton Nayshtut if (res == -1) { 613*e21c39aaSAnton Nayshtut SPDK_ERRLOG("setegid(%u)", old->egid); 614*e21c39aaSAnton Nayshtut } 615*e21c39aaSAnton Nayshtut } 616*e21c39aaSAnton Nayshtut 617*e21c39aaSAnton Nayshtut static int 618*e21c39aaSAnton Nayshtut lo_readdir(struct spdk_io_channel *ch, struct spdk_fsdev_io *fsdev_io) 619*e21c39aaSAnton Nayshtut { 620*e21c39aaSAnton Nayshtut struct aio_fsdev *vfsdev = fsdev_to_aio_fsdev(fsdev_io->fsdev); 621*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *fobject = fsdev_io->u_in.readdir.fobject; 622*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_handle *fhandle = fsdev_io->u_in.readdir.fhandle; 623*e21c39aaSAnton Nayshtut uint64_t offset = fsdev_io->u_in.readdir.offset; 624*e21c39aaSAnton Nayshtut 625*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fobject(vfsdev, fobject)) { 626*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid fobject: %p\n", fobject); 627*e21c39aaSAnton Nayshtut return -EINVAL; 628*e21c39aaSAnton Nayshtut } 629*e21c39aaSAnton Nayshtut 630*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fhandle(vfsdev, fhandle)) { 631*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid fhandle: %p\n", fhandle); 632*e21c39aaSAnton Nayshtut return -EINVAL; 633*e21c39aaSAnton Nayshtut } 634*e21c39aaSAnton Nayshtut 635*e21c39aaSAnton Nayshtut if (((off_t)offset) != fhandle->dir.offset) { 636*e21c39aaSAnton Nayshtut seekdir(fhandle->dir.dp, offset); 637*e21c39aaSAnton Nayshtut fhandle->dir.entry = NULL; 638*e21c39aaSAnton Nayshtut fhandle->dir.offset = offset; 639*e21c39aaSAnton Nayshtut } 640*e21c39aaSAnton Nayshtut 641*e21c39aaSAnton Nayshtut while (1) { 642*e21c39aaSAnton Nayshtut off_t nextoff; 643*e21c39aaSAnton Nayshtut const char *name; 644*e21c39aaSAnton Nayshtut int res; 645*e21c39aaSAnton Nayshtut 646*e21c39aaSAnton Nayshtut if (!fhandle->dir.entry) { 647*e21c39aaSAnton Nayshtut errno = 0; 648*e21c39aaSAnton Nayshtut fhandle->dir.entry = readdir(fhandle->dir.dp); 649*e21c39aaSAnton Nayshtut if (!fhandle->dir.entry) { 650*e21c39aaSAnton Nayshtut if (errno) { /* Error */ 651*e21c39aaSAnton Nayshtut res = -errno; 652*e21c39aaSAnton Nayshtut SPDK_ERRLOG("readdir failed with err=%d", res); 653*e21c39aaSAnton Nayshtut return res; 654*e21c39aaSAnton Nayshtut } else { /* End of stream */ 655*e21c39aaSAnton Nayshtut break; 656*e21c39aaSAnton Nayshtut } 657*e21c39aaSAnton Nayshtut } 658*e21c39aaSAnton Nayshtut } 659*e21c39aaSAnton Nayshtut 660*e21c39aaSAnton Nayshtut nextoff = fhandle->dir.entry->d_off; 661*e21c39aaSAnton Nayshtut name = fhandle->dir.entry->d_name; 662*e21c39aaSAnton Nayshtut 663*e21c39aaSAnton Nayshtut /* Hide root's parent directory */ 664*e21c39aaSAnton Nayshtut if (fobject == vfsdev->root && strcmp(name, "..") == 0) { 665*e21c39aaSAnton Nayshtut goto skip_entry; 666*e21c39aaSAnton Nayshtut } 667*e21c39aaSAnton Nayshtut 668*e21c39aaSAnton Nayshtut if (is_dot_or_dotdot(name)) { 669*e21c39aaSAnton Nayshtut fsdev_io->u_out.readdir.fobject = NULL; 670*e21c39aaSAnton Nayshtut memset(&fsdev_io->u_out.readdir.attr, 0, sizeof(fsdev_io->u_out.readdir.attr)); 671*e21c39aaSAnton Nayshtut fsdev_io->u_out.readdir.attr.ino = fhandle->dir.entry->d_ino; 672*e21c39aaSAnton Nayshtut fsdev_io->u_out.readdir.attr.mode = DT_DIR << 12; 673*e21c39aaSAnton Nayshtut goto skip_lookup; 674*e21c39aaSAnton Nayshtut } 675*e21c39aaSAnton Nayshtut 676*e21c39aaSAnton Nayshtut res = lo_do_lookup(vfsdev, fobject, name, &fsdev_io->u_out.readdir.fobject, 677*e21c39aaSAnton Nayshtut &fsdev_io->u_out.readdir.attr); 678*e21c39aaSAnton Nayshtut if (res) { 679*e21c39aaSAnton Nayshtut SPDK_DEBUGLOG(fsdev_aio, "lo_do_lookup(%s) failed with err=%d\n", name, res); 680*e21c39aaSAnton Nayshtut return res; 681*e21c39aaSAnton Nayshtut } 682*e21c39aaSAnton Nayshtut 683*e21c39aaSAnton Nayshtut skip_lookup: 684*e21c39aaSAnton Nayshtut fsdev_io->u_out.readdir.name = name; 685*e21c39aaSAnton Nayshtut fsdev_io->u_out.readdir.offset = nextoff; 686*e21c39aaSAnton Nayshtut 687*e21c39aaSAnton Nayshtut res = fsdev_io->u_in.readdir.entry_cb_fn(fsdev_io, fsdev_io->internal.cb_arg); 688*e21c39aaSAnton Nayshtut if (res) { 689*e21c39aaSAnton Nayshtut if (fsdev_io->u_out.readdir.fobject) { 690*e21c39aaSAnton Nayshtut file_object_unref(fsdev_io->u_out.readdir.fobject, 1); 691*e21c39aaSAnton Nayshtut } 692*e21c39aaSAnton Nayshtut break; 693*e21c39aaSAnton Nayshtut } 694*e21c39aaSAnton Nayshtut 695*e21c39aaSAnton Nayshtut skip_entry: 696*e21c39aaSAnton Nayshtut fhandle->dir.entry = NULL; 697*e21c39aaSAnton Nayshtut fhandle->dir.offset = nextoff; 698*e21c39aaSAnton Nayshtut } 699*e21c39aaSAnton Nayshtut 700*e21c39aaSAnton Nayshtut SPDK_DEBUGLOG(fsdev_aio, "READDIR succeeded for " FOBJECT_FMT " (fh=%p, offset=%" PRIu64 ")\n", 701*e21c39aaSAnton Nayshtut FOBJECT_ARGS(fobject), fhandle, offset); 702*e21c39aaSAnton Nayshtut return 0; 703*e21c39aaSAnton Nayshtut } 704*e21c39aaSAnton Nayshtut 705*e21c39aaSAnton Nayshtut static int 706*e21c39aaSAnton Nayshtut lo_forget(struct spdk_io_channel *ch, struct spdk_fsdev_io *fsdev_io) 707*e21c39aaSAnton Nayshtut { 708*e21c39aaSAnton Nayshtut struct aio_fsdev *vfsdev = fsdev_to_aio_fsdev(fsdev_io->fsdev); 709*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *fobject = fsdev_io->u_in.readdir.fobject; 710*e21c39aaSAnton Nayshtut uint64_t nlookup = fsdev_io->u_in.forget.nlookup; 711*e21c39aaSAnton Nayshtut 712*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fobject(vfsdev, fobject)) { 713*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid fobject: %p\n", fobject); 714*e21c39aaSAnton Nayshtut return -EINVAL; 715*e21c39aaSAnton Nayshtut } 716*e21c39aaSAnton Nayshtut 717*e21c39aaSAnton Nayshtut file_object_unref(fobject, nlookup); 718*e21c39aaSAnton Nayshtut 719*e21c39aaSAnton Nayshtut return 0; 720*e21c39aaSAnton Nayshtut } 721*e21c39aaSAnton Nayshtut 722*e21c39aaSAnton Nayshtut static uint32_t 723*e21c39aaSAnton Nayshtut update_open_flags(struct aio_fsdev *vfsdev, uint32_t flags) 724*e21c39aaSAnton Nayshtut { 725*e21c39aaSAnton Nayshtut /* 726*e21c39aaSAnton Nayshtut * With writeback cache, kernel may send read requests even 727*e21c39aaSAnton Nayshtut * when userspace opened write-only 728*e21c39aaSAnton Nayshtut */ 729*e21c39aaSAnton Nayshtut if (vfsdev->fsdev.opts.writeback_cache_enabled && (flags & O_ACCMODE) == O_WRONLY) { 730*e21c39aaSAnton Nayshtut flags &= ~O_ACCMODE; 731*e21c39aaSAnton Nayshtut flags |= O_RDWR; 732*e21c39aaSAnton Nayshtut } 733*e21c39aaSAnton Nayshtut 734*e21c39aaSAnton Nayshtut /* 735*e21c39aaSAnton Nayshtut * With writeback cache, O_APPEND is handled by the kernel. 736*e21c39aaSAnton Nayshtut * This breaks atomicity (since the file may change in the 737*e21c39aaSAnton Nayshtut * underlying filesystem, so that the kernel's idea of the 738*e21c39aaSAnton Nayshtut * end of the file isn't accurate anymore). In this example, 739*e21c39aaSAnton Nayshtut * we just accept that. A more rigorous filesystem may want 740*e21c39aaSAnton Nayshtut * to return an error here 741*e21c39aaSAnton Nayshtut */ 742*e21c39aaSAnton Nayshtut if (vfsdev->fsdev.opts.writeback_cache_enabled && (flags & O_APPEND)) { 743*e21c39aaSAnton Nayshtut flags &= ~O_APPEND; 744*e21c39aaSAnton Nayshtut } 745*e21c39aaSAnton Nayshtut 746*e21c39aaSAnton Nayshtut /* 747*e21c39aaSAnton Nayshtut * O_DIRECT in guest should not necessarily mean bypassing page 748*e21c39aaSAnton Nayshtut * cache on host as well. If somebody needs that behavior, it 749*e21c39aaSAnton Nayshtut * probably should be a configuration knob in daemon. 750*e21c39aaSAnton Nayshtut */ 751*e21c39aaSAnton Nayshtut flags &= ~O_DIRECT; 752*e21c39aaSAnton Nayshtut 753*e21c39aaSAnton Nayshtut return flags; 754*e21c39aaSAnton Nayshtut } 755*e21c39aaSAnton Nayshtut 756*e21c39aaSAnton Nayshtut static int 757*e21c39aaSAnton Nayshtut lo_open(struct spdk_io_channel *ch, struct spdk_fsdev_io *fsdev_io) 758*e21c39aaSAnton Nayshtut { 759*e21c39aaSAnton Nayshtut struct aio_fsdev *vfsdev = fsdev_to_aio_fsdev(fsdev_io->fsdev); 760*e21c39aaSAnton Nayshtut int fd, saverr; 761*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *fobject = fsdev_io->u_in.open.fobject; 762*e21c39aaSAnton Nayshtut uint32_t flags = fsdev_io->u_in.open.flags; 763*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_handle *fhandle; 764*e21c39aaSAnton Nayshtut 765*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fobject(vfsdev, fobject)) { 766*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid fobject: %p\n", fobject); 767*e21c39aaSAnton Nayshtut return -EINVAL; 768*e21c39aaSAnton Nayshtut } 769*e21c39aaSAnton Nayshtut 770*e21c39aaSAnton Nayshtut flags = update_open_flags(vfsdev, flags); 771*e21c39aaSAnton Nayshtut 772*e21c39aaSAnton Nayshtut fd = openat(vfsdev->proc_self_fd, fobject->fd_str, flags & ~O_NOFOLLOW); 773*e21c39aaSAnton Nayshtut if (fd == -1) { 774*e21c39aaSAnton Nayshtut saverr = -errno; 775*e21c39aaSAnton Nayshtut SPDK_ERRLOG("openat(%d, %s, 0x%08" PRIx32 ") failed with err=%d\n", 776*e21c39aaSAnton Nayshtut vfsdev->proc_self_fd, fobject->fd_str, flags, saverr); 777*e21c39aaSAnton Nayshtut return saverr; 778*e21c39aaSAnton Nayshtut } 779*e21c39aaSAnton Nayshtut 780*e21c39aaSAnton Nayshtut fhandle = file_handle_create(fobject, fd); 781*e21c39aaSAnton Nayshtut if (!fhandle) { 782*e21c39aaSAnton Nayshtut SPDK_ERRLOG("cannot create a file handle (fd=%d)\n", fd); 783*e21c39aaSAnton Nayshtut close(fd); 784*e21c39aaSAnton Nayshtut return -ENOMEM; 785*e21c39aaSAnton Nayshtut } 786*e21c39aaSAnton Nayshtut 787*e21c39aaSAnton Nayshtut fsdev_io->u_out.open.fhandle = fhandle; 788*e21c39aaSAnton Nayshtut 789*e21c39aaSAnton Nayshtut SPDK_DEBUGLOG(fsdev_aio, "OPEN succeeded for " FOBJECT_FMT " (fh=%p, fd=%d)\n", 790*e21c39aaSAnton Nayshtut FOBJECT_ARGS(fobject), fhandle, fd); 791*e21c39aaSAnton Nayshtut 792*e21c39aaSAnton Nayshtut return 0; 793*e21c39aaSAnton Nayshtut } 794*e21c39aaSAnton Nayshtut 795*e21c39aaSAnton Nayshtut static int 796*e21c39aaSAnton Nayshtut lo_flush(struct spdk_io_channel *ch, struct spdk_fsdev_io *fsdev_io) 797*e21c39aaSAnton Nayshtut { 798*e21c39aaSAnton Nayshtut struct aio_fsdev *vfsdev = fsdev_to_aio_fsdev(fsdev_io->fsdev); 799*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *fobject = fsdev_io->u_in.flush.fobject; 800*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_handle *fhandle = fsdev_io->u_in.flush.fhandle; 801*e21c39aaSAnton Nayshtut int res, saverr; 802*e21c39aaSAnton Nayshtut 803*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fobject(vfsdev, fobject)) { 804*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid fobject: %p\n", fobject); 805*e21c39aaSAnton Nayshtut return -EINVAL; 806*e21c39aaSAnton Nayshtut } 807*e21c39aaSAnton Nayshtut 808*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fhandle(vfsdev, fhandle)) { 809*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid fhandle: %p\n", fhandle); 810*e21c39aaSAnton Nayshtut return -EINVAL; 811*e21c39aaSAnton Nayshtut } 812*e21c39aaSAnton Nayshtut 813*e21c39aaSAnton Nayshtut res = close(dup(fhandle->fd)); 814*e21c39aaSAnton Nayshtut if (res) { 815*e21c39aaSAnton Nayshtut saverr = -errno; 816*e21c39aaSAnton Nayshtut SPDK_ERRLOG("close(dup(%d)) failed for " FOBJECT_FMT " (fh=%p, err=%d)\n", 817*e21c39aaSAnton Nayshtut fhandle->fd, FOBJECT_ARGS(fobject), fhandle, saverr); 818*e21c39aaSAnton Nayshtut return saverr; 819*e21c39aaSAnton Nayshtut } 820*e21c39aaSAnton Nayshtut 821*e21c39aaSAnton Nayshtut SPDK_DEBUGLOG(fsdev_aio, "FLUSH succeeded for " FOBJECT_FMT " (fh=%p)\n", FOBJECT_ARGS(fobject), 822*e21c39aaSAnton Nayshtut fhandle); 823*e21c39aaSAnton Nayshtut 824*e21c39aaSAnton Nayshtut return 0; 825*e21c39aaSAnton Nayshtut } 826*e21c39aaSAnton Nayshtut 827*e21c39aaSAnton Nayshtut static int 828*e21c39aaSAnton Nayshtut lo_setattr(struct spdk_io_channel *ch, struct spdk_fsdev_io *fsdev_io) 829*e21c39aaSAnton Nayshtut { 830*e21c39aaSAnton Nayshtut struct aio_fsdev *vfsdev = fsdev_to_aio_fsdev(fsdev_io->fsdev); 831*e21c39aaSAnton Nayshtut int saverr; 832*e21c39aaSAnton Nayshtut int res; 833*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *fobject = fsdev_io->u_in.setattr.fobject; 834*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_handle *fhandle = fsdev_io->u_in.setattr.fhandle; 835*e21c39aaSAnton Nayshtut uint32_t to_set = fsdev_io->u_in.setattr.to_set; 836*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_attr *attr = &fsdev_io->u_in.setattr.attr; 837*e21c39aaSAnton Nayshtut 838*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fobject(vfsdev, fobject)) { 839*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid fobject: %p\n", fobject); 840*e21c39aaSAnton Nayshtut return -EINVAL; 841*e21c39aaSAnton Nayshtut } 842*e21c39aaSAnton Nayshtut 843*e21c39aaSAnton Nayshtut if (to_set & FSDEV_SET_ATTR_MODE) { 844*e21c39aaSAnton Nayshtut if (fhandle) { 845*e21c39aaSAnton Nayshtut res = fchmod(fhandle->fd, attr->mode); 846*e21c39aaSAnton Nayshtut } else { 847*e21c39aaSAnton Nayshtut res = fchmodat(vfsdev->proc_self_fd, fobject->fd_str, attr->mode, 0); 848*e21c39aaSAnton Nayshtut } 849*e21c39aaSAnton Nayshtut if (res == -1) { 850*e21c39aaSAnton Nayshtut saverr = -errno; 851*e21c39aaSAnton Nayshtut SPDK_ERRLOG("fchmod failed for " FOBJECT_FMT "\n", FOBJECT_ARGS(fobject)); 852*e21c39aaSAnton Nayshtut return saverr; 853*e21c39aaSAnton Nayshtut } 854*e21c39aaSAnton Nayshtut } 855*e21c39aaSAnton Nayshtut 856*e21c39aaSAnton Nayshtut if (to_set & (FSDEV_SET_ATTR_UID | FSDEV_SET_ATTR_GID)) { 857*e21c39aaSAnton Nayshtut uid_t uid = (to_set & FSDEV_SET_ATTR_UID) ? attr->uid : (uid_t) -1; 858*e21c39aaSAnton Nayshtut gid_t gid = (to_set & FSDEV_SET_ATTR_GID) ? attr->gid : (gid_t) -1; 859*e21c39aaSAnton Nayshtut 860*e21c39aaSAnton Nayshtut res = fchownat(fobject->fd, "", uid, gid, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW); 861*e21c39aaSAnton Nayshtut if (res == -1) { 862*e21c39aaSAnton Nayshtut saverr = -errno; 863*e21c39aaSAnton Nayshtut SPDK_ERRLOG("fchownat failed for " FOBJECT_FMT "\n", FOBJECT_ARGS(fobject)); 864*e21c39aaSAnton Nayshtut return saverr; 865*e21c39aaSAnton Nayshtut } 866*e21c39aaSAnton Nayshtut } 867*e21c39aaSAnton Nayshtut 868*e21c39aaSAnton Nayshtut if (to_set & FSDEV_SET_ATTR_SIZE) { 869*e21c39aaSAnton Nayshtut int truncfd; 870*e21c39aaSAnton Nayshtut 871*e21c39aaSAnton Nayshtut if (fhandle) { 872*e21c39aaSAnton Nayshtut truncfd = fhandle->fd; 873*e21c39aaSAnton Nayshtut } else { 874*e21c39aaSAnton Nayshtut truncfd = openat(vfsdev->proc_self_fd, fobject->fd_str, O_RDWR); 875*e21c39aaSAnton Nayshtut if (truncfd < 0) { 876*e21c39aaSAnton Nayshtut saverr = -errno; 877*e21c39aaSAnton Nayshtut SPDK_ERRLOG("openat failed for " FOBJECT_FMT "\n", FOBJECT_ARGS(fobject)); 878*e21c39aaSAnton Nayshtut return saverr; 879*e21c39aaSAnton Nayshtut } 880*e21c39aaSAnton Nayshtut } 881*e21c39aaSAnton Nayshtut 882*e21c39aaSAnton Nayshtut res = ftruncate(truncfd, attr->size); 883*e21c39aaSAnton Nayshtut if (!fhandle) { 884*e21c39aaSAnton Nayshtut saverr = -errno; 885*e21c39aaSAnton Nayshtut close(truncfd); 886*e21c39aaSAnton Nayshtut errno = saverr; 887*e21c39aaSAnton Nayshtut } 888*e21c39aaSAnton Nayshtut if (res == -1) { 889*e21c39aaSAnton Nayshtut saverr = -errno; 890*e21c39aaSAnton Nayshtut SPDK_ERRLOG("ftruncate failed for " FOBJECT_FMT " (size=%" PRIu64 ")\n", FOBJECT_ARGS(fobject), 891*e21c39aaSAnton Nayshtut attr->size); 892*e21c39aaSAnton Nayshtut return saverr; 893*e21c39aaSAnton Nayshtut } 894*e21c39aaSAnton Nayshtut } 895*e21c39aaSAnton Nayshtut 896*e21c39aaSAnton Nayshtut if (to_set & (FSDEV_SET_ATTR_ATIME | FSDEV_SET_ATTR_MTIME)) { 897*e21c39aaSAnton Nayshtut struct timespec tv[2]; 898*e21c39aaSAnton Nayshtut 899*e21c39aaSAnton Nayshtut tv[0].tv_sec = 0; 900*e21c39aaSAnton Nayshtut tv[1].tv_sec = 0; 901*e21c39aaSAnton Nayshtut tv[0].tv_nsec = UTIME_OMIT; 902*e21c39aaSAnton Nayshtut tv[1].tv_nsec = UTIME_OMIT; 903*e21c39aaSAnton Nayshtut 904*e21c39aaSAnton Nayshtut if (to_set & FSDEV_SET_ATTR_ATIME_NOW) { 905*e21c39aaSAnton Nayshtut tv[0].tv_nsec = UTIME_NOW; 906*e21c39aaSAnton Nayshtut } else if (to_set & FSDEV_SET_ATTR_ATIME) { 907*e21c39aaSAnton Nayshtut tv[0].tv_sec = attr->atime; 908*e21c39aaSAnton Nayshtut tv[0].tv_nsec = attr->atimensec; 909*e21c39aaSAnton Nayshtut } 910*e21c39aaSAnton Nayshtut 911*e21c39aaSAnton Nayshtut if (to_set & FSDEV_SET_ATTR_MTIME_NOW) { 912*e21c39aaSAnton Nayshtut tv[1].tv_nsec = UTIME_NOW; 913*e21c39aaSAnton Nayshtut } else if (to_set & FSDEV_SET_ATTR_MTIME) { 914*e21c39aaSAnton Nayshtut tv[1].tv_sec = attr->mtime; 915*e21c39aaSAnton Nayshtut tv[1].tv_nsec = attr->mtimensec; 916*e21c39aaSAnton Nayshtut } 917*e21c39aaSAnton Nayshtut 918*e21c39aaSAnton Nayshtut if (fhandle) { 919*e21c39aaSAnton Nayshtut res = futimens(fhandle->fd, tv); 920*e21c39aaSAnton Nayshtut } else { 921*e21c39aaSAnton Nayshtut res = utimensat_empty(vfsdev, fobject, tv); 922*e21c39aaSAnton Nayshtut } 923*e21c39aaSAnton Nayshtut if (res == -1) { 924*e21c39aaSAnton Nayshtut saverr = -errno; 925*e21c39aaSAnton Nayshtut SPDK_ERRLOG("futimens/utimensat_empty failed for " FOBJECT_FMT "\n", 926*e21c39aaSAnton Nayshtut FOBJECT_ARGS(fobject)); 927*e21c39aaSAnton Nayshtut return saverr; 928*e21c39aaSAnton Nayshtut } 929*e21c39aaSAnton Nayshtut } 930*e21c39aaSAnton Nayshtut 931*e21c39aaSAnton Nayshtut res = file_object_fill_attr(fobject, &fsdev_io->u_out.setattr.attr); 932*e21c39aaSAnton Nayshtut if (res) { 933*e21c39aaSAnton Nayshtut SPDK_ERRLOG("file_object_fill_attr failed for " FOBJECT_FMT "\n", 934*e21c39aaSAnton Nayshtut FOBJECT_ARGS(fobject)); 935*e21c39aaSAnton Nayshtut return res; 936*e21c39aaSAnton Nayshtut } 937*e21c39aaSAnton Nayshtut 938*e21c39aaSAnton Nayshtut SPDK_DEBUGLOG(fsdev_aio, "SETATTR succeeded for " FOBJECT_FMT "\n", 939*e21c39aaSAnton Nayshtut FOBJECT_ARGS(fobject)); 940*e21c39aaSAnton Nayshtut 941*e21c39aaSAnton Nayshtut return 0; 942*e21c39aaSAnton Nayshtut } 943*e21c39aaSAnton Nayshtut 944*e21c39aaSAnton Nayshtut static int 945*e21c39aaSAnton Nayshtut lo_create(struct spdk_io_channel *ch, struct spdk_fsdev_io *fsdev_io) 946*e21c39aaSAnton Nayshtut { 947*e21c39aaSAnton Nayshtut struct aio_fsdev *vfsdev = fsdev_to_aio_fsdev(fsdev_io->fsdev); 948*e21c39aaSAnton Nayshtut int fd; 949*e21c39aaSAnton Nayshtut int err; 950*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *parent_fobject = fsdev_io->u_in.create.parent_fobject; 951*e21c39aaSAnton Nayshtut const char *name = fsdev_io->u_in.create.name; 952*e21c39aaSAnton Nayshtut uint32_t mode = fsdev_io->u_in.create.mode; 953*e21c39aaSAnton Nayshtut uint32_t flags = fsdev_io->u_in.create.flags; 954*e21c39aaSAnton Nayshtut uint32_t umask = fsdev_io->u_in.create.umask; 955*e21c39aaSAnton Nayshtut struct lo_cred old_cred, new_cred = { 956*e21c39aaSAnton Nayshtut .euid = fsdev_io->u_in.create.euid, 957*e21c39aaSAnton Nayshtut .egid = fsdev_io->u_in.create.egid, 958*e21c39aaSAnton Nayshtut }; 959*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *fobject; 960*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_handle *fhandle; 961*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_attr *attr = &fsdev_io->u_out.create.attr; 962*e21c39aaSAnton Nayshtut 963*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fobject(vfsdev, parent_fobject)) { 964*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid parent_fobject: %p\n", parent_fobject); 965*e21c39aaSAnton Nayshtut return -EINVAL; 966*e21c39aaSAnton Nayshtut } 967*e21c39aaSAnton Nayshtut 968*e21c39aaSAnton Nayshtut UNUSED(umask); 969*e21c39aaSAnton Nayshtut 970*e21c39aaSAnton Nayshtut if (!is_safe_path_component(name)) { 971*e21c39aaSAnton Nayshtut SPDK_ERRLOG("CREATE: %s not a safe component\n", name); 972*e21c39aaSAnton Nayshtut return -EINVAL; 973*e21c39aaSAnton Nayshtut } 974*e21c39aaSAnton Nayshtut 975*e21c39aaSAnton Nayshtut err = lo_change_cred(&new_cred, &old_cred); 976*e21c39aaSAnton Nayshtut if (err) { 977*e21c39aaSAnton Nayshtut SPDK_ERRLOG("CREATE: cannot change credentials\n"); 978*e21c39aaSAnton Nayshtut return err; 979*e21c39aaSAnton Nayshtut } 980*e21c39aaSAnton Nayshtut 981*e21c39aaSAnton Nayshtut flags = update_open_flags(vfsdev, flags); 982*e21c39aaSAnton Nayshtut 983*e21c39aaSAnton Nayshtut fd = openat(parent_fobject->fd, name, (flags | O_CREAT) & ~O_NOFOLLOW, mode); 984*e21c39aaSAnton Nayshtut err = fd == -1 ? -errno : 0; 985*e21c39aaSAnton Nayshtut lo_restore_cred(&old_cred); 986*e21c39aaSAnton Nayshtut 987*e21c39aaSAnton Nayshtut if (err) { 988*e21c39aaSAnton Nayshtut SPDK_ERRLOG("CREATE: openat failed with %d\n", err); 989*e21c39aaSAnton Nayshtut return err; 990*e21c39aaSAnton Nayshtut } 991*e21c39aaSAnton Nayshtut 992*e21c39aaSAnton Nayshtut err = lo_do_lookup(vfsdev, parent_fobject, name, &fobject, attr); 993*e21c39aaSAnton Nayshtut if (err) { 994*e21c39aaSAnton Nayshtut SPDK_ERRLOG("CREATE: lookup failed with %d\n", err); 995*e21c39aaSAnton Nayshtut return err; 996*e21c39aaSAnton Nayshtut } 997*e21c39aaSAnton Nayshtut 998*e21c39aaSAnton Nayshtut fhandle = file_handle_create(fobject, fd); 999*e21c39aaSAnton Nayshtut if (!fhandle) { 1000*e21c39aaSAnton Nayshtut SPDK_ERRLOG("cannot create a file handle (fd=%d)\n", fd); 1001*e21c39aaSAnton Nayshtut close(fd); 1002*e21c39aaSAnton Nayshtut file_object_unref(fobject, 1); 1003*e21c39aaSAnton Nayshtut return -ENOMEM; 1004*e21c39aaSAnton Nayshtut } 1005*e21c39aaSAnton Nayshtut 1006*e21c39aaSAnton Nayshtut SPDK_DEBUGLOG(fsdev_aio, "CREATE: succeeded (name=%s " FOBJECT_FMT " fh=%p)\n", 1007*e21c39aaSAnton Nayshtut name, FOBJECT_ARGS(fobject), fhandle); 1008*e21c39aaSAnton Nayshtut 1009*e21c39aaSAnton Nayshtut fsdev_io->u_out.create.fobject = fobject; 1010*e21c39aaSAnton Nayshtut fsdev_io->u_out.create.fhandle = fhandle; 1011*e21c39aaSAnton Nayshtut 1012*e21c39aaSAnton Nayshtut return 0; 1013*e21c39aaSAnton Nayshtut } 1014*e21c39aaSAnton Nayshtut 1015*e21c39aaSAnton Nayshtut static int 1016*e21c39aaSAnton Nayshtut lo_release(struct spdk_io_channel *ch, struct spdk_fsdev_io *fsdev_io) 1017*e21c39aaSAnton Nayshtut { 1018*e21c39aaSAnton Nayshtut struct aio_fsdev *vfsdev = fsdev_to_aio_fsdev(fsdev_io->fsdev); 1019*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *fobject = fsdev_io->u_in.release.fobject; 1020*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_handle *fhandle = fsdev_io->u_in.release.fhandle; 1021*e21c39aaSAnton Nayshtut 1022*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fobject(vfsdev, fobject)) { 1023*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid fobject: %p\n", fobject); 1024*e21c39aaSAnton Nayshtut return -EINVAL; 1025*e21c39aaSAnton Nayshtut } 1026*e21c39aaSAnton Nayshtut 1027*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fhandle(vfsdev, fhandle)) { 1028*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid fhandle: %p\n", fhandle); 1029*e21c39aaSAnton Nayshtut return -EINVAL; 1030*e21c39aaSAnton Nayshtut } 1031*e21c39aaSAnton Nayshtut 1032*e21c39aaSAnton Nayshtut file_handle_delete(fhandle); 1033*e21c39aaSAnton Nayshtut 1034*e21c39aaSAnton Nayshtut SPDK_DEBUGLOG(fsdev_aio, "RELEASE succeeded for " FOBJECT_FMT " fh=%p)\n", 1035*e21c39aaSAnton Nayshtut FOBJECT_ARGS(fobject), fhandle); 1036*e21c39aaSAnton Nayshtut return 0; 1037*e21c39aaSAnton Nayshtut } 1038*e21c39aaSAnton Nayshtut 1039*e21c39aaSAnton Nayshtut static void 1040*e21c39aaSAnton Nayshtut lo_read_cb(void *ctx, uint32_t data_size, int error) 1041*e21c39aaSAnton Nayshtut { 1042*e21c39aaSAnton Nayshtut struct spdk_fsdev_io *fsdev_io = ctx; 1043*e21c39aaSAnton Nayshtut struct aio_fsdev_io *vfsdev_io = fsdev_to_aio_io(fsdev_io); 1044*e21c39aaSAnton Nayshtut 1045*e21c39aaSAnton Nayshtut if (vfsdev_io->aio) { 1046*e21c39aaSAnton Nayshtut TAILQ_REMOVE(&vfsdev_io->ch->ios_in_progress, vfsdev_io, link); 1047*e21c39aaSAnton Nayshtut } 1048*e21c39aaSAnton Nayshtut 1049*e21c39aaSAnton Nayshtut fsdev_io->u_out.read.data_size = data_size; 1050*e21c39aaSAnton Nayshtut 1051*e21c39aaSAnton Nayshtut spdk_fsdev_io_complete(fsdev_io, error); 1052*e21c39aaSAnton Nayshtut } 1053*e21c39aaSAnton Nayshtut 1054*e21c39aaSAnton Nayshtut static int 1055*e21c39aaSAnton Nayshtut lo_read(struct spdk_io_channel *_ch, struct spdk_fsdev_io *fsdev_io) 1056*e21c39aaSAnton Nayshtut { 1057*e21c39aaSAnton Nayshtut struct aio_fsdev *vfsdev = fsdev_to_aio_fsdev(fsdev_io->fsdev); 1058*e21c39aaSAnton Nayshtut struct aio_io_channel *ch = spdk_io_channel_get_ctx(_ch); 1059*e21c39aaSAnton Nayshtut struct aio_fsdev_io *vfsdev_io = fsdev_to_aio_io(fsdev_io); 1060*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *fobject = fsdev_io->u_in.read.fobject; 1061*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_handle *fhandle = fsdev_io->u_in.read.fhandle; 1062*e21c39aaSAnton Nayshtut size_t size = fsdev_io->u_in.read.size; 1063*e21c39aaSAnton Nayshtut uint64_t offs = fsdev_io->u_in.read.offs; 1064*e21c39aaSAnton Nayshtut uint32_t flags = fsdev_io->u_in.read.flags; 1065*e21c39aaSAnton Nayshtut struct iovec *outvec = fsdev_io->u_in.read.iov; 1066*e21c39aaSAnton Nayshtut uint32_t outcnt = fsdev_io->u_in.read.iovcnt; 1067*e21c39aaSAnton Nayshtut 1068*e21c39aaSAnton Nayshtut /* we don't suport the memory domains at the moment */ 1069*e21c39aaSAnton Nayshtut assert(!fsdev_io->u_in.read.opts || !fsdev_io->u_in.read.opts->memory_domain); 1070*e21c39aaSAnton Nayshtut 1071*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fobject(vfsdev, fobject)) { 1072*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid fobject: %p\n", fobject); 1073*e21c39aaSAnton Nayshtut return -EINVAL; 1074*e21c39aaSAnton Nayshtut } 1075*e21c39aaSAnton Nayshtut 1076*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fhandle(vfsdev, fhandle)) { 1077*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid fhandle: %p\n", fhandle); 1078*e21c39aaSAnton Nayshtut return -EINVAL; 1079*e21c39aaSAnton Nayshtut } 1080*e21c39aaSAnton Nayshtut 1081*e21c39aaSAnton Nayshtut UNUSED(flags); 1082*e21c39aaSAnton Nayshtut 1083*e21c39aaSAnton Nayshtut if (!outcnt || !outvec) { 1084*e21c39aaSAnton Nayshtut SPDK_ERRLOG("bad outvec: iov=%p outcnt=%" PRIu32 "\n", outvec, outcnt); 1085*e21c39aaSAnton Nayshtut return -EINVAL; 1086*e21c39aaSAnton Nayshtut } 1087*e21c39aaSAnton Nayshtut 1088*e21c39aaSAnton Nayshtut vfsdev_io->aio = spdk_aio_mgr_read(ch->mgr, lo_read_cb, fsdev_io, fhandle->fd, offs, size, outvec, 1089*e21c39aaSAnton Nayshtut outcnt); 1090*e21c39aaSAnton Nayshtut if (vfsdev_io->aio) { 1091*e21c39aaSAnton Nayshtut vfsdev_io->ch = ch; 1092*e21c39aaSAnton Nayshtut TAILQ_INSERT_TAIL(&ch->ios_in_progress, vfsdev_io, link); 1093*e21c39aaSAnton Nayshtut } 1094*e21c39aaSAnton Nayshtut 1095*e21c39aaSAnton Nayshtut return IO_STATUS_ASYNC; 1096*e21c39aaSAnton Nayshtut } 1097*e21c39aaSAnton Nayshtut 1098*e21c39aaSAnton Nayshtut static void 1099*e21c39aaSAnton Nayshtut lo_write_cb(void *ctx, uint32_t data_size, int error) 1100*e21c39aaSAnton Nayshtut { 1101*e21c39aaSAnton Nayshtut struct spdk_fsdev_io *fsdev_io = ctx; 1102*e21c39aaSAnton Nayshtut struct aio_fsdev_io *vfsdev_io = fsdev_to_aio_io(fsdev_io); 1103*e21c39aaSAnton Nayshtut 1104*e21c39aaSAnton Nayshtut if (vfsdev_io->aio) { 1105*e21c39aaSAnton Nayshtut TAILQ_REMOVE(&vfsdev_io->ch->ios_in_progress, vfsdev_io, link); 1106*e21c39aaSAnton Nayshtut } 1107*e21c39aaSAnton Nayshtut 1108*e21c39aaSAnton Nayshtut fsdev_io->u_out.write.data_size = data_size; 1109*e21c39aaSAnton Nayshtut 1110*e21c39aaSAnton Nayshtut spdk_fsdev_io_complete(fsdev_io, error); 1111*e21c39aaSAnton Nayshtut } 1112*e21c39aaSAnton Nayshtut 1113*e21c39aaSAnton Nayshtut static int 1114*e21c39aaSAnton Nayshtut lo_write(struct spdk_io_channel *_ch, struct spdk_fsdev_io *fsdev_io) 1115*e21c39aaSAnton Nayshtut { 1116*e21c39aaSAnton Nayshtut struct aio_fsdev *vfsdev = fsdev_to_aio_fsdev(fsdev_io->fsdev); 1117*e21c39aaSAnton Nayshtut struct aio_io_channel *ch = spdk_io_channel_get_ctx(_ch); 1118*e21c39aaSAnton Nayshtut struct aio_fsdev_io *vfsdev_io = fsdev_to_aio_io(fsdev_io); 1119*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *fobject = fsdev_io->u_in.write.fobject; 1120*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_handle *fhandle = fsdev_io->u_in.write.fhandle; 1121*e21c39aaSAnton Nayshtut size_t size = fsdev_io->u_in.write.size; 1122*e21c39aaSAnton Nayshtut uint64_t offs = fsdev_io->u_in.write.offs; 1123*e21c39aaSAnton Nayshtut uint32_t flags = fsdev_io->u_in.write.flags; 1124*e21c39aaSAnton Nayshtut const struct iovec *invec = fsdev_io->u_in.write.iov; 1125*e21c39aaSAnton Nayshtut uint32_t incnt = fsdev_io->u_in.write.iovcnt; 1126*e21c39aaSAnton Nayshtut 1127*e21c39aaSAnton Nayshtut /* we don't suport the memory domains at the moment */ 1128*e21c39aaSAnton Nayshtut assert(!fsdev_io->u_in.write.opts || !fsdev_io->u_in.write.opts->memory_domain); 1129*e21c39aaSAnton Nayshtut 1130*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fobject(vfsdev, fobject)) { 1131*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid fobject: %p\n", fobject); 1132*e21c39aaSAnton Nayshtut return -EINVAL; 1133*e21c39aaSAnton Nayshtut } 1134*e21c39aaSAnton Nayshtut 1135*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fhandle(vfsdev, fhandle)) { 1136*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid fhandle: %p\n", fhandle); 1137*e21c39aaSAnton Nayshtut return -EINVAL; 1138*e21c39aaSAnton Nayshtut } 1139*e21c39aaSAnton Nayshtut 1140*e21c39aaSAnton Nayshtut UNUSED(flags); 1141*e21c39aaSAnton Nayshtut 1142*e21c39aaSAnton Nayshtut if (!incnt || !invec) { /* there should be at least one iovec with data */ 1143*e21c39aaSAnton Nayshtut SPDK_ERRLOG("bad invec: iov=%p cnt=%" PRIu32 "\n", invec, incnt); 1144*e21c39aaSAnton Nayshtut return -EINVAL; 1145*e21c39aaSAnton Nayshtut } 1146*e21c39aaSAnton Nayshtut 1147*e21c39aaSAnton Nayshtut vfsdev_io->aio = spdk_aio_mgr_write(ch->mgr, lo_write_cb, fsdev_io, 1148*e21c39aaSAnton Nayshtut fhandle->fd, offs, size, invec, incnt); 1149*e21c39aaSAnton Nayshtut if (vfsdev_io->aio) { 1150*e21c39aaSAnton Nayshtut vfsdev_io->ch = ch; 1151*e21c39aaSAnton Nayshtut TAILQ_INSERT_TAIL(&ch->ios_in_progress, vfsdev_io, link); 1152*e21c39aaSAnton Nayshtut } 1153*e21c39aaSAnton Nayshtut 1154*e21c39aaSAnton Nayshtut return IO_STATUS_ASYNC; 1155*e21c39aaSAnton Nayshtut } 1156*e21c39aaSAnton Nayshtut 1157*e21c39aaSAnton Nayshtut static int 1158*e21c39aaSAnton Nayshtut lo_readlink(struct spdk_io_channel *ch, struct spdk_fsdev_io *fsdev_io) 1159*e21c39aaSAnton Nayshtut { 1160*e21c39aaSAnton Nayshtut struct aio_fsdev *vfsdev = fsdev_to_aio_fsdev(fsdev_io->fsdev); 1161*e21c39aaSAnton Nayshtut int res; 1162*e21c39aaSAnton Nayshtut char *buf; 1163*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *fobject = fsdev_io->u_in.readlink.fobject; 1164*e21c39aaSAnton Nayshtut 1165*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fobject(vfsdev, fobject)) { 1166*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid fobject: %p\n", fobject); 1167*e21c39aaSAnton Nayshtut return -EINVAL; 1168*e21c39aaSAnton Nayshtut } 1169*e21c39aaSAnton Nayshtut 1170*e21c39aaSAnton Nayshtut buf = malloc(PATH_MAX + 1); 1171*e21c39aaSAnton Nayshtut if (!buf) { 1172*e21c39aaSAnton Nayshtut SPDK_ERRLOG("malloc(%zu) failed\n", (size_t)(PATH_MAX + 1)); 1173*e21c39aaSAnton Nayshtut return -ENOMEM; 1174*e21c39aaSAnton Nayshtut } 1175*e21c39aaSAnton Nayshtut 1176*e21c39aaSAnton Nayshtut res = readlinkat(fobject->fd, "", buf, PATH_MAX + 1); 1177*e21c39aaSAnton Nayshtut if (res == -1) { 1178*e21c39aaSAnton Nayshtut int saverr = -errno; 1179*e21c39aaSAnton Nayshtut SPDK_ERRLOG("readlinkat failed for " FOBJECT_FMT " with %d\n", 1180*e21c39aaSAnton Nayshtut FOBJECT_ARGS(fobject), saverr); 1181*e21c39aaSAnton Nayshtut free(buf); 1182*e21c39aaSAnton Nayshtut return saverr; 1183*e21c39aaSAnton Nayshtut } 1184*e21c39aaSAnton Nayshtut 1185*e21c39aaSAnton Nayshtut if (((uint32_t)res) == PATH_MAX + 1) { 1186*e21c39aaSAnton Nayshtut SPDK_ERRLOG("buffer is too short\n"); 1187*e21c39aaSAnton Nayshtut free(buf); 1188*e21c39aaSAnton Nayshtut return -ENAMETOOLONG; 1189*e21c39aaSAnton Nayshtut } 1190*e21c39aaSAnton Nayshtut 1191*e21c39aaSAnton Nayshtut buf[res] = 0; 1192*e21c39aaSAnton Nayshtut fsdev_io->u_out.readlink.linkname = buf; 1193*e21c39aaSAnton Nayshtut 1194*e21c39aaSAnton Nayshtut return 0; 1195*e21c39aaSAnton Nayshtut } 1196*e21c39aaSAnton Nayshtut 1197*e21c39aaSAnton Nayshtut static int 1198*e21c39aaSAnton Nayshtut lo_statfs(struct spdk_io_channel *ch, struct spdk_fsdev_io *fsdev_io) 1199*e21c39aaSAnton Nayshtut { 1200*e21c39aaSAnton Nayshtut struct aio_fsdev *vfsdev = fsdev_to_aio_fsdev(fsdev_io->fsdev); 1201*e21c39aaSAnton Nayshtut int res; 1202*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *fobject = fsdev_io->u_in.statfs.fobject; 1203*e21c39aaSAnton Nayshtut struct statvfs stbuf; 1204*e21c39aaSAnton Nayshtut 1205*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fobject(vfsdev, fobject)) { 1206*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid fobject: %p\n", fobject); 1207*e21c39aaSAnton Nayshtut return -EINVAL; 1208*e21c39aaSAnton Nayshtut } 1209*e21c39aaSAnton Nayshtut 1210*e21c39aaSAnton Nayshtut res = fstatvfs(fobject->fd, &stbuf); 1211*e21c39aaSAnton Nayshtut if (res == -1) { 1212*e21c39aaSAnton Nayshtut int saverr = -errno; 1213*e21c39aaSAnton Nayshtut SPDK_ERRLOG("fstatvfs failed with %d\n", saverr); 1214*e21c39aaSAnton Nayshtut return saverr; 1215*e21c39aaSAnton Nayshtut } 1216*e21c39aaSAnton Nayshtut 1217*e21c39aaSAnton Nayshtut fsdev_io->u_out.statfs.statfs.blocks = stbuf.f_blocks; 1218*e21c39aaSAnton Nayshtut fsdev_io->u_out.statfs.statfs.bfree = stbuf.f_bfree; 1219*e21c39aaSAnton Nayshtut fsdev_io->u_out.statfs.statfs.bavail = stbuf.f_bavail; 1220*e21c39aaSAnton Nayshtut fsdev_io->u_out.statfs.statfs.files = stbuf.f_files; 1221*e21c39aaSAnton Nayshtut fsdev_io->u_out.statfs.statfs.ffree = stbuf.f_ffree; 1222*e21c39aaSAnton Nayshtut fsdev_io->u_out.statfs.statfs.bsize = stbuf.f_bsize; 1223*e21c39aaSAnton Nayshtut fsdev_io->u_out.statfs.statfs.namelen = stbuf.f_namemax; 1224*e21c39aaSAnton Nayshtut fsdev_io->u_out.statfs.statfs.frsize = stbuf.f_frsize; 1225*e21c39aaSAnton Nayshtut 1226*e21c39aaSAnton Nayshtut return 0; 1227*e21c39aaSAnton Nayshtut } 1228*e21c39aaSAnton Nayshtut 1229*e21c39aaSAnton Nayshtut static int 1230*e21c39aaSAnton Nayshtut lo_mknod_symlink(struct spdk_fsdev_io *fsdev_io, struct spdk_fsdev_file_object *parent_fobject, 1231*e21c39aaSAnton Nayshtut const char *name, mode_t mode, dev_t rdev, const char *link, uid_t euid, gid_t egid, 1232*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object **pfobject, struct spdk_fsdev_file_attr *attr) 1233*e21c39aaSAnton Nayshtut { 1234*e21c39aaSAnton Nayshtut struct aio_fsdev *vfsdev = fsdev_to_aio_fsdev(fsdev_io->fsdev); 1235*e21c39aaSAnton Nayshtut int res; 1236*e21c39aaSAnton Nayshtut int saverr; 1237*e21c39aaSAnton Nayshtut struct lo_cred old_cred, new_cred = { 1238*e21c39aaSAnton Nayshtut .euid = euid, 1239*e21c39aaSAnton Nayshtut .egid = egid, 1240*e21c39aaSAnton Nayshtut }; 1241*e21c39aaSAnton Nayshtut 1242*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fobject(vfsdev, parent_fobject)) { 1243*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid parent_fobject: %p\n", parent_fobject); 1244*e21c39aaSAnton Nayshtut return -EINVAL; 1245*e21c39aaSAnton Nayshtut } 1246*e21c39aaSAnton Nayshtut 1247*e21c39aaSAnton Nayshtut if (!is_safe_path_component(name)) { 1248*e21c39aaSAnton Nayshtut SPDK_ERRLOG("%s isn'h safe\n", name); 1249*e21c39aaSAnton Nayshtut return -EINVAL; 1250*e21c39aaSAnton Nayshtut } 1251*e21c39aaSAnton Nayshtut 1252*e21c39aaSAnton Nayshtut res = lo_change_cred(&new_cred, &old_cred); 1253*e21c39aaSAnton Nayshtut if (res) { 1254*e21c39aaSAnton Nayshtut SPDK_ERRLOG("cannot change cred (err=%d)\n", res); 1255*e21c39aaSAnton Nayshtut return res; 1256*e21c39aaSAnton Nayshtut } 1257*e21c39aaSAnton Nayshtut 1258*e21c39aaSAnton Nayshtut if (S_ISDIR(mode)) { 1259*e21c39aaSAnton Nayshtut res = mkdirat(parent_fobject->fd, name, mode); 1260*e21c39aaSAnton Nayshtut } else if (S_ISLNK(mode)) { 1261*e21c39aaSAnton Nayshtut if (link) { 1262*e21c39aaSAnton Nayshtut res = symlinkat(link, parent_fobject->fd, name); 1263*e21c39aaSAnton Nayshtut } else { 1264*e21c39aaSAnton Nayshtut SPDK_ERRLOG("NULL link pointer\n"); 1265*e21c39aaSAnton Nayshtut errno = EINVAL; 1266*e21c39aaSAnton Nayshtut } 1267*e21c39aaSAnton Nayshtut } else { 1268*e21c39aaSAnton Nayshtut res = mknodat(parent_fobject->fd, name, mode, rdev); 1269*e21c39aaSAnton Nayshtut } 1270*e21c39aaSAnton Nayshtut saverr = -errno; 1271*e21c39aaSAnton Nayshtut 1272*e21c39aaSAnton Nayshtut lo_restore_cred(&old_cred); 1273*e21c39aaSAnton Nayshtut 1274*e21c39aaSAnton Nayshtut if (res == -1) { 1275*e21c39aaSAnton Nayshtut SPDK_ERRLOG("cannot mkdirat/symlinkat/mknodat (err=%d)\n", saverr); 1276*e21c39aaSAnton Nayshtut return saverr; 1277*e21c39aaSAnton Nayshtut } 1278*e21c39aaSAnton Nayshtut 1279*e21c39aaSAnton Nayshtut res = lo_do_lookup(vfsdev, parent_fobject, name, pfobject, attr); 1280*e21c39aaSAnton Nayshtut if (res) { 1281*e21c39aaSAnton Nayshtut SPDK_ERRLOG("lookup failed (err=%d)\n", res); 1282*e21c39aaSAnton Nayshtut return res; 1283*e21c39aaSAnton Nayshtut } 1284*e21c39aaSAnton Nayshtut 1285*e21c39aaSAnton Nayshtut SPDK_DEBUGLOG(fsdev_aio, "lo_mknod_symlink(" FOBJECT_FMT "/%s -> " FOBJECT_FMT "\n", 1286*e21c39aaSAnton Nayshtut FOBJECT_ARGS(parent_fobject), name, FOBJECT_ARGS(*pfobject)); 1287*e21c39aaSAnton Nayshtut 1288*e21c39aaSAnton Nayshtut return 0; 1289*e21c39aaSAnton Nayshtut } 1290*e21c39aaSAnton Nayshtut 1291*e21c39aaSAnton Nayshtut static int 1292*e21c39aaSAnton Nayshtut lo_mknod(struct spdk_io_channel *ch, struct spdk_fsdev_io *fsdev_io) 1293*e21c39aaSAnton Nayshtut { 1294*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *parent_fobject = fsdev_io->u_in.mknod.parent_fobject; 1295*e21c39aaSAnton Nayshtut char *name = fsdev_io->u_in.mknod.name; 1296*e21c39aaSAnton Nayshtut mode_t mode = fsdev_io->u_in.mknod.mode; 1297*e21c39aaSAnton Nayshtut dev_t rdev = fsdev_io->u_in.mknod.rdev; 1298*e21c39aaSAnton Nayshtut uid_t euid = fsdev_io->u_in.mknod.euid; 1299*e21c39aaSAnton Nayshtut gid_t egid = fsdev_io->u_in.mknod.egid; 1300*e21c39aaSAnton Nayshtut 1301*e21c39aaSAnton Nayshtut return lo_mknod_symlink(fsdev_io, parent_fobject, name, mode, rdev, NULL, euid, egid, 1302*e21c39aaSAnton Nayshtut &fsdev_io->u_out.mknod.fobject, &fsdev_io->u_out.mknod.attr); 1303*e21c39aaSAnton Nayshtut } 1304*e21c39aaSAnton Nayshtut 1305*e21c39aaSAnton Nayshtut static int 1306*e21c39aaSAnton Nayshtut lo_mkdir(struct spdk_io_channel *ch, struct spdk_fsdev_io *fsdev_io) 1307*e21c39aaSAnton Nayshtut { 1308*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *parent_fobject = fsdev_io->u_in.mkdir.parent_fobject; 1309*e21c39aaSAnton Nayshtut char *name = fsdev_io->u_in.mkdir.name; 1310*e21c39aaSAnton Nayshtut mode_t mode = fsdev_io->u_in.mkdir.mode; 1311*e21c39aaSAnton Nayshtut uid_t euid = fsdev_io->u_in.mkdir.euid; 1312*e21c39aaSAnton Nayshtut gid_t egid = fsdev_io->u_in.mkdir.egid; 1313*e21c39aaSAnton Nayshtut 1314*e21c39aaSAnton Nayshtut return lo_mknod_symlink(fsdev_io, parent_fobject, name, S_IFDIR | mode, 0, NULL, euid, egid, 1315*e21c39aaSAnton Nayshtut &fsdev_io->u_out.mkdir.fobject, &fsdev_io->u_out.mkdir.attr); 1316*e21c39aaSAnton Nayshtut } 1317*e21c39aaSAnton Nayshtut 1318*e21c39aaSAnton Nayshtut static int 1319*e21c39aaSAnton Nayshtut lo_symlink(struct spdk_io_channel *ch, struct spdk_fsdev_io *fsdev_io) 1320*e21c39aaSAnton Nayshtut { 1321*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *parent_fobject = fsdev_io->u_in.symlink.parent_fobject; 1322*e21c39aaSAnton Nayshtut char *target = fsdev_io->u_in.symlink.target; 1323*e21c39aaSAnton Nayshtut char *linkpath = fsdev_io->u_in.symlink.linkpath; 1324*e21c39aaSAnton Nayshtut uid_t euid = fsdev_io->u_in.symlink.euid; 1325*e21c39aaSAnton Nayshtut gid_t egid = fsdev_io->u_in.symlink.egid; 1326*e21c39aaSAnton Nayshtut 1327*e21c39aaSAnton Nayshtut return lo_mknod_symlink(fsdev_io, parent_fobject, target, S_IFLNK, 0, linkpath, euid, egid, 1328*e21c39aaSAnton Nayshtut &fsdev_io->u_out.symlink.fobject, &fsdev_io->u_out.symlink.attr); 1329*e21c39aaSAnton Nayshtut } 1330*e21c39aaSAnton Nayshtut 1331*e21c39aaSAnton Nayshtut static int 1332*e21c39aaSAnton Nayshtut lo_do_unlink(struct aio_fsdev *vfsdev, struct spdk_fsdev_file_object *parent_fobject, 1333*e21c39aaSAnton Nayshtut const char *name, bool is_dir) 1334*e21c39aaSAnton Nayshtut { 1335*e21c39aaSAnton Nayshtut /* fobject must be initialized to avoid a scan-build false positive */ 1336*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *fobject = NULL; 1337*e21c39aaSAnton Nayshtut int res; 1338*e21c39aaSAnton Nayshtut 1339*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fobject(vfsdev, parent_fobject)) { 1340*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid parent_fobject: %p\n", parent_fobject); 1341*e21c39aaSAnton Nayshtut return -EINVAL; 1342*e21c39aaSAnton Nayshtut } 1343*e21c39aaSAnton Nayshtut 1344*e21c39aaSAnton Nayshtut if (!is_safe_path_component(name)) { 1345*e21c39aaSAnton Nayshtut SPDK_ERRLOG("%s isn't safe\n", name); 1346*e21c39aaSAnton Nayshtut return -EINVAL; 1347*e21c39aaSAnton Nayshtut } 1348*e21c39aaSAnton Nayshtut 1349*e21c39aaSAnton Nayshtut res = lo_do_lookup(vfsdev, parent_fobject, name, &fobject, NULL); 1350*e21c39aaSAnton Nayshtut if (res) { 1351*e21c39aaSAnton Nayshtut SPDK_ERRLOG("can't find '%s' under " FOBJECT_FMT "\n", name, FOBJECT_ARGS(parent_fobject)); 1352*e21c39aaSAnton Nayshtut return -EIO; 1353*e21c39aaSAnton Nayshtut } 1354*e21c39aaSAnton Nayshtut 1355*e21c39aaSAnton Nayshtut res = unlinkat(parent_fobject->fd, name, is_dir ? AT_REMOVEDIR : 0); 1356*e21c39aaSAnton Nayshtut if (res) { 1357*e21c39aaSAnton Nayshtut res = -errno; 1358*e21c39aaSAnton Nayshtut SPDK_WARNLOG("unlinkat(" FOBJECT_FMT " %s) failed (err=%d)\n", 1359*e21c39aaSAnton Nayshtut FOBJECT_ARGS(parent_fobject), name, res); 1360*e21c39aaSAnton Nayshtut } 1361*e21c39aaSAnton Nayshtut 1362*e21c39aaSAnton Nayshtut file_object_unref(fobject, 1); 1363*e21c39aaSAnton Nayshtut return res; 1364*e21c39aaSAnton Nayshtut } 1365*e21c39aaSAnton Nayshtut 1366*e21c39aaSAnton Nayshtut static int 1367*e21c39aaSAnton Nayshtut lo_unlink(struct spdk_io_channel *ch, struct spdk_fsdev_io *fsdev_io) 1368*e21c39aaSAnton Nayshtut { 1369*e21c39aaSAnton Nayshtut struct aio_fsdev *vfsdev = fsdev_to_aio_fsdev(fsdev_io->fsdev); 1370*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *parent_fobject = fsdev_io->u_in.unlink.parent_fobject; 1371*e21c39aaSAnton Nayshtut char *name = fsdev_io->u_in.unlink.name; 1372*e21c39aaSAnton Nayshtut 1373*e21c39aaSAnton Nayshtut return lo_do_unlink(vfsdev, parent_fobject, name, false); 1374*e21c39aaSAnton Nayshtut } 1375*e21c39aaSAnton Nayshtut 1376*e21c39aaSAnton Nayshtut static int 1377*e21c39aaSAnton Nayshtut lo_rmdir(struct spdk_io_channel *ch, struct spdk_fsdev_io *fsdev_io) 1378*e21c39aaSAnton Nayshtut { 1379*e21c39aaSAnton Nayshtut struct aio_fsdev *vfsdev = fsdev_to_aio_fsdev(fsdev_io->fsdev); 1380*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *parent_fobject = fsdev_io->u_in.rmdir.parent_fobject; 1381*e21c39aaSAnton Nayshtut char *name = fsdev_io->u_in.rmdir.name; 1382*e21c39aaSAnton Nayshtut 1383*e21c39aaSAnton Nayshtut return lo_do_unlink(vfsdev, parent_fobject, name, true); 1384*e21c39aaSAnton Nayshtut } 1385*e21c39aaSAnton Nayshtut 1386*e21c39aaSAnton Nayshtut static int 1387*e21c39aaSAnton Nayshtut lo_rename(struct spdk_io_channel *ch, struct spdk_fsdev_io *fsdev_io) 1388*e21c39aaSAnton Nayshtut { 1389*e21c39aaSAnton Nayshtut struct aio_fsdev *vfsdev = fsdev_to_aio_fsdev(fsdev_io->fsdev); 1390*e21c39aaSAnton Nayshtut int res, saverr; 1391*e21c39aaSAnton Nayshtut /* old_fobject must be initialized to avoid a scan-build false positive */ 1392*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *old_fobject = NULL; 1393*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *parent_fobject = fsdev_io->u_in.rename.parent_fobject; 1394*e21c39aaSAnton Nayshtut char *name = fsdev_io->u_in.rename.name; 1395*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *new_parent_fobject = fsdev_io->u_in.rename.new_parent_fobject; 1396*e21c39aaSAnton Nayshtut char *new_name = fsdev_io->u_in.rename.new_name; 1397*e21c39aaSAnton Nayshtut uint32_t flags = fsdev_io->u_in.rename.flags; 1398*e21c39aaSAnton Nayshtut 1399*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fobject(vfsdev, parent_fobject)) { 1400*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid parent_fobject: %p\n", parent_fobject); 1401*e21c39aaSAnton Nayshtut return -EINVAL; 1402*e21c39aaSAnton Nayshtut } 1403*e21c39aaSAnton Nayshtut 1404*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fobject(vfsdev, new_parent_fobject)) { 1405*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid new_parent_fobject: %p\n", new_parent_fobject); 1406*e21c39aaSAnton Nayshtut return -EINVAL; 1407*e21c39aaSAnton Nayshtut } 1408*e21c39aaSAnton Nayshtut 1409*e21c39aaSAnton Nayshtut if (!is_safe_path_component(name)) { 1410*e21c39aaSAnton Nayshtut SPDK_ERRLOG("name '%s' isn't safe\n", name); 1411*e21c39aaSAnton Nayshtut return -EINVAL; 1412*e21c39aaSAnton Nayshtut } 1413*e21c39aaSAnton Nayshtut 1414*e21c39aaSAnton Nayshtut if (!is_safe_path_component(new_name)) { 1415*e21c39aaSAnton Nayshtut SPDK_ERRLOG("newname '%s' isn't safe\n", new_name); 1416*e21c39aaSAnton Nayshtut return -EINVAL; 1417*e21c39aaSAnton Nayshtut } 1418*e21c39aaSAnton Nayshtut 1419*e21c39aaSAnton Nayshtut res = lo_do_lookup(vfsdev, parent_fobject, name, &old_fobject, NULL); 1420*e21c39aaSAnton Nayshtut if (res) { 1421*e21c39aaSAnton Nayshtut SPDK_ERRLOG("can't find '%s' under " FOBJECT_FMT "\n", name, FOBJECT_ARGS(parent_fobject)); 1422*e21c39aaSAnton Nayshtut return -EIO; 1423*e21c39aaSAnton Nayshtut } 1424*e21c39aaSAnton Nayshtut 1425*e21c39aaSAnton Nayshtut saverr = 0; 1426*e21c39aaSAnton Nayshtut if (flags) { 1427*e21c39aaSAnton Nayshtut #ifndef SYS_renameat2 1428*e21c39aaSAnton Nayshtut SPDK_ERRLOG("flags are not supported\n"); 1429*e21c39aaSAnton Nayshtut return -ENOTSUP; 1430*e21c39aaSAnton Nayshtut #else 1431*e21c39aaSAnton Nayshtut res = syscall(SYS_renameat2, parent_fobject->fd, name, new_parent_fobject->fd, 1432*e21c39aaSAnton Nayshtut new_name, flags); 1433*e21c39aaSAnton Nayshtut if (res == -1 && errno == ENOSYS) { 1434*e21c39aaSAnton Nayshtut SPDK_ERRLOG("SYS_renameat2 returned ENOSYS\n"); 1435*e21c39aaSAnton Nayshtut saverr = -EINVAL; 1436*e21c39aaSAnton Nayshtut } else if (res == -1) { 1437*e21c39aaSAnton Nayshtut saverr = -errno; 1438*e21c39aaSAnton Nayshtut SPDK_ERRLOG("SYS_renameat2 failed (err=%d))\n", saverr); 1439*e21c39aaSAnton Nayshtut } 1440*e21c39aaSAnton Nayshtut #endif 1441*e21c39aaSAnton Nayshtut } else { 1442*e21c39aaSAnton Nayshtut res = renameat(parent_fobject->fd, name, new_parent_fobject->fd, new_name); 1443*e21c39aaSAnton Nayshtut if (res == -1) { 1444*e21c39aaSAnton Nayshtut saverr = -errno; 1445*e21c39aaSAnton Nayshtut SPDK_ERRLOG("renameat failed (err=%d)\n", saverr); 1446*e21c39aaSAnton Nayshtut } 1447*e21c39aaSAnton Nayshtut } 1448*e21c39aaSAnton Nayshtut 1449*e21c39aaSAnton Nayshtut file_object_unref(old_fobject, 1); 1450*e21c39aaSAnton Nayshtut 1451*e21c39aaSAnton Nayshtut return saverr; 1452*e21c39aaSAnton Nayshtut } 1453*e21c39aaSAnton Nayshtut 1454*e21c39aaSAnton Nayshtut static int 1455*e21c39aaSAnton Nayshtut linkat_empty_nofollow(struct aio_fsdev *vfsdev, struct spdk_fsdev_file_object *fobject, int dfd, 1456*e21c39aaSAnton Nayshtut const char *name) 1457*e21c39aaSAnton Nayshtut { 1458*e21c39aaSAnton Nayshtut int res; 1459*e21c39aaSAnton Nayshtut 1460*e21c39aaSAnton Nayshtut if (fobject->is_symlink) { 1461*e21c39aaSAnton Nayshtut res = linkat(fobject->fd, "", dfd, name, AT_EMPTY_PATH); 1462*e21c39aaSAnton Nayshtut if (res == -1 && (errno == ENOENT || errno == EINVAL)) { 1463*e21c39aaSAnton Nayshtut /* Sorry, no race free way to hard-link a symlink. */ 1464*e21c39aaSAnton Nayshtut errno = EPERM; 1465*e21c39aaSAnton Nayshtut } 1466*e21c39aaSAnton Nayshtut } else { 1467*e21c39aaSAnton Nayshtut res = linkat(vfsdev->proc_self_fd, fobject->fd_str, dfd, name, AT_SYMLINK_FOLLOW); 1468*e21c39aaSAnton Nayshtut } 1469*e21c39aaSAnton Nayshtut 1470*e21c39aaSAnton Nayshtut return res; 1471*e21c39aaSAnton Nayshtut } 1472*e21c39aaSAnton Nayshtut 1473*e21c39aaSAnton Nayshtut static int 1474*e21c39aaSAnton Nayshtut lo_link(struct spdk_io_channel *ch, struct spdk_fsdev_io *fsdev_io) 1475*e21c39aaSAnton Nayshtut { 1476*e21c39aaSAnton Nayshtut struct aio_fsdev *vfsdev = fsdev_to_aio_fsdev(fsdev_io->fsdev); 1477*e21c39aaSAnton Nayshtut int res; 1478*e21c39aaSAnton Nayshtut int saverr; 1479*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *fobject = fsdev_io->u_in.link.fobject; 1480*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *new_parent_fobject = fsdev_io->u_in.link.new_parent_fobject; 1481*e21c39aaSAnton Nayshtut char *name = fsdev_io->u_in.link.name; 1482*e21c39aaSAnton Nayshtut 1483*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fobject(vfsdev, fobject)) { 1484*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid fobject: %p\n", fobject); 1485*e21c39aaSAnton Nayshtut return -EINVAL; 1486*e21c39aaSAnton Nayshtut } 1487*e21c39aaSAnton Nayshtut 1488*e21c39aaSAnton Nayshtut if (!is_safe_path_component(name)) { 1489*e21c39aaSAnton Nayshtut SPDK_ERRLOG("%s is not a safe component\n", name); 1490*e21c39aaSAnton Nayshtut return -EINVAL; 1491*e21c39aaSAnton Nayshtut } 1492*e21c39aaSAnton Nayshtut 1493*e21c39aaSAnton Nayshtut res = linkat_empty_nofollow(vfsdev, fobject, new_parent_fobject->fd, name); 1494*e21c39aaSAnton Nayshtut if (res == -1) { 1495*e21c39aaSAnton Nayshtut saverr = -errno; 1496*e21c39aaSAnton Nayshtut SPDK_ERRLOG("linkat_empty_nofollow failed " FOBJECT_FMT " -> " FOBJECT_FMT " name=%s (err=%d)\n", 1497*e21c39aaSAnton Nayshtut FOBJECT_ARGS(fobject), FOBJECT_ARGS(new_parent_fobject), name, saverr); 1498*e21c39aaSAnton Nayshtut return saverr; 1499*e21c39aaSAnton Nayshtut } 1500*e21c39aaSAnton Nayshtut 1501*e21c39aaSAnton Nayshtut res = lo_do_lookup(vfsdev, new_parent_fobject, name, &fsdev_io->u_out.link.fobject, 1502*e21c39aaSAnton Nayshtut &fsdev_io->u_out.link.attr); 1503*e21c39aaSAnton Nayshtut if (res) { 1504*e21c39aaSAnton Nayshtut SPDK_ERRLOG("lookup failed (err=%d)\n", res); 1505*e21c39aaSAnton Nayshtut return res; 1506*e21c39aaSAnton Nayshtut } 1507*e21c39aaSAnton Nayshtut 1508*e21c39aaSAnton Nayshtut SPDK_DEBUGLOG(fsdev_aio, "LINK succeeded for " FOBJECT_FMT " -> " FOBJECT_FMT " name=%s\n", 1509*e21c39aaSAnton Nayshtut FOBJECT_ARGS(fobject), FOBJECT_ARGS(fsdev_io->u_out.link.fobject), name); 1510*e21c39aaSAnton Nayshtut 1511*e21c39aaSAnton Nayshtut return 0; 1512*e21c39aaSAnton Nayshtut } 1513*e21c39aaSAnton Nayshtut 1514*e21c39aaSAnton Nayshtut static int 1515*e21c39aaSAnton Nayshtut lo_fsync(struct spdk_io_channel *ch, struct spdk_fsdev_io *fsdev_io) 1516*e21c39aaSAnton Nayshtut { 1517*e21c39aaSAnton Nayshtut struct aio_fsdev *vfsdev = fsdev_to_aio_fsdev(fsdev_io->fsdev); 1518*e21c39aaSAnton Nayshtut int res, saverr, fd; 1519*e21c39aaSAnton Nayshtut char *buf; 1520*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *fobject = fsdev_io->u_in.fsync.fobject; 1521*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_handle *fhandle = fsdev_io->u_in.fsync.fhandle; 1522*e21c39aaSAnton Nayshtut bool datasync = fsdev_io->u_in.fsync.datasync; 1523*e21c39aaSAnton Nayshtut 1524*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fobject(vfsdev, fobject)) { 1525*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid fobject: %p\n", fobject); 1526*e21c39aaSAnton Nayshtut return -EINVAL; 1527*e21c39aaSAnton Nayshtut } 1528*e21c39aaSAnton Nayshtut 1529*e21c39aaSAnton Nayshtut if (!fhandle) { 1530*e21c39aaSAnton Nayshtut res = asprintf(&buf, "%i", fobject->fd); 1531*e21c39aaSAnton Nayshtut if (res == -1) { 1532*e21c39aaSAnton Nayshtut saverr = -errno; 1533*e21c39aaSAnton Nayshtut SPDK_ERRLOG("asprintf failed (errno=%d)\n", saverr); 1534*e21c39aaSAnton Nayshtut return saverr; 1535*e21c39aaSAnton Nayshtut } 1536*e21c39aaSAnton Nayshtut 1537*e21c39aaSAnton Nayshtut fd = openat(vfsdev->proc_self_fd, buf, O_RDWR); 1538*e21c39aaSAnton Nayshtut saverr = -errno; 1539*e21c39aaSAnton Nayshtut free(buf); 1540*e21c39aaSAnton Nayshtut if (fd == -1) { 1541*e21c39aaSAnton Nayshtut SPDK_ERRLOG("openat failed (errno=%d)\n", saverr); 1542*e21c39aaSAnton Nayshtut return saverr; 1543*e21c39aaSAnton Nayshtut } 1544*e21c39aaSAnton Nayshtut } else { 1545*e21c39aaSAnton Nayshtut fd = fhandle->fd; 1546*e21c39aaSAnton Nayshtut } 1547*e21c39aaSAnton Nayshtut 1548*e21c39aaSAnton Nayshtut if (datasync) { 1549*e21c39aaSAnton Nayshtut res = fdatasync(fd); 1550*e21c39aaSAnton Nayshtut } else { 1551*e21c39aaSAnton Nayshtut res = fsync(fd); 1552*e21c39aaSAnton Nayshtut } 1553*e21c39aaSAnton Nayshtut 1554*e21c39aaSAnton Nayshtut saverr = -errno; 1555*e21c39aaSAnton Nayshtut if (!fhandle) { 1556*e21c39aaSAnton Nayshtut close(fd); 1557*e21c39aaSAnton Nayshtut } 1558*e21c39aaSAnton Nayshtut 1559*e21c39aaSAnton Nayshtut if (res == -1) { 1560*e21c39aaSAnton Nayshtut SPDK_ERRLOG("fdatasync/fsync failed for " FOBJECT_FMT " fh=%p (err=%d)\n", 1561*e21c39aaSAnton Nayshtut FOBJECT_ARGS(fobject), fhandle, saverr); 1562*e21c39aaSAnton Nayshtut return saverr; 1563*e21c39aaSAnton Nayshtut } 1564*e21c39aaSAnton Nayshtut 1565*e21c39aaSAnton Nayshtut SPDK_DEBUGLOG(fsdev_aio, "FSYNC succeeded for " FOBJECT_FMT " fh=%p\n", 1566*e21c39aaSAnton Nayshtut FOBJECT_ARGS(fobject), fhandle); 1567*e21c39aaSAnton Nayshtut 1568*e21c39aaSAnton Nayshtut return 0; 1569*e21c39aaSAnton Nayshtut } 1570*e21c39aaSAnton Nayshtut 1571*e21c39aaSAnton Nayshtut static int 1572*e21c39aaSAnton Nayshtut lo_setxattr(struct spdk_io_channel *ch, struct spdk_fsdev_io *fsdev_io) 1573*e21c39aaSAnton Nayshtut { 1574*e21c39aaSAnton Nayshtut struct aio_fsdev *vfsdev = fsdev_to_aio_fsdev(fsdev_io->fsdev); 1575*e21c39aaSAnton Nayshtut ssize_t ret; 1576*e21c39aaSAnton Nayshtut int saverr; 1577*e21c39aaSAnton Nayshtut int fd = -1; 1578*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *fobject = fsdev_io->u_in.setxattr.fobject; 1579*e21c39aaSAnton Nayshtut char *name = fsdev_io->u_in.setxattr.name; 1580*e21c39aaSAnton Nayshtut char *value = fsdev_io->u_in.setxattr.value; 1581*e21c39aaSAnton Nayshtut uint32_t size = fsdev_io->u_in.setxattr.size; 1582*e21c39aaSAnton Nayshtut uint32_t flags = fsdev_io->u_in.setxattr.flags; 1583*e21c39aaSAnton Nayshtut 1584*e21c39aaSAnton Nayshtut if (!vfsdev->xattr_enabled) { 1585*e21c39aaSAnton Nayshtut SPDK_INFOLOG(fsdev_aio, "xattr is disabled by config\n"); 1586*e21c39aaSAnton Nayshtut return -ENOSYS; 1587*e21c39aaSAnton Nayshtut } 1588*e21c39aaSAnton Nayshtut 1589*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fobject(vfsdev, fobject)) { 1590*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid fobject: %p\n", fobject); 1591*e21c39aaSAnton Nayshtut return -EINVAL; 1592*e21c39aaSAnton Nayshtut } 1593*e21c39aaSAnton Nayshtut 1594*e21c39aaSAnton Nayshtut if (fobject->is_symlink) { 1595*e21c39aaSAnton Nayshtut /* Sorry, no race free way to removexattr on symlink. */ 1596*e21c39aaSAnton Nayshtut SPDK_ERRLOG("cannot set xattr for symlink\n"); 1597*e21c39aaSAnton Nayshtut return -EPERM; 1598*e21c39aaSAnton Nayshtut } 1599*e21c39aaSAnton Nayshtut 1600*e21c39aaSAnton Nayshtut fd = openat(vfsdev->proc_self_fd, fobject->fd_str, O_RDWR); 1601*e21c39aaSAnton Nayshtut if (fd < 0) { 1602*e21c39aaSAnton Nayshtut saverr = -errno; 1603*e21c39aaSAnton Nayshtut SPDK_ERRLOG("openat failed with errno=%d\n", saverr); 1604*e21c39aaSAnton Nayshtut return saverr; 1605*e21c39aaSAnton Nayshtut } 1606*e21c39aaSAnton Nayshtut 1607*e21c39aaSAnton Nayshtut ret = fsetxattr(fd, name, value, size, flags); 1608*e21c39aaSAnton Nayshtut saverr = -errno; 1609*e21c39aaSAnton Nayshtut close(fd); 1610*e21c39aaSAnton Nayshtut if (ret == -1) { 1611*e21c39aaSAnton Nayshtut if (saverr == -ENOTSUP) { 1612*e21c39aaSAnton Nayshtut SPDK_INFOLOG(fsdev_aio, "flistxattr: extended attributes are not supported or disabled\n"); 1613*e21c39aaSAnton Nayshtut } else { 1614*e21c39aaSAnton Nayshtut SPDK_ERRLOG("flistxattr failed with errno=%d\n", saverr); 1615*e21c39aaSAnton Nayshtut } 1616*e21c39aaSAnton Nayshtut return saverr; 1617*e21c39aaSAnton Nayshtut } 1618*e21c39aaSAnton Nayshtut 1619*e21c39aaSAnton Nayshtut SPDK_DEBUGLOG(fsdev_aio, 1620*e21c39aaSAnton Nayshtut "SETXATTR succeeded for " FOBJECT_FMT " name=%s value=%s size=%" PRIu32 "flags=0x%x" PRIx32 "\n", 1621*e21c39aaSAnton Nayshtut FOBJECT_ARGS(fobject), name, value, size, flags); 1622*e21c39aaSAnton Nayshtut 1623*e21c39aaSAnton Nayshtut return 0; 1624*e21c39aaSAnton Nayshtut } 1625*e21c39aaSAnton Nayshtut 1626*e21c39aaSAnton Nayshtut static int 1627*e21c39aaSAnton Nayshtut lo_getxattr(struct spdk_io_channel *ch, struct spdk_fsdev_io *fsdev_io) 1628*e21c39aaSAnton Nayshtut { 1629*e21c39aaSAnton Nayshtut struct aio_fsdev *vfsdev = fsdev_to_aio_fsdev(fsdev_io->fsdev); 1630*e21c39aaSAnton Nayshtut ssize_t ret; 1631*e21c39aaSAnton Nayshtut int saverr; 1632*e21c39aaSAnton Nayshtut int fd = -1; 1633*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *fobject = fsdev_io->u_in.getxattr.fobject; 1634*e21c39aaSAnton Nayshtut char *name = fsdev_io->u_in.getxattr.name; 1635*e21c39aaSAnton Nayshtut void *buffer = fsdev_io->u_in.getxattr.buffer; 1636*e21c39aaSAnton Nayshtut size_t size = fsdev_io->u_in.getxattr.size; 1637*e21c39aaSAnton Nayshtut 1638*e21c39aaSAnton Nayshtut if (!vfsdev->xattr_enabled) { 1639*e21c39aaSAnton Nayshtut SPDK_INFOLOG(fsdev_aio, "xattr is disabled by config\n"); 1640*e21c39aaSAnton Nayshtut return -ENOSYS; 1641*e21c39aaSAnton Nayshtut } 1642*e21c39aaSAnton Nayshtut 1643*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fobject(vfsdev, fobject)) { 1644*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid fobject: %p\n", fobject); 1645*e21c39aaSAnton Nayshtut return -EINVAL; 1646*e21c39aaSAnton Nayshtut } 1647*e21c39aaSAnton Nayshtut 1648*e21c39aaSAnton Nayshtut if (fobject->is_symlink) { 1649*e21c39aaSAnton Nayshtut /* Sorry, no race free way to getxattr on symlink. */ 1650*e21c39aaSAnton Nayshtut SPDK_ERRLOG("cannot get xattr for symlink\n"); 1651*e21c39aaSAnton Nayshtut return -EPERM; 1652*e21c39aaSAnton Nayshtut } 1653*e21c39aaSAnton Nayshtut 1654*e21c39aaSAnton Nayshtut fd = openat(vfsdev->proc_self_fd, fobject->fd_str, O_RDWR); 1655*e21c39aaSAnton Nayshtut if (fd < 0) { 1656*e21c39aaSAnton Nayshtut saverr = -errno; 1657*e21c39aaSAnton Nayshtut SPDK_ERRLOG("openat failed with errno=%d\n", saverr); 1658*e21c39aaSAnton Nayshtut return saverr; 1659*e21c39aaSAnton Nayshtut } 1660*e21c39aaSAnton Nayshtut 1661*e21c39aaSAnton Nayshtut ret = fgetxattr(fd, name, buffer, size); 1662*e21c39aaSAnton Nayshtut saverr = -errno; 1663*e21c39aaSAnton Nayshtut close(fd); 1664*e21c39aaSAnton Nayshtut if (ret == -1) { 1665*e21c39aaSAnton Nayshtut if (saverr == -ENODATA) { 1666*e21c39aaSAnton Nayshtut SPDK_INFOLOG(fsdev_aio, "fgetxattr: no extended attribute '%s' found\n", name); 1667*e21c39aaSAnton Nayshtut } else if (saverr == -ENOTSUP) { 1668*e21c39aaSAnton Nayshtut SPDK_INFOLOG(fsdev_aio, "fgetxattr: extended attributes are not supported or disabled\n"); 1669*e21c39aaSAnton Nayshtut } else { 1670*e21c39aaSAnton Nayshtut SPDK_ERRLOG("fgetxattr failed with errno=%d\n", saverr); 1671*e21c39aaSAnton Nayshtut } 1672*e21c39aaSAnton Nayshtut return saverr; 1673*e21c39aaSAnton Nayshtut } 1674*e21c39aaSAnton Nayshtut 1675*e21c39aaSAnton Nayshtut fsdev_io->u_out.getxattr.value_size = ret; 1676*e21c39aaSAnton Nayshtut 1677*e21c39aaSAnton Nayshtut SPDK_DEBUGLOG(fsdev_aio, 1678*e21c39aaSAnton Nayshtut "GETXATTR succeeded for " FOBJECT_FMT " name=%s value=%s value_size=%zd\n", 1679*e21c39aaSAnton Nayshtut FOBJECT_ARGS(fobject), name, (char *)buffer, ret); 1680*e21c39aaSAnton Nayshtut 1681*e21c39aaSAnton Nayshtut return 0; 1682*e21c39aaSAnton Nayshtut } 1683*e21c39aaSAnton Nayshtut 1684*e21c39aaSAnton Nayshtut static int 1685*e21c39aaSAnton Nayshtut lo_listxattr(struct spdk_io_channel *ch, struct spdk_fsdev_io *fsdev_io) 1686*e21c39aaSAnton Nayshtut { 1687*e21c39aaSAnton Nayshtut struct aio_fsdev *vfsdev = fsdev_to_aio_fsdev(fsdev_io->fsdev); 1688*e21c39aaSAnton Nayshtut ssize_t ret; 1689*e21c39aaSAnton Nayshtut int saverr; 1690*e21c39aaSAnton Nayshtut int fd = -1; 1691*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *fobject = fsdev_io->u_in.listxattr.fobject; 1692*e21c39aaSAnton Nayshtut char *buffer = fsdev_io->u_in.listxattr.buffer; 1693*e21c39aaSAnton Nayshtut size_t size = fsdev_io->u_in.listxattr.size; 1694*e21c39aaSAnton Nayshtut 1695*e21c39aaSAnton Nayshtut if (!vfsdev->xattr_enabled) { 1696*e21c39aaSAnton Nayshtut SPDK_INFOLOG(fsdev_aio, "xattr is disabled by config\n"); 1697*e21c39aaSAnton Nayshtut return -ENOSYS; 1698*e21c39aaSAnton Nayshtut } 1699*e21c39aaSAnton Nayshtut 1700*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fobject(vfsdev, fobject)) { 1701*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid fobject: %p\n", fobject); 1702*e21c39aaSAnton Nayshtut return -EINVAL; 1703*e21c39aaSAnton Nayshtut } 1704*e21c39aaSAnton Nayshtut 1705*e21c39aaSAnton Nayshtut if (fobject->is_symlink) { 1706*e21c39aaSAnton Nayshtut /* Sorry, no race free way to listxattr on symlink. */ 1707*e21c39aaSAnton Nayshtut SPDK_ERRLOG("cannot list xattr for symlink\n"); 1708*e21c39aaSAnton Nayshtut return -EPERM; 1709*e21c39aaSAnton Nayshtut } 1710*e21c39aaSAnton Nayshtut 1711*e21c39aaSAnton Nayshtut fd = openat(vfsdev->proc_self_fd, fobject->fd_str, O_RDONLY); 1712*e21c39aaSAnton Nayshtut if (fd < 0) { 1713*e21c39aaSAnton Nayshtut saverr = -errno; 1714*e21c39aaSAnton Nayshtut SPDK_ERRLOG("openat failed with errno=%d\n", saverr); 1715*e21c39aaSAnton Nayshtut return saverr; 1716*e21c39aaSAnton Nayshtut } 1717*e21c39aaSAnton Nayshtut 1718*e21c39aaSAnton Nayshtut ret = flistxattr(fd, buffer, size); 1719*e21c39aaSAnton Nayshtut saverr = -errno; 1720*e21c39aaSAnton Nayshtut close(fd); 1721*e21c39aaSAnton Nayshtut if (ret == -1) { 1722*e21c39aaSAnton Nayshtut if (saverr == -ENOTSUP) { 1723*e21c39aaSAnton Nayshtut SPDK_INFOLOG(fsdev_aio, "flistxattr: extended attributes are not supported or disabled\n"); 1724*e21c39aaSAnton Nayshtut } else { 1725*e21c39aaSAnton Nayshtut SPDK_ERRLOG("flistxattr failed with errno=%d\n", saverr); 1726*e21c39aaSAnton Nayshtut } 1727*e21c39aaSAnton Nayshtut return saverr; 1728*e21c39aaSAnton Nayshtut } 1729*e21c39aaSAnton Nayshtut 1730*e21c39aaSAnton Nayshtut fsdev_io->u_out.listxattr.data_size = ret; 1731*e21c39aaSAnton Nayshtut fsdev_io->u_out.listxattr.size_only = (size == 0); 1732*e21c39aaSAnton Nayshtut 1733*e21c39aaSAnton Nayshtut SPDK_DEBUGLOG(fsdev_aio, "LISTXATTR succeeded for " FOBJECT_FMT " data_size=%zu\n", 1734*e21c39aaSAnton Nayshtut FOBJECT_ARGS(fobject), ret); 1735*e21c39aaSAnton Nayshtut 1736*e21c39aaSAnton Nayshtut return 0; 1737*e21c39aaSAnton Nayshtut } 1738*e21c39aaSAnton Nayshtut 1739*e21c39aaSAnton Nayshtut static int 1740*e21c39aaSAnton Nayshtut lo_removexattr(struct spdk_io_channel *ch, struct spdk_fsdev_io *fsdev_io) 1741*e21c39aaSAnton Nayshtut { 1742*e21c39aaSAnton Nayshtut struct aio_fsdev *vfsdev = fsdev_to_aio_fsdev(fsdev_io->fsdev); 1743*e21c39aaSAnton Nayshtut ssize_t ret; 1744*e21c39aaSAnton Nayshtut int saverr; 1745*e21c39aaSAnton Nayshtut int fd = -1; 1746*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *fobject = fsdev_io->u_in.removexattr.fobject; 1747*e21c39aaSAnton Nayshtut char *name = fsdev_io->u_in.removexattr.name; 1748*e21c39aaSAnton Nayshtut 1749*e21c39aaSAnton Nayshtut if (!vfsdev->xattr_enabled) { 1750*e21c39aaSAnton Nayshtut SPDK_INFOLOG(fsdev_aio, "xattr is disabled by config\n"); 1751*e21c39aaSAnton Nayshtut return -ENOSYS; 1752*e21c39aaSAnton Nayshtut } 1753*e21c39aaSAnton Nayshtut 1754*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fobject(vfsdev, fobject)) { 1755*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid fobject: %p\n", fobject); 1756*e21c39aaSAnton Nayshtut return -EINVAL; 1757*e21c39aaSAnton Nayshtut } 1758*e21c39aaSAnton Nayshtut 1759*e21c39aaSAnton Nayshtut if (fobject->is_symlink) { 1760*e21c39aaSAnton Nayshtut /* Sorry, no race free way to setxattr on symlink. */ 1761*e21c39aaSAnton Nayshtut SPDK_ERRLOG("cannot list xattr for symlink\n"); 1762*e21c39aaSAnton Nayshtut return -EPERM; 1763*e21c39aaSAnton Nayshtut } 1764*e21c39aaSAnton Nayshtut 1765*e21c39aaSAnton Nayshtut fd = openat(vfsdev->proc_self_fd, fobject->fd_str, O_RDONLY); 1766*e21c39aaSAnton Nayshtut if (fd < 0) { 1767*e21c39aaSAnton Nayshtut saverr = -errno; 1768*e21c39aaSAnton Nayshtut SPDK_ERRLOG("openat failed with errno=%d\n", saverr); 1769*e21c39aaSAnton Nayshtut return saverr; 1770*e21c39aaSAnton Nayshtut } 1771*e21c39aaSAnton Nayshtut 1772*e21c39aaSAnton Nayshtut ret = fremovexattr(fd, name); 1773*e21c39aaSAnton Nayshtut saverr = -errno; 1774*e21c39aaSAnton Nayshtut close(fd); 1775*e21c39aaSAnton Nayshtut if (ret == -1) { 1776*e21c39aaSAnton Nayshtut if (saverr == -ENODATA) { 1777*e21c39aaSAnton Nayshtut SPDK_INFOLOG(fsdev_aio, "fremovexattr: no extended attribute '%s' found\n", name); 1778*e21c39aaSAnton Nayshtut } else if (saverr == -ENOTSUP) { 1779*e21c39aaSAnton Nayshtut SPDK_INFOLOG(fsdev_aio, "fremovexattr: extended attributes are not supported or disabled\n"); 1780*e21c39aaSAnton Nayshtut } else { 1781*e21c39aaSAnton Nayshtut SPDK_ERRLOG("fremovexattr failed with errno=%d\n", saverr); 1782*e21c39aaSAnton Nayshtut } 1783*e21c39aaSAnton Nayshtut return saverr; 1784*e21c39aaSAnton Nayshtut } 1785*e21c39aaSAnton Nayshtut 1786*e21c39aaSAnton Nayshtut SPDK_DEBUGLOG(fsdev_aio, "REMOVEXATTR succeeded for " FOBJECT_FMT " name=%s\n", 1787*e21c39aaSAnton Nayshtut FOBJECT_ARGS(fobject), name); 1788*e21c39aaSAnton Nayshtut 1789*e21c39aaSAnton Nayshtut return 0; 1790*e21c39aaSAnton Nayshtut } 1791*e21c39aaSAnton Nayshtut 1792*e21c39aaSAnton Nayshtut static int 1793*e21c39aaSAnton Nayshtut lo_fsyncdir(struct spdk_io_channel *ch, struct spdk_fsdev_io *fsdev_io) 1794*e21c39aaSAnton Nayshtut { 1795*e21c39aaSAnton Nayshtut struct aio_fsdev *vfsdev = fsdev_to_aio_fsdev(fsdev_io->fsdev); 1796*e21c39aaSAnton Nayshtut int res; 1797*e21c39aaSAnton Nayshtut int saverr = 0; 1798*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *fobject = fsdev_io->u_in.fsyncdir.fobject; 1799*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_handle *fhandle = fsdev_io->u_in.fsyncdir.fhandle; 1800*e21c39aaSAnton Nayshtut bool datasync = fsdev_io->u_in.fsyncdir.datasync; 1801*e21c39aaSAnton Nayshtut 1802*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fobject(vfsdev, fobject)) { 1803*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid fobject: %p\n", fobject); 1804*e21c39aaSAnton Nayshtut return -EINVAL; 1805*e21c39aaSAnton Nayshtut } 1806*e21c39aaSAnton Nayshtut 1807*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fhandle(vfsdev, fhandle)) { 1808*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid fhandle: %p\n", fhandle); 1809*e21c39aaSAnton Nayshtut return -EINVAL; 1810*e21c39aaSAnton Nayshtut } 1811*e21c39aaSAnton Nayshtut 1812*e21c39aaSAnton Nayshtut if (datasync) { 1813*e21c39aaSAnton Nayshtut res = fdatasync(fhandle->fd); 1814*e21c39aaSAnton Nayshtut } else { 1815*e21c39aaSAnton Nayshtut res = fsync(fhandle->fd); 1816*e21c39aaSAnton Nayshtut } 1817*e21c39aaSAnton Nayshtut 1818*e21c39aaSAnton Nayshtut if (res == -1) { 1819*e21c39aaSAnton Nayshtut saverr = -errno; 1820*e21c39aaSAnton Nayshtut SPDK_ERRLOG("%s failed for fh=%p with err=%d\n", 1821*e21c39aaSAnton Nayshtut datasync ? "fdatasync" : "fsync", fhandle, saverr); 1822*e21c39aaSAnton Nayshtut return saverr; 1823*e21c39aaSAnton Nayshtut } 1824*e21c39aaSAnton Nayshtut 1825*e21c39aaSAnton Nayshtut SPDK_DEBUGLOG(fsdev_aio, "FSYNCDIR succeeded for " FOBJECT_FMT " fh=%p datasync=%d\n", 1826*e21c39aaSAnton Nayshtut FOBJECT_ARGS(fobject), fhandle, datasync); 1827*e21c39aaSAnton Nayshtut 1828*e21c39aaSAnton Nayshtut return 0; 1829*e21c39aaSAnton Nayshtut } 1830*e21c39aaSAnton Nayshtut 1831*e21c39aaSAnton Nayshtut static int 1832*e21c39aaSAnton Nayshtut lo_flock(struct spdk_io_channel *ch, struct spdk_fsdev_io *fsdev_io) 1833*e21c39aaSAnton Nayshtut { 1834*e21c39aaSAnton Nayshtut struct aio_fsdev *vfsdev = fsdev_to_aio_fsdev(fsdev_io->fsdev); 1835*e21c39aaSAnton Nayshtut int res; 1836*e21c39aaSAnton Nayshtut int saverr = 0; 1837*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *fobject = fsdev_io->u_in.flock.fobject; 1838*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_handle *fhandle = fsdev_io->u_in.flock.fhandle; 1839*e21c39aaSAnton Nayshtut int operation = fsdev_io->u_in.flock.operation; 1840*e21c39aaSAnton Nayshtut 1841*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fobject(vfsdev, fobject)) { 1842*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid fobject: %p\n", fobject); 1843*e21c39aaSAnton Nayshtut return -EINVAL; 1844*e21c39aaSAnton Nayshtut } 1845*e21c39aaSAnton Nayshtut 1846*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fhandle(vfsdev, fhandle)) { 1847*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid fhandle: %p\n", fhandle); 1848*e21c39aaSAnton Nayshtut return -EINVAL; 1849*e21c39aaSAnton Nayshtut } 1850*e21c39aaSAnton Nayshtut 1851*e21c39aaSAnton Nayshtut res = flock(fhandle->fd, operation | LOCK_NB); 1852*e21c39aaSAnton Nayshtut if (res == -1) { 1853*e21c39aaSAnton Nayshtut saverr = -errno; 1854*e21c39aaSAnton Nayshtut SPDK_ERRLOG("flock failed for fh=%p with err=%d\n", fhandle, saverr); 1855*e21c39aaSAnton Nayshtut return saverr; 1856*e21c39aaSAnton Nayshtut } 1857*e21c39aaSAnton Nayshtut 1858*e21c39aaSAnton Nayshtut SPDK_DEBUGLOG(fsdev_aio, "FLOCK succeeded for " FOBJECT_FMT " fh=%p operation=%d\n", 1859*e21c39aaSAnton Nayshtut FOBJECT_ARGS(fobject), fhandle, operation); 1860*e21c39aaSAnton Nayshtut 1861*e21c39aaSAnton Nayshtut return 0; 1862*e21c39aaSAnton Nayshtut } 1863*e21c39aaSAnton Nayshtut 1864*e21c39aaSAnton Nayshtut static int 1865*e21c39aaSAnton Nayshtut lo_fallocate(struct spdk_io_channel *ch, struct spdk_fsdev_io *fsdev_io) 1866*e21c39aaSAnton Nayshtut { 1867*e21c39aaSAnton Nayshtut struct aio_fsdev *vfsdev = fsdev_to_aio_fsdev(fsdev_io->fsdev); 1868*e21c39aaSAnton Nayshtut int err; 1869*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *fobject = fsdev_io->u_in.fallocate.fobject; 1870*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_handle *fhandle = fsdev_io->u_in.fallocate.fhandle; 1871*e21c39aaSAnton Nayshtut uint32_t mode = fsdev_io->u_in.fallocate.mode; 1872*e21c39aaSAnton Nayshtut uint64_t offset = fsdev_io->u_in.fallocate.offset; 1873*e21c39aaSAnton Nayshtut uint64_t length = fsdev_io->u_in.fallocate.length; 1874*e21c39aaSAnton Nayshtut 1875*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fobject(vfsdev, fobject)) { 1876*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid fobject: %p\n", fobject); 1877*e21c39aaSAnton Nayshtut return -EINVAL; 1878*e21c39aaSAnton Nayshtut } 1879*e21c39aaSAnton Nayshtut 1880*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fhandle(vfsdev, fhandle)) { 1881*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid fhandle: %p\n", fhandle); 1882*e21c39aaSAnton Nayshtut return -EINVAL; 1883*e21c39aaSAnton Nayshtut } 1884*e21c39aaSAnton Nayshtut 1885*e21c39aaSAnton Nayshtut if (mode) { 1886*e21c39aaSAnton Nayshtut SPDK_ERRLOG("non-zero mode is not suppored\n"); 1887*e21c39aaSAnton Nayshtut return -EOPNOTSUPP; 1888*e21c39aaSAnton Nayshtut } 1889*e21c39aaSAnton Nayshtut 1890*e21c39aaSAnton Nayshtut err = posix_fallocate(fhandle->fd, offset, length); 1891*e21c39aaSAnton Nayshtut if (err) { 1892*e21c39aaSAnton Nayshtut SPDK_ERRLOG("posix_fallocate failed for fh=%p with err=%d\n", 1893*e21c39aaSAnton Nayshtut fhandle, err); 1894*e21c39aaSAnton Nayshtut } 1895*e21c39aaSAnton Nayshtut 1896*e21c39aaSAnton Nayshtut SPDK_DEBUGLOG(fsdev_aio, 1897*e21c39aaSAnton Nayshtut "FALLOCATE returns %d for " FOBJECT_FMT " fh=%p offset=%" PRIu64 " length=%" PRIu64 "\n", 1898*e21c39aaSAnton Nayshtut err, FOBJECT_ARGS(fobject), fhandle, offset, length); 1899*e21c39aaSAnton Nayshtut return err; 1900*e21c39aaSAnton Nayshtut } 1901*e21c39aaSAnton Nayshtut 1902*e21c39aaSAnton Nayshtut static int 1903*e21c39aaSAnton Nayshtut lo_copy_file_range(struct spdk_io_channel *ch, struct spdk_fsdev_io *fsdev_io) 1904*e21c39aaSAnton Nayshtut { 1905*e21c39aaSAnton Nayshtut #ifdef SPDK_CONFIG_COPY_FILE_RANGE 1906*e21c39aaSAnton Nayshtut struct aio_fsdev *vfsdev = fsdev_to_aio_fsdev(fsdev_io->fsdev); 1907*e21c39aaSAnton Nayshtut ssize_t res; 1908*e21c39aaSAnton Nayshtut int saverr = 0; 1909*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *fobject_in = fsdev_io->u_in.copy_file_range.fobject_in; 1910*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_handle *fhandle_in = fsdev_io->u_in.copy_file_range.fhandle_in; 1911*e21c39aaSAnton Nayshtut off_t off_in = fsdev_io->u_in.copy_file_range.off_in; 1912*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *fobject_out = fsdev_io->u_in.copy_file_range.fobject_out; 1913*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_handle *fhandle_out = fsdev_io->u_in.copy_file_range.fhandle_out; 1914*e21c39aaSAnton Nayshtut off_t off_out = fsdev_io->u_in.copy_file_range.off_out; 1915*e21c39aaSAnton Nayshtut size_t len = fsdev_io->u_in.copy_file_range.len; 1916*e21c39aaSAnton Nayshtut uint32_t flags = fsdev_io->u_in.copy_file_range.flags; 1917*e21c39aaSAnton Nayshtut 1918*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fobject(vfsdev, fobject_in)) { 1919*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid fobject_in: %p\n", fobject_in); 1920*e21c39aaSAnton Nayshtut return -EINVAL; 1921*e21c39aaSAnton Nayshtut } 1922*e21c39aaSAnton Nayshtut 1923*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fhandle(vfsdev, fhandle_in)) { 1924*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid fhandle_in: %p\n", fhandle_in); 1925*e21c39aaSAnton Nayshtut return -EINVAL; 1926*e21c39aaSAnton Nayshtut } 1927*e21c39aaSAnton Nayshtut 1928*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fobject(vfsdev, fobject_out)) { 1929*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid fobject_out: %p\n", fobject_out); 1930*e21c39aaSAnton Nayshtut return -EINVAL; 1931*e21c39aaSAnton Nayshtut } 1932*e21c39aaSAnton Nayshtut 1933*e21c39aaSAnton Nayshtut if (!fsdev_aio_is_valid_fhandle(vfsdev, fhandle_out)) { 1934*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Invalid fhandle_out: %p\n", fhandle_out); 1935*e21c39aaSAnton Nayshtut return -EINVAL; 1936*e21c39aaSAnton Nayshtut } 1937*e21c39aaSAnton Nayshtut 1938*e21c39aaSAnton Nayshtut res = copy_file_range(fhandle_in->fd, &off_in, fhandle_out->fd, &off_out, len, flags); 1939*e21c39aaSAnton Nayshtut if (res < 0) { 1940*e21c39aaSAnton Nayshtut saverr = -errno; 1941*e21c39aaSAnton Nayshtut SPDK_ERRLOG("copy_file_range failed with err=%d\n", saverr); 1942*e21c39aaSAnton Nayshtut return saverr; 1943*e21c39aaSAnton Nayshtut } 1944*e21c39aaSAnton Nayshtut 1945*e21c39aaSAnton Nayshtut SPDK_DEBUGLOG(fsdev_aio, 1946*e21c39aaSAnton Nayshtut "COPY_FILE_RANGE succeeded for " FOBJECT_FMT " fh=%p offset=%" PRIu64 " -> " FOBJECT_FMT 1947*e21c39aaSAnton Nayshtut " fh=%p offset=%" PRIu64 " (len-%zu flags=0x%" PRIx32 ")\n", 1948*e21c39aaSAnton Nayshtut FOBJECT_ARGS(fobject_in), fhandle_in, (uint64_t)off_in, FOBJECT_ARGS(fobject_out), fhandle_out, 1949*e21c39aaSAnton Nayshtut (uint64_t)off_out, len, flags); 1950*e21c39aaSAnton Nayshtut 1951*e21c39aaSAnton Nayshtut return 0; 1952*e21c39aaSAnton Nayshtut #else 1953*e21c39aaSAnton Nayshtut return -ENOSYS; 1954*e21c39aaSAnton Nayshtut #endif 1955*e21c39aaSAnton Nayshtut } 1956*e21c39aaSAnton Nayshtut 1957*e21c39aaSAnton Nayshtut static int 1958*e21c39aaSAnton Nayshtut lo_abort(struct spdk_io_channel *_ch, struct spdk_fsdev_io *fsdev_io) 1959*e21c39aaSAnton Nayshtut { 1960*e21c39aaSAnton Nayshtut struct aio_io_channel *ch = spdk_io_channel_get_ctx(_ch); 1961*e21c39aaSAnton Nayshtut struct aio_fsdev_io *vfsdev_io; 1962*e21c39aaSAnton Nayshtut uint64_t unique_to_abort = fsdev_io->u_in.abort.unique_to_abort; 1963*e21c39aaSAnton Nayshtut 1964*e21c39aaSAnton Nayshtut TAILQ_FOREACH(vfsdev_io, &ch->ios_in_progress, link) { 1965*e21c39aaSAnton Nayshtut struct spdk_fsdev_io *_fsdev_io = aio_to_fsdev_io(vfsdev_io); 1966*e21c39aaSAnton Nayshtut if (spdk_fsdev_io_get_unique(_fsdev_io) == unique_to_abort) { 1967*e21c39aaSAnton Nayshtut spdk_aio_mgr_cancel(ch->mgr, vfsdev_io->aio); 1968*e21c39aaSAnton Nayshtut return 0; 1969*e21c39aaSAnton Nayshtut } 1970*e21c39aaSAnton Nayshtut } 1971*e21c39aaSAnton Nayshtut 1972*e21c39aaSAnton Nayshtut return 0; 1973*e21c39aaSAnton Nayshtut } 1974*e21c39aaSAnton Nayshtut 1975*e21c39aaSAnton Nayshtut static int 1976*e21c39aaSAnton Nayshtut aio_io_poll(void *arg) 1977*e21c39aaSAnton Nayshtut { 1978*e21c39aaSAnton Nayshtut struct aio_io_channel *ch = arg; 1979*e21c39aaSAnton Nayshtut 1980*e21c39aaSAnton Nayshtut spdk_aio_mgr_poll(ch->mgr); 1981*e21c39aaSAnton Nayshtut 1982*e21c39aaSAnton Nayshtut return SPDK_POLLER_IDLE; 1983*e21c39aaSAnton Nayshtut } 1984*e21c39aaSAnton Nayshtut 1985*e21c39aaSAnton Nayshtut static int 1986*e21c39aaSAnton Nayshtut aio_fsdev_create_cb(void *io_device, void *ctx_buf) 1987*e21c39aaSAnton Nayshtut { 1988*e21c39aaSAnton Nayshtut struct aio_io_channel *ch = ctx_buf; 1989*e21c39aaSAnton Nayshtut struct spdk_thread *thread = spdk_get_thread(); 1990*e21c39aaSAnton Nayshtut 1991*e21c39aaSAnton Nayshtut ch->mgr = spdk_aio_mgr_create(MAX_AIOS); 1992*e21c39aaSAnton Nayshtut if (!ch->mgr) { 1993*e21c39aaSAnton Nayshtut SPDK_ERRLOG("aoi manager init for failed (thread=%s)\n", spdk_thread_get_name(thread)); 1994*e21c39aaSAnton Nayshtut return -ENOMEM; 1995*e21c39aaSAnton Nayshtut } 1996*e21c39aaSAnton Nayshtut 1997*e21c39aaSAnton Nayshtut ch->poller = SPDK_POLLER_REGISTER(aio_io_poll, ch, 0); 1998*e21c39aaSAnton Nayshtut TAILQ_INIT(&ch->ios_in_progress); 1999*e21c39aaSAnton Nayshtut 2000*e21c39aaSAnton Nayshtut SPDK_DEBUGLOG(fsdev_aio, "Created aio fsdev IO channel: thread %s, thread id %" PRIu64 2001*e21c39aaSAnton Nayshtut "\n", 2002*e21c39aaSAnton Nayshtut spdk_thread_get_name(thread), spdk_thread_get_id(thread)); 2003*e21c39aaSAnton Nayshtut return 0; 2004*e21c39aaSAnton Nayshtut } 2005*e21c39aaSAnton Nayshtut 2006*e21c39aaSAnton Nayshtut static void 2007*e21c39aaSAnton Nayshtut aio_fsdev_destroy_cb(void *io_device, void *ctx_buf) 2008*e21c39aaSAnton Nayshtut { 2009*e21c39aaSAnton Nayshtut struct aio_io_channel *ch = ctx_buf; 2010*e21c39aaSAnton Nayshtut struct spdk_thread *thread = spdk_get_thread(); 2011*e21c39aaSAnton Nayshtut 2012*e21c39aaSAnton Nayshtut UNUSED(thread); 2013*e21c39aaSAnton Nayshtut 2014*e21c39aaSAnton Nayshtut spdk_poller_unregister(&ch->poller); 2015*e21c39aaSAnton Nayshtut spdk_aio_mgr_delete(ch->mgr); 2016*e21c39aaSAnton Nayshtut 2017*e21c39aaSAnton Nayshtut SPDK_DEBUGLOG(fsdev_aio, "Destroyed aio fsdev IO channel: thread %s, thread id %" PRIu64 2018*e21c39aaSAnton Nayshtut "\n", 2019*e21c39aaSAnton Nayshtut spdk_thread_get_name(thread), spdk_thread_get_id(thread)); 2020*e21c39aaSAnton Nayshtut } 2021*e21c39aaSAnton Nayshtut 2022*e21c39aaSAnton Nayshtut static int 2023*e21c39aaSAnton Nayshtut fsdev_aio_initialize(void) 2024*e21c39aaSAnton Nayshtut { 2025*e21c39aaSAnton Nayshtut /* 2026*e21c39aaSAnton Nayshtut * We need to pick some unique address as our "io device" - so just use the 2027*e21c39aaSAnton Nayshtut * address of the global tailq. 2028*e21c39aaSAnton Nayshtut */ 2029*e21c39aaSAnton Nayshtut spdk_io_device_register(&g_aio_fsdev_head, 2030*e21c39aaSAnton Nayshtut aio_fsdev_create_cb, aio_fsdev_destroy_cb, 2031*e21c39aaSAnton Nayshtut sizeof(struct aio_io_channel), "aio_fsdev"); 2032*e21c39aaSAnton Nayshtut 2033*e21c39aaSAnton Nayshtut return 0; 2034*e21c39aaSAnton Nayshtut } 2035*e21c39aaSAnton Nayshtut 2036*e21c39aaSAnton Nayshtut static void 2037*e21c39aaSAnton Nayshtut _fsdev_aio_finish_cb(void *arg) 2038*e21c39aaSAnton Nayshtut { 2039*e21c39aaSAnton Nayshtut /* @todo: handle async module fini */ 2040*e21c39aaSAnton Nayshtut /* spdk_fsdev_module_fini_done(); */ 2041*e21c39aaSAnton Nayshtut } 2042*e21c39aaSAnton Nayshtut 2043*e21c39aaSAnton Nayshtut static void 2044*e21c39aaSAnton Nayshtut fsdev_aio_finish(void) 2045*e21c39aaSAnton Nayshtut { 2046*e21c39aaSAnton Nayshtut spdk_io_device_unregister(&g_aio_fsdev_head, _fsdev_aio_finish_cb); 2047*e21c39aaSAnton Nayshtut } 2048*e21c39aaSAnton Nayshtut 2049*e21c39aaSAnton Nayshtut static int 2050*e21c39aaSAnton Nayshtut fsdev_aio_get_ctx_size(void) 2051*e21c39aaSAnton Nayshtut { 2052*e21c39aaSAnton Nayshtut return sizeof(struct aio_fsdev_io); 2053*e21c39aaSAnton Nayshtut } 2054*e21c39aaSAnton Nayshtut 2055*e21c39aaSAnton Nayshtut static struct spdk_fsdev_module aio_fsdev_module = { 2056*e21c39aaSAnton Nayshtut .name = "aio", 2057*e21c39aaSAnton Nayshtut .module_init = fsdev_aio_initialize, 2058*e21c39aaSAnton Nayshtut .module_fini = fsdev_aio_finish, 2059*e21c39aaSAnton Nayshtut .get_ctx_size = fsdev_aio_get_ctx_size, 2060*e21c39aaSAnton Nayshtut }; 2061*e21c39aaSAnton Nayshtut 2062*e21c39aaSAnton Nayshtut SPDK_FSDEV_MODULE_REGISTER(aio, &aio_fsdev_module); 2063*e21c39aaSAnton Nayshtut 2064*e21c39aaSAnton Nayshtut static void 2065*e21c39aaSAnton Nayshtut fsdev_aio_free(struct aio_fsdev *vfsdev) 2066*e21c39aaSAnton Nayshtut { 2067*e21c39aaSAnton Nayshtut if (vfsdev->proc_self_fd != -1) { 2068*e21c39aaSAnton Nayshtut close(vfsdev->proc_self_fd); 2069*e21c39aaSAnton Nayshtut } 2070*e21c39aaSAnton Nayshtut 2071*e21c39aaSAnton Nayshtut if (vfsdev->root) { 2072*e21c39aaSAnton Nayshtut int destroyed = file_object_unref(vfsdev->root, 1); 2073*e21c39aaSAnton Nayshtut assert(destroyed == 0); 2074*e21c39aaSAnton Nayshtut UNUSED(destroyed); 2075*e21c39aaSAnton Nayshtut 2076*e21c39aaSAnton Nayshtut } 2077*e21c39aaSAnton Nayshtut 2078*e21c39aaSAnton Nayshtut free(vfsdev->fsdev.name); 2079*e21c39aaSAnton Nayshtut free(vfsdev->root_path); 2080*e21c39aaSAnton Nayshtut 2081*e21c39aaSAnton Nayshtut free(vfsdev); 2082*e21c39aaSAnton Nayshtut } 2083*e21c39aaSAnton Nayshtut 2084*e21c39aaSAnton Nayshtut static void 2085*e21c39aaSAnton Nayshtut fsdev_free_leafs(struct spdk_fsdev_file_object *fobject) 2086*e21c39aaSAnton Nayshtut { 2087*e21c39aaSAnton Nayshtut while (!TAILQ_EMPTY(&fobject->handles)) { 2088*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_handle *fhandle = TAILQ_FIRST(&fobject->handles); 2089*e21c39aaSAnton Nayshtut file_handle_delete(fhandle); 2090*e21c39aaSAnton Nayshtut #ifdef __clang_analyzer__ 2091*e21c39aaSAnton Nayshtut /* 2092*e21c39aaSAnton Nayshtut * scan-build fails to comprehend that file_handle_delete() removes the fhandle 2093*e21c39aaSAnton Nayshtut * from the queue, so it thinks it's remained accessible and throws the "Use of 2094*e21c39aaSAnton Nayshtut * memory after it is freed" error here. 2095*e21c39aaSAnton Nayshtut * The loop below "teaches" the scan-build that the freed fhandle is not on the 2096*e21c39aaSAnton Nayshtut * list anymore and supresses the error in this way. 2097*e21c39aaSAnton Nayshtut */ 2098*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_handle *tmp; 2099*e21c39aaSAnton Nayshtut TAILQ_FOREACH(tmp, &fobject->handles, link) { 2100*e21c39aaSAnton Nayshtut assert(tmp != fhandle); 2101*e21c39aaSAnton Nayshtut } 2102*e21c39aaSAnton Nayshtut #endif 2103*e21c39aaSAnton Nayshtut } 2104*e21c39aaSAnton Nayshtut 2105*e21c39aaSAnton Nayshtut while (!TAILQ_EMPTY(&fobject->leafs)) { 2106*e21c39aaSAnton Nayshtut struct spdk_fsdev_file_object *leaf_fobject = TAILQ_FIRST(&fobject->leafs); 2107*e21c39aaSAnton Nayshtut fsdev_free_leafs(leaf_fobject); 2108*e21c39aaSAnton Nayshtut } 2109*e21c39aaSAnton Nayshtut 2110*e21c39aaSAnton Nayshtut if (fobject->refcount) { 2111*e21c39aaSAnton Nayshtut /* if still referenced - zero refcount */ 2112*e21c39aaSAnton Nayshtut int res = file_object_unref(fobject, fobject->refcount); 2113*e21c39aaSAnton Nayshtut assert(res == 0); 2114*e21c39aaSAnton Nayshtut UNUSED(res); 2115*e21c39aaSAnton Nayshtut } 2116*e21c39aaSAnton Nayshtut } 2117*e21c39aaSAnton Nayshtut 2118*e21c39aaSAnton Nayshtut static int 2119*e21c39aaSAnton Nayshtut fsdev_aio_destruct(void *ctx) 2120*e21c39aaSAnton Nayshtut { 2121*e21c39aaSAnton Nayshtut struct aio_fsdev *vfsdev = ctx; 2122*e21c39aaSAnton Nayshtut 2123*e21c39aaSAnton Nayshtut TAILQ_REMOVE(&g_aio_fsdev_head, vfsdev, tailq); 2124*e21c39aaSAnton Nayshtut 2125*e21c39aaSAnton Nayshtut fsdev_free_leafs(vfsdev->root); 2126*e21c39aaSAnton Nayshtut vfsdev->root = NULL; 2127*e21c39aaSAnton Nayshtut 2128*e21c39aaSAnton Nayshtut pthread_mutex_destroy(&vfsdev->mutex); 2129*e21c39aaSAnton Nayshtut 2130*e21c39aaSAnton Nayshtut fsdev_aio_free(vfsdev); 2131*e21c39aaSAnton Nayshtut return 0; 2132*e21c39aaSAnton Nayshtut } 2133*e21c39aaSAnton Nayshtut 2134*e21c39aaSAnton Nayshtut typedef int (*fsdev_op_handler_func)(struct spdk_io_channel *ch, struct spdk_fsdev_io *fsdev_io); 2135*e21c39aaSAnton Nayshtut 2136*e21c39aaSAnton Nayshtut static fsdev_op_handler_func handlers[] = { 2137*e21c39aaSAnton Nayshtut [SPDK_FSDEV_IO_LOOKUP] = lo_lookup, 2138*e21c39aaSAnton Nayshtut [SPDK_FSDEV_IO_FORGET] = lo_forget, 2139*e21c39aaSAnton Nayshtut [SPDK_FSDEV_IO_GETATTR] = lo_getattr, 2140*e21c39aaSAnton Nayshtut [SPDK_FSDEV_IO_SETATTR] = lo_setattr, 2141*e21c39aaSAnton Nayshtut [SPDK_FSDEV_IO_READLINK] = lo_readlink, 2142*e21c39aaSAnton Nayshtut [SPDK_FSDEV_IO_SYMLINK] = lo_symlink, 2143*e21c39aaSAnton Nayshtut [SPDK_FSDEV_IO_MKNOD] = lo_mknod, 2144*e21c39aaSAnton Nayshtut [SPDK_FSDEV_IO_MKDIR] = lo_mkdir, 2145*e21c39aaSAnton Nayshtut [SPDK_FSDEV_IO_UNLINK] = lo_unlink, 2146*e21c39aaSAnton Nayshtut [SPDK_FSDEV_IO_RMDIR] = lo_rmdir, 2147*e21c39aaSAnton Nayshtut [SPDK_FSDEV_IO_RENAME] = lo_rename, 2148*e21c39aaSAnton Nayshtut [SPDK_FSDEV_IO_LINK] = lo_link, 2149*e21c39aaSAnton Nayshtut [SPDK_FSDEV_IO_OPEN] = lo_open, 2150*e21c39aaSAnton Nayshtut [SPDK_FSDEV_IO_READ] = lo_read, 2151*e21c39aaSAnton Nayshtut [SPDK_FSDEV_IO_WRITE] = lo_write, 2152*e21c39aaSAnton Nayshtut [SPDK_FSDEV_IO_STATFS] = lo_statfs, 2153*e21c39aaSAnton Nayshtut [SPDK_FSDEV_IO_RELEASE] = lo_release, 2154*e21c39aaSAnton Nayshtut [SPDK_FSDEV_IO_FSYNC] = lo_fsync, 2155*e21c39aaSAnton Nayshtut [SPDK_FSDEV_IO_SETXATTR] = lo_setxattr, 2156*e21c39aaSAnton Nayshtut [SPDK_FSDEV_IO_GETXATTR] = lo_getxattr, 2157*e21c39aaSAnton Nayshtut [SPDK_FSDEV_IO_LISTXATTR] = lo_listxattr, 2158*e21c39aaSAnton Nayshtut [SPDK_FSDEV_IO_REMOVEXATTR] = lo_removexattr, 2159*e21c39aaSAnton Nayshtut [SPDK_FSDEV_IO_FLUSH] = lo_flush, 2160*e21c39aaSAnton Nayshtut [SPDK_FSDEV_IO_OPENDIR] = lo_opendir, 2161*e21c39aaSAnton Nayshtut [SPDK_FSDEV_IO_READDIR] = lo_readdir, 2162*e21c39aaSAnton Nayshtut [SPDK_FSDEV_IO_RELEASEDIR] = lo_releasedir, 2163*e21c39aaSAnton Nayshtut [SPDK_FSDEV_IO_FSYNCDIR] = lo_fsyncdir, 2164*e21c39aaSAnton Nayshtut [SPDK_FSDEV_IO_FLOCK] = lo_flock, 2165*e21c39aaSAnton Nayshtut [SPDK_FSDEV_IO_CREATE] = lo_create, 2166*e21c39aaSAnton Nayshtut [SPDK_FSDEV_IO_ABORT] = lo_abort, 2167*e21c39aaSAnton Nayshtut [SPDK_FSDEV_IO_FALLOCATE] = lo_fallocate, 2168*e21c39aaSAnton Nayshtut [SPDK_FSDEV_IO_COPY_FILE_RANGE] = lo_copy_file_range, 2169*e21c39aaSAnton Nayshtut }; 2170*e21c39aaSAnton Nayshtut 2171*e21c39aaSAnton Nayshtut static void 2172*e21c39aaSAnton Nayshtut fsdev_aio_submit_request(struct spdk_io_channel *ch, struct spdk_fsdev_io *fsdev_io) 2173*e21c39aaSAnton Nayshtut { 2174*e21c39aaSAnton Nayshtut int status; 2175*e21c39aaSAnton Nayshtut enum spdk_fsdev_io_type type = spdk_fsdev_io_get_type(fsdev_io); 2176*e21c39aaSAnton Nayshtut 2177*e21c39aaSAnton Nayshtut assert(type >= 0 && type < __SPDK_FSDEV_IO_LAST); 2178*e21c39aaSAnton Nayshtut 2179*e21c39aaSAnton Nayshtut status = handlers[type](ch, fsdev_io); 2180*e21c39aaSAnton Nayshtut if (status != IO_STATUS_ASYNC) { 2181*e21c39aaSAnton Nayshtut spdk_fsdev_io_complete(fsdev_io, status); 2182*e21c39aaSAnton Nayshtut } 2183*e21c39aaSAnton Nayshtut } 2184*e21c39aaSAnton Nayshtut 2185*e21c39aaSAnton Nayshtut static struct spdk_io_channel * 2186*e21c39aaSAnton Nayshtut fsdev_aio_get_io_channel(void *ctx) 2187*e21c39aaSAnton Nayshtut { 2188*e21c39aaSAnton Nayshtut return spdk_get_io_channel(&g_aio_fsdev_head); 2189*e21c39aaSAnton Nayshtut } 2190*e21c39aaSAnton Nayshtut 2191*e21c39aaSAnton Nayshtut static int 2192*e21c39aaSAnton Nayshtut fsdev_aio_negotiate_opts(void *ctx, struct spdk_fsdev_open_opts *opts) 2193*e21c39aaSAnton Nayshtut { 2194*e21c39aaSAnton Nayshtut struct aio_fsdev *vfsdev = ctx; 2195*e21c39aaSAnton Nayshtut 2196*e21c39aaSAnton Nayshtut assert(opts != 0); 2197*e21c39aaSAnton Nayshtut assert(opts->opts_size != 0); 2198*e21c39aaSAnton Nayshtut 2199*e21c39aaSAnton Nayshtut UNUSED(vfsdev); 2200*e21c39aaSAnton Nayshtut 2201*e21c39aaSAnton Nayshtut if (opts->opts_size > offsetof(struct spdk_fsdev_open_opts, max_write)) { 2202*e21c39aaSAnton Nayshtut /* Set the value the aio fsdev was created with */ 2203*e21c39aaSAnton Nayshtut opts->max_write = vfsdev->fsdev.opts.max_write; 2204*e21c39aaSAnton Nayshtut } 2205*e21c39aaSAnton Nayshtut 2206*e21c39aaSAnton Nayshtut if (opts->opts_size > offsetof(struct spdk_fsdev_open_opts, writeback_cache_enabled)) { 2207*e21c39aaSAnton Nayshtut if (vfsdev->fsdev.opts.writeback_cache_enabled) { 2208*e21c39aaSAnton Nayshtut /* The writeback_cache_enabled was enabled upon creation => we follow the opts */ 2209*e21c39aaSAnton Nayshtut vfsdev->fsdev.opts.writeback_cache_enabled = opts->writeback_cache_enabled; 2210*e21c39aaSAnton Nayshtut } else { 2211*e21c39aaSAnton Nayshtut /* The writeback_cache_enabled was disabled upon creation => we reflect it in the opts */ 2212*e21c39aaSAnton Nayshtut opts->writeback_cache_enabled = false; 2213*e21c39aaSAnton Nayshtut } 2214*e21c39aaSAnton Nayshtut } 2215*e21c39aaSAnton Nayshtut 2216*e21c39aaSAnton Nayshtut /* The AIO doesn't apply any additional restrictions, so we just accept the requested opts */ 2217*e21c39aaSAnton Nayshtut SPDK_DEBUGLOG(fsdev_aio, 2218*e21c39aaSAnton Nayshtut "aio filesystem %s: opts updated: max_write=%" PRIu32 ", writeback_cache=%" PRIu8 "\n", 2219*e21c39aaSAnton Nayshtut vfsdev->fsdev.name, vfsdev->fsdev.opts.max_write, vfsdev->fsdev.opts.writeback_cache_enabled); 2220*e21c39aaSAnton Nayshtut 2221*e21c39aaSAnton Nayshtut return 0; 2222*e21c39aaSAnton Nayshtut } 2223*e21c39aaSAnton Nayshtut 2224*e21c39aaSAnton Nayshtut static void 2225*e21c39aaSAnton Nayshtut fsdev_aio_write_config_json(struct spdk_fsdev *fsdev, struct spdk_json_write_ctx *w) 2226*e21c39aaSAnton Nayshtut { 2227*e21c39aaSAnton Nayshtut struct aio_fsdev *vfsdev = fsdev_to_aio_fsdev(fsdev); 2228*e21c39aaSAnton Nayshtut 2229*e21c39aaSAnton Nayshtut spdk_json_write_object_begin(w); 2230*e21c39aaSAnton Nayshtut spdk_json_write_named_string(w, "method", "fsdev_aio_create"); 2231*e21c39aaSAnton Nayshtut spdk_json_write_named_object_begin(w, "params"); 2232*e21c39aaSAnton Nayshtut spdk_json_write_named_string(w, "name", spdk_fsdev_get_name(&vfsdev->fsdev)); 2233*e21c39aaSAnton Nayshtut spdk_json_write_named_string(w, "root_path", vfsdev->root_path); 2234*e21c39aaSAnton Nayshtut spdk_json_write_named_bool(w, "enable_xattr", vfsdev->xattr_enabled); 2235*e21c39aaSAnton Nayshtut spdk_json_write_named_bool(w, "enable_writeback_cache", 2236*e21c39aaSAnton Nayshtut !!vfsdev->fsdev.opts.writeback_cache_enabled); 2237*e21c39aaSAnton Nayshtut spdk_json_write_named_uint32(w, "max_write", vfsdev->fsdev.opts.max_write); 2238*e21c39aaSAnton Nayshtut spdk_json_write_object_end(w); /* params */ 2239*e21c39aaSAnton Nayshtut spdk_json_write_object_end(w); 2240*e21c39aaSAnton Nayshtut } 2241*e21c39aaSAnton Nayshtut 2242*e21c39aaSAnton Nayshtut static const struct spdk_fsdev_fn_table aio_fn_table = { 2243*e21c39aaSAnton Nayshtut .destruct = fsdev_aio_destruct, 2244*e21c39aaSAnton Nayshtut .submit_request = fsdev_aio_submit_request, 2245*e21c39aaSAnton Nayshtut .get_io_channel = fsdev_aio_get_io_channel, 2246*e21c39aaSAnton Nayshtut .negotiate_opts = fsdev_aio_negotiate_opts, 2247*e21c39aaSAnton Nayshtut .write_config_json = fsdev_aio_write_config_json, 2248*e21c39aaSAnton Nayshtut }; 2249*e21c39aaSAnton Nayshtut 2250*e21c39aaSAnton Nayshtut static int 2251*e21c39aaSAnton Nayshtut setup_root(struct aio_fsdev *vfsdev) 2252*e21c39aaSAnton Nayshtut { 2253*e21c39aaSAnton Nayshtut int fd, res; 2254*e21c39aaSAnton Nayshtut struct stat stat; 2255*e21c39aaSAnton Nayshtut 2256*e21c39aaSAnton Nayshtut fd = open(vfsdev->root_path, O_PATH); 2257*e21c39aaSAnton Nayshtut if (fd == -1) { 2258*e21c39aaSAnton Nayshtut res = -errno; 2259*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Cannot open root %s (err=%d)\n", vfsdev->root_path, res); 2260*e21c39aaSAnton Nayshtut return res; 2261*e21c39aaSAnton Nayshtut } 2262*e21c39aaSAnton Nayshtut 2263*e21c39aaSAnton Nayshtut res = fstatat(fd, "", &stat, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW); 2264*e21c39aaSAnton Nayshtut if (res == -1) { 2265*e21c39aaSAnton Nayshtut res = -errno; 2266*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Cannot get root fstatat of %s (err=%d)\n", vfsdev->root_path, res); 2267*e21c39aaSAnton Nayshtut close(fd); 2268*e21c39aaSAnton Nayshtut return res; 2269*e21c39aaSAnton Nayshtut } 2270*e21c39aaSAnton Nayshtut 2271*e21c39aaSAnton Nayshtut vfsdev->root = file_object_create_unsafe(NULL, fd, stat.st_ino, stat.st_dev, stat.st_mode); 2272*e21c39aaSAnton Nayshtut if (!vfsdev->root) { 2273*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Cannot alloc root\n"); 2274*e21c39aaSAnton Nayshtut close(fd); 2275*e21c39aaSAnton Nayshtut return -ENOMEM; 2276*e21c39aaSAnton Nayshtut } 2277*e21c39aaSAnton Nayshtut 2278*e21c39aaSAnton Nayshtut SPDK_INFOLOG(fsdev_aio, "root (%s) fd=%d\n", vfsdev->root_path, fd); 2279*e21c39aaSAnton Nayshtut return 0; 2280*e21c39aaSAnton Nayshtut } 2281*e21c39aaSAnton Nayshtut 2282*e21c39aaSAnton Nayshtut static int 2283*e21c39aaSAnton Nayshtut setup_proc_self_fd(struct aio_fsdev *vfsdev) 2284*e21c39aaSAnton Nayshtut { 2285*e21c39aaSAnton Nayshtut vfsdev->proc_self_fd = open("/proc/self/fd", O_PATH); 2286*e21c39aaSAnton Nayshtut if (vfsdev->proc_self_fd == -1) { 2287*e21c39aaSAnton Nayshtut int saverr = -errno; 2288*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Failed to open procfs fd dir with %d\n", saverr); 2289*e21c39aaSAnton Nayshtut return saverr; 2290*e21c39aaSAnton Nayshtut } 2291*e21c39aaSAnton Nayshtut 2292*e21c39aaSAnton Nayshtut SPDK_DEBUGLOG(fsdev_aio, "procfs fd dir opened (fd=%d)\n", vfsdev->proc_self_fd); 2293*e21c39aaSAnton Nayshtut return 0; 2294*e21c39aaSAnton Nayshtut } 2295*e21c39aaSAnton Nayshtut 2296*e21c39aaSAnton Nayshtut void 2297*e21c39aaSAnton Nayshtut spdk_fsdev_aio_get_default_opts(struct spdk_fsdev_aio_opts *opts) 2298*e21c39aaSAnton Nayshtut { 2299*e21c39aaSAnton Nayshtut assert(opts); 2300*e21c39aaSAnton Nayshtut 2301*e21c39aaSAnton Nayshtut memset(opts, 0, sizeof(*opts)); 2302*e21c39aaSAnton Nayshtut 2303*e21c39aaSAnton Nayshtut opts->xattr_enabled = DEFAULT_XATTR_ENABLED; 2304*e21c39aaSAnton Nayshtut opts->writeback_cache_enabled = DEFAULT_WRITEBACK_CACHE; 2305*e21c39aaSAnton Nayshtut opts->max_write = DEFAULT_MAX_WRITE; 2306*e21c39aaSAnton Nayshtut } 2307*e21c39aaSAnton Nayshtut 2308*e21c39aaSAnton Nayshtut int 2309*e21c39aaSAnton Nayshtut spdk_fsdev_aio_create(struct spdk_fsdev **fsdev, const char *name, const char *root_path, 2310*e21c39aaSAnton Nayshtut const struct spdk_fsdev_aio_opts *opts) 2311*e21c39aaSAnton Nayshtut { 2312*e21c39aaSAnton Nayshtut struct aio_fsdev *vfsdev; 2313*e21c39aaSAnton Nayshtut int rc; 2314*e21c39aaSAnton Nayshtut 2315*e21c39aaSAnton Nayshtut vfsdev = calloc(1, sizeof(*vfsdev)); 2316*e21c39aaSAnton Nayshtut if (!vfsdev) { 2317*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Could not allocate aio_fsdev\n"); 2318*e21c39aaSAnton Nayshtut return -ENOMEM; 2319*e21c39aaSAnton Nayshtut } 2320*e21c39aaSAnton Nayshtut 2321*e21c39aaSAnton Nayshtut vfsdev->proc_self_fd = -1; 2322*e21c39aaSAnton Nayshtut 2323*e21c39aaSAnton Nayshtut vfsdev->fsdev.name = strdup(name); 2324*e21c39aaSAnton Nayshtut if (!vfsdev->fsdev.name) { 2325*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Could not strdup fsdev name: %s\n", name); 2326*e21c39aaSAnton Nayshtut fsdev_aio_free(vfsdev); 2327*e21c39aaSAnton Nayshtut return -ENOMEM; 2328*e21c39aaSAnton Nayshtut } 2329*e21c39aaSAnton Nayshtut 2330*e21c39aaSAnton Nayshtut vfsdev->root_path = strdup(root_path); 2331*e21c39aaSAnton Nayshtut if (!vfsdev->root_path) { 2332*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Could not strdup root path: %s\n", root_path); 2333*e21c39aaSAnton Nayshtut fsdev_aio_free(vfsdev); 2334*e21c39aaSAnton Nayshtut return -ENOMEM; 2335*e21c39aaSAnton Nayshtut } 2336*e21c39aaSAnton Nayshtut 2337*e21c39aaSAnton Nayshtut rc = setup_root(vfsdev); 2338*e21c39aaSAnton Nayshtut if (rc) { 2339*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Could not setup root: %s (err=%d)\n", root_path, rc); 2340*e21c39aaSAnton Nayshtut fsdev_aio_free(vfsdev); 2341*e21c39aaSAnton Nayshtut return rc; 2342*e21c39aaSAnton Nayshtut } 2343*e21c39aaSAnton Nayshtut 2344*e21c39aaSAnton Nayshtut rc = setup_proc_self_fd(vfsdev); 2345*e21c39aaSAnton Nayshtut if (rc) { 2346*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Could not setup proc_self_fd (err=%d)\n", rc); 2347*e21c39aaSAnton Nayshtut fsdev_aio_free(vfsdev); 2348*e21c39aaSAnton Nayshtut return rc; 2349*e21c39aaSAnton Nayshtut } 2350*e21c39aaSAnton Nayshtut 2351*e21c39aaSAnton Nayshtut if (opts->xattr_enabled) { 2352*e21c39aaSAnton Nayshtut SPDK_ERRLOG("Extended attributes can only be enabled in Linux\n"); 2353*e21c39aaSAnton Nayshtut fsdev_aio_free(vfsdev); 2354*e21c39aaSAnton Nayshtut return rc; 2355*e21c39aaSAnton Nayshtut } 2356*e21c39aaSAnton Nayshtut 2357*e21c39aaSAnton Nayshtut vfsdev->xattr_enabled = opts->xattr_enabled; 2358*e21c39aaSAnton Nayshtut vfsdev->fsdev.ctxt = vfsdev; 2359*e21c39aaSAnton Nayshtut vfsdev->fsdev.fn_table = &aio_fn_table; 2360*e21c39aaSAnton Nayshtut vfsdev->fsdev.module = &aio_fsdev_module; 2361*e21c39aaSAnton Nayshtut 2362*e21c39aaSAnton Nayshtut pthread_mutex_init(&vfsdev->mutex, NULL); 2363*e21c39aaSAnton Nayshtut 2364*e21c39aaSAnton Nayshtut rc = spdk_fsdev_register(&vfsdev->fsdev); 2365*e21c39aaSAnton Nayshtut if (rc) { 2366*e21c39aaSAnton Nayshtut fsdev_aio_free(vfsdev); 2367*e21c39aaSAnton Nayshtut return rc; 2368*e21c39aaSAnton Nayshtut } 2369*e21c39aaSAnton Nayshtut 2370*e21c39aaSAnton Nayshtut vfsdev->fsdev.opts.writeback_cache_enabled = opts->writeback_cache_enabled; 2371*e21c39aaSAnton Nayshtut vfsdev->fsdev.opts.max_write = opts->max_write; 2372*e21c39aaSAnton Nayshtut 2373*e21c39aaSAnton Nayshtut *fsdev = &(vfsdev->fsdev); 2374*e21c39aaSAnton Nayshtut TAILQ_INSERT_TAIL(&g_aio_fsdev_head, vfsdev, tailq); 2375*e21c39aaSAnton Nayshtut SPDK_DEBUGLOG(fsdev_aio, "Created aio filesystem %s (xattr_enabled=%" PRIu8 " writeback_cache=%" 2376*e21c39aaSAnton Nayshtut PRIu8 " max_write=%" PRIu32 ")\n", 2377*e21c39aaSAnton Nayshtut vfsdev->fsdev.name, vfsdev->xattr_enabled, vfsdev->fsdev.opts.writeback_cache_enabled, 2378*e21c39aaSAnton Nayshtut vfsdev->fsdev.opts.max_write); 2379*e21c39aaSAnton Nayshtut return rc; 2380*e21c39aaSAnton Nayshtut } 2381*e21c39aaSAnton Nayshtut void 2382*e21c39aaSAnton Nayshtut spdk_fsdev_aio_delete(const char *name, 2383*e21c39aaSAnton Nayshtut spdk_delete_aio_fsdev_complete cb_fn, void *cb_arg) 2384*e21c39aaSAnton Nayshtut { 2385*e21c39aaSAnton Nayshtut int rc; 2386*e21c39aaSAnton Nayshtut 2387*e21c39aaSAnton Nayshtut rc = spdk_fsdev_unregister_by_name(name, &aio_fsdev_module, cb_fn, cb_arg); 2388*e21c39aaSAnton Nayshtut if (rc != 0) { 2389*e21c39aaSAnton Nayshtut cb_fn(cb_arg, rc); 2390*e21c39aaSAnton Nayshtut } 2391*e21c39aaSAnton Nayshtut 2392*e21c39aaSAnton Nayshtut SPDK_DEBUGLOG(fsdev_aio, "Deleted aio filesystem %s\n", name); 2393*e21c39aaSAnton Nayshtut } 2394*e21c39aaSAnton Nayshtut 2395*e21c39aaSAnton Nayshtut SPDK_LOG_REGISTER_COMPONENT(fsdev_aio) 2396