aboutsummaryrefslogtreecommitdiff
path: root/fs/cifs
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2007-01-18 10:34:51 +1100
committerDavid Woodhouse <dwmw2@infradead.org>2007-01-18 10:34:51 +1100
commit9cdf083f981b8d37b3212400a359368661385099 (patch)
treeaa15a6a08ad87e650dea40fb59b3180bef0d345b /fs/cifs
parente499e01d234a31d59679b7b1e1cf628d917ba49a (diff)
parenta8b3485287731978899ced11f24628c927890e78 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/CHANGES3
-rw-r--r--fs/cifs/cifsencrypt.c4
-rw-r--r--fs/cifs/cifsfs.c21
-rw-r--r--fs/cifs/cifspdu.h8
-rw-r--r--fs/cifs/cifssmb.c2
-rw-r--r--fs/cifs/connect.c1
-rw-r--r--fs/cifs/fcntl.c4
-rw-r--r--fs/cifs/file.c142
-rw-r--r--fs/cifs/inode.c6
-rw-r--r--fs/cifs/link.c33
-rw-r--r--fs/cifs/misc.c4
-rw-r--r--fs/cifs/readdir.c32
-rw-r--r--fs/cifs/transport.c6
13 files changed, 159 insertions, 107 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 0b3c37ef52e..3539d6ef961 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -5,7 +5,8 @@ Allow null user to be specified on mount ("username="). Do not return
EINVAL on readdir when filldir fails due to overwritten blocksize
(fixes FC problem). Return error in rename 2nd attempt retry (ie report
if rename by handle also fails, after rename by path fails, we were
-not reporting whether the retry worked or not).
+not reporting whether the retry worked or not). Fix NTLMv2 to
+work to Windows servers (mount with option "sec=ntlmv2").
Version 1.45
------------
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 4bc250b2d9f..fdeda519eac 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -372,8 +372,10 @@ void setup_ntlmv2_rsp(struct cifsSesInfo * ses, char * resp_buf,
buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
get_random_bytes(&buf->client_chal, sizeof(buf->client_chal));
buf->reserved2 = 0;
- buf->names[0].type = 0;
+ buf->names[0].type = cpu_to_le16(NTLMSSP_DOMAIN_TYPE);
buf->names[0].length = 0;
+ buf->names[1].type = 0;
+ buf->names[1].length = 0;
/* calculate buf->ntlmv2_hash */
rc = calc_ntlmv2_hash(ses, nls_cp);
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 84976cdbe71..10c90294cd1 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -34,6 +34,7 @@
#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
@@ -81,7 +82,7 @@ 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;
+extern struct kmem_cache *cifs_oplock_cachep;
static int
cifs_read_super(struct super_block *sb, void *data,
@@ -232,11 +233,11 @@ static int cifs_permission(struct inode * inode, int mask, struct nameidata *nd)
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;
@@ -245,7 +246,7 @@ static struct inode *
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 */
@@ -497,7 +498,7 @@ cifs_get_sb(struct file_system_type *fs_type,
static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t pos)
{
- struct inode *inode = iocb->ki_filp->f_dentry->d_inode;
+ struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode;
ssize_t written;
written = generic_file_aio_write(iocb, iov, nr_segs, pos);
@@ -510,7 +511,7 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int origin)
{
/* origin == SEEK_END => we must revalidate the cached file length */
if (origin == SEEK_END) {
- int retval = cifs_revalidate(file->f_dentry);
+ int retval = cifs_revalidate(file->f_path.dentry);
if (retval < 0)
return (loff_t)retval;
}
@@ -668,7 +669,7 @@ const struct file_operations cifs_dir_ops = {
};
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;
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index 6df9dadba64..068ef51edbf 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -580,6 +580,12 @@ typedef union smb_com_session_setup_andx {
/* format of NLTMv2 Response ie "case sensitive password" hash when NTLMv2 */
+#define NTLMSSP_SERVER_TYPE 1
+#define NTLMSSP_DOMAIN_TYPE 2
+#define NTLMSSP_FQ_DOMAIN_TYPE 3
+#define NTLMSSP_DNS_DOMAIN_TYPE 4
+#define NTLMSSP_DNS_PARENT_TYPE 5
+
struct ntlmssp2_name {
__le16 type;
__le16 length;
@@ -593,7 +599,7 @@ struct ntlmv2_resp {
__le64 time;
__u64 client_chal; /* random */
__u32 reserved2;
- struct ntlmssp2_name names[1];
+ struct ntlmssp2_name names[2];
/* array of name entries could follow ending in minimum 4 byte struct */
} __attribute__((packed));
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 098790eb2aa..472e33e0f3c 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -4876,7 +4876,7 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
} else {
/* Add file to outstanding requests */
/* BB change to kmem cache alloc */
- dnotify_req = (struct dir_notify_req *) kmalloc(
+ dnotify_req = kmalloc(
sizeof(struct dir_notify_req),
GFP_KERNEL);
if(dnotify_req) {
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 71f77914ce9..2caca06b4ba 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -31,6 +31,7 @@
#include <linux/delay.h>
#include <linux/completion.h>
#include <linux/pagevec.h>
+#include <linux/freezer.h>
#include <asm/uaccess.h>
#include <asm/processor.h>
#include "cifspdu.h"
diff --git a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c
index d91a3d44e9e..da12b482ebe 100644
--- a/fs/cifs/fcntl.c
+++ b/fs/cifs/fcntl.c
@@ -83,10 +83,10 @@ int cifs_dir_notify(struct file * file, unsigned long arg)
return 0;
xid = GetXid();
- cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+ cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
pTcon = cifs_sb->tcon;
- full_path = build_path_from_dentry(file->f_dentry);
+ full_path = build_path_from_dentry(file->f_path.dentry);
if(full_path == NULL) {
rc = -ENOMEM;
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 2436ed8fc84..8a49b2e77d3 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -29,6 +29,7 @@
#include <linux/pagevec.h>
#include <linux/smp_lock.h>
#include <linux/writeback.h>
+#include <linux/task_io_accounting_ops.h>
#include <linux/delay.h>
#include <asm/div64.h>
#include "cifsfs.h"
@@ -122,34 +123,34 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
/* 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 ==
+ if (timespec_equal(&file->f_path.dentry->d_inode->i_mtime, &temp) &&
+ (file->f_path.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) {
+ if (file->f_path.dentry->d_inode->i_mapping) {
/* BB no need to lock inode until after invalidate
since namei code should already have it locked? */
- filemap_write_and_wait(file->f_dentry->d_inode->i_mapping);
+ filemap_write_and_wait(file->f_path.dentry->d_inode->i_mapping);
}
cFYI(1, ("invalidating remote inode since open detected it "
"changed"));
- invalidate_remote_inode(file->f_dentry->d_inode);
+ invalidate_remote_inode(file->f_path.dentry->d_inode);
}
client_can_cache:
if (pTcon->ses->capabilities & CAP_UNIX)
- rc = cifs_get_inode_info_unix(&file->f_dentry->d_inode,
+ rc = cifs_get_inode_info_unix(&file->f_path.dentry->d_inode,
full_path, inode->i_sb, xid);
else
- rc = cifs_get_inode_info(&file->f_dentry->d_inode,
+ rc = cifs_get_inode_info(&file->f_path.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));
+ file->f_path.dentry->d_inode));
} else if ((*oplock & 0xF) == OPLOCK_READ)
pCifsInode->clientCanCacheRead = TRUE;
@@ -178,7 +179,7 @@ int cifs_open(struct inode *inode, struct file *file)
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);
+ pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
read_lock(&GlobalSMBSeslock);
list_for_each(tmp, &pCifsInode->openFileList) {
pCifsFile = list_entry(tmp, struct cifsFileInfo,
@@ -206,7 +207,7 @@ int cifs_open(struct inode *inode, struct file *file)
}
}
- full_path = build_path_from_dentry(file->f_dentry);
+ full_path = build_path_from_dentry(file->f_path.dentry);
if (full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
@@ -291,7 +292,7 @@ int cifs_open(struct inode *inode, struct file *file)
write_lock(&GlobalSMBSeslock);
list_add(&pCifsFile->tlist, &pTcon->openFileList);
- pCifsInode = CIFS_I(file->f_dentry->d_inode);
+ pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
if (pCifsInode) {
rc = cifs_open_inode_helper(inode, file, pCifsInode,
pCifsFile, pTcon,
@@ -366,7 +367,7 @@ static int cifs_reopen_file(struct inode *inode, struct file *file,
return 0;
}
- if (file->f_dentry == NULL) {
+ if (file->f_path.dentry == NULL) {
up(&pCifsFile->fh_sem);
cFYI(1, ("failed file reopen, no valid name if dentry freed"));
FreeXid(xid);
@@ -378,7 +379,7 @@ static int cifs_reopen_file(struct inode *inode, struct file *file,
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);
+ full_path = build_path_from_dentry(file->f_path.dentry);
if (full_path == NULL) {
up(&pCifsFile->fh_sem);
FreeXid(xid);
@@ -444,7 +445,7 @@ static int cifs_reopen_file(struct inode *inode, struct file *file,
pCifsInode->clientCanCacheAll = TRUE;
pCifsInode->clientCanCacheRead = TRUE;
cFYI(1, ("Exclusive Oplock granted on inode %p",
- file->f_dentry->d_inode));
+ file->f_path.dentry->d_inode));
} else if ((oplock & 0xF) == OPLOCK_READ) {
pCifsInode->clientCanCacheRead = TRUE;
pCifsInode->clientCanCacheAll = FALSE;
@@ -551,7 +552,7 @@ int cifs_closedir(struct inode *inode, struct file *file)
if (pCFileStruct) {
struct cifsTconInfo *pTcon;
- struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+ struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
pTcon = cifs_sb->tcon;
@@ -664,7 +665,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
} else
cFYI(1, ("Unknown type of lock"));
- cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+ cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
pTcon = cifs_sb->tcon;
if (file->private_data == NULL) {
@@ -791,10 +792,10 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
int xid, long_op;
struct cifsFileInfo *open_file;
- if (file->f_dentry == NULL)
+ if (file->f_path.dentry == NULL)
return -EBADF;
- cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+ cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
if (cifs_sb == NULL)
return -EBADF;
@@ -802,7 +803,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
/* cFYI(1,
(" write %d bytes to offset %lld of %s", write_size,
- *poffset, file->f_dentry->d_name.name)); */
+ *poffset, file->f_path.dentry->d_name.name)); */
if (file->private_data == NULL)
return -EBADF;
@@ -810,12 +811,12 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
open_file = (struct cifsFileInfo *) file->private_data;
xid = GetXid();
- if (file->f_dentry->d_inode == NULL) {
+ if (file->f_path.dentry->d_inode == NULL) {
FreeXid(xid);
return -EBADF;
}
- if (*poffset > file->f_dentry->d_inode->i_size)
+ if (*poffset > file->f_path.dentry->d_inode->i_size)
long_op = 2; /* writes past end of file can take a long time */
else
long_op = 1;
@@ -840,8 +841,8 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
return -EBADF;
}
if (open_file->invalidHandle) {
- if ((file->f_dentry == NULL) ||
- (file->f_dentry->d_inode == NULL)) {
+ if ((file->f_path.dentry == NULL) ||
+ (file->f_path.dentry->d_inode == NULL)) {
FreeXid(xid);
return total_written;
}
@@ -849,7 +850,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
filemap_fdatawait from here so tell
reopen_file not to flush data to server
now */
- rc = cifs_reopen_file(file->f_dentry->d_inode,
+ rc = cifs_reopen_file(file->f_path.dentry->d_inode,
file, FALSE);
if (rc != 0)
break;
@@ -878,17 +879,17 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
cifs_stats_bytes_written(pTcon, total_written);
/* 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;
+ if (file->f_path.dentry) {
+ if (file->f_path.dentry->d_inode) {
+ struct inode *inode = file->f_path.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,
+ if (*poffset > file->f_path.dentry->d_inode->i_size)
+ i_size_write(file->f_path.dentry->d_inode,
*poffset);
}
- mark_inode_dirty_sync(file->f_dentry->d_inode);
+ mark_inode_dirty_sync(file->f_path.dentry->d_inode);
}
}
FreeXid(xid);
@@ -906,17 +907,17 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
int xid, long_op;
struct cifsFileInfo *open_file;
- if (file->f_dentry == NULL)
+ if (file->f_path.dentry == NULL)
return -EBADF;
- cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+ cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
if (cifs_sb == NULL)
return -EBADF;
pTcon = cifs_sb->tcon;
cFYI(1,("write %zd bytes to offset %lld of %s", write_size,
- *poffset, file->f_dentry->d_name.name));
+ *poffset, file->f_path.dentry->d_name.name));
if (file->private_data == NULL)
return -EBADF;
@@ -924,12 +925,12 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
open_file = (struct cifsFileInfo *)file->private_data;
xid = GetXid();
- if (file->f_dentry->d_inode == NULL) {
+ if (file->f_path.dentry->d_inode == NULL) {
FreeXid(xid);
return -EBADF;
}
- if (*poffset > file->f_dentry->d_inode->i_size)
+ if (*poffset > file->f_path.dentry->d_inode->i_size)
long_op = 2; /* writes past end of file can take a long time */
else
long_op = 1;
@@ -955,8 +956,8 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
return -EBADF;
}
if (open_file->invalidHandle) {
- if ((file->f_dentry == NULL) ||
- (file->f_dentry->d_inode == NULL)) {
+ if ((file->f_path.dentry == NULL) ||
+ (file->f_path.dentry->d_inode == NULL)) {
FreeXid(xid);
return total_written;
}
@@ -964,7 +965,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
filemap_fdatawait from here so tell
reopen_file not to flush data to
server now */
- rc = cifs_reopen_file(file->f_dentry->d_inode,
+ rc = cifs_reopen_file(file->f_path.dentry->d_inode,
file, FALSE);
if (rc != 0)
break;
@@ -1011,16 +1012,16 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
cifs_stats_bytes_written(pTcon, total_written);
/* 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 (file->f_path.dentry) {
+ if (file->f_path.dentry->d_inode) {
+ file->f_path.dentry->d_inode->i_ctime =
+ file->f_path.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,
+ if (*poffset > file->f_path.dentry->d_inode->i_size)
+ i_size_write(file->f_path.dentry->d_inode,
*poffset);
}
- mark_inode_dirty_sync(file->f_dentry->d_inode);
+ mark_inode_dirty_sync(file->f_path.dentry->d_inode);
}
}
FreeXid(xid);
@@ -1244,14 +1245,21 @@ retry:
wait_on_page_writeback(page);
if (PageWriteback(page) ||
- !test_clear_page_dirty(page)) {
+ !clear_page_dirty_for_io(page)) {
unlock_page(page);
break;
}
+ /*
+ * This actually clears the dirty bit in the radix tree.
+ * See cifs_writepage() for more commentary.
+ */
+ set_page_writeback(page);
+
if (page_offset(page) >= mapping->host->i_size) {
done = 1;
unlock_page(page);
+ end_page_writeback(page);
break;
}
@@ -1315,6 +1323,7 @@ retry:
SetPageError(page);
kunmap(page);
unlock_page(page);
+ end_page_writeback(page);
page_cache_release(page);
}
if ((wbc->nr_to_write -= n_iov) <= 0)
@@ -1351,11 +1360,23 @@ static int cifs_writepage(struct page* page, struct writeback_control *wbc)
if (!PageUptodate(page)) {
cFYI(1, ("ppw - page not up to date"));
}
-
+
+ /*
+ * Set the "writeback" flag, and clear "dirty" in the radix tree.
+ *
+ * A writepage() implementation always needs to do either this,
+ * or re-dirty the page with "redirty_page_for_writepage()" in
+ * the case of a failure.
+ *
+ * Just unlocking the page will cause the radix tree tag-bits
+ * to fail to update with the state of the page correctly.
+ */
+ set_page_writeback(page);
rc = cifs_partialpagewrite(page, 0, PAGE_CACHE_SIZE);
SetPageUptodate(page); /* BB add check for error and Clearuptodate? */
unlock_page(page);
- page_cache_release(page);
+ end_page_writeback(page);
+ page_cache_release(page);
FreeXid(xid);
return rc;
}
@@ -1384,7 +1405,7 @@ static int cifs_commit_write(struct file *file, struct page *page,
if ((open_file->invalidHandle) &&
(!open_file->closePend)) {
rc = cifs_reopen_file(
- file->f_dentry->d_inode, file);
+ file->f_path.dentry->d_inode, file);
if (rc != 0)
break;
}
@@ -1434,7 +1455,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
{
int xid;
int rc = 0;
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
xid = GetXid();
@@ -1482,7 +1503,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
*/
int cifs_flush(struct file *file, fl_owner_t id)
{
- struct inode * inode = file->f_dentry->d_inode;
+ struct inode * inode = file->f_path.dentry->d_inode;
int rc = 0;
/* Rather than do the steps manually:
@@ -1519,7 +1540,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
struct smb_com_read_rsp *pSMBr;
xid = GetXid();
- cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+ cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
pTcon = cifs_sb->tcon;
if (file->private_data == NULL) {
@@ -1542,7 +1563,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
int buf_type = CIFS_NO_BUFFER;
if ((open_file->invalidHandle) &&
(!open_file->closePend)) {
- rc = cifs_reopen_file(file->f_dentry->d_inode,
+ rc = cifs_reopen_file(file->f_path.dentry->d_inode,
file, TRUE);
if (rc != 0)
break;
@@ -1601,7 +1622,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
int buf_type = CIFS_NO_BUFFER;
xid = GetXid();
- cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+ cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
pTcon = cifs_sb->tcon;
if (file->private_data == NULL) {
@@ -1629,7 +1650,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
while (rc == -EAGAIN) {
if ((open_file->invalidHandle) &&
(!open_file->closePend)) {
- rc = cifs_reopen_file(file->f_dentry->d_inode,
+ rc = cifs_reopen_file(file->f_path.dentry->d_inode,
file, TRUE);
if (rc != 0)
break;
@@ -1658,7 +1679,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
{
- struct dentry *dentry = file->f_dentry;
+ struct dentry *dentry = file->f_path.dentry;
int rc, xid;
xid = GetXid();
@@ -1744,7 +1765,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
return -EBADF;
}
open_file = (struct cifsFileInfo *)file->private_data;
- cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+ cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
pTcon = cifs_sb->tcon;
pagevec_init(&lru_pvec, 0);
@@ -1786,7 +1807,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
while (rc == -EAGAIN) {
if ((open_file->invalidHandle) &&
(!open_file->closePend)) {
- rc = cifs_reopen_file(file->f_dentry->d_inode,
+ rc = cifs_reopen_file(file->f_path.dentry->d_inode,
file, TRUE);
if (rc != 0)
break;
@@ -1812,6 +1833,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
cFYI(1, ("Read error in readpages: %d", rc));
break;
} else if (bytes_read > 0) {
+ task_io_account_read(bytes_read);
pSMBr = (struct smb_com_read_rsp *)smb_read_data;
cifs_copy_cache_pages(mapping, page_list, bytes_read,
smb_read_data + 4 /* RFC1001 hdr */ +
@@ -1880,8 +1902,8 @@ static int cifs_readpage_worker(struct file *file, struct page *page,
else
cFYI(1, ("Bytes read %d",rc));
- file->f_dentry->d_inode->i_atime =
- current_fs_time(file->f_dentry->d_inode->i_sb);
+ file->f_path.dentry->d_inode->i_atime =
+ current_fs_time(file->f_path.dentry->d_inode->i_sb);
if (PAGE_CACHE_SIZE > rc)
memset(read_data + rc, 0, PAGE_CACHE_SIZE - rc);
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 1ad8c9fcc74..c4fa91b8b62 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -318,6 +318,7 @@ int cifs_get_inode_info(struct inode **pinode,
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
char *tmp_path;
char *buf = NULL;
+ int adjustTZ = FALSE;
pTcon = cifs_sb->tcon;
cFYI(1,("Getting info on %s", search_path));
@@ -348,6 +349,7 @@ int cifs_get_inode_info(struct inode **pinode,
pfindData, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
+ adjustTZ = TRUE;
}
}
@@ -444,6 +446,10 @@ int cifs_get_inode_info(struct inode **pinode,
inode->i_ctime =
cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
cFYI(0, ("Attributes came in as 0x%x", attr));
+ if(adjustTZ && (pTcon->ses) && (pTcon->ses->server)) {
+ inode->i_ctime.tv_sec += pTcon->ses->server->timeAdj;
+ inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj;
+ }
/* set default mode. will override for dirs below */
if (atomic_read(&cifsInfo->inUse) == 0)
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 0bee8b7e521..8e259969354 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -69,17 +69,30 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
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 of target */
+
+ /* if source file is cached (oplocked) revalidate will not go to server
+ until the file is closed or oplock broken so update nlinks locally */
+ if(old_file->d_inode) {
+ cifsInode = CIFS_I(old_file->d_inode);
+ if(rc == 0) {
+ old_file->d_inode->i_nlink++;
+ old_file->d_inode->i_ctime = CURRENT_TIME;
+ /* parent dir timestamps will update from srv
+ within a second, would it really be worth it
+ to set the parent dir cifs inode time to zero
+ to force revalidate (faster) for it too? */
+ }
+ /* if not oplocked will force revalidate to get info
+ on source file from srv */
+ cifsInode->time = 0;
+
+ /* Will update parent dir timestamps from srv within a second.
+ Would it really be worth it to set the parent dir (cifs
+ inode) time field to zero to force revalidate on parent
+ directory faster ie
+ CIFS_I(inode)->time = 0; */
}
- 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:
kfree(fromName);
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index bbc9cd34b6e..aedf683f011 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -153,7 +153,7 @@ cifs_buf_get(void)
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);
+ (struct smb_hdr *) mempool_alloc(cifs_req_poolp, GFP_KERNEL | GFP_NOFS);
/* clear the first few header bytes */
/* for most paths, more is cleared in header_assemble */
@@ -192,7 +192,7 @@ cifs_small_buf_get(void)
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);
+ (struct smb_hdr *) mempool_alloc(cifs_sm_req_poolp, GFP_KERNEL | GFP_NOFS);
if (ret_buf) {
/* No need to clear memory here, cleared in header assemble */
/* memset(ret_buf, 0, sizeof(struct smb_hdr) + 27);*/
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index ed18c3965f7..99dfb5337e3 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -68,30 +68,30 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
int rc = 0;
cFYI(1, ("For %s", qstring->name));
- cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+ cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
pTcon = cifs_sb->tcon;
qstring->hash = full_name_hash(qstring->name, qstring->len);
- tmp_dentry = d_lookup(file->f_dentry, qstring);
+ tmp_dentry = d_lookup(file->f_path.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);
+ *ptmp_inode = new_inode(file->f_path.dentry->d_sb);
if(*ptmp_inode == NULL)
return rc;
rc = 1;
}
} else {
- tmp_dentry = d_alloc(file->f_dentry, qstring);
+ tmp_dentry = d_alloc(file->f_path.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);
+ *ptmp_inode = new_inode(file->f_path.dentry->d_sb);
if (pTcon->nocase)
tmp_dentry->d_op = &cifs_ci_dentry_ops;
else
@@ -432,10 +432,10 @@ static int initiate_cifs_search(const int xid, struct file *file)
cifsFile->invalidHandle = TRUE;
cifsFile->srch_inf.endOfSearch = FALSE;
- if(file->f_dentry == NULL)
+ if(file->f_path.dentry == NULL)
return -ENOENT;
- cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+ cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
if(cifs_sb == NULL)
return -EINVAL;
@@ -443,7 +443,7 @@ static int initiate_cifs_search(const int xid, struct file *file)
if(pTcon == NULL)
return -EINVAL;
- full_path = build_path_from_dentry(file->f_dentry);
+ full_path = build_path_from_dentry(file->f_path.dentry);
if(full_path == NULL) {
return -ENOMEM;
@@ -609,10 +609,10 @@ static int is_dir_changed(struct file * file)
struct inode * inode;
struct cifsInodeInfo *cifsInfo;
- if(file->f_dentry == NULL)
+ if(file->f_path.dentry == NULL)
return 0;
- inode = file->f_dentry->d_inode;
+ inode = file->f_path.dentry->d_inode;
if(inode == NULL)
return 0;
@@ -839,7 +839,7 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
if((scratch_buf == NULL) || (pfindEntry == NULL) || (pCifsF == NULL))
return -ENOENT;
- if(file->f_dentry == NULL)
+ if(file->f_path.dentry == NULL)
return -ENOENT;
rc = cifs_entry_is_dot(pfindEntry,pCifsF);
@@ -847,7 +847,7 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
if(rc != 0)
return 0;
- cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+ cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
qstring.name = scratch_buf;
rc = cifs_get_name_from_search_buf(&qstring,pfindEntry,
@@ -985,12 +985,12 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
xid = GetXid();
- if(file->f_dentry == NULL) {
+ if(file->f_path.dentry == NULL) {
FreeXid(xid);
return -EIO;
}
- cifs_sb = CIFS_SB(file->f_dentry->d_sb);
+ cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
pTcon = cifs_sb->tcon;
if(pTcon == NULL)
return -EINVAL;
@@ -998,7 +998,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
switch ((int) file->f_pos) {
case 0:
if (filldir(direntry, ".", 1, file->f_pos,
- file->f_dentry->d_inode->i_ino, DT_DIR) < 0) {
+ file->f_path.dentry->d_inode->i_ino, DT_DIR) < 0) {
cERROR(1, ("Filldir for current dir failed"));
rc = -ENOMEM;
break;
@@ -1006,7 +1006,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
file->f_pos++;
case 1:
if (filldir(direntry, "..", 2, file->f_pos,
- file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
+ file->f_path.dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
cERROR(1, ("Filldir for parent dir failed"));
rc = -ENOMEM;
break;
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 48d47b46b1f..f80007eaebf 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -34,7 +34,7 @@
#include "cifs_debug.h"
extern mempool_t *cifs_mid_poolp;
-extern kmem_cache_t *cifs_oplock_cachep;
+extern struct kmem_cache *cifs_oplock_cachep;
static struct mid_q_entry *
AllocMidQEntry(const struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
@@ -51,7 +51,7 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
}
temp = (struct mid_q_entry *) mempool_alloc(cifs_mid_poolp,
- SLAB_KERNEL | SLAB_NOFS);
+ GFP_KERNEL | GFP_NOFS);
if (temp == NULL)
return temp;
else {
@@ -118,7 +118,7 @@ AllocOplockQEntry(struct inode * pinode, __u16 fid, struct cifsTconInfo * tcon)
return NULL;
}
temp = (struct oplock_q_entry *) kmem_cache_alloc(cifs_oplock_cachep,
- SLAB_KERNEL);
+ GFP_KERNEL);
if (temp == NULL)
return temp;
else {