Reorganize the code to make the memory already allocated before spinlock'ed loop. Signed-off-by: Pavel Shilovsky <piastry@xxxxxxxxxxx> --- fs/cifs/file.c | 49 ++++++++++++++++++++++++++++++++----------------- 1 files changed, 32 insertions(+), 17 deletions(-) diff --git a/fs/cifs/file.c b/fs/cifs/file.c index b5e38b1..aa2581e 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -926,10 +926,10 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile) struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode); struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); struct file_lock *flock, **before; - struct cifsLockInfo *lck, *tmp; + struct cifsLockInfo *lcks, *lck; + unsigned int count = 0, i = 0; int rc = 0, xid, type; __u64 length; - struct list_head locks_to_send; xid = GetXid(); @@ -940,7 +940,19 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile) return rc; } - INIT_LIST_HEAD(&locks_to_send); + lock_flocks(); + cifs_for_each_lock(cfile->dentry->d_inode, before) + count++; + unlock_flocks(); + + /* + * We can safely allocate count locks, because the hold lock_mutex. + * Allocate (count + 1) * 2 locks to be more safe. + */ + count = (count + 1) * 2; + lcks = kmalloc(count * sizeof(struct cifsLockInfo), GFP_KERNEL); + if (!lcks) + goto out; lock_flocks(); cifs_for_each_lock(cfile->dentry->d_inode, before) { @@ -950,35 +962,38 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile) type = CIFS_RDLCK; else type = CIFS_WRLCK; - - lck = cifs_lock_init(flock->fl_start, length, type, - cfile->netfid); - if (!lck) { - rc = -ENOMEM; - goto send_locks; - } + lck = &lcks[i]; lck->pid = flock->fl_pid; - - list_add_tail(&lck->llist, &locks_to_send); + lck->netfid = cfile->netfid; + lck->length = length; + lck->type = type; + lck->offset = flock->fl_start; + i++; + if (i == count) + break; } - -send_locks: unlock_flocks(); - list_for_each_entry_safe(lck, tmp, &locks_to_send, llist) { + if (i == count) + cERROR(1, "Can't push all brlocks!"); + + count = i; + + for (i = 0; i < count; i++) { struct file_lock tmp_lock; int stored_rc; + lck = &lcks[i]; tmp_lock.fl_start = lck->offset; stored_rc = CIFSSMBPosixLock(xid, tcon, lck->netfid, lck->pid, 0, lck->length, &tmp_lock, lck->type, 0); if (stored_rc) rc = stored_rc; - list_del(&lck->llist); - kfree(lck); } + kfree(lcks); +out: cinode->can_cache_brlcks = false; mutex_unlock(&cinode->lock_mutex); -- 1.7.1 -- 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