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