Subject: [PATCH 32/40] block: add a swapdev callback to the request_queue

From: Peter Zijlstra <[email-masked]>
Date: Fri, 04 May 2007 12:27:23 +0200

Networked storage devices need a swap-on/off callback in order to setup
some state and reserve memory. Place the block device callback in the
request_queue as suggested by James Bottomley.

Signed-off-by: Peter Zijlstra <[email-masked]>
Cc: Jens Axboe <[email-masked]>
Cc: James Bottomley <[email-masked]>
---
 include/linux/blkdev.h |   19 +++++++++++++++++++
 mm/swapfile.c          |    4 ++++
 2 files changed, 23 insertions(+)

Index: linux-2.6-git/include/linux/blkdev.h
===================================================================
--- linux-2.6-git.orig/include/linux/blkdev.h	2007-01-08 11:53:13.000000000 +0100
+++ linux-2.6-git/include/linux/blkdev.h	2007-01-16 14:14:50.000000000 +0100
@@ -341,6 +341,7 @@ typedef int (merge_bvec_fn) (request_que
 typedef int (issue_flush_fn) (request_queue_t *, struct gendisk *, sector_t *);
 typedef void (prepare_flush_fn) (request_queue_t *, struct request *);
 typedef void (softirq_done_fn)(struct request *);
+typedef int (swapdev_fn)(void*, int);
 
 enum blk_queue_state {
 	Queue_down,
@@ -379,6 +380,8 @@ struct request_queue
 	issue_flush_fn		*issue_flush_fn;
 	prepare_flush_fn	*prepare_flush_fn;
 	softirq_done_fn		*softirq_done_fn;
+	swapdev_fn		*swapdev_fn;
+	void			*swapdev_obj;
 
 	/*
 	 * Dispatch queue sorting
@@ -766,6 +769,22 @@ request_queue_t *blk_alloc_queue(gfp_t);
 request_queue_t *blk_alloc_queue_node(gfp_t, int);
 extern void blk_put_queue(request_queue_t *);
 
+static inline
+void blk_queue_swapdev(struct request_queue *rq,
+		       swapdev_fn *swapdev_fn, void *swapdev_obj)
+{
+	rq->swapdev_fn = swapdev_fn;
+	rq->swapdev_obj = swapdev_obj;
+}
+
+static inline
+int blk_queue_swapdev_fn(struct request_queue *rq, int enable)
+{
+	if (rq->swapdev_fn)
+		return rq->swapdev_fn(rq->swapdev_obj, enable);
+	return 0;
+}
+
 /*
  * tag stuff
  */
Index: linux-2.6-git/mm/swapfile.c
===================================================================
--- linux-2.6-git.orig/mm/swapfile.c	2007-01-15 09:59:02.000000000 +0100
+++ linux-2.6-git/mm/swapfile.c	2007-01-16 14:14:50.000000000 +0100
@@ -1305,6 +1305,7 @@ asmlinkage long sys_swapoff(const char _
 	inode = mapping->host;
 	if (S_ISBLK(inode->i_mode)) {
 		struct block_device *bdev = I_BDEV(inode);
+		blk_queue_swapdev_fn(bdev->bd_disk->queue, 0);
 		set_blocksize(bdev, p->old_block_size);
 		bd_release(bdev);
 	} else {
@@ -1524,6 +1525,9 @@ asmlinkage long sys_swapon(const char __
 		error = set_blocksize(bdev, PAGE_SIZE);
 		if (error < 0)
 			goto bad_swap;
+		error = blk_queue_swapdev_fn(bdev->bd_disk->queue, 1);
+		if (error < 0)
+			goto bad_swap;
 		p->bdev = bdev;
 	} else if (S_ISREG(inode->i_mode)) {
 		p->bdev = inode->i_sb->s_bdev;

--