diff options
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/Kconfig | 1 | ||||
-rw-r--r-- | fs/cifs/Makefile | 2 | ||||
-rw-r--r-- | fs/cifs/README | 5 | ||||
-rw-r--r-- | fs/cifs/cache.c | 16 | ||||
-rw-r--r-- | fs/cifs/cifs_debug.c | 32 | ||||
-rw-r--r-- | fs/cifs/cifs_dfs_ref.c | 122 | ||||
-rw-r--r-- | fs/cifs/cifs_fs_sb.h | 1 | ||||
-rw-r--r-- | fs/cifs/cifs_spnego.c | 10 | ||||
-rw-r--r-- | fs/cifs/cifs_unicode.c | 127 | ||||
-rw-r--r-- | fs/cifs/cifsacl.c | 17 | ||||
-rw-r--r-- | fs/cifs/cifsencrypt.c | 44 | ||||
-rw-r--r-- | fs/cifs/cifsencrypt.h | 33 | ||||
-rw-r--r-- | fs/cifs/cifsfs.c | 94 | ||||
-rw-r--r-- | fs/cifs/cifsfs.h | 25 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 110 | ||||
-rw-r--r-- | fs/cifs/cifspdu.h | 62 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 20 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 126 | ||||
-rw-r--r-- | fs/cifs/connect.c | 712 | ||||
-rw-r--r-- | fs/cifs/dir.c | 94 | ||||
-rw-r--r-- | fs/cifs/file.c | 729 | ||||
-rw-r--r-- | fs/cifs/inode.c | 36 | ||||
-rw-r--r-- | fs/cifs/link.c | 63 | ||||
-rw-r--r-- | fs/cifs/md4.c | 205 | ||||
-rw-r--r-- | fs/cifs/md5.c | 366 | ||||
-rw-r--r-- | fs/cifs/md5.h | 38 | ||||
-rw-r--r-- | fs/cifs/misc.c | 189 | ||||
-rw-r--r-- | fs/cifs/netmisc.c | 16 | ||||
-rw-r--r-- | fs/cifs/readdir.c | 11 | ||||
-rw-r--r-- | fs/cifs/sess.c | 158 | ||||
-rw-r--r-- | fs/cifs/smbdes.c | 1 | ||||
-rw-r--r-- | fs/cifs/smbencrypt.c | 92 | ||||
-rw-r--r-- | fs/cifs/transport.c | 483 |
33 files changed, 1977 insertions, 2063 deletions
diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig index ee45648b0d1a..7cb0f7f847e4 100644 --- a/fs/cifs/Kconfig +++ b/fs/cifs/Kconfig | |||
@@ -3,6 +3,7 @@ config CIFS | |||
3 | depends on INET | 3 | depends on INET |
4 | select NLS | 4 | select NLS |
5 | select CRYPTO | 5 | select CRYPTO |
6 | select CRYPTO_MD4 | ||
6 | select CRYPTO_MD5 | 7 | select CRYPTO_MD5 |
7 | select CRYPTO_HMAC | 8 | select CRYPTO_HMAC |
8 | select CRYPTO_ARC4 | 9 | select CRYPTO_ARC4 |
diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile index 43b19dd39191..d87558448e3d 100644 --- a/fs/cifs/Makefile +++ b/fs/cifs/Makefile | |||
@@ -5,7 +5,7 @@ obj-$(CONFIG_CIFS) += cifs.o | |||
5 | 5 | ||
6 | cifs-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o \ | 6 | cifs-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o \ |
7 | link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o \ | 7 | link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o \ |
8 | md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o \ | 8 | cifs_unicode.o nterr.o xattr.o cifsencrypt.o \ |
9 | readdir.o ioctl.o sess.o export.o | 9 | readdir.o ioctl.o sess.o export.o |
10 | 10 | ||
11 | cifs-$(CONFIG_CIFS_ACL) += cifsacl.o | 11 | cifs-$(CONFIG_CIFS_ACL) += cifsacl.o |
diff --git a/fs/cifs/README b/fs/cifs/README index 46af99ab3614..fe1683590828 100644 --- a/fs/cifs/README +++ b/fs/cifs/README | |||
@@ -452,6 +452,11 @@ A partial list of the supported mount options follows: | |||
452 | if oplock (caching token) is granted and held. Note that | 452 | if oplock (caching token) is granted and held. Note that |
453 | direct allows write operations larger than page size | 453 | direct allows write operations larger than page size |
454 | to be sent to the server. | 454 | to be sent to the server. |
455 | strictcache Use for switching on strict cache mode. In this mode the | ||
456 | client read from the cache all the time it has Oplock Level II, | ||
457 | otherwise - read from the server. All written data are stored | ||
458 | in the cache, but if the client doesn't have Exclusive Oplock, | ||
459 | it writes the data to the server. | ||
455 | acl Allow setfacl and getfacl to manage posix ACLs if server | 460 | acl Allow setfacl and getfacl to manage posix ACLs if server |
456 | supports them. (default) | 461 | supports them. (default) |
457 | noacl Do not allow setfacl and getfacl calls on this mount | 462 | noacl Do not allow setfacl and getfacl calls on this mount |
diff --git a/fs/cifs/cache.c b/fs/cifs/cache.c index 224d7bbd1fcc..e654dfd092c3 100644 --- a/fs/cifs/cache.c +++ b/fs/cifs/cache.c | |||
@@ -64,7 +64,9 @@ static uint16_t cifs_server_get_key(const void *cookie_netfs_data, | |||
64 | void *buffer, uint16_t maxbuf) | 64 | void *buffer, uint16_t maxbuf) |
65 | { | 65 | { |
66 | const struct TCP_Server_Info *server = cookie_netfs_data; | 66 | const struct TCP_Server_Info *server = cookie_netfs_data; |
67 | const struct sockaddr *sa = (struct sockaddr *) &server->addr.sockAddr; | 67 | const struct sockaddr *sa = (struct sockaddr *) &server->dstaddr; |
68 | const struct sockaddr_in *addr = (struct sockaddr_in *) sa; | ||
69 | const struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) sa; | ||
68 | struct cifs_server_key *key = buffer; | 70 | struct cifs_server_key *key = buffer; |
69 | uint16_t key_len = sizeof(struct cifs_server_key); | 71 | uint16_t key_len = sizeof(struct cifs_server_key); |
70 | 72 | ||
@@ -76,16 +78,16 @@ static uint16_t cifs_server_get_key(const void *cookie_netfs_data, | |||
76 | */ | 78 | */ |
77 | switch (sa->sa_family) { | 79 | switch (sa->sa_family) { |
78 | case AF_INET: | 80 | case AF_INET: |
79 | key->family = server->addr.sockAddr.sin_family; | 81 | key->family = sa->sa_family; |
80 | key->port = server->addr.sockAddr.sin_port; | 82 | key->port = addr->sin_port; |
81 | key->addr[0].ipv4_addr = server->addr.sockAddr.sin_addr; | 83 | key->addr[0].ipv4_addr = addr->sin_addr; |
82 | key_len += sizeof(key->addr[0].ipv4_addr); | 84 | key_len += sizeof(key->addr[0].ipv4_addr); |
83 | break; | 85 | break; |
84 | 86 | ||
85 | case AF_INET6: | 87 | case AF_INET6: |
86 | key->family = server->addr.sockAddr6.sin6_family; | 88 | key->family = sa->sa_family; |
87 | key->port = server->addr.sockAddr6.sin6_port; | 89 | key->port = addr6->sin6_port; |
88 | key->addr[0].ipv6_addr = server->addr.sockAddr6.sin6_addr; | 90 | key->addr[0].ipv6_addr = addr6->sin6_addr; |
89 | key_len += sizeof(key->addr[0].ipv6_addr); | 91 | key_len += sizeof(key->addr[0].ipv6_addr); |
90 | break; | 92 | break; |
91 | 93 | ||
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index 103ab8b605b0..65829d32128c 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c | |||
@@ -79,11 +79,11 @@ void cifs_dump_mids(struct TCP_Server_Info *server) | |||
79 | spin_lock(&GlobalMid_Lock); | 79 | spin_lock(&GlobalMid_Lock); |
80 | list_for_each(tmp, &server->pending_mid_q) { | 80 | list_for_each(tmp, &server->pending_mid_q) { |
81 | mid_entry = list_entry(tmp, struct mid_q_entry, qhead); | 81 | mid_entry = list_entry(tmp, struct mid_q_entry, qhead); |
82 | cERROR(1, "State: %d Cmd: %d Pid: %d Tsk: %p Mid %d", | 82 | cERROR(1, "State: %d Cmd: %d Pid: %d Cbdata: %p Mid %d", |
83 | mid_entry->midState, | 83 | mid_entry->midState, |
84 | (int)mid_entry->command, | 84 | (int)mid_entry->command, |
85 | mid_entry->pid, | 85 | mid_entry->pid, |
86 | mid_entry->tsk, | 86 | mid_entry->callback_data, |
87 | mid_entry->mid); | 87 | mid_entry->mid); |
88 | #ifdef CONFIG_CIFS_STATS2 | 88 | #ifdef CONFIG_CIFS_STATS2 |
89 | cERROR(1, "IsLarge: %d buf: %p time rcv: %ld now: %ld", | 89 | cERROR(1, "IsLarge: %d buf: %p time rcv: %ld now: %ld", |
@@ -119,29 +119,27 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) | |||
119 | "Display Internal CIFS Data Structures for Debugging\n" | 119 | "Display Internal CIFS Data Structures for Debugging\n" |
120 | "---------------------------------------------------\n"); | 120 | "---------------------------------------------------\n"); |
121 | seq_printf(m, "CIFS Version %s\n", CIFS_VERSION); | 121 | seq_printf(m, "CIFS Version %s\n", CIFS_VERSION); |
122 | seq_printf(m, "Features: "); | 122 | seq_printf(m, "Features:"); |
123 | #ifdef CONFIG_CIFS_DFS_UPCALL | 123 | #ifdef CONFIG_CIFS_DFS_UPCALL |
124 | seq_printf(m, "dfs"); | 124 | seq_printf(m, " dfs"); |
125 | seq_putc(m, ' '); | ||
126 | #endif | 125 | #endif |
127 | #ifdef CONFIG_CIFS_FSCACHE | 126 | #ifdef CONFIG_CIFS_FSCACHE |
128 | seq_printf(m, "fscache"); | 127 | seq_printf(m, " fscache"); |
129 | seq_putc(m, ' '); | ||
130 | #endif | 128 | #endif |
131 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | 129 | #ifdef CONFIG_CIFS_WEAK_PW_HASH |
132 | seq_printf(m, "lanman"); | 130 | seq_printf(m, " lanman"); |
133 | seq_putc(m, ' '); | ||
134 | #endif | 131 | #endif |
135 | #ifdef CONFIG_CIFS_POSIX | 132 | #ifdef CONFIG_CIFS_POSIX |
136 | seq_printf(m, "posix"); | 133 | seq_printf(m, " posix"); |
137 | seq_putc(m, ' '); | ||
138 | #endif | 134 | #endif |
139 | #ifdef CONFIG_CIFS_UPCALL | 135 | #ifdef CONFIG_CIFS_UPCALL |
140 | seq_printf(m, "spnego"); | 136 | seq_printf(m, " spnego"); |
141 | seq_putc(m, ' '); | ||
142 | #endif | 137 | #endif |
143 | #ifdef CONFIG_CIFS_XATTR | 138 | #ifdef CONFIG_CIFS_XATTR |
144 | seq_printf(m, "xattr"); | 139 | seq_printf(m, " xattr"); |
140 | #endif | ||
141 | #ifdef CONFIG_CIFS_ACL | ||
142 | seq_printf(m, " acl"); | ||
145 | #endif | 143 | #endif |
146 | seq_putc(m, '\n'); | 144 | seq_putc(m, '\n'); |
147 | seq_printf(m, "Active VFS Requests: %d\n", GlobalTotalActiveXid); | 145 | seq_printf(m, "Active VFS Requests: %d\n", GlobalTotalActiveXid); |
@@ -220,11 +218,11 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) | |||
220 | mid_entry = list_entry(tmp3, struct mid_q_entry, | 218 | mid_entry = list_entry(tmp3, struct mid_q_entry, |
221 | qhead); | 219 | qhead); |
222 | seq_printf(m, "\tState: %d com: %d pid:" | 220 | seq_printf(m, "\tState: %d com: %d pid:" |
223 | " %d tsk: %p mid %d\n", | 221 | " %d cbdata: %p mid %d\n", |
224 | mid_entry->midState, | 222 | mid_entry->midState, |
225 | (int)mid_entry->command, | 223 | (int)mid_entry->command, |
226 | mid_entry->pid, | 224 | mid_entry->pid, |
227 | mid_entry->tsk, | 225 | mid_entry->callback_data, |
228 | mid_entry->mid); | 226 | mid_entry->mid); |
229 | } | 227 | } |
230 | spin_unlock(&GlobalMid_Lock); | 228 | spin_unlock(&GlobalMid_Lock); |
@@ -333,7 +331,7 @@ static int cifs_stats_proc_show(struct seq_file *m, void *v) | |||
333 | atomic_read(&totSmBufAllocCount)); | 331 | atomic_read(&totSmBufAllocCount)); |
334 | #endif /* CONFIG_CIFS_STATS2 */ | 332 | #endif /* CONFIG_CIFS_STATS2 */ |
335 | 333 | ||
336 | seq_printf(m, "Operations (MIDs): %d\n", midCount.counter); | 334 | seq_printf(m, "Operations (MIDs): %d\n", atomic_read(&midCount)); |
337 | seq_printf(m, | 335 | seq_printf(m, |
338 | "\n%d session %d share reconnects\n", | 336 | "\n%d session %d share reconnects\n", |
339 | tcpSesReconnectCount.counter, tconInfoReconnectCount.counter); | 337 | tcpSesReconnectCount.counter, tconInfoReconnectCount.counter); |
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c index c68a056f27fd..0a265ad9e426 100644 --- a/fs/cifs/cifs_dfs_ref.c +++ b/fs/cifs/cifs_dfs_ref.c | |||
@@ -255,35 +255,6 @@ static struct vfsmount *cifs_dfs_do_refmount(struct cifs_sb_info *cifs_sb, | |||
255 | 255 | ||
256 | } | 256 | } |
257 | 257 | ||
258 | static int add_mount_helper(struct vfsmount *newmnt, struct nameidata *nd, | ||
259 | struct list_head *mntlist) | ||
260 | { | ||
261 | /* stolen from afs code */ | ||
262 | int err; | ||
263 | |||
264 | mntget(newmnt); | ||
265 | err = do_add_mount(newmnt, &nd->path, nd->path.mnt->mnt_flags | MNT_SHRINKABLE, mntlist); | ||
266 | switch (err) { | ||
267 | case 0: | ||
268 | path_put(&nd->path); | ||
269 | nd->path.mnt = newmnt; | ||
270 | nd->path.dentry = dget(newmnt->mnt_root); | ||
271 | schedule_delayed_work(&cifs_dfs_automount_task, | ||
272 | cifs_dfs_mountpoint_expiry_timeout); | ||
273 | break; | ||
274 | case -EBUSY: | ||
275 | /* someone else made a mount here whilst we were busy */ | ||
276 | while (d_mountpoint(nd->path.dentry) && | ||
277 | follow_down(&nd->path)) | ||
278 | ; | ||
279 | err = 0; | ||
280 | default: | ||
281 | mntput(newmnt); | ||
282 | break; | ||
283 | } | ||
284 | return err; | ||
285 | } | ||
286 | |||
287 | static void dump_referral(const struct dfs_info3_param *ref) | 258 | static void dump_referral(const struct dfs_info3_param *ref) |
288 | { | 259 | { |
289 | cFYI(1, "DFS: ref path: %s", ref->path_name); | 260 | cFYI(1, "DFS: ref path: %s", ref->path_name); |
@@ -293,27 +264,23 @@ static void dump_referral(const struct dfs_info3_param *ref) | |||
293 | ref->path_consumed); | 264 | ref->path_consumed); |
294 | } | 265 | } |
295 | 266 | ||
296 | 267 | /* | |
297 | static void* | 268 | * Create a vfsmount that we can automount |
298 | cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) | 269 | */ |
270 | static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt) | ||
299 | { | 271 | { |
300 | struct dfs_info3_param *referrals = NULL; | 272 | struct dfs_info3_param *referrals = NULL; |
301 | unsigned int num_referrals = 0; | 273 | unsigned int num_referrals = 0; |
302 | struct cifs_sb_info *cifs_sb; | 274 | struct cifs_sb_info *cifs_sb; |
303 | struct cifsSesInfo *ses; | 275 | struct cifsSesInfo *ses; |
304 | char *full_path = NULL; | 276 | char *full_path; |
305 | int xid, i; | 277 | int xid, i; |
306 | int rc = 0; | 278 | int rc; |
307 | struct vfsmount *mnt = ERR_PTR(-ENOENT); | 279 | struct vfsmount *mnt; |
308 | struct tcon_link *tlink; | 280 | struct tcon_link *tlink; |
309 | 281 | ||
310 | cFYI(1, "in %s", __func__); | 282 | cFYI(1, "in %s", __func__); |
311 | BUG_ON(IS_ROOT(dentry)); | 283 | BUG_ON(IS_ROOT(mntpt)); |
312 | |||
313 | xid = GetXid(); | ||
314 | |||
315 | dput(nd->path.dentry); | ||
316 | nd->path.dentry = dget(dentry); | ||
317 | 284 | ||
318 | /* | 285 | /* |
319 | * The MSDFS spec states that paths in DFS referral requests and | 286 | * The MSDFS spec states that paths in DFS referral requests and |
@@ -321,66 +288,83 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) | |||
321 | * the double backslashes usually used in the UNC. This function | 288 | * the double backslashes usually used in the UNC. This function |
322 | * gives us the latter, so we must adjust the result. | 289 | * gives us the latter, so we must adjust the result. |
323 | */ | 290 | */ |
324 | full_path = build_path_from_dentry(dentry); | 291 | mnt = ERR_PTR(-ENOMEM); |
325 | if (full_path == NULL) { | 292 | full_path = build_path_from_dentry(mntpt); |
326 | rc = -ENOMEM; | 293 | if (full_path == NULL) |
327 | goto out_err; | 294 | goto cdda_exit; |
328 | } | ||
329 | 295 | ||
330 | cifs_sb = CIFS_SB(dentry->d_inode->i_sb); | 296 | cifs_sb = CIFS_SB(mntpt->d_inode->i_sb); |
331 | tlink = cifs_sb_tlink(cifs_sb); | 297 | tlink = cifs_sb_tlink(cifs_sb); |
332 | if (IS_ERR(tlink)) { | 298 | if (IS_ERR(tlink)) { |
333 | rc = PTR_ERR(tlink); | 299 | mnt = ERR_CAST(tlink); |
334 | goto out_err; | 300 | goto free_full_path; |
335 | } | 301 | } |
336 | ses = tlink_tcon(tlink)->ses; | 302 | ses = tlink_tcon(tlink)->ses; |
337 | 303 | ||
304 | xid = GetXid(); | ||
338 | rc = get_dfs_path(xid, ses, full_path + 1, cifs_sb->local_nls, | 305 | rc = get_dfs_path(xid, ses, full_path + 1, cifs_sb->local_nls, |
339 | &num_referrals, &referrals, | 306 | &num_referrals, &referrals, |
340 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 307 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
308 | FreeXid(xid); | ||
341 | 309 | ||
342 | cifs_put_tlink(tlink); | 310 | cifs_put_tlink(tlink); |
343 | 311 | ||
312 | mnt = ERR_PTR(-ENOENT); | ||
344 | for (i = 0; i < num_referrals; i++) { | 313 | for (i = 0; i < num_referrals; i++) { |
345 | int len; | 314 | int len; |
346 | dump_referral(referrals+i); | 315 | dump_referral(referrals + i); |
347 | /* connect to a node */ | 316 | /* connect to a node */ |
348 | len = strlen(referrals[i].node_name); | 317 | len = strlen(referrals[i].node_name); |
349 | if (len < 2) { | 318 | if (len < 2) { |
350 | cERROR(1, "%s: Net Address path too short: %s", | 319 | cERROR(1, "%s: Net Address path too short: %s", |
351 | __func__, referrals[i].node_name); | 320 | __func__, referrals[i].node_name); |
352 | rc = -EINVAL; | 321 | mnt = ERR_PTR(-EINVAL); |
353 | goto out_err; | 322 | break; |
354 | } | 323 | } |
355 | mnt = cifs_dfs_do_refmount(cifs_sb, | 324 | mnt = cifs_dfs_do_refmount(cifs_sb, |
356 | full_path, referrals + i); | 325 | full_path, referrals + i); |
357 | cFYI(1, "%s: cifs_dfs_do_refmount:%s , mnt:%p", __func__, | 326 | cFYI(1, "%s: cifs_dfs_do_refmount:%s , mnt:%p", __func__, |
358 | referrals[i].node_name, mnt); | 327 | referrals[i].node_name, mnt); |
359 | |||
360 | /* complete mount procedure if we accured submount */ | ||
361 | if (!IS_ERR(mnt)) | 328 | if (!IS_ERR(mnt)) |
362 | break; | 329 | goto success; |
363 | } | 330 | } |
364 | 331 | ||
365 | /* we need it cause for() above could exit without valid submount */ | 332 | /* no valid submounts were found; return error from get_dfs_path() by |
366 | rc = PTR_ERR(mnt); | 333 | * preference */ |
367 | if (IS_ERR(mnt)) | 334 | if (rc != 0) |
368 | goto out_err; | 335 | mnt = ERR_PTR(rc); |
369 | 336 | ||
370 | rc = add_mount_helper(mnt, nd, &cifs_dfs_automount_list); | 337 | success: |
371 | |||
372 | out: | ||
373 | FreeXid(xid); | ||
374 | free_dfs_info_array(referrals, num_referrals); | 338 | free_dfs_info_array(referrals, num_referrals); |
339 | free_full_path: | ||
375 | kfree(full_path); | 340 | kfree(full_path); |
341 | cdda_exit: | ||
376 | cFYI(1, "leaving %s" , __func__); | 342 | cFYI(1, "leaving %s" , __func__); |
377 | return ERR_PTR(rc); | 343 | return mnt; |
378 | out_err: | 344 | } |
379 | path_put(&nd->path); | 345 | |
380 | goto out; | 346 | /* |
347 | * Attempt to automount the referral | ||
348 | */ | ||
349 | struct vfsmount *cifs_dfs_d_automount(struct path *path) | ||
350 | { | ||
351 | struct vfsmount *newmnt; | ||
352 | |||
353 | cFYI(1, "in %s", __func__); | ||
354 | |||
355 | newmnt = cifs_dfs_do_automount(path->dentry); | ||
356 | if (IS_ERR(newmnt)) { | ||
357 | cFYI(1, "leaving %s [automount failed]" , __func__); | ||
358 | return newmnt; | ||
359 | } | ||
360 | |||
361 | mntget(newmnt); /* prevent immediate expiration */ | ||
362 | mnt_set_expiry(newmnt, &cifs_dfs_automount_list); | ||
363 | schedule_delayed_work(&cifs_dfs_automount_task, | ||
364 | cifs_dfs_mountpoint_expiry_timeout); | ||
365 | cFYI(1, "leaving %s [ok]" , __func__); | ||
366 | return newmnt; | ||
381 | } | 367 | } |
382 | 368 | ||
383 | const struct inode_operations cifs_dfs_referral_inode_operations = { | 369 | const struct inode_operations cifs_dfs_referral_inode_operations = { |
384 | .follow_link = cifs_dfs_follow_mountpoint, | ||
385 | }; | 370 | }; |
386 | |||
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h index 7852cd677051..ac51cd2d33ae 100644 --- a/fs/cifs/cifs_fs_sb.h +++ b/fs/cifs/cifs_fs_sb.h | |||
@@ -40,6 +40,7 @@ | |||
40 | #define CIFS_MOUNT_FSCACHE 0x8000 /* local caching enabled */ | 40 | #define CIFS_MOUNT_FSCACHE 0x8000 /* local caching enabled */ |
41 | #define CIFS_MOUNT_MF_SYMLINKS 0x10000 /* Minshall+French Symlinks enabled */ | 41 | #define CIFS_MOUNT_MF_SYMLINKS 0x10000 /* Minshall+French Symlinks enabled */ |
42 | #define CIFS_MOUNT_MULTIUSER 0x20000 /* multiuser mount */ | 42 | #define CIFS_MOUNT_MULTIUSER 0x20000 /* multiuser mount */ |
43 | #define CIFS_MOUNT_STRICT_IO 0x40000 /* strict cache mode */ | ||
43 | 44 | ||
44 | struct cifs_sb_info { | 45 | struct cifs_sb_info { |
45 | struct rb_root tlink_tree; | 46 | struct rb_root tlink_tree; |
diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c index 87044906cd1f..4dfba8283165 100644 --- a/fs/cifs/cifs_spnego.c +++ b/fs/cifs/cifs_spnego.c | |||
@@ -98,6 +98,8 @@ struct key * | |||
98 | cifs_get_spnego_key(struct cifsSesInfo *sesInfo) | 98 | cifs_get_spnego_key(struct cifsSesInfo *sesInfo) |
99 | { | 99 | { |
100 | struct TCP_Server_Info *server = sesInfo->server; | 100 | struct TCP_Server_Info *server = sesInfo->server; |
101 | struct sockaddr_in *sa = (struct sockaddr_in *) &server->dstaddr; | ||
102 | struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) &server->dstaddr; | ||
101 | char *description, *dp; | 103 | char *description, *dp; |
102 | size_t desc_len; | 104 | size_t desc_len; |
103 | struct key *spnego_key; | 105 | struct key *spnego_key; |
@@ -127,10 +129,10 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo) | |||
127 | dp = description + strlen(description); | 129 | dp = description + strlen(description); |
128 | 130 | ||
129 | /* add the server address */ | 131 | /* add the server address */ |
130 | if (server->addr.sockAddr.sin_family == AF_INET) | 132 | if (server->dstaddr.ss_family == AF_INET) |
131 | sprintf(dp, "ip4=%pI4", &server->addr.sockAddr.sin_addr); | 133 | sprintf(dp, "ip4=%pI4", &sa->sin_addr); |
132 | else if (server->addr.sockAddr.sin_family == AF_INET6) | 134 | else if (server->dstaddr.ss_family == AF_INET6) |
133 | sprintf(dp, "ip6=%pI6", &server->addr.sockAddr6.sin6_addr); | 135 | sprintf(dp, "ip6=%pI6", &sa6->sin6_addr); |
134 | else | 136 | else |
135 | goto out; | 137 | goto out; |
136 | 138 | ||
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c index 430f510a1720..fc0fd4fde306 100644 --- a/fs/cifs/cifs_unicode.c +++ b/fs/cifs/cifs_unicode.c | |||
@@ -44,10 +44,14 @@ cifs_ucs2_bytes(const __le16 *from, int maxbytes, | |||
44 | int charlen, outlen = 0; | 44 | int charlen, outlen = 0; |
45 | int maxwords = maxbytes / 2; | 45 | int maxwords = maxbytes / 2; |
46 | char tmp[NLS_MAX_CHARSET_SIZE]; | 46 | char tmp[NLS_MAX_CHARSET_SIZE]; |
47 | __u16 ftmp; | ||
47 | 48 | ||
48 | for (i = 0; i < maxwords && from[i]; i++) { | 49 | for (i = 0; i < maxwords; i++) { |
49 | charlen = codepage->uni2char(le16_to_cpu(from[i]), tmp, | 50 | ftmp = get_unaligned_le16(&from[i]); |
50 | NLS_MAX_CHARSET_SIZE); | 51 | if (ftmp == 0) |
52 | break; | ||
53 | |||
54 | charlen = codepage->uni2char(ftmp, tmp, NLS_MAX_CHARSET_SIZE); | ||
51 | if (charlen > 0) | 55 | if (charlen > 0) |
52 | outlen += charlen; | 56 | outlen += charlen; |
53 | else | 57 | else |
@@ -58,9 +62,9 @@ cifs_ucs2_bytes(const __le16 *from, int maxbytes, | |||
58 | } | 62 | } |
59 | 63 | ||
60 | /* | 64 | /* |
61 | * cifs_mapchar - convert a little-endian char to proper char in codepage | 65 | * cifs_mapchar - convert a host-endian char to proper char in codepage |
62 | * @target - where converted character should be copied | 66 | * @target - where converted character should be copied |
63 | * @src_char - 2 byte little-endian source character | 67 | * @src_char - 2 byte host-endian source character |
64 | * @cp - codepage to which character should be converted | 68 | * @cp - codepage to which character should be converted |
65 | * @mapchar - should character be mapped according to mapchars mount option? | 69 | * @mapchar - should character be mapped according to mapchars mount option? |
66 | * | 70 | * |
@@ -69,7 +73,7 @@ cifs_ucs2_bytes(const __le16 *from, int maxbytes, | |||
69 | * enough to hold the result of the conversion (at least NLS_MAX_CHARSET_SIZE). | 73 | * enough to hold the result of the conversion (at least NLS_MAX_CHARSET_SIZE). |
70 | */ | 74 | */ |
71 | static int | 75 | static int |
72 | cifs_mapchar(char *target, const __le16 src_char, const struct nls_table *cp, | 76 | cifs_mapchar(char *target, const __u16 src_char, const struct nls_table *cp, |
73 | bool mapchar) | 77 | bool mapchar) |
74 | { | 78 | { |
75 | int len = 1; | 79 | int len = 1; |
@@ -82,7 +86,7 @@ cifs_mapchar(char *target, const __le16 src_char, const struct nls_table *cp, | |||
82 | * build_path_from_dentry are modified, as they use slash as | 86 | * build_path_from_dentry are modified, as they use slash as |
83 | * separator. | 87 | * separator. |
84 | */ | 88 | */ |
85 | switch (le16_to_cpu(src_char)) { | 89 | switch (src_char) { |
86 | case UNI_COLON: | 90 | case UNI_COLON: |
87 | *target = ':'; | 91 | *target = ':'; |
88 | break; | 92 | break; |
@@ -109,8 +113,7 @@ out: | |||
109 | return len; | 113 | return len; |
110 | 114 | ||
111 | cp_convert: | 115 | cp_convert: |
112 | len = cp->uni2char(le16_to_cpu(src_char), target, | 116 | len = cp->uni2char(src_char, target, NLS_MAX_CHARSET_SIZE); |
113 | NLS_MAX_CHARSET_SIZE); | ||
114 | if (len <= 0) { | 117 | if (len <= 0) { |
115 | *target = '?'; | 118 | *target = '?'; |
116 | len = 1; | 119 | len = 1; |
@@ -149,6 +152,7 @@ cifs_from_ucs2(char *to, const __le16 *from, int tolen, int fromlen, | |||
149 | int nullsize = nls_nullsize(codepage); | 152 | int nullsize = nls_nullsize(codepage); |
150 | int fromwords = fromlen / 2; | 153 | int fromwords = fromlen / 2; |
151 | char tmp[NLS_MAX_CHARSET_SIZE]; | 154 | char tmp[NLS_MAX_CHARSET_SIZE]; |
155 | __u16 ftmp; | ||
152 | 156 | ||
153 | /* | 157 | /* |
154 | * because the chars can be of varying widths, we need to take care | 158 | * because the chars can be of varying widths, we need to take care |
@@ -158,19 +162,23 @@ cifs_from_ucs2(char *to, const __le16 *from, int tolen, int fromlen, | |||
158 | */ | 162 | */ |
159 | safelen = tolen - (NLS_MAX_CHARSET_SIZE + nullsize); | 163 | safelen = tolen - (NLS_MAX_CHARSET_SIZE + nullsize); |
160 | 164 | ||
161 | for (i = 0; i < fromwords && from[i]; i++) { | 165 | for (i = 0; i < fromwords; i++) { |
166 | ftmp = get_unaligned_le16(&from[i]); | ||
167 | if (ftmp == 0) | ||
168 | break; | ||
169 | |||
162 | /* | 170 | /* |
163 | * check to see if converting this character might make the | 171 | * check to see if converting this character might make the |
164 | * conversion bleed into the null terminator | 172 | * conversion bleed into the null terminator |
165 | */ | 173 | */ |
166 | if (outlen >= safelen) { | 174 | if (outlen >= safelen) { |
167 | charlen = cifs_mapchar(tmp, from[i], codepage, mapchar); | 175 | charlen = cifs_mapchar(tmp, ftmp, codepage, mapchar); |
168 | if ((outlen + charlen) > (tolen - nullsize)) | 176 | if ((outlen + charlen) > (tolen - nullsize)) |
169 | break; | 177 | break; |
170 | } | 178 | } |
171 | 179 | ||
172 | /* put converted char into 'to' buffer */ | 180 | /* put converted char into 'to' buffer */ |
173 | charlen = cifs_mapchar(&to[outlen], from[i], codepage, mapchar); | 181 | charlen = cifs_mapchar(&to[outlen], ftmp, codepage, mapchar); |
174 | outlen += charlen; | 182 | outlen += charlen; |
175 | } | 183 | } |
176 | 184 | ||
@@ -193,24 +201,21 @@ cifs_strtoUCS(__le16 *to, const char *from, int len, | |||
193 | { | 201 | { |
194 | int charlen; | 202 | int charlen; |
195 | int i; | 203 | int i; |
196 | wchar_t *wchar_to = (wchar_t *)to; /* needed to quiet sparse */ | 204 | wchar_t wchar_to; /* needed to quiet sparse */ |
197 | 205 | ||
198 | for (i = 0; len && *from; i++, from += charlen, len -= charlen) { | 206 | for (i = 0; len && *from; i++, from += charlen, len -= charlen) { |
199 | 207 | charlen = codepage->char2uni(from, len, &wchar_to); | |
200 | /* works for 2.4.0 kernel or later */ | ||
201 | charlen = codepage->char2uni(from, len, &wchar_to[i]); | ||
202 | if (charlen < 1) { | 208 | if (charlen < 1) { |
203 | cERROR(1, "strtoUCS: char2uni of %d returned %d", | 209 | cERROR(1, "strtoUCS: char2uni of 0x%x returned %d", |
204 | (int)*from, charlen); | 210 | *from, charlen); |
205 | /* A question mark */ | 211 | /* A question mark */ |
206 | to[i] = cpu_to_le16(0x003f); | 212 | wchar_to = 0x003f; |
207 | charlen = 1; | 213 | charlen = 1; |
208 | } else | 214 | } |
209 | to[i] = cpu_to_le16(wchar_to[i]); | 215 | put_unaligned_le16(wchar_to, &to[i]); |
210 | |||
211 | } | 216 | } |
212 | 217 | ||
213 | to[i] = 0; | 218 | put_unaligned_le16(0, &to[i]); |
214 | return i; | 219 | return i; |
215 | } | 220 | } |
216 | 221 | ||
@@ -252,3 +257,79 @@ cifs_strndup_from_ucs(const char *src, const int maxlen, const bool is_unicode, | |||
252 | return dst; | 257 | return dst; |
253 | } | 258 | } |
254 | 259 | ||
260 | /* | ||
261 | * Convert 16 bit Unicode pathname to wire format from string in current code | ||
262 | * page. Conversion may involve remapping up the six characters that are | ||
263 | * only legal in POSIX-like OS (if they are present in the string). Path | ||
264 | * names are little endian 16 bit Unicode on the wire | ||
265 | */ | ||
266 | int | ||
267 | cifsConvertToUCS(__le16 *target, const char *source, int maxlen, | ||
268 | const struct nls_table *cp, int mapChars) | ||
269 | { | ||
270 | int i, j, charlen; | ||
271 | int len_remaining = maxlen; | ||
272 | char src_char; | ||
273 | __u16 temp; | ||
274 | |||
275 | if (!mapChars) | ||
276 | return cifs_strtoUCS(target, source, PATH_MAX, cp); | ||
277 | |||
278 | for (i = 0, j = 0; i < maxlen; j++) { | ||
279 | src_char = source[i]; | ||
280 | switch (src_char) { | ||
281 | case 0: | ||
282 | put_unaligned_le16(0, &target[j]); | ||
283 | goto ctoUCS_out; | ||
284 | case ':': | ||
285 | temp = UNI_COLON; | ||
286 | break; | ||
287 | case '*': | ||
288 | temp = UNI_ASTERIK; | ||
289 | break; | ||
290 | case '?': | ||
291 | temp = UNI_QUESTION; | ||
292 | break; | ||
293 | case '<': | ||
294 | temp = UNI_LESSTHAN; | ||
295 | break; | ||
296 | case '>': | ||
297 | temp = UNI_GRTRTHAN; | ||
298 | break; | ||
299 | case '|': | ||
300 | temp = UNI_PIPE; | ||
301 | break; | ||
302 | /* | ||
303 | * FIXME: We can not handle remapping backslash (UNI_SLASH) | ||
304 | * until all the calls to build_path_from_dentry are modified, | ||
305 | * as they use backslash as separator. | ||
306 | */ | ||
307 | default: | ||
308 | charlen = cp->char2uni(source+i, len_remaining, | ||
309 | &temp); | ||
310 | /* | ||
311 | * if no match, use question mark, which at least in | ||
312 | * some cases serves as wild card | ||
313 | */ | ||
314 | if (charlen < 1) { | ||
315 | temp = 0x003f; | ||
316 | charlen = 1; | ||
317 | } | ||
318 | len_remaining -= charlen; | ||
319 | /* | ||
320 | * character may take more than one byte in the source | ||
321 | * string, but will take exactly two bytes in the | ||
322 | * target string | ||
323 | */ | ||
324 | i += charlen; | ||
325 | continue; | ||
326 | } | ||
327 | put_unaligned_le16(temp, &target[j]); | ||
328 | i++; /* move to next char in source string */ | ||
329 | len_remaining--; | ||
330 | } | ||
331 | |||
332 | ctoUCS_out: | ||
333 | return i; | ||
334 | } | ||
335 | |||
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index a437ec391a01..beeebf194234 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c | |||
@@ -41,9 +41,12 @@ static struct cifs_wksid wksidarr[NUM_WK_SIDS] = { | |||
41 | ; | 41 | ; |
42 | 42 | ||
43 | 43 | ||
44 | /* security id for everyone */ | 44 | /* security id for everyone/world system group */ |
45 | static const struct cifs_sid sid_everyone = { | 45 | static const struct cifs_sid sid_everyone = { |
46 | 1, 1, {0, 0, 0, 0, 0, 1}, {0} }; | 46 | 1, 1, {0, 0, 0, 0, 0, 1}, {0} }; |
47 | /* security id for Authenticated Users system group */ | ||
48 | static const struct cifs_sid sid_authusers = { | ||
49 | 1, 1, {0, 0, 0, 0, 0, 5}, {11} }; | ||
47 | /* group users */ | 50 | /* group users */ |
48 | static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} }; | 51 | static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} }; |
49 | 52 | ||
@@ -365,10 +368,14 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, | |||
365 | if (num_aces > 0) { | 368 | if (num_aces > 0) { |
366 | umode_t user_mask = S_IRWXU; | 369 | umode_t user_mask = S_IRWXU; |
367 | umode_t group_mask = S_IRWXG; | 370 | umode_t group_mask = S_IRWXG; |
368 | umode_t other_mask = S_IRWXO; | 371 | umode_t other_mask = S_IRWXU | S_IRWXG | S_IRWXO; |
369 | 372 | ||
370 | ppace = kmalloc(num_aces * sizeof(struct cifs_ace *), | 373 | ppace = kmalloc(num_aces * sizeof(struct cifs_ace *), |
371 | GFP_KERNEL); | 374 | GFP_KERNEL); |
375 | if (!ppace) { | ||
376 | cERROR(1, "DACL memory allocation error"); | ||
377 | return; | ||
378 | } | ||
372 | 379 | ||
373 | for (i = 0; i < num_aces; ++i) { | 380 | for (i = 0; i < num_aces; ++i) { |
374 | ppace[i] = (struct cifs_ace *) (acl_base + acl_size); | 381 | ppace[i] = (struct cifs_ace *) (acl_base + acl_size); |
@@ -390,6 +397,12 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, | |||
390 | ppace[i]->type, | 397 | ppace[i]->type, |
391 | &fattr->cf_mode, | 398 | &fattr->cf_mode, |
392 | &other_mask); | 399 | &other_mask); |
400 | if (compare_sids(&(ppace[i]->sid), &sid_authusers)) | ||
401 | access_flags_to_mode(ppace[i]->access_req, | ||
402 | ppace[i]->type, | ||
403 | &fattr->cf_mode, | ||
404 | &other_mask); | ||
405 | |||
393 | 406 | ||
394 | /* memcpy((void *)(&(cifscred->aces[i])), | 407 | /* memcpy((void *)(&(cifscred->aces[i])), |
395 | (void *)ppace[i], | 408 | (void *)ppace[i], |
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index f856732161ab..a51585f9852b 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include "cifspdu.h" | 24 | #include "cifspdu.h" |
25 | #include "cifsglob.h" | 25 | #include "cifsglob.h" |
26 | #include "cifs_debug.h" | 26 | #include "cifs_debug.h" |
27 | #include "md5.h" | ||
28 | #include "cifs_unicode.h" | 27 | #include "cifs_unicode.h" |
29 | #include "cifsproto.h" | 28 | #include "cifsproto.h" |
30 | #include "ntlmssp.h" | 29 | #include "ntlmssp.h" |
@@ -37,11 +36,6 @@ | |||
37 | /* Note that the smb header signature field on input contains the | 36 | /* Note that the smb header signature field on input contains the |
38 | sequence number before this function is called */ | 37 | sequence number before this function is called */ |
39 | 38 | ||
40 | extern void mdfour(unsigned char *out, unsigned char *in, int n); | ||
41 | extern void E_md4hash(const unsigned char *passwd, unsigned char *p16); | ||
42 | extern void SMBencrypt(unsigned char *passwd, const unsigned char *c8, | ||
43 | unsigned char *p24); | ||
44 | |||
45 | static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu, | 39 | static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu, |
46 | struct TCP_Server_Info *server, char *signature) | 40 | struct TCP_Server_Info *server, char *signature) |
47 | { | 41 | { |
@@ -72,6 +66,7 @@ static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu, | |||
72 | return 0; | 66 | return 0; |
73 | } | 67 | } |
74 | 68 | ||
69 | /* must be called with server->srv_mutex held */ | ||
75 | int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, | 70 | int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, |
76 | __u32 *pexpected_response_sequence_number) | 71 | __u32 *pexpected_response_sequence_number) |
77 | { | 72 | { |
@@ -84,14 +79,12 @@ int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, | |||
84 | if ((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0) | 79 | if ((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0) |
85 | return rc; | 80 | return rc; |
86 | 81 | ||
87 | spin_lock(&GlobalMid_Lock); | ||
88 | cifs_pdu->Signature.Sequence.SequenceNumber = | 82 | cifs_pdu->Signature.Sequence.SequenceNumber = |
89 | cpu_to_le32(server->sequence_number); | 83 | cpu_to_le32(server->sequence_number); |
90 | cifs_pdu->Signature.Sequence.Reserved = 0; | 84 | cifs_pdu->Signature.Sequence.Reserved = 0; |
91 | 85 | ||
92 | *pexpected_response_sequence_number = server->sequence_number++; | 86 | *pexpected_response_sequence_number = server->sequence_number++; |
93 | server->sequence_number++; | 87 | server->sequence_number++; |
94 | spin_unlock(&GlobalMid_Lock); | ||
95 | 88 | ||
96 | rc = cifs_calculate_signature(cifs_pdu, server, smb_signature); | 89 | rc = cifs_calculate_signature(cifs_pdu, server, smb_signature); |
97 | if (rc) | 90 | if (rc) |
@@ -149,6 +142,7 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec, | |||
149 | return rc; | 142 | return rc; |
150 | } | 143 | } |
151 | 144 | ||
145 | /* must be called with server->srv_mutex held */ | ||
152 | int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, | 146 | int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, |
153 | __u32 *pexpected_response_sequence_number) | 147 | __u32 *pexpected_response_sequence_number) |
154 | { | 148 | { |
@@ -162,14 +156,12 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, | |||
162 | if ((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0) | 156 | if ((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0) |
163 | return rc; | 157 | return rc; |
164 | 158 | ||
165 | spin_lock(&GlobalMid_Lock); | ||
166 | cifs_pdu->Signature.Sequence.SequenceNumber = | 159 | cifs_pdu->Signature.Sequence.SequenceNumber = |
167 | cpu_to_le32(server->sequence_number); | 160 | cpu_to_le32(server->sequence_number); |
168 | cifs_pdu->Signature.Sequence.Reserved = 0; | 161 | cifs_pdu->Signature.Sequence.Reserved = 0; |
169 | 162 | ||
170 | *pexpected_response_sequence_number = server->sequence_number++; | 163 | *pexpected_response_sequence_number = server->sequence_number++; |
171 | server->sequence_number++; | 164 | server->sequence_number++; |
172 | spin_unlock(&GlobalMid_Lock); | ||
173 | 165 | ||
174 | rc = cifs_calc_signature2(iov, n_vec, server, smb_signature); | 166 | rc = cifs_calc_signature2(iov, n_vec, server, smb_signature); |
175 | if (rc) | 167 | if (rc) |
@@ -236,6 +228,7 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu, | |||
236 | /* first calculate 24 bytes ntlm response and then 16 byte session key */ | 228 | /* first calculate 24 bytes ntlm response and then 16 byte session key */ |
237 | int setup_ntlm_response(struct cifsSesInfo *ses) | 229 | int setup_ntlm_response(struct cifsSesInfo *ses) |
238 | { | 230 | { |
231 | int rc = 0; | ||
239 | unsigned int temp_len = CIFS_SESS_KEY_SIZE + CIFS_AUTH_RESP_SIZE; | 232 | unsigned int temp_len = CIFS_SESS_KEY_SIZE + CIFS_AUTH_RESP_SIZE; |
240 | char temp_key[CIFS_SESS_KEY_SIZE]; | 233 | char temp_key[CIFS_SESS_KEY_SIZE]; |
241 | 234 | ||
@@ -249,13 +242,26 @@ int setup_ntlm_response(struct cifsSesInfo *ses) | |||
249 | } | 242 | } |
250 | ses->auth_key.len = temp_len; | 243 | ses->auth_key.len = temp_len; |
251 | 244 | ||
252 | SMBNTencrypt(ses->password, ses->server->cryptkey, | 245 | rc = SMBNTencrypt(ses->password, ses->server->cryptkey, |
253 | ses->auth_key.response + CIFS_SESS_KEY_SIZE); | 246 | ses->auth_key.response + CIFS_SESS_KEY_SIZE); |
247 | if (rc) { | ||
248 | cFYI(1, "%s Can't generate NTLM response, error: %d", | ||
249 | __func__, rc); | ||
250 | return rc; | ||
251 | } | ||
254 | 252 | ||
255 | E_md4hash(ses->password, temp_key); | 253 | rc = E_md4hash(ses->password, temp_key); |
256 | mdfour(ses->auth_key.response, temp_key, CIFS_SESS_KEY_SIZE); | 254 | if (rc) { |
255 | cFYI(1, "%s Can't generate NT hash, error: %d", __func__, rc); | ||
256 | return rc; | ||
257 | } | ||
257 | 258 | ||
258 | return 0; | 259 | rc = mdfour(ses->auth_key.response, temp_key, CIFS_SESS_KEY_SIZE); |
260 | if (rc) | ||
261 | cFYI(1, "%s Can't generate NTLM session key, error: %d", | ||
262 | __func__, rc); | ||
263 | |||
264 | return rc; | ||
259 | } | 265 | } |
260 | 266 | ||
261 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | 267 | #ifdef CONFIG_CIFS_WEAK_PW_HASH |
@@ -651,9 +657,10 @@ calc_seckey(struct cifsSesInfo *ses) | |||
651 | get_random_bytes(sec_key, CIFS_SESS_KEY_SIZE); | 657 | get_random_bytes(sec_key, CIFS_SESS_KEY_SIZE); |
652 | 658 | ||
653 | tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); | 659 | tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); |
654 | if (!tfm_arc4 || IS_ERR(tfm_arc4)) { | 660 | if (IS_ERR(tfm_arc4)) { |
661 | rc = PTR_ERR(tfm_arc4); | ||
655 | cERROR(1, "could not allocate crypto API arc4\n"); | 662 | cERROR(1, "could not allocate crypto API arc4\n"); |
656 | return PTR_ERR(tfm_arc4); | 663 | return rc; |
657 | } | 664 | } |
658 | 665 | ||
659 | desc.tfm = tfm_arc4; | 666 | desc.tfm = tfm_arc4; |
@@ -702,14 +709,13 @@ cifs_crypto_shash_allocate(struct TCP_Server_Info *server) | |||
702 | unsigned int size; | 709 | unsigned int size; |
703 | 710 | ||
704 | server->secmech.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0); | 711 | server->secmech.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0); |
705 | if (!server->secmech.hmacmd5 || | 712 | if (IS_ERR(server->secmech.hmacmd5)) { |
706 | IS_ERR(server->secmech.hmacmd5)) { | ||
707 | cERROR(1, "could not allocate crypto hmacmd5\n"); | 713 | cERROR(1, "could not allocate crypto hmacmd5\n"); |
708 | return PTR_ERR(server->secmech.hmacmd5); | 714 | return PTR_ERR(server->secmech.hmacmd5); |
709 | } | 715 | } |
710 | 716 | ||
711 | server->secmech.md5 = crypto_alloc_shash("md5", 0, 0); | 717 | server->secmech.md5 = crypto_alloc_shash("md5", 0, 0); |
712 | if (!server->secmech.md5 || IS_ERR(server->secmech.md5)) { | 718 | if (IS_ERR(server->secmech.md5)) { |
713 | cERROR(1, "could not allocate crypto md5\n"); | 719 | cERROR(1, "could not allocate crypto md5\n"); |
714 | rc = PTR_ERR(server->secmech.md5); | 720 | rc = PTR_ERR(server->secmech.md5); |
715 | goto crypto_allocate_md5_fail; | 721 | goto crypto_allocate_md5_fail; |
diff --git a/fs/cifs/cifsencrypt.h b/fs/cifs/cifsencrypt.h deleted file mode 100644 index 15d2ec006474..000000000000 --- a/fs/cifs/cifsencrypt.h +++ /dev/null | |||
@@ -1,33 +0,0 @@ | |||
1 | /* | ||
2 | * fs/cifs/cifsencrypt.h | ||
3 | * | ||
4 | * Copyright (c) International Business Machines Corp., 2005 | ||
5 | * Author(s): Steve French (sfrench@us.ibm.com) | ||
6 | * | ||
7 | * Externs for misc. small encryption routines | ||
8 | * so we do not have to put them in cifsproto.h | ||
9 | * | ||
10 | * This library is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU Lesser General Public License as published | ||
12 | * by the Free Software Foundation; either version 2.1 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This library is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | ||
18 | * the GNU Lesser General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU Lesser General Public License | ||
21 | * along with this library; if not, write to the Free Software | ||
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
23 | */ | ||
24 | |||
25 | /* md4.c */ | ||
26 | extern void mdfour(unsigned char *out, unsigned char *in, int n); | ||
27 | /* smbdes.c */ | ||
28 | extern void E_P16(unsigned char *p14, unsigned char *p16); | ||
29 | extern void E_P24(unsigned char *p21, const unsigned char *c8, | ||
30 | unsigned char *p24); | ||
31 | |||
32 | |||
33 | |||
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 3936aa7f2c22..f2970136d17d 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -77,7 +77,11 @@ unsigned int cifs_max_pending = CIFS_MAX_REQ; | |||
77 | module_param(cifs_max_pending, int, 0); | 77 | module_param(cifs_max_pending, int, 0); |
78 | MODULE_PARM_DESC(cifs_max_pending, "Simultaneous requests to server. " | 78 | MODULE_PARM_DESC(cifs_max_pending, "Simultaneous requests to server. " |
79 | "Default: 50 Range: 2 to 256"); | 79 | "Default: 50 Range: 2 to 256"); |
80 | 80 | unsigned short echo_retries = 5; | |
81 | module_param(echo_retries, ushort, 0644); | ||
82 | MODULE_PARM_DESC(echo_retries, "Number of echo attempts before giving up and " | ||
83 | "reconnecting server. Default: 5. 0 means " | ||
84 | "never reconnect."); | ||
81 | extern mempool_t *cifs_sm_req_poolp; | 85 | extern mempool_t *cifs_sm_req_poolp; |
82 | extern mempool_t *cifs_req_poolp; | 86 | extern mempool_t *cifs_req_poolp; |
83 | extern mempool_t *cifs_mid_poolp; | 87 | extern mempool_t *cifs_mid_poolp; |
@@ -174,6 +178,12 @@ cifs_read_super(struct super_block *sb, void *data, | |||
174 | goto out_no_root; | 178 | goto out_no_root; |
175 | } | 179 | } |
176 | 180 | ||
181 | /* do that *after* d_alloc_root() - we want NULL ->d_op for root here */ | ||
182 | if (cifs_sb_master_tcon(cifs_sb)->nocase) | ||
183 | sb->s_d_op = &cifs_ci_dentry_ops; | ||
184 | else | ||
185 | sb->s_d_op = &cifs_dentry_ops; | ||
186 | |||
177 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 187 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
178 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { | 188 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { |
179 | cFYI(1, "export ops supported"); | 189 | cFYI(1, "export ops supported"); |
@@ -283,10 +293,13 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
283 | return 0; | 293 | return 0; |
284 | } | 294 | } |
285 | 295 | ||
286 | static int cifs_permission(struct inode *inode, int mask) | 296 | static int cifs_permission(struct inode *inode, int mask, unsigned int flags) |
287 | { | 297 | { |
288 | struct cifs_sb_info *cifs_sb; | 298 | struct cifs_sb_info *cifs_sb; |
289 | 299 | ||
300 | if (flags & IPERM_FLAG_RCU) | ||
301 | return -ECHILD; | ||
302 | |||
290 | cifs_sb = CIFS_SB(inode->i_sb); | 303 | cifs_sb = CIFS_SB(inode->i_sb); |
291 | 304 | ||
292 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) { | 305 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) { |
@@ -298,7 +311,7 @@ static int cifs_permission(struct inode *inode, int mask) | |||
298 | on the client (above and beyond ACL on servers) for | 311 | on the client (above and beyond ACL on servers) for |
299 | servers which do not support setting and viewing mode bits, | 312 | servers which do not support setting and viewing mode bits, |
300 | so allowing client to check permissions is useful */ | 313 | so allowing client to check permissions is useful */ |
301 | return generic_permission(inode, mask, NULL); | 314 | return generic_permission(inode, mask, flags, NULL); |
302 | } | 315 | } |
303 | 316 | ||
304 | static struct kmem_cache *cifs_inode_cachep; | 317 | static struct kmem_cache *cifs_inode_cachep; |
@@ -326,6 +339,8 @@ cifs_alloc_inode(struct super_block *sb) | |||
326 | cifs_inode->invalid_mapping = false; | 339 | cifs_inode->invalid_mapping = false; |
327 | cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */ | 340 | cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */ |
328 | cifs_inode->server_eof = 0; | 341 | cifs_inode->server_eof = 0; |
342 | cifs_inode->uniqueid = 0; | ||
343 | cifs_inode->createtime = 0; | ||
329 | 344 | ||
330 | /* Can not set i_flags here - they get immediately overwritten | 345 | /* Can not set i_flags here - they get immediately overwritten |
331 | to zero by the VFS */ | 346 | to zero by the VFS */ |
@@ -334,10 +349,17 @@ cifs_alloc_inode(struct super_block *sb) | |||
334 | return &cifs_inode->vfs_inode; | 349 | return &cifs_inode->vfs_inode; |
335 | } | 350 | } |
336 | 351 | ||
352 | static void cifs_i_callback(struct rcu_head *head) | ||
353 | { | ||
354 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
355 | INIT_LIST_HEAD(&inode->i_dentry); | ||
356 | kmem_cache_free(cifs_inode_cachep, CIFS_I(inode)); | ||
357 | } | ||
358 | |||
337 | static void | 359 | static void |
338 | cifs_destroy_inode(struct inode *inode) | 360 | cifs_destroy_inode(struct inode *inode) |
339 | { | 361 | { |
340 | kmem_cache_free(cifs_inode_cachep, CIFS_I(inode)); | 362 | call_rcu(&inode->i_rcu, cifs_i_callback); |
341 | } | 363 | } |
342 | 364 | ||
343 | static void | 365 | static void |
@@ -351,18 +373,19 @@ cifs_evict_inode(struct inode *inode) | |||
351 | static void | 373 | static void |
352 | cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server) | 374 | cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server) |
353 | { | 375 | { |
376 | struct sockaddr_in *sa = (struct sockaddr_in *) &server->dstaddr; | ||
377 | struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) &server->dstaddr; | ||
378 | |||
354 | seq_printf(s, ",addr="); | 379 | seq_printf(s, ",addr="); |
355 | 380 | ||
356 | switch (server->addr.sockAddr.sin_family) { | 381 | switch (server->dstaddr.ss_family) { |
357 | case AF_INET: | 382 | case AF_INET: |
358 | seq_printf(s, "%pI4", &server->addr.sockAddr.sin_addr.s_addr); | 383 | seq_printf(s, "%pI4", &sa->sin_addr.s_addr); |
359 | break; | 384 | break; |
360 | case AF_INET6: | 385 | case AF_INET6: |
361 | seq_printf(s, "%pI6", | 386 | seq_printf(s, "%pI6", &sa6->sin6_addr.s6_addr); |
362 | &server->addr.sockAddr6.sin6_addr.s6_addr); | 387 | if (sa6->sin6_scope_id) |
363 | if (server->addr.sockAddr6.sin6_scope_id) | 388 | seq_printf(s, "%%%u", sa6->sin6_scope_id); |
364 | seq_printf(s, "%%%u", | ||
365 | server->addr.sockAddr6.sin6_scope_id); | ||
366 | break; | 389 | break; |
367 | default: | 390 | default: |
368 | seq_printf(s, "(unknown)"); | 391 | seq_printf(s, "(unknown)"); |
@@ -577,10 +600,17 @@ static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | |||
577 | { | 600 | { |
578 | struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode; | 601 | struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode; |
579 | ssize_t written; | 602 | ssize_t written; |
603 | int rc; | ||
580 | 604 | ||
581 | written = generic_file_aio_write(iocb, iov, nr_segs, pos); | 605 | written = generic_file_aio_write(iocb, iov, nr_segs, pos); |
582 | if (!CIFS_I(inode)->clientCanCacheAll) | 606 | |
583 | filemap_fdatawrite(inode->i_mapping); | 607 | if (CIFS_I(inode)->clientCanCacheAll) |
608 | return written; | ||
609 | |||
610 | rc = filemap_fdatawrite(inode->i_mapping); | ||
611 | if (rc) | ||
612 | cFYI(1, "cifs_file_aio_write: %d rc on %p inode", rc, inode); | ||
613 | |||
584 | return written; | 614 | return written; |
585 | } | 615 | } |
586 | 616 | ||
@@ -710,6 +740,25 @@ const struct file_operations cifs_file_ops = { | |||
710 | .setlease = cifs_setlease, | 740 | .setlease = cifs_setlease, |
711 | }; | 741 | }; |
712 | 742 | ||
743 | const struct file_operations cifs_file_strict_ops = { | ||
744 | .read = do_sync_read, | ||
745 | .write = do_sync_write, | ||
746 | .aio_read = cifs_strict_readv, | ||
747 | .aio_write = cifs_strict_writev, | ||
748 | .open = cifs_open, | ||
749 | .release = cifs_close, | ||
750 | .lock = cifs_lock, | ||
751 | .fsync = cifs_strict_fsync, | ||
752 | .flush = cifs_flush, | ||
753 | .mmap = cifs_file_strict_mmap, | ||
754 | .splice_read = generic_file_splice_read, | ||
755 | .llseek = cifs_llseek, | ||
756 | #ifdef CONFIG_CIFS_POSIX | ||
757 | .unlocked_ioctl = cifs_ioctl, | ||
758 | #endif /* CONFIG_CIFS_POSIX */ | ||
759 | .setlease = cifs_setlease, | ||
760 | }; | ||
761 | |||
713 | const struct file_operations cifs_file_direct_ops = { | 762 | const struct file_operations cifs_file_direct_ops = { |
714 | /* no aio, no readv - | 763 | /* no aio, no readv - |
715 | BB reevaluate whether they can be done with directio, no cache */ | 764 | BB reevaluate whether they can be done with directio, no cache */ |
@@ -728,6 +777,7 @@ const struct file_operations cifs_file_direct_ops = { | |||
728 | .llseek = cifs_llseek, | 777 | .llseek = cifs_llseek, |
729 | .setlease = cifs_setlease, | 778 | .setlease = cifs_setlease, |
730 | }; | 779 | }; |
780 | |||
731 | const struct file_operations cifs_file_nobrl_ops = { | 781 | const struct file_operations cifs_file_nobrl_ops = { |
732 | .read = do_sync_read, | 782 | .read = do_sync_read, |
733 | .write = do_sync_write, | 783 | .write = do_sync_write, |
@@ -746,6 +796,24 @@ const struct file_operations cifs_file_nobrl_ops = { | |||
746 | .setlease = cifs_setlease, | 796 | .setlease = cifs_setlease, |
747 | }; | 797 | }; |
748 | 798 | ||
799 | const struct file_operations cifs_file_strict_nobrl_ops = { | ||
800 | .read = do_sync_read, | ||
801 | .write = do_sync_write, | ||
802 | .aio_read = cifs_strict_readv, | ||
803 | .aio_write = cifs_strict_writev, | ||
804 | .open = cifs_open, | ||
805 | .release = cifs_close, | ||
806 | .fsync = cifs_strict_fsync, | ||
807 | .flush = cifs_flush, | ||
808 | .mmap = cifs_file_strict_mmap, | ||
809 | .splice_read = generic_file_splice_read, | ||
810 | .llseek = cifs_llseek, | ||
811 | #ifdef CONFIG_CIFS_POSIX | ||
812 | .unlocked_ioctl = cifs_ioctl, | ||
813 | #endif /* CONFIG_CIFS_POSIX */ | ||
814 | .setlease = cifs_setlease, | ||
815 | }; | ||
816 | |||
749 | const struct file_operations cifs_file_direct_nobrl_ops = { | 817 | const struct file_operations cifs_file_direct_nobrl_ops = { |
750 | /* no mmap, no aio, no readv - | 818 | /* no mmap, no aio, no readv - |
751 | BB reevaluate whether they can be done with directio, no cache */ | 819 | BB reevaluate whether they can be done with directio, no cache */ |
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 897b2b2b28b5..a9371b6578c0 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
@@ -61,6 +61,7 @@ extern int cifs_rename(struct inode *, struct dentry *, struct inode *, | |||
61 | struct dentry *); | 61 | struct dentry *); |
62 | extern int cifs_revalidate_file(struct file *filp); | 62 | extern int cifs_revalidate_file(struct file *filp); |
63 | extern int cifs_revalidate_dentry(struct dentry *); | 63 | extern int cifs_revalidate_dentry(struct dentry *); |
64 | extern void cifs_invalidate_mapping(struct inode *inode); | ||
64 | extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *); | 65 | extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *); |
65 | extern int cifs_setattr(struct dentry *, struct iattr *); | 66 | extern int cifs_setattr(struct dentry *, struct iattr *); |
66 | 67 | ||
@@ -72,19 +73,27 @@ extern const struct inode_operations cifs_dfs_referral_inode_operations; | |||
72 | /* Functions related to files and directories */ | 73 | /* Functions related to files and directories */ |
73 | extern const struct file_operations cifs_file_ops; | 74 | extern const struct file_operations cifs_file_ops; |
74 | extern const struct file_operations cifs_file_direct_ops; /* if directio mnt */ | 75 | extern const struct file_operations cifs_file_direct_ops; /* if directio mnt */ |
75 | extern const struct file_operations cifs_file_nobrl_ops; | 76 | extern const struct file_operations cifs_file_strict_ops; /* if strictio mnt */ |
76 | extern const struct file_operations cifs_file_direct_nobrl_ops; /* no brlocks */ | 77 | extern const struct file_operations cifs_file_nobrl_ops; /* no brlocks */ |
78 | extern const struct file_operations cifs_file_direct_nobrl_ops; | ||
79 | extern const struct file_operations cifs_file_strict_nobrl_ops; | ||
77 | extern int cifs_open(struct inode *inode, struct file *file); | 80 | extern int cifs_open(struct inode *inode, struct file *file); |
78 | extern int cifs_close(struct inode *inode, struct file *file); | 81 | extern int cifs_close(struct inode *inode, struct file *file); |
79 | extern int cifs_closedir(struct inode *inode, struct file *file); | 82 | extern int cifs_closedir(struct inode *inode, struct file *file); |
80 | extern ssize_t cifs_user_read(struct file *file, char __user *read_data, | 83 | extern ssize_t cifs_user_read(struct file *file, char __user *read_data, |
81 | size_t read_size, loff_t *poffset); | 84 | size_t read_size, loff_t *poffset); |
85 | extern ssize_t cifs_strict_readv(struct kiocb *iocb, const struct iovec *iov, | ||
86 | unsigned long nr_segs, loff_t pos); | ||
82 | extern ssize_t cifs_user_write(struct file *file, const char __user *write_data, | 87 | extern ssize_t cifs_user_write(struct file *file, const char __user *write_data, |
83 | size_t write_size, loff_t *poffset); | 88 | size_t write_size, loff_t *poffset); |
89 | extern ssize_t cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov, | ||
90 | unsigned long nr_segs, loff_t pos); | ||
84 | extern int cifs_lock(struct file *, int, struct file_lock *); | 91 | extern int cifs_lock(struct file *, int, struct file_lock *); |
85 | extern int cifs_fsync(struct file *, int); | 92 | extern int cifs_fsync(struct file *, int); |
93 | extern int cifs_strict_fsync(struct file *, int); | ||
86 | extern int cifs_flush(struct file *, fl_owner_t id); | 94 | extern int cifs_flush(struct file *, fl_owner_t id); |
87 | extern int cifs_file_mmap(struct file * , struct vm_area_struct *); | 95 | extern int cifs_file_mmap(struct file * , struct vm_area_struct *); |
96 | extern int cifs_file_strict_mmap(struct file * , struct vm_area_struct *); | ||
88 | extern const struct file_operations cifs_dir_ops; | 97 | extern const struct file_operations cifs_dir_ops; |
89 | extern int cifs_dir_open(struct inode *inode, struct file *file); | 98 | extern int cifs_dir_open(struct inode *inode, struct file *file); |
90 | extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir); | 99 | extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir); |
@@ -93,6 +102,12 @@ extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir); | |||
93 | extern const struct dentry_operations cifs_dentry_ops; | 102 | extern const struct dentry_operations cifs_dentry_ops; |
94 | extern const struct dentry_operations cifs_ci_dentry_ops; | 103 | extern const struct dentry_operations cifs_ci_dentry_ops; |
95 | 104 | ||
105 | #ifdef CONFIG_CIFS_DFS_UPCALL | ||
106 | extern struct vfsmount *cifs_dfs_d_automount(struct path *path); | ||
107 | #else | ||
108 | #define cifs_dfs_d_automount NULL | ||
109 | #endif | ||
110 | |||
96 | /* Functions related to symlinks */ | 111 | /* Functions related to symlinks */ |
97 | extern void *cifs_follow_link(struct dentry *direntry, struct nameidata *nd); | 112 | extern void *cifs_follow_link(struct dentry *direntry, struct nameidata *nd); |
98 | extern void cifs_put_link(struct dentry *direntry, | 113 | extern void cifs_put_link(struct dentry *direntry, |
@@ -112,5 +127,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); | |||
112 | extern const struct export_operations cifs_export_ops; | 127 | extern const struct export_operations cifs_export_ops; |
113 | #endif /* EXPERIMENTAL */ | 128 | #endif /* EXPERIMENTAL */ |
114 | 129 | ||
115 | #define CIFS_VERSION "1.68" | 130 | #define CIFS_VERSION "1.71" |
116 | #endif /* _CIFSFS_H */ | 131 | #endif /* _CIFSFS_H */ |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 7136c0c3e2f9..17afb0fbcaed 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -161,72 +161,97 @@ struct TCP_Server_Info { | |||
161 | int srv_count; /* reference counter */ | 161 | int srv_count; /* reference counter */ |
162 | /* 15 character server name + 0x20 16th byte indicating type = srv */ | 162 | /* 15 character server name + 0x20 16th byte indicating type = srv */ |
163 | char server_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL]; | 163 | char server_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL]; |
164 | enum statusEnum tcpStatus; /* what we think the status is */ | ||
164 | char *hostname; /* hostname portion of UNC string */ | 165 | char *hostname; /* hostname portion of UNC string */ |
165 | struct socket *ssocket; | 166 | struct socket *ssocket; |
166 | union { | 167 | struct sockaddr_storage dstaddr; |
167 | struct sockaddr_in sockAddr; | ||
168 | struct sockaddr_in6 sockAddr6; | ||
169 | } addr; | ||
170 | struct sockaddr_storage srcaddr; /* locally bind to this IP */ | 168 | struct sockaddr_storage srcaddr; /* locally bind to this IP */ |
169 | #ifdef CONFIG_NET_NS | ||
170 | struct net *net; | ||
171 | #endif | ||
171 | wait_queue_head_t response_q; | 172 | wait_queue_head_t response_q; |
172 | wait_queue_head_t request_q; /* if more than maxmpx to srvr must block*/ | 173 | wait_queue_head_t request_q; /* if more than maxmpx to srvr must block*/ |
173 | struct list_head pending_mid_q; | 174 | struct list_head pending_mid_q; |
174 | void *Server_NlsInfo; /* BB - placeholder for future NLS info */ | ||
175 | unsigned short server_codepage; /* codepage for the server */ | ||
176 | enum protocolEnum protocolType; | ||
177 | char versionMajor; | ||
178 | char versionMinor; | ||
179 | bool svlocal:1; /* local server or remote */ | ||
180 | bool noblocksnd; /* use blocking sendmsg */ | 175 | bool noblocksnd; /* use blocking sendmsg */ |
181 | bool noautotune; /* do not autotune send buf sizes */ | 176 | bool noautotune; /* do not autotune send buf sizes */ |
182 | bool tcp_nodelay; | 177 | bool tcp_nodelay; |
183 | atomic_t inFlight; /* number of requests on the wire to server */ | 178 | atomic_t inFlight; /* number of requests on the wire to server */ |
184 | #ifdef CONFIG_CIFS_STATS2 | ||
185 | atomic_t inSend; /* requests trying to send */ | ||
186 | atomic_t num_waiters; /* blocked waiting to get in sendrecv */ | ||
187 | #endif | ||
188 | enum statusEnum tcpStatus; /* what we think the status is */ | ||
189 | struct mutex srv_mutex; | 179 | struct mutex srv_mutex; |
190 | struct task_struct *tsk; | 180 | struct task_struct *tsk; |
191 | char server_GUID[16]; | 181 | char server_GUID[16]; |
192 | char secMode; | 182 | char secMode; |
183 | bool session_estab; /* mark when very first sess is established */ | ||
184 | u16 dialect; /* dialect index that server chose */ | ||
193 | enum securityEnum secType; | 185 | enum securityEnum secType; |
194 | unsigned int maxReq; /* Clients should submit no more */ | 186 | unsigned int maxReq; /* Clients should submit no more */ |
195 | /* than maxReq distinct unanswered SMBs to the server when using */ | 187 | /* than maxReq distinct unanswered SMBs to the server when using */ |
196 | /* multiplexed reads or writes */ | 188 | /* multiplexed reads or writes */ |
197 | unsigned int maxBuf; /* maxBuf specifies the maximum */ | 189 | unsigned int maxBuf; /* maxBuf specifies the maximum */ |
198 | /* message size the server can send or receive for non-raw SMBs */ | 190 | /* message size the server can send or receive for non-raw SMBs */ |
191 | /* maxBuf is returned by SMB NegotiateProtocol so maxBuf is only 0 */ | ||
192 | /* when socket is setup (and during reconnect) before NegProt sent */ | ||
199 | unsigned int max_rw; /* maxRw specifies the maximum */ | 193 | unsigned int max_rw; /* maxRw specifies the maximum */ |
200 | /* message size the server can send or receive for */ | 194 | /* message size the server can send or receive for */ |
201 | /* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */ | 195 | /* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */ |
202 | unsigned int max_vcs; /* maximum number of smb sessions, at least | 196 | unsigned int max_vcs; /* maximum number of smb sessions, at least |
203 | those that can be specified uniquely with | 197 | those that can be specified uniquely with |
204 | vcnumbers */ | 198 | vcnumbers */ |
205 | char sessid[4]; /* unique token id for this session */ | ||
206 | /* (returned on Negotiate */ | ||
207 | int capabilities; /* allow selective disabling of caps by smb sess */ | 199 | int capabilities; /* allow selective disabling of caps by smb sess */ |
208 | int timeAdj; /* Adjust for difference in server time zone in sec */ | 200 | int timeAdj; /* Adjust for difference in server time zone in sec */ |
209 | __u16 CurrentMid; /* multiplex id - rotating counter */ | 201 | __u16 CurrentMid; /* multiplex id - rotating counter */ |
210 | char cryptkey[CIFS_CRYPTO_KEY_SIZE]; /* used by ntlm, ntlmv2 etc */ | 202 | char cryptkey[CIFS_CRYPTO_KEY_SIZE]; /* used by ntlm, ntlmv2 etc */ |
211 | /* 16th byte of RFC1001 workstation name is always null */ | 203 | /* 16th byte of RFC1001 workstation name is always null */ |
212 | char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL]; | 204 | char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL]; |
213 | __u32 sequence_number; /* needed for CIFS PDU signature */ | 205 | __u32 sequence_number; /* for signing, protected by srv_mutex */ |
214 | struct session_key session_key; | 206 | struct session_key session_key; |
215 | unsigned long lstrp; /* when we got last response from this server */ | 207 | unsigned long lstrp; /* when we got last response from this server */ |
216 | u16 dialect; /* dialect index that server chose */ | ||
217 | struct cifs_secmech secmech; /* crypto sec mech functs, descriptors */ | 208 | struct cifs_secmech secmech; /* crypto sec mech functs, descriptors */ |
218 | /* extended security flavors that server supports */ | 209 | /* extended security flavors that server supports */ |
210 | bool sec_ntlmssp; /* supports NTLMSSP */ | ||
211 | bool sec_kerberosu2u; /* supports U2U Kerberos */ | ||
219 | bool sec_kerberos; /* supports plain Kerberos */ | 212 | bool sec_kerberos; /* supports plain Kerberos */ |
220 | bool sec_mskerberos; /* supports legacy MS Kerberos */ | 213 | bool sec_mskerberos; /* supports legacy MS Kerberos */ |
221 | bool sec_kerberosu2u; /* supports U2U Kerberos */ | 214 | struct delayed_work echo; /* echo ping workqueue job */ |
222 | bool sec_ntlmssp; /* supports NTLMSSP */ | ||
223 | bool session_estab; /* mark when very first sess is established */ | ||
224 | #ifdef CONFIG_CIFS_FSCACHE | 215 | #ifdef CONFIG_CIFS_FSCACHE |
225 | struct fscache_cookie *fscache; /* client index cache cookie */ | 216 | struct fscache_cookie *fscache; /* client index cache cookie */ |
226 | #endif | 217 | #endif |
218 | #ifdef CONFIG_CIFS_STATS2 | ||
219 | atomic_t inSend; /* requests trying to send */ | ||
220 | atomic_t num_waiters; /* blocked waiting to get in sendrecv */ | ||
221 | #endif | ||
227 | }; | 222 | }; |
228 | 223 | ||
229 | /* | 224 | /* |
225 | * Macros to allow the TCP_Server_Info->net field and related code to drop out | ||
226 | * when CONFIG_NET_NS isn't set. | ||
227 | */ | ||
228 | |||
229 | #ifdef CONFIG_NET_NS | ||
230 | |||
231 | static inline struct net *cifs_net_ns(struct TCP_Server_Info *srv) | ||
232 | { | ||
233 | return srv->net; | ||
234 | } | ||
235 | |||
236 | static inline void cifs_set_net_ns(struct TCP_Server_Info *srv, struct net *net) | ||
237 | { | ||
238 | srv->net = net; | ||
239 | } | ||
240 | |||
241 | #else | ||
242 | |||
243 | static inline struct net *cifs_net_ns(struct TCP_Server_Info *srv) | ||
244 | { | ||
245 | return &init_net; | ||
246 | } | ||
247 | |||
248 | static inline void cifs_set_net_ns(struct TCP_Server_Info *srv, struct net *net) | ||
249 | { | ||
250 | } | ||
251 | |||
252 | #endif | ||
253 | |||
254 | /* | ||
230 | * Session structure. One of these for each uid session with a particular host | 255 | * Session structure. One of these for each uid session with a particular host |
231 | */ | 256 | */ |
232 | struct cifsSesInfo { | 257 | struct cifsSesInfo { |
@@ -449,13 +474,14 @@ struct cifsInodeInfo { | |||
449 | /* BB add in lists for dirty pages i.e. write caching info for oplock */ | 474 | /* BB add in lists for dirty pages i.e. write caching info for oplock */ |
450 | struct list_head openFileList; | 475 | struct list_head openFileList; |
451 | __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */ | 476 | __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */ |
452 | unsigned long time; /* jiffies of last update/check of inode */ | 477 | bool clientCanCacheRead; /* read oplock */ |
453 | bool clientCanCacheRead:1; /* read oplock */ | 478 | bool clientCanCacheAll; /* read and writebehind oplock */ |
454 | bool clientCanCacheAll:1; /* read and writebehind oplock */ | 479 | bool delete_pending; /* DELETE_ON_CLOSE is set */ |
455 | bool delete_pending:1; /* DELETE_ON_CLOSE is set */ | 480 | bool invalid_mapping; /* pagecache is invalid */ |
456 | bool invalid_mapping:1; /* pagecache is invalid */ | 481 | unsigned long time; /* jiffies of last update of inode */ |
457 | u64 server_eof; /* current file size on server */ | 482 | u64 server_eof; /* current file size on server */ |
458 | u64 uniqueid; /* server inode number */ | 483 | u64 uniqueid; /* server inode number */ |
484 | u64 createtime; /* creation time on server */ | ||
459 | #ifdef CONFIG_CIFS_FSCACHE | 485 | #ifdef CONFIG_CIFS_FSCACHE |
460 | struct fscache_cookie *fscache; | 486 | struct fscache_cookie *fscache; |
461 | #endif | 487 | #endif |
@@ -510,6 +536,18 @@ static inline void cifs_stats_bytes_read(struct cifsTconInfo *tcon, | |||
510 | 536 | ||
511 | #endif | 537 | #endif |
512 | 538 | ||
539 | struct mid_q_entry; | ||
540 | |||
541 | /* | ||
542 | * This is the prototype for the mid callback function. When creating one, | ||
543 | * take special care to avoid deadlocks. Things to bear in mind: | ||
544 | * | ||
545 | * - it will be called by cifsd | ||
546 | * - the GlobalMid_Lock will be held | ||
547 | * - the mid will be removed from the pending_mid_q list | ||
548 | */ | ||
549 | typedef void (mid_callback_t)(struct mid_q_entry *mid); | ||
550 | |||
513 | /* one of these for every pending CIFS request to the server */ | 551 | /* one of these for every pending CIFS request to the server */ |
514 | struct mid_q_entry { | 552 | struct mid_q_entry { |
515 | struct list_head qhead; /* mids waiting on reply from this server */ | 553 | struct list_head qhead; /* mids waiting on reply from this server */ |
@@ -521,7 +559,8 @@ struct mid_q_entry { | |||
521 | unsigned long when_sent; /* time when smb send finished */ | 559 | unsigned long when_sent; /* time when smb send finished */ |
522 | unsigned long when_received; /* when demux complete (taken off wire) */ | 560 | unsigned long when_received; /* when demux complete (taken off wire) */ |
523 | #endif | 561 | #endif |
524 | struct task_struct *tsk; /* task waiting for response */ | 562 | mid_callback_t *callback; /* call completion callback */ |
563 | void *callback_data; /* general purpose pointer for callback */ | ||
525 | struct smb_hdr *resp_buf; /* response buffer */ | 564 | struct smb_hdr *resp_buf; /* response buffer */ |
526 | int midState; /* wish this were enum but can not pass to wait_event */ | 565 | int midState; /* wish this were enum but can not pass to wait_event */ |
527 | __u8 command; /* smb command code */ | 566 | __u8 command; /* smb command code */ |
@@ -576,6 +615,7 @@ struct cifs_fattr { | |||
576 | u64 cf_uniqueid; | 615 | u64 cf_uniqueid; |
577 | u64 cf_eof; | 616 | u64 cf_eof; |
578 | u64 cf_bytes; | 617 | u64 cf_bytes; |
618 | u64 cf_createtime; | ||
579 | uid_t cf_uid; | 619 | uid_t cf_uid; |
580 | gid_t cf_gid; | 620 | gid_t cf_gid; |
581 | umode_t cf_mode; | 621 | umode_t cf_mode; |
@@ -614,7 +654,7 @@ static inline void free_dfs_info_array(struct dfs_info3_param *param, | |||
614 | #define MID_REQUEST_SUBMITTED 2 | 654 | #define MID_REQUEST_SUBMITTED 2 |
615 | #define MID_RESPONSE_RECEIVED 4 | 655 | #define MID_RESPONSE_RECEIVED 4 |
616 | #define MID_RETRY_NEEDED 8 /* session closed while this request out */ | 656 | #define MID_RETRY_NEEDED 8 /* session closed while this request out */ |
617 | #define MID_NO_RESP_NEEDED 0x10 | 657 | #define MID_RESPONSE_MALFORMED 0x10 |
618 | 658 | ||
619 | /* Types of response buffer returned from SendReceive2 */ | 659 | /* Types of response buffer returned from SendReceive2 */ |
620 | #define CIFS_NO_BUFFER 0 /* Response buffer not returned */ | 660 | #define CIFS_NO_BUFFER 0 /* Response buffer not returned */ |
@@ -623,12 +663,9 @@ static inline void free_dfs_info_array(struct dfs_info3_param *param, | |||
623 | #define CIFS_IOVEC 4 /* array of response buffers */ | 663 | #define CIFS_IOVEC 4 /* array of response buffers */ |
624 | 664 | ||
625 | /* Type of Request to SendReceive2 */ | 665 | /* Type of Request to SendReceive2 */ |
626 | #define CIFS_STD_OP 0 /* normal request timeout */ | 666 | #define CIFS_BLOCKING_OP 1 /* operation can block */ |
627 | #define CIFS_LONG_OP 1 /* long op (up to 45 sec, oplock time) */ | 667 | #define CIFS_ASYNC_OP 2 /* do not wait for response */ |
628 | #define CIFS_VLONG_OP 2 /* sloow op - can take up to 180 seconds */ | 668 | #define CIFS_TIMEOUT_MASK 0x003 /* only one of above set in req */ |
629 | #define CIFS_BLOCKING_OP 4 /* operation can block */ | ||
630 | #define CIFS_ASYNC_OP 8 /* do not wait for response */ | ||
631 | #define CIFS_TIMEOUT_MASK 0x00F /* only one of 5 above set in req */ | ||
632 | #define CIFS_LOG_ERROR 0x010 /* log NT STATUS if non-zero */ | 669 | #define CIFS_LOG_ERROR 0x010 /* log NT STATUS if non-zero */ |
633 | #define CIFS_LARGE_BUF_OP 0x020 /* large request buffer */ | 670 | #define CIFS_LARGE_BUF_OP 0x020 /* large request buffer */ |
634 | #define CIFS_NO_RESP 0x040 /* no response buffer required */ | 671 | #define CIFS_NO_RESP 0x040 /* no response buffer required */ |
@@ -791,6 +828,9 @@ GLOBAL_EXTERN unsigned int cifs_min_rcv; /* min size of big ntwrk buf pool */ | |||
791 | GLOBAL_EXTERN unsigned int cifs_min_small; /* min size of small buf pool */ | 828 | GLOBAL_EXTERN unsigned int cifs_min_small; /* min size of small buf pool */ |
792 | GLOBAL_EXTERN unsigned int cifs_max_pending; /* MAX requests at once to server*/ | 829 | GLOBAL_EXTERN unsigned int cifs_max_pending; /* MAX requests at once to server*/ |
793 | 830 | ||
831 | /* reconnect after this many failed echo attempts */ | ||
832 | GLOBAL_EXTERN unsigned short echo_retries; | ||
833 | |||
794 | void cifs_oplock_break(struct work_struct *work); | 834 | void cifs_oplock_break(struct work_struct *work); |
795 | void cifs_oplock_break_get(struct cifsFileInfo *cfile); | 835 | void cifs_oplock_break_get(struct cifsFileInfo *cfile); |
796 | void cifs_oplock_break_put(struct cifsFileInfo *cfile); | 836 | void cifs_oplock_break_put(struct cifsFileInfo *cfile); |
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index de36b09763a8..b5c8cc5d7a7f 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
@@ -23,6 +23,7 @@ | |||
23 | #define _CIFSPDU_H | 23 | #define _CIFSPDU_H |
24 | 24 | ||
25 | #include <net/sock.h> | 25 | #include <net/sock.h> |
26 | #include <asm/unaligned.h> | ||
26 | #include "smbfsctl.h" | 27 | #include "smbfsctl.h" |
27 | 28 | ||
28 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | 29 | #ifdef CONFIG_CIFS_WEAK_PW_HASH |
@@ -50,6 +51,7 @@ | |||
50 | #define SMB_COM_SETATTR 0x09 /* trivial response */ | 51 | #define SMB_COM_SETATTR 0x09 /* trivial response */ |
51 | #define SMB_COM_LOCKING_ANDX 0x24 /* trivial response */ | 52 | #define SMB_COM_LOCKING_ANDX 0x24 /* trivial response */ |
52 | #define SMB_COM_COPY 0x29 /* trivial rsp, fail filename ignrd*/ | 53 | #define SMB_COM_COPY 0x29 /* trivial rsp, fail filename ignrd*/ |
54 | #define SMB_COM_ECHO 0x2B /* echo request */ | ||
53 | #define SMB_COM_OPEN_ANDX 0x2D /* Legacy open for old servers */ | 55 | #define SMB_COM_OPEN_ANDX 0x2D /* Legacy open for old servers */ |
54 | #define SMB_COM_READ_ANDX 0x2E | 56 | #define SMB_COM_READ_ANDX 0x2E |
55 | #define SMB_COM_WRITE_ANDX 0x2F | 57 | #define SMB_COM_WRITE_ANDX 0x2F |
@@ -425,11 +427,49 @@ struct smb_hdr { | |||
425 | __u16 Mid; | 427 | __u16 Mid; |
426 | __u8 WordCount; | 428 | __u8 WordCount; |
427 | } __attribute__((packed)); | 429 | } __attribute__((packed)); |
428 | /* given a pointer to an smb_hdr retrieve the value of byte count */ | 430 | |
429 | #define BCC(smb_var) (*(__u16 *)((char *)(smb_var) + sizeof(struct smb_hdr) + (2 * (smb_var)->WordCount))) | 431 | /* given a pointer to an smb_hdr retrieve a char pointer to the byte count */ |
430 | #define BCC_LE(smb_var) (*(__le16 *)((char *)(smb_var) + sizeof(struct smb_hdr) + (2 * (smb_var)->WordCount))) | 432 | #define BCC(smb_var) ((unsigned char *)(smb_var) + sizeof(struct smb_hdr) + \ |
433 | (2 * (smb_var)->WordCount)) | ||
434 | |||
431 | /* given a pointer to an smb_hdr retrieve the pointer to the byte area */ | 435 | /* given a pointer to an smb_hdr retrieve the pointer to the byte area */ |
432 | #define pByteArea(smb_var) ((unsigned char *)(smb_var) + sizeof(struct smb_hdr) + (2 * (smb_var)->WordCount) + 2) | 436 | #define pByteArea(smb_var) (BCC(smb_var) + 2) |
437 | |||
438 | /* get the converted ByteCount for a SMB packet and return it */ | ||
439 | static inline __u16 | ||
440 | get_bcc(struct smb_hdr *hdr) | ||
441 | { | ||
442 | __u16 *bc_ptr = (__u16 *)BCC(hdr); | ||
443 | |||
444 | return get_unaligned(bc_ptr); | ||
445 | } | ||
446 | |||
447 | /* get the unconverted ByteCount for a SMB packet and return it */ | ||
448 | static inline __u16 | ||
449 | get_bcc_le(struct smb_hdr *hdr) | ||
450 | { | ||
451 | __le16 *bc_ptr = (__le16 *)BCC(hdr); | ||
452 | |||
453 | return get_unaligned_le16(bc_ptr); | ||
454 | } | ||
455 | |||
456 | /* set the ByteCount for a SMB packet in host-byte order */ | ||
457 | static inline void | ||
458 | put_bcc(__u16 count, struct smb_hdr *hdr) | ||
459 | { | ||
460 | __u16 *bc_ptr = (__u16 *)BCC(hdr); | ||
461 | |||
462 | put_unaligned(count, bc_ptr); | ||
463 | } | ||
464 | |||
465 | /* set the ByteCount for a SMB packet in little-endian */ | ||
466 | static inline void | ||
467 | put_bcc_le(__u16 count, struct smb_hdr *hdr) | ||
468 | { | ||
469 | __le16 *bc_ptr = (__le16 *)BCC(hdr); | ||
470 | |||
471 | put_unaligned_le16(count, bc_ptr); | ||
472 | } | ||
433 | 473 | ||
434 | /* | 474 | /* |
435 | * Computer Name Length (since Netbios name was length 16 with last byte 0x20) | 475 | * Computer Name Length (since Netbios name was length 16 with last byte 0x20) |
@@ -760,6 +800,20 @@ typedef struct smb_com_tconx_rsp_ext { | |||
760 | * | 800 | * |
761 | */ | 801 | */ |
762 | 802 | ||
803 | typedef struct smb_com_echo_req { | ||
804 | struct smb_hdr hdr; | ||
805 | __le16 EchoCount; | ||
806 | __le16 ByteCount; | ||
807 | char Data[1]; | ||
808 | } __attribute__((packed)) ECHO_REQ; | ||
809 | |||
810 | typedef struct smb_com_echo_rsp { | ||
811 | struct smb_hdr hdr; | ||
812 | __le16 SequenceNumber; | ||
813 | __le16 ByteCount; | ||
814 | char Data[1]; | ||
815 | } __attribute__((packed)) ECHO_RSP; | ||
816 | |||
763 | typedef struct smb_com_logoff_andx_req { | 817 | typedef struct smb_com_logoff_andx_req { |
764 | struct smb_hdr hdr; /* wct = 2 */ | 818 | struct smb_hdr hdr; /* wct = 2 */ |
765 | __u8 AndXCommand; | 819 | __u8 AndXCommand; |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index e6d1481b16c1..8096f27ad9a8 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -61,6 +61,12 @@ extern char *cifs_compose_mount_options(const char *sb_mountdata, | |||
61 | const char *fullpath, const struct dfs_info3_param *ref, | 61 | const char *fullpath, const struct dfs_info3_param *ref, |
62 | char **devname); | 62 | char **devname); |
63 | /* extern void renew_parental_timestamps(struct dentry *direntry);*/ | 63 | /* extern void renew_parental_timestamps(struct dentry *direntry);*/ |
64 | extern struct mid_q_entry *AllocMidQEntry(const struct smb_hdr *smb_buffer, | ||
65 | struct TCP_Server_Info *server); | ||
66 | extern void DeleteMidQEntry(struct mid_q_entry *midEntry); | ||
67 | extern int cifs_call_async(struct TCP_Server_Info *server, | ||
68 | struct smb_hdr *in_buf, mid_callback_t *callback, | ||
69 | void *cbdata); | ||
64 | extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *, | 70 | extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *, |
65 | struct smb_hdr * /* input */ , | 71 | struct smb_hdr * /* input */ , |
66 | struct smb_hdr * /* out */ , | 72 | struct smb_hdr * /* out */ , |
@@ -79,6 +85,8 @@ extern int checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length); | |||
79 | extern bool is_valid_oplock_break(struct smb_hdr *smb, | 85 | extern bool is_valid_oplock_break(struct smb_hdr *smb, |
80 | struct TCP_Server_Info *); | 86 | struct TCP_Server_Info *); |
81 | extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof); | 87 | extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof); |
88 | extern void cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset, | ||
89 | unsigned int bytes_written); | ||
82 | extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, bool); | 90 | extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, bool); |
83 | extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool); | 91 | extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool); |
84 | extern unsigned int smbCalcSize(struct smb_hdr *ptr); | 92 | extern unsigned int smbCalcSize(struct smb_hdr *ptr); |
@@ -347,12 +355,13 @@ extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | |||
347 | const __u16 netfid, const __u64 len, | 355 | const __u16 netfid, const __u64 len, |
348 | const __u64 offset, const __u32 numUnlock, | 356 | const __u64 offset, const __u32 numUnlock, |
349 | const __u32 numLock, const __u8 lockType, | 357 | const __u32 numLock, const __u8 lockType, |
350 | const bool waitFlag); | 358 | const bool waitFlag, const __u8 oplock_level); |
351 | extern int CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, | 359 | extern int CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, |
352 | const __u16 smb_file_id, const int get_flag, | 360 | const __u16 smb_file_id, const int get_flag, |
353 | const __u64 len, struct file_lock *, | 361 | const __u64 len, struct file_lock *, |
354 | const __u16 lock_type, const bool waitFlag); | 362 | const __u16 lock_type, const bool waitFlag); |
355 | extern int CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon); | 363 | extern int CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon); |
364 | extern int CIFSSMBEcho(struct TCP_Server_Info *server); | ||
356 | extern int CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses); | 365 | extern int CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses); |
357 | 366 | ||
358 | extern struct cifsSesInfo *sesInfoAlloc(void); | 367 | extern struct cifsSesInfo *sesInfoAlloc(void); |
@@ -366,7 +375,7 @@ extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *, | |||
366 | extern int cifs_verify_signature(struct smb_hdr *, | 375 | extern int cifs_verify_signature(struct smb_hdr *, |
367 | struct TCP_Server_Info *server, | 376 | struct TCP_Server_Info *server, |
368 | __u32 expected_sequence_number); | 377 | __u32 expected_sequence_number); |
369 | extern void SMBNTencrypt(unsigned char *, unsigned char *, unsigned char *); | 378 | extern int SMBNTencrypt(unsigned char *, unsigned char *, unsigned char *); |
370 | extern int setup_ntlm_response(struct cifsSesInfo *); | 379 | extern int setup_ntlm_response(struct cifsSesInfo *); |
371 | extern int setup_ntlmv2_rsp(struct cifsSesInfo *, const struct nls_table *); | 380 | extern int setup_ntlmv2_rsp(struct cifsSesInfo *, const struct nls_table *); |
372 | extern int cifs_crypto_shash_allocate(struct TCP_Server_Info *); | 381 | extern int cifs_crypto_shash_allocate(struct TCP_Server_Info *); |
@@ -416,4 +425,11 @@ extern bool CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr); | |||
416 | extern int CIFSCheckMFSymlink(struct cifs_fattr *fattr, | 425 | extern int CIFSCheckMFSymlink(struct cifs_fattr *fattr, |
417 | const unsigned char *path, | 426 | const unsigned char *path, |
418 | struct cifs_sb_info *cifs_sb, int xid); | 427 | struct cifs_sb_info *cifs_sb, int xid); |
428 | extern int mdfour(unsigned char *, unsigned char *, int); | ||
429 | extern int E_md4hash(const unsigned char *passwd, unsigned char *p16); | ||
430 | extern void SMBencrypt(unsigned char *passwd, const unsigned char *c8, | ||
431 | unsigned char *p24); | ||
432 | extern void E_P16(unsigned char *p14, unsigned char *p16); | ||
433 | extern void E_P24(unsigned char *p21, const unsigned char *c8, | ||
434 | unsigned char *p24); | ||
419 | #endif /* _CIFSPROTO_H */ | 435 | #endif /* _CIFSPROTO_H */ |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 67acfb3acad2..904aa47e3515 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -136,9 +136,6 @@ cifs_reconnect_tcon(struct cifsTconInfo *tcon, int smb_command) | |||
136 | } | 136 | } |
137 | } | 137 | } |
138 | 138 | ||
139 | if (ses->status == CifsExiting) | ||
140 | return -EIO; | ||
141 | |||
142 | /* | 139 | /* |
143 | * Give demultiplex thread up to 10 seconds to reconnect, should be | 140 | * Give demultiplex thread up to 10 seconds to reconnect, should be |
144 | * greater than cifs socket timeout which is 7 seconds | 141 | * greater than cifs socket timeout which is 7 seconds |
@@ -156,7 +153,7 @@ cifs_reconnect_tcon(struct cifsTconInfo *tcon, int smb_command) | |||
156 | * retrying until process is killed or server comes | 153 | * retrying until process is killed or server comes |
157 | * back on-line | 154 | * back on-line |
158 | */ | 155 | */ |
159 | if (!tcon->retry || ses->status == CifsExiting) { | 156 | if (!tcon->retry) { |
160 | cFYI(1, "gave up waiting on reconnect in smb_init"); | 157 | cFYI(1, "gave up waiting on reconnect in smb_init"); |
161 | return -EHOSTDOWN; | 158 | return -EHOSTDOWN; |
162 | } | 159 | } |
@@ -331,37 +328,35 @@ smb_init_no_reconnect(int smb_command, int wct, struct cifsTconInfo *tcon, | |||
331 | 328 | ||
332 | static int validate_t2(struct smb_t2_rsp *pSMB) | 329 | static int validate_t2(struct smb_t2_rsp *pSMB) |
333 | { | 330 | { |
334 | int rc = -EINVAL; | 331 | unsigned int total_size; |
335 | int total_size; | 332 | |
336 | char *pBCC; | 333 | /* check for plausible wct */ |
334 | if (pSMB->hdr.WordCount < 10) | ||
335 | goto vt2_err; | ||
337 | 336 | ||
338 | /* check for plausible wct, bcc and t2 data and parm sizes */ | ||
339 | /* check for parm and data offset going beyond end of smb */ | 337 | /* check for parm and data offset going beyond end of smb */ |
340 | if (pSMB->hdr.WordCount >= 10) { | 338 | if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 || |
341 | if ((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) && | 339 | get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024) |
342 | (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) { | 340 | goto vt2_err; |
343 | /* check that bcc is at least as big as parms + data */ | 341 | |
344 | /* check that bcc is less than negotiated smb buffer */ | 342 | /* check that bcc is at least as big as parms + data */ |
345 | total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount); | 343 | /* check that bcc is less than negotiated smb buffer */ |
346 | if (total_size < 512) { | 344 | total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount); |
347 | total_size += | 345 | if (total_size >= 512) |
348 | le16_to_cpu(pSMB->t2_rsp.DataCount); | 346 | goto vt2_err; |
349 | /* BCC le converted in SendReceive */ | 347 | |
350 | pBCC = (pSMB->hdr.WordCount * 2) + | 348 | total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount); |
351 | sizeof(struct smb_hdr) + | 349 | if (total_size > get_bcc(&pSMB->hdr) || |
352 | (char *)pSMB; | 350 | total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) |
353 | if ((total_size <= (*(u16 *)pBCC)) && | 351 | goto vt2_err; |
354 | (total_size < | 352 | |
355 | CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) { | 353 | return 0; |
356 | return 0; | 354 | vt2_err: |
357 | } | ||
358 | } | ||
359 | } | ||
360 | } | ||
361 | cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB, | 355 | cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB, |
362 | sizeof(struct smb_t2_rsp) + 16); | 356 | sizeof(struct smb_t2_rsp) + 16); |
363 | return rc; | 357 | return -EINVAL; |
364 | } | 358 | } |
359 | |||
365 | int | 360 | int |
366 | CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | 361 | CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) |
367 | { | 362 | { |
@@ -401,15 +396,12 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
401 | else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) { | 396 | else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) { |
402 | cFYI(1, "Kerberos only mechanism, enable extended security"); | 397 | cFYI(1, "Kerberos only mechanism, enable extended security"); |
403 | pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; | 398 | pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; |
404 | } | 399 | } else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP) |
405 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
406 | else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP) | ||
407 | pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; | 400 | pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; |
408 | else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) { | 401 | else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) { |
409 | cFYI(1, "NTLMSSP only mechanism, enable extended security"); | 402 | cFYI(1, "NTLMSSP only mechanism, enable extended security"); |
410 | pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; | 403 | pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; |
411 | } | 404 | } |
412 | #endif | ||
413 | 405 | ||
414 | count = 0; | 406 | count = 0; |
415 | for (i = 0; i < CIFS_NUM_PROT; i++) { | 407 | for (i = 0; i < CIFS_NUM_PROT; i++) { |
@@ -455,7 +447,6 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
455 | server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize), | 447 | server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize), |
456 | (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); | 448 | (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); |
457 | server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs); | 449 | server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs); |
458 | GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey); | ||
459 | /* even though we do not use raw we might as well set this | 450 | /* even though we do not use raw we might as well set this |
460 | accurately, in case we ever find a need for it */ | 451 | accurately, in case we ever find a need for it */ |
461 | if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) { | 452 | if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) { |
@@ -569,7 +560,6 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
569 | (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); | 560 | (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); |
570 | server->max_rw = le32_to_cpu(pSMBr->MaxRawSize); | 561 | server->max_rw = le32_to_cpu(pSMBr->MaxRawSize); |
571 | cFYI(DBG2, "Max buf = %d", ses->server->maxBuf); | 562 | cFYI(DBG2, "Max buf = %d", ses->server->maxBuf); |
572 | GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey); | ||
573 | server->capabilities = le32_to_cpu(pSMBr->Capabilities); | 563 | server->capabilities = le32_to_cpu(pSMBr->Capabilities); |
574 | server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone); | 564 | server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone); |
575 | server->timeAdj *= 60; | 565 | server->timeAdj *= 60; |
@@ -709,6 +699,53 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon) | |||
709 | return rc; | 699 | return rc; |
710 | } | 700 | } |
711 | 701 | ||
702 | /* | ||
703 | * This is a no-op for now. We're not really interested in the reply, but | ||
704 | * rather in the fact that the server sent one and that server->lstrp | ||
705 | * gets updated. | ||
706 | * | ||
707 | * FIXME: maybe we should consider checking that the reply matches request? | ||
708 | */ | ||
709 | static void | ||
710 | cifs_echo_callback(struct mid_q_entry *mid) | ||
711 | { | ||
712 | struct TCP_Server_Info *server = mid->callback_data; | ||
713 | |||
714 | DeleteMidQEntry(mid); | ||
715 | atomic_dec(&server->inFlight); | ||
716 | wake_up(&server->request_q); | ||
717 | } | ||
718 | |||
719 | int | ||
720 | CIFSSMBEcho(struct TCP_Server_Info *server) | ||
721 | { | ||
722 | ECHO_REQ *smb; | ||
723 | int rc = 0; | ||
724 | |||
725 | cFYI(1, "In echo request"); | ||
726 | |||
727 | rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb); | ||
728 | if (rc) | ||
729 | return rc; | ||
730 | |||
731 | /* set up echo request */ | ||
732 | smb->hdr.Tid = cpu_to_le16(0xffff); | ||
733 | smb->hdr.WordCount = 1; | ||
734 | put_unaligned_le16(1, &smb->EchoCount); | ||
735 | put_bcc_le(1, &smb->hdr); | ||
736 | smb->Data[0] = 'a'; | ||
737 | smb->hdr.smb_buf_length += 3; | ||
738 | |||
739 | rc = cifs_call_async(server, (struct smb_hdr *)smb, | ||
740 | cifs_echo_callback, server); | ||
741 | if (rc) | ||
742 | cFYI(1, "Echo request failed: %d", rc); | ||
743 | |||
744 | cifs_small_buf_release(smb); | ||
745 | |||
746 | return rc; | ||
747 | } | ||
748 | |||
712 | int | 749 | int |
713 | CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) | 750 | CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) |
714 | { | 751 | { |
@@ -1196,7 +1233,7 @@ OldOpenRetry: | |||
1196 | pSMB->ByteCount = cpu_to_le16(count); | 1233 | pSMB->ByteCount = cpu_to_le16(count); |
1197 | /* long_op set to 1 to allow for oplock break timeouts */ | 1234 | /* long_op set to 1 to allow for oplock break timeouts */ |
1198 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1235 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
1199 | (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP); | 1236 | (struct smb_hdr *)pSMBr, &bytes_returned, 0); |
1200 | cifs_stats_inc(&tcon->num_opens); | 1237 | cifs_stats_inc(&tcon->num_opens); |
1201 | if (rc) { | 1238 | if (rc) { |
1202 | cFYI(1, "Error in Open = %d", rc); | 1239 | cFYI(1, "Error in Open = %d", rc); |
@@ -1309,7 +1346,7 @@ openRetry: | |||
1309 | pSMB->ByteCount = cpu_to_le16(count); | 1346 | pSMB->ByteCount = cpu_to_le16(count); |
1310 | /* long_op set to 1 to allow for oplock break timeouts */ | 1347 | /* long_op set to 1 to allow for oplock break timeouts */ |
1311 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1348 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
1312 | (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP); | 1349 | (struct smb_hdr *)pSMBr, &bytes_returned, 0); |
1313 | cifs_stats_inc(&tcon->num_opens); | 1350 | cifs_stats_inc(&tcon->num_opens); |
1314 | if (rc) { | 1351 | if (rc) { |
1315 | cFYI(1, "Error in Open = %d", rc); | 1352 | cFYI(1, "Error in Open = %d", rc); |
@@ -1391,7 +1428,7 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid, | |||
1391 | iov[0].iov_base = (char *)pSMB; | 1428 | iov[0].iov_base = (char *)pSMB; |
1392 | iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; | 1429 | iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; |
1393 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, | 1430 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, |
1394 | &resp_buf_type, CIFS_STD_OP | CIFS_LOG_ERROR); | 1431 | &resp_buf_type, CIFS_LOG_ERROR); |
1395 | cifs_stats_inc(&tcon->num_reads); | 1432 | cifs_stats_inc(&tcon->num_reads); |
1396 | pSMBr = (READ_RSP *)iov[0].iov_base; | 1433 | pSMBr = (READ_RSP *)iov[0].iov_base; |
1397 | if (rc) { | 1434 | if (rc) { |
@@ -1666,7 +1703,8 @@ int | |||
1666 | CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | 1703 | CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, |
1667 | const __u16 smb_file_id, const __u64 len, | 1704 | const __u16 smb_file_id, const __u64 len, |
1668 | const __u64 offset, const __u32 numUnlock, | 1705 | const __u64 offset, const __u32 numUnlock, |
1669 | const __u32 numLock, const __u8 lockType, const bool waitFlag) | 1706 | const __u32 numLock, const __u8 lockType, |
1707 | const bool waitFlag, const __u8 oplock_level) | ||
1670 | { | 1708 | { |
1671 | int rc = 0; | 1709 | int rc = 0; |
1672 | LOCK_REQ *pSMB = NULL; | 1710 | LOCK_REQ *pSMB = NULL; |
@@ -1694,6 +1732,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | |||
1694 | pSMB->NumberOfLocks = cpu_to_le16(numLock); | 1732 | pSMB->NumberOfLocks = cpu_to_le16(numLock); |
1695 | pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock); | 1733 | pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock); |
1696 | pSMB->LockType = lockType; | 1734 | pSMB->LockType = lockType; |
1735 | pSMB->OplockLevel = oplock_level; | ||
1697 | pSMB->AndXCommand = 0xFF; /* none */ | 1736 | pSMB->AndXCommand = 0xFF; /* none */ |
1698 | pSMB->Fid = smb_file_id; /* netfid stays le */ | 1737 | pSMB->Fid = smb_file_id; /* netfid stays le */ |
1699 | 1738 | ||
@@ -3090,7 +3129,7 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, | |||
3090 | iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; | 3129 | iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; |
3091 | 3130 | ||
3092 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, | 3131 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, |
3093 | CIFS_STD_OP); | 3132 | 0); |
3094 | cifs_stats_inc(&tcon->num_acl_get); | 3133 | cifs_stats_inc(&tcon->num_acl_get); |
3095 | if (rc) { | 3134 | if (rc) { |
3096 | cFYI(1, "Send error in QuerySecDesc = %d", rc); | 3135 | cFYI(1, "Send error in QuerySecDesc = %d", rc); |
@@ -4872,7 +4911,6 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, | |||
4872 | __u16 fid, __u32 pid_of_opener, bool SetAllocation) | 4911 | __u16 fid, __u32 pid_of_opener, bool SetAllocation) |
4873 | { | 4912 | { |
4874 | struct smb_com_transaction2_sfi_req *pSMB = NULL; | 4913 | struct smb_com_transaction2_sfi_req *pSMB = NULL; |
4875 | char *data_offset; | ||
4876 | struct file_end_of_file_info *parm_data; | 4914 | struct file_end_of_file_info *parm_data; |
4877 | int rc = 0; | 4915 | int rc = 0; |
4878 | __u16 params, param_offset, offset, byte_count, count; | 4916 | __u16 params, param_offset, offset, byte_count, count; |
@@ -4896,8 +4934,6 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, | |||
4896 | param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4; | 4934 | param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4; |
4897 | offset = param_offset + params; | 4935 | offset = param_offset + params; |
4898 | 4936 | ||
4899 | data_offset = (char *) (&pSMB->hdr.Protocol) + offset; | ||
4900 | |||
4901 | count = sizeof(struct file_end_of_file_info); | 4937 | count = sizeof(struct file_end_of_file_info); |
4902 | pSMB->MaxParameterCount = cpu_to_le16(2); | 4938 | pSMB->MaxParameterCount = cpu_to_le16(2); |
4903 | /* BB find exact max SMB PDU from sess structure BB */ | 4939 | /* BB find exact max SMB PDU from sess structure BB */ |
@@ -5565,7 +5601,7 @@ QAllEAsRetry: | |||
5565 | } | 5601 | } |
5566 | 5602 | ||
5567 | /* make sure list_len doesn't go past end of SMB */ | 5603 | /* make sure list_len doesn't go past end of SMB */ |
5568 | end_of_smb = (char *)pByteArea(&pSMBr->hdr) + BCC(&pSMBr->hdr); | 5604 | end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr); |
5569 | if ((char *)ea_response_data + list_len > end_of_smb) { | 5605 | if ((char *)ea_response_data + list_len > end_of_smb) { |
5570 | cFYI(1, "EA list appears to go beyond SMB"); | 5606 | cFYI(1, "EA list appears to go beyond SMB"); |
5571 | rc = -EIO; | 5607 | rc = -EIO; |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index cc1a8604a790..8d6c17ab593d 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -52,8 +52,8 @@ | |||
52 | #define CIFS_PORT 445 | 52 | #define CIFS_PORT 445 |
53 | #define RFC1001_PORT 139 | 53 | #define RFC1001_PORT 139 |
54 | 54 | ||
55 | extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, | 55 | /* SMB echo "timeout" -- FIXME: tunable? */ |
56 | unsigned char *p24); | 56 | #define SMB_ECHO_INTERVAL (60 * HZ) |
57 | 57 | ||
58 | extern mempool_t *cifs_req_poolp; | 58 | extern mempool_t *cifs_req_poolp; |
59 | 59 | ||
@@ -64,8 +64,8 @@ struct smb_vol { | |||
64 | char *UNC; | 64 | char *UNC; |
65 | char *UNCip; | 65 | char *UNCip; |
66 | char *iocharset; /* local code page for mapping to and from Unicode */ | 66 | char *iocharset; /* local code page for mapping to and from Unicode */ |
67 | char source_rfc1001_name[16]; /* netbios name of client */ | 67 | char source_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* clnt nb name */ |
68 | char target_rfc1001_name[16]; /* netbios name of server for Win9x/ME */ | 68 | char target_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* srvr nb name */ |
69 | uid_t cred_uid; | 69 | uid_t cred_uid; |
70 | uid_t linux_uid; | 70 | uid_t linux_uid; |
71 | gid_t linux_gid; | 71 | gid_t linux_gid; |
@@ -84,6 +84,7 @@ struct smb_vol { | |||
84 | bool no_xattr:1; /* set if xattr (EA) support should be disabled*/ | 84 | bool no_xattr:1; /* set if xattr (EA) support should be disabled*/ |
85 | bool server_ino:1; /* use inode numbers from server ie UniqueId */ | 85 | bool server_ino:1; /* use inode numbers from server ie UniqueId */ |
86 | bool direct_io:1; | 86 | bool direct_io:1; |
87 | bool strict_io:1; /* strict cache behavior */ | ||
87 | bool remap:1; /* set to remap seven reserved chars in filenames */ | 88 | bool remap:1; /* set to remap seven reserved chars in filenames */ |
88 | bool posix_paths:1; /* unset to not ask for posix pathnames. */ | 89 | bool posix_paths:1; /* unset to not ask for posix pathnames. */ |
89 | bool no_linux_ext:1; | 90 | bool no_linux_ext:1; |
@@ -115,8 +116,8 @@ struct smb_vol { | |||
115 | #define TLINK_ERROR_EXPIRE (1 * HZ) | 116 | #define TLINK_ERROR_EXPIRE (1 * HZ) |
116 | #define TLINK_IDLE_EXPIRE (600 * HZ) | 117 | #define TLINK_IDLE_EXPIRE (600 * HZ) |
117 | 118 | ||
118 | static int ipv4_connect(struct TCP_Server_Info *server); | 119 | static int ip_connect(struct TCP_Server_Info *server); |
119 | static int ipv6_connect(struct TCP_Server_Info *server); | 120 | static int generic_ip_connect(struct TCP_Server_Info *server); |
120 | static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink); | 121 | static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink); |
121 | static void cifs_prune_tlinks(struct work_struct *work); | 122 | static void cifs_prune_tlinks(struct work_struct *work); |
122 | 123 | ||
@@ -152,6 +153,7 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
152 | 153 | ||
153 | /* before reconnecting the tcp session, mark the smb session (uid) | 154 | /* before reconnecting the tcp session, mark the smb session (uid) |
154 | and the tid bad so they are not used until reconnected */ | 155 | and the tid bad so they are not used until reconnected */ |
156 | cFYI(1, "%s: marking sessions and tcons for reconnect", __func__); | ||
155 | spin_lock(&cifs_tcp_ses_lock); | 157 | spin_lock(&cifs_tcp_ses_lock); |
156 | list_for_each(tmp, &server->smb_ses_list) { | 158 | list_for_each(tmp, &server->smb_ses_list) { |
157 | ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list); | 159 | ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list); |
@@ -163,7 +165,9 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
163 | } | 165 | } |
164 | } | 166 | } |
165 | spin_unlock(&cifs_tcp_ses_lock); | 167 | spin_unlock(&cifs_tcp_ses_lock); |
168 | |||
166 | /* do not want to be sending data on a socket we are freeing */ | 169 | /* do not want to be sending data on a socket we are freeing */ |
170 | cFYI(1, "%s: tearing down socket", __func__); | ||
167 | mutex_lock(&server->srv_mutex); | 171 | mutex_lock(&server->srv_mutex); |
168 | if (server->ssocket) { | 172 | if (server->ssocket) { |
169 | cFYI(1, "State: 0x%x Flags: 0x%lx", server->ssocket->state, | 173 | cFYI(1, "State: 0x%x Flags: 0x%lx", server->ssocket->state, |
@@ -180,30 +184,27 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
180 | kfree(server->session_key.response); | 184 | kfree(server->session_key.response); |
181 | server->session_key.response = NULL; | 185 | server->session_key.response = NULL; |
182 | server->session_key.len = 0; | 186 | server->session_key.len = 0; |
187 | server->lstrp = jiffies; | ||
188 | mutex_unlock(&server->srv_mutex); | ||
183 | 189 | ||
190 | /* mark submitted MIDs for retry and issue callback */ | ||
191 | cFYI(1, "%s: issuing mid callbacks", __func__); | ||
184 | spin_lock(&GlobalMid_Lock); | 192 | spin_lock(&GlobalMid_Lock); |
185 | list_for_each(tmp, &server->pending_mid_q) { | 193 | list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { |
186 | mid_entry = list_entry(tmp, struct | 194 | mid_entry = list_entry(tmp, struct mid_q_entry, qhead); |
187 | mid_q_entry, | 195 | if (mid_entry->midState == MID_REQUEST_SUBMITTED) |
188 | qhead); | ||
189 | if (mid_entry->midState == MID_REQUEST_SUBMITTED) { | ||
190 | /* Mark other intransit requests as needing | ||
191 | retry so we do not immediately mark the | ||
192 | session bad again (ie after we reconnect | ||
193 | below) as they timeout too */ | ||
194 | mid_entry->midState = MID_RETRY_NEEDED; | 196 | mid_entry->midState = MID_RETRY_NEEDED; |
195 | } | 197 | list_del_init(&mid_entry->qhead); |
198 | mid_entry->callback(mid_entry); | ||
196 | } | 199 | } |
197 | spin_unlock(&GlobalMid_Lock); | 200 | spin_unlock(&GlobalMid_Lock); |
198 | mutex_unlock(&server->srv_mutex); | ||
199 | 201 | ||
200 | while ((server->tcpStatus != CifsExiting) && | 202 | while ((server->tcpStatus != CifsExiting) && |
201 | (server->tcpStatus != CifsGood)) { | 203 | (server->tcpStatus != CifsGood)) { |
202 | try_to_freeze(); | 204 | try_to_freeze(); |
203 | if (server->addr.sockAddr6.sin6_family == AF_INET6) | 205 | |
204 | rc = ipv6_connect(server); | 206 | /* we should try only the port we connected to before */ |
205 | else | 207 | rc = generic_ip_connect(server); |
206 | rc = ipv4_connect(server); | ||
207 | if (rc) { | 208 | if (rc) { |
208 | cFYI(1, "reconnect error %d", rc); | 209 | cFYI(1, "reconnect error %d", rc); |
209 | msleep(3000); | 210 | msleep(3000); |
@@ -213,10 +214,9 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
213 | if (server->tcpStatus != CifsExiting) | 214 | if (server->tcpStatus != CifsExiting) |
214 | server->tcpStatus = CifsGood; | 215 | server->tcpStatus = CifsGood; |
215 | spin_unlock(&GlobalMid_Lock); | 216 | spin_unlock(&GlobalMid_Lock); |
216 | /* atomic_set(&server->inFlight,0);*/ | ||
217 | wake_up(&server->response_q); | ||
218 | } | 217 | } |
219 | } | 218 | } |
219 | |||
220 | return rc; | 220 | return rc; |
221 | } | 221 | } |
222 | 222 | ||
@@ -230,9 +230,8 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
230 | static int check2ndT2(struct smb_hdr *pSMB, unsigned int maxBufSize) | 230 | static int check2ndT2(struct smb_hdr *pSMB, unsigned int maxBufSize) |
231 | { | 231 | { |
232 | struct smb_t2_rsp *pSMBt; | 232 | struct smb_t2_rsp *pSMBt; |
233 | int total_data_size; | ||
234 | int data_in_this_rsp; | ||
235 | int remaining; | 233 | int remaining; |
234 | __u16 total_data_size, data_in_this_rsp; | ||
236 | 235 | ||
237 | if (pSMB->Command != SMB_COM_TRANSACTION2) | 236 | if (pSMB->Command != SMB_COM_TRANSACTION2) |
238 | return 0; | 237 | return 0; |
@@ -246,8 +245,8 @@ static int check2ndT2(struct smb_hdr *pSMB, unsigned int maxBufSize) | |||
246 | 245 | ||
247 | pSMBt = (struct smb_t2_rsp *)pSMB; | 246 | pSMBt = (struct smb_t2_rsp *)pSMB; |
248 | 247 | ||
249 | total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount); | 248 | total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount); |
250 | data_in_this_rsp = le16_to_cpu(pSMBt->t2_rsp.DataCount); | 249 | data_in_this_rsp = get_unaligned_le16(&pSMBt->t2_rsp.DataCount); |
251 | 250 | ||
252 | remaining = total_data_size - data_in_this_rsp; | 251 | remaining = total_data_size - data_in_this_rsp; |
253 | 252 | ||
@@ -273,21 +272,18 @@ static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB) | |||
273 | { | 272 | { |
274 | struct smb_t2_rsp *pSMB2 = (struct smb_t2_rsp *)psecond; | 273 | struct smb_t2_rsp *pSMB2 = (struct smb_t2_rsp *)psecond; |
275 | struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)pTargetSMB; | 274 | struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)pTargetSMB; |
276 | int total_data_size; | ||
277 | int total_in_buf; | ||
278 | int remaining; | ||
279 | int total_in_buf2; | ||
280 | char *data_area_of_target; | 275 | char *data_area_of_target; |
281 | char *data_area_of_buf2; | 276 | char *data_area_of_buf2; |
282 | __u16 byte_count; | 277 | int remaining; |
278 | __u16 byte_count, total_data_size, total_in_buf, total_in_buf2; | ||
283 | 279 | ||
284 | total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount); | 280 | total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount); |
285 | 281 | ||
286 | if (total_data_size != le16_to_cpu(pSMB2->t2_rsp.TotalDataCount)) { | 282 | if (total_data_size != |
283 | get_unaligned_le16(&pSMB2->t2_rsp.TotalDataCount)) | ||
287 | cFYI(1, "total data size of primary and secondary t2 differ"); | 284 | cFYI(1, "total data size of primary and secondary t2 differ"); |
288 | } | ||
289 | 285 | ||
290 | total_in_buf = le16_to_cpu(pSMBt->t2_rsp.DataCount); | 286 | total_in_buf = get_unaligned_le16(&pSMBt->t2_rsp.DataCount); |
291 | 287 | ||
292 | remaining = total_data_size - total_in_buf; | 288 | remaining = total_data_size - total_in_buf; |
293 | 289 | ||
@@ -297,28 +293,28 @@ static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB) | |||
297 | if (remaining == 0) /* nothing to do, ignore */ | 293 | if (remaining == 0) /* nothing to do, ignore */ |
298 | return 0; | 294 | return 0; |
299 | 295 | ||
300 | total_in_buf2 = le16_to_cpu(pSMB2->t2_rsp.DataCount); | 296 | total_in_buf2 = get_unaligned_le16(&pSMB2->t2_rsp.DataCount); |
301 | if (remaining < total_in_buf2) { | 297 | if (remaining < total_in_buf2) { |
302 | cFYI(1, "transact2 2nd response contains too much data"); | 298 | cFYI(1, "transact2 2nd response contains too much data"); |
303 | } | 299 | } |
304 | 300 | ||
305 | /* find end of first SMB data area */ | 301 | /* find end of first SMB data area */ |
306 | data_area_of_target = (char *)&pSMBt->hdr.Protocol + | 302 | data_area_of_target = (char *)&pSMBt->hdr.Protocol + |
307 | le16_to_cpu(pSMBt->t2_rsp.DataOffset); | 303 | get_unaligned_le16(&pSMBt->t2_rsp.DataOffset); |
308 | /* validate target area */ | 304 | /* validate target area */ |
309 | 305 | ||
310 | data_area_of_buf2 = (char *) &pSMB2->hdr.Protocol + | 306 | data_area_of_buf2 = (char *)&pSMB2->hdr.Protocol + |
311 | le16_to_cpu(pSMB2->t2_rsp.DataOffset); | 307 | get_unaligned_le16(&pSMB2->t2_rsp.DataOffset); |
312 | 308 | ||
313 | data_area_of_target += total_in_buf; | 309 | data_area_of_target += total_in_buf; |
314 | 310 | ||
315 | /* copy second buffer into end of first buffer */ | 311 | /* copy second buffer into end of first buffer */ |
316 | memcpy(data_area_of_target, data_area_of_buf2, total_in_buf2); | 312 | memcpy(data_area_of_target, data_area_of_buf2, total_in_buf2); |
317 | total_in_buf += total_in_buf2; | 313 | total_in_buf += total_in_buf2; |
318 | pSMBt->t2_rsp.DataCount = cpu_to_le16(total_in_buf); | 314 | put_unaligned_le16(total_in_buf, &pSMBt->t2_rsp.DataCount); |
319 | byte_count = le16_to_cpu(BCC_LE(pTargetSMB)); | 315 | byte_count = get_bcc_le(pTargetSMB); |
320 | byte_count += total_in_buf2; | 316 | byte_count += total_in_buf2; |
321 | BCC_LE(pTargetSMB) = cpu_to_le16(byte_count); | 317 | put_bcc_le(byte_count, pTargetSMB); |
322 | 318 | ||
323 | byte_count = pTargetSMB->smb_buf_length; | 319 | byte_count = pTargetSMB->smb_buf_length; |
324 | byte_count += total_in_buf2; | 320 | byte_count += total_in_buf2; |
@@ -332,7 +328,31 @@ static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB) | |||
332 | return 0; /* we are done */ | 328 | return 0; /* we are done */ |
333 | } else /* more responses to go */ | 329 | } else /* more responses to go */ |
334 | return 1; | 330 | return 1; |
331 | } | ||
332 | |||
333 | static void | ||
334 | cifs_echo_request(struct work_struct *work) | ||
335 | { | ||
336 | int rc; | ||
337 | struct TCP_Server_Info *server = container_of(work, | ||
338 | struct TCP_Server_Info, echo.work); | ||
335 | 339 | ||
340 | /* | ||
341 | * We cannot send an echo until the NEGOTIATE_PROTOCOL request is | ||
342 | * done, which is indicated by maxBuf != 0. Also, no need to ping if | ||
343 | * we got a response recently | ||
344 | */ | ||
345 | if (server->maxBuf == 0 || | ||
346 | time_before(jiffies, server->lstrp + SMB_ECHO_INTERVAL - HZ)) | ||
347 | goto requeue_echo; | ||
348 | |||
349 | rc = CIFSSMBEcho(server); | ||
350 | if (rc) | ||
351 | cFYI(1, "Unable to send echo request to server: %s", | ||
352 | server->hostname); | ||
353 | |||
354 | requeue_echo: | ||
355 | queue_delayed_work(system_nrt_wq, &server->echo, SMB_ECHO_INTERVAL); | ||
336 | } | 356 | } |
337 | 357 | ||
338 | static int | 358 | static int |
@@ -346,8 +366,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
346 | struct msghdr smb_msg; | 366 | struct msghdr smb_msg; |
347 | struct kvec iov; | 367 | struct kvec iov; |
348 | struct socket *csocket = server->ssocket; | 368 | struct socket *csocket = server->ssocket; |
349 | struct list_head *tmp; | 369 | struct list_head *tmp, *tmp2; |
350 | struct cifsSesInfo *ses; | ||
351 | struct task_struct *task_to_wake = NULL; | 370 | struct task_struct *task_to_wake = NULL; |
352 | struct mid_q_entry *mid_entry; | 371 | struct mid_q_entry *mid_entry; |
353 | char temp; | 372 | char temp; |
@@ -400,7 +419,20 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) | |||
400 | smb_msg.msg_control = NULL; | 419 | smb_msg.msg_control = NULL; |
401 | smb_msg.msg_controllen = 0; | 420 | smb_msg.msg_controllen = 0; |
402 | pdu_length = 4; /* enough to get RFC1001 header */ | 421 | pdu_length = 4; /* enough to get RFC1001 header */ |
422 | |||
403 | incomplete_rcv: | 423 | incomplete_rcv: |
424 | if (echo_retries > 0 && | ||
425 | time_after(jiffies, server->lstrp + | ||
426 | (echo_retries * SMB_ECHO_INTERVAL))) { | ||
427 | cERROR(1, "Server %s has not responded in %d seconds. " | ||
428 | "Reconnecting...", server->hostname, | ||
429 | (echo_retries * SMB_ECHO_INTERVAL / HZ)); | ||
430 | cifs_reconnect(server); | ||
431 | csocket = server->ssocket; | ||
432 | wake_up(&server->response_q); | ||
433 | continue; | ||
434 | } | ||
435 | |||
404 | length = | 436 | length = |
405 | kernel_recvmsg(csocket, &smb_msg, | 437 | kernel_recvmsg(csocket, &smb_msg, |
406 | &iov, 1, pdu_length, 0 /* BB other flags? */); | 438 | &iov, 1, pdu_length, 0 /* BB other flags? */); |
@@ -477,7 +509,7 @@ incomplete_rcv: | |||
477 | * initialize frame) | 509 | * initialize frame) |
478 | */ | 510 | */ |
479 | cifs_set_port((struct sockaddr *) | 511 | cifs_set_port((struct sockaddr *) |
480 | &server->addr.sockAddr, CIFS_PORT); | 512 | &server->dstaddr, CIFS_PORT); |
481 | cifs_reconnect(server); | 513 | cifs_reconnect(server); |
482 | csocket = server->ssocket; | 514 | csocket = server->ssocket; |
483 | wake_up(&server->response_q); | 515 | wake_up(&server->response_q); |
@@ -551,25 +583,36 @@ incomplete_rcv: | |||
551 | else if (reconnect == 1) | 583 | else if (reconnect == 1) |
552 | continue; | 584 | continue; |
553 | 585 | ||
554 | length += 4; /* account for rfc1002 hdr */ | 586 | total_read += 4; /* account for rfc1002 hdr */ |
555 | 587 | ||
588 | dump_smb(smb_buffer, total_read); | ||
556 | 589 | ||
557 | dump_smb(smb_buffer, length); | 590 | /* |
558 | if (checkSMB(smb_buffer, smb_buffer->Mid, total_read+4)) { | 591 | * We know that we received enough to get to the MID as we |
559 | cifs_dump_mem("Bad SMB: ", smb_buffer, 48); | 592 | * checked the pdu_length earlier. Now check to see |
560 | continue; | 593 | * if the rest of the header is OK. We borrow the length |
561 | } | 594 | * var for the rest of the loop to avoid a new stack var. |
595 | * | ||
596 | * 48 bytes is enough to display the header and a little bit | ||
597 | * into the payload for debugging purposes. | ||
598 | */ | ||
599 | length = checkSMB(smb_buffer, smb_buffer->Mid, total_read); | ||
600 | if (length != 0) | ||
601 | cifs_dump_mem("Bad SMB: ", smb_buffer, | ||
602 | min_t(unsigned int, total_read, 48)); | ||
562 | 603 | ||
604 | mid_entry = NULL; | ||
605 | server->lstrp = jiffies; | ||
563 | 606 | ||
564 | task_to_wake = NULL; | ||
565 | spin_lock(&GlobalMid_Lock); | 607 | spin_lock(&GlobalMid_Lock); |
566 | list_for_each(tmp, &server->pending_mid_q) { | 608 | list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { |
567 | mid_entry = list_entry(tmp, struct mid_q_entry, qhead); | 609 | mid_entry = list_entry(tmp, struct mid_q_entry, qhead); |
568 | 610 | ||
569 | if ((mid_entry->mid == smb_buffer->Mid) && | 611 | if ((mid_entry->mid == smb_buffer->Mid) && |
570 | (mid_entry->midState == MID_REQUEST_SUBMITTED) && | 612 | (mid_entry->midState == MID_REQUEST_SUBMITTED) && |
571 | (mid_entry->command == smb_buffer->Command)) { | 613 | (mid_entry->command == smb_buffer->Command)) { |
572 | if (check2ndT2(smb_buffer,server->maxBuf) > 0) { | 614 | if (length == 0 && |
615 | check2ndT2(smb_buffer, server->maxBuf) > 0) { | ||
573 | /* We have a multipart transact2 resp */ | 616 | /* We have a multipart transact2 resp */ |
574 | isMultiRsp = true; | 617 | isMultiRsp = true; |
575 | if (mid_entry->resp_buf) { | 618 | if (mid_entry->resp_buf) { |
@@ -604,20 +647,24 @@ incomplete_rcv: | |||
604 | mid_entry->resp_buf = smb_buffer; | 647 | mid_entry->resp_buf = smb_buffer; |
605 | mid_entry->largeBuf = isLargeBuf; | 648 | mid_entry->largeBuf = isLargeBuf; |
606 | multi_t2_fnd: | 649 | multi_t2_fnd: |
607 | task_to_wake = mid_entry->tsk; | 650 | if (length == 0) |
608 | mid_entry->midState = MID_RESPONSE_RECEIVED; | 651 | mid_entry->midState = |
652 | MID_RESPONSE_RECEIVED; | ||
653 | else | ||
654 | mid_entry->midState = | ||
655 | MID_RESPONSE_MALFORMED; | ||
609 | #ifdef CONFIG_CIFS_STATS2 | 656 | #ifdef CONFIG_CIFS_STATS2 |
610 | mid_entry->when_received = jiffies; | 657 | mid_entry->when_received = jiffies; |
611 | #endif | 658 | #endif |
612 | /* so we do not time out requests to server | 659 | list_del_init(&mid_entry->qhead); |
613 | which is still responding (since server could | 660 | mid_entry->callback(mid_entry); |
614 | be busy but not dead) */ | ||
615 | server->lstrp = jiffies; | ||
616 | break; | 661 | break; |
617 | } | 662 | } |
663 | mid_entry = NULL; | ||
618 | } | 664 | } |
619 | spin_unlock(&GlobalMid_Lock); | 665 | spin_unlock(&GlobalMid_Lock); |
620 | if (task_to_wake) { | 666 | |
667 | if (mid_entry != NULL) { | ||
621 | /* Was previous buf put in mpx struct for multi-rsp? */ | 668 | /* Was previous buf put in mpx struct for multi-rsp? */ |
622 | if (!isMultiRsp) { | 669 | if (!isMultiRsp) { |
623 | /* smb buffer will be freed by user thread */ | 670 | /* smb buffer will be freed by user thread */ |
@@ -626,11 +673,13 @@ multi_t2_fnd: | |||
626 | else | 673 | else |
627 | smallbuf = NULL; | 674 | smallbuf = NULL; |
628 | } | 675 | } |
629 | wake_up_process(task_to_wake); | 676 | } else if (length != 0) { |
677 | /* response sanity checks failed */ | ||
678 | continue; | ||
630 | } else if (!is_valid_oplock_break(smb_buffer, server) && | 679 | } else if (!is_valid_oplock_break(smb_buffer, server) && |
631 | !isMultiRsp) { | 680 | !isMultiRsp) { |
632 | cERROR(1, "No task to wake, unknown frame received! " | 681 | cERROR(1, "No task to wake, unknown frame received! " |
633 | "NumMids %d", midCount.counter); | 682 | "NumMids %d", atomic_read(&midCount)); |
634 | cifs_dump_mem("Received Data is: ", (char *)smb_buffer, | 683 | cifs_dump_mem("Received Data is: ", (char *)smb_buffer, |
635 | sizeof(struct smb_hdr)); | 684 | sizeof(struct smb_hdr)); |
636 | #ifdef CONFIG_CIFS_DEBUG2 | 685 | #ifdef CONFIG_CIFS_DEBUG2 |
@@ -678,44 +727,16 @@ multi_t2_fnd: | |||
678 | if (smallbuf) /* no sense logging a debug message if NULL */ | 727 | if (smallbuf) /* no sense logging a debug message if NULL */ |
679 | cifs_small_buf_release(smallbuf); | 728 | cifs_small_buf_release(smallbuf); |
680 | 729 | ||
681 | /* | 730 | if (!list_empty(&server->pending_mid_q)) { |
682 | * BB: we shouldn't have to do any of this. It shouldn't be | ||
683 | * possible to exit from the thread with active SMB sessions | ||
684 | */ | ||
685 | spin_lock(&cifs_tcp_ses_lock); | ||
686 | if (list_empty(&server->pending_mid_q)) { | ||
687 | /* loop through server session structures attached to this and | ||
688 | mark them dead */ | ||
689 | list_for_each(tmp, &server->smb_ses_list) { | ||
690 | ses = list_entry(tmp, struct cifsSesInfo, | ||
691 | smb_ses_list); | ||
692 | ses->status = CifsExiting; | ||
693 | ses->server = NULL; | ||
694 | } | ||
695 | spin_unlock(&cifs_tcp_ses_lock); | ||
696 | } else { | ||
697 | /* although we can not zero the server struct pointer yet, | ||
698 | since there are active requests which may depnd on them, | ||
699 | mark the corresponding SMB sessions as exiting too */ | ||
700 | list_for_each(tmp, &server->smb_ses_list) { | ||
701 | ses = list_entry(tmp, struct cifsSesInfo, | ||
702 | smb_ses_list); | ||
703 | ses->status = CifsExiting; | ||
704 | } | ||
705 | |||
706 | spin_lock(&GlobalMid_Lock); | 731 | spin_lock(&GlobalMid_Lock); |
707 | list_for_each(tmp, &server->pending_mid_q) { | 732 | list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { |
708 | mid_entry = list_entry(tmp, struct mid_q_entry, qhead); | 733 | mid_entry = list_entry(tmp, struct mid_q_entry, qhead); |
709 | if (mid_entry->midState == MID_REQUEST_SUBMITTED) { | 734 | cFYI(1, "Clearing Mid 0x%x - issuing callback", |
710 | cFYI(1, "Clearing Mid 0x%x - waking up ", | ||
711 | mid_entry->mid); | 735 | mid_entry->mid); |
712 | task_to_wake = mid_entry->tsk; | 736 | list_del_init(&mid_entry->qhead); |
713 | if (task_to_wake) | 737 | mid_entry->callback(mid_entry); |
714 | wake_up_process(task_to_wake); | ||
715 | } | ||
716 | } | 738 | } |
717 | spin_unlock(&GlobalMid_Lock); | 739 | spin_unlock(&GlobalMid_Lock); |
718 | spin_unlock(&cifs_tcp_ses_lock); | ||
719 | /* 1/8th of sec is more than enough time for them to exit */ | 740 | /* 1/8th of sec is more than enough time for them to exit */ |
720 | msleep(125); | 741 | msleep(125); |
721 | } | 742 | } |
@@ -733,18 +754,6 @@ multi_t2_fnd: | |||
733 | coming home not much else we can do but free the memory */ | 754 | coming home not much else we can do but free the memory */ |
734 | } | 755 | } |
735 | 756 | ||
736 | /* last chance to mark ses pointers invalid | ||
737 | if there are any pointing to this (e.g | ||
738 | if a crazy root user tried to kill cifsd | ||
739 | kernel thread explicitly this might happen) */ | ||
740 | /* BB: This shouldn't be necessary, see above */ | ||
741 | spin_lock(&cifs_tcp_ses_lock); | ||
742 | list_for_each(tmp, &server->smb_ses_list) { | ||
743 | ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list); | ||
744 | ses->server = NULL; | ||
745 | } | ||
746 | spin_unlock(&cifs_tcp_ses_lock); | ||
747 | |||
748 | kfree(server->hostname); | 757 | kfree(server->hostname); |
749 | task_to_wake = xchg(&server->tsk, NULL); | 758 | task_to_wake = xchg(&server->tsk, NULL); |
750 | kfree(server); | 759 | kfree(server); |
@@ -817,11 +826,11 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
817 | * informational, only used for servers that do not support | 826 | * informational, only used for servers that do not support |
818 | * port 445 and it can be overridden at mount time | 827 | * port 445 and it can be overridden at mount time |
819 | */ | 828 | */ |
820 | memset(vol->source_rfc1001_name, 0x20, 15); | 829 | memset(vol->source_rfc1001_name, 0x20, RFC1001_NAME_LEN); |
821 | for (i = 0; i < strnlen(nodename, 15); i++) | 830 | for (i = 0; i < strnlen(nodename, RFC1001_NAME_LEN); i++) |
822 | vol->source_rfc1001_name[i] = toupper(nodename[i]); | 831 | vol->source_rfc1001_name[i] = toupper(nodename[i]); |
823 | 832 | ||
824 | vol->source_rfc1001_name[15] = 0; | 833 | vol->source_rfc1001_name[RFC1001_NAME_LEN] = 0; |
825 | /* null target name indicates to use *SMBSERVR default called name | 834 | /* null target name indicates to use *SMBSERVR default called name |
826 | if we end up sending RFC1001 session initialize */ | 835 | if we end up sending RFC1001 session initialize */ |
827 | vol->target_rfc1001_name[0] = 0; | 836 | vol->target_rfc1001_name[0] = 0; |
@@ -985,13 +994,11 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
985 | return 1; | 994 | return 1; |
986 | } else if (strnicmp(value, "krb5", 4) == 0) { | 995 | } else if (strnicmp(value, "krb5", 4) == 0) { |
987 | vol->secFlg |= CIFSSEC_MAY_KRB5; | 996 | vol->secFlg |= CIFSSEC_MAY_KRB5; |
988 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
989 | } else if (strnicmp(value, "ntlmsspi", 8) == 0) { | 997 | } else if (strnicmp(value, "ntlmsspi", 8) == 0) { |
990 | vol->secFlg |= CIFSSEC_MAY_NTLMSSP | | 998 | vol->secFlg |= CIFSSEC_MAY_NTLMSSP | |
991 | CIFSSEC_MUST_SIGN; | 999 | CIFSSEC_MUST_SIGN; |
992 | } else if (strnicmp(value, "ntlmssp", 7) == 0) { | 1000 | } else if (strnicmp(value, "ntlmssp", 7) == 0) { |
993 | vol->secFlg |= CIFSSEC_MAY_NTLMSSP; | 1001 | vol->secFlg |= CIFSSEC_MAY_NTLMSSP; |
994 | #endif | ||
995 | } else if (strnicmp(value, "ntlmv2i", 7) == 0) { | 1002 | } else if (strnicmp(value, "ntlmv2i", 7) == 0) { |
996 | vol->secFlg |= CIFSSEC_MAY_NTLMV2 | | 1003 | vol->secFlg |= CIFSSEC_MAY_NTLMV2 | |
997 | CIFSSEC_MUST_SIGN; | 1004 | CIFSSEC_MUST_SIGN; |
@@ -1116,6 +1123,8 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1116 | } else if (!strnicmp(data, "uid", 3) && value && *value) { | 1123 | } else if (!strnicmp(data, "uid", 3) && value && *value) { |
1117 | vol->linux_uid = simple_strtoul(value, &value, 0); | 1124 | vol->linux_uid = simple_strtoul(value, &value, 0); |
1118 | uid_specified = true; | 1125 | uid_specified = true; |
1126 | } else if (!strnicmp(data, "cruid", 5) && value && *value) { | ||
1127 | vol->cred_uid = simple_strtoul(value, &value, 0); | ||
1119 | } else if (!strnicmp(data, "forceuid", 8)) { | 1128 | } else if (!strnicmp(data, "forceuid", 8)) { |
1120 | override_uid = 1; | 1129 | override_uid = 1; |
1121 | } else if (!strnicmp(data, "noforceuid", 10)) { | 1130 | } else if (!strnicmp(data, "noforceuid", 10)) { |
@@ -1168,22 +1177,22 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1168 | if (!value || !*value || (*value == ' ')) { | 1177 | if (!value || !*value || (*value == ' ')) { |
1169 | cFYI(1, "invalid (empty) netbiosname"); | 1178 | cFYI(1, "invalid (empty) netbiosname"); |
1170 | } else { | 1179 | } else { |
1171 | memset(vol->source_rfc1001_name, 0x20, 15); | 1180 | memset(vol->source_rfc1001_name, 0x20, |
1172 | for (i = 0; i < 15; i++) { | 1181 | RFC1001_NAME_LEN); |
1173 | /* BB are there cases in which a comma can be | 1182 | /* |
1174 | valid in this workstation netbios name (and need | 1183 | * FIXME: are there cases in which a comma can |
1175 | special handling)? */ | 1184 | * be valid in workstation netbios name (and |
1176 | 1185 | * need special handling)? | |
1177 | /* We do not uppercase netbiosname for user */ | 1186 | */ |
1187 | for (i = 0; i < RFC1001_NAME_LEN; i++) { | ||
1188 | /* don't ucase netbiosname for user */ | ||
1178 | if (value[i] == 0) | 1189 | if (value[i] == 0) |
1179 | break; | 1190 | break; |
1180 | else | 1191 | vol->source_rfc1001_name[i] = value[i]; |
1181 | vol->source_rfc1001_name[i] = | ||
1182 | value[i]; | ||
1183 | } | 1192 | } |
1184 | /* The string has 16th byte zero still from | 1193 | /* The string has 16th byte zero still from |
1185 | set at top of the function */ | 1194 | set at top of the function */ |
1186 | if ((i == 15) && (value[i] != 0)) | 1195 | if (i == RFC1001_NAME_LEN && value[i] != 0) |
1187 | printk(KERN_WARNING "CIFS: netbiosname" | 1196 | printk(KERN_WARNING "CIFS: netbiosname" |
1188 | " longer than 15 truncated.\n"); | 1197 | " longer than 15 truncated.\n"); |
1189 | } | 1198 | } |
@@ -1193,7 +1202,8 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1193 | cFYI(1, "empty server netbiosname specified"); | 1202 | cFYI(1, "empty server netbiosname specified"); |
1194 | } else { | 1203 | } else { |
1195 | /* last byte, type, is 0x20 for servr type */ | 1204 | /* last byte, type, is 0x20 for servr type */ |
1196 | memset(vol->target_rfc1001_name, 0x20, 16); | 1205 | memset(vol->target_rfc1001_name, 0x20, |
1206 | RFC1001_NAME_LEN_WITH_NULL); | ||
1197 | 1207 | ||
1198 | for (i = 0; i < 15; i++) { | 1208 | for (i = 0; i < 15; i++) { |
1199 | /* BB are there cases in which a comma can be | 1209 | /* BB are there cases in which a comma can be |
@@ -1210,7 +1220,7 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1210 | } | 1220 | } |
1211 | /* The string has 16th byte zero still from | 1221 | /* The string has 16th byte zero still from |
1212 | set at top of the function */ | 1222 | set at top of the function */ |
1213 | if ((i == 15) && (value[i] != 0)) | 1223 | if (i == RFC1001_NAME_LEN && value[i] != 0) |
1214 | printk(KERN_WARNING "CIFS: server net" | 1224 | printk(KERN_WARNING "CIFS: server net" |
1215 | "biosname longer than 15 truncated.\n"); | 1225 | "biosname longer than 15 truncated.\n"); |
1216 | } | 1226 | } |
@@ -1341,10 +1351,8 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1341 | vol->no_psx_acl = 0; | 1351 | vol->no_psx_acl = 0; |
1342 | } else if (strnicmp(data, "noacl", 5) == 0) { | 1352 | } else if (strnicmp(data, "noacl", 5) == 0) { |
1343 | vol->no_psx_acl = 1; | 1353 | vol->no_psx_acl = 1; |
1344 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
1345 | } else if (strnicmp(data, "locallease", 6) == 0) { | 1354 | } else if (strnicmp(data, "locallease", 6) == 0) { |
1346 | vol->local_lease = 1; | 1355 | vol->local_lease = 1; |
1347 | #endif | ||
1348 | } else if (strnicmp(data, "sign", 4) == 0) { | 1356 | } else if (strnicmp(data, "sign", 4) == 0) { |
1349 | vol->secFlg |= CIFSSEC_MUST_SIGN; | 1357 | vol->secFlg |= CIFSSEC_MUST_SIGN; |
1350 | } else if (strnicmp(data, "seal", 4) == 0) { | 1358 | } else if (strnicmp(data, "seal", 4) == 0) { |
@@ -1357,6 +1365,8 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1357 | vol->direct_io = 1; | 1365 | vol->direct_io = 1; |
1358 | } else if (strnicmp(data, "forcedirectio", 13) == 0) { | 1366 | } else if (strnicmp(data, "forcedirectio", 13) == 0) { |
1359 | vol->direct_io = 1; | 1367 | vol->direct_io = 1; |
1368 | } else if (strnicmp(data, "strictcache", 11) == 0) { | ||
1369 | vol->strict_io = 1; | ||
1360 | } else if (strnicmp(data, "noac", 4) == 0) { | 1370 | } else if (strnicmp(data, "noac", 4) == 0) { |
1361 | printk(KERN_WARNING "CIFS: Mount option noac not " | 1371 | printk(KERN_WARNING "CIFS: Mount option noac not " |
1362 | "supported. Instead set " | 1372 | "supported. Instead set " |
@@ -1454,35 +1464,71 @@ srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs) | |||
1454 | } | 1464 | } |
1455 | } | 1465 | } |
1456 | 1466 | ||
1467 | /* | ||
1468 | * If no port is specified in addr structure, we try to match with 445 port | ||
1469 | * and if it fails - with 139 ports. It should be called only if address | ||
1470 | * families of server and addr are equal. | ||
1471 | */ | ||
1472 | static bool | ||
1473 | match_port(struct TCP_Server_Info *server, struct sockaddr *addr) | ||
1474 | { | ||
1475 | unsigned short int port, *sport; | ||
1476 | |||
1477 | switch (addr->sa_family) { | ||
1478 | case AF_INET: | ||
1479 | sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port; | ||
1480 | port = ((struct sockaddr_in *) addr)->sin_port; | ||
1481 | break; | ||
1482 | case AF_INET6: | ||
1483 | sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port; | ||
1484 | port = ((struct sockaddr_in6 *) addr)->sin6_port; | ||
1485 | break; | ||
1486 | default: | ||
1487 | WARN_ON(1); | ||
1488 | return false; | ||
1489 | } | ||
1490 | |||
1491 | if (!port) { | ||
1492 | port = htons(CIFS_PORT); | ||
1493 | if (port == *sport) | ||
1494 | return true; | ||
1495 | |||
1496 | port = htons(RFC1001_PORT); | ||
1497 | } | ||
1498 | |||
1499 | return port == *sport; | ||
1500 | } | ||
1457 | 1501 | ||
1458 | static bool | 1502 | static bool |
1459 | match_address(struct TCP_Server_Info *server, struct sockaddr *addr, | 1503 | match_address(struct TCP_Server_Info *server, struct sockaddr *addr, |
1460 | struct sockaddr *srcaddr) | 1504 | struct sockaddr *srcaddr) |
1461 | { | 1505 | { |
1462 | struct sockaddr_in *addr4 = (struct sockaddr_in *)addr; | ||
1463 | struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr; | ||
1464 | |||
1465 | switch (addr->sa_family) { | 1506 | switch (addr->sa_family) { |
1466 | case AF_INET: | 1507 | case AF_INET: { |
1467 | if (addr4->sin_addr.s_addr != | 1508 | struct sockaddr_in *addr4 = (struct sockaddr_in *)addr; |
1468 | server->addr.sockAddr.sin_addr.s_addr) | 1509 | struct sockaddr_in *srv_addr4 = |
1469 | return false; | 1510 | (struct sockaddr_in *)&server->dstaddr; |
1470 | if (addr4->sin_port && | 1511 | |
1471 | addr4->sin_port != server->addr.sockAddr.sin_port) | 1512 | if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr) |
1472 | return false; | 1513 | return false; |
1473 | break; | 1514 | break; |
1474 | case AF_INET6: | 1515 | } |
1516 | case AF_INET6: { | ||
1517 | struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr; | ||
1518 | struct sockaddr_in6 *srv_addr6 = | ||
1519 | (struct sockaddr_in6 *)&server->dstaddr; | ||
1520 | |||
1475 | if (!ipv6_addr_equal(&addr6->sin6_addr, | 1521 | if (!ipv6_addr_equal(&addr6->sin6_addr, |
1476 | &server->addr.sockAddr6.sin6_addr)) | 1522 | &srv_addr6->sin6_addr)) |
1477 | return false; | 1523 | return false; |
1478 | if (addr6->sin6_scope_id != | 1524 | if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id) |
1479 | server->addr.sockAddr6.sin6_scope_id) | ||
1480 | return false; | ||
1481 | if (addr6->sin6_port && | ||
1482 | addr6->sin6_port != server->addr.sockAddr6.sin6_port) | ||
1483 | return false; | 1525 | return false; |
1484 | break; | 1526 | break; |
1485 | } | 1527 | } |
1528 | default: | ||
1529 | WARN_ON(1); | ||
1530 | return false; /* don't expect to be here */ | ||
1531 | } | ||
1486 | 1532 | ||
1487 | if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr)) | 1533 | if (!srcip_matches(srcaddr, (struct sockaddr *)&server->srcaddr)) |
1488 | return false; | 1534 | return false; |
@@ -1545,10 +1591,16 @@ cifs_find_tcp_session(struct sockaddr *addr, struct smb_vol *vol) | |||
1545 | 1591 | ||
1546 | spin_lock(&cifs_tcp_ses_lock); | 1592 | spin_lock(&cifs_tcp_ses_lock); |
1547 | list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) { | 1593 | list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) { |
1594 | if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns)) | ||
1595 | continue; | ||
1596 | |||
1548 | if (!match_address(server, addr, | 1597 | if (!match_address(server, addr, |
1549 | (struct sockaddr *)&vol->srcaddr)) | 1598 | (struct sockaddr *)&vol->srcaddr)) |
1550 | continue; | 1599 | continue; |
1551 | 1600 | ||
1601 | if (!match_port(server, addr)) | ||
1602 | continue; | ||
1603 | |||
1552 | if (!match_security(server, vol)) | 1604 | if (!match_security(server, vol)) |
1553 | continue; | 1605 | continue; |
1554 | 1606 | ||
@@ -1572,9 +1624,13 @@ cifs_put_tcp_session(struct TCP_Server_Info *server) | |||
1572 | return; | 1624 | return; |
1573 | } | 1625 | } |
1574 | 1626 | ||
1627 | put_net(cifs_net_ns(server)); | ||
1628 | |||
1575 | list_del_init(&server->tcp_ses_list); | 1629 | list_del_init(&server->tcp_ses_list); |
1576 | spin_unlock(&cifs_tcp_ses_lock); | 1630 | spin_unlock(&cifs_tcp_ses_lock); |
1577 | 1631 | ||
1632 | cancel_delayed_work_sync(&server->echo); | ||
1633 | |||
1578 | spin_lock(&GlobalMid_Lock); | 1634 | spin_lock(&GlobalMid_Lock); |
1579 | server->tcpStatus = CifsExiting; | 1635 | server->tcpStatus = CifsExiting; |
1580 | spin_unlock(&GlobalMid_Lock); | 1636 | spin_unlock(&GlobalMid_Lock); |
@@ -1644,6 +1700,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info) | |||
1644 | goto out_err; | 1700 | goto out_err; |
1645 | } | 1701 | } |
1646 | 1702 | ||
1703 | cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns)); | ||
1647 | tcp_ses->hostname = extract_hostname(volume_info->UNC); | 1704 | tcp_ses->hostname = extract_hostname(volume_info->UNC); |
1648 | if (IS_ERR(tcp_ses->hostname)) { | 1705 | if (IS_ERR(tcp_ses->hostname)) { |
1649 | rc = PTR_ERR(tcp_ses->hostname); | 1706 | rc = PTR_ERR(tcp_ses->hostname); |
@@ -1664,8 +1721,10 @@ cifs_get_tcp_session(struct smb_vol *volume_info) | |||
1664 | volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL); | 1721 | volume_info->target_rfc1001_name, RFC1001_NAME_LEN_WITH_NULL); |
1665 | tcp_ses->session_estab = false; | 1722 | tcp_ses->session_estab = false; |
1666 | tcp_ses->sequence_number = 0; | 1723 | tcp_ses->sequence_number = 0; |
1724 | tcp_ses->lstrp = jiffies; | ||
1667 | INIT_LIST_HEAD(&tcp_ses->tcp_ses_list); | 1725 | INIT_LIST_HEAD(&tcp_ses->tcp_ses_list); |
1668 | INIT_LIST_HEAD(&tcp_ses->smb_ses_list); | 1726 | INIT_LIST_HEAD(&tcp_ses->smb_ses_list); |
1727 | INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request); | ||
1669 | 1728 | ||
1670 | /* | 1729 | /* |
1671 | * at this point we are the only ones with the pointer | 1730 | * at this point we are the only ones with the pointer |
@@ -1681,14 +1740,13 @@ cifs_get_tcp_session(struct smb_vol *volume_info) | |||
1681 | cFYI(1, "attempting ipv6 connect"); | 1740 | cFYI(1, "attempting ipv6 connect"); |
1682 | /* BB should we allow ipv6 on port 139? */ | 1741 | /* BB should we allow ipv6 on port 139? */ |
1683 | /* other OS never observed in Wild doing 139 with v6 */ | 1742 | /* other OS never observed in Wild doing 139 with v6 */ |
1684 | memcpy(&tcp_ses->addr.sockAddr6, sin_server6, | 1743 | memcpy(&tcp_ses->dstaddr, sin_server6, |
1685 | sizeof(struct sockaddr_in6)); | 1744 | sizeof(struct sockaddr_in6)); |
1686 | rc = ipv6_connect(tcp_ses); | 1745 | } else |
1687 | } else { | 1746 | memcpy(&tcp_ses->dstaddr, sin_server, |
1688 | memcpy(&tcp_ses->addr.sockAddr, sin_server, | 1747 | sizeof(struct sockaddr_in)); |
1689 | sizeof(struct sockaddr_in)); | 1748 | |
1690 | rc = ipv4_connect(tcp_ses); | 1749 | rc = ip_connect(tcp_ses); |
1691 | } | ||
1692 | if (rc < 0) { | 1750 | if (rc < 0) { |
1693 | cERROR(1, "Error connecting to socket. Aborting operation"); | 1751 | cERROR(1, "Error connecting to socket. Aborting operation"); |
1694 | goto out_err_crypto_release; | 1752 | goto out_err_crypto_release; |
@@ -1715,11 +1773,16 @@ cifs_get_tcp_session(struct smb_vol *volume_info) | |||
1715 | 1773 | ||
1716 | cifs_fscache_get_client_cookie(tcp_ses); | 1774 | cifs_fscache_get_client_cookie(tcp_ses); |
1717 | 1775 | ||
1776 | /* queue echo request delayed work */ | ||
1777 | queue_delayed_work(system_nrt_wq, &tcp_ses->echo, SMB_ECHO_INTERVAL); | ||
1778 | |||
1718 | return tcp_ses; | 1779 | return tcp_ses; |
1719 | 1780 | ||
1720 | out_err_crypto_release: | 1781 | out_err_crypto_release: |
1721 | cifs_crypto_shash_release(tcp_ses); | 1782 | cifs_crypto_shash_release(tcp_ses); |
1722 | 1783 | ||
1784 | put_net(cifs_net_ns(tcp_ses)); | ||
1785 | |||
1723 | out_err: | 1786 | out_err: |
1724 | if (tcp_ses) { | 1787 | if (tcp_ses) { |
1725 | if (!IS_ERR(tcp_ses->hostname)) | 1788 | if (!IS_ERR(tcp_ses->hostname)) |
@@ -1793,6 +1856,8 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info) | |||
1793 | { | 1856 | { |
1794 | int rc = -ENOMEM, xid; | 1857 | int rc = -ENOMEM, xid; |
1795 | struct cifsSesInfo *ses; | 1858 | struct cifsSesInfo *ses; |
1859 | struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr; | ||
1860 | struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr; | ||
1796 | 1861 | ||
1797 | xid = GetXid(); | 1862 | xid = GetXid(); |
1798 | 1863 | ||
@@ -1836,12 +1901,10 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info) | |||
1836 | 1901 | ||
1837 | /* new SMB session uses our server ref */ | 1902 | /* new SMB session uses our server ref */ |
1838 | ses->server = server; | 1903 | ses->server = server; |
1839 | if (server->addr.sockAddr6.sin6_family == AF_INET6) | 1904 | if (server->dstaddr.ss_family == AF_INET6) |
1840 | sprintf(ses->serverName, "%pI6", | 1905 | sprintf(ses->serverName, "%pI6", &addr6->sin6_addr); |
1841 | &server->addr.sockAddr6.sin6_addr); | ||
1842 | else | 1906 | else |
1843 | sprintf(ses->serverName, "%pI4", | 1907 | sprintf(ses->serverName, "%pI4", &addr->sin_addr); |
1844 | &server->addr.sockAddr.sin_addr.s_addr); | ||
1845 | 1908 | ||
1846 | if (volume_info->username) | 1909 | if (volume_info->username) |
1847 | strncpy(ses->userName, volume_info->username, | 1910 | strncpy(ses->userName, volume_info->username, |
@@ -2136,19 +2199,106 @@ bind_socket(struct TCP_Server_Info *server) | |||
2136 | } | 2199 | } |
2137 | 2200 | ||
2138 | static int | 2201 | static int |
2139 | ipv4_connect(struct TCP_Server_Info *server) | 2202 | ip_rfc1001_connect(struct TCP_Server_Info *server) |
2203 | { | ||
2204 | int rc = 0; | ||
2205 | /* | ||
2206 | * some servers require RFC1001 sessinit before sending | ||
2207 | * negprot - BB check reconnection in case where second | ||
2208 | * sessinit is sent but no second negprot | ||
2209 | */ | ||
2210 | struct rfc1002_session_packet *ses_init_buf; | ||
2211 | struct smb_hdr *smb_buf; | ||
2212 | ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet), | ||
2213 | GFP_KERNEL); | ||
2214 | if (ses_init_buf) { | ||
2215 | ses_init_buf->trailer.session_req.called_len = 32; | ||
2216 | |||
2217 | if (server->server_RFC1001_name && | ||
2218 | server->server_RFC1001_name[0] != 0) | ||
2219 | rfc1002mangle(ses_init_buf->trailer. | ||
2220 | session_req.called_name, | ||
2221 | server->server_RFC1001_name, | ||
2222 | RFC1001_NAME_LEN_WITH_NULL); | ||
2223 | else | ||
2224 | rfc1002mangle(ses_init_buf->trailer. | ||
2225 | session_req.called_name, | ||
2226 | DEFAULT_CIFS_CALLED_NAME, | ||
2227 | RFC1001_NAME_LEN_WITH_NULL); | ||
2228 | |||
2229 | ses_init_buf->trailer.session_req.calling_len = 32; | ||
2230 | |||
2231 | /* | ||
2232 | * calling name ends in null (byte 16) from old smb | ||
2233 | * convention. | ||
2234 | */ | ||
2235 | if (server->workstation_RFC1001_name && | ||
2236 | server->workstation_RFC1001_name[0] != 0) | ||
2237 | rfc1002mangle(ses_init_buf->trailer. | ||
2238 | session_req.calling_name, | ||
2239 | server->workstation_RFC1001_name, | ||
2240 | RFC1001_NAME_LEN_WITH_NULL); | ||
2241 | else | ||
2242 | rfc1002mangle(ses_init_buf->trailer. | ||
2243 | session_req.calling_name, | ||
2244 | "LINUX_CIFS_CLNT", | ||
2245 | RFC1001_NAME_LEN_WITH_NULL); | ||
2246 | |||
2247 | ses_init_buf->trailer.session_req.scope1 = 0; | ||
2248 | ses_init_buf->trailer.session_req.scope2 = 0; | ||
2249 | smb_buf = (struct smb_hdr *)ses_init_buf; | ||
2250 | |||
2251 | /* sizeof RFC1002_SESSION_REQUEST with no scope */ | ||
2252 | smb_buf->smb_buf_length = 0x81000044; | ||
2253 | rc = smb_send(server, smb_buf, 0x44); | ||
2254 | kfree(ses_init_buf); | ||
2255 | /* | ||
2256 | * RFC1001 layer in at least one server | ||
2257 | * requires very short break before negprot | ||
2258 | * presumably because not expecting negprot | ||
2259 | * to follow so fast. This is a simple | ||
2260 | * solution that works without | ||
2261 | * complicating the code and causes no | ||
2262 | * significant slowing down on mount | ||
2263 | * for everyone else | ||
2264 | */ | ||
2265 | usleep_range(1000, 2000); | ||
2266 | } | ||
2267 | /* | ||
2268 | * else the negprot may still work without this | ||
2269 | * even though malloc failed | ||
2270 | */ | ||
2271 | |||
2272 | return rc; | ||
2273 | } | ||
2274 | |||
2275 | static int | ||
2276 | generic_ip_connect(struct TCP_Server_Info *server) | ||
2140 | { | 2277 | { |
2141 | int rc = 0; | 2278 | int rc = 0; |
2142 | int val; | 2279 | unsigned short int sport; |
2143 | bool connected = false; | 2280 | int slen, sfamily; |
2144 | __be16 orig_port = 0; | ||
2145 | struct socket *socket = server->ssocket; | 2281 | struct socket *socket = server->ssocket; |
2282 | struct sockaddr *saddr; | ||
2283 | |||
2284 | saddr = (struct sockaddr *) &server->dstaddr; | ||
2285 | |||
2286 | if (server->dstaddr.ss_family == AF_INET6) { | ||
2287 | sport = ((struct sockaddr_in6 *) saddr)->sin6_port; | ||
2288 | slen = sizeof(struct sockaddr_in6); | ||
2289 | sfamily = AF_INET6; | ||
2290 | } else { | ||
2291 | sport = ((struct sockaddr_in *) saddr)->sin_port; | ||
2292 | slen = sizeof(struct sockaddr_in); | ||
2293 | sfamily = AF_INET; | ||
2294 | } | ||
2146 | 2295 | ||
2147 | if (socket == NULL) { | 2296 | if (socket == NULL) { |
2148 | rc = sock_create_kern(PF_INET, SOCK_STREAM, | 2297 | rc = __sock_create(cifs_net_ns(server), sfamily, SOCK_STREAM, |
2149 | IPPROTO_TCP, &socket); | 2298 | IPPROTO_TCP, &socket, 1); |
2150 | if (rc < 0) { | 2299 | if (rc < 0) { |
2151 | cERROR(1, "Error %d creating socket", rc); | 2300 | cERROR(1, "Error %d creating socket", rc); |
2301 | server->ssocket = NULL; | ||
2152 | return rc; | 2302 | return rc; |
2153 | } | 2303 | } |
2154 | 2304 | ||
@@ -2156,63 +2306,28 @@ ipv4_connect(struct TCP_Server_Info *server) | |||
2156 | cFYI(1, "Socket created"); | 2306 | cFYI(1, "Socket created"); |
2157 | server->ssocket = socket; | 2307 | server->ssocket = socket; |
2158 | socket->sk->sk_allocation = GFP_NOFS; | 2308 | socket->sk->sk_allocation = GFP_NOFS; |
2159 | cifs_reclassify_socket4(socket); | 2309 | if (sfamily == AF_INET6) |
2310 | cifs_reclassify_socket6(socket); | ||
2311 | else | ||
2312 | cifs_reclassify_socket4(socket); | ||
2160 | } | 2313 | } |
2161 | 2314 | ||
2162 | rc = bind_socket(server); | 2315 | rc = bind_socket(server); |
2163 | if (rc < 0) | 2316 | if (rc < 0) |
2164 | return rc; | 2317 | return rc; |
2165 | 2318 | ||
2166 | /* user overrode default port */ | 2319 | rc = socket->ops->connect(socket, saddr, slen, 0); |
2167 | if (server->addr.sockAddr.sin_port) { | 2320 | if (rc < 0) { |
2168 | rc = socket->ops->connect(socket, (struct sockaddr *) | 2321 | cFYI(1, "Error %d connecting to server", rc); |
2169 | &server->addr.sockAddr, | ||
2170 | sizeof(struct sockaddr_in), 0); | ||
2171 | if (rc >= 0) | ||
2172 | connected = true; | ||
2173 | } | ||
2174 | |||
2175 | if (!connected) { | ||
2176 | /* save original port so we can retry user specified port | ||
2177 | later if fall back ports fail this time */ | ||
2178 | orig_port = server->addr.sockAddr.sin_port; | ||
2179 | |||
2180 | /* do not retry on the same port we just failed on */ | ||
2181 | if (server->addr.sockAddr.sin_port != htons(CIFS_PORT)) { | ||
2182 | server->addr.sockAddr.sin_port = htons(CIFS_PORT); | ||
2183 | rc = socket->ops->connect(socket, | ||
2184 | (struct sockaddr *) | ||
2185 | &server->addr.sockAddr, | ||
2186 | sizeof(struct sockaddr_in), 0); | ||
2187 | if (rc >= 0) | ||
2188 | connected = true; | ||
2189 | } | ||
2190 | } | ||
2191 | if (!connected) { | ||
2192 | server->addr.sockAddr.sin_port = htons(RFC1001_PORT); | ||
2193 | rc = socket->ops->connect(socket, (struct sockaddr *) | ||
2194 | &server->addr.sockAddr, | ||
2195 | sizeof(struct sockaddr_in), 0); | ||
2196 | if (rc >= 0) | ||
2197 | connected = true; | ||
2198 | } | ||
2199 | |||
2200 | /* give up here - unless we want to retry on different | ||
2201 | protocol families some day */ | ||
2202 | if (!connected) { | ||
2203 | if (orig_port) | ||
2204 | server->addr.sockAddr.sin_port = orig_port; | ||
2205 | cFYI(1, "Error %d connecting to server via ipv4", rc); | ||
2206 | sock_release(socket); | 2322 | sock_release(socket); |
2207 | server->ssocket = NULL; | 2323 | server->ssocket = NULL; |
2208 | return rc; | 2324 | return rc; |
2209 | } | 2325 | } |
2210 | 2326 | ||
2211 | |||
2212 | /* | 2327 | /* |
2213 | * Eventually check for other socket options to change from | 2328 | * Eventually check for other socket options to change from |
2214 | * the default. sock_setsockopt not used because it expects | 2329 | * the default. sock_setsockopt not used because it expects |
2215 | * user space buffer | 2330 | * user space buffer |
2216 | */ | 2331 | */ |
2217 | socket->sk->sk_rcvtimeo = 7 * HZ; | 2332 | socket->sk->sk_rcvtimeo = 7 * HZ; |
2218 | socket->sk->sk_sndtimeo = 5 * HZ; | 2333 | socket->sk->sk_sndtimeo = 5 * HZ; |
@@ -2226,7 +2341,7 @@ ipv4_connect(struct TCP_Server_Info *server) | |||
2226 | } | 2341 | } |
2227 | 2342 | ||
2228 | if (server->tcp_nodelay) { | 2343 | if (server->tcp_nodelay) { |
2229 | val = 1; | 2344 | int val = 1; |
2230 | rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY, | 2345 | rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY, |
2231 | (char *)&val, sizeof(val)); | 2346 | (char *)&val, sizeof(val)); |
2232 | if (rc) | 2347 | if (rc) |
@@ -2237,161 +2352,39 @@ ipv4_connect(struct TCP_Server_Info *server) | |||
2237 | socket->sk->sk_sndbuf, | 2352 | socket->sk->sk_sndbuf, |
2238 | socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo); | 2353 | socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo); |
2239 | 2354 | ||
2240 | /* send RFC1001 sessinit */ | 2355 | if (sport == htons(RFC1001_PORT)) |
2241 | if (server->addr.sockAddr.sin_port == htons(RFC1001_PORT)) { | 2356 | rc = ip_rfc1001_connect(server); |
2242 | /* some servers require RFC1001 sessinit before sending | ||
2243 | negprot - BB check reconnection in case where second | ||
2244 | sessinit is sent but no second negprot */ | ||
2245 | struct rfc1002_session_packet *ses_init_buf; | ||
2246 | struct smb_hdr *smb_buf; | ||
2247 | ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet), | ||
2248 | GFP_KERNEL); | ||
2249 | if (ses_init_buf) { | ||
2250 | ses_init_buf->trailer.session_req.called_len = 32; | ||
2251 | if (server->server_RFC1001_name && | ||
2252 | server->server_RFC1001_name[0] != 0) | ||
2253 | rfc1002mangle(ses_init_buf->trailer. | ||
2254 | session_req.called_name, | ||
2255 | server->server_RFC1001_name, | ||
2256 | RFC1001_NAME_LEN_WITH_NULL); | ||
2257 | else | ||
2258 | rfc1002mangle(ses_init_buf->trailer. | ||
2259 | session_req.called_name, | ||
2260 | DEFAULT_CIFS_CALLED_NAME, | ||
2261 | RFC1001_NAME_LEN_WITH_NULL); | ||
2262 | |||
2263 | ses_init_buf->trailer.session_req.calling_len = 32; | ||
2264 | |||
2265 | /* calling name ends in null (byte 16) from old smb | ||
2266 | convention. */ | ||
2267 | if (server->workstation_RFC1001_name && | ||
2268 | server->workstation_RFC1001_name[0] != 0) | ||
2269 | rfc1002mangle(ses_init_buf->trailer. | ||
2270 | session_req.calling_name, | ||
2271 | server->workstation_RFC1001_name, | ||
2272 | RFC1001_NAME_LEN_WITH_NULL); | ||
2273 | else | ||
2274 | rfc1002mangle(ses_init_buf->trailer. | ||
2275 | session_req.calling_name, | ||
2276 | "LINUX_CIFS_CLNT", | ||
2277 | RFC1001_NAME_LEN_WITH_NULL); | ||
2278 | |||
2279 | ses_init_buf->trailer.session_req.scope1 = 0; | ||
2280 | ses_init_buf->trailer.session_req.scope2 = 0; | ||
2281 | smb_buf = (struct smb_hdr *)ses_init_buf; | ||
2282 | /* sizeof RFC1002_SESSION_REQUEST with no scope */ | ||
2283 | smb_buf->smb_buf_length = 0x81000044; | ||
2284 | rc = smb_send(server, smb_buf, 0x44); | ||
2285 | kfree(ses_init_buf); | ||
2286 | msleep(1); /* RFC1001 layer in at least one server | ||
2287 | requires very short break before negprot | ||
2288 | presumably because not expecting negprot | ||
2289 | to follow so fast. This is a simple | ||
2290 | solution that works without | ||
2291 | complicating the code and causes no | ||
2292 | significant slowing down on mount | ||
2293 | for everyone else */ | ||
2294 | } | ||
2295 | /* else the negprot may still work without this | ||
2296 | even though malloc failed */ | ||
2297 | |||
2298 | } | ||
2299 | 2357 | ||
2300 | return rc; | 2358 | return rc; |
2301 | } | 2359 | } |
2302 | 2360 | ||
2303 | static int | 2361 | static int |
2304 | ipv6_connect(struct TCP_Server_Info *server) | 2362 | ip_connect(struct TCP_Server_Info *server) |
2305 | { | 2363 | { |
2306 | int rc = 0; | 2364 | unsigned short int *sport; |
2307 | int val; | 2365 | struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr; |
2308 | bool connected = false; | 2366 | struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr; |
2309 | __be16 orig_port = 0; | ||
2310 | struct socket *socket = server->ssocket; | ||
2311 | 2367 | ||
2312 | if (socket == NULL) { | 2368 | if (server->dstaddr.ss_family == AF_INET6) |
2313 | rc = sock_create_kern(PF_INET6, SOCK_STREAM, | 2369 | sport = &addr6->sin6_port; |
2314 | IPPROTO_TCP, &socket); | 2370 | else |
2315 | if (rc < 0) { | 2371 | sport = &addr->sin_port; |
2316 | cERROR(1, "Error %d creating ipv6 socket", rc); | ||
2317 | socket = NULL; | ||
2318 | return rc; | ||
2319 | } | ||
2320 | 2372 | ||
2321 | /* BB other socket options to set KEEPALIVE, NODELAY? */ | 2373 | if (*sport == 0) { |
2322 | cFYI(1, "ipv6 Socket created"); | 2374 | int rc; |
2323 | server->ssocket = socket; | ||
2324 | socket->sk->sk_allocation = GFP_NOFS; | ||
2325 | cifs_reclassify_socket6(socket); | ||
2326 | } | ||
2327 | 2375 | ||
2328 | rc = bind_socket(server); | 2376 | /* try with 445 port at first */ |
2329 | if (rc < 0) | 2377 | *sport = htons(CIFS_PORT); |
2330 | return rc; | ||
2331 | 2378 | ||
2332 | /* user overrode default port */ | 2379 | rc = generic_ip_connect(server); |
2333 | if (server->addr.sockAddr6.sin6_port) { | ||
2334 | rc = socket->ops->connect(socket, | ||
2335 | (struct sockaddr *) &server->addr.sockAddr6, | ||
2336 | sizeof(struct sockaddr_in6), 0); | ||
2337 | if (rc >= 0) | 2380 | if (rc >= 0) |
2338 | connected = true; | 2381 | return rc; |
2339 | } | ||
2340 | |||
2341 | if (!connected) { | ||
2342 | /* save original port so we can retry user specified port | ||
2343 | later if fall back ports fail this time */ | ||
2344 | |||
2345 | orig_port = server->addr.sockAddr6.sin6_port; | ||
2346 | /* do not retry on the same port we just failed on */ | ||
2347 | if (server->addr.sockAddr6.sin6_port != htons(CIFS_PORT)) { | ||
2348 | server->addr.sockAddr6.sin6_port = htons(CIFS_PORT); | ||
2349 | rc = socket->ops->connect(socket, (struct sockaddr *) | ||
2350 | &server->addr.sockAddr6, | ||
2351 | sizeof(struct sockaddr_in6), 0); | ||
2352 | if (rc >= 0) | ||
2353 | connected = true; | ||
2354 | } | ||
2355 | } | ||
2356 | if (!connected) { | ||
2357 | server->addr.sockAddr6.sin6_port = htons(RFC1001_PORT); | ||
2358 | rc = socket->ops->connect(socket, (struct sockaddr *) | ||
2359 | &server->addr.sockAddr6, | ||
2360 | sizeof(struct sockaddr_in6), 0); | ||
2361 | if (rc >= 0) | ||
2362 | connected = true; | ||
2363 | } | ||
2364 | |||
2365 | /* give up here - unless we want to retry on different | ||
2366 | protocol families some day */ | ||
2367 | if (!connected) { | ||
2368 | if (orig_port) | ||
2369 | server->addr.sockAddr6.sin6_port = orig_port; | ||
2370 | cFYI(1, "Error %d connecting to server via ipv6", rc); | ||
2371 | sock_release(socket); | ||
2372 | server->ssocket = NULL; | ||
2373 | return rc; | ||
2374 | } | ||
2375 | |||
2376 | /* | ||
2377 | * Eventually check for other socket options to change from | ||
2378 | * the default. sock_setsockopt not used because it expects | ||
2379 | * user space buffer | ||
2380 | */ | ||
2381 | socket->sk->sk_rcvtimeo = 7 * HZ; | ||
2382 | socket->sk->sk_sndtimeo = 5 * HZ; | ||
2383 | 2382 | ||
2384 | if (server->tcp_nodelay) { | 2383 | /* if it failed, try with 139 port */ |
2385 | val = 1; | 2384 | *sport = htons(RFC1001_PORT); |
2386 | rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY, | ||
2387 | (char *)&val, sizeof(val)); | ||
2388 | if (rc) | ||
2389 | cFYI(1, "set TCP_NODELAY socket option error %d", rc); | ||
2390 | } | 2385 | } |
2391 | 2386 | ||
2392 | server->ssocket = socket; | 2387 | return generic_ip_connect(server); |
2393 | |||
2394 | return rc; | ||
2395 | } | 2388 | } |
2396 | 2389 | ||
2397 | void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon, | 2390 | void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon, |
@@ -2614,6 +2607,8 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info, | |||
2614 | if (pvolume_info->multiuser) | 2607 | if (pvolume_info->multiuser) |
2615 | cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER | | 2608 | cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER | |
2616 | CIFS_MOUNT_NO_PERM); | 2609 | CIFS_MOUNT_NO_PERM); |
2610 | if (pvolume_info->strict_io) | ||
2611 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO; | ||
2617 | if (pvolume_info->direct_io) { | 2612 | if (pvolume_info->direct_io) { |
2618 | cFYI(1, "mounting share using direct i/o"); | 2613 | cFYI(1, "mounting share using direct i/o"); |
2619 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; | 2614 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; |
@@ -2970,8 +2965,8 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
2970 | TCONX_RSP *pSMBr; | 2965 | TCONX_RSP *pSMBr; |
2971 | unsigned char *bcc_ptr; | 2966 | unsigned char *bcc_ptr; |
2972 | int rc = 0; | 2967 | int rc = 0; |
2973 | int length, bytes_left; | 2968 | int length; |
2974 | __u16 count; | 2969 | __u16 bytes_left, count; |
2975 | 2970 | ||
2976 | if (ses == NULL) | 2971 | if (ses == NULL) |
2977 | return -EIO; | 2972 | return -EIO; |
@@ -2999,7 +2994,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
2999 | bcc_ptr++; /* skip password */ | 2994 | bcc_ptr++; /* skip password */ |
3000 | /* already aligned so no need to do it below */ | 2995 | /* already aligned so no need to do it below */ |
3001 | } else { | 2996 | } else { |
3002 | pSMB->PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE); | 2997 | pSMB->PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE); |
3003 | /* BB FIXME add code to fail this if NTLMv2 or Kerberos | 2998 | /* BB FIXME add code to fail this if NTLMv2 or Kerberos |
3004 | specified as required (when that support is added to | 2999 | specified as required (when that support is added to |
3005 | the vfs in the future) as only NTLM or the much | 3000 | the vfs in the future) as only NTLM or the much |
@@ -3015,9 +3010,10 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
3015 | bcc_ptr); | 3010 | bcc_ptr); |
3016 | else | 3011 | else |
3017 | #endif /* CIFS_WEAK_PW_HASH */ | 3012 | #endif /* CIFS_WEAK_PW_HASH */ |
3018 | SMBNTencrypt(tcon->password, ses->server->cryptkey, bcc_ptr); | 3013 | rc = SMBNTencrypt(tcon->password, ses->server->cryptkey, |
3014 | bcc_ptr); | ||
3019 | 3015 | ||
3020 | bcc_ptr += CIFS_SESS_KEY_SIZE; | 3016 | bcc_ptr += CIFS_AUTH_RESP_SIZE; |
3021 | if (ses->capabilities & CAP_UNICODE) { | 3017 | if (ses->capabilities & CAP_UNICODE) { |
3022 | /* must align unicode strings */ | 3018 | /* must align unicode strings */ |
3023 | *bcc_ptr = 0; /* null byte password */ | 3019 | *bcc_ptr = 0; /* null byte password */ |
@@ -3055,7 +3051,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
3055 | pSMB->ByteCount = cpu_to_le16(count); | 3051 | pSMB->ByteCount = cpu_to_le16(count); |
3056 | 3052 | ||
3057 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, | 3053 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, |
3058 | CIFS_STD_OP); | 3054 | 0); |
3059 | 3055 | ||
3060 | /* above now done in SendReceive */ | 3056 | /* above now done in SendReceive */ |
3061 | if ((rc == 0) && (tcon != NULL)) { | 3057 | if ((rc == 0) && (tcon != NULL)) { |
@@ -3065,7 +3061,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
3065 | tcon->need_reconnect = false; | 3061 | tcon->need_reconnect = false; |
3066 | tcon->tid = smb_buffer_response->Tid; | 3062 | tcon->tid = smb_buffer_response->Tid; |
3067 | bcc_ptr = pByteArea(smb_buffer_response); | 3063 | bcc_ptr = pByteArea(smb_buffer_response); |
3068 | bytes_left = BCC(smb_buffer_response); | 3064 | bytes_left = get_bcc(smb_buffer_response); |
3069 | length = strnlen(bcc_ptr, bytes_left - 2); | 3065 | length = strnlen(bcc_ptr, bytes_left - 2); |
3070 | if (smb_buffer->Flags2 & SMBFLG2_UNICODE) | 3066 | if (smb_buffer->Flags2 & SMBFLG2_UNICODE) |
3071 | is_unicode = true; | 3067 | is_unicode = true; |
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 3840eddbfb7a..dd5f22918c33 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
@@ -130,17 +130,6 @@ cifs_bp_rename_retry: | |||
130 | return full_path; | 130 | return full_path; |
131 | } | 131 | } |
132 | 132 | ||
133 | static void setup_cifs_dentry(struct cifsTconInfo *tcon, | ||
134 | struct dentry *direntry, | ||
135 | struct inode *newinode) | ||
136 | { | ||
137 | if (tcon->nocase) | ||
138 | direntry->d_op = &cifs_ci_dentry_ops; | ||
139 | else | ||
140 | direntry->d_op = &cifs_dentry_ops; | ||
141 | d_instantiate(direntry, newinode); | ||
142 | } | ||
143 | |||
144 | /* Inode operations in similar order to how they appear in Linux file fs.h */ | 133 | /* Inode operations in similar order to how they appear in Linux file fs.h */ |
145 | 134 | ||
146 | int | 135 | int |
@@ -293,10 +282,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
293 | args.uid = NO_CHANGE_64; | 282 | args.uid = NO_CHANGE_64; |
294 | args.gid = NO_CHANGE_64; | 283 | args.gid = NO_CHANGE_64; |
295 | } | 284 | } |
296 | CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args, | 285 | CIFSSMBUnixSetFileInfo(xid, tcon, &args, fileHandle, |
297 | cifs_sb->local_nls, | 286 | current->tgid); |
298 | cifs_sb->mnt_cifs_flags & | ||
299 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
300 | } else { | 287 | } else { |
301 | /* BB implement mode setting via Windows security | 288 | /* BB implement mode setting via Windows security |
302 | descriptors e.g. */ | 289 | descriptors e.g. */ |
@@ -329,7 +316,7 @@ cifs_create_get_file_info: | |||
329 | 316 | ||
330 | cifs_create_set_dentry: | 317 | cifs_create_set_dentry: |
331 | if (rc == 0) | 318 | if (rc == 0) |
332 | setup_cifs_dentry(tcon, direntry, newinode); | 319 | d_instantiate(direntry, newinode); |
333 | else | 320 | else |
334 | cFYI(1, "Create worked, get_inode_info failed rc = %d", rc); | 321 | cFYI(1, "Create worked, get_inode_info failed rc = %d", rc); |
335 | 322 | ||
@@ -420,10 +407,6 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, | |||
420 | 407 | ||
421 | rc = cifs_get_inode_info_unix(&newinode, full_path, | 408 | rc = cifs_get_inode_info_unix(&newinode, full_path, |
422 | inode->i_sb, xid); | 409 | inode->i_sb, xid); |
423 | if (pTcon->nocase) | ||
424 | direntry->d_op = &cifs_ci_dentry_ops; | ||
425 | else | ||
426 | direntry->d_op = &cifs_dentry_ops; | ||
427 | 410 | ||
428 | if (rc == 0) | 411 | if (rc == 0) |
429 | d_instantiate(direntry, newinode); | 412 | d_instantiate(direntry, newinode); |
@@ -603,10 +586,6 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, | |||
603 | parent_dir_inode->i_sb, xid, NULL); | 586 | parent_dir_inode->i_sb, xid, NULL); |
604 | 587 | ||
605 | if ((rc == 0) && (newInode != NULL)) { | 588 | if ((rc == 0) && (newInode != NULL)) { |
606 | if (pTcon->nocase) | ||
607 | direntry->d_op = &cifs_ci_dentry_ops; | ||
608 | else | ||
609 | direntry->d_op = &cifs_dentry_ops; | ||
610 | d_add(direntry, newInode); | 589 | d_add(direntry, newInode); |
611 | if (posix_open) { | 590 | if (posix_open) { |
612 | filp = lookup_instantiate_filp(nd, direntry, | 591 | filp = lookup_instantiate_filp(nd, direntry, |
@@ -633,10 +612,6 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, | |||
633 | } else if (rc == -ENOENT) { | 612 | } else if (rc == -ENOENT) { |
634 | rc = 0; | 613 | rc = 0; |
635 | direntry->d_time = jiffies; | 614 | direntry->d_time = jiffies; |
636 | if (pTcon->nocase) | ||
637 | direntry->d_op = &cifs_ci_dentry_ops; | ||
638 | else | ||
639 | direntry->d_op = &cifs_dentry_ops; | ||
640 | d_add(direntry, NULL); | 615 | d_add(direntry, NULL); |
641 | /* if it was once a directory (but how can we tell?) we could do | 616 | /* if it was once a directory (but how can we tell?) we could do |
642 | shrink_dcache_parent(direntry); */ | 617 | shrink_dcache_parent(direntry); */ |
@@ -656,22 +631,37 @@ lookup_out: | |||
656 | static int | 631 | static int |
657 | cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd) | 632 | cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd) |
658 | { | 633 | { |
659 | int isValid = 1; | 634 | if (nd->flags & LOOKUP_RCU) |
635 | return -ECHILD; | ||
660 | 636 | ||
661 | if (direntry->d_inode) { | 637 | if (direntry->d_inode) { |
662 | if (cifs_revalidate_dentry(direntry)) | 638 | if (cifs_revalidate_dentry(direntry)) |
663 | return 0; | 639 | return 0; |
664 | } else { | 640 | else |
665 | cFYI(1, "neg dentry 0x%p name = %s", | 641 | return 1; |
666 | direntry, direntry->d_name.name); | ||
667 | if (time_after(jiffies, direntry->d_time + HZ) || | ||
668 | !lookupCacheEnabled) { | ||
669 | d_drop(direntry); | ||
670 | isValid = 0; | ||
671 | } | ||
672 | } | 642 | } |
673 | 643 | ||
674 | return isValid; | 644 | /* |
645 | * This may be nfsd (or something), anyway, we can't see the | ||
646 | * intent of this. So, since this can be for creation, drop it. | ||
647 | */ | ||
648 | if (!nd) | ||
649 | return 0; | ||
650 | |||
651 | /* | ||
652 | * Drop the negative dentry, in order to make sure to use the | ||
653 | * case sensitive name which is specified by user if this is | ||
654 | * for creation. | ||
655 | */ | ||
656 | if (!(nd->flags & (LOOKUP_CONTINUE | LOOKUP_PARENT))) { | ||
657 | if (nd->flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET)) | ||
658 | return 0; | ||
659 | } | ||
660 | |||
661 | if (time_after(jiffies, direntry->d_time + HZ) || !lookupCacheEnabled) | ||
662 | return 0; | ||
663 | |||
664 | return 1; | ||
675 | } | 665 | } |
676 | 666 | ||
677 | /* static int cifs_d_delete(struct dentry *direntry) | 667 | /* static int cifs_d_delete(struct dentry *direntry) |
@@ -685,12 +675,14 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd) | |||
685 | 675 | ||
686 | const struct dentry_operations cifs_dentry_ops = { | 676 | const struct dentry_operations cifs_dentry_ops = { |
687 | .d_revalidate = cifs_d_revalidate, | 677 | .d_revalidate = cifs_d_revalidate, |
678 | .d_automount = cifs_dfs_d_automount, | ||
688 | /* d_delete: cifs_d_delete, */ /* not needed except for debugging */ | 679 | /* d_delete: cifs_d_delete, */ /* not needed except for debugging */ |
689 | }; | 680 | }; |
690 | 681 | ||
691 | static int cifs_ci_hash(struct dentry *dentry, struct qstr *q) | 682 | static int cifs_ci_hash(const struct dentry *dentry, const struct inode *inode, |
683 | struct qstr *q) | ||
692 | { | 684 | { |
693 | struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls; | 685 | struct nls_table *codepage = CIFS_SB(dentry->d_sb)->local_nls; |
694 | unsigned long hash; | 686 | unsigned long hash; |
695 | int i; | 687 | int i; |
696 | 688 | ||
@@ -703,21 +695,16 @@ static int cifs_ci_hash(struct dentry *dentry, struct qstr *q) | |||
703 | return 0; | 695 | return 0; |
704 | } | 696 | } |
705 | 697 | ||
706 | static int cifs_ci_compare(struct dentry *dentry, struct qstr *a, | 698 | static int cifs_ci_compare(const struct dentry *parent, |
707 | struct qstr *b) | 699 | const struct inode *pinode, |
700 | const struct dentry *dentry, const struct inode *inode, | ||
701 | unsigned int len, const char *str, const struct qstr *name) | ||
708 | { | 702 | { |
709 | struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls; | 703 | struct nls_table *codepage = CIFS_SB(pinode->i_sb)->local_nls; |
710 | 704 | ||
711 | if ((a->len == b->len) && | 705 | if ((name->len == len) && |
712 | (nls_strnicmp(codepage, a->name, b->name, a->len) == 0)) { | 706 | (nls_strnicmp(codepage, name->name, str, len) == 0)) |
713 | /* | ||
714 | * To preserve case, don't let an existing negative dentry's | ||
715 | * case take precedence. If a is not a negative dentry, this | ||
716 | * should have no side effects | ||
717 | */ | ||
718 | memcpy((void *)a->name, b->name, a->len); | ||
719 | return 0; | 707 | return 0; |
720 | } | ||
721 | return 1; | 708 | return 1; |
722 | } | 709 | } |
723 | 710 | ||
@@ -725,4 +712,5 @@ const struct dentry_operations cifs_ci_dentry_ops = { | |||
725 | .d_revalidate = cifs_d_revalidate, | 712 | .d_revalidate = cifs_d_revalidate, |
726 | .d_hash = cifs_ci_hash, | 713 | .d_hash = cifs_ci_hash, |
727 | .d_compare = cifs_ci_compare, | 714 | .d_compare = cifs_ci_compare, |
715 | .d_automount = cifs_dfs_d_automount, | ||
728 | }; | 716 | }; |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 5a28660ca2b5..e964b1cd5dd0 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -104,53 +104,6 @@ static inline int cifs_get_disposition(unsigned int flags) | |||
104 | return FILE_OPEN; | 104 | return FILE_OPEN; |
105 | } | 105 | } |
106 | 106 | ||
107 | static inline int cifs_open_inode_helper(struct inode *inode, | ||
108 | struct cifsTconInfo *pTcon, __u32 oplock, FILE_ALL_INFO *buf, | ||
109 | char *full_path, int xid) | ||
110 | { | ||
111 | struct cifsInodeInfo *pCifsInode = CIFS_I(inode); | ||
112 | struct timespec temp; | ||
113 | int rc; | ||
114 | |||
115 | if (pCifsInode->clientCanCacheRead) { | ||
116 | /* we have the inode open somewhere else | ||
117 | no need to discard cache data */ | ||
118 | goto client_can_cache; | ||
119 | } | ||
120 | |||
121 | /* BB need same check in cifs_create too? */ | ||
122 | /* if not oplocked, invalidate inode pages if mtime or file | ||
123 | size changed */ | ||
124 | temp = cifs_NTtimeToUnix(buf->LastWriteTime); | ||
125 | if (timespec_equal(&inode->i_mtime, &temp) && | ||
126 | (inode->i_size == | ||
127 | (loff_t)le64_to_cpu(buf->EndOfFile))) { | ||
128 | cFYI(1, "inode unchanged on server"); | ||
129 | } else { | ||
130 | if (inode->i_mapping) { | ||
131 | /* BB no need to lock inode until after invalidate | ||
132 | since namei code should already have it locked? */ | ||
133 | rc = filemap_write_and_wait(inode->i_mapping); | ||
134 | mapping_set_error(inode->i_mapping, rc); | ||
135 | } | ||
136 | cFYI(1, "invalidating remote inode since open detected it " | ||
137 | "changed"); | ||
138 | invalidate_remote_inode(inode); | ||
139 | } | ||
140 | |||
141 | client_can_cache: | ||
142 | if (pTcon->unix_ext) | ||
143 | rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb, | ||
144 | xid); | ||
145 | else | ||
146 | rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb, | ||
147 | xid, NULL); | ||
148 | |||
149 | cifs_set_oplock_level(pCifsInode, oplock); | ||
150 | |||
151 | return rc; | ||
152 | } | ||
153 | |||
154 | int cifs_posix_open(char *full_path, struct inode **pinode, | 107 | int cifs_posix_open(char *full_path, struct inode **pinode, |
155 | struct super_block *sb, int mode, unsigned int f_flags, | 108 | struct super_block *sb, int mode, unsigned int f_flags, |
156 | __u32 *poplock, __u16 *pnetfid, int xid) | 109 | __u32 *poplock, __u16 *pnetfid, int xid) |
@@ -213,6 +166,76 @@ posix_open_ret: | |||
213 | return rc; | 166 | return rc; |
214 | } | 167 | } |
215 | 168 | ||
169 | static int | ||
170 | cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb, | ||
171 | struct cifsTconInfo *tcon, unsigned int f_flags, __u32 *poplock, | ||
172 | __u16 *pnetfid, int xid) | ||
173 | { | ||
174 | int rc; | ||
175 | int desiredAccess; | ||
176 | int disposition; | ||
177 | FILE_ALL_INFO *buf; | ||
178 | |||
179 | desiredAccess = cifs_convert_flags(f_flags); | ||
180 | |||
181 | /********************************************************************* | ||
182 | * open flag mapping table: | ||
183 | * | ||
184 | * POSIX Flag CIFS Disposition | ||
185 | * ---------- ---------------- | ||
186 | * O_CREAT FILE_OPEN_IF | ||
187 | * O_CREAT | O_EXCL FILE_CREATE | ||
188 | * O_CREAT | O_TRUNC FILE_OVERWRITE_IF | ||
189 | * O_TRUNC FILE_OVERWRITE | ||
190 | * none of the above FILE_OPEN | ||
191 | * | ||
192 | * Note that there is not a direct match between disposition | ||
193 | * FILE_SUPERSEDE (ie create whether or not file exists although | ||
194 | * O_CREAT | O_TRUNC is similar but truncates the existing | ||
195 | * file rather than creating a new file as FILE_SUPERSEDE does | ||
196 | * (which uses the attributes / metadata passed in on open call) | ||
197 | *? | ||
198 | *? O_SYNC is a reasonable match to CIFS writethrough flag | ||
199 | *? and the read write flags match reasonably. O_LARGEFILE | ||
200 | *? is irrelevant because largefile support is always used | ||
201 | *? by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY, | ||
202 | * O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation | ||
203 | *********************************************************************/ | ||
204 | |||
205 | disposition = cifs_get_disposition(f_flags); | ||
206 | |||
207 | /* BB pass O_SYNC flag through on file attributes .. BB */ | ||
208 | |||
209 | buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); | ||
210 | if (!buf) | ||
211 | return -ENOMEM; | ||
212 | |||
213 | if (tcon->ses->capabilities & CAP_NT_SMBS) | ||
214 | rc = CIFSSMBOpen(xid, tcon, full_path, disposition, | ||
215 | desiredAccess, CREATE_NOT_DIR, pnetfid, poplock, buf, | ||
216 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags | ||
217 | & CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
218 | else | ||
219 | rc = SMBLegacyOpen(xid, tcon, full_path, disposition, | ||
220 | desiredAccess, CREATE_NOT_DIR, pnetfid, poplock, buf, | ||
221 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags | ||
222 | & CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
223 | |||
224 | if (rc) | ||
225 | goto out; | ||
226 | |||
227 | if (tcon->unix_ext) | ||
228 | rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb, | ||
229 | xid); | ||
230 | else | ||
231 | rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb, | ||
232 | xid, pnetfid); | ||
233 | |||
234 | out: | ||
235 | kfree(buf); | ||
236 | return rc; | ||
237 | } | ||
238 | |||
216 | struct cifsFileInfo * | 239 | struct cifsFileInfo * |
217 | cifs_new_fileinfo(__u16 fileHandle, struct file *file, | 240 | cifs_new_fileinfo(__u16 fileHandle, struct file *file, |
218 | struct tcon_link *tlink, __u32 oplock) | 241 | struct tcon_link *tlink, __u32 oplock) |
@@ -264,6 +287,7 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file) | |||
264 | struct inode *inode = cifs_file->dentry->d_inode; | 287 | struct inode *inode = cifs_file->dentry->d_inode; |
265 | struct cifsTconInfo *tcon = tlink_tcon(cifs_file->tlink); | 288 | struct cifsTconInfo *tcon = tlink_tcon(cifs_file->tlink); |
266 | struct cifsInodeInfo *cifsi = CIFS_I(inode); | 289 | struct cifsInodeInfo *cifsi = CIFS_I(inode); |
290 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
267 | struct cifsLockInfo *li, *tmp; | 291 | struct cifsLockInfo *li, *tmp; |
268 | 292 | ||
269 | spin_lock(&cifs_file_list_lock); | 293 | spin_lock(&cifs_file_list_lock); |
@@ -279,6 +303,13 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file) | |||
279 | if (list_empty(&cifsi->openFileList)) { | 303 | if (list_empty(&cifsi->openFileList)) { |
280 | cFYI(1, "closing last open instance for inode %p", | 304 | cFYI(1, "closing last open instance for inode %p", |
281 | cifs_file->dentry->d_inode); | 305 | cifs_file->dentry->d_inode); |
306 | |||
307 | /* in strict cache mode we need invalidate mapping on the last | ||
308 | close because it may cause a error when we open this file | ||
309 | again and get at least level II oplock */ | ||
310 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) | ||
311 | CIFS_I(inode)->invalid_mapping = true; | ||
312 | |||
282 | cifs_set_oplock_level(cifsi, 0); | 313 | cifs_set_oplock_level(cifsi, 0); |
283 | } | 314 | } |
284 | spin_unlock(&cifs_file_list_lock); | 315 | spin_unlock(&cifs_file_list_lock); |
@@ -315,12 +346,9 @@ int cifs_open(struct inode *inode, struct file *file) | |||
315 | struct cifsTconInfo *tcon; | 346 | struct cifsTconInfo *tcon; |
316 | struct tcon_link *tlink; | 347 | struct tcon_link *tlink; |
317 | struct cifsFileInfo *pCifsFile = NULL; | 348 | struct cifsFileInfo *pCifsFile = NULL; |
318 | struct cifsInodeInfo *pCifsInode; | ||
319 | char *full_path = NULL; | 349 | char *full_path = NULL; |
320 | int desiredAccess; | 350 | bool posix_open_ok = false; |
321 | int disposition; | ||
322 | __u16 netfid; | 351 | __u16 netfid; |
323 | FILE_ALL_INFO *buf = NULL; | ||
324 | 352 | ||
325 | xid = GetXid(); | 353 | xid = GetXid(); |
326 | 354 | ||
@@ -332,8 +360,6 @@ int cifs_open(struct inode *inode, struct file *file) | |||
332 | } | 360 | } |
333 | tcon = tlink_tcon(tlink); | 361 | tcon = tlink_tcon(tlink); |
334 | 362 | ||
335 | pCifsInode = CIFS_I(file->f_path.dentry->d_inode); | ||
336 | |||
337 | full_path = build_path_from_dentry(file->f_path.dentry); | 363 | full_path = build_path_from_dentry(file->f_path.dentry); |
338 | if (full_path == NULL) { | 364 | if (full_path == NULL) { |
339 | rc = -ENOMEM; | 365 | rc = -ENOMEM; |
@@ -358,17 +384,7 @@ int cifs_open(struct inode *inode, struct file *file) | |||
358 | file->f_flags, &oplock, &netfid, xid); | 384 | file->f_flags, &oplock, &netfid, xid); |
359 | if (rc == 0) { | 385 | if (rc == 0) { |
360 | cFYI(1, "posix open succeeded"); | 386 | cFYI(1, "posix open succeeded"); |
361 | 387 | posix_open_ok = true; | |
362 | pCifsFile = cifs_new_fileinfo(netfid, file, tlink, | ||
363 | oplock); | ||
364 | if (pCifsFile == NULL) { | ||
365 | CIFSSMBClose(xid, tcon, netfid); | ||
366 | rc = -ENOMEM; | ||
367 | } | ||
368 | |||
369 | cifs_fscache_set_inode_cookie(inode, file); | ||
370 | |||
371 | goto out; | ||
372 | } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { | 388 | } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { |
373 | if (tcon->ses->serverNOS) | 389 | if (tcon->ses->serverNOS) |
374 | cERROR(1, "server %s of type %s returned" | 390 | cERROR(1, "server %s of type %s returned" |
@@ -385,103 +401,39 @@ int cifs_open(struct inode *inode, struct file *file) | |||
385 | or DFS errors */ | 401 | or DFS errors */ |
386 | } | 402 | } |
387 | 403 | ||
388 | desiredAccess = cifs_convert_flags(file->f_flags); | 404 | if (!posix_open_ok) { |
389 | 405 | rc = cifs_nt_open(full_path, inode, cifs_sb, tcon, | |
390 | /********************************************************************* | 406 | file->f_flags, &oplock, &netfid, xid); |
391 | * open flag mapping table: | 407 | if (rc) |
392 | * | 408 | goto out; |
393 | * POSIX Flag CIFS Disposition | ||
394 | * ---------- ---------------- | ||
395 | * O_CREAT FILE_OPEN_IF | ||
396 | * O_CREAT | O_EXCL FILE_CREATE | ||
397 | * O_CREAT | O_TRUNC FILE_OVERWRITE_IF | ||
398 | * O_TRUNC FILE_OVERWRITE | ||
399 | * none of the above FILE_OPEN | ||
400 | * | ||
401 | * Note that there is not a direct match between disposition | ||
402 | * FILE_SUPERSEDE (ie create whether or not file exists although | ||
403 | * O_CREAT | O_TRUNC is similar but truncates the existing | ||
404 | * file rather than creating a new file as FILE_SUPERSEDE does | ||
405 | * (which uses the attributes / metadata passed in on open call) | ||
406 | *? | ||
407 | *? O_SYNC is a reasonable match to CIFS writethrough flag | ||
408 | *? and the read write flags match reasonably. O_LARGEFILE | ||
409 | *? is irrelevant because largefile support is always used | ||
410 | *? by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY, | ||
411 | * O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation | ||
412 | *********************************************************************/ | ||
413 | |||
414 | disposition = cifs_get_disposition(file->f_flags); | ||
415 | |||
416 | /* BB pass O_SYNC flag through on file attributes .. BB */ | ||
417 | |||
418 | /* Also refresh inode by passing in file_info buf returned by SMBOpen | ||
419 | and calling get_inode_info with returned buf (at least helps | ||
420 | non-Unix server case) */ | ||
421 | |||
422 | /* BB we can not do this if this is the second open of a file | ||
423 | and the first handle has writebehind data, we might be | ||
424 | able to simply do a filemap_fdatawrite/filemap_fdatawait first */ | ||
425 | buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); | ||
426 | if (!buf) { | ||
427 | rc = -ENOMEM; | ||
428 | goto out; | ||
429 | } | ||
430 | |||
431 | if (tcon->ses->capabilities & CAP_NT_SMBS) | ||
432 | rc = CIFSSMBOpen(xid, tcon, full_path, disposition, | ||
433 | desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf, | ||
434 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags | ||
435 | & CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
436 | else | ||
437 | rc = -EIO; /* no NT SMB support fall into legacy open below */ | ||
438 | |||
439 | if (rc == -EIO) { | ||
440 | /* Old server, try legacy style OpenX */ | ||
441 | rc = SMBLegacyOpen(xid, tcon, full_path, disposition, | ||
442 | desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf, | ||
443 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags | ||
444 | & CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
445 | } | ||
446 | if (rc) { | ||
447 | cFYI(1, "cifs_open returned 0x%x", rc); | ||
448 | goto out; | ||
449 | } | 409 | } |
450 | 410 | ||
451 | rc = cifs_open_inode_helper(inode, tcon, oplock, buf, full_path, xid); | ||
452 | if (rc != 0) | ||
453 | goto out; | ||
454 | |||
455 | pCifsFile = cifs_new_fileinfo(netfid, file, tlink, oplock); | 411 | pCifsFile = cifs_new_fileinfo(netfid, file, tlink, oplock); |
456 | if (pCifsFile == NULL) { | 412 | if (pCifsFile == NULL) { |
413 | CIFSSMBClose(xid, tcon, netfid); | ||
457 | rc = -ENOMEM; | 414 | rc = -ENOMEM; |
458 | goto out; | 415 | goto out; |
459 | } | 416 | } |
460 | 417 | ||
461 | cifs_fscache_set_inode_cookie(inode, file); | 418 | cifs_fscache_set_inode_cookie(inode, file); |
462 | 419 | ||
463 | if (oplock & CIFS_CREATE_ACTION) { | 420 | if ((oplock & CIFS_CREATE_ACTION) && !posix_open_ok && tcon->unix_ext) { |
464 | /* time to set mode which we can not set earlier due to | 421 | /* time to set mode which we can not set earlier due to |
465 | problems creating new read-only files */ | 422 | problems creating new read-only files */ |
466 | if (tcon->unix_ext) { | 423 | struct cifs_unix_set_info_args args = { |
467 | struct cifs_unix_set_info_args args = { | 424 | .mode = inode->i_mode, |
468 | .mode = inode->i_mode, | 425 | .uid = NO_CHANGE_64, |
469 | .uid = NO_CHANGE_64, | 426 | .gid = NO_CHANGE_64, |
470 | .gid = NO_CHANGE_64, | 427 | .ctime = NO_CHANGE_64, |
471 | .ctime = NO_CHANGE_64, | 428 | .atime = NO_CHANGE_64, |
472 | .atime = NO_CHANGE_64, | 429 | .mtime = NO_CHANGE_64, |
473 | .mtime = NO_CHANGE_64, | 430 | .device = 0, |
474 | .device = 0, | 431 | }; |
475 | }; | 432 | CIFSSMBUnixSetFileInfo(xid, tcon, &args, netfid, |
476 | CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args, | 433 | pCifsFile->pid); |
477 | cifs_sb->local_nls, | ||
478 | cifs_sb->mnt_cifs_flags & | ||
479 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
480 | } | ||
481 | } | 434 | } |
482 | 435 | ||
483 | out: | 436 | out: |
484 | kfree(buf); | ||
485 | kfree(full_path); | 437 | kfree(full_path); |
486 | FreeXid(xid); | 438 | FreeXid(xid); |
487 | cifs_put_tlink(tlink); | 439 | cifs_put_tlink(tlink); |
@@ -779,12 +731,12 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
779 | 731 | ||
780 | /* BB we could chain these into one lock request BB */ | 732 | /* BB we could chain these into one lock request BB */ |
781 | rc = CIFSSMBLock(xid, tcon, netfid, length, pfLock->fl_start, | 733 | rc = CIFSSMBLock(xid, tcon, netfid, length, pfLock->fl_start, |
782 | 0, 1, lockType, 0 /* wait flag */ ); | 734 | 0, 1, lockType, 0 /* wait flag */, 0); |
783 | if (rc == 0) { | 735 | if (rc == 0) { |
784 | rc = CIFSSMBLock(xid, tcon, netfid, length, | 736 | rc = CIFSSMBLock(xid, tcon, netfid, length, |
785 | pfLock->fl_start, 1 /* numUnlock */ , | 737 | pfLock->fl_start, 1 /* numUnlock */ , |
786 | 0 /* numLock */ , lockType, | 738 | 0 /* numLock */ , lockType, |
787 | 0 /* wait flag */ ); | 739 | 0 /* wait flag */, 0); |
788 | pfLock->fl_type = F_UNLCK; | 740 | pfLock->fl_type = F_UNLCK; |
789 | if (rc != 0) | 741 | if (rc != 0) |
790 | cERROR(1, "Error unlocking previously locked " | 742 | cERROR(1, "Error unlocking previously locked " |
@@ -801,13 +753,13 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
801 | rc = CIFSSMBLock(xid, tcon, netfid, length, | 753 | rc = CIFSSMBLock(xid, tcon, netfid, length, |
802 | pfLock->fl_start, 0, 1, | 754 | pfLock->fl_start, 0, 1, |
803 | lockType | LOCKING_ANDX_SHARED_LOCK, | 755 | lockType | LOCKING_ANDX_SHARED_LOCK, |
804 | 0 /* wait flag */); | 756 | 0 /* wait flag */, 0); |
805 | if (rc == 0) { | 757 | if (rc == 0) { |
806 | rc = CIFSSMBLock(xid, tcon, netfid, | 758 | rc = CIFSSMBLock(xid, tcon, netfid, |
807 | length, pfLock->fl_start, 1, 0, | 759 | length, pfLock->fl_start, 1, 0, |
808 | lockType | | 760 | lockType | |
809 | LOCKING_ANDX_SHARED_LOCK, | 761 | LOCKING_ANDX_SHARED_LOCK, |
810 | 0 /* wait flag */); | 762 | 0 /* wait flag */, 0); |
811 | pfLock->fl_type = F_RDLCK; | 763 | pfLock->fl_type = F_RDLCK; |
812 | if (rc != 0) | 764 | if (rc != 0) |
813 | cERROR(1, "Error unlocking " | 765 | cERROR(1, "Error unlocking " |
@@ -850,8 +802,8 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
850 | 802 | ||
851 | if (numLock) { | 803 | if (numLock) { |
852 | rc = CIFSSMBLock(xid, tcon, netfid, length, | 804 | rc = CIFSSMBLock(xid, tcon, netfid, length, |
853 | pfLock->fl_start, | 805 | pfLock->fl_start, 0, numLock, lockType, |
854 | 0, numLock, lockType, wait_flag); | 806 | wait_flag, 0); |
855 | 807 | ||
856 | if (rc == 0) { | 808 | if (rc == 0) { |
857 | /* For Windows locks we must store them. */ | 809 | /* For Windows locks we must store them. */ |
@@ -871,9 +823,9 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
871 | (pfLock->fl_start + length) >= | 823 | (pfLock->fl_start + length) >= |
872 | (li->offset + li->length)) { | 824 | (li->offset + li->length)) { |
873 | stored_rc = CIFSSMBLock(xid, tcon, | 825 | stored_rc = CIFSSMBLock(xid, tcon, |
874 | netfid, | 826 | netfid, li->length, |
875 | li->length, li->offset, | 827 | li->offset, 1, 0, |
876 | 1, 0, li->type, false); | 828 | li->type, false, 0); |
877 | if (stored_rc) | 829 | if (stored_rc) |
878 | rc = stored_rc; | 830 | rc = stored_rc; |
879 | else { | 831 | else { |
@@ -892,31 +844,8 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
892 | return rc; | 844 | return rc; |
893 | } | 845 | } |
894 | 846 | ||
895 | /* | ||
896 | * Set the timeout on write requests past EOF. For some servers (Windows) | ||
897 | * these calls can be very long. | ||
898 | * | ||
899 | * If we're writing >10M past the EOF we give a 180s timeout. Anything less | ||
900 | * than that gets a 45s timeout. Writes not past EOF get 15s timeouts. | ||
901 | * The 10M cutoff is totally arbitrary. A better scheme for this would be | ||
902 | * welcome if someone wants to suggest one. | ||
903 | * | ||
904 | * We may be able to do a better job with this if there were some way to | ||
905 | * declare that a file should be sparse. | ||
906 | */ | ||
907 | static int | ||
908 | cifs_write_timeout(struct cifsInodeInfo *cifsi, loff_t offset) | ||
909 | { | ||
910 | if (offset <= cifsi->server_eof) | ||
911 | return CIFS_STD_OP; | ||
912 | else if (offset > (cifsi->server_eof + (10 * 1024 * 1024))) | ||
913 | return CIFS_VLONG_OP; | ||
914 | else | ||
915 | return CIFS_LONG_OP; | ||
916 | } | ||
917 | |||
918 | /* update the file size (if needed) after a write */ | 847 | /* update the file size (if needed) after a write */ |
919 | static void | 848 | void |
920 | cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset, | 849 | cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset, |
921 | unsigned int bytes_written) | 850 | unsigned int bytes_written) |
922 | { | 851 | { |
@@ -935,7 +864,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, | |||
935 | unsigned int total_written; | 864 | unsigned int total_written; |
936 | struct cifs_sb_info *cifs_sb; | 865 | struct cifs_sb_info *cifs_sb; |
937 | struct cifsTconInfo *pTcon; | 866 | struct cifsTconInfo *pTcon; |
938 | int xid, long_op; | 867 | int xid; |
939 | struct cifsFileInfo *open_file; | 868 | struct cifsFileInfo *open_file; |
940 | struct cifsInodeInfo *cifsi = CIFS_I(inode); | 869 | struct cifsInodeInfo *cifsi = CIFS_I(inode); |
941 | 870 | ||
@@ -956,7 +885,6 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, | |||
956 | 885 | ||
957 | xid = GetXid(); | 886 | xid = GetXid(); |
958 | 887 | ||
959 | long_op = cifs_write_timeout(cifsi, *poffset); | ||
960 | for (total_written = 0; write_size > total_written; | 888 | for (total_written = 0; write_size > total_written; |
961 | total_written += bytes_written) { | 889 | total_written += bytes_written) { |
962 | rc = -EAGAIN; | 890 | rc = -EAGAIN; |
@@ -984,7 +912,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, | |||
984 | min_t(const int, cifs_sb->wsize, | 912 | min_t(const int, cifs_sb->wsize, |
985 | write_size - total_written), | 913 | write_size - total_written), |
986 | *poffset, &bytes_written, | 914 | *poffset, &bytes_written, |
987 | NULL, write_data + total_written, long_op); | 915 | NULL, write_data + total_written, 0); |
988 | } | 916 | } |
989 | if (rc || (bytes_written == 0)) { | 917 | if (rc || (bytes_written == 0)) { |
990 | if (total_written) | 918 | if (total_written) |
@@ -997,8 +925,6 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, | |||
997 | cifs_update_eof(cifsi, *poffset, bytes_written); | 925 | cifs_update_eof(cifsi, *poffset, bytes_written); |
998 | *poffset += bytes_written; | 926 | *poffset += bytes_written; |
999 | } | 927 | } |
1000 | long_op = CIFS_STD_OP; /* subsequent writes fast - | ||
1001 | 15 seconds is plenty */ | ||
1002 | } | 928 | } |
1003 | 929 | ||
1004 | cifs_stats_bytes_written(pTcon, total_written); | 930 | cifs_stats_bytes_written(pTcon, total_written); |
@@ -1027,7 +953,7 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, | |||
1027 | unsigned int total_written; | 953 | unsigned int total_written; |
1028 | struct cifs_sb_info *cifs_sb; | 954 | struct cifs_sb_info *cifs_sb; |
1029 | struct cifsTconInfo *pTcon; | 955 | struct cifsTconInfo *pTcon; |
1030 | int xid, long_op; | 956 | int xid; |
1031 | struct dentry *dentry = open_file->dentry; | 957 | struct dentry *dentry = open_file->dentry; |
1032 | struct cifsInodeInfo *cifsi = CIFS_I(dentry->d_inode); | 958 | struct cifsInodeInfo *cifsi = CIFS_I(dentry->d_inode); |
1033 | 959 | ||
@@ -1040,7 +966,6 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, | |||
1040 | 966 | ||
1041 | xid = GetXid(); | 967 | xid = GetXid(); |
1042 | 968 | ||
1043 | long_op = cifs_write_timeout(cifsi, *poffset); | ||
1044 | for (total_written = 0; write_size > total_written; | 969 | for (total_written = 0; write_size > total_written; |
1045 | total_written += bytes_written) { | 970 | total_written += bytes_written) { |
1046 | rc = -EAGAIN; | 971 | rc = -EAGAIN; |
@@ -1070,7 +995,7 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, | |||
1070 | rc = CIFSSMBWrite2(xid, pTcon, | 995 | rc = CIFSSMBWrite2(xid, pTcon, |
1071 | open_file->netfid, len, | 996 | open_file->netfid, len, |
1072 | *poffset, &bytes_written, | 997 | *poffset, &bytes_written, |
1073 | iov, 1, long_op); | 998 | iov, 1, 0); |
1074 | } else | 999 | } else |
1075 | rc = CIFSSMBWrite(xid, pTcon, | 1000 | rc = CIFSSMBWrite(xid, pTcon, |
1076 | open_file->netfid, | 1001 | open_file->netfid, |
@@ -1078,7 +1003,7 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, | |||
1078 | write_size - total_written), | 1003 | write_size - total_written), |
1079 | *poffset, &bytes_written, | 1004 | *poffset, &bytes_written, |
1080 | write_data + total_written, | 1005 | write_data + total_written, |
1081 | NULL, long_op); | 1006 | NULL, 0); |
1082 | } | 1007 | } |
1083 | if (rc || (bytes_written == 0)) { | 1008 | if (rc || (bytes_written == 0)) { |
1084 | if (total_written) | 1009 | if (total_written) |
@@ -1091,8 +1016,6 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, | |||
1091 | cifs_update_eof(cifsi, *poffset, bytes_written); | 1016 | cifs_update_eof(cifsi, *poffset, bytes_written); |
1092 | *poffset += bytes_written; | 1017 | *poffset += bytes_written; |
1093 | } | 1018 | } |
1094 | long_op = CIFS_STD_OP; /* subsequent writes fast - | ||
1095 | 15 seconds is plenty */ | ||
1096 | } | 1019 | } |
1097 | 1020 | ||
1098 | cifs_stats_bytes_written(pTcon, total_written); | 1021 | cifs_stats_bytes_written(pTcon, total_written); |
@@ -1220,7 +1143,6 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to) | |||
1220 | char *write_data; | 1143 | char *write_data; |
1221 | int rc = -EFAULT; | 1144 | int rc = -EFAULT; |
1222 | int bytes_written = 0; | 1145 | int bytes_written = 0; |
1223 | struct cifs_sb_info *cifs_sb; | ||
1224 | struct inode *inode; | 1146 | struct inode *inode; |
1225 | struct cifsFileInfo *open_file; | 1147 | struct cifsFileInfo *open_file; |
1226 | 1148 | ||
@@ -1228,7 +1150,6 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to) | |||
1228 | return -EFAULT; | 1150 | return -EFAULT; |
1229 | 1151 | ||
1230 | inode = page->mapping->host; | 1152 | inode = page->mapping->host; |
1231 | cifs_sb = CIFS_SB(inode->i_sb); | ||
1232 | 1153 | ||
1233 | offset += (loff_t)from; | 1154 | offset += (loff_t)from; |
1234 | write_data = kmap(page); | 1155 | write_data = kmap(page); |
@@ -1292,7 +1213,7 @@ static int cifs_writepages(struct address_space *mapping, | |||
1292 | struct pagevec pvec; | 1213 | struct pagevec pvec; |
1293 | int rc = 0; | 1214 | int rc = 0; |
1294 | int scanned = 0; | 1215 | int scanned = 0; |
1295 | int xid, long_op; | 1216 | int xid; |
1296 | 1217 | ||
1297 | cifs_sb = CIFS_SB(mapping->host->i_sb); | 1218 | cifs_sb = CIFS_SB(mapping->host->i_sb); |
1298 | 1219 | ||
@@ -1430,43 +1351,67 @@ retry: | |||
1430 | break; | 1351 | break; |
1431 | } | 1352 | } |
1432 | if (n_iov) { | 1353 | if (n_iov) { |
1354 | retry_write: | ||
1433 | open_file = find_writable_file(CIFS_I(mapping->host), | 1355 | open_file = find_writable_file(CIFS_I(mapping->host), |
1434 | false); | 1356 | false); |
1435 | if (!open_file) { | 1357 | if (!open_file) { |
1436 | cERROR(1, "No writable handles for inode"); | 1358 | cERROR(1, "No writable handles for inode"); |
1437 | rc = -EBADF; | 1359 | rc = -EBADF; |
1438 | } else { | 1360 | } else { |
1439 | long_op = cifs_write_timeout(cifsi, offset); | ||
1440 | rc = CIFSSMBWrite2(xid, tcon, open_file->netfid, | 1361 | rc = CIFSSMBWrite2(xid, tcon, open_file->netfid, |
1441 | bytes_to_write, offset, | 1362 | bytes_to_write, offset, |
1442 | &bytes_written, iov, n_iov, | 1363 | &bytes_written, iov, n_iov, |
1443 | long_op); | 1364 | 0); |
1444 | cifsFileInfo_put(open_file); | 1365 | cifsFileInfo_put(open_file); |
1445 | cifs_update_eof(cifsi, offset, bytes_written); | ||
1446 | } | 1366 | } |
1447 | 1367 | ||
1448 | if (rc || bytes_written < bytes_to_write) { | 1368 | cFYI(1, "Write2 rc=%d, wrote=%u", rc, bytes_written); |
1449 | cERROR(1, "Write2 ret %d, wrote %d", | 1369 | |
1450 | rc, bytes_written); | 1370 | /* |
1451 | mapping_set_error(mapping, rc); | 1371 | * For now, treat a short write as if nothing got |
1452 | } else { | 1372 | * written. A zero length write however indicates |
1373 | * ENOSPC or EFBIG. We have no way to know which | ||
1374 | * though, so call it ENOSPC for now. EFBIG would | ||
1375 | * get translated to AS_EIO anyway. | ||
1376 | * | ||
1377 | * FIXME: make it take into account the data that did | ||
1378 | * get written | ||
1379 | */ | ||
1380 | if (rc == 0) { | ||
1381 | if (bytes_written == 0) | ||
1382 | rc = -ENOSPC; | ||
1383 | else if (bytes_written < bytes_to_write) | ||
1384 | rc = -EAGAIN; | ||
1385 | } | ||
1386 | |||
1387 | /* retry on data-integrity flush */ | ||
1388 | if (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN) | ||
1389 | goto retry_write; | ||
1390 | |||
1391 | /* fix the stats and EOF */ | ||
1392 | if (bytes_written > 0) { | ||
1453 | cifs_stats_bytes_written(tcon, bytes_written); | 1393 | cifs_stats_bytes_written(tcon, bytes_written); |
1394 | cifs_update_eof(cifsi, offset, bytes_written); | ||
1454 | } | 1395 | } |
1455 | 1396 | ||
1456 | for (i = 0; i < n_iov; i++) { | 1397 | for (i = 0; i < n_iov; i++) { |
1457 | page = pvec.pages[first + i]; | 1398 | page = pvec.pages[first + i]; |
1458 | /* Should we also set page error on | 1399 | /* on retryable write error, redirty page */ |
1459 | success rc but too little data written? */ | 1400 | if (rc == -EAGAIN) |
1460 | /* BB investigate retry logic on temporary | 1401 | redirty_page_for_writepage(wbc, page); |
1461 | server crash cases and how recovery works | 1402 | else if (rc != 0) |
1462 | when page marked as error */ | ||
1463 | if (rc) | ||
1464 | SetPageError(page); | 1403 | SetPageError(page); |
1465 | kunmap(page); | 1404 | kunmap(page); |
1466 | unlock_page(page); | 1405 | unlock_page(page); |
1467 | end_page_writeback(page); | 1406 | end_page_writeback(page); |
1468 | page_cache_release(page); | 1407 | page_cache_release(page); |
1469 | } | 1408 | } |
1409 | |||
1410 | if (rc != -EAGAIN) | ||
1411 | mapping_set_error(mapping, rc); | ||
1412 | else | ||
1413 | rc = 0; | ||
1414 | |||
1470 | if ((wbc->nr_to_write -= n_iov) <= 0) | 1415 | if ((wbc->nr_to_write -= n_iov) <= 0) |
1471 | done = 1; | 1416 | done = 1; |
1472 | index = next; | 1417 | index = next; |
@@ -1578,27 +1523,47 @@ static int cifs_write_end(struct file *file, struct address_space *mapping, | |||
1578 | return rc; | 1523 | return rc; |
1579 | } | 1524 | } |
1580 | 1525 | ||
1581 | int cifs_fsync(struct file *file, int datasync) | 1526 | int cifs_strict_fsync(struct file *file, int datasync) |
1582 | { | 1527 | { |
1583 | int xid; | 1528 | int xid; |
1584 | int rc = 0; | 1529 | int rc = 0; |
1585 | struct cifsTconInfo *tcon; | 1530 | struct cifsTconInfo *tcon; |
1586 | struct cifsFileInfo *smbfile = file->private_data; | 1531 | struct cifsFileInfo *smbfile = file->private_data; |
1587 | struct inode *inode = file->f_path.dentry->d_inode; | 1532 | struct inode *inode = file->f_path.dentry->d_inode; |
1533 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
1588 | 1534 | ||
1589 | xid = GetXid(); | 1535 | xid = GetXid(); |
1590 | 1536 | ||
1591 | cFYI(1, "Sync file - name: %s datasync: 0x%x", | 1537 | cFYI(1, "Sync file - name: %s datasync: 0x%x", |
1592 | file->f_path.dentry->d_name.name, datasync); | 1538 | file->f_path.dentry->d_name.name, datasync); |
1593 | 1539 | ||
1594 | rc = filemap_write_and_wait(inode->i_mapping); | 1540 | if (!CIFS_I(inode)->clientCanCacheRead) |
1595 | if (rc == 0) { | 1541 | cifs_invalidate_mapping(inode); |
1596 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
1597 | 1542 | ||
1598 | tcon = tlink_tcon(smbfile->tlink); | 1543 | tcon = tlink_tcon(smbfile->tlink); |
1599 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) | 1544 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) |
1600 | rc = CIFSSMBFlush(xid, tcon, smbfile->netfid); | 1545 | rc = CIFSSMBFlush(xid, tcon, smbfile->netfid); |
1601 | } | 1546 | |
1547 | FreeXid(xid); | ||
1548 | return rc; | ||
1549 | } | ||
1550 | |||
1551 | int cifs_fsync(struct file *file, int datasync) | ||
1552 | { | ||
1553 | int xid; | ||
1554 | int rc = 0; | ||
1555 | struct cifsTconInfo *tcon; | ||
1556 | struct cifsFileInfo *smbfile = file->private_data; | ||
1557 | struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | ||
1558 | |||
1559 | xid = GetXid(); | ||
1560 | |||
1561 | cFYI(1, "Sync file - name: %s datasync: 0x%x", | ||
1562 | file->f_path.dentry->d_name.name, datasync); | ||
1563 | |||
1564 | tcon = tlink_tcon(smbfile->tlink); | ||
1565 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) | ||
1566 | rc = CIFSSMBFlush(xid, tcon, smbfile->netfid); | ||
1602 | 1567 | ||
1603 | FreeXid(xid); | 1568 | FreeXid(xid); |
1604 | return rc; | 1569 | return rc; |
@@ -1649,42 +1614,244 @@ int cifs_flush(struct file *file, fl_owner_t id) | |||
1649 | return rc; | 1614 | return rc; |
1650 | } | 1615 | } |
1651 | 1616 | ||
1652 | ssize_t cifs_user_read(struct file *file, char __user *read_data, | 1617 | static int |
1653 | size_t read_size, loff_t *poffset) | 1618 | cifs_write_allocate_pages(struct page **pages, unsigned long num_pages) |
1654 | { | 1619 | { |
1655 | int rc = -EACCES; | 1620 | int rc = 0; |
1621 | unsigned long i; | ||
1622 | |||
1623 | for (i = 0; i < num_pages; i++) { | ||
1624 | pages[i] = alloc_page(__GFP_HIGHMEM); | ||
1625 | if (!pages[i]) { | ||
1626 | /* | ||
1627 | * save number of pages we have already allocated and | ||
1628 | * return with ENOMEM error | ||
1629 | */ | ||
1630 | num_pages = i; | ||
1631 | rc = -ENOMEM; | ||
1632 | goto error; | ||
1633 | } | ||
1634 | } | ||
1635 | |||
1636 | return rc; | ||
1637 | |||
1638 | error: | ||
1639 | for (i = 0; i < num_pages; i++) | ||
1640 | put_page(pages[i]); | ||
1641 | return rc; | ||
1642 | } | ||
1643 | |||
1644 | static inline | ||
1645 | size_t get_numpages(const size_t wsize, const size_t len, size_t *cur_len) | ||
1646 | { | ||
1647 | size_t num_pages; | ||
1648 | size_t clen; | ||
1649 | |||
1650 | clen = min_t(const size_t, len, wsize); | ||
1651 | num_pages = clen / PAGE_CACHE_SIZE; | ||
1652 | if (clen % PAGE_CACHE_SIZE) | ||
1653 | num_pages++; | ||
1654 | |||
1655 | if (cur_len) | ||
1656 | *cur_len = clen; | ||
1657 | |||
1658 | return num_pages; | ||
1659 | } | ||
1660 | |||
1661 | static ssize_t | ||
1662 | cifs_iovec_write(struct file *file, const struct iovec *iov, | ||
1663 | unsigned long nr_segs, loff_t *poffset) | ||
1664 | { | ||
1665 | unsigned int written; | ||
1666 | unsigned long num_pages, npages, i; | ||
1667 | size_t copied, len, cur_len; | ||
1668 | ssize_t total_written = 0; | ||
1669 | struct kvec *to_send; | ||
1670 | struct page **pages; | ||
1671 | struct iov_iter it; | ||
1672 | struct inode *inode; | ||
1673 | struct cifsFileInfo *open_file; | ||
1674 | struct cifsTconInfo *pTcon; | ||
1675 | struct cifs_sb_info *cifs_sb; | ||
1676 | int xid, rc; | ||
1677 | |||
1678 | len = iov_length(iov, nr_segs); | ||
1679 | if (!len) | ||
1680 | return 0; | ||
1681 | |||
1682 | rc = generic_write_checks(file, poffset, &len, 0); | ||
1683 | if (rc) | ||
1684 | return rc; | ||
1685 | |||
1686 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | ||
1687 | num_pages = get_numpages(cifs_sb->wsize, len, &cur_len); | ||
1688 | |||
1689 | pages = kmalloc(sizeof(struct pages *)*num_pages, GFP_KERNEL); | ||
1690 | if (!pages) | ||
1691 | return -ENOMEM; | ||
1692 | |||
1693 | to_send = kmalloc(sizeof(struct kvec)*(num_pages + 1), GFP_KERNEL); | ||
1694 | if (!to_send) { | ||
1695 | kfree(pages); | ||
1696 | return -ENOMEM; | ||
1697 | } | ||
1698 | |||
1699 | rc = cifs_write_allocate_pages(pages, num_pages); | ||
1700 | if (rc) { | ||
1701 | kfree(pages); | ||
1702 | kfree(to_send); | ||
1703 | return rc; | ||
1704 | } | ||
1705 | |||
1706 | xid = GetXid(); | ||
1707 | open_file = file->private_data; | ||
1708 | pTcon = tlink_tcon(open_file->tlink); | ||
1709 | inode = file->f_path.dentry->d_inode; | ||
1710 | |||
1711 | iov_iter_init(&it, iov, nr_segs, len, 0); | ||
1712 | npages = num_pages; | ||
1713 | |||
1714 | do { | ||
1715 | size_t save_len = cur_len; | ||
1716 | for (i = 0; i < npages; i++) { | ||
1717 | copied = min_t(const size_t, cur_len, PAGE_CACHE_SIZE); | ||
1718 | copied = iov_iter_copy_from_user(pages[i], &it, 0, | ||
1719 | copied); | ||
1720 | cur_len -= copied; | ||
1721 | iov_iter_advance(&it, copied); | ||
1722 | to_send[i+1].iov_base = kmap(pages[i]); | ||
1723 | to_send[i+1].iov_len = copied; | ||
1724 | } | ||
1725 | |||
1726 | cur_len = save_len - cur_len; | ||
1727 | |||
1728 | do { | ||
1729 | if (open_file->invalidHandle) { | ||
1730 | rc = cifs_reopen_file(open_file, false); | ||
1731 | if (rc != 0) | ||
1732 | break; | ||
1733 | } | ||
1734 | rc = CIFSSMBWrite2(xid, pTcon, open_file->netfid, | ||
1735 | cur_len, *poffset, &written, | ||
1736 | to_send, npages, 0); | ||
1737 | } while (rc == -EAGAIN); | ||
1738 | |||
1739 | for (i = 0; i < npages; i++) | ||
1740 | kunmap(pages[i]); | ||
1741 | |||
1742 | if (written) { | ||
1743 | len -= written; | ||
1744 | total_written += written; | ||
1745 | cifs_update_eof(CIFS_I(inode), *poffset, written); | ||
1746 | *poffset += written; | ||
1747 | } else if (rc < 0) { | ||
1748 | if (!total_written) | ||
1749 | total_written = rc; | ||
1750 | break; | ||
1751 | } | ||
1752 | |||
1753 | /* get length and number of kvecs of the next write */ | ||
1754 | npages = get_numpages(cifs_sb->wsize, len, &cur_len); | ||
1755 | } while (len > 0); | ||
1756 | |||
1757 | if (total_written > 0) { | ||
1758 | spin_lock(&inode->i_lock); | ||
1759 | if (*poffset > inode->i_size) | ||
1760 | i_size_write(inode, *poffset); | ||
1761 | spin_unlock(&inode->i_lock); | ||
1762 | } | ||
1763 | |||
1764 | cifs_stats_bytes_written(pTcon, total_written); | ||
1765 | mark_inode_dirty_sync(inode); | ||
1766 | |||
1767 | for (i = 0; i < num_pages; i++) | ||
1768 | put_page(pages[i]); | ||
1769 | kfree(to_send); | ||
1770 | kfree(pages); | ||
1771 | FreeXid(xid); | ||
1772 | return total_written; | ||
1773 | } | ||
1774 | |||
1775 | static ssize_t cifs_user_writev(struct kiocb *iocb, const struct iovec *iov, | ||
1776 | unsigned long nr_segs, loff_t pos) | ||
1777 | { | ||
1778 | ssize_t written; | ||
1779 | struct inode *inode; | ||
1780 | |||
1781 | inode = iocb->ki_filp->f_path.dentry->d_inode; | ||
1782 | |||
1783 | /* | ||
1784 | * BB - optimize the way when signing is disabled. We can drop this | ||
1785 | * extra memory-to-memory copying and use iovec buffers for constructing | ||
1786 | * write request. | ||
1787 | */ | ||
1788 | |||
1789 | written = cifs_iovec_write(iocb->ki_filp, iov, nr_segs, &pos); | ||
1790 | if (written > 0) { | ||
1791 | CIFS_I(inode)->invalid_mapping = true; | ||
1792 | iocb->ki_pos = pos; | ||
1793 | } | ||
1794 | |||
1795 | return written; | ||
1796 | } | ||
1797 | |||
1798 | ssize_t cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov, | ||
1799 | unsigned long nr_segs, loff_t pos) | ||
1800 | { | ||
1801 | struct inode *inode; | ||
1802 | |||
1803 | inode = iocb->ki_filp->f_path.dentry->d_inode; | ||
1804 | |||
1805 | if (CIFS_I(inode)->clientCanCacheAll) | ||
1806 | return generic_file_aio_write(iocb, iov, nr_segs, pos); | ||
1807 | |||
1808 | /* | ||
1809 | * In strict cache mode we need to write the data to the server exactly | ||
1810 | * from the pos to pos+len-1 rather than flush all affected pages | ||
1811 | * because it may cause a error with mandatory locks on these pages but | ||
1812 | * not on the region from pos to ppos+len-1. | ||
1813 | */ | ||
1814 | |||
1815 | return cifs_user_writev(iocb, iov, nr_segs, pos); | ||
1816 | } | ||
1817 | |||
1818 | static ssize_t | ||
1819 | cifs_iovec_read(struct file *file, const struct iovec *iov, | ||
1820 | unsigned long nr_segs, loff_t *poffset) | ||
1821 | { | ||
1822 | int rc; | ||
1823 | int xid; | ||
1824 | ssize_t total_read; | ||
1656 | unsigned int bytes_read = 0; | 1825 | unsigned int bytes_read = 0; |
1657 | unsigned int total_read = 0; | 1826 | size_t len, cur_len; |
1658 | unsigned int current_read_size; | 1827 | int iov_offset = 0; |
1659 | struct cifs_sb_info *cifs_sb; | 1828 | struct cifs_sb_info *cifs_sb; |
1660 | struct cifsTconInfo *pTcon; | 1829 | struct cifsTconInfo *pTcon; |
1661 | int xid; | ||
1662 | struct cifsFileInfo *open_file; | 1830 | struct cifsFileInfo *open_file; |
1663 | char *smb_read_data; | ||
1664 | char __user *current_offset; | ||
1665 | struct smb_com_read_rsp *pSMBr; | 1831 | struct smb_com_read_rsp *pSMBr; |
1832 | char *read_data; | ||
1833 | |||
1834 | if (!nr_segs) | ||
1835 | return 0; | ||
1836 | |||
1837 | len = iov_length(iov, nr_segs); | ||
1838 | if (!len) | ||
1839 | return 0; | ||
1666 | 1840 | ||
1667 | xid = GetXid(); | 1841 | xid = GetXid(); |
1668 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | 1842 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); |
1669 | 1843 | ||
1670 | if (file->private_data == NULL) { | ||
1671 | rc = -EBADF; | ||
1672 | FreeXid(xid); | ||
1673 | return rc; | ||
1674 | } | ||
1675 | open_file = file->private_data; | 1844 | open_file = file->private_data; |
1676 | pTcon = tlink_tcon(open_file->tlink); | 1845 | pTcon = tlink_tcon(open_file->tlink); |
1677 | 1846 | ||
1678 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) | 1847 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) |
1679 | cFYI(1, "attempting read on write only file instance"); | 1848 | cFYI(1, "attempting read on write only file instance"); |
1680 | 1849 | ||
1681 | for (total_read = 0, current_offset = read_data; | 1850 | for (total_read = 0; total_read < len; total_read += bytes_read) { |
1682 | read_size > total_read; | 1851 | cur_len = min_t(const size_t, len - total_read, cifs_sb->rsize); |
1683 | total_read += bytes_read, current_offset += bytes_read) { | ||
1684 | current_read_size = min_t(const int, read_size - total_read, | ||
1685 | cifs_sb->rsize); | ||
1686 | rc = -EAGAIN; | 1852 | rc = -EAGAIN; |
1687 | smb_read_data = NULL; | 1853 | read_data = NULL; |
1854 | |||
1688 | while (rc == -EAGAIN) { | 1855 | while (rc == -EAGAIN) { |
1689 | int buf_type = CIFS_NO_BUFFER; | 1856 | int buf_type = CIFS_NO_BUFFER; |
1690 | if (open_file->invalidHandle) { | 1857 | if (open_file->invalidHandle) { |
@@ -1692,27 +1859,25 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data, | |||
1692 | if (rc != 0) | 1859 | if (rc != 0) |
1693 | break; | 1860 | break; |
1694 | } | 1861 | } |
1695 | rc = CIFSSMBRead(xid, pTcon, | 1862 | rc = CIFSSMBRead(xid, pTcon, open_file->netfid, |
1696 | open_file->netfid, | 1863 | cur_len, *poffset, &bytes_read, |
1697 | current_read_size, *poffset, | 1864 | &read_data, &buf_type); |
1698 | &bytes_read, &smb_read_data, | 1865 | pSMBr = (struct smb_com_read_rsp *)read_data; |
1699 | &buf_type); | 1866 | if (read_data) { |
1700 | pSMBr = (struct smb_com_read_rsp *)smb_read_data; | 1867 | char *data_offset = read_data + 4 + |
1701 | if (smb_read_data) { | 1868 | le16_to_cpu(pSMBr->DataOffset); |
1702 | if (copy_to_user(current_offset, | 1869 | if (memcpy_toiovecend(iov, data_offset, |
1703 | smb_read_data + | 1870 | iov_offset, bytes_read)) |
1704 | 4 /* RFC1001 length field */ + | ||
1705 | le16_to_cpu(pSMBr->DataOffset), | ||
1706 | bytes_read)) | ||
1707 | rc = -EFAULT; | 1871 | rc = -EFAULT; |
1708 | |||
1709 | if (buf_type == CIFS_SMALL_BUFFER) | 1872 | if (buf_type == CIFS_SMALL_BUFFER) |
1710 | cifs_small_buf_release(smb_read_data); | 1873 | cifs_small_buf_release(read_data); |
1711 | else if (buf_type == CIFS_LARGE_BUFFER) | 1874 | else if (buf_type == CIFS_LARGE_BUFFER) |
1712 | cifs_buf_release(smb_read_data); | 1875 | cifs_buf_release(read_data); |
1713 | smb_read_data = NULL; | 1876 | read_data = NULL; |
1877 | iov_offset += bytes_read; | ||
1714 | } | 1878 | } |
1715 | } | 1879 | } |
1880 | |||
1716 | if (rc || (bytes_read == 0)) { | 1881 | if (rc || (bytes_read == 0)) { |
1717 | if (total_read) { | 1882 | if (total_read) { |
1718 | break; | 1883 | break; |
@@ -1725,13 +1890,57 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data, | |||
1725 | *poffset += bytes_read; | 1890 | *poffset += bytes_read; |
1726 | } | 1891 | } |
1727 | } | 1892 | } |
1893 | |||
1728 | FreeXid(xid); | 1894 | FreeXid(xid); |
1729 | return total_read; | 1895 | return total_read; |
1730 | } | 1896 | } |
1731 | 1897 | ||
1898 | ssize_t cifs_user_read(struct file *file, char __user *read_data, | ||
1899 | size_t read_size, loff_t *poffset) | ||
1900 | { | ||
1901 | struct iovec iov; | ||
1902 | iov.iov_base = read_data; | ||
1903 | iov.iov_len = read_size; | ||
1904 | |||
1905 | return cifs_iovec_read(file, &iov, 1, poffset); | ||
1906 | } | ||
1907 | |||
1908 | static ssize_t cifs_user_readv(struct kiocb *iocb, const struct iovec *iov, | ||
1909 | unsigned long nr_segs, loff_t pos) | ||
1910 | { | ||
1911 | ssize_t read; | ||
1912 | |||
1913 | read = cifs_iovec_read(iocb->ki_filp, iov, nr_segs, &pos); | ||
1914 | if (read > 0) | ||
1915 | iocb->ki_pos = pos; | ||
1916 | |||
1917 | return read; | ||
1918 | } | ||
1919 | |||
1920 | ssize_t cifs_strict_readv(struct kiocb *iocb, const struct iovec *iov, | ||
1921 | unsigned long nr_segs, loff_t pos) | ||
1922 | { | ||
1923 | struct inode *inode; | ||
1924 | |||
1925 | inode = iocb->ki_filp->f_path.dentry->d_inode; | ||
1926 | |||
1927 | if (CIFS_I(inode)->clientCanCacheRead) | ||
1928 | return generic_file_aio_read(iocb, iov, nr_segs, pos); | ||
1929 | |||
1930 | /* | ||
1931 | * In strict cache mode we need to read from the server all the time | ||
1932 | * if we don't have level II oplock because the server can delay mtime | ||
1933 | * change - so we can't make a decision about inode invalidating. | ||
1934 | * And we can also fail with pagereading if there are mandatory locks | ||
1935 | * on pages affected by this read but not on the region from pos to | ||
1936 | * pos+len-1. | ||
1937 | */ | ||
1938 | |||
1939 | return cifs_user_readv(iocb, iov, nr_segs, pos); | ||
1940 | } | ||
1732 | 1941 | ||
1733 | static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, | 1942 | static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, |
1734 | loff_t *poffset) | 1943 | loff_t *poffset) |
1735 | { | 1944 | { |
1736 | int rc = -EACCES; | 1945 | int rc = -EACCES; |
1737 | unsigned int bytes_read = 0; | 1946 | unsigned int bytes_read = 0; |
@@ -1799,6 +2008,21 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, | |||
1799 | return total_read; | 2008 | return total_read; |
1800 | } | 2009 | } |
1801 | 2010 | ||
2011 | int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma) | ||
2012 | { | ||
2013 | int rc, xid; | ||
2014 | struct inode *inode = file->f_path.dentry->d_inode; | ||
2015 | |||
2016 | xid = GetXid(); | ||
2017 | |||
2018 | if (!CIFS_I(inode)->clientCanCacheRead) | ||
2019 | cifs_invalidate_mapping(inode); | ||
2020 | |||
2021 | rc = generic_file_mmap(file, vma); | ||
2022 | FreeXid(xid); | ||
2023 | return rc; | ||
2024 | } | ||
2025 | |||
1802 | int cifs_file_mmap(struct file *file, struct vm_area_struct *vma) | 2026 | int cifs_file_mmap(struct file *file, struct vm_area_struct *vma) |
1803 | { | 2027 | { |
1804 | int rc, xid; | 2028 | int rc, xid; |
@@ -2245,7 +2469,8 @@ void cifs_oplock_break(struct work_struct *work) | |||
2245 | */ | 2469 | */ |
2246 | if (!cfile->oplock_break_cancelled) { | 2470 | if (!cfile->oplock_break_cancelled) { |
2247 | rc = CIFSSMBLock(0, tlink_tcon(cfile->tlink), cfile->netfid, 0, | 2471 | rc = CIFSSMBLock(0, tlink_tcon(cfile->tlink), cfile->netfid, 0, |
2248 | 0, 0, 0, LOCKING_ANDX_OPLOCK_RELEASE, false); | 2472 | 0, 0, 0, LOCKING_ANDX_OPLOCK_RELEASE, false, |
2473 | cinode->clientCanCacheRead ? 1 : 0); | ||
2249 | cFYI(1, "Oplock release rc = %d", rc); | 2474 | cFYI(1, "Oplock release rc = %d", rc); |
2250 | } | 2475 | } |
2251 | 2476 | ||
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 589f3e3f6e00..8852470b4fbb 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -32,7 +32,7 @@ | |||
32 | #include "fscache.h" | 32 | #include "fscache.h" |
33 | 33 | ||
34 | 34 | ||
35 | static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral) | 35 | static void cifs_set_ops(struct inode *inode) |
36 | { | 36 | { |
37 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 37 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
38 | 38 | ||
@@ -44,13 +44,17 @@ static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral) | |||
44 | inode->i_fop = &cifs_file_direct_nobrl_ops; | 44 | inode->i_fop = &cifs_file_direct_nobrl_ops; |
45 | else | 45 | else |
46 | inode->i_fop = &cifs_file_direct_ops; | 46 | inode->i_fop = &cifs_file_direct_ops; |
47 | } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) { | ||
48 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | ||
49 | inode->i_fop = &cifs_file_strict_nobrl_ops; | ||
50 | else | ||
51 | inode->i_fop = &cifs_file_strict_ops; | ||
47 | } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | 52 | } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) |
48 | inode->i_fop = &cifs_file_nobrl_ops; | 53 | inode->i_fop = &cifs_file_nobrl_ops; |
49 | else { /* not direct, send byte range locks */ | 54 | else { /* not direct, send byte range locks */ |
50 | inode->i_fop = &cifs_file_ops; | 55 | inode->i_fop = &cifs_file_ops; |
51 | } | 56 | } |
52 | 57 | ||
53 | |||
54 | /* check if server can support readpages */ | 58 | /* check if server can support readpages */ |
55 | if (cifs_sb_master_tcon(cifs_sb)->ses->server->maxBuf < | 59 | if (cifs_sb_master_tcon(cifs_sb)->ses->server->maxBuf < |
56 | PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE) | 60 | PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE) |
@@ -60,7 +64,7 @@ static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral) | |||
60 | break; | 64 | break; |
61 | case S_IFDIR: | 65 | case S_IFDIR: |
62 | #ifdef CONFIG_CIFS_DFS_UPCALL | 66 | #ifdef CONFIG_CIFS_DFS_UPCALL |
63 | if (is_dfs_referral) { | 67 | if (IS_AUTOMOUNT(inode)) { |
64 | inode->i_op = &cifs_dfs_referral_inode_operations; | 68 | inode->i_op = &cifs_dfs_referral_inode_operations; |
65 | } else { | 69 | } else { |
66 | #else /* NO DFS support, treat as a directory */ | 70 | #else /* NO DFS support, treat as a directory */ |
@@ -167,7 +171,9 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) | |||
167 | } | 171 | } |
168 | spin_unlock(&inode->i_lock); | 172 | spin_unlock(&inode->i_lock); |
169 | 173 | ||
170 | cifs_set_ops(inode, fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL); | 174 | if (fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL) |
175 | inode->i_flags |= S_AUTOMOUNT; | ||
176 | cifs_set_ops(inode); | ||
171 | } | 177 | } |
172 | 178 | ||
173 | void | 179 | void |
@@ -518,6 +524,7 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, | |||
518 | 524 | ||
519 | fattr->cf_eof = le64_to_cpu(info->EndOfFile); | 525 | fattr->cf_eof = le64_to_cpu(info->EndOfFile); |
520 | fattr->cf_bytes = le64_to_cpu(info->AllocationSize); | 526 | fattr->cf_bytes = le64_to_cpu(info->AllocationSize); |
527 | fattr->cf_createtime = le64_to_cpu(info->CreationTime); | ||
521 | 528 | ||
522 | if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { | 529 | if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { |
523 | fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode; | 530 | fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode; |
@@ -779,6 +786,10 @@ cifs_find_inode(struct inode *inode, void *opaque) | |||
779 | if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid) | 786 | if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid) |
780 | return 0; | 787 | return 0; |
781 | 788 | ||
789 | /* use createtime like an i_generation field */ | ||
790 | if (CIFS_I(inode)->createtime != fattr->cf_createtime) | ||
791 | return 0; | ||
792 | |||
782 | /* don't match inode of different type */ | 793 | /* don't match inode of different type */ |
783 | if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT)) | 794 | if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT)) |
784 | return 0; | 795 | return 0; |
@@ -796,6 +807,7 @@ cifs_init_inode(struct inode *inode, void *opaque) | |||
796 | struct cifs_fattr *fattr = (struct cifs_fattr *) opaque; | 807 | struct cifs_fattr *fattr = (struct cifs_fattr *) opaque; |
797 | 808 | ||
798 | CIFS_I(inode)->uniqueid = fattr->cf_uniqueid; | 809 | CIFS_I(inode)->uniqueid = fattr->cf_uniqueid; |
810 | CIFS_I(inode)->createtime = fattr->cf_createtime; | ||
799 | return 0; | 811 | return 0; |
800 | } | 812 | } |
801 | 813 | ||
@@ -809,14 +821,14 @@ inode_has_hashed_dentries(struct inode *inode) | |||
809 | { | 821 | { |
810 | struct dentry *dentry; | 822 | struct dentry *dentry; |
811 | 823 | ||
812 | spin_lock(&dcache_lock); | 824 | spin_lock(&inode->i_lock); |
813 | list_for_each_entry(dentry, &inode->i_dentry, d_alias) { | 825 | list_for_each_entry(dentry, &inode->i_dentry, d_alias) { |
814 | if (!d_unhashed(dentry) || IS_ROOT(dentry)) { | 826 | if (!d_unhashed(dentry) || IS_ROOT(dentry)) { |
815 | spin_unlock(&dcache_lock); | 827 | spin_unlock(&inode->i_lock); |
816 | return true; | 828 | return true; |
817 | } | 829 | } |
818 | } | 830 | } |
819 | spin_unlock(&dcache_lock); | 831 | spin_unlock(&inode->i_lock); |
820 | return false; | 832 | return false; |
821 | } | 833 | } |
822 | 834 | ||
@@ -1318,10 +1330,6 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
1318 | /*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need | 1330 | /*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need |
1319 | to set uid/gid */ | 1331 | to set uid/gid */ |
1320 | inc_nlink(inode); | 1332 | inc_nlink(inode); |
1321 | if (pTcon->nocase) | ||
1322 | direntry->d_op = &cifs_ci_dentry_ops; | ||
1323 | else | ||
1324 | direntry->d_op = &cifs_dentry_ops; | ||
1325 | 1333 | ||
1326 | cifs_unix_basic_to_fattr(&fattr, pInfo, cifs_sb); | 1334 | cifs_unix_basic_to_fattr(&fattr, pInfo, cifs_sb); |
1327 | cifs_fill_uniqueid(inode->i_sb, &fattr); | 1335 | cifs_fill_uniqueid(inode->i_sb, &fattr); |
@@ -1362,10 +1370,6 @@ mkdir_get_info: | |||
1362 | rc = cifs_get_inode_info(&newinode, full_path, NULL, | 1370 | rc = cifs_get_inode_info(&newinode, full_path, NULL, |
1363 | inode->i_sb, xid, NULL); | 1371 | inode->i_sb, xid, NULL); |
1364 | 1372 | ||
1365 | if (pTcon->nocase) | ||
1366 | direntry->d_op = &cifs_ci_dentry_ops; | ||
1367 | else | ||
1368 | direntry->d_op = &cifs_dentry_ops; | ||
1369 | d_instantiate(direntry, newinode); | 1373 | d_instantiate(direntry, newinode); |
1370 | /* setting nlink not necessary except in cases where we | 1374 | /* setting nlink not necessary except in cases where we |
1371 | * failed to get it from the server or was set bogus */ | 1375 | * failed to get it from the server or was set bogus */ |
@@ -1679,7 +1683,7 @@ cifs_inode_needs_reval(struct inode *inode) | |||
1679 | /* | 1683 | /* |
1680 | * Zap the cache. Called when invalid_mapping flag is set. | 1684 | * Zap the cache. Called when invalid_mapping flag is set. |
1681 | */ | 1685 | */ |
1682 | static void | 1686 | void |
1683 | cifs_invalidate_mapping(struct inode *inode) | 1687 | cifs_invalidate_mapping(struct inode *inode) |
1684 | { | 1688 | { |
1685 | int rc; | 1689 | int rc; |
diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 85cdbf831e7b..e8804d373404 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c | |||
@@ -28,7 +28,6 @@ | |||
28 | #include "cifsproto.h" | 28 | #include "cifsproto.h" |
29 | #include "cifs_debug.h" | 29 | #include "cifs_debug.h" |
30 | #include "cifs_fs_sb.h" | 30 | #include "cifs_fs_sb.h" |
31 | #include "md5.h" | ||
32 | 31 | ||
33 | #define CIFS_MF_SYMLINK_LEN_OFFSET (4+1) | 32 | #define CIFS_MF_SYMLINK_LEN_OFFSET (4+1) |
34 | #define CIFS_MF_SYMLINK_MD5_OFFSET (CIFS_MF_SYMLINK_LEN_OFFSET+(4+1)) | 33 | #define CIFS_MF_SYMLINK_MD5_OFFSET (CIFS_MF_SYMLINK_LEN_OFFSET+(4+1)) |
@@ -47,6 +46,45 @@ | |||
47 | md5_hash[12], md5_hash[13], md5_hash[14], md5_hash[15] | 46 | md5_hash[12], md5_hash[13], md5_hash[14], md5_hash[15] |
48 | 47 | ||
49 | static int | 48 | static int |
49 | symlink_hash(unsigned int link_len, const char *link_str, u8 *md5_hash) | ||
50 | { | ||
51 | int rc; | ||
52 | unsigned int size; | ||
53 | struct crypto_shash *md5; | ||
54 | struct sdesc *sdescmd5; | ||
55 | |||
56 | md5 = crypto_alloc_shash("md5", 0, 0); | ||
57 | if (IS_ERR(md5)) { | ||
58 | rc = PTR_ERR(md5); | ||
59 | cERROR(1, "%s: Crypto md5 allocation error %d\n", __func__, rc); | ||
60 | return rc; | ||
61 | } | ||
62 | size = sizeof(struct shash_desc) + crypto_shash_descsize(md5); | ||
63 | sdescmd5 = kmalloc(size, GFP_KERNEL); | ||
64 | if (!sdescmd5) { | ||
65 | rc = -ENOMEM; | ||
66 | cERROR(1, "%s: Memory allocation failure\n", __func__); | ||
67 | goto symlink_hash_err; | ||
68 | } | ||
69 | sdescmd5->shash.tfm = md5; | ||
70 | sdescmd5->shash.flags = 0x0; | ||
71 | |||
72 | rc = crypto_shash_init(&sdescmd5->shash); | ||
73 | if (rc) { | ||
74 | cERROR(1, "%s: Could not init md5 shash\n", __func__); | ||
75 | goto symlink_hash_err; | ||
76 | } | ||
77 | crypto_shash_update(&sdescmd5->shash, link_str, link_len); | ||
78 | rc = crypto_shash_final(&sdescmd5->shash, md5_hash); | ||
79 | |||
80 | symlink_hash_err: | ||
81 | crypto_free_shash(md5); | ||
82 | kfree(sdescmd5); | ||
83 | |||
84 | return rc; | ||
85 | } | ||
86 | |||
87 | static int | ||
50 | CIFSParseMFSymlink(const u8 *buf, | 88 | CIFSParseMFSymlink(const u8 *buf, |
51 | unsigned int buf_len, | 89 | unsigned int buf_len, |
52 | unsigned int *_link_len, | 90 | unsigned int *_link_len, |
@@ -56,7 +94,6 @@ CIFSParseMFSymlink(const u8 *buf, | |||
56 | unsigned int link_len; | 94 | unsigned int link_len; |
57 | const char *md5_str1; | 95 | const char *md5_str1; |
58 | const char *link_str; | 96 | const char *link_str; |
59 | struct MD5Context md5_ctx; | ||
60 | u8 md5_hash[16]; | 97 | u8 md5_hash[16]; |
61 | char md5_str2[34]; | 98 | char md5_str2[34]; |
62 | 99 | ||
@@ -70,9 +107,11 @@ CIFSParseMFSymlink(const u8 *buf, | |||
70 | if (rc != 1) | 107 | if (rc != 1) |
71 | return -EINVAL; | 108 | return -EINVAL; |
72 | 109 | ||
73 | cifs_MD5_init(&md5_ctx); | 110 | rc = symlink_hash(link_len, link_str, md5_hash); |
74 | cifs_MD5_update(&md5_ctx, (const u8 *)link_str, link_len); | 111 | if (rc) { |
75 | cifs_MD5_final(md5_hash, &md5_ctx); | 112 | cFYI(1, "%s: MD5 hash failure: %d\n", __func__, rc); |
113 | return rc; | ||
114 | } | ||
76 | 115 | ||
77 | snprintf(md5_str2, sizeof(md5_str2), | 116 | snprintf(md5_str2, sizeof(md5_str2), |
78 | CIFS_MF_SYMLINK_MD5_FORMAT, | 117 | CIFS_MF_SYMLINK_MD5_FORMAT, |
@@ -94,9 +133,9 @@ CIFSParseMFSymlink(const u8 *buf, | |||
94 | static int | 133 | static int |
95 | CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str) | 134 | CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str) |
96 | { | 135 | { |
136 | int rc; | ||
97 | unsigned int link_len; | 137 | unsigned int link_len; |
98 | unsigned int ofs; | 138 | unsigned int ofs; |
99 | struct MD5Context md5_ctx; | ||
100 | u8 md5_hash[16]; | 139 | u8 md5_hash[16]; |
101 | 140 | ||
102 | if (buf_len != CIFS_MF_SYMLINK_FILE_SIZE) | 141 | if (buf_len != CIFS_MF_SYMLINK_FILE_SIZE) |
@@ -107,9 +146,11 @@ CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str) | |||
107 | if (link_len > CIFS_MF_SYMLINK_LINK_MAXLEN) | 146 | if (link_len > CIFS_MF_SYMLINK_LINK_MAXLEN) |
108 | return -ENAMETOOLONG; | 147 | return -ENAMETOOLONG; |
109 | 148 | ||
110 | cifs_MD5_init(&md5_ctx); | 149 | rc = symlink_hash(link_len, link_str, md5_hash); |
111 | cifs_MD5_update(&md5_ctx, (const u8 *)link_str, link_len); | 150 | if (rc) { |
112 | cifs_MD5_final(md5_hash, &md5_ctx); | 151 | cFYI(1, "%s: MD5 hash failure: %d\n", __func__, rc); |
152 | return rc; | ||
153 | } | ||
113 | 154 | ||
114 | snprintf(buf, buf_len, | 155 | snprintf(buf, buf_len, |
115 | CIFS_MF_SYMLINK_LEN_FORMAT CIFS_MF_SYMLINK_MD5_FORMAT, | 156 | CIFS_MF_SYMLINK_LEN_FORMAT CIFS_MF_SYMLINK_MD5_FORMAT, |
@@ -524,10 +565,6 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) | |||
524 | cFYI(1, "Create symlink ok, getinodeinfo fail rc = %d", | 565 | cFYI(1, "Create symlink ok, getinodeinfo fail rc = %d", |
525 | rc); | 566 | rc); |
526 | } else { | 567 | } else { |
527 | if (pTcon->nocase) | ||
528 | direntry->d_op = &cifs_ci_dentry_ops; | ||
529 | else | ||
530 | direntry->d_op = &cifs_dentry_ops; | ||
531 | d_instantiate(direntry, newinode); | 568 | d_instantiate(direntry, newinode); |
532 | } | 569 | } |
533 | } | 570 | } |
diff --git a/fs/cifs/md4.c b/fs/cifs/md4.c deleted file mode 100644 index a725c2609d67..000000000000 --- a/fs/cifs/md4.c +++ /dev/null | |||
@@ -1,205 +0,0 @@ | |||
1 | /* | ||
2 | Unix SMB/Netbios implementation. | ||
3 | Version 1.9. | ||
4 | a implementation of MD4 designed for use in the SMB authentication protocol | ||
5 | Copyright (C) Andrew Tridgell 1997-1998. | ||
6 | Modified by Steve French (sfrench@us.ibm.com) 2002-2003 | ||
7 | |||
8 | This program is free software; you can redistribute it and/or modify | ||
9 | it under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation; either version 2 of the License, or | ||
11 | (at your option) any later version. | ||
12 | |||
13 | This program is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; if not, write to the Free Software | ||
20 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/fs.h> | ||
24 | #include "cifsencrypt.h" | ||
25 | |||
26 | /* NOTE: This code makes no attempt to be fast! */ | ||
27 | |||
28 | static __u32 | ||
29 | F(__u32 X, __u32 Y, __u32 Z) | ||
30 | { | ||
31 | return (X & Y) | ((~X) & Z); | ||
32 | } | ||
33 | |||
34 | static __u32 | ||
35 | G(__u32 X, __u32 Y, __u32 Z) | ||
36 | { | ||
37 | return (X & Y) | (X & Z) | (Y & Z); | ||
38 | } | ||
39 | |||
40 | static __u32 | ||
41 | H(__u32 X, __u32 Y, __u32 Z) | ||
42 | { | ||
43 | return X ^ Y ^ Z; | ||
44 | } | ||
45 | |||
46 | static __u32 | ||
47 | lshift(__u32 x, int s) | ||
48 | { | ||
49 | x &= 0xFFFFFFFF; | ||
50 | return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s)); | ||
51 | } | ||
52 | |||
53 | #define ROUND1(a,b,c,d,k,s) (*a) = lshift((*a) + F(*b,*c,*d) + X[k], s) | ||
54 | #define ROUND2(a,b,c,d,k,s) (*a) = lshift((*a) + G(*b,*c,*d) + X[k] + (__u32)0x5A827999,s) | ||
55 | #define ROUND3(a,b,c,d,k,s) (*a) = lshift((*a) + H(*b,*c,*d) + X[k] + (__u32)0x6ED9EBA1,s) | ||
56 | |||
57 | /* this applies md4 to 64 byte chunks */ | ||
58 | static void | ||
59 | mdfour64(__u32 *M, __u32 *A, __u32 *B, __u32 *C, __u32 *D) | ||
60 | { | ||
61 | int j; | ||
62 | __u32 AA, BB, CC, DD; | ||
63 | __u32 X[16]; | ||
64 | |||
65 | |||
66 | for (j = 0; j < 16; j++) | ||
67 | X[j] = M[j]; | ||
68 | |||
69 | AA = *A; | ||
70 | BB = *B; | ||
71 | CC = *C; | ||
72 | DD = *D; | ||
73 | |||
74 | ROUND1(A, B, C, D, 0, 3); | ||
75 | ROUND1(D, A, B, C, 1, 7); | ||
76 | ROUND1(C, D, A, B, 2, 11); | ||
77 | ROUND1(B, C, D, A, 3, 19); | ||
78 | ROUND1(A, B, C, D, 4, 3); | ||
79 | ROUND1(D, A, B, C, 5, 7); | ||
80 | ROUND1(C, D, A, B, 6, 11); | ||
81 | ROUND1(B, C, D, A, 7, 19); | ||
82 | ROUND1(A, B, C, D, 8, 3); | ||
83 | ROUND1(D, A, B, C, 9, 7); | ||
84 | ROUND1(C, D, A, B, 10, 11); | ||
85 | ROUND1(B, C, D, A, 11, 19); | ||
86 | ROUND1(A, B, C, D, 12, 3); | ||
87 | ROUND1(D, A, B, C, 13, 7); | ||
88 | ROUND1(C, D, A, B, 14, 11); | ||
89 | ROUND1(B, C, D, A, 15, 19); | ||
90 | |||
91 | ROUND2(A, B, C, D, 0, 3); | ||
92 | ROUND2(D, A, B, C, 4, 5); | ||
93 | ROUND2(C, D, A, B, 8, 9); | ||
94 | ROUND2(B, C, D, A, 12, 13); | ||
95 | ROUND2(A, B, C, D, 1, 3); | ||
96 | ROUND2(D, A, B, C, 5, 5); | ||
97 | ROUND2(C, D, A, B, 9, 9); | ||
98 | ROUND2(B, C, D, A, 13, 13); | ||
99 | ROUND2(A, B, C, D, 2, 3); | ||
100 | ROUND2(D, A, B, C, 6, 5); | ||
101 | ROUND2(C, D, A, B, 10, 9); | ||
102 | ROUND2(B, C, D, A, 14, 13); | ||
103 | ROUND2(A, B, C, D, 3, 3); | ||
104 | ROUND2(D, A, B, C, 7, 5); | ||
105 | ROUND2(C, D, A, B, 11, 9); | ||
106 | ROUND2(B, C, D, A, 15, 13); | ||
107 | |||
108 | ROUND3(A, B, C, D, 0, 3); | ||
109 | ROUND3(D, A, B, C, 8, 9); | ||
110 | ROUND3(C, D, A, B, 4, 11); | ||
111 | ROUND3(B, C, D, A, 12, 15); | ||
112 | ROUND3(A, B, C, D, 2, 3); | ||
113 | ROUND3(D, A, B, C, 10, 9); | ||
114 | ROUND3(C, D, A, B, 6, 11); | ||
115 | ROUND3(B, C, D, A, 14, 15); | ||
116 | ROUND3(A, B, C, D, 1, 3); | ||
117 | ROUND3(D, A, B, C, 9, 9); | ||
118 | ROUND3(C, D, A, B, 5, 11); | ||
119 | ROUND3(B, C, D, A, 13, 15); | ||
120 | ROUND3(A, B, C, D, 3, 3); | ||
121 | ROUND3(D, A, B, C, 11, 9); | ||
122 | ROUND3(C, D, A, B, 7, 11); | ||
123 | ROUND3(B, C, D, A, 15, 15); | ||
124 | |||
125 | *A += AA; | ||
126 | *B += BB; | ||
127 | *C += CC; | ||
128 | *D += DD; | ||
129 | |||
130 | *A &= 0xFFFFFFFF; | ||
131 | *B &= 0xFFFFFFFF; | ||
132 | *C &= 0xFFFFFFFF; | ||
133 | *D &= 0xFFFFFFFF; | ||
134 | |||
135 | for (j = 0; j < 16; j++) | ||
136 | X[j] = 0; | ||
137 | } | ||
138 | |||
139 | static void | ||
140 | copy64(__u32 *M, unsigned char *in) | ||
141 | { | ||
142 | int i; | ||
143 | |||
144 | for (i = 0; i < 16; i++) | ||
145 | M[i] = (in[i * 4 + 3] << 24) | (in[i * 4 + 2] << 16) | | ||
146 | (in[i * 4 + 1] << 8) | (in[i * 4 + 0] << 0); | ||
147 | } | ||
148 | |||
149 | static void | ||
150 | copy4(unsigned char *out, __u32 x) | ||
151 | { | ||
152 | out[0] = x & 0xFF; | ||
153 | out[1] = (x >> 8) & 0xFF; | ||
154 | out[2] = (x >> 16) & 0xFF; | ||
155 | out[3] = (x >> 24) & 0xFF; | ||
156 | } | ||
157 | |||
158 | /* produce a md4 message digest from data of length n bytes */ | ||
159 | void | ||
160 | mdfour(unsigned char *out, unsigned char *in, int n) | ||
161 | { | ||
162 | unsigned char buf[128]; | ||
163 | __u32 M[16]; | ||
164 | __u32 b = n * 8; | ||
165 | int i; | ||
166 | __u32 A = 0x67452301; | ||
167 | __u32 B = 0xefcdab89; | ||
168 | __u32 C = 0x98badcfe; | ||
169 | __u32 D = 0x10325476; | ||
170 | |||
171 | while (n > 64) { | ||
172 | copy64(M, in); | ||
173 | mdfour64(M, &A, &B, &C, &D); | ||
174 | in += 64; | ||
175 | n -= 64; | ||
176 | } | ||
177 | |||
178 | for (i = 0; i < 128; i++) | ||
179 | buf[i] = 0; | ||
180 | memcpy(buf, in, n); | ||
181 | buf[n] = 0x80; | ||
182 | |||
183 | if (n <= 55) { | ||
184 | copy4(buf + 56, b); | ||
185 | copy64(M, buf); | ||
186 | mdfour64(M, &A, &B, &C, &D); | ||
187 | } else { | ||
188 | copy4(buf + 120, b); | ||
189 | copy64(M, buf); | ||
190 | mdfour64(M, &A, &B, &C, &D); | ||
191 | copy64(M, buf + 64); | ||
192 | mdfour64(M, &A, &B, &C, &D); | ||
193 | } | ||
194 | |||
195 | for (i = 0; i < 128; i++) | ||
196 | buf[i] = 0; | ||
197 | copy64(M, buf); | ||
198 | |||
199 | copy4(out, A); | ||
200 | copy4(out + 4, B); | ||
201 | copy4(out + 8, C); | ||
202 | copy4(out + 12, D); | ||
203 | |||
204 | A = B = C = D = 0; | ||
205 | } | ||
diff --git a/fs/cifs/md5.c b/fs/cifs/md5.c deleted file mode 100644 index 98b66a54c319..000000000000 --- a/fs/cifs/md5.c +++ /dev/null | |||
@@ -1,366 +0,0 @@ | |||
1 | /* | ||
2 | * This code implements the MD5 message-digest algorithm. | ||
3 | * The algorithm is due to Ron Rivest. This code was | ||
4 | * written by Colin Plumb in 1993, no copyright is claimed. | ||
5 | * This code is in the public domain; do with it what you wish. | ||
6 | * | ||
7 | * Equivalent code is available from RSA Data Security, Inc. | ||
8 | * This code has been tested against that, and is equivalent, | ||
9 | * except that you don't need to include two pages of legalese | ||
10 | * with every copy. | ||
11 | * | ||
12 | * To compute the message digest of a chunk of bytes, declare an | ||
13 | * MD5Context structure, pass it to cifs_MD5_init, call cifs_MD5_update as | ||
14 | * needed on buffers full of bytes, and then call cifs_MD5_final, which | ||
15 | * will fill a supplied 16-byte array with the digest. | ||
16 | */ | ||
17 | |||
18 | /* This code slightly modified to fit into Samba by | ||
19 | abartlet@samba.org Jun 2001 | ||
20 | and to fit the cifs vfs by | ||
21 | Steve French sfrench@us.ibm.com */ | ||
22 | |||
23 | #include <linux/string.h> | ||
24 | #include "md5.h" | ||
25 | |||
26 | static void MD5Transform(__u32 buf[4], __u32 const in[16]); | ||
27 | |||
28 | /* | ||
29 | * Note: this code is harmless on little-endian machines. | ||
30 | */ | ||
31 | static void | ||
32 | byteReverse(unsigned char *buf, unsigned longs) | ||
33 | { | ||
34 | __u32 t; | ||
35 | do { | ||
36 | t = (__u32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | | ||
37 | ((unsigned) buf[1] << 8 | buf[0]); | ||
38 | *(__u32 *) buf = t; | ||
39 | buf += 4; | ||
40 | } while (--longs); | ||
41 | } | ||
42 | |||
43 | /* | ||
44 | * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious | ||
45 | * initialization constants. | ||
46 | */ | ||
47 | void | ||
48 | cifs_MD5_init(struct MD5Context *ctx) | ||
49 | { | ||
50 | ctx->buf[0] = 0x67452301; | ||
51 | ctx->buf[1] = 0xefcdab89; | ||
52 | ctx->buf[2] = 0x98badcfe; | ||
53 | ctx->buf[3] = 0x10325476; | ||
54 | |||
55 | ctx->bits[0] = 0; | ||
56 | ctx->bits[1] = 0; | ||
57 | } | ||
58 | |||
59 | /* | ||
60 | * Update context to reflect the concatenation of another buffer full | ||
61 | * of bytes. | ||
62 | */ | ||
63 | void | ||
64 | cifs_MD5_update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) | ||
65 | { | ||
66 | register __u32 t; | ||
67 | |||
68 | /* Update bitcount */ | ||
69 | |||
70 | t = ctx->bits[0]; | ||
71 | if ((ctx->bits[0] = t + ((__u32) len << 3)) < t) | ||
72 | ctx->bits[1]++; /* Carry from low to high */ | ||
73 | ctx->bits[1] += len >> 29; | ||
74 | |||
75 | t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ | ||
76 | |||
77 | /* Handle any leading odd-sized chunks */ | ||
78 | |||
79 | if (t) { | ||
80 | unsigned char *p = (unsigned char *) ctx->in + t; | ||
81 | |||
82 | t = 64 - t; | ||
83 | if (len < t) { | ||
84 | memmove(p, buf, len); | ||
85 | return; | ||
86 | } | ||
87 | memmove(p, buf, t); | ||
88 | byteReverse(ctx->in, 16); | ||
89 | MD5Transform(ctx->buf, (__u32 *) ctx->in); | ||
90 | buf += t; | ||
91 | len -= t; | ||
92 | } | ||
93 | /* Process data in 64-byte chunks */ | ||
94 | |||
95 | while (len >= 64) { | ||
96 | memmove(ctx->in, buf, 64); | ||
97 | byteReverse(ctx->in, 16); | ||
98 | MD5Transform(ctx->buf, (__u32 *) ctx->in); | ||
99 | buf += 64; | ||
100 | len -= 64; | ||
101 | } | ||
102 | |||
103 | /* Handle any remaining bytes of data. */ | ||
104 | |||
105 | memmove(ctx->in, buf, len); | ||
106 | } | ||
107 | |||
108 | /* | ||
109 | * Final wrapup - pad to 64-byte boundary with the bit pattern | ||
110 | * 1 0* (64-bit count of bits processed, MSB-first) | ||
111 | */ | ||
112 | void | ||
113 | cifs_MD5_final(unsigned char digest[16], struct MD5Context *ctx) | ||
114 | { | ||
115 | unsigned int count; | ||
116 | unsigned char *p; | ||
117 | |||
118 | /* Compute number of bytes mod 64 */ | ||
119 | count = (ctx->bits[0] >> 3) & 0x3F; | ||
120 | |||
121 | /* Set the first char of padding to 0x80. This is safe since there is | ||
122 | always at least one byte free */ | ||
123 | p = ctx->in + count; | ||
124 | *p++ = 0x80; | ||
125 | |||
126 | /* Bytes of padding needed to make 64 bytes */ | ||
127 | count = 64 - 1 - count; | ||
128 | |||
129 | /* Pad out to 56 mod 64 */ | ||
130 | if (count < 8) { | ||
131 | /* Two lots of padding: Pad the first block to 64 bytes */ | ||
132 | memset(p, 0, count); | ||
133 | byteReverse(ctx->in, 16); | ||
134 | MD5Transform(ctx->buf, (__u32 *) ctx->in); | ||
135 | |||
136 | /* Now fill the next block with 56 bytes */ | ||
137 | memset(ctx->in, 0, 56); | ||
138 | } else { | ||
139 | /* Pad block to 56 bytes */ | ||
140 | memset(p, 0, count - 8); | ||
141 | } | ||
142 | byteReverse(ctx->in, 14); | ||
143 | |||
144 | /* Append length in bits and transform */ | ||
145 | ((__u32 *) ctx->in)[14] = ctx->bits[0]; | ||
146 | ((__u32 *) ctx->in)[15] = ctx->bits[1]; | ||
147 | |||
148 | MD5Transform(ctx->buf, (__u32 *) ctx->in); | ||
149 | byteReverse((unsigned char *) ctx->buf, 4); | ||
150 | memmove(digest, ctx->buf, 16); | ||
151 | memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */ | ||
152 | } | ||
153 | |||
154 | /* The four core functions - F1 is optimized somewhat */ | ||
155 | |||
156 | /* #define F1(x, y, z) (x & y | ~x & z) */ | ||
157 | #define F1(x, y, z) (z ^ (x & (y ^ z))) | ||
158 | #define F2(x, y, z) F1(z, x, y) | ||
159 | #define F3(x, y, z) (x ^ y ^ z) | ||
160 | #define F4(x, y, z) (y ^ (x | ~z)) | ||
161 | |||
162 | /* This is the central step in the MD5 algorithm. */ | ||
163 | #define MD5STEP(f, w, x, y, z, data, s) \ | ||
164 | (w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x) | ||
165 | |||
166 | /* | ||
167 | * The core of the MD5 algorithm, this alters an existing MD5 hash to | ||
168 | * reflect the addition of 16 longwords of new data. cifs_MD5_update blocks | ||
169 | * the data and converts bytes into longwords for this routine. | ||
170 | */ | ||
171 | static void | ||
172 | MD5Transform(__u32 buf[4], __u32 const in[16]) | ||
173 | { | ||
174 | register __u32 a, b, c, d; | ||
175 | |||
176 | a = buf[0]; | ||
177 | b = buf[1]; | ||
178 | c = buf[2]; | ||
179 | d = buf[3]; | ||
180 | |||
181 | MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); | ||
182 | MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); | ||
183 | MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); | ||
184 | MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); | ||
185 | MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); | ||
186 | MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); | ||
187 | MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); | ||
188 | MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); | ||
189 | MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); | ||
190 | MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); | ||
191 | MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); | ||
192 | MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); | ||
193 | MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); | ||
194 | MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); | ||
195 | MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); | ||
196 | MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); | ||
197 | |||
198 | MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); | ||
199 | MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); | ||
200 | MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); | ||
201 | MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); | ||
202 | MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); | ||
203 | MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); | ||
204 | MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); | ||
205 | MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); | ||
206 | MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); | ||
207 | MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); | ||
208 | MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); | ||
209 | MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); | ||
210 | MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); | ||
211 | MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); | ||
212 | MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); | ||
213 | MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); | ||
214 | |||
215 | MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); | ||
216 | MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); | ||
217 | MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); | ||
218 | MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); | ||
219 | MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); | ||
220 | MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); | ||
221 | MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); | ||
222 | MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); | ||
223 | MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); | ||
224 | MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); | ||
225 | MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); | ||
226 | MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); | ||
227 | MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); | ||
228 | MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); | ||
229 | MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); | ||
230 | MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); | ||
231 | |||
232 | MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); | ||
233 | MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); | ||
234 | MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); | ||
235 | MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); | ||
236 | MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); | ||
237 | MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); | ||
238 | MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); | ||
239 | MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); | ||
240 | MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); | ||
241 | MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); | ||
242 | MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); | ||
243 | MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); | ||
244 | MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); | ||
245 | MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); | ||
246 | MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); | ||
247 | MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); | ||
248 | |||
249 | buf[0] += a; | ||
250 | buf[1] += b; | ||
251 | buf[2] += c; | ||
252 | buf[3] += d; | ||
253 | } | ||
254 | |||
255 | #if 0 /* currently unused */ | ||
256 | /*********************************************************************** | ||
257 | the rfc 2104 version of hmac_md5 initialisation. | ||
258 | ***********************************************************************/ | ||
259 | static void | ||
260 | hmac_md5_init_rfc2104(unsigned char *key, int key_len, | ||
261 | struct HMACMD5Context *ctx) | ||
262 | { | ||
263 | int i; | ||
264 | |||
265 | /* if key is longer than 64 bytes reset it to key=MD5(key) */ | ||
266 | if (key_len > 64) { | ||
267 | unsigned char tk[16]; | ||
268 | struct MD5Context tctx; | ||
269 | |||
270 | cifs_MD5_init(&tctx); | ||
271 | cifs_MD5_update(&tctx, key, key_len); | ||
272 | cifs_MD5_final(tk, &tctx); | ||
273 | |||
274 | key = tk; | ||
275 | key_len = 16; | ||
276 | } | ||
277 | |||
278 | /* start out by storing key in pads */ | ||
279 | memset(ctx->k_ipad, 0, sizeof(ctx->k_ipad)); | ||
280 | memset(ctx->k_opad, 0, sizeof(ctx->k_opad)); | ||
281 | memcpy(ctx->k_ipad, key, key_len); | ||
282 | memcpy(ctx->k_opad, key, key_len); | ||
283 | |||
284 | /* XOR key with ipad and opad values */ | ||
285 | for (i = 0; i < 64; i++) { | ||
286 | ctx->k_ipad[i] ^= 0x36; | ||
287 | ctx->k_opad[i] ^= 0x5c; | ||
288 | } | ||
289 | |||
290 | cifs_MD5_init(&ctx->ctx); | ||
291 | cifs_MD5_update(&ctx->ctx, ctx->k_ipad, 64); | ||
292 | } | ||
293 | #endif | ||
294 | |||
295 | /*********************************************************************** | ||
296 | the microsoft version of hmac_md5 initialisation. | ||
297 | ***********************************************************************/ | ||
298 | void | ||
299 | hmac_md5_init_limK_to_64(const unsigned char *key, int key_len, | ||
300 | struct HMACMD5Context *ctx) | ||
301 | { | ||
302 | int i; | ||
303 | |||
304 | /* if key is longer than 64 bytes truncate it */ | ||
305 | if (key_len > 64) | ||
306 | key_len = 64; | ||
307 | |||
308 | /* start out by storing key in pads */ | ||
309 | memset(ctx->k_ipad, 0, sizeof(ctx->k_ipad)); | ||
310 | memset(ctx->k_opad, 0, sizeof(ctx->k_opad)); | ||
311 | memcpy(ctx->k_ipad, key, key_len); | ||
312 | memcpy(ctx->k_opad, key, key_len); | ||
313 | |||
314 | /* XOR key with ipad and opad values */ | ||
315 | for (i = 0; i < 64; i++) { | ||
316 | ctx->k_ipad[i] ^= 0x36; | ||
317 | ctx->k_opad[i] ^= 0x5c; | ||
318 | } | ||
319 | |||
320 | cifs_MD5_init(&ctx->ctx); | ||
321 | cifs_MD5_update(&ctx->ctx, ctx->k_ipad, 64); | ||
322 | } | ||
323 | |||
324 | /*********************************************************************** | ||
325 | update hmac_md5 "inner" buffer | ||
326 | ***********************************************************************/ | ||
327 | void | ||
328 | hmac_md5_update(const unsigned char *text, int text_len, | ||
329 | struct HMACMD5Context *ctx) | ||
330 | { | ||
331 | cifs_MD5_update(&ctx->ctx, text, text_len); /* then text of datagram */ | ||
332 | } | ||
333 | |||
334 | /*********************************************************************** | ||
335 | finish off hmac_md5 "inner" buffer and generate outer one. | ||
336 | ***********************************************************************/ | ||
337 | void | ||
338 | hmac_md5_final(unsigned char *digest, struct HMACMD5Context *ctx) | ||
339 | { | ||
340 | struct MD5Context ctx_o; | ||
341 | |||
342 | cifs_MD5_final(digest, &ctx->ctx); | ||
343 | |||
344 | cifs_MD5_init(&ctx_o); | ||
345 | cifs_MD5_update(&ctx_o, ctx->k_opad, 64); | ||
346 | cifs_MD5_update(&ctx_o, digest, 16); | ||
347 | cifs_MD5_final(digest, &ctx_o); | ||
348 | } | ||
349 | |||
350 | /*********************************************************** | ||
351 | single function to calculate an HMAC MD5 digest from data. | ||
352 | use the microsoft hmacmd5 init method because the key is 16 bytes. | ||
353 | ************************************************************/ | ||
354 | #if 0 /* currently unused */ | ||
355 | static void | ||
356 | hmac_md5(unsigned char key[16], unsigned char *data, int data_len, | ||
357 | unsigned char *digest) | ||
358 | { | ||
359 | struct HMACMD5Context ctx; | ||
360 | hmac_md5_init_limK_to_64(key, 16, &ctx); | ||
361 | if (data_len != 0) | ||
362 | hmac_md5_update(data, data_len, &ctx); | ||
363 | |||
364 | hmac_md5_final(digest, &ctx); | ||
365 | } | ||
366 | #endif | ||
diff --git a/fs/cifs/md5.h b/fs/cifs/md5.h deleted file mode 100644 index 6fba8cb402fd..000000000000 --- a/fs/cifs/md5.h +++ /dev/null | |||
@@ -1,38 +0,0 @@ | |||
1 | #ifndef MD5_H | ||
2 | #define MD5_H | ||
3 | #ifndef HEADER_MD5_H | ||
4 | /* Try to avoid clashes with OpenSSL */ | ||
5 | #define HEADER_MD5_H | ||
6 | #endif | ||
7 | |||
8 | struct MD5Context { | ||
9 | __u32 buf[4]; | ||
10 | __u32 bits[2]; | ||
11 | unsigned char in[64]; | ||
12 | }; | ||
13 | #endif /* !MD5_H */ | ||
14 | |||
15 | #ifndef _HMAC_MD5_H | ||
16 | struct HMACMD5Context { | ||
17 | struct MD5Context ctx; | ||
18 | unsigned char k_ipad[65]; | ||
19 | unsigned char k_opad[65]; | ||
20 | }; | ||
21 | #endif /* _HMAC_MD5_H */ | ||
22 | |||
23 | void cifs_MD5_init(struct MD5Context *context); | ||
24 | void cifs_MD5_update(struct MD5Context *context, unsigned char const *buf, | ||
25 | unsigned len); | ||
26 | void cifs_MD5_final(unsigned char digest[16], struct MD5Context *context); | ||
27 | |||
28 | /* The following definitions come from lib/hmacmd5.c */ | ||
29 | |||
30 | /* void hmac_md5_init_rfc2104(unsigned char *key, int key_len, | ||
31 | struct HMACMD5Context *ctx);*/ | ||
32 | void hmac_md5_init_limK_to_64(const unsigned char *key, int key_len, | ||
33 | struct HMACMD5Context *ctx); | ||
34 | void hmac_md5_update(const unsigned char *text, int text_len, | ||
35 | struct HMACMD5Context *ctx); | ||
36 | void hmac_md5_final(unsigned char *digest, struct HMACMD5Context *ctx); | ||
37 | /* void hmac_md5(unsigned char key[16], unsigned char *data, int data_len, | ||
38 | unsigned char *digest);*/ | ||
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 43f10281bc19..2a930a752a78 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c | |||
@@ -236,10 +236,7 @@ __u16 GetNextMid(struct TCP_Server_Info *server) | |||
236 | { | 236 | { |
237 | __u16 mid = 0; | 237 | __u16 mid = 0; |
238 | __u16 last_mid; | 238 | __u16 last_mid; |
239 | int collision; | 239 | bool collision; |
240 | |||
241 | if (server == NULL) | ||
242 | return mid; | ||
243 | 240 | ||
244 | spin_lock(&GlobalMid_Lock); | 241 | spin_lock(&GlobalMid_Lock); |
245 | last_mid = server->CurrentMid; /* we do not want to loop forever */ | 242 | last_mid = server->CurrentMid; /* we do not want to loop forever */ |
@@ -252,24 +249,38 @@ __u16 GetNextMid(struct TCP_Server_Info *server) | |||
252 | (and it would also have to have been a request that | 249 | (and it would also have to have been a request that |
253 | did not time out) */ | 250 | did not time out) */ |
254 | while (server->CurrentMid != last_mid) { | 251 | while (server->CurrentMid != last_mid) { |
255 | struct list_head *tmp; | ||
256 | struct mid_q_entry *mid_entry; | 252 | struct mid_q_entry *mid_entry; |
253 | unsigned int num_mids; | ||
257 | 254 | ||
258 | collision = 0; | 255 | collision = false; |
259 | if (server->CurrentMid == 0) | 256 | if (server->CurrentMid == 0) |
260 | server->CurrentMid++; | 257 | server->CurrentMid++; |
261 | 258 | ||
262 | list_for_each(tmp, &server->pending_mid_q) { | 259 | num_mids = 0; |
263 | mid_entry = list_entry(tmp, struct mid_q_entry, qhead); | 260 | list_for_each_entry(mid_entry, &server->pending_mid_q, qhead) { |
264 | 261 | ++num_mids; | |
265 | if ((mid_entry->mid == server->CurrentMid) && | 262 | if (mid_entry->mid == server->CurrentMid && |
266 | (mid_entry->midState == MID_REQUEST_SUBMITTED)) { | 263 | mid_entry->midState == MID_REQUEST_SUBMITTED) { |
267 | /* This mid is in use, try a different one */ | 264 | /* This mid is in use, try a different one */ |
268 | collision = 1; | 265 | collision = true; |
269 | break; | 266 | break; |
270 | } | 267 | } |
271 | } | 268 | } |
272 | if (collision == 0) { | 269 | |
270 | /* | ||
271 | * if we have more than 32k mids in the list, then something | ||
272 | * is very wrong. Possibly a local user is trying to DoS the | ||
273 | * box by issuing long-running calls and SIGKILL'ing them. If | ||
274 | * we get to 2^16 mids then we're in big trouble as this | ||
275 | * function could loop forever. | ||
276 | * | ||
277 | * Go ahead and assign out the mid in this situation, but force | ||
278 | * an eventual reconnect to clean out the pending_mid_q. | ||
279 | */ | ||
280 | if (num_mids > 32768) | ||
281 | server->tcpStatus = CifsNeedReconnect; | ||
282 | |||
283 | if (!collision) { | ||
273 | mid = server->CurrentMid; | 284 | mid = server->CurrentMid; |
274 | break; | 285 | break; |
275 | } | 286 | } |
@@ -381,29 +392,31 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , | |||
381 | } | 392 | } |
382 | 393 | ||
383 | static int | 394 | static int |
384 | checkSMBhdr(struct smb_hdr *smb, __u16 mid) | 395 | check_smb_hdr(struct smb_hdr *smb, __u16 mid) |
385 | { | 396 | { |
386 | /* Make sure that this really is an SMB, that it is a response, | 397 | /* does it have the right SMB "signature" ? */ |
387 | and that the message ids match */ | 398 | if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff)) { |
388 | if ((*(__le32 *) smb->Protocol == cpu_to_le32(0x424d53ff)) && | 399 | cERROR(1, "Bad protocol string signature header 0x%x", |
389 | (mid == smb->Mid)) { | 400 | *(unsigned int *)smb->Protocol); |
390 | if (smb->Flags & SMBFLG_RESPONSE) | 401 | return 1; |
391 | return 0; | ||
392 | else { | ||
393 | /* only one valid case where server sends us request */ | ||
394 | if (smb->Command == SMB_COM_LOCKING_ANDX) | ||
395 | return 0; | ||
396 | else | ||
397 | cERROR(1, "Received Request not response"); | ||
398 | } | ||
399 | } else { /* bad signature or mid */ | ||
400 | if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff)) | ||
401 | cERROR(1, "Bad protocol string signature header %x", | ||
402 | *(unsigned int *) smb->Protocol); | ||
403 | if (mid != smb->Mid) | ||
404 | cERROR(1, "Mids do not match"); | ||
405 | } | 402 | } |
406 | cERROR(1, "bad smb detected. The Mid=%d", smb->Mid); | 403 | |
404 | /* Make sure that message ids match */ | ||
405 | if (mid != smb->Mid) { | ||
406 | cERROR(1, "Mids do not match. received=%u expected=%u", | ||
407 | smb->Mid, mid); | ||
408 | return 1; | ||
409 | } | ||
410 | |||
411 | /* if it's a response then accept */ | ||
412 | if (smb->Flags & SMBFLG_RESPONSE) | ||
413 | return 0; | ||
414 | |||
415 | /* only one valid case where server sends us request */ | ||
416 | if (smb->Command == SMB_COM_LOCKING_ANDX) | ||
417 | return 0; | ||
418 | |||
419 | cERROR(1, "Server sent request, not response. mid=%u", smb->Mid); | ||
407 | return 1; | 420 | return 1; |
408 | } | 421 | } |
409 | 422 | ||
@@ -448,7 +461,7 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length) | |||
448 | return 1; | 461 | return 1; |
449 | } | 462 | } |
450 | 463 | ||
451 | if (checkSMBhdr(smb, mid)) | 464 | if (check_smb_hdr(smb, mid)) |
452 | return 1; | 465 | return 1; |
453 | clc_len = smbCalcSize_LE(smb); | 466 | clc_len = smbCalcSize_LE(smb); |
454 | 467 | ||
@@ -465,25 +478,26 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length) | |||
465 | if (((4 + len) & 0xFFFF) == (clc_len & 0xFFFF)) | 478 | if (((4 + len) & 0xFFFF) == (clc_len & 0xFFFF)) |
466 | return 0; /* bcc wrapped */ | 479 | return 0; /* bcc wrapped */ |
467 | } | 480 | } |
468 | cFYI(1, "Calculated size %d vs length %d mismatch for mid %d", | 481 | cFYI(1, "Calculated size %u vs length %u mismatch for mid=%u", |
469 | clc_len, 4 + len, smb->Mid); | 482 | clc_len, 4 + len, smb->Mid); |
470 | /* Windows XP can return a few bytes too much, presumably | 483 | |
471 | an illegal pad, at the end of byte range lock responses | 484 | if (4 + len < clc_len) { |
472 | so we allow for that three byte pad, as long as actual | 485 | cERROR(1, "RFC1001 size %u smaller than SMB for mid=%u", |
473 | received length is as long or longer than calculated length */ | ||
474 | /* We have now had to extend this more, since there is a | ||
475 | case in which it needs to be bigger still to handle a | ||
476 | malformed response to transact2 findfirst from WinXP when | ||
477 | access denied is returned and thus bcc and wct are zero | ||
478 | but server says length is 0x21 bytes too long as if the server | ||
479 | forget to reset the smb rfc1001 length when it reset the | ||
480 | wct and bcc to minimum size and drop the t2 parms and data */ | ||
481 | if ((4+len > clc_len) && (len <= clc_len + 512)) | ||
482 | return 0; | ||
483 | else { | ||
484 | cERROR(1, "RFC1001 size %d bigger than SMB for Mid=%d", | ||
485 | len, smb->Mid); | 486 | len, smb->Mid); |
486 | return 1; | 487 | return 1; |
488 | } else if (len > clc_len + 512) { | ||
489 | /* | ||
490 | * Some servers (Windows XP in particular) send more | ||
491 | * data than the lengths in the SMB packet would | ||
492 | * indicate on certain calls (byte range locks and | ||
493 | * trans2 find first calls in particular). While the | ||
494 | * client can handle such a frame by ignoring the | ||
495 | * trailing data, we choose limit the amount of extra | ||
496 | * data to 512 bytes. | ||
497 | */ | ||
498 | cERROR(1, "RFC1001 size %u more than 512 bytes larger " | ||
499 | "than SMB for mid=%u", len, smb->Mid); | ||
500 | return 1; | ||
487 | } | 501 | } |
488 | } | 502 | } |
489 | return 0; | 503 | return 0; |
@@ -571,7 +585,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) | |||
571 | pCifsInode = CIFS_I(netfile->dentry->d_inode); | 585 | pCifsInode = CIFS_I(netfile->dentry->d_inode); |
572 | 586 | ||
573 | cifs_set_oplock_level(pCifsInode, | 587 | cifs_set_oplock_level(pCifsInode, |
574 | pSMB->OplockLevel); | 588 | pSMB->OplockLevel ? OPLOCK_READ : 0); |
575 | /* | 589 | /* |
576 | * cifs_oplock_break_put() can't be called | 590 | * cifs_oplock_break_put() can't be called |
577 | * from here. Get reference after queueing | 591 | * from here. Get reference after queueing |
@@ -637,77 +651,6 @@ dump_smb(struct smb_hdr *smb_buf, int smb_buf_length) | |||
637 | return; | 651 | return; |
638 | } | 652 | } |
639 | 653 | ||
640 | /* Convert 16 bit Unicode pathname to wire format from string in current code | ||
641 | page. Conversion may involve remapping up the seven characters that are | ||
642 | only legal in POSIX-like OS (if they are present in the string). Path | ||
643 | names are little endian 16 bit Unicode on the wire */ | ||
644 | int | ||
645 | cifsConvertToUCS(__le16 *target, const char *source, int maxlen, | ||
646 | const struct nls_table *cp, int mapChars) | ||
647 | { | ||
648 | int i, j, charlen; | ||
649 | int len_remaining = maxlen; | ||
650 | char src_char; | ||
651 | __u16 temp; | ||
652 | |||
653 | if (!mapChars) | ||
654 | return cifs_strtoUCS(target, source, PATH_MAX, cp); | ||
655 | |||
656 | for (i = 0, j = 0; i < maxlen; j++) { | ||
657 | src_char = source[i]; | ||
658 | switch (src_char) { | ||
659 | case 0: | ||
660 | target[j] = 0; | ||
661 | goto ctoUCS_out; | ||
662 | case ':': | ||
663 | target[j] = cpu_to_le16(UNI_COLON); | ||
664 | break; | ||
665 | case '*': | ||
666 | target[j] = cpu_to_le16(UNI_ASTERIK); | ||
667 | break; | ||
668 | case '?': | ||
669 | target[j] = cpu_to_le16(UNI_QUESTION); | ||
670 | break; | ||
671 | case '<': | ||
672 | target[j] = cpu_to_le16(UNI_LESSTHAN); | ||
673 | break; | ||
674 | case '>': | ||
675 | target[j] = cpu_to_le16(UNI_GRTRTHAN); | ||
676 | break; | ||
677 | case '|': | ||
678 | target[j] = cpu_to_le16(UNI_PIPE); | ||
679 | break; | ||
680 | /* BB We can not handle remapping slash until | ||
681 | all the calls to build_path_from_dentry | ||
682 | are modified, as they use slash as separator BB */ | ||
683 | /* case '\\': | ||
684 | target[j] = cpu_to_le16(UNI_SLASH); | ||
685 | break;*/ | ||
686 | default: | ||
687 | charlen = cp->char2uni(source+i, | ||
688 | len_remaining, &temp); | ||
689 | /* if no match, use question mark, which | ||
690 | at least in some cases servers as wild card */ | ||
691 | if (charlen < 1) { | ||
692 | target[j] = cpu_to_le16(0x003f); | ||
693 | charlen = 1; | ||
694 | } else | ||
695 | target[j] = cpu_to_le16(temp); | ||
696 | len_remaining -= charlen; | ||
697 | /* character may take more than one byte in the | ||
698 | the source string, but will take exactly two | ||
699 | bytes in the target string */ | ||
700 | i += charlen; | ||
701 | continue; | ||
702 | } | ||
703 | i++; /* move to next char in source string */ | ||
704 | len_remaining--; | ||
705 | } | ||
706 | |||
707 | ctoUCS_out: | ||
708 | return i; | ||
709 | } | ||
710 | |||
711 | void | 654 | void |
712 | cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb) | 655 | cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb) |
713 | { | 656 | { |
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index 9aad47a2d62f..79f641eeda30 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c | |||
@@ -170,7 +170,7 @@ cifs_convert_address(struct sockaddr *dst, const char *src, int len) | |||
170 | { | 170 | { |
171 | int rc, alen, slen; | 171 | int rc, alen, slen; |
172 | const char *pct; | 172 | const char *pct; |
173 | char *endp, scope_id[13]; | 173 | char scope_id[13]; |
174 | struct sockaddr_in *s4 = (struct sockaddr_in *) dst; | 174 | struct sockaddr_in *s4 = (struct sockaddr_in *) dst; |
175 | struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) dst; | 175 | struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) dst; |
176 | 176 | ||
@@ -197,9 +197,9 @@ cifs_convert_address(struct sockaddr *dst, const char *src, int len) | |||
197 | memcpy(scope_id, pct + 1, slen); | 197 | memcpy(scope_id, pct + 1, slen); |
198 | scope_id[slen] = '\0'; | 198 | scope_id[slen] = '\0'; |
199 | 199 | ||
200 | s6->sin6_scope_id = (u32) simple_strtoul(pct, &endp, 0); | 200 | rc = strict_strtoul(scope_id, 0, |
201 | if (endp != scope_id + slen) | 201 | (unsigned long *)&s6->sin6_scope_id); |
202 | return 0; | 202 | rc = (rc == 0) ? 1 : 0; |
203 | } | 203 | } |
204 | 204 | ||
205 | return rc; | 205 | return rc; |
@@ -899,8 +899,8 @@ map_smb_to_linux_error(struct smb_hdr *smb, int logErr) | |||
899 | } | 899 | } |
900 | /* else ERRHRD class errors or junk - return EIO */ | 900 | /* else ERRHRD class errors or junk - return EIO */ |
901 | 901 | ||
902 | cFYI(1, "Mapping smb error code %d to POSIX err %d", | 902 | cFYI(1, "Mapping smb error code 0x%x to POSIX err %d", |
903 | smberrcode, rc); | 903 | le32_to_cpu(smb->Status.CifsError), rc); |
904 | 904 | ||
905 | /* generic corrective action e.g. reconnect SMB session on | 905 | /* generic corrective action e.g. reconnect SMB session on |
906 | * ERRbaduid could be added */ | 906 | * ERRbaduid could be added */ |
@@ -916,14 +916,14 @@ unsigned int | |||
916 | smbCalcSize(struct smb_hdr *ptr) | 916 | smbCalcSize(struct smb_hdr *ptr) |
917 | { | 917 | { |
918 | return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) + | 918 | return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) + |
919 | 2 /* size of the bcc field */ + BCC(ptr)); | 919 | 2 /* size of the bcc field */ + get_bcc(ptr)); |
920 | } | 920 | } |
921 | 921 | ||
922 | unsigned int | 922 | unsigned int |
923 | smbCalcSize_LE(struct smb_hdr *ptr) | 923 | smbCalcSize_LE(struct smb_hdr *ptr) |
924 | { | 924 | { |
925 | return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) + | 925 | return (sizeof(struct smb_hdr) + (2 * ptr->WordCount) + |
926 | 2 /* size of the bcc field */ + le16_to_cpu(BCC_LE(ptr))); | 926 | 2 /* size of the bcc field */ + get_bcc_le(ptr)); |
927 | } | 927 | } |
928 | 928 | ||
929 | /* The following are taken from fs/ntfs/util.c */ | 929 | /* The following are taken from fs/ntfs/util.c */ |
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index a73eb9f4bdaf..f8e4cd2a7912 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
@@ -79,7 +79,7 @@ cifs_readdir_lookup(struct dentry *parent, struct qstr *name, | |||
79 | cFYI(1, "For %s", name->name); | 79 | cFYI(1, "For %s", name->name); |
80 | 80 | ||
81 | if (parent->d_op && parent->d_op->d_hash) | 81 | if (parent->d_op && parent->d_op->d_hash) |
82 | parent->d_op->d_hash(parent, name); | 82 | parent->d_op->d_hash(parent, parent->d_inode, name); |
83 | else | 83 | else |
84 | name->hash = full_name_hash(name->name, name->len); | 84 | name->hash = full_name_hash(name->name, name->len); |
85 | 85 | ||
@@ -102,11 +102,6 @@ cifs_readdir_lookup(struct dentry *parent, struct qstr *name, | |||
102 | return NULL; | 102 | return NULL; |
103 | } | 103 | } |
104 | 104 | ||
105 | if (cifs_sb_master_tcon(CIFS_SB(sb))->nocase) | ||
106 | dentry->d_op = &cifs_ci_dentry_ops; | ||
107 | else | ||
108 | dentry->d_op = &cifs_dentry_ops; | ||
109 | |||
110 | alias = d_materialise_unique(dentry, inode); | 105 | alias = d_materialise_unique(dentry, inode); |
111 | if (alias != NULL) { | 106 | if (alias != NULL) { |
112 | dput(dentry); | 107 | dput(dentry); |
@@ -160,6 +155,7 @@ cifs_dir_info_to_fattr(struct cifs_fattr *fattr, FILE_DIRECTORY_INFO *info, | |||
160 | fattr->cf_cifsattrs = le32_to_cpu(info->ExtFileAttributes); | 155 | fattr->cf_cifsattrs = le32_to_cpu(info->ExtFileAttributes); |
161 | fattr->cf_eof = le64_to_cpu(info->EndOfFile); | 156 | fattr->cf_eof = le64_to_cpu(info->EndOfFile); |
162 | fattr->cf_bytes = le64_to_cpu(info->AllocationSize); | 157 | fattr->cf_bytes = le64_to_cpu(info->AllocationSize); |
158 | fattr->cf_createtime = le64_to_cpu(info->CreationTime); | ||
163 | fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime); | 159 | fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime); |
164 | fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime); | 160 | fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime); |
165 | fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime); | 161 | fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime); |
@@ -768,7 +764,6 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) | |||
768 | { | 764 | { |
769 | int rc = 0; | 765 | int rc = 0; |
770 | int xid, i; | 766 | int xid, i; |
771 | struct cifs_sb_info *cifs_sb; | ||
772 | struct cifsTconInfo *pTcon; | 767 | struct cifsTconInfo *pTcon; |
773 | struct cifsFileInfo *cifsFile = NULL; | 768 | struct cifsFileInfo *cifsFile = NULL; |
774 | char *current_entry; | 769 | char *current_entry; |
@@ -779,8 +774,6 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) | |||
779 | 774 | ||
780 | xid = GetXid(); | 775 | xid = GetXid(); |
781 | 776 | ||
782 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | ||
783 | |||
784 | /* | 777 | /* |
785 | * Ensure FindFirst doesn't fail before doing filldir() for '.' and | 778 | * Ensure FindFirst doesn't fail before doing filldir() for '.' and |
786 | * '..'. Otherwise we won't be able to notify VFS in case of failure. | 779 | * '..'. Otherwise we won't be able to notify VFS in case of failure. |
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 7b01d3f6eed6..16765703131b 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c | |||
@@ -277,7 +277,7 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses, | |||
277 | } | 277 | } |
278 | 278 | ||
279 | static void | 279 | static void |
280 | decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifsSesInfo *ses, | 280 | decode_unicode_ssetup(char **pbcc_area, __u16 bleft, struct cifsSesInfo *ses, |
281 | const struct nls_table *nls_cp) | 281 | const struct nls_table *nls_cp) |
282 | { | 282 | { |
283 | int len; | 283 | int len; |
@@ -323,7 +323,7 @@ decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifsSesInfo *ses, | |||
323 | return; | 323 | return; |
324 | } | 324 | } |
325 | 325 | ||
326 | static int decode_ascii_ssetup(char **pbcc_area, int bleft, | 326 | static int decode_ascii_ssetup(char **pbcc_area, __u16 bleft, |
327 | struct cifsSesInfo *ses, | 327 | struct cifsSesInfo *ses, |
328 | const struct nls_table *nls_cp) | 328 | const struct nls_table *nls_cp) |
329 | { | 329 | { |
@@ -420,7 +420,6 @@ static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, | |||
420 | return 0; | 420 | return 0; |
421 | } | 421 | } |
422 | 422 | ||
423 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
424 | /* BB Move to ntlmssp.c eventually */ | 423 | /* BB Move to ntlmssp.c eventually */ |
425 | 424 | ||
426 | /* We do not malloc the blob, it is passed in pbuffer, because | 425 | /* We do not malloc the blob, it is passed in pbuffer, because |
@@ -431,13 +430,14 @@ static void build_ntlmssp_negotiate_blob(unsigned char *pbuffer, | |||
431 | NEGOTIATE_MESSAGE *sec_blob = (NEGOTIATE_MESSAGE *)pbuffer; | 430 | NEGOTIATE_MESSAGE *sec_blob = (NEGOTIATE_MESSAGE *)pbuffer; |
432 | __u32 flags; | 431 | __u32 flags; |
433 | 432 | ||
433 | memset(pbuffer, 0, sizeof(NEGOTIATE_MESSAGE)); | ||
434 | memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); | 434 | memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); |
435 | sec_blob->MessageType = NtLmNegotiate; | 435 | sec_blob->MessageType = NtLmNegotiate; |
436 | 436 | ||
437 | /* BB is NTLMV2 session security format easier to use here? */ | 437 | /* BB is NTLMV2 session security format easier to use here? */ |
438 | flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET | | 438 | flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET | |
439 | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | | 439 | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | |
440 | NTLMSSP_NEGOTIATE_NTLM; | 440 | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC; |
441 | if (ses->server->secMode & | 441 | if (ses->server->secMode & |
442 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { | 442 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { |
443 | flags |= NTLMSSP_NEGOTIATE_SIGN; | 443 | flags |= NTLMSSP_NEGOTIATE_SIGN; |
@@ -446,7 +446,7 @@ static void build_ntlmssp_negotiate_blob(unsigned char *pbuffer, | |||
446 | NTLMSSP_NEGOTIATE_EXTENDED_SEC; | 446 | NTLMSSP_NEGOTIATE_EXTENDED_SEC; |
447 | } | 447 | } |
448 | 448 | ||
449 | sec_blob->NegotiateFlags |= cpu_to_le32(flags); | 449 | sec_blob->NegotiateFlags = cpu_to_le32(flags); |
450 | 450 | ||
451 | sec_blob->WorkstationName.BufferOffset = 0; | 451 | sec_blob->WorkstationName.BufferOffset = 0; |
452 | sec_blob->WorkstationName.Length = 0; | 452 | sec_blob->WorkstationName.Length = 0; |
@@ -477,7 +477,7 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, | |||
477 | flags = NTLMSSP_NEGOTIATE_56 | | 477 | flags = NTLMSSP_NEGOTIATE_56 | |
478 | NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO | | 478 | NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO | |
479 | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | | 479 | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | |
480 | NTLMSSP_NEGOTIATE_NTLM; | 480 | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC; |
481 | if (ses->server->secMode & | 481 | if (ses->server->secMode & |
482 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) | 482 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) |
483 | flags |= NTLMSSP_NEGOTIATE_SIGN; | 483 | flags |= NTLMSSP_NEGOTIATE_SIGN; |
@@ -485,7 +485,7 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, | |||
485 | flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; | 485 | flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; |
486 | 486 | ||
487 | tmp = pbuffer + sizeof(AUTHENTICATE_MESSAGE); | 487 | tmp = pbuffer + sizeof(AUTHENTICATE_MESSAGE); |
488 | sec_blob->NegotiateFlags |= cpu_to_le32(flags); | 488 | sec_blob->NegotiateFlags = cpu_to_le32(flags); |
489 | 489 | ||
490 | sec_blob->LmChallengeResponse.BufferOffset = | 490 | sec_blob->LmChallengeResponse.BufferOffset = |
491 | cpu_to_le32(sizeof(AUTHENTICATE_MESSAGE)); | 491 | cpu_to_le32(sizeof(AUTHENTICATE_MESSAGE)); |
@@ -544,8 +544,9 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, | |||
544 | sec_blob->WorkstationName.MaximumLength = 0; | 544 | sec_blob->WorkstationName.MaximumLength = 0; |
545 | tmp += 2; | 545 | tmp += 2; |
546 | 546 | ||
547 | if ((ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) && | 547 | if (((ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_KEY_XCH) || |
548 | !calc_seckey(ses)) { | 548 | (ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_EXTENDED_SEC)) |
549 | && !calc_seckey(ses)) { | ||
549 | memcpy(tmp, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE); | 550 | memcpy(tmp, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE); |
550 | sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); | 551 | sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer); |
551 | sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE); | 552 | sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE); |
@@ -563,17 +564,6 @@ setup_ntlmv2_ret: | |||
563 | return rc; | 564 | return rc; |
564 | } | 565 | } |
565 | 566 | ||
566 | |||
567 | static void setup_ntlmssp_neg_req(SESSION_SETUP_ANDX *pSMB, | ||
568 | struct cifsSesInfo *ses) | ||
569 | { | ||
570 | build_ntlmssp_negotiate_blob(&pSMB->req.SecurityBlob[0], ses); | ||
571 | pSMB->req.SecurityBlobLength = cpu_to_le16(sizeof(NEGOTIATE_MESSAGE)); | ||
572 | |||
573 | return; | ||
574 | } | ||
575 | #endif | ||
576 | |||
577 | int | 567 | int |
578 | CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, | 568 | CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, |
579 | const struct nls_table *nls_cp) | 569 | const struct nls_table *nls_cp) |
@@ -585,12 +575,11 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, | |||
585 | char *str_area; | 575 | char *str_area; |
586 | SESSION_SETUP_ANDX *pSMB; | 576 | SESSION_SETUP_ANDX *pSMB; |
587 | __u32 capabilities; | 577 | __u32 capabilities; |
588 | int count; | 578 | __u16 count; |
589 | int resp_buf_type; | 579 | int resp_buf_type; |
590 | struct kvec iov[3]; | 580 | struct kvec iov[3]; |
591 | enum securityEnum type; | 581 | enum securityEnum type; |
592 | __u16 action; | 582 | __u16 action, bytes_remaining; |
593 | int bytes_remaining; | ||
594 | struct key *spnego_key = NULL; | 583 | struct key *spnego_key = NULL; |
595 | __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */ | 584 | __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */ |
596 | u16 blob_len; | 585 | u16 blob_len; |
@@ -667,13 +656,13 @@ ssetup_ntlmssp_authenticate: | |||
667 | 656 | ||
668 | if (type == LANMAN) { | 657 | if (type == LANMAN) { |
669 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | 658 | #ifdef CONFIG_CIFS_WEAK_PW_HASH |
670 | char lnm_session_key[CIFS_SESS_KEY_SIZE]; | 659 | char lnm_session_key[CIFS_AUTH_RESP_SIZE]; |
671 | 660 | ||
672 | pSMB->req.hdr.Flags2 &= ~SMBFLG2_UNICODE; | 661 | pSMB->req.hdr.Flags2 &= ~SMBFLG2_UNICODE; |
673 | 662 | ||
674 | /* no capabilities flags in old lanman negotiation */ | 663 | /* no capabilities flags in old lanman negotiation */ |
675 | 664 | ||
676 | pSMB->old_req.PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE); | 665 | pSMB->old_req.PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE); |
677 | 666 | ||
678 | /* Calculate hash with password and copy into bcc_ptr. | 667 | /* Calculate hash with password and copy into bcc_ptr. |
679 | * Encryption Key (stored as in cryptkey) gets used if the | 668 | * Encryption Key (stored as in cryptkey) gets used if the |
@@ -686,8 +675,8 @@ ssetup_ntlmssp_authenticate: | |||
686 | true : false, lnm_session_key); | 675 | true : false, lnm_session_key); |
687 | 676 | ||
688 | ses->flags |= CIFS_SES_LANMAN; | 677 | ses->flags |= CIFS_SES_LANMAN; |
689 | memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_SESS_KEY_SIZE); | 678 | memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_AUTH_RESP_SIZE); |
690 | bcc_ptr += CIFS_SESS_KEY_SIZE; | 679 | bcc_ptr += CIFS_AUTH_RESP_SIZE; |
691 | 680 | ||
692 | /* can not sign if LANMAN negotiated so no need | 681 | /* can not sign if LANMAN negotiated so no need |
693 | to calculate signing key? but what if server | 682 | to calculate signing key? but what if server |
@@ -814,71 +803,70 @@ ssetup_ntlmssp_authenticate: | |||
814 | rc = -ENOSYS; | 803 | rc = -ENOSYS; |
815 | goto ssetup_exit; | 804 | goto ssetup_exit; |
816 | #endif /* CONFIG_CIFS_UPCALL */ | 805 | #endif /* CONFIG_CIFS_UPCALL */ |
817 | } else { | 806 | } else if (type == RawNTLMSSP) { |
818 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 807 | if ((pSMB->req.hdr.Flags2 & SMBFLG2_UNICODE) == 0) { |
819 | if (type == RawNTLMSSP) { | 808 | cERROR(1, "NTLMSSP requires Unicode support"); |
820 | if ((pSMB->req.hdr.Flags2 & SMBFLG2_UNICODE) == 0) { | 809 | rc = -ENOSYS; |
821 | cERROR(1, "NTLMSSP requires Unicode support"); | 810 | goto ssetup_exit; |
822 | rc = -ENOSYS; | 811 | } |
812 | |||
813 | cFYI(1, "ntlmssp session setup phase %d", phase); | ||
814 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; | ||
815 | capabilities |= CAP_EXTENDED_SECURITY; | ||
816 | pSMB->req.Capabilities |= cpu_to_le32(capabilities); | ||
817 | switch(phase) { | ||
818 | case NtLmNegotiate: | ||
819 | build_ntlmssp_negotiate_blob( | ||
820 | pSMB->req.SecurityBlob, ses); | ||
821 | iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE); | ||
822 | iov[1].iov_base = pSMB->req.SecurityBlob; | ||
823 | pSMB->req.SecurityBlobLength = | ||
824 | cpu_to_le16(sizeof(NEGOTIATE_MESSAGE)); | ||
825 | break; | ||
826 | case NtLmAuthenticate: | ||
827 | /* | ||
828 | * 5 is an empirical value, large enough to hold | ||
829 | * authenticate message plus max 10 of av paris, | ||
830 | * domain, user, workstation names, flags, etc. | ||
831 | */ | ||
832 | ntlmsspblob = kzalloc( | ||
833 | 5*sizeof(struct _AUTHENTICATE_MESSAGE), | ||
834 | GFP_KERNEL); | ||
835 | if (!ntlmsspblob) { | ||
836 | cERROR(1, "Can't allocate NTLMSSP blob"); | ||
837 | rc = -ENOMEM; | ||
823 | goto ssetup_exit; | 838 | goto ssetup_exit; |
824 | } | 839 | } |
825 | 840 | ||
826 | cFYI(1, "ntlmssp session setup phase %d", phase); | 841 | rc = build_ntlmssp_auth_blob(ntlmsspblob, |
827 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; | 842 | &blob_len, ses, nls_cp); |
828 | capabilities |= CAP_EXTENDED_SECURITY; | 843 | if (rc) |
829 | pSMB->req.Capabilities |= cpu_to_le32(capabilities); | ||
830 | if (phase == NtLmNegotiate) { | ||
831 | setup_ntlmssp_neg_req(pSMB, ses); | ||
832 | iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE); | ||
833 | iov[1].iov_base = &pSMB->req.SecurityBlob[0]; | ||
834 | } else if (phase == NtLmAuthenticate) { | ||
835 | /* 5 is an empirical value, large enought to | ||
836 | * hold authenticate message, max 10 of | ||
837 | * av paris, doamin,user,workstation mames, | ||
838 | * flags etc.. | ||
839 | */ | ||
840 | ntlmsspblob = kmalloc( | ||
841 | 5*sizeof(struct _AUTHENTICATE_MESSAGE), | ||
842 | GFP_KERNEL); | ||
843 | if (!ntlmsspblob) { | ||
844 | cERROR(1, "Can't allocate NTLMSSP"); | ||
845 | rc = -ENOMEM; | ||
846 | goto ssetup_exit; | ||
847 | } | ||
848 | |||
849 | rc = build_ntlmssp_auth_blob(ntlmsspblob, | ||
850 | &blob_len, ses, nls_cp); | ||
851 | if (rc) | ||
852 | goto ssetup_exit; | ||
853 | iov[1].iov_len = blob_len; | ||
854 | iov[1].iov_base = ntlmsspblob; | ||
855 | pSMB->req.SecurityBlobLength = | ||
856 | cpu_to_le16(blob_len); | ||
857 | /* Make sure that we tell the server that we | ||
858 | are using the uid that it just gave us back | ||
859 | on the response (challenge) */ | ||
860 | smb_buf->Uid = ses->Suid; | ||
861 | } else { | ||
862 | cERROR(1, "invalid phase %d", phase); | ||
863 | rc = -ENOSYS; | ||
864 | goto ssetup_exit; | 844 | goto ssetup_exit; |
865 | } | 845 | iov[1].iov_len = blob_len; |
866 | /* unicode strings must be word aligned */ | 846 | iov[1].iov_base = ntlmsspblob; |
867 | if ((iov[0].iov_len + iov[1].iov_len) % 2) { | 847 | pSMB->req.SecurityBlobLength = cpu_to_le16(blob_len); |
868 | *bcc_ptr = 0; | 848 | /* |
869 | bcc_ptr++; | 849 | * Make sure that we tell the server that we are using |
870 | } | 850 | * the uid that it just gave us back on the response |
871 | unicode_oslm_strings(&bcc_ptr, nls_cp); | 851 | * (challenge) |
872 | } else { | 852 | */ |
873 | cERROR(1, "secType %d not supported!", type); | 853 | smb_buf->Uid = ses->Suid; |
854 | break; | ||
855 | default: | ||
856 | cERROR(1, "invalid phase %d", phase); | ||
874 | rc = -ENOSYS; | 857 | rc = -ENOSYS; |
875 | goto ssetup_exit; | 858 | goto ssetup_exit; |
876 | } | 859 | } |
877 | #else | 860 | /* unicode strings must be word aligned */ |
861 | if ((iov[0].iov_len + iov[1].iov_len) % 2) { | ||
862 | *bcc_ptr = 0; | ||
863 | bcc_ptr++; | ||
864 | } | ||
865 | unicode_oslm_strings(&bcc_ptr, nls_cp); | ||
866 | } else { | ||
878 | cERROR(1, "secType %d not supported!", type); | 867 | cERROR(1, "secType %d not supported!", type); |
879 | rc = -ENOSYS; | 868 | rc = -ENOSYS; |
880 | goto ssetup_exit; | 869 | goto ssetup_exit; |
881 | #endif | ||
882 | } | 870 | } |
883 | 871 | ||
884 | iov[2].iov_base = str_area; | 872 | iov[2].iov_base = str_area; |
@@ -887,10 +875,10 @@ ssetup_ntlmssp_authenticate: | |||
887 | count = iov[1].iov_len + iov[2].iov_len; | 875 | count = iov[1].iov_len + iov[2].iov_len; |
888 | smb_buf->smb_buf_length += count; | 876 | smb_buf->smb_buf_length += count; |
889 | 877 | ||
890 | BCC_LE(smb_buf) = cpu_to_le16(count); | 878 | put_bcc_le(count, smb_buf); |
891 | 879 | ||
892 | rc = SendReceive2(xid, ses, iov, 3 /* num_iovecs */, &resp_buf_type, | 880 | rc = SendReceive2(xid, ses, iov, 3 /* num_iovecs */, &resp_buf_type, |
893 | CIFS_STD_OP /* not long */ | CIFS_LOG_ERROR); | 881 | CIFS_LOG_ERROR); |
894 | /* SMB request buf freed in SendReceive2 */ | 882 | /* SMB request buf freed in SendReceive2 */ |
895 | 883 | ||
896 | pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base; | 884 | pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base; |
@@ -921,7 +909,7 @@ ssetup_ntlmssp_authenticate: | |||
921 | cFYI(1, "UID = %d ", ses->Suid); | 909 | cFYI(1, "UID = %d ", ses->Suid); |
922 | /* response can have either 3 or 4 word count - Samba sends 3 */ | 910 | /* response can have either 3 or 4 word count - Samba sends 3 */ |
923 | /* and lanman response is 3 */ | 911 | /* and lanman response is 3 */ |
924 | bytes_remaining = BCC(smb_buf); | 912 | bytes_remaining = get_bcc(smb_buf); |
925 | bcc_ptr = pByteArea(smb_buf); | 913 | bcc_ptr = pByteArea(smb_buf); |
926 | 914 | ||
927 | if (smb_buf->WordCount == 4) { | 915 | if (smb_buf->WordCount == 4) { |
diff --git a/fs/cifs/smbdes.c b/fs/cifs/smbdes.c index b6b6dcb500bf..04721485925d 100644 --- a/fs/cifs/smbdes.c +++ b/fs/cifs/smbdes.c | |||
@@ -45,7 +45,6 @@ | |||
45 | up with a different answer to the one above) | 45 | up with a different answer to the one above) |
46 | */ | 46 | */ |
47 | #include <linux/slab.h> | 47 | #include <linux/slab.h> |
48 | #include "cifsencrypt.h" | ||
49 | #define uchar unsigned char | 48 | #define uchar unsigned char |
50 | 49 | ||
51 | static uchar perm1[56] = { 57, 49, 41, 33, 25, 17, 9, | 50 | static uchar perm1[56] = { 57, 49, 41, 33, 25, 17, 9, |
diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c index 192ea51af20f..b5041c849981 100644 --- a/fs/cifs/smbencrypt.c +++ b/fs/cifs/smbencrypt.c | |||
@@ -32,9 +32,8 @@ | |||
32 | #include "cifs_unicode.h" | 32 | #include "cifs_unicode.h" |
33 | #include "cifspdu.h" | 33 | #include "cifspdu.h" |
34 | #include "cifsglob.h" | 34 | #include "cifsglob.h" |
35 | #include "md5.h" | ||
36 | #include "cifs_debug.h" | 35 | #include "cifs_debug.h" |
37 | #include "cifsencrypt.h" | 36 | #include "cifsproto.h" |
38 | 37 | ||
39 | #ifndef false | 38 | #ifndef false |
40 | #define false 0 | 39 | #define false 0 |
@@ -48,14 +47,58 @@ | |||
48 | #define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8) | 47 | #define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8) |
49 | #define SSVAL(buf,pos,val) SSVALX((buf),(pos),((__u16)(val))) | 48 | #define SSVAL(buf,pos,val) SSVALX((buf),(pos),((__u16)(val))) |
50 | 49 | ||
51 | /*The following definitions come from libsmb/smbencrypt.c */ | 50 | /* produce a md4 message digest from data of length n bytes */ |
51 | int | ||
52 | mdfour(unsigned char *md4_hash, unsigned char *link_str, int link_len) | ||
53 | { | ||
54 | int rc; | ||
55 | unsigned int size; | ||
56 | struct crypto_shash *md4; | ||
57 | struct sdesc *sdescmd4; | ||
58 | |||
59 | md4 = crypto_alloc_shash("md4", 0, 0); | ||
60 | if (IS_ERR(md4)) { | ||
61 | rc = PTR_ERR(md4); | ||
62 | cERROR(1, "%s: Crypto md4 allocation error %d\n", __func__, rc); | ||
63 | return rc; | ||
64 | } | ||
65 | size = sizeof(struct shash_desc) + crypto_shash_descsize(md4); | ||
66 | sdescmd4 = kmalloc(size, GFP_KERNEL); | ||
67 | if (!sdescmd4) { | ||
68 | rc = -ENOMEM; | ||
69 | cERROR(1, "%s: Memory allocation failure\n", __func__); | ||
70 | goto mdfour_err; | ||
71 | } | ||
72 | sdescmd4->shash.tfm = md4; | ||
73 | sdescmd4->shash.flags = 0x0; | ||
74 | |||
75 | rc = crypto_shash_init(&sdescmd4->shash); | ||
76 | if (rc) { | ||
77 | cERROR(1, "%s: Could not init md4 shash\n", __func__); | ||
78 | goto mdfour_err; | ||
79 | } | ||
80 | crypto_shash_update(&sdescmd4->shash, link_str, link_len); | ||
81 | rc = crypto_shash_final(&sdescmd4->shash, md4_hash); | ||
52 | 82 | ||
53 | void SMBencrypt(unsigned char *passwd, const unsigned char *c8, | 83 | mdfour_err: |
54 | unsigned char *p24); | 84 | crypto_free_shash(md4); |
55 | void E_md4hash(const unsigned char *passwd, unsigned char *p16); | 85 | kfree(sdescmd4); |
56 | static void SMBOWFencrypt(unsigned char passwd[16], const unsigned char *c8, | 86 | |
57 | unsigned char p24[24]); | 87 | return rc; |
58 | void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24); | 88 | } |
89 | |||
90 | /* Does the des encryption from the NT or LM MD4 hash. */ | ||
91 | static void | ||
92 | SMBOWFencrypt(unsigned char passwd[16], const unsigned char *c8, | ||
93 | unsigned char p24[24]) | ||
94 | { | ||
95 | unsigned char p21[21]; | ||
96 | |||
97 | memset(p21, '\0', 21); | ||
98 | |||
99 | memcpy(p21, passwd, 16); | ||
100 | E_P24(p21, c8, p24); | ||
101 | } | ||
59 | 102 | ||
60 | /* | 103 | /* |
61 | This implements the X/Open SMB password encryption | 104 | This implements the X/Open SMB password encryption |
@@ -118,9 +161,10 @@ _my_mbstowcs(__u16 *dst, const unsigned char *src, int len) | |||
118 | * Creates the MD4 Hash of the users password in NT UNICODE. | 161 | * Creates the MD4 Hash of the users password in NT UNICODE. |
119 | */ | 162 | */ |
120 | 163 | ||
121 | void | 164 | int |
122 | E_md4hash(const unsigned char *passwd, unsigned char *p16) | 165 | E_md4hash(const unsigned char *passwd, unsigned char *p16) |
123 | { | 166 | { |
167 | int rc; | ||
124 | int len; | 168 | int len; |
125 | __u16 wpwd[129]; | 169 | __u16 wpwd[129]; |
126 | 170 | ||
@@ -139,8 +183,10 @@ E_md4hash(const unsigned char *passwd, unsigned char *p16) | |||
139 | /* Calculate length in bytes */ | 183 | /* Calculate length in bytes */ |
140 | len = _my_wcslen(wpwd) * sizeof(__u16); | 184 | len = _my_wcslen(wpwd) * sizeof(__u16); |
141 | 185 | ||
142 | mdfour(p16, (unsigned char *) wpwd, len); | 186 | rc = mdfour(p16, (unsigned char *) wpwd, len); |
143 | memset(wpwd, 0, 129 * 2); | 187 | memset(wpwd, 0, 129 * 2); |
188 | |||
189 | return rc; | ||
144 | } | 190 | } |
145 | 191 | ||
146 | #if 0 /* currently unused */ | 192 | #if 0 /* currently unused */ |
@@ -212,19 +258,6 @@ ntv2_owf_gen(const unsigned char owf[16], const char *user_n, | |||
212 | } | 258 | } |
213 | #endif | 259 | #endif |
214 | 260 | ||
215 | /* Does the des encryption from the NT or LM MD4 hash. */ | ||
216 | static void | ||
217 | SMBOWFencrypt(unsigned char passwd[16], const unsigned char *c8, | ||
218 | unsigned char p24[24]) | ||
219 | { | ||
220 | unsigned char p21[21]; | ||
221 | |||
222 | memset(p21, '\0', 21); | ||
223 | |||
224 | memcpy(p21, passwd, 16); | ||
225 | E_P24(p21, c8, p24); | ||
226 | } | ||
227 | |||
228 | /* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */ | 261 | /* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */ |
229 | #if 0 /* currently unused */ | 262 | #if 0 /* currently unused */ |
230 | static void | 263 | static void |
@@ -242,16 +275,21 @@ NTLMSSPOWFencrypt(unsigned char passwd[8], | |||
242 | #endif | 275 | #endif |
243 | 276 | ||
244 | /* Does the NT MD4 hash then des encryption. */ | 277 | /* Does the NT MD4 hash then des encryption. */ |
245 | 278 | int | |
246 | void | ||
247 | SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24) | 279 | SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24) |
248 | { | 280 | { |
281 | int rc; | ||
249 | unsigned char p21[21]; | 282 | unsigned char p21[21]; |
250 | 283 | ||
251 | memset(p21, '\0', 21); | 284 | memset(p21, '\0', 21); |
252 | 285 | ||
253 | E_md4hash(passwd, p21); | 286 | rc = E_md4hash(passwd, p21); |
287 | if (rc) { | ||
288 | cFYI(1, "%s Can't generate NT hash, error: %d", __func__, rc); | ||
289 | return rc; | ||
290 | } | ||
254 | SMBOWFencrypt(p21, c8, p24); | 291 | SMBOWFencrypt(p21, c8, p24); |
292 | return rc; | ||
255 | } | 293 | } |
256 | 294 | ||
257 | 295 | ||
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index e0588cdf4cc5..46d8756f2b24 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
@@ -36,7 +36,13 @@ | |||
36 | 36 | ||
37 | extern mempool_t *cifs_mid_poolp; | 37 | extern mempool_t *cifs_mid_poolp; |
38 | 38 | ||
39 | static struct mid_q_entry * | 39 | static void |
40 | wake_up_task(struct mid_q_entry *mid) | ||
41 | { | ||
42 | wake_up_process(mid->callback_data); | ||
43 | } | ||
44 | |||
45 | struct mid_q_entry * | ||
40 | AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server) | 46 | AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server) |
41 | { | 47 | { |
42 | struct mid_q_entry *temp; | 48 | struct mid_q_entry *temp; |
@@ -58,28 +64,28 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server) | |||
58 | /* do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */ | 64 | /* do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */ |
59 | /* when mid allocated can be before when sent */ | 65 | /* when mid allocated can be before when sent */ |
60 | temp->when_alloc = jiffies; | 66 | temp->when_alloc = jiffies; |
61 | temp->tsk = current; | 67 | |
68 | /* | ||
69 | * The default is for the mid to be synchronous, so the | ||
70 | * default callback just wakes up the current task. | ||
71 | */ | ||
72 | temp->callback = wake_up_task; | ||
73 | temp->callback_data = current; | ||
62 | } | 74 | } |
63 | 75 | ||
64 | spin_lock(&GlobalMid_Lock); | ||
65 | list_add_tail(&temp->qhead, &server->pending_mid_q); | ||
66 | atomic_inc(&midCount); | 76 | atomic_inc(&midCount); |
67 | temp->midState = MID_REQUEST_ALLOCATED; | 77 | temp->midState = MID_REQUEST_ALLOCATED; |
68 | spin_unlock(&GlobalMid_Lock); | ||
69 | return temp; | 78 | return temp; |
70 | } | 79 | } |
71 | 80 | ||
72 | static void | 81 | void |
73 | DeleteMidQEntry(struct mid_q_entry *midEntry) | 82 | DeleteMidQEntry(struct mid_q_entry *midEntry) |
74 | { | 83 | { |
75 | #ifdef CONFIG_CIFS_STATS2 | 84 | #ifdef CONFIG_CIFS_STATS2 |
76 | unsigned long now; | 85 | unsigned long now; |
77 | #endif | 86 | #endif |
78 | spin_lock(&GlobalMid_Lock); | ||
79 | midEntry->midState = MID_FREE; | 87 | midEntry->midState = MID_FREE; |
80 | list_del(&midEntry->qhead); | ||
81 | atomic_dec(&midCount); | 88 | atomic_dec(&midCount); |
82 | spin_unlock(&GlobalMid_Lock); | ||
83 | if (midEntry->largeBuf) | 89 | if (midEntry->largeBuf) |
84 | cifs_buf_release(midEntry->resp_buf); | 90 | cifs_buf_release(midEntry->resp_buf); |
85 | else | 91 | else |
@@ -103,6 +109,16 @@ DeleteMidQEntry(struct mid_q_entry *midEntry) | |||
103 | mempool_free(midEntry, cifs_mid_poolp); | 109 | mempool_free(midEntry, cifs_mid_poolp); |
104 | } | 110 | } |
105 | 111 | ||
112 | static void | ||
113 | delete_mid(struct mid_q_entry *mid) | ||
114 | { | ||
115 | spin_lock(&GlobalMid_Lock); | ||
116 | list_del(&mid->qhead); | ||
117 | spin_unlock(&GlobalMid_Lock); | ||
118 | |||
119 | DeleteMidQEntry(mid); | ||
120 | } | ||
121 | |||
106 | static int | 122 | static int |
107 | smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec) | 123 | smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec) |
108 | { | 124 | { |
@@ -119,7 +135,7 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec) | |||
119 | if (ssocket == NULL) | 135 | if (ssocket == NULL) |
120 | return -ENOTSOCK; /* BB eventually add reconnect code here */ | 136 | return -ENOTSOCK; /* BB eventually add reconnect code here */ |
121 | 137 | ||
122 | smb_msg.msg_name = (struct sockaddr *) &server->addr.sockAddr; | 138 | smb_msg.msg_name = (struct sockaddr *) &server->dstaddr; |
123 | smb_msg.msg_namelen = sizeof(struct sockaddr); | 139 | smb_msg.msg_namelen = sizeof(struct sockaddr); |
124 | smb_msg.msg_control = NULL; | 140 | smb_msg.msg_control = NULL; |
125 | smb_msg.msg_controllen = 0; | 141 | smb_msg.msg_controllen = 0; |
@@ -220,9 +236,9 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec) | |||
220 | server->tcpStatus = CifsNeedReconnect; | 236 | server->tcpStatus = CifsNeedReconnect; |
221 | } | 237 | } |
222 | 238 | ||
223 | if (rc < 0) { | 239 | if (rc < 0 && rc != -EINTR) |
224 | cERROR(1, "Error %d sending data on socket to server", rc); | 240 | cERROR(1, "Error %d sending data on socket to server", rc); |
225 | } else | 241 | else |
226 | rc = 0; | 242 | rc = 0; |
227 | 243 | ||
228 | /* Don't want to modify the buffer as a | 244 | /* Don't want to modify the buffer as a |
@@ -244,31 +260,31 @@ smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer, | |||
244 | return smb_sendv(server, &iov, 1); | 260 | return smb_sendv(server, &iov, 1); |
245 | } | 261 | } |
246 | 262 | ||
247 | static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op) | 263 | static int wait_for_free_request(struct TCP_Server_Info *server, |
264 | const int long_op) | ||
248 | { | 265 | { |
249 | if (long_op == CIFS_ASYNC_OP) { | 266 | if (long_op == CIFS_ASYNC_OP) { |
250 | /* oplock breaks must not be held up */ | 267 | /* oplock breaks must not be held up */ |
251 | atomic_inc(&ses->server->inFlight); | 268 | atomic_inc(&server->inFlight); |
252 | return 0; | 269 | return 0; |
253 | } | 270 | } |
254 | 271 | ||
255 | spin_lock(&GlobalMid_Lock); | 272 | spin_lock(&GlobalMid_Lock); |
256 | while (1) { | 273 | while (1) { |
257 | if (atomic_read(&ses->server->inFlight) >= | 274 | if (atomic_read(&server->inFlight) >= cifs_max_pending) { |
258 | cifs_max_pending){ | ||
259 | spin_unlock(&GlobalMid_Lock); | 275 | spin_unlock(&GlobalMid_Lock); |
260 | #ifdef CONFIG_CIFS_STATS2 | 276 | #ifdef CONFIG_CIFS_STATS2 |
261 | atomic_inc(&ses->server->num_waiters); | 277 | atomic_inc(&server->num_waiters); |
262 | #endif | 278 | #endif |
263 | wait_event(ses->server->request_q, | 279 | wait_event(server->request_q, |
264 | atomic_read(&ses->server->inFlight) | 280 | atomic_read(&server->inFlight) |
265 | < cifs_max_pending); | 281 | < cifs_max_pending); |
266 | #ifdef CONFIG_CIFS_STATS2 | 282 | #ifdef CONFIG_CIFS_STATS2 |
267 | atomic_dec(&ses->server->num_waiters); | 283 | atomic_dec(&server->num_waiters); |
268 | #endif | 284 | #endif |
269 | spin_lock(&GlobalMid_Lock); | 285 | spin_lock(&GlobalMid_Lock); |
270 | } else { | 286 | } else { |
271 | if (ses->server->tcpStatus == CifsExiting) { | 287 | if (server->tcpStatus == CifsExiting) { |
272 | spin_unlock(&GlobalMid_Lock); | 288 | spin_unlock(&GlobalMid_Lock); |
273 | return -ENOENT; | 289 | return -ENOENT; |
274 | } | 290 | } |
@@ -278,7 +294,7 @@ static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op) | |||
278 | 294 | ||
279 | /* update # of requests on the wire to server */ | 295 | /* update # of requests on the wire to server */ |
280 | if (long_op != CIFS_BLOCKING_OP) | 296 | if (long_op != CIFS_BLOCKING_OP) |
281 | atomic_inc(&ses->server->inFlight); | 297 | atomic_inc(&server->inFlight); |
282 | spin_unlock(&GlobalMid_Lock); | 298 | spin_unlock(&GlobalMid_Lock); |
283 | break; | 299 | break; |
284 | } | 300 | } |
@@ -308,53 +324,85 @@ static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf, | |||
308 | *ppmidQ = AllocMidQEntry(in_buf, ses->server); | 324 | *ppmidQ = AllocMidQEntry(in_buf, ses->server); |
309 | if (*ppmidQ == NULL) | 325 | if (*ppmidQ == NULL) |
310 | return -ENOMEM; | 326 | return -ENOMEM; |
327 | spin_lock(&GlobalMid_Lock); | ||
328 | list_add_tail(&(*ppmidQ)->qhead, &ses->server->pending_mid_q); | ||
329 | spin_unlock(&GlobalMid_Lock); | ||
311 | return 0; | 330 | return 0; |
312 | } | 331 | } |
313 | 332 | ||
314 | static int wait_for_response(struct cifsSesInfo *ses, | 333 | static int |
315 | struct mid_q_entry *midQ, | 334 | wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ) |
316 | unsigned long timeout, | ||
317 | unsigned long time_to_wait) | ||
318 | { | 335 | { |
319 | unsigned long curr_timeout; | 336 | int error; |
320 | 337 | ||
321 | for (;;) { | 338 | error = wait_event_killable(server->response_q, |
322 | curr_timeout = timeout + jiffies; | 339 | midQ->midState != MID_REQUEST_SUBMITTED); |
323 | wait_event_timeout(ses->server->response_q, | 340 | if (error < 0) |
324 | midQ->midState != MID_REQUEST_SUBMITTED, timeout); | 341 | return -ERESTARTSYS; |
325 | 342 | ||
326 | if (time_after(jiffies, curr_timeout) && | 343 | return 0; |
327 | (midQ->midState == MID_REQUEST_SUBMITTED) && | 344 | } |
328 | ((ses->server->tcpStatus == CifsGood) || | ||
329 | (ses->server->tcpStatus == CifsNew))) { | ||
330 | 345 | ||
331 | unsigned long lrt; | ||
332 | 346 | ||
333 | /* We timed out. Is the server still | 347 | /* |
334 | sending replies ? */ | 348 | * Send a SMB request and set the callback function in the mid to handle |
335 | spin_lock(&GlobalMid_Lock); | 349 | * the result. Caller is responsible for dealing with timeouts. |
336 | lrt = ses->server->lstrp; | 350 | */ |
337 | spin_unlock(&GlobalMid_Lock); | 351 | int |
352 | cifs_call_async(struct TCP_Server_Info *server, struct smb_hdr *in_buf, | ||
353 | mid_callback_t *callback, void *cbdata) | ||
354 | { | ||
355 | int rc; | ||
356 | struct mid_q_entry *mid; | ||
338 | 357 | ||
339 | /* Calculate time_to_wait past last receive time. | 358 | rc = wait_for_free_request(server, CIFS_ASYNC_OP); |
340 | Although we prefer not to time out if the | 359 | if (rc) |
341 | server is still responding - we will time | 360 | return rc; |
342 | out if the server takes more than 15 (or 45 | 361 | |
343 | or 180) seconds to respond to this request | 362 | /* enable signing if server requires it */ |
344 | and has not responded to any request from | 363 | if (server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) |
345 | other threads on the client within 10 seconds */ | 364 | in_buf->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; |
346 | lrt += time_to_wait; | 365 | |
347 | if (time_after(jiffies, lrt)) { | 366 | mutex_lock(&server->srv_mutex); |
348 | /* No replies for time_to_wait. */ | 367 | mid = AllocMidQEntry(in_buf, server); |
349 | cERROR(1, "server not responding"); | 368 | if (mid == NULL) { |
350 | return -1; | 369 | mutex_unlock(&server->srv_mutex); |
351 | } | 370 | return -ENOMEM; |
352 | } else { | ||
353 | return 0; | ||
354 | } | ||
355 | } | 371 | } |
356 | } | ||
357 | 372 | ||
373 | /* put it on the pending_mid_q */ | ||
374 | spin_lock(&GlobalMid_Lock); | ||
375 | list_add_tail(&mid->qhead, &server->pending_mid_q); | ||
376 | spin_unlock(&GlobalMid_Lock); | ||
377 | |||
378 | rc = cifs_sign_smb(in_buf, server, &mid->sequence_number); | ||
379 | if (rc) { | ||
380 | mutex_unlock(&server->srv_mutex); | ||
381 | goto out_err; | ||
382 | } | ||
383 | |||
384 | mid->callback = callback; | ||
385 | mid->callback_data = cbdata; | ||
386 | mid->midState = MID_REQUEST_SUBMITTED; | ||
387 | #ifdef CONFIG_CIFS_STATS2 | ||
388 | atomic_inc(&server->inSend); | ||
389 | #endif | ||
390 | rc = smb_send(server, in_buf, in_buf->smb_buf_length); | ||
391 | #ifdef CONFIG_CIFS_STATS2 | ||
392 | atomic_dec(&server->inSend); | ||
393 | mid->when_sent = jiffies; | ||
394 | #endif | ||
395 | mutex_unlock(&server->srv_mutex); | ||
396 | if (rc) | ||
397 | goto out_err; | ||
398 | |||
399 | return rc; | ||
400 | out_err: | ||
401 | delete_mid(mid); | ||
402 | atomic_dec(&server->inFlight); | ||
403 | wake_up(&server->request_q); | ||
404 | return rc; | ||
405 | } | ||
358 | 406 | ||
359 | /* | 407 | /* |
360 | * | 408 | * |
@@ -382,6 +430,84 @@ SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses, | |||
382 | return rc; | 430 | return rc; |
383 | } | 431 | } |
384 | 432 | ||
433 | static int | ||
434 | sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server) | ||
435 | { | ||
436 | int rc = 0; | ||
437 | |||
438 | cFYI(1, "%s: cmd=%d mid=%d state=%d", __func__, mid->command, | ||
439 | mid->mid, mid->midState); | ||
440 | |||
441 | spin_lock(&GlobalMid_Lock); | ||
442 | /* ensure that it's no longer on the pending_mid_q */ | ||
443 | list_del_init(&mid->qhead); | ||
444 | |||
445 | switch (mid->midState) { | ||
446 | case MID_RESPONSE_RECEIVED: | ||
447 | spin_unlock(&GlobalMid_Lock); | ||
448 | return rc; | ||
449 | case MID_REQUEST_SUBMITTED: | ||
450 | /* socket is going down, reject all calls */ | ||
451 | if (server->tcpStatus == CifsExiting) { | ||
452 | cERROR(1, "%s: canceling mid=%d cmd=0x%x state=%d", | ||
453 | __func__, mid->mid, mid->command, mid->midState); | ||
454 | rc = -EHOSTDOWN; | ||
455 | break; | ||
456 | } | ||
457 | case MID_RETRY_NEEDED: | ||
458 | rc = -EAGAIN; | ||
459 | break; | ||
460 | case MID_RESPONSE_MALFORMED: | ||
461 | rc = -EIO; | ||
462 | break; | ||
463 | default: | ||
464 | cERROR(1, "%s: invalid mid state mid=%d state=%d", __func__, | ||
465 | mid->mid, mid->midState); | ||
466 | rc = -EIO; | ||
467 | } | ||
468 | spin_unlock(&GlobalMid_Lock); | ||
469 | |||
470 | DeleteMidQEntry(mid); | ||
471 | return rc; | ||
472 | } | ||
473 | |||
474 | /* | ||
475 | * An NT cancel request header looks just like the original request except: | ||
476 | * | ||
477 | * The Command is SMB_COM_NT_CANCEL | ||
478 | * The WordCount is zeroed out | ||
479 | * The ByteCount is zeroed out | ||
480 | * | ||
481 | * This function mangles an existing request buffer into a | ||
482 | * SMB_COM_NT_CANCEL request and then sends it. | ||
483 | */ | ||
484 | static int | ||
485 | send_nt_cancel(struct TCP_Server_Info *server, struct smb_hdr *in_buf, | ||
486 | struct mid_q_entry *mid) | ||
487 | { | ||
488 | int rc = 0; | ||
489 | |||
490 | /* -4 for RFC1001 length and +2 for BCC field */ | ||
491 | in_buf->smb_buf_length = sizeof(struct smb_hdr) - 4 + 2; | ||
492 | in_buf->Command = SMB_COM_NT_CANCEL; | ||
493 | in_buf->WordCount = 0; | ||
494 | put_bcc_le(0, in_buf); | ||
495 | |||
496 | mutex_lock(&server->srv_mutex); | ||
497 | rc = cifs_sign_smb(in_buf, server, &mid->sequence_number); | ||
498 | if (rc) { | ||
499 | mutex_unlock(&server->srv_mutex); | ||
500 | return rc; | ||
501 | } | ||
502 | rc = smb_send(server, in_buf, in_buf->smb_buf_length); | ||
503 | mutex_unlock(&server->srv_mutex); | ||
504 | |||
505 | cFYI(1, "issued NT_CANCEL for mid %u, rc = %d", | ||
506 | in_buf->Mid, rc); | ||
507 | |||
508 | return rc; | ||
509 | } | ||
510 | |||
385 | int | 511 | int |
386 | SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, | 512 | SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, |
387 | struct kvec *iov, int n_vec, int *pRespBufType /* ret */, | 513 | struct kvec *iov, int n_vec, int *pRespBufType /* ret */, |
@@ -390,7 +516,6 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, | |||
390 | int rc = 0; | 516 | int rc = 0; |
391 | int long_op; | 517 | int long_op; |
392 | unsigned int receive_len; | 518 | unsigned int receive_len; |
393 | unsigned long timeout; | ||
394 | struct mid_q_entry *midQ; | 519 | struct mid_q_entry *midQ; |
395 | struct smb_hdr *in_buf = iov[0].iov_base; | 520 | struct smb_hdr *in_buf = iov[0].iov_base; |
396 | 521 | ||
@@ -413,7 +538,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, | |||
413 | to the same server. We may make this configurable later or | 538 | to the same server. We may make this configurable later or |
414 | use ses->maxReq */ | 539 | use ses->maxReq */ |
415 | 540 | ||
416 | rc = wait_for_free_request(ses, long_op); | 541 | rc = wait_for_free_request(ses->server, long_op); |
417 | if (rc) { | 542 | if (rc) { |
418 | cifs_small_buf_release(in_buf); | 543 | cifs_small_buf_release(in_buf); |
419 | return rc; | 544 | return rc; |
@@ -452,70 +577,41 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, | |||
452 | #endif | 577 | #endif |
453 | 578 | ||
454 | mutex_unlock(&ses->server->srv_mutex); | 579 | mutex_unlock(&ses->server->srv_mutex); |
455 | cifs_small_buf_release(in_buf); | ||
456 | 580 | ||
457 | if (rc < 0) | 581 | if (rc < 0) { |
458 | goto out; | 582 | cifs_small_buf_release(in_buf); |
459 | |||
460 | if (long_op == CIFS_STD_OP) | ||
461 | timeout = 15 * HZ; | ||
462 | else if (long_op == CIFS_VLONG_OP) /* e.g. slow writes past EOF */ | ||
463 | timeout = 180 * HZ; | ||
464 | else if (long_op == CIFS_LONG_OP) | ||
465 | timeout = 45 * HZ; /* should be greater than | ||
466 | servers oplock break timeout (about 43 seconds) */ | ||
467 | else if (long_op == CIFS_ASYNC_OP) | ||
468 | goto out; | ||
469 | else if (long_op == CIFS_BLOCKING_OP) | ||
470 | timeout = 0x7FFFFFFF; /* large, but not so large as to wrap */ | ||
471 | else { | ||
472 | cERROR(1, "unknown timeout flag %d", long_op); | ||
473 | rc = -EIO; | ||
474 | goto out; | 583 | goto out; |
475 | } | 584 | } |
476 | 585 | ||
477 | /* wait for 15 seconds or until woken up due to response arriving or | 586 | if (long_op == CIFS_ASYNC_OP) { |
478 | due to last connection to this server being unmounted */ | 587 | cifs_small_buf_release(in_buf); |
479 | if (signal_pending(current)) { | 588 | goto out; |
480 | /* if signal pending do not hold up user for full smb timeout | ||
481 | but we still give response a chance to complete */ | ||
482 | timeout = 2 * HZ; | ||
483 | } | 589 | } |
484 | 590 | ||
485 | /* No user interrupts in wait - wreaks havoc with performance */ | 591 | rc = wait_for_response(ses->server, midQ); |
486 | wait_for_response(ses, midQ, timeout, 10 * HZ); | 592 | if (rc != 0) { |
487 | 593 | send_nt_cancel(ses->server, in_buf, midQ); | |
488 | spin_lock(&GlobalMid_Lock); | 594 | spin_lock(&GlobalMid_Lock); |
489 | |||
490 | if (midQ->resp_buf == NULL) { | ||
491 | cERROR(1, "No response to cmd %d mid %d", | ||
492 | midQ->command, midQ->mid); | ||
493 | if (midQ->midState == MID_REQUEST_SUBMITTED) { | 595 | if (midQ->midState == MID_REQUEST_SUBMITTED) { |
494 | if (ses->server->tcpStatus == CifsExiting) | 596 | midQ->callback = DeleteMidQEntry; |
495 | rc = -EHOSTDOWN; | 597 | spin_unlock(&GlobalMid_Lock); |
496 | else { | 598 | cifs_small_buf_release(in_buf); |
497 | ses->server->tcpStatus = CifsNeedReconnect; | 599 | atomic_dec(&ses->server->inFlight); |
498 | midQ->midState = MID_RETRY_NEEDED; | 600 | wake_up(&ses->server->request_q); |
499 | } | 601 | return rc; |
500 | } | ||
501 | |||
502 | if (rc != -EHOSTDOWN) { | ||
503 | if (midQ->midState == MID_RETRY_NEEDED) { | ||
504 | rc = -EAGAIN; | ||
505 | cFYI(1, "marking request for retry"); | ||
506 | } else { | ||
507 | rc = -EIO; | ||
508 | } | ||
509 | } | 602 | } |
510 | spin_unlock(&GlobalMid_Lock); | 603 | spin_unlock(&GlobalMid_Lock); |
511 | DeleteMidQEntry(midQ); | 604 | } |
512 | /* Update # of requests on wire to server */ | 605 | |
606 | cifs_small_buf_release(in_buf); | ||
607 | |||
608 | rc = sync_mid_result(midQ, ses->server); | ||
609 | if (rc != 0) { | ||
513 | atomic_dec(&ses->server->inFlight); | 610 | atomic_dec(&ses->server->inFlight); |
514 | wake_up(&ses->server->request_q); | 611 | wake_up(&ses->server->request_q); |
515 | return rc; | 612 | return rc; |
516 | } | 613 | } |
517 | 614 | ||
518 | spin_unlock(&GlobalMid_Lock); | ||
519 | receive_len = midQ->resp_buf->smb_buf_length; | 615 | receive_len = midQ->resp_buf->smb_buf_length; |
520 | 616 | ||
521 | if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { | 617 | if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { |
@@ -559,19 +655,18 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, | |||
559 | if (receive_len >= sizeof(struct smb_hdr) - 4 | 655 | if (receive_len >= sizeof(struct smb_hdr) - 4 |
560 | /* do not count RFC1001 header */ + | 656 | /* do not count RFC1001 header */ + |
561 | (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ ) | 657 | (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ ) |
562 | BCC(midQ->resp_buf) = | 658 | put_bcc(get_bcc_le(midQ->resp_buf), midQ->resp_buf); |
563 | le16_to_cpu(BCC_LE(midQ->resp_buf)); | ||
564 | if ((flags & CIFS_NO_RESP) == 0) | 659 | if ((flags & CIFS_NO_RESP) == 0) |
565 | midQ->resp_buf = NULL; /* mark it so buf will | 660 | midQ->resp_buf = NULL; /* mark it so buf will |
566 | not be freed by | 661 | not be freed by |
567 | DeleteMidQEntry */ | 662 | delete_mid */ |
568 | } else { | 663 | } else { |
569 | rc = -EIO; | 664 | rc = -EIO; |
570 | cFYI(1, "Bad MID state?"); | 665 | cFYI(1, "Bad MID state?"); |
571 | } | 666 | } |
572 | 667 | ||
573 | out: | 668 | out: |
574 | DeleteMidQEntry(midQ); | 669 | delete_mid(midQ); |
575 | atomic_dec(&ses->server->inFlight); | 670 | atomic_dec(&ses->server->inFlight); |
576 | wake_up(&ses->server->request_q); | 671 | wake_up(&ses->server->request_q); |
577 | 672 | ||
@@ -585,7 +680,6 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, | |||
585 | { | 680 | { |
586 | int rc = 0; | 681 | int rc = 0; |
587 | unsigned int receive_len; | 682 | unsigned int receive_len; |
588 | unsigned long timeout; | ||
589 | struct mid_q_entry *midQ; | 683 | struct mid_q_entry *midQ; |
590 | 684 | ||
591 | if (ses == NULL) { | 685 | if (ses == NULL) { |
@@ -610,7 +704,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, | |||
610 | return -EIO; | 704 | return -EIO; |
611 | } | 705 | } |
612 | 706 | ||
613 | rc = wait_for_free_request(ses, long_op); | 707 | rc = wait_for_free_request(ses->server, long_op); |
614 | if (rc) | 708 | if (rc) |
615 | return rc; | 709 | return rc; |
616 | 710 | ||
@@ -649,64 +743,31 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, | |||
649 | if (rc < 0) | 743 | if (rc < 0) |
650 | goto out; | 744 | goto out; |
651 | 745 | ||
652 | if (long_op == CIFS_STD_OP) | 746 | if (long_op == CIFS_ASYNC_OP) |
653 | timeout = 15 * HZ; | ||
654 | /* wait for 15 seconds or until woken up due to response arriving or | ||
655 | due to last connection to this server being unmounted */ | ||
656 | else if (long_op == CIFS_ASYNC_OP) | ||
657 | goto out; | ||
658 | else if (long_op == CIFS_VLONG_OP) /* writes past EOF can be slow */ | ||
659 | timeout = 180 * HZ; | ||
660 | else if (long_op == CIFS_LONG_OP) | ||
661 | timeout = 45 * HZ; /* should be greater than | ||
662 | servers oplock break timeout (about 43 seconds) */ | ||
663 | else if (long_op == CIFS_BLOCKING_OP) | ||
664 | timeout = 0x7FFFFFFF; /* large but no so large as to wrap */ | ||
665 | else { | ||
666 | cERROR(1, "unknown timeout flag %d", long_op); | ||
667 | rc = -EIO; | ||
668 | goto out; | 747 | goto out; |
669 | } | ||
670 | |||
671 | if (signal_pending(current)) { | ||
672 | /* if signal pending do not hold up user for full smb timeout | ||
673 | but we still give response a chance to complete */ | ||
674 | timeout = 2 * HZ; | ||
675 | } | ||
676 | |||
677 | /* No user interrupts in wait - wreaks havoc with performance */ | ||
678 | wait_for_response(ses, midQ, timeout, 10 * HZ); | ||
679 | 748 | ||
680 | spin_lock(&GlobalMid_Lock); | 749 | rc = wait_for_response(ses->server, midQ); |
681 | if (midQ->resp_buf == NULL) { | 750 | if (rc != 0) { |
682 | cERROR(1, "No response for cmd %d mid %d", | 751 | send_nt_cancel(ses->server, in_buf, midQ); |
683 | midQ->command, midQ->mid); | 752 | spin_lock(&GlobalMid_Lock); |
684 | if (midQ->midState == MID_REQUEST_SUBMITTED) { | 753 | if (midQ->midState == MID_REQUEST_SUBMITTED) { |
685 | if (ses->server->tcpStatus == CifsExiting) | 754 | /* no longer considered to be "in-flight" */ |
686 | rc = -EHOSTDOWN; | 755 | midQ->callback = DeleteMidQEntry; |
687 | else { | 756 | spin_unlock(&GlobalMid_Lock); |
688 | ses->server->tcpStatus = CifsNeedReconnect; | 757 | atomic_dec(&ses->server->inFlight); |
689 | midQ->midState = MID_RETRY_NEEDED; | 758 | wake_up(&ses->server->request_q); |
690 | } | 759 | return rc; |
691 | } | ||
692 | |||
693 | if (rc != -EHOSTDOWN) { | ||
694 | if (midQ->midState == MID_RETRY_NEEDED) { | ||
695 | rc = -EAGAIN; | ||
696 | cFYI(1, "marking request for retry"); | ||
697 | } else { | ||
698 | rc = -EIO; | ||
699 | } | ||
700 | } | 760 | } |
701 | spin_unlock(&GlobalMid_Lock); | 761 | spin_unlock(&GlobalMid_Lock); |
702 | DeleteMidQEntry(midQ); | 762 | } |
703 | /* Update # of requests on wire to server */ | 763 | |
764 | rc = sync_mid_result(midQ, ses->server); | ||
765 | if (rc != 0) { | ||
704 | atomic_dec(&ses->server->inFlight); | 766 | atomic_dec(&ses->server->inFlight); |
705 | wake_up(&ses->server->request_q); | 767 | wake_up(&ses->server->request_q); |
706 | return rc; | 768 | return rc; |
707 | } | 769 | } |
708 | 770 | ||
709 | spin_unlock(&GlobalMid_Lock); | ||
710 | receive_len = midQ->resp_buf->smb_buf_length; | 771 | receive_len = midQ->resp_buf->smb_buf_length; |
711 | 772 | ||
712 | if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { | 773 | if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { |
@@ -748,43 +809,20 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, | |||
748 | if (receive_len >= sizeof(struct smb_hdr) - 4 | 809 | if (receive_len >= sizeof(struct smb_hdr) - 4 |
749 | /* do not count RFC1001 header */ + | 810 | /* do not count RFC1001 header */ + |
750 | (2 * out_buf->WordCount) + 2 /* bcc */ ) | 811 | (2 * out_buf->WordCount) + 2 /* bcc */ ) |
751 | BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf)); | 812 | put_bcc(get_bcc_le(midQ->resp_buf), midQ->resp_buf); |
752 | } else { | 813 | } else { |
753 | rc = -EIO; | 814 | rc = -EIO; |
754 | cERROR(1, "Bad MID state?"); | 815 | cERROR(1, "Bad MID state?"); |
755 | } | 816 | } |
756 | 817 | ||
757 | out: | 818 | out: |
758 | DeleteMidQEntry(midQ); | 819 | delete_mid(midQ); |
759 | atomic_dec(&ses->server->inFlight); | 820 | atomic_dec(&ses->server->inFlight); |
760 | wake_up(&ses->server->request_q); | 821 | wake_up(&ses->server->request_q); |
761 | 822 | ||
762 | return rc; | 823 | return rc; |
763 | } | 824 | } |
764 | 825 | ||
765 | /* Send an NT_CANCEL SMB to cause the POSIX blocking lock to return. */ | ||
766 | |||
767 | static int | ||
768 | send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf, | ||
769 | struct mid_q_entry *midQ) | ||
770 | { | ||
771 | int rc = 0; | ||
772 | struct cifsSesInfo *ses = tcon->ses; | ||
773 | __u16 mid = in_buf->Mid; | ||
774 | |||
775 | header_assemble(in_buf, SMB_COM_NT_CANCEL, tcon, 0); | ||
776 | in_buf->Mid = mid; | ||
777 | mutex_lock(&ses->server->srv_mutex); | ||
778 | rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number); | ||
779 | if (rc) { | ||
780 | mutex_unlock(&ses->server->srv_mutex); | ||
781 | return rc; | ||
782 | } | ||
783 | rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length); | ||
784 | mutex_unlock(&ses->server->srv_mutex); | ||
785 | return rc; | ||
786 | } | ||
787 | |||
788 | /* We send a LOCKINGX_CANCEL_LOCK to cause the Windows | 826 | /* We send a LOCKINGX_CANCEL_LOCK to cause the Windows |
789 | blocking lock to return. */ | 827 | blocking lock to return. */ |
790 | 828 | ||
@@ -807,7 +845,7 @@ send_lock_cancel(const unsigned int xid, struct cifsTconInfo *tcon, | |||
807 | pSMB->hdr.Mid = GetNextMid(ses->server); | 845 | pSMB->hdr.Mid = GetNextMid(ses->server); |
808 | 846 | ||
809 | return SendReceive(xid, ses, in_buf, out_buf, | 847 | return SendReceive(xid, ses, in_buf, out_buf, |
810 | &bytes_returned, CIFS_STD_OP); | 848 | &bytes_returned, 0); |
811 | } | 849 | } |
812 | 850 | ||
813 | int | 851 | int |
@@ -845,7 +883,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, | |||
845 | return -EIO; | 883 | return -EIO; |
846 | } | 884 | } |
847 | 885 | ||
848 | rc = wait_for_free_request(ses, CIFS_BLOCKING_OP); | 886 | rc = wait_for_free_request(ses->server, CIFS_BLOCKING_OP); |
849 | if (rc) | 887 | if (rc) |
850 | return rc; | 888 | return rc; |
851 | 889 | ||
@@ -863,7 +901,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, | |||
863 | 901 | ||
864 | rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number); | 902 | rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number); |
865 | if (rc) { | 903 | if (rc) { |
866 | DeleteMidQEntry(midQ); | 904 | delete_mid(midQ); |
867 | mutex_unlock(&ses->server->srv_mutex); | 905 | mutex_unlock(&ses->server->srv_mutex); |
868 | return rc; | 906 | return rc; |
869 | } | 907 | } |
@@ -880,7 +918,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, | |||
880 | mutex_unlock(&ses->server->srv_mutex); | 918 | mutex_unlock(&ses->server->srv_mutex); |
881 | 919 | ||
882 | if (rc < 0) { | 920 | if (rc < 0) { |
883 | DeleteMidQEntry(midQ); | 921 | delete_mid(midQ); |
884 | return rc; | 922 | return rc; |
885 | } | 923 | } |
886 | 924 | ||
@@ -899,10 +937,9 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, | |||
899 | if (in_buf->Command == SMB_COM_TRANSACTION2) { | 937 | if (in_buf->Command == SMB_COM_TRANSACTION2) { |
900 | /* POSIX lock. We send a NT_CANCEL SMB to cause the | 938 | /* POSIX lock. We send a NT_CANCEL SMB to cause the |
901 | blocking lock to return. */ | 939 | blocking lock to return. */ |
902 | 940 | rc = send_nt_cancel(ses->server, in_buf, midQ); | |
903 | rc = send_nt_cancel(tcon, in_buf, midQ); | ||
904 | if (rc) { | 941 | if (rc) { |
905 | DeleteMidQEntry(midQ); | 942 | delete_mid(midQ); |
906 | return rc; | 943 | return rc; |
907 | } | 944 | } |
908 | } else { | 945 | } else { |
@@ -914,47 +951,33 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, | |||
914 | /* If we get -ENOLCK back the lock may have | 951 | /* If we get -ENOLCK back the lock may have |
915 | already been removed. Don't exit in this case. */ | 952 | already been removed. Don't exit in this case. */ |
916 | if (rc && rc != -ENOLCK) { | 953 | if (rc && rc != -ENOLCK) { |
917 | DeleteMidQEntry(midQ); | 954 | delete_mid(midQ); |
918 | return rc; | 955 | return rc; |
919 | } | 956 | } |
920 | } | 957 | } |
921 | 958 | ||
922 | /* Wait 5 seconds for the response. */ | 959 | rc = wait_for_response(ses->server, midQ); |
923 | if (wait_for_response(ses, midQ, 5 * HZ, 5 * HZ) == 0) { | 960 | if (rc) { |
924 | /* We got the response - restart system call. */ | 961 | send_nt_cancel(ses->server, in_buf, midQ); |
925 | rstart = 1; | 962 | spin_lock(&GlobalMid_Lock); |
926 | } | 963 | if (midQ->midState == MID_REQUEST_SUBMITTED) { |
927 | } | 964 | /* no longer considered to be "in-flight" */ |
928 | 965 | midQ->callback = DeleteMidQEntry; | |
929 | spin_lock(&GlobalMid_Lock); | 966 | spin_unlock(&GlobalMid_Lock); |
930 | if (midQ->resp_buf) { | 967 | return rc; |
931 | spin_unlock(&GlobalMid_Lock); | ||
932 | receive_len = midQ->resp_buf->smb_buf_length; | ||
933 | } else { | ||
934 | cERROR(1, "No response for cmd %d mid %d", | ||
935 | midQ->command, midQ->mid); | ||
936 | if (midQ->midState == MID_REQUEST_SUBMITTED) { | ||
937 | if (ses->server->tcpStatus == CifsExiting) | ||
938 | rc = -EHOSTDOWN; | ||
939 | else { | ||
940 | ses->server->tcpStatus = CifsNeedReconnect; | ||
941 | midQ->midState = MID_RETRY_NEEDED; | ||
942 | } | 968 | } |
969 | spin_unlock(&GlobalMid_Lock); | ||
943 | } | 970 | } |
944 | 971 | ||
945 | if (rc != -EHOSTDOWN) { | 972 | /* We got the response - restart system call. */ |
946 | if (midQ->midState == MID_RETRY_NEEDED) { | 973 | rstart = 1; |
947 | rc = -EAGAIN; | ||
948 | cFYI(1, "marking request for retry"); | ||
949 | } else { | ||
950 | rc = -EIO; | ||
951 | } | ||
952 | } | ||
953 | spin_unlock(&GlobalMid_Lock); | ||
954 | DeleteMidQEntry(midQ); | ||
955 | return rc; | ||
956 | } | 974 | } |
957 | 975 | ||
976 | rc = sync_mid_result(midQ, ses->server); | ||
977 | if (rc != 0) | ||
978 | return rc; | ||
979 | |||
980 | receive_len = midQ->resp_buf->smb_buf_length; | ||
958 | if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { | 981 | if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { |
959 | cERROR(1, "Frame too large received. Length: %d Xid: %d", | 982 | cERROR(1, "Frame too large received. Length: %d Xid: %d", |
960 | receive_len, xid); | 983 | receive_len, xid); |
@@ -998,10 +1021,10 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, | |||
998 | if (receive_len >= sizeof(struct smb_hdr) - 4 | 1021 | if (receive_len >= sizeof(struct smb_hdr) - 4 |
999 | /* do not count RFC1001 header */ + | 1022 | /* do not count RFC1001 header */ + |
1000 | (2 * out_buf->WordCount) + 2 /* bcc */ ) | 1023 | (2 * out_buf->WordCount) + 2 /* bcc */ ) |
1001 | BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf)); | 1024 | put_bcc(get_bcc_le(out_buf), out_buf); |
1002 | 1025 | ||
1003 | out: | 1026 | out: |
1004 | DeleteMidQEntry(midQ); | 1027 | delete_mid(midQ); |
1005 | if (rstart && rc == -EACCES) | 1028 | if (rstart && rc == -EACCES) |
1006 | return -ERESTARTSYS; | 1029 | return -ERESTARTSYS; |
1007 | return rc; | 1030 | return rc; |