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: saving negative to unsigned char 9p: return on mutex_lock_interruptible() 9p: Creating files with names too long should fail with ENAMETOOLONG. 9p: Make sure we are able to clunk the cached fid on umount 9p: drop nlink remove fs/9p: Clunk the fid resulting from partial walk of the name 9p: documentation update 9p: Fix setting of protocol flags in v9fs_session_info structure.
This commit is contained in:
@@ -37,6 +37,15 @@ For Plan 9 From User Space applications (http://swtch.com/plan9)
|
|||||||
|
|
||||||
mount -t 9p `namespace`/acme /mnt/9 -o trans=unix,uname=$USER
|
mount -t 9p `namespace`/acme /mnt/9 -o trans=unix,uname=$USER
|
||||||
|
|
||||||
|
For server running on QEMU host with virtio transport:
|
||||||
|
|
||||||
|
mount -t 9p -o trans=virtio <mount_tag> /mnt/9
|
||||||
|
|
||||||
|
where mount_tag is the tag associated by the server to each of the exported
|
||||||
|
mount points. Each 9P export is seen by the client as a virtio device with an
|
||||||
|
associated "mount_tag" property. Available mount tags can be
|
||||||
|
seen by reading /sys/bus/virtio/drivers/9pnet_virtio/virtio<n>/mount_tag files.
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
=======
|
=======
|
||||||
|
|
||||||
@@ -47,7 +56,7 @@ OPTIONS
|
|||||||
fd - used passed file descriptors for connection
|
fd - used passed file descriptors for connection
|
||||||
(see rfdno and wfdno)
|
(see rfdno and wfdno)
|
||||||
virtio - connect to the next virtio channel available
|
virtio - connect to the next virtio channel available
|
||||||
(from lguest or KVM with trans_virtio module)
|
(from QEMU with trans_virtio module)
|
||||||
rdma - connect to a specified RDMA channel
|
rdma - connect to a specified RDMA channel
|
||||||
|
|
||||||
uname=name user name to attempt mount as on the remote server. The
|
uname=name user name to attempt mount as on the remote server. The
|
||||||
@@ -85,7 +94,12 @@ OPTIONS
|
|||||||
|
|
||||||
port=n port to connect to on the remote server
|
port=n port to connect to on the remote server
|
||||||
|
|
||||||
noextend force legacy mode (no 9p2000.u semantics)
|
noextend force legacy mode (no 9p2000.u or 9p2000.L semantics)
|
||||||
|
|
||||||
|
version=name Select 9P protocol version. Valid options are:
|
||||||
|
9p2000 - Legacy mode (same as noextend)
|
||||||
|
9p2000.u - Use 9P2000.u protocol
|
||||||
|
9p2000.L - Use 9P2000.L protocol
|
||||||
|
|
||||||
dfltuid attempt to mount as a particular uid
|
dfltuid attempt to mount as a particular uid
|
||||||
|
|
||||||
|
12
fs/9p/fid.c
12
fs/9p/fid.c
@@ -111,7 +111,7 @@ struct p9_fid *v9fs_fid_lookup(struct dentry *dentry)
|
|||||||
{
|
{
|
||||||
int i, n, l, clone, any, access;
|
int i, n, l, clone, any, access;
|
||||||
u32 uid;
|
u32 uid;
|
||||||
struct p9_fid *fid;
|
struct p9_fid *fid, *old_fid = NULL;
|
||||||
struct dentry *d, *ds;
|
struct dentry *d, *ds;
|
||||||
struct v9fs_session_info *v9ses;
|
struct v9fs_session_info *v9ses;
|
||||||
char **wnames, *uname;
|
char **wnames, *uname;
|
||||||
@@ -184,10 +184,18 @@ struct p9_fid *v9fs_fid_lookup(struct dentry *dentry)
|
|||||||
l = min(n - i, P9_MAXWELEM);
|
l = min(n - i, P9_MAXWELEM);
|
||||||
fid = p9_client_walk(fid, l, &wnames[i], clone);
|
fid = p9_client_walk(fid, l, &wnames[i], clone);
|
||||||
if (IS_ERR(fid)) {
|
if (IS_ERR(fid)) {
|
||||||
|
if (old_fid) {
|
||||||
|
/*
|
||||||
|
* If we fail, clunk fid which are mapping
|
||||||
|
* to path component and not the last component
|
||||||
|
* of the path.
|
||||||
|
*/
|
||||||
|
p9_client_clunk(old_fid);
|
||||||
|
}
|
||||||
kfree(wnames);
|
kfree(wnames);
|
||||||
return fid;
|
return fid;
|
||||||
}
|
}
|
||||||
|
old_fid = fid;
|
||||||
i += l;
|
i += l;
|
||||||
clone = 0;
|
clone = 0;
|
||||||
}
|
}
|
||||||
|
21
fs/9p/v9fs.c
21
fs/9p/v9fs.c
@@ -242,7 +242,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
|
|||||||
list_add(&v9ses->slist, &v9fs_sessionlist);
|
list_add(&v9ses->slist, &v9fs_sessionlist);
|
||||||
spin_unlock(&v9fs_sessionlist_lock);
|
spin_unlock(&v9fs_sessionlist_lock);
|
||||||
|
|
||||||
v9ses->flags = V9FS_PROTO_2000U | V9FS_ACCESS_USER;
|
v9ses->flags = V9FS_ACCESS_USER;
|
||||||
strcpy(v9ses->uname, V9FS_DEFUSER);
|
strcpy(v9ses->uname, V9FS_DEFUSER);
|
||||||
strcpy(v9ses->aname, V9FS_DEFANAME);
|
strcpy(v9ses->aname, V9FS_DEFANAME);
|
||||||
v9ses->uid = ~0;
|
v9ses->uid = ~0;
|
||||||
@@ -263,8 +263,10 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!p9_is_proto_dotu(v9ses->clnt))
|
if (p9_is_proto_dotl(v9ses->clnt))
|
||||||
v9ses->flags &= ~V9FS_PROTO_2000U;
|
v9ses->flags |= V9FS_PROTO_2000L;
|
||||||
|
else if (p9_is_proto_dotu(v9ses->clnt))
|
||||||
|
v9ses->flags |= V9FS_PROTO_2000U;
|
||||||
|
|
||||||
v9ses->maxdata = v9ses->clnt->msize - P9_IOHDRSZ;
|
v9ses->maxdata = v9ses->clnt->msize - P9_IOHDRSZ;
|
||||||
|
|
||||||
@@ -341,6 +343,19 @@ void v9fs_session_cancel(struct v9fs_session_info *v9ses) {
|
|||||||
p9_client_disconnect(v9ses->clnt);
|
p9_client_disconnect(v9ses->clnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* v9fs_session_begin_cancel - Begin terminate of a session
|
||||||
|
* @v9ses: session to terminate
|
||||||
|
*
|
||||||
|
* After this call we don't allow any request other than clunk.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void v9fs_session_begin_cancel(struct v9fs_session_info *v9ses)
|
||||||
|
{
|
||||||
|
P9_DPRINTK(P9_DEBUG_ERROR, "begin cancel session %p\n", v9ses);
|
||||||
|
p9_client_begin_disconnect(v9ses->clnt);
|
||||||
|
}
|
||||||
|
|
||||||
extern int v9fs_error_init(void);
|
extern int v9fs_error_init(void);
|
||||||
|
|
||||||
static struct kobject *v9fs_kobj;
|
static struct kobject *v9fs_kobj;
|
||||||
|
@@ -108,6 +108,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *, const char *,
|
|||||||
char *);
|
char *);
|
||||||
void v9fs_session_close(struct v9fs_session_info *v9ses);
|
void v9fs_session_close(struct v9fs_session_info *v9ses);
|
||||||
void v9fs_session_cancel(struct v9fs_session_info *v9ses);
|
void v9fs_session_cancel(struct v9fs_session_info *v9ses);
|
||||||
|
void v9fs_session_begin_cancel(struct v9fs_session_info *v9ses);
|
||||||
|
|
||||||
#define V9FS_MAGIC 0x01021997
|
#define V9FS_MAGIC 0x01021997
|
||||||
|
|
||||||
|
@@ -131,6 +131,8 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
|
|||||||
rdir = (struct p9_rdir *) fid->rdir;
|
rdir = (struct p9_rdir *) fid->rdir;
|
||||||
|
|
||||||
err = mutex_lock_interruptible(&rdir->mutex);
|
err = mutex_lock_interruptible(&rdir->mutex);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
while (err == 0) {
|
while (err == 0) {
|
||||||
if (rdir->tail == rdir->head) {
|
if (rdir->tail == rdir->head) {
|
||||||
err = v9fs_file_readn(filp, rdir->buf, NULL,
|
err = v9fs_file_readn(filp, rdir->buf, NULL,
|
||||||
|
@@ -432,6 +432,7 @@ error:
|
|||||||
|
|
||||||
static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir)
|
static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir)
|
||||||
{
|
{
|
||||||
|
int retval;
|
||||||
struct inode *file_inode;
|
struct inode *file_inode;
|
||||||
struct v9fs_session_info *v9ses;
|
struct v9fs_session_info *v9ses;
|
||||||
struct p9_fid *v9fid;
|
struct p9_fid *v9fid;
|
||||||
@@ -445,7 +446,10 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir)
|
|||||||
if (IS_ERR(v9fid))
|
if (IS_ERR(v9fid))
|
||||||
return PTR_ERR(v9fid);
|
return PTR_ERR(v9fid);
|
||||||
|
|
||||||
return p9_client_remove(v9fid);
|
retval = p9_client_remove(v9fid);
|
||||||
|
if (!retval)
|
||||||
|
drop_nlink(file_inode);
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -657,6 +661,9 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
|
|||||||
P9_DPRINTK(P9_DEBUG_VFS, "dir: %p dentry: (%s) %p nameidata: %p\n",
|
P9_DPRINTK(P9_DEBUG_VFS, "dir: %p dentry: (%s) %p nameidata: %p\n",
|
||||||
dir, dentry->d_name.name, dentry, nameidata);
|
dir, dentry->d_name.name, dentry, nameidata);
|
||||||
|
|
||||||
|
if (dentry->d_name.len > NAME_MAX)
|
||||||
|
return ERR_PTR(-ENAMETOOLONG);
|
||||||
|
|
||||||
sb = dir->i_sb;
|
sb = dir->i_sb;
|
||||||
v9ses = v9fs_inode2v9ses(dir);
|
v9ses = v9fs_inode2v9ses(dir);
|
||||||
dfid = v9fs_fid_lookup(dentry->d_parent);
|
dfid = v9fs_fid_lookup(dentry->d_parent);
|
||||||
|
@@ -194,6 +194,7 @@ static void v9fs_kill_super(struct super_block *s)
|
|||||||
|
|
||||||
kill_anon_super(s);
|
kill_anon_super(s);
|
||||||
|
|
||||||
|
v9fs_session_cancel(v9ses);
|
||||||
v9fs_session_close(v9ses);
|
v9fs_session_close(v9ses);
|
||||||
kfree(v9ses);
|
kfree(v9ses);
|
||||||
s->s_fs_info = NULL;
|
s->s_fs_info = NULL;
|
||||||
@@ -206,7 +207,7 @@ v9fs_umount_begin(struct super_block *sb)
|
|||||||
struct v9fs_session_info *v9ses;
|
struct v9fs_session_info *v9ses;
|
||||||
|
|
||||||
v9ses = sb->s_fs_info;
|
v9ses = sb->s_fs_info;
|
||||||
v9fs_session_cancel(v9ses);
|
v9fs_session_begin_cancel(v9ses);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct super_operations v9fs_super_ops = {
|
static const struct super_operations v9fs_super_ops = {
|
||||||
|
@@ -54,6 +54,7 @@ enum p9_proto_versions{
|
|||||||
|
|
||||||
enum p9_trans_status {
|
enum p9_trans_status {
|
||||||
Connected,
|
Connected,
|
||||||
|
BeginDisconnect,
|
||||||
Disconnected,
|
Disconnected,
|
||||||
Hung,
|
Hung,
|
||||||
};
|
};
|
||||||
@@ -198,6 +199,7 @@ int p9_client_version(struct p9_client *);
|
|||||||
struct p9_client *p9_client_create(const char *dev_name, char *options);
|
struct p9_client *p9_client_create(const char *dev_name, char *options);
|
||||||
void p9_client_destroy(struct p9_client *clnt);
|
void p9_client_destroy(struct p9_client *clnt);
|
||||||
void p9_client_disconnect(struct p9_client *clnt);
|
void p9_client_disconnect(struct p9_client *clnt);
|
||||||
|
void p9_client_begin_disconnect(struct p9_client *clnt);
|
||||||
struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
|
struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
|
||||||
char *uname, u32 n_uname, char *aname);
|
char *uname, u32 n_uname, char *aname);
|
||||||
struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname,
|
struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname,
|
||||||
|
@@ -72,9 +72,10 @@ inline int p9_is_proto_dotu(struct p9_client *clnt)
|
|||||||
EXPORT_SYMBOL(p9_is_proto_dotu);
|
EXPORT_SYMBOL(p9_is_proto_dotu);
|
||||||
|
|
||||||
/* Interpret mount option for protocol version */
|
/* Interpret mount option for protocol version */
|
||||||
static unsigned char get_protocol_version(const substring_t *name)
|
static int get_protocol_version(const substring_t *name)
|
||||||
{
|
{
|
||||||
unsigned char version = -EINVAL;
|
int version = -EINVAL;
|
||||||
|
|
||||||
if (!strncmp("9p2000", name->from, name->to-name->from)) {
|
if (!strncmp("9p2000", name->from, name->to-name->from)) {
|
||||||
version = p9_proto_legacy;
|
version = p9_proto_legacy;
|
||||||
P9_DPRINTK(P9_DEBUG_9P, "Protocol version: Legacy\n");
|
P9_DPRINTK(P9_DEBUG_9P, "Protocol version: Legacy\n");
|
||||||
@@ -534,7 +535,12 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
|
|||||||
|
|
||||||
P9_DPRINTK(P9_DEBUG_MUX, "client %p op %d\n", c, type);
|
P9_DPRINTK(P9_DEBUG_MUX, "client %p op %d\n", c, type);
|
||||||
|
|
||||||
if (c->status != Connected)
|
/* we allow for any status other than disconnected */
|
||||||
|
if (c->status == Disconnected)
|
||||||
|
return ERR_PTR(-EIO);
|
||||||
|
|
||||||
|
/* if status is begin_disconnected we allow only clunk request */
|
||||||
|
if ((c->status == BeginDisconnect) && (type != P9_TCLUNK))
|
||||||
return ERR_PTR(-EIO);
|
return ERR_PTR(-EIO);
|
||||||
|
|
||||||
if (signal_pending(current)) {
|
if (signal_pending(current)) {
|
||||||
@@ -800,8 +806,10 @@ void p9_client_destroy(struct p9_client *clnt)
|
|||||||
|
|
||||||
v9fs_put_trans(clnt->trans_mod);
|
v9fs_put_trans(clnt->trans_mod);
|
||||||
|
|
||||||
list_for_each_entry_safe(fid, fidptr, &clnt->fidlist, flist)
|
list_for_each_entry_safe(fid, fidptr, &clnt->fidlist, flist) {
|
||||||
|
printk(KERN_INFO "Found fid %d not clunked\n", fid->fid);
|
||||||
p9_fid_destroy(fid);
|
p9_fid_destroy(fid);
|
||||||
|
}
|
||||||
|
|
||||||
if (clnt->fidpool)
|
if (clnt->fidpool)
|
||||||
p9_idpool_destroy(clnt->fidpool);
|
p9_idpool_destroy(clnt->fidpool);
|
||||||
@@ -819,6 +827,13 @@ void p9_client_disconnect(struct p9_client *clnt)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(p9_client_disconnect);
|
EXPORT_SYMBOL(p9_client_disconnect);
|
||||||
|
|
||||||
|
void p9_client_begin_disconnect(struct p9_client *clnt)
|
||||||
|
{
|
||||||
|
P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt);
|
||||||
|
clnt->status = BeginDisconnect;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(p9_client_begin_disconnect);
|
||||||
|
|
||||||
struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
|
struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
|
||||||
char *uname, u32 n_uname, char *aname)
|
char *uname, u32 n_uname, char *aname)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user