kernel/sysrq, watchdog, sched/core: Reset watchdog on all CPUs while processing sysrq-w
[pandora-kernel.git] / fs / cifs / cifssmb.c
index 6aa7457..969f74f 100644 (file)
@@ -89,6 +89,32 @@ static struct {
 /* Forward declarations */
 static void cifs_readv_complete(struct work_struct *work);
 
+#ifdef CONFIG_HIGHMEM
+/*
+ * On arches that have high memory, kmap address space is limited. By
+ * serializing the kmap operations on those arches, we ensure that we don't
+ * end up with a bunch of threads in writeback with partially mapped page
+ * arrays, stuck waiting for kmap to come back. That situation prevents
+ * progress and can deadlock.
+ */
+static DEFINE_MUTEX(cifs_kmap_mutex);
+
+static inline void
+cifs_kmap_lock(void)
+{
+       mutex_lock(&cifs_kmap_mutex);
+}
+
+static inline void
+cifs_kmap_unlock(void)
+{
+       mutex_unlock(&cifs_kmap_mutex);
+}
+#else /* !CONFIG_HIGHMEM */
+#define cifs_kmap_lock() do { ; } while(0)
+#define cifs_kmap_unlock() do { ; } while(0)
+#endif /* CONFIG_HIGHMEM */
+
 /* Mark as invalid, all open files on tree connections since they
    were closed when session to server was lost */
 static void mark_open_files_invalid(struct cifs_tcon *pTcon)
@@ -1540,6 +1566,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
        eof_index = eof ? (eof - 1) >> PAGE_CACHE_SHIFT : 0;
        cFYI(1, "eof=%llu eof_index=%lu", eof, eof_index);
 
+       cifs_kmap_lock();
        list_for_each_entry_safe(page, tpage, &rdata->pages, lru) {
                if (remaining >= PAGE_CACHE_SIZE) {
                        /* enough data to fill the page */
@@ -1589,6 +1616,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
                        page_cache_release(page);
                }
        }
+       cifs_kmap_unlock();
 
        /* issue the read if we have any iovecs left to fill */
        if (rdata->nr_iov > 1) {
@@ -2171,6 +2199,7 @@ cifs_async_writev(struct cifs_writedata *wdata)
        iov[0].iov_base = smb;
 
        /* marshal up the pages into iov array */
+       cifs_kmap_lock();
        wdata->bytes = 0;
        for (i = 0; i < wdata->nr_pages; i++) {
                iov[i + 1].iov_len = min(inode->i_size -
@@ -2179,6 +2208,7 @@ cifs_async_writev(struct cifs_writedata *wdata)
                iov[i + 1].iov_base = kmap(wdata->pages[i]);
                wdata->bytes += iov[i + 1].iov_len;
        }
+       cifs_kmap_unlock();
 
        cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes);
 
@@ -3407,11 +3437,13 @@ static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
                return 0;
        }
        cifs_acl->version = cpu_to_le16(1);
-       if (acl_type == ACL_TYPE_ACCESS)
+       if (acl_type == ACL_TYPE_ACCESS) {
                cifs_acl->access_entry_count = cpu_to_le16(count);
-       else if (acl_type == ACL_TYPE_DEFAULT)
+               cifs_acl->default_entry_count = __constant_cpu_to_le16(0xFFFF);
+       } else if (acl_type == ACL_TYPE_DEFAULT) {
                cifs_acl->default_entry_count = cpu_to_le16(count);
-       else {
+               cifs_acl->access_entry_count = __constant_cpu_to_le16(0xFFFF);
+       } else {
                cFYI(1, "unknown ACL type %d", acl_type);
                return 0;
        }