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