2011/10/31 Jeff Layton <[email protected]>:
> On Sat, 29 Oct 2011 17:17:58 +0400
> Pavel Shilovsky <[email protected]> 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 <[email protected]>
>> ---
>> 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);
>
> Here, you're adding "lock" to the list...
If we added the lock to the list cifs_lock_add_if returns 0 and we
will jump to out label.
>
>> if (rc < 0)
>> - return rc;
>> - else if (!rc)
>> + kfree(lock);
>> + if (rc <= 0)
>> goto out;
>>
>> 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);
>
> ...and here you're freeing "lock" without removing it from the list.
> Isn't that like to cause a problem?
So, if CIFSSMBLock returns a error we free the lock that hasn't been
added to the list. If CIFSSMBLock returns ok, we will add it to the
list with cifs_lock_add void function.
Seems no problem with it.
--
Best regards,
Pavel Shilovsky.
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html