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:
Linus Torvalds 2010-03-14 11:11:08 -07:00
commit ceb804cd0f
8 changed files with 96 additions and 22 deletions

View File

@ -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;
}

View File

@ -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);

View File

@ -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,

View File

@ -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);

View File

@ -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 */

View File

@ -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,
};

View File

@ -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))

View File

@ -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 = {