Commit fa2925cf authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://oss.sgi.com/xfs/xfs

* 'for-linus' of git://oss.sgi.com/xfs/xfs:
  xfs: Make fiemap work with sparse files
  xfs: prevent 32bit overflow in space reservation
  xfs: Disallow 32bit project quota id
  xfs: improve buffer cache hash scalability
parents 98e52c37 cb7a9341
...@@ -440,12 +440,7 @@ _xfs_buf_find( ...@@ -440,12 +440,7 @@ _xfs_buf_find(
ASSERT(btp == bp->b_target); ASSERT(btp == bp->b_target);
if (bp->b_file_offset == range_base && if (bp->b_file_offset == range_base &&
bp->b_buffer_length == range_length) { bp->b_buffer_length == range_length) {
/*
* If we look at something, bring it to the
* front of the list for next time.
*/
atomic_inc(&bp->b_hold); atomic_inc(&bp->b_hold);
list_move(&bp->b_hash_list, &hash->bh_list);
goto found; goto found;
} }
} }
...@@ -1443,8 +1438,7 @@ xfs_alloc_bufhash( ...@@ -1443,8 +1438,7 @@ xfs_alloc_bufhash(
{ {
unsigned int i; unsigned int i;
btp->bt_hashshift = external ? 3 : 8; /* 8 or 256 buckets */ btp->bt_hashshift = external ? 3 : 12; /* 8 or 4096 buckets */
btp->bt_hashmask = (1 << btp->bt_hashshift) - 1;
btp->bt_hash = kmem_zalloc_large((1 << btp->bt_hashshift) * btp->bt_hash = kmem_zalloc_large((1 << btp->bt_hashshift) *
sizeof(xfs_bufhash_t)); sizeof(xfs_bufhash_t));
for (i = 0; i < (1 << btp->bt_hashshift); i++) { for (i = 0; i < (1 << btp->bt_hashshift); i++) {
......
...@@ -137,7 +137,6 @@ typedef struct xfs_buftarg { ...@@ -137,7 +137,6 @@ typedef struct xfs_buftarg {
size_t bt_smask; size_t bt_smask;
/* per device buffer hash table */ /* per device buffer hash table */
uint bt_hashmask;
uint bt_hashshift; uint bt_hashshift;
xfs_bufhash_t *bt_hash; xfs_bufhash_t *bt_hash;
......
...@@ -906,6 +906,13 @@ xfs_ioctl_setattr( ...@@ -906,6 +906,13 @@ xfs_ioctl_setattr(
if (XFS_FORCED_SHUTDOWN(mp)) if (XFS_FORCED_SHUTDOWN(mp))
return XFS_ERROR(EIO); return XFS_ERROR(EIO);
/*
* Disallow 32bit project ids because on-disk structure
* is 16bit only.
*/
if ((mask & FSX_PROJID) && (fa->fsx_projid > (__uint16_t)-1))
return XFS_ERROR(EINVAL);
/* /*
* If disk quotas is on, we make sure that the dquots do exist on disk, * If disk quotas is on, we make sure that the dquots do exist on disk,
* before we start any other transactions. Trying to do this later * before we start any other transactions. Trying to do this later
......
...@@ -664,7 +664,7 @@ xfs_vn_fiemap( ...@@ -664,7 +664,7 @@ xfs_vn_fiemap(
fieinfo->fi_extents_max + 1; fieinfo->fi_extents_max + 1;
bm.bmv_count = min_t(__s32, bm.bmv_count, bm.bmv_count = min_t(__s32, bm.bmv_count,
(PAGE_SIZE * 16 / sizeof(struct getbmapx))); (PAGE_SIZE * 16 / sizeof(struct getbmapx)));
bm.bmv_iflags = BMV_IF_PREALLOC; bm.bmv_iflags = BMV_IF_PREALLOC | BMV_IF_NO_HOLES;
if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR) if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR)
bm.bmv_iflags |= BMV_IF_ATTRFORK; bm.bmv_iflags |= BMV_IF_ATTRFORK;
if (!(fieinfo->fi_flags & FIEMAP_FLAG_SYNC)) if (!(fieinfo->fi_flags & FIEMAP_FLAG_SYNC))
......
...@@ -5533,12 +5533,24 @@ xfs_getbmap( ...@@ -5533,12 +5533,24 @@ xfs_getbmap(
map[i].br_startblock)) map[i].br_startblock))
goto out_free_map; goto out_free_map;
nexleft--;
bmv->bmv_offset = bmv->bmv_offset =
out[cur_ext].bmv_offset + out[cur_ext].bmv_offset +
out[cur_ext].bmv_length; out[cur_ext].bmv_length;
bmv->bmv_length = bmv->bmv_length =
max_t(__int64_t, 0, bmvend - bmv->bmv_offset); max_t(__int64_t, 0, bmvend - bmv->bmv_offset);
/*
* In case we don't want to return the hole,
* don't increase cur_ext so that we can reuse
* it in the next loop.
*/
if ((iflags & BMV_IF_NO_HOLES) &&
map[i].br_startblock == HOLESTARTBLOCK) {
memset(&out[cur_ext], 0, sizeof(out[cur_ext]));
continue;
}
nexleft--;
bmv->bmv_entries++; bmv->bmv_entries++;
cur_ext++; cur_ext++;
} }
......
...@@ -114,8 +114,10 @@ struct getbmapx { ...@@ -114,8 +114,10 @@ struct getbmapx {
#define BMV_IF_NO_DMAPI_READ 0x2 /* Do not generate DMAPI read event */ #define BMV_IF_NO_DMAPI_READ 0x2 /* Do not generate DMAPI read event */
#define BMV_IF_PREALLOC 0x4 /* rtn status BMV_OF_PREALLOC if req */ #define BMV_IF_PREALLOC 0x4 /* rtn status BMV_OF_PREALLOC if req */
#define BMV_IF_DELALLOC 0x8 /* rtn status BMV_OF_DELALLOC if req */ #define BMV_IF_DELALLOC 0x8 /* rtn status BMV_OF_DELALLOC if req */
#define BMV_IF_NO_HOLES 0x10 /* Do not return holes */
#define BMV_IF_VALID \ #define BMV_IF_VALID \
(BMV_IF_ATTRFORK|BMV_IF_NO_DMAPI_READ|BMV_IF_PREALLOC|BMV_IF_DELALLOC) (BMV_IF_ATTRFORK|BMV_IF_NO_DMAPI_READ|BMV_IF_PREALLOC| \
BMV_IF_DELALLOC|BMV_IF_NO_HOLES)
/* bmv_oflags values - returned for each non-header segment */ /* bmv_oflags values - returned for each non-header segment */
#define BMV_OF_PREALLOC 0x1 /* segment = unwritten pre-allocation */ #define BMV_OF_PREALLOC 0x1 /* segment = unwritten pre-allocation */
......
...@@ -2299,15 +2299,22 @@ xfs_alloc_file_space( ...@@ -2299,15 +2299,22 @@ xfs_alloc_file_space(
e = allocatesize_fsb; e = allocatesize_fsb;
} }
/*
* The transaction reservation is limited to a 32-bit block
* count, hence we need to limit the number of blocks we are
* trying to reserve to avoid an overflow. We can't allocate
* more than @nimaps extents, and an extent is limited on disk
* to MAXEXTLEN (21 bits), so use that to enforce the limit.
*/
resblks = min_t(xfs_fileoff_t, (e - s), (MAXEXTLEN * nimaps));
if (unlikely(rt)) { if (unlikely(rt)) {
resrtextents = qblocks = (uint)(e - s); resrtextents = qblocks = resblks;
resrtextents /= mp->m_sb.sb_rextsize; resrtextents /= mp->m_sb.sb_rextsize;
resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0); resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
quota_flag = XFS_QMOPT_RES_RTBLKS; quota_flag = XFS_QMOPT_RES_RTBLKS;
} else { } else {
resrtextents = 0; resrtextents = 0;
resblks = qblocks = \ resblks = qblocks = XFS_DIOSTRAT_SPACE_RES(mp, resblks);
XFS_DIOSTRAT_SPACE_RES(mp, (uint)(e - s));
quota_flag = XFS_QMOPT_RES_REGBLKS; quota_flag = XFS_QMOPT_RES_REGBLKS;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment