forked from Minki/linux
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
|
||||
* @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_USER: a new attach will be issued for every user (default)
|
||||
* @V9FS_ACCESS_ANY: use a single attach for all users
|
||||
@ -34,7 +34,7 @@
|
||||
*/
|
||||
enum p9_session_flags {
|
||||
V9FS_PROTO_2000U = 0x01,
|
||||
V9FS_PROTO_2010L = 0x02,
|
||||
V9FS_PROTO_2000L = 0x02,
|
||||
V9FS_ACCESS_SINGLE = 0x04,
|
||||
V9FS_ACCESS_USER = 0x08,
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
* @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->tail = err;
|
||||
}
|
||||
|
||||
while (rdir->head < rdir->tail) {
|
||||
p9stat_init(&st);
|
||||
err = p9stat_read(rdir->buf + rdir->head,
|
||||
buflen - rdir->head, &st,
|
||||
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);
|
||||
|
||||
/* No mandatory locks */
|
||||
if (__mandatory_lock(inode))
|
||||
if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK)
|
||||
return -ENOLCK;
|
||||
|
||||
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_client *clnt;
|
||||
struct inode *inode = filp->f_path.dentry->d_inode;
|
||||
int origin = *offset;
|
||||
loff_t origin = *offset;
|
||||
unsigned long pg_start, pg_end;
|
||||
|
||||
P9_DPRINTK(P9_DEBUG_VFS, "data %p count %d offset %x\n", data,
|
||||
|
@ -98,6 +98,7 @@ struct virtio_device {
|
||||
void *priv;
|
||||
};
|
||||
|
||||
#define dev_to_virtio(dev) container_of(dev, struct virtio_device, dev)
|
||||
int register_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_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 */
|
||||
|
@ -32,13 +32,13 @@
|
||||
/** enum p9_proto_versions - 9P protocol versions
|
||||
* @p9_proto_legacy: 9P Legacy mode, pre-9P2000.u
|
||||
* @p9_proto_2000u: 9P2000.u extension
|
||||
* @p9_proto_2010L: 9P2010.L extension
|
||||
* @p9_proto_2000L: 9P2000.L extension
|
||||
*/
|
||||
|
||||
enum p9_proto_versions{
|
||||
p9_proto_legacy = 0,
|
||||
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)
|
||||
{
|
||||
return (clnt->proto_version == p9_proto_2010L);
|
||||
return (clnt->proto_version == p9_proto_2000L);
|
||||
}
|
||||
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)) {
|
||||
version = p9_proto_2000u;
|
||||
P9_DPRINTK(P9_DEBUG_9P, "Protocol version: 9P2000.u\n");
|
||||
} else if (!strncmp("9p2010.L", name->from, name->to-name->from)) {
|
||||
version = p9_proto_2010L;
|
||||
P9_DPRINTK(P9_DEBUG_9P, "Protocol version: 9P2010.L\n");
|
||||
} else if (!strncmp("9p2000.L", name->from, name->to-name->from)) {
|
||||
version = p9_proto_2000L;
|
||||
P9_DPRINTK(P9_DEBUG_9P, "Protocol version: 9P2000.L\n");
|
||||
} else {
|
||||
P9_DPRINTK(P9_DEBUG_ERROR, "Unknown protocol version %s. ",
|
||||
name->from);
|
||||
@ -672,9 +672,9 @@ int p9_client_version(struct p9_client *c)
|
||||
c->msize, c->proto_version);
|
||||
|
||||
switch (c->proto_version) {
|
||||
case p9_proto_2010L:
|
||||
case p9_proto_2000L:
|
||||
req = p9_client_rpc(c, P9_TVERSION, "ds",
|
||||
c->msize, "9P2010.L");
|
||||
c->msize, "9P2000.L");
|
||||
break;
|
||||
case p9_proto_2000u:
|
||||
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);
|
||||
if (!strncmp(version, "9P2010.L", 8))
|
||||
c->proto_version = p9_proto_2010L;
|
||||
if (!strncmp(version, "9P2000.L", 8))
|
||||
c->proto_version = p9_proto_2000L;
|
||||
else if (!strncmp(version, "9P2000.u", 8))
|
||||
c->proto_version = p9_proto_2000u;
|
||||
else if (!strncmp(version, "9P2000", 6))
|
||||
|
@ -78,6 +78,12 @@ struct virtio_chan {
|
||||
/* Scatterlist: can be too big for stack. */
|
||||
struct scatterlist sg[VIRTQUEUE_NUM];
|
||||
|
||||
int tag_len;
|
||||
/*
|
||||
* tag name to identify a mount Non-null terminated
|
||||
*/
|
||||
char *tag;
|
||||
|
||||
struct list_head chan_list;
|
||||
};
|
||||
|
||||
@ -214,6 +220,20 @@ p9_virtio_request(struct p9_client *client, struct p9_req_t *req)
|
||||
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
|
||||
* @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)
|
||||
{
|
||||
__u16 tag_len;
|
||||
char *tag;
|
||||
int err;
|
||||
struct virtio_chan *chan;
|
||||
|
||||
@ -248,6 +270,28 @@ static int p9_virtio_probe(struct virtio_device *vdev)
|
||||
sg_init_table(chan->sg, VIRTQUEUE_NUM);
|
||||
|
||||
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);
|
||||
list_add_tail(&chan->chan_list, &virtio_chan_list);
|
||||
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);
|
||||
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) {
|
||||
chan->inuse = true;
|
||||
found = 1;
|
||||
@ -323,6 +367,8 @@ static void p9_virtio_remove(struct virtio_device *vdev)
|
||||
mutex_lock(&virtio_9p_lock);
|
||||
list_del(&chan->chan_list);
|
||||
mutex_unlock(&virtio_9p_lock);
|
||||
sysfs_remove_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr);
|
||||
kfree(chan->tag);
|
||||
kfree(chan);
|
||||
|
||||
}
|
||||
@ -332,13 +378,19 @@ static struct virtio_device_id id_table[] = {
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
static unsigned int features[] = {
|
||||
VIRTIO_9P_MOUNT_TAG,
|
||||
};
|
||||
|
||||
/* The standard "struct lguest_driver": */
|
||||
static struct virtio_driver p9_virtio_drv = {
|
||||
.driver.name = KBUILD_MODNAME,
|
||||
.driver.owner = THIS_MODULE,
|
||||
.id_table = id_table,
|
||||
.probe = p9_virtio_probe,
|
||||
.remove = p9_virtio_remove,
|
||||
.feature_table = features,
|
||||
.feature_table_size = ARRAY_SIZE(features),
|
||||
.driver.name = KBUILD_MODNAME,
|
||||
.driver.owner = THIS_MODULE,
|
||||
.id_table = id_table,
|
||||
.probe = p9_virtio_probe,
|
||||
.remove = p9_virtio_remove,
|
||||
};
|
||||
|
||||
static struct p9_trans_module p9_virtio_trans = {
|
||||
|
Loading…
Reference in New Issue
Block a user