提交 547a77ae 编写于 作者: L Linus Torvalds

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

* master.kernel.org:/pub/scm/linux/kernel/git/sfrench/cifs-2.6:
  [CIFS] Fix typo in earlier cifs_unlink change and protect one
  [CIFS] Incorrect signature sent on SMB Read
  [CIFS] Fix unlink oops when indirectly called in rename error path
  [CIFS] Fix two remaining coverity scan tool warnings.
  [CIFS] Set correct lock type on new posix unlock call
  [CIFS] Upate cifs change log
  [CIFS] Fix slow oplock break response when mounts to different
  [CIFS] Workaround various server bugs found in testing at connectathon
  [CIFS] Allow fallback for setting file size to Procom SMB server when
  [CIFS] Make POSIX CIFS Extensions SetFSInfo match exactly what we want
  [CIFS] Move noisy debug message (triggerred by some older servers) from
  [CIFS] Use correct pid on new cifs posix byte range lock call
  [CIFS] Add posix (advisory) byte range locking support to cifs client
  [CIFS] CIFS readdir perf optimizations part 1
  [CIFS] Free small buffers earlier so we exceed the cifs
  [CIFS] Fix large (ie over 64K for MaxCIFSBufSize) buffer case for wrapping
  [CIFS] Convert remaining places in fs/cifs from
  [CIFS] SessionSetup cleanup part 2
  [CIFS] fix compile error (typo) and warning in cifssmb.c
  [CIFS] Cleanup NTLMSSP session setup handling
Version 1.42
------------
Fix slow oplock break when mounted to different servers at the same time and
the tids match and we try to find matching fid on wrong server.
Version 1.41
------------
Fix NTLMv2 security (can be enabled in /proc/fs/cifs) so customers can
configure stronger authentication. Fix sfu symlinks so they can
be followed (not just recognized). Fix wraparound of bcc on
read responses when buffer size over 64K and also fix wrap of
max smb buffer size when CIFSMaxBufSize over 64K. Fix oops in
cifs_user_read and cifs_readpages (when EAGAIN on send of smb
on socket is returned over and over). Add POSIX (advisory) byte range
locking support (requires server with newest CIFS UNIX Extensions
to the protocol implemented). Slow down negprot slightly in port 139
RFC1001 case to give session_init time on buggy servers.
Version 1.40 Version 1.40
------------ ------------
Use fsuid (fsgid) more consistently instead of uid (gid). Improve performance Use fsuid (fsgid) more consistently instead of uid (gid). Improve performance
......
...@@ -3,4 +3,4 @@ ...@@ -3,4 +3,4 @@
# #
obj-$(CONFIG_CIFS) += cifs.o obj-$(CONFIG_CIFS) += cifs.o
cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o ntlmssp.o
...@@ -422,6 +422,13 @@ A partial list of the supported mount options follows: ...@@ -422,6 +422,13 @@ A partial list of the supported mount options follows:
nomapchars Do not translate any of these seven characters (default). nomapchars Do not translate any of these seven characters (default).
nocase Request case insensitive path name matching (case nocase Request case insensitive path name matching (case
sensitive is the default if the server suports it). sensitive is the default if the server suports it).
posixpaths If CIFS Unix extensions are supported, attempt to
negotiate posix path name support which allows certain
characters forbidden in typical CIFS filenames, without
requiring remapping. (default)
noposixpaths If CIFS Unix extensions are supported, do not request
posix path name support (this may cause servers to
reject creatingfile with certain reserved characters).
nobrl Do not send byte range lock requests to the server. nobrl Do not send byte range lock requests to the server.
This is necessary for certain applications that break This is necessary for certain applications that break
with cifs style mandatory byte range locks (and most with cifs style mandatory byte range locks (and most
......
/* /*
* fs/cifs/cifsencrypt.c * fs/cifs/cifsencrypt.c
* *
* Copyright (C) International Business Machines Corp., 2005 * Copyright (C) International Business Machines Corp., 2005,2006
* Author(s): Steve French (sfrench@us.ibm.com) * Author(s): Steve French (sfrench@us.ibm.com)
* *
* This library is free software; you can redistribute it and/or modify * This library is free software; you can redistribute it and/or modify
...@@ -36,7 +36,8 @@ ...@@ -36,7 +36,8 @@
extern void mdfour(unsigned char *out, unsigned char *in, int n); extern void mdfour(unsigned char *out, unsigned char *in, int n);
extern void E_md4hash(const unsigned char *passwd, unsigned char *p16); extern void E_md4hash(const unsigned char *passwd, unsigned char *p16);
static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, const char * key, char * signature) static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu,
const char * key, char * signature)
{ {
struct MD5Context context; struct MD5Context context;
...@@ -56,9 +57,6 @@ int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct TCP_Server_Info * server, ...@@ -56,9 +57,6 @@ int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct TCP_Server_Info * server,
int rc = 0; int rc = 0;
char smb_signature[20]; char smb_signature[20];
/* BB remember to initialize sequence number elsewhere and initialize mac_signing key elsewhere BB */
/* BB remember to add code to save expected sequence number in midQ entry BB */
if((cifs_pdu == NULL) || (server == NULL)) if((cifs_pdu == NULL) || (server == NULL))
return -EINVAL; return -EINVAL;
...@@ -86,19 +84,32 @@ static int cifs_calc_signature2(const struct kvec * iov, int n_vec, ...@@ -86,19 +84,32 @@ static int cifs_calc_signature2(const struct kvec * iov, int n_vec,
const char * key, char * signature) const char * key, char * signature)
{ {
struct MD5Context context; struct MD5Context context;
int i;
if((iov == NULL) || (signature == NULL)) if((iov == NULL) || (signature == NULL))
return -EINVAL; return -EINVAL;
MD5Init(&context); MD5Init(&context);
MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16); MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16);
for(i=0;i<n_vec;i++) {
/* MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length); */ /* BB FIXME BB */ if(iov[i].iov_base == NULL) {
cERROR(1,("null iovec entry"));
return -EIO;
} else if(iov[i].iov_len == 0)
break; /* bail out if we are sent nothing to sign */
/* The first entry includes a length field (which does not get
signed that occupies the first 4 bytes before the header */
if(i==0) {
if (iov[0].iov_len <= 8 ) /* cmd field at offset 9 */
break; /* nothing to sign or corrupt header */
MD5Update(&context,iov[0].iov_base+4, iov[0].iov_len-4);
} else
MD5Update(&context,iov[i].iov_base, iov[i].iov_len);
}
MD5Final(signature,&context); MD5Final(signature,&context);
return -EOPNOTSUPP; return 0;
/* return 0; */
} }
...@@ -259,4 +270,5 @@ void CalcNTLMv2_response(const struct cifsSesInfo * ses,char * v2_session_respon ...@@ -259,4 +270,5 @@ void CalcNTLMv2_response(const struct cifsSesInfo * ses,char * v2_session_respon
/* hmac_md5_update(v2_session_response+16)client thing,8,&context); */ /* BB fix */ /* hmac_md5_update(v2_session_response+16)client thing,8,&context); */ /* BB fix */
hmac_md5_final(v2_session_response,&context); hmac_md5_final(v2_session_response,&context);
cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); /* BB removeme BB */
} }
...@@ -93,13 +93,10 @@ cifs_read_super(struct super_block *sb, void *data, ...@@ -93,13 +93,10 @@ cifs_read_super(struct super_block *sb, void *data,
int rc = 0; int rc = 0;
sb->s_flags |= MS_NODIRATIME; /* and probably even noatime */ sb->s_flags |= MS_NODIRATIME; /* and probably even noatime */
sb->s_fs_info = kmalloc(sizeof(struct cifs_sb_info),GFP_KERNEL); sb->s_fs_info = kzalloc(sizeof(struct cifs_sb_info),GFP_KERNEL);
cifs_sb = CIFS_SB(sb); cifs_sb = CIFS_SB(sb);
if(cifs_sb == NULL) if(cifs_sb == NULL)
return -ENOMEM; return -ENOMEM;
else
memset(cifs_sb,0,sizeof(struct cifs_sb_info));
rc = cifs_mount(sb, cifs_sb, data, devname); rc = cifs_mount(sb, cifs_sb, data, devname);
......
...@@ -99,5 +99,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); ...@@ -99,5 +99,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
extern int cifs_ioctl (struct inode * inode, struct file * filep, extern int cifs_ioctl (struct inode * inode, struct file * filep,
unsigned int command, unsigned long arg); unsigned int command, unsigned long arg);
#define CIFS_VERSION "1.40" #define CIFS_VERSION "1.42"
#endif /* _CIFSFS_H */ #endif /* _CIFSFS_H */
/* /*
* fs/cifs/cifsglob.h * fs/cifs/cifsglob.h
* *
* Copyright (C) International Business Machines Corp., 2002,2005 * Copyright (C) International Business Machines Corp., 2002,2006
* Author(s): Steve French (sfrench@us.ibm.com) * Author(s): Steve French (sfrench@us.ibm.com)
* *
* This library is free software; you can redistribute it and/or modify * This library is free software; you can redistribute it and/or modify
...@@ -430,6 +430,15 @@ struct dir_notify_req { ...@@ -430,6 +430,15 @@ struct dir_notify_req {
#define CIFS_LARGE_BUFFER 2 #define CIFS_LARGE_BUFFER 2
#define CIFS_IOVEC 4 /* array of response buffers */ #define CIFS_IOVEC 4 /* array of response buffers */
/* Type of session setup needed */
#define CIFS_PLAINTEXT 0
#define CIFS_LANMAN 1
#define CIFS_NTLM 2
#define CIFS_NTLMSSP_NEG 3
#define CIFS_NTLMSSP_AUTH 4
#define CIFS_SPNEGO_INIT 5
#define CIFS_SPNEGO_TARG 6
/* /*
***************************************************************** *****************************************************************
* All constants go here * All constants go here
......
...@@ -859,7 +859,10 @@ typedef struct smb_com_lock_req { ...@@ -859,7 +859,10 @@ typedef struct smb_com_lock_req {
LOCKING_ANDX_RANGE Locks[1]; LOCKING_ANDX_RANGE Locks[1];
} __attribute__((packed)) LOCK_REQ; } __attribute__((packed)) LOCK_REQ;
/* lock type */
#define CIFS_RDLCK 0
#define CIFS_WRLCK 1
#define CIFS_UNLCK 2
typedef struct cifs_posix_lock { typedef struct cifs_posix_lock {
__le16 lock_type; /* 0 = Read, 1 = Write, 2 = Unlock */ __le16 lock_type; /* 0 = Read, 1 = Write, 2 = Unlock */
__le16 lock_flags; /* 1 = Wait (only valid for setlock) */ __le16 lock_flags; /* 1 = Wait (only valid for setlock) */
...@@ -1786,7 +1789,13 @@ typedef struct { ...@@ -1786,7 +1789,13 @@ typedef struct {
#define CIFS_UNIX_POSIX_ACL_CAP 0x00000002 /* support getfacl/setfacl */ #define CIFS_UNIX_POSIX_ACL_CAP 0x00000002 /* support getfacl/setfacl */
#define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */ #define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */
#define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */ #define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */
#define CIFS_UNIX_POSIX_PATHNAMES_CAP 0x00000010 /* Use POSIX pathnames on the wire. */ #define CIFS_UNIX_POSIX_PATHNAMES_CAP 0x00000010 /* Allow POSIX path chars */
#ifdef CONFIG_CIFS_POSIX
#define CIFS_UNIX_CAP_MASK 0x0000001b
#else
#define CIFS_UNIX_CAP_MASK 0x00000013
#endif /* CONFIG_CIFS_POSIX */
#define CIFS_POSIX_EXTENSIONS 0x00000010 /* support for new QFSInfo */ #define CIFS_POSIX_EXTENSIONS 0x00000010 /* support for new QFSInfo */
......
/* /*
* fs/cifs/cifsproto.h * fs/cifs/cifsproto.h
* *
* Copyright (c) International Business Machines Corp., 2002,2005 * Copyright (c) International Business Machines Corp., 2002,2006
* Author(s): Steve French (sfrench@us.ibm.com) * Author(s): Steve French (sfrench@us.ibm.com)
* *
* This library is free software; you can redistribute it and/or modify * This library is free software; you can redistribute it and/or modify
...@@ -64,6 +64,14 @@ extern int map_smb_to_linux_error(struct smb_hdr *smb); ...@@ -64,6 +64,14 @@ extern int map_smb_to_linux_error(struct smb_hdr *smb);
extern void header_assemble(struct smb_hdr *, char /* command */ , extern void header_assemble(struct smb_hdr *, char /* command */ ,
const struct cifsTconInfo *, int /* length of const struct cifsTconInfo *, int /* length of
fixed section (word count) in two byte units */); fixed section (word count) in two byte units */);
#ifdef CONFIG_CIFS_EXPERIMENTAL
extern int small_smb_init_no_tc(const int smb_cmd, const int wct,
struct cifsSesInfo *ses,
void ** request_buf);
extern int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
const int stage, int * pNTLMv2_flg,
const struct nls_table *nls_cp);
#endif
extern __u16 GetNextMid(struct TCP_Server_Info *server); extern __u16 GetNextMid(struct TCP_Server_Info *server);
extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16,
struct cifsTconInfo *); struct cifsTconInfo *);
...@@ -257,7 +265,10 @@ extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, ...@@ -257,7 +265,10 @@ extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
const __u64 offset, const __u32 numUnlock, const __u64 offset, const __u32 numUnlock,
const __u32 numLock, const __u8 lockType, const __u32 numLock, const __u8 lockType,
const int waitFlag); const int waitFlag);
extern int CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
const __u16 smb_file_id, const int get_flag,
const __u64 len, const __u64 offset,
const __u16 lock_type, const int waitFlag);
extern int CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon); extern int CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon);
extern int CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses); extern int CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses);
......
/* /*
* fs/cifs/cifssmb.c * fs/cifs/cifssmb.c
* *
* Copyright (C) International Business Machines Corp., 2002,2005 * Copyright (C) International Business Machines Corp., 2002,2006
* Author(s): Steve French (sfrench@us.ibm.com) * Author(s): Steve French (sfrench@us.ibm.com)
* *
* Contains the routines for constructing the SMB PDUs themselves * Contains the routines for constructing the SMB PDUs themselves
...@@ -188,6 +188,34 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, ...@@ -188,6 +188,34 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
return rc; return rc;
} }
#ifdef CONFIG_CIFS_EXPERIMENTAL
int
small_smb_init_no_tc(const int smb_command, const int wct,
struct cifsSesInfo *ses, void **request_buf)
{
int rc;
struct smb_hdr * buffer;
rc = small_smb_init(smb_command, wct, NULL, request_buf);
if(rc)
return rc;
buffer = (struct smb_hdr *)*request_buf;
buffer->Mid = GetNextMid(ses->server);
if (ses->capabilities & CAP_UNICODE)
buffer->Flags2 |= SMBFLG2_UNICODE;
if (ses->capabilities & CAP_STATUS32)
buffer->Flags2 |= SMBFLG2_ERR_STATUS;
/* uid, tid can stay at zero as set in header assemble */
/* BB add support for turning on the signing when
this function is used after 1st of session setup requests */
return rc;
}
#endif /* CONFIG_CIFS_EXPERIMENTAL */
/* If the return code is zero, this function must fill in request_buf pointer */ /* If the return code is zero, this function must fill in request_buf pointer */
static int static int
smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
...@@ -1042,7 +1070,7 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, ...@@ -1042,7 +1070,7 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
} }
} }
cifs_small_buf_release(pSMB); /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
if(*buf) { if(*buf) {
if(resp_buf_type == CIFS_SMALL_BUFFER) if(resp_buf_type == CIFS_SMALL_BUFFER)
cifs_small_buf_release(iov[0].iov_base); cifs_small_buf_release(iov[0].iov_base);
...@@ -1246,7 +1274,7 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, ...@@ -1246,7 +1274,7 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
*nbytes += le16_to_cpu(pSMBr->Count); *nbytes += le16_to_cpu(pSMBr->Count);
} }
cifs_small_buf_release(pSMB); /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
if(resp_buf_type == CIFS_SMALL_BUFFER) if(resp_buf_type == CIFS_SMALL_BUFFER)
cifs_small_buf_release(iov[0].iov_base); cifs_small_buf_release(iov[0].iov_base);
else if(resp_buf_type == CIFS_LARGE_BUFFER) else if(resp_buf_type == CIFS_LARGE_BUFFER)
...@@ -1324,6 +1352,85 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, ...@@ -1324,6 +1352,85 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
return rc; return rc;
} }
int
CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
const __u16 smb_file_id, const int get_flag, const __u64 len,
const __u64 lkoffset, const __u16 lock_type, const int waitFlag)
{
struct smb_com_transaction2_sfi_req *pSMB = NULL;
struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
char *data_offset;
struct cifs_posix_lock *parm_data;
int rc = 0;
int bytes_returned = 0;
__u16 params, param_offset, offset, byte_count, count;
cFYI(1, ("Posix Lock"));
rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
if (rc)
return rc;
pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
params = 6;
pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0;
pSMB->Flags = 0;
pSMB->Timeout = 0;
pSMB->Reserved2 = 0;
param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
offset = param_offset + params;
data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
count = sizeof(struct cifs_posix_lock);
pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
pSMB->SetupCount = 1;
pSMB->Reserved3 = 0;
if(get_flag)
pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
else
pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
byte_count = 3 /* pad */ + params + count;
pSMB->DataCount = cpu_to_le16(count);
pSMB->ParameterCount = cpu_to_le16(params);
pSMB->TotalDataCount = pSMB->DataCount;
pSMB->TotalParameterCount = pSMB->ParameterCount;
pSMB->ParameterOffset = cpu_to_le16(param_offset);
parm_data = (struct cifs_posix_lock *)
(((char *) &pSMB->hdr.Protocol) + offset);
parm_data->lock_type = cpu_to_le16(lock_type);
if(waitFlag)
parm_data->lock_flags = 1;
parm_data->pid = cpu_to_le32(current->tgid);
parm_data->start = lkoffset;
parm_data->length = len; /* normalize negative numbers */
pSMB->DataOffset = cpu_to_le16(offset);
pSMB->Fid = smb_file_id;
pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK);
pSMB->Reserved4 = 0;
pSMB->hdr.smb_buf_length += byte_count;
pSMB->ByteCount = cpu_to_le16(byte_count);
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cFYI(1, ("Send error in Posix Lock = %d", rc));
}
if (pSMB)
cifs_small_buf_release(pSMB);
/* Note: On -EAGAIN error only caller can retry on handle based calls
since file handle passed in no longer valid */
return rc;
}
int int
CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id) CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
{ {
...@@ -2578,7 +2685,7 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, ...@@ -2578,7 +2685,7 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
cifs_small_buf_release(iov[0].iov_base); cifs_small_buf_release(iov[0].iov_base);
else if(buf_type == CIFS_LARGE_BUFFER) else if(buf_type == CIFS_LARGE_BUFFER)
cifs_buf_release(iov[0].iov_base); cifs_buf_release(iov[0].iov_base);
cifs_small_buf_release(pSMB); /* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
return rc; return rc;
} }
...@@ -2954,7 +3061,8 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon, ...@@ -2954,7 +3061,8 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
pSMB->TotalParameterCount = cpu_to_le16(params); pSMB->TotalParameterCount = cpu_to_le16(params);
pSMB->ParameterCount = pSMB->TotalParameterCount; pSMB->ParameterCount = pSMB->TotalParameterCount;
pSMB->ParameterOffset = cpu_to_le16( pSMB->ParameterOffset = cpu_to_le16(
offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4); offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes)
- 4);
pSMB->DataCount = 0; pSMB->DataCount = 0;
pSMB->DataOffset = 0; pSMB->DataOffset = 0;
pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */ pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
...@@ -2977,11 +3085,11 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon, ...@@ -2977,11 +3085,11 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
(struct smb_hdr *) pSMBr, &bytes_returned, 0); (struct smb_hdr *) pSMBr, &bytes_returned, 0);
cifs_stats_inc(&tcon->num_ffirst); cifs_stats_inc(&tcon->num_ffirst);
if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */ if (rc) {/* BB add logic to retry regular search if Unix search
rejected unexpectedly by server */
/* BB Add code to handle unsupported level rc */ /* BB Add code to handle unsupported level rc */
cFYI(1, ("Error in FindFirst = %d", rc)); cFYI(1, ("Error in FindFirst = %d", rc));
if (pSMB)
cifs_buf_release(pSMB); cifs_buf_release(pSMB);
/* BB eventually could optimize out free and realloc of buf */ /* BB eventually could optimize out free and realloc of buf */
...@@ -2998,6 +3106,7 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon, ...@@ -2998,6 +3106,7 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
psrch_inf->unicode = FALSE; psrch_inf->unicode = FALSE;
psrch_inf->ntwrk_buf_start = (char *)pSMBr; psrch_inf->ntwrk_buf_start = (char *)pSMBr;
psrch_inf->smallBuf = 0;
psrch_inf->srch_entries_start = psrch_inf->srch_entries_start =
(char *) &pSMBr->hdr.Protocol + (char *) &pSMBr->hdr.Protocol +
le16_to_cpu(pSMBr->t2.DataOffset); le16_to_cpu(pSMBr->t2.DataOffset);
...@@ -3118,9 +3227,14 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, ...@@ -3118,9 +3227,14 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
parms = (T2_FNEXT_RSP_PARMS *)response_data; parms = (T2_FNEXT_RSP_PARMS *)response_data;
response_data = (char *)&pSMBr->hdr.Protocol + response_data = (char *)&pSMBr->hdr.Protocol +
le16_to_cpu(pSMBr->t2.DataOffset); le16_to_cpu(pSMBr->t2.DataOffset);
if(psrch_inf->smallBuf)
cifs_small_buf_release(
psrch_inf->ntwrk_buf_start);
else
cifs_buf_release(psrch_inf->ntwrk_buf_start); cifs_buf_release(psrch_inf->ntwrk_buf_start);
psrch_inf->srch_entries_start = response_data; psrch_inf->srch_entries_start = response_data;
psrch_inf->ntwrk_buf_start = (char *)pSMB; psrch_inf->ntwrk_buf_start = (char *)pSMB;
psrch_inf->smallBuf = 0;
if(parms->EndofSearch) if(parms->EndofSearch)
psrch_inf->endOfSearch = TRUE; psrch_inf->endOfSearch = TRUE;
else else
...@@ -3834,6 +3948,7 @@ CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap) ...@@ -3834,6 +3948,7 @@ CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
cFYI(1, ("In SETFSUnixInfo")); cFYI(1, ("In SETFSUnixInfo"));
SETFSUnixRetry: SETFSUnixRetry:
/* BB switch to small buf init to save memory */
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr); (void **) &pSMBr);
if (rc) if (rc)
......
/* /*
* fs/cifs/connect.c * fs/cifs/connect.c
* *
* Copyright (C) International Business Machines Corp., 2002,2005 * Copyright (C) International Business Machines Corp., 2002,2006
* Author(s): Steve French (sfrench@us.ibm.com) * Author(s): Steve French (sfrench@us.ibm.com)
* *
* This library is free software; you can redistribute it and/or modify * This library is free software; you can redistribute it and/or modify
...@@ -564,7 +564,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -564,7 +564,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
dump_smb(smb_buffer, length); dump_smb(smb_buffer, length);
if (checkSMB (smb_buffer, smb_buffer->Mid, total_read+4)) { if (checkSMB(smb_buffer, smb_buffer->Mid, total_read+4)) {
cifs_dump_mem("Bad SMB: ", smb_buffer, 48); cifs_dump_mem("Bad SMB: ", smb_buffer, 48);
continue; continue;
} }
...@@ -1476,6 +1476,14 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, ...@@ -1476,6 +1476,14 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
rc = smb_send(*csocket, smb_buf, 0x44, rc = smb_send(*csocket, smb_buf, 0x44,
(struct sockaddr *)psin_server); (struct sockaddr *)psin_server);
kfree(ses_init_buf); kfree(ses_init_buf);
msleep(1); /* RFC1001 layer in at least one server
requires very short break before negprot
presumably because not expecting negprot
to follow so fast. This is a simple
solution that works without
complicating the code and causes no
significant slowing down on mount
for everyone else */
} }
/* else the negprot may still work without this /* else the negprot may still work without this
even though malloc failed */ even though malloc failed */
...@@ -1920,27 +1928,34 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, ...@@ -1920,27 +1928,34 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
cifs_sb->tcon = tcon; cifs_sb->tcon = tcon;
tcon->ses = pSesInfo; tcon->ses = pSesInfo;
/* do not care if following two calls succeed - informational only */ /* do not care if following two calls succeed - informational */
CIFSSMBQFSDeviceInfo(xid, tcon); CIFSSMBQFSDeviceInfo(xid, tcon);
CIFSSMBQFSAttributeInfo(xid, tcon); CIFSSMBQFSAttributeInfo(xid, tcon);
if (tcon->ses->capabilities & CAP_UNIX) { if (tcon->ses->capabilities & CAP_UNIX) {
if(!CIFSSMBQFSUnixInfo(xid, tcon)) { if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
if(!volume_info.no_psx_acl) { __u64 cap =
if(CIFS_UNIX_POSIX_ACL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability);
le64_to_cpu(tcon->fsUnixInfo.Capability)) cap &= CIFS_UNIX_CAP_MASK;
cFYI(1,("server negotiated posix acl support")); if(volume_info.no_psx_acl)
cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
else if(CIFS_UNIX_POSIX_ACL_CAP & cap) {
cFYI(1,("negotiated posix acl support"));
sb->s_flags |= MS_POSIXACL; sb->s_flags |= MS_POSIXACL;
} }
/* Try and negotiate POSIX pathnames if we can. */ if(volume_info.posix_paths == 0)
if (volume_info.posix_paths && (CIFS_UNIX_POSIX_PATHNAMES_CAP & cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
le64_to_cpu(tcon->fsUnixInfo.Capability))) { else if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
if (!CIFSSMBSetFSUnixInfo(xid, tcon, CIFS_UNIX_POSIX_PATHNAMES_CAP)) { cFYI(1,("negotiate posix pathnames"));
cFYI(1,("negotiated posix pathnames support")); cifs_sb->mnt_cifs_flags |=
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS; CIFS_MOUNT_POSIX_PATHS;
} else {
cFYI(1,("posix pathnames support requested but not supported"));
} }
cFYI(1,("Negotiate caps 0x%x",(int)cap));
if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
cFYI(1,("setting capabilities failed"));
} }
} }
} }
...@@ -2278,6 +2293,8 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses, ...@@ -2278,6 +2293,8 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
smb_buffer->Mid = GetNextMid(ses->server); smb_buffer->Mid = GetNextMid(ses->server);
pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
pSMB->req.AndXCommand = 0xFF; pSMB->req.AndXCommand = 0xFF;
if(ses->server->maxBuf > 64*1024)
ses->server->maxBuf = (64*1023);
pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
...@@ -2525,7 +2542,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, ...@@ -2525,7 +2542,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
__u32 negotiate_flags, capabilities; __u32 negotiate_flags, capabilities;
__u16 count; __u16 count;
cFYI(1, ("In NTLMSSP sesssetup (negotiate) ")); cFYI(1, ("In NTLMSSP sesssetup (negotiate)"));
if(ses == NULL) if(ses == NULL)
return -EINVAL; return -EINVAL;
domain = ses->domainName; domain = ses->domainName;
...@@ -2575,7 +2592,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, ...@@ -2575,7 +2592,8 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
SecurityBlob->MessageType = NtLmNegotiate; SecurityBlob->MessageType = NtLmNegotiate;
negotiate_flags = negotiate_flags =
NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM | NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 | NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM |
NTLMSSP_NEGOTIATE_56 |
/* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128; /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
if(sign_CIFS_PDUs) if(sign_CIFS_PDUs)
negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN; negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
...@@ -2588,26 +2606,11 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, ...@@ -2588,26 +2606,11 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
SecurityBlob->WorkstationName.Length = 0; SecurityBlob->WorkstationName.Length = 0;
SecurityBlob->WorkstationName.MaximumLength = 0; SecurityBlob->WorkstationName.MaximumLength = 0;
if (domain == NULL) { /* Domain not sent on first Sesssetup in NTLMSSP, instead it is sent
along with username on auth request (ie the response to challenge) */
SecurityBlob->DomainName.Buffer = 0; SecurityBlob->DomainName.Buffer = 0;
SecurityBlob->DomainName.Length = 0; SecurityBlob->DomainName.Length = 0;
SecurityBlob->DomainName.MaximumLength = 0; SecurityBlob->DomainName.MaximumLength = 0;
} else {
__u16 len;
negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
strncpy(bcc_ptr, domain, 63);
len = strnlen(domain, 64);
SecurityBlob->DomainName.MaximumLength =
cpu_to_le16(len);
SecurityBlob->DomainName.Buffer =
cpu_to_le32((long) &SecurityBlob->
DomainString -
(long) &SecurityBlob->Signature);
bcc_ptr += len;
SecurityBlobLength += len;
SecurityBlob->DomainName.Length =
cpu_to_le16(len);
}
if (ses->capabilities & CAP_UNICODE) { if (ses->capabilities & CAP_UNICODE) {
if ((long) bcc_ptr % 2) { if ((long) bcc_ptr % 2) {
*bcc_ptr = 0; *bcc_ptr = 0;
...@@ -2677,7 +2680,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, ...@@ -2677,7 +2680,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
SecurityBlob2->MessageType)); SecurityBlob2->MessageType));
} else if (ses) { } else if (ses) {
ses->Suid = smb_buffer_response->Uid; /* UID left in le format */ ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
cFYI(1, ("UID = %d ", ses->Suid)); cFYI(1, ("UID = %d", ses->Suid));
if ((pSMBr->resp.hdr.WordCount == 3) if ((pSMBr->resp.hdr.WordCount == 3)
|| ((pSMBr->resp.hdr.WordCount == 4) || ((pSMBr->resp.hdr.WordCount == 4)
&& (blob_len < && (blob_len <
...@@ -2685,17 +2688,17 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, ...@@ -2685,17 +2688,17 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
if (pSMBr->resp.hdr.WordCount == 4) { if (pSMBr->resp.hdr.WordCount == 4) {
bcc_ptr += blob_len; bcc_ptr += blob_len;
cFYI(1, cFYI(1, ("Security Blob Length %d",
("Security Blob Length %d ",
blob_len)); blob_len));
} }
cFYI(1, ("NTLMSSP Challenge rcvd ")); cFYI(1, ("NTLMSSP Challenge rcvd"));
memcpy(ses->server->cryptKey, memcpy(ses->server->cryptKey,
SecurityBlob2->Challenge, SecurityBlob2->Challenge,
CIFS_CRYPTO_KEY_SIZE); CIFS_CRYPTO_KEY_SIZE);
if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2)) if(SecurityBlob2->NegotiateFlags &
cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
*pNTLMv2_flag = TRUE; *pNTLMv2_flag = TRUE;
if((SecurityBlob2->NegotiateFlags & if((SecurityBlob2->NegotiateFlags &
...@@ -2818,7 +2821,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, ...@@ -2818,7 +2821,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
bcc_ptr++; bcc_ptr++;
} else } else
cFYI(1, cFYI(1,
("Variable field of length %d extends beyond end of smb ", ("Variable field of length %d extends beyond end of smb",
len)); len));
} }
} else { } else {
...@@ -2830,7 +2833,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, ...@@ -2830,7 +2833,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
} }
} else { } else {
cERROR(1, cERROR(1,
(" Invalid Word count %d: ", (" Invalid Word count %d:",
smb_buffer_response->WordCount)); smb_buffer_response->WordCount));
rc = -EIO; rc = -EIO;
} }
...@@ -3447,7 +3450,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, ...@@ -3447,7 +3450,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
if (extended_security if (extended_security
&& (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
&& (pSesInfo->server->secType == NTLMSSP)) { && (pSesInfo->server->secType == NTLMSSP)) {
cFYI(1, ("New style sesssetup ")); cFYI(1, ("New style sesssetup"));
rc = CIFSSpnegoSessSetup(xid, pSesInfo, rc = CIFSSpnegoSessSetup(xid, pSesInfo,
NULL /* security blob */, NULL /* security blob */,
0 /* blob length */, 0 /* blob length */,
...@@ -3455,7 +3458,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, ...@@ -3455,7 +3458,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
} else if (extended_security } else if (extended_security
&& (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
&& (pSesInfo->server->secType == RawNTLMSSP)) { && (pSesInfo->server->secType == RawNTLMSSP)) {
cFYI(1, ("NTLMSSP sesssetup ")); cFYI(1, ("NTLMSSP sesssetup"));
rc = CIFSNTLMSSPNegotiateSessSetup(xid, rc = CIFSNTLMSSPNegotiateSessSetup(xid,
pSesInfo, pSesInfo,
&ntlmv2_flag, &ntlmv2_flag,
......
...@@ -48,13 +48,14 @@ build_path_from_dentry(struct dentry *direntry) ...@@ -48,13 +48,14 @@ build_path_from_dentry(struct dentry *direntry)
struct dentry *temp; struct dentry *temp;
int namelen = 0; int namelen = 0;
char *full_path; char *full_path;
char dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb)); char dirsep;
if(direntry == NULL) if(direntry == NULL)
return NULL; /* not much we can do if dentry is freed and return NULL; /* not much we can do if dentry is freed and
we need to reopen the file after it was closed implicitly we need to reopen the file after it was closed implicitly
when the server crashed */ when the server crashed */
dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb));
cifs_bp_rename_retry: cifs_bp_rename_retry:
for (temp = direntry; !IS_ROOT(temp);) { for (temp = direntry; !IS_ROOT(temp);) {
namelen += (1 + temp->d_name.len); namelen += (1 + temp->d_name.len);
...@@ -255,12 +256,10 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -255,12 +256,10 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
CIFSSMBClose(xid, pTcon, fileHandle); CIFSSMBClose(xid, pTcon, fileHandle);
} else if(newinode) { } else if(newinode) {
pCifsFile = pCifsFile =
kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL); kzalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
if(pCifsFile == NULL) if(pCifsFile == NULL)
goto cifs_create_out; goto cifs_create_out;
memset((char *)pCifsFile, 0,
sizeof (struct cifsFileInfo));
pCifsFile->netfid = fileHandle; pCifsFile->netfid = fileHandle;
pCifsFile->pid = current->tgid; pCifsFile->pid = current->tgid;
pCifsFile->pInode = newinode; pCifsFile->pInode = newinode;
......
...@@ -555,6 +555,9 @@ int cifs_closedir(struct inode *inode, struct file *file) ...@@ -555,6 +555,9 @@ int cifs_closedir(struct inode *inode, struct file *file)
if (ptmp) { if (ptmp) {
cFYI(1, ("closedir free smb buf in srch struct")); cFYI(1, ("closedir free smb buf in srch struct"));
pCFileStruct->srch_inf.ntwrk_buf_start = NULL; pCFileStruct->srch_inf.ntwrk_buf_start = NULL;
if(pCFileStruct->srch_inf.smallBuf)
cifs_small_buf_release(ptmp);
else
cifs_buf_release(ptmp); cifs_buf_release(ptmp);
} }
ptmp = pCFileStruct->search_resume_name; ptmp = pCFileStruct->search_resume_name;
...@@ -574,13 +577,14 @@ int cifs_closedir(struct inode *inode, struct file *file) ...@@ -574,13 +577,14 @@ int cifs_closedir(struct inode *inode, struct file *file)
int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
{ {
int rc, xid; int rc, xid;
__u32 lockType = LOCKING_ANDX_LARGE_FILES;
__u32 numLock = 0; __u32 numLock = 0;
__u32 numUnlock = 0; __u32 numUnlock = 0;
__u64 length; __u64 length;
int wait_flag = FALSE; int wait_flag = FALSE;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
__u16 netfid;
__u8 lockType = LOCKING_ANDX_LARGE_FILES;
length = 1 + pfLock->fl_end - pfLock->fl_start; length = 1 + pfLock->fl_end - pfLock->fl_start;
rc = -EACCES; rc = -EACCES;
...@@ -592,11 +596,11 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) ...@@ -592,11 +596,11 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
pfLock->fl_end)); pfLock->fl_end));
if (pfLock->fl_flags & FL_POSIX) if (pfLock->fl_flags & FL_POSIX)
cFYI(1, ("Posix ")); cFYI(1, ("Posix"));
if (pfLock->fl_flags & FL_FLOCK) if (pfLock->fl_flags & FL_FLOCK)
cFYI(1, ("Flock ")); cFYI(1, ("Flock"));
if (pfLock->fl_flags & FL_SLEEP) { if (pfLock->fl_flags & FL_SLEEP) {
cFYI(1, ("Blocking lock ")); cFYI(1, ("Blocking lock"));
wait_flag = TRUE; wait_flag = TRUE;
} }
if (pfLock->fl_flags & FL_ACCESS) if (pfLock->fl_flags & FL_ACCESS)
...@@ -612,21 +616,23 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) ...@@ -612,21 +616,23 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
cFYI(1, ("F_WRLCK ")); cFYI(1, ("F_WRLCK "));
numLock = 1; numLock = 1;
} else if (pfLock->fl_type == F_UNLCK) { } else if (pfLock->fl_type == F_UNLCK) {
cFYI(1, ("F_UNLCK ")); cFYI(1, ("F_UNLCK"));
numUnlock = 1; numUnlock = 1;
/* Check if unlock includes more than
one lock range */
} else if (pfLock->fl_type == F_RDLCK) { } else if (pfLock->fl_type == F_RDLCK) {
cFYI(1, ("F_RDLCK ")); cFYI(1, ("F_RDLCK"));
lockType |= LOCKING_ANDX_SHARED_LOCK; lockType |= LOCKING_ANDX_SHARED_LOCK;
numLock = 1; numLock = 1;
} else if (pfLock->fl_type == F_EXLCK) { } else if (pfLock->fl_type == F_EXLCK) {
cFYI(1, ("F_EXLCK ")); cFYI(1, ("F_EXLCK"));
numLock = 1; numLock = 1;
} else if (pfLock->fl_type == F_SHLCK) { } else if (pfLock->fl_type == F_SHLCK) {
cFYI(1, ("F_SHLCK ")); cFYI(1, ("F_SHLCK"));
lockType |= LOCKING_ANDX_SHARED_LOCK; lockType |= LOCKING_ANDX_SHARED_LOCK;
numLock = 1; numLock = 1;
} else } else
cFYI(1, ("Unknown type of lock ")); cFYI(1, ("Unknown type of lock"));
cifs_sb = CIFS_SB(file->f_dentry->d_sb); cifs_sb = CIFS_SB(file->f_dentry->d_sb);
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
...@@ -635,27 +641,41 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) ...@@ -635,27 +641,41 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
FreeXid(xid); FreeXid(xid);
return -EBADF; return -EBADF;
} }
netfid = ((struct cifsFileInfo *)file->private_data)->netfid;
/* BB add code here to normalize offset and length to
account for negative length which we can not accept over the
wire */
if (IS_GETLK(cmd)) { if (IS_GETLK(cmd)) {
rc = CIFSSMBLock(xid, pTcon, if(experimEnabled &&
((struct cifsFileInfo *)file-> (cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
private_data)->netfid, (CIFS_UNIX_FCNTL_CAP &
length, le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) {
pfLock->fl_start, 0, 1, lockType, int posix_lock_type;
0 /* wait flag */ ); if(lockType & LOCKING_ANDX_SHARED_LOCK)
posix_lock_type = CIFS_RDLCK;
else
posix_lock_type = CIFS_WRLCK;
rc = CIFSSMBPosixLock(xid, pTcon, netfid, 1 /* get */,
length, pfLock->fl_start,
posix_lock_type, wait_flag);
FreeXid(xid);
return rc;
}
/* BB we could chain these into one lock request BB */
rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start,
0, 1, lockType, 0 /* wait flag */ );
if (rc == 0) { if (rc == 0) {
rc = CIFSSMBLock(xid, pTcon, rc = CIFSSMBLock(xid, pTcon, netfid, length,
((struct cifsFileInfo *) file->
private_data)->netfid,
length,
pfLock->fl_start, 1 /* numUnlock */ , pfLock->fl_start, 1 /* numUnlock */ ,
0 /* numLock */ , lockType, 0 /* numLock */ , lockType,
0 /* wait flag */ ); 0 /* wait flag */ );
pfLock->fl_type = F_UNLCK; pfLock->fl_type = F_UNLCK;
if (rc != 0) if (rc != 0)
cERROR(1, ("Error unlocking previously locked " cERROR(1, ("Error unlocking previously locked "
"range %d during test of lock ", "range %d during test of lock", rc));
rc));
rc = 0; rc = 0;
} else { } else {
...@@ -667,12 +687,30 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) ...@@ -667,12 +687,30 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
FreeXid(xid); FreeXid(xid);
return rc; return rc;
} }
if (experimEnabled &&
(cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
(CIFS_UNIX_FCNTL_CAP &
le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) {
int posix_lock_type;
if(lockType & LOCKING_ANDX_SHARED_LOCK)
posix_lock_type = CIFS_RDLCK;
else
posix_lock_type = CIFS_WRLCK;
rc = CIFSSMBLock(xid, pTcon, if(numUnlock == 1)
((struct cifsFileInfo *) file->private_data)-> posix_lock_type = CIFS_UNLCK;
netfid, length, else if(numLock == 0) {
pfLock->fl_start, numUnlock, numLock, lockType, /* if no lock or unlock then nothing
wait_flag); to do since we do not know what it is */
FreeXid(xid);
return -EOPNOTSUPP;
}
rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */,
length, pfLock->fl_start,
posix_lock_type, wait_flag);
} else
rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start,
numUnlock, numLock, lockType, wait_flag);
if (pfLock->fl_flags & FL_POSIX) if (pfLock->fl_flags & FL_POSIX)
posix_lock_file_wait(file, pfLock); posix_lock_file_wait(file, pfLock);
FreeXid(xid); FreeXid(xid);
......
...@@ -565,11 +565,14 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) ...@@ -565,11 +565,14 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
struct cifsInodeInfo *cifsInode; struct cifsInodeInfo *cifsInode;
FILE_BASIC_INFO *pinfo_buf; FILE_BASIC_INFO *pinfo_buf;
cFYI(1, ("cifs_unlink, inode = 0x%p with ", inode)); cFYI(1, ("cifs_unlink, inode = 0x%p", inode));
xid = GetXid(); xid = GetXid();
if(inode)
cifs_sb = CIFS_SB(inode->i_sb); cifs_sb = CIFS_SB(inode->i_sb);
else
cifs_sb = CIFS_SB(direntry->d_sb);
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
/* Unlink can be called from rename so we can not grab the sem here /* Unlink can be called from rename so we can not grab the sem here
...@@ -609,9 +612,8 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) ...@@ -609,9 +612,8 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
} }
} else if (rc == -EACCES) { } else if (rc == -EACCES) {
/* try only if r/o attribute set in local lookup data? */ /* try only if r/o attribute set in local lookup data? */
pinfo_buf = kmalloc(sizeof(FILE_BASIC_INFO), GFP_KERNEL); pinfo_buf = kzalloc(sizeof(FILE_BASIC_INFO), GFP_KERNEL);
if (pinfo_buf) { if (pinfo_buf) {
memset(pinfo_buf, 0, sizeof(FILE_BASIC_INFO));
/* ATTRS set to normal clears r/o bit */ /* ATTRS set to normal clears r/o bit */
pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL); pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL);
if (!(pTcon->ses->flags & CIFS_SES_NT4)) if (!(pTcon->ses->flags & CIFS_SES_NT4))
...@@ -693,9 +695,11 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) ...@@ -693,9 +695,11 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
when needed */ when needed */
direntry->d_inode->i_ctime = current_fs_time(inode->i_sb); direntry->d_inode->i_ctime = current_fs_time(inode->i_sb);
} }
if(inode) {
inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb); inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb);
cifsInode = CIFS_I(inode); cifsInode = CIFS_I(inode);
cifsInode->time = 0; /* force revalidate of dir as well */ cifsInode->time = 0; /* force revalidate of dir as well */
}
kfree(full_path); kfree(full_path);
FreeXid(xid); FreeXid(xid);
...@@ -1167,7 +1171,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) ...@@ -1167,7 +1171,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
nfid, npid, FALSE); nfid, npid, FALSE);
atomic_dec(&open_file->wrtPending); atomic_dec(&open_file->wrtPending);
cFYI(1,("SetFSize for attrs rc = %d", rc)); cFYI(1,("SetFSize for attrs rc = %d", rc));
if(rc == -EINVAL) { if((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
int bytes_written; int bytes_written;
rc = CIFSSMBWrite(xid, pTcon, rc = CIFSSMBWrite(xid, pTcon,
nfid, 0, attrs->ia_size, nfid, 0, attrs->ia_size,
...@@ -1189,7 +1193,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) ...@@ -1189,7 +1193,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc)); cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc));
if(rc == -EINVAL) { if((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
__u16 netfid; __u16 netfid;
int oplock = FALSE; int oplock = FALSE;
......
...@@ -67,7 +67,7 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, ...@@ -67,7 +67,7 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
cifs_sb_target->local_nls, cifs_sb_target->local_nls,
cifs_sb_target->mnt_cifs_flags & cifs_sb_target->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
if(rc == -EIO) if((rc == -EIO) || (rc == -EINVAL))
rc = -EOPNOTSUPP; rc = -EOPNOTSUPP;
} }
......
...@@ -72,10 +72,9 @@ sesInfoAlloc(void) ...@@ -72,10 +72,9 @@ sesInfoAlloc(void)
struct cifsSesInfo *ret_buf; struct cifsSesInfo *ret_buf;
ret_buf = ret_buf =
(struct cifsSesInfo *) kmalloc(sizeof (struct cifsSesInfo), (struct cifsSesInfo *) kzalloc(sizeof (struct cifsSesInfo),
GFP_KERNEL); GFP_KERNEL);
if (ret_buf) { if (ret_buf) {
memset(ret_buf, 0, sizeof (struct cifsSesInfo));
write_lock(&GlobalSMBSeslock); write_lock(&GlobalSMBSeslock);
atomic_inc(&sesInfoAllocCount); atomic_inc(&sesInfoAllocCount);
ret_buf->status = CifsNew; ret_buf->status = CifsNew;
...@@ -110,10 +109,9 @@ tconInfoAlloc(void) ...@@ -110,10 +109,9 @@ tconInfoAlloc(void)
{ {
struct cifsTconInfo *ret_buf; struct cifsTconInfo *ret_buf;
ret_buf = ret_buf =
(struct cifsTconInfo *) kmalloc(sizeof (struct cifsTconInfo), (struct cifsTconInfo *) kzalloc(sizeof (struct cifsTconInfo),
GFP_KERNEL); GFP_KERNEL);
if (ret_buf) { if (ret_buf) {
memset(ret_buf, 0, sizeof (struct cifsTconInfo));
write_lock(&GlobalSMBSeslock); write_lock(&GlobalSMBSeslock);
atomic_inc(&tconInfoAllocCount); atomic_inc(&tconInfoAllocCount);
list_add(&ret_buf->cifsConnectionList, list_add(&ret_buf->cifsConnectionList,
...@@ -423,9 +421,7 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length) ...@@ -423,9 +421,7 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length)
{ {
__u32 len = smb->smb_buf_length; __u32 len = smb->smb_buf_length;
__u32 clc_len; /* calculated length */ __u32 clc_len; /* calculated length */
cFYI(0, cFYI(0, ("checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len));
("Entering checkSMB with Length: %x, smb_buf_length: %x",
length, len));
if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) || if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) ||
(len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) { (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) {
if ((unsigned int)length < 2 + sizeof (struct smb_hdr)) { if ((unsigned int)length < 2 + sizeof (struct smb_hdr)) {
...@@ -433,17 +429,14 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length) ...@@ -433,17 +429,14 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length)
sizeof (struct smb_hdr) - 1) sizeof (struct smb_hdr) - 1)
&& (smb->Status.CifsError != 0)) { && (smb->Status.CifsError != 0)) {
smb->WordCount = 0; smb->WordCount = 0;
return 0; /* some error cases do not return wct and bcc */ /* some error cases do not return wct and bcc */
return 0;
} else { } else {
cERROR(1, ("Length less than smb header size")); cERROR(1, ("Length less than smb header size"));
} }
} }
if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)
cERROR(1, cERROR(1, ("smb length greater than MaxBufSize, mid=%d",
("smb_buf_length greater than MaxBufSize"));
cERROR(1,
("bad smb detected. Illegal length. mid=%d",
smb->Mid)); smb->Mid));
return 1; return 1;
} }
...@@ -451,11 +444,21 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length) ...@@ -451,11 +444,21 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length)
if (checkSMBhdr(smb, mid)) if (checkSMBhdr(smb, mid))
return 1; return 1;
clc_len = smbCalcSize_LE(smb); clc_len = smbCalcSize_LE(smb);
if ((4 + len != clc_len)
|| (4 + len != (unsigned int)length)) { if(4 + len != (unsigned int)length) {
cERROR(1, ("Calculated size 0x%x vs actual length 0x%x", cERROR(1, ("Length read does not match RFC1001 length %d",len));
clc_len, 4 + len)); return 1;
cERROR(1, ("bad smb size detected for Mid=%d", smb->Mid)); }
if (4 + len != clc_len) {
/* check if bcc wrapped around for large read responses */
if((len > 64 * 1024) && (len > clc_len)) {
/* check if lengths match mod 64K */
if(((4 + len) & 0xFFFF) == (clc_len & 0xFFFF))
return 0; /* bcc wrapped */
}
cFYI(1, ("Calculated size %d vs length %d mismatch for mid %d",
clc_len, 4 + len, smb->Mid));
/* Windows XP can return a few bytes too much, presumably /* Windows XP can return a few bytes too much, presumably
an illegal pad, at the end of byte range lock responses an illegal pad, at the end of byte range lock responses
so we allow for that three byte pad, as long as actual so we allow for that three byte pad, as long as actual
...@@ -469,9 +472,12 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length) ...@@ -469,9 +472,12 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length)
wct and bcc to minimum size and drop the t2 parms and data */ wct and bcc to minimum size and drop the t2 parms and data */
if((4+len > clc_len) && (len <= clc_len + 512)) if((4+len > clc_len) && (len <= clc_len + 512))
return 0; return 0;
else else {
cERROR(1, ("RFC1001 size %d bigger than SMB for Mid=%d",
len, smb->Mid));
return 1; return 1;
} }
}
return 0; return 0;
} }
int int
......
/*
* fs/cifs/ntlmssp.h
*
* Copyright (c) International Business Machines Corp., 2006
* Author(s): Steve French (sfrench@us.ibm.com)
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "cifspdu.h"
#include "cifsglob.h"
#include "cifsproto.h"
#include "cifs_unicode.h"
#include "cifs_debug.h"
#include "ntlmssp.h"
#include "nterr.h"
#ifdef CONFIG_CIFS_EXPERIMENTAL
static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
{
__u32 capabilities = 0;
/* init fields common to all four types of SessSetup */
/* note that header is initialized to zero in header_assemble */
pSMB->req.AndXCommand = 0xFF;
pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
/* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */
/* BB verify whether signing required on neg or just on auth frame
(and NTLM case) */
capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
if (ses->capabilities & CAP_UNICODE) {
pSMB->req.hdr.Flags2 |= SMBFLG2_UNICODE;
capabilities |= CAP_UNICODE;
}
if (ses->capabilities & CAP_STATUS32) {
pSMB->req.hdr.Flags2 |= SMBFLG2_ERR_STATUS;
capabilities |= CAP_STATUS32;
}
if (ses->capabilities & CAP_DFS) {
pSMB->req.hdr.Flags2 |= SMBFLG2_DFS;
capabilities |= CAP_DFS;
}
/* BB check whether to init vcnum BB */
return capabilities;
}
int
CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, const int type,
int * pNTLMv2_flg, const struct nls_table *nls_cp)
{
int rc = 0;
int wct;
struct smb_hdr *smb_buffer;
char *bcc_ptr;
SESSION_SETUP_ANDX *pSMB;
__u32 capabilities;
if(ses == NULL)
return -EINVAL;
cFYI(1,("SStp type: %d",type));
if(type < CIFS_NTLM) {
#ifndef CONFIG_CIFS_WEAK_PW_HASH
/* LANMAN and plaintext are less secure and off by default.
So we make this explicitly be turned on in kconfig (in the
build) and turned on at runtime (changed from the default)
in proc/fs/cifs or via mount parm. Unfortunately this is
needed for old Win (e.g. Win95), some obscure NAS and OS/2 */
return -EOPNOTSUPP;
#endif
wct = 10; /* lanman 2 style sessionsetup */
} else if(type < CIFS_NTLMSSP_NEG)
wct = 13; /* old style NTLM sessionsetup */
else /* same size for negotiate or auth, NTLMSSP or extended security */
wct = 12;
rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
(void **)&smb_buffer);
if(rc)
return rc;
pSMB = (SESSION_SETUP_ANDX *)smb_buffer;
capabilities = cifs_ssetup_hdr(ses, pSMB);
bcc_ptr = pByteArea(smb_buffer);
if(type > CIFS_NTLM) {
pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
capabilities |= CAP_EXTENDED_SECURITY;
pSMB->req.Capabilities = cpu_to_le32(capabilities);
/* BB set password lengths */
} else if(type < CIFS_NTLM) /* lanman */ {
/* no capabilities flags in old lanman negotiation */
/* pSMB->old_req.PasswordLength = */ /* BB fixme BB */
} else /* type CIFS_NTLM */ {
pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
pSMB->req_no_secext.CaseInsensitivePasswordLength =
cpu_to_le16(CIFS_SESSION_KEY_SIZE);
pSMB->req_no_secext.CaseSensitivePasswordLength =
cpu_to_le16(CIFS_SESSION_KEY_SIZE);
}
/* rc = SendReceive2(xid, ses, iov, num_iovecs, &resp_buf_type, 0); */
/* SMB request buf freed in SendReceive2 */
return rc;
}
#endif /* CONFIG_CIFS_EXPERIMENTAL */
/* /*
* fs/cifs/ntlmssp.h * fs/cifs/ntlmssp.h
* *
* Copyright (c) International Business Machines Corp., 2002 * Copyright (c) International Business Machines Corp., 2002,2006
* Author(s): Steve French (sfrench@us.ibm.com) * Author(s): Steve French (sfrench@us.ibm.com)
* *
* This library is free software; you can redistribute it and/or modify * This library is free software; you can redistribute it and/or modify
......
...@@ -604,7 +604,12 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, ...@@ -604,7 +604,12 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
cifsFile->search_resume_name = NULL; cifsFile->search_resume_name = NULL;
if(cifsFile->srch_inf.ntwrk_buf_start) { if(cifsFile->srch_inf.ntwrk_buf_start) {
cFYI(1,("freeing SMB ff cache buf on search rewind")); cFYI(1,("freeing SMB ff cache buf on search rewind"));
cifs_buf_release(cifsFile->srch_inf.ntwrk_buf_start); if(cifsFile->srch_inf.smallBuf)
cifs_small_buf_release(cifsFile->srch_inf.
ntwrk_buf_start);
else
cifs_buf_release(cifsFile->srch_inf.
ntwrk_buf_start);
} }
rc = initiate_cifs_search(xid,file); rc = initiate_cifs_search(xid,file);
if(rc) { if(rc) {
......
...@@ -309,17 +309,16 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -309,17 +309,16 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
*pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */ *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
if (ses == NULL) { if ((ses == NULL) || (ses->server == NULL)) {
cERROR(1,("Null smb session")); cifs_small_buf_release(in_buf);
return -EIO; cERROR(1,("Null session"));
}
if(ses->server == NULL) {
cERROR(1,("Null tcp session"));
return -EIO; return -EIO;
} }
if(ses->server->tcpStatus == CifsExiting) if(ses->server->tcpStatus == CifsExiting) {
cifs_small_buf_release(in_buf);
return -ENOENT; return -ENOENT;
}
/* Ensure that we do not send more than 50 overlapping requests /* Ensure that we do not send more than 50 overlapping requests
to the same server. We may make this configurable later or to the same server. We may make this configurable later or
...@@ -346,6 +345,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -346,6 +345,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
} else { } else {
if(ses->server->tcpStatus == CifsExiting) { if(ses->server->tcpStatus == CifsExiting) {
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
cifs_small_buf_release(in_buf);
return -ENOENT; return -ENOENT;
} }
...@@ -385,6 +385,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -385,6 +385,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
midQ = AllocMidQEntry(in_buf, ses); midQ = AllocMidQEntry(in_buf, ses);
if (midQ == NULL) { if (midQ == NULL) {
up(&ses->server->tcpSem); up(&ses->server->tcpSem);
cifs_small_buf_release(in_buf);
/* If not lock req, update # of requests on wire to server */ /* If not lock req, update # of requests on wire to server */
if(long_op < 3) { if(long_op < 3) {
atomic_dec(&ses->server->inFlight); atomic_dec(&ses->server->inFlight);
...@@ -408,14 +409,18 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -408,14 +409,18 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
if(rc < 0) { if(rc < 0) {
DeleteMidQEntry(midQ); DeleteMidQEntry(midQ);
up(&ses->server->tcpSem); up(&ses->server->tcpSem);
cifs_small_buf_release(in_buf);
/* If not lock req, update # of requests on wire to server */ /* If not lock req, update # of requests on wire to server */
if(long_op < 3) { if(long_op < 3) {
atomic_dec(&ses->server->inFlight); atomic_dec(&ses->server->inFlight);
wake_up(&ses->server->request_q); wake_up(&ses->server->request_q);
} }
return rc; return rc;
} else } else {
up(&ses->server->tcpSem); up(&ses->server->tcpSem);
cifs_small_buf_release(in_buf);
}
if (long_op == -1) if (long_op == -1)
goto cifs_no_response_exit2; goto cifs_no_response_exit2;
else if (long_op == 2) /* writes past end of file can take loong time */ else if (long_op == 2) /* writes past end of file can take loong time */
...@@ -543,6 +548,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -543,6 +548,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
out_unlock2: out_unlock2:
up(&ses->server->tcpSem); up(&ses->server->tcpSem);
cifs_small_buf_release(in_buf);
/* If not lock req, update # of requests on wire to server */ /* If not lock req, update # of requests on wire to server */
if(long_op < 3) { if(long_op < 3) {
atomic_dec(&ses->server->inFlight); atomic_dec(&ses->server->inFlight);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册