1172198d4SAneesh Kumar K.V 2172198d4SAneesh Kumar K.V /* 3172198d4SAneesh Kumar K.V * Virtio 9p backend 4172198d4SAneesh Kumar K.V * 5172198d4SAneesh Kumar K.V * Copyright IBM, Corp. 2011 6172198d4SAneesh Kumar K.V * 7172198d4SAneesh Kumar K.V * Authors: 8172198d4SAneesh Kumar K.V * Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> 9172198d4SAneesh Kumar K.V * 10172198d4SAneesh Kumar K.V * This work is licensed under the terms of the GNU GPL, version 2. See 11172198d4SAneesh Kumar K.V * the COPYING file in the top-level directory. 12172198d4SAneesh Kumar K.V * 13172198d4SAneesh Kumar K.V */ 14172198d4SAneesh Kumar K.V 15172198d4SAneesh Kumar K.V #include "fsdev/qemu-fsdev.h" 16*1de7afc9SPaolo Bonzini #include "qemu/thread.h" 17737e150eSPaolo Bonzini #include "block/coroutine.h" 18172198d4SAneesh Kumar K.V #include "virtio-9p-coth.h" 19172198d4SAneesh Kumar K.V 20e06a765eSHarsh Prateek Bora int v9fs_co_st_gen(V9fsPDU *pdu, V9fsPath *path, mode_t st_mode, 21e06a765eSHarsh Prateek Bora V9fsStatDotl *v9stat) 22e06a765eSHarsh Prateek Bora { 23e06a765eSHarsh Prateek Bora int err = 0; 24e06a765eSHarsh Prateek Bora V9fsState *s = pdu->s; 25e06a765eSHarsh Prateek Bora 26e06a765eSHarsh Prateek Bora if (v9fs_request_cancelled(pdu)) { 27e06a765eSHarsh Prateek Bora return -EINTR; 28e06a765eSHarsh Prateek Bora } 29e06a765eSHarsh Prateek Bora if (s->ctx.exops.get_st_gen) { 30e06a765eSHarsh Prateek Bora v9fs_path_read_lock(s); 31e06a765eSHarsh Prateek Bora v9fs_co_run_in_worker( 32e06a765eSHarsh Prateek Bora { 33e06a765eSHarsh Prateek Bora err = s->ctx.exops.get_st_gen(&s->ctx, path, st_mode, 34e06a765eSHarsh Prateek Bora &v9stat->st_gen); 35e06a765eSHarsh Prateek Bora if (err < 0) { 36e06a765eSHarsh Prateek Bora err = -errno; 37e06a765eSHarsh Prateek Bora } 38e06a765eSHarsh Prateek Bora }); 39e06a765eSHarsh Prateek Bora v9fs_path_unlock(s); 40e06a765eSHarsh Prateek Bora } 41e06a765eSHarsh Prateek Bora return err; 42e06a765eSHarsh Prateek Bora } 43e06a765eSHarsh Prateek Bora 44bccacf6cSAneesh Kumar K.V int v9fs_co_lstat(V9fsPDU *pdu, V9fsPath *path, struct stat *stbuf) 45172198d4SAneesh Kumar K.V { 46172198d4SAneesh Kumar K.V int err; 47bccacf6cSAneesh Kumar K.V V9fsState *s = pdu->s; 48172198d4SAneesh Kumar K.V 49bccacf6cSAneesh Kumar K.V if (v9fs_request_cancelled(pdu)) { 50bccacf6cSAneesh Kumar K.V return -EINTR; 51bccacf6cSAneesh Kumar K.V } 52532decb7SAneesh Kumar K.V v9fs_path_read_lock(s); 53172198d4SAneesh Kumar K.V v9fs_co_run_in_worker( 54172198d4SAneesh Kumar K.V { 552289be19SAneesh Kumar K.V err = s->ops->lstat(&s->ctx, path, stbuf); 56172198d4SAneesh Kumar K.V if (err < 0) { 57172198d4SAneesh Kumar K.V err = -errno; 58172198d4SAneesh Kumar K.V } 59172198d4SAneesh Kumar K.V }); 60532decb7SAneesh Kumar K.V v9fs_path_unlock(s); 61172198d4SAneesh Kumar K.V return err; 62172198d4SAneesh Kumar K.V } 6303feb1e1SAneesh Kumar K.V 64cc720ddbSAneesh Kumar K.V int v9fs_co_fstat(V9fsPDU *pdu, V9fsFidState *fidp, struct stat *stbuf) 6503feb1e1SAneesh Kumar K.V { 6603feb1e1SAneesh Kumar K.V int err; 67bccacf6cSAneesh Kumar K.V V9fsState *s = pdu->s; 6803feb1e1SAneesh Kumar K.V 69bccacf6cSAneesh Kumar K.V if (v9fs_request_cancelled(pdu)) { 70bccacf6cSAneesh Kumar K.V return -EINTR; 71bccacf6cSAneesh Kumar K.V } 7203feb1e1SAneesh Kumar K.V v9fs_co_run_in_worker( 7303feb1e1SAneesh Kumar K.V { 748b888272SAneesh Kumar K.V err = s->ops->fstat(&s->ctx, fidp->fid_type, &fidp->fs, stbuf); 7503feb1e1SAneesh Kumar K.V if (err < 0) { 7603feb1e1SAneesh Kumar K.V err = -errno; 7703feb1e1SAneesh Kumar K.V } 7803feb1e1SAneesh Kumar K.V }); 792c30dd74SAneesh Kumar K.V /* 802c30dd74SAneesh Kumar K.V * Some FS driver (local:mapped-file) can't support fetching attributes 812c30dd74SAneesh Kumar K.V * using file descriptor. Use Path name in that case. 822c30dd74SAneesh Kumar K.V */ 832c30dd74SAneesh Kumar K.V if (err == -EOPNOTSUPP) { 842c30dd74SAneesh Kumar K.V err = v9fs_co_lstat(pdu, &fidp->path, stbuf); 852c30dd74SAneesh Kumar K.V if (err == -ENOENT) { 862c30dd74SAneesh Kumar K.V /* 872c30dd74SAneesh Kumar K.V * fstat on an unlinked file. Work with partial results 882c30dd74SAneesh Kumar K.V * returned from s->ops->fstat 892c30dd74SAneesh Kumar K.V */ 902c30dd74SAneesh Kumar K.V err = 0; 912c30dd74SAneesh Kumar K.V } 922c30dd74SAneesh Kumar K.V } 9303feb1e1SAneesh Kumar K.V return err; 9403feb1e1SAneesh Kumar K.V } 95f6b7f0abSAneesh Kumar K.V 96bccacf6cSAneesh Kumar K.V int v9fs_co_open(V9fsPDU *pdu, V9fsFidState *fidp, int flags) 97f6b7f0abSAneesh Kumar K.V { 98f6b7f0abSAneesh Kumar K.V int err; 99bccacf6cSAneesh Kumar K.V V9fsState *s = pdu->s; 100f6b7f0abSAneesh Kumar K.V 101bccacf6cSAneesh Kumar K.V if (v9fs_request_cancelled(pdu)) { 102bccacf6cSAneesh Kumar K.V return -EINTR; 103bccacf6cSAneesh Kumar K.V } 104532decb7SAneesh Kumar K.V v9fs_path_read_lock(s); 105f6b7f0abSAneesh Kumar K.V v9fs_co_run_in_worker( 106f6b7f0abSAneesh Kumar K.V { 107cc720ddbSAneesh Kumar K.V err = s->ops->open(&s->ctx, &fidp->path, flags, &fidp->fs); 108cc720ddbSAneesh Kumar K.V if (err == -1) { 109f6b7f0abSAneesh Kumar K.V err = -errno; 110f6b7f0abSAneesh Kumar K.V } else { 111f6b7f0abSAneesh Kumar K.V err = 0; 112f6b7f0abSAneesh Kumar K.V } 113f6b7f0abSAneesh Kumar K.V }); 114532decb7SAneesh Kumar K.V v9fs_path_unlock(s); 1157a462745SAneesh Kumar K.V if (!err) { 1167a462745SAneesh Kumar K.V total_open_fd++; 1177a462745SAneesh Kumar K.V if (total_open_fd > open_fd_hw) { 118bccacf6cSAneesh Kumar K.V v9fs_reclaim_fd(pdu); 1197a462745SAneesh Kumar K.V } 1207a462745SAneesh Kumar K.V } 121f6b7f0abSAneesh Kumar K.V return err; 122f6b7f0abSAneesh Kumar K.V } 123e4de4232SVenkateswararao Jujjuri 124bccacf6cSAneesh Kumar K.V int v9fs_co_open2(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name, gid_t gid, 12502cb7f3aSAneesh Kumar K.V int flags, int mode, struct stat *stbuf) 126e4de4232SVenkateswararao Jujjuri { 127e4de4232SVenkateswararao Jujjuri int err; 128e4de4232SVenkateswararao Jujjuri FsCred cred; 1292289be19SAneesh Kumar K.V V9fsPath path; 130bccacf6cSAneesh Kumar K.V V9fsState *s = pdu->s; 1312289be19SAneesh Kumar K.V 132bccacf6cSAneesh Kumar K.V if (v9fs_request_cancelled(pdu)) { 133bccacf6cSAneesh Kumar K.V return -EINTR; 134bccacf6cSAneesh Kumar K.V } 135e4de4232SVenkateswararao Jujjuri cred_init(&cred); 136e4de4232SVenkateswararao Jujjuri cred.fc_mode = mode & 07777; 137e4de4232SVenkateswararao Jujjuri cred.fc_uid = fidp->uid; 138e4de4232SVenkateswararao Jujjuri cred.fc_gid = gid; 13902cb7f3aSAneesh Kumar K.V /* 14002cb7f3aSAneesh Kumar K.V * Hold the directory fid lock so that directory path name 14102cb7f3aSAneesh Kumar K.V * don't change. Read lock is fine because this fid cannot 14202cb7f3aSAneesh Kumar K.V * be used by any other operation. 14302cb7f3aSAneesh Kumar K.V */ 144532decb7SAneesh Kumar K.V v9fs_path_read_lock(s); 145e4de4232SVenkateswararao Jujjuri v9fs_co_run_in_worker( 146e4de4232SVenkateswararao Jujjuri { 147cc720ddbSAneesh Kumar K.V err = s->ops->open2(&s->ctx, &fidp->path, 148cc720ddbSAneesh Kumar K.V name->data, flags, &cred, &fidp->fs); 149cc720ddbSAneesh Kumar K.V if (err < 0) { 150e4de4232SVenkateswararao Jujjuri err = -errno; 15102cb7f3aSAneesh Kumar K.V } else { 1522289be19SAneesh Kumar K.V v9fs_path_init(&path); 1532289be19SAneesh Kumar K.V err = v9fs_name_to_path(s, &fidp->path, name->data, &path); 1542289be19SAneesh Kumar K.V if (!err) { 1552289be19SAneesh Kumar K.V err = s->ops->lstat(&s->ctx, &path, stbuf); 15602cb7f3aSAneesh Kumar K.V if (err < 0) { 15702cb7f3aSAneesh Kumar K.V err = -errno; 158cc720ddbSAneesh Kumar K.V s->ops->close(&s->ctx, &fidp->fs); 15902cb7f3aSAneesh Kumar K.V } else { 1602289be19SAneesh Kumar K.V v9fs_path_copy(&fidp->path, &path); 16102cb7f3aSAneesh Kumar K.V } 1622289be19SAneesh Kumar K.V } else { 163cc720ddbSAneesh Kumar K.V s->ops->close(&s->ctx, &fidp->fs); 1642289be19SAneesh Kumar K.V } 1652289be19SAneesh Kumar K.V v9fs_path_free(&path); 166e4de4232SVenkateswararao Jujjuri } 167e4de4232SVenkateswararao Jujjuri }); 168532decb7SAneesh Kumar K.V v9fs_path_unlock(s); 1697a462745SAneesh Kumar K.V if (!err) { 1707a462745SAneesh Kumar K.V total_open_fd++; 1717a462745SAneesh Kumar K.V if (total_open_fd > open_fd_hw) { 172bccacf6cSAneesh Kumar K.V v9fs_reclaim_fd(pdu); 1737a462745SAneesh Kumar K.V } 1747a462745SAneesh Kumar K.V } 175e4de4232SVenkateswararao Jujjuri return err; 176e4de4232SVenkateswararao Jujjuri } 177bed4352cSAneesh Kumar K.V 178cc720ddbSAneesh Kumar K.V int v9fs_co_close(V9fsPDU *pdu, V9fsFidOpenState *fs) 179bed4352cSAneesh Kumar K.V { 180bed4352cSAneesh Kumar K.V int err; 181bccacf6cSAneesh Kumar K.V V9fsState *s = pdu->s; 182bed4352cSAneesh Kumar K.V 183bccacf6cSAneesh Kumar K.V if (v9fs_request_cancelled(pdu)) { 184bccacf6cSAneesh Kumar K.V return -EINTR; 185bccacf6cSAneesh Kumar K.V } 186bed4352cSAneesh Kumar K.V v9fs_co_run_in_worker( 187bed4352cSAneesh Kumar K.V { 188cc720ddbSAneesh Kumar K.V err = s->ops->close(&s->ctx, fs); 189bed4352cSAneesh Kumar K.V if (err < 0) { 190bed4352cSAneesh Kumar K.V err = -errno; 191bed4352cSAneesh Kumar K.V } 192bed4352cSAneesh Kumar K.V }); 1937a462745SAneesh Kumar K.V if (!err) { 1947a462745SAneesh Kumar K.V total_open_fd--; 1957a462745SAneesh Kumar K.V } 196bed4352cSAneesh Kumar K.V return err; 197bed4352cSAneesh Kumar K.V } 1984743d1f5SAneesh Kumar K.V 199bccacf6cSAneesh Kumar K.V int v9fs_co_fsync(V9fsPDU *pdu, V9fsFidState *fidp, int datasync) 2004743d1f5SAneesh Kumar K.V { 201cc720ddbSAneesh Kumar K.V int err; 202bccacf6cSAneesh Kumar K.V V9fsState *s = pdu->s; 2034743d1f5SAneesh Kumar K.V 204bccacf6cSAneesh Kumar K.V if (v9fs_request_cancelled(pdu)) { 205bccacf6cSAneesh Kumar K.V return -EINTR; 206bccacf6cSAneesh Kumar K.V } 2074743d1f5SAneesh Kumar K.V v9fs_co_run_in_worker( 2084743d1f5SAneesh Kumar K.V { 2098b888272SAneesh Kumar K.V err = s->ops->fsync(&s->ctx, fidp->fid_type, &fidp->fs, datasync); 2104743d1f5SAneesh Kumar K.V if (err < 0) { 2114743d1f5SAneesh Kumar K.V err = -errno; 2124743d1f5SAneesh Kumar K.V } 2134743d1f5SAneesh Kumar K.V }); 2144743d1f5SAneesh Kumar K.V return err; 2154743d1f5SAneesh Kumar K.V } 216c6c069b0SVenkateswararao Jujjuri 217bccacf6cSAneesh Kumar K.V int v9fs_co_link(V9fsPDU *pdu, V9fsFidState *oldfid, 2182289be19SAneesh Kumar K.V V9fsFidState *newdirfid, V9fsString *name) 219c6c069b0SVenkateswararao Jujjuri { 220c6c069b0SVenkateswararao Jujjuri int err; 221bccacf6cSAneesh Kumar K.V V9fsState *s = pdu->s; 222c6c069b0SVenkateswararao Jujjuri 223bccacf6cSAneesh Kumar K.V if (v9fs_request_cancelled(pdu)) { 224bccacf6cSAneesh Kumar K.V return -EINTR; 225bccacf6cSAneesh Kumar K.V } 226532decb7SAneesh Kumar K.V v9fs_path_read_lock(s); 227c6c069b0SVenkateswararao Jujjuri v9fs_co_run_in_worker( 228c6c069b0SVenkateswararao Jujjuri { 2292289be19SAneesh Kumar K.V err = s->ops->link(&s->ctx, &oldfid->path, 2302289be19SAneesh Kumar K.V &newdirfid->path, name->data); 231c6c069b0SVenkateswararao Jujjuri if (err < 0) { 232c6c069b0SVenkateswararao Jujjuri err = -errno; 233c6c069b0SVenkateswararao Jujjuri } 234c6c069b0SVenkateswararao Jujjuri }); 235532decb7SAneesh Kumar K.V v9fs_path_unlock(s); 236c6c069b0SVenkateswararao Jujjuri return err; 237c6c069b0SVenkateswararao Jujjuri } 238f6b3c976SAneesh Kumar K.V 239bccacf6cSAneesh Kumar K.V int v9fs_co_pwritev(V9fsPDU *pdu, V9fsFidState *fidp, 240f6b3c976SAneesh Kumar K.V struct iovec *iov, int iovcnt, int64_t offset) 241f6b3c976SAneesh Kumar K.V { 242cc720ddbSAneesh Kumar K.V int err; 243bccacf6cSAneesh Kumar K.V V9fsState *s = pdu->s; 244f6b3c976SAneesh Kumar K.V 245bccacf6cSAneesh Kumar K.V if (v9fs_request_cancelled(pdu)) { 246bccacf6cSAneesh Kumar K.V return -EINTR; 247bccacf6cSAneesh Kumar K.V } 248f6b3c976SAneesh Kumar K.V v9fs_co_run_in_worker( 249f6b3c976SAneesh Kumar K.V { 250cc720ddbSAneesh Kumar K.V err = s->ops->pwritev(&s->ctx, &fidp->fs, iov, iovcnt, offset); 251f6b3c976SAneesh Kumar K.V if (err < 0) { 252f6b3c976SAneesh Kumar K.V err = -errno; 253f6b3c976SAneesh Kumar K.V } 254f6b3c976SAneesh Kumar K.V }); 255f6b3c976SAneesh Kumar K.V return err; 256f6b3c976SAneesh Kumar K.V } 2577eafdcc9SAneesh Kumar K.V 258bccacf6cSAneesh Kumar K.V int v9fs_co_preadv(V9fsPDU *pdu, V9fsFidState *fidp, 2597eafdcc9SAneesh Kumar K.V struct iovec *iov, int iovcnt, int64_t offset) 2607eafdcc9SAneesh Kumar K.V { 261cc720ddbSAneesh Kumar K.V int err; 262bccacf6cSAneesh Kumar K.V V9fsState *s = pdu->s; 2637eafdcc9SAneesh Kumar K.V 264bccacf6cSAneesh Kumar K.V if (v9fs_request_cancelled(pdu)) { 265bccacf6cSAneesh Kumar K.V return -EINTR; 266bccacf6cSAneesh Kumar K.V } 2677eafdcc9SAneesh Kumar K.V v9fs_co_run_in_worker( 2687eafdcc9SAneesh Kumar K.V { 269cc720ddbSAneesh Kumar K.V err = s->ops->preadv(&s->ctx, &fidp->fs, iov, iovcnt, offset); 2707eafdcc9SAneesh Kumar K.V if (err < 0) { 2717eafdcc9SAneesh Kumar K.V err = -errno; 2727eafdcc9SAneesh Kumar K.V } 2737eafdcc9SAneesh Kumar K.V }); 2747eafdcc9SAneesh Kumar K.V return err; 2757eafdcc9SAneesh Kumar K.V } 276