diff options
Diffstat (limited to 'fs/9p/vfs_inode.c')
-rw-r--r-- | fs/9p/vfs_inode.c | 101 |
1 files changed, 44 insertions, 57 deletions
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 18f74ec4dce9..f2434fc9d2c4 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/namei.h> | 34 | #include <linux/namei.h> |
35 | #include <linux/idr.h> | 35 | #include <linux/idr.h> |
36 | #include <linux/sched.h> | 36 | #include <linux/sched.h> |
37 | #include <linux/slab.h> | ||
37 | #include <net/9p/9p.h> | 38 | #include <net/9p/9p.h> |
38 | #include <net/9p/client.h> | 39 | #include <net/9p/client.h> |
39 | 40 | ||
@@ -60,7 +61,7 @@ static int unixmode2p9mode(struct v9fs_session_info *v9ses, int mode) | |||
60 | res = mode & 0777; | 61 | res = mode & 0777; |
61 | if (S_ISDIR(mode)) | 62 | if (S_ISDIR(mode)) |
62 | res |= P9_DMDIR; | 63 | res |= P9_DMDIR; |
63 | if (v9fs_extended(v9ses)) { | 64 | if (v9fs_proto_dotu(v9ses)) { |
64 | if (S_ISLNK(mode)) | 65 | if (S_ISLNK(mode)) |
65 | res |= P9_DMSYMLINK; | 66 | res |= P9_DMSYMLINK; |
66 | if (v9ses->nodev == 0) { | 67 | if (v9ses->nodev == 0) { |
@@ -102,21 +103,21 @@ static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode) | |||
102 | 103 | ||
103 | if ((mode & P9_DMDIR) == P9_DMDIR) | 104 | if ((mode & P9_DMDIR) == P9_DMDIR) |
104 | res |= S_IFDIR; | 105 | res |= S_IFDIR; |
105 | else if ((mode & P9_DMSYMLINK) && (v9fs_extended(v9ses))) | 106 | else if ((mode & P9_DMSYMLINK) && (v9fs_proto_dotu(v9ses))) |
106 | res |= S_IFLNK; | 107 | res |= S_IFLNK; |
107 | else if ((mode & P9_DMSOCKET) && (v9fs_extended(v9ses)) | 108 | else if ((mode & P9_DMSOCKET) && (v9fs_proto_dotu(v9ses)) |
108 | && (v9ses->nodev == 0)) | 109 | && (v9ses->nodev == 0)) |
109 | res |= S_IFSOCK; | 110 | res |= S_IFSOCK; |
110 | else if ((mode & P9_DMNAMEDPIPE) && (v9fs_extended(v9ses)) | 111 | else if ((mode & P9_DMNAMEDPIPE) && (v9fs_proto_dotu(v9ses)) |
111 | && (v9ses->nodev == 0)) | 112 | && (v9ses->nodev == 0)) |
112 | res |= S_IFIFO; | 113 | res |= S_IFIFO; |
113 | else if ((mode & P9_DMDEVICE) && (v9fs_extended(v9ses)) | 114 | else if ((mode & P9_DMDEVICE) && (v9fs_proto_dotu(v9ses)) |
114 | && (v9ses->nodev == 0)) | 115 | && (v9ses->nodev == 0)) |
115 | res |= S_IFBLK; | 116 | res |= S_IFBLK; |
116 | else | 117 | else |
117 | res |= S_IFREG; | 118 | res |= S_IFREG; |
118 | 119 | ||
119 | if (v9fs_extended(v9ses)) { | 120 | if (v9fs_proto_dotu(v9ses)) { |
120 | if ((mode & P9_DMSETUID) == P9_DMSETUID) | 121 | if ((mode & P9_DMSETUID) == P9_DMSETUID) |
121 | res |= S_ISUID; | 122 | res |= S_ISUID; |
122 | 123 | ||
@@ -176,7 +177,7 @@ int v9fs_uflags2omode(int uflags, int extended) | |||
176 | * | 177 | * |
177 | */ | 178 | */ |
178 | 179 | ||
179 | static void | 180 | void |
180 | v9fs_blank_wstat(struct p9_wstat *wstat) | 181 | v9fs_blank_wstat(struct p9_wstat *wstat) |
181 | { | 182 | { |
182 | wstat->type = ~0; | 183 | wstat->type = ~0; |
@@ -265,7 +266,7 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode) | |||
265 | case S_IFBLK: | 266 | case S_IFBLK: |
266 | case S_IFCHR: | 267 | case S_IFCHR: |
267 | case S_IFSOCK: | 268 | case S_IFSOCK: |
268 | if (!v9fs_extended(v9ses)) { | 269 | if (!v9fs_proto_dotu(v9ses)) { |
269 | P9_DPRINTK(P9_DEBUG_ERROR, | 270 | P9_DPRINTK(P9_DEBUG_ERROR, |
270 | "special files without extended mode\n"); | 271 | "special files without extended mode\n"); |
271 | err = -EINVAL; | 272 | err = -EINVAL; |
@@ -278,7 +279,7 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode) | |||
278 | inode->i_fop = &v9fs_file_operations; | 279 | inode->i_fop = &v9fs_file_operations; |
279 | break; | 280 | break; |
280 | case S_IFLNK: | 281 | case S_IFLNK: |
281 | if (!v9fs_extended(v9ses)) { | 282 | if (!v9fs_proto_dotu(v9ses)) { |
282 | P9_DPRINTK(P9_DEBUG_ERROR, | 283 | P9_DPRINTK(P9_DEBUG_ERROR, |
283 | "extended modes used w/o 9P2000.u\n"); | 284 | "extended modes used w/o 9P2000.u\n"); |
284 | err = -EINVAL; | 285 | err = -EINVAL; |
@@ -288,7 +289,7 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode) | |||
288 | break; | 289 | break; |
289 | case S_IFDIR: | 290 | case S_IFDIR: |
290 | inc_nlink(inode); | 291 | inc_nlink(inode); |
291 | if (v9fs_extended(v9ses)) | 292 | if (v9fs_proto_dotu(v9ses)) |
292 | inode->i_op = &v9fs_dir_inode_operations_ext; | 293 | inode->i_op = &v9fs_dir_inode_operations_ext; |
293 | else | 294 | else |
294 | inode->i_op = &v9fs_dir_inode_operations; | 295 | inode->i_op = &v9fs_dir_inode_operations; |
@@ -431,6 +432,7 @@ error: | |||
431 | 432 | ||
432 | static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) | 433 | static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) |
433 | { | 434 | { |
435 | int retval; | ||
434 | struct inode *file_inode; | 436 | struct inode *file_inode; |
435 | struct v9fs_session_info *v9ses; | 437 | struct v9fs_session_info *v9ses; |
436 | struct p9_fid *v9fid; | 438 | struct p9_fid *v9fid; |
@@ -444,7 +446,10 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) | |||
444 | if (IS_ERR(v9fid)) | 446 | if (IS_ERR(v9fid)) |
445 | return PTR_ERR(v9fid); | 447 | return PTR_ERR(v9fid); |
446 | 448 | ||
447 | return p9_client_remove(v9fid); | 449 | retval = p9_client_remove(v9fid); |
450 | if (!retval) | ||
451 | drop_nlink(file_inode); | ||
452 | return retval; | ||
448 | } | 453 | } |
449 | 454 | ||
450 | static int | 455 | static int |
@@ -575,7 +580,8 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode, | |||
575 | flags = O_RDWR; | 580 | flags = O_RDWR; |
576 | 581 | ||
577 | fid = v9fs_create(v9ses, dir, dentry, NULL, perm, | 582 | fid = v9fs_create(v9ses, dir, dentry, NULL, perm, |
578 | v9fs_uflags2omode(flags, v9fs_extended(v9ses))); | 583 | v9fs_uflags2omode(flags, |
584 | v9fs_proto_dotu(v9ses))); | ||
579 | if (IS_ERR(fid)) { | 585 | if (IS_ERR(fid)) { |
580 | err = PTR_ERR(fid); | 586 | err = PTR_ERR(fid); |
581 | fid = NULL; | 587 | fid = NULL; |
@@ -655,6 +661,9 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
655 | P9_DPRINTK(P9_DEBUG_VFS, "dir: %p dentry: (%s) %p nameidata: %p\n", | 661 | P9_DPRINTK(P9_DEBUG_VFS, "dir: %p dentry: (%s) %p nameidata: %p\n", |
656 | dir, dentry->d_name.name, dentry, nameidata); | 662 | dir, dentry->d_name.name, dentry, nameidata); |
657 | 663 | ||
664 | if (dentry->d_name.len > NAME_MAX) | ||
665 | return ERR_PTR(-ENAMETOOLONG); | ||
666 | |||
658 | sb = dir->i_sb; | 667 | sb = dir->i_sb; |
659 | v9ses = v9fs_inode2v9ses(dir); | 668 | v9ses = v9fs_inode2v9ses(dir); |
660 | dfid = v9fs_fid_lookup(dentry->d_parent); | 669 | dfid = v9fs_fid_lookup(dentry->d_parent); |
@@ -858,7 +867,7 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) | |||
858 | if (iattr->ia_valid & ATTR_SIZE) | 867 | if (iattr->ia_valid & ATTR_SIZE) |
859 | wstat.length = iattr->ia_size; | 868 | wstat.length = iattr->ia_size; |
860 | 869 | ||
861 | if (v9fs_extended(v9ses)) { | 870 | if (v9fs_proto_dotu(v9ses)) { |
862 | if (iattr->ia_valid & ATTR_UID) | 871 | if (iattr->ia_valid & ATTR_UID) |
863 | wstat.n_uid = iattr->ia_uid; | 872 | wstat.n_uid = iattr->ia_uid; |
864 | 873 | ||
@@ -886,6 +895,8 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode, | |||
886 | struct super_block *sb) | 895 | struct super_block *sb) |
887 | { | 896 | { |
888 | char ext[32]; | 897 | char ext[32]; |
898 | char tag_name[14]; | ||
899 | unsigned int i_nlink; | ||
889 | struct v9fs_session_info *v9ses = sb->s_fs_info; | 900 | struct v9fs_session_info *v9ses = sb->s_fs_info; |
890 | 901 | ||
891 | inode->i_nlink = 1; | 902 | inode->i_nlink = 1; |
@@ -897,11 +908,26 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode, | |||
897 | inode->i_uid = v9ses->dfltuid; | 908 | inode->i_uid = v9ses->dfltuid; |
898 | inode->i_gid = v9ses->dfltgid; | 909 | inode->i_gid = v9ses->dfltgid; |
899 | 910 | ||
900 | if (v9fs_extended(v9ses)) { | 911 | if (v9fs_proto_dotu(v9ses)) { |
901 | inode->i_uid = stat->n_uid; | 912 | inode->i_uid = stat->n_uid; |
902 | inode->i_gid = stat->n_gid; | 913 | inode->i_gid = stat->n_gid; |
903 | } | 914 | } |
904 | 915 | if ((S_ISREG(inode->i_mode)) || (S_ISDIR(inode->i_mode))) { | |
916 | if (v9fs_proto_dotu(v9ses) && (stat->extension[0] != '\0')) { | ||
917 | /* | ||
918 | * Hadlink support got added later to | ||
919 | * to the .u extension. So there can be | ||
920 | * server out there that doesn't support | ||
921 | * this even with .u extension. So check | ||
922 | * for non NULL stat->extension | ||
923 | */ | ||
924 | strncpy(ext, stat->extension, sizeof(ext)); | ||
925 | /* HARDLINKCOUNT %u */ | ||
926 | sscanf(ext, "%13s %u", tag_name, &i_nlink); | ||
927 | if (!strncmp(tag_name, "HARDLINKCOUNT", 13)) | ||
928 | inode->i_nlink = i_nlink; | ||
929 | } | ||
930 | } | ||
905 | inode->i_mode = p9mode2unixmode(v9ses, stat->mode); | 931 | inode->i_mode = p9mode2unixmode(v9ses, stat->mode); |
906 | if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode))) { | 932 | if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode))) { |
907 | char type = 0; | 933 | char type = 0; |
@@ -976,7 +1002,7 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) | |||
976 | if (IS_ERR(fid)) | 1002 | if (IS_ERR(fid)) |
977 | return PTR_ERR(fid); | 1003 | return PTR_ERR(fid); |
978 | 1004 | ||
979 | if (!v9fs_extended(v9ses)) | 1005 | if (!v9fs_proto_dotu(v9ses)) |
980 | return -EBADF; | 1006 | return -EBADF; |
981 | 1007 | ||
982 | st = p9_client_stat(fid); | 1008 | st = p9_client_stat(fid); |
@@ -1001,44 +1027,6 @@ done: | |||
1001 | } | 1027 | } |
1002 | 1028 | ||
1003 | /** | 1029 | /** |
1004 | * v9fs_vfs_readlink - read a symlink's location | ||
1005 | * @dentry: dentry for symlink | ||
1006 | * @buffer: buffer to load symlink location into | ||
1007 | * @buflen: length of buffer | ||
1008 | * | ||
1009 | */ | ||
1010 | |||
1011 | static int v9fs_vfs_readlink(struct dentry *dentry, char __user * buffer, | ||
1012 | int buflen) | ||
1013 | { | ||
1014 | int retval; | ||
1015 | int ret; | ||
1016 | char *link = __getname(); | ||
1017 | |||
1018 | if (unlikely(!link)) | ||
1019 | return -ENOMEM; | ||
1020 | |||
1021 | if (buflen > PATH_MAX) | ||
1022 | buflen = PATH_MAX; | ||
1023 | |||
1024 | P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_name.name, | ||
1025 | dentry); | ||
1026 | |||
1027 | retval = v9fs_readlink(dentry, link, buflen); | ||
1028 | |||
1029 | if (retval > 0) { | ||
1030 | if ((ret = copy_to_user(buffer, link, retval)) != 0) { | ||
1031 | P9_DPRINTK(P9_DEBUG_ERROR, | ||
1032 | "problem copying to user: %d\n", ret); | ||
1033 | retval = ret; | ||
1034 | } | ||
1035 | } | ||
1036 | |||
1037 | __putname(link); | ||
1038 | return retval; | ||
1039 | } | ||
1040 | |||
1041 | /** | ||
1042 | * v9fs_vfs_follow_link - follow a symlink path | 1030 | * v9fs_vfs_follow_link - follow a symlink path |
1043 | * @dentry: dentry for symlink | 1031 | * @dentry: dentry for symlink |
1044 | * @nd: nameidata | 1032 | * @nd: nameidata |
@@ -1104,7 +1092,7 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry, | |||
1104 | struct p9_fid *fid; | 1092 | struct p9_fid *fid; |
1105 | 1093 | ||
1106 | v9ses = v9fs_inode2v9ses(dir); | 1094 | v9ses = v9fs_inode2v9ses(dir); |
1107 | if (!v9fs_extended(v9ses)) { | 1095 | if (!v9fs_proto_dotu(v9ses)) { |
1108 | P9_DPRINTK(P9_DEBUG_ERROR, "not extended\n"); | 1096 | P9_DPRINTK(P9_DEBUG_ERROR, "not extended\n"); |
1109 | return -EPERM; | 1097 | return -EPERM; |
1110 | } | 1098 | } |
@@ -1230,7 +1218,6 @@ static const struct inode_operations v9fs_dir_inode_operations_ext = { | |||
1230 | .rmdir = v9fs_vfs_rmdir, | 1218 | .rmdir = v9fs_vfs_rmdir, |
1231 | .mknod = v9fs_vfs_mknod, | 1219 | .mknod = v9fs_vfs_mknod, |
1232 | .rename = v9fs_vfs_rename, | 1220 | .rename = v9fs_vfs_rename, |
1233 | .readlink = v9fs_vfs_readlink, | ||
1234 | .getattr = v9fs_vfs_getattr, | 1221 | .getattr = v9fs_vfs_getattr, |
1235 | .setattr = v9fs_vfs_setattr, | 1222 | .setattr = v9fs_vfs_setattr, |
1236 | }; | 1223 | }; |
@@ -1253,7 +1240,7 @@ static const struct inode_operations v9fs_file_inode_operations = { | |||
1253 | }; | 1240 | }; |
1254 | 1241 | ||
1255 | static const struct inode_operations v9fs_symlink_inode_operations = { | 1242 | static const struct inode_operations v9fs_symlink_inode_operations = { |
1256 | .readlink = v9fs_vfs_readlink, | 1243 | .readlink = generic_readlink, |
1257 | .follow_link = v9fs_vfs_follow_link, | 1244 | .follow_link = v9fs_vfs_follow_link, |
1258 | .put_link = v9fs_vfs_put_link, | 1245 | .put_link = v9fs_vfs_put_link, |
1259 | .getattr = v9fs_vfs_getattr, | 1246 | .getattr = v9fs_vfs_getattr, |