diff mbox series

[RFC,v16,03/11] NFSD: Add lm_lock_expired call out

Message ID 1647051215-2873-4-git-send-email-dai.ngo@oracle.com (mailing list archive)
State New, archived
Headers show
Series NFSD: Initial implementation of NFSv4 Courteous Server | expand

Commit Message

Dai Ngo March 12, 2022, 2:13 a.m. UTC
Add callout function nfsd4_lm_lock_expired for lm_lock_expired.
If lock request has conflict with courtesy client then expire the
courtesy client and return no conflict to caller.

Signed-off-by: Dai Ngo <dai.ngo@oracle.com>
---
 fs/nfsd/nfs4state.c | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

Comments

J. Bruce Fields March 15, 2022, 3:02 p.m. UTC | #1
On Fri, Mar 11, 2022 at 06:13:27PM -0800, Dai Ngo wrote:
> Add callout function nfsd4_lm_lock_expired for lm_lock_expired.
> If lock request has conflict with courtesy client then expire the
> courtesy client and return no conflict to caller.
> 
> Signed-off-by: Dai Ngo <dai.ngo@oracle.com>
> ---
>  fs/nfsd/nfs4state.c | 37 +++++++++++++++++++++++++++++++++++++
>  1 file changed, 37 insertions(+)
> 
> diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
> index a65d59510681..583ac807e98d 100644
> --- a/fs/nfsd/nfs4state.c
> +++ b/fs/nfsd/nfs4state.c
> @@ -6578,10 +6578,47 @@ nfsd4_lm_notify(struct file_lock *fl)
>  	}
>  }
>  
> +/**
> + * nfsd4_lm_lock_expired - check if lock conflict can be resolved.
> + *
> + * @fl: pointer to file_lock with a potential conflict
> + * Return values:
> + *   %false: real conflict, lock conflict can not be resolved.
> + *   %true: no conflict, lock conflict was resolved.
> + *
> + * Note that this function is called while the flc_lock is held.
> + */
> +static bool
> +nfsd4_lm_lock_expired(struct file_lock *fl)
> +{
> +	struct nfs4_lockowner *lo;
> +	struct nfs4_client *clp;
> +	bool rc = false;
> +
> +	if (!fl)
> +		return false;
> +	lo = (struct nfs4_lockowner *)fl->fl_owner;
> +	clp = lo->lo_owner.so_client;
> +
> +	/* need to sync with courtesy client trying to reconnect */
> +	spin_lock(&clp->cl_cs_lock);
> +	if (test_bit(NFSD4_CLIENT_EXPIRED, &clp->cl_flags))
> +		rc = true;
> +	else {
> +		if (test_bit(NFSD4_CLIENT_COURTESY, &clp->cl_flags)) {
> +			set_bit(NFSD4_CLIENT_EXPIRED, &clp->cl_flags);
> +			rc =  true;
> +		}
> +	}

I'd prefer:

	if (test_bit(NFSD4_CLIENT_COURTESY, &clp->cl_flags))
		set_bit(NFSD4_CLIENT_EXPIRED, &clp->cl_flags);
	if (test_bit(NFSD4_CLIENT_EXPIRED, &clp->cl_flags))
		rc = true;

Same result, but more compact and straightforward, I think.

--b.

> +	spin_unlock(&clp->cl_cs_lock);
> +	return rc;
> +}
> +
>  static const struct lock_manager_operations nfsd_posix_mng_ops  = {
>  	.lm_notify = nfsd4_lm_notify,
>  	.lm_get_owner = nfsd4_lm_get_owner,
>  	.lm_put_owner = nfsd4_lm_put_owner,
> +	.lm_lock_expired = nfsd4_lm_lock_expired,
>  };
>  
>  static inline void
> -- 
> 2.9.5
Dai Ngo March 15, 2022, 4:26 p.m. UTC | #2
On 3/15/22 8:02 AM, J. Bruce Fields wrote:
> On Fri, Mar 11, 2022 at 06:13:27PM -0800, Dai Ngo wrote:
>> Add callout function nfsd4_lm_lock_expired for lm_lock_expired.
>> If lock request has conflict with courtesy client then expire the
>> courtesy client and return no conflict to caller.
>>
>> Signed-off-by: Dai Ngo <dai.ngo@oracle.com>
>> ---
>>   fs/nfsd/nfs4state.c | 37 +++++++++++++++++++++++++++++++++++++
>>   1 file changed, 37 insertions(+)
>>
>> diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
>> index a65d59510681..583ac807e98d 100644
>> --- a/fs/nfsd/nfs4state.c
>> +++ b/fs/nfsd/nfs4state.c
>> @@ -6578,10 +6578,47 @@ nfsd4_lm_notify(struct file_lock *fl)
>>   	}
>>   }
>>   
>> +/**
>> + * nfsd4_lm_lock_expired - check if lock conflict can be resolved.
>> + *
>> + * @fl: pointer to file_lock with a potential conflict
>> + * Return values:
>> + *   %false: real conflict, lock conflict can not be resolved.
>> + *   %true: no conflict, lock conflict was resolved.
>> + *
>> + * Note that this function is called while the flc_lock is held.
>> + */
>> +static bool
>> +nfsd4_lm_lock_expired(struct file_lock *fl)
>> +{
>> +	struct nfs4_lockowner *lo;
>> +	struct nfs4_client *clp;
>> +	bool rc = false;
>> +
>> +	if (!fl)
>> +		return false;
>> +	lo = (struct nfs4_lockowner *)fl->fl_owner;
>> +	clp = lo->lo_owner.so_client;
>> +
>> +	/* need to sync with courtesy client trying to reconnect */
>> +	spin_lock(&clp->cl_cs_lock);
>> +	if (test_bit(NFSD4_CLIENT_EXPIRED, &clp->cl_flags))
>> +		rc = true;
>> +	else {
>> +		if (test_bit(NFSD4_CLIENT_COURTESY, &clp->cl_flags)) {
>> +			set_bit(NFSD4_CLIENT_EXPIRED, &clp->cl_flags);
>> +			rc =  true;
>> +		}
>> +	}
> I'd prefer:
>
> 	if (test_bit(NFSD4_CLIENT_COURTESY, &clp->cl_flags))
> 		set_bit(NFSD4_CLIENT_EXPIRED, &clp->cl_flags);

we also need to set rc to true here.

> 	if (test_bit(NFSD4_CLIENT_EXPIRED, &clp->cl_flags))
> 		rc = true;

With v16 we need to check for NFSD4_CLIENT_EXPIRED first then
NFSD4_CLIENT_COURTESY because both flags can be set. In the
next patch version, we will clear NFSD4_CLIENT_COURTESY when
setting NFSD4_CLIENT_EXPIRED so the order of check does not
matter.

>
> Same result, but more compact and straightforward, I think.

Chuck wants to replace the bits used for courtesy client in
cl_flags with a  separate u8 field so it does not have to use
bit operation to set/test.

-Dai

>
> --b.
>
>> +	spin_unlock(&clp->cl_cs_lock);
>> +	return rc;
>> +}
>> +
>>   static const struct lock_manager_operations nfsd_posix_mng_ops  = {
>>   	.lm_notify = nfsd4_lm_notify,
>>   	.lm_get_owner = nfsd4_lm_get_owner,
>>   	.lm_put_owner = nfsd4_lm_put_owner,
>> +	.lm_lock_expired = nfsd4_lm_lock_expired,
>>   };
>>   
>>   static inline void
>> -- 
>> 2.9.5
J. Bruce Fields March 15, 2022, 5:20 p.m. UTC | #3
On Tue, Mar 15, 2022 at 09:26:46AM -0700, dai.ngo@oracle.com wrote:
> 
> On 3/15/22 8:02 AM, J. Bruce Fields wrote:
> >On Fri, Mar 11, 2022 at 06:13:27PM -0800, Dai Ngo wrote:
> >>Add callout function nfsd4_lm_lock_expired for lm_lock_expired.
> >>If lock request has conflict with courtesy client then expire the
> >>courtesy client and return no conflict to caller.
> >>
> >>Signed-off-by: Dai Ngo <dai.ngo@oracle.com>
> >>---
> >>  fs/nfsd/nfs4state.c | 37 +++++++++++++++++++++++++++++++++++++
> >>  1 file changed, 37 insertions(+)
> >>
> >>diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
> >>index a65d59510681..583ac807e98d 100644
> >>--- a/fs/nfsd/nfs4state.c
> >>+++ b/fs/nfsd/nfs4state.c
> >>@@ -6578,10 +6578,47 @@ nfsd4_lm_notify(struct file_lock *fl)
> >>  	}
> >>  }
> >>+/**
> >>+ * nfsd4_lm_lock_expired - check if lock conflict can be resolved.
> >>+ *
> >>+ * @fl: pointer to file_lock with a potential conflict
> >>+ * Return values:
> >>+ *   %false: real conflict, lock conflict can not be resolved.
> >>+ *   %true: no conflict, lock conflict was resolved.
> >>+ *
> >>+ * Note that this function is called while the flc_lock is held.
> >>+ */
> >>+static bool
> >>+nfsd4_lm_lock_expired(struct file_lock *fl)
> >>+{
> >>+	struct nfs4_lockowner *lo;
> >>+	struct nfs4_client *clp;
> >>+	bool rc = false;
> >>+
> >>+	if (!fl)
> >>+		return false;
> >>+	lo = (struct nfs4_lockowner *)fl->fl_owner;
> >>+	clp = lo->lo_owner.so_client;
> >>+
> >>+	/* need to sync with courtesy client trying to reconnect */
> >>+	spin_lock(&clp->cl_cs_lock);
> >>+	if (test_bit(NFSD4_CLIENT_EXPIRED, &clp->cl_flags))
> >>+		rc = true;
> >>+	else {
> >>+		if (test_bit(NFSD4_CLIENT_COURTESY, &clp->cl_flags)) {
> >>+			set_bit(NFSD4_CLIENT_EXPIRED, &clp->cl_flags);
> >>+			rc =  true;
> >>+		}
> >>+	}
> >I'd prefer:
> >
> >	if (test_bit(NFSD4_CLIENT_COURTESY, &clp->cl_flags))
> >		set_bit(NFSD4_CLIENT_EXPIRED, &clp->cl_flags);
> 
> we also need to set rc to true here.

No, the next line does it because we set the EXPIRED bit.

--b.

> 
> >	if (test_bit(NFSD4_CLIENT_EXPIRED, &clp->cl_flags))
> >		rc = true;
> 
> With v16 we need to check for NFSD4_CLIENT_EXPIRED first then
> NFSD4_CLIENT_COURTESY because both flags can be set. In the
> next patch version, we will clear NFSD4_CLIENT_COURTESY when
> setting NFSD4_CLIENT_EXPIRED so the order of check does not
> matter.
> 
> >
> >Same result, but more compact and straightforward, I think.
> 
> Chuck wants to replace the bits used for courtesy client in
> cl_flags with a  separate u8 field so it does not have to use
> bit operation to set/test.
> 
> -Dai
> 
> >
> >--b.
> >
> >>+	spin_unlock(&clp->cl_cs_lock);
> >>+	return rc;
> >>+}
> >>+
> >>  static const struct lock_manager_operations nfsd_posix_mng_ops  = {
> >>  	.lm_notify = nfsd4_lm_notify,
> >>  	.lm_get_owner = nfsd4_lm_get_owner,
> >>  	.lm_put_owner = nfsd4_lm_put_owner,
> >>+	.lm_lock_expired = nfsd4_lm_lock_expired,
> >>  };
> >>  static inline void
> >>-- 
> >>2.9.5
Dai Ngo March 15, 2022, 5:30 p.m. UTC | #4
On 3/15/22 10:20 AM, J. Bruce Fields wrote:
> On Tue, Mar 15, 2022 at 09:26:46AM -0700, dai.ngo@oracle.com wrote:
>> On 3/15/22 8:02 AM, J. Bruce Fields wrote:
>>> On Fri, Mar 11, 2022 at 06:13:27PM -0800, Dai Ngo wrote:
>>>> Add callout function nfsd4_lm_lock_expired for lm_lock_expired.
>>>> If lock request has conflict with courtesy client then expire the
>>>> courtesy client and return no conflict to caller.
>>>>
>>>> Signed-off-by: Dai Ngo <dai.ngo@oracle.com>
>>>> ---
>>>>   fs/nfsd/nfs4state.c | 37 +++++++++++++++++++++++++++++++++++++
>>>>   1 file changed, 37 insertions(+)
>>>>
>>>> diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
>>>> index a65d59510681..583ac807e98d 100644
>>>> --- a/fs/nfsd/nfs4state.c
>>>> +++ b/fs/nfsd/nfs4state.c
>>>> @@ -6578,10 +6578,47 @@ nfsd4_lm_notify(struct file_lock *fl)
>>>>   	}
>>>>   }
>>>> +/**
>>>> + * nfsd4_lm_lock_expired - check if lock conflict can be resolved.
>>>> + *
>>>> + * @fl: pointer to file_lock with a potential conflict
>>>> + * Return values:
>>>> + *   %false: real conflict, lock conflict can not be resolved.
>>>> + *   %true: no conflict, lock conflict was resolved.
>>>> + *
>>>> + * Note that this function is called while the flc_lock is held.
>>>> + */
>>>> +static bool
>>>> +nfsd4_lm_lock_expired(struct file_lock *fl)
>>>> +{
>>>> +	struct nfs4_lockowner *lo;
>>>> +	struct nfs4_client *clp;
>>>> +	bool rc = false;
>>>> +
>>>> +	if (!fl)
>>>> +		return false;
>>>> +	lo = (struct nfs4_lockowner *)fl->fl_owner;
>>>> +	clp = lo->lo_owner.so_client;
>>>> +
>>>> +	/* need to sync with courtesy client trying to reconnect */
>>>> +	spin_lock(&clp->cl_cs_lock);
>>>> +	if (test_bit(NFSD4_CLIENT_EXPIRED, &clp->cl_flags))
>>>> +		rc = true;
>>>> +	else {
>>>> +		if (test_bit(NFSD4_CLIENT_COURTESY, &clp->cl_flags)) {
>>>> +			set_bit(NFSD4_CLIENT_EXPIRED, &clp->cl_flags);
>>>> +			rc =  true;
>>>> +		}
>>>> +	}
>>> I'd prefer:
>>>
>>> 	if (test_bit(NFSD4_CLIENT_COURTESY, &clp->cl_flags))
>>> 		set_bit(NFSD4_CLIENT_EXPIRED, &clp->cl_flags);
>> we also need to set rc to true here.
> No, the next line does it because we set the EXPIRED bit.

ok, as mentioned below this code will be changed to use an u8
for the courtesy client state and only either CLIENT_EXPIRED or
CLIENT_COURTESY is set but not both so it might be slightly
different in v17.

-Dai

>
> --b.
>
>>> 	if (test_bit(NFSD4_CLIENT_EXPIRED, &clp->cl_flags))
>>> 		rc = true;
>> With v16 we need to check for NFSD4_CLIENT_EXPIRED first then
>> NFSD4_CLIENT_COURTESY because both flags can be set. In the
>> next patch version, we will clear NFSD4_CLIENT_COURTESY when
>> setting NFSD4_CLIENT_EXPIRED so the order of check does not
>> matter.
>>
>>> Same result, but more compact and straightforward, I think.
>> Chuck wants to replace the bits used for courtesy client in
>> cl_flags with a  separate u8 field so it does not have to use
>> bit operation to set/test.
>>
>> -Dai
>>
>>> --b.
>>>
>>>> +	spin_unlock(&clp->cl_cs_lock);
>>>> +	return rc;
>>>> +}
>>>> +
>>>>   static const struct lock_manager_operations nfsd_posix_mng_ops  = {
>>>>   	.lm_notify = nfsd4_lm_notify,
>>>>   	.lm_get_owner = nfsd4_lm_get_owner,
>>>>   	.lm_put_owner = nfsd4_lm_put_owner,
>>>> +	.lm_lock_expired = nfsd4_lm_lock_expired,
>>>>   };
>>>>   static inline void
>>>> -- 
>>>> 2.9.5
Chuck Lever March 15, 2022, 5:39 p.m. UTC | #5
> On Mar 15, 2022, at 12:26 PM, Dai Ngo <dai.ngo@oracle.com> wrote:
> 
> 
> On 3/15/22 8:02 AM, J. Bruce Fields wrote:
>> On Fri, Mar 11, 2022 at 06:13:27PM -0800, Dai Ngo wrote:
>>> Add callout function nfsd4_lm_lock_expired for lm_lock_expired.
>>> If lock request has conflict with courtesy client then expire the
>>> courtesy client and return no conflict to caller.
>>> 
>>> Signed-off-by: Dai Ngo <dai.ngo@oracle.com>
>>> ---
>>>  fs/nfsd/nfs4state.c | 37 +++++++++++++++++++++++++++++++++++++
>>>  1 file changed, 37 insertions(+)
>>> 
>>> diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
>>> index a65d59510681..583ac807e98d 100644
>>> --- a/fs/nfsd/nfs4state.c
>>> +++ b/fs/nfsd/nfs4state.c
>>> @@ -6578,10 +6578,47 @@ nfsd4_lm_notify(struct file_lock *fl)
>>>  	}
>>>  }
>>>  +/**
>>> + * nfsd4_lm_lock_expired - check if lock conflict can be resolved.
>>> + *
>>> + * @fl: pointer to file_lock with a potential conflict
>>> + * Return values:
>>> + *   %false: real conflict, lock conflict can not be resolved.
>>> + *   %true: no conflict, lock conflict was resolved.
>>> + *
>>> + * Note that this function is called while the flc_lock is held.
>>> + */
>>> +static bool
>>> +nfsd4_lm_lock_expired(struct file_lock *fl)
>>> +{
>>> +	struct nfs4_lockowner *lo;
>>> +	struct nfs4_client *clp;
>>> +	bool rc = false;
>>> +
>>> +	if (!fl)
>>> +		return false;
>>> +	lo = (struct nfs4_lockowner *)fl->fl_owner;
>>> +	clp = lo->lo_owner.so_client;
>>> +
>>> +	/* need to sync with courtesy client trying to reconnect */
>>> +	spin_lock(&clp->cl_cs_lock);
>>> +	if (test_bit(NFSD4_CLIENT_EXPIRED, &clp->cl_flags))
>>> +		rc = true;
>>> +	else {
>>> +		if (test_bit(NFSD4_CLIENT_COURTESY, &clp->cl_flags)) {
>>> +			set_bit(NFSD4_CLIENT_EXPIRED, &clp->cl_flags);
>>> +			rc =  true;
>>> +		}
>>> +	}
>> I'd prefer:
>> 
>> 	if (test_bit(NFSD4_CLIENT_COURTESY, &clp->cl_flags))
>> 		set_bit(NFSD4_CLIENT_EXPIRED, &clp->cl_flags);
> 
> we also need to set rc to true here.
> 
>> 	if (test_bit(NFSD4_CLIENT_EXPIRED, &clp->cl_flags))
>> 		rc = true;
> 
> With v16 we need to check for NFSD4_CLIENT_EXPIRED first then
> NFSD4_CLIENT_COURTESY because both flags can be set. In the
> next patch version, we will clear NFSD4_CLIENT_COURTESY when
> setting NFSD4_CLIENT_EXPIRED so the order of check does not
> matter.
> 
>> 
>> Same result, but more compact and straightforward, I think.
> 
> Chuck wants to replace the bits used for courtesy client in
> cl_flags with a  separate u8 field so it does not have to use
> bit operation to set/test.

Code audit suggested there are really only four unique
combinations of the bit flags that are used.

Plus, taking a spin_lock and using bitops seems like overkill.

The rules for transitioning between the courtesy states are
straightforward, but need to be done in a critical section.
So I suggested storing the courtesy state in a lock-protected
unsigned int instead of using bit flags.

If we hate it, we can go back to bit flags.


>>> +	spin_unlock(&clp->cl_cs_lock);
>>> +	return rc;
>>> +}
>>> +
>>>  static const struct lock_manager_operations nfsd_posix_mng_ops  = {
>>>  	.lm_notify = nfsd4_lm_notify,
>>>  	.lm_get_owner = nfsd4_lm_get_owner,
>>>  	.lm_put_owner = nfsd4_lm_put_owner,
>>> +	.lm_lock_expired = nfsd4_lm_lock_expired,
>>>  };
>>>    static inline void
>>> -- 
>>> 2.9.5

--
Chuck Lever
Dai Ngo March 15, 2022, 6:56 p.m. UTC | #6
On 3/15/22 10:39 AM, Chuck Lever III wrote:
>
>> On Mar 15, 2022, at 12:26 PM, Dai Ngo <dai.ngo@oracle.com> wrote:
>>
>>
>> On 3/15/22 8:02 AM, J. Bruce Fields wrote:
>>> On Fri, Mar 11, 2022 at 06:13:27PM -0800, Dai Ngo wrote:
>>>> Add callout function nfsd4_lm_lock_expired for lm_lock_expired.
>>>> If lock request has conflict with courtesy client then expire the
>>>> courtesy client and return no conflict to caller.
>>>>
>>>> Signed-off-by: Dai Ngo <dai.ngo@oracle.com>
>>>> ---
>>>>   fs/nfsd/nfs4state.c | 37 +++++++++++++++++++++++++++++++++++++
>>>>   1 file changed, 37 insertions(+)
>>>>
>>>> diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
>>>> index a65d59510681..583ac807e98d 100644
>>>> --- a/fs/nfsd/nfs4state.c
>>>> +++ b/fs/nfsd/nfs4state.c
>>>> @@ -6578,10 +6578,47 @@ nfsd4_lm_notify(struct file_lock *fl)
>>>>   	}
>>>>   }
>>>>   +/**
>>>> + * nfsd4_lm_lock_expired - check if lock conflict can be resolved.
>>>> + *
>>>> + * @fl: pointer to file_lock with a potential conflict
>>>> + * Return values:
>>>> + *   %false: real conflict, lock conflict can not be resolved.
>>>> + *   %true: no conflict, lock conflict was resolved.
>>>> + *
>>>> + * Note that this function is called while the flc_lock is held.
>>>> + */
>>>> +static bool
>>>> +nfsd4_lm_lock_expired(struct file_lock *fl)
>>>> +{
>>>> +	struct nfs4_lockowner *lo;
>>>> +	struct nfs4_client *clp;
>>>> +	bool rc = false;
>>>> +
>>>> +	if (!fl)
>>>> +		return false;
>>>> +	lo = (struct nfs4_lockowner *)fl->fl_owner;
>>>> +	clp = lo->lo_owner.so_client;
>>>> +
>>>> +	/* need to sync with courtesy client trying to reconnect */
>>>> +	spin_lock(&clp->cl_cs_lock);
>>>> +	if (test_bit(NFSD4_CLIENT_EXPIRED, &clp->cl_flags))
>>>> +		rc = true;
>>>> +	else {
>>>> +		if (test_bit(NFSD4_CLIENT_COURTESY, &clp->cl_flags)) {
>>>> +			set_bit(NFSD4_CLIENT_EXPIRED, &clp->cl_flags);
>>>> +			rc =  true;
>>>> +		}
>>>> +	}
>>> I'd prefer:
>>>
>>> 	if (test_bit(NFSD4_CLIENT_COURTESY, &clp->cl_flags))
>>> 		set_bit(NFSD4_CLIENT_EXPIRED, &clp->cl_flags);
>> we also need to set rc to true here.
>>
>>> 	if (test_bit(NFSD4_CLIENT_EXPIRED, &clp->cl_flags))
>>> 		rc = true;
>> With v16 we need to check for NFSD4_CLIENT_EXPIRED first then
>> NFSD4_CLIENT_COURTESY because both flags can be set. In the
>> next patch version, we will clear NFSD4_CLIENT_COURTESY when
>> setting NFSD4_CLIENT_EXPIRED so the order of check does not
>> matter.
>>
>>> Same result, but more compact and straightforward, I think.
>> Chuck wants to replace the bits used for courtesy client in
>> cl_flags with a  separate u8 field so it does not have to use
>> bit operation to set/test.
> Code audit suggested there are really only four unique
> combinations of the bit flags that are used.
>
> Plus, taking a spin_lock and using bitops seems like overkill.
>
> The rules for transitioning between the courtesy states are
> straightforward, but need to be done in a critical section.
> So I suggested storing the courtesy state in a lock-protected
> unsigned int instead of using bit flags.

I will try what Chuck suggested.

>
> If we hate it, we can go back to bit flags.

ok.

-Dai


>>>> +	spin_unlock(&clp->cl_cs_lock);
>>>> +	return rc;
>>>> +}
>>>> +
>>>>   static const struct lock_manager_operations nfsd_posix_mng_ops  = {
>>>>   	.lm_notify = nfsd4_lm_notify,
>>>>   	.lm_get_owner = nfsd4_lm_get_owner,
>>>>   	.lm_put_owner = nfsd4_lm_put_owner,
>>>> +	.lm_lock_expired = nfsd4_lm_lock_expired,
>>>>   };
>>>>     static inline void
>>>> -- 
>>>> 2.9.5
> --
> Chuck Lever
>
>
>
diff mbox series

Patch

diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index a65d59510681..583ac807e98d 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -6578,10 +6578,47 @@  nfsd4_lm_notify(struct file_lock *fl)
 	}
 }
 
+/**
+ * nfsd4_lm_lock_expired - check if lock conflict can be resolved.
+ *
+ * @fl: pointer to file_lock with a potential conflict
+ * Return values:
+ *   %false: real conflict, lock conflict can not be resolved.
+ *   %true: no conflict, lock conflict was resolved.
+ *
+ * Note that this function is called while the flc_lock is held.
+ */
+static bool
+nfsd4_lm_lock_expired(struct file_lock *fl)
+{
+	struct nfs4_lockowner *lo;
+	struct nfs4_client *clp;
+	bool rc = false;
+
+	if (!fl)
+		return false;
+	lo = (struct nfs4_lockowner *)fl->fl_owner;
+	clp = lo->lo_owner.so_client;
+
+	/* need to sync with courtesy client trying to reconnect */
+	spin_lock(&clp->cl_cs_lock);
+	if (test_bit(NFSD4_CLIENT_EXPIRED, &clp->cl_flags))
+		rc = true;
+	else {
+		if (test_bit(NFSD4_CLIENT_COURTESY, &clp->cl_flags)) {
+			set_bit(NFSD4_CLIENT_EXPIRED, &clp->cl_flags);
+			rc =  true;
+		}
+	}
+	spin_unlock(&clp->cl_cs_lock);
+	return rc;
+}
+
 static const struct lock_manager_operations nfsd_posix_mng_ops  = {
 	.lm_notify = nfsd4_lm_notify,
 	.lm_get_owner = nfsd4_lm_get_owner,
 	.lm_put_owner = nfsd4_lm_put_owner,
+	.lm_lock_expired = nfsd4_lm_lock_expired,
 };
 
 static inline void