diff options
author | Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | 2011-07-25 14:06:33 -0400 |
---|---|---|
committer | Eric Van Hensbergen <ericvh@gmail.com> | 2011-09-06 09:17:14 -0400 |
commit | 45089142b1497dab2327d60f6c71c40766fc3ea4 (patch) | |
tree | 8a553d984c355fb89d9937d1212dbb0b2cfcc414 /fs/9p | |
parent | 5441ae5eb3614d3c28f77073370738a2820c88e4 (diff) |
fs/9p: Don't update file type when updating file attributes
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>
Diffstat (limited to 'fs/9p')
-rw-r--r-- | fs/9p/v9fs_vfs.h | 4 | ||||
-rw-r--r-- | fs/9p/vfs_inode.c | 91 | ||||
-rw-r--r-- | fs/9p/vfs_inode_dotl.c | 23 | ||||
-rw-r--r-- | fs/9p/vfs_super.c | 2 |
4 files changed, 68 insertions, 52 deletions
diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h index 46ce357ca1a..7ac1faec2bd 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 | ||
55 | struct inode *v9fs_alloc_inode(struct super_block *sb); | 55 | struct inode *v9fs_alloc_inode(struct super_block *sb); |
56 | void v9fs_destroy_inode(struct inode *inode); | 56 | void v9fs_destroy_inode(struct inode *inode); |
57 | struct inode *v9fs_get_inode(struct super_block *sb, int mode); | 57 | struct inode *v9fs_get_inode(struct super_block *sb, int mode, dev_t); |
58 | int v9fs_init_inode(struct v9fs_session_info *v9ses, | 58 | int v9fs_init_inode(struct v9fs_session_info *v9ses, |
59 | struct inode *inode, int mode); | 59 | struct inode *inode, int mode, dev_t); |
60 | void v9fs_evict_inode(struct inode *inode); | 60 | void v9fs_evict_inode(struct inode *inode); |
61 | ino_t v9fs_qid2ino(struct p9_qid *qid); | 61 | ino_t v9fs_qid2ino(struct p9_qid *qid); |
62 | void v9fs_stat2inode(struct p9_wstat *, struct inode *, struct super_block *); | 62 | void 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 43dd540663a..3563cace0a2 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 | 102 | static int p9mode2unixmode(struct v9fs_session_info *v9ses, | |
102 | static 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 | ||
244 | int v9fs_init_inode(struct v9fs_session_info *v9ses, | 263 | int 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 | ||
338 | struct inode *v9fs_get_inode(struct super_block *sb, int mode) | 357 | struct 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) | |||
435 | static int v9fs_test_inode(struct inode *inode, void *data) | 454 | static 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 | ||
@@ -1000,7 +1021,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
1000 | return PTR_ERR(st); | 1021 | return PTR_ERR(st); |
1001 | 1022 | ||
1002 | v9fs_stat2inode(st, dentry->d_inode, dentry->d_inode->i_sb); | 1023 | v9fs_stat2inode(st, dentry->d_inode, dentry->d_inode->i_sb); |
1003 | generic_fillattr(dentry->d_inode, stat); | 1024 | generic_fillattr(dentry->d_inode, stat); |
1004 | 1025 | ||
1005 | p9stat_free(st); | 1026 | p9stat_free(st); |
1006 | kfree(st); | 1027 | kfree(st); |
@@ -1084,6 +1105,7 @@ void | |||
1084 | v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode, | 1105 | v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode, |
1085 | struct super_block *sb) | 1106 | struct super_block *sb) |
1086 | { | 1107 | { |
1108 | mode_t mode; | ||
1087 | char ext[32]; | 1109 | char ext[32]; |
1088 | char tag_name[14]; | 1110 | char tag_name[14]; |
1089 | unsigned int i_nlink; | 1111 | unsigned int i_nlink; |
@@ -1119,31 +1141,9 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode, | |||
1119 | inode->i_nlink = i_nlink; | 1141 | inode->i_nlink = i_nlink; |
1120 | } | 1142 | } |
1121 | } | 1143 | } |
1122 | inode->i_mode = p9mode2unixmode(v9ses, stat->mode); | 1144 | mode = stat->mode & S_IALLUGO; |
1123 | if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode))) { | 1145 | mode |= inode->i_mode & ~S_IALLUGO; |
1124 | char type = 0; | 1146 | inode->i_mode = mode; |
1125 | int major = -1; | ||
1126 | int minor = -1; | ||
1127 | |||
1128 | strncpy(ext, stat->extension, sizeof(ext)); | ||
1129 | sscanf(ext, "%c %u %u", &type, &major, &minor); | ||
1130 | switch (type) { | ||
1131 | case 'c': | ||
1132 | inode->i_mode &= ~S_IFBLK; | ||
1133 | inode->i_mode |= S_IFCHR; | ||
1134 | break; | ||
1135 | case 'b': | ||
1136 | break; | ||
1137 | default: | ||
1138 | P9_DPRINTK(P9_DEBUG_ERROR, | ||
1139 | "Unknown special type %c %s\n", type, | ||
1140 | stat->extension); | ||
1141 | }; | ||
1142 | inode->i_rdev = MKDEV(major, minor); | ||
1143 | init_special_inode(inode, inode->i_mode, inode->i_rdev); | ||
1144 | } else | ||
1145 | inode->i_rdev = 0; | ||
1146 | |||
1147 | i_size_write(inode, stat->length); | 1147 | i_size_write(inode, stat->length); |
1148 | 1148 | ||
1149 | /* not real number of blocks, but 512 byte ones ... */ | 1149 | /* not real number of blocks, but 512 byte ones ... */ |
@@ -1409,6 +1409,8 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) | |||
1409 | 1409 | ||
1410 | int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode) | 1410 | int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode) |
1411 | { | 1411 | { |
1412 | int umode; | ||
1413 | dev_t rdev; | ||
1412 | loff_t i_size; | 1414 | loff_t i_size; |
1413 | struct p9_wstat *st; | 1415 | struct p9_wstat *st; |
1414 | struct v9fs_session_info *v9ses; | 1416 | struct v9fs_session_info *v9ses; |
@@ -1417,6 +1419,12 @@ int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode) | |||
1417 | st = p9_client_stat(fid); | 1419 | st = p9_client_stat(fid); |
1418 | if (IS_ERR(st)) | 1420 | if (IS_ERR(st)) |
1419 | return PTR_ERR(st); | 1421 | return PTR_ERR(st); |
1422 | /* | ||
1423 | * Don't update inode if the file type is different | ||
1424 | */ | ||
1425 | umode = p9mode2unixmode(v9ses, st, &rdev); | ||
1426 | if ((inode->i_mode & S_IFMT) != (umode & S_IFMT)) | ||
1427 | goto out; | ||
1420 | 1428 | ||
1421 | spin_lock(&inode->i_lock); | 1429 | spin_lock(&inode->i_lock); |
1422 | /* | 1430 | /* |
@@ -1428,6 +1436,7 @@ int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode) | |||
1428 | if (v9ses->cache) | 1436 | if (v9ses->cache) |
1429 | inode->i_size = i_size; | 1437 | inode->i_size = i_size; |
1430 | spin_unlock(&inode->i_lock); | 1438 | spin_unlock(&inode->i_lock); |
1439 | out: | ||
1431 | p9stat_free(st); | 1440 | p9stat_free(st); |
1432 | kfree(st); | 1441 | kfree(st); |
1433 | return 0; | 1442 | return 0; |
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index 0ca224c8bb6..a3f2540cc4b 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) | |||
540 | void | 541 | void |
541 | v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode) | 542 | v9fs_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); |
906 | out: | ||
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; |