forked from mirrors/linux
		
	 7b5a35225b
			
		
	
	
		7b5a35225b
		
	
	
	
	
		
			
			Currently there is not limitation of number of requests in the loop bio list. This can lead into some nasty situations when the caller spawns tons of bio requests taking huge amount of memory. This is even more obvious with discard where blkdev_issue_discard() will submit all bios for the range and wait for them to finish afterwards. On really big loop devices and slow backing file system this can lead to OOM situation as reported by Dave Chinner. With this patch we will wait in loop_make_request() if the number of bios in the loop bio list would exceed 'nr_congestion_on'. We'll wake up the process as we process the bios form the list. Some threshold hysteresis is in place to avoid high frequency oscillation. Signed-off-by: Lukas Czerner <lczerner@redhat.com> Reported-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
		
			
				
	
	
		
			85 lines
		
	
	
	
		
			2.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			85 lines
		
	
	
	
		
			2.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * include/linux/loop.h
 | |
|  *
 | |
|  * Written by Theodore Ts'o, 3/29/93.
 | |
|  *
 | |
|  * Copyright 1993 by Theodore Ts'o.  Redistribution of this file is
 | |
|  * permitted under the GNU General Public License.
 | |
|  */
 | |
| #ifndef _LINUX_LOOP_H
 | |
| #define _LINUX_LOOP_H
 | |
| 
 | |
| #include <linux/bio.h>
 | |
| #include <linux/blkdev.h>
 | |
| #include <linux/spinlock.h>
 | |
| #include <linux/mutex.h>
 | |
| #include <uapi/linux/loop.h>
 | |
| 
 | |
| /* Possible states of device */
 | |
| enum {
 | |
| 	Lo_unbound,
 | |
| 	Lo_bound,
 | |
| 	Lo_rundown,
 | |
| };
 | |
| 
 | |
| struct loop_func_table;
 | |
| 
 | |
| struct loop_device {
 | |
| 	int		lo_number;
 | |
| 	int		lo_refcnt;
 | |
| 	loff_t		lo_offset;
 | |
| 	loff_t		lo_sizelimit;
 | |
| 	int		lo_flags;
 | |
| 	int		(*transfer)(struct loop_device *, int cmd,
 | |
| 				    struct page *raw_page, unsigned raw_off,
 | |
| 				    struct page *loop_page, unsigned loop_off,
 | |
| 				    int size, sector_t real_block);
 | |
| 	char		lo_file_name[LO_NAME_SIZE];
 | |
| 	char		lo_crypt_name[LO_NAME_SIZE];
 | |
| 	char		lo_encrypt_key[LO_KEY_SIZE];
 | |
| 	int		lo_encrypt_key_size;
 | |
| 	struct loop_func_table *lo_encryption;
 | |
| 	__u32           lo_init[2];
 | |
| 	kuid_t		lo_key_owner;	/* Who set the key */
 | |
| 	int		(*ioctl)(struct loop_device *, int cmd, 
 | |
| 				 unsigned long arg); 
 | |
| 
 | |
| 	struct file *	lo_backing_file;
 | |
| 	struct block_device *lo_device;
 | |
| 	unsigned	lo_blocksize;
 | |
| 	void		*key_data; 
 | |
| 
 | |
| 	gfp_t		old_gfp_mask;
 | |
| 
 | |
| 	spinlock_t		lo_lock;
 | |
| 	struct bio_list		lo_bio_list;
 | |
| 	unsigned int		lo_bio_count;
 | |
| 	int			lo_state;
 | |
| 	struct mutex		lo_ctl_mutex;
 | |
| 	struct task_struct	*lo_thread;
 | |
| 	wait_queue_head_t	lo_event;
 | |
| 	/* wait queue for incoming requests */
 | |
| 	wait_queue_head_t	lo_req_wait;
 | |
| 
 | |
| 	struct request_queue	*lo_queue;
 | |
| 	struct gendisk		*lo_disk;
 | |
| };
 | |
| 
 | |
| /* Support for loadable transfer modules */
 | |
| struct loop_func_table {
 | |
| 	int number;	/* filter type */ 
 | |
| 	int (*transfer)(struct loop_device *lo, int cmd,
 | |
| 			struct page *raw_page, unsigned raw_off,
 | |
| 			struct page *loop_page, unsigned loop_off,
 | |
| 			int size, sector_t real_block);
 | |
| 	int (*init)(struct loop_device *, const struct loop_info64 *); 
 | |
| 	/* release is called from loop_unregister_transfer or clr_fd */
 | |
| 	int (*release)(struct loop_device *); 
 | |
| 	int (*ioctl)(struct loop_device *, int cmd, unsigned long arg);
 | |
| 	struct module *owner;
 | |
| }; 
 | |
| 
 | |
| int loop_register_transfer(struct loop_func_table *funcs);
 | |
| int loop_unregister_transfer(int number); 
 | |
| 
 | |
| #endif
 |