Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GIT PULL] v9fs fixes for 3.1-rc6 #10

Merged
merged 6 commits into from
Sep 7, 2011
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions fs/9p/v9fs_vfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 *);
Expand All @@ -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
36 changes: 28 additions & 8 deletions fs/9p/vfs_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}

Expand Down
139 changes: 87 additions & 52 deletions fs/9p/vfs_inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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)) {
Expand All @@ -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;
}

Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -335,7 +354,7 @@ int v9fs_init_inode(struct v9fs_session_info *v9ses,
*
*/

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;
Expand All @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 ... */
Expand Down Expand Up @@ -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;
Expand All @@ -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);
/*
Expand All @@ -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;
Expand Down
Loading