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 "coth.h" 19 20 int coroutine_fn v9fs_co_readdir(V9fsPDU *pdu, V9fsFidState *fidp, 21 struct dirent **dent) 22 { 23 int err; 24 V9fsState *s = pdu->s; 25 26 if (v9fs_request_cancelled(pdu)) { 27 return -EINTR; 28 } 29 v9fs_co_run_in_worker( 30 { 31 struct dirent *entry; 32 33 errno = 0; 34 entry = s->ops->readdir(&s->ctx, &fidp->fs); 35 if (!entry && errno) { 36 err = -errno; 37 } else { 38 *dent = entry; 39 err = 0; 40 } 41 }); 42 return err; 43 } 44 45 off_t v9fs_co_telldir(V9fsPDU *pdu, V9fsFidState *fidp) 46 { 47 off_t err; 48 V9fsState *s = pdu->s; 49 50 if (v9fs_request_cancelled(pdu)) { 51 return -EINTR; 52 } 53 v9fs_co_run_in_worker( 54 { 55 err = s->ops->telldir(&s->ctx, &fidp->fs); 56 if (err < 0) { 57 err = -errno; 58 } 59 }); 60 return err; 61 } 62 63 void coroutine_fn v9fs_co_seekdir(V9fsPDU *pdu, V9fsFidState *fidp, 64 off_t offset) 65 { 66 V9fsState *s = pdu->s; 67 if (v9fs_request_cancelled(pdu)) { 68 return; 69 } 70 v9fs_co_run_in_worker( 71 { 72 s->ops->seekdir(&s->ctx, &fidp->fs, offset); 73 }); 74 } 75 76 void coroutine_fn v9fs_co_rewinddir(V9fsPDU *pdu, V9fsFidState *fidp) 77 { 78 V9fsState *s = pdu->s; 79 if (v9fs_request_cancelled(pdu)) { 80 return; 81 } 82 v9fs_co_run_in_worker( 83 { 84 s->ops->rewinddir(&s->ctx, &fidp->fs); 85 }); 86 } 87 88 int coroutine_fn v9fs_co_mkdir(V9fsPDU *pdu, V9fsFidState *fidp, 89 V9fsString *name, mode_t mode, uid_t uid, 90 gid_t gid, struct stat *stbuf) 91 { 92 int err; 93 FsCred cred; 94 V9fsPath path; 95 V9fsState *s = pdu->s; 96 97 if (v9fs_request_cancelled(pdu)) { 98 return -EINTR; 99 } 100 cred_init(&cred); 101 cred.fc_mode = mode; 102 cred.fc_uid = uid; 103 cred.fc_gid = gid; 104 v9fs_path_read_lock(s); 105 v9fs_co_run_in_worker( 106 { 107 err = s->ops->mkdir(&s->ctx, &fidp->path, name->data, &cred); 108 if (err < 0) { 109 err = -errno; 110 } else { 111 v9fs_path_init(&path); 112 err = v9fs_name_to_path(s, &fidp->path, name->data, &path); 113 if (!err) { 114 err = s->ops->lstat(&s->ctx, &path, stbuf); 115 if (err < 0) { 116 err = -errno; 117 } 118 } 119 v9fs_path_free(&path); 120 } 121 }); 122 v9fs_path_unlock(s); 123 return err; 124 } 125 126 int coroutine_fn v9fs_co_opendir(V9fsPDU *pdu, V9fsFidState *fidp) 127 { 128 int err; 129 V9fsState *s = pdu->s; 130 131 if (v9fs_request_cancelled(pdu)) { 132 return -EINTR; 133 } 134 v9fs_path_read_lock(s); 135 v9fs_co_run_in_worker( 136 { 137 err = s->ops->opendir(&s->ctx, &fidp->path, &fidp->fs); 138 if (err < 0) { 139 err = -errno; 140 } else { 141 err = 0; 142 } 143 }); 144 v9fs_path_unlock(s); 145 if (!err) { 146 total_open_fd++; 147 if (total_open_fd > open_fd_hw) { 148 v9fs_reclaim_fd(pdu); 149 } 150 } 151 return err; 152 } 153 154 int coroutine_fn v9fs_co_closedir(V9fsPDU *pdu, V9fsFidOpenState *fs) 155 { 156 int err; 157 V9fsState *s = pdu->s; 158 159 if (v9fs_request_cancelled(pdu)) { 160 return -EINTR; 161 } 162 v9fs_co_run_in_worker( 163 { 164 err = s->ops->closedir(&s->ctx, fs); 165 if (err < 0) { 166 err = -errno; 167 } 168 }); 169 if (!err) { 170 total_open_fd--; 171 } 172 return err; 173 } 174