diff options
Diffstat (limited to 'fs')
42 files changed, 706 insertions, 458 deletions
diff --git a/fs/Kconfig b/fs/Kconfig index 429a00228507..635f3e286ad8 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
@@ -459,6 +459,15 @@ config OCFS2_DEBUG_MASKLOG | |||
459 | This option will enlarge your kernel, but it allows debugging of | 459 | This option will enlarge your kernel, but it allows debugging of |
460 | ocfs2 filesystem issues. | 460 | ocfs2 filesystem issues. |
461 | 461 | ||
462 | config OCFS2_DEBUG_FS | ||
463 | bool "OCFS2 expensive checks" | ||
464 | depends on OCFS2_FS | ||
465 | default n | ||
466 | help | ||
467 | This option will enable expensive consistency checks. Enable | ||
468 | this option for debugging only as it is likely to decrease | ||
469 | performance of the filesystem. | ||
470 | |||
462 | config MINIX_FS | 471 | config MINIX_FS |
463 | tristate "Minix fs support" | 472 | tristate "Minix fs support" |
464 | help | 473 | help |
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 64dd22239b21..a609599287aa 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
@@ -1,6 +1,9 @@ | |||
1 | Version 1.52 | 1 | Version 1.52 |
2 | ------------ | 2 | ------------ |
3 | Fix oops on second mount to server when null auth is used. | 3 | Fix oops on second mount to server when null auth is used. |
4 | Enable experimental Kerberos support. Return writebehind errors on flush | ||
5 | and sync so that events like out of disk space get reported properly on | ||
6 | cached files. | ||
4 | 7 | ||
5 | Version 1.51 | 8 | Version 1.51 |
6 | ------------ | 9 | ------------ |
diff --git a/fs/cifs/README b/fs/cifs/README index b806b11b5560..bf11329ac784 100644 --- a/fs/cifs/README +++ b/fs/cifs/README | |||
@@ -225,12 +225,9 @@ If no password is provided, mount.cifs will prompt for password entry | |||
225 | 225 | ||
226 | Restrictions | 226 | Restrictions |
227 | ============ | 227 | ============ |
228 | Servers must support the NTLM SMB dialect (which is the most recent, supported | ||
229 | by Samba and Windows NT version 4, 2000 and XP and many other SMB/CIFS servers) | ||
230 | Servers must support either "pure-TCP" (port 445 TCP/IP CIFS connections) or RFC | 228 | Servers must support either "pure-TCP" (port 445 TCP/IP CIFS connections) or RFC |
231 | 1001/1002 support for "Netbios-Over-TCP/IP." Neither of these is likely to be a | 229 | 1001/1002 support for "Netbios-Over-TCP/IP." This is not likely to be a |
232 | problem as most servers support this. IPv6 support is planned for the future, | 230 | problem as most servers support this. |
233 | and is almost complete. | ||
234 | 231 | ||
235 | Valid filenames differ between Windows and Linux. Windows typically restricts | 232 | Valid filenames differ between Windows and Linux. Windows typically restricts |
236 | filenames which contain certain reserved characters (e.g.the character : | 233 | filenames which contain certain reserved characters (e.g.the character : |
@@ -458,6 +455,8 @@ A partial list of the supported mount options follows: | |||
458 | byte range locks). | 455 | byte range locks). |
459 | remount remount the share (often used to change from ro to rw mounts | 456 | remount remount the share (often used to change from ro to rw mounts |
460 | or vice versa) | 457 | or vice versa) |
458 | cifsacl Report mode bits (e.g. on stat) based on the Windows ACL for | ||
459 | the file. (EXPERIMENTAL) | ||
461 | servern Specify the server 's netbios name (RFC1001 name) to use | 460 | servern Specify the server 's netbios name (RFC1001 name) to use |
462 | when attempting to setup a session to the server. This is | 461 | when attempting to setup a session to the server. This is |
463 | This is needed for mounting to some older servers (such | 462 | This is needed for mounting to some older servers (such |
@@ -584,8 +583,8 @@ Experimental When set to 1 used to enable certain experimental | |||
584 | performance enhancement was disabled when | 583 | performance enhancement was disabled when |
585 | signing turned on in case buffer was modified | 584 | signing turned on in case buffer was modified |
586 | just before it was sent, also this flag will | 585 | just before it was sent, also this flag will |
587 | be used to use the new experimental sessionsetup | 586 | be used to use the new experimental directory change |
588 | code). | 587 | notification code). |
589 | 588 | ||
590 | These experimental features and tracing can be enabled by changing flags in | 589 | These experimental features and tracing can be enabled by changing flags in |
591 | /proc/fs/cifs (after the cifs module has been installed or built into the | 590 | /proc/fs/cifs (after the cifs module has been installed or built into the |
@@ -608,7 +607,8 @@ the start of smb requests and responses can be enabled via: | |||
608 | Two other experimental features are under development. To test these | 607 | Two other experimental features are under development. To test these |
609 | requires enabling CONFIG_CIFS_EXPERIMENTAL | 608 | requires enabling CONFIG_CIFS_EXPERIMENTAL |
610 | 609 | ||
611 | ipv6 enablement | 610 | cifsacl support needed to retrieve approximated mode bits based on |
611 | the contents on the CIFS ACL. | ||
612 | 612 | ||
613 | DNOTIFY fcntl: needed for support of directory change | 613 | DNOTIFY fcntl: needed for support of directory change |
614 | notification and perhaps later for file leases) | 614 | notification and perhaps later for file leases) |
@@ -625,10 +625,7 @@ that they represent all for that share, not just those for which the server | |||
625 | returned success. | 625 | returned success. |
626 | 626 | ||
627 | Also note that "cat /proc/fs/cifs/DebugData" will display information about | 627 | Also note that "cat /proc/fs/cifs/DebugData" will display information about |
628 | the active sessions and the shares that are mounted. Note: NTLMv2 enablement | 628 | the active sessions and the shares that are mounted. |
629 | will not work since its implementation is not quite complete yet. Do not alter | 629 | Enabling Kerberos (extended security) works when CONFIG_CIFS_EXPERIMENTAL is enabled |
630 | the ExtendedSecurity configuration value unless you are doing specific testing. | 630 | but requires a user space helper (from the Samba project). NTLM and NTLMv2 and |
631 | Enabling extended security works to Windows 2000 Workstations and XP but not to | 631 | LANMAN support do not require this helpr. |
632 | Windows 2000 server or Samba since it does not usually send "raw NTLMSSP" | ||
633 | (instead it sends NTLMSSP encapsulated in SPNEGO/GSSAPI, which support is not | ||
634 | complete in the CIFS VFS yet). | ||
diff --git a/fs/cifs/TODO b/fs/cifs/TODO index 29d4b2715254..a8852c200728 100644 --- a/fs/cifs/TODO +++ b/fs/cifs/TODO | |||
@@ -16,7 +16,7 @@ SecurityDescriptors | |||
16 | c) Better pam/winbind integration (e.g. to handle uid mapping | 16 | c) Better pam/winbind integration (e.g. to handle uid mapping |
17 | better) | 17 | better) |
18 | 18 | ||
19 | d) Kerberos/SPNEGO session setup support - (started) | 19 | d) Verify that Kerberos signing works |
20 | 20 | ||
21 | e) Cleanup now unneeded SessSetup code in | 21 | e) Cleanup now unneeded SessSetup code in |
22 | fs/cifs/connect.c and add back in NTLMSSP code if any servers | 22 | fs/cifs/connect.c and add back in NTLMSSP code if any servers |
diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c index ad54a3a6e434..1529d2b12e9c 100644 --- a/fs/cifs/cifs_spnego.c +++ b/fs/cifs/cifs_spnego.c | |||
@@ -66,20 +66,26 @@ struct key_type cifs_spnego_key_type = { | |||
66 | .describe = user_describe, | 66 | .describe = user_describe, |
67 | }; | 67 | }; |
68 | 68 | ||
69 | #define MAX_VER_STR_LEN 9 /* length of longest version string e.g. | ||
70 | strlen(";ver=0xFF") */ | ||
71 | #define MAX_MECH_STR_LEN 13 /* length of longest security mechanism name, eg | ||
72 | in future could have strlen(";sec=ntlmsspi") */ | ||
73 | #define MAX_IPV6_ADDR_LEN 42 /* eg FEDC:BA98:7654:3210:FEDC:BA98:7654:3210/60 */ | ||
69 | /* get a key struct with a SPNEGO security blob, suitable for session setup */ | 74 | /* get a key struct with a SPNEGO security blob, suitable for session setup */ |
70 | struct key * | 75 | struct key * |
71 | cifs_get_spnego_key(struct cifsSesInfo *sesInfo, const char *hostname) | 76 | cifs_get_spnego_key(struct cifsSesInfo *sesInfo) |
72 | { | 77 | { |
73 | struct TCP_Server_Info *server = sesInfo->server; | 78 | struct TCP_Server_Info *server = sesInfo->server; |
74 | char *description, *dp; | 79 | char *description, *dp; |
75 | size_t desc_len; | 80 | size_t desc_len; |
76 | struct key *spnego_key; | 81 | struct key *spnego_key; |
82 | const char *hostname = server->hostname; | ||
77 | 83 | ||
78 | 84 | /* BB: come up with better scheme for determining length */ | |
79 | /* version + ;ip{4|6}= + address + ;host=hostname + | 85 | /* length of fields (with semicolons): ver=0xyz ipv4= ipaddress host= |
80 | ;sec= + ;uid= + NULL */ | 86 | hostname sec=mechanism uid=0x uid */ |
81 | desc_len = 4 + 5 + 32 + 1 + 5 + strlen(hostname) + | 87 | desc_len = MAX_VER_STR_LEN + 5 + MAX_IPV6_ADDR_LEN + 1 + 6 + |
82 | strlen(";sec=krb5") + 7 + sizeof(uid_t)*2 + 1; | 88 | strlen(hostname) + MAX_MECH_STR_LEN + 8 + (sizeof(uid_t) * 2); |
83 | spnego_key = ERR_PTR(-ENOMEM); | 89 | spnego_key = ERR_PTR(-ENOMEM); |
84 | description = kzalloc(desc_len, GFP_KERNEL); | 90 | description = kzalloc(desc_len, GFP_KERNEL); |
85 | if (description == NULL) | 91 | if (description == NULL) |
@@ -88,7 +94,7 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo, const char *hostname) | |||
88 | dp = description; | 94 | dp = description; |
89 | /* start with version and hostname portion of UNC string */ | 95 | /* start with version and hostname portion of UNC string */ |
90 | spnego_key = ERR_PTR(-EINVAL); | 96 | spnego_key = ERR_PTR(-EINVAL); |
91 | sprintf(dp, "0x%2.2x;host=%s;", CIFS_SPNEGO_UPCALL_VERSION, | 97 | sprintf(dp, "ver=0x%x;host=%s;", CIFS_SPNEGO_UPCALL_VERSION, |
92 | hostname); | 98 | hostname); |
93 | dp = description + strlen(description); | 99 | dp = description + strlen(description); |
94 | 100 | ||
diff --git a/fs/cifs/cifs_spnego.h b/fs/cifs/cifs_spnego.h index f443f3b35134..05a34b17a1ab 100644 --- a/fs/cifs/cifs_spnego.h +++ b/fs/cifs/cifs_spnego.h | |||
@@ -41,6 +41,7 @@ struct cifs_spnego_msg { | |||
41 | 41 | ||
42 | #ifdef __KERNEL__ | 42 | #ifdef __KERNEL__ |
43 | extern struct key_type cifs_spnego_key_type; | 43 | extern struct key_type cifs_spnego_key_type; |
44 | extern struct key *cifs_get_spnego_key(struct cifsSesInfo *sesInfo); | ||
44 | #endif /* KERNEL */ | 45 | #endif /* KERNEL */ |
45 | 46 | ||
46 | #endif /* _CIFS_SPNEGO_H */ | 47 | #endif /* _CIFS_SPNEGO_H */ |
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index dabbce00712b..f02fdef463a7 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c | |||
@@ -269,6 +269,13 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, | |||
269 | 269 | ||
270 | /* BB need to add parm so we can store the SID BB */ | 270 | /* BB need to add parm so we can store the SID BB */ |
271 | 271 | ||
272 | if (!pdacl) { | ||
273 | /* no DACL in the security descriptor, set | ||
274 | all the permissions for user/group/other */ | ||
275 | inode->i_mode |= S_IRWXUGO; | ||
276 | return; | ||
277 | } | ||
278 | |||
272 | /* validate that we do not go past end of acl */ | 279 | /* validate that we do not go past end of acl */ |
273 | if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) { | 280 | if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) { |
274 | cERROR(1, ("ACL too small to parse DACL")); | 281 | cERROR(1, ("ACL too small to parse DACL")); |
@@ -286,12 +293,6 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, | |||
286 | user/group/other have no permissions */ | 293 | user/group/other have no permissions */ |
287 | inode->i_mode &= ~(S_IRWXUGO); | 294 | inode->i_mode &= ~(S_IRWXUGO); |
288 | 295 | ||
289 | if (!pdacl) { | ||
290 | /* no DACL in the security descriptor, set | ||
291 | all the permissions for user/group/other */ | ||
292 | inode->i_mode |= S_IRWXUGO; | ||
293 | return; | ||
294 | } | ||
295 | acl_base = (char *)pdacl; | 296 | acl_base = (char *)pdacl; |
296 | acl_size = sizeof(struct cifs_acl); | 297 | acl_size = sizeof(struct cifs_acl); |
297 | 298 | ||
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 416dc9fe8961..093beaa3900d 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -266,6 +266,7 @@ cifs_alloc_inode(struct super_block *sb) | |||
266 | cifs_inode->cifsAttrs = 0x20; /* default */ | 266 | cifs_inode->cifsAttrs = 0x20; /* default */ |
267 | atomic_set(&cifs_inode->inUse, 0); | 267 | atomic_set(&cifs_inode->inUse, 0); |
268 | cifs_inode->time = 0; | 268 | cifs_inode->time = 0; |
269 | cifs_inode->write_behind_rc = 0; | ||
269 | /* Until the file is open and we have gotten oplock | 270 | /* Until the file is open and we have gotten oplock |
270 | info back from the server, can not assume caching of | 271 | info back from the server, can not assume caching of |
271 | file data or metadata */ | 272 | file data or metadata */ |
@@ -852,7 +853,7 @@ static int cifs_oplock_thread(void *dummyarg) | |||
852 | struct cifsTconInfo *pTcon; | 853 | struct cifsTconInfo *pTcon; |
853 | struct inode *inode; | 854 | struct inode *inode; |
854 | __u16 netfid; | 855 | __u16 netfid; |
855 | int rc; | 856 | int rc, waitrc = 0; |
856 | 857 | ||
857 | set_freezable(); | 858 | set_freezable(); |
858 | do { | 859 | do { |
@@ -884,9 +885,11 @@ static int cifs_oplock_thread(void *dummyarg) | |||
884 | filemap_fdatawrite(inode->i_mapping); | 885 | filemap_fdatawrite(inode->i_mapping); |
885 | if (CIFS_I(inode)->clientCanCacheRead | 886 | if (CIFS_I(inode)->clientCanCacheRead |
886 | == 0) { | 887 | == 0) { |
887 | filemap_fdatawait(inode->i_mapping); | 888 | waitrc = filemap_fdatawait(inode->i_mapping); |
888 | invalidate_remote_inode(inode); | 889 | invalidate_remote_inode(inode); |
889 | } | 890 | } |
891 | if (rc == 0) | ||
892 | rc = waitrc; | ||
890 | } else | 893 | } else |
891 | rc = 0; | 894 | rc = 0; |
892 | /* mutex_unlock(&inode->i_mutex);*/ | 895 | /* mutex_unlock(&inode->i_mutex);*/ |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 87f51f23276f..1fde2197ad76 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -110,6 +110,7 @@ struct mac_key { | |||
110 | unsigned int len; | 110 | unsigned int len; |
111 | union { | 111 | union { |
112 | char ntlm[CIFS_SESS_KEY_SIZE + 16]; | 112 | char ntlm[CIFS_SESS_KEY_SIZE + 16]; |
113 | char krb5[CIFS_SESS_KEY_SIZE + 16]; /* BB: length correct? */ | ||
113 | struct { | 114 | struct { |
114 | char key[16]; | 115 | char key[16]; |
115 | struct ntlmv2_resp resp; | 116 | struct ntlmv2_resp resp; |
@@ -139,6 +140,7 @@ struct TCP_Server_Info { | |||
139 | /* 15 character server name + 0x20 16th byte indicating type = srv */ | 140 | /* 15 character server name + 0x20 16th byte indicating type = srv */ |
140 | char server_RFC1001_name[SERVER_NAME_LEN_WITH_NULL]; | 141 | char server_RFC1001_name[SERVER_NAME_LEN_WITH_NULL]; |
141 | char unicode_server_Name[SERVER_NAME_LEN_WITH_NULL * 2]; | 142 | char unicode_server_Name[SERVER_NAME_LEN_WITH_NULL * 2]; |
143 | char *hostname; /* hostname portion of UNC string */ | ||
142 | struct socket *ssocket; | 144 | struct socket *ssocket; |
143 | union { | 145 | union { |
144 | struct sockaddr_in sockAddr; | 146 | struct sockaddr_in sockAddr; |
@@ -471,6 +473,17 @@ struct dir_notify_req { | |||
471 | #define CIFS_LARGE_BUFFER 2 | 473 | #define CIFS_LARGE_BUFFER 2 |
472 | #define CIFS_IOVEC 4 /* array of response buffers */ | 474 | #define CIFS_IOVEC 4 /* array of response buffers */ |
473 | 475 | ||
476 | /* Type of Request to SendReceive2 */ | ||
477 | #define CIFS_STD_OP 0 /* normal request timeout */ | ||
478 | #define CIFS_LONG_OP 1 /* long op (up to 45 sec, oplock time) */ | ||
479 | #define CIFS_VLONG_OP 2 /* sloow op - can take up to 180 seconds */ | ||
480 | #define CIFS_BLOCKING_OP 4 /* operation can block */ | ||
481 | #define CIFS_ASYNC_OP 8 /* do not wait for response */ | ||
482 | #define CIFS_TIMEOUT_MASK 0x00F /* only one of 5 above set in req */ | ||
483 | #define CIFS_LOG_ERROR 0x010 /* log NT STATUS if non-zero */ | ||
484 | #define CIFS_LARGE_BUF_OP 0x020 /* large request buffer */ | ||
485 | #define CIFS_NO_RESP 0x040 /* no response buffer required */ | ||
486 | |||
474 | /* Security Flags: indicate type of session setup needed */ | 487 | /* Security Flags: indicate type of session setup needed */ |
475 | #define CIFSSEC_MAY_SIGN 0x00001 | 488 | #define CIFSSEC_MAY_SIGN 0x00001 |
476 | #define CIFSSEC_MAY_NTLM 0x00002 | 489 | #define CIFSSEC_MAY_NTLM 0x00002 |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index dd1d7c200ee6..8350eec49663 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -48,10 +48,11 @@ 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 */ , |
50 | int * /* bytes returned */ , const int long_op); | 50 | int * /* bytes returned */ , const int long_op); |
51 | extern int SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses, | ||
52 | struct smb_hdr *in_buf, int flags); | ||
51 | extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *, | 53 | extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *, |
52 | struct kvec *, int /* nvec to send */, | 54 | struct kvec *, int /* nvec to send */, |
53 | int * /* type of buf returned */ , const int long_op, | 55 | int * /* type of buf returned */ , const int flags); |
54 | const int logError /* whether to log status code*/ ); | ||
55 | extern int SendReceiveBlockingLock(const unsigned int /* xid */ , | 56 | extern int SendReceiveBlockingLock(const unsigned int /* xid */ , |
56 | struct cifsTconInfo *, | 57 | struct cifsTconInfo *, |
57 | struct smb_hdr * /* input */ , | 58 | struct smb_hdr * /* input */ , |
@@ -76,8 +77,6 @@ extern void header_assemble(struct smb_hdr *, char /* command */ , | |||
76 | extern int small_smb_init_no_tc(const int smb_cmd, const int wct, | 77 | extern int small_smb_init_no_tc(const int smb_cmd, const int wct, |
77 | struct cifsSesInfo *ses, | 78 | struct cifsSesInfo *ses, |
78 | void **request_buf); | 79 | void **request_buf); |
79 | extern struct key *cifs_get_spnego_key(struct cifsSesInfo *sesInfo, | ||
80 | const char *hostname); | ||
81 | extern int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, | 80 | extern int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, |
82 | const int stage, | 81 | const int stage, |
83 | const struct nls_table *nls_cp); | 82 | const struct nls_table *nls_cp); |
@@ -248,15 +247,15 @@ extern int CIFSSMBQueryReparseLinkInfo(const int xid, | |||
248 | extern int CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, | 247 | extern int CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, |
249 | const char *fileName, const int disposition, | 248 | const char *fileName, const int disposition, |
250 | const int access_flags, const int omode, | 249 | const int access_flags, const int omode, |
251 | __u16 * netfid, int *pOplock, FILE_ALL_INFO *, | 250 | __u16 *netfid, int *pOplock, FILE_ALL_INFO *, |
252 | const struct nls_table *nls_codepage, int remap); | 251 | const struct nls_table *nls_codepage, int remap); |
253 | extern int SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon, | 252 | extern int SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon, |
254 | const char *fileName, const int disposition, | 253 | const char *fileName, const int disposition, |
255 | const int access_flags, const int omode, | 254 | const int access_flags, const int omode, |
256 | __u16 * netfid, int *pOplock, FILE_ALL_INFO *, | 255 | __u16 *netfid, int *pOplock, FILE_ALL_INFO *, |
257 | const struct nls_table *nls_codepage, int remap); | 256 | const struct nls_table *nls_codepage, int remap); |
258 | extern int CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, | 257 | extern int CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, |
259 | u32 posix_flags, __u64 mode, __u16 * netfid, | 258 | u32 posix_flags, __u64 mode, __u16 *netfid, |
260 | FILE_UNIX_BASIC_INFO *pRetData, | 259 | FILE_UNIX_BASIC_INFO *pRetData, |
261 | __u32 *pOplock, const char *name, | 260 | __u32 *pOplock, const char *name, |
262 | const struct nls_table *nls_codepage, int remap); | 261 | const struct nls_table *nls_codepage, int remap); |
@@ -277,7 +276,7 @@ extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, | |||
277 | const __u64 offset, unsigned int *nbytes, | 276 | const __u64 offset, unsigned int *nbytes, |
278 | struct kvec *iov, const int nvec, const int long_op); | 277 | struct kvec *iov, const int nvec, const int long_op); |
279 | extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, | 278 | extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, |
280 | const unsigned char *searchName, __u64 * inode_number, | 279 | const unsigned char *searchName, __u64 *inode_number, |
281 | const struct nls_table *nls_codepage, | 280 | const struct nls_table *nls_codepage, |
282 | int remap_special_chars); | 281 | int remap_special_chars); |
283 | extern int cifs_convertUCSpath(char *target, const __le16 *source, int maxlen, | 282 | extern int cifs_convertUCSpath(char *target, const __le16 *source, int maxlen, |
@@ -352,5 +351,5 @@ extern int CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon, | |||
352 | const char *local_acl, const int buflen, const int acl_type, | 351 | const char *local_acl, const int buflen, const int acl_type, |
353 | const struct nls_table *nls_codepage, int remap_special_chars); | 352 | const struct nls_table *nls_codepage, int remap_special_chars); |
354 | extern int CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon, | 353 | extern int CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon, |
355 | const int netfid, __u64 * pExtAttrBits, __u64 *pMask); | 354 | const int netfid, __u64 *pExtAttrBits, __u64 *pMask); |
356 | #endif /* _CIFSPROTO_H */ | 355 | #endif /* _CIFSPROTO_H */ |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 59d7b7c037ad..9e8a6bef029a 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -698,9 +698,7 @@ int | |||
698 | CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon) | 698 | CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon) |
699 | { | 699 | { |
700 | struct smb_hdr *smb_buffer; | 700 | struct smb_hdr *smb_buffer; |
701 | struct smb_hdr *smb_buffer_response; /* BB removeme BB */ | ||
702 | int rc = 0; | 701 | int rc = 0; |
703 | int length; | ||
704 | 702 | ||
705 | cFYI(1, ("In tree disconnect")); | 703 | cFYI(1, ("In tree disconnect")); |
706 | /* | 704 | /* |
@@ -737,16 +735,12 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon) | |||
737 | if (rc) { | 735 | if (rc) { |
738 | up(&tcon->tconSem); | 736 | up(&tcon->tconSem); |
739 | return rc; | 737 | return rc; |
740 | } else { | ||
741 | smb_buffer_response = smb_buffer; /* BB removeme BB */ | ||
742 | } | 738 | } |
743 | rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response, | 739 | |
744 | &length, 0); | 740 | rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0); |
745 | if (rc) | 741 | if (rc) |
746 | cFYI(1, ("Tree disconnect failed %d", rc)); | 742 | cFYI(1, ("Tree disconnect failed %d", rc)); |
747 | 743 | ||
748 | if (smb_buffer) | ||
749 | cifs_small_buf_release(smb_buffer); | ||
750 | up(&tcon->tconSem); | 744 | up(&tcon->tconSem); |
751 | 745 | ||
752 | /* No need to return error on this operation if tid invalidated and | 746 | /* No need to return error on this operation if tid invalidated and |
@@ -760,10 +754,8 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon) | |||
760 | int | 754 | int |
761 | CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) | 755 | CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) |
762 | { | 756 | { |
763 | struct smb_hdr *smb_buffer_response; | ||
764 | LOGOFF_ANDX_REQ *pSMB; | 757 | LOGOFF_ANDX_REQ *pSMB; |
765 | int rc = 0; | 758 | int rc = 0; |
766 | int length; | ||
767 | 759 | ||
768 | cFYI(1, ("In SMBLogoff for session disconnect")); | 760 | cFYI(1, ("In SMBLogoff for session disconnect")); |
769 | if (ses) | 761 | if (ses) |
@@ -782,8 +774,6 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) | |||
782 | return rc; | 774 | return rc; |
783 | } | 775 | } |
784 | 776 | ||
785 | smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */ | ||
786 | |||
787 | if (ses->server) { | 777 | if (ses->server) { |
788 | pSMB->hdr.Mid = GetNextMid(ses->server); | 778 | pSMB->hdr.Mid = GetNextMid(ses->server); |
789 | 779 | ||
@@ -795,8 +785,7 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) | |||
795 | pSMB->hdr.Uid = ses->Suid; | 785 | pSMB->hdr.Uid = ses->Suid; |
796 | 786 | ||
797 | pSMB->AndXCommand = 0xFF; | 787 | pSMB->AndXCommand = 0xFF; |
798 | rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, | 788 | rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0); |
799 | smb_buffer_response, &length, 0); | ||
800 | if (ses->server) { | 789 | if (ses->server) { |
801 | atomic_dec(&ses->server->socketUseCount); | 790 | atomic_dec(&ses->server->socketUseCount); |
802 | if (atomic_read(&ses->server->socketUseCount) == 0) { | 791 | if (atomic_read(&ses->server->socketUseCount) == 0) { |
@@ -807,7 +796,6 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) | |||
807 | } | 796 | } |
808 | } | 797 | } |
809 | up(&ses->sesSem); | 798 | up(&ses->sesSem); |
810 | cifs_small_buf_release(pSMB); | ||
811 | 799 | ||
812 | /* if session dead then we do not need to do ulogoff, | 800 | /* if session dead then we do not need to do ulogoff, |
813 | since server closed smb session, no sense reporting | 801 | since server closed smb session, no sense reporting |
@@ -1255,7 +1243,7 @@ OldOpenRetry: | |||
1255 | pSMB->ByteCount = cpu_to_le16(count); | 1243 | pSMB->ByteCount = cpu_to_le16(count); |
1256 | /* long_op set to 1 to allow for oplock break timeouts */ | 1244 | /* long_op set to 1 to allow for oplock break timeouts */ |
1257 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1245 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
1258 | (struct smb_hdr *) pSMBr, &bytes_returned, 1); | 1246 | (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP); |
1259 | cifs_stats_inc(&tcon->num_opens); | 1247 | cifs_stats_inc(&tcon->num_opens); |
1260 | if (rc) { | 1248 | if (rc) { |
1261 | cFYI(1, ("Error in Open = %d", rc)); | 1249 | cFYI(1, ("Error in Open = %d", rc)); |
@@ -1368,7 +1356,7 @@ openRetry: | |||
1368 | pSMB->ByteCount = cpu_to_le16(count); | 1356 | pSMB->ByteCount = cpu_to_le16(count); |
1369 | /* long_op set to 1 to allow for oplock break timeouts */ | 1357 | /* long_op set to 1 to allow for oplock break timeouts */ |
1370 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1358 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
1371 | (struct smb_hdr *) pSMBr, &bytes_returned, 1); | 1359 | (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP); |
1372 | cifs_stats_inc(&tcon->num_opens); | 1360 | cifs_stats_inc(&tcon->num_opens); |
1373 | if (rc) { | 1361 | if (rc) { |
1374 | cFYI(1, ("Error in Open = %d", rc)); | 1362 | cFYI(1, ("Error in Open = %d", rc)); |
@@ -1446,7 +1434,7 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid, | |||
1446 | iov[0].iov_base = (char *)pSMB; | 1434 | iov[0].iov_base = (char *)pSMB; |
1447 | iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; | 1435 | iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; |
1448 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, | 1436 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, |
1449 | &resp_buf_type, 0 /* not long op */, 1 /* log err */ ); | 1437 | &resp_buf_type, CIFS_STD_OP | CIFS_LOG_ERROR); |
1450 | cifs_stats_inc(&tcon->num_reads); | 1438 | cifs_stats_inc(&tcon->num_reads); |
1451 | pSMBr = (READ_RSP *)iov[0].iov_base; | 1439 | pSMBr = (READ_RSP *)iov[0].iov_base; |
1452 | if (rc) { | 1440 | if (rc) { |
@@ -1665,7 +1653,7 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, | |||
1665 | 1653 | ||
1666 | 1654 | ||
1667 | rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, | 1655 | rc = SendReceive2(xid, tcon->ses, iov, n_vec + 1, &resp_buf_type, |
1668 | long_op, 0 /* do not log STATUS code */ ); | 1656 | long_op); |
1669 | cifs_stats_inc(&tcon->num_writes); | 1657 | cifs_stats_inc(&tcon->num_writes); |
1670 | if (rc) { | 1658 | if (rc) { |
1671 | cFYI(1, ("Send error Write2 = %d", rc)); | 1659 | cFYI(1, ("Send error Write2 = %d", rc)); |
@@ -1707,7 +1695,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | |||
1707 | int timeout = 0; | 1695 | int timeout = 0; |
1708 | __u16 count; | 1696 | __u16 count; |
1709 | 1697 | ||
1710 | cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d", waitFlag, numLock)); | 1698 | cFYI(1, ("CIFSSMBLock timeout %d numLock %d", waitFlag, numLock)); |
1711 | rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB); | 1699 | rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB); |
1712 | 1700 | ||
1713 | if (rc) | 1701 | if (rc) |
@@ -1716,10 +1704,10 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | |||
1716 | pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */ | 1704 | pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */ |
1717 | 1705 | ||
1718 | if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) { | 1706 | if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) { |
1719 | timeout = -1; /* no response expected */ | 1707 | timeout = CIFS_ASYNC_OP; /* no response expected */ |
1720 | pSMB->Timeout = 0; | 1708 | pSMB->Timeout = 0; |
1721 | } else if (waitFlag == TRUE) { | 1709 | } else if (waitFlag == TRUE) { |
1722 | timeout = 3; /* blocking operation, no timeout */ | 1710 | timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */ |
1723 | pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */ | 1711 | pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */ |
1724 | } else { | 1712 | } else { |
1725 | pSMB->Timeout = 0; | 1713 | pSMB->Timeout = 0; |
@@ -1749,15 +1737,16 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | |||
1749 | if (waitFlag) { | 1737 | if (waitFlag) { |
1750 | rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, | 1738 | rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, |
1751 | (struct smb_hdr *) pSMBr, &bytes_returned); | 1739 | (struct smb_hdr *) pSMBr, &bytes_returned); |
1740 | cifs_small_buf_release(pSMB); | ||
1752 | } else { | 1741 | } else { |
1753 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1742 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB, |
1754 | (struct smb_hdr *) pSMBr, &bytes_returned, timeout); | 1743 | timeout); |
1744 | /* SMB buffer freed by function above */ | ||
1755 | } | 1745 | } |
1756 | cifs_stats_inc(&tcon->num_locks); | 1746 | cifs_stats_inc(&tcon->num_locks); |
1757 | if (rc) { | 1747 | if (rc) { |
1758 | cFYI(1, ("Send error in Lock = %d", rc)); | 1748 | cFYI(1, ("Send error in Lock = %d", rc)); |
1759 | } | 1749 | } |
1760 | cifs_small_buf_release(pSMB); | ||
1761 | 1750 | ||
1762 | /* Note: On -EAGAIN error only caller can retry on handle based calls | 1751 | /* Note: On -EAGAIN error only caller can retry on handle based calls |
1763 | since file handle passed in no longer valid */ | 1752 | since file handle passed in no longer valid */ |
@@ -1776,7 +1765,9 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, | |||
1776 | int rc = 0; | 1765 | int rc = 0; |
1777 | int timeout = 0; | 1766 | int timeout = 0; |
1778 | int bytes_returned = 0; | 1767 | int bytes_returned = 0; |
1768 | int resp_buf_type = 0; | ||
1779 | __u16 params, param_offset, offset, byte_count, count; | 1769 | __u16 params, param_offset, offset, byte_count, count; |
1770 | struct kvec iov[1]; | ||
1780 | 1771 | ||
1781 | cFYI(1, ("Posix Lock")); | 1772 | cFYI(1, ("Posix Lock")); |
1782 | 1773 | ||
@@ -1818,7 +1809,7 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, | |||
1818 | 1809 | ||
1819 | parm_data->lock_type = cpu_to_le16(lock_type); | 1810 | parm_data->lock_type = cpu_to_le16(lock_type); |
1820 | if (waitFlag) { | 1811 | if (waitFlag) { |
1821 | timeout = 3; /* blocking operation, no timeout */ | 1812 | timeout = CIFS_BLOCKING_OP; /* blocking operation, no timeout */ |
1822 | parm_data->lock_flags = cpu_to_le16(1); | 1813 | parm_data->lock_flags = cpu_to_le16(1); |
1823 | pSMB->Timeout = cpu_to_le32(-1); | 1814 | pSMB->Timeout = cpu_to_le32(-1); |
1824 | } else | 1815 | } else |
@@ -1838,8 +1829,13 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, | |||
1838 | rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, | 1829 | rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, |
1839 | (struct smb_hdr *) pSMBr, &bytes_returned); | 1830 | (struct smb_hdr *) pSMBr, &bytes_returned); |
1840 | } else { | 1831 | } else { |
1841 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1832 | iov[0].iov_base = (char *)pSMB; |
1842 | (struct smb_hdr *) pSMBr, &bytes_returned, timeout); | 1833 | iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; |
1834 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, | ||
1835 | &resp_buf_type, timeout); | ||
1836 | pSMB = NULL; /* request buf already freed by SendReceive2. Do | ||
1837 | not try to free it twice below on exit */ | ||
1838 | pSMBr = (struct smb_com_transaction2_sfi_rsp *)iov[0].iov_base; | ||
1843 | } | 1839 | } |
1844 | 1840 | ||
1845 | if (rc) { | 1841 | if (rc) { |
@@ -1874,6 +1870,11 @@ plk_err_exit: | |||
1874 | if (pSMB) | 1870 | if (pSMB) |
1875 | cifs_small_buf_release(pSMB); | 1871 | cifs_small_buf_release(pSMB); |
1876 | 1872 | ||
1873 | if (resp_buf_type == CIFS_SMALL_BUFFER) | ||
1874 | cifs_small_buf_release(iov[0].iov_base); | ||
1875 | else if (resp_buf_type == CIFS_LARGE_BUFFER) | ||
1876 | cifs_buf_release(iov[0].iov_base); | ||
1877 | |||
1877 | /* Note: On -EAGAIN error only caller can retry on handle based calls | 1878 | /* Note: On -EAGAIN error only caller can retry on handle based calls |
1878 | since file handle passed in no longer valid */ | 1879 | since file handle passed in no longer valid */ |
1879 | 1880 | ||
@@ -1886,8 +1887,6 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id) | |||
1886 | { | 1887 | { |
1887 | int rc = 0; | 1888 | int rc = 0; |
1888 | CLOSE_REQ *pSMB = NULL; | 1889 | CLOSE_REQ *pSMB = NULL; |
1889 | CLOSE_RSP *pSMBr = NULL; | ||
1890 | int bytes_returned; | ||
1891 | cFYI(1, ("In CIFSSMBClose")); | 1890 | cFYI(1, ("In CIFSSMBClose")); |
1892 | 1891 | ||
1893 | /* do not retry on dead session on close */ | 1892 | /* do not retry on dead session on close */ |
@@ -1897,13 +1896,10 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id) | |||
1897 | if (rc) | 1896 | if (rc) |
1898 | return rc; | 1897 | return rc; |
1899 | 1898 | ||
1900 | pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */ | ||
1901 | |||
1902 | pSMB->FileID = (__u16) smb_file_id; | 1899 | pSMB->FileID = (__u16) smb_file_id; |
1903 | pSMB->LastWriteTime = 0xFFFFFFFF; | 1900 | pSMB->LastWriteTime = 0xFFFFFFFF; |
1904 | pSMB->ByteCount = 0; | 1901 | pSMB->ByteCount = 0; |
1905 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1902 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); |
1906 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | ||
1907 | cifs_stats_inc(&tcon->num_closes); | 1903 | cifs_stats_inc(&tcon->num_closes); |
1908 | if (rc) { | 1904 | if (rc) { |
1909 | if (rc != -EINTR) { | 1905 | if (rc != -EINTR) { |
@@ -1912,8 +1908,6 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id) | |||
1912 | } | 1908 | } |
1913 | } | 1909 | } |
1914 | 1910 | ||
1915 | cifs_small_buf_release(pSMB); | ||
1916 | |||
1917 | /* Since session is dead, file will be closed on server already */ | 1911 | /* Since session is dead, file will be closed on server already */ |
1918 | if (rc == -EAGAIN) | 1912 | if (rc == -EAGAIN) |
1919 | rc = 0; | 1913 | rc = 0; |
@@ -3102,7 +3096,7 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, | |||
3102 | iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; | 3096 | iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; |
3103 | 3097 | ||
3104 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, | 3098 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, |
3105 | 0 /* not long op */, 0 /* do not log STATUS codes */ ); | 3099 | CIFS_STD_OP); |
3106 | cifs_stats_inc(&tcon->num_acl_get); | 3100 | cifs_stats_inc(&tcon->num_acl_get); |
3107 | if (rc) { | 3101 | if (rc) { |
3108 | cFYI(1, ("Send error in QuerySecDesc = %d", rc)); | 3102 | cFYI(1, ("Send error in QuerySecDesc = %d", rc)); |
@@ -3763,8 +3757,6 @@ CIFSFindClose(const int xid, struct cifsTconInfo *tcon, | |||
3763 | { | 3757 | { |
3764 | int rc = 0; | 3758 | int rc = 0; |
3765 | FINDCLOSE_REQ *pSMB = NULL; | 3759 | FINDCLOSE_REQ *pSMB = NULL; |
3766 | CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */ | ||
3767 | int bytes_returned; | ||
3768 | 3760 | ||
3769 | cFYI(1, ("In CIFSSMBFindClose")); | 3761 | cFYI(1, ("In CIFSSMBFindClose")); |
3770 | rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB); | 3762 | rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB); |
@@ -3776,16 +3768,13 @@ CIFSFindClose(const int xid, struct cifsTconInfo *tcon, | |||
3776 | if (rc) | 3768 | if (rc) |
3777 | return rc; | 3769 | return rc; |
3778 | 3770 | ||
3779 | pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */ | ||
3780 | pSMB->FileID = searchHandle; | 3771 | pSMB->FileID = searchHandle; |
3781 | pSMB->ByteCount = 0; | 3772 | pSMB->ByteCount = 0; |
3782 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3773 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); |
3783 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | ||
3784 | if (rc) { | 3774 | if (rc) { |
3785 | cERROR(1, ("Send error in FindClose = %d", rc)); | 3775 | cERROR(1, ("Send error in FindClose = %d", rc)); |
3786 | } | 3776 | } |
3787 | cifs_stats_inc(&tcon->num_fclose); | 3777 | cifs_stats_inc(&tcon->num_fclose); |
3788 | cifs_small_buf_release(pSMB); | ||
3789 | 3778 | ||
3790 | /* Since session is dead, search handle closed on server already */ | 3779 | /* Since session is dead, search handle closed on server already */ |
3791 | if (rc == -EAGAIN) | 3780 | if (rc == -EAGAIN) |
@@ -4707,11 +4696,9 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, | |||
4707 | __u16 fid, __u32 pid_of_opener, int SetAllocation) | 4696 | __u16 fid, __u32 pid_of_opener, int SetAllocation) |
4708 | { | 4697 | { |
4709 | struct smb_com_transaction2_sfi_req *pSMB = NULL; | 4698 | struct smb_com_transaction2_sfi_req *pSMB = NULL; |
4710 | struct smb_com_transaction2_sfi_rsp *pSMBr = NULL; | ||
4711 | char *data_offset; | 4699 | char *data_offset; |
4712 | struct file_end_of_file_info *parm_data; | 4700 | struct file_end_of_file_info *parm_data; |
4713 | int rc = 0; | 4701 | int rc = 0; |
4714 | int bytes_returned = 0; | ||
4715 | __u16 params, param_offset, offset, byte_count, count; | 4702 | __u16 params, param_offset, offset, byte_count, count; |
4716 | 4703 | ||
4717 | cFYI(1, ("SetFileSize (via SetFileInfo) %lld", | 4704 | cFYI(1, ("SetFileSize (via SetFileInfo) %lld", |
@@ -4721,8 +4708,6 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, | |||
4721 | if (rc) | 4708 | if (rc) |
4722 | return rc; | 4709 | return rc; |
4723 | 4710 | ||
4724 | pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB; | ||
4725 | |||
4726 | pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener); | 4711 | pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener); |
4727 | pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16)); | 4712 | pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16)); |
4728 | 4713 | ||
@@ -4773,17 +4758,13 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, | |||
4773 | pSMB->Reserved4 = 0; | 4758 | pSMB->Reserved4 = 0; |
4774 | pSMB->hdr.smb_buf_length += byte_count; | 4759 | pSMB->hdr.smb_buf_length += byte_count; |
4775 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4760 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4776 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4761 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); |
4777 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | ||
4778 | if (rc) { | 4762 | if (rc) { |
4779 | cFYI(1, | 4763 | cFYI(1, |
4780 | ("Send error in SetFileInfo (SetFileSize) = %d", | 4764 | ("Send error in SetFileInfo (SetFileSize) = %d", |
4781 | rc)); | 4765 | rc)); |
4782 | } | 4766 | } |
4783 | 4767 | ||
4784 | if (pSMB) | ||
4785 | cifs_small_buf_release(pSMB); | ||
4786 | |||
4787 | /* Note: On -EAGAIN error only caller can retry on handle based calls | 4768 | /* Note: On -EAGAIN error only caller can retry on handle based calls |
4788 | since file handle passed in no longer valid */ | 4769 | since file handle passed in no longer valid */ |
4789 | 4770 | ||
@@ -4801,10 +4782,8 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, | |||
4801 | const FILE_BASIC_INFO *data, __u16 fid) | 4782 | const FILE_BASIC_INFO *data, __u16 fid) |
4802 | { | 4783 | { |
4803 | struct smb_com_transaction2_sfi_req *pSMB = NULL; | 4784 | struct smb_com_transaction2_sfi_req *pSMB = NULL; |
4804 | struct smb_com_transaction2_sfi_rsp *pSMBr = NULL; | ||
4805 | char *data_offset; | 4785 | char *data_offset; |
4806 | int rc = 0; | 4786 | int rc = 0; |
4807 | int bytes_returned = 0; | ||
4808 | __u16 params, param_offset, offset, byte_count, count; | 4787 | __u16 params, param_offset, offset, byte_count, count; |
4809 | 4788 | ||
4810 | cFYI(1, ("Set Times (via SetFileInfo)")); | 4789 | cFYI(1, ("Set Times (via SetFileInfo)")); |
@@ -4813,8 +4792,6 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, | |||
4813 | if (rc) | 4792 | if (rc) |
4814 | return rc; | 4793 | return rc; |
4815 | 4794 | ||
4816 | pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB; | ||
4817 | |||
4818 | /* At this point there is no need to override the current pid | 4795 | /* At this point there is no need to override the current pid |
4819 | with the pid of the opener, but that could change if we someday | 4796 | with the pid of the opener, but that could change if we someday |
4820 | use an existing handle (rather than opening one on the fly) */ | 4797 | use an existing handle (rather than opening one on the fly) */ |
@@ -4854,14 +4831,11 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, | |||
4854 | pSMB->hdr.smb_buf_length += byte_count; | 4831 | pSMB->hdr.smb_buf_length += byte_count; |
4855 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4832 | pSMB->ByteCount = cpu_to_le16(byte_count); |
4856 | memcpy(data_offset, data, sizeof(FILE_BASIC_INFO)); | 4833 | memcpy(data_offset, data, sizeof(FILE_BASIC_INFO)); |
4857 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4834 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); |
4858 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | ||
4859 | if (rc) { | 4835 | if (rc) { |
4860 | cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc)); | 4836 | cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc)); |
4861 | } | 4837 | } |
4862 | 4838 | ||
4863 | cifs_small_buf_release(pSMB); | ||
4864 | |||
4865 | /* Note: On -EAGAIN error only caller can retry on handle based calls | 4839 | /* Note: On -EAGAIN error only caller can retry on handle based calls |
4866 | since file handle passed in no longer valid */ | 4840 | since file handle passed in no longer valid */ |
4867 | 4841 | ||
@@ -5152,7 +5126,8 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, | |||
5152 | pSMB->ByteCount = 0; | 5126 | pSMB->ByteCount = 0; |
5153 | 5127 | ||
5154 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 5128 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
5155 | (struct smb_hdr *) pSMBr, &bytes_returned, -1); | 5129 | (struct smb_hdr *)pSMBr, &bytes_returned, |
5130 | CIFS_ASYNC_OP); | ||
5156 | if (rc) { | 5131 | if (rc) { |
5157 | cFYI(1, ("Error in Notify = %d", rc)); | 5132 | cFYI(1, ("Error in Notify = %d", rc)); |
5158 | } else { | 5133 | } else { |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index c52a76ff4bb9..fd9147cdb5a9 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -438,9 +438,9 @@ incomplete_rcv: | |||
438 | csocket = server->ssocket; | 438 | csocket = server->ssocket; |
439 | wake_up(&server->response_q); | 439 | wake_up(&server->response_q); |
440 | continue; | 440 | continue; |
441 | } else if (length < 4) { | 441 | } else if (length < pdu_length) { |
442 | cFYI(1, ("less than four bytes received (%d bytes)", | 442 | cFYI(1, ("requested %d bytes but only got %d bytes", |
443 | length)); | 443 | pdu_length, length)); |
444 | pdu_length -= length; | 444 | pdu_length -= length; |
445 | msleep(1); | 445 | msleep(1); |
446 | goto incomplete_rcv; | 446 | goto incomplete_rcv; |
@@ -752,6 +752,7 @@ multi_t2_fnd: | |||
752 | } | 752 | } |
753 | write_unlock(&GlobalSMBSeslock); | 753 | write_unlock(&GlobalSMBSeslock); |
754 | 754 | ||
755 | kfree(server->hostname); | ||
755 | kfree(server); | 756 | kfree(server); |
756 | if (length > 0) | 757 | if (length > 0) |
757 | mempool_resize(cifs_req_poolp, length + cifs_min_rcv, | 758 | mempool_resize(cifs_req_poolp, length + cifs_min_rcv, |
@@ -760,6 +761,34 @@ multi_t2_fnd: | |||
760 | return 0; | 761 | return 0; |
761 | } | 762 | } |
762 | 763 | ||
764 | /* extract the host portion of the UNC string */ | ||
765 | static char * | ||
766 | extract_hostname(const char *unc) | ||
767 | { | ||
768 | const char *src; | ||
769 | char *dst, *delim; | ||
770 | unsigned int len; | ||
771 | |||
772 | /* skip double chars at beginning of string */ | ||
773 | /* BB: check validity of these bytes? */ | ||
774 | src = unc + 2; | ||
775 | |||
776 | /* delimiter between hostname and sharename is always '\\' now */ | ||
777 | delim = strchr(src, '\\'); | ||
778 | if (!delim) | ||
779 | return ERR_PTR(-EINVAL); | ||
780 | |||
781 | len = delim - src; | ||
782 | dst = kmalloc((len + 1), GFP_KERNEL); | ||
783 | if (dst == NULL) | ||
784 | return ERR_PTR(-ENOMEM); | ||
785 | |||
786 | memcpy(dst, src, len); | ||
787 | dst[len] = '\0'; | ||
788 | |||
789 | return dst; | ||
790 | } | ||
791 | |||
763 | static int | 792 | static int |
764 | cifs_parse_mount_options(char *options, const char *devname, | 793 | cifs_parse_mount_options(char *options, const char *devname, |
765 | struct smb_vol *vol) | 794 | struct smb_vol *vol) |
@@ -1781,11 +1810,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1781 | 1810 | ||
1782 | memset(&volume_info, 0, sizeof(struct smb_vol)); | 1811 | memset(&volume_info, 0, sizeof(struct smb_vol)); |
1783 | if (cifs_parse_mount_options(mount_data, devname, &volume_info)) { | 1812 | if (cifs_parse_mount_options(mount_data, devname, &volume_info)) { |
1784 | kfree(volume_info.UNC); | 1813 | rc = -EINVAL; |
1785 | kfree(volume_info.password); | 1814 | goto out; |
1786 | kfree(volume_info.prepath); | ||
1787 | FreeXid(xid); | ||
1788 | return -EINVAL; | ||
1789 | } | 1815 | } |
1790 | 1816 | ||
1791 | if (volume_info.nullauth) { | 1817 | if (volume_info.nullauth) { |
@@ -1798,11 +1824,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1798 | cifserror("No username specified"); | 1824 | cifserror("No username specified"); |
1799 | /* In userspace mount helper we can get user name from alternate | 1825 | /* In userspace mount helper we can get user name from alternate |
1800 | locations such as env variables and files on disk */ | 1826 | locations such as env variables and files on disk */ |
1801 | kfree(volume_info.UNC); | 1827 | rc = -EINVAL; |
1802 | kfree(volume_info.password); | 1828 | goto out; |
1803 | kfree(volume_info.prepath); | ||
1804 | FreeXid(xid); | ||
1805 | return -EINVAL; | ||
1806 | } | 1829 | } |
1807 | 1830 | ||
1808 | if (volume_info.UNCip && volume_info.UNC) { | 1831 | if (volume_info.UNCip && volume_info.UNC) { |
@@ -1821,11 +1844,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1821 | 1844 | ||
1822 | if (rc <= 0) { | 1845 | if (rc <= 0) { |
1823 | /* we failed translating address */ | 1846 | /* we failed translating address */ |
1824 | kfree(volume_info.UNC); | 1847 | rc = -EINVAL; |
1825 | kfree(volume_info.password); | 1848 | goto out; |
1826 | kfree(volume_info.prepath); | ||
1827 | FreeXid(xid); | ||
1828 | return -EINVAL; | ||
1829 | } | 1849 | } |
1830 | 1850 | ||
1831 | cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip)); | 1851 | cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip)); |
@@ -1835,20 +1855,14 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1835 | /* BB using ip addr as server name to connect to the | 1855 | /* BB using ip addr as server name to connect to the |
1836 | DFS root below */ | 1856 | DFS root below */ |
1837 | cERROR(1, ("Connecting to DFS root not implemented yet")); | 1857 | cERROR(1, ("Connecting to DFS root not implemented yet")); |
1838 | kfree(volume_info.UNC); | 1858 | rc = -EINVAL; |
1839 | kfree(volume_info.password); | 1859 | goto out; |
1840 | kfree(volume_info.prepath); | ||
1841 | FreeXid(xid); | ||
1842 | return -EINVAL; | ||
1843 | } else /* which servers DFS root would we conect to */ { | 1860 | } else /* which servers DFS root would we conect to */ { |
1844 | cERROR(1, | 1861 | cERROR(1, |
1845 | ("CIFS mount error: No UNC path (e.g. -o " | 1862 | ("CIFS mount error: No UNC path (e.g. -o " |
1846 | "unc=//192.168.1.100/public) specified")); | 1863 | "unc=//192.168.1.100/public) specified")); |
1847 | kfree(volume_info.UNC); | 1864 | rc = -EINVAL; |
1848 | kfree(volume_info.password); | 1865 | goto out; |
1849 | kfree(volume_info.prepath); | ||
1850 | FreeXid(xid); | ||
1851 | return -EINVAL; | ||
1852 | } | 1866 | } |
1853 | 1867 | ||
1854 | /* this is needed for ASCII cp to Unicode converts */ | 1868 | /* this is needed for ASCII cp to Unicode converts */ |
@@ -1860,11 +1874,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1860 | if (cifs_sb->local_nls == NULL) { | 1874 | if (cifs_sb->local_nls == NULL) { |
1861 | cERROR(1, ("CIFS mount error: iocharset %s not found", | 1875 | cERROR(1, ("CIFS mount error: iocharset %s not found", |
1862 | volume_info.iocharset)); | 1876 | volume_info.iocharset)); |
1863 | kfree(volume_info.UNC); | 1877 | rc = -ELIBACC; |
1864 | kfree(volume_info.password); | 1878 | goto out; |
1865 | kfree(volume_info.prepath); | ||
1866 | FreeXid(xid); | ||
1867 | return -ELIBACC; | ||
1868 | } | 1879 | } |
1869 | } | 1880 | } |
1870 | 1881 | ||
@@ -1878,11 +1889,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1878 | &sin_server6.sin6_addr, | 1889 | &sin_server6.sin6_addr, |
1879 | volume_info.username, &srvTcp); | 1890 | volume_info.username, &srvTcp); |
1880 | } else { | 1891 | } else { |
1881 | kfree(volume_info.UNC); | 1892 | rc = -EINVAL; |
1882 | kfree(volume_info.password); | 1893 | goto out; |
1883 | kfree(volume_info.prepath); | ||
1884 | FreeXid(xid); | ||
1885 | return -EINVAL; | ||
1886 | } | 1894 | } |
1887 | 1895 | ||
1888 | if (srvTcp) { | 1896 | if (srvTcp) { |
@@ -1906,22 +1914,14 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1906 | "Aborting operation")); | 1914 | "Aborting operation")); |
1907 | if (csocket != NULL) | 1915 | if (csocket != NULL) |
1908 | sock_release(csocket); | 1916 | sock_release(csocket); |
1909 | kfree(volume_info.UNC); | 1917 | goto out; |
1910 | kfree(volume_info.password); | ||
1911 | kfree(volume_info.prepath); | ||
1912 | FreeXid(xid); | ||
1913 | return rc; | ||
1914 | } | 1918 | } |
1915 | 1919 | ||
1916 | srvTcp = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL); | 1920 | srvTcp = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL); |
1917 | if (!srvTcp) { | 1921 | if (!srvTcp) { |
1918 | rc = -ENOMEM; | 1922 | rc = -ENOMEM; |
1919 | sock_release(csocket); | 1923 | sock_release(csocket); |
1920 | kfree(volume_info.UNC); | 1924 | goto out; |
1921 | kfree(volume_info.password); | ||
1922 | kfree(volume_info.prepath); | ||
1923 | FreeXid(xid); | ||
1924 | return rc; | ||
1925 | } else { | 1925 | } else { |
1926 | memcpy(&srvTcp->addr.sockAddr, &sin_server, | 1926 | memcpy(&srvTcp->addr.sockAddr, &sin_server, |
1927 | sizeof(struct sockaddr_in)); | 1927 | sizeof(struct sockaddr_in)); |
@@ -1929,6 +1929,12 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1929 | /* BB Add code for ipv6 case too */ | 1929 | /* BB Add code for ipv6 case too */ |
1930 | srvTcp->ssocket = csocket; | 1930 | srvTcp->ssocket = csocket; |
1931 | srvTcp->protocolType = IPV4; | 1931 | srvTcp->protocolType = IPV4; |
1932 | srvTcp->hostname = extract_hostname(volume_info.UNC); | ||
1933 | if (IS_ERR(srvTcp->hostname)) { | ||
1934 | rc = PTR_ERR(srvTcp->hostname); | ||
1935 | sock_release(csocket); | ||
1936 | goto out; | ||
1937 | } | ||
1932 | init_waitqueue_head(&srvTcp->response_q); | 1938 | init_waitqueue_head(&srvTcp->response_q); |
1933 | init_waitqueue_head(&srvTcp->request_q); | 1939 | init_waitqueue_head(&srvTcp->request_q); |
1934 | INIT_LIST_HEAD(&srvTcp->pending_mid_q); | 1940 | INIT_LIST_HEAD(&srvTcp->pending_mid_q); |
@@ -1938,16 +1944,13 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1938 | srvTcp->tcpStatus = CifsNew; | 1944 | srvTcp->tcpStatus = CifsNew; |
1939 | init_MUTEX(&srvTcp->tcpSem); | 1945 | init_MUTEX(&srvTcp->tcpSem); |
1940 | srvTcp->tsk = kthread_run((void *)(void *)cifs_demultiplex_thread, srvTcp, "cifsd"); | 1946 | srvTcp->tsk = kthread_run((void *)(void *)cifs_demultiplex_thread, srvTcp, "cifsd"); |
1941 | if ( IS_ERR(srvTcp->tsk) ) { | 1947 | if (IS_ERR(srvTcp->tsk)) { |
1942 | rc = PTR_ERR(srvTcp->tsk); | 1948 | rc = PTR_ERR(srvTcp->tsk); |
1943 | cERROR(1, ("error %d create cifsd thread", rc)); | 1949 | cERROR(1, ("error %d create cifsd thread", rc)); |
1944 | srvTcp->tsk = NULL; | 1950 | srvTcp->tsk = NULL; |
1945 | sock_release(csocket); | 1951 | sock_release(csocket); |
1946 | kfree(volume_info.UNC); | 1952 | kfree(srvTcp->hostname); |
1947 | kfree(volume_info.password); | 1953 | goto out; |
1948 | kfree(volume_info.prepath); | ||
1949 | FreeXid(xid); | ||
1950 | return rc; | ||
1951 | } | 1954 | } |
1952 | wait_for_completion(&cifsd_complete); | 1955 | wait_for_completion(&cifsd_complete); |
1953 | rc = 0; | 1956 | rc = 0; |
@@ -1962,8 +1965,6 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1962 | if (existingCifsSes) { | 1965 | if (existingCifsSes) { |
1963 | pSesInfo = existingCifsSes; | 1966 | pSesInfo = existingCifsSes; |
1964 | cFYI(1, ("Existing smb sess found")); | 1967 | cFYI(1, ("Existing smb sess found")); |
1965 | kfree(volume_info.password); | ||
1966 | /* volume_info.UNC freed at end of function */ | ||
1967 | } else if (!rc) { | 1968 | } else if (!rc) { |
1968 | cFYI(1, ("Existing smb sess not found")); | 1969 | cFYI(1, ("Existing smb sess not found")); |
1969 | pSesInfo = sesInfoAlloc(); | 1970 | pSesInfo = sesInfoAlloc(); |
@@ -1977,8 +1978,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1977 | 1978 | ||
1978 | if (!rc) { | 1979 | if (!rc) { |
1979 | /* volume_info.password freed at unmount */ | 1980 | /* volume_info.password freed at unmount */ |
1980 | if (volume_info.password) | 1981 | if (volume_info.password) { |
1981 | pSesInfo->password = volume_info.password; | 1982 | pSesInfo->password = volume_info.password; |
1983 | /* set to NULL to prevent freeing on exit */ | ||
1984 | volume_info.password = NULL; | ||
1985 | } | ||
1982 | if (volume_info.username) | 1986 | if (volume_info.username) |
1983 | strncpy(pSesInfo->userName, | 1987 | strncpy(pSesInfo->userName, |
1984 | volume_info.username, | 1988 | volume_info.username, |
@@ -2000,8 +2004,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2000 | up(&pSesInfo->sesSem); | 2004 | up(&pSesInfo->sesSem); |
2001 | if (!rc) | 2005 | if (!rc) |
2002 | atomic_inc(&srvTcp->socketUseCount); | 2006 | atomic_inc(&srvTcp->socketUseCount); |
2003 | } else | 2007 | } |
2004 | kfree(volume_info.password); | ||
2005 | } | 2008 | } |
2006 | 2009 | ||
2007 | /* search for existing tcon to this server share */ | 2010 | /* search for existing tcon to this server share */ |
@@ -2106,9 +2109,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2106 | "", cifs_sb->local_nls, | 2109 | "", cifs_sb->local_nls, |
2107 | cifs_sb->mnt_cifs_flags & | 2110 | cifs_sb->mnt_cifs_flags & |
2108 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 2111 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
2109 | kfree(volume_info.UNC); | 2112 | rc = -ENODEV; |
2110 | FreeXid(xid); | 2113 | goto out; |
2111 | return -ENODEV; | ||
2112 | } else { | 2114 | } else { |
2113 | /* BB Do we need to wrap sesSem around | 2115 | /* BB Do we need to wrap sesSem around |
2114 | * this TCon call and Unix SetFS as | 2116 | * this TCon call and Unix SetFS as |
@@ -2231,6 +2233,12 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2231 | (in which case it is not needed anymore) but when new sesion is created | 2233 | (in which case it is not needed anymore) but when new sesion is created |
2232 | the password ptr is put in the new session structure (in which case the | 2234 | the password ptr is put in the new session structure (in which case the |
2233 | password will be freed at unmount time) */ | 2235 | password will be freed at unmount time) */ |
2236 | out: | ||
2237 | /* zero out password before freeing */ | ||
2238 | if (volume_info.password != NULL) { | ||
2239 | memset(volume_info.password, 0, strlen(volume_info.password)); | ||
2240 | kfree(volume_info.password); | ||
2241 | } | ||
2234 | kfree(volume_info.UNC); | 2242 | kfree(volume_info.UNC); |
2235 | kfree(volume_info.prepath); | 2243 | kfree(volume_info.prepath); |
2236 | FreeXid(xid); | 2244 | FreeXid(xid); |
@@ -2374,7 +2382,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
2374 | pSMB->req_no_secext.ByteCount = cpu_to_le16(count); | 2382 | pSMB->req_no_secext.ByteCount = cpu_to_le16(count); |
2375 | 2383 | ||
2376 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, | 2384 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, |
2377 | &bytes_returned, 1); | 2385 | &bytes_returned, CIFS_LONG_OP); |
2378 | if (rc) { | 2386 | if (rc) { |
2379 | /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */ | 2387 | /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */ |
2380 | } else if ((smb_buffer_response->WordCount == 3) | 2388 | } else if ((smb_buffer_response->WordCount == 3) |
@@ -2678,7 +2686,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | |||
2678 | pSMB->req.ByteCount = cpu_to_le16(count); | 2686 | pSMB->req.ByteCount = cpu_to_le16(count); |
2679 | 2687 | ||
2680 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, | 2688 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, |
2681 | &bytes_returned, 1); | 2689 | &bytes_returned, CIFS_LONG_OP); |
2682 | 2690 | ||
2683 | if (smb_buffer_response->Status.CifsError == | 2691 | if (smb_buffer_response->Status.CifsError == |
2684 | cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED)) | 2692 | cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED)) |
@@ -3105,7 +3113,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
3105 | pSMB->req.ByteCount = cpu_to_le16(count); | 3113 | pSMB->req.ByteCount = cpu_to_le16(count); |
3106 | 3114 | ||
3107 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, | 3115 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, |
3108 | &bytes_returned, 1); | 3116 | &bytes_returned, CIFS_LONG_OP); |
3109 | if (rc) { | 3117 | if (rc) { |
3110 | /* rc = map_smb_to_linux_error(smb_buffer_response) done in SendReceive now */ | 3118 | /* rc = map_smb_to_linux_error(smb_buffer_response) done in SendReceive now */ |
3111 | } else if ((smb_buffer_response->WordCount == 3) || | 3119 | } else if ((smb_buffer_response->WordCount == 3) || |
@@ -3381,7 +3389,8 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
3381 | pSMB->hdr.smb_buf_length += count; | 3389 | pSMB->hdr.smb_buf_length += count; |
3382 | pSMB->ByteCount = cpu_to_le16(count); | 3390 | pSMB->ByteCount = cpu_to_le16(count); |
3383 | 3391 | ||
3384 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0); | 3392 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, |
3393 | CIFS_STD_OP); | ||
3385 | 3394 | ||
3386 | /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */ | 3395 | /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */ |
3387 | /* above now done in SendReceive */ | 3396 | /* above now done in SendReceive */ |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 68ad4ca0cfa3..dd26e2759b17 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -130,7 +130,9 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file, | |||
130 | if (file->f_path.dentry->d_inode->i_mapping) { | 130 | if (file->f_path.dentry->d_inode->i_mapping) { |
131 | /* BB no need to lock inode until after invalidate | 131 | /* BB no need to lock inode until after invalidate |
132 | since namei code should already have it locked? */ | 132 | since namei code should already have it locked? */ |
133 | filemap_write_and_wait(file->f_path.dentry->d_inode->i_mapping); | 133 | rc = filemap_write_and_wait(file->f_path.dentry->d_inode->i_mapping); |
134 | if (rc != 0) | ||
135 | CIFS_I(file->f_path.dentry->d_inode)->write_behind_rc = rc; | ||
134 | } | 136 | } |
135 | cFYI(1, ("invalidating remote inode since open detected it " | 137 | cFYI(1, ("invalidating remote inode since open detected it " |
136 | "changed")); | 138 | "changed")); |
@@ -425,7 +427,9 @@ reopen_error_exit: | |||
425 | pCifsInode = CIFS_I(inode); | 427 | pCifsInode = CIFS_I(inode); |
426 | if (pCifsInode) { | 428 | if (pCifsInode) { |
427 | if (can_flush) { | 429 | if (can_flush) { |
428 | filemap_write_and_wait(inode->i_mapping); | 430 | rc = filemap_write_and_wait(inode->i_mapping); |
431 | if (rc != 0) | ||
432 | CIFS_I(inode)->write_behind_rc = rc; | ||
429 | /* temporarily disable caching while we | 433 | /* temporarily disable caching while we |
430 | go to server to get inode info */ | 434 | go to server to get inode info */ |
431 | pCifsInode->clientCanCacheAll = FALSE; | 435 | pCifsInode->clientCanCacheAll = FALSE; |
@@ -835,9 +839,9 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, | |||
835 | xid = GetXid(); | 839 | xid = GetXid(); |
836 | 840 | ||
837 | if (*poffset > file->f_path.dentry->d_inode->i_size) | 841 | if (*poffset > file->f_path.dentry->d_inode->i_size) |
838 | long_op = 2; /* writes past end of file can take a long time */ | 842 | long_op = CIFS_VLONG_OP; /* writes past EOF take long time */ |
839 | else | 843 | else |
840 | long_op = 1; | 844 | long_op = CIFS_LONG_OP; |
841 | 845 | ||
842 | for (total_written = 0; write_size > total_written; | 846 | for (total_written = 0; write_size > total_written; |
843 | total_written += bytes_written) { | 847 | total_written += bytes_written) { |
@@ -884,7 +888,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, | |||
884 | } | 888 | } |
885 | } else | 889 | } else |
886 | *poffset += bytes_written; | 890 | *poffset += bytes_written; |
887 | long_op = FALSE; /* subsequent writes fast - | 891 | long_op = CIFS_STD_OP; /* subsequent writes fast - |
888 | 15 seconds is plenty */ | 892 | 15 seconds is plenty */ |
889 | } | 893 | } |
890 | 894 | ||
@@ -934,9 +938,9 @@ static ssize_t cifs_write(struct file *file, const char *write_data, | |||
934 | xid = GetXid(); | 938 | xid = GetXid(); |
935 | 939 | ||
936 | if (*poffset > file->f_path.dentry->d_inode->i_size) | 940 | if (*poffset > file->f_path.dentry->d_inode->i_size) |
937 | long_op = 2; /* writes past end of file can take a long time */ | 941 | long_op = CIFS_VLONG_OP; /* writes past EOF can be slow */ |
938 | else | 942 | else |
939 | long_op = 1; | 943 | long_op = CIFS_LONG_OP; |
940 | 944 | ||
941 | for (total_written = 0; write_size > total_written; | 945 | for (total_written = 0; write_size > total_written; |
942 | total_written += bytes_written) { | 946 | total_written += bytes_written) { |
@@ -1002,7 +1006,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data, | |||
1002 | } | 1006 | } |
1003 | } else | 1007 | } else |
1004 | *poffset += bytes_written; | 1008 | *poffset += bytes_written; |
1005 | long_op = FALSE; /* subsequent writes fast - | 1009 | long_op = CIFS_STD_OP; /* subsequent writes fast - |
1006 | 15 seconds is plenty */ | 1010 | 15 seconds is plenty */ |
1007 | } | 1011 | } |
1008 | 1012 | ||
@@ -1087,11 +1091,11 @@ refind_writable: | |||
1087 | read_unlock(&GlobalSMBSeslock); | 1091 | read_unlock(&GlobalSMBSeslock); |
1088 | return open_file; | 1092 | return open_file; |
1089 | } | 1093 | } |
1090 | 1094 | ||
1091 | read_unlock(&GlobalSMBSeslock); | 1095 | read_unlock(&GlobalSMBSeslock); |
1092 | /* Had to unlock since following call can block */ | 1096 | /* Had to unlock since following call can block */ |
1093 | rc = cifs_reopen_file(open_file->pfile, FALSE); | 1097 | rc = cifs_reopen_file(open_file->pfile, FALSE); |
1094 | if (!rc) { | 1098 | if (!rc) { |
1095 | if (!open_file->closePend) | 1099 | if (!open_file->closePend) |
1096 | return open_file; | 1100 | return open_file; |
1097 | else { /* start over in case this was deleted */ | 1101 | else { /* start over in case this was deleted */ |
@@ -1114,7 +1118,7 @@ refind_writable: | |||
1114 | /* can not use this handle, no write | 1118 | /* can not use this handle, no write |
1115 | pending on this one after all */ | 1119 | pending on this one after all */ |
1116 | atomic_dec(&open_file->wrtPending); | 1120 | atomic_dec(&open_file->wrtPending); |
1117 | 1121 | ||
1118 | if (open_file->closePend) /* list could have changed */ | 1122 | if (open_file->closePend) /* list could have changed */ |
1119 | goto refind_writable; | 1123 | goto refind_writable; |
1120 | /* else we simply continue to the next entry. Thus | 1124 | /* else we simply continue to the next entry. Thus |
@@ -1360,14 +1364,17 @@ retry: | |||
1360 | open_file->netfid, | 1364 | open_file->netfid, |
1361 | bytes_to_write, offset, | 1365 | bytes_to_write, offset, |
1362 | &bytes_written, iov, n_iov, | 1366 | &bytes_written, iov, n_iov, |
1363 | 1); | 1367 | CIFS_LONG_OP); |
1364 | atomic_dec(&open_file->wrtPending); | 1368 | atomic_dec(&open_file->wrtPending); |
1365 | if (rc || bytes_written < bytes_to_write) { | 1369 | if (rc || bytes_written < bytes_to_write) { |
1366 | cERROR(1, ("Write2 ret %d, wrote %d", | 1370 | cERROR(1, ("Write2 ret %d, wrote %d", |
1367 | rc, bytes_written)); | 1371 | rc, bytes_written)); |
1368 | /* BB what if continued retry is | 1372 | /* BB what if continued retry is |
1369 | requested via mount flags? */ | 1373 | requested via mount flags? */ |
1370 | set_bit(AS_EIO, &mapping->flags); | 1374 | if (rc == -ENOSPC) |
1375 | set_bit(AS_ENOSPC, &mapping->flags); | ||
1376 | else | ||
1377 | set_bit(AS_EIO, &mapping->flags); | ||
1371 | } else { | 1378 | } else { |
1372 | cifs_stats_bytes_written(cifs_sb->tcon, | 1379 | cifs_stats_bytes_written(cifs_sb->tcon, |
1373 | bytes_written); | 1380 | bytes_written); |
@@ -1499,9 +1506,11 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync) | |||
1499 | cFYI(1, ("Sync file - name: %s datasync: 0x%x", | 1506 | cFYI(1, ("Sync file - name: %s datasync: 0x%x", |
1500 | dentry->d_name.name, datasync)); | 1507 | dentry->d_name.name, datasync)); |
1501 | 1508 | ||
1502 | rc = filemap_fdatawrite(inode->i_mapping); | 1509 | rc = filemap_write_and_wait(inode->i_mapping); |
1503 | if (rc == 0) | 1510 | if (rc == 0) { |
1511 | rc = CIFS_I(inode)->write_behind_rc; | ||
1504 | CIFS_I(inode)->write_behind_rc = 0; | 1512 | CIFS_I(inode)->write_behind_rc = 0; |
1513 | } | ||
1505 | FreeXid(xid); | 1514 | FreeXid(xid); |
1506 | return rc; | 1515 | return rc; |
1507 | } | 1516 | } |
@@ -1553,8 +1562,11 @@ int cifs_flush(struct file *file, fl_owner_t id) | |||
1553 | filemapfdatawrite appears easier for the time being */ | 1562 | filemapfdatawrite appears easier for the time being */ |
1554 | 1563 | ||
1555 | rc = filemap_fdatawrite(inode->i_mapping); | 1564 | rc = filemap_fdatawrite(inode->i_mapping); |
1556 | if (!rc) /* reset wb rc if we were able to write out dirty pages */ | 1565 | /* reset wb rc if we were able to write out dirty pages */ |
1566 | if (!rc) { | ||
1567 | rc = CIFS_I(inode)->write_behind_rc; | ||
1557 | CIFS_I(inode)->write_behind_rc = 0; | 1568 | CIFS_I(inode)->write_behind_rc = 0; |
1569 | } | ||
1558 | 1570 | ||
1559 | cFYI(1, ("Flush inode %p file %p rc %d", inode, file, rc)); | 1571 | cFYI(1, ("Flush inode %p file %p rc %d", inode, file, rc)); |
1560 | 1572 | ||
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 7d907e84e032..e915eb1d2e66 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -1233,7 +1233,7 @@ cifs_rename_exit: | |||
1233 | int cifs_revalidate(struct dentry *direntry) | 1233 | int cifs_revalidate(struct dentry *direntry) |
1234 | { | 1234 | { |
1235 | int xid; | 1235 | int xid; |
1236 | int rc = 0; | 1236 | int rc = 0, wbrc = 0; |
1237 | char *full_path; | 1237 | char *full_path; |
1238 | struct cifs_sb_info *cifs_sb; | 1238 | struct cifs_sb_info *cifs_sb; |
1239 | struct cifsInodeInfo *cifsInode; | 1239 | struct cifsInodeInfo *cifsInode; |
@@ -1333,7 +1333,9 @@ int cifs_revalidate(struct dentry *direntry) | |||
1333 | if (direntry->d_inode->i_mapping) { | 1333 | if (direntry->d_inode->i_mapping) { |
1334 | /* do we need to lock inode until after invalidate completes | 1334 | /* do we need to lock inode until after invalidate completes |
1335 | below? */ | 1335 | below? */ |
1336 | filemap_fdatawrite(direntry->d_inode->i_mapping); | 1336 | wbrc = filemap_fdatawrite(direntry->d_inode->i_mapping); |
1337 | if (wbrc) | ||
1338 | CIFS_I(direntry->d_inode)->write_behind_rc = wbrc; | ||
1337 | } | 1339 | } |
1338 | if (invalidate_inode) { | 1340 | if (invalidate_inode) { |
1339 | /* shrink_dcache not necessary now that cifs dentry ops | 1341 | /* shrink_dcache not necessary now that cifs dentry ops |
@@ -1342,7 +1344,9 @@ int cifs_revalidate(struct dentry *direntry) | |||
1342 | shrink_dcache_parent(direntry); */ | 1344 | shrink_dcache_parent(direntry); */ |
1343 | if (S_ISREG(direntry->d_inode->i_mode)) { | 1345 | if (S_ISREG(direntry->d_inode->i_mode)) { |
1344 | if (direntry->d_inode->i_mapping) | 1346 | if (direntry->d_inode->i_mapping) |
1345 | filemap_fdatawait(direntry->d_inode->i_mapping); | 1347 | wbrc = filemap_fdatawait(direntry->d_inode->i_mapping); |
1348 | if (wbrc) | ||
1349 | CIFS_I(direntry->d_inode)->write_behind_rc = wbrc; | ||
1346 | /* may eventually have to do this for open files too */ | 1350 | /* may eventually have to do this for open files too */ |
1347 | if (list_empty(&(cifsInode->openFileList))) { | 1351 | if (list_empty(&(cifsInode->openFileList))) { |
1348 | /* changed on server - flush read ahead pages */ | 1352 | /* changed on server - flush read ahead pages */ |
@@ -1485,10 +1489,20 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1485 | 1489 | ||
1486 | /* BB check if we need to refresh inode from server now ? BB */ | 1490 | /* BB check if we need to refresh inode from server now ? BB */ |
1487 | 1491 | ||
1488 | /* need to flush data before changing file size on server */ | ||
1489 | filemap_write_and_wait(direntry->d_inode->i_mapping); | ||
1490 | |||
1491 | if (attrs->ia_valid & ATTR_SIZE) { | 1492 | if (attrs->ia_valid & ATTR_SIZE) { |
1493 | /* | ||
1494 | Flush data before changing file size on server. If the | ||
1495 | flush returns error, store it to report later and continue. | ||
1496 | BB: This should be smarter. Why bother flushing pages that | ||
1497 | will be truncated anyway? Also, should we error out here if | ||
1498 | the flush returns error? | ||
1499 | */ | ||
1500 | rc = filemap_write_and_wait(direntry->d_inode->i_mapping); | ||
1501 | if (rc != 0) { | ||
1502 | CIFS_I(direntry->d_inode)->write_behind_rc = rc; | ||
1503 | rc = 0; | ||
1504 | } | ||
1505 | |||
1492 | /* To avoid spurious oplock breaks from server, in the case of | 1506 | /* To avoid spurious oplock breaks from server, in the case of |
1493 | inodes that we already have open, avoid doing path based | 1507 | inodes that we already have open, avoid doing path based |
1494 | setting of file size if we can do it by handle. | 1508 | setting of file size if we can do it by handle. |
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 899dc6078d9a..d0cb469daab7 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include "ntlmssp.h" | 29 | #include "ntlmssp.h" |
30 | #include "nterr.h" | 30 | #include "nterr.h" |
31 | #include <linux/utsname.h> | 31 | #include <linux/utsname.h> |
32 | #include "cifs_spnego.h" | ||
32 | 33 | ||
33 | extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, | 34 | extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, |
34 | unsigned char *p24); | 35 | unsigned char *p24); |
@@ -340,11 +341,12 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, | |||
340 | SESSION_SETUP_ANDX *pSMB; | 341 | SESSION_SETUP_ANDX *pSMB; |
341 | __u32 capabilities; | 342 | __u32 capabilities; |
342 | int count; | 343 | int count; |
343 | int resp_buf_type = 0; | 344 | int resp_buf_type; |
344 | struct kvec iov[2]; | 345 | struct kvec iov[3]; |
345 | enum securityEnum type; | 346 | enum securityEnum type; |
346 | __u16 action; | 347 | __u16 action; |
347 | int bytes_remaining; | 348 | int bytes_remaining; |
349 | struct key *spnego_key = NULL; | ||
348 | 350 | ||
349 | if (ses == NULL) | 351 | if (ses == NULL) |
350 | return -EINVAL; | 352 | return -EINVAL; |
@@ -377,24 +379,32 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, | |||
377 | 379 | ||
378 | capabilities = cifs_ssetup_hdr(ses, pSMB); | 380 | capabilities = cifs_ssetup_hdr(ses, pSMB); |
379 | 381 | ||
380 | /* we will send the SMB in two pieces, | 382 | /* we will send the SMB in three pieces: |
381 | a fixed length beginning part, and a | 383 | a fixed length beginning part, an optional |
382 | second part which will include the strings | 384 | SPNEGO blob (which can be zero length), and a |
383 | and rest of bcc area, in order to avoid having | 385 | last part which will include the strings |
384 | to do a large buffer 17K allocation */ | 386 | and rest of bcc area. This allows us to avoid |
387 | a large buffer 17K allocation */ | ||
385 | iov[0].iov_base = (char *)pSMB; | 388 | iov[0].iov_base = (char *)pSMB; |
386 | iov[0].iov_len = smb_buf->smb_buf_length + 4; | 389 | iov[0].iov_len = smb_buf->smb_buf_length + 4; |
387 | 390 | ||
391 | /* setting this here allows the code at the end of the function | ||
392 | to free the request buffer if there's an error */ | ||
393 | resp_buf_type = CIFS_SMALL_BUFFER; | ||
394 | |||
388 | /* 2000 big enough to fit max user, domain, NOS name etc. */ | 395 | /* 2000 big enough to fit max user, domain, NOS name etc. */ |
389 | str_area = kmalloc(2000, GFP_KERNEL); | 396 | str_area = kmalloc(2000, GFP_KERNEL); |
390 | if (str_area == NULL) { | 397 | if (str_area == NULL) { |
391 | cifs_small_buf_release(smb_buf); | 398 | rc = -ENOMEM; |
392 | return -ENOMEM; | 399 | goto ssetup_exit; |
393 | } | 400 | } |
394 | bcc_ptr = str_area; | 401 | bcc_ptr = str_area; |
395 | 402 | ||
396 | ses->flags &= ~CIFS_SES_LANMAN; | 403 | ses->flags &= ~CIFS_SES_LANMAN; |
397 | 404 | ||
405 | iov[1].iov_base = NULL; | ||
406 | iov[1].iov_len = 0; | ||
407 | |||
398 | if (type == LANMAN) { | 408 | if (type == LANMAN) { |
399 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | 409 | #ifdef CONFIG_CIFS_WEAK_PW_HASH |
400 | char lnm_session_key[CIFS_SESS_KEY_SIZE]; | 410 | char lnm_session_key[CIFS_SESS_KEY_SIZE]; |
@@ -463,8 +473,8 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, | |||
463 | struct ntlmv2_resp */ | 473 | struct ntlmv2_resp */ |
464 | 474 | ||
465 | if (v2_sess_key == NULL) { | 475 | if (v2_sess_key == NULL) { |
466 | cifs_small_buf_release(smb_buf); | 476 | rc = -ENOMEM; |
467 | return -ENOMEM; | 477 | goto ssetup_exit; |
468 | } | 478 | } |
469 | 479 | ||
470 | pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); | 480 | pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); |
@@ -499,22 +509,67 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, | |||
499 | unicode_ssetup_strings(&bcc_ptr, ses, nls_cp); | 509 | unicode_ssetup_strings(&bcc_ptr, ses, nls_cp); |
500 | } else | 510 | } else |
501 | ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); | 511 | ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); |
502 | } else /* NTLMSSP or SPNEGO */ { | 512 | } else if (type == Kerberos) { |
513 | #ifdef CONFIG_CIFS_UPCALL | ||
514 | struct cifs_spnego_msg *msg; | ||
515 | spnego_key = cifs_get_spnego_key(ses); | ||
516 | if (IS_ERR(spnego_key)) { | ||
517 | rc = PTR_ERR(spnego_key); | ||
518 | spnego_key = NULL; | ||
519 | goto ssetup_exit; | ||
520 | } | ||
521 | |||
522 | msg = spnego_key->payload.data; | ||
523 | /* bail out if key is too long */ | ||
524 | if (msg->sesskey_len > | ||
525 | sizeof(ses->server->mac_signing_key.data.krb5)) { | ||
526 | cERROR(1, ("Kerberos signing key too long (%u bytes)", | ||
527 | msg->sesskey_len)); | ||
528 | rc = -EOVERFLOW; | ||
529 | goto ssetup_exit; | ||
530 | } | ||
531 | ses->server->mac_signing_key.len = msg->sesskey_len; | ||
532 | memcpy(ses->server->mac_signing_key.data.krb5, msg->data, | ||
533 | msg->sesskey_len); | ||
503 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; | 534 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; |
504 | capabilities |= CAP_EXTENDED_SECURITY; | 535 | capabilities |= CAP_EXTENDED_SECURITY; |
505 | pSMB->req.Capabilities = cpu_to_le32(capabilities); | 536 | pSMB->req.Capabilities = cpu_to_le32(capabilities); |
506 | /* BB set password lengths */ | 537 | iov[1].iov_base = msg->data + msg->sesskey_len; |
538 | iov[1].iov_len = msg->secblob_len; | ||
539 | pSMB->req.SecurityBlobLength = cpu_to_le16(iov[1].iov_len); | ||
540 | |||
541 | if (ses->capabilities & CAP_UNICODE) { | ||
542 | /* unicode strings must be word aligned */ | ||
543 | if (iov[0].iov_len % 2) { | ||
544 | *bcc_ptr = 0; | ||
545 | bcc_ptr++; | ||
546 | } | ||
547 | unicode_oslm_strings(&bcc_ptr, nls_cp); | ||
548 | unicode_domain_string(&bcc_ptr, ses, nls_cp); | ||
549 | } else | ||
550 | /* BB: is this right? */ | ||
551 | ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); | ||
552 | #else /* ! CONFIG_CIFS_UPCALL */ | ||
553 | cERROR(1, ("Kerberos negotiated but upcall support disabled!")); | ||
554 | rc = -ENOSYS; | ||
555 | goto ssetup_exit; | ||
556 | #endif /* CONFIG_CIFS_UPCALL */ | ||
557 | } else { | ||
558 | cERROR(1, ("secType %d not supported!", type)); | ||
559 | rc = -ENOSYS; | ||
560 | goto ssetup_exit; | ||
507 | } | 561 | } |
508 | 562 | ||
509 | count = (long) bcc_ptr - (long) str_area; | 563 | iov[2].iov_base = str_area; |
564 | iov[2].iov_len = (long) bcc_ptr - (long) str_area; | ||
565 | |||
566 | count = iov[1].iov_len + iov[2].iov_len; | ||
510 | smb_buf->smb_buf_length += count; | 567 | smb_buf->smb_buf_length += count; |
511 | 568 | ||
512 | BCC_LE(smb_buf) = cpu_to_le16(count); | 569 | BCC_LE(smb_buf) = cpu_to_le16(count); |
513 | 570 | ||
514 | iov[1].iov_base = str_area; | 571 | rc = SendReceive2(xid, ses, iov, 3 /* num_iovecs */, &resp_buf_type, |
515 | iov[1].iov_len = count; | 572 | CIFS_STD_OP /* not long */ | CIFS_LOG_ERROR); |
516 | rc = SendReceive2(xid, ses, iov, 2 /* num_iovecs */, &resp_buf_type, | ||
517 | 0 /* not long op */, 1 /* log NT STATUS if any */ ); | ||
518 | /* SMB request buf freed in SendReceive2 */ | 573 | /* SMB request buf freed in SendReceive2 */ |
519 | 574 | ||
520 | cFYI(1, ("ssetup rc from sendrecv2 is %d", rc)); | 575 | cFYI(1, ("ssetup rc from sendrecv2 is %d", rc)); |
@@ -560,6 +615,8 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, | |||
560 | ses, nls_cp); | 615 | ses, nls_cp); |
561 | 616 | ||
562 | ssetup_exit: | 617 | ssetup_exit: |
618 | if (spnego_key) | ||
619 | key_put(spnego_key); | ||
563 | kfree(str_area); | 620 | kfree(str_area); |
564 | if (resp_buf_type == CIFS_SMALL_BUFFER) { | 621 | if (resp_buf_type == CIFS_SMALL_BUFFER) { |
565 | cFYI(1, ("ssetup freeing small buf %p", iov[0].iov_base)); | 622 | cFYI(1, ("ssetup freeing small buf %p", iov[0].iov_base)); |
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 7ed32b3cb781..50b623ad9320 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
@@ -308,7 +308,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, | |||
308 | 308 | ||
309 | static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op) | 309 | static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op) |
310 | { | 310 | { |
311 | if (long_op == -1) { | 311 | if (long_op == CIFS_ASYNC_OP) { |
312 | /* oplock breaks must not be held up */ | 312 | /* oplock breaks must not be held up */ |
313 | atomic_inc(&ses->server->inFlight); | 313 | atomic_inc(&ses->server->inFlight); |
314 | } else { | 314 | } else { |
@@ -337,7 +337,7 @@ static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op) | |||
337 | as they are allowed to block on server */ | 337 | as they are allowed to block on server */ |
338 | 338 | ||
339 | /* update # of requests on the wire to server */ | 339 | /* update # of requests on the wire to server */ |
340 | if (long_op < 3) | 340 | if (long_op != CIFS_BLOCKING_OP) |
341 | atomic_inc(&ses->server->inFlight); | 341 | atomic_inc(&ses->server->inFlight); |
342 | spin_unlock(&GlobalMid_Lock); | 342 | spin_unlock(&GlobalMid_Lock); |
343 | break; | 343 | break; |
@@ -415,17 +415,48 @@ static int wait_for_response(struct cifsSesInfo *ses, | |||
415 | } | 415 | } |
416 | } | 416 | } |
417 | 417 | ||
418 | |||
419 | /* | ||
420 | * | ||
421 | * Send an SMB Request. No response info (other than return code) | ||
422 | * needs to be parsed. | ||
423 | * | ||
424 | * flags indicate the type of request buffer and how long to wait | ||
425 | * and whether to log NT STATUS code (error) before mapping it to POSIX error | ||
426 | * | ||
427 | */ | ||
428 | int | ||
429 | SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses, | ||
430 | struct smb_hdr *in_buf, int flags) | ||
431 | { | ||
432 | int rc; | ||
433 | struct kvec iov[1]; | ||
434 | int resp_buf_type; | ||
435 | |||
436 | iov[0].iov_base = (char *)in_buf; | ||
437 | iov[0].iov_len = in_buf->smb_buf_length + 4; | ||
438 | flags |= CIFS_NO_RESP; | ||
439 | rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags); | ||
440 | #ifdef CONFIG_CIFS_DEBUG2 | ||
441 | cFYI(1, ("SendRcvNoR flags %d rc %d", flags, rc)); | ||
442 | #endif | ||
443 | return rc; | ||
444 | } | ||
445 | |||
418 | int | 446 | int |
419 | SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, | 447 | SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, |
420 | struct kvec *iov, int n_vec, int *pRespBufType /* ret */, | 448 | struct kvec *iov, int n_vec, int *pRespBufType /* ret */, |
421 | const int long_op, const int logError) | 449 | const int flags) |
422 | { | 450 | { |
423 | int rc = 0; | 451 | int rc = 0; |
452 | int long_op; | ||
424 | unsigned int receive_len; | 453 | unsigned int receive_len; |
425 | unsigned long timeout; | 454 | unsigned long timeout; |
426 | struct mid_q_entry *midQ; | 455 | struct mid_q_entry *midQ; |
427 | struct smb_hdr *in_buf = iov[0].iov_base; | 456 | struct smb_hdr *in_buf = iov[0].iov_base; |
428 | 457 | ||
458 | long_op = flags & CIFS_TIMEOUT_MASK; | ||
459 | |||
429 | *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */ | 460 | *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */ |
430 | 461 | ||
431 | if ((ses == NULL) || (ses->server == NULL)) { | 462 | if ((ses == NULL) || (ses->server == NULL)) { |
@@ -483,15 +514,22 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, | |||
483 | if (rc < 0) | 514 | if (rc < 0) |
484 | goto out; | 515 | goto out; |
485 | 516 | ||
486 | if (long_op == -1) | 517 | if (long_op == CIFS_STD_OP) |
487 | goto out; | 518 | timeout = 15 * HZ; |
488 | else if (long_op == 2) /* writes past end of file can take loong time */ | 519 | else if (long_op == CIFS_VLONG_OP) /* e.g. slow writes past EOF */ |
489 | timeout = 180 * HZ; | 520 | timeout = 180 * HZ; |
490 | else if (long_op == 1) | 521 | else if (long_op == CIFS_LONG_OP) |
491 | timeout = 45 * HZ; /* should be greater than | 522 | timeout = 45 * HZ; /* should be greater than |
492 | servers oplock break timeout (about 43 seconds) */ | 523 | servers oplock break timeout (about 43 seconds) */ |
493 | else | 524 | else if (long_op == CIFS_ASYNC_OP) |
494 | timeout = 15 * HZ; | 525 | goto out; |
526 | else if (long_op == CIFS_BLOCKING_OP) | ||
527 | timeout = 0x7FFFFFFF; /* large, but not so large as to wrap */ | ||
528 | else { | ||
529 | cERROR(1, ("unknown timeout flag %d", long_op)); | ||
530 | rc = -EIO; | ||
531 | goto out; | ||
532 | } | ||
495 | 533 | ||
496 | /* wait for 15 seconds or until woken up due to response arriving or | 534 | /* wait for 15 seconds or until woken up due to response arriving or |
497 | due to last connection to this server being unmounted */ | 535 | due to last connection to this server being unmounted */ |
@@ -566,7 +604,8 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, | |||
566 | } | 604 | } |
567 | 605 | ||
568 | /* BB special case reconnect tid and uid here? */ | 606 | /* BB special case reconnect tid and uid here? */ |
569 | rc = map_smb_to_linux_error(midQ->resp_buf, logError); | 607 | rc = map_smb_to_linux_error(midQ->resp_buf, |
608 | flags & CIFS_LOG_ERROR); | ||
570 | 609 | ||
571 | /* convert ByteCount if necessary */ | 610 | /* convert ByteCount if necessary */ |
572 | if (receive_len >= sizeof(struct smb_hdr) - 4 | 611 | if (receive_len >= sizeof(struct smb_hdr) - 4 |
@@ -574,8 +613,10 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, | |||
574 | (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ ) | 613 | (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ ) |
575 | BCC(midQ->resp_buf) = | 614 | BCC(midQ->resp_buf) = |
576 | le16_to_cpu(BCC_LE(midQ->resp_buf)); | 615 | le16_to_cpu(BCC_LE(midQ->resp_buf)); |
577 | midQ->resp_buf = NULL; /* mark it so will not be freed | 616 | if ((flags & CIFS_NO_RESP) == 0) |
578 | by DeleteMidQEntry */ | 617 | midQ->resp_buf = NULL; /* mark it so buf will |
618 | not be freed by | ||
619 | DeleteMidQEntry */ | ||
579 | } else { | 620 | } else { |
580 | rc = -EIO; | 621 | rc = -EIO; |
581 | cFYI(1, ("Bad MID state?")); | 622 | cFYI(1, ("Bad MID state?")); |
@@ -663,17 +704,25 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, | |||
663 | if (rc < 0) | 704 | if (rc < 0) |
664 | goto out; | 705 | goto out; |
665 | 706 | ||
666 | if (long_op == -1) | 707 | if (long_op == CIFS_STD_OP) |
708 | timeout = 15 * HZ; | ||
709 | /* wait for 15 seconds or until woken up due to response arriving or | ||
710 | due to last connection to this server being unmounted */ | ||
711 | else if (long_op == CIFS_ASYNC_OP) | ||
667 | goto out; | 712 | goto out; |
668 | else if (long_op == 2) /* writes past end of file can take loong time */ | 713 | else if (long_op == CIFS_VLONG_OP) /* writes past EOF can be slow */ |
669 | timeout = 180 * HZ; | 714 | timeout = 180 * HZ; |
670 | else if (long_op == 1) | 715 | else if (long_op == CIFS_LONG_OP) |
671 | timeout = 45 * HZ; /* should be greater than | 716 | timeout = 45 * HZ; /* should be greater than |
672 | servers oplock break timeout (about 43 seconds) */ | 717 | servers oplock break timeout (about 43 seconds) */ |
673 | else | 718 | else if (long_op == CIFS_BLOCKING_OP) |
674 | timeout = 15 * HZ; | 719 | timeout = 0x7FFFFFFF; /* large but no so large as to wrap */ |
675 | /* wait for 15 seconds or until woken up due to response arriving or | 720 | else { |
676 | due to last connection to this server being unmounted */ | 721 | cERROR(1, ("unknown timeout flag %d", long_op)); |
722 | rc = -EIO; | ||
723 | goto out; | ||
724 | } | ||
725 | |||
677 | if (signal_pending(current)) { | 726 | if (signal_pending(current)) { |
678 | /* if signal pending do not hold up user for full smb timeout | 727 | /* if signal pending do not hold up user for full smb timeout |
679 | but we still give response a chance to complete */ | 728 | but we still give response a chance to complete */ |
@@ -812,7 +861,7 @@ send_lock_cancel(const unsigned int xid, struct cifsTconInfo *tcon, | |||
812 | pSMB->hdr.Mid = GetNextMid(ses->server); | 861 | pSMB->hdr.Mid = GetNextMid(ses->server); |
813 | 862 | ||
814 | return SendReceive(xid, ses, in_buf, out_buf, | 863 | return SendReceive(xid, ses, in_buf, out_buf, |
815 | &bytes_returned, 0); | 864 | &bytes_returned, CIFS_STD_OP); |
816 | } | 865 | } |
817 | 866 | ||
818 | int | 867 | int |
@@ -844,7 +893,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, | |||
844 | to the same server. We may make this configurable later or | 893 | to the same server. We may make this configurable later or |
845 | use ses->maxReq */ | 894 | use ses->maxReq */ |
846 | 895 | ||
847 | rc = wait_for_free_request(ses, 3); | 896 | rc = wait_for_free_request(ses, CIFS_BLOCKING_OP); |
848 | if (rc) | 897 | if (rc) |
849 | return rc; | 898 | return rc; |
850 | 899 | ||
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index bd26e4cbb994..e8b7c3a98a54 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c | |||
@@ -1954,6 +1954,12 @@ ULONG_IOCTL(TIOCSCTTY) | |||
1954 | COMPATIBLE_IOCTL(TIOCGPTN) | 1954 | COMPATIBLE_IOCTL(TIOCGPTN) |
1955 | COMPATIBLE_IOCTL(TIOCSPTLCK) | 1955 | COMPATIBLE_IOCTL(TIOCSPTLCK) |
1956 | COMPATIBLE_IOCTL(TIOCSERGETLSR) | 1956 | COMPATIBLE_IOCTL(TIOCSERGETLSR) |
1957 | #ifdef TCGETS2 | ||
1958 | COMPATIBLE_IOCTL(TCGETS2) | ||
1959 | COMPATIBLE_IOCTL(TCSETS2) | ||
1960 | COMPATIBLE_IOCTL(TCSETSW2) | ||
1961 | COMPATIBLE_IOCTL(TCSETSF2) | ||
1962 | #endif | ||
1957 | /* Little f */ | 1963 | /* Little f */ |
1958 | COMPATIBLE_IOCTL(FIOCLEX) | 1964 | COMPATIBLE_IOCTL(FIOCLEX) |
1959 | COMPATIBLE_IOCTL(FIONCLEX) | 1965 | COMPATIBLE_IOCTL(FIONCLEX) |
@@ -1780,6 +1780,12 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) | |||
1780 | but keep the previous behaviour for now. */ | 1780 | but keep the previous behaviour for now. */ |
1781 | if (!ispipe && !S_ISREG(inode->i_mode)) | 1781 | if (!ispipe && !S_ISREG(inode->i_mode)) |
1782 | goto close_fail; | 1782 | goto close_fail; |
1783 | /* | ||
1784 | * Dont allow local users get cute and trick others to coredump | ||
1785 | * into their pre-created files: | ||
1786 | */ | ||
1787 | if (inode->i_uid != current->fsuid) | ||
1788 | goto close_fail; | ||
1783 | if (!file->f_op) | 1789 | if (!file->f_op) |
1784 | goto close_fail; | 1790 | goto close_fail; |
1785 | if (!file->f_op->write) | 1791 | if (!file->f_op->write) |
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h index 7730388c4931..c87ae29c19cb 100644 --- a/fs/ext2/ext2.h +++ b/fs/ext2/ext2.h | |||
@@ -178,3 +178,10 @@ extern const struct inode_operations ext2_special_inode_operations; | |||
178 | /* symlink.c */ | 178 | /* symlink.c */ |
179 | extern const struct inode_operations ext2_fast_symlink_inode_operations; | 179 | extern const struct inode_operations ext2_fast_symlink_inode_operations; |
180 | extern const struct inode_operations ext2_symlink_inode_operations; | 180 | extern const struct inode_operations ext2_symlink_inode_operations; |
181 | |||
182 | static inline ext2_fsblk_t | ||
183 | ext2_group_first_block_no(struct super_block *sb, unsigned long group_no) | ||
184 | { | ||
185 | return group_no * (ext2_fsblk_t)EXT2_BLOCKS_PER_GROUP(sb) + | ||
186 | le32_to_cpu(EXT2_SB(sb)->s_es->s_first_data_block); | ||
187 | } | ||
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 3763757f9fe7..80d2f5292cf9 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -132,6 +132,21 @@ static void fuse_lookup_init(struct fuse_req *req, struct inode *dir, | |||
132 | req->out.args[0].value = outarg; | 132 | req->out.args[0].value = outarg; |
133 | } | 133 | } |
134 | 134 | ||
135 | static u64 fuse_get_attr_version(struct fuse_conn *fc) | ||
136 | { | ||
137 | u64 curr_version; | ||
138 | |||
139 | /* | ||
140 | * The spin lock isn't actually needed on 64bit archs, but we | ||
141 | * don't yet care too much about such optimizations. | ||
142 | */ | ||
143 | spin_lock(&fc->lock); | ||
144 | curr_version = fc->attr_version; | ||
145 | spin_unlock(&fc->lock); | ||
146 | |||
147 | return curr_version; | ||
148 | } | ||
149 | |||
135 | /* | 150 | /* |
136 | * Check whether the dentry is still valid | 151 | * Check whether the dentry is still valid |
137 | * | 152 | * |
@@ -171,9 +186,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd) | |||
171 | return 0; | 186 | return 0; |
172 | } | 187 | } |
173 | 188 | ||
174 | spin_lock(&fc->lock); | 189 | attr_version = fuse_get_attr_version(fc); |
175 | attr_version = fc->attr_version; | ||
176 | spin_unlock(&fc->lock); | ||
177 | 190 | ||
178 | parent = dget_parent(entry); | 191 | parent = dget_parent(entry); |
179 | fuse_lookup_init(req, parent->d_inode, entry, &outarg); | 192 | fuse_lookup_init(req, parent->d_inode, entry, &outarg); |
@@ -264,9 +277,7 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, | |||
264 | return ERR_PTR(PTR_ERR(forget_req)); | 277 | return ERR_PTR(PTR_ERR(forget_req)); |
265 | } | 278 | } |
266 | 279 | ||
267 | spin_lock(&fc->lock); | 280 | attr_version = fuse_get_attr_version(fc); |
268 | attr_version = fc->attr_version; | ||
269 | spin_unlock(&fc->lock); | ||
270 | 281 | ||
271 | fuse_lookup_init(req, dir, entry, &outarg); | 282 | fuse_lookup_init(req, dir, entry, &outarg); |
272 | request_send(fc, req); | 283 | request_send(fc, req); |
@@ -646,6 +657,9 @@ static int fuse_rename(struct inode *olddir, struct dentry *oldent, | |||
646 | err = req->out.h.error; | 657 | err = req->out.h.error; |
647 | fuse_put_request(fc, req); | 658 | fuse_put_request(fc, req); |
648 | if (!err) { | 659 | if (!err) { |
660 | /* ctime changes */ | ||
661 | fuse_invalidate_attr(oldent->d_inode); | ||
662 | |||
649 | fuse_invalidate_attr(olddir); | 663 | fuse_invalidate_attr(olddir); |
650 | if (olddir != newdir) | 664 | if (olddir != newdir) |
651 | fuse_invalidate_attr(newdir); | 665 | fuse_invalidate_attr(newdir); |
@@ -733,9 +747,7 @@ static int fuse_do_getattr(struct inode *inode, struct kstat *stat, | |||
733 | if (IS_ERR(req)) | 747 | if (IS_ERR(req)) |
734 | return PTR_ERR(req); | 748 | return PTR_ERR(req); |
735 | 749 | ||
736 | spin_lock(&fc->lock); | 750 | attr_version = fuse_get_attr_version(fc); |
737 | attr_version = fc->attr_version; | ||
738 | spin_unlock(&fc->lock); | ||
739 | 751 | ||
740 | memset(&inarg, 0, sizeof(inarg)); | 752 | memset(&inarg, 0, sizeof(inarg)); |
741 | memset(&outarg, 0, sizeof(outarg)); | 753 | memset(&outarg, 0, sizeof(outarg)); |
@@ -775,6 +787,31 @@ static int fuse_do_getattr(struct inode *inode, struct kstat *stat, | |||
775 | return err; | 787 | return err; |
776 | } | 788 | } |
777 | 789 | ||
790 | int fuse_update_attributes(struct inode *inode, struct kstat *stat, | ||
791 | struct file *file, bool *refreshed) | ||
792 | { | ||
793 | struct fuse_inode *fi = get_fuse_inode(inode); | ||
794 | int err; | ||
795 | bool r; | ||
796 | |||
797 | if (fi->i_time < get_jiffies_64()) { | ||
798 | r = true; | ||
799 | err = fuse_do_getattr(inode, stat, file); | ||
800 | } else { | ||
801 | r = false; | ||
802 | err = 0; | ||
803 | if (stat) { | ||
804 | generic_fillattr(inode, stat); | ||
805 | stat->mode = fi->orig_i_mode; | ||
806 | } | ||
807 | } | ||
808 | |||
809 | if (refreshed != NULL) | ||
810 | *refreshed = r; | ||
811 | |||
812 | return err; | ||
813 | } | ||
814 | |||
778 | /* | 815 | /* |
779 | * Calling into a user-controlled filesystem gives the filesystem | 816 | * Calling into a user-controlled filesystem gives the filesystem |
780 | * daemon ptrace-like capabilities over the requester process. This | 817 | * daemon ptrace-like capabilities over the requester process. This |
@@ -862,14 +899,9 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd) | |||
862 | */ | 899 | */ |
863 | if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) || | 900 | if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) || |
864 | ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) { | 901 | ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) { |
865 | struct fuse_inode *fi = get_fuse_inode(inode); | 902 | err = fuse_update_attributes(inode, NULL, NULL, &refreshed); |
866 | if (fi->i_time < get_jiffies_64()) { | 903 | if (err) |
867 | err = fuse_do_getattr(inode, NULL, NULL); | 904 | return err; |
868 | if (err) | ||
869 | return err; | ||
870 | |||
871 | refreshed = true; | ||
872 | } | ||
873 | } | 905 | } |
874 | 906 | ||
875 | if (fc->flags & FUSE_DEFAULT_PERMISSIONS) { | 907 | if (fc->flags & FUSE_DEFAULT_PERMISSIONS) { |
@@ -935,7 +967,6 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir) | |||
935 | struct page *page; | 967 | struct page *page; |
936 | struct inode *inode = file->f_path.dentry->d_inode; | 968 | struct inode *inode = file->f_path.dentry->d_inode; |
937 | struct fuse_conn *fc = get_fuse_conn(inode); | 969 | struct fuse_conn *fc = get_fuse_conn(inode); |
938 | struct fuse_file *ff = file->private_data; | ||
939 | struct fuse_req *req; | 970 | struct fuse_req *req; |
940 | 971 | ||
941 | if (is_bad_inode(inode)) | 972 | if (is_bad_inode(inode)) |
@@ -952,7 +983,7 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir) | |||
952 | } | 983 | } |
953 | req->num_pages = 1; | 984 | req->num_pages = 1; |
954 | req->pages[0] = page; | 985 | req->pages[0] = page; |
955 | fuse_read_fill(req, ff, inode, file->f_pos, PAGE_SIZE, FUSE_READDIR); | 986 | fuse_read_fill(req, file, inode, file->f_pos, PAGE_SIZE, FUSE_READDIR); |
956 | request_send(fc, req); | 987 | request_send(fc, req); |
957 | nbytes = req->out.args[0].size; | 988 | nbytes = req->out.args[0].size; |
958 | err = req->out.h.error; | 989 | err = req->out.h.error; |
@@ -1173,22 +1204,12 @@ static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry, | |||
1173 | struct kstat *stat) | 1204 | struct kstat *stat) |
1174 | { | 1205 | { |
1175 | struct inode *inode = entry->d_inode; | 1206 | struct inode *inode = entry->d_inode; |
1176 | struct fuse_inode *fi = get_fuse_inode(inode); | ||
1177 | struct fuse_conn *fc = get_fuse_conn(inode); | 1207 | struct fuse_conn *fc = get_fuse_conn(inode); |
1178 | int err; | ||
1179 | 1208 | ||
1180 | if (!fuse_allow_task(fc, current)) | 1209 | if (!fuse_allow_task(fc, current)) |
1181 | return -EACCES; | 1210 | return -EACCES; |
1182 | 1211 | ||
1183 | if (fi->i_time < get_jiffies_64()) | 1212 | return fuse_update_attributes(inode, stat, NULL, NULL); |
1184 | err = fuse_do_getattr(inode, stat, NULL); | ||
1185 | else { | ||
1186 | err = 0; | ||
1187 | generic_fillattr(inode, stat); | ||
1188 | stat->mode = fi->orig_i_mode; | ||
1189 | } | ||
1190 | |||
1191 | return err; | ||
1192 | } | 1213 | } |
1193 | 1214 | ||
1194 | static int fuse_setxattr(struct dentry *entry, const char *name, | 1215 | static int fuse_setxattr(struct dentry *entry, const char *name, |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 535b37399009..bb05d227cf30 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -289,14 +289,16 @@ static int fuse_fsync(struct file *file, struct dentry *de, int datasync) | |||
289 | return fuse_fsync_common(file, de, datasync, 0); | 289 | return fuse_fsync_common(file, de, datasync, 0); |
290 | } | 290 | } |
291 | 291 | ||
292 | void fuse_read_fill(struct fuse_req *req, struct fuse_file *ff, | 292 | void fuse_read_fill(struct fuse_req *req, struct file *file, |
293 | struct inode *inode, loff_t pos, size_t count, int opcode) | 293 | struct inode *inode, loff_t pos, size_t count, int opcode) |
294 | { | 294 | { |
295 | struct fuse_read_in *inarg = &req->misc.read_in; | 295 | struct fuse_read_in *inarg = &req->misc.read_in; |
296 | struct fuse_file *ff = file->private_data; | ||
296 | 297 | ||
297 | inarg->fh = ff->fh; | 298 | inarg->fh = ff->fh; |
298 | inarg->offset = pos; | 299 | inarg->offset = pos; |
299 | inarg->size = count; | 300 | inarg->size = count; |
301 | inarg->flags = file->f_flags; | ||
300 | req->in.h.opcode = opcode; | 302 | req->in.h.opcode = opcode; |
301 | req->in.h.nodeid = get_node_id(inode); | 303 | req->in.h.nodeid = get_node_id(inode); |
302 | req->in.numargs = 1; | 304 | req->in.numargs = 1; |
@@ -313,9 +315,8 @@ static size_t fuse_send_read(struct fuse_req *req, struct file *file, | |||
313 | fl_owner_t owner) | 315 | fl_owner_t owner) |
314 | { | 316 | { |
315 | struct fuse_conn *fc = get_fuse_conn(inode); | 317 | struct fuse_conn *fc = get_fuse_conn(inode); |
316 | struct fuse_file *ff = file->private_data; | ||
317 | 318 | ||
318 | fuse_read_fill(req, ff, inode, pos, count, FUSE_READ); | 319 | fuse_read_fill(req, file, inode, pos, count, FUSE_READ); |
319 | if (owner != NULL) { | 320 | if (owner != NULL) { |
320 | struct fuse_read_in *inarg = &req->misc.read_in; | 321 | struct fuse_read_in *inarg = &req->misc.read_in; |
321 | 322 | ||
@@ -376,15 +377,16 @@ static void fuse_readpages_end(struct fuse_conn *fc, struct fuse_req *req) | |||
376 | fuse_put_request(fc, req); | 377 | fuse_put_request(fc, req); |
377 | } | 378 | } |
378 | 379 | ||
379 | static void fuse_send_readpages(struct fuse_req *req, struct fuse_file *ff, | 380 | static void fuse_send_readpages(struct fuse_req *req, struct file *file, |
380 | struct inode *inode) | 381 | struct inode *inode) |
381 | { | 382 | { |
382 | struct fuse_conn *fc = get_fuse_conn(inode); | 383 | struct fuse_conn *fc = get_fuse_conn(inode); |
383 | loff_t pos = page_offset(req->pages[0]); | 384 | loff_t pos = page_offset(req->pages[0]); |
384 | size_t count = req->num_pages << PAGE_CACHE_SHIFT; | 385 | size_t count = req->num_pages << PAGE_CACHE_SHIFT; |
385 | req->out.page_zeroing = 1; | 386 | req->out.page_zeroing = 1; |
386 | fuse_read_fill(req, ff, inode, pos, count, FUSE_READ); | 387 | fuse_read_fill(req, file, inode, pos, count, FUSE_READ); |
387 | if (fc->async_read) { | 388 | if (fc->async_read) { |
389 | struct fuse_file *ff = file->private_data; | ||
388 | req->ff = fuse_file_get(ff); | 390 | req->ff = fuse_file_get(ff); |
389 | req->end = fuse_readpages_end; | 391 | req->end = fuse_readpages_end; |
390 | request_send_background(fc, req); | 392 | request_send_background(fc, req); |
@@ -396,7 +398,7 @@ static void fuse_send_readpages(struct fuse_req *req, struct fuse_file *ff, | |||
396 | 398 | ||
397 | struct fuse_fill_data { | 399 | struct fuse_fill_data { |
398 | struct fuse_req *req; | 400 | struct fuse_req *req; |
399 | struct fuse_file *ff; | 401 | struct file *file; |
400 | struct inode *inode; | 402 | struct inode *inode; |
401 | }; | 403 | }; |
402 | 404 | ||
@@ -411,7 +413,7 @@ static int fuse_readpages_fill(void *_data, struct page *page) | |||
411 | (req->num_pages == FUSE_MAX_PAGES_PER_REQ || | 413 | (req->num_pages == FUSE_MAX_PAGES_PER_REQ || |
412 | (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read || | 414 | (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read || |
413 | req->pages[req->num_pages - 1]->index + 1 != page->index)) { | 415 | req->pages[req->num_pages - 1]->index + 1 != page->index)) { |
414 | fuse_send_readpages(req, data->ff, inode); | 416 | fuse_send_readpages(req, data->file, inode); |
415 | data->req = req = fuse_get_req(fc); | 417 | data->req = req = fuse_get_req(fc); |
416 | if (IS_ERR(req)) { | 418 | if (IS_ERR(req)) { |
417 | unlock_page(page); | 419 | unlock_page(page); |
@@ -435,7 +437,7 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, | |||
435 | if (is_bad_inode(inode)) | 437 | if (is_bad_inode(inode)) |
436 | goto out; | 438 | goto out; |
437 | 439 | ||
438 | data.ff = file->private_data; | 440 | data.file = file; |
439 | data.inode = inode; | 441 | data.inode = inode; |
440 | data.req = fuse_get_req(fc); | 442 | data.req = fuse_get_req(fc); |
441 | err = PTR_ERR(data.req); | 443 | err = PTR_ERR(data.req); |
@@ -445,7 +447,7 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, | |||
445 | err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data); | 447 | err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data); |
446 | if (!err) { | 448 | if (!err) { |
447 | if (data.req->num_pages) | 449 | if (data.req->num_pages) |
448 | fuse_send_readpages(data.req, data.ff, inode); | 450 | fuse_send_readpages(data.req, file, inode); |
449 | else | 451 | else |
450 | fuse_put_request(fc, data.req); | 452 | fuse_put_request(fc, data.req); |
451 | } | 453 | } |
@@ -453,11 +455,31 @@ out: | |||
453 | return err; | 455 | return err; |
454 | } | 456 | } |
455 | 457 | ||
456 | static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff, | 458 | static ssize_t fuse_file_aio_read(struct kiocb *iocb, const struct iovec *iov, |
459 | unsigned long nr_segs, loff_t pos) | ||
460 | { | ||
461 | struct inode *inode = iocb->ki_filp->f_mapping->host; | ||
462 | |||
463 | if (pos + iov_length(iov, nr_segs) > i_size_read(inode)) { | ||
464 | int err; | ||
465 | /* | ||
466 | * If trying to read past EOF, make sure the i_size | ||
467 | * attribute is up-to-date. | ||
468 | */ | ||
469 | err = fuse_update_attributes(inode, NULL, iocb->ki_filp, NULL); | ||
470 | if (err) | ||
471 | return err; | ||
472 | } | ||
473 | |||
474 | return generic_file_aio_read(iocb, iov, nr_segs, pos); | ||
475 | } | ||
476 | |||
477 | static void fuse_write_fill(struct fuse_req *req, struct file *file, | ||
457 | struct inode *inode, loff_t pos, size_t count, | 478 | struct inode *inode, loff_t pos, size_t count, |
458 | int writepage) | 479 | int writepage) |
459 | { | 480 | { |
460 | struct fuse_conn *fc = get_fuse_conn(inode); | 481 | struct fuse_conn *fc = get_fuse_conn(inode); |
482 | struct fuse_file *ff = file->private_data; | ||
461 | struct fuse_write_in *inarg = &req->misc.write.in; | 483 | struct fuse_write_in *inarg = &req->misc.write.in; |
462 | struct fuse_write_out *outarg = &req->misc.write.out; | 484 | struct fuse_write_out *outarg = &req->misc.write.out; |
463 | 485 | ||
@@ -466,6 +488,7 @@ static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff, | |||
466 | inarg->offset = pos; | 488 | inarg->offset = pos; |
467 | inarg->size = count; | 489 | inarg->size = count; |
468 | inarg->write_flags = writepage ? FUSE_WRITE_CACHE : 0; | 490 | inarg->write_flags = writepage ? FUSE_WRITE_CACHE : 0; |
491 | inarg->flags = file->f_flags; | ||
469 | req->in.h.opcode = FUSE_WRITE; | 492 | req->in.h.opcode = FUSE_WRITE; |
470 | req->in.h.nodeid = get_node_id(inode); | 493 | req->in.h.nodeid = get_node_id(inode); |
471 | req->in.argpages = 1; | 494 | req->in.argpages = 1; |
@@ -486,7 +509,7 @@ static size_t fuse_send_write(struct fuse_req *req, struct file *file, | |||
486 | fl_owner_t owner) | 509 | fl_owner_t owner) |
487 | { | 510 | { |
488 | struct fuse_conn *fc = get_fuse_conn(inode); | 511 | struct fuse_conn *fc = get_fuse_conn(inode); |
489 | fuse_write_fill(req, file->private_data, inode, pos, count, 0); | 512 | fuse_write_fill(req, file, inode, pos, count, 0); |
490 | if (owner != NULL) { | 513 | if (owner != NULL) { |
491 | struct fuse_write_in *inarg = &req->misc.write.in; | 514 | struct fuse_write_in *inarg = &req->misc.write.in; |
492 | inarg->write_flags |= FUSE_WRITE_LOCKOWNER; | 515 | inarg->write_flags |= FUSE_WRITE_LOCKOWNER; |
@@ -887,7 +910,7 @@ static sector_t fuse_bmap(struct address_space *mapping, sector_t block) | |||
887 | static const struct file_operations fuse_file_operations = { | 910 | static const struct file_operations fuse_file_operations = { |
888 | .llseek = generic_file_llseek, | 911 | .llseek = generic_file_llseek, |
889 | .read = do_sync_read, | 912 | .read = do_sync_read, |
890 | .aio_read = generic_file_aio_read, | 913 | .aio_read = fuse_file_aio_read, |
891 | .write = do_sync_write, | 914 | .write = do_sync_write, |
892 | .aio_write = generic_file_aio_write, | 915 | .aio_write = generic_file_aio_write, |
893 | .mmap = fuse_file_mmap, | 916 | .mmap = fuse_file_mmap, |
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 6c5461de1a5f..3ab8a3048e8b 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
@@ -447,7 +447,7 @@ void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req, | |||
447 | /** | 447 | /** |
448 | * Initialize READ or READDIR request | 448 | * Initialize READ or READDIR request |
449 | */ | 449 | */ |
450 | void fuse_read_fill(struct fuse_req *req, struct fuse_file *ff, | 450 | void fuse_read_fill(struct fuse_req *req, struct file *file, |
451 | struct inode *inode, loff_t pos, size_t count, int opcode); | 451 | struct inode *inode, loff_t pos, size_t count, int opcode); |
452 | 452 | ||
453 | /** | 453 | /** |
@@ -593,3 +593,6 @@ int fuse_valid_type(int m); | |||
593 | int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task); | 593 | int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task); |
594 | 594 | ||
595 | u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id); | 595 | u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id); |
596 | |||
597 | int fuse_update_attributes(struct inode *inode, struct kstat *stat, | ||
598 | struct file *file, bool *refreshed); | ||
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 9a68d6970845..84f9f7dfdf5b 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
@@ -56,6 +56,7 @@ static struct inode *fuse_alloc_inode(struct super_block *sb) | |||
56 | fi->i_time = 0; | 56 | fi->i_time = 0; |
57 | fi->nodeid = 0; | 57 | fi->nodeid = 0; |
58 | fi->nlookup = 0; | 58 | fi->nlookup = 0; |
59 | fi->attr_version = 0; | ||
59 | INIT_LIST_HEAD(&fi->write_files); | 60 | INIT_LIST_HEAD(&fi->write_files); |
60 | fi->forget_req = fuse_request_alloc(); | 61 | fi->forget_req = fuse_request_alloc(); |
61 | if (!fi->forget_req) { | 62 | if (!fi->forget_req) { |
@@ -562,8 +563,7 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req) | |||
562 | arg->major = FUSE_KERNEL_VERSION; | 563 | arg->major = FUSE_KERNEL_VERSION; |
563 | arg->minor = FUSE_KERNEL_MINOR_VERSION; | 564 | arg->minor = FUSE_KERNEL_MINOR_VERSION; |
564 | arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE; | 565 | arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE; |
565 | arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_FILE_OPS | | 566 | arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC; |
566 | FUSE_ATOMIC_O_TRUNC; | ||
567 | req->in.h.opcode = FUSE_INIT; | 567 | req->in.h.opcode = FUSE_INIT; |
568 | req->in.numargs = 1; | 568 | req->in.numargs = 1; |
569 | req->in.args[0].size = sizeof(*arg); | 569 | req->in.args[0].size = sizeof(*arg); |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 35334539d947..f697b5c74b7c 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include "nfs4_fs.h" | 38 | #include "nfs4_fs.h" |
39 | #include "delegation.h" | 39 | #include "delegation.h" |
40 | #include "iostat.h" | 40 | #include "iostat.h" |
41 | #include "internal.h" | ||
41 | 42 | ||
42 | /* #define NFS_DEBUG_VERBOSE 1 */ | 43 | /* #define NFS_DEBUG_VERBOSE 1 */ |
43 | 44 | ||
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index afcab007a22b..5e8d82f6666b 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -263,17 +263,19 @@ static const struct rpc_call_ops nfs_read_direct_ops = { | |||
263 | * handled automatically by nfs_direct_read_result(). Otherwise, if | 263 | * handled automatically by nfs_direct_read_result(). Otherwise, if |
264 | * no requests have been sent, just return an error. | 264 | * no requests have been sent, just return an error. |
265 | */ | 265 | */ |
266 | static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq, unsigned long user_addr, size_t count, loff_t pos) | 266 | static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq, |
267 | const struct iovec *iov, | ||
268 | loff_t pos) | ||
267 | { | 269 | { |
268 | struct nfs_open_context *ctx = dreq->ctx; | 270 | struct nfs_open_context *ctx = dreq->ctx; |
269 | struct inode *inode = ctx->path.dentry->d_inode; | 271 | struct inode *inode = ctx->path.dentry->d_inode; |
272 | unsigned long user_addr = (unsigned long)iov->iov_base; | ||
273 | size_t count = iov->iov_len; | ||
270 | size_t rsize = NFS_SERVER(inode)->rsize; | 274 | size_t rsize = NFS_SERVER(inode)->rsize; |
271 | unsigned int pgbase; | 275 | unsigned int pgbase; |
272 | int result; | 276 | int result; |
273 | ssize_t started = 0; | 277 | ssize_t started = 0; |
274 | 278 | ||
275 | get_dreq(dreq); | ||
276 | |||
277 | do { | 279 | do { |
278 | struct nfs_read_data *data; | 280 | struct nfs_read_data *data; |
279 | size_t bytes; | 281 | size_t bytes; |
@@ -347,15 +349,46 @@ static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq, unsigned lo | |||
347 | count -= bytes; | 349 | count -= bytes; |
348 | } while (count != 0); | 350 | } while (count != 0); |
349 | 351 | ||
352 | if (started) | ||
353 | return started; | ||
354 | return result < 0 ? (ssize_t) result : -EFAULT; | ||
355 | } | ||
356 | |||
357 | static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq, | ||
358 | const struct iovec *iov, | ||
359 | unsigned long nr_segs, | ||
360 | loff_t pos) | ||
361 | { | ||
362 | ssize_t result = -EINVAL; | ||
363 | size_t requested_bytes = 0; | ||
364 | unsigned long seg; | ||
365 | |||
366 | get_dreq(dreq); | ||
367 | |||
368 | for (seg = 0; seg < nr_segs; seg++) { | ||
369 | const struct iovec *vec = &iov[seg]; | ||
370 | result = nfs_direct_read_schedule_segment(dreq, vec, pos); | ||
371 | if (result < 0) | ||
372 | break; | ||
373 | requested_bytes += result; | ||
374 | if ((size_t)result < vec->iov_len) | ||
375 | break; | ||
376 | pos += vec->iov_len; | ||
377 | } | ||
378 | |||
350 | if (put_dreq(dreq)) | 379 | if (put_dreq(dreq)) |
351 | nfs_direct_complete(dreq); | 380 | nfs_direct_complete(dreq); |
352 | 381 | ||
353 | if (started) | 382 | if (requested_bytes != 0) |
354 | return 0; | 383 | return 0; |
355 | return result < 0 ? (ssize_t) result : -EFAULT; | 384 | |
385 | if (result < 0) | ||
386 | return result; | ||
387 | return -EIO; | ||
356 | } | 388 | } |
357 | 389 | ||
358 | static ssize_t nfs_direct_read(struct kiocb *iocb, unsigned long user_addr, size_t count, loff_t pos) | 390 | static ssize_t nfs_direct_read(struct kiocb *iocb, const struct iovec *iov, |
391 | unsigned long nr_segs, loff_t pos) | ||
359 | { | 392 | { |
360 | ssize_t result = 0; | 393 | ssize_t result = 0; |
361 | sigset_t oldset; | 394 | sigset_t oldset; |
@@ -372,9 +405,8 @@ static ssize_t nfs_direct_read(struct kiocb *iocb, unsigned long user_addr, size | |||
372 | if (!is_sync_kiocb(iocb)) | 405 | if (!is_sync_kiocb(iocb)) |
373 | dreq->iocb = iocb; | 406 | dreq->iocb = iocb; |
374 | 407 | ||
375 | nfs_add_stats(inode, NFSIOS_DIRECTREADBYTES, count); | ||
376 | rpc_clnt_sigmask(clnt, &oldset); | 408 | rpc_clnt_sigmask(clnt, &oldset); |
377 | result = nfs_direct_read_schedule(dreq, user_addr, count, pos); | 409 | result = nfs_direct_read_schedule_iovec(dreq, iov, nr_segs, pos); |
378 | if (!result) | 410 | if (!result) |
379 | result = nfs_direct_wait(dreq); | 411 | result = nfs_direct_wait(dreq); |
380 | rpc_clnt_sigunmask(clnt, &oldset); | 412 | rpc_clnt_sigunmask(clnt, &oldset); |
@@ -601,17 +633,19 @@ static const struct rpc_call_ops nfs_write_direct_ops = { | |||
601 | * handled automatically by nfs_direct_write_result(). Otherwise, if | 633 | * handled automatically by nfs_direct_write_result(). Otherwise, if |
602 | * no requests have been sent, just return an error. | 634 | * no requests have been sent, just return an error. |
603 | */ | 635 | */ |
604 | static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq, unsigned long user_addr, size_t count, loff_t pos, int sync) | 636 | static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq, |
637 | const struct iovec *iov, | ||
638 | loff_t pos, int sync) | ||
605 | { | 639 | { |
606 | struct nfs_open_context *ctx = dreq->ctx; | 640 | struct nfs_open_context *ctx = dreq->ctx; |
607 | struct inode *inode = ctx->path.dentry->d_inode; | 641 | struct inode *inode = ctx->path.dentry->d_inode; |
642 | unsigned long user_addr = (unsigned long)iov->iov_base; | ||
643 | size_t count = iov->iov_len; | ||
608 | size_t wsize = NFS_SERVER(inode)->wsize; | 644 | size_t wsize = NFS_SERVER(inode)->wsize; |
609 | unsigned int pgbase; | 645 | unsigned int pgbase; |
610 | int result; | 646 | int result; |
611 | ssize_t started = 0; | 647 | ssize_t started = 0; |
612 | 648 | ||
613 | get_dreq(dreq); | ||
614 | |||
615 | do { | 649 | do { |
616 | struct nfs_write_data *data; | 650 | struct nfs_write_data *data; |
617 | size_t bytes; | 651 | size_t bytes; |
@@ -689,15 +723,48 @@ static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq, unsigned l | |||
689 | count -= bytes; | 723 | count -= bytes; |
690 | } while (count != 0); | 724 | } while (count != 0); |
691 | 725 | ||
726 | if (started) | ||
727 | return started; | ||
728 | return result < 0 ? (ssize_t) result : -EFAULT; | ||
729 | } | ||
730 | |||
731 | static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq, | ||
732 | const struct iovec *iov, | ||
733 | unsigned long nr_segs, | ||
734 | loff_t pos, int sync) | ||
735 | { | ||
736 | ssize_t result = 0; | ||
737 | size_t requested_bytes = 0; | ||
738 | unsigned long seg; | ||
739 | |||
740 | get_dreq(dreq); | ||
741 | |||
742 | for (seg = 0; seg < nr_segs; seg++) { | ||
743 | const struct iovec *vec = &iov[seg]; | ||
744 | result = nfs_direct_write_schedule_segment(dreq, vec, | ||
745 | pos, sync); | ||
746 | if (result < 0) | ||
747 | break; | ||
748 | requested_bytes += result; | ||
749 | if ((size_t)result < vec->iov_len) | ||
750 | break; | ||
751 | pos += vec->iov_len; | ||
752 | } | ||
753 | |||
692 | if (put_dreq(dreq)) | 754 | if (put_dreq(dreq)) |
693 | nfs_direct_write_complete(dreq, inode); | 755 | nfs_direct_write_complete(dreq, dreq->inode); |
694 | 756 | ||
695 | if (started) | 757 | if (requested_bytes != 0) |
696 | return 0; | 758 | return 0; |
697 | return result < 0 ? (ssize_t) result : -EFAULT; | 759 | |
760 | if (result < 0) | ||
761 | return result; | ||
762 | return -EIO; | ||
698 | } | 763 | } |
699 | 764 | ||
700 | static ssize_t nfs_direct_write(struct kiocb *iocb, unsigned long user_addr, size_t count, loff_t pos) | 765 | static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov, |
766 | unsigned long nr_segs, loff_t pos, | ||
767 | size_t count) | ||
701 | { | 768 | { |
702 | ssize_t result = 0; | 769 | ssize_t result = 0; |
703 | sigset_t oldset; | 770 | sigset_t oldset; |
@@ -720,10 +787,8 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, unsigned long user_addr, siz | |||
720 | if (!is_sync_kiocb(iocb)) | 787 | if (!is_sync_kiocb(iocb)) |
721 | dreq->iocb = iocb; | 788 | dreq->iocb = iocb; |
722 | 789 | ||
723 | nfs_add_stats(inode, NFSIOS_DIRECTWRITTENBYTES, count); | ||
724 | |||
725 | rpc_clnt_sigmask(clnt, &oldset); | 790 | rpc_clnt_sigmask(clnt, &oldset); |
726 | result = nfs_direct_write_schedule(dreq, user_addr, count, pos, sync); | 791 | result = nfs_direct_write_schedule_iovec(dreq, iov, nr_segs, pos, sync); |
727 | if (!result) | 792 | if (!result) |
728 | result = nfs_direct_wait(dreq); | 793 | result = nfs_direct_wait(dreq); |
729 | rpc_clnt_sigunmask(clnt, &oldset); | 794 | rpc_clnt_sigunmask(clnt, &oldset); |
@@ -759,21 +824,16 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov, | |||
759 | ssize_t retval = -EINVAL; | 824 | ssize_t retval = -EINVAL; |
760 | struct file *file = iocb->ki_filp; | 825 | struct file *file = iocb->ki_filp; |
761 | struct address_space *mapping = file->f_mapping; | 826 | struct address_space *mapping = file->f_mapping; |
762 | /* XXX: temporary */ | 827 | size_t count; |
763 | const char __user *buf = iov[0].iov_base; | 828 | |
764 | size_t count = iov[0].iov_len; | 829 | count = iov_length(iov, nr_segs); |
830 | nfs_add_stats(mapping->host, NFSIOS_DIRECTREADBYTES, count); | ||
765 | 831 | ||
766 | dprintk("nfs: direct read(%s/%s, %lu@%Ld)\n", | 832 | dprintk("nfs: direct read(%s/%s, %zd@%Ld)\n", |
767 | file->f_path.dentry->d_parent->d_name.name, | 833 | file->f_path.dentry->d_parent->d_name.name, |
768 | file->f_path.dentry->d_name.name, | 834 | file->f_path.dentry->d_name.name, |
769 | (unsigned long) count, (long long) pos); | 835 | count, (long long) pos); |
770 | |||
771 | if (nr_segs != 1) | ||
772 | goto out; | ||
773 | 836 | ||
774 | retval = -EFAULT; | ||
775 | if (!access_ok(VERIFY_WRITE, buf, count)) | ||
776 | goto out; | ||
777 | retval = 0; | 837 | retval = 0; |
778 | if (!count) | 838 | if (!count) |
779 | goto out; | 839 | goto out; |
@@ -782,7 +842,7 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov, | |||
782 | if (retval) | 842 | if (retval) |
783 | goto out; | 843 | goto out; |
784 | 844 | ||
785 | retval = nfs_direct_read(iocb, (unsigned long) buf, count, pos); | 845 | retval = nfs_direct_read(iocb, iov, nr_segs, pos); |
786 | if (retval > 0) | 846 | if (retval > 0) |
787 | iocb->ki_pos = pos + retval; | 847 | iocb->ki_pos = pos + retval; |
788 | 848 | ||
@@ -821,21 +881,21 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov, | |||
821 | ssize_t retval = -EINVAL; | 881 | ssize_t retval = -EINVAL; |
822 | struct file *file = iocb->ki_filp; | 882 | struct file *file = iocb->ki_filp; |
823 | struct address_space *mapping = file->f_mapping; | 883 | struct address_space *mapping = file->f_mapping; |
824 | /* XXX: temporary */ | 884 | size_t count; |
825 | const char __user *buf = iov[0].iov_base; | 885 | |
826 | size_t count = iov[0].iov_len; | 886 | count = iov_length(iov, nr_segs); |
887 | nfs_add_stats(mapping->host, NFSIOS_DIRECTWRITTENBYTES, count); | ||
827 | 888 | ||
828 | dprintk("nfs: direct write(%s/%s, %lu@%Ld)\n", | 889 | dfprintk(VFS, "nfs: direct write(%s/%s, %zd@%Ld)\n", |
829 | file->f_path.dentry->d_parent->d_name.name, | 890 | file->f_path.dentry->d_parent->d_name.name, |
830 | file->f_path.dentry->d_name.name, | 891 | file->f_path.dentry->d_name.name, |
831 | (unsigned long) count, (long long) pos); | 892 | count, (long long) pos); |
832 | |||
833 | if (nr_segs != 1) | ||
834 | goto out; | ||
835 | 893 | ||
836 | retval = generic_write_checks(file, &pos, &count, 0); | 894 | retval = generic_write_checks(file, &pos, &count, 0); |
837 | if (retval) | 895 | if (retval) |
838 | goto out; | 896 | goto out; |
897 | if (!count) | ||
898 | goto out; /* return 0 */ | ||
839 | 899 | ||
840 | retval = -EINVAL; | 900 | retval = -EINVAL; |
841 | if ((ssize_t) count < 0) | 901 | if ((ssize_t) count < 0) |
@@ -844,15 +904,11 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov, | |||
844 | if (!count) | 904 | if (!count) |
845 | goto out; | 905 | goto out; |
846 | 906 | ||
847 | retval = -EFAULT; | ||
848 | if (!access_ok(VERIFY_READ, buf, count)) | ||
849 | goto out; | ||
850 | |||
851 | retval = nfs_sync_mapping(mapping); | 907 | retval = nfs_sync_mapping(mapping); |
852 | if (retval) | 908 | if (retval) |
853 | goto out; | 909 | goto out; |
854 | 910 | ||
855 | retval = nfs_direct_write(iocb, (unsigned long) buf, count, pos); | 911 | retval = nfs_direct_write(iocb, iov, nr_segs, pos, count); |
856 | 912 | ||
857 | if (retval > 0) | 913 | if (retval > 0) |
858 | iocb->ki_pos = pos + retval; | 914 | iocb->ki_pos = pos + retval; |
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c index 522e5ad4d8ad..0ee43843f4ec 100644 --- a/fs/nfs/getroot.c +++ b/fs/nfs/getroot.c | |||
@@ -43,6 +43,25 @@ | |||
43 | #define NFSDBG_FACILITY NFSDBG_CLIENT | 43 | #define NFSDBG_FACILITY NFSDBG_CLIENT |
44 | 44 | ||
45 | /* | 45 | /* |
46 | * Set the superblock root dentry. | ||
47 | * Note that this function frees the inode in case of error. | ||
48 | */ | ||
49 | static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *inode) | ||
50 | { | ||
51 | /* The mntroot acts as the dummy root dentry for this superblock */ | ||
52 | if (sb->s_root == NULL) { | ||
53 | sb->s_root = d_alloc_root(inode); | ||
54 | if (sb->s_root == NULL) { | ||
55 | iput(inode); | ||
56 | return -ENOMEM; | ||
57 | } | ||
58 | /* Circumvent igrab(): we know the inode is not being freed */ | ||
59 | atomic_inc(&inode->i_count); | ||
60 | } | ||
61 | return 0; | ||
62 | } | ||
63 | |||
64 | /* | ||
46 | * get an NFS2/NFS3 root dentry from the root filehandle | 65 | * get an NFS2/NFS3 root dentry from the root filehandle |
47 | */ | 66 | */ |
48 | struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh) | 67 | struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh) |
@@ -54,33 +73,6 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh) | |||
54 | struct inode *inode; | 73 | struct inode *inode; |
55 | int error; | 74 | int error; |
56 | 75 | ||
57 | /* create a dummy root dentry with dummy inode for this superblock */ | ||
58 | if (!sb->s_root) { | ||
59 | struct nfs_fh dummyfh; | ||
60 | struct dentry *root; | ||
61 | struct inode *iroot; | ||
62 | |||
63 | memset(&dummyfh, 0, sizeof(dummyfh)); | ||
64 | memset(&fattr, 0, sizeof(fattr)); | ||
65 | nfs_fattr_init(&fattr); | ||
66 | fattr.valid = NFS_ATTR_FATTR; | ||
67 | fattr.type = NFDIR; | ||
68 | fattr.mode = S_IFDIR | S_IRUSR | S_IWUSR; | ||
69 | fattr.nlink = 2; | ||
70 | |||
71 | iroot = nfs_fhget(sb, &dummyfh, &fattr); | ||
72 | if (IS_ERR(iroot)) | ||
73 | return ERR_PTR(PTR_ERR(iroot)); | ||
74 | |||
75 | root = d_alloc_root(iroot); | ||
76 | if (!root) { | ||
77 | iput(iroot); | ||
78 | return ERR_PTR(-ENOMEM); | ||
79 | } | ||
80 | |||
81 | sb->s_root = root; | ||
82 | } | ||
83 | |||
84 | /* get the actual root for this mount */ | 76 | /* get the actual root for this mount */ |
85 | fsinfo.fattr = &fattr; | 77 | fsinfo.fattr = &fattr; |
86 | 78 | ||
@@ -96,6 +88,10 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh) | |||
96 | return ERR_PTR(PTR_ERR(inode)); | 88 | return ERR_PTR(PTR_ERR(inode)); |
97 | } | 89 | } |
98 | 90 | ||
91 | error = nfs_superblock_set_dummy_root(sb, inode); | ||
92 | if (error != 0) | ||
93 | return ERR_PTR(error); | ||
94 | |||
99 | /* root dentries normally start off anonymous and get spliced in later | 95 | /* root dentries normally start off anonymous and get spliced in later |
100 | * if the dentry tree reaches them; however if the dentry already | 96 | * if the dentry tree reaches them; however if the dentry already |
101 | * exists, we'll pick it up at this point and use it as the root | 97 | * exists, we'll pick it up at this point and use it as the root |
@@ -241,33 +237,6 @@ struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh) | |||
241 | 237 | ||
242 | dprintk("--> nfs4_get_root()\n"); | 238 | dprintk("--> nfs4_get_root()\n"); |
243 | 239 | ||
244 | /* create a dummy root dentry with dummy inode for this superblock */ | ||
245 | if (!sb->s_root) { | ||
246 | struct nfs_fh dummyfh; | ||
247 | struct dentry *root; | ||
248 | struct inode *iroot; | ||
249 | |||
250 | memset(&dummyfh, 0, sizeof(dummyfh)); | ||
251 | memset(&fattr, 0, sizeof(fattr)); | ||
252 | nfs_fattr_init(&fattr); | ||
253 | fattr.valid = NFS_ATTR_FATTR; | ||
254 | fattr.type = NFDIR; | ||
255 | fattr.mode = S_IFDIR | S_IRUSR | S_IWUSR; | ||
256 | fattr.nlink = 2; | ||
257 | |||
258 | iroot = nfs_fhget(sb, &dummyfh, &fattr); | ||
259 | if (IS_ERR(iroot)) | ||
260 | return ERR_PTR(PTR_ERR(iroot)); | ||
261 | |||
262 | root = d_alloc_root(iroot); | ||
263 | if (!root) { | ||
264 | iput(iroot); | ||
265 | return ERR_PTR(-ENOMEM); | ||
266 | } | ||
267 | |||
268 | sb->s_root = root; | ||
269 | } | ||
270 | |||
271 | /* get the info about the server and filesystem */ | 240 | /* get the info about the server and filesystem */ |
272 | error = nfs4_server_capabilities(server, mntfh); | 241 | error = nfs4_server_capabilities(server, mntfh); |
273 | if (error < 0) { | 242 | if (error < 0) { |
@@ -289,6 +258,10 @@ struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh) | |||
289 | return ERR_PTR(PTR_ERR(inode)); | 258 | return ERR_PTR(PTR_ERR(inode)); |
290 | } | 259 | } |
291 | 260 | ||
261 | error = nfs_superblock_set_dummy_root(sb, inode); | ||
262 | if (error != 0) | ||
263 | return ERR_PTR(error); | ||
264 | |||
292 | /* root dentries normally start off anonymous and get spliced in later | 265 | /* root dentries normally start off anonymous and get spliced in later |
293 | * if the dentry tree reaches them; however if the dentry already | 266 | * if the dentry tree reaches them; however if the dentry already |
294 | * exists, we'll pick it up at this point and use it as the root | 267 | * exists, we'll pick it up at this point and use it as the root |
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index fa517ae9207f..2426e713b77f 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -1054,10 +1054,11 @@ static int nfs_validate_mount_data(void *options, | |||
1054 | { | 1054 | { |
1055 | struct nfs_mount_data *data = (struct nfs_mount_data *)options; | 1055 | struct nfs_mount_data *data = (struct nfs_mount_data *)options; |
1056 | 1056 | ||
1057 | memset(args, 0, sizeof(*args)); | ||
1058 | |||
1057 | if (data == NULL) | 1059 | if (data == NULL) |
1058 | goto out_no_data; | 1060 | goto out_no_data; |
1059 | 1061 | ||
1060 | memset(args, 0, sizeof(*args)); | ||
1061 | args->flags = (NFS_MOUNT_VER3 | NFS_MOUNT_TCP); | 1062 | args->flags = (NFS_MOUNT_VER3 | NFS_MOUNT_TCP); |
1062 | args->rsize = NFS_MAX_FILE_IO_SIZE; | 1063 | args->rsize = NFS_MAX_FILE_IO_SIZE; |
1063 | args->wsize = NFS_MAX_FILE_IO_SIZE; | 1064 | args->wsize = NFS_MAX_FILE_IO_SIZE; |
@@ -1474,6 +1475,11 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags, | |||
1474 | error = PTR_ERR(mntroot); | 1475 | error = PTR_ERR(mntroot); |
1475 | goto error_splat_super; | 1476 | goto error_splat_super; |
1476 | } | 1477 | } |
1478 | if (mntroot->d_inode->i_op != &nfs_dir_inode_operations) { | ||
1479 | dput(mntroot); | ||
1480 | error = -ESTALE; | ||
1481 | goto error_splat_super; | ||
1482 | } | ||
1477 | 1483 | ||
1478 | s->s_flags |= MS_ACTIVE; | 1484 | s->s_flags |= MS_ACTIVE; |
1479 | mnt->mnt_sb = s; | 1485 | mnt->mnt_sb = s; |
@@ -1531,10 +1537,11 @@ static int nfs4_validate_mount_data(void *options, | |||
1531 | struct nfs4_mount_data *data = (struct nfs4_mount_data *)options; | 1537 | struct nfs4_mount_data *data = (struct nfs4_mount_data *)options; |
1532 | char *c; | 1538 | char *c; |
1533 | 1539 | ||
1540 | memset(args, 0, sizeof(*args)); | ||
1541 | |||
1534 | if (data == NULL) | 1542 | if (data == NULL) |
1535 | goto out_no_data; | 1543 | goto out_no_data; |
1536 | 1544 | ||
1537 | memset(args, 0, sizeof(*args)); | ||
1538 | args->rsize = NFS_MAX_FILE_IO_SIZE; | 1545 | args->rsize = NFS_MAX_FILE_IO_SIZE; |
1539 | args->wsize = NFS_MAX_FILE_IO_SIZE; | 1546 | args->wsize = NFS_MAX_FILE_IO_SIZE; |
1540 | args->timeo = 600; | 1547 | args->timeo = 600; |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 89527a487ed7..51cc1bd6a116 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -1436,7 +1436,8 @@ out: | |||
1436 | return ret; | 1436 | return ret; |
1437 | } | 1437 | } |
1438 | 1438 | ||
1439 | int nfs_wb_page_priority(struct inode *inode, struct page *page, int how) | 1439 | static int nfs_wb_page_priority(struct inode *inode, struct page *page, |
1440 | int how) | ||
1440 | { | 1441 | { |
1441 | loff_t range_start = page_offset(page); | 1442 | loff_t range_start = page_offset(page); |
1442 | loff_t range_end = range_start + (loff_t)(PAGE_CACHE_SIZE - 1); | 1443 | loff_t range_end = range_start + (loff_t)(PAGE_CACHE_SIZE - 1); |
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 556e34ccb005..56f7790cad46 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
@@ -1514,7 +1514,7 @@ int ocfs2_size_fits_inline_data(struct buffer_head *di_bh, u64 new_size) | |||
1514 | { | 1514 | { |
1515 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; | 1515 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; |
1516 | 1516 | ||
1517 | if (new_size < le16_to_cpu(di->id2.i_data.id_count)) | 1517 | if (new_size <= le16_to_cpu(di->id2.i_data.id_count)) |
1518 | return 1; | 1518 | return 1; |
1519 | return 0; | 1519 | return 0; |
1520 | } | 1520 | } |
diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index cd046060114e..597e064bb94f 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h | |||
@@ -212,7 +212,7 @@ extern struct mlog_bits mlog_and_bits, mlog_not_bits; | |||
212 | #define mlog_errno(st) do { \ | 212 | #define mlog_errno(st) do { \ |
213 | int _st = (st); \ | 213 | int _st = (st); \ |
214 | if (_st != -ERESTARTSYS && _st != -EINTR && \ | 214 | if (_st != -ERESTARTSYS && _st != -EINTR && \ |
215 | _st != AOP_TRUNCATED_PAGE) \ | 215 | _st != AOP_TRUNCATED_PAGE && _st != -ENOSPC) \ |
216 | mlog(ML_ERROR, "status = %lld\n", (long long)_st); \ | 216 | mlog(ML_ERROR, "status = %lld\n", (long long)_st); \ |
217 | } while (0) | 217 | } while (0) |
218 | 218 | ||
diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c index 1957a5ed219e..9923278ea6d4 100644 --- a/fs/ocfs2/dcache.c +++ b/fs/ocfs2/dcache.c | |||
@@ -344,12 +344,24 @@ static void ocfs2_dentry_iput(struct dentry *dentry, struct inode *inode) | |||
344 | { | 344 | { |
345 | struct ocfs2_dentry_lock *dl = dentry->d_fsdata; | 345 | struct ocfs2_dentry_lock *dl = dentry->d_fsdata; |
346 | 346 | ||
347 | mlog_bug_on_msg(!dl && !(dentry->d_flags & DCACHE_DISCONNECTED), | 347 | if (!dl) { |
348 | "dentry: %.*s\n", dentry->d_name.len, | 348 | /* |
349 | dentry->d_name.name); | 349 | * No dentry lock is ok if we're disconnected or |
350 | * unhashed. | ||
351 | */ | ||
352 | if (!(dentry->d_flags & DCACHE_DISCONNECTED) && | ||
353 | !d_unhashed(dentry)) { | ||
354 | unsigned long long ino = 0ULL; | ||
355 | if (inode) | ||
356 | ino = (unsigned long long)OCFS2_I(inode)->ip_blkno; | ||
357 | mlog(ML_ERROR, "Dentry is missing cluster lock. " | ||
358 | "inode: %llu, d_flags: 0x%x, d_name: %.*s\n", | ||
359 | ino, dentry->d_flags, dentry->d_name.len, | ||
360 | dentry->d_name.name); | ||
361 | } | ||
350 | 362 | ||
351 | if (!dl) | ||
352 | goto out; | 363 | goto out; |
364 | } | ||
353 | 365 | ||
354 | mlog_bug_on_msg(dl->dl_count == 0, "dentry: %.*s, count: %u\n", | 366 | mlog_bug_on_msg(dl->dl_count == 0, "dentry: %.*s, count: %u\n", |
355 | dentry->d_name.len, dentry->d_name.name, | 367 | dentry->d_name.len, dentry->d_name.name, |
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c index 62e4a7daa286..a54d33d95ada 100644 --- a/fs/ocfs2/dlm/dlmmaster.c +++ b/fs/ocfs2/dlm/dlmmaster.c | |||
@@ -908,7 +908,7 @@ lookup: | |||
908 | * but they might own this lockres. wait on them. */ | 908 | * but they might own this lockres. wait on them. */ |
909 | bit = find_next_bit(dlm->recovery_map, O2NM_MAX_NODES, 0); | 909 | bit = find_next_bit(dlm->recovery_map, O2NM_MAX_NODES, 0); |
910 | if (bit < O2NM_MAX_NODES) { | 910 | if (bit < O2NM_MAX_NODES) { |
911 | mlog(ML_NOTICE, "%s:%.*s: at least one node (%d) to" | 911 | mlog(ML_NOTICE, "%s:%.*s: at least one node (%d) to " |
912 | "recover before lock mastery can begin\n", | 912 | "recover before lock mastery can begin\n", |
913 | dlm->name, namelen, (char *)lockid, bit); | 913 | dlm->name, namelen, (char *)lockid, bit); |
914 | wait_on_recovery = 1; | 914 | wait_on_recovery = 1; |
@@ -962,7 +962,7 @@ redo_request: | |||
962 | spin_lock(&dlm->spinlock); | 962 | spin_lock(&dlm->spinlock); |
963 | bit = find_next_bit(dlm->recovery_map, O2NM_MAX_NODES, 0); | 963 | bit = find_next_bit(dlm->recovery_map, O2NM_MAX_NODES, 0); |
964 | if (bit < O2NM_MAX_NODES) { | 964 | if (bit < O2NM_MAX_NODES) { |
965 | mlog(ML_NOTICE, "%s:%.*s: at least one node (%d) to" | 965 | mlog(ML_NOTICE, "%s:%.*s: at least one node (%d) to " |
966 | "recover before lock mastery can begin\n", | 966 | "recover before lock mastery can begin\n", |
967 | dlm->name, namelen, (char *)lockid, bit); | 967 | dlm->name, namelen, (char *)lockid, bit); |
968 | wait_on_recovery = 1; | 968 | wait_on_recovery = 1; |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index bbac7cd33e0b..b75b2e1f0e42 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
@@ -399,7 +399,7 @@ static int ocfs2_truncate_file(struct inode *inode, | |||
399 | 399 | ||
400 | if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { | 400 | if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { |
401 | status = ocfs2_truncate_inline(inode, di_bh, new_i_size, | 401 | status = ocfs2_truncate_inline(inode, di_bh, new_i_size, |
402 | i_size_read(inode), 0); | 402 | i_size_read(inode), 1); |
403 | if (status) | 403 | if (status) |
404 | mlog_errno(status); | 404 | mlog_errno(status); |
405 | 405 | ||
@@ -1521,6 +1521,7 @@ static int ocfs2_remove_inode_range(struct inode *inode, | |||
1521 | u32 trunc_start, trunc_len, cpos, phys_cpos, alloc_size; | 1521 | u32 trunc_start, trunc_len, cpos, phys_cpos, alloc_size; |
1522 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 1522 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
1523 | struct ocfs2_cached_dealloc_ctxt dealloc; | 1523 | struct ocfs2_cached_dealloc_ctxt dealloc; |
1524 | struct address_space *mapping = inode->i_mapping; | ||
1524 | 1525 | ||
1525 | ocfs2_init_dealloc_ctxt(&dealloc); | 1526 | ocfs2_init_dealloc_ctxt(&dealloc); |
1526 | 1527 | ||
@@ -1529,10 +1530,20 @@ static int ocfs2_remove_inode_range(struct inode *inode, | |||
1529 | 1530 | ||
1530 | if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { | 1531 | if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { |
1531 | ret = ocfs2_truncate_inline(inode, di_bh, byte_start, | 1532 | ret = ocfs2_truncate_inline(inode, di_bh, byte_start, |
1532 | byte_start + byte_len, 1); | 1533 | byte_start + byte_len, 0); |
1533 | if (ret) | 1534 | if (ret) { |
1534 | mlog_errno(ret); | 1535 | mlog_errno(ret); |
1535 | return ret; | 1536 | goto out; |
1537 | } | ||
1538 | /* | ||
1539 | * There's no need to get fancy with the page cache | ||
1540 | * truncate of an inline-data inode. We're talking | ||
1541 | * about less than a page here, which will be cached | ||
1542 | * in the dinode buffer anyway. | ||
1543 | */ | ||
1544 | unmap_mapping_range(mapping, 0, 0, 0); | ||
1545 | truncate_inode_pages(mapping, 0); | ||
1546 | goto out; | ||
1536 | } | 1547 | } |
1537 | 1548 | ||
1538 | trunc_start = ocfs2_clusters_for_bytes(osb->sb, byte_start); | 1549 | trunc_start = ocfs2_clusters_for_bytes(osb->sb, byte_start); |
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index 1d5e0cb0fda1..ebb2bbe30f35 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c | |||
@@ -455,8 +455,8 @@ static int ocfs2_read_locked_inode(struct inode *inode, | |||
455 | status = -EINVAL; | 455 | status = -EINVAL; |
456 | fe = (struct ocfs2_dinode *) bh->b_data; | 456 | fe = (struct ocfs2_dinode *) bh->b_data; |
457 | if (!OCFS2_IS_VALID_DINODE(fe)) { | 457 | if (!OCFS2_IS_VALID_DINODE(fe)) { |
458 | mlog(ML_ERROR, "Invalid dinode #%llu: signature = %.*s\n", | 458 | mlog(0, "Invalid dinode #%llu: signature = %.*s\n", |
459 | (unsigned long long)le64_to_cpu(fe->i_blkno), 7, | 459 | (unsigned long long)args->fi_blkno, 7, |
460 | fe->i_signature); | 460 | fe->i_signature); |
461 | goto bail; | 461 | goto bail; |
462 | } | 462 | } |
@@ -863,7 +863,7 @@ static int ocfs2_query_inode_wipe(struct inode *inode, | |||
863 | status = ocfs2_try_open_lock(inode, 1); | 863 | status = ocfs2_try_open_lock(inode, 1); |
864 | if (status == -EAGAIN) { | 864 | if (status == -EAGAIN) { |
865 | status = 0; | 865 | status = 0; |
866 | mlog(0, "Skipping delete of %llu because it is in use on" | 866 | mlog(0, "Skipping delete of %llu because it is in use on " |
867 | "other nodes\n", (unsigned long long)oi->ip_blkno); | 867 | "other nodes\n", (unsigned long long)oi->ip_blkno); |
868 | goto bail; | 868 | goto bail; |
869 | } | 869 | } |
diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c index d272847d5a07..58ea88b5af36 100644 --- a/fs/ocfs2/localalloc.c +++ b/fs/ocfs2/localalloc.c | |||
@@ -484,6 +484,7 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb, | |||
484 | 484 | ||
485 | alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data; | 485 | alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data; |
486 | 486 | ||
487 | #ifdef OCFS2_DEBUG_FS | ||
487 | if (le32_to_cpu(alloc->id1.bitmap1.i_used) != | 488 | if (le32_to_cpu(alloc->id1.bitmap1.i_used) != |
488 | ocfs2_local_alloc_count_bits(alloc)) { | 489 | ocfs2_local_alloc_count_bits(alloc)) { |
489 | ocfs2_error(osb->sb, "local alloc inode %llu says it has " | 490 | ocfs2_error(osb->sb, "local alloc inode %llu says it has " |
@@ -494,6 +495,7 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb, | |||
494 | status = -EIO; | 495 | status = -EIO; |
495 | goto bail; | 496 | goto bail; |
496 | } | 497 | } |
498 | #endif | ||
497 | 499 | ||
498 | free_bits = le32_to_cpu(alloc->id1.bitmap1.i_total) - | 500 | free_bits = le32_to_cpu(alloc->id1.bitmap1.i_total) - |
499 | le32_to_cpu(alloc->id1.bitmap1.i_used); | 501 | le32_to_cpu(alloc->id1.bitmap1.i_used); |
@@ -712,9 +714,8 @@ static int ocfs2_sync_local_to_main(struct ocfs2_super *osb, | |||
712 | void *bitmap; | 714 | void *bitmap; |
713 | struct ocfs2_local_alloc *la = OCFS2_LOCAL_ALLOC(alloc); | 715 | struct ocfs2_local_alloc *la = OCFS2_LOCAL_ALLOC(alloc); |
714 | 716 | ||
715 | mlog_entry("total = %u, COUNT = %u, used = %u\n", | 717 | mlog_entry("total = %u, used = %u\n", |
716 | le32_to_cpu(alloc->id1.bitmap1.i_total), | 718 | le32_to_cpu(alloc->id1.bitmap1.i_total), |
717 | ocfs2_local_alloc_count_bits(alloc), | ||
718 | le32_to_cpu(alloc->id1.bitmap1.i_used)); | 719 | le32_to_cpu(alloc->id1.bitmap1.i_used)); |
719 | 720 | ||
720 | if (!alloc->id1.bitmap1.i_total) { | 721 | if (!alloc->id1.bitmap1.i_total) { |
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index be562ac3e89c..5ee775420665 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c | |||
@@ -438,14 +438,14 @@ unlock_osb: | |||
438 | } | 438 | } |
439 | 439 | ||
440 | if (!ret) { | 440 | if (!ret) { |
441 | if (!ocfs2_is_hard_readonly(osb)) | ||
442 | ocfs2_set_journal_params(osb); | ||
443 | |||
444 | /* Only save off the new mount options in case of a successful | 441 | /* Only save off the new mount options in case of a successful |
445 | * remount. */ | 442 | * remount. */ |
446 | osb->s_mount_opt = parsed_options.mount_opt; | 443 | osb->s_mount_opt = parsed_options.mount_opt; |
447 | osb->s_atime_quantum = parsed_options.atime_quantum; | 444 | osb->s_atime_quantum = parsed_options.atime_quantum; |
448 | osb->preferred_slot = parsed_options.slot; | 445 | osb->preferred_slot = parsed_options.slot; |
446 | |||
447 | if (!ocfs2_is_hard_readonly(osb)) | ||
448 | ocfs2_set_journal_params(osb); | ||
449 | } | 449 | } |
450 | out: | 450 | out: |
451 | return ret; | 451 | return ret; |
diff --git a/fs/proc/array.c b/fs/proc/array.c index eba339ecba27..65c62e1bfd6f 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c | |||
@@ -374,7 +374,9 @@ static cputime_t task_stime(struct task_struct *p) | |||
374 | stime = nsec_to_clock_t(p->se.sum_exec_runtime) - | 374 | stime = nsec_to_clock_t(p->se.sum_exec_runtime) - |
375 | cputime_to_clock_t(task_utime(p)); | 375 | cputime_to_clock_t(task_utime(p)); |
376 | 376 | ||
377 | p->prev_stime = max(p->prev_stime, clock_t_to_cputime(stime)); | 377 | if (stime >= 0) |
378 | p->prev_stime = max(p->prev_stime, clock_t_to_cputime(stime)); | ||
379 | |||
378 | return p->prev_stime; | 380 | return p->prev_stime; |
379 | } | 381 | } |
380 | #endif | 382 | #endif |
diff --git a/fs/proc/base.c b/fs/proc/base.c index a17c26859074..02a63ac04178 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -2411,19 +2411,23 @@ out: | |||
2411 | * Find the first task with tgid >= tgid | 2411 | * Find the first task with tgid >= tgid |
2412 | * | 2412 | * |
2413 | */ | 2413 | */ |
2414 | static struct task_struct *next_tgid(unsigned int tgid, | 2414 | struct tgid_iter { |
2415 | struct pid_namespace *ns) | 2415 | unsigned int tgid; |
2416 | { | ||
2417 | struct task_struct *task; | 2416 | struct task_struct *task; |
2417 | }; | ||
2418 | static struct tgid_iter next_tgid(struct pid_namespace *ns, struct tgid_iter iter) | ||
2419 | { | ||
2418 | struct pid *pid; | 2420 | struct pid *pid; |
2419 | 2421 | ||
2422 | if (iter.task) | ||
2423 | put_task_struct(iter.task); | ||
2420 | rcu_read_lock(); | 2424 | rcu_read_lock(); |
2421 | retry: | 2425 | retry: |
2422 | task = NULL; | 2426 | iter.task = NULL; |
2423 | pid = find_ge_pid(tgid, ns); | 2427 | pid = find_ge_pid(iter.tgid, ns); |
2424 | if (pid) { | 2428 | if (pid) { |
2425 | tgid = pid_nr_ns(pid, ns) + 1; | 2429 | iter.tgid = pid_nr_ns(pid, ns); |
2426 | task = pid_task(pid, PIDTYPE_PID); | 2430 | iter.task = pid_task(pid, PIDTYPE_PID); |
2427 | /* What we to know is if the pid we have find is the | 2431 | /* What we to know is if the pid we have find is the |
2428 | * pid of a thread_group_leader. Testing for task | 2432 | * pid of a thread_group_leader. Testing for task |
2429 | * being a thread_group_leader is the obvious thing | 2433 | * being a thread_group_leader is the obvious thing |
@@ -2436,23 +2440,25 @@ retry: | |||
2436 | * found doesn't happen to be a thread group leader. | 2440 | * found doesn't happen to be a thread group leader. |
2437 | * As we don't care in the case of readdir. | 2441 | * As we don't care in the case of readdir. |
2438 | */ | 2442 | */ |
2439 | if (!task || !has_group_leader_pid(task)) | 2443 | if (!iter.task || !has_group_leader_pid(iter.task)) { |
2444 | iter.tgid += 1; | ||
2440 | goto retry; | 2445 | goto retry; |
2441 | get_task_struct(task); | 2446 | } |
2447 | get_task_struct(iter.task); | ||
2442 | } | 2448 | } |
2443 | rcu_read_unlock(); | 2449 | rcu_read_unlock(); |
2444 | return task; | 2450 | return iter; |
2445 | } | 2451 | } |
2446 | 2452 | ||
2447 | #define TGID_OFFSET (FIRST_PROCESS_ENTRY + ARRAY_SIZE(proc_base_stuff)) | 2453 | #define TGID_OFFSET (FIRST_PROCESS_ENTRY + ARRAY_SIZE(proc_base_stuff)) |
2448 | 2454 | ||
2449 | static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | 2455 | static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldir, |
2450 | struct task_struct *task, int tgid) | 2456 | struct tgid_iter iter) |
2451 | { | 2457 | { |
2452 | char name[PROC_NUMBUF]; | 2458 | char name[PROC_NUMBUF]; |
2453 | int len = snprintf(name, sizeof(name), "%d", tgid); | 2459 | int len = snprintf(name, sizeof(name), "%d", iter.tgid); |
2454 | return proc_fill_cache(filp, dirent, filldir, name, len, | 2460 | return proc_fill_cache(filp, dirent, filldir, name, len, |
2455 | proc_pid_instantiate, task, NULL); | 2461 | proc_pid_instantiate, iter.task, NULL); |
2456 | } | 2462 | } |
2457 | 2463 | ||
2458 | /* for the /proc/ directory itself, after non-process stuff has been done */ | 2464 | /* for the /proc/ directory itself, after non-process stuff has been done */ |
@@ -2460,8 +2466,7 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
2460 | { | 2466 | { |
2461 | unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY; | 2467 | unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY; |
2462 | struct task_struct *reaper = get_proc_task(filp->f_path.dentry->d_inode); | 2468 | struct task_struct *reaper = get_proc_task(filp->f_path.dentry->d_inode); |
2463 | struct task_struct *task; | 2469 | struct tgid_iter iter; |
2464 | int tgid; | ||
2465 | struct pid_namespace *ns; | 2470 | struct pid_namespace *ns; |
2466 | 2471 | ||
2467 | if (!reaper) | 2472 | if (!reaper) |
@@ -2474,14 +2479,14 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
2474 | } | 2479 | } |
2475 | 2480 | ||
2476 | ns = filp->f_dentry->d_sb->s_fs_info; | 2481 | ns = filp->f_dentry->d_sb->s_fs_info; |
2477 | tgid = filp->f_pos - TGID_OFFSET; | 2482 | iter.task = NULL; |
2478 | for (task = next_tgid(tgid, ns); | 2483 | iter.tgid = filp->f_pos - TGID_OFFSET; |
2479 | task; | 2484 | for (iter = next_tgid(ns, iter); |
2480 | put_task_struct(task), task = next_tgid(tgid + 1, ns)) { | 2485 | iter.task; |
2481 | tgid = task_pid_nr_ns(task, ns); | 2486 | iter.tgid += 1, iter = next_tgid(ns, iter)) { |
2482 | filp->f_pos = tgid + TGID_OFFSET; | 2487 | filp->f_pos = iter.tgid + TGID_OFFSET; |
2483 | if (proc_pid_fill_cache(filp, dirent, filldir, task, tgid) < 0) { | 2488 | if (proc_pid_fill_cache(filp, dirent, filldir, iter) < 0) { |
2484 | put_task_struct(task); | 2489 | put_task_struct(iter.task); |
2485 | goto out; | 2490 | goto out; |
2486 | } | 2491 | } |
2487 | } | 2492 | } |
diff --git a/fs/proc/generic.c b/fs/proc/generic.c index c2b752341f89..5fccfe222a63 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c | |||
@@ -565,41 +565,6 @@ static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp | |||
565 | return 0; | 565 | return 0; |
566 | } | 566 | } |
567 | 567 | ||
568 | /* | ||
569 | * Kill an inode that got unregistered.. | ||
570 | */ | ||
571 | static void proc_kill_inodes(struct proc_dir_entry *de) | ||
572 | { | ||
573 | struct list_head *p; | ||
574 | struct super_block *sb; | ||
575 | |||
576 | /* | ||
577 | * Actually it's a partial revoke(). | ||
578 | */ | ||
579 | spin_lock(&sb_lock); | ||
580 | list_for_each_entry(sb, &proc_fs_type.fs_supers, s_instances) { | ||
581 | file_list_lock(); | ||
582 | list_for_each(p, &sb->s_files) { | ||
583 | struct file *filp = list_entry(p, struct file, | ||
584 | f_u.fu_list); | ||
585 | struct dentry *dentry = filp->f_path.dentry; | ||
586 | struct inode *inode; | ||
587 | const struct file_operations *fops; | ||
588 | |||
589 | if (dentry->d_op != &proc_dentry_operations) | ||
590 | continue; | ||
591 | inode = dentry->d_inode; | ||
592 | if (PDE(inode) != de) | ||
593 | continue; | ||
594 | fops = filp->f_op; | ||
595 | filp->f_op = NULL; | ||
596 | fops_put(fops); | ||
597 | } | ||
598 | file_list_unlock(); | ||
599 | } | ||
600 | spin_unlock(&sb_lock); | ||
601 | } | ||
602 | |||
603 | static struct proc_dir_entry *proc_create(struct proc_dir_entry **parent, | 568 | static struct proc_dir_entry *proc_create(struct proc_dir_entry **parent, |
604 | const char *name, | 569 | const char *name, |
605 | mode_t mode, | 570 | mode_t mode, |
@@ -774,8 +739,6 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent) | |||
774 | continue_removing: | 739 | continue_removing: |
775 | if (S_ISDIR(de->mode)) | 740 | if (S_ISDIR(de->mode)) |
776 | parent->nlink--; | 741 | parent->nlink--; |
777 | if (!S_ISREG(de->mode)) | ||
778 | proc_kill_inodes(de); | ||
779 | de->nlink = 0; | 742 | de->nlink = 0; |
780 | WARN_ON(de->subdir); | 743 | WARN_ON(de->subdir); |
781 | if (!atomic_read(&de->count)) | 744 | if (!atomic_read(&de->count)) |
diff --git a/fs/proc/internal.h b/fs/proc/internal.h index 1b2b6c6bb475..1820eb2ef762 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h | |||
@@ -78,5 +78,3 @@ static inline int proc_fd(struct inode *inode) | |||
78 | { | 78 | { |
79 | return PROC_I(inode)->fd; | 79 | return PROC_I(inode)->fd; |
80 | } | 80 | } |
81 | |||
82 | extern struct file_system_type proc_fs_type; | ||
diff --git a/fs/proc/root.c b/fs/proc/root.c index 1f86bb860e04..ec9cb3b6c93b 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c | |||
@@ -98,7 +98,7 @@ static void proc_kill_sb(struct super_block *sb) | |||
98 | put_pid_ns(ns); | 98 | put_pid_ns(ns); |
99 | } | 99 | } |
100 | 100 | ||
101 | struct file_system_type proc_fs_type = { | 101 | static struct file_system_type proc_fs_type = { |
102 | .name = "proc", | 102 | .name = "proc", |
103 | .get_sb = proc_get_sb, | 103 | .get_sb = proc_get_sb, |
104 | .kill_sb = proc_kill_sb, | 104 | .kill_sb = proc_kill_sb, |
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 27d1785b7644..4045bdcc4b33 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
@@ -119,7 +119,11 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer | |||
119 | 119 | ||
120 | sysfs_put_active_two(attr_sd); | 120 | sysfs_put_active_two(attr_sd); |
121 | 121 | ||
122 | BUG_ON(count > (ssize_t)PAGE_SIZE); | 122 | /* |
123 | * The code works fine with PAGE_SIZE return but it's likely to | ||
124 | * indicate truncated result or overflow in normal use cases. | ||
125 | */ | ||
126 | BUG_ON(count >= (ssize_t)PAGE_SIZE); | ||
123 | if (count >= 0) { | 127 | if (count >= 0) { |
124 | buffer->needs_read_fill = 0; | 128 | buffer->needs_read_fill = 0; |
125 | buffer->count = count; | 129 | buffer->count = count; |