diff options
Diffstat (limited to 'fs/nfsd/vfs.c')
-rw-r--r-- | fs/nfsd/vfs.c | 93 |
1 files changed, 52 insertions, 41 deletions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 3c111120b619..96360a83cb91 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -604,7 +604,7 @@ nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, struct nfs4_ac | |||
604 | return error; | 604 | return error; |
605 | } | 605 | } |
606 | 606 | ||
607 | #endif /* defined(CONFIG_NFS_V4) */ | 607 | #endif /* defined(CONFIG_NFSD_V4) */ |
608 | 608 | ||
609 | #ifdef CONFIG_NFSD_V3 | 609 | #ifdef CONFIG_NFSD_V3 |
610 | /* | 610 | /* |
@@ -903,7 +903,6 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | |||
903 | loff_t offset, struct kvec *vec, int vlen, unsigned long *count) | 903 | loff_t offset, struct kvec *vec, int vlen, unsigned long *count) |
904 | { | 904 | { |
905 | struct inode *inode; | 905 | struct inode *inode; |
906 | struct raparms *ra; | ||
907 | mm_segment_t oldfs; | 906 | mm_segment_t oldfs; |
908 | __be32 err; | 907 | __be32 err; |
909 | int host_err; | 908 | int host_err; |
@@ -914,12 +913,6 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | |||
914 | if (svc_msnfs(fhp) && !lock_may_read(inode, offset, *count)) | 913 | if (svc_msnfs(fhp) && !lock_may_read(inode, offset, *count)) |
915 | goto out; | 914 | goto out; |
916 | 915 | ||
917 | /* Get readahead parameters */ | ||
918 | ra = nfsd_get_raparms(inode->i_sb->s_dev, inode->i_ino); | ||
919 | |||
920 | if (ra && ra->p_set) | ||
921 | file->f_ra = ra->p_ra; | ||
922 | |||
923 | if (file->f_op->splice_read && rqstp->rq_splice_ok) { | 916 | if (file->f_op->splice_read && rqstp->rq_splice_ok) { |
924 | struct splice_desc sd = { | 917 | struct splice_desc sd = { |
925 | .len = 0, | 918 | .len = 0, |
@@ -937,21 +930,11 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | |||
937 | set_fs(oldfs); | 930 | set_fs(oldfs); |
938 | } | 931 | } |
939 | 932 | ||
940 | /* Write back readahead params */ | ||
941 | if (ra) { | ||
942 | struct raparm_hbucket *rab = &raparm_hash[ra->p_hindex]; | ||
943 | spin_lock(&rab->pb_lock); | ||
944 | ra->p_ra = file->f_ra; | ||
945 | ra->p_set = 1; | ||
946 | ra->p_count--; | ||
947 | spin_unlock(&rab->pb_lock); | ||
948 | } | ||
949 | |||
950 | if (host_err >= 0) { | 933 | if (host_err >= 0) { |
951 | nfsdstats.io_read += host_err; | 934 | nfsdstats.io_read += host_err; |
952 | *count = host_err; | 935 | *count = host_err; |
953 | err = 0; | 936 | err = 0; |
954 | fsnotify_access(file->f_path.dentry); | 937 | fsnotify_access(file); |
955 | } else | 938 | } else |
956 | err = nfserrno(host_err); | 939 | err = nfserrno(host_err); |
957 | out: | 940 | out: |
@@ -1062,7 +1045,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | |||
1062 | goto out_nfserr; | 1045 | goto out_nfserr; |
1063 | *cnt = host_err; | 1046 | *cnt = host_err; |
1064 | nfsdstats.io_write += host_err; | 1047 | nfsdstats.io_write += host_err; |
1065 | fsnotify_modify(file->f_path.dentry); | 1048 | fsnotify_modify(file); |
1066 | 1049 | ||
1067 | /* clear setuid/setgid flag after write */ | 1050 | /* clear setuid/setgid flag after write */ |
1068 | if (inode->i_mode & (S_ISUID | S_ISGID)) | 1051 | if (inode->i_mode & (S_ISUID | S_ISGID)) |
@@ -1086,8 +1069,45 @@ out: | |||
1086 | * on entry. On return, *count contains the number of bytes actually read. | 1069 | * on entry. On return, *count contains the number of bytes actually read. |
1087 | * N.B. After this call fhp needs an fh_put | 1070 | * N.B. After this call fhp needs an fh_put |
1088 | */ | 1071 | */ |
1072 | __be32 nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, | ||
1073 | loff_t offset, struct kvec *vec, int vlen, unsigned long *count) | ||
1074 | { | ||
1075 | struct file *file; | ||
1076 | struct inode *inode; | ||
1077 | struct raparms *ra; | ||
1078 | __be32 err; | ||
1079 | |||
1080 | err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file); | ||
1081 | if (err) | ||
1082 | return err; | ||
1083 | |||
1084 | inode = file->f_path.dentry->d_inode; | ||
1085 | |||
1086 | /* Get readahead parameters */ | ||
1087 | ra = nfsd_get_raparms(inode->i_sb->s_dev, inode->i_ino); | ||
1088 | |||
1089 | if (ra && ra->p_set) | ||
1090 | file->f_ra = ra->p_ra; | ||
1091 | |||
1092 | err = nfsd_vfs_read(rqstp, fhp, file, offset, vec, vlen, count); | ||
1093 | |||
1094 | /* Write back readahead params */ | ||
1095 | if (ra) { | ||
1096 | struct raparm_hbucket *rab = &raparm_hash[ra->p_hindex]; | ||
1097 | spin_lock(&rab->pb_lock); | ||
1098 | ra->p_ra = file->f_ra; | ||
1099 | ra->p_set = 1; | ||
1100 | ra->p_count--; | ||
1101 | spin_unlock(&rab->pb_lock); | ||
1102 | } | ||
1103 | |||
1104 | nfsd_close(file); | ||
1105 | return err; | ||
1106 | } | ||
1107 | |||
1108 | /* As above, but use the provided file descriptor. */ | ||
1089 | __be32 | 1109 | __be32 |
1090 | nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | 1110 | nfsd_read_file(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, |
1091 | loff_t offset, struct kvec *vec, int vlen, | 1111 | loff_t offset, struct kvec *vec, int vlen, |
1092 | unsigned long *count) | 1112 | unsigned long *count) |
1093 | { | 1113 | { |
@@ -1099,13 +1119,8 @@ nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | |||
1099 | if (err) | 1119 | if (err) |
1100 | goto out; | 1120 | goto out; |
1101 | err = nfsd_vfs_read(rqstp, fhp, file, offset, vec, vlen, count); | 1121 | err = nfsd_vfs_read(rqstp, fhp, file, offset, vec, vlen, count); |
1102 | } else { | 1122 | } else /* Note file may still be NULL in NFSv4 special stateid case: */ |
1103 | err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file); | 1123 | err = nfsd_read(rqstp, fhp, offset, vec, vlen, count); |
1104 | if (err) | ||
1105 | goto out; | ||
1106 | err = nfsd_vfs_read(rqstp, fhp, file, offset, vec, vlen, count); | ||
1107 | nfsd_close(file); | ||
1108 | } | ||
1109 | out: | 1124 | out: |
1110 | return err; | 1125 | return err; |
1111 | } | 1126 | } |
@@ -1631,7 +1646,7 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, | |||
1631 | char *name, int len, struct svc_fh *tfhp) | 1646 | char *name, int len, struct svc_fh *tfhp) |
1632 | { | 1647 | { |
1633 | struct dentry *ddir, *dnew, *dold; | 1648 | struct dentry *ddir, *dnew, *dold; |
1634 | struct inode *dirp, *dest; | 1649 | struct inode *dirp; |
1635 | __be32 err; | 1650 | __be32 err; |
1636 | int host_err; | 1651 | int host_err; |
1637 | 1652 | ||
@@ -1659,7 +1674,6 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, | |||
1659 | goto out_nfserr; | 1674 | goto out_nfserr; |
1660 | 1675 | ||
1661 | dold = tfhp->fh_dentry; | 1676 | dold = tfhp->fh_dentry; |
1662 | dest = dold->d_inode; | ||
1663 | 1677 | ||
1664 | host_err = mnt_want_write(tfhp->fh_export->ex_path.mnt); | 1678 | host_err = mnt_want_write(tfhp->fh_export->ex_path.mnt); |
1665 | if (host_err) { | 1679 | if (host_err) { |
@@ -2019,8 +2033,14 @@ out: | |||
2019 | __be32 | 2033 | __be32 |
2020 | nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat, int access) | 2034 | nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat, int access) |
2021 | { | 2035 | { |
2022 | __be32 err = fh_verify(rqstp, fhp, 0, NFSD_MAY_NOP | access); | 2036 | struct path path = { |
2023 | if (!err && vfs_statfs(fhp->fh_dentry,stat)) | 2037 | .mnt = fhp->fh_export->ex_path.mnt, |
2038 | .dentry = fhp->fh_dentry, | ||
2039 | }; | ||
2040 | __be32 err; | ||
2041 | |||
2042 | err = fh_verify(rqstp, fhp, 0, NFSD_MAY_NOP | access); | ||
2043 | if (!err && vfs_statfs(&path, stat)) | ||
2024 | err = nfserr_io; | 2044 | err = nfserr_io; |
2025 | return err; | 2045 | return err; |
2026 | } | 2046 | } |
@@ -2038,7 +2058,6 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp, | |||
2038 | struct dentry *dentry, int acc) | 2058 | struct dentry *dentry, int acc) |
2039 | { | 2059 | { |
2040 | struct inode *inode = dentry->d_inode; | 2060 | struct inode *inode = dentry->d_inode; |
2041 | struct path path; | ||
2042 | int err; | 2061 | int err; |
2043 | 2062 | ||
2044 | if (acc == NFSD_MAY_NOP) | 2063 | if (acc == NFSD_MAY_NOP) |
@@ -2111,15 +2130,7 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp, | |||
2111 | if (err == -EACCES && S_ISREG(inode->i_mode) && | 2130 | if (err == -EACCES && S_ISREG(inode->i_mode) && |
2112 | acc == (NFSD_MAY_READ | NFSD_MAY_OWNER_OVERRIDE)) | 2131 | acc == (NFSD_MAY_READ | NFSD_MAY_OWNER_OVERRIDE)) |
2113 | err = inode_permission(inode, MAY_EXEC); | 2132 | err = inode_permission(inode, MAY_EXEC); |
2114 | if (err) | ||
2115 | goto nfsd_out; | ||
2116 | 2133 | ||
2117 | /* Do integrity (permission) checking now, but defer incrementing | ||
2118 | * IMA counts to the actual file open. | ||
2119 | */ | ||
2120 | path.mnt = exp->ex_path.mnt; | ||
2121 | path.dentry = dentry; | ||
2122 | nfsd_out: | ||
2123 | return err? nfserrno(err) : 0; | 2134 | return err? nfserrno(err) : 0; |
2124 | } | 2135 | } |
2125 | 2136 | ||