Re: [PATCH 2/3] CIFS: Simplify setlk error handling for mandatory locking

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

 



Pavel,

I may have found a bug in this patch. I've commented inline.

On Sat, 2011-10-29 at 17:17 +0400, Pavel Shilovsky wrote:
> Now we allocate a lock structure at first, then we request to the server
> and save the lock if server returned OK though void function - it prevents
> the situation when we locked a file on the server and then return -ENOMEM
> from setlk.
> 
> Signed-off-by: Pavel Shilovsky <piastry@xxxxxxxxxxx>
> ---
>  fs/cifs/file.c |   64 ++++++++++++++++++++++++++++----------------------------
>  1 files changed, 32 insertions(+), 32 deletions(-)
> 
> diff --git a/fs/cifs/file.c b/fs/cifs/file.c
> index c1f063c..d9cc07f 100644
> --- a/fs/cifs/file.c
> +++ b/fs/cifs/file.c
> @@ -672,7 +672,7 @@ cifs_del_lock_waiters(struct cifsLockInfo *lock)
>  }
>  
>  static bool
> -cifs_find_lock_conflict(struct cifsInodeInfo *cinode, __u64 offset,
> +__cifs_find_lock_conflict(struct cifsInodeInfo *cinode, __u64 offset,
>  			__u64 length, __u8 type, __u16 netfid,
>  			struct cifsLockInfo **conf_lock)
>  {
> @@ -694,6 +694,14 @@ cifs_find_lock_conflict(struct cifsInodeInfo *cinode, __u64 offset,
>  	return false;
>  }
>  
> +static bool
> +cifs_find_lock_conflict(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock,
> +			struct cifsLockInfo **conf_lock)
> +{
> +	return __cifs_find_lock_conflict(cinode, lock->offset, lock->length,
> +					 lock->type, lock->netfid, conf_lock);
> +}
> +
>  static int
>  cifs_lock_test(struct cifsInodeInfo *cinode, __u64 offset, __u64 length,
>  	       __u8 type, __u16 netfid, struct file_lock *flock)
> @@ -704,8 +712,8 @@ cifs_lock_test(struct cifsInodeInfo *cinode, __u64 offset, __u64 length,
>  
>  	mutex_lock(&cinode->lock_mutex);
>  
> -	exist = cifs_find_lock_conflict(cinode, offset, length, type, netfid,
> -					&conf_lock);
> +	exist = __cifs_find_lock_conflict(cinode, offset, length, type, netfid,
> +					  &conf_lock);
>  	if (exist) {
>  		flock->fl_start = conf_lock->offset;
>  		flock->fl_end = conf_lock->offset + conf_lock->length - 1;
> @@ -723,40 +731,27 @@ cifs_lock_test(struct cifsInodeInfo *cinode, __u64 offset, __u64 length,
>  	return rc;
>  }
>  
> -static int
> -cifs_lock_add(struct cifsInodeInfo *cinode, __u64 len, __u64 offset,
> -	      __u8 type, __u16 netfid)
> +static void
> +cifs_lock_add(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock)
>  {
> -	struct cifsLockInfo *li;
> -
> -	li = cifs_lock_init(len, offset, type, netfid);
> -	if (!li)
> -		return -ENOMEM;
> -
>  	mutex_lock(&cinode->lock_mutex);
> -	list_add_tail(&li->llist, &cinode->llist);
> +	list_add_tail(&lock->llist, &cinode->llist);
>  	mutex_unlock(&cinode->lock_mutex);
> -	return 0;
>  }
>  
>  static int
> -cifs_lock_add_if(struct cifsInodeInfo *cinode, __u64 offset, __u64 length,
> -		 __u8 type, __u16 netfid, bool wait)
> +cifs_lock_add_if(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock,
> +		 bool wait)
>  {
> -	struct cifsLockInfo *lock, *conf_lock;
> +	struct cifsLockInfo *conf_lock;
>  	bool exist;
>  	int rc = 0;
>  
> -	lock = cifs_lock_init(length, offset, type, netfid);
> -	if (!lock)
> -		return -ENOMEM;
> -
>  try_again:
>  	exist = false;
>  	mutex_lock(&cinode->lock_mutex);
>  
> -	exist = cifs_find_lock_conflict(cinode, offset, length, type, netfid,
> -					&conf_lock);
> +	exist = cifs_find_lock_conflict(cinode, lock, &conf_lock);
>  	if (!exist && cinode->can_cache_brlcks) {
>  		list_add_tail(&lock->llist, &cinode->llist);
>  		mutex_unlock(&cinode->lock_mutex);
> @@ -781,7 +776,6 @@ try_again:
>  		}
>  	}
>  
> -	kfree(lock);
>  	mutex_unlock(&cinode->lock_mutex);
>  	return rc;
>  }
> @@ -1254,20 +1248,26 @@ cifs_setlk(struct file *file,  struct file_lock *flock, __u8 type,
>  	}
>  
>  	if (lock) {
> -		rc = cifs_lock_add_if(cinode, flock->fl_start, length,
> -				      type, netfid, wait_flag);
> +		struct cifsLockInfo *lock;
> +
> +		lock = cifs_lock_init(length, flock->fl_start, type, netfid);
> +		if (!lock)
> +			return -ENOMEM;
> +
> +		rc = cifs_lock_add_if(cinode, lock, wait_flag);
>  		if (rc < 0)
> -			return rc;
> -		else if (!rc)
> +			kfree(lock);
> +		if (rc <= 0)
>  			goto out;

The return values for cifs_lock_add_if could be
0 - If no locks exist and we can cache byte range locks
1 - If lock doesn't exist and we do not cache byte range locks.
< 0 in case of an error

In case of an error, ie. return value < 0, shouldn't we just return rc
and skip the call to posix_lock_file_wait below?

This should be 
                if (rc < 0) {
                        kfree(lock);
			return rc;
                if (!rc)
                        goto out;

Sachin Prabhu


>  
>  		rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, length,
>  				 flock->fl_start, 0, 1, type, wait_flag, 0);
> -		if (rc == 0) {
> -			/* For Windows locks we must store them. */
> -			rc = cifs_lock_add(cinode, length, flock->fl_start,
> -					   type, netfid);
> +		if (rc) {
> +			kfree(lock);
> +			goto out;
>  		}
> +
> +		cifs_lock_add(cinode, lock);
>  	} else if (unlock)
>  		rc = cifs_unlock_range(cfile, flock, xid);
>  


--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux