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
This commit is contained in:
commit
f2257b70b0
9 changed files with 121 additions and 161 deletions
|
@ -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
|
||||
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
|
||||
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
|
||||
------------
|
||||
|
|
|
@ -48,11 +48,11 @@ static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu,
|
|||
if ((cifs_pdu == NULL) || (signature == NULL) || (key == NULL))
|
||||
return -EINVAL;
|
||||
|
||||
MD5Init(&context);
|
||||
MD5Update(&context, (char *)&key->data, key->len);
|
||||
MD5Update(&context, cifs_pdu->Protocol, cifs_pdu->smb_buf_length);
|
||||
cifs_MD5_init(&context);
|
||||
cifs_MD5_update(&context, (char *)&key->data, key->len);
|
||||
cifs_MD5_update(&context, cifs_pdu->Protocol, cifs_pdu->smb_buf_length);
|
||||
|
||||
MD5Final(signature, &context);
|
||||
cifs_MD5_final(signature, &context);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -96,8 +96,8 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
|
|||
if ((iov == NULL) || (signature == NULL) || (key == NULL))
|
||||
return -EINVAL;
|
||||
|
||||
MD5Init(&context);
|
||||
MD5Update(&context, (char *)&key->data, key->len);
|
||||
cifs_MD5_init(&context);
|
||||
cifs_MD5_update(&context, (char *)&key->data, key->len);
|
||||
for (i = 0; i < n_vec; i++) {
|
||||
if (iov[i].iov_len == 0)
|
||||
continue;
|
||||
|
@ -110,13 +110,13 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec,
|
|||
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,
|
||||
cifs_MD5_update(&context, iov[0].iov_base+4,
|
||||
iov[0].iov_len-4);
|
||||
} 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;
|
||||
}
|
||||
|
|
|
@ -35,8 +35,8 @@ extern struct smb_hdr *cifs_buf_get(void);
|
|||
extern void cifs_buf_release(void *);
|
||||
extern struct smb_hdr *cifs_small_buf_get(void);
|
||||
extern void cifs_small_buf_release(void *);
|
||||
extern int smb_send(struct socket *, struct smb_hdr *,
|
||||
unsigned int /* length */ , struct sockaddr *, bool);
|
||||
extern int smb_send(struct TCP_Server_Info *, struct smb_hdr *,
|
||||
unsigned int /* length */);
|
||||
extern unsigned int _GetXid(void);
|
||||
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()));
|
||||
|
|
|
@ -1354,7 +1354,7 @@ cifs_parse_mount_options(char *options, const char *devname,
|
|||
}
|
||||
|
||||
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 TCP_Server_Info *server;
|
||||
|
@ -1374,11 +1374,11 @@ cifs_find_tcp_session(struct sockaddr *addr)
|
|||
if (server->tcpStatus == CifsNew)
|
||||
continue;
|
||||
|
||||
if (addr->sa_family == AF_INET &&
|
||||
if (addr->ss_family == AF_INET &&
|
||||
(addr4->sin_addr.s_addr !=
|
||||
server->addr.sockAddr.sin_addr.s_addr))
|
||||
continue;
|
||||
else if (addr->sa_family == AF_INET6 &&
|
||||
else if (addr->ss_family == AF_INET6 &&
|
||||
memcmp(&server->addr.sockAddr6.sin6_addr,
|
||||
&addr6->sin6_addr, sizeof(addr6->sin6_addr)))
|
||||
continue;
|
||||
|
@ -1419,12 +1419,12 @@ static struct TCP_Server_Info *
|
|||
cifs_get_tcp_session(struct smb_vol *volume_info)
|
||||
{
|
||||
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_in6 *sin_server6 = (struct sockaddr_in6 *) &addr;
|
||||
int rc;
|
||||
|
||||
memset(&addr, 0, sizeof(struct sockaddr));
|
||||
memset(&addr, 0, sizeof(struct sockaddr_storage));
|
||||
|
||||
if (volume_info->UNCip && volume_info->UNC) {
|
||||
rc = cifs_inet_pton(AF_INET, volume_info->UNCip,
|
||||
|
@ -1435,9 +1435,9 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
|
|||
rc = cifs_inet_pton(AF_INET6, volume_info->UNCip,
|
||||
&sin_server6->sin6_addr.in6_u);
|
||||
if (rc > 0)
|
||||
addr.sa_family = AF_INET6;
|
||||
addr.ss_family = AF_INET6;
|
||||
} else {
|
||||
addr.sa_family = AF_INET;
|
||||
addr.ss_family = AF_INET;
|
||||
}
|
||||
|
||||
if (rc <= 0) {
|
||||
|
@ -1502,7 +1502,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
|
|||
tcp_ses->tcpStatus = CifsNew;
|
||||
++tcp_ses->srv_count;
|
||||
|
||||
if (addr.sa_family == AF_INET6) {
|
||||
if (addr.ss_family == AF_INET6) {
|
||||
cFYI(1, ("attempting ipv6 connect"));
|
||||
/* BB should we allow ipv6 on port 139? */
|
||||
/* other OS never observed in Wild doing 139 with v6 */
|
||||
|
@ -1802,7 +1802,7 @@ ipv4_connect(struct TCP_Server_Info *server)
|
|||
* user space buffer
|
||||
*/
|
||||
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 */
|
||||
if (server->noautotune) {
|
||||
|
@ -1860,9 +1860,7 @@ ipv4_connect(struct TCP_Server_Info *server)
|
|||
smb_buf = (struct smb_hdr *)ses_init_buf;
|
||||
/* sizeof RFC1002_SESSION_REQUEST with no scope */
|
||||
smb_buf->smb_buf_length = 0x81000044;
|
||||
rc = smb_send(socket, smb_buf, 0x44,
|
||||
(struct sockaddr *) &server->addr.sockAddr,
|
||||
server->noblocksnd);
|
||||
rc = smb_send(server, smb_buf, 0x44);
|
||||
kfree(ses_init_buf);
|
||||
msleep(1); /* RFC1001 layer in at least one server
|
||||
requires very short break before negprot
|
||||
|
@ -1955,7 +1953,7 @@ ipv6_connect(struct TCP_Server_Info *server)
|
|||
* user space buffer
|
||||
*/
|
||||
socket->sk->sk_rcvtimeo = 7 * HZ;
|
||||
socket->sk->sk_sndtimeo = 3 * HZ;
|
||||
socket->sk->sk_sndtimeo = 5 * HZ;
|
||||
server->ssocket = socket;
|
||||
|
||||
return rc;
|
||||
|
|
|
@ -129,6 +129,17 @@ cifs_bp_rename_retry:
|
|||
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 */
|
||||
|
||||
int
|
||||
|
@ -139,14 +150,14 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
|
|||
int xid;
|
||||
int create_options = CREATE_NOT_DIR;
|
||||
int oplock = 0;
|
||||
/* BB below access is too much for the mknod to request */
|
||||
int desiredAccess = GENERIC_READ | GENERIC_WRITE;
|
||||
__u16 fileHandle;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct cifsTconInfo *pTcon;
|
||||
struct cifsTconInfo *tcon;
|
||||
char *full_path = NULL;
|
||||
FILE_ALL_INFO *buf = NULL;
|
||||
struct inode *newinode = NULL;
|
||||
struct cifsFileInfo *pCifsFile = NULL;
|
||||
struct cifsInodeInfo *pCifsInode;
|
||||
int disposition = FILE_OVERWRITE_IF;
|
||||
bool write_only = false;
|
||||
|
@ -154,7 +165,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
|
|||
xid = GetXid();
|
||||
|
||||
cifs_sb = CIFS_SB(inode->i_sb);
|
||||
pTcon = cifs_sb->tcon;
|
||||
tcon = cifs_sb->tcon;
|
||||
|
||||
full_path = build_path_from_dentry(direntry);
|
||||
if (full_path == NULL) {
|
||||
|
@ -162,6 +173,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mode &= ~current->fs->umask;
|
||||
|
||||
if (nd && (nd->flags & LOOKUP_OPEN)) {
|
||||
int oflags = nd->intent.open.flags;
|
||||
|
||||
|
@ -196,17 +209,15 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mode &= ~current->fs->umask;
|
||||
|
||||
/*
|
||||
* if we're not using unix extensions, see if we need to set
|
||||
* 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;
|
||||
|
||||
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,
|
||||
&fileHandle, &oplock, buf, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
|
@ -215,7 +226,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
|
|||
|
||||
if (rc == -EIO) {
|
||||
/* old server, retry the open legacy style */
|
||||
rc = SMBLegacyOpen(xid, pTcon, full_path, disposition,
|
||||
rc = SMBLegacyOpen(xid, tcon, full_path, disposition,
|
||||
desiredAccess, create_options,
|
||||
&fileHandle, &oplock, buf, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
|
@ -225,7 +236,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
|
|||
} else {
|
||||
/* If Open reported that we actually created a file
|
||||
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 = {
|
||||
.mode = mode,
|
||||
.ctime = NO_CHANGE_64,
|
||||
|
@ -244,20 +255,20 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
|
|||
args.uid = 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->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
} else {
|
||||
/* BB implement mode setting via Windows security
|
||||
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 */
|
||||
}
|
||||
|
||||
/* 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,
|
||||
inode->i_sb, xid);
|
||||
else {
|
||||
|
@ -283,22 +294,17 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
|
|||
}
|
||||
|
||||
if (rc != 0) {
|
||||
cFYI(1,
|
||||
("Create worked but get_inode_info failed rc = %d",
|
||||
rc));
|
||||
} else {
|
||||
if (pTcon->nocase)
|
||||
direntry->d_op = &cifs_ci_dentry_ops;
|
||||
else
|
||||
direntry->d_op = &cifs_dentry_ops;
|
||||
d_instantiate(direntry, newinode);
|
||||
}
|
||||
cFYI(1, ("Create worked, get_inode_info failed rc = %d",
|
||||
rc));
|
||||
} else
|
||||
setup_cifs_dentry(tcon, direntry, newinode);
|
||||
|
||||
if ((nd == NULL /* nfsd case - nfs srv does not set nd */) ||
|
||||
(!(nd->flags & LOOKUP_OPEN))) {
|
||||
/* mknod case - do not leave file open */
|
||||
CIFSSMBClose(xid, pTcon, fileHandle);
|
||||
CIFSSMBClose(xid, tcon, fileHandle);
|
||||
} else if (newinode) {
|
||||
pCifsFile =
|
||||
struct cifsFileInfo *pCifsFile =
|
||||
kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
|
||||
|
||||
if (pCifsFile == NULL)
|
||||
|
@ -316,7 +322,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
|
|||
/* set the following in open now
|
||||
pCifsFile->pfile = file; */
|
||||
write_lock(&GlobalSMBSeslock);
|
||||
list_add(&pCifsFile->tlist, &pTcon->openFileList);
|
||||
list_add(&pCifsFile->tlist, &tcon->openFileList);
|
||||
pCifsInode = CIFS_I(newinode);
|
||||
if (pCifsInode) {
|
||||
/* if readable file instance put first in list*/
|
||||
|
|
|
@ -1285,6 +1285,11 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
|
|||
cifsInode = CIFS_I(direntry->d_inode);
|
||||
cifsInode->time = 0; /* force revalidate to go get info when
|
||||
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 =
|
||||
current_fs_time(inode->i_sb);
|
||||
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
* with every copy.
|
||||
*
|
||||
* To compute the message digest of a chunk of bytes, declare an
|
||||
* MD5Context structure, pass it to MD5Init, call MD5Update as
|
||||
* needed on buffers full of bytes, and then call MD5Final, which
|
||||
* MD5Context structure, pass it to cifs_MD5_init, call cifs_MD5_update as
|
||||
* needed on buffers full of bytes, and then call cifs_MD5_final, which
|
||||
* will fill a supplied 16-byte array with the digest.
|
||||
*/
|
||||
|
||||
|
@ -45,7 +45,7 @@ byteReverse(unsigned char *buf, unsigned longs)
|
|||
* initialization constants.
|
||||
*/
|
||||
void
|
||||
MD5Init(struct MD5Context *ctx)
|
||||
cifs_MD5_init(struct MD5Context *ctx)
|
||||
{
|
||||
ctx->buf[0] = 0x67452301;
|
||||
ctx->buf[1] = 0xefcdab89;
|
||||
|
@ -61,7 +61,7 @@ MD5Init(struct MD5Context *ctx)
|
|||
* of bytes.
|
||||
*/
|
||||
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;
|
||||
|
||||
|
@ -110,7 +110,7 @@ MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
|
|||
* 1 0* (64-bit count of bits processed, MSB-first)
|
||||
*/
|
||||
void
|
||||
MD5Final(unsigned char digest[16], struct MD5Context *ctx)
|
||||
cifs_MD5_final(unsigned char digest[16], struct MD5Context *ctx)
|
||||
{
|
||||
unsigned int count;
|
||||
unsigned char *p;
|
||||
|
@ -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
|
||||
* 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.
|
||||
*/
|
||||
static void
|
||||
|
@ -267,9 +267,9 @@ hmac_md5_init_rfc2104(unsigned char *key, int key_len,
|
|||
unsigned char tk[16];
|
||||
struct MD5Context tctx;
|
||||
|
||||
MD5Init(&tctx);
|
||||
MD5Update(&tctx, key, key_len);
|
||||
MD5Final(tk, &tctx);
|
||||
cifs_MD5_init(&tctx);
|
||||
cifs_MD5_update(&tctx, key, key_len);
|
||||
cifs_MD5_final(tk, &tctx);
|
||||
|
||||
key = tk;
|
||||
key_len = 16;
|
||||
|
@ -287,8 +287,8 @@ hmac_md5_init_rfc2104(unsigned char *key, int key_len,
|
|||
ctx->k_opad[i] ^= 0x5c;
|
||||
}
|
||||
|
||||
MD5Init(&ctx->ctx);
|
||||
MD5Update(&ctx->ctx, ctx->k_ipad, 64);
|
||||
cifs_MD5_init(&ctx->ctx);
|
||||
cifs_MD5_update(&ctx->ctx, ctx->k_ipad, 64);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -317,8 +317,8 @@ hmac_md5_init_limK_to_64(const unsigned char *key, int key_len,
|
|||
ctx->k_opad[i] ^= 0x5c;
|
||||
}
|
||||
|
||||
MD5Init(&ctx->ctx);
|
||||
MD5Update(&ctx->ctx, ctx->k_ipad, 64);
|
||||
cifs_MD5_init(&ctx->ctx);
|
||||
cifs_MD5_update(&ctx->ctx, ctx->k_ipad, 64);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -328,7 +328,7 @@ void
|
|||
hmac_md5_update(const unsigned char *text, int text_len,
|
||||
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)
|
|||
{
|
||||
struct MD5Context ctx_o;
|
||||
|
||||
MD5Final(digest, &ctx->ctx);
|
||||
cifs_MD5_final(digest, &ctx->ctx);
|
||||
|
||||
MD5Init(&ctx_o);
|
||||
MD5Update(&ctx_o, ctx->k_opad, 64);
|
||||
MD5Update(&ctx_o, digest, 16);
|
||||
MD5Final(digest, &ctx_o);
|
||||
cifs_MD5_init(&ctx_o);
|
||||
cifs_MD5_update(&ctx_o, ctx->k_opad, 64);
|
||||
cifs_MD5_update(&ctx_o, digest, 16);
|
||||
cifs_MD5_final(digest, &ctx_o);
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
|
|
|
@ -20,10 +20,10 @@ struct HMACMD5Context {
|
|||
};
|
||||
#endif /* _HMAC_MD5_H */
|
||||
|
||||
void MD5Init(struct MD5Context *context);
|
||||
void MD5Update(struct MD5Context *context, unsigned char const *buf,
|
||||
void cifs_MD5_init(struct MD5Context *context);
|
||||
void cifs_MD5_update(struct MD5Context *context, unsigned char const *buf,
|
||||
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 */
|
||||
|
||||
|
|
|
@ -154,81 +154,8 @@ void DeleteTconOplockQEntries(struct cifsTconInfo *tcon)
|
|||
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
|
||||
smb_send2(struct TCP_Server_Info *server, struct kvec *iov, int n_vec,
|
||||
struct sockaddr *sin, bool noblocksnd)
|
||||
smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
|
||||
{
|
||||
int rc = 0;
|
||||
int i = 0;
|
||||
|
@ -243,11 +170,11 @@ smb_send2(struct TCP_Server_Info *server, struct kvec *iov, int n_vec,
|
|||
if (ssocket == NULL)
|
||||
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_control = NULL;
|
||||
smb_msg.msg_controllen = 0;
|
||||
if (noblocksnd)
|
||||
if (server->noblocksnd)
|
||||
smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL;
|
||||
else
|
||||
smb_msg.msg_flags = MSG_NOSIGNAL;
|
||||
|
@ -272,7 +199,25 @@ smb_send2(struct TCP_Server_Info *server, struct kvec *iov, int n_vec,
|
|||
n_vec - first_vec, total_len);
|
||||
if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
|
||||
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,
|
||||
("sends on sock %p stuck for 15 seconds",
|
||||
ssocket));
|
||||
|
@ -339,6 +284,18 @@ smb_send2(struct TCP_Server_Info *server, struct kvec *iov, int n_vec,
|
|||
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)
|
||||
{
|
||||
if (long_op == CIFS_ASYNC_OP) {
|
||||
|
@ -540,9 +497,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
|||
#ifdef CONFIG_CIFS_STATS2
|
||||
atomic_inc(&ses->server->inSend);
|
||||
#endif
|
||||
rc = smb_send2(ses->server, iov, n_vec,
|
||||
(struct sockaddr *) &(ses->server->addr.sockAddr),
|
||||
ses->server->noblocksnd);
|
||||
rc = smb_sendv(ses->server, iov, n_vec);
|
||||
#ifdef CONFIG_CIFS_STATS2
|
||||
atomic_dec(&ses->server->inSend);
|
||||
midQ->when_sent = jiffies;
|
||||
|
@ -736,9 +691,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
|
|||
#ifdef CONFIG_CIFS_STATS2
|
||||
atomic_inc(&ses->server->inSend);
|
||||
#endif
|
||||
rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
|
||||
(struct sockaddr *) &(ses->server->addr.sockAddr),
|
||||
ses->server->noblocksnd);
|
||||
rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
|
||||
#ifdef CONFIG_CIFS_STATS2
|
||||
atomic_dec(&ses->server->inSend);
|
||||
midQ->when_sent = jiffies;
|
||||
|
@ -879,9 +832,7 @@ send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf,
|
|||
mutex_unlock(&ses->server->srv_mutex);
|
||||
return rc;
|
||||
}
|
||||
rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
|
||||
(struct sockaddr *) &(ses->server->addr.sockAddr),
|
||||
ses->server->noblocksnd);
|
||||
rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
|
||||
mutex_unlock(&ses->server->srv_mutex);
|
||||
return rc;
|
||||
}
|
||||
|
@ -973,9 +924,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
|
|||
#ifdef CONFIG_CIFS_STATS2
|
||||
atomic_inc(&ses->server->inSend);
|
||||
#endif
|
||||
rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
|
||||
(struct sockaddr *) &(ses->server->addr.sockAddr),
|
||||
ses->server->noblocksnd);
|
||||
rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
|
||||
#ifdef CONFIG_CIFS_STATS2
|
||||
atomic_dec(&ses->server->inSend);
|
||||
midQ->when_sent = jiffies;
|
||||
|
|
Loading…
Reference in a new issue