1 /* 2 * 9p backend 3 * 4 * Copyright IBM, Corp. 2011 5 * 6 * Authors: 7 * Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> 8 * 9 * This work is licensed under the terms of the GNU GPL, version 2. See 10 * the COPYING file in the top-level directory. 11 * 12 */ 13 14 #include "qemu/osdep.h" 15 #include "fsdev/qemu-fsdev.h" 16 #include "qemu/thread.h" 17 #include "qemu/coroutine.h" 18 #include "qemu/main-loop.h" 19 #include "coth.h" 20 21 int coroutine_fn v9fs_co_readdir(V9fsPDU *pdu, V9fsFidState *fidp, 22 struct dirent **dent) 23 { 24 int err; 25 V9fsState *s = pdu->s; 26 27 if (v9fs_request_cancelled(pdu)) { 28 return -EINTR; 29 } 30 v9fs_co_run_in_worker( 31 { 32 struct dirent *entry; 33 34 errno = 0; 35 entry = s->ops->readdir(&s->ctx, &fidp->fs); 36 if (!entry && errno) { 37 err = -errno; 38 } else { 39 *dent = entry; 40 err = 0; 41 } 42 }); 43 return err; 44 } 45 46 off_t v9fs_co_telldir(V9fsPDU *pdu, V9fsFidState *fidp) 47 { 48 off_t err; 49 V9fsState *s = pdu->s; 50 51 if (v9fs_request_cancelled(pdu)) { 52 return -EINTR; 53 } 54 v9fs_co_run_in_worker( 55 { 56 err = s->ops->telldir(&s->ctx, &fidp->fs); 57 if (err < 0) { 58 err = -errno; 59 } 60 }); 61 return err; 62 } 63 64 void coroutine_fn v9fs_co_seekdir(V9fsPDU *pdu, V9fsFidState *fidp, 65 off_t offset) 66 { 67 V9fsState *s = pdu->s; 68 if (v9fs_request_cancelled(pdu)) { 69 return; 70 } 71 v9fs_co_run_in_worker( 72 { 73 s->ops->seekdir(&s->ctx, &fidp->fs, offset); 74 }); 75 } 76 77 void coroutine_fn v9fs_co_rewinddir(V9fsPDU *pdu, V9fsFidState *fidp) 78 { 79 V9fsState *s = pdu->s; 80 if (v9fs_request_cancelled(pdu)) { 81 return; 82 } 83 v9fs_co_run_in_worker( 84 { 85 s->ops->rewinddir(&s->ctx, &fidp->fs); 86 }); 87 } 88 89 int coroutine_fn v9fs_co_mkdir(V9fsPDU *pdu, V9fsFidState *fidp, 90 V9fsString *name, mode_t mode, uid_t uid, 91 gid_t gid, struct stat *stbuf) 92 { 93 int err; 94 FsCred cred; 95 V9fsPath path; 96 V9fsState *s = pdu->s; 97 98 if (v9fs_request_cancelled(pdu)) { 99 return -EINTR; 100 } 101 cred_init(&cred); 102 cred.fc_mode = mode; 103 cred.fc_uid = uid; 104 cred.fc_gid = gid; 105 v9fs_path_read_lock(s); 106 v9fs_co_run_in_worker( 107 { 108 err = s->ops->mkdir(&s->ctx, &fidp->path, name->data, &cred); 109 if (err < 0) { 110 err = -errno; 111 } else { 112 v9fs_path_init(&path); 113 err = v9fs_name_to_path(s, &fidp->path, name->data, &path); 114 if (!err) { 115 err = s->ops->lstat(&s->ctx, &path, stbuf); 116 if (err < 0) { 117 err = -errno; 118 } 119 } 120 v9fs_path_free(&path); 121 } 122 }); 123 v9fs_path_unlock(s); 124 return err; 125 } 126 127 int coroutine_fn v9fs_co_opendir(V9fsPDU *pdu, V9fsFidState *fidp) 128 { 129 int err; 130 V9fsState *s = pdu->s; 131 132 if (v9fs_request_cancelled(pdu)) { 133 return -EINTR; 134 } 135 v9fs_path_read_lock(s); 136 v9fs_co_run_in_worker( 137 { 138 err = s->ops->opendir(&s->ctx, &fidp->path, &fidp->fs); 139 if (err < 0) { 140 err = -errno; 141 } else { 142 err = 0; 143 } 144 }); 145 v9fs_path_unlock(s); 146 if (!err) { 147 total_open_fd++; 148 if (total_open_fd > open_fd_hw) { 149 v9fs_reclaim_fd(pdu); 150 } 151 } 152 return err; 153 } 154 155 int coroutine_fn v9fs_co_closedir(V9fsPDU *pdu, V9fsFidOpenState *fs) 156 { 157 int err; 158 V9fsState *s = pdu->s; 159 160 if (v9fs_request_cancelled(pdu)) { 161 return -EINTR; 162 } 163 v9fs_co_run_in_worker( 164 { 165 err = s->ops->closedir(&s->ctx, fs); 166 if (err < 0) { 167 err = -errno; 168 } 169 }); 170 if (!err) { 171 total_open_fd--; 172 } 173 return err; 174 } 175