Re: file locks: Split flock_find_conflict out of flock_lock_file

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Jan 14, 2008 at 09:29:39PM -0700, Matthew Wilcox wrote:
> 
> Reduce the spaghetti-like nature of flock_lock_file by making the chunk
> of code labelled find_conflict into its own function.  Also allocate
> memory before taking the kernel lock in preparation for switching to a
> normal spinlock.

If we did those two steps separately, would the result be two simpler
patches?

> 
> Signed-off-by: Matthew Wilcox <willy@xxxxxxxxxxxxxxx>
> 
> diff --git a/fs/locks.c b/fs/locks.c
> index b681459..bc691e5 100644
> --- a/fs/locks.c
> +++ b/fs/locks.c
> @@ -699,6 +699,33 @@ next_task:
>  	return 0;
>  }
>  
> +/*
> + * A helper function for flock_lock_file().  It searches the list of locks
> + * for @inode looking for one which would conflict with @request.
> + * If it does not find one, it returns the address where the requested lock
> + * should be inserted.  If it does find a conflicting lock, it returns NULL.
> + */

The return value is the reverse of what I'd naively expect--I don't
expect something named flock_find_conflict to return something exactly
when conflict is *not* found, but I don't see a better way to do it.
Perhaps there's a better name?

--b.


> +static struct file_lock **
> +flock_find_conflict(struct inode *inode, struct file_lock *request)
> +{
> +	struct file_lock **before;
> +
> +	for_each_lock(inode, before) {
> +		struct file_lock *fl = *before;
> +		if (IS_POSIX(fl))
> +			break;
> +		if (IS_LEASE(fl))
> +			continue;
> +		if (!flock_locks_conflict(request, fl))
> +			continue;
> +
> +		if (request->fl_flags & FL_SLEEP)
> +			locks_insert_block(fl, request);
> +		return NULL;
> +	}
> +	return before;
> +}
> +
>  /* Try to create a FLOCK lock on filp. We always insert new FLOCK locks
>   * after any leases, but before any posix locks.
>   *
> @@ -714,18 +741,21 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)
>  	int error = 0;
>  	int found = 0;
>  
> -	lock_kernel();
> -	if (request->fl_flags & FL_ACCESS)
> -		goto find_conflict;
> +	if (request->fl_flags & FL_ACCESS) {
> +		lock_kernel();
> +		before = flock_find_conflict(inode, request);
> +		unlock_kernel();
> +		return before ? 0 : -EAGAIN;
> +	}
>  
>  	if (request->fl_type != F_UNLCK) {
> -		error = -ENOMEM;
>  		new_fl = locks_alloc_lock();
> -		if (new_fl == NULL)
> -			goto out;
> -		error = 0;
> +		if (!new_fl)
> +			return -ENOMEM;
>  	}
>  
> +	lock_kernel();
> +
>  	for_each_lock(inode, before) {
>  		struct file_lock *fl = *before;
>  		if (IS_POSIX(fl))
> @@ -754,22 +784,12 @@ static int flock_lock_file(struct file *filp, struct file_lock *request)
>  	if (found)
>  		cond_resched();
>  
> -find_conflict:
> -	for_each_lock(inode, before) {
> -		struct file_lock *fl = *before;
> -		if (IS_POSIX(fl))
> -			break;
> -		if (IS_LEASE(fl))
> -			continue;
> -		if (!flock_locks_conflict(request, fl))
> -			continue;
> +	before = flock_find_conflict(inode, request);
> +	if (!before) {
>  		error = -EAGAIN;
> -		if (request->fl_flags & FL_SLEEP)
> -			locks_insert_block(fl, request);
>  		goto out;
>  	}
> -	if (request->fl_flags & FL_ACCESS)
> -		goto out;
> +
>  	locks_copy_lock(new_fl, request);
>  	locks_insert_lock(before, new_fl);
>  	new_fl = NULL;
> -- 
> Intel are signing my paycheques ... these opinions are still mine
> "Bill, look, we understand that you're interested in selling us this
> operating system, but compare it to ours.  We can't possibly take such
> a retrograde step."
-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux