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)) |