@@ -209,76 +209,99 @@ static struct md_rdev *next_active_rdev(struct md_rdev *rdev, struct mddev *mdde
209209 return NULL ;
210210}
211211
212- static int write_sb_page (struct bitmap * bitmap , struct page * page , int wait )
212+ static unsigned int optimal_io_size (struct block_device * bdev ,
213+ unsigned int last_page_size ,
214+ unsigned int io_size )
215+ {
216+ if (bdev_io_opt (bdev ) > bdev_logical_block_size (bdev ))
217+ return roundup (last_page_size , bdev_io_opt (bdev ));
218+ return io_size ;
219+ }
220+
221+ static unsigned int bitmap_io_size (unsigned int io_size , unsigned int opt_size ,
222+ sector_t start , sector_t boundary )
223+ {
224+ if (io_size != opt_size &&
225+ start + opt_size / SECTOR_SIZE <= boundary )
226+ return opt_size ;
227+ if (start + io_size / SECTOR_SIZE <= boundary )
228+ return io_size ;
229+
230+ /* Overflows boundary */
231+ return 0 ;
232+ }
233+
234+ static int __write_sb_page (struct md_rdev * rdev , struct bitmap * bitmap ,
235+ struct page * page )
213236{
214- struct md_rdev * rdev ;
215237 struct block_device * bdev ;
216238 struct mddev * mddev = bitmap -> mddev ;
217239 struct bitmap_storage * store = & bitmap -> storage ;
240+ sector_t offset = mddev -> bitmap_info .offset ;
241+ sector_t ps , sboff , doff ;
242+ unsigned int size = PAGE_SIZE ;
243+ unsigned int opt_size = PAGE_SIZE ;
244+
245+ bdev = (rdev -> meta_bdev ) ? rdev -> meta_bdev : rdev -> bdev ;
246+ if (page -> index == store -> file_pages - 1 ) {
247+ unsigned int last_page_size = store -> bytes & (PAGE_SIZE - 1 );
248+
249+ if (last_page_size == 0 )
250+ last_page_size = PAGE_SIZE ;
251+ size = roundup (last_page_size , bdev_logical_block_size (bdev ));
252+ opt_size = optimal_io_size (bdev , last_page_size , size );
253+ }
254+
255+ ps = page -> index * PAGE_SIZE / SECTOR_SIZE ;
256+ sboff = rdev -> sb_start + offset ;
257+ doff = rdev -> data_offset ;
258+
259+ /* Just make sure we aren't corrupting data or metadata */
260+ if (mddev -> external ) {
261+ /* Bitmap could be anywhere. */
262+ if (sboff + ps > doff &&
263+ sboff < (doff + mddev -> dev_sectors + PAGE_SIZE / SECTOR_SIZE ))
264+ return - EINVAL ;
265+ } else if (offset < 0 ) {
266+ /* DATA BITMAP METADATA */
267+ size = bitmap_io_size (size , opt_size , offset + ps , 0 );
268+ if (size == 0 )
269+ /* bitmap runs in to metadata */
270+ return - EINVAL ;
271+
272+ if (doff + mddev -> dev_sectors > sboff )
273+ /* data runs in to bitmap */
274+ return - EINVAL ;
275+ } else if (rdev -> sb_start < rdev -> data_offset ) {
276+ /* METADATA BITMAP DATA */
277+ size = bitmap_io_size (size , opt_size , sboff + ps , doff );
278+ if (size == 0 )
279+ /* bitmap runs in to data */
280+ return - EINVAL ;
281+ } else {
282+ /* DATA METADATA BITMAP - no problems */
283+ }
218284
219- restart :
220- rdev = NULL ;
221- while ((rdev = next_active_rdev (rdev , mddev )) != NULL ) {
222- int size = PAGE_SIZE ;
223- loff_t offset = mddev -> bitmap_info .offset ;
285+ md_super_write (mddev , rdev , sboff + ps , (int ) size , page );
286+ return 0 ;
287+ }
224288
225- bdev = (rdev -> meta_bdev ) ? rdev -> meta_bdev : rdev -> bdev ;
289+ static int write_sb_page (struct bitmap * bitmap , struct page * page , int wait )
290+ {
291+ struct md_rdev * rdev ;
292+ struct mddev * mddev = bitmap -> mddev ;
293+ int ret ;
226294
227- if (page -> index == store -> file_pages - 1 ) {
228- int last_page_size = store -> bytes & (PAGE_SIZE - 1 );
229- if (last_page_size == 0 )
230- last_page_size = PAGE_SIZE ;
231- size = roundup (last_page_size ,
232- bdev_logical_block_size (bdev ));
233- }
234- /* Just make sure we aren't corrupting data or
235- * metadata
236- */
237- if (mddev -> external ) {
238- /* Bitmap could be anywhere. */
239- if (rdev -> sb_start + offset + (page -> index
240- * (PAGE_SIZE /512 ))
241- > rdev -> data_offset
242- &&
243- rdev -> sb_start + offset
244- < (rdev -> data_offset + mddev -> dev_sectors
245- + (PAGE_SIZE /512 )))
246- goto bad_alignment ;
247- } else if (offset < 0 ) {
248- /* DATA BITMAP METADATA */
249- if (offset
250- + (long )(page -> index * (PAGE_SIZE /512 ))
251- + size /512 > 0 )
252- /* bitmap runs in to metadata */
253- goto bad_alignment ;
254- if (rdev -> data_offset + mddev -> dev_sectors
255- > rdev -> sb_start + offset )
256- /* data runs in to bitmap */
257- goto bad_alignment ;
258- } else if (rdev -> sb_start < rdev -> data_offset ) {
259- /* METADATA BITMAP DATA */
260- if (rdev -> sb_start
261- + offset
262- + page -> index * (PAGE_SIZE /512 ) + size /512
263- > rdev -> data_offset )
264- /* bitmap runs in to data */
265- goto bad_alignment ;
266- } else {
267- /* DATA METADATA BITMAP - no problems */
295+ do {
296+ rdev = NULL ;
297+ while ((rdev = next_active_rdev (rdev , mddev )) != NULL ) {
298+ ret = __write_sb_page (rdev , bitmap , page );
299+ if (ret )
300+ return ret ;
268301 }
269- md_super_write (mddev , rdev ,
270- rdev -> sb_start + offset
271- + page -> index * (PAGE_SIZE /512 ),
272- size ,
273- page );
274- }
302+ } while (wait && md_super_wait (mddev ) < 0 );
275303
276- if (wait && md_super_wait (mddev ) < 0 )
277- goto restart ;
278304 return 0 ;
279-
280- bad_alignment :
281- return - EINVAL ;
282305}
283306
284307static void md_bitmap_file_kick (struct bitmap * bitmap );
0 commit comments