diff options
-rw-r--r-- | fs/9p/v9fs.h | 6 | ||||
-rw-r--r-- | fs/9p/vfs_dir.c | 11 | ||||
-rw-r--r-- | fs/9p/vfs_file.c | 4 | ||||
-rw-r--r-- | include/linux/virtio.h | 1 | ||||
-rw-r--r-- | include/linux/virtio_9p.h | 12 | ||||
-rw-r--r-- | include/net/9p/client.h | 4 | ||||
-rw-r--r-- | net/9p/client.c | 16 | ||||
-rw-r--r-- | net/9p/trans_virtio.c | 64 |
8 files changed, 96 insertions, 22 deletions
diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h index 79000bf62491..6b801d1ddf4b 100644 --- a/fs/9p/v9fs.h +++ b/fs/9p/v9fs.h | |||
@@ -24,7 +24,7 @@ | |||
24 | /** | 24 | /** |
25 | * enum p9_session_flags - option flags for each 9P session | 25 | * enum p9_session_flags - option flags for each 9P session |
26 | * @V9FS_PROTO_2000U: whether or not to use 9P2000.u extensions | 26 | * @V9FS_PROTO_2000U: whether or not to use 9P2000.u extensions |
27 | * @V9FS_PROTO_2010L: whether or not to use 9P2010.l extensions | 27 | * @V9FS_PROTO_2000L: whether or not to use 9P2000.l extensions |
28 | * @V9FS_ACCESS_SINGLE: only the mounting user can access the hierarchy | 28 | * @V9FS_ACCESS_SINGLE: only the mounting user can access the hierarchy |
29 | * @V9FS_ACCESS_USER: a new attach will be issued for every user (default) | 29 | * @V9FS_ACCESS_USER: a new attach will be issued for every user (default) |
30 | * @V9FS_ACCESS_ANY: use a single attach for all users | 30 | * @V9FS_ACCESS_ANY: use a single attach for all users |
@@ -34,7 +34,7 @@ | |||
34 | */ | 34 | */ |
35 | enum p9_session_flags { | 35 | enum p9_session_flags { |
36 | V9FS_PROTO_2000U = 0x01, | 36 | V9FS_PROTO_2000U = 0x01, |
37 | V9FS_PROTO_2010L = 0x02, | 37 | V9FS_PROTO_2000L = 0x02, |
38 | V9FS_ACCESS_SINGLE = 0x04, | 38 | V9FS_ACCESS_SINGLE = 0x04, |
39 | V9FS_ACCESS_USER = 0x08, | 39 | V9FS_ACCESS_USER = 0x08, |
40 | V9FS_ACCESS_ANY = 0x0C, | 40 | V9FS_ACCESS_ANY = 0x0C, |
@@ -130,5 +130,5 @@ static inline int v9fs_proto_dotu(struct v9fs_session_info *v9ses) | |||
130 | 130 | ||
131 | static inline int v9fs_proto_dotl(struct v9fs_session_info *v9ses) | 131 | static inline int v9fs_proto_dotl(struct v9fs_session_info *v9ses) |
132 | { | 132 | { |
133 | return v9ses->flags & V9FS_PROTO_2010L; | 133 | return v9ses->flags & V9FS_PROTO_2000L; |
134 | } | 134 | } |
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c index 6580aa449541..d8a3afe4ff72 100644 --- a/fs/9p/vfs_dir.c +++ b/fs/9p/vfs_dir.c | |||
@@ -76,6 +76,15 @@ static inline int dt_type(struct p9_wstat *mistat) | |||
76 | return rettype; | 76 | return rettype; |
77 | } | 77 | } |
78 | 78 | ||
79 | static void p9stat_init(struct p9_wstat *stbuf) | ||
80 | { | ||
81 | stbuf->name = NULL; | ||
82 | stbuf->uid = NULL; | ||
83 | stbuf->gid = NULL; | ||
84 | stbuf->muid = NULL; | ||
85 | stbuf->extension = NULL; | ||
86 | } | ||
87 | |||
79 | /** | 88 | /** |
80 | * v9fs_dir_readdir - read a directory | 89 | * v9fs_dir_readdir - read a directory |
81 | * @filp: opened file structure | 90 | * @filp: opened file structure |
@@ -131,8 +140,8 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
131 | rdir->head = 0; | 140 | rdir->head = 0; |
132 | rdir->tail = err; | 141 | rdir->tail = err; |
133 | } | 142 | } |
134 | |||
135 | while (rdir->head < rdir->tail) { | 143 | while (rdir->head < rdir->tail) { |
144 | p9stat_init(&st); | ||
136 | err = p9stat_read(rdir->buf + rdir->head, | 145 | err = p9stat_read(rdir->buf + rdir->head, |
137 | buflen - rdir->head, &st, | 146 | buflen - rdir->head, &st, |
138 | fid->clnt->proto_version); | 147 | fid->clnt->proto_version); |
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index 36122683fae8..df52d488d2a6 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c | |||
@@ -114,7 +114,7 @@ static int v9fs_file_lock(struct file *filp, int cmd, struct file_lock *fl) | |||
114 | P9_DPRINTK(P9_DEBUG_VFS, "filp: %p lock: %p\n", filp, fl); | 114 | P9_DPRINTK(P9_DEBUG_VFS, "filp: %p lock: %p\n", filp, fl); |
115 | 115 | ||
116 | /* No mandatory locks */ | 116 | /* No mandatory locks */ |
117 | if (__mandatory_lock(inode)) | 117 | if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK) |
118 | return -ENOLCK; | 118 | return -ENOLCK; |
119 | 119 | ||
120 | if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) { | 120 | if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) { |
@@ -215,7 +215,7 @@ v9fs_file_write(struct file *filp, const char __user * data, | |||
215 | struct p9_fid *fid; | 215 | struct p9_fid *fid; |
216 | struct p9_client *clnt; | 216 | struct p9_client *clnt; |
217 | struct inode *inode = filp->f_path.dentry->d_inode; | 217 | struct inode *inode = filp->f_path.dentry->d_inode; |
218 | int origin = *offset; | 218 | loff_t origin = *offset; |
219 | unsigned long pg_start, pg_end; | 219 | unsigned long pg_start, pg_end; |
220 | 220 | ||
221 | P9_DPRINTK(P9_DEBUG_VFS, "data %p count %d offset %x\n", data, | 221 | P9_DPRINTK(P9_DEBUG_VFS, "data %p count %d offset %x\n", data, |
diff --git a/include/linux/virtio.h b/include/linux/virtio.h index f508c651e53d..40d1709bdbf4 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h | |||
@@ -98,6 +98,7 @@ struct virtio_device { | |||
98 | void *priv; | 98 | void *priv; |
99 | }; | 99 | }; |
100 | 100 | ||
101 | #define dev_to_virtio(dev) container_of(dev, struct virtio_device, dev) | ||
101 | int register_virtio_device(struct virtio_device *dev); | 102 | int register_virtio_device(struct virtio_device *dev); |
102 | void unregister_virtio_device(struct virtio_device *dev); | 103 | void unregister_virtio_device(struct virtio_device *dev); |
103 | 104 | ||
diff --git a/include/linux/virtio_9p.h b/include/linux/virtio_9p.h index 332275080083..5cf11765146b 100644 --- a/include/linux/virtio_9p.h +++ b/include/linux/virtio_9p.h | |||
@@ -5,4 +5,16 @@ | |||
5 | #include <linux/virtio_ids.h> | 5 | #include <linux/virtio_ids.h> |
6 | #include <linux/virtio_config.h> | 6 | #include <linux/virtio_config.h> |
7 | 7 | ||
8 | /* The feature bitmap for virtio 9P */ | ||
9 | |||
10 | /* The mount point is specified in a config variable */ | ||
11 | #define VIRTIO_9P_MOUNT_TAG 0 | ||
12 | |||
13 | struct virtio_9p_config { | ||
14 | /* length of the tag name */ | ||
15 | __u16 tag_len; | ||
16 | /* non-NULL terminated tag name */ | ||
17 | __u8 tag[0]; | ||
18 | } __attribute__((packed)); | ||
19 | |||
8 | #endif /* _LINUX_VIRTIO_9P_H */ | 20 | #endif /* _LINUX_VIRTIO_9P_H */ |
diff --git a/include/net/9p/client.h b/include/net/9p/client.h index 52e1fff709e4..f076dfa75ae8 100644 --- a/include/net/9p/client.h +++ b/include/net/9p/client.h | |||
@@ -32,13 +32,13 @@ | |||
32 | /** enum p9_proto_versions - 9P protocol versions | 32 | /** enum p9_proto_versions - 9P protocol versions |
33 | * @p9_proto_legacy: 9P Legacy mode, pre-9P2000.u | 33 | * @p9_proto_legacy: 9P Legacy mode, pre-9P2000.u |
34 | * @p9_proto_2000u: 9P2000.u extension | 34 | * @p9_proto_2000u: 9P2000.u extension |
35 | * @p9_proto_2010L: 9P2010.L extension | 35 | * @p9_proto_2000L: 9P2000.L extension |
36 | */ | 36 | */ |
37 | 37 | ||
38 | enum p9_proto_versions{ | 38 | enum p9_proto_versions{ |
39 | p9_proto_legacy = 0, | 39 | p9_proto_legacy = 0, |
40 | p9_proto_2000u = 1, | 40 | p9_proto_2000u = 1, |
41 | p9_proto_2010L = 2, | 41 | p9_proto_2000L = 2, |
42 | }; | 42 | }; |
43 | 43 | ||
44 | 44 | ||
diff --git a/net/9p/client.c b/net/9p/client.c index bde9f3d38c57..e3e5bf4469ce 100644 --- a/net/9p/client.c +++ b/net/9p/client.c | |||
@@ -60,7 +60,7 @@ static const match_table_t tokens = { | |||
60 | 60 | ||
61 | inline int p9_is_proto_dotl(struct p9_client *clnt) | 61 | inline int p9_is_proto_dotl(struct p9_client *clnt) |
62 | { | 62 | { |
63 | return (clnt->proto_version == p9_proto_2010L); | 63 | return (clnt->proto_version == p9_proto_2000L); |
64 | } | 64 | } |
65 | EXPORT_SYMBOL(p9_is_proto_dotl); | 65 | EXPORT_SYMBOL(p9_is_proto_dotl); |
66 | 66 | ||
@@ -80,9 +80,9 @@ static unsigned char get_protocol_version(const substring_t *name) | |||
80 | } else if (!strncmp("9p2000.u", name->from, name->to-name->from)) { | 80 | } else if (!strncmp("9p2000.u", name->from, name->to-name->from)) { |
81 | version = p9_proto_2000u; | 81 | version = p9_proto_2000u; |
82 | P9_DPRINTK(P9_DEBUG_9P, "Protocol version: 9P2000.u\n"); | 82 | P9_DPRINTK(P9_DEBUG_9P, "Protocol version: 9P2000.u\n"); |
83 | } else if (!strncmp("9p2010.L", name->from, name->to-name->from)) { | 83 | } else if (!strncmp("9p2000.L", name->from, name->to-name->from)) { |
84 | version = p9_proto_2010L; | 84 | version = p9_proto_2000L; |
85 | P9_DPRINTK(P9_DEBUG_9P, "Protocol version: 9P2010.L\n"); | 85 | P9_DPRINTK(P9_DEBUG_9P, "Protocol version: 9P2000.L\n"); |
86 | } else { | 86 | } else { |
87 | P9_DPRINTK(P9_DEBUG_ERROR, "Unknown protocol version %s. ", | 87 | P9_DPRINTK(P9_DEBUG_ERROR, "Unknown protocol version %s. ", |
88 | name->from); | 88 | name->from); |
@@ -672,9 +672,9 @@ int p9_client_version(struct p9_client *c) | |||
672 | c->msize, c->proto_version); | 672 | c->msize, c->proto_version); |
673 | 673 | ||
674 | switch (c->proto_version) { | 674 | switch (c->proto_version) { |
675 | case p9_proto_2010L: | 675 | case p9_proto_2000L: |
676 | req = p9_client_rpc(c, P9_TVERSION, "ds", | 676 | req = p9_client_rpc(c, P9_TVERSION, "ds", |
677 | c->msize, "9P2010.L"); | 677 | c->msize, "9P2000.L"); |
678 | break; | 678 | break; |
679 | case p9_proto_2000u: | 679 | case p9_proto_2000u: |
680 | req = p9_client_rpc(c, P9_TVERSION, "ds", | 680 | req = p9_client_rpc(c, P9_TVERSION, "ds", |
@@ -700,8 +700,8 @@ int p9_client_version(struct p9_client *c) | |||
700 | } | 700 | } |
701 | 701 | ||
702 | P9_DPRINTK(P9_DEBUG_9P, "<<< RVERSION msize %d %s\n", msize, version); | 702 | P9_DPRINTK(P9_DEBUG_9P, "<<< RVERSION msize %d %s\n", msize, version); |
703 | if (!strncmp(version, "9P2010.L", 8)) | 703 | if (!strncmp(version, "9P2000.L", 8)) |
704 | c->proto_version = p9_proto_2010L; | 704 | c->proto_version = p9_proto_2000L; |
705 | else if (!strncmp(version, "9P2000.u", 8)) | 705 | else if (!strncmp(version, "9P2000.u", 8)) |
706 | c->proto_version = p9_proto_2000u; | 706 | c->proto_version = p9_proto_2000u; |
707 | else if (!strncmp(version, "9P2000", 6)) | 707 | else if (!strncmp(version, "9P2000", 6)) |
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index 0aaed4819379..afde1a89fbb3 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c | |||
@@ -78,6 +78,12 @@ struct virtio_chan { | |||
78 | /* Scatterlist: can be too big for stack. */ | 78 | /* Scatterlist: can be too big for stack. */ |
79 | struct scatterlist sg[VIRTQUEUE_NUM]; | 79 | struct scatterlist sg[VIRTQUEUE_NUM]; |
80 | 80 | ||
81 | int tag_len; | ||
82 | /* | ||
83 | * tag name to identify a mount Non-null terminated | ||
84 | */ | ||
85 | char *tag; | ||
86 | |||
81 | struct list_head chan_list; | 87 | struct list_head chan_list; |
82 | }; | 88 | }; |
83 | 89 | ||
@@ -214,6 +220,20 @@ p9_virtio_request(struct p9_client *client, struct p9_req_t *req) | |||
214 | return 0; | 220 | return 0; |
215 | } | 221 | } |
216 | 222 | ||
223 | static ssize_t p9_mount_tag_show(struct device *dev, | ||
224 | struct device_attribute *attr, char *buf) | ||
225 | { | ||
226 | struct virtio_chan *chan; | ||
227 | struct virtio_device *vdev; | ||
228 | |||
229 | vdev = dev_to_virtio(dev); | ||
230 | chan = vdev->priv; | ||
231 | |||
232 | return snprintf(buf, chan->tag_len + 1, "%s", chan->tag); | ||
233 | } | ||
234 | |||
235 | static DEVICE_ATTR(mount_tag, 0444, p9_mount_tag_show, NULL); | ||
236 | |||
217 | /** | 237 | /** |
218 | * p9_virtio_probe - probe for existence of 9P virtio channels | 238 | * p9_virtio_probe - probe for existence of 9P virtio channels |
219 | * @vdev: virtio device to probe | 239 | * @vdev: virtio device to probe |
@@ -224,6 +244,8 @@ p9_virtio_request(struct p9_client *client, struct p9_req_t *req) | |||
224 | 244 | ||
225 | static int p9_virtio_probe(struct virtio_device *vdev) | 245 | static int p9_virtio_probe(struct virtio_device *vdev) |
226 | { | 246 | { |
247 | __u16 tag_len; | ||
248 | char *tag; | ||
227 | int err; | 249 | int err; |
228 | struct virtio_chan *chan; | 250 | struct virtio_chan *chan; |
229 | 251 | ||
@@ -248,6 +270,28 @@ static int p9_virtio_probe(struct virtio_device *vdev) | |||
248 | sg_init_table(chan->sg, VIRTQUEUE_NUM); | 270 | sg_init_table(chan->sg, VIRTQUEUE_NUM); |
249 | 271 | ||
250 | chan->inuse = false; | 272 | chan->inuse = false; |
273 | if (virtio_has_feature(vdev, VIRTIO_9P_MOUNT_TAG)) { | ||
274 | vdev->config->get(vdev, | ||
275 | offsetof(struct virtio_9p_config, tag_len), | ||
276 | &tag_len, sizeof(tag_len)); | ||
277 | } else { | ||
278 | err = -EINVAL; | ||
279 | goto out_free_vq; | ||
280 | } | ||
281 | tag = kmalloc(tag_len, GFP_KERNEL); | ||
282 | if (!tag) { | ||
283 | err = -ENOMEM; | ||
284 | goto out_free_vq; | ||
285 | } | ||
286 | vdev->config->get(vdev, offsetof(struct virtio_9p_config, tag), | ||
287 | tag, tag_len); | ||
288 | chan->tag = tag; | ||
289 | chan->tag_len = tag_len; | ||
290 | err = sysfs_create_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); | ||
291 | if (err) { | ||
292 | kfree(tag); | ||
293 | goto out_free_vq; | ||
294 | } | ||
251 | mutex_lock(&virtio_9p_lock); | 295 | mutex_lock(&virtio_9p_lock); |
252 | list_add_tail(&chan->chan_list, &virtio_chan_list); | 296 | list_add_tail(&chan->chan_list, &virtio_chan_list); |
253 | mutex_unlock(&virtio_9p_lock); | 297 | mutex_unlock(&virtio_9p_lock); |
@@ -284,7 +328,7 @@ p9_virtio_create(struct p9_client *client, const char *devname, char *args) | |||
284 | 328 | ||
285 | mutex_lock(&virtio_9p_lock); | 329 | mutex_lock(&virtio_9p_lock); |
286 | list_for_each_entry(chan, &virtio_chan_list, chan_list) { | 330 | list_for_each_entry(chan, &virtio_chan_list, chan_list) { |
287 | if (!strcmp(devname, dev_name(&chan->vdev->dev))) { | 331 | if (!strncmp(devname, chan->tag, chan->tag_len)) { |
288 | if (!chan->inuse) { | 332 | if (!chan->inuse) { |
289 | chan->inuse = true; | 333 | chan->inuse = true; |
290 | found = 1; | 334 | found = 1; |
@@ -323,6 +367,8 @@ static void p9_virtio_remove(struct virtio_device *vdev) | |||
323 | mutex_lock(&virtio_9p_lock); | 367 | mutex_lock(&virtio_9p_lock); |
324 | list_del(&chan->chan_list); | 368 | list_del(&chan->chan_list); |
325 | mutex_unlock(&virtio_9p_lock); | 369 | mutex_unlock(&virtio_9p_lock); |
370 | sysfs_remove_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); | ||
371 | kfree(chan->tag); | ||
326 | kfree(chan); | 372 | kfree(chan); |
327 | 373 | ||
328 | } | 374 | } |
@@ -332,13 +378,19 @@ static struct virtio_device_id id_table[] = { | |||
332 | { 0 }, | 378 | { 0 }, |
333 | }; | 379 | }; |
334 | 380 | ||
381 | static unsigned int features[] = { | ||
382 | VIRTIO_9P_MOUNT_TAG, | ||
383 | }; | ||
384 | |||
335 | /* The standard "struct lguest_driver": */ | 385 | /* The standard "struct lguest_driver": */ |
336 | static struct virtio_driver p9_virtio_drv = { | 386 | static struct virtio_driver p9_virtio_drv = { |
337 | .driver.name = KBUILD_MODNAME, | 387 | .feature_table = features, |
338 | .driver.owner = THIS_MODULE, | 388 | .feature_table_size = ARRAY_SIZE(features), |
339 | .id_table = id_table, | 389 | .driver.name = KBUILD_MODNAME, |
340 | .probe = p9_virtio_probe, | 390 | .driver.owner = THIS_MODULE, |
341 | .remove = p9_virtio_remove, | 391 | .id_table = id_table, |
392 | .probe = p9_virtio_probe, | ||
393 | .remove = p9_virtio_remove, | ||
342 | }; | 394 | }; |
343 | 395 | ||
344 | static struct p9_trans_module p9_virtio_trans = { | 396 | static struct p9_trans_module p9_virtio_trans = { |