All of lore.kernel.org
 help / color / mirror / Atom feed
From: NeilBrown <neilb@suse.com>
To: "J. Bruce Fields" <bfields@fieldses.org>
Cc: Jeff Layton <jlayton@kernel.org>,
	Alexander Viro <viro@zeniv.linux.org.uk>,
	Martin Wilck <mwilck@suse.de>,
	linux-fsdevel@vger.kernel.org,
	Frank Filz <ffilzlnx@mindspring.com>,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH 3/5] fs/locks: change all *_conflict() functions to return a new enum.
Date: Fri, 10 Aug 2018 09:40:35 +1000	[thread overview]
Message-ID: <87d0urrtvw.fsf@notabene.neil.brown.name> (raw)
In-Reply-To: <20180809130959.GH23873@fieldses.org>

[-- Attachment #1: Type: text/plain, Size: 5497 bytes --]

On Thu, Aug 09 2018, J. Bruce Fields wrote:

> On Thu, Aug 09, 2018 at 12:04:41PM +1000, NeilBrown wrote:
>> In a future patch we will need to differentiate between conflicts that
>> are "transitive" and those that aren't.
>> A "transitive" conflict is defined as one where any lock that
>> conflicts with the first (newly requested) lock would conflict with
>> the existing lock.
>> 
>> So change posix_locks_conflict(), flock_locks_conflict() (both
>> currently returning int) and leases_conflict() (currently returning
>> bool) to return "enum conflict".
>> Add locks_transitive_overlap() to make it possible to compute the
>> correct conflict for posix locks.
>> 
>> The FL_NO_CONFLICT value is zero, so current code which only tests the
>> truth value of these functions will still work the same way.
>> 
>> And convert some
>>    return (foo);
>> to
>>    return foo;
>> 
>> Signed-off-by: NeilBrown <neilb@suse.com>
>> ---
>>  fs/locks.c |   64 ++++++++++++++++++++++++++++++++++++++++++++++--------------
>>  1 file changed, 49 insertions(+), 15 deletions(-)
>> 
>> diff --git a/fs/locks.c b/fs/locks.c
>> index b4812da2a374..d06658b2dc7a 100644
>> --- a/fs/locks.c
>> +++ b/fs/locks.c
>> @@ -139,6 +139,16 @@
>>  #define IS_OFDLCK(fl)	(fl->fl_flags & FL_OFDLCK)
>>  #define IS_REMOTELCK(fl)	(fl->fl_pid <= 0)
>>  
>> +/* A transitive conflict is one where the first lock conflicts with
>> + * the second lock, and any other lock that conflicts with the
>> + * first lock, also conflicts with the second lock.
>> + */
>> +enum conflict {
>> +	FL_NO_CONFLICT = 0,
>> +	FL_CONFLICT,
>> +	FL_TRANSITIVE_CONFLICT,
>> +};
>> +
>>  static inline bool is_remote_lock(struct file *filp)
>>  {
>>  	return likely(!(filp->f_path.dentry->d_sb->s_flags & SB_NOREMOTELOCK));
>> @@ -612,6 +622,15 @@ static inline int locks_overlap(struct file_lock *fl1, struct file_lock *fl2)
>>  		(fl2->fl_end >= fl1->fl_start));
>>  }
>>  
>> +/* Check for transitive-overlap - true if any lock that overlaps
>> + * the first lock must overlap the seconds
>> + */
>> +static inline bool locks_transitive_overlap(struct file_lock *fl1,
>> +					    struct file_lock *fl2)
>> +{
>> +	return (fl1->fl_start >= fl2->fl_start) &&
>> +		(fl1->fl_end <= fl2->fl_end);
>> +}
>>  /*
>>   * Check whether two locks have the same owner.
>>   */
>> @@ -793,47 +812,61 @@ locks_delete_lock_ctx(struct file_lock *fl, struct list_head *dispose)
>>  /* Determine if lock sys_fl blocks lock caller_fl. Common functionality
>>   * checks for shared/exclusive status of overlapping locks.
>>   */
>> -static int locks_conflict(struct file_lock *caller_fl, struct file_lock *sys_fl)
>> +static enum conflict locks_conflict(struct file_lock *caller_fl,
>> +				    struct file_lock *sys_fl)
>>  {
>>  	if (sys_fl->fl_type == F_WRLCK)
>> -		return 1;
>> +		return FL_TRANSITIVE_CONFLICT;
>>  	if (caller_fl->fl_type == F_WRLCK)
>> -		return 1;
>> -	return 0;
>> +		return FL_CONFLICT;
>> +	return FL_NO_CONFLICT;
>>  }
>>  
>>  /* Determine if lock sys_fl blocks lock caller_fl. POSIX specific
>>   * checking before calling the locks_conflict().
>>   */
>> -static int posix_locks_conflict(struct file_lock *caller_fl, struct file_lock *sys_fl)
>> +static enum conflict posix_locks_conflict(struct file_lock *caller_fl,
>> +					  struct file_lock *sys_fl)
>>  {
>>  	/* POSIX locks owned by the same process do not conflict with
>>  	 * each other.
>>  	 */
>>  	if (posix_same_owner(caller_fl, sys_fl))
>> -		return (0);
>> +		return FL_NO_CONFLICT;
>>  
>>  	/* Check whether they overlap */
>>  	if (!locks_overlap(caller_fl, sys_fl))
>> -		return 0;
>> +		return FL_NO_CONFLICT;
>>  
>> -	return (locks_conflict(caller_fl, sys_fl));
>> +	switch (locks_conflict(caller_fl, sys_fl)) {
>> +	default:
>> +	case FL_NO_CONFLICT:
>> +		return FL_NO_CONFLICT;
>> +	case FL_CONFLICT:
>> +		return FL_CONFLICT;
>
> If I'm understanding the logic here and in locks_conflict correctly,
> you're telling me that in the case where sys_fl is a read lock, and
> caller_fl is a write lock, then any lock which conflicts with sys_fl
> must conflict with caller_fl?  Or do I have that backwards?  It doesn't
> sound right, in any case.

As I was writing this code, I was thinking that I'd probably end up
getting something backwards....
Let's see.  I wrote:

>> +/* A transitive conflict is one where the first lock conflicts with
>> + * the second lock, and any other lock that conflicts with the
>> + * first lock, also conflicts with the second lock.
>> + */

caller_fl is first and sys_fl is second.

if sys_fl, the second, is a read lock, and caller_fl, the first, is a
write lock, they clearly conflict but any other lock that conflict
with caller_fl (The write lock) would *not* necessarily conflict with
the read lock.  So this situation is *not*  FL_TRANSITIVE_CONFLICT.

locks_conflict() only returns FL_TRANSITIVE_CONFLICT when sys_fl (the
second) is a write lock, which it isn't in this case.  So I think that
this case is handled correctly.
posix_locks_conflict() will return FL_CONFLICT, but not
FL_TRANSITIVE_CONFLICT.

Have I convinced you, or have I missed your point?

Thanks,
NeilBrown


>
> --b.
>
>> +	case FL_TRANSITIVE_CONFLICT:
>> +		if (locks_transitive_overlap(caller_fl, sys_fl))
>> +			return FL_TRANSITIVE_CONFLICT;
>> +		else
>> +			return FL_CONFLICT;
>> +	}
>>  }

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]

  reply	other threads:[~2018-08-09 23:40 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-08-09  2:04 [PATCH 0/5 - V2] locks: avoid thundering-herd wake-ups NeilBrown
2018-08-09  2:04 ` [PATCH 1/5] fs/locks: rename some lists and pointers NeilBrown
2018-08-09  2:04 ` [PATCH 2/5] fs/locks: allow a lock request to block other requests NeilBrown
2018-08-09  2:04 ` [PATCH 3/5] fs/locks: change all *_conflict() functions to return a new enum NeilBrown
2018-08-09 11:09   ` Jeff Layton
2018-08-09 13:09   ` J. Bruce Fields
2018-08-09 23:40     ` NeilBrown [this message]
2018-08-10  0:56       ` J. Bruce Fields
2018-08-09  2:04 ` [PATCH 4/5] fs/locks: split out __locks_wake_one() NeilBrown
2018-08-09  2:04 ` [PATCH 5/5] fs/locks: create a tree of dependent requests NeilBrown
2018-08-09 11:17   ` Jeff Layton
2018-08-09 23:25     ` NeilBrown
2018-08-09 14:13   ` J. Bruce Fields
2018-08-09 22:19     ` NeilBrown
2018-08-10  0:36       ` J. Bruce Fields
2018-08-09 17:32 ` [PATCH 0/5 - V2] locks: avoid thundering-herd wake-ups J. Bruce Fields
2018-08-09 22:12   ` NeilBrown
2018-08-10  0:29     ` J. Bruce Fields
2018-08-10  1:50       ` NeilBrown
2018-08-10  2:52         ` J. Bruce Fields
2018-08-10  3:17           ` NeilBrown
2018-08-10 15:47             ` J. Bruce Fields
2018-08-11 11:56               ` Jeff Layton
2018-08-11 12:35                 ` J. Bruce Fields
2018-08-11 11:51       ` Jeff Layton
2018-08-11 12:21         ` J. Bruce Fields
2018-08-11 13:15           ` Jeff Layton

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87d0urrtvw.fsf@notabene.neil.brown.name \
    --to=neilb@suse.com \
    --cc=bfields@fieldses.org \
    --cc=ffilzlnx@mindspring.com \
    --cc=jlayton@kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mwilck@suse.de \
    --cc=viro@zeniv.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.