aboutsummaryrefslogtreecommitdiffstats
path: root/fs/9p/vfs_inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/9p/vfs_inode.c')
-rw-r--r--fs/9p/vfs_inode.c101
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
179static void 180void
180v9fs_blank_wstat(struct p9_wstat *wstat) 181v9fs_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
432static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) 433static 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
450static int 455static 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
1011static 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
1255static const struct inode_operations v9fs_symlink_inode_operations = { 1242static 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,