aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/CHANGES9
-rw-r--r--fs/cifs/README19
-rw-r--r--fs/cifs/cifsfs.c42
-rw-r--r--fs/cifs/cifsfs.h2
-rw-r--r--fs/cifs/cifsglob.h2
-rw-r--r--fs/cifs/cifssmb.c2
-rw-r--r--fs/cifs/connect.c94
-rw-r--r--fs/cifs/inode.c211
-rw-r--r--fs/cifs/readdir.c3
9 files changed, 259 insertions, 125 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 06e521a945c3..8f528ea24c48 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,3 +1,11 @@
1Version 1.55
2------------
3Various fixes to make delete of open files behavior more predictable
4(when delete of an open file fails we mark the file as "delete-on-close"
5in a way that more servers accept, but only if we can first rename the
6file to a temporary name). Add experimental support for more safely
7handling fcntl(F_SETLEASE).
8
1Version 1.54 9Version 1.54
2------------ 10------------
3Fix premature write failure on congested networks (we would give up 11Fix premature write failure on congested networks (we would give up
@@ -13,6 +21,7 @@ on dns_upcall (resolving DFS referralls). Fix plain text password
13authentication (requires setting SecurityFlags to 0x30030 to enable 21authentication (requires setting SecurityFlags to 0x30030 to enable
14lanman and plain text though). Fix writes to be at correct offset when 22lanman and plain text though). Fix writes to be at correct offset when
15file is open with O_APPEND and file is on a directio (forcediretio) mount. 23file is open with O_APPEND and file is on a directio (forcediretio) mount.
24Fix bug in rewinding readdir directory searches. Add nodfs mount option.
16 25
17Version 1.53 26Version 1.53
18------------ 27------------
diff --git a/fs/cifs/README b/fs/cifs/README
index bd2343d4c6a6..a439dc1739b3 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -463,6 +463,9 @@ A partial list of the supported mount options follows:
463 with cifs style mandatory byte range locks (and most 463 with cifs style mandatory byte range locks (and most
464 cifs servers do not yet support requesting advisory 464 cifs servers do not yet support requesting advisory
465 byte range locks). 465 byte range locks).
466 nodfs Disable DFS (global name space support) even if the
467 server claims to support it. This can help work around
468 a problem with parsing of DFS paths with Samba 3.0.24 server.
466 remount remount the share (often used to change from ro to rw mounts 469 remount remount the share (often used to change from ro to rw mounts
467 or vice versa) 470 or vice versa)
468 cifsacl Report mode bits (e.g. on stat) based on the Windows ACL for 471 cifsacl Report mode bits (e.g. on stat) based on the Windows ACL for
@@ -488,6 +491,19 @@ A partial list of the supported mount options follows:
488 Note that this differs from the sign mount option in that it 491 Note that this differs from the sign mount option in that it
489 causes encryption of data sent over this mounted share but other 492 causes encryption of data sent over this mounted share but other
490 shares mounted to the same server are unaffected. 493 shares mounted to the same server are unaffected.
494 locallease This option is rarely needed. Fcntl F_SETLEASE is
495 used by some applications such as Samba and NFSv4 server to
496 check to see whether a file is cacheable. CIFS has no way
497 to explicitly request a lease, but can check whether a file
498 is cacheable (oplocked). Unfortunately, even if a file
499 is not oplocked, it could still be cacheable (ie cifs client
500 could grant fcntl leases if no other local processes are using
501 the file) for cases for example such as when the server does not
502 support oplocks and the user is sure that the only updates to
503 the file will be from this client. Specifying this mount option
504 will allow the cifs client to check for leases (only) locally
505 for files which are not oplocked instead of denying leases
506 in that case. (EXPERIMENTAL)
491 sec Security mode. Allowed values are: 507 sec Security mode. Allowed values are:
492 none attempt to connection as a null user (no name) 508 none attempt to connection as a null user (no name)
493 krb5 Use Kerberos version 5 authentication 509 krb5 Use Kerberos version 5 authentication
@@ -638,6 +654,9 @@ requires enabling CONFIG_CIFS_EXPERIMENTAL
638 cifsacl support needed to retrieve approximated mode bits based on 654 cifsacl support needed to retrieve approximated mode bits based on
639 the contents on the CIFS ACL. 655 the contents on the CIFS ACL.
640 656
657 lease support: cifs will check the oplock state before calling into
658 the vfs to see if we can grant a lease on a file.
659
641 DNOTIFY fcntl: needed for support of directory change 660 DNOTIFY fcntl: needed for support of directory change
642 notification and perhaps later for file leases) 661 notification and perhaps later for file leases)
643 662
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 84cc011a16e4..ac5915d61dca 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -312,6 +312,7 @@ cifs_alloc_inode(struct super_block *sb)
312 file data or metadata */ 312 file data or metadata */
313 cifs_inode->clientCanCacheRead = false; 313 cifs_inode->clientCanCacheRead = false;
314 cifs_inode->clientCanCacheAll = false; 314 cifs_inode->clientCanCacheAll = false;
315 cifs_inode->delete_pending = false;
315 cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */ 316 cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
316 317
317 /* Can not set i_flags here - they get immediately overwritten 318 /* Can not set i_flags here - they get immediately overwritten
@@ -620,6 +621,37 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int origin)
620 return generic_file_llseek_unlocked(file, offset, origin); 621 return generic_file_llseek_unlocked(file, offset, origin);
621} 622}
622 623
624#ifdef CONFIG_CIFS_EXPERIMENTAL
625static int cifs_setlease(struct file *file, long arg, struct file_lock **lease)
626{
627 /* note that this is called by vfs setlease with the BKL held
628 although I doubt that BKL is needed here in cifs */
629 struct inode *inode = file->f_path.dentry->d_inode;
630
631 if (!(S_ISREG(inode->i_mode)))
632 return -EINVAL;
633
634 /* check if file is oplocked */
635 if (((arg == F_RDLCK) &&
636 (CIFS_I(inode)->clientCanCacheRead)) ||
637 ((arg == F_WRLCK) &&
638 (CIFS_I(inode)->clientCanCacheAll)))
639 return generic_setlease(file, arg, lease);
640 else if (CIFS_SB(inode->i_sb)->tcon->local_lease &&
641 !CIFS_I(inode)->clientCanCacheRead)
642 /* If the server claims to support oplock on this
643 file, then we still need to check oplock even
644 if the local_lease mount option is set, but there
645 are servers which do not support oplock for which
646 this mount option may be useful if the user
647 knows that the file won't be changed on the server
648 by anyone else */
649 return generic_setlease(file, arg, lease);
650 else
651 return -EAGAIN;
652}
653#endif
654
623struct file_system_type cifs_fs_type = { 655struct file_system_type cifs_fs_type = {
624 .owner = THIS_MODULE, 656 .owner = THIS_MODULE,
625 .name = "cifs", 657 .name = "cifs",
@@ -698,6 +730,7 @@ const struct file_operations cifs_file_ops = {
698 730
699#ifdef CONFIG_CIFS_EXPERIMENTAL 731#ifdef CONFIG_CIFS_EXPERIMENTAL
700 .dir_notify = cifs_dir_notify, 732 .dir_notify = cifs_dir_notify,
733 .setlease = cifs_setlease,
701#endif /* CONFIG_CIFS_EXPERIMENTAL */ 734#endif /* CONFIG_CIFS_EXPERIMENTAL */
702}; 735};
703 736
@@ -718,6 +751,7 @@ const struct file_operations cifs_file_direct_ops = {
718 .llseek = cifs_llseek, 751 .llseek = cifs_llseek,
719#ifdef CONFIG_CIFS_EXPERIMENTAL 752#ifdef CONFIG_CIFS_EXPERIMENTAL
720 .dir_notify = cifs_dir_notify, 753 .dir_notify = cifs_dir_notify,
754 .setlease = cifs_setlease,
721#endif /* CONFIG_CIFS_EXPERIMENTAL */ 755#endif /* CONFIG_CIFS_EXPERIMENTAL */
722}; 756};
723const struct file_operations cifs_file_nobrl_ops = { 757const struct file_operations cifs_file_nobrl_ops = {
@@ -738,6 +772,7 @@ const struct file_operations cifs_file_nobrl_ops = {
738 772
739#ifdef CONFIG_CIFS_EXPERIMENTAL 773#ifdef CONFIG_CIFS_EXPERIMENTAL
740 .dir_notify = cifs_dir_notify, 774 .dir_notify = cifs_dir_notify,
775 .setlease = cifs_setlease,
741#endif /* CONFIG_CIFS_EXPERIMENTAL */ 776#endif /* CONFIG_CIFS_EXPERIMENTAL */
742}; 777};
743 778
@@ -757,6 +792,7 @@ const struct file_operations cifs_file_direct_nobrl_ops = {
757 .llseek = cifs_llseek, 792 .llseek = cifs_llseek,
758#ifdef CONFIG_CIFS_EXPERIMENTAL 793#ifdef CONFIG_CIFS_EXPERIMENTAL
759 .dir_notify = cifs_dir_notify, 794 .dir_notify = cifs_dir_notify,
795 .setlease = cifs_setlease,
760#endif /* CONFIG_CIFS_EXPERIMENTAL */ 796#endif /* CONFIG_CIFS_EXPERIMENTAL */
761}; 797};
762 798
@@ -949,6 +985,12 @@ static int cifs_oplock_thread(void *dummyarg)
949 the call */ 985 the call */
950 /* mutex_lock(&inode->i_mutex);*/ 986 /* mutex_lock(&inode->i_mutex);*/
951 if (S_ISREG(inode->i_mode)) { 987 if (S_ISREG(inode->i_mode)) {
988#ifdef CONFIG_CIFS_EXPERIMENTAL
989 if (CIFS_I(inode)->clientCanCacheAll == 0)
990 break_lease(inode, FMODE_READ);
991 else if (CIFS_I(inode)->clientCanCacheRead == 0)
992 break_lease(inode, FMODE_WRITE);
993#endif
952 rc = filemap_fdatawrite(inode->i_mapping); 994 rc = filemap_fdatawrite(inode->i_mapping);
953 if (CIFS_I(inode)->clientCanCacheRead == 0) { 995 if (CIFS_I(inode)->clientCanCacheRead == 0) {
954 waitrc = filemap_fdatawait( 996 waitrc = filemap_fdatawait(
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index f7b4a5cd837b..074de0b5064d 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -101,5 +101,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
101extern const struct export_operations cifs_export_ops; 101extern const struct export_operations cifs_export_ops;
102#endif /* EXPERIMENTAL */ 102#endif /* EXPERIMENTAL */
103 103
104#define CIFS_VERSION "1.54" 104#define CIFS_VERSION "1.55"
105#endif /* _CIFSFS_H */ 105#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 0d22479d99b7..c791e5b5a914 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -285,6 +285,7 @@ struct cifsTconInfo {
285 bool seal:1; /* transport encryption for this mounted share */ 285 bool seal:1; /* transport encryption for this mounted share */
286 bool unix_ext:1; /* if false disable Linux extensions to CIFS protocol 286 bool unix_ext:1; /* if false disable Linux extensions to CIFS protocol
287 for this mount even if server would support */ 287 for this mount even if server would support */
288 bool local_lease:1; /* check leases (only) on local system not remote */
288 /* BB add field for back pointer to sb struct(s)? */ 289 /* BB add field for back pointer to sb struct(s)? */
289}; 290};
290 291
@@ -353,6 +354,7 @@ struct cifsInodeInfo {
353 bool clientCanCacheRead:1; /* read oplock */ 354 bool clientCanCacheRead:1; /* read oplock */
354 bool clientCanCacheAll:1; /* read and writebehind oplock */ 355 bool clientCanCacheAll:1; /* read and writebehind oplock */
355 bool oplockPending:1; 356 bool oplockPending:1;
357 bool delete_pending:1; /* DELETE_ON_CLOSE is set */
356 struct inode vfs_inode; 358 struct inode vfs_inode;
357}; 359};
358 360
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 6f4ffe15d68d..843a85fb8b9a 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -1309,6 +1309,7 @@ OldOpenRetry:
1309 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile)); 1309 cpu_to_le64(le32_to_cpu(pSMBr->EndOfFile));
1310 pfile_info->EndOfFile = pfile_info->AllocationSize; 1310 pfile_info->EndOfFile = pfile_info->AllocationSize;
1311 pfile_info->NumberOfLinks = cpu_to_le32(1); 1311 pfile_info->NumberOfLinks = cpu_to_le32(1);
1312 pfile_info->DeletePending = 0;
1312 } 1313 }
1313 } 1314 }
1314 1315
@@ -1410,6 +1411,7 @@ openRetry:
1410 pfile_info->AllocationSize = pSMBr->AllocationSize; 1411 pfile_info->AllocationSize = pSMBr->AllocationSize;
1411 pfile_info->EndOfFile = pSMBr->EndOfFile; 1412 pfile_info->EndOfFile = pSMBr->EndOfFile;
1412 pfile_info->NumberOfLinks = cpu_to_le32(1); 1413 pfile_info->NumberOfLinks = cpu_to_le32(1);
1414 pfile_info->DeletePending = 0;
1413 } 1415 }
1414 } 1416 }
1415 1417
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 4c13bcdb92a5..71b7661e2260 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -90,6 +90,8 @@ struct smb_vol {
90 bool nocase:1; /* request case insensitive filenames */ 90 bool nocase:1; /* request case insensitive filenames */
91 bool nobrl:1; /* disable sending byte range locks to srv */ 91 bool nobrl:1; /* disable sending byte range locks to srv */
92 bool seal:1; /* request transport encryption on share */ 92 bool seal:1; /* request transport encryption on share */
93 bool nodfs:1; /* Do not request DFS, even if available */
94 bool local_lease:1; /* check leases only on local system, not remote */
93 unsigned int rsize; 95 unsigned int rsize;
94 unsigned int wsize; 96 unsigned int wsize;
95 unsigned int sockopt; 97 unsigned int sockopt;
@@ -124,7 +126,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
124 struct mid_q_entry *mid_entry; 126 struct mid_q_entry *mid_entry;
125 127
126 spin_lock(&GlobalMid_Lock); 128 spin_lock(&GlobalMid_Lock);
127 if (kthread_should_stop()) { 129 if (server->tcpStatus == CifsExiting) {
128 /* the demux thread will exit normally 130 /* the demux thread will exit normally
129 next time through the loop */ 131 next time through the loop */
130 spin_unlock(&GlobalMid_Lock); 132 spin_unlock(&GlobalMid_Lock);
@@ -184,7 +186,8 @@ cifs_reconnect(struct TCP_Server_Info *server)
184 spin_unlock(&GlobalMid_Lock); 186 spin_unlock(&GlobalMid_Lock);
185 up(&server->tcpSem); 187 up(&server->tcpSem);
186 188
187 while ((!kthread_should_stop()) && (server->tcpStatus != CifsGood)) { 189 while ((server->tcpStatus != CifsExiting) &&
190 (server->tcpStatus != CifsGood)) {
188 try_to_freeze(); 191 try_to_freeze();
189 if (server->protocolType == IPV6) { 192 if (server->protocolType == IPV6) {
190 rc = ipv6_connect(&server->addr.sockAddr6, 193 rc = ipv6_connect(&server->addr.sockAddr6,
@@ -201,7 +204,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
201 } else { 204 } else {
202 atomic_inc(&tcpSesReconnectCount); 205 atomic_inc(&tcpSesReconnectCount);
203 spin_lock(&GlobalMid_Lock); 206 spin_lock(&GlobalMid_Lock);
204 if (!kthread_should_stop()) 207 if (server->tcpStatus != CifsExiting)
205 server->tcpStatus = CifsGood; 208 server->tcpStatus = CifsGood;
206 server->sequence_number = 0; 209 server->sequence_number = 0;
207 spin_unlock(&GlobalMid_Lock); 210 spin_unlock(&GlobalMid_Lock);
@@ -356,7 +359,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
356 GFP_KERNEL); 359 GFP_KERNEL);
357 360
358 set_freezable(); 361 set_freezable();
359 while (!kthread_should_stop()) { 362 while (server->tcpStatus != CifsExiting) {
360 if (try_to_freeze()) 363 if (try_to_freeze())
361 continue; 364 continue;
362 if (bigbuf == NULL) { 365 if (bigbuf == NULL) {
@@ -397,7 +400,7 @@ incomplete_rcv:
397 kernel_recvmsg(csocket, &smb_msg, 400 kernel_recvmsg(csocket, &smb_msg,
398 &iov, 1, pdu_length, 0 /* BB other flags? */); 401 &iov, 1, pdu_length, 0 /* BB other flags? */);
399 402
400 if (kthread_should_stop()) { 403 if (server->tcpStatus == CifsExiting) {
401 break; 404 break;
402 } else if (server->tcpStatus == CifsNeedReconnect) { 405 } else if (server->tcpStatus == CifsNeedReconnect) {
403 cFYI(1, ("Reconnect after server stopped responding")); 406 cFYI(1, ("Reconnect after server stopped responding"));
@@ -522,7 +525,7 @@ incomplete_rcv:
522 total_read += length) { 525 total_read += length) {
523 length = kernel_recvmsg(csocket, &smb_msg, &iov, 1, 526 length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
524 pdu_length - total_read, 0); 527 pdu_length - total_read, 0);
525 if (kthread_should_stop() || 528 if ((server->tcpStatus == CifsExiting) ||
526 (length == -EINTR)) { 529 (length == -EINTR)) {
527 /* then will exit */ 530 /* then will exit */
528 reconnect = 2; 531 reconnect = 2;
@@ -651,14 +654,6 @@ multi_t2_fnd:
651 spin_unlock(&GlobalMid_Lock); 654 spin_unlock(&GlobalMid_Lock);
652 wake_up_all(&server->response_q); 655 wake_up_all(&server->response_q);
653 656
654 /* don't exit until kthread_stop is called */
655 set_current_state(TASK_UNINTERRUPTIBLE);
656 while (!kthread_should_stop()) {
657 schedule();
658 set_current_state(TASK_UNINTERRUPTIBLE);
659 }
660 set_current_state(TASK_RUNNING);
661
662 /* check if we have blocked requests that need to free */ 657 /* check if we have blocked requests that need to free */
663 /* Note that cifs_max_pending is normally 50, but 658 /* Note that cifs_max_pending is normally 50, but
664 can be set at module install time to as little as two */ 659 can be set at module install time to as little as two */
@@ -755,6 +750,7 @@ multi_t2_fnd:
755 write_unlock(&GlobalSMBSeslock); 750 write_unlock(&GlobalSMBSeslock);
756 751
757 kfree(server->hostname); 752 kfree(server->hostname);
753 task_to_wake = xchg(&server->tsk, NULL);
758 kfree(server); 754 kfree(server);
759 755
760 length = atomic_dec_return(&tcpSesAllocCount); 756 length = atomic_dec_return(&tcpSesAllocCount);
@@ -762,6 +758,16 @@ multi_t2_fnd:
762 mempool_resize(cifs_req_poolp, length + cifs_min_rcv, 758 mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
763 GFP_KERNEL); 759 GFP_KERNEL);
764 760
761 /* if server->tsk was NULL then wait for a signal before exiting */
762 if (!task_to_wake) {
763 set_current_state(TASK_INTERRUPTIBLE);
764 while (!signal_pending(current)) {
765 schedule();
766 set_current_state(TASK_INTERRUPTIBLE);
767 }
768 set_current_state(TASK_RUNNING);
769 }
770
765 return 0; 771 return 0;
766} 772}
767 773
@@ -1218,6 +1224,8 @@ cifs_parse_mount_options(char *options, const char *devname,
1218 vol->sfu_emul = 1; 1224 vol->sfu_emul = 1;
1219 } else if (strnicmp(data, "nosfu", 5) == 0) { 1225 } else if (strnicmp(data, "nosfu", 5) == 0) {
1220 vol->sfu_emul = 0; 1226 vol->sfu_emul = 0;
1227 } else if (strnicmp(data, "nodfs", 5) == 0) {
1228 vol->nodfs = 1;
1221 } else if (strnicmp(data, "posixpaths", 10) == 0) { 1229 } else if (strnicmp(data, "posixpaths", 10) == 0) {
1222 vol->posix_paths = 1; 1230 vol->posix_paths = 1;
1223 } else if (strnicmp(data, "noposixpaths", 12) == 0) { 1231 } else if (strnicmp(data, "noposixpaths", 12) == 0) {
@@ -1268,6 +1276,10 @@ cifs_parse_mount_options(char *options, const char *devname,
1268 vol->no_psx_acl = 0; 1276 vol->no_psx_acl = 0;
1269 } else if (strnicmp(data, "noacl", 5) == 0) { 1277 } else if (strnicmp(data, "noacl", 5) == 0) {
1270 vol->no_psx_acl = 1; 1278 vol->no_psx_acl = 1;
1279#ifdef CONFIG_CIFS_EXPERIMENTAL
1280 } else if (strnicmp(data, "locallease", 6) == 0) {
1281 vol->local_lease = 1;
1282#endif
1271 } else if (strnicmp(data, "sign", 4) == 0) { 1283 } else if (strnicmp(data, "sign", 4) == 0) {
1272 vol->secFlg |= CIFSSEC_MUST_SIGN; 1284 vol->secFlg |= CIFSSEC_MUST_SIGN;
1273 } else if (strnicmp(data, "seal", 4) == 0) { 1285 } else if (strnicmp(data, "seal", 4) == 0) {
@@ -1845,6 +1857,16 @@ convert_delimiter(char *path, char delim)
1845 } 1857 }
1846} 1858}
1847 1859
1860static void
1861kill_cifsd(struct TCP_Server_Info *server)
1862{
1863 struct task_struct *task;
1864
1865 task = xchg(&server->tsk, NULL);
1866 if (task)
1867 force_sig(SIGKILL, task);
1868}
1869
1848int 1870int
1849cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, 1871cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1850 char *mount_data, const char *devname) 1872 char *mount_data, const char *devname)
@@ -2166,6 +2188,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2166 for the retry flag is used */ 2188 for the retry flag is used */
2167 tcon->retry = volume_info.retry; 2189 tcon->retry = volume_info.retry;
2168 tcon->nocase = volume_info.nocase; 2190 tcon->nocase = volume_info.nocase;
2191 tcon->local_lease = volume_info.local_lease;
2169 if (tcon->seal != volume_info.seal) 2192 if (tcon->seal != volume_info.seal)
2170 cERROR(1, ("transport encryption setting " 2193 cERROR(1, ("transport encryption setting "
2171 "conflicts with existing tid")); 2194 "conflicts with existing tid"));
@@ -2197,6 +2220,12 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2197 volume_info.UNC, 2220 volume_info.UNC,
2198 tcon, cifs_sb->local_nls); 2221 tcon, cifs_sb->local_nls);
2199 cFYI(1, ("CIFS Tcon rc = %d", rc)); 2222 cFYI(1, ("CIFS Tcon rc = %d", rc));
2223 if (volume_info.nodfs) {
2224 tcon->Flags &=
2225 ~SMB_SHARE_IS_IN_DFS;
2226 cFYI(1, ("DFS disabled (%d)",
2227 tcon->Flags));
2228 }
2200 } 2229 }
2201 if (!rc) { 2230 if (!rc) {
2202 atomic_inc(&pSesInfo->inUse); 2231 atomic_inc(&pSesInfo->inUse);
@@ -2225,14 +2254,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2225 spin_lock(&GlobalMid_Lock); 2254 spin_lock(&GlobalMid_Lock);
2226 srvTcp->tcpStatus = CifsExiting; 2255 srvTcp->tcpStatus = CifsExiting;
2227 spin_unlock(&GlobalMid_Lock); 2256 spin_unlock(&GlobalMid_Lock);
2228 if (srvTcp->tsk) { 2257 kill_cifsd(srvTcp);
2229 /* If we could verify that kthread_stop would
2230 always wake up processes blocked in
2231 tcp in recv_mesg then we could remove the
2232 send_sig call */
2233 force_sig(SIGKILL, srvTcp->tsk);
2234 kthread_stop(srvTcp->tsk);
2235 }
2236 } 2258 }
2237 /* If find_unc succeeded then rc == 0 so we can not end */ 2259 /* If find_unc succeeded then rc == 0 so we can not end */
2238 if (tcon) /* up accidently freeing someone elses tcon struct */ 2260 if (tcon) /* up accidently freeing someone elses tcon struct */
@@ -2245,19 +2267,15 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2245 temp_rc = CIFSSMBLogoff(xid, pSesInfo); 2267 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
2246 /* if the socketUseCount is now zero */ 2268 /* if the socketUseCount is now zero */
2247 if ((temp_rc == -ESHUTDOWN) && 2269 if ((temp_rc == -ESHUTDOWN) &&
2248 (pSesInfo->server) && 2270 (pSesInfo->server))
2249 (pSesInfo->server->tsk)) { 2271 kill_cifsd(pSesInfo->server);
2250 force_sig(SIGKILL,
2251 pSesInfo->server->tsk);
2252 kthread_stop(pSesInfo->server->tsk);
2253 }
2254 } else { 2272 } else {
2255 cFYI(1, ("No session or bad tcon")); 2273 cFYI(1, ("No session or bad tcon"));
2256 if ((pSesInfo->server) && 2274 if (pSesInfo->server) {
2257 (pSesInfo->server->tsk)) { 2275 spin_lock(&GlobalMid_Lock);
2258 force_sig(SIGKILL, 2276 srvTcp->tcpStatus = CifsExiting;
2259 pSesInfo->server->tsk); 2277 spin_unlock(&GlobalMid_Lock);
2260 kthread_stop(pSesInfo->server->tsk); 2278 kill_cifsd(pSesInfo->server);
2261 } 2279 }
2262 } 2280 }
2263 sesInfoFree(pSesInfo); 2281 sesInfoFree(pSesInfo);
@@ -3544,7 +3562,6 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3544 int rc = 0; 3562 int rc = 0;
3545 int xid; 3563 int xid;
3546 struct cifsSesInfo *ses = NULL; 3564 struct cifsSesInfo *ses = NULL;
3547 struct task_struct *cifsd_task;
3548 char *tmp; 3565 char *tmp;
3549 3566
3550 xid = GetXid(); 3567 xid = GetXid();
@@ -3560,7 +3577,6 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3560 tconInfoFree(cifs_sb->tcon); 3577 tconInfoFree(cifs_sb->tcon);
3561 if ((ses) && (ses->server)) { 3578 if ((ses) && (ses->server)) {
3562 /* save off task so we do not refer to ses later */ 3579 /* save off task so we do not refer to ses later */
3563 cifsd_task = ses->server->tsk;
3564 cFYI(1, ("About to do SMBLogoff ")); 3580 cFYI(1, ("About to do SMBLogoff "));
3565 rc = CIFSSMBLogoff(xid, ses); 3581 rc = CIFSSMBLogoff(xid, ses);
3566 if (rc == -EBUSY) { 3582 if (rc == -EBUSY) {
@@ -3568,10 +3584,8 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3568 return 0; 3584 return 0;
3569 } else if (rc == -ESHUTDOWN) { 3585 } else if (rc == -ESHUTDOWN) {
3570 cFYI(1, ("Waking up socket by sending signal")); 3586 cFYI(1, ("Waking up socket by sending signal"));
3571 if (cifsd_task) { 3587 if (ses->server)
3572 force_sig(SIGKILL, cifsd_task); 3588 kill_cifsd(ses->server);
3573 kthread_stop(cifsd_task);
3574 }
3575 rc = 0; 3589 rc = 0;
3576 } /* else - we have an smb session 3590 } /* else - we have an smb session
3577 left on this socket do not kill cifsd */ 3591 left on this socket do not kill cifsd */
@@ -3701,7 +3715,9 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3701 cERROR(1, ("Send error in SessSetup = %d", rc)); 3715 cERROR(1, ("Send error in SessSetup = %d", rc));
3702 } else { 3716 } else {
3703 cFYI(1, ("CIFS Session Established successfully")); 3717 cFYI(1, ("CIFS Session Established successfully"));
3718 spin_lock(&GlobalMid_Lock);
3704 pSesInfo->status = CifsGood; 3719 pSesInfo->status = CifsGood;
3720 spin_unlock(&GlobalMid_Lock);
3705 } 3721 }
3706 3722
3707ss_err_exit: 3723ss_err_exit:
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index a8c833345fc9..d54fa8aeaea9 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -506,6 +506,7 @@ int cifs_get_inode_info(struct inode **pinode,
506 inode = *pinode; 506 inode = *pinode;
507 cifsInfo = CIFS_I(inode); 507 cifsInfo = CIFS_I(inode);
508 cifsInfo->cifsAttrs = attr; 508 cifsInfo->cifsAttrs = attr;
509 cifsInfo->delete_pending = pfindData->DeletePending ? true : false;
509 cFYI(1, ("Old time %ld", cifsInfo->time)); 510 cFYI(1, ("Old time %ld", cifsInfo->time));
510 cifsInfo->time = jiffies; 511 cifsInfo->time = jiffies;
511 cFYI(1, ("New time %ld", cifsInfo->time)); 512 cFYI(1, ("New time %ld", cifsInfo->time));
@@ -772,63 +773,106 @@ out:
772 * anything else. 773 * anything else.
773 */ 774 */
774static int 775static int
775cifs_rename_pending_delete(char *full_path, struct inode *inode, int xid) 776cifs_rename_pending_delete(char *full_path, struct dentry *dentry, int xid)
776{ 777{
777 int oplock = 0; 778 int oplock = 0;
778 int rc; 779 int rc;
779 __u16 netfid; 780 __u16 netfid;
781 struct inode *inode = dentry->d_inode;
780 struct cifsInodeInfo *cifsInode = CIFS_I(inode); 782 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
781 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 783 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
782 struct cifsTconInfo *tcon = cifs_sb->tcon; 784 struct cifsTconInfo *tcon = cifs_sb->tcon;
783 __u32 dosattr; 785 __u32 dosattr, origattr;
784 FILE_BASIC_INFO *info_buf; 786 FILE_BASIC_INFO *info_buf = NULL;
785 787
786 rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, 788 rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN,
787 DELETE|FILE_WRITE_ATTRIBUTES, 789 DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR,
788 CREATE_NOT_DIR|CREATE_DELETE_ON_CLOSE,
789 &netfid, &oplock, NULL, cifs_sb->local_nls, 790 &netfid, &oplock, NULL, cifs_sb->local_nls,
790 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 791 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
791 if (rc != 0) 792 if (rc != 0)
792 goto out; 793 goto out;
793 794
794 /* set ATTR_HIDDEN and clear ATTR_READONLY */ 795 origattr = cifsInode->cifsAttrs;
795 cifsInode = CIFS_I(inode); 796 if (origattr == 0)
796 dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY; 797 origattr |= ATTR_NORMAL;
798
799 dosattr = origattr & ~ATTR_READONLY;
797 if (dosattr == 0) 800 if (dosattr == 0)
798 dosattr |= ATTR_NORMAL; 801 dosattr |= ATTR_NORMAL;
799 dosattr |= ATTR_HIDDEN; 802 dosattr |= ATTR_HIDDEN;
800 803
801 info_buf = kzalloc(sizeof(*info_buf), GFP_KERNEL); 804 /* set ATTR_HIDDEN and clear ATTR_READONLY, but only if needed */
802 if (info_buf == NULL) { 805 if (dosattr != origattr) {
803 rc = -ENOMEM; 806 info_buf = kzalloc(sizeof(*info_buf), GFP_KERNEL);
804 goto out_close; 807 if (info_buf == NULL) {
808 rc = -ENOMEM;
809 goto out_close;
810 }
811 info_buf->Attributes = cpu_to_le32(dosattr);
812 rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid,
813 current->tgid);
814 /* although we would like to mark the file hidden
815 if that fails we will still try to rename it */
816 if (rc != 0)
817 cifsInode->cifsAttrs = dosattr;
818 else
819 dosattr = origattr; /* since not able to change them */
805 } 820 }
806 info_buf->Attributes = cpu_to_le32(dosattr);
807 rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid, current->tgid);
808 kfree(info_buf);
809 if (rc != 0)
810 goto out_close;
811 cifsInode->cifsAttrs = dosattr;
812 821
813 /* silly-rename the file */ 822 /* rename the file */
814 CIFSSMBRenameOpenFile(xid, tcon, netfid, NULL, cifs_sb->local_nls, 823 rc = CIFSSMBRenameOpenFile(xid, tcon, netfid, NULL, cifs_sb->local_nls,
815 cifs_sb->mnt_cifs_flags & 824 cifs_sb->mnt_cifs_flags &
816 CIFS_MOUNT_MAP_SPECIAL_CHR); 825 CIFS_MOUNT_MAP_SPECIAL_CHR);
826 if (rc != 0) {
827 rc = -ETXTBSY;
828 goto undo_setattr;
829 }
817 830
818 /* set DELETE_ON_CLOSE */ 831 /* try to set DELETE_ON_CLOSE */
819 rc = CIFSSMBSetFileDisposition(xid, tcon, true, netfid, current->tgid); 832 if (!cifsInode->delete_pending) {
820 833 rc = CIFSSMBSetFileDisposition(xid, tcon, true, netfid,
821 /* 834 current->tgid);
822 * some samba versions return -ENOENT when we try to set the file 835 /*
823 * disposition here. Likely a samba bug, but work around it for now 836 * some samba versions return -ENOENT when we try to set the
824 */ 837 * file disposition here. Likely a samba bug, but work around
825 if (rc == -ENOENT) 838 * it for now. This means that some cifsXXX files may hang
826 rc = 0; 839 * around after they shouldn't.
840 *
841 * BB: remove this hack after more servers have the fix
842 */
843 if (rc == -ENOENT)
844 rc = 0;
845 else if (rc != 0) {
846 rc = -ETXTBSY;
847 goto undo_rename;
848 }
849 cifsInode->delete_pending = true;
850 }
827 851
828out_close: 852out_close:
829 CIFSSMBClose(xid, tcon, netfid); 853 CIFSSMBClose(xid, tcon, netfid);
830out: 854out:
855 kfree(info_buf);
831 return rc; 856 return rc;
857
858 /*
859 * reset everything back to the original state. Don't bother
860 * dealing with errors here since we can't do anything about
861 * them anyway.
862 */
863undo_rename:
864 CIFSSMBRenameOpenFile(xid, tcon, netfid, dentry->d_name.name,
865 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
866 CIFS_MOUNT_MAP_SPECIAL_CHR);
867undo_setattr:
868 if (dosattr != origattr) {
869 info_buf->Attributes = cpu_to_le32(origattr);
870 if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid,
871 current->tgid))
872 cifsInode->cifsAttrs = origattr;
873 }
874
875 goto out_close;
832} 876}
833 877
834int cifs_unlink(struct inode *dir, struct dentry *dentry) 878int cifs_unlink(struct inode *dir, struct dentry *dentry)
@@ -878,7 +922,7 @@ psx_del_no_retry:
878 } else if (rc == -ENOENT) { 922 } else if (rc == -ENOENT) {
879 d_drop(dentry); 923 d_drop(dentry);
880 } else if (rc == -ETXTBSY) { 924 } else if (rc == -ETXTBSY) {
881 rc = cifs_rename_pending_delete(full_path, inode, xid); 925 rc = cifs_rename_pending_delete(full_path, dentry, xid);
882 if (rc == 0) 926 if (rc == 0)
883 drop_nlink(inode); 927 drop_nlink(inode);
884 } else if (rc == -EACCES && dosattr == 0) { 928 } else if (rc == -EACCES && dosattr == 0) {
@@ -1241,22 +1285,21 @@ cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath,
1241 return rc; 1285 return rc;
1242} 1286}
1243 1287
1244int cifs_rename(struct inode *source_inode, struct dentry *source_direntry, 1288int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
1245 struct inode *target_inode, struct dentry *target_direntry) 1289 struct inode *target_dir, struct dentry *target_dentry)
1246{ 1290{
1247 char *fromName = NULL; 1291 char *fromName = NULL;
1248 char *toName = NULL; 1292 char *toName = NULL;
1249 struct cifs_sb_info *cifs_sb_source; 1293 struct cifs_sb_info *cifs_sb_source;
1250 struct cifs_sb_info *cifs_sb_target; 1294 struct cifs_sb_info *cifs_sb_target;
1251 struct cifsTconInfo *pTcon; 1295 struct cifsTconInfo *tcon;
1252 FILE_UNIX_BASIC_INFO *info_buf_source = NULL; 1296 FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
1253 FILE_UNIX_BASIC_INFO *info_buf_target; 1297 FILE_UNIX_BASIC_INFO *info_buf_target;
1254 int xid; 1298 int xid, rc, tmprc;
1255 int rc;
1256 1299
1257 cifs_sb_target = CIFS_SB(target_inode->i_sb); 1300 cifs_sb_target = CIFS_SB(target_dir->i_sb);
1258 cifs_sb_source = CIFS_SB(source_inode->i_sb); 1301 cifs_sb_source = CIFS_SB(source_dir->i_sb);
1259 pTcon = cifs_sb_source->tcon; 1302 tcon = cifs_sb_source->tcon;
1260 1303
1261 xid = GetXid(); 1304 xid = GetXid();
1262 1305
@@ -1264,7 +1307,7 @@ int cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
1264 * BB: this might be allowed if same server, but different share. 1307 * BB: this might be allowed if same server, but different share.
1265 * Consider adding support for this 1308 * Consider adding support for this
1266 */ 1309 */
1267 if (pTcon != cifs_sb_target->tcon) { 1310 if (tcon != cifs_sb_target->tcon) {
1268 rc = -EXDEV; 1311 rc = -EXDEV;
1269 goto cifs_rename_exit; 1312 goto cifs_rename_exit;
1270 } 1313 }
@@ -1273,65 +1316,65 @@ int cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
1273 * we already have the rename sem so we do not need to 1316 * we already have the rename sem so we do not need to
1274 * grab it again here to protect the path integrity 1317 * grab it again here to protect the path integrity
1275 */ 1318 */
1276 fromName = build_path_from_dentry(source_direntry); 1319 fromName = build_path_from_dentry(source_dentry);
1277 if (fromName == NULL) { 1320 if (fromName == NULL) {
1278 rc = -ENOMEM; 1321 rc = -ENOMEM;
1279 goto cifs_rename_exit; 1322 goto cifs_rename_exit;
1280 } 1323 }
1281 1324
1282 toName = build_path_from_dentry(target_direntry); 1325 toName = build_path_from_dentry(target_dentry);
1283 if (toName == NULL) { 1326 if (toName == NULL) {
1284 rc = -ENOMEM; 1327 rc = -ENOMEM;
1285 goto cifs_rename_exit; 1328 goto cifs_rename_exit;
1286 } 1329 }
1287 1330
1288 rc = cifs_do_rename(xid, source_direntry, fromName, 1331 rc = cifs_do_rename(xid, source_dentry, fromName,
1289 target_direntry, toName); 1332 target_dentry, toName);
1290 1333
1291 if (rc == -EEXIST) { 1334 if (rc == -EEXIST && tcon->unix_ext) {
1292 if (pTcon->unix_ext) { 1335 /*
1293 /* 1336 * Are src and dst hardlinks of same inode? We can
1294 * Are src and dst hardlinks of same inode? We can 1337 * only tell with unix extensions enabled
1295 * only tell with unix extensions enabled 1338 */
1296 */ 1339 info_buf_source =
1297 info_buf_source = 1340 kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),
1298 kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO), 1341 GFP_KERNEL);
1299 GFP_KERNEL); 1342 if (info_buf_source == NULL) {
1300 if (info_buf_source == NULL) 1343 rc = -ENOMEM;
1301 goto unlink_target; 1344 goto cifs_rename_exit;
1302 1345 }
1303 info_buf_target = info_buf_source + 1;
1304 rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName,
1305 info_buf_source,
1306 cifs_sb_source->local_nls,
1307 cifs_sb_source->mnt_cifs_flags &
1308 CIFS_MOUNT_MAP_SPECIAL_CHR);
1309 if (rc != 0)
1310 goto unlink_target;
1311
1312 rc = CIFSSMBUnixQPathInfo(xid, pTcon,
1313 toName, info_buf_target,
1314 cifs_sb_target->local_nls,
1315 /* remap based on source sb */
1316 cifs_sb_source->mnt_cifs_flags &
1317 CIFS_MOUNT_MAP_SPECIAL_CHR);
1318 1346
1319 if (rc == 0 && (info_buf_source->UniqueId == 1347 info_buf_target = info_buf_source + 1;
1320 info_buf_target->UniqueId)) 1348 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, fromName,
1321 /* same file, POSIX says that this is a noop */ 1349 info_buf_source,
1322 goto cifs_rename_exit; 1350 cifs_sb_source->local_nls,
1323 } /* else ... BB we could add the same check for Windows by 1351 cifs_sb_source->mnt_cifs_flags &
1352 CIFS_MOUNT_MAP_SPECIAL_CHR);
1353 if (tmprc != 0)
1354 goto unlink_target;
1355
1356 tmprc = CIFSSMBUnixQPathInfo(xid, tcon,
1357 toName, info_buf_target,
1358 cifs_sb_target->local_nls,
1359 /* remap based on source sb */
1360 cifs_sb_source->mnt_cifs_flags &
1361 CIFS_MOUNT_MAP_SPECIAL_CHR);
1362
1363 if (tmprc == 0 && (info_buf_source->UniqueId ==
1364 info_buf_target->UniqueId))
1365 /* same file, POSIX says that this is a noop */
1366 goto cifs_rename_exit;
1367 } /* else ... BB we could add the same check for Windows by
1324 checking the UniqueId via FILE_INTERNAL_INFO */ 1368 checking the UniqueId via FILE_INTERNAL_INFO */
1369
1325unlink_target: 1370unlink_target:
1326 /* 1371 if ((rc == -EACCES) || (rc == -EEXIST)) {
1327 * we either can not tell the files are hardlinked (as with 1372 tmprc = cifs_unlink(target_dir, target_dentry);
1328 * Windows servers) or files are not hardlinked. Delete the 1373 if (tmprc)
1329 * target manually before renaming to follow POSIX rather than 1374 goto cifs_rename_exit;
1330 * Windows semantics 1375
1331 */ 1376 rc = cifs_do_rename(xid, source_dentry, fromName,
1332 cifs_unlink(target_inode, target_direntry); 1377 target_dentry, toName);
1333 rc = cifs_do_rename(xid, source_direntry, fromName,
1334 target_direntry, toName);
1335 } 1378 }
1336 1379
1337cifs_rename_exit: 1380cifs_rename_exit:
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 765adf12d54f..58d57299f2a0 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -762,14 +762,15 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
762 rc)); 762 rc));
763 return rc; 763 return rc;
764 } 764 }
765 cifs_save_resume_key(cifsFile->srch_inf.last_entry, cifsFile);
765 } 766 }
766 767
767 while ((index_to_find >= cifsFile->srch_inf.index_of_last_entry) && 768 while ((index_to_find >= cifsFile->srch_inf.index_of_last_entry) &&
768 (rc == 0) && !cifsFile->srch_inf.endOfSearch) { 769 (rc == 0) && !cifsFile->srch_inf.endOfSearch) {
769 cFYI(1, ("calling findnext2")); 770 cFYI(1, ("calling findnext2"));
770 cifs_save_resume_key(cifsFile->srch_inf.last_entry, cifsFile);
771 rc = CIFSFindNext(xid, pTcon, cifsFile->netfid, 771 rc = CIFSFindNext(xid, pTcon, cifsFile->netfid,
772 &cifsFile->srch_inf); 772 &cifsFile->srch_inf);
773 cifs_save_resume_key(cifsFile->srch_inf.last_entry, cifsFile);
773 if (rc) 774 if (rc)
774 return -ENOENT; 775 return -ENOENT;
775 } 776 }