|
@@ -97,19 +97,20 @@ nfs4_lock_state(void)
|
|
|
|
|
|
static void free_session(struct nfsd4_session *);
|
|
|
|
|
|
-void nfsd4_put_session(struct nfsd4_session *ses)
|
|
|
+static bool is_session_dead(struct nfsd4_session *ses)
|
|
|
{
|
|
|
- atomic_dec(&ses->se_ref);
|
|
|
+ return ses->se_flags & NFS4_SESSION_DEAD;
|
|
|
}
|
|
|
|
|
|
-static bool is_session_dead(struct nfsd4_session *ses)
|
|
|
+void nfsd4_put_session(struct nfsd4_session *ses)
|
|
|
{
|
|
|
- return ses->se_flags & NFS4_SESSION_DEAD;
|
|
|
+ if (atomic_dec_and_test(&ses->se_ref) && is_session_dead(ses))
|
|
|
+ free_session(ses);
|
|
|
}
|
|
|
|
|
|
-static __be32 mark_session_dead_locked(struct nfsd4_session *ses)
|
|
|
+static __be32 mark_session_dead_locked(struct nfsd4_session *ses, int ref_held_by_me)
|
|
|
{
|
|
|
- if (atomic_read(&ses->se_ref))
|
|
|
+ if (atomic_read(&ses->se_ref) > ref_held_by_me)
|
|
|
return nfserr_jukebox;
|
|
|
ses->se_flags |= NFS4_SESSION_DEAD;
|
|
|
return nfs_ok;
|
|
@@ -364,19 +365,12 @@ static struct nfs4_ol_stateid * nfs4_alloc_stateid(struct nfs4_client *clp)
|
|
|
}
|
|
|
|
|
|
static struct nfs4_delegation *
|
|
|
-alloc_init_deleg(struct nfs4_client *clp, struct nfs4_ol_stateid *stp, struct svc_fh *current_fh, u32 type)
|
|
|
+alloc_init_deleg(struct nfs4_client *clp, struct nfs4_ol_stateid *stp, struct svc_fh *current_fh)
|
|
|
{
|
|
|
struct nfs4_delegation *dp;
|
|
|
struct nfs4_file *fp = stp->st_file;
|
|
|
|
|
|
dprintk("NFSD alloc_init_deleg\n");
|
|
|
- /*
|
|
|
- * Major work on the lease subsystem (for example, to support
|
|
|
- * calbacks on stat) will be required before we can support
|
|
|
- * write delegations properly.
|
|
|
- */
|
|
|
- if (type != NFS4_OPEN_DELEGATE_READ)
|
|
|
- return NULL;
|
|
|
if (fp->fi_had_conflict)
|
|
|
return NULL;
|
|
|
if (num_delegations > max_delegations)
|
|
@@ -397,7 +391,7 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_ol_stateid *stp, struct sv
|
|
|
INIT_LIST_HEAD(&dp->dl_recall_lru);
|
|
|
get_nfs4_file(fp);
|
|
|
dp->dl_file = fp;
|
|
|
- dp->dl_type = type;
|
|
|
+ dp->dl_type = NFS4_OPEN_DELEGATE_READ;
|
|
|
fh_copy_shallow(&dp->dl_fh, ¤t_fh->fh_handle);
|
|
|
dp->dl_time = 0;
|
|
|
atomic_set(&dp->dl_count, 1);
|
|
@@ -1188,6 +1182,9 @@ static int copy_cred(struct svc_cred *target, struct svc_cred *source)
|
|
|
target->cr_gid = source->cr_gid;
|
|
|
target->cr_group_info = source->cr_group_info;
|
|
|
get_group_info(target->cr_group_info);
|
|
|
+ target->cr_gss_mech = source->cr_gss_mech;
|
|
|
+ if (source->cr_gss_mech)
|
|
|
+ gss_mech_get(source->cr_gss_mech);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -1262,6 +1259,31 @@ same_creds(struct svc_cred *cr1, struct svc_cred *cr2)
|
|
|
return 0 == strcmp(cr1->cr_principal, cr2->cr_principal);
|
|
|
}
|
|
|
|
|
|
+static bool svc_rqst_integrity_protected(struct svc_rqst *rqstp)
|
|
|
+{
|
|
|
+ struct svc_cred *cr = &rqstp->rq_cred;
|
|
|
+ u32 service;
|
|
|
+
|
|
|
+ service = gss_pseudoflavor_to_service(cr->cr_gss_mech, cr->cr_flavor);
|
|
|
+ return service == RPC_GSS_SVC_INTEGRITY ||
|
|
|
+ service == RPC_GSS_SVC_PRIVACY;
|
|
|
+}
|
|
|
+
|
|
|
+static bool mach_creds_match(struct nfs4_client *cl, struct svc_rqst *rqstp)
|
|
|
+{
|
|
|
+ struct svc_cred *cr = &rqstp->rq_cred;
|
|
|
+
|
|
|
+ if (!cl->cl_mach_cred)
|
|
|
+ return true;
|
|
|
+ if (cl->cl_cred.cr_gss_mech != cr->cr_gss_mech)
|
|
|
+ return false;
|
|
|
+ if (!svc_rqst_integrity_protected(rqstp))
|
|
|
+ return false;
|
|
|
+ if (!cr->cr_principal)
|
|
|
+ return false;
|
|
|
+ return 0 == strcmp(cl->cl_cred.cr_principal, cr->cr_principal);
|
|
|
+}
|
|
|
+
|
|
|
static void gen_clid(struct nfs4_client *clp, struct nfsd_net *nn)
|
|
|
{
|
|
|
static u32 current_clientid = 1;
|
|
@@ -1639,16 +1661,16 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
|
|
|
if (exid->flags & ~EXCHGID4_FLAG_MASK_A)
|
|
|
return nfserr_inval;
|
|
|
|
|
|
- /* Currently only support SP4_NONE */
|
|
|
switch (exid->spa_how) {
|
|
|
+ case SP4_MACH_CRED:
|
|
|
+ if (!svc_rqst_integrity_protected(rqstp))
|
|
|
+ return nfserr_inval;
|
|
|
case SP4_NONE:
|
|
|
break;
|
|
|
default: /* checked by xdr code */
|
|
|
WARN_ON_ONCE(1);
|
|
|
case SP4_SSV:
|
|
|
return nfserr_encr_alg_unsupp;
|
|
|
- case SP4_MACH_CRED:
|
|
|
- return nfserr_serverfault; /* no excuse :-/ */
|
|
|
}
|
|
|
|
|
|
/* Cases below refer to rfc 5661 section 18.35.4: */
|
|
@@ -1663,6 +1685,10 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
|
|
|
status = nfserr_inval;
|
|
|
goto out;
|
|
|
}
|
|
|
+ if (!mach_creds_match(conf, rqstp)) {
|
|
|
+ status = nfserr_wrong_cred;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
if (!creds_match) { /* case 9 */
|
|
|
status = nfserr_perm;
|
|
|
goto out;
|
|
@@ -1709,7 +1735,8 @@ out_new:
|
|
|
status = nfserr_jukebox;
|
|
|
goto out;
|
|
|
}
|
|
|
- new->cl_minorversion = 1;
|
|
|
+ new->cl_minorversion = cstate->minorversion;
|
|
|
+ new->cl_mach_cred = (exid->spa_how == SP4_MACH_CRED);
|
|
|
|
|
|
gen_clid(new, nn);
|
|
|
add_to_unconfirmed(new);
|
|
@@ -1839,6 +1866,24 @@ static __be32 check_backchannel_attrs(struct nfsd4_channel_attrs *ca)
|
|
|
return nfs_ok;
|
|
|
}
|
|
|
|
|
|
+static __be32 nfsd4_check_cb_sec(struct nfsd4_cb_sec *cbs)
|
|
|
+{
|
|
|
+ switch (cbs->flavor) {
|
|
|
+ case RPC_AUTH_NULL:
|
|
|
+ case RPC_AUTH_UNIX:
|
|
|
+ return nfs_ok;
|
|
|
+ default:
|
|
|
+ /*
|
|
|
+ * GSS case: the spec doesn't allow us to return this
|
|
|
+ * error. But it also doesn't allow us not to support
|
|
|
+ * GSS.
|
|
|
+ * I'd rather this fail hard than return some error the
|
|
|
+ * client might think it can already handle:
|
|
|
+ */
|
|
|
+ return nfserr_encr_alg_unsupp;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
__be32
|
|
|
nfsd4_create_session(struct svc_rqst *rqstp,
|
|
|
struct nfsd4_compound_state *cstate,
|
|
@@ -1854,6 +1899,9 @@ nfsd4_create_session(struct svc_rqst *rqstp,
|
|
|
|
|
|
if (cr_ses->flags & ~SESSION4_FLAG_MASK_A)
|
|
|
return nfserr_inval;
|
|
|
+ status = nfsd4_check_cb_sec(&cr_ses->cb_sec);
|
|
|
+ if (status)
|
|
|
+ return status;
|
|
|
status = check_forechannel_attrs(&cr_ses->fore_channel, nn);
|
|
|
if (status)
|
|
|
return status;
|
|
@@ -1874,6 +1922,9 @@ nfsd4_create_session(struct svc_rqst *rqstp,
|
|
|
WARN_ON_ONCE(conf && unconf);
|
|
|
|
|
|
if (conf) {
|
|
|
+ status = nfserr_wrong_cred;
|
|
|
+ if (!mach_creds_match(conf, rqstp))
|
|
|
+ goto out_free_conn;
|
|
|
cs_slot = &conf->cl_cs_slot;
|
|
|
status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0);
|
|
|
if (status == nfserr_replay_cache) {
|
|
@@ -1890,6 +1941,9 @@ nfsd4_create_session(struct svc_rqst *rqstp,
|
|
|
status = nfserr_clid_inuse;
|
|
|
goto out_free_conn;
|
|
|
}
|
|
|
+ status = nfserr_wrong_cred;
|
|
|
+ if (!mach_creds_match(unconf, rqstp))
|
|
|
+ goto out_free_conn;
|
|
|
cs_slot = &unconf->cl_cs_slot;
|
|
|
status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0);
|
|
|
if (status) {
|
|
@@ -1957,7 +2011,11 @@ __be32 nfsd4_backchannel_ctl(struct svc_rqst *rqstp, struct nfsd4_compound_state
|
|
|
{
|
|
|
struct nfsd4_session *session = cstate->session;
|
|
|
struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
|
|
|
+ __be32 status;
|
|
|
|
|
|
+ status = nfsd4_check_cb_sec(&bc->bc_cb_sec);
|
|
|
+ if (status)
|
|
|
+ return status;
|
|
|
spin_lock(&nn->client_lock);
|
|
|
session->se_cb_prog = bc->bc_cb_program;
|
|
|
session->se_cb_sec = bc->bc_cb_sec;
|
|
@@ -1986,6 +2044,9 @@ __be32 nfsd4_bind_conn_to_session(struct svc_rqst *rqstp,
|
|
|
status = nfserr_badsession;
|
|
|
if (!session)
|
|
|
goto out;
|
|
|
+ status = nfserr_wrong_cred;
|
|
|
+ if (!mach_creds_match(session->se_client, rqstp))
|
|
|
+ goto out;
|
|
|
status = nfsd4_map_bcts_dir(&bcts->dir);
|
|
|
if (status)
|
|
|
goto out;
|
|
@@ -2014,6 +2075,7 @@ nfsd4_destroy_session(struct svc_rqst *r,
|
|
|
{
|
|
|
struct nfsd4_session *ses;
|
|
|
__be32 status;
|
|
|
+ int ref_held_by_me = 0;
|
|
|
struct nfsd_net *nn = net_generic(SVC_NET(r), nfsd_net_id);
|
|
|
|
|
|
nfs4_lock_state();
|
|
@@ -2021,6 +2083,7 @@ nfsd4_destroy_session(struct svc_rqst *r,
|
|
|
if (nfsd4_compound_in_session(cstate->session, &sessionid->sessionid)) {
|
|
|
if (!nfsd4_last_compound_op(r))
|
|
|
goto out;
|
|
|
+ ref_held_by_me++;
|
|
|
}
|
|
|
dump_sessionid(__func__, &sessionid->sessionid);
|
|
|
spin_lock(&nn->client_lock);
|
|
@@ -2028,17 +2091,22 @@ nfsd4_destroy_session(struct svc_rqst *r,
|
|
|
status = nfserr_badsession;
|
|
|
if (!ses)
|
|
|
goto out_client_lock;
|
|
|
- status = mark_session_dead_locked(ses);
|
|
|
- if (status)
|
|
|
+ status = nfserr_wrong_cred;
|
|
|
+ if (!mach_creds_match(ses->se_client, r))
|
|
|
goto out_client_lock;
|
|
|
+ nfsd4_get_session_locked(ses);
|
|
|
+ status = mark_session_dead_locked(ses, 1 + ref_held_by_me);
|
|
|
+ if (status)
|
|
|
+ goto out_put_session;
|
|
|
unhash_session(ses);
|
|
|
spin_unlock(&nn->client_lock);
|
|
|
|
|
|
nfsd4_probe_callback_sync(ses->se_client);
|
|
|
|
|
|
spin_lock(&nn->client_lock);
|
|
|
- free_session(ses);
|
|
|
status = nfs_ok;
|
|
|
+out_put_session:
|
|
|
+ nfsd4_put_session(ses);
|
|
|
out_client_lock:
|
|
|
spin_unlock(&nn->client_lock);
|
|
|
out:
|
|
@@ -2058,26 +2126,31 @@ static struct nfsd4_conn *__nfsd4_find_conn(struct svc_xprt *xpt, struct nfsd4_s
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
-static void nfsd4_sequence_check_conn(struct nfsd4_conn *new, struct nfsd4_session *ses)
|
|
|
+static __be32 nfsd4_sequence_check_conn(struct nfsd4_conn *new, struct nfsd4_session *ses)
|
|
|
{
|
|
|
struct nfs4_client *clp = ses->se_client;
|
|
|
struct nfsd4_conn *c;
|
|
|
+ __be32 status = nfs_ok;
|
|
|
int ret;
|
|
|
|
|
|
spin_lock(&clp->cl_lock);
|
|
|
c = __nfsd4_find_conn(new->cn_xprt, ses);
|
|
|
- if (c) {
|
|
|
- spin_unlock(&clp->cl_lock);
|
|
|
- free_conn(new);
|
|
|
- return;
|
|
|
- }
|
|
|
+ if (c)
|
|
|
+ goto out_free;
|
|
|
+ status = nfserr_conn_not_bound_to_session;
|
|
|
+ if (clp->cl_mach_cred)
|
|
|
+ goto out_free;
|
|
|
__nfsd4_hash_conn(new, ses);
|
|
|
spin_unlock(&clp->cl_lock);
|
|
|
ret = nfsd4_register_conn(new);
|
|
|
if (ret)
|
|
|
/* oops; xprt is already down: */
|
|
|
nfsd4_conn_lost(&new->cn_xpt_user);
|
|
|
- return;
|
|
|
+ return nfs_ok;
|
|
|
+out_free:
|
|
|
+ spin_unlock(&clp->cl_lock);
|
|
|
+ free_conn(new);
|
|
|
+ return status;
|
|
|
}
|
|
|
|
|
|
static bool nfsd4_session_too_many_ops(struct svc_rqst *rqstp, struct nfsd4_session *session)
|
|
@@ -2169,8 +2242,10 @@ nfsd4_sequence(struct svc_rqst *rqstp,
|
|
|
if (status)
|
|
|
goto out_put_session;
|
|
|
|
|
|
- nfsd4_sequence_check_conn(conn, session);
|
|
|
+ status = nfsd4_sequence_check_conn(conn, session);
|
|
|
conn = NULL;
|
|
|
+ if (status)
|
|
|
+ goto out_put_session;
|
|
|
|
|
|
/* Success! bump slot seqid */
|
|
|
slot->sl_seqid = seq->seqid;
|
|
@@ -2232,7 +2307,10 @@ nfsd4_destroy_clientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *csta
|
|
|
status = nfserr_stale_clientid;
|
|
|
goto out;
|
|
|
}
|
|
|
-
|
|
|
+ if (!mach_creds_match(clp, rqstp)) {
|
|
|
+ status = nfserr_wrong_cred;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
expire_client(clp);
|
|
|
out:
|
|
|
nfs4_unlock_state();
|
|
@@ -2940,13 +3018,13 @@ static struct file_lock *nfs4_alloc_init_lease(struct nfs4_delegation *dp, int f
|
|
|
return fl;
|
|
|
}
|
|
|
|
|
|
-static int nfs4_setlease(struct nfs4_delegation *dp, int flag)
|
|
|
+static int nfs4_setlease(struct nfs4_delegation *dp)
|
|
|
{
|
|
|
struct nfs4_file *fp = dp->dl_file;
|
|
|
struct file_lock *fl;
|
|
|
int status;
|
|
|
|
|
|
- fl = nfs4_alloc_init_lease(dp, flag);
|
|
|
+ fl = nfs4_alloc_init_lease(dp, NFS4_OPEN_DELEGATE_READ);
|
|
|
if (!fl)
|
|
|
return -ENOMEM;
|
|
|
fl->fl_file = find_readable_file(fp);
|
|
@@ -2964,12 +3042,12 @@ static int nfs4_setlease(struct nfs4_delegation *dp, int flag)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int nfs4_set_delegation(struct nfs4_delegation *dp, int flag)
|
|
|
+static int nfs4_set_delegation(struct nfs4_delegation *dp)
|
|
|
{
|
|
|
struct nfs4_file *fp = dp->dl_file;
|
|
|
|
|
|
if (!fp->fi_lease)
|
|
|
- return nfs4_setlease(dp, flag);
|
|
|
+ return nfs4_setlease(dp);
|
|
|
spin_lock(&recall_lock);
|
|
|
if (fp->fi_had_conflict) {
|
|
|
spin_unlock(&recall_lock);
|
|
@@ -3005,6 +3083,9 @@ static void nfsd4_open_deleg_none_ext(struct nfsd4_open *open, int status)
|
|
|
|
|
|
/*
|
|
|
* Attempt to hand out a delegation.
|
|
|
+ *
|
|
|
+ * Note we don't support write delegations, and won't until the vfs has
|
|
|
+ * proper support for them.
|
|
|
*/
|
|
|
static void
|
|
|
nfs4_open_delegation(struct net *net, struct svc_fh *fh,
|
|
@@ -3013,39 +3094,45 @@ nfs4_open_delegation(struct net *net, struct svc_fh *fh,
|
|
|
struct nfs4_delegation *dp;
|
|
|
struct nfs4_openowner *oo = container_of(stp->st_stateowner, struct nfs4_openowner, oo_owner);
|
|
|
int cb_up;
|
|
|
- int status = 0, flag = 0;
|
|
|
+ int status = 0;
|
|
|
|
|
|
cb_up = nfsd4_cb_channel_good(oo->oo_owner.so_client);
|
|
|
- flag = NFS4_OPEN_DELEGATE_NONE;
|
|
|
open->op_recall = 0;
|
|
|
switch (open->op_claim_type) {
|
|
|
case NFS4_OPEN_CLAIM_PREVIOUS:
|
|
|
if (!cb_up)
|
|
|
open->op_recall = 1;
|
|
|
- flag = open->op_delegate_type;
|
|
|
- if (flag == NFS4_OPEN_DELEGATE_NONE)
|
|
|
- goto out;
|
|
|
+ if (open->op_delegate_type != NFS4_OPEN_DELEGATE_READ)
|
|
|
+ goto out_no_deleg;
|
|
|
break;
|
|
|
case NFS4_OPEN_CLAIM_NULL:
|
|
|
- /* Let's not give out any delegations till everyone's
|
|
|
- * had the chance to reclaim theirs.... */
|
|
|
+ /*
|
|
|
+ * Let's not give out any delegations till everyone's
|
|
|
+ * had the chance to reclaim theirs....
|
|
|
+ */
|
|
|
if (locks_in_grace(net))
|
|
|
- goto out;
|
|
|
+ goto out_no_deleg;
|
|
|
if (!cb_up || !(oo->oo_flags & NFS4_OO_CONFIRMED))
|
|
|
- goto out;
|
|
|
+ goto out_no_deleg;
|
|
|
+ /*
|
|
|
+ * Also, if the file was opened for write or
|
|
|
+ * create, there's a good chance the client's
|
|
|
+ * about to write to it, resulting in an
|
|
|
+ * immediate recall (since we don't support
|
|
|
+ * write delegations):
|
|
|
+ */
|
|
|
if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
|
|
|
- flag = NFS4_OPEN_DELEGATE_WRITE;
|
|
|
- else
|
|
|
- flag = NFS4_OPEN_DELEGATE_READ;
|
|
|
+ goto out_no_deleg;
|
|
|
+ if (open->op_create == NFS4_OPEN_CREATE)
|
|
|
+ goto out_no_deleg;
|
|
|
break;
|
|
|
default:
|
|
|
- goto out;
|
|
|
+ goto out_no_deleg;
|
|
|
}
|
|
|
-
|
|
|
- dp = alloc_init_deleg(oo->oo_owner.so_client, stp, fh, flag);
|
|
|
+ dp = alloc_init_deleg(oo->oo_owner.so_client, stp, fh);
|
|
|
if (dp == NULL)
|
|
|
goto out_no_deleg;
|
|
|
- status = nfs4_set_delegation(dp, flag);
|
|
|
+ status = nfs4_set_delegation(dp);
|
|
|
if (status)
|
|
|
goto out_free;
|
|
|
|
|
@@ -3053,24 +3140,23 @@ nfs4_open_delegation(struct net *net, struct svc_fh *fh,
|
|
|
|
|
|
dprintk("NFSD: delegation stateid=" STATEID_FMT "\n",
|
|
|
STATEID_VAL(&dp->dl_stid.sc_stateid));
|
|
|
-out:
|
|
|
- open->op_delegate_type = flag;
|
|
|
- if (flag == NFS4_OPEN_DELEGATE_NONE) {
|
|
|
- if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS &&
|
|
|
- open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE)
|
|
|
- dprintk("NFSD: WARNING: refusing delegation reclaim\n");
|
|
|
-
|
|
|
- /* 4.1 client asking for a delegation? */
|
|
|
- if (open->op_deleg_want)
|
|
|
- nfsd4_open_deleg_none_ext(open, status);
|
|
|
- }
|
|
|
+ open->op_delegate_type = NFS4_OPEN_DELEGATE_READ;
|
|
|
return;
|
|
|
out_free:
|
|
|
unhash_stid(&dp->dl_stid);
|
|
|
nfs4_put_delegation(dp);
|
|
|
out_no_deleg:
|
|
|
- flag = NFS4_OPEN_DELEGATE_NONE;
|
|
|
- goto out;
|
|
|
+ open->op_delegate_type = NFS4_OPEN_DELEGATE_NONE;
|
|
|
+ if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS &&
|
|
|
+ open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE) {
|
|
|
+ dprintk("NFSD: WARNING: refusing delegation reclaim\n");
|
|
|
+ open->op_recall = 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 4.1 client asking for a delegation? */
|
|
|
+ if (open->op_deleg_want)
|
|
|
+ nfsd4_open_deleg_none_ext(open, status);
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
static void nfsd4_deleg_xgrade_none_ext(struct nfsd4_open *open,
|
|
@@ -3427,7 +3513,7 @@ grace_disallows_io(struct net *net, struct inode *inode)
|
|
|
/* Returns true iff a is later than b: */
|
|
|
static bool stateid_generation_after(stateid_t *a, stateid_t *b)
|
|
|
{
|
|
|
- return (s32)a->si_generation - (s32)b->si_generation > 0;
|
|
|
+ return (s32)(a->si_generation - b->si_generation) > 0;
|
|
|
}
|
|
|
|
|
|
static __be32 check_stateid_generation(stateid_t *in, stateid_t *ref, bool has_session)
|
|
@@ -4435,7 +4521,6 @@ __be32
|
|
|
nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|
|
struct nfsd4_locku *locku)
|
|
|
{
|
|
|
- struct nfs4_lockowner *lo;
|
|
|
struct nfs4_ol_stateid *stp;
|
|
|
struct file *filp = NULL;
|
|
|
struct file_lock *file_lock = NULL;
|
|
@@ -4468,10 +4553,9 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|
|
status = nfserr_jukebox;
|
|
|
goto out;
|
|
|
}
|
|
|
- lo = lockowner(stp->st_stateowner);
|
|
|
locks_init_lock(file_lock);
|
|
|
file_lock->fl_type = F_UNLCK;
|
|
|
- file_lock->fl_owner = (fl_owner_t)lo;
|
|
|
+ file_lock->fl_owner = (fl_owner_t)lockowner(stp->st_stateowner);
|
|
|
file_lock->fl_pid = current->tgid;
|
|
|
file_lock->fl_file = filp;
|
|
|
file_lock->fl_flags = FL_POSIX;
|
|
@@ -4490,11 +4574,6 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|
|
update_stateid(&stp->st_stid.sc_stateid);
|
|
|
memcpy(&locku->lu_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
|
|
|
|
|
|
- if (nfsd4_has_session(cstate) && !check_for_locks(stp->st_file, lo)) {
|
|
|
- WARN_ON_ONCE(cstate->replay_owner);
|
|
|
- release_lockowner(lo);
|
|
|
- }
|
|
|
-
|
|
|
out:
|
|
|
nfsd4_bump_seqid(cstate, status);
|
|
|
if (!cstate->replay_owner)
|