Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 14 Sep 2009 21:33:13 +0000 (14:33 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 14 Sep 2009 21:33:13 +0000 (14:33 -0700)
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6:
  cifs: consolidate reconnect logic in smb_init routines
  cifs: Replace wrtPending with a real reference count
  cifs: protect GlobalOplock_Q with its own spinlock
  cifs: use tcon pointer in cifs_show_options
  cifs: send IPv6 addr in upcall with colon delimiters
  [CIFS] Fix checkpatch warnings
  PATCH] cifs: fix broken mounts when a SSH tunnel is used (try #4)
  [CIFS] Memory leak in ntlmv2 hash calculation
  [CIFS] potential NULL dereference in parse_DFS_referrals()

13 files changed:
fs/cifs/CHANGES
fs/cifs/cifs_spnego.c
fs/cifs/cifsacl.c
fs/cifs/cifsencrypt.c
fs/cifs/cifsfs.c
fs/cifs/cifsfs.h
fs/cifs/cifsglob.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/dir.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/transport.c

index e85b1e4389e093e13c6ed23768c875ba49271dc1..145540a316ab4497be3c60814d05137aca4f0568 100644 (file)
@@ -3,7 +3,10 @@ Version 1.60
 Fix memory leak in reconnect.  Fix oops in DFS mount error path.
 Set s_maxbytes to smaller (the max that vfs can handle) so that
 sendfile will now work over cifs mounts again.  Add noforcegid
-and noforceuid mount parameters.
+and noforceuid mount parameters. Fix small mem leak when using
+ntlmv2. Fix 2nd mount to same server but with different port to
+be allowed (rather than reusing the 1st port) - only when the
+user explicitly overrides the port on the 2nd mount.
 
 Version 1.59
 ------------
index 051caecf7d677ebb621ba825e7b23962aef957bb..8ec7736ce954cd63cbe7a1cea7c368d248ad20ba 100644 (file)
@@ -125,7 +125,7 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo)
        if (server->addr.sockAddr.sin_family == AF_INET)
                sprintf(dp, "ip4=%pI4", &server->addr.sockAddr.sin_addr);
        else if (server->addr.sockAddr.sin_family == AF_INET6)
-               sprintf(dp, "ip6=%pi6", &server->addr.sockAddr6.sin6_addr);
+               sprintf(dp, "ip6=%pI6", &server->addr.sockAddr6.sin6_addr);
        else
                goto out;
 
index 6941c22398a6ac4097528add80d3ebcbcad2bbc2..7dfe0842a6f6046ac590ebdb6b7762b6aad91315 100644 (file)
@@ -607,7 +607,7 @@ static struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
                return get_cifs_acl_by_path(cifs_sb, path, pacllen);
 
        pntsd = get_cifs_acl_by_fid(cifs_sb, open_file->netfid, pacllen);
-       atomic_dec(&open_file->wrtPending);
+       cifsFileInfo_put(open_file);
        return pntsd;
 }
 
@@ -665,7 +665,7 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
                return set_cifs_acl_by_path(cifs_sb, path, pnntsd, acllen);
 
        rc = set_cifs_acl_by_fid(cifs_sb, open_file->netfid, pnntsd, acllen);
-       atomic_dec(&open_file->wrtPending);
+       cifsFileInfo_put(open_file);
        return rc;
 }
 
index 7c9809523f428a1cf3a31128d32d0d101152e2f6..7efe1745494d10a4968ef09f308af577d6ccc1c9 100644 (file)
@@ -373,6 +373,7 @@ calc_exit_2:
           compare with the NTLM example */
        hmac_md5_final(ses->server->ntlmv2_hash, pctxt);
 
+       kfree(pctxt);
        return rc;
 }
 
index 84b75253b05a01cf13748b33d642e58a515e7c41..3610e9958b4cedd2f7264a134f3bdb6ac0a4f8d1 100644 (file)
@@ -361,13 +361,10 @@ cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server)
 static int
 cifs_show_options(struct seq_file *s, struct vfsmount *m)
 {
-       struct cifs_sb_info *cifs_sb;
-       struct cifsTconInfo *tcon;
-
-       cifs_sb = CIFS_SB(m->mnt_sb);
-       tcon = cifs_sb->tcon;
+       struct cifs_sb_info *cifs_sb = CIFS_SB(m->mnt_sb);
+       struct cifsTconInfo *tcon = cifs_sb->tcon;
 
-       seq_printf(s, ",unc=%s", cifs_sb->tcon->treeName);
+       seq_printf(s, ",unc=%s", tcon->treeName);
        if (tcon->ses->userName)
                seq_printf(s, ",username=%s", tcon->ses->userName);
        if (tcon->ses->domainName)
@@ -989,19 +986,19 @@ static int cifs_oplock_thread(void *dummyarg)
                if (try_to_freeze())
                        continue;
 
-               spin_lock(&GlobalMid_Lock);
-               if (list_empty(&GlobalOplock_Q)) {
-                       spin_unlock(&GlobalMid_Lock);
+               spin_lock(&cifs_oplock_lock);
+               if (list_empty(&cifs_oplock_list)) {
+                       spin_unlock(&cifs_oplock_lock);
                        set_current_state(TASK_INTERRUPTIBLE);
                        schedule_timeout(39*HZ);
                } else {
-                       oplock_item = list_entry(GlobalOplock_Q.next,
+                       oplock_item = list_entry(cifs_oplock_list.next,
                                                struct oplock_q_entry, qhead);
                        cFYI(1, ("found oplock item to write out"));
                        pTcon = oplock_item->tcon;
                        inode = oplock_item->pinode;
                        netfid = oplock_item->netfid;
-                       spin_unlock(&GlobalMid_Lock);
+                       spin_unlock(&cifs_oplock_lock);
                        DeleteOplockQEntry(oplock_item);
                        /* can not grab inode sem here since it would
                                deadlock when oplock received on delete
@@ -1058,7 +1055,7 @@ init_cifs(void)
        int rc = 0;
        cifs_proc_init();
        INIT_LIST_HEAD(&cifs_tcp_ses_list);
-       INIT_LIST_HEAD(&GlobalOplock_Q);
+       INIT_LIST_HEAD(&cifs_oplock_list);
 #ifdef CONFIG_CIFS_EXPERIMENTAL
        INIT_LIST_HEAD(&GlobalDnotifyReqList);
        INIT_LIST_HEAD(&GlobalDnotifyRsp_Q);
@@ -1087,6 +1084,7 @@ init_cifs(void)
        rwlock_init(&GlobalSMBSeslock);
        rwlock_init(&cifs_tcp_ses_lock);
        spin_lock_init(&GlobalMid_Lock);
+       spin_lock_init(&cifs_oplock_lock);
 
        if (cifs_max_pending < 2) {
                cifs_max_pending = 2;
index 6c170948300d9be5cc6d8cc47eac8d73053bf390..094325e3f7147cd26c78da12fd842a3f223843d8 100644 (file)
@@ -113,5 +113,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
 extern const struct export_operations cifs_export_ops;
 #endif /* EXPERIMENTAL */
 
-#define CIFS_VERSION   "1.60"
+#define CIFS_VERSION   "1.61"
 #endif                         /* _CIFSFS_H */
index 6084d6379c03fb95ddf268e33ba903a55aa3b7c7..6cfc81a32703185c66ab93122fc4afb636c4e2d9 100644 (file)
@@ -351,11 +351,24 @@ struct cifsFileInfo {
        bool closePend:1;       /* file is marked to close */
        bool invalidHandle:1;   /* file closed via session abend */
        bool messageMode:1;     /* for pipes: message vs byte mode */
-       atomic_t wrtPending;   /* handle in use - defer close */
+       atomic_t count;         /* reference count */
        struct mutex fh_mutex; /* prevents reopen race after dead ses*/
        struct cifs_search_info srch_inf;
 };
 
+/* Take a reference on the file private data */
+static inline void cifsFileInfo_get(struct cifsFileInfo *cifs_file)
+{
+       atomic_inc(&cifs_file->count);
+}
+
+/* Release a reference on the file private data */
+static inline void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
+{
+       if (atomic_dec_and_test(&cifs_file->count))
+               kfree(cifs_file);
+}
+
 /*
  * One of these for each file inode
  */
@@ -656,7 +669,11 @@ GLOBAL_EXTERN rwlock_t             cifs_tcp_ses_lock;
  */
 GLOBAL_EXTERN rwlock_t GlobalSMBSeslock;
 
-GLOBAL_EXTERN struct list_head GlobalOplock_Q;
+/* Global list of oplocks */
+GLOBAL_EXTERN struct list_head cifs_oplock_list;
+
+/* Protects the cifs_oplock_list */
+GLOBAL_EXTERN spinlock_t cifs_oplock_lock;
 
 /* Outstanding dir notify requests */
 GLOBAL_EXTERN struct list_head GlobalDnotifyReqList;
index 1866bc2927d4f376182e98e71182fcff345f0a71..301e307e127900e71eb1291ae80c050a03d8aa98 100644 (file)
@@ -100,110 +100,138 @@ static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
           to this tcon */
 }
 
-/* Allocate and return pointer to an SMB request buffer, and set basic
-   SMB information in the SMB header.  If the return code is zero, this
-   function must have filled in request_buf pointer */
+/* reconnect the socket, tcon, and smb session if needed */
 static int
-small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
-               void **request_buf)
+cifs_reconnect_tcon(struct cifsTconInfo *tcon, int smb_command)
 {
        int rc = 0;
+       struct cifsSesInfo *ses;
+       struct TCP_Server_Info *server;
+       struct nls_table *nls_codepage;
 
-       /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
-          check for tcp and smb session status done differently
-          for those three - in the calling routine */
-       if (tcon) {
-               if (tcon->tidStatus == CifsExiting) {
-                       /* only tree disconnect, open, and write,
-                       (and ulogoff which does not have tcon)
-                       are allowed as we start force umount */
-                       if ((smb_command != SMB_COM_WRITE_ANDX) &&
-                          (smb_command != SMB_COM_OPEN_ANDX) &&
-                          (smb_command != SMB_COM_TREE_DISCONNECT)) {
-                               cFYI(1, ("can not send cmd %d while umounting",
-                                       smb_command));
-                               return -ENODEV;
-                       }
+       /*
+        * SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
+        * tcp and smb session status done differently for those three - in the
+        * calling routine
+        */
+       if (!tcon)
+               return 0;
+
+       ses = tcon->ses;
+       server = ses->server;
+
+       /*
+        * only tree disconnect, open, and write, (and ulogoff which does not
+        * have tcon) are allowed as we start force umount
+        */
+       if (tcon->tidStatus == CifsExiting) {
+               if (smb_command != SMB_COM_WRITE_ANDX &&
+                   smb_command != SMB_COM_OPEN_ANDX &&
+                   smb_command != SMB_COM_TREE_DISCONNECT) {
+                       cFYI(1, ("can not send cmd %d while umounting",
+                               smb_command));
+                       return -ENODEV;
                }
-               if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
-                                 (tcon->ses->server)) {
-                       struct nls_table *nls_codepage;
-                               /* Give Demultiplex thread up to 10 seconds to
-                                  reconnect, should be greater than cifs socket
-                                  timeout which is 7 seconds */
-                       while (tcon->ses->server->tcpStatus ==
-                                                        CifsNeedReconnect) {
-                               wait_event_interruptible_timeout(tcon->ses->server->response_q,
-                                       (tcon->ses->server->tcpStatus ==
-                                                       CifsGood), 10 * HZ);
-                               if (tcon->ses->server->tcpStatus ==
-                                                       CifsNeedReconnect) {
-                                       /* on "soft" mounts we wait once */
-                                       if (!tcon->retry ||
-                                          (tcon->ses->status == CifsExiting)) {
-                                               cFYI(1, ("gave up waiting on "
-                                                     "reconnect in smb_init"));
-                                               return -EHOSTDOWN;
-                                       } /* else "hard" mount - keep retrying
-                                            until process is killed or server
-                                            comes back on-line */
-                               } else /* TCP session is reestablished now */
-                                       break;
-                       }
+       }
 
-                       nls_codepage = load_nls_default();
-               /* need to prevent multiple threads trying to
-               simultaneously reconnect the same SMB session */
-                       down(&tcon->ses->sesSem);
-                       if (tcon->ses->need_reconnect)
-                               rc = cifs_setup_session(0, tcon->ses,
-                                                       nls_codepage);
-                       if (!rc && (tcon->need_reconnect)) {
-                               mark_open_files_invalid(tcon);
-                               rc = CIFSTCon(0, tcon->ses, tcon->treeName,
-                                             tcon, nls_codepage);
-                               up(&tcon->ses->sesSem);
-                               /* BB FIXME add code to check if wsize needs
-                                  update due to negotiated smb buffer size
-                                  shrinking */
-                               if (rc == 0) {
-                                       atomic_inc(&tconInfoReconnectCount);
-                                       /* tell server Unix caps we support */
-                                       if (tcon->ses->capabilities & CAP_UNIX)
-                                               reset_cifs_unix_caps(
-                                               0 /* no xid */,
-                                               tcon,
-                                               NULL /* we do not know sb */,
-                                               NULL /* no vol info */);
-                               }
+       if (ses->status == CifsExiting)
+               return -EIO;
 
-                               cFYI(1, ("reconnect tcon rc = %d", rc));
-                               /* Removed call to reopen open files here.
-                                  It is safer (and faster) to reopen files
-                                  one at a time as needed in read and write */
-
-                               /* Check if handle based operation so we
-                                  know whether we can continue or not without
-                                  returning to caller to reset file handle */
-                               switch (smb_command) {
-                                       case SMB_COM_READ_ANDX:
-                                       case SMB_COM_WRITE_ANDX:
-                                       case SMB_COM_CLOSE:
-                                       case SMB_COM_FIND_CLOSE2:
-                                       case SMB_COM_LOCKING_ANDX: {
-                                               unload_nls(nls_codepage);
-                                               return -EAGAIN;
-                                       }
-                               }
-                       } else {
-                               up(&tcon->ses->sesSem);
-                       }
-                       unload_nls(nls_codepage);
+       /*
+        * Give demultiplex thread up to 10 seconds to reconnect, should be
+        * greater than cifs socket timeout which is 7 seconds
+        */
+       while (server->tcpStatus == CifsNeedReconnect) {
+               wait_event_interruptible_timeout(server->response_q,
+                       (server->tcpStatus == CifsGood), 10 * HZ);
 
-               } else {
-                       return -EIO;
+               /* is TCP session is reestablished now ?*/
+               if (server->tcpStatus != CifsNeedReconnect)
+                       break;
+
+               /*
+                * on "soft" mounts we wait once. Hard mounts keep
+                * retrying until process is killed or server comes
+                * back on-line
+                */
+               if (!tcon->retry || ses->status == CifsExiting) {
+                       cFYI(1, ("gave up waiting on reconnect in smb_init"));
+                       return -EHOSTDOWN;
                }
        }
+
+       if (!ses->need_reconnect && !tcon->need_reconnect)
+               return 0;
+
+       nls_codepage = load_nls_default();
+
+       /*
+        * need to prevent multiple threads trying to simultaneously
+        * reconnect the same SMB session
+        */
+       down(&ses->sesSem);
+       if (ses->need_reconnect)
+               rc = cifs_setup_session(0, ses, nls_codepage);
+
+       /* do we need to reconnect tcon? */
+       if (rc || !tcon->need_reconnect) {
+               up(&ses->sesSem);
+               goto out;
+       }
+
+       mark_open_files_invalid(tcon);
+       rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage);
+       up(&ses->sesSem);
+       cFYI(1, ("reconnect tcon rc = %d", rc));
+
+       if (rc)
+               goto out;
+
+       /*
+        * FIXME: check if wsize needs updated due to negotiated smb buffer
+        *        size shrinking
+        */
+       atomic_inc(&tconInfoReconnectCount);
+
+       /* tell server Unix caps we support */
+       if (ses->capabilities & CAP_UNIX)
+               reset_cifs_unix_caps(0, tcon, NULL, NULL);
+
+       /*
+        * Removed call to reopen open files here. It is safer (and faster) to
+        * reopen files one at a time as needed in read and write.
+        *
+        * FIXME: what about file locks? don't we need to reclaim them ASAP?
+        */
+
+out:
+       /*
+        * Check if handle based operation so we know whether we can continue
+        * or not without returning to caller to reset file handle
+        */
+       switch (smb_command) {
+       case SMB_COM_READ_ANDX:
+       case SMB_COM_WRITE_ANDX:
+       case SMB_COM_CLOSE:
+       case SMB_COM_FIND_CLOSE2:
+       case SMB_COM_LOCKING_ANDX:
+               rc = -EAGAIN;
+       }
+
+       unload_nls(nls_codepage);
+       return rc;
+}
+
+/* Allocate and return pointer to an SMB request buffer, and set basic
+   SMB information in the SMB header.  If the return code is zero, this
+   function must have filled in request_buf pointer */
+static int
+small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
+               void **request_buf)
+{
+       int rc = 0;
+
+       rc = cifs_reconnect_tcon(tcon, smb_command);
        if (rc)
                return rc;
 
@@ -256,101 +284,7 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
 {
        int rc = 0;
 
-       /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
-          check for tcp and smb session status done differently
-          for those three - in the calling routine */
-       if (tcon) {
-               if (tcon->tidStatus == CifsExiting) {
-                       /* only tree disconnect, open, and write,
-                         (and ulogoff which does not have tcon)
-                         are allowed as we start force umount */
-                       if ((smb_command != SMB_COM_WRITE_ANDX) &&
-                          (smb_command != SMB_COM_OPEN_ANDX) &&
-                          (smb_command != SMB_COM_TREE_DISCONNECT)) {
-                               cFYI(1, ("can not send cmd %d while umounting",
-                                       smb_command));
-                               return -ENODEV;
-                       }
-               }
-
-               if ((tcon->ses) && (tcon->ses->status != CifsExiting) &&
-                                 (tcon->ses->server)) {
-                       struct nls_table *nls_codepage;
-                               /* Give Demultiplex thread up to 10 seconds to
-                                  reconnect, should be greater than cifs socket
-                                  timeout which is 7 seconds */
-                       while (tcon->ses->server->tcpStatus ==
-                                                       CifsNeedReconnect) {
-                               wait_event_interruptible_timeout(tcon->ses->server->response_q,
-                                       (tcon->ses->server->tcpStatus ==
-                                                       CifsGood), 10 * HZ);
-                               if (tcon->ses->server->tcpStatus ==
-                                               CifsNeedReconnect) {
-                                       /* on "soft" mounts we wait once */
-                                       if (!tcon->retry ||
-                                          (tcon->ses->status == CifsExiting)) {
-                                               cFYI(1, ("gave up waiting on "
-                                                     "reconnect in smb_init"));
-                                               return -EHOSTDOWN;
-                                       } /* else "hard" mount - keep retrying
-                                            until process is killed or server
-                                            comes on-line */
-                               } else /* TCP session is reestablished now */
-                                       break;
-                       }
-                       nls_codepage = load_nls_default();
-               /* need to prevent multiple threads trying to
-               simultaneously reconnect the same SMB session */
-                       down(&tcon->ses->sesSem);
-                       if (tcon->ses->need_reconnect)
-                               rc = cifs_setup_session(0, tcon->ses,
-                                                       nls_codepage);
-                       if (!rc && (tcon->need_reconnect)) {
-                               mark_open_files_invalid(tcon);
-                               rc = CIFSTCon(0, tcon->ses, tcon->treeName,
-                                             tcon, nls_codepage);
-                               up(&tcon->ses->sesSem);
-                               /* BB FIXME add code to check if wsize needs
-                               update due to negotiated smb buffer size
-                               shrinking */
-                               if (rc == 0) {
-                                       atomic_inc(&tconInfoReconnectCount);
-                                       /* tell server Unix caps we support */
-                                       if (tcon->ses->capabilities & CAP_UNIX)
-                                               reset_cifs_unix_caps(
-                                               0 /* no xid */,
-                                               tcon,
-                                               NULL /* do not know sb */,
-                                               NULL /* no vol info */);
-                               }
-
-                               cFYI(1, ("reconnect tcon rc = %d", rc));
-                               /* Removed call to reopen open files here.
-                                  It is safer (and faster) to reopen files
-                                  one at a time as needed in read and write */
-
-                               /* Check if handle based operation so we
-                                  know whether we can continue or not without
-                                  returning to caller to reset file handle */
-                               switch (smb_command) {
-                                       case SMB_COM_READ_ANDX:
-                                       case SMB_COM_WRITE_ANDX:
-                                       case SMB_COM_CLOSE:
-                                       case SMB_COM_FIND_CLOSE2:
-                                       case SMB_COM_LOCKING_ANDX: {
-                                               unload_nls(nls_codepage);
-                                               return -EAGAIN;
-                                       }
-                               }
-                       } else {
-                               up(&tcon->ses->sesSem);
-                       }
-                       unload_nls(nls_codepage);
-
-               } else {
-                       return -EIO;
-               }
-       }
+       rc = cifs_reconnect_tcon(tcon, smb_command);
        if (rc)
                return rc;
 
@@ -3961,6 +3895,10 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
                if (is_unicode) {
                        __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
                                                GFP_KERNEL);
+                       if (tmp == NULL) {
+                               rc = -ENOMEM;
+                               goto parse_DFS_referrals_exit;
+                       }
                        cifsConvertToUCS((__le16 *) tmp, searchName,
                                        PATH_MAX, nls_codepage, remap);
                        node->path_consumed = cifs_ucs2_bytes(tmp,
index 1f3345d7fa79a5e5dffc6f7be54f9734873ed3da..d49682433c20d03917bc7fbc1501345f718484b8 100644 (file)
@@ -1377,7 +1377,7 @@ cifs_parse_mount_options(char *options, const char *devname,
 }
 
 static struct TCP_Server_Info *
-cifs_find_tcp_session(struct sockaddr_storage *addr)
+cifs_find_tcp_session(struct sockaddr_storage *addr, unsigned short int port)
 {
        struct list_head *tmp;
        struct TCP_Server_Info *server;
@@ -1397,16 +1397,37 @@ cifs_find_tcp_session(struct sockaddr_storage *addr)
                if (server->tcpStatus == CifsNew)
                        continue;
 
-               if (addr->ss_family == AF_INET &&
-                   (addr4->sin_addr.s_addr !=
-                    server->addr.sockAddr.sin_addr.s_addr))
-                       continue;
-               else if (addr->ss_family == AF_INET6 &&
-                        (!ipv6_addr_equal(&server->addr.sockAddr6.sin6_addr,
-                                          &addr6->sin6_addr) ||
-                         server->addr.sockAddr6.sin6_scope_id !=
-                                          addr6->sin6_scope_id))
-                       continue;
+               switch (addr->ss_family) {
+               case AF_INET:
+                       if (addr4->sin_addr.s_addr ==
+                           server->addr.sockAddr.sin_addr.s_addr) {
+                               addr4->sin_port = htons(port);
+                               /* user overrode default port? */
+                               if (addr4->sin_port) {
+                                       if (addr4->sin_port !=
+                                           server->addr.sockAddr.sin_port)
+                                               continue;
+                               }
+                               break;
+                       } else
+                               continue;
+
+               case AF_INET6:
+                       if (ipv6_addr_equal(&addr6->sin6_addr,
+                           &server->addr.sockAddr6.sin6_addr) &&
+                           (addr6->sin6_scope_id ==
+                           server->addr.sockAddr6.sin6_scope_id)) {
+                               addr6->sin6_port = htons(port);
+                               /* user overrode default port? */
+                               if (addr6->sin6_port) {
+                                       if (addr6->sin6_port !=
+                                          server->addr.sockAddr6.sin6_port)
+                                               continue;
+                               }
+                               break;
+                       } else
+                               continue;
+               }
 
                ++server->srv_count;
                write_unlock(&cifs_tcp_ses_lock);
@@ -1475,7 +1496,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
        }
 
        /* see if we already have a matching tcp_ses */
-       tcp_ses = cifs_find_tcp_session(&addr);
+       tcp_ses = cifs_find_tcp_session(&addr, volume_info->port);
        if (tcp_ses)
                return tcp_ses;
 
@@ -2636,9 +2657,9 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
                return -EIO;
 
        smb_buffer = cifs_buf_get();
-       if (smb_buffer == NULL) {
+       if (smb_buffer == NULL)
                return -ENOMEM;
-       }
+
        smb_buffer_response = smb_buffer;
 
        header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
index 4326ffd90fa91b92086ab993bcfe7631396c7cf4..a6424cfc0121dfe543b656a88883583ad8f24920 100644 (file)
@@ -153,7 +153,7 @@ cifs_fill_fileinfo(struct inode *newinode, __u16 fileHandle,
        mutex_init(&pCifsFile->fh_mutex);
        mutex_init(&pCifsFile->lock_mutex);
        INIT_LIST_HEAD(&pCifsFile->llist);
-       atomic_set(&pCifsFile->wrtPending, 0);
+       atomic_set(&pCifsFile->count, 1);
 
        /* set the following in open now
                        pCifsFile->pfile = file; */
index c34b7f8a217b383b1f8505822f00052276779833..fa7beac8b80e6df1a3e25d936f3048a0b14cc584 100644 (file)
@@ -53,11 +53,9 @@ static inline struct cifsFileInfo *cifs_init_private(
        private_data->pInode = inode;
        private_data->invalidHandle = false;
        private_data->closePend = false;
-       /* we have to track num writers to the inode, since writepages
-       does not tell us which handle the write is for so there can
-       be a close (overlapping with write) of the filehandle that
-       cifs_writepages chose to use */
-       atomic_set(&private_data->wrtPending, 0);
+       /* Initialize reference count to one.  The private data is
+       freed on the release of the last reference */
+       atomic_set(&private_data->count, 1);
 
        return private_data;
 }
@@ -643,7 +641,7 @@ int cifs_close(struct inode *inode, struct file *file)
                        if (!pTcon->need_reconnect) {
                                write_unlock(&GlobalSMBSeslock);
                                timeout = 2;
-                               while ((atomic_read(&pSMBFile->wrtPending) != 0)
+                               while ((atomic_read(&pSMBFile->count) != 1)
                                        && (timeout <= 2048)) {
                                        /* Give write a better chance to get to
                                        server ahead of the close.  We do not
@@ -657,8 +655,6 @@ int cifs_close(struct inode *inode, struct file *file)
                                        msleep(timeout);
                                        timeout *= 4;
                                }
-                               if (atomic_read(&pSMBFile->wrtPending))
-                                       cERROR(1, ("close with pending write"));
                                if (!pTcon->need_reconnect &&
                                    !pSMBFile->invalidHandle)
                                        rc = CIFSSMBClose(xid, pTcon,
@@ -681,24 +677,7 @@ int cifs_close(struct inode *inode, struct file *file)
                list_del(&pSMBFile->flist);
                list_del(&pSMBFile->tlist);
                write_unlock(&GlobalSMBSeslock);
-               timeout = 10;
-               /* We waited above to give the SMBWrite a chance to issue
-                  on the wire (so we do not get SMBWrite returning EBADF
-                  if writepages is racing with close.  Note that writepages
-                  does not specify a file handle, so it is possible for a file
-                  to be opened twice, and the application close the "wrong"
-                  file handle - in these cases we delay long enough to allow
-                  the SMBWrite to get on the wire before the SMB Close.
-                  We allow total wait here over 45 seconds, more than
-                  oplock break time, and more than enough to allow any write
-                  to complete on the server, or to time out on the client */
-               while ((atomic_read(&pSMBFile->wrtPending) != 0)
-                               && (timeout <= 50000)) {
-                       cERROR(1, ("writes pending, delay free of handle"));
-                       msleep(timeout);
-                       timeout *= 8;
-               }
-               kfree(file->private_data);
+               cifsFileInfo_put(file->private_data);
                file->private_data = NULL;
        } else
                rc = -EBADF;
@@ -1236,7 +1215,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode)
                        if (!open_file->invalidHandle) {
                                /* found a good file */
                                /* lock it so it will not be closed on us */
-                               atomic_inc(&open_file->wrtPending);
+                               cifsFileInfo_get(open_file);
                                read_unlock(&GlobalSMBSeslock);
                                return open_file;
                        } /* else might as well continue, and look for
@@ -1276,7 +1255,7 @@ refind_writable:
                if (open_file->pfile &&
                    ((open_file->pfile->f_flags & O_RDWR) ||
                     (open_file->pfile->f_flags & O_WRONLY))) {
-                       atomic_inc(&open_file->wrtPending);
+                       cifsFileInfo_get(open_file);
 
                        if (!open_file->invalidHandle) {
                                /* found a good writable file */
@@ -1293,7 +1272,7 @@ refind_writable:
                                else { /* start over in case this was deleted */
                                       /* since the list could be modified */
                                        read_lock(&GlobalSMBSeslock);
-                                       atomic_dec(&open_file->wrtPending);
+                                       cifsFileInfo_put(open_file);
                                        goto refind_writable;
                                }
                        }
@@ -1309,7 +1288,7 @@ refind_writable:
                        read_lock(&GlobalSMBSeslock);
                        /* can not use this handle, no write
                           pending on this one after all */
-                       atomic_dec(&open_file->wrtPending);
+                       cifsFileInfo_put(open_file);
 
                        if (open_file->closePend) /* list could have changed */
                                goto refind_writable;
@@ -1373,7 +1352,7 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
        if (open_file) {
                bytes_written = cifs_write(open_file->pfile, write_data,
                                           to-from, &offset);
-               atomic_dec(&open_file->wrtPending);
+               cifsFileInfo_put(open_file);
                /* Does mm or vfs already set times? */
                inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb);
                if ((bytes_written > 0) && (offset))
@@ -1562,7 +1541,7 @@ retry:
                                                   bytes_to_write, offset,
                                                   &bytes_written, iov, n_iov,
                                                   long_op);
-                               atomic_dec(&open_file->wrtPending);
+                               cifsFileInfo_put(open_file);
                                cifs_update_eof(cifsi, offset, bytes_written);
 
                                if (rc || bytes_written < bytes_to_write) {
index 82d83839655eed195fa91dd10120e048309bd287..1f09c7619319d794dd10a3d58a3543aa34e36ca9 100644 (file)
@@ -800,7 +800,7 @@ set_via_filehandle:
        if (open_file == NULL)
                CIFSSMBClose(xid, pTcon, netfid);
        else
-               atomic_dec(&open_file->wrtPending);
+               cifsFileInfo_put(open_file);
 out:
        return rc;
 }
@@ -1635,7 +1635,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
                __u32 npid = open_file->pid;
                rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size, nfid,
                                        npid, false);
-               atomic_dec(&open_file->wrtPending);
+               cifsFileInfo_put(open_file);
                cFYI(1, ("SetFSize for attrs rc = %d", rc));
                if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
                        unsigned int bytes_written;
@@ -1790,7 +1790,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
                u16 nfid = open_file->netfid;
                u32 npid = open_file->pid;
                rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
-               atomic_dec(&open_file->wrtPending);
+               cifsFileInfo_put(open_file);
        } else {
                rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
                                    cifs_sb->local_nls,
index 0ad3e2d116a6b0fb8238601bcb654b871ecb9845..1da4ab250eae327a5e9a8889b9e498b4bc4946eb 100644 (file)
@@ -119,20 +119,19 @@ AllocOplockQEntry(struct inode *pinode, __u16 fid, struct cifsTconInfo *tcon)
                temp->pinode = pinode;
                temp->tcon = tcon;
                temp->netfid = fid;
-               spin_lock(&GlobalMid_Lock);
-               list_add_tail(&temp->qhead, &GlobalOplock_Q);
-               spin_unlock(&GlobalMid_Lock);
+               spin_lock(&cifs_oplock_lock);
+               list_add_tail(&temp->qhead, &cifs_oplock_list);
+               spin_unlock(&cifs_oplock_lock);
        }
        return temp;
-
 }
 
 void DeleteOplockQEntry(struct oplock_q_entry *oplockEntry)
 {
-       spin_lock(&GlobalMid_Lock);
+       spin_lock(&cifs_oplock_lock);
     /* should we check if list empty first? */
        list_del(&oplockEntry->qhead);
-       spin_unlock(&GlobalMid_Lock);
+       spin_unlock(&cifs_oplock_lock);
        kmem_cache_free(cifs_oplock_cachep, oplockEntry);
 }
 
@@ -144,14 +143,14 @@ void DeleteTconOplockQEntries(struct cifsTconInfo *tcon)
        if (tcon == NULL)
                return;
 
-       spin_lock(&GlobalMid_Lock);
-       list_for_each_entry(temp, &GlobalOplock_Q, qhead) {
+       spin_lock(&cifs_oplock_lock);
+       list_for_each_entry(temp, &cifs_oplock_list, qhead) {
                if ((temp->tcon) && (temp->tcon == tcon)) {
                        list_del(&temp->qhead);
                        kmem_cache_free(cifs_oplock_cachep, temp);
                }
        }
-       spin_unlock(&GlobalMid_Lock);
+       spin_unlock(&cifs_oplock_lock);
 }
 
 static int