Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

NFSD: Get response size before operation for all RPCs

NFSD usess PAGE_SIZE as the reply size estimate for RPCs which don't
support op_rsize_bop(), A PAGE_SIZE (4096) is larger than many real
response sizes, eg, access (op_encode_hdr_size + 2), seek
(op_encode_hdr_size + 3).

This patch just adds op_rsize_bop() for all RPCs getting response size.

An overestimate is generally safe but the tighter estimates are probably
better.

Signed-off-by: Kinglong Mee <kinglongmee@gmail.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>

authored by

Kinglong Mee and committed by
J. Bruce Fields
2282cd2c 82743380

+63 -6
+63 -6
fs/nfsd/nfs4proc.c
··· 1842 1842 return (op_encode_hdr_size + op_encode_stateid_maxsz)* sizeof(__be32); 1843 1843 } 1844 1844 1845 + static inline u32 nfsd4_access_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) 1846 + { 1847 + /* ac_supported, ac_resp_access */ 1848 + return (op_encode_hdr_size + 2)* sizeof(__be32); 1849 + } 1850 + 1845 1851 static inline u32 nfsd4_commit_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) 1846 1852 { 1847 1853 return (op_encode_hdr_size + op_encode_verifier_maxsz) * sizeof(__be32); ··· 1902 1896 return ret; 1903 1897 } 1904 1898 1899 + static inline u32 nfsd4_getfh_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) 1900 + { 1901 + return (op_encode_hdr_size + 1) * sizeof(__be32) + NFS4_FHSIZE; 1902 + } 1903 + 1905 1904 static inline u32 nfsd4_link_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) 1906 1905 { 1907 1906 return (op_encode_hdr_size + op_encode_change_info_maxsz) ··· 1948 1937 XDR_QUADLEN(rlen)) * sizeof(__be32); 1949 1938 } 1950 1939 1940 + static inline u32 nfsd4_readlink_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) 1941 + { 1942 + return (op_encode_hdr_size + 1) * sizeof(__be32) + PAGE_SIZE; 1943 + } 1944 + 1951 1945 static inline u32 nfsd4_remove_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) 1952 1946 { 1953 1947 return (op_encode_hdr_size + op_encode_change_info_maxsz) ··· 1972 1956 + XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 5) * sizeof(__be32); 1973 1957 } 1974 1958 1959 + static inline u32 nfsd4_test_stateid_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) 1960 + { 1961 + return (op_encode_hdr_size + 1 + op->u.test_stateid.ts_num_ids) 1962 + * sizeof(__be32); 1963 + } 1964 + 1975 1965 static inline u32 nfsd4_setattr_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) 1976 1966 { 1977 1967 return (op_encode_hdr_size + nfs4_fattr_bitmap_maxsz) * sizeof(__be32); 1968 + } 1969 + 1970 + static inline u32 nfsd4_secinfo_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) 1971 + { 1972 + return (op_encode_hdr_size + RPC_AUTH_MAXFLAVOR * 1973 + (4 + XDR_QUADLEN(GSS_OID_MAX_LEN))) * sizeof(__be32); 1978 1974 } 1979 1975 1980 1976 static inline u32 nfsd4_setclientid_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) ··· 2043 2015 } 2044 2016 2045 2017 #ifdef CONFIG_NFSD_PNFS 2018 + static inline u32 nfsd4_getdeviceinfo_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) 2019 + { 2020 + u32 maxcount = 0, rlen = 0; 2021 + 2022 + maxcount = svc_max_payload(rqstp); 2023 + rlen = min(op->u.getdeviceinfo.gd_maxcount, maxcount); 2024 + 2025 + return (op_encode_hdr_size + 2026 + 1 /* gd_layout_type*/ + 2027 + XDR_QUADLEN(rlen) + 2028 + 2 /* gd_notify_types */) * sizeof(__be32); 2029 + } 2030 + 2046 2031 /* 2047 2032 * At this stage we don't really know what layout driver will handle the request, 2048 2033 * so we need to define an arbitrary upper bound here. ··· 2085 2044 } 2086 2045 #endif /* CONFIG_NFSD_PNFS */ 2087 2046 2047 + 2048 + static inline u32 nfsd4_seek_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) 2049 + { 2050 + return (op_encode_hdr_size + 3) * sizeof(__be32); 2051 + } 2052 + 2088 2053 static struct nfsd4_operation nfsd4_ops[] = { 2089 2054 [OP_ACCESS] = { 2090 2055 .op_func = (nfsd4op_func)nfsd4_access, 2091 2056 .op_name = "OP_ACCESS", 2057 + .op_rsize_bop = (nfsd4op_rsize)nfsd4_access_rsize, 2092 2058 }, 2093 2059 [OP_CLOSE] = { 2094 2060 .op_func = (nfsd4op_func)nfsd4_close, ··· 2133 2085 [OP_GETFH] = { 2134 2086 .op_func = (nfsd4op_func)nfsd4_getfh, 2135 2087 .op_name = "OP_GETFH", 2088 + .op_rsize_bop = (nfsd4op_rsize)nfsd4_getfh_rsize, 2136 2089 }, 2137 2090 [OP_LINK] = { 2138 2091 .op_func = (nfsd4op_func)nfsd4_link, ··· 2152 2103 [OP_LOCKT] = { 2153 2104 .op_func = (nfsd4op_func)nfsd4_lockt, 2154 2105 .op_name = "OP_LOCKT", 2106 + .op_rsize_bop = (nfsd4op_rsize)nfsd4_lock_rsize, 2155 2107 }, 2156 2108 [OP_LOCKU] = { 2157 2109 .op_func = (nfsd4op_func)nfsd4_locku, ··· 2165 2115 .op_func = (nfsd4op_func)nfsd4_lookup, 2166 2116 .op_flags = OP_HANDLES_WRONGSEC | OP_CLEAR_STATEID, 2167 2117 .op_name = "OP_LOOKUP", 2118 + .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, 2168 2119 }, 2169 2120 [OP_LOOKUPP] = { 2170 2121 .op_func = (nfsd4op_func)nfsd4_lookupp, 2171 2122 .op_flags = OP_HANDLES_WRONGSEC | OP_CLEAR_STATEID, 2172 2123 .op_name = "OP_LOOKUPP", 2124 + .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, 2173 2125 }, 2174 2126 [OP_NVERIFY] = { 2175 2127 .op_func = (nfsd4op_func)nfsd4_nverify, 2176 2128 .op_name = "OP_NVERIFY", 2129 + .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, 2177 2130 }, 2178 2131 [OP_OPEN] = { 2179 2132 .op_func = (nfsd4op_func)nfsd4_open, ··· 2234 2181 [OP_READLINK] = { 2235 2182 .op_func = (nfsd4op_func)nfsd4_readlink, 2236 2183 .op_name = "OP_READLINK", 2184 + .op_rsize_bop = (nfsd4op_rsize)nfsd4_readlink_rsize, 2237 2185 }, 2238 2186 [OP_REMOVE] = { 2239 2187 .op_func = (nfsd4op_func)nfsd4_remove, ··· 2273 2219 .op_func = (nfsd4op_func)nfsd4_secinfo, 2274 2220 .op_flags = OP_HANDLES_WRONGSEC, 2275 2221 .op_name = "OP_SECINFO", 2222 + .op_rsize_bop = (nfsd4op_rsize)nfsd4_secinfo_rsize, 2276 2223 }, 2277 2224 [OP_SETATTR] = { 2278 2225 .op_func = (nfsd4op_func)nfsd4_setattr, ··· 2299 2244 [OP_VERIFY] = { 2300 2245 .op_func = (nfsd4op_func)nfsd4_verify, 2301 2246 .op_name = "OP_VERIFY", 2247 + .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, 2302 2248 }, 2303 2249 [OP_WRITE] = { 2304 2250 .op_func = (nfsd4op_func)nfsd4_write, ··· 2374 2318 .op_func = (nfsd4op_func)nfsd4_secinfo_no_name, 2375 2319 .op_flags = OP_HANDLES_WRONGSEC, 2376 2320 .op_name = "OP_SECINFO_NO_NAME", 2321 + .op_rsize_bop = (nfsd4op_rsize)nfsd4_secinfo_rsize, 2377 2322 }, 2378 2323 [OP_TEST_STATEID] = { 2379 2324 .op_func = (nfsd4op_func)nfsd4_test_stateid, 2380 2325 .op_flags = ALLOWED_WITHOUT_FH, 2381 2326 .op_name = "OP_TEST_STATEID", 2327 + .op_rsize_bop = (nfsd4op_rsize)nfsd4_test_stateid_rsize, 2382 2328 }, 2383 2329 [OP_FREE_STATEID] = { 2384 2330 .op_func = (nfsd4op_func)nfsd4_free_stateid, ··· 2394 2336 .op_func = (nfsd4op_func)nfsd4_getdeviceinfo, 2395 2337 .op_flags = ALLOWED_WITHOUT_FH, 2396 2338 .op_name = "OP_GETDEVICEINFO", 2339 + .op_rsize_bop = (nfsd4op_rsize)nfsd4_getdeviceinfo_rsize, 2397 2340 }, 2398 2341 [OP_LAYOUTGET] = { 2399 2342 .op_func = (nfsd4op_func)nfsd4_layoutget, ··· 2444 2385 [OP_SEEK] = { 2445 2386 .op_func = (nfsd4op_func)nfsd4_seek, 2446 2387 .op_name = "OP_SEEK", 2388 + .op_rsize_bop = (nfsd4op_rsize)nfsd4_seek_rsize, 2447 2389 }, 2448 2390 }; 2449 2391 ··· 2489 2429 2490 2430 int nfsd4_max_reply(struct svc_rqst *rqstp, struct nfsd4_op *op) 2491 2431 { 2492 - struct nfsd4_operation *opdesc; 2493 - nfsd4op_rsize estimator; 2494 - 2495 2432 if (op->opnum == OP_ILLEGAL) 2496 2433 return op_encode_hdr_size * sizeof(__be32); 2497 - opdesc = OPDESC(op); 2498 - estimator = opdesc->op_rsize_bop; 2499 - return estimator ? estimator(rqstp, op) : PAGE_SIZE; 2434 + 2435 + BUG_ON(OPDESC(op)->op_rsize_bop == NULL); 2436 + return OPDESC(op)->op_rsize_bop(rqstp, op); 2500 2437 } 2501 2438 2502 2439 void warn_on_nonidempotent_op(struct nfsd4_op *op)