4 * Copyright IBM, Corp. 2010
7 * Anthony Liguori <aliguori@us.ibm.com>
9 * This work is licensed under the terms of the GNU GPL, version 2. See
10 * the COPYING file in the top-level directory.
14 #include "hw/virtio/virtio.h"
15 #include "hw/i386/pc.h"
16 #include "qemu/sockets.h"
17 #include "virtio-9p.h"
18 #include "fsdev/qemu-fsdev.h"
21 #include "hw/virtio/virtio-access.h"
23 static uint64_t virtio_9p_get_features(VirtIODevice
*vdev
, uint64_t features
,
26 virtio_add_feature(&features
, VIRTIO_9P_MOUNT_TAG
);
30 static void virtio_9p_get_config(VirtIODevice
*vdev
, uint8_t *config
)
33 struct virtio_9p_config
*cfg
;
34 V9fsState
*s
= VIRTIO_9P(vdev
);
37 cfg
= g_malloc0(sizeof(struct virtio_9p_config
) + len
);
38 virtio_stw_p(vdev
, &cfg
->tag_len
, len
);
39 /* We don't copy the terminating null to config space */
40 memcpy(cfg
->tag
, s
->tag
, len
);
41 memcpy(config
, cfg
, s
->config_size
);
45 static void virtio_9p_save(QEMUFile
*f
, void *opaque
)
47 virtio_save(VIRTIO_DEVICE(opaque
), f
);
50 static int virtio_9p_load(QEMUFile
*f
, void *opaque
, int version_id
)
52 return virtio_load(VIRTIO_DEVICE(opaque
), f
, version_id
);
55 static void virtio_9p_device_realize(DeviceState
*dev
, Error
**errp
)
57 VirtIODevice
*vdev
= VIRTIO_DEVICE(dev
);
58 V9fsState
*s
= VIRTIO_9P(dev
);
64 virtio_init(vdev
, "virtio-9p", VIRTIO_ID_9P
,
65 sizeof(struct virtio_9p_config
) + MAX_TAG_LEN
);
67 /* initialize pdu allocator */
68 QLIST_INIT(&s
->free_list
);
69 QLIST_INIT(&s
->active_list
);
70 for (i
= 0; i
< (MAX_REQ
- 1); i
++) {
71 QLIST_INSERT_HEAD(&s
->free_list
, &s
->pdus
[i
], next
);
74 s
->vq
= virtio_add_queue(vdev
, MAX_REQ
, handle_9p_output
);
76 v9fs_path_init(&path
);
78 fse
= get_fsdev_fsentry(s
->fsconf
.fsdev_id
);
81 /* We don't have a fsdev identified by fsdev_id */
82 error_setg(errp
, "Virtio-9p device couldn't find fsdev with the "
84 s
->fsconf
.fsdev_id
? s
->fsconf
.fsdev_id
: "NULL");
89 /* we haven't specified a mount_tag */
90 error_setg(errp
, "fsdev with id %s needs mount_tag arguments",
95 s
->ctx
.export_flags
= fse
->export_flags
;
96 s
->ctx
.fs_root
= g_strdup(fse
->path
);
97 s
->ctx
.exops
.get_st_gen
= NULL
;
98 len
= strlen(s
->fsconf
.tag
);
99 if (len
> MAX_TAG_LEN
- 1) {
100 error_setg(errp
, "mount tag '%s' (%d bytes) is longer than "
101 "maximum (%d bytes)", s
->fsconf
.tag
, len
, MAX_TAG_LEN
- 1);
105 s
->tag
= g_strdup(s
->fsconf
.tag
);
109 s
->config_size
= sizeof(struct virtio_9p_config
) + len
;
111 qemu_co_rwlock_init(&s
->rename_lock
);
113 if (s
->ops
->init(&s
->ctx
) < 0) {
114 error_setg(errp
, "Virtio-9p Failed to initialize fs-driver with id:%s"
115 " and export path:%s", s
->fsconf
.fsdev_id
, s
->ctx
.fs_root
);
120 * Check details of export path, We need to use fs driver
121 * call back to do that. Since we are in the init path, we don't
122 * use co-routines here.
124 if (s
->ops
->name_to_path(&s
->ctx
, NULL
, "/", &path
) < 0) {
126 "error in converting name to path %s", strerror(errno
));
129 if (s
->ops
->lstat(&s
->ctx
, &path
, &stat
)) {
130 error_setg(errp
, "share path %s does not exist", fse
->path
);
132 } else if (!S_ISDIR(stat
.st_mode
)) {
133 error_setg(errp
, "share path %s is not a directory", fse
->path
);
136 v9fs_path_free(&path
);
138 register_savevm(dev
, "virtio-9p", -1, 1, virtio_9p_save
, virtio_9p_load
, s
);
141 g_free(s
->ctx
.fs_root
);
143 virtio_cleanup(vdev
);
144 v9fs_path_free(&path
);
147 static void virtio_9p_device_unrealize(DeviceState
*dev
, Error
**errp
)
149 VirtIODevice
*vdev
= VIRTIO_DEVICE(dev
);
150 V9fsState
*s
= VIRTIO_9P(dev
);
152 virtio_cleanup(vdev
);
153 unregister_savevm(dev
, "virtio-9p", s
);
154 g_free(s
->ctx
.fs_root
);
158 /* virtio-9p device */
160 static Property virtio_9p_properties
[] = {
161 DEFINE_PROP_STRING("mount_tag", V9fsState
, fsconf
.tag
),
162 DEFINE_PROP_STRING("fsdev", V9fsState
, fsconf
.fsdev_id
),
163 DEFINE_PROP_END_OF_LIST(),
166 static void virtio_9p_class_init(ObjectClass
*klass
, void *data
)
168 DeviceClass
*dc
= DEVICE_CLASS(klass
);
169 VirtioDeviceClass
*vdc
= VIRTIO_DEVICE_CLASS(klass
);
171 dc
->props
= virtio_9p_properties
;
172 set_bit(DEVICE_CATEGORY_STORAGE
, dc
->categories
);
173 vdc
->realize
= virtio_9p_device_realize
;
174 vdc
->unrealize
= virtio_9p_device_unrealize
;
175 vdc
->get_features
= virtio_9p_get_features
;
176 vdc
->get_config
= virtio_9p_get_config
;
179 static const TypeInfo virtio_device_info
= {
180 .name
= TYPE_VIRTIO_9P
,
181 .parent
= TYPE_VIRTIO_DEVICE
,
182 .instance_size
= sizeof(V9fsState
),
183 .class_init
= virtio_9p_class_init
,
186 static void virtio_9p_register_types(void)
188 type_register_static(&virtio_device_info
);
191 type_init(virtio_9p_register_types
)