diff options
| -rw-r--r-- | fs/9p/v9fs_vfs.h | 1 | ||||
| -rw-r--r-- | fs/9p/vfs_inode.c | 177 | ||||
| -rw-r--r-- | fs/9p/vfs_super.c | 43 | ||||
| -rw-r--r-- | include/net/9p/9p.h | 44 | ||||
| -rw-r--r-- | include/net/9p/client.h | 3 | ||||
| -rw-r--r-- | net/9p/client.c | 59 | ||||
| -rw-r--r-- | net/9p/protocol.c | 28 |
7 files changed, 321 insertions, 34 deletions
diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h index 32ef4009d030..f47c6bbb01b3 100644 --- a/fs/9p/v9fs_vfs.h +++ b/fs/9p/v9fs_vfs.h | |||
| @@ -55,6 +55,7 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode); | |||
| 55 | void v9fs_clear_inode(struct inode *inode); | 55 | void v9fs_clear_inode(struct inode *inode); |
| 56 | ino_t v9fs_qid2ino(struct p9_qid *qid); | 56 | ino_t v9fs_qid2ino(struct p9_qid *qid); |
| 57 | void v9fs_stat2inode(struct p9_wstat *, struct inode *, struct super_block *); | 57 | void v9fs_stat2inode(struct p9_wstat *, struct inode *, struct super_block *); |
| 58 | void v9fs_stat2inode_dotl(struct p9_stat_dotl *, struct inode *); | ||
| 58 | int v9fs_dir_release(struct inode *inode, struct file *filp); | 59 | int v9fs_dir_release(struct inode *inode, struct file *filp); |
| 59 | int v9fs_file_open(struct inode *inode, struct file *file); | 60 | int v9fs_file_open(struct inode *inode, struct file *file); |
| 60 | void v9fs_inode2stat(struct inode *inode, struct p9_wstat *stat); | 61 | void v9fs_inode2stat(struct inode *inode, struct p9_wstat *stat); |
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 4331b3b5ee1c..afcb8d889382 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
| @@ -396,23 +396,14 @@ void v9fs_clear_inode(struct inode *inode) | |||
| 396 | #endif | 396 | #endif |
| 397 | } | 397 | } |
| 398 | 398 | ||
| 399 | /** | ||
| 400 | * v9fs_inode_from_fid - populate an inode by issuing a attribute request | ||
| 401 | * @v9ses: session information | ||
| 402 | * @fid: fid to issue attribute request for | ||
| 403 | * @sb: superblock on which to create inode | ||
| 404 | * | ||
| 405 | */ | ||
| 406 | |||
| 407 | static struct inode * | 399 | static struct inode * |
| 408 | v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid, | 400 | v9fs_inode(struct v9fs_session_info *v9ses, struct p9_fid *fid, |
| 409 | struct super_block *sb) | 401 | struct super_block *sb) |
| 410 | { | 402 | { |
| 411 | int err, umode; | 403 | int err, umode; |
| 412 | struct inode *ret; | 404 | struct inode *ret = NULL; |
| 413 | struct p9_wstat *st; | 405 | struct p9_wstat *st; |
| 414 | 406 | ||
| 415 | ret = NULL; | ||
| 416 | st = p9_client_stat(fid); | 407 | st = p9_client_stat(fid); |
| 417 | if (IS_ERR(st)) | 408 | if (IS_ERR(st)) |
| 418 | return ERR_CAST(st); | 409 | return ERR_CAST(st); |
| @@ -433,15 +424,62 @@ v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid, | |||
| 433 | #endif | 424 | #endif |
| 434 | p9stat_free(st); | 425 | p9stat_free(st); |
| 435 | kfree(st); | 426 | kfree(st); |
| 436 | |||
| 437 | return ret; | 427 | return ret; |
| 438 | |||
| 439 | error: | 428 | error: |
| 440 | p9stat_free(st); | 429 | p9stat_free(st); |
| 441 | kfree(st); | 430 | kfree(st); |
| 442 | return ERR_PTR(err); | 431 | return ERR_PTR(err); |
| 443 | } | 432 | } |
| 444 | 433 | ||
| 434 | static struct inode * | ||
| 435 | v9fs_inode_dotl(struct v9fs_session_info *v9ses, struct p9_fid *fid, | ||
| 436 | struct super_block *sb) | ||
| 437 | { | ||
| 438 | struct inode *ret = NULL; | ||
| 439 | int err; | ||
| 440 | struct p9_stat_dotl *st; | ||
| 441 | |||
| 442 | st = p9_client_getattr_dotl(fid, P9_STATS_BASIC); | ||
| 443 | if (IS_ERR(st)) | ||
| 444 | return ERR_CAST(st); | ||
| 445 | |||
| 446 | ret = v9fs_get_inode(sb, st->st_mode); | ||
| 447 | if (IS_ERR(ret)) { | ||
| 448 | err = PTR_ERR(ret); | ||
| 449 | goto error; | ||
| 450 | } | ||
| 451 | |||
| 452 | v9fs_stat2inode_dotl(st, ret); | ||
| 453 | ret->i_ino = v9fs_qid2ino(&st->qid); | ||
| 454 | #ifdef CONFIG_9P_FSCACHE | ||
| 455 | v9fs_vcookie_set_qid(ret, &st->qid); | ||
| 456 | v9fs_cache_inode_get_cookie(ret); | ||
| 457 | #endif | ||
| 458 | kfree(st); | ||
| 459 | return ret; | ||
| 460 | error: | ||
| 461 | kfree(st); | ||
| 462 | return ERR_PTR(err); | ||
| 463 | } | ||
| 464 | |||
| 465 | /** | ||
| 466 | * v9fs_inode_from_fid - Helper routine to populate an inode by | ||
| 467 | * issuing a attribute request | ||
| 468 | * @v9ses: session information | ||
| 469 | * @fid: fid to issue attribute request for | ||
| 470 | * @sb: superblock on which to create inode | ||
| 471 | * | ||
| 472 | */ | ||
| 473 | static inline struct inode * | ||
| 474 | v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid, | ||
| 475 | struct super_block *sb) | ||
| 476 | { | ||
| 477 | if (v9fs_proto_dotl(v9ses)) | ||
| 478 | return v9fs_inode_dotl(v9ses, fid, sb); | ||
| 479 | else | ||
| 480 | return v9fs_inode(v9ses, fid, sb); | ||
| 481 | } | ||
| 482 | |||
| 445 | /** | 483 | /** |
| 446 | * v9fs_remove - helper function to remove files and directories | 484 | * v9fs_remove - helper function to remove files and directories |
| 447 | * @dir: directory inode that is being deleted | 485 | * @dir: directory inode that is being deleted |
| @@ -853,6 +891,42 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
| 853 | return 0; | 891 | return 0; |
| 854 | } | 892 | } |
| 855 | 893 | ||
| 894 | static int | ||
| 895 | v9fs_vfs_getattr_dotl(struct vfsmount *mnt, struct dentry *dentry, | ||
| 896 | struct kstat *stat) | ||
| 897 | { | ||
| 898 | int err; | ||
| 899 | struct v9fs_session_info *v9ses; | ||
| 900 | struct p9_fid *fid; | ||
| 901 | struct p9_stat_dotl *st; | ||
| 902 | |||
| 903 | P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry); | ||
| 904 | err = -EPERM; | ||
| 905 | v9ses = v9fs_inode2v9ses(dentry->d_inode); | ||
| 906 | if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) | ||
| 907 | return simple_getattr(mnt, dentry, stat); | ||
| 908 | |||
| 909 | fid = v9fs_fid_lookup(dentry); | ||
| 910 | if (IS_ERR(fid)) | ||
| 911 | return PTR_ERR(fid); | ||
| 912 | |||
| 913 | /* Ask for all the fields in stat structure. Server will return | ||
| 914 | * whatever it supports | ||
| 915 | */ | ||
| 916 | |||
| 917 | st = p9_client_getattr_dotl(fid, P9_STATS_ALL); | ||
| 918 | if (IS_ERR(st)) | ||
| 919 | return PTR_ERR(st); | ||
| 920 | |||
| 921 | v9fs_stat2inode_dotl(st, dentry->d_inode); | ||
| 922 | generic_fillattr(dentry->d_inode, stat); | ||
| 923 | /* Change block size to what the server returned */ | ||
| 924 | stat->blksize = st->st_blksize; | ||
| 925 | |||
| 926 | kfree(st); | ||
| 927 | return 0; | ||
| 928 | } | ||
| 929 | |||
| 856 | /** | 930 | /** |
| 857 | * v9fs_vfs_setattr - set file metadata | 931 | * v9fs_vfs_setattr - set file metadata |
| 858 | * @dentry: file whose metadata to set | 932 | * @dentry: file whose metadata to set |
| @@ -980,6 +1054,77 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode, | |||
| 980 | } | 1054 | } |
| 981 | 1055 | ||
| 982 | /** | 1056 | /** |
| 1057 | * v9fs_stat2inode_dotl - populate an inode structure with stat info | ||
| 1058 | * @stat: stat structure | ||
| 1059 | * @inode: inode to populate | ||
| 1060 | * @sb: superblock of filesystem | ||
| 1061 | * | ||
| 1062 | */ | ||
| 1063 | |||
| 1064 | void | ||
| 1065 | v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode) | ||
| 1066 | { | ||
| 1067 | |||
| 1068 | if ((stat->st_result_mask & P9_STATS_BASIC) == P9_STATS_BASIC) { | ||
| 1069 | inode->i_atime.tv_sec = stat->st_atime_sec; | ||
| 1070 | inode->i_atime.tv_nsec = stat->st_atime_nsec; | ||
| 1071 | inode->i_mtime.tv_sec = stat->st_mtime_sec; | ||
| 1072 | inode->i_mtime.tv_nsec = stat->st_mtime_nsec; | ||
| 1073 | inode->i_ctime.tv_sec = stat->st_ctime_sec; | ||
| 1074 | inode->i_ctime.tv_nsec = stat->st_ctime_nsec; | ||
| 1075 | inode->i_uid = stat->st_uid; | ||
| 1076 | inode->i_gid = stat->st_gid; | ||
| 1077 | inode->i_nlink = stat->st_nlink; | ||
| 1078 | inode->i_mode = stat->st_mode; | ||
| 1079 | inode->i_rdev = new_decode_dev(stat->st_rdev); | ||
| 1080 | |||
| 1081 | if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode))) | ||
| 1082 | init_special_inode(inode, inode->i_mode, inode->i_rdev); | ||
| 1083 | |||
| 1084 | i_size_write(inode, stat->st_size); | ||
| 1085 | inode->i_blocks = stat->st_blocks; | ||
| 1086 | } else { | ||
| 1087 | if (stat->st_result_mask & P9_STATS_ATIME) { | ||
| 1088 | inode->i_atime.tv_sec = stat->st_atime_sec; | ||
| 1089 | inode->i_atime.tv_nsec = stat->st_atime_nsec; | ||
| 1090 | } | ||
| 1091 | if (stat->st_result_mask & P9_STATS_MTIME) { | ||
| 1092 | inode->i_mtime.tv_sec = stat->st_mtime_sec; | ||
| 1093 | inode->i_mtime.tv_nsec = stat->st_mtime_nsec; | ||
| 1094 | } | ||
| 1095 | if (stat->st_result_mask & P9_STATS_CTIME) { | ||
| 1096 | inode->i_ctime.tv_sec = stat->st_ctime_sec; | ||
| 1097 | inode->i_ctime.tv_nsec = stat->st_ctime_nsec; | ||
| 1098 | } | ||
| 1099 | if (stat->st_result_mask & P9_STATS_UID) | ||
| 1100 | inode->i_uid = stat->st_uid; | ||
| 1101 | if (stat->st_result_mask & P9_STATS_GID) | ||
| 1102 | inode->i_gid = stat->st_gid; | ||
| 1103 | if (stat->st_result_mask & P9_STATS_NLINK) | ||
| 1104 | inode->i_nlink = stat->st_nlink; | ||
| 1105 | if (stat->st_result_mask & P9_STATS_MODE) { | ||
| 1106 | inode->i_mode = stat->st_mode; | ||
| 1107 | if ((S_ISBLK(inode->i_mode)) || | ||
| 1108 | (S_ISCHR(inode->i_mode))) | ||
| 1109 | init_special_inode(inode, inode->i_mode, | ||
| 1110 | inode->i_rdev); | ||
| 1111 | } | ||
| 1112 | if (stat->st_result_mask & P9_STATS_RDEV) | ||
| 1113 | inode->i_rdev = new_decode_dev(stat->st_rdev); | ||
| 1114 | if (stat->st_result_mask & P9_STATS_SIZE) | ||
| 1115 | i_size_write(inode, stat->st_size); | ||
| 1116 | if (stat->st_result_mask & P9_STATS_BLOCKS) | ||
| 1117 | inode->i_blocks = stat->st_blocks; | ||
| 1118 | } | ||
| 1119 | if (stat->st_result_mask & P9_STATS_GEN) | ||
| 1120 | inode->i_generation = stat->st_gen; | ||
| 1121 | |||
| 1122 | /* Currently we don't support P9_STATS_BTIME and P9_STATS_DATA_VERSION | ||
| 1123 | * because the inode structure does not have fields for them. | ||
| 1124 | */ | ||
| 1125 | } | ||
| 1126 | |||
| 1127 | /** | ||
| 983 | * v9fs_qid2ino - convert qid into inode number | 1128 | * v9fs_qid2ino - convert qid into inode number |
| 984 | * @qid: qid to hash | 1129 | * @qid: qid to hash |
| 985 | * | 1130 | * |
| @@ -1254,7 +1399,7 @@ static const struct inode_operations v9fs_dir_inode_operations_dotl = { | |||
| 1254 | .rmdir = v9fs_vfs_rmdir, | 1399 | .rmdir = v9fs_vfs_rmdir, |
| 1255 | .mknod = v9fs_vfs_mknod, | 1400 | .mknod = v9fs_vfs_mknod, |
| 1256 | .rename = v9fs_vfs_rename, | 1401 | .rename = v9fs_vfs_rename, |
| 1257 | .getattr = v9fs_vfs_getattr, | 1402 | .getattr = v9fs_vfs_getattr_dotl, |
| 1258 | .setattr = v9fs_vfs_setattr, | 1403 | .setattr = v9fs_vfs_setattr, |
| 1259 | }; | 1404 | }; |
| 1260 | 1405 | ||
| @@ -1276,7 +1421,7 @@ static const struct inode_operations v9fs_file_inode_operations = { | |||
| 1276 | }; | 1421 | }; |
| 1277 | 1422 | ||
| 1278 | static const struct inode_operations v9fs_file_inode_operations_dotl = { | 1423 | static const struct inode_operations v9fs_file_inode_operations_dotl = { |
| 1279 | .getattr = v9fs_vfs_getattr, | 1424 | .getattr = v9fs_vfs_getattr_dotl, |
| 1280 | .setattr = v9fs_vfs_setattr, | 1425 | .setattr = v9fs_vfs_setattr, |
| 1281 | }; | 1426 | }; |
| 1282 | 1427 | ||
| @@ -1292,6 +1437,6 @@ static const struct inode_operations v9fs_symlink_inode_operations_dotl = { | |||
| 1292 | .readlink = generic_readlink, | 1437 | .readlink = generic_readlink, |
| 1293 | .follow_link = v9fs_vfs_follow_link, | 1438 | .follow_link = v9fs_vfs_follow_link, |
| 1294 | .put_link = v9fs_vfs_put_link, | 1439 | .put_link = v9fs_vfs_put_link, |
| 1295 | .getattr = v9fs_vfs_getattr, | 1440 | .getattr = v9fs_vfs_getattr_dotl, |
| 1296 | .setattr = v9fs_vfs_setattr, | 1441 | .setattr = v9fs_vfs_setattr, |
| 1297 | }; | 1442 | }; |
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index be74d020436e..3623f692b448 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c | |||
| @@ -107,7 +107,6 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags, | |||
| 107 | struct inode *inode = NULL; | 107 | struct inode *inode = NULL; |
| 108 | struct dentry *root = NULL; | 108 | struct dentry *root = NULL; |
| 109 | struct v9fs_session_info *v9ses = NULL; | 109 | struct v9fs_session_info *v9ses = NULL; |
| 110 | struct p9_wstat *st = NULL; | ||
| 111 | int mode = S_IRWXUGO | S_ISVTX; | 110 | int mode = S_IRWXUGO | S_ISVTX; |
| 112 | struct p9_fid *fid; | 111 | struct p9_fid *fid; |
| 113 | int retval = 0; | 112 | int retval = 0; |
| @@ -124,16 +123,10 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags, | |||
| 124 | goto close_session; | 123 | goto close_session; |
| 125 | } | 124 | } |
| 126 | 125 | ||
| 127 | st = p9_client_stat(fid); | ||
| 128 | if (IS_ERR(st)) { | ||
| 129 | retval = PTR_ERR(st); | ||
| 130 | goto clunk_fid; | ||
| 131 | } | ||
| 132 | |||
| 133 | sb = sget(fs_type, NULL, v9fs_set_super, v9ses); | 126 | sb = sget(fs_type, NULL, v9fs_set_super, v9ses); |
| 134 | if (IS_ERR(sb)) { | 127 | if (IS_ERR(sb)) { |
| 135 | retval = PTR_ERR(sb); | 128 | retval = PTR_ERR(sb); |
| 136 | goto free_stat; | 129 | goto clunk_fid; |
| 137 | } | 130 | } |
| 138 | v9fs_fill_super(sb, v9ses, flags, data); | 131 | v9fs_fill_super(sb, v9ses, flags, data); |
| 139 | 132 | ||
| @@ -151,22 +144,38 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags, | |||
| 151 | } | 144 | } |
| 152 | 145 | ||
| 153 | sb->s_root = root; | 146 | sb->s_root = root; |
| 154 | root->d_inode->i_ino = v9fs_qid2ino(&st->qid); | ||
| 155 | 147 | ||
| 156 | v9fs_stat2inode(st, root->d_inode, sb); | 148 | if (v9fs_proto_dotl(v9ses)) { |
| 149 | struct p9_stat_dotl *st = NULL; | ||
| 150 | st = p9_client_getattr_dotl(fid, P9_STATS_BASIC); | ||
| 151 | if (IS_ERR(st)) { | ||
| 152 | retval = PTR_ERR(st); | ||
| 153 | goto clunk_fid; | ||
| 154 | } | ||
| 155 | |||
| 156 | v9fs_stat2inode_dotl(st, root->d_inode); | ||
| 157 | kfree(st); | ||
| 158 | } else { | ||
| 159 | struct p9_wstat *st = NULL; | ||
| 160 | st = p9_client_stat(fid); | ||
| 161 | if (IS_ERR(st)) { | ||
| 162 | retval = PTR_ERR(st); | ||
| 163 | goto clunk_fid; | ||
| 164 | } | ||
| 165 | |||
| 166 | root->d_inode->i_ino = v9fs_qid2ino(&st->qid); | ||
| 167 | v9fs_stat2inode(st, root->d_inode, sb); | ||
| 168 | |||
| 169 | p9stat_free(st); | ||
| 170 | kfree(st); | ||
| 171 | } | ||
| 157 | 172 | ||
| 158 | v9fs_fid_add(root, fid); | 173 | v9fs_fid_add(root, fid); |
| 159 | p9stat_free(st); | ||
| 160 | kfree(st); | ||
| 161 | 174 | ||
| 162 | P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n"); | 175 | P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n"); |
| 163 | simple_set_mnt(mnt, sb); | 176 | simple_set_mnt(mnt, sb); |
| 164 | return 0; | 177 | return 0; |
| 165 | 178 | ||
| 166 | free_stat: | ||
| 167 | p9stat_free(st); | ||
| 168 | kfree(st); | ||
| 169 | |||
| 170 | clunk_fid: | 179 | clunk_fid: |
| 171 | p9_client_clunk(fid); | 180 | p9_client_clunk(fid); |
| 172 | 181 | ||
| @@ -176,8 +185,6 @@ close_session: | |||
| 176 | return retval; | 185 | return retval; |
| 177 | 186 | ||
| 178 | release_sb: | 187 | release_sb: |
| 179 | p9stat_free(st); | ||
| 180 | kfree(st); | ||
| 181 | deactivate_locked_super(sb); | 188 | deactivate_locked_super(sb); |
| 182 | return retval; | 189 | return retval; |
| 183 | } | 190 | } |
diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h index f1b0b310265d..ab12e1c9cc7e 100644 --- a/include/net/9p/9p.h +++ b/include/net/9p/9p.h | |||
| @@ -133,6 +133,8 @@ enum p9_msg_t { | |||
| 133 | P9_RSTATFS, | 133 | P9_RSTATFS, |
| 134 | P9_TRENAME = 20, | 134 | P9_TRENAME = 20, |
| 135 | P9_RRENAME, | 135 | P9_RRENAME, |
| 136 | P9_TGETATTR = 24, | ||
| 137 | P9_RGETATTR, | ||
| 136 | P9_TREADDIR = 40, | 138 | P9_TREADDIR = 40, |
| 137 | P9_RREADDIR, | 139 | P9_RREADDIR, |
| 138 | P9_TVERSION = 100, | 140 | P9_TVERSION = 100, |
| @@ -362,6 +364,48 @@ struct p9_wstat { | |||
| 362 | u32 n_muid; /* 9p2000.u extensions */ | 364 | u32 n_muid; /* 9p2000.u extensions */ |
| 363 | }; | 365 | }; |
| 364 | 366 | ||
| 367 | struct p9_stat_dotl { | ||
| 368 | u64 st_result_mask; | ||
| 369 | struct p9_qid qid; | ||
| 370 | u32 st_mode; | ||
| 371 | u32 st_uid; | ||
| 372 | u32 st_gid; | ||
| 373 | u64 st_nlink; | ||
| 374 | u64 st_rdev; | ||
| 375 | u64 st_size; | ||
| 376 | u64 st_blksize; | ||
| 377 | u64 st_blocks; | ||
| 378 | u64 st_atime_sec; | ||
| 379 | u64 st_atime_nsec; | ||
| 380 | u64 st_mtime_sec; | ||
| 381 | u64 st_mtime_nsec; | ||
| 382 | u64 st_ctime_sec; | ||
| 383 | u64 st_ctime_nsec; | ||
| 384 | u64 st_btime_sec; | ||
| 385 | u64 st_btime_nsec; | ||
| 386 | u64 st_gen; | ||
| 387 | u64 st_data_version; | ||
| 388 | }; | ||
| 389 | |||
| 390 | #define P9_STATS_MODE 0x00000001ULL | ||
| 391 | #define P9_STATS_NLINK 0x00000002ULL | ||
| 392 | #define P9_STATS_UID 0x00000004ULL | ||
| 393 | #define P9_STATS_GID 0x00000008ULL | ||
| 394 | #define P9_STATS_RDEV 0x00000010ULL | ||
| 395 | #define P9_STATS_ATIME 0x00000020ULL | ||
| 396 | #define P9_STATS_MTIME 0x00000040ULL | ||
| 397 | #define P9_STATS_CTIME 0x00000080ULL | ||
| 398 | #define P9_STATS_INO 0x00000100ULL | ||
| 399 | #define P9_STATS_SIZE 0x00000200ULL | ||
| 400 | #define P9_STATS_BLOCKS 0x00000400ULL | ||
| 401 | |||
| 402 | #define P9_STATS_BTIME 0x00000800ULL | ||
| 403 | #define P9_STATS_GEN 0x00001000ULL | ||
| 404 | #define P9_STATS_DATA_VERSION 0x00002000ULL | ||
| 405 | |||
| 406 | #define P9_STATS_BASIC 0x000007ffULL /* Mask for fields up to BLOCKS */ | ||
| 407 | #define P9_STATS_ALL 0x00003fffULL /* Mask for All fields above */ | ||
| 408 | |||
| 365 | /* Structures for Protocol Operations */ | 409 | /* Structures for Protocol Operations */ |
| 366 | struct p9_tstatfs { | 410 | struct p9_tstatfs { |
| 367 | u32 fid; | 411 | u32 fid; |
diff --git a/include/net/9p/client.h b/include/net/9p/client.h index 2ec93685e6db..6462eec435bc 100644 --- a/include/net/9p/client.h +++ b/include/net/9p/client.h | |||
| @@ -238,6 +238,9 @@ int p9dirent_read(char *buf, int len, struct p9_dirent *dirent, | |||
| 238 | struct p9_wstat *p9_client_stat(struct p9_fid *fid); | 238 | struct p9_wstat *p9_client_stat(struct p9_fid *fid); |
| 239 | int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst); | 239 | int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst); |
| 240 | 240 | ||
| 241 | struct p9_stat_dotl *p9_client_getattr_dotl(struct p9_fid *fid, | ||
| 242 | u64 request_mask); | ||
| 243 | |||
| 241 | struct p9_req_t *p9_tag_lookup(struct p9_client *, u16); | 244 | struct p9_req_t *p9_tag_lookup(struct p9_client *, u16); |
| 242 | void p9_client_cb(struct p9_client *c, struct p9_req_t *req); | 245 | void p9_client_cb(struct p9_client *c, struct p9_req_t *req); |
| 243 | 246 | ||
diff --git a/net/9p/client.c b/net/9p/client.c index 4ff068e98f76..5e97118da3bf 100644 --- a/net/9p/client.c +++ b/net/9p/client.c | |||
| @@ -1303,6 +1303,65 @@ error: | |||
| 1303 | } | 1303 | } |
| 1304 | EXPORT_SYMBOL(p9_client_stat); | 1304 | EXPORT_SYMBOL(p9_client_stat); |
| 1305 | 1305 | ||
| 1306 | struct p9_stat_dotl *p9_client_getattr_dotl(struct p9_fid *fid, | ||
| 1307 | u64 request_mask) | ||
| 1308 | { | ||
| 1309 | int err; | ||
| 1310 | struct p9_client *clnt; | ||
| 1311 | struct p9_stat_dotl *ret = kmalloc(sizeof(struct p9_stat_dotl), | ||
| 1312 | GFP_KERNEL); | ||
| 1313 | struct p9_req_t *req; | ||
| 1314 | |||
| 1315 | P9_DPRINTK(P9_DEBUG_9P, ">>> TGETATTR fid %d, request_mask %lld\n", | ||
| 1316 | fid->fid, request_mask); | ||
| 1317 | |||
| 1318 | if (!ret) | ||
| 1319 | return ERR_PTR(-ENOMEM); | ||
| 1320 | |||
| 1321 | err = 0; | ||
| 1322 | clnt = fid->clnt; | ||
| 1323 | |||
| 1324 | req = p9_client_rpc(clnt, P9_TGETATTR, "dq", fid->fid, request_mask); | ||
| 1325 | if (IS_ERR(req)) { | ||
| 1326 | err = PTR_ERR(req); | ||
| 1327 | goto error; | ||
| 1328 | } | ||
| 1329 | |||
| 1330 | err = p9pdu_readf(req->rc, clnt->proto_version, "A", ret); | ||
| 1331 | if (err) { | ||
| 1332 | p9pdu_dump(1, req->rc); | ||
| 1333 | p9_free_req(clnt, req); | ||
| 1334 | goto error; | ||
| 1335 | } | ||
| 1336 | |||
| 1337 | P9_DPRINTK(P9_DEBUG_9P, | ||
| 1338 | "<<< RGETATTR st_result_mask=%lld\n" | ||
| 1339 | "<<< qid=%x.%llx.%x\n" | ||
| 1340 | "<<< st_mode=%8.8x st_nlink=%llu\n" | ||
| 1341 | "<<< st_uid=%d st_gid=%d\n" | ||
| 1342 | "<<< st_rdev=%llx st_size=%llx st_blksize=%llu st_blocks=%llu\n" | ||
| 1343 | "<<< st_atime_sec=%lld st_atime_nsec=%lld\n" | ||
| 1344 | "<<< st_mtime_sec=%lld st_mtime_nsec=%lld\n" | ||
| 1345 | "<<< st_ctime_sec=%lld st_ctime_nsec=%lld\n" | ||
| 1346 | "<<< st_btime_sec=%lld st_btime_nsec=%lld\n" | ||
| 1347 | "<<< st_gen=%lld st_data_version=%lld", | ||
| 1348 | ret->st_result_mask, ret->qid.type, ret->qid.path, | ||
| 1349 | ret->qid.version, ret->st_mode, ret->st_nlink, ret->st_uid, | ||
| 1350 | ret->st_gid, ret->st_rdev, ret->st_size, ret->st_blksize, | ||
| 1351 | ret->st_blocks, ret->st_atime_sec, ret->st_atime_nsec, | ||
| 1352 | ret->st_mtime_sec, ret->st_mtime_nsec, ret->st_ctime_sec, | ||
| 1353 | ret->st_ctime_nsec, ret->st_btime_sec, ret->st_btime_nsec, | ||
| 1354 | ret->st_gen, ret->st_data_version); | ||
| 1355 | |||
| 1356 | p9_free_req(clnt, req); | ||
| 1357 | return ret; | ||
| 1358 | |||
| 1359 | error: | ||
| 1360 | kfree(ret); | ||
| 1361 | return ERR_PTR(err); | ||
| 1362 | } | ||
| 1363 | EXPORT_SYMBOL(p9_client_getattr_dotl); | ||
| 1364 | |||
| 1306 | static int p9_client_statsize(struct p9_wstat *wst, int proto_version) | 1365 | static int p9_client_statsize(struct p9_wstat *wst, int proto_version) |
| 1307 | { | 1366 | { |
| 1308 | int ret; | 1367 | int ret; |
diff --git a/net/9p/protocol.c b/net/9p/protocol.c index b645c8263538..3e4f77695891 100644 --- a/net/9p/protocol.c +++ b/net/9p/protocol.c | |||
| @@ -141,6 +141,7 @@ pdu_write_u(struct p9_fcall *pdu, const char __user *udata, size_t size) | |||
| 141 | D - data blob (int32_t size followed by void *, results are not freed) | 141 | D - data blob (int32_t size followed by void *, results are not freed) |
| 142 | T - array of strings (int16_t count, followed by strings) | 142 | T - array of strings (int16_t count, followed by strings) |
| 143 | R - array of qids (int16_t count, followed by qids) | 143 | R - array of qids (int16_t count, followed by qids) |
| 144 | A - stat for 9p2000.L (p9_stat_dotl) | ||
| 144 | ? - if optional = 1, continue parsing | 145 | ? - if optional = 1, continue parsing |
| 145 | */ | 146 | */ |
| 146 | 147 | ||
| @@ -340,6 +341,33 @@ p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt, | |||
| 340 | } | 341 | } |
| 341 | } | 342 | } |
| 342 | break; | 343 | break; |
| 344 | case 'A': { | ||
| 345 | struct p9_stat_dotl *stbuf = | ||
| 346 | va_arg(ap, struct p9_stat_dotl *); | ||
| 347 | |||
| 348 | memset(stbuf, 0, sizeof(struct p9_stat_dotl)); | ||
| 349 | errcode = | ||
| 350 | p9pdu_readf(pdu, proto_version, | ||
| 351 | "qQdddqqqqqqqqqqqqqqq", | ||
| 352 | &stbuf->st_result_mask, | ||
| 353 | &stbuf->qid, | ||
| 354 | &stbuf->st_mode, | ||
| 355 | &stbuf->st_uid, &stbuf->st_gid, | ||
| 356 | &stbuf->st_nlink, | ||
| 357 | &stbuf->st_rdev, &stbuf->st_size, | ||
| 358 | &stbuf->st_blksize, &stbuf->st_blocks, | ||
| 359 | &stbuf->st_atime_sec, | ||
| 360 | &stbuf->st_atime_nsec, | ||
| 361 | &stbuf->st_mtime_sec, | ||
| 362 | &stbuf->st_mtime_nsec, | ||
| 363 | &stbuf->st_ctime_sec, | ||
| 364 | &stbuf->st_ctime_nsec, | ||
| 365 | &stbuf->st_btime_sec, | ||
| 366 | &stbuf->st_btime_nsec, | ||
| 367 | &stbuf->st_gen, | ||
| 368 | &stbuf->st_data_version); | ||
| 369 | } | ||
| 370 | break; | ||
| 343 | case '?': | 371 | case '?': |
| 344 | if ((proto_version != p9_proto_2000u) && | 372 | if ((proto_version != p9_proto_2000u) && |
| 345 | (proto_version != p9_proto_2000L)) | 373 | (proto_version != p9_proto_2000L)) |
