Pull request for inlusion in 5.1
Two fixes (leak on invalid mount argument and possible deadlock on i_size update on 32bit smp) and a fall-through warning cleanup ---------------------------------------------------------------- Gustavo A. R. Silva (1): 9p: mark expected switch fall-through Hou Tao (1): 9p: use inode->i_lock to protect i_size_write() under 32-bit zhengbin (1): 9p/net: fix memory leak in p9_client_create fs/9p/v9fs_vfs.h | 23 +++++++++++++++++++++-- fs/9p/vfs_file.c | 6 +++++- fs/9p/vfs_inode.c | 23 +++++++++++------------ fs/9p/vfs_inode_dotl.c | 27 ++++++++++++++------------- fs/9p/vfs_super.c | 4 ++-- net/9p/client.c | 2 +- net/9p/trans_xen.c | 2 +- 7 files changed, 55 insertions(+), 32 deletions(-) -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEE/IPbcYBuWt0zoYhOq06b7GqY5nAFAlyOVo4ACgkQq06b7GqY 5nC7tQ//SJfSH6ooQE6nZywokUKpgXSzEPKHI6krI2lj8XuqL5r6iSQMqKwaWXFt h2onfPKtp+SHJaCnW82G9P54IvmiS9sMt6kRzGvFR0Gz93Cy4koIRc2TmAZLIw3N Gmyb7oEzUSmH8mJMt0qrlyxTzQEMhainWjod4QSmwuhJe9rndox+aBsNnFb7UOJw 2bbV8T2j8amrF124VkK8wsglIpbKGJjDBAsfZ1ZHaWks2XqaNGDIvSIXse38WUhi rmOswBo1ZJBqS/FyojWW9hhtGmGSM9TgAzNdMABAZvjgmoWCk4xyO/6H95O8iL6Q Jp4XevUBcdwJWSp9VKeILLOyGx2UjkYy3KLuLnwyQUATDqDf+avdaiZC+Z0P/ulC l1fHgqK5E1wks328OvtO+kjFGqgiGzXfE1MnEmbFopvX3nqBr0yx8w4GdYm9irb9 7PKz7HoGkOVuwhveNAQHR/Q58Mc/kxfOKvoRb19r5cM+pynFbWL9p4kFtG2Wc7sE y2xZ9jKKvoTh6BmAfkQTwJmGWDYWr3iSTq3YF5B7bNd8S9omzlY0e0PxOs0NHfMb wCoZhBRTAdv2NJvN2Q2nQeCFYPjCA7mnarDTVI3F+CwgGsbEFdCqi6B/H7aNcvv8 uVm31guy2Df45ySL1FCz+sQdXIZBRS7+S38ufKXGlKERBIeEsCQ= =q3cR -----END PGP SIGNATURE----- Merge tag '9p-for-5.1' of git://github.com/martinetd/linux Pull 9p updates from Dominique Martinet: "Here is a 9p update for 5.1; there honestly hasn't been much. Two fixes (leak on invalid mount argument and possible deadlock on i_size update on 32bit smp) and a fall-through warning cleanup" * tag '9p-for-5.1' of git://github.com/martinetd/linux: 9p/net: fix memory leak in p9_client_create 9p: use inode->i_lock to protect i_size_write() under 32-bit 9p: mark expected switch fall-through
This commit is contained in:
commit
db77bef53b
|
@ -40,6 +40,9 @@
|
||||||
*/
|
*/
|
||||||
#define P9_LOCK_TIMEOUT (30*HZ)
|
#define P9_LOCK_TIMEOUT (30*HZ)
|
||||||
|
|
||||||
|
/* flags for v9fs_stat2inode() & v9fs_stat2inode_dotl() */
|
||||||
|
#define V9FS_STAT2INODE_KEEP_ISIZE 1
|
||||||
|
|
||||||
extern struct file_system_type v9fs_fs_type;
|
extern struct file_system_type v9fs_fs_type;
|
||||||
extern const struct address_space_operations v9fs_addr_operations;
|
extern const struct address_space_operations v9fs_addr_operations;
|
||||||
extern const struct file_operations v9fs_file_operations;
|
extern const struct file_operations v9fs_file_operations;
|
||||||
|
@ -61,8 +64,10 @@ int v9fs_init_inode(struct v9fs_session_info *v9ses,
|
||||||
struct inode *inode, umode_t mode, dev_t);
|
struct inode *inode, umode_t mode, dev_t);
|
||||||
void v9fs_evict_inode(struct inode *inode);
|
void v9fs_evict_inode(struct inode *inode);
|
||||||
ino_t v9fs_qid2ino(struct p9_qid *qid);
|
ino_t v9fs_qid2ino(struct p9_qid *qid);
|
||||||
void v9fs_stat2inode(struct p9_wstat *, struct inode *, struct super_block *);
|
void v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
|
||||||
void v9fs_stat2inode_dotl(struct p9_stat_dotl *, struct inode *);
|
struct super_block *sb, unsigned int flags);
|
||||||
|
void v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode,
|
||||||
|
unsigned int flags);
|
||||||
int v9fs_dir_release(struct inode *inode, struct file *filp);
|
int v9fs_dir_release(struct inode *inode, struct file *filp);
|
||||||
int v9fs_file_open(struct inode *inode, struct file *file);
|
int v9fs_file_open(struct inode *inode, struct file *file);
|
||||||
void v9fs_inode2stat(struct inode *inode, struct p9_wstat *stat);
|
void v9fs_inode2stat(struct inode *inode, struct p9_wstat *stat);
|
||||||
|
@ -83,4 +88,18 @@ static inline void v9fs_invalidate_inode_attr(struct inode *inode)
|
||||||
}
|
}
|
||||||
|
|
||||||
int v9fs_open_to_dotl_flags(int flags);
|
int v9fs_open_to_dotl_flags(int flags);
|
||||||
|
|
||||||
|
static inline void v9fs_i_size_write(struct inode *inode, loff_t i_size)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* 32-bit need the lock, concurrent updates could break the
|
||||||
|
* sequences and make i_size_read() loop forever.
|
||||||
|
* 64-bit updates are atomic and can skip the locking.
|
||||||
|
*/
|
||||||
|
if (sizeof(i_size) > sizeof(long))
|
||||||
|
spin_lock(&inode->i_lock);
|
||||||
|
i_size_write(inode, i_size);
|
||||||
|
if (sizeof(i_size) > sizeof(long))
|
||||||
|
spin_unlock(&inode->i_lock);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -446,7 +446,11 @@ v9fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
|
||||||
i_size = i_size_read(inode);
|
i_size = i_size_read(inode);
|
||||||
if (iocb->ki_pos > i_size) {
|
if (iocb->ki_pos > i_size) {
|
||||||
inode_add_bytes(inode, iocb->ki_pos - i_size);
|
inode_add_bytes(inode, iocb->ki_pos - i_size);
|
||||||
i_size_write(inode, iocb->ki_pos);
|
/*
|
||||||
|
* Need to serialize against i_size_write() in
|
||||||
|
* v9fs_stat2inode()
|
||||||
|
*/
|
||||||
|
v9fs_i_size_write(inode, iocb->ki_pos);
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
|
@ -538,7 +538,7 @@ static struct inode *v9fs_qid_iget(struct super_block *sb,
|
||||||
if (retval)
|
if (retval)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
v9fs_stat2inode(st, inode, sb);
|
v9fs_stat2inode(st, inode, sb, 0);
|
||||||
v9fs_cache_inode_get_cookie(inode);
|
v9fs_cache_inode_get_cookie(inode);
|
||||||
unlock_new_inode(inode);
|
unlock_new_inode(inode);
|
||||||
return inode;
|
return inode;
|
||||||
|
@ -1092,7 +1092,7 @@ v9fs_vfs_getattr(const struct path *path, struct kstat *stat,
|
||||||
if (IS_ERR(st))
|
if (IS_ERR(st))
|
||||||
return PTR_ERR(st);
|
return PTR_ERR(st);
|
||||||
|
|
||||||
v9fs_stat2inode(st, d_inode(dentry), dentry->d_sb);
|
v9fs_stat2inode(st, d_inode(dentry), dentry->d_sb, 0);
|
||||||
generic_fillattr(d_inode(dentry), stat);
|
generic_fillattr(d_inode(dentry), stat);
|
||||||
|
|
||||||
p9stat_free(st);
|
p9stat_free(st);
|
||||||
|
@ -1170,12 +1170,13 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
|
||||||
* @stat: Plan 9 metadata (mistat) structure
|
* @stat: Plan 9 metadata (mistat) structure
|
||||||
* @inode: inode to populate
|
* @inode: inode to populate
|
||||||
* @sb: superblock of filesystem
|
* @sb: superblock of filesystem
|
||||||
|
* @flags: control flags (e.g. V9FS_STAT2INODE_KEEP_ISIZE)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
|
v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
|
||||||
struct super_block *sb)
|
struct super_block *sb, unsigned int flags)
|
||||||
{
|
{
|
||||||
umode_t mode;
|
umode_t mode;
|
||||||
char ext[32];
|
char ext[32];
|
||||||
|
@ -1216,10 +1217,11 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
|
||||||
mode = p9mode2perm(v9ses, stat);
|
mode = p9mode2perm(v9ses, stat);
|
||||||
mode |= inode->i_mode & ~S_IALLUGO;
|
mode |= inode->i_mode & ~S_IALLUGO;
|
||||||
inode->i_mode = mode;
|
inode->i_mode = mode;
|
||||||
i_size_write(inode, stat->length);
|
|
||||||
|
|
||||||
|
if (!(flags & V9FS_STAT2INODE_KEEP_ISIZE))
|
||||||
|
v9fs_i_size_write(inode, stat->length);
|
||||||
/* not real number of blocks, but 512 byte ones ... */
|
/* not real number of blocks, but 512 byte ones ... */
|
||||||
inode->i_blocks = (i_size_read(inode) + 512 - 1) >> 9;
|
inode->i_blocks = (stat->length + 512 - 1) >> 9;
|
||||||
v9inode->cache_validity &= ~V9FS_INO_INVALID_ATTR;
|
v9inode->cache_validity &= ~V9FS_INO_INVALID_ATTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1416,9 +1418,9 @@ int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode)
|
||||||
{
|
{
|
||||||
int umode;
|
int umode;
|
||||||
dev_t rdev;
|
dev_t rdev;
|
||||||
loff_t i_size;
|
|
||||||
struct p9_wstat *st;
|
struct p9_wstat *st;
|
||||||
struct v9fs_session_info *v9ses;
|
struct v9fs_session_info *v9ses;
|
||||||
|
unsigned int flags;
|
||||||
|
|
||||||
v9ses = v9fs_inode2v9ses(inode);
|
v9ses = v9fs_inode2v9ses(inode);
|
||||||
st = p9_client_stat(fid);
|
st = p9_client_stat(fid);
|
||||||
|
@ -1431,16 +1433,13 @@ int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode)
|
||||||
if ((inode->i_mode & S_IFMT) != (umode & S_IFMT))
|
if ((inode->i_mode & S_IFMT) != (umode & S_IFMT))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
spin_lock(&inode->i_lock);
|
|
||||||
/*
|
/*
|
||||||
* We don't want to refresh inode->i_size,
|
* We don't want to refresh inode->i_size,
|
||||||
* because we may have cached data
|
* because we may have cached data
|
||||||
*/
|
*/
|
||||||
i_size = inode->i_size;
|
flags = (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) ?
|
||||||
v9fs_stat2inode(st, inode, inode->i_sb);
|
V9FS_STAT2INODE_KEEP_ISIZE : 0;
|
||||||
if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
|
v9fs_stat2inode(st, inode, inode->i_sb, flags);
|
||||||
inode->i_size = i_size;
|
|
||||||
spin_unlock(&inode->i_lock);
|
|
||||||
out:
|
out:
|
||||||
p9stat_free(st);
|
p9stat_free(st);
|
||||||
kfree(st);
|
kfree(st);
|
||||||
|
|
|
@ -143,7 +143,7 @@ static struct inode *v9fs_qid_iget_dotl(struct super_block *sb,
|
||||||
if (retval)
|
if (retval)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
v9fs_stat2inode_dotl(st, inode);
|
v9fs_stat2inode_dotl(st, inode, 0);
|
||||||
v9fs_cache_inode_get_cookie(inode);
|
v9fs_cache_inode_get_cookie(inode);
|
||||||
retval = v9fs_get_acl(inode, fid);
|
retval = v9fs_get_acl(inode, fid);
|
||||||
if (retval)
|
if (retval)
|
||||||
|
@ -496,7 +496,7 @@ v9fs_vfs_getattr_dotl(const struct path *path, struct kstat *stat,
|
||||||
if (IS_ERR(st))
|
if (IS_ERR(st))
|
||||||
return PTR_ERR(st);
|
return PTR_ERR(st);
|
||||||
|
|
||||||
v9fs_stat2inode_dotl(st, d_inode(dentry));
|
v9fs_stat2inode_dotl(st, d_inode(dentry), 0);
|
||||||
generic_fillattr(d_inode(dentry), stat);
|
generic_fillattr(d_inode(dentry), stat);
|
||||||
/* Change block size to what the server returned */
|
/* Change block size to what the server returned */
|
||||||
stat->blksize = st->st_blksize;
|
stat->blksize = st->st_blksize;
|
||||||
|
@ -607,11 +607,13 @@ int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr)
|
||||||
* v9fs_stat2inode_dotl - populate an inode structure with stat info
|
* v9fs_stat2inode_dotl - populate an inode structure with stat info
|
||||||
* @stat: stat structure
|
* @stat: stat structure
|
||||||
* @inode: inode to populate
|
* @inode: inode to populate
|
||||||
|
* @flags: ctrl flags (e.g. V9FS_STAT2INODE_KEEP_ISIZE)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode)
|
v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode,
|
||||||
|
unsigned int flags)
|
||||||
{
|
{
|
||||||
umode_t mode;
|
umode_t mode;
|
||||||
struct v9fs_inode *v9inode = V9FS_I(inode);
|
struct v9fs_inode *v9inode = V9FS_I(inode);
|
||||||
|
@ -631,7 +633,8 @@ v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode)
|
||||||
mode |= inode->i_mode & ~S_IALLUGO;
|
mode |= inode->i_mode & ~S_IALLUGO;
|
||||||
inode->i_mode = mode;
|
inode->i_mode = mode;
|
||||||
|
|
||||||
i_size_write(inode, stat->st_size);
|
if (!(flags & V9FS_STAT2INODE_KEEP_ISIZE))
|
||||||
|
v9fs_i_size_write(inode, stat->st_size);
|
||||||
inode->i_blocks = stat->st_blocks;
|
inode->i_blocks = stat->st_blocks;
|
||||||
} else {
|
} else {
|
||||||
if (stat->st_result_mask & P9_STATS_ATIME) {
|
if (stat->st_result_mask & P9_STATS_ATIME) {
|
||||||
|
@ -661,8 +664,9 @@ v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode)
|
||||||
}
|
}
|
||||||
if (stat->st_result_mask & P9_STATS_RDEV)
|
if (stat->st_result_mask & P9_STATS_RDEV)
|
||||||
inode->i_rdev = new_decode_dev(stat->st_rdev);
|
inode->i_rdev = new_decode_dev(stat->st_rdev);
|
||||||
if (stat->st_result_mask & P9_STATS_SIZE)
|
if (!(flags & V9FS_STAT2INODE_KEEP_ISIZE) &&
|
||||||
i_size_write(inode, stat->st_size);
|
stat->st_result_mask & P9_STATS_SIZE)
|
||||||
|
v9fs_i_size_write(inode, stat->st_size);
|
||||||
if (stat->st_result_mask & P9_STATS_BLOCKS)
|
if (stat->st_result_mask & P9_STATS_BLOCKS)
|
||||||
inode->i_blocks = stat->st_blocks;
|
inode->i_blocks = stat->st_blocks;
|
||||||
}
|
}
|
||||||
|
@ -928,9 +932,9 @@ v9fs_vfs_get_link_dotl(struct dentry *dentry,
|
||||||
|
|
||||||
int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode)
|
int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode)
|
||||||
{
|
{
|
||||||
loff_t i_size;
|
|
||||||
struct p9_stat_dotl *st;
|
struct p9_stat_dotl *st;
|
||||||
struct v9fs_session_info *v9ses;
|
struct v9fs_session_info *v9ses;
|
||||||
|
unsigned int flags;
|
||||||
|
|
||||||
v9ses = v9fs_inode2v9ses(inode);
|
v9ses = v9fs_inode2v9ses(inode);
|
||||||
st = p9_client_getattr_dotl(fid, P9_STATS_ALL);
|
st = p9_client_getattr_dotl(fid, P9_STATS_ALL);
|
||||||
|
@ -942,16 +946,13 @@ int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode)
|
||||||
if ((inode->i_mode & S_IFMT) != (st->st_mode & S_IFMT))
|
if ((inode->i_mode & S_IFMT) != (st->st_mode & S_IFMT))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
spin_lock(&inode->i_lock);
|
|
||||||
/*
|
/*
|
||||||
* We don't want to refresh inode->i_size,
|
* We don't want to refresh inode->i_size,
|
||||||
* because we may have cached data
|
* because we may have cached data
|
||||||
*/
|
*/
|
||||||
i_size = inode->i_size;
|
flags = (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) ?
|
||||||
v9fs_stat2inode_dotl(st, inode);
|
V9FS_STAT2INODE_KEEP_ISIZE : 0;
|
||||||
if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
|
v9fs_stat2inode_dotl(st, inode, flags);
|
||||||
inode->i_size = i_size;
|
|
||||||
spin_unlock(&inode->i_lock);
|
|
||||||
out:
|
out:
|
||||||
kfree(st);
|
kfree(st);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -172,7 +172,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
|
||||||
goto release_sb;
|
goto release_sb;
|
||||||
}
|
}
|
||||||
d_inode(root)->i_ino = v9fs_qid2ino(&st->qid);
|
d_inode(root)->i_ino = v9fs_qid2ino(&st->qid);
|
||||||
v9fs_stat2inode_dotl(st, d_inode(root));
|
v9fs_stat2inode_dotl(st, d_inode(root), 0);
|
||||||
kfree(st);
|
kfree(st);
|
||||||
} else {
|
} else {
|
||||||
struct p9_wstat *st = NULL;
|
struct p9_wstat *st = NULL;
|
||||||
|
@ -183,7 +183,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
|
||||||
}
|
}
|
||||||
|
|
||||||
d_inode(root)->i_ino = v9fs_qid2ino(&st->qid);
|
d_inode(root)->i_ino = v9fs_qid2ino(&st->qid);
|
||||||
v9fs_stat2inode(st, d_inode(root), sb);
|
v9fs_stat2inode(st, d_inode(root), sb, 0);
|
||||||
|
|
||||||
p9stat_free(st);
|
p9stat_free(st);
|
||||||
kfree(st);
|
kfree(st);
|
||||||
|
|
|
@ -1061,7 +1061,7 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
|
||||||
p9_debug(P9_DEBUG_ERROR,
|
p9_debug(P9_DEBUG_ERROR,
|
||||||
"Please specify a msize of at least 4k\n");
|
"Please specify a msize of at least 4k\n");
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
goto free_client;
|
goto close_trans;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = p9_client_version(clnt);
|
err = p9_client_version(clnt);
|
||||||
|
|
|
@ -513,7 +513,7 @@ static void xen_9pfs_front_changed(struct xenbus_device *dev,
|
||||||
case XenbusStateClosed:
|
case XenbusStateClosed:
|
||||||
if (dev->state == XenbusStateClosed)
|
if (dev->state == XenbusStateClosed)
|
||||||
break;
|
break;
|
||||||
/* Missed the backend's CLOSING state -- fallthrough */
|
/* fall through - Missed the backend's CLOSING state */
|
||||||
case XenbusStateClosing:
|
case XenbusStateClosing:
|
||||||
xenbus_frontend_closed(dev);
|
xenbus_frontend_closed(dev);
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue