diff options
Diffstat (limited to 'fs/9p/vfs_inode.c')
| -rw-r--r-- | fs/9p/vfs_inode.c | 177 |
1 files changed, 161 insertions, 16 deletions
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 | }; |
