aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/file.c49
1 files changed, 43 insertions, 6 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 569184e..ea096ce 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -829,6 +829,11 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile)
struct cifsLockInfo *li, *tmp;
struct cifs_tcon *tcon;
struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
+ unsigned int num, max_num;
+ LOCKING_ANDX_RANGE *buf, *cur;
+ int types[] = {LOCKING_ANDX_LARGE_FILES,
+ LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES};
+ int i;
xid = GetXid();
tcon = tlink_tcon(cfile->tlink);
@@ -840,17 +845,49 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile)
return rc;
}
- list_for_each_entry_safe(li, tmp, &cinode->llist, llist) {
- stored_rc = CIFSSMBLock(xid, tcon, cfile->netfid,
- li->pid, li->length, li->offset,
- 0, 1, li->type, 0, 0);
- if (stored_rc)
- rc = stored_rc;
+ max_num = (tcon->ses->server->maxBuf - sizeof(struct smb_hdr)) /
+ sizeof(LOCKING_ANDX_RANGE);
+ buf = kzalloc(max_num * sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL);
+ if (!buf) {
+ mutex_unlock(&cinode->lock_mutex);
+ FreeXid(xid);
+ return rc;
+ }
+
+ for (i = 0; i < 2; i++) {
+ cur = buf;
+ num = 0;
+ list_for_each_entry_safe(li, tmp, &cinode->llist, llist) {
+ if (li->type != types[i])
+ continue;
+ cur->Pid = cpu_to_le16(li->pid);
+ cur->LengthLow = cpu_to_le32((u32)li->length);
+ cur->LengthHigh = cpu_to_le32((u32)(li->length>>32));
+ cur->OffsetLow = cpu_to_le32((u32)li->offset);
+ cur->OffsetHigh = cpu_to_le32((u32)(li->offset>>32));
+ if (++num == max_num) {
+ stored_rc = cifs_lockv(xid, tcon, cfile->netfid,
+ li->type, 0, num, buf);
+ if (stored_rc)
+ rc = stored_rc;
+ cur = buf;
+ num = 0;
+ } else
+ cur++;
+ }
+
+ if (num) {
+ stored_rc = cifs_lockv(xid, tcon, cfile->netfid,
+ types[i], 0, num, buf);
+ if (stored_rc)
+ rc = stored_rc;
+ }
}
cinode->can_cache_brlcks = false;
mutex_unlock(&cinode->lock_mutex);
+ kfree(buf);
FreeXid(xid);
return rc;
}