diff options
Diffstat (limited to 'block/ll_rw_blk.c')
-rw-r--r-- | block/ll_rw_blk.c | 63 |
1 files changed, 33 insertions, 30 deletions
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 8904f8b1f417..548f0d826679 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c | |||
@@ -3120,6 +3120,35 @@ static inline int should_fail_request(struct bio *bio) | |||
3120 | 3120 | ||
3121 | #endif /* CONFIG_FAIL_MAKE_REQUEST */ | 3121 | #endif /* CONFIG_FAIL_MAKE_REQUEST */ |
3122 | 3122 | ||
3123 | /* | ||
3124 | * Check whether this bio extends beyond the end of the device. | ||
3125 | */ | ||
3126 | static inline int bio_check_eod(struct bio *bio, unsigned int nr_sectors) | ||
3127 | { | ||
3128 | sector_t maxsector; | ||
3129 | |||
3130 | if (!nr_sectors) | ||
3131 | return 0; | ||
3132 | |||
3133 | /* Test device or partition size, when known. */ | ||
3134 | maxsector = bio->bi_bdev->bd_inode->i_size >> 9; | ||
3135 | if (maxsector) { | ||
3136 | sector_t sector = bio->bi_sector; | ||
3137 | |||
3138 | if (maxsector < nr_sectors || maxsector - nr_sectors < sector) { | ||
3139 | /* | ||
3140 | * This may well happen - the kernel calls bread() | ||
3141 | * without checking the size of the device, e.g., when | ||
3142 | * mounting a device. | ||
3143 | */ | ||
3144 | handle_bad_sector(bio); | ||
3145 | return 1; | ||
3146 | } | ||
3147 | } | ||
3148 | |||
3149 | return 0; | ||
3150 | } | ||
3151 | |||
3123 | /** | 3152 | /** |
3124 | * generic_make_request: hand a buffer to its device driver for I/O | 3153 | * generic_make_request: hand a buffer to its device driver for I/O |
3125 | * @bio: The bio describing the location in memory and on the device. | 3154 | * @bio: The bio describing the location in memory and on the device. |
@@ -3147,27 +3176,14 @@ static inline int should_fail_request(struct bio *bio) | |||
3147 | static inline void __generic_make_request(struct bio *bio) | 3176 | static inline void __generic_make_request(struct bio *bio) |
3148 | { | 3177 | { |
3149 | struct request_queue *q; | 3178 | struct request_queue *q; |
3150 | sector_t maxsector; | ||
3151 | sector_t old_sector; | 3179 | sector_t old_sector; |
3152 | int ret, nr_sectors = bio_sectors(bio); | 3180 | int ret, nr_sectors = bio_sectors(bio); |
3153 | dev_t old_dev; | 3181 | dev_t old_dev; |
3154 | 3182 | ||
3155 | might_sleep(); | 3183 | might_sleep(); |
3156 | /* Test device or partition size, when known. */ | ||
3157 | maxsector = bio->bi_bdev->bd_inode->i_size >> 9; | ||
3158 | if (maxsector) { | ||
3159 | sector_t sector = bio->bi_sector; | ||
3160 | 3184 | ||
3161 | if (maxsector < nr_sectors || maxsector - nr_sectors < sector) { | 3185 | if (bio_check_eod(bio, nr_sectors)) |
3162 | /* | 3186 | goto end_io; |
3163 | * This may well happen - the kernel calls bread() | ||
3164 | * without checking the size of the device, e.g., when | ||
3165 | * mounting a device. | ||
3166 | */ | ||
3167 | handle_bad_sector(bio); | ||
3168 | goto end_io; | ||
3169 | } | ||
3170 | } | ||
3171 | 3187 | ||
3172 | /* | 3188 | /* |
3173 | * Resolve the mapping until finished. (drivers are | 3189 | * Resolve the mapping until finished. (drivers are |
@@ -3223,21 +3239,8 @@ end_io: | |||
3223 | old_sector = bio->bi_sector; | 3239 | old_sector = bio->bi_sector; |
3224 | old_dev = bio->bi_bdev->bd_dev; | 3240 | old_dev = bio->bi_bdev->bd_dev; |
3225 | 3241 | ||
3226 | maxsector = bio->bi_bdev->bd_inode->i_size >> 9; | 3242 | if (bio_check_eod(bio, nr_sectors)) |
3227 | if (maxsector) { | 3243 | goto end_io; |
3228 | sector_t sector = bio->bi_sector; | ||
3229 | |||
3230 | if (maxsector < nr_sectors || | ||
3231 | maxsector - nr_sectors < sector) { | ||
3232 | /* | ||
3233 | * This may well happen - partitions are not | ||
3234 | * checked to make sure they are within the size | ||
3235 | * of the whole device. | ||
3236 | */ | ||
3237 | handle_bad_sector(bio); | ||
3238 | goto end_io; | ||
3239 | } | ||
3240 | } | ||
3241 | 3244 | ||
3242 | ret = q->make_request_fn(q, bio); | 3245 | ret = q->make_request_fn(q, bio); |
3243 | } while (ret); | 3246 | } while (ret); |