aboutsummaryrefslogtreecommitdiffstats
path: root/fs/9p
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-03-17 12:10:56 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-03-17 12:10:56 -0400
commitdb77bef53ba6ba5205ac1788bb8b66ce141ab020 (patch)
tree14ed240b50e3a7b89e7f77bd80b24487649d95b8 /fs/9p
parenta9dce6679d736cb3d612af39bab9f31f8db66f9b (diff)
parentbb06c388fa20ae24cfe80c52488de718a7e3a53f (diff)
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
Diffstat (limited to 'fs/9p')
-rw-r--r--fs/9p/v9fs_vfs.h23
-rw-r--r--fs/9p/vfs_file.c6
-rw-r--r--fs/9p/vfs_inode.c23
-rw-r--r--fs/9p/vfs_inode_dotl.c27
-rw-r--r--fs/9p/vfs_super.c4
5 files changed, 53 insertions, 30 deletions
diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h
index 5a0db6dec8d1..aaee1e6584e6 100644
--- a/fs/9p/v9fs_vfs.h
+++ b/fs/9p/v9fs_vfs.h
@@ -40,6 +40,9 @@
40 */ 40 */
41#define P9_LOCK_TIMEOUT (30*HZ) 41#define P9_LOCK_TIMEOUT (30*HZ)
42 42
43/* flags for v9fs_stat2inode() & v9fs_stat2inode_dotl() */
44#define V9FS_STAT2INODE_KEEP_ISIZE 1
45
43extern struct file_system_type v9fs_fs_type; 46extern struct file_system_type v9fs_fs_type;
44extern const struct address_space_operations v9fs_addr_operations; 47extern const struct address_space_operations v9fs_addr_operations;
45extern const struct file_operations v9fs_file_operations; 48extern const struct file_operations v9fs_file_operations;
@@ -61,8 +64,10 @@ int v9fs_init_inode(struct v9fs_session_info *v9ses,
61 struct inode *inode, umode_t mode, dev_t); 64 struct inode *inode, umode_t mode, dev_t);
62void v9fs_evict_inode(struct inode *inode); 65void v9fs_evict_inode(struct inode *inode);
63ino_t v9fs_qid2ino(struct p9_qid *qid); 66ino_t v9fs_qid2ino(struct p9_qid *qid);
64void v9fs_stat2inode(struct p9_wstat *, struct inode *, struct super_block *); 67void v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
65void v9fs_stat2inode_dotl(struct p9_stat_dotl *, struct inode *); 68 struct super_block *sb, unsigned int flags);
69void v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode,
70 unsigned int flags);
66int v9fs_dir_release(struct inode *inode, struct file *filp); 71int v9fs_dir_release(struct inode *inode, struct file *filp);
67int v9fs_file_open(struct inode *inode, struct file *file); 72int v9fs_file_open(struct inode *inode, struct file *file);
68void v9fs_inode2stat(struct inode *inode, struct p9_wstat *stat); 73void v9fs_inode2stat(struct inode *inode, struct p9_wstat *stat);
@@ -83,4 +88,18 @@ static inline void v9fs_invalidate_inode_attr(struct inode *inode)
83} 88}
84 89
85int v9fs_open_to_dotl_flags(int flags); 90int v9fs_open_to_dotl_flags(int flags);
91
92static inline void v9fs_i_size_write(struct inode *inode, loff_t i_size)
93{
94 /*
95 * 32-bit need the lock, concurrent updates could break the
96 * sequences and make i_size_read() loop forever.
97 * 64-bit updates are atomic and can skip the locking.
98 */
99 if (sizeof(i_size) > sizeof(long))
100 spin_lock(&inode->i_lock);
101 i_size_write(inode, i_size);
102 if (sizeof(i_size) > sizeof(long))
103 spin_unlock(&inode->i_lock);
104}
86#endif 105#endif
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index a25efa782fcc..9a1125305d84 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -446,7 +446,11 @@ v9fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
446 i_size = i_size_read(inode); 446 i_size = i_size_read(inode);
447 if (iocb->ki_pos > i_size) { 447 if (iocb->ki_pos > i_size) {
448 inode_add_bytes(inode, iocb->ki_pos - i_size); 448 inode_add_bytes(inode, iocb->ki_pos - i_size);
449 i_size_write(inode, iocb->ki_pos); 449 /*
450 * Need to serialize against i_size_write() in
451 * v9fs_stat2inode()
452 */
453 v9fs_i_size_write(inode, iocb->ki_pos);
450 } 454 }
451 return retval; 455 return retval;
452 } 456 }
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 85ff859d3af5..72b779bc0942 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -538,7 +538,7 @@ static struct inode *v9fs_qid_iget(struct super_block *sb,
538 if (retval) 538 if (retval)
539 goto error; 539 goto error;
540 540
541 v9fs_stat2inode(st, inode, sb); 541 v9fs_stat2inode(st, inode, sb, 0);
542 v9fs_cache_inode_get_cookie(inode); 542 v9fs_cache_inode_get_cookie(inode);
543 unlock_new_inode(inode); 543 unlock_new_inode(inode);
544 return inode; 544 return inode;
@@ -1092,7 +1092,7 @@ v9fs_vfs_getattr(const struct path *path, struct kstat *stat,
1092 if (IS_ERR(st)) 1092 if (IS_ERR(st))
1093 return PTR_ERR(st); 1093 return PTR_ERR(st);
1094 1094
1095 v9fs_stat2inode(st, d_inode(dentry), dentry->d_sb); 1095 v9fs_stat2inode(st, d_inode(dentry), dentry->d_sb, 0);
1096 generic_fillattr(d_inode(dentry), stat); 1096 generic_fillattr(d_inode(dentry), stat);
1097 1097
1098 p9stat_free(st); 1098 p9stat_free(st);
@@ -1170,12 +1170,13 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
1170 * @stat: Plan 9 metadata (mistat) structure 1170 * @stat: Plan 9 metadata (mistat) structure
1171 * @inode: inode to populate 1171 * @inode: inode to populate
1172 * @sb: superblock of filesystem 1172 * @sb: superblock of filesystem
1173 * @flags: control flags (e.g. V9FS_STAT2INODE_KEEP_ISIZE)
1173 * 1174 *
1174 */ 1175 */
1175 1176
1176void 1177void
1177v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode, 1178v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
1178 struct super_block *sb) 1179 struct super_block *sb, unsigned int flags)
1179{ 1180{
1180 umode_t mode; 1181 umode_t mode;
1181 char ext[32]; 1182 char ext[32];
@@ -1216,10 +1217,11 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
1216 mode = p9mode2perm(v9ses, stat); 1217 mode = p9mode2perm(v9ses, stat);
1217 mode |= inode->i_mode & ~S_IALLUGO; 1218 mode |= inode->i_mode & ~S_IALLUGO;
1218 inode->i_mode = mode; 1219 inode->i_mode = mode;
1219 i_size_write(inode, stat->length);
1220 1220
1221 if (!(flags & V9FS_STAT2INODE_KEEP_ISIZE))
1222 v9fs_i_size_write(inode, stat->length);
1221 /* not real number of blocks, but 512 byte ones ... */ 1223 /* not real number of blocks, but 512 byte ones ... */
1222 inode->i_blocks = (i_size_read(inode) + 512 - 1) >> 9; 1224 inode->i_blocks = (stat->length + 512 - 1) >> 9;
1223 v9inode->cache_validity &= ~V9FS_INO_INVALID_ATTR; 1225 v9inode->cache_validity &= ~V9FS_INO_INVALID_ATTR;
1224} 1226}
1225 1227
@@ -1416,9 +1418,9 @@ int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode)
1416{ 1418{
1417 int umode; 1419 int umode;
1418 dev_t rdev; 1420 dev_t rdev;
1419 loff_t i_size;
1420 struct p9_wstat *st; 1421 struct p9_wstat *st;
1421 struct v9fs_session_info *v9ses; 1422 struct v9fs_session_info *v9ses;
1423 unsigned int flags;
1422 1424
1423 v9ses = v9fs_inode2v9ses(inode); 1425 v9ses = v9fs_inode2v9ses(inode);
1424 st = p9_client_stat(fid); 1426 st = p9_client_stat(fid);
@@ -1431,16 +1433,13 @@ int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode)
1431 if ((inode->i_mode & S_IFMT) != (umode & S_IFMT)) 1433 if ((inode->i_mode & S_IFMT) != (umode & S_IFMT))
1432 goto out; 1434 goto out;
1433 1435
1434 spin_lock(&inode->i_lock);
1435 /* 1436 /*
1436 * We don't want to refresh inode->i_size, 1437 * We don't want to refresh inode->i_size,
1437 * because we may have cached data 1438 * because we may have cached data
1438 */ 1439 */
1439 i_size = inode->i_size; 1440 flags = (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) ?
1440 v9fs_stat2inode(st, inode, inode->i_sb); 1441 V9FS_STAT2INODE_KEEP_ISIZE : 0;
1441 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) 1442 v9fs_stat2inode(st, inode, inode->i_sb, flags);
1442 inode->i_size = i_size;
1443 spin_unlock(&inode->i_lock);
1444out: 1443out:
1445 p9stat_free(st); 1444 p9stat_free(st);
1446 kfree(st); 1445 kfree(st);
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
index 4823e1c46999..a950a927a626 100644
--- a/fs/9p/vfs_inode_dotl.c
+++ b/fs/9p/vfs_inode_dotl.c
@@ -143,7 +143,7 @@ static struct inode *v9fs_qid_iget_dotl(struct super_block *sb,
143 if (retval) 143 if (retval)
144 goto error; 144 goto error;
145 145
146 v9fs_stat2inode_dotl(st, inode); 146 v9fs_stat2inode_dotl(st, inode, 0);
147 v9fs_cache_inode_get_cookie(inode); 147 v9fs_cache_inode_get_cookie(inode);
148 retval = v9fs_get_acl(inode, fid); 148 retval = v9fs_get_acl(inode, fid);
149 if (retval) 149 if (retval)
@@ -496,7 +496,7 @@ v9fs_vfs_getattr_dotl(const struct path *path, struct kstat *stat,
496 if (IS_ERR(st)) 496 if (IS_ERR(st))
497 return PTR_ERR(st); 497 return PTR_ERR(st);
498 498
499 v9fs_stat2inode_dotl(st, d_inode(dentry)); 499 v9fs_stat2inode_dotl(st, d_inode(dentry), 0);
500 generic_fillattr(d_inode(dentry), stat); 500 generic_fillattr(d_inode(dentry), stat);
501 /* Change block size to what the server returned */ 501 /* Change block size to what the server returned */
502 stat->blksize = st->st_blksize; 502 stat->blksize = st->st_blksize;
@@ -607,11 +607,13 @@ int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr)
607 * v9fs_stat2inode_dotl - populate an inode structure with stat info 607 * v9fs_stat2inode_dotl - populate an inode structure with stat info
608 * @stat: stat structure 608 * @stat: stat structure
609 * @inode: inode to populate 609 * @inode: inode to populate
610 * @flags: ctrl flags (e.g. V9FS_STAT2INODE_KEEP_ISIZE)
610 * 611 *
611 */ 612 */
612 613
613void 614void
614v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode) 615v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode,
616 unsigned int flags)
615{ 617{
616 umode_t mode; 618 umode_t mode;
617 struct v9fs_inode *v9inode = V9FS_I(inode); 619 struct v9fs_inode *v9inode = V9FS_I(inode);
@@ -631,7 +633,8 @@ v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode)
631 mode |= inode->i_mode & ~S_IALLUGO; 633 mode |= inode->i_mode & ~S_IALLUGO;
632 inode->i_mode = mode; 634 inode->i_mode = mode;
633 635
634 i_size_write(inode, stat->st_size); 636 if (!(flags & V9FS_STAT2INODE_KEEP_ISIZE))
637 v9fs_i_size_write(inode, stat->st_size);
635 inode->i_blocks = stat->st_blocks; 638 inode->i_blocks = stat->st_blocks;
636 } else { 639 } else {
637 if (stat->st_result_mask & P9_STATS_ATIME) { 640 if (stat->st_result_mask & P9_STATS_ATIME) {
@@ -661,8 +664,9 @@ v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode)
661 } 664 }
662 if (stat->st_result_mask & P9_STATS_RDEV) 665 if (stat->st_result_mask & P9_STATS_RDEV)
663 inode->i_rdev = new_decode_dev(stat->st_rdev); 666 inode->i_rdev = new_decode_dev(stat->st_rdev);
664 if (stat->st_result_mask & P9_STATS_SIZE) 667 if (!(flags & V9FS_STAT2INODE_KEEP_ISIZE) &&
665 i_size_write(inode, stat->st_size); 668 stat->st_result_mask & P9_STATS_SIZE)
669 v9fs_i_size_write(inode, stat->st_size);
666 if (stat->st_result_mask & P9_STATS_BLOCKS) 670 if (stat->st_result_mask & P9_STATS_BLOCKS)
667 inode->i_blocks = stat->st_blocks; 671 inode->i_blocks = stat->st_blocks;
668 } 672 }
@@ -928,9 +932,9 @@ v9fs_vfs_get_link_dotl(struct dentry *dentry,
928 932
929int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode) 933int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode)
930{ 934{
931 loff_t i_size;
932 struct p9_stat_dotl *st; 935 struct p9_stat_dotl *st;
933 struct v9fs_session_info *v9ses; 936 struct v9fs_session_info *v9ses;
937 unsigned int flags;
934 938
935 v9ses = v9fs_inode2v9ses(inode); 939 v9ses = v9fs_inode2v9ses(inode);
936 st = p9_client_getattr_dotl(fid, P9_STATS_ALL); 940 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)
942 if ((inode->i_mode & S_IFMT) != (st->st_mode & S_IFMT)) 946 if ((inode->i_mode & S_IFMT) != (st->st_mode & S_IFMT))
943 goto out; 947 goto out;
944 948
945 spin_lock(&inode->i_lock);
946 /* 949 /*
947 * We don't want to refresh inode->i_size, 950 * We don't want to refresh inode->i_size,
948 * because we may have cached data 951 * because we may have cached data
949 */ 952 */
950 i_size = inode->i_size; 953 flags = (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) ?
951 v9fs_stat2inode_dotl(st, inode); 954 V9FS_STAT2INODE_KEEP_ISIZE : 0;
952 if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) 955 v9fs_stat2inode_dotl(st, inode, flags);
953 inode->i_size = i_size;
954 spin_unlock(&inode->i_lock);
955out: 956out:
956 kfree(st); 957 kfree(st);
957 return 0; 958 return 0;
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index 10d3bd3f534b..d13d35cf69c0 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -172,7 +172,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
172 goto release_sb; 172 goto release_sb;
173 } 173 }
174 d_inode(root)->i_ino = v9fs_qid2ino(&st->qid); 174 d_inode(root)->i_ino = v9fs_qid2ino(&st->qid);
175 v9fs_stat2inode_dotl(st, d_inode(root)); 175 v9fs_stat2inode_dotl(st, d_inode(root), 0);
176 kfree(st); 176 kfree(st);
177 } else { 177 } else {
178 struct p9_wstat *st = NULL; 178 struct p9_wstat *st = NULL;
@@ -183,7 +183,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
183 } 183 }
184 184
185 d_inode(root)->i_ino = v9fs_qid2ino(&st->qid); 185 d_inode(root)->i_ino = v9fs_qid2ino(&st->qid);
186 v9fs_stat2inode(st, d_inode(root), sb); 186 v9fs_stat2inode(st, d_inode(root), sb, 0);
187 187
188 p9stat_free(st); 188 p9stat_free(st);
189 kfree(st); 189 kfree(st);