diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/buffer.c | 9 | ||||
-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 | ||||
-rw-r--r-- | fs/ncpfs/inode.c | 16 | ||||
-rw-r--r-- | fs/ncpfs/sock.c | 151 | ||||
-rw-r--r-- | fs/sysfs/dir.c | 2 | ||||
-rw-r--r-- | fs/sysfs/inode.c | 5 |
20 files changed, 342 insertions, 138 deletions
diff --git a/fs/buffer.c b/fs/buffer.c index e8504b65176c..1d0852fa728b 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
@@ -2365,6 +2365,10 @@ failed: | |||
2365 | } | 2365 | } |
2366 | EXPORT_SYMBOL(nobh_prepare_write); | 2366 | EXPORT_SYMBOL(nobh_prepare_write); |
2367 | 2367 | ||
2368 | /* | ||
2369 | * Make sure any changes to nobh_commit_write() are reflected in | ||
2370 | * nobh_truncate_page(), since it doesn't call commit_write(). | ||
2371 | */ | ||
2368 | int nobh_commit_write(struct file *file, struct page *page, | 2372 | int nobh_commit_write(struct file *file, struct page *page, |
2369 | unsigned from, unsigned to) | 2373 | unsigned from, unsigned to) |
2370 | { | 2374 | { |
@@ -2466,6 +2470,11 @@ int nobh_truncate_page(struct address_space *mapping, loff_t from) | |||
2466 | memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset); | 2470 | memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset); |
2467 | flush_dcache_page(page); | 2471 | flush_dcache_page(page); |
2468 | kunmap_atomic(kaddr, KM_USER0); | 2472 | kunmap_atomic(kaddr, KM_USER0); |
2473 | /* | ||
2474 | * It would be more correct to call aops->commit_write() | ||
2475 | * here, but this is more efficient. | ||
2476 | */ | ||
2477 | SetPageUptodate(page); | ||
2469 | set_page_dirty(page); | 2478 | set_page_dirty(page); |
2470 | } | 2479 | } |
2471 | unlock_page(page); | 2480 | unlock_page(page); |
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); |
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index 14939ddf74f1..7285c94956c4 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c | |||
@@ -576,6 +576,12 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) | |||
576 | server->packet = vmalloc(NCP_PACKET_SIZE); | 576 | server->packet = vmalloc(NCP_PACKET_SIZE); |
577 | if (server->packet == NULL) | 577 | if (server->packet == NULL) |
578 | goto out_nls; | 578 | goto out_nls; |
579 | server->txbuf = vmalloc(NCP_PACKET_SIZE); | ||
580 | if (server->txbuf == NULL) | ||
581 | goto out_packet; | ||
582 | server->rxbuf = vmalloc(NCP_PACKET_SIZE); | ||
583 | if (server->rxbuf == NULL) | ||
584 | goto out_txbuf; | ||
579 | 585 | ||
580 | sock->sk->sk_data_ready = ncp_tcp_data_ready; | 586 | sock->sk->sk_data_ready = ncp_tcp_data_ready; |
581 | sock->sk->sk_error_report = ncp_tcp_error_report; | 587 | sock->sk->sk_error_report = ncp_tcp_error_report; |
@@ -597,7 +603,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) | |||
597 | error = ncp_connect(server); | 603 | error = ncp_connect(server); |
598 | ncp_unlock_server(server); | 604 | ncp_unlock_server(server); |
599 | if (error < 0) | 605 | if (error < 0) |
600 | goto out_packet; | 606 | goto out_rxbuf; |
601 | DPRINTK("ncp_fill_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb)); | 607 | DPRINTK("ncp_fill_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb)); |
602 | 608 | ||
603 | error = -EMSGSIZE; /* -EREMOTESIDEINCOMPATIBLE */ | 609 | error = -EMSGSIZE; /* -EREMOTESIDEINCOMPATIBLE */ |
@@ -666,8 +672,12 @@ out_disconnect: | |||
666 | ncp_lock_server(server); | 672 | ncp_lock_server(server); |
667 | ncp_disconnect(server); | 673 | ncp_disconnect(server); |
668 | ncp_unlock_server(server); | 674 | ncp_unlock_server(server); |
669 | out_packet: | 675 | out_rxbuf: |
670 | ncp_stop_tasks(server); | 676 | ncp_stop_tasks(server); |
677 | vfree(server->rxbuf); | ||
678 | out_txbuf: | ||
679 | vfree(server->txbuf); | ||
680 | out_packet: | ||
671 | vfree(server->packet); | 681 | vfree(server->packet); |
672 | out_nls: | 682 | out_nls: |
673 | #ifdef CONFIG_NCPFS_NLS | 683 | #ifdef CONFIG_NCPFS_NLS |
@@ -723,6 +733,8 @@ static void ncp_put_super(struct super_block *sb) | |||
723 | 733 | ||
724 | kfree(server->priv.data); | 734 | kfree(server->priv.data); |
725 | kfree(server->auth.object_name); | 735 | kfree(server->auth.object_name); |
736 | vfree(server->rxbuf); | ||
737 | vfree(server->txbuf); | ||
726 | vfree(server->packet); | 738 | vfree(server->packet); |
727 | sb->s_fs_info = NULL; | 739 | sb->s_fs_info = NULL; |
728 | kfree(server); | 740 | kfree(server); |
diff --git a/fs/ncpfs/sock.c b/fs/ncpfs/sock.c index e496d8b65e92..e37df8d5fe70 100644 --- a/fs/ncpfs/sock.c +++ b/fs/ncpfs/sock.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/socket.h> | 14 | #include <linux/socket.h> |
15 | #include <linux/fcntl.h> | 15 | #include <linux/fcntl.h> |
16 | #include <linux/stat.h> | 16 | #include <linux/stat.h> |
17 | #include <linux/string.h> | ||
17 | #include <asm/uaccess.h> | 18 | #include <asm/uaccess.h> |
18 | #include <linux/in.h> | 19 | #include <linux/in.h> |
19 | #include <linux/net.h> | 20 | #include <linux/net.h> |
@@ -55,10 +56,11 @@ static int _send(struct socket *sock, const void *buff, int len) | |||
55 | struct ncp_request_reply { | 56 | struct ncp_request_reply { |
56 | struct list_head req; | 57 | struct list_head req; |
57 | wait_queue_head_t wq; | 58 | wait_queue_head_t wq; |
58 | struct ncp_reply_header* reply_buf; | 59 | atomic_t refs; |
60 | unsigned char* reply_buf; | ||
59 | size_t datalen; | 61 | size_t datalen; |
60 | int result; | 62 | int result; |
61 | enum { RQ_DONE, RQ_INPROGRESS, RQ_QUEUED, RQ_IDLE } status; | 63 | enum { RQ_DONE, RQ_INPROGRESS, RQ_QUEUED, RQ_IDLE, RQ_ABANDONED } status; |
62 | struct kvec* tx_ciov; | 64 | struct kvec* tx_ciov; |
63 | size_t tx_totallen; | 65 | size_t tx_totallen; |
64 | size_t tx_iovlen; | 66 | size_t tx_iovlen; |
@@ -67,6 +69,32 @@ struct ncp_request_reply { | |||
67 | u_int32_t sign[6]; | 69 | u_int32_t sign[6]; |
68 | }; | 70 | }; |
69 | 71 | ||
72 | static inline struct ncp_request_reply* ncp_alloc_req(void) | ||
73 | { | ||
74 | struct ncp_request_reply *req; | ||
75 | |||
76 | req = kmalloc(sizeof(struct ncp_request_reply), GFP_KERNEL); | ||
77 | if (!req) | ||
78 | return NULL; | ||
79 | |||
80 | init_waitqueue_head(&req->wq); | ||
81 | atomic_set(&req->refs, (1)); | ||
82 | req->status = RQ_IDLE; | ||
83 | |||
84 | return req; | ||
85 | } | ||
86 | |||
87 | static void ncp_req_get(struct ncp_request_reply *req) | ||
88 | { | ||
89 | atomic_inc(&req->refs); | ||
90 | } | ||
91 | |||
92 | static void ncp_req_put(struct ncp_request_reply *req) | ||
93 | { | ||
94 | if (atomic_dec_and_test(&req->refs)) | ||
95 | kfree(req); | ||
96 | } | ||
97 | |||
70 | void ncp_tcp_data_ready(struct sock *sk, int len) | 98 | void ncp_tcp_data_ready(struct sock *sk, int len) |
71 | { | 99 | { |
72 | struct ncp_server *server = sk->sk_user_data; | 100 | struct ncp_server *server = sk->sk_user_data; |
@@ -101,14 +129,17 @@ void ncpdgram_timeout_call(unsigned long v) | |||
101 | schedule_work(&server->timeout_tq); | 129 | schedule_work(&server->timeout_tq); |
102 | } | 130 | } |
103 | 131 | ||
104 | static inline void ncp_finish_request(struct ncp_request_reply *req, int result) | 132 | static inline void ncp_finish_request(struct ncp_server *server, struct ncp_request_reply *req, int result) |
105 | { | 133 | { |
106 | req->result = result; | 134 | req->result = result; |
135 | if (req->status != RQ_ABANDONED) | ||
136 | memcpy(req->reply_buf, server->rxbuf, req->datalen); | ||
107 | req->status = RQ_DONE; | 137 | req->status = RQ_DONE; |
108 | wake_up_all(&req->wq); | 138 | wake_up_all(&req->wq); |
139 | ncp_req_put(req); | ||
109 | } | 140 | } |
110 | 141 | ||
111 | static void __abort_ncp_connection(struct ncp_server *server, struct ncp_request_reply *aborted, int err) | 142 | static void __abort_ncp_connection(struct ncp_server *server) |
112 | { | 143 | { |
113 | struct ncp_request_reply *req; | 144 | struct ncp_request_reply *req; |
114 | 145 | ||
@@ -118,31 +149,19 @@ static void __abort_ncp_connection(struct ncp_server *server, struct ncp_request | |||
118 | req = list_entry(server->tx.requests.next, struct ncp_request_reply, req); | 149 | req = list_entry(server->tx.requests.next, struct ncp_request_reply, req); |
119 | 150 | ||
120 | list_del_init(&req->req); | 151 | list_del_init(&req->req); |
121 | if (req == aborted) { | 152 | ncp_finish_request(server, req, -EIO); |
122 | ncp_finish_request(req, err); | ||
123 | } else { | ||
124 | ncp_finish_request(req, -EIO); | ||
125 | } | ||
126 | } | 153 | } |
127 | req = server->rcv.creq; | 154 | req = server->rcv.creq; |
128 | if (req) { | 155 | if (req) { |
129 | server->rcv.creq = NULL; | 156 | server->rcv.creq = NULL; |
130 | if (req == aborted) { | 157 | ncp_finish_request(server, req, -EIO); |
131 | ncp_finish_request(req, err); | ||
132 | } else { | ||
133 | ncp_finish_request(req, -EIO); | ||
134 | } | ||
135 | server->rcv.ptr = NULL; | 158 | server->rcv.ptr = NULL; |
136 | server->rcv.state = 0; | 159 | server->rcv.state = 0; |
137 | } | 160 | } |
138 | req = server->tx.creq; | 161 | req = server->tx.creq; |
139 | if (req) { | 162 | if (req) { |
140 | server->tx.creq = NULL; | 163 | server->tx.creq = NULL; |
141 | if (req == aborted) { | 164 | ncp_finish_request(server, req, -EIO); |
142 | ncp_finish_request(req, err); | ||
143 | } else { | ||
144 | ncp_finish_request(req, -EIO); | ||
145 | } | ||
146 | } | 165 | } |
147 | } | 166 | } |
148 | 167 | ||
@@ -160,10 +179,12 @@ static inline void __ncp_abort_request(struct ncp_server *server, struct ncp_req | |||
160 | break; | 179 | break; |
161 | case RQ_QUEUED: | 180 | case RQ_QUEUED: |
162 | list_del_init(&req->req); | 181 | list_del_init(&req->req); |
163 | ncp_finish_request(req, err); | 182 | ncp_finish_request(server, req, err); |
164 | break; | 183 | break; |
165 | case RQ_INPROGRESS: | 184 | case RQ_INPROGRESS: |
166 | __abort_ncp_connection(server, req, err); | 185 | req->status = RQ_ABANDONED; |
186 | break; | ||
187 | case RQ_ABANDONED: | ||
167 | break; | 188 | break; |
168 | } | 189 | } |
169 | } | 190 | } |
@@ -177,7 +198,7 @@ static inline void ncp_abort_request(struct ncp_server *server, struct ncp_reque | |||
177 | 198 | ||
178 | static inline void __ncptcp_abort(struct ncp_server *server) | 199 | static inline void __ncptcp_abort(struct ncp_server *server) |
179 | { | 200 | { |
180 | __abort_ncp_connection(server, NULL, 0); | 201 | __abort_ncp_connection(server); |
181 | } | 202 | } |
182 | 203 | ||
183 | static int ncpdgram_send(struct socket *sock, struct ncp_request_reply *req) | 204 | static int ncpdgram_send(struct socket *sock, struct ncp_request_reply *req) |
@@ -294,6 +315,11 @@ static void ncptcp_start_request(struct ncp_server *server, struct ncp_request_r | |||
294 | 315 | ||
295 | static inline void __ncp_start_request(struct ncp_server *server, struct ncp_request_reply *req) | 316 | static inline void __ncp_start_request(struct ncp_server *server, struct ncp_request_reply *req) |
296 | { | 317 | { |
318 | /* we copy the data so that we do not depend on the caller | ||
319 | staying alive */ | ||
320 | memcpy(server->txbuf, req->tx_iov[1].iov_base, req->tx_iov[1].iov_len); | ||
321 | req->tx_iov[1].iov_base = server->txbuf; | ||
322 | |||
297 | if (server->ncp_sock->type == SOCK_STREAM) | 323 | if (server->ncp_sock->type == SOCK_STREAM) |
298 | ncptcp_start_request(server, req); | 324 | ncptcp_start_request(server, req); |
299 | else | 325 | else |
@@ -308,6 +334,7 @@ static int ncp_add_request(struct ncp_server *server, struct ncp_request_reply * | |||
308 | printk(KERN_ERR "ncpfs: tcp: Server died\n"); | 334 | printk(KERN_ERR "ncpfs: tcp: Server died\n"); |
309 | return -EIO; | 335 | return -EIO; |
310 | } | 336 | } |
337 | ncp_req_get(req); | ||
311 | if (server->tx.creq || server->rcv.creq) { | 338 | if (server->tx.creq || server->rcv.creq) { |
312 | req->status = RQ_QUEUED; | 339 | req->status = RQ_QUEUED; |
313 | list_add_tail(&req->req, &server->tx.requests); | 340 | list_add_tail(&req->req, &server->tx.requests); |
@@ -409,7 +436,7 @@ void ncpdgram_rcv_proc(struct work_struct *work) | |||
409 | server->timeout_last = NCP_MAX_RPC_TIMEOUT; | 436 | server->timeout_last = NCP_MAX_RPC_TIMEOUT; |
410 | mod_timer(&server->timeout_tm, jiffies + NCP_MAX_RPC_TIMEOUT); | 437 | mod_timer(&server->timeout_tm, jiffies + NCP_MAX_RPC_TIMEOUT); |
411 | } else if (reply.type == NCP_REPLY) { | 438 | } else if (reply.type == NCP_REPLY) { |
412 | result = _recv(sock, (void*)req->reply_buf, req->datalen, MSG_DONTWAIT); | 439 | result = _recv(sock, server->rxbuf, req->datalen, MSG_DONTWAIT); |
413 | #ifdef CONFIG_NCPFS_PACKET_SIGNING | 440 | #ifdef CONFIG_NCPFS_PACKET_SIGNING |
414 | if (result >= 0 && server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) { | 441 | if (result >= 0 && server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) { |
415 | if (result < 8 + 8) { | 442 | if (result < 8 + 8) { |
@@ -419,7 +446,7 @@ void ncpdgram_rcv_proc(struct work_struct *work) | |||
419 | 446 | ||
420 | result -= 8; | 447 | result -= 8; |
421 | hdrl = sock->sk->sk_family == AF_INET ? 8 : 6; | 448 | hdrl = sock->sk->sk_family == AF_INET ? 8 : 6; |
422 | if (sign_verify_reply(server, ((char*)req->reply_buf) + hdrl, result - hdrl, cpu_to_le32(result), ((char*)req->reply_buf) + result)) { | 449 | if (sign_verify_reply(server, server->rxbuf + hdrl, result - hdrl, cpu_to_le32(result), server->rxbuf + result)) { |
423 | printk(KERN_INFO "ncpfs: Signature violation\n"); | 450 | printk(KERN_INFO "ncpfs: Signature violation\n"); |
424 | result = -EIO; | 451 | result = -EIO; |
425 | } | 452 | } |
@@ -428,7 +455,7 @@ void ncpdgram_rcv_proc(struct work_struct *work) | |||
428 | #endif | 455 | #endif |
429 | del_timer(&server->timeout_tm); | 456 | del_timer(&server->timeout_tm); |
430 | server->rcv.creq = NULL; | 457 | server->rcv.creq = NULL; |
431 | ncp_finish_request(req, result); | 458 | ncp_finish_request(server, req, result); |
432 | __ncp_next_request(server); | 459 | __ncp_next_request(server); |
433 | mutex_unlock(&server->rcv.creq_mutex); | 460 | mutex_unlock(&server->rcv.creq_mutex); |
434 | continue; | 461 | continue; |
@@ -478,12 +505,6 @@ void ncpdgram_timeout_proc(struct work_struct *work) | |||
478 | mutex_unlock(&server->rcv.creq_mutex); | 505 | mutex_unlock(&server->rcv.creq_mutex); |
479 | } | 506 | } |
480 | 507 | ||
481 | static inline void ncp_init_req(struct ncp_request_reply* req) | ||
482 | { | ||
483 | init_waitqueue_head(&req->wq); | ||
484 | req->status = RQ_IDLE; | ||
485 | } | ||
486 | |||
487 | static int do_tcp_rcv(struct ncp_server *server, void *buffer, size_t len) | 508 | static int do_tcp_rcv(struct ncp_server *server, void *buffer, size_t len) |
488 | { | 509 | { |
489 | int result; | 510 | int result; |
@@ -601,8 +622,8 @@ skipdata:; | |||
601 | goto skipdata; | 622 | goto skipdata; |
602 | } | 623 | } |
603 | req->datalen = datalen - 8; | 624 | req->datalen = datalen - 8; |
604 | req->reply_buf->type = NCP_REPLY; | 625 | ((struct ncp_reply_header*)server->rxbuf)->type = NCP_REPLY; |
605 | server->rcv.ptr = (unsigned char*)(req->reply_buf) + 2; | 626 | server->rcv.ptr = server->rxbuf + 2; |
606 | server->rcv.len = datalen - 10; | 627 | server->rcv.len = datalen - 10; |
607 | server->rcv.state = 1; | 628 | server->rcv.state = 1; |
608 | break; | 629 | break; |
@@ -615,12 +636,12 @@ skipdata:; | |||
615 | case 1: | 636 | case 1: |
616 | req = server->rcv.creq; | 637 | req = server->rcv.creq; |
617 | if (req->tx_type != NCP_ALLOC_SLOT_REQUEST) { | 638 | if (req->tx_type != NCP_ALLOC_SLOT_REQUEST) { |
618 | if (req->reply_buf->sequence != server->sequence) { | 639 | if (((struct ncp_reply_header*)server->rxbuf)->sequence != server->sequence) { |
619 | printk(KERN_ERR "ncpfs: tcp: Bad sequence number\n"); | 640 | printk(KERN_ERR "ncpfs: tcp: Bad sequence number\n"); |
620 | __ncp_abort_request(server, req, -EIO); | 641 | __ncp_abort_request(server, req, -EIO); |
621 | return -EIO; | 642 | return -EIO; |
622 | } | 643 | } |
623 | if ((req->reply_buf->conn_low | (req->reply_buf->conn_high << 8)) != server->connection) { | 644 | if ((((struct ncp_reply_header*)server->rxbuf)->conn_low | (((struct ncp_reply_header*)server->rxbuf)->conn_high << 8)) != server->connection) { |
624 | printk(KERN_ERR "ncpfs: tcp: Connection number mismatch\n"); | 645 | printk(KERN_ERR "ncpfs: tcp: Connection number mismatch\n"); |
625 | __ncp_abort_request(server, req, -EIO); | 646 | __ncp_abort_request(server, req, -EIO); |
626 | return -EIO; | 647 | return -EIO; |
@@ -628,14 +649,14 @@ skipdata:; | |||
628 | } | 649 | } |
629 | #ifdef CONFIG_NCPFS_PACKET_SIGNING | 650 | #ifdef CONFIG_NCPFS_PACKET_SIGNING |
630 | if (server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) { | 651 | if (server->sign_active && req->tx_type != NCP_DEALLOC_SLOT_REQUEST) { |
631 | if (sign_verify_reply(server, (unsigned char*)(req->reply_buf) + 6, req->datalen - 6, cpu_to_be32(req->datalen + 16), &server->rcv.buf.type)) { | 652 | if (sign_verify_reply(server, server->rxbuf + 6, req->datalen - 6, cpu_to_be32(req->datalen + 16), &server->rcv.buf.type)) { |
632 | printk(KERN_ERR "ncpfs: tcp: Signature violation\n"); | 653 | printk(KERN_ERR "ncpfs: tcp: Signature violation\n"); |
633 | __ncp_abort_request(server, req, -EIO); | 654 | __ncp_abort_request(server, req, -EIO); |
634 | return -EIO; | 655 | return -EIO; |
635 | } | 656 | } |
636 | } | 657 | } |
637 | #endif | 658 | #endif |
638 | ncp_finish_request(req, req->datalen); | 659 | ncp_finish_request(server, req, req->datalen); |
639 | nextreq:; | 660 | nextreq:; |
640 | __ncp_next_request(server); | 661 | __ncp_next_request(server); |
641 | case 2: | 662 | case 2: |
@@ -645,7 +666,7 @@ skipdata:; | |||
645 | server->rcv.state = 0; | 666 | server->rcv.state = 0; |
646 | break; | 667 | break; |
647 | case 3: | 668 | case 3: |
648 | ncp_finish_request(server->rcv.creq, -EIO); | 669 | ncp_finish_request(server, server->rcv.creq, -EIO); |
649 | goto nextreq; | 670 | goto nextreq; |
650 | case 5: | 671 | case 5: |
651 | info_server(server, 0, server->unexpected_packet.data, server->unexpected_packet.len); | 672 | info_server(server, 0, server->unexpected_packet.data, server->unexpected_packet.len); |
@@ -675,28 +696,39 @@ void ncp_tcp_tx_proc(struct work_struct *work) | |||
675 | } | 696 | } |
676 | 697 | ||
677 | static int do_ncp_rpc_call(struct ncp_server *server, int size, | 698 | static int do_ncp_rpc_call(struct ncp_server *server, int size, |
678 | struct ncp_reply_header* reply_buf, int max_reply_size) | 699 | unsigned char* reply_buf, int max_reply_size) |
679 | { | 700 | { |
680 | int result; | 701 | int result; |
681 | struct ncp_request_reply req; | 702 | struct ncp_request_reply *req; |
682 | 703 | ||
683 | ncp_init_req(&req); | 704 | req = ncp_alloc_req(); |
684 | req.reply_buf = reply_buf; | 705 | if (!req) |
685 | req.datalen = max_reply_size; | 706 | return -ENOMEM; |
686 | req.tx_iov[1].iov_base = server->packet; | 707 | |
687 | req.tx_iov[1].iov_len = size; | 708 | req->reply_buf = reply_buf; |
688 | req.tx_iovlen = 1; | 709 | req->datalen = max_reply_size; |
689 | req.tx_totallen = size; | 710 | req->tx_iov[1].iov_base = server->packet; |
690 | req.tx_type = *(u_int16_t*)server->packet; | 711 | req->tx_iov[1].iov_len = size; |
691 | 712 | req->tx_iovlen = 1; | |
692 | result = ncp_add_request(server, &req); | 713 | req->tx_totallen = size; |
693 | if (result < 0) { | 714 | req->tx_type = *(u_int16_t*)server->packet; |
694 | return result; | 715 | |
695 | } | 716 | result = ncp_add_request(server, req); |
696 | if (wait_event_interruptible(req.wq, req.status == RQ_DONE)) { | 717 | if (result < 0) |
697 | ncp_abort_request(server, &req, -EIO); | 718 | goto out; |
719 | |||
720 | if (wait_event_interruptible(req->wq, req->status == RQ_DONE)) { | ||
721 | ncp_abort_request(server, req, -EINTR); | ||
722 | result = -EINTR; | ||
723 | goto out; | ||
698 | } | 724 | } |
699 | return req.result; | 725 | |
726 | result = req->result; | ||
727 | |||
728 | out: | ||
729 | ncp_req_put(req); | ||
730 | |||
731 | return result; | ||
700 | } | 732 | } |
701 | 733 | ||
702 | /* | 734 | /* |
@@ -751,11 +783,6 @@ static int ncp_do_request(struct ncp_server *server, int size, | |||
751 | 783 | ||
752 | DDPRINTK("do_ncp_rpc_call returned %d\n", result); | 784 | DDPRINTK("do_ncp_rpc_call returned %d\n", result); |
753 | 785 | ||
754 | if (result < 0) { | ||
755 | /* There was a problem with I/O, so the connections is | ||
756 | * no longer usable. */ | ||
757 | ncp_invalidate_conn(server); | ||
758 | } | ||
759 | return result; | 786 | return result; |
760 | } | 787 | } |
761 | 788 | ||
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 8813990304fe..85a668680f82 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
@@ -431,6 +431,8 @@ int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent) | |||
431 | new_parent_dentry = new_parent ? | 431 | new_parent_dentry = new_parent ? |
432 | new_parent->dentry : sysfs_mount->mnt_sb->s_root; | 432 | new_parent->dentry : sysfs_mount->mnt_sb->s_root; |
433 | 433 | ||
434 | if (old_parent_dentry->d_inode == new_parent_dentry->d_inode) | ||
435 | return 0; /* nothing to move */ | ||
434 | again: | 436 | again: |
435 | mutex_lock(&old_parent_dentry->d_inode->i_mutex); | 437 | mutex_lock(&old_parent_dentry->d_inode->i_mutex); |
436 | if (!mutex_trylock(&new_parent_dentry->d_inode->i_mutex)) { | 438 | if (!mutex_trylock(&new_parent_dentry->d_inode->i_mutex)) { |
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index dd1344b007f5..ccb7d722c558 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c | |||
@@ -227,11 +227,8 @@ static inline void orphan_all_buffers(struct inode *node) | |||
227 | 227 | ||
228 | mutex_lock_nested(&node->i_mutex, I_MUTEX_CHILD); | 228 | mutex_lock_nested(&node->i_mutex, I_MUTEX_CHILD); |
229 | if (node->i_private) { | 229 | if (node->i_private) { |
230 | list_for_each_entry(buf, &set->associates, associates) { | 230 | list_for_each_entry(buf, &set->associates, associates) |
231 | down(&buf->sem); | ||
232 | buf->orphaned = 1; | 231 | buf->orphaned = 1; |
233 | up(&buf->sem); | ||
234 | } | ||
235 | } | 232 | } |
236 | mutex_unlock(&node->i_mutex); | 233 | mutex_unlock(&node->i_mutex); |
237 | } | 234 | } |