diff options
| -rw-r--r-- | fs/xfs/xfs_buf.c | 5 | ||||
| -rw-r--r-- | fs/xfs/xfs_buf.h | 15 | ||||
| -rw-r--r-- | fs/xfs/xfs_file.c | 7 | ||||
| -rw-r--r-- | fs/xfs/xfs_ioctl.c | 2 |
4 files changed, 26 insertions, 3 deletions
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index a526f8d2dc6f..51757113a822 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c | |||
| @@ -1599,6 +1599,7 @@ xfs_setsize_buftarg( | |||
| 1599 | unsigned int blocksize, | 1599 | unsigned int blocksize, |
| 1600 | unsigned int sectorsize) | 1600 | unsigned int sectorsize) |
| 1601 | { | 1601 | { |
| 1602 | /* Set up metadata sector size info */ | ||
| 1602 | btp->bt_meta_sectorsize = sectorsize; | 1603 | btp->bt_meta_sectorsize = sectorsize; |
| 1603 | btp->bt_meta_sectormask = sectorsize - 1; | 1604 | btp->bt_meta_sectormask = sectorsize - 1; |
| 1604 | 1605 | ||
| @@ -1613,6 +1614,10 @@ xfs_setsize_buftarg( | |||
| 1613 | return EINVAL; | 1614 | return EINVAL; |
| 1614 | } | 1615 | } |
| 1615 | 1616 | ||
| 1617 | /* Set up device logical sector size mask */ | ||
| 1618 | btp->bt_logical_sectorsize = bdev_logical_block_size(btp->bt_bdev); | ||
| 1619 | btp->bt_logical_sectormask = bdev_logical_block_size(btp->bt_bdev) - 1; | ||
| 1620 | |||
| 1616 | return 0; | 1621 | return 0; |
| 1617 | } | 1622 | } |
| 1618 | 1623 | ||
diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h index d5d88dda4d31..995339534db6 100644 --- a/fs/xfs/xfs_buf.h +++ b/fs/xfs/xfs_buf.h | |||
| @@ -88,6 +88,19 @@ typedef unsigned int xfs_buf_flags_t; | |||
| 88 | */ | 88 | */ |
| 89 | #define XFS_BSTATE_DISPOSE (1 << 0) /* buffer being discarded */ | 89 | #define XFS_BSTATE_DISPOSE (1 << 0) /* buffer being discarded */ |
| 90 | 90 | ||
| 91 | /* | ||
| 92 | * The xfs_buftarg contains 2 notions of "sector size" - | ||
| 93 | * | ||
| 94 | * 1) The metadata sector size, which is the minimum unit and | ||
| 95 | * alignment of IO which will be performed by metadata operations. | ||
| 96 | * 2) The device logical sector size | ||
| 97 | * | ||
| 98 | * The first is specified at mkfs time, and is stored on-disk in the | ||
| 99 | * superblock's sb_sectsize. | ||
| 100 | * | ||
| 101 | * The latter is derived from the underlying device, and controls direct IO | ||
| 102 | * alignment constraints. | ||
| 103 | */ | ||
| 91 | typedef struct xfs_buftarg { | 104 | typedef struct xfs_buftarg { |
| 92 | dev_t bt_dev; | 105 | dev_t bt_dev; |
| 93 | struct block_device *bt_bdev; | 106 | struct block_device *bt_bdev; |
| @@ -95,6 +108,8 @@ typedef struct xfs_buftarg { | |||
| 95 | struct xfs_mount *bt_mount; | 108 | struct xfs_mount *bt_mount; |
| 96 | unsigned int bt_meta_sectorsize; | 109 | unsigned int bt_meta_sectorsize; |
| 97 | size_t bt_meta_sectormask; | 110 | size_t bt_meta_sectormask; |
| 111 | size_t bt_logical_sectorsize; | ||
| 112 | size_t bt_logical_sectormask; | ||
| 98 | 113 | ||
| 99 | /* LRU control structures */ | 114 | /* LRU control structures */ |
| 100 | struct shrinker bt_shrinker; | 115 | struct shrinker bt_shrinker; |
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index d01745f748ac..2e7989e3a2d6 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c | |||
| @@ -261,7 +261,8 @@ xfs_file_aio_read( | |||
| 261 | xfs_buftarg_t *target = | 261 | xfs_buftarg_t *target = |
| 262 | XFS_IS_REALTIME_INODE(ip) ? | 262 | XFS_IS_REALTIME_INODE(ip) ? |
| 263 | mp->m_rtdev_targp : mp->m_ddev_targp; | 263 | mp->m_rtdev_targp : mp->m_ddev_targp; |
| 264 | if ((pos | size) & target->bt_meta_sectormask) { | 264 | /* DIO must be aligned to device logical sector size */ |
| 265 | if ((pos | size) & target->bt_logical_sectormask) { | ||
| 265 | if (pos == i_size_read(inode)) | 266 | if (pos == i_size_read(inode)) |
| 266 | return 0; | 267 | return 0; |
| 267 | return -XFS_ERROR(EINVAL); | 268 | return -XFS_ERROR(EINVAL); |
| @@ -641,9 +642,11 @@ xfs_file_dio_aio_write( | |||
| 641 | struct xfs_buftarg *target = XFS_IS_REALTIME_INODE(ip) ? | 642 | struct xfs_buftarg *target = XFS_IS_REALTIME_INODE(ip) ? |
| 642 | mp->m_rtdev_targp : mp->m_ddev_targp; | 643 | mp->m_rtdev_targp : mp->m_ddev_targp; |
| 643 | 644 | ||
| 644 | if ((pos | count) & target->bt_meta_sectormask) | 645 | /* DIO must be aligned to device logical sector size */ |
| 646 | if ((pos | count) & target->bt_logical_sectormask) | ||
| 645 | return -XFS_ERROR(EINVAL); | 647 | return -XFS_ERROR(EINVAL); |
| 646 | 648 | ||
| 649 | /* "unaligned" here means not aligned to a filesystem block */ | ||
| 647 | if ((pos & mp->m_blockmask) || ((pos + count) & mp->m_blockmask)) | 650 | if ((pos & mp->m_blockmask) || ((pos + count) & mp->m_blockmask)) |
| 648 | unaligned_io = 1; | 651 | unaligned_io = 1; |
| 649 | 652 | ||
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 3dc60ed9572a..bcfe61202115 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c | |||
| @@ -1583,7 +1583,7 @@ xfs_file_ioctl( | |||
| 1583 | XFS_IS_REALTIME_INODE(ip) ? | 1583 | XFS_IS_REALTIME_INODE(ip) ? |
| 1584 | mp->m_rtdev_targp : mp->m_ddev_targp; | 1584 | mp->m_rtdev_targp : mp->m_ddev_targp; |
| 1585 | 1585 | ||
| 1586 | da.d_mem = da.d_miniosz = target->bt_meta_sectorsize; | 1586 | da.d_mem = da.d_miniosz = target->bt_logical_sectorsize; |
| 1587 | da.d_maxiosz = INT_MAX & ~(da.d_miniosz - 1); | 1587 | da.d_maxiosz = INT_MAX & ~(da.d_miniosz - 1); |
| 1588 | 1588 | ||
| 1589 | if (copy_to_user(arg, &da, sizeof(da))) | 1589 | if (copy_to_user(arg, &da, sizeof(da))) |
