diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-03-06 20:32:22 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-03-06 20:32:22 -0500 |
commit | 9f6632d6290785caf9e9f874c0a0cfaf2c178e59 (patch) | |
tree | 2757e79374b98211170782c1ff8d15b8532492b7 /fs | |
parent | 8328258e745b80290534c9ab5bede6cd8340ea75 (diff) | |
parent | 8a236264f7d6db3f52881d37a86c5a5f704072b0 (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/CHANGES | 7 | ||||
-rw-r--r-- | fs/cifs/Makefile | 2 | ||||
-rw-r--r-- | fs/cifs/TODO | 16 | ||||
-rw-r--r-- | fs/cifs/cifsfs.c | 16 | ||||
-rw-r--r-- | fs/cifs/cifsfs.h | 4 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 8 | ||||
-rw-r--r-- | fs/cifs/cifspdu.h | 3 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 2 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 10 | ||||
-rw-r--r-- | fs/cifs/dir.c | 2 | ||||
-rw-r--r-- | fs/cifs/export.c | 52 | ||||
-rw-r--r-- | fs/cifs/file.c | 105 | ||||
-rw-r--r-- | fs/cifs/inode.c | 58 | ||||
-rw-r--r-- | fs/cifs/readdir.c | 6 | ||||
-rw-r--r-- | fs/cifs/transport.c | 6 |
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 @@ | |||
1 | Verison 1.48 | ||
2 | ------------ | ||
3 | Fix mtime bouncing around from local idea of last write times to remote time. | ||
4 | Fix hang (in i_size_read) when simultaneous size update of same remote file | ||
5 | on 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 | |||
1 | Version 1.47 | 8 | Version 1.47 |
2 | ------------ | 9 | ------------ |
3 | Fix oops in list_del during mount caused by unaligned string. | 10 | Fix 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 | # |
4 | obj-$(CONFIG_CIFS) += cifs.o | 4 | obj-$(CONFIG_CIFS) += cifs.o |
5 | 5 | ||
6 | cifs-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 | 6 | cifs-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 | ||
19 | d) Kerberos/SPNEGO session setup support - (started) | 19 | d) Kerberos/SPNEGO session setup support - (started) |
20 | 20 | ||
21 | e) NTLMv2 authentication (mostly implemented) | 21 | e) NTLMv2 authentication (mostly implemented - double check |
22 | that NTLMv2 signing works, also need to cleanup now unneeded SessSetup code in | ||
23 | fs/cifs/connect.c) | ||
22 | 24 | ||
23 | f) MD5-HMAC signing SMB PDUs when SPNEGO style SessionSetup | 25 | f) MD5-HMAC signing SMB PDUs when SPNEGO style SessionSetup |
24 | used (Kerberos or NTLMSSP). Signing alreadyimplemented for NTLM | 26 | used (Kerberos or NTLMSSP). Signing alreadyimplemented for NTLM |
@@ -88,11 +90,12 @@ w) Finish up the dos time conversion routines needed to return old server | |||
88 | time to the client (default time, of now or time 0 is used now for these | 90 | time to the client (default time, of now or time 0 is used now for these |
89 | very old servers) | 91 | very old servers) |
90 | 92 | ||
91 | x) Add support for OS/2 (LANMAN 1.2 and LANMAN2.1 based SMB servers) | 93 | x) In support for OS/2 (LANMAN 1.2 and LANMAN2.1 based SMB servers) |
94 | need to add ability to set time to server (utimes command) | ||
92 | 95 | ||
93 | y) Finish testing of Windows 9x/Windows ME server support (started). | 96 | y) Finish testing of Windows 9x/Windows ME server support (started). |
94 | 97 | ||
95 | KNOWN BUGS (updated April 29, 2005) | 98 | KNOWN BUGS (updated February 26, 2007) |
96 | ==================================== | 99 | ==================================== |
97 | See http://bugzilla.samba.org - search on product "CifsVFS" for | 100 | See http://bugzilla.samba.org - search on product "CifsVFS" for |
98 | current bug list. | 101 | current bug list. |
@@ -107,11 +110,6 @@ but recognizes them | |||
107 | succeed but still return access denied (appears to be Windows | 110 | succeed but still return access denied (appears to be Windows |
108 | server not cifs client problem) and has not been reproduced recently. | 111 | server not cifs client problem) and has not been reproduced recently. |
109 | NTFS partitions do not have this problem. | 112 | NTFS partitions do not have this problem. |
110 | 4) debug connectathon lock test case 10 which fails against | ||
111 | Samba (may be unmappable due to POSIX to Windows lock model | ||
112 | differences but worth investigating). Also debug Samba to | ||
113 | see why lock test case 7 takes longer to complete to Samba | ||
114 | than to Windows. | ||
115 | 113 | ||
116 | Misc testing to do | 114 | Misc testing to do |
117 | ================== | 115 | ================== |
@@ -119,7 +117,7 @@ Misc testing to do | |||
119 | types. Try nested symlinks (8 deep). Return max path name in stat -f information | 117 | types. Try nested symlinks (8 deep). Return max path name in stat -f information |
120 | 118 | ||
121 | 2) Modify file portion of ltp so it can run against a mounted network | 119 | 2) Modify file portion of ltp so it can run against a mounted network |
122 | share and run it against cifs vfs. | 120 | share and run it against cifs vfs in automated fashion. |
123 | 121 | ||
124 | 3) Additional performance testing and optimization using iozone and similar - | 122 | 3) Additional performance testing and optimization using iozone and similar - |
125 | there are some easy changes that can be done to parallelize sequential writes, | 123 | there 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 |
49 | static struct quotactl_ops cifs_quotactl_ops; | 49 | static struct quotactl_ops cifs_quotactl_ops; |
50 | #endif | 50 | #endif /* QUOTA */ |
51 | |||
52 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
53 | extern struct export_operations cifs_export_ops; | ||
54 | #endif /* EXPERIMENTAL */ | ||
51 | 55 | ||
52 | int cifsFYI = 0; | 56 | int cifsFYI = 0; |
53 | int cifsERROR = 1; | 57 | int cifsERROR = 1; |
@@ -62,8 +66,8 @@ unsigned int extended_security = CIFSSEC_DEF; | |||
62 | unsigned int sign_CIFS_PDUs = 1; | 66 | unsigned int sign_CIFS_PDUs = 1; |
63 | extern struct task_struct * oplockThread; /* remove sparse warning */ | 67 | extern struct task_struct * oplockThread; /* remove sparse warning */ |
64 | struct task_struct * oplockThread = NULL; | 68 | struct task_struct * oplockThread = NULL; |
65 | extern struct task_struct * dnotifyThread; /* remove sparse warning */ | 69 | /* extern struct task_struct * dnotifyThread; remove sparse warning */ |
66 | struct task_struct * dnotifyThread = NULL; | 70 | static struct task_struct * dnotifyThread = NULL; |
67 | static const struct super_operations cifs_super_ops; | 71 | static const struct super_operations cifs_super_ops; |
68 | unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE; | 72 | unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE; |
69 | module_param(CIFSMaxBufSize, int, 0); | 73 | module_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;*/ |
40 | extern void cifs_read_inode(struct inode *); | 40 | extern void cifs_read_inode(struct inode *); |
41 | extern 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 */ |
45 | extern const struct inode_operations cifs_dir_inode_ops; | 45 | extern 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 | */ |
526 | GLOBAL_EXTERN struct smbUidInfo *GlobalUidList[UID_HASH]; | 526 | GLOBAL_EXTERN struct smbUidInfo *GlobalUidList[UID_HASH]; |
527 | 527 | ||
528 | GLOBAL_EXTERN struct list_head GlobalServerList; /* BB not implemented yet */ | 528 | /* GLOBAL_EXTERN struct list_head GlobalServerList; BB not implemented yet */ |
529 | GLOBAL_EXTERN struct list_head GlobalSMBSessionList; | 529 | GLOBAL_EXTERN struct list_head GlobalSMBSessionList; |
530 | GLOBAL_EXTERN struct list_head GlobalTreeConnectionList; | 530 | GLOBAL_EXTERN struct list_head GlobalTreeConnectionList; |
531 | GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; /* protects list inserts on 3 above */ | 531 | GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; /* protects list inserts on 3 above */ |
532 | 532 | ||
533 | GLOBAL_EXTERN struct list_head GlobalOplock_Q; | 533 | GLOBAL_EXTERN struct list_head GlobalOplock_Q; |
534 | 534 | ||
535 | GLOBAL_EXTERN struct list_head GlobalDnotifyReqList; /* Outstanding dir notify requests */ | 535 | /* Outstanding dir notify requests */ |
536 | GLOBAL_EXTERN struct list_head GlobalDnotifyRsp_Q;/* DirNotify response queue */ | 536 | GLOBAL_EXTERN struct list_head GlobalDnotifyReqList; |
537 | /* DirNotify response queue */ | ||
538 | GLOBAL_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));} |
44 | extern char *build_path_from_dentry(struct dentry *); | 44 | extern char *build_path_from_dentry(struct dentry *); |
45 | extern char *build_wildcard_path_from_dentry(struct dentry *direntry); | 45 | extern char *build_wildcard_path_from_dentry(struct dentry *direntry); |
46 | extern void renew_parental_timestamps(struct dentry *direntry); | 46 | /* extern void renew_parental_timestamps(struct dentry *direntry);*/ |
47 | extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *, | 47 | extern 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 | ||
34 | void | 34 | static void |
35 | renew_parental_timestamps(struct dentry *direntry) | 35 | renew_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 | |||
35 | static 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 | |||
41 | struct 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 | ||
1137 | static 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 | |||
1159 | do_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); | ||
1171 | out_truncate: | ||
1172 | if (inode->i_op && inode->i_op->truncate) | ||
1173 | inode->i_op->truncate(inode); | ||
1174 | return 0; | ||
1175 | out_sig: | ||
1176 | send_sig(SIGXFSZ, current, 0); | ||
1177 | out_big: | ||
1178 | return -EFBIG; | ||
1179 | out_busy: | ||
1180 | return -ETXTBSY; | ||
1181 | } | ||
1182 | |||
1131 | int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | 1183 | int 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 | ||
1382 | void cifs_delete_inode(struct inode *inode) | 1435 | void 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 | ||
589 | out: | 589 | out: |
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 | ||
767 | out: | 766 | out: |
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); |