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