Prechádzať zdrojové kódy

Merge branch 'akpm' (patches from Andrew Morton)

Merge misc fixes from Andrew Morton:
 "7 fixes"

* emailed patches from Andrew Morton <akpm@linux-foundation.org>:
  mm/debug_pagealloc: fix build failure on ppc and some other archs
  nilfs2: fix deadlock of segment constructor over I_SYNC flag
  MAINTAINERS: remove SUPERH website
  memcg, shmem: fix shmem migration to use lrucare
  mm: export "high_memory" symbol on !MMU
  .mailmap: update Konstantin Khlebnikov's email address
  mm: pagewalk: call pte_hole() for VM_PFNMAP during walk_page_range
Linus Torvalds 10 rokov pred
rodič
commit
48beb121f0

+ 1 - 0
.mailmap

@@ -73,6 +73,7 @@ Juha Yrjola <juha.yrjola@nokia.com>
 Juha Yrjola <juha.yrjola@solidboot.com>
 Juha Yrjola <juha.yrjola@solidboot.com>
 Kay Sievers <kay.sievers@vrfy.org>
 Kay Sievers <kay.sievers@vrfy.org>
 Kenneth W Chen <kenneth.w.chen@intel.com>
 Kenneth W Chen <kenneth.w.chen@intel.com>
+Konstantin Khlebnikov <koct9i@gmail.com> <k.khlebnikov@samsung.com>
 Koushik <raghavendra.koushik@neterion.com>
 Koushik <raghavendra.koushik@neterion.com>
 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
 Leonid I Ananiev <leonid.i.ananiev@intel.com>
 Leonid I Ananiev <leonid.i.ananiev@intel.com>

+ 0 - 1
MAINTAINERS

@@ -9241,7 +9241,6 @@ F:	drivers/net/ethernet/dlink/sundance.c
 
 
 SUPERH
 SUPERH
 L:	linux-sh@vger.kernel.org
 L:	linux-sh@vger.kernel.org
-W:	http://www.linux-sh.org
 Q:	http://patchwork.kernel.org/project/linux-sh/list/
 Q:	http://patchwork.kernel.org/project/linux-sh/list/
 S:	Orphan
 S:	Orphan
 F:	Documentation/sh/
 F:	Documentation/sh/

+ 0 - 7
arch/mn10300/include/asm/cacheflush.h

@@ -159,13 +159,6 @@ extern void flush_icache_range(unsigned long start, unsigned long end);
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
 	memcpy(dst, src, len)
 	memcpy(dst, src, len)
 
 
-/*
- * Internal debugging function
- */
-#ifdef CONFIG_DEBUG_PAGEALLOC
-extern void kernel_map_pages(struct page *page, int numpages, int enable);
-#endif
-
 #endif /* __ASSEMBLY__ */
 #endif /* __ASSEMBLY__ */
 
 
 #endif /* _ASM_CACHEFLUSH_H */
 #endif /* _ASM_CACHEFLUSH_H */

+ 0 - 7
arch/powerpc/include/asm/cacheflush.h

@@ -60,13 +60,6 @@ extern void flush_dcache_phys_range(unsigned long start, unsigned long stop);
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
 	memcpy(dst, src, len)
 	memcpy(dst, src, len)
 
 
-
-
-#ifdef CONFIG_DEBUG_PAGEALLOC
-/* internal debugging function */
-void kernel_map_pages(struct page *page, int numpages, int enable);
-#endif
-
 #endif /* __KERNEL__ */
 #endif /* __KERNEL__ */
 
 
 #endif /* _ASM_POWERPC_CACHEFLUSH_H */
 #endif /* _ASM_POWERPC_CACHEFLUSH_H */

+ 0 - 4
arch/s390/include/asm/cacheflush.h

@@ -4,10 +4,6 @@
 /* Caches aren't brain-dead on the s390. */
 /* Caches aren't brain-dead on the s390. */
 #include <asm-generic/cacheflush.h>
 #include <asm-generic/cacheflush.h>
 
 
-#ifdef CONFIG_DEBUG_PAGEALLOC
-void kernel_map_pages(struct page *page, int numpages, int enable);
-#endif
-
 int set_memory_ro(unsigned long addr, int numpages);
 int set_memory_ro(unsigned long addr, int numpages);
 int set_memory_rw(unsigned long addr, int numpages);
 int set_memory_rw(unsigned long addr, int numpages);
 int set_memory_nx(unsigned long addr, int numpages);
 int set_memory_nx(unsigned long addr, int numpages);

+ 0 - 5
arch/sparc/include/asm/cacheflush_64.h

@@ -74,11 +74,6 @@ void flush_ptrace_access(struct vm_area_struct *, struct page *,
 #define flush_cache_vmap(start, end)		do { } while (0)
 #define flush_cache_vmap(start, end)		do { } while (0)
 #define flush_cache_vunmap(start, end)		do { } while (0)
 #define flush_cache_vunmap(start, end)		do { } while (0)
 
 
-#ifdef CONFIG_DEBUG_PAGEALLOC
-/* internal debugging function */
-void kernel_map_pages(struct page *page, int numpages, int enable);
-#endif
-
 #endif /* !__ASSEMBLY__ */
 #endif /* !__ASSEMBLY__ */
 
 
 #endif /* _SPARC64_CACHEFLUSH_H */
 #endif /* _SPARC64_CACHEFLUSH_H */

+ 0 - 2
fs/nilfs2/nilfs.h

@@ -141,7 +141,6 @@ enum {
  * @ti_save: Backup of journal_info field of task_struct
  * @ti_save: Backup of journal_info field of task_struct
  * @ti_flags: Flags
  * @ti_flags: Flags
  * @ti_count: Nest level
  * @ti_count: Nest level
- * @ti_garbage:	List of inode to be put when releasing semaphore
  */
  */
 struct nilfs_transaction_info {
 struct nilfs_transaction_info {
 	u32			ti_magic;
 	u32			ti_magic;
@@ -150,7 +149,6 @@ struct nilfs_transaction_info {
 				   one of other filesystems has a bug. */
 				   one of other filesystems has a bug. */
 	unsigned short		ti_flags;
 	unsigned short		ti_flags;
 	unsigned short		ti_count;
 	unsigned short		ti_count;
-	struct list_head	ti_garbage;
 };
 };
 
 
 /* ti_magic */
 /* ti_magic */

+ 39 - 5
fs/nilfs2/segment.c

@@ -305,7 +305,6 @@ static void nilfs_transaction_lock(struct super_block *sb,
 	ti->ti_count = 0;
 	ti->ti_count = 0;
 	ti->ti_save = cur_ti;
 	ti->ti_save = cur_ti;
 	ti->ti_magic = NILFS_TI_MAGIC;
 	ti->ti_magic = NILFS_TI_MAGIC;
-	INIT_LIST_HEAD(&ti->ti_garbage);
 	current->journal_info = ti;
 	current->journal_info = ti;
 
 
 	for (;;) {
 	for (;;) {
@@ -332,8 +331,6 @@ static void nilfs_transaction_unlock(struct super_block *sb)
 
 
 	up_write(&nilfs->ns_segctor_sem);
 	up_write(&nilfs->ns_segctor_sem);
 	current->journal_info = ti->ti_save;
 	current->journal_info = ti->ti_save;
-	if (!list_empty(&ti->ti_garbage))
-		nilfs_dispose_list(nilfs, &ti->ti_garbage, 0);
 }
 }
 
 
 static void *nilfs_segctor_map_segsum_entry(struct nilfs_sc_info *sci,
 static void *nilfs_segctor_map_segsum_entry(struct nilfs_sc_info *sci,
@@ -746,6 +743,15 @@ static void nilfs_dispose_list(struct the_nilfs *nilfs,
 	}
 	}
 }
 }
 
 
+static void nilfs_iput_work_func(struct work_struct *work)
+{
+	struct nilfs_sc_info *sci = container_of(work, struct nilfs_sc_info,
+						 sc_iput_work);
+	struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
+
+	nilfs_dispose_list(nilfs, &sci->sc_iput_queue, 0);
+}
+
 static int nilfs_test_metadata_dirty(struct the_nilfs *nilfs,
 static int nilfs_test_metadata_dirty(struct the_nilfs *nilfs,
 				     struct nilfs_root *root)
 				     struct nilfs_root *root)
 {
 {
@@ -1900,8 +1906,8 @@ static int nilfs_segctor_collect_dirty_files(struct nilfs_sc_info *sci,
 static void nilfs_segctor_drop_written_files(struct nilfs_sc_info *sci,
 static void nilfs_segctor_drop_written_files(struct nilfs_sc_info *sci,
 					     struct the_nilfs *nilfs)
 					     struct the_nilfs *nilfs)
 {
 {
-	struct nilfs_transaction_info *ti = current->journal_info;
 	struct nilfs_inode_info *ii, *n;
 	struct nilfs_inode_info *ii, *n;
+	int defer_iput = false;
 
 
 	spin_lock(&nilfs->ns_inode_lock);
 	spin_lock(&nilfs->ns_inode_lock);
 	list_for_each_entry_safe(ii, n, &sci->sc_dirty_files, i_dirty) {
 	list_for_each_entry_safe(ii, n, &sci->sc_dirty_files, i_dirty) {
@@ -1912,9 +1918,24 @@ static void nilfs_segctor_drop_written_files(struct nilfs_sc_info *sci,
 		clear_bit(NILFS_I_BUSY, &ii->i_state);
 		clear_bit(NILFS_I_BUSY, &ii->i_state);
 		brelse(ii->i_bh);
 		brelse(ii->i_bh);
 		ii->i_bh = NULL;
 		ii->i_bh = NULL;
-		list_move_tail(&ii->i_dirty, &ti->ti_garbage);
+		list_del_init(&ii->i_dirty);
+		if (!ii->vfs_inode.i_nlink) {
+			/*
+			 * Defer calling iput() to avoid a deadlock
+			 * over I_SYNC flag for inodes with i_nlink == 0
+			 */
+			list_add_tail(&ii->i_dirty, &sci->sc_iput_queue);
+			defer_iput = true;
+		} else {
+			spin_unlock(&nilfs->ns_inode_lock);
+			iput(&ii->vfs_inode);
+			spin_lock(&nilfs->ns_inode_lock);
+		}
 	}
 	}
 	spin_unlock(&nilfs->ns_inode_lock);
 	spin_unlock(&nilfs->ns_inode_lock);
+
+	if (defer_iput)
+		schedule_work(&sci->sc_iput_work);
 }
 }
 
 
 /*
 /*
@@ -2583,6 +2604,8 @@ static struct nilfs_sc_info *nilfs_segctor_new(struct super_block *sb,
 	INIT_LIST_HEAD(&sci->sc_segbufs);
 	INIT_LIST_HEAD(&sci->sc_segbufs);
 	INIT_LIST_HEAD(&sci->sc_write_logs);
 	INIT_LIST_HEAD(&sci->sc_write_logs);
 	INIT_LIST_HEAD(&sci->sc_gc_inodes);
 	INIT_LIST_HEAD(&sci->sc_gc_inodes);
+	INIT_LIST_HEAD(&sci->sc_iput_queue);
+	INIT_WORK(&sci->sc_iput_work, nilfs_iput_work_func);
 	init_timer(&sci->sc_timer);
 	init_timer(&sci->sc_timer);
 
 
 	sci->sc_interval = HZ * NILFS_SC_DEFAULT_TIMEOUT;
 	sci->sc_interval = HZ * NILFS_SC_DEFAULT_TIMEOUT;
@@ -2609,6 +2632,8 @@ static void nilfs_segctor_write_out(struct nilfs_sc_info *sci)
 		ret = nilfs_segctor_construct(sci, SC_LSEG_SR);
 		ret = nilfs_segctor_construct(sci, SC_LSEG_SR);
 		nilfs_transaction_unlock(sci->sc_super);
 		nilfs_transaction_unlock(sci->sc_super);
 
 
+		flush_work(&sci->sc_iput_work);
+
 	} while (ret && retrycount-- > 0);
 	} while (ret && retrycount-- > 0);
 }
 }
 
 
@@ -2633,6 +2658,9 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci)
 		|| sci->sc_seq_request != sci->sc_seq_done);
 		|| sci->sc_seq_request != sci->sc_seq_done);
 	spin_unlock(&sci->sc_state_lock);
 	spin_unlock(&sci->sc_state_lock);
 
 
+	if (flush_work(&sci->sc_iput_work))
+		flag = true;
+
 	if (flag || !nilfs_segctor_confirm(sci))
 	if (flag || !nilfs_segctor_confirm(sci))
 		nilfs_segctor_write_out(sci);
 		nilfs_segctor_write_out(sci);
 
 
@@ -2642,6 +2670,12 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci)
 		nilfs_dispose_list(nilfs, &sci->sc_dirty_files, 1);
 		nilfs_dispose_list(nilfs, &sci->sc_dirty_files, 1);
 	}
 	}
 
 
+	if (!list_empty(&sci->sc_iput_queue)) {
+		nilfs_warning(sci->sc_super, __func__,
+			      "iput queue is not empty\n");
+		nilfs_dispose_list(nilfs, &sci->sc_iput_queue, 1);
+	}
+
 	WARN_ON(!list_empty(&sci->sc_segbufs));
 	WARN_ON(!list_empty(&sci->sc_segbufs));
 	WARN_ON(!list_empty(&sci->sc_write_logs));
 	WARN_ON(!list_empty(&sci->sc_write_logs));
 
 

+ 5 - 0
fs/nilfs2/segment.h

@@ -26,6 +26,7 @@
 #include <linux/types.h>
 #include <linux/types.h>
 #include <linux/fs.h>
 #include <linux/fs.h>
 #include <linux/buffer_head.h>
 #include <linux/buffer_head.h>
+#include <linux/workqueue.h>
 #include <linux/nilfs2_fs.h>
 #include <linux/nilfs2_fs.h>
 #include "nilfs.h"
 #include "nilfs.h"
 
 
@@ -92,6 +93,8 @@ struct nilfs_segsum_pointer {
  * @sc_nblk_inc: Block count of current generation
  * @sc_nblk_inc: Block count of current generation
  * @sc_dirty_files: List of files to be written
  * @sc_dirty_files: List of files to be written
  * @sc_gc_inodes: List of GC inodes having blocks to be written
  * @sc_gc_inodes: List of GC inodes having blocks to be written
+ * @sc_iput_queue: list of inodes for which iput should be done
+ * @sc_iput_work: work struct to defer iput call
  * @sc_freesegs: array of segment numbers to be freed
  * @sc_freesegs: array of segment numbers to be freed
  * @sc_nfreesegs: number of segments on @sc_freesegs
  * @sc_nfreesegs: number of segments on @sc_freesegs
  * @sc_dsync_inode: inode whose data pages are written for a sync operation
  * @sc_dsync_inode: inode whose data pages are written for a sync operation
@@ -135,6 +138,8 @@ struct nilfs_sc_info {
 
 
 	struct list_head	sc_dirty_files;
 	struct list_head	sc_dirty_files;
 	struct list_head	sc_gc_inodes;
 	struct list_head	sc_gc_inodes;
+	struct list_head	sc_iput_queue;
+	struct work_struct	sc_iput_work;
 
 
 	__u64		       *sc_freesegs;
 	__u64		       *sc_freesegs;
 	size_t			sc_nfreesegs;
 	size_t			sc_nfreesegs;

+ 1 - 1
mm/memcontrol.c

@@ -5773,7 +5773,7 @@ void mem_cgroup_uncharge_list(struct list_head *page_list)
  * mem_cgroup_migrate - migrate a charge to another page
  * mem_cgroup_migrate - migrate a charge to another page
  * @oldpage: currently charged page
  * @oldpage: currently charged page
  * @newpage: page to transfer the charge to
  * @newpage: page to transfer the charge to
- * @lrucare: both pages might be on the LRU already
+ * @lrucare: either or both pages might be on the LRU already
  *
  *
  * Migrate the charge from @oldpage to @newpage.
  * Migrate the charge from @oldpage to @newpage.
  *
  *

+ 1 - 0
mm/nommu.c

@@ -59,6 +59,7 @@
 #endif
 #endif
 
 
 void *high_memory;
 void *high_memory;
+EXPORT_SYMBOL(high_memory);
 struct page *mem_map;
 struct page *mem_map;
 unsigned long max_mapnr;
 unsigned long max_mapnr;
 unsigned long highest_memmap_pfn;
 unsigned long highest_memmap_pfn;

+ 4 - 1
mm/pagewalk.c

@@ -199,7 +199,10 @@ int walk_page_range(unsigned long addr, unsigned long end,
 			 */
 			 */
 			if ((vma->vm_start <= addr) &&
 			if ((vma->vm_start <= addr) &&
 			    (vma->vm_flags & VM_PFNMAP)) {
 			    (vma->vm_flags & VM_PFNMAP)) {
-				next = vma->vm_end;
+				if (walk->pte_hole)
+					err = walk->pte_hole(addr, next, walk);
+				if (err)
+					break;
 				pgd = pgd_offset(walk->mm, next);
 				pgd = pgd_offset(walk->mm, next);
 				continue;
 				continue;
 			}
 			}

+ 1 - 1
mm/shmem.c

@@ -1013,7 +1013,7 @@ static int shmem_replace_page(struct page **pagep, gfp_t gfp,
 		 */
 		 */
 		oldpage = newpage;
 		oldpage = newpage;
 	} else {
 	} else {
-		mem_cgroup_migrate(oldpage, newpage, false);
+		mem_cgroup_migrate(oldpage, newpage, true);
 		lru_cache_add_anon(newpage);
 		lru_cache_add_anon(newpage);
 		*pagep = newpage;
 		*pagep = newpage;
 	}
 	}