diff options
Diffstat (limited to 'fs/9p/vfs_inode_dotl.c')
-rw-r--r-- | fs/9p/vfs_inode_dotl.c | 86 |
1 files changed, 73 insertions, 13 deletions
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index b6c8ed205192..aded79fcd5cf 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 | ||
@@ -190,6 +191,58 @@ v9fs_inode_from_fid_dotl(struct v9fs_session_info *v9ses, struct p9_fid *fid, | |||
190 | return inode; | 191 | return inode; |
191 | } | 192 | } |
192 | 193 | ||
194 | struct dotl_openflag_map { | ||
195 | int open_flag; | ||
196 | int dotl_flag; | ||
197 | }; | ||
198 | |||
199 | static int v9fs_mapped_dotl_flags(int flags) | ||
200 | { | ||
201 | int i; | ||
202 | int rflags = 0; | ||
203 | struct dotl_openflag_map dotl_oflag_map[] = { | ||
204 | { O_CREAT, P9_DOTL_CREATE }, | ||
205 | { O_EXCL, P9_DOTL_EXCL }, | ||
206 | { O_NOCTTY, P9_DOTL_NOCTTY }, | ||
207 | { O_TRUNC, P9_DOTL_TRUNC }, | ||
208 | { O_APPEND, P9_DOTL_APPEND }, | ||
209 | { O_NONBLOCK, P9_DOTL_NONBLOCK }, | ||
210 | { O_DSYNC, P9_DOTL_DSYNC }, | ||
211 | { FASYNC, P9_DOTL_FASYNC }, | ||
212 | { O_DIRECT, P9_DOTL_DIRECT }, | ||
213 | { O_LARGEFILE, P9_DOTL_LARGEFILE }, | ||
214 | { O_DIRECTORY, P9_DOTL_DIRECTORY }, | ||
215 | { O_NOFOLLOW, P9_DOTL_NOFOLLOW }, | ||
216 | { O_NOATIME, P9_DOTL_NOATIME }, | ||
217 | { O_CLOEXEC, P9_DOTL_CLOEXEC }, | ||
218 | { O_SYNC, P9_DOTL_SYNC}, | ||
219 | }; | ||
220 | for (i = 0; i < ARRAY_SIZE(dotl_oflag_map); i++) { | ||
221 | if (flags & dotl_oflag_map[i].open_flag) | ||
222 | rflags |= dotl_oflag_map[i].dotl_flag; | ||
223 | } | ||
224 | return rflags; | ||
225 | } | ||
226 | |||
227 | /** | ||
228 | * v9fs_open_to_dotl_flags- convert Linux specific open flags to | ||
229 | * plan 9 open flag. | ||
230 | * @flags: flags to convert | ||
231 | */ | ||
232 | int v9fs_open_to_dotl_flags(int flags) | ||
233 | { | ||
234 | int rflags = 0; | ||
235 | |||
236 | /* | ||
237 | * We have same bits for P9_DOTL_READONLY, P9_DOTL_WRONLY | ||
238 | * and P9_DOTL_NOACCESS | ||
239 | */ | ||
240 | rflags |= flags & O_ACCMODE; | ||
241 | rflags |= v9fs_mapped_dotl_flags(flags); | ||
242 | |||
243 | return rflags; | ||
244 | } | ||
245 | |||
193 | /** | 246 | /** |
194 | * v9fs_vfs_create_dotl - VFS hook to create files for 9P2000.L protocol. | 247 | * v9fs_vfs_create_dotl - VFS hook to create files for 9P2000.L protocol. |
195 | * @dir: directory inode that is being created | 248 | * @dir: directory inode that is being created |
@@ -258,7 +311,8 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode, | |||
258 | "Failed to get acl values in creat %d\n", err); | 311 | "Failed to get acl values in creat %d\n", err); |
259 | goto error; | 312 | goto error; |
260 | } | 313 | } |
261 | err = p9_client_create_dotl(ofid, name, flags, mode, gid, &qid); | 314 | err = p9_client_create_dotl(ofid, name, v9fs_open_to_dotl_flags(flags), |
315 | mode, gid, &qid); | ||
262 | if (err < 0) { | 316 | if (err < 0) { |
263 | P9_DPRINTK(P9_DEBUG_VFS, | 317 | P9_DPRINTK(P9_DEBUG_VFS, |
264 | "p9_client_open_dotl failed in creat %d\n", | 318 | "p9_client_open_dotl failed in creat %d\n", |
@@ -281,10 +335,10 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode, | |||
281 | P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err); | 335 | P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err); |
282 | goto error; | 336 | goto error; |
283 | } | 337 | } |
284 | d_instantiate(dentry, inode); | ||
285 | err = v9fs_fid_add(dentry, fid); | 338 | err = v9fs_fid_add(dentry, fid); |
286 | if (err < 0) | 339 | if (err < 0) |
287 | goto error; | 340 | goto error; |
341 | d_instantiate(dentry, inode); | ||
288 | 342 | ||
289 | /* Now set the ACL based on the default value */ | 343 | /* Now set the ACL based on the default value */ |
290 | v9fs_set_create_acl(dentry, &dacl, &pacl); | 344 | v9fs_set_create_acl(dentry, &dacl, &pacl); |
@@ -403,10 +457,10 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir, | |||
403 | err); | 457 | err); |
404 | goto error; | 458 | goto error; |
405 | } | 459 | } |
406 | d_instantiate(dentry, inode); | ||
407 | err = v9fs_fid_add(dentry, fid); | 460 | err = v9fs_fid_add(dentry, fid); |
408 | if (err < 0) | 461 | if (err < 0) |
409 | goto error; | 462 | goto error; |
463 | d_instantiate(dentry, inode); | ||
410 | fid = NULL; | 464 | fid = NULL; |
411 | } else { | 465 | } else { |
412 | /* | 466 | /* |
@@ -414,7 +468,7 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir, | |||
414 | * inode with stat. We need to get an inode | 468 | * inode with stat. We need to get an inode |
415 | * so that we can set the acl with dentry | 469 | * so that we can set the acl with dentry |
416 | */ | 470 | */ |
417 | inode = v9fs_get_inode(dir->i_sb, mode); | 471 | inode = v9fs_get_inode(dir->i_sb, mode, 0); |
418 | if (IS_ERR(inode)) { | 472 | if (IS_ERR(inode)) { |
419 | err = PTR_ERR(inode); | 473 | err = PTR_ERR(inode); |
420 | goto error; | 474 | goto error; |
@@ -540,6 +594,7 @@ int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr) | |||
540 | void | 594 | void |
541 | v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode) | 595 | v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode) |
542 | { | 596 | { |
597 | mode_t mode; | ||
543 | struct v9fs_inode *v9inode = V9FS_I(inode); | 598 | struct v9fs_inode *v9inode = V9FS_I(inode); |
544 | 599 | ||
545 | if ((stat->st_result_mask & P9_STATS_BASIC) == P9_STATS_BASIC) { | 600 | if ((stat->st_result_mask & P9_STATS_BASIC) == P9_STATS_BASIC) { |
@@ -552,11 +607,10 @@ v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode) | |||
552 | inode->i_uid = stat->st_uid; | 607 | inode->i_uid = stat->st_uid; |
553 | inode->i_gid = stat->st_gid; | 608 | inode->i_gid = stat->st_gid; |
554 | inode->i_nlink = stat->st_nlink; | 609 | inode->i_nlink = stat->st_nlink; |
555 | inode->i_mode = stat->st_mode; | ||
556 | inode->i_rdev = new_decode_dev(stat->st_rdev); | ||
557 | 610 | ||
558 | if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode))) | 611 | mode = stat->st_mode & S_IALLUGO; |
559 | init_special_inode(inode, inode->i_mode, inode->i_rdev); | 612 | mode |= inode->i_mode & ~S_IALLUGO; |
613 | inode->i_mode = mode; | ||
560 | 614 | ||
561 | i_size_write(inode, stat->st_size); | 615 | i_size_write(inode, stat->st_size); |
562 | inode->i_blocks = stat->st_blocks; | 616 | inode->i_blocks = stat->st_blocks; |
@@ -657,14 +711,14 @@ v9fs_vfs_symlink_dotl(struct inode *dir, struct dentry *dentry, | |||
657 | err); | 711 | err); |
658 | goto error; | 712 | goto error; |
659 | } | 713 | } |
660 | d_instantiate(dentry, inode); | ||
661 | err = v9fs_fid_add(dentry, fid); | 714 | err = v9fs_fid_add(dentry, fid); |
662 | if (err < 0) | 715 | if (err < 0) |
663 | goto error; | 716 | goto error; |
717 | d_instantiate(dentry, inode); | ||
664 | fid = NULL; | 718 | fid = NULL; |
665 | } else { | 719 | } else { |
666 | /* Not in cached mode. No need to populate inode with stat */ | 720 | /* Not in cached mode. No need to populate inode with stat */ |
667 | inode = v9fs_get_inode(dir->i_sb, S_IFLNK); | 721 | inode = v9fs_get_inode(dir->i_sb, S_IFLNK, 0); |
668 | if (IS_ERR(inode)) { | 722 | if (IS_ERR(inode)) { |
669 | err = PTR_ERR(inode); | 723 | err = PTR_ERR(inode); |
670 | goto error; | 724 | goto error; |
@@ -810,17 +864,17 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int omode, | |||
810 | err); | 864 | err); |
811 | goto error; | 865 | goto error; |
812 | } | 866 | } |
813 | d_instantiate(dentry, inode); | ||
814 | err = v9fs_fid_add(dentry, fid); | 867 | err = v9fs_fid_add(dentry, fid); |
815 | if (err < 0) | 868 | if (err < 0) |
816 | goto error; | 869 | goto error; |
870 | d_instantiate(dentry, inode); | ||
817 | fid = NULL; | 871 | fid = NULL; |
818 | } else { | 872 | } else { |
819 | /* | 873 | /* |
820 | * Not in cached mode. No need to populate inode with stat. | 874 | * Not in cached mode. No need to populate inode with stat. |
821 | * socket syscall returns a fd, so we need instantiate | 875 | * socket syscall returns a fd, so we need instantiate |
822 | */ | 876 | */ |
823 | inode = v9fs_get_inode(dir->i_sb, mode); | 877 | inode = v9fs_get_inode(dir->i_sb, mode, rdev); |
824 | if (IS_ERR(inode)) { | 878 | if (IS_ERR(inode)) { |
825 | err = PTR_ERR(inode); | 879 | err = PTR_ERR(inode); |
826 | goto error; | 880 | goto error; |
@@ -886,6 +940,11 @@ int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode) | |||
886 | st = p9_client_getattr_dotl(fid, P9_STATS_ALL); | 940 | st = p9_client_getattr_dotl(fid, P9_STATS_ALL); |
887 | if (IS_ERR(st)) | 941 | if (IS_ERR(st)) |
888 | return PTR_ERR(st); | 942 | return PTR_ERR(st); |
943 | /* | ||
944 | * Don't update inode if the file type is different | ||
945 | */ | ||
946 | if ((inode->i_mode & S_IFMT) != (st->st_mode & S_IFMT)) | ||
947 | goto out; | ||
889 | 948 | ||
890 | spin_lock(&inode->i_lock); | 949 | spin_lock(&inode->i_lock); |
891 | /* | 950 | /* |
@@ -897,6 +956,7 @@ int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode) | |||
897 | if (v9ses->cache) | 956 | if (v9ses->cache) |
898 | inode->i_size = i_size; | 957 | inode->i_size = i_size; |
899 | spin_unlock(&inode->i_lock); | 958 | spin_unlock(&inode->i_lock); |
959 | out: | ||
900 | kfree(st); | 960 | kfree(st); |
901 | return 0; | 961 | return 0; |
902 | } | 962 | } |