aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-03-06 20:32:22 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-03-06 20:32:22 -0500
commit9f6632d6290785caf9e9f874c0a0cfaf2c178e59 (patch)
tree2757e79374b98211170782c1ff8d15b8532492b7 /fs
parent8328258e745b80290534c9ab5bede6cd8340ea75 (diff)
parent8a236264f7d6db3f52881d37a86c5a5f704072b0 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6: [CIFS] cifs_prepare_write was incorrectly rereading page in some cases [CIFS] Fix set file size to zero when doing chmod to Samba 3.0.26pre [CIFS] Remove some unused functions/declarations [CIFS] New file for previous commit [CIFS] cifs export operations [CIFS] small piece missing from previous patch [CIFS] Fix locking problem around some cifs uses of i_size write
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/CHANGES7
-rw-r--r--fs/cifs/Makefile2
-rw-r--r--fs/cifs/TODO16
-rw-r--r--fs/cifs/cifsfs.c16
-rw-r--r--fs/cifs/cifsfs.h4
-rw-r--r--fs/cifs/cifsglob.h8
-rw-r--r--fs/cifs/cifspdu.h3
-rw-r--r--fs/cifs/cifsproto.h2
-rw-r--r--fs/cifs/cifssmb.c10
-rw-r--r--fs/cifs/dir.c2
-rw-r--r--fs/cifs/export.c52
-rw-r--r--fs/cifs/file.c105
-rw-r--r--fs/cifs/inode.c58
-rw-r--r--fs/cifs/readdir.c6
-rw-r--r--fs/cifs/transport.c6
15 files changed, 227 insertions, 70 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 5fe13593b57f..6247628bdaed 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,3 +1,10 @@
1Verison 1.48
2------------
3Fix mtime bouncing around from local idea of last write times to remote time.
4Fix hang (in i_size_read) when simultaneous size update of same remote file
5on smp system corrupts sequence number. Do not reread unnecessarily partial page
6(which we are about to overwrite anyway) when writing out file opened rw.
7
1Version 1.47 8Version 1.47
2------------ 9------------
3Fix oops in list_del during mount caused by unaligned string. 10Fix oops in list_del during mount caused by unaligned string.
diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile
index a26f26ed5a17..6ecd9d6ba3f3 100644
--- a/fs/cifs/Makefile
+++ b/fs/cifs/Makefile
@@ -3,4 +3,4 @@
3# 3#
4obj-$(CONFIG_CIFS) += cifs.o 4obj-$(CONFIG_CIFS) += cifs.o
5 5
6cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o sess.o 6cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o sess.o export.o
diff --git a/fs/cifs/TODO b/fs/cifs/TODO
index 68372946dc92..d7b9c27c942d 100644
--- a/fs/cifs/TODO
+++ b/fs/cifs/TODO
@@ -18,7 +18,9 @@ better)
18 18
19d) Kerberos/SPNEGO session setup support - (started) 19d) Kerberos/SPNEGO session setup support - (started)
20 20
21e) NTLMv2 authentication (mostly implemented) 21e) NTLMv2 authentication (mostly implemented - double check
22that NTLMv2 signing works, also need to cleanup now unneeded SessSetup code in
23fs/cifs/connect.c)
22 24
23f) MD5-HMAC signing SMB PDUs when SPNEGO style SessionSetup 25f) MD5-HMAC signing SMB PDUs when SPNEGO style SessionSetup
24used (Kerberos or NTLMSSP). Signing alreadyimplemented for NTLM 26used (Kerberos or NTLMSSP). Signing alreadyimplemented for NTLM
@@ -88,11 +90,12 @@ w) Finish up the dos time conversion routines needed to return old server
88time to the client (default time, of now or time 0 is used now for these 90time to the client (default time, of now or time 0 is used now for these
89very old servers) 91very old servers)
90 92
91x) Add support for OS/2 (LANMAN 1.2 and LANMAN2.1 based SMB servers) 93x) In support for OS/2 (LANMAN 1.2 and LANMAN2.1 based SMB servers)
94need to add ability to set time to server (utimes command)
92 95
93y) Finish testing of Windows 9x/Windows ME server support (started). 96y) Finish testing of Windows 9x/Windows ME server support (started).
94 97
95KNOWN BUGS (updated April 29, 2005) 98KNOWN BUGS (updated February 26, 2007)
96==================================== 99====================================
97See http://bugzilla.samba.org - search on product "CifsVFS" for 100See http://bugzilla.samba.org - search on product "CifsVFS" for
98current bug list. 101current bug list.
@@ -107,11 +110,6 @@ but recognizes them
107succeed but still return access denied (appears to be Windows 110succeed but still return access denied (appears to be Windows
108server not cifs client problem) and has not been reproduced recently. 111server not cifs client problem) and has not been reproduced recently.
109NTFS partitions do not have this problem. 112NTFS partitions do not have this problem.
1104) debug connectathon lock test case 10 which fails against
111Samba (may be unmappable due to POSIX to Windows lock model
112differences but worth investigating). Also debug Samba to
113see why lock test case 7 takes longer to complete to Samba
114than to Windows.
115 113
116Misc testing to do 114Misc testing to do
117================== 115==================
@@ -119,7 +117,7 @@ Misc testing to do
119types. Try nested symlinks (8 deep). Return max path name in stat -f information 117types. Try nested symlinks (8 deep). Return max path name in stat -f information
120 118
1212) Modify file portion of ltp so it can run against a mounted network 1192) Modify file portion of ltp so it can run against a mounted network
122share and run it against cifs vfs. 120share and run it against cifs vfs in automated fashion.
123 121
1243) Additional performance testing and optimization using iozone and similar - 1223) Additional performance testing and optimization using iozone and similar -
125there are some easy changes that can be done to parallelize sequential writes, 123there are some easy changes that can be done to parallelize sequential writes,
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index bc2c0ac27169..faba4d69fe91 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs/cifsfs.c 2 * fs/cifs/cifsfs.c
3 * 3 *
4 * Copyright (C) International Business Machines Corp., 2002,2004 4 * Copyright (C) International Business Machines Corp., 2002,2007
5 * Author(s): Steve French (sfrench@us.ibm.com) 5 * Author(s): Steve French (sfrench@us.ibm.com)
6 * 6 *
7 * Common Internet FileSystem (CIFS) client 7 * Common Internet FileSystem (CIFS) client
@@ -47,7 +47,11 @@
47 47
48#ifdef CONFIG_CIFS_QUOTA 48#ifdef CONFIG_CIFS_QUOTA
49static struct quotactl_ops cifs_quotactl_ops; 49static struct quotactl_ops cifs_quotactl_ops;
50#endif 50#endif /* QUOTA */
51
52#ifdef CONFIG_CIFS_EXPERIMENTAL
53extern struct export_operations cifs_export_ops;
54#endif /* EXPERIMENTAL */
51 55
52int cifsFYI = 0; 56int cifsFYI = 0;
53int cifsERROR = 1; 57int cifsERROR = 1;
@@ -62,8 +66,8 @@ unsigned int extended_security = CIFSSEC_DEF;
62unsigned int sign_CIFS_PDUs = 1; 66unsigned int sign_CIFS_PDUs = 1;
63extern struct task_struct * oplockThread; /* remove sparse warning */ 67extern struct task_struct * oplockThread; /* remove sparse warning */
64struct task_struct * oplockThread = NULL; 68struct task_struct * oplockThread = NULL;
65extern struct task_struct * dnotifyThread; /* remove sparse warning */ 69/* extern struct task_struct * dnotifyThread; remove sparse warning */
66struct task_struct * dnotifyThread = NULL; 70static struct task_struct * dnotifyThread = NULL;
67static const struct super_operations cifs_super_ops; 71static const struct super_operations cifs_super_ops;
68unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE; 72unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE;
69module_param(CIFSMaxBufSize, int, 0); 73module_param(CIFSMaxBufSize, int, 0);
@@ -110,6 +114,10 @@ cifs_read_super(struct super_block *sb, void *data,
110 114
111 sb->s_magic = CIFS_MAGIC_NUMBER; 115 sb->s_magic = CIFS_MAGIC_NUMBER;
112 sb->s_op = &cifs_super_ops; 116 sb->s_op = &cifs_super_ops;
117#ifdef CONFIG_CIFS_EXPERIMENTAL
118 if(experimEnabled != 0)
119 sb->s_export_op = &cifs_export_ops;
120#endif /* EXPERIMENTAL */
113/* if(cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512) 121/* if(cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512)
114 sb->s_blocksize = cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */ 122 sb->s_blocksize = cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */
115#ifdef CONFIG_CIFS_QUOTA 123#ifdef CONFIG_CIFS_QUOTA
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index c97c08eb481a..2c2c384894d8 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -38,8 +38,8 @@ extern const struct address_space_operations cifs_addr_ops_smallbuf;
38/* Functions related to super block operations */ 38/* Functions related to super block operations */
39/* extern const struct super_operations cifs_super_ops;*/ 39/* extern const struct super_operations cifs_super_ops;*/
40extern void cifs_read_inode(struct inode *); 40extern void cifs_read_inode(struct inode *);
41extern void cifs_delete_inode(struct inode *); 41/*extern void cifs_delete_inode(struct inode *);*/ /* BB not needed yet */
42/* extern void cifs_write_inode(struct inode *); *//* BB not needed yet */ 42/* extern void cifs_write_inode(struct inode *); */ /* BB not needed yet */
43 43
44/* Functions related to inodes */ 44/* Functions related to inodes */
45extern const struct inode_operations cifs_dir_inode_ops; 45extern const struct inode_operations cifs_dir_inode_ops;
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 74d3ccbb103b..e4de8eba4780 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -525,15 +525,17 @@ require use of the stronger protocol */
525 */ 525 */
526GLOBAL_EXTERN struct smbUidInfo *GlobalUidList[UID_HASH]; 526GLOBAL_EXTERN struct smbUidInfo *GlobalUidList[UID_HASH];
527 527
528GLOBAL_EXTERN struct list_head GlobalServerList; /* BB not implemented yet */ 528/* GLOBAL_EXTERN struct list_head GlobalServerList; BB not implemented yet */
529GLOBAL_EXTERN struct list_head GlobalSMBSessionList; 529GLOBAL_EXTERN struct list_head GlobalSMBSessionList;
530GLOBAL_EXTERN struct list_head GlobalTreeConnectionList; 530GLOBAL_EXTERN struct list_head GlobalTreeConnectionList;
531GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; /* protects list inserts on 3 above */ 531GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; /* protects list inserts on 3 above */
532 532
533GLOBAL_EXTERN struct list_head GlobalOplock_Q; 533GLOBAL_EXTERN struct list_head GlobalOplock_Q;
534 534
535GLOBAL_EXTERN struct list_head GlobalDnotifyReqList; /* Outstanding dir notify requests */ 535/* Outstanding dir notify requests */
536GLOBAL_EXTERN struct list_head GlobalDnotifyRsp_Q;/* DirNotify response queue */ 536GLOBAL_EXTERN struct list_head GlobalDnotifyReqList;
537/* DirNotify response queue */
538GLOBAL_EXTERN struct list_head GlobalDnotifyRsp_Q;
537 539
538/* 540/*
539 * Global transaction id (XID) information 541 * Global transaction id (XID) information
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index 2498d644827c..0efdf35aab2c 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -220,6 +220,9 @@
220 */ 220 */
221#define CIFS_NO_HANDLE 0xFFFF 221#define CIFS_NO_HANDLE 0xFFFF
222 222
223#define NO_CHANGE_64 0xFFFFFFFFFFFFFFFFULL
224#define NO_CHANGE_32 0xFFFFFFFFUL
225
223/* IPC$ in ASCII */ 226/* IPC$ in ASCII */
224#define CIFS_IPC_RESOURCE "\x49\x50\x43\x24" 227#define CIFS_IPC_RESOURCE "\x49\x50\x43\x24"
225 228
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 6148b82170c4..32eb1acab630 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -43,7 +43,7 @@ extern void _FreeXid(unsigned int);
43#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__FUNCTION__,curr_xid,(int)rc));} 43#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__FUNCTION__,curr_xid,(int)rc));}
44extern char *build_path_from_dentry(struct dentry *); 44extern char *build_path_from_dentry(struct dentry *);
45extern char *build_wildcard_path_from_dentry(struct dentry *direntry); 45extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
46extern void renew_parental_timestamps(struct dentry *direntry); 46/* extern void renew_parental_timestamps(struct dentry *direntry);*/
47extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *, 47extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
48 struct smb_hdr * /* input */ , 48 struct smb_hdr * /* input */ ,
49 struct smb_hdr * /* out */ , 49 struct smb_hdr * /* out */ ,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 24364106b8f9..48fc0c2ab0e5 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -4803,6 +4803,16 @@ setPermsRetry:
4803 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); 4803 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
4804 pSMB->Reserved4 = 0; 4804 pSMB->Reserved4 = 0;
4805 pSMB->hdr.smb_buf_length += byte_count; 4805 pSMB->hdr.smb_buf_length += byte_count;
4806 /* Samba server ignores set of file size to zero due to bugs in some
4807 older clients, but we should be precise - we use SetFileSize to
4808 set file size and do not want to truncate file size to zero
4809 accidently as happened on one Samba server beta by putting
4810 zero instead of -1 here */
4811 data_offset->EndOfFile = NO_CHANGE_64;
4812 data_offset->NumOfBytes = NO_CHANGE_64;
4813 data_offset->LastStatusChange = NO_CHANGE_64;
4814 data_offset->LastAccessTime = NO_CHANGE_64;
4815 data_offset->LastModificationTime = NO_CHANGE_64;
4806 data_offset->Uid = cpu_to_le64(uid); 4816 data_offset->Uid = cpu_to_le64(uid);
4807 data_offset->Gid = cpu_to_le64(gid); 4817 data_offset->Gid = cpu_to_le64(gid);
4808 /* better to leave device as zero when it is */ 4818 /* better to leave device as zero when it is */
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 66b825ade3e1..3fad638d26d3 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -31,7 +31,7 @@
31#include "cifs_debug.h" 31#include "cifs_debug.h"
32#include "cifs_fs_sb.h" 32#include "cifs_fs_sb.h"
33 33
34void 34static void
35renew_parental_timestamps(struct dentry *direntry) 35renew_parental_timestamps(struct dentry *direntry)
36{ 36{
37 /* BB check if there is a way to get the kernel to do this or if we really need this */ 37 /* BB check if there is a way to get the kernel to do this or if we really need this */
diff --git a/fs/cifs/export.c b/fs/cifs/export.c
new file mode 100644
index 000000000000..1d716392c3aa
--- /dev/null
+++ b/fs/cifs/export.c
@@ -0,0 +1,52 @@
1/*
2 * fs/cifs/export.c
3 *
4 * Copyright (C) International Business Machines Corp., 2007
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * Common Internet FileSystem (CIFS) client
8 *
9 * Operations related to support for exporting files via NFSD
10 *
11 * This library is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License as published
13 * by the Free Software Foundation; either version 2.1 of the License, or
14 * (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
19 * the GNU Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public License
22 * along with this library; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25
26 /*
27 * See Documentation/filesystems/Exporting
28 * and examples in fs/exportfs
29 */
30
31#include <linux/fs.h>
32
33#ifdef CONFIG_CIFS_EXPERIMENTAL
34
35static struct dentry *cifs_get_parent(struct dentry *dentry)
36{
37 /* BB need to add code here eventually to enable export via NFSD */
38 return ERR_PTR(-EACCES);
39}
40
41struct export_operations cifs_export_ops = {
42 .get_parent = cifs_get_parent,
43/* Following five export operations are unneeded so far and can default */
44/* .get_dentry =
45 .get_name =
46 .find_exported_dentry =
47 .decode_fh =
48 .encode_fs = */
49 };
50
51#endif /* EXPERIMENTAL */
52
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index a1265c9bfec0..2d3275bedb55 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -879,18 +879,19 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
879 cifs_stats_bytes_written(pTcon, total_written); 879 cifs_stats_bytes_written(pTcon, total_written);
880 880
881 /* since the write may have blocked check these pointers again */ 881 /* since the write may have blocked check these pointers again */
882 if (file->f_path.dentry) { 882 if ((file->f_path.dentry) && (file->f_path.dentry->d_inode)) {
883 if (file->f_path.dentry->d_inode) { 883 struct inode *inode = file->f_path.dentry->d_inode;
884 struct inode *inode = file->f_path.dentry->d_inode; 884/* Do not update local mtime - server will set its actual value on write
885 inode->i_ctime = inode->i_mtime = 885 * inode->i_ctime = inode->i_mtime =
886 current_fs_time(inode->i_sb); 886 * current_fs_time(inode->i_sb);*/
887 if (total_written > 0) { 887 if (total_written > 0) {
888 if (*poffset > file->f_path.dentry->d_inode->i_size) 888 spin_lock(&inode->i_lock);
889 i_size_write(file->f_path.dentry->d_inode, 889 if (*poffset > file->f_path.dentry->d_inode->i_size)
890 i_size_write(file->f_path.dentry->d_inode,
890 *poffset); 891 *poffset);
891 } 892 spin_unlock(&inode->i_lock);
892 mark_inode_dirty_sync(file->f_path.dentry->d_inode);
893 } 893 }
894 mark_inode_dirty_sync(file->f_path.dentry->d_inode);
894 } 895 }
895 FreeXid(xid); 896 FreeXid(xid);
896 return total_written; 897 return total_written;
@@ -1012,18 +1013,18 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
1012 cifs_stats_bytes_written(pTcon, total_written); 1013 cifs_stats_bytes_written(pTcon, total_written);
1013 1014
1014 /* since the write may have blocked check these pointers again */ 1015 /* since the write may have blocked check these pointers again */
1015 if (file->f_path.dentry) { 1016 if ((file->f_path.dentry) && (file->f_path.dentry->d_inode)) {
1016 if (file->f_path.dentry->d_inode) {
1017/*BB We could make this contingent on superblock ATIME flag too */ 1017/*BB We could make this contingent on superblock ATIME flag too */
1018/* file->f_path.dentry->d_inode->i_ctime = 1018/* file->f_path.dentry->d_inode->i_ctime =
1019 file->f_path.dentry->d_inode->i_mtime = CURRENT_TIME;*/ 1019 file->f_path.dentry->d_inode->i_mtime = CURRENT_TIME;*/
1020 if (total_written > 0) { 1020 if (total_written > 0) {
1021 if (*poffset > file->f_path.dentry->d_inode->i_size) 1021 spin_lock(&file->f_path.dentry->d_inode->i_lock);
1022 i_size_write(file->f_path.dentry->d_inode, 1022 if (*poffset > file->f_path.dentry->d_inode->i_size)
1023 *poffset); 1023 i_size_write(file->f_path.dentry->d_inode,
1024 } 1024 *poffset);
1025 mark_inode_dirty_sync(file->f_path.dentry->d_inode); 1025 spin_unlock(&file->f_path.dentry->d_inode->i_lock);
1026 } 1026 }
1027 mark_inode_dirty_sync(file->f_path.dentry->d_inode);
1027 } 1028 }
1028 FreeXid(xid); 1029 FreeXid(xid);
1029 return total_written; 1030 return total_written;
@@ -1400,6 +1401,7 @@ static int cifs_commit_write(struct file *file, struct page *page,
1400 xid = GetXid(); 1401 xid = GetXid();
1401 cFYI(1, ("commit write for page %p up to position %lld for %d", 1402 cFYI(1, ("commit write for page %p up to position %lld for %d",
1402 page, position, to)); 1403 page, position, to));
1404 spin_lock(&inode->i_lock);
1403 if (position > inode->i_size) { 1405 if (position > inode->i_size) {
1404 i_size_write(inode, position); 1406 i_size_write(inode, position);
1405 /* if (file->private_data == NULL) { 1407 /* if (file->private_data == NULL) {
@@ -1429,6 +1431,7 @@ static int cifs_commit_write(struct file *file, struct page *page,
1429 cFYI(1, (" SetEOF (commit write) rc = %d", rc)); 1431 cFYI(1, (" SetEOF (commit write) rc = %d", rc));
1430 } */ 1432 } */
1431 } 1433 }
1434 spin_unlock(&inode->i_lock);
1432 if (!PageUptodate(page)) { 1435 if (!PageUptodate(page)) {
1433 position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + offset; 1436 position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + offset;
1434 /* can not rely on (or let) writepage write this data */ 1437 /* can not rely on (or let) writepage write this data */
@@ -1989,34 +1992,52 @@ static int cifs_prepare_write(struct file *file, struct page *page,
1989 unsigned from, unsigned to) 1992 unsigned from, unsigned to)
1990{ 1993{
1991 int rc = 0; 1994 int rc = 0;
1992 loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT; 1995 loff_t i_size;
1996 loff_t offset;
1997
1993 cFYI(1, ("prepare write for page %p from %d to %d",page,from,to)); 1998 cFYI(1, ("prepare write for page %p from %d to %d",page,from,to));
1994 if (!PageUptodate(page)) { 1999 if (PageUptodate(page))
1995 /* if (to - from != PAGE_CACHE_SIZE) { 2000 return 0;
1996 void *kaddr = kmap_atomic(page, KM_USER0); 2001
2002 /* If we are writing a full page it will be up to date,
2003 no need to read from the server */
2004 if ((to == PAGE_CACHE_SIZE) && (from == 0)) {
2005 SetPageUptodate(page);
2006 return 0;
2007 }
2008
2009 offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
2010 i_size = i_size_read(page->mapping->host);
2011
2012 if ((offset >= i_size) ||
2013 ((from == 0) && (offset + to) >= i_size)) {
2014 /*
2015 * We don't need to read data beyond the end of the file.
2016 * zero it, and set the page uptodate
2017 */
2018 void *kaddr = kmap_atomic(page, KM_USER0);
2019
2020 if (from)
1997 memset(kaddr, 0, from); 2021 memset(kaddr, 0, from);
2022 if (to < PAGE_CACHE_SIZE)
1998 memset(kaddr + to, 0, PAGE_CACHE_SIZE - to); 2023 memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
1999 flush_dcache_page(page); 2024 flush_dcache_page(page);
2000 kunmap_atomic(kaddr, KM_USER0); 2025 kunmap_atomic(kaddr, KM_USER0);
2001 } */ 2026 SetPageUptodate(page);
2002 /* If we are writing a full page it will be up to date, 2027 } else if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
2003 no need to read from the server */
2004 if ((to == PAGE_CACHE_SIZE) && (from == 0))
2005 SetPageUptodate(page);
2006
2007 /* might as well read a page, it is fast enough */ 2028 /* might as well read a page, it is fast enough */
2008 if ((file->f_flags & O_ACCMODE) != O_WRONLY) { 2029 rc = cifs_readpage_worker(file, page, &offset);
2009 rc = cifs_readpage_worker(file, page, &offset); 2030 } else {
2010 } else { 2031 /* we could try using another file handle if there is one -
2011 /* should we try using another file handle if there is one - 2032 but how would we lock it to prevent close of that handle
2012 how would we lock it to prevent close of that handle 2033 racing with this read? In any case
2013 racing with this read? 2034 this will be written out by commit_write so is fine */
2014 In any case this will be written out by commit_write */
2015 }
2016 } 2035 }
2017 2036
2018 /* BB should we pass any errors back? 2037 /* we do not need to pass errors back
2019 e.g. if we do not have read access to the file */ 2038 e.g. if we do not have read access to the file
2039 because cifs_commit_write will do the right thing. -- shaggy */
2040
2020 return 0; 2041 return 0;
2021} 2042}
2022 2043
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 37c6ce87416b..86b9dbbd8441 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -143,10 +143,10 @@ int cifs_get_inode_info_unix(struct inode **pinode,
143 inode->i_gid = le64_to_cpu(findData.Gid); 143 inode->i_gid = le64_to_cpu(findData.Gid);
144 inode->i_nlink = le64_to_cpu(findData.Nlinks); 144 inode->i_nlink = le64_to_cpu(findData.Nlinks);
145 145
146 spin_lock(&inode->i_lock);
146 if (is_size_safe_to_change(cifsInfo, end_of_file)) { 147 if (is_size_safe_to_change(cifsInfo, end_of_file)) {
147 /* can not safely change the file size here if the 148 /* can not safely change the file size here if the
148 client is writing to it due to potential races */ 149 client is writing to it due to potential races */
149
150 i_size_write(inode, end_of_file); 150 i_size_write(inode, end_of_file);
151 151
152 /* blksize needs to be multiple of two. So safer to default to 152 /* blksize needs to be multiple of two. So safer to default to
@@ -162,6 +162,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
162 /* for this calculation */ 162 /* for this calculation */
163 inode->i_blocks = (512 - 1 + num_of_bytes) >> 9; 163 inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
164 } 164 }
165 spin_unlock(&inode->i_lock);
165 166
166 if (num_of_bytes < end_of_file) 167 if (num_of_bytes < end_of_file)
167 cFYI(1, ("allocation size less than end of file")); 168 cFYI(1, ("allocation size less than end of file"));
@@ -496,6 +497,8 @@ int cifs_get_inode_info(struct inode **pinode,
496 /* BB add code here - 497 /* BB add code here -
497 validate if device or weird share or device type? */ 498 validate if device or weird share or device type? */
498 } 499 }
500
501 spin_lock(&inode->i_lock);
499 if (is_size_safe_to_change(cifsInfo, le64_to_cpu(pfindData->EndOfFile))) { 502 if (is_size_safe_to_change(cifsInfo, le64_to_cpu(pfindData->EndOfFile))) {
500 /* can not safely shrink the file size here if the 503 /* can not safely shrink the file size here if the
501 client is writing to it due to potential races */ 504 client is writing to it due to potential races */
@@ -506,6 +509,7 @@ int cifs_get_inode_info(struct inode **pinode,
506 inode->i_blocks = (512 - 1 + le64_to_cpu( 509 inode->i_blocks = (512 - 1 + le64_to_cpu(
507 pfindData->AllocationSize)) >> 9; 510 pfindData->AllocationSize)) >> 9;
508 } 511 }
512 spin_unlock(&inode->i_lock);
509 513
510 inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks); 514 inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks);
511 515
@@ -834,8 +838,10 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
834 838
835 if (!rc) { 839 if (!rc) {
836 drop_nlink(inode); 840 drop_nlink(inode);
841 spin_lock(&direntry->d_inode->i_lock);
837 i_size_write(direntry->d_inode,0); 842 i_size_write(direntry->d_inode,0);
838 clear_nlink(direntry->d_inode); 843 clear_nlink(direntry->d_inode);
844 spin_unlock(&direntry->d_inode->i_lock);
839 } 845 }
840 846
841 cifsInode = CIFS_I(direntry->d_inode); 847 cifsInode = CIFS_I(direntry->d_inode);
@@ -1128,6 +1134,52 @@ static int cifs_truncate_page(struct address_space *mapping, loff_t from)
1128 return rc; 1134 return rc;
1129} 1135}
1130 1136
1137static int cifs_vmtruncate(struct inode * inode, loff_t offset)
1138{
1139 struct address_space *mapping = inode->i_mapping;
1140 unsigned long limit;
1141
1142 spin_lock(&inode->i_lock);
1143 if (inode->i_size < offset)
1144 goto do_expand;
1145 /*
1146 * truncation of in-use swapfiles is disallowed - it would cause
1147 * subsequent swapout to scribble on the now-freed blocks.
1148 */
1149 if (IS_SWAPFILE(inode)) {
1150 spin_unlock(&inode->i_lock);
1151 goto out_busy;
1152 }
1153 i_size_write(inode, offset);
1154 spin_unlock(&inode->i_lock);
1155 unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
1156 truncate_inode_pages(mapping, offset);
1157 goto out_truncate;
1158
1159do_expand:
1160 limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
1161 if (limit != RLIM_INFINITY && offset > limit) {
1162 spin_unlock(&inode->i_lock);
1163 goto out_sig;
1164 }
1165 if (offset > inode->i_sb->s_maxbytes) {
1166 spin_unlock(&inode->i_lock);
1167 goto out_big;
1168 }
1169 i_size_write(inode, offset);
1170 spin_unlock(&inode->i_lock);
1171out_truncate:
1172 if (inode->i_op && inode->i_op->truncate)
1173 inode->i_op->truncate(inode);
1174 return 0;
1175out_sig:
1176 send_sig(SIGXFSZ, current, 0);
1177out_big:
1178 return -EFBIG;
1179out_busy:
1180 return -ETXTBSY;
1181}
1182
1131int cifs_setattr(struct dentry *direntry, struct iattr *attrs) 1183int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1132{ 1184{
1133 int xid; 1185 int xid;
@@ -1244,7 +1296,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1244 */ 1296 */
1245 1297
1246 if (rc == 0) { 1298 if (rc == 0) {
1247 rc = vmtruncate(direntry->d_inode, attrs->ia_size); 1299 rc = cifs_vmtruncate(direntry->d_inode, attrs->ia_size);
1248 cifs_truncate_page(direntry->d_inode->i_mapping, 1300 cifs_truncate_page(direntry->d_inode->i_mapping,
1249 direntry->d_inode->i_size); 1301 direntry->d_inode->i_size);
1250 } else 1302 } else
@@ -1379,9 +1431,11 @@ cifs_setattr_exit:
1379 return rc; 1431 return rc;
1380} 1432}
1381 1433
1434#if 0
1382void cifs_delete_inode(struct inode *inode) 1435void cifs_delete_inode(struct inode *inode)
1383{ 1436{
1384 cFYI(1, ("In cifs_delete_inode, inode = 0x%p", inode)); 1437 cFYI(1, ("In cifs_delete_inode, inode = 0x%p", inode));
1385 /* may have to add back in if and when safe distributed caching of 1438 /* may have to add back in if and when safe distributed caching of
1386 directories added e.g. via FindNotify */ 1439 directories added e.g. via FindNotify */
1387} 1440}
1441#endif
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index c444798f0740..44cfb528797d 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Directory search handling 4 * Directory search handling
5 * 5 *
6 * Copyright (C) International Business Machines Corp., 2004, 2005 6 * Copyright (C) International Business Machines Corp., 2004, 2007
7 * Author(s): Steve French (sfrench@us.ibm.com) 7 * Author(s): Steve French (sfrench@us.ibm.com)
8 * 8 *
9 * This library is free software; you can redistribute it and/or modify 9 * This library is free software; you can redistribute it and/or modify
@@ -226,6 +226,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
226 atomic_set(&cifsInfo->inUse, 1); 226 atomic_set(&cifsInfo->inUse, 1);
227 } 227 }
228 228
229 spin_lock(&tmp_inode->i_lock);
229 if (is_size_safe_to_change(cifsInfo, end_of_file)) { 230 if (is_size_safe_to_change(cifsInfo, end_of_file)) {
230 /* can not safely change the file size here if the 231 /* can not safely change the file size here if the
231 client is writing to it due to potential races */ 232 client is writing to it due to potential races */
@@ -235,6 +236,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
235 /* for this calculation, even though the reported blocksize is larger */ 236 /* for this calculation, even though the reported blocksize is larger */
236 tmp_inode->i_blocks = (512 - 1 + allocation_size) >> 9; 237 tmp_inode->i_blocks = (512 - 1 + allocation_size) >> 9;
237 } 238 }
239 spin_unlock(&tmp_inode->i_lock);
238 240
239 if (allocation_size < end_of_file) 241 if (allocation_size < end_of_file)
240 cFYI(1, ("May be sparse file, allocation less than file size")); 242 cFYI(1, ("May be sparse file, allocation less than file size"));
@@ -355,6 +357,7 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
355 tmp_inode->i_gid = le64_to_cpu(pfindData->Gid); 357 tmp_inode->i_gid = le64_to_cpu(pfindData->Gid);
356 tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks); 358 tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks);
357 359
360 spin_lock(&tmp_inode->i_lock);
358 if (is_size_safe_to_change(cifsInfo, end_of_file)) { 361 if (is_size_safe_to_change(cifsInfo, end_of_file)) {
359 /* can not safely change the file size here if the 362 /* can not safely change the file size here if the
360 client is writing to it due to potential races */ 363 client is writing to it due to potential races */
@@ -364,6 +367,7 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
364 /* for this calculation, not the real blocksize */ 367 /* for this calculation, not the real blocksize */
365 tmp_inode->i_blocks = (512 - 1 + num_of_bytes) >> 9; 368 tmp_inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
366 } 369 }
370 spin_unlock(&tmp_inode->i_lock);
367 371
368 if (S_ISREG(tmp_inode->i_mode)) { 372 if (S_ISREG(tmp_inode->i_mode)) {
369 cFYI(1, ("File inode")); 373 cFYI(1, ("File inode"));
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index f80007eaebf4..5f468459a1e2 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -499,7 +499,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
499 due to last connection to this server being unmounted */ 499 due to last connection to this server being unmounted */
500 if (signal_pending(current)) { 500 if (signal_pending(current)) {
501 /* if signal pending do not hold up user for full smb timeout 501 /* if signal pending do not hold up user for full smb timeout
502 but we still give response a change to complete */ 502 but we still give response a chance to complete */
503 timeout = 2 * HZ; 503 timeout = 2 * HZ;
504 } 504 }
505 505
@@ -587,7 +587,6 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
587 } 587 }
588 588
589out: 589out:
590
591 DeleteMidQEntry(midQ); 590 DeleteMidQEntry(midQ);
592 atomic_dec(&ses->server->inFlight); 591 atomic_dec(&ses->server->inFlight);
593 wake_up(&ses->server->request_q); 592 wake_up(&ses->server->request_q);
@@ -681,7 +680,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
681 due to last connection to this server being unmounted */ 680 due to last connection to this server being unmounted */
682 if (signal_pending(current)) { 681 if (signal_pending(current)) {
683 /* if signal pending do not hold up user for full smb timeout 682 /* if signal pending do not hold up user for full smb timeout
684 but we still give response a change to complete */ 683 but we still give response a chance to complete */
685 timeout = 2 * HZ; 684 timeout = 2 * HZ;
686 } 685 }
687 686
@@ -765,7 +764,6 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
765 } 764 }
766 765
767out: 766out:
768
769 DeleteMidQEntry(midQ); 767 DeleteMidQEntry(midQ);
770 atomic_dec(&ses->server->inFlight); 768 atomic_dec(&ses->server->inFlight);
771 wake_up(&ses->server->request_q); 769 wake_up(&ses->server->request_q);