unsigned int            blocksize,
        unsigned int            sectorsize)
 {
+       /* Set up metadata sector size info */
        btp->bt_meta_sectorsize = sectorsize;
        btp->bt_meta_sectormask = sectorsize - 1;
 
                return EINVAL;
        }
 
+       /* Set up device logical sector size mask */
+       btp->bt_logical_sectorsize = bdev_logical_block_size(btp->bt_bdev);
+       btp->bt_logical_sectormask = bdev_logical_block_size(btp->bt_bdev) - 1;
+
        return 0;
 }
 
 
  */
 #define XFS_BSTATE_DISPOSE      (1 << 0)       /* buffer being discarded */
 
+/*
+ * The xfs_buftarg contains 2 notions of "sector size" -
+ *
+ * 1) The metadata sector size, which is the minimum unit and
+ *    alignment of IO which will be performed by metadata operations.
+ * 2) The device logical sector size
+ *
+ * The first is specified at mkfs time, and is stored on-disk in the
+ * superblock's sb_sectsize.
+ *
+ * The latter is derived from the underlying device, and controls direct IO
+ * alignment constraints.
+ */
 typedef struct xfs_buftarg {
        dev_t                   bt_dev;
        struct block_device     *bt_bdev;
        struct xfs_mount        *bt_mount;
        unsigned int            bt_meta_sectorsize;
        size_t                  bt_meta_sectormask;
+       size_t                  bt_logical_sectorsize;
+       size_t                  bt_logical_sectormask;
 
        /* LRU control structures */
        struct shrinker         bt_shrinker;
 
                xfs_buftarg_t   *target =
                        XFS_IS_REALTIME_INODE(ip) ?
                                mp->m_rtdev_targp : mp->m_ddev_targp;
-               if ((pos | size) & target->bt_meta_sectormask) {
+               /* DIO must be aligned to device logical sector size */
+               if ((pos | size) & target->bt_logical_sectormask) {
                        if (pos == i_size_read(inode))
                                return 0;
                        return -XFS_ERROR(EINVAL);
        struct xfs_buftarg      *target = XFS_IS_REALTIME_INODE(ip) ?
                                        mp->m_rtdev_targp : mp->m_ddev_targp;
 
-       if ((pos | count) & target->bt_meta_sectormask)
+       /* DIO must be aligned to device logical sector size */
+       if ((pos | count) & target->bt_logical_sectormask)
                return -XFS_ERROR(EINVAL);
 
+       /* "unaligned" here means not aligned to a filesystem block */
        if ((pos & mp->m_blockmask) || ((pos + count) & mp->m_blockmask))
                unaligned_io = 1;
 
 
                        XFS_IS_REALTIME_INODE(ip) ?
                        mp->m_rtdev_targp : mp->m_ddev_targp;
 
-               da.d_mem = da.d_miniosz = target->bt_meta_sectorsize;
+               da.d_mem =  da.d_miniosz = target->bt_logical_sectorsize;
                da.d_maxiosz = INT_MAX & ~(da.d_miniosz - 1);
 
                if (copy_to_user(arg, &da, sizeof(da)))