Revision 5e94c103

b/hw/virtio-9p.c
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] |
b/hw/virtio-9p.h
70 70
#define P9_NOFID    (u32)(~0)
71 71
#define P9_MAXWELEM 16
72 72

  
73
/*
74
 * ample room for Twrite/Rread header
75
 * size[4] Tread/Twrite tag[2] fid[4] offset[8] count[4]
76
 */
77
#define P9_IOHDRSZ 24
78

  
73 79
typedef struct V9fsPDU V9fsPDU;
74 80

  
75 81
struct V9fsPDU
......
154 160
    uint8_t *tag;
155 161
    size_t config_size;
156 162
    enum p9_proto_version proto_version;
163
    int32_t msize;
157 164
} V9fsState;
158 165

  
159 166
typedef struct V9fsCreateState {
......
167 174
    V9fsString name;
168 175
    V9fsString extension;
169 176
    V9fsString fullname;
177
    int iounit;
170 178
} V9fsCreateState;
171 179

  
172 180
typedef struct V9fsStatState {
......
197 205
    V9fsFidState *fidp;
198 206
    V9fsQID qid;
199 207
    struct stat stbuf;
208
    int iounit;
200 209
} V9fsOpenState;
201 210

  
202 211
typedef struct V9fsReadState {

Also available in: Unified diff