aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4state.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-07-11 13:17:13 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-11 13:17:13 -0400
commit0ff08ba5d066619f9973bfcdb5a21320d54219d0 (patch)
tree526e4a5799eb3023e9d5d81e81c0964b1d928a3e /fs/nfsd/nfs4state.c
parentc72bb316916b1a6cf35e1d5238566ef27b0b7f80 (diff)
parentd109148111cdfcdae94f797dc142468bd0ff7557 (diff)
Merge branch 'for-3.11' of git://linux-nfs.org/~bfields/linux
Pull nfsd changes from Bruce Fields: "Changes this time include: - 4.1 enabled on the server by default: the last 4.1-specific issues I know of are fixed, so we're not going to find the rest of the bugs without more exposure. - Experimental support for NFSv4.2 MAC Labeling (to allow running selinux over NFS), from Dave Quigley. - Fixes for some delicate cache/upcall races that could cause rare server hangs; thanks to Neil Brown and Bodo Stroesser for extreme debugging persistence. - Fixes for some bugs found at the recent NFS bakeathon, mostly v4 and v4.1-specific, but also a generic bug handling fragmented rpc calls" * 'for-3.11' of git://linux-nfs.org/~bfields/linux: (31 commits) nfsd4: support minorversion 1 by default nfsd4: allow destroy_session over destroyed session svcrpc: fix failures to handle -1 uid's sunrpc: Don't schedule an upcall on a replaced cache entry. net/sunrpc: xpt_auth_cache should be ignored when expired. sunrpc/cache: ensure items removed from cache do not have pending upcalls. sunrpc/cache: use cache_fresh_unlocked consistently and correctly. sunrpc/cache: remove races with queuing an upcall. nfsd4: return delegation immediately if lease fails nfsd4: do not throw away 4.1 lock state on last unlock nfsd4: delegation-based open reclaims should bypass permissions svcrpc: don't error out on small tcp fragment svcrpc: fix handling of too-short rpc's nfsd4: minor read_buf cleanup nfsd4: fix decoding of compounds across page boundaries nfsd4: clean up nfs4_open_delegation NFSD: Don't give out read delegations on creates nfsd4: allow client to send no cb_sec flavors nfsd4: fail attempts to request gss on the backchannel nfsd4: implement minimal SP4_MACH_CRED ...
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r--fs/nfsd/nfs4state.c225
1 files changed, 152 insertions, 73 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index f17051838b41..280acef6f0dc 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -97,19 +97,20 @@ nfs4_lock_state(void)
97 97
98static void free_session(struct nfsd4_session *); 98static void free_session(struct nfsd4_session *);
99 99
100void nfsd4_put_session(struct nfsd4_session *ses) 100static bool is_session_dead(struct nfsd4_session *ses)
101{ 101{
102 atomic_dec(&ses->se_ref); 102 return ses->se_flags & NFS4_SESSION_DEAD;
103} 103}
104 104
105static bool is_session_dead(struct nfsd4_session *ses) 105void nfsd4_put_session(struct nfsd4_session *ses)
106{ 106{
107 return ses->se_flags & NFS4_SESSION_DEAD; 107 if (atomic_dec_and_test(&ses->se_ref) && is_session_dead(ses))
108 free_session(ses);
108} 109}
109 110
110static __be32 mark_session_dead_locked(struct nfsd4_session *ses) 111static __be32 mark_session_dead_locked(struct nfsd4_session *ses, int ref_held_by_me)
111{ 112{
112 if (atomic_read(&ses->se_ref)) 113 if (atomic_read(&ses->se_ref) > ref_held_by_me)
113 return nfserr_jukebox; 114 return nfserr_jukebox;
114 ses->se_flags |= NFS4_SESSION_DEAD; 115 ses->se_flags |= NFS4_SESSION_DEAD;
115 return nfs_ok; 116 return nfs_ok;
@@ -364,19 +365,12 @@ static struct nfs4_ol_stateid * nfs4_alloc_stateid(struct nfs4_client *clp)
364} 365}
365 366
366static struct nfs4_delegation * 367static struct nfs4_delegation *
367alloc_init_deleg(struct nfs4_client *clp, struct nfs4_ol_stateid *stp, struct svc_fh *current_fh, u32 type) 368alloc_init_deleg(struct nfs4_client *clp, struct nfs4_ol_stateid *stp, struct svc_fh *current_fh)
368{ 369{
369 struct nfs4_delegation *dp; 370 struct nfs4_delegation *dp;
370 struct nfs4_file *fp = stp->st_file; 371 struct nfs4_file *fp = stp->st_file;
371 372
372 dprintk("NFSD alloc_init_deleg\n"); 373 dprintk("NFSD alloc_init_deleg\n");
373 /*
374 * Major work on the lease subsystem (for example, to support
375 * calbacks on stat) will be required before we can support
376 * write delegations properly.
377 */
378 if (type != NFS4_OPEN_DELEGATE_READ)
379 return NULL;
380 if (fp->fi_had_conflict) 374 if (fp->fi_had_conflict)
381 return NULL; 375 return NULL;
382 if (num_delegations > max_delegations) 376 if (num_delegations > max_delegations)
@@ -397,7 +391,7 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_ol_stateid *stp, struct sv
397 INIT_LIST_HEAD(&dp->dl_recall_lru); 391 INIT_LIST_HEAD(&dp->dl_recall_lru);
398 get_nfs4_file(fp); 392 get_nfs4_file(fp);
399 dp->dl_file = fp; 393 dp->dl_file = fp;
400 dp->dl_type = type; 394 dp->dl_type = NFS4_OPEN_DELEGATE_READ;
401 fh_copy_shallow(&dp->dl_fh, &current_fh->fh_handle); 395 fh_copy_shallow(&dp->dl_fh, &current_fh->fh_handle);
402 dp->dl_time = 0; 396 dp->dl_time = 0;
403 atomic_set(&dp->dl_count, 1); 397 atomic_set(&dp->dl_count, 1);
@@ -1188,6 +1182,9 @@ static int copy_cred(struct svc_cred *target, struct svc_cred *source)
1188 target->cr_gid = source->cr_gid; 1182 target->cr_gid = source->cr_gid;
1189 target->cr_group_info = source->cr_group_info; 1183 target->cr_group_info = source->cr_group_info;
1190 get_group_info(target->cr_group_info); 1184 get_group_info(target->cr_group_info);
1185 target->cr_gss_mech = source->cr_gss_mech;
1186 if (source->cr_gss_mech)
1187 gss_mech_get(source->cr_gss_mech);
1191 return 0; 1188 return 0;
1192} 1189}
1193 1190
@@ -1262,6 +1259,31 @@ same_creds(struct svc_cred *cr1, struct svc_cred *cr2)
1262 return 0 == strcmp(cr1->cr_principal, cr2->cr_principal); 1259 return 0 == strcmp(cr1->cr_principal, cr2->cr_principal);
1263} 1260}
1264 1261
1262static bool svc_rqst_integrity_protected(struct svc_rqst *rqstp)
1263{
1264 struct svc_cred *cr = &rqstp->rq_cred;
1265 u32 service;
1266
1267 service = gss_pseudoflavor_to_service(cr->cr_gss_mech, cr->cr_flavor);
1268 return service == RPC_GSS_SVC_INTEGRITY ||
1269 service == RPC_GSS_SVC_PRIVACY;
1270}
1271
1272static bool mach_creds_match(struct nfs4_client *cl, struct svc_rqst *rqstp)
1273{
1274 struct svc_cred *cr = &rqstp->rq_cred;
1275
1276 if (!cl->cl_mach_cred)
1277 return true;
1278 if (cl->cl_cred.cr_gss_mech != cr->cr_gss_mech)
1279 return false;
1280 if (!svc_rqst_integrity_protected(rqstp))
1281 return false;
1282 if (!cr->cr_principal)
1283 return false;
1284 return 0 == strcmp(cl->cl_cred.cr_principal, cr->cr_principal);
1285}
1286
1265static void gen_clid(struct nfs4_client *clp, struct nfsd_net *nn) 1287static void gen_clid(struct nfs4_client *clp, struct nfsd_net *nn)
1266{ 1288{
1267 static u32 current_clientid = 1; 1289 static u32 current_clientid = 1;
@@ -1639,16 +1661,16 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
1639 if (exid->flags & ~EXCHGID4_FLAG_MASK_A) 1661 if (exid->flags & ~EXCHGID4_FLAG_MASK_A)
1640 return nfserr_inval; 1662 return nfserr_inval;
1641 1663
1642 /* Currently only support SP4_NONE */
1643 switch (exid->spa_how) { 1664 switch (exid->spa_how) {
1665 case SP4_MACH_CRED:
1666 if (!svc_rqst_integrity_protected(rqstp))
1667 return nfserr_inval;
1644 case SP4_NONE: 1668 case SP4_NONE:
1645 break; 1669 break;
1646 default: /* checked by xdr code */ 1670 default: /* checked by xdr code */
1647 WARN_ON_ONCE(1); 1671 WARN_ON_ONCE(1);
1648 case SP4_SSV: 1672 case SP4_SSV:
1649 return nfserr_encr_alg_unsupp; 1673 return nfserr_encr_alg_unsupp;
1650 case SP4_MACH_CRED:
1651 return nfserr_serverfault; /* no excuse :-/ */
1652 } 1674 }
1653 1675
1654 /* Cases below refer to rfc 5661 section 18.35.4: */ 1676 /* Cases below refer to rfc 5661 section 18.35.4: */
@@ -1663,6 +1685,10 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
1663 status = nfserr_inval; 1685 status = nfserr_inval;
1664 goto out; 1686 goto out;
1665 } 1687 }
1688 if (!mach_creds_match(conf, rqstp)) {
1689 status = nfserr_wrong_cred;
1690 goto out;
1691 }
1666 if (!creds_match) { /* case 9 */ 1692 if (!creds_match) { /* case 9 */
1667 status = nfserr_perm; 1693 status = nfserr_perm;
1668 goto out; 1694 goto out;
@@ -1709,7 +1735,8 @@ out_new:
1709 status = nfserr_jukebox; 1735 status = nfserr_jukebox;
1710 goto out; 1736 goto out;
1711 } 1737 }
1712 new->cl_minorversion = 1; 1738 new->cl_minorversion = cstate->minorversion;
1739 new->cl_mach_cred = (exid->spa_how == SP4_MACH_CRED);
1713 1740
1714 gen_clid(new, nn); 1741 gen_clid(new, nn);
1715 add_to_unconfirmed(new); 1742 add_to_unconfirmed(new);
@@ -1839,6 +1866,24 @@ static __be32 check_backchannel_attrs(struct nfsd4_channel_attrs *ca)
1839 return nfs_ok; 1866 return nfs_ok;
1840} 1867}
1841 1868
1869static __be32 nfsd4_check_cb_sec(struct nfsd4_cb_sec *cbs)
1870{
1871 switch (cbs->flavor) {
1872 case RPC_AUTH_NULL:
1873 case RPC_AUTH_UNIX:
1874 return nfs_ok;
1875 default:
1876 /*
1877 * GSS case: the spec doesn't allow us to return this
1878 * error. But it also doesn't allow us not to support
1879 * GSS.
1880 * I'd rather this fail hard than return some error the
1881 * client might think it can already handle:
1882 */
1883 return nfserr_encr_alg_unsupp;
1884 }
1885}
1886
1842__be32 1887__be32
1843nfsd4_create_session(struct svc_rqst *rqstp, 1888nfsd4_create_session(struct svc_rqst *rqstp,
1844 struct nfsd4_compound_state *cstate, 1889 struct nfsd4_compound_state *cstate,
@@ -1854,6 +1899,9 @@ nfsd4_create_session(struct svc_rqst *rqstp,
1854 1899
1855 if (cr_ses->flags & ~SESSION4_FLAG_MASK_A) 1900 if (cr_ses->flags & ~SESSION4_FLAG_MASK_A)
1856 return nfserr_inval; 1901 return nfserr_inval;
1902 status = nfsd4_check_cb_sec(&cr_ses->cb_sec);
1903 if (status)
1904 return status;
1857 status = check_forechannel_attrs(&cr_ses->fore_channel, nn); 1905 status = check_forechannel_attrs(&cr_ses->fore_channel, nn);
1858 if (status) 1906 if (status)
1859 return status; 1907 return status;
@@ -1874,6 +1922,9 @@ nfsd4_create_session(struct svc_rqst *rqstp,
1874 WARN_ON_ONCE(conf && unconf); 1922 WARN_ON_ONCE(conf && unconf);
1875 1923
1876 if (conf) { 1924 if (conf) {
1925 status = nfserr_wrong_cred;
1926 if (!mach_creds_match(conf, rqstp))
1927 goto out_free_conn;
1877 cs_slot = &conf->cl_cs_slot; 1928 cs_slot = &conf->cl_cs_slot;
1878 status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0); 1929 status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0);
1879 if (status == nfserr_replay_cache) { 1930 if (status == nfserr_replay_cache) {
@@ -1890,6 +1941,9 @@ nfsd4_create_session(struct svc_rqst *rqstp,
1890 status = nfserr_clid_inuse; 1941 status = nfserr_clid_inuse;
1891 goto out_free_conn; 1942 goto out_free_conn;
1892 } 1943 }
1944 status = nfserr_wrong_cred;
1945 if (!mach_creds_match(unconf, rqstp))
1946 goto out_free_conn;
1893 cs_slot = &unconf->cl_cs_slot; 1947 cs_slot = &unconf->cl_cs_slot;
1894 status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0); 1948 status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0);
1895 if (status) { 1949 if (status) {
@@ -1957,7 +2011,11 @@ __be32 nfsd4_backchannel_ctl(struct svc_rqst *rqstp, struct nfsd4_compound_state
1957{ 2011{
1958 struct nfsd4_session *session = cstate->session; 2012 struct nfsd4_session *session = cstate->session;
1959 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); 2013 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
2014 __be32 status;
1960 2015
2016 status = nfsd4_check_cb_sec(&bc->bc_cb_sec);
2017 if (status)
2018 return status;
1961 spin_lock(&nn->client_lock); 2019 spin_lock(&nn->client_lock);
1962 session->se_cb_prog = bc->bc_cb_program; 2020 session->se_cb_prog = bc->bc_cb_program;
1963 session->se_cb_sec = bc->bc_cb_sec; 2021 session->se_cb_sec = bc->bc_cb_sec;
@@ -1986,6 +2044,9 @@ __be32 nfsd4_bind_conn_to_session(struct svc_rqst *rqstp,
1986 status = nfserr_badsession; 2044 status = nfserr_badsession;
1987 if (!session) 2045 if (!session)
1988 goto out; 2046 goto out;
2047 status = nfserr_wrong_cred;
2048 if (!mach_creds_match(session->se_client, rqstp))
2049 goto out;
1989 status = nfsd4_map_bcts_dir(&bcts->dir); 2050 status = nfsd4_map_bcts_dir(&bcts->dir);
1990 if (status) 2051 if (status)
1991 goto out; 2052 goto out;
@@ -2014,6 +2075,7 @@ nfsd4_destroy_session(struct svc_rqst *r,
2014{ 2075{
2015 struct nfsd4_session *ses; 2076 struct nfsd4_session *ses;
2016 __be32 status; 2077 __be32 status;
2078 int ref_held_by_me = 0;
2017 struct nfsd_net *nn = net_generic(SVC_NET(r), nfsd_net_id); 2079 struct nfsd_net *nn = net_generic(SVC_NET(r), nfsd_net_id);
2018 2080
2019 nfs4_lock_state(); 2081 nfs4_lock_state();
@@ -2021,6 +2083,7 @@ nfsd4_destroy_session(struct svc_rqst *r,
2021 if (nfsd4_compound_in_session(cstate->session, &sessionid->sessionid)) { 2083 if (nfsd4_compound_in_session(cstate->session, &sessionid->sessionid)) {
2022 if (!nfsd4_last_compound_op(r)) 2084 if (!nfsd4_last_compound_op(r))
2023 goto out; 2085 goto out;
2086 ref_held_by_me++;
2024 } 2087 }
2025 dump_sessionid(__func__, &sessionid->sessionid); 2088 dump_sessionid(__func__, &sessionid->sessionid);
2026 spin_lock(&nn->client_lock); 2089 spin_lock(&nn->client_lock);
@@ -2028,17 +2091,22 @@ nfsd4_destroy_session(struct svc_rqst *r,
2028 status = nfserr_badsession; 2091 status = nfserr_badsession;
2029 if (!ses) 2092 if (!ses)
2030 goto out_client_lock; 2093 goto out_client_lock;
2031 status = mark_session_dead_locked(ses); 2094 status = nfserr_wrong_cred;
2032 if (status) 2095 if (!mach_creds_match(ses->se_client, r))
2033 goto out_client_lock; 2096 goto out_client_lock;
2097 nfsd4_get_session_locked(ses);
2098 status = mark_session_dead_locked(ses, 1 + ref_held_by_me);
2099 if (status)
2100 goto out_put_session;
2034 unhash_session(ses); 2101 unhash_session(ses);
2035 spin_unlock(&nn->client_lock); 2102 spin_unlock(&nn->client_lock);
2036 2103
2037 nfsd4_probe_callback_sync(ses->se_client); 2104 nfsd4_probe_callback_sync(ses->se_client);
2038 2105
2039 spin_lock(&nn->client_lock); 2106 spin_lock(&nn->client_lock);
2040 free_session(ses);
2041 status = nfs_ok; 2107 status = nfs_ok;
2108out_put_session:
2109 nfsd4_put_session(ses);
2042out_client_lock: 2110out_client_lock:
2043 spin_unlock(&nn->client_lock); 2111 spin_unlock(&nn->client_lock);
2044out: 2112out:
@@ -2058,26 +2126,31 @@ static struct nfsd4_conn *__nfsd4_find_conn(struct svc_xprt *xpt, struct nfsd4_s
2058 return NULL; 2126 return NULL;
2059} 2127}
2060 2128
2061static void nfsd4_sequence_check_conn(struct nfsd4_conn *new, struct nfsd4_session *ses) 2129static __be32 nfsd4_sequence_check_conn(struct nfsd4_conn *new, struct nfsd4_session *ses)
2062{ 2130{
2063 struct nfs4_client *clp = ses->se_client; 2131 struct nfs4_client *clp = ses->se_client;
2064 struct nfsd4_conn *c; 2132 struct nfsd4_conn *c;
2133 __be32 status = nfs_ok;
2065 int ret; 2134 int ret;
2066 2135
2067 spin_lock(&clp->cl_lock); 2136 spin_lock(&clp->cl_lock);
2068 c = __nfsd4_find_conn(new->cn_xprt, ses); 2137 c = __nfsd4_find_conn(new->cn_xprt, ses);
2069 if (c) { 2138 if (c)
2070 spin_unlock(&clp->cl_lock); 2139 goto out_free;
2071 free_conn(new); 2140 status = nfserr_conn_not_bound_to_session;
2072 return; 2141 if (clp->cl_mach_cred)
2073 } 2142 goto out_free;
2074 __nfsd4_hash_conn(new, ses); 2143 __nfsd4_hash_conn(new, ses);
2075 spin_unlock(&clp->cl_lock); 2144 spin_unlock(&clp->cl_lock);
2076 ret = nfsd4_register_conn(new); 2145 ret = nfsd4_register_conn(new);
2077 if (ret) 2146 if (ret)
2078 /* oops; xprt is already down: */ 2147 /* oops; xprt is already down: */
2079 nfsd4_conn_lost(&new->cn_xpt_user); 2148 nfsd4_conn_lost(&new->cn_xpt_user);
2080 return; 2149 return nfs_ok;
2150out_free:
2151 spin_unlock(&clp->cl_lock);
2152 free_conn(new);
2153 return status;
2081} 2154}
2082 2155
2083static bool nfsd4_session_too_many_ops(struct svc_rqst *rqstp, struct nfsd4_session *session) 2156static bool nfsd4_session_too_many_ops(struct svc_rqst *rqstp, struct nfsd4_session *session)
@@ -2169,8 +2242,10 @@ nfsd4_sequence(struct svc_rqst *rqstp,
2169 if (status) 2242 if (status)
2170 goto out_put_session; 2243 goto out_put_session;
2171 2244
2172 nfsd4_sequence_check_conn(conn, session); 2245 status = nfsd4_sequence_check_conn(conn, session);
2173 conn = NULL; 2246 conn = NULL;
2247 if (status)
2248 goto out_put_session;
2174 2249
2175 /* Success! bump slot seqid */ 2250 /* Success! bump slot seqid */
2176 slot->sl_seqid = seq->seqid; 2251 slot->sl_seqid = seq->seqid;
@@ -2232,7 +2307,10 @@ nfsd4_destroy_clientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *csta
2232 status = nfserr_stale_clientid; 2307 status = nfserr_stale_clientid;
2233 goto out; 2308 goto out;
2234 } 2309 }
2235 2310 if (!mach_creds_match(clp, rqstp)) {
2311 status = nfserr_wrong_cred;
2312 goto out;
2313 }
2236 expire_client(clp); 2314 expire_client(clp);
2237out: 2315out:
2238 nfs4_unlock_state(); 2316 nfs4_unlock_state();
@@ -2940,13 +3018,13 @@ static struct file_lock *nfs4_alloc_init_lease(struct nfs4_delegation *dp, int f
2940 return fl; 3018 return fl;
2941} 3019}
2942 3020
2943static int nfs4_setlease(struct nfs4_delegation *dp, int flag) 3021static int nfs4_setlease(struct nfs4_delegation *dp)
2944{ 3022{
2945 struct nfs4_file *fp = dp->dl_file; 3023 struct nfs4_file *fp = dp->dl_file;
2946 struct file_lock *fl; 3024 struct file_lock *fl;
2947 int status; 3025 int status;
2948 3026
2949 fl = nfs4_alloc_init_lease(dp, flag); 3027 fl = nfs4_alloc_init_lease(dp, NFS4_OPEN_DELEGATE_READ);
2950 if (!fl) 3028 if (!fl)
2951 return -ENOMEM; 3029 return -ENOMEM;
2952 fl->fl_file = find_readable_file(fp); 3030 fl->fl_file = find_readable_file(fp);
@@ -2964,12 +3042,12 @@ static int nfs4_setlease(struct nfs4_delegation *dp, int flag)
2964 return 0; 3042 return 0;
2965} 3043}
2966 3044
2967static int nfs4_set_delegation(struct nfs4_delegation *dp, int flag) 3045static int nfs4_set_delegation(struct nfs4_delegation *dp)
2968{ 3046{
2969 struct nfs4_file *fp = dp->dl_file; 3047 struct nfs4_file *fp = dp->dl_file;
2970 3048
2971 if (!fp->fi_lease) 3049 if (!fp->fi_lease)
2972 return nfs4_setlease(dp, flag); 3050 return nfs4_setlease(dp);
2973 spin_lock(&recall_lock); 3051 spin_lock(&recall_lock);
2974 if (fp->fi_had_conflict) { 3052 if (fp->fi_had_conflict) {
2975 spin_unlock(&recall_lock); 3053 spin_unlock(&recall_lock);
@@ -3005,6 +3083,9 @@ static void nfsd4_open_deleg_none_ext(struct nfsd4_open *open, int status)
3005 3083
3006/* 3084/*
3007 * Attempt to hand out a delegation. 3085 * Attempt to hand out a delegation.
3086 *
3087 * Note we don't support write delegations, and won't until the vfs has
3088 * proper support for them.
3008 */ 3089 */
3009static void 3090static void
3010nfs4_open_delegation(struct net *net, struct svc_fh *fh, 3091nfs4_open_delegation(struct net *net, struct svc_fh *fh,
@@ -3013,39 +3094,45 @@ nfs4_open_delegation(struct net *net, struct svc_fh *fh,
3013 struct nfs4_delegation *dp; 3094 struct nfs4_delegation *dp;
3014 struct nfs4_openowner *oo = container_of(stp->st_stateowner, struct nfs4_openowner, oo_owner); 3095 struct nfs4_openowner *oo = container_of(stp->st_stateowner, struct nfs4_openowner, oo_owner);
3015 int cb_up; 3096 int cb_up;
3016 int status = 0, flag = 0; 3097 int status = 0;
3017 3098
3018 cb_up = nfsd4_cb_channel_good(oo->oo_owner.so_client); 3099 cb_up = nfsd4_cb_channel_good(oo->oo_owner.so_client);
3019 flag = NFS4_OPEN_DELEGATE_NONE;
3020 open->op_recall = 0; 3100 open->op_recall = 0;
3021 switch (open->op_claim_type) { 3101 switch (open->op_claim_type) {
3022 case NFS4_OPEN_CLAIM_PREVIOUS: 3102 case NFS4_OPEN_CLAIM_PREVIOUS:
3023 if (!cb_up) 3103 if (!cb_up)
3024 open->op_recall = 1; 3104 open->op_recall = 1;
3025 flag = open->op_delegate_type; 3105 if (open->op_delegate_type != NFS4_OPEN_DELEGATE_READ)
3026 if (flag == NFS4_OPEN_DELEGATE_NONE) 3106 goto out_no_deleg;
3027 goto out;
3028 break; 3107 break;
3029 case NFS4_OPEN_CLAIM_NULL: 3108 case NFS4_OPEN_CLAIM_NULL:
3030 /* Let's not give out any delegations till everyone's 3109 /*
3031 * had the chance to reclaim theirs.... */ 3110 * Let's not give out any delegations till everyone's
3111 * had the chance to reclaim theirs....
3112 */
3032 if (locks_in_grace(net)) 3113 if (locks_in_grace(net))
3033 goto out; 3114 goto out_no_deleg;
3034 if (!cb_up || !(oo->oo_flags & NFS4_OO_CONFIRMED)) 3115 if (!cb_up || !(oo->oo_flags & NFS4_OO_CONFIRMED))
3035 goto out; 3116 goto out_no_deleg;
3117 /*
3118 * Also, if the file was opened for write or
3119 * create, there's a good chance the client's
3120 * about to write to it, resulting in an
3121 * immediate recall (since we don't support
3122 * write delegations):
3123 */
3036 if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE) 3124 if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
3037 flag = NFS4_OPEN_DELEGATE_WRITE; 3125 goto out_no_deleg;
3038 else 3126 if (open->op_create == NFS4_OPEN_CREATE)
3039 flag = NFS4_OPEN_DELEGATE_READ; 3127 goto out_no_deleg;
3040 break; 3128 break;
3041 default: 3129 default:
3042 goto out; 3130 goto out_no_deleg;
3043 } 3131 }
3044 3132 dp = alloc_init_deleg(oo->oo_owner.so_client, stp, fh);
3045 dp = alloc_init_deleg(oo->oo_owner.so_client, stp, fh, flag);
3046 if (dp == NULL) 3133 if (dp == NULL)
3047 goto out_no_deleg; 3134 goto out_no_deleg;
3048 status = nfs4_set_delegation(dp, flag); 3135 status = nfs4_set_delegation(dp);
3049 if (status) 3136 if (status)
3050 goto out_free; 3137 goto out_free;
3051 3138
@@ -3053,24 +3140,23 @@ nfs4_open_delegation(struct net *net, struct svc_fh *fh,
3053 3140
3054 dprintk("NFSD: delegation stateid=" STATEID_FMT "\n", 3141 dprintk("NFSD: delegation stateid=" STATEID_FMT "\n",
3055 STATEID_VAL(&dp->dl_stid.sc_stateid)); 3142 STATEID_VAL(&dp->dl_stid.sc_stateid));
3056out: 3143 open->op_delegate_type = NFS4_OPEN_DELEGATE_READ;
3057 open->op_delegate_type = flag;
3058 if (flag == NFS4_OPEN_DELEGATE_NONE) {
3059 if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS &&
3060 open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE)
3061 dprintk("NFSD: WARNING: refusing delegation reclaim\n");
3062
3063 /* 4.1 client asking for a delegation? */
3064 if (open->op_deleg_want)
3065 nfsd4_open_deleg_none_ext(open, status);
3066 }
3067 return; 3144 return;
3068out_free: 3145out_free:
3069 unhash_stid(&dp->dl_stid); 3146 unhash_stid(&dp->dl_stid);
3070 nfs4_put_delegation(dp); 3147 nfs4_put_delegation(dp);
3071out_no_deleg: 3148out_no_deleg:
3072 flag = NFS4_OPEN_DELEGATE_NONE; 3149 open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE;
3073 goto out; 3150 if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS &&
3151 open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE) {
3152 dprintk("NFSD: WARNING: refusing delegation reclaim\n");
3153 open->op_recall = 1;
3154 }
3155
3156 /* 4.1 client asking for a delegation? */
3157 if (open->op_deleg_want)
3158 nfsd4_open_deleg_none_ext(open, status);
3159 return;
3074} 3160}
3075 3161
3076static void nfsd4_deleg_xgrade_none_ext(struct nfsd4_open *open, 3162static void nfsd4_deleg_xgrade_none_ext(struct nfsd4_open *open,
@@ -3427,7 +3513,7 @@ grace_disallows_io(struct net *net, struct inode *inode)
3427/* Returns true iff a is later than b: */ 3513/* Returns true iff a is later than b: */
3428static bool stateid_generation_after(stateid_t *a, stateid_t *b) 3514static bool stateid_generation_after(stateid_t *a, stateid_t *b)
3429{ 3515{
3430 return (s32)a->si_generation - (s32)b->si_generation > 0; 3516 return (s32)(a->si_generation - b->si_generation) > 0;
3431} 3517}
3432 3518
3433static __be32 check_stateid_generation(stateid_t *in, stateid_t *ref, bool has_session) 3519static __be32 check_stateid_generation(stateid_t *in, stateid_t *ref, bool has_session)
@@ -4435,7 +4521,6 @@ __be32
4435nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 4521nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4436 struct nfsd4_locku *locku) 4522 struct nfsd4_locku *locku)
4437{ 4523{
4438 struct nfs4_lockowner *lo;
4439 struct nfs4_ol_stateid *stp; 4524 struct nfs4_ol_stateid *stp;
4440 struct file *filp = NULL; 4525 struct file *filp = NULL;
4441 struct file_lock *file_lock = NULL; 4526 struct file_lock *file_lock = NULL;
@@ -4468,10 +4553,9 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4468 status = nfserr_jukebox; 4553 status = nfserr_jukebox;
4469 goto out; 4554 goto out;
4470 } 4555 }
4471 lo = lockowner(stp->st_stateowner);
4472 locks_init_lock(file_lock); 4556 locks_init_lock(file_lock);
4473 file_lock->fl_type = F_UNLCK; 4557 file_lock->fl_type = F_UNLCK;
4474 file_lock->fl_owner = (fl_owner_t)lo; 4558 file_lock->fl_owner = (fl_owner_t)lockowner(stp->st_stateowner);
4475 file_lock->fl_pid = current->tgid; 4559 file_lock->fl_pid = current->tgid;
4476 file_lock->fl_file = filp; 4560 file_lock->fl_file = filp;
4477 file_lock->fl_flags = FL_POSIX; 4561 file_lock->fl_flags = FL_POSIX;
@@ -4490,11 +4574,6 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4490 update_stateid(&stp->st_stid.sc_stateid); 4574 update_stateid(&stp->st_stid.sc_stateid);
4491 memcpy(&locku->lu_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); 4575 memcpy(&locku->lu_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
4492 4576
4493 if (nfsd4_has_session(cstate) && !check_for_locks(stp->st_file, lo)) {
4494 WARN_ON_ONCE(cstate->replay_owner);
4495 release_lockowner(lo);
4496 }
4497
4498out: 4577out:
4499 nfsd4_bump_seqid(cstate, status); 4578 nfsd4_bump_seqid(cstate, status);
4500 if (!cstate->replay_owner) 4579 if (!cstate->replay_owner)