1 2 /* 3 * Virtio 9p backend 4 * 5 * Copyright IBM, Corp. 2011 6 * 7 * Authors: 8 * Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> 9 * 10 * This work is licensed under the terms of the GNU GPL, version 2. See 11 * the COPYING file in the top-level directory. 12 * 13 */ 14 15 #include "fsdev/qemu-fsdev.h" 16 #include "qemu-thread.h" 17 #include "qemu-coroutine.h" 18 #include "virtio-9p-coth.h" 19 20 int v9fs_co_lstat(V9fsPDU *pdu, V9fsPath *path, struct stat *stbuf) 21 { 22 int err; 23 V9fsState *s = pdu->s; 24 25 if (v9fs_request_cancelled(pdu)) { 26 return -EINTR; 27 } 28 v9fs_path_read_lock(s); 29 v9fs_co_run_in_worker( 30 { 31 err = s->ops->lstat(&s->ctx, path, stbuf); 32 if (err < 0) { 33 err = -errno; 34 } 35 }); 36 v9fs_path_unlock(s); 37 return err; 38 } 39 40 int v9fs_co_fstat(V9fsPDU *pdu, int fd, struct stat *stbuf) 41 { 42 int err; 43 V9fsState *s = pdu->s; 44 45 if (v9fs_request_cancelled(pdu)) { 46 return -EINTR; 47 } 48 v9fs_co_run_in_worker( 49 { 50 err = s->ops->fstat(&s->ctx, fd, stbuf); 51 if (err < 0) { 52 err = -errno; 53 } 54 }); 55 return err; 56 } 57 58 int v9fs_co_open(V9fsPDU *pdu, V9fsFidState *fidp, int flags) 59 { 60 int err; 61 V9fsState *s = pdu->s; 62 63 if (v9fs_request_cancelled(pdu)) { 64 return -EINTR; 65 } 66 v9fs_path_read_lock(s); 67 v9fs_co_run_in_worker( 68 { 69 fidp->fs.fd = s->ops->open(&s->ctx, &fidp->path, flags); 70 if (fidp->fs.fd == -1) { 71 err = -errno; 72 } else { 73 err = 0; 74 } 75 }); 76 v9fs_path_unlock(s); 77 if (!err) { 78 total_open_fd++; 79 if (total_open_fd > open_fd_hw) { 80 v9fs_reclaim_fd(pdu); 81 } 82 } 83 return err; 84 } 85 86 int v9fs_co_open2(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name, gid_t gid, 87 int flags, int mode, struct stat *stbuf) 88 { 89 int err; 90 FsCred cred; 91 V9fsPath path; 92 V9fsState *s = pdu->s; 93 94 if (v9fs_request_cancelled(pdu)) { 95 return -EINTR; 96 } 97 cred_init(&cred); 98 cred.fc_mode = mode & 07777; 99 cred.fc_uid = fidp->uid; 100 cred.fc_gid = gid; 101 /* 102 * Hold the directory fid lock so that directory path name 103 * don't change. Read lock is fine because this fid cannot 104 * be used by any other operation. 105 */ 106 v9fs_path_read_lock(s); 107 v9fs_co_run_in_worker( 108 { 109 fidp->fs.fd = s->ops->open2(&s->ctx, &fidp->path, 110 name->data, flags, &cred); 111 if (fidp->fs.fd == -1) { 112 err = -errno; 113 } else { 114 v9fs_path_init(&path); 115 err = v9fs_name_to_path(s, &fidp->path, name->data, &path); 116 if (!err) { 117 err = s->ops->lstat(&s->ctx, &path, stbuf); 118 if (err < 0) { 119 err = -errno; 120 s->ops->close(&s->ctx, fidp->fs.fd); 121 } else { 122 v9fs_path_copy(&fidp->path, &path); 123 } 124 } else { 125 s->ops->close(&s->ctx, fidp->fs.fd); 126 } 127 v9fs_path_free(&path); 128 } 129 }); 130 v9fs_path_unlock(s); 131 if (!err) { 132 total_open_fd++; 133 if (total_open_fd > open_fd_hw) { 134 v9fs_reclaim_fd(pdu); 135 } 136 } 137 return err; 138 } 139 140 int v9fs_co_close(V9fsPDU *pdu, int fd) 141 { 142 int err; 143 V9fsState *s = pdu->s; 144 145 if (v9fs_request_cancelled(pdu)) { 146 return -EINTR; 147 } 148 v9fs_co_run_in_worker( 149 { 150 err = s->ops->close(&s->ctx, fd); 151 if (err < 0) { 152 err = -errno; 153 } 154 }); 155 if (!err) { 156 total_open_fd--; 157 } 158 return err; 159 } 160 161 int v9fs_co_fsync(V9fsPDU *pdu, V9fsFidState *fidp, int datasync) 162 { 163 int fd, err; 164 V9fsState *s = pdu->s; 165 166 if (v9fs_request_cancelled(pdu)) { 167 return -EINTR; 168 } 169 fd = fidp->fs.fd; 170 v9fs_co_run_in_worker( 171 { 172 err = s->ops->fsync(&s->ctx, fd, datasync); 173 if (err < 0) { 174 err = -errno; 175 } 176 }); 177 return err; 178 } 179 180 int v9fs_co_link(V9fsPDU *pdu, V9fsFidState *oldfid, 181 V9fsFidState *newdirfid, V9fsString *name) 182 { 183 int err; 184 V9fsState *s = pdu->s; 185 186 if (v9fs_request_cancelled(pdu)) { 187 return -EINTR; 188 } 189 v9fs_path_read_lock(s); 190 v9fs_co_run_in_worker( 191 { 192 err = s->ops->link(&s->ctx, &oldfid->path, 193 &newdirfid->path, name->data); 194 if (err < 0) { 195 err = -errno; 196 } 197 }); 198 v9fs_path_unlock(s); 199 return err; 200 } 201 202 int v9fs_co_pwritev(V9fsPDU *pdu, V9fsFidState *fidp, 203 struct iovec *iov, int iovcnt, int64_t offset) 204 { 205 int fd, err; 206 V9fsState *s = pdu->s; 207 208 if (v9fs_request_cancelled(pdu)) { 209 return -EINTR; 210 } 211 fd = fidp->fs.fd; 212 v9fs_co_run_in_worker( 213 { 214 err = s->ops->pwritev(&s->ctx, fd, iov, iovcnt, offset); 215 if (err < 0) { 216 err = -errno; 217 } 218 }); 219 return err; 220 } 221 222 int v9fs_co_preadv(V9fsPDU *pdu, V9fsFidState *fidp, 223 struct iovec *iov, int iovcnt, int64_t offset) 224 { 225 int fd, err; 226 V9fsState *s = pdu->s; 227 228 if (v9fs_request_cancelled(pdu)) { 229 return -EINTR; 230 } 231 fd = fidp->fs.fd; 232 v9fs_co_run_in_worker( 233 { 234 err = s->ops->preadv(&s->ctx, fd, iov, iovcnt, offset); 235 if (err < 0) { 236 err = -errno; 237 } 238 }); 239 return err; 240 } 241