Merge branch 'for-linus' of git://github.com/ericvh/linux
* 'for-linus' of git://github.com/ericvh/linux: fs/9p: Use protocol-defined value for lock/getlock 'type' field. fs/9p: Always ask new inode in lookup for cache mode disabled fs/9p: Add OS dependent open flags in 9p protocol net/9p: Fix kernel crash with msize 512K fs/9p: Don't update file type when updating file attributes fs/9p: Add fid before dentry instantiation
This commit is contained in:
commit
28c51ee3da
|
@ -54,9 +54,9 @@ extern struct kmem_cache *v9fs_inode_cache;
|
|||
|
||||
struct inode *v9fs_alloc_inode(struct super_block *sb);
|
||||
void v9fs_destroy_inode(struct inode *inode);
|
||||
struct inode *v9fs_get_inode(struct super_block *sb, int mode);
|
||||
struct inode *v9fs_get_inode(struct super_block *sb, int mode, dev_t);
|
||||
int v9fs_init_inode(struct v9fs_session_info *v9ses,
|
||||
struct inode *inode, int mode);
|
||||
struct inode *inode, int mode, dev_t);
|
||||
void v9fs_evict_inode(struct inode *inode);
|
||||
ino_t v9fs_qid2ino(struct p9_qid *qid);
|
||||
void v9fs_stat2inode(struct p9_wstat *, struct inode *, struct super_block *);
|
||||
|
@ -83,4 +83,6 @@ static inline void v9fs_invalidate_inode_attr(struct inode *inode)
|
|||
v9inode->cache_validity |= V9FS_INO_INVALID_ATTR;
|
||||
return;
|
||||
}
|
||||
|
||||
int v9fs_open_to_dotl_flags(int flags);
|
||||
#endif
|
||||
|
|
|
@ -65,7 +65,7 @@ int v9fs_file_open(struct inode *inode, struct file *file)
|
|||
v9inode = V9FS_I(inode);
|
||||
v9ses = v9fs_inode2v9ses(inode);
|
||||
if (v9fs_proto_dotl(v9ses))
|
||||
omode = file->f_flags;
|
||||
omode = v9fs_open_to_dotl_flags(file->f_flags);
|
||||
else
|
||||
omode = v9fs_uflags2omode(file->f_flags,
|
||||
v9fs_proto_dotu(v9ses));
|
||||
|
@ -169,7 +169,18 @@ static int v9fs_file_do_lock(struct file *filp, int cmd, struct file_lock *fl)
|
|||
|
||||
/* convert posix lock to p9 tlock args */
|
||||
memset(&flock, 0, sizeof(flock));
|
||||
flock.type = fl->fl_type;
|
||||
/* map the lock type */
|
||||
switch (fl->fl_type) {
|
||||
case F_RDLCK:
|
||||
flock.type = P9_LOCK_TYPE_RDLCK;
|
||||
break;
|
||||
case F_WRLCK:
|
||||
flock.type = P9_LOCK_TYPE_WRLCK;
|
||||
break;
|
||||
case F_UNLCK:
|
||||
flock.type = P9_LOCK_TYPE_UNLCK;
|
||||
break;
|
||||
}
|
||||
flock.start = fl->fl_start;
|
||||
if (fl->fl_end == OFFSET_MAX)
|
||||
flock.length = 0;
|
||||
|
@ -245,7 +256,7 @@ static int v9fs_file_getlock(struct file *filp, struct file_lock *fl)
|
|||
|
||||
/* convert posix lock to p9 tgetlock args */
|
||||
memset(&glock, 0, sizeof(glock));
|
||||
glock.type = fl->fl_type;
|
||||
glock.type = P9_LOCK_TYPE_UNLCK;
|
||||
glock.start = fl->fl_start;
|
||||
if (fl->fl_end == OFFSET_MAX)
|
||||
glock.length = 0;
|
||||
|
@ -257,17 +268,26 @@ static int v9fs_file_getlock(struct file *filp, struct file_lock *fl)
|
|||
res = p9_client_getlock_dotl(fid, &glock);
|
||||
if (res < 0)
|
||||
return res;
|
||||
if (glock.type != F_UNLCK) {
|
||||
fl->fl_type = glock.type;
|
||||
/* map 9p lock type to os lock type */
|
||||
switch (glock.type) {
|
||||
case P9_LOCK_TYPE_RDLCK:
|
||||
fl->fl_type = F_RDLCK;
|
||||
break;
|
||||
case P9_LOCK_TYPE_WRLCK:
|
||||
fl->fl_type = F_WRLCK;
|
||||
break;
|
||||
case P9_LOCK_TYPE_UNLCK:
|
||||
fl->fl_type = F_UNLCK;
|
||||
break;
|
||||
}
|
||||
if (glock.type != P9_LOCK_TYPE_UNLCK) {
|
||||
fl->fl_start = glock.start;
|
||||
if (glock.length == 0)
|
||||
fl->fl_end = OFFSET_MAX;
|
||||
else
|
||||
fl->fl_end = glock.start + glock.length - 1;
|
||||
fl->fl_pid = glock.proc_id;
|
||||
} else
|
||||
fl->fl_type = F_UNLCK;
|
||||
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -95,15 +95,18 @@ static int unixmode2p9mode(struct v9fs_session_info *v9ses, int mode)
|
|||
/**
|
||||
* p9mode2unixmode- convert plan9 mode bits to unix mode bits
|
||||
* @v9ses: v9fs session information
|
||||
* @mode: mode to convert
|
||||
* @stat: p9_wstat from which mode need to be derived
|
||||
* @rdev: major number, minor number in case of device files.
|
||||
*
|
||||
*/
|
||||
|
||||
static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode)
|
||||
static int p9mode2unixmode(struct v9fs_session_info *v9ses,
|
||||
struct p9_wstat *stat, dev_t *rdev)
|
||||
{
|
||||
int res;
|
||||
int mode = stat->mode;
|
||||
|
||||
res = mode & 0777;
|
||||
res = mode & S_IALLUGO;
|
||||
*rdev = 0;
|
||||
|
||||
if ((mode & P9_DMDIR) == P9_DMDIR)
|
||||
res |= S_IFDIR;
|
||||
|
@ -116,9 +119,26 @@ static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode)
|
|||
&& (v9ses->nodev == 0))
|
||||
res |= S_IFIFO;
|
||||
else if ((mode & P9_DMDEVICE) && (v9fs_proto_dotu(v9ses))
|
||||
&& (v9ses->nodev == 0))
|
||||
res |= S_IFBLK;
|
||||
else
|
||||
&& (v9ses->nodev == 0)) {
|
||||
char type = 0, ext[32];
|
||||
int major = -1, minor = -1;
|
||||
|
||||
strncpy(ext, stat->extension, sizeof(ext));
|
||||
sscanf(ext, "%c %u %u", &type, &major, &minor);
|
||||
switch (type) {
|
||||
case 'c':
|
||||
res |= S_IFCHR;
|
||||
break;
|
||||
case 'b':
|
||||
res |= S_IFBLK;
|
||||
break;
|
||||
default:
|
||||
P9_DPRINTK(P9_DEBUG_ERROR,
|
||||
"Unknown special type %c %s\n", type,
|
||||
stat->extension);
|
||||
};
|
||||
*rdev = MKDEV(major, minor);
|
||||
} else
|
||||
res |= S_IFREG;
|
||||
|
||||
if (v9fs_proto_dotu(v9ses)) {
|
||||
|
@ -131,7 +151,6 @@ static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode)
|
|||
if ((mode & P9_DMSETVTX) == P9_DMSETVTX)
|
||||
res |= S_ISVTX;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -242,13 +261,13 @@ void v9fs_destroy_inode(struct inode *inode)
|
|||
}
|
||||
|
||||
int v9fs_init_inode(struct v9fs_session_info *v9ses,
|
||||
struct inode *inode, int mode)
|
||||
struct inode *inode, int mode, dev_t rdev)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
inode_init_owner(inode, NULL, mode);
|
||||
inode->i_blocks = 0;
|
||||
inode->i_rdev = 0;
|
||||
inode->i_rdev = rdev;
|
||||
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
|
||||
inode->i_mapping->a_ops = &v9fs_addr_operations;
|
||||
|
||||
|
@ -335,7 +354,7 @@ error:
|
|||
*
|
||||
*/
|
||||
|
||||
struct inode *v9fs_get_inode(struct super_block *sb, int mode)
|
||||
struct inode *v9fs_get_inode(struct super_block *sb, int mode, dev_t rdev)
|
||||
{
|
||||
int err;
|
||||
struct inode *inode;
|
||||
|
@ -348,7 +367,7 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
|
|||
P9_EPRINTK(KERN_WARNING, "Problem allocating inode\n");
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
err = v9fs_init_inode(v9ses, inode, mode);
|
||||
err = v9fs_init_inode(v9ses, inode, mode, rdev);
|
||||
if (err) {
|
||||
iput(inode);
|
||||
return ERR_PTR(err);
|
||||
|
@ -435,11 +454,12 @@ void v9fs_evict_inode(struct inode *inode)
|
|||
static int v9fs_test_inode(struct inode *inode, void *data)
|
||||
{
|
||||
int umode;
|
||||
dev_t rdev;
|
||||
struct v9fs_inode *v9inode = V9FS_I(inode);
|
||||
struct p9_wstat *st = (struct p9_wstat *)data;
|
||||
struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
|
||||
|
||||
umode = p9mode2unixmode(v9ses, st->mode);
|
||||
umode = p9mode2unixmode(v9ses, st, &rdev);
|
||||
/* don't match inode of different type */
|
||||
if ((inode->i_mode & S_IFMT) != (umode & S_IFMT))
|
||||
return 0;
|
||||
|
@ -473,6 +493,7 @@ static struct inode *v9fs_qid_iget(struct super_block *sb,
|
|||
struct p9_wstat *st,
|
||||
int new)
|
||||
{
|
||||
dev_t rdev;
|
||||
int retval, umode;
|
||||
unsigned long i_ino;
|
||||
struct inode *inode;
|
||||
|
@ -496,8 +517,8 @@ static struct inode *v9fs_qid_iget(struct super_block *sb,
|
|||
* later.
|
||||
*/
|
||||
inode->i_ino = i_ino;
|
||||
umode = p9mode2unixmode(v9ses, st->mode);
|
||||
retval = v9fs_init_inode(v9ses, inode, umode);
|
||||
umode = p9mode2unixmode(v9ses, st, &rdev);
|
||||
retval = v9fs_init_inode(v9ses, inode, umode, rdev);
|
||||
if (retval)
|
||||
goto error;
|
||||
|
||||
|
@ -531,6 +552,19 @@ v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
|
|||
return inode;
|
||||
}
|
||||
|
||||
/**
|
||||
* v9fs_at_to_dotl_flags- convert Linux specific AT flags to
|
||||
* plan 9 AT flag.
|
||||
* @flags: flags to convert
|
||||
*/
|
||||
static int v9fs_at_to_dotl_flags(int flags)
|
||||
{
|
||||
int rflags = 0;
|
||||
if (flags & AT_REMOVEDIR)
|
||||
rflags |= P9_DOTL_AT_REMOVEDIR;
|
||||
return rflags;
|
||||
}
|
||||
|
||||
/**
|
||||
* v9fs_remove - helper function to remove files and directories
|
||||
* @dir: directory inode that is being deleted
|
||||
|
@ -558,7 +592,8 @@ static int v9fs_remove(struct inode *dir, struct dentry *dentry, int flags)
|
|||
return retval;
|
||||
}
|
||||
if (v9fs_proto_dotl(v9ses))
|
||||
retval = p9_client_unlinkat(dfid, dentry->d_name.name, flags);
|
||||
retval = p9_client_unlinkat(dfid, dentry->d_name.name,
|
||||
v9fs_at_to_dotl_flags(flags));
|
||||
if (retval == -EOPNOTSUPP) {
|
||||
/* Try the one based on path */
|
||||
v9fid = v9fs_fid_clone(dentry);
|
||||
|
@ -645,13 +680,11 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
|
|||
P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err);
|
||||
goto error;
|
||||
}
|
||||
d_instantiate(dentry, inode);
|
||||
err = v9fs_fid_add(dentry, fid);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
d_instantiate(dentry, inode);
|
||||
return ofid;
|
||||
|
||||
error:
|
||||
if (ofid)
|
||||
p9_client_clunk(ofid);
|
||||
|
@ -792,6 +825,7 @@ static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
|
|||
struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
|
||||
struct nameidata *nameidata)
|
||||
{
|
||||
struct dentry *res;
|
||||
struct super_block *sb;
|
||||
struct v9fs_session_info *v9ses;
|
||||
struct p9_fid *dfid, *fid;
|
||||
|
@ -823,22 +857,35 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
|
|||
|
||||
return ERR_PTR(result);
|
||||
}
|
||||
|
||||
inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb);
|
||||
/*
|
||||
* Make sure we don't use a wrong inode due to parallel
|
||||
* unlink. For cached mode create calls request for new
|
||||
* inode. But with cache disabled, lookup should do this.
|
||||
*/
|
||||
if (v9ses->cache)
|
||||
inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb);
|
||||
else
|
||||
inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
|
||||
if (IS_ERR(inode)) {
|
||||
result = PTR_ERR(inode);
|
||||
inode = NULL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
result = v9fs_fid_add(dentry, fid);
|
||||
if (result < 0)
|
||||
goto error_iput;
|
||||
|
||||
inst_out:
|
||||
d_add(dentry, inode);
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* If we had a rename on the server and a parallel lookup
|
||||
* for the new name, then make sure we instantiate with
|
||||
* the new name. ie look up for a/b, while on server somebody
|
||||
* moved b under k and client parallely did a lookup for
|
||||
* k/b.
|
||||
*/
|
||||
res = d_materialise_unique(dentry, inode);
|
||||
if (!IS_ERR(res))
|
||||
return res;
|
||||
result = PTR_ERR(res);
|
||||
error_iput:
|
||||
iput(inode);
|
||||
error:
|
||||
|
@ -1002,7 +1049,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
|
|||
return PTR_ERR(st);
|
||||
|
||||
v9fs_stat2inode(st, dentry->d_inode, dentry->d_inode->i_sb);
|
||||
generic_fillattr(dentry->d_inode, stat);
|
||||
generic_fillattr(dentry->d_inode, stat);
|
||||
|
||||
p9stat_free(st);
|
||||
kfree(st);
|
||||
|
@ -1086,6 +1133,7 @@ void
|
|||
v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
|
||||
struct super_block *sb)
|
||||
{
|
||||
mode_t mode;
|
||||
char ext[32];
|
||||
char tag_name[14];
|
||||
unsigned int i_nlink;
|
||||
|
@ -1121,31 +1169,9 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
|
|||
inode->i_nlink = i_nlink;
|
||||
}
|
||||
}
|
||||
inode->i_mode = p9mode2unixmode(v9ses, stat->mode);
|
||||
if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode))) {
|
||||
char type = 0;
|
||||
int major = -1;
|
||||
int minor = -1;
|
||||
|
||||
strncpy(ext, stat->extension, sizeof(ext));
|
||||
sscanf(ext, "%c %u %u", &type, &major, &minor);
|
||||
switch (type) {
|
||||
case 'c':
|
||||
inode->i_mode &= ~S_IFBLK;
|
||||
inode->i_mode |= S_IFCHR;
|
||||
break;
|
||||
case 'b':
|
||||
break;
|
||||
default:
|
||||
P9_DPRINTK(P9_DEBUG_ERROR,
|
||||
"Unknown special type %c %s\n", type,
|
||||
stat->extension);
|
||||
};
|
||||
inode->i_rdev = MKDEV(major, minor);
|
||||
init_special_inode(inode, inode->i_mode, inode->i_rdev);
|
||||
} else
|
||||
inode->i_rdev = 0;
|
||||
|
||||
mode = stat->mode & S_IALLUGO;
|
||||
mode |= inode->i_mode & ~S_IALLUGO;
|
||||
inode->i_mode = mode;
|
||||
i_size_write(inode, stat->length);
|
||||
|
||||
/* not real number of blocks, but 512 byte ones ... */
|
||||
|
@ -1411,6 +1437,8 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
|
|||
|
||||
int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode)
|
||||
{
|
||||
int umode;
|
||||
dev_t rdev;
|
||||
loff_t i_size;
|
||||
struct p9_wstat *st;
|
||||
struct v9fs_session_info *v9ses;
|
||||
|
@ -1419,6 +1447,12 @@ int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode)
|
|||
st = p9_client_stat(fid);
|
||||
if (IS_ERR(st))
|
||||
return PTR_ERR(st);
|
||||
/*
|
||||
* Don't update inode if the file type is different
|
||||
*/
|
||||
umode = p9mode2unixmode(v9ses, st, &rdev);
|
||||
if ((inode->i_mode & S_IFMT) != (umode & S_IFMT))
|
||||
goto out;
|
||||
|
||||
spin_lock(&inode->i_lock);
|
||||
/*
|
||||
|
@ -1430,6 +1464,7 @@ int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode)
|
|||
if (v9ses->cache)
|
||||
inode->i_size = i_size;
|
||||
spin_unlock(&inode->i_lock);
|
||||
out:
|
||||
p9stat_free(st);
|
||||
kfree(st);
|
||||
return 0;
|
||||
|
|
|
@ -153,7 +153,8 @@ static struct inode *v9fs_qid_iget_dotl(struct super_block *sb,
|
|||
* later.
|
||||
*/
|
||||
inode->i_ino = i_ino;
|
||||
retval = v9fs_init_inode(v9ses, inode, st->st_mode);
|
||||
retval = v9fs_init_inode(v9ses, inode,
|
||||
st->st_mode, new_decode_dev(st->st_rdev));
|
||||
if (retval)
|
||||
goto error;
|
||||
|
||||
|
@ -190,6 +191,58 @@ v9fs_inode_from_fid_dotl(struct v9fs_session_info *v9ses, struct p9_fid *fid,
|
|||
return inode;
|
||||
}
|
||||
|
||||
struct dotl_openflag_map {
|
||||
int open_flag;
|
||||
int dotl_flag;
|
||||
};
|
||||
|
||||
static int v9fs_mapped_dotl_flags(int flags)
|
||||
{
|
||||
int i;
|
||||
int rflags = 0;
|
||||
struct dotl_openflag_map dotl_oflag_map[] = {
|
||||
{ O_CREAT, P9_DOTL_CREATE },
|
||||
{ O_EXCL, P9_DOTL_EXCL },
|
||||
{ O_NOCTTY, P9_DOTL_NOCTTY },
|
||||
{ O_TRUNC, P9_DOTL_TRUNC },
|
||||
{ O_APPEND, P9_DOTL_APPEND },
|
||||
{ O_NONBLOCK, P9_DOTL_NONBLOCK },
|
||||
{ O_DSYNC, P9_DOTL_DSYNC },
|
||||
{ FASYNC, P9_DOTL_FASYNC },
|
||||
{ O_DIRECT, P9_DOTL_DIRECT },
|
||||
{ O_LARGEFILE, P9_DOTL_LARGEFILE },
|
||||
{ O_DIRECTORY, P9_DOTL_DIRECTORY },
|
||||
{ O_NOFOLLOW, P9_DOTL_NOFOLLOW },
|
||||
{ O_NOATIME, P9_DOTL_NOATIME },
|
||||
{ O_CLOEXEC, P9_DOTL_CLOEXEC },
|
||||
{ O_SYNC, P9_DOTL_SYNC},
|
||||
};
|
||||
for (i = 0; i < ARRAY_SIZE(dotl_oflag_map); i++) {
|
||||
if (flags & dotl_oflag_map[i].open_flag)
|
||||
rflags |= dotl_oflag_map[i].dotl_flag;
|
||||
}
|
||||
return rflags;
|
||||
}
|
||||
|
||||
/**
|
||||
* v9fs_open_to_dotl_flags- convert Linux specific open flags to
|
||||
* plan 9 open flag.
|
||||
* @flags: flags to convert
|
||||
*/
|
||||
int v9fs_open_to_dotl_flags(int flags)
|
||||
{
|
||||
int rflags = 0;
|
||||
|
||||
/*
|
||||
* We have same bits for P9_DOTL_READONLY, P9_DOTL_WRONLY
|
||||
* and P9_DOTL_NOACCESS
|
||||
*/
|
||||
rflags |= flags & O_ACCMODE;
|
||||
rflags |= v9fs_mapped_dotl_flags(flags);
|
||||
|
||||
return rflags;
|
||||
}
|
||||
|
||||
/**
|
||||
* v9fs_vfs_create_dotl - VFS hook to create files for 9P2000.L protocol.
|
||||
* @dir: directory inode that is being created
|
||||
|
@ -258,7 +311,8 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode,
|
|||
"Failed to get acl values in creat %d\n", err);
|
||||
goto error;
|
||||
}
|
||||
err = p9_client_create_dotl(ofid, name, flags, mode, gid, &qid);
|
||||
err = p9_client_create_dotl(ofid, name, v9fs_open_to_dotl_flags(flags),
|
||||
mode, gid, &qid);
|
||||
if (err < 0) {
|
||||
P9_DPRINTK(P9_DEBUG_VFS,
|
||||
"p9_client_open_dotl failed in creat %d\n",
|
||||
|
@ -281,10 +335,10 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode,
|
|||
P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err);
|
||||
goto error;
|
||||
}
|
||||
d_instantiate(dentry, inode);
|
||||
err = v9fs_fid_add(dentry, fid);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
d_instantiate(dentry, inode);
|
||||
|
||||
/* Now set the ACL based on the default value */
|
||||
v9fs_set_create_acl(dentry, &dacl, &pacl);
|
||||
|
@ -403,10 +457,10 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir,
|
|||
err);
|
||||
goto error;
|
||||
}
|
||||
d_instantiate(dentry, inode);
|
||||
err = v9fs_fid_add(dentry, fid);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
d_instantiate(dentry, inode);
|
||||
fid = NULL;
|
||||
} else {
|
||||
/*
|
||||
|
@ -414,7 +468,7 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir,
|
|||
* inode with stat. We need to get an inode
|
||||
* so that we can set the acl with dentry
|
||||
*/
|
||||
inode = v9fs_get_inode(dir->i_sb, mode);
|
||||
inode = v9fs_get_inode(dir->i_sb, mode, 0);
|
||||
if (IS_ERR(inode)) {
|
||||
err = PTR_ERR(inode);
|
||||
goto error;
|
||||
|
@ -540,6 +594,7 @@ int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr)
|
|||
void
|
||||
v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode)
|
||||
{
|
||||
mode_t mode;
|
||||
struct v9fs_inode *v9inode = V9FS_I(inode);
|
||||
|
||||
if ((stat->st_result_mask & P9_STATS_BASIC) == P9_STATS_BASIC) {
|
||||
|
@ -552,11 +607,10 @@ v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode)
|
|||
inode->i_uid = stat->st_uid;
|
||||
inode->i_gid = stat->st_gid;
|
||||
inode->i_nlink = stat->st_nlink;
|
||||
inode->i_mode = stat->st_mode;
|
||||
inode->i_rdev = new_decode_dev(stat->st_rdev);
|
||||
|
||||
if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode)))
|
||||
init_special_inode(inode, inode->i_mode, inode->i_rdev);
|
||||
mode = stat->st_mode & S_IALLUGO;
|
||||
mode |= inode->i_mode & ~S_IALLUGO;
|
||||
inode->i_mode = mode;
|
||||
|
||||
i_size_write(inode, stat->st_size);
|
||||
inode->i_blocks = stat->st_blocks;
|
||||
|
@ -657,14 +711,14 @@ v9fs_vfs_symlink_dotl(struct inode *dir, struct dentry *dentry,
|
|||
err);
|
||||
goto error;
|
||||
}
|
||||
d_instantiate(dentry, inode);
|
||||
err = v9fs_fid_add(dentry, fid);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
d_instantiate(dentry, inode);
|
||||
fid = NULL;
|
||||
} else {
|
||||
/* Not in cached mode. No need to populate inode with stat */
|
||||
inode = v9fs_get_inode(dir->i_sb, S_IFLNK);
|
||||
inode = v9fs_get_inode(dir->i_sb, S_IFLNK, 0);
|
||||
if (IS_ERR(inode)) {
|
||||
err = PTR_ERR(inode);
|
||||
goto error;
|
||||
|
@ -810,17 +864,17 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int omode,
|
|||
err);
|
||||
goto error;
|
||||
}
|
||||
d_instantiate(dentry, inode);
|
||||
err = v9fs_fid_add(dentry, fid);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
d_instantiate(dentry, inode);
|
||||
fid = NULL;
|
||||
} else {
|
||||
/*
|
||||
* Not in cached mode. No need to populate inode with stat.
|
||||
* socket syscall returns a fd, so we need instantiate
|
||||
*/
|
||||
inode = v9fs_get_inode(dir->i_sb, mode);
|
||||
inode = v9fs_get_inode(dir->i_sb, mode, rdev);
|
||||
if (IS_ERR(inode)) {
|
||||
err = PTR_ERR(inode);
|
||||
goto error;
|
||||
|
@ -886,6 +940,11 @@ int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode)
|
|||
st = p9_client_getattr_dotl(fid, P9_STATS_ALL);
|
||||
if (IS_ERR(st))
|
||||
return PTR_ERR(st);
|
||||
/*
|
||||
* Don't update inode if the file type is different
|
||||
*/
|
||||
if ((inode->i_mode & S_IFMT) != (st->st_mode & S_IFMT))
|
||||
goto out;
|
||||
|
||||
spin_lock(&inode->i_lock);
|
||||
/*
|
||||
|
@ -897,6 +956,7 @@ int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode)
|
|||
if (v9ses->cache)
|
||||
inode->i_size = i_size;
|
||||
spin_unlock(&inode->i_lock);
|
||||
out:
|
||||
kfree(st);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -149,7 +149,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
|
|||
else
|
||||
sb->s_d_op = &v9fs_dentry_operations;
|
||||
|
||||
inode = v9fs_get_inode(sb, S_IFDIR | mode);
|
||||
inode = v9fs_get_inode(sb, S_IFDIR | mode, 0);
|
||||
if (IS_ERR(inode)) {
|
||||
retval = PTR_ERR(inode);
|
||||
goto release_sb;
|
||||
|
|
|
@ -288,6 +288,35 @@ enum p9_perm_t {
|
|||
P9_DMSETVTX = 0x00010000,
|
||||
};
|
||||
|
||||
/* 9p2000.L open flags */
|
||||
#define P9_DOTL_RDONLY 00000000
|
||||
#define P9_DOTL_WRONLY 00000001
|
||||
#define P9_DOTL_RDWR 00000002
|
||||
#define P9_DOTL_NOACCESS 00000003
|
||||
#define P9_DOTL_CREATE 00000100
|
||||
#define P9_DOTL_EXCL 00000200
|
||||
#define P9_DOTL_NOCTTY 00000400
|
||||
#define P9_DOTL_TRUNC 00001000
|
||||
#define P9_DOTL_APPEND 00002000
|
||||
#define P9_DOTL_NONBLOCK 00004000
|
||||
#define P9_DOTL_DSYNC 00010000
|
||||
#define P9_DOTL_FASYNC 00020000
|
||||
#define P9_DOTL_DIRECT 00040000
|
||||
#define P9_DOTL_LARGEFILE 00100000
|
||||
#define P9_DOTL_DIRECTORY 00200000
|
||||
#define P9_DOTL_NOFOLLOW 00400000
|
||||
#define P9_DOTL_NOATIME 01000000
|
||||
#define P9_DOTL_CLOEXEC 02000000
|
||||
#define P9_DOTL_SYNC 04000000
|
||||
|
||||
/* 9p2000.L at flags */
|
||||
#define P9_DOTL_AT_REMOVEDIR 0x200
|
||||
|
||||
/* 9p2000.L lock type */
|
||||
#define P9_LOCK_TYPE_RDLCK 0
|
||||
#define P9_LOCK_TYPE_WRLCK 1
|
||||
#define P9_LOCK_TYPE_UNLCK 2
|
||||
|
||||
/**
|
||||
* enum p9_qid_t - QID types
|
||||
* @P9_QTDIR: directory
|
||||
|
|
|
@ -263,7 +263,6 @@ p9_virtio_request(struct p9_client *client, struct p9_req_t *req)
|
|||
{
|
||||
int in, out, inp, outp;
|
||||
struct virtio_chan *chan = client->trans;
|
||||
char *rdata = (char *)req->rc+sizeof(struct p9_fcall);
|
||||
unsigned long flags;
|
||||
size_t pdata_off = 0;
|
||||
struct trans_rpage_info *rpinfo = NULL;
|
||||
|
@ -346,7 +345,8 @@ req_retry_pinned:
|
|||
* Arrange in such a way that server places header in the
|
||||
* alloced memory and payload onto the user buffer.
|
||||
*/
|
||||
inp = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM, rdata, 11);
|
||||
inp = pack_sg_list(chan->sg, out,
|
||||
VIRTQUEUE_NUM, req->rc->sdata, 11);
|
||||
/*
|
||||
* Running executables in the filesystem may result in
|
||||
* a read request with kernel buffer as opposed to user buffer.
|
||||
|
@ -366,8 +366,8 @@ req_retry_pinned:
|
|||
}
|
||||
in += inp;
|
||||
} else {
|
||||
in = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM, rdata,
|
||||
req->rc->capacity);
|
||||
in = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM,
|
||||
req->rc->sdata, req->rc->capacity);
|
||||
}
|
||||
|
||||
err = virtqueue_add_buf(chan->vq, chan->sg, out, in, req->tc);
|
||||
|
@ -592,7 +592,14 @@ static struct p9_trans_module p9_virtio_trans = {
|
|||
.close = p9_virtio_close,
|
||||
.request = p9_virtio_request,
|
||||
.cancel = p9_virtio_cancel,
|
||||
.maxsize = PAGE_SIZE*VIRTQUEUE_NUM,
|
||||
|
||||
/*
|
||||
* We leave one entry for input and one entry for response
|
||||
* headers. We also skip one more entry to accomodate, address
|
||||
* that are not at page boundary, that can result in an extra
|
||||
* page in zero copy.
|
||||
*/
|
||||
.maxsize = PAGE_SIZE * (VIRTQUEUE_NUM - 3),
|
||||
.pref = P9_TRANS_PREF_PAYLOAD_SEP,
|
||||
.def = 0,
|
||||
.owner = THIS_MODULE,
|
||||
|
|
Loading…
Reference in New Issue