/*
* fs/cifs/cifsfs.c
*
- * Copyright (C) International Business Machines Corp., 2002,2004
+ * Copyright (C) International Business Machines Corp., 2002,2007
* Author(s): Steve French (sfrench@us.ibm.com)
*
* Common Internet FileSystem (CIFS) client
#include <linux/mempool.h>
#include <linux/delay.h>
#include <linux/kthread.h>
+#include <linux/freezer.h>
#include "cifsfs.h"
#include "cifspdu.h"
#define DECLARE_GLOBALS_HERE
#ifdef CONFIG_CIFS_QUOTA
static struct quotactl_ops cifs_quotactl_ops;
-#endif
+#endif /* QUOTA */
+
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+extern struct export_operations cifs_export_ops;
+#endif /* EXPERIMENTAL */
int cifsFYI = 0;
int cifsERROR = 1;
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;
-static struct super_operations cifs_super_ops;
+/* extern struct task_struct * dnotifyThread; remove sparse warning */
+static struct task_struct * dnotifyThread = NULL;
+static const struct super_operations cifs_super_ops;
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");
extern mempool_t *cifs_req_poolp;
extern mempool_t *cifs_mid_poolp;
-extern kmem_cache_t *cifs_oplock_cachep;
+extern struct kmem_cache *cifs_oplock_cachep;
static int
cifs_read_super(struct super_block *sb, void *data,
struct inode *inode;
struct cifs_sb_info *cifs_sb;
int rc = 0;
-
- sb->s_flags |= MS_NODIRATIME; /* and probably even noatime */
+
+ /* BB should we make this contingent on mount parm? */
+ sb->s_flags |= MS_NODIRATIME | MS_NOATIME;
sb->s_fs_info = kzalloc(sizeof(struct cifs_sb_info),GFP_KERNEL);
cifs_sb = CIFS_SB(sb);
- if(cifs_sb == NULL)
+ if (cifs_sb == NULL)
return -ENOMEM;
rc = cifs_mount(sb, cifs_sb, data, devname);
sb->s_magic = CIFS_MAGIC_NUMBER;
sb->s_op = &cifs_super_ops;
-/* if(cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512)
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+ if (experimEnabled != 0)
+ sb->s_export_op = &cifs_export_ops;
+#endif /* EXPERIMENTAL */
+/* 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;
iput(inode);
out_mount_failed:
- if(cifs_sb) {
- if(cifs_sb->local_nls)
+ if (cifs_sb) {
+ if (cifs_sb->local_nls)
unload_nls(cifs_sb->local_nls);
kfree(cifs_sb);
}
cFYI(1, ("In cifs_put_super"));
cifs_sb = CIFS_SB(sb);
- if(cifs_sb == NULL) {
+ if (cifs_sb == NULL) {
cFYI(1,("Empty cifs superblock info passed to unmount"));
return;
}
/* Only need to call the old QFSInfo if failed
on newer one */
- if(rc)
- rc = CIFSSMBQFSInfo(xid, pTcon, buf);
+ if (rc)
+ if (pTcon->ses->capabilities & CAP_NT_SMBS)
+ rc = CIFSSMBQFSInfo(xid, pTcon, buf); /* not supported by OS2 */
- /* Old Windows servers do not support level 103, retry with level
- one if old server failed the previous call */
- if(rc)
+ /* Some old Windows servers also do not support level 103, retry with
+ older level one if old server failed the previous call or we
+ bypassed it because we detected that this was an older LANMAN sess */
+ if (rc)
rc = SMBOldQFSInfo(xid, pTcon, buf);
/*
int f_type;
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;
+static struct kmem_cache *cifs_inode_cachep;
+static struct kmem_cache *cifs_req_cachep;
+static struct kmem_cache *cifs_mid_cachep;
+struct kmem_cache *cifs_oplock_cachep;
+static struct kmem_cache *cifs_sm_req_cachep;
mempool_t *cifs_sm_req_poolp;
mempool_t *cifs_req_poolp;
mempool_t *cifs_mid_poolp;
cifs_alloc_inode(struct super_block *sb)
{
struct cifsInodeInfo *cifs_inode;
- cifs_inode = kmem_cache_alloc(cifs_inode_cachep, SLAB_KERNEL);
+ cifs_inode = kmem_cache_alloc(cifs_inode_cachep, GFP_KERNEL);
if (!cifs_inode)
return NULL;
cifs_inode->cifsAttrs = 0x20; /* default */
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 */
- cifs_inode->vfs_inode.i_flags = S_NOATIME | S_NOCMTIME;
+
+ /* 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;*/
INIT_LIST_HEAD(&cifs_inode->openFileList);
return &cifs_inode->vfs_inode;
}
if (cifs_sb) {
if (cifs_sb->tcon) {
+/* BB add prepath to mount options displayed */
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)
+ if (cifs_sb->tcon->ses->domainName)
seq_printf(s, ",domain=%s",
cifs_sb->tcon->ses->domainName);
}
}
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
+ seq_printf(s, ",posixpaths");
+ if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) ||
+ !(cifs_sb->tcon->ses->capabilities & CAP_UNIX))
+ seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
+ if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) ||
+ !(cifs_sb->tcon->ses->capabilities & CAP_UNIX))
+ seq_printf(s, ",gid=%d", cifs_sb->mnt_gid);
seq_printf(s, ",rsize=%d",cifs_sb->rsize);
seq_printf(s, ",wsize=%d",cifs_sb->wsize);
}
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
struct cifsTconInfo *pTcon;
- if(cifs_sb)
+ if (cifs_sb)
pTcon = cifs_sb->tcon;
else
return -EIO;
xid = GetXid();
- if(pTcon) {
+ if (pTcon) {
cFYI(1,("set type: 0x%x id: %d",quota_type,qid));
} else {
return -EIO;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
struct cifsTconInfo *pTcon;
- if(cifs_sb)
+ if (cifs_sb)
pTcon = cifs_sb->tcon;
else
return -EIO;
xid = GetXid();
- if(pTcon) {
+ if (pTcon) {
cFYI(1,("set type: 0x%x id: %d",quota_type,qid));
} else {
rc = -EIO;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
struct cifsTconInfo *pTcon;
- if(cifs_sb)
+ if (cifs_sb)
pTcon = cifs_sb->tcon;
else
return -EIO;
xid = GetXid();
- if(pTcon) {
+ if (pTcon) {
cFYI(1,("flags: 0x%x operation: 0x%x",flags,operation));
} else {
rc = -EIO;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
struct cifsTconInfo *pTcon;
- if(cifs_sb) {
+ if (cifs_sb) {
pTcon = cifs_sb->tcon;
} else {
return -EIO;
}
xid = GetXid();
- if(pTcon) {
+ if (pTcon) {
cFYI(1,("pqstats %p",qstats));
} else {
rc = -EIO;
if (!(flags & MNT_FORCE))
return;
cifs_sb = CIFS_SB(vfsmnt->mnt_sb);
- if(cifs_sb == NULL)
+ if (cifs_sb == NULL)
return;
tcon = cifs_sb->tcon;
- if(tcon == NULL)
+ if (tcon == NULL)
return;
down(&tcon->tconSem);
if (atomic_read(&tcon->useCount) == 1)
/* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */
/* cancel_notify_requests(tcon); */
- if(tcon->ses && tcon->ses->server)
+ if (tcon->ses && tcon->ses->server)
{
cFYI(1,("wake up tasks now - umount begin not complete"));
wake_up_all(&tcon->ses->server->request_q);
return 0;
}
-static struct super_operations cifs_super_ops = {
+static const struct super_operations cifs_super_ops = {
.read_inode = cifs_read_inode,
.put_super = cifs_put_super,
.statfs = cifs_statfs,
.umount_begin = cifs_umount_begin,
.remount_fs = cifs_remount,
#ifdef CONFIG_CIFS_STATS2
- cifs_show_stats,
+ .show_stats = cifs_show_stats,
#endif
};
return simple_set_mnt(mnt, sb);
}
-static ssize_t cifs_file_writev(struct file *file, const struct iovec *iov,
- unsigned long nr_segs, loff_t *ppos)
+static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode;
ssize_t written;
- written = generic_file_writev(file, iov, nr_segs, ppos);
- if (!CIFS_I(inode)->clientCanCacheAll)
- filemap_fdatawrite(inode->i_mapping);
- return written;
-}
-
-static ssize_t cifs_file_aio_write(struct kiocb *iocb, const char __user *buf,
- size_t count, loff_t pos)
-{
- struct inode *inode = iocb->ki_filp->f_dentry->d_inode;
- ssize_t written;
-
- written = generic_file_aio_write(iocb, buf, count, pos);
+ written = generic_file_aio_write(iocb, iov, nr_segs, pos);
if (!CIFS_I(inode)->clientCanCacheAll)
filemap_fdatawrite(inode->i_mapping);
return written;
{
/* origin == SEEK_END => we must revalidate the cached file length */
if (origin == SEEK_END) {
- int retval = cifs_revalidate(file->f_dentry);
+ int retval;
+
+ /* 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(file->f_path.dentry->d_inode)->time = 0;
+
+ retval = cifs_revalidate(file->f_path.dentry);
if (retval < 0)
return (loff_t)retval;
}
.kill_sb = kill_anon_super,
/* .fs_flags */
};
-struct inode_operations cifs_dir_inode_ops = {
+const struct inode_operations cifs_dir_inode_ops = {
.create = cifs_create,
.lookup = cifs_lookup,
.getattr = cifs_getattr,
#endif
};
-struct inode_operations cifs_file_inode_ops = {
+const struct inode_operations cifs_file_inode_ops = {
/* revalidate:cifs_revalidate, */
.setattr = cifs_setattr,
.getattr = cifs_getattr, /* do we need this anymore? */
#endif
};
-struct inode_operations cifs_symlink_inode_ops = {
+const struct inode_operations cifs_symlink_inode_ops = {
.readlink = generic_readlink,
.follow_link = cifs_follow_link,
.put_link = cifs_put_link,
const struct file_operations cifs_file_ops = {
.read = do_sync_read,
.write = do_sync_write,
- .readv = generic_file_readv,
- .writev = cifs_file_writev,
.aio_read = generic_file_aio_read,
.aio_write = cifs_file_aio_write,
.open = cifs_open,
const struct file_operations cifs_file_nobrl_ops = {
.read = do_sync_read,
.write = do_sync_write,
- .readv = generic_file_readv,
- .writev = cifs_file_writev,
.aio_read = generic_file_aio_read,
.aio_write = cifs_file_aio_write,
.open = cifs_open,
};
static void
-cifs_init_once(void *inode, kmem_cache_t * cachep, unsigned long flags)
+cifs_init_once(void *inode, struct kmem_cache * cachep, unsigned long flags)
{
struct cifsInodeInfo *cifsi = inode;
- if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
- SLAB_CTOR_CONSTRUCTOR) {
+ if (flags & SLAB_CTOR_CONSTRUCTOR) {
inode_init_once(&cifsi->vfs_inode);
INIT_LIST_HEAD(&cifsi->lockList);
}
static void
cifs_destroy_inodecache(void)
{
- if (kmem_cache_destroy(cifs_inode_cachep))
- printk(KERN_WARNING "cifs_inode_cache: error freeing\n");
+ kmem_cache_destroy(cifs_inode_cachep);
}
static int
cifs_init_request_bufs(void)
{
- if(CIFSMaxBufSize < 8192) {
+ 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;
if (cifs_req_cachep == NULL)
return -ENOMEM;
- if(cifs_min_rcv < 1)
+ if (cifs_min_rcv < 1)
cifs_min_rcv = 1;
else if (cifs_min_rcv > 64) {
cifs_min_rcv = 64;
cifs_req_poolp = mempool_create_slab_pool(cifs_min_rcv,
cifs_req_cachep);
- if(cifs_req_poolp == NULL) {
+ if (cifs_req_poolp == NULL) {
kmem_cache_destroy(cifs_req_cachep);
return -ENOMEM;
}
return -ENOMEM;
}
- if(cifs_min_small < 2)
+ if (cifs_min_small < 2)
cifs_min_small = 2;
else if (cifs_min_small > 256) {
cifs_min_small = 256;
cifs_sm_req_poolp = mempool_create_slab_pool(cifs_min_small,
cifs_sm_req_cachep);
- if(cifs_sm_req_poolp == NULL) {
+ if (cifs_sm_req_poolp == NULL) {
mempool_destroy(cifs_req_poolp);
kmem_cache_destroy(cifs_req_cachep);
kmem_cache_destroy(cifs_sm_req_cachep);
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");
+ kmem_cache_destroy(cifs_req_cachep);
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");
+ kmem_cache_destroy(cifs_sm_req_cachep);
}
static int
/* 3 is a reasonable minimum number of simultaneous operations */
cifs_mid_poolp = mempool_create_slab_pool(3, cifs_mid_cachep);
- if(cifs_mid_poolp == NULL) {
+ if (cifs_mid_poolp == NULL) {
kmem_cache_destroy(cifs_mid_cachep);
return -ENOMEM;
}
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");
+ kmem_cache_destroy(cifs_mid_cachep);
+ kmem_cache_destroy(cifs_oplock_cachep);
}
static int cifs_oplock_thread(void * dummyarg)
continue;
spin_lock(&GlobalMid_Lock);
- if(list_empty(&GlobalOplock_Q)) {
+ 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) {
+ if (oplock_item) {
cFYI(1,("found oplock item to write out"));
pTcon = oplock_item->tcon;
inode = oplock_item->pinode;
/* mutex_lock(&inode->i_mutex);*/
if (S_ISREG(inode->i_mode)) {
rc = filemap_fdatawrite(inode->i_mapping);
- if(CIFS_I(inode)->clientCanCacheRead == 0) {
+ if (CIFS_I(inode)->clientCanCacheRead == 0) {
filemap_fdatawait(inode->i_mapping);
invalidate_remote_inode(inode);
}
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) {
+ if (pTcon->tidStatus != CifsNeedReconnect) {
rc = CIFSSMBLock(0, pTcon, netfid,
0 /* len */ , 0 /* offset */, 0,
0, LOCKING_ANDX_OPLOCK_RELEASE,
list_for_each(tmp, &GlobalSMBSessionList) {
ses = list_entry(tmp, struct cifsSesInfo,
cifsSessionList);
- if(ses && ses->server &&
+ if (ses && ses->server &&
atomic_read(&ses->server->inFlight))
wake_up_all(&ses->server->response_q);
}
rwlock_init(&GlobalSMBSeslock);
spin_lock_init(&GlobalMid_Lock);
- if(cifs_max_pending < 2) {
+ 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) {
+ } else if (cifs_max_pending > 256) {
cifs_max_pending = 256;
cFYI(1,("cifs_max_pending set to max of 256"));
}