提交 9ddd3a31 编写于 作者: L Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6:
  not overwriting file_lock structure after GET_LK
  cifs: Fix a kernel BUG with remote OS/2 server (try #3)
  [CIFS] initialize nbytes at the beginning of CIFSSMBWrite()
  [CIFS] Add mmap for direct, nobrl cifs mount types
...@@ -808,6 +808,7 @@ const struct file_operations cifs_file_direct_nobrl_ops = { ...@@ -808,6 +808,7 @@ const struct file_operations cifs_file_direct_nobrl_ops = {
.release = cifs_close, .release = cifs_close,
.fsync = cifs_fsync, .fsync = cifs_fsync,
.flush = cifs_flush, .flush = cifs_flush,
.mmap = cifs_file_mmap,
.splice_read = generic_file_splice_read, .splice_read = generic_file_splice_read,
#ifdef CONFIG_CIFS_POSIX #ifdef CONFIG_CIFS_POSIX
.unlocked_ioctl = cifs_ioctl, .unlocked_ioctl = cifs_ioctl,
......
...@@ -1431,6 +1431,8 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, ...@@ -1431,6 +1431,8 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
__u32 bytes_sent; __u32 bytes_sent;
__u16 byte_count; __u16 byte_count;
*nbytes = 0;
/* cFYI(1, ("write at %lld %d bytes", offset, count));*/ /* cFYI(1, ("write at %lld %d bytes", offset, count));*/
if (tcon->ses == NULL) if (tcon->ses == NULL)
return -ECONNABORTED; return -ECONNABORTED;
...@@ -1513,11 +1515,18 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, ...@@ -1513,11 +1515,18 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
cifs_stats_inc(&tcon->num_writes); cifs_stats_inc(&tcon->num_writes);
if (rc) { if (rc) {
cFYI(1, ("Send error in write = %d", rc)); cFYI(1, ("Send error in write = %d", rc));
*nbytes = 0;
} else { } else {
*nbytes = le16_to_cpu(pSMBr->CountHigh); *nbytes = le16_to_cpu(pSMBr->CountHigh);
*nbytes = (*nbytes) << 16; *nbytes = (*nbytes) << 16;
*nbytes += le16_to_cpu(pSMBr->Count); *nbytes += le16_to_cpu(pSMBr->Count);
/*
* Mask off high 16 bits when bytes written as returned by the
* server is greater than bytes requested by the client. Some
* OS/2 servers are known to set incorrect CountHigh values.
*/
if (*nbytes > count)
*nbytes &= 0xFFFF;
} }
cifs_buf_release(pSMB); cifs_buf_release(pSMB);
...@@ -1606,6 +1615,14 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, ...@@ -1606,6 +1615,14 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
*nbytes = le16_to_cpu(pSMBr->CountHigh); *nbytes = le16_to_cpu(pSMBr->CountHigh);
*nbytes = (*nbytes) << 16; *nbytes = (*nbytes) << 16;
*nbytes += le16_to_cpu(pSMBr->Count); *nbytes += le16_to_cpu(pSMBr->Count);
/*
* Mask off high 16 bits when bytes written as returned by the
* server is greater than bytes requested by the client. OS/2
* servers are known to set incorrect CountHigh values.
*/
if (*nbytes > count)
*nbytes &= 0xFFFF;
} }
/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */ /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
...@@ -1794,8 +1811,21 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, ...@@ -1794,8 +1811,21 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
} }
parm_data = (struct cifs_posix_lock *) parm_data = (struct cifs_posix_lock *)
((char *)&pSMBr->hdr.Protocol + data_offset); ((char *)&pSMBr->hdr.Protocol + data_offset);
if (parm_data->lock_type == cpu_to_le16(CIFS_UNLCK)) if (parm_data->lock_type == __constant_cpu_to_le16(CIFS_UNLCK))
pLockData->fl_type = F_UNLCK; pLockData->fl_type = F_UNLCK;
else {
if (parm_data->lock_type ==
__constant_cpu_to_le16(CIFS_RDLCK))
pLockData->fl_type = F_RDLCK;
else if (parm_data->lock_type ==
__constant_cpu_to_le16(CIFS_WRLCK))
pLockData->fl_type = F_WRLCK;
pLockData->fl_start = parm_data->start;
pLockData->fl_end = parm_data->start +
parm_data->length - 1;
pLockData->fl_pid = parm_data->pid;
}
} }
plk_err_exit: plk_err_exit:
......
...@@ -839,8 +839,32 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) ...@@ -839,8 +839,32 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
} else { } else {
/* if rc == ERR_SHARING_VIOLATION ? */ /* if rc == ERR_SHARING_VIOLATION ? */
rc = 0; /* do not change lock type to unlock rc = 0;
since range in use */
if (lockType & LOCKING_ANDX_SHARED_LOCK) {
pfLock->fl_type = F_WRLCK;
} else {
rc = CIFSSMBLock(xid, tcon, netfid, length,
pfLock->fl_start, 0, 1,
lockType | LOCKING_ANDX_SHARED_LOCK,
0 /* wait flag */);
if (rc == 0) {
rc = CIFSSMBLock(xid, tcon, netfid,
length, pfLock->fl_start, 1, 0,
lockType |
LOCKING_ANDX_SHARED_LOCK,
0 /* wait flag */);
pfLock->fl_type = F_RDLCK;
if (rc != 0)
cERROR(1, ("Error unlocking "
"previously locked range %d "
"during test of lock", rc));
rc = 0;
} else {
pfLock->fl_type = F_WRLCK;
rc = 0;
}
}
} }
FreeXid(xid); FreeXid(xid);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册