History

block: loop: prepare for supporing direct IO

This patches provides one interface for enabling direct IO from user space: - userspace(such as losetup) can pass 'file' which is opened/fcntl as O_DIRECT Also __loop_update_dio() is introduced to check if direct I/O can be used on current loop setting. The last big change is to introduce LO_FLAGS_DIRECT_IO flag for userspace to know if direct IO is used to access backing file.

Ming Lei committed 11 years ago

Commit 2e5ab5f1 parent e03a3d73 files · +79 −0Browse files

Unified · Split

3 files
  1. drivers/block/loop.c +77 −0
  2. drivers/block/loop.h +1 −0
  3. include/uapi/linux/loop.h +1 −0
drivers/block/loop.c+77−0
@@ -164,6 +164,62 @@ static loff_t get_loop_size(struct loop_device *lo, struct file *file) · 163 unmodified lines
164 return get_size(lo->lo_offset, lo->lo_sizelimit, file);164 return get_size(lo->lo_offset, lo->lo_sizelimit, file);
165}165}
166 166
167static void __loop_update_dio(struct loop_device *lo, bool dio)
168{
169 struct file *file = lo->lo_backing_file;
170 struct address_space *mapping = file->f_mapping;
171 struct inode *inode = mapping->host;
172 unsigned short sb_bsize = 0;
173 unsigned dio_align = 0;
174 bool use_dio;
175
176 if (inode->i_sb->s_bdev) {
177 sb_bsize = bdev_logical_block_size(inode->i_sb->s_bdev);
178 dio_align = sb_bsize - 1;
179 }
180
181 /*
182 * We support direct I/O only if lo_offset is aligned with the
183 * logical I/O size of backing device, and the logical block
184 * size of loop is bigger than the backing device's and the loop
185 * needn't transform transfer.
186 *
187 * TODO: the above condition may be loosed in the future, and
188 * direct I/O may be switched runtime at that time because most
189 * of requests in sane appplications should be PAGE_SIZE algined
190 */
191 if (dio) {
192 if (queue_logical_block_size(lo->lo_queue) >= sb_bsize &&
193 !(lo->lo_offset & dio_align) &&
194 mapping->a_ops->direct_IO &&
195 !lo->transfer)
196 use_dio = true;
197 else
198 use_dio = false;
199 } else {
200 use_dio = false;
201 }
202
203 if (lo->use_dio == use_dio)
204 return;
205
206 /* flush dirty pages before changing direct IO */
207 vfs_fsync(file, 0);
208
209 /*
210 * The flag of LO_FLAGS_DIRECT_IO is handled similarly with
211 * LO_FLAGS_READ_ONLY, both are set from kernel, and losetup
212 * will get updated by ioctl(LOOP_GET_STATUS)
213 */
214 blk_mq_freeze_queue(lo->lo_queue);
215 lo->use_dio = use_dio;
216 if (use_dio)
217 lo->lo_flags |= LO_FLAGS_DIRECT_IO;
218 else
219 lo->lo_flags &= ~LO_FLAGS_DIRECT_IO;
220 blk_mq_unfreeze_queue(lo->lo_queue);
221}
222
167static int223static int
168figure_loop_size(struct loop_device *lo, loff_t offset, loff_t sizelimit)224figure_loop_size(struct loop_device *lo, loff_t offset, loff_t sizelimit)
169{225{
@@ -421,6 +477,12 @@ struct switch_request { · 251 unmodified lines
421 struct completion wait;477 struct completion wait;
422};478};
423 479
480static inline void loop_update_dio(struct loop_device *lo)
481{
482 __loop_update_dio(lo, io_is_direct(lo->lo_backing_file) |
483 lo->use_dio);
484}
485
424/*486/*
425 * Do the actual switch; called from the BIO completion routine487 * Do the actual switch; called from the BIO completion routine
426 */488 */
@@ -441,6 +503,7 @@ static void do_loop_switch(struct loop_device *lo, struct switch_request *p) · 14 unmodified lines
441 mapping->host->i_bdev->bd_block_size : PAGE_SIZE;503 mapping->host->i_bdev->bd_block_size : PAGE_SIZE;
442 lo->old_gfp_mask = mapping_gfp_mask(mapping);504 lo->old_gfp_mask = mapping_gfp_mask(mapping);
443 mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));505 mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
506 loop_update_dio(lo);
444}507}
445 508
446/*509/*
@@ -627,11 +690,19 @@ static ssize_t loop_attr_partscan_show(struct loop_device *lo, char *buf) · 180 unmodified lines
627 return sprintf(buf, "%s\n", partscan ? "1" : "0");690 return sprintf(buf, "%s\n", partscan ? "1" : "0");
628}691}
629 692
693static ssize_t loop_attr_dio_show(struct loop_device *lo, char *buf)
694{
695 int dio = (lo->lo_flags & LO_FLAGS_DIRECT_IO);
696
697 return sprintf(buf, "%s\n", dio ? "1" : "0");
698}
699
630LOOP_ATTR_RO(backing_file);700LOOP_ATTR_RO(backing_file);
631LOOP_ATTR_RO(offset);701LOOP_ATTR_RO(offset);
632LOOP_ATTR_RO(sizelimit);702LOOP_ATTR_RO(sizelimit);
633LOOP_ATTR_RO(autoclear);703LOOP_ATTR_RO(autoclear);
634LOOP_ATTR_RO(partscan);704LOOP_ATTR_RO(partscan);
705LOOP_ATTR_RO(dio);
635 706
636static struct attribute *loop_attrs[] = {707static struct attribute *loop_attrs[] = {
637 &loop_attr_backing_file.attr,708 &loop_attr_backing_file.attr,
@@ -639,6 +710,7 @@ static struct attribute *loop_attrs[] = { · 1 unmodified line
639 &loop_attr_sizelimit.attr,710 &loop_attr_sizelimit.attr,
640 &loop_attr_autoclear.attr,711 &loop_attr_autoclear.attr,
641 &loop_attr_partscan.attr,712 &loop_attr_partscan.attr,
713 &loop_attr_dio.attr,
642 NULL,714 NULL,
643};715};
644 716
@@ -770,6 +842,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, · 125 unmodified lines
770 842
771 set_device_ro(bdev, (lo_flags & LO_FLAGS_READ_ONLY) != 0);843 set_device_ro(bdev, (lo_flags & LO_FLAGS_READ_ONLY) != 0);
772 844
845 lo->use_dio = false;
773 lo->lo_blocksize = lo_blocksize;846 lo->lo_blocksize = lo_blocksize;
774 lo->lo_device = bdev;847 lo->lo_device = bdev;
775 lo->lo_flags = lo_flags;848 lo->lo_flags = lo_flags;
@@ -783,6 +856,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, · 7 unmodified lines
783 if (!(lo_flags & LO_FLAGS_READ_ONLY) && file->f_op->fsync)856 if (!(lo_flags & LO_FLAGS_READ_ONLY) && file->f_op->fsync)
784 blk_queue_flush(lo->lo_queue, REQ_FLUSH);857 blk_queue_flush(lo->lo_queue, REQ_FLUSH);
785 858
859 loop_update_dio(lo);
786 set_capacity(lo->lo_disk, size);860 set_capacity(lo->lo_disk, size);
787 bd_set_size(bdev, size << 9);861 bd_set_size(bdev, size << 9);
788 loop_sysfs_init(lo);862 loop_sysfs_init(lo);
@@ -1001,6 +1075,9 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) · 212 unmodified lines
1001 lo->lo_key_owner = uid;1075 lo->lo_key_owner = uid;
1002 }1076 }
1003 1077
1078 /* update dio if lo_offset or transfer is changed */
1079 __loop_update_dio(lo, lo->use_dio);
1080
1004 return 0;1081 return 0;
1005}1082}
1006 1083
drivers/block/loop.h+1−0
@@ -58,6 +58,7 @@ struct loop_device { · 57 unmodified lines
58 struct mutex lo_ctl_mutex;58 struct mutex lo_ctl_mutex;
59 struct kthread_worker worker;59 struct kthread_worker worker;
60 struct task_struct *worker_task;60 struct task_struct *worker_task;
61 bool use_dio;
61 62
62 struct request_queue *lo_queue;63 struct request_queue *lo_queue;
63 struct blk_mq_tag_set tag_set;64 struct blk_mq_tag_set tag_set;
include/uapi/linux/loop.h+1−0
@@ -21,6 +21,7 @@ enum { · 20 unmodified lines
21 LO_FLAGS_READ_ONLY = 1,21 LO_FLAGS_READ_ONLY = 1,
22 LO_FLAGS_AUTOCLEAR = 4,22 LO_FLAGS_AUTOCLEAR = 4,
23 LO_FLAGS_PARTSCAN = 8,23 LO_FLAGS_PARTSCAN = 8,
24 LO_FLAGS_DIRECT_IO = 16,
24};25};
25 26
26#include <asm/posix_types.h> /* for __kernel_old_dev_t */27#include <asm/posix_types.h> /* for __kernel_old_dev_t */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t