mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-09 23:00:21 +00:00
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs: 9p: Skip check for mandatory locks when unlocking 9p: Fixes a simple bug enabling writes beyond 2GB. 9p: Change the name of new protocol from 9p2010.L to 9p2000.L fs/9p: re-init the wstat in readdir loop net/9p: Add sysfs mount_tag file for virtio 9P device net/9p: Use the tag name in the config space for identifying mount point
This commit is contained in:
commit
ceb804cd0f
@ -24,7 +24,7 @@
|
|||||||
/**
|
/**
|
||||||
* enum p9_session_flags - option flags for each 9P session
|
* enum p9_session_flags - option flags for each 9P session
|
||||||
* @V9FS_PROTO_2000U: whether or not to use 9P2000.u extensions
|
* @V9FS_PROTO_2000U: whether or not to use 9P2000.u extensions
|
||||||
* @V9FS_PROTO_2010L: whether or not to use 9P2010.l extensions
|
* @V9FS_PROTO_2000L: whether or not to use 9P2000.l extensions
|
||||||
* @V9FS_ACCESS_SINGLE: only the mounting user can access the hierarchy
|
* @V9FS_ACCESS_SINGLE: only the mounting user can access the hierarchy
|
||||||
* @V9FS_ACCESS_USER: a new attach will be issued for every user (default)
|
* @V9FS_ACCESS_USER: a new attach will be issued for every user (default)
|
||||||
* @V9FS_ACCESS_ANY: use a single attach for all users
|
* @V9FS_ACCESS_ANY: use a single attach for all users
|
||||||
@ -34,7 +34,7 @@
|
|||||||
*/
|
*/
|
||||||
enum p9_session_flags {
|
enum p9_session_flags {
|
||||||
V9FS_PROTO_2000U = 0x01,
|
V9FS_PROTO_2000U = 0x01,
|
||||||
V9FS_PROTO_2010L = 0x02,
|
V9FS_PROTO_2000L = 0x02,
|
||||||
V9FS_ACCESS_SINGLE = 0x04,
|
V9FS_ACCESS_SINGLE = 0x04,
|
||||||
V9FS_ACCESS_USER = 0x08,
|
V9FS_ACCESS_USER = 0x08,
|
||||||
V9FS_ACCESS_ANY = 0x0C,
|
V9FS_ACCESS_ANY = 0x0C,
|
||||||
@ -130,5 +130,5 @@ static inline int v9fs_proto_dotu(struct v9fs_session_info *v9ses)
|
|||||||
|
|
||||||
static inline int v9fs_proto_dotl(struct v9fs_session_info *v9ses)
|
static inline int v9fs_proto_dotl(struct v9fs_session_info *v9ses)
|
||||||
{
|
{
|
||||||
return v9ses->flags & V9FS_PROTO_2010L;
|
return v9ses->flags & V9FS_PROTO_2000L;
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,15 @@ static inline int dt_type(struct p9_wstat *mistat)
|
|||||||
return rettype;
|
return rettype;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void p9stat_init(struct p9_wstat *stbuf)
|
||||||
|
{
|
||||||
|
stbuf->name = NULL;
|
||||||
|
stbuf->uid = NULL;
|
||||||
|
stbuf->gid = NULL;
|
||||||
|
stbuf->muid = NULL;
|
||||||
|
stbuf->extension = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* v9fs_dir_readdir - read a directory
|
* v9fs_dir_readdir - read a directory
|
||||||
* @filp: opened file structure
|
* @filp: opened file structure
|
||||||
@ -131,8 +140,8 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
|
|||||||
rdir->head = 0;
|
rdir->head = 0;
|
||||||
rdir->tail = err;
|
rdir->tail = err;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (rdir->head < rdir->tail) {
|
while (rdir->head < rdir->tail) {
|
||||||
|
p9stat_init(&st);
|
||||||
err = p9stat_read(rdir->buf + rdir->head,
|
err = p9stat_read(rdir->buf + rdir->head,
|
||||||
buflen - rdir->head, &st,
|
buflen - rdir->head, &st,
|
||||||
fid->clnt->proto_version);
|
fid->clnt->proto_version);
|
||||||
|
@ -114,7 +114,7 @@ static int v9fs_file_lock(struct file *filp, int cmd, struct file_lock *fl)
|
|||||||
P9_DPRINTK(P9_DEBUG_VFS, "filp: %p lock: %p\n", filp, fl);
|
P9_DPRINTK(P9_DEBUG_VFS, "filp: %p lock: %p\n", filp, fl);
|
||||||
|
|
||||||
/* No mandatory locks */
|
/* No mandatory locks */
|
||||||
if (__mandatory_lock(inode))
|
if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK)
|
||||||
return -ENOLCK;
|
return -ENOLCK;
|
||||||
|
|
||||||
if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) {
|
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,
|
|||||||
struct p9_fid *fid;
|
struct p9_fid *fid;
|
||||||
struct p9_client *clnt;
|
struct p9_client *clnt;
|
||||||
struct inode *inode = filp->f_path.dentry->d_inode;
|
struct inode *inode = filp->f_path.dentry->d_inode;
|
||||||
int origin = *offset;
|
loff_t origin = *offset;
|
||||||
unsigned long pg_start, pg_end;
|
unsigned long pg_start, pg_end;
|
||||||
|
|
||||||
P9_DPRINTK(P9_DEBUG_VFS, "data %p count %d offset %x\n", data,
|
P9_DPRINTK(P9_DEBUG_VFS, "data %p count %d offset %x\n", data,
|
||||||
|
@ -98,6 +98,7 @@ struct virtio_device {
|
|||||||
void *priv;
|
void *priv;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define dev_to_virtio(dev) container_of(dev, struct virtio_device, dev)
|
||||||
int register_virtio_device(struct virtio_device *dev);
|
int register_virtio_device(struct virtio_device *dev);
|
||||||
void unregister_virtio_device(struct virtio_device *dev);
|
void unregister_virtio_device(struct virtio_device *dev);
|
||||||
|
|
||||||
|
@ -5,4 +5,16 @@
|
|||||||
#include <linux/virtio_ids.h>
|
#include <linux/virtio_ids.h>
|
||||||
#include <linux/virtio_config.h>
|
#include <linux/virtio_config.h>
|
||||||
|
|
||||||
|
/* The feature bitmap for virtio 9P */
|
||||||
|
|
||||||
|
/* The mount point is specified in a config variable */
|
||||||
|
#define VIRTIO_9P_MOUNT_TAG 0
|
||||||
|
|
||||||
|
struct virtio_9p_config {
|
||||||
|
/* length of the tag name */
|
||||||
|
__u16 tag_len;
|
||||||
|
/* non-NULL terminated tag name */
|
||||||
|
__u8 tag[0];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
#endif /* _LINUX_VIRTIO_9P_H */
|
#endif /* _LINUX_VIRTIO_9P_H */
|
||||||
|
@ -32,13 +32,13 @@
|
|||||||
/** enum p9_proto_versions - 9P protocol versions
|
/** enum p9_proto_versions - 9P protocol versions
|
||||||
* @p9_proto_legacy: 9P Legacy mode, pre-9P2000.u
|
* @p9_proto_legacy: 9P Legacy mode, pre-9P2000.u
|
||||||
* @p9_proto_2000u: 9P2000.u extension
|
* @p9_proto_2000u: 9P2000.u extension
|
||||||
* @p9_proto_2010L: 9P2010.L extension
|
* @p9_proto_2000L: 9P2000.L extension
|
||||||
*/
|
*/
|
||||||
|
|
||||||
enum p9_proto_versions{
|
enum p9_proto_versions{
|
||||||
p9_proto_legacy = 0,
|
p9_proto_legacy = 0,
|
||||||
p9_proto_2000u = 1,
|
p9_proto_2000u = 1,
|
||||||
p9_proto_2010L = 2,
|
p9_proto_2000L = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ static const match_table_t tokens = {
|
|||||||
|
|
||||||
inline int p9_is_proto_dotl(struct p9_client *clnt)
|
inline int p9_is_proto_dotl(struct p9_client *clnt)
|
||||||
{
|
{
|
||||||
return (clnt->proto_version == p9_proto_2010L);
|
return (clnt->proto_version == p9_proto_2000L);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(p9_is_proto_dotl);
|
EXPORT_SYMBOL(p9_is_proto_dotl);
|
||||||
|
|
||||||
@ -80,9 +80,9 @@ static unsigned char get_protocol_version(const substring_t *name)
|
|||||||
} else if (!strncmp("9p2000.u", name->from, name->to-name->from)) {
|
} else if (!strncmp("9p2000.u", name->from, name->to-name->from)) {
|
||||||
version = p9_proto_2000u;
|
version = p9_proto_2000u;
|
||||||
P9_DPRINTK(P9_DEBUG_9P, "Protocol version: 9P2000.u\n");
|
P9_DPRINTK(P9_DEBUG_9P, "Protocol version: 9P2000.u\n");
|
||||||
} else if (!strncmp("9p2010.L", name->from, name->to-name->from)) {
|
} else if (!strncmp("9p2000.L", name->from, name->to-name->from)) {
|
||||||
version = p9_proto_2010L;
|
version = p9_proto_2000L;
|
||||||
P9_DPRINTK(P9_DEBUG_9P, "Protocol version: 9P2010.L\n");
|
P9_DPRINTK(P9_DEBUG_9P, "Protocol version: 9P2000.L\n");
|
||||||
} else {
|
} else {
|
||||||
P9_DPRINTK(P9_DEBUG_ERROR, "Unknown protocol version %s. ",
|
P9_DPRINTK(P9_DEBUG_ERROR, "Unknown protocol version %s. ",
|
||||||
name->from);
|
name->from);
|
||||||
@ -672,9 +672,9 @@ int p9_client_version(struct p9_client *c)
|
|||||||
c->msize, c->proto_version);
|
c->msize, c->proto_version);
|
||||||
|
|
||||||
switch (c->proto_version) {
|
switch (c->proto_version) {
|
||||||
case p9_proto_2010L:
|
case p9_proto_2000L:
|
||||||
req = p9_client_rpc(c, P9_TVERSION, "ds",
|
req = p9_client_rpc(c, P9_TVERSION, "ds",
|
||||||
c->msize, "9P2010.L");
|
c->msize, "9P2000.L");
|
||||||
break;
|
break;
|
||||||
case p9_proto_2000u:
|
case p9_proto_2000u:
|
||||||
req = p9_client_rpc(c, P9_TVERSION, "ds",
|
req = p9_client_rpc(c, P9_TVERSION, "ds",
|
||||||
@ -700,8 +700,8 @@ int p9_client_version(struct p9_client *c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
P9_DPRINTK(P9_DEBUG_9P, "<<< RVERSION msize %d %s\n", msize, version);
|
P9_DPRINTK(P9_DEBUG_9P, "<<< RVERSION msize %d %s\n", msize, version);
|
||||||
if (!strncmp(version, "9P2010.L", 8))
|
if (!strncmp(version, "9P2000.L", 8))
|
||||||
c->proto_version = p9_proto_2010L;
|
c->proto_version = p9_proto_2000L;
|
||||||
else if (!strncmp(version, "9P2000.u", 8))
|
else if (!strncmp(version, "9P2000.u", 8))
|
||||||
c->proto_version = p9_proto_2000u;
|
c->proto_version = p9_proto_2000u;
|
||||||
else if (!strncmp(version, "9P2000", 6))
|
else if (!strncmp(version, "9P2000", 6))
|
||||||
|
@ -78,6 +78,12 @@ struct virtio_chan {
|
|||||||
/* Scatterlist: can be too big for stack. */
|
/* Scatterlist: can be too big for stack. */
|
||||||
struct scatterlist sg[VIRTQUEUE_NUM];
|
struct scatterlist sg[VIRTQUEUE_NUM];
|
||||||
|
|
||||||
|
int tag_len;
|
||||||
|
/*
|
||||||
|
* tag name to identify a mount Non-null terminated
|
||||||
|
*/
|
||||||
|
char *tag;
|
||||||
|
|
||||||
struct list_head chan_list;
|
struct list_head chan_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -214,6 +220,20 @@ p9_virtio_request(struct p9_client *client, struct p9_req_t *req)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t p9_mount_tag_show(struct device *dev,
|
||||||
|
struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
struct virtio_chan *chan;
|
||||||
|
struct virtio_device *vdev;
|
||||||
|
|
||||||
|
vdev = dev_to_virtio(dev);
|
||||||
|
chan = vdev->priv;
|
||||||
|
|
||||||
|
return snprintf(buf, chan->tag_len + 1, "%s", chan->tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEVICE_ATTR(mount_tag, 0444, p9_mount_tag_show, NULL);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* p9_virtio_probe - probe for existence of 9P virtio channels
|
* p9_virtio_probe - probe for existence of 9P virtio channels
|
||||||
* @vdev: virtio device to probe
|
* @vdev: virtio device to probe
|
||||||
@ -224,6 +244,8 @@ p9_virtio_request(struct p9_client *client, struct p9_req_t *req)
|
|||||||
|
|
||||||
static int p9_virtio_probe(struct virtio_device *vdev)
|
static int p9_virtio_probe(struct virtio_device *vdev)
|
||||||
{
|
{
|
||||||
|
__u16 tag_len;
|
||||||
|
char *tag;
|
||||||
int err;
|
int err;
|
||||||
struct virtio_chan *chan;
|
struct virtio_chan *chan;
|
||||||
|
|
||||||
@ -248,6 +270,28 @@ static int p9_virtio_probe(struct virtio_device *vdev)
|
|||||||
sg_init_table(chan->sg, VIRTQUEUE_NUM);
|
sg_init_table(chan->sg, VIRTQUEUE_NUM);
|
||||||
|
|
||||||
chan->inuse = false;
|
chan->inuse = false;
|
||||||
|
if (virtio_has_feature(vdev, VIRTIO_9P_MOUNT_TAG)) {
|
||||||
|
vdev->config->get(vdev,
|
||||||
|
offsetof(struct virtio_9p_config, tag_len),
|
||||||
|
&tag_len, sizeof(tag_len));
|
||||||
|
} else {
|
||||||
|
err = -EINVAL;
|
||||||
|
goto out_free_vq;
|
||||||
|
}
|
||||||
|
tag = kmalloc(tag_len, GFP_KERNEL);
|
||||||
|
if (!tag) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto out_free_vq;
|
||||||
|
}
|
||||||
|
vdev->config->get(vdev, offsetof(struct virtio_9p_config, tag),
|
||||||
|
tag, tag_len);
|
||||||
|
chan->tag = tag;
|
||||||
|
chan->tag_len = tag_len;
|
||||||
|
err = sysfs_create_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr);
|
||||||
|
if (err) {
|
||||||
|
kfree(tag);
|
||||||
|
goto out_free_vq;
|
||||||
|
}
|
||||||
mutex_lock(&virtio_9p_lock);
|
mutex_lock(&virtio_9p_lock);
|
||||||
list_add_tail(&chan->chan_list, &virtio_chan_list);
|
list_add_tail(&chan->chan_list, &virtio_chan_list);
|
||||||
mutex_unlock(&virtio_9p_lock);
|
mutex_unlock(&virtio_9p_lock);
|
||||||
@ -284,7 +328,7 @@ p9_virtio_create(struct p9_client *client, const char *devname, char *args)
|
|||||||
|
|
||||||
mutex_lock(&virtio_9p_lock);
|
mutex_lock(&virtio_9p_lock);
|
||||||
list_for_each_entry(chan, &virtio_chan_list, chan_list) {
|
list_for_each_entry(chan, &virtio_chan_list, chan_list) {
|
||||||
if (!strcmp(devname, dev_name(&chan->vdev->dev))) {
|
if (!strncmp(devname, chan->tag, chan->tag_len)) {
|
||||||
if (!chan->inuse) {
|
if (!chan->inuse) {
|
||||||
chan->inuse = true;
|
chan->inuse = true;
|
||||||
found = 1;
|
found = 1;
|
||||||
@ -323,6 +367,8 @@ static void p9_virtio_remove(struct virtio_device *vdev)
|
|||||||
mutex_lock(&virtio_9p_lock);
|
mutex_lock(&virtio_9p_lock);
|
||||||
list_del(&chan->chan_list);
|
list_del(&chan->chan_list);
|
||||||
mutex_unlock(&virtio_9p_lock);
|
mutex_unlock(&virtio_9p_lock);
|
||||||
|
sysfs_remove_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr);
|
||||||
|
kfree(chan->tag);
|
||||||
kfree(chan);
|
kfree(chan);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -332,13 +378,19 @@ static struct virtio_device_id id_table[] = {
|
|||||||
{ 0 },
|
{ 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static unsigned int features[] = {
|
||||||
|
VIRTIO_9P_MOUNT_TAG,
|
||||||
|
};
|
||||||
|
|
||||||
/* The standard "struct lguest_driver": */
|
/* The standard "struct lguest_driver": */
|
||||||
static struct virtio_driver p9_virtio_drv = {
|
static struct virtio_driver p9_virtio_drv = {
|
||||||
.driver.name = KBUILD_MODNAME,
|
.feature_table = features,
|
||||||
.driver.owner = THIS_MODULE,
|
.feature_table_size = ARRAY_SIZE(features),
|
||||||
.id_table = id_table,
|
.driver.name = KBUILD_MODNAME,
|
||||||
.probe = p9_virtio_probe,
|
.driver.owner = THIS_MODULE,
|
||||||
.remove = p9_virtio_remove,
|
.id_table = id_table,
|
||||||
|
.probe = p9_virtio_probe,
|
||||||
|
.remove = p9_virtio_remove,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct p9_trans_module p9_virtio_trans = {
|
static struct p9_trans_module p9_virtio_trans = {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user