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