aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>2011-07-25 14:06:33 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2011-10-03 14:40:21 -0400
commit29a3e8657d2a2640384166e3fe29a086d235fc33 (patch)
treeb361d43245798a0e227c4e3b7e8cfdbaf07ab2a7
parente279cdca3ca67dcd8e24051629163f9d5d838894 (diff)
fs/9p: Don't update file type when updating file attributes
commit 45089142b1497dab2327d60f6c71c40766fc3ea4 upstream. We should only update attributes that we can change on stat2inode. Also do file type initialization in v9fs_init_inode. Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--fs/9p/v9fs_vfs.h4
-rw-r--r--fs/9p/vfs_inode.c91
-rw-r--r--fs/9p/vfs_inode_dotl.c23
-rw-r--r--fs/9p/vfs_super.c2
4 files changed, 68 insertions, 52 deletions
diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h
index 4014160903a..bd86d22ad91 100644
--- a/fs/9p/v9fs_vfs.h
+++ b/fs/9p/v9fs_vfs.h
@@ -54,9 +54,9 @@ extern struct kmem_cache *v9fs_inode_cache;
54 54
55struct inode *v9fs_alloc_inode(struct super_block *sb); 55struct inode *v9fs_alloc_inode(struct super_block *sb);
56void v9fs_destroy_inode(struct inode *inode); 56void v9fs_destroy_inode(struct inode *inode);
57struct inode *v9fs_get_inode(struct super_block *sb, int mode); 57struct inode *v9fs_get_inode(struct super_block *sb, int mode, dev_t);
58int v9fs_init_inode(struct v9fs_session_info *v9ses, 58int v9fs_init_inode(struct v9fs_session_info *v9ses,
59 struct inode *inode, int mode); 59 struct inode *inode, int mode, dev_t);
60void v9fs_evict_inode(struct inode *inode); 60void v9fs_evict_inode(struct inode *inode);
61ino_t v9fs_qid2ino(struct p9_qid *qid); 61ino_t v9fs_qid2ino(struct p9_qid *qid);
62void v9fs_stat2inode(struct p9_wstat *, struct inode *, struct super_block *); 62void v9fs_stat2inode(struct p9_wstat *, struct inode *, struct super_block *);
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index ad7aae4b03d..1ab561d3aa2 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -95,15 +95,18 @@ static int unixmode2p9mode(struct v9fs_session_info *v9ses, int mode)
95/** 95/**
96 * p9mode2unixmode- convert plan9 mode bits to unix mode bits 96 * p9mode2unixmode- convert plan9 mode bits to unix mode bits
97 * @v9ses: v9fs session information 97 * @v9ses: v9fs session information
98 * @mode: mode to convert 98 * @stat: p9_wstat from which mode need to be derived
99 * @rdev: major number, minor number in case of device files.
99 * 100 *
100 */ 101 */
101 102static int p9mode2unixmode(struct v9fs_session_info *v9ses,
102static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode) 103 struct p9_wstat *stat, dev_t *rdev)
103{ 104{
104 int res; 105 int res;
106 int mode = stat->mode;
105 107
106 res = mode & 0777; 108 res = mode & S_IALLUGO;
109 *rdev = 0;
107 110
108 if ((mode & P9_DMDIR) == P9_DMDIR) 111 if ((mode & P9_DMDIR) == P9_DMDIR)
109 res |= S_IFDIR; 112 res |= S_IFDIR;
@@ -116,9 +119,26 @@ static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode)
116 && (v9ses->nodev == 0)) 119 && (v9ses->nodev == 0))
117 res |= S_IFIFO; 120 res |= S_IFIFO;
118 else if ((mode & P9_DMDEVICE) && (v9fs_proto_dotu(v9ses)) 121 else if ((mode & P9_DMDEVICE) && (v9fs_proto_dotu(v9ses))
119 && (v9ses->nodev == 0)) 122 && (v9ses->nodev == 0)) {
120 res |= S_IFBLK; 123 char type = 0, ext[32];
121 else 124 int major = -1, minor = -1;
125
126 strncpy(ext, stat->extension, sizeof(ext));
127 sscanf(ext, "%c %u %u", &type, &major, &minor);
128 switch (type) {
129 case 'c':
130 res |= S_IFCHR;
131 break;
132 case 'b':
133 res |= S_IFBLK;
134 break;
135 default:
136 P9_DPRINTK(P9_DEBUG_ERROR,
137 "Unknown special type %c %s\n", type,
138 stat->extension);
139 };
140 *rdev = MKDEV(major, minor);
141 } else
122 res |= S_IFREG; 142 res |= S_IFREG;
123 143
124 if (v9fs_proto_dotu(v9ses)) { 144 if (v9fs_proto_dotu(v9ses)) {
@@ -131,7 +151,6 @@ static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode)
131 if ((mode & P9_DMSETVTX) == P9_DMSETVTX) 151 if ((mode & P9_DMSETVTX) == P9_DMSETVTX)
132 res |= S_ISVTX; 152 res |= S_ISVTX;
133 } 153 }
134
135 return res; 154 return res;
136} 155}
137 156
@@ -242,13 +261,13 @@ void v9fs_destroy_inode(struct inode *inode)
242} 261}
243 262
244int v9fs_init_inode(struct v9fs_session_info *v9ses, 263int v9fs_init_inode(struct v9fs_session_info *v9ses,
245 struct inode *inode, int mode) 264 struct inode *inode, int mode, dev_t rdev)
246{ 265{
247 int err = 0; 266 int err = 0;
248 267
249 inode_init_owner(inode, NULL, mode); 268 inode_init_owner(inode, NULL, mode);
250 inode->i_blocks = 0; 269 inode->i_blocks = 0;
251 inode->i_rdev = 0; 270 inode->i_rdev = rdev;
252 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; 271 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
253 inode->i_mapping->a_ops = &v9fs_addr_operations; 272 inode->i_mapping->a_ops = &v9fs_addr_operations;
254 273
@@ -335,7 +354,7 @@ error:
335 * 354 *
336 */ 355 */
337 356
338struct inode *v9fs_get_inode(struct super_block *sb, int mode) 357struct inode *v9fs_get_inode(struct super_block *sb, int mode, dev_t rdev)
339{ 358{
340 int err; 359 int err;
341 struct inode *inode; 360 struct inode *inode;
@@ -348,7 +367,7 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
348 P9_EPRINTK(KERN_WARNING, "Problem allocating inode\n"); 367 P9_EPRINTK(KERN_WARNING, "Problem allocating inode\n");
349 return ERR_PTR(-ENOMEM); 368 return ERR_PTR(-ENOMEM);
350 } 369 }
351 err = v9fs_init_inode(v9ses, inode, mode); 370 err = v9fs_init_inode(v9ses, inode, mode, rdev);
352 if (err) { 371 if (err) {
353 iput(inode); 372 iput(inode);
354 return ERR_PTR(err); 373 return ERR_PTR(err);
@@ -435,11 +454,12 @@ void v9fs_evict_inode(struct inode *inode)
435static int v9fs_test_inode(struct inode *inode, void *data) 454static int v9fs_test_inode(struct inode *inode, void *data)
436{ 455{
437 int umode; 456 int umode;
457 dev_t rdev;
438 struct v9fs_inode *v9inode = V9FS_I(inode); 458 struct v9fs_inode *v9inode = V9FS_I(inode);
439 struct p9_wstat *st = (struct p9_wstat *)data; 459 struct p9_wstat *st = (struct p9_wstat *)data;
440 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); 460 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
441 461
442 umode = p9mode2unixmode(v9ses, st->mode); 462 umode = p9mode2unixmode(v9ses, st, &rdev);
443 /* don't match inode of different type */ 463 /* don't match inode of different type */
444 if ((inode->i_mode & S_IFMT) != (umode & S_IFMT)) 464 if ((inode->i_mode & S_IFMT) != (umode & S_IFMT))
445 return 0; 465 return 0;
@@ -473,6 +493,7 @@ static struct inode *v9fs_qid_iget(struct super_block *sb,
473 struct p9_wstat *st, 493 struct p9_wstat *st,
474 int new) 494 int new)
475{ 495{
496 dev_t rdev;
476 int retval, umode; 497 int retval, umode;
477 unsigned long i_ino; 498 unsigned long i_ino;
478 struct inode *inode; 499 struct inode *inode;
@@ -496,8 +517,8 @@ static struct inode *v9fs_qid_iget(struct super_block *sb,
496 * later. 517 * later.
497 */ 518 */
498 inode->i_ino = i_ino; 519 inode->i_ino = i_ino;
499 umode = p9mode2unixmode(v9ses, st->mode); 520 umode = p9mode2unixmode(v9ses, st, &rdev);
500 retval = v9fs_init_inode(v9ses, inode, umode); 521 retval = v9fs_init_inode(v9ses, inode, umode, rdev);
501 if (retval) 522 if (retval)
502 goto error; 523 goto error;
503 524
@@ -990,7 +1011,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
990 return PTR_ERR(st); 1011 return PTR_ERR(st);
991 1012
992 v9fs_stat2inode(st, dentry->d_inode, dentry->d_inode->i_sb); 1013 v9fs_stat2inode(st, dentry->d_inode, dentry->d_inode->i_sb);
993 generic_fillattr(dentry->d_inode, stat); 1014 generic_fillattr(dentry->d_inode, stat);
994 1015
995 p9stat_free(st); 1016 p9stat_free(st);
996 kfree(st); 1017 kfree(st);
@@ -1074,6 +1095,7 @@ void
1074v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode, 1095v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
1075 struct super_block *sb) 1096 struct super_block *sb)
1076{ 1097{
1098 mode_t mode;
1077 char ext[32]; 1099 char ext[32];
1078 char tag_name[14]; 1100 char tag_name[14];
1079 unsigned int i_nlink; 1101 unsigned int i_nlink;
@@ -1109,31 +1131,9 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
1109 inode->i_nlink = i_nlink; 1131 inode->i_nlink = i_nlink;
1110 } 1132 }
1111 } 1133 }
1112 inode->i_mode = p9mode2unixmode(v9ses, stat->mode); 1134 mode = stat->mode & S_IALLUGO;
1113 if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode))) { 1135 mode |= inode->i_mode & ~S_IALLUGO;
1114 char type = 0; 1136 inode->i_mode = mode;
1115 int major = -1;
1116 int minor = -1;
1117
1118 strncpy(ext, stat->extension, sizeof(ext));
1119 sscanf(ext, "%c %u %u", &type, &major, &minor);
1120 switch (type) {
1121 case 'c':
1122 inode->i_mode &= ~S_IFBLK;
1123 inode->i_mode |= S_IFCHR;
1124 break;
1125 case 'b':
1126 break;
1127 default:
1128 P9_DPRINTK(P9_DEBUG_ERROR,
1129 "Unknown special type %c %s\n", type,
1130 stat->extension);
1131 };
1132 inode->i_rdev = MKDEV(major, minor);
1133 init_special_inode(inode, inode->i_mode, inode->i_rdev);
1134 } else
1135 inode->i_rdev = 0;
1136
1137 i_size_write(inode, stat->length); 1137 i_size_write(inode, stat->length);
1138 1138
1139 /* not real number of blocks, but 512 byte ones ... */ 1139 /* not real number of blocks, but 512 byte ones ... */
@@ -1399,6 +1399,8 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
1399 1399
1400int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode) 1400int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode)
1401{ 1401{
1402 int umode;
1403 dev_t rdev;
1402 loff_t i_size; 1404 loff_t i_size;
1403 struct p9_wstat *st; 1405 struct p9_wstat *st;
1404 struct v9fs_session_info *v9ses; 1406 struct v9fs_session_info *v9ses;
@@ -1407,6 +1409,12 @@ int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode)
1407 st = p9_client_stat(fid); 1409 st = p9_client_stat(fid);
1408 if (IS_ERR(st)) 1410 if (IS_ERR(st))
1409 return PTR_ERR(st); 1411 return PTR_ERR(st);
1412 /*
1413 * Don't update inode if the file type is different
1414 */
1415 umode = p9mode2unixmode(v9ses, st, &rdev);
1416 if ((inode->i_mode & S_IFMT) != (umode & S_IFMT))
1417 goto out;
1410 1418
1411 spin_lock(&inode->i_lock); 1419 spin_lock(&inode->i_lock);
1412 /* 1420 /*
@@ -1418,6 +1426,7 @@ int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode)
1418 if (v9ses->cache) 1426 if (v9ses->cache)
1419 inode->i_size = i_size; 1427 inode->i_size = i_size;
1420 spin_unlock(&inode->i_lock); 1428 spin_unlock(&inode->i_lock);
1429out:
1421 p9stat_free(st); 1430 p9stat_free(st);
1422 kfree(st); 1431 kfree(st);
1423 return 0; 1432 return 0;
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
index 0a1723587fa..818bf6f9633 100644
--- a/fs/9p/vfs_inode_dotl.c
+++ b/fs/9p/vfs_inode_dotl.c
@@ -153,7 +153,8 @@ static struct inode *v9fs_qid_iget_dotl(struct super_block *sb,
153 * later. 153 * later.
154 */ 154 */
155 inode->i_ino = i_ino; 155 inode->i_ino = i_ino;
156 retval = v9fs_init_inode(v9ses, inode, st->st_mode); 156 retval = v9fs_init_inode(v9ses, inode,
157 st->st_mode, new_decode_dev(st->st_rdev));
157 if (retval) 158 if (retval)
158 goto error; 159 goto error;
159 160
@@ -414,7 +415,7 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir,
414 * inode with stat. We need to get an inode 415 * inode with stat. We need to get an inode
415 * so that we can set the acl with dentry 416 * so that we can set the acl with dentry
416 */ 417 */
417 inode = v9fs_get_inode(dir->i_sb, mode); 418 inode = v9fs_get_inode(dir->i_sb, mode, 0);
418 if (IS_ERR(inode)) { 419 if (IS_ERR(inode)) {
419 err = PTR_ERR(inode); 420 err = PTR_ERR(inode);
420 goto error; 421 goto error;
@@ -540,6 +541,7 @@ int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr)
540void 541void
541v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode) 542v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode)
542{ 543{
544 mode_t mode;
543 struct v9fs_inode *v9inode = V9FS_I(inode); 545 struct v9fs_inode *v9inode = V9FS_I(inode);
544 546
545 if ((stat->st_result_mask & P9_STATS_BASIC) == P9_STATS_BASIC) { 547 if ((stat->st_result_mask & P9_STATS_BASIC) == P9_STATS_BASIC) {
@@ -552,11 +554,10 @@ v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode)
552 inode->i_uid = stat->st_uid; 554 inode->i_uid = stat->st_uid;
553 inode->i_gid = stat->st_gid; 555 inode->i_gid = stat->st_gid;
554 inode->i_nlink = stat->st_nlink; 556 inode->i_nlink = stat->st_nlink;
555 inode->i_mode = stat->st_mode;
556 inode->i_rdev = new_decode_dev(stat->st_rdev);
557 557
558 if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode))) 558 mode = stat->st_mode & S_IALLUGO;
559 init_special_inode(inode, inode->i_mode, inode->i_rdev); 559 mode |= inode->i_mode & ~S_IALLUGO;
560 inode->i_mode = mode;
560 561
561 i_size_write(inode, stat->st_size); 562 i_size_write(inode, stat->st_size);
562 inode->i_blocks = stat->st_blocks; 563 inode->i_blocks = stat->st_blocks;
@@ -664,7 +665,7 @@ v9fs_vfs_symlink_dotl(struct inode *dir, struct dentry *dentry,
664 fid = NULL; 665 fid = NULL;
665 } else { 666 } else {
666 /* Not in cached mode. No need to populate inode with stat */ 667 /* Not in cached mode. No need to populate inode with stat */
667 inode = v9fs_get_inode(dir->i_sb, S_IFLNK); 668 inode = v9fs_get_inode(dir->i_sb, S_IFLNK, 0);
668 if (IS_ERR(inode)) { 669 if (IS_ERR(inode)) {
669 err = PTR_ERR(inode); 670 err = PTR_ERR(inode);
670 goto error; 671 goto error;
@@ -820,7 +821,7 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int omode,
820 * Not in cached mode. No need to populate inode with stat. 821 * Not in cached mode. No need to populate inode with stat.
821 * socket syscall returns a fd, so we need instantiate 822 * socket syscall returns a fd, so we need instantiate
822 */ 823 */
823 inode = v9fs_get_inode(dir->i_sb, mode); 824 inode = v9fs_get_inode(dir->i_sb, mode, rdev);
824 if (IS_ERR(inode)) { 825 if (IS_ERR(inode)) {
825 err = PTR_ERR(inode); 826 err = PTR_ERR(inode);
826 goto error; 827 goto error;
@@ -886,6 +887,11 @@ int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode)
886 st = p9_client_getattr_dotl(fid, P9_STATS_ALL); 887 st = p9_client_getattr_dotl(fid, P9_STATS_ALL);
887 if (IS_ERR(st)) 888 if (IS_ERR(st))
888 return PTR_ERR(st); 889 return PTR_ERR(st);
890 /*
891 * Don't update inode if the file type is different
892 */
893 if ((inode->i_mode & S_IFMT) != (st->st_mode & S_IFMT))
894 goto out;
889 895
890 spin_lock(&inode->i_lock); 896 spin_lock(&inode->i_lock);
891 /* 897 /*
@@ -897,6 +903,7 @@ int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode)
897 if (v9ses->cache) 903 if (v9ses->cache)
898 inode->i_size = i_size; 904 inode->i_size = i_size;
899 spin_unlock(&inode->i_lock); 905 spin_unlock(&inode->i_lock);
906out:
900 kfree(st); 907 kfree(st);
901 return 0; 908 return 0;
902} 909}
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index feef6cdc1fd..c70251d47ed 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -149,7 +149,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
149 else 149 else
150 sb->s_d_op = &v9fs_dentry_operations; 150 sb->s_d_op = &v9fs_dentry_operations;
151 151
152 inode = v9fs_get_inode(sb, S_IFDIR | mode); 152 inode = v9fs_get_inode(sb, S_IFDIR | mode, 0);
153 if (IS_ERR(inode)) { 153 if (IS_ERR(inode)) {
154 retval = PTR_ERR(inode); 154 retval = PTR_ERR(inode);
155 goto release_sb; 155 goto release_sb;