]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 20 Nov 2008 21:14:16 +0000 (13:14 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 20 Nov 2008 21:14:16 +0000 (13:14 -0800)
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6:
  [CIFS] Do not attempt to close invalidated file handles
  [CIFS] fix check for dead tcon in smb_init

fs/cifs/CHANGES
fs/cifs/cifsglob.h
fs/cifs/cifssmb.c
fs/cifs/file.c
fs/cifs/misc.c
fs/cifs/readdir.c

index 8855331b2fba551984776b30b1747b80a98607f1..e078b7aea1431d648b9b6dd6df5313b0b2cc738a 100644 (file)
@@ -8,7 +8,11 @@ handling fcntl(F_SETLEASE).  Convert cifs to using blocking tcp
 sends, and also let tcp autotune the socket send and receive buffers.
 This reduces the number of EAGAIN errors returned by TCP/IP in
 high stress workloads (and the number of retries on socket writes
-when sending large SMBWriteX requests).
+when sending large SMBWriteX requests).  Fix case in which a portion of
+data can in some cases not get written to the file on the server before the
+file is closed.  Fix DFS parsing to properly handle path consumed field,
+and to handle certain codepage conversions better.  Fix mount and
+umount race that can cause oops in mount or umount or reconnect.
 
 Version 1.54
 ------------
index f1ae1f57c30dcbfd86de17dcbb46bcc9c3991e71..c57c0565547fa99058e9a192796123a419309066 100644 (file)
@@ -606,7 +606,15 @@ GLOBAL_EXTERN struct list_head             cifs_tcp_ses_list;
  * changes to the tcon->tidStatus should be done while holding this lock.
  */
 GLOBAL_EXTERN rwlock_t         cifs_tcp_ses_lock;
-GLOBAL_EXTERN rwlock_t GlobalSMBSeslock;  /* protects list inserts on 3 above */
+
+/*
+ * This lock protects the cifs_file->llist and cifs_file->flist
+ * list operations, and updates to some flags (cifs_file->invalidHandle)
+ * It will be moved to either use the tcon->stat_lock or equivalent later.
+ * If cifs_tcp_ses_lock and the lock below are both needed to be held, then
+ * the cifs_tcp_ses_lock must be grabbed first and released last.
+ */
+GLOBAL_EXTERN rwlock_t GlobalSMBSeslock;
 
 GLOBAL_EXTERN struct list_head GlobalOplock_Q;
 
index bdda46dd435a0d9fd8c6d0d692e7b98be4390cc6..2af8626ced435c10bea3654e38570f7decaa8a7d 100644 (file)
@@ -295,7 +295,7 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
           check for tcp and smb session status done differently
           for those three - in the calling routine */
        if (tcon) {
-               if (tcon->need_reconnect) {
+               if (tcon->tidStatus == CifsExiting) {
                        /* only tree disconnect, open, and write,
                          (and ulogoff which does not have tcon)
                          are allowed as we start force umount */
index 6449e1aae621aa2721a1f5a5bd12338ac2890b6c..b691b893a848a8d4d74c1e0ecce800d561b99b67 100644 (file)
@@ -488,12 +488,13 @@ int cifs_close(struct inode *inode, struct file *file)
        pTcon = cifs_sb->tcon;
        if (pSMBFile) {
                struct cifsLockInfo *li, *tmp;
-
+               write_lock(&GlobalSMBSeslock);
                pSMBFile->closePend = true;
                if (pTcon) {
                        /* no sense reconnecting to close a file that is
                           already closed */
                        if (!pTcon->need_reconnect) {
+                               write_unlock(&GlobalSMBSeslock);
                                timeout = 2;
                                while ((atomic_read(&pSMBFile->wrtPending) != 0)
                                        && (timeout <= 2048)) {
@@ -510,12 +511,15 @@ int cifs_close(struct inode *inode, struct file *file)
                                        timeout *= 4;
                                }
                                if (atomic_read(&pSMBFile->wrtPending))
-                                       cERROR(1,
-                                               ("close with pending writes"));
-                               rc = CIFSSMBClose(xid, pTcon,
+                                       cERROR(1, ("close with pending write"));
+                               if (!pTcon->need_reconnect &&
+                                   !pSMBFile->invalidHandle)
+                                       rc = CIFSSMBClose(xid, pTcon,
                                                  pSMBFile->netfid);
-                       }
-               }
+                       } else
+                               write_unlock(&GlobalSMBSeslock);
+               } else
+                       write_unlock(&GlobalSMBSeslock);
 
                /* Delete any outstanding lock records.
                   We'll lose them when the file is closed anyway. */
@@ -587,15 +591,18 @@ int cifs_closedir(struct inode *inode, struct file *file)
                pTcon = cifs_sb->tcon;
 
                cFYI(1, ("Freeing private data in close dir"));
+               write_lock(&GlobalSMBSeslock);
                if (!pCFileStruct->srch_inf.endOfSearch &&
                    !pCFileStruct->invalidHandle) {
                        pCFileStruct->invalidHandle = true;
+                       write_unlock(&GlobalSMBSeslock);
                        rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid);
                        cFYI(1, ("Closing uncompleted readdir with rc %d",
                                 rc));
                        /* not much we can do if it fails anyway, ignore rc */
                        rc = 0;
-               }
+               } else
+                       write_unlock(&GlobalSMBSeslock);
                ptmp = pCFileStruct->srch_inf.ntwrk_buf_start;
                if (ptmp) {
                        cFYI(1, ("closedir free smb buf in srch struct"));
index addd1dcc2d79513ab6404e6a530d6927cbe71eee..9ee3f689c2b0c0f78468082658d0aad8cf56791c 100644 (file)
@@ -555,12 +555,14 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
                                continue;
 
                        cifs_stats_inc(&tcon->num_oplock_brks);
+                       write_lock(&GlobalSMBSeslock);
                        list_for_each(tmp2, &tcon->openFileList) {
                                netfile = list_entry(tmp2, struct cifsFileInfo,
                                                     tlist);
                                if (pSMB->Fid != netfile->netfid)
                                        continue;
 
+                               write_unlock(&GlobalSMBSeslock);
                                read_unlock(&cifs_tcp_ses_lock);
                                cFYI(1, ("file id match, oplock break"));
                                pCifsInode = CIFS_I(netfile->pInode);
@@ -576,6 +578,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
 
                                return true;
                        }
+                       write_unlock(&GlobalSMBSeslock);
                        read_unlock(&cifs_tcp_ses_lock);
                        cFYI(1, ("No matching file for oplock break"));
                        return true;
index 58d57299f2a08c432625f9be298e731e2fa7bae0..9f51f9bf0292f4a67aee9ca82aae2f6d3b6cc5d0 100644 (file)
@@ -741,11 +741,14 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
           (index_to_find < first_entry_in_buffer)) {
                /* close and restart search */
                cFYI(1, ("search backing up - close and restart search"));
+               write_lock(&GlobalSMBSeslock);
                if (!cifsFile->srch_inf.endOfSearch &&
                    !cifsFile->invalidHandle) {
                        cifsFile->invalidHandle = true;
+                       write_unlock(&GlobalSMBSeslock);
                        CIFSFindClose(xid, pTcon, cifsFile->netfid);
-               }
+               } else
+                       write_unlock(&GlobalSMBSeslock);
                if (cifsFile->srch_inf.ntwrk_buf_start) {
                        cFYI(1, ("freeing SMB ff cache buf on search rewind"));
                        if (cifsFile->srch_inf.smallBuf)