Commit b668ec86 authored by Steve French's avatar Steve French

Merge in fixes from version 0.6.5 of the CIFS VFS. Greatly improved...

Merge in fixes from version 0.6.5 of the CIFS VFS.  Greatly improved performance including improved distributed caching support and support for readpages and larger read sizes. Cache data now flushed properly at file close time. Socket and memory leak fixed.  Fix two oops. Fix error logging and made more consistent.  Generic sendfile added.
parent 15f1049d
Version 0.65
------------
Finish fixes to commit write for caching/readahead consistency. fsx
now works to Samba servers. Fix oops caused when readahead
was interrupted by a signal.
Version 0.64
------------
Fix data corruption (in partial page after truncate) that caused fsx to
fail to Windows servers. Cleaned up some extraneous error logging in
common error paths. Add generic sendfile support.
Version 0.63
------------
Fix memory leak in AllocMidQEntry.
Finish reconnection logic, so connection with server can be dropped
(or server rebooted) and the cifs client will reconnect.
Version 0.62
------------
Fix temporary socket leak when bad userid or password specified
(or other SMBSessSetup failure). Increase maximum buffer size to slightly
over 16K to allow negotiation of up to Samba and Windows server default read
sizes. Add support for readpages
Version 0.61
------------
Fix oops when username not passed in on mount. Extensive fixes and improvements
to error logging (strip redundant newlines, change debug macros to ensure newline
passed in and to be more consistent). Fix writepage wrong file handle problem,
a readonly file handle could be incorrectly used to attempt to write out
file updates through the page cache to multiply open files. This could cause
the iozone benchmark to fail on the fwrite test. Fix bug mounting two different
shares to the same Windows server when using different usernames
(doing this to Samba servers worked but Windows was rejecting it) - now it is
possible to use different userids when connecting to the same server from a
Linux client. Fix oops when treeDisconnect called during unmount on
previously freed socket.
Version 0.60
------------
Fix oops in readpages caused by not setting address space operations in inode in
......
version 0.5.3 October 8th, 2002
version 0.6.5 February 15, 2003
A Partial List of Known Problems and Missing Features
=====================================================
......@@ -7,7 +7,8 @@ Contributions are welcome. There are plenty of opportunities
for visible, important contributions to this module. Here
is a partial list of the known problems and missing features:
a) Support for SecurityDescriptors for chmod/chgrp/chown
a) Support for SecurityDescriptors for chmod/chgrp/chown so
these can be supported for Windows servers
b) Better pam/winbind integration
......@@ -16,9 +17,9 @@ c) multi-user mounts - multiplexed sessionsetups over single vc
d) Kerberos/SPNEGO session setup support - (started)
e)NTLMv2 authentication and MD5-HMAC signing of SMB PDUs - (mostly implemented)
e) NTLMv2 authentication and MD5-HMAC signing SMB PDUs - (mostly implemented)
f) oplock support (ie safe CIFS distributed file caching) is not complete.
f) oplock support (ie safe CIFS distributed file caching) is not quite complete.
In addition Directory entry caching relies on a 1 second timer, rather than
using FindNotify or equivalent. - (started)
......@@ -28,27 +29,34 @@ of recent 2.5 kernel improvements in byte-range locking
h) quota support
i) support for the Linux 2.5 kernel new feature get_xattr and set_xattr
which will allow us to expose dos attributes as well as real
ACLs
j) finish off the mount helper, mount.cifs - (started)
KNOWN BUGS (updated October 8nd, 2002)
k) finish writepages support (multi-page write behind for improved
performance) and syncpage
l) hook lower into the sockets api (as NFS/SunRPC does) to avoid the
extra copy in/out of the socket buffers in some cases.
m) finish support for IPv6
KNOWN BUGS (updated February 15, 2003)
====================================
1) symbolic links (Windows reparse points) are recognized but
1) existing symbolic links (Windows reparse points) are recognized but
can not be created remotely. They are implemented for Samba and those that
support the CIFS Unix extensions but Samba has a bug currently handling
symlink text beginning with slash
2) delete of file with read-only attribute set will fail (may be ok)
3) autoreconnection logic is only partially complete.
4) there may be a problem with truncating a memmapped file to smaller than 4k with
the size being reported as exactly 4k.
Misc testing to do
=================
1) check out max path names and max path name components against various server
types.
2) Run POSIX bencharks against cifs
2) Run dbench
3) Run dbench
3) Finish FSX testing on SMP now that we workaround the Samba bug
4) Finish FSX testing on SMP now that we workaround the Samba bug
4) Additional performance testing and optimization
......@@ -458,16 +458,18 @@ decode_negTokenInit(unsigned char *security_blob, int length,
unsigned int cls, con, tag, oidlen, rc;
int use_ntlmssp = FALSE;
*secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default */
/* cifs_dump_mem(" Received SecBlob ", security_blob, length); */
asn1_open(&ctx, security_blob, length);
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1, ("\nError decoding negTokenInit header "));
cFYI(1, ("Error decoding negTokenInit header "));
return 0;
} else if ((cls != ASN1_APL) || (con != ASN1_CON)
|| (tag != ASN1_EOC)) {
cFYI(1, ("\ncls = %d con = %d tag = %d", cls, con, tag));
cFYI(1, ("cls = %d con = %d tag = %d", cls, con, tag));
return 0;
} else {
/* remember to free obj->oid */
......@@ -486,51 +488,49 @@ decode_negTokenInit(unsigned char *security_blob, int length,
}
if (!rc) {
cFYI(1, ("\nError decoding negTokenInit header"));
cFYI(1, ("Error decoding negTokenInit header"));
return 0;
}
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1, ("\nError decoding negTokenInit "));
cFYI(1, ("Error decoding negTokenInit "));
return 0;
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)
|| (tag != ASN1_EOC)) {
cFYI(1,
("\ncls = %d con = %d tag = %d end = %p (%d) exit 0",
cFYI(1,("cls = %d con = %d tag = %d end = %p (%d) exit 0",
cls, con, tag, end, *end));
return 0;
}
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1, ("\nError decoding negTokenInit "));
cFYI(1, ("Error decoding negTokenInit "));
return 0;
} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
|| (tag != ASN1_SEQ)) {
cFYI(1,
("\ncls = %d con = %d tag = %d end = %p (%d) exit 1",
cFYI(1,("cls = %d con = %d tag = %d end = %p (%d) exit 1",
cls, con, tag, end, *end));
return 0;
}
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1, ("\nError decoding 2nd part of negTokenInit "));
cFYI(1, ("Error decoding 2nd part of negTokenInit "));
return 0;
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)
|| (tag != ASN1_EOC)) {
cFYI(1,
("\ncls = %d con = %d tag = %d end = %p (%d) exit 0",
("cls = %d con = %d tag = %d end = %p (%d) exit 0",
cls, con, tag, end, *end));
return 0;
}
if (asn1_header_decode
(&ctx, &sequence_end, &cls, &con, &tag) == 0) {
cFYI(1, ("\nError decoding 2nd part of negTokenInit "));
cFYI(1, ("Error decoding 2nd part of negTokenInit "));
return 0;
} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
|| (tag != ASN1_SEQ)) {
cFYI(1,
("\ncls = %d con = %d tag = %d end = %p (%d) exit 1",
("cls = %d con = %d tag = %d end = %p (%d) exit 1",
cls, con, tag, end, *end));
return 0;
}
......@@ -539,13 +539,13 @@ decode_negTokenInit(unsigned char *security_blob, int length,
rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
if (!rc) {
cFYI(1,
("\nError 1 decoding negTokenInit header exit 2"));
("Error 1 decoding negTokenInit header exit 2"));
return 0;
}
if ((tag == ASN1_OJI) && (con == ASN1_PRI)) {
asn1_oid_decode(&ctx, end, &oid, &oidlen);
cFYI(1,
("\nOID len = %d oid = 0x%lx 0x%lx 0x%lx 0x%lx",
("OID len = %d oid = 0x%lx 0x%lx 0x%lx 0x%lx",
oidlen, *oid, *(oid + 1), *(oid + 2),
*(oid + 3)));
rc = compare_oid(oid, oidlen, NTLMSSP_OID,
......@@ -554,54 +554,53 @@ decode_negTokenInit(unsigned char *security_blob, int length,
if (rc)
use_ntlmssp = TRUE;
} else {
cFYI(1,
("\nThis should be an oid what is going on? "));
cFYI(1,("This should be an oid what is going on? "));
}
}
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1,
("\nError decoding last part of negTokenInit exit 3"));
("Error decoding last part of negTokenInit exit 3"));
return 0;
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { /* tag = 3 indicating mechListMIC */
cFYI(1,
("\nExit 4 cls = %d con = %d tag = %d end = %p (%d)",
("Exit 4 cls = %d con = %d tag = %d end = %p (%d)",
cls, con, tag, end, *end));
return 0;
}
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1,
("\nError decoding last part of negTokenInit exit 5"));
("Error decoding last part of negTokenInit exit 5"));
return 0;
} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
|| (tag != ASN1_SEQ)) {
cFYI(1,
("\nExit 6 cls = %d con = %d tag = %d end = %p (%d)",
("Exit 6 cls = %d con = %d tag = %d end = %p (%d)",
cls, con, tag, end, *end));
}
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1,
("\nError decoding last part of negTokenInit exit 7"));
("Error decoding last part of negTokenInit exit 7"));
return 0;
} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
cFYI(1,
("\nExit 8 cls = %d con = %d tag = %d end = %p (%d)",
("Exit 8 cls = %d con = %d tag = %d end = %p (%d)",
cls, con, tag, end, *end));
return 0;
}
if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
cFYI(1,
("\nError decoding last part of negTokenInit exit 9"));
("Error decoding last part of negTokenInit exit 9"));
return 0;
} else if ((cls != ASN1_UNI) || (con != ASN1_PRI)
|| (tag != ASN1_GENSTR)) {
cFYI(1,
("\nExit 10 cls = %d con = %d tag = %d end = %p (%d)",
("Exit 10 cls = %d con = %d tag = %d end = %p (%d)",
cls, con, tag, end, *end));
return 0;
}
cFYI(1, ("\nNeed to call asn1_octets_decode() function for this %s", ctx.pointer)); /* is this UTF-8 or ASCII? */
cFYI(1, ("Need to call asn1_octets_decode() function for this %s", ctx.pointer)); /* is this UTF-8 or ASCII? */
}
/* if (use_kerberos)
......
......@@ -39,7 +39,8 @@ cifs_dump_mem(char *label, void *data, int length)
char *charptr = data;
char buf[10], line[80];
printk("%s: dump of %d bytes of data at 0x%p\n\n", label, length, data);
printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n\n",
label, length, data);
for (i = 0; i < length; i += 16) {
line[0] = 0;
for (j = 0; (j < 4) && (i + j * 4 < length); j++) {
......@@ -52,7 +53,7 @@ cifs_dump_mem(char *label, void *data, int length)
buf[1] = isprint(charptr[i + j]) ? charptr[i + j] : '.';
strcat(line, buf);
}
printk("%s\n", line);
printk(KERN_DEBUG "%s\n", line);
}
}
......@@ -68,7 +69,6 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
int length = 0;
char *buf_start = buf;
printk("\n\nEntering cifs_debug_data_read: buf=0x%p, beginBuffer=0x%p, offset=%ld, count=%d, eof=%d, data=0x%p\n", buf, *beginBuffer, offset, count, *eof, data); /* BB remove */
length =
sprintf(buf,
"Display Internal CIFS Data Structures for Debugging\n"
......@@ -85,17 +85,17 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
length =
sprintf(buf,
"\n%d) Name: %s Domain: %s HowManyMounts: %d ServerOS: %s ServerNOS: %s\n\tCapabilities: 0x%x",
"\n%d) Name: %s Domain: %s Mounts: %d ServerOS: %s ServerNOS: %s\n\tCapabilities: 0x%x",
i, ses->serverName, ses->serverDomain, atomic_read(&ses->inUse),
ses->serverOS, ses->serverNOS, ses->capabilities);
buf += length;
if(ses->server)
buf += sprintf(buf, "\tLocal Users To Same Server: %d ",atomic_read(&ses->server->socketUseCount));
buf += sprintf(buf, "\tLocal Users To Same Server: %d ",
atomic_read(&ses->server->socketUseCount));
}
read_unlock(&GlobalSMBSeslock);
sprintf(buf, "\n");
buf++;
printk("\nTotal Buffer so far: %s\n", buf_start);
length = sprintf(buf, "\nShares: \n");
buf += length;
......@@ -107,7 +107,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
length =
sprintf(buf,
"\n%d) %s UseCount: %d on FS: %s with characteristics: 0x%x Attributes: 0x%x\n\tPathComponentLengthMax: %d",
"\n%d) %s Uses: %d on FS: %s with characteristics: 0x%x Attributes: 0x%x\n\tPathComponentMax: %d",
i, tcon->treeName,
atomic_read(&tcon->useCount),
tcon->nativeFileSystem,
......
......@@ -33,29 +33,35 @@ void dump_smb(struct smb_hdr *, int);
*/
#ifdef CIFS_DEBUG
/* information message: e.g., configuration, major event */
extern int cifsFYI;
#define cFYI(button,prspec)\
{ if (button && cifsFYI) printk prspec; }
#define cifsfyi(format,arg...) if (cifsFYI) printk(KERN_DEBUG " " __FILE__ ": " format "\n" "" , ## arg)
#define cFYI(button,prspec) if (button) cifsfyi prspec
#define cifswarn(format, arg...) printk(KERN_WARNING ": " format "\n" , ## arg)
/* debug event message: */
#define cEVENT(button,prspec)\
{ if (button) printk prspec; }
extern int cifsERROR;
#define cEVENT(format,arg...) if (cifsERROR) printk(KERN_EVENT __FILE__ ": " format "\n" , ## arg)
/* error event message: e.g., i/o error */
extern int cifsERROR;
#define cERROR(button, prspec)\
{ if (button && cifsERROR) { printk prspec; if (button > 1) BUG(); } }
#define cifserror(format,arg...) if (cifsERROR) printk(KERN_ERR " CIFS VFS: " format "\n" "" , ## arg)
#define cERROR(button, prspec) if (button) cifserror prspec
/*
* debug OFF
* ---------
*/
#else /* _CIFS_DEBUG */
#else /* _CIFS_DEBUG */
#define cERROR(button,prspec)
#define cEVENT(button,prspec)
#define cEVENT(format,arg...)
#define cFYI(button, prspec)
#endif /* _CIFS_DEBUG */
#define cifserror(format,arg...)
#endif /* _CIFS_DEBUG */
/*
* statistics
......
......@@ -69,7 +69,6 @@ cifs_strfromUCS_le(char *to, const wchar_t * from, /* LITTLE ENDIAN */
}
}
to[outlen] = 0;
cEVENT(0, ("cifs_strfromUCS returning %d - '%s'\n", outlen, to));
return outlen;
}
......@@ -86,15 +85,13 @@ cifs_strtoUCS(wchar_t * to, const char *from, int len,
int charlen;
int i;
cEVENT(0, ("cifs_strtoUCS - '%s'\n", from));
for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
/* works for 2.4.0 kernel or later */
charlen = codepage->char2uni(from, len, &to[i]);
if (charlen < 1) {
cERROR(1,
("cifs_strtoUCS: char2uni returned %d.\n",
("cifs_strtoUCS: char2uni returned %d",
charlen));
to[i] = cpu_to_le16(0x003f); /* a question mark */
charlen = 1;
......@@ -103,8 +100,6 @@ cifs_strtoUCS(wchar_t * to, const char *from, int len,
}
cEVENT(0, (" returning %d\n", i));
to[i] = 0;
return i;
}
......
......@@ -71,12 +71,13 @@ cifs_read_super(struct super_block *sb, void *data, char *devname, int silent)
if(cifs_sb == NULL)
return -ENOMEM;
cifs_sb->local_nls = load_nls_default(); /* needed for ASCII cp to Unicode converts */
rc = cifs_mount(sb, cifs_sb, data, devname);
if (rc) {
if (!silent)
cERROR(1,
("cifs_mount failed w/return code = %d\n", rc));
("cifs_mount failed w/return code = %d", rc));
goto out_mount_failed;
}
......@@ -97,13 +98,10 @@ cifs_read_super(struct super_block *sb, void *data, char *devname, int silent)
return 0;
out_no_root:
cEVENT(1, ("cifs_read_super: get root inode failed\n"));
cERROR(1, ("cifs_read_super: get root inode failed"));
if (inode)
iput(inode);
if (rc) {
cERROR(1, ("cifs_mount failed with no root inode"));
}
out_mount_failed:
if(cifs_sb)
kfree(cifs_sb);
......@@ -116,15 +114,15 @@ cifs_put_super(struct super_block *sb)
int rc = 0;
struct cifs_sb_info *cifs_sb;
cFYI(1, ("In cifs_put_super\n"));
cFYI(1, ("In cifs_put_super"));
cifs_sb = CIFS_SB(sb);
if(cifs_sb == NULL) {
cFYI(1,("\nEmpty cifs superblock info passed to unmount"));
cFYI(1,("Empty cifs superblock info passed to unmount"));
return;
}
rc = cifs_umount(sb, cifs_sb);
if (rc) {
cERROR(1, ("cifs_umount failed with return code %d\n", rc));
cERROR(1, ("cifs_umount failed with return code %d", rc));
}
unload_nls(cifs_sb->local_nls);
kfree(cifs_sb);
......@@ -180,7 +178,8 @@ cifs_alloc_inode(struct super_block *sb)
cifs_inode->cifsAttrs = 0x20; /* default */
atomic_set(&cifs_inode->inUse, 0);
cifs_inode->time = 0;
cifs_inode->clientCanCache = 0;
if(oplockEnabled)
cifs_inode->clientCanCacheAll = 1;
INIT_LIST_HEAD(&cifs_inode->openFileList);
return &cifs_inode->vfs_inode;
}
......@@ -236,7 +235,7 @@ cifs_get_sb(struct file_system_type *fs_type,
int rc;
struct super_block *sb = sget(fs_type, NULL, set_anon_super, NULL);
cFYI(1, ("\nDevname: %s flags: %d ", dev_name, flags));
cFYI(1, ("Devname: %s flags: %d ", dev_name, flags));
if (IS_ERR(sb))
return sb;
......@@ -277,8 +276,15 @@ struct inode_operations cifs_dir_inode_ops = {
struct inode_operations cifs_file_inode_ops = {
/* revalidate:cifs_revalidate, */
.setattr = cifs_setattr,
.getattr = cifs_getattr,
.getattr = cifs_getattr, /* do we need this anymore? */
.rename = cifs_rename,
#ifdef CIFS_XATTR
.setxattr = cifs_setxattr,
.getxattr = cifs_getxattr,
.listxattr = cifs_listxattr,
.removexattr = cifs_removexattr,
.permission = cifs_permission,
#endif
};
struct inode_operations cifs_symlink_inode_ops = {
......@@ -287,16 +293,24 @@ struct inode_operations cifs_symlink_inode_ops = {
/* BB add the following two eventually */
/* revalidate: cifs_revalidate,
setattr: cifs_notify_change, *//* BB do we need notify change */
#ifdef CIFS_XATTR
.setxattr = cifs_setxattr,
.getxattr = cifs_getxattr,
.listxattr = cifs_listxattr,
.removexattr = cifs_removexattr,
#endif
};
struct file_operations cifs_file_ops = {
.read = generic_file_read,
.write = generic_file_write,
.write = generic_file_write,
.open = cifs_open,
.release = cifs_close,
.lock = cifs_lock,
.fsync = cifs_fsync,
.flush = cifs_flush,
.mmap = cifs_file_mmap,
.sendfile = generic_file_sendfile,
};
struct file_operations cifs_dir_ops = {
......@@ -333,7 +347,7 @@ void
cifs_destroy_inodecache(void)
{
if (kmem_cache_destroy(cifs_inode_cachep))
printk(KERN_INFO "cifs_inode_cache: error freeing\n");
printk(KERN_WARNING "cifs_inode_cache: error freeing\n");
}
int
......@@ -353,7 +367,7 @@ void
cifs_destroy_request_bufs(void)
{
if (kmem_cache_destroy(cifs_req_cachep))
printk(KERN_INFO
printk(KERN_WARNING
"cifs_destroy_request_cache: error not all structures were freed\n");
}
......@@ -373,7 +387,7 @@ void
cifs_destroy_mids(void)
{
if (kmem_cache_destroy(cifs_mid_cachep))
printk(KERN_INFO
printk(KERN_WARNING
"cifs_destroy_mids: error not all structures were freed\n");
}
......@@ -426,7 +440,7 @@ init_cifs(void)
static void __exit
exit_cifs(void)
{
cFYI(0, ("\nIn unregister ie exit_cifs"));
cFYI(0, ("In unregister ie exit_cifs"));
#if CONFIG_PROC_FS
cifs_proc_clean();
#endif
......
......@@ -74,6 +74,7 @@ extern ssize_t cifs_write(struct file *file, const char *write_data,
size_t write_size, loff_t * poffset);
extern int cifs_lock(struct file *, int, struct file_lock *);
extern int cifs_fsync(struct file *, struct dentry *, int);
extern int cifs_flush(struct file *);
extern int cifs_file_mmap(struct file * , struct vm_area_struct *);
extern struct file_operations cifs_dir_ops;
extern int cifs_dir_open(struct inode *inode, struct file *file);
......
......@@ -27,7 +27,7 @@
#define MAX_TREE_SIZE 2 + MAX_SERVER_SIZE + 1 + MAX_SHARE_SIZE + 1
#define MAX_SERVER_SIZE 15
#define MAX_SHARE_SIZE 64 /* used to be 20 - this should still be enough */
#define MAX_USERNAME_SIZE 32 /* 22 is to allow for 15 char names + null
#define MAX_USERNAME_SIZE 32 /* 32 is to allow for 15 char names + null
termination then *2 for unicode versions */
#define MAX_PASSWORD_SIZE 16
......@@ -109,6 +109,21 @@ struct TCP_Server_Info {
struct semaphore tcpSem;
struct task_struct *tsk;
char server_GUID[16];
char secMode;
enum securityEnum secType;
unsigned int maxReq; /* Clients should submit no more */
/* than maxReq distinct unanswered SMBs to the server when using */
/* multiplexed reads or writes */
unsigned int maxBuf; /* maxBuf specifies the maximum */
/* message size the server can send or receive for non-raw SMBs */
unsigned int maxRw; /* maxRw specifies the maximum */
/* message size the server can send or receive for */
/* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */
char sessid[4]; /* unique token id for this session */
/* (returned on Negotiate */
int capabilities; /* allow selective disabling of caps by smb sess */
__u16 timeZone;
char cryptKey[CIFS_CRYPTO_KEY_SIZE];
};
/*
......@@ -117,12 +132,11 @@ struct TCP_Server_Info {
* has changed. We also hang a list of sessions owned by this user off here.
*/
struct cifsUidInfo {
struct cifsUidInfo *next1; /* BB replace with list and atomicize */
struct cifsSesInfo *ses; /* list of sessions *//* BB replace with list and atomicize */
struct srSesInfo *sesSR; /* Save/Restore session list */
struct list_head userList;
struct list_head sessionList; /* SMB sessions for this user */
uid_t linux_uid;
char user[MAX_USERNAME_SIZE + 1]; /* ascii name of user */
/* BB eventually need ptr into PAM or WinBind info */
/* BB may need ptr or callback for PAM or WinBind info */
};
/*
......@@ -135,28 +149,16 @@ struct cifsSesInfo {
struct TCP_Server_Info *server; /* pointer to server info */
atomic_t inUse; /* # of CURRENT users of this ses */
enum statusEnum status;
int dialectIndex; /* the negotiated dialect index */
char secMode;
enum securityEnum secType;
unsigned int maxReq; /* Clients should submit no more */
/* than maxReq distinct unanswered SMBs to the server when using */
/* multiplexed reads or writes */
unsigned int maxBuf; /* maxBuf specifies the maximum */
/* message size the server can send or receive for non-raw SMBs */
unsigned int maxRw; /* maxRw specifies the maximum */
/* message size the server can send or receive for */
/* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */
char sessid[4]; /* unique token id for this session */
/* (returned on Negotiate */
__u16 ipc_tid; /* special tid for connection to IPC share */
int capabilities;
__u16 timeZone;
char *serverOS; /* name of operating system underlying the server */
char *serverNOS; /* name of network operating system that the server is running */
char *serverDomain; /* security realm of server */
int Suid; /* needed for user level security */
int capabilities;
char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for tcp names - will ipv6 and sctp addresses fit here?? */
char userName[MAX_USERNAME_SIZE + 1]; /* BB remove and replace with list of cifsUidInfo structures */
char userName[MAX_USERNAME_SIZE + 1];
char domainName[MAX_USERNAME_SIZE + 1];
char password_with_pad[CIFS_ENCPWD_SIZE];
};
/*
......@@ -172,6 +174,7 @@ struct cifsTconInfo {
char *nativeFileSystem;
__u16 tid; /* The 2 byte transaction id */
__u16 Flags; /* optional support bits */
enum statusEnum tidStatus;
atomic_t useCount; /* how many mounts (explicit or implicit refer to this share */
FILE_SYSTEM_DEVICE_INFO fsDevInfo;
FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* note file system name may be truncated - but very unlikely */
......@@ -214,11 +217,11 @@ struct cifsInodeInfo {
struct list_head lockList;
/* BB add in lists for dirty pages - i.e. write caching info for oplock */
struct list_head openFileList;
__u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system etc. */
atomic_t inUse; /* num concurrent users (local openers cifs) of file */
__u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */
atomic_t inUse; /* num concurrent users (local openers cifs) of file*/
unsigned long time; /* jiffies of last update/check of inode */
int clientCanCache:1; /* oplocked. We need to extend cases beyond this i.e. what
if file read-only or if file locked? or if file on r/o vol? */
int clientCanCacheRead:1; /* read oplock */
int clientCanCacheAll:1; /* read and writebehind oplock */
struct inode vfs_inode;
};
......
......@@ -79,7 +79,7 @@
/*
* Starting value for maximum SMB size negotiation
*/
#define CIFS_MAX_MSGSIZE (4*1024)
#define CIFS_MAX_MSGSIZE (4*4096)
/*
* Size of encrypted user password in bytes
......
......@@ -36,8 +36,8 @@ extern int smb_send(struct socket *, struct smb_hdr *,
unsigned int /* length */ , struct sockaddr *);
extern unsigned int _GetXid(void);
extern void _FreeXid(unsigned int);
#define GetXid() (int)_GetXid(); cFYI(1,("\nCIFS VFS: in %s as Xid: %d with uid: %d",__FUNCTION__, xid,current->fsuid));
#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("\nCIFS VFS: leaving %s (xid = %d) rc = %d\n",__FUNCTION__,curr_xid,rc));}
#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__FUNCTION__, xid,current->fsuid));
#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__FUNCTION__,curr_xid,rc));}
extern char *build_path_from_dentry(struct dentry *);
extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
extern void renew_parental_timestamps(struct dentry *direntry);
......@@ -72,28 +72,21 @@ extern int cifs_get_inode_info_unix(struct inode **pinode,
const unsigned char *search_path,
struct super_block *sb);
extern int CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses,
char cryptokey[CIFS_CRYPTO_KEY_SIZE]);
extern int setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
struct nls_table * nls_info);
extern int CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses);
extern int CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
char *user, char *domain,
char *session_key, char *ntlm_session_key,
const struct nls_table *);
extern int CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
char *user, char *domain,
char *SecurityBlob,
int SecurityBlobLength,
char *SecurityBlob,int SecurityBlobLength,
const struct nls_table *);
extern int CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
struct cifsSesInfo *ses,
char *domain,
char *ntlm_session_key,
int *ntlmv2_flag,
struct cifsSesInfo *ses, int *ntlmv2_flag,
const struct nls_table *);
extern int CIFSNTLMSSPAuthSessSetup(unsigned int xid,
struct cifsSesInfo *ses, char *user,
char *domain, char *ntlm_session_key,
char *lanman_session_key,
int ntlmv2_flag,
struct cifsSesInfo *ses, char *ntlm_session_key,
char *lanman_session_key,int ntlmv2_flag,
const struct nls_table *);
extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
......@@ -202,7 +195,7 @@ extern int CIFSSMBClose(const int xid, const struct cifsTconInfo *tcon,
extern int CIFSSMBRead(const int xid, const struct cifsTconInfo *tcon,
const int netfid, unsigned int count,
const __u64 lseek, unsigned int *nbytes, char *buf);
const __u64 lseek, unsigned int *nbytes, char **buf);
extern int CIFSSMBWrite(const int xid, const struct cifsTconInfo *tcon,
const int netfid, const unsigned int count,
const __u64 lseek, unsigned int *nbytes,
......
......@@ -49,6 +49,11 @@ smb_init(int smb_command, int wct, const struct cifsTconInfo *tcon,
{
int rc = 0;
if(tcon)
if(tcon->ses)
if(tcon->ses->status == CifsNeedReconnect)
setup_session(0, tcon->ses, load_nls_default());
*request_buf = buf_get();
if (request_buf == 0) {
return -ENOMEM;
......@@ -65,13 +70,20 @@ smb_init(int smb_command, int wct, const struct cifsTconInfo *tcon,
}
int
CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses,
char cryptokey[CIFS_CRYPTO_KEY_SIZE])
CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
{
NEGOTIATE_REQ *pSMB;
NEGOTIATE_RSP *pSMBr;
int rc = 0;
int bytes_returned;
struct TCP_Server_Info * server;
if(ses->server)
server = ses->server;
else {
rc = -EIO;
return rc;
}
rc = smb_init(SMB_COM_NEGOTIATE, 0, 0 /* no tcon yet */ ,
(void **) &pSMB, (void **) &pSMBr);
......@@ -81,9 +93,9 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses,
pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
if (extended_security)
pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
if (sign_CIFS_PDUs) {
pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
}
if (sign_CIFS_PDUs) {
pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
}
pSMB->ByteCount = strlen(protocols[0].name) + 1;
strncpy(pSMB->DialectsArray, protocols[0].name, 30);
......@@ -95,22 +107,22 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses,
rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc == 0) {
ses->dialectIndex = le16_to_cpu(pSMBr->DialectIndex);
ses->secMode = pSMBr->SecurityMode;
server->secMode = pSMBr->SecurityMode;
server->secType = NTLM; /* BB override default for NTLMv2 or krb*/
/* one byte - no need to convert this or EncryptionKeyLen from le,*/
ses->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
/* probably no need to store and check maxvcs */
ses->maxBuf =
server->maxBuf =
min(le32_to_cpu(pSMBr->MaxBufferSize),
(__u32) CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE);
ses->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
cFYI(1, ("\nMax buf = %d ", ses->maxBuf));
GETU32(ses->sessid) = le32_to_cpu(pSMBr->SessionKey);
ses->capabilities = le32_to_cpu(pSMBr->Capabilities);
ses->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
cFYI(0, ("Max buf = %d ", ses->server->maxBuf));
GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
server->capabilities = le32_to_cpu(pSMBr->Capabilities);
server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
/* BB with UTC do we ever need to be using srvr timezone? */
if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
memcpy(cryptokey, pSMBr->u.EncryptionKey,
memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
CIFS_CRYPTO_KEY_SIZE);
} else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
&& (pSMBr->EncryptionKeyLength == 0)) {
......@@ -124,22 +136,22 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses,
if (pSMBr->ByteCount < 16)
rc = -EIO;
else if (pSMBr->ByteCount == 16) {
ses->secType = RawNTLMSSP;
if (ses->server->socketUseCount.counter > 1) {
server->secType = RawNTLMSSP;
if (server->socketUseCount.counter > 1) {
if (memcmp
(ses->server->server_GUID,
pSMBr->u.extended_response.
GUID, 16) != 0) {
(server->server_GUID,
pSMBr->u.extended_response.
GUID, 16) != 0) {
cFYI(1,
("UID of server does not match that of previous connection to same ip address"));
memcpy(ses->server->
server_GUID,
pSMBr->u.
extended_response.
GUID, 16);
("UID of server does not match that of previous connection to same ip address"));
memcpy(server->
server_GUID,
pSMBr->u.
extended_response.
GUID, 16);
}
} else
memcpy(ses->server->server_GUID,
memcpy(server->server_GUID,
pSMBr->u.extended_response.
GUID, 16);
} else {
......@@ -147,16 +159,16 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses,
extended_response.
SecurityBlob,
pSMBr->ByteCount -
16, &ses->secType);
16, &server->secType);
}
} else
ses->capabilities &= ~CAP_EXTENDED_SECURITY;
if(sign_CIFS_PDUs == FALSE) {
if(ses->secMode & SECMODE_SIGN_REQUIRED)
cERROR(1,("\nServer required CIFS packet signing - enable /proc/fs/cifs/PacketSigningEnabled"));
ses->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
}
server->capabilities &= ~CAP_EXTENDED_SECURITY;
if(sign_CIFS_PDUs == FALSE) {
if(server->secMode & SECMODE_SIGN_REQUIRED)
cERROR(1,("Server required CIFS packet signing - enable /proc/fs/cifs/PacketSigningEnabled"));
server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
}
}
if (pSMB)
buf_release(pSMB);
......@@ -171,7 +183,7 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
int rc = 0;
int length;
cFYI(1, ("\nIn tree disconnect"));
cFYI(1, ("In tree disconnect"));
/*
* If last user of the connection and
* connection alive - disconnect it
......@@ -192,6 +204,10 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
/* BB remove (from server) list of shares - but with smp safety BB */
/* BB is ses active - do we need to check here - but how? BB */
if((tcon->ses == 0) || (tcon->ses->server == 0)) {
up(&tcon->tconSem);
return -EIO;
}
rc = smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
(void **) &smb_buffer, (void **) &smb_buffer_response);
......@@ -218,7 +234,7 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
int rc = 0;
int length;
cFYI(1, ("\nIn SMBLogoff for session disconnect"));
cFYI(1, ("In SMBLogoff for session disconnect"));
if (ses)
down(&ses->sesSem); /* need to add more places where this sem is checked */
......@@ -230,7 +246,7 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
up(&ses->sesSem);
return -EBUSY;
}
if(ses->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
rc = smb_init(SMB_COM_LOGOFF_ANDX, 2, 0 /* no tcon anymore */ ,
(void **) &pSMB, (void **) &smb_buffer_response);
......@@ -278,7 +294,6 @@ CIFSSMBDelFile(const int xid, const struct cifsTconInfo *tcon,
name_len++; /* trailing null */
name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */
name_len = strnlen(fileName, 530);
name_len++; /* trailing null */
strncpy(pSMB->fileName, fileName, name_len);
......@@ -292,7 +307,7 @@ CIFSSMBDelFile(const int xid, const struct cifsTconInfo *tcon,
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cERROR(1, ("\nSend error in RMFile = %d\n", rc));
cFYI(1, ("Error in RMFile = %d", rc));
}
if (pSMB)
buf_release(pSMB);
......@@ -309,7 +324,7 @@ CIFSSMBRmDir(const int xid, const struct cifsTconInfo *tcon,
int bytes_returned;
int name_len;
cFYI(1, ("\nIn CIFSSMBRmDir"));
cFYI(1, ("In CIFSSMBRmDir"));
rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
(void **) &pSMBr);
......@@ -323,7 +338,6 @@ CIFSSMBRmDir(const int xid, const struct cifsTconInfo *tcon,
name_len++; /* trailing null */
name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */
name_len = strnlen(dirName, 530);
name_len++; /* trailing null */
strncpy(pSMB->DirName, dirName, name_len);
......@@ -336,7 +350,7 @@ CIFSSMBRmDir(const int xid, const struct cifsTconInfo *tcon,
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cERROR(1, ("\nSend error in RMDir = %d\n", rc));
cFYI(1, ("Error in RMDir = %d", rc));
}
if (pSMB)
buf_release(pSMB);
......@@ -353,7 +367,7 @@ CIFSSMBMkDir(const int xid, const struct cifsTconInfo *tcon,
int bytes_returned;
int name_len;
cFYI(1, ("\nIn CIFSSMBMkDir"));
cFYI(1, ("In CIFSSMBMkDir"));
rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
(void **) &pSMBr);
......@@ -367,7 +381,6 @@ CIFSSMBMkDir(const int xid, const struct cifsTconInfo *tcon,
name_len++; /* trailing null */
name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */
name_len = strnlen(name, 530);
name_len++; /* trailing null */
strncpy(pSMB->DirName, name, name_len);
......@@ -380,7 +393,7 @@ CIFSSMBMkDir(const int xid, const struct cifsTconInfo *tcon,
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cERROR(1, ("\nSend error in RMDir = %d\n", rc));
cFYI(1, ("Error in Mkdir = %d", rc));
}
if (pSMB)
buf_release(pSMB);
......@@ -418,15 +431,17 @@ CIFSSMBOpen(const int xid, const struct cifsTconInfo *tcon,
name_len *= 2;
pSMB->NameLength = cpu_to_le16(name_len);
} else { /* BB improve the check for buffer overruns BB */
pSMB->ByteCount = 0; /* no pad */
name_len = strnlen(fileName, 530);
name_len++; /* trailing null */
pSMB->NameLength = cpu_to_le16(name_len);
strncpy(pSMB->fileName, fileName, name_len);
}
if (*pOplock)
if (*pOplock & REQ_OPLOCK)
pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
else if (*pOplock & REQ_BATCHOPLOCK) {
pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
}
pSMB->DesiredAccess = cpu_to_le32(access_flags);
pSMB->AllocationSize = 0;
pSMB->FileAttributes = ATTR_NORMAL; /* XP does not handle ATTR_POSIX_SEMANTICS */
......@@ -449,7 +464,7 @@ CIFSSMBOpen(const int xid, const struct cifsTconInfo *tcon,
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cERROR(1, ("\nSend error in Open = %d\n", rc));
cFYI(1, ("Error in Open = %d", rc));
} else {
*pOplock = pSMBr->OplockLevel; /* one byte no need to le_to_cpu */
*netfid = pSMBr->Fid; /* cifs fid stays in le */
......@@ -463,17 +478,22 @@ CIFSSMBOpen(const int xid, const struct cifsTconInfo *tcon,
return rc;
}
/* If no buffer passed in, then caller wants to do the copy
as in the case of readpages so the SMB buffer must be
freed by the caller */
int
CIFSSMBRead(const int xid, const struct cifsTconInfo *tcon,
const int netfid, const unsigned int count,
const __u64 lseek, unsigned int *nbytes, char *buf)
const __u64 lseek, unsigned int *nbytes, char **buf)
{
int rc = -EACCES;
READ_REQ *pSMB = NULL;
READ_RSP *pSMBr = NULL;
char *pReadData;
char *pReadData = NULL;
int bytes_returned;
*nbytes = 0;
rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB,
(void **) &pSMBr);
if (rc)
......@@ -485,7 +505,7 @@ CIFSSMBRead(const int xid, const struct cifsTconInfo *tcon,
pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
pSMB->Remaining = 0;
pSMB->MaxCount = cpu_to_le16(min(count,
(tcon->ses->maxBuf -
(tcon->ses->server->maxBuf -
MAX_CIFS_HDR_SIZE) & 0xFFFFFF00));
pSMB->MaxCountHigh = 0;
pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */
......@@ -493,14 +513,14 @@ CIFSSMBRead(const int xid, const struct cifsTconInfo *tcon,
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cERROR(1, ("\nSend error in read = %d\n", rc));
*nbytes = 0;
cERROR(1, ("Send error in read = %d", rc));
} else {
pSMBr->DataLength = le16_to_cpu(pSMBr->DataLength);
*nbytes = pSMBr->DataLength;
/*check that DataLength would not go beyond end of SMB */
if ((pSMBr->DataLength > CIFS_MAX_MSGSIZE)
|| (pSMBr->DataLength > count)) {
cFYI(1,("bad length %d for count %d",pSMBr->DataLength,count));
rc = -EIO;
*nbytes = 0;
} else {
......@@ -508,16 +528,19 @@ CIFSSMBRead(const int xid, const struct cifsTconInfo *tcon,
(char *) (&pSMBr->hdr.Protocol) +
le16_to_cpu(pSMBr->DataOffset);
/* if(rc = copy_to_user(buf, pReadData, pSMBr->DataLength)) {
cERROR(1,("\nFaulting on read rc = %d",rc));
cERROR(1,("Faulting on read rc = %d",rc));
rc = -EFAULT;
}*/ /* can not use copy_to_user when using page cache*/
memcpy(buf,pReadData,pSMBr->DataLength);
if(*buf)
memcpy(*buf,pReadData,pSMBr->DataLength);
}
}
if (pSMB)
buf_release(pSMB);
if (pSMB) {
if(*buf)
buf_release(pSMB);
else
*buf = (char *)pSMB;
}
return rc;
}
......@@ -542,9 +565,9 @@ CIFSSMBWrite(const int xid, const struct cifsTconInfo *tcon,
pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
pSMB->Remaining = 0;
if (count > ((tcon->ses->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00))
if (count > ((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00))
pSMB->DataLengthLow =
(tcon->ses->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00;
(tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00;
else
pSMB->DataLengthLow = count;
pSMB->DataLengthHigh = 0;
......@@ -561,7 +584,7 @@ CIFSSMBWrite(const int xid, const struct cifsTconInfo *tcon,
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, long_op);
if (rc) {
cERROR(1, ("\nSend error in write = %d\n", rc));
cERROR(1, ("Send error in write = %d", rc));
*nbytes = 0;
} else
*nbytes = le16_to_cpu(pSMBr->Count);
......@@ -583,7 +606,7 @@ CIFSSMBLock(const int xid, const struct cifsTconInfo *tcon,
LOCK_RSP *pSMBr = NULL;
int bytes_returned;
cFYI(1, ("\nIn CIFSSMBLock"));
cFYI(1, ("In CIFSSMBLock"));
rc = smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB,
(void **) &pSMBr);
......@@ -607,7 +630,7 @@ CIFSSMBLock(const int xid, const struct cifsTconInfo *tcon,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cERROR(1, ("\nSend error in Lock = %d\n", rc));
cERROR(1, ("Send error in Lock = %d", rc));
}
if (pSMB)
buf_release(pSMB);
......@@ -622,7 +645,7 @@ CIFSSMBClose(const int xid, const struct cifsTconInfo *tcon, int smb_file_id)
CLOSE_REQ *pSMB = NULL;
CLOSE_RSP *pSMBr = NULL;
int bytes_returned;
cFYI(1, ("\nIn CIFSSMBClose"));
cFYI(1, ("In CIFSSMBClose"));
rc = smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB,
(void **) &pSMBr);
......@@ -635,7 +658,7 @@ CIFSSMBClose(const int xid, const struct cifsTconInfo *tcon, int smb_file_id)
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cERROR(1, ("\nSend error in Close = %d\n", rc));
cERROR(1, ("Send error in Close = %d", rc));
}
if (pSMB)
buf_release(pSMB);
......@@ -654,7 +677,7 @@ CIFSSMBRename(const int xid, const struct cifsTconInfo *tcon,
int bytes_returned;
int name_len, name_len2;
cFYI(1, ("\nIn CIFSSMBRename"));
cFYI(1, ("In CIFSSMBRename"));
rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
(void **) &pSMBr);
......@@ -682,7 +705,6 @@ CIFSSMBRename(const int xid, const struct cifsTconInfo *tcon,
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
name_len2 *= 2; /* convert to bytes */
} else { /* BB improve the check for buffer overruns BB */
name_len = strnlen(fromName, 530);
name_len++; /* trailing null */
strncpy(pSMB->OldFileName, fromName, name_len);
......@@ -702,7 +724,7 @@ CIFSSMBRename(const int xid, const struct cifsTconInfo *tcon,
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cFYI(1, ("\nSend error in RMDir = %d\n", rc));
cFYI(1, ("Send error in RMDir = %d", rc));
}
if (pSMB)
buf_release(pSMB);
......@@ -723,7 +745,7 @@ CIFSUnixCreateSymLink(const int xid, const struct cifsTconInfo *tcon,
int rc = 0;
int bytes_returned = 0;
cFYI(1, ("\nIn Symlink Unix style"));
cFYI(1, ("In Symlink Unix style"));
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
......@@ -788,7 +810,7 @@ CIFSUnixCreateSymLink(const int xid, const struct cifsTconInfo *tcon,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cFYI(1,
("\nSend error in SetPathInfo (create symlink) = %d\n",
("Send error in SetPathInfo (create symlink) = %d",
rc));
}
......@@ -810,7 +832,7 @@ CIFSUnixCreateHardLink(const int xid, const struct cifsTconInfo *tcon,
int rc = 0;
int bytes_returned = 0;
cFYI(1, ("\nIn Create Hard link Unix style"));
cFYI(1, ("In Create Hard link Unix style"));
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
......@@ -873,7 +895,7 @@ CIFSUnixCreateHardLink(const int xid, const struct cifsTconInfo *tcon,
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cFYI(1, ("\nSend error in SetPathInfo (hard link) = %d\n", rc));
cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
}
if (pSMB)
......@@ -892,7 +914,7 @@ CIFSCreateHardLink(const int xid, const struct cifsTconInfo *tcon,
int bytes_returned;
int name_len, name_len2;
cFYI(1, ("\nIn CIFSCreateHardLink"));
cFYI(1, ("In CIFSCreateHardLink"));
rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
(void **) &pSMBr);
......@@ -923,7 +945,6 @@ CIFSCreateHardLink(const int xid, const struct cifsTconInfo *tcon,
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
name_len2 *= 2; /* convert to bytes */
} else { /* BB improve the check for buffer overruns BB */
name_len = strnlen(fromName, 530);
name_len++; /* trailing null */
strncpy(pSMB->OldFileName, fromName, name_len);
......@@ -942,7 +963,7 @@ CIFSCreateHardLink(const int xid, const struct cifsTconInfo *tcon,
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cFYI(1, ("\nSend error in hard link (NT rename) = %d\n", rc));
cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
}
if (pSMB)
buf_release(pSMB);
......@@ -963,7 +984,7 @@ CIFSSMBUnixQuerySymLink(const int xid, const struct cifsTconInfo *tcon,
int bytes_returned;
int name_len;
cFYI(1, ("\nIn QPathSymLinkInfo (Unix) for path %s", searchName));
cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
if (rc)
......@@ -977,7 +998,6 @@ CIFSSMBUnixQuerySymLink(const int xid, const struct cifsTconInfo *tcon,
name_len++; /* trailing null */
name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */
name_len = strnlen(searchName, 530);
name_len++; /* trailing null */
strncpy(pSMB->FileName, searchName, name_len);
......@@ -1011,7 +1031,7 @@ CIFSSMBUnixQuerySymLink(const int xid, const struct cifsTconInfo *tcon,
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cFYI(1, ("\nSend error in QuerySymLinkInfo = %d\n", rc));
cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
} else { /* decode response */
pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
......@@ -1066,7 +1086,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, const struct cifsTconInfo *tcon,
struct smb_com_transaction_ioctl_req * pSMB;
struct smb_com_transaction_ioctl_rsp * pSMBr;
cFYI(1, ("\nIn Windows reparse style QueryLink info for path %s", searchName));
cFYI(1, ("In Windows reparse style QueryLink info for path %s", searchName));
rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
(void **) &pSMBr);
if (rc)
......@@ -1093,7 +1113,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, const struct cifsTconInfo *tcon,
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cFYI(1, ("\nSend error in QueryReparseLinkInfo = %d\n", rc));
cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
} else { /* decode response */
pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
......@@ -1121,11 +1141,11 @@ CIFSSMBQueryReparseLinkInfo(const int xid, const struct cifsTconInfo *tcon,
}
} else {
rc = -EIO;
cFYI(1,("\nInvalid return data count on get reparse info ioctl"));
cFYI(1,("Invalid return data count on get reparse info ioctl"));
}
symlinkinfo[buflen] = 0; /* just in case so the caller
does not go off the end of the buffer */
cFYI(1,("\nreadlink result - %s ",symlinkinfo));
cFYI(1,("readlink result - %s ",symlinkinfo));
}
}
if (pSMB)
......@@ -1146,7 +1166,7 @@ CIFSSMBQPathInfo(const int xid, const struct cifsTconInfo *tcon,
int bytes_returned;
int name_len;
cFYI(1, ("\nIn QPathInfo path %s", searchName));
cFYI(1, ("In QPathInfo path %s", searchName));
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
if (rc)
......@@ -1160,7 +1180,6 @@ CIFSSMBQPathInfo(const int xid, const struct cifsTconInfo *tcon,
name_len++; /* trailing null */
name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */
name_len = strnlen(searchName, 530);
name_len++; /* trailing null */
strncpy(pSMB->FileName, searchName, name_len);
......@@ -1194,7 +1213,7 @@ CIFSSMBQPathInfo(const int xid, const struct cifsTconInfo *tcon,
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cFYI(1, ("\nSend error in QPathInfo = %d\n", rc));
cFYI(1, ("Send error in QPathInfo = %d", rc));
} else { /* decode response */
pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512)) /* BB also check enough total bytes returned */
......@@ -1223,7 +1242,7 @@ CIFSSMBUnixQPathInfo(const int xid, const struct cifsTconInfo *tcon,
int bytes_returned;
int name_len;
cFYI(1, ("\nIn QPathInfo (Unix) the path %s", searchName));
cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
if (rc)
......@@ -1237,7 +1256,6 @@ CIFSSMBUnixQPathInfo(const int xid, const struct cifsTconInfo *tcon,
name_len++; /* trailing null */
name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */
name_len = strnlen(searchName, 530);
name_len++; /* trailing null */
strncpy(pSMB->FileName, searchName, name_len);
......@@ -1271,7 +1289,7 @@ CIFSSMBUnixQPathInfo(const int xid, const struct cifsTconInfo *tcon,
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cFYI(1, ("\nSend error in QPathInfo = %d\n", rc));
cFYI(1, ("Send error in QPathInfo = %d", rc));
} else { /* decode response */
pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512)) /* BB also check enough total bytes returned */
......@@ -1300,7 +1318,7 @@ CIFSFindSingle(const int xid, const struct cifsTconInfo *tcon,
int bytes_returned;
int name_len;
cFYI(1, ("\nIn FindUnique"));
cFYI(1, ("In FindUnique"));
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
if (rc)
......@@ -1314,7 +1332,6 @@ CIFSFindSingle(const int xid, const struct cifsTconInfo *tcon,
name_len++; /* trailing null */
name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */
name_len = strnlen(searchName, 530);
name_len++; /* trailing null */
strncpy(pSMB->FileName, searchName, name_len);
......@@ -1353,7 +1370,7 @@ CIFSFindSingle(const int xid, const struct cifsTconInfo *tcon,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cFYI(1, ("\nSend error in FindFileDirInfo = %d\n", rc));
cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
} else { /* decode response */
/* BB fill in */
......@@ -1378,7 +1395,7 @@ CIFSFindFirst(const int xid, const struct cifsTconInfo *tcon,
int bytes_returned;
int name_len;
cFYI(1, ("\nIn FindFirst"));
cFYI(1, ("In FindFirst"));
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
if (rc)
......@@ -1392,7 +1409,6 @@ CIFSFindFirst(const int xid, const struct cifsTconInfo *tcon,
name_len++; /* trailing null */
name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */
name_len = strnlen(searchName, 530);
name_len++; /* trailing null */
strncpy(pSMB->FileName, searchName, name_len);
......@@ -1401,7 +1417,7 @@ CIFSFindFirst(const int xid, const struct cifsTconInfo *tcon,
pSMB->TotalParameterCount = 12 + name_len /* includes null */ ;
pSMB->TotalDataCount = 0; /* no EAs */
pSMB->MaxParameterCount = cpu_to_le16(10);
pSMB->MaxDataCount = cpu_to_le16((tcon->ses->maxBuf -
pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0;
......@@ -1441,7 +1457,7 @@ CIFSFindFirst(const int xid, const struct cifsTconInfo *tcon,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) { /* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
cFYI(1, ("\nError in FindFirst = %d\n", rc));
cFYI(1, ("Error in FindFirst = %d", rc));
} else { /* decode response */
/* BB add safety checks for these memcpys */
if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
......@@ -1480,7 +1496,7 @@ CIFSFindNext(const int xid, const struct cifsTconInfo *tcon,
int rc = 0;
int bytes_returned;
cFYI(1, ("\nIn FindNext"));
cFYI(1, ("In FindNext"));
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
if (rc)
......@@ -1490,7 +1506,7 @@ CIFSFindNext(const int xid, const struct cifsTconInfo *tcon,
pSMB->TotalDataCount = 0; /* no EAs */
pSMB->MaxParameterCount = cpu_to_le16(8);
pSMB->MaxDataCount =
cpu_to_le16((tcon->ses->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0;
pSMB->Flags = 0;
......@@ -1533,7 +1549,7 @@ CIFSFindNext(const int xid, const struct cifsTconInfo *tcon,
if (rc == -EBADF)
rc = 0; /* search probably was closed at end of search above */
else
cFYI(1, ("\nFindNext returned = %d\n", rc));
cFYI(1, ("FindNext returned = %d", rc));
} else { /* decode response */
/* BB add safety checks for these memcpys */
if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
......@@ -1574,7 +1590,7 @@ CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
*number_of_UNC_in_array = 0;
*targetUNCs = NULL;
cFYI(1, ("\nIn GetDFSRefer the path %s", searchName));
cFYI(1, ("In GetDFSRefer the path %s", searchName));
if (ses == NULL)
return -ENODEV;
......@@ -1591,7 +1607,7 @@ CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
if (ses->capabilities & CAP_DFS) {
pSMB->hdr.Flags2 |= SMBFLG2_DFS;
}
if(ses->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
if (ses->capabilities & CAP_UNICODE) {
......@@ -1604,7 +1620,6 @@ CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
name_len++; /* trailing null */
name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */
name_len = strnlen(searchName, 530);
name_len++; /* trailing null */
strncpy(pSMB->RequestFileName, searchName, name_len);
......@@ -1636,7 +1651,7 @@ CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cFYI(1, ("\nSend error in GetDFSRefer = %d\n", rc));
cFYI(1, ("Send error in GetDFSRefer = %d", rc));
} else { /* decode response */
/* BB Add logic to parse referrals here */
}
......@@ -1656,7 +1671,7 @@ CIFSSMBQFSInfo(const int xid, const struct cifsTconInfo *tcon,
int rc = 0;
int bytes_returned = 0;
cFYI(1, ("\nIn QFSInfo"));
cFYI(1, ("In QFSInfo"));
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
......@@ -1689,11 +1704,11 @@ CIFSSMBQFSInfo(const int xid, const struct cifsTconInfo *tcon,
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cERROR(1, ("\nSend error in QFSInfo = %d\n", rc));
cERROR(1, ("Send error in QFSInfo = %d", rc));
} else { /* decode response */
pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
cFYI(1,
("\nDecoding qfsinfo response. BCC: %d Offset %d\n",
("Decoding qfsinfo response. BCC: %d Offset %d",
pSMBr->ByteCount, pSMBr->DataOffset));
if ((pSMBr->ByteCount < 24) || (pSMBr->DataOffset > 512)) /* BB also check enough total bytes returned */
rc = -EIO; /* bad smb */
......@@ -1711,7 +1726,7 @@ CIFSSMBQFSInfo(const int xid, const struct cifsTconInfo *tcon,
FSData->f_bfree = FSData->f_bavail =
le64_to_cpu(response_data->FreeAllocationUnits);
cFYI(1,
("\nBlocks: %ld Free: %ld Block size %ld\n",
("Blocks: %ld Free: %ld Block size %ld",
FSData->f_blocks, FSData->f_bfree,
FSData->f_bsize));
}
......@@ -1732,7 +1747,7 @@ CIFSSMBQFSAttributeInfo(int xid, struct cifsTconInfo *tcon,
int rc = 0;
int bytes_returned = 0;
cFYI(1, ("\nIn QFSAttributeInfo"));
cFYI(1, ("In QFSAttributeInfo"));
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
if (rc)
......@@ -1764,7 +1779,7 @@ CIFSSMBQFSAttributeInfo(int xid, struct cifsTconInfo *tcon,
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cERROR(1, ("\nSend error in QFSAttributeInfo = %d\n", rc));
cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
} else { /* decode response */
pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) { /* BB also check enough bytes returned */
......@@ -1794,7 +1809,7 @@ CIFSSMBQFSDeviceInfo(int xid, struct cifsTconInfo *tcon,
int rc = 0;
int bytes_returned = 0;
cFYI(1, ("\nIn QFSDeviceInfo"));
cFYI(1, ("In QFSDeviceInfo"));
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
......@@ -1828,7 +1843,7 @@ CIFSSMBQFSDeviceInfo(int xid, struct cifsTconInfo *tcon,
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cERROR(1, ("\nSend error in QFSDeviceInfo = %d\n", rc));
cERROR(1, ("Send error in QFSDeviceInfo = %d", rc));
} else { /* decode response */
pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
if ((pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO))
......@@ -1859,7 +1874,7 @@ CIFSSMBQFSUnixInfo(int xid, struct cifsTconInfo *tcon,
int rc = 0;
int bytes_returned = 0;
cFYI(1, ("\nIn QFSUnixInfo"));
cFYI(1, ("In QFSUnixInfo"));
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
if (rc)
......@@ -1891,7 +1906,7 @@ CIFSSMBQFSUnixInfo(int xid, struct cifsTconInfo *tcon,
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cERROR(1, ("\nSend error in QFSUnixInfo = %d\n", rc));
cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
} else { /* decode response */
pSMBr->DataOffset = cpu_to_le16(pSMBr->DataOffset);
if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) {
......@@ -1927,7 +1942,7 @@ CIFSSMBSetEOF(int xid, struct cifsTconInfo *tcon, char *fileName,
int rc = 0;
int bytes_returned = 0;
cFYI(1, ("\nIn SetEOF"));
cFYI(1, ("In SetEOF"));
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
......@@ -1942,7 +1957,6 @@ CIFSSMBSetEOF(int xid, struct cifsTconInfo *tcon, char *fileName,
name_len++; /* trailing null */
name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */
name_len = strnlen(fileName, 530);
name_len++; /* trailing null */
strncpy(pSMB->FileName, fileName, name_len);
......@@ -1995,7 +2009,7 @@ CIFSSMBSetEOF(int xid, struct cifsTconInfo *tcon, char *fileName,
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cFYI(1, ("\nSetPathInfo (file size) returned %d\n", rc));
cFYI(1, ("SetPathInfo (file size) returned %d", rc));
}
if (pSMB)
......@@ -2015,7 +2029,7 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
int bytes_returned = 0;
__u32 tmp;
cFYI(1, ("\nSetFileSize (via SetFileInfo)"));
cFYI(1, ("SetFileSize (via SetFileInfo)"));
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
......@@ -2080,7 +2094,7 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cFYI(1,
("\nSend error in SetFileInfo (SetFileSize) = %d\n",
("Send error in SetFileInfo (SetFileSize) = %d",
rc));
}
......@@ -2100,7 +2114,7 @@ CIFSSMBSetTimes(int xid, struct cifsTconInfo *tcon, char *fileName,
int bytes_returned = 0;
char *data_offset;
cFYI(1, ("\nIn SetTimes"));
cFYI(1, ("In SetTimes"));
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
......@@ -2115,7 +2129,6 @@ CIFSSMBSetTimes(int xid, struct cifsTconInfo *tcon, char *fileName,
name_len++; /* trailing null */
name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */
name_len = strnlen(fileName, 530);
name_len++; /* trailing null */
strncpy(pSMB->FileName, fileName, name_len);
......@@ -2156,7 +2169,7 @@ CIFSSMBSetTimes(int xid, struct cifsTconInfo *tcon, char *fileName,
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cFYI(1, ("\nSetPathInfo (times) returned %d\n", rc));
cFYI(1, ("SetPathInfo (times) returned %d", rc));
}
if (pSMB)
......@@ -2176,7 +2189,7 @@ CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
int bytes_returned = 0;
FILE_UNIX_BASIC_INFO *data_offset;
cFYI(1, ("\nIn SetUID/GID/Mode"));
cFYI(1, ("In SetUID/GID/Mode"));
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
......@@ -2191,7 +2204,6 @@ CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
name_len++; /* trailing null */
name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */
name_len = strnlen(fileName, 530);
name_len++; /* trailing null */
strncpy(pSMB->FileName, fileName, name_len);
......@@ -2232,7 +2244,7 @@ CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cFYI(1, ("\nSetPathInfo (perms) returned %d\n", rc));
cFYI(1, ("SetPathInfo (perms) returned %d", rc));
}
if (pSMB)
......
......@@ -60,22 +60,61 @@ struct smb_vol {
int ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket);
/*
* cifs tcp session reconnection
*
* mark tcp session as reconnecting so temporarily locked
* mark all smb sessions as reconnecting for tcp session (TBD BB)
* reconnect tcp session
* wake up waiters on reconnection? - (not needed currently)
*/
int
cifs_reconnect(struct TCP_Server_Info *server)
{
int rc = 0;
struct list_head *tmp;
struct cifsSesInfo *ses;
server->tcpStatus = CifsNeedReconnect;
server->maxBuf = 0;
cFYI(1, ("\nReconnecting tcp session "));
cFYI(1, ("Reconnecting tcp session "));
read_lock(&GlobalSMBSeslock);
list_for_each(tmp, &GlobalSMBSessionList) {
ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
if (ses->server) {
if (ses->server == server) {
ses->status = CifsNeedReconnect;
}
}
/* else tcp and smb sessions need reconnection */
}
read_unlock(&GlobalSMBSeslock);
/* lock tcp session */
/* mark all smb sessions as reconnecting which use this tcp session */
/* reconnect tcp session */
/* wake up waiters on reconnection */
cFYI(1,
("\nState: 0x%x Flags: 0x%lx", server->ssocket->state,
server->ssocket->flags));
if(server->ssocket) {
cFYI(1,("State: 0x%x Flags: 0x%lx", server->ssocket->state,
server->ssocket->flags));
server->ssocket->ops->shutdown(server->ssocket,SEND_SHUTDOWN);;
cFYI(1,("Post shutdown state: 0x%x Flags: 0x%lx", server->ssocket->state,
server->ssocket->flags));
sock_release(server->ssocket);
server->ssocket = NULL;
}
while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
{
rc = ipv4_connect(&server->sockAddr, &server->ssocket);
if(rc) {
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(3 * HZ);
} else {
server->tcpStatus = CifsGood;
}
}
ipv4_connect(&server->sockAddr, &server->ssocket);
return rc;
}
......@@ -99,7 +138,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
allow_signal(SIGKILL);
server->tsk = current; /* save process info to wake at shutdown */
cFYI(1, ("\nDemultiplex PID: %d", current->pid));
cFYI(1, ("Demultiplex PID: %d", current->pid));
temp_fs = get_fs(); /* we must turn off socket api parm checking */
set_fs(get_ds());
......@@ -112,7 +151,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
if (smb_buffer == NULL) {
cERROR(1,
("\n Error - can not get mem for SMB response buffer "));
("Can not get mem for SMB response buffer "));
return -ENOMEM;
}
iov.iov_base = smb_buffer;
......@@ -130,25 +169,26 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
MSG_PEEK /* flags see socket.h */ );
if (length < 0) {
if (length == -ECONNRESET) {
cERROR(1, ("\nConnection reset by peer "));
/* BB fix call below */
/* cifs_reconnect(server); */
cERROR(1, ("Connection reset by peer "));
cifs_reconnect(server);
csocket = server->ssocket;
continue;
} else { /* find define for the -512 returned at unmount time */
cFYI(1,
("\nReceived error on sock_recvmsg( peek) with length = %d\n",
("Received error on sock_recvmsg( peek) with length = %d",
length));
}
break;
}
if (length == 0) {
cFYI(1,
("\nZero length peek received - dead session?? "));
/* schedule_timeout(HZ/4);
continue; */
break;
("Zero length peek received - dead session?"));
cifs_reconnect(server);
csocket = server->ssocket;
continue;
}
pdu_length = 4 + ntohl(smb_buffer->smb_buf_length);
cFYI(1, ("\nPeek length rcvd: %d with smb length: %d", length, pdu_length)); /* BB */
cFYI(1, ("Peek length rcvd: %d with smb length: %d", length, pdu_length)); /* BB */
temp = (char *) smb_buffer;
if (length > 3) {
......@@ -157,18 +197,18 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
iov.iov_len = 4;
length = sock_recvmsg(csocket, &smb_msg, 4, 0);
cFYI(0,
("\nReceived 4 byte keep alive packet "));
("Received 4 byte keep alive packet "));
} else if ((temp[0] == (char) 0x83)
&& (length == 5)) {
/* we get this from Windows 98 instead of error on SMB negprot response */
cERROR(1,
("\nNegative RFC 1002 Session response. Error = 0x%x",
("Negative RFC 1002 Session response. Error = 0x%x",
temp[4]));
break;
} else if (temp[0] != (char) 0) {
cERROR(1,
("\nUnknown RFC 1001 frame received not 0x00 nor 0x85"));
("Unknown RFC 1001 frame received not 0x00 nor 0x85"));
cifs_dump_mem(" Received Data is: ", temp, length);
break;
} else {
......@@ -182,7 +222,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
(smb_buffer, smb_buffer->Mid))) {
cERROR(1,
(KERN_ERR
"\nInvalid size or format for SMB found with length %d and pdu_lenght %d\n",
"Invalid size or format for SMB found with length %d and pdu_lenght %d",
length, pdu_length));
/* BB fix by finding next smb signature - and reading off data until next smb ? BB */
......@@ -200,11 +240,11 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
iov.iov_len = pdu_length-total_read; */
length = sock_recvmsg(csocket, &smb_msg,
pdu_length - total_read, 0);
/* cERROR(1,("\nFor iovlen %d Length received: %d with total read %d",
/* cERROR(1,("For iovlen %d Length received: %d with total read %d",
iov.iov_len, length,total_read)); */
if (length == 0) {
cERROR(1,
("\nZero length receive when expecting %d ",
("Zero length receive when expecting %d ",
pdu_length - total_read));
/* BB add reconnect here */
break;
......@@ -215,11 +255,11 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
dump_smb(smb_buffer, length);
if (checkSMB
(smb_buffer, smb_buffer->Mid, total_read)) {
cERROR(1, ("\n Bad SMB Received "));
cERROR(1, ("Bad SMB Received "));
continue;
}
task_to_wake = NULL;
task_to_wake = NULL;
read_lock(&GlobalMid_Lock);
list_for_each(tmp, &server->pending_mid_q) {
mid_entry = list_entry(tmp, struct
......@@ -228,7 +268,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
if (mid_entry->mid == smb_buffer->Mid) {
cFYI(1,
(" Mid 0x%x matched - waking up\n ",mid_entry->mid));
(" Mid 0x%x matched - waking up ",mid_entry->mid));
task_to_wake = mid_entry->tsk;
mid_entry->resp_buf =
smb_buffer;
......@@ -241,17 +281,17 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
smb_buffer = NULL; /* will be freed by users thread after he is done */
wake_up_process(task_to_wake);
} else if (is_valid_oplock_break(smb_buffer) == FALSE) {
cERROR(1, ("\n No task to wake, unknown frame rcvd!\n"));
}
cERROR(1, ("No task to wake, unknown frame rcvd!"));
}
}
} else {
cFYI(0,
("\nFrame less than four bytes received %d bytes long.",
("Frame less than four bytes received %d bytes long.",
length));
if (length > 0) {
length = sock_recvmsg(csocket, &smb_msg, length, 0); /* throw away junk frame */
cFYI(1,
(" with junk 0x%x in it\n",
(" with junk 0x%x in it ",
*(__u32 *) smb_buffer));
}
}
......@@ -280,13 +320,12 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
kfree(server);
} else /* BB need to more gracefully handle the rare negative session
response case because response will be still outstanding */
cERROR(1, ("\nThere are still active MIDs in queue and we are exiting but we can not delete mid_q_entries or TCP_Server_Info structure due to pending requests MEMORY LEAK!!\n ")); /* BB wake up waitors, and/or wait and/or free stale mids and try again? BB */
cERROR(1, ("There are still active MIDs in queue and we are exiting but we can not delete mid_q_entries or TCP_Server_Info structure due to pending requests MEMORY LEAK!!")); /* BB wake up waitors, and/or wait and/or free stale mids and try again? BB */
/* BB Need to fix bug in error path above - perhaps wait until smb requests
time out and then free the tcp per server struct BB */
read_unlock(&GlobalSMBSeslock);
cFYI(1, ("\nAbout to exit from demultiplex thread\n"));
cFYI(1, ("About to exit from demultiplex thread"));
return 0;
}
......@@ -315,14 +354,14 @@ parse_mount_options(char *options, char *devname, struct smb_vol *vol)
*value++ = '\0';
if (strnicmp(data, "user", 4) == 0) {
if (!value || !*value) {
printk(KERN_ERR
"CIFS: invalid or missing username");
printk(KERN_WARNING
"CIFS: invalid or missing username\n");
return 1; /* needs_arg; */
}
if (strnlen(value, 200) < 200) {
vol->username = value;
} else {
printk(KERN_ERR "CIFS: username too long");
printk(KERN_WARNING "CIFS: username too long\n");
return 1;
}
} else if (strnicmp(data, "pass", 4) == 0) {
......@@ -331,15 +370,15 @@ parse_mount_options(char *options, char *devname, struct smb_vol *vol)
} else if (strnlen(value, 17) < 17) {
vol->password = value;
} else {
printk(KERN_ERR "CIFS: password too long");
printk(KERN_WARNING "CIFS: password too long\n");
return 1;
}
} else if ((strnicmp(data, "unc", 3) == 0)
|| (strnicmp(data, "target", 6) == 0)
|| (strnicmp(data, "path", 4) == 0)) {
if (!value || !*value) {
printk(KERN_ERR
"CIFS: invalid path to network resource");
printk(KERN_WARNING
"CIFS: invalid path to network resource\n");
return 1; /* needs_arg; */
}
if (strnlen(value, 300) < 300) {
......@@ -348,26 +387,26 @@ parse_mount_options(char *options, char *devname, struct smb_vol *vol)
vol->UNC[0] = '\\';
vol->UNC[1] = '\\';
} else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
printk(KERN_ERR
"CIFS: UNC Path does not begin with // or \\\\");
printk(KERN_WARNING
"CIFS: UNC Path does not begin with // or \\\\ \n");
return 1;
}
vol->UNCip = &vol->UNC[2];
} else {
printk(KERN_ERR "CIFS: UNC name too long");
printk(KERN_WARNING "CIFS: UNC name too long\n");
return 1;
}
} else if ((strnicmp(data, "domain", 3) == 0)
|| (strnicmp(data, "workgroup", 5) == 0)) {
if (!value || !*value) {
printk(KERN_ERR "CIFS: invalid domain name");
printk(KERN_WARNING "CIFS: invalid domain name\n");
return 1; /* needs_arg; */
}
if (strnlen(value, 65) < 65) {
vol->domainname = value;
cFYI(1, ("\nDomain name set"));
cFYI(1, ("Domain name set"));
} else {
printk(KERN_ERR "CIFS: domain name too long");
printk(KERN_WARNING "CIFS: domain name too long\n");
return 1;
}
} else if (strnicmp(data, "uid", 3) == 0) {
......@@ -395,9 +434,7 @@ parse_mount_options(char *options, char *devname, struct smb_vol *vol)
} else if (strnicmp(data, "rw", 2) == 0) {
vol->rw = TRUE;
} else
printk(KERN_ERR
"CIFS: Unrecognized mount option %s = %s",
data, value);
printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
}
if (vol->UNC == NULL) {
if (strnlen(devname, 300) < 300) {
......@@ -406,13 +443,12 @@ parse_mount_options(char *options, char *devname, struct smb_vol *vol)
vol->UNC[0] = '\\';
vol->UNC[1] = '\\';
} else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
printk(KERN_ERR
"CIFS: UNC Path does not begin with // or \\\\");
printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
return 1;
}
vol->UNCip = &vol->UNC[2];
} else {
printk(KERN_ERR "CIFS: UNC name too long");
printk(KERN_WARNING "CIFS: UNC name too long\n");
return 1;
}
}
......@@ -458,7 +494,7 @@ find_unc(__u32 new_target_ip_addr, char *uncName, char *userName)
read_lock(&GlobalSMBSeslock);
list_for_each(tmp, &GlobalTreeConnectionList) {
cFYI(1, ("\nNext tcon - "));
cFYI(1, ("Next tcon - "));
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
if (tcon->ses) {
if (tcon->ses->server) {
......@@ -472,13 +508,13 @@ find_unc(__u32 new_target_ip_addr, char *uncName, char *userName)
/* found a match on the TCP session */
/* BB check if reconnection needed */
cFYI(1,
("\nMatched ip, old UNC: %s == new: %s ?",
("Matched ip, old UNC: %s == new: %s ?",
tcon->treeName, uncName));
if (strncmp
(tcon->treeName, uncName,
MAX_TREE_SIZE) == 0) {
cFYI(1,
("\nMatched UNC, old user: %s == new: %s ?",
("Matched UNC, old user: %s == new: %s ?",
tcon->treeName, uncName));
if (strncmp
(tcon->ses->userName,
......@@ -522,45 +558,118 @@ connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
SERVER_NAME_LEN_WITH_NULL * 2), "\\IPC$", 6);
rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
cFYI(1,
("\nCIFS Tcon rc = %d ipc_tid = %d\n", rc,
pSesInfo->ipc_tid));
("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
kfree(temp_unc);
}
if (rc == 0)
rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, &referrals,
&num_referrals, nls_codepage);
return -ENODEV; /* BB remove and add return rc; */
return -ENODEV; /* BB remove and add return code processing */
}
int setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, struct nls_table * nls_info)
{
int rc = 0;
char session_key[CIFS_SESSION_KEY_SIZE];
char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
int ntlmv2_flag = FALSE;
if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */
rc = CIFSSMBNegotiate(xid, pSesInfo);
pSesInfo->capabilities = pSesInfo->server->capabilities;
if (!rc) {
cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
pSesInfo->server->secMode,
pSesInfo->server->capabilities,
pSesInfo->server->timeZone));
if (extended_security
&& (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
&& (pSesInfo->server->secType == NTLMSSP)) {
cFYI(1, ("New style sesssetup "));
rc = CIFSSpnegoSessSetup(xid, pSesInfo,
NULL /* security blob */,
0 /* blob length */,
nls_info);
} else if (extended_security
&& (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
&& (pSesInfo->server->secType == RawNTLMSSP)) {
cFYI(1, ("NTLMSSP sesssetup "));
rc = CIFSNTLMSSPNegotiateSessSetup(xid,
pSesInfo,
&ntlmv2_flag,
nls_info);
if (!rc) {
if(ntlmv2_flag) {
cFYI(1,("Able to use the more secure NTLM version 2 password hash"));
/* SMBNTv2encrypt( ...); */ /* BB fix this up -
and note that Samba client equivalent looks wrong */
} else
SMBNTencrypt(pSesInfo->password_with_pad,
pSesInfo->server->cryptKey,ntlm_session_key);
/* for better security the weaker lanman hash not sent
in AuthSessSetup so why bother calculating it */
/* toUpper(nls_info,
password_with_pad);
SMBencrypt(password_with_pad,
pSesInfo->server->cryptKey, session_key); */
rc = CIFSNTLMSSPAuthSessSetup(xid,
pSesInfo,
ntlm_session_key,
session_key,
ntlmv2_flag,
nls_info);
}
} else { /* old style NTLM 0.12 session setup */
SMBNTencrypt(pSesInfo->password_with_pad,
pSesInfo->server->cryptKey,
ntlm_session_key);
rc = CIFSSessSetup(xid, pSesInfo,
session_key,
ntlm_session_key,
nls_info);
}
if (rc) {
cERROR(1,("Send error in SessSetup = %d",rc));
} else {
cFYI(1,("CIFS Session Established successfully"));
pSesInfo->status = CifsGood;
}
}
return rc;
}
int
ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket)
{
int rc = 0;
rc = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
if (rc < 0) {
cERROR(1, ("Error creating socket. Aborting operation\n"));
return rc;
if(*csocket == NULL) {
rc = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
if (rc < 0) {
cERROR(1, ("Error %d creating socket",rc));
*csocket = NULL;
return rc;
} else {
cFYI(1,("Socket created"));
}
}
psin_server->sin_family = AF_INET;
psin_server->sin_port = htons(CIFS_PORT);
rc = (*csocket)->ops->connect(*csocket,
(struct sockaddr *) psin_server,
sizeof (struct sockaddr_in), 0
/* Is there a way to fix a polling timeout -
and find out what more of the flags really mean? */
);
(struct sockaddr *) psin_server,
sizeof (struct sockaddr_in),0);
if (rc < 0) {
psin_server->sin_port = htons(RFC1001_PORT);
rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
psin_server,
sizeof (struct sockaddr_in), 0);
psin_server, sizeof (struct sockaddr_in),0);
if (rc < 0) {
cFYI(1, ("Error connecting to socket. %d\n", rc));
cFYI(1, ("Error connecting to socket. %d", rc));
sock_release(*csocket);
*csocket = NULL;
return rc;
......@@ -578,7 +687,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
rc = sock_create(PF_INET6, SOCK_STREAM,
IPPROTO_TCP /* IPPROTO_IPV6 ? */ , csocket);
if (rc < 0) {
cERROR(1, ("Error creating socket. Aborting operation\n"));
cERROR(1, ("Error creating socket. Aborting operation"));
return rc;
}
......@@ -597,7 +706,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
sizeof (struct sockaddr_in6), 0);
if (rc < 0) {
cFYI(1,
("Error connecting to socket (via ipv6). %d\n",
("Error connecting to socket (via ipv6). %d",
rc));
sock_release(*csocket);
*csocket = NULL;
......@@ -614,8 +723,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
{
int rc = 0;
int xid;
int ntlmv2_flag = FALSE;
struct socket *csocket;
struct socket *csocket = NULL;
struct sockaddr_in sin_server;
/* struct sockaddr_in6 sin_server6; */
struct smb_vol volume_info;
......@@ -623,35 +731,33 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
struct cifsSesInfo *existingCifsSes = NULL;
struct cifsTconInfo *tcon = NULL;
struct TCP_Server_Info *srvTcp = NULL;
char cryptKey[CIFS_CRYPTO_KEY_SIZE];
char session_key[CIFS_SESSION_KEY_SIZE];
char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
char password_with_pad[CIFS_ENCPWD_SIZE];
xid = GetXid();
cFYI(0, ("\nEntering cifs_mount. Xid: %d with: %s\n", xid, mount_data));
cFYI(0, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data));
if(parse_mount_options(mount_data, devname, &volume_info)) {
FreeXid(xid);
return -EINVAL;
}
if (volume_info.username) {
cFYI(1, ("\nUsername: %s ", volume_info.username));
cFYI(1, ("Username: %s ", volume_info.username));
} else {
cERROR(1, ("\nNo username specified "));
/* Could add ways to allow getting user name from alternate locations */
cifserror("No username specified ");
/* In userspace mount helper we can get user name from alternate
locations such as env variables and files on disk */
FreeXid(xid);
return -EINVAL;
}
if (volume_info.UNC) {
sin_server.sin_addr.s_addr = inet_addr(volume_info.UNCip);
cFYI(1, ("\nUNC: %s ", volume_info.UNC));
cFYI(1, ("UNC: %s ", volume_info.UNC));
} else {
/* BB we could connect to the DFS root? but which server do we ask? */
cERROR(1,
("\nCIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
FreeXid(xid);
return -EINVAL;
}
......@@ -660,12 +766,14 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
find_tcp_session(sin_server.sin_addr.s_addr,
volume_info.username, &srvTcp);
if (srvTcp) {
cFYI(1, ("\nExisting tcp session with server found "));
cFYI(1, ("Existing tcp session with server found "));
} else { /* create socket */
rc = ipv4_connect(&sin_server, &csocket);
if (rc < 0) {
cERROR(1,
("Error connecting to IPv4 socket. Aborting operation\n"));
("Error connecting to IPv4 socket. Aborting operation"));
if(csocket != NULL)
sock_release(csocket);
FreeXid(xid);
return rc;
}
......@@ -683,6 +791,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
srvTcp->ssocket = csocket;
init_waitqueue_head(&srvTcp->response_q);
INIT_LIST_HEAD(&srvTcp->pending_mid_q);
srvTcp->tcpStatus = CifsGood;
kernel_thread((void *) (void *)
cifs_demultiplex_thread, srvTcp,
CLONE_FS | CLONE_FILES | CLONE_VM);
......@@ -691,113 +800,32 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
if (existingCifsSes) {
pSesInfo = existingCifsSes;
cFYI(1, ("\nExisting smb sess found "));
cFYI(1, ("Existing smb sess found "));
} else if (!rc) {
cFYI(1, ("\nExisting smb sess not found "));
cFYI(1, ("Existing smb sess not found "));
pSesInfo = sesInfoAlloc();
if (pSesInfo == NULL)
rc = -ENOMEM;
else {
pSesInfo->server = srvTcp;
pSesInfo->status = CifsGood;
sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
NIPQUAD(sin_server.sin_addr.s_addr));
}
/* send negotiate protocol smb */
if (!rc)
rc = CIFSSMBNegotiate(xid, pSesInfo, cryptKey);
cFYI(0, ("\nNegotiate rc = %d ", rc));
if (!rc) {
cFYI(1, ("\nSecurity Mode: %x", pSesInfo->secMode));
cFYI(1,
(" Server Capabilities: %x",
pSesInfo->capabilities));
cFYI(1,
(" Time Zone: 0x%x %d\n", pSesInfo->timeZone,
pSesInfo->timeZone));
memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
if (!rc){
if (volume_info.password)
strcpy(password_with_pad, volume_info.password);
if (extended_security
&& (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
&& (pSesInfo->secType == NTLMSSP)) {
cFYI(1, ("\nNew style sesssetup "));
rc = CIFSSpnegoSessSetup(xid, pSesInfo,
volume_info.
username,
volume_info.
domainname, NULL
/* security blob */
, 0 /* blob length */
, cifs_sb->local_nls);
} else if (extended_security
&& (pSesInfo->
capabilities & CAP_EXTENDED_SECURITY)
&& (pSesInfo->secType == RawNTLMSSP)) {
cFYI(1, ("\nNTLMSSP sesssetup "));
rc = CIFSNTLMSSPNegotiateSessSetup(xid,
pSesInfo,
cryptKey,
volume_info.domainname,
&ntlmv2_flag,
cifs_sb->local_nls);
if (!rc) {
if(ntlmv2_flag) {
cFYI(1,("\nAble to use the more secure NTLM version 2 password hash"));
/* SMBNTv2encrypt( ...); */ /* BB fix this up -
and note that Samba client equivalent looks wrong */
} else
SMBNTencrypt(password_with_pad,cryptKey,ntlm_session_key);
/* for better security the weaker lanman hash not sent
in AuthSessSetup so why bother calculating it */
/* toUpper(cifs_sb->local_nls,
password_with_pad);
SMBencrypt(password_with_pad,
cryptKey, session_key); */
rc = CIFSNTLMSSPAuthSessSetup(xid,
pSesInfo,
volume_info.
username,
volume_info.domainname,
ntlm_session_key,
session_key,
ntlmv2_flag,
cifs_sb->local_nls);
}
} else { /* old style NTLM 0.12 session setup */
SMBNTencrypt(password_with_pad, cryptKey,
ntlm_session_key);
/* Removed following few lines to not send old style password
hash ever - for better security */
/* toUpper(cifs_sb->local_nls, password_with_pad);
SMBencrypt(password_with_pad, cryptKey,session_key); */
rc = CIFSSessSetup(xid, pSesInfo,
volume_info.username,
volume_info.
domainname,
session_key,
ntlm_session_key,
cifs_sb->local_nls);
}
if (rc) {
cERROR(1,
("\nSend error in SessSetup = %d\n",
rc));
} else {
cFYI(1,
("CIFS Session Established successfully "));
strncpy(pSesInfo->password_with_pad,
volume_info.password,CIFS_ENCPWD_SIZE);
if (volume_info.username)
strncpy(pSesInfo->userName,
volume_info.username,
MAX_USERNAME_SIZE);
volume_info.username,MAX_USERNAME_SIZE);
if (volume_info.domainname)
strncpy(pSesInfo->domainName,
volume_info.domainname,MAX_USERNAME_SIZE);
rc = setup_session(xid,pSesInfo, cifs_sb->local_nls);
if(!rc)
atomic_inc(&srvTcp->socketUseCount);
}
}
}
......@@ -807,7 +835,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
volume_info.username);
if (tcon) {
cFYI(1, ("\nFound match on UNC path "));
cFYI(1, ("Found match on UNC path "));
} else {
tcon = tconInfoAlloc();
if (tcon == NULL)
......@@ -830,7 +858,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
rc = CIFSTCon(xid, pSesInfo,
volume_info.UNC,
tcon, cifs_sb->local_nls);
cFYI(1, ("\nCIFS Tcon rc = %d\n", rc));
cFYI(1, ("CIFS Tcon rc = %d", rc));
}
if (!rc)
atomic_inc(&pSesInfo->inUse);
......@@ -838,7 +866,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
}
}
if (pSesInfo->capabilities & CAP_LARGE_FILES) {
cFYI(0, ("\nLarge files supported "));
cFYI(0, ("Large files supported "));
sb->s_maxbytes = (u64) 1 << 63;
} else
sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
......@@ -846,19 +874,21 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
/* on error free sesinfo and tcon struct if needed */
if (rc) {
/* If find_unc succeeded then rc == 0 so we can not end */
if (tcon) /* up here accidently freeing someone elses tcon struct */
if (tcon) /* up here accidently freeing someone elses tcon struct */
tconInfoFree(tcon);
if (existingCifsSes == 0) {
if (pSesInfo) {
if (pSesInfo->server) {
cFYI(0,
("\nAbout to check if we need to do SMBLogoff "));
if (pSesInfo->Suid)
CIFSSMBLogoff(xid, pSesInfo);
wake_up_process(pSesInfo->server->tsk);
if(pSesInfo->server->tsk)
send_sig(SIGINT,pSesInfo->server->tsk,1);
else
cFYI(1,("Can not wake captive thread on cleanup of failed mount"));
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(HZ / 4); /* give captive thread time to exit */
} else
cFYI(1, ("\nNo session or bad tcon"));
cFYI(1, ("No session or bad tcon"));
sesInfoFree(pSesInfo);
/* pSesInfo = NULL; */
}
......@@ -876,13 +906,12 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
}
FreeXid(xid);
return rc;
}
int
CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, char *user,
char *domain, char session_key[CIFS_SESSION_KEY_SIZE],
CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
char session_key[CIFS_SESSION_KEY_SIZE],
char session_key2[CIFS_SESSION_KEY_SIZE],
const struct nls_table *nls_codepage)
{
......@@ -891,12 +920,14 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, char *user,
SESSION_SETUP_ANDX *pSMB;
SESSION_SETUP_ANDX *pSMBr;
char *bcc_ptr;
char *user = ses->userName;
char *domain = ses->domainName;
int rc = 0;
int remaining_words = 0;
int bytes_returned = 0;
int len;
cFYI(1, ("\nIn sesssetup "));
cFYI(1, ("In sesssetup "));
smb_buffer = buf_get();
if (smb_buffer == 0) {
......@@ -910,10 +941,10 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, char *user,
0 /* no tCon exists yet */ , 13 /* wct */ );
pSMB->req_no_secext.AndXCommand = 0xFF;
pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->maxBuf);
pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->maxReq);
pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
if(ses->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
pSMB->req_no_secext.Capabilities =
......@@ -1136,21 +1167,22 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, char *user,
int
CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
char *user, char *domain, char *SecurityBlob,
int SecurityBlobLength,
const struct nls_table *nls_codepage)
char *SecurityBlob,int SecurityBlobLength,
const struct nls_table *nls_codepage)
{
struct smb_hdr *smb_buffer;
struct smb_hdr *smb_buffer_response;
SESSION_SETUP_ANDX *pSMB;
SESSION_SETUP_ANDX *pSMBr;
char *bcc_ptr;
char *user = ses->userName;
char *domain = ses->domainName;
int rc = 0;
int remaining_words = 0;
int bytes_returned = 0;
int len;
cFYI(1, ("\nIn v2 sesssetup "));
cFYI(1, ("In v2 sesssetup "));
smb_buffer = buf_get();
if (smb_buffer == 0) {
......@@ -1164,10 +1196,10 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
0 /* no tCon exists yet */ , 12 /* wct */ );
pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
pSMB->req.AndXCommand = 0xFF;
pSMB->req.MaxBufferSize = cpu_to_le16(ses->maxBuf);
pSMB->req.MaxMpxCount = cpu_to_le16(ses->maxReq);
pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
if(ses->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
pSMB->req.Capabilities =
......@@ -1276,7 +1308,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
bcc_ptr +=
pSMBr->resp.SecurityBlobLength;
cFYI(1,
("\nSecurity Blob Length %d ",
("Security Blob Length %d ",
pSMBr->resp.SecurityBlobLength));
}
......@@ -1394,9 +1426,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
int
CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
struct cifsSesInfo *ses,
char *challenge_from_server,
char *domain, int * pNTLMv2_flag,
struct cifsSesInfo *ses, int * pNTLMv2_flag,
const struct nls_table *nls_codepage)
{
struct smb_hdr *smb_buffer;
......@@ -1404,6 +1434,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
SESSION_SETUP_ANDX *pSMB;
SESSION_SETUP_ANDX *pSMBr;
char *bcc_ptr;
char *domain = ses->domainName;
int rc = 0;
int remaining_words = 0;
int bytes_returned = 0;
......@@ -1412,7 +1443,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
PNEGOTIATE_MESSAGE SecurityBlob;
PCHALLENGE_MESSAGE SecurityBlob2;
cFYI(1, ("\nIn NTLMSSP sesssetup (negotiate) "));
cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
*pNTLMv2_flag = FALSE;
smb_buffer = buf_get();
if (smb_buffer == 0) {
......@@ -1429,10 +1460,10 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
pSMB->req.AndXCommand = 0xFF;
pSMB->req.MaxBufferSize = cpu_to_le16(ses->maxBuf);
pSMB->req.MaxMpxCount = cpu_to_le16(ses->maxReq);
pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
if(ses->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
pSMB->req.Capabilities =
......@@ -1555,7 +1586,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
if (SecurityBlob2->MessageType != NtLmChallenge) {
cFYI(1,
("\nUnexpected NTLMSSP message type received %d",
("Unexpected NTLMSSP message type received %d",
SecurityBlob2->MessageType));
} else if (ses) {
ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
......@@ -1568,13 +1599,13 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
bcc_ptr +=
pSMBr->resp.SecurityBlobLength;
cFYI(1,
("\nSecurity Blob Length %d ",
("Security Blob Length %d ",
pSMBr->resp.SecurityBlobLength));
}
cFYI(1, ("\nNTLMSSP Challenge rcvd "));
cFYI(1, ("NTLMSSP Challenge rcvd "));
memcpy(challenge_from_server,
memcpy(ses->server->cryptKey,
SecurityBlob2->Challenge,
CIFS_CRYPTO_KEY_SIZE);
if(SecurityBlob2->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLMV2)
......@@ -1722,16 +1753,16 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
int
CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
char *user, char *domain,
char *ntlm_session_key,
char *lanman_session_key, int ntlmv2_flag,
const struct nls_table *nls_codepage)
char *ntlm_session_key, char *lanman_session_key, int ntlmv2_flag,
const struct nls_table *nls_codepage)
{
struct smb_hdr *smb_buffer;
struct smb_hdr *smb_buffer_response;
SESSION_SETUP_ANDX *pSMB;
SESSION_SETUP_ANDX *pSMBr;
char *bcc_ptr;
char *user = ses->userName;
char *domain = ses->domainName;
int rc = 0;
int remaining_words = 0;
int bytes_returned = 0;
......@@ -1739,7 +1770,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
PAUTHENTICATE_MESSAGE SecurityBlob;
cFYI(1, ("\nIn NTLMSSPSessSetup (Authenticate)"));
cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
smb_buffer = buf_get();
if (smb_buffer == 0) {
......@@ -1755,12 +1786,12 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
pSMB->req.AndXCommand = 0xFF;
pSMB->req.MaxBufferSize = cpu_to_le16(ses->maxBuf);
pSMB->req.MaxMpxCount = cpu_to_le16(ses->maxReq);
pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
pSMB->req.hdr.Uid = ses->Suid;
if(ses->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
pSMB->req.Capabilities =
......@@ -1949,7 +1980,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
if (pSMBr->resp.Action & GUEST_LOGIN)
cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
/* if(SecurityBlob2->MessageType != NtLm??){
cFYI("\nUnexpected message type on auth response is %d "));
cFYI("Unexpected message type on auth response is %d "));
} */
if (ses) {
cFYI(1,
......@@ -1966,12 +1997,12 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
bcc_ptr +=
pSMBr->resp.SecurityBlobLength;
cFYI(1,
("\nSecurity Blob Length %d ",
("Security Blob Length %d ",
pSMBr->resp.SecurityBlobLength));
}
cFYI(1,
("\nNTLMSSP response to Authenticate "));
("NTLMSSP response to Authenticate "));
if (smb_buffer->Flags2 &= SMBFLG2_UNICODE) {
if ((long) (bcc_ptr) % 2) {
......@@ -2133,7 +2164,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
bcc_ptr = &(pSMB->Password[0]);
bcc_ptr++; /* skip password */
if(ses->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
if (ses->capabilities & CAP_STATUS32) {
......@@ -2163,7 +2194,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
/* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
/* above now done in SendReceive */
/* above now done in SendReceive */
if ((rc == 0) && (tcon != NULL)) {
tcon->tid = smb_buffer_response->Tid;
bcc_ptr = pByteArea(smb_buffer_response);
......@@ -2200,7 +2231,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
/* else do not bother copying these informational fields */
}
tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
cFYI(1, ("\nTcon flags: 0x%x ", tcon->Flags));
cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
} else if ((rc == 0) && tcon == NULL) {
/* all we need to save for IPC$ connection */
ses->ipc_tid = smb_buffer_response->Tid;
......@@ -2229,27 +2260,28 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
}
tconInfoFree(cifs_sb->tcon);
if ((ses) && (ses->server)) {
cFYI(1, ("\nAbout to do SMBLogoff "));
cFYI(1, ("About to do SMBLogoff "));
rc = CIFSSMBLogoff(xid, ses);
if (rc == -EBUSY) {
/* BB this looks wrong - why is this here? */
FreeXid(xid);
return 0;
}
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(HZ / 4); /* give captive thread time to exit */
if((ses->server) && (ses->server->ssocket)) {
cFYI(1,("\nWaking up socket by sending it signal "));
cFYI(1,("Waking up socket by sending it signal "));
send_sig(SIGINT,ses->server->tsk,1);
}
} else
cFYI(1, ("\nNo session or bad tcon"));
cFYI(1, ("No session or bad tcon"));
}
/* BB future check active count of tcon and then free if needed BB */
cifs_sb->tcon = NULL;
if (ses) {
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(HZ / 2);
/* if ((ses->server) && (ses->server->ssocket)) {
cFYI(1,("\nReleasing socket "));
cFYI(1,("Releasing socket "));
sock_release(ses->server->ssocket);
kfree(ses->server);
} */
......
......@@ -54,7 +54,6 @@ build_path_from_dentry(struct dentry *direntry)
temp = temp->d_parent;
}
namelen += 1; /* allow for trailing null */
cFYI(1, ("Final namelength (in build_path): %d ", namelen)); /* BB remove */
full_path = kmalloc(namelen, GFP_KERNEL);
namelen--;
full_path[namelen] = 0; /* trailing null */
......@@ -66,13 +65,13 @@ build_path_from_dentry(struct dentry *direntry)
full_path[namelen] = '\\';
strncpy(full_path + namelen + 1, temp->d_name.name,
temp->d_name.len);
cFYI(1, (" name: %s ", full_path + namelen)); /* BB remove */
cFYI(0, (" name: %s ", full_path + namelen));
}
temp = temp->d_parent;
}
if (namelen != 0)
cERROR(1,
("\nWe did not end path lookup where we expected namelen is %d",
("We did not end path lookup where we expected namelen is %d",
namelen));
return full_path;
......@@ -111,7 +110,7 @@ build_wildcard_path_from_dentry(struct dentry *direntry)
}
if (namelen != 0)
cERROR(1,
("\nWe did not end path lookup where we expected namelen is %d",
("We did not end path lookup where we expected namelen is %d",
namelen));
return full_path;
......@@ -124,7 +123,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode)
{
int rc = -ENOENT;
int xid;
int oplock = FALSE; /* no need to oplock when we are not going to read from the file */
int oplock = REQ_OPLOCK;
__u16 fileHandle;
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
......@@ -144,7 +143,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode)
/* 0x20197 was used previously */ , CREATE_NOT_DIR,
&fileHandle, &oplock, cifs_sb->local_nls);
if (rc) {
cFYI(1, ("\ncifs_create returned 0x%x ", rc));
cFYI(1, ("cifs_create returned 0x%x ", rc));
} else {
if (pTcon->ses->capabilities & CAP_UNIX)
rc = cifs_get_inode_info_unix(&newinode, full_path,
......@@ -154,14 +153,17 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode)
inode->i_sb);
if (rc != 0) {
cFYI(1,
("\nCreate worked but get_inode_info failed with rc = %d ",
cFYI(1,("Create worked but get_inode_info failed with rc = %d",
rc));
/* close handle */
} else {
direntry->d_op = &cifs_dentry_ops;
d_instantiate(direntry, newinode);
}
/* BB check oplock state before deciding to call following */
/* if(*oplock)
save off handle in inode and dontdoclose */
CIFSSMBClose(xid, pTcon, fileHandle);
/* BB In the future chain close with the NTCreateX to narrow window */
......@@ -204,7 +206,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry)
cFYI(1, (" NULL inode in lookup"));
}
cFYI(1,
(" Full path: %s inode = 0x%p\n", full_path, direntry->d_inode));
(" Full path: %s inode = 0x%p", full_path, direntry->d_inode));
if (pTcon->ses->capabilities & CAP_UNIX)
rc = cifs_get_inode_info_unix(&newInode, full_path,
parent_dir_inode->i_sb);
......@@ -224,7 +226,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry)
d_add(direntry, NULL);
} else {
cERROR(1,
("Error 0x%x or (%d decimal) on cifs_get_inode_info in lookup\n",
("Error 0x%x or (%d decimal) on cifs_get_inode_info in lookup",
rc, rc));
/* BB special case check for Access Denied - watch security exposure of returning dir info implicitly via different rc if file exists or not but no access BB */
}
......@@ -251,7 +253,7 @@ cifs_dir_open(struct inode *inode, struct file *file)
full_path = build_wildcard_path_from_dentry(file->f_dentry);
cFYI(1, (" inode = 0x%p and full path is %s\n", inode, full_path));
cFYI(1, (" inode = 0x%p and full path is %s", inode, full_path));
if (full_path)
kfree(full_path);
......@@ -273,7 +275,7 @@ cifs_d_revalidate(struct dentry *direntry, int flags)
}
} else {
cFYI(1,
("In cifs_d_revalidate with no inode but name = %s and dentry 0x%p\n",
("In cifs_d_revalidate with no inode but name = %s and dentry 0x%p",
direntry->d_name.name, direntry));
}
......@@ -286,7 +288,7 @@ cifs_d_revalidate(struct dentry *direntry, int flags)
{
int rc = 0;
cFYI(1, ("In cifs d_delete, name = %s\n", direntry->d_name.name));
cFYI(1, ("In cifs d_delete, name = %s", direntry->d_name.name));
return rc;
} */
......
......@@ -25,6 +25,7 @@
#include <linux/fcntl.h>
#include <linux/version.h>
#include <linux/pagemap.h>
#include <linux/pagevec.h>
#include <linux/smp_lock.h>
#include <asm/div64.h>
#include "cifsfs.h"
......@@ -85,9 +86,11 @@ cifs_open(struct inode *inode, struct file *file)
if (file->f_flags & O_CREAT)
disposition = FILE_OVERWRITE;
/* BB first check if file has batch oplock (or oplock ?) */
/* BB finish adding in oplock support BB */
if (oplockEnabled)
oplock = TRUE;
oplock = REQ_OPLOCK;
else
oplock = FALSE;
......@@ -95,8 +98,8 @@ cifs_open(struct inode *inode, struct file *file)
rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
CREATE_NOT_DIR, &netfid, &oplock, cifs_sb->local_nls);
if (rc) {
cFYI(1, ("\ncifs_open returned 0x%x ", rc));
cFYI(1, (" oplock: %d ", oplock));
cFYI(1, ("cifs_open returned 0x%x ", rc));
cFYI(1, ("oplock: %d ", oplock));
} else {
file->private_data =
kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
......@@ -142,9 +145,7 @@ cifs_close(struct inode *inode, struct file *file)
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
struct cifsFileInfo *pSMBFile =
(struct cifsFileInfo *) file->private_data;
cFYI(1, ("\n inode = 0x%p with ", inode));
(struct cifsFileInfo *) file->private_data;
xid = GetXid();
......@@ -172,12 +173,12 @@ cifs_closedir(struct inode *inode, struct file *file)
struct cifsFileInfo *pSMBFileStruct =
(struct cifsFileInfo *) file->private_data;
cFYI(1, ("\nClosedir inode = 0x%p with ", inode));
cFYI(1, ("Closedir inode = 0x%p with ", inode));
xid = GetXid();
if (pSMBFileStruct) {
cFYI(1, ("\nFreeing private data in close dir"));
cFYI(1, ("Freeing private data in close dir"));
kfree(file->private_data);
file->private_data = NULL;
}
......@@ -202,42 +203,42 @@ cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
xid = GetXid();
cFYI(1,
("\nLock parm: 0x%x flockflags: 0x%x flocktype: 0x%x start: %lld end: %lld",
("Lock parm: 0x%x flockflags: 0x%x flocktype: 0x%x start: %lld end: %lld",
cmd, pfLock->fl_flags, pfLock->fl_type, pfLock->fl_start,
pfLock->fl_end));
if (pfLock->fl_flags & FL_POSIX)
cFYI(1, ("\nPosix "));
cFYI(1, ("Posix "));
if (pfLock->fl_flags & FL_FLOCK)
cFYI(1, ("\nFlock "));
cFYI(1, ("Flock "));
if (pfLock->fl_flags & FL_SLEEP)
cFYI(1, ("\nBlocking lock "));
cFYI(1, ("Blocking lock "));
if (pfLock->fl_flags & FL_ACCESS)
cFYI(1, ("\nProcess suspended by mandatory locking "));
cFYI(1, ("Process suspended by mandatory locking "));
if (pfLock->fl_flags & FL_LEASE)
cFYI(1, ("\nLease on file "));
cFYI(1, ("Lease on file "));
if (pfLock->fl_flags & 0xFFD0)
cFYI(1, ("\n Unknown lock flags "));
cFYI(1, ("Unknown lock flags "));
if (pfLock->fl_type == F_WRLCK) {
cFYI(1, ("\nF_WRLCK "));
cFYI(1, ("F_WRLCK "));
numLock = 1;
} else if (pfLock->fl_type == F_UNLCK) {
cFYI(1, ("\nF_UNLCK "));
cFYI(1, ("F_UNLCK "));
numUnlock = 1;
} else if (pfLock->fl_type == F_RDLCK) {
cFYI(1, ("\nF_RDLCK "));
cFYI(1, ("F_RDLCK "));
lockType |= LOCKING_ANDX_SHARED_LOCK;
numLock = 1;
} else if (pfLock->fl_type == F_EXLCK) {
cFYI(1, ("\nF_EXLCK "));
cFYI(1, ("F_EXLCK "));
numLock = 1;
} else if (pfLock->fl_type == F_SHLCK) {
cFYI(1, ("\nF_SHLCK "));
cFYI(1, ("F_SHLCK "));
lockType |= LOCKING_ANDX_SHARED_LOCK;
numLock = 1;
} else
cFYI(1, ("\nUnknown type of lock "));
cFYI(1, ("Unknown type of lock "));
cifs_sb = CIFS_SB(file->f_dentry->d_sb);
pTcon = cifs_sb->tcon;
......@@ -265,7 +266,7 @@ cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
pfLock->fl_type = F_UNLCK;
if (rc != 0)
cERROR(1,
("\nError unlocking previously locked range %d during test of lock ",
("Error unlocking previously locked range %d during test of lock ",
rc));
rc = 0;
......@@ -304,7 +305,7 @@ cifs_write(struct file * file, const char *write_data,
pTcon = cifs_sb->tcon;
/*cFYI(1,
(" write %d bytes to offset %lld of %s \n", write_size,
(" write %d bytes to offset %lld of %s", write_size,
*poffset, file->f_dentry->d_name.name)); */
if (file->private_data == NULL) {
......@@ -360,6 +361,7 @@ cifs_partialpagewrite(struct page *page,unsigned from, unsigned to)
struct inode *inode = page->mapping->host;
struct cifsInodeInfo *cifsInode;
struct cifsFileInfo *open_file = NULL;
struct list_head *tmp;
int xid;
xid = GetXid();
......@@ -381,32 +383,39 @@ cifs_partialpagewrite(struct page *page,unsigned from, unsigned to)
return -EFAULT;
}
if((to > PAGE_CACHE_SIZE) || (from > to))
offset += (loff_t)from;
write_data += from;
if((to > PAGE_CACHE_SIZE) || (from > to) || (offset > mapping->host->i_size)) {
FreeXid(xid);
return -EIO;
}
offset += (loff_t)from;
write_data += from;
/* check to make sure that we are not extending the file */
if(mapping->host->i_size - offset < (loff_t)to)
to = (unsigned)(mapping->host->i_size - offset);
cifsInode = CIFS_I(mapping->host);
if(!list_empty(&(cifsInode->openFileList))) {
open_file = list_entry(cifsInode->openFileList.next,
struct cifsFileInfo, flist);
list_for_each(tmp, &cifsInode->openFileList) {
open_file = list_entry(tmp,struct cifsFileInfo, flist);
/* We could check if file is open for writing first */
if(open_file->pfile)
if((open_file->pfile) &&
((open_file->pfile->f_flags & O_RDWR) ||
(open_file->pfile->f_flags & O_WRONLY))) {
bytes_written = cifs_write(open_file->pfile, write_data,
to-from, &offset);
/* Does mm or vfs already set times? */
inode->i_atime = inode->i_mtime = CURRENT_TIME;
if ((bytes_written > 0) && (offset)) {
rc = 0;
if (offset > inode->i_size)
inode->i_size = offset;
} else if(bytes_written < 0) {
rc = bytes_written;
inode->i_atime = inode->i_mtime = CURRENT_TIME;
if ((bytes_written > 0) && (offset)) {
rc = 0;
} else if(bytes_written < 0) {
rc = bytes_written;
}
}
mark_inode_dirty_sync(inode);
} else {
cFYI(1,("\nNo open files to get file handle from"));
}
if(open_file == NULL) {
cFYI(1,("No writeable filehandles for inode"));
rc = -EIO;
}
......@@ -414,6 +423,18 @@ cifs_partialpagewrite(struct page *page,unsigned from, unsigned to)
return rc;
}
static int
cifs_writepages(struct address_space *mapping, struct writeback_control *wbc)
{
int rc = -EFAULT;
int xid;
xid = GetXid();
/* call 16K write then Setpageuptodate */
FreeXid(xid);
return rc;
}
static int
cifs_writepage(struct page* page, struct writeback_control *wbc)
{
......@@ -421,9 +442,11 @@ cifs_writepage(struct page* page, struct writeback_control *wbc)
int xid;
xid = GetXid();
/* BB add check for wbc flags */
page_cache_get(page);
rc = cifs_partialpagewrite(page,0,PAGE_CACHE_SIZE);
/* insert call to SetPageToUpdate like function here? */
SetPageUptodate(page); /* BB add check for error and Clearuptodate? */
unlock_page(page);
page_cache_release(page);
FreeXid(xid);
......@@ -434,32 +457,47 @@ static int
cifs_commit_write(struct file *file, struct page *page, unsigned offset,
unsigned to)
{
int xid,rc;
int xid;
int rc = 0;
struct inode *inode = page->mapping->host;
loff_t position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
struct cifsFileInfo *open_file;
struct cifs_sb_info *cifs_sb;
xid = GetXid();
if(offset > to)
return -EIO;
rc = cifs_partialpagewrite(page,offset,to);
if (position > inode->i_size){
inode->i_size = position;
if (file->private_data == NULL) {
rc = -EBADF;
} else {
cifs_sb = CIFS_SB(inode->i_sb);
open_file = (struct cifsFileInfo *)file->private_data;
rc = CIFSSMBSetFileSize(xid, cifs_sb->tcon, position,
open_file->netfid,open_file->pid,FALSE);
cFYI(1,(" SetEOF (commit write) rc = %d",rc));
}
}
set_page_dirty(page);
FreeXid(xid);
return rc;
}
static int
cifs_prepare_write(struct file *file, struct page *page, unsigned offset,
unsigned to)
{
return 0; /* eventually add code to flush any incompatible requests */
}
int
cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
{
int xid;
int rc = 0;
struct inode * inode = file->f_dentry->d_inode;
xid = GetXid();
/* BB fill in code to flush write behind buffers - when we start supporting oplock */
cFYI(1, (" name: %s datasync: 0x%x ", dentry->d_name.name, datasync));
cFYI(1, ("Sync file - name: %s datasync: 0x%x ",
dentry->d_name.name, datasync));
rc = filemap_fdatawrite(inode->i_mapping);
FreeXid(xid);
return rc;
}
......@@ -473,6 +511,7 @@ cifs_sync_page(struct page *page)
unsigned int rpages = 0;
int rc = 0;
cFYI(1,("sync page %p",page));
mapping = page->mapping;
if (!mapping)
return 0;
......@@ -483,13 +522,39 @@ cifs_sync_page(struct page *page)
/* fill in rpages then
result = cifs_pagein_inode(inode, index, rpages); *//* BB finish */
cFYI(1, ("\nrpages is %d for sync page of Index %ld ", rpages, index));
cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index));
if (rc < 0)
return rc;
return 0;
}
/*
* As file closes, flush all cached write data for this inode checking
* for write behind errors.
*
*/
int cifs_flush(struct file *file)
{
struct inode * inode = file->f_dentry->d_inode;
int rc = 0;
/* Rather than do the steps manually: */
/* lock the inode for writing */
/* loop through pages looking for write behind data (dirty pages) */
/* coalesce into contiguous 16K (or smaller) chunks to write to server */
/* send to server (prefer in parallel) */
/* deal with writebehind errors */
/* unlock inode for writing */
/* filemapfdatawrite appears easier for the time being */
rc = filemap_fdatawrite(inode->i_mapping);
cFYI(1,("Flush inode %p file %p rc %d",inode,file,rc));
return rc;
}
ssize_t
cifs_read(struct file * file, char *read_data, size_t read_size,
loff_t * poffset)
......@@ -500,6 +565,7 @@ cifs_read(struct file * file, char *read_data, size_t read_size,
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
int xid;
char * current_offset;
xid = GetXid();
cifs_sb = CIFS_SB(file->f_dentry->d_sb);
......@@ -510,12 +576,13 @@ cifs_read(struct file * file, char *read_data, size_t read_size,
return -EBADF;
}
for (total_read = 0; read_size > total_read; total_read += bytes_read) {
for (total_read = 0,current_offset=read_data; read_size > total_read;
total_read += bytes_read,current_offset+=bytes_read) {
rc = CIFSSMBRead(xid, pTcon,
((struct cifsFileInfo *) file->
private_data)->netfid,
read_size - total_read, *poffset,
&bytes_read, read_data + total_read);
&bytes_read, &current_offset);
if (rc || (bytes_read == 0)) {
if (total_read) {
break;
......@@ -531,8 +598,7 @@ cifs_read(struct file * file, char *read_data, size_t read_size,
return total_read;
}
int
cifs_file_mmap(struct file * file, struct vm_area_struct * vma)
int cifs_file_mmap(struct file * file, struct vm_area_struct * vma)
{
struct dentry * dentry = file->f_dentry;
int rc, xid;
......@@ -540,7 +606,7 @@ cifs_file_mmap(struct file * file, struct vm_area_struct * vma)
xid = GetXid();
rc = cifs_revalidate(dentry);
if (rc) {
cFYI(1,("Validation prior to mmap failed, error=%d\n", rc));
cFYI(1,("Validation prior to mmap failed, error=%d", rc));
FreeXid(xid);
return rc;
}
......@@ -549,34 +615,157 @@ cifs_file_mmap(struct file * file, struct vm_area_struct * vma)
return rc;
}
static void cifs_copy_cache_pages(struct address_space *mapping,
struct list_head *pages, int bytes_read,
char *data,struct pagevec * plru_pvec)
{
struct page *page;
char * target;
while (bytes_read > 0) {
if(list_empty(pages))
break;
page = list_entry(pages->prev, struct page, list);
list_del(&page->list);
if (add_to_page_cache(page, mapping, page->index, GFP_KERNEL)) {
page_cache_release(page);
cFYI(1,("Add page cache failed"));
continue;
}
page_cache_get(page);
target = kmap(page);
if(PAGE_CACHE_SIZE > bytes_read) {
memcpy(target,data,bytes_read);
bytes_read = 0;
} else {
memcpy(target,data,PAGE_CACHE_SIZE);
bytes_read -= PAGE_CACHE_SIZE;
}
if (!pagevec_add(plru_pvec, page))
__pagevec_lru_add(plru_pvec);
flush_dcache_page(page);
SetPageUptodate(page);
kunmap(page);
unlock_page(page);
page_cache_release(page);
data += PAGE_CACHE_SIZE;
}
return;
}
static int
cifs_readpages(struct file *file, struct address_space *mapping,
struct list_head *page_list, unsigned num_pages)
{
int rc = -EACCES;
int xid,i;
loff_t offset;
struct page * page;
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
int bytes_read = 0;
unsigned int read_size;
char * smb_read_data = 0;
struct smb_com_read_rsp * pSMBr;
struct pagevec lru_pvec;
xid = GetXid();
if (file->private_data == NULL) {
FreeXid(xid);
return -EBADF;
}
cifs_sb = CIFS_SB(file->f_dentry->d_sb);
pTcon = cifs_sb->tcon;
pagevec_init(&lru_pvec, 0);
for(i = 0;i<num_pages;) {
if(list_empty(page_list)) {
break;
}
page = list_entry(page_list->prev, struct page, list);
offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
/* for reads over a certain size could initiate async read ahead */
cFYI(0,("Read %d pages into cache at offset %ld ",
num_pages-i, (unsigned long) offset));
read_size = (num_pages - i) * PAGE_CACHE_SIZE;
rc = CIFSSMBRead(xid, pTcon,
((struct cifsFileInfo *) file->
private_data)->netfid,
read_size, offset,
&bytes_read, &smb_read_data);
if ((rc < 0) || (smb_read_data == NULL)) {
cFYI(1,("Read error in readpages: %d",rc));
/* clean up remaing pages off list */
while (!list_empty(page_list) && (i < num_pages)) {
page = list_entry(page_list->prev, struct page, list);
list_del(&page->list);
}
break;
} else if (bytes_read > 0){
pSMBr = (struct smb_com_read_rsp *)smb_read_data;
cifs_copy_cache_pages(mapping, page_list, bytes_read,
smb_read_data + 4 /* RFC1000 hdr */ +
le16_to_cpu(pSMBr->DataOffset), &lru_pvec);
i += bytes_read >> PAGE_CACHE_SHIFT;
if((bytes_read & PAGE_CACHE_MASK) != bytes_read) {
cFYI(1,("Partial page %d of %d read to cache",i++,num_pages));
break;
}
} else {
cFYI(1,("No bytes read"));
break;
}
if(smb_read_data) {
buf_release(smb_read_data);
smb_read_data = 0;
}
bytes_read = 0;
}
pagevec_lru_add(&lru_pvec);
FreeXid(xid);
return rc;
}
static int
cifs_readpage(struct file *file, struct page *page)
{
loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
char * read_data;
int rc = -EACCES;
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
int xid;
xid = GetXid();
cifs_sb = CIFS_SB(file->f_dentry->d_sb);
pTcon = cifs_sb->tcon;
if (file->private_data == NULL) {
FreeXid(xid);
return -EBADF;
}
cFYI(0,("readpage %p at offset %d 0x%x\n",page,(int)offset,(int)offset));
page_cache_get(page);
read_data = kmap(page);
/* for reads over a certain size we could initiate async read ahead */
/* for reads over a certain size could initiate async read ahead */
rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, &offset);
if (rc < 0)
goto io_error;
else {
cFYI(1,("\nBytes read %d ",rc));
cFYI(1,("Bytes read %d ",rc));
}
file->f_dentry->d_inode->i_atime = CURRENT_TIME;
......@@ -610,38 +799,41 @@ fill_in_inode(struct inode *tmp_inode,
cifsInfo->time = jiffies;
atomic_inc(&cifsInfo->inUse); /* inc on every refresh of inode info */
/* Linux can not store file creation time unfortunately so we ignore it */
/* Linux can not store file creation time unfortunately so ignore it */
tmp_inode->i_atime =
cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
tmp_inode->i_mtime =
cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
tmp_inode->i_ctime =
cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
/* should we treat the dos attribute of read-only as read-only mode bit e.g. 555 */
tmp_inode->i_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP); /* 2767 perms - indicate mandatory locking */
/* treat dos attribute of read-only as read-only mode bit e.g. 555? */
/* 2767 perms - indicate mandatory locking */
tmp_inode->i_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
cFYI(0,
("\nCIFS FFIRST: Attributes came in as 0x%x",
("CIFS FFIRST: Attributes came in as 0x%x",
pfindData->ExtFileAttributes));
if (pfindData->ExtFileAttributes & ATTR_REPARSE) {
*pobject_type = DT_LNK;
tmp_inode->i_mode |= S_IFLNK; /* BB can this and S_IFREG or S_IFDIR be set at same time as in Windows? */
/* BB can this and S_IFREG or S_IFDIR be set as in Windows? */
tmp_inode->i_mode |= S_IFLNK;
} else if (pfindData->ExtFileAttributes & ATTR_DIRECTORY) {
*pobject_type = DT_DIR;
tmp_inode->i_mode = S_IRWXUGO; /* override default perms since we do not lock dirs */
/* override default perms since we do not lock dirs */
tmp_inode->i_mode = S_IRWXUGO;
tmp_inode->i_mode |= S_IFDIR;
} else {
*pobject_type = DT_REG;
tmp_inode->i_mode |= S_IFREG;
}/* could add code here - to validate if device or weird share type? */
/* can not fill in nlink here as in qpathinfo version and in Unx search */
/* can not fill in nlink here as in qpathinfo version and Unx search */
tmp_inode->i_size = pfindData->EndOfFile;
tmp_inode->i_blocks =
do_div(pfindData->AllocationSize, tmp_inode->i_blksize);
if (pfindData->AllocationSize < pfindData->EndOfFile)
cFYI(1, ("\nServer inconsistency Error: it says allocation size less than end of file "));
cFYI(1, ("Possible sparse file: allocation size less than end of file "));
cFYI(1,
("\nCIFS FFIRST: Size %ld and blocks %ld and blocksize %ld",
("File Size %ld and blocks %ld and blocksize %ld",
(unsigned long) tmp_inode->i_size, tmp_inode->i_blocks,
tmp_inode->i_blksize));
if (S_ISREG(tmp_inode->i_mode)) {
......@@ -657,7 +849,7 @@ fill_in_inode(struct inode *tmp_inode,
cFYI(1, (" Symbolic Link inode "));
tmp_inode->i_op = &cifs_symlink_inode_ops;
} else {
cFYI(1, ("\nInit special inode "));
cFYI(1, (" Init special inode "));
init_special_inode(tmp_inode, tmp_inode->i_mode,
kdev_t_to_nr(tmp_inode->i_rdev));
}
......@@ -726,7 +918,7 @@ unix_fill_in_inode(struct inode *tmp_inode,
tmp_inode->i_op = &cifs_symlink_inode_ops;
/* tmp_inode->i_fop = *//* do not need to set to anything */
} else {
cFYI(1, ("\nInit special inode "));
cFYI(1, (" Init special inode "));
init_special_inode(tmp_inode, tmp_inode->i_mode,
kdev_t_to_nr(tmp_inode->i_rdev));
}
......@@ -740,22 +932,21 @@ construct_dentry(struct qstr *qstring, struct file *file,
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
cFYI(1, ("\nFor %s ", qstring->name));
cFYI(1, ("For %s ", qstring->name));
cifs_sb = CIFS_SB(file->f_dentry->d_sb);
pTcon = cifs_sb->tcon;
qstring->hash = full_name_hash(qstring->name, qstring->len);
tmp_dentry = d_lookup(file->f_dentry, qstring);
if (tmp_dentry) {
cFYI(1, (" existing dentry with inode 0x%p ", tmp_dentry->d_inode)); /* BB remove */
cFYI(0, (" existing dentry with inode 0x%p", tmp_dentry->d_inode));
*ptmp_inode = tmp_dentry->d_inode;
/* BB overwrite the old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len ?? */
} else {
tmp_dentry = d_alloc(file->f_dentry, qstring);
*ptmp_inode = new_inode(file->f_dentry->d_sb);
cFYI(1, ("\nAlloc new inode %p ", *ptmp_inode));
tmp_dentry->d_op = &cifs_dentry_ops;
cFYI(1, (" instantiate dentry 0x%p with inode 0x%p ",
cFYI(0, (" instantiate dentry 0x%p with inode 0x%p ",
tmp_dentry, *ptmp_inode));
d_instantiate(tmp_dentry, *ptmp_inode);
d_rehash(tmp_dentry);
......@@ -763,8 +954,8 @@ construct_dentry(struct qstr *qstring, struct file *file,
tmp_dentry->d_time = jiffies;
(*ptmp_inode)->i_blksize =
(pTcon->ses->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;
cFYI(1, ("\ni_blksize = %ld", (*ptmp_inode)->i_blksize));
(pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;
cFYI(1, ("i_blksize = %ld", (*ptmp_inode)->i_blksize));
*pnew_dentry = tmp_dentry;
}
......@@ -836,14 +1027,14 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
full_path = build_wildcard_path_from_dentry(file->f_dentry);
cFYI(1, ("\nFull path: %s start at: %lld ", full_path, file->f_pos));
cFYI(1, ("Full path: %s start at: %lld ", full_path, file->f_pos));
switch ((int) file->f_pos) {
case 0:
if (filldir
(direntry, ".", 1, file->f_pos,
file->f_dentry->d_inode->i_ino, DT_DIR) < 0) {
cERROR(1, ("\nFilldir for current dir failed "));
cERROR(1, ("Filldir for current dir failed "));
break;
}
file->f_pos++;
......@@ -852,7 +1043,7 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
if (filldir
(direntry, "..", 2, file->f_pos,
file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
cERROR(1, ("\nFilldir for parent dir failed "));
cERROR(1, ("Filldir for parent dir failed "));
break;
}
file->f_pos++;
......@@ -957,13 +1148,13 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
if (file->private_data == NULL) {
rc = -EBADF;
cFYI(1,
("\nReaddir on closed srch, pos = %lld",
("Readdir on closed srch, pos = %lld",
file->f_pos));
} else {
cifsFile = (struct cifsFileInfo *) file->private_data;
if (cifsFile->endOfSearch) {
rc = 0;
cFYI(1, ("\nEnd of search "));
cFYI(1, ("End of search "));
break;
}
searchHandle = cifsFile->netfid;
......@@ -1077,17 +1268,28 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
struct address_space_operations cifs_addr_ops = {
.readpage = cifs_readpage,
.readpages = cifs_readpages,
.writepage = cifs_writepage,
.prepare_write = cifs_prepare_write,
.prepare_write = simple_prepare_write,
.commit_write = cifs_commit_write,
/* .sync_page = cifs_sync_page, */
.sync_page = cifs_sync_page,
};
/* change over to struct below when sync page tested and complete */
struct address_space_operations cifs_addr_ops2 = {
struct address_space_operations cifs_addr_ops_writethrough = {
.readpage = cifs_readpage,
.readpages = cifs_readpages,
.writepage = cifs_writepage,
.prepare_write = cifs_prepare_write,
.prepare_write = simple_prepare_write,
.commit_write = cifs_commit_write,
.sync_page = cifs_sync_page,
};
struct address_space_operations cifs_addr_ops_nocache = {
.readpage = cifs_readpage,
.readpages = cifs_readpages,
.writepage = cifs_writepage,
.prepare_write = simple_prepare_write,
.commit_write = cifs_commit_write,
.sync_page = cifs_sync_page,
};
......@@ -19,6 +19,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/fs.h>
#include <linux/buffer_head.h>
#include <linux/stat.h>
#include <asm/div64.h>
#include "cifsfs.h"
......@@ -44,7 +45,7 @@ cifs_get_inode_info_unix(struct inode **pinode,
xid = GetXid();
pTcon = cifs_sb->tcon;
cFYI(1, ("\nGetting info on %s ", search_path));
cFYI(1, (" Getting info on %s ", search_path));
/* we could have done a find first instead but this returns more info */
rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData,
cifs_sb->local_nls);
......@@ -85,7 +86,7 @@ cifs_get_inode_info_unix(struct inode **pinode,
/* get new inode */
if (*pinode == NULL) {
*pinode = new_inode(sb);
cFYI(1, ("\nAlloc new inode %p ", *pinode));
cFYI(1, (" Alloc new inode %p ", *pinode));
}
inode = *pinode;
/* new_inode = iget(parent_dir_inode->i_sb, findData.IndexNumber); */
......@@ -93,7 +94,7 @@ cifs_get_inode_info_unix(struct inode **pinode,
cifsInfo = CIFS_I(inode);
cFYI(1, ("\nOld time %ld ", cifsInfo->time));
cFYI(1, (" Old time %ld ", cifsInfo->time));
cifsInfo->time = jiffies;
cFYI(1, (" New time %ld ", cifsInfo->time));
atomic_inc(&cifsInfo->inUse); /* inc on every refresh of inode */
......@@ -129,12 +130,12 @@ cifs_get_inode_info_unix(struct inode **pinode,
findData.EndOfFile = le64_to_cpu(findData.EndOfFile);
inode->i_size = findData.EndOfFile;
inode->i_blksize =
(pTcon->ses->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;
(pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;
inode->i_blocks = do_div(findData.NumOfBytes, inode->i_blksize);
if (findData.NumOfBytes < findData.EndOfFile)
cFYI(1, ("\nServer inconsistency Error: it says allocation size less than end of file "));
cFYI(1, ("Server inconsistency Error: it says allocation size less than end of file "));
cFYI(1,
("\nCIFS FFIRST: Size %ld and blocks %ld ",
("Size %ld and blocks %ld ",
(unsigned long) inode->i_size, inode->i_blocks));
if (S_ISREG(inode->i_mode)) {
cFYI(1, (" File inode "));
......@@ -150,7 +151,7 @@ cifs_get_inode_info_unix(struct inode **pinode,
inode->i_op = &cifs_symlink_inode_ops;
/* tmp_inode->i_fop = *//* do not need to set to anything */
} else {
cFYI(1, ("\nInit special inode "));
cFYI(1, (" Init special inode "));
init_special_inode(inode, inode->i_mode,
kdev_t_to_nr(inode->i_rdev));
}
......@@ -174,7 +175,7 @@ cifs_get_inode_info(struct inode **pinode,
xid = GetXid();
pTcon = cifs_sb->tcon;
cFYI(1, ("\nGetting info on %s ", search_path));
cFYI(1, (" Getting info on %s ", search_path));
/* we could have done a find first instead but this returns more info */
rc = CIFSSMBQPathInfo(xid, pTcon, search_path, &findData,
cifs_sb->local_nls);
......@@ -214,20 +215,20 @@ cifs_get_inode_info(struct inode **pinode,
/* get new inode */
if (*pinode == NULL) {
*pinode = new_inode(sb);
cFYI(1, ("\nAlloc new inode %p ", *pinode));
cFYI(1, (" Alloc new inode %p ", *pinode));
}
inode = *pinode;
cifsInfo = CIFS_I(inode);
findData.Attributes = le32_to_cpu(findData.Attributes);
cifsInfo->cifsAttrs = findData.Attributes;
cFYI(1, ("\nOld time %ld ", cifsInfo->time));
cFYI(1, (" Old time %ld ", cifsInfo->time));
cifsInfo->time = jiffies;
cFYI(1, (" New time %ld ", cifsInfo->time));
atomic_inc(&cifsInfo->inUse); /* inc on every refresh of inode */
inode->i_blksize =
(pTcon->ses->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;
(pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;
/* Linux can not store file creation time unfortunately so we ignore it */
inode->i_atime =
cifs_NTtimeToUnix(le64_to_cpu(findData.LastAccessTime));
......@@ -239,7 +240,7 @@ cifs_get_inode_info(struct inode **pinode,
/* should we treat the dos attribute of read-only as read-only mode bit e.g. 555 */
inode->i_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP); /* 2767 perms indicate mandatory locking - will override for dirs later */
cFYI(0,
("\nAttributes came in as 0x%x\n", findData.Attributes));
(" Attributes came in as 0x%x ", findData.Attributes));
if (findData.Attributes & ATTR_REPARSE) {
/* Can IFLNK be set as it basically is on windows with IFREG or IFDIR? */
inode->i_mode |= S_IFLNK;
......@@ -256,7 +257,7 @@ cifs_get_inode_info(struct inode **pinode,
inode->i_blocks =
do_div(findData.AllocationSize, inode->i_blksize);
cFYI(1,
("\n Size %ld and blocks %ld ",
(" Size %ld and blocks %ld ",
(unsigned long) inode->i_size, inode->i_blocks));
inode->i_nlink = le32_to_cpu(findData.NumberOfLinks);
......@@ -307,7 +308,7 @@ cifs_unlink(struct inode *inode, struct dentry *direntry)
char *full_path = NULL;
struct cifsInodeInfo *cifsInode;
cFYI(1, ("\n cifs_unlink, inode = 0x%p with ", inode));
cFYI(1, (" cifs_unlink, inode = 0x%p with ", inode));
xid = GetXid();
......@@ -356,7 +357,7 @@ cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
char *full_path = NULL;
struct inode *newinode = NULL;
cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p\n", mode, inode));
cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p ", mode, inode));
xid = GetXid();
......@@ -367,7 +368,7 @@ cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
/* BB add setting the equivalent of mode via CreateX w/ACLs */
rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls);
if (rc) {
cFYI(1, ("\ncifs_mkdir returned 0x%x ", rc));
cFYI(1, ("cifs_mkdir returned 0x%x ", rc));
} else {
inode->i_nlink++;
if (pTcon->ses->capabilities & CAP_UNIX)
......@@ -407,7 +408,7 @@ cifs_rmdir(struct inode *inode, struct dentry *direntry)
char *full_path = NULL;
struct cifsInodeInfo *cifsInode;
cFYI(1, ("\nn cifs_rmdir, inode = 0x%p with ", inode));
cFYI(1, (" cifs_rmdir, inode = 0x%p with ", inode));
xid = GetXid();
......@@ -493,7 +494,7 @@ cifs_revalidate(struct dentry *direntry)
full_path = build_path_from_dentry(direntry);
cFYI(1,
(" full path: %s for inode 0x%p with count %d dentry: 0x%p d_time %ld at time %ld \n",
(" full path: %s for inode 0x%p with count %d dentry: 0x%p d_time %ld at time %ld ",
full_path, direntry->d_inode,
direntry->d_inode->i_count.counter, direntry,
direntry->d_time, jiffies));
......@@ -562,7 +563,7 @@ cifs_truncate_file(struct inode *inode)
full_path = build_path_from_dentry(dirent);
rc = CIFSSMBSetEOF(xid, pTcon, full_path, inode->i_size,FALSE,
cifs_sb->local_nls);
cFYI(1,("\nSetEOF (truncate) rc = %d",rc));
cFYI(1,(" SetEOF (truncate) rc = %d",rc));
if(rc == -ETXTBSY) {
cifsInode = CIFS_I(inode);
if(!list_empty(&(cifsInode->openFileList))) {
......@@ -572,7 +573,7 @@ cifs_truncate_file(struct inode *inode)
rc = CIFSSMBSetFileSize(xid, pTcon, inode->i_size,
open_file->netfid,open_file->pid,FALSE);
} else {
cFYI(1,("\nNo open files to get file handle from"));
cFYI(1,(" No open files to get file handle from"));
}
}
if (!rc)
......@@ -604,7 +605,7 @@ cifs_setattr(struct dentry *direntry, struct iattr *attrs)
xid = GetXid();
cFYI(1,
("\nIn cifs_setattr, name = %s attrs->iavalid 0x%x\n",
(" In cifs_setattr, name = %s attrs->iavalid 0x%x ",
direntry->d_name.name, attrs->ia_valid));
cifs_sb = CIFS_SB(direntry->d_inode->i_sb);
pTcon = cifs_sb->tcon;
......@@ -614,12 +615,12 @@ cifs_setattr(struct dentry *direntry, struct iattr *attrs)
/* BB check if we need to refresh inode from server now ? BB */
cFYI(1, ("\nChanging attributes 0x%x", attrs->ia_valid));
cFYI(1, (" Changing attributes 0x%x", attrs->ia_valid));
if (attrs->ia_valid & ATTR_SIZE) {
rc = CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size,FALSE,
cifs_sb->local_nls);
cFYI(1,("\nSetEOF (setattrs) rc = %d",rc));
cFYI(1,(" SetEOF (setattrs) rc = %d",rc));
if(rc == -ETXTBSY) {
if(!list_empty(&(cifsInode->openFileList))) {
......@@ -629,29 +630,30 @@ cifs_setattr(struct dentry *direntry, struct iattr *attrs)
rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size,
open_file->netfid,open_file->pid,FALSE);
} else {
cFYI(1,("\nNo open files to get file handle from"));
cFYI(1,(" No open files to get file handle from"));
}
}
/* Set Allocation Size of file - might not even need to call the
following but might as well and it does not hurt if it fails */
CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, TRUE, cifs_sb->local_nls);
if (rc == 0)
vmtruncate(direntry->d_inode, attrs->ia_size);
/* BB add special case to handle sharing violation (due to Samba bug)
by calling SetFileInfo to set the sizes */
/* For Allocation Size - do not need to call the following
it did not hurt if it fails but why bother */
/* CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, TRUE, cifs_sb->local_nls);*/
if (rc == 0) {
rc = vmtruncate(direntry->d_inode, attrs->ia_size);
nobh_truncate_page(direntry->d_inode->i_mapping, direntry->d_inode->i_size);
/* cFYI(1,("truncate_page to 0x%lx \n",direntry->d_inode->i_size)); */
}
}
if (attrs->ia_valid & ATTR_UID) {
cFYI(1, ("\nCIFS - UID changed to %d", attrs->ia_uid));
cFYI(1, (" CIFS - UID changed to %d", attrs->ia_uid));
uid = attrs->ia_uid;
/* entry->uid = cpu_to_le16(attr->ia_uid); */
}
if (attrs->ia_valid & ATTR_GID) {
cFYI(1, ("\nCIFS - GID changed to %d", attrs->ia_gid));
cFYI(1, (" CIFS - GID changed to %d", attrs->ia_gid));
gid = attrs->ia_gid;
/* entry->gid = cpu_to_le16(attr->ia_gid); */
}
if (attrs->ia_valid & ATTR_MODE) {
cFYI(1, ("\nCIFS - Mode changed to 0x%x", attrs->ia_mode));
cFYI(1, (" CIFS - Mode changed to 0x%x", attrs->ia_mode));
mode = attrs->ia_mode;
/* entry->mode = cpu_to_le16(attr->ia_mode); */
}
......@@ -680,7 +682,7 @@ cifs_setattr(struct dentry *direntry, struct iattr *attrs)
if (attrs->ia_valid & ATTR_CTIME) {
set_time = TRUE;
cFYI(1, ("\nCIFS - CTIME changed ")); /* BB probably do not need */
cFYI(1, (" CIFS - CTIME changed ")); /* BB probably do not need */
time_buf.ChangeTime =
cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
} else
......@@ -695,7 +697,7 @@ cifs_setattr(struct dentry *direntry, struct iattr *attrs)
rc = CIFSSMBSetTimes(xid, pTcon, full_path, &time_buf,
cifs_sb->local_nls);
}
cifsInode->time = 0; /* force revalidate to get attributes when needed */
/* cifsInode->time = 0; */ /* force revalidate to get attributes when needed */
if (full_path)
kfree(full_path);
......@@ -707,7 +709,7 @@ void
cifs_delete_inode(struct inode *inode)
{
/* Note: called without the big kernel filelock - remember spinlocks! */
cFYI(1, ("In cifs_delete_inode, inode = 0x%p\n", inode));
cFYI(1, ("In cifs_delete_inode, inode = 0x%p ", inode));
/* may have to add back in when safe distributed caching of
directories via e.g. FindNotify added */
}
......@@ -88,7 +88,7 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
xid = GetXid();
full_path = build_path_from_dentry(direntry);
cFYI(1, ("\nFull path: %s inode = 0x%p\n", full_path, inode));
cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode));
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
......@@ -136,8 +136,8 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry);
cFYI(1, ("\nFull path: %s ", full_path));
cFYI(1, (" symname is %s\n", symname));
cFYI(1, ("Full path: %s ", full_path));
cFYI(1, ("symname is %s", symname));
/* BB what if DFS and this volume is on different share? BB */
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
......@@ -156,7 +156,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
if (rc != 0) {
cFYI(1,
("\nCreate symlink worked but get_inode_info failed with rc = %d ",
("Create symlink worked but get_inode_info failed with rc = %d ",
rc));
} else {
direntry->d_op = &cifs_dentry_ops;
......@@ -188,7 +188,7 @@ cifs_readlink(struct dentry *direntry, char *pBuffer, int buflen)
pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry);
cFYI(1,
("\nFull path: %s inode = 0x%p pBuffer = 0x%p buflen = %d\n",
("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d",
full_path, inode, pBuffer, buflen));
/* BB add read reparse point symlink code and Unix extensions symlink code here BB */
......
......@@ -81,7 +81,7 @@ void
sesInfoFree(struct cifsSesInfo *buf_to_free)
{
if (buf_to_free == NULL) {
cFYI(1, ("\nNull buffer passed to sesInfoFree"));
cFYI(1, ("Null buffer passed to sesInfoFree"));
return;
}
......@@ -122,7 +122,7 @@ void
tconInfoFree(struct cifsTconInfo *buf_to_free)
{
if (buf_to_free == NULL) {
cFYI(1, ("\nNull buffer passed to tconInfoFree"));
cFYI(1, ("Null buffer passed to tconInfoFree"));
return;
}
write_lock(&GlobalSMBSeslock);
......@@ -169,7 +169,7 @@ buf_release(void *buf_to_free)
{
if (buf_to_free == NULL) {
cFYI(1, ("\nNull buffer passed to buf_release"));
cFYI(1, ("Null buffer passed to buf_release"));
return;
}
kmem_cache_free(cifs_req_cachep, buf_to_free);
......@@ -225,8 +225,10 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
}
if (treeCon->Flags & SMB_SHARE_IS_IN_DFS)
buffer->Flags2 |= SMBFLG2_DFS;
if(treeCon->ses->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
if(treeCon->ses->server)
if(treeCon->ses->server->secMode &
(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
}
/* endian conversion of flags is now done just before sending */
......@@ -248,17 +250,17 @@ checkSMBhdr(struct smb_hdr *smb, __u16 mid)
if(smb->Command == SMB_COM_LOCKING_ANDX)
return 0;
else
cERROR(1, ("\n Rcvd Request not response "));
cERROR(1, ("Rcvd Request not response "));
}
} else { /* bad signature or mid */
if (*(unsigned int *) smb->Protocol != cpu_to_le32(0x424d53ff))
cERROR(1,
("\nBad protocol string signature header %x ",
("Bad protocol string signature header %x ",
*(unsigned int *) smb->Protocol));
if (mid != smb->Mid)
cERROR(1, ("\n Mids do not match \n"));
cERROR(1, ("Mids do not match"));
}
cERROR(1, ("\nCIFS: bad smb detected. The Mid=%d\n", smb->Mid));
cERROR(1, ("bad smb detected. The Mid=%d", smb->Mid));
return 1;
}
......@@ -266,13 +268,13 @@ int
checkSMB(struct smb_hdr *smb, __u16 mid, int length)
{
cFYI(0,
("\nEntering checkSMB with Length: %x, smb_buf_length: %x ",
("Entering checkSMB with Length: %x, smb_buf_length: %x ",
length, ntohl(smb->smb_buf_length)));
if ((length < 2 + sizeof (struct smb_hdr))
|| (4 + ntohl(smb->smb_buf_length) >
CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE)) {
if (length < 2 + sizeof (struct smb_hdr)) {
cERROR(1, ("\n Length less than 2 + sizeof smb_hdr "));
cERROR(1, ("Length less than 2 + sizeof smb_hdr "));
if ((length >= sizeof (struct smb_hdr) - 1)
&& (smb->Status.CifsError != 0))
return 0; /* some error cases do not return wct and bcc */
......@@ -281,9 +283,9 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length)
if (4 + ntohl(smb->smb_buf_length) >
CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE)
cERROR(1,
("\n smb_buf_length greater than CIFS_MAX_MSGSIZE ... "));
("smb_buf_length greater than CIFS_MAX_MSGSIZE ... "));
cERROR(1,
("CIFS: bad smb detected. Illegal length. The mid=%d\n",
("bad smb detected. Illegal length. The mid=%d",
smb->Mid));
return 1;
}
......@@ -295,51 +297,62 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length)
|| (4 + ntohl(smb->smb_buf_length) != length)) {
return 0;
} else {
cERROR(1, ("\nCIFS: smbCalcSize %x ", smbCalcSize(smb)));
cERROR(1, ("smbCalcSize %x ", smbCalcSize(smb)));
cERROR(1,
("CIFS: bad smb size detected. The Mid=%d\n", smb->Mid));
("bad smb size detected. The Mid=%d", smb->Mid));
return 1;
}
}
int
is_valid_oplock_break(struct smb_hdr *buf)
{
struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)buf;
struct list_head *tmp;
struct cifsTconInfo *tcon;
/* could add check for smb response flag 0x80 */
cFYI(1,("\nChecking for oplock break"));
if(pSMB->hdr.Command != SMB_COM_LOCKING_ANDX)
return FALSE;
if(pSMB->hdr.Flags & SMBFLG_RESPONSE)
return FALSE; /* server sends us "request" here */
if(pSMB->hdr.WordCount != 8)
return FALSE;
cFYI(1,(" oplock type 0x%d level 0x%d",pSMB->LockType,pSMB->OplockLevel));
if(!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE))
return FALSE;
/* look up tcon based on tid & uid */
read_lock(&GlobalSMBSeslock);
list_for_each(tmp, &GlobalTreeConnectionList) {
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
if (tcon->tid == buf->Tid)
if(tcon->ses->Suid == buf->Uid) {
/* BB Add following logic:
2) look up inode from tcon->openFileList->file->f_dentry->d_inode
3) flush dirty pages and cached byte range locks and mark inode
4) depending on break type change to r/o caching or no caching
5) send oplock break response to server */
read_unlock(&GlobalSMBSeslock);
cFYI(1,("\nFound matching connection, process oplock break"));
return TRUE;
}
}
read_unlock(&GlobalSMBSeslock);
cFYI(1,("\nProcessing oplock break for non-existent connection"));
return TRUE;
struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)buf;
struct list_head *tmp;
struct list_head *tmp1;
struct cifsTconInfo *tcon;
struct cifsFileInfo *netfile;
/* could add check for smb response flag 0x80 */
cFYI(1,("Checking for oplock break"));
if(pSMB->hdr.Command != SMB_COM_LOCKING_ANDX)
return FALSE;
if(pSMB->hdr.Flags & SMBFLG_RESPONSE)
return FALSE; /* server sends us "request" here */
if(pSMB->hdr.WordCount != 8)
return FALSE;
cFYI(1,(" oplock type 0x%d level 0x%d",pSMB->LockType,pSMB->OplockLevel));
if(!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE))
return FALSE;
/* look up tcon based on tid & uid */
read_lock(&GlobalSMBSeslock);
list_for_each(tmp, &GlobalTreeConnectionList) {
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
if (tcon->tid == buf->Tid) {
list_for_each(tmp1,&tcon->openFileList){
netfile = list_entry(tmp1,struct cifsFileInfo,tlist);
if(pSMB->Fid == netfile->netfid) {
/* BB Add following logic:
2) look up inode from tcon->openFileList->file->f_dentry->d_inode
3) flush dirty pages and cached byte range locks and mark inode
4) depending on break type change to r/o caching or no caching
cifsinode->clientCanCacheAll = 0
5) inode->i_data.a_ops = &cifs_addr_ops_writethrough;
6) send oplock break response to server */
read_unlock(&GlobalSMBSeslock);
cFYI(1,("Matching file id, processing oplock break"));
return TRUE;
}
}
read_unlock(&GlobalSMBSeslock);
cFYI(1,("No matching file for oplock break on connection"));
return TRUE;
}
}
read_unlock(&GlobalSMBSeslock);
cFYI(1,("Can not process oplock break for non-existent connection"));
return TRUE;
}
void
......@@ -355,7 +368,7 @@ dump_smb(struct smb_hdr *smb_buf, int smb_buf_length)
buffer = (unsigned char *) smb_buf;
for (i = 0, j = 0; i < smb_buf_length; i++, j++) {
if (i % 8 == 0) { /* we have reached the beginning of line */
printk("\n| ");
printk(KERN_DEBUG "| ");
j = 0;
}
printk("%0#4x ", buffer[i]);
......@@ -367,7 +380,7 @@ dump_smb(struct smb_hdr *smb_buf, int smb_buf_length)
if (i % 8 == 7) { /* we have reached end of line, time to print ascii */
debug_line[16] = 0;
printk(" | %s", debug_line);
printk(" | %s\n", debug_line);
}
}
for (; j < 8; j++) {
......@@ -375,6 +388,6 @@ dump_smb(struct smb_hdr *smb_buf, int smb_buf_length)
debug_line[2 * j] = ' ';
debug_line[1 + (2 * j)] = ' ';
}
printk(" | %s\n", debug_line);
printk( " | %s\n", debug_line);
return;
}
......@@ -753,12 +753,11 @@ cifs_print_status(__u32 status_code)
{
int idx = 0;
printk("\nStatus code returned: 0x%08x ", status_code);
while (nt_errs[idx].nt_errstr != NULL) {
if (((nt_errs[idx].nt_errcode) & 0xFFFFFF) ==
(status_code & 0xFFFFFF)) {
printk(nt_errs[idx].nt_errstr);
printk(KERN_NOTICE "Status code returned 0x%08x %s\n",
status_code,nt_errs[idx].nt_errstr);
}
idx++;
}
......@@ -815,11 +814,8 @@ map_smb_to_linux_error(struct smb_hdr *smb)
}
/* old style errors */
cFYI(1, (" !!Mapping smb error code %d ", smberrcode));
/* DOS class smb error codes - map DOS */
/* BB special case reconnect tid and reconnect uid here? */
/* DOS class smb error codes - map DOS */
if (smberrclass == ERRDOS) { /* one byte field no need to byte reverse */
for (i = 0;
i <
......@@ -849,10 +845,7 @@ map_smb_to_linux_error(struct smb_hdr *smb)
}
/* else ERRHRD class errors or junk - return EIO */
/* BB get smb->error_class and code lookup in table if ERR_STATUS is not
set in this frame else translate newer NT Status code - in both cases
change to equivalent posix error BB */
cFYI(1, (" to POSIX err %d !!", rc));
cFYI(1, (" !!Mapping smb error code %d to POSIX err %d !!", smberrcode,rc));
/* generic corrective action e.g. reconnect SMB session on ERRbaduid could be added */
......
......@@ -305,7 +305,7 @@ make_oem_passwd_hash(char data[516], const char *passwd,
if (new_pw_len > 512) {
cERROR(1,
("CIFS make_oem_passwd_hash: new password is too long.\n"));
("CIFS make_oem_passwd_hash: new password is too long."));
return FALSE;
}
......
......@@ -40,10 +40,9 @@ AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
/* BB add spinlock to protect midq for each session BB */
if (ses == NULL) {
cERROR(1, ("\nNull session passed in to AllocMidQEntry "));
cERROR(1, ("Null session passed in to AllocMidQEntry "));
return NULL;
}
temp = kmalloc(sizeof (struct mid_q_entry), GFP_KERNEL);
temp = (struct mid_q_entry *) kmem_cache_alloc(cifs_mid_cachep,
SLAB_KERNEL);
if (temp == NULL)
......@@ -53,21 +52,19 @@ AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
temp->mid = smb_buffer->Mid; /* always LE */
temp->pid = current->pid;
temp->command = smb_buffer->Command;
cFYI(1, ("\nFor smb_command %d", temp->command));
cFYI(1, ("For smb_command %d", temp->command));
do_gettimeofday(&temp->when_sent);
temp->ses = ses;
temp->tsk = current;
}
if (ses->status == CifsGood) {
if (ses->server->tcpStatus == CifsGood) {
write_lock(&GlobalMid_Lock);
list_add_tail(&temp->qhead, &ses->server->pending_mid_q);
atomic_inc(&midCount);
temp->midState = MID_REQUEST_ALLOCATED;
write_unlock(&GlobalMid_Lock);
} else { /* BB add reconnect code here BB */
cERROR(1,
("\nNeed to reconnect after session died to server\n"));
} else { /* could add more reconnect code here BB */
cERROR(1,("Need to reconnect after session died to server"));
if (temp)
kmem_cache_free(cifs_mid_cachep, temp);
return NULL;
......@@ -121,7 +118,7 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
sign_smb(smb_buffer); */ /* BB enable when signing tested more */
smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
cFYI(1, ("\nSending smb of length %d ", smb_buf_length));
cFYI(1, ("Sending smb of length %d ", smb_buf_length));
dump_smb(smb_buffer, smb_buf_length + 4);
temp_fs = get_fs(); /* we must turn off socket api parm checking */
......@@ -132,7 +129,7 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
if (rc < 0) {
cERROR(1,
("\nError %d sending data on socket to server.\n", rc));
("Error %d sending data on socket to server.", rc));
} else
rc = 0;
......@@ -154,7 +151,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
return -EIO; /* reconnect should be done, if possible, in AllocMidQEntry */
if (in_buf->smb_buf_length > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE) {
cERROR(1,
("\nIllegal length, greater than maximum frame, %d ",
("Illegal length, greater than maximum frame, %d ",
in_buf->smb_buf_length));
DeleteMidQEntry(midQ);
return -EIO;
......@@ -163,27 +160,21 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
(struct sockaddr *) &(ses->server->sockAddr));
if (long_op > 1) /* writes past end of file can take a looooooong time */
if (long_op > 1) /* writes past end of file can take looooong time */
timeout = 300 * HZ;
else if (long_op == 1)
timeout = 60 * HZ;
else
timeout = 15 * HZ;
/* wait for 15 seconds or until woken up due to response arriving or due to
last connection to this server being unmounted */
/* timeout = interruptible_sleep_on_timeout(&ses->server->response_q,timeout); */
/* Replace above line with wait_event to get rid of sleep_on per lk guidelines */
/* wait for 15 seconds or until woken up due to response arriving or
due to last connection to this server being unmounted */
timeout = wait_event_interruptible_timeout(ses->server->response_q,
midQ->
midState & MID_RESPONSE_RECEIVED,
timeout);
cFYI(1,
(" with timeout %ld and Out_buf: %p midQ->resp_buf: %p ", timeout,
out_buf, midQ->resp_buf));
if (signal_pending(current)) {
cERROR(1, (KERN_ERR "\nCIFS: caught signal"));
cERROR(1, ("CIFS: caught signal"));
DeleteMidQEntry(midQ);
return -EINTR;
} else {
......@@ -198,11 +189,11 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
if (timeout == 0) {
cFYI(1,
("\nTimeout on receive. Assume response SMB is invalid.\n"));
("Timeout on receive. Assume response SMB is invalid."));
rc = -ETIMEDOUT;
} else if (receive_len > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE) {
cERROR(1,
("\nFrame too large received. Length: %d Xid: %d\n",
("Frame too large received. Length: %d Xid: %d",
receive_len, xid));
rc = -EIO;
} else { /* rcvd frame is ok */
......@@ -215,7 +206,6 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
/* convert the length back to a form that we can use */
dump_smb(out_buf, 92);
out_buf->smb_buf_length =
be32_to_cpu(out_buf->smb_buf_length);
if (out_buf->smb_buf_length > 12)
......
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