Commit f2257b70 authored by Linus Torvalds's avatar 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:
  cifs: make sure we allocate enough storage for socket address
  [CIFS] Make socket retry timeouts consistent between blocking and nonblocking cases
  [CIFS] some cleanup to dir.c prior to addition of posix_open
  [CIFS] revalidate parent inode when rmdir done within that directory
  [CIFS] Rename md5 functions to avoid collision with new rt modules
  cifs: turn smb_send into a wrapper around smb_sendv
parents 1737ef75 a9ac49d3
...@@ -5,7 +5,9 @@ rather than posix (advisory) byte range locks, even though server would ...@@ -5,7 +5,9 @@ rather than posix (advisory) byte range locks, even though server would
support posix byte range locks. Fix query of root inode when prefixpath support posix byte range locks. Fix query of root inode when prefixpath
specified and user does not have access to query information about the specified and user does not have access to query information about the
top of the share. Fix problem in 2.6.28 resolving DFS paths to top of the share. Fix problem in 2.6.28 resolving DFS paths to
Samba servers (worked to Windows). Samba servers (worked to Windows). Fix rmdir so that pending search
(readdir) requests do not get invalid results which include the now
removed directory.
Version 1.55 Version 1.55
------------ ------------
......
...@@ -48,11 +48,11 @@ static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu, ...@@ -48,11 +48,11 @@ static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu,
if ((cifs_pdu == NULL) || (signature == NULL) || (key == NULL)) if ((cifs_pdu == NULL) || (signature == NULL) || (key == NULL))
return -EINVAL; return -EINVAL;
MD5Init(&context); cifs_MD5_init(&context);
MD5Update(&context, (char *)&key->data, key->len); cifs_MD5_update(&context, (char *)&key->data, key->len);
MD5Update(&context, cifs_pdu->Protocol, cifs_pdu->smb_buf_length); cifs_MD5_update(&context, cifs_pdu->Protocol, cifs_pdu->smb_buf_length);
MD5Final(signature, &context); cifs_MD5_final(signature, &context);
return 0; return 0;
} }
...@@ -96,8 +96,8 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec, ...@@ -96,8 +96,8 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
if ((iov == NULL) || (signature == NULL) || (key == NULL)) if ((iov == NULL) || (signature == NULL) || (key == NULL))
return -EINVAL; return -EINVAL;
MD5Init(&context); cifs_MD5_init(&context);
MD5Update(&context, (char *)&key->data, key->len); cifs_MD5_update(&context, (char *)&key->data, key->len);
for (i = 0; i < n_vec; i++) { for (i = 0; i < n_vec; i++) {
if (iov[i].iov_len == 0) if (iov[i].iov_len == 0)
continue; continue;
...@@ -110,13 +110,13 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec, ...@@ -110,13 +110,13 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
if (i == 0) { if (i == 0) {
if (iov[0].iov_len <= 8) /* cmd field at offset 9 */ if (iov[0].iov_len <= 8) /* cmd field at offset 9 */
break; /* nothing to sign or corrupt header */ break; /* nothing to sign or corrupt header */
MD5Update(&context, iov[0].iov_base+4, cifs_MD5_update(&context, iov[0].iov_base+4,
iov[0].iov_len-4); iov[0].iov_len-4);
} else } else
MD5Update(&context, iov[i].iov_base, iov[i].iov_len); cifs_MD5_update(&context, iov[i].iov_base, iov[i].iov_len);
} }
MD5Final(signature, &context); cifs_MD5_final(signature, &context);
return 0; return 0;
} }
......
...@@ -35,8 +35,8 @@ extern struct smb_hdr *cifs_buf_get(void); ...@@ -35,8 +35,8 @@ extern struct smb_hdr *cifs_buf_get(void);
extern void cifs_buf_release(void *); extern void cifs_buf_release(void *);
extern struct smb_hdr *cifs_small_buf_get(void); extern struct smb_hdr *cifs_small_buf_get(void);
extern void cifs_small_buf_release(void *); extern void cifs_small_buf_release(void *);
extern int smb_send(struct socket *, struct smb_hdr *, extern int smb_send(struct TCP_Server_Info *, struct smb_hdr *,
unsigned int /* length */ , struct sockaddr *, bool); unsigned int /* length */);
extern unsigned int _GetXid(void); extern unsigned int _GetXid(void);
extern void _FreeXid(unsigned int); extern void _FreeXid(unsigned int);
#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current_fsuid())); #define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current_fsuid()));
......
...@@ -1354,7 +1354,7 @@ cifs_parse_mount_options(char *options, const char *devname, ...@@ -1354,7 +1354,7 @@ cifs_parse_mount_options(char *options, const char *devname,
} }
static struct TCP_Server_Info * static struct TCP_Server_Info *
cifs_find_tcp_session(struct sockaddr *addr) cifs_find_tcp_session(struct sockaddr_storage *addr)
{ {
struct list_head *tmp; struct list_head *tmp;
struct TCP_Server_Info *server; struct TCP_Server_Info *server;
...@@ -1374,11 +1374,11 @@ cifs_find_tcp_session(struct sockaddr *addr) ...@@ -1374,11 +1374,11 @@ cifs_find_tcp_session(struct sockaddr *addr)
if (server->tcpStatus == CifsNew) if (server->tcpStatus == CifsNew)
continue; continue;
if (addr->sa_family == AF_INET && if (addr->ss_family == AF_INET &&
(addr4->sin_addr.s_addr != (addr4->sin_addr.s_addr !=
server->addr.sockAddr.sin_addr.s_addr)) server->addr.sockAddr.sin_addr.s_addr))
continue; continue;
else if (addr->sa_family == AF_INET6 && else if (addr->ss_family == AF_INET6 &&
memcmp(&server->addr.sockAddr6.sin6_addr, memcmp(&server->addr.sockAddr6.sin6_addr,
&addr6->sin6_addr, sizeof(addr6->sin6_addr))) &addr6->sin6_addr, sizeof(addr6->sin6_addr)))
continue; continue;
...@@ -1419,12 +1419,12 @@ static struct TCP_Server_Info * ...@@ -1419,12 +1419,12 @@ static struct TCP_Server_Info *
cifs_get_tcp_session(struct smb_vol *volume_info) cifs_get_tcp_session(struct smb_vol *volume_info)
{ {
struct TCP_Server_Info *tcp_ses = NULL; struct TCP_Server_Info *tcp_ses = NULL;
struct sockaddr addr; struct sockaddr_storage addr;
struct sockaddr_in *sin_server = (struct sockaddr_in *) &addr; struct sockaddr_in *sin_server = (struct sockaddr_in *) &addr;
struct sockaddr_in6 *sin_server6 = (struct sockaddr_in6 *) &addr; struct sockaddr_in6 *sin_server6 = (struct sockaddr_in6 *) &addr;
int rc; int rc;
memset(&addr, 0, sizeof(struct sockaddr)); memset(&addr, 0, sizeof(struct sockaddr_storage));
if (volume_info->UNCip && volume_info->UNC) { if (volume_info->UNCip && volume_info->UNC) {
rc = cifs_inet_pton(AF_INET, volume_info->UNCip, rc = cifs_inet_pton(AF_INET, volume_info->UNCip,
...@@ -1435,9 +1435,9 @@ cifs_get_tcp_session(struct smb_vol *volume_info) ...@@ -1435,9 +1435,9 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
rc = cifs_inet_pton(AF_INET6, volume_info->UNCip, rc = cifs_inet_pton(AF_INET6, volume_info->UNCip,
&sin_server6->sin6_addr.in6_u); &sin_server6->sin6_addr.in6_u);
if (rc > 0) if (rc > 0)
addr.sa_family = AF_INET6; addr.ss_family = AF_INET6;
} else { } else {
addr.sa_family = AF_INET; addr.ss_family = AF_INET;
} }
if (rc <= 0) { if (rc <= 0) {
...@@ -1502,7 +1502,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info) ...@@ -1502,7 +1502,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
tcp_ses->tcpStatus = CifsNew; tcp_ses->tcpStatus = CifsNew;
++tcp_ses->srv_count; ++tcp_ses->srv_count;
if (addr.sa_family == AF_INET6) { if (addr.ss_family == AF_INET6) {
cFYI(1, ("attempting ipv6 connect")); cFYI(1, ("attempting ipv6 connect"));
/* BB should we allow ipv6 on port 139? */ /* BB should we allow ipv6 on port 139? */
/* other OS never observed in Wild doing 139 with v6 */ /* other OS never observed in Wild doing 139 with v6 */
...@@ -1802,7 +1802,7 @@ ipv4_connect(struct TCP_Server_Info *server) ...@@ -1802,7 +1802,7 @@ ipv4_connect(struct TCP_Server_Info *server)
* user space buffer * user space buffer
*/ */
socket->sk->sk_rcvtimeo = 7 * HZ; socket->sk->sk_rcvtimeo = 7 * HZ;
socket->sk->sk_sndtimeo = 3 * HZ; socket->sk->sk_sndtimeo = 5 * HZ;
/* make the bufsizes depend on wsize/rsize and max requests */ /* make the bufsizes depend on wsize/rsize and max requests */
if (server->noautotune) { if (server->noautotune) {
...@@ -1860,9 +1860,7 @@ ipv4_connect(struct TCP_Server_Info *server) ...@@ -1860,9 +1860,7 @@ ipv4_connect(struct TCP_Server_Info *server)
smb_buf = (struct smb_hdr *)ses_init_buf; smb_buf = (struct smb_hdr *)ses_init_buf;
/* sizeof RFC1002_SESSION_REQUEST with no scope */ /* sizeof RFC1002_SESSION_REQUEST with no scope */
smb_buf->smb_buf_length = 0x81000044; smb_buf->smb_buf_length = 0x81000044;
rc = smb_send(socket, smb_buf, 0x44, rc = smb_send(server, smb_buf, 0x44);
(struct sockaddr *) &server->addr.sockAddr,
server->noblocksnd);
kfree(ses_init_buf); kfree(ses_init_buf);
msleep(1); /* RFC1001 layer in at least one server msleep(1); /* RFC1001 layer in at least one server
requires very short break before negprot requires very short break before negprot
...@@ -1955,7 +1953,7 @@ ipv6_connect(struct TCP_Server_Info *server) ...@@ -1955,7 +1953,7 @@ ipv6_connect(struct TCP_Server_Info *server)
* user space buffer * user space buffer
*/ */
socket->sk->sk_rcvtimeo = 7 * HZ; socket->sk->sk_rcvtimeo = 7 * HZ;
socket->sk->sk_sndtimeo = 3 * HZ; socket->sk->sk_sndtimeo = 5 * HZ;
server->ssocket = socket; server->ssocket = socket;
return rc; return rc;
......
...@@ -129,6 +129,17 @@ build_path_from_dentry(struct dentry *direntry) ...@@ -129,6 +129,17 @@ build_path_from_dentry(struct dentry *direntry)
return full_path; return full_path;
} }
static void setup_cifs_dentry(struct cifsTconInfo *tcon,
struct dentry *direntry,
struct inode *newinode)
{
if (tcon->nocase)
direntry->d_op = &cifs_ci_dentry_ops;
else
direntry->d_op = &cifs_dentry_ops;
d_instantiate(direntry, newinode);
}
/* Inode operations in similar order to how they appear in Linux file fs.h */ /* Inode operations in similar order to how they appear in Linux file fs.h */
int int
...@@ -139,14 +150,14 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -139,14 +150,14 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
int xid; int xid;
int create_options = CREATE_NOT_DIR; int create_options = CREATE_NOT_DIR;
int oplock = 0; int oplock = 0;
/* BB below access is too much for the mknod to request */
int desiredAccess = GENERIC_READ | GENERIC_WRITE; int desiredAccess = GENERIC_READ | GENERIC_WRITE;
__u16 fileHandle; __u16 fileHandle;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon; struct cifsTconInfo *tcon;
char *full_path = NULL; char *full_path = NULL;
FILE_ALL_INFO *buf = NULL; FILE_ALL_INFO *buf = NULL;
struct inode *newinode = NULL; struct inode *newinode = NULL;
struct cifsFileInfo *pCifsFile = NULL;
struct cifsInodeInfo *pCifsInode; struct cifsInodeInfo *pCifsInode;
int disposition = FILE_OVERWRITE_IF; int disposition = FILE_OVERWRITE_IF;
bool write_only = false; bool write_only = false;
...@@ -154,7 +165,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -154,7 +165,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
xid = GetXid(); xid = GetXid();
cifs_sb = CIFS_SB(inode->i_sb); cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon; tcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if (full_path == NULL) { if (full_path == NULL) {
...@@ -162,6 +173,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -162,6 +173,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
return -ENOMEM; return -ENOMEM;
} }
mode &= ~current->fs->umask;
if (nd && (nd->flags & LOOKUP_OPEN)) { if (nd && (nd->flags & LOOKUP_OPEN)) {
int oflags = nd->intent.open.flags; int oflags = nd->intent.open.flags;
...@@ -196,17 +209,15 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -196,17 +209,15 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
return -ENOMEM; return -ENOMEM;
} }
mode &= ~current->fs->umask;
/* /*
* if we're not using unix extensions, see if we need to set * if we're not using unix extensions, see if we need to set
* ATTR_READONLY on the create call * ATTR_READONLY on the create call
*/ */
if (!pTcon->unix_ext && (mode & S_IWUGO) == 0) if (!tcon->unix_ext && (mode & S_IWUGO) == 0)
create_options |= CREATE_OPTION_READONLY; create_options |= CREATE_OPTION_READONLY;
if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS) if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
desiredAccess, create_options, desiredAccess, create_options,
&fileHandle, &oplock, buf, cifs_sb->local_nls, &fileHandle, &oplock, buf, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
...@@ -215,7 +226,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -215,7 +226,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
if (rc == -EIO) { if (rc == -EIO) {
/* old server, retry the open legacy style */ /* old server, retry the open legacy style */
rc = SMBLegacyOpen(xid, pTcon, full_path, disposition, rc = SMBLegacyOpen(xid, tcon, full_path, disposition,
desiredAccess, create_options, desiredAccess, create_options,
&fileHandle, &oplock, buf, cifs_sb->local_nls, &fileHandle, &oplock, buf, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
...@@ -225,7 +236,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -225,7 +236,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
} else { } else {
/* If Open reported that we actually created a file /* If Open reported that we actually created a file
then we now have to set the mode if possible */ then we now have to set the mode if possible */
if ((pTcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) { if ((tcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) {
struct cifs_unix_set_info_args args = { struct cifs_unix_set_info_args args = {
.mode = mode, .mode = mode,
.ctime = NO_CHANGE_64, .ctime = NO_CHANGE_64,
...@@ -244,20 +255,20 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -244,20 +255,20 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
args.uid = NO_CHANGE_64; args.uid = NO_CHANGE_64;
args.gid = NO_CHANGE_64; args.gid = NO_CHANGE_64;
} }
CIFSSMBUnixSetInfo(xid, pTcon, full_path, &args, CIFSSMBUnixSetInfo(xid, tcon, full_path, &args,
cifs_sb->local_nls, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
} else { } else {
/* BB implement mode setting via Windows security /* BB implement mode setting via Windows security
descriptors e.g. */ descriptors e.g. */
/* CIFSSMBWinSetPerms(xid,pTcon,path,mode,-1,-1,nls);*/ /* CIFSSMBWinSetPerms(xid,tcon,path,mode,-1,-1,nls);*/
/* Could set r/o dos attribute if mode & 0222 == 0 */ /* Could set r/o dos attribute if mode & 0222 == 0 */
} }
/* server might mask mode so we have to query for it */ /* server might mask mode so we have to query for it */
if (pTcon->unix_ext) if (tcon->unix_ext)
rc = cifs_get_inode_info_unix(&newinode, full_path, rc = cifs_get_inode_info_unix(&newinode, full_path,
inode->i_sb, xid); inode->i_sb, xid);
else { else {
...@@ -283,22 +294,17 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -283,22 +294,17 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
} }
if (rc != 0) { if (rc != 0) {
cFYI(1, cFYI(1, ("Create worked, get_inode_info failed rc = %d",
("Create worked but get_inode_info failed rc = %d",
rc)); rc));
} else { } else
if (pTcon->nocase) setup_cifs_dentry(tcon, direntry, newinode);
direntry->d_op = &cifs_ci_dentry_ops;
else
direntry->d_op = &cifs_dentry_ops;
d_instantiate(direntry, newinode);
}
if ((nd == NULL /* nfsd case - nfs srv does not set nd */) || if ((nd == NULL /* nfsd case - nfs srv does not set nd */) ||
(!(nd->flags & LOOKUP_OPEN))) { (!(nd->flags & LOOKUP_OPEN))) {
/* mknod case - do not leave file open */ /* mknod case - do not leave file open */
CIFSSMBClose(xid, pTcon, fileHandle); CIFSSMBClose(xid, tcon, fileHandle);
} else if (newinode) { } else if (newinode) {
pCifsFile = struct cifsFileInfo *pCifsFile =
kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
if (pCifsFile == NULL) if (pCifsFile == NULL)
...@@ -316,7 +322,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -316,7 +322,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
/* set the following in open now /* set the following in open now
pCifsFile->pfile = file; */ pCifsFile->pfile = file; */
write_lock(&GlobalSMBSeslock); write_lock(&GlobalSMBSeslock);
list_add(&pCifsFile->tlist, &pTcon->openFileList); list_add(&pCifsFile->tlist, &tcon->openFileList);
pCifsInode = CIFS_I(newinode); pCifsInode = CIFS_I(newinode);
if (pCifsInode) { if (pCifsInode) {
/* if readable file instance put first in list*/ /* if readable file instance put first in list*/
......
...@@ -1285,6 +1285,11 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) ...@@ -1285,6 +1285,11 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
cifsInode = CIFS_I(direntry->d_inode); cifsInode = CIFS_I(direntry->d_inode);
cifsInode->time = 0; /* force revalidate to go get info when cifsInode->time = 0; /* force revalidate to go get info when
needed */ needed */
cifsInode = CIFS_I(inode);
cifsInode->time = 0; /* force revalidate to get parent dir info
since cached search results now invalid */
direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime = direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
current_fs_time(inode->i_sb); current_fs_time(inode->i_sb);
......
...@@ -10,8 +10,8 @@ ...@@ -10,8 +10,8 @@
* with every copy. * with every copy.
* *
* To compute the message digest of a chunk of bytes, declare an * To compute the message digest of a chunk of bytes, declare an
* MD5Context structure, pass it to MD5Init, call MD5Update as * MD5Context structure, pass it to cifs_MD5_init, call cifs_MD5_update as
* needed on buffers full of bytes, and then call MD5Final, which * needed on buffers full of bytes, and then call cifs_MD5_final, which
* will fill a supplied 16-byte array with the digest. * will fill a supplied 16-byte array with the digest.
*/ */
...@@ -45,7 +45,7 @@ byteReverse(unsigned char *buf, unsigned longs) ...@@ -45,7 +45,7 @@ byteReverse(unsigned char *buf, unsigned longs)
* initialization constants. * initialization constants.
*/ */
void void
MD5Init(struct MD5Context *ctx) cifs_MD5_init(struct MD5Context *ctx)
{ {
ctx->buf[0] = 0x67452301; ctx->buf[0] = 0x67452301;
ctx->buf[1] = 0xefcdab89; ctx->buf[1] = 0xefcdab89;
...@@ -61,7 +61,7 @@ MD5Init(struct MD5Context *ctx) ...@@ -61,7 +61,7 @@ MD5Init(struct MD5Context *ctx)
* of bytes. * of bytes.
*/ */
void void
MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) cifs_MD5_update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
{ {
register __u32 t; register __u32 t;
...@@ -110,7 +110,7 @@ MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) ...@@ -110,7 +110,7 @@ MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
* 1 0* (64-bit count of bits processed, MSB-first) * 1 0* (64-bit count of bits processed, MSB-first)
*/ */
void void
MD5Final(unsigned char digest[16], struct MD5Context *ctx) cifs_MD5_final(unsigned char digest[16], struct MD5Context *ctx)
{ {
unsigned int count; unsigned int count;
unsigned char *p; unsigned char *p;
...@@ -165,7 +165,7 @@ MD5Final(unsigned char digest[16], struct MD5Context *ctx) ...@@ -165,7 +165,7 @@ MD5Final(unsigned char digest[16], struct MD5Context *ctx)
/* /*
* The core of the MD5 algorithm, this alters an existing MD5 hash to * The core of the MD5 algorithm, this alters an existing MD5 hash to
* reflect the addition of 16 longwords of new data. MD5Update blocks * reflect the addition of 16 longwords of new data. cifs_MD5_update blocks
* the data and converts bytes into longwords for this routine. * the data and converts bytes into longwords for this routine.
*/ */
static void static void
...@@ -267,9 +267,9 @@ hmac_md5_init_rfc2104(unsigned char *key, int key_len, ...@@ -267,9 +267,9 @@ hmac_md5_init_rfc2104(unsigned char *key, int key_len,
unsigned char tk[16]; unsigned char tk[16];
struct MD5Context tctx; struct MD5Context tctx;
MD5Init(&tctx); cifs_MD5_init(&tctx);
MD5Update(&tctx, key, key_len); cifs_MD5_update(&tctx, key, key_len);
MD5Final(tk, &tctx); cifs_MD5_final(tk, &tctx);
key = tk; key = tk;
key_len = 16; key_len = 16;
...@@ -287,8 +287,8 @@ hmac_md5_init_rfc2104(unsigned char *key, int key_len, ...@@ -287,8 +287,8 @@ hmac_md5_init_rfc2104(unsigned char *key, int key_len,
ctx->k_opad[i] ^= 0x5c; ctx->k_opad[i] ^= 0x5c;
} }
MD5Init(&ctx->ctx); cifs_MD5_init(&ctx->ctx);
MD5Update(&ctx->ctx, ctx->k_ipad, 64); cifs_MD5_update(&ctx->ctx, ctx->k_ipad, 64);
} }
#endif #endif
...@@ -317,8 +317,8 @@ hmac_md5_init_limK_to_64(const unsigned char *key, int key_len, ...@@ -317,8 +317,8 @@ hmac_md5_init_limK_to_64(const unsigned char *key, int key_len,
ctx->k_opad[i] ^= 0x5c; ctx->k_opad[i] ^= 0x5c;
} }
MD5Init(&ctx->ctx); cifs_MD5_init(&ctx->ctx);
MD5Update(&ctx->ctx, ctx->k_ipad, 64); cifs_MD5_update(&ctx->ctx, ctx->k_ipad, 64);
} }
/*********************************************************************** /***********************************************************************
...@@ -328,7 +328,7 @@ void ...@@ -328,7 +328,7 @@ void
hmac_md5_update(const unsigned char *text, int text_len, hmac_md5_update(const unsigned char *text, int text_len,
struct HMACMD5Context *ctx) struct HMACMD5Context *ctx)
{ {
MD5Update(&ctx->ctx, text, text_len); /* then text of datagram */ cifs_MD5_update(&ctx->ctx, text, text_len); /* then text of datagram */
} }
/*********************************************************************** /***********************************************************************
...@@ -339,12 +339,12 @@ hmac_md5_final(unsigned char *digest, struct HMACMD5Context *ctx) ...@@ -339,12 +339,12 @@ hmac_md5_final(unsigned char *digest, struct HMACMD5Context *ctx)
{ {
struct MD5Context ctx_o; struct MD5Context ctx_o;
MD5Final(digest, &ctx->ctx); cifs_MD5_final(digest, &ctx->ctx);
MD5Init(&ctx_o); cifs_MD5_init(&ctx_o);
MD5Update(&ctx_o, ctx->k_opad, 64); cifs_MD5_update(&ctx_o, ctx->k_opad, 64);
MD5Update(&ctx_o, digest, 16); cifs_MD5_update(&ctx_o, digest, 16);
MD5Final(digest, &ctx_o); cifs_MD5_final(digest, &ctx_o);
} }
/*********************************************************** /***********************************************************
......
...@@ -20,10 +20,10 @@ struct HMACMD5Context { ...@@ -20,10 +20,10 @@ struct HMACMD5Context {
}; };
#endif /* _HMAC_MD5_H */ #endif /* _HMAC_MD5_H */
void MD5Init(struct MD5Context *context); void cifs_MD5_init(struct MD5Context *context);
void MD5Update(struct MD5Context *context, unsigned char const *buf, void cifs_MD5_update(struct MD5Context *context, unsigned char const *buf,
unsigned len); unsigned len);
void MD5Final(unsigned char digest[16], struct MD5Context *context); void cifs_MD5_final(unsigned char digest[16], struct MD5Context *context);
/* The following definitions come from lib/hmacmd5.c */ /* The following definitions come from lib/hmacmd5.c */
......
...@@ -154,81 +154,8 @@ void DeleteTconOplockQEntries(struct cifsTconInfo *tcon) ...@@ -154,81 +154,8 @@ void DeleteTconOplockQEntries(struct cifsTconInfo *tcon)
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
} }
int
smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
unsigned int smb_buf_length, struct sockaddr *sin, bool noblocksnd)
{
int rc = 0;
int i = 0;
struct msghdr smb_msg;
struct kvec iov;
unsigned len = smb_buf_length + 4;
if (ssocket == NULL)
return -ENOTSOCK; /* BB eventually add reconnect code here */
iov.iov_base = smb_buffer;
iov.iov_len = len;
smb_msg.msg_name = sin;
smb_msg.msg_namelen = sizeof(struct sockaddr);
smb_msg.msg_control = NULL;
smb_msg.msg_controllen = 0;
if (noblocksnd)
smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL;
else
smb_msg.msg_flags = MSG_NOSIGNAL;
/* smb header is converted in header_assemble. bcc and rest of SMB word
area, and byte area if necessary, is converted to littleendian in
cifssmb.c and RFC1001 len is converted to bigendian in smb_send
Flags2 is converted in SendReceive */
smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
cFYI(1, ("Sending smb of length %d", smb_buf_length));
dump_smb(smb_buffer, len);
while (len > 0) {
rc = kernel_sendmsg(ssocket, &smb_msg, &iov, 1, len);
if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
i++;
/* smaller timeout here than send2 since smaller size */
/* Although it may not be required, this also is smaller
oplock break time */
if (i > 12) {
cERROR(1,
("sends on sock %p stuck for 7 seconds",
ssocket));
rc = -EAGAIN;
break;
}
msleep(1 << i);
continue;
}
if (rc < 0)
break;
else
i = 0; /* reset i after each successful send */
iov.iov_base += rc;
iov.iov_len -= rc;
len -= rc;
}
if (rc < 0) {
cERROR(1, ("Error %d sending data on socket to server", rc));
} else {
rc = 0;
}
/* Don't want to modify the buffer as a
side effect of this call. */
smb_buffer->smb_buf_length = smb_buf_length;
return rc;
}
static int static int
smb_send2(struct TCP_Server_Info *server, struct kvec *iov, int n_vec, smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
struct sockaddr *sin, bool noblocksnd)
{ {
int rc = 0; int rc = 0;
int i = 0; int i = 0;
...@@ -243,11 +170,11 @@ smb_send2(struct TCP_Server_Info *server, struct kvec *iov, int n_vec, ...@@ -243,11 +170,11 @@ smb_send2(struct TCP_Server_Info *server, struct kvec *iov, int n_vec,
if (ssocket == NULL) if (ssocket == NULL)
return -ENOTSOCK; /* BB eventually add reconnect code here */ return -ENOTSOCK; /* BB eventually add reconnect code here */
smb_msg.msg_name = sin; smb_msg.msg_name = (struct sockaddr *) &server->addr.sockAddr;
smb_msg.msg_namelen = sizeof(struct sockaddr); smb_msg.msg_namelen = sizeof(struct sockaddr);
smb_msg.msg_control = NULL; smb_msg.msg_control = NULL;
smb_msg.msg_controllen = 0; smb_msg.msg_controllen = 0;
if (noblocksnd) if (server->noblocksnd)
smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL;
else else
smb_msg.msg_flags = MSG_NOSIGNAL; smb_msg.msg_flags = MSG_NOSIGNAL;
...@@ -272,7 +199,25 @@ smb_send2(struct TCP_Server_Info *server, struct kvec *iov, int n_vec, ...@@ -272,7 +199,25 @@ smb_send2(struct TCP_Server_Info *server, struct kvec *iov, int n_vec,
n_vec - first_vec, total_len); n_vec - first_vec, total_len);
if ((rc == -ENOSPC) || (rc == -EAGAIN)) { if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
i++; i++;
if (i >= 14) { /* if blocking send we try 3 times, since each can block
for 5 seconds. For nonblocking we have to try more
but wait increasing amounts of time allowing time for
socket to clear. The overall time we wait in either
case to send on the socket is about 15 seconds.
Similarly we wait for 15 seconds for
a response from the server in SendReceive[2]
for the server to send a response back for
most types of requests (except SMB Write
past end of file which can be slow, and
blocking lock operations). NFS waits slightly longer
than CIFS, but this can make it take longer for
nonresponsive servers to be detected and 15 seconds
is more than enough time for modern networks to
send a packet. In most cases if we fail to send
after the retries we will kill the socket and
reconnect which may clear the network problem.
*/
if ((i >= 14) || (!server->noblocksnd && (i > 2))) {
cERROR(1, cERROR(1,
("sends on sock %p stuck for 15 seconds", ("sends on sock %p stuck for 15 seconds",
ssocket)); ssocket));
...@@ -339,6 +284,18 @@ smb_send2(struct TCP_Server_Info *server, struct kvec *iov, int n_vec, ...@@ -339,6 +284,18 @@ smb_send2(struct TCP_Server_Info *server, struct kvec *iov, int n_vec,
return rc; return rc;
} }
int
smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer,
unsigned int smb_buf_length)
{
struct kvec iov;
iov.iov_base = smb_buffer;
iov.iov_len = smb_buf_length + 4;
return smb_sendv(server, &iov, 1);
}
static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op) static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op)
{ {
if (long_op == CIFS_ASYNC_OP) { if (long_op == CIFS_ASYNC_OP) {
...@@ -540,9 +497,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -540,9 +497,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
#ifdef CONFIG_CIFS_STATS2 #ifdef CONFIG_CIFS_STATS2
atomic_inc(&ses->server->inSend); atomic_inc(&ses->server->inSend);
#endif #endif
rc = smb_send2(ses->server, iov, n_vec, rc = smb_sendv(ses->server, iov, n_vec);
(struct sockaddr *) &(ses->server->addr.sockAddr),
ses->server->noblocksnd);
#ifdef CONFIG_CIFS_STATS2 #ifdef CONFIG_CIFS_STATS2
atomic_dec(&ses->server->inSend); atomic_dec(&ses->server->inSend);
midQ->when_sent = jiffies; midQ->when_sent = jiffies;
...@@ -736,9 +691,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, ...@@ -736,9 +691,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
#ifdef CONFIG_CIFS_STATS2 #ifdef CONFIG_CIFS_STATS2
atomic_inc(&ses->server->inSend); atomic_inc(&ses->server->inSend);
#endif #endif
rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
(struct sockaddr *) &(ses->server->addr.sockAddr),
ses->server->noblocksnd);
#ifdef CONFIG_CIFS_STATS2 #ifdef CONFIG_CIFS_STATS2
atomic_dec(&ses->server->inSend); atomic_dec(&ses->server->inSend);
midQ->when_sent = jiffies; midQ->when_sent = jiffies;
...@@ -879,9 +832,7 @@ send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf, ...@@ -879,9 +832,7 @@ send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf,
mutex_unlock(&ses->server->srv_mutex); mutex_unlock(&ses->server->srv_mutex);
return rc; return rc;
} }
rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
(struct sockaddr *) &(ses->server->addr.sockAddr),
ses->server->noblocksnd);
mutex_unlock(&ses->server->srv_mutex); mutex_unlock(&ses->server->srv_mutex);
return rc; return rc;
} }
...@@ -973,9 +924,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, ...@@ -973,9 +924,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
#ifdef CONFIG_CIFS_STATS2 #ifdef CONFIG_CIFS_STATS2
atomic_inc(&ses->server->inSend); atomic_inc(&ses->server->inSend);
#endif #endif
rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
(struct sockaddr *) &(ses->server->addr.sockAddr),
ses->server->noblocksnd);
#ifdef CONFIG_CIFS_STATS2 #ifdef CONFIG_CIFS_STATS2
atomic_dec(&ses->server->inSend); atomic_dec(&ses->server->inSend);
midQ->when_sent = jiffies; midQ->when_sent = jiffies;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment