Linux-2.6.12-rc2

Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.

Let it rip!
diff --git a/fs/cifs/AUTHORS b/fs/cifs/AUTHORS
new file mode 100644
index 0000000..acce36e
--- /dev/null
+++ b/fs/cifs/AUTHORS
@@ -0,0 +1,42 @@
+Original Author
+===============
+Steve French (sfrench@samba.org)
+
+The author wishes to express his appreciation and thanks to:
+Andrew Tridgell (Samba team) for his early suggestions about smb/cifs VFS
+improvements. Thanks to IBM for allowing me the time and test resources to pursue
+this project. Jim McDonough from IBM (and the Samba Team) for his help.
+The IBM Linux JFS team for explaining many esoteric Linux filesystem features.
+Dave Boutcher of IBM Rochester (author of the OS/400 smb/cifs filesystem client)
+for proving years ago that a very good smb/cifs client could be done on a Unix like 
+operating system.  Volker Lendecke, Andrew Tridgell, Urban Widmark, John Newbigin 
+and others for their work on the Linux smbfs module over the years. Thanks to
+the other members of the Storage Network Industry Association CIFS Technical
+Workgroup for their work specifying this highly complex protocol and finally
+thanks to the Samba team for their technical advice and encouragement.
+
+Patch Contributors
+------------------
+Zwane Mwaikambo
+Andi Kleen
+Amrut Joshi
+Shobhit Dayal
+Sergey Vlasov
+Richard Hughes
+Yury Umanets
+Mark Hamzy
+Domen Puncer
+Jesper Juhl
+
+Test case and Bug Report contributors
+-------------------------------------
+Thanks to those in the community who have submitted detailed bug reports
+and debug of problems they have found:  Jochen Dolze, David Blaine,
+Rene Scharfe, Martin Josefsson, Alexander Wild, Anthony Liguori,
+Lars Muller, Urban Widmark, Massimiliano Ferrero, Howard Owen,
+Olaf Kirch, Kieron Briggs, Nick Millington and others. Also special
+mention to the Stanford Checker (SWAT) which pointed out many minor
+bugs in error paths.
+
+And thanks to the IBM LTC and Power test teams and SuSE testers for
+finding multiple bugs during excellent stress test runs.
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
new file mode 100644
index 0000000..5316c8d
--- /dev/null
+++ b/fs/cifs/CHANGES
@@ -0,0 +1,671 @@
+Version 1.31
+------------
+Fix oops in ls when Transact2 FindFirst (or FindNext) returns more than one
+transact response for an SMB request and search entry split across two frames.
+Fix updates of DOS attributes and time fields so that files on NT4 servers
+do not get marked delete on close. Display sizes of cifs buffer pools in
+cifs stats. Fix oops in unmount when cifsd thread being killed by 
+shutdown. Add generic readv/writev and aio support. Report inode numbers 
+consistently in readdir and lookup (when serverino mount option is
+specified use the inode number that the server reports - for both lookup
+and readdir, otherwise by default the locally generated inode number is used
+for inodes created in either path since servers are not always able to 
+provide unique inode numbers when exporting multiple volumes from under one
+sharename).
+
+Version 1.30
+------------
+Allow new nouser_xattr mount parm to disable xattr support for user namespace.
+Do not flag user_xattr mount parm in dmesg.  Retry failures setting file time  
+(mostly affects NT4 servers) by retry with handle based network operation. 
+Add new POSIX Query FS Info for returning statfs info more accurately.
+Handle passwords with multiple commas in them.
+
+Version 1.29
+------------
+Fix default mode in sysfs of cifs module parms.  Remove old readdir routine.
+Fix capabilities flags for large readx so as to allow reads larger than 64K.
+
+Version 1.28
+------------
+Add module init parm for large SMB buffer size (to allow it to be changed
+from its default of 16K) which is especially useful for large file copy
+when mounting with the directio mount option. Fix oops after 
+returning from mount when experimental ExtendedSecurity enabled and
+SpnegoNegotiated returning invalid error. Fix case to retry better when 
+peek returns from 1 to 3 bytes on socket which should have more data.
+Fixed path based calls (such as cifs lookup) to handle path names
+longer than 530 (now can handle PATH_MAX). Fix pass through authentication
+from Samba server to DC (Samba required dummy LM password).
+
+Version 1.27
+------------
+Turn off DNOTIFY (directory change notification support) by default
+(unless built with the experimental flag) to fix hang with KDE
+file browser. Fix DNOTIFY flag mappings.  Fix hang (in wait_event
+waiting on an SMB response) in SendReceive when session dies but
+reconnects quickly from another task.  Add module init  parms for
+minimum number of large and small network buffers in the buffer pools,
+and for the maximum number of simultaneous requests.
+
+Version 1.26
+------------
+Add setfacl support to allow setting of ACLs remotely to Samba 3.10 and later
+and other POSIX CIFS compliant servers.  Fix error mapping for getfacl 
+to EOPNOTSUPP when server does not support posix acls on the wire. Fix 
+improperly zeroed buffer in CIFS Unix extensions set times call. 
+
+Version 1.25
+------------
+Fix internationlization problem in cifs readdir with filenames that map to 
+longer UTF8 strings than the string on the wire was in Unicode.  Add workaround
+for readdir to netapp servers. Fix search rewind (seek into readdir to return 
+non-consecutive entries).  Do not do readdir when server negotiates 
+buffer size to small to fit filename. Add support for reading POSIX ACLs from
+the server (add also acl and noacl mount options).
+
+Version 1.24
+------------
+Optionally allow using server side inode numbers, rather than client generated
+ones by specifying mount option "serverino" - this is required for some apps
+to work which double check hardlinked files and have persistent inode numbers.
+
+Version 1.23
+------------
+Multiple bigendian fixes. On little endian systems (for reconnect after
+network failure) fix tcp session reconnect code so we do not try first
+to reconnect on reverse of port 445. Treat reparse points (NTFS junctions)
+as directories rather than symlinks because we can do follow link on them.
+
+Version 1.22
+------------
+Add config option to enable XATTR (extended attribute) support, mapping
+xattr names in the "user." namespace space to SMB/CIFS EAs. Lots of
+minor fixes pointed out by the Stanford SWAT checker (mostly missing
+or out of order NULL pointer checks in little used error paths).
+
+Version 1.21
+------------
+Add new mount parm to control whether mode check (generic_permission) is done
+on the client.  If Unix extensions are enabled and the uids on the client
+and server do not match, client permission checks are meaningless on
+server uids that do not exist on the client (this does not affect the
+normal ACL check which occurs on the server).  Fix default uid
+on mknod to match create and mkdir. Add optional mount parm to allow
+override of the default uid behavior (in which the server sets the uid
+and gid of newly created files). Normally for network filesystem mounts
+user want the server to set the uid/gid on newly created files (rather than 
+using uid of the client processes you would in a local filesystem).
+
+Version 1.20
+------------
+Make transaction counts more consistent. Merge /proc/fs/cifs/SimultaneousOps
+info into /proc/fs/cifs/DebugData.  Fix oops in rare oops in readdir 
+(in build_wildcard_path_from_dentry).  Fix mknod to pass type field
+(block/char/fifo) properly.  Remove spurious mount warning log entry when
+credentials passed as mount argument. Set major/minor device number in
+inode for block and char devices when unix extensions enabled.
+
+Version 1.19
+------------
+Fix /proc/fs/cifs/Stats and DebugData display to handle larger
+amounts of return data. Properly limit requests to MAX_REQ (50
+is the usual maximum active multiplex SMB/CIFS requests per server).
+Do not kill cifsd (and thus hurt the other SMB session) when more than one
+session to the same server (but with different userids) exists and one
+of the two user's smb sessions is being removed while leaving the other.
+Do not loop reconnecting in cifsd demultiplex thread when admin
+kills the thread without going through unmount.
+
+Version 1.18
+------------
+Do not rename hardlinked files (since that should be a noop). Flush
+cached write behind data when reopening a file after session abend,
+except when already in write. Grab per socket sem during reconnect 
+to avoid oops in sendmsg if overlapping with reconnect. Do not
+reset cached inode file size on readdir for files open for write on 
+client.
+
+
+Version 1.17
+------------
+Update number of blocks in file so du command is happier (in Linux a fake
+blocksize of 512 is required for calculating number of blocks in inode).
+Fix prepare write of partial pages to read in data from server if possible.
+Fix race on tcpStatus field between unmount and reconnection code, causing
+cifsd process sometimes to hang around forever. Improve out of memory
+checks in cifs_filldir
+
+Version 1.16
+------------
+Fix incorrect file size in file handle based setattr on big endian hardware.
+Fix oops in build_path_from_dentry when out of memory.  Add checks for invalid
+and closing file structs in writepage/partialpagewrite.  Add statistics
+for each mounted share (new menuconfig option). Fix endianness problem in
+volume information displayed in /proc/fs/cifs/DebugData (only affects
+affects big endian architectures). Prevent renames while constructing
+path names for open, mkdir and rmdir.
+
+Version 1.15
+------------
+Change to mempools for alloc smb request buffers and multiplex structs
+to better handle low memory problems (and potential deadlocks).
+
+Version 1.14
+------------
+Fix incomplete listings of large directories on Samba servers when Unix
+extensions enabled.  Fix oops when smb_buffer can not be allocated. Fix
+rename deadlock when writing out dirty pages at same time.
+
+Version 1.13
+------------
+Fix open of files in which O_CREATE can cause the mode to change in
+some cases. Fix case in which retry of write overlaps file close.
+Fix PPC64 build error.  Reduce excessive stack usage in smb password
+hashing. Fix overwrite of Linux user's view of file mode to Windows servers.
+
+Version 1.12
+------------
+Fixes for large file copy, signal handling, socket retry, buffer
+allocation and low memory situations.
+
+Version 1.11
+------------
+Better port 139 support to Windows servers (RFC1001/RFC1002 Session_Initialize)
+also now allowing support for specifying client netbiosname.  NT4 support added.
+
+Version 1.10
+------------
+Fix reconnection (and certain failed mounts) to properly wake up the
+blocked users thread so it does not seem hung (in some cases was blocked
+until the cifs receive timeout expired). Fix spurious error logging
+to kernel log when application with open network files killed. 
+
+Version 1.09
+------------
+Fix /proc/fs module unload warning message (that could be logged
+to the kernel log). Fix intermittent failure in connectathon
+test7 (hardlink count not immediately refreshed in case in which
+inode metadata can be incorrectly kept cached when time near zero)
+
+Version 1.08
+------------
+Allow file_mode and dir_mode (specified at mount time) to be enforced
+locally (the server already enforced its own ACLs too) for servers
+that do not report the correct mode (do not support the 
+CIFS Unix Extensions).
+
+Version 1.07
+------------
+Fix some small memory leaks in some unmount error paths. Fix major leak
+of cache pages in readpages causing multiple read oriented stress
+testcases (including fsx, and even large file copy) to fail over time. 
+
+Version 1.06
+------------
+Send NTCreateX with ATTR_POSIX if Linux/Unix extensions negotiated with server.
+This allows files that differ only in case and improves performance of file
+creation and file open to such servers.  Fix semaphore conflict which causes 
+slow delete of open file to Samba (which unfortunately can cause an oplock
+break to self while vfs_unlink held i_sem) which can hang for 20 seconds.
+
+Version 1.05
+------------
+fixes to cifs_readpages for fsx test case
+
+Version 1.04
+------------
+Fix caching data integrity bug when extending file size especially when no
+oplock on file.  Fix spurious logging of valid already parsed mount options
+that are parsed outside of the cifs vfs such as nosuid.
+
+
+Version 1.03
+------------
+Connect to server when port number override not specified, and tcp port
+unitialized.  Reset search to restart at correct file when kernel routine
+filldir returns error during large directory searches (readdir). 
+
+Version 1.02
+------------
+Fix caching problem when files opened by multiple clients in which 
+page cache could contain stale data, and write through did
+not occur often enough while file was still open when read ahead
+(read oplock) not allowed.  Treat "sep=" when first mount option
+as an overrride of comma as the default separator between mount
+options. 
+
+Version 1.01
+------------
+Allow passwords longer than 16 bytes. Allow null password string.
+
+Version 1.00
+------------
+Gracefully clean up failed mounts when attempting to mount to servers such as
+Windows 98 that terminate tcp sessions during prototocol negotiation.  Handle
+embedded commas in mount parsing of passwords.
+
+Version 0.99
+------------
+Invalidate local inode cached pages on oplock break and when last file
+instance is closed so that the client does not continue using stale local
+copy rather than later modified server copy of file.  Do not reconnect
+when server drops the tcp session prematurely before negotiate
+protocol response.  Fix oops in roepen_file when dentry freed.  Allow
+the support for CIFS Unix Extensions to be disabled via proc interface.
+
+Version 0.98
+------------
+Fix hang in commit_write during reconnection of open files under heavy load.
+Fix unload_nls oops in a mount failure path. Serialize writes to same socket
+which also fixes any possible races when cifs signatures are enabled in SMBs
+being sent out of signature sequence number order.    
+
+Version 0.97
+------------
+Fix byte range locking bug (endian problem) causing bad offset and
+length.
+
+Version 0.96
+------------
+Fix oops (in send_sig) caused by CIFS unmount code trying to
+wake up the demultiplex thread after it had exited. Do not log
+error on harmless oplock release of closed handle.
+
+Version 0.95
+------------
+Fix unsafe global variable usage and password hash failure on gcc 3.3.1
+Fix problem reconnecting secondary mounts to same server after session 
+failure.  Fix invalid dentry - race in mkdir when directory gets created
+by another client between the lookup and mkdir.
+ 
+Version 0.94
+------------
+Fix to list processing in reopen_files. Fix reconnection when server hung
+but tcpip session still alive.  Set proper timeout on socket read.
+
+Version 0.93
+------------
+Add missing mount options including iocharset.  SMP fixes in write and open. 
+Fix errors in reconnecting after TCP session failure.  Fix module unloading
+of default nls codepage
+
+Version 0.92
+------------
+Active smb transactions should never go negative (fix double FreeXid). Fix
+list processing in file routines. Check return code on kmalloc in open.
+Fix spinlock usage for SMP.
+
+Version 0.91
+------------
+Fix oops in reopen_files when invalid dentry. drop dentry on server rename 
+and on revalidate errors. Fix cases where pid is now tgid.  Fix return code
+on create hard link when server does not support them. 
+
+Version 0.90
+------------
+Fix scheduling while atomic error in getting inode info on newly created file. 
+Fix truncate of existing files opened with O_CREAT but not O_TRUNC set.
+
+Version 0.89
+------------
+Fix oops on write to dead tcp session. Remove error log write for case when file open
+O_CREAT but not O_EXCL
+
+Version 0.88
+------------
+Fix non-POSIX behavior on rename of open file and delete of open file by taking 
+advantage of trans2 SetFileInfo rename facility if available on target server.
+Retry on ENOSPC and EAGAIN socket errors.
+
+Version 0.87
+------------
+Fix oops on big endian readdir.  Set blksize to be even power of two (2**blkbits) to fix
+allocation size miscalculation. After oplock token lost do not read through
+cache. 
+
+Version 0.86
+------------
+Fix oops on empty file readahead.  Fix for file size handling for locally cached files.
+
+Version 0.85
+------------
+Fix oops in mkdir when server fails to return inode info. Fix oops in reopen_files
+during auto reconnection to server after server recovered from failure.
+
+Version 0.84
+------------
+Finish support for Linux 2.5 open/create changes, which removes the
+redundant NTCreate/QPathInfo/close that was sent during file create.
+Enable oplock by default. Enable packet signing by default (needed to 
+access many recent Windows servers)
+
+Version 0.83
+------------
+Fix oops when mounting to long server names caused by inverted parms to kmalloc.
+Fix MultiuserMount (/proc/fs/cifs configuration setting) so that when enabled
+we will choose a cifs user session (smb uid) that better matches the local
+uid if a) the mount uid does not match the current uid and b) we have another
+session to the same server (ip address) for a different mount which
+matches the current local uid.
+
+Version 0.82
+------------
+Add support for mknod of block or character devices.  Fix oplock
+code (distributed caching) to properly send response to oplock
+break from server.
+
+Version 0.81
+------------
+Finish up CIFS packet digital signing for the default
+NTLM security case. This should help Windows 2003
+network interoperability since it is common for
+packet signing to be required now. Fix statfs (stat -f)
+which recently started returning errors due to 
+invalid value (-1 instead of 0) being set in the
+struct kstatfs f_ffiles field.
+
+Version 0.80
+-----------
+Fix oops on stopping oplock thread when removing cifs when
+built as module.
+
+Version 0.79
+------------
+Fix mount options for ro (readonly), uid, gid and file and directory mode. 
+
+Version 0.78
+------------
+Fix errors displayed on failed mounts to be more understandable.
+Fixed various incorrect or misleading smb to posix error code mappings.
+
+Version 0.77
+------------
+Fix display of NTFS DFS junctions to display as symlinks.
+They are the network equivalent.  Fix oops in 
+cifs_partialpagewrite caused by missing spinlock protection
+of openfile linked list.  Allow writebehind caching errors to 
+be returned to the application at file close.
+
+Version 0.76
+------------
+Clean up options displayed in /proc/mounts by show_options to
+be more consistent with other filesystems.
+
+Version 0.75
+------------
+Fix delete of readonly file to Windows servers.  Reflect
+presence or absence of read only dos attribute in mode
+bits for servers that do not support CIFS Unix extensions.
+Fix shortened results on readdir of large directories to
+servers supporting CIFS Unix extensions (caused by
+incorrect resume key).
+
+Version 0.74
+------------
+Fix truncate bug (set file size) that could cause hangs e.g. running fsx
+
+Version 0.73
+------------
+unload nls if mount fails.
+
+Version 0.72
+------------
+Add resume key support to search (readdir) code to workaround
+Windows bug.  Add /proc/fs/cifs/LookupCacheEnable which
+allows disabling caching of attribute information for
+lookups.
+
+Version 0.71
+------------
+Add more oplock handling (distributed caching code).  Remove
+dead code.  Remove excessive stack space utilization from
+symlink routines.
+
+Version 0.70
+------------
+Fix oops in get dfs referral (triggered when null path sent in to
+mount).  Add support for overriding rsize at mount time.
+
+Version 0.69
+------------
+Fix buffer overrun in readdir which caused intermittent kernel oopses.
+Fix writepage code to release kmap on write data.  Allow "-ip=" new 
+mount option to be passed in on parameter distinct from the first part
+(server name portion of) the UNC name.  Allow override of the
+tcp port of the target server via new mount option "-port="  
+
+Version 0.68
+------------
+Fix search handle leak on rewind.  Fix setuid and gid so that they are 
+reflected in the local inode immediately.  Cleanup of whitespace
+to make 2.4 and 2.5 versions more consistent.
+
+
+Version 0.67
+------------
+Fix signal sending so that captive thread (cifsd) exits on umount 
+(which was causing the warning in kmem_cache_free of the request buffers
+at rmmod time).  This had broken as a sideeffect of the recent global
+kernel change to daemonize.  Fix memory leak in readdir code which
+showed up in "ls -R" (and applications that did search rewinding).
+
+Version 0.66
+------------
+Reconnect tids and fids after session reconnection (still do not
+reconnect byte range locks though).  Fix problem caching
+lookup information for directory inodes, improving performance,
+especially in deep directory trees.  Fix various build warnings.
+
+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 
+rare code path. 
+
+Version 0.59
+------------
+Includes support for deleting of open files and renaming over existing files (per POSIX
+requirement).  Add readlink support for Windows junction points (directory symlinks).
+
+Version 0.58
+------------
+Changed read and write to go through pagecache. Added additional address space operations.
+Memory mapped operations now working.
+
+Version 0.57
+------------
+Added writepage code for additional memory mapping support.  Fixed leak in xids causing
+the simultaneous operations counter (/proc/fs/cifs/SimultaneousOps) to increase on 
+every stat call.  Additional formatting cleanup. 
+
+Version 0.56
+------------
+Fix bigendian bug in order of time conversion. Merge 2.5 to 2.4 version.  Formatting cleanup.   
+
+Version 0.55
+------------
+Fixes from Zwane Mwaikambo for adding missing return code checking in a few places.
+Also included a modified version of his fix to protect global list manipulation of
+the smb session and tree connection and mid related global variables.
+
+Version 0.54
+------------
+Fix problem with captive thread hanging around at unmount time.  Adjust to 2.5.42-pre
+changes to superblock layout.   Remove wasteful allocation of smb buffers (now the send 
+buffer is reused for responses).  Add more oplock handling. Additional minor cleanup.
+
+Version 0.53
+------------
+More stylistic updates to better match kernel style.  Add additional statistics
+for filesystem which can be viewed via /proc/fs/cifs.  Add more pieces of NTLMv2
+and CIFS Packet Signing enablement.
+
+Version 0.52
+------------
+Replace call to sleep_on with safer wait_on_event.
+Make stylistic changes to better match kernel style recommendations.
+Remove most typedef usage (except for the PDUs themselves).
+
+Version 0.51
+------------
+Update mount so the -unc mount option is no longer required (the ip address can be specified
+in a UNC style device name.   Implementation of readpage/writepage started.
+
+Version 0.50
+------------
+Fix intermittent problem with incorrect smb header checking on badly 
+fragmented tcp responses
+
+Version 0.49
+------------
+Fixes to setting of allocation size and file size.
+
+Version 0.48
+------------
+Various 2.5.38 fixes.  Now works on 2.5.38
+
+Version 0.47
+------------
+Prepare for 2.5 kernel merge.  Remove ifdefs.
+
+Version 0.46
+------------
+Socket buffer management fixes.  Fix dual free.
+
+Version 0.45
+------------
+Various big endian fixes for hardlinks and symlinks and also for dfs.
+
+Version 0.44
+------------
+Various big endian fixes for servers with Unix extensions such as Samba
+
+Version 0.43
+------------
+Various FindNext fixes for incorrect filenames on large directory searches on big endian
+clients.  basic posix file i/o tests now work on big endian machines, not just le
+
+Version 0.42
+------------
+SessionSetup and NegotiateProtocol now work from Big Endian machines.
+Various Big Endian fixes found during testing on the Linux on 390.  Various fixes for compatibility with older
+versions of 2.4 kernel (now builds and works again on kernels at least as early as 2.4.7).
+
+Version 0.41
+------------
+Various minor fixes for Connectathon Posix "basic" file i/o test suite.  Directory caching fixed so hardlinked
+files now return the correct rumber of links on fstat as they are repeatedly linked and unlinked.
+
+Version 0.40
+------------
+Implemented "Raw" (i.e. not encapsulated in SPNEGO) NTLMSSP (i.e. the Security Provider Interface used to negotiate
+session advanced session authentication).  Raw NTLMSSP is preferred by Windows 2000 Professional and Windows XP.
+Began implementing support for SPNEGO encapsulation of NTLMSSP based session authentication blobs
+(which is the mechanism preferred by Windows 2000 server in the absence of Kerberos).
+
+Version 0.38
+------------
+Introduced optional mount helper utility mount.cifs and made coreq changes to cifs vfs to enable
+it. Fixed a few bugs in the DFS code (e.g. bcc two bytes too short and incorrect uid in PDU).
+
+Version 0.37
+------------
+Rewrote much of connection and mount/unmount logic to handle bugs with
+multiple uses to same share, multiple users to same server etc.
+
+Version 0.36
+------------
+Fixed major problem with dentry corruption (missing call to dput)
+
+Version 0.35
+------------
+Rewrite of readdir code to fix bug. Various fixes for bigendian machines.
+Begin adding oplock support.  Multiusermount and oplockEnabled flags added to /proc/fs/cifs
+although corresponding function not fully implemented in the vfs yet
+
+Version 0.34
+------------
+Fixed dentry caching bug, misc. cleanup 
+
+Version 0.33
+------------
+Fixed 2.5 support to handle build and configure changes as well as misc. 2.5 changes.  Now can build
+on current 2.5 beta version (2.5.24) of the Linux kernel as well as on 2.4 Linux kernels.
+Support for STATUS codes (newer 32 bit NT error codes) added.  DFS support begun to be added.
+
+Version 0.32
+------------
+Unix extensions (symlink, readlink, hardlink, chmod and some chgrp and chown) implemented
+and tested against Samba 2.2.5
+
+
+Version 0.31
+------------
+1) Fixed lockrange to be correct (it was one byte too short)
+
+2) Fixed GETLK (i.e. the fcntl call to test a range of bytes in a file to see if locked) to correctly 
+show range as locked when there is a conflict with an existing lock.
+
+3) default file perms are now 2767 (indicating support for mandatory locks) instead of 777 for directories
+in most cases.  Eventually will offer optional ability to query server for the correct perms.
+
+3) Fixed eventual trap when mounting twice to different shares on the same server when the first succeeded 
+but the second one was invalid and failed (the second one was incorrectly disconnecting the tcp and smb
+session) 
+
+4) Fixed error logging of valid mount options
+
+5) Removed logging of password field.
+
+6) Moved negotiate, treeDisconnect and uloggoffX (only tConx and SessSetup remain in connect.c) to cifssmb.c
+and cleaned them up and made them more consistent with other cifs functions. 
+
+7) Server support for Unix extensions is now fully detected and FindFirst is implemented both ways 
+(with or without Unix exentions) but FindNext and QueryPathInfo with the Unix extensions are not completed,
+nor is the symlink support using the Unix extensions
+
+8) Started adding the readlink and follow_link code 
+
+Version 0.3 
+-----------
+Initial drop
+
diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile
new file mode 100644
index 0000000..7384947
--- /dev/null
+++ b/fs/cifs/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for Linux CIFS VFS client 
+#
+obj-$(CONFIG_CIFS) += cifs.o
+
+cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o
diff --git a/fs/cifs/README b/fs/cifs/README
new file mode 100644
index 0000000..0f20edc
--- /dev/null
+++ b/fs/cifs/README
@@ -0,0 +1,475 @@
+The CIFS VFS support for Linux supports many advanced network filesystem 
+features such as heirarchical dfs like namespace, hardlinks, locking and more.  
+It was designed to comply with the SNIA CIFS Technical Reference (which 
+supersedes the 1992 X/Open SMB Standard) as well as to perform best practice 
+practical interoperability with Windows 2000, Windows XP, Samba and equivalent 
+servers.  
+
+For questions or bug reports please contact:
+    sfrench@samba.org (sfrench@us.ibm.com) 
+
+Build instructions:
+==================
+For Linux 2.4:
+1) Get the kernel source (e.g.from http://www.kernel.org)
+and download the cifs vfs source (see the project page
+at http://us1.samba.org/samba/Linux_CIFS_client.html)
+and change directory into the top of the kernel directory
+then patch the kernel (e.g. "patch -p1 < cifs_24.patch") 
+to add the cifs vfs to your kernel configure options if
+it has not already been added (e.g. current SuSE and UL
+users do not need to apply the cifs_24.patch since the cifs vfs is
+already in the kernel configure menu) and then
+mkdir linux/fs/cifs and then copy the current cifs vfs files from
+the cifs download to your kernel build directory e.g.
+
+	cp <cifs_download_dir>/fs/cifs/* to <kernel_download_dir>/fs/cifs
+	
+2) make menuconfig (or make xconfig)
+3) select cifs from within the network filesystem choices
+4) save and exit
+5) make dep
+6) make modules (or "make" if CIFS VFS not to be built as a module)
+
+For Linux 2.6:
+1) Download the kernel (e.g. from http://www.kernel.org or from bitkeeper
+at bk://linux.bkbits.net/linux-2.5) and change directory into the top
+of the kernel directory tree (e.g. /usr/src/linux-2.5.73)
+2) make menuconfig (or make xconfig)
+3) select cifs from within the network filesystem choices
+4) save and exit
+5) make
+
+
+Installation instructions:
+=========================
+If you have built the CIFS vfs as module (successfully) simply
+type "make modules_install" (or if you prefer, manually copy the file to
+the modules directory e.g. /lib/modules/2.4.10-4GB/kernel/fs/cifs/cifs.o).
+
+If you have built the CIFS vfs into the kernel itself, follow the instructions
+for your distribution on how to install a new kernel (usually you
+would simply type "make install").
+
+If you do not have the utility mount.cifs (in the Samba 3.0 source tree and on 
+the CIFS VFS web site) copy it to the same directory in which mount.smbfs and 
+similar files reside (usually /sbin).  Although the helper software is not  
+required, mount.cifs is recommended.  Eventually the Samba 3.0 utility program 
+"net" may also be helpful since it may someday provide easier mount syntax for
+users who are used to Windows e.g.  net use <mount point> <UNC name or cifs URL>
+Note that running the Winbind pam/nss module (logon service) on all of your
+Linux clients is useful in mapping Uids and Gids consistently across the
+domain to the proper network user.  The mount.cifs mount helper can be
+trivially built from Samba 3.0 or later source e.g. by executing:
+
+	gcc samba/source/client/mount.cifs.c -o mount.cifs
+
+If cifs is built as a module, then the size and number of network buffers
+and maximum number of simultaneous requests to one server can be configured.
+Changing these from their defaults is not recommended. By executing modinfo
+	modinfo kernel/fs/cifs/cifs.ko
+on kernel/fs/cifs/cifs.ko the list of configuration changes that can be made
+at module initialization time (by running insmod cifs.ko) can be seen.
+
+Allowing User Mounts
+====================
+To permit users to mount and unmount over directories they own is possible
+with the cifs vfs.  A way to enable such mounting is to mark the mount.cifs
+utility as suid (e.g. "chmod +s /sbin/mount/cifs). To enable users to 
+umount shares they mount requires
+1) mount.cifs version 1.4 or later
+2) an entry for the share in /etc/fstab indicating that a user may
+unmount it e.g.
+//server/usersharename  /mnt/username cifs user 0 0
+
+Note that when the mount.cifs utility is run suid (allowing user mounts), 
+in order to reduce risks, the "nosuid" mount flag is passed in on mount to
+disallow execution of an suid program mounted on the remote target.
+When mount is executed as root, nosuid is not passed in by default,
+and execution of suid programs on the remote target would be enabled
+by default. This can be changed, as with nfs and other filesystems, 
+by simply specifying "nosuid" among the mount options. For user mounts 
+though to be able to pass the suid flag to mount requires rebuilding 
+mount.cifs with the following flag: 
+ 
+        gcc samba/source/client/mount.cifs.c -DCIFS_ALLOW_USR_SUID -o mount.cifs
+
+There is a corresponding manual page for cifs mounting in the Samba 3.0 and
+later source tree in docs/manpages/mount.cifs.8 
+
+Samba Considerations 
+==================== 
+To get the maximum benefit from the CIFS VFS, we recommend using a server that 
+supports the SNIA CIFS Unix Extensions standard (e.g.  Samba 2.2.5 or later or 
+Samba 3.0) but the CIFS vfs works fine with a wide variety of CIFS servers.  
+Note that uid, gid and file permissions will display default values if you do 
+not have a server that supports the Unix extensions for CIFS (such as Samba 
+2.2.5 or later).  To enable the Unix CIFS Extensions in the Samba server, add 
+the line: 
+
+	unix extensions = yes
+	
+to your smb.conf file on the server.  Note that the following smb.conf settings 
+are also useful (on the Samba server) when the majority of clients are Unix or 
+Linux: 
+
+	case sensitive = yes
+	delete readonly = yes 
+	ea support = yes
+
+Note that server ea support is required for supporting xattrs from the Linux
+cifs client, and that EA support is present in later versions of Samba (e.g. 
+3.0.6 and later (also EA support works in all versions of Windows, at least to
+shares on NTFS filesystems).  Extended Attribute (xattr) support is an optional
+feature of most Linux filesystems which may require enabling via
+make menuconfig. Client support for extended attributes (user xattr) can be
+disabled on a per-mount basis by specifying "nouser_xattr" on mount.
+
+The CIFS client can get and set POSIX ACLs (getfacl, setfacl) to Samba servers
+version 3.10 and later.  Setting POSIX ACLs requires enabling both XATTR and 
+then POSIX support in the CIFS configuration options when building the cifs
+module.  POSIX ACL support can be disabled on a per mount basic by specifying
+"noacl" on mount.
+ 
+Some administrators may want to change Samba's smb.conf "map archive" and 
+"create mask" parameters from the default.  Unless the create mask is changed
+newly created files can end up with an unnecessarily restrictive default mode,
+which may not be what you want, although if the CIFS Unix extensions are
+enabled on the server and client, subsequent setattr calls (e.g. chmod) can
+fix the mode.  Note that creating special devices (mknod) remotely 
+may require specifying a mkdev function to Samba if you are not using 
+Samba 3.0.6 or later.  For more information on these see the manual pages
+("man smb.conf") on the Samba server system.  Note that the cifs vfs,
+unlike the smbfs vfs, does not read the smb.conf on the client system 
+(the few optional settings are passed in on mount via -o parameters instead).  
+Note that Samba 2.2.7 or later includes a fix that allows the CIFS VFS to delete
+open files (required for strict POSIX compliance).  Windows Servers already 
+supported this feature. Samba server does not allow symlinks that refer to files
+outside of the share, so in Samba versions prior to 3.0.6, most symlinks to
+files with absolute paths (ie beginning with slash) such as:
+	 ln -s /mnt/foo bar
+would be forbidden. Samba 3.0.6 server or later includes the ability to create 
+such symlinks safely by converting unsafe symlinks (ie symlinks to server 
+files that are outside of the share) to a samba specific format on the server
+that is ignored by local server applications and non-cifs clients and that will
+not be traversed by the Samba server).  This is opaque to the Linux client
+application using the cifs vfs. Absolute symlinks will work to Samba 3.0.5 or
+later, but only for remote clients using the CIFS Unix extensions, and will
+be invisbile to Windows clients and typically will not affect local
+applications running on the same server as Samba.  
+
+Use instructions:
+================
+Once the CIFS VFS support is built into the kernel or installed as a module 
+(cifs.o), you can use mount syntax like the following to access Samba or Windows 
+servers: 
+
+  mount -t cifs //9.53.216.11/e$ /mnt -o user=myname,pass=mypassword
+
+Before -o the option -v may be specified to make the mount.cifs
+mount helper display the mount steps more verbosely.  
+After -o the following commonly used cifs vfs specific options
+are supported:
+
+  user=<username>
+  pass=<password>
+  domain=<domain name>
+  
+Other cifs mount options are described below.  Use of TCP names (in addition to
+ip addresses) is available if the mount helper (mount.cifs) is installed. If
+you do not trust the server to which are mounted, or if you do not have
+cifs signing enabled (and the physical network is insecure), consider use
+of the standard mount options "noexec" and "nosuid" to reduce the risk of 
+running an altered binary on your local system (downloaded from a hostile server
+or altered by a hostile router).
+
+Although mounting using format corresponding to the CIFS URL specification is
+not possible in mount.cifs yet, it is possible to use an alternate format
+for the server and sharename (which is somewhat similar to NFS style mount
+syntax) instead of the more widely used UNC format (i.e. \\server\share):
+  mount -t cifs tcp_name_of_server:share_name /mnt -o user=myname,pass=mypasswd
+
+When using the mount helper mount.cifs, passwords may be specified via alternate
+mechanisms, instead of specifying it after -o using the normal "pass=" syntax
+on the command line:
+1) By including it in a credential file. Specify credentials=filename as one
+of the mount options. Credential files contain two lines
+        username=someuser
+        password=your_password
+2) By specifying the password in the PASSWD environment variable (similarly
+the user name can be taken from the USER environment variable).
+3) By specifying the password in a file by name via PASSWD_FILE
+4) By specifying the password in a file by file descriptor via PASSWD_FD
+
+If no password is provided, mount.cifs will prompt for password entry
+
+Restrictions
+============
+Servers must support the NTLM SMB dialect (which is the most recent, supported 
+by Samba and Windows NT version 4, 2000 and XP and many other SMB/CIFS servers) 
+Servers must support either "pure-TCP" (port 445 TCP/IP CIFS connections) or RFC 
+1001/1002 support for "Netbios-Over-TCP/IP." Neither of these is likely to be a 
+problem as most servers support this.  IPv6 support is planned for the future,
+and is almost complete.
+
+Valid filenames differ between Windows and Linux.  Windows typically restricts
+filenames which contain certain reserved characters (e.g.the character : 
+which is used to delimit the beginning of a stream name by Windows), while
+Linux allows a slightly wider set of valid characters in filenames. Windows
+servers can remap such characters when an explicit mapping is specified in
+the Server's registry.  Samba starting with version 3.10 will allow such 
+filenames (ie those which contain valid Linux characters, which normally
+would be forbidden for Windows/CIFS semantics) as long as the server is
+configured for Unix Extensions (and the client has not disabled
+/proc/fs/cifs/LinuxExtensionsEnabled).
+  
+
+CIFS VFS Mount Options
+======================
+A partial list of the supported mount options follows:
+  user		The user name to use when trying to establish
+		the CIFS session.
+  password	The user password.  If the mount helper is
+		installed, the user will be prompted for password
+		if it is not supplied.
+  ip		The ip address of the target server
+  unc		The target server Universal Network Name (export) to 
+		mount.	
+  domain	Set the SMB/CIFS workgroup name prepended to the
+		username during CIFS session establishment
+  uid		If CIFS Unix extensions are not supported by the server
+		this overrides the default uid for inodes. For mounts to
+		servers which do support the CIFS Unix extensions, such
+		as a properly configured Samba server, the server provides
+		the uid, gid and mode.  For servers which do not support
+		the Unix extensions, the default uid (and gid) returned on
+		lookup of existing files is the uid (gid) of the person
+		who executed the mount (root, except when mount.cifs
+		is configured setuid for user mounts) unless the "uid=" 
+		(gid) mount option is specified.  For the uid (gid) of newly
+		created files and directories, ie files created since 
+		the last mount of the server share, the expected uid 
+		(gid) is cached as as long as the inode remains in 
+		memory on the client.   Also note that permission
+		checks (authorization checks) on accesses to a file occur
+		at the server, but there are cases in which an administrator
+		may want to restrict at the client as well.  For those
+		servers which do not report a uid/gid owner
+		(such as Windows), permissions can also be checked at the
+		client, and a crude form of client side permission checking 
+		can be enabled by specifying file_mode and dir_mode on 
+		the client
+  gid		If CIFS Unix extensions are not supported by the server
+		this overrides the default gid for inodes.
+  file_mode     If CIFS Unix extensions are not supported by the server
+		this overrides the default mode for file inodes.
+  dir_mode      If CIFS Unix extensions are not supported by the server 
+		this overrides the default mode for directory inodes.
+  port		attempt to contact the server on this tcp port, before
+		trying the usual ports (port 445, then 139).
+  iocharset     Codepage used to convert local path names to and from
+		Unicode. Unicode is used by default for network path
+		names if the server supports it.  If iocharset is
+		not specified then the nls_default specified
+		during the local client kernel build will be used.
+		If server does not support Unicode, this parameter is
+		unused.
+  rsize		default read size
+  wsize		default write size
+  rw		mount the network share read-write (note that the
+		server may still consider the share read-only)
+  ro		mount network share read-only
+  version	used to distinguish different versions of the
+		mount helper utility (not typically needed)
+  sep		if first mount option (after the -o), overrides
+		the comma as the separator between the mount
+		parms. e.g.
+			-o user=myname,password=mypassword,domain=mydom
+		could be passed instead with period as the separator by
+			-o sep=.user=myname.password=mypassword.domain=mydom
+		this might be useful when comma is contained within username
+		or password or domain. This option is less important
+		when the cifs mount helper cifs.mount (version 1.1 or later)
+		is used.
+  nosuid        Do not allow remote executables with the suid bit 
+		program to be executed.  This is only meaningful for mounts
+		to servers such as Samba which support the CIFS Unix Extensions.
+		If you do not trust the servers in your network (your mount
+		targets) it is recommended that you specify this option for
+		greater security.
+  exec		Permit execution of binaries on the mount.
+  noexec	Do not permit execution of binaries on the mount.
+  dev		Recognize block devices on the remote mount.
+  nodev		Do not recognize devices on the remote mount.
+  suid          Allow remote files on this mountpoint with suid enabled to 
+		be executed (default for mounts when executed as root,
+		nosuid is default for user mounts).
+  credentials   Although ignored by the cifs kernel component, it is used by 
+		the mount helper, mount.cifs. When mount.cifs is installed it
+		opens and reads the credential file specified in order  
+		to obtain the userid and password arguments which are passed to
+		the cifs vfs.
+  guest         Although ignored by the kernel component, the mount.cifs
+		mount helper will not prompt the user for a password
+		if guest is specified on the mount options.  If no
+		password is specified a null password will be used.
+  perm          Client does permission checks (vfs_permission check of uid
+		and gid of the file against the mode and desired operation),
+		Note that this is in addition to the normal ACL check on the
+		target machine done by the server software. 
+		Client permission checking is enabled by default.
+  noperm        Client does not do permission checks.  This can expose
+		files on this mount to access by other users on the local
+		client system. It is typically only needed when the server
+		supports the CIFS Unix Extensions but the UIDs/GIDs on the
+		client and server system do not match closely enough to allow
+		access by the user doing the mount.
+		Note that this does not affect the normal ACL check on the
+		target machine done by the server software (of the server
+		ACL against the user name provided at mount time).
+  serverino	Use servers inode numbers instead of generating automatically
+		incrementing inode numbers on the client.  Although this will
+		make it easier to spot hardlinked files (as they will have
+		the same inode numbers) and inode numbers may be persistent,
+		note that the server does not guarantee that the inode numbers
+		are unique if multiple server side mounts are exported under a
+		single share (since inode numbers on the servers might not
+		be unique if multiple filesystems are mounted under the same
+		shared higher level directory).  Note that this requires that
+		the server support the CIFS Unix Extensions as other servers
+		do not return a unique IndexNumber on SMB FindFirst (most
+		servers return zero as the IndexNumber).  Parameter has no
+		effect to Windows servers and others which do not support the
+		CIFS Unix Extensions.
+  noserverino   Client generates inode numbers (rather than using the actual one
+		from the server) by default.
+  setuids       If the CIFS Unix extensions are negotiated with the server
+		the client will attempt to set the effective uid and gid of
+		the local process on newly created files, directories, and
+		devices (create, mkdir, mknod).
+  nosetuids     The client will not attempt to set the uid and gid on
+		on newly created files, directories, and devices (create, 
+		mkdir, mknod) which will result in the server setting the
+		uid and gid to the default (usually the server uid of the
+		usern who mounted the share).  Letting the server (rather than
+		the client) set the uid and gid is the default. This
+		parameter has no effect if the CIFS Unix Extensions are not
+		negotiated.
+  netbiosname   When mounting to servers via port 139, specifies the RFC1001
+		source name to use to represent the client netbios machine 
+		name when doing the RFC1001 netbios session initialize.
+  direct        Do not do inode data caching on files opened on this mount.
+		This precludes mmaping files on this mount. In some cases
+		with fast networks and little or no caching benefits on the
+		client (e.g. when the application is doing large sequential
+		reads bigger than page size without rereading the same data) 
+		this can provide better performance than the default
+		behavior which caches reads (reaadahead) and writes 
+		(writebehind) through the local Linux client pagecache 
+		if oplock (caching token) is granted and held. Note that
+		direct allows write operations larger than page size
+		to be sent to the server.
+  acl   	Allow setfacl and getfacl to manage posix ACLs if server
+		supports them.  (default)
+  noacl 	Do not allow setfacl and getfacl calls on this mount
+  user_xattr    Allow getting and setting user xattrs as OS/2 EAs (extended
+		attributes) to the server (default) e.g. via setfattr 
+		and getfattr utilities. 
+  nouser_xattr  Do not allow getfattr/setfattr to get/set xattrs 
+		
+The mount.cifs mount helper also accepts a few mount options before -o
+including:
+
+	-S      take password from stdin (equivalent to setting the environment
+		variable "PASSWD_FD=0"
+	-V      print mount.cifs version
+	-?      display simple usage information
+
+With recent 2.6 kernel versions of modutils, the version of the cifs kernel
+module can be displayed via modinfo.
+
+Misc /proc/fs/cifs Flags and Debug Info
+=======================================
+Informational pseudo-files:
+DebugData		Displays information about active CIFS sessions
+			and shares.
+Stats			Lists summary resource usage information as well as per
+			share statistics, if CONFIG_CIFS_STATS in enabled
+			in the kernel configuration.
+
+Configuration pseudo-files:
+MultiuserMount		If set to one, more than one CIFS session to 
+			the same server ip address can be established
+			if more than one uid accesses the same mount
+			point and if the uids user/password mapping
+			information is available. (default is 0)
+PacketSigningEnabled	If set to one, cifs packet signing is enabled
+			and will be used if the server requires 
+			it.  If set to two, cifs packet signing is
+			required even if the server considers packet
+			signing optional. (default 1)
+cifsFYI			If set to one, additional debug information is
+			logged to the system error log. (default 0)
+ExtendedSecurity	If set to one, SPNEGO session establishment
+			is allowed which enables more advanced 
+			secure CIFS session establishment (default 0)
+NTLMV2Enabled		If set to one, more secure password hashes
+			are used when the server supports them and
+			when kerberos is not negotiated (default 0)
+traceSMB		If set to one, debug information is logged to the
+			system error log with the start of smb requests
+			and responses (default 0)
+LookupCacheEnable	If set to one, inode information is kept cached
+			for one second improving performance of lookups
+			(default 1)
+OplockEnabled		If set to one, safe distributed caching enabled.
+			(default 1)
+LinuxExtensionsEnabled	If set to one then the client will attempt to
+			use the CIFS "UNIX" extensions which are optional
+			protocol enhancements that allow CIFS servers
+			to return accurate UID/GID information as well
+			as support symbolic links. If you use servers
+			such as Samba that support the CIFS Unix
+			extensions but do not want to use symbolic link
+			support and want to map the uid and gid fields 
+			to values supplied at mount (rather than the 
+			actual values, then set this to zero. (default 1)
+
+These experimental features and tracing can be enabled by changing flags in 
+/proc/fs/cifs (after the cifs module has been installed or built into the 
+kernel, e.g.  insmod cifs).  To enable a feature set it to 1 e.g.  to enable 
+tracing to the kernel message log type: 
+
+	echo 1 > /proc/fs/cifs/cifsFYI
+	
+and for more extensive tracing including the start of smb requests and responses
+
+	echo 1 > /proc/fs/cifs/traceSMB
+
+Two other experimental features are under development and to test 
+require enabling CONFIG_CIFS_EXPERIMENTAL
+
+	More efficient write operations and SMB buffer handling
+
+	DNOTIFY fcntl: needed for support of directory change 
+			    notification and perhaps later for file leases)
+
+Per share (per client mount) statistics are available in /proc/fs/cifs/Stats
+if the kernel was configured with cifs statistics enabled.  The statistics
+represent the number of successful (ie non-zero return code from the server) 
+SMB responses to some of the more common commands (open, delete, mkdir etc.).
+Also recorded is the total bytes read and bytes written to the server for
+that share.  Note that due to client caching effects this can be less than the
+number of bytes read and written by the application running on the client.
+The statistics for the number of total SMBs and oplock breaks are different in
+that they represent all for that share, not just those for which the server
+returned success.
+	
+Also note that "cat /proc/fs/cifs/DebugData" will display information about 
+the active sessions and the shares that are mounted.  Note: NTLMv2 enablement 
+will not work since they its implementation is not quite complete yet.
+Do not alter these configuration values unless you are doing specific testing.  
+Enabling extended security works to Windows 2000 Workstations and XP but not to 
+Windows 2000 server or Samba since it does not usually send "raw NTLMSSP" 
+(instead it sends NTLMSSP encapsulated in SPNEGO/GSSAPI, which support is not 
+complete in the CIFS VFS yet).  
diff --git a/fs/cifs/TODO b/fs/cifs/TODO
new file mode 100644
index 0000000..f4e3e1f
--- /dev/null
+++ b/fs/cifs/TODO
@@ -0,0 +1,104 @@
+version 1.22 July 30, 2004 
+
+A Partial List of Missing Features
+==================================
+
+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 so
+these can be supported for Windows servers
+
+b) Better pam/winbind integration (e.g. to handle uid mapping
+better)
+
+c) multi-user mounts - multiplexed sessionsetups over single vc
+(ie tcp session) - prettying up needed, and more testing needed
+
+d) Kerberos/SPNEGO session setup support - (started)
+
+e) NTLMv2 authentication (mostly implemented)
+
+f) MD5-HMAC signing SMB PDUs when SPNEGO style SessionSetup 
+used (Kerberos or NTLMSSP). Signing alreadyimplemented for NTLM
+and raw NTLMSSP already. This is important when enabling
+extended security and mounting to Windows 2003 Servers
+
+f) Directory entry caching relies on a 1 second timer, rather than 
+using FindNotify or equivalent.  - (started)
+
+g) A few byte range testcases fail due to POSIX vs. Windows/CIFS
+style byte range lock differences
+
+h) quota support
+
+j) finish writepages support (multi-page write behind for improved
+performance) and syncpage
+
+k) hook lower into the sockets api (as NFS/SunRPC does) to avoid the
+extra copy in/out of the socket buffers in some cases.
+
+l) finish support for IPv6.  This is mostly complete but
+needs a simple conversion of ipv6 to sin6_addr from the
+address in string representation.
+
+m) Better optimize open (and pathbased setfilesize) to reduce the
+oplock breaks coming from windows srv.  Piggyback identical file
+opens on top of each other by incrementing reference count rather
+than resending (helps reduce server resource utilization and avoid
+spurious oplock breaks).
+
+o) Improve performance of readpages by sending more than one read
+at a time when 8 pages or more are requested. In conjuntion
+add support for async_cifs_readpages.
+
+p) Add support for storing symlink and fifo info to Windows servers 
+in the Extended Attribute format their SFU clients would recognize.
+
+q) Finish fcntl D_NOTIFY support so kde and gnome file list windows
+will autorefresh (started)
+
+r) Add GUI tool to configure /proc/fs/cifs settings and for display of
+the CIFS statistics (started)
+
+q) implement support for security and trusted categories of xattrs
+(requires minor protocol extension) to enable better support for SELINUX
+
+r) Implement O_DIRECT flag on open (already supported on mount)
+
+KNOWN BUGS (updated December 10, 2004)
+====================================
+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) follow_link and readdir code does not follow dfs junctions
+but recognizes them
+3) create of new files to FAT partitions on Windows servers can
+succeed but still return access denied (appears to be Windows 
+server not cifs client problem) and has not been reproduced recently.
+NTFS partitions do not have this problem.
+4) debug connectathon lock test case 10 which fails against
+Samba (may be unmappable due to POSIX to Windows lock model
+differences but worth investigating).  Also debug Samba to 
+see why lock test case 7 takes longer to complete to Samba
+than to Windows.
+
+Misc testing to do
+==================
+1) check out max path names and max path name components against various server
+types. Try nested symlinks (8 deep). Return max path name in stat -f information
+
+2) Modify file portion of ltp so it can run against a mounted network
+share and run it against cifs vfs.
+
+3) Additional performance testing and optimization using iozone and similar - 
+there are some easy changes that can be done to parallelize sequential writes,
+and when signing is disabled to request larger read sizes (larger than 
+negotiated size) and send larger write sizes to modern servers.
+
+4) More exhaustively test the recently added NT4 support against various
+NT4 service pack levels, and fix cifs_setattr for setting file times and 
+size to fall back to level 1 when error invalid level returned.
+
diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c
new file mode 100644
index 0000000..e02010d
--- /dev/null
+++ b/fs/cifs/asn1.c
@@ -0,0 +1,618 @@
+/* 
+ * The ASB.1/BER parsing code is derived from ip_nat_snmp_basic.c which was in
+ * turn derived from the gxsnmp package by Gregory McLean & Jochen Friedrich
+ *      
+ * Copyright (c) 2000 RP Internet (www.rpi.net.au).
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifs_debug.h"
+#include "cifsproto.h"
+
+/*****************************************************************************
+ *
+ * Basic ASN.1 decoding routines (gxsnmp author Dirk Wisse)
+ *
+ *****************************************************************************/
+
+/* Class */
+#define ASN1_UNI	0	/* Universal */
+#define ASN1_APL	1	/* Application */
+#define ASN1_CTX	2	/* Context */
+#define ASN1_PRV	3	/* Private */
+
+/* Tag */
+#define ASN1_EOC	0	/* End Of Contents or N/A */
+#define ASN1_BOL	1	/* Boolean */
+#define ASN1_INT	2	/* Integer */
+#define ASN1_BTS	3	/* Bit String */
+#define ASN1_OTS	4	/* Octet String */
+#define ASN1_NUL	5	/* Null */
+#define ASN1_OJI	6	/* Object Identifier  */
+#define ASN1_OJD	7	/* Object Description */
+#define ASN1_EXT	8	/* External */
+#define ASN1_SEQ	16	/* Sequence */
+#define ASN1_SET	17	/* Set */
+#define ASN1_NUMSTR	18	/* Numerical String */
+#define ASN1_PRNSTR	19	/* Printable String */
+#define ASN1_TEXSTR	20	/* Teletext String */
+#define ASN1_VIDSTR	21	/* Video String */
+#define ASN1_IA5STR	22	/* IA5 String */
+#define ASN1_UNITIM	23	/* Universal Time */
+#define ASN1_GENTIM	24	/* General Time */
+#define ASN1_GRASTR	25	/* Graphical String */
+#define ASN1_VISSTR	26	/* Visible String */
+#define ASN1_GENSTR	27	/* General String */
+
+/* Primitive / Constructed methods*/
+#define ASN1_PRI	0	/* Primitive */
+#define ASN1_CON	1	/* Constructed */
+
+/*
+ * Error codes.
+ */
+#define ASN1_ERR_NOERROR		0
+#define ASN1_ERR_DEC_EMPTY		2
+#define ASN1_ERR_DEC_EOC_MISMATCH	3
+#define ASN1_ERR_DEC_LENGTH_MISMATCH	4
+#define ASN1_ERR_DEC_BADVALUE		5
+
+#define SPNEGO_OID_LEN 7
+#define NTLMSSP_OID_LEN  10
+static unsigned long SPNEGO_OID[7] = { 1, 3, 6, 1, 5, 5, 2 };
+static unsigned long NTLMSSP_OID[10] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10 };
+
+/* 
+ * ASN.1 context.
+ */
+struct asn1_ctx {
+	int error;		/* Error condition */
+	unsigned char *pointer;	/* Octet just to be decoded */
+	unsigned char *begin;	/* First octet */
+	unsigned char *end;	/* Octet after last octet */
+};
+
+/*
+ * Octet string (not null terminated)
+ */
+struct asn1_octstr {
+	unsigned char *data;
+	unsigned int len;
+};
+
+static void
+asn1_open(struct asn1_ctx *ctx, unsigned char *buf, unsigned int len)
+{
+	ctx->begin = buf;
+	ctx->end = buf + len;
+	ctx->pointer = buf;
+	ctx->error = ASN1_ERR_NOERROR;
+}
+
+static unsigned char
+asn1_octet_decode(struct asn1_ctx *ctx, unsigned char *ch)
+{
+	if (ctx->pointer >= ctx->end) {
+		ctx->error = ASN1_ERR_DEC_EMPTY;
+		return 0;
+	}
+	*ch = *(ctx->pointer)++;
+	return 1;
+}
+
+static unsigned char
+asn1_tag_decode(struct asn1_ctx *ctx, unsigned int *tag)
+{
+	unsigned char ch;
+
+	*tag = 0;
+
+	do {
+		if (!asn1_octet_decode(ctx, &ch))
+			return 0;
+		*tag <<= 7;
+		*tag |= ch & 0x7F;
+	} while ((ch & 0x80) == 0x80);
+	return 1;
+}
+
+static unsigned char
+asn1_id_decode(struct asn1_ctx *ctx,
+	       unsigned int *cls, unsigned int *con, unsigned int *tag)
+{
+	unsigned char ch;
+
+	if (!asn1_octet_decode(ctx, &ch))
+		return 0;
+
+	*cls = (ch & 0xC0) >> 6;
+	*con = (ch & 0x20) >> 5;
+	*tag = (ch & 0x1F);
+
+	if (*tag == 0x1F) {
+		if (!asn1_tag_decode(ctx, tag))
+			return 0;
+	}
+	return 1;
+}
+
+static unsigned char
+asn1_length_decode(struct asn1_ctx *ctx, unsigned int *def, unsigned int *len)
+{
+	unsigned char ch, cnt;
+
+	if (!asn1_octet_decode(ctx, &ch))
+		return 0;
+
+	if (ch == 0x80)
+		*def = 0;
+	else {
+		*def = 1;
+
+		if (ch < 0x80)
+			*len = ch;
+		else {
+			cnt = (unsigned char) (ch & 0x7F);
+			*len = 0;
+
+			while (cnt > 0) {
+				if (!asn1_octet_decode(ctx, &ch))
+					return 0;
+				*len <<= 8;
+				*len |= ch;
+				cnt--;
+			}
+		}
+	}
+	return 1;
+}
+
+static unsigned char
+asn1_header_decode(struct asn1_ctx *ctx,
+		   unsigned char **eoc,
+		   unsigned int *cls, unsigned int *con, unsigned int *tag)
+{
+	unsigned int def, len;
+
+	if (!asn1_id_decode(ctx, cls, con, tag))
+		return 0;
+
+	if (!asn1_length_decode(ctx, &def, &len))
+		return 0;
+
+	if (def)
+		*eoc = ctx->pointer + len;
+	else
+		*eoc = NULL;
+	return 1;
+}
+
+static unsigned char
+asn1_eoc_decode(struct asn1_ctx *ctx, unsigned char *eoc)
+{
+	unsigned char ch;
+
+	if (eoc == NULL) {
+		if (!asn1_octet_decode(ctx, &ch))
+			return 0;
+
+		if (ch != 0x00) {
+			ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;
+			return 0;
+		}
+
+		if (!asn1_octet_decode(ctx, &ch))
+			return 0;
+
+		if (ch != 0x00) {
+			ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;
+			return 0;
+		}
+		return 1;
+	} else {
+		if (ctx->pointer != eoc) {
+			ctx->error = ASN1_ERR_DEC_LENGTH_MISMATCH;
+			return 0;
+		}
+		return 1;
+	}
+}
+
+/* static unsigned char asn1_null_decode(struct asn1_ctx *ctx,
+				      unsigned char *eoc)
+{
+	ctx->pointer = eoc;
+	return 1;
+}
+
+static unsigned char asn1_long_decode(struct asn1_ctx *ctx,
+				      unsigned char *eoc, long *integer)
+{
+	unsigned char ch;
+	unsigned int len;
+
+	if (!asn1_octet_decode(ctx, &ch))
+		return 0;
+
+	*integer = (signed char) ch;
+	len = 1;
+
+	while (ctx->pointer < eoc) {
+		if (++len > sizeof(long)) {
+			ctx->error = ASN1_ERR_DEC_BADVALUE;
+			return 0;
+		}
+
+		if (!asn1_octet_decode(ctx, &ch))
+			return 0;
+
+		*integer <<= 8;
+		*integer |= ch;
+	}
+	return 1;
+}
+
+static unsigned char asn1_uint_decode(struct asn1_ctx *ctx,
+				      unsigned char *eoc,
+				      unsigned int *integer)
+{
+	unsigned char ch;
+	unsigned int len;
+
+	if (!asn1_octet_decode(ctx, &ch))
+		return 0;
+
+	*integer = ch;
+	if (ch == 0)
+		len = 0;
+	else
+		len = 1;
+
+	while (ctx->pointer < eoc) {
+		if (++len > sizeof(unsigned int)) {
+			ctx->error = ASN1_ERR_DEC_BADVALUE;
+			return 0;
+		}
+
+		if (!asn1_octet_decode(ctx, &ch))
+			return 0;
+
+		*integer <<= 8;
+		*integer |= ch;
+	}
+	return 1;
+}
+
+static unsigned char asn1_ulong_decode(struct asn1_ctx *ctx,
+				       unsigned char *eoc,
+				       unsigned long *integer)
+{
+	unsigned char ch;
+	unsigned int len;
+
+	if (!asn1_octet_decode(ctx, &ch))
+		return 0;
+
+	*integer = ch;
+	if (ch == 0)
+		len = 0;
+	else
+		len = 1;
+
+	while (ctx->pointer < eoc) {
+		if (++len > sizeof(unsigned long)) {
+			ctx->error = ASN1_ERR_DEC_BADVALUE;
+			return 0;
+		}
+
+		if (!asn1_octet_decode(ctx, &ch))
+			return 0;
+
+		*integer <<= 8;
+		*integer |= ch;
+	}
+	return 1;
+} 
+
+static unsigned char
+asn1_octets_decode(struct asn1_ctx *ctx,
+		   unsigned char *eoc,
+		   unsigned char **octets, unsigned int *len)
+{
+	unsigned char *ptr;
+
+	*len = 0;
+
+	*octets = kmalloc(eoc - ctx->pointer, GFP_ATOMIC);
+	if (*octets == NULL) {
+		return 0;
+	}
+
+	ptr = *octets;
+	while (ctx->pointer < eoc) {
+		if (!asn1_octet_decode(ctx, (unsigned char *) ptr++)) {
+			kfree(*octets);
+			*octets = NULL;
+			return 0;
+		}
+		(*len)++;
+	}
+	return 1;
+} */
+
+static unsigned char
+asn1_subid_decode(struct asn1_ctx *ctx, unsigned long *subid)
+{
+	unsigned char ch;
+
+	*subid = 0;
+
+	do {
+		if (!asn1_octet_decode(ctx, &ch))
+			return 0;
+
+		*subid <<= 7;
+		*subid |= ch & 0x7F;
+	} while ((ch & 0x80) == 0x80);
+	return 1;
+}
+
+static int 
+asn1_oid_decode(struct asn1_ctx *ctx,
+		unsigned char *eoc, unsigned long **oid, unsigned int *len)
+{
+	unsigned long subid;
+	unsigned int size;
+	unsigned long *optr;
+
+	size = eoc - ctx->pointer + 1;
+	*oid = kmalloc(size * sizeof (unsigned long), GFP_ATOMIC);
+	if (*oid == NULL) {
+		return 0;
+	}
+
+	optr = *oid;
+
+	if (!asn1_subid_decode(ctx, &subid)) {
+		kfree(*oid);
+		*oid = NULL;
+		return 0;
+	}
+
+	if (subid < 40) {
+		optr[0] = 0;
+		optr[1] = subid;
+	} else if (subid < 80) {
+		optr[0] = 1;
+		optr[1] = subid - 40;
+	} else {
+		optr[0] = 2;
+		optr[1] = subid - 80;
+	}
+
+	*len = 2;
+	optr += 2;
+
+	while (ctx->pointer < eoc) {
+		if (++(*len) > size) {
+			ctx->error = ASN1_ERR_DEC_BADVALUE;
+			kfree(*oid);
+			*oid = NULL;
+			return 0;
+		}
+
+		if (!asn1_subid_decode(ctx, optr++)) {
+			kfree(*oid);
+			*oid = NULL;
+			return 0;
+		}
+	}
+	return 1;
+}
+
+static int
+compare_oid(unsigned long *oid1, unsigned int oid1len,
+	    unsigned long *oid2, unsigned int oid2len)
+{
+	unsigned int i;
+
+	if (oid1len != oid2len)
+		return 0;
+	else {
+		for (i = 0; i < oid1len; i++) {
+			if (oid1[i] != oid2[i])
+				return 0;
+		}
+		return 1;
+	}
+}
+
+	/* BB check for endian conversion issues here */
+
+int
+decode_negTokenInit(unsigned char *security_blob, int length,
+		    enum securityEnum *secType)
+{
+	struct asn1_ctx ctx;
+	unsigned char *end;
+	unsigned char *sequence_end;
+	unsigned long *oid = NULL;
+	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, ("Error decoding negTokenInit header "));
+		return 0;
+	} else if ((cls != ASN1_APL) || (con != ASN1_CON)
+		   || (tag != ASN1_EOC)) {
+		cFYI(1, ("cls = %d con = %d tag = %d", cls, con, tag));
+		return 0;
+	} else {
+		/*      remember to free obj->oid */
+		rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
+		if (rc) {
+			if ((tag == ASN1_OJI) && (cls == ASN1_PRI)) {
+				rc = asn1_oid_decode(&ctx, end, &oid, &oidlen);
+				if (rc) {
+					rc = compare_oid(oid, oidlen,
+							 SPNEGO_OID,
+							 SPNEGO_OID_LEN);
+					kfree(oid);
+				}
+			} else
+				rc = 0;
+		}
+
+		if (!rc) {
+			cFYI(1, ("Error decoding negTokenInit header"));
+			return 0;
+		}
+
+		if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
+			cFYI(1, ("Error decoding negTokenInit "));
+			return 0;
+		} else if ((cls != ASN1_CTX) || (con != ASN1_CON)
+			   || (tag != ASN1_EOC)) {
+			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, ("Error decoding negTokenInit "));
+			return 0;
+		} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
+			   || (tag != ASN1_SEQ)) {
+			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, ("Error decoding 2nd part of negTokenInit "));
+			return 0;
+		} else if ((cls != ASN1_CTX) || (con != ASN1_CON)
+			   || (tag != ASN1_EOC)) {
+			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, &sequence_end, &cls, &con, &tag) == 0) {
+			cFYI(1, ("Error decoding 2nd part of negTokenInit "));
+			return 0;
+		} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
+			   || (tag != ASN1_SEQ)) {
+			cFYI(1,
+			     ("cls = %d con = %d tag = %d end = %p (%d) exit 1",
+			      cls, con, tag, end, *end));
+			return 0;
+		}
+
+		while (!asn1_eoc_decode(&ctx, sequence_end)) {
+			rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
+			if (!rc) {
+				cFYI(1,
+				     ("Error 1 decoding negTokenInit header exit 2"));
+				return 0;
+			}
+			if ((tag == ASN1_OJI) && (con == ASN1_PRI)) {
+				rc = asn1_oid_decode(&ctx, end, &oid, &oidlen);
+				if(rc) {		
+					cFYI(1,
+					  ("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,
+						 NTLMSSP_OID_LEN);
+					if(oid)
+						kfree(oid);
+					if (rc)
+						use_ntlmssp = TRUE;
+				}
+			} else {
+				cFYI(1,("This should be an oid what is going on? "));
+			}
+		}
+
+		if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
+			cFYI(1,
+			     ("Error decoding last part of negTokenInit exit 3"));
+			return 0;
+		} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {	/* tag = 3 indicating mechListMIC */
+			cFYI(1,
+			     ("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,
+			     ("Error decoding last part of negTokenInit exit 5"));
+			return 0;
+		} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
+			   || (tag != ASN1_SEQ)) {
+			cFYI(1,
+			     ("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,
+			     ("Error decoding last part of negTokenInit exit 7"));
+			return 0;
+		} else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
+			cFYI(1,
+			     ("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,
+			     ("Error decoding last part of negTokenInit exit 9"));
+			return 0;
+		} else if ((cls != ASN1_UNI) || (con != ASN1_PRI)
+			   || (tag != ASN1_GENSTR)) {
+			cFYI(1,
+			     ("Exit 10 cls = %d con = %d tag = %d end = %p (%d)",
+			      cls, con, tag, end, *end));
+			return 0;
+		}
+		cFYI(1, ("Need to call asn1_octets_decode() function for this %s", ctx.pointer));	/* is this UTF-8 or ASCII? */
+	}
+
+	/* if (use_kerberos) 
+	   *secType = Kerberos 
+	   else */
+	if (use_ntlmssp) {
+		*secType = NTLMSSP;
+	}
+
+	return 1;
+}
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
new file mode 100644
index 0000000..db28b56
--- /dev/null
+++ b/fs/cifs/cifs_debug.c
@@ -0,0 +1,805 @@
+/*
+ *   fs/cifs_debug.c
+ *
+ *   Copyright (C) International Business Machines  Corp., 2000,2003
+ *
+ *   Modified by Steve French (sfrench@us.ibm.com)
+ *
+ *   This program is free software;  you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or 
+ *   (at your option) any later version.
+ * 
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program;  if not, write to the Free Software 
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <asm/uaccess.h>
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+
+void
+cifs_dump_mem(char *label, void *data, int length)
+{
+	int i, j;
+	int *intptr = data;
+	char *charptr = data;
+	char buf[10], line[80];
+
+	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++) {
+			sprintf(buf, " %08x", intptr[i / 4 + j]);
+			strcat(line, buf);
+		}
+		buf[0] = ' ';
+		buf[2] = 0;
+		for (j = 0; (j < 16) && (i + j < length); j++) {
+			buf[1] = isprint(charptr[i + j]) ? charptr[i + j] : '.';
+			strcat(line, buf);
+		}
+		printk(KERN_DEBUG "%s\n", line);
+	}
+}
+
+#ifdef CONFIG_PROC_FS
+static int
+cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
+		     int count, int *eof, void *data)
+{
+	struct list_head *tmp;
+	struct list_head *tmp1;
+	struct mid_q_entry * mid_entry;
+	struct cifsSesInfo *ses;
+	struct cifsTconInfo *tcon;
+	int i;
+	int length = 0;
+	char * original_buf = buf;
+
+	*beginBuffer = buf + offset;
+
+	
+	length =
+	    sprintf(buf,
+		    "Display Internal CIFS Data Structures for Debugging\n"
+		    "---------------------------------------------------\n");
+	buf += length;
+
+	length = sprintf(buf, "Servers:\n");
+	buf += length;
+
+	i = 0;
+	read_lock(&GlobalSMBSeslock);
+	list_for_each(tmp, &GlobalSMBSessionList) {
+		i++;
+		ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
+		length =
+		    sprintf(buf,
+			    "\n%d) Name: %s  Domain: %s Mounts: %d ServerOS: %s  \n\tServerNOS: %s\tCapabilities: 0x%x\n\tSMB session status: %d\t",
+				i, ses->serverName, ses->serverDomain, atomic_read(&ses->inUse),
+				ses->serverOS, ses->serverNOS, ses->capabilities,ses->status);
+		buf += length;
+		if(ses->server) {
+			buf += sprintf(buf, "TCP status: %d\n\tLocal Users To Server: %d SecMode: 0x%x Req Active: %d",
+				ses->server->tcpStatus,
+				atomic_read(&ses->server->socketUseCount),
+				ses->server->secMode,
+				atomic_read(&ses->server->inFlight));
+			
+			length = sprintf(buf, "\nMIDs: \n");
+			buf += length;
+
+			spin_lock(&GlobalMid_Lock);
+			list_for_each(tmp1, &ses->server->pending_mid_q) {
+				mid_entry = list_entry(tmp1, struct
+					mid_q_entry,
+					qhead);
+				if(mid_entry) {
+					length = sprintf(buf,"State: %d com: %d pid: %d tsk: %p mid %d\n",mid_entry->midState,mid_entry->command,mid_entry->pid,mid_entry->tsk,mid_entry->mid);
+					buf += length;
+				}
+			}
+			spin_unlock(&GlobalMid_Lock); 
+		}
+
+	}
+	read_unlock(&GlobalSMBSeslock);
+	sprintf(buf, "\n");
+	buf++;
+
+	length = sprintf(buf, "\nShares:\n");
+	buf += length;
+
+	i = 0;
+	read_lock(&GlobalSMBSeslock);
+	list_for_each(tmp, &GlobalTreeConnectionList) {
+		__u32 dev_type;
+		i++;
+		tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
+		dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
+		length =
+		    sprintf(buf,
+			    "\n%d) %s Uses: %d Type: %s Characteristics: 0x%x Attributes: 0x%x\nPathComponentMax: %d Status: %d",
+			    i, tcon->treeName,
+			    atomic_read(&tcon->useCount),
+			    tcon->nativeFileSystem,
+			    le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics),
+			    le32_to_cpu(tcon->fsAttrInfo.Attributes),
+			    le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
+			    tcon->tidStatus);
+		buf += length;        
+		if (dev_type == FILE_DEVICE_DISK)
+			length = sprintf(buf, " type: DISK ");
+		else if (dev_type == FILE_DEVICE_CD_ROM)
+			length = sprintf(buf, " type: CDROM ");
+		else
+			length =
+			    sprintf(buf, " type: %d ", dev_type);
+		buf += length;
+		if(tcon->tidStatus == CifsNeedReconnect) {
+			buf += sprintf(buf, "\tDISCONNECTED ");
+			length += 14;
+		}
+	}
+	read_unlock(&GlobalSMBSeslock);
+
+	length = sprintf(buf, "\n");
+	buf += length;
+
+	/* BB add code to dump additional info such as TCP session info now */
+	/* Now calculate total size of returned data */
+	length = buf - original_buf;
+
+	if(offset + count >= length)
+		*eof = 1;
+	if(length < offset) {
+		*eof = 1;
+		return 0;
+	} else {
+		length = length - offset;
+	}
+	if (length > count)
+		length = count;
+
+	return length;
+}
+
+#ifdef CONFIG_CIFS_STATS
+static int
+cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
+		  int count, int *eof, void *data)
+{
+	int item_length,i,length;
+	struct list_head *tmp;
+	struct cifsTconInfo *tcon;
+
+	*beginBuffer = buf + offset;
+
+	length = sprintf(buf,
+			"Resources in use\nCIFS Session: %d\n",
+			sesInfoAllocCount.counter);
+	buf += length;
+	item_length = 
+		sprintf(buf,"Share (unique mount targets): %d\n",
+			tconInfoAllocCount.counter);
+	length += item_length;
+	buf += item_length;      
+	item_length = 
+		sprintf(buf,"SMB Request/Response Buffer: %d Pool size: %d\n",
+			bufAllocCount.counter,cifs_min_rcv + tcpSesAllocCount.counter);
+	length += item_length;
+	buf += item_length;
+	item_length = 
+		sprintf(buf,"SMB Small Req/Resp Buffer: %d Pool size: %d\n",
+			smBufAllocCount.counter,cifs_min_small);
+	length += item_length;
+	buf += item_length;
+	item_length = 
+		sprintf(buf,"Operations (MIDs): %d\n",
+			midCount.counter);
+	length += item_length;
+	buf += item_length;
+	item_length = sprintf(buf,
+		"\n%d session %d share reconnects\n",
+		tcpSesReconnectCount.counter,tconInfoReconnectCount.counter);
+	length += item_length;
+	buf += item_length;
+
+	item_length = sprintf(buf,
+		"Total vfs operations: %d maximum at one time: %d\n",
+		GlobalCurrentXid,GlobalMaxActiveXid);
+	length += item_length;
+	buf += item_length;
+
+	i = 0;
+	read_lock(&GlobalSMBSeslock);
+	list_for_each(tmp, &GlobalTreeConnectionList) {
+		i++;
+		tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
+		item_length = sprintf(buf,"\n%d) %s",i, tcon->treeName);
+		buf += item_length;
+		length += item_length;
+		if(tcon->tidStatus == CifsNeedReconnect) {
+			buf += sprintf(buf, "\tDISCONNECTED ");
+			length += 14;
+		}
+		item_length = sprintf(buf,"\nSMBs: %d Oplock Breaks: %d",
+			atomic_read(&tcon->num_smbs_sent),
+			atomic_read(&tcon->num_oplock_brks));
+		buf += item_length;
+		length += item_length;
+		item_length = sprintf(buf,"\nReads: %d Bytes %lld",
+			atomic_read(&tcon->num_reads),
+			(long long)(tcon->bytes_read));
+		buf += item_length;
+		length += item_length;
+		item_length = sprintf(buf,"\nWrites: %d Bytes: %lld",
+			atomic_read(&tcon->num_writes),
+			(long long)(tcon->bytes_written));
+		buf += item_length;
+		length += item_length;
+		item_length = sprintf(buf,
+			"\nOpens: %d Deletes: %d\nMkdirs: %d Rmdirs: %d",
+			atomic_read(&tcon->num_opens),
+			atomic_read(&tcon->num_deletes),
+			atomic_read(&tcon->num_mkdirs),
+			atomic_read(&tcon->num_rmdirs));
+		buf += item_length;
+		length += item_length;
+		item_length = sprintf(buf,
+			"\nRenames: %d T2 Renames %d",
+			atomic_read(&tcon->num_renames),
+			atomic_read(&tcon->num_t2renames));
+		buf += item_length;
+		length += item_length;
+	}
+	read_unlock(&GlobalSMBSeslock);
+
+	buf += sprintf(buf,"\n");
+	length++;
+
+	if(offset + count >= length)
+		*eof = 1;
+	if(length < offset) {
+		*eof = 1;
+		return 0;
+	} else {
+		length = length - offset;
+	}
+	if (length > count)
+		length = count;
+		
+	return length;
+}
+#endif
+
+static struct proc_dir_entry *proc_fs_cifs;
+read_proc_t cifs_txanchor_read;
+static read_proc_t cifsFYI_read;
+static write_proc_t cifsFYI_write;
+static read_proc_t oplockEnabled_read;
+static write_proc_t oplockEnabled_write;
+static read_proc_t lookupFlag_read;
+static write_proc_t lookupFlag_write;
+static read_proc_t traceSMB_read;
+static write_proc_t traceSMB_write;
+static read_proc_t multiuser_mount_read;
+static write_proc_t multiuser_mount_write;
+static read_proc_t extended_security_read;
+static write_proc_t extended_security_write;
+static read_proc_t ntlmv2_enabled_read;
+static write_proc_t ntlmv2_enabled_write;
+static read_proc_t packet_signing_enabled_read;
+static write_proc_t packet_signing_enabled_write;
+static read_proc_t quotaEnabled_read;
+static write_proc_t quotaEnabled_write;
+static read_proc_t linuxExtensionsEnabled_read;
+static write_proc_t linuxExtensionsEnabled_write;
+
+void
+cifs_proc_init(void)
+{
+	struct proc_dir_entry *pde;
+
+	proc_fs_cifs = proc_mkdir("cifs", proc_root_fs);
+	if (proc_fs_cifs == NULL)
+		return;
+
+	proc_fs_cifs->owner = THIS_MODULE;
+	create_proc_read_entry("DebugData", 0, proc_fs_cifs,
+				cifs_debug_data_read, NULL);
+
+#ifdef CONFIG_CIFS_STATS
+	create_proc_read_entry("Stats", 0, proc_fs_cifs,
+				cifs_stats_read, NULL);
+#endif
+	pde = create_proc_read_entry("cifsFYI", 0, proc_fs_cifs,
+				cifsFYI_read, NULL);
+	if (pde)
+		pde->write_proc = cifsFYI_write;
+
+	pde =
+	    create_proc_read_entry("traceSMB", 0, proc_fs_cifs,
+				traceSMB_read, NULL);
+	if (pde)
+		pde->write_proc = traceSMB_write;
+
+	pde = create_proc_read_entry("OplockEnabled", 0, proc_fs_cifs,
+				oplockEnabled_read, NULL);
+	if (pde)
+		pde->write_proc = oplockEnabled_write;
+
+	pde = create_proc_read_entry("ReenableOldCifsReaddirCode", 0, proc_fs_cifs,
+				quotaEnabled_read, NULL);
+	if (pde)
+		pde->write_proc = quotaEnabled_write;
+
+	pde = create_proc_read_entry("LinuxExtensionsEnabled", 0, proc_fs_cifs,
+				linuxExtensionsEnabled_read, NULL);
+	if (pde)
+		pde->write_proc = linuxExtensionsEnabled_write;
+
+	pde =
+	    create_proc_read_entry("MultiuserMount", 0, proc_fs_cifs,
+				multiuser_mount_read, NULL);
+	if (pde)
+		pde->write_proc = multiuser_mount_write;
+
+	pde =
+	    create_proc_read_entry("ExtendedSecurity", 0, proc_fs_cifs,
+				extended_security_read, NULL);
+	if (pde)
+		pde->write_proc = extended_security_write;
+
+	pde =
+	create_proc_read_entry("LookupCacheEnabled", 0, proc_fs_cifs,
+				lookupFlag_read, NULL);
+	if (pde)
+		pde->write_proc = lookupFlag_write;
+
+	pde =
+	    create_proc_read_entry("NTLMV2Enabled", 0, proc_fs_cifs,
+				ntlmv2_enabled_read, NULL);
+	if (pde)
+		pde->write_proc = ntlmv2_enabled_write;
+
+	pde =
+	    create_proc_read_entry("PacketSigningEnabled", 0, proc_fs_cifs,
+				packet_signing_enabled_read, NULL);
+	if (pde)
+		pde->write_proc = packet_signing_enabled_write;
+}
+
+void
+cifs_proc_clean(void)
+{
+	if (proc_fs_cifs == NULL)
+		return;
+
+	remove_proc_entry("DebugData", proc_fs_cifs);
+	remove_proc_entry("cifsFYI", proc_fs_cifs);
+	remove_proc_entry("traceSMB", proc_fs_cifs);
+#ifdef CONFIG_CIFS_STATS
+	remove_proc_entry("Stats", proc_fs_cifs);
+#endif
+	remove_proc_entry("MultiuserMount", proc_fs_cifs);
+	remove_proc_entry("OplockEnabled", proc_fs_cifs);
+	remove_proc_entry("NTLMV2Enabled",proc_fs_cifs);
+	remove_proc_entry("ExtendedSecurity",proc_fs_cifs);
+	remove_proc_entry("PacketSigningEnabled",proc_fs_cifs);
+	remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs);
+	remove_proc_entry("ReenableOldCifsReaddirCode",proc_fs_cifs);
+	remove_proc_entry("LookupCacheEnabled",proc_fs_cifs);
+	remove_proc_entry("cifs", proc_root_fs);
+}
+
+static int
+cifsFYI_read(char *page, char **start, off_t off, int count,
+	     int *eof, void *data)
+{
+	int len;
+
+	len = sprintf(page, "%d\n", cifsFYI);
+
+	len -= off;
+	*start = page + off;
+
+	if (len > count)
+		len = count;
+	else
+		*eof = 1;
+
+	if (len < 0)
+		len = 0;
+
+	return len;
+}
+static int
+cifsFYI_write(struct file *file, const char __user *buffer,
+	      unsigned long count, void *data)
+{
+	char c;
+	int rc;
+
+	rc = get_user(c, buffer);
+	if (rc)
+		return rc;
+	if (c == '0' || c == 'n' || c == 'N')
+		cifsFYI = 0;
+	else if (c == '1' || c == 'y' || c == 'Y')
+		cifsFYI = 1;
+
+	return count;
+}
+
+static int
+oplockEnabled_read(char *page, char **start, off_t off,
+		   int count, int *eof, void *data)
+{
+	int len;
+
+	len = sprintf(page, "%d\n", oplockEnabled);
+
+	len -= off;
+	*start = page + off;
+
+	if (len > count)
+		len = count;
+	else
+		*eof = 1;
+
+	if (len < 0)
+		len = 0;
+
+	return len;
+}
+static int
+oplockEnabled_write(struct file *file, const char __user *buffer,
+		    unsigned long count, void *data)
+{
+	char c;
+	int rc;
+
+	rc = get_user(c, buffer);
+	if (rc)
+		return rc;
+	if (c == '0' || c == 'n' || c == 'N')
+		oplockEnabled = 0;
+	else if (c == '1' || c == 'y' || c == 'Y')
+		oplockEnabled = 1;
+
+	return count;
+}
+
+static int
+quotaEnabled_read(char *page, char **start, off_t off,
+                   int count, int *eof, void *data)
+{
+        int len;
+
+        len = sprintf(page, "%d\n", experimEnabled);
+/* could also check if quotas are enabled in kernel
+	as a whole first */
+        len -= off;
+        *start = page + off;
+
+        if (len > count)
+                len = count;
+        else
+                *eof = 1;
+
+        if (len < 0)
+                len = 0;
+
+        return len;
+}
+static int
+quotaEnabled_write(struct file *file, const char __user *buffer,
+                    unsigned long count, void *data)
+{
+        char c;
+        int rc;
+
+        rc = get_user(c, buffer);
+        if (rc)
+                return rc;
+        if (c == '0' || c == 'n' || c == 'N')
+                experimEnabled = 0;
+        else if (c == '1' || c == 'y' || c == 'Y')
+                experimEnabled = 1;
+
+        return count;
+}
+
+static int
+linuxExtensionsEnabled_read(char *page, char **start, off_t off,
+                   int count, int *eof, void *data)
+{
+        int len;
+
+        len = sprintf(page, "%d\n", linuxExtEnabled);
+/* could also check if quotas are enabled in kernel
+	as a whole first */
+        len -= off;
+        *start = page + off;
+
+        if (len > count)
+                len = count;
+        else
+                *eof = 1;
+
+        if (len < 0)
+                len = 0;
+
+        return len;
+}
+static int
+linuxExtensionsEnabled_write(struct file *file, const char __user *buffer,
+                    unsigned long count, void *data)
+{
+        char c;
+        int rc;
+
+        rc = get_user(c, buffer);
+        if (rc)
+                return rc;
+        if (c == '0' || c == 'n' || c == 'N')
+                linuxExtEnabled = 0;
+        else if (c == '1' || c == 'y' || c == 'Y')
+                linuxExtEnabled = 1;
+
+        return count;
+}
+
+
+static int
+lookupFlag_read(char *page, char **start, off_t off,
+		   int count, int *eof, void *data)
+{
+	int len;
+
+	len = sprintf(page, "%d\n", lookupCacheEnabled);
+
+	len -= off;
+	*start = page + off;
+
+	if (len > count)
+		len = count;
+	else
+		*eof = 1;
+
+	if (len < 0)
+		len = 0;
+
+	return len;
+}
+static int
+lookupFlag_write(struct file *file, const char __user *buffer,
+		    unsigned long count, void *data)
+{
+	char c;
+	int rc;
+
+	rc = get_user(c, buffer);
+	if (rc)
+		return rc;
+	if (c == '0' || c == 'n' || c == 'N')
+		lookupCacheEnabled = 0;
+	else if (c == '1' || c == 'y' || c == 'Y')
+		lookupCacheEnabled = 1;
+
+	return count;
+}
+static int
+traceSMB_read(char *page, char **start, off_t off, int count,
+	      int *eof, void *data)
+{
+	int len;
+
+	len = sprintf(page, "%d\n", traceSMB);
+
+	len -= off;
+	*start = page + off;
+
+	if (len > count)
+		len = count;
+	else
+		*eof = 1;
+
+	if (len < 0)
+		len = 0;
+
+	return len;
+}
+static int
+traceSMB_write(struct file *file, const char __user *buffer,
+	       unsigned long count, void *data)
+{
+	char c;
+	int rc;
+
+	rc = get_user(c, buffer);
+	if (rc)
+		return rc;
+	if (c == '0' || c == 'n' || c == 'N')
+		traceSMB = 0;
+	else if (c == '1' || c == 'y' || c == 'Y')
+		traceSMB = 1;
+
+	return count;
+}
+
+static int
+multiuser_mount_read(char *page, char **start, off_t off,
+		     int count, int *eof, void *data)
+{
+	int len;
+
+	len = sprintf(page, "%d\n", multiuser_mount);
+
+	len -= off;
+	*start = page + off;
+
+	if (len > count)
+		len = count;
+	else
+		*eof = 1;
+
+	if (len < 0)
+		len = 0;
+
+	return len;
+}
+static int
+multiuser_mount_write(struct file *file, const char __user *buffer,
+		      unsigned long count, void *data)
+{
+	char c;
+	int rc;
+
+	rc = get_user(c, buffer);
+	if (rc)
+		return rc;
+	if (c == '0' || c == 'n' || c == 'N')
+		multiuser_mount = 0;
+	else if (c == '1' || c == 'y' || c == 'Y')
+		multiuser_mount = 1;
+
+	return count;
+}
+
+static int
+extended_security_read(char *page, char **start, off_t off,
+		       int count, int *eof, void *data)
+{
+	int len;
+
+	len = sprintf(page, "%d\n", extended_security);
+
+	len -= off;
+	*start = page + off;
+
+	if (len > count)
+		len = count;
+	else
+		*eof = 1;
+
+	if (len < 0)
+		len = 0;
+
+	return len;
+}
+static int
+extended_security_write(struct file *file, const char __user *buffer,
+			unsigned long count, void *data)
+{
+	char c;
+	int rc;
+
+	rc = get_user(c, buffer);
+	if (rc)
+		return rc;
+	if (c == '0' || c == 'n' || c == 'N')
+		extended_security = 0;
+	else if (c == '1' || c == 'y' || c == 'Y')
+		extended_security = 1;
+
+	return count;
+}
+
+static int
+ntlmv2_enabled_read(char *page, char **start, off_t off,
+		       int count, int *eof, void *data)
+{
+	int len;
+
+	len = sprintf(page, "%d\n", ntlmv2_support);
+
+	len -= off;
+	*start = page + off;
+
+	if (len > count)
+		len = count;
+	else
+		*eof = 1;
+
+	if (len < 0)
+		len = 0;
+
+	return len;
+}
+static int
+ntlmv2_enabled_write(struct file *file, const char __user *buffer,
+			unsigned long count, void *data)
+{
+	char c;
+	int rc;
+
+	rc = get_user(c, buffer);
+	if (rc)
+		return rc;
+	if (c == '0' || c == 'n' || c == 'N')
+		ntlmv2_support = 0;
+	else if (c == '1' || c == 'y' || c == 'Y')
+		ntlmv2_support = 1;
+
+	return count;
+}
+
+static int
+packet_signing_enabled_read(char *page, char **start, off_t off,
+		       int count, int *eof, void *data)
+{
+	int len;
+
+	len = sprintf(page, "%d\n", sign_CIFS_PDUs);
+
+	len -= off;
+	*start = page + off;
+
+	if (len > count)
+		len = count;
+	else
+		*eof = 1;
+
+	if (len < 0)
+		len = 0;
+
+	return len;
+}
+static int
+packet_signing_enabled_write(struct file *file, const char __user *buffer,
+			unsigned long count, void *data)
+{
+	char c;
+	int rc;
+
+	rc = get_user(c, buffer);
+	if (rc)
+		return rc;
+	if (c == '0' || c == 'n' || c == 'N')
+		sign_CIFS_PDUs = 0;
+	else if (c == '1' || c == 'y' || c == 'Y')
+		sign_CIFS_PDUs = 1;
+	else if (c == '2')
+		sign_CIFS_PDUs = 2;
+
+	return count;
+}
+
+
+#endif
diff --git a/fs/cifs/cifs_debug.h b/fs/cifs/cifs_debug.h
new file mode 100644
index 0000000..bf24d28
--- /dev/null
+++ b/fs/cifs/cifs_debug.h
@@ -0,0 +1,66 @@
+/*
+ *
+ *   Copyright (c) International Business Machines  Corp., 2000,2002
+ *   Modified by Steve French (sfrench@us.ibm.com)
+ *
+ *   This program is free software;  you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program;  if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+*/
+#define CIFS_DEBUG		/* BB temporary */
+
+#ifndef _H_CIFS_DEBUG
+#define _H_CIFS_DEBUG
+
+void cifs_dump_mem(char *label, void *data, int length);
+extern int traceSMB;		/* flag which enables the function below */
+void dump_smb(struct smb_hdr *, int);
+
+/*
+ *	debug ON
+ *	--------
+ */
+#ifdef CIFS_DEBUG
+
+
+/* information message: e.g., configuration, major event */
+extern int cifsFYI;
+#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: */
+extern int cifsERROR;
+
+#define cEVENT(format,arg...) if (cifsERROR) printk(KERN_EVENT __FILE__ ": " format "\n" , ## arg)
+
+/* error event message: e.g., i/o error */
+#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 */
+#define cERROR(button,prspec)
+#define cEVENT(format,arg...)
+#define cFYI(button, prspec)
+#define cifserror(format,arg...)
+#endif		/* _CIFS_DEBUG */
+
+#endif				/* _H_CIFS_DEBUG */
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
new file mode 100644
index 0000000..77da902
--- /dev/null
+++ b/fs/cifs/cifs_fs_sb.h
@@ -0,0 +1,39 @@
+/*
+ *   fs/cifs/cifs_fs_sb.h
+ *
+ *   Copyright (c) International Business Machines  Corp., 2002,2004
+ *   Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU Lesser General Public License for more details.
+ *
+ */
+#ifndef _CIFS_FS_SB_H
+#define _CIFS_FS_SB_H
+
+#define CIFS_MOUNT_NO_PERM      1 /* do not do client vfs_perm check */
+#define CIFS_MOUNT_SET_UID      2 /* set current->euid in create etc. */
+#define CIFS_MOUNT_SERVER_INUM  4 /* inode numbers from uniqueid from server */
+#define CIFS_MOUNT_DIRECT_IO    8 /* do not write nor read through page cache */
+#define CIFS_MOUNT_NO_XATTR  0x10 /* if set - disable xattr support */
+
+struct cifs_sb_info {
+	struct cifsTconInfo *tcon;	/* primary mount */
+	struct list_head nested_tcon_q;
+	struct nls_table *local_nls;
+	unsigned int rsize;
+	unsigned int wsize;
+	uid_t	mnt_uid;
+	gid_t	mnt_gid;
+	mode_t	mnt_file_mode;
+	mode_t	mnt_dir_mode;
+	int     mnt_cifs_flags;
+};
+#endif				/* _CIFS_FS_SB_H */
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
new file mode 100644
index 0000000..a17adf4
--- /dev/null
+++ b/fs/cifs/cifs_unicode.c
@@ -0,0 +1,87 @@
+/*
+ *   fs/cifs/cifs_unicode.c
+ *
+ *   Copyright (c) International Business Machines  Corp., 2000,2002
+ *   Modified by Steve French (sfrench@us.ibm.com)
+ *
+ *   This program is free software;  you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or 
+ *   (at your option) any later version.
+ * 
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program;  if not, write to the Free Software 
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/fs.h>
+#include "cifs_unicode.h"
+#include "cifs_uniupr.h"
+#include "cifspdu.h"
+#include "cifs_debug.h"
+
+/*
+ * NAME:	cifs_strfromUCS()
+ *
+ * FUNCTION:	Convert little-endian unicode string to character string
+ *
+ */
+int
+cifs_strfromUCS_le(char *to, const wchar_t * from,	/* LITTLE ENDIAN */
+		   int len, const struct nls_table *codepage)
+{
+	int i;
+	int outlen = 0;
+
+	for (i = 0; (i < len) && from[i]; i++) {
+		int charlen;
+		/* 2.4.0 kernel or greater */
+		charlen =
+		    codepage->uni2char(le16_to_cpu(from[i]), &to[outlen],
+				       NLS_MAX_CHARSET_SIZE);
+		if (charlen > 0) {
+			outlen += charlen;
+		} else {
+			to[outlen++] = '?';
+		}
+	}
+	to[outlen] = 0;
+	return outlen;
+}
+
+/*
+ * NAME:	cifs_strtoUCS()
+ *
+ * FUNCTION:	Convert character string to unicode string
+ *
+ */
+int
+cifs_strtoUCS(wchar_t * to, const char *from, int len,
+	      const struct nls_table *codepage)
+{
+	int charlen;
+	int i;
+
+	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",
+				charlen));
+			to[i] = cpu_to_le16(0x003f);	/* a question mark */
+			charlen = 1;
+		}
+		to[i] = cpu_to_le16(to[i]);
+
+	}
+
+	to[i] = 0;
+	return i;
+}
+
diff --git a/fs/cifs/cifs_unicode.h b/fs/cifs/cifs_unicode.h
new file mode 100644
index 0000000..da8dde9
--- /dev/null
+++ b/fs/cifs/cifs_unicode.h
@@ -0,0 +1,353 @@
+/*
+ * cifs_unicode:  Unicode kernel case support
+ *
+ * Function:
+ *     Convert a unicode character to upper or lower case using
+ *     compressed tables.
+ *
+ *   Copyright (c) International Business Machines  Corp., 2000,2002
+ *
+ *   This program is free software;  you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or 
+ *   (at your option) any later version.
+ * 
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program;  if not, write to the Free Software 
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ *
+ * Notes:
+ *     These APIs are based on the C library functions.  The semantics
+ *     should match the C functions but with expanded size operands.
+ *
+ *     The upper/lower functions are based on a table created by mkupr.
+ *     This is a compressed table of upper and lower case conversion.
+ *
+ */
+
+#include <asm/byteorder.h>
+#include <linux/types.h>
+#include <linux/nls.h>
+
+#define  UNIUPR_NOLOWER		/* Example to not expand lower case tables */
+
+/* Just define what we want from uniupr.h.  We don't want to define the tables
+ * in each source file.
+ */
+#ifndef	UNICASERANGE_DEFINED
+struct UniCaseRange {
+	wchar_t start;
+	wchar_t end;
+	signed char *table;
+};
+#endif				/* UNICASERANGE_DEFINED */
+
+#ifndef UNIUPR_NOUPPER
+extern signed char CifsUniUpperTable[512];
+extern const struct UniCaseRange CifsUniUpperRange[];
+#endif				/* UNIUPR_NOUPPER */
+
+#ifndef UNIUPR_NOLOWER
+extern signed char UniLowerTable[512];
+extern struct UniCaseRange UniLowerRange[];
+#endif				/* UNIUPR_NOLOWER */
+
+#ifdef __KERNEL__
+int cifs_strfromUCS_le(char *, const wchar_t *, int, const struct nls_table *);
+int cifs_strtoUCS(wchar_t *, const char *, int, const struct nls_table *);
+#endif
+
+/*
+ * UniStrcat:  Concatenate the second string to the first
+ *
+ * Returns:
+ *     Address of the first string
+ */
+static inline wchar_t *
+UniStrcat(wchar_t * ucs1, const wchar_t * ucs2)
+{
+	wchar_t *anchor = ucs1;	/* save a pointer to start of ucs1 */
+
+	while (*ucs1++) ;	/* To end of first string */
+	ucs1--;			/* Return to the null */
+	while ((*ucs1++ = *ucs2++)) ;	/* copy string 2 over */
+	return anchor;
+}
+
+/*
+ * UniStrchr:  Find a character in a string
+ *
+ * Returns:
+ *     Address of first occurrence of character in string
+ *     or NULL if the character is not in the string
+ */
+static inline wchar_t *
+UniStrchr(const wchar_t * ucs, wchar_t uc)
+{
+	while ((*ucs != uc) && *ucs)
+		ucs++;
+
+	if (*ucs == uc)
+		return (wchar_t *) ucs;
+	return NULL;
+}
+
+/*
+ * UniStrcmp:  Compare two strings
+ *
+ * Returns:
+ *     < 0:  First string is less than second
+ *     = 0:  Strings are equal
+ *     > 0:  First string is greater than second
+ */
+static inline int
+UniStrcmp(const wchar_t * ucs1, const wchar_t * ucs2)
+{
+	while ((*ucs1 == *ucs2) && *ucs1) {
+		ucs1++;
+		ucs2++;
+	}
+	return (int) *ucs1 - (int) *ucs2;
+}
+
+/*
+ * UniStrcpy:  Copy a string
+ */
+static inline wchar_t *
+UniStrcpy(wchar_t * ucs1, const wchar_t * ucs2)
+{
+	wchar_t *anchor = ucs1;	/* save the start of result string */
+
+	while ((*ucs1++ = *ucs2++)) ;
+	return anchor;
+}
+
+/*
+ * UniStrlen:  Return the length of a string (in 16 bit Unicode chars not bytes)
+ */
+static inline size_t
+UniStrlen(const wchar_t * ucs1)
+{
+	int i = 0;
+
+	while (*ucs1++)
+		i++;
+	return i;
+}
+
+/*
+ * UniStrnlen:  Return the length (in 16 bit Unicode chars not bytes) of a string (length limited)
+ */
+static inline size_t
+UniStrnlen(const wchar_t * ucs1, int maxlen)
+{
+	int i = 0;
+
+	while (*ucs1++) {
+		i++;
+		if (i >= maxlen)
+			break;
+	}
+	return i;
+}
+
+/*
+ * UniStrncat:  Concatenate length limited string
+ */
+static inline wchar_t *
+UniStrncat(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
+{
+	wchar_t *anchor = ucs1;	/* save pointer to string 1 */
+
+	while (*ucs1++) ;
+	ucs1--;			/* point to null terminator of s1 */
+	while (n-- && (*ucs1 = *ucs2)) {	/* copy s2 after s1 */
+		ucs1++;
+		ucs2++;
+	}
+	*ucs1 = 0;		/* Null terminate the result */
+	return (anchor);
+}
+
+/*
+ * UniStrncmp:  Compare length limited string
+ */
+static inline int
+UniStrncmp(const wchar_t * ucs1, const wchar_t * ucs2, size_t n)
+{
+	if (!n)
+		return 0;	/* Null strings are equal */
+	while ((*ucs1 == *ucs2) && *ucs1 && --n) {
+		ucs1++;
+		ucs2++;
+	}
+	return (int) *ucs1 - (int) *ucs2;
+}
+
+/*
+ * UniStrncmp_le:  Compare length limited string - native to little-endian
+ */
+static inline int
+UniStrncmp_le(const wchar_t * ucs1, const wchar_t * ucs2, size_t n)
+{
+	if (!n)
+		return 0;	/* Null strings are equal */
+	while ((*ucs1 == __le16_to_cpu(*ucs2)) && *ucs1 && --n) {
+		ucs1++;
+		ucs2++;
+	}
+	return (int) *ucs1 - (int) __le16_to_cpu(*ucs2);
+}
+
+/*
+ * UniStrncpy:  Copy length limited string with pad
+ */
+static inline wchar_t *
+UniStrncpy(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
+{
+	wchar_t *anchor = ucs1;
+
+	while (n-- && *ucs2)	/* Copy the strings */
+		*ucs1++ = *ucs2++;
+
+	n++;
+	while (n--)		/* Pad with nulls */
+		*ucs1++ = 0;
+	return anchor;
+}
+
+/*
+ * UniStrncpy_le:  Copy length limited string with pad to little-endian
+ */
+static inline wchar_t *
+UniStrncpy_le(wchar_t * ucs1, const wchar_t * ucs2, size_t n)
+{
+	wchar_t *anchor = ucs1;
+
+	while (n-- && *ucs2)	/* Copy the strings */
+		*ucs1++ = __le16_to_cpu(*ucs2++);
+
+	n++;
+	while (n--)		/* Pad with nulls */
+		*ucs1++ = 0;
+	return anchor;
+}
+
+/*
+ * UniStrstr:  Find a string in a string
+ *
+ * Returns:
+ *     Address of first match found
+ *     NULL if no matching string is found
+ */
+static inline wchar_t *
+UniStrstr(const wchar_t * ucs1, const wchar_t * ucs2)
+{
+	const wchar_t *anchor1 = ucs1;
+	const wchar_t *anchor2 = ucs2;
+
+	while (*ucs1) {
+		if (*ucs1 == *ucs2) {	/* Partial match found */
+			ucs1++;
+			ucs2++;
+		} else {
+			if (!*ucs2)	/* Match found */
+				return (wchar_t *) anchor1;
+			ucs1 = ++anchor1;	/* No match */
+			ucs2 = anchor2;
+		}
+	}
+
+	if (!*ucs2)		/* Both end together */
+		return (wchar_t *) anchor1;	/* Match found */
+	return NULL;		/* No match */
+}
+
+#ifndef UNIUPR_NOUPPER
+/*
+ * UniToupper:  Convert a unicode character to upper case
+ */
+static inline wchar_t
+UniToupper(register wchar_t uc)
+{
+	register const struct UniCaseRange *rp;
+
+	if (uc < sizeof (CifsUniUpperTable)) {	/* Latin characters */
+		return uc + CifsUniUpperTable[uc];	/* Use base tables */
+	} else {
+		rp = CifsUniUpperRange;	/* Use range tables */
+		while (rp->start) {
+			if (uc < rp->start)	/* Before start of range */
+				return uc;	/* Uppercase = input */
+			if (uc <= rp->end)	/* In range */
+				return uc + rp->table[uc - rp->start];
+			rp++;	/* Try next range */
+		}
+	}
+	return uc;		/* Past last range */
+}
+
+/*
+ * UniStrupr:  Upper case a unicode string
+ */
+static inline wchar_t *
+UniStrupr(register wchar_t * upin)
+{
+	register wchar_t *up;
+
+	up = upin;
+	while (*up) {		/* For all characters */
+		*up = UniToupper(*up);
+		up++;
+	}
+	return upin;		/* Return input pointer */
+}
+#endif				/* UNIUPR_NOUPPER */
+
+#ifndef UNIUPR_NOLOWER
+/*
+ * UniTolower:  Convert a unicode character to lower case
+ */
+static inline wchar_t
+UniTolower(wchar_t uc)
+{
+	register struct UniCaseRange *rp;
+
+	if (uc < sizeof (UniLowerTable)) {	/* Latin characters */
+		return uc + UniLowerTable[uc];	/* Use base tables */
+	} else {
+		rp = UniLowerRange;	/* Use range tables */
+		while (rp->start) {
+			if (uc < rp->start)	/* Before start of range */
+				return uc;	/* Uppercase = input */
+			if (uc <= rp->end)	/* In range */
+				return uc + rp->table[uc - rp->start];
+			rp++;	/* Try next range */
+		}
+	}
+	return uc;		/* Past last range */
+}
+
+/*
+ * UniStrlwr:  Lower case a unicode string
+ */
+static inline wchar_t *
+UniStrlwr(register wchar_t * upin)
+{
+	register wchar_t *up;
+
+	up = upin;
+	while (*up) {		/* For all characters */
+		*up = UniTolower(*up);
+		up++;
+	}
+	return upin;		/* Return input pointer */
+}
+
+#endif
diff --git a/fs/cifs/cifs_uniupr.h b/fs/cifs/cifs_uniupr.h
new file mode 100644
index 0000000..decd138
--- /dev/null
+++ b/fs/cifs/cifs_uniupr.h
@@ -0,0 +1,253 @@
+/*
+ *   Copyright (c) International Business Machines  Corp., 2000,2002
+ *
+ *   This program is free software;  you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or 
+ *   (at your option) any later version.
+ * 
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program;  if not, write to the Free Software 
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * uniupr.h - Unicode compressed case ranges
+ *
+*/
+
+#ifndef UNIUPR_NOUPPER
+/*
+ * Latin upper case
+ */
+signed char CifsUniUpperTable[512] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 000-00f */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 010-01f */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 020-02f */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 030-03f */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 040-04f */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 050-05f */
+	0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,	/* 060-06f */
+	-32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, 0, 0, 0, 0, 0,	/* 070-07f */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 080-08f */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 090-09f */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 0a0-0af */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 0b0-0bf */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 0c0-0cf */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 0d0-0df */
+	-32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,	/* 0e0-0ef */
+	-32, -32, -32, -32, -32, -32, -32, 0, -32, -32, -32, -32, -32, -32, -32, 121,	/* 0f0-0ff */
+	0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 100-10f */
+	0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 110-11f */
+	0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 120-12f */
+	0, 0, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, 0,	/* 130-13f */
+	-1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1,	/* 140-14f */
+	0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 150-15f */
+	0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 160-16f */
+	0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, 0,	/* 170-17f */
+	0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0,	/* 180-18f */
+	0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0,	/* 190-19f */
+	0, -1, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0,	/* 1a0-1af */
+	-1, 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0,	/* 1b0-1bf */
+	0, 0, 0, 0, 0, -1, -2, 0, -1, -2, 0, -1, -2, 0, -1, 0,	/* 1c0-1cf */
+	-1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, -79, 0, -1,	/* 1d0-1df */
+	0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 1e0-1ef */
+	0, 0, -1, -2, 0, -1, 0, 0, 0, -1, 0, -1, 0, -1, 0, -1,	/* 1f0-1ff */
+};
+
+/* Upper case range - Greek */
+static signed char UniCaseRangeU03a0[47] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -38, -37, -37, -37,	/* 3a0-3af */
+	0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,	/* 3b0-3bf */
+	-32, -32, -31, -32, -32, -32, -32, -32, -32, -32, -32, -32, -64,
+	-63, -63,
+};
+
+/* Upper case range - Cyrillic */
+static signed char UniCaseRangeU0430[48] = {
+	-32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,	/* 430-43f */
+	-32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,	/* 440-44f */
+	0, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, 0, -80, -80,	/* 450-45f */
+};
+
+/* Upper case range - Extended cyrillic */
+static signed char UniCaseRangeU0490[61] = {
+	0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 490-49f */
+	0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 4a0-4af */
+	0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 4b0-4bf */
+	0, 0, -1, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1,
+};
+
+/* Upper case range - Extended latin and greek */
+static signed char UniCaseRangeU1e00[509] = {
+	0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 1e00-1e0f */
+	0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 1e10-1e1f */
+	0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 1e20-1e2f */
+	0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 1e30-1e3f */
+	0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 1e40-1e4f */
+	0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 1e50-1e5f */
+	0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 1e60-1e6f */
+	0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 1e70-1e7f */
+	0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 1e80-1e8f */
+	0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, -59, 0, -1, 0, -1,	/* 1e90-1e9f */
+	0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 1ea0-1eaf */
+	0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 1eb0-1ebf */
+	0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 1ec0-1ecf */
+	0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 1ed0-1edf */
+	0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1,	/* 1ee0-1eef */
+	0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0,	/* 1ef0-1eff */
+	8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0,	/* 1f00-1f0f */
+	8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 1f10-1f1f */
+	8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0,	/* 1f20-1f2f */
+	8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0,	/* 1f30-1f3f */
+	8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 1f40-1f4f */
+	0, 8, 0, 8, 0, 8, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0,	/* 1f50-1f5f */
+	8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0,	/* 1f60-1f6f */
+	74, 74, 86, 86, 86, 86, 100, 100, 0, 0, 112, 112, 126, 126, 0, 0,	/* 1f70-1f7f */
+	8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0,	/* 1f80-1f8f */
+	8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0,	/* 1f90-1f9f */
+	8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0,	/* 1fa0-1faf */
+	8, 8, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 1fb0-1fbf */
+	0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 1fc0-1fcf */
+	8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 1fd0-1fdf */
+	8, 8, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 1fe0-1fef */
+	0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+/* Upper case range - Wide latin */
+static signed char UniCaseRangeUff40[27] = {
+	0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,	/* ff40-ff4f */
+	-32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32,
+};
+
+/*
+ * Upper Case Range
+ */
+const struct UniCaseRange CifsUniUpperRange[] = {
+	{0x03a0, 0x03ce, UniCaseRangeU03a0},
+	{0x0430, 0x045f, UniCaseRangeU0430},
+	{0x0490, 0x04cc, UniCaseRangeU0490},
+	{0x1e00, 0x1ffc, UniCaseRangeU1e00},
+	{0xff40, 0xff5a, UniCaseRangeUff40},
+	{0}
+};
+#endif
+
+#ifndef UNIUPR_NOLOWER
+/*
+ * Latin lower case
+ */
+static signed char CifsUniLowerTable[512] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 000-00f */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 010-01f */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 020-02f */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 030-03f */
+	0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,	/* 040-04f */
+	32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 0, 0, 0, 0, 0,	/* 050-05f */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 060-06f */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 070-07f */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 080-08f */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 090-09f */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 0a0-0af */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 0b0-0bf */
+	32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,	/* 0c0-0cf */
+	32, 32, 32, 32, 32, 32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 0,	/* 0d0-0df */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 0e0-0ef */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 0f0-0ff */
+	1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 100-10f */
+	1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 110-11f */
+	1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 120-12f */
+	0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1,	/* 130-13f */
+	0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0,	/* 140-14f */
+	1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 150-15f */
+	1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 160-16f */
+	1, 0, 1, 0, 1, 0, 1, 0, -121, 1, 0, 1, 0, 1, 0, 0,	/* 170-17f */
+	0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 79, 0,	/* 180-18f */
+	0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,	/* 190-19f */
+	1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1,	/* 1a0-1af */
+	0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,	/* 1b0-1bf */
+	0, 0, 0, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 1, 0, 1,	/* 1c0-1cf */
+	0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0,	/* 1d0-1df */
+	1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 1e0-1ef */
+	0, 2, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 1f0-1ff */
+};
+
+/* Lower case range - Greek */
+static signed char UniCaseRangeL0380[44] = {
+	0, 0, 0, 0, 0, 0, 38, 0, 37, 37, 37, 0, 64, 0, 63, 63,	/* 380-38f */
+	0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,	/* 390-39f */
+	32, 32, 0, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+};
+
+/* Lower case range - Cyrillic */
+static signed char UniCaseRangeL0400[48] = {
+	0, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 0, 80, 80,	/* 400-40f */
+	32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,	/* 410-41f */
+	32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,	/* 420-42f */
+};
+
+/* Lower case range - Extended cyrillic */
+static signed char UniCaseRangeL0490[60] = {
+	1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 490-49f */
+	1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 4a0-4af */
+	1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 4b0-4bf */
+	0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1,
+};
+
+/* Lower case range - Extended latin and greek */
+static signed char UniCaseRangeL1e00[504] = {
+	1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 1e00-1e0f */
+	1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 1e10-1e1f */
+	1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 1e20-1e2f */
+	1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 1e30-1e3f */
+	1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 1e40-1e4f */
+	1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 1e50-1e5f */
+	1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 1e60-1e6f */
+	1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 1e70-1e7f */
+	1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 1e80-1e8f */
+	1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,	/* 1e90-1e9f */
+	1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 1ea0-1eaf */
+	1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 1eb0-1ebf */
+	1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 1ec0-1ecf */
+	1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 1ed0-1edf */
+	1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,	/* 1ee0-1eef */
+	1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0,	/* 1ef0-1eff */
+	0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8,	/* 1f00-1f0f */
+	0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, 0, 0,	/* 1f10-1f1f */
+	0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8,	/* 1f20-1f2f */
+	0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8,	/* 1f30-1f3f */
+	0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, 0, 0,	/* 1f40-1f4f */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, -8, 0, -8, 0, -8, 0, -8,	/* 1f50-1f5f */
+	0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8,	/* 1f60-1f6f */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 1f70-1f7f */
+	0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8,	/* 1f80-1f8f */
+	0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8,	/* 1f90-1f9f */
+	0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -8, -8, -8, -8, -8, -8,	/* 1fa0-1faf */
+	0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -74, -74, -9, 0, 0, 0,	/* 1fb0-1fbf */
+	0, 0, 0, 0, 0, 0, 0, 0, -86, -86, -86, -86, -9, 0, 0, 0,	/* 1fc0-1fcf */
+	0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -100, -100, 0, 0, 0, 0,	/* 1fd0-1fdf */
+	0, 0, 0, 0, 0, 0, 0, 0, -8, -8, -112, -112, -7, 0, 0, 0,	/* 1fe0-1fef */
+	0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+/* Lower case range - Wide latin */
+static signed char UniCaseRangeLff20[27] = {
+	0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,	/* ff20-ff2f */
+	32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+};
+
+/*
+ * Lower Case Range
+ */
+const static struct UniCaseRange CifsUniLowerRange[] = {
+	0x0380, 0x03ab, UniCaseRangeL0380,
+	0x0400, 0x042f, UniCaseRangeL0400,
+	0x0490, 0x04cb, UniCaseRangeL0490,
+	0x1e00, 0x1ff7, UniCaseRangeL1e00,
+	0xff20, 0xff3a, UniCaseRangeLff20,
+	0, 0, 0
+};
+#endif
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
new file mode 100644
index 0000000..78829e7
--- /dev/null
+++ b/fs/cifs/cifsencrypt.c
@@ -0,0 +1,209 @@
+/*
+ *   fs/cifs/cifsencrypt.c
+ *
+ *   Copyright (C) International Business Machines  Corp., 2003
+ *   Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/fs.h>
+#include "cifspdu.h"
+#include "cifsglob.h" 
+#include "cifs_debug.h"
+#include "md5.h"
+#include "cifs_unicode.h"
+#include "cifsproto.h"
+
+/* Calculate and return the CIFS signature based on the mac key and the smb pdu */
+/* the 16 byte signature must be allocated by the caller  */
+/* Note we only use the 1st eight bytes */
+/* Note that the smb header signature field on input contains the  
+	sequence number before this function is called */
+
+extern void mdfour(unsigned char *out, unsigned char *in, int n);
+extern void E_md4hash(const unsigned char *passwd, unsigned char *p16);
+	
+static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, const char * key, char * signature)
+{
+	struct	MD5Context context;
+
+	if((cifs_pdu == NULL) || (signature == NULL))
+		return -EINVAL;
+
+	MD5Init(&context);
+	MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16);
+	MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length);
+	MD5Final(signature,&context);
+	return 0;
+}
+
+int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct cifsSesInfo * ses,
+	__u32 * pexpected_response_sequence_number)
+{
+	int rc = 0;
+	char smb_signature[20];
+
+	/* BB remember to initialize sequence number elsewhere and initialize mac_signing key elsewhere BB */
+	/* BB remember to add code to save expected sequence number in midQ entry BB */
+
+	if((cifs_pdu == NULL) || (ses == NULL))
+		return -EINVAL;
+
+	if((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0) 
+		return rc;
+
+	spin_lock(&GlobalMid_Lock);
+	cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(ses->sequence_number);
+	cifs_pdu->Signature.Sequence.Reserved = 0;
+	
+	*pexpected_response_sequence_number = ses->sequence_number++;
+	ses->sequence_number++;
+	spin_unlock(&GlobalMid_Lock);
+
+	rc = cifs_calculate_signature(cifs_pdu, ses->mac_signing_key,smb_signature);
+	if(rc)
+		memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
+	else
+		memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
+
+	return rc;
+}
+
+int cifs_verify_signature(struct smb_hdr * cifs_pdu, const char * mac_key,
+	__u32 expected_sequence_number)
+{
+	unsigned int rc;
+	char server_response_sig[8];
+	char what_we_think_sig_should_be[20];
+
+	if((cifs_pdu == NULL) || (mac_key == NULL))
+		return -EINVAL;
+
+	if (cifs_pdu->Command == SMB_COM_NEGOTIATE)
+		return 0;
+
+	if (cifs_pdu->Command == SMB_COM_LOCKING_ANDX) {
+		struct smb_com_lock_req * pSMB = (struct smb_com_lock_req *)cifs_pdu;
+	    if(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)
+			return 0;
+	}
+
+	/* BB what if signatures are supposed to be on for session but server does not
+		send one? BB */
+	
+	/* Do not need to verify session setups with signature "BSRSPYL "  */
+	if(memcmp(cifs_pdu->Signature.SecuritySignature,"BSRSPYL ",8)==0)
+		cFYI(1,("dummy signature received for smb command 0x%x",cifs_pdu->Command));
+
+	/* save off the origiginal signature so we can modify the smb and check
+		its signature against what the server sent */
+	memcpy(server_response_sig,cifs_pdu->Signature.SecuritySignature,8);
+
+	cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(expected_sequence_number);
+	cifs_pdu->Signature.Sequence.Reserved = 0;
+
+	rc = cifs_calculate_signature(cifs_pdu, mac_key,
+		what_we_think_sig_should_be);
+
+	if(rc)
+		return rc;
+
+	
+/*	cifs_dump_mem("what we think it should be: ",what_we_think_sig_should_be,16); */
+
+	if(memcmp(server_response_sig, what_we_think_sig_should_be, 8))
+		return -EACCES;
+	else
+		return 0;
+
+}
+
+/* We fill in key by putting in 40 byte array which was allocated by caller */
+int cifs_calculate_mac_key(char * key, const char * rn, const char * password)
+{
+	char temp_key[16];
+	if ((key == NULL) || (rn == NULL))
+		return -EINVAL;
+
+	E_md4hash(password, temp_key);
+	mdfour(key,temp_key,16);
+	memcpy(key+16,rn, CIFS_SESSION_KEY_SIZE);
+	return 0;
+}
+
+int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_info)
+{
+	char temp_hash[16];
+	struct HMACMD5Context ctx;
+	char * ucase_buf;
+	wchar_t * unicode_buf;
+	unsigned int i,user_name_len,dom_name_len;
+
+	if(ses == NULL)
+		return -EINVAL;
+
+	E_md4hash(ses->password, temp_hash);
+
+	hmac_md5_init_limK_to_64(temp_hash, 16, &ctx);
+	user_name_len = strlen(ses->userName);
+	if(user_name_len > MAX_USERNAME_SIZE)
+		return -EINVAL;
+	dom_name_len = strlen(ses->domainName);
+	if(dom_name_len > MAX_USERNAME_SIZE)
+		return -EINVAL;
+  
+	ucase_buf = kmalloc((MAX_USERNAME_SIZE+1), GFP_KERNEL);
+	if(ucase_buf == NULL)
+		return -ENOMEM;
+	unicode_buf = kmalloc((MAX_USERNAME_SIZE+1)*4, GFP_KERNEL);
+	if(unicode_buf == NULL) {
+		kfree(ucase_buf);
+		return -ENOMEM;
+	}
+   
+	for(i=0;i<user_name_len;i++)
+		ucase_buf[i] = nls_info->charset2upper[(int)ses->userName[i]];
+	ucase_buf[i] = 0;
+	user_name_len = cifs_strtoUCS(unicode_buf, ucase_buf, MAX_USERNAME_SIZE*2, nls_info);
+	unicode_buf[user_name_len] = 0;
+	user_name_len++;
+
+	for(i=0;i<dom_name_len;i++)
+		ucase_buf[i] = nls_info->charset2upper[(int)ses->domainName[i]];
+	ucase_buf[i] = 0;
+	dom_name_len = cifs_strtoUCS(unicode_buf+user_name_len, ucase_buf, MAX_USERNAME_SIZE*2, nls_info);
+
+	unicode_buf[user_name_len + dom_name_len] = 0;
+	hmac_md5_update((const unsigned char *) unicode_buf,
+		(user_name_len+dom_name_len)*2,&ctx);
+
+	hmac_md5_final(ses->mac_signing_key,&ctx);
+	kfree(ucase_buf);
+	kfree(unicode_buf);
+	return 0;
+}
+void CalcNTLMv2_response(const struct cifsSesInfo * ses,char * v2_session_response)
+{
+	struct HMACMD5Context context;
+	memcpy(v2_session_response + 8, ses->server->cryptKey,8);
+	/* gen_blob(v2_session_response + 16); */
+	hmac_md5_init_limK_to_64(ses->mac_signing_key, 16, &context);
+
+	hmac_md5_update(ses->server->cryptKey,8,&context);
+/*	hmac_md5_update(v2_session_response+16)client thing,8,&context); */ /* BB fix */
+
+	hmac_md5_final(v2_session_response,&context);
+}
diff --git a/fs/cifs/cifsencrypt.h b/fs/cifs/cifsencrypt.h
new file mode 100644
index 0000000..03e359b
--- /dev/null
+++ b/fs/cifs/cifsencrypt.h
@@ -0,0 +1,34 @@
+/*
+ *   fs/cifs/cifsencrypt.h
+ *
+ *   Copyright (c) International Business Machines  Corp., 2005
+ *   Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ *   Externs for misc. small encryption routines
+ *   so we do not have to put them in cifsproto.h
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* md4.c */
+extern void mdfour(unsigned char *out, unsigned char *in, int n);
+/* smbdes.c */
+extern void E_P16(unsigned char *p14, unsigned char *p16);
+extern void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24);
+extern void D_P16(unsigned char *p14, unsigned char *in, unsigned char *out);
+extern void E_old_pw_hash(unsigned char *, unsigned char *, unsigned char *);
+
+
+
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
new file mode 100644
index 0000000..5082fce
--- /dev/null
+++ b/fs/cifs/cifsfs.c
@@ -0,0 +1,913 @@
+/*
+ *   fs/cifs/cifsfs.c
+ *
+ *   Copyright (C) International Business Machines  Corp., 2002,2004
+ *   Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ *   Common Internet FileSystem (CIFS) client
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* Note that BB means BUGBUG (ie something to fix eventually) */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/mount.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/seq_file.h>
+#include <linux/vfs.h>
+#include <linux/mempool.h>
+#include "cifsfs.h"
+#include "cifspdu.h"
+#define DECLARE_GLOBALS_HERE
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+#include "cifs_fs_sb.h"
+#include <linux/mm.h>
+#define CIFS_MAGIC_NUMBER 0xFF534D42	/* the first four bytes of SMB PDUs */
+
+#ifdef CONFIG_CIFS_QUOTA
+static struct quotactl_ops cifs_quotactl_ops;
+#endif
+
+int cifsFYI = 0;
+int cifsERROR = 1;
+int traceSMB = 0;
+unsigned int oplockEnabled = 1;
+unsigned int experimEnabled = 0;
+unsigned int linuxExtEnabled = 1;
+unsigned int lookupCacheEnabled = 1;
+unsigned int multiuser_mount = 0;
+unsigned int extended_security = 0;
+unsigned int ntlmv2_support = 0;
+unsigned int sign_CIFS_PDUs = 1;
+extern struct task_struct * oplockThread; /* remove sparse warning */
+struct task_struct * oplockThread = NULL;
+unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE;
+module_param(CIFSMaxBufSize, int, 0);
+MODULE_PARM_DESC(CIFSMaxBufSize,"Network buffer size (not including header). Default: 16384 Range: 8192 to 130048");
+unsigned int cifs_min_rcv = CIFS_MIN_RCV_POOL;
+module_param(cifs_min_rcv, int, 0);
+MODULE_PARM_DESC(cifs_min_rcv,"Network buffers in pool. Default: 4 Range: 1 to 64");
+unsigned int cifs_min_small = 30;
+module_param(cifs_min_small, int, 0);
+MODULE_PARM_DESC(cifs_min_small,"Small network buffers in pool. Default: 30 Range: 2 to 256");
+unsigned int cifs_max_pending = CIFS_MAX_REQ;
+module_param(cifs_max_pending, int, 0);
+MODULE_PARM_DESC(cifs_max_pending,"Simultaneous requests to server. Default: 50 Range: 2 to 256");
+
+static DECLARE_COMPLETION(cifs_oplock_exited);
+
+extern mempool_t *cifs_sm_req_poolp;
+extern mempool_t *cifs_req_poolp;
+extern mempool_t *cifs_mid_poolp;
+
+extern kmem_cache_t *cifs_oplock_cachep;
+
+static int
+cifs_read_super(struct super_block *sb, void *data,
+		const char *devname, int silent)
+{
+	struct inode *inode;
+	struct cifs_sb_info *cifs_sb;
+	int rc = 0;
+
+	sb->s_flags |= MS_NODIRATIME; /* and probably even noatime */
+	sb->s_fs_info = kmalloc(sizeof(struct cifs_sb_info),GFP_KERNEL);
+	cifs_sb = CIFS_SB(sb);
+	if(cifs_sb == NULL)
+		return -ENOMEM;
+	else
+		memset(cifs_sb,0,sizeof(struct cifs_sb_info));
+	
+
+	rc = cifs_mount(sb, cifs_sb, data, devname);
+
+	if (rc) {
+		if (!silent)
+			cERROR(1,
+			       ("cifs_mount failed w/return code = %d", rc));
+		goto out_mount_failed;
+	}
+
+	sb->s_magic = CIFS_MAGIC_NUMBER;
+	sb->s_op = &cifs_super_ops;
+/*	if(cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512)
+	    sb->s_blocksize = cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */
+#ifdef CONFIG_CIFS_QUOTA
+	sb->s_qcop = &cifs_quotactl_ops;
+#endif
+	sb->s_blocksize = CIFS_MAX_MSGSIZE;
+	sb->s_blocksize_bits = 14;	/* default 2**14 = CIFS_MAX_MSGSIZE */
+	inode = iget(sb, ROOT_I);
+
+	if (!inode) {
+		rc = -ENOMEM;
+		goto out_no_root;
+	}
+
+	sb->s_root = d_alloc_root(inode);
+
+	if (!sb->s_root) {
+		rc = -ENOMEM;
+		goto out_no_root;
+	}
+
+	return 0;
+
+out_no_root:
+	cERROR(1, ("cifs_read_super: get root inode failed"));
+	if (inode)
+		iput(inode);
+
+out_mount_failed:
+	if(cifs_sb) {
+		if(cifs_sb->local_nls)
+			unload_nls(cifs_sb->local_nls);	
+		kfree(cifs_sb);
+	}
+	return rc;
+}
+
+static void
+cifs_put_super(struct super_block *sb)
+{
+	int rc = 0;
+	struct cifs_sb_info *cifs_sb;
+
+	cFYI(1, ("In cifs_put_super"));
+	cifs_sb = CIFS_SB(sb);
+	if(cifs_sb == NULL) {
+		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", rc));
+	}
+	unload_nls(cifs_sb->local_nls);
+	kfree(cifs_sb);
+	return;
+}
+
+static int
+cifs_statfs(struct super_block *sb, struct kstatfs *buf)
+{
+	int xid, rc = -EOPNOTSUPP;
+	struct cifs_sb_info *cifs_sb;
+	struct cifsTconInfo *pTcon;
+
+	xid = GetXid();
+
+	cifs_sb = CIFS_SB(sb);
+	pTcon = cifs_sb->tcon;
+
+	buf->f_type = CIFS_MAGIC_NUMBER;
+
+	/* instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO */
+	buf->f_namelen = PATH_MAX;	/* PATH_MAX may be too long - it would presumably
+					   be length of total path, note that some servers may be 
+					   able to support more than this, but best to be safe
+					   since Win2k and others can not handle very long filenames */
+	buf->f_files = 0;	/* undefined */
+	buf->f_ffree = 0;	/* unlimited */
+
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+/* BB we could add a second check for a QFS Unix capability bit */
+    if (pTcon->ses->capabilities & CAP_UNIX)
+	    rc = CIFSSMBQFSPosixInfo(xid, pTcon, buf, cifs_sb->local_nls);
+
+    /* Only need to call the old QFSInfo if failed
+    on newer one */
+    if(rc)
+#endif /* CIFS_EXPERIMENTAL */
+	rc = CIFSSMBQFSInfo(xid, pTcon, buf, cifs_sb->local_nls);
+
+	/*     
+	   int f_type;
+	   __fsid_t f_fsid;
+	   int f_namelen;  */
+	/* BB get from info put in tcon struct at mount time with call to QFSAttrInfo */
+	FreeXid(xid);
+	return 0;		/* always return success? what if volume is no longer available? */
+}
+
+static int cifs_permission(struct inode * inode, int mask, struct nameidata *nd)
+{
+	struct cifs_sb_info *cifs_sb;
+
+	cifs_sb = CIFS_SB(inode->i_sb);
+
+	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) {
+		return 0;
+	} else /* file mode might have been restricted at mount time 
+		on the client (above and beyond ACL on servers) for  
+		servers which do not support setting and viewing mode bits,
+		so allowing client to check permissions is useful */ 
+		return generic_permission(inode, mask, NULL);
+}
+
+static kmem_cache_t *cifs_inode_cachep;
+static kmem_cache_t *cifs_req_cachep;
+static kmem_cache_t *cifs_mid_cachep;
+kmem_cache_t *cifs_oplock_cachep;
+static kmem_cache_t *cifs_sm_req_cachep;
+mempool_t *cifs_sm_req_poolp;
+mempool_t *cifs_req_poolp;
+mempool_t *cifs_mid_poolp;
+
+static struct inode *
+cifs_alloc_inode(struct super_block *sb)
+{
+	struct cifsInodeInfo *cifs_inode;
+	cifs_inode = kmem_cache_alloc(cifs_inode_cachep, SLAB_KERNEL);
+	if (!cifs_inode)
+		return NULL;
+	cifs_inode->cifsAttrs = 0x20;	/* default */
+	atomic_set(&cifs_inode->inUse, 0);
+	cifs_inode->time = 0;
+	/* Until the file is open and we have gotten oplock
+	info back from the server, can not assume caching of
+	file data or metadata */
+	cifs_inode->clientCanCacheRead = FALSE;
+	cifs_inode->clientCanCacheAll = FALSE;
+	cifs_inode->vfs_inode.i_blksize = CIFS_MAX_MSGSIZE;
+	cifs_inode->vfs_inode.i_blkbits = 14;  /* 2**14 = CIFS_MAX_MSGSIZE */
+
+	INIT_LIST_HEAD(&cifs_inode->openFileList);
+	return &cifs_inode->vfs_inode;
+}
+
+static void
+cifs_destroy_inode(struct inode *inode)
+{
+	kmem_cache_free(cifs_inode_cachep, CIFS_I(inode));
+}
+
+/*
+ * cifs_show_options() is for displaying mount options in /proc/mounts.
+ * Not all settable options are displayed but most of the important
+ * ones are.
+ */
+static int
+cifs_show_options(struct seq_file *s, struct vfsmount *m)
+{
+	struct cifs_sb_info *cifs_sb;
+
+	cifs_sb = CIFS_SB(m->mnt_sb);
+
+	if (cifs_sb) {
+		if (cifs_sb->tcon) {
+			seq_printf(s, ",unc=%s", cifs_sb->tcon->treeName);
+			if (cifs_sb->tcon->ses) {
+				if (cifs_sb->tcon->ses->userName)
+					seq_printf(s, ",username=%s",
+					   cifs_sb->tcon->ses->userName);
+				if(cifs_sb->tcon->ses->domainName)
+					seq_printf(s, ",domain=%s",
+					   cifs_sb->tcon->ses->domainName);
+			}
+		}
+		seq_printf(s, ",rsize=%d",cifs_sb->rsize);
+		seq_printf(s, ",wsize=%d",cifs_sb->wsize);
+	}
+	return 0;
+}
+
+#ifdef CONFIG_CIFS_QUOTA
+int cifs_xquota_set(struct super_block * sb, int quota_type, qid_t qid,
+		struct fs_disk_quota * pdquota)
+{
+	int xid;
+	int rc = 0;
+	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+	struct cifsTconInfo *pTcon;
+	
+	if(cifs_sb)
+		pTcon = cifs_sb->tcon;
+	else
+		return -EIO;
+
+
+	xid = GetXid();
+	if(pTcon) {
+		cFYI(1,("set type: 0x%x id: %d",quota_type,qid));		
+	} else {
+		return -EIO;
+	}
+
+	FreeXid(xid);
+	return rc;
+}
+
+int cifs_xquota_get(struct super_block * sb, int quota_type, qid_t qid,
+                struct fs_disk_quota * pdquota)
+{
+	int xid;
+	int rc = 0;
+	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+	struct cifsTconInfo *pTcon;
+
+	if(cifs_sb)
+		pTcon = cifs_sb->tcon;
+	else
+		return -EIO;
+
+	xid = GetXid();
+	if(pTcon) {
+                cFYI(1,("set type: 0x%x id: %d",quota_type,qid));
+	} else {
+		rc = -EIO;
+	}
+
+	FreeXid(xid);
+	return rc;
+}
+
+int cifs_xstate_set(struct super_block * sb, unsigned int flags, int operation)
+{
+	int xid; 
+	int rc = 0;
+	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+	struct cifsTconInfo *pTcon;
+
+	if(cifs_sb)
+		pTcon = cifs_sb->tcon;
+	else
+		return -EIO;
+
+	xid = GetXid();
+	if(pTcon) {
+                cFYI(1,("flags: 0x%x operation: 0x%x",flags,operation));
+	} else {
+		rc = -EIO;
+	}
+
+	FreeXid(xid);
+	return rc;
+}
+
+int cifs_xstate_get(struct super_block * sb, struct fs_quota_stat *qstats)
+{
+	int xid;
+	int rc = 0;
+	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+	struct cifsTconInfo *pTcon;
+
+	if(cifs_sb) {
+		pTcon = cifs_sb->tcon;
+	} else {
+		return -EIO;
+	}
+	xid = GetXid();
+	if(pTcon) {
+		cFYI(1,("pqstats %p",qstats));		
+	} else {
+		rc = -EIO;
+	}
+
+	FreeXid(xid);
+	return rc;
+}
+
+static struct quotactl_ops cifs_quotactl_ops = {
+	.set_xquota	= cifs_xquota_set,
+	.get_xquota	= cifs_xquota_set,
+	.set_xstate	= cifs_xstate_set,
+	.get_xstate	= cifs_xstate_get,
+};
+#endif
+
+static int cifs_remount(struct super_block *sb, int *flags, char *data)
+{
+	*flags |= MS_NODIRATIME;
+	return 0;
+}
+
+struct super_operations cifs_super_ops = {
+	.read_inode = cifs_read_inode,
+	.put_super = cifs_put_super,
+	.statfs = cifs_statfs,
+	.alloc_inode = cifs_alloc_inode,
+	.destroy_inode = cifs_destroy_inode,
+/*	.drop_inode	    = generic_delete_inode, 
+	.delete_inode	= cifs_delete_inode,  *//* Do not need the above two functions     
+   unless later we add lazy close of inodes or unless the kernel forgets to call
+   us with the same number of releases (closes) as opens */
+	.show_options = cifs_show_options,
+/*    .umount_begin   = cifs_umount_begin, *//* consider adding in the future */
+	.remount_fs = cifs_remount,
+};
+
+static struct super_block *
+cifs_get_sb(struct file_system_type *fs_type,
+	    int flags, const char *dev_name, void *data)
+{
+	int rc;
+	struct super_block *sb = sget(fs_type, NULL, set_anon_super, NULL);
+
+	cFYI(1, ("Devname: %s flags: %d ", dev_name, flags));
+
+	if (IS_ERR(sb))
+		return sb;
+
+	sb->s_flags = flags;
+
+	rc = cifs_read_super(sb, data, dev_name, flags & MS_VERBOSE ? 1 : 0);
+	if (rc) {
+		up_write(&sb->s_umount);
+		deactivate_super(sb);
+		return ERR_PTR(rc);
+	}
+	sb->s_flags |= MS_ACTIVE;
+	return sb;
+}
+
+static ssize_t
+cifs_read_wrapper(struct file * file, char __user *read_data, size_t read_size,
+          loff_t * poffset)
+{
+	if(file->f_dentry == NULL)
+		return -EIO;
+	else if(file->f_dentry->d_inode == NULL)
+		return -EIO;
+
+	cFYI(1,("In read_wrapper size %zd at %lld",read_size,*poffset));
+
+	if(CIFS_I(file->f_dentry->d_inode)->clientCanCacheRead) {
+		return generic_file_read(file,read_data,read_size,poffset);
+	} else {
+		/* BB do we need to lock inode from here until after invalidate? */
+/*		if(file->f_dentry->d_inode->i_mapping) {
+			filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
+			filemap_fdatawait(file->f_dentry->d_inode->i_mapping);
+		}*/
+/*		cifs_revalidate(file->f_dentry);*/ /* BB fixme */
+
+		/* BB we should make timer configurable - perhaps 
+		   by simply calling cifs_revalidate here */
+		/* invalidate_remote_inode(file->f_dentry->d_inode);*/
+		return generic_file_read(file,read_data,read_size,poffset);
+	}
+}
+
+static ssize_t
+cifs_write_wrapper(struct file * file, const char __user *write_data,
+           size_t write_size, loff_t * poffset) 
+{
+	ssize_t written;
+
+	if(file->f_dentry == NULL)
+		return -EIO;
+	else if(file->f_dentry->d_inode == NULL)
+		return -EIO;
+
+	cFYI(1,("In write_wrapper size %zd at %lld",write_size,*poffset));
+
+	written = generic_file_write(file,write_data,write_size,poffset);
+	if(!CIFS_I(file->f_dentry->d_inode)->clientCanCacheAll)  {
+		if(file->f_dentry->d_inode->i_mapping) {
+			filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
+		}
+	}
+	return written;
+}
+
+
+static struct file_system_type cifs_fs_type = {
+	.owner = THIS_MODULE,
+	.name = "cifs",
+	.get_sb = cifs_get_sb,
+	.kill_sb = kill_anon_super,
+	/*  .fs_flags */
+};
+struct inode_operations cifs_dir_inode_ops = {
+	.create = cifs_create,
+	.lookup = cifs_lookup,
+	.getattr = cifs_getattr,
+	.unlink = cifs_unlink,
+	.link = cifs_hardlink,
+	.mkdir = cifs_mkdir,
+	.rmdir = cifs_rmdir,
+	.rename = cifs_rename,
+	.permission = cifs_permission,
+/*	revalidate:cifs_revalidate,   */
+	.setattr = cifs_setattr,
+	.symlink = cifs_symlink,
+	.mknod   = cifs_mknod,
+#ifdef CONFIG_CIFS_XATTR
+	.setxattr = cifs_setxattr,
+	.getxattr = cifs_getxattr,
+	.listxattr = cifs_listxattr,
+	.removexattr = cifs_removexattr,
+#endif
+};
+
+struct inode_operations cifs_file_inode_ops = {
+/*	revalidate:cifs_revalidate, */
+	.setattr = cifs_setattr,
+	.getattr = cifs_getattr, /* do we need this anymore? */
+	.rename = cifs_rename,
+	.permission = cifs_permission,
+#ifdef CONFIG_CIFS_XATTR
+	.setxattr = cifs_setxattr,
+	.getxattr = cifs_getxattr,
+	.listxattr = cifs_listxattr,
+	.removexattr = cifs_removexattr,
+#endif 
+};
+
+struct inode_operations cifs_symlink_inode_ops = {
+	.readlink = generic_readlink, 
+	.follow_link = cifs_follow_link,
+	.put_link = cifs_put_link,
+	.permission = cifs_permission,
+	/* BB add the following two eventually */
+	/* revalidate: cifs_revalidate,
+	   setattr:    cifs_notify_change, *//* BB do we need notify change */
+#ifdef CONFIG_CIFS_XATTR
+	.setxattr = cifs_setxattr,
+	.getxattr = cifs_getxattr,
+	.listxattr = cifs_listxattr,
+	.removexattr = cifs_removexattr,
+#endif 
+};
+
+struct file_operations cifs_file_ops = {
+	.read = cifs_read_wrapper,
+	.write = cifs_write_wrapper, 
+	.open = cifs_open,
+	.release = cifs_close,
+	.lock = cifs_lock,
+	.fsync = cifs_fsync,
+	.flush = cifs_flush,
+	.mmap  = cifs_file_mmap,
+	.sendfile = generic_file_sendfile,
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+	.readv = generic_file_readv,
+	.writev = generic_file_writev,
+	.aio_read = generic_file_aio_read,
+	.aio_write = generic_file_aio_write,
+	.dir_notify = cifs_dir_notify,
+#endif /* CONFIG_CIFS_EXPERIMENTAL */
+};
+
+struct file_operations cifs_file_direct_ops = {
+	/* no mmap, no aio, no readv - 
+	   BB reevaluate whether they can be done with directio, no cache */
+	.read = cifs_user_read,
+	.write = cifs_user_write,
+	.open = cifs_open,
+	.release = cifs_close,
+	.lock = cifs_lock,
+	.fsync = cifs_fsync,
+	.flush = cifs_flush,
+	.sendfile = generic_file_sendfile, /* BB removeme BB */
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+	.dir_notify = cifs_dir_notify,
+#endif /* CONFIG_CIFS_EXPERIMENTAL */
+};
+
+struct file_operations cifs_dir_ops = {
+	.readdir = cifs_readdir,
+	.release = cifs_closedir,
+	.read    = generic_read_dir,
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+	.dir_notify = cifs_dir_notify,
+#endif /* CONFIG_CIFS_EXPERIMENTAL */
+};
+
+static void
+cifs_init_once(void *inode, kmem_cache_t * cachep, unsigned long flags)
+{
+	struct cifsInodeInfo *cifsi = inode;
+
+	if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
+	    SLAB_CTOR_CONSTRUCTOR) {
+		inode_init_once(&cifsi->vfs_inode);
+		INIT_LIST_HEAD(&cifsi->lockList);
+	}
+}
+
+static int
+cifs_init_inodecache(void)
+{
+	cifs_inode_cachep = kmem_cache_create("cifs_inode_cache",
+					      sizeof (struct cifsInodeInfo),
+					      0, SLAB_RECLAIM_ACCOUNT,
+					      cifs_init_once, NULL);
+	if (cifs_inode_cachep == NULL)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static void
+cifs_destroy_inodecache(void)
+{
+	if (kmem_cache_destroy(cifs_inode_cachep))
+		printk(KERN_WARNING "cifs_inode_cache: error freeing\n");
+}
+
+static int
+cifs_init_request_bufs(void)
+{
+	if(CIFSMaxBufSize < 8192) {
+	/* Buffer size can not be smaller than 2 * PATH_MAX since maximum
+	Unicode path name has to fit in any SMB/CIFS path based frames */
+		CIFSMaxBufSize = 8192;
+	} else if (CIFSMaxBufSize > 1024*127) {
+		CIFSMaxBufSize = 1024 * 127;
+	} else {
+		CIFSMaxBufSize &= 0x1FE00; /* Round size to even 512 byte mult*/
+	}
+/*	cERROR(1,("CIFSMaxBufSize %d 0x%x",CIFSMaxBufSize,CIFSMaxBufSize)); */
+	cifs_req_cachep = kmem_cache_create("cifs_request",
+					    CIFSMaxBufSize +
+					    MAX_CIFS_HDR_SIZE, 0,
+					    SLAB_HWCACHE_ALIGN, NULL, NULL);
+	if (cifs_req_cachep == NULL)
+		return -ENOMEM;
+
+	if(cifs_min_rcv < 1)
+		cifs_min_rcv = 1;
+	else if (cifs_min_rcv > 64) {
+		cifs_min_rcv = 64;
+		cERROR(1,("cifs_min_rcv set to maximum (64)"));
+	}
+
+	cifs_req_poolp = mempool_create(cifs_min_rcv,
+					mempool_alloc_slab,
+					mempool_free_slab,
+					cifs_req_cachep);
+
+	if(cifs_req_poolp == NULL) {
+		kmem_cache_destroy(cifs_req_cachep);
+		return -ENOMEM;
+	}
+	/* 256 (MAX_CIFS_HDR_SIZE bytes is enough for most SMB responses and
+	almost all handle based requests (but not write response, nor is it
+	sufficient for path based requests).  A smaller size would have
+	been more efficient (compacting multiple slab items on one 4k page) 
+	for the case in which debug was on, but this larger size allows
+	more SMBs to use small buffer alloc and is still much more
+	efficient to alloc 1 per page off the slab compared to 17K (5page) 
+	alloc of large cifs buffers even when page debugging is on */
+	cifs_sm_req_cachep = kmem_cache_create("cifs_small_rq",
+			MAX_CIFS_HDR_SIZE, 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+	if (cifs_sm_req_cachep == NULL) {
+		mempool_destroy(cifs_req_poolp);
+		kmem_cache_destroy(cifs_req_cachep);
+		return -ENOMEM;              
+	}
+
+	if(cifs_min_small < 2)
+		cifs_min_small = 2;
+	else if (cifs_min_small > 256) {
+		cifs_min_small = 256;
+		cFYI(1,("cifs_min_small set to maximum (256)"));
+	}
+
+	cifs_sm_req_poolp = mempool_create(cifs_min_small,
+				mempool_alloc_slab,
+				mempool_free_slab,
+				cifs_sm_req_cachep);
+
+	if(cifs_sm_req_poolp == NULL) {
+		mempool_destroy(cifs_req_poolp);
+		kmem_cache_destroy(cifs_req_cachep);
+		kmem_cache_destroy(cifs_sm_req_cachep);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void
+cifs_destroy_request_bufs(void)
+{
+	mempool_destroy(cifs_req_poolp);
+	if (kmem_cache_destroy(cifs_req_cachep))
+		printk(KERN_WARNING
+		       "cifs_destroy_request_cache: error not all structures were freed\n");
+	mempool_destroy(cifs_sm_req_poolp);
+	if (kmem_cache_destroy(cifs_sm_req_cachep))
+		printk(KERN_WARNING
+		      "cifs_destroy_request_cache: cifs_small_rq free error\n");
+}
+
+static int
+cifs_init_mids(void)
+{
+	cifs_mid_cachep = kmem_cache_create("cifs_mpx_ids",
+				sizeof (struct mid_q_entry), 0,
+				SLAB_HWCACHE_ALIGN, NULL, NULL);
+	if (cifs_mid_cachep == NULL)
+		return -ENOMEM;
+
+	cifs_mid_poolp = mempool_create(3 /* a reasonable min simultan opers */,
+					mempool_alloc_slab,
+					mempool_free_slab,
+					cifs_mid_cachep);
+	if(cifs_mid_poolp == NULL) {
+		kmem_cache_destroy(cifs_mid_cachep);
+		return -ENOMEM;
+	}
+
+	cifs_oplock_cachep = kmem_cache_create("cifs_oplock_structs",
+				sizeof (struct oplock_q_entry), 0,
+				SLAB_HWCACHE_ALIGN, NULL, NULL);
+	if (cifs_oplock_cachep == NULL) {
+		kmem_cache_destroy(cifs_mid_cachep);
+		mempool_destroy(cifs_mid_poolp);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void
+cifs_destroy_mids(void)
+{
+	mempool_destroy(cifs_mid_poolp);
+	if (kmem_cache_destroy(cifs_mid_cachep))
+		printk(KERN_WARNING
+		       "cifs_destroy_mids: error not all structures were freed\n");
+
+	if (kmem_cache_destroy(cifs_oplock_cachep))
+		printk(KERN_WARNING
+		       "error not all oplock structures were freed\n");
+}
+
+static int cifs_oplock_thread(void * dummyarg)
+{
+	struct oplock_q_entry * oplock_item;
+	struct cifsTconInfo *pTcon;
+	struct inode * inode;
+	__u16  netfid;
+	int rc;
+
+	daemonize("cifsoplockd");
+	allow_signal(SIGTERM);
+
+	oplockThread = current;
+	do {
+		set_current_state(TASK_INTERRUPTIBLE);
+		
+		schedule_timeout(1*HZ);  
+		spin_lock(&GlobalMid_Lock);
+		if(list_empty(&GlobalOplock_Q)) {
+			spin_unlock(&GlobalMid_Lock);
+			set_current_state(TASK_INTERRUPTIBLE);
+			schedule_timeout(39*HZ);
+		} else {
+			oplock_item = list_entry(GlobalOplock_Q.next, 
+				struct oplock_q_entry, qhead);
+			if(oplock_item) {
+				cFYI(1,("found oplock item to write out")); 
+				pTcon = oplock_item->tcon;
+				inode = oplock_item->pinode;
+				netfid = oplock_item->netfid;
+				spin_unlock(&GlobalMid_Lock);
+				DeleteOplockQEntry(oplock_item);
+				/* can not grab inode sem here since it would
+				deadlock when oplock received on delete 
+				since vfs_unlink holds the i_sem across
+				the call */
+				/* down(&inode->i_sem);*/
+				if (S_ISREG(inode->i_mode)) {
+					rc = filemap_fdatawrite(inode->i_mapping);
+					if(CIFS_I(inode)->clientCanCacheRead == 0) {
+						filemap_fdatawait(inode->i_mapping);
+						invalidate_remote_inode(inode);
+					}
+				} else
+					rc = 0;
+				/* up(&inode->i_sem);*/
+				if (rc)
+					CIFS_I(inode)->write_behind_rc = rc;
+				cFYI(1,("Oplock flush inode %p rc %d",inode,rc));
+
+				/* releasing a stale oplock after recent reconnection 
+				of smb session using a now incorrect file 
+				handle is not a data integrity issue but do  
+				not bother sending an oplock release if session 
+				to server still is disconnected since oplock 
+				already released by the server in that case */
+				if(pTcon->tidStatus != CifsNeedReconnect) {
+				    rc = CIFSSMBLock(0, pTcon, netfid,
+					    0 /* len */ , 0 /* offset */, 0, 
+					    0, LOCKING_ANDX_OPLOCK_RELEASE,
+					    0 /* wait flag */);
+					cFYI(1,("Oplock release rc = %d ",rc));
+				}
+			} else
+				spin_unlock(&GlobalMid_Lock);
+		}
+	} while(!signal_pending(current));
+	complete_and_exit (&cifs_oplock_exited, 0);
+}
+
+static int __init
+init_cifs(void)
+{
+	int rc = 0;
+#ifdef CONFIG_PROC_FS
+	cifs_proc_init();
+#endif
+	INIT_LIST_HEAD(&GlobalServerList);	/* BB not implemented yet */
+	INIT_LIST_HEAD(&GlobalSMBSessionList);
+	INIT_LIST_HEAD(&GlobalTreeConnectionList);
+	INIT_LIST_HEAD(&GlobalOplock_Q);
+/*
+ *  Initialize Global counters
+ */
+	atomic_set(&sesInfoAllocCount, 0);
+	atomic_set(&tconInfoAllocCount, 0);
+	atomic_set(&tcpSesAllocCount,0);
+	atomic_set(&tcpSesReconnectCount, 0);
+	atomic_set(&tconInfoReconnectCount, 0);
+
+	atomic_set(&bufAllocCount, 0);
+	atomic_set(&midCount, 0);
+	GlobalCurrentXid = 0;
+	GlobalTotalActiveXid = 0;
+	GlobalMaxActiveXid = 0;
+	rwlock_init(&GlobalSMBSeslock);
+	spin_lock_init(&GlobalMid_Lock);
+
+	if(cifs_max_pending < 2) {
+		cifs_max_pending = 2;
+		cFYI(1,("cifs_max_pending set to min of 2"));
+	} else if(cifs_max_pending > 256) {
+		cifs_max_pending = 256;
+		cFYI(1,("cifs_max_pending set to max of 256"));
+	}
+
+	rc = cifs_init_inodecache();
+	if (!rc) {
+		rc = cifs_init_mids();
+		if (!rc) {
+			rc = cifs_init_request_bufs();
+			if (!rc) {
+				rc = register_filesystem(&cifs_fs_type);
+				if (!rc) {                
+					rc = (int)kernel_thread(cifs_oplock_thread, NULL, 
+						CLONE_FS | CLONE_FILES | CLONE_VM);
+					if(rc > 0)
+						return 0;
+					else 
+						cERROR(1,("error %d create oplock thread",rc));
+				}
+				cifs_destroy_request_bufs();
+			}
+			cifs_destroy_mids();
+		}
+		cifs_destroy_inodecache();
+	}
+#ifdef CONFIG_PROC_FS
+	cifs_proc_clean();
+#endif
+	return rc;
+}
+
+static void __exit
+exit_cifs(void)
+{
+	cFYI(0, ("In unregister ie exit_cifs"));
+#ifdef CONFIG_PROC_FS
+	cifs_proc_clean();
+#endif
+	unregister_filesystem(&cifs_fs_type);
+	cifs_destroy_inodecache();
+	cifs_destroy_mids();
+	cifs_destroy_request_bufs();
+	if(oplockThread) {
+		send_sig(SIGTERM, oplockThread, 1);
+		wait_for_completion(&cifs_oplock_exited);
+	}
+}
+
+MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>");
+MODULE_LICENSE("GPL");		/* combination of LGPL + GPL source behaves as GPL */
+MODULE_DESCRIPTION
+    ("VFS to access servers complying with the SNIA CIFS Specification e.g. Samba and Windows");
+MODULE_VERSION(CIFS_VERSION);
+module_init(init_cifs)
+module_exit(exit_cifs)
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
new file mode 100644
index 0000000..451f18a
--- /dev/null
+++ b/fs/cifs/cifsfs.h
@@ -0,0 +1,98 @@
+/*
+ *   fs/cifs/cifsfs.h
+ *
+ *   Copyright (c) International Business Machines  Corp., 2002
+ *   Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ */
+
+#ifndef _CIFSFS_H
+#define _CIFSFS_H
+
+#define ROOT_I 2
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+extern struct address_space_operations cifs_addr_ops;
+
+/* Functions related to super block operations */
+extern struct super_operations cifs_super_ops;
+extern void cifs_read_inode(struct inode *);
+extern void cifs_delete_inode(struct inode *);
+/* extern void cifs_write_inode(struct inode *); *//* BB not needed yet */
+
+/* Functions related to inodes */
+extern struct inode_operations cifs_dir_inode_ops;
+extern int cifs_create(struct inode *, struct dentry *, int, 
+		       struct nameidata *);
+extern struct dentry * cifs_lookup(struct inode *, struct dentry *,
+				  struct nameidata *);
+extern int cifs_unlink(struct inode *, struct dentry *);
+extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *);
+extern int cifs_mknod(struct inode *, struct dentry *, int, dev_t);
+extern int cifs_mkdir(struct inode *, struct dentry *, int);
+extern int cifs_rmdir(struct inode *, struct dentry *);
+extern int cifs_rename(struct inode *, struct dentry *, struct inode *,
+		       struct dentry *);
+extern int cifs_revalidate(struct dentry *);
+extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
+extern int cifs_setattr(struct dentry *, struct iattr *);
+
+extern struct inode_operations cifs_file_inode_ops;
+extern struct inode_operations cifs_symlink_inode_ops;
+
+/* Functions related to files and directories */
+extern struct file_operations cifs_file_ops;
+extern struct file_operations cifs_file_direct_ops; /* if directio mount */
+extern int cifs_open(struct inode *inode, struct file *file);
+extern int cifs_close(struct inode *inode, struct file *file);
+extern int cifs_closedir(struct inode *inode, struct file *file);
+extern ssize_t cifs_user_read(struct file *file, char __user *read_data,
+			 size_t read_size, loff_t * poffset);
+extern ssize_t cifs_user_write(struct file *file, const char __user *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);
+extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir);
+extern int cifs_dir_notify(struct file *, unsigned long arg);
+
+/* Functions related to dir entries */
+extern struct dentry_operations cifs_dentry_ops;
+
+/* Functions related to symlinks */
+extern int cifs_follow_link(struct dentry *direntry, struct nameidata *nd);
+extern void cifs_put_link(struct dentry *direntry, struct nameidata *nd);
+extern int cifs_readlink(struct dentry *direntry, char __user *buffer, 
+			 int buflen);
+extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
+			const char *symname);
+extern int	cifs_removexattr(struct dentry *, const char *);
+extern int 	cifs_setxattr(struct dentry *, const char *, const void *,
+			 size_t, int);
+extern ssize_t	cifs_getxattr(struct dentry *, const char *, void *, size_t);
+extern ssize_t	cifs_listxattr(struct dentry *, char *, size_t);
+#define CIFS_VERSION   "1.31"
+#endif				/* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
new file mode 100644
index 0000000..69aff1a7
--- /dev/null
+++ b/fs/cifs/cifsglob.h
@@ -0,0 +1,439 @@
+/*
+ *   fs/cifs/cifsglob.h
+ *
+ *   Copyright (C) International Business Machines  Corp., 2002,2003
+ *   Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU Lesser General Public License for more details.
+ * 
+ */
+#include <linux/in.h>
+#include <linux/in6.h>
+#include "cifs_fs_sb.h"
+/*
+ * The sizes of various internal tables and strings
+ */
+#define MAX_UID_INFO 16
+#define MAX_SES_INFO 2
+#define MAX_TCON_INFO 4
+
+#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	/* 32 is to allow for 15 char names + null
+				   termination then *2 for unicode versions */
+#define MAX_PASSWORD_SIZE 16
+
+#define CIFS_MIN_RCV_POOL 4
+
+/*
+ * MAX_REQ is the maximum number of requests that WE will send
+ * on one socket concurently. It also matches the most common
+ * value of max multiplex returned by servers.  We may 
+ * eventually want to use the negotiated value (in case
+ * future servers can handle more) when we are more confident that
+ * we will not have problems oveloading the socket with pending
+ * write data.
+ */
+#define CIFS_MAX_REQ 50 
+
+#define SERVER_NAME_LENGTH 15
+#define SERVER_NAME_LEN_WITH_NULL     (SERVER_NAME_LENGTH + 1)
+
+/* used to define string lengths for reversing unicode strings */
+/*         (256+1)*2 = 514                                     */
+/*           (max path length + 1 for null) * 2 for unicode    */
+#define MAX_NAME 514
+
+#include "cifspdu.h"
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef XATTR_DOS_ATTRIB
+#define XATTR_DOS_ATTRIB "user.DOSATTRIB"
+#endif
+
+/*
+ * This information is kept on every Server we know about.
+ *
+ * Some things to note:
+ *
+ */
+#define SERVER_NAME_LEN_WITH_NULL	(SERVER_NAME_LENGTH + 1)
+
+/*
+ * CIFS vfs client Status information (based on what we know.)
+ */
+
+ /* associated with each tcp and smb session */
+enum statusEnum {
+	CifsNew = 0,
+	CifsGood,
+	CifsExiting,
+	CifsNeedReconnect
+};
+
+enum securityEnum {
+	NTLM = 0,		/* Legacy NTLM012 auth with NTLM hash */
+	NTLMv2,			/* Legacy NTLM auth with NTLMv2 hash */
+	RawNTLMSSP,		/* NTLMSSP without SPNEGO */
+	NTLMSSP,		/* NTLMSSP via SPNEGO */
+	Kerberos		/* Kerberos via SPNEGO */
+};
+
+enum protocolEnum {
+	IPV4 = 0,
+	IPV6,
+	SCTP
+	/* Netbios frames protocol not supported at this time */
+};
+
+/*
+ *****************************************************************
+ * Except the CIFS PDUs themselves all the
+ * globally interesting structs should go here
+ *****************************************************************
+ */
+
+struct TCP_Server_Info {
+	char server_Name[SERVER_NAME_LEN_WITH_NULL];	/* 15 chars + X'20'in 16th */
+	char unicode_server_Name[SERVER_NAME_LEN_WITH_NULL * 2];	/* Unicode version of server_Name */
+	struct socket *ssocket;
+	union {
+		struct sockaddr_in sockAddr;
+		struct sockaddr_in6 sockAddr6;
+	} addr;
+	wait_queue_head_t response_q; 
+	wait_queue_head_t request_q; /* if more than maxmpx to srvr must block*/
+	struct list_head pending_mid_q;
+	void *Server_NlsInfo;	/* BB - placeholder for future NLS info  */
+	unsigned short server_codepage;	/* codepage for the server    */
+	unsigned long ip_address;	/* IP addr for the server if known     */
+	enum protocolEnum protocolType;	
+	char versionMajor;
+	char versionMinor;
+	unsigned svlocal:1;	/* local server or remote */
+	atomic_t socketUseCount; /* number of open cifs sessions on socket */
+	atomic_t inFlight;  /* number of requests on the wire to server */
+	enum statusEnum tcpStatus; /* what we think the status is */
+	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];
+	char workstation_RFC1001_name[16]; /* 16th byte is always zero */
+};
+
+/*
+ * The following is our shortcut to user information.  We surface the uid,
+ * and name. We always get the password on the fly in case it
+ * has changed. We also hang a list of sessions owned by this user off here. 
+ */
+struct cifsUidInfo {
+	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 may need ptr or callback for PAM or WinBind info */
+};
+
+/*
+ * Session structure.  One of these for each uid session with a particular host
+ */
+struct cifsSesInfo {
+	struct list_head cifsSessionList;
+	struct semaphore sesSem;
+	struct cifsUidInfo *uidInfo;	/* pointer to user info */
+	struct TCP_Server_Info *server;	/* pointer to server info */
+	atomic_t inUse; /* # of mounts (tree connections) on this ses */
+	enum statusEnum status;
+	__u32 sequence_number;  /* needed for CIFS PDU signature */
+	__u16 ipc_tid;		/* special tid for connection to IPC share */
+	__u16 flags;
+	char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16];	
+	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;		/* remote smb uid  */
+	uid_t linux_uid;        /* local Linux uid */
+	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];
+	char domainName[MAX_USERNAME_SIZE + 1];
+	char * password;
+};
+/* session flags */
+#define CIFS_SES_NT4 1
+
+/*
+ * there is one of these for each connection to a resource on a particular
+ * session 
+ */
+struct cifsTconInfo {
+	struct list_head cifsConnectionList;
+	struct list_head openFileList;
+	struct semaphore tconSem;
+	struct cifsSesInfo *ses;	/* pointer to session associated with */
+	char treeName[MAX_TREE_SIZE + 1]; /* UNC name of resource (in ASCII not UTF) */
+	char *nativeFileSystem;
+	__u16 tid;		/* The 2 byte tree id */
+	__u16 Flags;		/* optional support bits */
+	enum statusEnum tidStatus;
+	atomic_t useCount;	/* how many mounts (explicit or implicit) to this share */
+#ifdef CONFIG_CIFS_STATS
+	atomic_t num_smbs_sent;
+	atomic_t num_writes;
+	atomic_t num_reads;
+	atomic_t num_oplock_brks;
+	atomic_t num_opens;
+	atomic_t num_deletes;
+	atomic_t num_mkdirs;
+	atomic_t num_rmdirs;
+	atomic_t num_renames;
+	atomic_t num_t2renames;
+	__u64    bytes_read;
+	__u64    bytes_written;
+	spinlock_t stat_lock;
+#endif
+	FILE_SYSTEM_DEVICE_INFO fsDevInfo;
+	FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo;	/* ok if file system name truncated */
+	FILE_SYSTEM_UNIX_INFO fsUnixInfo;
+	unsigned retry:1;
+	/* BB add field for back pointer to sb struct? */
+};
+
+/*
+ * This info hangs off the cifsFileInfo structure.  This is used to track
+ * byte stream locks on the file
+ */
+struct cifsLockInfo {
+	struct cifsLockInfo *next;
+	int start;
+	int length;
+	int type;
+};
+
+/*
+ * One of these for each open instance of a file
+ */
+struct cifs_search_info {
+	loff_t index_of_last_entry;
+	__u16 entries_in_buffer;
+	__u16 info_level;
+	__u32 resume_key;
+	char * ntwrk_buf_start;
+	char * srch_entries_start;
+	char * presume_name;
+	unsigned int resume_name_len;
+	unsigned endOfSearch:1;
+	unsigned emptyDir:1;
+	unsigned unicode:1;
+};
+
+struct cifsFileInfo {
+	struct list_head tlist;	/* pointer to next fid owned by tcon */
+	struct list_head flist;	/* next fid (file instance) for this inode */
+	unsigned int uid;	/* allows finding which FileInfo structure */
+	__u32 pid;		/* process id who opened file */
+	__u16 netfid;		/* file id from remote */
+	/* BB add lock scope info here if needed */ ;
+	/* lock scope id (0 if none) */
+	struct file * pfile; /* needed for writepage */
+	struct inode * pInode; /* needed for oplock break */
+	unsigned closePend:1;	/* file is marked to close */
+	unsigned invalidHandle:1;  /* file closed via session abend */
+	struct semaphore fh_sem; /* prevents reopen race after dead ses*/
+	char * search_resume_name; /* BB removeme BB */
+	unsigned int resume_name_length; /* BB removeme - field renamed and moved BB */
+	struct cifs_search_info srch_inf;
+};
+
+/*
+ * One of these for each file inode
+ */
+
+struct cifsInodeInfo {
+	struct list_head lockList;
+	/* BB add in lists for dirty pages - i.e. write caching info for oplock */
+	struct list_head openFileList;
+	int write_behind_rc;
+	__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 */
+	unsigned clientCanCacheRead:1; /* read oplock */
+	unsigned clientCanCacheAll:1;  /* read and writebehind oplock */
+	unsigned oplockPending:1;
+	struct inode vfs_inode;
+};
+
+static inline struct cifsInodeInfo *
+CIFS_I(struct inode *inode)
+{
+	return container_of(inode, struct cifsInodeInfo, vfs_inode);
+}
+
+static inline struct cifs_sb_info *
+CIFS_SB(struct super_block *sb)
+{
+	return sb->s_fs_info;
+}
+
+
+/* one of these for every pending CIFS request to the server */
+struct mid_q_entry {
+	struct list_head qhead;	/* mids waiting on reply from this server */
+	__u16 mid;		/* multiplex id */
+	__u16 pid;		/* process id */
+	__u32 sequence_number;  /* for CIFS signing */
+	__u16 command;		/* smb command code */
+	struct timeval when_sent;	/* time when smb sent */
+	struct cifsSesInfo *ses;	/* smb was sent to this server */
+	struct task_struct *tsk;	/* task waiting for response */
+	struct smb_hdr *resp_buf;	/* response buffer */
+	int midState;	/* wish this were enum but can not pass to wait_event */
+};
+
+struct oplock_q_entry {
+	struct list_head qhead;
+	struct inode * pinode;
+	struct cifsTconInfo * tcon; 
+	__u16 netfid;
+};
+
+#define   MID_FREE 0
+#define   MID_REQUEST_ALLOCATED 1
+#define   MID_REQUEST_SUBMITTED 2
+#define   MID_RESPONSE_RECEIVED 4
+#define   MID_RETRY_NEEDED      8 /* session closed while this request out */
+#define   MID_NO_RESP_NEEDED 0x10
+#define   MID_SMALL_BUFFER   0x20 /* 112 byte response buffer instead of 4K */
+
+/*
+ *****************************************************************
+ * All constants go here
+ *****************************************************************
+ */
+
+#define UID_HASH (16)
+
+/*
+ * Note that ONE module should define _DECLARE_GLOBALS_HERE to cause the
+ * following to be declared.
+ */
+
+/****************************************************************************
+ *  Locking notes.  All updates to global variables and lists should be
+ *                  protected by spinlocks or semaphores.
+ *
+ *  Spinlocks
+ *  ---------
+ *  GlobalMid_Lock protects:
+ *	list operations on pending_mid_q and oplockQ
+ *      updates to XID counters, multiplex id  and SMB sequence numbers
+ *  GlobalSMBSesLock protects:
+ *	list operations on tcp and SMB session lists and tCon lists
+ *  f_owner.lock protects certain per file struct operations
+ *  mapping->page_lock protects certain per page operations
+ *
+ *  Semaphores
+ *  ----------
+ *  sesSem     operations on smb session
+ *  tconSem    operations on tree connection
+ *  fh_sem      file handle reconnection operations 
+ *
+ ****************************************************************************/
+
+#ifdef DECLARE_GLOBALS_HERE
+#define GLOBAL_EXTERN
+#else
+#define GLOBAL_EXTERN extern
+#endif
+
+/*
+ * The list of servers that did not respond with NT LM 0.12.
+ * This list helps improve performance and eliminate the messages indicating
+ * that we had a communications error talking to the server in this list. 
+ */
+GLOBAL_EXTERN struct servers_not_supported *NotSuppList;	/*@z4a */
+
+/*
+ * The following is a hash table of all the users we know about.
+ */
+GLOBAL_EXTERN struct smbUidInfo *GlobalUidList[UID_HASH];
+
+GLOBAL_EXTERN struct list_head GlobalServerList; /* BB not implemented yet */
+GLOBAL_EXTERN struct list_head GlobalSMBSessionList;
+GLOBAL_EXTERN struct list_head GlobalTreeConnectionList;
+GLOBAL_EXTERN rwlock_t GlobalSMBSeslock;  /* protects list inserts on 3 above */
+
+GLOBAL_EXTERN struct list_head GlobalOplock_Q;
+
+/*
+ * Global transaction id (XID) information
+ */
+GLOBAL_EXTERN unsigned int GlobalCurrentXid;	/* protected by GlobalMid_Sem */
+GLOBAL_EXTERN unsigned int GlobalTotalActiveXid;	/* prot by GlobalMid_Sem */
+GLOBAL_EXTERN unsigned int GlobalMaxActiveXid;	/* prot by GlobalMid_Sem */
+GLOBAL_EXTERN spinlock_t GlobalMid_Lock;  /* protects above and list operations */
+					/* on midQ entries */
+GLOBAL_EXTERN char Local_System_Name[15];
+
+/*
+ *  Global counters, updated atomically
+ */
+GLOBAL_EXTERN atomic_t sesInfoAllocCount;
+GLOBAL_EXTERN atomic_t tconInfoAllocCount;
+GLOBAL_EXTERN atomic_t tcpSesAllocCount;
+GLOBAL_EXTERN atomic_t tcpSesReconnectCount;
+GLOBAL_EXTERN atomic_t tconInfoReconnectCount;
+
+/* Various Debug counters to remove someday (BB) */
+GLOBAL_EXTERN atomic_t bufAllocCount;
+GLOBAL_EXTERN atomic_t smBufAllocCount;      
+GLOBAL_EXTERN atomic_t midCount;
+
+/* Misc globals */
+GLOBAL_EXTERN unsigned int multiuser_mount;	/* if enabled allows new sessions
+				to be established on existing mount if we
+				have the uid/password or Kerberos credential 
+				or equivalent for current user */
+GLOBAL_EXTERN unsigned int oplockEnabled;
+GLOBAL_EXTERN unsigned int experimEnabled;
+GLOBAL_EXTERN unsigned int lookupCacheEnabled;
+GLOBAL_EXTERN unsigned int extended_security;	/* if on, session setup sent 
+				with more secure ntlmssp2 challenge/resp */
+GLOBAL_EXTERN unsigned int ntlmv2_support;  /* better optional password hash */
+GLOBAL_EXTERN unsigned int sign_CIFS_PDUs;  /* enable smb packet signing */
+GLOBAL_EXTERN unsigned int linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/
+GLOBAL_EXTERN unsigned int CIFSMaxBufSize;  /* max size not including hdr */
+GLOBAL_EXTERN unsigned int cifs_min_rcv;    /* min size of big ntwrk buf pool */
+GLOBAL_EXTERN unsigned int cifs_min_small;  /* min size of small buf pool */
+GLOBAL_EXTERN unsigned int cifs_max_pending; /* MAX requests at once to server*/
+
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
new file mode 100644
index 0000000..bcd4a61
--- /dev/null
+++ b/fs/cifs/cifspdu.h
@@ -0,0 +1,1987 @@
+/*
+ *   fs/cifs/cifspdu.h
+ *
+ *   Copyright (c) International Business Machines  Corp., 2002
+ *   Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ */
+
+#ifndef _CIFSPDU_H
+#define _CIFSPDU_H
+
+#include <net/sock.h>
+
+#define CIFS_PROT   0
+#define BAD_PROT    CIFS_PROT+1
+
+/* SMB command codes */
+/* Some commands have minimal (wct=0,bcc=0), or uninteresting, responses
+ (ie which include no useful data other than the SMB error code itself).
+ Knowing this helps avoid response buffer allocations and copy in some cases */
+#define SMB_COM_CREATE_DIRECTORY      0x00 /* trivial response */
+#define SMB_COM_DELETE_DIRECTORY      0x01 /* trivial response */
+#define SMB_COM_CLOSE                 0x04 /* triv req/rsp, timestamp ignored */
+#define SMB_COM_DELETE                0x06 /* trivial response */
+#define SMB_COM_RENAME                0x07 /* trivial response */
+#define SMB_COM_SETATTR               0x09 /* trivial response */
+#define SMB_COM_LOCKING_ANDX          0x24 /* trivial response */
+#define SMB_COM_COPY                  0x29 /* trivial rsp, fail filename ignrd*/
+#define SMB_COM_READ_ANDX             0x2E
+#define SMB_COM_WRITE_ANDX            0x2F
+#define SMB_COM_TRANSACTION2          0x32
+#define SMB_COM_TRANSACTION2_SECONDARY 0x33
+#define SMB_COM_FIND_CLOSE2           0x34 /* trivial response */
+#define SMB_COM_TREE_DISCONNECT       0x71 /* trivial response */
+#define SMB_COM_NEGOTIATE             0x72
+#define SMB_COM_SESSION_SETUP_ANDX    0x73
+#define SMB_COM_LOGOFF_ANDX           0x74 /* trivial response */
+#define SMB_COM_TREE_CONNECT_ANDX     0x75
+#define SMB_COM_NT_TRANSACT           0xA0
+#define SMB_COM_NT_TRANSACT_SECONDARY 0xA1
+#define SMB_COM_NT_CREATE_ANDX        0xA2
+#define SMB_COM_NT_RENAME             0xA5 /* trivial response */
+
+/* Transact2 subcommand codes */
+#define TRANS2_OPEN                   0x00
+#define TRANS2_FIND_FIRST             0x01
+#define TRANS2_FIND_NEXT              0x02
+#define TRANS2_QUERY_FS_INFORMATION   0x03
+#define TRANS2_QUERY_PATH_INFORMATION 0x05
+#define TRANS2_SET_PATH_INFORMATION   0x06
+#define TRANS2_QUERY_FILE_INFORMATION 0x07
+#define TRANS2_SET_FILE_INFORMATION   0x08
+#define TRANS2_GET_DFS_REFERRAL       0x10
+#define TRANS2_REPORT_DFS_INCOSISTENCY 0x11
+
+/* NT Transact subcommand codes */
+#define NT_TRANSACT_CREATE            0x01
+#define NT_TRANSACT_IOCTL             0x02
+#define NT_TRANSACT_SET_SECURITY_DESC 0x03
+#define NT_TRANSACT_NOTIFY_CHANGE     0x04
+#define NT_TRANSACT_RENAME            0x05
+#define NT_TRANSACT_QUERY_SECURITY_DESC 0x06
+#define NT_TRANSACT_GET_USER_QUOTA    0x07
+#define NT_TRANSACT_SET_USER_QUOTA    0x08
+
+#define MAX_CIFS_HDR_SIZE 256	/* chained NTCreateXReadX will probably be biggest */
+
+/* internal cifs vfs structures */
+/*****************************************************************
+ * All constants go here
+ *****************************************************************
+ */
+
+/*
+ * Starting value for maximum SMB size negotiation
+ */
+#define CIFS_MAX_MSGSIZE (4*4096)
+
+/*
+ * Size of encrypted user password in bytes
+ */
+#define CIFS_ENCPWD_SIZE (16)
+
+/*
+ * Size of the crypto key returned on the negotiate SMB in bytes
+ */
+#define CIFS_CRYPTO_KEY_SIZE (8)
+
+/*
+ * Size of the session key (crypto key encrypted with the password
+ */
+#define CIFS_SESSION_KEY_SIZE (24)
+
+/*
+ * Maximum user name length
+ */
+#define CIFS_UNLEN (20)
+
+/*
+ * Flags on SMB open
+ */
+#define SMBOPEN_WRITE_THROUGH 0x4000
+#define SMBOPEN_DENY_ALL      0x0010
+#define SMBOPEN_DENY_WRITE    0x0020
+#define SMBOPEN_DENY_READ     0x0030
+#define SMBOPEN_DENY_NONE     0x0040
+#define SMBOPEN_READ          0x0000
+#define SMBOPEN_WRITE         0x0001
+#define SMBOPEN_READWRITE     0x0002
+#define SMBOPEN_EXECUTE       0x0003
+
+#define SMBOPEN_OCREATE       0x0010
+#define SMBOPEN_OTRUNC        0x0002
+#define SMBOPEN_OAPPEND       0x0001
+
+/*
+ * SMB flag definitions 
+ */
+#define SMBFLG_EXTD_LOCK 0x01	/* server supports lock-read write-unlock primitives */
+#define SMBFLG_RCV_POSTED 0x02	/* obsolete */
+#define SMBFLG_RSVD 0x04
+#define SMBFLG_CASELESS 0x08	/* all pathnames treated as caseless (off implies case sensitive file handling requested) */
+#define SMBFLG_CANONICAL_PATH_FORMAT 0x10	/* obsolete */
+#define SMBFLG_OLD_OPLOCK 0x20	/* obsolete */
+#define SMBFLG_OLD_OPLOCK_NOTIFY 0x40	/* obsolete */
+#define SMBFLG_RESPONSE 0x80	/* this PDU is a response from server */
+
+/*
+ * SMB flag2 definitions 
+ */
+#define SMBFLG2_KNOWS_LONG_NAMES cpu_to_le16(1)	/* can send long (non-8.3) path names in response */
+#define SMBFLG2_KNOWS_EAS cpu_to_le16(2)
+#define SMBFLG2_SECURITY_SIGNATURE cpu_to_le16(4)
+#define SMBFLG2_IS_LONG_NAME cpu_to_le16(0x40)
+#define SMBFLG2_EXT_SEC cpu_to_le16(0x800)
+#define SMBFLG2_DFS cpu_to_le16(0x1000)
+#define SMBFLG2_PAGING_IO cpu_to_le16(0x2000)
+#define SMBFLG2_ERR_STATUS cpu_to_le16(0x4000)
+#define SMBFLG2_UNICODE cpu_to_le16(0x8000)
+
+/*
+ * These are the file access permission bits defined in CIFS for the
+ * NTCreateAndX as well as the level 0x107
+ * TRANS2_QUERY_PATH_INFORMATION API.  The level 0x107, SMB_QUERY_FILE_ALL_INFO
+ * responds with the AccessFlags.
+ * The AccessFlags specifies the access permissions a caller has to the
+ * file and can have any suitable combination of the following values:
+ */
+
+#define FILE_READ_DATA        0x00000001	/* Data can be read from the file   */
+#define FILE_WRITE_DATA       0x00000002	/* Data can be written to the file  */
+#define FILE_APPEND_DATA      0x00000004	/* Data can be appended to the file */
+#define FILE_READ_EA          0x00000008	/* Extended attributes associated   */
+					 /* with the file can be read        */
+#define FILE_WRITE_EA         0x00000010	/* Extended attributes associated   */
+					 /* with the file can be written     */
+#define FILE_EXECUTE          0x00000020	/*Data can be read into memory from */
+					 /* the file using system paging I/O */
+#define FILE_DELETE_CHILD     0x00000040
+#define FILE_READ_ATTRIBUTES  0x00000080	/* Attributes associated with the   */
+					 /* file can be read                 */
+#define FILE_WRITE_ATTRIBUTES 0x00000100	/* Attributes associated with the   */
+					 /* file can be written              */
+#define DELETE                0x00010000	/* The file can be deleted          */
+#define READ_CONTROL          0x00020000	/* The access control list and      */
+					 /* ownership associated with the    */
+					 /* file can be read                 */
+#define WRITE_DAC             0x00040000	/* The access control list and      */
+					 /* ownership associated with the    */
+					 /* file can be written.             */
+#define WRITE_OWNER           0x00080000	/* Ownership information associated */
+					 /* with the file can be written     */
+#define SYNCHRONIZE           0x00100000	/* The file handle can waited on to */
+					 /* synchronize with the completion  */
+					 /* of an input/output request       */
+#define GENERIC_ALL           0x10000000
+#define GENERIC_EXECUTE       0x20000000
+#define GENERIC_WRITE         0x40000000
+#define GENERIC_READ          0x80000000
+					 /* In summary - Relevant file       */
+					 /* access flags from CIFS are       */
+					 /* file_read_data, file_write_data  */
+					 /* file_execute, file_read_attributes */
+					 /* write_dac, and delete.           */
+
+/*
+ * Invalid readdir handle
+ */
+#define CIFS_NO_HANDLE        0xFFFF
+
+/* IPC$ in ASCII */
+#define CIFS_IPC_RESOURCE "\x49\x50\x43\x24"
+
+/* IPC$ in Unicode */
+#define CIFS_IPC_UNICODE_RESOURCE "\x00\x49\x00\x50\x00\x43\x00\x24\x00\x00"
+
+/* Unicode Null terminate 2 bytes of 0 */
+#define UNICODE_NULL "\x00\x00"
+#define ASCII_NULL 0x00
+
+/*
+ * Server type values (returned on EnumServer API
+ */
+#define CIFS_SV_TYPE_DC     0x00000008
+#define CIFS_SV_TYPE_BACKDC 0x00000010
+
+/*
+ * Alias type flags (From EnumAlias API call
+ */
+#define CIFS_ALIAS_TYPE_FILE 0x0001
+#define CIFS_SHARE_TYPE_FILE 0x0000
+
+/*
+ * File Attribute flags
+ */
+#define ATTR_READONLY  0x0001
+#define ATTR_HIDDEN    0x0002
+#define ATTR_SYSTEM    0x0004
+#define ATTR_VOLUME    0x0008
+#define ATTR_DIRECTORY 0x0010
+#define ATTR_ARCHIVE   0x0020
+#define ATTR_DEVICE    0x0040
+#define ATTR_NORMAL    0x0080
+#define ATTR_TEMPORARY 0x0100
+#define ATTR_SPARSE    0x0200
+#define ATTR_REPARSE   0x0400
+#define ATTR_COMPRESSED 0x0800
+#define ATTR_OFFLINE    0x1000	/* ie file not immediately available - offline storage */
+#define ATTR_NOT_CONTENT_INDEXED 0x2000
+#define ATTR_ENCRYPTED  0x4000
+#define ATTR_POSIX_SEMANTICS 0x01000000
+#define ATTR_BACKUP_SEMANTICS 0x02000000
+#define ATTR_DELETE_ON_CLOSE 0x04000000
+#define ATTR_SEQUENTIAL_SCAN 0x08000000
+#define ATTR_RANDOM_ACCESS   0x10000000
+#define ATTR_NO_BUFFERING    0x20000000
+#define ATTR_WRITE_THROUGH   0x80000000
+
+/* ShareAccess flags */
+#define FILE_NO_SHARE     0x00000000
+#define FILE_SHARE_READ   0x00000001
+#define FILE_SHARE_WRITE  0x00000002
+#define FILE_SHARE_DELETE 0x00000004
+#define FILE_SHARE_ALL    0x00000007
+
+/* CreateDisposition flags */
+#define FILE_SUPERSEDE    0x00000000
+#define FILE_OPEN         0x00000001
+#define FILE_CREATE       0x00000002
+#define FILE_OPEN_IF      0x00000003
+#define FILE_OVERWRITE    0x00000004
+#define FILE_OVERWRITE_IF 0x00000005
+
+/* CreateOptions */
+#define CREATE_NOT_FILE		0x00000001	/* if set must not be file */
+#define CREATE_WRITE_THROUGH	0x00000002
+#define CREATE_NOT_DIR		0x00000040	/* if set must not be directory */
+#define CREATE_RANDOM_ACCESS	0x00000800
+#define CREATE_DELETE_ON_CLOSE	0x00001000
+#define OPEN_REPARSE_POINT	0x00200000
+
+/* ImpersonationLevel flags */
+#define SECURITY_ANONYMOUS      0
+#define SECURITY_IDENTIFICATION 1
+#define SECURITY_IMPERSONATION  2
+#define SECURITY_DELEGATION     3
+
+/* SecurityFlags */
+#define SECURITY_CONTEXT_TRACKING 0x01
+#define SECURITY_EFFECTIVE_ONLY   0x02
+
+/*
+ * Default PID value, used in all SMBs where the PID is not important
+ */
+#define CIFS_DFT_PID  0x1234
+
+/*
+ * We use the same routine for Copy and Move SMBs.  This flag is used to
+ * distinguish
+ */
+#define CIFS_COPY_OP 1
+#define CIFS_RENAME_OP 2
+
+#define GETU16(var)  (*((__u16 *)var))	/* BB check for endian issues */
+#define GETU32(var)  (*((__u32 *)var))	/* BB check for endian issues */
+
+#pragma pack(1)
+
+struct smb_hdr {
+	__u32 smb_buf_length;	/* big endian on wire *//* BB length is only two or three bytes - with one or two byte type preceding it but that is always zero - we could mask the type byte off just in case BB */
+	__u8 Protocol[4];
+	__u8 Command;
+	union {
+		struct {
+			__u8 ErrorClass;
+			__u8 Reserved;
+			__le16 Error;
+		} DosError;
+		__le32 CifsError;
+	} Status;
+	__u8 Flags;
+	__le16 Flags2;		/* note: le */
+	__le16 PidHigh;
+	union {
+		struct {
+			__le32 SequenceNumber;  /* le */
+			__u32 Reserved; /* zero */
+		} Sequence;
+		__u8 SecuritySignature[8];	/* le */
+	} Signature;
+	__u8 pad[2];
+	__u16 Tid;
+	__le16 Pid;
+	__u16 Uid;
+	__u16 Mid;
+	__u8 WordCount;
+};
+/* given a pointer to an smb_hdr retrieve the value of byte count */
+#define BCC(smb_var) ( *(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) )
+
+/* given a pointer to an smb_hdr retrieve the pointer to the byte area */
+#define pByteArea(smb_var) ((unsigned char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) + 2 )
+
+/*
+ * Computer Name Length
+ */
+#define CNLEN 15
+
+/*
+ * Share Name Length					  @S8A
+ * Note:  This length is limited by the SMB used to get   @S8A
+ *        the Share info.   NetShareEnum only returns 13  @S8A
+ *        chars, including the null termination.          @S8A 
+ */
+#define SNLEN 12		/*@S8A */
+
+/*
+ * Comment Length
+ */
+#define MAXCOMMENTLEN 40
+
+/*
+ * The OS/2 maximum path name
+ */
+#define MAX_PATHCONF 256
+
+/*
+ *  SMB frame definitions  (following must be packed structs)
+ *  See the SNIA CIFS Specification for details.
+ *
+ *  The Naming convention is the lower case version of the
+ *  smb command code name for the struct and this is typedef to the
+ *  uppercase version of the same name with the prefix SMB_ removed 
+ *  for brevity.  Although typedefs are not commonly used for 
+ *  structure definitions in the Linux kernel, their use in the
+ *  CIFS standards document, which this code is based on, may
+ *  make this one of the cases where typedefs for structures make
+ *  sense to improve readability for readers of the standards doc.
+ *  Typedefs can always be removed later if they are too distracting
+ *  and they are only used for the CIFSs PDUs themselves, not
+ *  internal cifs vfs structures
+ *  
+ */
+
+typedef struct negotiate_req {
+	struct smb_hdr hdr;	/* wct = 0 */
+	__le16 ByteCount;
+	unsigned char DialectsArray[1];
+} NEGOTIATE_REQ;
+
+typedef struct negotiate_rsp {
+	struct smb_hdr hdr;	/* wct = 17 */
+	__le16 DialectIndex;
+	__u8 SecurityMode;
+	__le16 MaxMpxCount;
+	__le16 MaxNumberVcs;
+	__le32 MaxBufferSize;
+	__le32 MaxRawSize;
+	__le32 SessionKey;
+	__le32 Capabilities;	/* see below */
+	__le32 SystemTimeLow;
+	__le32 SystemTimeHigh;
+	__le16 ServerTimeZone;
+	__u8 EncryptionKeyLength;
+	__u16 ByteCount;
+	union {
+		unsigned char EncryptionKey[1];	/* if cap extended security is off */
+		/* followed by Domain name - if extended security is off */
+		/* followed by 16 bytes of server GUID */
+		/* followed by security blob if cap_extended_security negotiated */
+		struct {
+			unsigned char GUID[16];
+			unsigned char SecurityBlob[1];
+		} extended_response;
+	} u;
+} NEGOTIATE_RSP;
+
+/* SecurityMode bits */
+#define SECMODE_USER          0x01	/* off indicates share level security */
+#define SECMODE_PW_ENCRYPT    0x02
+#define SECMODE_SIGN_ENABLED  0x04	/* SMB security signatures enabled */
+#define SECMODE_SIGN_REQUIRED 0x08	/* SMB security signatures required */
+
+/* Negotiate response Capabilities */
+#define CAP_RAW_MODE           0x00000001
+#define CAP_MPX_MODE           0x00000002
+#define CAP_UNICODE            0x00000004
+#define CAP_LARGE_FILES        0x00000008
+#define CAP_NT_SMBS            0x00000010	/* implies CAP_NT_FIND */
+#define CAP_RPC_REMOTE_APIS    0x00000020
+#define CAP_STATUS32           0x00000040
+#define CAP_LEVEL_II_OPLOCKS   0x00000080
+#define CAP_LOCK_AND_READ      0x00000100
+#define CAP_NT_FIND            0x00000200
+#define CAP_DFS                0x00001000
+#define CAP_INFOLEVEL_PASSTHRU 0x00002000
+#define CAP_LARGE_READ_X       0x00004000
+#define CAP_LARGE_WRITE_X      0x00008000
+#define CAP_UNIX               0x00800000
+#define CAP_RESERVED           0x02000000
+#define CAP_BULK_TRANSFER      0x20000000
+#define CAP_COMPRESSED_DATA    0x40000000
+#define CAP_EXTENDED_SECURITY  0x80000000
+
+typedef union smb_com_session_setup_andx {
+	struct {		/* request format */
+		struct smb_hdr hdr;	/* wct = 12 */
+		__u8 AndXCommand;
+		__u8 AndXReserved;
+		__le16 AndXOffset;
+		__le16 MaxBufferSize;
+		__le16 MaxMpxCount;
+		__le16 VcNumber;
+		__u32 SessionKey;
+		__le16 SecurityBlobLength;
+		__u32 Reserved;
+		__le32 Capabilities;	/* see below */
+		__le16 ByteCount;
+		unsigned char SecurityBlob[1];	/* followed by */
+		/* STRING NativeOS */
+		/* STRING NativeLanMan */
+	} req;			/* NTLM request format (with extended security */
+
+	struct {		/* request format */
+		struct smb_hdr hdr;	/* wct = 13 */
+		__u8 AndXCommand;
+		__u8 AndXReserved;
+		__le16 AndXOffset;
+		__le16 MaxBufferSize;
+		__le16 MaxMpxCount;
+		__le16 VcNumber;
+		__u32 SessionKey;
+		__le16 CaseInsensitivePasswordLength;	/* ASCII password length */
+		__le16 CaseSensitivePasswordLength;	/* Unicode password length */
+		__u32 Reserved;	/* see below */
+		__le32 Capabilities;
+		__le16 ByteCount;
+		unsigned char CaseInsensitivePassword[1];	/* followed by: */
+		/* unsigned char * CaseSensitivePassword; */
+		/* STRING AccountName */
+		/* STRING PrimaryDomain */
+		/* STRING NativeOS */
+		/* STRING NativeLanMan */
+	} req_no_secext;	/* NTLM request format (without extended security */
+
+	struct {		/* default (NTLM) response format */
+		struct smb_hdr hdr;	/* wct = 4 */
+		__u8 AndXCommand;
+		__u8 AndXReserved;
+		__le16 AndXOffset;
+		__le16 Action;	/* see below */
+		__le16 SecurityBlobLength;
+		__u16 ByteCount;
+		unsigned char SecurityBlob[1];	/* followed by */
+/*      unsigned char  * NativeOS;      */
+/*	unsigned char  * NativeLanMan;  */
+/*      unsigned char  * PrimaryDomain; */
+	} resp;			/* NTLM response format (with or without extended security */
+
+	struct {		/* request format */
+		struct smb_hdr hdr;	/* wct = 10 */
+		__u8 AndXCommand;
+		__u8 AndXReserved;
+		__le16 AndXOffset;
+		__le16 MaxBufferSize;
+		__le16 MaxMpxCount;
+		__le16 VcNumber;
+		__u32 SessionKey;
+		__le16 PassswordLength;
+		__u32 Reserved;
+		__le16 ByteCount;
+		unsigned char AccountPassword[1];	/* followed by */
+		/* STRING AccountName */
+		/* STRING PrimaryDomain */
+		/* STRING NativeOS */
+		/* STRING NativeLanMan */
+	} old_req;		/* pre-NTLM (LANMAN2.1) request format */
+
+	struct {		/* default (NTLM) response format */
+		struct smb_hdr hdr;	/* wct = 3 */
+		__u8 AndXCommand;
+		__u8 AndXReserved;
+		__le16 AndXOffset;
+		__le16 Action;	/* see below */
+		__u16 ByteCount;
+		unsigned char NativeOS[1];	/* followed by */
+/*	unsigned char * NativeLanMan; */
+/*      unsigned char * PrimaryDomain; */
+	} old_resp;		/* pre-NTLM (LANMAN2.1) response format */
+} SESSION_SETUP_ANDX;
+
+#define CIFS_NETWORK_OPSYS "CIFS VFS Client for Linux"
+
+/* Capabilities bits (for NTLM SessSetup request) */
+#define CAP_UNICODE            0x00000004
+#define CAP_LARGE_FILES        0x00000008
+#define CAP_NT_SMBS            0x00000010
+#define CAP_STATUS32           0x00000040
+#define CAP_LEVEL_II_OPLOCKS   0x00000080
+#define CAP_NT_FIND            0x00000200	/* reserved should be zero (presumably because NT_SMBs implies the same thing) */
+#define CAP_BULK_TRANSFER      0x20000000
+#define CAP_EXTENDED_SECURITY  0x80000000
+
+/* Action bits */
+#define GUEST_LOGIN 1
+
+typedef struct smb_com_tconx_req {
+	struct smb_hdr hdr;	/* wct = 4 */
+	__u8 AndXCommand;
+	__u8 AndXReserved;
+	__le16 AndXOffset;
+	__le16 Flags;		/* see below */
+	__le16 PasswordLength;
+	__le16 ByteCount;
+	unsigned char Password[1];	/* followed by */
+/* STRING Path    *//* \\server\share name */
+	/* STRING Service */
+} TCONX_REQ;
+
+typedef struct smb_com_tconx_rsp {
+	struct smb_hdr hdr;	/* wct = 3 *//* note that Win2000 has sent wct=7 in some cases on responses. Four unspecified words followed OptionalSupport */
+	__u8 AndXCommand;
+	__u8 AndXReserved;
+	__le16 AndXOffset;
+	__le16 OptionalSupport;	/* see below */
+	__u16 ByteCount;
+	unsigned char Service[1];	/* always ASCII, not Unicode */
+	/* STRING NativeFileSystem */
+} TCONX_RSP;
+
+/* tree connect Flags */
+#define DISCONNECT_TID          0x0001
+#define TCON_EXTENDED_SECINFO   0x0008
+/* OptionalSupport bits */
+#define SMB_SUPPORT_SEARCH_BITS 0x0001	/* must have bits (exclusive searches suppt. */
+#define SMB_SHARE_IS_IN_DFS     0x0002
+
+typedef struct smb_com_logoff_andx_req {
+	struct smb_hdr hdr;	/* wct = 2 */
+	__u8 AndXCommand;
+	__u8 AndXReserved;
+	__u16 AndXOffset;
+	__u16 ByteCount;
+} LOGOFF_ANDX_REQ;
+
+typedef struct smb_com_logoff_andx_rsp {
+	struct smb_hdr hdr;	/* wct = 2 */
+	__u8 AndXCommand;
+	__u8 AndXReserved;
+	__u16 AndXOffset;
+	__u16 ByteCount;
+} LOGOFF_ANDX_RSP;
+
+typedef union smb_com_tree_disconnect {	/* as an altetnative can use flag on tree_connect PDU to effect disconnect *//* probably the simplest SMB PDU */
+	struct {
+		struct smb_hdr hdr;	/* wct = 0 */
+		__u16 ByteCount;	/* bcc = 0 */
+	} req;
+	struct {
+		struct smb_hdr hdr;	/* wct = 0 */
+		__u16 ByteCount;	/* bcc = 0 */
+	} resp;
+} TREE_DISCONNECT;
+
+typedef struct smb_com_close_req {
+	struct smb_hdr hdr;	/* wct = 3 */
+	__u16 FileID;
+	__u32 LastWriteTime;	/* should be zero */
+	__u16 ByteCount;	/* 0 */
+} CLOSE_REQ;
+
+typedef struct smb_com_close_rsp {
+	struct smb_hdr hdr;	/* wct = 0 */
+	__u16 ByteCount;	/* bct = 0 */
+} CLOSE_RSP;
+
+typedef struct smb_com_findclose_req {
+	struct smb_hdr hdr; /* wct = 1 */
+	__u16 FileID;
+	__u16 ByteCount;    /* 0 */
+} FINDCLOSE_REQ;
+
+/* OpenFlags */
+#define REQ_OPLOCK         0x00000002
+#define REQ_BATCHOPLOCK    0x00000004
+#define REQ_OPENDIRONLY    0x00000008
+
+typedef struct smb_com_open_req {	/* also handles create */
+	struct smb_hdr hdr;	/* wct = 24 */
+	__u8 AndXCommand;
+	__u8 AndXReserved;
+	__le16 AndXOffset;
+	__u8 Reserved;		/* Must Be Zero */
+	__le16 NameLength;
+	__le32 OpenFlags;
+	__le32 RootDirectoryFid;
+	__le32 DesiredAccess;
+	__le64 AllocationSize;
+	__le32 FileAttributes;
+	__le32 ShareAccess;
+	__le32 CreateDisposition;
+	__le32 CreateOptions;
+	__le32 ImpersonationLevel;
+	__u8 SecurityFlags;
+	__le16 ByteCount;
+	char fileName[1];
+} OPEN_REQ;
+
+/* open response: oplock levels */
+#define OPLOCK_NONE  	 0
+#define OPLOCK_EXCLUSIVE 1
+#define OPLOCK_BATCH	 2
+#define OPLOCK_READ	 3  /* level 2 oplock */
+
+/* open response for CreateAction shifted left */
+#define CIFS_CREATE_ACTION 0x20000 /* file created */
+
+typedef struct smb_com_open_rsp {
+	struct smb_hdr hdr;	/* wct = 34 BB */
+	__u8 AndXCommand;
+	__u8 AndXReserved;
+	__le16 AndXOffset;
+	__u8 OplockLevel;
+	__u16 Fid;
+	__le32 CreateAction;
+	__le64 CreationTime;
+	__le64 LastAccessTime;
+	__le64 LastWriteTime;
+	__le64 ChangeTime;
+	__le32 FileAttributes;
+	__le64 AllocationSize;
+	__le64 EndOfFile;
+	__le16 FileType;
+	__le16 DeviceState;
+	__u8 DirectoryFlag;
+	__u16 ByteCount;	/* bct = 0 */
+} OPEN_RSP;
+
+typedef struct smb_com_write_req {
+	struct smb_hdr hdr;	/* wct = 14 */
+	__u8 AndXCommand;
+	__u8 AndXReserved;
+	__le16 AndXOffset;
+	__u16 Fid;
+	__le32 OffsetLow;
+	__u32 Reserved;
+	__le16 WriteMode;
+	__le16 Remaining;
+	__le16 DataLengthHigh;
+	__le16 DataLengthLow;
+	__le16 DataOffset;
+	__le32 OffsetHigh;
+	__le16 ByteCount;
+	__u8 Pad;		/* BB check for whether padded to DWORD boundary and optimum performance here */
+	char Data[0];
+} WRITE_REQ;
+
+typedef struct smb_com_write_rsp {
+	struct smb_hdr hdr;	/* wct = 6 */
+	__u8 AndXCommand;
+	__u8 AndXReserved;
+	__le16 AndXOffset;
+	__le16 Count;
+	__le16 Remaining;
+	__le16 CountHigh;
+	__u16  Reserved;
+	__u16 ByteCount;
+} WRITE_RSP;
+
+typedef struct smb_com_read_req {
+	struct smb_hdr hdr;	/* wct = 12 */
+	__u8 AndXCommand;
+	__u8 AndXReserved;
+	__le16 AndXOffset;
+	__u16 Fid;
+	__le32 OffsetLow;
+	__le16 MaxCount;
+	__le16 MinCount;		/* obsolete */
+	__le32 MaxCountHigh;
+	__le16 Remaining;
+	__le32 OffsetHigh;
+	__le16 ByteCount;
+} READ_REQ;
+
+typedef struct smb_com_read_rsp {
+	struct smb_hdr hdr;	/* wct = 12 */
+	__u8 AndXCommand;
+	__u8 AndXReserved;
+	__le16 AndXOffset;
+	__le16 Remaining;
+	__le16 DataCompactionMode;
+	__le16 Reserved;
+	__le16 DataLength;
+	__le16 DataOffset;
+	__le16 DataLengthHigh;
+	__u64 Reserved2;
+	__u16 ByteCount;
+	__u8 Pad;		/* BB check for whether padded to DWORD boundary and optimum performance here */
+	char Data[1];
+} READ_RSP;
+
+typedef struct locking_andx_range {
+	__le16 Pid;
+	__le16 Pad;
+	__le32 OffsetHigh;
+	__le32 OffsetLow;
+	__le32 LengthHigh;
+	__le32 LengthLow;
+} LOCKING_ANDX_RANGE;
+
+#define LOCKING_ANDX_SHARED_LOCK     0x01
+#define LOCKING_ANDX_OPLOCK_RELEASE  0x02
+#define LOCKING_ANDX_CHANGE_LOCKTYPE 0x04
+#define LOCKING_ANDX_CANCEL_LOCK     0x08
+#define LOCKING_ANDX_LARGE_FILES     0x10	/* always on for us */
+
+typedef struct smb_com_lock_req {
+	struct smb_hdr hdr;	/* wct = 8 */
+	__u8 AndXCommand;
+	__u8 AndXReserved;
+	__le16 AndXOffset;
+	__u16 Fid;
+	__u8 LockType;
+	__u8 OplockLevel;
+	__le32 Timeout;
+	__le16 NumberOfUnlocks;
+	__le16 NumberOfLocks;
+	__le16 ByteCount;
+	LOCKING_ANDX_RANGE Locks[1];
+} LOCK_REQ;
+
+typedef struct smb_com_lock_rsp {
+	struct smb_hdr hdr;	/* wct = 2 */
+	__u8 AndXCommand;
+	__u8 AndXReserved;
+	__le16 AndXOffset;
+	__u16 ByteCount;
+} LOCK_RSP;
+
+typedef struct smb_com_rename_req {
+	struct smb_hdr hdr;	/* wct = 1 */
+	__le16 SearchAttributes;	/* target file attributes */
+	__le16 ByteCount;
+	__u8 BufferFormat;	/* 4 = ASCII or Unicode */
+	unsigned char OldFileName[1];
+	/* followed by __u8 BufferFormat2 */
+	/* followed by NewFileName */
+} RENAME_REQ;
+
+	/* copy request flags */
+#define COPY_MUST_BE_FILE      0x0001
+#define COPY_MUST_BE_DIR       0x0002
+#define COPY_TARGET_MODE_ASCII 0x0004 /* if not set, binary */
+#define COPY_SOURCE_MODE_ASCII 0x0008 /* if not set, binary */
+#define COPY_VERIFY_WRITES     0x0010
+#define COPY_TREE              0x0020 
+
+typedef struct smb_com_copy_req {
+	struct smb_hdr hdr;	/* wct = 3 */
+	__u16 Tid2;
+	__le16 OpenFunction;
+	__le16 Flags;
+	__le16 ByteCount;
+	__u8 BufferFormat;	/* 4 = ASCII or Unicode */ 
+	unsigned char OldFileName[1];
+	/* followed by __u8 BufferFormat2 */
+	/* followed by NewFileName string */
+} COPY_REQ;
+
+typedef struct smb_com_copy_rsp {
+	struct smb_hdr hdr;     /* wct = 1 */
+	__le16 CopyCount;    /* number of files copied */
+	__u16 ByteCount;    /* may be zero */
+	__u8 BufferFormat;  /* 0x04 - only present if errored file follows */
+	unsigned char ErrorFileName[1]; /* only present if error in copy */
+} COPY_RSP;
+
+#define CREATE_HARD_LINK		0x103
+#define MOVEFILE_COPY_ALLOWED		0x0002
+#define MOVEFILE_REPLACE_EXISTING	0x0001
+
+typedef struct smb_com_nt_rename_req {	/* A5 - also used for create hardlink */
+	struct smb_hdr hdr;	/* wct = 4 */
+	__le16 SearchAttributes;	/* target file attributes */
+	__le16 Flags;		/* spec says Information Level */
+	__le32 ClusterCount;
+	__le16 ByteCount;
+	__u8 BufferFormat;	/* 4 = ASCII or Unicode */
+	unsigned char OldFileName[1];
+	/* followed by __u8 BufferFormat2 */
+	/* followed by NewFileName */
+} NT_RENAME_REQ;
+
+typedef struct smb_com_rename_rsp {
+	struct smb_hdr hdr;	/* wct = 0 */
+	__u16 ByteCount;	/* bct = 0 */
+} RENAME_RSP;
+
+typedef struct smb_com_delete_file_req {
+	struct smb_hdr hdr;	/* wct = 1 */
+	__le16 SearchAttributes;
+	__le16 ByteCount;
+	__u8 BufferFormat;	/* 4 = ASCII */
+	unsigned char fileName[1];
+} DELETE_FILE_REQ;
+
+typedef struct smb_com_delete_file_rsp {
+	struct smb_hdr hdr;	/* wct = 0 */
+	__u16 ByteCount;	/* bct = 0 */
+} DELETE_FILE_RSP;
+
+typedef struct smb_com_delete_directory_req {
+	struct smb_hdr hdr;	/* wct = 0 */
+	__le16 ByteCount;
+	__u8 BufferFormat;	/* 4 = ASCII */
+	unsigned char DirName[1];
+} DELETE_DIRECTORY_REQ;
+
+typedef struct smb_com_delete_directory_rsp {
+	struct smb_hdr hdr;	/* wct = 0 */
+	__u16 ByteCount;	/* bct = 0 */
+} DELETE_DIRECTORY_RSP;
+
+typedef struct smb_com_create_directory_req {
+	struct smb_hdr hdr;	/* wct = 0 */
+	__le16 ByteCount;
+	__u8 BufferFormat;	/* 4 = ASCII */
+	unsigned char DirName[1];
+} CREATE_DIRECTORY_REQ;
+
+typedef struct smb_com_create_directory_rsp {
+	struct smb_hdr hdr;	/* wct = 0 */
+	__u16 ByteCount;	/* bct = 0 */
+} CREATE_DIRECTORY_RSP;
+
+typedef struct smb_com_setattr_req {
+	struct smb_hdr hdr; /* wct = 8 */
+	__le16 attr;
+	__le16 time_low;
+	__le16 time_high;
+	__le16 reserved[5]; /* must be zero */
+	__u16  ByteCount;
+	__u8   BufferFormat; /* 4 = ASCII */
+	unsigned char fileName[1];
+} SETATTR_REQ;
+
+typedef struct smb_com_setattr_rsp {
+	struct smb_hdr hdr;     /* wct = 0 */
+	__u16 ByteCount;        /* bct = 0 */
+} SETATTR_RSP;
+
+/* empty wct response to setattr */
+
+/***************************************************/
+/* NT Transact structure defintions follow         */
+/* Currently only ioctl and notify are implemented */
+/***************************************************/
+typedef struct smb_com_transaction_ioctl_req {
+	struct smb_hdr hdr;	/* wct = 23 */
+	__u8 MaxSetupCount;
+	__u16 Reserved;
+	__le32 TotalParameterCount;
+	__le32 TotalDataCount;
+	__le32 MaxParameterCount;
+	__le32 MaxDataCount;
+	__le32 ParameterCount;
+	__le32 ParameterOffset;
+	__le32 DataCount;
+	__le32 DataOffset;
+	__u8 SetupCount; /* four setup words follow subcommand */
+	/* SNIA spec incorrectly included spurious pad here */
+	__le16 SubCommand;/* 2 = IOCTL/FSCTL */
+	__le32 FunctionCode;
+	__u16 Fid;
+	__u8 IsFsctl;    /* 1 = File System Control, 0 = device control (IOCTL)*/
+	__u8 IsRootFlag; /* 1 = apply command to root of share (must be DFS share)*/
+	__le16 ByteCount;
+	__u8 Pad[3];
+	__u8 Data[1];
+} TRANSACT_IOCTL_REQ;
+
+typedef struct smb_com_transaction_ioctl_rsp {
+	struct smb_hdr hdr;	/* wct = 19 */
+	__u8 Reserved[3];
+	__le32 TotalParameterCount;
+	__le32 TotalDataCount;
+	__le32 ParameterCount;
+	__le32 ParameterOffset;
+	__le32 ParameterDisplacement;
+	__le32 DataCount;
+	__le32 DataOffset;
+	__le32 DataDisplacement;
+	__u8 SetupCount;	/* 1 */
+	__le16 ReturnedDataLen;
+	__u16 ByteCount;
+	__u8 Pad[3];
+} TRANSACT_IOCTL_RSP;
+
+typedef struct smb_com_transaction_change_notify_req {
+	struct smb_hdr hdr;     /* wct = 23 */
+	__u8 MaxSetupCount;
+	__u16 Reserved;
+	__le32 TotalParameterCount;
+	__le32 TotalDataCount;
+	__le32 MaxParameterCount;
+	__le32 MaxDataCount;
+	__le32 ParameterCount;
+	__le32 ParameterOffset;
+	__le32 DataCount;
+	__le32 DataOffset;
+	__u8 SetupCount; /* four setup words follow subcommand */
+	/* SNIA spec incorrectly included spurious pad here */
+	__le16 SubCommand;/* 4 = Change Notify */
+	__le32 CompletionFilter;  /* operation to monitor */
+	__u16 Fid;
+	__u8 WatchTree;  /* 1 = Monitor subdirectories */
+	__u8 Reserved2;
+	__le16 ByteCount;
+/* __u8 Pad[3];*/
+/*	__u8 Data[1];*/
+} TRANSACT_CHANGE_NOTIFY_REQ;
+
+typedef struct smb_com_transaction_change_notify_rsp {
+	struct smb_hdr hdr;	/* wct = 18 */
+	__u8 Reserved[3];
+	__le32 TotalParameterCount;
+	__le32 TotalDataCount;
+	__le32 ParameterCount;
+	__le32 ParameterOffset;
+	__le32 ParameterDisplacement;
+	__le32 DataCount;
+	__le32 DataOffset;
+	__le32 DataDisplacement;
+	__u8 SetupCount;   /* 0 */
+	__u16 ByteCount;
+	/* __u8 Pad[3]; */
+} TRANSACT_CHANGE_NOTIFY_RSP;
+/* Completion Filter flags for Notify */
+#define FILE_NOTIFY_CHANGE_FILE_NAME    0x00000001
+#define FILE_NOTIFY_CHANGE_DIR_NAME     0x00000002
+#define FILE_NOTIFY_CHANGE_NAME         0x00000003
+#define FILE_NOTIFY_CHANGE_ATTRIBUTES   0x00000004
+#define FILE_NOTIFY_CHANGE_SIZE         0x00000008
+#define FILE_NOTIFY_CHANGE_LAST_WRITE   0x00000010
+#define FILE_NOTIFY_CHANGE_LAST_ACCESS  0x00000020
+#define FILE_NOTIFY_CHANGE_CREATION     0x00000040
+#define FILE_NOTIFY_CHANGE_EA           0x00000080
+#define FILE_NOTIFY_CHANGE_SECURITY     0x00000100
+#define FILE_NOTIFY_CHANGE_STREAM_NAME  0x00000200
+#define FILE_NOTIFY_CHANGE_STREAM_SIZE  0x00000400
+#define FILE_NOTIFY_CHANGE_STREAM_WRITE 0x00000800
+
+#define FILE_ACTION_ADDED		0x00000001
+#define FILE_ACTION_REMOVED		0x00000002
+#define FILE_ACTION_MODIFIED		0x00000003
+#define FILE_ACTION_RENAMED_OLD_NAME	0x00000004
+#define FILE_ACTION_RENAMED_NEW_NAME	0x00000005
+#define FILE_ACTION_ADDED_STREAM	0x00000006
+#define FILE_ACTION_REMOVED_STREAM	0x00000007
+#define FILE_ACTION_MODIFIED_STREAM	0x00000008
+
+/* response contains array of the following structures */
+struct file_notify_information {
+	__le32 NextEntryOffset;
+	__le32 Action;
+	__le32 FileNameLength;
+	__u8  FileName[0];
+}; 
+
+struct reparse_data {
+	__u32	ReparseTag;
+	__u16	ReparseDataLength;
+	__u16	Reserved;
+	__u16	AltNameOffset;
+	__u16	AltNameLen;
+	__u16	TargetNameOffset;
+	__u16	TargetNameLen;
+	char	LinkNamesBuf[1];
+};
+
+struct cifs_quota_data {
+	__u32	rsrvd1;  /* 0 */
+	__u32	sid_size;
+	__u64	rsrvd2;  /* 0 */
+	__u64	space_used;
+	__u64	soft_limit;
+	__u64	hard_limit;
+	char	sid[1];  /* variable size? */
+};
+
+/* quota sub commands */
+#define QUOTA_LIST_CONTINUE	    0
+#define QUOTA_LIST_START	0x100
+#define QUOTA_FOR_SID		0x101
+
+struct trans2_req {
+	/* struct smb_hdr hdr precedes. Set wct = 14+ */
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
+	__le16 MaxParameterCount;
+	__le16 MaxDataCount;
+	__u8 MaxSetupCount;
+	__u8 Reserved;
+	__le16 Flags;
+	__le32 Timeout;
+	__u16 Reserved2;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 DataCount;
+	__le16 DataOffset;
+	__u8 SetupCount;
+	__u8 Reserved3;
+	__le16 SubCommand; /* 1st setup word - SetupCount words follow */
+	__le16 ByteCount;
+};
+
+struct smb_t2_req {
+	struct smb_hdr hdr;
+	struct trans2_req t2_req;
+};
+
+struct trans2_resp {
+	/* struct smb_hdr hdr precedes. Note wct = 10 + setup count */
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
+	__u16 Reserved;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 ParameterDisplacement;
+	__le16 DataCount;
+	__le16 DataOffset;
+	__le16 DataDisplacement;
+	__u8 SetupCount;
+	__u8 Reserved1;
+	/* SetupWords[SetupCount];
+	__u16 ByteCount;
+	__u16 Reserved2;*/	
+	/* data area follows */
+};
+
+struct smb_t2_rsp {
+	struct smb_hdr hdr;
+	struct trans2_resp t2_rsp;
+};
+
+/* PathInfo/FileInfo infolevels */
+#define SMB_INFO_STANDARD                   1
+#define SMB_SET_FILE_EA                     2
+#define SMB_QUERY_FILE_EA_SIZE              2
+#define SMB_INFO_QUERY_EAS_FROM_LIST        3
+#define SMB_INFO_QUERY_ALL_EAS              4
+#define SMB_INFO_IS_NAME_VALID              6
+#define SMB_QUERY_FILE_BASIC_INFO       0x101
+#define SMB_QUERY_FILE_STANDARD_INFO    0x102
+#define SMB_QUERY_FILE_EA_INFO          0x103
+#define SMB_QUERY_FILE_NAME_INFO        0x104
+#define SMB_QUERY_FILE_ALLOCATION_INFO  0x105
+#define SMB_QUERY_FILE_END_OF_FILEINFO  0x106
+#define SMB_QUERY_FILE_ALL_INFO         0x107
+#define SMB_QUERY_ALT_NAME_INFO         0x108
+#define SMB_QUERY_FILE_STREAM_INFO      0x109
+#define SMB_QUERY_FILE_COMPRESSION_INFO 0x10B
+#define SMB_QUERY_FILE_UNIX_BASIC       0x200
+#define SMB_QUERY_FILE_UNIX_LINK        0x201
+#define SMB_QUERY_POSIX_ACL             0x204
+#define SMB_QUERY_XATTR                 0x205
+#define SMB_QUERY_ATTR_FLAGS            0x206  /* append,immutable etc. */
+#define SMB_QUERY_FILE_INTERNAL_INFO    0x3ee
+#define SMB_QUERY_FILE_ACCESS_INFO      0x3f0
+#define SMB_QUERY_FILE_NAME_INFO2       0x3f1 /* 0x30 bytes */
+#define SMB_QUERY_FILE_POSITION_INFO    0x3f6 
+#define SMB_QUERY_FILE_MODE_INFO        0x3f8
+#define SMB_QUERY_FILE_ALGN_INFO        0x3f9 
+
+
+#define SMB_SET_FILE_BASIC_INFO	        0x101
+#define SMB_SET_FILE_DISPOSITION_INFO   0x102
+#define SMB_SET_FILE_ALLOCATION_INFO    0x103
+#define SMB_SET_FILE_END_OF_FILE_INFO   0x104
+#define SMB_SET_FILE_UNIX_BASIC         0x200
+#define SMB_SET_FILE_UNIX_LINK          0x201
+#define SMB_SET_FILE_UNIX_HLINK         0x203
+#define SMB_SET_POSIX_ACL               0x204
+#define SMB_SET_XATTR                   0x205
+#define SMB_SET_ATTR_FLAGS              0x206  /* append, immutable etc. */
+#define SMB_SET_FILE_BASIC_INFO2        0x3ec
+#define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo level too */
+#define SMB_FILE_ALL_INFO2              0x3fa
+#define SMB_SET_FILE_ALLOCATION_INFO2   0x3fb
+#define SMB_SET_FILE_END_OF_FILE_INFO2  0x3fc
+#define SMB_FILE_MOVE_CLUSTER_INFO      0x407
+#define SMB_FILE_QUOTA_INFO             0x408
+#define SMB_FILE_REPARSEPOINT_INFO      0x409
+#define SMB_FILE_MAXIMUM_INFO           0x40d
+
+/* Find File infolevels */
+#define SMB_FIND_FILE_DIRECTORY_INFO      0x101
+#define SMB_FIND_FILE_FULL_DIRECTORY_INFO 0x102
+#define SMB_FIND_FILE_NAMES_INFO          0x103
+#define SMB_FIND_FILE_BOTH_DIRECTORY_INFO 0x104
+#define SMB_FIND_FILE_ID_FULL_DIR_INFO    0x105
+#define SMB_FIND_FILE_ID_BOTH_DIR_INFO    0x106
+#define SMB_FIND_FILE_UNIX                0x202
+
+typedef struct smb_com_transaction2_qpi_req {
+	struct smb_hdr hdr;	/* wct = 14+ */
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
+	__le16 MaxParameterCount;
+	__le16 MaxDataCount;
+	__u8 MaxSetupCount;
+	__u8 Reserved;
+	__le16 Flags;
+	__le32 Timeout;
+	__u16 Reserved2;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 DataCount;
+	__le16 DataOffset;
+	__u8 SetupCount;
+	__u8 Reserved3;
+	__le16 SubCommand;	/* one setup word */
+	__le16 ByteCount;
+	__u8 Pad;
+	__le16 InformationLevel;
+	__u32 Reserved4;
+	char FileName[1];
+} TRANSACTION2_QPI_REQ;
+
+typedef struct smb_com_transaction2_qpi_rsp {
+	struct smb_hdr hdr;	/* wct = 10 + SetupCount */
+	struct trans2_resp t2;
+	__u16 ByteCount;
+	__u16 Reserved2;	/* parameter word reserved - present for infolevels > 100 */
+} TRANSACTION2_QPI_RSP;
+
+typedef struct smb_com_transaction2_spi_req {
+	struct smb_hdr hdr;	/* wct = 15 */
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
+	__le16 MaxParameterCount;
+	__le16 MaxDataCount;
+	__u8 MaxSetupCount;
+	__u8 Reserved;
+	__le16 Flags;
+	__le32 Timeout;
+	__u16 Reserved2;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 DataCount;
+	__le16 DataOffset;
+	__u8 SetupCount;
+	__u8 Reserved3;
+	__le16 SubCommand;	/* one setup word */
+	__le16 ByteCount;
+	__u8 Pad;
+	__u16 Pad1;
+	__le16 InformationLevel;
+	__u32 Reserved4;
+	char FileName[1];
+} TRANSACTION2_SPI_REQ;
+
+typedef struct smb_com_transaction2_spi_rsp {
+	struct smb_hdr hdr;	/* wct = 10 + SetupCount */
+	struct trans2_resp t2;
+	__u16 ByteCount;
+	__u16 Reserved2;	/* parameter word reserved - present for infolevels > 100 */
+} TRANSACTION2_SPI_RSP;
+
+struct set_file_rename {
+	__le32 overwrite;   /* 1 = overwrite dest */
+	__u32 root_fid;   /* zero */
+	__le32 target_name_len;
+	char  target_name[0];  /* Must be unicode */
+};
+
+struct smb_com_transaction2_sfi_req {
+	struct smb_hdr hdr;	/* wct = 15 */
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
+	__le16 MaxParameterCount;
+	__le16 MaxDataCount;
+	__u8 MaxSetupCount;
+	__u8 Reserved;
+	__le16 Flags;
+	__le32 Timeout;
+	__u16 Reserved2;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 DataCount;
+	__le16 DataOffset;
+	__u8 SetupCount;
+	__u8 Reserved3;
+	__le16 SubCommand;	/* one setup word */
+	__le16 ByteCount;
+	__u8 Pad;
+	__u16 Pad1;
+	__u16 Fid;
+	__le16 InformationLevel;
+	__u16 Reserved4;	
+};
+
+struct smb_com_transaction2_sfi_rsp {
+	struct smb_hdr hdr;	/* wct = 10 + SetupCount */
+	struct trans2_resp t2;
+	__u16 ByteCount;
+	__u16 Reserved2;	/* parameter word reserved - present for infolevels > 100 */
+};
+
+
+/*
+ * Flags on T2 FINDFIRST and FINDNEXT 
+ */
+#define CIFS_SEARCH_CLOSE_ALWAYS  0x0001
+#define CIFS_SEARCH_CLOSE_AT_END  0x0002
+#define CIFS_SEARCH_RETURN_RESUME 0x0004
+#define CIFS_SEARCH_CONTINUE_FROM_LAST 0x0008
+#define CIFS_SEARCH_BACKUP_SEARCH 0x0010
+
+/*
+ * Size of the resume key on FINDFIRST and FINDNEXT calls
+ */
+#define CIFS_SMB_RESUME_KEY_SIZE 4
+
+typedef struct smb_com_transaction2_ffirst_req {
+	struct smb_hdr hdr;	/* wct = 15 */
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
+	__le16 MaxParameterCount;
+	__le16 MaxDataCount;
+	__u8 MaxSetupCount;
+	__u8 Reserved;
+	__le16 Flags;
+	__le32 Timeout;
+	__u16 Reserved2;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 DataCount;
+	__le16 DataOffset;
+	__u8 SetupCount;	/* one */
+	__u8 Reserved3;
+	__le16 SubCommand;	/* TRANS2_FIND_FIRST */
+	__le16 ByteCount;
+	__u8 Pad;
+	__le16 SearchAttributes;
+	__le16 SearchCount;
+	__le16 SearchFlags;
+	__le16 InformationLevel;
+	__le32 SearchStorageType;
+	char FileName[1];
+} TRANSACTION2_FFIRST_REQ;
+
+typedef struct smb_com_transaction2_ffirst_rsp {
+	struct smb_hdr hdr;	/* wct = 10 */
+	struct trans2_resp t2;
+	__u16 ByteCount;
+} TRANSACTION2_FFIRST_RSP;
+
+typedef struct smb_com_transaction2_ffirst_rsp_parms {
+	__u16 SearchHandle;
+	__le16 SearchCount;
+	__le16 EndofSearch;
+	__le16 EAErrorOffset;
+	__le16 LastNameOffset;
+} T2_FFIRST_RSP_PARMS;
+
+typedef struct smb_com_transaction2_fnext_req {
+	struct smb_hdr hdr;	/* wct = 15 */
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
+	__le16 MaxParameterCount;
+	__le16 MaxDataCount;
+	__u8 MaxSetupCount;
+	__u8 Reserved;
+	__le16 Flags;
+	__le32 Timeout;
+	__u16 Reserved2;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 DataCount;
+	__le16 DataOffset;
+	__u8 SetupCount;	/* one */
+	__u8 Reserved3;
+	__le16 SubCommand;	/* TRANS2_FIND_NEXT */
+	__le16 ByteCount;
+	__u8 Pad;
+	__u16 SearchHandle;
+	__le16 SearchCount;
+	__le16 InformationLevel;
+	__u32 ResumeKey;
+	__le16 SearchFlags;
+	char ResumeFileName[1];
+} TRANSACTION2_FNEXT_REQ;
+
+typedef struct smb_com_transaction2_fnext_rsp {
+	struct smb_hdr hdr;	/* wct = 10 */
+	struct trans2_resp t2;
+	__u16 ByteCount;
+} TRANSACTION2_FNEXT_RSP;
+
+typedef struct smb_com_transaction2_fnext_rsp_parms {
+	__le16 SearchCount;
+	__le16 EndofSearch;
+	__le16 EAErrorOffset;
+	__le16 LastNameOffset;
+} T2_FNEXT_RSP_PARMS;
+
+/* QFSInfo Levels */
+#define SMB_INFO_ALLOCATION         1
+#define SMB_INFO_VOLUME             2
+#define SMB_QUERY_FS_VOLUME_INFO    0x102
+#define SMB_QUERY_FS_SIZE_INFO      0x103
+#define SMB_QUERY_FS_DEVICE_INFO    0x104
+#define SMB_QUERY_FS_ATTRIBUTE_INFO 0x105
+#define SMB_QUERY_CIFS_UNIX_INFO    0x200
+#define SMB_QUERY_POSIX_FS_INFO     0x201
+#define SMB_QUERY_LABEL_INFO        0x3ea
+#define SMB_QUERY_FS_QUOTA_INFO     0x3ee
+#define SMB_QUERY_FS_FULL_SIZE_INFO 0x3ef
+#define SMB_QUERY_OBJECTID_INFO     0x3f0
+
+typedef struct smb_com_transaction2_qfsi_req {
+	struct smb_hdr hdr;	/* wct = 14+ */
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
+	__le16 MaxParameterCount;
+	__le16 MaxDataCount;
+	__u8 MaxSetupCount;
+	__u8 Reserved;
+	__le16 Flags;
+	__le32 Timeout;
+	__u16 Reserved2;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 DataCount;
+	__le16 DataOffset;
+	__u8 SetupCount;
+	__u8 Reserved3;
+	__le16 SubCommand;	/* one setup word */
+	__le16 ByteCount;
+	__u8 Pad;
+	__le16 InformationLevel;
+} TRANSACTION2_QFSI_REQ;
+
+typedef struct smb_com_transaction_qfsi_rsp {
+	struct smb_hdr hdr;	/* wct = 10 + SetupCount */
+	struct trans2_resp t2;
+	__u16 ByteCount;
+	__u8 Pad;		/* may be three bytes *//* followed by data area */
+} TRANSACTION2_QFSI_RSP;
+
+typedef struct smb_com_transaction2_get_dfs_refer_req {
+	struct smb_hdr hdr;	/* wct = 15 */
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
+	__le16 MaxParameterCount;
+	__le16 MaxDataCount;
+	__u8 MaxSetupCount;
+	__u8 Reserved;
+	__le16 Flags;
+	__le32 Timeout;
+	__u16 Reserved2;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 DataCount;
+	__le16 DataOffset;
+	__u8 SetupCount;
+	__u8 Reserved3;
+	__le16 SubCommand;	/* one setup word */
+	__le16 ByteCount;
+	__u8 Pad[3];		/* Win2K has sent 0x0F01 (max resp length perhaps?) followed by one byte pad - doesn't seem to matter though */
+	__le16 MaxReferralLevel;
+	char RequestFileName[1];
+} TRANSACTION2_GET_DFS_REFER_REQ;
+
+typedef struct dfs_referral_level_3 {
+	__le16 VersionNumber;
+	__le16 ReferralSize;
+	__le16 ServerType;	/* 0x0001 = CIFS server */
+	__le16 ReferralFlags;	/* or proximity - not clear which since always set to zero - SNIA spec says 0x01 means strip off PathConsumed chars before submitting RequestFileName to remote node */
+	__le16 TimeToLive;
+	__le16 Proximity;
+	__le16 DfsPathOffset;
+	__le16 DfsAlternatePathOffset;
+	__le16 NetworkAddressOffset;
+} REFERRAL3;
+
+typedef struct smb_com_transaction_get_dfs_refer_rsp {
+	struct smb_hdr hdr;	/* wct = 10 */
+	struct trans2_resp t2;
+	__u16 ByteCount;
+	__u8 Pad;
+	__le16 PathConsumed;
+	__le16 NumberOfReferrals;
+	__le16 DFSFlags;
+	__u16 Pad2;
+	REFERRAL3 referrals[1];	/* array of level 3 dfs_referral structures */
+	/* followed by the strings pointed to by the referral structures */
+} TRANSACTION2_GET_DFS_REFER_RSP;
+
+/* DFS Flags */
+#define DFSREF_REFERRAL_SERVER  0x0001
+#define DFSREF_STORAGE_SERVER   0x0002
+
+/* IOCTL information */
+/* List of ioctl function codes that look to be of interest to remote clients like this. */
+/* Need to do some experimentation to make sure they all work remotely.                  */
+/* Some of the following such as the encryption/compression ones would be                */
+/* invoked from tools via a specialized hook into the VFS rather than via the            */
+/* standard vfs entry points */
+#define FSCTL_REQUEST_OPLOCK_LEVEL_1 0x00090000
+#define FSCTL_REQUEST_OPLOCK_LEVEL_2 0x00090004
+#define FSCTL_REQUEST_BATCH_OPLOCK   0x00090008
+#define FSCTL_LOCK_VOLUME            0x00090018
+#define FSCTL_UNLOCK_VOLUME          0x0009001C
+#define FSCTL_GET_COMPRESSION        0x0009003C
+#define FSCTL_SET_COMPRESSION        0x0009C040
+#define FSCTL_REQUEST_FILTER_OPLOCK  0x0009008C
+#define FSCTL_FILESYS_GET_STATISTICS 0x00090090
+#define FSCTL_SET_REPARSE_POINT      0x000900A4
+#define FSCTL_GET_REPARSE_POINT      0x000900A8
+#define FSCTL_DELETE_REPARSE_POINT   0x000900AC
+#define FSCTL_SET_SPARSE             0x000900C4
+#define FSCTL_SET_ZERO_DATA          0x000900C8
+#define FSCTL_SET_ENCRYPTION         0x000900D7
+#define FSCTL_ENCRYPTION_FSCTL_IO    0x000900DB
+#define FSCTL_WRITE_RAW_ENCRYPTED    0x000900DF
+#define FSCTL_READ_RAW_ENCRYPTED     0x000900E3
+#define FSCTL_SIS_COPYFILE           0x00090100
+#define FSCTL_SIS_LINK_FILES         0x0009C104
+
+#define IO_REPARSE_TAG_MOUNT_POINT   0xA0000003
+#define IO_REPARSE_TAG_HSM           0xC0000004
+#define IO_REPARSE_TAG_SIS           0x80000007
+
+/*
+ ************************************************************************
+ * All structs for everything above the SMB PDUs themselves
+ * (such as the T2 level specific data) go here                  
+ ************************************************************************
+ */
+
+/*
+ * Information on a server
+ */
+
+struct serverInfo {
+	char name[16];
+	unsigned char versionMajor;
+	unsigned char versionMinor;
+	unsigned long type;
+	unsigned int commentOffset;
+};
+
+/*
+ * The following structure is the format of the data returned on a NetShareEnum
+ * with level "90" (x5A)
+ */
+
+struct shareInfo {
+	char shareName[13];
+	char pad;
+	unsigned short type;
+	unsigned int commentOffset;
+};
+
+struct aliasInfo {
+	char aliasName[9];
+	char pad;
+	unsigned int commentOffset;
+	unsigned char type[2];
+};
+
+struct aliasInfo92 {
+	int aliasNameOffset;
+	int serverNameOffset;
+	int shareNameOffset;
+};
+
+typedef struct {
+	__le64 TotalAllocationUnits;
+	__le64 FreeAllocationUnits;
+	__le32 SectorsPerAllocationUnit;
+	__le32 BytesPerSector;
+} FILE_SYSTEM_INFO;		/* size info, level 0x103 */
+
+typedef struct {
+	__le16 MajorVersionNumber;
+	__le16 MinorVersionNumber;
+	__le64 Capability;
+} FILE_SYSTEM_UNIX_INFO;	/* Unix extensions info, level 0x200 */
+/* Linux/Unix extensions capability flags */
+#define CIFS_UNIX_FCNTL_CAP             0x00000001 /* support for fcntl locks */
+#define CIFS_UNIX_POSIX_ACL_CAP         0x00000002
+#define CIFS_UNIX_XATTR_CAP             0x00000004 /*support for new namespace*/
+
+typedef struct {
+	/* For undefined recommended transfer size return -1 in that field */
+	__le32 OptimalTransferSize;  /* bsize on some os, iosize on other os */
+	__le32 BlockSize; 
+    /* The next three fields are in terms of the block size.
+	(above). If block size is unknown, 4096 would be a
+	reasonable block size for a server to report. 
+	Note that returning the blocks/blocksavail removes need
+	to make a second call (to QFSInfo level 0x103 to get this info.
+	UserBlockAvail is typically less than or equal to BlocksAvail,
+	if no distinction is made return the same value in each */
+	__le64 TotalBlocks;
+	__le64 BlocksAvail;       /* bfree */
+	__le64 UserBlocksAvail;   /* bavail */
+    /* For undefined Node fields or FSID return -1 */
+	__le64 TotalFileNodes;
+	__le64 FreeFileNodes;
+	__le64 FileSysIdentifier;   /* fsid */
+	/* NB Namelen comes from FILE_SYSTEM_ATTRIBUTE_INFO call */
+	/* NB flags can come from FILE_SYSTEM_DEVICE_INFO call   */
+} FILE_SYSTEM_POSIX_INFO;
+
+/* DeviceType Flags */
+#define FILE_DEVICE_CD_ROM              0x00000002
+#define FILE_DEVICE_CD_ROM_FILE_SYSTEM  0x00000003
+#define FILE_DEVICE_DFS                 0x00000006
+#define FILE_DEVICE_DISK                0x00000007
+#define FILE_DEVICE_DISK_FILE_SYSTEM    0x00000008
+#define FILE_DEVICE_FILE_SYSTEM         0x00000009
+#define FILE_DEVICE_NAMED_PIPE          0x00000011
+#define FILE_DEVICE_NETWORK             0x00000012
+#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014
+#define FILE_DEVICE_NULL                0x00000015
+#define FILE_DEVICE_PARALLEL_PORT       0x00000016
+#define FILE_DEVICE_PRINTER             0x00000018
+#define FILE_DEVICE_SERIAL_PORT         0x0000001b
+#define FILE_DEVICE_STREAMS             0x0000001e
+#define FILE_DEVICE_TAPE                0x0000001f
+#define FILE_DEVICE_TAPE_FILE_SYSTEM    0x00000020
+#define FILE_DEVICE_VIRTUAL_DISK        0x00000024
+#define FILE_DEVICE_NETWORK_REDIRECTOR  0x00000028
+
+typedef struct {
+	__le32 DeviceType;
+	__le32 DeviceCharacteristics;
+} FILE_SYSTEM_DEVICE_INFO;	/* device info, level 0x104 */
+
+typedef struct {
+	__le32 Attributes;
+	__le32 MaxPathNameComponentLength;
+	__le32 FileSystemNameLen;
+	char FileSystemName[52]; /* do not really need to save this - so potentially get only subset of name */
+} FILE_SYSTEM_ATTRIBUTE_INFO;
+
+/******************************************************************************/
+/* QueryFileInfo/QueryPathinfo (also for SetPath/SetFile) data buffer formats */
+/******************************************************************************/
+typedef struct { /* data block encoding of response to level 263 QPathInfo */
+	__le64 CreationTime;
+	__le64 LastAccessTime;
+	__le64 LastWriteTime;
+	__le64 ChangeTime;
+	__le32 Attributes;
+	__u32 Pad1;
+	__le64 AllocationSize;
+	__le64 EndOfFile;	/* size ie offset to first free byte in file */
+	__le32 NumberOfLinks;	/* hard links */
+	__u8 DeletePending;
+	__u8 Directory;
+	__u16 Pad2;
+	__u64 IndexNumber;
+	__le32 EASize;
+	__le32 AccessFlags;
+	__u64 IndexNumber1;
+	__le64 CurrentByteOffset;
+	__le32 Mode;
+	__le32 AlignmentRequirement;
+	__le32 FileNameLength;
+	char FileName[1];
+} FILE_ALL_INFO;		/* level 0x107 QPathInfo */
+
+/* defines for enumerating possible values of the Unix type field below */
+#define UNIX_FILE      0
+#define UNIX_DIR       1
+#define UNIX_SYMLINK   2
+#define UNIX_CHARDEV   3
+#define UNIX_BLOCKDEV  4
+#define UNIX_FIFO      5
+#define UNIX_SOCKET    6
+typedef struct {
+	__le64 EndOfFile;
+	__le64 NumOfBytes;
+	__le64 LastStatusChange; /*SNIA specs DCE time for the 3 time fields */
+	__le64 LastAccessTime;
+	__le64 LastModificationTime;
+	__le64 Uid;
+	__le64 Gid;
+	__le32 Type;
+	__le64 DevMajor;
+	__le64 DevMinor;
+	__u64 UniqueId;
+	__le64 Permissions;
+	__le64 Nlinks;
+} FILE_UNIX_BASIC_INFO;		/* level 0x200 QPathInfo */
+
+typedef struct {
+	char LinkDest[1];
+} FILE_UNIX_LINK_INFO;		/* level 0x201 QPathInfo */
+
+/* The following three structures are needed only for
+	setting time to NT4 and some older servers via
+	the primitive DOS time format */
+typedef struct {
+	__u16 Day:5;
+	__u16 Month:4;
+	__u16 Year:7;
+} SMB_DATE;
+
+typedef struct {
+	__u16 TwoSeconds:5;
+	__u16 Minutes:6;
+	__u16 Hours:5;
+} SMB_TIME;
+
+typedef struct {
+	__le16 CreationDate; /* SMB Date see above */
+	__le16 CreationTime; /* SMB Time */
+	__le16 LastAccessDate;
+	__le16 LastAccessTime;
+	__le16 LastWriteDate;
+	__le16 LastWriteTime;
+	__le32 DataSize; /* File Size (EOF) */
+	__le32 AllocationSize;
+	__le16 Attributes; /* verify not u32 */
+	__le32 EASize;
+} FILE_INFO_STANDARD;  /* level 1 SetPath/FileInfo */
+
+typedef struct {
+	__le64 CreationTime;
+	__le64 LastAccessTime;
+	__le64 LastWriteTime;
+	__le64 ChangeTime;
+	__le32 Attributes;
+	__u32 Pad;
+} FILE_BASIC_INFO;		/* size info, level 0x101 */
+
+struct file_allocation_info {
+	__le64 AllocationSize; /* Note old Samba srvr rounds this up too much */
+};	/* size used on disk, level 0x103 for set, 0x105 for query */
+
+struct file_end_of_file_info {
+	__le64 FileSize;		/* offset to end of file */
+};	/* size info, level 0x104 for set, 0x106 for query */
+
+struct file_alt_name_info {
+	__u8   alt_name[1];
+};      /* level 0x0108 */
+
+struct file_stream_info {
+	__le32 number_of_streams;  /* BB check sizes and verify location */
+	/* followed by info on streams themselves 
+		u64 size;
+		u64 allocation_size 
+		stream info */
+};      /* level 0x109 */
+
+struct file_compression_info {
+	__le64 compressed_size;
+	__le16 format;
+	__u8   unit_shift;
+	__u8   ch_shift;
+	__u8   cl_shift;
+	__u8   pad[3];
+};      /* level 0x10b */
+
+/* POSIX ACL set/query path info structures */
+#define CIFS_ACL_VERSION 1
+struct cifs_posix_ace { /* access control entry (ACE) */
+	__u8  cifs_e_tag;
+	__u8  cifs_e_perm;
+	__le64 cifs_uid; /* or gid */
+}; 
+
+struct cifs_posix_acl { /* access conrol list  (ACL) */
+	__le16	version;
+	__le16	access_entry_count;  /* access ACL - count of entries */
+	__le16	default_entry_count; /* default ACL - count of entries */
+	struct cifs_posix_ace ace_array[0];
+	/* followed by
+	struct cifs_posix_ace default_ace_arraay[] */
+};  /* level 0x204 */
+
+/* types of access control entries already defined in posix_acl.h */
+/* #define CIFS_POSIX_ACL_USER_OBJ	 0x01
+#define CIFS_POSIX_ACL_USER      0x02
+#define CIFS_POSIX_ACL_GROUP_OBJ 0x04
+#define CIFS_POSIX_ACL_GROUP     0x08
+#define CIFS_POSIX_ACL_MASK      0x10
+#define CIFS_POSIX_ACL_OTHER     0x20 */
+
+/* types of perms */
+/* #define CIFS_POSIX_ACL_EXECUTE   0x01
+#define CIFS_POSIX_ACL_WRITE     0x02
+#define CIFS_POSIX_ACL_READ	     0x04 */
+
+/* end of POSIX ACL definitions */
+
+struct file_internal_info {
+	__u64  UniqueId; /* inode number */
+};      /* level 0x3ee */
+struct file_mode_info {
+	__le32	Mode;
+};      /* level 0x3f8 */
+
+struct file_attrib_tag {
+	__le32 Attribute;
+	__le32 ReparseTag;
+};      /* level 0x40b */
+
+
+/********************************************************/
+/*  FindFirst/FindNext transact2 data buffer formats    */ 
+/********************************************************/
+
+typedef struct {
+	__le32 NextEntryOffset;
+	__u32 ResumeKey; /* as with FileIndex - no need to convert */
+	__le64 EndOfFile;
+	__le64 NumOfBytes;
+	__le64 LastStatusChange; /*SNIA specs DCE time for the 3 time fields */
+	__le64 LastAccessTime;
+	__le64 LastModificationTime;
+	__le64 Uid;
+	__le64 Gid;
+	__le32 Type;
+	__le64 DevMajor;
+	__le64 DevMinor;
+	__u64 UniqueId;
+	__le64 Permissions;
+	__le64 Nlinks;
+	char FileName[1];
+} FILE_UNIX_INFO; /* level 0x202 */
+
+typedef struct {
+	__le32 NextEntryOffset;
+	__u32 FileIndex;
+	__le64 CreationTime;
+	__le64 LastAccessTime;
+	__le64 LastWriteTime;
+	__le64 ChangeTime;
+	__le64 EndOfFile;
+	__le64 AllocationSize;
+	__le32 ExtFileAttributes;
+	__le32 FileNameLength;
+	char FileName[1];
+} FILE_DIRECTORY_INFO;   /* level 0x101 FF response data area */
+
+typedef struct {
+	__le32 NextEntryOffset;
+	__u32 FileIndex;
+	__le64 CreationTime;
+	__le64 LastAccessTime;
+	__le64 LastWriteTime;
+	__le64 ChangeTime;
+	__le64 EndOfFile;
+	__le64 AllocationSize;
+	__le32 ExtFileAttributes;
+	__le32 FileNameLength;
+	__le32 EaSize; /* length of the xattrs */
+	char FileName[1];
+} FILE_FULL_DIRECTORY_INFO;   /* level 0x102 FF response data area */
+
+typedef struct {
+	__le32 NextEntryOffset;
+	__u32 FileIndex;
+	__le64 CreationTime;
+	__le64 LastAccessTime;
+	__le64 LastWriteTime;
+	__le64 ChangeTime;
+	__le64 EndOfFile;
+	__le64 AllocationSize;
+	__le32 ExtFileAttributes;
+	__le32 FileNameLength;
+	__le32 EaSize; /* EA size */
+	__le32 Reserved;
+	__u64 UniqueId; /* inode num - le since Samba puts ino in low 32 bit*/
+	char FileName[1];
+} SEARCH_ID_FULL_DIR_INFO;   /* level 0x105 FF response data area */
+
+typedef struct {
+	__le32 NextEntryOffset;
+	__u32 FileIndex;
+	__le64 CreationTime;
+	__le64 LastAccessTime;
+	__le64 LastWriteTime;
+	__le64 ChangeTime;
+	__le64 EndOfFile;
+	__le64 AllocationSize;
+	__le32 ExtFileAttributes;
+	__le32 FileNameLength; 
+	__le32 EaSize; /* length of the xattrs */
+	__u8   ShortNameLength;
+	__u8   Reserved;
+	__u8   ShortName[12];
+	char FileName[1];
+} FILE_BOTH_DIRECTORY_INFO;   /* level 0x104 FF response data area */
+
+
+struct gea {
+	unsigned char name_len;
+	char name[1];
+};
+
+struct gealist {
+	unsigned long list_len;
+	struct gea list[1];
+};
+
+struct fea {
+	unsigned char EA_flags;
+	__u8 name_len;
+	__le16 value_len;
+	char name[1];
+	/* optionally followed by value */
+};
+/* flags for _FEA.fEA */
+#define FEA_NEEDEA         0x80	/* need EA bit */
+
+struct fealist {
+	__le32 list_len;
+	struct fea list[1];
+};
+
+/* used to hold an arbitrary blob of data */
+struct data_blob {
+	__u8 *data;
+	size_t length;
+	void (*free) (struct data_blob * data_blob);
+};
+
+
+#ifdef CONFIG_CIFS_POSIX
+/* 
+	For better POSIX semantics from Linux client, (even better
+	than the existing CIFS Unix Extensions) we need updated PDUs for:
+	
+	1) PosixCreateX - to set and return the mode, inode#, device info and
+	perhaps add a CreateDevice - to create Pipes and other special .inodes
+	Also note POSIX open flags
+	2) Close - to return the last write time to do cache across close more safely
+	3) PosixQFSInfo - to return statfs info
+	4) FindFirst return unique inode number - what about resume key, two forms short (matches readdir) and full (enough info to cache inodes)
+	5) Mkdir - set mode
+	
+	And under consideration: 
+	6) FindClose2 (return nanosecond timestamp ??)
+	7) Use nanosecond timestamps throughout all time fields if 
+	   corresponding attribute flag is set
+	8) sendfile - handle based copy
+	9) Direct i/o
+	10) "POSIX ACL" support
+	11) Misc fcntls?
+	
+	what about fixing 64 bit alignment
+	
+	There are also various legacy SMB/CIFS requests used as is
+	
+	From existing Lanman and NTLM dialects:
+	--------------------------------------
+	NEGOTIATE
+	SESSION_SETUP_ANDX (BB which?)
+	TREE_CONNECT_ANDX (BB which wct?)
+	TREE_DISCONNECT (BB add volume timestamp on response)
+	LOGOFF_ANDX
+	DELETE (note delete open file behavior)
+	DELETE_DIRECTORY
+	READ_AND_X
+	WRITE_AND_X
+	LOCKING_AND_X (note posix lock semantics)
+	RENAME (note rename across dirs and open file rename posix behaviors)
+	NT_RENAME (for hardlinks) Is this good enough for all features?
+	FIND_CLOSE2
+	TRANSACTION2 (18 cases)
+		SMB_SET_FILE_END_OF_FILE_INFO2 SMB_SET_PATH_END_OF_FILE_INFO2
+		(BB verify that never need to set allocation size)
+		SMB_SET_FILE_BASIC_INFO2 (setting times - BB can it be done via Unix ext?)
+	
+	COPY (note support for copy across directories) - FUTURE, OPTIONAL
+	setting/getting OS/2 EAs - FUTURE (BB can this handle
+	setting Linux xattrs perfectly)         - OPTIONAL
+	dnotify                                 - FUTURE, OPTIONAL
+	quota                                   - FUTURE, OPTIONAL
+			
+	Note that various requests implemented for NT interop such as 
+		NT_TRANSACT (IOCTL) QueryReparseInfo
+	are unneeded to servers compliant with the CIFS POSIX extensions
+	
+	From CIFS Unix Extensions:
+	-------------------------
+	T2 SET_PATH_INFO (SMB_SET_FILE_UNIX_LINK) for symlinks
+	T2 SET_PATH_INFO (SMB_SET_FILE_BASIC_INFO2)
+	T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_LINK)
+	T2 QUERY_PATH_INFO (SMB_QUERY_FILE_UNIX_BASIC) - BB check for missing inode fields
+					Actually need QUERY_FILE_UNIX_INFO since has inode num
+					BB what about a) blksize/blkbits/blocks
+								  b) i_version
+								  c) i_rdev
+								  d) notify mask?
+								  e) generation
+								  f) size_seqcount
+	T2 FIND_FIRST/FIND_NEXT FIND_FILE_UNIX
+	TRANS2_GET_DFS_REFERRAL				  - OPTIONAL but recommended
+	T2_QFS_INFO QueryDevice/AttributeInfo - OPTIONAL
+	
+	
+ */
+
+/* xsymlink is a symlink format that can be used
+   to save symlink info in a regular file when 
+   mounted to operating systems that do not
+   support the cifs Unix extensions or EAs (for xattr
+   based symlinks).  For such a file to be recognized
+   as containing symlink data: 
+
+   1) file size must be 1067, 
+   2) signature must begin file data,
+   3) length field must be set to ASCII representation
+	of a number which is less than or equal to 1024, 
+   4) md5 must match that of the path data */
+
+struct xsymlink {
+	/* 1067 bytes */
+	char signature[4]; /* XSym */ /* not null terminated */
+	char cr0;         /* \n */
+/* ASCII representation of length (4 bytes decimal) terminated by \n not null */
+	char length[4];
+	char cr1;         /* \n */
+/* md5 of valid subset of path ie path[0] through path[length-1] */
+	__u8 md5[32];    
+	char cr2;        /* \n */
+/* if room left, then end with \n then 0x20s by convention but not required */
+	char path[1024];  
+};
+
+typedef struct {
+	/* BB do we need another field for flags? BB */
+	__u32 xattr_name_len;
+	__u32 xattr_value_len;
+	char  xattr_name[0];
+	/* followed by xattr_value[xattr_value_len], no pad */
+} FILE_XATTR_INFO;	/* extended attribute, info level 205 */
+
+
+#endif 
+
+#pragma pack()			/* resume default structure packing */
+
+#endif				/* _CIFSPDU_H */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
new file mode 100644
index 0000000..787eef4
--- /dev/null
+++ b/fs/cifs/cifsproto.h
@@ -0,0 +1,269 @@
+/*
+ *   fs/cifs/cifsproto.h
+ *
+ *   Copyright (c) International Business Machines  Corp., 2002,2005
+ *   Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ */
+#ifndef _CIFSPROTO_H
+#define _CIFSPROTO_H
+#include <linux/nls.h>
+
+struct statfs;
+
+/*
+ *****************************************************************
+ * All Prototypes
+ *****************************************************************
+ */
+
+extern struct smb_hdr *cifs_buf_get(void);
+extern void cifs_buf_release(void *);
+extern struct smb_hdr *cifs_small_buf_get(void);
+extern void cifs_small_buf_release(void *);
+extern int smb_send(struct socket *, struct smb_hdr *,
+			unsigned int /* length */ , struct sockaddr *);
+extern unsigned int _GetXid(void);
+extern void _FreeXid(unsigned int);
+#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__FUNCTION__, xid,current->fsuid));
+#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__FUNCTION__,curr_xid,(int)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);
+extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
+			struct smb_hdr * /* input */ ,
+			struct smb_hdr * /* out */ ,
+			int * /* bytes returned */ , const int long_op);
+extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid);
+extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length);
+extern int is_valid_oplock_break(struct smb_hdr *smb);
+extern int is_size_safe_to_change(struct cifsInodeInfo *);
+extern unsigned int smbCalcSize(struct smb_hdr *ptr);
+extern int decode_negTokenInit(unsigned char *security_blob, int length,
+			enum securityEnum *secType);
+extern int cifs_inet_pton(int, char * source, void *dst);
+extern int map_smb_to_linux_error(struct smb_hdr *smb);
+extern void header_assemble(struct smb_hdr *, char /* command */ ,
+			const struct cifsTconInfo *, int
+			/* length of fixed section (word count) in two byte units  */
+			);
+extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, struct cifsTconInfo *);
+extern void DeleteOplockQEntry(struct oplock_q_entry *);
+extern struct timespec cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ );
+extern u64 cifs_UnixTimeToNT(struct timespec);
+extern int cifs_get_inode_info(struct inode **pinode,
+			const unsigned char *search_path, 
+			FILE_ALL_INFO * pfile_info,
+			struct super_block *sb, int xid);
+extern int cifs_get_inode_info_unix(struct inode **pinode,
+			const unsigned char *search_path,
+			struct super_block *sb,int xid);
+
+extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
+			const char *);
+extern int cifs_umount(struct super_block *, struct cifs_sb_info *);
+void cifs_proc_init(void);
+void cifs_proc_clean(void);
+
+extern int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, 
+			struct nls_table * nls_info);
+extern int CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses);
+
+extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
+			const char *tree, struct cifsTconInfo *tcon,
+			const struct nls_table *);
+
+extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
+            const char *searchName, const struct nls_table *nls_codepage,
+            __u16 *searchHandle, struct cifs_search_info * psrch_inf);
+
+extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
+            __u16 searchHandle, struct cifs_search_info * psrch_inf);
+
+extern int CIFSFindClose(const int, struct cifsTconInfo *tcon,
+			const __u16 search_handle);
+
+extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
+			const unsigned char *searchName,
+			FILE_ALL_INFO * findData,
+			const struct nls_table *nls_codepage);
+
+extern int CIFSSMBUnixQPathInfo(const int xid,
+			struct cifsTconInfo *tcon,
+			const unsigned char *searchName,
+			FILE_UNIX_BASIC_INFO * pFindData,
+			const struct nls_table *nls_codepage);
+
+extern int CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
+			const unsigned char *searchName,
+			unsigned char **targetUNCs,
+			unsigned int *number_of_UNC_in_array,
+			const struct nls_table *nls_codepage);
+
+extern int connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
+			const char *old_path,
+			const struct nls_table *nls_codepage);
+extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
+			const char *old_path, const struct nls_table *nls_codepage, 
+			unsigned int *pnum_referrals, unsigned char ** preferrals);
+extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
+			struct kstatfs *FSData,
+			const struct nls_table *nls_codepage);
+extern int CIFSSMBQFSAttributeInfo(const int xid,
+			struct cifsTconInfo *tcon,
+			const struct nls_table *nls_codepage);
+extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon,
+			const struct nls_table *nls_codepage);
+extern int CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
+			const struct nls_table *nls_codepage);
+extern int CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
+			struct kstatfs *FSData, const struct nls_table *nls_codepage);
+
+extern int CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon,
+			const char *fileName, const FILE_BASIC_INFO * data,
+			const struct nls_table *nls_codepage);
+extern int CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon,
+			const FILE_BASIC_INFO * data, __u16 fid);
+#if 0
+extern int CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon,
+			char *fileName, __u16 dos_attributes,
+			const struct nls_table *nls_codepage);
+#endif /* possibly unneeded function */
+extern int CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon,
+			const char *fileName, __u64 size,int setAllocationSizeFlag,
+			const struct nls_table *nls_codepage);
+extern int CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon,
+			 __u64 size, __u16 fileHandle,__u32 opener_pid, int AllocSizeFlag);
+extern int CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *pTcon,
+			char *full_path, __u64 mode, __u64 uid,
+			__u64 gid, dev_t dev, const struct nls_table *nls_codepage);
+
+extern int CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
+			const char *newName,
+			const struct nls_table *nls_codepage);
+extern int CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
+			const char *name, const struct nls_table *nls_codepage);
+
+extern int CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
+			const char *name,
+			const struct nls_table *nls_codepage);
+extern int CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
+			const char *fromName, const char *toName,
+			const struct nls_table *nls_codepage);
+extern int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
+			int netfid, char * target_name, const struct nls_table *nls_codepage);
+extern int CIFSCreateHardLink(const int xid,
+			struct cifsTconInfo *tcon,
+			const char *fromName, const char *toName,
+			const struct nls_table *nls_codepage);
+extern int CIFSUnixCreateHardLink(const int xid,
+			struct cifsTconInfo *tcon,
+			const char *fromName, const char *toName,
+			const struct nls_table *nls_codepage);
+extern int CIFSUnixCreateSymLink(const int xid,
+			struct cifsTconInfo *tcon,
+			const char *fromName, const char *toName,
+			const struct nls_table *nls_codepage);
+extern int CIFSSMBUnixQuerySymLink(const int xid,
+			struct cifsTconInfo *tcon,
+			const unsigned char *searchName,
+			char *syminfo, const int buflen,
+			const struct nls_table *nls_codepage);
+extern int CIFSSMBQueryReparseLinkInfo(const int xid, 
+			struct cifsTconInfo *tcon,
+			const unsigned char *searchName,
+			char *symlinkinfo, const int buflen, __u16 fid,
+			const struct nls_table *nls_codepage);
+
+extern int CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
+			const char *fileName, const int disposition,
+			const int access_flags, const int omode,
+			__u16 * netfid, int *pOplock, FILE_ALL_INFO *,
+			const struct nls_table *nls_codepage);
+extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon,
+			const int smb_file_id);
+
+extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
+			const int netfid, unsigned int count,
+			const __u64 lseek, unsigned int *nbytes, char **buf);
+extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
+			const int netfid, const unsigned int count,
+			const __u64 lseek, unsigned int *nbytes,
+			const char *buf, const char __user *ubuf, 
+			const int long_op);
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
+			const int netfid, const unsigned int count,
+			const __u64 offset, unsigned int *nbytes, 
+			const char __user *buf,const int long_op);
+extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
+			const unsigned char *searchName, __u64 * inode_number,
+			const struct nls_table *nls_codepage);
+#endif /* CONFIG_CIFS_EXPERIMENTAL */
+
+extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
+			const __u16 netfid, const __u64 len,
+			const __u64 offset, const __u32 numUnlock,
+			const __u32 numLock, const __u8 lockType,
+			const int waitFlag);
+
+extern int CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon);
+extern int CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses);
+
+extern struct cifsSesInfo *sesInfoAlloc(void);
+extern void sesInfoFree(struct cifsSesInfo *);
+extern struct cifsTconInfo *tconInfoAlloc(void);
+extern void tconInfoFree(struct cifsTconInfo *);
+
+extern int cifs_reconnect(struct TCP_Server_Info *server);
+
+extern int cifs_sign_smb(struct smb_hdr *, struct cifsSesInfo *,__u32 *);
+extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key,
+	__u32 expected_sequence_number);
+extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
+extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, struct nls_table *);
+extern void CalcNTLMv2_response(const struct cifsSesInfo *,char * );
+extern int CIFSSMBCopy(int xid,
+			struct cifsTconInfo *source_tcon,
+			const char *fromName,
+			const __u16 target_tid,
+			const char *toName, const int flags,
+			const struct nls_table *nls_codepage);
+extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, 
+			const int notify_subdirs,const __u16 netfid,__u32 filter,
+			const struct nls_table *nls_codepage);
+extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
+			const unsigned char *searchName, char * EAData,
+			size_t bufsize, const struct nls_table *nls_codepage);
+extern ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
+		const unsigned char * searchName,const unsigned char * ea_name,
+		unsigned char * ea_value, size_t buf_size, 
+		const struct nls_table *nls_codepage);
+extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, 
+		const char *fileName, const char * ea_name, 
+		const void * ea_value, const __u16 ea_value_len, 
+		const struct nls_table *nls_codepage);
+extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
+		const unsigned char *searchName,
+		char *acl_inf, const int buflen,const int acl_type,
+		const struct nls_table *nls_codepage);
+extern int CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
+		const unsigned char *fileName,
+		const char *local_acl, const int buflen, const int acl_type,
+		const struct nls_table *nls_codepage);
+int cifs_ioctl (struct inode * inode, struct file * filep,
+                unsigned int command, unsigned long arg);
+#endif			/* _CIFSPROTO_H */
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
new file mode 100644
index 0000000..df6a619
--- /dev/null
+++ b/fs/cifs/cifssmb.c
@@ -0,0 +1,4186 @@
+/*
+ *   fs/cifs/cifssmb.c
+ *
+ *   Copyright (C) International Business Machines  Corp., 2002,2005
+ *   Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ *   Contains the routines for constructing the SMB PDUs themselves
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+ /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c   */
+ /* These are mostly routines that operate on a pathname, or on a tree id     */
+ /* (mounted volume), but there are eight handle based routines which must be */
+ /* treated slightly different for reconnection purposes since we never want  */
+ /* to reuse a stale file handle and the caller knows the file handle */
+
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/vfs.h>
+#include <linux/posix_acl_xattr.h>
+#include <asm/uaccess.h>
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_unicode.h"
+#include "cifs_debug.h"
+
+#ifdef CONFIG_CIFS_POSIX
+static struct {
+	int index;
+	char *name;
+} protocols[] = {
+	{CIFS_PROT, "\2NT LM 0.12"}, 
+	{CIFS_PROT, "\2POSIX 2"},
+	{BAD_PROT, "\2"}
+};
+#else
+static struct {
+	int index;
+	char *name;
+} protocols[] = {
+	{CIFS_PROT, "\2NT LM 0.12"}, 
+	{BAD_PROT, "\2"}
+};
+#endif
+
+
+/* Mark as invalid, all open files on tree connections since they
+   were closed when session to server was lost */
+static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
+{
+	struct cifsFileInfo *open_file = NULL;
+	struct list_head * tmp;
+	struct list_head * tmp1;
+
+/* list all files open on tree connection and mark them invalid */
+	write_lock(&GlobalSMBSeslock);
+	list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
+		open_file = list_entry(tmp,struct cifsFileInfo, tlist);
+		if(open_file) {
+			open_file->invalidHandle = TRUE;
+		}
+	}
+	write_unlock(&GlobalSMBSeslock);
+	/* BB Add call to invalidate_inodes(sb) for all superblocks mounted to this tcon */
+}
+
+/* If the return code is zero, this function must fill in request_buf pointer */
+static int
+small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
+	 void **request_buf /* returned */)
+{
+	int rc = 0;
+
+	/* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
+	   check for tcp and smb session status done differently
+	   for those three - in the calling routine */
+	if(tcon) {
+		if((tcon->ses) && (tcon->ses->server)){
+			struct nls_table *nls_codepage;
+				/* Give Demultiplex thread up to 10 seconds to 
+					reconnect, should be greater than cifs socket
+					timeout which is 7 seconds */
+			while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
+				wait_event_interruptible_timeout(tcon->ses->server->response_q,
+					(tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
+				if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
+					/* on "soft" mounts we wait once */
+					if((tcon->retry == FALSE) || 
+					   (tcon->ses->status == CifsExiting)) {
+						cFYI(1,("gave up waiting on reconnect in smb_init"));
+						return -EHOSTDOWN;
+					} /* else "hard" mount - keep retrying until 
+					process is killed or server comes back up */
+				} else /* TCP session is reestablished now */
+					break;
+				 
+			}
+			
+			nls_codepage = load_nls_default();
+		/* need to prevent multiple threads trying to
+		simultaneously reconnect the same SMB session */
+			down(&tcon->ses->sesSem);
+			if(tcon->ses->status == CifsNeedReconnect)
+				rc = cifs_setup_session(0, tcon->ses, nls_codepage);
+			if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
+				mark_open_files_invalid(tcon);
+				rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon,
+					nls_codepage);
+				up(&tcon->ses->sesSem);
+				if(rc == 0)
+					atomic_inc(&tconInfoReconnectCount);
+
+				cFYI(1, ("reconnect tcon rc = %d", rc));
+				/* Removed call to reopen open files here - 
+					it is safer (and faster) to reopen files
+					one at a time as needed in read and write */
+
+				/* Check if handle based operation so we 
+					know whether we can continue or not without
+					returning to caller to reset file handle */
+				switch(smb_command) {
+					case SMB_COM_READ_ANDX:
+					case SMB_COM_WRITE_ANDX:
+					case SMB_COM_CLOSE:
+					case SMB_COM_FIND_CLOSE2:
+					case SMB_COM_LOCKING_ANDX: {
+						unload_nls(nls_codepage);
+						return -EAGAIN;
+					}
+				}
+			} else {
+				up(&tcon->ses->sesSem);
+			}
+			unload_nls(nls_codepage);
+
+		} else {
+			return -EIO;
+		}
+	}
+	if(rc)
+		return rc;
+
+	*request_buf = cifs_small_buf_get();
+	if (*request_buf == NULL) {
+		/* BB should we add a retry in here if not a writepage? */
+		return -ENOMEM;
+	}
+
+	header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct);
+
+#ifdef CONFIG_CIFS_STATS
+        if(tcon != NULL) {
+                atomic_inc(&tcon->num_smbs_sent);
+        }
+#endif /* CONFIG_CIFS_STATS */
+	return rc;
+}  
+
+/* If the return code is zero, this function must fill in request_buf pointer */
+static int
+smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
+	 void **request_buf /* returned */ ,
+	 void **response_buf /* returned */ )
+{
+	int rc = 0;
+
+	/* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
+	   check for tcp and smb session status done differently
+	   for those three - in the calling routine */
+	if(tcon) {
+		if((tcon->ses) && (tcon->ses->server)){
+			struct nls_table *nls_codepage;
+				/* Give Demultiplex thread up to 10 seconds to 
+					reconnect, should be greater than cifs socket
+					timeout which is 7 seconds */
+			while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
+				wait_event_interruptible_timeout(tcon->ses->server->response_q,
+					(tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
+				if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
+					/* on "soft" mounts we wait once */
+					if((tcon->retry == FALSE) || 
+					   (tcon->ses->status == CifsExiting)) {
+						cFYI(1,("gave up waiting on reconnect in smb_init"));
+						return -EHOSTDOWN;
+					} /* else "hard" mount - keep retrying until 
+					process is killed or server comes back up */
+				} else /* TCP session is reestablished now */
+					break;
+				 
+			}
+			
+			nls_codepage = load_nls_default();
+		/* need to prevent multiple threads trying to
+		simultaneously reconnect the same SMB session */
+			down(&tcon->ses->sesSem);
+			if(tcon->ses->status == CifsNeedReconnect)
+				rc = cifs_setup_session(0, tcon->ses, nls_codepage);
+			if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
+				mark_open_files_invalid(tcon);
+				rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon,
+					nls_codepage);
+				up(&tcon->ses->sesSem);
+				if(rc == 0)
+					atomic_inc(&tconInfoReconnectCount);
+
+				cFYI(1, ("reconnect tcon rc = %d", rc));
+				/* Removed call to reopen open files here - 
+					it is safer (and faster) to reopen files
+					one at a time as needed in read and write */
+
+				/* Check if handle based operation so we 
+					know whether we can continue or not without
+					returning to caller to reset file handle */
+				switch(smb_command) {
+					case SMB_COM_READ_ANDX:
+					case SMB_COM_WRITE_ANDX:
+					case SMB_COM_CLOSE:
+					case SMB_COM_FIND_CLOSE2:
+					case SMB_COM_LOCKING_ANDX: {
+						unload_nls(nls_codepage);
+						return -EAGAIN;
+					}
+				}
+			} else {
+				up(&tcon->ses->sesSem);
+			}
+			unload_nls(nls_codepage);
+
+		} else {
+			return -EIO;
+		}
+	}
+	if(rc)
+		return rc;
+
+	*request_buf = cifs_buf_get();
+	if (*request_buf == NULL) {
+		/* BB should we add a retry in here if not a writepage? */
+		return -ENOMEM;
+	}
+    /* Although the original thought was we needed the response buf for  */
+    /* potential retries of smb operations it turns out we can determine */
+    /* from the mid flags when the request buffer can be resent without  */
+    /* having to use a second distinct buffer for the response */
+	*response_buf = *request_buf; 
+
+	header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
+			wct /*wct */ );
+
+#ifdef CONFIG_CIFS_STATS
+        if(tcon != NULL) {
+                atomic_inc(&tcon->num_smbs_sent);
+        }
+#endif /* CONFIG_CIFS_STATS */
+	return rc;
+}
+
+static int validate_t2(struct smb_t2_rsp * pSMB) 
+{
+	int rc = -EINVAL;
+	int total_size;
+	char * pBCC;
+
+	/* check for plausible wct, bcc and t2 data and parm sizes */
+	/* check for parm and data offset going beyond end of smb */
+	if(pSMB->hdr.WordCount >= 10) {
+		if((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
+		   (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
+			/* check that bcc is at least as big as parms + data */
+			/* check that bcc is less than negotiated smb buffer */
+			total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
+			if(total_size < 512) {
+				total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount);
+				/* BCC le converted in SendReceive */
+				pBCC = (pSMB->hdr.WordCount * 2) + sizeof(struct smb_hdr) + 
+					(char *)pSMB;
+				if((total_size <= (*(u16 *)pBCC)) && 
+				   (total_size < 
+					CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
+					return 0;
+				}
+				
+			}
+		}
+	}
+	cifs_dump_mem("Invalid transact2 SMB: ",(char *)pSMB,
+		sizeof(struct smb_t2_rsp) + 16);
+	return rc;
+}
+int
+CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
+{
+	NEGOTIATE_REQ *pSMB;
+	NEGOTIATE_RSP *pSMBr;
+	int rc = 0;
+	int bytes_returned;
+	struct TCP_Server_Info * server;
+	u16 count;
+
+	if(ses->server)
+		server = ses->server;
+	else {
+		rc = -EIO;
+		return rc;
+	}
+	rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
+		      (void **) &pSMB, (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
+	if (extended_security)
+		pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
+
+	count = strlen(protocols[0].name) + 1;
+	strncpy(pSMB->DialectsArray, protocols[0].name, 30);	
+    /* null guaranteed to be at end of source and target buffers anyway */
+
+	pSMB->hdr.smb_buf_length += count;
+	pSMB->ByteCount = cpu_to_le16(count);
+
+	rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc == 0) {
+		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,*/
+		server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
+		/* probably no need to store and check maxvcs */
+		server->maxBuf =
+			min(le32_to_cpu(pSMBr->MaxBufferSize),
+			(__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
+		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(server->cryptKey, pSMBr->u.EncryptionKey,
+			       CIFS_CRYPTO_KEY_SIZE);
+		} else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
+			   && (pSMBr->EncryptionKeyLength == 0)) {
+			/* decode security blob */
+		} else
+			rc = -EIO;
+
+		/* BB might be helpful to save off the domain of server here */
+
+		if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) && 
+			(server->capabilities & CAP_EXTENDED_SECURITY)) {
+			count = pSMBr->ByteCount;
+			if (count < 16)
+				rc = -EIO;
+			else if (count == 16) {
+				server->secType = RawNTLMSSP;
+				if (server->socketUseCount.counter > 1) {
+					if (memcmp
+						(server->server_GUID,
+						pSMBr->u.extended_response.
+						GUID, 16) != 0) {
+						cFYI(1,
+							("UID of server does not match previous connection to same ip address"));
+						memcpy(server->
+							server_GUID,
+							pSMBr->u.
+							extended_response.
+							GUID, 16);
+					}
+				} else
+					memcpy(server->server_GUID,
+					       pSMBr->u.extended_response.
+					       GUID, 16);
+			} else {
+				rc = decode_negTokenInit(pSMBr->u.
+							 extended_response.
+							 SecurityBlob,
+							 count - 16,
+							 &server->secType);
+				if(rc == 1) {
+				/* BB Need to fill struct for sessetup here */
+					rc = -EOPNOTSUPP;
+				} else {
+					rc = -EINVAL;
+				}
+			}
+		} else
+			server->capabilities &= ~CAP_EXTENDED_SECURITY;
+		if(sign_CIFS_PDUs == FALSE) {        
+			if(server->secMode & SECMODE_SIGN_REQUIRED)
+				cERROR(1,
+				 ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
+			server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
+		} else if(sign_CIFS_PDUs == 1) {
+			if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
+				server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
+		}
+				
+	}
+	if (pSMB)
+		cifs_buf_release(pSMB);
+	return rc;
+}
+
+int
+CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
+{
+	struct smb_hdr *smb_buffer;
+	struct smb_hdr *smb_buffer_response; /* BB removeme BB */
+	int rc = 0;
+	int length;
+
+	cFYI(1, ("In tree disconnect"));
+	/*
+	 *  If last user of the connection and
+	 *  connection alive - disconnect it
+	 *  If this is the last connection on the server session disconnect it
+	 *  (and inside session disconnect we should check if tcp socket needs 
+	 *  to be freed and kernel thread woken up).
+	 */
+	if (tcon)
+		down(&tcon->tconSem);
+	else
+		return -EIO;
+
+	atomic_dec(&tcon->useCount);
+	if (atomic_read(&tcon->useCount) > 0) {
+		up(&tcon->tconSem);
+		return -EBUSY;
+	}
+
+	/* No need to return error on this operation if tid invalidated and 
+	closed on server already e.g. due to tcp session crashing */
+	if(tcon->tidStatus == CifsNeedReconnect) {
+		up(&tcon->tconSem);
+		return 0;  
+	}
+
+	if((tcon->ses == NULL) || (tcon->ses->server == NULL)) {    
+		up(&tcon->tconSem);
+		return -EIO;
+	}
+	rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon, (void **)&smb_buffer);
+	if (rc) {
+		up(&tcon->tconSem);
+		return rc;
+	} else {
+		smb_buffer_response = smb_buffer; /* BB removeme BB */
+    }
+	rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
+			 &length, 0);
+	if (rc)
+		cFYI(1, (" Tree disconnect failed %d", rc));
+
+	if (smb_buffer)
+		cifs_small_buf_release(smb_buffer);
+	up(&tcon->tconSem);
+
+	/* No need to return error on this operation if tid invalidated and 
+	closed on server already e.g. due to tcp session crashing */
+	if (rc == -EAGAIN)
+		rc = 0;
+
+	return rc;
+}
+
+int
+CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
+{
+	struct smb_hdr *smb_buffer_response;
+	LOGOFF_ANDX_REQ *pSMB;
+	int rc = 0;
+	int length;
+
+	cFYI(1, ("In SMBLogoff for session disconnect"));
+	if (ses)
+		down(&ses->sesSem);
+	else
+		return -EIO;
+
+	atomic_dec(&ses->inUse);
+	if (atomic_read(&ses->inUse) > 0) {
+		up(&ses->sesSem);
+		return -EBUSY;
+	}
+	rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
+	if (rc) {
+		up(&ses->sesSem);
+		return rc;
+	}
+
+	smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
+	
+	if(ses->server) {
+		if(ses->server->secMode & 
+		   (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+			pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+	}
+
+	pSMB->hdr.Uid = ses->Suid;
+
+	pSMB->AndXCommand = 0xFF;
+	rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
+			 smb_buffer_response, &length, 0);
+	if (ses->server) {
+		atomic_dec(&ses->server->socketUseCount);
+		if (atomic_read(&ses->server->socketUseCount) == 0) {
+			spin_lock(&GlobalMid_Lock);
+			ses->server->tcpStatus = CifsExiting;
+			spin_unlock(&GlobalMid_Lock);
+			rc = -ESHUTDOWN;
+		}
+	}
+	if (pSMB)
+		cifs_small_buf_release(pSMB);
+	up(&ses->sesSem);
+
+	/* if session dead then we do not need to do ulogoff,
+		since server closed smb session, no sense reporting 
+		error */
+	if (rc == -EAGAIN)
+		rc = 0;
+	return rc;
+}
+
+int
+CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
+	       const char *fileName, const struct nls_table *nls_codepage)
+{
+	DELETE_FILE_REQ *pSMB = NULL;
+	DELETE_FILE_RSP *pSMBr = NULL;
+	int rc = 0;
+	int bytes_returned;
+	int name_len;
+
+DelFileRetry:
+	rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+		name_len =
+		    cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName, PATH_MAX
+				  /* find define for this maxpathcomponent */
+				  , nls_codepage);
+		name_len++;	/* trailing null */
+		name_len *= 2;
+	} else {		/* BB improve the check for buffer overruns BB */
+		name_len = strnlen(fileName, PATH_MAX);
+		name_len++;	/* trailing null */
+		strncpy(pSMB->fileName, fileName, name_len);
+	}
+	pSMB->SearchAttributes =
+	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
+	pSMB->BufferFormat = 0x04;
+	pSMB->hdr.smb_buf_length += name_len + 1;
+	pSMB->ByteCount = cpu_to_le16(name_len + 1);
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cFYI(1, ("Error in RMFile = %d", rc));
+	} 
+#ifdef CONFIG_CIFS_STATS
+        else {
+		atomic_inc(&tcon->num_deletes);
+        }
+#endif
+
+	cifs_buf_release(pSMB);
+	if (rc == -EAGAIN)
+		goto DelFileRetry;
+
+	return rc;
+}
+
+int
+CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
+	     const char *dirName, const struct nls_table *nls_codepage)
+{
+	DELETE_DIRECTORY_REQ *pSMB = NULL;
+	DELETE_DIRECTORY_RSP *pSMBr = NULL;
+	int rc = 0;
+	int bytes_returned;
+	int name_len;
+
+	cFYI(1, ("In CIFSSMBRmDir"));
+RmDirRetry:
+	rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+		name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, dirName, PATH_MAX
+				/* find define for this maxpathcomponent */
+				, nls_codepage);
+		name_len++;	/* trailing null */
+		name_len *= 2;
+	} else {		/* BB improve the check for buffer overruns BB */
+		name_len = strnlen(dirName, PATH_MAX);
+		name_len++;	/* trailing null */
+		strncpy(pSMB->DirName, dirName, name_len);
+	}
+
+	pSMB->BufferFormat = 0x04;
+	pSMB->hdr.smb_buf_length += name_len + 1;
+	pSMB->ByteCount = cpu_to_le16(name_len + 1);
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cFYI(1, ("Error in RMDir = %d", rc));
+	}
+#ifdef CONFIG_CIFS_STATS
+        else {
+		atomic_inc(&tcon->num_rmdirs);
+        }
+#endif
+
+	cifs_buf_release(pSMB);
+	if (rc == -EAGAIN)
+		goto RmDirRetry;
+	return rc;
+}
+
+int
+CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
+	     const char *name, const struct nls_table *nls_codepage)
+{
+	int rc = 0;
+	CREATE_DIRECTORY_REQ *pSMB = NULL;
+	CREATE_DIRECTORY_RSP *pSMBr = NULL;
+	int bytes_returned;
+	int name_len;
+
+	cFYI(1, ("In CIFSSMBMkDir"));
+MkDirRetry:
+	rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+		name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, name, PATH_MAX
+					 /* find define for this maxpathcomponent */
+					 , nls_codepage);
+		name_len++;	/* trailing null */
+		name_len *= 2;
+	} else {		/* BB improve the check for buffer overruns BB */
+		name_len = strnlen(name, PATH_MAX);
+		name_len++;	/* trailing null */
+		strncpy(pSMB->DirName, name, name_len);
+	}
+
+	pSMB->BufferFormat = 0x04;
+	pSMB->hdr.smb_buf_length += name_len + 1;
+	pSMB->ByteCount = cpu_to_le16(name_len + 1);
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cFYI(1, ("Error in Mkdir = %d", rc));
+	}
+#ifdef CONFIG_CIFS_STATS
+        else {
+		atomic_inc(&tcon->num_mkdirs);
+        }
+#endif
+	cifs_buf_release(pSMB);
+	if (rc == -EAGAIN)
+		goto MkDirRetry;
+	return rc;
+}
+
+int
+CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
+	    const char *fileName, const int openDisposition,
+	    const int access_flags, const int create_options, __u16 * netfid,
+	    int *pOplock, FILE_ALL_INFO * pfile_info, 
+	    const struct nls_table *nls_codepage)
+{
+	int rc = -EACCES;
+	OPEN_REQ *pSMB = NULL;
+	OPEN_RSP *pSMBr = NULL;
+	int bytes_returned;
+	int name_len;
+	__u16 count;
+
+openRetry:
+	rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	pSMB->AndXCommand = 0xFF;	/* none */
+
+	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+		count = 1;	/* account for one byte pad to word boundary */
+		name_len =
+		    cifs_strtoUCS((wchar_t *) (pSMB->fileName + 1),
+				  fileName, PATH_MAX
+				  /* find define for this maxpathcomponent */
+				  , nls_codepage);
+		name_len++;	/* trailing null */
+		name_len *= 2;
+		pSMB->NameLength = cpu_to_le16(name_len);
+	} else {		/* BB improve the check for buffer overruns BB */
+		count = 0;	/* no pad */
+		name_len = strnlen(fileName, PATH_MAX);
+		name_len++;	/* trailing null */
+		pSMB->NameLength = cpu_to_le16(name_len);
+		strncpy(pSMB->fileName, fileName, name_len);
+	}
+	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 = cpu_to_le32(ATTR_NORMAL);
+	/* XP does not handle ATTR_POSIX_SEMANTICS */
+	/* but it helps speed up case sensitive checks for other
+	servers such as Samba */
+	if (tcon->ses->capabilities & CAP_UNIX)
+		pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
+
+	/* if ((omode & S_IWUGO) == 0)
+		pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
+	/*  Above line causes problems due to vfs splitting create into two
+		pieces - need to set mode after file created not while it is
+		being created */
+	pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
+	pSMB->CreateDisposition = cpu_to_le32(openDisposition);
+	pSMB->CreateOptions = cpu_to_le32(create_options);
+	pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);	/* BB ??*/
+	pSMB->SecurityFlags =
+	    SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
+
+	count += name_len;
+	pSMB->hdr.smb_buf_length += count;
+
+	pSMB->ByteCount = cpu_to_le16(count);
+	/* long_op set to 1 to allow for oplock break timeouts */
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
+	if (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 */
+		/* Let caller know file was created so we can set the mode. */
+		/* Do we care about the CreateAction in any other cases? */
+		if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
+			*pOplock |= CIFS_CREATE_ACTION; 
+		if(pfile_info) {
+		    memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
+			36 /* CreationTime to Attributes */);
+		    /* the file_info buf is endian converted by caller */
+		    pfile_info->AllocationSize = pSMBr->AllocationSize;
+		    pfile_info->EndOfFile = pSMBr->EndOfFile;
+		    pfile_info->NumberOfLinks = cpu_to_le32(1);
+		}
+
+#ifdef CONFIG_CIFS_STATS
+		atomic_inc(&tcon->num_opens);
+#endif
+	}
+	cifs_buf_release(pSMB);
+	if (rc == -EAGAIN)
+		goto openRetry;
+	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, struct cifsTconInfo *tcon,
+	    const int netfid, const unsigned int count,
+	    const __u64 lseek, unsigned int *nbytes, char **buf)
+{
+	int rc = -EACCES;
+	READ_REQ *pSMB = NULL;
+	READ_RSP *pSMBr = NULL;
+	char *pReadData = NULL;
+	int bytes_returned;
+
+	cFYI(1,("Reading %d bytes on fid %d",count,netfid));
+
+	*nbytes = 0;
+	rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	/* tcon and ses pointer are checked in smb_init */
+	if (tcon->ses->server == NULL)
+		return -ECONNABORTED;
+
+	pSMB->AndXCommand = 0xFF;	/* none */
+	pSMB->Fid = netfid;
+	pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
+	pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
+	pSMB->Remaining = 0;
+	pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
+	pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
+	pSMB->ByteCount = 0;  /* no need to do le conversion since it is 0 */
+
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cERROR(1, ("Send error in read = %d", rc));
+	} else {
+		int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
+		data_length = data_length << 16;
+		data_length += le16_to_cpu(pSMBr->DataLength);
+		*nbytes = data_length;
+
+		/*check that DataLength would not go beyond end of SMB */
+		if ((data_length > CIFSMaxBufSize) 
+				|| (data_length > count)) {
+			cFYI(1,("bad length %d for count %d",data_length,count));
+			rc = -EIO;
+			*nbytes = 0;
+		} else {
+			pReadData =
+			    (char *) (&pSMBr->hdr.Protocol) +
+			    le16_to_cpu(pSMBr->DataOffset);
+/*			if(rc = copy_to_user(buf, pReadData, data_length)) {
+				cERROR(1,("Faulting on read rc = %d",rc));
+				rc = -EFAULT;
+			}*/ /* can not use copy_to_user when using page cache*/
+			if(*buf)
+			    memcpy(*buf,pReadData,data_length);
+		}
+	}
+	if(*buf)
+		cifs_buf_release(pSMB);
+	else
+		*buf = (char *)pSMB;
+
+	/* Note: On -EAGAIN error only caller can retry on handle based calls 
+		since file handle passed in no longer valid */
+	return rc;
+}
+
+int
+CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
+	     const int netfid, const unsigned int count,
+	     const __u64 offset, unsigned int *nbytes, const char *buf,
+	     const char __user * ubuf, const int long_op)
+{
+	int rc = -EACCES;
+	WRITE_REQ *pSMB = NULL;
+	WRITE_RSP *pSMBr = NULL;
+	int bytes_returned;
+	__u32 bytes_sent;
+	__u16 byte_count;
+
+	/* cFYI(1,("write at %lld %d bytes",offset,count));*/
+	rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+	/* tcon and ses pointer are checked in smb_init */
+	if (tcon->ses->server == NULL)
+		return -ECONNABORTED;
+
+	pSMB->AndXCommand = 0xFF;	/* none */
+	pSMB->Fid = netfid;
+	pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
+	pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
+	pSMB->Reserved = 0xFFFFFFFF;
+	pSMB->WriteMode = 0;
+	pSMB->Remaining = 0;
+
+	/* Can increase buffer size if buffer is big enough in some cases - ie we 
+	can send more if LARGE_WRITE_X capability returned by the server and if
+	our buffer is big enough or if we convert to iovecs on socket writes
+	and eliminate the copy to the CIFS buffer */
+	if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
+		bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
+	} else {
+		bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
+			 & ~0xFF;
+	}
+
+	if (bytes_sent > count)
+		bytes_sent = count;
+	pSMB->DataOffset =
+	    cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
+	if(buf)
+	    memcpy(pSMB->Data,buf,bytes_sent);
+	else if(ubuf) {
+		if(copy_from_user(pSMB->Data,ubuf,bytes_sent)) {
+			cifs_buf_release(pSMB);
+			return -EFAULT;
+		}
+	} else {
+		/* No buffer */
+		cifs_buf_release(pSMB);
+		return -EINVAL;
+	}
+
+	byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */
+	pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
+	pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
+	pSMB->hdr.smb_buf_length += bytes_sent+1;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
+
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
+	if (rc) {
+		cFYI(1, ("Send error in write = %d", rc));
+		*nbytes = 0;
+	} else {
+		*nbytes = le16_to_cpu(pSMBr->CountHigh);
+		*nbytes = (*nbytes) << 16;
+		*nbytes += le16_to_cpu(pSMBr->Count);
+	}
+
+	cifs_buf_release(pSMB);
+
+	/* Note: On -EAGAIN error only caller can retry on handle based calls 
+		since file handle passed in no longer valid */
+
+	return rc;
+}
+
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
+	     const int netfid, const unsigned int count,
+	     const __u64 offset, unsigned int *nbytes, const char __user *buf,
+	     const int long_op)
+{
+	int rc = -EACCES;
+	WRITE_REQ *pSMB = NULL;
+	WRITE_RSP *pSMBr = NULL;
+	/*int bytes_returned;*/
+	unsigned bytes_sent;
+	__u16 byte_count;
+
+	rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB);
+    
+	if (rc)
+		return rc;
+	
+	pSMBr = (WRITE_RSP *)pSMB; /* BB removeme BB */
+
+	/* tcon and ses pointer are checked in smb_init */
+	if (tcon->ses->server == NULL)
+		return -ECONNABORTED;
+
+	pSMB->AndXCommand = 0xFF; /* none */
+	pSMB->Fid = netfid;
+	pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
+	pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
+	pSMB->Reserved = 0xFFFFFFFF;
+	pSMB->WriteMode = 0;
+	pSMB->Remaining = 0;
+	bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & ~0xFF;
+	if (bytes_sent > count)
+		bytes_sent = count;
+	pSMB->DataLengthHigh = 0;
+	pSMB->DataOffset =
+	    cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
+
+	byte_count = bytes_sent + 1 /* pad */ ;
+	pSMB->DataLengthLow = cpu_to_le16(bytes_sent);
+	pSMB->DataLengthHigh = 0;
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
+
+/*	rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, buf, buflen, &bytes_returned, long_op); */  /* BB fixme BB */
+	if (rc) {
+		cFYI(1, ("Send error in write2 (large write) = %d", rc));
+		*nbytes = 0;
+	} else
+		*nbytes = le16_to_cpu(pSMBr->Count);
+
+	cifs_small_buf_release(pSMB);
+
+	/* Note: On -EAGAIN error only caller can retry on handle based calls 
+		since file handle passed in no longer valid */
+
+	return rc;
+}
+#endif /* CIFS_EXPERIMENTAL */
+
+int
+CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
+	    const __u16 smb_file_id, const __u64 len,
+	    const __u64 offset, const __u32 numUnlock,
+	    const __u32 numLock, const __u8 lockType, const int waitFlag)
+{
+	int rc = 0;
+	LOCK_REQ *pSMB = NULL;
+	LOCK_RSP *pSMBr = NULL;
+	int bytes_returned;
+	int timeout = 0;
+	__u16 count;
+
+	cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
+	rc = smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
+		timeout = -1; /* no response expected */
+		pSMB->Timeout = 0;
+	} else if (waitFlag == TRUE) {
+		timeout = 3;  /* blocking operation, no timeout */
+		pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
+	} else {
+		pSMB->Timeout = 0;
+	}
+
+	pSMB->NumberOfLocks = cpu_to_le16(numLock);
+	pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
+	pSMB->LockType = lockType;
+	pSMB->AndXCommand = 0xFF;	/* none */
+	pSMB->Fid = smb_file_id; /* netfid stays le */
+
+	if((numLock != 0) || (numUnlock != 0)) {
+		pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
+		/* BB where to store pid high? */
+		pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
+		pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
+		pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
+		pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
+		count = sizeof(LOCKING_ANDX_RANGE);
+	} else {
+		/* oplock break */
+		count = 0;
+	}
+	pSMB->hdr.smb_buf_length += count;
+	pSMB->ByteCount = cpu_to_le16(count);
+
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
+
+	if (rc) {
+		cFYI(1, ("Send error in Lock = %d", rc));
+	}
+	cifs_buf_release(pSMB);
+
+	/* Note: On -EAGAIN error only caller can retry on handle based calls 
+	since file handle passed in no longer valid */
+	return rc;
+}
+
+int
+CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
+{
+	int rc = 0;
+	CLOSE_REQ *pSMB = NULL;
+	CLOSE_RSP *pSMBr = NULL;
+	int bytes_returned;
+	cFYI(1, ("In CIFSSMBClose"));
+
+/* do not retry on dead session on close */
+	rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
+	if(rc == -EAGAIN)
+		return 0;
+	if (rc)
+		return rc;
+
+	pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
+
+	pSMB->FileID = (__u16) smb_file_id;
+	pSMB->LastWriteTime = 0;
+	pSMB->ByteCount = 0;
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		if(rc!=-EINTR) {
+			/* EINTR is expected when user ctl-c to kill app */
+			cERROR(1, ("Send error in Close = %d", rc));
+		}
+	}
+
+	cifs_small_buf_release(pSMB);
+
+	/* Since session is dead, file will be closed on server already */
+	if(rc == -EAGAIN)
+		rc = 0;
+
+	return rc;
+}
+
+int
+CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
+	      const char *fromName, const char *toName,
+	      const struct nls_table *nls_codepage)
+{
+	int rc = 0;
+	RENAME_REQ *pSMB = NULL;
+	RENAME_RSP *pSMBr = NULL;
+	int bytes_returned;
+	int name_len, name_len2;
+	__u16 count;
+
+	cFYI(1, ("In CIFSSMBRename"));
+renameRetry:
+	rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	pSMB->BufferFormat = 0x04;
+	pSMB->SearchAttributes =
+	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
+			ATTR_DIRECTORY);
+
+	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+		name_len =
+		    cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, PATH_MAX
+				  /* find define for this maxpathcomponent */
+				  , nls_codepage);
+		name_len++;	/* trailing null */
+		name_len *= 2;
+		pSMB->OldFileName[name_len] = 0x04;	/* pad */
+	/* protocol requires ASCII signature byte on Unicode string */
+		pSMB->OldFileName[name_len + 1] = 0x00;
+		name_len2 =
+		    cifs_strtoUCS((wchar_t *) & pSMB->
+				  OldFileName[name_len + 2], toName, PATH_MAX,
+				  nls_codepage);
+		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, PATH_MAX);
+		name_len++;	/* trailing null */
+		strncpy(pSMB->OldFileName, fromName, name_len);
+		name_len2 = strnlen(toName, PATH_MAX);
+		name_len2++;	/* trailing null */
+		pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
+		strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
+		name_len2++;	/* trailing null */
+		name_len2++;	/* signature byte */
+	}
+
+	count = 1 /* 1st signature byte */  + name_len + name_len2;
+	pSMB->hdr.smb_buf_length += count;
+	pSMB->ByteCount = cpu_to_le16(count);
+
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cFYI(1, ("Send error in rename = %d", rc));
+	} 
+
+#ifdef CONFIG_CIFS_STATS
+	  else {
+		atomic_inc(&tcon->num_renames);
+	}
+#endif
+
+	cifs_buf_release(pSMB);
+
+	if (rc == -EAGAIN)
+		goto renameRetry;
+
+	return rc;
+}
+
+int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon, 
+		int netfid, char * target_name, const struct nls_table * nls_codepage) 
+{
+	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
+	struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
+	struct set_file_rename * rename_info;
+	char *data_offset;
+	char dummy_string[30];
+	int rc = 0;
+	int bytes_returned = 0;
+	int len_of_str;
+	__u16 params, param_offset, offset, count, byte_count;
+
+	cFYI(1, ("Rename to File by handle"));
+	rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
+			(void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	params = 6;
+	pSMB->MaxSetupCount = 0;
+	pSMB->Reserved = 0;
+	pSMB->Flags = 0;
+	pSMB->Timeout = 0;
+	pSMB->Reserved2 = 0;
+	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
+	offset = param_offset + params;
+
+	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
+	rename_info = (struct set_file_rename *) data_offset;
+	pSMB->MaxParameterCount = cpu_to_le16(2);
+	pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
+	pSMB->SetupCount = 1;
+	pSMB->Reserved3 = 0;
+	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
+	byte_count = 3 /* pad */  + params;
+	pSMB->ParameterCount = cpu_to_le16(params);
+	pSMB->TotalParameterCount = pSMB->ParameterCount;
+	pSMB->ParameterOffset = cpu_to_le16(param_offset);
+	pSMB->DataOffset = cpu_to_le16(offset);
+	/* construct random name ".cifs_tmp<inodenum><mid>" */
+	rename_info->overwrite = cpu_to_le32(1);
+	rename_info->root_fid  = 0;
+	/* unicode only call */
+	if(target_name == NULL) {
+		sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
+	        len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, dummy_string, 24, nls_codepage);
+	} else {
+		len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, target_name, PATH_MAX, nls_codepage);
+	}
+	rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
+	count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
+	byte_count += count;
+	pSMB->DataCount = cpu_to_le16(count);
+	pSMB->TotalDataCount = pSMB->DataCount;
+	pSMB->Fid = netfid;
+	pSMB->InformationLevel =
+		cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
+	pSMB->Reserved4 = 0;
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
+	rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
+                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cFYI(1,("Send error in Rename (by file handle) = %d", rc));
+	}
+#ifdef CONFIG_CIFS_STATS
+	  else {
+		atomic_inc(&pTcon->num_t2renames);
+	}
+#endif
+	cifs_buf_release(pSMB);
+
+	/* Note: On -EAGAIN error only caller can retry on handle based calls
+		since file handle passed in no longer valid */
+
+	return rc;
+}
+
+int
+CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName, 
+            const __u16 target_tid, const char *toName, const int flags,
+            const struct nls_table *nls_codepage)
+{
+	int rc = 0;
+	COPY_REQ *pSMB = NULL;
+	COPY_RSP *pSMBr = NULL;
+	int bytes_returned;
+	int name_len, name_len2;
+	__u16 count;
+
+	cFYI(1, ("In CIFSSMBCopy"));
+copyRetry:
+	rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
+			(void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	pSMB->BufferFormat = 0x04;
+	pSMB->Tid2 = target_tid;
+
+	pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
+
+	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+		name_len = cifs_strtoUCS((wchar_t *) pSMB->OldFileName, 
+				fromName, 
+				PATH_MAX /* find define for this maxpathcomponent */,
+				nls_codepage);
+		name_len++;     /* trailing null */
+		name_len *= 2;
+		pSMB->OldFileName[name_len] = 0x04;     /* pad */
+		/* protocol requires ASCII signature byte on Unicode string */
+		pSMB->OldFileName[name_len + 1] = 0x00;
+		name_len2 = cifs_strtoUCS((wchar_t *) & pSMB->
+				OldFileName[name_len + 2], toName, PATH_MAX,
+				nls_codepage);
+		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, PATH_MAX);
+		name_len++;     /* trailing null */
+		strncpy(pSMB->OldFileName, fromName, name_len);
+		name_len2 = strnlen(toName, PATH_MAX);
+		name_len2++;    /* trailing null */
+		pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
+		strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
+		name_len2++;    /* trailing null */
+		name_len2++;    /* signature byte */
+	}
+
+	count = 1 /* 1st signature byte */  + name_len + name_len2;
+	pSMB->hdr.smb_buf_length += count;
+	pSMB->ByteCount = cpu_to_le16(count);
+
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cFYI(1, ("Send error in copy = %d with %d files copied",
+			rc, le16_to_cpu(pSMBr->CopyCount)));
+	}
+	if (pSMB)
+		cifs_buf_release(pSMB);
+
+	if (rc == -EAGAIN)
+		goto copyRetry;
+
+	return rc;
+}
+
+int
+CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
+		      const char *fromName, const char *toName,
+		      const struct nls_table *nls_codepage)
+{
+	TRANSACTION2_SPI_REQ *pSMB = NULL;
+	TRANSACTION2_SPI_RSP *pSMBr = NULL;
+	char *data_offset;
+	int name_len;
+	int name_len_target;
+	int rc = 0;
+	int bytes_returned = 0;
+	__u16 params, param_offset, offset, byte_count;
+
+	cFYI(1, ("In Symlink Unix style"));
+createSymLinkRetry:
+	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+		name_len =
+		    cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, PATH_MAX
+				  /* find define for this maxpathcomponent */
+				  , nls_codepage);
+		name_len++;	/* trailing null */
+		name_len *= 2;
+
+	} else {		/* BB improve the check for buffer overruns BB */
+		name_len = strnlen(fromName, PATH_MAX);
+		name_len++;	/* trailing null */
+		strncpy(pSMB->FileName, fromName, name_len);
+	}
+	params = 6 + name_len;
+	pSMB->MaxSetupCount = 0;
+	pSMB->Reserved = 0;
+	pSMB->Flags = 0;
+	pSMB->Timeout = 0;
+	pSMB->Reserved2 = 0;
+	param_offset = offsetof(struct smb_com_transaction2_spi_req,
+                                     InformationLevel) - 4;
+	offset = param_offset + params;
+
+	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
+	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+		name_len_target =
+		    cifs_strtoUCS((wchar_t *) data_offset, toName, PATH_MAX
+				  /* find define for this maxpathcomponent */
+				  , nls_codepage);
+		name_len_target++;	/* trailing null */
+		name_len_target *= 2;
+	} else {		/* BB improve the check for buffer overruns BB */
+		name_len_target = strnlen(toName, PATH_MAX);
+		name_len_target++;	/* trailing null */
+		strncpy(data_offset, toName, name_len_target);
+	}
+
+	pSMB->MaxParameterCount = cpu_to_le16(2);
+	/* BB find exact max on data count below from sess */
+	pSMB->MaxDataCount = cpu_to_le16(1000);
+	pSMB->SetupCount = 1;
+	pSMB->Reserved3 = 0;
+	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
+	byte_count = 3 /* pad */  + params + name_len_target;
+	pSMB->DataCount = cpu_to_le16(name_len_target);
+	pSMB->ParameterCount = cpu_to_le16(params);
+	pSMB->TotalDataCount = pSMB->DataCount;
+	pSMB->TotalParameterCount = pSMB->ParameterCount;
+	pSMB->ParameterOffset = cpu_to_le16(param_offset);
+	pSMB->DataOffset = cpu_to_le16(offset);
+	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
+	pSMB->Reserved4 = 0;
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cFYI(1,
+		     ("Send error in SetPathInfo (create symlink) = %d",
+		      rc));
+	}
+
+	if (pSMB)
+		cifs_buf_release(pSMB);
+
+	if (rc == -EAGAIN)
+		goto createSymLinkRetry;
+
+	return rc;
+}
+
+int
+CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
+		       const char *fromName, const char *toName,
+		       const struct nls_table *nls_codepage)
+{
+	TRANSACTION2_SPI_REQ *pSMB = NULL;
+	TRANSACTION2_SPI_RSP *pSMBr = NULL;
+	char *data_offset;
+	int name_len;
+	int name_len_target;
+	int rc = 0;
+	int bytes_returned = 0;
+	__u16 params, param_offset, offset, byte_count;
+
+	cFYI(1, ("In Create Hard link Unix style"));
+createHardLinkRetry:
+	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+		name_len = cifs_strtoUCS((wchar_t *) pSMB->FileName, toName, PATH_MAX
+					 /* find define for this maxpathcomponent */
+					 , nls_codepage);
+		name_len++;	/* trailing null */
+		name_len *= 2;
+
+	} else {		/* BB improve the check for buffer overruns BB */
+		name_len = strnlen(toName, PATH_MAX);
+		name_len++;	/* trailing null */
+		strncpy(pSMB->FileName, toName, name_len);
+	}
+	params = 6 + name_len;
+	pSMB->MaxSetupCount = 0;
+	pSMB->Reserved = 0;
+	pSMB->Flags = 0;
+	pSMB->Timeout = 0;
+	pSMB->Reserved2 = 0;
+	param_offset = offsetof(struct smb_com_transaction2_spi_req,
+                                     InformationLevel) - 4;
+	offset = param_offset + params;
+
+	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
+	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+		name_len_target =
+		    cifs_strtoUCS((wchar_t *) data_offset, fromName, PATH_MAX
+				  /* find define for this maxpathcomponent */
+				  , nls_codepage);
+		name_len_target++;	/* trailing null */
+		name_len_target *= 2;
+	} else {		/* BB improve the check for buffer overruns BB */
+		name_len_target = strnlen(fromName, PATH_MAX);
+		name_len_target++;	/* trailing null */
+		strncpy(data_offset, fromName, name_len_target);
+	}
+
+	pSMB->MaxParameterCount = cpu_to_le16(2);
+	/* BB find exact max on data count below from sess*/
+	pSMB->MaxDataCount = cpu_to_le16(1000);
+	pSMB->SetupCount = 1;
+	pSMB->Reserved3 = 0;
+	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
+	byte_count = 3 /* pad */  + params + name_len_target;
+	pSMB->ParameterCount = cpu_to_le16(params);
+	pSMB->TotalParameterCount = pSMB->ParameterCount;
+	pSMB->DataCount = cpu_to_le16(name_len_target);
+	pSMB->TotalDataCount = pSMB->DataCount;
+	pSMB->ParameterOffset = cpu_to_le16(param_offset);
+	pSMB->DataOffset = cpu_to_le16(offset);
+	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
+	pSMB->Reserved4 = 0;
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
+	}
+
+	cifs_buf_release(pSMB);
+	if (rc == -EAGAIN)
+		goto createHardLinkRetry;
+
+	return rc;
+}
+
+int
+CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
+		   const char *fromName, const char *toName,
+		   const struct nls_table *nls_codepage)
+{
+	int rc = 0;
+	NT_RENAME_REQ *pSMB = NULL;
+	RENAME_RSP *pSMBr = NULL;
+	int bytes_returned;
+	int name_len, name_len2;
+	__u16 count;
+
+	cFYI(1, ("In CIFSCreateHardLink"));
+winCreateHardLinkRetry:
+
+	rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	pSMB->SearchAttributes =
+	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
+			ATTR_DIRECTORY);
+	pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
+	pSMB->ClusterCount = 0;
+
+	pSMB->BufferFormat = 0x04;
+
+	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+		name_len =
+		    cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, PATH_MAX
+				  /* find define for this maxpathcomponent */
+				  , nls_codepage);
+		name_len++;	/* trailing null */
+		name_len *= 2;
+		pSMB->OldFileName[name_len] = 0;	/* pad */
+		pSMB->OldFileName[name_len + 1] = 0x04; 
+		name_len2 =
+		    cifs_strtoUCS((wchar_t *) & pSMB->
+				  OldFileName[name_len + 2], toName, PATH_MAX,
+				  nls_codepage);
+		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, PATH_MAX);
+		name_len++;	/* trailing null */
+		strncpy(pSMB->OldFileName, fromName, name_len);
+		name_len2 = strnlen(toName, PATH_MAX);
+		name_len2++;	/* trailing null */
+		pSMB->OldFileName[name_len] = 0x04;	/* 2nd buffer format */
+		strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
+		name_len2++;	/* trailing null */
+		name_len2++;	/* signature byte */
+	}
+
+	count = 1 /* string type byte */  + name_len + name_len2;
+	pSMB->hdr.smb_buf_length += count;
+	pSMB->ByteCount = cpu_to_le16(count);
+
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
+	}
+	cifs_buf_release(pSMB);
+	if (rc == -EAGAIN)
+		goto winCreateHardLinkRetry;
+
+	return rc;
+}
+
+int
+CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
+			const unsigned char *searchName,
+			char *symlinkinfo, const int buflen,
+			const struct nls_table *nls_codepage)
+{
+/* SMB_QUERY_FILE_UNIX_LINK */
+	TRANSACTION2_QPI_REQ *pSMB = NULL;
+	TRANSACTION2_QPI_RSP *pSMBr = NULL;
+	int rc = 0;
+	int bytes_returned;
+	int name_len;
+	__u16 params, byte_count;
+
+	cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
+
+querySymLinkRetry:
+	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+		name_len =
+		    cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
+				  /* find define for this maxpathcomponent */
+				  , nls_codepage);
+		name_len++;	/* trailing null */
+		name_len *= 2;
+	} else {		/* BB improve the check for buffer overruns BB */
+		name_len = strnlen(searchName, PATH_MAX);
+		name_len++;	/* trailing null */
+		strncpy(pSMB->FileName, searchName, name_len);
+	}
+
+	params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
+	pSMB->TotalDataCount = 0;
+	pSMB->MaxParameterCount = cpu_to_le16(2);
+	/* BB find exact max data count below from sess structure BB */
+	pSMB->MaxDataCount = cpu_to_le16(4000);
+	pSMB->MaxSetupCount = 0;
+	pSMB->Reserved = 0;
+	pSMB->Flags = 0;
+	pSMB->Timeout = 0;
+	pSMB->Reserved2 = 0;
+	pSMB->ParameterOffset = cpu_to_le16(offsetof(
+        struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
+	pSMB->DataCount = 0;
+	pSMB->DataOffset = 0;
+	pSMB->SetupCount = 1;
+	pSMB->Reserved3 = 0;
+	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
+	byte_count = params + 1 /* pad */ ;
+	pSMB->TotalParameterCount = cpu_to_le16(params);
+	pSMB->ParameterCount = pSMB->TotalParameterCount;
+	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
+	pSMB->Reserved4 = 0;
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
+
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
+	} else {
+		/* decode response */
+
+		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+		if (rc || (pSMBr->ByteCount < 2))
+		/* BB also check enough total bytes returned */
+			rc = -EIO;	/* bad smb */
+		else {
+			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+			__u16 count = le16_to_cpu(pSMBr->t2.DataCount);
+
+			if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
+				name_len = UniStrnlen((wchar_t *) ((char *)
+					&pSMBr->hdr.Protocol +data_offset),
+					min_t(const int, buflen,count) / 2);
+				cifs_strfromUCS_le(symlinkinfo,
+					(wchar_t *) ((char *)&pSMBr->hdr.Protocol +
+						data_offset),
+					name_len, nls_codepage);
+			} else {
+				strncpy(symlinkinfo,
+					(char *) &pSMBr->hdr.Protocol + 
+						data_offset,
+					min_t(const int, buflen, count));
+			}
+			symlinkinfo[buflen] = 0;
+	/* just in case so calling code does not go off the end of buffer */
+		}
+	}
+	cifs_buf_release(pSMB);
+	if (rc == -EAGAIN)
+		goto querySymLinkRetry;
+	return rc;
+}
+
+int
+CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
+			const unsigned char *searchName,
+			char *symlinkinfo, const int buflen,__u16 fid,
+			const struct nls_table *nls_codepage)
+{
+	int rc = 0;
+	int bytes_returned;
+	int name_len;
+	struct smb_com_transaction_ioctl_req * pSMB;
+	struct smb_com_transaction_ioctl_rsp * pSMBr;
+
+	cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
+	rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	pSMB->TotalParameterCount = 0 ;
+	pSMB->TotalDataCount = 0;
+	pSMB->MaxParameterCount = cpu_to_le32(2);
+	/* BB find exact data count max from sess structure BB */
+	pSMB->MaxDataCount = cpu_to_le32(4000);
+	pSMB->MaxSetupCount = 4;
+	pSMB->Reserved = 0;
+	pSMB->ParameterOffset = 0;
+	pSMB->DataCount = 0;
+	pSMB->DataOffset = 0;
+	pSMB->SetupCount = 4;
+	pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
+	pSMB->ParameterCount = pSMB->TotalParameterCount;
+	pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
+	pSMB->IsFsctl = 1; /* FSCTL */
+	pSMB->IsRootFlag = 0;
+	pSMB->Fid = fid; /* file handle always le */
+	pSMB->ByteCount = 0;
+
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
+	} else {		/* decode response */
+		__u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
+		__u32 data_count = le32_to_cpu(pSMBr->DataCount);
+		if ((pSMBr->ByteCount < 2) || (data_offset > 512))
+		/* BB also check enough total bytes returned */
+			rc = -EIO;	/* bad smb */
+		else {
+			if(data_count && (data_count < 2048)) {
+				char * end_of_smb = pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
+
+				struct reparse_data * reparse_buf = (struct reparse_data *)
+					((char *)&pSMBr->hdr.Protocol + data_offset);
+				if((char*)reparse_buf >= end_of_smb) {
+					rc = -EIO;
+					goto qreparse_out;
+				}
+				if((reparse_buf->LinkNamesBuf + 
+					reparse_buf->TargetNameOffset +
+					reparse_buf->TargetNameLen) >
+						end_of_smb) {
+					cFYI(1,("reparse buf extended beyond SMB"));
+					rc = -EIO;
+					goto qreparse_out;
+				}
+				
+				if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
+					name_len = UniStrnlen((wchar_t *)
+							(reparse_buf->LinkNamesBuf + 
+							reparse_buf->TargetNameOffset),
+							min(buflen/2, reparse_buf->TargetNameLen / 2)); 
+					cifs_strfromUCS_le(symlinkinfo,
+						(wchar_t *) (reparse_buf->LinkNamesBuf + 
+						reparse_buf->TargetNameOffset),
+						name_len, nls_codepage);
+				} else { /* ASCII names */
+					strncpy(symlinkinfo,reparse_buf->LinkNamesBuf + 
+						reparse_buf->TargetNameOffset, 
+						min_t(const int, buflen, reparse_buf->TargetNameLen));
+				}
+			} else {
+				rc = -EIO;
+				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,("readlink result - %s ",symlinkinfo));
+		}
+	}
+qreparse_out:
+	if (pSMB)
+		cifs_buf_release(pSMB);
+
+	/* Note: On -EAGAIN error only caller can retry on handle based calls
+		since file handle passed in no longer valid */
+
+	return rc;
+}
+
+#ifdef CONFIG_CIFS_POSIX
+
+/*Convert an Access Control Entry from wire format to local POSIX xattr format*/
+static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
+{
+	/* u8 cifs fields do not need le conversion */
+	ace->e_perm = (__u16)cifs_ace->cifs_e_perm; 
+	ace->e_tag  = (__u16)cifs_ace->cifs_e_tag;
+	ace->e_id   = (__u32)le64_to_cpu(cifs_ace->cifs_uid);
+	/* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
+
+	return;
+}
+
+/* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
+static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,const int acl_type,const int size_of_data_area)
+{
+	int size =  0;
+	int i;
+	__u16 count;
+	struct cifs_posix_ace * pACE;
+	struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)src;
+	posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)trgt;
+
+	if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
+		return -EOPNOTSUPP;
+
+	if(acl_type & ACL_TYPE_ACCESS) {
+		count = le16_to_cpu(cifs_acl->access_entry_count);
+		pACE = &cifs_acl->ace_array[0];
+		size = sizeof(struct cifs_posix_acl);
+		size += sizeof(struct cifs_posix_ace) * count;
+		/* check if we would go beyond end of SMB */
+		if(size_of_data_area < size) {
+			cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area,size));
+			return -EINVAL;
+		}
+	} else if(acl_type & ACL_TYPE_DEFAULT) {
+		count = le16_to_cpu(cifs_acl->access_entry_count);
+		size = sizeof(struct cifs_posix_acl);
+		size += sizeof(struct cifs_posix_ace) * count;
+/* skip past access ACEs to get to default ACEs */
+		pACE = &cifs_acl->ace_array[count];
+		count = le16_to_cpu(cifs_acl->default_entry_count);
+		size += sizeof(struct cifs_posix_ace) * count;
+		/* check if we would go beyond end of SMB */
+		if(size_of_data_area < size)
+			return -EINVAL;
+	} else {
+		/* illegal type */
+		return -EINVAL;
+	}
+
+	size = posix_acl_xattr_size(count);
+	if((buflen == 0) || (local_acl == NULL)) {
+		/* used to query ACL EA size */				
+	} else if(size > buflen) {
+		return -ERANGE;
+	} else /* buffer big enough */ {
+		local_acl->a_version = POSIX_ACL_XATTR_VERSION;
+		for(i = 0;i < count ;i++) {
+			cifs_convert_ace(&local_acl->a_entries[i],pACE);
+			pACE ++;
+		}
+	}
+	return size;
+}
+
+static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
+			const posix_acl_xattr_entry * local_ace)
+{
+	__u16 rc = 0; /* 0 = ACL converted ok */
+
+	cifs_ace->cifs_e_perm = (__u8)cpu_to_le16(local_ace->e_perm);
+	cifs_ace->cifs_e_tag =  (__u8)cpu_to_le16(local_ace->e_tag);
+	/* BB is there a better way to handle the large uid? */
+	if(local_ace->e_id == -1) {
+	/* Probably no need to le convert -1 on any arch but can not hurt */
+		cifs_ace->cifs_uid = cpu_to_le64(-1);
+	} else 
+		cifs_ace->cifs_uid = (__u64)cpu_to_le32(local_ace->e_id);
+        /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
+	return rc;
+}
+
+/* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
+static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
+		const int acl_type)
+{
+	__u16 rc = 0;
+        struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)parm_data;
+        posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)pACL;
+	int count;
+	int i;
+
+	if((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
+		return 0;
+
+	count = posix_acl_xattr_count((size_t)buflen);
+	cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
+		count,buflen,local_acl->a_version));
+	if(local_acl->a_version != 2) {
+		cFYI(1,("unknown POSIX ACL version %d",local_acl->a_version));
+		return 0;
+	}
+	cifs_acl->version = cpu_to_le16(1);
+	if(acl_type == ACL_TYPE_ACCESS) 
+		cifs_acl->access_entry_count = count;
+	else if(acl_type == ACL_TYPE_DEFAULT)
+		cifs_acl->default_entry_count = count;
+	else {
+		cFYI(1,("unknown ACL type %d",acl_type));
+		return 0;
+	}
+	for(i=0;i<count;i++) {
+		rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
+					&local_acl->a_entries[i]);
+		if(rc != 0) {
+			/* ACE not converted */
+			break;
+		}
+	}
+	if(rc == 0) {
+		rc = (__u16)(count * sizeof(struct cifs_posix_ace));
+		rc += sizeof(struct cifs_posix_acl);
+		/* BB add check to make sure ACL does not overflow SMB */
+	}
+	return rc;
+}
+
+int
+CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
+                        const unsigned char *searchName,
+                        char *acl_inf, const int buflen, const int acl_type,
+                        const struct nls_table *nls_codepage)
+{
+/* SMB_QUERY_POSIX_ACL */
+	TRANSACTION2_QPI_REQ *pSMB = NULL;
+	TRANSACTION2_QPI_RSP *pSMBr = NULL;
+	int rc = 0;
+	int bytes_returned;
+	int name_len;
+	__u16 params, byte_count;
+                                                                                                                                             
+	cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
+
+queryAclRetry:
+	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+		(void **) &pSMBr);
+	if (rc)
+		return rc;
+                                                                                                                                             
+	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+		name_len =
+			cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
+				, nls_codepage);
+		name_len++;     /* trailing null */
+		name_len *= 2;
+		pSMB->FileName[name_len] = 0;
+		pSMB->FileName[name_len+1] = 0;
+	} else {                /* BB improve the check for buffer overruns BB */
+		name_len = strnlen(searchName, PATH_MAX);
+		name_len++;     /* trailing null */
+		strncpy(pSMB->FileName, searchName, name_len);
+	}
+
+	params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
+	pSMB->TotalDataCount = 0;
+	pSMB->MaxParameterCount = cpu_to_le16(2);
+        /* BB find exact max data count below from sess structure BB */
+	pSMB->MaxDataCount = cpu_to_le16(4000);
+	pSMB->MaxSetupCount = 0;
+	pSMB->Reserved = 0;
+	pSMB->Flags = 0;
+	pSMB->Timeout = 0;
+	pSMB->Reserved2 = 0;
+	pSMB->ParameterOffset = cpu_to_le16(
+		offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
+	pSMB->DataCount = 0;
+	pSMB->DataOffset = 0;
+	pSMB->SetupCount = 1;
+	pSMB->Reserved3 = 0;
+	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
+	byte_count = params + 1 /* pad */ ;
+	pSMB->TotalParameterCount = cpu_to_le16(params);
+	pSMB->ParameterCount = pSMB->TotalParameterCount;
+	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
+	pSMB->Reserved4 = 0;
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
+
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
+	} else {
+		/* decode response */
+ 
+		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+		if (rc || (pSMBr->ByteCount < 2))
+		/* BB also check enough total bytes returned */
+			rc = -EIO;      /* bad smb */
+		else {
+			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+			__u16 count = le16_to_cpu(pSMBr->t2.DataCount);
+			rc = cifs_copy_posix_acl(acl_inf,
+				(char *)&pSMBr->hdr.Protocol+data_offset,
+				buflen,acl_type,count);
+		}
+	}
+	cifs_buf_release(pSMB);
+	if (rc == -EAGAIN)
+		goto queryAclRetry;
+	return rc;
+}
+
+int
+CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
+                        const unsigned char *fileName,
+                        const char *local_acl, const int buflen, const int acl_type,
+                        const struct nls_table *nls_codepage)
+{
+	struct smb_com_transaction2_spi_req *pSMB = NULL;
+	struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
+	char *parm_data;
+	int name_len;
+	int rc = 0;
+	int bytes_returned = 0;
+	__u16 params, byte_count, data_count, param_offset, offset;
+
+	cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
+setAclRetry:
+	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+                      (void **) &pSMBr);
+	if (rc)
+		return rc;
+	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+		name_len =
+			cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
+				, nls_codepage);
+		name_len++;     /* trailing null */
+		name_len *= 2;
+	} else {                /* BB improve the check for buffer overruns BB */
+		name_len = strnlen(fileName, PATH_MAX);
+		name_len++;     /* trailing null */
+		strncpy(pSMB->FileName, fileName, name_len);
+	}
+	params = 6 + name_len;
+	pSMB->MaxParameterCount = cpu_to_le16(2);
+	pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
+	pSMB->MaxSetupCount = 0;
+	pSMB->Reserved = 0;
+	pSMB->Flags = 0;
+	pSMB->Timeout = 0;
+	pSMB->Reserved2 = 0;
+	param_offset = offsetof(struct smb_com_transaction2_spi_req,
+                                     InformationLevel) - 4;
+	offset = param_offset + params;
+	parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
+	pSMB->ParameterOffset = cpu_to_le16(param_offset);
+
+	/* convert to on the wire format for POSIX ACL */
+	data_count = ACL_to_cifs_posix(parm_data,local_acl,buflen,acl_type);
+
+	if(data_count == 0) {
+		rc = -EOPNOTSUPP;
+		goto setACLerrorExit;
+	}
+	pSMB->DataOffset = cpu_to_le16(offset);
+	pSMB->SetupCount = 1;
+	pSMB->Reserved3 = 0;
+	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
+	pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
+	byte_count = 3 /* pad */  + params + data_count;
+	pSMB->DataCount = cpu_to_le16(data_count);
+	pSMB->TotalDataCount = pSMB->DataCount;
+	pSMB->ParameterCount = cpu_to_le16(params);
+	pSMB->TotalParameterCount = pSMB->ParameterCount;
+	pSMB->Reserved4 = 0;
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cFYI(1, ("Set POSIX ACL returned %d", rc));
+	}
+
+setACLerrorExit:
+	cifs_buf_release(pSMB);
+	if (rc == -EAGAIN)
+		goto setAclRetry;
+	return rc;
+}
+
+#endif
+
+int
+CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
+		 const unsigned char *searchName,
+		 FILE_ALL_INFO * pFindData,
+		 const struct nls_table *nls_codepage)
+{
+/* level 263 SMB_QUERY_FILE_ALL_INFO */
+	TRANSACTION2_QPI_REQ *pSMB = NULL;
+	TRANSACTION2_QPI_RSP *pSMBr = NULL;
+	int rc = 0;
+	int bytes_returned;
+	int name_len;
+	__u16 params, byte_count;
+
+/* cFYI(1, ("In QPathInfo path %s", searchName)); */
+QPathInfoRetry:
+	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+		name_len =
+		    cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
+				  /* find define for this maxpathcomponent */
+				  , nls_codepage);
+		name_len++;	/* trailing null */
+		name_len *= 2;
+	} else {		/* BB improve the check for buffer overruns BB */
+		name_len = strnlen(searchName, PATH_MAX);
+		name_len++;	/* trailing null */
+		strncpy(pSMB->FileName, searchName, name_len);
+	}
+
+	params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
+	pSMB->TotalDataCount = 0;
+	pSMB->MaxParameterCount = cpu_to_le16(2);
+	pSMB->MaxDataCount = cpu_to_le16(4000);	/* BB find exact max SMB PDU from sess structure BB */
+	pSMB->MaxSetupCount = 0;
+	pSMB->Reserved = 0;
+	pSMB->Flags = 0;
+	pSMB->Timeout = 0;
+	pSMB->Reserved2 = 0;
+	pSMB->ParameterOffset = cpu_to_le16(offsetof(
+        struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
+	pSMB->DataCount = 0;
+	pSMB->DataOffset = 0;
+	pSMB->SetupCount = 1;
+	pSMB->Reserved3 = 0;
+	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
+	byte_count = params + 1 /* pad */ ;
+	pSMB->TotalParameterCount = cpu_to_le16(params);
+	pSMB->ParameterCount = pSMB->TotalParameterCount;
+	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
+	pSMB->Reserved4 = 0;
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
+
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cFYI(1, ("Send error in QPathInfo = %d", rc));
+	} else {		/* decode response */
+		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+		if (rc || (pSMBr->ByteCount < 40)) 
+			rc = -EIO;	/* bad smb */
+		else if (pFindData){
+			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+			memcpy((char *) pFindData,
+			       (char *) &pSMBr->hdr.Protocol +
+			       data_offset, sizeof (FILE_ALL_INFO));
+		} else
+		    rc = -ENOMEM;
+	}
+	cifs_buf_release(pSMB);
+	if (rc == -EAGAIN)
+		goto QPathInfoRetry;
+
+	return rc;
+}
+
+int
+CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
+		     const unsigned char *searchName,
+		     FILE_UNIX_BASIC_INFO * pFindData,
+		     const struct nls_table *nls_codepage)
+{
+/* SMB_QUERY_FILE_UNIX_BASIC */
+	TRANSACTION2_QPI_REQ *pSMB = NULL;
+	TRANSACTION2_QPI_RSP *pSMBr = NULL;
+	int rc = 0;
+	int bytes_returned = 0;
+	int name_len;
+	__u16 params, byte_count;
+
+	cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
+UnixQPathInfoRetry:
+	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+		name_len =
+		    cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
+				  /* find define for this maxpathcomponent */
+				  , nls_codepage);
+		name_len++;	/* trailing null */
+		name_len *= 2;
+	} else {		/* BB improve the check for buffer overruns BB */
+		name_len = strnlen(searchName, PATH_MAX);
+		name_len++;	/* trailing null */
+		strncpy(pSMB->FileName, searchName, name_len);
+	}
+
+	params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
+	pSMB->TotalDataCount = 0;
+	pSMB->MaxParameterCount = cpu_to_le16(2);
+	/* BB find exact max SMB PDU from sess structure BB */
+	pSMB->MaxDataCount = cpu_to_le16(4000); 
+	pSMB->MaxSetupCount = 0;
+	pSMB->Reserved = 0;
+	pSMB->Flags = 0;
+	pSMB->Timeout = 0;
+	pSMB->Reserved2 = 0;
+	pSMB->ParameterOffset = cpu_to_le16(offsetof(
+        struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
+	pSMB->DataCount = 0;
+	pSMB->DataOffset = 0;
+	pSMB->SetupCount = 1;
+	pSMB->Reserved3 = 0;
+	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
+	byte_count = params + 1 /* pad */ ;
+	pSMB->TotalParameterCount = cpu_to_le16(params);
+	pSMB->ParameterCount = pSMB->TotalParameterCount;
+	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
+	pSMB->Reserved4 = 0;
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
+
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cFYI(1, ("Send error in QPathInfo = %d", rc));
+	} else {		/* decode response */
+		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+		if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
+			rc = -EIO;	/* bad smb */
+		} else {
+			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+			memcpy((char *) pFindData,
+			       (char *) &pSMBr->hdr.Protocol +
+			       data_offset,
+			       sizeof (FILE_UNIX_BASIC_INFO));
+		}
+	}
+	cifs_buf_release(pSMB);
+	if (rc == -EAGAIN)
+		goto UnixQPathInfoRetry;
+
+	return rc;
+}
+
+#if 0  /* function unused at present */
+int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
+	       const char *searchName, FILE_ALL_INFO * findData,
+	       const struct nls_table *nls_codepage)
+{
+/* level 257 SMB_ */
+	TRANSACTION2_FFIRST_REQ *pSMB = NULL;
+	TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
+	int rc = 0;
+	int bytes_returned;
+	int name_len;
+	__u16 params, byte_count;
+
+	cFYI(1, ("In FindUnique"));
+findUniqueRetry:
+	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+		name_len =
+		    cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
+				  /* find define for this maxpathcomponent */
+				  , nls_codepage);
+		name_len++;	/* trailing null */
+		name_len *= 2;
+	} else {		/* BB improve the check for buffer overruns BB */
+		name_len = strnlen(searchName, PATH_MAX);
+		name_len++;	/* trailing null */
+		strncpy(pSMB->FileName, searchName, name_len);
+	}
+
+	params = 12 + name_len /* includes null */ ;
+	pSMB->TotalDataCount = 0;	/* no EAs */
+	pSMB->MaxParameterCount = cpu_to_le16(2);
+	pSMB->MaxDataCount = cpu_to_le16(4000);	/* BB find exact max SMB PDU from sess structure BB */
+	pSMB->MaxSetupCount = 0;
+	pSMB->Reserved = 0;
+	pSMB->Flags = 0;
+	pSMB->Timeout = 0;
+	pSMB->Reserved2 = 0;
+	pSMB->ParameterOffset = cpu_to_le16(
+         offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
+	pSMB->DataCount = 0;
+	pSMB->DataOffset = 0;
+	pSMB->SetupCount = 1;	/* one byte, no need to le convert */
+	pSMB->Reserved3 = 0;
+	pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
+	byte_count = params + 1 /* pad */ ;
+	pSMB->TotalParameterCount = cpu_to_le16(params);
+	pSMB->ParameterCount = pSMB->TotalParameterCount;
+	pSMB->SearchAttributes =
+	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
+			ATTR_DIRECTORY);
+	pSMB->SearchCount = cpu_to_le16(16);	/* BB increase */
+	pSMB->SearchFlags = cpu_to_le16(1);
+	pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
+	pSMB->SearchStorageType = 0;	/* BB what should we set this to? BB */
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
+
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+
+	if (rc) {
+		cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
+	} else {		/* decode response */
+
+		/* BB fill in */
+	}
+
+	cifs_buf_release(pSMB);
+	if (rc == -EAGAIN)
+		goto findUniqueRetry;
+
+	return rc;
+}
+#endif /* end unused (temporarily) function */
+
+/* xid, tcon, searchName and codepage are input parms, rest are returned */
+int
+CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
+	      const char *searchName, 
+	      const struct nls_table *nls_codepage,
+	      __u16 *	pnetfid,
+	      struct cifs_search_info * psrch_inf)
+{
+/* level 257 SMB_ */
+	TRANSACTION2_FFIRST_REQ *pSMB = NULL;
+	TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
+	T2_FFIRST_RSP_PARMS * parms;
+	int rc = 0;
+	int bytes_returned = 0;
+	int name_len;
+	__u16 params, byte_count;
+
+	cFYI(1, ("In FindFirst"));
+
+findFirstRetry:
+	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+		name_len =
+		    cifs_strtoUCS((wchar_t *) pSMB->FileName,searchName,
+				 PATH_MAX, nls_codepage);
+		name_len++;	/* trailing null */
+		name_len *= 2;
+		pSMB->FileName[name_len] = 0; /* null terminate just in case */
+		pSMB->FileName[name_len+1] = 0;
+	} else {	/* BB add check for overrun of SMB buf BB */
+		name_len = strnlen(searchName, PATH_MAX);
+		name_len++;	/* trailing null */
+/* BB fix here and in unicode clause above ie
+		if(name_len > buffersize-header)
+			free buffer exit; BB */
+		strncpy(pSMB->FileName, searchName, name_len);
+		pSMB->FileName[name_len] = 0; /* just in case */
+	}
+
+	params = 12 + name_len /* includes null */ ;
+	pSMB->TotalDataCount = 0;	/* no EAs */
+	pSMB->MaxParameterCount = cpu_to_le16(10);
+	pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
+					  MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
+	pSMB->MaxSetupCount = 0;
+	pSMB->Reserved = 0;
+	pSMB->Flags = 0;
+	pSMB->Timeout = 0;
+	pSMB->Reserved2 = 0;
+	byte_count = params + 1 /* pad */ ;
+	pSMB->TotalParameterCount = cpu_to_le16(params);
+	pSMB->ParameterCount = pSMB->TotalParameterCount;
+	pSMB->ParameterOffset = cpu_to_le16(
+	  offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
+	pSMB->DataCount = 0;
+	pSMB->DataOffset = 0;
+	pSMB->SetupCount = 1;	/* one byte, no need to make endian neutral */
+	pSMB->Reserved3 = 0;
+	pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
+	pSMB->SearchAttributes =
+	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
+			ATTR_DIRECTORY);
+	pSMB->SearchCount= cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
+	pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | 
+		CIFS_SEARCH_RETURN_RESUME);
+	pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
+
+	/* BB what should we set StorageType to? Does it matter? BB */
+	pSMB->SearchStorageType = 0;
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
+
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+
+	if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
+		/* BB Add code to handle unsupported level rc */
+		cFYI(1, ("Error in FindFirst = %d", rc));
+
+		if (pSMB)
+			cifs_buf_release(pSMB);
+
+		/* BB eventually could optimize out free and realloc of buf */
+		/*    for this case */
+		if (rc == -EAGAIN)
+			goto findFirstRetry;
+	} else { /* decode response */
+		/* BB remember to free buffer if error BB */
+		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+		if(rc == 0) {
+			if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
+				psrch_inf->unicode = TRUE;
+			else
+				psrch_inf->unicode = FALSE;
+
+			psrch_inf->ntwrk_buf_start = (char *)pSMBr;
+			psrch_inf->srch_entries_start = 
+				(char *) &pSMBr->hdr.Protocol + 
+					le16_to_cpu(pSMBr->t2.DataOffset);
+
+			parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
+			       le16_to_cpu(pSMBr->t2.ParameterOffset));
+
+			if(parms->EndofSearch)
+				psrch_inf->endOfSearch = TRUE;
+			else
+				psrch_inf->endOfSearch = FALSE;
+
+			psrch_inf->entries_in_buffer  = le16_to_cpu(parms->SearchCount);
+			psrch_inf->index_of_last_entry = 
+				psrch_inf->entries_in_buffer;
+/*cFYI(1,("entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry));  */
+			*pnetfid = parms->SearchHandle;
+		} else {
+			cifs_buf_release(pSMB);
+		}
+	}
+
+	return rc;
+}
+
+int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
+            __u16 searchHandle, struct cifs_search_info * psrch_inf)
+{
+	TRANSACTION2_FNEXT_REQ *pSMB = NULL;
+	TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
+	T2_FNEXT_RSP_PARMS * parms;
+	char *response_data;
+	int rc = 0;
+	int bytes_returned, name_len;
+	__u16 params, byte_count;
+
+	cFYI(1, ("In FindNext"));
+
+	if(psrch_inf->endOfSearch == TRUE)
+		return -ENOENT;
+
+	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+		(void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	params = 14;    /* includes 2 bytes of null string, converted to LE below */
+	byte_count = 0;
+	pSMB->TotalDataCount = 0;       /* no EAs */
+	pSMB->MaxParameterCount = cpu_to_le16(8);
+	pSMB->MaxDataCount =
+            cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
+	pSMB->MaxSetupCount = 0;
+	pSMB->Reserved = 0;
+	pSMB->Flags = 0;
+	pSMB->Timeout = 0;
+	pSMB->Reserved2 = 0;
+	pSMB->ParameterOffset =  cpu_to_le16(
+	      offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
+	pSMB->DataCount = 0;
+	pSMB->DataOffset = 0;
+	pSMB->SetupCount = 1;
+	pSMB->Reserved3 = 0;
+	pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
+	pSMB->SearchHandle = searchHandle;      /* always kept as le */
+	pSMB->SearchCount =
+		cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
+	/* test for Unix extensions */
+/*	if (tcon->ses->capabilities & CAP_UNIX) {
+		pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
+		psrch_inf->info_level = SMB_FIND_FILE_UNIX;
+	} else {
+		pSMB->InformationLevel =
+		   cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
+		psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
+	} */
+	pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
+	pSMB->ResumeKey = psrch_inf->resume_key;
+	pSMB->SearchFlags =
+	      cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
+
+	name_len = psrch_inf->resume_name_len;
+	params += name_len;
+	if(name_len < PATH_MAX) {
+		memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
+		byte_count += name_len;
+	} else {
+		rc = -EINVAL;
+		goto FNext2_err_exit;
+	}
+	byte_count = params + 1 /* pad */ ;
+	pSMB->TotalParameterCount = cpu_to_le16(params);
+	pSMB->ParameterCount = pSMB->TotalParameterCount;
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
+                                                                                              
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			(struct smb_hdr *) pSMBr, &bytes_returned, 0);
+                                                                                              
+	if (rc) {
+		if (rc == -EBADF) {
+			psrch_inf->endOfSearch = TRUE;
+			rc = 0; /* search probably was closed at end of search above */
+		} else
+			cFYI(1, ("FindNext returned = %d", rc));
+	} else {                /* decode response */
+		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+		
+		if(rc == 0) {
+			/* BB fixme add lock for file (srch_info) struct here */
+			if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
+				psrch_inf->unicode = TRUE;
+			else
+				psrch_inf->unicode = FALSE;
+			response_data = (char *) &pSMBr->hdr.Protocol +
+			       le16_to_cpu(pSMBr->t2.ParameterOffset);
+			parms = (T2_FNEXT_RSP_PARMS *)response_data;
+			response_data = (char *)&pSMBr->hdr.Protocol +
+				le16_to_cpu(pSMBr->t2.DataOffset);
+			cifs_buf_release(psrch_inf->ntwrk_buf_start);
+			psrch_inf->srch_entries_start = response_data;
+			psrch_inf->ntwrk_buf_start = (char *)pSMB;
+			if(parms->EndofSearch)
+				psrch_inf->endOfSearch = TRUE;
+			else
+				psrch_inf->endOfSearch = FALSE;
+                                                                                              
+			psrch_inf->entries_in_buffer  = le16_to_cpu(parms->SearchCount);
+			psrch_inf->index_of_last_entry +=
+				psrch_inf->entries_in_buffer;
+/*  cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
+
+			/* BB fixme add unlock here */
+		}
+
+	}
+
+	/* BB On error, should we leave previous search buf (and count and
+	last entry fields) intact or free the previous one? */
+
+	/* Note: On -EAGAIN error only caller can retry on handle based calls
+	since file handle passed in no longer valid */
+FNext2_err_exit:
+	if (rc != 0)
+		cifs_buf_release(pSMB);
+                                                                                              
+	return rc;
+}
+
+int
+CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
+{
+	int rc = 0;
+	FINDCLOSE_REQ *pSMB = NULL;
+	CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
+	int bytes_returned;
+
+	cFYI(1, ("In CIFSSMBFindClose"));
+	rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
+
+	/* no sense returning error if session restarted
+		as file handle has been closed */
+	if(rc == -EAGAIN)
+		return 0;
+	if (rc)
+		return rc;
+
+	pSMBr = (CLOSE_RSP *)pSMB;  /* BB removeme BB */
+	pSMB->FileID = searchHandle;
+	pSMB->ByteCount = 0;
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cERROR(1, ("Send error in FindClose = %d", rc));
+	}
+	cifs_small_buf_release(pSMB);
+
+	/* Since session is dead, search handle closed on server already */
+	if (rc == -EAGAIN)
+		rc = 0;
+
+	return rc;
+}
+
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+int
+CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
+                const unsigned char *searchName,
+                __u64 * inode_number,
+                const struct nls_table *nls_codepage)
+{
+	int rc = 0;
+	TRANSACTION2_QPI_REQ *pSMB = NULL;
+	TRANSACTION2_QPI_RSP *pSMBr = NULL;
+	int name_len, bytes_returned;
+	__u16 params, byte_count;
+
+	cFYI(1,("In GetSrvInodeNum for %s",searchName));
+	if(tcon == NULL)
+		return -ENODEV; 
+
+GetInodeNumberRetry:
+	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+                      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+
+	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+		name_len =
+			cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 
+				PATH_MAX,nls_codepage);
+		name_len++;     /* trailing null */
+		name_len *= 2;
+	} else {                /* BB improve the check for buffer overruns BB */
+		name_len = strnlen(searchName, PATH_MAX);
+		name_len++;     /* trailing null */
+		strncpy(pSMB->FileName, searchName, name_len);
+	}
+
+	params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
+	pSMB->TotalDataCount = 0;
+	pSMB->MaxParameterCount = cpu_to_le16(2);
+	/* BB find exact max data count below from sess structure BB */
+	pSMB->MaxDataCount = cpu_to_le16(4000);
+	pSMB->MaxSetupCount = 0;
+	pSMB->Reserved = 0;
+	pSMB->Flags = 0;
+	pSMB->Timeout = 0;
+	pSMB->Reserved2 = 0;
+	pSMB->ParameterOffset = cpu_to_le16(offsetof(
+		struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
+	pSMB->DataCount = 0;
+	pSMB->DataOffset = 0;
+	pSMB->SetupCount = 1;
+	pSMB->Reserved3 = 0;
+	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
+	byte_count = params + 1 /* pad */ ;
+	pSMB->TotalParameterCount = cpu_to_le16(params);
+	pSMB->ParameterCount = pSMB->TotalParameterCount;
+	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
+	pSMB->Reserved4 = 0;
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
+
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cFYI(1, ("error %d in QueryInternalInfo", rc));
+	} else {
+		/* decode response */
+		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+		if (rc || (pSMBr->ByteCount < 2))
+		/* BB also check enough total bytes returned */
+			/* If rc should we check for EOPNOSUPP and
+			disable the srvino flag? or in caller? */
+			rc = -EIO;      /* bad smb */
+                else {
+			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+			__u16 count = le16_to_cpu(pSMBr->t2.DataCount);
+			struct file_internal_info * pfinfo;
+			/* BB Do we need a cast or hash here ? */
+			if(count < 8) {
+				cFYI(1, ("Illegal size ret in QryIntrnlInf"));
+				rc = -EIO;
+				goto GetInodeNumOut;
+			}
+			pfinfo = (struct file_internal_info *)
+				(data_offset + (char *) &pSMBr->hdr.Protocol);
+			*inode_number = pfinfo->UniqueId;
+		}
+	}
+GetInodeNumOut:
+	cifs_buf_release(pSMB);
+	if (rc == -EAGAIN)
+		goto GetInodeNumberRetry;
+	return rc;
+}
+#endif /* CIFS_EXPERIMENTAL */
+
+int
+CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
+		const unsigned char *searchName,
+		unsigned char **targetUNCs,
+		unsigned int *number_of_UNC_in_array,
+		const struct nls_table *nls_codepage)
+{
+/* TRANS2_GET_DFS_REFERRAL */
+	TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
+	TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
+	struct dfs_referral_level_3 * referrals = NULL;
+	int rc = 0;
+	int bytes_returned;
+	int name_len;
+	unsigned int i;
+	char * temp;
+	__u16 params, byte_count;
+	*number_of_UNC_in_array = 0;
+	*targetUNCs = NULL;
+
+	cFYI(1, ("In GetDFSRefer the path %s", searchName));
+	if (ses == NULL)
+		return -ENODEV;
+getDFSRetry:
+	rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	pSMB->hdr.Tid = ses->ipc_tid;
+	pSMB->hdr.Uid = ses->Suid;
+	if (ses->capabilities & CAP_STATUS32) {
+		pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
+	}
+	if (ses->capabilities & CAP_DFS) {
+		pSMB->hdr.Flags2 |= SMBFLG2_DFS;
+	}
+
+	if (ses->capabilities & CAP_UNICODE) {
+		pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
+		name_len =
+		    cifs_strtoUCS((wchar_t *) pSMB->RequestFileName,
+				  searchName, PATH_MAX
+				  /* find define for this maxpathcomponent */
+				  , nls_codepage);
+		name_len++;	/* trailing null */
+		name_len *= 2;
+	} else {		/* BB improve the check for buffer overruns BB */
+		name_len = strnlen(searchName, PATH_MAX);
+		name_len++;	/* trailing null */
+		strncpy(pSMB->RequestFileName, searchName, name_len);
+	}
+
+	params = 2 /* level */  + name_len /*includes null */ ;
+	pSMB->TotalDataCount = 0;
+	pSMB->DataCount = 0;
+	pSMB->DataOffset = 0;
+	pSMB->MaxParameterCount = 0;
+	pSMB->MaxDataCount = cpu_to_le16(4000);	/* BB find exact max SMB PDU from sess structure BB */
+	pSMB->MaxSetupCount = 0;
+	pSMB->Reserved = 0;
+	pSMB->Flags = 0;
+	pSMB->Timeout = 0;
+	pSMB->Reserved2 = 0;
+	pSMB->ParameterOffset = cpu_to_le16(offsetof(
+        struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
+	pSMB->SetupCount = 1;
+	pSMB->Reserved3 = 0;
+	pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
+	byte_count = params + 3 /* pad */ ;
+	pSMB->ParameterCount = cpu_to_le16(params);
+	pSMB->TotalParameterCount = pSMB->ParameterCount;
+	pSMB->MaxReferralLevel = cpu_to_le16(3);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
+
+	rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cFYI(1, ("Send error in GetDFSRefer = %d", rc));
+	} else {		/* decode response */
+/* BB Add logic to parse referrals here */
+		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+		if (rc || (pSMBr->ByteCount < 17))      /* BB also check enough total bytes returned */
+			rc = -EIO;      /* bad smb */
+		else {
+			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); 
+			__u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
+
+			cFYI(1,
+			     ("Decoding GetDFSRefer response.  BCC: %d  Offset %d",
+			      pSMBr->ByteCount, data_offset));
+			referrals = 
+			    (struct dfs_referral_level_3 *) 
+					(8 /* sizeof start of data block */ +
+					data_offset +
+					(char *) &pSMBr->hdr.Protocol); 
+			cFYI(1,("num_referrals: %d dfs flags: 0x%x ... \nfor referral one refer size: 0x%x srv type: 0x%x refer flags: 0x%x ttl: 0x%x",
+				le16_to_cpu(pSMBr->NumberOfReferrals),le16_to_cpu(pSMBr->DFSFlags), le16_to_cpu(referrals->ReferralSize),le16_to_cpu(referrals->ServerType),le16_to_cpu(referrals->ReferralFlags),le16_to_cpu(referrals->TimeToLive)));
+			/* BB This field is actually two bytes in from start of
+			   data block so we could do safety check that DataBlock
+			   begins at address of pSMBr->NumberOfReferrals */
+			*number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
+
+			/* BB Fix below so can return more than one referral */
+			if(*number_of_UNC_in_array > 1)
+				*number_of_UNC_in_array = 1;
+
+			/* get the length of the strings describing refs */
+			name_len = 0;
+			for(i=0;i<*number_of_UNC_in_array;i++) {
+				/* make sure that DfsPathOffset not past end */
+				__u16 offset = le16_to_cpu(referrals->DfsPathOffset);
+				if (offset > data_count) {
+					/* if invalid referral, stop here and do 
+					not try to copy any more */
+					*number_of_UNC_in_array = i;
+					break;
+				} 
+				temp = ((char *)referrals) + offset;
+
+				if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
+					name_len += UniStrnlen((wchar_t *)temp,data_count);
+				} else {
+					name_len += strnlen(temp,data_count);
+				}
+				referrals++;
+				/* BB add check that referral pointer does not fall off end PDU */
+				
+			}
+			/* BB add check for name_len bigger than bcc */
+			*targetUNCs = 
+				kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
+			if(*targetUNCs == NULL) {
+				rc = -ENOMEM;
+				goto GetDFSRefExit;
+			}
+			/* copy the ref strings */
+			referrals =  
+			    (struct dfs_referral_level_3 *) 
+					(8 /* sizeof data hdr */ +
+					data_offset + 
+					(char *) &pSMBr->hdr.Protocol);
+
+			for(i=0;i<*number_of_UNC_in_array;i++) {
+				temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
+				if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
+					cifs_strfromUCS_le(*targetUNCs,
+						(wchar_t *) temp, name_len, nls_codepage);
+				} else {
+					strncpy(*targetUNCs,temp,name_len);
+				}
+				/*  BB update target_uncs pointers */
+				referrals++;
+			}
+			temp = *targetUNCs;
+			temp[name_len] = 0;
+		}
+
+	}
+GetDFSRefExit:
+	if (pSMB)
+		cifs_buf_release(pSMB);
+
+	if (rc == -EAGAIN)
+		goto getDFSRetry;
+
+	return rc;
+}
+
+int
+CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
+	       struct kstatfs *FSData, const struct nls_table *nls_codepage)
+{
+/* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
+	TRANSACTION2_QFSI_REQ *pSMB = NULL;
+	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
+	FILE_SYSTEM_INFO *response_data;
+	int rc = 0;
+	int bytes_returned = 0;
+	__u16 params, byte_count;
+
+	cFYI(1, ("In QFSInfo"));
+QFSInfoRetry:
+	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	params = 2;	/* level */
+	pSMB->TotalDataCount = 0;
+	pSMB->MaxParameterCount = cpu_to_le16(2);
+	pSMB->MaxDataCount = cpu_to_le16(1000);	/* BB find exact max SMB PDU from sess structure BB */
+	pSMB->MaxSetupCount = 0;
+	pSMB->Reserved = 0;
+	pSMB->Flags = 0;
+	pSMB->Timeout = 0;
+	pSMB->Reserved2 = 0;
+	byte_count = params + 1 /* pad */ ;
+	pSMB->TotalParameterCount = cpu_to_le16(params);
+	pSMB->ParameterCount = pSMB->TotalParameterCount;
+	pSMB->ParameterOffset = cpu_to_le16(offsetof(
+        struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
+	pSMB->DataCount = 0;
+	pSMB->DataOffset = 0;
+	pSMB->SetupCount = 1;
+	pSMB->Reserved3 = 0;
+	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
+	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
+
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cERROR(1, ("Send error in QFSInfo = %d", rc));
+	} else {		/* decode response */
+                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+		if (rc || (pSMBr->ByteCount < 24)) /* BB alsO CHEck enough total bytes returned */
+			rc = -EIO;	/* bad smb */
+		else {
+			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+			cFYI(1,
+				("Decoding qfsinfo response.  BCC: %d  Offset %d",
+				pSMBr->ByteCount, data_offset));
+
+			response_data =
+			    (FILE_SYSTEM_INFO
+			     *) (((char *) &pSMBr->hdr.Protocol) +
+				 data_offset);
+			FSData->f_bsize =
+			    le32_to_cpu(response_data->BytesPerSector) *
+			    le32_to_cpu(response_data->
+					SectorsPerAllocationUnit);
+			FSData->f_blocks =
+			    le64_to_cpu(response_data->TotalAllocationUnits);
+			FSData->f_bfree = FSData->f_bavail =
+			    le64_to_cpu(response_data->FreeAllocationUnits);
+			cFYI(1,
+			     ("Blocks: %lld  Free: %lld Block size %ld",
+			      (unsigned long long)FSData->f_blocks,
+			      (unsigned long long)FSData->f_bfree,
+			      FSData->f_bsize));
+		}
+	}
+	cifs_buf_release(pSMB);
+
+	if (rc == -EAGAIN)
+		goto QFSInfoRetry;
+
+	return rc;
+}
+
+int
+CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon,
+			const struct nls_table *nls_codepage)
+{
+/* level 0x105  SMB_QUERY_FILE_SYSTEM_INFO */
+	TRANSACTION2_QFSI_REQ *pSMB = NULL;
+	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
+	FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
+	int rc = 0;
+	int bytes_returned = 0;
+	__u16 params, byte_count;
+
+	cFYI(1, ("In QFSAttributeInfo"));
+QFSAttributeRetry:
+	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	params = 2;	/* level */
+	pSMB->TotalDataCount = 0;
+	pSMB->MaxParameterCount = cpu_to_le16(2);
+	pSMB->MaxDataCount = cpu_to_le16(1000);	/* BB find exact max SMB PDU from sess structure BB */
+	pSMB->MaxSetupCount = 0;
+	pSMB->Reserved = 0;
+	pSMB->Flags = 0;
+	pSMB->Timeout = 0;
+	pSMB->Reserved2 = 0;
+	byte_count = params + 1 /* pad */ ;
+	pSMB->TotalParameterCount = cpu_to_le16(params);
+	pSMB->ParameterCount = pSMB->TotalParameterCount;
+	pSMB->ParameterOffset = cpu_to_le16(offsetof(
+        struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
+	pSMB->DataCount = 0;
+	pSMB->DataOffset = 0;
+	pSMB->SetupCount = 1;
+	pSMB->Reserved3 = 0;
+	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
+	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
+
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
+	} else {		/* decode response */
+		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+		if (rc || (pSMBr->ByteCount < 13)) {	/* BB also check enough bytes returned */
+			rc = -EIO;	/* bad smb */
+		} else {
+			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+			response_data =
+			    (FILE_SYSTEM_ATTRIBUTE_INFO
+			     *) (((char *) &pSMBr->hdr.Protocol) +
+				 data_offset);
+			memcpy(&tcon->fsAttrInfo, response_data,
+			       sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
+		}
+	}
+	cifs_buf_release(pSMB);
+
+	if (rc == -EAGAIN)
+		goto QFSAttributeRetry;
+
+	return rc;
+}
+
+int
+CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon,
+		     const struct nls_table *nls_codepage)
+{
+/* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
+	TRANSACTION2_QFSI_REQ *pSMB = NULL;
+	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
+	FILE_SYSTEM_DEVICE_INFO *response_data;
+	int rc = 0;
+	int bytes_returned = 0;
+	__u16 params, byte_count;
+
+	cFYI(1, ("In QFSDeviceInfo"));
+QFSDeviceRetry:
+	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	params = 2;	/* level */
+	pSMB->TotalDataCount = 0;
+	pSMB->MaxParameterCount = cpu_to_le16(2);
+	pSMB->MaxDataCount = cpu_to_le16(1000);	/* BB find exact max SMB PDU from sess structure BB */
+	pSMB->MaxSetupCount = 0;
+	pSMB->Reserved = 0;
+	pSMB->Flags = 0;
+	pSMB->Timeout = 0;
+	pSMB->Reserved2 = 0;
+	byte_count = params + 1 /* pad */ ;
+	pSMB->TotalParameterCount = cpu_to_le16(params);
+	pSMB->ParameterCount = pSMB->TotalParameterCount;
+	pSMB->ParameterOffset = cpu_to_le16(offsetof(
+        struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
+
+	pSMB->DataCount = 0;
+	pSMB->DataOffset = 0;
+	pSMB->SetupCount = 1;
+	pSMB->Reserved3 = 0;
+	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
+	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
+
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
+	} else {		/* decode response */
+		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+		if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
+			rc = -EIO;	/* bad smb */
+		else {
+			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+			response_data =
+			    (FILE_SYSTEM_DEVICE_INFO
+			     *) (((char *) &pSMBr->hdr.Protocol) +
+				 data_offset);
+			memcpy(&tcon->fsDevInfo, response_data,
+			       sizeof (FILE_SYSTEM_DEVICE_INFO));
+		}
+	}
+	cifs_buf_release(pSMB);
+
+	if (rc == -EAGAIN)
+		goto QFSDeviceRetry;
+
+	return rc;
+}
+
+int
+CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
+		   const struct nls_table *nls_codepage)
+{
+/* level 0x200  SMB_QUERY_CIFS_UNIX_INFO */
+	TRANSACTION2_QFSI_REQ *pSMB = NULL;
+	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
+	FILE_SYSTEM_UNIX_INFO *response_data;
+	int rc = 0;
+	int bytes_returned = 0;
+	__u16 params, byte_count;
+
+	cFYI(1, ("In QFSUnixInfo"));
+QFSUnixRetry:
+	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	params = 2;	/* level */
+	pSMB->TotalDataCount = 0;
+	pSMB->DataCount = 0;
+	pSMB->DataOffset = 0;
+	pSMB->MaxParameterCount = cpu_to_le16(2);
+	pSMB->MaxDataCount = cpu_to_le16(100);	/* BB find exact max SMB PDU from sess structure BB */
+	pSMB->MaxSetupCount = 0;
+	pSMB->Reserved = 0;
+	pSMB->Flags = 0;
+	pSMB->Timeout = 0;
+	pSMB->Reserved2 = 0;
+	byte_count = params + 1 /* pad */ ;
+	pSMB->ParameterCount = cpu_to_le16(params);
+	pSMB->TotalParameterCount = pSMB->ParameterCount;
+	pSMB->ParameterOffset = cpu_to_le16(offsetof(struct 
+        smb_com_transaction2_qfsi_req, InformationLevel) - 4);
+	pSMB->SetupCount = 1;
+	pSMB->Reserved3 = 0;
+	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
+	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
+
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
+	} else {		/* decode response */
+		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+		if (rc || (pSMBr->ByteCount < 13)) {
+			rc = -EIO;	/* bad smb */
+		} else {
+			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+			response_data =
+			    (FILE_SYSTEM_UNIX_INFO
+			     *) (((char *) &pSMBr->hdr.Protocol) +
+				 data_offset);
+			memcpy(&tcon->fsUnixInfo, response_data,
+			       sizeof (FILE_SYSTEM_UNIX_INFO));
+		}
+	}
+	cifs_buf_release(pSMB);
+
+	if (rc == -EAGAIN)
+		goto QFSUnixRetry;
+
+
+	return rc;
+}
+
+
+int
+CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
+		   struct kstatfs *FSData, const struct nls_table *nls_codepage)
+{
+/* level 0x201  SMB_QUERY_CIFS_POSIX_INFO */
+	TRANSACTION2_QFSI_REQ *pSMB = NULL;
+	TRANSACTION2_QFSI_RSP *pSMBr = NULL;
+	FILE_SYSTEM_POSIX_INFO *response_data;
+	int rc = 0;
+	int bytes_returned = 0;
+	__u16 params, byte_count;
+
+	cFYI(1, ("In QFSPosixInfo"));
+QFSPosixRetry:
+	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	params = 2;	/* level */
+	pSMB->TotalDataCount = 0;
+	pSMB->DataCount = 0;
+	pSMB->DataOffset = 0;
+	pSMB->MaxParameterCount = cpu_to_le16(2);
+	pSMB->MaxDataCount = cpu_to_le16(100);	/* BB find exact max SMB PDU from sess structure BB */
+	pSMB->MaxSetupCount = 0;
+	pSMB->Reserved = 0;
+	pSMB->Flags = 0;
+	pSMB->Timeout = 0;
+	pSMB->Reserved2 = 0;
+	byte_count = params + 1 /* pad */ ;
+	pSMB->ParameterCount = cpu_to_le16(params);
+	pSMB->TotalParameterCount = pSMB->ParameterCount;
+	pSMB->ParameterOffset = cpu_to_le16(offsetof(struct 
+        smb_com_transaction2_qfsi_req, InformationLevel) - 4);
+	pSMB->SetupCount = 1;
+	pSMB->Reserved3 = 0;
+	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
+	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
+
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
+	} else {		/* decode response */
+		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+		if (rc || (pSMBr->ByteCount < 13)) {
+			rc = -EIO;	/* bad smb */
+		} else {
+			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+			response_data =
+			    (FILE_SYSTEM_POSIX_INFO
+			     *) (((char *) &pSMBr->hdr.Protocol) +
+				 data_offset);
+			FSData->f_bsize =
+					le32_to_cpu(response_data->BlockSize);
+			FSData->f_blocks =
+					le64_to_cpu(response_data->TotalBlocks);
+			FSData->f_bfree =
+			    le64_to_cpu(response_data->BlocksAvail);
+			if(response_data->UserBlocksAvail == -1) {
+				FSData->f_bavail = FSData->f_bfree;
+			} else {
+				FSData->f_bavail =
+					le64_to_cpu(response_data->UserBlocksAvail);
+			}
+			if(response_data->TotalFileNodes != -1)
+				FSData->f_files =
+					le64_to_cpu(response_data->TotalFileNodes);
+			if(response_data->FreeFileNodes != -1)
+				FSData->f_ffree =
+					le64_to_cpu(response_data->FreeFileNodes);
+		}
+	}
+	cifs_buf_release(pSMB);
+
+	if (rc == -EAGAIN)
+		goto QFSPosixRetry;
+
+	return rc;
+}
+
+
+/* We can not use write of zero bytes trick to 
+   set file size due to need for large file support.  Also note that 
+   this SetPathInfo is preferred to SetFileInfo based method in next 
+   routine which is only needed to work around a sharing violation bug
+   in Samba which this routine can run into */
+
+int
+CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
+	      __u64 size, int SetAllocation, const struct nls_table *nls_codepage)
+{
+	struct smb_com_transaction2_spi_req *pSMB = NULL;
+	struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
+	struct file_end_of_file_info *parm_data;
+	int name_len;
+	int rc = 0;
+	int bytes_returned = 0;
+	__u16 params, byte_count, data_count, param_offset, offset;
+
+	cFYI(1, ("In SetEOF"));
+SetEOFRetry:
+	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+		name_len =
+		    cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
+				  /* find define for this maxpathcomponent */
+				  , nls_codepage);
+		name_len++;	/* trailing null */
+		name_len *= 2;
+	} else {		/* BB improve the check for buffer overruns BB */
+		name_len = strnlen(fileName, PATH_MAX);
+		name_len++;	/* trailing null */
+		strncpy(pSMB->FileName, fileName, name_len);
+	}
+	params = 6 + name_len;
+	data_count = sizeof (struct file_end_of_file_info);
+	pSMB->MaxParameterCount = cpu_to_le16(2);
+	pSMB->MaxDataCount = cpu_to_le16(1000);	/* BB find max SMB size from sess */
+	pSMB->MaxSetupCount = 0;
+	pSMB->Reserved = 0;
+	pSMB->Flags = 0;
+	pSMB->Timeout = 0;
+	pSMB->Reserved2 = 0;
+	param_offset = offsetof(struct smb_com_transaction2_spi_req,
+                                     InformationLevel) - 4;
+	offset = param_offset + params;
+	if(SetAllocation) {
+        	if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
+	            pSMB->InformationLevel =
+                	cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
+        	else
+	            pSMB->InformationLevel =
+        	        cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
+	} else /* Set File Size */  {    
+	    if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
+		    pSMB->InformationLevel =
+		        cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
+	    else
+		    pSMB->InformationLevel =
+		        cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
+	}
+
+	parm_data =
+	    (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
+				       offset);
+	pSMB->ParameterOffset = cpu_to_le16(param_offset);
+	pSMB->DataOffset = cpu_to_le16(offset);
+	pSMB->SetupCount = 1;
+	pSMB->Reserved3 = 0;
+	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
+	byte_count = 3 /* pad */  + params + data_count;
+	pSMB->DataCount = cpu_to_le16(data_count);
+	pSMB->TotalDataCount = pSMB->DataCount;
+	pSMB->ParameterCount = cpu_to_le16(params);
+	pSMB->TotalParameterCount = pSMB->ParameterCount;
+	pSMB->Reserved4 = 0;
+	pSMB->hdr.smb_buf_length += byte_count;
+	parm_data->FileSize = cpu_to_le64(size);
+	pSMB->ByteCount = cpu_to_le16(byte_count);
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cFYI(1, ("SetPathInfo (file size) returned %d", rc));
+	}
+
+	cifs_buf_release(pSMB);
+
+	if (rc == -EAGAIN)
+		goto SetEOFRetry;
+
+	return rc;
+}
+
+int
+CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, 
+                   __u16 fid, __u32 pid_of_opener, int SetAllocation)
+{
+	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
+	struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
+	char *data_offset;
+	struct file_end_of_file_info *parm_data;
+	int rc = 0;
+	int bytes_returned = 0;
+	__u16 params, param_offset, offset, byte_count, count;
+
+	cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
+			(long long)size));
+	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
+	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
+    
+	params = 6;
+	pSMB->MaxSetupCount = 0;
+	pSMB->Reserved = 0;
+	pSMB->Flags = 0;
+	pSMB->Timeout = 0;
+	pSMB->Reserved2 = 0;
+	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
+	offset = param_offset + params;
+
+	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;	
+
+	count = sizeof(struct file_end_of_file_info);
+	pSMB->MaxParameterCount = cpu_to_le16(2);
+	pSMB->MaxDataCount = cpu_to_le16(1000);	/* BB find max SMB PDU from sess */
+	pSMB->SetupCount = 1;
+	pSMB->Reserved3 = 0;
+	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
+	byte_count = 3 /* pad */  + params + count;
+	pSMB->DataCount = cpu_to_le16(count);
+	pSMB->ParameterCount = cpu_to_le16(params);
+	pSMB->TotalDataCount = pSMB->DataCount;
+	pSMB->TotalParameterCount = pSMB->ParameterCount;
+	pSMB->ParameterOffset = cpu_to_le16(param_offset);
+	parm_data =
+		(struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
+			offset);
+	pSMB->DataOffset = cpu_to_le16(offset);
+	parm_data->FileSize = cpu_to_le64(size);
+	pSMB->Fid = fid;
+	if(SetAllocation) {
+		if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
+			pSMB->InformationLevel =
+				cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
+		else
+			pSMB->InformationLevel =
+				cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
+	} else /* Set File Size */  {    
+	    if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
+		    pSMB->InformationLevel =
+		        cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
+	    else
+		    pSMB->InformationLevel =
+		        cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
+	}
+	pSMB->Reserved4 = 0;
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cFYI(1,
+		     ("Send error in SetFileInfo (SetFileSize) = %d",
+		      rc));
+	}
+
+	if (pSMB)
+		cifs_buf_release(pSMB);
+
+	/* Note: On -EAGAIN error only caller can retry on handle based calls 
+		since file handle passed in no longer valid */
+
+	return rc;
+}
+
+/* Some legacy servers such as NT4 require that the file times be set on 
+   an open handle, rather than by pathname - this is awkward due to
+   potential access conflicts on the open, but it is unavoidable for these
+   old servers since the only other choice is to go from 100 nanosecond DCE
+   time and resort to the original setpathinfo level which takes the ancient
+   DOS time format with 2 second granularity */
+int
+CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO * data, 
+                   __u16 fid)
+{
+	struct smb_com_transaction2_sfi_req *pSMB  = NULL;
+	struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
+	char *data_offset;
+	int rc = 0;
+	int bytes_returned = 0;
+	__u16 params, param_offset, offset, byte_count, count;
+
+	cFYI(1, ("Set Times (via SetFileInfo)"));
+	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	/* At this point there is no need to override the current pid
+	with the pid of the opener, but that could change if we someday
+	use an existing handle (rather than opening one on the fly) */
+	/* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
+	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
+    
+	params = 6;
+	pSMB->MaxSetupCount = 0;
+	pSMB->Reserved = 0;
+	pSMB->Flags = 0;
+	pSMB->Timeout = 0;
+	pSMB->Reserved2 = 0;
+	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
+	offset = param_offset + params;
+
+	data_offset = (char *) (&pSMB->hdr.Protocol) + offset; 
+
+	count = sizeof (FILE_BASIC_INFO);
+	pSMB->MaxParameterCount = cpu_to_le16(2);
+	pSMB->MaxDataCount = cpu_to_le16(1000);	/* BB find max SMB PDU from sess */
+	pSMB->SetupCount = 1;
+	pSMB->Reserved3 = 0;
+	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
+	byte_count = 3 /* pad */  + params + count;
+	pSMB->DataCount = cpu_to_le16(count);
+	pSMB->ParameterCount = cpu_to_le16(params);
+	pSMB->TotalDataCount = pSMB->DataCount;
+	pSMB->TotalParameterCount = pSMB->ParameterCount;
+	pSMB->ParameterOffset = cpu_to_le16(param_offset);
+	pSMB->DataOffset = cpu_to_le16(offset);
+	pSMB->Fid = fid;
+	if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
+		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
+	else
+		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
+	pSMB->Reserved4 = 0;
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
+	memcpy(data_offset,data,sizeof(FILE_BASIC_INFO));
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
+	}
+
+	cifs_buf_release(pSMB);
+
+	/* Note: On -EAGAIN error only caller can retry on handle based calls 
+		since file handle passed in no longer valid */
+
+	return rc;
+}
+
+
+int
+CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
+		const FILE_BASIC_INFO * data, 
+		const struct nls_table *nls_codepage)
+{
+	TRANSACTION2_SPI_REQ *pSMB = NULL;
+	TRANSACTION2_SPI_RSP *pSMBr = NULL;
+	int name_len;
+	int rc = 0;
+	int bytes_returned = 0;
+	char *data_offset;
+	__u16 params, param_offset, offset, byte_count, count;
+
+	cFYI(1, ("In SetTimes"));
+
+SetTimesRetry:
+	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+		name_len =
+		    cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
+				  /* find define for this maxpathcomponent */
+				  , nls_codepage);
+		name_len++;	/* trailing null */
+		name_len *= 2;
+	} else {		/* BB improve the check for buffer overruns BB */
+		name_len = strnlen(fileName, PATH_MAX);
+		name_len++;	/* trailing null */
+		strncpy(pSMB->FileName, fileName, name_len);
+	}
+
+	params = 6 + name_len;
+	count = sizeof (FILE_BASIC_INFO);
+	pSMB->MaxParameterCount = cpu_to_le16(2);
+	pSMB->MaxDataCount = cpu_to_le16(1000);	/* BB find exact max SMB PDU from sess structure BB */
+	pSMB->MaxSetupCount = 0;
+	pSMB->Reserved = 0;
+	pSMB->Flags = 0;
+	pSMB->Timeout = 0;
+	pSMB->Reserved2 = 0;
+	param_offset = offsetof(struct smb_com_transaction2_spi_req,
+                                     InformationLevel) - 4;
+	offset = param_offset + params;
+	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
+	pSMB->ParameterOffset = cpu_to_le16(param_offset);
+	pSMB->DataOffset = cpu_to_le16(offset);
+	pSMB->SetupCount = 1;
+	pSMB->Reserved3 = 0;
+	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
+	byte_count = 3 /* pad */  + params + count;
+
+	pSMB->DataCount = cpu_to_le16(count);
+	pSMB->ParameterCount = cpu_to_le16(params);
+	pSMB->TotalDataCount = pSMB->DataCount;
+	pSMB->TotalParameterCount = pSMB->ParameterCount;
+	if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
+		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
+	else
+		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
+	pSMB->Reserved4 = 0;
+	pSMB->hdr.smb_buf_length += byte_count;
+	memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
+	pSMB->ByteCount = cpu_to_le16(byte_count);
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cFYI(1, ("SetPathInfo (times) returned %d", rc));
+	}
+
+	cifs_buf_release(pSMB);
+
+	if (rc == -EAGAIN)
+		goto SetTimesRetry;
+
+	return rc;
+}
+
+/* Can not be used to set time stamps yet (due to old DOS time format) */
+/* Can be used to set attributes */
+#if 0  /* Possibly not needed - since it turns out that strangely NT4 has a bug
+	  handling it anyway and NT4 was what we thought it would be needed for
+	  Do not delete it until we prove whether needed for Win9x though */
+int
+CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
+		__u16 dos_attrs, const struct nls_table *nls_codepage)
+{
+	SETATTR_REQ *pSMB = NULL;
+	SETATTR_RSP *pSMBr = NULL;
+	int rc = 0;
+	int bytes_returned;
+	int name_len;
+
+	cFYI(1, ("In SetAttrLegacy"));
+
+SetAttrLgcyRetry:
+	rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+		name_len =
+			cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName, 
+				PATH_MAX, nls_codepage);
+		name_len++;     /* trailing null */
+		name_len *= 2;
+	} else {                /* BB improve the check for buffer overruns BB */
+		name_len = strnlen(fileName, PATH_MAX);
+		name_len++;     /* trailing null */
+		strncpy(pSMB->fileName, fileName, name_len);
+	}
+	pSMB->attr = cpu_to_le16(dos_attrs);
+	pSMB->BufferFormat = 0x04;
+	pSMB->hdr.smb_buf_length += name_len + 1;
+	pSMB->ByteCount = cpu_to_le16(name_len + 1);
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cFYI(1, ("Error in LegacySetAttr = %d", rc));
+	}
+
+	cifs_buf_release(pSMB);
+
+	if (rc == -EAGAIN)
+		goto SetAttrLgcyRetry;
+
+	return rc;
+}
+#endif /* temporarily unneeded SetAttr legacy function */
+
+int
+CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
+		    char *fileName, __u64 mode, __u64 uid, __u64 gid,
+		    dev_t device, const struct nls_table *nls_codepage)
+{
+	TRANSACTION2_SPI_REQ *pSMB = NULL;
+	TRANSACTION2_SPI_RSP *pSMBr = NULL;
+	int name_len;
+	int rc = 0;
+	int bytes_returned = 0;
+	FILE_UNIX_BASIC_INFO *data_offset;
+	__u16 params, param_offset, offset, count, byte_count;
+
+	cFYI(1, ("In SetUID/GID/Mode"));
+setPermsRetry:
+	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+		name_len =
+		    cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
+				  /* find define for this maxpathcomponent */
+				  , nls_codepage);
+		name_len++;	/* trailing null */
+		name_len *= 2;
+	} else {		/* BB improve the check for buffer overruns BB */
+		name_len = strnlen(fileName, PATH_MAX);
+		name_len++;	/* trailing null */
+		strncpy(pSMB->FileName, fileName, name_len);
+	}
+
+	params = 6 + name_len;
+	count = sizeof (FILE_UNIX_BASIC_INFO);
+	pSMB->MaxParameterCount = cpu_to_le16(2);
+	pSMB->MaxDataCount = cpu_to_le16(1000);	/* BB find exact max SMB PDU from sess structure BB */
+	pSMB->MaxSetupCount = 0;
+	pSMB->Reserved = 0;
+	pSMB->Flags = 0;
+	pSMB->Timeout = 0;
+	pSMB->Reserved2 = 0;
+	param_offset = offsetof(struct smb_com_transaction2_spi_req,
+                                     InformationLevel) - 4;
+	offset = param_offset + params;
+	data_offset =
+	    (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
+				      offset);
+	memset(data_offset, 0, count);
+	pSMB->DataOffset = cpu_to_le16(offset);
+	pSMB->ParameterOffset = cpu_to_le16(param_offset);
+	pSMB->SetupCount = 1;
+	pSMB->Reserved3 = 0;
+	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
+	byte_count = 3 /* pad */  + params + count;
+	pSMB->ParameterCount = cpu_to_le16(params);
+	pSMB->DataCount = cpu_to_le16(count);
+	pSMB->TotalParameterCount = pSMB->ParameterCount;
+	pSMB->TotalDataCount = pSMB->DataCount;
+	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
+	pSMB->Reserved4 = 0;
+	pSMB->hdr.smb_buf_length += byte_count;
+	data_offset->Uid = cpu_to_le64(uid);
+	data_offset->Gid = cpu_to_le64(gid);
+	/* better to leave device as zero when it is  */
+	data_offset->DevMajor = cpu_to_le64(MAJOR(device));
+	data_offset->DevMinor = cpu_to_le64(MINOR(device));
+	data_offset->Permissions = cpu_to_le64(mode);
+    
+	if(S_ISREG(mode))
+		data_offset->Type = cpu_to_le32(UNIX_FILE);
+	else if(S_ISDIR(mode))
+		data_offset->Type = cpu_to_le32(UNIX_DIR);
+	else if(S_ISLNK(mode))
+		data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
+	else if(S_ISCHR(mode))
+		data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
+	else if(S_ISBLK(mode))
+		data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
+	else if(S_ISFIFO(mode))
+		data_offset->Type = cpu_to_le32(UNIX_FIFO);
+	else if(S_ISSOCK(mode))
+		data_offset->Type = cpu_to_le32(UNIX_SOCKET);
+
+
+	pSMB->ByteCount = cpu_to_le16(byte_count);
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cFYI(1, ("SetPathInfo (perms) returned %d", rc));
+	}
+
+	if (pSMB)
+		cifs_buf_release(pSMB);
+	if (rc == -EAGAIN)
+		goto setPermsRetry;
+	return rc;
+}
+
+int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, 
+			const int notify_subdirs, const __u16 netfid,
+			__u32 filter, const struct nls_table *nls_codepage)
+{
+	int rc = 0;
+	struct smb_com_transaction_change_notify_req * pSMB = NULL;
+	struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
+	int bytes_returned;
+
+	cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
+	rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
+                      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	pSMB->TotalParameterCount = 0 ;
+	pSMB->TotalDataCount = 0;
+	pSMB->MaxParameterCount = cpu_to_le32(2);
+	/* BB find exact data count max from sess structure BB */
+	pSMB->MaxDataCount = 0; /* same in little endian or be */
+	pSMB->MaxSetupCount = 4;
+	pSMB->Reserved = 0;
+	pSMB->ParameterOffset = 0;
+	pSMB->DataCount = 0;
+	pSMB->DataOffset = 0;
+	pSMB->SetupCount = 4; /* single byte does not need le conversion */
+	pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
+	pSMB->ParameterCount = pSMB->TotalParameterCount;
+	if(notify_subdirs)
+		pSMB->WatchTree = 1; /* one byte - no le conversion needed */
+	pSMB->Reserved2 = 0;
+	pSMB->CompletionFilter = cpu_to_le32(filter);
+	pSMB->Fid = netfid; /* file handle always le */
+	pSMB->ByteCount = 0;
+
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			(struct smb_hdr *) pSMBr, &bytes_returned, -1);
+	if (rc) {
+		cFYI(1, ("Error in Notify = %d", rc));
+	}
+	cifs_buf_release(pSMB);
+	return rc;	
+}
+#ifdef CONFIG_CIFS_XATTR
+ssize_t
+CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
+		 const unsigned char *searchName,
+		 char * EAData, size_t buf_size,
+		 const struct nls_table *nls_codepage)
+{
+		/* BB assumes one setup word */
+	TRANSACTION2_QPI_REQ *pSMB = NULL;
+	TRANSACTION2_QPI_RSP *pSMBr = NULL;
+	int rc = 0;
+	int bytes_returned;
+	int name_len;
+	struct fea * temp_fea;
+	char * temp_ptr;
+	__u16 params, byte_count;
+
+	cFYI(1, ("In Query All EAs path %s", searchName));
+QAllEAsRetry:
+	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+		name_len =
+		    cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
+				  /* find define for this maxpathcomponent */
+				  , nls_codepage);
+		name_len++;	/* trailing null */
+		name_len *= 2;
+	} else {	/* BB improve the check for buffer overruns BB */
+		name_len = strnlen(searchName, PATH_MAX);
+		name_len++;	/* trailing null */
+		strncpy(pSMB->FileName, searchName, name_len);
+	}
+
+	params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
+	pSMB->TotalDataCount = 0;
+	pSMB->MaxParameterCount = cpu_to_le16(2);
+	pSMB->MaxDataCount = cpu_to_le16(4000);	/* BB find exact max SMB PDU from sess structure BB */
+	pSMB->MaxSetupCount = 0;
+	pSMB->Reserved = 0;
+	pSMB->Flags = 0;
+	pSMB->Timeout = 0;
+	pSMB->Reserved2 = 0;
+	pSMB->ParameterOffset = cpu_to_le16(offsetof(
+        struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
+	pSMB->DataCount = 0;
+	pSMB->DataOffset = 0;
+	pSMB->SetupCount = 1;
+	pSMB->Reserved3 = 0;
+	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
+	byte_count = params + 1 /* pad */ ;
+	pSMB->TotalParameterCount = cpu_to_le16(params);
+	pSMB->ParameterCount = pSMB->TotalParameterCount;
+	pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
+	pSMB->Reserved4 = 0;
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
+
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cFYI(1, ("Send error in QueryAllEAs = %d", rc));
+	} else {		/* decode response */
+		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+		/* BB also check enough total bytes returned */
+		/* BB we need to improve the validity checking
+		of these trans2 responses */
+		if (rc || (pSMBr->ByteCount < 4)) 
+			rc = -EIO;	/* bad smb */
+	   /* else if (pFindData){
+			memcpy((char *) pFindData,
+			       (char *) &pSMBr->hdr.Protocol +
+			       data_offset, kl);
+		}*/ else {
+			/* check that length of list is not more than bcc */
+			/* check that each entry does not go beyond length
+			   of list */
+			/* check that each element of each entry does not
+			   go beyond end of list */
+			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+			struct fealist * ea_response_data;
+			rc = 0;
+			/* validate_trans2_offsets() */
+			/* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
+			ea_response_data = (struct fealist *)
+				(((char *) &pSMBr->hdr.Protocol) +
+				data_offset);
+			name_len = le32_to_cpu(ea_response_data->list_len);
+			cFYI(1,("ea length %d", name_len));
+			if(name_len <= 8) {
+			/* returned EA size zeroed at top of function */
+				cFYI(1,("empty EA list returned from server"));
+			} else {
+				/* account for ea list len */
+				name_len -= 4;
+				temp_fea = ea_response_data->list;
+				temp_ptr = (char *)temp_fea;
+				while(name_len > 0) {
+					__u16 value_len;
+					name_len -= 4;
+					temp_ptr += 4;
+					rc += temp_fea->name_len;
+				/* account for prefix user. and trailing null */
+					rc = rc + 5 + 1; 
+					if(rc<(int)buf_size) {
+						memcpy(EAData,"user.",5);
+						EAData+=5;
+						memcpy(EAData,temp_ptr,temp_fea->name_len);
+						EAData+=temp_fea->name_len;
+						/* null terminate name */
+						*EAData = 0;
+						EAData = EAData + 1;
+					} else if(buf_size == 0) {
+						/* skip copy - calc size only */
+					} else {
+						/* stop before overrun buffer */
+						rc = -ERANGE;
+						break;
+					}
+					name_len -= temp_fea->name_len;
+					temp_ptr += temp_fea->name_len;
+					/* account for trailing null */
+					name_len--;
+					temp_ptr++;
+					value_len = le16_to_cpu(temp_fea->value_len);
+					name_len -= value_len;
+					temp_ptr += value_len;
+					/* BB check that temp_ptr is still within smb BB*/
+				/* no trailing null to account for in value len */
+					/* go on to next EA */
+					temp_fea = (struct fea *)temp_ptr;
+				}
+			}
+		}
+	}
+	if (pSMB)
+		cifs_buf_release(pSMB);
+	if (rc == -EAGAIN)
+		goto QAllEAsRetry;
+
+	return (ssize_t)rc;
+}
+
+ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
+		const unsigned char * searchName,const unsigned char * ea_name,
+		unsigned char * ea_value, size_t buf_size, 
+		const struct nls_table *nls_codepage)
+{
+	TRANSACTION2_QPI_REQ *pSMB = NULL;
+	TRANSACTION2_QPI_RSP *pSMBr = NULL;
+	int rc = 0;
+	int bytes_returned;
+	int name_len;
+	struct fea * temp_fea;
+	char * temp_ptr;
+	__u16 params, byte_count;
+
+	cFYI(1, ("In Query EA path %s", searchName));
+QEARetry:
+	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+		name_len =
+		    cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
+				  /* find define for this maxpathcomponent */
+				  , nls_codepage);
+		name_len++;	/* trailing null */
+		name_len *= 2;
+	} else {	/* BB improve the check for buffer overruns BB */
+		name_len = strnlen(searchName, PATH_MAX);
+		name_len++;	/* trailing null */
+		strncpy(pSMB->FileName, searchName, name_len);
+	}
+
+	params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
+	pSMB->TotalDataCount = 0;
+	pSMB->MaxParameterCount = cpu_to_le16(2);
+	pSMB->MaxDataCount = cpu_to_le16(4000);	/* BB find exact max SMB PDU from sess structure BB */
+	pSMB->MaxSetupCount = 0;
+	pSMB->Reserved = 0;
+	pSMB->Flags = 0;
+	pSMB->Timeout = 0;
+	pSMB->Reserved2 = 0;
+	pSMB->ParameterOffset = cpu_to_le16(offsetof(
+        struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
+	pSMB->DataCount = 0;
+	pSMB->DataOffset = 0;
+	pSMB->SetupCount = 1;
+	pSMB->Reserved3 = 0;
+	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
+	byte_count = params + 1 /* pad */ ;
+	pSMB->TotalParameterCount = cpu_to_le16(params);
+	pSMB->ParameterCount = pSMB->TotalParameterCount;
+	pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
+	pSMB->Reserved4 = 0;
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
+
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cFYI(1, ("Send error in Query EA = %d", rc));
+	} else {		/* decode response */
+		rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+		/* BB also check enough total bytes returned */
+		/* BB we need to improve the validity checking
+		of these trans2 responses */
+		if (rc || (pSMBr->ByteCount < 4)) 
+			rc = -EIO;	/* bad smb */
+	   /* else if (pFindData){
+			memcpy((char *) pFindData,
+			       (char *) &pSMBr->hdr.Protocol +
+			       data_offset, kl);
+		}*/ else {
+			/* check that length of list is not more than bcc */
+			/* check that each entry does not go beyond length
+			   of list */
+			/* check that each element of each entry does not
+			   go beyond end of list */
+			__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+			struct fealist * ea_response_data;
+			rc = -ENODATA;
+			/* validate_trans2_offsets() */
+			/* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
+			ea_response_data = (struct fealist *)
+				(((char *) &pSMBr->hdr.Protocol) +
+				data_offset);
+			name_len = le32_to_cpu(ea_response_data->list_len);
+			cFYI(1,("ea length %d", name_len));
+			if(name_len <= 8) {
+			/* returned EA size zeroed at top of function */
+				cFYI(1,("empty EA list returned from server"));
+			} else {
+				/* account for ea list len */
+				name_len -= 4;
+				temp_fea = ea_response_data->list;
+				temp_ptr = (char *)temp_fea;
+				/* loop through checking if we have a matching
+				name and then return the associated value */
+				while(name_len > 0) {
+					__u16 value_len;
+					name_len -= 4;
+					temp_ptr += 4;
+					value_len = le16_to_cpu(temp_fea->value_len);
+				/* BB validate that value_len falls within SMB, 
+				even though maximum for name_len is 255 */ 
+					if(memcmp(temp_fea->name,ea_name,
+						  temp_fea->name_len) == 0) {
+						/* found a match */
+						rc = value_len;
+				/* account for prefix user. and trailing null */
+						if(rc<=(int)buf_size) {
+							memcpy(ea_value,
+								temp_fea->name+temp_fea->name_len+1,
+								rc);
+							/* ea values, unlike ea names,
+							are not null terminated */
+						} else if(buf_size == 0) {
+						/* skip copy - calc size only */
+						} else {
+							/* stop before overrun buffer */
+							rc = -ERANGE;
+						}
+						break;
+					}
+					name_len -= temp_fea->name_len;
+					temp_ptr += temp_fea->name_len;
+					/* account for trailing null */
+					name_len--;
+					temp_ptr++;
+					name_len -= value_len;
+					temp_ptr += value_len;
+				/* no trailing null to account for in value len */
+					/* go on to next EA */
+					temp_fea = (struct fea *)temp_ptr;
+				}
+			} 
+		}
+	}
+	if (pSMB)
+		cifs_buf_release(pSMB);
+	if (rc == -EAGAIN)
+		goto QEARetry;
+
+	return (ssize_t)rc;
+}
+
+int
+CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
+		const char * ea_name, const void * ea_value, 
+		const __u16 ea_value_len, const struct nls_table *nls_codepage)
+{
+	struct smb_com_transaction2_spi_req *pSMB = NULL;
+	struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
+	struct fealist *parm_data;
+	int name_len;
+	int rc = 0;
+	int bytes_returned = 0;
+	__u16 params, param_offset, byte_count, offset, count;
+
+	cFYI(1, ("In SetEA"));
+SetEARetry:
+	rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+		name_len =
+		    cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
+				  /* find define for this maxpathcomponent */
+				  , nls_codepage);
+		name_len++;	/* trailing null */
+		name_len *= 2;
+	} else {		/* BB improve the check for buffer overruns BB */
+		name_len = strnlen(fileName, PATH_MAX);
+		name_len++;	/* trailing null */
+		strncpy(pSMB->FileName, fileName, name_len);
+	}
+
+	params = 6 + name_len;
+
+	/* done calculating parms using name_len of file name,
+	now use name_len to calculate length of ea name
+	we are going to create in the inode xattrs */
+	if(ea_name == NULL)
+		name_len = 0;
+	else
+		name_len = strnlen(ea_name,255);
+
+	count = sizeof(*parm_data) + ea_value_len + name_len + 1;
+	pSMB->MaxParameterCount = cpu_to_le16(2);
+	pSMB->MaxDataCount = cpu_to_le16(1000);	/* BB find max SMB size from sess */
+	pSMB->MaxSetupCount = 0;
+	pSMB->Reserved = 0;
+	pSMB->Flags = 0;
+	pSMB->Timeout = 0;
+	pSMB->Reserved2 = 0;
+	param_offset = offsetof(struct smb_com_transaction2_spi_req,
+                                     InformationLevel) - 4;
+	offset = param_offset + params;
+	pSMB->InformationLevel =
+		cpu_to_le16(SMB_SET_FILE_EA);
+
+	parm_data =
+		(struct fealist *) (((char *) &pSMB->hdr.Protocol) +
+				       offset);
+	pSMB->ParameterOffset = cpu_to_le16(param_offset);
+	pSMB->DataOffset = cpu_to_le16(offset);
+	pSMB->SetupCount = 1;
+	pSMB->Reserved3 = 0;
+	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
+	byte_count = 3 /* pad */  + params + count;
+	pSMB->DataCount = cpu_to_le16(count);
+	parm_data->list_len = cpu_to_le32(count);
+	parm_data->list[0].EA_flags = 0;
+	/* we checked above that name len is less than 255 */
+	parm_data->list[0].name_len = (__u8)name_len;;
+	/* EA names are always ASCII */
+	if(ea_name)
+		strncpy(parm_data->list[0].name,ea_name,name_len);
+	parm_data->list[0].name[name_len] = 0;
+	parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
+	/* caller ensures that ea_value_len is less than 64K but
+	we need to ensure that it fits within the smb */
+
+	/*BB add length check that it would fit in negotiated SMB buffer size BB */
+	/* if(ea_value_len > buffer_size - 512 (enough for header)) */
+	if(ea_value_len)
+		memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
+
+	pSMB->TotalDataCount = pSMB->DataCount;
+	pSMB->ParameterCount = cpu_to_le16(params);
+	pSMB->TotalParameterCount = pSMB->ParameterCount;
+	pSMB->Reserved4 = 0;
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cFYI(1, ("SetPathInfo (EA) returned %d", rc));
+	}
+
+	cifs_buf_release(pSMB);
+
+	if (rc == -EAGAIN)
+		goto SetEARetry;
+
+	return rc;
+}
+
+#endif
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
new file mode 100644
index 0000000..40470b9
--- /dev/null
+++ b/fs/cifs/connect.c
@@ -0,0 +1,3064 @@
+/*
+ *   fs/cifs/connect.c
+ *
+ *   Copyright (C) International Business Machines  Corp., 2002,2004
+ *   Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ */
+#include <linux/fs.h>
+#include <linux/net.h>
+#include <linux/string.h>
+#include <linux/list.h>
+#include <linux/wait.h>
+#include <linux/ipv6.h>
+#include <linux/pagemap.h>
+#include <linux/ctype.h>
+#include <linux/utsname.h>
+#include <linux/mempool.h>
+#include <asm/uaccess.h>
+#include <asm/processor.h>
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_unicode.h"
+#include "cifs_debug.h"
+#include "cifs_fs_sb.h"
+#include "ntlmssp.h"
+#include "nterr.h"
+#include "rfc1002pdu.h"
+
+#define CIFS_PORT 445
+#define RFC1001_PORT 139
+
+extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
+		       unsigned char *p24);
+extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
+			 unsigned char *p24);
+
+extern mempool_t *cifs_req_poolp;
+
+struct smb_vol {
+	char *username;
+	char *password;
+	char *domainname;
+	char *UNC;
+	char *UNCip;
+	char *in6_addr;  /* ipv6 address as human readable form of in6_addr */
+	char *iocharset;  /* local code page for mapping to and from Unicode */
+	char source_rfc1001_name[16]; /* netbios name of client */
+	uid_t linux_uid;
+	gid_t linux_gid;
+	mode_t file_mode;
+	mode_t dir_mode;
+	unsigned rw:1;
+	unsigned retry:1;
+	unsigned intr:1;
+	unsigned setuids:1;
+	unsigned noperm:1;
+	unsigned no_psx_acl:1; /* set if posix acl support should be disabled */
+	unsigned no_xattr:1;   /* set if xattr (EA) support should be disabled*/
+	unsigned server_ino:1; /* use inode numbers from server ie UniqueId */
+	unsigned direct_io:1;
+	unsigned int rsize;
+	unsigned int wsize;
+	unsigned int sockopt;
+	unsigned short int port;
+};
+
+static int ipv4_connect(struct sockaddr_in *psin_server, 
+			struct socket **csocket,
+			char * netb_name);
+static int ipv6_connect(struct sockaddr_in6 *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
+	 * 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;
+	struct cifsTconInfo *tcon;
+	struct mid_q_entry * mid_entry;
+	
+	spin_lock(&GlobalMid_Lock);
+	if(server->tcpStatus == CifsExiting) {
+		/* the demux thread will exit normally 
+		next time through the loop */
+		spin_unlock(&GlobalMid_Lock);
+		return rc;
+	} else
+		server->tcpStatus = CifsNeedReconnect;
+	spin_unlock(&GlobalMid_Lock);
+	server->maxBuf = 0;
+
+	cFYI(1, ("Reconnecting tcp session "));
+
+	/* before reconnecting the tcp session, mark the smb session (uid)
+		and the tid bad so they are not used until reconnected */
+	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;
+				ses->ipc_tid = 0;
+			}
+		}
+		/* else tcp and smb sessions need reconnection */
+	}
+	list_for_each(tmp, &GlobalTreeConnectionList) {
+		tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
+		if((tcon) && (tcon->ses) && (tcon->ses->server == server)) {
+			tcon->tidStatus = CifsNeedReconnect;
+		}
+	}
+	read_unlock(&GlobalSMBSeslock);
+	/* do not want to be sending data on a socket we are freeing */
+	down(&server->tcpSem); 
+	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;
+	}
+
+	spin_lock(&GlobalMid_Lock);
+	list_for_each(tmp, &server->pending_mid_q) {
+		mid_entry = list_entry(tmp, struct
+					mid_q_entry,
+					qhead);
+		if(mid_entry) {
+			if(mid_entry->midState == MID_REQUEST_SUBMITTED) {
+				/* Mark other intransit requests as needing retry so 
+				  we do not immediately mark the session bad again 
+				  (ie after we reconnect below) as they timeout too */
+				mid_entry->midState = MID_RETRY_NEEDED;
+			}
+		}
+	}
+	spin_unlock(&GlobalMid_Lock);
+	up(&server->tcpSem); 
+
+	while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
+	{
+		if(server->protocolType == IPV6) {
+			rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket);
+		} else {
+			rc = ipv4_connect(&server->addr.sockAddr, 
+					&server->ssocket,
+					server->workstation_RFC1001_name);
+		}
+		if(rc) {
+			set_current_state(TASK_INTERRUPTIBLE);
+			schedule_timeout(3 * HZ);
+		} else {
+			atomic_inc(&tcpSesReconnectCount);
+			spin_lock(&GlobalMid_Lock);
+			if(server->tcpStatus != CifsExiting)
+				server->tcpStatus = CifsGood;
+			spin_unlock(&GlobalMid_Lock);
+	/*		atomic_set(&server->inFlight,0);*/
+			wake_up(&server->response_q);
+		}
+	}
+	return rc;
+}
+
+static int
+cifs_demultiplex_thread(struct TCP_Server_Info *server)
+{
+	int length;
+	unsigned int pdu_length, total_read;
+	struct smb_hdr *smb_buffer = NULL;
+	struct msghdr smb_msg;
+	struct kvec iov;
+	struct socket *csocket = server->ssocket;
+	struct list_head *tmp;
+	struct cifsSesInfo *ses;
+	struct task_struct *task_to_wake = NULL;
+	struct mid_q_entry *mid_entry;
+	char *temp;
+
+	daemonize("cifsd");
+	allow_signal(SIGKILL);
+	current->flags |= PF_MEMALLOC;
+	server->tsk = current;	/* save process info to wake at shutdown */
+	cFYI(1, ("Demultiplex PID: %d", current->pid));
+	write_lock(&GlobalSMBSeslock); 
+	atomic_inc(&tcpSesAllocCount);
+	length = tcpSesAllocCount.counter;
+	write_unlock(&GlobalSMBSeslock);
+	if(length  > 1) {
+		mempool_resize(cifs_req_poolp,
+			length + cifs_min_rcv,
+			GFP_KERNEL);
+	}
+
+	while (server->tcpStatus != CifsExiting) {
+		if (smb_buffer == NULL)
+			smb_buffer = cifs_buf_get();
+		else
+			memset(smb_buffer, 0, sizeof (struct smb_hdr));
+
+		if (smb_buffer == NULL) {
+			cERROR(1,("Can not get memory for SMB response"));
+			set_current_state(TASK_INTERRUPTIBLE);
+			schedule_timeout(HZ * 3); /* give system time to free memory */
+			continue;
+		}
+		iov.iov_base = smb_buffer;
+		iov.iov_len = 4;
+		smb_msg.msg_control = NULL;
+		smb_msg.msg_controllen = 0;
+		length =
+		    kernel_recvmsg(csocket, &smb_msg,
+				 &iov, 1, 4, 0 /* BB see socket.h flags */);
+
+		if(server->tcpStatus == CifsExiting) {
+			break;
+		} else if (server->tcpStatus == CifsNeedReconnect) {
+			cFYI(1,("Reconnecting after server stopped responding"));
+			cifs_reconnect(server);
+			cFYI(1,("call to reconnect done"));
+			csocket = server->ssocket;
+			continue;
+		} else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
+			set_current_state(TASK_INTERRUPTIBLE);
+			schedule_timeout(1); /* minimum sleep to prevent looping
+				allowing socket to clear and app threads to set
+				tcpStatus CifsNeedReconnect if server hung */
+			continue;
+		} else if (length <= 0) {
+			if(server->tcpStatus == CifsNew) {
+				cFYI(1,("tcp session abended prematurely (after SMBnegprot)"));
+				/* some servers kill tcp session rather than returning
+					smb negprot error in which case reconnecting here is
+					not going to help - return error to mount */
+				break;
+			}
+			if(length == -EINTR) { 
+				cFYI(1,("cifsd thread killed"));
+				break;
+			}
+			cFYI(1,("Reconnecting after unexpected peek error %d",length));
+			cifs_reconnect(server);
+			csocket = server->ssocket;
+			wake_up(&server->response_q);
+			continue;
+		} else if (length > 3) {
+			pdu_length = ntohl(smb_buffer->smb_buf_length);
+		/* Only read pdu_length after below checks for too short (due
+		   to e.g. int overflow) and too long ie beyond end of buf */
+			cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4));
+
+			temp = (char *) smb_buffer;
+			if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
+				cFYI(0,("Received 4 byte keep alive packet"));
+			} else if (temp[0] == (char) RFC1002_POSITIVE_SESSION_RESPONSE) {
+					cFYI(1,("Good RFC 1002 session rsp"));
+			} else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
+				/* we get this from Windows 98 instead of error on SMB negprot response */
+				cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4]));
+				if(server->tcpStatus == CifsNew) {
+					/* if nack on negprot (rather than 
+					ret of smb negprot error) reconnecting
+					not going to help, ret error to mount */
+					break;
+				} else {
+					/* give server a second to
+					clean up before reconnect attempt */
+					set_current_state(TASK_INTERRUPTIBLE);
+					schedule_timeout(HZ);
+					/* always try 445 first on reconnect
+					since we get NACK on some if we ever
+					connected to port 139 (the NACK is 
+					since we do not begin with RFC1001
+					session initialize frame) */
+					server->addr.sockAddr.sin_port = htons(CIFS_PORT);
+					cifs_reconnect(server);
+					csocket = server->ssocket;
+					wake_up(&server->response_q);
+					continue;
+				}
+			} else if (temp[0] != (char) 0) {
+				cERROR(1,("Unknown RFC 1002 frame"));
+				cifs_dump_mem(" Received Data: ", temp, length);
+				cifs_reconnect(server);
+				csocket = server->ssocket;
+				continue;
+			} else {
+				if((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)
+				    || (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {
+					cERROR(1,
+					    ("Invalid size SMB length %d and pdu_length %d",
+						length, pdu_length+4));
+					cifs_reconnect(server);
+					csocket = server->ssocket;
+					wake_up(&server->response_q);
+					continue;
+				} else { /* length ok */
+					length = 0;
+					iov.iov_base = 4 + (char *)smb_buffer;
+					iov.iov_len = pdu_length;
+					for (total_read = 0; 
+					     total_read < pdu_length;
+					     total_read += length) {
+						length = kernel_recvmsg(csocket, &smb_msg, 
+							&iov, 1,
+							pdu_length - total_read, 0);
+						if (length == 0) {
+							cERROR(1,
+							       ("Zero length receive when expecting %d ",
+								pdu_length - total_read));
+							cifs_reconnect(server);
+							csocket = server->ssocket;
+							wake_up(&server->response_q);
+							continue;
+						}
+					}
+					length += 4; /* account for rfc1002 hdr */
+				}
+
+				dump_smb(smb_buffer, length);
+				if (checkSMB
+				    (smb_buffer, smb_buffer->Mid, total_read+4)) {
+					cERROR(1, ("Bad SMB Received "));
+					continue;
+				}
+
+				task_to_wake = NULL;
+				spin_lock(&GlobalMid_Lock);
+				list_for_each(tmp, &server->pending_mid_q) {
+					mid_entry = list_entry(tmp, struct
+							       mid_q_entry,
+							       qhead);
+
+					if ((mid_entry->mid == smb_buffer->Mid) && (mid_entry->midState == MID_REQUEST_SUBMITTED)) {
+						cFYI(1,
+						     (" Mid 0x%x matched - waking up ",mid_entry->mid));
+						task_to_wake = mid_entry->tsk;
+						mid_entry->resp_buf =
+						    smb_buffer;
+						mid_entry->midState =
+						    MID_RESPONSE_RECEIVED;
+					}
+				}
+				spin_unlock(&GlobalMid_Lock);
+				if (task_to_wake) {
+					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, ("No task to wake, unknown frame rcvd!"));
+					cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
+				}
+			}
+		} else {
+			cFYI(1,
+			    ("Frame less than four bytes received  %d bytes long.",
+			      length));
+			cifs_reconnect(server);
+			csocket = server->ssocket;
+			wake_up(&server->response_q);
+			continue;
+		}
+	}
+	spin_lock(&GlobalMid_Lock);
+	server->tcpStatus = CifsExiting;
+	server->tsk = NULL;
+	atomic_set(&server->inFlight, 0);
+	spin_unlock(&GlobalMid_Lock);
+	/* Although there should not be any requests blocked on 
+	this queue it can not hurt to be paranoid and try to wake up requests
+	that may haven been blocked when more than 50 at time were on the wire 
+	to the same server - they now will see the session is in exit state
+	and get out of SendReceive.  */
+	wake_up_all(&server->request_q);
+	/* give those requests time to exit */
+	set_current_state(TASK_INTERRUPTIBLE);
+	schedule_timeout(HZ/8);
+
+	if(server->ssocket) {
+		sock_release(csocket);
+		server->ssocket = NULL;
+	}
+	if (smb_buffer) /* buffer usually freed in free_mid - need to free it on error or exit */
+		cifs_buf_release(smb_buffer);
+
+	read_lock(&GlobalSMBSeslock);
+	if (list_empty(&server->pending_mid_q)) {
+		/* loop through server session structures attached to this and mark them dead */
+		list_for_each(tmp, &GlobalSMBSessionList) {
+			ses =
+			    list_entry(tmp, struct cifsSesInfo,
+				       cifsSessionList);
+			if (ses->server == server) {
+				ses->status = CifsExiting;
+				ses->server = NULL;
+			}
+		}
+		read_unlock(&GlobalSMBSeslock);
+	} else {
+		spin_lock(&GlobalMid_Lock);
+		list_for_each(tmp, &server->pending_mid_q) {
+		mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
+			if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
+				cFYI(1,
+					 (" Clearing Mid 0x%x - waking up ",mid_entry->mid));
+				task_to_wake = mid_entry->tsk;
+				if(task_to_wake) {
+					wake_up_process(task_to_wake);
+				}
+			}
+		}
+		spin_unlock(&GlobalMid_Lock);
+		read_unlock(&GlobalSMBSeslock);
+		set_current_state(TASK_INTERRUPTIBLE);
+		/* 1/8th of sec is more than enough time for them to exit */
+		schedule_timeout(HZ/8); 
+	}
+
+	if (list_empty(&server->pending_mid_q)) {
+		/* mpx threads have not exited yet give them 
+		at least the smb send timeout time for long ops */
+		cFYI(1, ("Wait for exit from demultiplex thread"));
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(46 * HZ);	
+		/* if threads still have not exited they are probably never
+		coming home not much else we can do but free the memory */
+	}
+	kfree(server);
+
+	write_lock(&GlobalSMBSeslock);
+	atomic_dec(&tcpSesAllocCount);
+	length = tcpSesAllocCount.counter;
+	write_unlock(&GlobalSMBSeslock);
+	if(length  > 0) {
+		mempool_resize(cifs_req_poolp,
+			length + cifs_min_rcv,
+			GFP_KERNEL);
+	}
+
+	set_current_state(TASK_INTERRUPTIBLE);
+	schedule_timeout(HZ/4);
+	return 0;
+}
+
+static void * 
+cifs_kcalloc(size_t size, unsigned int __nocast type)
+{
+	void *addr;
+	addr = kmalloc(size, type);
+	if (addr)
+		memset(addr, 0, size);
+	return addr;
+}
+
+static int
+cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
+{
+	char *value;
+	char *data;
+	unsigned int  temp_len, i, j;
+	char separator[2];
+
+	separator[0] = ',';
+	separator[1] = 0; 
+
+	memset(vol->source_rfc1001_name,0x20,15);
+	for(i=0;i < strnlen(system_utsname.nodename,15);i++) {
+		/* does not have to be a perfect mapping since the field is
+		informational, only used for servers that do not support
+		port 445 and it can be overridden at mount time */
+		vol->source_rfc1001_name[i] = toupper(system_utsname.nodename[i]);
+	}
+	vol->source_rfc1001_name[15] = 0;
+
+	vol->linux_uid = current->uid;	/* current->euid instead? */
+	vol->linux_gid = current->gid;
+	vol->dir_mode = S_IRWXUGO;
+	/* 2767 perms indicate mandatory locking support */
+	vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
+
+	/* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
+	vol->rw = TRUE;
+
+	if (!options)
+		return 1;
+
+	if(strncmp(options,"sep=",4) == 0) {
+		if(options[4] != 0) {
+			separator[0] = options[4];
+			options += 5;
+		} else {
+			cFYI(1,("Null separator not allowed"));
+		}
+	}
+		
+	while ((data = strsep(&options, separator)) != NULL) {
+		if (!*data)
+			continue;
+		if ((value = strchr(data, '=')) != NULL)
+			*value++ = '\0';
+
+		if (strnicmp(data, "user_xattr",10) == 0) {/*parse before user*/
+			vol->no_xattr = 0;
+		} else if (strnicmp(data, "nouser_xattr",12) == 0) {
+			vol->no_xattr = 1;
+		} else if (strnicmp(data, "user", 4) == 0) {
+			if (!value || !*value) {
+				printk(KERN_WARNING
+				       "CIFS: invalid or missing username\n");
+				return 1;	/* needs_arg; */
+			}
+			if (strnlen(value, 200) < 200) {
+				vol->username = value;
+			} else {
+				printk(KERN_WARNING "CIFS: username too long\n");
+				return 1;
+			}
+		} else if (strnicmp(data, "pass", 4) == 0) {
+			if (!value) {
+				vol->password = NULL;
+				continue;
+			} else if(value[0] == 0) {
+				/* check if string begins with double comma
+				   since that would mean the password really
+				   does start with a comma, and would not
+				   indicate an empty string */
+				if(value[1] != separator[0]) {
+					vol->password = NULL;
+					continue;
+				}
+			}
+			temp_len = strlen(value);
+			/* removed password length check, NTLM passwords
+				can be arbitrarily long */
+
+			/* if comma in password, the string will be 
+			prematurely null terminated.  Commas in password are
+			specified across the cifs mount interface by a double
+			comma ie ,, and a comma used as in other cases ie ','
+			as a parameter delimiter/separator is single and due
+			to the strsep above is temporarily zeroed. */
+
+			/* NB: password legally can have multiple commas and
+			the only illegal character in a password is null */
+
+			if ((value[temp_len] == 0) && (value[temp_len+1] == separator[0])) {
+				/* reinsert comma */
+				value[temp_len] = separator[0];
+				temp_len+=2;  /* move after the second comma */
+				while(value[temp_len] != 0)  {
+					if (value[temp_len] == separator[0]) {
+						if (value[temp_len+1] == separator[0]) {
+							temp_len++; /* skip second comma */
+						} else { 
+						/* single comma indicating start
+							 of next parm */
+							break;
+						}
+					}
+					temp_len++;
+				}
+				if(value[temp_len] == 0) {
+					options = NULL;
+				} else {
+					value[temp_len] = 0;
+					/* point option to start of next parm */
+					options = value + temp_len + 1;
+				}
+				/* go from value to value + temp_len condensing 
+				double commas to singles. Note that this ends up
+				allocating a few bytes too many, which is ok */
+				vol->password = cifs_kcalloc(temp_len, GFP_KERNEL);
+				for(i=0,j=0;i<temp_len;i++,j++) {
+					vol->password[j] = value[i];
+					if(value[i] == separator[0] && value[i+1] == separator[0]) {
+						/* skip second comma */
+						i++;
+					}
+				}
+				vol->password[j] = 0;
+			} else {
+				vol->password = cifs_kcalloc(temp_len + 1, GFP_KERNEL);
+				strcpy(vol->password, value);
+			}
+		} else if (strnicmp(data, "ip", 2) == 0) {
+			if (!value || !*value) {
+				vol->UNCip = NULL;
+			} else if (strnlen(value, 35) < 35) {
+				vol->UNCip = value;
+			} else {
+				printk(KERN_WARNING "CIFS: ip address 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_WARNING
+				       "CIFS: invalid path to network resource\n");
+				return 1;	/* needs_arg; */
+			}
+			if ((temp_len = strnlen(value, 300)) < 300) {
+				vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
+				if(vol->UNC == NULL)
+					return 1;
+				strcpy(vol->UNC,value);
+				if (strncmp(vol->UNC, "//", 2) == 0) {
+					vol->UNC[0] = '\\';
+					vol->UNC[1] = '\\';
+				} else if (strncmp(vol->UNC, "\\\\", 2) != 0) {	                   
+					printk(KERN_WARNING
+					       "CIFS: UNC Path does not begin with // or \\\\ \n");
+					return 1;
+				}
+			} else {
+				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_WARNING "CIFS: invalid domain name\n");
+				return 1;	/* needs_arg; */
+			}
+			/* BB are there cases in which a comma can be valid in
+			a domain name and need special handling? */
+			if (strnlen(value, 65) < 65) {
+				vol->domainname = value;
+				cFYI(1, ("Domain name set"));
+			} else {
+				printk(KERN_WARNING "CIFS: domain name too long\n");
+				return 1;
+			}
+		} else if (strnicmp(data, "iocharset", 9) == 0) {
+			if (!value || !*value) {
+				printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
+				return 1;	/* needs_arg; */
+			}
+			if (strnlen(value, 65) < 65) {
+				if(strnicmp(value,"default",7))
+					vol->iocharset = value;
+				/* if iocharset not set load_nls_default used by caller */
+				cFYI(1, ("iocharset set to %s",value));
+			} else {
+				printk(KERN_WARNING "CIFS: iocharset name too long.\n");
+				return 1;
+			}
+		} else if (strnicmp(data, "uid", 3) == 0) {
+			if (value && *value) {
+				vol->linux_uid =
+					simple_strtoul(value, &value, 0);
+			}
+		} else if (strnicmp(data, "gid", 3) == 0) {
+			if (value && *value) {
+				vol->linux_gid =
+					simple_strtoul(value, &value, 0);
+			}
+		} else if (strnicmp(data, "file_mode", 4) == 0) {
+			if (value && *value) {
+				vol->file_mode =
+					simple_strtoul(value, &value, 0);
+			}
+		} else if (strnicmp(data, "dir_mode", 4) == 0) {
+			if (value && *value) {
+				vol->dir_mode =
+					simple_strtoul(value, &value, 0);
+			}
+		} else if (strnicmp(data, "dirmode", 4) == 0) {
+			if (value && *value) {
+				vol->dir_mode =
+					simple_strtoul(value, &value, 0);
+			}
+		} else if (strnicmp(data, "port", 4) == 0) {
+			if (value && *value) {
+				vol->port =
+					simple_strtoul(value, &value, 0);
+			}
+		} else if (strnicmp(data, "rsize", 5) == 0) {
+			if (value && *value) {
+				vol->rsize =
+					simple_strtoul(value, &value, 0);
+			}
+		} else if (strnicmp(data, "wsize", 5) == 0) {
+			if (value && *value) {
+				vol->wsize =
+					simple_strtoul(value, &value, 0);
+			}
+		} else if (strnicmp(data, "sockopt", 5) == 0) {
+			if (value && *value) {
+				vol->sockopt =
+					simple_strtoul(value, &value, 0);
+			}
+		} else if (strnicmp(data, "netbiosname", 4) == 0) {
+			if (!value || !*value || (*value == ' ')) {
+				cFYI(1,("invalid (empty) netbiosname specified"));
+			} else {
+				memset(vol->source_rfc1001_name,0x20,15);
+				for(i=0;i<15;i++) {
+				/* BB are there cases in which a comma can be 
+				valid in this workstation netbios name (and need
+				special handling)? */
+
+				/* We do not uppercase netbiosname for user */
+					if (value[i]==0)
+						break;
+					else 
+						vol->source_rfc1001_name[i] = value[i];
+				}
+				/* The string has 16th byte zero still from
+				set at top of the function  */
+				if((i==15) && (value[i] != 0))
+					printk(KERN_WARNING "CIFS: netbiosname longer than 15 and was truncated.\n");
+			}
+		} else if (strnicmp(data, "credentials", 4) == 0) {
+			/* ignore */
+		} else if (strnicmp(data, "version", 3) == 0) {
+			/* ignore */
+		} else if (strnicmp(data, "guest",5) == 0) {
+			/* ignore */
+		} else if (strnicmp(data, "rw", 2) == 0) {
+			vol->rw = TRUE;
+		} else if ((strnicmp(data, "suid", 4) == 0) ||
+				   (strnicmp(data, "nosuid", 6) == 0) ||
+				   (strnicmp(data, "exec", 4) == 0) ||
+				   (strnicmp(data, "noexec", 6) == 0) ||
+				   (strnicmp(data, "nodev", 5) == 0) ||
+				   (strnicmp(data, "noauto", 6) == 0) ||
+				   (strnicmp(data, "dev", 3) == 0)) {
+			/*  The mount tool or mount.cifs helper (if present)
+				uses these opts to set flags, and the flags are read
+				by the kernel vfs layer before we get here (ie
+				before read super) so there is no point trying to
+				parse these options again and set anything and it
+				is ok to just ignore them */
+			continue;
+		} else if (strnicmp(data, "ro", 2) == 0) {
+			vol->rw = FALSE;
+		} else if (strnicmp(data, "hard", 4) == 0) {
+			vol->retry = 1;
+		} else if (strnicmp(data, "soft", 4) == 0) {
+			vol->retry = 0;
+		} else if (strnicmp(data, "perm", 4) == 0) {
+			vol->noperm = 0;
+		} else if (strnicmp(data, "noperm", 6) == 0) {
+			vol->noperm = 1;
+		} else if (strnicmp(data, "setuids", 7) == 0) {
+			vol->setuids = 1;
+		} else if (strnicmp(data, "nosetuids", 9) == 0) {
+			vol->setuids = 0;
+		} else if (strnicmp(data, "nohard", 6) == 0) {
+			vol->retry = 0;
+		} else if (strnicmp(data, "nosoft", 6) == 0) {
+			vol->retry = 1;
+		} else if (strnicmp(data, "nointr", 6) == 0) {
+			vol->intr = 0;
+		} else if (strnicmp(data, "intr", 4) == 0) {
+			vol->intr = 1;
+		} else if (strnicmp(data, "serverino",7) == 0) {
+			vol->server_ino = 1;
+		} else if (strnicmp(data, "noserverino",9) == 0) {
+			vol->server_ino = 0;
+		} else if (strnicmp(data, "acl",3) == 0) {
+			vol->no_psx_acl = 0;
+		} else if (strnicmp(data, "noacl",5) == 0) {
+			vol->no_psx_acl = 1;
+		} else if (strnicmp(data, "direct",6) == 0) {
+			vol->direct_io = 1;
+		} else if (strnicmp(data, "forcedirectio",13) == 0) {
+			vol->direct_io = 1;
+		} else if (strnicmp(data, "in6_addr",8) == 0) {
+			if (!value || !*value) {
+				vol->in6_addr = NULL;
+			} else if (strnlen(value, 49) == 48) {
+				vol->in6_addr = value;
+			} else {
+				printk(KERN_WARNING "CIFS: ip v6 address not 48 characters long\n");
+				return 1;
+			}
+		} else if (strnicmp(data, "noac", 4) == 0) {
+			printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
+		} else
+			printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
+	}
+	if (vol->UNC == NULL) {
+		if(devname == NULL) {
+			printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
+			return 1;
+		}
+		if ((temp_len = strnlen(devname, 300)) < 300) {
+			vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
+			if(vol->UNC == NULL)
+				return 1;
+			strcpy(vol->UNC,devname);
+			if (strncmp(vol->UNC, "//", 2) == 0) {
+				vol->UNC[0] = '\\';
+				vol->UNC[1] = '\\';
+			} else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
+				printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
+				return 1;
+			}
+		} else {
+			printk(KERN_WARNING "CIFS: UNC name too long\n");
+			return 1;
+		}
+	}
+	if(vol->UNCip == NULL)
+		vol->UNCip = &vol->UNC[2];
+
+	return 0;
+}
+
+static struct cifsSesInfo *
+cifs_find_tcp_session(struct in_addr * target_ip_addr, 
+		struct in6_addr *target_ip6_addr,
+		 char *userName, struct TCP_Server_Info **psrvTcp)
+{
+	struct list_head *tmp;
+	struct cifsSesInfo *ses;
+	*psrvTcp = NULL;
+	read_lock(&GlobalSMBSeslock);
+
+	list_for_each(tmp, &GlobalSMBSessionList) {
+		ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
+		if (ses->server) {
+			if((target_ip_addr && 
+				(ses->server->addr.sockAddr.sin_addr.s_addr
+				  == target_ip_addr->s_addr)) || (target_ip6_addr
+				&& memcmp(&ses->server->addr.sockAddr6.sin6_addr,
+					target_ip6_addr,sizeof(*target_ip6_addr)))){
+				/* BB lock server and tcp session and increment use count here?? */
+				*psrvTcp = ses->server;	/* found a match on the TCP session */
+				/* BB check if reconnection needed */
+				if (strncmp
+				    (ses->userName, userName,
+				     MAX_USERNAME_SIZE) == 0){
+					read_unlock(&GlobalSMBSeslock);
+					return ses;	/* found exact match on both tcp and SMB sessions */
+				}
+			}
+		}
+		/* else tcp and smb sessions need reconnection */
+	}
+	read_unlock(&GlobalSMBSeslock);
+	return NULL;
+}
+
+static struct cifsTconInfo *
+find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
+{
+	struct list_head *tmp;
+	struct cifsTconInfo *tcon;
+
+	read_lock(&GlobalSMBSeslock);
+	list_for_each(tmp, &GlobalTreeConnectionList) {
+		cFYI(1, ("Next tcon - "));
+		tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
+		if (tcon->ses) {
+			if (tcon->ses->server) {
+				cFYI(1,
+				     (" old ip addr: %x == new ip %x ?",
+				      tcon->ses->server->addr.sockAddr.sin_addr.
+				      s_addr, new_target_ip_addr));
+				if (tcon->ses->server->addr.sockAddr.sin_addr.
+				    s_addr == new_target_ip_addr) {
+	/* BB lock tcon and server and tcp session and increment use count here? */
+					/* found a match on the TCP session */
+					/* BB check if reconnection needed */
+					cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
+					      tcon->treeName, uncName));
+					if (strncmp
+					    (tcon->treeName, uncName,
+					     MAX_TREE_SIZE) == 0) {
+						cFYI(1,
+						     ("Matched UNC, old user: %s == new: %s ?",
+						      tcon->treeName, uncName));
+						if (strncmp
+						    (tcon->ses->userName,
+						     userName,
+						     MAX_USERNAME_SIZE) == 0) {
+							read_unlock(&GlobalSMBSeslock);
+							return tcon;/* also matched user (smb session)*/
+						}
+					}
+				}
+			}
+		}
+	}
+	read_unlock(&GlobalSMBSeslock);
+	return NULL;
+}
+
+int
+connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
+		    const char *old_path, const struct nls_table *nls_codepage)
+{
+	unsigned char *referrals = NULL;
+	unsigned int num_referrals;
+	int rc = 0;
+
+	rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage, 
+			&num_referrals, &referrals);
+
+	/* BB Add in code to: if valid refrl, if not ip address contact
+		the helper that resolves tcp names, mount to it, try to 
+		tcon to it unmount it if fail */
+
+	if(referrals)
+		kfree(referrals);
+
+	return rc;
+}
+
+int
+get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
+			const char *old_path, const struct nls_table *nls_codepage, 
+			unsigned int *pnum_referrals, unsigned char ** preferrals)
+{
+	char *temp_unc;
+	int rc = 0;
+
+	*pnum_referrals = 0;
+
+	if (pSesInfo->ipc_tid == 0) {
+		temp_unc = kmalloc(2 /* for slashes */ +
+			strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
+				 + 1 + 4 /* slash IPC$ */  + 2,
+				GFP_KERNEL);
+		if (temp_unc == NULL)
+			return -ENOMEM;
+		temp_unc[0] = '\\';
+		temp_unc[1] = '\\';
+		strcpy(temp_unc + 2, pSesInfo->serverName);
+		strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
+		rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
+		cFYI(1,
+		     ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
+		kfree(temp_unc);
+	}
+	if (rc == 0)
+		rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
+				     pnum_referrals, nls_codepage);
+
+	return rc;
+}
+
+/* See RFC1001 section 14 on representation of Netbios names */
+static void rfc1002mangle(char * target,char * source, unsigned int length)
+{
+	unsigned int i,j;
+
+	for(i=0,j=0;i<(length);i++) {
+		/* mask a nibble at a time and encode */
+		target[j] = 'A' + (0x0F & (source[i] >> 4));
+		target[j+1] = 'A' + (0x0F & source[i]);
+		j+=2;
+	}
+
+}
+
+
+static int
+ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, 
+			 char * netbios_name)
+{
+	int rc = 0;
+	int connected = 0;
+	__be16 orig_port = 0;
+
+	if(*csocket == NULL) {
+		rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
+		if (rc < 0) {
+			cERROR(1, ("Error %d creating socket",rc));
+			*csocket = NULL;
+			return rc;
+		} else {
+		/* BB other socket options to set KEEPALIVE, NODELAY? */
+			cFYI(1,("Socket created"));
+			(*csocket)->sk->sk_allocation = GFP_NOFS; 
+		}
+	}
+
+	psin_server->sin_family = AF_INET;
+	if(psin_server->sin_port) { /* user overrode default port */
+		rc = (*csocket)->ops->connect(*csocket,
+				(struct sockaddr *) psin_server,
+				sizeof (struct sockaddr_in),0);
+		if (rc >= 0)
+			connected = 1;
+	} 
+
+	if(!connected) {
+		/* save original port so we can retry user specified port  
+			later if fall back ports fail this time  */
+		orig_port = psin_server->sin_port;
+
+		/* do not retry on the same port we just failed on */
+		if(psin_server->sin_port != htons(CIFS_PORT)) {
+			psin_server->sin_port = htons(CIFS_PORT);
+
+			rc = (*csocket)->ops->connect(*csocket,
+					(struct sockaddr *) psin_server,
+					sizeof (struct sockaddr_in),0);
+			if (rc >= 0)
+				connected = 1;
+		}
+	}
+	if (!connected) {
+		psin_server->sin_port = htons(RFC1001_PORT);
+		rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
+					      psin_server, sizeof (struct sockaddr_in),0);
+		if (rc >= 0) 
+			connected = 1;
+	}
+
+	/* give up here - unless we want to retry on different
+		protocol families some day */
+	if (!connected) {
+		if(orig_port)
+			psin_server->sin_port = orig_port;
+		cFYI(1,("Error %d connecting to server via ipv4",rc));
+		sock_release(*csocket);
+		*csocket = NULL;
+		return rc;
+	}
+	/* Eventually check for other socket options to change from 
+		the default. sock_setsockopt not used because it expects 
+		user space buffer */
+	(*csocket)->sk->sk_rcvtimeo = 7 * HZ;
+
+	/* send RFC1001 sessinit */
+
+	if(psin_server->sin_port == htons(RFC1001_PORT)) {
+		/* some servers require RFC1001 sessinit before sending
+		negprot - BB check reconnection in case where second 
+		sessinit is sent but no second negprot */
+		struct rfc1002_session_packet * ses_init_buf;
+		struct smb_hdr * smb_buf;
+		ses_init_buf = cifs_kcalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL);
+		if(ses_init_buf) {
+			ses_init_buf->trailer.session_req.called_len = 32;
+			rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
+				DEFAULT_CIFS_CALLED_NAME,16);
+			ses_init_buf->trailer.session_req.calling_len = 32;
+			/* calling name ends in null (byte 16) from old smb
+			convention. */
+			if(netbios_name && (netbios_name[0] !=0)) {
+				rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
+					netbios_name,16);
+			} else {
+				rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
+					"LINUX_CIFS_CLNT",16);
+			}
+			ses_init_buf->trailer.session_req.scope1 = 0;
+			ses_init_buf->trailer.session_req.scope2 = 0;
+			smb_buf = (struct smb_hdr *)ses_init_buf;
+			/* sizeof RFC1002_SESSION_REQUEST with no scope */
+			smb_buf->smb_buf_length = 0x81000044;
+			rc = smb_send(*csocket, smb_buf, 0x44,
+				(struct sockaddr *)psin_server);
+			kfree(ses_init_buf);
+		}
+		/* else the negprot may still work without this 
+		even though malloc failed */
+		
+	}
+		
+	return rc;
+}
+
+static int
+ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
+{
+	int rc = 0;
+	int connected = 0;
+	__be16 orig_port = 0;
+
+	if(*csocket == NULL) {
+		rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
+		if (rc < 0) {
+			cERROR(1, ("Error %d creating ipv6 socket",rc));
+			*csocket = NULL;
+			return rc;
+		} else {
+		/* BB other socket options to set KEEPALIVE, NODELAY? */
+			 cFYI(1,("ipv6 Socket created"));
+			(*csocket)->sk->sk_allocation = GFP_NOFS;
+		}
+	}
+
+	psin_server->sin6_family = AF_INET6;
+
+	if(psin_server->sin6_port) { /* user overrode default port */
+		rc = (*csocket)->ops->connect(*csocket,
+				(struct sockaddr *) psin_server,
+				sizeof (struct sockaddr_in6),0);
+		if (rc >= 0)
+			connected = 1;
+	} 
+
+	if(!connected) {
+		/* save original port so we can retry user specified port  
+			later if fall back ports fail this time  */
+
+		orig_port = psin_server->sin6_port;
+		/* do not retry on the same port we just failed on */
+		if(psin_server->sin6_port != htons(CIFS_PORT)) {
+			psin_server->sin6_port = htons(CIFS_PORT);
+
+			rc = (*csocket)->ops->connect(*csocket,
+					(struct sockaddr *) psin_server,
+					sizeof (struct sockaddr_in6),0);
+			if (rc >= 0)
+				connected = 1;
+		}
+	}
+	if (!connected) {
+		psin_server->sin6_port = htons(RFC1001_PORT);
+		rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
+					 psin_server, sizeof (struct sockaddr_in6),0);
+		if (rc >= 0) 
+			connected = 1;
+	}
+
+	/* give up here - unless we want to retry on different
+		protocol families some day */
+	if (!connected) {
+		if(orig_port)
+			psin_server->sin6_port = orig_port;
+		cFYI(1,("Error %d connecting to server via ipv6",rc));
+		sock_release(*csocket);
+		*csocket = NULL;
+		return rc;
+	}
+	/* Eventually check for other socket options to change from 
+		the default. sock_setsockopt not used because it expects 
+		user space buffer */
+	(*csocket)->sk->sk_rcvtimeo = 7 * HZ;
+		
+	return rc;
+}
+
+int
+cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
+	   char *mount_data, const char *devname)
+{
+	int rc = 0;
+	int xid;
+	int address_type = AF_INET;
+	struct socket *csocket = NULL;
+	struct sockaddr_in sin_server;
+	struct sockaddr_in6 sin_server6;
+	struct smb_vol volume_info;
+	struct cifsSesInfo *pSesInfo = NULL;
+	struct cifsSesInfo *existingCifsSes = NULL;
+	struct cifsTconInfo *tcon = NULL;
+	struct TCP_Server_Info *srvTcp = NULL;
+
+	xid = GetXid();
+
+/* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
+	
+	memset(&volume_info,0,sizeof(struct smb_vol));
+	if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
+		if(volume_info.UNC)
+			kfree(volume_info.UNC);
+		if(volume_info.password)
+			kfree(volume_info.password);
+		FreeXid(xid);
+		return -EINVAL;
+	}
+
+	if (volume_info.username) {
+		/* BB fixme parse for domain name here */
+		cFYI(1, ("Username: %s ", volume_info.username));
+
+	} else {
+		cifserror("No username specified ");
+        /* In userspace mount helper we can get user name from alternate
+           locations such as env variables and files on disk */
+		if(volume_info.UNC)
+			kfree(volume_info.UNC);
+		if(volume_info.password)
+			kfree(volume_info.password);
+		FreeXid(xid);
+		return -EINVAL;
+	}
+
+	if (volume_info.UNCip && volume_info.UNC) {
+		rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
+
+		if(rc <= 0) {
+			/* not ipv4 address, try ipv6 */
+			rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u); 
+			if(rc > 0)
+				address_type = AF_INET6;
+		} else {
+			address_type = AF_INET;
+		}
+       
+		if(rc <= 0) {
+			/* we failed translating address */
+			if(volume_info.UNC)
+				kfree(volume_info.UNC);
+			if(volume_info.password)
+				kfree(volume_info.password);
+			FreeXid(xid);
+			return -EINVAL;
+		}
+
+		cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
+		/* success */
+		rc = 0;
+	} else if (volume_info.UNCip){
+		/* BB using ip addr as server name connect to the DFS root below */
+		cERROR(1,("Connecting to DFS root not implemented yet"));
+		if(volume_info.UNC)
+			kfree(volume_info.UNC);
+		if(volume_info.password)
+			kfree(volume_info.password);
+		FreeXid(xid);
+		return -EINVAL;
+	} else /* which servers DFS root would we conect to */ {
+		cERROR(1,
+		       ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified  "));
+		if(volume_info.UNC)
+			kfree(volume_info.UNC);
+		if(volume_info.password)
+			kfree(volume_info.password);
+		FreeXid(xid);
+		return -EINVAL;
+	}
+
+	/* this is needed for ASCII cp to Unicode converts */
+	if(volume_info.iocharset == NULL) {
+		cifs_sb->local_nls = load_nls_default();
+	/* load_nls_default can not return null */
+	} else {
+		cifs_sb->local_nls = load_nls(volume_info.iocharset);
+		if(cifs_sb->local_nls == NULL) {
+			cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
+			if(volume_info.UNC)
+				kfree(volume_info.UNC);
+			if(volume_info.password)
+				kfree(volume_info.password);
+			FreeXid(xid);
+			return -ELIBACC;
+		}
+	}
+
+	if(address_type == AF_INET)
+		existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
+			NULL /* no ipv6 addr */,
+			volume_info.username, &srvTcp);
+	else if(address_type == AF_INET6)
+		existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
+			&sin_server6.sin6_addr,
+			volume_info.username, &srvTcp);
+	else {
+		if(volume_info.UNC)
+			kfree(volume_info.UNC);
+		if(volume_info.password)
+			kfree(volume_info.password);
+		FreeXid(xid);
+		return -EINVAL;
+	}
+
+
+	if (srvTcp) {
+		cFYI(1, ("Existing tcp session with server found "));                
+	} else {	/* create socket */
+		if(volume_info.port)
+			sin_server.sin_port = htons(volume_info.port);
+		else
+			sin_server.sin_port = 0;
+		rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name);
+		if (rc < 0) {
+			cERROR(1,
+			       ("Error connecting to IPv4 socket. Aborting operation"));
+			if(csocket != NULL)
+				sock_release(csocket);
+			if(volume_info.UNC)
+				kfree(volume_info.UNC);
+			if(volume_info.password)
+				kfree(volume_info.password);
+			FreeXid(xid);
+			return rc;
+		}
+
+		srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
+		if (srvTcp == NULL) {
+			rc = -ENOMEM;
+			sock_release(csocket);
+			if(volume_info.UNC)
+				kfree(volume_info.UNC);
+			if(volume_info.password)
+				kfree(volume_info.password);
+			FreeXid(xid);
+			return rc;
+		} else {
+			memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
+			memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
+			atomic_set(&srvTcp->inFlight,0);
+			/* BB Add code for ipv6 case too */
+			srvTcp->ssocket = csocket;
+			srvTcp->protocolType = IPV4;
+			init_waitqueue_head(&srvTcp->response_q);
+			init_waitqueue_head(&srvTcp->request_q);
+			INIT_LIST_HEAD(&srvTcp->pending_mid_q);
+			/* at this point we are the only ones with the pointer
+			to the struct since the kernel thread not created yet
+			so no need to spinlock this init of tcpStatus */
+			srvTcp->tcpStatus = CifsNew;
+			init_MUTEX(&srvTcp->tcpSem);
+			rc = (int)kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
+				      CLONE_FS | CLONE_FILES | CLONE_VM);
+			if(rc < 0) {
+				rc = -ENOMEM;
+				sock_release(csocket);
+				if(volume_info.UNC)
+					kfree(volume_info.UNC);
+				if(volume_info.password)
+					kfree(volume_info.password);
+				FreeXid(xid);
+				return rc;
+			} else
+				rc = 0;
+			memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
+		}
+	}
+
+	if (existingCifsSes) {
+		pSesInfo = existingCifsSes;
+		cFYI(1, ("Existing smb sess found "));
+		if(volume_info.password)
+			kfree(volume_info.password);
+		/* volume_info.UNC freed at end of function */
+	} else if (!rc) {
+		cFYI(1, ("Existing smb sess not found "));
+		pSesInfo = sesInfoAlloc();
+		if (pSesInfo == NULL)
+			rc = -ENOMEM;
+		else {
+			pSesInfo->server = srvTcp;
+			sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
+				NIPQUAD(sin_server.sin_addr.s_addr));
+		}
+
+		if (!rc){
+			/* volume_info.password freed at unmount */   
+			if (volume_info.password)
+				pSesInfo->password = volume_info.password;
+			if (volume_info.username)
+				strncpy(pSesInfo->userName,
+					volume_info.username,MAX_USERNAME_SIZE);
+			if (volume_info.domainname)
+				strncpy(pSesInfo->domainName,
+					volume_info.domainname,MAX_USERNAME_SIZE);
+			pSesInfo->linux_uid = volume_info.linux_uid;
+			down(&pSesInfo->sesSem);
+			rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
+			up(&pSesInfo->sesSem);
+			if(!rc)
+				atomic_inc(&srvTcp->socketUseCount);
+		} else
+			if(volume_info.password)
+				kfree(volume_info.password);
+	}
+    
+	/* search for existing tcon to this server share */
+	if (!rc) {
+		if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize))
+			cifs_sb->rsize = volume_info.rsize;
+		else
+			cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
+		if((volume_info.wsize) && (volume_info.wsize <= CIFSMaxBufSize))
+			cifs_sb->wsize = volume_info.wsize;
+		else
+			cifs_sb->wsize = CIFSMaxBufSize; /* default */
+		if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
+			cifs_sb->rsize = PAGE_CACHE_SIZE;
+			cERROR(1,("Attempt to set readsize for mount to less than one page (4096)"));
+		}
+		cifs_sb->mnt_uid = volume_info.linux_uid;
+		cifs_sb->mnt_gid = volume_info.linux_gid;
+		cifs_sb->mnt_file_mode = volume_info.file_mode;
+		cifs_sb->mnt_dir_mode = volume_info.dir_mode;
+		cFYI(1,("file mode: 0x%x  dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
+
+		if(volume_info.noperm)
+			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
+		if(volume_info.setuids)
+			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
+		if(volume_info.server_ino)
+			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
+		if(volume_info.no_xattr)
+			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
+		if(volume_info.direct_io) {
+			cERROR(1,("mounting share using direct i/o"));
+			cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
+		}
+
+		tcon =
+		    find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
+			     volume_info.username);
+		if (tcon) {
+			cFYI(1, ("Found match on UNC path "));
+			/* we can have only one retry value for a connection
+			   to a share so for resources mounted more than once
+			   to the same server share the last value passed in 
+			   for the retry flag is used */
+			tcon->retry = volume_info.retry;
+		} else {
+			tcon = tconInfoAlloc();
+			if (tcon == NULL)
+				rc = -ENOMEM;
+			else {
+				/* check for null share name ie connect to dfs root */
+
+				/* BB check if this works for exactly length three strings */
+				if ((strchr(volume_info.UNC + 3, '\\') == NULL)
+				    && (strchr(volume_info.UNC + 3, '/') ==
+					NULL)) {
+					rc = connect_to_dfs_path(xid,
+								 pSesInfo,
+								 "",
+								 cifs_sb->
+								 local_nls);
+					if(volume_info.UNC)
+						kfree(volume_info.UNC);
+					FreeXid(xid);
+					return -ENODEV;
+				} else {
+					rc = CIFSTCon(xid, pSesInfo, 
+						volume_info.UNC,
+						tcon, cifs_sb->local_nls);
+					cFYI(1, ("CIFS Tcon rc = %d", rc));
+				}
+				if (!rc) {
+					atomic_inc(&pSesInfo->inUse);
+					tcon->retry = volume_info.retry;
+				}
+			}
+		}
+	}
+	if(pSesInfo) {
+		if (pSesInfo->capabilities & CAP_LARGE_FILES) {
+			sb->s_maxbytes = (u64) 1 << 63;
+		} else
+			sb->s_maxbytes = (u64) 1 << 31;	/* 2 GB */
+	}
+
+	sb->s_time_gran = 100;
+
+/* on error free sesinfo and tcon struct if needed */
+	if (rc) {
+		/* if session setup failed, use count is zero but
+		we still need to free cifsd thread */
+		if(atomic_read(&srvTcp->socketUseCount) == 0) {
+			spin_lock(&GlobalMid_Lock);
+			srvTcp->tcpStatus = CifsExiting;
+			spin_unlock(&GlobalMid_Lock);
+			if(srvTcp->tsk)
+				send_sig(SIGKILL,srvTcp->tsk,1);
+		}
+		 /* If find_unc succeeded then rc == 0 so we can not end */
+		if (tcon)  /* up accidently freeing someone elses tcon struct */
+			tconInfoFree(tcon);
+		if (existingCifsSes == NULL) {
+			if (pSesInfo) {
+				if ((pSesInfo->server) && 
+				    (pSesInfo->status == CifsGood)) {
+					int temp_rc;
+					temp_rc = CIFSSMBLogoff(xid, pSesInfo);
+					/* if the socketUseCount is now zero */
+					if((temp_rc == -ESHUTDOWN) &&
+					   (pSesInfo->server->tsk))
+						send_sig(SIGKILL,pSesInfo->server->tsk,1);
+				} else
+					cFYI(1, ("No session or bad tcon"));
+				sesInfoFree(pSesInfo);
+				/* pSesInfo = NULL; */
+			}
+		}
+	} else {
+		atomic_inc(&tcon->useCount);
+		cifs_sb->tcon = tcon;
+		tcon->ses = pSesInfo;
+
+		/* do not care if following two calls succeed - informational only */
+		CIFSSMBQFSDeviceInfo(xid, tcon, cifs_sb->local_nls);
+		CIFSSMBQFSAttributeInfo(xid, tcon, cifs_sb->local_nls);
+		if (tcon->ses->capabilities & CAP_UNIX) {
+			if(!CIFSSMBQFSUnixInfo(xid, tcon, cifs_sb->local_nls)) {
+				if(!volume_info.no_psx_acl) {
+					if(CIFS_UNIX_POSIX_ACL_CAP & 
+					   le64_to_cpu(tcon->fsUnixInfo.Capability))
+						cFYI(1,("server negotiated posix acl support"));
+						sb->s_flags |= MS_POSIXACL;
+				}
+			}
+		}
+	}
+
+	/* volume_info.password is freed above when existing session found
+	(in which case it is not needed anymore) but when new sesion is created
+	the password ptr is put in the new session structure (in which case the
+	password will be freed at unmount time) */
+	if(volume_info.UNC)
+		kfree(volume_info.UNC);
+	FreeXid(xid);
+	return rc;
+}
+
+static int
+CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
+	      char session_key[CIFS_SESSION_KEY_SIZE],
+	      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;
+	char *domain;
+	int rc = 0;
+	int remaining_words = 0;
+	int bytes_returned = 0;
+	int len;
+	__u32 capabilities;
+	__u16 count;
+
+	cFYI(1, ("In sesssetup "));
+	if(ses == NULL)
+		return -EINVAL;
+	user = ses->userName;
+	domain = ses->domainName;
+	smb_buffer = cifs_buf_get();
+	if (smb_buffer == NULL) {
+		return -ENOMEM;
+	}
+	smb_buffer_response = smb_buffer;
+	pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
+
+	/* send SMBsessionSetup here */
+	header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
+			NULL /* no tCon exists yet */ , 13 /* wct */ );
+
+	pSMB->req_no_secext.AndXCommand = 0xFF;
+	pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
+	pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
+
+	if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+		smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+
+	capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
+		CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
+	if (ses->capabilities & CAP_UNICODE) {
+		smb_buffer->Flags2 |= SMBFLG2_UNICODE;
+		capabilities |= CAP_UNICODE;
+	}
+	if (ses->capabilities & CAP_STATUS32) {
+		smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
+		capabilities |= CAP_STATUS32;
+	}
+	if (ses->capabilities & CAP_DFS) {
+		smb_buffer->Flags2 |= SMBFLG2_DFS;
+		capabilities |= CAP_DFS;
+	}
+	pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
+
+	pSMB->req_no_secext.CaseInsensitivePasswordLength = 
+		cpu_to_le16(CIFS_SESSION_KEY_SIZE);
+
+	pSMB->req_no_secext.CaseSensitivePasswordLength =
+	    cpu_to_le16(CIFS_SESSION_KEY_SIZE);
+	bcc_ptr = pByteArea(smb_buffer);
+	memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
+	bcc_ptr += CIFS_SESSION_KEY_SIZE;
+	memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
+	bcc_ptr += CIFS_SESSION_KEY_SIZE;
+
+	if (ses->capabilities & CAP_UNICODE) {
+		if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
+			*bcc_ptr = 0;
+			bcc_ptr++;
+		}
+		if(user == NULL)
+			bytes_returned = 0; /* skill null user */
+	        else
+			bytes_returned =
+			        cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100,
+					nls_codepage);
+		/* convert number of 16 bit words to bytes */
+		bcc_ptr += 2 * bytes_returned;
+		bcc_ptr += 2;	/* trailing null */
+		if (domain == NULL)
+			bytes_returned =
+			    cifs_strtoUCS((wchar_t *) bcc_ptr,
+					  "CIFS_LINUX_DOM", 32, nls_codepage);
+		else
+			bytes_returned =
+			    cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
+					  nls_codepage);
+		bcc_ptr += 2 * bytes_returned;
+		bcc_ptr += 2;
+		bytes_returned =
+		    cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
+				  32, nls_codepage);
+		bcc_ptr += 2 * bytes_returned;
+		bytes_returned =
+		    cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release,
+				  32, nls_codepage);
+		bcc_ptr += 2 * bytes_returned;
+		bcc_ptr += 2;
+		bytes_returned =
+		    cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
+				  64, nls_codepage);
+		bcc_ptr += 2 * bytes_returned;
+		bcc_ptr += 2;
+	} else {
+		if(user != NULL) {                
+		    strncpy(bcc_ptr, user, 200);
+		    bcc_ptr += strnlen(user, 200);
+		}
+		*bcc_ptr = 0;
+		bcc_ptr++;
+		if (domain == NULL) {
+			strcpy(bcc_ptr, "CIFS_LINUX_DOM");
+			bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
+		} else {
+			strncpy(bcc_ptr, domain, 64);
+			bcc_ptr += strnlen(domain, 64);
+			*bcc_ptr = 0;
+			bcc_ptr++;
+		}
+		strcpy(bcc_ptr, "Linux version ");
+		bcc_ptr += strlen("Linux version ");
+		strcpy(bcc_ptr, system_utsname.release);
+		bcc_ptr += strlen(system_utsname.release) + 1;
+		strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
+		bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
+	}
+	count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
+	smb_buffer->smb_buf_length += count;
+	pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
+
+	rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
+			 &bytes_returned, 1);
+	if (rc) {
+/* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
+	} else if ((smb_buffer_response->WordCount == 3)
+		   || (smb_buffer_response->WordCount == 4)) {
+		__u16 action = le16_to_cpu(pSMBr->resp.Action);
+		__u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
+		if (action & GUEST_LOGIN)
+			cFYI(1, (" Guest login"));	/* do we want to mark SesInfo struct ? */
+		ses->Suid = smb_buffer_response->Uid;	/* UID left in wire format (le) */
+		cFYI(1, ("UID = %d ", ses->Suid));
+         /* response can have either 3 or 4 word count - Samba sends 3 */
+		bcc_ptr = pByteArea(smb_buffer_response);	
+		if ((pSMBr->resp.hdr.WordCount == 3)
+		    || ((pSMBr->resp.hdr.WordCount == 4)
+			&& (blob_len < pSMBr->resp.ByteCount))) {
+			if (pSMBr->resp.hdr.WordCount == 4)
+				bcc_ptr += blob_len;
+
+			if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
+				if ((long) (bcc_ptr) % 2) {
+					remaining_words =
+					    (BCC(smb_buffer_response) - 1) /2;
+					bcc_ptr++;	/* Unicode strings must be word aligned */
+				} else {
+					remaining_words =
+						BCC(smb_buffer_response) / 2;
+				}
+				len =
+				    UniStrnlen((wchar_t *) bcc_ptr,
+					       remaining_words - 1);
+/* We look for obvious messed up bcc or strings in response so we do not go off
+   the end since (at least) WIN2K and Windows XP have a major bug in not null
+   terminating last Unicode string in response  */
+				ses->serverOS = cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
+				cifs_strfromUCS_le(ses->serverOS,
+					   (wchar_t *)bcc_ptr, len,nls_codepage);
+				bcc_ptr += 2 * (len + 1);
+				remaining_words -= len + 1;
+				ses->serverOS[2 * len] = 0;
+				ses->serverOS[1 + (2 * len)] = 0;
+				if (remaining_words > 0) {
+					len = UniStrnlen((wchar_t *)bcc_ptr,
+							 remaining_words-1);
+					ses->serverNOS =cifs_kcalloc(2 * (len + 1),GFP_KERNEL);
+					cifs_strfromUCS_le(ses->serverNOS,
+							   (wchar_t *)bcc_ptr,len,nls_codepage);
+					bcc_ptr += 2 * (len + 1);
+					ses->serverNOS[2 * len] = 0;
+					ses->serverNOS[1 + (2 * len)] = 0;
+					if(strncmp(ses->serverNOS,
+						"NT LAN Manager 4",16) == 0) {
+						cFYI(1,("NT4 server"));
+						ses->flags |= CIFS_SES_NT4;
+					}
+					remaining_words -= len + 1;
+					if (remaining_words > 0) {
+						len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);	
+          /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
+						ses->serverDomain =
+						    cifs_kcalloc(2*(len+1),GFP_KERNEL);
+						cifs_strfromUCS_le(ses->serverDomain,
+						     (wchar_t *)bcc_ptr,len,nls_codepage);
+						bcc_ptr += 2 * (len + 1);
+						ses->serverDomain[2*len] = 0;
+						ses->serverDomain[1+(2*len)] = 0;
+					} /* else no more room so create dummy domain string */
+					else
+						ses->serverDomain =
+						    cifs_kcalloc(2,
+							    GFP_KERNEL);
+				} else {	/* no room so create dummy domain and NOS string */
+					ses->serverDomain =
+					    cifs_kcalloc(2, GFP_KERNEL);
+					ses->serverNOS =
+					    cifs_kcalloc(2, GFP_KERNEL);
+				}
+			} else {	/* ASCII */
+				len = strnlen(bcc_ptr, 1024);
+				if (((long) bcc_ptr + len) - (long)
+				    pByteArea(smb_buffer_response)
+					    <= BCC(smb_buffer_response)) {
+					ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
+					strncpy(ses->serverOS,bcc_ptr, len);
+
+					bcc_ptr += len;
+					bcc_ptr[0] = 0;	/* null terminate the string */
+					bcc_ptr++;
+
+					len = strnlen(bcc_ptr, 1024);
+					ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
+					strncpy(ses->serverNOS, bcc_ptr, len);
+					bcc_ptr += len;
+					bcc_ptr[0] = 0;
+					bcc_ptr++;
+
+					len = strnlen(bcc_ptr, 1024);
+					ses->serverDomain = cifs_kcalloc(len + 1,GFP_KERNEL);
+					strncpy(ses->serverDomain, bcc_ptr, len);
+					bcc_ptr += len;
+					bcc_ptr[0] = 0;
+					bcc_ptr++;
+				} else
+					cFYI(1,
+					     ("Variable field of length %d extends beyond end of smb ",
+					      len));
+			}
+		} else {
+			cERROR(1,
+			       (" Security Blob Length extends beyond end of SMB"));
+		}
+	} else {
+		cERROR(1,
+		       (" Invalid Word count %d: ",
+			smb_buffer_response->WordCount));
+		rc = -EIO;
+	}
+	
+	if (smb_buffer)
+		cifs_buf_release(smb_buffer);
+
+	return rc;
+}
+
+static int
+CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
+		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;
+	char *domain;
+	int rc = 0;
+	int remaining_words = 0;
+	int bytes_returned = 0;
+	int len;
+	__u32 capabilities;
+	__u16 count;
+
+	cFYI(1, ("In spnego sesssetup "));
+	if(ses == NULL)
+		return -EINVAL;
+	user = ses->userName;
+	domain = ses->domainName;
+
+	smb_buffer = cifs_buf_get();
+	if (smb_buffer == NULL) {
+		return -ENOMEM;
+	}
+	smb_buffer_response = smb_buffer;
+	pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
+
+	/* send SMBsessionSetup here */
+	header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
+			NULL /* no tCon exists yet */ , 12 /* wct */ );
+	pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
+	pSMB->req.AndXCommand = 0xFF;
+	pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
+	pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
+
+	if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+		smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+
+	capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
+	    CAP_EXTENDED_SECURITY;
+	if (ses->capabilities & CAP_UNICODE) {
+		smb_buffer->Flags2 |= SMBFLG2_UNICODE;
+		capabilities |= CAP_UNICODE;
+	}
+	if (ses->capabilities & CAP_STATUS32) {
+		smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
+		capabilities |= CAP_STATUS32;
+	}
+	if (ses->capabilities & CAP_DFS) {
+		smb_buffer->Flags2 |= SMBFLG2_DFS;
+		capabilities |= CAP_DFS;
+	}
+	pSMB->req.Capabilities = cpu_to_le32(capabilities);
+
+	pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
+	bcc_ptr = pByteArea(smb_buffer);
+	memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
+	bcc_ptr += SecurityBlobLength;
+
+	if (ses->capabilities & CAP_UNICODE) {
+		if ((long) bcc_ptr % 2) {	/* must be word aligned for Unicode strings */
+			*bcc_ptr = 0;
+			bcc_ptr++;
+		}
+		bytes_returned =
+		    cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
+		bcc_ptr += 2 * bytes_returned;	/* convert num of 16 bit words to bytes */
+		bcc_ptr += 2;	/* trailing null */
+		if (domain == NULL)
+			bytes_returned =
+			    cifs_strtoUCS((wchar_t *) bcc_ptr,
+					  "CIFS_LINUX_DOM", 32, nls_codepage);
+		else
+			bytes_returned =
+			    cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
+					  nls_codepage);
+		bcc_ptr += 2 * bytes_returned;
+		bcc_ptr += 2;
+		bytes_returned =
+		    cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
+				  32, nls_codepage);
+		bcc_ptr += 2 * bytes_returned;
+		bytes_returned =
+		    cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
+				  nls_codepage);
+		bcc_ptr += 2 * bytes_returned;
+		bcc_ptr += 2;
+		bytes_returned =
+		    cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
+				  64, nls_codepage);
+		bcc_ptr += 2 * bytes_returned;
+		bcc_ptr += 2;
+	} else {
+		strncpy(bcc_ptr, user, 200);
+		bcc_ptr += strnlen(user, 200);
+		*bcc_ptr = 0;
+		bcc_ptr++;
+		if (domain == NULL) {
+			strcpy(bcc_ptr, "CIFS_LINUX_DOM");
+			bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
+		} else {
+			strncpy(bcc_ptr, domain, 64);
+			bcc_ptr += strnlen(domain, 64);
+			*bcc_ptr = 0;
+			bcc_ptr++;
+		}
+		strcpy(bcc_ptr, "Linux version ");
+		bcc_ptr += strlen("Linux version ");
+		strcpy(bcc_ptr, system_utsname.release);
+		bcc_ptr += strlen(system_utsname.release) + 1;
+		strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
+		bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
+	}
+	count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
+	smb_buffer->smb_buf_length += count;
+	pSMB->req.ByteCount = cpu_to_le16(count);
+
+	rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
+			 &bytes_returned, 1);
+	if (rc) {
+/*    rc = map_smb_to_linux_error(smb_buffer_response);  *//* done in SendReceive now */
+	} else if ((smb_buffer_response->WordCount == 3)
+		   || (smb_buffer_response->WordCount == 4)) {
+		__u16 action = le16_to_cpu(pSMBr->resp.Action);
+		__u16 blob_len =
+		    le16_to_cpu(pSMBr->resp.SecurityBlobLength);
+		if (action & GUEST_LOGIN)
+			cFYI(1, (" Guest login"));	/* BB do we want to set anything in SesInfo struct ? */
+		if (ses) {
+			ses->Suid = smb_buffer_response->Uid;	/* UID left in wire format (le) */
+			cFYI(1, ("UID = %d ", ses->Suid));
+			bcc_ptr = pByteArea(smb_buffer_response);	/* response can have either 3 or 4 word count - Samba sends 3 */
+
+			/* BB Fix below to make endian neutral !! */
+
+			if ((pSMBr->resp.hdr.WordCount == 3)
+			    || ((pSMBr->resp.hdr.WordCount == 4)
+				&& (blob_len <
+				    pSMBr->resp.ByteCount))) {
+				if (pSMBr->resp.hdr.WordCount == 4) {
+					bcc_ptr +=
+					    blob_len;
+					cFYI(1,
+					     ("Security Blob Length %d ",
+					      blob_len));
+				}
+
+				if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
+					if ((long) (bcc_ptr) % 2) {
+						remaining_words =
+						    (BCC(smb_buffer_response)
+						     - 1) / 2;
+						bcc_ptr++;	/* Unicode strings must be word aligned */
+					} else {
+						remaining_words =
+						    BCC
+						    (smb_buffer_response) / 2;
+					}
+					len =
+					    UniStrnlen((wchar_t *) bcc_ptr,
+						       remaining_words - 1);
+/* We look for obvious messed up bcc or strings in response so we do not go off
+   the end since (at least) WIN2K and Windows XP have a major bug in not null
+   terminating last Unicode string in response  */
+					ses->serverOS =
+					    cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
+					cifs_strfromUCS_le(ses->serverOS,
+							   (wchar_t *)
+							   bcc_ptr, len,
+							   nls_codepage);
+					bcc_ptr += 2 * (len + 1);
+					remaining_words -= len + 1;
+					ses->serverOS[2 * len] = 0;
+					ses->serverOS[1 + (2 * len)] = 0;
+					if (remaining_words > 0) {
+						len = UniStrnlen((wchar_t *)bcc_ptr,
+								 remaining_words
+								 - 1);
+						ses->serverNOS =
+						    cifs_kcalloc(2 * (len + 1),
+							    GFP_KERNEL);
+						cifs_strfromUCS_le(ses->serverNOS,
+								   (wchar_t *)bcc_ptr,
+								   len,
+								   nls_codepage);
+						bcc_ptr += 2 * (len + 1);
+						ses->serverNOS[2 * len] = 0;
+						ses->serverNOS[1 + (2 * len)] = 0;
+						remaining_words -= len + 1;
+						if (remaining_words > 0) {
+							len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);	
+                            /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
+							ses->serverDomain = cifs_kcalloc(2*(len+1),GFP_KERNEL);
+							cifs_strfromUCS_le(ses->serverDomain,
+							     (wchar_t *)bcc_ptr, 
+                                 len,
+							     nls_codepage);
+							bcc_ptr += 2*(len+1);
+							ses->serverDomain[2*len] = 0;
+							ses->serverDomain[1+(2*len)] = 0;
+						} /* else no more room so create dummy domain string */
+						else
+							ses->serverDomain =
+							    cifs_kcalloc(2,GFP_KERNEL);
+					} else {	/* no room so create dummy domain and NOS string */
+						ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL);
+						ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL);
+					}
+				} else {	/* ASCII */
+
+					len = strnlen(bcc_ptr, 1024);
+					if (((long) bcc_ptr + len) - (long)
+					    pByteArea(smb_buffer_response)
+					    <= BCC(smb_buffer_response)) {
+						ses->serverOS = cifs_kcalloc(len + 1, GFP_KERNEL);
+						strncpy(ses->serverOS, bcc_ptr, len);
+
+						bcc_ptr += len;
+						bcc_ptr[0] = 0;	/* null terminate the string */
+						bcc_ptr++;
+
+						len = strnlen(bcc_ptr, 1024);
+						ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
+						strncpy(ses->serverNOS, bcc_ptr, len);
+						bcc_ptr += len;
+						bcc_ptr[0] = 0;
+						bcc_ptr++;
+
+						len = strnlen(bcc_ptr, 1024);
+						ses->serverDomain = cifs_kcalloc(len + 1, GFP_KERNEL);
+						strncpy(ses->serverDomain, bcc_ptr, len);
+						bcc_ptr += len;
+						bcc_ptr[0] = 0;
+						bcc_ptr++;
+					} else
+						cFYI(1,
+						     ("Variable field of length %d extends beyond end of smb ",
+						      len));
+				}
+			} else {
+				cERROR(1,
+				       (" Security Blob Length extends beyond end of SMB"));
+			}
+		} else {
+			cERROR(1, ("No session structure passed in."));
+		}
+	} else {
+		cERROR(1,
+		       (" Invalid Word count %d: ",
+			smb_buffer_response->WordCount));
+		rc = -EIO;
+	}
+
+	if (smb_buffer)
+		cifs_buf_release(smb_buffer);
+
+	return rc;
+}
+
+static int
+CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
+			      struct cifsSesInfo *ses, int * pNTLMv2_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 *domain;
+	int rc = 0;
+	int remaining_words = 0;
+	int bytes_returned = 0;
+	int len;
+	int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
+	PNEGOTIATE_MESSAGE SecurityBlob;
+	PCHALLENGE_MESSAGE SecurityBlob2;
+	__u32 negotiate_flags, capabilities;
+	__u16 count;
+
+	cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
+	if(ses == NULL)
+		return -EINVAL;
+	domain = ses->domainName;
+	*pNTLMv2_flag = FALSE;
+	smb_buffer = cifs_buf_get();
+	if (smb_buffer == NULL) {
+		return -ENOMEM;
+	}
+	smb_buffer_response = smb_buffer;
+	pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
+	pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
+
+	/* send SMBsessionSetup here */
+	header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
+			NULL /* no tCon exists yet */ , 12 /* wct */ );
+	pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
+	pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
+
+	pSMB->req.AndXCommand = 0xFF;
+	pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
+	pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
+
+	if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+		smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+
+	capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
+	    CAP_EXTENDED_SECURITY;
+	if (ses->capabilities & CAP_UNICODE) {
+		smb_buffer->Flags2 |= SMBFLG2_UNICODE;
+		capabilities |= CAP_UNICODE;
+	}
+	if (ses->capabilities & CAP_STATUS32) {
+		smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
+		capabilities |= CAP_STATUS32;
+	}
+	if (ses->capabilities & CAP_DFS) {
+		smb_buffer->Flags2 |= SMBFLG2_DFS;
+		capabilities |= CAP_DFS;
+	}
+	pSMB->req.Capabilities = cpu_to_le32(capabilities);
+
+	bcc_ptr = (char *) &pSMB->req.SecurityBlob;
+	SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
+	strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
+	SecurityBlob->MessageType = NtLmNegotiate;
+	negotiate_flags =
+	    NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
+	    NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
+	    /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
+	if(sign_CIFS_PDUs)
+		negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
+	if(ntlmv2_support)
+		negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
+	/* setup pointers to domain name and workstation name */
+	bcc_ptr += SecurityBlobLength;
+
+	SecurityBlob->WorkstationName.Buffer = 0;
+	SecurityBlob->WorkstationName.Length = 0;
+	SecurityBlob->WorkstationName.MaximumLength = 0;
+
+	if (domain == NULL) {
+		SecurityBlob->DomainName.Buffer = 0;
+		SecurityBlob->DomainName.Length = 0;
+		SecurityBlob->DomainName.MaximumLength = 0;
+	} else {
+		__u16 len;
+		negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
+		strncpy(bcc_ptr, domain, 63);
+		len = strnlen(domain, 64);
+		SecurityBlob->DomainName.MaximumLength =
+		    cpu_to_le16(len);
+		SecurityBlob->DomainName.Buffer =
+		    cpu_to_le32((long) &SecurityBlob->
+				DomainString -
+				(long) &SecurityBlob->Signature);
+		bcc_ptr += len;
+		SecurityBlobLength += len;
+		SecurityBlob->DomainName.Length =
+		    cpu_to_le16(len);
+	}
+	if (ses->capabilities & CAP_UNICODE) {
+		if ((long) bcc_ptr % 2) {
+			*bcc_ptr = 0;
+			bcc_ptr++;
+		}
+
+		bytes_returned =
+		    cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
+				  32, nls_codepage);
+		bcc_ptr += 2 * bytes_returned;
+		bytes_returned =
+		    cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
+				  nls_codepage);
+		bcc_ptr += 2 * bytes_returned;
+		bcc_ptr += 2;	/* null terminate Linux version */
+		bytes_returned =
+		    cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
+				  64, nls_codepage);
+		bcc_ptr += 2 * bytes_returned;
+		*(bcc_ptr + 1) = 0;
+		*(bcc_ptr + 2) = 0;
+		bcc_ptr += 2;	/* null terminate network opsys string */
+		*(bcc_ptr + 1) = 0;
+		*(bcc_ptr + 2) = 0;
+		bcc_ptr += 2;	/* null domain */
+	} else {		/* ASCII */
+		strcpy(bcc_ptr, "Linux version ");
+		bcc_ptr += strlen("Linux version ");
+		strcpy(bcc_ptr, system_utsname.release);
+		bcc_ptr += strlen(system_utsname.release) + 1;
+		strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
+		bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
+		bcc_ptr++;	/* empty domain field */
+		*bcc_ptr = 0;
+	}
+	SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
+	pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
+	count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
+	smb_buffer->smb_buf_length += count;
+	pSMB->req.ByteCount = cpu_to_le16(count);
+
+	rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
+			 &bytes_returned, 1);
+
+	if (smb_buffer_response->Status.CifsError ==
+	    cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
+		rc = 0;
+
+	if (rc) {
+/*    rc = map_smb_to_linux_error(smb_buffer_response);  *//* done in SendReceive now */
+	} else if ((smb_buffer_response->WordCount == 3)
+		   || (smb_buffer_response->WordCount == 4)) {
+		__u16 action = le16_to_cpu(pSMBr->resp.Action);
+		__u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
+
+		if (action & GUEST_LOGIN)
+			cFYI(1, (" Guest login"));	
+        /* Do we want to set anything in SesInfo struct when guest login? */
+
+		bcc_ptr = pByteArea(smb_buffer_response);	
+        /* response can have either 3 or 4 word count - Samba sends 3 */
+
+		SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
+		if (SecurityBlob2->MessageType != NtLmChallenge) {
+			cFYI(1,
+			     ("Unexpected NTLMSSP message type received %d",
+			      SecurityBlob2->MessageType));
+		} else if (ses) {
+			ses->Suid = smb_buffer_response->Uid; /* UID left in le format */ 
+			cFYI(1, ("UID = %d ", ses->Suid));
+			if ((pSMBr->resp.hdr.WordCount == 3)
+			    || ((pSMBr->resp.hdr.WordCount == 4)
+				&& (blob_len <
+				    pSMBr->resp.ByteCount))) {
+
+				if (pSMBr->resp.hdr.WordCount == 4) {
+					bcc_ptr += blob_len;
+					cFYI(1,
+					     ("Security Blob Length %d ",
+					      blob_len));
+				}
+
+				cFYI(1, ("NTLMSSP Challenge rcvd "));
+
+				memcpy(ses->server->cryptKey,
+				       SecurityBlob2->Challenge,
+				       CIFS_CRYPTO_KEY_SIZE);
+				if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
+					*pNTLMv2_flag = TRUE;
+
+				if((SecurityBlob2->NegotiateFlags & 
+					cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN)) 
+					|| (sign_CIFS_PDUs > 1))
+						ses->server->secMode |= 
+							SECMODE_SIGN_REQUIRED;	
+				if ((SecurityBlob2->NegotiateFlags & 
+					cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
+						ses->server->secMode |= 
+							SECMODE_SIGN_ENABLED;
+
+				if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
+					if ((long) (bcc_ptr) % 2) {
+						remaining_words =
+						    (BCC(smb_buffer_response)
+						     - 1) / 2;
+						bcc_ptr++;	/* Unicode strings must be word aligned */
+					} else {
+						remaining_words =
+						    BCC
+						    (smb_buffer_response) / 2;
+					}
+					len =
+					    UniStrnlen((wchar_t *) bcc_ptr,
+						       remaining_words - 1);
+/* We look for obvious messed up bcc or strings in response so we do not go off
+   the end since (at least) WIN2K and Windows XP have a major bug in not null
+   terminating last Unicode string in response  */
+					ses->serverOS =
+					    cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
+					cifs_strfromUCS_le(ses->serverOS,
+							   (wchar_t *)
+							   bcc_ptr, len,
+							   nls_codepage);
+					bcc_ptr += 2 * (len + 1);
+					remaining_words -= len + 1;
+					ses->serverOS[2 * len] = 0;
+					ses->serverOS[1 + (2 * len)] = 0;
+					if (remaining_words > 0) {
+						len = UniStrnlen((wchar_t *)
+								 bcc_ptr,
+								 remaining_words
+								 - 1);
+						ses->serverNOS =
+						    cifs_kcalloc(2 * (len + 1),
+							    GFP_KERNEL);
+						cifs_strfromUCS_le(ses->
+								   serverNOS,
+								   (wchar_t *)
+								   bcc_ptr,
+								   len,
+								   nls_codepage);
+						bcc_ptr += 2 * (len + 1);
+						ses->serverNOS[2 * len] = 0;
+						ses->serverNOS[1 +
+							       (2 * len)] = 0;
+						remaining_words -= len + 1;
+						if (remaining_words > 0) {
+							len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);	
+           /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
+							ses->serverDomain =
+							    cifs_kcalloc(2 *
+								    (len +
+								     1),
+								    GFP_KERNEL);
+							cifs_strfromUCS_le
+							    (ses->
+							     serverDomain,
+							     (wchar_t *)
+							     bcc_ptr, len,
+							     nls_codepage);
+							bcc_ptr +=
+							    2 * (len + 1);
+							ses->
+							    serverDomain[2
+									 * len]
+							    = 0;
+							ses->
+							    serverDomain[1
+									 +
+									 (2
+									  *
+									  len)]
+							    = 0;
+						} /* else no more room so create dummy domain string */
+						else
+							ses->serverDomain =
+							    cifs_kcalloc(2,
+								    GFP_KERNEL);
+					} else {	/* no room so create dummy domain and NOS string */
+						ses->serverDomain =
+						    cifs_kcalloc(2, GFP_KERNEL);
+						ses->serverNOS =
+						    cifs_kcalloc(2, GFP_KERNEL);
+					}
+				} else {	/* ASCII */
+					len = strnlen(bcc_ptr, 1024);
+					if (((long) bcc_ptr + len) - (long)
+					    pByteArea(smb_buffer_response)
+					    <= BCC(smb_buffer_response)) {
+						ses->serverOS =
+						    cifs_kcalloc(len + 1,
+							    GFP_KERNEL);
+						strncpy(ses->serverOS,
+							bcc_ptr, len);
+
+						bcc_ptr += len;
+						bcc_ptr[0] = 0;	/* null terminate string */
+						bcc_ptr++;
+
+						len = strnlen(bcc_ptr, 1024);
+						ses->serverNOS =
+						    cifs_kcalloc(len + 1,
+							    GFP_KERNEL);
+						strncpy(ses->serverNOS, bcc_ptr, len);
+						bcc_ptr += len;
+						bcc_ptr[0] = 0;
+						bcc_ptr++;
+
+						len = strnlen(bcc_ptr, 1024);
+						ses->serverDomain =
+						    cifs_kcalloc(len + 1,
+							    GFP_KERNEL);
+						strncpy(ses->serverDomain, bcc_ptr, len);	
+						bcc_ptr += len;
+						bcc_ptr[0] = 0;
+						bcc_ptr++;
+					} else
+						cFYI(1,
+						     ("Variable field of length %d extends beyond end of smb ",
+						      len));
+				}
+			} else {
+				cERROR(1,
+				       (" Security Blob Length extends beyond end of SMB"));
+			}
+		} else {
+			cERROR(1, ("No session structure passed in."));
+		}
+	} else {
+		cERROR(1,
+		       (" Invalid Word count %d: ",
+			smb_buffer_response->WordCount));
+		rc = -EIO;
+	}
+
+	if (smb_buffer)
+		cifs_buf_release(smb_buffer);
+
+	return rc;
+}
+static int
+CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
+		char *ntlm_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;
+	char *domain;
+	int rc = 0;
+	int remaining_words = 0;
+	int bytes_returned = 0;
+	int len;
+	int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
+	PAUTHENTICATE_MESSAGE SecurityBlob;
+	__u32 negotiate_flags, capabilities;
+	__u16 count;
+
+	cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
+	if(ses == NULL)
+		return -EINVAL;
+	user = ses->userName;
+	domain = ses->domainName;
+	smb_buffer = cifs_buf_get();
+	if (smb_buffer == NULL) {
+		return -ENOMEM;
+	}
+	smb_buffer_response = smb_buffer;
+	pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
+	pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
+
+	/* send SMBsessionSetup here */
+	header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
+			NULL /* no tCon exists yet */ , 12 /* wct */ );
+	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->server->maxBuf);
+	pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
+
+	pSMB->req.hdr.Uid = ses->Suid;
+
+	if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+		smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+
+	capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
+	    CAP_EXTENDED_SECURITY;
+	if (ses->capabilities & CAP_UNICODE) {
+		smb_buffer->Flags2 |= SMBFLG2_UNICODE;
+		capabilities |= CAP_UNICODE;
+	}
+	if (ses->capabilities & CAP_STATUS32) {
+		smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
+		capabilities |= CAP_STATUS32;
+	}
+	if (ses->capabilities & CAP_DFS) {
+		smb_buffer->Flags2 |= SMBFLG2_DFS;
+		capabilities |= CAP_DFS;
+	}
+	pSMB->req.Capabilities = cpu_to_le32(capabilities);
+
+	bcc_ptr = (char *) &pSMB->req.SecurityBlob;
+	SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
+	strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
+	SecurityBlob->MessageType = NtLmAuthenticate;
+	bcc_ptr += SecurityBlobLength;
+	negotiate_flags = 
+	    NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
+	    NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
+	    0x80000000 | NTLMSSP_NEGOTIATE_128;
+	if(sign_CIFS_PDUs)
+		negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
+	if(ntlmv2_flag)
+		negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
+
+/* setup pointers to domain name and workstation name */
+
+	SecurityBlob->WorkstationName.Buffer = 0;
+	SecurityBlob->WorkstationName.Length = 0;
+	SecurityBlob->WorkstationName.MaximumLength = 0;
+	SecurityBlob->SessionKey.Length = 0;
+	SecurityBlob->SessionKey.MaximumLength = 0;
+	SecurityBlob->SessionKey.Buffer = 0;
+
+	SecurityBlob->LmChallengeResponse.Length = 0;
+	SecurityBlob->LmChallengeResponse.MaximumLength = 0;
+	SecurityBlob->LmChallengeResponse.Buffer = 0;
+
+	SecurityBlob->NtChallengeResponse.Length =
+	    cpu_to_le16(CIFS_SESSION_KEY_SIZE);
+	SecurityBlob->NtChallengeResponse.MaximumLength =
+	    cpu_to_le16(CIFS_SESSION_KEY_SIZE);
+	memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
+	SecurityBlob->NtChallengeResponse.Buffer =
+	    cpu_to_le32(SecurityBlobLength);
+	SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
+	bcc_ptr += CIFS_SESSION_KEY_SIZE;
+
+	if (ses->capabilities & CAP_UNICODE) {
+		if (domain == NULL) {
+			SecurityBlob->DomainName.Buffer = 0;
+			SecurityBlob->DomainName.Length = 0;
+			SecurityBlob->DomainName.MaximumLength = 0;
+		} else {
+			__u16 len =
+			    cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
+					  nls_codepage);
+			len *= 2;
+			SecurityBlob->DomainName.MaximumLength =
+			    cpu_to_le16(len);
+			SecurityBlob->DomainName.Buffer =
+			    cpu_to_le32(SecurityBlobLength);
+			bcc_ptr += len;
+			SecurityBlobLength += len;
+			SecurityBlob->DomainName.Length =
+			    cpu_to_le16(len);
+		}
+		if (user == NULL) {
+			SecurityBlob->UserName.Buffer = 0;
+			SecurityBlob->UserName.Length = 0;
+			SecurityBlob->UserName.MaximumLength = 0;
+		} else {
+			__u16 len =
+			    cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
+					  nls_codepage);
+			len *= 2;
+			SecurityBlob->UserName.MaximumLength =
+			    cpu_to_le16(len);
+			SecurityBlob->UserName.Buffer =
+			    cpu_to_le32(SecurityBlobLength);
+			bcc_ptr += len;
+			SecurityBlobLength += len;
+			SecurityBlob->UserName.Length =
+			    cpu_to_le16(len);
+		}
+
+		/* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
+		   SecurityBlob->WorkstationName.Length *= 2;
+		   SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
+		   SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
+		   bcc_ptr += SecurityBlob->WorkstationName.Length;
+		   SecurityBlobLength += SecurityBlob->WorkstationName.Length;
+		   SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length);  */
+
+		if ((long) bcc_ptr % 2) {
+			*bcc_ptr = 0;
+			bcc_ptr++;
+		}
+		bytes_returned =
+		    cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
+				  32, nls_codepage);
+		bcc_ptr += 2 * bytes_returned;
+		bytes_returned =
+		    cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
+				  nls_codepage);
+		bcc_ptr += 2 * bytes_returned;
+		bcc_ptr += 2;	/* null term version string */
+		bytes_returned =
+		    cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
+				  64, nls_codepage);
+		bcc_ptr += 2 * bytes_returned;
+		*(bcc_ptr + 1) = 0;
+		*(bcc_ptr + 2) = 0;
+		bcc_ptr += 2;	/* null terminate network opsys string */
+		*(bcc_ptr + 1) = 0;
+		*(bcc_ptr + 2) = 0;
+		bcc_ptr += 2;	/* null domain */
+	} else {		/* ASCII */
+		if (domain == NULL) {
+			SecurityBlob->DomainName.Buffer = 0;
+			SecurityBlob->DomainName.Length = 0;
+			SecurityBlob->DomainName.MaximumLength = 0;
+		} else {
+			__u16 len;
+			negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
+			strncpy(bcc_ptr, domain, 63);
+			len = strnlen(domain, 64);
+			SecurityBlob->DomainName.MaximumLength =
+			    cpu_to_le16(len);
+			SecurityBlob->DomainName.Buffer =
+			    cpu_to_le32(SecurityBlobLength);
+			bcc_ptr += len;
+			SecurityBlobLength += len;
+			SecurityBlob->DomainName.Length = cpu_to_le16(len);
+		}
+		if (user == NULL) {
+			SecurityBlob->UserName.Buffer = 0;
+			SecurityBlob->UserName.Length = 0;
+			SecurityBlob->UserName.MaximumLength = 0;
+		} else {
+			__u16 len;
+			strncpy(bcc_ptr, user, 63);
+			len = strnlen(user, 64);
+			SecurityBlob->UserName.MaximumLength =
+			    cpu_to_le16(len);
+			SecurityBlob->UserName.Buffer =
+			    cpu_to_le32(SecurityBlobLength);
+			bcc_ptr += len;
+			SecurityBlobLength += len;
+			SecurityBlob->UserName.Length = cpu_to_le16(len);
+		}
+		/* BB fill in our workstation name if known BB */
+
+		strcpy(bcc_ptr, "Linux version ");
+		bcc_ptr += strlen("Linux version ");
+		strcpy(bcc_ptr, system_utsname.release);
+		bcc_ptr += strlen(system_utsname.release) + 1;
+		strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
+		bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
+		bcc_ptr++;	/* null domain */
+		*bcc_ptr = 0;
+	}
+	SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
+	pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
+	count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
+	smb_buffer->smb_buf_length += count;
+	pSMB->req.ByteCount = cpu_to_le16(count);
+
+	rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
+			 &bytes_returned, 1);
+	if (rc) {
+/*    rc = map_smb_to_linux_error(smb_buffer_response);  *//* done in SendReceive now */
+	} else if ((smb_buffer_response->WordCount == 3)
+		   || (smb_buffer_response->WordCount == 4)) {
+		__u16 action = le16_to_cpu(pSMBr->resp.Action);
+		__u16 blob_len =
+		    le16_to_cpu(pSMBr->resp.SecurityBlobLength);
+		if (action & GUEST_LOGIN)
+			cFYI(1, (" Guest login"));	/* BB do we want to set anything in SesInfo struct ? */
+/*        if(SecurityBlob2->MessageType != NtLm??){                               
+                 cFYI("Unexpected message type on auth response is %d ")); 
+        } */
+		if (ses) {
+			cFYI(1,
+			     ("Does UID on challenge %d match auth response UID %d ",
+			      ses->Suid, smb_buffer_response->Uid));
+			ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
+			bcc_ptr = pByteArea(smb_buffer_response);	
+            /* response can have either 3 or 4 word count - Samba sends 3 */
+			if ((pSMBr->resp.hdr.WordCount == 3)
+			    || ((pSMBr->resp.hdr.WordCount == 4)
+				&& (blob_len <
+				    pSMBr->resp.ByteCount))) {
+				if (pSMBr->resp.hdr.WordCount == 4) {
+					bcc_ptr +=
+					    blob_len;
+					cFYI(1,
+					     ("Security Blob Length %d ",
+					      blob_len));
+				}
+
+				cFYI(1,
+				     ("NTLMSSP response to Authenticate "));
+
+				if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
+					if ((long) (bcc_ptr) % 2) {
+						remaining_words =
+						    (BCC(smb_buffer_response)
+						     - 1) / 2;
+						bcc_ptr++;	/* Unicode strings must be word aligned */
+					} else {
+						remaining_words = BCC(smb_buffer_response) / 2;
+					}
+					len =
+					    UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
+/* We look for obvious messed up bcc or strings in response so we do not go off
+  the end since (at least) WIN2K and Windows XP have a major bug in not null
+  terminating last Unicode string in response  */
+					ses->serverOS =
+					    cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
+					cifs_strfromUCS_le(ses->serverOS,
+							   (wchar_t *)
+							   bcc_ptr, len,
+							   nls_codepage);
+					bcc_ptr += 2 * (len + 1);
+					remaining_words -= len + 1;
+					ses->serverOS[2 * len] = 0;
+					ses->serverOS[1 + (2 * len)] = 0;
+					if (remaining_words > 0) {
+						len = UniStrnlen((wchar_t *)
+								 bcc_ptr,
+								 remaining_words
+								 - 1);
+						ses->serverNOS =
+						    cifs_kcalloc(2 * (len + 1),
+							    GFP_KERNEL);
+						cifs_strfromUCS_le(ses->
+								   serverNOS,
+								   (wchar_t *)
+								   bcc_ptr,
+								   len,
+								   nls_codepage);
+						bcc_ptr += 2 * (len + 1);
+						ses->serverNOS[2 * len] = 0;
+						ses->serverNOS[1+(2*len)] = 0;
+						remaining_words -= len + 1;
+						if (remaining_words > 0) {
+							len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);	
+     /* last string not always null terminated (e.g. for Windows XP & 2000) */
+							ses->serverDomain =
+							    cifs_kcalloc(2 *
+								    (len +
+								     1),
+								    GFP_KERNEL);
+							cifs_strfromUCS_le
+							    (ses->
+							     serverDomain,
+							     (wchar_t *)
+							     bcc_ptr, len,
+							     nls_codepage);
+							bcc_ptr +=
+							    2 * (len + 1);
+							ses->
+							    serverDomain[2
+									 * len]
+							    = 0;
+							ses->
+							    serverDomain[1
+									 +
+									 (2
+									  *
+									  len)]
+							    = 0;
+						} /* else no more room so create dummy domain string */
+						else
+							ses->serverDomain = cifs_kcalloc(2,GFP_KERNEL);
+					} else {  /* no room so create dummy domain and NOS string */
+						ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL);
+						ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL);
+					}
+				} else {	/* ASCII */
+					len = strnlen(bcc_ptr, 1024);
+					if (((long) bcc_ptr + len) - 
+                        (long) pByteArea(smb_buffer_response) 
+                            <= BCC(smb_buffer_response)) {
+						ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
+						strncpy(ses->serverOS,bcc_ptr, len);
+
+						bcc_ptr += len;
+						bcc_ptr[0] = 0;	/* null terminate the string */
+						bcc_ptr++;
+
+						len = strnlen(bcc_ptr, 1024);
+						ses->serverNOS = cifs_kcalloc(len+1,GFP_KERNEL);
+						strncpy(ses->serverNOS, bcc_ptr, len);	
+						bcc_ptr += len;
+						bcc_ptr[0] = 0;
+						bcc_ptr++;
+
+						len = strnlen(bcc_ptr, 1024);
+						ses->serverDomain = cifs_kcalloc(len+1,GFP_KERNEL);
+						strncpy(ses->serverDomain, bcc_ptr, len);
+						bcc_ptr += len;
+						bcc_ptr[0] = 0;
+						bcc_ptr++;
+					} else
+						cFYI(1,
+						     ("Variable field of length %d extends beyond end of smb ",
+						      len));
+				}
+			} else {
+				cERROR(1,
+				       (" Security Blob Length extends beyond end of SMB"));
+			}
+		} else {
+			cERROR(1, ("No session structure passed in."));
+		}
+	} else {
+		cERROR(1,
+		       (" Invalid Word count %d: ",
+			smb_buffer_response->WordCount));
+		rc = -EIO;
+	}
+
+	if (smb_buffer)
+		cifs_buf_release(smb_buffer);
+
+	return rc;
+}
+
+int
+CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
+	 const char *tree, struct cifsTconInfo *tcon,
+	 const struct nls_table *nls_codepage)
+{
+	struct smb_hdr *smb_buffer;
+	struct smb_hdr *smb_buffer_response;
+	TCONX_REQ *pSMB;
+	TCONX_RSP *pSMBr;
+	unsigned char *bcc_ptr;
+	int rc = 0;
+	int length;
+	__u16 count;
+
+	if (ses == NULL)
+		return -EIO;
+
+	smb_buffer = cifs_buf_get();
+	if (smb_buffer == NULL) {
+		return -ENOMEM;
+	}
+	smb_buffer_response = smb_buffer;
+
+	header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
+			NULL /*no tid */ , 4 /*wct */ );
+	smb_buffer->Uid = ses->Suid;
+	pSMB = (TCONX_REQ *) smb_buffer;
+	pSMBr = (TCONX_RSP *) smb_buffer_response;
+
+	pSMB->AndXCommand = 0xFF;
+	pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
+	pSMB->PasswordLength = cpu_to_le16(1);	/* minimum */
+	bcc_ptr = &pSMB->Password[0];
+	bcc_ptr++;		/* skip password */
+
+	if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+		smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+
+	if (ses->capabilities & CAP_STATUS32) {
+		smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
+	}
+	if (ses->capabilities & CAP_DFS) {
+		smb_buffer->Flags2 |= SMBFLG2_DFS;
+	}
+	if (ses->capabilities & CAP_UNICODE) {
+		smb_buffer->Flags2 |= SMBFLG2_UNICODE;
+		length =
+		    cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage);
+		bcc_ptr += 2 * length;	/* convert num of 16 bit words to bytes */
+		bcc_ptr += 2;	/* skip trailing null */
+	} else {		/* ASCII */
+
+		strcpy(bcc_ptr, tree);
+		bcc_ptr += strlen(tree) + 1;
+	}
+	strcpy(bcc_ptr, "?????");
+	bcc_ptr += strlen("?????");
+	bcc_ptr += 1;
+	count = bcc_ptr - &pSMB->Password[0];
+	pSMB->hdr.smb_buf_length += count;
+	pSMB->ByteCount = cpu_to_le16(count);
+
+	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 */
+	if ((rc == 0) && (tcon != NULL)) {
+		tcon->tidStatus = CifsGood;
+		tcon->tid = smb_buffer_response->Tid;
+		bcc_ptr = pByteArea(smb_buffer_response);
+		length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
+        /* skip service field (NB: this field is always ASCII) */
+		bcc_ptr += length + 1;	
+		strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
+		if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
+			length = UniStrnlen((wchar_t *) bcc_ptr, 512);
+			if ((bcc_ptr + (2 * length)) -
+			     pByteArea(smb_buffer_response) <=
+			    BCC(smb_buffer_response)) {
+				if(tcon->nativeFileSystem)
+					kfree(tcon->nativeFileSystem);
+				tcon->nativeFileSystem =
+				    cifs_kcalloc(length + 2, GFP_KERNEL);
+				cifs_strfromUCS_le(tcon->nativeFileSystem,
+						   (wchar_t *) bcc_ptr,
+						   length, nls_codepage);
+				bcc_ptr += 2 * length;
+				bcc_ptr[0] = 0;	/* null terminate the string */
+				bcc_ptr[1] = 0;
+				bcc_ptr += 2;
+			}
+			/* else do not bother copying these informational fields */
+		} else {
+			length = strnlen(bcc_ptr, 1024);
+			if ((bcc_ptr + length) -
+			    pByteArea(smb_buffer_response) <=
+			    BCC(smb_buffer_response)) {
+				if(tcon->nativeFileSystem)
+					kfree(tcon->nativeFileSystem);
+				tcon->nativeFileSystem =
+				    cifs_kcalloc(length + 1, GFP_KERNEL);
+				strncpy(tcon->nativeFileSystem, bcc_ptr,
+					length);
+			}
+			/* else do not bother copying these informational fields */
+		}
+		tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
+		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;
+	}
+
+	if (smb_buffer)
+		cifs_buf_release(smb_buffer);
+	return rc;
+}
+
+int
+cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
+{
+	int rc = 0;
+	int xid;
+	struct cifsSesInfo *ses = NULL;
+	struct task_struct *cifsd_task;
+
+	xid = GetXid();
+
+	if (cifs_sb->tcon) {
+		ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
+		rc = CIFSSMBTDis(xid, cifs_sb->tcon);
+		if (rc == -EBUSY) {
+			FreeXid(xid);
+			return 0;
+		}
+		tconInfoFree(cifs_sb->tcon);
+		if ((ses) && (ses->server)) {
+			/* save off task so we do not refer to ses later */
+			cifsd_task = ses->server->tsk;
+			cFYI(1, ("About to do SMBLogoff "));
+			rc = CIFSSMBLogoff(xid, ses);
+			if (rc == -EBUSY) {
+				FreeXid(xid);
+				return 0;
+			} else if (rc == -ESHUTDOWN) {
+				cFYI(1,("Waking up socket by sending it signal"));
+				if(cifsd_task)
+					send_sig(SIGKILL,cifsd_task,1);
+				rc = 0;
+			} /* else - we have an smb session
+				left on this socket do not kill cifsd */
+		} else
+			cFYI(1, ("No session or bad tcon"));
+	}
+	
+	cifs_sb->tcon = NULL;
+	if (ses) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(HZ / 2);
+	}
+	if (ses)
+		sesInfoFree(ses);
+
+	FreeXid(xid);
+	return rc;		/* BB check if we should always return zero here */
+} 
+
+int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
+					   struct nls_table * nls_info)
+{
+	int rc = 0;
+	char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
+	int ntlmv2_flag = FALSE;
+
+	/* what if server changes its buffer size after dropping the session? */
+	if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
+		rc = CIFSSMBNegotiate(xid, pSesInfo);
+		if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
+			rc = CIFSSMBNegotiate(xid, pSesInfo);
+			if(rc == -EAGAIN) 
+				rc = -EHOSTDOWN;
+		}
+		if(rc == 0) {
+			spin_lock(&GlobalMid_Lock);
+			if(pSesInfo->server->tcpStatus != CifsExiting)
+				pSesInfo->server->tcpStatus = CifsGood;
+			else
+				rc = -EHOSTDOWN;
+			spin_unlock(&GlobalMid_Lock);
+
+		}
+	}
+	if (!rc) {
+		pSesInfo->capabilities = pSesInfo->server->capabilities;
+		if(linuxExtEnabled == 0)
+			pSesInfo->capabilities &= (~CAP_UNIX);
+		pSesInfo->sequence_number = 0;
+		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) {
+					char * v2_response;
+					cFYI(1,("Can use more secure NTLM version 2 password hash"));
+					if(CalcNTLMv2_partial_mac_key(pSesInfo, 
+						nls_info)) {
+						rc = -ENOMEM;
+						goto ss_err_exit;
+					} else
+						v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
+					if(v2_response) {
+						CalcNTLMv2_response(pSesInfo,v2_response);
+/*						cifs_calculate_ntlmv2_mac_key(pSesInfo->mac_signing_key, response, ntlm_session_key, */
+						kfree(v2_response);
+					/* BB Put dummy sig in SessSetup PDU? */
+					} else {
+						rc = -ENOMEM;
+						goto ss_err_exit;
+					}
+
+				} else {
+					SMBNTencrypt(pSesInfo->password,
+						pSesInfo->server->cryptKey,
+						ntlm_session_key);
+
+					cifs_calculate_mac_key(pSesInfo->mac_signing_key,
+						ntlm_session_key,
+						pSesInfo->password);
+				}
+			/* for better security the weaker lanman hash not sent
+			   in AuthSessSetup so we no longer calculate it */
+
+				rc = CIFSNTLMSSPAuthSessSetup(xid,
+					pSesInfo,
+					ntlm_session_key,
+					ntlmv2_flag,
+					nls_info);
+			}
+		} else { /* old style NTLM 0.12 session setup */
+			SMBNTencrypt(pSesInfo->password,
+				pSesInfo->server->cryptKey,
+				ntlm_session_key);
+
+			cifs_calculate_mac_key(pSesInfo->mac_signing_key, 
+				ntlm_session_key, pSesInfo->password);
+			rc = CIFSSessSetup(xid, pSesInfo,
+				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;
+		}
+	}
+ss_err_exit:
+	return rc;
+}
+
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
new file mode 100644
index 0000000..f54e186
--- /dev/null
+++ b/fs/cifs/dir.c
@@ -0,0 +1,523 @@
+/*
+ *   fs/cifs/dir.c
+ *
+ *   vfs operations that deal with dentries
+ * 
+ *   Copyright (C) International Business Machines  Corp., 2002,2003
+ *   Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <linux/slab.h>
+#include <linux/namei.h>
+#include "cifsfs.h"
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+#include "cifs_fs_sb.h"
+
+void
+renew_parental_timestamps(struct dentry *direntry)
+{
+	/* BB check if there is a way to get the kernel to do this or if we really need this */
+	do {
+		direntry->d_time = jiffies;
+		direntry = direntry->d_parent;
+	} while (!IS_ROOT(direntry));	
+}
+
+/* Note: caller must free return buffer */
+char *
+build_path_from_dentry(struct dentry *direntry)
+{
+	struct dentry *temp;
+	int namelen = 0;
+	char *full_path;
+
+	if(direntry == NULL)
+		return NULL;  /* not much we can do if dentry is freed and
+		we need to reopen the file after it was closed implicitly
+		when the server crashed */
+
+cifs_bp_rename_retry:
+	for (temp = direntry; !IS_ROOT(temp);) {
+		namelen += (1 + temp->d_name.len);
+		temp = temp->d_parent;
+		if(temp == NULL) {
+			cERROR(1,("corrupt dentry"));
+			return NULL;
+		}
+	}
+
+	full_path = kmalloc(namelen+1, GFP_KERNEL);
+	if(full_path == NULL)
+		return full_path;
+	full_path[namelen] = 0;	/* trailing null */
+
+	for (temp = direntry; !IS_ROOT(temp);) {
+		namelen -= 1 + temp->d_name.len;
+		if (namelen < 0) {
+			break;
+		} else {
+			full_path[namelen] = '\\';
+			strncpy(full_path + namelen + 1, temp->d_name.name,
+				temp->d_name.len);
+			cFYI(0, (" name: %s ", full_path + namelen));
+		}
+		temp = temp->d_parent;
+		if(temp == NULL) {
+			cERROR(1,("corrupt dentry"));
+			kfree(full_path);
+			return NULL;
+		}
+	}
+	if (namelen != 0) {
+		cERROR(1,
+		       ("We did not end path lookup where we expected namelen is %d",
+			namelen));
+		/* presumably this is only possible if we were racing with a rename 
+		of one of the parent directories  (we can not lock the dentries
+		above us to prevent this, but retrying should be harmless) */
+		kfree(full_path);
+		namelen = 0;
+		goto cifs_bp_rename_retry;
+	}
+
+	return full_path;
+}
+
+/* Note: caller must free return buffer */
+char *
+build_wildcard_path_from_dentry(struct dentry *direntry)
+{
+	struct dentry *temp;
+	int namelen = 0;
+	char *full_path;
+
+	if(direntry == NULL)
+		return NULL;  /* not much we can do if dentry is freed and
+		we need to reopen the file after it was closed implicitly
+		when the server crashed */
+
+cifs_bwp_rename_retry:
+	for (temp = direntry; !IS_ROOT(temp);) {
+		namelen += (1 + temp->d_name.len);
+		temp = temp->d_parent;
+		if(temp == NULL) {
+			cERROR(1,("corrupt dentry"));
+			return NULL;
+		}
+	}
+
+	full_path = kmalloc(namelen+3, GFP_KERNEL);
+	if(full_path == NULL)
+		return full_path;
+
+	full_path[namelen] = '\\';
+	full_path[namelen+1] = '*';
+	full_path[namelen+2] = 0;  /* trailing null */
+
+	for (temp = direntry; !IS_ROOT(temp);) {
+		namelen -= 1 + temp->d_name.len;
+		if (namelen < 0) {
+			break;
+		} else {
+			full_path[namelen] = '\\';
+			strncpy(full_path + namelen + 1, temp->d_name.name,
+				temp->d_name.len);
+			cFYI(0, (" name: %s ", full_path + namelen));
+		}
+		temp = temp->d_parent;
+		if(temp == NULL) {
+			cERROR(1,("corrupt dentry"));
+			kfree(full_path);
+			return NULL;
+		}
+	}
+	if (namelen != 0) {
+		cERROR(1,
+		       ("We did not end path lookup where we expected namelen is %d",
+			namelen));
+		/* presumably this is only possible if we were racing with a rename 
+		of one of the parent directories  (we can not lock the dentries
+		above us to prevent this, but retrying should be harmless) */
+		kfree(full_path);
+		namelen = 0;
+		goto cifs_bwp_rename_retry;
+	}
+
+	return full_path;
+}
+
+/* Inode operations in similar order to how they appear in the Linux file fs.h */
+
+int
+cifs_create(struct inode *inode, struct dentry *direntry, int mode,
+		struct nameidata *nd)
+{
+	int rc = -ENOENT;
+	int xid;
+	int oplock = 0;
+	int desiredAccess = GENERIC_READ | GENERIC_WRITE;
+	__u16 fileHandle;
+	struct cifs_sb_info *cifs_sb;
+	struct cifsTconInfo *pTcon;
+	char *full_path = NULL;
+	FILE_ALL_INFO * buf = NULL;
+	struct inode *newinode = NULL;
+	struct cifsFileInfo * pCifsFile = NULL;
+	struct cifsInodeInfo * pCifsInode;
+	int disposition = FILE_OVERWRITE_IF;
+	int write_only = FALSE;
+
+	xid = GetXid();
+
+	cifs_sb = CIFS_SB(inode->i_sb);
+	pTcon = cifs_sb->tcon;
+
+	down(&direntry->d_sb->s_vfs_rename_sem);
+	full_path = build_path_from_dentry(direntry);
+	up(&direntry->d_sb->s_vfs_rename_sem);
+	if(full_path == NULL) {
+		FreeXid(xid);
+		return -ENOMEM;
+	}
+
+	if(nd) {
+		if ((nd->intent.open.flags & O_ACCMODE) == O_RDONLY)
+			desiredAccess = GENERIC_READ;
+		else if ((nd->intent.open.flags & O_ACCMODE) == O_WRONLY) {
+			desiredAccess = GENERIC_WRITE;
+			write_only = TRUE;
+		} else if ((nd->intent.open.flags & O_ACCMODE) == O_RDWR) {
+			/* GENERIC_ALL is too much permission to request */
+			/* can cause unnecessary access denied on create */
+			/* desiredAccess = GENERIC_ALL; */
+			desiredAccess = GENERIC_READ | GENERIC_WRITE;
+		}
+
+		if((nd->intent.open.flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
+			disposition = FILE_CREATE;
+		else if((nd->intent.open.flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
+			disposition = FILE_OVERWRITE_IF;
+		else if((nd->intent.open.flags & O_CREAT) == O_CREAT)
+			disposition = FILE_OPEN_IF;
+		else {
+			cFYI(1,("Create flag not set in create function"));
+		}
+	}
+
+	/* BB add processing to set equivalent of mode - e.g. via CreateX with ACLs */
+	if (oplockEnabled)
+		oplock = REQ_OPLOCK;
+
+	buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
+	if(buf == NULL) {
+		kfree(full_path);
+		FreeXid(xid);
+		return -ENOMEM;
+	}
+
+	rc = CIFSSMBOpen(xid, pTcon, full_path, disposition,
+			 desiredAccess, CREATE_NOT_DIR,
+			 &fileHandle, &oplock, buf, cifs_sb->local_nls);
+	if (rc) {
+		cFYI(1, ("cifs_create returned 0x%x ", rc));
+	} else {
+		/* If Open reported that we actually created a file
+		then we now have to set the mode if possible */
+		if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
+			(oplock & CIFS_CREATE_ACTION))
+			if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
+				CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
+					(__u64)current->euid,
+					(__u64)current->egid,
+					0 /* dev */,
+					cifs_sb->local_nls);
+			} else {
+				CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
+					(__u64)-1,
+					(__u64)-1,
+					0 /* dev */,
+					cifs_sb->local_nls);
+			}
+		else {
+			/* BB implement via Windows security descriptors */
+			/* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
+			/* could set r/o dos attribute if mode & 0222 == 0 */
+		}
+
+	/* BB server might mask mode so we have to query for Unix case*/
+		if (pTcon->ses->capabilities & CAP_UNIX)
+			rc = cifs_get_inode_info_unix(&newinode, full_path,
+						 inode->i_sb,xid);
+		else {
+			rc = cifs_get_inode_info(&newinode, full_path,
+						 buf, inode->i_sb,xid);
+			if(newinode)
+				newinode->i_mode = mode;
+		}
+
+		if (rc != 0) {
+			cFYI(1,("Create worked but get_inode_info failed with rc = %d",
+			      rc));
+		} else {
+			direntry->d_op = &cifs_dentry_ops;
+			d_instantiate(direntry, newinode);
+		}
+		if((nd->flags & LOOKUP_OPEN) == FALSE) {
+			/* mknod case - do not leave file open */
+			CIFSSMBClose(xid, pTcon, fileHandle);
+		} else if(newinode) {
+			pCifsFile = (struct cifsFileInfo *)
+			   kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
+		
+			if (pCifsFile) {
+				memset((char *)pCifsFile, 0,
+				       sizeof (struct cifsFileInfo));
+				pCifsFile->netfid = fileHandle;
+				pCifsFile->pid = current->tgid;
+				pCifsFile->pInode = newinode;
+				pCifsFile->invalidHandle = FALSE;
+				pCifsFile->closePend     = FALSE;
+				init_MUTEX(&pCifsFile->fh_sem);
+				/* put the following in at open now */
+				/* pCifsFile->pfile = file; */ 
+				write_lock(&GlobalSMBSeslock);
+				list_add(&pCifsFile->tlist,&pTcon->openFileList);
+				pCifsInode = CIFS_I(newinode);
+				if(pCifsInode) {
+				/* if readable file instance put first in list*/
+					if (write_only == TRUE) {
+                                        	list_add_tail(&pCifsFile->flist,
+							&pCifsInode->openFileList);
+					} else {
+						list_add(&pCifsFile->flist,
+							&pCifsInode->openFileList);
+					}
+					if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
+						pCifsInode->clientCanCacheAll = TRUE;
+						pCifsInode->clientCanCacheRead = TRUE;
+						cFYI(1,("Exclusive Oplock granted on inode %p",
+							newinode));
+					} else if((oplock & 0xF) == OPLOCK_READ)
+						pCifsInode->clientCanCacheRead = TRUE;
+				}
+				write_unlock(&GlobalSMBSeslock);
+			}
+		}
+	} 
+
+	if (buf)
+	    kfree(buf);
+	if (full_path)
+	    kfree(full_path);
+	FreeXid(xid);
+
+	return rc;
+}
+
+int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t device_number) 
+{
+	int rc = -EPERM;
+	int xid;
+	struct cifs_sb_info *cifs_sb;
+	struct cifsTconInfo *pTcon;
+	char *full_path = NULL;
+	struct inode * newinode = NULL;
+
+	if (!old_valid_dev(device_number))
+		return -EINVAL;
+
+	xid = GetXid();
+
+	cifs_sb = CIFS_SB(inode->i_sb);
+	pTcon = cifs_sb->tcon;
+
+	down(&direntry->d_sb->s_vfs_rename_sem);
+	full_path = build_path_from_dentry(direntry);
+	up(&direntry->d_sb->s_vfs_rename_sem);
+	if(full_path == NULL)
+		rc = -ENOMEM;
+	
+	if (full_path && (pTcon->ses->capabilities & CAP_UNIX)) {
+		if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
+			rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
+				mode,(__u64)current->euid,(__u64)current->egid,
+				device_number, cifs_sb->local_nls);
+		} else {
+			rc = CIFSSMBUnixSetPerms(xid, pTcon,
+				full_path, mode, (__u64)-1, (__u64)-1,
+				device_number, cifs_sb->local_nls);
+		}
+
+		if(!rc) {
+			rc = cifs_get_inode_info_unix(&newinode, full_path,
+						inode->i_sb,xid);
+			direntry->d_op = &cifs_dentry_ops;
+			if(rc == 0)
+				d_instantiate(direntry, newinode);
+		}
+	}
+
+	if (full_path)
+		kfree(full_path);
+	FreeXid(xid);
+
+	return rc;
+}
+
+
+struct dentry *
+cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct nameidata *nd)
+{
+	int xid;
+	int rc = 0; /* to get around spurious gcc warning, set to zero here */
+	struct cifs_sb_info *cifs_sb;
+	struct cifsTconInfo *pTcon;
+	struct inode *newInode = NULL;
+	char *full_path = NULL;
+
+	xid = GetXid();
+
+	cFYI(1,
+	     (" parent inode = 0x%p name is: %s and dentry = 0x%p",
+	      parent_dir_inode, direntry->d_name.name, direntry));
+
+	/* BB Add check of incoming data - e.g. frame not longer than maximum SMB - let server check the namelen BB */
+
+	/* check whether path exists */
+
+	cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
+	pTcon = cifs_sb->tcon;
+
+	/* can not grab the rename sem here since it would
+	deadlock in the cases (beginning of sys_rename itself)
+	in which we already have the sb rename sem */
+	full_path = build_path_from_dentry(direntry);
+	if(full_path == NULL) {
+		FreeXid(xid);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	if (direntry->d_inode != NULL) {
+		cFYI(1, (" non-NULL inode in lookup"));
+	} else {
+		cFYI(1, (" NULL inode in lookup"));
+	}
+	cFYI(1,
+	     (" 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,xid);
+	else
+		rc = cifs_get_inode_info(&newInode, full_path, NULL,
+					 parent_dir_inode->i_sb,xid);
+
+	if ((rc == 0) && (newInode != NULL)) {
+		direntry->d_op = &cifs_dentry_ops;
+		d_add(direntry, newInode);
+
+		/* since paths are not looked up by component - the parent directories are presumed to be good here */
+		renew_parental_timestamps(direntry);
+
+	} else if (rc == -ENOENT) {
+		rc = 0;
+		d_add(direntry, NULL);
+	} else {
+		cERROR(1,("Error 0x%x or on cifs_get_inode_info in lookup",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 */
+	}
+
+	if (full_path)
+		kfree(full_path);
+	FreeXid(xid);
+	return ERR_PTR(rc);
+}
+
+int
+cifs_dir_open(struct inode *inode, struct file *file)
+{				/* NB: currently unused since searches are opened in readdir */
+	int rc = 0;
+	int xid;
+	struct cifs_sb_info *cifs_sb;
+	struct cifsTconInfo *pTcon;
+	char *full_path = NULL;
+
+	xid = GetXid();
+
+	cifs_sb = CIFS_SB(inode->i_sb);
+	pTcon = cifs_sb->tcon;
+
+	if(file->f_dentry) {
+		down(&file->f_dentry->d_sb->s_vfs_rename_sem);
+		full_path = build_wildcard_path_from_dentry(file->f_dentry);
+		up(&file->f_dentry->d_sb->s_vfs_rename_sem);
+	} else {
+		FreeXid(xid);
+		return -EIO;
+	}
+
+	cFYI(1, ("inode = 0x%p and full path is %s", inode, full_path));
+
+	if (full_path)
+		kfree(full_path);
+	FreeXid(xid);
+	return rc;
+}
+
+static int
+cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
+{
+	int isValid = 1;
+
+/*	lock_kernel(); *//* surely we do not want to lock the kernel for a whole network round trip which could take seconds */
+
+	if (direntry->d_inode) {
+		if (cifs_revalidate(direntry)) {
+			/* unlock_kernel(); */
+			return 0;
+		}
+	} else {
+		cFYI(1,
+		     ("In cifs_d_revalidate with no inode but name = %s and dentry 0x%p",
+		      direntry->d_name.name, direntry));
+	}
+
+/*    unlock_kernel(); */
+
+	return isValid;
+}
+
+/* static int cifs_d_delete(struct dentry *direntry)
+{
+	int rc = 0;
+
+	cFYI(1, ("In cifs d_delete, name = %s", direntry->d_name.name));
+
+	return rc;
+}     */
+
+struct dentry_operations cifs_dentry_ops = {
+	.d_revalidate = cifs_d_revalidate,
+/* d_delete:       cifs_d_delete,       *//* not needed except for debugging */
+	/* no need for d_hash, d_compare, d_release, d_iput ... yet. BB confirm this BB */
+};
diff --git a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c
new file mode 100644
index 0000000..9d24c40
--- /dev/null
+++ b/fs/cifs/fcntl.c
@@ -0,0 +1,117 @@
+/*
+ *   fs/cifs/fcntl.c
+ *
+ *   vfs operations that deal with the file control API
+ * 
+ *   Copyright (C) International Business Machines  Corp., 2003,2004
+ *   Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <linux/fcntl.h>
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_unicode.h"
+#include "cifs_debug.h"
+#include "cifsfs.h"
+
+static __u32 convert_to_cifs_notify_flags(unsigned long fcntl_notify_flags)
+{
+	__u32 cifs_ntfy_flags = 0;
+
+	/* No way on Linux VFS to ask to monitor xattr
+	changes (and no stream support either */
+	if(fcntl_notify_flags & DN_ACCESS) {
+		cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
+	}
+	if(fcntl_notify_flags & DN_MODIFY) {
+		/* What does this mean on directories? */
+		cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_WRITE |
+			FILE_NOTIFY_CHANGE_SIZE;
+	}
+	if(fcntl_notify_flags & DN_CREATE) {
+		cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_CREATION | 
+			FILE_NOTIFY_CHANGE_LAST_WRITE;
+	}
+	if(fcntl_notify_flags & DN_DELETE) {
+		cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_WRITE;
+	}
+	if(fcntl_notify_flags & DN_RENAME) {
+		/* BB review this - checking various server behaviors */
+		cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_DIR_NAME | 
+			FILE_NOTIFY_CHANGE_FILE_NAME;
+	}
+	if(fcntl_notify_flags & DN_ATTRIB) {
+		cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_SECURITY | 
+			FILE_NOTIFY_CHANGE_ATTRIBUTES;
+	}
+/*	if(fcntl_notify_flags & DN_MULTISHOT) {
+		cifs_ntfy_flags |= ;
+	} */ /* BB fixme - not sure how to handle this with CIFS yet */
+
+
+	return cifs_ntfy_flags;
+}
+
+int cifs_dir_notify(struct file * file, unsigned long arg)
+{
+	int xid;
+	int rc = -EINVAL;
+	int oplock = FALSE;
+	struct cifs_sb_info *cifs_sb;
+	struct cifsTconInfo *pTcon;
+	char *full_path = NULL;
+	__u32 filter = FILE_NOTIFY_CHANGE_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES;
+	__u16 netfid;
+
+	xid = GetXid();
+	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+	pTcon = cifs_sb->tcon;
+
+	down(&file->f_dentry->d_sb->s_vfs_rename_sem);
+	full_path = build_path_from_dentry(file->f_dentry);
+	up(&file->f_dentry->d_sb->s_vfs_rename_sem);
+
+	if(full_path == NULL) {
+		rc = -ENOMEM;
+	} else {
+		cERROR(1,("cifs dir notify on file %s with arg 0x%lx",full_path,arg)); /* BB removeme BB */
+		rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, 
+			GENERIC_READ | SYNCHRONIZE, 0 /* create options */,
+			&netfid, &oplock,NULL, cifs_sb->local_nls);
+		/* BB fixme - add this handle to a notify handle list */
+		if(rc) {
+			cERROR(1,("Could not open directory for notify"));  /* BB remove BB */
+		} else {
+			filter = convert_to_cifs_notify_flags(arg);
+			if(filter != 0) {
+				rc = CIFSSMBNotify(xid, pTcon, 0 /* no subdirs */, netfid, 
+					filter, cifs_sb->local_nls);
+			} else {
+				rc = -EINVAL;
+			}
+			/* BB add code to close file eventually (at unmount
+			it would close automatically but may be a way
+			to do it easily when inode freed or when
+			notify info is cleared/changed */
+            cERROR(1,("notify rc %d",rc));
+		}
+	}
+	
+	FreeXid(xid);
+	return rc;
+}
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
new file mode 100644
index 0000000..dcab7cf
--- /dev/null
+++ b/fs/cifs/file.c
@@ -0,0 +1,1675 @@
+/*
+ *   fs/cifs/file.c
+ *
+ *   vfs operations that deal with files
+ * 
+ *   Copyright (C) International Business Machines  Corp., 2002,2003
+ *   Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <linux/fcntl.h>
+#include <linux/pagemap.h>
+#include <linux/pagevec.h>
+#include <linux/smp_lock.h>
+#include <asm/div64.h>
+#include "cifsfs.h"
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_unicode.h"
+#include "cifs_debug.h"
+#include "cifs_fs_sb.h"
+
+static inline struct cifsFileInfo *cifs_init_private(
+	struct cifsFileInfo *private_data, struct inode *inode,
+	struct file *file, __u16 netfid)
+{
+	memset(private_data, 0, sizeof(struct cifsFileInfo));
+	private_data->netfid = netfid;
+	private_data->pid = current->tgid;	
+	init_MUTEX(&private_data->fh_sem);
+	private_data->pfile = file; /* needed for writepage */
+	private_data->pInode = inode;
+	private_data->invalidHandle = FALSE;
+	private_data->closePend = FALSE;
+
+	return private_data;
+}
+
+static inline int cifs_convert_flags(unsigned int flags)
+{
+	if ((flags & O_ACCMODE) == O_RDONLY)
+		return GENERIC_READ;
+	else if ((flags & O_ACCMODE) == O_WRONLY)
+		return GENERIC_WRITE;
+	else if ((flags & O_ACCMODE) == O_RDWR) {
+		/* GENERIC_ALL is too much permission to request
+		   can cause unnecessary access denied on create */
+		/* return GENERIC_ALL; */
+		return (GENERIC_READ | GENERIC_WRITE);
+	}
+
+	return 0x20197;
+}
+
+static inline int cifs_get_disposition(unsigned int flags)
+{
+	if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
+		return FILE_CREATE;
+	else if ((flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
+		return FILE_OVERWRITE_IF;
+	else if ((flags & O_CREAT) == O_CREAT)
+		return FILE_OPEN_IF;
+	else
+		return FILE_OPEN;
+}
+
+/* all arguments to this function must be checked for validity in caller */
+static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
+	struct cifsInodeInfo *pCifsInode, struct cifsFileInfo *pCifsFile,
+	struct cifsTconInfo *pTcon, int *oplock, FILE_ALL_INFO *buf,
+	char *full_path, int xid)
+{
+	struct timespec temp;
+	int rc;
+
+	/* want handles we can use to read with first
+	   in the list so we do not have to walk the
+	   list to search for one in prepare_write */
+	if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
+		list_add_tail(&pCifsFile->flist, 
+			      &pCifsInode->openFileList);
+	} else {
+		list_add(&pCifsFile->flist,
+			 &pCifsInode->openFileList);
+	}
+	write_unlock(&GlobalSMBSeslock);
+	write_unlock(&file->f_owner.lock);
+	if (pCifsInode->clientCanCacheRead) {
+		/* we have the inode open somewhere else
+		   no need to discard cache data */
+		goto client_can_cache;
+	}
+
+	/* BB need same check in cifs_create too? */
+	/* if not oplocked, invalidate inode pages if mtime or file
+	   size changed */
+	temp = cifs_NTtimeToUnix(le64_to_cpu(buf->LastWriteTime));
+	if (timespec_equal(&file->f_dentry->d_inode->i_mtime, &temp) && 
+			   (file->f_dentry->d_inode->i_size == 
+			    (loff_t)le64_to_cpu(buf->EndOfFile))) {
+		cFYI(1, ("inode unchanged on server"));
+	} else {
+		if (file->f_dentry->d_inode->i_mapping) {
+		/* BB no need to lock inode until after invalidate
+		   since namei code should already have it locked? */
+			filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
+			filemap_fdatawait(file->f_dentry->d_inode->i_mapping);
+		}
+		cFYI(1, ("invalidating remote inode since open detected it "
+			 "changed"));
+		invalidate_remote_inode(file->f_dentry->d_inode);
+	}
+
+client_can_cache:
+	if (pTcon->ses->capabilities & CAP_UNIX)
+		rc = cifs_get_inode_info_unix(&file->f_dentry->d_inode,
+			full_path, inode->i_sb, xid);
+	else
+		rc = cifs_get_inode_info(&file->f_dentry->d_inode,
+			full_path, buf, inode->i_sb, xid);
+
+	if ((*oplock & 0xF) == OPLOCK_EXCLUSIVE) {
+		pCifsInode->clientCanCacheAll = TRUE;
+		pCifsInode->clientCanCacheRead = TRUE;
+		cFYI(1, ("Exclusive Oplock granted on inode %p",
+			 file->f_dentry->d_inode));
+	} else if ((*oplock & 0xF) == OPLOCK_READ)
+		pCifsInode->clientCanCacheRead = TRUE;
+
+	return rc;
+}
+
+int cifs_open(struct inode *inode, struct file *file)
+{
+	int rc = -EACCES;
+	int xid, oplock;
+	struct cifs_sb_info *cifs_sb;
+	struct cifsTconInfo *pTcon;
+	struct cifsFileInfo *pCifsFile;
+	struct cifsInodeInfo *pCifsInode;
+	struct list_head *tmp;
+	char *full_path = NULL;
+	int desiredAccess;
+	int disposition;
+	__u16 netfid;
+	FILE_ALL_INFO *buf = NULL;
+
+	xid = GetXid();
+
+	cifs_sb = CIFS_SB(inode->i_sb);
+	pTcon = cifs_sb->tcon;
+
+	if (file->f_flags & O_CREAT) {
+		/* search inode for this file and fill in file->private_data */
+		pCifsInode = CIFS_I(file->f_dentry->d_inode);
+		read_lock(&GlobalSMBSeslock);
+		list_for_each(tmp, &pCifsInode->openFileList) {
+			pCifsFile = list_entry(tmp, struct cifsFileInfo,
+					       flist);
+			if ((pCifsFile->pfile == NULL) &&
+			    (pCifsFile->pid == current->tgid)) {
+				/* mode set in cifs_create */
+
+				/* needed for writepage */
+				pCifsFile->pfile = file;
+				
+				file->private_data = pCifsFile;
+				break;
+			}
+		}
+		read_unlock(&GlobalSMBSeslock);
+		if (file->private_data != NULL) {
+			rc = 0;
+			FreeXid(xid);
+			return rc;
+		} else {
+			if (file->f_flags & O_EXCL)
+				cERROR(1, ("could not find file instance for "
+					   "new file %p ", file));
+		}
+	}
+
+	down(&inode->i_sb->s_vfs_rename_sem);
+	full_path = build_path_from_dentry(file->f_dentry);
+	up(&inode->i_sb->s_vfs_rename_sem);
+	if (full_path == NULL) {
+		FreeXid(xid);
+		return -ENOMEM;
+	}
+
+	cFYI(1, (" inode = 0x%p file flags are 0x%x for %s",
+		 inode, file->f_flags, full_path));
+	desiredAccess = cifs_convert_flags(file->f_flags);
+
+/*********************************************************************
+ *  open flag mapping table:
+ *  
+ *	POSIX Flag            CIFS Disposition
+ *	----------            ---------------- 
+ *	O_CREAT               FILE_OPEN_IF
+ *	O_CREAT | O_EXCL      FILE_CREATE
+ *	O_CREAT | O_TRUNC     FILE_OVERWRITE_IF
+ *	O_TRUNC               FILE_OVERWRITE
+ *	none of the above     FILE_OPEN
+ *
+ *	Note that there is not a direct match between disposition
+ *	FILE_SUPERSEDE (ie create whether or not file exists although 
+ *	O_CREAT | O_TRUNC is similar but truncates the existing
+ *	file rather than creating a new file as FILE_SUPERSEDE does
+ *	(which uses the attributes / metadata passed in on open call)
+ *?
+ *?  O_SYNC is a reasonable match to CIFS writethrough flag  
+ *?  and the read write flags match reasonably.  O_LARGEFILE
+ *?  is irrelevant because largefile support is always used
+ *?  by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY,
+ *	 O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation
+ *********************************************************************/
+
+	disposition = cifs_get_disposition(file->f_flags);
+
+	if (oplockEnabled)
+		oplock = REQ_OPLOCK;
+	else
+		oplock = FALSE;
+
+	/* BB pass O_SYNC flag through on file attributes .. BB */
+
+	/* Also refresh inode by passing in file_info buf returned by SMBOpen
+	   and calling get_inode_info with returned buf (at least helps
+	   non-Unix server case) */
+
+	/* BB we can not do this if this is the second open of a file 
+	   and the first handle has writebehind data, we might be 
+	   able to simply do a filemap_fdatawrite/filemap_fdatawait first */
+	buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
+	if (!buf) {
+		rc = -ENOMEM;
+		goto out;
+	}
+	rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
+			 CREATE_NOT_DIR, &netfid, &oplock, buf,
+			 cifs_sb->local_nls);
+	if (rc) {
+		cFYI(1, ("cifs_open returned 0x%x ", rc));
+		goto out;
+	}
+	file->private_data =
+		kmalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
+	if (file->private_data == NULL) {
+		rc = -ENOMEM;
+		goto out;
+	}
+	pCifsFile = cifs_init_private(file->private_data, inode, file, netfid);
+	write_lock(&file->f_owner.lock);
+	write_lock(&GlobalSMBSeslock);
+	list_add(&pCifsFile->tlist, &pTcon->openFileList);
+
+	pCifsInode = CIFS_I(file->f_dentry->d_inode);
+	if (pCifsInode) {
+		rc = cifs_open_inode_helper(inode, file, pCifsInode,
+					    pCifsFile, pTcon,
+					    &oplock, buf, full_path, xid);
+	} else {
+		write_unlock(&GlobalSMBSeslock);
+		write_unlock(&file->f_owner.lock);
+	}
+
+	if (oplock & CIFS_CREATE_ACTION) {           
+		/* time to set mode which we can not set earlier due to
+		   problems creating new read-only files */
+		if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
+			CIFSSMBUnixSetPerms(xid, pTcon, full_path,
+					    inode->i_mode,
+					    (__u64)-1, (__u64)-1, 0 /* dev */,
+					    cifs_sb->local_nls);
+		} else {
+			/* BB implement via Windows security descriptors eg
+			   CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
+					      -1, -1, local_nls);
+			   in the meantime could set r/o dos attribute when
+			   perms are eg: mode & 0222 == 0 */
+		}
+	}
+
+out:
+	kfree(buf);
+	kfree(full_path);
+	FreeXid(xid);
+	return rc;
+}
+
+/* Try to reaquire byte range locks that were released when session */
+/* to server was lost */
+static int cifs_relock_file(struct cifsFileInfo *cifsFile)
+{
+	int rc = 0;
+
+/* BB list all locks open on this file and relock */
+
+	return rc;
+}
+
+static int cifs_reopen_file(struct inode *inode, struct file *file, 
+	int can_flush)
+{
+	int rc = -EACCES;
+	int xid, oplock;
+	struct cifs_sb_info *cifs_sb;
+	struct cifsTconInfo *pTcon;
+	struct cifsFileInfo *pCifsFile;
+	struct cifsInodeInfo *pCifsInode;
+	char *full_path = NULL;
+	int desiredAccess;
+	int disposition = FILE_OPEN;
+	__u16 netfid;
+
+	if (inode == NULL)
+		return -EBADF;
+	if (file->private_data) {
+		pCifsFile = (struct cifsFileInfo *)file->private_data;
+	} else
+		return -EBADF;
+
+	xid = GetXid();
+	down(&pCifsFile->fh_sem);
+	if (pCifsFile->invalidHandle == FALSE) {
+		up(&pCifsFile->fh_sem);
+		FreeXid(xid);
+		return 0;
+	}
+
+	if (file->f_dentry == NULL) {
+		up(&pCifsFile->fh_sem);
+		cFYI(1, ("failed file reopen, no valid name if dentry freed"));
+		FreeXid(xid);
+		return -EBADF;
+	}
+	cifs_sb = CIFS_SB(inode->i_sb);
+	pTcon = cifs_sb->tcon;
+/* can not grab rename sem here because various ops, including
+   those that already have the rename sem can end up causing writepage
+   to get called and if the server was down that means we end up here,
+   and we can never tell if the caller already has the rename_sem */
+	full_path = build_path_from_dentry(file->f_dentry);
+	if (full_path == NULL) {
+		up(&pCifsFile->fh_sem);
+		FreeXid(xid);
+		return -ENOMEM;
+	}
+
+	cFYI(1, (" inode = 0x%p file flags are 0x%x for %s",
+		 inode, file->f_flags,full_path));
+	desiredAccess = cifs_convert_flags(file->f_flags);
+
+	if (oplockEnabled)
+		oplock = REQ_OPLOCK;
+	else
+		oplock = FALSE;
+
+	/* Can not refresh inode by passing in file_info buf to be returned
+	   by SMBOpen and then calling get_inode_info with returned buf 
+	   since file might have write behind data that needs to be flushed 
+	   and server version of file size can be stale. If we knew for sure
+	   that inode was not dirty locally we could do this */
+
+/*	buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
+	if (buf == 0) {
+		up(&pCifsFile->fh_sem);
+		kfree(full_path);
+		FreeXid(xid);
+		return -ENOMEM;
+	} */
+	rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
+			 CREATE_NOT_DIR, &netfid, &oplock, NULL,
+			 cifs_sb->local_nls);
+	if (rc) {
+		up(&pCifsFile->fh_sem);
+		cFYI(1, ("cifs_open returned 0x%x ", rc));
+		cFYI(1, ("oplock: %d ", oplock));
+	} else {
+		pCifsFile->netfid = netfid;
+		pCifsFile->invalidHandle = FALSE;
+		up(&pCifsFile->fh_sem);
+		pCifsInode = CIFS_I(inode);
+		if (pCifsInode) {
+			if (can_flush) {
+				filemap_fdatawrite(inode->i_mapping);
+				filemap_fdatawait(inode->i_mapping);
+			/* temporarily disable caching while we
+			   go to server to get inode info */
+				pCifsInode->clientCanCacheAll = FALSE;
+				pCifsInode->clientCanCacheRead = FALSE;
+				if (pTcon->ses->capabilities & CAP_UNIX)
+					rc = cifs_get_inode_info_unix(&inode,
+						full_path, inode->i_sb, xid);
+				else
+					rc = cifs_get_inode_info(&inode,
+						full_path, NULL, inode->i_sb,
+						xid);
+			} /* else we are writing out data to server already
+			     and could deadlock if we tried to flush data, and
+			     since we do not know if we have data that would
+			     invalidate the current end of file on the server
+			     we can not go to the server to get the new inod
+			     info */
+			if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
+				pCifsInode->clientCanCacheAll = TRUE;
+				pCifsInode->clientCanCacheRead = TRUE;
+				cFYI(1, ("Exclusive Oplock granted on inode %p",
+					 file->f_dentry->d_inode));
+			} else if ((oplock & 0xF) == OPLOCK_READ) {
+				pCifsInode->clientCanCacheRead = TRUE;
+				pCifsInode->clientCanCacheAll = FALSE;
+			} else {
+				pCifsInode->clientCanCacheRead = FALSE;
+				pCifsInode->clientCanCacheAll = FALSE;
+			}
+			cifs_relock_file(pCifsFile);
+		}
+	}
+
+	kfree(full_path);
+	FreeXid(xid);
+	return rc;
+}
+
+int cifs_close(struct inode *inode, struct file *file)
+{
+	int rc = 0;
+	int xid;
+	struct cifs_sb_info *cifs_sb;
+	struct cifsTconInfo *pTcon;
+	struct cifsFileInfo *pSMBFile =
+		(struct cifsFileInfo *)file->private_data;
+
+	xid = GetXid();
+
+	cifs_sb = CIFS_SB(inode->i_sb);
+	pTcon = cifs_sb->tcon;
+	if (pSMBFile) {
+		pSMBFile->closePend = TRUE;
+		write_lock(&file->f_owner.lock);
+		if (pTcon) {
+			/* no sense reconnecting to close a file that is
+			   already closed */
+			if (pTcon->tidStatus != CifsNeedReconnect) {
+				write_unlock(&file->f_owner.lock);
+				rc = CIFSSMBClose(xid, pTcon,
+						  pSMBFile->netfid);
+				write_lock(&file->f_owner.lock);
+			}
+		}
+		list_del(&pSMBFile->flist);
+		list_del(&pSMBFile->tlist);
+		write_unlock(&file->f_owner.lock);
+		kfree(pSMBFile->search_resume_name);
+		kfree(file->private_data);
+		file->private_data = NULL;
+	} else
+		rc = -EBADF;
+
+	if (list_empty(&(CIFS_I(inode)->openFileList))) {
+		cFYI(1, ("closing last open instance for inode %p", inode));
+		/* if the file is not open we do not know if we can cache info
+		   on this inode, much less write behind and read ahead */
+		CIFS_I(inode)->clientCanCacheRead = FALSE;
+		CIFS_I(inode)->clientCanCacheAll  = FALSE;
+	}
+	if ((rc ==0) && CIFS_I(inode)->write_behind_rc)
+		rc = CIFS_I(inode)->write_behind_rc;
+	FreeXid(xid);
+	return rc;
+}
+
+int cifs_closedir(struct inode *inode, struct file *file)
+{
+	int rc = 0;
+	int xid;
+	struct cifsFileInfo *pCFileStruct =
+	    (struct cifsFileInfo *)file->private_data;
+	char *ptmp;
+
+	cFYI(1, ("Closedir inode = 0x%p with ", inode));
+
+	xid = GetXid();
+
+	if (pCFileStruct) {
+		struct cifsTconInfo *pTcon;
+		struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+
+		pTcon = cifs_sb->tcon;
+
+		cFYI(1, ("Freeing private data in close dir"));
+		if (pCFileStruct->srch_inf.endOfSearch == FALSE) {
+			pCFileStruct->invalidHandle = TRUE;
+			rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid);
+			cFYI(1, ("Closing uncompleted readdir with rc %d",
+				 rc));
+			/* not much we can do if it fails anyway, ignore rc */
+			rc = 0;
+		}
+		ptmp = pCFileStruct->srch_inf.ntwrk_buf_start;
+		if (ptmp) {
+   /* BB removeme BB */	cFYI(1, ("freeing smb buf in srch struct in closedir"));
+			pCFileStruct->srch_inf.ntwrk_buf_start = NULL;
+			cifs_buf_release(ptmp);
+		}
+		ptmp = pCFileStruct->search_resume_name;
+		if (ptmp) {
+   /* BB removeme BB */	cFYI(1, ("freeing resume name in closedir"));
+			pCFileStruct->search_resume_name = NULL;
+			kfree(ptmp);
+		}
+		kfree(file->private_data);
+		file->private_data = NULL;
+	}
+	/* BB can we lock the filestruct while this is going on? */
+	FreeXid(xid);
+	return rc;
+}
+
+int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
+{
+	int rc, xid;
+	__u32 lockType = LOCKING_ANDX_LARGE_FILES;
+	__u32 numLock = 0;
+	__u32 numUnlock = 0;
+	__u64 length;
+	int wait_flag = FALSE;
+	struct cifs_sb_info *cifs_sb;
+	struct cifsTconInfo *pTcon;
+
+	length = 1 + pfLock->fl_end - pfLock->fl_start;
+	rc = -EACCES;
+	xid = GetXid();
+
+	cFYI(1, ("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, ("Posix "));
+	if (pfLock->fl_flags & FL_FLOCK)
+		cFYI(1, ("Flock "));
+	if (pfLock->fl_flags & FL_SLEEP) {
+		cFYI(1, ("Blocking lock "));
+		wait_flag = TRUE;
+	}
+	if (pfLock->fl_flags & FL_ACCESS)
+		cFYI(1, ("Process suspended by mandatory locking - "
+			 "not implemented yet "));
+	if (pfLock->fl_flags & FL_LEASE)
+		cFYI(1, ("Lease on file - not implemented yet"));
+	if (pfLock->fl_flags & 
+	    (~(FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | FL_LEASE)))
+		cFYI(1, ("Unknown lock flags 0x%x", pfLock->fl_flags));
+
+	if (pfLock->fl_type == F_WRLCK) {
+		cFYI(1, ("F_WRLCK "));
+		numLock = 1;
+	} else if (pfLock->fl_type == F_UNLCK) {
+		cFYI(1, ("F_UNLCK "));
+		numUnlock = 1;
+	} else if (pfLock->fl_type == F_RDLCK) {
+		cFYI(1, ("F_RDLCK "));
+		lockType |= LOCKING_ANDX_SHARED_LOCK;
+		numLock = 1;
+	} else if (pfLock->fl_type == F_EXLCK) {
+		cFYI(1, ("F_EXLCK "));
+		numLock = 1;
+	} else if (pfLock->fl_type == F_SHLCK) {
+		cFYI(1, ("F_SHLCK "));
+		lockType |= LOCKING_ANDX_SHARED_LOCK;
+		numLock = 1;
+	} else
+		cFYI(1, ("Unknown type of lock "));
+
+	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+	pTcon = cifs_sb->tcon;
+
+	if (file->private_data == NULL) {
+		FreeXid(xid);
+		return -EBADF;
+	}
+
+	if (IS_GETLK(cmd)) {
+		rc = CIFSSMBLock(xid, pTcon,
+				 ((struct cifsFileInfo *)file->
+				  private_data)->netfid,
+				 length,
+				 pfLock->fl_start, 0, 1, lockType,
+				 0 /* wait flag */ );
+		if (rc == 0) {
+			rc = CIFSSMBLock(xid, pTcon,
+					 ((struct cifsFileInfo *) file->
+					  private_data)->netfid,
+					 length,
+					 pfLock->fl_start, 1 /* numUnlock */ ,
+					 0 /* numLock */ , lockType,
+					 0 /* wait flag */ );
+			pfLock->fl_type = F_UNLCK;
+			if (rc != 0)
+				cERROR(1, ("Error unlocking previously locked "
+					   "range %d during test of lock ",
+					   rc));
+			rc = 0;
+
+		} else {
+			/* if rc == ERR_SHARING_VIOLATION ? */
+			rc = 0;	/* do not change lock type to unlock
+				   since range in use */
+		}
+
+		FreeXid(xid);
+		return rc;
+	}
+
+	rc = CIFSSMBLock(xid, pTcon,
+			 ((struct cifsFileInfo *) file->private_data)->
+			 netfid, length,
+			 pfLock->fl_start, numUnlock, numLock, lockType,
+			 wait_flag);
+	if (rc == 0 && (pfLock->fl_flags & FL_POSIX))
+		posix_lock_file_wait(file, pfLock);
+	FreeXid(xid);
+	return rc;
+}
+
+ssize_t cifs_user_write(struct file *file, const char __user *write_data,
+	size_t write_size, loff_t *poffset)
+{
+	int rc = 0;
+	unsigned int bytes_written = 0;
+	unsigned int total_written;
+	struct cifs_sb_info *cifs_sb;
+	struct cifsTconInfo *pTcon;
+	int xid, long_op;
+	struct cifsFileInfo *open_file;
+
+	if (file->f_dentry == NULL)
+		return -EBADF;
+
+	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+	if (cifs_sb == NULL)
+		return -EBADF;
+
+	pTcon = cifs_sb->tcon;
+
+	/* cFYI(1,
+	   (" write %d bytes to offset %lld of %s", write_size,
+	   *poffset, file->f_dentry->d_name.name)); */
+
+	if (file->private_data == NULL)
+		return -EBADF;
+	else
+		open_file = (struct cifsFileInfo *) file->private_data;
+	
+	xid = GetXid();
+	if (file->f_dentry->d_inode == NULL) {
+		FreeXid(xid);
+		return -EBADF;
+	}
+
+	if (*poffset > file->f_dentry->d_inode->i_size)
+		long_op = 2; /* writes past end of file can take a long time */
+	else
+		long_op = 1;
+
+	for (total_written = 0; write_size > total_written;
+	     total_written += bytes_written) {
+		rc = -EAGAIN;
+		while (rc == -EAGAIN) {
+			if (file->private_data == NULL) {
+				/* file has been closed on us */
+				FreeXid(xid);
+			/* if we have gotten here we have written some data
+			   and blocked, and the file has been freed on us while
+			   we blocked so return what we managed to write */
+				return total_written;
+			} 
+			if (open_file->closePend) {
+				FreeXid(xid);
+				if (total_written)
+					return total_written;
+				else
+					return -EBADF;
+			}
+			if (open_file->invalidHandle) {
+				if ((file->f_dentry == NULL) ||
+				    (file->f_dentry->d_inode == NULL)) {
+					FreeXid(xid);
+					return total_written;
+				}
+				/* we could deadlock if we called
+				   filemap_fdatawait from here so tell
+				   reopen_file not to flush data to server
+				   now */
+				rc = cifs_reopen_file(file->f_dentry->d_inode,
+					file, FALSE);
+				if (rc != 0)
+					break;
+			}
+
+			rc = CIFSSMBWrite(xid, pTcon,
+				open_file->netfid,
+				min_t(const int, cifs_sb->wsize,
+				      write_size - total_written),
+				*poffset, &bytes_written,
+				NULL, write_data + total_written, long_op);
+		}
+		if (rc || (bytes_written == 0)) {
+			if (total_written)
+				break;
+			else {
+				FreeXid(xid);
+				return rc;
+			}
+		} else
+			*poffset += bytes_written;
+		long_op = FALSE; /* subsequent writes fast -
+				    15 seconds is plenty */
+	}
+
+#ifdef CONFIG_CIFS_STATS
+	if (total_written > 0) {
+		atomic_inc(&pTcon->num_writes);
+		spin_lock(&pTcon->stat_lock);
+		pTcon->bytes_written += total_written;
+		spin_unlock(&pTcon->stat_lock);
+	}
+#endif		
+
+	/* since the write may have blocked check these pointers again */
+	if (file->f_dentry) {
+		if (file->f_dentry->d_inode) {
+			struct inode *inode = file->f_dentry->d_inode;
+			inode->i_ctime = inode->i_mtime =
+				current_fs_time(inode->i_sb);
+			if (total_written > 0) {
+				if (*poffset > file->f_dentry->d_inode->i_size)
+					i_size_write(file->f_dentry->d_inode,
+					*poffset);
+			}
+			mark_inode_dirty_sync(file->f_dentry->d_inode);
+		}
+	}
+	FreeXid(xid);
+	return total_written;
+}
+
+static ssize_t cifs_write(struct file *file, const char *write_data,
+	size_t write_size, loff_t *poffset)
+{
+	int rc = 0;
+	unsigned int bytes_written = 0;
+	unsigned int total_written;
+	struct cifs_sb_info *cifs_sb;
+	struct cifsTconInfo *pTcon;
+	int xid, long_op;
+	struct cifsFileInfo *open_file;
+
+	if (file->f_dentry == NULL)
+		return -EBADF;
+
+	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+	if (cifs_sb == NULL)
+		return -EBADF;
+
+	pTcon = cifs_sb->tcon;
+
+	/* cFYI(1,
+	   (" write %d bytes to offset %lld of %s", write_size,
+	   *poffset, file->f_dentry->d_name.name)); */
+
+	if (file->private_data == NULL)
+		return -EBADF;
+	else
+		open_file = (struct cifsFileInfo *)file->private_data;
+	
+	xid = GetXid();
+	if (file->f_dentry->d_inode == NULL) {
+		FreeXid(xid);
+		return -EBADF;
+	}
+
+	if (*poffset > file->f_dentry->d_inode->i_size)
+		long_op = 2; /* writes past end of file can take a long time */
+	else
+		long_op = 1;
+
+	for (total_written = 0; write_size > total_written;
+	     total_written += bytes_written) {
+		rc = -EAGAIN;
+		while (rc == -EAGAIN) {
+			if (file->private_data == NULL) {
+				/* file has been closed on us */
+				FreeXid(xid);
+			/* if we have gotten here we have written some data
+			   and blocked, and the file has been freed on us
+			   while we blocked so return what we managed to 
+			   write */
+				return total_written;
+			} 
+			if (open_file->closePend) {
+				FreeXid(xid);
+				if (total_written)
+					return total_written;
+				else
+					return -EBADF;
+			}
+			if (open_file->invalidHandle) {
+				if ((file->f_dentry == NULL) ||
+				   (file->f_dentry->d_inode == NULL)) {
+					FreeXid(xid);
+					return total_written;
+				}
+				/* we could deadlock if we called
+				   filemap_fdatawait from here so tell
+				   reopen_file not to flush data to 
+				   server now */
+				rc = cifs_reopen_file(file->f_dentry->d_inode,
+					file, FALSE);
+				if (rc != 0)
+					break;
+			}
+
+			rc = CIFSSMBWrite(xid, pTcon,
+				 open_file->netfid,
+				 min_t(const int, cifs_sb->wsize, 
+				       write_size - total_written),
+				 *poffset, &bytes_written,
+				 write_data + total_written, NULL, long_op);
+		}
+		if (rc || (bytes_written == 0)) {
+			if (total_written)
+				break;
+			else {
+				FreeXid(xid);
+				return rc;
+			}
+		} else
+			*poffset += bytes_written;
+		long_op = FALSE; /* subsequent writes fast - 
+				    15 seconds is plenty */
+	}
+
+#ifdef CONFIG_CIFS_STATS
+	if (total_written > 0) {
+		atomic_inc(&pTcon->num_writes);
+		spin_lock(&pTcon->stat_lock);
+		pTcon->bytes_written += total_written;
+		spin_unlock(&pTcon->stat_lock);
+	}
+#endif		
+
+	/* since the write may have blocked check these pointers again */
+	if (file->f_dentry) {
+		if (file->f_dentry->d_inode) {
+			file->f_dentry->d_inode->i_ctime = 
+			file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
+			if (total_written > 0) {
+				if (*poffset > file->f_dentry->d_inode->i_size)
+					i_size_write(file->f_dentry->d_inode, 
+						     *poffset);
+			}
+			mark_inode_dirty_sync(file->f_dentry->d_inode);
+		}
+	}
+	FreeXid(xid);
+	return total_written;
+}
+
+static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
+{
+	struct address_space *mapping = page->mapping;
+	loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
+	char *write_data;
+	int rc = -EFAULT;
+	int bytes_written = 0;
+	struct cifs_sb_info *cifs_sb;
+	struct cifsTconInfo *pTcon;
+	struct inode *inode;
+	struct cifsInodeInfo *cifsInode;
+	struct cifsFileInfo *open_file = NULL;
+	struct list_head *tmp;
+	struct list_head *tmp1;
+
+	if (!mapping || !mapping->host)
+		return -EFAULT;
+
+	inode = page->mapping->host;
+	cifs_sb = CIFS_SB(inode->i_sb);
+	pTcon = cifs_sb->tcon;
+
+	offset += (loff_t)from;
+	write_data = kmap(page);
+	write_data += from;
+
+	if ((to > PAGE_CACHE_SIZE) || (from > to)) {
+		kunmap(page);
+		return -EIO;
+	}
+
+	/* racing with truncate? */
+	if (offset > mapping->host->i_size) {
+		kunmap(page);
+		return 0; /* don't care */
+	}
+
+	/* 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);
+	read_lock(&GlobalSMBSeslock); 
+	/* BB we should start at the end */
+	list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {            
+		open_file = list_entry(tmp, struct cifsFileInfo, flist);
+		if (open_file->closePend)
+			continue;
+		/* We check if file is open for writing first */
+		if ((open_file->pfile) && 
+		   ((open_file->pfile->f_flags & O_RDWR) || 
+			(open_file->pfile->f_flags & O_WRONLY))) {
+			read_unlock(&GlobalSMBSeslock);
+			bytes_written = cifs_write(open_file->pfile,
+						write_data, to-from,
+						&offset);
+			read_lock(&GlobalSMBSeslock);
+		/* Does mm or vfs already set times? */
+			inode->i_atime = 
+			inode->i_mtime = current_fs_time(inode->i_sb);
+			if ((bytes_written > 0) && (offset)) {
+				rc = 0;
+			} else if (bytes_written < 0) {
+				if (rc == -EBADF) {
+				/* have seen a case in which kernel seemed to
+				   have closed/freed a file even with writes
+				   active so we might as well see if there are
+				   other file structs to try for the same
+				   inode before giving up */
+					continue;
+				} else
+					rc = bytes_written;
+			}
+			break;  /* now that we found a valid file handle and
+				   tried to write to it we are done, no sense
+				   continuing to loop looking for another */
+		}
+		if (tmp->next == NULL) {
+			cFYI(1, ("File instance %p removed", tmp));
+			break;
+		}
+	}
+	read_unlock(&GlobalSMBSeslock);
+	if (open_file == NULL) {
+		cFYI(1, ("No writeable filehandles for inode"));
+		rc = -EIO;
+	}
+
+	kunmap(page);
+	return rc;
+}
+
+#if 0
+static int cifs_writepages(struct address_space *mapping,
+	struct writeback_control *wbc)
+{
+	int rc = -EFAULT;
+	int xid;
+
+	xid = GetXid();
+
+	/* Find contiguous pages then iterate through repeating
+	   call 16K write then Setpageuptodate or if LARGE_WRITE_X
+	   support then send larger writes via kevec so as to eliminate
+	   a memcpy */
+	FreeXid(xid);
+	return rc;
+}
+#endif
+
+static int cifs_writepage(struct page* page, struct writeback_control *wbc)
+{
+	int rc = -EFAULT;
+	int xid;
+
+	xid = GetXid();
+/* BB add check for wbc flags */
+	page_cache_get(page);
+        if (!PageUptodate(page)) {
+		cFYI(1, ("ppw - page not up to date"));
+	}
+	
+	rc = cifs_partialpagewrite(page, 0, PAGE_CACHE_SIZE);
+	SetPageUptodate(page); /* BB add check for error and Clearuptodate? */
+	unlock_page(page);
+	page_cache_release(page);	
+	FreeXid(xid);
+	return rc;
+}
+
+static int cifs_commit_write(struct file *file, struct page *page,
+	unsigned offset, unsigned to)
+{
+	int xid;
+	int rc = 0;
+	struct inode *inode = page->mapping->host;
+	loff_t position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
+	char *page_data;
+
+	xid = GetXid();
+	cFYI(1, ("commit write for page %p up to position %lld for %d", 
+		 page, position, to));
+	if (position > inode->i_size) {
+		i_size_write(inode, position);
+		/* if (file->private_data == NULL) {
+			rc = -EBADF;
+		} else {
+			open_file = (struct cifsFileInfo *)file->private_data;
+			cifs_sb = CIFS_SB(inode->i_sb);
+			rc = -EAGAIN;
+			while (rc == -EAGAIN) {
+				if ((open_file->invalidHandle) && 
+				    (!open_file->closePend)) {
+					rc = cifs_reopen_file(
+						file->f_dentry->d_inode, file);
+					if (rc != 0)
+						break;
+				}
+				if (!open_file->closePend) {
+					rc = CIFSSMBSetFileSize(xid,
+						cifs_sb->tcon, position,
+						open_file->netfid,
+						open_file->pid, FALSE);
+				} else {
+					rc = -EBADF;
+					break;
+				}
+			}
+			cFYI(1, (" SetEOF (commit write) rc = %d", rc));
+		} */
+	}
+	if (!PageUptodate(page)) {
+		position =  ((loff_t)page->index << PAGE_CACHE_SHIFT) + offset;
+		/* can not rely on (or let) writepage write this data */
+		if (to < offset) {
+			cFYI(1, ("Illegal offsets, can not copy from %d to %d",
+				offset, to));
+			FreeXid(xid);
+			return rc;
+		}
+		/* this is probably better than directly calling
+		   partialpage_write since in this function the file handle is
+		   known which we might as well	leverage */
+		/* BB check if anything else missing out of ppw
+		   such as updating last write time */
+		page_data = kmap(page);
+		rc = cifs_write(file, page_data + offset, to-offset,
+				&position);
+		if (rc > 0)
+			rc = 0;
+		/* else if (rc < 0) should we set writebehind rc? */
+		kunmap(page);
+	} else {	
+		set_page_dirty(page);
+	}
+
+	FreeXid(xid);
+	return rc;
+}
+
+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();
+
+	cFYI(1, ("Sync file - name: %s datasync: 0x%x ", 
+		dentry->d_name.name, datasync));
+	
+	rc = filemap_fdatawrite(inode->i_mapping);
+	if (rc == 0)
+		CIFS_I(inode)->write_behind_rc = 0;
+	FreeXid(xid);
+	return rc;
+}
+
+/* static int cifs_sync_page(struct page *page)
+{
+	struct address_space *mapping;
+	struct inode *inode;
+	unsigned long index = page->index;
+	unsigned int rpages = 0;
+	int rc = 0;
+
+	cFYI(1, ("sync page %p",page));
+	mapping = page->mapping;
+	if (!mapping)
+		return 0;
+	inode = mapping->host;
+	if (!inode)
+		return 0; */
+
+/*	fill in rpages then 
+	result = cifs_pagein_inode(inode, index, rpages); */ /* BB finish */
+
+/*	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);
+	if (!rc) /* reset wb rc if we were able to write out dirty pages */
+		CIFS_I(inode)->write_behind_rc = 0;
+		
+	cFYI(1, ("Flush inode %p file %p rc %d",inode,file,rc));
+
+	return rc;
+}
+
+ssize_t cifs_user_read(struct file *file, char __user *read_data,
+	size_t read_size, loff_t *poffset)
+{
+	int rc = -EACCES;
+	unsigned int bytes_read = 0;
+	unsigned int total_read = 0;
+	unsigned int current_read_size;
+	struct cifs_sb_info *cifs_sb;
+	struct cifsTconInfo *pTcon;
+	int xid;
+	struct cifsFileInfo *open_file;
+	char *smb_read_data;
+	char __user *current_offset;
+	struct smb_com_read_rsp *pSMBr;
+
+	xid = GetXid();
+	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+	pTcon = cifs_sb->tcon;
+
+	if (file->private_data == NULL) {
+		FreeXid(xid);
+		return -EBADF;
+	}
+	open_file = (struct cifsFileInfo *)file->private_data;
+
+	if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
+		cFYI(1, ("attempting read on write only file instance"));
+	}
+	for (total_read = 0, current_offset = read_data;
+	     read_size > total_read;
+	     total_read += bytes_read, current_offset += bytes_read) {
+		current_read_size = min_t(const int, read_size - total_read, 
+					  cifs_sb->rsize);
+		rc = -EAGAIN;
+		smb_read_data = NULL;
+		while (rc == -EAGAIN) {
+			if ((open_file->invalidHandle) && 
+			    (!open_file->closePend)) {
+				rc = cifs_reopen_file(file->f_dentry->d_inode,
+					file, TRUE);
+				if (rc != 0)
+					break;
+			}
+
+			rc = CIFSSMBRead(xid, pTcon,
+				 open_file->netfid,
+				 current_read_size, *poffset,
+				 &bytes_read, &smb_read_data);
+
+			pSMBr = (struct smb_com_read_rsp *)smb_read_data;
+			if (copy_to_user(current_offset, 
+					 smb_read_data + 4 /* RFC1001 hdr */
+					 + le16_to_cpu(pSMBr->DataOffset), 
+					 bytes_read)) {
+				rc = -EFAULT;
+				FreeXid(xid);
+				return rc;
+            }
+			if (smb_read_data) {
+				cifs_buf_release(smb_read_data);
+				smb_read_data = NULL;
+			}
+		}
+		if (rc || (bytes_read == 0)) {
+			if (total_read) {
+				break;
+			} else {
+				FreeXid(xid);
+				return rc;
+			}
+		} else {
+#ifdef CONFIG_CIFS_STATS
+			atomic_inc(&pTcon->num_reads);
+			spin_lock(&pTcon->stat_lock);
+			pTcon->bytes_read += total_read;
+			spin_unlock(&pTcon->stat_lock);
+#endif
+			*poffset += bytes_read;
+		}
+	}
+	FreeXid(xid);
+	return total_read;
+}
+
+
+static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
+	loff_t *poffset)
+{
+	int rc = -EACCES;
+	unsigned int bytes_read = 0;
+	unsigned int total_read;
+	unsigned int current_read_size;
+	struct cifs_sb_info *cifs_sb;
+	struct cifsTconInfo *pTcon;
+	int xid;
+	char *current_offset;
+	struct cifsFileInfo *open_file;
+
+	xid = GetXid();
+	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+	pTcon = cifs_sb->tcon;
+
+	if (file->private_data == NULL) {
+		FreeXid(xid);
+		return -EBADF;
+	}
+	open_file = (struct cifsFileInfo *)file->private_data;
+
+	if ((file->f_flags & O_ACCMODE) == O_WRONLY)
+		cFYI(1, ("attempting read on write only file instance"));
+
+	for (total_read = 0, current_offset = read_data; 
+	     read_size > total_read;
+	     total_read += bytes_read, current_offset += bytes_read) {
+		current_read_size = min_t(const int, read_size - total_read,
+					  cifs_sb->rsize);
+		rc = -EAGAIN;
+		while (rc == -EAGAIN) {
+			if ((open_file->invalidHandle) && 
+			    (!open_file->closePend)) {
+				rc = cifs_reopen_file(file->f_dentry->d_inode,
+					file, TRUE);
+				if (rc != 0)
+					break;
+			}
+
+			rc = CIFSSMBRead(xid, pTcon,
+				 open_file->netfid,
+				 current_read_size, *poffset,
+				 &bytes_read, &current_offset);
+		}
+		if (rc || (bytes_read == 0)) {
+			if (total_read) {
+				break;
+			} else {
+				FreeXid(xid);
+				return rc;
+			}
+		} else {
+#ifdef CONFIG_CIFS_STATS
+			atomic_inc(&pTcon->num_reads);
+			spin_lock(&pTcon->stat_lock);
+			pTcon->bytes_read += total_read;
+			spin_unlock(&pTcon->stat_lock);
+#endif
+			*poffset += bytes_read;
+		}
+	}
+	FreeXid(xid);
+	return total_read;
+}
+
+int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct dentry *dentry = file->f_dentry;
+	int rc, xid;
+
+	xid = GetXid();
+	rc = cifs_revalidate(dentry);
+	if (rc) {
+		cFYI(1, ("Validation prior to mmap failed, error=%d", rc));
+		FreeXid(xid);
+		return rc;
+	}
+	rc = generic_file_mmap(file, vma);
+	FreeXid(xid);
+	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, lru);
+		list_del(&page->lru);
+
+		if (add_to_page_cache(page, mapping, page->index,
+				      GFP_KERNEL)) {
+			page_cache_release(page);
+			cFYI(1, ("Add page cache failed"));
+			continue;
+		}
+
+		target = kmap_atomic(page,KM_USER0);
+
+		if (PAGE_CACHE_SIZE > bytes_read) {
+			memcpy(target, data, bytes_read);
+			/* zero the tail end of this partial page */
+			memset(target + bytes_read, 0, 
+			       PAGE_CACHE_SIZE - bytes_read);
+			bytes_read = 0;
+		} else {
+			memcpy(target, data, PAGE_CACHE_SIZE);
+			bytes_read -= PAGE_CACHE_SIZE;
+		}
+		kunmap_atomic(target, KM_USER0);
+
+		flush_dcache_page(page);
+		SetPageUptodate(page);
+		unlock_page(page);
+		if (!pagevec_add(plru_pvec, page))
+			__pagevec_lru_add(plru_pvec);
+		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;
+	loff_t offset;
+	struct page *page;
+	struct cifs_sb_info *cifs_sb;
+	struct cifsTconInfo *pTcon;
+	int bytes_read = 0;
+	unsigned int read_size,i;
+	char *smb_read_data = NULL;
+	struct smb_com_read_rsp *pSMBr;
+	struct pagevec lru_pvec;
+	struct cifsFileInfo *open_file;
+
+	xid = GetXid();
+	if (file->private_data == NULL) {
+		FreeXid(xid);
+		return -EBADF;
+	}
+	open_file = (struct cifsFileInfo *)file->private_data;
+	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+	pTcon = cifs_sb->tcon;
+
+	pagevec_init(&lru_pvec, 0);
+
+	for (i = 0; i < num_pages; ) {
+		unsigned contig_pages;
+		struct page *tmp_page;
+		unsigned long expected_index;
+
+		if (list_empty(page_list))
+			break;
+
+		page = list_entry(page_list->prev, struct page, lru);
+		offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
+
+		/* count adjacent pages that we will read into */
+		contig_pages = 0;
+		expected_index = 
+			list_entry(page_list->prev, struct page, lru)->index;
+		list_for_each_entry_reverse(tmp_page,page_list,lru) {
+			if (tmp_page->index == expected_index) {
+				contig_pages++;
+				expected_index++;
+			} else
+				break; 
+		}
+		if (contig_pages + i >  num_pages)
+			contig_pages = num_pages - i;
+
+		/* for reads over a certain size could initiate async
+		   read ahead */
+
+		read_size = contig_pages * PAGE_CACHE_SIZE;
+		/* Read size needs to be in multiples of one page */
+		read_size = min_t(const unsigned int, read_size,
+				  cifs_sb->rsize & PAGE_CACHE_MASK);
+
+		rc = -EAGAIN;
+		while (rc == -EAGAIN) {
+			if ((open_file->invalidHandle) && 
+			    (!open_file->closePend)) {
+				rc = cifs_reopen_file(file->f_dentry->d_inode,
+					file, TRUE);
+				if (rc != 0)
+					break;
+			}
+
+			rc = CIFSSMBRead(xid, pTcon,
+				open_file->netfid,
+				read_size, offset,
+				&bytes_read, &smb_read_data);
+			/* BB need to check return code here */
+			if (rc== -EAGAIN) {
+				if (smb_read_data) {
+					cifs_buf_release(smb_read_data);
+					smb_read_data = NULL;
+				}
+			}
+		}
+		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,
+						  lru);
+				list_del(&page->lru);
+				page_cache_release(page);
+			}
+			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 /* RFC1001 hdr */ +
+				le16_to_cpu(pSMBr->DataOffset), &lru_pvec);
+
+			i +=  bytes_read >> PAGE_CACHE_SHIFT;
+#ifdef CONFIG_CIFS_STATS
+			atomic_inc(&pTcon->num_reads);
+			spin_lock(&pTcon->stat_lock);
+			pTcon->bytes_read += bytes_read;
+			spin_unlock(&pTcon->stat_lock);
+#endif
+			if ((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
+				i++; /* account for partial page */
+
+				/* server copy of file can have smaller size 
+				   than client */
+				/* BB do we need to verify this common case ? 
+				   this case is ok - if we are at server EOF 
+				   we will hit it on next read */
+
+			/* while (!list_empty(page_list) && (i < num_pages)) {
+					page = list_entry(page_list->prev, 
+							  struct page, list);
+					list_del(&page->list);
+					page_cache_release(page);
+				}
+				break; */
+			}
+		} else {
+			cFYI(1, ("No bytes read (%d) at offset %lld . "
+				 "Cleaning remaining pages from readahead list",
+				 bytes_read, offset));
+			/* BB turn off caching and do new lookup on 
+			   file size at server? */
+			while (!list_empty(page_list) && (i < num_pages)) {
+				page = list_entry(page_list->prev, struct page,
+						  lru);
+				list_del(&page->lru);
+
+				/* BB removeme - replace with zero of page? */
+				page_cache_release(page);
+			}
+			break;
+		}
+		if (smb_read_data) {
+			cifs_buf_release(smb_read_data);
+			smb_read_data = NULL;
+		}
+		bytes_read = 0;
+	}
+
+	pagevec_lru_add(&lru_pvec);
+
+/* need to free smb_read_data buf before exit */
+	if (smb_read_data) {
+		cifs_buf_release(smb_read_data);
+		smb_read_data = NULL;
+	} 
+
+	FreeXid(xid);
+	return rc;
+}
+
+static int cifs_readpage_worker(struct file *file, struct page *page,
+	loff_t *poffset)
+{
+	char *read_data;
+	int rc;
+
+	page_cache_get(page);
+	read_data = kmap(page);
+	/* for reads over a certain size could initiate async read ahead */
+                                                                                                                           
+	rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset);
+                                                                                                                           
+	if (rc < 0)
+		goto io_error;
+	else
+		cFYI(1, ("Bytes read %d ",rc));
+                                                                                                                           
+	file->f_dentry->d_inode->i_atime =
+		current_fs_time(file->f_dentry->d_inode->i_sb);
+                                                                                                                           
+	if (PAGE_CACHE_SIZE > rc)
+		memset(read_data + rc, 0, PAGE_CACHE_SIZE - rc);
+
+	flush_dcache_page(page);
+	SetPageUptodate(page);
+	rc = 0;
+                                                                                                                           
+io_error:
+        kunmap(page);
+	page_cache_release(page);
+	return rc;
+}
+
+static int cifs_readpage(struct file *file, struct page *page)
+{
+	loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
+	int rc = -EACCES;
+	int xid;
+
+	xid = GetXid();
+
+	if (file->private_data == NULL) {
+		FreeXid(xid);
+		return -EBADF;
+	}
+
+	cFYI(1, ("readpage %p at offset %d 0x%x\n", 
+		 page, (int)offset, (int)offset));
+
+	rc = cifs_readpage_worker(file, page, &offset);
+
+	unlock_page(page);
+
+	FreeXid(xid);
+	return rc;
+}
+
+/* We do not want to update the file size from server for inodes
+   open for write - to avoid races with writepage extending
+   the file - in the future we could consider allowing
+   refreshing the inode only on increases in the file size 
+   but this is tricky to do without racing with writebehind
+   page caching in the current Linux kernel design */
+int is_size_safe_to_change(struct cifsInodeInfo *cifsInode)
+{
+	struct list_head *tmp;
+	struct list_head *tmp1;
+	struct cifsFileInfo *open_file = NULL;
+	int rc = TRUE;
+
+	if (cifsInode == NULL)
+		return rc;
+
+	read_lock(&GlobalSMBSeslock); 
+	list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {            
+		open_file = list_entry(tmp, struct cifsFileInfo, flist);
+		if (open_file == NULL)
+			break;
+		if (open_file->closePend)
+			continue;
+	/* We check if file is open for writing,   
+	   BB we could supplement this with a check to see if file size
+	   changes have been flushed to server - ie inode metadata dirty */
+		if ((open_file->pfile) && 
+		    ((open_file->pfile->f_flags & O_RDWR) || 
+		    (open_file->pfile->f_flags & O_WRONLY))) {
+			rc = FALSE;
+			break;
+		}
+		if (tmp->next == NULL) {
+			cFYI(1, ("File instance %p removed", tmp));
+			break;
+		}
+	}
+	read_unlock(&GlobalSMBSeslock);
+	return rc;
+}
+
+
+static int cifs_prepare_write(struct file *file, struct page *page,
+	unsigned from, unsigned to)
+{
+	int rc = 0;
+        loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
+	cFYI(1, ("prepare write for page %p from %d to %d",page,from,to));
+	if (!PageUptodate(page)) {
+	/*	if (to - from != PAGE_CACHE_SIZE) {
+			void *kaddr = kmap_atomic(page, KM_USER0);
+			memset(kaddr, 0, from);
+			memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
+			flush_dcache_page(page);
+			kunmap_atomic(kaddr, KM_USER0);
+		} */
+		/* If we are writing a full page it will be up to date,
+		   no need to read from the server */
+		if ((to == PAGE_CACHE_SIZE) && (from == 0))
+			SetPageUptodate(page);
+
+		/* might as well read a page, it is fast enough */
+		if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
+			rc = cifs_readpage_worker(file, page, &offset);
+		} else {
+		/* should we try using another file handle if there is one -
+		   how would we lock it to prevent close of that handle
+		   racing with this read?
+		   In any case this will be written out by commit_write */
+		}
+	}
+
+	/* BB should we pass any errors back? 
+	   e.g. if we do not have read access to the file */
+	return 0;
+}
+
+struct address_space_operations cifs_addr_ops = {
+	.readpage = cifs_readpage,
+	.readpages = cifs_readpages,
+	.writepage = cifs_writepage,
+	.prepare_write = cifs_prepare_write,
+	.commit_write = cifs_commit_write,
+	.set_page_dirty = __set_page_dirty_nobuffers,
+	/* .sync_page = cifs_sync_page, */
+	/* .direct_IO = */
+};
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
new file mode 100644
index 0000000..d73b0aa
--- /dev/null
+++ b/fs/cifs/inode.c
@@ -0,0 +1,1096 @@
+/*
+ *   fs/cifs/inode.c
+ *
+ *   Copyright (C) International Business Machines  Corp., 2002,2005
+ *   Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/fs.h>
+#include <linux/buffer_head.h>
+#include <linux/stat.h>
+#include <linux/pagemap.h>
+#include <asm/div64.h>
+#include "cifsfs.h"
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+#include "cifs_fs_sb.h"
+
+int cifs_get_inode_info_unix(struct inode **pinode,
+	const unsigned char *search_path, struct super_block *sb, int xid)
+{
+	int rc = 0;
+	FILE_UNIX_BASIC_INFO findData;
+	struct cifsTconInfo *pTcon;
+	struct inode *inode;
+	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+	char *tmp_path;
+
+	pTcon = cifs_sb->tcon;
+	cFYI(1, (" Getting info on %s ", search_path));
+	/* could have done a find first instead but this returns more info */
+	rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData,
+				  cifs_sb->local_nls);
+/*	dump_mem("\nUnixQPathInfo return data", &findData,
+		 sizeof(findData)); */
+	if (rc) {
+		if (rc == -EREMOTE) {
+			tmp_path =
+			    kmalloc(strnlen(pTcon->treeName,
+					    MAX_TREE_SIZE + 1) +
+				    strnlen(search_path, MAX_PATHCONF) + 1,
+				    GFP_KERNEL);
+			if (tmp_path == NULL) {
+				return -ENOMEM;
+			}
+        		/* have to skip first of the double backslash of
+			   UNC name */
+			strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
+			strncat(tmp_path, search_path, MAX_PATHCONF);
+			rc = connect_to_dfs_path(xid, pTcon->ses,
+						 /* treename + */ tmp_path,
+						 cifs_sb->local_nls);
+			kfree(tmp_path);
+
+			/* BB fix up inode etc. */
+		} else if (rc) {
+			return rc;
+		}
+	} else {
+		struct cifsInodeInfo *cifsInfo;
+		__u32 type = le32_to_cpu(findData.Type);
+		__u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes);
+		__u64 end_of_file = le64_to_cpu(findData.EndOfFile);
+
+		/* get new inode */
+		if (*pinode == NULL) {
+			*pinode = new_inode(sb);
+			if(*pinode == NULL) 
+				return -ENOMEM;
+			/* Is an i_ino of zero legal? */
+			/* Are there sanity checks we can use to ensure that
+			   the server is really filling in that field? */
+			if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
+				(*pinode)->i_ino =
+					(unsigned long)findData.UniqueId;
+			} /* note ino incremented to unique num in new_inode */
+			insert_inode_hash(*pinode);
+		}
+
+		inode = *pinode;
+		cifsInfo = CIFS_I(inode);
+
+		cFYI(1, (" Old time %ld ", cifsInfo->time));
+		cifsInfo->time = jiffies;
+		cFYI(1, (" New time %ld ", cifsInfo->time));
+		/* this is ok to set on every inode revalidate */
+		atomic_set(&cifsInfo->inUse,1);
+
+		inode->i_atime =
+		    cifs_NTtimeToUnix(le64_to_cpu(findData.LastAccessTime));
+		inode->i_mtime =
+		    cifs_NTtimeToUnix(le64_to_cpu
+				(findData.LastModificationTime));
+		inode->i_ctime =
+		    cifs_NTtimeToUnix(le64_to_cpu(findData.LastStatusChange));
+		inode->i_mode = le64_to_cpu(findData.Permissions);
+		if (type == UNIX_FILE) {
+			inode->i_mode |= S_IFREG;
+		} else if (type == UNIX_SYMLINK) {
+			inode->i_mode |= S_IFLNK;
+		} else if (type == UNIX_DIR) {
+			inode->i_mode |= S_IFDIR;
+		} else if (type == UNIX_CHARDEV) {
+			inode->i_mode |= S_IFCHR;
+			inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
+				le64_to_cpu(findData.DevMinor) & MINORMASK);
+		} else if (type == UNIX_BLOCKDEV) {
+			inode->i_mode |= S_IFBLK;
+			inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
+				le64_to_cpu(findData.DevMinor) & MINORMASK);
+		} else if (type == UNIX_FIFO) {
+			inode->i_mode |= S_IFIFO;
+		} else if (type == UNIX_SOCKET) {
+			inode->i_mode |= S_IFSOCK;
+		}
+		inode->i_uid = le64_to_cpu(findData.Uid);
+		inode->i_gid = le64_to_cpu(findData.Gid);
+		inode->i_nlink = le64_to_cpu(findData.Nlinks);
+
+		if(is_size_safe_to_change(cifsInfo)) {
+		/* can not safely change the file size here if the
+		   client is writing to it due to potential races */
+
+			i_size_write(inode, end_of_file);
+
+		/* blksize needs to be multiple of two. So safer to default to
+		blksize and blkbits set in superblock so 2**blkbits and blksize
+		will match rather than setting to:
+		(pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
+
+		/* This seems incredibly stupid but it turns out that i_blocks
+		   is not related to (i_size / i_blksize), instead 512 byte size
+		   is required for calculating num blocks */
+
+		/* 512 bytes (2**9) is the fake blocksize that must be used */
+		/* for this calculation */
+			inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
+		}
+
+		if (num_of_bytes < end_of_file)
+			cFYI(1, ("allocation size less than end of file "));
+		cFYI(1,
+		     ("Size %ld and blocks %ld",
+		      (unsigned long) inode->i_size, inode->i_blocks));
+		if (S_ISREG(inode->i_mode)) {
+			cFYI(1, (" File inode "));
+			inode->i_op = &cifs_file_inode_ops;
+			if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
+				inode->i_fop = &cifs_file_direct_ops;
+			else
+				inode->i_fop = &cifs_file_ops;
+			inode->i_data.a_ops = &cifs_addr_ops;
+		} else if (S_ISDIR(inode->i_mode)) {
+			cFYI(1, (" Directory inode"));
+			inode->i_op = &cifs_dir_inode_ops;
+			inode->i_fop = &cifs_dir_ops;
+		} else if (S_ISLNK(inode->i_mode)) {
+			cFYI(1, (" Symbolic Link inode "));
+			inode->i_op = &cifs_symlink_inode_ops;
+		/* tmp_inode->i_fop = */ /* do not need to set to anything */
+		} else {
+			cFYI(1, (" Init special inode "));
+			init_special_inode(inode, inode->i_mode,
+					   inode->i_rdev);
+		}
+	}
+	return rc;
+}
+
+int cifs_get_inode_info(struct inode **pinode,
+	const unsigned char *search_path, FILE_ALL_INFO *pfindData,
+	struct super_block *sb, int xid)
+{
+	int rc = 0;
+	struct cifsTconInfo *pTcon;
+	struct inode *inode;
+	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+	char *tmp_path;
+	char *buf = NULL;
+
+	pTcon = cifs_sb->tcon;
+	cFYI(1,("Getting info on %s ", search_path));
+
+	if((pfindData == NULL) && (*pinode != NULL)) {
+		if(CIFS_I(*pinode)->clientCanCacheRead) {
+			cFYI(1,("No need to revalidate cached inode sizes"));
+			return rc;
+		}
+	}
+
+	/* if file info not passed in then get it from server */
+	if(pfindData == NULL) {
+		buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
+		if(buf == NULL)
+			return -ENOMEM;
+		pfindData = (FILE_ALL_INFO *)buf;
+		/* could do find first instead but this returns more info */
+		rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData,
+			      cifs_sb->local_nls);
+	}
+	/* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
+	if (rc) {
+		if (rc == -EREMOTE) {
+			tmp_path =
+			    kmalloc(strnlen
+				    (pTcon->treeName,
+				     MAX_TREE_SIZE + 1) +
+				    strnlen(search_path, MAX_PATHCONF) + 1,
+				    GFP_KERNEL);
+			if (tmp_path == NULL) {
+				kfree(buf);
+				return -ENOMEM;
+			}
+
+			strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
+			strncat(tmp_path, search_path, MAX_PATHCONF);
+			rc = connect_to_dfs_path(xid, pTcon->ses,
+						 /* treename + */ tmp_path,
+						 cifs_sb->local_nls);
+			kfree(tmp_path);
+			/* BB fix up inode etc. */
+		} else if (rc) {
+			kfree(buf);
+			return rc;
+		}
+	} else {
+		struct cifsInodeInfo *cifsInfo;
+		__u32 attr = le32_to_cpu(pfindData->Attributes);
+
+		/* get new inode */
+		if (*pinode == NULL) {
+			*pinode = new_inode(sb);
+			if (*pinode == NULL)
+				return -ENOMEM;
+			/* Is an i_ino of zero legal? Can we use that to check
+			   if the server supports returning inode numbers?  Are
+			   there other sanity checks we can use to ensure that
+			   the server is really filling in that field? */
+
+			/* We can not use the IndexNumber field by default from
+			   Windows or Samba (in ALL_INFO buf) but we can request
+			   it explicitly.  It may not be unique presumably if
+			   the server has multiple devices mounted under one
+			   share */
+
+			/* There may be higher info levels that work but are
+			   there Windows server or network appliances for which
+			   IndexNumber field is not guaranteed unique? */
+
+#ifdef CONFIG_CIFS_EXPERIMENTAL		
+			if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM){
+				int rc1 = 0;
+				__u64 inode_num;
+
+				rc1 = CIFSGetSrvInodeNumber(xid, pTcon, 
+					search_path, &inode_num, 
+					cifs_sb->local_nls);
+				if(rc1) {
+					cFYI(1,("GetSrvInodeNum rc %d", rc1));
+					/* BB EOPNOSUPP disable SERVER_INUM? */
+				} else /* do we need cast or hash to ino? */
+					(*pinode)->i_ino = inode_num;
+			} /* else ino incremented to unique num in new_inode*/
+#endif /* CIFS_EXPERIMENTAL */
+			insert_inode_hash(*pinode);
+		}
+		inode = *pinode;
+		cifsInfo = CIFS_I(inode);
+		cifsInfo->cifsAttrs = attr;
+		cFYI(1, (" Old time %ld ", cifsInfo->time));
+		cifsInfo->time = jiffies;
+		cFYI(1, (" New time %ld ", cifsInfo->time));
+
+		/* blksize needs to be multiple of two. So safer to default to
+		blksize and blkbits set in superblock so 2**blkbits and blksize
+		will match rather than setting to:
+		(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(pfindData->LastAccessTime));
+		inode->i_mtime =
+		    cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
+		inode->i_ctime =
+		    cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
+		cFYI(0, (" Attributes came in as 0x%x ", attr));
+
+		/* set default mode. will override for dirs below */
+		if (atomic_read(&cifsInfo->inUse) == 0)
+			/* new inode, can safely set these fields */
+			inode->i_mode = cifs_sb->mnt_file_mode;
+
+/*		if (attr & ATTR_REPARSE)  */
+		/* We no longer handle these as symlinks because we could not
+		   follow them due to the absolute path with drive letter */
+		if (attr & ATTR_DIRECTORY) {
+		/* override default perms since we do not do byte range locking
+		   on dirs */
+			inode->i_mode = cifs_sb->mnt_dir_mode;
+			inode->i_mode |= S_IFDIR;
+		} else {
+			inode->i_mode |= S_IFREG;
+			/* treat the dos attribute of read-only as read-only
+			   mode e.g. 555 */
+			if (cifsInfo->cifsAttrs & ATTR_READONLY)
+				inode->i_mode &= ~(S_IWUGO);
+		/* BB add code here -
+		   validate if device or weird share or device type? */
+		}
+		if (is_size_safe_to_change(cifsInfo)) {
+			/* can not safely change the file size here if the
+			   client is writing to it due to potential races */
+			i_size_write(inode,le64_to_cpu(pfindData->EndOfFile));
+
+			/* 512 bytes (2**9) is the fake blocksize that must be
+			   used for this calculation */
+			inode->i_blocks = (512 - 1 + le64_to_cpu(
+					   pfindData->AllocationSize)) >> 9;
+		}
+
+		inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks);
+
+		/* BB fill in uid and gid here? with help from winbind? 
+		   or retrieve from NTFS stream extended attribute */
+		if (atomic_read(&cifsInfo->inUse) == 0) {
+			inode->i_uid = cifs_sb->mnt_uid;
+			inode->i_gid = cifs_sb->mnt_gid;
+			/* set so we do not keep refreshing these fields with
+			   bad data after user has changed them in memory */
+			atomic_set(&cifsInfo->inUse,1);
+		}
+
+		if (S_ISREG(inode->i_mode)) {
+			cFYI(1, (" File inode "));
+			inode->i_op = &cifs_file_inode_ops;
+			if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
+				inode->i_fop = &cifs_file_direct_ops;
+			else
+				inode->i_fop = &cifs_file_ops;
+			inode->i_data.a_ops = &cifs_addr_ops;
+		} else if (S_ISDIR(inode->i_mode)) {
+			cFYI(1, (" Directory inode "));
+			inode->i_op = &cifs_dir_inode_ops;
+			inode->i_fop = &cifs_dir_ops;
+		} else if (S_ISLNK(inode->i_mode)) {
+			cFYI(1, (" Symbolic Link inode "));
+			inode->i_op = &cifs_symlink_inode_ops;
+		} else {
+			init_special_inode(inode, inode->i_mode,
+					   inode->i_rdev);
+		}
+	}
+	kfree(buf);
+	return rc;
+}
+
+/* gets root inode */
+void cifs_read_inode(struct inode *inode)
+{
+	int xid;
+	struct cifs_sb_info *cifs_sb;
+
+	cifs_sb = CIFS_SB(inode->i_sb);
+	xid = GetXid();
+	if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
+		cifs_get_inode_info_unix(&inode, "", inode->i_sb,xid);
+	else
+		cifs_get_inode_info(&inode, "", NULL, inode->i_sb,xid);
+	/* can not call macro FreeXid here since in a void func */
+	_FreeXid(xid);
+}
+
+int cifs_unlink(struct inode *inode, struct dentry *direntry)
+{
+	int rc = 0;
+	int xid;
+	struct cifs_sb_info *cifs_sb;
+	struct cifsTconInfo *pTcon;
+	char *full_path = NULL;
+	struct cifsInodeInfo *cifsInode;
+	FILE_BASIC_INFO *pinfo_buf;
+
+	cFYI(1, (" cifs_unlink, inode = 0x%p with ", inode));
+
+	xid = GetXid();
+
+	cifs_sb = CIFS_SB(inode->i_sb);
+	pTcon = cifs_sb->tcon;
+
+	/* Unlink can be called from rename so we can not grab the sem here
+	   since we deadlock otherwise */
+/*	down(&direntry->d_sb->s_vfs_rename_sem);*/
+	full_path = build_path_from_dentry(direntry);
+/*	up(&direntry->d_sb->s_vfs_rename_sem);*/
+	if (full_path == NULL) {
+		FreeXid(xid);
+		return -ENOMEM;
+	}
+	rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls);
+
+	if (!rc) {
+		direntry->d_inode->i_nlink--;
+	} else if (rc == -ENOENT) {
+		d_drop(direntry);
+	} else if (rc == -ETXTBSY) {
+		int oplock = FALSE;
+		__u16 netfid;
+
+		rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
+				 CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
+				 &netfid, &oplock, NULL, cifs_sb->local_nls);
+		if (rc==0) {
+			CIFSSMBRenameOpenFile(xid, pTcon, netfid, NULL,
+					      cifs_sb->local_nls);
+			CIFSSMBClose(xid, pTcon, netfid);
+			direntry->d_inode->i_nlink--;
+		}
+	} else if (rc == -EACCES) {
+		/* try only if r/o attribute set in local lookup data? */
+		pinfo_buf = kmalloc(sizeof(FILE_BASIC_INFO), GFP_KERNEL);
+		if (pinfo_buf) {
+			memset(pinfo_buf, 0, sizeof(FILE_BASIC_INFO));
+			/* ATTRS set to normal clears r/o bit */
+			pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL);
+			if (!(pTcon->ses->flags & CIFS_SES_NT4))
+				rc = CIFSSMBSetTimes(xid, pTcon, full_path,
+						     pinfo_buf,
+						     cifs_sb->local_nls);
+			else
+				rc = -EOPNOTSUPP;
+
+			if (rc == -EOPNOTSUPP) {
+				int oplock = FALSE;
+				__u16 netfid;
+			/*	rc = CIFSSMBSetAttrLegacy(xid, pTcon,
+							  full_path,
+							  (__u16)ATTR_NORMAL,
+							  cifs_sb->local_nls); 
+			   For some strange reason it seems that NT4 eats the
+			   old setattr call without actually setting the
+			   attributes so on to the third attempted workaround
+			   */
+
+			/* BB could scan to see if we already have it open
+			   and pass in pid of opener to function */
+				rc = CIFSSMBOpen(xid, pTcon, full_path,
+						 FILE_OPEN, SYNCHRONIZE |
+						 FILE_WRITE_ATTRIBUTES, 0,
+						 &netfid, &oplock, NULL,
+						 cifs_sb->local_nls);
+				if (rc==0) {
+					rc = CIFSSMBSetFileTimes(xid, pTcon,
+								 pinfo_buf,
+								 netfid);
+					CIFSSMBClose(xid, pTcon, netfid);
+				}
+			}
+			kfree(pinfo_buf);
+		}
+		if (rc==0) {
+			rc = CIFSSMBDelFile(xid, pTcon, full_path,
+					    cifs_sb->local_nls);
+			if (!rc) {
+				direntry->d_inode->i_nlink--;
+			} else if (rc == -ETXTBSY) {
+				int oplock = FALSE;
+				__u16 netfid;
+
+				rc = CIFSSMBOpen(xid, pTcon, full_path,
+						 FILE_OPEN, DELETE,
+						 CREATE_NOT_DIR |
+						 CREATE_DELETE_ON_CLOSE,
+						 &netfid, &oplock, NULL,
+						 cifs_sb->local_nls);
+				if (rc==0) {
+					CIFSSMBRenameOpenFile(xid, pTcon,
+						netfid, NULL,
+						cifs_sb->local_nls);
+					CIFSSMBClose(xid, pTcon, netfid);
+		                        direntry->d_inode->i_nlink--;
+				}
+			/* BB if rc = -ETXTBUSY goto the rename logic BB */
+			}
+		}
+	}
+	cifsInode = CIFS_I(direntry->d_inode);
+	cifsInode->time = 0;	/* will force revalidate to get info when
+				   needed */
+	direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
+		current_fs_time(inode->i_sb);
+	cifsInode = CIFS_I(inode);
+	cifsInode->time = 0;	/* force revalidate of dir as well */
+
+	kfree(full_path);
+	FreeXid(xid);
+	return rc;
+}
+
+int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
+{
+	int rc = 0;
+	int xid;
+	struct cifs_sb_info *cifs_sb;
+	struct cifsTconInfo *pTcon;
+	char *full_path = NULL;
+	struct inode *newinode = NULL;
+
+	cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p ", mode, inode));
+
+	xid = GetXid();
+
+	cifs_sb = CIFS_SB(inode->i_sb);
+	pTcon = cifs_sb->tcon;
+
+	down(&inode->i_sb->s_vfs_rename_sem);
+	full_path = build_path_from_dentry(direntry);
+	up(&inode->i_sb->s_vfs_rename_sem);
+	if (full_path == NULL) {
+		FreeXid(xid);
+		return -ENOMEM;
+	}
+	/* 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, ("cifs_mkdir returned 0x%x ", rc));
+		d_drop(direntry);
+	} else {
+		inode->i_nlink++;
+		if (pTcon->ses->capabilities & CAP_UNIX)
+			rc = cifs_get_inode_info_unix(&newinode, full_path,
+						      inode->i_sb,xid);
+		else
+			rc = cifs_get_inode_info(&newinode, full_path, NULL,
+						 inode->i_sb,xid);
+
+		direntry->d_op = &cifs_dentry_ops;
+		d_instantiate(direntry, newinode);
+		if (direntry->d_inode)
+			direntry->d_inode->i_nlink = 2;
+		if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
+			if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
+				CIFSSMBUnixSetPerms(xid, pTcon, full_path,
+						    mode,
+						    (__u64)current->euid,
+						    (__u64)current->egid,
+						    0 /* dev_t */,
+						    cifs_sb->local_nls);
+			} else {
+				CIFSSMBUnixSetPerms(xid, pTcon, full_path,
+						    mode, (__u64)-1,
+						    (__u64)-1, 0 /* dev_t */,
+						    cifs_sb->local_nls);
+			}
+		else {
+			/* BB to be implemented via Windows secrty descriptors
+			   eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
+						 -1, -1, local_nls); */
+		}
+	}
+	kfree(full_path);
+	FreeXid(xid);
+	return rc;
+}
+
+int cifs_rmdir(struct inode *inode, struct dentry *direntry)
+{
+	int rc = 0;
+	int xid;
+	struct cifs_sb_info *cifs_sb;
+	struct cifsTconInfo *pTcon;
+	char *full_path = NULL;
+	struct cifsInodeInfo *cifsInode;
+
+	cFYI(1, (" cifs_rmdir, inode = 0x%p with ", inode));
+
+	xid = GetXid();
+
+	cifs_sb = CIFS_SB(inode->i_sb);
+	pTcon = cifs_sb->tcon;
+
+	down(&inode->i_sb->s_vfs_rename_sem);
+	full_path = build_path_from_dentry(direntry);
+	up(&inode->i_sb->s_vfs_rename_sem);
+	if (full_path == NULL) {
+		FreeXid(xid);
+		return -ENOMEM;
+	}
+
+	rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls);
+
+	if (!rc) {
+		inode->i_nlink--;
+		i_size_write(direntry->d_inode,0);
+		direntry->d_inode->i_nlink = 0;
+	}
+
+	cifsInode = CIFS_I(direntry->d_inode);
+	cifsInode->time = 0;	/* force revalidate to go get info when
+				   needed */
+	direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
+		current_fs_time(inode->i_sb);
+
+	kfree(full_path);
+	FreeXid(xid);
+	return rc;
+}
+
+int cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
+	struct inode *target_inode, struct dentry *target_direntry)
+{
+	char *fromName;
+	char *toName;
+	struct cifs_sb_info *cifs_sb_source;
+	struct cifs_sb_info *cifs_sb_target;
+	struct cifsTconInfo *pTcon;
+	int xid;
+	int rc = 0;
+
+	xid = GetXid();
+
+	cifs_sb_target = CIFS_SB(target_inode->i_sb);
+	cifs_sb_source = CIFS_SB(source_inode->i_sb);
+	pTcon = cifs_sb_source->tcon;
+
+	if (pTcon != cifs_sb_target->tcon) {
+		FreeXid(xid);
+		return -EXDEV;	/* BB actually could be allowed if same server,
+				   but different share.
+				   Might eventually add support for this */
+	}
+
+	/* we already  have the rename sem so we do not need to grab it again
+	   here to protect the path integrity */
+	fromName = build_path_from_dentry(source_direntry);
+	toName = build_path_from_dentry(target_direntry);
+	if ((fromName == NULL) || (toName == NULL)) {
+		rc = -ENOMEM;
+		goto cifs_rename_exit;
+	}
+
+	rc = CIFSSMBRename(xid, pTcon, fromName, toName,
+			   cifs_sb_source->local_nls);
+	if (rc == -EEXIST) {
+		/* check if they are the same file because rename of hardlinked
+		   files is a noop */
+		FILE_UNIX_BASIC_INFO *info_buf_source;
+		FILE_UNIX_BASIC_INFO *info_buf_target;
+
+		info_buf_source =
+			kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
+		if (info_buf_source != NULL) {
+			info_buf_target = info_buf_source + 1;
+			rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName,
+				info_buf_source, cifs_sb_source->local_nls);
+			if (rc == 0) {
+				rc = CIFSSMBUnixQPathInfo(xid, pTcon, toName,
+						info_buf_target,
+						cifs_sb_target->local_nls);
+			}
+			if ((rc == 0) &&
+			    (info_buf_source->UniqueId ==
+			     info_buf_target->UniqueId)) {
+			/* do not rename since the files are hardlinked which
+			   is a noop */
+			} else {
+			/* we either can not tell the files are hardlinked
+			   (as with Windows servers) or files are not
+			   hardlinked so delete the target manually before
+			   renaming to follow POSIX rather than Windows
+			   semantics */
+				cifs_unlink(target_inode, target_direntry);
+				rc = CIFSSMBRename(xid, pTcon, fromName,
+						   toName,
+						   cifs_sb_source->local_nls);
+			}
+			kfree(info_buf_source);
+		} /* if we can not get memory just leave rc as EEXIST */
+	}
+
+	if (rc) {
+		cFYI(1, ("rename rc %d", rc));
+	}
+
+	if ((rc == -EIO) || (rc == -EEXIST)) {
+		int oplock = FALSE;
+		__u16 netfid;
+
+		/* BB FIXME Is Generic Read correct for rename? */
+		/* if renaming directory - we should not say CREATE_NOT_DIR,
+		   need to test renaming open directory, also GENERIC_READ
+		   might not right be right access to request */
+		rc = CIFSSMBOpen(xid, pTcon, fromName, FILE_OPEN, GENERIC_READ,
+				 CREATE_NOT_DIR, &netfid, &oplock, NULL,
+				 cifs_sb_source->local_nls);
+		if (rc==0) {
+			CIFSSMBRenameOpenFile(xid, pTcon, netfid, toName,
+					      cifs_sb_source->local_nls);
+			CIFSSMBClose(xid, pTcon, netfid);
+		}
+	}
+
+cifs_rename_exit:
+	kfree(fromName);
+	kfree(toName);
+	FreeXid(xid);
+	return rc;
+}
+
+int cifs_revalidate(struct dentry *direntry)
+{
+	int xid;
+	int rc = 0;
+	char *full_path;
+	struct cifs_sb_info *cifs_sb;
+	struct cifsInodeInfo *cifsInode;
+	loff_t local_size;
+	struct timespec local_mtime;
+	int invalidate_inode = FALSE;
+
+	if (direntry->d_inode == NULL)
+		return -ENOENT;
+
+	cifsInode = CIFS_I(direntry->d_inode);
+
+	if (cifsInode == NULL)
+		return -ENOENT;
+
+	/* no sense revalidating inode info on file that no one can write */
+	if (CIFS_I(direntry->d_inode)->clientCanCacheRead)
+		return rc;
+
+	xid = GetXid();
+
+	cifs_sb = CIFS_SB(direntry->d_sb);
+
+	/* can not safely grab the rename sem here if rename calls revalidate
+	   since that would deadlock */
+	full_path = build_path_from_dentry(direntry);
+	if (full_path == NULL) {
+		FreeXid(xid);
+		return -ENOMEM;
+	}
+	cFYI(1, ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld "
+		 "jiffies %ld", full_path, direntry->d_inode,
+		 direntry->d_inode->i_count.counter, direntry,
+		 direntry->d_time, jiffies));
+
+	if (cifsInode->time == 0) {
+		/* was set to zero previously to force revalidate */
+	} else if (time_before(jiffies, cifsInode->time + HZ) &&
+		   lookupCacheEnabled) {
+		if ((S_ISREG(direntry->d_inode->i_mode) == 0) ||
+		    (direntry->d_inode->i_nlink == 1)) {
+			kfree(full_path);
+			FreeXid(xid);
+			return rc;
+		} else {
+			cFYI(1, ("Have to revalidate file due to hardlinks"));
+		}
+	}
+
+	/* save mtime and size */
+	local_mtime = direntry->d_inode->i_mtime;
+	local_size = direntry->d_inode->i_size;
+
+	if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
+		rc = cifs_get_inode_info_unix(&direntry->d_inode, full_path,
+					      direntry->d_sb,xid);
+		if (rc) {
+			cFYI(1, ("error on getting revalidate info %d", rc));
+/*			if (rc != -ENOENT)
+				rc = 0; */	/* BB should we cache info on
+						   certain errors? */
+		}
+	} else {
+		rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL,
+					 direntry->d_sb,xid);
+		if (rc) {
+			cFYI(1, ("error on getting revalidate info %d", rc));
+/*			if (rc != -ENOENT)
+				rc = 0; */	/* BB should we cache info on
+						   certain errors? */
+		}
+	}
+	/* should we remap certain errors, access denied?, to zero */
+
+	/* if not oplocked, we invalidate inode pages if mtime or file size
+	   had changed on server */
+
+	if (timespec_equal(&local_mtime,&direntry->d_inode->i_mtime) && 
+	    (local_size == direntry->d_inode->i_size)) {
+		cFYI(1, ("cifs_revalidate - inode unchanged"));
+	} else {
+		/* file may have changed on server */
+		if (cifsInode->clientCanCacheRead) {
+			/* no need to invalidate inode pages since we were the
+			   only ones who could have modified the file and the
+			   server copy is staler than ours */
+		} else {
+			invalidate_inode = TRUE;
+		}
+	}
+
+	/* can not grab this sem since kernel filesys locking documentation
+	   indicates i_sem may be taken by the kernel on lookup and rename
+	   which could deadlock if we grab the i_sem here as well */
+/*	down(&direntry->d_inode->i_sem);*/
+	/* need to write out dirty pages here  */
+	if (direntry->d_inode->i_mapping) {
+		/* do we need to lock inode until after invalidate completes
+		   below? */
+		filemap_fdatawrite(direntry->d_inode->i_mapping);
+	}
+	if (invalidate_inode) {
+		if (direntry->d_inode->i_mapping)
+			filemap_fdatawait(direntry->d_inode->i_mapping);
+		/* may eventually have to do this for open files too */
+		if (list_empty(&(cifsInode->openFileList))) {
+			/* Has changed on server - flush read ahead pages */
+			cFYI(1, ("Invalidating read ahead data on "
+				 "closed file"));
+			invalidate_remote_inode(direntry->d_inode);
+		}
+	}
+/*	up(&direntry->d_inode->i_sem); */
+	
+	kfree(full_path);
+	FreeXid(xid);
+	return rc;
+}
+
+int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
+	struct kstat *stat)
+{
+	int err = cifs_revalidate(dentry);
+	if (!err)
+		generic_fillattr(dentry->d_inode, stat);
+	return err;
+}
+
+static int cifs_truncate_page(struct address_space *mapping, loff_t from)
+{
+	pgoff_t index = from >> PAGE_CACHE_SHIFT;
+	unsigned offset = from & (PAGE_CACHE_SIZE - 1);
+	struct page *page;
+	char *kaddr;
+	int rc = 0;
+
+	page = grab_cache_page(mapping, index);
+	if (!page)
+		return -ENOMEM;
+
+	kaddr = kmap_atomic(page, KM_USER0);
+	memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset);
+	flush_dcache_page(page);
+	kunmap_atomic(kaddr, KM_USER0);
+	unlock_page(page);
+	page_cache_release(page);
+	return rc;
+}
+
+int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
+{
+	int xid;
+	struct cifs_sb_info *cifs_sb;
+	struct cifsTconInfo *pTcon;
+	char *full_path = NULL;
+	int rc = -EACCES;
+	int found = FALSE;
+	struct cifsFileInfo *open_file = NULL;
+	FILE_BASIC_INFO time_buf;
+	int set_time = FALSE;
+	__u64 mode = 0xFFFFFFFFFFFFFFFFULL;
+	__u64 uid = 0xFFFFFFFFFFFFFFFFULL;
+	__u64 gid = 0xFFFFFFFFFFFFFFFFULL;
+	struct cifsInodeInfo *cifsInode;
+	struct list_head *tmp;
+
+	xid = GetXid();
+
+	cFYI(1, (" 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;
+
+	down(&direntry->d_sb->s_vfs_rename_sem);
+	full_path = build_path_from_dentry(direntry);
+	up(&direntry->d_sb->s_vfs_rename_sem);
+	if (full_path == NULL) {
+		FreeXid(xid);
+		return -ENOMEM;
+	}
+	cifsInode = CIFS_I(direntry->d_inode);
+
+	/* BB check if we need to refresh inode from server now ? BB */
+
+	/* need to flush data before changing file size on server */
+	filemap_fdatawrite(direntry->d_inode->i_mapping);
+	filemap_fdatawait(direntry->d_inode->i_mapping);
+
+	if (attrs->ia_valid & ATTR_SIZE) {
+		read_lock(&GlobalSMBSeslock);
+		/* To avoid spurious oplock breaks from server, in the case of
+		   inodes that we already have open, avoid doing path based
+		   setting of file size if we can do it by handle.
+		   This keeps our caching token (oplock) and avoids timeouts
+		   when the local oplock break takes longer to flush
+		   writebehind data than the SMB timeout for the SetPathInfo
+		   request would allow */
+		list_for_each(tmp, &cifsInode->openFileList) {
+			open_file = list_entry(tmp, struct cifsFileInfo,
+					       flist);
+			/* We check if file is open for writing first */
+			if ((open_file->pfile) &&
+			    ((open_file->pfile->f_flags & O_RDWR) ||
+			    (open_file->pfile->f_flags & O_WRONLY))) {
+				if (open_file->invalidHandle == FALSE) {
+					/* we found a valid, writeable network
+					   file handle to use to try to set the
+					   file size */
+					__u16 nfid = open_file->netfid;
+					__u32 npid = open_file->pid;
+					read_unlock(&GlobalSMBSeslock);
+					found = TRUE;
+					rc = CIFSSMBSetFileSize(xid, pTcon,
+						attrs->ia_size, nfid, npid,
+						FALSE);
+					cFYI(1, ("SetFileSize by handle "
+						 "(setattrs) rc = %d", rc));
+					/* Do not need reopen and retry on
+					   EAGAIN since we will retry by
+					   pathname below */
+
+					/* now that we found one valid file
+					   handle no sense continuing to loop
+					   trying others, so break here */
+					break;
+				}
+			}
+		}
+		if (found == FALSE)
+			read_unlock(&GlobalSMBSeslock);
+
+		if (rc != 0) {
+			/* Set file size by pathname rather than by handle
+			   either because no valid, writeable file handle for
+			   it was found or because there was an error setting
+			   it by handle */
+			rc = CIFSSMBSetEOF(xid, pTcon, full_path,
+					   attrs->ia_size, FALSE,
+					   cifs_sb->local_nls);
+			cFYI(1, (" SetEOF by path (setattrs) rc = %d", rc));
+		}
+
+		/* Server is ok setting allocation size implicitly - no need
+		   to call:
+		CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, TRUE,
+			 cifs_sb->local_nls);
+		   */
+
+		if (rc == 0) {
+			rc = vmtruncate(direntry->d_inode, attrs->ia_size);
+			cifs_truncate_page(direntry->d_inode->i_mapping,
+					   direntry->d_inode->i_size);
+		}
+	}
+	if (attrs->ia_valid & ATTR_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, (" CIFS - GID changed to %d", attrs->ia_gid));
+		gid = attrs->ia_gid;
+		/* entry->gid = cpu_to_le16(attr->ia_gid); */
+	}
+
+	time_buf.Attributes = 0;
+	if (attrs->ia_valid & ATTR_MODE) {
+		cFYI(1, (" CIFS - Mode changed to 0x%x", attrs->ia_mode));
+		mode = attrs->ia_mode;
+		/* entry->mode = cpu_to_le16(attr->ia_mode); */
+	}
+
+	if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX)
+	    && (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID)))
+		rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid,
+					 0 /* dev_t */, cifs_sb->local_nls);
+	else if (attrs->ia_valid & ATTR_MODE) {
+		if ((mode & S_IWUGO) == 0) /* not writeable */ {
+			if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0)
+				time_buf.Attributes =
+					cpu_to_le32(cifsInode->cifsAttrs |
+						    ATTR_READONLY);
+		} else if ((mode & S_IWUGO) == S_IWUGO) {
+			if (cifsInode->cifsAttrs & ATTR_READONLY)
+				time_buf.Attributes =
+					cpu_to_le32(cifsInode->cifsAttrs &
+						    (~ATTR_READONLY));
+		}
+		/* BB to be implemented -
+		   via Windows security descriptors or streams */
+		/* CIFSSMBWinSetPerms(xid, pTcon, full_path, mode, uid, gid,
+				      cifs_sb->local_nls); */
+	}
+
+	if (attrs->ia_valid & ATTR_ATIME) {
+		set_time = TRUE;
+		time_buf.LastAccessTime =
+		    cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
+	} else
+		time_buf.LastAccessTime = 0;
+
+	if (attrs->ia_valid & ATTR_MTIME) {
+		set_time = TRUE;
+		time_buf.LastWriteTime =
+		    cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
+	} else
+		time_buf.LastWriteTime = 0;
+
+	if (attrs->ia_valid & ATTR_CTIME) {
+		set_time = TRUE;
+		cFYI(1, (" CIFS - CTIME changed ")); /* BB probably no need */
+		time_buf.ChangeTime =
+		    cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
+	} else
+		time_buf.ChangeTime = 0;
+
+	if (set_time || time_buf.Attributes) {
+		/* BB what if setting one attribute fails (such as size) but
+		   time setting works? */
+		time_buf.CreationTime = 0;	/* do not change */
+		/* In the future we should experiment - try setting timestamps
+		   via Handle (SetFileInfo) instead of by path */
+		if (!(pTcon->ses->flags & CIFS_SES_NT4))
+			rc = CIFSSMBSetTimes(xid, pTcon, full_path, &time_buf,
+					     cifs_sb->local_nls);
+		else
+			rc = -EOPNOTSUPP;
+
+		if (rc == -EOPNOTSUPP) {
+			int oplock = FALSE;
+			__u16 netfid;
+
+			cFYI(1, ("calling SetFileInfo since SetPathInfo for "
+				 "times not supported by this server"));
+			/* BB we could scan to see if we already have it open
+			   and pass in pid of opener to function */
+			rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
+					 SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
+					 CREATE_NOT_DIR, &netfid, &oplock,
+					 NULL, cifs_sb->local_nls);
+			if (rc==0) {
+				rc = CIFSSMBSetFileTimes(xid, pTcon, &time_buf,
+							 netfid);
+				CIFSSMBClose(xid, pTcon, netfid);
+			} else {
+			/* BB For even older servers we could convert time_buf
+			   into old DOS style which uses two second
+			   granularity */
+
+			/* rc = CIFSSMBSetTimesLegacy(xid, pTcon, full_path,
+        	        		&time_buf, cifs_sb->local_nls); */
+			}
+		}
+	}
+
+	/* do not need local check to inode_check_ok since the server does
+	   that */
+	if (!rc)
+		rc = inode_setattr(direntry->d_inode, attrs);
+	kfree(full_path);
+	FreeXid(xid);
+	return rc;
+}
+
+void cifs_delete_inode(struct inode *inode)
+{
+	cFYI(1, ("In cifs_delete_inode, inode = 0x%p ", inode));
+	/* may have to add back in if and when safe distributed caching of
+	   directories added e.g. via FindNotify */
+}
diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
new file mode 100644
index 0000000..b4b8e20
--- /dev/null
+++ b/fs/cifs/ioctl.c
@@ -0,0 +1,49 @@
+/*
+ *   fs/cifs/ioctl.c
+ *
+ *   vfs operations that deal with io control
+ *
+ *   Copyright (C) International Business Machines  Corp., 2005
+ *   Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/fs.h>
+#include <linux/ext2_fs.h>
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+
+int cifs_ioctl (struct inode * inode, struct file * filep, 
+		unsigned int command, unsigned long arg)
+{
+	int rc = -ENOTTY; /* strange error - but the precedent */
+#ifdef CONFIG_CIFS_POSIX
+	cFYI(1,("ioctl file %p  cmd %u  arg %lu",filep,command,arg));
+	switch(command) {
+		case EXT2_IOC_GETFLAGS:
+			cFYI(1,("get flags not implemented yet"));
+			return -EOPNOTSUPP;
+		case EXT2_IOC_SETFLAGS:
+			cFYI(1,("set flags not implemented yet"));
+			return -EOPNOTSUPP;
+		default:
+			cFYI(1,("unsupported ioctl"));
+			return rc;
+	}
+#endif /* CONFIG_CIFS_POSIX */
+	return rc;
+} 
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
new file mode 100644
index 0000000..1455810
--- /dev/null
+++ b/fs/cifs/link.c
@@ -0,0 +1,328 @@
+/*
+ *   fs/cifs/link.c
+ *
+ *   Copyright (C) International Business Machines  Corp., 2002,2003
+ *   Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <linux/namei.h>
+#include "cifsfs.h"
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+#include "cifs_fs_sb.h"
+
+int
+cifs_hardlink(struct dentry *old_file, struct inode *inode,
+	      struct dentry *direntry)
+{
+	int rc = -EACCES;
+	int xid;
+	char *fromName = NULL;
+	char *toName = NULL;
+	struct cifs_sb_info *cifs_sb_target;
+	struct cifsTconInfo *pTcon;
+	struct cifsInodeInfo *cifsInode;
+
+	xid = GetXid();
+
+	cifs_sb_target = CIFS_SB(inode->i_sb);
+	pTcon = cifs_sb_target->tcon;
+
+/* No need to check for cross device links since server will do that
+   BB note DFS case in future though (when we may have to check) */
+
+	down(&inode->i_sb->s_vfs_rename_sem);
+	fromName = build_path_from_dentry(old_file);
+	toName = build_path_from_dentry(direntry);
+	up(&inode->i_sb->s_vfs_rename_sem);
+	if((fromName == NULL) || (toName == NULL)) {
+		rc = -ENOMEM;
+		goto cifs_hl_exit;
+	}
+
+	if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX)
+		rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName,
+					    cifs_sb_target->local_nls);
+	else {
+		rc = CIFSCreateHardLink(xid, pTcon, fromName, toName,
+					cifs_sb_target->local_nls);
+		if(rc == -EIO)
+			rc = -EOPNOTSUPP;  
+	}
+
+/* if (!rc)     */
+	{
+		/*   renew_parental_timestamps(old_file);
+		   inode->i_nlink++;
+		   mark_inode_dirty(inode);
+		   d_instantiate(direntry, inode); */
+		/* BB add call to either mark inode dirty or refresh its data and timestamp to current time */
+	}
+	d_drop(direntry);	/* force new lookup from server */
+	cifsInode = CIFS_I(old_file->d_inode);
+	cifsInode->time = 0;	/* will force revalidate to go get info when needed */
+
+cifs_hl_exit:
+	if (fromName)
+		kfree(fromName);
+	if (toName)
+		kfree(toName);
+	FreeXid(xid);
+	return rc;
+}
+
+int
+cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
+{
+	struct inode *inode = direntry->d_inode;
+	int rc = -EACCES;
+	int xid;
+	char *full_path = NULL;
+	char * target_path = ERR_PTR(-ENOMEM);
+	struct cifs_sb_info *cifs_sb;
+	struct cifsTconInfo *pTcon;
+
+	xid = GetXid();
+
+	down(&direntry->d_sb->s_vfs_rename_sem);
+	full_path = build_path_from_dentry(direntry);
+	up(&direntry->d_sb->s_vfs_rename_sem);
+
+	if (!full_path)
+		goto out_no_free;
+
+	cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode));
+	cifs_sb = CIFS_SB(inode->i_sb);
+	pTcon = cifs_sb->tcon;
+	target_path = kmalloc(PATH_MAX, GFP_KERNEL);
+	if (!target_path) {
+		target_path = ERR_PTR(-ENOMEM);
+		goto out;
+	}
+
+/* BB add read reparse point symlink code and Unix extensions symlink code here BB */
+	if (pTcon->ses->capabilities & CAP_UNIX)
+		rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
+					     target_path,
+					     PATH_MAX-1,
+					     cifs_sb->local_nls);
+	else {
+		/* rc = CIFSSMBQueryReparseLinkInfo */
+		/* BB Add code to Query ReparsePoint info */
+		/* BB Add MAC style xsymlink check here if enabled */
+	}
+
+	if (rc == 0) {
+
+/* BB Add special case check for Samba DFS symlinks */
+
+		target_path[PATH_MAX-1] = 0;
+	} else {
+		kfree(target_path);
+		target_path = ERR_PTR(rc);
+	}
+
+out:
+	kfree(full_path);
+out_no_free:
+	FreeXid(xid);
+	nd_set_link(nd, target_path);
+	return 0;
+}
+
+int
+cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
+{
+	int rc = -EOPNOTSUPP;
+	int xid;
+	struct cifs_sb_info *cifs_sb;
+	struct cifsTconInfo *pTcon;
+	char *full_path = NULL;
+	struct inode *newinode = NULL;
+
+	xid = GetXid();
+
+	cifs_sb = CIFS_SB(inode->i_sb);
+	pTcon = cifs_sb->tcon;
+
+	down(&inode->i_sb->s_vfs_rename_sem);
+	full_path = build_path_from_dentry(direntry);
+	up(&inode->i_sb->s_vfs_rename_sem);
+
+	if(full_path == NULL) {
+		FreeXid(xid);
+		return -ENOMEM;
+	}
+
+	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)
+		rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
+					   cifs_sb->local_nls);
+	/* else
+	   rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName,cifs_sb_target->local_nls); */
+
+	if (rc == 0) {
+		if (pTcon->ses->capabilities & CAP_UNIX)
+			rc = cifs_get_inode_info_unix(&newinode, full_path,
+						      inode->i_sb,xid);
+		else
+			rc = cifs_get_inode_info(&newinode, full_path, NULL,
+						 inode->i_sb,xid);
+
+		if (rc != 0) {
+			cFYI(1,
+			     ("Create symlink worked but get_inode_info failed with rc = %d ",
+			      rc));
+		} else {
+			direntry->d_op = &cifs_dentry_ops;
+			d_instantiate(direntry, newinode);
+		}
+	}
+
+	if (full_path)
+		kfree(full_path);
+	FreeXid(xid);
+	return rc;
+}
+
+int
+cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
+{
+	struct inode *inode = direntry->d_inode;
+	int rc = -EACCES;
+	int xid;
+	int oplock = FALSE;
+	struct cifs_sb_info *cifs_sb;
+	struct cifsTconInfo *pTcon;
+	char *full_path = NULL;
+	char *tmp_path =  NULL;
+	char * tmpbuffer;
+	unsigned char * referrals = NULL;
+	int num_referrals = 0;
+	int len;
+	__u16 fid;
+
+	xid = GetXid();
+	cifs_sb = CIFS_SB(inode->i_sb);
+	pTcon = cifs_sb->tcon;
+
+/* BB would it be safe against deadlock to grab this sem 
+      even though rename itself grabs the sem and calls lookup? */
+/*       down(&inode->i_sb->s_vfs_rename_sem);*/
+	full_path = build_path_from_dentry(direntry);
+/*       up(&inode->i_sb->s_vfs_rename_sem);*/
+
+	if(full_path == NULL) {
+		FreeXid(xid);
+		return -ENOMEM;
+	}
+
+	cFYI(1,
+	     ("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d",
+	      full_path, inode, pBuffer, buflen));
+	if(buflen > PATH_MAX)
+		len = PATH_MAX;
+	else
+		len = buflen;
+	tmpbuffer = kmalloc(len,GFP_KERNEL);   
+	if(tmpbuffer == NULL) {
+		if (full_path)
+			kfree(full_path);
+		FreeXid(xid);
+		return -ENOMEM;
+	}
+
+/* BB add read reparse point symlink code and Unix extensions symlink code here BB */
+	if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
+		rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
+				tmpbuffer,
+				len - 1,
+				cifs_sb->local_nls);
+	else {
+		rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ,
+				OPEN_REPARSE_POINT,&fid, &oplock, NULL, cifs_sb->local_nls);
+		if(!rc) {
+			rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path,
+				tmpbuffer,
+				len - 1, 
+				fid,
+				cifs_sb->local_nls);
+			if(CIFSSMBClose(xid, pTcon, fid)) {
+				cFYI(1,("Error closing junction point (open for ioctl)"));
+			}
+			if(rc == -EIO) {
+				/* Query if DFS Junction */
+				tmp_path =
+					kmalloc(MAX_TREE_SIZE + MAX_PATHCONF + 1,
+						GFP_KERNEL);
+				if (tmp_path) {
+					strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
+					strncat(tmp_path, full_path, MAX_PATHCONF);
+					rc = get_dfs_path(xid, pTcon->ses, tmp_path,
+						cifs_sb->local_nls, &num_referrals, &referrals);
+					cFYI(1,("Get DFS for %s rc = %d ",tmp_path, rc));
+					if((num_referrals == 0) && (rc == 0))
+						rc = -EACCES;
+					else {
+						cFYI(1,("num referral: %d",num_referrals));
+						if(referrals) {
+							cFYI(1,("referral string: %s ",referrals));
+							strncpy(tmpbuffer, referrals, len-1);                            
+						}
+					}
+					if(referrals)
+						kfree(referrals);
+					kfree(tmp_path);
+}
+				/* BB add code like else decode referrals then memcpy to
+				  tmpbuffer and free referrals string array BB */
+			}
+		}
+	}
+	/* BB Anything else to do to handle recursive links? */
+	/* BB Should we be using page ops here? */
+
+	/* BB null terminate returned string in pBuffer? BB */
+	if (rc == 0) {
+		rc = vfs_readlink(direntry, pBuffer, len, tmpbuffer);
+		cFYI(1,
+		     ("vfs_readlink called from cifs_readlink returned %d",
+		      rc));
+	}
+
+	if (tmpbuffer) {
+		kfree(tmpbuffer);
+	}
+	if (full_path) {
+		kfree(full_path);
+	}
+	FreeXid(xid);
+	return rc;
+}
+
+void cifs_put_link(struct dentry *direntry, struct nameidata *nd)
+{
+	char *p = nd_get_link(nd);
+	if (!IS_ERR(p))
+		kfree(p);
+}
diff --git a/fs/cifs/md4.c b/fs/cifs/md4.c
new file mode 100644
index 0000000..46d62c9
--- /dev/null
+++ b/fs/cifs/md4.c
@@ -0,0 +1,205 @@
+/* 
+   Unix SMB/Netbios implementation.
+   Version 1.9.
+   a implementation of MD4 designed for use in the SMB authentication protocol
+   Copyright (C) Andrew Tridgell 1997-1998.
+   Modified by Steve French (sfrench@us.ibm.com) 2002-2003
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#include <linux/module.h>
+#include <linux/fs.h>
+#include "cifsencrypt.h"
+
+/* NOTE: This code makes no attempt to be fast! */
+
+static __u32
+F(__u32 X, __u32 Y, __u32 Z)
+{
+	return (X & Y) | ((~X) & Z);
+}
+
+static __u32
+G(__u32 X, __u32 Y, __u32 Z)
+{
+	return (X & Y) | (X & Z) | (Y & Z);
+}
+
+static __u32
+H(__u32 X, __u32 Y, __u32 Z)
+{
+	return X ^ Y ^ Z;
+}
+
+static __u32
+lshift(__u32 x, int s)
+{
+	x &= 0xFFFFFFFF;
+	return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s));
+}
+
+#define ROUND1(a,b,c,d,k,s) (*a) = lshift((*a) + F(*b,*c,*d) + X[k], s)
+#define ROUND2(a,b,c,d,k,s) (*a) = lshift((*a) + G(*b,*c,*d) + X[k] + (__u32)0x5A827999,s)
+#define ROUND3(a,b,c,d,k,s) (*a) = lshift((*a) + H(*b,*c,*d) + X[k] + (__u32)0x6ED9EBA1,s)
+
+/* this applies md4 to 64 byte chunks */
+static void
+mdfour64(__u32 * M, __u32 * A, __u32 *B, __u32 * C, __u32 *D)
+{
+	int j;
+	__u32 AA, BB, CC, DD;
+	__u32 X[16];
+
+
+	for (j = 0; j < 16; j++)
+		X[j] = M[j];
+
+	AA = *A;
+	BB = *B;
+	CC = *C;
+	DD = *D;
+
+	ROUND1(A, B, C, D, 0, 3);
+	ROUND1(D, A, B, C, 1, 7);
+	ROUND1(C, D, A, B, 2, 11);
+	ROUND1(B, C, D, A, 3, 19);
+	ROUND1(A, B, C, D, 4, 3);
+	ROUND1(D, A, B, C, 5, 7);
+	ROUND1(C, D, A, B, 6, 11);
+	ROUND1(B, C, D, A, 7, 19);
+	ROUND1(A, B, C, D, 8, 3);
+	ROUND1(D, A, B, C, 9, 7);
+	ROUND1(C, D, A, B, 10, 11);
+	ROUND1(B, C, D, A, 11, 19);
+	ROUND1(A, B, C, D, 12, 3);
+	ROUND1(D, A, B, C, 13, 7);
+	ROUND1(C, D, A, B, 14, 11);
+	ROUND1(B, C, D, A, 15, 19);
+
+	ROUND2(A, B, C, D, 0, 3);
+	ROUND2(D, A, B, C, 4, 5);
+	ROUND2(C, D, A, B, 8, 9);
+	ROUND2(B, C, D, A, 12, 13);
+	ROUND2(A, B, C, D, 1, 3);
+	ROUND2(D, A, B, C, 5, 5);
+	ROUND2(C, D, A, B, 9, 9);
+	ROUND2(B, C, D, A, 13, 13);
+	ROUND2(A, B, C, D, 2, 3);
+	ROUND2(D, A, B, C, 6, 5);
+	ROUND2(C, D, A, B, 10, 9);
+	ROUND2(B, C, D, A, 14, 13);
+	ROUND2(A, B, C, D, 3, 3);
+	ROUND2(D, A, B, C, 7, 5);
+	ROUND2(C, D, A, B, 11, 9);
+	ROUND2(B, C, D, A, 15, 13);
+
+	ROUND3(A, B, C, D, 0, 3);
+	ROUND3(D, A, B, C, 8, 9);
+	ROUND3(C, D, A, B, 4, 11);
+	ROUND3(B, C, D, A, 12, 15);
+	ROUND3(A, B, C, D, 2, 3);
+	ROUND3(D, A, B, C, 10, 9);
+	ROUND3(C, D, A, B, 6, 11);
+	ROUND3(B, C, D, A, 14, 15);
+	ROUND3(A, B, C, D, 1, 3);
+	ROUND3(D, A, B, C, 9, 9);
+	ROUND3(C, D, A, B, 5, 11);
+	ROUND3(B, C, D, A, 13, 15);
+	ROUND3(A, B, C, D, 3, 3);
+	ROUND3(D, A, B, C, 11, 9);
+	ROUND3(C, D, A, B, 7, 11);
+	ROUND3(B, C, D, A, 15, 15);
+
+	*A += AA;
+	*B += BB;
+	*C += CC;
+	*D += DD;
+
+	*A &= 0xFFFFFFFF;
+	*B &= 0xFFFFFFFF;
+	*C &= 0xFFFFFFFF;
+	*D &= 0xFFFFFFFF;
+
+	for (j = 0; j < 16; j++)
+		X[j] = 0;
+}
+
+static void
+copy64(__u32 * M, unsigned char *in)
+{
+	int i;
+
+	for (i = 0; i < 16; i++)
+		M[i] = (in[i * 4 + 3] << 24) | (in[i * 4 + 2] << 16) |
+		    (in[i * 4 + 1] << 8) | (in[i * 4 + 0] << 0);
+}
+
+static void
+copy4(unsigned char *out, __u32 x)
+{
+	out[0] = x & 0xFF;
+	out[1] = (x >> 8) & 0xFF;
+	out[2] = (x >> 16) & 0xFF;
+	out[3] = (x >> 24) & 0xFF;
+}
+
+/* produce a md4 message digest from data of length n bytes */
+void
+mdfour(unsigned char *out, unsigned char *in, int n)
+{
+	unsigned char buf[128];
+	__u32 M[16];
+	__u32 b = n * 8;
+	int i;
+	__u32 A = 0x67452301;
+	__u32 B = 0xefcdab89;
+	__u32 C = 0x98badcfe;
+	__u32 D = 0x10325476;
+
+	while (n > 64) {
+		copy64(M, in);
+		mdfour64(M,&A,&B, &C, &D);
+		in += 64;
+		n -= 64;
+	}
+
+	for (i = 0; i < 128; i++)
+		buf[i] = 0;
+	memcpy(buf, in, n);
+	buf[n] = 0x80;
+
+	if (n <= 55) {
+		copy4(buf + 56, b);
+		copy64(M, buf);
+		mdfour64(M, &A, &B, &C, &D);
+	} else {
+		copy4(buf + 120, b);
+		copy64(M, buf);
+		mdfour64(M, &A, &B, &C, &D);
+		copy64(M, buf + 64);
+		mdfour64(M, &A, &B, &C, &D);
+	}
+
+	for (i = 0; i < 128; i++)
+		buf[i] = 0;
+	copy64(M, buf);
+
+	copy4(out, A);
+	copy4(out + 4, B);
+	copy4(out + 8, C);
+	copy4(out + 12, D);
+
+	A = B = C = D = 0;
+}
diff --git a/fs/cifs/md5.c b/fs/cifs/md5.c
new file mode 100644
index 0000000..7aa2349
--- /dev/null
+++ b/fs/cifs/md5.c
@@ -0,0 +1,363 @@
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest.  This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ */
+
+/* This code slightly modified to fit into Samba by 
+   abartlet@samba.org Jun 2001 
+   and to fit the cifs vfs by 
+   Steve French sfrench@us.ibm.com */
+
+#include <linux/string.h>
+#include "md5.h"
+
+static void MD5Transform(__u32 buf[4], __u32 const in[16]);
+
+/*
+ * Note: this code is harmless on little-endian machines.
+ */
+static void
+byteReverse(unsigned char *buf, unsigned longs)
+{
+	__u32 t;
+	do {
+		t = (__u32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
+		    ((unsigned) buf[1] << 8 | buf[0]);
+		*(__u32 *) buf = t;
+		buf += 4;
+	} while (--longs);
+}
+
+/*
+ * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void
+MD5Init(struct MD5Context *ctx)
+{
+	ctx->buf[0] = 0x67452301;
+	ctx->buf[1] = 0xefcdab89;
+	ctx->buf[2] = 0x98badcfe;
+	ctx->buf[3] = 0x10325476;
+
+	ctx->bits[0] = 0;
+	ctx->bits[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void
+MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
+{
+	register __u32 t;
+
+	/* Update bitcount */
+
+	t = ctx->bits[0];
+	if ((ctx->bits[0] = t + ((__u32) len << 3)) < t)
+		ctx->bits[1]++;	/* Carry from low to high */
+	ctx->bits[1] += len >> 29;
+
+	t = (t >> 3) & 0x3f;	/* Bytes already in shsInfo->data */
+
+	/* Handle any leading odd-sized chunks */
+
+	if (t) {
+		unsigned char *p = (unsigned char *) ctx->in + t;
+
+		t = 64 - t;
+		if (len < t) {
+			memmove(p, buf, len);
+			return;
+		}
+		memmove(p, buf, t);
+		byteReverse(ctx->in, 16);
+		MD5Transform(ctx->buf, (__u32 *) ctx->in);
+		buf += t;
+		len -= t;
+	}
+	/* Process data in 64-byte chunks */
+
+	while (len >= 64) {
+		memmove(ctx->in, buf, 64);
+		byteReverse(ctx->in, 16);
+		MD5Transform(ctx->buf, (__u32 *) ctx->in);
+		buf += 64;
+		len -= 64;
+	}
+
+	/* Handle any remaining bytes of data. */
+
+	memmove(ctx->in, buf, len);
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern 
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void
+MD5Final(unsigned char digest[16], struct MD5Context *ctx)
+{
+	unsigned int count;
+	unsigned char *p;
+
+	/* Compute number of bytes mod 64 */
+	count = (ctx->bits[0] >> 3) & 0x3F;
+
+	/* Set the first char of padding to 0x80.  This is safe since there is
+	   always at least one byte free */
+	p = ctx->in + count;
+	*p++ = 0x80;
+
+	/* Bytes of padding needed to make 64 bytes */
+	count = 64 - 1 - count;
+
+	/* Pad out to 56 mod 64 */
+	if (count < 8) {
+		/* Two lots of padding:  Pad the first block to 64 bytes */
+		memset(p, 0, count);
+		byteReverse(ctx->in, 16);
+		MD5Transform(ctx->buf, (__u32 *) ctx->in);
+
+		/* Now fill the next block with 56 bytes */
+		memset(ctx->in, 0, 56);
+	} else {
+		/* Pad block to 56 bytes */
+		memset(p, 0, count - 8);
+	}
+	byteReverse(ctx->in, 14);
+
+	/* Append length in bits and transform */
+	((__u32 *) ctx->in)[14] = ctx->bits[0];
+	((__u32 *) ctx->in)[15] = ctx->bits[1];
+
+	MD5Transform(ctx->buf, (__u32 *) ctx->in);
+	byteReverse((unsigned char *) ctx->buf, 4);
+	memmove(digest, ctx->buf, 16);
+	memset(ctx, 0, sizeof(*ctx));	/* In case it's sensitive */
+}
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f, w, x, y, z, data, s) \
+	( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data.  MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+static void
+MD5Transform(__u32 buf[4], __u32 const in[16])
+{
+	register __u32 a, b, c, d;
+
+	a = buf[0];
+	b = buf[1];
+	c = buf[2];
+	d = buf[3];
+
+	MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+	MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+	MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+	MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+	MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+	MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+	MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+	MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+	MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+	MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+	MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+	MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+	MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+	MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+	MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+	MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+	MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+	MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+	MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+	MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+	MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+	MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+	MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+	MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+	MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+	MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+	MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+	MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+	MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+	MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+	MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+	MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+	MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+	MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+	MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+	MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+	MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+	MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+	MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+	MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+	MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+	MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+	MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+	MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+	MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+	MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+	MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+	MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+	MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+	MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+	MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+	MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+	MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+	MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+	MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+	MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+	MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+	MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+	MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+	MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+	MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+	MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+	MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+	MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+	buf[0] += a;
+	buf[1] += b;
+	buf[2] += c;
+	buf[3] += d;
+}
+
+/***********************************************************************
+ the rfc 2104 version of hmac_md5 initialisation.
+***********************************************************************/
+void
+hmac_md5_init_rfc2104(unsigned char *key, int key_len,
+		      struct HMACMD5Context *ctx)
+{
+	int i;
+
+	/* if key is longer than 64 bytes reset it to key=MD5(key) */
+	if (key_len > 64) {
+		unsigned char tk[16];
+		struct MD5Context tctx;
+
+		MD5Init(&tctx);
+		MD5Update(&tctx, key, key_len);
+		MD5Final(tk, &tctx);
+
+		key = tk;
+		key_len = 16;
+	}
+
+	/* start out by storing key in pads */
+	memset(ctx->k_ipad, 0, sizeof (ctx->k_ipad));
+	memset(ctx->k_opad, 0, sizeof (ctx->k_opad));
+	memcpy(ctx->k_ipad, key, key_len);
+	memcpy(ctx->k_opad, key, key_len);
+
+	/* XOR key with ipad and opad values */
+	for (i = 0; i < 64; i++) {
+		ctx->k_ipad[i] ^= 0x36;
+		ctx->k_opad[i] ^= 0x5c;
+	}
+
+	MD5Init(&ctx->ctx);
+	MD5Update(&ctx->ctx, ctx->k_ipad, 64);
+}
+
+/***********************************************************************
+ the microsoft version of hmac_md5 initialisation.
+***********************************************************************/
+void
+hmac_md5_init_limK_to_64(const unsigned char *key, int key_len,
+			 struct HMACMD5Context *ctx)
+{
+	int i;
+
+	/* if key is longer than 64 bytes truncate it */
+	if (key_len > 64) {
+		key_len = 64;
+	}
+
+	/* start out by storing key in pads */
+	memset(ctx->k_ipad, 0, sizeof (ctx->k_ipad));
+	memset(ctx->k_opad, 0, sizeof (ctx->k_opad));
+	memcpy(ctx->k_ipad, key, key_len);
+	memcpy(ctx->k_opad, key, key_len);
+
+	/* XOR key with ipad and opad values */
+	for (i = 0; i < 64; i++) {
+		ctx->k_ipad[i] ^= 0x36;
+		ctx->k_opad[i] ^= 0x5c;
+	}
+
+	MD5Init(&ctx->ctx);
+	MD5Update(&ctx->ctx, ctx->k_ipad, 64);
+}
+
+/***********************************************************************
+ update hmac_md5 "inner" buffer
+***********************************************************************/
+void
+hmac_md5_update(const unsigned char *text, int text_len,
+		struct HMACMD5Context *ctx)
+{
+	MD5Update(&ctx->ctx, text, text_len);	/* then text of datagram */
+}
+
+/***********************************************************************
+ finish off hmac_md5 "inner" buffer and generate outer one.
+***********************************************************************/
+void
+hmac_md5_final(unsigned char *digest, struct HMACMD5Context *ctx)
+{
+	struct MD5Context ctx_o;
+
+	MD5Final(digest, &ctx->ctx);
+
+	MD5Init(&ctx_o);
+	MD5Update(&ctx_o, ctx->k_opad, 64);
+	MD5Update(&ctx_o, digest, 16);
+	MD5Final(digest, &ctx_o);
+}
+
+/***********************************************************
+ single function to calculate an HMAC MD5 digest from data.
+ use the microsoft hmacmd5 init method because the key is 16 bytes.
+************************************************************/
+void
+hmac_md5(unsigned char key[16], unsigned char *data, int data_len,
+	 unsigned char *digest)
+{
+	struct HMACMD5Context ctx;
+	hmac_md5_init_limK_to_64(key, 16, &ctx);
+	if (data_len != 0) {
+		hmac_md5_update(data, data_len, &ctx);
+	}
+	hmac_md5_final(digest, &ctx);
+}
diff --git a/fs/cifs/md5.h b/fs/cifs/md5.h
new file mode 100644
index 0000000..00e1c53
--- /dev/null
+++ b/fs/cifs/md5.h
@@ -0,0 +1,38 @@
+#ifndef MD5_H
+#define MD5_H
+#ifndef HEADER_MD5_H
+/* Try to avoid clashes with OpenSSL */
+#define HEADER_MD5_H
+#endif
+
+struct MD5Context {
+	__u32 buf[4];
+	__u32 bits[2];
+	unsigned char in[64];
+};
+#endif				/* !MD5_H */
+
+#ifndef _HMAC_MD5_H
+struct HMACMD5Context {
+	struct MD5Context ctx;
+	unsigned char k_ipad[65];
+	unsigned char k_opad[65];
+};
+#endif				/* _HMAC_MD5_H */
+
+void MD5Init(struct MD5Context *context);
+void MD5Update(struct MD5Context *context, unsigned char const *buf,
+			unsigned len);
+void MD5Final(unsigned char digest[16], struct MD5Context *context);
+
+/* The following definitions come from lib/hmacmd5.c  */
+
+void hmac_md5_init_rfc2104(unsigned char *key, int key_len,
+			struct HMACMD5Context *ctx);
+void hmac_md5_init_limK_to_64(const unsigned char *key, int key_len,
+			struct HMACMD5Context *ctx);
+void hmac_md5_update(const unsigned char *text, int text_len,
+			struct HMACMD5Context *ctx);
+void hmac_md5_final(unsigned char *digest, struct HMACMD5Context *ctx);
+void hmac_md5(unsigned char key[16], unsigned char *data, int data_len,
+			unsigned char *digest);
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
new file mode 100644
index 0000000..7b38d30
--- /dev/null
+++ b/fs/cifs/misc.c
@@ -0,0 +1,516 @@
+/*
+ *   fs/cifs/misc.c
+ *
+ *   Copyright (C) International Business Machines  Corp., 2002,2004
+ *   Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ */
+
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/mempool.h>
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+#include "smberr.h"
+#include "nterr.h"
+
+extern mempool_t *cifs_sm_req_poolp;
+extern mempool_t *cifs_req_poolp;
+extern struct task_struct * oplockThread;
+
+static __u16 GlobalMid;		/* multiplex id - rotating counter */
+
+/* The xid serves as a useful identifier for each incoming vfs request, 
+   in a similar way to the mid which is useful to track each sent smb, 
+   and CurrentXid can also provide a running counter (although it 
+   will eventually wrap past zero) of the total vfs operations handled 
+   since the cifs fs was mounted */
+
+unsigned int
+_GetXid(void)
+{
+	unsigned int xid;
+
+	spin_lock(&GlobalMid_Lock);
+	GlobalTotalActiveXid++;
+	if (GlobalTotalActiveXid > GlobalMaxActiveXid)
+		GlobalMaxActiveXid = GlobalTotalActiveXid;	/* keep high water mark for number of simultaneous vfs ops in our filesystem */
+	xid = GlobalCurrentXid++;
+	spin_unlock(&GlobalMid_Lock);
+	return xid;
+}
+
+void
+_FreeXid(unsigned int xid)
+{
+	spin_lock(&GlobalMid_Lock);
+	/* if(GlobalTotalActiveXid == 0)
+		BUG(); */
+	GlobalTotalActiveXid--;
+	spin_unlock(&GlobalMid_Lock);
+}
+
+struct cifsSesInfo *
+sesInfoAlloc(void)
+{
+	struct cifsSesInfo *ret_buf;
+
+	ret_buf =
+	    (struct cifsSesInfo *) kmalloc(sizeof (struct cifsSesInfo),
+					   GFP_KERNEL);
+	if (ret_buf) {
+		memset(ret_buf, 0, sizeof (struct cifsSesInfo));
+		write_lock(&GlobalSMBSeslock);
+		atomic_inc(&sesInfoAllocCount);
+		ret_buf->status = CifsNew;
+		list_add(&ret_buf->cifsSessionList, &GlobalSMBSessionList);
+		init_MUTEX(&ret_buf->sesSem);
+		write_unlock(&GlobalSMBSeslock);
+	}
+	return ret_buf;
+}
+
+void
+sesInfoFree(struct cifsSesInfo *buf_to_free)
+{
+	if (buf_to_free == NULL) {
+		cFYI(1, ("Null buffer passed to sesInfoFree"));
+		return;
+	}
+
+	write_lock(&GlobalSMBSeslock);
+	atomic_dec(&sesInfoAllocCount);
+	list_del(&buf_to_free->cifsSessionList);
+	write_unlock(&GlobalSMBSeslock);
+	if (buf_to_free->serverOS)
+		kfree(buf_to_free->serverOS);
+	if (buf_to_free->serverDomain)
+		kfree(buf_to_free->serverDomain);
+	if (buf_to_free->serverNOS)
+		kfree(buf_to_free->serverNOS);
+	if (buf_to_free->password)
+		kfree(buf_to_free->password);
+	kfree(buf_to_free);
+}
+
+struct cifsTconInfo *
+tconInfoAlloc(void)
+{
+	struct cifsTconInfo *ret_buf;
+	ret_buf =
+	    (struct cifsTconInfo *) kmalloc(sizeof (struct cifsTconInfo),
+					    GFP_KERNEL);
+	if (ret_buf) {
+		memset(ret_buf, 0, sizeof (struct cifsTconInfo));
+		write_lock(&GlobalSMBSeslock);
+		atomic_inc(&tconInfoAllocCount);
+		list_add(&ret_buf->cifsConnectionList,
+			 &GlobalTreeConnectionList);
+		ret_buf->tidStatus = CifsNew;
+		INIT_LIST_HEAD(&ret_buf->openFileList);
+		init_MUTEX(&ret_buf->tconSem);
+#ifdef CONFIG_CIFS_STATS
+		spin_lock_init(&ret_buf->stat_lock);
+#endif
+		write_unlock(&GlobalSMBSeslock);
+	}
+	return ret_buf;
+}
+
+void
+tconInfoFree(struct cifsTconInfo *buf_to_free)
+{
+	if (buf_to_free == NULL) {
+		cFYI(1, ("Null buffer passed to tconInfoFree"));
+		return;
+	}
+	write_lock(&GlobalSMBSeslock);
+	atomic_dec(&tconInfoAllocCount);
+	list_del(&buf_to_free->cifsConnectionList);
+	write_unlock(&GlobalSMBSeslock);
+	if (buf_to_free->nativeFileSystem)
+		kfree(buf_to_free->nativeFileSystem);
+	kfree(buf_to_free);
+}
+
+struct smb_hdr *
+cifs_buf_get(void)
+{
+	struct smb_hdr *ret_buf = NULL;
+
+/* We could use negotiated size instead of max_msgsize - 
+   but it may be more efficient to always alloc same size 
+   albeit slightly larger than necessary and maxbuffersize 
+   defaults to this and can not be bigger */
+	ret_buf =
+	    (struct smb_hdr *) mempool_alloc(cifs_req_poolp, SLAB_KERNEL | SLAB_NOFS);
+
+	/* clear the first few header bytes */
+	/* for most paths, more is cleared in header_assemble */
+	if (ret_buf) {
+		memset(ret_buf, 0, sizeof(struct smb_hdr) + 3);
+		atomic_inc(&bufAllocCount);
+	}
+
+	return ret_buf;
+}
+
+void
+cifs_buf_release(void *buf_to_free)
+{
+
+	if (buf_to_free == NULL) {
+		/* cFYI(1, ("Null buffer passed to cifs_buf_release"));*/
+		return;
+	}
+	mempool_free(buf_to_free,cifs_req_poolp);
+
+	atomic_dec(&bufAllocCount);
+	return;
+}
+
+struct smb_hdr *
+cifs_small_buf_get(void)
+{
+	struct smb_hdr *ret_buf = NULL;
+
+/* We could use negotiated size instead of max_msgsize - 
+   but it may be more efficient to always alloc same size 
+   albeit slightly larger than necessary and maxbuffersize 
+   defaults to this and can not be bigger */
+	ret_buf =
+	    (struct smb_hdr *) mempool_alloc(cifs_sm_req_poolp, SLAB_KERNEL | SLAB_NOFS);
+	if (ret_buf) {
+	/* No need to clear memory here, cleared in header assemble */
+	/*	memset(ret_buf, 0, sizeof(struct smb_hdr) + 27);*/
+		atomic_inc(&smBufAllocCount);
+	}
+	return ret_buf;
+}
+
+void
+cifs_small_buf_release(void *buf_to_free)
+{
+
+	if (buf_to_free == NULL) {
+		cFYI(1, ("Null buffer passed to cifs_small_buf_release"));
+		return;
+	}
+	mempool_free(buf_to_free,cifs_sm_req_poolp);
+
+	atomic_dec(&smBufAllocCount);
+	return;
+}
+
+void
+header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
+		const struct cifsTconInfo *treeCon, int word_count
+		/* length of fixed section (word count) in two byte units  */)
+{
+	struct list_head* temp_item;
+	struct cifsSesInfo * ses;
+	char *temp = (char *) buffer;
+
+	memset(temp,0,MAX_CIFS_HDR_SIZE);
+
+	buffer->smb_buf_length =
+	    (2 * word_count) + sizeof (struct smb_hdr) -
+	    4 /*  RFC 1001 length field does not count */  +
+	    2 /* for bcc field itself */ ;
+	/* Note that this is the only network field that has to be converted to big endian and it is done just before we send it */
+
+	buffer->Protocol[0] = 0xFF;
+	buffer->Protocol[1] = 'S';
+	buffer->Protocol[2] = 'M';
+	buffer->Protocol[3] = 'B';
+	buffer->Command = smb_command;
+	buffer->Flags = 0x00;	/* case sensitive */
+	buffer->Flags2 = SMBFLG2_KNOWS_LONG_NAMES;
+	buffer->Pid = cpu_to_le16((__u16)current->tgid);
+	buffer->PidHigh = cpu_to_le16((__u16)(current->tgid >> 16));
+	spin_lock(&GlobalMid_Lock);
+	GlobalMid++;
+	buffer->Mid = GlobalMid;
+	spin_unlock(&GlobalMid_Lock);
+	if (treeCon) {
+		buffer->Tid = treeCon->tid;
+		if (treeCon->ses) {
+			if (treeCon->ses->capabilities & CAP_UNICODE)
+				buffer->Flags2 |= SMBFLG2_UNICODE;
+			if (treeCon->ses->capabilities & CAP_STATUS32) {
+				buffer->Flags2 |= SMBFLG2_ERR_STATUS;
+			}
+
+			buffer->Uid = treeCon->ses->Suid;	/* always in LE format */
+			if(multiuser_mount != 0) {
+		/* For the multiuser case, there are few obvious technically  */
+		/* possible mechanisms to match the local linux user (uid)    */
+		/* to a valid remote smb user (smb_uid):		      */
+		/* 	1) Query Winbind (or other local pam/nss daemon       */
+		/* 	  for userid/password/logon_domain or credential      */
+		/*      2) Query Winbind for uid to sid to username mapping   */
+		/* 	   and see if we have a matching password for existing*/
+		/*         session for that user perhas getting password by   */
+		/*         adding a new pam_cifs module that stores passwords */
+		/*         so that the cifs vfs can get at that for all logged*/
+		/*	   on users					      */
+		/*	3) (Which is the mechanism we have chosen)	      */
+		/*	   Search through sessions to the same server for a   */
+		/*	   a match on the uid that was passed in on mount     */
+		/*         with the current processes uid (or euid?) and use  */
+		/* 	   that smb uid.   If no existing smb session for     */
+		/* 	   that uid found, use the default smb session ie     */
+		/*         the smb session for the volume mounted which is    */
+		/* 	   the same as would be used if the multiuser mount   */
+		/* 	   flag were disabled.  */
+
+		/*  BB Add support for establishing new tCon and SMB Session  */
+		/*      with userid/password pairs found on the smb session   */ 
+		/*	for other target tcp/ip addresses 		BB    */
+				if(current->uid != treeCon->ses->linux_uid) {
+					cFYI(1,("Multiuser mode and UID did not match tcon uid "));
+					read_lock(&GlobalSMBSeslock);
+					list_for_each(temp_item, &GlobalSMBSessionList) {
+						ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList);
+						if(ses->linux_uid == current->uid) {
+							if(ses->server == treeCon->ses->server) {
+								cFYI(1,("found matching uid substitute right smb_uid"));  
+								buffer->Uid = ses->Suid;
+								break;
+							} else {
+								/* BB eventually call cifs_setup_session here */
+								cFYI(1,("local UID found but smb sess with this server does not exist"));  
+							}
+						}
+					}
+					read_unlock(&GlobalSMBSeslock);
+				}
+			}
+		}
+		if (treeCon->Flags & SMB_SHARE_IS_IN_DFS)
+			buffer->Flags2 |= SMBFLG2_DFS;
+		if((treeCon->ses) && (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 */
+	buffer->WordCount = (char) word_count;
+	return;
+}
+
+int
+checkSMBhdr(struct smb_hdr *smb, __u16 mid)
+{
+	/* Make sure that this really is an SMB, that it is a response, 
+	   and that the message ids match */
+	if ((*(__le32 *) smb->Protocol == cpu_to_le32(0x424d53ff)) && 
+		(mid == smb->Mid)) {    
+		if(smb->Flags & SMBFLG_RESPONSE)
+			return 0;                    
+		else {        
+		/* only one valid case where server sends us request */
+			if(smb->Command == SMB_COM_LOCKING_ANDX)
+				return 0;
+			else
+				cERROR(1, ("Rcvd Request not response "));         
+		}
+	} else { /* bad signature or mid */
+		if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff))
+			cERROR(1,
+			       ("Bad protocol string signature header %x ",
+				*(unsigned int *) smb->Protocol));
+		if (mid != smb->Mid)
+			cERROR(1, ("Mids do not match"));
+	}
+	cERROR(1, ("bad smb detected. The Mid=%d", smb->Mid));
+	return 1;
+}
+
+int
+checkSMB(struct smb_hdr *smb, __u16 mid, int length)
+{
+	__u32 len = be32_to_cpu(smb->smb_buf_length);
+	cFYI(0,
+	     ("Entering checkSMB with Length: %x, smb_buf_length: %x ",
+	      length, len));
+	if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) ||
+	    (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) {
+		if ((unsigned int)length < 2 + sizeof (struct smb_hdr)) {
+			if (((unsigned int)length >= 
+				sizeof (struct smb_hdr) - 1)
+			    && (smb->Status.CifsError != 0)) {
+				smb->WordCount = 0;
+				return 0;	/* some error cases do not return wct and bcc */
+			} else {
+				cERROR(1, ("Length less than smb header size"));
+			}
+
+		}
+		if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)
+			cERROR(1,
+			       ("smb_buf_length greater than MaxBufSize"));
+		cERROR(1,
+		       ("bad smb detected. Illegal length. The mid=%d",
+			smb->Mid));
+		return 1;
+	}
+
+	if (checkSMBhdr(smb, mid))
+		return 1;
+
+	if ((4 + len != smbCalcSize(smb))
+	    || (4 + len != (unsigned int)length)) {
+		return 0;
+	} else {
+		cERROR(1, ("smbCalcSize %x ", smbCalcSize(smb)));
+		cERROR(1,
+		       ("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 list_head *tmp1;
+	struct cifsTconInfo *tcon;
+	struct cifsFileInfo *netfile;
+
+	cFYI(1,("Checking for oplock break or dnotify response"));
+	if((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) &&
+	   (pSMB->hdr.Flags & SMBFLG_RESPONSE)) {
+		struct smb_com_transaction_change_notify_rsp * pSMBr =
+			(struct smb_com_transaction_change_notify_rsp *)buf;
+		struct file_notify_information * pnotify;
+		__u32 data_offset = 0;
+		if(pSMBr->ByteCount > sizeof(struct file_notify_information)) {
+			data_offset = le32_to_cpu(pSMBr->DataOffset);
+
+			pnotify = (struct file_notify_information *)((char *)&pSMBr->hdr.Protocol
+				+ data_offset);
+			cFYI(1,("dnotify on %s with action: 0x%x",pnotify->FileName,
+				pnotify->Action));  /* BB removeme BB */
+	             /*   cifs_dump_mem("Received notify Data is: ",buf,sizeof(struct smb_hdr)+60); */
+			return TRUE;
+		}
+		if(pSMBr->hdr.Status.CifsError) {
+			cFYI(1,("notify err 0x%d",pSMBr->hdr.Status.CifsError));
+			return TRUE;
+		}
+		return FALSE;
+	}  
+	if(pSMB->hdr.Command != SMB_COM_LOCKING_ANDX)
+		return FALSE;
+	if(pSMB->hdr.Flags & SMBFLG_RESPONSE) {
+		/* no sense logging error on invalid handle on oplock
+		   break - harmless race between close request and oplock
+		   break response is expected from time to time writing out
+		   large dirty files cached on the client */
+		if ((NT_STATUS_INVALID_HANDLE) == 
+		   le32_to_cpu(pSMB->hdr.Status.CifsError)) { 
+			cFYI(1,("invalid handle on oplock break"));
+			return TRUE;
+		} else if (ERRbadfid == 
+		   le16_to_cpu(pSMB->hdr.Status.DosError.Error)) {
+			return TRUE;	  
+		} else {
+			return FALSE; /* on valid oplock brk we get "request" */
+		}
+	}
+	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) {
+#ifdef CONFIG_CIFS_STATS
+			atomic_inc(&tcon->num_oplock_brks);
+#endif
+			list_for_each(tmp1,&tcon->openFileList){
+				netfile = list_entry(tmp1,struct cifsFileInfo,tlist);
+				if(pSMB->Fid == netfile->netfid) {
+					struct cifsInodeInfo *pCifsInode;
+					read_unlock(&GlobalSMBSeslock);
+					cFYI(1,("Matching file id, processing oplock break"));
+					pCifsInode = 
+						CIFS_I(netfile->pInode);
+					pCifsInode->clientCanCacheAll = FALSE;
+					if(pSMB->OplockLevel == 0)
+						pCifsInode->clientCanCacheRead = FALSE;
+					pCifsInode->oplockPending = TRUE;
+					AllocOplockQEntry(netfile->pInode, netfile->netfid, tcon);
+					cFYI(1,("about to wake up oplock thd"));
+					wake_up_process(oplockThread);               
+					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
+dump_smb(struct smb_hdr *smb_buf, int smb_buf_length)
+{
+	int i, j;
+	char debug_line[17];
+	unsigned char *buffer;
+
+	if (traceSMB == 0)
+		return;
+
+	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(KERN_DEBUG "| ");
+			j = 0;
+		}
+		printk("%0#4x ", buffer[i]);
+		debug_line[2 * j] = ' ';
+		if (isprint(buffer[i]))
+			debug_line[1 + (2 * j)] = buffer[i];
+		else
+			debug_line[1 + (2 * j)] = '_';
+
+		if (i % 8 == 7) {	/* we have reached end of line, time to print ascii */
+			debug_line[16] = 0;
+			printk(" | %s\n", debug_line);
+		}
+	}
+	for (; j < 8; j++) {
+		printk("     ");
+		debug_line[2 * j] = ' ';
+		debug_line[1 + (2 * j)] = ' ';
+	}
+	printk( " | %s\n", debug_line);
+	return;
+}
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
new file mode 100644
index 0000000..4e34c89
--- /dev/null
+++ b/fs/cifs/netmisc.c
@@ -0,0 +1,904 @@
+/*
+ *   fs/cifs/netmisc.c
+ *
+ *   Copyright (c) International Business Machines  Corp., 2002
+ *   Author(s): Steve French (sfrench@us.ibm.com)
+ * 
+ *   Error mapping routines from Samba libsmb/errormap.c
+ *   Copyright (C) Andrew Tridgell 2001
+ *
+ *
+ *   This program is free software;  you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or 
+ *   (at your option) any later version.
+ * 
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program;  if not, write to the Free Software 
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/net.h>
+#include <linux/string.h>
+#include <linux/in.h>
+#include <linux/ctype.h>
+#include <linux/fs.h>
+#include <asm/div64.h>
+#include <asm/byteorder.h>
+#include "cifsfs.h"
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "smberr.h"
+#include "cifs_debug.h"
+#include "nterr.h"
+
+struct smb_to_posix_error {
+	__u16 smb_err;
+	int posix_code;
+};
+
+static const struct smb_to_posix_error mapping_table_ERRDOS[] = {
+	{ERRbadfunc, -EINVAL},
+	{ERRbadfile, -ENOENT},
+	{ERRbadpath, -ENOTDIR},
+	{ERRnofids, -EMFILE},
+	{ERRnoaccess, -EACCES},
+	{ERRbadfid, -EBADF},
+	{ERRbadmcb, -EIO},
+	{ERRnomem, -ENOMEM},
+	{ERRbadmem, -EFAULT},
+	{ERRbadenv, -EFAULT},
+	{ERRbadformat, -EINVAL},
+	{ERRbadaccess, -EACCES},
+	{ERRbaddata, -EIO},
+	{ERRbaddrive, -ENXIO},
+	{ERRremcd, -EACCES},
+	{ERRdiffdevice, -EXDEV},
+	{ERRnofiles, -ENOENT},
+	{ERRbadshare, -ETXTBSY},
+	{ERRlock, -EACCES},
+	{ERRunsup, -EINVAL},
+	{ERRnosuchshare,-ENXIO},
+	{ERRfilexists, -EEXIST},
+	{ERRinvparm, -EINVAL},
+	{ERRdiskfull, -ENOSPC},
+	{ERRinvname, -ENOENT},
+	{ERRinvlevel,-EOPNOTSUPP},
+	{ERRdirnotempty, -ENOTEMPTY},
+	{ERRnotlocked, -ENOLCK},
+	{ERRalreadyexists, -EEXIST},
+	{ERRmoredata, -EOVERFLOW},
+	{ERReasnotsupported,-EOPNOTSUPP},
+	{ErrQuota, -EDQUOT},
+	{ErrNotALink, -ENOLINK},
+	{ERRnetlogonNotStarted,-ENOPROTOOPT},
+	{0, 0}
+};
+
+static const struct smb_to_posix_error mapping_table_ERRSRV[] = {
+	{ERRerror, -EIO},
+	{ERRbadpw, -EPERM},
+	{ERRbadtype, -EREMOTE},
+	{ERRaccess, -EACCES},
+	{ERRinvtid, -ENXIO},
+	{ERRinvnetname, -ENODEV},
+	{ERRinvdevice, -ENXIO},
+	{ERRqfull, -ENOSPC},
+	{ERRqtoobig, -ENOSPC},
+	{ERRqeof, -EIO},
+	{ERRinvpfid, -EBADF},
+	{ERRsmbcmd, -EBADRQC},
+	{ERRsrverror, -EIO},
+	{ERRbadBID, -EIO},
+	{ERRfilespecs, -EINVAL},
+	{ERRbadLink, -EIO},
+	{ERRbadpermits, -EINVAL},
+	{ERRbadPID, -ESRCH},
+	{ERRsetattrmode, -EINVAL},
+	{ERRpaused, -EHOSTDOWN},
+	{ERRmsgoff, -EHOSTDOWN},
+	{ERRnoroom, -ENOSPC},
+	{ERRrmuns, -EUSERS},
+	{ERRtimeout, -ETIME},
+	{ERRnoresource, -ENOBUFS},
+	{ERRtoomanyuids, -EUSERS},
+	{ERRbaduid, -EACCES},
+	{ERRusempx, -EIO},
+	{ERRusestd, -EIO},
+	{ERR_NOTIFY_ENUM_DIR, -ENOBUFS},
+	{ERRaccountexpired, -EACCES},
+	{ERRbadclient, -EACCES},
+	{ERRbadLogonTime, -EACCES},
+	{ERRpasswordExpired, -EACCES},
+	{ERRnosupport, -EINVAL},
+	{0, 0}
+};
+
+static const struct smb_to_posix_error mapping_table_ERRHRD[] = {
+	{0, 0}
+};
+
+/* Convert string containing dotted ip address to binary form */
+/* returns 0 if invalid address */
+
+/* BB add address family, change rc to status flag and return union or for ipv6 */
+/*  will need parent to call something like inet_pton to convert ipv6 address  BB */
+int
+cifs_inet_pton(int address_family, char *cp,void *dst)
+{
+	struct in_addr address;
+	int value;
+	int digit;
+	int i;
+	char temp;
+	char bytes[4];
+	char *end = bytes;
+	static const int addr_class_max[4] =
+	    { 0xffffffff, 0xffffff, 0xffff, 0xff };
+
+	if(address_family != AF_INET)
+		return -EAFNOSUPPORT;
+
+	for (i = 0; i < 4; i++) {
+		bytes[i] = 0;
+	}
+
+	temp = *cp;
+
+	while (TRUE) {
+		if (!isdigit(temp))
+			return 0;
+
+		value = 0;
+		digit = 0;
+		for (;;) {
+			if (isascii(temp) && isdigit(temp)) {
+				value = (value * 10) + temp - '0';
+				temp = *++cp;
+				digit = 1;
+			} else
+				break;
+		}
+
+		if (temp == '.') {
+			if ((end > bytes + 2) || (value > 255))
+				return 0;
+			*end++ = value;
+			temp = *++cp;
+		} else if (temp == ':') {
+			cFYI(1,("IPv6 addresses not supported for CIFS mounts yet"));
+			return -1;
+		} else
+			break;
+	}
+
+	/* check for last characters */
+	if (temp != '\0' && (!isascii(temp) || !isspace(temp)))
+		if (temp != '\\') {
+			if (temp != '/')
+				return 0;
+			else
+				(*cp = '\\');	/* switch the slash the expected way */
+		}
+	if (value > addr_class_max[end - bytes])
+		return 0;
+
+	address.s_addr = *((__be32 *) bytes) | htonl(value);
+	*((__be32 *)dst) = address.s_addr;
+	return 1; /* success */
+}
+
+/*****************************************************************************
+convert a NT status code to a dos class/code
+ *****************************************************************************/
+/* NT status -> dos error map */
+static const struct {
+	__u8 dos_class;
+	__u16 dos_code;
+	__u32 ntstatus;
+} ntstatus_to_dos_map[] = {
+	{
+	ERRDOS, ERRgeneral, NT_STATUS_UNSUCCESSFUL}, {
+	ERRDOS, ERRbadfunc, NT_STATUS_NOT_IMPLEMENTED}, {
+	ERRDOS, 87, NT_STATUS_INVALID_INFO_CLASS}, {
+	ERRDOS, 24, NT_STATUS_INFO_LENGTH_MISMATCH}, {
+	ERRHRD, ERRgeneral, NT_STATUS_ACCESS_VIOLATION}, {
+	ERRHRD, ERRgeneral, NT_STATUS_IN_PAGE_ERROR}, {
+	ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_QUOTA}, {
+	ERRDOS, ERRbadfid, NT_STATUS_INVALID_HANDLE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_BAD_INITIAL_STACK}, {
+	ERRDOS, 193, NT_STATUS_BAD_INITIAL_PC}, {
+	ERRDOS, 87, NT_STATUS_INVALID_CID}, {
+	ERRHRD, ERRgeneral, NT_STATUS_TIMER_NOT_CANCELED}, {
+	ERRDOS, 87, NT_STATUS_INVALID_PARAMETER}, {
+	ERRDOS, ERRbadfile, NT_STATUS_NO_SUCH_DEVICE}, {
+	ERRDOS, ERRbadfile, NT_STATUS_NO_SUCH_FILE}, {
+	ERRDOS, ERRbadfunc, NT_STATUS_INVALID_DEVICE_REQUEST}, {
+	ERRDOS, 38, NT_STATUS_END_OF_FILE}, {
+	ERRDOS, 34, NT_STATUS_WRONG_VOLUME}, {
+	ERRDOS, 21, NT_STATUS_NO_MEDIA_IN_DEVICE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_UNRECOGNIZED_MEDIA}, {
+	ERRDOS, 27, NT_STATUS_NONEXISTENT_SECTOR},
+/*	{ This NT error code was 'sqashed'
+	 from NT_STATUS_MORE_PROCESSING_REQUIRED to NT_STATUS_OK 
+	 during the session setup } */
+	{
+	ERRDOS, ERRnomem, NT_STATUS_NO_MEMORY}, {
+	ERRDOS, 487, NT_STATUS_CONFLICTING_ADDRESSES}, {
+	ERRDOS, 487, NT_STATUS_NOT_MAPPED_VIEW}, {
+	ERRDOS, 87, NT_STATUS_UNABLE_TO_FREE_VM}, {
+	ERRDOS, 87, NT_STATUS_UNABLE_TO_DELETE_SECTION}, {
+	ERRDOS, 2142, NT_STATUS_INVALID_SYSTEM_SERVICE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_INSTRUCTION}, {
+	ERRDOS, ERRnoaccess, NT_STATUS_INVALID_LOCK_SEQUENCE}, {
+	ERRDOS, ERRnoaccess, NT_STATUS_INVALID_VIEW_SIZE}, {
+	ERRDOS, 193, NT_STATUS_INVALID_FILE_FOR_SECTION}, {
+	ERRDOS, ERRnoaccess, NT_STATUS_ALREADY_COMMITTED},
+/*	{ This NT error code was 'sqashed'
+	 from NT_STATUS_ACCESS_DENIED to NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE 
+	 during the session setup }   */
+	{
+	ERRDOS, ERRnoaccess, NT_STATUS_ACCESS_DENIED}, {
+	ERRDOS, 111, NT_STATUS_BUFFER_TOO_SMALL}, {
+	ERRDOS, ERRbadfid, NT_STATUS_OBJECT_TYPE_MISMATCH}, {
+	ERRHRD, ERRgeneral, NT_STATUS_NONCONTINUABLE_EXCEPTION}, {
+	ERRHRD, ERRgeneral, NT_STATUS_INVALID_DISPOSITION}, {
+	ERRHRD, ERRgeneral, NT_STATUS_UNWIND}, {
+	ERRHRD, ERRgeneral, NT_STATUS_BAD_STACK}, {
+	ERRHRD, ERRgeneral, NT_STATUS_INVALID_UNWIND_TARGET}, {
+	ERRDOS, 158, NT_STATUS_NOT_LOCKED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_PARITY_ERROR}, {
+	ERRDOS, 487, NT_STATUS_UNABLE_TO_DECOMMIT_VM}, {
+	ERRDOS, 487, NT_STATUS_NOT_COMMITTED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_INVALID_PORT_ATTRIBUTES}, {
+	ERRHRD, ERRgeneral, NT_STATUS_PORT_MESSAGE_TOO_LONG}, {
+	ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_MIX}, {
+	ERRHRD, ERRgeneral, NT_STATUS_INVALID_QUOTA_LOWER}, {
+	ERRHRD, ERRgeneral, NT_STATUS_DISK_CORRUPT_ERROR}, {
+	ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_INVALID}, {	/* mapping changed since shell does lookup on * and expects file not found */
+	ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_NOT_FOUND}, {
+	ERRDOS, ERRalreadyexists, NT_STATUS_OBJECT_NAME_COLLISION}, {
+	ERRHRD, ERRgeneral, NT_STATUS_HANDLE_NOT_WAITABLE}, {
+	ERRDOS, ERRbadfid, NT_STATUS_PORT_DISCONNECTED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_DEVICE_ALREADY_ATTACHED}, {
+	ERRDOS, 161, NT_STATUS_OBJECT_PATH_INVALID}, {
+	ERRDOS, ERRbadpath, NT_STATUS_OBJECT_PATH_NOT_FOUND}, {
+	ERRDOS, 161, NT_STATUS_OBJECT_PATH_SYNTAX_BAD}, {
+	ERRHRD, ERRgeneral, NT_STATUS_DATA_OVERRUN}, {
+	ERRHRD, ERRgeneral, NT_STATUS_DATA_LATE_ERROR}, {
+	ERRDOS, 23, NT_STATUS_DATA_ERROR}, {
+	ERRDOS, 23, NT_STATUS_CRC_ERROR}, {
+	ERRDOS, ERRnomem, NT_STATUS_SECTION_TOO_BIG}, {
+	ERRDOS, ERRnoaccess, NT_STATUS_PORT_CONNECTION_REFUSED}, {
+	ERRDOS, ERRbadfid, NT_STATUS_INVALID_PORT_HANDLE}, {
+	ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION}, {
+	ERRHRD, ERRgeneral, NT_STATUS_QUOTA_EXCEEDED}, {
+	ERRDOS, 87, NT_STATUS_INVALID_PAGE_PROTECTION}, {
+	ERRDOS, 288, NT_STATUS_MUTANT_NOT_OWNED}, {
+	ERRDOS, 298, NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED}, {
+	ERRDOS, 87, NT_STATUS_PORT_ALREADY_SET}, {
+	ERRDOS, 87, NT_STATUS_SECTION_NOT_IMAGE}, {
+	ERRDOS, 156, NT_STATUS_SUSPEND_COUNT_EXCEEDED}, {
+	ERRDOS, ERRnoaccess, NT_STATUS_THREAD_IS_TERMINATING}, {
+	ERRDOS, 87, NT_STATUS_BAD_WORKING_SET_LIMIT}, {
+	ERRDOS, 87, NT_STATUS_INCOMPATIBLE_FILE_MAP}, {
+	ERRDOS, 87, NT_STATUS_SECTION_PROTECTION}, {
+	ERRDOS, ERReasnotsupported, NT_STATUS_EAS_NOT_SUPPORTED}, {
+	ERRDOS, 255, NT_STATUS_EA_TOO_LARGE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_NONEXISTENT_EA_ENTRY}, {
+	ERRHRD, ERRgeneral, NT_STATUS_NO_EAS_ON_FILE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_EA_CORRUPT_ERROR}, {
+	ERRDOS, ERRlock, NT_STATUS_FILE_LOCK_CONFLICT}, {
+	ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED}, {
+	ERRDOS, ERRbadfile, NT_STATUS_DELETE_PENDING}, {
+	ERRDOS, ERRunsup, NT_STATUS_CTL_FILE_NOT_SUPPORTED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_UNKNOWN_REVISION}, {
+	ERRHRD, ERRgeneral, NT_STATUS_REVISION_MISMATCH}, {
+	ERRHRD, ERRgeneral, NT_STATUS_INVALID_OWNER}, {
+	ERRHRD, ERRgeneral, NT_STATUS_INVALID_PRIMARY_GROUP}, {
+	ERRHRD, ERRgeneral, NT_STATUS_NO_IMPERSONATION_TOKEN}, {
+	ERRHRD, ERRgeneral, NT_STATUS_CANT_DISABLE_MANDATORY}, {
+	ERRDOS, 2215, NT_STATUS_NO_LOGON_SERVERS}, {
+	ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_LOGON_SESSION}, {
+	ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_PRIVILEGE}, {
+	ERRDOS, ERRnoaccess, NT_STATUS_PRIVILEGE_NOT_HELD}, {
+	ERRHRD, ERRgeneral, NT_STATUS_INVALID_ACCOUNT_NAME}, {
+	ERRHRD, ERRgeneral, NT_STATUS_USER_EXISTS},
+/*	{ This NT error code was 'sqashed'
+	 from NT_STATUS_NO_SUCH_USER to NT_STATUS_LOGON_FAILURE 
+	 during the session setup } */
+	{
+	ERRDOS, ERRnoaccess, NT_STATUS_NO_SUCH_USER}, {
+	ERRHRD, ERRgeneral, NT_STATUS_GROUP_EXISTS}, {
+	ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_GROUP}, {
+	ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_GROUP}, {
+	ERRHRD, ERRgeneral, NT_STATUS_MEMBER_NOT_IN_GROUP}, {
+	ERRHRD, ERRgeneral, NT_STATUS_LAST_ADMIN},
+/*	{ This NT error code was 'sqashed'
+	 from NT_STATUS_WRONG_PASSWORD to NT_STATUS_LOGON_FAILURE 
+	 during the session setup } */
+	{
+	ERRSRV, ERRbadpw, NT_STATUS_WRONG_PASSWORD}, {
+	ERRHRD, ERRgeneral, NT_STATUS_ILL_FORMED_PASSWORD}, {
+	ERRHRD, ERRgeneral, NT_STATUS_PASSWORD_RESTRICTION}, {
+	ERRDOS, ERRnoaccess, NT_STATUS_LOGON_FAILURE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_ACCOUNT_RESTRICTION}, {
+	ERRSRV, 2241, NT_STATUS_INVALID_LOGON_HOURS}, {
+	ERRSRV, 2240, NT_STATUS_INVALID_WORKSTATION}, {
+	ERRSRV, 2242, NT_STATUS_PASSWORD_EXPIRED}, {
+	ERRSRV, 2239, NT_STATUS_ACCOUNT_DISABLED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_NONE_MAPPED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LUIDS_REQUESTED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_LUIDS_EXHAUSTED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_INVALID_SUB_AUTHORITY}, {
+	ERRHRD, ERRgeneral, NT_STATUS_INVALID_ACL}, {
+	ERRHRD, ERRgeneral, NT_STATUS_INVALID_SID}, {
+	ERRHRD, ERRgeneral, NT_STATUS_INVALID_SECURITY_DESCR}, {
+	ERRDOS, 127, NT_STATUS_PROCEDURE_NOT_FOUND}, {
+	ERRDOS, 193, NT_STATUS_INVALID_IMAGE_FORMAT}, {
+	ERRHRD, ERRgeneral, NT_STATUS_NO_TOKEN}, {
+	ERRHRD, ERRgeneral, NT_STATUS_BAD_INHERITANCE_ACL}, {
+	ERRDOS, 158, NT_STATUS_RANGE_NOT_LOCKED}, {
+	ERRDOS, 112, NT_STATUS_DISK_FULL}, {
+	ERRHRD, ERRgeneral, NT_STATUS_SERVER_DISABLED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_SERVER_NOT_DISABLED}, {
+	ERRDOS, 68, NT_STATUS_TOO_MANY_GUIDS_REQUESTED}, {
+	ERRDOS, 259, NT_STATUS_GUIDS_EXHAUSTED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_INVALID_ID_AUTHORITY}, {
+	ERRDOS, 259, NT_STATUS_AGENTS_EXHAUSTED}, {
+	ERRDOS, 154, NT_STATUS_INVALID_VOLUME_LABEL}, {
+	ERRDOS, 14, NT_STATUS_SECTION_NOT_EXTENDED}, {
+	ERRDOS, 487, NT_STATUS_NOT_MAPPED_DATA}, {
+	ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_DATA_NOT_FOUND}, {
+	ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_TYPE_NOT_FOUND}, {
+	ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_NAME_NOT_FOUND}, {
+	ERRHRD, ERRgeneral, NT_STATUS_ARRAY_BOUNDS_EXCEEDED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_FLOAT_DENORMAL_OPERAND}, {
+	ERRHRD, ERRgeneral, NT_STATUS_FLOAT_DIVIDE_BY_ZERO}, {
+	ERRHRD, ERRgeneral, NT_STATUS_FLOAT_INEXACT_RESULT}, {
+	ERRHRD, ERRgeneral, NT_STATUS_FLOAT_INVALID_OPERATION}, {
+	ERRHRD, ERRgeneral, NT_STATUS_FLOAT_OVERFLOW}, {
+	ERRHRD, ERRgeneral, NT_STATUS_FLOAT_STACK_CHECK}, {
+	ERRHRD, ERRgeneral, NT_STATUS_FLOAT_UNDERFLOW}, {
+	ERRHRD, ERRgeneral, NT_STATUS_INTEGER_DIVIDE_BY_ZERO}, {
+	ERRDOS, 534, NT_STATUS_INTEGER_OVERFLOW}, {
+	ERRHRD, ERRgeneral, NT_STATUS_PRIVILEGED_INSTRUCTION}, {
+	ERRDOS, ERRnomem, NT_STATUS_TOO_MANY_PAGING_FILES}, {
+	ERRHRD, ERRgeneral, NT_STATUS_FILE_INVALID}, {
+	ERRHRD, ERRgeneral, NT_STATUS_ALLOTTED_SPACE_EXCEEDED},
+/*	{ This NT error code was 'sqashed'
+	 from NT_STATUS_INSUFFICIENT_RESOURCES to NT_STATUS_INSUFF_SERVER_RESOURCES 
+	 during the session setup } */
+	{
+	ERRDOS, ERRnomem, NT_STATUS_INSUFFICIENT_RESOURCES}, {
+	ERRDOS, ERRbadpath, NT_STATUS_DFS_EXIT_PATH_FOUND}, {
+	ERRDOS, 23, NT_STATUS_DEVICE_DATA_ERROR}, {
+	ERRHRD, ERRgeneral, NT_STATUS_DEVICE_NOT_CONNECTED}, {
+	ERRDOS, 21, NT_STATUS_DEVICE_POWER_FAILURE}, {
+	ERRDOS, 487, NT_STATUS_FREE_VM_NOT_AT_BASE}, {
+	ERRDOS, 487, NT_STATUS_MEMORY_NOT_ALLOCATED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_WORKING_SET_QUOTA}, {
+	ERRDOS, 19, NT_STATUS_MEDIA_WRITE_PROTECTED}, {
+	ERRDOS, 21, NT_STATUS_DEVICE_NOT_READY}, {
+	ERRHRD, ERRgeneral, NT_STATUS_INVALID_GROUP_ATTRIBUTES}, {
+	ERRHRD, ERRgeneral, NT_STATUS_BAD_IMPERSONATION_LEVEL}, {
+	ERRHRD, ERRgeneral, NT_STATUS_CANT_OPEN_ANONYMOUS}, {
+	ERRHRD, ERRgeneral, NT_STATUS_BAD_VALIDATION_CLASS}, {
+	ERRHRD, ERRgeneral, NT_STATUS_BAD_TOKEN_TYPE}, {
+	ERRDOS, 87, NT_STATUS_BAD_MASTER_BOOT_RECORD}, {
+	ERRHRD, ERRgeneral, NT_STATUS_INSTRUCTION_MISALIGNMENT}, {
+	ERRDOS, ERRpipebusy, NT_STATUS_INSTANCE_NOT_AVAILABLE}, {
+	ERRDOS, ERRpipebusy, NT_STATUS_PIPE_NOT_AVAILABLE}, {
+	ERRDOS, ERRbadpipe, NT_STATUS_INVALID_PIPE_STATE}, {
+	ERRDOS, ERRpipebusy, NT_STATUS_PIPE_BUSY}, {
+	ERRDOS, ERRbadfunc, NT_STATUS_ILLEGAL_FUNCTION}, {
+	ERRDOS, ERRnotconnected, NT_STATUS_PIPE_DISCONNECTED}, {
+	ERRDOS, ERRpipeclosing, NT_STATUS_PIPE_CLOSING}, {
+	ERRHRD, ERRgeneral, NT_STATUS_PIPE_CONNECTED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_PIPE_LISTENING}, {
+	ERRDOS, ERRbadpipe, NT_STATUS_INVALID_READ_MODE}, {
+	ERRDOS, 121, NT_STATUS_IO_TIMEOUT}, {
+	ERRDOS, 38, NT_STATUS_FILE_FORCED_CLOSED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_PROFILING_NOT_STARTED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_PROFILING_NOT_STOPPED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_COULD_NOT_INTERPRET}, {
+	ERRDOS, ERRnoaccess, NT_STATUS_FILE_IS_A_DIRECTORY}, {
+	ERRDOS, ERRunsup, NT_STATUS_NOT_SUPPORTED}, {
+	ERRDOS, 51, NT_STATUS_REMOTE_NOT_LISTENING}, {
+	ERRDOS, 52, NT_STATUS_DUPLICATE_NAME}, {
+	ERRDOS, 53, NT_STATUS_BAD_NETWORK_PATH}, {
+	ERRDOS, 54, NT_STATUS_NETWORK_BUSY}, {
+	ERRDOS, 55, NT_STATUS_DEVICE_DOES_NOT_EXIST}, {
+	ERRDOS, 56, NT_STATUS_TOO_MANY_COMMANDS}, {
+	ERRDOS, 57, NT_STATUS_ADAPTER_HARDWARE_ERROR}, {
+	ERRDOS, 58, NT_STATUS_INVALID_NETWORK_RESPONSE}, {
+	ERRDOS, 59, NT_STATUS_UNEXPECTED_NETWORK_ERROR}, {
+	ERRDOS, 60, NT_STATUS_BAD_REMOTE_ADAPTER}, {
+	ERRDOS, 61, NT_STATUS_PRINT_QUEUE_FULL}, {
+	ERRDOS, 62, NT_STATUS_NO_SPOOL_SPACE}, {
+	ERRDOS, 63, NT_STATUS_PRINT_CANCELLED}, {
+	ERRDOS, 64, NT_STATUS_NETWORK_NAME_DELETED}, {
+	ERRDOS, 65, NT_STATUS_NETWORK_ACCESS_DENIED}, {
+	ERRDOS, 66, NT_STATUS_BAD_DEVICE_TYPE}, {
+	ERRDOS, ERRnosuchshare, NT_STATUS_BAD_NETWORK_NAME}, {
+	ERRDOS, 68, NT_STATUS_TOO_MANY_NAMES}, {
+	ERRDOS, 69, NT_STATUS_TOO_MANY_SESSIONS}, {
+	ERRDOS, 70, NT_STATUS_SHARING_PAUSED}, {
+	ERRDOS, 71, NT_STATUS_REQUEST_NOT_ACCEPTED}, {
+	ERRDOS, 72, NT_STATUS_REDIRECTOR_PAUSED}, {
+	ERRDOS, 88, NT_STATUS_NET_WRITE_FAULT}, {
+	ERRHRD, ERRgeneral, NT_STATUS_PROFILING_AT_LIMIT}, {
+	ERRDOS, ERRdiffdevice, NT_STATUS_NOT_SAME_DEVICE}, {
+	ERRDOS, ERRnoaccess, NT_STATUS_FILE_RENAMED}, {
+	ERRDOS, 240, NT_STATUS_VIRTUAL_CIRCUIT_CLOSED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_NO_SECURITY_ON_OBJECT}, {
+	ERRHRD, ERRgeneral, NT_STATUS_CANT_WAIT}, {
+	ERRDOS, ERRpipeclosing, NT_STATUS_PIPE_EMPTY}, {
+	ERRHRD, ERRgeneral, NT_STATUS_CANT_ACCESS_DOMAIN_INFO}, {
+	ERRHRD, ERRgeneral, NT_STATUS_CANT_TERMINATE_SELF}, {
+	ERRHRD, ERRgeneral, NT_STATUS_INVALID_SERVER_STATE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_INVALID_DOMAIN_STATE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_INVALID_DOMAIN_ROLE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_DOMAIN}, {
+	ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_EXISTS}, {
+	ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_LIMIT_EXCEEDED}, {
+	ERRDOS, 300, NT_STATUS_OPLOCK_NOT_GRANTED}, {
+	ERRDOS, 301, NT_STATUS_INVALID_OPLOCK_PROTOCOL}, {
+	ERRHRD, ERRgeneral, NT_STATUS_INTERNAL_DB_CORRUPTION}, {
+	ERRHRD, ERRgeneral, NT_STATUS_INTERNAL_ERROR}, {
+	ERRHRD, ERRgeneral, NT_STATUS_GENERIC_NOT_MAPPED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_BAD_DESCRIPTOR_FORMAT}, {
+	ERRHRD, ERRgeneral, NT_STATUS_INVALID_USER_BUFFER}, {
+	ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_IO_ERROR}, {
+	ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_MM_CREATE_ERR}, {
+	ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_MM_MAP_ERROR}, {
+	ERRHRD, ERRgeneral, NT_STATUS_UNEXPECTED_MM_EXTEND_ERR}, {
+	ERRHRD, ERRgeneral, NT_STATUS_NOT_LOGON_PROCESS}, {
+	ERRHRD, ERRgeneral, NT_STATUS_LOGON_SESSION_EXISTS}, {
+	ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_1}, {
+	ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_2}, {
+	ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_3}, {
+	ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_4}, {
+	ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_5}, {
+	ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_6}, {
+	ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_7}, {
+	ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_8}, {
+	ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_9}, {
+	ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_10}, {
+	ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_11}, {
+	ERRDOS, 87, NT_STATUS_INVALID_PARAMETER_12}, {
+	ERRDOS, ERRbadpath, NT_STATUS_REDIRECTOR_NOT_STARTED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_REDIRECTOR_STARTED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_STACK_OVERFLOW}, {
+	ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_PACKAGE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_BAD_FUNCTION_TABLE}, {
+	ERRDOS, 203, 0xc0000100}, {
+	ERRDOS, 145, NT_STATUS_DIRECTORY_NOT_EMPTY}, {
+	ERRHRD, ERRgeneral, NT_STATUS_FILE_CORRUPT_ERROR}, {
+	ERRDOS, 267, NT_STATUS_NOT_A_DIRECTORY}, {
+	ERRHRD, ERRgeneral, NT_STATUS_BAD_LOGON_SESSION_STATE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_LOGON_SESSION_COLLISION}, {
+	ERRDOS, 206, NT_STATUS_NAME_TOO_LONG}, {
+	ERRDOS, 2401, NT_STATUS_FILES_OPEN}, {
+	ERRDOS, 2404, NT_STATUS_CONNECTION_IN_USE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_MESSAGE_NOT_FOUND}, {
+	ERRDOS, ERRnoaccess, NT_STATUS_PROCESS_IS_TERMINATING}, {
+	ERRHRD, ERRgeneral, NT_STATUS_INVALID_LOGON_TYPE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_NO_GUID_TRANSLATION}, {
+	ERRHRD, ERRgeneral, NT_STATUS_CANNOT_IMPERSONATE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_IMAGE_ALREADY_LOADED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_ABIOS_NOT_PRESENT}, {
+	ERRHRD, ERRgeneral, NT_STATUS_ABIOS_LID_NOT_EXIST}, {
+	ERRHRD, ERRgeneral, NT_STATUS_ABIOS_LID_ALREADY_OWNED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_ABIOS_NOT_LID_OWNER}, {
+	ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_COMMAND}, {
+	ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_LID}, {
+	ERRHRD, ERRgeneral, NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_ABIOS_INVALID_SELECTOR}, {
+	ERRHRD, ERRgeneral, NT_STATUS_NO_LDT}, {
+	ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_SIZE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_OFFSET}, {
+	ERRHRD, ERRgeneral, NT_STATUS_INVALID_LDT_DESCRIPTOR}, {
+	ERRDOS, 193, NT_STATUS_INVALID_IMAGE_NE_FORMAT}, {
+	ERRHRD, ERRgeneral, NT_STATUS_RXACT_INVALID_STATE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_RXACT_COMMIT_FAILURE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_MAPPED_FILE_SIZE_ZERO}, {
+	ERRDOS, ERRnofids, NT_STATUS_TOO_MANY_OPENED_FILES}, {
+	ERRHRD, ERRgeneral, NT_STATUS_CANCELLED}, {
+	ERRDOS, ERRnoaccess, NT_STATUS_CANNOT_DELETE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_INVALID_COMPUTER_NAME}, {
+	ERRDOS, ERRnoaccess, NT_STATUS_FILE_DELETED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_SPECIAL_ACCOUNT}, {
+	ERRHRD, ERRgeneral, NT_STATUS_SPECIAL_GROUP}, {
+	ERRHRD, ERRgeneral, NT_STATUS_SPECIAL_USER}, {
+	ERRHRD, ERRgeneral, NT_STATUS_MEMBERS_PRIMARY_GROUP}, {
+	ERRDOS, ERRbadfid, NT_STATUS_FILE_CLOSED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_THREADS}, {
+	ERRHRD, ERRgeneral, NT_STATUS_THREAD_NOT_IN_PROCESS}, {
+	ERRHRD, ERRgeneral, NT_STATUS_TOKEN_ALREADY_IN_USE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_QUOTA_EXCEEDED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_COMMITMENT_LIMIT}, {
+	ERRDOS, 193, NT_STATUS_INVALID_IMAGE_LE_FORMAT}, {
+	ERRDOS, 193, NT_STATUS_INVALID_IMAGE_NOT_MZ}, {
+	ERRDOS, 193, NT_STATUS_INVALID_IMAGE_PROTECT}, {
+	ERRDOS, 193, NT_STATUS_INVALID_IMAGE_WIN_16}, {
+	ERRHRD, ERRgeneral, NT_STATUS_LOGON_SERVER_CONFLICT}, {
+	ERRHRD, ERRgeneral, NT_STATUS_TIME_DIFFERENCE_AT_DC}, {
+	ERRHRD, ERRgeneral, NT_STATUS_SYNCHRONIZATION_REQUIRED}, {
+	ERRDOS, 126, NT_STATUS_DLL_NOT_FOUND}, {
+	ERRHRD, ERRgeneral, NT_STATUS_OPEN_FAILED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_IO_PRIVILEGE_FAILED}, {
+	ERRDOS, 182, NT_STATUS_ORDINAL_NOT_FOUND}, {
+	ERRDOS, 127, NT_STATUS_ENTRYPOINT_NOT_FOUND}, {
+	ERRHRD, ERRgeneral, NT_STATUS_CONTROL_C_EXIT}, {
+	ERRDOS, 64, NT_STATUS_LOCAL_DISCONNECT}, {
+	ERRDOS, 64, NT_STATUS_REMOTE_DISCONNECT}, {
+	ERRDOS, 51, NT_STATUS_REMOTE_RESOURCES}, {
+	ERRDOS, 59, NT_STATUS_LINK_FAILED}, {
+	ERRDOS, 59, NT_STATUS_LINK_TIMEOUT}, {
+	ERRDOS, 59, NT_STATUS_INVALID_CONNECTION}, {
+	ERRDOS, 59, NT_STATUS_INVALID_ADDRESS}, {
+	ERRHRD, ERRgeneral, NT_STATUS_DLL_INIT_FAILED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_MISSING_SYSTEMFILE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_UNHANDLED_EXCEPTION}, {
+	ERRHRD, ERRgeneral, NT_STATUS_APP_INIT_FAILURE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_PAGEFILE_CREATE_FAILED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_NO_PAGEFILE}, {
+	ERRDOS, 124, NT_STATUS_INVALID_LEVEL}, {
+	ERRDOS, 86, NT_STATUS_WRONG_PASSWORD_CORE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_FLOAT_CONTEXT}, {
+	ERRDOS, 109, NT_STATUS_PIPE_BROKEN}, {
+	ERRHRD, ERRgeneral, NT_STATUS_REGISTRY_CORRUPT}, {
+	ERRHRD, ERRgeneral, NT_STATUS_REGISTRY_IO_FAILED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_NO_EVENT_PAIR}, {
+	ERRHRD, ERRgeneral, NT_STATUS_UNRECOGNIZED_VOLUME}, {
+	ERRHRD, ERRgeneral, NT_STATUS_SERIAL_NO_DEVICE_INITED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_ALIAS}, {
+	ERRHRD, ERRgeneral, NT_STATUS_MEMBER_NOT_IN_ALIAS}, {
+	ERRHRD, ERRgeneral, NT_STATUS_MEMBER_IN_ALIAS}, {
+	ERRHRD, ERRgeneral, NT_STATUS_ALIAS_EXISTS}, {
+	ERRHRD, ERRgeneral, NT_STATUS_LOGON_NOT_GRANTED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_SECRETS}, {
+	ERRHRD, ERRgeneral, NT_STATUS_SECRET_TOO_LONG}, {
+	ERRHRD, ERRgeneral, NT_STATUS_INTERNAL_DB_ERROR}, {
+	ERRHRD, ERRgeneral, NT_STATUS_FULLSCREEN_MODE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_CONTEXT_IDS}, {
+	ERRDOS, ERRnoaccess, NT_STATUS_LOGON_TYPE_NOT_GRANTED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_NOT_REGISTRY_FILE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR}, {
+	ERRHRD, ERRgeneral, NT_STATUS_FT_MISSING_MEMBER}, {
+	ERRHRD, ERRgeneral, NT_STATUS_ILL_FORMED_SERVICE_ENTRY}, {
+	ERRHRD, ERRgeneral, NT_STATUS_ILLEGAL_CHARACTER}, {
+	ERRHRD, ERRgeneral, NT_STATUS_UNMAPPABLE_CHARACTER}, {
+	ERRHRD, ERRgeneral, NT_STATUS_UNDEFINED_CHARACTER}, {
+	ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_VOLUME}, {
+	ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND}, {
+	ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_WRONG_CYLINDER}, {
+	ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_UNKNOWN_ERROR}, {
+	ERRHRD, ERRgeneral, NT_STATUS_FLOPPY_BAD_REGISTERS}, {
+	ERRHRD, ERRgeneral, NT_STATUS_DISK_RECALIBRATE_FAILED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_DISK_OPERATION_FAILED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_DISK_RESET_FAILED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_SHARED_IRQ_BUSY}, {
+	ERRHRD, ERRgeneral, NT_STATUS_FT_ORPHANING}, {
+	ERRHRD, ERRgeneral, 0xc000016e}, {
+	ERRHRD, ERRgeneral, 0xc000016f}, {
+	ERRHRD, ERRgeneral, 0xc0000170}, {
+	ERRHRD, ERRgeneral, 0xc0000171}, {
+	ERRHRD, ERRgeneral, NT_STATUS_PARTITION_FAILURE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_INVALID_BLOCK_LENGTH}, {
+	ERRHRD, ERRgeneral, NT_STATUS_DEVICE_NOT_PARTITIONED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_UNABLE_TO_LOCK_MEDIA}, {
+	ERRHRD, ERRgeneral, NT_STATUS_UNABLE_TO_UNLOAD_MEDIA}, {
+	ERRHRD, ERRgeneral, NT_STATUS_EOM_OVERFLOW}, {
+	ERRHRD, ERRgeneral, NT_STATUS_NO_MEDIA}, {
+	ERRHRD, ERRgeneral, 0xc0000179}, {
+	ERRHRD, ERRgeneral, NT_STATUS_NO_SUCH_MEMBER}, {
+	ERRHRD, ERRgeneral, NT_STATUS_INVALID_MEMBER}, {
+	ERRHRD, ERRgeneral, NT_STATUS_KEY_DELETED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_NO_LOG_SPACE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_SIDS}, {
+	ERRHRD, ERRgeneral, NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_KEY_HAS_CHILDREN}, {
+	ERRHRD, ERRgeneral, NT_STATUS_CHILD_MUST_BE_VOLATILE}, {
+	ERRDOS, 87, NT_STATUS_DEVICE_CONFIGURATION_ERROR}, {
+	ERRHRD, ERRgeneral, NT_STATUS_DRIVER_INTERNAL_ERROR}, {
+	ERRDOS, 22, NT_STATUS_INVALID_DEVICE_STATE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_IO_DEVICE_ERROR}, {
+	ERRHRD, ERRgeneral, NT_STATUS_DEVICE_PROTOCOL_ERROR}, {
+	ERRHRD, ERRgeneral, NT_STATUS_BACKUP_CONTROLLER}, {
+	ERRHRD, ERRgeneral, NT_STATUS_LOG_FILE_FULL}, {
+	ERRDOS, 19, NT_STATUS_TOO_LATE}, {
+	ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_LSA_SECRET},
+/*	{ This NT error code was 'sqashed'
+	 from NT_STATUS_NO_TRUST_SAM_ACCOUNT to NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE 
+	 during the session setup } */
+	{
+	ERRDOS, ERRnoaccess, NT_STATUS_NO_TRUST_SAM_ACCOUNT}, {
+	ERRDOS, ERRnoaccess, NT_STATUS_TRUSTED_DOMAIN_FAILURE}, {
+	ERRDOS, ERRnoaccess, NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_FILE_CORRUPT}, {
+	ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_CANT_START}, {
+	ERRDOS, ERRnoaccess, NT_STATUS_TRUST_FAILURE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_MUTANT_LIMIT_EXCEEDED}, {
+	ERRDOS, ERRnetlogonNotStarted, NT_STATUS_NETLOGON_NOT_STARTED}, {
+	ERRSRV, 2239, NT_STATUS_ACCOUNT_EXPIRED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_POSSIBLE_DEADLOCK}, {
+	ERRHRD, ERRgeneral, NT_STATUS_NETWORK_CREDENTIAL_CONFLICT}, {
+	ERRHRD, ERRgeneral, NT_STATUS_REMOTE_SESSION_LIMIT}, {
+	ERRHRD, ERRgeneral, NT_STATUS_EVENTLOG_FILE_CHANGED}, {
+	ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT}, {
+	ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT}, {
+	ERRDOS, ERRnoaccess, NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT},
+/*	{ This NT error code was 'sqashed'
+	 from NT_STATUS_DOMAIN_TRUST_INCONSISTENT to NT_STATUS_LOGON_FAILURE 
+	 during the session setup }  */
+	{
+	ERRDOS, ERRnoaccess, NT_STATUS_DOMAIN_TRUST_INCONSISTENT}, {
+	ERRHRD, ERRgeneral, NT_STATUS_FS_DRIVER_REQUIRED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_NO_USER_SESSION_KEY}, {
+	ERRDOS, 59, NT_STATUS_USER_SESSION_DELETED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_RESOURCE_LANG_NOT_FOUND}, {
+	ERRDOS, ERRnomem, NT_STATUS_INSUFF_SERVER_RESOURCES}, {
+	ERRHRD, ERRgeneral, NT_STATUS_INVALID_BUFFER_SIZE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_INVALID_ADDRESS_COMPONENT}, {
+	ERRHRD, ERRgeneral, NT_STATUS_INVALID_ADDRESS_WILDCARD}, {
+	ERRDOS, 68, NT_STATUS_TOO_MANY_ADDRESSES}, {
+	ERRDOS, 52, NT_STATUS_ADDRESS_ALREADY_EXISTS}, {
+	ERRDOS, 64, NT_STATUS_ADDRESS_CLOSED}, {
+	ERRDOS, 64, NT_STATUS_CONNECTION_DISCONNECTED}, {
+	ERRDOS, 64, NT_STATUS_CONNECTION_RESET}, {
+	ERRDOS, 68, NT_STATUS_TOO_MANY_NODES}, {
+	ERRDOS, 59, NT_STATUS_TRANSACTION_ABORTED}, {
+	ERRDOS, 59, NT_STATUS_TRANSACTION_TIMED_OUT}, {
+	ERRDOS, 59, NT_STATUS_TRANSACTION_NO_RELEASE}, {
+	ERRDOS, 59, NT_STATUS_TRANSACTION_NO_MATCH}, {
+	ERRDOS, 59, NT_STATUS_TRANSACTION_RESPONDED}, {
+	ERRDOS, 59, NT_STATUS_TRANSACTION_INVALID_ID}, {
+	ERRDOS, 59, NT_STATUS_TRANSACTION_INVALID_TYPE}, {
+	ERRDOS, ERRunsup, NT_STATUS_NOT_SERVER_SESSION}, {
+	ERRDOS, ERRunsup, NT_STATUS_NOT_CLIENT_SESSION}, {
+	ERRHRD, ERRgeneral, NT_STATUS_CANNOT_LOAD_REGISTRY_FILE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_DEBUG_ATTACH_FAILED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_SYSTEM_PROCESS_TERMINATED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_DATA_NOT_ACCEPTED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_NO_BROWSER_SERVERS_FOUND}, {
+	ERRHRD, ERRgeneral, NT_STATUS_VDM_HARD_ERROR}, {
+	ERRHRD, ERRgeneral, NT_STATUS_DRIVER_CANCEL_TIMEOUT}, {
+	ERRHRD, ERRgeneral, NT_STATUS_REPLY_MESSAGE_MISMATCH}, {
+	ERRHRD, ERRgeneral, NT_STATUS_MAPPED_ALIGNMENT}, {
+	ERRDOS, 193, NT_STATUS_IMAGE_CHECKSUM_MISMATCH}, {
+	ERRHRD, ERRgeneral, NT_STATUS_LOST_WRITEBEHIND_DATA}, {
+	ERRHRD, ERRgeneral, NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID}, {
+	ERRSRV, 2242, NT_STATUS_PASSWORD_MUST_CHANGE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_NOT_FOUND}, {
+	ERRHRD, ERRgeneral, NT_STATUS_NOT_TINY_STREAM}, {
+	ERRHRD, ERRgeneral, NT_STATUS_RECOVERY_FAILURE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_STACK_OVERFLOW_READ}, {
+	ERRHRD, ERRgeneral, NT_STATUS_FAIL_CHECK}, {
+	ERRHRD, ERRgeneral, NT_STATUS_DUPLICATE_OBJECTID}, {
+	ERRHRD, ERRgeneral, NT_STATUS_OBJECTID_EXISTS}, {
+	ERRHRD, ERRgeneral, NT_STATUS_CONVERT_TO_LARGE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_RETRY}, {
+	ERRHRD, ERRgeneral, NT_STATUS_FOUND_OUT_OF_SCOPE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_ALLOCATE_BUCKET}, {
+	ERRHRD, ERRgeneral, NT_STATUS_PROPSET_NOT_FOUND}, {
+	ERRHRD, ERRgeneral, NT_STATUS_MARSHALL_OVERFLOW}, {
+	ERRHRD, ERRgeneral, NT_STATUS_INVALID_VARIANT}, {
+	ERRHRD, ERRgeneral, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND}, {
+	ERRDOS, ERRnoaccess, NT_STATUS_ACCOUNT_LOCKED_OUT}, {
+	ERRDOS, ERRbadfid, NT_STATUS_HANDLE_NOT_CLOSABLE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_REFUSED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_GRACEFUL_DISCONNECT}, {
+	ERRHRD, ERRgeneral, NT_STATUS_ADDRESS_ALREADY_ASSOCIATED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_ADDRESS_NOT_ASSOCIATED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_INVALID}, {
+	ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_ACTIVE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_NETWORK_UNREACHABLE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_HOST_UNREACHABLE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_PROTOCOL_UNREACHABLE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_PORT_UNREACHABLE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_REQUEST_ABORTED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_ABORTED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_BAD_COMPRESSION_BUFFER}, {
+	ERRHRD, ERRgeneral, NT_STATUS_USER_MAPPED_FILE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_AUDIT_FAILED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_TIMER_RESOLUTION_NOT_SET}, {
+	ERRHRD, ERRgeneral, NT_STATUS_CONNECTION_COUNT_LIMIT}, {
+	ERRHRD, ERRgeneral, NT_STATUS_LOGIN_TIME_RESTRICTION}, {
+	ERRHRD, ERRgeneral, NT_STATUS_LOGIN_WKSTA_RESTRICTION}, {
+	ERRDOS, 193, NT_STATUS_IMAGE_MP_UP_MISMATCH}, {
+	ERRHRD, ERRgeneral, 0xc000024a}, {
+	ERRHRD, ERRgeneral, 0xc000024b}, {
+	ERRHRD, ERRgeneral, 0xc000024c}, {
+	ERRHRD, ERRgeneral, 0xc000024d}, {
+	ERRHRD, ERRgeneral, 0xc000024e}, {
+	ERRHRD, ERRgeneral, 0xc000024f}, {
+	ERRHRD, ERRgeneral, NT_STATUS_INSUFFICIENT_LOGON_INFO}, {
+	ERRHRD, ERRgeneral, NT_STATUS_BAD_DLL_ENTRYPOINT}, {
+	ERRHRD, ERRgeneral, NT_STATUS_BAD_SERVICE_ENTRYPOINT}, {
+	ERRHRD, ERRgeneral, NT_STATUS_LPC_REPLY_LOST}, {
+	ERRHRD, ERRgeneral, NT_STATUS_IP_ADDRESS_CONFLICT1}, {
+	ERRHRD, ERRgeneral, NT_STATUS_IP_ADDRESS_CONFLICT2}, {
+	ERRHRD, ERRgeneral, NT_STATUS_REGISTRY_QUOTA_LIMIT}, {
+	ERRSRV, 3, NT_STATUS_PATH_NOT_COVERED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_NO_CALLBACK_ACTIVE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_LICENSE_QUOTA_EXCEEDED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_PWD_TOO_SHORT}, {
+	ERRHRD, ERRgeneral, NT_STATUS_PWD_TOO_RECENT}, {
+	ERRHRD, ERRgeneral, NT_STATUS_PWD_HISTORY_CONFLICT}, {
+	ERRHRD, ERRgeneral, 0xc000025d}, {
+	ERRHRD, ERRgeneral, NT_STATUS_PLUGPLAY_NO_DEVICE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_UNSUPPORTED_COMPRESSION}, {
+	ERRHRD, ERRgeneral, NT_STATUS_INVALID_HW_PROFILE}, {
+	ERRHRD, ERRgeneral, NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH}, {
+	ERRDOS, 182, NT_STATUS_DRIVER_ORDINAL_NOT_FOUND}, {
+	ERRDOS, 127, NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND}, {
+	ERRDOS, 288, NT_STATUS_RESOURCE_NOT_OWNED}, {
+	ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LINKS}, {
+	ERRHRD, ERRgeneral, NT_STATUS_QUOTA_LIST_INCONSISTENT}, {
+	ERRHRD, ERRgeneral, NT_STATUS_FILE_IS_OFFLINE}, {
+	ERRDOS, 21, 0xc000026e}, {
+	ERRDOS, 161, 0xc0000281}, {
+	ERRDOS, ERRnoaccess, 0xc000028a}, {
+	ERRDOS, ERRnoaccess, 0xc000028b}, {
+	ERRHRD, ERRgeneral, 0xc000028c}, {
+	ERRDOS, ERRnoaccess, 0xc000028d}, {
+	ERRDOS, ERRnoaccess, 0xc000028e}, {
+	ERRDOS, ERRnoaccess, 0xc000028f}, {
+	ERRDOS, ERRnoaccess, 0xc0000290}, {
+	ERRDOS, ERRbadfunc, 0xc000029c}, {
+	ERRDOS, ERRinvlevel, 0x007c0001}, };
+
+/*****************************************************************************
+ Print an error message from the status code
+ *****************************************************************************/
+static void
+cifs_print_status(__u32 status_code)
+{
+	int idx = 0;
+
+	while (nt_errs[idx].nt_errstr != NULL) {
+		if (((nt_errs[idx].nt_errcode) & 0xFFFFFF) ==
+		    (status_code & 0xFFFFFF)) {
+			printk(KERN_NOTICE "Status code returned 0x%08x %s\n",
+				   status_code,nt_errs[idx].nt_errstr);
+		}
+		idx++;
+	}
+	return;
+}
+
+
+static void
+ntstatus_to_dos(__u32 ntstatus, __u8 * eclass, __u16 * ecode)
+{
+	int i;
+	if (ntstatus == 0) {
+		*eclass = 0;
+		*ecode = 0;
+		return;
+	}
+	for (i = 0; ntstatus_to_dos_map[i].ntstatus; i++) {
+		if (ntstatus == ntstatus_to_dos_map[i].ntstatus) {
+			*eclass = ntstatus_to_dos_map[i].dos_class;
+			*ecode = ntstatus_to_dos_map[i].dos_code;
+			return;
+		}
+	}
+	*eclass = ERRHRD;
+	*ecode = ERRgeneral;
+}
+
+int
+map_smb_to_linux_error(struct smb_hdr *smb)
+{
+	unsigned int i;
+	int rc = -EIO;		/* if transport error smb error may not be set */
+	__u8 smberrclass;
+	__u16 smberrcode;
+
+	/* BB if NT Status codes - map NT BB */
+
+	/* old style smb error codes */
+	if (smb->Status.CifsError == 0)
+		return 0;
+
+	if (smb->Flags2 & SMBFLG2_ERR_STATUS) {
+		/* translate the newer STATUS codes to old style errors and then to POSIX errors */
+		__u32 err = le32_to_cpu(smb->Status.CifsError);
+		if(cifsFYI)
+			cifs_print_status(err);
+		ntstatus_to_dos(err, &smberrclass, &smberrcode);
+	} else {
+		smberrclass = smb->Status.DosError.ErrorClass;
+		smberrcode = le16_to_cpu(smb->Status.DosError.Error);
+	}
+
+	/* old style errors */
+
+	/* DOS class smb error codes - map DOS */
+	if (smberrclass == ERRDOS) {	/* one byte field no need to byte reverse */
+		for (i = 0;
+		     i <
+		     sizeof (mapping_table_ERRDOS) /
+		     sizeof (struct smb_to_posix_error); i++) {
+			if (mapping_table_ERRDOS[i].smb_err == 0)
+				break;
+			else if (mapping_table_ERRDOS[i].smb_err == smberrcode) {
+				rc = mapping_table_ERRDOS[i].posix_code;
+				break;
+			}
+			/* else try the next error mapping one to see if it will match */
+		}
+	} else if (smberrclass == ERRSRV) {	/* server class of error codes */
+		for (i = 0;
+		     i <
+		     sizeof (mapping_table_ERRSRV) /
+		     sizeof (struct smb_to_posix_error); i++) {
+			if (mapping_table_ERRSRV[i].smb_err == 0)
+				break;
+			else if (mapping_table_ERRSRV[i].smb_err == smberrcode) {
+				rc = mapping_table_ERRSRV[i].posix_code;
+				break;
+			}
+			/* else try the next error mapping one to see if it will match */
+		}
+	}
+	/* else ERRHRD class errors or junk  - return EIO */
+
+	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 */
+
+	return rc;
+}
+
+/*
+ * calculate the size of the SMB message based on the fixed header
+ * portion, the number of word parameters and the data portion of the message
+ */
+unsigned int
+smbCalcSize(struct smb_hdr *ptr)
+{
+	return (sizeof (struct smb_hdr) + (2 * ptr->WordCount) +
+		BCC(ptr));
+}
+
+/* The following are taken from fs/ntfs/util.c */
+
+#define NTFS_TIME_OFFSET ((u64)(369*365 + 89) * 24 * 3600 * 10000000)
+
+    /*
+     * Convert the NT UTC (based 1601-01-01, in hundred nanosecond units)
+     * into Unix UTC (based 1970-01-01, in seconds).
+     */
+struct timespec
+cifs_NTtimeToUnix(u64 ntutc)
+{
+	struct timespec ts; 
+	/* BB what about the timezone? BB */
+
+	/* Subtract the NTFS time offset, then convert to 1s intervals. */
+	u64 t;
+
+	t = ntutc - NTFS_TIME_OFFSET;
+	ts.tv_nsec = do_div(t, 10000000) * 100;
+	ts.tv_sec = t; 
+	return ts;
+}
+
+/* Convert the Unix UTC into NT UTC. */
+u64
+cifs_UnixTimeToNT(struct timespec t)
+{
+	/* Convert to 100ns intervals and then add the NTFS time offset. */
+	return (u64) t.tv_sec * 10000000 + t.tv_nsec/100 + NTFS_TIME_OFFSET;
+}
diff --git a/fs/cifs/nterr.c b/fs/cifs/nterr.c
new file mode 100644
index 0000000..4da50cd
--- /dev/null
+++ b/fs/cifs/nterr.c
@@ -0,0 +1,687 @@
+/* 
+ *  Unix SMB/Netbios implementation.
+ *  Version 1.9.
+ *  RPC Pipe client / server routines
+ *  Copyright (C) Luke Kenneth Casson Leighton 1997-2001.
+ *  
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *  
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *  
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* NT error codes - see nterr.h */
+#include <linux/types.h>
+#include <linux/fs.h>
+#include "nterr.h"
+
+const struct nt_err_code_struct nt_errs[] = {
+	{"NT_STATUS_OK", NT_STATUS_OK},
+	{"NT_STATUS_UNSUCCESSFUL", NT_STATUS_UNSUCCESSFUL},
+	{"NT_STATUS_NOT_IMPLEMENTED", NT_STATUS_NOT_IMPLEMENTED},
+	{"NT_STATUS_INVALID_INFO_CLASS", NT_STATUS_INVALID_INFO_CLASS},
+	{"NT_STATUS_INFO_LENGTH_MISMATCH", NT_STATUS_INFO_LENGTH_MISMATCH},
+	{"NT_STATUS_ACCESS_VIOLATION", NT_STATUS_ACCESS_VIOLATION},
+	{"STATUS_BUFFER_OVERFLOW", STATUS_BUFFER_OVERFLOW},
+	{"NT_STATUS_IN_PAGE_ERROR", NT_STATUS_IN_PAGE_ERROR},
+	{"NT_STATUS_PAGEFILE_QUOTA", NT_STATUS_PAGEFILE_QUOTA},
+	{"NT_STATUS_INVALID_HANDLE", NT_STATUS_INVALID_HANDLE},
+	{"NT_STATUS_BAD_INITIAL_STACK", NT_STATUS_BAD_INITIAL_STACK},
+	{"NT_STATUS_BAD_INITIAL_PC", NT_STATUS_BAD_INITIAL_PC},
+	{"NT_STATUS_INVALID_CID", NT_STATUS_INVALID_CID},
+	{"NT_STATUS_TIMER_NOT_CANCELED", NT_STATUS_TIMER_NOT_CANCELED},
+	{"NT_STATUS_INVALID_PARAMETER", NT_STATUS_INVALID_PARAMETER},
+	{"NT_STATUS_NO_SUCH_DEVICE", NT_STATUS_NO_SUCH_DEVICE},
+	{"NT_STATUS_NO_SUCH_FILE", NT_STATUS_NO_SUCH_FILE},
+	{"NT_STATUS_INVALID_DEVICE_REQUEST",
+	 NT_STATUS_INVALID_DEVICE_REQUEST},
+	{"NT_STATUS_END_OF_FILE", NT_STATUS_END_OF_FILE},
+	{"NT_STATUS_WRONG_VOLUME", NT_STATUS_WRONG_VOLUME},
+	{"NT_STATUS_NO_MEDIA_IN_DEVICE", NT_STATUS_NO_MEDIA_IN_DEVICE},
+	{"NT_STATUS_UNRECOGNIZED_MEDIA", NT_STATUS_UNRECOGNIZED_MEDIA},
+	{"NT_STATUS_NONEXISTENT_SECTOR", NT_STATUS_NONEXISTENT_SECTOR},
+	{"NT_STATUS_MORE_PROCESSING_REQUIRED",
+	 NT_STATUS_MORE_PROCESSING_REQUIRED},
+	{"NT_STATUS_NO_MEMORY", NT_STATUS_NO_MEMORY},
+	{"NT_STATUS_CONFLICTING_ADDRESSES",
+	 NT_STATUS_CONFLICTING_ADDRESSES},
+	{"NT_STATUS_NOT_MAPPED_VIEW", NT_STATUS_NOT_MAPPED_VIEW},
+	{"NT_STATUS_UNABLE_TO_FREE_VM", NT_STATUS_UNABLE_TO_FREE_VM},
+	{"NT_STATUS_UNABLE_TO_DELETE_SECTION",
+	 NT_STATUS_UNABLE_TO_DELETE_SECTION},
+	{"NT_STATUS_INVALID_SYSTEM_SERVICE",
+	 NT_STATUS_INVALID_SYSTEM_SERVICE},
+	{"NT_STATUS_ILLEGAL_INSTRUCTION", NT_STATUS_ILLEGAL_INSTRUCTION},
+	{"NT_STATUS_INVALID_LOCK_SEQUENCE",
+	 NT_STATUS_INVALID_LOCK_SEQUENCE},
+	{"NT_STATUS_INVALID_VIEW_SIZE", NT_STATUS_INVALID_VIEW_SIZE},
+	{"NT_STATUS_INVALID_FILE_FOR_SECTION",
+	 NT_STATUS_INVALID_FILE_FOR_SECTION},
+	{"NT_STATUS_ALREADY_COMMITTED", NT_STATUS_ALREADY_COMMITTED},
+	{"NT_STATUS_ACCESS_DENIED", NT_STATUS_ACCESS_DENIED},
+	{"NT_STATUS_BUFFER_TOO_SMALL", NT_STATUS_BUFFER_TOO_SMALL},
+	{"NT_STATUS_OBJECT_TYPE_MISMATCH", NT_STATUS_OBJECT_TYPE_MISMATCH},
+	{"NT_STATUS_NONCONTINUABLE_EXCEPTION",
+	 NT_STATUS_NONCONTINUABLE_EXCEPTION},
+	{"NT_STATUS_INVALID_DISPOSITION", NT_STATUS_INVALID_DISPOSITION},
+	{"NT_STATUS_UNWIND", NT_STATUS_UNWIND},
+	{"NT_STATUS_BAD_STACK", NT_STATUS_BAD_STACK},
+	{"NT_STATUS_INVALID_UNWIND_TARGET",
+	 NT_STATUS_INVALID_UNWIND_TARGET},
+	{"NT_STATUS_NOT_LOCKED", NT_STATUS_NOT_LOCKED},
+	{"NT_STATUS_PARITY_ERROR", NT_STATUS_PARITY_ERROR},
+	{"NT_STATUS_UNABLE_TO_DECOMMIT_VM",
+	 NT_STATUS_UNABLE_TO_DECOMMIT_VM},
+	{"NT_STATUS_NOT_COMMITTED", NT_STATUS_NOT_COMMITTED},
+	{"NT_STATUS_INVALID_PORT_ATTRIBUTES",
+	 NT_STATUS_INVALID_PORT_ATTRIBUTES},
+	{"NT_STATUS_PORT_MESSAGE_TOO_LONG",
+	 NT_STATUS_PORT_MESSAGE_TOO_LONG},
+	{"NT_STATUS_INVALID_PARAMETER_MIX",
+	 NT_STATUS_INVALID_PARAMETER_MIX},
+	{"NT_STATUS_INVALID_QUOTA_LOWER", NT_STATUS_INVALID_QUOTA_LOWER},
+	{"NT_STATUS_DISK_CORRUPT_ERROR", NT_STATUS_DISK_CORRUPT_ERROR},
+	{"NT_STATUS_OBJECT_NAME_INVALID", NT_STATUS_OBJECT_NAME_INVALID},
+	{"NT_STATUS_OBJECT_NAME_NOT_FOUND",
+	 NT_STATUS_OBJECT_NAME_NOT_FOUND},
+	{"NT_STATUS_OBJECT_NAME_COLLISION",
+	 NT_STATUS_OBJECT_NAME_COLLISION},
+	{"NT_STATUS_HANDLE_NOT_WAITABLE", NT_STATUS_HANDLE_NOT_WAITABLE},
+	{"NT_STATUS_PORT_DISCONNECTED", NT_STATUS_PORT_DISCONNECTED},
+	{"NT_STATUS_DEVICE_ALREADY_ATTACHED",
+	 NT_STATUS_DEVICE_ALREADY_ATTACHED},
+	{"NT_STATUS_OBJECT_PATH_INVALID", NT_STATUS_OBJECT_PATH_INVALID},
+	{"NT_STATUS_OBJECT_PATH_NOT_FOUND",
+	 NT_STATUS_OBJECT_PATH_NOT_FOUND},
+	{"NT_STATUS_OBJECT_PATH_SYNTAX_BAD",
+	 NT_STATUS_OBJECT_PATH_SYNTAX_BAD},
+	{"NT_STATUS_DATA_OVERRUN", NT_STATUS_DATA_OVERRUN},
+	{"NT_STATUS_DATA_LATE_ERROR", NT_STATUS_DATA_LATE_ERROR},
+	{"NT_STATUS_DATA_ERROR", NT_STATUS_DATA_ERROR},
+	{"NT_STATUS_CRC_ERROR", NT_STATUS_CRC_ERROR},
+	{"NT_STATUS_SECTION_TOO_BIG", NT_STATUS_SECTION_TOO_BIG},
+	{"NT_STATUS_PORT_CONNECTION_REFUSED",
+	 NT_STATUS_PORT_CONNECTION_REFUSED},
+	{"NT_STATUS_INVALID_PORT_HANDLE", NT_STATUS_INVALID_PORT_HANDLE},
+	{"NT_STATUS_SHARING_VIOLATION", NT_STATUS_SHARING_VIOLATION},
+	{"NT_STATUS_QUOTA_EXCEEDED", NT_STATUS_QUOTA_EXCEEDED},
+	{"NT_STATUS_INVALID_PAGE_PROTECTION",
+	 NT_STATUS_INVALID_PAGE_PROTECTION},
+	{"NT_STATUS_MUTANT_NOT_OWNED", NT_STATUS_MUTANT_NOT_OWNED},
+	{"NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED",
+	 NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED},
+	{"NT_STATUS_PORT_ALREADY_SET", NT_STATUS_PORT_ALREADY_SET},
+	{"NT_STATUS_SECTION_NOT_IMAGE", NT_STATUS_SECTION_NOT_IMAGE},
+	{"NT_STATUS_SUSPEND_COUNT_EXCEEDED",
+	 NT_STATUS_SUSPEND_COUNT_EXCEEDED},
+	{"NT_STATUS_THREAD_IS_TERMINATING",
+	 NT_STATUS_THREAD_IS_TERMINATING},
+	{"NT_STATUS_BAD_WORKING_SET_LIMIT",
+	 NT_STATUS_BAD_WORKING_SET_LIMIT},
+	{"NT_STATUS_INCOMPATIBLE_FILE_MAP",
+	 NT_STATUS_INCOMPATIBLE_FILE_MAP},
+	{"NT_STATUS_SECTION_PROTECTION", NT_STATUS_SECTION_PROTECTION},
+	{"NT_STATUS_EAS_NOT_SUPPORTED", NT_STATUS_EAS_NOT_SUPPORTED},
+	{"NT_STATUS_EA_TOO_LARGE", NT_STATUS_EA_TOO_LARGE},
+	{"NT_STATUS_NONEXISTENT_EA_ENTRY", NT_STATUS_NONEXISTENT_EA_ENTRY},
+	{"NT_STATUS_NO_EAS_ON_FILE", NT_STATUS_NO_EAS_ON_FILE},
+	{"NT_STATUS_EA_CORRUPT_ERROR", NT_STATUS_EA_CORRUPT_ERROR},
+	{"NT_STATUS_FILE_LOCK_CONFLICT", NT_STATUS_FILE_LOCK_CONFLICT},
+	{"NT_STATUS_LOCK_NOT_GRANTED", NT_STATUS_LOCK_NOT_GRANTED},
+	{"NT_STATUS_DELETE_PENDING", NT_STATUS_DELETE_PENDING},
+	{"NT_STATUS_CTL_FILE_NOT_SUPPORTED",
+	 NT_STATUS_CTL_FILE_NOT_SUPPORTED},
+	{"NT_STATUS_UNKNOWN_REVISION", NT_STATUS_UNKNOWN_REVISION},
+	{"NT_STATUS_REVISION_MISMATCH", NT_STATUS_REVISION_MISMATCH},
+	{"NT_STATUS_INVALID_OWNER", NT_STATUS_INVALID_OWNER},
+	{"NT_STATUS_INVALID_PRIMARY_GROUP",
+	 NT_STATUS_INVALID_PRIMARY_GROUP},
+	{"NT_STATUS_NO_IMPERSONATION_TOKEN",
+	 NT_STATUS_NO_IMPERSONATION_TOKEN},
+	{"NT_STATUS_CANT_DISABLE_MANDATORY",
+	 NT_STATUS_CANT_DISABLE_MANDATORY},
+	{"NT_STATUS_NO_LOGON_SERVERS", NT_STATUS_NO_LOGON_SERVERS},
+	{"NT_STATUS_NO_SUCH_LOGON_SESSION",
+	 NT_STATUS_NO_SUCH_LOGON_SESSION},
+	{"NT_STATUS_NO_SUCH_PRIVILEGE", NT_STATUS_NO_SUCH_PRIVILEGE},
+	{"NT_STATUS_PRIVILEGE_NOT_HELD", NT_STATUS_PRIVILEGE_NOT_HELD},
+	{"NT_STATUS_INVALID_ACCOUNT_NAME", NT_STATUS_INVALID_ACCOUNT_NAME},
+	{"NT_STATUS_USER_EXISTS", NT_STATUS_USER_EXISTS},
+	{"NT_STATUS_NO_SUCH_USER", NT_STATUS_NO_SUCH_USER},
+	{"NT_STATUS_GROUP_EXISTS", NT_STATUS_GROUP_EXISTS},
+	{"NT_STATUS_NO_SUCH_GROUP", NT_STATUS_NO_SUCH_GROUP},
+	{"NT_STATUS_MEMBER_IN_GROUP", NT_STATUS_MEMBER_IN_GROUP},
+	{"NT_STATUS_MEMBER_NOT_IN_GROUP", NT_STATUS_MEMBER_NOT_IN_GROUP},
+	{"NT_STATUS_LAST_ADMIN", NT_STATUS_LAST_ADMIN},
+	{"NT_STATUS_WRONG_PASSWORD", NT_STATUS_WRONG_PASSWORD},
+	{"NT_STATUS_ILL_FORMED_PASSWORD", NT_STATUS_ILL_FORMED_PASSWORD},
+	{"NT_STATUS_PASSWORD_RESTRICTION", NT_STATUS_PASSWORD_RESTRICTION},
+	{"NT_STATUS_LOGON_FAILURE", NT_STATUS_LOGON_FAILURE},
+	{"NT_STATUS_ACCOUNT_RESTRICTION", NT_STATUS_ACCOUNT_RESTRICTION},
+	{"NT_STATUS_INVALID_LOGON_HOURS", NT_STATUS_INVALID_LOGON_HOURS},
+	{"NT_STATUS_INVALID_WORKSTATION", NT_STATUS_INVALID_WORKSTATION},
+	{"NT_STATUS_PASSWORD_EXPIRED", NT_STATUS_PASSWORD_EXPIRED},
+	{"NT_STATUS_ACCOUNT_DISABLED", NT_STATUS_ACCOUNT_DISABLED},
+	{"NT_STATUS_NONE_MAPPED", NT_STATUS_NONE_MAPPED},
+	{"NT_STATUS_TOO_MANY_LUIDS_REQUESTED",
+	 NT_STATUS_TOO_MANY_LUIDS_REQUESTED},
+	{"NT_STATUS_LUIDS_EXHAUSTED", NT_STATUS_LUIDS_EXHAUSTED},
+	{"NT_STATUS_INVALID_SUB_AUTHORITY",
+	 NT_STATUS_INVALID_SUB_AUTHORITY},
+	{"NT_STATUS_INVALID_ACL", NT_STATUS_INVALID_ACL},
+	{"NT_STATUS_INVALID_SID", NT_STATUS_INVALID_SID},
+	{"NT_STATUS_INVALID_SECURITY_DESCR",
+	 NT_STATUS_INVALID_SECURITY_DESCR},
+	{"NT_STATUS_PROCEDURE_NOT_FOUND", NT_STATUS_PROCEDURE_NOT_FOUND},
+	{"NT_STATUS_INVALID_IMAGE_FORMAT", NT_STATUS_INVALID_IMAGE_FORMAT},
+	{"NT_STATUS_NO_TOKEN", NT_STATUS_NO_TOKEN},
+	{"NT_STATUS_BAD_INHERITANCE_ACL", NT_STATUS_BAD_INHERITANCE_ACL},
+	{"NT_STATUS_RANGE_NOT_LOCKED", NT_STATUS_RANGE_NOT_LOCKED},
+	{"NT_STATUS_DISK_FULL", NT_STATUS_DISK_FULL},
+	{"NT_STATUS_SERVER_DISABLED", NT_STATUS_SERVER_DISABLED},
+	{"NT_STATUS_SERVER_NOT_DISABLED", NT_STATUS_SERVER_NOT_DISABLED},
+	{"NT_STATUS_TOO_MANY_GUIDS_REQUESTED",
+	 NT_STATUS_TOO_MANY_GUIDS_REQUESTED},
+	{"NT_STATUS_GUIDS_EXHAUSTED", NT_STATUS_GUIDS_EXHAUSTED},
+	{"NT_STATUS_INVALID_ID_AUTHORITY", NT_STATUS_INVALID_ID_AUTHORITY},
+	{"NT_STATUS_AGENTS_EXHAUSTED", NT_STATUS_AGENTS_EXHAUSTED},
+	{"NT_STATUS_INVALID_VOLUME_LABEL", NT_STATUS_INVALID_VOLUME_LABEL},
+	{"NT_STATUS_SECTION_NOT_EXTENDED", NT_STATUS_SECTION_NOT_EXTENDED},
+	{"NT_STATUS_NOT_MAPPED_DATA", NT_STATUS_NOT_MAPPED_DATA},
+	{"NT_STATUS_RESOURCE_DATA_NOT_FOUND",
+	 NT_STATUS_RESOURCE_DATA_NOT_FOUND},
+	{"NT_STATUS_RESOURCE_TYPE_NOT_FOUND",
+	 NT_STATUS_RESOURCE_TYPE_NOT_FOUND},
+	{"NT_STATUS_RESOURCE_NAME_NOT_FOUND",
+	 NT_STATUS_RESOURCE_NAME_NOT_FOUND},
+	{"NT_STATUS_ARRAY_BOUNDS_EXCEEDED",
+	 NT_STATUS_ARRAY_BOUNDS_EXCEEDED},
+	{"NT_STATUS_FLOAT_DENORMAL_OPERAND",
+	 NT_STATUS_FLOAT_DENORMAL_OPERAND},
+	{"NT_STATUS_FLOAT_DIVIDE_BY_ZERO", NT_STATUS_FLOAT_DIVIDE_BY_ZERO},
+	{"NT_STATUS_FLOAT_INEXACT_RESULT", NT_STATUS_FLOAT_INEXACT_RESULT},
+	{"NT_STATUS_FLOAT_INVALID_OPERATION",
+	 NT_STATUS_FLOAT_INVALID_OPERATION},
+	{"NT_STATUS_FLOAT_OVERFLOW", NT_STATUS_FLOAT_OVERFLOW},
+	{"NT_STATUS_FLOAT_STACK_CHECK", NT_STATUS_FLOAT_STACK_CHECK},
+	{"NT_STATUS_FLOAT_UNDERFLOW", NT_STATUS_FLOAT_UNDERFLOW},
+	{"NT_STATUS_INTEGER_DIVIDE_BY_ZERO",
+	 NT_STATUS_INTEGER_DIVIDE_BY_ZERO},
+	{"NT_STATUS_INTEGER_OVERFLOW", NT_STATUS_INTEGER_OVERFLOW},
+	{"NT_STATUS_PRIVILEGED_INSTRUCTION",
+	 NT_STATUS_PRIVILEGED_INSTRUCTION},
+	{"NT_STATUS_TOO_MANY_PAGING_FILES",
+	 NT_STATUS_TOO_MANY_PAGING_FILES},
+	{"NT_STATUS_FILE_INVALID", NT_STATUS_FILE_INVALID},
+	{"NT_STATUS_ALLOTTED_SPACE_EXCEEDED",
+	 NT_STATUS_ALLOTTED_SPACE_EXCEEDED},
+	{"NT_STATUS_INSUFFICIENT_RESOURCES",
+	 NT_STATUS_INSUFFICIENT_RESOURCES},
+	{"NT_STATUS_DFS_EXIT_PATH_FOUND", NT_STATUS_DFS_EXIT_PATH_FOUND},
+	{"NT_STATUS_DEVICE_DATA_ERROR", NT_STATUS_DEVICE_DATA_ERROR},
+	{"NT_STATUS_DEVICE_NOT_CONNECTED", NT_STATUS_DEVICE_NOT_CONNECTED},
+	{"NT_STATUS_DEVICE_POWER_FAILURE", NT_STATUS_DEVICE_POWER_FAILURE},
+	{"NT_STATUS_FREE_VM_NOT_AT_BASE", NT_STATUS_FREE_VM_NOT_AT_BASE},
+	{"NT_STATUS_MEMORY_NOT_ALLOCATED", NT_STATUS_MEMORY_NOT_ALLOCATED},
+	{"NT_STATUS_WORKING_SET_QUOTA", NT_STATUS_WORKING_SET_QUOTA},
+	{"NT_STATUS_MEDIA_WRITE_PROTECTED",
+	 NT_STATUS_MEDIA_WRITE_PROTECTED},
+	{"NT_STATUS_DEVICE_NOT_READY", NT_STATUS_DEVICE_NOT_READY},
+	{"NT_STATUS_INVALID_GROUP_ATTRIBUTES",
+	 NT_STATUS_INVALID_GROUP_ATTRIBUTES},
+	{"NT_STATUS_BAD_IMPERSONATION_LEVEL",
+	 NT_STATUS_BAD_IMPERSONATION_LEVEL},
+	{"NT_STATUS_CANT_OPEN_ANONYMOUS", NT_STATUS_CANT_OPEN_ANONYMOUS},
+	{"NT_STATUS_BAD_VALIDATION_CLASS", NT_STATUS_BAD_VALIDATION_CLASS},
+	{"NT_STATUS_BAD_TOKEN_TYPE", NT_STATUS_BAD_TOKEN_TYPE},
+	{"NT_STATUS_BAD_MASTER_BOOT_RECORD",
+	 NT_STATUS_BAD_MASTER_BOOT_RECORD},
+	{"NT_STATUS_INSTRUCTION_MISALIGNMENT",
+	 NT_STATUS_INSTRUCTION_MISALIGNMENT},
+	{"NT_STATUS_INSTANCE_NOT_AVAILABLE",
+	 NT_STATUS_INSTANCE_NOT_AVAILABLE},
+	{"NT_STATUS_PIPE_NOT_AVAILABLE", NT_STATUS_PIPE_NOT_AVAILABLE},
+	{"NT_STATUS_INVALID_PIPE_STATE", NT_STATUS_INVALID_PIPE_STATE},
+	{"NT_STATUS_PIPE_BUSY", NT_STATUS_PIPE_BUSY},
+	{"NT_STATUS_ILLEGAL_FUNCTION", NT_STATUS_ILLEGAL_FUNCTION},
+	{"NT_STATUS_PIPE_DISCONNECTED", NT_STATUS_PIPE_DISCONNECTED},
+	{"NT_STATUS_PIPE_CLOSING", NT_STATUS_PIPE_CLOSING},
+	{"NT_STATUS_PIPE_CONNECTED", NT_STATUS_PIPE_CONNECTED},
+	{"NT_STATUS_PIPE_LISTENING", NT_STATUS_PIPE_LISTENING},
+	{"NT_STATUS_INVALID_READ_MODE", NT_STATUS_INVALID_READ_MODE},
+	{"NT_STATUS_IO_TIMEOUT", NT_STATUS_IO_TIMEOUT},
+	{"NT_STATUS_FILE_FORCED_CLOSED", NT_STATUS_FILE_FORCED_CLOSED},
+	{"NT_STATUS_PROFILING_NOT_STARTED",
+	 NT_STATUS_PROFILING_NOT_STARTED},
+	{"NT_STATUS_PROFILING_NOT_STOPPED",
+	 NT_STATUS_PROFILING_NOT_STOPPED},
+	{"NT_STATUS_COULD_NOT_INTERPRET", NT_STATUS_COULD_NOT_INTERPRET},
+	{"NT_STATUS_FILE_IS_A_DIRECTORY", NT_STATUS_FILE_IS_A_DIRECTORY},
+	{"NT_STATUS_NOT_SUPPORTED", NT_STATUS_NOT_SUPPORTED},
+	{"NT_STATUS_REMOTE_NOT_LISTENING", NT_STATUS_REMOTE_NOT_LISTENING},
+	{"NT_STATUS_DUPLICATE_NAME", NT_STATUS_DUPLICATE_NAME},
+	{"NT_STATUS_BAD_NETWORK_PATH", NT_STATUS_BAD_NETWORK_PATH},
+	{"NT_STATUS_NETWORK_BUSY", NT_STATUS_NETWORK_BUSY},
+	{"NT_STATUS_DEVICE_DOES_NOT_EXIST",
+	 NT_STATUS_DEVICE_DOES_NOT_EXIST},
+	{"NT_STATUS_TOO_MANY_COMMANDS", NT_STATUS_TOO_MANY_COMMANDS},
+	{"NT_STATUS_ADAPTER_HARDWARE_ERROR",
+	 NT_STATUS_ADAPTER_HARDWARE_ERROR},
+	{"NT_STATUS_INVALID_NETWORK_RESPONSE",
+	 NT_STATUS_INVALID_NETWORK_RESPONSE},
+	{"NT_STATUS_UNEXPECTED_NETWORK_ERROR",
+	 NT_STATUS_UNEXPECTED_NETWORK_ERROR},
+	{"NT_STATUS_BAD_REMOTE_ADAPTER", NT_STATUS_BAD_REMOTE_ADAPTER},
+	{"NT_STATUS_PRINT_QUEUE_FULL", NT_STATUS_PRINT_QUEUE_FULL},
+	{"NT_STATUS_NO_SPOOL_SPACE", NT_STATUS_NO_SPOOL_SPACE},
+	{"NT_STATUS_PRINT_CANCELLED", NT_STATUS_PRINT_CANCELLED},
+	{"NT_STATUS_NETWORK_NAME_DELETED", NT_STATUS_NETWORK_NAME_DELETED},
+	{"NT_STATUS_NETWORK_ACCESS_DENIED",
+	 NT_STATUS_NETWORK_ACCESS_DENIED},
+	{"NT_STATUS_BAD_DEVICE_TYPE", NT_STATUS_BAD_DEVICE_TYPE},
+	{"NT_STATUS_BAD_NETWORK_NAME", NT_STATUS_BAD_NETWORK_NAME},
+	{"NT_STATUS_TOO_MANY_NAMES", NT_STATUS_TOO_MANY_NAMES},
+	{"NT_STATUS_TOO_MANY_SESSIONS", NT_STATUS_TOO_MANY_SESSIONS},
+	{"NT_STATUS_SHARING_PAUSED", NT_STATUS_SHARING_PAUSED},
+	{"NT_STATUS_REQUEST_NOT_ACCEPTED", NT_STATUS_REQUEST_NOT_ACCEPTED},
+	{"NT_STATUS_REDIRECTOR_PAUSED", NT_STATUS_REDIRECTOR_PAUSED},
+	{"NT_STATUS_NET_WRITE_FAULT", NT_STATUS_NET_WRITE_FAULT},
+	{"NT_STATUS_PROFILING_AT_LIMIT", NT_STATUS_PROFILING_AT_LIMIT},
+	{"NT_STATUS_NOT_SAME_DEVICE", NT_STATUS_NOT_SAME_DEVICE},
+	{"NT_STATUS_FILE_RENAMED", NT_STATUS_FILE_RENAMED},
+	{"NT_STATUS_VIRTUAL_CIRCUIT_CLOSED",
+	 NT_STATUS_VIRTUAL_CIRCUIT_CLOSED},
+	{"NT_STATUS_NO_SECURITY_ON_OBJECT",
+	 NT_STATUS_NO_SECURITY_ON_OBJECT},
+	{"NT_STATUS_CANT_WAIT", NT_STATUS_CANT_WAIT},
+	{"NT_STATUS_PIPE_EMPTY", NT_STATUS_PIPE_EMPTY},
+	{"NT_STATUS_CANT_ACCESS_DOMAIN_INFO",
+	 NT_STATUS_CANT_ACCESS_DOMAIN_INFO},
+	{"NT_STATUS_CANT_TERMINATE_SELF", NT_STATUS_CANT_TERMINATE_SELF},
+	{"NT_STATUS_INVALID_SERVER_STATE", NT_STATUS_INVALID_SERVER_STATE},
+	{"NT_STATUS_INVALID_DOMAIN_STATE", NT_STATUS_INVALID_DOMAIN_STATE},
+	{"NT_STATUS_INVALID_DOMAIN_ROLE", NT_STATUS_INVALID_DOMAIN_ROLE},
+	{"NT_STATUS_NO_SUCH_DOMAIN", NT_STATUS_NO_SUCH_DOMAIN},
+	{"NT_STATUS_DOMAIN_EXISTS", NT_STATUS_DOMAIN_EXISTS},
+	{"NT_STATUS_DOMAIN_LIMIT_EXCEEDED",
+	 NT_STATUS_DOMAIN_LIMIT_EXCEEDED},
+	{"NT_STATUS_OPLOCK_NOT_GRANTED", NT_STATUS_OPLOCK_NOT_GRANTED},
+	{"NT_STATUS_INVALID_OPLOCK_PROTOCOL",
+	 NT_STATUS_INVALID_OPLOCK_PROTOCOL},
+	{"NT_STATUS_INTERNAL_DB_CORRUPTION",
+	 NT_STATUS_INTERNAL_DB_CORRUPTION},
+	{"NT_STATUS_INTERNAL_ERROR", NT_STATUS_INTERNAL_ERROR},
+	{"NT_STATUS_GENERIC_NOT_MAPPED", NT_STATUS_GENERIC_NOT_MAPPED},
+	{"NT_STATUS_BAD_DESCRIPTOR_FORMAT",
+	 NT_STATUS_BAD_DESCRIPTOR_FORMAT},
+	{"NT_STATUS_INVALID_USER_BUFFER", NT_STATUS_INVALID_USER_BUFFER},
+	{"NT_STATUS_UNEXPECTED_IO_ERROR", NT_STATUS_UNEXPECTED_IO_ERROR},
+	{"NT_STATUS_UNEXPECTED_MM_CREATE_ERR",
+	 NT_STATUS_UNEXPECTED_MM_CREATE_ERR},
+	{"NT_STATUS_UNEXPECTED_MM_MAP_ERROR",
+	 NT_STATUS_UNEXPECTED_MM_MAP_ERROR},
+	{"NT_STATUS_UNEXPECTED_MM_EXTEND_ERR",
+	 NT_STATUS_UNEXPECTED_MM_EXTEND_ERR},
+	{"NT_STATUS_NOT_LOGON_PROCESS", NT_STATUS_NOT_LOGON_PROCESS},
+	{"NT_STATUS_LOGON_SESSION_EXISTS", NT_STATUS_LOGON_SESSION_EXISTS},
+	{"NT_STATUS_INVALID_PARAMETER_1", NT_STATUS_INVALID_PARAMETER_1},
+	{"NT_STATUS_INVALID_PARAMETER_2", NT_STATUS_INVALID_PARAMETER_2},
+	{"NT_STATUS_INVALID_PARAMETER_3", NT_STATUS_INVALID_PARAMETER_3},
+	{"NT_STATUS_INVALID_PARAMETER_4", NT_STATUS_INVALID_PARAMETER_4},
+	{"NT_STATUS_INVALID_PARAMETER_5", NT_STATUS_INVALID_PARAMETER_5},
+	{"NT_STATUS_INVALID_PARAMETER_6", NT_STATUS_INVALID_PARAMETER_6},
+	{"NT_STATUS_INVALID_PARAMETER_7", NT_STATUS_INVALID_PARAMETER_7},
+	{"NT_STATUS_INVALID_PARAMETER_8", NT_STATUS_INVALID_PARAMETER_8},
+	{"NT_STATUS_INVALID_PARAMETER_9", NT_STATUS_INVALID_PARAMETER_9},
+	{"NT_STATUS_INVALID_PARAMETER_10", NT_STATUS_INVALID_PARAMETER_10},
+	{"NT_STATUS_INVALID_PARAMETER_11", NT_STATUS_INVALID_PARAMETER_11},
+	{"NT_STATUS_INVALID_PARAMETER_12", NT_STATUS_INVALID_PARAMETER_12},
+	{"NT_STATUS_REDIRECTOR_NOT_STARTED",
+	 NT_STATUS_REDIRECTOR_NOT_STARTED},
+	{"NT_STATUS_REDIRECTOR_STARTED", NT_STATUS_REDIRECTOR_STARTED},
+	{"NT_STATUS_STACK_OVERFLOW", NT_STATUS_STACK_OVERFLOW},
+	{"NT_STATUS_NO_SUCH_PACKAGE", NT_STATUS_NO_SUCH_PACKAGE},
+	{"NT_STATUS_BAD_FUNCTION_TABLE", NT_STATUS_BAD_FUNCTION_TABLE},
+	{"NT_STATUS_DIRECTORY_NOT_EMPTY", NT_STATUS_DIRECTORY_NOT_EMPTY},
+	{"NT_STATUS_FILE_CORRUPT_ERROR", NT_STATUS_FILE_CORRUPT_ERROR},
+	{"NT_STATUS_NOT_A_DIRECTORY", NT_STATUS_NOT_A_DIRECTORY},
+	{"NT_STATUS_BAD_LOGON_SESSION_STATE",
+	 NT_STATUS_BAD_LOGON_SESSION_STATE},
+	{"NT_STATUS_LOGON_SESSION_COLLISION",
+	 NT_STATUS_LOGON_SESSION_COLLISION},
+	{"NT_STATUS_NAME_TOO_LONG", NT_STATUS_NAME_TOO_LONG},
+	{"NT_STATUS_FILES_OPEN", NT_STATUS_FILES_OPEN},
+	{"NT_STATUS_CONNECTION_IN_USE", NT_STATUS_CONNECTION_IN_USE},
+	{"NT_STATUS_MESSAGE_NOT_FOUND", NT_STATUS_MESSAGE_NOT_FOUND},
+	{"NT_STATUS_PROCESS_IS_TERMINATING",
+	 NT_STATUS_PROCESS_IS_TERMINATING},
+	{"NT_STATUS_INVALID_LOGON_TYPE", NT_STATUS_INVALID_LOGON_TYPE},
+	{"NT_STATUS_NO_GUID_TRANSLATION", NT_STATUS_NO_GUID_TRANSLATION},
+	{"NT_STATUS_CANNOT_IMPERSONATE", NT_STATUS_CANNOT_IMPERSONATE},
+	{"NT_STATUS_IMAGE_ALREADY_LOADED", NT_STATUS_IMAGE_ALREADY_LOADED},
+	{"NT_STATUS_ABIOS_NOT_PRESENT", NT_STATUS_ABIOS_NOT_PRESENT},
+	{"NT_STATUS_ABIOS_LID_NOT_EXIST", NT_STATUS_ABIOS_LID_NOT_EXIST},
+	{"NT_STATUS_ABIOS_LID_ALREADY_OWNED",
+	 NT_STATUS_ABIOS_LID_ALREADY_OWNED},
+	{"NT_STATUS_ABIOS_NOT_LID_OWNER", NT_STATUS_ABIOS_NOT_LID_OWNER},
+	{"NT_STATUS_ABIOS_INVALID_COMMAND",
+	 NT_STATUS_ABIOS_INVALID_COMMAND},
+	{"NT_STATUS_ABIOS_INVALID_LID", NT_STATUS_ABIOS_INVALID_LID},
+	{"NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE",
+	 NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE},
+	{"NT_STATUS_ABIOS_INVALID_SELECTOR",
+	 NT_STATUS_ABIOS_INVALID_SELECTOR},
+	{"NT_STATUS_NO_LDT", NT_STATUS_NO_LDT},
+	{"NT_STATUS_INVALID_LDT_SIZE", NT_STATUS_INVALID_LDT_SIZE},
+	{"NT_STATUS_INVALID_LDT_OFFSET", NT_STATUS_INVALID_LDT_OFFSET},
+	{"NT_STATUS_INVALID_LDT_DESCRIPTOR",
+	 NT_STATUS_INVALID_LDT_DESCRIPTOR},
+	{"NT_STATUS_INVALID_IMAGE_NE_FORMAT",
+	 NT_STATUS_INVALID_IMAGE_NE_FORMAT},
+	{"NT_STATUS_RXACT_INVALID_STATE", NT_STATUS_RXACT_INVALID_STATE},
+	{"NT_STATUS_RXACT_COMMIT_FAILURE", NT_STATUS_RXACT_COMMIT_FAILURE},
+	{"NT_STATUS_MAPPED_FILE_SIZE_ZERO",
+	 NT_STATUS_MAPPED_FILE_SIZE_ZERO},
+	{"NT_STATUS_TOO_MANY_OPENED_FILES",
+	 NT_STATUS_TOO_MANY_OPENED_FILES},
+	{"NT_STATUS_CANCELLED", NT_STATUS_CANCELLED},
+	{"NT_STATUS_CANNOT_DELETE", NT_STATUS_CANNOT_DELETE},
+	{"NT_STATUS_INVALID_COMPUTER_NAME",
+	 NT_STATUS_INVALID_COMPUTER_NAME},
+	{"NT_STATUS_FILE_DELETED", NT_STATUS_FILE_DELETED},
+	{"NT_STATUS_SPECIAL_ACCOUNT", NT_STATUS_SPECIAL_ACCOUNT},
+	{"NT_STATUS_SPECIAL_GROUP", NT_STATUS_SPECIAL_GROUP},
+	{"NT_STATUS_SPECIAL_USER", NT_STATUS_SPECIAL_USER},
+	{"NT_STATUS_MEMBERS_PRIMARY_GROUP",
+	 NT_STATUS_MEMBERS_PRIMARY_GROUP},
+	{"NT_STATUS_FILE_CLOSED", NT_STATUS_FILE_CLOSED},
+	{"NT_STATUS_TOO_MANY_THREADS", NT_STATUS_TOO_MANY_THREADS},
+	{"NT_STATUS_THREAD_NOT_IN_PROCESS",
+	 NT_STATUS_THREAD_NOT_IN_PROCESS},
+	{"NT_STATUS_TOKEN_ALREADY_IN_USE", NT_STATUS_TOKEN_ALREADY_IN_USE},
+	{"NT_STATUS_PAGEFILE_QUOTA_EXCEEDED",
+	 NT_STATUS_PAGEFILE_QUOTA_EXCEEDED},
+	{"NT_STATUS_COMMITMENT_LIMIT", NT_STATUS_COMMITMENT_LIMIT},
+	{"NT_STATUS_INVALID_IMAGE_LE_FORMAT",
+	 NT_STATUS_INVALID_IMAGE_LE_FORMAT},
+	{"NT_STATUS_INVALID_IMAGE_NOT_MZ", NT_STATUS_INVALID_IMAGE_NOT_MZ},
+	{"NT_STATUS_INVALID_IMAGE_PROTECT",
+	 NT_STATUS_INVALID_IMAGE_PROTECT},
+	{"NT_STATUS_INVALID_IMAGE_WIN_16", NT_STATUS_INVALID_IMAGE_WIN_16},
+	{"NT_STATUS_LOGON_SERVER_CONFLICT",
+	 NT_STATUS_LOGON_SERVER_CONFLICT},
+	{"NT_STATUS_TIME_DIFFERENCE_AT_DC",
+	 NT_STATUS_TIME_DIFFERENCE_AT_DC},
+	{"NT_STATUS_SYNCHRONIZATION_REQUIRED",
+	 NT_STATUS_SYNCHRONIZATION_REQUIRED},
+	{"NT_STATUS_DLL_NOT_FOUND", NT_STATUS_DLL_NOT_FOUND},
+	{"NT_STATUS_OPEN_FAILED", NT_STATUS_OPEN_FAILED},
+	{"NT_STATUS_IO_PRIVILEGE_FAILED", NT_STATUS_IO_PRIVILEGE_FAILED},
+	{"NT_STATUS_ORDINAL_NOT_FOUND", NT_STATUS_ORDINAL_NOT_FOUND},
+	{"NT_STATUS_ENTRYPOINT_NOT_FOUND", NT_STATUS_ENTRYPOINT_NOT_FOUND},
+	{"NT_STATUS_CONTROL_C_EXIT", NT_STATUS_CONTROL_C_EXIT},
+	{"NT_STATUS_LOCAL_DISCONNECT", NT_STATUS_LOCAL_DISCONNECT},
+	{"NT_STATUS_REMOTE_DISCONNECT", NT_STATUS_REMOTE_DISCONNECT},
+	{"NT_STATUS_REMOTE_RESOURCES", NT_STATUS_REMOTE_RESOURCES},
+	{"NT_STATUS_LINK_FAILED", NT_STATUS_LINK_FAILED},
+	{"NT_STATUS_LINK_TIMEOUT", NT_STATUS_LINK_TIMEOUT},
+	{"NT_STATUS_INVALID_CONNECTION", NT_STATUS_INVALID_CONNECTION},
+	{"NT_STATUS_INVALID_ADDRESS", NT_STATUS_INVALID_ADDRESS},
+	{"NT_STATUS_DLL_INIT_FAILED", NT_STATUS_DLL_INIT_FAILED},
+	{"NT_STATUS_MISSING_SYSTEMFILE", NT_STATUS_MISSING_SYSTEMFILE},
+	{"NT_STATUS_UNHANDLED_EXCEPTION", NT_STATUS_UNHANDLED_EXCEPTION},
+	{"NT_STATUS_APP_INIT_FAILURE", NT_STATUS_APP_INIT_FAILURE},
+	{"NT_STATUS_PAGEFILE_CREATE_FAILED",
+	 NT_STATUS_PAGEFILE_CREATE_FAILED},
+	{"NT_STATUS_NO_PAGEFILE", NT_STATUS_NO_PAGEFILE},
+	{"NT_STATUS_INVALID_LEVEL", NT_STATUS_INVALID_LEVEL},
+	{"NT_STATUS_WRONG_PASSWORD_CORE", NT_STATUS_WRONG_PASSWORD_CORE},
+	{"NT_STATUS_ILLEGAL_FLOAT_CONTEXT",
+	 NT_STATUS_ILLEGAL_FLOAT_CONTEXT},
+	{"NT_STATUS_PIPE_BROKEN", NT_STATUS_PIPE_BROKEN},
+	{"NT_STATUS_REGISTRY_CORRUPT", NT_STATUS_REGISTRY_CORRUPT},
+	{"NT_STATUS_REGISTRY_IO_FAILED", NT_STATUS_REGISTRY_IO_FAILED},
+	{"NT_STATUS_NO_EVENT_PAIR", NT_STATUS_NO_EVENT_PAIR},
+	{"NT_STATUS_UNRECOGNIZED_VOLUME", NT_STATUS_UNRECOGNIZED_VOLUME},
+	{"NT_STATUS_SERIAL_NO_DEVICE_INITED",
+	 NT_STATUS_SERIAL_NO_DEVICE_INITED},
+	{"NT_STATUS_NO_SUCH_ALIAS", NT_STATUS_NO_SUCH_ALIAS},
+	{"NT_STATUS_MEMBER_NOT_IN_ALIAS", NT_STATUS_MEMBER_NOT_IN_ALIAS},
+	{"NT_STATUS_MEMBER_IN_ALIAS", NT_STATUS_MEMBER_IN_ALIAS},
+	{"NT_STATUS_ALIAS_EXISTS", NT_STATUS_ALIAS_EXISTS},
+	{"NT_STATUS_LOGON_NOT_GRANTED", NT_STATUS_LOGON_NOT_GRANTED},
+	{"NT_STATUS_TOO_MANY_SECRETS", NT_STATUS_TOO_MANY_SECRETS},
+	{"NT_STATUS_SECRET_TOO_LONG", NT_STATUS_SECRET_TOO_LONG},
+	{"NT_STATUS_INTERNAL_DB_ERROR", NT_STATUS_INTERNAL_DB_ERROR},
+	{"NT_STATUS_FULLSCREEN_MODE", NT_STATUS_FULLSCREEN_MODE},
+	{"NT_STATUS_TOO_MANY_CONTEXT_IDS", NT_STATUS_TOO_MANY_CONTEXT_IDS},
+	{"NT_STATUS_LOGON_TYPE_NOT_GRANTED",
+	 NT_STATUS_LOGON_TYPE_NOT_GRANTED},
+	{"NT_STATUS_NOT_REGISTRY_FILE", NT_STATUS_NOT_REGISTRY_FILE},
+	{"NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED",
+	 NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED},
+	{"NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR",
+	 NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR},
+	{"NT_STATUS_FT_MISSING_MEMBER", NT_STATUS_FT_MISSING_MEMBER},
+	{"NT_STATUS_ILL_FORMED_SERVICE_ENTRY",
+	 NT_STATUS_ILL_FORMED_SERVICE_ENTRY},
+	{"NT_STATUS_ILLEGAL_CHARACTER", NT_STATUS_ILLEGAL_CHARACTER},
+	{"NT_STATUS_UNMAPPABLE_CHARACTER", NT_STATUS_UNMAPPABLE_CHARACTER},
+	{"NT_STATUS_UNDEFINED_CHARACTER", NT_STATUS_UNDEFINED_CHARACTER},
+	{"NT_STATUS_FLOPPY_VOLUME", NT_STATUS_FLOPPY_VOLUME},
+	{"NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND",
+	 NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND},
+	{"NT_STATUS_FLOPPY_WRONG_CYLINDER",
+	 NT_STATUS_FLOPPY_WRONG_CYLINDER},
+	{"NT_STATUS_FLOPPY_UNKNOWN_ERROR", NT_STATUS_FLOPPY_UNKNOWN_ERROR},
+	{"NT_STATUS_FLOPPY_BAD_REGISTERS", NT_STATUS_FLOPPY_BAD_REGISTERS},
+	{"NT_STATUS_DISK_RECALIBRATE_FAILED",
+	 NT_STATUS_DISK_RECALIBRATE_FAILED},
+	{"NT_STATUS_DISK_OPERATION_FAILED",
+	 NT_STATUS_DISK_OPERATION_FAILED},
+	{"NT_STATUS_DISK_RESET_FAILED", NT_STATUS_DISK_RESET_FAILED},
+	{"NT_STATUS_SHARED_IRQ_BUSY", NT_STATUS_SHARED_IRQ_BUSY},
+	{"NT_STATUS_FT_ORPHANING", NT_STATUS_FT_ORPHANING},
+	{"NT_STATUS_PARTITION_FAILURE", NT_STATUS_PARTITION_FAILURE},
+	{"NT_STATUS_INVALID_BLOCK_LENGTH", NT_STATUS_INVALID_BLOCK_LENGTH},
+	{"NT_STATUS_DEVICE_NOT_PARTITIONED",
+	 NT_STATUS_DEVICE_NOT_PARTITIONED},
+	{"NT_STATUS_UNABLE_TO_LOCK_MEDIA", NT_STATUS_UNABLE_TO_LOCK_MEDIA},
+	{"NT_STATUS_UNABLE_TO_UNLOAD_MEDIA",
+	 NT_STATUS_UNABLE_TO_UNLOAD_MEDIA},
+	{"NT_STATUS_EOM_OVERFLOW", NT_STATUS_EOM_OVERFLOW},
+	{"NT_STATUS_NO_MEDIA", NT_STATUS_NO_MEDIA},
+	{"NT_STATUS_NO_SUCH_MEMBER", NT_STATUS_NO_SUCH_MEMBER},
+	{"NT_STATUS_INVALID_MEMBER", NT_STATUS_INVALID_MEMBER},
+	{"NT_STATUS_KEY_DELETED", NT_STATUS_KEY_DELETED},
+	{"NT_STATUS_NO_LOG_SPACE", NT_STATUS_NO_LOG_SPACE},
+	{"NT_STATUS_TOO_MANY_SIDS", NT_STATUS_TOO_MANY_SIDS},
+	{"NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED",
+	 NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED},
+	{"NT_STATUS_KEY_HAS_CHILDREN", NT_STATUS_KEY_HAS_CHILDREN},
+	{"NT_STATUS_CHILD_MUST_BE_VOLATILE",
+	 NT_STATUS_CHILD_MUST_BE_VOLATILE},
+	{"NT_STATUS_DEVICE_CONFIGURATION_ERROR",
+	 NT_STATUS_DEVICE_CONFIGURATION_ERROR},
+	{"NT_STATUS_DRIVER_INTERNAL_ERROR",
+	 NT_STATUS_DRIVER_INTERNAL_ERROR},
+	{"NT_STATUS_INVALID_DEVICE_STATE", NT_STATUS_INVALID_DEVICE_STATE},
+	{"NT_STATUS_IO_DEVICE_ERROR", NT_STATUS_IO_DEVICE_ERROR},
+	{"NT_STATUS_DEVICE_PROTOCOL_ERROR",
+	 NT_STATUS_DEVICE_PROTOCOL_ERROR},
+	{"NT_STATUS_BACKUP_CONTROLLER", NT_STATUS_BACKUP_CONTROLLER},
+	{"NT_STATUS_LOG_FILE_FULL", NT_STATUS_LOG_FILE_FULL},
+	{"NT_STATUS_TOO_LATE", NT_STATUS_TOO_LATE},
+	{"NT_STATUS_NO_TRUST_LSA_SECRET", NT_STATUS_NO_TRUST_LSA_SECRET},
+	{"NT_STATUS_NO_TRUST_SAM_ACCOUNT", NT_STATUS_NO_TRUST_SAM_ACCOUNT},
+	{"NT_STATUS_TRUSTED_DOMAIN_FAILURE",
+	 NT_STATUS_TRUSTED_DOMAIN_FAILURE},
+	{"NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE",
+	 NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE},
+	{"NT_STATUS_EVENTLOG_FILE_CORRUPT",
+	 NT_STATUS_EVENTLOG_FILE_CORRUPT},
+	{"NT_STATUS_EVENTLOG_CANT_START", NT_STATUS_EVENTLOG_CANT_START},
+	{"NT_STATUS_TRUST_FAILURE", NT_STATUS_TRUST_FAILURE},
+	{"NT_STATUS_MUTANT_LIMIT_EXCEEDED",
+	 NT_STATUS_MUTANT_LIMIT_EXCEEDED},
+	{"NT_STATUS_NETLOGON_NOT_STARTED", NT_STATUS_NETLOGON_NOT_STARTED},
+	{"NT_STATUS_ACCOUNT_EXPIRED", NT_STATUS_ACCOUNT_EXPIRED},
+	{"NT_STATUS_POSSIBLE_DEADLOCK", NT_STATUS_POSSIBLE_DEADLOCK},
+	{"NT_STATUS_NETWORK_CREDENTIAL_CONFLICT",
+	 NT_STATUS_NETWORK_CREDENTIAL_CONFLICT},
+	{"NT_STATUS_REMOTE_SESSION_LIMIT", NT_STATUS_REMOTE_SESSION_LIMIT},
+	{"NT_STATUS_EVENTLOG_FILE_CHANGED",
+	 NT_STATUS_EVENTLOG_FILE_CHANGED},
+	{"NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT",
+	 NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT},
+	{"NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT",
+	 NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT},
+	{"NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT",
+	 NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT},
+	{"NT_STATUS_DOMAIN_TRUST_INCONSISTENT",
+	 NT_STATUS_DOMAIN_TRUST_INCONSISTENT},
+	{"NT_STATUS_FS_DRIVER_REQUIRED", NT_STATUS_FS_DRIVER_REQUIRED},
+	{"NT_STATUS_NO_USER_SESSION_KEY", NT_STATUS_NO_USER_SESSION_KEY},
+	{"NT_STATUS_USER_SESSION_DELETED", NT_STATUS_USER_SESSION_DELETED},
+	{"NT_STATUS_RESOURCE_LANG_NOT_FOUND",
+	 NT_STATUS_RESOURCE_LANG_NOT_FOUND},
+	{"NT_STATUS_INSUFF_SERVER_RESOURCES",
+	 NT_STATUS_INSUFF_SERVER_RESOURCES},
+	{"NT_STATUS_INVALID_BUFFER_SIZE", NT_STATUS_INVALID_BUFFER_SIZE},
+	{"NT_STATUS_INVALID_ADDRESS_COMPONENT",
+	 NT_STATUS_INVALID_ADDRESS_COMPONENT},
+	{"NT_STATUS_INVALID_ADDRESS_WILDCARD",
+	 NT_STATUS_INVALID_ADDRESS_WILDCARD},
+	{"NT_STATUS_TOO_MANY_ADDRESSES", NT_STATUS_TOO_MANY_ADDRESSES},
+	{"NT_STATUS_ADDRESS_ALREADY_EXISTS",
+	 NT_STATUS_ADDRESS_ALREADY_EXISTS},
+	{"NT_STATUS_ADDRESS_CLOSED", NT_STATUS_ADDRESS_CLOSED},
+	{"NT_STATUS_CONNECTION_DISCONNECTED",
+	 NT_STATUS_CONNECTION_DISCONNECTED},
+	{"NT_STATUS_CONNECTION_RESET", NT_STATUS_CONNECTION_RESET},
+	{"NT_STATUS_TOO_MANY_NODES", NT_STATUS_TOO_MANY_NODES},
+	{"NT_STATUS_TRANSACTION_ABORTED", NT_STATUS_TRANSACTION_ABORTED},
+	{"NT_STATUS_TRANSACTION_TIMED_OUT",
+	 NT_STATUS_TRANSACTION_TIMED_OUT},
+	{"NT_STATUS_TRANSACTION_NO_RELEASE",
+	 NT_STATUS_TRANSACTION_NO_RELEASE},
+	{"NT_STATUS_TRANSACTION_NO_MATCH", NT_STATUS_TRANSACTION_NO_MATCH},
+	{"NT_STATUS_TRANSACTION_RESPONDED",
+	 NT_STATUS_TRANSACTION_RESPONDED},
+	{"NT_STATUS_TRANSACTION_INVALID_ID",
+	 NT_STATUS_TRANSACTION_INVALID_ID},
+	{"NT_STATUS_TRANSACTION_INVALID_TYPE",
+	 NT_STATUS_TRANSACTION_INVALID_TYPE},
+	{"NT_STATUS_NOT_SERVER_SESSION", NT_STATUS_NOT_SERVER_SESSION},
+	{"NT_STATUS_NOT_CLIENT_SESSION", NT_STATUS_NOT_CLIENT_SESSION},
+	{"NT_STATUS_CANNOT_LOAD_REGISTRY_FILE",
+	 NT_STATUS_CANNOT_LOAD_REGISTRY_FILE},
+	{"NT_STATUS_DEBUG_ATTACH_FAILED", NT_STATUS_DEBUG_ATTACH_FAILED},
+	{"NT_STATUS_SYSTEM_PROCESS_TERMINATED",
+	 NT_STATUS_SYSTEM_PROCESS_TERMINATED},
+	{"NT_STATUS_DATA_NOT_ACCEPTED", NT_STATUS_DATA_NOT_ACCEPTED},
+	{"NT_STATUS_NO_BROWSER_SERVERS_FOUND",
+	 NT_STATUS_NO_BROWSER_SERVERS_FOUND},
+	{"NT_STATUS_VDM_HARD_ERROR", NT_STATUS_VDM_HARD_ERROR},
+	{"NT_STATUS_DRIVER_CANCEL_TIMEOUT",
+	 NT_STATUS_DRIVER_CANCEL_TIMEOUT},
+	{"NT_STATUS_REPLY_MESSAGE_MISMATCH",
+	 NT_STATUS_REPLY_MESSAGE_MISMATCH},
+	{"NT_STATUS_MAPPED_ALIGNMENT", NT_STATUS_MAPPED_ALIGNMENT},
+	{"NT_STATUS_IMAGE_CHECKSUM_MISMATCH",
+	 NT_STATUS_IMAGE_CHECKSUM_MISMATCH},
+	{"NT_STATUS_LOST_WRITEBEHIND_DATA",
+	 NT_STATUS_LOST_WRITEBEHIND_DATA},
+	{"NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID",
+	 NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID},
+	{"NT_STATUS_PASSWORD_MUST_CHANGE", NT_STATUS_PASSWORD_MUST_CHANGE},
+	{"NT_STATUS_NOT_FOUND", NT_STATUS_NOT_FOUND},
+	{"NT_STATUS_NOT_TINY_STREAM", NT_STATUS_NOT_TINY_STREAM},
+	{"NT_STATUS_RECOVERY_FAILURE", NT_STATUS_RECOVERY_FAILURE},
+	{"NT_STATUS_STACK_OVERFLOW_READ", NT_STATUS_STACK_OVERFLOW_READ},
+	{"NT_STATUS_FAIL_CHECK", NT_STATUS_FAIL_CHECK},
+	{"NT_STATUS_DUPLICATE_OBJECTID", NT_STATUS_DUPLICATE_OBJECTID},
+	{"NT_STATUS_OBJECTID_EXISTS", NT_STATUS_OBJECTID_EXISTS},
+	{"NT_STATUS_CONVERT_TO_LARGE", NT_STATUS_CONVERT_TO_LARGE},
+	{"NT_STATUS_RETRY", NT_STATUS_RETRY},
+	{"NT_STATUS_FOUND_OUT_OF_SCOPE", NT_STATUS_FOUND_OUT_OF_SCOPE},
+	{"NT_STATUS_ALLOCATE_BUCKET", NT_STATUS_ALLOCATE_BUCKET},
+	{"NT_STATUS_PROPSET_NOT_FOUND", NT_STATUS_PROPSET_NOT_FOUND},
+	{"NT_STATUS_MARSHALL_OVERFLOW", NT_STATUS_MARSHALL_OVERFLOW},
+	{"NT_STATUS_INVALID_VARIANT", NT_STATUS_INVALID_VARIANT},
+	{"NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND",
+	 NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND},
+	{"NT_STATUS_ACCOUNT_LOCKED_OUT", NT_STATUS_ACCOUNT_LOCKED_OUT},
+	{"NT_STATUS_HANDLE_NOT_CLOSABLE", NT_STATUS_HANDLE_NOT_CLOSABLE},
+	{"NT_STATUS_CONNECTION_REFUSED", NT_STATUS_CONNECTION_REFUSED},
+	{"NT_STATUS_GRACEFUL_DISCONNECT", NT_STATUS_GRACEFUL_DISCONNECT},
+	{"NT_STATUS_ADDRESS_ALREADY_ASSOCIATED",
+	 NT_STATUS_ADDRESS_ALREADY_ASSOCIATED},
+	{"NT_STATUS_ADDRESS_NOT_ASSOCIATED",
+	 NT_STATUS_ADDRESS_NOT_ASSOCIATED},
+	{"NT_STATUS_CONNECTION_INVALID", NT_STATUS_CONNECTION_INVALID},
+	{"NT_STATUS_CONNECTION_ACTIVE", NT_STATUS_CONNECTION_ACTIVE},
+	{"NT_STATUS_NETWORK_UNREACHABLE", NT_STATUS_NETWORK_UNREACHABLE},
+	{"NT_STATUS_HOST_UNREACHABLE", NT_STATUS_HOST_UNREACHABLE},
+	{"NT_STATUS_PROTOCOL_UNREACHABLE", NT_STATUS_PROTOCOL_UNREACHABLE},
+	{"NT_STATUS_PORT_UNREACHABLE", NT_STATUS_PORT_UNREACHABLE},
+	{"NT_STATUS_REQUEST_ABORTED", NT_STATUS_REQUEST_ABORTED},
+	{"NT_STATUS_CONNECTION_ABORTED", NT_STATUS_CONNECTION_ABORTED},
+	{"NT_STATUS_BAD_COMPRESSION_BUFFER",
+	 NT_STATUS_BAD_COMPRESSION_BUFFER},
+	{"NT_STATUS_USER_MAPPED_FILE", NT_STATUS_USER_MAPPED_FILE},
+	{"NT_STATUS_AUDIT_FAILED", NT_STATUS_AUDIT_FAILED},
+	{"NT_STATUS_TIMER_RESOLUTION_NOT_SET",
+	 NT_STATUS_TIMER_RESOLUTION_NOT_SET},
+	{"NT_STATUS_CONNECTION_COUNT_LIMIT",
+	 NT_STATUS_CONNECTION_COUNT_LIMIT},
+	{"NT_STATUS_LOGIN_TIME_RESTRICTION",
+	 NT_STATUS_LOGIN_TIME_RESTRICTION},
+	{"NT_STATUS_LOGIN_WKSTA_RESTRICTION",
+	 NT_STATUS_LOGIN_WKSTA_RESTRICTION},
+	{"NT_STATUS_IMAGE_MP_UP_MISMATCH", NT_STATUS_IMAGE_MP_UP_MISMATCH},
+	{"NT_STATUS_INSUFFICIENT_LOGON_INFO",
+	 NT_STATUS_INSUFFICIENT_LOGON_INFO},
+	{"NT_STATUS_BAD_DLL_ENTRYPOINT", NT_STATUS_BAD_DLL_ENTRYPOINT},
+	{"NT_STATUS_BAD_SERVICE_ENTRYPOINT",
+	 NT_STATUS_BAD_SERVICE_ENTRYPOINT},
+	{"NT_STATUS_LPC_REPLY_LOST", NT_STATUS_LPC_REPLY_LOST},
+	{"NT_STATUS_IP_ADDRESS_CONFLICT1", NT_STATUS_IP_ADDRESS_CONFLICT1},
+	{"NT_STATUS_IP_ADDRESS_CONFLICT2", NT_STATUS_IP_ADDRESS_CONFLICT2},
+	{"NT_STATUS_REGISTRY_QUOTA_LIMIT", NT_STATUS_REGISTRY_QUOTA_LIMIT},
+	{"NT_STATUS_PATH_NOT_COVERED", NT_STATUS_PATH_NOT_COVERED},
+	{"NT_STATUS_NO_CALLBACK_ACTIVE", NT_STATUS_NO_CALLBACK_ACTIVE},
+	{"NT_STATUS_LICENSE_QUOTA_EXCEEDED",
+	 NT_STATUS_LICENSE_QUOTA_EXCEEDED},
+	{"NT_STATUS_PWD_TOO_SHORT", NT_STATUS_PWD_TOO_SHORT},
+	{"NT_STATUS_PWD_TOO_RECENT", NT_STATUS_PWD_TOO_RECENT},
+	{"NT_STATUS_PWD_HISTORY_CONFLICT", NT_STATUS_PWD_HISTORY_CONFLICT},
+	{"NT_STATUS_PLUGPLAY_NO_DEVICE", NT_STATUS_PLUGPLAY_NO_DEVICE},
+	{"NT_STATUS_UNSUPPORTED_COMPRESSION",
+	 NT_STATUS_UNSUPPORTED_COMPRESSION},
+	{"NT_STATUS_INVALID_HW_PROFILE", NT_STATUS_INVALID_HW_PROFILE},
+	{"NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH",
+	 NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH},
+	{"NT_STATUS_DRIVER_ORDINAL_NOT_FOUND",
+	 NT_STATUS_DRIVER_ORDINAL_NOT_FOUND},
+	{"NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND",
+	 NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND},
+	{"NT_STATUS_RESOURCE_NOT_OWNED", NT_STATUS_RESOURCE_NOT_OWNED},
+	{"NT_STATUS_TOO_MANY_LINKS", NT_STATUS_TOO_MANY_LINKS},
+	{"NT_STATUS_QUOTA_LIST_INCONSISTENT",
+	 NT_STATUS_QUOTA_LIST_INCONSISTENT},
+	{"NT_STATUS_FILE_IS_OFFLINE", NT_STATUS_FILE_IS_OFFLINE},
+	{"NT_STATUS_NO_MORE_ENTRIES", NT_STATUS_NO_MORE_ENTRIES},
+	{"STATUS_MORE_ENTRIES", STATUS_MORE_ENTRIES},
+	{"STATUS_SOME_UNMAPPED", STATUS_SOME_UNMAPPED},
+	{NULL, 0}
+};
diff --git a/fs/cifs/nterr.h b/fs/cifs/nterr.h
new file mode 100644
index 0000000..d2fb06c
--- /dev/null
+++ b/fs/cifs/nterr.h
@@ -0,0 +1,556 @@
+/* 
+   Unix SMB/Netbios implementation.
+   Version 1.9.
+   NT error code constants
+   Copyright (C) Andrew Tridgell              1992-2000
+   Copyright (C) John H Terpstra              1996-2000
+   Copyright (C) Luke Kenneth Casson Leighton 1996-2000
+   Copyright (C) Paul Ashton                  1998-2000
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+
+
+#ifndef _NTERR_H
+#define _NTERR_H
+
+struct nt_err_code_struct {
+	char *nt_errstr;
+	__u32 nt_errcode;
+};
+
+extern const struct nt_err_code_struct nt_errs[];
+
+/* Win32 Status codes. */
+
+#define STATUS_BUFFER_OVERFLOW            0x80000005
+#define STATUS_MORE_ENTRIES               0x0105
+#define ERROR_INVALID_PARAMETER		  0x0057
+#define ERROR_INSUFFICIENT_BUFFER	  0x007a
+#define STATUS_1804	                  0x070c
+#define STATUS_NOTIFY_ENUM_DIR            0x010c
+
+/* Win32 Error codes extracted using a loop in smbclient then printing a
+   netmon sniff to a file. */
+
+#define NT_STATUS_OK 0x0000
+#define STATUS_SOME_UNMAPPED       0x0107
+#define STATUS_BUFFER_OVERFLOW     0x80000005
+#define NT_STATUS_NO_MORE_ENTRIES  0x8000001a
+#define NT_STATUS_UNSUCCESSFUL 0xC0000000 | 0x0001
+#define NT_STATUS_NOT_IMPLEMENTED 0xC0000000 | 0x0002
+#define NT_STATUS_INVALID_INFO_CLASS 0xC0000000 | 0x0003
+#define NT_STATUS_INFO_LENGTH_MISMATCH 0xC0000000 | 0x0004
+#define NT_STATUS_ACCESS_VIOLATION 0xC0000000 | 0x0005
+#define NT_STATUS_IN_PAGE_ERROR 0xC0000000 | 0x0006
+#define NT_STATUS_PAGEFILE_QUOTA 0xC0000000 | 0x0007
+#define NT_STATUS_INVALID_HANDLE 0xC0000000 | 0x0008
+#define NT_STATUS_BAD_INITIAL_STACK 0xC0000000 | 0x0009
+#define NT_STATUS_BAD_INITIAL_PC 0xC0000000 | 0x000a
+#define NT_STATUS_INVALID_CID 0xC0000000 | 0x000b
+#define NT_STATUS_TIMER_NOT_CANCELED 0xC0000000 | 0x000c
+#define NT_STATUS_INVALID_PARAMETER 0xC0000000 | 0x000d
+#define NT_STATUS_NO_SUCH_DEVICE 0xC0000000 | 0x000e
+#define NT_STATUS_NO_SUCH_FILE 0xC0000000 | 0x000f
+#define NT_STATUS_INVALID_DEVICE_REQUEST 0xC0000000 | 0x0010
+#define NT_STATUS_END_OF_FILE 0xC0000000 | 0x0011
+#define NT_STATUS_WRONG_VOLUME 0xC0000000 | 0x0012
+#define NT_STATUS_NO_MEDIA_IN_DEVICE 0xC0000000 | 0x0013
+#define NT_STATUS_UNRECOGNIZED_MEDIA 0xC0000000 | 0x0014
+#define NT_STATUS_NONEXISTENT_SECTOR 0xC0000000 | 0x0015
+#define NT_STATUS_MORE_PROCESSING_REQUIRED 0xC0000000 | 0x0016
+#define NT_STATUS_NO_MEMORY 0xC0000000 | 0x0017
+#define NT_STATUS_CONFLICTING_ADDRESSES 0xC0000000 | 0x0018
+#define NT_STATUS_NOT_MAPPED_VIEW 0xC0000000 | 0x0019
+#define NT_STATUS_UNABLE_TO_FREE_VM 0x80000000 | 0x001a
+#define NT_STATUS_UNABLE_TO_DELETE_SECTION 0xC0000000 | 0x001b
+#define NT_STATUS_INVALID_SYSTEM_SERVICE 0xC0000000 | 0x001c
+#define NT_STATUS_ILLEGAL_INSTRUCTION 0xC0000000 | 0x001d
+#define NT_STATUS_INVALID_LOCK_SEQUENCE 0xC0000000 | 0x001e
+#define NT_STATUS_INVALID_VIEW_SIZE 0xC0000000 | 0x001f
+#define NT_STATUS_INVALID_FILE_FOR_SECTION 0xC0000000 | 0x0020
+#define NT_STATUS_ALREADY_COMMITTED 0xC0000000 | 0x0021
+#define NT_STATUS_ACCESS_DENIED 0xC0000000 | 0x0022
+#define NT_STATUS_BUFFER_TOO_SMALL 0xC0000000 | 0x0023
+#define NT_STATUS_OBJECT_TYPE_MISMATCH 0xC0000000 | 0x0024
+#define NT_STATUS_NONCONTINUABLE_EXCEPTION 0xC0000000 | 0x0025
+#define NT_STATUS_INVALID_DISPOSITION 0xC0000000 | 0x0026
+#define NT_STATUS_UNWIND 0xC0000000 | 0x0027
+#define NT_STATUS_BAD_STACK 0xC0000000 | 0x0028
+#define NT_STATUS_INVALID_UNWIND_TARGET 0xC0000000 | 0x0029
+#define NT_STATUS_NOT_LOCKED 0xC0000000 | 0x002a
+#define NT_STATUS_PARITY_ERROR 0xC0000000 | 0x002b
+#define NT_STATUS_UNABLE_TO_DECOMMIT_VM 0xC0000000 | 0x002c
+#define NT_STATUS_NOT_COMMITTED 0xC0000000 | 0x002d
+#define NT_STATUS_INVALID_PORT_ATTRIBUTES 0xC0000000 | 0x002e
+#define NT_STATUS_PORT_MESSAGE_TOO_LONG 0xC0000000 | 0x002f
+#define NT_STATUS_INVALID_PARAMETER_MIX 0xC0000000 | 0x0030
+#define NT_STATUS_INVALID_QUOTA_LOWER 0xC0000000 | 0x0031
+#define NT_STATUS_DISK_CORRUPT_ERROR 0xC0000000 | 0x0032
+#define NT_STATUS_OBJECT_NAME_INVALID 0xC0000000 | 0x0033
+#define NT_STATUS_OBJECT_NAME_NOT_FOUND 0xC0000000 | 0x0034
+#define NT_STATUS_OBJECT_NAME_COLLISION 0xC0000000 | 0x0035
+#define NT_STATUS_HANDLE_NOT_WAITABLE 0xC0000000 | 0x0036
+#define NT_STATUS_PORT_DISCONNECTED 0xC0000000 | 0x0037
+#define NT_STATUS_DEVICE_ALREADY_ATTACHED 0xC0000000 | 0x0038
+#define NT_STATUS_OBJECT_PATH_INVALID 0xC0000000 | 0x0039
+#define NT_STATUS_OBJECT_PATH_NOT_FOUND 0xC0000000 | 0x003a
+#define NT_STATUS_OBJECT_PATH_SYNTAX_BAD 0xC0000000 | 0x003b
+#define NT_STATUS_DATA_OVERRUN 0xC0000000 | 0x003c
+#define NT_STATUS_DATA_LATE_ERROR 0xC0000000 | 0x003d
+#define NT_STATUS_DATA_ERROR 0xC0000000 | 0x003e
+#define NT_STATUS_CRC_ERROR 0xC0000000 | 0x003f
+#define NT_STATUS_SECTION_TOO_BIG 0xC0000000 | 0x0040
+#define NT_STATUS_PORT_CONNECTION_REFUSED 0xC0000000 | 0x0041
+#define NT_STATUS_INVALID_PORT_HANDLE 0xC0000000 | 0x0042
+#define NT_STATUS_SHARING_VIOLATION 0xC0000000 | 0x0043
+#define NT_STATUS_QUOTA_EXCEEDED 0xC0000000 | 0x0044
+#define NT_STATUS_INVALID_PAGE_PROTECTION 0xC0000000 | 0x0045
+#define NT_STATUS_MUTANT_NOT_OWNED 0xC0000000 | 0x0046
+#define NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED 0xC0000000 | 0x0047
+#define NT_STATUS_PORT_ALREADY_SET 0xC0000000 | 0x0048
+#define NT_STATUS_SECTION_NOT_IMAGE 0xC0000000 | 0x0049
+#define NT_STATUS_SUSPEND_COUNT_EXCEEDED 0xC0000000 | 0x004a
+#define NT_STATUS_THREAD_IS_TERMINATING 0xC0000000 | 0x004b
+#define NT_STATUS_BAD_WORKING_SET_LIMIT 0xC0000000 | 0x004c
+#define NT_STATUS_INCOMPATIBLE_FILE_MAP 0xC0000000 | 0x004d
+#define NT_STATUS_SECTION_PROTECTION 0xC0000000 | 0x004e
+#define NT_STATUS_EAS_NOT_SUPPORTED 0xC0000000 | 0x004f
+#define NT_STATUS_EA_TOO_LARGE 0xC0000000 | 0x0050
+#define NT_STATUS_NONEXISTENT_EA_ENTRY 0xC0000000 | 0x0051
+#define NT_STATUS_NO_EAS_ON_FILE 0xC0000000 | 0x0052
+#define NT_STATUS_EA_CORRUPT_ERROR 0xC0000000 | 0x0053
+#define NT_STATUS_FILE_LOCK_CONFLICT 0xC0000000 | 0x0054
+#define NT_STATUS_LOCK_NOT_GRANTED 0xC0000000 | 0x0055
+#define NT_STATUS_DELETE_PENDING 0xC0000000 | 0x0056
+#define NT_STATUS_CTL_FILE_NOT_SUPPORTED 0xC0000000 | 0x0057
+#define NT_STATUS_UNKNOWN_REVISION 0xC0000000 | 0x0058
+#define NT_STATUS_REVISION_MISMATCH 0xC0000000 | 0x0059
+#define NT_STATUS_INVALID_OWNER 0xC0000000 | 0x005a
+#define NT_STATUS_INVALID_PRIMARY_GROUP 0xC0000000 | 0x005b
+#define NT_STATUS_NO_IMPERSONATION_TOKEN 0xC0000000 | 0x005c
+#define NT_STATUS_CANT_DISABLE_MANDATORY 0xC0000000 | 0x005d
+#define NT_STATUS_NO_LOGON_SERVERS 0xC0000000 | 0x005e
+#define NT_STATUS_NO_SUCH_LOGON_SESSION 0xC0000000 | 0x005f
+#define NT_STATUS_NO_SUCH_PRIVILEGE 0xC0000000 | 0x0060
+#define NT_STATUS_PRIVILEGE_NOT_HELD 0xC0000000 | 0x0061
+#define NT_STATUS_INVALID_ACCOUNT_NAME 0xC0000000 | 0x0062
+#define NT_STATUS_USER_EXISTS 0xC0000000 | 0x0063
+#define NT_STATUS_NO_SUCH_USER 0xC0000000 | 0x0064
+#define NT_STATUS_GROUP_EXISTS 0xC0000000 | 0x0065
+#define NT_STATUS_NO_SUCH_GROUP 0xC0000000 | 0x0066
+#define NT_STATUS_MEMBER_IN_GROUP 0xC0000000 | 0x0067
+#define NT_STATUS_MEMBER_NOT_IN_GROUP 0xC0000000 | 0x0068
+#define NT_STATUS_LAST_ADMIN 0xC0000000 | 0x0069
+#define NT_STATUS_WRONG_PASSWORD 0xC0000000 | 0x006a
+#define NT_STATUS_ILL_FORMED_PASSWORD 0xC0000000 | 0x006b
+#define NT_STATUS_PASSWORD_RESTRICTION 0xC0000000 | 0x006c
+#define NT_STATUS_LOGON_FAILURE 0xC0000000 | 0x006d
+#define NT_STATUS_ACCOUNT_RESTRICTION 0xC0000000 | 0x006e
+#define NT_STATUS_INVALID_LOGON_HOURS 0xC0000000 | 0x006f
+#define NT_STATUS_INVALID_WORKSTATION 0xC0000000 | 0x0070
+#define NT_STATUS_PASSWORD_EXPIRED 0xC0000000 | 0x0071
+#define NT_STATUS_ACCOUNT_DISABLED 0xC0000000 | 0x0072
+#define NT_STATUS_NONE_MAPPED 0xC0000000 | 0x0073
+#define NT_STATUS_TOO_MANY_LUIDS_REQUESTED 0xC0000000 | 0x0074
+#define NT_STATUS_LUIDS_EXHAUSTED 0xC0000000 | 0x0075
+#define NT_STATUS_INVALID_SUB_AUTHORITY 0xC0000000 | 0x0076
+#define NT_STATUS_INVALID_ACL 0xC0000000 | 0x0077
+#define NT_STATUS_INVALID_SID 0xC0000000 | 0x0078
+#define NT_STATUS_INVALID_SECURITY_DESCR 0xC0000000 | 0x0079
+#define NT_STATUS_PROCEDURE_NOT_FOUND 0xC0000000 | 0x007a
+#define NT_STATUS_INVALID_IMAGE_FORMAT 0xC0000000 | 0x007b
+#define NT_STATUS_NO_TOKEN 0xC0000000 | 0x007c
+#define NT_STATUS_BAD_INHERITANCE_ACL 0xC0000000 | 0x007d
+#define NT_STATUS_RANGE_NOT_LOCKED 0xC0000000 | 0x007e
+#define NT_STATUS_DISK_FULL 0xC0000000 | 0x007f
+#define NT_STATUS_SERVER_DISABLED 0xC0000000 | 0x0080
+#define NT_STATUS_SERVER_NOT_DISABLED 0xC0000000 | 0x0081
+#define NT_STATUS_TOO_MANY_GUIDS_REQUESTED 0xC0000000 | 0x0082
+#define NT_STATUS_GUIDS_EXHAUSTED 0xC0000000 | 0x0083
+#define NT_STATUS_INVALID_ID_AUTHORITY 0xC0000000 | 0x0084
+#define NT_STATUS_AGENTS_EXHAUSTED 0xC0000000 | 0x0085
+#define NT_STATUS_INVALID_VOLUME_LABEL 0xC0000000 | 0x0086
+#define NT_STATUS_SECTION_NOT_EXTENDED 0xC0000000 | 0x0087
+#define NT_STATUS_NOT_MAPPED_DATA 0xC0000000 | 0x0088
+#define NT_STATUS_RESOURCE_DATA_NOT_FOUND 0xC0000000 | 0x0089
+#define NT_STATUS_RESOURCE_TYPE_NOT_FOUND 0xC0000000 | 0x008a
+#define NT_STATUS_RESOURCE_NAME_NOT_FOUND 0xC0000000 | 0x008b
+#define NT_STATUS_ARRAY_BOUNDS_EXCEEDED 0xC0000000 | 0x008c
+#define NT_STATUS_FLOAT_DENORMAL_OPERAND 0xC0000000 | 0x008d
+#define NT_STATUS_FLOAT_DIVIDE_BY_ZERO 0xC0000000 | 0x008e
+#define NT_STATUS_FLOAT_INEXACT_RESULT 0xC0000000 | 0x008f
+#define NT_STATUS_FLOAT_INVALID_OPERATION 0xC0000000 | 0x0090
+#define NT_STATUS_FLOAT_OVERFLOW 0xC0000000 | 0x0091
+#define NT_STATUS_FLOAT_STACK_CHECK 0xC0000000 | 0x0092
+#define NT_STATUS_FLOAT_UNDERFLOW 0xC0000000 | 0x0093
+#define NT_STATUS_INTEGER_DIVIDE_BY_ZERO 0xC0000000 | 0x0094
+#define NT_STATUS_INTEGER_OVERFLOW 0xC0000000 | 0x0095
+#define NT_STATUS_PRIVILEGED_INSTRUCTION 0xC0000000 | 0x0096
+#define NT_STATUS_TOO_MANY_PAGING_FILES 0xC0000000 | 0x0097
+#define NT_STATUS_FILE_INVALID 0xC0000000 | 0x0098
+#define NT_STATUS_ALLOTTED_SPACE_EXCEEDED 0xC0000000 | 0x0099
+#define NT_STATUS_INSUFFICIENT_RESOURCES 0xC0000000 | 0x009a
+#define NT_STATUS_DFS_EXIT_PATH_FOUND 0xC0000000 | 0x009b
+#define NT_STATUS_DEVICE_DATA_ERROR 0xC0000000 | 0x009c
+#define NT_STATUS_DEVICE_NOT_CONNECTED 0xC0000000 | 0x009d
+#define NT_STATUS_DEVICE_POWER_FAILURE 0xC0000000 | 0x009e
+#define NT_STATUS_FREE_VM_NOT_AT_BASE 0xC0000000 | 0x009f
+#define NT_STATUS_MEMORY_NOT_ALLOCATED 0xC0000000 | 0x00a0
+#define NT_STATUS_WORKING_SET_QUOTA 0xC0000000 | 0x00a1
+#define NT_STATUS_MEDIA_WRITE_PROTECTED 0xC0000000 | 0x00a2
+#define NT_STATUS_DEVICE_NOT_READY 0xC0000000 | 0x00a3
+#define NT_STATUS_INVALID_GROUP_ATTRIBUTES 0xC0000000 | 0x00a4
+#define NT_STATUS_BAD_IMPERSONATION_LEVEL 0xC0000000 | 0x00a5
+#define NT_STATUS_CANT_OPEN_ANONYMOUS 0xC0000000 | 0x00a6
+#define NT_STATUS_BAD_VALIDATION_CLASS 0xC0000000 | 0x00a7
+#define NT_STATUS_BAD_TOKEN_TYPE 0xC0000000 | 0x00a8
+#define NT_STATUS_BAD_MASTER_BOOT_RECORD 0xC0000000 | 0x00a9
+#define NT_STATUS_INSTRUCTION_MISALIGNMENT 0xC0000000 | 0x00aa
+#define NT_STATUS_INSTANCE_NOT_AVAILABLE 0xC0000000 | 0x00ab
+#define NT_STATUS_PIPE_NOT_AVAILABLE 0xC0000000 | 0x00ac
+#define NT_STATUS_INVALID_PIPE_STATE 0xC0000000 | 0x00ad
+#define NT_STATUS_PIPE_BUSY 0xC0000000 | 0x00ae
+#define NT_STATUS_ILLEGAL_FUNCTION 0xC0000000 | 0x00af
+#define NT_STATUS_PIPE_DISCONNECTED 0xC0000000 | 0x00b0
+#define NT_STATUS_PIPE_CLOSING 0xC0000000 | 0x00b1
+#define NT_STATUS_PIPE_CONNECTED 0xC0000000 | 0x00b2
+#define NT_STATUS_PIPE_LISTENING 0xC0000000 | 0x00b3
+#define NT_STATUS_INVALID_READ_MODE 0xC0000000 | 0x00b4
+#define NT_STATUS_IO_TIMEOUT 0xC0000000 | 0x00b5
+#define NT_STATUS_FILE_FORCED_CLOSED 0xC0000000 | 0x00b6
+#define NT_STATUS_PROFILING_NOT_STARTED 0xC0000000 | 0x00b7
+#define NT_STATUS_PROFILING_NOT_STOPPED 0xC0000000 | 0x00b8
+#define NT_STATUS_COULD_NOT_INTERPRET 0xC0000000 | 0x00b9
+#define NT_STATUS_FILE_IS_A_DIRECTORY 0xC0000000 | 0x00ba
+#define NT_STATUS_NOT_SUPPORTED 0xC0000000 | 0x00bb
+#define NT_STATUS_REMOTE_NOT_LISTENING 0xC0000000 | 0x00bc
+#define NT_STATUS_DUPLICATE_NAME 0xC0000000 | 0x00bd
+#define NT_STATUS_BAD_NETWORK_PATH 0xC0000000 | 0x00be
+#define NT_STATUS_NETWORK_BUSY 0xC0000000 | 0x00bf
+#define NT_STATUS_DEVICE_DOES_NOT_EXIST 0xC0000000 | 0x00c0
+#define NT_STATUS_TOO_MANY_COMMANDS 0xC0000000 | 0x00c1
+#define NT_STATUS_ADAPTER_HARDWARE_ERROR 0xC0000000 | 0x00c2
+#define NT_STATUS_INVALID_NETWORK_RESPONSE 0xC0000000 | 0x00c3
+#define NT_STATUS_UNEXPECTED_NETWORK_ERROR 0xC0000000 | 0x00c4
+#define NT_STATUS_BAD_REMOTE_ADAPTER 0xC0000000 | 0x00c5
+#define NT_STATUS_PRINT_QUEUE_FULL 0xC0000000 | 0x00c6
+#define NT_STATUS_NO_SPOOL_SPACE 0xC0000000 | 0x00c7
+#define NT_STATUS_PRINT_CANCELLED 0xC0000000 | 0x00c8
+#define NT_STATUS_NETWORK_NAME_DELETED 0xC0000000 | 0x00c9
+#define NT_STATUS_NETWORK_ACCESS_DENIED 0xC0000000 | 0x00ca
+#define NT_STATUS_BAD_DEVICE_TYPE 0xC0000000 | 0x00cb
+#define NT_STATUS_BAD_NETWORK_NAME 0xC0000000 | 0x00cc
+#define NT_STATUS_TOO_MANY_NAMES 0xC0000000 | 0x00cd
+#define NT_STATUS_TOO_MANY_SESSIONS 0xC0000000 | 0x00ce
+#define NT_STATUS_SHARING_PAUSED 0xC0000000 | 0x00cf
+#define NT_STATUS_REQUEST_NOT_ACCEPTED 0xC0000000 | 0x00d0
+#define NT_STATUS_REDIRECTOR_PAUSED 0xC0000000 | 0x00d1
+#define NT_STATUS_NET_WRITE_FAULT 0xC0000000 | 0x00d2
+#define NT_STATUS_PROFILING_AT_LIMIT 0xC0000000 | 0x00d3
+#define NT_STATUS_NOT_SAME_DEVICE 0xC0000000 | 0x00d4
+#define NT_STATUS_FILE_RENAMED 0xC0000000 | 0x00d5
+#define NT_STATUS_VIRTUAL_CIRCUIT_CLOSED 0xC0000000 | 0x00d6
+#define NT_STATUS_NO_SECURITY_ON_OBJECT 0xC0000000 | 0x00d7
+#define NT_STATUS_CANT_WAIT 0xC0000000 | 0x00d8
+#define NT_STATUS_PIPE_EMPTY 0xC0000000 | 0x00d9
+#define NT_STATUS_CANT_ACCESS_DOMAIN_INFO 0xC0000000 | 0x00da
+#define NT_STATUS_CANT_TERMINATE_SELF 0xC0000000 | 0x00db
+#define NT_STATUS_INVALID_SERVER_STATE 0xC0000000 | 0x00dc
+#define NT_STATUS_INVALID_DOMAIN_STATE 0xC0000000 | 0x00dd
+#define NT_STATUS_INVALID_DOMAIN_ROLE 0xC0000000 | 0x00de
+#define NT_STATUS_NO_SUCH_DOMAIN 0xC0000000 | 0x00df
+#define NT_STATUS_DOMAIN_EXISTS 0xC0000000 | 0x00e0
+#define NT_STATUS_DOMAIN_LIMIT_EXCEEDED 0xC0000000 | 0x00e1
+#define NT_STATUS_OPLOCK_NOT_GRANTED 0xC0000000 | 0x00e2
+#define NT_STATUS_INVALID_OPLOCK_PROTOCOL 0xC0000000 | 0x00e3
+#define NT_STATUS_INTERNAL_DB_CORRUPTION 0xC0000000 | 0x00e4
+#define NT_STATUS_INTERNAL_ERROR 0xC0000000 | 0x00e5
+#define NT_STATUS_GENERIC_NOT_MAPPED 0xC0000000 | 0x00e6
+#define NT_STATUS_BAD_DESCRIPTOR_FORMAT 0xC0000000 | 0x00e7
+#define NT_STATUS_INVALID_USER_BUFFER 0xC0000000 | 0x00e8
+#define NT_STATUS_UNEXPECTED_IO_ERROR 0xC0000000 | 0x00e9
+#define NT_STATUS_UNEXPECTED_MM_CREATE_ERR 0xC0000000 | 0x00ea
+#define NT_STATUS_UNEXPECTED_MM_MAP_ERROR 0xC0000000 | 0x00eb
+#define NT_STATUS_UNEXPECTED_MM_EXTEND_ERR 0xC0000000 | 0x00ec
+#define NT_STATUS_NOT_LOGON_PROCESS 0xC0000000 | 0x00ed
+#define NT_STATUS_LOGON_SESSION_EXISTS 0xC0000000 | 0x00ee
+#define NT_STATUS_INVALID_PARAMETER_1 0xC0000000 | 0x00ef
+#define NT_STATUS_INVALID_PARAMETER_2 0xC0000000 | 0x00f0
+#define NT_STATUS_INVALID_PARAMETER_3 0xC0000000 | 0x00f1
+#define NT_STATUS_INVALID_PARAMETER_4 0xC0000000 | 0x00f2
+#define NT_STATUS_INVALID_PARAMETER_5 0xC0000000 | 0x00f3
+#define NT_STATUS_INVALID_PARAMETER_6 0xC0000000 | 0x00f4
+#define NT_STATUS_INVALID_PARAMETER_7 0xC0000000 | 0x00f5
+#define NT_STATUS_INVALID_PARAMETER_8 0xC0000000 | 0x00f6
+#define NT_STATUS_INVALID_PARAMETER_9 0xC0000000 | 0x00f7
+#define NT_STATUS_INVALID_PARAMETER_10 0xC0000000 | 0x00f8
+#define NT_STATUS_INVALID_PARAMETER_11 0xC0000000 | 0x00f9
+#define NT_STATUS_INVALID_PARAMETER_12 0xC0000000 | 0x00fa
+#define NT_STATUS_REDIRECTOR_NOT_STARTED 0xC0000000 | 0x00fb
+#define NT_STATUS_REDIRECTOR_STARTED 0xC0000000 | 0x00fc
+#define NT_STATUS_STACK_OVERFLOW 0xC0000000 | 0x00fd
+#define NT_STATUS_NO_SUCH_PACKAGE 0xC0000000 | 0x00fe
+#define NT_STATUS_BAD_FUNCTION_TABLE 0xC0000000 | 0x00ff
+#define NT_STATUS_DIRECTORY_NOT_EMPTY 0xC0000000 | 0x0101
+#define NT_STATUS_FILE_CORRUPT_ERROR 0xC0000000 | 0x0102
+#define NT_STATUS_NOT_A_DIRECTORY 0xC0000000 | 0x0103
+#define NT_STATUS_BAD_LOGON_SESSION_STATE 0xC0000000 | 0x0104
+#define NT_STATUS_LOGON_SESSION_COLLISION 0xC0000000 | 0x0105
+#define NT_STATUS_NAME_TOO_LONG 0xC0000000 | 0x0106
+#define NT_STATUS_FILES_OPEN 0xC0000000 | 0x0107
+#define NT_STATUS_CONNECTION_IN_USE 0xC0000000 | 0x0108
+#define NT_STATUS_MESSAGE_NOT_FOUND 0xC0000000 | 0x0109
+#define NT_STATUS_PROCESS_IS_TERMINATING 0xC0000000 | 0x010a
+#define NT_STATUS_INVALID_LOGON_TYPE 0xC0000000 | 0x010b
+#define NT_STATUS_NO_GUID_TRANSLATION 0xC0000000 | 0x010c
+#define NT_STATUS_CANNOT_IMPERSONATE 0xC0000000 | 0x010d
+#define NT_STATUS_IMAGE_ALREADY_LOADED 0xC0000000 | 0x010e
+#define NT_STATUS_ABIOS_NOT_PRESENT 0xC0000000 | 0x010f
+#define NT_STATUS_ABIOS_LID_NOT_EXIST 0xC0000000 | 0x0110
+#define NT_STATUS_ABIOS_LID_ALREADY_OWNED 0xC0000000 | 0x0111
+#define NT_STATUS_ABIOS_NOT_LID_OWNER 0xC0000000 | 0x0112
+#define NT_STATUS_ABIOS_INVALID_COMMAND 0xC0000000 | 0x0113
+#define NT_STATUS_ABIOS_INVALID_LID 0xC0000000 | 0x0114
+#define NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE 0xC0000000 | 0x0115
+#define NT_STATUS_ABIOS_INVALID_SELECTOR 0xC0000000 | 0x0116
+#define NT_STATUS_NO_LDT 0xC0000000 | 0x0117
+#define NT_STATUS_INVALID_LDT_SIZE 0xC0000000 | 0x0118
+#define NT_STATUS_INVALID_LDT_OFFSET 0xC0000000 | 0x0119
+#define NT_STATUS_INVALID_LDT_DESCRIPTOR 0xC0000000 | 0x011a
+#define NT_STATUS_INVALID_IMAGE_NE_FORMAT 0xC0000000 | 0x011b
+#define NT_STATUS_RXACT_INVALID_STATE 0xC0000000 | 0x011c
+#define NT_STATUS_RXACT_COMMIT_FAILURE 0xC0000000 | 0x011d
+#define NT_STATUS_MAPPED_FILE_SIZE_ZERO 0xC0000000 | 0x011e
+#define NT_STATUS_TOO_MANY_OPENED_FILES 0xC0000000 | 0x011f
+#define NT_STATUS_CANCELLED 0xC0000000 | 0x0120
+#define NT_STATUS_CANNOT_DELETE 0xC0000000 | 0x0121
+#define NT_STATUS_INVALID_COMPUTER_NAME 0xC0000000 | 0x0122
+#define NT_STATUS_FILE_DELETED 0xC0000000 | 0x0123
+#define NT_STATUS_SPECIAL_ACCOUNT 0xC0000000 | 0x0124
+#define NT_STATUS_SPECIAL_GROUP 0xC0000000 | 0x0125
+#define NT_STATUS_SPECIAL_USER 0xC0000000 | 0x0126
+#define NT_STATUS_MEMBERS_PRIMARY_GROUP 0xC0000000 | 0x0127
+#define NT_STATUS_FILE_CLOSED 0xC0000000 | 0x0128
+#define NT_STATUS_TOO_MANY_THREADS 0xC0000000 | 0x0129
+#define NT_STATUS_THREAD_NOT_IN_PROCESS 0xC0000000 | 0x012a
+#define NT_STATUS_TOKEN_ALREADY_IN_USE 0xC0000000 | 0x012b
+#define NT_STATUS_PAGEFILE_QUOTA_EXCEEDED 0xC0000000 | 0x012c
+#define NT_STATUS_COMMITMENT_LIMIT 0xC0000000 | 0x012d
+#define NT_STATUS_INVALID_IMAGE_LE_FORMAT 0xC0000000 | 0x012e
+#define NT_STATUS_INVALID_IMAGE_NOT_MZ 0xC0000000 | 0x012f
+#define NT_STATUS_INVALID_IMAGE_PROTECT 0xC0000000 | 0x0130
+#define NT_STATUS_INVALID_IMAGE_WIN_16 0xC0000000 | 0x0131
+#define NT_STATUS_LOGON_SERVER_CONFLICT 0xC0000000 | 0x0132
+#define NT_STATUS_TIME_DIFFERENCE_AT_DC 0xC0000000 | 0x0133
+#define NT_STATUS_SYNCHRONIZATION_REQUIRED 0xC0000000 | 0x0134
+#define NT_STATUS_DLL_NOT_FOUND 0xC0000000 | 0x0135
+#define NT_STATUS_OPEN_FAILED 0xC0000000 | 0x0136
+#define NT_STATUS_IO_PRIVILEGE_FAILED 0xC0000000 | 0x0137
+#define NT_STATUS_ORDINAL_NOT_FOUND 0xC0000000 | 0x0138
+#define NT_STATUS_ENTRYPOINT_NOT_FOUND 0xC0000000 | 0x0139
+#define NT_STATUS_CONTROL_C_EXIT 0xC0000000 | 0x013a
+#define NT_STATUS_LOCAL_DISCONNECT 0xC0000000 | 0x013b
+#define NT_STATUS_REMOTE_DISCONNECT 0xC0000000 | 0x013c
+#define NT_STATUS_REMOTE_RESOURCES 0xC0000000 | 0x013d
+#define NT_STATUS_LINK_FAILED 0xC0000000 | 0x013e
+#define NT_STATUS_LINK_TIMEOUT 0xC0000000 | 0x013f
+#define NT_STATUS_INVALID_CONNECTION 0xC0000000 | 0x0140
+#define NT_STATUS_INVALID_ADDRESS 0xC0000000 | 0x0141
+#define NT_STATUS_DLL_INIT_FAILED 0xC0000000 | 0x0142
+#define NT_STATUS_MISSING_SYSTEMFILE 0xC0000000 | 0x0143
+#define NT_STATUS_UNHANDLED_EXCEPTION 0xC0000000 | 0x0144
+#define NT_STATUS_APP_INIT_FAILURE 0xC0000000 | 0x0145
+#define NT_STATUS_PAGEFILE_CREATE_FAILED 0xC0000000 | 0x0146
+#define NT_STATUS_NO_PAGEFILE 0xC0000000 | 0x0147
+#define NT_STATUS_INVALID_LEVEL 0xC0000000 | 0x0148
+#define NT_STATUS_WRONG_PASSWORD_CORE 0xC0000000 | 0x0149
+#define NT_STATUS_ILLEGAL_FLOAT_CONTEXT 0xC0000000 | 0x014a
+#define NT_STATUS_PIPE_BROKEN 0xC0000000 | 0x014b
+#define NT_STATUS_REGISTRY_CORRUPT 0xC0000000 | 0x014c
+#define NT_STATUS_REGISTRY_IO_FAILED 0xC0000000 | 0x014d
+#define NT_STATUS_NO_EVENT_PAIR 0xC0000000 | 0x014e
+#define NT_STATUS_UNRECOGNIZED_VOLUME 0xC0000000 | 0x014f
+#define NT_STATUS_SERIAL_NO_DEVICE_INITED 0xC0000000 | 0x0150
+#define NT_STATUS_NO_SUCH_ALIAS 0xC0000000 | 0x0151
+#define NT_STATUS_MEMBER_NOT_IN_ALIAS 0xC0000000 | 0x0152
+#define NT_STATUS_MEMBER_IN_ALIAS 0xC0000000 | 0x0153
+#define NT_STATUS_ALIAS_EXISTS 0xC0000000 | 0x0154
+#define NT_STATUS_LOGON_NOT_GRANTED 0xC0000000 | 0x0155
+#define NT_STATUS_TOO_MANY_SECRETS 0xC0000000 | 0x0156
+#define NT_STATUS_SECRET_TOO_LONG 0xC0000000 | 0x0157
+#define NT_STATUS_INTERNAL_DB_ERROR 0xC0000000 | 0x0158
+#define NT_STATUS_FULLSCREEN_MODE 0xC0000000 | 0x0159
+#define NT_STATUS_TOO_MANY_CONTEXT_IDS 0xC0000000 | 0x015a
+#define NT_STATUS_LOGON_TYPE_NOT_GRANTED 0xC0000000 | 0x015b
+#define NT_STATUS_NOT_REGISTRY_FILE 0xC0000000 | 0x015c
+#define NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED 0xC0000000 | 0x015d
+#define NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR 0xC0000000 | 0x015e
+#define NT_STATUS_FT_MISSING_MEMBER 0xC0000000 | 0x015f
+#define NT_STATUS_ILL_FORMED_SERVICE_ENTRY 0xC0000000 | 0x0160
+#define NT_STATUS_ILLEGAL_CHARACTER 0xC0000000 | 0x0161
+#define NT_STATUS_UNMAPPABLE_CHARACTER 0xC0000000 | 0x0162
+#define NT_STATUS_UNDEFINED_CHARACTER 0xC0000000 | 0x0163
+#define NT_STATUS_FLOPPY_VOLUME 0xC0000000 | 0x0164
+#define NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND 0xC0000000 | 0x0165
+#define NT_STATUS_FLOPPY_WRONG_CYLINDER 0xC0000000 | 0x0166
+#define NT_STATUS_FLOPPY_UNKNOWN_ERROR 0xC0000000 | 0x0167
+#define NT_STATUS_FLOPPY_BAD_REGISTERS 0xC0000000 | 0x0168
+#define NT_STATUS_DISK_RECALIBRATE_FAILED 0xC0000000 | 0x0169
+#define NT_STATUS_DISK_OPERATION_FAILED 0xC0000000 | 0x016a
+#define NT_STATUS_DISK_RESET_FAILED 0xC0000000 | 0x016b
+#define NT_STATUS_SHARED_IRQ_BUSY 0xC0000000 | 0x016c
+#define NT_STATUS_FT_ORPHANING 0xC0000000 | 0x016d
+#define NT_STATUS_PARTITION_FAILURE 0xC0000000 | 0x0172
+#define NT_STATUS_INVALID_BLOCK_LENGTH 0xC0000000 | 0x0173
+#define NT_STATUS_DEVICE_NOT_PARTITIONED 0xC0000000 | 0x0174
+#define NT_STATUS_UNABLE_TO_LOCK_MEDIA 0xC0000000 | 0x0175
+#define NT_STATUS_UNABLE_TO_UNLOAD_MEDIA 0xC0000000 | 0x0176
+#define NT_STATUS_EOM_OVERFLOW 0xC0000000 | 0x0177
+#define NT_STATUS_NO_MEDIA 0xC0000000 | 0x0178
+#define NT_STATUS_NO_SUCH_MEMBER 0xC0000000 | 0x017a
+#define NT_STATUS_INVALID_MEMBER 0xC0000000 | 0x017b
+#define NT_STATUS_KEY_DELETED 0xC0000000 | 0x017c
+#define NT_STATUS_NO_LOG_SPACE 0xC0000000 | 0x017d
+#define NT_STATUS_TOO_MANY_SIDS 0xC0000000 | 0x017e
+#define NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED 0xC0000000 | 0x017f
+#define NT_STATUS_KEY_HAS_CHILDREN 0xC0000000 | 0x0180
+#define NT_STATUS_CHILD_MUST_BE_VOLATILE 0xC0000000 | 0x0181
+#define NT_STATUS_DEVICE_CONFIGURATION_ERROR 0xC0000000 | 0x0182
+#define NT_STATUS_DRIVER_INTERNAL_ERROR 0xC0000000 | 0x0183
+#define NT_STATUS_INVALID_DEVICE_STATE 0xC0000000 | 0x0184
+#define NT_STATUS_IO_DEVICE_ERROR 0xC0000000 | 0x0185
+#define NT_STATUS_DEVICE_PROTOCOL_ERROR 0xC0000000 | 0x0186
+#define NT_STATUS_BACKUP_CONTROLLER 0xC0000000 | 0x0187
+#define NT_STATUS_LOG_FILE_FULL 0xC0000000 | 0x0188
+#define NT_STATUS_TOO_LATE 0xC0000000 | 0x0189
+#define NT_STATUS_NO_TRUST_LSA_SECRET 0xC0000000 | 0x018a
+#define NT_STATUS_NO_TRUST_SAM_ACCOUNT 0xC0000000 | 0x018b
+#define NT_STATUS_TRUSTED_DOMAIN_FAILURE 0xC0000000 | 0x018c
+#define NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE 0xC0000000 | 0x018d
+#define NT_STATUS_EVENTLOG_FILE_CORRUPT 0xC0000000 | 0x018e
+#define NT_STATUS_EVENTLOG_CANT_START 0xC0000000 | 0x018f
+#define NT_STATUS_TRUST_FAILURE 0xC0000000 | 0x0190
+#define NT_STATUS_MUTANT_LIMIT_EXCEEDED 0xC0000000 | 0x0191
+#define NT_STATUS_NETLOGON_NOT_STARTED 0xC0000000 | 0x0192
+#define NT_STATUS_ACCOUNT_EXPIRED 0xC0000000 | 0x0193
+#define NT_STATUS_POSSIBLE_DEADLOCK 0xC0000000 | 0x0194
+#define NT_STATUS_NETWORK_CREDENTIAL_CONFLICT 0xC0000000 | 0x0195
+#define NT_STATUS_REMOTE_SESSION_LIMIT 0xC0000000 | 0x0196
+#define NT_STATUS_EVENTLOG_FILE_CHANGED 0xC0000000 | 0x0197
+#define NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT 0xC0000000 | 0x0198
+#define NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT 0xC0000000 | 0x0199
+#define NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT 0xC0000000 | 0x019a
+#define NT_STATUS_DOMAIN_TRUST_INCONSISTENT 0xC0000000 | 0x019b
+#define NT_STATUS_FS_DRIVER_REQUIRED 0xC0000000 | 0x019c
+#define NT_STATUS_NO_USER_SESSION_KEY 0xC0000000 | 0x0202
+#define NT_STATUS_USER_SESSION_DELETED 0xC0000000 | 0x0203
+#define NT_STATUS_RESOURCE_LANG_NOT_FOUND 0xC0000000 | 0x0204
+#define NT_STATUS_INSUFF_SERVER_RESOURCES 0xC0000000 | 0x0205
+#define NT_STATUS_INVALID_BUFFER_SIZE 0xC0000000 | 0x0206
+#define NT_STATUS_INVALID_ADDRESS_COMPONENT 0xC0000000 | 0x0207
+#define NT_STATUS_INVALID_ADDRESS_WILDCARD 0xC0000000 | 0x0208
+#define NT_STATUS_TOO_MANY_ADDRESSES 0xC0000000 | 0x0209
+#define NT_STATUS_ADDRESS_ALREADY_EXISTS 0xC0000000 | 0x020a
+#define NT_STATUS_ADDRESS_CLOSED 0xC0000000 | 0x020b
+#define NT_STATUS_CONNECTION_DISCONNECTED 0xC0000000 | 0x020c
+#define NT_STATUS_CONNECTION_RESET 0xC0000000 | 0x020d
+#define NT_STATUS_TOO_MANY_NODES 0xC0000000 | 0x020e
+#define NT_STATUS_TRANSACTION_ABORTED 0xC0000000 | 0x020f
+#define NT_STATUS_TRANSACTION_TIMED_OUT 0xC0000000 | 0x0210
+#define NT_STATUS_TRANSACTION_NO_RELEASE 0xC0000000 | 0x0211
+#define NT_STATUS_TRANSACTION_NO_MATCH 0xC0000000 | 0x0212
+#define NT_STATUS_TRANSACTION_RESPONDED 0xC0000000 | 0x0213
+#define NT_STATUS_TRANSACTION_INVALID_ID 0xC0000000 | 0x0214
+#define NT_STATUS_TRANSACTION_INVALID_TYPE 0xC0000000 | 0x0215
+#define NT_STATUS_NOT_SERVER_SESSION 0xC0000000 | 0x0216
+#define NT_STATUS_NOT_CLIENT_SESSION 0xC0000000 | 0x0217
+#define NT_STATUS_CANNOT_LOAD_REGISTRY_FILE 0xC0000000 | 0x0218
+#define NT_STATUS_DEBUG_ATTACH_FAILED 0xC0000000 | 0x0219
+#define NT_STATUS_SYSTEM_PROCESS_TERMINATED 0xC0000000 | 0x021a
+#define NT_STATUS_DATA_NOT_ACCEPTED 0xC0000000 | 0x021b
+#define NT_STATUS_NO_BROWSER_SERVERS_FOUND 0xC0000000 | 0x021c
+#define NT_STATUS_VDM_HARD_ERROR 0xC0000000 | 0x021d
+#define NT_STATUS_DRIVER_CANCEL_TIMEOUT 0xC0000000 | 0x021e
+#define NT_STATUS_REPLY_MESSAGE_MISMATCH 0xC0000000 | 0x021f
+#define NT_STATUS_MAPPED_ALIGNMENT 0xC0000000 | 0x0220
+#define NT_STATUS_IMAGE_CHECKSUM_MISMATCH 0xC0000000 | 0x0221
+#define NT_STATUS_LOST_WRITEBEHIND_DATA 0xC0000000 | 0x0222
+#define NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID 0xC0000000 | 0x0223
+#define NT_STATUS_PASSWORD_MUST_CHANGE 0xC0000000 | 0x0224
+#define NT_STATUS_NOT_FOUND 0xC0000000 | 0x0225
+#define NT_STATUS_NOT_TINY_STREAM 0xC0000000 | 0x0226
+#define NT_STATUS_RECOVERY_FAILURE 0xC0000000 | 0x0227
+#define NT_STATUS_STACK_OVERFLOW_READ 0xC0000000 | 0x0228
+#define NT_STATUS_FAIL_CHECK 0xC0000000 | 0x0229
+#define NT_STATUS_DUPLICATE_OBJECTID 0xC0000000 | 0x022a
+#define NT_STATUS_OBJECTID_EXISTS 0xC0000000 | 0x022b
+#define NT_STATUS_CONVERT_TO_LARGE 0xC0000000 | 0x022c
+#define NT_STATUS_RETRY 0xC0000000 | 0x022d
+#define NT_STATUS_FOUND_OUT_OF_SCOPE 0xC0000000 | 0x022e
+#define NT_STATUS_ALLOCATE_BUCKET 0xC0000000 | 0x022f
+#define NT_STATUS_PROPSET_NOT_FOUND 0xC0000000 | 0x0230
+#define NT_STATUS_MARSHALL_OVERFLOW 0xC0000000 | 0x0231
+#define NT_STATUS_INVALID_VARIANT 0xC0000000 | 0x0232
+#define NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND 0xC0000000 | 0x0233
+#define NT_STATUS_ACCOUNT_LOCKED_OUT 0xC0000000 | 0x0234
+#define NT_STATUS_HANDLE_NOT_CLOSABLE 0xC0000000 | 0x0235
+#define NT_STATUS_CONNECTION_REFUSED 0xC0000000 | 0x0236
+#define NT_STATUS_GRACEFUL_DISCONNECT 0xC0000000 | 0x0237
+#define NT_STATUS_ADDRESS_ALREADY_ASSOCIATED 0xC0000000 | 0x0238
+#define NT_STATUS_ADDRESS_NOT_ASSOCIATED 0xC0000000 | 0x0239
+#define NT_STATUS_CONNECTION_INVALID 0xC0000000 | 0x023a
+#define NT_STATUS_CONNECTION_ACTIVE 0xC0000000 | 0x023b
+#define NT_STATUS_NETWORK_UNREACHABLE 0xC0000000 | 0x023c
+#define NT_STATUS_HOST_UNREACHABLE 0xC0000000 | 0x023d
+#define NT_STATUS_PROTOCOL_UNREACHABLE 0xC0000000 | 0x023e
+#define NT_STATUS_PORT_UNREACHABLE 0xC0000000 | 0x023f
+#define NT_STATUS_REQUEST_ABORTED 0xC0000000 | 0x0240
+#define NT_STATUS_CONNECTION_ABORTED 0xC0000000 | 0x0241
+#define NT_STATUS_BAD_COMPRESSION_BUFFER 0xC0000000 | 0x0242
+#define NT_STATUS_USER_MAPPED_FILE 0xC0000000 | 0x0243
+#define NT_STATUS_AUDIT_FAILED 0xC0000000 | 0x0244
+#define NT_STATUS_TIMER_RESOLUTION_NOT_SET 0xC0000000 | 0x0245
+#define NT_STATUS_CONNECTION_COUNT_LIMIT 0xC0000000 | 0x0246
+#define NT_STATUS_LOGIN_TIME_RESTRICTION 0xC0000000 | 0x0247
+#define NT_STATUS_LOGIN_WKSTA_RESTRICTION 0xC0000000 | 0x0248
+#define NT_STATUS_IMAGE_MP_UP_MISMATCH 0xC0000000 | 0x0249
+#define NT_STATUS_INSUFFICIENT_LOGON_INFO 0xC0000000 | 0x0250
+#define NT_STATUS_BAD_DLL_ENTRYPOINT 0xC0000000 | 0x0251
+#define NT_STATUS_BAD_SERVICE_ENTRYPOINT 0xC0000000 | 0x0252
+#define NT_STATUS_LPC_REPLY_LOST 0xC0000000 | 0x0253
+#define NT_STATUS_IP_ADDRESS_CONFLICT1 0xC0000000 | 0x0254
+#define NT_STATUS_IP_ADDRESS_CONFLICT2 0xC0000000 | 0x0255
+#define NT_STATUS_REGISTRY_QUOTA_LIMIT 0xC0000000 | 0x0256
+#define NT_STATUS_PATH_NOT_COVERED 0xC0000000 | 0x0257
+#define NT_STATUS_NO_CALLBACK_ACTIVE 0xC0000000 | 0x0258
+#define NT_STATUS_LICENSE_QUOTA_EXCEEDED 0xC0000000 | 0x0259
+#define NT_STATUS_PWD_TOO_SHORT 0xC0000000 | 0x025a
+#define NT_STATUS_PWD_TOO_RECENT 0xC0000000 | 0x025b
+#define NT_STATUS_PWD_HISTORY_CONFLICT 0xC0000000 | 0x025c
+#define NT_STATUS_PLUGPLAY_NO_DEVICE 0xC0000000 | 0x025e
+#define NT_STATUS_UNSUPPORTED_COMPRESSION 0xC0000000 | 0x025f
+#define NT_STATUS_INVALID_HW_PROFILE 0xC0000000 | 0x0260
+#define NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH 0xC0000000 | 0x0261
+#define NT_STATUS_DRIVER_ORDINAL_NOT_FOUND 0xC0000000 | 0x0262
+#define NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND 0xC0000000 | 0x0263
+#define NT_STATUS_RESOURCE_NOT_OWNED 0xC0000000 | 0x0264
+#define NT_STATUS_TOO_MANY_LINKS 0xC0000000 | 0x0265
+#define NT_STATUS_QUOTA_LIST_INCONSISTENT 0xC0000000 | 0x0266
+#define NT_STATUS_FILE_IS_OFFLINE 0xC0000000 | 0x0267
+#define NT_STATUS_NO_SUCH_JOB 0xC0000000 | 0xEDE	/* scheduler */
+
+#endif				/* _NTERR_H */
diff --git a/fs/cifs/ntlmssp.h b/fs/cifs/ntlmssp.h
new file mode 100644
index 0000000..6facb41
--- /dev/null
+++ b/fs/cifs/ntlmssp.h
@@ -0,0 +1,101 @@
+/*
+ *   fs/cifs/ntlmssp.h
+ *
+ *   Copyright (c) International Business Machines  Corp., 2002
+ *   Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ */
+
+#pragma pack(1)
+
+#define NTLMSSP_SIGNATURE "NTLMSSP"
+/* Message Types */
+#define NtLmNegotiate     cpu_to_le32(1)
+#define NtLmChallenge     cpu_to_le32(2)
+#define NtLmAuthenticate  cpu_to_le32(3)
+#define UnknownMessage    cpu_to_le32(8)
+
+/* Negotiate Flags */
+#define NTLMSSP_NEGOTIATE_UNICODE       0x01	// Text strings are in unicode
+#define NTLMSSP_NEGOTIATE_OEM           0x02	// Text strings are in OEM
+#define NTLMSSP_REQUEST_TARGET          0x04	// Server return its auth realm
+#define NTLMSSP_NEGOTIATE_SIGN        0x0010	// Request signature capability
+#define NTLMSSP_NEGOTIATE_SEAL        0x0020	// Request confidentiality
+#define NTLMSSP_NEGOTIATE_DGRAM       0x0040
+#define NTLMSSP_NEGOTIATE_LM_KEY      0x0080 // Use LM session key for sign/seal
+#define NTLMSSP_NEGOTIATE_NTLM        0x0200	// NTLM authentication
+#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000
+#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x2000
+#define NTLMSSP_NEGOTIATE_LOCAL_CALL  0x4000	// client/server on same machine
+#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x8000	// Sign for all security levels
+#define NTLMSSP_TARGET_TYPE_DOMAIN   0x10000
+#define NTLMSSP_TARGET_TYPE_SERVER   0x20000
+#define NTLMSSP_TARGET_TYPE_SHARE    0x40000
+#define NTLMSSP_NEGOTIATE_NTLMV2     0x80000
+#define NTLMSSP_REQUEST_INIT_RESP   0x100000
+#define NTLMSSP_REQUEST_ACCEPT_RESP 0x200000
+#define NTLMSSP_REQUEST_NOT_NT_KEY  0x400000
+#define NTLMSSP_NEGOTIATE_TARGET_INFO 0x800000
+#define NTLMSSP_NEGOTIATE_128     0x20000000
+#define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000
+#define NTLMSSP_NEGOTIATE_56      0x80000000
+
+/* Although typedefs are not commonly used for structure definitions */
+/* in the Linux kernel, in this particular case they are useful      */
+/* to more closely match the standards document for NTLMSSP from     */
+/* OpenGroup and to make the code more closely match the standard in */
+/* appearance */
+
+typedef struct _SECURITY_BUFFER {
+	__le16 Length;
+	__le16 MaximumLength;
+	__le32 Buffer;		/* offset to buffer */
+} SECURITY_BUFFER;
+
+typedef struct _NEGOTIATE_MESSAGE {
+	__u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
+	__le32 MessageType;     /* 1 */
+	__le32 NegotiateFlags;
+	SECURITY_BUFFER DomainName;	/* RFC 1001 style and ASCII */
+	SECURITY_BUFFER WorkstationName;	/* RFC 1001 and ASCII */
+	char DomainString[0];
+	/* followed by WorkstationString */
+} NEGOTIATE_MESSAGE, *PNEGOTIATE_MESSAGE;
+
+typedef struct _CHALLENGE_MESSAGE {
+	__u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
+	__le32 MessageType;   /* 2 */
+	SECURITY_BUFFER TargetName;
+	__le32 NegotiateFlags;
+	__u8 Challenge[CIFS_CRYPTO_KEY_SIZE];
+	__u8 Reserved[8];
+	SECURITY_BUFFER TargetInfoArray;
+} CHALLENGE_MESSAGE, *PCHALLENGE_MESSAGE;
+
+typedef struct _AUTHENTICATE_MESSAGE {
+	__u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
+	__le32 MessageType;  /* 3 */
+	SECURITY_BUFFER LmChallengeResponse;
+	SECURITY_BUFFER NtChallengeResponse;
+	SECURITY_BUFFER DomainName;
+	SECURITY_BUFFER UserName;
+	SECURITY_BUFFER WorkstationName;
+	SECURITY_BUFFER SessionKey;
+	__le32 NegotiateFlags;
+	char UserString[0];
+} AUTHENTICATE_MESSAGE, *PAUTHENTICATE_MESSAGE;
+
+#pragma pack()			/* resume default structure packing */
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
new file mode 100644
index 0000000..f8bea39
--- /dev/null
+++ b/fs/cifs/readdir.c
@@ -0,0 +1,867 @@
+/*
+ *   fs/cifs/readdir.c
+ *
+ *   Directory search handling
+ * 
+ *   Copyright (C) International Business Machines  Corp., 2004
+ *   Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <linux/smp_lock.h>
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_unicode.h"
+#include "cifs_debug.h"
+#include "cifs_fs_sb.h"
+#include "cifsfs.h"
+
+/* BB fixme - add debug wrappers around this function to disable it fixme BB */
+/* static void dump_cifs_file_struct(struct file *file, char *label)
+{
+	struct cifsFileInfo * cf;
+
+	if(file) {
+		cf = file->private_data;
+		if(cf == NULL) {
+			cFYI(1,("empty cifs private file data"));
+			return;
+		}
+		if(cf->invalidHandle) {
+			cFYI(1,("invalid handle"));
+		}
+		if(cf->srch_inf.endOfSearch) {
+			cFYI(1,("end of search"));
+		}
+		if(cf->srch_inf.emptyDir) {
+			cFYI(1,("empty dir"));
+		}
+		
+	}
+} */
+
+/* Returns one if new inode created (which therefore needs to be hashed) */
+/* Might check in the future if inode number changed so we can rehash inode */
+static int construct_dentry(struct qstr *qstring, struct file *file,
+	struct inode **ptmp_inode, struct dentry **pnew_dentry)
+{
+	struct dentry *tmp_dentry;
+	struct cifs_sb_info *cifs_sb;
+	struct cifsTconInfo *pTcon;
+	int rc = 0;
+
+	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(0, (" existing dentry with inode 0x%p", tmp_dentry->d_inode));
+		*ptmp_inode = tmp_dentry->d_inode;
+/* BB overwrite old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len??*/
+		if(*ptmp_inode == NULL) {
+			*ptmp_inode = new_inode(file->f_dentry->d_sb);
+			if(*ptmp_inode == NULL)
+				return rc;
+			rc = 1;
+			d_instantiate(tmp_dentry, *ptmp_inode);
+		}
+	} else {
+		tmp_dentry = d_alloc(file->f_dentry, qstring);
+		if(tmp_dentry == NULL) {
+			cERROR(1,("Failed allocating dentry"));
+			*ptmp_inode = NULL;
+			return rc;
+		}
+
+		*ptmp_inode = new_inode(file->f_dentry->d_sb);
+		tmp_dentry->d_op = &cifs_dentry_ops;
+		if(*ptmp_inode == NULL)
+			return rc;
+		rc = 1;
+		d_instantiate(tmp_dentry, *ptmp_inode);
+		d_rehash(tmp_dentry);
+	}
+
+	tmp_dentry->d_time = jiffies;
+	*pnew_dentry = tmp_dentry;
+	return rc;
+}
+
+static void fill_in_inode(struct inode *tmp_inode,
+	FILE_DIRECTORY_INFO *pfindData, int *pobject_type)
+{
+	struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
+	struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
+	__u32 attr = le32_to_cpu(pfindData->ExtFileAttributes);
+	__u64 allocation_size = le64_to_cpu(pfindData->AllocationSize);
+	__u64 end_of_file = le64_to_cpu(pfindData->EndOfFile);
+
+	cifsInfo->cifsAttrs = attr;
+	cifsInfo->time = jiffies;
+
+	/* 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));
+	/* treat dos attribute of read-only as read-only mode bit e.g. 555? */
+	/* 2767 perms - indicate mandatory locking */
+		/* BB fill in uid and gid here? with help from winbind? 
+		   or retrieve from NTFS stream extended attribute */
+	if (atomic_read(&cifsInfo->inUse) == 0) {
+		tmp_inode->i_uid = cifs_sb->mnt_uid;
+		tmp_inode->i_gid = cifs_sb->mnt_gid;
+		/* set default mode. will override for dirs below */
+		tmp_inode->i_mode = cifs_sb->mnt_file_mode;
+	}
+
+	cFYI(0,("CIFS FFIRST: Attributes came in as 0x%x",attr));
+	if (attr & ATTR_DIRECTORY) {
+		*pobject_type = DT_DIR;
+		/* override default perms since we do not lock dirs */
+		if(atomic_read(&cifsInfo->inUse) == 0) {
+			tmp_inode->i_mode = cifs_sb->mnt_dir_mode;
+		}
+		tmp_inode->i_mode |= S_IFDIR;
+/* we no longer mark these because we could not follow them */
+/*        } else if (attr & ATTR_REPARSE) {
+                *pobject_type = DT_LNK;
+                tmp_inode->i_mode |= S_IFLNK; */
+	} else {
+		*pobject_type = DT_REG;
+		tmp_inode->i_mode |= S_IFREG;
+		if (attr & ATTR_READONLY)
+			tmp_inode->i_mode &= ~(S_IWUGO);
+	} /* could add code here - to validate if device or weird share type? */
+
+	/* can not fill in nlink here as in qpathinfo version and Unx search */
+	if (atomic_read(&cifsInfo->inUse) == 0) {
+		atomic_set(&cifsInfo->inUse, 1);
+	}
+
+	if (is_size_safe_to_change(cifsInfo)) {
+		/* can not safely change the file size here if the 
+		client is writing to it due to potential races */
+		i_size_write(tmp_inode, end_of_file);
+
+	/* 512 bytes (2**9) is the fake blocksize that must be used */
+	/* for this calculation, even though the reported blocksize is larger */
+		tmp_inode->i_blocks = (512 - 1 + allocation_size) >> 9;
+	}
+
+	if (allocation_size < end_of_file)
+		cFYI(1, ("May be sparse file, allocation less than file size"));
+	cFYI(1,
+	     ("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)) {
+		cFYI(1, (" File inode "));
+		tmp_inode->i_op = &cifs_file_inode_ops;
+		if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
+			tmp_inode->i_fop = &cifs_file_direct_ops;
+		else
+			tmp_inode->i_fop = &cifs_file_ops;
+		tmp_inode->i_data.a_ops = &cifs_addr_ops;
+	} else if (S_ISDIR(tmp_inode->i_mode)) {
+		cFYI(1, (" Directory inode"));
+		tmp_inode->i_op = &cifs_dir_inode_ops;
+		tmp_inode->i_fop = &cifs_dir_ops;
+	} else if (S_ISLNK(tmp_inode->i_mode)) {
+		cFYI(1, (" Symbolic Link inode "));
+		tmp_inode->i_op = &cifs_symlink_inode_ops;
+	} else {
+		cFYI(1, (" Init special inode "));
+		init_special_inode(tmp_inode, tmp_inode->i_mode,
+				   tmp_inode->i_rdev);
+	}
+}
+
+static void unix_fill_in_inode(struct inode *tmp_inode,
+	FILE_UNIX_INFO *pfindData, int *pobject_type)
+{
+	struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
+	struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
+
+	__u32 type = le32_to_cpu(pfindData->Type);
+	__u64 num_of_bytes = le64_to_cpu(pfindData->NumOfBytes);
+	__u64 end_of_file = le64_to_cpu(pfindData->EndOfFile);
+	cifsInfo->time = jiffies;
+	atomic_inc(&cifsInfo->inUse);
+
+	tmp_inode->i_atime =
+	    cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
+	tmp_inode->i_mtime =
+	    cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastModificationTime));
+	tmp_inode->i_ctime =
+	    cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastStatusChange));
+
+	tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions);
+	if (type == UNIX_FILE) {
+		*pobject_type = DT_REG;
+		tmp_inode->i_mode |= S_IFREG;
+	} else if (type == UNIX_SYMLINK) {
+		*pobject_type = DT_LNK;
+		tmp_inode->i_mode |= S_IFLNK;
+	} else if (type == UNIX_DIR) {
+		*pobject_type = DT_DIR;
+		tmp_inode->i_mode |= S_IFDIR;
+	} else if (type == UNIX_CHARDEV) {
+		*pobject_type = DT_CHR;
+		tmp_inode->i_mode |= S_IFCHR;
+		tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor),
+				le64_to_cpu(pfindData->DevMinor) & MINORMASK);
+	} else if (type == UNIX_BLOCKDEV) {
+		*pobject_type = DT_BLK;
+		tmp_inode->i_mode |= S_IFBLK;
+		tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor),
+				le64_to_cpu(pfindData->DevMinor) & MINORMASK);
+	} else if (type == UNIX_FIFO) {
+		*pobject_type = DT_FIFO;
+		tmp_inode->i_mode |= S_IFIFO;
+	} else if (type == UNIX_SOCKET) {
+		*pobject_type = DT_SOCK;
+		tmp_inode->i_mode |= S_IFSOCK;
+	}
+
+	tmp_inode->i_uid = le64_to_cpu(pfindData->Uid);
+	tmp_inode->i_gid = le64_to_cpu(pfindData->Gid);
+	tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks);
+
+	if (is_size_safe_to_change(cifsInfo)) {
+		/* can not safely change the file size here if the 
+		client is writing to it due to potential races */
+		i_size_write(tmp_inode,end_of_file);
+
+	/* 512 bytes (2**9) is the fake blocksize that must be used */
+	/* for this calculation, not the real blocksize */
+		tmp_inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
+	}
+
+	if (S_ISREG(tmp_inode->i_mode)) {
+		cFYI(1, ("File inode"));
+		tmp_inode->i_op = &cifs_file_inode_ops;
+		if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
+			tmp_inode->i_fop = &cifs_file_direct_ops;
+		else
+			tmp_inode->i_fop = &cifs_file_ops;
+		tmp_inode->i_data.a_ops = &cifs_addr_ops;
+	} else if (S_ISDIR(tmp_inode->i_mode)) {
+		cFYI(1, ("Directory inode"));
+		tmp_inode->i_op = &cifs_dir_inode_ops;
+		tmp_inode->i_fop = &cifs_dir_ops;
+	} else if (S_ISLNK(tmp_inode->i_mode)) {
+		cFYI(1, ("Symbolic Link inode"));
+		tmp_inode->i_op = &cifs_symlink_inode_ops;
+/* tmp_inode->i_fop = *//* do not need to set to anything */
+	} else {
+		cFYI(1, ("Special inode")); 
+		init_special_inode(tmp_inode, tmp_inode->i_mode,
+				   tmp_inode->i_rdev);
+	}
+}
+
+static int initiate_cifs_search(const int xid, struct file *file)
+{
+	int rc = 0;
+	char * full_path;
+	struct cifsFileInfo * cifsFile;
+	struct cifs_sb_info *cifs_sb;
+	struct cifsTconInfo *pTcon;
+
+	if(file->private_data == NULL) {
+		file->private_data = 
+			kmalloc(sizeof(struct cifsFileInfo),GFP_KERNEL);
+	}
+
+	if(file->private_data == NULL) {
+		return -ENOMEM;
+	} else {
+		memset(file->private_data,0,sizeof(struct cifsFileInfo));
+	}
+	cifsFile = file->private_data;
+	cifsFile->invalidHandle = TRUE;
+	cifsFile->srch_inf.endOfSearch = FALSE;
+
+	if(file->f_dentry == NULL)
+		return -ENOENT;
+
+	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+	if(cifs_sb == NULL)
+		return -EINVAL;
+
+	pTcon = cifs_sb->tcon;
+	if(pTcon == NULL)
+		return -EINVAL;
+
+	down(&file->f_dentry->d_sb->s_vfs_rename_sem);
+	full_path = build_wildcard_path_from_dentry(file->f_dentry);
+	up(&file->f_dentry->d_sb->s_vfs_rename_sem);
+
+	if(full_path == NULL) {
+		return -ENOMEM;
+	}
+
+	cFYI(1, ("Full path: %s start at: %lld ", full_path, file->f_pos));
+
+	/* test for Unix extensions */
+	if (pTcon->ses->capabilities & CAP_UNIX) {
+		cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX; 
+	} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
+		cifsFile->srch_inf.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
+	} else /* not srvinos - BB fixme add check for backlevel? */ {
+		cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO;
+	}
+
+	rc = CIFSFindFirst(xid, pTcon,full_path,cifs_sb->local_nls, 
+		&cifsFile->netfid, &cifsFile->srch_inf); 
+	if(rc == 0)
+		cifsFile->invalidHandle = FALSE;
+	kfree(full_path);
+	return rc;
+}
+
+/* return length of unicode string in bytes */
+static int cifs_unicode_bytelen(char *str)
+{
+	int len;
+	__le16 * ustr = (__le16 *)str;
+
+	for(len=0;len <= PATH_MAX;len++) {
+		if(ustr[len] == 0)
+			return len << 1;
+	}
+	cFYI(1,("Unicode string longer than PATH_MAX found"));
+	return len << 1;
+}
+
+static char *nxt_dir_entry(char *old_entry, char *end_of_smb)
+{
+	char * new_entry;
+	FILE_DIRECTORY_INFO * pDirInfo = (FILE_DIRECTORY_INFO *)old_entry;
+
+	new_entry = old_entry + le32_to_cpu(pDirInfo->NextEntryOffset);
+	cFYI(1,("new entry %p old entry %p",new_entry,old_entry));
+	/* validate that new_entry is not past end of SMB */
+	if(new_entry >= end_of_smb) {
+		cFYI(1,("search entry %p began after end of SMB %p old entry %p",
+			new_entry,end_of_smb,old_entry)); 
+		return NULL;
+	} else
+		return new_entry;
+
+}
+
+#define UNICODE_DOT cpu_to_le16(0x2e)
+
+/* return 0 if no match and 1 for . (current directory) and 2 for .. (parent) */
+static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile)
+{
+	int rc = 0;
+	char * filename = NULL;
+	int len = 0; 
+
+	if(cfile->srch_inf.info_level == 0x202) {
+		FILE_UNIX_INFO * pFindData = (FILE_UNIX_INFO *)current_entry;
+		filename = &pFindData->FileName[0];
+		if(cfile->srch_inf.unicode) {
+			len = cifs_unicode_bytelen(filename);
+		} else {
+			/* BB should we make this strnlen of PATH_MAX? */
+			len = strnlen(filename, 5);
+		}
+	} else if(cfile->srch_inf.info_level == 0x101) {
+		FILE_DIRECTORY_INFO * pFindData = 
+			(FILE_DIRECTORY_INFO *)current_entry;
+		filename = &pFindData->FileName[0];
+		len = le32_to_cpu(pFindData->FileNameLength);
+	} else if(cfile->srch_inf.info_level == 0x102) {
+		FILE_FULL_DIRECTORY_INFO * pFindData = 
+			(FILE_FULL_DIRECTORY_INFO *)current_entry;
+		filename = &pFindData->FileName[0];
+		len = le32_to_cpu(pFindData->FileNameLength);
+	} else if(cfile->srch_inf.info_level == 0x105) {
+		SEARCH_ID_FULL_DIR_INFO * pFindData = 
+			(SEARCH_ID_FULL_DIR_INFO *)current_entry;
+		filename = &pFindData->FileName[0];
+		len = le32_to_cpu(pFindData->FileNameLength);
+	} else if(cfile->srch_inf.info_level == 0x104) {
+		FILE_BOTH_DIRECTORY_INFO * pFindData = 
+			(FILE_BOTH_DIRECTORY_INFO *)current_entry;
+		filename = &pFindData->FileName[0];
+		len = le32_to_cpu(pFindData->FileNameLength);
+	} else {
+		cFYI(1,("Unknown findfirst level %d",cfile->srch_inf.info_level));
+	}
+
+	if(filename) {
+		if(cfile->srch_inf.unicode) {
+			__le16 *ufilename = (__le16 *)filename;
+			if(len == 2) {
+				/* check for . */
+				if(ufilename[0] == UNICODE_DOT)
+					rc = 1;
+			} else if(len == 4) {
+				/* check for .. */
+				if((ufilename[0] == UNICODE_DOT)
+				   &&(ufilename[1] == UNICODE_DOT))
+					rc = 2;
+			}
+		} else /* ASCII */ {
+			if(len == 1) {
+				if(filename[0] == '.') 
+					rc = 1;
+			} else if(len == 2) {
+				if((filename[0] == '.') && (filename[1] == '.')) 
+					rc = 2;
+			}
+		}
+	}
+
+	return rc;
+}
+
+/* find the corresponding entry in the search */
+/* Note that the SMB server returns search entries for . and .. which
+   complicates logic here if we choose to parse for them and we do not
+   assume that they are located in the findfirst return buffer.*/
+/* We start counting in the buffer with entry 2 and increment for every
+   entry (do not increment for . or .. entry) */
+static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
+	struct file *file, char **ppCurrentEntry, int *num_to_ret) 
+{
+	int rc = 0;
+	int pos_in_buf = 0;
+	loff_t first_entry_in_buffer;
+	loff_t index_to_find = file->f_pos;
+	struct cifsFileInfo * cifsFile = file->private_data;
+	/* check if index in the buffer */
+	
+	if((cifsFile == NULL) || (ppCurrentEntry == NULL) || (num_to_ret == NULL))
+		return -ENOENT;
+	
+	*ppCurrentEntry = NULL;
+	first_entry_in_buffer = 
+		cifsFile->srch_inf.index_of_last_entry - 
+			cifsFile->srch_inf.entries_in_buffer;
+/*	dump_cifs_file_struct(file, "In fce ");*/
+	if(index_to_find < first_entry_in_buffer) {
+		/* close and restart search */
+		cFYI(1,("search backing up - close and restart search"));
+		cifsFile->invalidHandle = TRUE;
+		CIFSFindClose(xid, pTcon, cifsFile->netfid);
+		kfree(cifsFile->search_resume_name);
+		cifsFile->search_resume_name = NULL;
+		if(cifsFile->srch_inf.ntwrk_buf_start) {
+			cFYI(1,("freeing SMB ff cache buf on search rewind"));
+			cifs_buf_release(cifsFile->srch_inf.ntwrk_buf_start);
+		}
+		rc = initiate_cifs_search(xid,file);
+		if(rc) {
+			cFYI(1,("error %d reinitiating a search on rewind",rc));
+			return rc;
+		}
+	}
+
+	while((index_to_find >= cifsFile->srch_inf.index_of_last_entry) && 
+	      (rc == 0) && (cifsFile->srch_inf.endOfSearch == FALSE)){
+	 	cFYI(1,("calling findnext2"));
+		rc = CIFSFindNext(xid,pTcon,cifsFile->netfid, &cifsFile->srch_inf);
+		if(rc)
+			return -ENOENT;
+	}
+	if(index_to_find < cifsFile->srch_inf.index_of_last_entry) {
+		/* we found the buffer that contains the entry */
+		/* scan and find it */
+		int i;
+		char * current_entry;
+		char * end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + 
+			smbCalcSize((struct smb_hdr *)
+				cifsFile->srch_inf.ntwrk_buf_start);
+/*	dump_cifs_file_struct(file,"found entry in fce "); */
+		first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry
+					- cifsFile->srch_inf.entries_in_buffer;
+		pos_in_buf = index_to_find - first_entry_in_buffer;
+		cFYI(1,("found entry - pos_in_buf %d",pos_in_buf)); 
+		current_entry = cifsFile->srch_inf.srch_entries_start;
+		for(i=0;(i<(pos_in_buf)) && (current_entry != NULL);i++) {
+			/* go entry to next entry figuring out which we need to start with */
+			/* if( . or ..)
+				skip */
+			rc = cifs_entry_is_dot(current_entry,cifsFile);
+			if(rc == 1) /* is . or .. so skip */ {
+				cFYI(1,("Entry is .")); /* BB removeme BB */
+				/* continue; */
+			} else if (rc == 2 ) {
+				cFYI(1,("Entry is ..")); /* BB removeme BB */
+				/* continue; */
+			}
+			current_entry = nxt_dir_entry(current_entry,end_of_smb);
+		}
+		if((current_entry == NULL) && (i < pos_in_buf)) {
+			/* BB fixme - check if we should flag this error */
+			cERROR(1,("reached end of buf searching for pos in buf"
+			  " %d index to find %lld rc %d",
+			  pos_in_buf,index_to_find,rc));
+		}
+		rc = 0;
+		*ppCurrentEntry = current_entry;
+	} else {
+		cFYI(1,("index not in buffer - could not findnext into it"));
+		return 0;
+	}
+
+	if(pos_in_buf >= cifsFile->srch_inf.entries_in_buffer) {
+		cFYI(1,("can not return entries when pos_in_buf beyond last entry"));
+		*num_to_ret = 0;
+	} else
+		*num_to_ret = cifsFile->srch_inf.entries_in_buffer - pos_in_buf;
+/*	dump_cifs_file_struct(file, "end fce ");*/
+
+	return rc;
+}
+
+/* inode num, inode type and filename returned */
+static int cifs_get_name_from_search_buf(struct qstr *pqst,
+	char *current_entry, __u16 level, unsigned int unicode,
+	struct cifs_sb_info * cifs_sb, ino_t *pinum)
+{
+	int rc = 0;
+	unsigned int len = 0;
+	char * filename;
+	struct nls_table * nlt = cifs_sb->local_nls;
+
+	*pinum = 0;
+
+	if(level == SMB_FIND_FILE_UNIX) {
+		FILE_UNIX_INFO * pFindData = (FILE_UNIX_INFO *)current_entry;
+
+		filename = &pFindData->FileName[0];
+		if(unicode) {
+			len = cifs_unicode_bytelen(filename);
+		} else {
+			/* BB should we make this strnlen of PATH_MAX? */
+			len = strnlen(filename, PATH_MAX);
+		}
+
+		/* BB fixme - hash low and high 32 bits if not 64 bit arch BB fixme */
+		if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
+			*pinum = pFindData->UniqueId;
+	} else if(level == SMB_FIND_FILE_DIRECTORY_INFO) {
+		FILE_DIRECTORY_INFO * pFindData = 
+			(FILE_DIRECTORY_INFO *)current_entry;
+		filename = &pFindData->FileName[0];
+		len = le32_to_cpu(pFindData->FileNameLength);
+	} else if(level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
+		FILE_FULL_DIRECTORY_INFO * pFindData = 
+			(FILE_FULL_DIRECTORY_INFO *)current_entry;
+		filename = &pFindData->FileName[0];
+		len = le32_to_cpu(pFindData->FileNameLength);
+	} else if(level == SMB_FIND_FILE_ID_FULL_DIR_INFO) {
+		SEARCH_ID_FULL_DIR_INFO * pFindData = 
+			(SEARCH_ID_FULL_DIR_INFO *)current_entry;
+		filename = &pFindData->FileName[0];
+		len = le32_to_cpu(pFindData->FileNameLength);
+		*pinum = pFindData->UniqueId;
+	} else if(level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
+		FILE_BOTH_DIRECTORY_INFO * pFindData = 
+			(FILE_BOTH_DIRECTORY_INFO *)current_entry;
+		filename = &pFindData->FileName[0];
+		len = le32_to_cpu(pFindData->FileNameLength);
+	} else {
+		cFYI(1,("Unknown findfirst level %d",level));
+		return -EINVAL;
+	}
+	if(unicode) {
+		/* BB fixme - test with long names */
+		/* Note converted filename can be longer than in unicode */
+		pqst->len = cifs_strfromUCS_le((char *)pqst->name,(wchar_t *)filename,len/2,nlt);
+	} else {
+		pqst->name = filename;
+		pqst->len = len;
+	}
+	pqst->hash = full_name_hash(pqst->name,pqst->len);
+/*	cFYI(1,("filldir on %s",pqst->name));  */
+	return rc;
+}
+
+static int cifs_filldir(char *pfindEntry, struct file *file,
+	filldir_t filldir, void *direntry, char *scratch_buf)
+{
+	int rc = 0;
+	struct qstr qstring;
+	struct cifsFileInfo * pCifsF;
+	unsigned obj_type;
+	ino_t  inum;
+	struct cifs_sb_info * cifs_sb;
+	struct inode *tmp_inode;
+	struct dentry *tmp_dentry;
+
+	/* get filename and len into qstring */
+	/* get dentry */
+	/* decide whether to create and populate ionde */
+	if((direntry == NULL) || (file == NULL))
+		return -EINVAL;
+
+	pCifsF = file->private_data;
+	
+	if((scratch_buf == NULL) || (pfindEntry == NULL) || (pCifsF == NULL))
+		return -ENOENT;
+
+	if(file->f_dentry == NULL)
+		return -ENOENT;
+
+	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+
+	qstring.name = scratch_buf;
+	rc = cifs_get_name_from_search_buf(&qstring,pfindEntry,
+			pCifsF->srch_inf.info_level,
+			pCifsF->srch_inf.unicode,cifs_sb,
+			&inum /* returned */);
+
+	if(rc)
+		return rc;
+
+	rc = construct_dentry(&qstring,file,&tmp_inode, &tmp_dentry);
+	if((tmp_inode == NULL) || (tmp_dentry == NULL))
+		return -ENOMEM;
+
+	if(rc) {
+		/* inode created, we need to hash it with right inode number */
+		if(inum != 0) {
+			/* BB fixme - hash the 2 32 quantities bits together if necessary BB */
+			tmp_inode->i_ino = inum;
+		}
+		insert_inode_hash(tmp_inode);
+	}
+
+	if(pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX) {
+		unix_fill_in_inode(tmp_inode,(FILE_UNIX_INFO *)pfindEntry,&obj_type);
+	} else {
+		fill_in_inode(tmp_inode,(FILE_DIRECTORY_INFO *)pfindEntry,&obj_type);
+	}
+	
+	rc = filldir(direntry,qstring.name,qstring.len,file->f_pos,tmp_inode->i_ino,obj_type);
+	if(rc) {
+		cFYI(1,("filldir rc = %d",rc));
+	}
+
+	dput(tmp_dentry);
+	return rc;
+}
+
+static int cifs_save_resume_key(const char *current_entry,
+	struct cifsFileInfo *cifsFile)
+{
+	int rc = 0;
+	unsigned int len = 0;
+	__u16 level;
+	char * filename;
+
+	if((cifsFile == NULL) || (current_entry == NULL))
+		return -EINVAL;
+
+	level = cifsFile->srch_inf.info_level;
+
+	if(level == SMB_FIND_FILE_UNIX) {
+		FILE_UNIX_INFO * pFindData = (FILE_UNIX_INFO *)current_entry;
+
+		filename = &pFindData->FileName[0];
+		if(cifsFile->srch_inf.unicode) {
+			len = cifs_unicode_bytelen(filename);
+		} else {
+			/* BB should we make this strnlen of PATH_MAX? */
+			len = strnlen(filename, PATH_MAX);
+		}
+		cifsFile->srch_inf.resume_key = pFindData->ResumeKey;
+	} else if(level == SMB_FIND_FILE_DIRECTORY_INFO) {
+		FILE_DIRECTORY_INFO * pFindData = 
+			(FILE_DIRECTORY_INFO *)current_entry;
+		filename = &pFindData->FileName[0];
+		len = le32_to_cpu(pFindData->FileNameLength);
+		cifsFile->srch_inf.resume_key = pFindData->FileIndex;
+	} else if(level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
+		FILE_FULL_DIRECTORY_INFO * pFindData = 
+			(FILE_FULL_DIRECTORY_INFO *)current_entry;
+		filename = &pFindData->FileName[0];
+		len = le32_to_cpu(pFindData->FileNameLength);
+		cifsFile->srch_inf.resume_key = pFindData->FileIndex;
+	} else if(level == SMB_FIND_FILE_ID_FULL_DIR_INFO) {
+		SEARCH_ID_FULL_DIR_INFO * pFindData = 
+			(SEARCH_ID_FULL_DIR_INFO *)current_entry;
+		filename = &pFindData->FileName[0];
+		len = le32_to_cpu(pFindData->FileNameLength);
+		cifsFile->srch_inf.resume_key = pFindData->FileIndex;
+	} else if(level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
+		FILE_BOTH_DIRECTORY_INFO * pFindData = 
+			(FILE_BOTH_DIRECTORY_INFO *)current_entry;
+		filename = &pFindData->FileName[0];
+		len = le32_to_cpu(pFindData->FileNameLength);
+		cifsFile->srch_inf.resume_key = pFindData->FileIndex;
+	} else {
+		cFYI(1,("Unknown findfirst level %d",level));
+		return -EINVAL;
+	}
+	cifsFile->srch_inf.resume_name_len = len;
+	cifsFile->srch_inf.presume_name = filename;
+	return rc;
+}
+
+int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
+{
+	int rc = 0;
+	int xid,i;
+	struct cifs_sb_info *cifs_sb;
+	struct cifsTconInfo *pTcon;
+	struct cifsFileInfo *cifsFile = NULL;
+	char * current_entry;
+	int num_to_fill = 0;
+	char * tmp_buf = NULL;
+	char * end_of_smb;
+
+	xid = GetXid();
+
+	if(file->f_dentry == NULL) {
+		FreeXid(xid);
+		return -EIO;
+	}
+/*	dump_cifs_file_struct(file, "Begin rdir "); */
+
+	cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+	pTcon = cifs_sb->tcon;
+	if(pTcon == NULL)
+		return -EINVAL;
+
+/*	cFYI(1,("readdir2 pos: %lld",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, ("Filldir for current dir failed "));
+			rc = -ENOMEM;
+			break;
+		}
+		file->f_pos++; */
+	case 1:
+		/* if (filldir(direntry, "..", 2, file->f_pos,
+		     file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
+			cERROR(1, ("Filldir for parent dir failed "));
+			rc = -ENOMEM;
+			break;
+		}
+		file->f_pos++; */
+	case 2:
+		/* 1) If search is active, 
+			is in current search buffer? 
+			if it before then restart search
+			if after then keep searching till find it */
+
+		if(file->private_data == NULL) {
+			rc = initiate_cifs_search(xid,file);
+			cFYI(1,("initiate cifs search rc %d",rc));
+			if(rc) {
+				FreeXid(xid);
+				return rc;
+			}
+		}
+	default:
+		if(file->private_data == NULL) {
+			rc = -EINVAL;
+			FreeXid(xid);
+			return rc;
+		}
+		cifsFile = file->private_data;
+		if (cifsFile->srch_inf.endOfSearch) {
+			if(cifsFile->srch_inf.emptyDir) {
+				cFYI(1, ("End of search, empty dir"));
+				rc = 0;
+				break;
+			}
+		} /* else {
+			cifsFile->invalidHandle = TRUE;
+			CIFSFindClose(xid, pTcon, cifsFile->netfid);
+		} 
+		kfree(cifsFile->search_resume_name);
+		cifsFile->search_resume_name = NULL; */
+
+		/* BB account for . and .. in f_pos as special case */
+		/* dump_cifs_file_struct(file, "rdir after default ");*/
+
+		rc = find_cifs_entry(xid,pTcon, file,
+				&current_entry,&num_to_fill);
+		if(rc) {
+			cFYI(1,("fce error %d",rc)); 
+			goto rddir2_exit;
+		} else if (current_entry != NULL) {
+			cFYI(1,("entry %lld found",file->f_pos));
+		} else {
+			cFYI(1,("could not find entry"));
+			goto rddir2_exit;
+		}
+		cFYI(1,("loop through %d times filling dir for net buf %p",
+			num_to_fill,cifsFile->srch_inf.ntwrk_buf_start)); 
+		end_of_smb = cifsFile->srch_inf.ntwrk_buf_start +
+			smbCalcSize((struct smb_hdr *)
+				    cifsFile->srch_inf.ntwrk_buf_start);
+		tmp_buf = kmalloc(NAME_MAX+1,GFP_KERNEL);
+		for(i=0;(i<num_to_fill) && (rc == 0);i++) {
+			if(current_entry == NULL) {
+				/* evaluate whether this case is an error */
+				cERROR(1,("past end of SMB num to fill %d i %d",
+					  num_to_fill, i));
+				break;
+			}
+
+			/* BB FIXME - need to enable the below code BB */
+
+		/* if((!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) ||
+			   (cifsFile->srch_inf.info_level != 
+				   something that supports server inodes)) {
+				create dentry
+				create inode
+				fill in inode new_inode (getting local i_ino)
+			}
+			also create local inode for performance reasons (so we 
+			have a cache of inode metadata) unless this new mount 
+			parm says otherwise */
+
+			rc = cifs_filldir(current_entry, file, 
+					filldir, direntry,tmp_buf);
+			file->f_pos++;
+			if(file->f_pos == cifsFile->srch_inf.index_of_last_entry) {
+				cFYI(1,("last entry in buf at pos %lld %s",
+					file->f_pos,tmp_buf)); /* BB removeme BB */
+				cifs_save_resume_key(current_entry,cifsFile);
+				break;
+			} else 
+				current_entry = nxt_dir_entry(current_entry,end_of_smb);
+		}
+		kfree(tmp_buf);
+		break;
+	} /* end switch */
+
+rddir2_exit:
+	/* dump_cifs_file_struct(file, "end rdir ");  */
+	FreeXid(xid);
+	return rc;
+}
diff --git a/fs/cifs/rfc1002pdu.h b/fs/cifs/rfc1002pdu.h
new file mode 100644
index 0000000..806c0ed
--- /dev/null
+++ b/fs/cifs/rfc1002pdu.h
@@ -0,0 +1,79 @@
+/*
+ *   fs/cifs/rfc1002pdu.h
+ *
+ *   Protocol Data Unit definitions for RFC 1001/1002 support
+ *
+ *   Copyright (c) International Business Machines  Corp., 2004
+ *   Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ */
+
+#pragma pack(1)
+
+/* NB: unlike smb/cifs packets, the RFC1002 structures are big endian */
+
+	/* RFC 1002 session packet types */
+#define RFC1002_SESSION_MESASAGE 0x00
+#define RFC1002_SESSION_REQUEST  0x81
+#define RFC1002_POSITIVE_SESSION_RESPONSE 0x82
+#define RFC1002_NEGATIVE_SESSION_RESPONSE 0x83
+#define RFC1002_RETARGET_SESSION_RESPONSE 0x83
+#define RFC1002_SESSION_KEEP_ALIVE 0x85
+
+	/* RFC 1002 flags (only one defined */
+#define RFC1002_LENGTH_EXTEND 0x80 /* high order bit of length (ie +64K) */
+
+struct rfc1002_session_packet {
+	__u8	type;
+	__u8	flags;
+	__u16	length;
+	union {
+		struct {
+			__u8 called_len;
+			__u8 called_name[32];
+			__u8 scope1; /* null */
+			__u8 calling_len;
+			__u8 calling_name[32];
+			__u8 scope2; /* null */
+		} session_req;
+		struct {
+			__u32 retarget_ip_addr;
+			__u16 port;
+		} retarget_resp;
+		__u8 neg_ses_resp_error_code;
+		/* POSITIVE_SESSION_RESPONSE packet does not include trailer.
+		SESSION_KEEP_ALIVE packet also does not include a trailer.
+		Trailer for the SESSION_MESSAGE packet is SMB/CIFS header */
+	} trailer;
+};
+
+/* Negative Session Response error codes */
+#define RFC1002_NOT_LISTENING_CALLED  0x80 /* not listening on called name */
+#define RFC1002_NOT_LISTENING_CALLING 0x81 /* not listening on calling name */
+#define RFC1002_NOT_PRESENT           0x82 /* called name not present */
+#define RFC1002_INSUFFICIENT_RESOURCE 0x83
+#define RFC1002_UNSPECIFIED_ERROR     0x8F
+
+/* RFC 1002 Datagram service packets are not defined here as they
+are not needed for the network filesystem client unless we plan on
+implementing broadcast resolution of the server ip address (from
+server netbios name). Currently server names are resolved only via DNS
+(tcp name) or ip address or an /etc/hosts equivalent mapping to ip address.*/
+
+#define DEFAULT_CIFS_CALLED_NAME  "*SMBSERVER      "
+
+#pragma pack()		/* resume default structure packing */
+                                                             
diff --git a/fs/cifs/smbdes.c b/fs/cifs/smbdes.c
new file mode 100644
index 0000000..efaa044
--- /dev/null
+++ b/fs/cifs/smbdes.c
@@ -0,0 +1,412 @@
+/* 
+   Unix SMB/Netbios implementation.
+   Version 1.9.
+
+   a partial implementation of DES designed for use in the 
+   SMB authentication protocol
+
+   Copyright (C) Andrew Tridgell 1998
+   Modified by Steve French (sfrench@us.ibm.com) 2002,2004
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/* NOTES: 
+
+   This code makes no attempt to be fast! In fact, it is a very
+   slow implementation 
+
+   This code is NOT a complete DES implementation. It implements only
+   the minimum necessary for SMB authentication, as used by all SMB
+   products (including every copy of Microsoft Windows95 ever sold)
+
+   In particular, it can only do a unchained forward DES pass. This
+   means it is not possible to use this code for encryption/decryption
+   of data, instead it is only useful as a "hash" algorithm.
+
+   There is no entry point into this code that allows normal DES operation.
+
+   I believe this means that this code does not come under ITAR
+   regulations but this is NOT a legal opinion. If you are concerned
+   about the applicability of ITAR regulations to this code then you
+   should confirm it for yourself (and maybe let me know if you come
+   up with a different answer to the one above)
+*/
+#include <linux/slab.h>
+#include "cifsencrypt.h"
+#define uchar unsigned char
+
+static uchar perm1[56] = { 57, 49, 41, 33, 25, 17, 9,
+	1, 58, 50, 42, 34, 26, 18,
+	10, 2, 59, 51, 43, 35, 27,
+	19, 11, 3, 60, 52, 44, 36,
+	63, 55, 47, 39, 31, 23, 15,
+	7, 62, 54, 46, 38, 30, 22,
+	14, 6, 61, 53, 45, 37, 29,
+	21, 13, 5, 28, 20, 12, 4
+};
+
+static uchar perm2[48] = { 14, 17, 11, 24, 1, 5,
+	3, 28, 15, 6, 21, 10,
+	23, 19, 12, 4, 26, 8,
+	16, 7, 27, 20, 13, 2,
+	41, 52, 31, 37, 47, 55,
+	30, 40, 51, 45, 33, 48,
+	44, 49, 39, 56, 34, 53,
+	46, 42, 50, 36, 29, 32
+};
+
+static uchar perm3[64] = { 58, 50, 42, 34, 26, 18, 10, 2,
+	60, 52, 44, 36, 28, 20, 12, 4,
+	62, 54, 46, 38, 30, 22, 14, 6,
+	64, 56, 48, 40, 32, 24, 16, 8,
+	57, 49, 41, 33, 25, 17, 9, 1,
+	59, 51, 43, 35, 27, 19, 11, 3,
+	61, 53, 45, 37, 29, 21, 13, 5,
+	63, 55, 47, 39, 31, 23, 15, 7
+};
+
+static uchar perm4[48] = { 32, 1, 2, 3, 4, 5,
+	4, 5, 6, 7, 8, 9,
+	8, 9, 10, 11, 12, 13,
+	12, 13, 14, 15, 16, 17,
+	16, 17, 18, 19, 20, 21,
+	20, 21, 22, 23, 24, 25,
+	24, 25, 26, 27, 28, 29,
+	28, 29, 30, 31, 32, 1
+};
+
+static uchar perm5[32] = { 16, 7, 20, 21,
+	29, 12, 28, 17,
+	1, 15, 23, 26,
+	5, 18, 31, 10,
+	2, 8, 24, 14,
+	32, 27, 3, 9,
+	19, 13, 30, 6,
+	22, 11, 4, 25
+};
+
+static uchar perm6[64] = { 40, 8, 48, 16, 56, 24, 64, 32,
+	39, 7, 47, 15, 55, 23, 63, 31,
+	38, 6, 46, 14, 54, 22, 62, 30,
+	37, 5, 45, 13, 53, 21, 61, 29,
+	36, 4, 44, 12, 52, 20, 60, 28,
+	35, 3, 43, 11, 51, 19, 59, 27,
+	34, 2, 42, 10, 50, 18, 58, 26,
+	33, 1, 41, 9, 49, 17, 57, 25
+};
+
+static uchar sc[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };
+
+static uchar sbox[8][4][16] = {
+	{{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},
+	 {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},
+	 {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},
+	 {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}},
+
+	{{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},
+	 {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},
+	 {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},
+	 {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}},
+
+	{{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},
+	 {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},
+	 {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},
+	 {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}},
+
+	{{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},
+	 {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},
+	 {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},
+	 {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}},
+
+	{{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},
+	 {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},
+	 {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},
+	 {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}},
+
+	{{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},
+	 {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},
+	 {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},
+	 {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}},
+
+	{{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},
+	 {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},
+	 {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},
+	 {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}},
+
+	{{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},
+	 {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},
+	 {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},
+	 {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}}
+};
+
+static void
+permute(char *out, char *in, uchar * p, int n)
+{
+	int i;
+	for (i = 0; i < n; i++)
+		out[i] = in[p[i] - 1];
+}
+
+static void
+lshift(char *d, int count, int n)
+{
+	char out[64];
+	int i;
+	for (i = 0; i < n; i++)
+		out[i] = d[(i + count) % n];
+	for (i = 0; i < n; i++)
+		d[i] = out[i];
+}
+
+static void
+concat(char *out, char *in1, char *in2, int l1, int l2)
+{
+	while (l1--)
+		*out++ = *in1++;
+	while (l2--)
+		*out++ = *in2++;
+}
+
+static void
+xor(char *out, char *in1, char *in2, int n)
+{
+	int i;
+	for (i = 0; i < n; i++)
+		out[i] = in1[i] ^ in2[i];
+}
+
+static void
+dohash(char *out, char *in, char *key, int forw)
+{
+	int i, j, k;
+	char *pk1;
+	char c[28];
+	char d[28];
+	char *cd;
+	char ki[16][48];
+	char *pd1;
+	char l[32], r[32];
+	char *rl;
+
+	/* Have to reduce stack usage */
+	pk1 = kmalloc(56+56+64+64,GFP_KERNEL);
+	if(pk1 == NULL)
+		return;
+
+	cd = pk1 + 56;
+	pd1= cd  + 56;
+	rl = pd1 + 64;
+
+	permute(pk1, key, perm1, 56);
+
+	for (i = 0; i < 28; i++)
+		c[i] = pk1[i];
+	for (i = 0; i < 28; i++)
+		d[i] = pk1[i + 28];
+
+	for (i = 0; i < 16; i++) {
+		lshift(c, sc[i], 28);
+		lshift(d, sc[i], 28);
+
+		concat(cd, c, d, 28, 28);
+		permute(ki[i], cd, perm2, 48);
+	}
+
+	permute(pd1, in, perm3, 64);
+
+	for (j = 0; j < 32; j++) {
+		l[j] = pd1[j];
+		r[j] = pd1[j + 32];
+	}
+
+	for (i = 0; i < 16; i++) {
+		char *er;  /* er[48]  */
+		char *erk; /* erk[48] */
+		char b[8][6];
+		char *cb;  /* cb[32]  */
+		char *pcb; /* pcb[32] */
+		char *r2;  /* r2[32]  */
+
+		er = kmalloc(48+48+32+32+32, GFP_KERNEL);
+		if(er == NULL) {
+			kfree(pk1);
+			return;
+		}
+		erk = er+48;
+		cb  = erk+48;
+		pcb = cb+32;
+		r2  = pcb+32;
+
+		permute(er, r, perm4, 48);
+
+		xor(erk, er, ki[forw ? i : 15 - i], 48);
+
+		for (j = 0; j < 8; j++)
+			for (k = 0; k < 6; k++)
+				b[j][k] = erk[j * 6 + k];
+
+		for (j = 0; j < 8; j++) {
+			int m, n;
+			m = (b[j][0] << 1) | b[j][5];
+
+			n = (b[j][1] << 3) | (b[j][2] << 2) | (b[j][3] <<
+							       1) | b[j][4];
+
+			for (k = 0; k < 4; k++)
+				b[j][k] =
+				    (sbox[j][m][n] & (1 << (3 - k))) ? 1 : 0;
+		}
+
+		for (j = 0; j < 8; j++)
+			for (k = 0; k < 4; k++)
+				cb[j * 4 + k] = b[j][k];
+		permute(pcb, cb, perm5, 32);
+
+		xor(r2, l, pcb, 32);
+
+		for (j = 0; j < 32; j++)
+			l[j] = r[j];
+
+		for (j = 0; j < 32; j++)
+			r[j] = r2[j];
+
+		kfree(er);
+	}
+
+	concat(rl, r, l, 32, 32);
+
+	permute(out, rl, perm6, 64);
+	kfree(pk1);
+}
+
+static void
+str_to_key(unsigned char *str, unsigned char *key)
+{
+	int i;
+
+	key[0] = str[0] >> 1;
+	key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2);
+	key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3);
+	key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4);
+	key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5);
+	key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6);
+	key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7);
+	key[7] = str[6] & 0x7F;
+	for (i = 0; i < 8; i++) {
+		key[i] = (key[i] << 1);
+	}
+}
+
+static void
+smbhash(unsigned char *out, unsigned char *in, unsigned char *key, int forw)
+{
+	int i;
+	char *outb; /* outb[64] */
+	char *inb;  /* inb[64]  */
+	char *keyb; /* keyb[64] */
+	unsigned char key2[8];
+
+	outb = kmalloc(64 * 3,GFP_KERNEL);
+	if(outb == NULL)
+		return;
+
+	inb  = outb + 64;
+	keyb = inb +  64;
+
+	str_to_key(key, key2);
+
+	for (i = 0; i < 64; i++) {
+		inb[i] = (in[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
+		keyb[i] = (key2[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
+		outb[i] = 0;
+	}
+
+	dohash(outb, inb, keyb, forw);
+
+	for (i = 0; i < 8; i++) {
+		out[i] = 0;
+	}
+
+	for (i = 0; i < 64; i++) {
+		if (outb[i])
+			out[i / 8] |= (1 << (7 - (i % 8)));
+	}
+	kfree(outb);
+}
+
+void
+E_P16(unsigned char *p14, unsigned char *p16)
+{
+	unsigned char sp8[8] =
+	    { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
+	smbhash(p16, sp8, p14, 1);
+	smbhash(p16 + 8, sp8, p14 + 7, 1);
+}
+
+void
+E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24)
+{
+	smbhash(p24, c8, p21, 1);
+	smbhash(p24 + 8, c8, p21 + 7, 1);
+	smbhash(p24 + 16, c8, p21 + 14, 1);
+}
+
+void
+D_P16(unsigned char *p14, unsigned char *in, unsigned char *out)
+{
+	smbhash(out, in, p14, 0);
+	smbhash(out + 8, in + 8, p14 + 7, 0);
+}
+
+void
+E_old_pw_hash(unsigned char *p14, unsigned char *in, unsigned char *out)
+{
+	smbhash(out, in, p14, 1);
+	smbhash(out + 8, in + 8, p14 + 7, 1);
+}
+#if 0
+/* these routines are currently unneeded, but may be
+	needed later */
+void
+cred_hash1(unsigned char *out, unsigned char *in, unsigned char *key)
+{
+	unsigned char buf[8];
+
+	smbhash(buf, in, key, 1);
+	smbhash(out, buf, key + 9, 1);
+}
+
+void
+cred_hash2(unsigned char *out, unsigned char *in, unsigned char *key)
+{
+	unsigned char buf[8];
+	static unsigned char key2[8];
+
+	smbhash(buf, in, key, 1);
+	key2[0] = key[7];
+	smbhash(out, buf, key2, 1);
+}
+
+void
+cred_hash3(unsigned char *out, unsigned char *in, unsigned char *key, int forw)
+{
+	static unsigned char key2[8];
+
+	smbhash(out, in, key, forw);
+	key2[0] = key[7];
+	smbhash(out + 8, in + 8, key2, forw);
+}
+#endif /* unneeded routines */
diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c
new file mode 100644
index 0000000..6103bcd
--- /dev/null
+++ b/fs/cifs/smbencrypt.c
@@ -0,0 +1,285 @@
+/* 
+   Unix SMB/Netbios implementation.
+   Version 1.9.
+   SMB parameters and setup
+   Copyright (C) Andrew Tridgell 1992-2000
+   Copyright (C) Luke Kenneth Casson Leighton 1996-2000
+   Modified by Jeremy Allison 1995.
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003
+   Modified by Steve French (sfrench@us.ibm.com) 2002-2003
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/random.h>
+#include "cifs_unicode.h"
+#include "cifspdu.h"
+#include "md5.h"
+#include "cifs_debug.h"
+#include "cifsencrypt.h"
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+/* following came from the other byteorder.h to avoid include conflicts */
+#define CVAL(buf,pos) (((unsigned char *)(buf))[pos])
+#define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8)
+#define SSVAL(buf,pos,val) SSVALX((buf),(pos),((__u16)(val)))
+
+/*The following definitions come from  libsmb/smbencrypt.c  */
+
+void SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24);
+void E_md4hash(const unsigned char *passwd, unsigned char *p16);
+void nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16]);
+static void SMBOWFencrypt(unsigned char passwd[16], unsigned char *c8,
+		   unsigned char p24[24]);
+void NTLMSSPOWFencrypt(unsigned char passwd[8],
+		       unsigned char *ntlmchalresp, unsigned char p24[24]);
+void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24);
+
+/*
+   This implements the X/Open SMB password encryption
+   It takes a password, a 8 byte "crypt key" and puts 24 bytes of 
+   encrypted password into p24 */
+/* Note that password must be uppercased and null terminated */
+void
+SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24)
+{
+	unsigned char p14[15], p21[21];
+
+	memset(p21, '\0', 21);
+	memset(p14, '\0', 14);
+	strncpy((char *) p14, (char *) passwd, 14);
+
+/*	strupper((char *)p14); *//* BB at least uppercase the easy range */
+	E_P16(p14, p21);
+
+	SMBOWFencrypt(p21, c8, p24);
+	
+	memset(p14,0,15);
+	memset(p21,0,21);
+}
+
+/* Routines for Windows NT MD4 Hash functions. */
+static int
+_my_wcslen(__u16 * str)
+{
+	int len = 0;
+	while (*str++ != 0)
+		len++;
+	return len;
+}
+
+/*
+ * Convert a string into an NT UNICODE string.
+ * Note that regardless of processor type 
+ * this must be in intel (little-endian)
+ * format.
+ */
+
+static int
+_my_mbstowcs(__u16 * dst, const unsigned char *src, int len)
+{				/* not a very good conversion routine - change/fix */
+	int i;
+	__u16 val;
+
+	for (i = 0; i < len; i++) {
+		val = *src;
+		SSVAL(dst, 0, val);
+		dst++;
+		src++;
+		if (val == 0)
+			break;
+	}
+	return i;
+}
+
+/* 
+ * Creates the MD4 Hash of the users password in NT UNICODE.
+ */
+
+void
+E_md4hash(const unsigned char *passwd, unsigned char *p16)
+{
+	int len;
+	__u16 wpwd[129];
+
+	/* Password cannot be longer than 128 characters */
+	if(passwd) {
+		len = strlen((char *) passwd);
+		if (len > 128) {
+			len = 128;
+		}
+		/* Password must be converted to NT unicode */
+		_my_mbstowcs(wpwd, passwd, len);
+	} else
+		len = 0;
+
+	wpwd[len] = 0;	/* Ensure string is null terminated */
+	/* Calculate length in bytes */
+	len = _my_wcslen(wpwd) * sizeof (__u16);
+
+	mdfour(p16, (unsigned char *) wpwd, len);
+	memset(wpwd,0,129 * 2);
+}
+
+/* Does both the NT and LM owfs of a user's password */
+void
+nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16])
+{
+	char passwd[514];
+
+	memset(passwd, '\0', 514);
+	if (strlen(pwd) < 513)
+		strcpy(passwd, pwd);
+	else
+		memcpy(passwd, pwd, 512);
+	/* Calculate the MD4 hash (NT compatible) of the password */
+	memset(nt_p16, '\0', 16);
+	E_md4hash(passwd, nt_p16);
+
+	/* Mangle the passwords into Lanman format */
+	passwd[14] = '\0';
+/*	strupper(passwd); */
+
+	/* Calculate the SMB (lanman) hash functions of the password */
+
+	memset(p16, '\0', 16);
+	E_P16((unsigned char *) passwd, (unsigned char *) p16);
+
+	/* clear out local copy of user's password (just being paranoid). */
+	memset(passwd, '\0', sizeof (passwd));
+}
+
+/* Does the NTLMv2 owfs of a user's password */
+#if 0  /* function not needed yet - but will be soon */
+static void
+ntv2_owf_gen(const unsigned char owf[16], const char *user_n,
+		const char *domain_n, unsigned char kr_buf[16],
+		const struct nls_table *nls_codepage)
+{
+	wchar_t * user_u;
+	wchar_t * dom_u;
+	int user_l, domain_l;
+	struct HMACMD5Context ctx;
+
+	/* might as well do one alloc to hold both (user_u and dom_u) */
+	user_u = kmalloc(2048 * sizeof(wchar_t),GFP_KERNEL); 
+	if(user_u == NULL)
+		return;
+	dom_u = user_u + 1024;
+    
+	/* push_ucs2(NULL, user_u, user_n, (user_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER);
+	   push_ucs2(NULL, dom_u, domain_n, (domain_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER); */
+
+	/* BB user and domain may need to be uppercased */
+	user_l = cifs_strtoUCS(user_u, user_n, 511, nls_codepage);
+	domain_l = cifs_strtoUCS(dom_u, domain_n, 511, nls_codepage);
+
+	user_l++;		/* trailing null */
+	domain_l++;
+
+	hmac_md5_init_limK_to_64(owf, 16, &ctx);
+	hmac_md5_update((const unsigned char *) user_u, user_l * 2, &ctx);
+	hmac_md5_update((const unsigned char *) dom_u, domain_l * 2, &ctx);
+	hmac_md5_final(kr_buf, &ctx);
+
+	kfree(user_u);
+}
+#endif 
+
+/* Does the des encryption from the NT or LM MD4 hash. */
+static void
+SMBOWFencrypt(unsigned char passwd[16], unsigned char *c8,
+	      unsigned char p24[24])
+{
+	unsigned char p21[21];
+
+	memset(p21, '\0', 21);
+
+	memcpy(p21, passwd, 16);
+	E_P24(p21, c8, p24);
+}
+
+/* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */
+void
+NTLMSSPOWFencrypt(unsigned char passwd[8],
+		  unsigned char *ntlmchalresp, unsigned char p24[24])
+{
+	unsigned char p21[21];
+
+	memset(p21, '\0', 21);
+	memcpy(p21, passwd, 8);
+	memset(p21 + 8, 0xbd, 8);
+
+	E_P24(p21, ntlmchalresp, p24);
+}
+
+/* Does the NT MD4 hash then des encryption. */
+
+void
+SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24)
+{
+	unsigned char p21[21];
+
+	memset(p21, '\0', 21);
+
+	E_md4hash(passwd, p21);
+	SMBOWFencrypt(p21, c8, p24);
+}
+
+
+/* Does the md5 encryption from the NT hash for NTLMv2. */
+/* These routines will be needed later */
+#if 0
+static void
+SMBOWFencrypt_ntv2(const unsigned char kr[16],
+                   const struct data_blob * srv_chal,
+                   const struct data_blob * cli_chal, unsigned char resp_buf[16])
+{
+        struct HMACMD5Context ctx;
+
+        hmac_md5_init_limK_to_64(kr, 16, &ctx);
+        hmac_md5_update(srv_chal->data, srv_chal->length, &ctx);
+        hmac_md5_update(cli_chal->data, cli_chal->length, &ctx);
+        hmac_md5_final(resp_buf, &ctx);
+}
+
+static void
+SMBsesskeygen_ntv2(const unsigned char kr[16],
+		   const unsigned char *nt_resp, __u8 sess_key[16])
+{
+	struct HMACMD5Context ctx;
+
+	hmac_md5_init_limK_to_64(kr, 16, &ctx);
+	hmac_md5_update(nt_resp, 16, &ctx);
+	hmac_md5_final((unsigned char *) sess_key, &ctx);
+}
+
+static void
+SMBsesskeygen_ntv1(const unsigned char kr[16],
+		   const unsigned char *nt_resp, __u8 sess_key[16])
+{
+	mdfour((unsigned char *) sess_key, (unsigned char *) kr, 16);
+}
+#endif
diff --git a/fs/cifs/smberr.h b/fs/cifs/smberr.h
new file mode 100644
index 0000000..e21f138
--- /dev/null
+++ b/fs/cifs/smberr.h
@@ -0,0 +1,115 @@
+/*
+ *   fs/cifs/smberr.h
+ *
+ *   Copyright (c) International Business Machines  Corp., 2002,2004
+ *   Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ *   See Error Codes section of the SNIA CIFS Specification 
+ *   for more information 
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ */
+
+#define SUCCESS 0		/* The request was successful. */
+#define ERRDOS 0x01		/* Error is from the core DOS operating system set */
+#define ERRSRV 0x02		/* Error is generated by the file server daemon */
+#define ERRHRD 0x03		/* Error is a hardware error. */
+#define ERRCMD 0xFF		/*  Command was not in the "SMB" format. */
+
+/* The following error codes may be generated with the SUCCESS error class.*/
+
+#define SUCCESS 0		/* The request was successful. */
+
+/* The following error codes may be generated with the ERRDOS error class.*/
+
+#define ERRbadfunc 1		/* Invalid function. The server did not recognize or could not perform a system call generated by the server, e.g., set the DIRECTORY attribute on a data file, invalid seek mode. */
+#define ERRbadfile 2		/*File not found. The last component of a file's pathname could not be found. */
+#define ERRbadpath 3		/* Directory invalid. A directory component in a pathname could not be found. */
+#define ERRnofids 4		/* Too many open files. The server has no file handles available. */
+#define ERRnoaccess 5		/* Access denied, the client's context does not permit the requested function. This includes the following conditions: invalid rename command, write to Fid open for read only, read on Fid open for write only, attempt to delete a non-empty directory */
+#define ERRbadfid 6		/* Invalid file handle. The file handle specified was not recognized by the server. */
+#define ERRbadmcb 7		/* Memory control blocks destroyed. */
+#define ERRnomem 8		/* Insufficient server memory to perform the requested function. */
+#define ERRbadmem 9		/* Invalid memory block address. */
+#define ERRbadenv 10		/* Invalid environment. */
+#define ERRbadformat 11		/* Invalid format. */
+#define ERRbadaccess 12		/* Invalid open mode. */
+#define ERRbaddata 13		/* Invalid data (generated only by IOCTL calls within the server). */
+#define ERRbaddrive 15		/* Invalid drive specified. */
+#define ERRremcd 16		/* A Delete Directory request attempted to remove the server's current directory. */
+#define ERRdiffdevice 17	/* Not same device (e.g., a cross volume rename was attempted */
+#define ERRnofiles 18		/* A File Search command can find no more files matching the specified criteria. */
+#define ERRgeneral 31
+#define ERRbadshare 32		/* The sharing mode specified for an Open conflicts with existing FIDs on the file. */
+#define ERRlock 33		/* A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process. */
+#define ERRunsup     50
+#define ERRnosuchshare 67
+#define ERRfilexists 80		/* The file named in the request already exists. */
+#define ERRinvparm   87
+#define ERRdiskfull  112
+#define ERRinvname   123
+#define ERRinvlevel  124
+#define ERRdirnotempty 145
+#define ERRnotlocked   158
+#define ERRalreadyexists 183
+#define ERRbadpipe 230
+#define ERRpipebusy 231
+#define ERRpipeclosing 232
+#define ERRnotconnected 233
+#define ERRmoredata    234
+#define ERReasnotsupported 282
+#define ErrQuota 0x200		/* The operation would cause a quota limit to be exceeded. */
+#define ErrNotALink 0x201	/* A link operation was performed on a pathname that
+				   was not a link. */
+
+/* Following error codes may be generated with the ERRSRV error
+class.*/
+
+#define ERRerror 1		/* Non-specific error code. It is returned under the following conditions: resource other than disk space exhausted (e.g. TIDs), first SMB command was not negotiate, multiple negotiates attempted, and internal server error. */
+#define ERRbadpw 2		/* Bad password - name/password pair in a TreeConnect or Session Setup are invalid. */
+#define ERRbadtype 3		/* used for indicating DFS referral needed */
+#define ERRaccess 4		/* The client does not have the necessary access rights within the specified context for requested function. */
+#define ERRinvtid 5		/* The Tid specified in a command was invalid. */
+#define ERRinvnetname 6		/* Invalid network name in tree connect. */
+#define ERRinvdevice 7		/* Invalid device - printer request made to non-printer connection or non-printer request made to printer connection. */
+#define ERRqfull 49		/* Print queue full (files) -- returned by open print file. */
+#define ERRqtoobig 50		/* Print queue full -- no space. */
+#define ERRqeof         51	/* EOF on print queue dump */
+#define ERRinvpfid      52	/* Invalid print file FID. */
+#define ERRsmbcmd       64	/* The server did not recognize the command received. */
+#define ERRsrverror     65	/* The server encountered an internal error, e.g., system file unavailable. */
+#define ERRbadBID       66	/* (obsolete) */
+#define ERRfilespecs    67	/* The Fid and pathname parameters contained an invalid combination of values. */
+#define ERRbadLink      68	/* (obsolete) */
+#define ERRbadpermits   69	/* The access permissions specified for a file or directory are not a valid combination. */
+#define ERRbadPID       70
+#define ERRsetattrmode  71	/* attribute (mode) is invalid */
+#define ERRpaused       81	/* Server is paused */
+#define ERRmsgoff	82	/* reserved - messaging off */
+#define ERRnoroom       83	/* reserved - no room for message */
+#define ERRrmuns        87	/* reserved - too many remote names */
+#define ERRtimeout      88	/* operation timed out */
+#define ERRnoresource   89	/* No resources available for request */
+#define ERRtoomanyuids  90	/* Too many UIDs active on this session */
+#define ERRbaduid       91	/* The UID is not known as a valid user */
+#define ERRusempx      250	/* temporarily unable to use raw */
+#define ERRusestd      251	/* temporarily unable to use either raw or mpx */
+#define ERR_NOTIFY_ENUM_DIR 1024
+#define ERRaccountexpired 2239
+#define ERRbadclient      2240
+#define ERRbadLogonTime   2241
+#define ERRpasswordExpired 2242
+#define ERRnetlogonNotStarted 2455
+#define ERRnosupport       0xFFFF
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
new file mode 100644
index 0000000..af13e52
--- /dev/null
+++ b/fs/cifs/transport.c
@@ -0,0 +1,619 @@
+/*
+ *   fs/cifs/transport.c
+ *
+ *   Copyright (C) International Business Machines  Corp., 2002,2004
+ *   Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ */
+
+#include <linux/fs.h>
+#include <linux/list.h>
+#include <linux/wait.h>
+#include <linux/net.h>
+#include <linux/delay.h>
+#include <asm/uaccess.h>
+#include <asm/processor.h>
+#include <linux/mempool.h>
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+  
+extern mempool_t *cifs_mid_poolp;
+extern kmem_cache_t *cifs_oplock_cachep;
+
+static struct mid_q_entry *
+AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
+{
+	struct mid_q_entry *temp;
+
+	if (ses == NULL) {
+		cERROR(1, ("Null session passed in to AllocMidQEntry "));
+		return NULL;
+	}
+	if (ses->server == NULL) {
+		cERROR(1, ("Null TCP session in AllocMidQEntry"));
+		return NULL;
+	}
+	
+	temp = (struct mid_q_entry *) mempool_alloc(cifs_mid_poolp,SLAB_KERNEL | SLAB_NOFS);
+	if (temp == NULL)
+		return temp;
+	else {
+		memset(temp, 0, sizeof (struct mid_q_entry));
+		temp->mid = smb_buffer->Mid;	/* always LE */
+		temp->pid = current->pid;
+		temp->command = smb_buffer->Command;
+		cFYI(1, ("For smb_command %d", temp->command));
+		do_gettimeofday(&temp->when_sent);
+		temp->ses = ses;
+		temp->tsk = current;
+	}
+
+	spin_lock(&GlobalMid_Lock);
+	list_add_tail(&temp->qhead, &ses->server->pending_mid_q);
+	atomic_inc(&midCount);
+	temp->midState = MID_REQUEST_ALLOCATED;
+	spin_unlock(&GlobalMid_Lock);
+	return temp;
+}
+
+static void
+DeleteMidQEntry(struct mid_q_entry *midEntry)
+{
+	spin_lock(&GlobalMid_Lock);
+	midEntry->midState = MID_FREE;
+	list_del(&midEntry->qhead);
+	atomic_dec(&midCount);
+	spin_unlock(&GlobalMid_Lock);
+	cifs_buf_release(midEntry->resp_buf);
+	mempool_free(midEntry, cifs_mid_poolp);
+}
+
+struct oplock_q_entry *
+AllocOplockQEntry(struct inode * pinode, __u16 fid, struct cifsTconInfo * tcon)
+{
+	struct oplock_q_entry *temp;
+	if ((pinode== NULL) || (tcon == NULL)) {
+		cERROR(1, ("Null parms passed to AllocOplockQEntry"));
+		return NULL;
+	}
+	temp = (struct oplock_q_entry *) kmem_cache_alloc(cifs_oplock_cachep,
+						       SLAB_KERNEL);
+	if (temp == NULL)
+		return temp;
+	else {
+		temp->pinode = pinode;
+		temp->tcon = tcon;
+		temp->netfid = fid;
+		spin_lock(&GlobalMid_Lock);
+		list_add_tail(&temp->qhead, &GlobalOplock_Q);
+		spin_unlock(&GlobalMid_Lock);
+	}
+	return temp;
+
+}
+
+void DeleteOplockQEntry(struct oplock_q_entry * oplockEntry)
+{
+	spin_lock(&GlobalMid_Lock); 
+    /* should we check if list empty first? */
+	list_del(&oplockEntry->qhead);
+	spin_unlock(&GlobalMid_Lock);
+	kmem_cache_free(cifs_oplock_cachep, oplockEntry);
+}
+
+int
+smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
+	 unsigned int smb_buf_length, struct sockaddr *sin)
+{
+	int rc = 0;
+	int i = 0;
+	struct msghdr smb_msg;
+	struct kvec iov;
+	unsigned len = smb_buf_length + 4;
+
+	if(ssocket == NULL)
+		return -ENOTSOCK; /* BB eventually add reconnect code here */
+	iov.iov_base = smb_buffer;
+	iov.iov_len = len;
+
+	smb_msg.msg_name = sin;
+	smb_msg.msg_namelen = sizeof (struct sockaddr);
+	smb_msg.msg_control = NULL;
+	smb_msg.msg_controllen = 0;
+	smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
+
+	/* smb header is converted in header_assemble. bcc and rest of SMB word
+	   area, and byte area if necessary, is converted to littleendian in 
+	   cifssmb.c and RFC1001 len is converted to bigendian in smb_send 
+	   Flags2 is converted in SendReceive */
+
+	smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
+	cFYI(1, ("Sending smb of length %d ", smb_buf_length));
+	dump_smb(smb_buffer, len);
+
+	while (len > 0) {
+		rc = kernel_sendmsg(ssocket, &smb_msg, &iov, 1, len);
+		if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
+			i++;
+			if(i > 60) {
+				cERROR(1,
+				   ("sends on sock %p stuck for 30 seconds",
+				    ssocket));
+				rc = -EAGAIN;
+				break;
+			}
+			msleep(500);
+			continue;
+		}
+		if (rc < 0) 
+			break;
+		iov.iov_base += rc;
+		iov.iov_len -= rc;
+		len -= rc;
+	}
+
+	if (rc < 0) {
+		cERROR(1,("Error %d sending data on socket to server.", rc));
+	} else {
+		rc = 0;
+	}
+
+	return rc;
+}
+
+#ifdef CIFS_EXPERIMENTAL
+/* BB finish off this function, adding support for writing set of pages as iovec */
+/* and also adding support for operations that need to parse the response smb    */
+
+int
+smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer,
+	 unsigned int smb_buf_length, struct kvec * write_vector /* page list */, struct sockaddr *sin)
+{
+	int rc = 0;
+	int i = 0;
+	struct msghdr smb_msg;
+	number_of_pages += 1; /* account for SMB header */
+	struct kvec * piov  = kmalloc(number_of_pages * sizeof(struct kvec));
+	if(i=0;i<num_pages-1;i++
+	unsigned len = smb_buf_length + 4;
+
+	if(ssocket == NULL)
+		return -ENOTSOCK; /* BB eventually add reconnect code here */
+	iov.iov_base = smb_buffer;
+	iov.iov_len = len;
+
+	smb_msg.msg_name = sin;
+	smb_msg.msg_namelen = sizeof (struct sockaddr);
+	smb_msg.msg_control = NULL;
+	smb_msg.msg_controllen = 0;
+	smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
+
+	/* smb header is converted in header_assemble. bcc and rest of SMB word
+	   area, and byte area if necessary, is converted to littleendian in 
+	   cifssmb.c and RFC1001 len is converted to bigendian in smb_send 
+	   Flags2 is converted in SendReceive */
+
+	smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
+	cFYI(1, ("Sending smb of length %d ", smb_buf_length));
+	dump_smb(smb_buffer, len);
+
+	while (len > 0) {
+		rc = kernel_sendmsg(ssocket, &smb_msg, &iov, number_of_pages, len?);
+		if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
+			i++;
+			if(i > 60) {
+				cERROR(1,
+				   ("sends on sock %p stuck for 30 seconds",
+				    ssocket));
+				rc = -EAGAIN;
+				break;
+			}
+			msleep(500);
+			continue;
+		}
+		if (rc < 0) 
+			break;
+		iov.iov_base += rc;
+		iov.iov_len -= rc;
+		len -= rc;
+	}
+
+	if (rc < 0) {
+		cERROR(1,("Error %d sending data on socket to server.", rc));
+	} else {
+		rc = 0;
+	}
+
+	return rc;
+}
+
+
+int
+CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses,
+	    struct smb_hdr *in_buf, struct kvec * write_vector /* page list */, int *pbytes_returned, const int long_op)
+{
+	int rc = 0;
+	unsigned long timeout = 15 * HZ;
+	struct mid_q_entry *midQ = NULL;
+
+	if (ses == NULL) {
+		cERROR(1,("Null smb session"));
+		return -EIO;
+	}
+	if(ses->server == NULL) {
+		cERROR(1,("Null tcp session"));
+		return -EIO;
+	}
+	if(pbytes_returned == NULL)
+		return -EIO;
+	else
+		*pbytes_returned = 0;
+
+  
+
+	/* Ensure that we do not send more than 50 overlapping requests 
+	   to the same server. We may make this configurable later or
+	   use ses->maxReq */
+	if(long_op == -1) {
+		/* oplock breaks must not be held up */
+		atomic_inc(&ses->server->inFlight);
+	} else {
+		spin_lock(&GlobalMid_Lock); 
+		while(1) {        
+			if(atomic_read(&ses->server->inFlight) >= cifs_max_pending){
+				spin_unlock(&GlobalMid_Lock);
+				wait_event(ses->server->request_q,
+					atomic_read(&ses->server->inFlight)
+					 < cifs_max_pending);
+				spin_lock(&GlobalMid_Lock);
+			} else {
+				if(ses->server->tcpStatus == CifsExiting) {
+					spin_unlock(&GlobalMid_Lock);
+					return -ENOENT;
+				}
+
+			/* can not count locking commands against total since
+			   they are allowed to block on server */
+					
+				if(long_op < 3) {
+				/* update # of requests on the wire to server */
+					atomic_inc(&ses->server->inFlight);
+				}
+				spin_unlock(&GlobalMid_Lock);
+				break;
+			}
+		}
+	}
+	/* make sure that we sign in the same order that we send on this socket 
+	   and avoid races inside tcp sendmsg code that could cause corruption
+	   of smb data */
+
+	down(&ses->server->tcpSem); 
+
+	if (ses->server->tcpStatus == CifsExiting) {
+		rc = -ENOENT;
+		goto cifs_out_label;
+	} else if (ses->server->tcpStatus == CifsNeedReconnect) {
+		cFYI(1,("tcp session dead - return to caller to retry"));
+		rc = -EAGAIN;
+		goto cifs_out_label;
+	} else if (ses->status != CifsGood) {
+		/* check if SMB session is bad because we are setting it up */
+		if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && 
+			(in_buf->Command != SMB_COM_NEGOTIATE)) {
+			rc = -EAGAIN;
+			goto cifs_out_label;
+		} /* else ok - we are setting up session */
+	}
+	midQ = AllocMidQEntry(in_buf, ses);
+	if (midQ == NULL) {
+		up(&ses->server->tcpSem);
+		/* If not lock req, update # of requests on wire to server */
+		if(long_op < 3) {
+			atomic_dec(&ses->server->inFlight); 
+			wake_up(&ses->server->request_q);
+		}
+		return -ENOMEM;
+	}
+
+	if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
+		up(&ses->server->tcpSem);
+		cERROR(1,
+		       ("Illegal length, greater than maximum frame, %d ",
+			in_buf->smb_buf_length));
+		DeleteMidQEntry(midQ);
+		/* If not lock req, update # of requests on wire to server */
+		if(long_op < 3) {
+			atomic_dec(&ses->server->inFlight); 
+			wake_up(&ses->server->request_q);
+		}
+		return -EIO;
+	}
+
+	/* BB can we sign efficiently in this path? */
+	rc = cifs_sign_smb(in_buf, ses, &midQ->sequence_number);
+
+	midQ->midState = MID_REQUEST_SUBMITTED;
+/*	rc = smb_sendv(ses->server->ssocket, in_buf, in_buf->smb_buf_length, piovec,
+		      (struct sockaddr *) &(ses->server->addr.sockAddr));*/
+	if(rc < 0) {
+		DeleteMidQEntry(midQ);
+		up(&ses->server->tcpSem);
+		/* If not lock req, update # of requests on wire to server */
+		if(long_op < 3) {
+			atomic_dec(&ses->server->inFlight); 
+			wake_up(&ses->server->request_q);
+		}
+		return rc;
+	} else
+		up(&ses->server->tcpSem);
+cifs_out_label:
+	if(midQ)
+	        DeleteMidQEntry(midQ);
+                                                                                                                           
+	if(long_op < 3) {
+		atomic_dec(&ses->server->inFlight);
+		wake_up(&ses->server->request_q);
+	}
+
+	return rc;
+}
+
+
+#endif /* CIFS_EXPERIMENTAL */
+
+int
+SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
+	    struct smb_hdr *in_buf, struct smb_hdr *out_buf,
+	    int *pbytes_returned, const int long_op)
+{
+	int rc = 0;
+	unsigned int receive_len;
+	unsigned long timeout;
+	struct mid_q_entry *midQ;
+
+	if (ses == NULL) {
+		cERROR(1,("Null smb session"));
+		return -EIO;
+	}
+	if(ses->server == NULL) {
+		cERROR(1,("Null tcp session"));
+		return -EIO;
+	}
+
+	/* Ensure that we do not send more than 50 overlapping requests 
+	   to the same server. We may make this configurable later or
+	   use ses->maxReq */
+	if(long_op == -1) {
+		/* oplock breaks must not be held up */
+		atomic_inc(&ses->server->inFlight);
+	} else {
+		spin_lock(&GlobalMid_Lock); 
+		while(1) {        
+			if(atomic_read(&ses->server->inFlight) >= cifs_max_pending){
+				spin_unlock(&GlobalMid_Lock);
+				wait_event(ses->server->request_q,
+					atomic_read(&ses->server->inFlight)
+					 < cifs_max_pending);
+				spin_lock(&GlobalMid_Lock);
+			} else {
+				if(ses->server->tcpStatus == CifsExiting) {
+					spin_unlock(&GlobalMid_Lock);
+					return -ENOENT;
+				}
+
+			/* can not count locking commands against total since
+			   they are allowed to block on server */
+					
+				if(long_op < 3) {
+				/* update # of requests on the wire to server */
+					atomic_inc(&ses->server->inFlight);
+				}
+				spin_unlock(&GlobalMid_Lock);
+				break;
+			}
+		}
+	}
+	/* make sure that we sign in the same order that we send on this socket 
+	   and avoid races inside tcp sendmsg code that could cause corruption
+	   of smb data */
+
+	down(&ses->server->tcpSem); 
+
+	if (ses->server->tcpStatus == CifsExiting) {
+		rc = -ENOENT;
+		goto out_unlock;
+	} else if (ses->server->tcpStatus == CifsNeedReconnect) {
+		cFYI(1,("tcp session dead - return to caller to retry"));
+		rc = -EAGAIN;
+		goto out_unlock;
+	} else if (ses->status != CifsGood) {
+		/* check if SMB session is bad because we are setting it up */
+		if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && 
+			(in_buf->Command != SMB_COM_NEGOTIATE)) {
+			rc = -EAGAIN;
+			goto out_unlock;
+		} /* else ok - we are setting up session */
+	}
+	midQ = AllocMidQEntry(in_buf, ses);
+	if (midQ == NULL) {
+		up(&ses->server->tcpSem);
+		/* If not lock req, update # of requests on wire to server */
+		if(long_op < 3) {
+			atomic_dec(&ses->server->inFlight); 
+			wake_up(&ses->server->request_q);
+		}
+		return -ENOMEM;
+	}
+
+	if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
+		up(&ses->server->tcpSem);
+		cERROR(1,
+		       ("Illegal length, greater than maximum frame, %d ",
+			in_buf->smb_buf_length));
+		DeleteMidQEntry(midQ);
+		/* If not lock req, update # of requests on wire to server */
+		if(long_op < 3) {
+			atomic_dec(&ses->server->inFlight); 
+			wake_up(&ses->server->request_q);
+		}
+		return -EIO;
+	}
+
+	rc = cifs_sign_smb(in_buf, ses, &midQ->sequence_number);
+
+	midQ->midState = MID_REQUEST_SUBMITTED;
+	rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
+		      (struct sockaddr *) &(ses->server->addr.sockAddr));
+	if(rc < 0) {
+		DeleteMidQEntry(midQ);
+		up(&ses->server->tcpSem);
+		/* If not lock req, update # of requests on wire to server */
+		if(long_op < 3) {
+			atomic_dec(&ses->server->inFlight); 
+			wake_up(&ses->server->request_q);
+		}
+		return rc;
+	} else
+		up(&ses->server->tcpSem);
+	if (long_op == -1)
+		goto cifs_no_response_exit;
+	else if (long_op == 2) /* writes past end of file can take looooong time */
+		timeout = 300 * HZ;
+	else if (long_op == 1)
+		timeout = 45 * HZ; /* should be greater than 
+			servers oplock break timeout (about 43 seconds) */
+	else if (long_op > 2) {
+		timeout = MAX_SCHEDULE_TIMEOUT;
+	} 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 */
+	if (signal_pending(current)) {
+		/* if signal pending do not hold up user for full smb timeout
+		but we still give response a change to complete */
+		timeout = 2 * HZ;
+	}   
+
+	/* No user interrupts in wait - wreaks havoc with performance */
+	if(timeout != MAX_SCHEDULE_TIMEOUT) {
+		timeout += jiffies;
+		wait_event(ses->server->response_q,
+			(!(midQ->midState & MID_REQUEST_SUBMITTED)) || 
+			time_after(jiffies, timeout) || 
+			((ses->server->tcpStatus != CifsGood) &&
+			 (ses->server->tcpStatus != CifsNew)));
+	} else {
+		wait_event(ses->server->response_q,
+			(!(midQ->midState & MID_REQUEST_SUBMITTED)) || 
+			((ses->server->tcpStatus != CifsGood) &&
+			 (ses->server->tcpStatus != CifsNew)));
+	}
+
+	spin_lock(&GlobalMid_Lock);
+	if (midQ->resp_buf) {
+		spin_unlock(&GlobalMid_Lock);
+		receive_len = be32_to_cpu(*(__be32 *)midQ->resp_buf);
+	} else {
+		cERROR(1,("No response buffer"));
+		if(midQ->midState == MID_REQUEST_SUBMITTED) {
+			if(ses->server->tcpStatus == CifsExiting)
+				rc = -EHOSTDOWN;
+			else {
+				ses->server->tcpStatus = CifsNeedReconnect;
+				midQ->midState = MID_RETRY_NEEDED;
+			}
+		}
+
+		if (rc != -EHOSTDOWN) {
+			if(midQ->midState == MID_RETRY_NEEDED) {
+				rc = -EAGAIN;
+				cFYI(1,("marking request for retry"));
+			} else {
+				rc = -EIO;
+			}
+		}
+		spin_unlock(&GlobalMid_Lock);
+		DeleteMidQEntry(midQ);
+		/* If not lock req, update # of requests on wire to server */
+		if(long_op < 3) {
+			atomic_dec(&ses->server->inFlight); 
+			wake_up(&ses->server->request_q);
+		}
+		return rc;
+	}
+  
+	if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
+		cERROR(1,
+		       ("Frame too large received.  Length: %d  Xid: %d",
+			receive_len, xid));
+		rc = -EIO;
+	} else {		/* rcvd frame is ok */
+
+		if (midQ->resp_buf && out_buf
+		    && (midQ->midState == MID_RESPONSE_RECEIVED)) {
+			out_buf->smb_buf_length = receive_len;
+			memcpy((char *)out_buf + 4,
+			       (char *)midQ->resp_buf + 4,
+			       receive_len);
+
+			dump_smb(out_buf, 92);
+			/* convert the length into a more usable form */
+			if((receive_len > 24) &&
+			   (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))) {
+				rc = cifs_verify_signature(out_buf, ses->mac_signing_key,midQ->sequence_number); /* BB fix BB */
+				if(rc)
+					cFYI(1,("Unexpected signature received from server"));
+			}
+
+			*pbytes_returned = out_buf->smb_buf_length;
+
+			/* BB special case reconnect tid and reconnect uid here? */
+			rc = map_smb_to_linux_error(out_buf);
+
+			/* convert ByteCount if necessary */
+			if (receive_len >=
+			    sizeof (struct smb_hdr) -
+			    4 /* do not count RFC1001 header */  +
+			    (2 * out_buf->WordCount) + 2 /* bcc */ )
+				BCC(out_buf) = le16_to_cpu(BCC(out_buf));
+		} else {
+			rc = -EIO;
+			cFYI(1,("Bad MID state? "));
+		}
+	}
+cifs_no_response_exit:
+	DeleteMidQEntry(midQ);
+
+	if(long_op < 3) {
+		atomic_dec(&ses->server->inFlight); 
+		wake_up(&ses->server->request_q);
+	}
+
+	return rc;
+
+out_unlock:
+	up(&ses->server->tcpSem);
+	/* If not lock req, update # of requests on wire to server */
+	if(long_op < 3) {
+		atomic_dec(&ses->server->inFlight); 
+		wake_up(&ses->server->request_q);
+	}
+
+	return rc;
+}
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
new file mode 100644
index 0000000..549afa1
--- /dev/null
+++ b/fs/cifs/xattr.c
@@ -0,0 +1,334 @@
+/*
+ *   fs/cifs/xattr.c
+ *
+ *   Copyright (c) International Business Machines  Corp., 2003
+ *   Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/fs.h>
+#include <linux/posix_acl_xattr.h>
+#include "cifsfs.h"
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_debug.h"
+
+#define MAX_EA_VALUE_SIZE 65535
+#define CIFS_XATTR_DOS_ATTRIB "user.DosAttrib"
+#define CIFS_XATTR_USER_PREFIX "user."
+#define CIFS_XATTR_SYSTEM_PREFIX "system."
+#define CIFS_XATTR_OS2_PREFIX "os2."
+#define CIFS_XATTR_SECURITY_PREFIX ".security"
+#define CIFS_XATTR_TRUSTED_PREFIX "trusted."
+#define XATTR_TRUSTED_PREFIX_LEN  8
+#define XATTR_SECURITY_PREFIX_LEN 9
+/* BB need to add server (Samba e.g) support for security and trusted prefix */
+  
+
+
+int cifs_removexattr(struct dentry * direntry, const char * ea_name)
+{
+	int rc = -EOPNOTSUPP;
+#ifdef CONFIG_CIFS_XATTR
+	int xid;
+	struct cifs_sb_info *cifs_sb;
+	struct cifsTconInfo *pTcon;
+	struct super_block * sb;
+	char * full_path;
+                                                                                     
+	if(direntry == NULL)
+		return -EIO;
+	if(direntry->d_inode == NULL)
+		return -EIO;
+	sb = direntry->d_inode->i_sb;
+	if(sb == NULL)
+		return -EIO;
+	xid = GetXid();
+                                                                                     
+	cifs_sb = CIFS_SB(sb);
+	pTcon = cifs_sb->tcon;
+                                                                                     
+	down(&sb->s_vfs_rename_sem);
+	full_path = build_path_from_dentry(direntry);
+	up(&sb->s_vfs_rename_sem);
+	if(full_path == NULL) {
+		FreeXid(xid);
+		return -ENOMEM;
+	}
+	if(ea_name == NULL) {
+		cFYI(1,("Null xattr names not supported"));
+	} else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5)
+		&& (strncmp(ea_name,CIFS_XATTR_OS2_PREFIX,4))) {
+		cFYI(1,("illegal xattr namespace %s (only user namespace supported)",ea_name));
+		/* BB what if no namespace prefix? */
+		/* Should we just pass them to server, except for
+		system and perhaps security prefixes? */
+	} else {
+		if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
+			goto remove_ea_exit;
+
+		ea_name+=5; /* skip past user. prefix */
+		rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,NULL,
+			(__u16)0, cifs_sb->local_nls);
+	}
+remove_ea_exit:
+	if (full_path)
+		kfree(full_path);
+	FreeXid(xid);
+#endif
+	return rc;
+}
+
+int cifs_setxattr(struct dentry * direntry, const char * ea_name,
+        const void * ea_value, size_t value_size, int flags)
+{
+	int rc = -EOPNOTSUPP;
+#ifdef CONFIG_CIFS_XATTR
+	int xid;
+	struct cifs_sb_info *cifs_sb;
+	struct cifsTconInfo *pTcon;
+	struct super_block * sb;
+	char * full_path;
+
+	if(direntry == NULL)
+		return -EIO;
+	if(direntry->d_inode == NULL)
+		return -EIO;
+	sb = direntry->d_inode->i_sb;
+	if(sb == NULL)
+		return -EIO;
+	xid = GetXid();
+
+	cifs_sb = CIFS_SB(sb);
+	pTcon = cifs_sb->tcon;
+
+	down(&sb->s_vfs_rename_sem);
+	full_path = build_path_from_dentry(direntry);
+	up(&sb->s_vfs_rename_sem);
+	if(full_path == NULL) {
+		FreeXid(xid);
+		return -ENOMEM;
+	}
+	/* return dos attributes as pseudo xattr */
+	/* return alt name if available as pseudo attr */
+
+	/* if proc/fs/cifs/streamstoxattr is set then
+		search server for EAs or streams to 
+		returns as xattrs */
+	if(value_size > MAX_EA_VALUE_SIZE) {
+		cFYI(1,("size of EA value too large"));
+		if(full_path)
+			kfree(full_path);
+		FreeXid(xid);
+		return -EOPNOTSUPP;
+	}
+
+	if(ea_name == NULL) {
+		cFYI(1,("Null xattr names not supported"));
+	} else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5) == 0) {
+		if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
+			goto set_ea_exit;
+		if(strncmp(ea_name,CIFS_XATTR_DOS_ATTRIB,14) == 0) {
+			cFYI(1,("attempt to set cifs inode metadata"));
+		}
+		ea_name += 5; /* skip past user. prefix */
+		rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value,
+			(__u16)value_size, cifs_sb->local_nls);
+	} else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) {
+		if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
+			goto set_ea_exit;
+
+		ea_name += 4; /* skip past os2. prefix */
+		rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value,
+			(__u16)value_size, cifs_sb->local_nls);
+	} else {
+		int temp; 
+		temp = strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,
+			strlen(POSIX_ACL_XATTR_ACCESS));
+		if (temp == 0) {
+#ifdef CONFIG_CIFS_POSIX
+			rc = CIFSSMBSetPosixACL(xid, pTcon,full_path,ea_value,
+				(const int)value_size, ACL_TYPE_ACCESS,
+				cifs_sb->local_nls);
+			cFYI(1,("set POSIX ACL rc %d",rc));
+#else
+			cFYI(1,("set POSIX ACL not supported"));
+#endif
+		} else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
+#ifdef CONFIG_CIFS_POSIX
+			rc = CIFSSMBSetPosixACL(xid, pTcon,full_path,ea_value,
+				(const int)value_size, ACL_TYPE_DEFAULT,
+				cifs_sb->local_nls);
+			cFYI(1,("set POSIX default ACL rc %d",rc));
+#else
+			cFYI(1,("set default POSIX ACL not supported"));
+#endif
+		} else {
+			cFYI(1,("illegal xattr request %s (only user namespace supported)",ea_name));
+		  /* BB what if no namespace prefix? */
+		  /* Should we just pass them to server, except for 
+		  system and perhaps security prefixes? */
+		}
+	}
+
+set_ea_exit:
+	if (full_path)
+		kfree(full_path);
+	FreeXid(xid);
+#endif
+	return rc;
+}
+
+ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name,
+         void * ea_value, size_t buf_size)
+{
+	ssize_t rc = -EOPNOTSUPP;
+#ifdef CONFIG_CIFS_XATTR
+	int xid;
+	struct cifs_sb_info *cifs_sb;
+	struct cifsTconInfo *pTcon;
+	struct super_block * sb;
+	char * full_path;
+
+	if(direntry == NULL)
+		return -EIO;
+	if(direntry->d_inode == NULL)
+		return -EIO;
+	sb = direntry->d_inode->i_sb;
+	if(sb == NULL)
+		return -EIO;
+
+	xid = GetXid();
+
+	cifs_sb = CIFS_SB(sb);
+	pTcon = cifs_sb->tcon;
+
+	down(&sb->s_vfs_rename_sem);
+	full_path = build_path_from_dentry(direntry);
+	up(&sb->s_vfs_rename_sem);
+	if(full_path == NULL) {
+		FreeXid(xid);
+		return -ENOMEM;
+	}
+	/* return dos attributes as pseudo xattr */
+	/* return alt name if available as pseudo attr */
+	if(ea_name == NULL) {
+		cFYI(1,("Null xattr names not supported"));
+	} else if(strncmp(ea_name,CIFS_XATTR_USER_PREFIX,5) == 0) {
+		if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
+			goto get_ea_exit;
+
+		if(strncmp(ea_name,CIFS_XATTR_DOS_ATTRIB,14) == 0) {
+			cFYI(1,("attempt to query cifs inode metadata"));
+			/* revalidate/getattr then populate from inode */
+		} /* BB add else when above is implemented */
+		ea_name += 5; /* skip past user. prefix */
+		rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value,
+			buf_size, cifs_sb->local_nls);
+	} else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) {
+		if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
+			goto get_ea_exit;
+
+		ea_name += 4; /* skip past os2. prefix */
+		rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value,
+			buf_size, cifs_sb->local_nls);
+	} else if(strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,strlen(POSIX_ACL_XATTR_ACCESS)) == 0) {
+#ifdef CONFIG_CIFS_POSIX
+		rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
+				ea_value, buf_size, ACL_TYPE_ACCESS, 
+				cifs_sb->local_nls);
+#else 
+		cFYI(1,("query POSIX ACL not supported yet"));
+#endif /* CONFIG_CIFS_POSIX */
+	} else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) {
+#ifdef CONFIG_CIFS_POSIX
+		rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
+				ea_value, buf_size, ACL_TYPE_DEFAULT, 
+				cifs_sb->local_nls);
+#else 
+		cFYI(1,("query POSIX default ACL not supported yet"));
+#endif
+	} else if(strncmp(ea_name,
+		  CIFS_XATTR_TRUSTED_PREFIX,XATTR_TRUSTED_PREFIX_LEN) == 0) {
+		cFYI(1,("Trusted xattr namespace not supported yet"));
+	} else if(strncmp(ea_name,
+		  CIFS_XATTR_SECURITY_PREFIX,XATTR_SECURITY_PREFIX_LEN) == 0) {
+		cFYI(1,("Security xattr namespace not supported yet"));
+	} else {
+		cFYI(1,("illegal xattr name request %s (only user namespace supported)",ea_name));
+	}
+
+	/* We could add an additional check for streams ie 
+	    if proc/fs/cifs/streamstoxattr is set then
+		search server for EAs or streams to 
+		returns as xattrs */
+
+	if(rc == -EINVAL)
+		rc = -EOPNOTSUPP; 
+
+get_ea_exit:
+	if (full_path)
+		kfree(full_path);
+	FreeXid(xid);
+#endif
+	return rc;
+}
+
+ssize_t cifs_listxattr(struct dentry * direntry, char * data, size_t buf_size)
+{
+	ssize_t rc = -EOPNOTSUPP;
+#ifdef CONFIG_CIFS_XATTR
+	int xid;
+	struct cifs_sb_info *cifs_sb;
+	struct cifsTconInfo *pTcon;
+	struct super_block * sb;
+	char * full_path;
+
+	if(direntry == NULL)
+		return -EIO;
+	if(direntry->d_inode == NULL)
+		return -EIO;
+	sb = direntry->d_inode->i_sb;
+	if(sb == NULL)
+		return -EIO;
+	xid = GetXid();
+
+	cifs_sb = CIFS_SB(sb);
+	pTcon = cifs_sb->tcon;
+
+	down(&sb->s_vfs_rename_sem);
+	full_path = build_path_from_dentry(direntry);
+	up(&sb->s_vfs_rename_sem);
+	if(full_path == NULL) {
+		FreeXid(xid);
+		return -ENOMEM;
+	}
+	/* return dos attributes as pseudo xattr */
+	/* return alt name if available as pseudo attr */
+
+	/* if proc/fs/cifs/streamstoxattr is set then
+		search server for EAs or streams to 
+		returns as xattrs */
+	rc = CIFSSMBQAllEAs(xid,pTcon,full_path,data,buf_size,
+				cifs_sb->local_nls);
+
+	if (full_path)
+		kfree(full_path);
+	FreeXid(xid);
+#endif
+	return rc;
+}