diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/AUTHORS | 4 | ||||
-rw-r--r-- | fs/cifs/CHANGES | 60 | ||||
-rw-r--r-- | fs/cifs/README | 24 | ||||
-rw-r--r-- | fs/cifs/TODO | 50 | ||||
-rw-r--r-- | fs/cifs/asn1.c | 3 | ||||
-rw-r--r-- | fs/cifs/cifs_debug.c | 103 | ||||
-rw-r--r-- | fs/cifs/cifs_debug.h | 5 | ||||
-rw-r--r-- | fs/cifs/cifs_fs_sb.h | 3 | ||||
-rw-r--r-- | fs/cifs/cifsfs.c | 80 | ||||
-rw-r--r-- | fs/cifs/cifsfs.h | 3 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 98 | ||||
-rw-r--r-- | fs/cifs/cifspdu.h | 499 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 32 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 659 | ||||
-rw-r--r-- | fs/cifs/connect.c | 219 | ||||
-rw-r--r-- | fs/cifs/dir.c | 108 | ||||
-rw-r--r-- | fs/cifs/fcntl.c | 12 | ||||
-rw-r--r-- | fs/cifs/file.c | 466 | ||||
-rw-r--r-- | fs/cifs/inode.c | 150 | ||||
-rw-r--r-- | fs/cifs/link.c | 5 | ||||
-rw-r--r-- | fs/cifs/misc.c | 123 | ||||
-rw-r--r-- | fs/cifs/netmisc.c | 15 | ||||
-rw-r--r-- | fs/cifs/ntlmssp.h | 12 | ||||
-rw-r--r-- | fs/cifs/readdir.c | 84 | ||||
-rw-r--r-- | fs/cifs/rfc1002pdu.h | 13 | ||||
-rw-r--r-- | fs/cifs/transport.c | 331 | ||||
-rw-r--r-- | fs/ntfs/file.c | 17 |
27 files changed, 2448 insertions, 730 deletions
diff --git a/fs/cifs/AUTHORS b/fs/cifs/AUTHORS index 72fdc10dfdd..8848e4dfa02 100644 --- a/fs/cifs/AUTHORS +++ b/fs/cifs/AUTHORS @@ -32,6 +32,10 @@ Domen Puncer Jesper Juhl (in particular for lots of whitespace/formatting cleanup) Vince Negri and Dave Stahl (for finding an important caching bug) Adrian Bunk (kcalloc cleanups) +Miklos Szeredi +Kazeon team for various fixes especially for 2.4 version. +Asser Ferno (Change Notify support) +Shaggy (Dave Kleikamp) for inumerable small fs suggestions and some good cleanup Test case and Bug Report contributors ------------------------------------- diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 3196d4c4eed..5bab24f5905 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -1,8 +1,52 @@ +Version 1.39 +------------ +Defer close of a file handle slightly if pending writes depend on that file handle +(this reduces the EBADF bad file handle errors that can be logged under heavy +stress on writes). + +Version 1.38 +------------ +Fix tcp socket retransmission timeouts (e.g. on ENOSPACE from the socket) +to be smaller at first (but increasing) so large write performance performance +over GigE is better. Do not hang thread on illegal byte range lock response +from Windows (Windows can send an RFC1001 size which does not match smb size) by +allowing an SMBs TCP length to be up to a few bytes longer than it should be. +wsize and rsize can now be larger than negotiated buffer size if server +supports large readx/writex, even when directio mount flag not specified. +Write size will in many cases now be 16K instead of 4K which greatly helps +file copy performance on lightly loaded networks. Fix oops in dnotify +when experimental config flag enabled. Make cifsFYI more granular. + +Version 1.37 +------------ +Fix readdir caching when unlink removes file in current search buffer, +and this is followed by a rewind search to just before the deleted entry. +Do not attempt to set ctime unless atime and/or mtime change requested +(most servers throw it away anyway). Fix length check of received smbs +to be more accurate. Fix big endian problem with mapchars mount option, +and with a field returned by statfs. + +Version 1.36 +------------ +Add support for mounting to older pre-CIFS servers such as Windows9x and ME. +For these older servers, add option for passing netbios name of server in +on mount (servernetbiosname). Add suspend support for power management, to +avoid cifsd thread preventing software suspend from working. +Add mount option for disabling the default behavior of sending byte range lock +requests to the server (necessary for certain applications which break with +mandatory lock behavior such as Evolution), and also mount option for +requesting case insensitive matching for path based requests (requesting +case sensitive is the default). + Version 1.35 ------------ Add writepage performance improvements. Fix path name conversions for long filenames on mounts which were done with "mapchars" mount option -specified. +specified. Ensure multiplex ids do not collide. Fix case in which +rmmod can oops if done soon after last unmount. Fix truncated +search (readdir) output when resume filename was a long filename. +Fix filename conversion when mapchars mount option was specified and +filename was a long filename. Version 1.34 ------------ @@ -11,7 +55,7 @@ Do not oops if root user kills cifs oplock kernel thread or kills the cifsd thread (NB: killing the cifs kernel threads is not recommended, unmount and rmmod cifs will kill them when they are no longer needed). Fix readdir to ASCII servers (ie older servers -which do not support Unicode) and also require asterik. +which do not support Unicode) and also require asterisk. Fix out of memory case in which data could be written one page off in the page cache. @@ -101,7 +145,7 @@ improperly zeroed buffer in CIFS Unix extensions set times call. Version 1.25 ------------ -Fix internationlization problem in cifs readdir with filenames that map to +Fix internationalization 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 @@ -276,7 +320,7 @@ 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 +as an override of comma as the default separator between mount options. Version 1.01 @@ -286,7 +330,7 @@ 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 +Windows 98 that terminate tcp sessions during protocol negotiation. Handle embedded commas in mount parsing of passwords. Version 0.99 @@ -295,7 +339,7 @@ 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 +protocol response. Fix oops in reopen_file when dentry freed. Allow the support for CIFS Unix Extensions to be disabled via proc interface. Version 0.98 @@ -637,7 +681,7 @@ versions of 2.4 kernel (now builds and works again on kernels at least as early 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. +files now return the correct number of links on fstat as they are repeatedly linked and unlinked. Version 0.40 ------------ @@ -704,7 +748,7 @@ session) 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, +(with or without Unix extensions) 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 diff --git a/fs/cifs/README b/fs/cifs/README index 34b0cf7111f..bb90941826a 100644 --- a/fs/cifs/README +++ b/fs/cifs/README @@ -294,8 +294,10 @@ A partial list of the supported mount options follows: 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 + rsize default read size (usually 16K) + wsize default write size (usually 16K, 32K is often better over GigE) + maximum wsize currently allowed by CIFS is 57344 (14 4096 byte + pages) rw mount the network share read-write (note that the server may still consider the share read-only) ro mount network share read-only @@ -407,6 +409,13 @@ A partial list of the supported mount options follows: This has no effect if the server does not support Unicode on the wire. nomapchars Do not translate any of these seven characters (default). + nocase Request case insensitive path name matching (case + sensitive is the default if the server suports it). + nobrl Do not send byte range lock requests to the server. + This is necessary for certain applications that break + with cifs style mandatory byte range locks (and most + cifs servers do not yet support requesting advisory + byte range locks). remount remount the share (often used to change from ro to rw mounts or vice versa) @@ -473,9 +482,16 @@ These experimental features and tracing can be enabled by changing flags in 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 + echo 7 > /proc/fs/cifs/cifsFYI -and for more extensive tracing including the start of smb requests and responses +cifsFYI functions as a bit mask. Setting it to 1 enables additional kernel +logging of various informational messages. 2 enables logging of non-zero +SMB return codes while 4 enables logging of requests that take longer +than one second to complete (except for byte range lock requests). +Setting it to 4 requires defining CONFIG_CIFS_STATS2 manually in the +source code (typically by setting it in the beginning of cifsglob.h), +and setting it to seven enables all three. Finally, tracing +the start of smb requests and responses can be enabled via: echo 1 > /proc/fs/cifs/traceSMB diff --git a/fs/cifs/TODO b/fs/cifs/TODO index 8cc881694e2..c909298d11e 100644 --- a/fs/cifs/TODO +++ b/fs/cifs/TODO @@ -1,4 +1,4 @@ -version 1.34 April 29, 2005 +version 1.37 October 9, 2005 A Partial List of Missing Features ================================== @@ -7,14 +7,14 @@ 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 +a) Support for SecurityDescriptors(Windows/CIFS ACLs) for chmod/chgrp/chown +so that these operations can be supported to Windows servers -b) Better pam/winbind integration (e.g. to handle uid mapping -better) +b) Mapping POSIX ACLs (and eventually NFSv4 ACLs) to CIFS +SecurityDescriptors -c) multi-user mounts - multiplexed sessionsetups over single vc -(ie tcp session) - more testing needed +c) Better pam/winbind integration (e.g. to handle uid mapping +better) d) Kerberos/SPNEGO session setup support - (started) @@ -29,12 +29,17 @@ 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 +style byte range lock differences. Save byte range locks so +reconnect can replay them. -h) quota support +h) Support unlock all (unlock 0,MAX_OFFSET) +by unlocking all known byte range locks that we locked on the file. -j) finish writepages support (multi-page write behind for improved -performance) and syncpage +i) quota support (needs minor kernel change since quota calls +to make it to network filesystems or deviceless filesystems) + +j) investigate sync behavior (including syncpage) and check +for proper behavior of intr/nointr 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. @@ -57,20 +62,18 @@ 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) +will autorefresh (partially complete by Asser). Needs minor kernel +vfs change to support removing D_NOTIFY on a file. 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 +s) 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) - -s) Allow remapping of last remaining character (\) to +0xF000 which -(this character is valid for POSIX but not for Windows) +t) Implement O_DIRECT flag on open (already supported on mount) -t) Create UID mapping facility so server UIDs can be mapped on a per +u) Create UID mapping facility so server UIDs can be mapped on a per mount or a per server basis to client UIDs or nobody if no mapping exists. This is helpful when Unix extensions are negotiated to allow better permission checking when UIDs differ on the server @@ -78,6 +81,17 @@ and client. Add new protocol request to the CIFS protocol standard for asking the server for the corresponding name of a particular uid. +v) Add support for CIFS Unix and also the newer POSIX extensions to the +server side for Samba 4. + +w) Finish up the dos time conversion routines needed to return old server +time to the client (default time, of now or time 0 is used now for these +very old servers) + +x) Add support for OS/2 (LANMAN 1.2 and LANMAN2.1 based SMB servers) + +y) Finish testing of Windows 9x/Windows ME server support (started). + KNOWN BUGS (updated April 29, 2005) ==================================== See http://bugzilla.samba.org - search on product "CifsVFS" for diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c index e02010dd73e..98539e2afe8 100644 --- a/fs/cifs/asn1.c +++ b/fs/cifs/asn1.c @@ -191,7 +191,8 @@ asn1_header_decode(struct asn1_ctx *ctx, unsigned char **eoc, unsigned int *cls, unsigned int *con, unsigned int *tag) { - unsigned int def, len; + unsigned int def = 0; + unsigned int len = 0; if (!asn1_id_decode(ctx, cls, con, tag)) return 0; diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index 4061e43471c..22a444a3fe4 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c @@ -81,6 +81,8 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, buf += length; length = sprintf(buf,"CIFS Version %s\n",CIFS_VERSION); buf += length; + length = sprintf(buf,"Active VFS Requests: %d\n", GlobalTotalActiveXid); + buf += length; length = sprintf(buf, "Servers:"); buf += length; @@ -97,7 +99,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, } else { 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", + "\n%d) Name: %s Domain: %s Mounts: %d OS: %s \n\tNOS: %s\tCapability: 0x%x\n\tSMB session status: %d\t", i, ses->serverName, ses->serverDomain, atomic_read(&ses->inUse), ses->serverOS, ses->serverNOS, @@ -105,12 +107,18 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, buf += length; } if(ses->server) { - buf += sprintf(buf, "TCP status: %d\n\tLocal Users To Server: %d SecMode: 0x%x Req Active: %d", + buf += sprintf(buf, "TCP status: %d\n\tLocal Users To Server: %d SecMode: 0x%x Req On Wire: %d", ses->server->tcpStatus, atomic_read(&ses->server->socketUseCount), ses->server->secMode, atomic_read(&ses->server->inFlight)); - + +#ifdef CONFIG_CIFS_STATS2 + buf += sprintf(buf, " In Send: %d In MaxReq Wait: %d", + atomic_read(&ses->server->inSend), + atomic_read(&ses->server->num_waiters)); +#endif + length = sprintf(buf, "\nMIDs:\n"); buf += length; @@ -149,7 +157,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, 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", + "\n%d) %s Uses: %d Type: %s DevInfo: 0x%x Attributes: 0x%x\nPathComponentMax: %d Status: %d", i, tcon->treeName, atomic_read(&tcon->useCount), tcon->nativeFileSystem, @@ -195,6 +203,49 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, } #ifdef CONFIG_CIFS_STATS + +static int +cifs_stats_write(struct file *file, const char __user *buffer, + unsigned long count, void *data) +{ + char c; + int rc; + struct list_head *tmp; + struct cifsTconInfo *tcon; + + rc = get_user(c, buffer); + if (rc) + return rc; + + if (c == '1' || c == 'y' || c == 'Y' || c == '0') { + read_lock(&GlobalSMBSeslock); + list_for_each(tmp, &GlobalTreeConnectionList) { + tcon = list_entry(tmp, struct cifsTconInfo, + cifsConnectionList); + atomic_set(&tcon->num_smbs_sent, 0); + atomic_set(&tcon->num_writes, 0); + atomic_set(&tcon->num_reads, 0); + atomic_set(&tcon->num_oplock_brks, 0); + atomic_set(&tcon->num_opens, 0); + atomic_set(&tcon->num_closes, 0); + atomic_set(&tcon->num_deletes, 0); + atomic_set(&tcon->num_mkdirs, 0); + atomic_set(&tcon->num_rmdirs, 0); + atomic_set(&tcon->num_renames, 0); + atomic_set(&tcon->num_t2renames, 0); + atomic_set(&tcon->num_ffirst, 0); + atomic_set(&tcon->num_fnext, 0); + atomic_set(&tcon->num_fclose, 0); + atomic_set(&tcon->num_hardlinks, 0); + atomic_set(&tcon->num_symlinks, 0); + atomic_set(&tcon->num_locks, 0); + } + read_unlock(&GlobalSMBSeslock); + } + + return count; +} + static int cifs_stats_read(char *buf, char **beginBuffer, off_t offset, int count, int *eof, void *data) @@ -254,35 +305,51 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset, buf += sprintf(buf, "\tDISCONNECTED "); length += 14; } - item_length = sprintf(buf,"\nSMBs: %d Oplock Breaks: %d", + 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", + 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", + 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, + "\nLocks: %d HardLinks: %d Symlinks: %d", + atomic_read(&tcon->num_locks), + atomic_read(&tcon->num_hardlinks), + atomic_read(&tcon->num_symlinks)); + buf += item_length; + length += item_length; + + item_length = sprintf(buf, "\nOpens: %d Closes: %d Deletes: %d", + atomic_read(&tcon->num_opens), + atomic_read(&tcon->num_closes), + atomic_read(&tcon->num_deletes)); 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), + item_length = sprintf(buf, "\nMkdirs: %d Rmdirs: %d", 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", + 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; + item_length = sprintf(buf, "\nFindFirst: %d FNext %d FClose %d", + atomic_read(&tcon->num_ffirst), + atomic_read(&tcon->num_fnext), + atomic_read(&tcon->num_fclose)); + buf += item_length; + length += item_length; } read_unlock(&GlobalSMBSeslock); @@ -341,8 +408,10 @@ cifs_proc_init(void) cifs_debug_data_read, NULL); #ifdef CONFIG_CIFS_STATS - create_proc_read_entry("Stats", 0, proc_fs_cifs, + pde = create_proc_read_entry("Stats", 0, proc_fs_cifs, cifs_stats_read, NULL); + if (pde) + pde->write_proc = cifs_stats_write; #endif pde = create_proc_read_entry("cifsFYI", 0, proc_fs_cifs, cifsFYI_read, NULL); @@ -360,7 +429,7 @@ cifs_proc_init(void) if (pde) pde->write_proc = oplockEnabled_write; - pde = create_proc_read_entry("ReenableOldCifsReaddirCode", 0, proc_fs_cifs, + pde = create_proc_read_entry("Experimental", 0, proc_fs_cifs, quotaEnabled_read, NULL); if (pde) pde->write_proc = quotaEnabled_write; @@ -419,7 +488,7 @@ cifs_proc_clean(void) 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("Experimental",proc_fs_cifs); remove_proc_entry("LookupCacheEnabled",proc_fs_cifs); remove_proc_entry("cifs", proc_root_fs); } @@ -459,6 +528,8 @@ cifsFYI_write(struct file *file, const char __user *buffer, cifsFYI = 0; else if (c == '1' || c == 'y' || c == 'Y') cifsFYI = 1; + else if((c > '1') && (c <= '9')) + cifsFYI = (int) (c - '0'); /* see cifs_debug.h for meanings */ return count; } diff --git a/fs/cifs/cifs_debug.h b/fs/cifs/cifs_debug.h index bf24d2828f6..4304d9dcfb6 100644 --- a/fs/cifs/cifs_debug.h +++ b/fs/cifs/cifs_debug.h @@ -26,6 +26,9 @@ 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); +#define CIFS_INFO 0x01 +#define CIFS_RC 0x02 +#define CIFS_TIMER 0x04 /* * debug ON @@ -36,7 +39,7 @@ void dump_smb(struct smb_hdr *, int); /* information message: e.g., configuration, major event */ extern int cifsFYI; -#define cifsfyi(format,arg...) if (cifsFYI) printk(KERN_DEBUG " " __FILE__ ": " format "\n" "" , ## arg) +#define cifsfyi(format,arg...) if (cifsFYI & CIFS_INFO) printk(KERN_DEBUG " " __FILE__ ": " format "\n" "" , ## arg) #define cFYI(button,prspec) if (button) cifsfyi prspec diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h index ec00d61d530..f799f6f0e72 100644 --- a/fs/cifs/cifs_fs_sb.h +++ b/fs/cifs/cifs_fs_sb.h @@ -24,6 +24,9 @@ #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 */ #define CIFS_MOUNT_MAP_SPECIAL_CHR 0x20 /* remap illegal chars in filenames */ +#define CIFS_MOUNT_POSIX_PATHS 0x40 /* Negotiate posix pathnames if possible. */ +#define CIFS_MOUNT_UNX_EMUL 0x80 /* Network compat with SFUnix emulation */ +#define CIFS_MOUNT_NO_BRL 0x100 /* No sending byte range locks to srv */ struct cifs_sb_info { struct cifsTconInfo *tcon; /* primary mount */ diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 1ebf7dafc1d..877095a1192 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -59,6 +59,8 @@ unsigned int ntlmv2_support = 0; unsigned int sign_CIFS_PDUs = 1; extern struct task_struct * oplockThread; /* remove sparse warning */ struct task_struct * oplockThread = NULL; +extern struct task_struct * dnotifyThread; /* remove sparse warning */ +struct task_struct * dnotifyThread = 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"); @@ -73,6 +75,7 @@ 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); +static DECLARE_COMPLETION(cifs_dnotify_exited); extern mempool_t *cifs_sm_req_poolp; extern mempool_t *cifs_req_poolp; @@ -202,6 +205,10 @@ cifs_statfs(struct super_block *sb, struct kstatfs *buf) #endif /* CIFS_EXPERIMENTAL */ rc = CIFSSMBQFSInfo(xid, pTcon, buf); + /* Old Windows servers do not support level 103, retry with level + one if old server failed the previous call */ + if(rc) + rc = SMBOldQFSInfo(xid, pTcon, buf); /* int f_type; __fsid_t f_fsid; @@ -253,7 +260,7 @@ cifs_alloc_inode(struct super_block *sb) 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 */ - + cifs_inode->vfs_inode.i_flags = S_NOATIME | S_NOCMTIME; INIT_LIST_HEAD(&cifs_inode->openFileList); return &cifs_inode->vfs_inode; } @@ -398,6 +405,34 @@ static struct quotactl_ops cifs_quotactl_ops = { }; #endif +static void cifs_umount_begin(struct super_block * sblock) +{ + struct cifs_sb_info *cifs_sb; + struct cifsTconInfo * tcon; + + cifs_sb = CIFS_SB(sblock); + if(cifs_sb == NULL) + return; + + tcon = cifs_sb->tcon; + if(tcon == NULL) + return; + down(&tcon->tconSem); + if (atomic_read(&tcon->useCount) == 1) + tcon->tidStatus = CifsExiting; + up(&tcon->tconSem); + + if(tcon->ses && tcon->ses->server) + { + cERROR(1,("wake up tasks now - umount begin not complete")); + wake_up_all(&tcon->ses->server->request_q); + } +/* BB FIXME - finish add checks for tidStatus BB */ + + return; +} + + static int cifs_remount(struct super_block *sb, int *flags, char *data) { *flags |= MS_NODIRATIME; @@ -415,7 +450,7 @@ struct super_operations cifs_super_ops = { 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 */ +/* .umount_begin = cifs_umount_begin, */ /* BB finish in the future */ .remount_fs = cifs_remount, }; @@ -783,9 +818,7 @@ static int cifs_oplock_thread(void * dummyarg) do { if (try_to_freeze()) continue; - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1*HZ); spin_lock(&GlobalMid_Lock); if(list_empty(&GlobalOplock_Q)) { spin_unlock(&GlobalMid_Lock); @@ -834,10 +867,27 @@ static int cifs_oplock_thread(void * dummyarg) } } else spin_unlock(&GlobalMid_Lock); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1); /* yield in case q were corrupt */ } } while(!signal_pending(current)); - complete_and_exit (&cifs_oplock_exited, 0); oplockThread = NULL; + complete_and_exit (&cifs_oplock_exited, 0); +} + +static int cifs_dnotify_thread(void * dummyarg) +{ + daemonize("cifsdnotifyd"); + allow_signal(SIGTERM); + + dnotifyThread = current; + do { + if(try_to_freeze()) + continue; + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(39*HZ); + } while(!signal_pending(current)); + complete_and_exit (&cifs_dnotify_exited, 0); } static int __init @@ -851,6 +901,10 @@ init_cifs(void) INIT_LIST_HEAD(&GlobalSMBSessionList); INIT_LIST_HEAD(&GlobalTreeConnectionList); INIT_LIST_HEAD(&GlobalOplock_Q); +#ifdef CONFIG_CIFS_EXPERIMENTAL + INIT_LIST_HEAD(&GlobalDnotifyReqList); + INIT_LIST_HEAD(&GlobalDnotifyRsp_Q); +#endif /* * Initialize Global counters */ @@ -886,10 +940,16 @@ init_cifs(void) if (!rc) { rc = (int)kernel_thread(cifs_oplock_thread, NULL, CLONE_FS | CLONE_FILES | CLONE_VM); - if(rc > 0) - return 0; - else + if(rc > 0) { + rc = (int)kernel_thread(cifs_dnotify_thread, NULL, + CLONE_FS | CLONE_FILES | CLONE_VM); + if(rc > 0) + return 0; + else + cERROR(1,("error %d create dnotify thread", rc)); + } else { cERROR(1,("error %d create oplock thread",rc)); + } } cifs_destroy_request_bufs(); } @@ -918,6 +978,10 @@ exit_cifs(void) send_sig(SIGTERM, oplockThread, 1); wait_for_completion(&cifs_oplock_exited); } + if(dnotifyThread) { + send_sig(SIGTERM, dnotifyThread, 1); + wait_for_completion(&cifs_dnotify_exited); + } } MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>"); diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 1fd21f66f24..1223fa81dbd 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -81,6 +81,7 @@ extern int cifs_dir_notify(struct file *, unsigned long arg); /* Functions related to dir entries */ extern struct dentry_operations cifs_dentry_ops; +extern struct dentry_operations cifs_ci_dentry_ops; /* Functions related to symlinks */ extern void *cifs_follow_link(struct dentry *direntry, struct nameidata *nd); @@ -96,5 +97,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); extern int cifs_ioctl (struct inode * inode, struct file * filep, unsigned int command, unsigned long arg); -#define CIFS_VERSION "1.35" +#define CIFS_VERSION "1.39" #endif /* _CIFSFS_H */ diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 81babab265e..1ba08f8c5bc 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -110,8 +110,9 @@ enum protocolEnum { */ 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 */ + /* 15 character server name + 0x20 16th byte indicating type = srv */ + char server_RFC1001_name[SERVER_NAME_LEN_WITH_NULL]; + char unicode_server_Name[SERVER_NAME_LEN_WITH_NULL * 2]; struct socket *ssocket; union { struct sockaddr_in sockAddr; @@ -122,13 +123,17 @@ struct TCP_Server_Info { 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 */ + 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 */ |