2005-04-17 02:20:36 +04:00
/*
* fs / cifs / cifsfs . c
*
2008-05-17 07:12:45 +04:00
* Copyright ( C ) International Business Machines Corp . , 2002 , 2008
2005-04-17 02:20:36 +04:00
* 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>
2005-11-30 07:55:11 +03:00
# include <linux/delay.h>
2006-04-22 02:52:25 +04:00
# include <linux/kthread.h>
2006-12-07 07:34:23 +03:00
# include <linux/freezer.h>
2011-07-18 21:50:40 +04:00
# include <linux/namei.h>
2010-09-02 04:06:02 +04:00
# include <net/ipv6.h>
2005-04-17 02:20:36 +04:00
# 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>
2007-11-03 08:02:24 +03:00
# include <linux/key-type.h>
2007-11-03 08:11:06 +03:00
# include "cifs_spnego.h"
2010-07-05 16:41:50 +04:00
# include "fscache.h"
2012-01-12 22:40:50 +04:00
# ifdef CONFIG_CIFS_SMB2
# include "smb2pdu.h"
# endif
2005-04-17 02:20:36 +04:00
int cifsFYI = 0 ;
int cifsERROR = 1 ;
int traceSMB = 0 ;
2011-10-13 02:47:03 +04:00
bool enable_oplocks = true ;
2005-04-17 02:20:36 +04:00
unsigned int linuxExtEnabled = 1 ;
unsigned int lookupCacheEnabled = 1 ;
2010-04-24 15:57:45 +04:00
unsigned int global_secflags = CIFSSEC_DEF ;
2006-06-01 02:40:51 +04:00
/* unsigned int ntlmv2_support = 0; */
2005-04-17 02:20:36 +04:00
unsigned int sign_CIFS_PDUs = 1 ;
2007-02-12 11:55:41 +03:00
static const struct super_operations cifs_super_ops ;
2005-04-17 02:20:36 +04:00
unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE ;
module_param ( CIFSMaxBufSize , int , 0 ) ;
2007-07-17 21:34:02 +04:00
MODULE_PARM_DESC ( CIFSMaxBufSize , " Network buffer size (not including header). "
" Default: 16384 Range: 8192 to 130048 " ) ;
2005-04-17 02:20:36 +04:00
unsigned int cifs_min_rcv = CIFS_MIN_RCV_POOL ;
module_param ( cifs_min_rcv , int , 0 ) ;
2007-07-17 21:34:02 +04:00
MODULE_PARM_DESC ( cifs_min_rcv , " Network buffers in pool. Default: 4 Range: "
" 1 to 64 " ) ;
2005-04-17 02:20:36 +04:00
unsigned int cifs_min_small = 30 ;
module_param ( cifs_min_small , int , 0 ) ;
2007-07-17 21:34:02 +04:00
MODULE_PARM_DESC ( cifs_min_small , " Small network buffers in pool. Default: 30 "
" Range: 2 to 256 " ) ;
2005-04-17 02:20:36 +04:00
unsigned int cifs_max_pending = CIFS_MAX_REQ ;
2011-10-19 23:30:37 +04:00
module_param ( cifs_max_pending , int , 0444 ) ;
2007-07-17 21:34:02 +04:00
MODULE_PARM_DESC ( cifs_max_pending , " Simultaneous requests to server. "
2012-03-20 13:55:09 +04:00
" Default: 32767 Range: 2 to 32767. " ) ;
2011-10-13 02:47:03 +04:00
module_param ( enable_oplocks , bool , 0644 ) ;
MODULE_PARM_DESC ( enable_oplocks , " Enable or disable oplocks (bool). Default: "
" y/Y/1 " ) ;
2005-04-17 02:20:36 +04:00
extern mempool_t * cifs_sm_req_poolp ;
extern mempool_t * cifs_req_poolp ;
extern mempool_t * cifs_mid_poolp ;
2012-03-23 22:40:53 +04:00
struct workqueue_struct * cifsiod_wq ;
2005-04-17 02:20:36 +04:00
static int
2011-06-17 17:29:57 +04:00
cifs_read_super ( struct super_block * sb )
2005-04-17 02:20:36 +04:00
{
struct inode * inode ;
2011-05-25 13:35:34 +04:00
struct cifs_sb_info * cifs_sb ;
2005-04-17 02:20:36 +04:00
int rc = 0 ;
2007-07-13 04:33:32 +04:00
2011-05-25 13:35:34 +04:00
cifs_sb = CIFS_SB ( sb ) ;
2005-04-17 02:20:36 +04:00
2011-06-17 17:05:48 +04:00
if ( cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_POSIXACL )
sb - > s_flags | = MS_POSIXACL ;
if ( cifs_sb_master_tcon ( cifs_sb ) - > ses - > capabilities & CAP_LARGE_FILES )
sb - > s_maxbytes = MAX_LFS_FILESIZE ;
else
sb - > s_maxbytes = MAX_NON_LFS ;
/* BB FIXME fix time_gran to be larger for LANMAN sessions */
sb - > s_time_gran = 100 ;
2005-04-17 02:20:36 +04:00
sb - > s_magic = CIFS_MAGIC_NUMBER ;
sb - > s_op = & cifs_super_ops ;
2010-04-22 14:09:48 +04:00
sb - > s_bdi = & cifs_sb - > bdi ;
2005-04-17 02:20:36 +04:00
sb - > s_blocksize = CIFS_MAX_MSGSIZE ;
sb - > s_blocksize_bits = 14 ; /* default 2**14 = CIFS_MAX_MSGSIZE */
2011-02-22 08:56:59 +03:00
inode = cifs_root_iget ( sb ) ;
2005-04-17 02:20:36 +04:00
2008-02-07 11:15:33 +03:00
if ( IS_ERR ( inode ) ) {
rc = PTR_ERR ( inode ) ;
2005-04-17 02:20:36 +04:00
goto out_no_root ;
}
2012-01-09 07:15:13 +04:00
sb - > s_root = d_make_root ( inode ) ;
2005-04-17 02:20:36 +04:00
if ( ! sb - > s_root ) {
rc = - ENOMEM ;
goto out_no_root ;
}
2007-07-13 04:33:32 +04:00
2012-04-28 16:13:53 +04:00
/* do that *after* d_make_root() - we want NULL ->d_op for root here */
2010-12-18 19:43:51 +03:00
if ( cifs_sb_master_tcon ( cifs_sb ) - > nocase )
sb - > s_d_op = & cifs_ci_dentry_ops ;
else
sb - > s_d_op = & cifs_dentry_ops ;
2011-10-12 16:14:04 +04:00
# ifdef CONFIG_CIFS_NFSD_EXPORT
2007-07-11 22:30:34 +04:00
if ( cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM ) {
2010-04-21 07:50:45 +04:00
cFYI ( 1 , " export ops supported " ) ;
2007-07-11 22:30:34 +04:00
sb - > s_export_op = & cifs_export_ops ;
}
2011-10-12 16:14:04 +04:00
# endif /* CONFIG_CIFS_NFSD_EXPORT */
2005-04-17 02:20:36 +04:00
return 0 ;
out_no_root :
2010-04-21 07:50:45 +04:00
cERROR ( 1 , " cifs_read_super: get root inode failed " ) ;
2005-04-17 02:20:36 +04:00
return rc ;
}
2011-06-17 16:34:57 +04:00
static void cifs_kill_sb ( struct super_block * sb )
{
struct cifs_sb_info * cifs_sb = CIFS_SB ( sb ) ;
kill_anon_super ( sb ) ;
2011-06-17 17:32:10 +04:00
cifs_umount ( cifs_sb ) ;
2005-04-17 02:20:36 +04:00
}
static int
2006-06-23 13:02:58 +04:00
cifs_statfs ( struct dentry * dentry , struct kstatfs * buf )
2005-04-17 02:20:36 +04:00
{
2006-06-23 13:02:58 +04:00
struct super_block * sb = dentry - > d_sb ;
2008-04-28 08:04:34 +04:00
struct cifs_sb_info * cifs_sb = CIFS_SB ( sb ) ;
2011-05-27 08:34:02 +04:00
struct cifs_tcon * tcon = cifs_sb_master_tcon ( cifs_sb ) ;
2012-09-19 03:20:33 +04:00
struct TCP_Server_Info * server = tcon - > ses - > server ;
2012-06-20 11:21:16 +04:00
unsigned int xid ;
2012-09-19 03:20:33 +04:00
int rc = 0 ;
2005-04-17 02:20:36 +04:00
2012-06-20 11:21:16 +04:00
xid = get_xid ( ) ;
2005-04-17 02:20:36 +04:00
2008-04-28 08:04:34 +04:00
/*
* PATH_MAX may be too long - it would presumably be total path ,
* but note that some servers ( includinng Samba 3 ) have a shorter
* maximum path .
*
* Instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO .
*/
buf - > f_namelen = PATH_MAX ;
2005-04-17 02:20:36 +04:00
buf - > f_files = 0 ; /* undefined */
buf - > f_ffree = 0 ; /* unlimited */
2012-09-19 03:20:33 +04:00
if ( server - > ops - > queryfs )
rc = server - > ops - > queryfs ( xid , tcon , buf ) ;
2008-04-28 08:04:34 +04:00
2012-06-20 11:21:16 +04:00
free_xid ( xid ) ;
2008-04-28 08:04:34 +04:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
2011-06-21 03:28:19 +04:00
static int cifs_permission ( struct inode * inode , int mask )
2005-04-17 02:20:36 +04:00
{
struct cifs_sb_info * cifs_sb ;
cifs_sb = CIFS_SB ( inode - > i_sb ) ;
2008-07-31 15:41:58 +04:00
if ( cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_NO_PERM ) {
if ( ( mask & MAY_EXEC ) & & ! execute_ok ( inode ) )
return - EACCES ;
else
return 0 ;
} else /* file mode might have been restricted at mount time
2007-07-13 04:33:32 +04:00
on the client ( above and beyond ACL on servers ) for
2005-04-17 02:20:36 +04:00
servers which do not support setting and viewing mode bits ,
2007-07-13 04:33:32 +04:00
so allowing client to check permissions is useful */
2011-06-21 03:16:29 +04:00
return generic_permission ( inode , mask ) ;
2005-04-17 02:20:36 +04:00
}
2006-12-07 07:33:20 +03:00
static struct kmem_cache * cifs_inode_cachep ;
static struct kmem_cache * cifs_req_cachep ;
static struct kmem_cache * cifs_mid_cachep ;
static struct kmem_cache * cifs_sm_req_cachep ;
2005-04-17 02:20:36 +04:00
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 ;
2006-12-07 07:33:17 +03:00
cifs_inode = kmem_cache_alloc ( cifs_inode_cachep , GFP_KERNEL ) ;
2005-04-17 02:20:36 +04:00
if ( ! cifs_inode )
return NULL ;
cifs_inode - > cifsAttrs = 0x20 ; /* default */
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 */
2010-11-03 10:58:57 +03:00
cifs_set_oplock_level ( cifs_inode , 0 ) ;
2008-10-18 05:03:20 +04:00
cifs_inode - > delete_pending = false ;
2010-02-12 15:44:16 +03:00
cifs_inode - > invalid_mapping = false ;
2005-04-17 02:20:36 +04:00
cifs_inode - > vfs_inode . i_blkbits = 14 ; /* 2**14 = CIFS_MAX_MSGSIZE */
2009-04-03 21:44:00 +04:00
cifs_inode - > server_eof = 0 ;
2011-01-07 19:30:27 +03:00
cifs_inode - > uniqueid = 0 ;
cifs_inode - > createtime = 0 ;
2007-07-13 04:33:32 +04:00
2007-02-17 07:30:54 +03:00
/* Can not set i_flags here - they get immediately overwritten
to zero by the VFS */
/* cifs_inode->vfs_inode.i_flags = S_NOATIME | S_NOCMTIME;*/
2005-04-17 02:20:36 +04:00
INIT_LIST_HEAD ( & cifs_inode - > openFileList ) ;
return & cifs_inode - > vfs_inode ;
}
2011-01-07 09:49:49 +03:00
static void cifs_i_callback ( struct rcu_head * head )
{
struct inode * inode = container_of ( head , struct inode , i_rcu ) ;
kmem_cache_free ( cifs_inode_cachep , CIFS_I ( inode ) ) ;
}
2005-04-17 02:20:36 +04:00
static void
cifs_destroy_inode ( struct inode * inode )
{
2011-01-07 09:49:49 +03:00
call_rcu ( & inode - > i_rcu , cifs_i_callback ) ;
2005-04-17 02:20:36 +04:00
}
2010-07-05 16:42:45 +04:00
static void
2010-06-07 22:34:48 +04:00
cifs_evict_inode ( struct inode * inode )
2010-07-05 16:42:45 +04:00
{
2010-06-07 22:34:48 +04:00
truncate_inode_pages ( & inode - > i_data , 0 ) ;
2012-05-03 16:48:02 +04:00
clear_inode ( inode ) ;
2010-07-05 16:42:45 +04:00
cifs_fscache_release_inode_cookie ( inode ) ;
}
2009-06-11 18:27:32 +04:00
static void
cifs_show_address ( struct seq_file * s , struct TCP_Server_Info * server )
{
2010-12-13 19:08:35 +03:00
struct sockaddr_in * sa = ( struct sockaddr_in * ) & server - > dstaddr ;
struct sockaddr_in6 * sa6 = ( struct sockaddr_in6 * ) & server - > dstaddr ;
2009-06-11 18:27:32 +04:00
seq_printf ( s , " ,addr= " ) ;
2010-12-13 19:08:35 +03:00
switch ( server - > dstaddr . ss_family ) {
2009-06-11 18:27:32 +04:00
case AF_INET :
2010-12-13 19:08:35 +03:00
seq_printf ( s , " %pI4 " , & sa - > sin_addr . s_addr ) ;
2009-06-11 18:27:32 +04:00
break ;
case AF_INET6 :
2010-12-13 19:08:35 +03:00
seq_printf ( s , " %pI6 " , & sa6 - > sin6_addr . s6_addr ) ;
if ( sa6 - > sin6_scope_id )
seq_printf ( s , " %%%u " , sa6 - > sin6_scope_id ) ;
2009-06-11 18:27:32 +04:00
break ;
default :
seq_printf ( s , " (unknown) " ) ;
}
}
2011-06-13 19:50:41 +04:00
static void
cifs_show_security ( struct seq_file * s , struct TCP_Server_Info * server )
{
seq_printf ( s , " ,sec= " ) ;
switch ( server - > secType ) {
case LANMAN :
seq_printf ( s , " lanman " ) ;
break ;
case NTLMv2 :
seq_printf ( s , " ntlmv2 " ) ;
break ;
case NTLM :
seq_printf ( s , " ntlm " ) ;
break ;
case Kerberos :
seq_printf ( s , " krb5 " ) ;
break ;
case RawNTLMSSP :
seq_printf ( s , " ntlmssp " ) ;
break ;
default :
/* shouldn't ever happen */
seq_printf ( s , " unknown " ) ;
break ;
}
if ( server - > sec_mode & ( SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED ) )
seq_printf ( s , " i " ) ;
}
2012-05-16 15:53:01 +04:00
static void
cifs_show_cache_flavor ( struct seq_file * s , struct cifs_sb_info * cifs_sb )
{
seq_printf ( s , " ,cache= " ) ;
if ( cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_STRICT_IO )
seq_printf ( s , " strict " ) ;
else if ( cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO )
seq_printf ( s , " none " ) ;
else
seq_printf ( s , " loose " ) ;
}
2005-04-17 02:20:36 +04:00
/*
* 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
2011-12-09 06:32:45 +04:00
cifs_show_options ( struct seq_file * s , struct dentry * root )
2005-04-17 02:20:36 +04:00
{
2011-12-09 06:32:45 +04:00
struct cifs_sb_info * cifs_sb = CIFS_SB ( root - > d_sb ) ;
2011-05-27 08:34:02 +04:00
struct cifs_tcon * tcon = cifs_sb_master_tcon ( cifs_sb ) ;
2010-09-02 04:06:02 +04:00
struct sockaddr * srcaddr ;
srcaddr = ( struct sockaddr * ) & tcon - > ses - > server - > srcaddr ;
2009-06-11 18:27:28 +04:00
2012-05-15 20:20:51 +04:00
seq_printf ( s , " ,vers=%s " , tcon - > ses - > server - > vals - > version_string ) ;
2011-06-13 19:50:41 +04:00
cifs_show_security ( s , tcon - > ses - > server ) ;
2012-05-16 15:53:01 +04:00
cifs_show_cache_flavor ( s , cifs_sb ) ;
2011-06-13 19:50:41 +04:00
2009-08-28 18:11:10 +04:00
seq_printf ( s , " ,unc=%s " , tcon - > treeName ) ;
2010-09-30 03:51:12 +04:00
if ( cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_MULTIUSER )
seq_printf ( s , " ,multiuser " ) ;
2011-02-25 10:11:56 +03:00
else if ( tcon - > ses - > user_name )
seq_printf ( s , " ,username=%s " , tcon - > ses - > user_name ) ;
2010-09-30 03:51:12 +04:00
2009-06-11 18:27:28 +04:00
if ( tcon - > ses - > domainName )
seq_printf ( s , " ,domain=%s " , tcon - > ses - > domainName ) ;
2010-09-02 04:06:02 +04:00
if ( srcaddr - > sa_family ! = AF_UNSPEC ) {
struct sockaddr_in * saddr4 ;
struct sockaddr_in6 * saddr6 ;
saddr4 = ( struct sockaddr_in * ) srcaddr ;
saddr6 = ( struct sockaddr_in6 * ) srcaddr ;
if ( srcaddr - > sa_family = = AF_INET6 )
seq_printf ( s , " ,srcaddr=%pI6c " ,
& saddr6 - > sin6_addr ) ;
else if ( srcaddr - > sa_family = = AF_INET )
seq_printf ( s , " ,srcaddr=%pI4 " ,
& saddr4 - > sin_addr . s_addr ) ;
else
seq_printf ( s , " ,srcaddr=BAD-AF:%i " ,
( int ) ( srcaddr - > sa_family ) ) ;
}
2012-04-24 18:28:30 +04:00
seq_printf ( s , " ,uid=%u " , cifs_sb - > mnt_uid ) ;
2009-06-11 18:27:29 +04:00
if ( cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_OVERR_UID )
seq_printf ( s , " ,forceuid " ) ;
2009-08-03 20:45:10 +04:00
else
seq_printf ( s , " ,noforceuid " ) ;
2009-06-11 18:27:29 +04:00
2012-04-24 18:28:30 +04:00
seq_printf ( s , " ,gid=%u " , cifs_sb - > mnt_gid ) ;
2009-06-11 18:27:29 +04:00
if ( cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_OVERR_GID )
seq_printf ( s , " ,forcegid " ) ;
2009-08-03 20:45:10 +04:00
else
seq_printf ( s , " ,noforcegid " ) ;
2009-06-11 18:27:28 +04:00
2009-06-11 18:27:32 +04:00
cifs_show_address ( s , tcon - > ses - > server ) ;
2005-04-17 02:20:36 +04:00
2009-06-11 18:27:28 +04:00
if ( ! tcon - > unix_ext )
2011-07-26 11:22:14 +04:00
seq_printf ( s , " ,file_mode=0%ho,dir_mode=0%ho " ,
2008-05-17 07:12:45 +04:00
cifs_sb - > mnt_file_mode ,
cifs_sb - > mnt_dir_mode ) ;
2009-06-11 18:27:28 +04:00
if ( tcon - > seal )
seq_printf ( s , " ,seal " ) ;
if ( tcon - > nocase )
seq_printf ( s , " ,nocase " ) ;
if ( tcon - > retry )
seq_printf ( s , " ,hard " ) ;
2011-05-26 10:02:00 +04:00
if ( tcon - > unix_ext )
seq_printf ( s , " ,unix " ) ;
else
seq_printf ( s , " ,nounix " ) ;
2009-06-11 18:27:28 +04:00
if ( cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS )
seq_printf ( s , " ,posixpaths " ) ;
if ( cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_SET_UID )
seq_printf ( s , " ,setuids " ) ;
if ( cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM )
seq_printf ( s , " ,serverino " ) ;
2011-05-26 10:02:00 +04:00
if ( cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD )
seq_printf ( s , " ,rwpidforward " ) ;
if ( cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL )
seq_printf ( s , " ,forcemand " ) ;
2009-06-11 18:27:28 +04:00
if ( cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_NO_XATTR )
seq_printf ( s , " ,nouser_xattr " ) ;
if ( cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR )
seq_printf ( s , " ,mapchars " ) ;
if ( cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL )
seq_printf ( s , " ,sfu " ) ;
if ( cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_NO_BRL )
seq_printf ( s , " ,nobrl " ) ;
if ( cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL )
seq_printf ( s , " ,cifsacl " ) ;
if ( cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_DYNPERM )
seq_printf ( s , " ,dynperm " ) ;
2011-12-09 06:32:45 +04:00
if ( root - > d_sb - > s_flags & MS_POSIXACL )
2009-06-11 18:27:28 +04:00
seq_printf ( s , " ,acl " ) ;
2010-07-30 16:56:00 +04:00
if ( cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS )
seq_printf ( s , " ,mfsymlinks " ) ;
2010-11-24 15:19:07 +03:00
if ( cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_FSCACHE )
seq_printf ( s , " ,fsc " ) ;
2011-10-20 05:44:48 +04:00
if ( cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_NOSSYNC )
seq_printf ( s , " ,nostrictsync " ) ;
if ( cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_NO_PERM )
seq_printf ( s , " ,noperm " ) ;
2012-04-24 18:28:14 +04:00
if ( cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPUID )
seq_printf ( s , " ,backupuid=%u " , cifs_sb - > mnt_backupuid ) ;
if ( cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPGID )
seq_printf ( s , " ,backupgid=%u " , cifs_sb - > mnt_backupgid ) ;
2009-06-11 18:27:28 +04:00
2012-04-24 18:28:30 +04:00
seq_printf ( s , " ,rsize=%u " , cifs_sb - > rsize ) ;
seq_printf ( s , " ,wsize=%u " , cifs_sb - > wsize ) ;
2010-12-01 12:12:28 +03:00
/* convert actimeo and display it in seconds */
2012-04-25 15:10:14 +04:00
seq_printf ( s , " ,actimeo=%lu " , cifs_sb - > actimeo / HZ ) ;
2009-06-11 18:27:28 +04:00
2005-04-17 02:20:36 +04:00
return 0 ;
}
2008-04-24 15:21:56 +04:00
static void cifs_umount_begin ( struct super_block * sb )
2005-10-10 21:34:22 +04:00
{
2008-04-24 15:21:56 +04:00
struct cifs_sb_info * cifs_sb = CIFS_SB ( sb ) ;
2011-05-27 08:34:02 +04:00
struct cifs_tcon * tcon ;
2005-10-10 21:34:22 +04:00
2007-05-01 00:13:06 +04:00
if ( cifs_sb = = NULL )
2005-10-11 01:28:38 +04:00
return ;
2010-09-21 03:01:35 +04:00
tcon = cifs_sb_master_tcon ( cifs_sb ) ;
2008-11-15 19:12:47 +03:00
2010-10-18 21:59:37 +04:00
spin_lock ( & cifs_tcp_ses_lock ) ;
2009-06-26 07:25:49 +04:00
if ( ( tcon - > tc_count > 1 ) | | ( tcon - > tidStatus = = CifsExiting ) ) {
/* we have other mounts to same share or we have
already tried to force umount this and woken up
all waiting network requests , nothing to do */
2010-10-18 21:59:37 +04:00
spin_unlock ( & cifs_tcp_ses_lock ) ;
2009-06-26 07:25:49 +04:00
return ;
} else if ( tcon - > tc_count = = 1 )
2005-10-11 01:06:37 +04:00
tcon - > tidStatus = CifsExiting ;
2010-10-18 21:59:37 +04:00
spin_unlock ( & cifs_tcp_ses_lock ) ;
2005-10-11 01:06:37 +04:00
2006-07-15 02:37:11 +04:00
/* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */
2005-11-10 02:21:09 +03:00
/* cancel_notify_requests(tcon); */
2007-07-13 04:33:32 +04:00
if ( tcon - > ses & & tcon - > ses - > server ) {
2010-04-21 07:50:45 +04:00
cFYI ( 1 , " wake up tasks now - umount begin not complete " ) ;
2005-10-11 01:28:38 +04:00
wake_up_all ( & tcon - > ses - > server - > request_q ) ;
2005-11-30 07:55:11 +03:00
wake_up_all ( & tcon - > ses - > server - > response_q ) ;
msleep ( 1 ) ; /* yield */
/* we have to kick the requests once more */
wake_up_all ( & tcon - > ses - > server - > response_q ) ;
msleep ( 1 ) ;
2005-10-11 01:06:37 +04:00
}
2005-10-10 21:34:22 +04:00
return ;
}
2006-09-29 01:34:06 +04:00
# ifdef CONFIG_CIFS_STATS2
2011-12-09 05:51:13 +04:00
static int cifs_show_stats ( struct seq_file * s , struct dentry * root )
2006-09-29 01:34:06 +04:00
{
/* BB FIXME */
return 0 ;
}
# endif
2005-04-17 02:20:36 +04:00
static int cifs_remount ( struct super_block * sb , int * flags , char * data )
{
* flags | = MS_NODIRATIME ;
return 0 ;
}
2010-06-07 21:43:19 +04:00
static int cifs_drop_inode ( struct inode * inode )
2010-06-01 22:47:40 +04:00
{
struct cifs_sb_info * cifs_sb = CIFS_SB ( inode - > i_sb ) ;
2010-06-07 21:43:19 +04:00
/* no serverino => unconditional eviction */
return ! ( cifs_sb - > mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM ) | |
generic_drop_inode ( inode ) ;
2010-06-01 22:47:40 +04:00
}
2007-02-12 11:55:41 +03:00
static const struct super_operations cifs_super_ops = {
2005-04-17 02:20:36 +04:00
. statfs = cifs_statfs ,
. alloc_inode = cifs_alloc_inode ,
. destroy_inode = cifs_destroy_inode ,
2010-06-01 22:47:40 +04:00
. drop_inode = cifs_drop_inode ,
2010-06-07 22:34:48 +04:00
. evict_inode = cifs_evict_inode ,
2010-06-01 22:47:40 +04:00
/* .delete_inode = cifs_delete_inode, */ /* Do not need above
function unless later we add lazy close of inodes or unless the
2007-07-13 04:33:32 +04:00
kernel forgets to call us with the same number of releases ( closes )
as opens */
2005-04-17 02:20:36 +04:00
. show_options = cifs_show_options ,
2005-11-10 02:21:09 +03:00
. umount_begin = cifs_umount_begin ,
2005-04-17 02:20:36 +04:00
. remount_fs = cifs_remount ,
2006-09-29 01:34:06 +04:00
# ifdef CONFIG_CIFS_STATS2
2006-09-30 05:08:55 +04:00
. show_stats = cifs_show_stats ,
2006-09-29 01:34:06 +04:00
# endif
2005-04-17 02:20:36 +04:00
} ;
2011-05-27 07:50:55 +04:00
/*
* Get root dentry from superblock according to prefix path mount option .
* Return dentry with refcount + 1 on success and NULL otherwise .
*/
static struct dentry *
cifs_get_root ( struct smb_vol * vol , struct super_block * sb )
{
2011-07-18 21:50:40 +04:00
struct dentry * dentry ;
2011-05-27 07:50:55 +04:00
struct cifs_sb_info * cifs_sb = CIFS_SB ( sb ) ;
2011-07-18 21:50:40 +04:00
char * full_path = NULL ;
char * s , * p ;
2011-05-27 07:50:55 +04:00
char sep ;
2012-05-27 20:39:52 +04:00
full_path = build_path_to_root ( vol , cifs_sb ,
cifs_sb_master_tcon ( cifs_sb ) ) ;
2011-05-27 07:50:55 +04:00
if ( full_path = = NULL )
2011-06-17 18:02:59 +04:00
return ERR_PTR ( - ENOMEM ) ;
2011-05-27 07:50:55 +04:00
cFYI ( 1 , " Get root dentry for %s " , full_path ) ;
sep = CIFS_DIR_SEP ( cifs_sb ) ;
2011-07-18 21:50:40 +04:00
dentry = dget ( sb - > s_root ) ;
p = s = full_path ;
do {
struct inode * dir = dentry - > d_inode ;
struct dentry * child ;
2011-08-21 19:30:15 +04:00
if ( ! dir ) {
dput ( dentry ) ;
dentry = ERR_PTR ( - ENOENT ) ;
break ;
}
2011-07-18 21:50:40 +04:00
/* skip separators */
while ( * s = = sep )
s + + ;
if ( ! * s )
break ;
p = s + + ;
/* next separator */
while ( * s & & * s ! = sep )
s + + ;
mutex_lock ( & dir - > i_mutex ) ;
child = lookup_one_len ( p , dentry , s - p ) ;
mutex_unlock ( & dir - > i_mutex ) ;
dput ( dentry ) ;
dentry = child ;
} while ( ! IS_ERR ( dentry ) ) ;
2011-05-27 07:50:55 +04:00
kfree ( full_path ) ;
2011-07-18 21:50:40 +04:00
return dentry ;
2011-05-27 07:50:55 +04:00
}
2011-06-17 17:47:23 +04:00
static int cifs_set_super ( struct super_block * sb , void * data )
{
struct cifs_mnt_data * mnt_data = data ;
sb - > s_fs_info = mnt_data - > cifs_sb ;
return set_anon_super ( sb , NULL ) ;
}
2010-07-26 12:52:33 +04:00
static struct dentry *
cifs_do_mount ( struct file_system_type * fs_type ,
2011-05-05 13:55:12 +04:00
int flags , const char * dev_name , void * data )
2005-04-17 02:20:36 +04:00
{
int rc ;
2010-08-16 00:51:10 +04:00
struct super_block * sb ;
2011-05-05 13:55:12 +04:00
struct cifs_sb_info * cifs_sb ;
struct smb_vol * volume_info ;
2011-05-26 23:35:47 +04:00
struct cifs_mnt_data mnt_data ;
2011-05-05 13:55:12 +04:00
struct dentry * root ;
2005-04-17 02:20:36 +04:00
2010-04-21 07:50:45 +04:00
cFYI ( 1 , " Devname: %s flags: %d " , dev_name , flags ) ;
2005-04-17 02:20:36 +04:00
2011-07-06 16:10:38 +04:00
volume_info = cifs_get_volume_info ( ( char * ) data , dev_name ) ;
if ( IS_ERR ( volume_info ) )
return ERR_CAST ( volume_info ) ;
2011-05-05 13:55:12 +04:00
cifs_sb = kzalloc ( sizeof ( struct cifs_sb_info ) , GFP_KERNEL ) ;
if ( cifs_sb = = NULL ) {
root = ERR_PTR ( - ENOMEM ) ;
2011-06-17 17:56:55 +04:00
goto out_nls ;
2011-05-05 13:55:12 +04:00
}
2011-06-17 17:17:28 +04:00
cifs_sb - > mountdata = kstrndup ( data , PAGE_SIZE , GFP_KERNEL ) ;
if ( cifs_sb - > mountdata = = NULL ) {
root = ERR_PTR ( - ENOMEM ) ;
2011-06-17 17:56:55 +04:00
goto out_cifs_sb ;
2011-06-17 17:17:28 +04:00
}
2011-05-05 13:55:12 +04:00
cifs_setup_cifs_sb ( volume_info , cifs_sb ) ;
2011-06-17 17:29:57 +04:00
rc = cifs_mount ( cifs_sb , volume_info ) ;
if ( rc ) {
if ( ! ( flags & MS_SILENT ) )
cERROR ( 1 , " cifs_mount failed w/return code = %d " , rc ) ;
root = ERR_PTR ( rc ) ;
2011-06-17 17:56:55 +04:00
goto out_mountdata ;
2011-06-17 17:29:57 +04:00
}
2011-05-26 23:35:47 +04:00
mnt_data . vol = volume_info ;
mnt_data . cifs_sb = cifs_sb ;
mnt_data . flags = flags ;
2012-06-25 15:55:37 +04:00
/* BB should we make this contingent on mount parm? */
flags | = MS_NODIRATIME | MS_NOATIME ;
sb = sget ( fs_type , cifs_match_super , cifs_set_super , flags , & mnt_data ) ;
2011-05-05 13:55:12 +04:00
if ( IS_ERR ( sb ) ) {
root = ERR_CAST ( sb ) ;
2011-06-17 17:29:57 +04:00
cifs_umount ( cifs_sb ) ;
2011-06-17 17:42:43 +04:00
goto out ;
2011-05-05 13:55:12 +04:00
}
2005-04-17 02:20:36 +04:00
2011-06-17 17:47:23 +04:00
if ( sb - > s_root ) {
2011-05-26 23:35:47 +04:00
cFYI ( 1 , " Use existing superblock " ) ;
2011-06-17 17:29:57 +04:00
cifs_umount ( cifs_sb ) ;
2011-06-17 17:56:55 +04:00
} else {
rc = cifs_read_super ( sb ) ;
if ( rc ) {
root = ERR_PTR ( rc ) ;
goto out_super ;
}
2011-05-25 13:35:34 +04:00
2011-06-17 17:56:55 +04:00
sb - > s_flags | = MS_ACTIVE ;
2005-04-17 02:20:36 +04:00
}
2011-05-05 13:55:12 +04:00
2011-05-27 07:50:55 +04:00
root = cifs_get_root ( volume_info , sb ) ;
2011-06-17 18:02:59 +04:00
if ( IS_ERR ( root ) )
2011-05-27 07:50:55 +04:00
goto out_super ;
2011-05-26 23:35:47 +04:00
2011-05-27 07:50:55 +04:00
cFYI ( 1 , " dentry root is: %p " , root ) ;
2011-05-26 00:02:16 +04:00
goto out ;
2011-05-05 13:55:12 +04:00
2011-05-26 00:02:16 +04:00
out_super :
deactivate_locked_super ( sb ) ;
out :
2011-07-06 16:10:37 +04:00
cifs_cleanup_volume_info ( volume_info ) ;
2011-05-05 13:55:12 +04:00
return root ;
2011-06-17 17:56:55 +04:00
out_mountdata :
kfree ( cifs_sb - > mountdata ) ;
out_cifs_sb :
kfree ( cifs_sb ) ;
out_nls :
unload_nls ( volume_info - > local_nls ) ;
goto out ;
2005-04-17 02:20:36 +04:00
}
2006-10-01 10:28:46 +04:00
static ssize_t cifs_file_aio_write ( struct kiocb * iocb , const struct iovec * iov ,
unsigned long nr_segs , loff_t pos )
2005-04-17 02:20:36 +04:00
{
2006-12-08 13:36:48 +03:00
struct inode * inode = iocb - > ki_filp - > f_path . dentry - > d_inode ;
2005-04-17 02:20:36 +04:00
ssize_t written ;
2011-01-24 22:16:35 +03:00
int rc ;
2005-04-17 02:20:36 +04:00
2006-10-01 10:28:46 +04:00
written = generic_file_aio_write ( iocb , iov , nr_segs , pos ) ;
2011-01-24 22:16:35 +03:00
if ( CIFS_I ( inode ) - > clientCanCacheAll )
return written ;
rc = filemap_fdatawrite ( inode - > i_mapping ) ;
if ( rc )
cFYI ( 1 , " cifs_file_aio_write: %d rc on %p inode " , rc , inode ) ;
2005-04-17 02:20:36 +04:00
return written ;
}
2006-01-13 01:41:28 +03:00
static loff_t cifs_llseek ( struct file * file , loff_t offset , int origin )
{
2011-07-18 21:21:38 +04:00
/*
* origin = = SEEK_END | | SEEK_DATA | | SEEK_HOLE = > we must revalidate
* the cached file length
*/
2012-04-30 18:36:21 +04:00
if ( origin ! = SEEK_SET & & origin ! = SEEK_CUR ) {
2011-04-07 18:18:11 +04:00
int rc ;
struct inode * inode = file - > f_path . dentry - > d_inode ;
/*
* We need to be sure that all dirty pages are written and the
* server has the newest file length .
*/
if ( ! CIFS_I ( inode ) - > clientCanCacheRead & & inode - > i_mapping & &
inode - > i_mapping - > nrpages ! = 0 ) {
rc = filemap_fdatawait ( inode - > i_mapping ) ;
2011-05-20 21:00:01 +04:00
if ( rc ) {
mapping_set_error ( inode - > i_mapping , rc ) ;
return rc ;
}
2011-04-07 18:18:11 +04:00
}
/*
* Some applications poll for the file length in this strange
* way so we must seek to end on non - oplocked files by
* setting the revalidate time to zero .
*/
CIFS_I ( inode ) - > time = 0 ;
rc = cifs_revalidate_file_attr ( file ) ;
if ( rc < 0 )
return ( loff_t ) rc ;
2006-01-13 01:41:28 +03:00
}
2011-09-16 03:06:48 +04:00
return generic_file_llseek ( file , offset , origin ) ;
2006-01-13 01:41:28 +03:00
}
2008-10-23 08:42:37 +04:00
static int cifs_setlease ( struct file * file , long arg , struct file_lock * * lease )
{
2010-09-18 17:09:31 +04:00
/* note that this is called by vfs setlease with lock_flocks held
to protect * lease from going away */
2008-10-23 08:42:37 +04:00
struct inode * inode = file - > f_path . dentry - > d_inode ;
2010-09-21 03:01:31 +04:00
struct cifsFileInfo * cfile = file - > private_data ;
2008-10-23 08:42:37 +04:00
if ( ! ( S_ISREG ( inode - > i_mode ) ) )
return - EINVAL ;
/* check if file is oplocked */
if ( ( ( arg = = F_RDLCK ) & &
( CIFS_I ( inode ) - > clientCanCacheRead ) ) | |
( ( arg = = F_WRLCK ) & &
( CIFS_I ( inode ) - > clientCanCacheAll ) ) )
return generic_setlease ( file , arg , lease ) ;
2010-09-30 03:51:11 +04:00
else if ( tlink_tcon ( cfile - > tlink ) - > local_lease & &
! CIFS_I ( inode ) - > clientCanCacheRead )
2008-10-23 08:42:37 +04:00
/* If the server claims to support oplock on this
file , then we still need to check oplock even
if the local_lease mount option is set , but there
are servers which do not support oplock for which
this mount option may be useful if the user
knows that the file won ' t be changed on the server
by anyone else */
return generic_setlease ( file , arg , lease ) ;
2010-10-31 15:35:10 +03:00
else
2008-10-23 08:42:37 +04:00
return - EAGAIN ;
}
2008-01-11 04:49:48 +03:00
struct file_system_type cifs_fs_type = {
2005-04-17 02:20:36 +04:00
. owner = THIS_MODULE ,
. name = " cifs " ,
2010-07-26 12:52:33 +04:00
. mount = cifs_do_mount ,
2011-06-17 16:34:57 +04:00
. kill_sb = cifs_kill_sb ,
2005-04-17 02:20:36 +04:00
/* .fs_flags */
} ;
2007-02-12 11:55:38 +03:00
const struct inode_operations cifs_dir_inode_ops = {
2005-04-17 02:20:36 +04:00
. create = cifs_create ,
2012-06-05 17:10:23 +04:00
. atomic_open = cifs_atomic_open ,
2005-04-17 02:20:36 +04:00
. 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
} ;
2007-02-12 11:55:38 +03:00
const struct inode_operations cifs_file_inode_ops = {
2005-04-17 02:20:36 +04:00
/* 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 ,
2007-07-13 04:33:32 +04:00
# endif
2005-04-17 02:20:36 +04:00
} ;
2007-02-12 11:55:38 +03:00
const struct inode_operations cifs_symlink_inode_ops = {
2007-07-13 04:33:32 +04:00
. readlink = generic_readlink ,
2005-04-17 02:20:36 +04:00
. 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 ,
2007-07-13 04:33:32 +04:00
# endif
2005-04-17 02:20:36 +04:00
} ;
2006-03-28 13:56:42 +04:00
const struct file_operations cifs_file_ops = {
2005-11-18 04:03:00 +03:00
. read = do_sync_read ,
. write = do_sync_write ,
. aio_read = generic_file_aio_read ,
. aio_write = cifs_file_aio_write ,
2005-04-17 02:20:36 +04:00
. open = cifs_open ,
. release = cifs_close ,
. lock = cifs_lock ,
. fsync = cifs_fsync ,
. flush = cifs_flush ,
. mmap = cifs_file_mmap ,
2007-06-01 13:49:19 +04:00
. splice_read = generic_file_splice_read ,
2006-01-13 01:41:28 +03:00
. llseek = cifs_llseek ,
2005-04-29 09:41:04 +04:00
# ifdef CONFIG_CIFS_POSIX
2008-05-15 09:51:55 +04:00
. unlocked_ioctl = cifs_ioctl ,
2005-04-29 09:41:04 +04:00
# endif /* CONFIG_CIFS_POSIX */
2008-10-23 08:42:37 +04:00
. setlease = cifs_setlease ,
2005-04-17 02:20:36 +04:00
} ;
2010-12-12 13:11:13 +03:00
const struct file_operations cifs_file_strict_ops = {
. read = do_sync_read ,
. write = do_sync_write ,
2010-12-14 11:50:41 +03:00
. aio_read = cifs_strict_readv ,
2011-01-24 22:16:35 +03:00
. aio_write = cifs_strict_writev ,
2010-12-12 13:11:13 +03:00
. open = cifs_open ,
. release = cifs_close ,
. lock = cifs_lock ,
. fsync = cifs_strict_fsync ,
. flush = cifs_flush ,
2010-12-14 11:29:51 +03:00
. mmap = cifs_file_strict_mmap ,
2010-12-12 13:11:13 +03:00
. splice_read = generic_file_splice_read ,
. llseek = cifs_llseek ,
# ifdef CONFIG_CIFS_POSIX
. unlocked_ioctl = cifs_ioctl ,
# endif /* CONFIG_CIFS_POSIX */
. setlease = cifs_setlease ,
} ;
2006-03-28 13:56:42 +04:00
const struct file_operations cifs_file_direct_ops = {
2011-03-10 10:11:05 +03:00
/* BB reevaluate whether they can be done with directio, no cache */
. read = do_sync_read ,
. write = do_sync_write ,
. aio_read = cifs_user_readv ,
. aio_write = cifs_user_writev ,
2005-04-17 02:20:36 +04:00
. open = cifs_open ,
. release = cifs_close ,
. lock = cifs_lock ,
. fsync = cifs_fsync ,
. flush = cifs_flush ,
2009-12-07 08:44:46 +03:00
. mmap = cifs_file_mmap ,
2007-06-01 13:49:19 +04:00
. splice_read = generic_file_splice_read ,
2005-04-29 09:41:04 +04:00
# ifdef CONFIG_CIFS_POSIX
2008-05-15 09:51:55 +04:00
. unlocked_ioctl = cifs_ioctl ,
2005-04-29 09:41:04 +04:00
# endif /* CONFIG_CIFS_POSIX */
2006-01-13 01:41:28 +03:00
. llseek = cifs_llseek ,
2008-10-23 08:42:37 +04:00
. setlease = cifs_setlease ,
2005-04-17 02:20:36 +04:00
} ;
2010-12-12 13:11:13 +03:00
2006-03-28 13:56:42 +04:00
const struct file_operations cifs_file_nobrl_ops = {
2005-11-18 04:03:00 +03:00
. read = do_sync_read ,
. write = do_sync_write ,
. aio_read = generic_file_aio_read ,
. aio_write = cifs_file_aio_write ,
. open = cifs_open ,
. release = cifs_close ,
. fsync = cifs_fsync ,
. flush = cifs_flush ,
. mmap = cifs_file_mmap ,
2007-06-01 13:49:19 +04:00
. splice_read = generic_file_splice_read ,
2006-01-13 01:41:28 +03:00
. llseek = cifs_llseek ,
2005-11-11 22:41:00 +03:00
# ifdef CONFIG_CIFS_POSIX
2008-05-15 09:51:55 +04:00
. unlocked_ioctl = cifs_ioctl ,
2005-11-11 22:41:00 +03:00
# endif /* CONFIG_CIFS_POSIX */
2008-10-23 08:42:37 +04:00
. setlease = cifs_setlease ,
2005-11-11 22:41:00 +03:00
} ;
2010-12-12 13:11:13 +03:00
const struct file_operations cifs_file_strict_nobrl_ops = {
. read = do_sync_read ,
. write = do_sync_write ,
2010-12-14 11:50:41 +03:00
. aio_read = cifs_strict_readv ,
2011-01-24 22:16:35 +03:00
. aio_write = cifs_strict_writev ,
2010-12-12 13:11:13 +03:00
. open = cifs_open ,
. release = cifs_close ,
. fsync = cifs_strict_fsync ,
. flush = cifs_flush ,
2010-12-14 11:29:51 +03:00
. mmap = cifs_file_strict_mmap ,
2010-12-12 13:11:13 +03:00
. splice_read = generic_file_splice_read ,
. llseek = cifs_llseek ,
# ifdef CONFIG_CIFS_POSIX
. unlocked_ioctl = cifs_ioctl ,
# endif /* CONFIG_CIFS_POSIX */
. setlease = cifs_setlease ,
} ;
2006-03-28 13:56:42 +04:00
const struct file_operations cifs_file_direct_nobrl_ops = {
2011-03-10 10:11:05 +03:00
/* BB reevaluate whether they can be done with directio, no cache */
. read = do_sync_read ,
. write = do_sync_write ,
. aio_read = cifs_user_readv ,
. aio_write = cifs_user_writev ,
2005-11-18 04:03:00 +03:00
. open = cifs_open ,
. release = cifs_close ,
. fsync = cifs_fsync ,
. flush = cifs_flush ,
2010-03-27 05:00:49 +03:00
. mmap = cifs_file_mmap ,
2007-06-01 13:49:19 +04:00
. splice_read = generic_file_splice_read ,
2005-11-11 22:41:00 +03:00
# ifdef CONFIG_CIFS_POSIX
2008-05-15 09:51:55 +04:00
. unlocked_ioctl = cifs_ioctl ,
2005-11-11 22:41:00 +03:00
# endif /* CONFIG_CIFS_POSIX */
2006-01-13 01:41:28 +03:00
. llseek = cifs_llseek ,
2008-10-23 08:42:37 +04:00
. setlease = cifs_setlease ,
2005-11-11 22:41:00 +03:00
} ;
2005-04-17 02:20:36 +04:00
2006-03-28 13:56:42 +04:00
const struct file_operations cifs_dir_ops = {
2005-04-17 02:20:36 +04:00
. readdir = cifs_readdir ,
. release = cifs_closedir ,
. read = generic_read_dir ,
2008-05-15 09:51:55 +04:00
. unlocked_ioctl = cifs_ioctl ,
2008-09-03 23:53:01 +04:00
. llseek = generic_file_llseek ,
2005-04-17 02:20:36 +04:00
} ;
static void
2008-07-26 06:45:34 +04:00
cifs_init_once ( void * inode )
2005-04-17 02:20:36 +04:00
{
struct cifsInodeInfo * cifsi = inode ;
2007-05-17 09:10:57 +04:00
inode_init_once ( & cifsi - > vfs_inode ) ;
2011-09-22 09:53:59 +04:00
mutex_init ( & cifsi - > lock_mutex ) ;
2005-04-17 02:20:36 +04:00
}
static int
cifs_init_inodecache ( void )
{
cifs_inode_cachep = kmem_cache_create ( " cifs_inode_cache " ,
2007-08-31 02:09:15 +04:00
sizeof ( struct cifsInodeInfo ) ,
2006-03-24 14:16:06 +03:00
0 , ( SLAB_RECLAIM_ACCOUNT |
SLAB_MEM_SPREAD ) ,
2007-07-20 05:11:58 +04:00
cifs_init_once ) ;
2005-04-17 02:20:36 +04:00
if ( cifs_inode_cachep = = NULL )
return - ENOMEM ;
return 0 ;
}
static void
cifs_destroy_inodecache ( void )
{
2006-09-27 12:49:40 +04:00
kmem_cache_destroy ( cifs_inode_cachep ) ;
2005-04-17 02:20:36 +04:00
}
static int
cifs_init_request_bufs ( void )
{
2012-01-12 22:40:50 +04:00
size_t max_hdr_size = MAX_CIFS_HDR_SIZE ;
# ifdef CONFIG_CIFS_SMB2
/*
* SMB2 maximum header size is bigger than CIFS one - no problems to
* allocate some more bytes for CIFS .
*/
max_hdr_size = MAX_SMB2_HDR_SIZE ;
# endif
2007-05-01 00:13:06 +04:00
if ( CIFSMaxBufSize < 8192 ) {
2005-04-17 02:20:36 +04:00
/* 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*/
}
2010-04-21 07:50:45 +04:00
/* cERROR(1, "CIFSMaxBufSize %d 0x%x",CIFSMaxBufSize,CIFSMaxBufSize); */
2005-04-17 02:20:36 +04:00
cifs_req_cachep = kmem_cache_create ( " cifs_request " ,
2012-01-12 22:40:50 +04:00
CIFSMaxBufSize + max_hdr_size , 0 ,
2007-07-20 05:11:58 +04:00
SLAB_HWCACHE_ALIGN , NULL ) ;
2005-04-17 02:20:36 +04:00
if ( cifs_req_cachep = = NULL )
return - ENOMEM ;
2007-05-01 00:13:06 +04:00
if ( cifs_min_rcv < 1 )
2005-04-17 02:20:36 +04:00
cifs_min_rcv = 1 ;
else if ( cifs_min_rcv > 64 ) {
cifs_min_rcv = 64 ;
2010-04-21 07:50:45 +04:00
cERROR ( 1 , " cifs_min_rcv set to maximum (64) " ) ;
2005-04-17 02:20:36 +04:00
}
2006-03-26 13:37:50 +04:00
cifs_req_poolp = mempool_create_slab_pool ( cifs_min_rcv ,
cifs_req_cachep ) ;
2005-04-17 02:20:36 +04:00
2007-05-01 00:13:06 +04:00
if ( cifs_req_poolp = = NULL ) {
2005-04-17 02:20:36 +04:00
kmem_cache_destroy ( cifs_req_cachep ) ;
return - ENOMEM ;
}
2005-12-13 07:53:18 +03:00
/* MAX_CIFS_SMALL_BUFFER_SIZE bytes is enough for most SMB responses and
2005-04-17 02:20:36 +04:00
almost all handle based requests ( but not write response , nor is it
sufficient for path based requests ) . A smaller size would have
2007-07-13 04:33:32 +04:00
been more efficient ( compacting multiple slab items on one 4 k page )
2005-04-17 02:20:36 +04:00
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
2007-07-07 03:13:06 +04:00
efficient to alloc 1 per page off the slab compared to 17 K ( 5 page )
2005-04-17 02:20:36 +04:00
alloc of large cifs buffers even when page debugging is on */
cifs_sm_req_cachep = kmem_cache_create ( " cifs_small_rq " ,
2007-07-07 03:13:06 +04:00
MAX_CIFS_SMALL_BUFFER_SIZE , 0 , SLAB_HWCACHE_ALIGN ,
2007-07-20 05:11:58 +04:00
NULL ) ;
2005-04-17 02:20:36 +04:00
if ( cifs_sm_req_cachep = = NULL ) {
mempool_destroy ( cifs_req_poolp ) ;
kmem_cache_destroy ( cifs_req_cachep ) ;
2007-07-07 03:13:06 +04:00
return - ENOMEM ;
2005-04-17 02:20:36 +04:00
}
2007-05-01 00:13:06 +04:00
if ( cifs_min_small < 2 )
2005-04-17 02:20:36 +04:00
cifs_min_small = 2 ;
else if ( cifs_min_small > 256 ) {
cifs_min_small = 256 ;
2010-04-21 07:50:45 +04:00
cFYI ( 1 , " cifs_min_small set to maximum (256) " ) ;
2005-04-17 02:20:36 +04:00
}
2006-03-26 13:37:50 +04:00
cifs_sm_req_poolp = mempool_create_slab_pool ( cifs_min_small ,
cifs_sm_req_cachep ) ;
2005-04-17 02:20:36 +04:00
2007-05-01 00:13:06 +04:00
if ( cifs_sm_req_poolp = = NULL ) {
2005-04-17 02:20:36 +04:00
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 ) ;
2006-09-27 12:49:40 +04:00
kmem_cache_destroy ( cifs_req_cachep ) ;
2005-04-17 02:20:36 +04:00
mempool_destroy ( cifs_sm_req_poolp ) ;
2006-09-27 12:49:40 +04:00
kmem_cache_destroy ( cifs_sm_req_cachep ) ;
2005-04-17 02:20:36 +04:00
}
static int
cifs_init_mids ( void )
{
cifs_mid_cachep = kmem_cache_create ( " cifs_mpx_ids " ,
2007-08-31 02:09:15 +04:00
sizeof ( struct mid_q_entry ) , 0 ,
SLAB_HWCACHE_ALIGN , NULL ) ;
2005-04-17 02:20:36 +04:00
if ( cifs_mid_cachep = = NULL )
return - ENOMEM ;
2006-03-26 13:37:50 +04:00
/* 3 is a reasonable minimum number of simultaneous operations */
cifs_mid_poolp = mempool_create_slab_pool ( 3 , cifs_mid_cachep ) ;
2007-05-01 00:13:06 +04:00
if ( cifs_mid_poolp = = NULL ) {
2005-04-17 02:20:36 +04:00
kmem_cache_destroy ( cifs_mid_cachep ) ;
return - ENOMEM ;
}
return 0 ;
}
static void
cifs_destroy_mids ( void )
{
mempool_destroy ( cifs_mid_poolp ) ;
2006-09-27 12:49:40 +04:00
kmem_cache_destroy ( cifs_mid_cachep ) ;
2005-04-17 02:20:36 +04:00
}
static int __init
init_cifs ( void )
{
int rc = 0 ;
cifs_proc_init ( ) ;
2008-11-14 21:44:38 +03:00
INIT_LIST_HEAD ( & cifs_tcp_ses_list ) ;
2011-02-24 08:39:23 +03:00
# ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* unused temporarily */
2005-10-11 06:52:13 +04:00
INIT_LIST_HEAD ( & GlobalDnotifyReqList ) ;
INIT_LIST_HEAD ( & GlobalDnotifyRsp_Q ) ;
2011-02-24 08:39:23 +03:00
# endif /* was needed for dnotify, and will be needed for inotify when VFS fix */
2005-04-17 02:20:36 +04:00
/*
* Initialize Global counters
*/
atomic_set ( & sesInfoAllocCount , 0 ) ;
atomic_set ( & tconInfoAllocCount , 0 ) ;
2007-07-07 03:13:06 +04:00
atomic_set ( & tcpSesAllocCount , 0 ) ;
2005-04-17 02:20:36 +04:00
atomic_set ( & tcpSesReconnectCount , 0 ) ;
atomic_set ( & tconInfoReconnectCount , 0 ) ;
atomic_set ( & bufAllocCount , 0 ) ;
2005-12-04 00:58:57 +03:00
atomic_set ( & smBufAllocCount , 0 ) ;
# ifdef CONFIG_CIFS_STATS2
atomic_set ( & totBufAllocCount , 0 ) ;
atomic_set ( & totSmBufAllocCount , 0 ) ;
# endif /* CONFIG_CIFS_STATS2 */
2005-04-17 02:20:36 +04:00
atomic_set ( & midCount , 0 ) ;
GlobalCurrentXid = 0 ;
GlobalTotalActiveXid = 0 ;
GlobalMaxActiveXid = 0 ;
2010-10-18 21:59:37 +04:00
spin_lock_init ( & cifs_tcp_ses_lock ) ;
2010-10-15 23:34:03 +04:00
spin_lock_init ( & cifs_file_list_lock ) ;
2005-04-17 02:20:36 +04:00
spin_lock_init ( & GlobalMid_Lock ) ;
2007-05-01 00:13:06 +04:00
if ( cifs_max_pending < 2 ) {
2005-04-17 02:20:36 +04:00
cifs_max_pending = 2 ;
2010-04-21 07:50:45 +04:00
cFYI ( 1 , " cifs_max_pending set to min of 2 " ) ;
2012-03-20 13:55:09 +04:00
} else if ( cifs_max_pending > CIFS_MAX_REQ ) {
cifs_max_pending = CIFS_MAX_REQ ;
cFYI ( 1 , " cifs_max_pending set to max of %u " , CIFS_MAX_REQ ) ;
2005-04-17 02:20:36 +04:00
}
2012-03-23 22:40:53 +04:00
cifsiod_wq = alloc_workqueue ( " cifsiod " , WQ_FREEZABLE | WQ_MEM_RECLAIM , 0 ) ;
if ( ! cifsiod_wq ) {
rc = - ENOMEM ;
goto out_clean_proc ;
}
2010-07-05 16:41:50 +04:00
rc = cifs_fscache_register ( ) ;
if ( rc )
2012-03-23 22:40:53 +04:00
goto out_destroy_wq ;
2010-07-05 16:41:50 +04:00
2005-04-17 02:20:36 +04:00
rc = cifs_init_inodecache ( ) ;
2006-04-22 02:52:25 +04:00
if ( rc )
2010-09-22 23:15:36 +04:00
goto out_unreg_fscache ;
2006-04-22 02:52:25 +04:00
rc = cifs_init_mids ( ) ;
if ( rc )
goto out_destroy_inodecache ;
rc = cifs_init_request_bufs ( ) ;
if ( rc )
goto out_destroy_mids ;
2007-11-03 08:02:24 +03:00
# ifdef CONFIG_CIFS_UPCALL
rc = register_key_type ( & cifs_spnego_key_type ) ;
if ( rc )
2011-04-28 08:34:35 +04:00
goto out_destroy_request_bufs ;
# endif /* CONFIG_CIFS_UPCALL */
# ifdef CONFIG_CIFS_ACL
rc = init_cifs_idmap ( ) ;
if ( rc )
2011-05-06 11:35:00 +04:00
goto out_register_key_type ;
2011-04-28 08:34:35 +04:00
# endif /* CONFIG_CIFS_ACL */
rc = register_filesystem ( & cifs_fs_type ) ;
if ( rc )
2011-05-06 11:35:00 +04:00
goto out_init_cifs_idmap ;
2006-04-22 02:52:25 +04:00
return 0 ;
2011-05-06 11:35:00 +04:00
out_init_cifs_idmap :
2011-04-28 08:34:35 +04:00
# ifdef CONFIG_CIFS_ACL
exit_cifs_idmap ( ) ;
2011-05-06 11:35:00 +04:00
out_register_key_type :
2011-04-28 08:34:35 +04:00
# endif
2007-11-03 08:02:24 +03:00
# ifdef CONFIG_CIFS_UPCALL
2011-04-28 08:34:35 +04:00
unregister_key_type ( & cifs_spnego_key_type ) ;
2011-05-06 11:35:00 +04:00
out_destroy_request_bufs :
2010-08-07 23:54:46 +04:00
# endif
2006-04-22 02:52:25 +04:00
cifs_destroy_request_bufs ( ) ;
2010-09-22 23:15:36 +04:00
out_destroy_mids :
2006-04-22 02:52:25 +04:00
cifs_destroy_mids ( ) ;
2010-09-22 23:15:36 +04:00
out_destroy_inodecache :
2006-04-22 02:52:25 +04:00
cifs_destroy_inodecache ( ) ;
2010-09-22 23:15:36 +04:00
out_unreg_fscache :
2010-07-05 16:41:50 +04:00
cifs_fscache_unregister ( ) ;
2012-03-23 22:40:53 +04:00
out_destroy_wq :
destroy_workqueue ( cifsiod_wq ) ;
2010-09-22 23:15:36 +04:00
out_clean_proc :
cifs_proc_clean ( ) ;
2005-04-17 02:20:36 +04:00
return rc ;
}
static void __exit
exit_cifs ( void )
{
2010-04-21 07:50:45 +04:00
cFYI ( DBG2 , " exit_cifs " ) ;
2012-03-21 14:27:55 +04:00
unregister_filesystem ( & cifs_fs_type ) ;
2008-04-24 12:56:07 +04:00
cifs_dfs_release_automount_timer ( ) ;
2011-04-28 08:34:35 +04:00
# ifdef CONFIG_CIFS_ACL
cifs_destroy_idmaptrees ( ) ;
exit_cifs_idmap ( ) ;
# endif
2007-11-03 08:02:24 +03:00
# ifdef CONFIG_CIFS_UPCALL
unregister_key_type ( & cifs_spnego_key_type ) ;
2005-04-17 02:20:36 +04:00
# endif
cifs_destroy_request_bufs ( ) ;
2012-03-21 14:27:55 +04:00
cifs_destroy_mids ( ) ;
cifs_destroy_inodecache ( ) ;
cifs_fscache_unregister ( ) ;
2012-03-23 22:40:53 +04:00
destroy_workqueue ( cifsiod_wq ) ;
2012-03-21 14:27:55 +04:00
cifs_proc_clean ( ) ;
2005-04-17 02:20:36 +04:00
}
MODULE_AUTHOR ( " Steve French <sfrench@us.ibm.com> " ) ;
2007-07-07 03:13:06 +04:00
MODULE_LICENSE ( " GPL " ) ; /* combination of LGPL + GPL source behaves as GPL */
2005-04-17 02:20:36 +04:00
MODULE_DESCRIPTION
2007-07-17 21:34:02 +04:00
( " VFS to access servers complying with the SNIA CIFS Specification "
" e.g. Samba and Windows " ) ;
2005-04-17 02:20:36 +04:00
MODULE_VERSION ( CIFS_VERSION ) ;
module_init ( init_cifs )
module_exit ( exit_cifs )