253 |
253 |
return s->ops->fsync(&s->ctx, fd);
|
254 |
254 |
}
|
255 |
255 |
|
|
256 |
static int v9fs_do_statfs(V9fsState *s, V9fsString *path, struct statfs *stbuf)
|
|
257 |
{
|
|
258 |
return s->ops->statfs(&s->ctx, path->data, stbuf);
|
|
259 |
}
|
|
260 |
|
256 |
261 |
static void v9fs_string_init(V9fsString *str)
|
257 |
262 |
{
|
258 |
263 |
str->data = NULL;
|
... | ... | |
1019 |
1024 |
|
1020 |
1025 |
static void v9fs_version(V9fsState *s, V9fsPDU *pdu)
|
1021 |
1026 |
{
|
1022 |
|
int32_t msize;
|
1023 |
1027 |
V9fsString version;
|
1024 |
1028 |
size_t offset = 7;
|
1025 |
1029 |
|
1026 |
|
pdu_unmarshal(pdu, offset, "ds", &msize, &version);
|
|
1030 |
pdu_unmarshal(pdu, offset, "ds", &s->msize, &version);
|
1027 |
1031 |
|
1028 |
1032 |
if (!strcmp(version.data, "9P2000.u")) {
|
1029 |
1033 |
s->proto_version = V9FS_PROTO_2000U;
|
... | ... | |
1033 |
1037 |
v9fs_string_sprintf(&version, "unknown");
|
1034 |
1038 |
}
|
1035 |
1039 |
|
1036 |
|
offset += pdu_marshal(pdu, offset, "ds", msize, &version);
|
|
1040 |
offset += pdu_marshal(pdu, offset, "ds", s->msize, &version);
|
1037 |
1041 |
complete_pdu(s, pdu, offset);
|
1038 |
1042 |
|
1039 |
1043 |
v9fs_string_free(&version);
|
... | ... | |
1288 |
1292 |
v9fs_walk_complete(s, vs, err);
|
1289 |
1293 |
}
|
1290 |
1294 |
|
|
1295 |
static int32_t get_iounit(V9fsState *s, V9fsString *name)
|
|
1296 |
{
|
|
1297 |
struct statfs stbuf;
|
|
1298 |
int32_t iounit = 0;
|
|
1299 |
|
|
1300 |
/*
|
|
1301 |
* iounit should be multiples of f_bsize (host filesystem block size
|
|
1302 |
* and as well as less than (client msize - P9_IOHDRSZ))
|
|
1303 |
*/
|
|
1304 |
if (!v9fs_do_statfs(s, name, &stbuf)) {
|
|
1305 |
iounit = stbuf.f_bsize;
|
|
1306 |
iounit *= (s->msize - P9_IOHDRSZ)/stbuf.f_bsize;
|
|
1307 |
}
|
|
1308 |
|
|
1309 |
if (!iounit) {
|
|
1310 |
iounit = s->msize - P9_IOHDRSZ;
|
|
1311 |
}
|
|
1312 |
return iounit;
|
|
1313 |
}
|
|
1314 |
|
1291 |
1315 |
static void v9fs_open_post_opendir(V9fsState *s, V9fsOpenState *vs, int err)
|
1292 |
1316 |
{
|
1293 |
1317 |
if (vs->fidp->dir == NULL) {
|
... | ... | |
1303 |
1327 |
|
1304 |
1328 |
}
|
1305 |
1329 |
|
|
1330 |
static void v9fs_open_post_getiounit(V9fsState *s, V9fsOpenState *vs)
|
|
1331 |
{
|
|
1332 |
int err;
|
|
1333 |
vs->offset += pdu_marshal(vs->pdu, vs->offset, "Qd", &vs->qid, vs->iounit);
|
|
1334 |
err = vs->offset;
|
|
1335 |
complete_pdu(s, vs->pdu, err);
|
|
1336 |
qemu_free(vs);
|
|
1337 |
}
|
|
1338 |
|
1306 |
1339 |
static void v9fs_open_post_open(V9fsState *s, V9fsOpenState *vs, int err)
|
1307 |
1340 |
{
|
1308 |
1341 |
if (vs->fidp->fd == -1) {
|
... | ... | |
1310 |
1343 |
goto out;
|
1311 |
1344 |
}
|
1312 |
1345 |
|
1313 |
|
vs->offset += pdu_marshal(vs->pdu, vs->offset, "Qd", &vs->qid, 0);
|
1314 |
|
err = vs->offset;
|
|
1346 |
vs->iounit = get_iounit(s, &vs->fidp->path);
|
|
1347 |
v9fs_open_post_getiounit(s, vs);
|
|
1348 |
return;
|
1315 |
1349 |
out:
|
1316 |
1350 |
complete_pdu(s, vs->pdu, err);
|
1317 |
1351 |
qemu_free(vs);
|
... | ... | |
1794 |
1828 |
qemu_free(vs);
|
1795 |
1829 |
}
|
1796 |
1830 |
|
1797 |
|
static void v9fs_post_create(V9fsState *s, V9fsCreateState *vs, int err)
|
|
1831 |
static void v9fs_create_post_getiounit(V9fsState *s, V9fsCreateState *vs)
|
1798 |
1832 |
{
|
1799 |
|
if (err == 0) {
|
1800 |
|
v9fs_string_copy(&vs->fidp->path, &vs->fullname);
|
1801 |
|
stat_to_qid(&vs->stbuf, &vs->qid);
|
|
1833 |
int err;
|
|
1834 |
v9fs_string_copy(&vs->fidp->path, &vs->fullname);
|
|
1835 |
stat_to_qid(&vs->stbuf, &vs->qid);
|
1802 |
1836 |
|
1803 |
|
vs->offset += pdu_marshal(vs->pdu, vs->offset, "Qd", &vs->qid, 0);
|
|
1837 |
vs->offset += pdu_marshal(vs->pdu, vs->offset, "Qd", &vs->qid, vs->iounit);
|
|
1838 |
err = vs->offset;
|
1804 |
1839 |
|
1805 |
|
err = vs->offset;
|
|
1840 |
complete_pdu(s, vs->pdu, err);
|
|
1841 |
v9fs_string_free(&vs->name);
|
|
1842 |
v9fs_string_free(&vs->extension);
|
|
1843 |
v9fs_string_free(&vs->fullname);
|
|
1844 |
qemu_free(vs);
|
|
1845 |
}
|
|
1846 |
|
|
1847 |
static void v9fs_post_create(V9fsState *s, V9fsCreateState *vs, int err)
|
|
1848 |
{
|
|
1849 |
if (err == 0) {
|
|
1850 |
vs->iounit = get_iounit(s, &vs->fidp->path);
|
|
1851 |
v9fs_create_post_getiounit(s, vs);
|
|
1852 |
return;
|
1806 |
1853 |
}
|
1807 |
1854 |
|
1808 |
1855 |
complete_pdu(s, vs->pdu, err);
|
... | ... | |
2266 |
2313 |
qemu_free(vs);
|
2267 |
2314 |
}
|
2268 |
2315 |
|
2269 |
|
static int v9fs_do_statfs(V9fsState *s, V9fsString *path, struct statfs *stbuf)
|
2270 |
|
{
|
2271 |
|
return s->ops->statfs(&s->ctx, path->data, stbuf);
|
2272 |
|
}
|
2273 |
|
|
2274 |
2316 |
static void v9fs_statfs_post_statfs(V9fsState *s, V9fsStatfsState *vs, int err)
|
2275 |
2317 |
{
|
|
2318 |
int32_t bsize_factor;
|
|
2319 |
|
2276 |
2320 |
if (err) {
|
2277 |
2321 |
err = -errno;
|
2278 |
2322 |
goto out;
|
2279 |
2323 |
}
|
2280 |
2324 |
|
|
2325 |
/*
|
|
2326 |
* compute bsize factor based on host file system block size
|
|
2327 |
* and client msize
|
|
2328 |
*/
|
|
2329 |
bsize_factor = (s->msize - P9_IOHDRSZ)/vs->stbuf.f_bsize;
|
|
2330 |
if (!bsize_factor) {
|
|
2331 |
bsize_factor = 1;
|
|
2332 |
}
|
2281 |
2333 |
vs->v9statfs.f_type = vs->stbuf.f_type;
|
2282 |
2334 |
vs->v9statfs.f_bsize = vs->stbuf.f_bsize;
|
2283 |
|
vs->v9statfs.f_blocks = vs->stbuf.f_blocks;
|
2284 |
|
vs->v9statfs.f_bfree = vs->stbuf.f_bfree;
|
2285 |
|
vs->v9statfs.f_bavail = vs->stbuf.f_bavail;
|
|
2335 |
vs->v9statfs.f_bsize *= bsize_factor;
|
|
2336 |
/*
|
|
2337 |
* f_bsize is adjusted(multiplied) by bsize factor, so we need to
|
|
2338 |
* adjust(divide) the number of blocks, free blocks and available
|
|
2339 |
* blocks by bsize factor
|
|
2340 |
*/
|
|
2341 |
vs->v9statfs.f_blocks = vs->stbuf.f_blocks/bsize_factor;
|
|
2342 |
vs->v9statfs.f_bfree = vs->stbuf.f_bfree/bsize_factor;
|
|
2343 |
vs->v9statfs.f_bavail = vs->stbuf.f_bavail/bsize_factor;
|
2286 |
2344 |
vs->v9statfs.f_files = vs->stbuf.f_files;
|
2287 |
2345 |
vs->v9statfs.f_ffree = vs->stbuf.f_ffree;
|
2288 |
2346 |
vs->v9statfs.fsid_val = (unsigned int) vs->stbuf.f_fsid.__val[0] |
|