Merge branch 'xfs-4.10-misc-fixes-2' into for-next
This commit is contained in:
commit
b7b26110ed
|
@ -49,6 +49,8 @@
|
||||||
#include "xfs_rmap.h"
|
#include "xfs_rmap.h"
|
||||||
#include "xfs_ag_resv.h"
|
#include "xfs_ag_resv.h"
|
||||||
#include "xfs_refcount.h"
|
#include "xfs_refcount.h"
|
||||||
|
#include "xfs_rmap_btree.h"
|
||||||
|
#include "xfs_icache.h"
|
||||||
|
|
||||||
|
|
||||||
kmem_zone_t *xfs_bmap_free_item_zone;
|
kmem_zone_t *xfs_bmap_free_item_zone;
|
||||||
|
@ -190,8 +192,12 @@ xfs_bmap_worst_indlen(
|
||||||
int maxrecs; /* maximum record count at this level */
|
int maxrecs; /* maximum record count at this level */
|
||||||
xfs_mount_t *mp; /* mount structure */
|
xfs_mount_t *mp; /* mount structure */
|
||||||
xfs_filblks_t rval; /* return value */
|
xfs_filblks_t rval; /* return value */
|
||||||
|
xfs_filblks_t orig_len;
|
||||||
|
|
||||||
mp = ip->i_mount;
|
mp = ip->i_mount;
|
||||||
|
|
||||||
|
/* Calculate the worst-case size of the bmbt. */
|
||||||
|
orig_len = len;
|
||||||
maxrecs = mp->m_bmap_dmxr[0];
|
maxrecs = mp->m_bmap_dmxr[0];
|
||||||
for (level = 0, rval = 0;
|
for (level = 0, rval = 0;
|
||||||
level < XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK);
|
level < XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK);
|
||||||
|
@ -199,12 +205,20 @@ xfs_bmap_worst_indlen(
|
||||||
len += maxrecs - 1;
|
len += maxrecs - 1;
|
||||||
do_div(len, maxrecs);
|
do_div(len, maxrecs);
|
||||||
rval += len;
|
rval += len;
|
||||||
if (len == 1)
|
if (len == 1) {
|
||||||
return rval + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) -
|
rval += XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) -
|
||||||
level - 1;
|
level - 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (level == 0)
|
if (level == 0)
|
||||||
maxrecs = mp->m_bmap_dmxr[1];
|
maxrecs = mp->m_bmap_dmxr[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Calculate the worst-case size of the rmapbt. */
|
||||||
|
if (xfs_sb_version_hasrmapbt(&mp->m_sb))
|
||||||
|
rval += 1 + xfs_rmapbt_calc_size(mp, orig_len) +
|
||||||
|
mp->m_rmap_maxlevels;
|
||||||
|
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4141,8 +4155,9 @@ int
|
||||||
xfs_bmapi_reserve_delalloc(
|
xfs_bmapi_reserve_delalloc(
|
||||||
struct xfs_inode *ip,
|
struct xfs_inode *ip,
|
||||||
int whichfork,
|
int whichfork,
|
||||||
xfs_fileoff_t aoff,
|
xfs_fileoff_t off,
|
||||||
xfs_filblks_t len,
|
xfs_filblks_t len,
|
||||||
|
xfs_filblks_t prealloc,
|
||||||
struct xfs_bmbt_irec *got,
|
struct xfs_bmbt_irec *got,
|
||||||
xfs_extnum_t *lastx,
|
xfs_extnum_t *lastx,
|
||||||
int eof)
|
int eof)
|
||||||
|
@ -4154,10 +4169,17 @@ xfs_bmapi_reserve_delalloc(
|
||||||
char rt = XFS_IS_REALTIME_INODE(ip);
|
char rt = XFS_IS_REALTIME_INODE(ip);
|
||||||
xfs_extlen_t extsz;
|
xfs_extlen_t extsz;
|
||||||
int error;
|
int error;
|
||||||
|
xfs_fileoff_t aoff = off;
|
||||||
|
|
||||||
alen = XFS_FILBLKS_MIN(len, MAXEXTLEN);
|
/*
|
||||||
|
* Cap the alloc length. Keep track of prealloc so we know whether to
|
||||||
|
* tag the inode before we return.
|
||||||
|
*/
|
||||||
|
alen = XFS_FILBLKS_MIN(len + prealloc, MAXEXTLEN);
|
||||||
if (!eof)
|
if (!eof)
|
||||||
alen = XFS_FILBLKS_MIN(alen, got->br_startoff - aoff);
|
alen = XFS_FILBLKS_MIN(alen, got->br_startoff - aoff);
|
||||||
|
if (prealloc && alen >= len)
|
||||||
|
prealloc = alen - len;
|
||||||
|
|
||||||
/* Figure out the extent size, adjust alen */
|
/* Figure out the extent size, adjust alen */
|
||||||
if (whichfork == XFS_COW_FORK)
|
if (whichfork == XFS_COW_FORK)
|
||||||
|
@ -4223,6 +4245,16 @@ xfs_bmapi_reserve_delalloc(
|
||||||
*/
|
*/
|
||||||
xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *lastx), got);
|
xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *lastx), got);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tag the inode if blocks were preallocated. Note that COW fork
|
||||||
|
* preallocation can occur at the start or end of the extent, even when
|
||||||
|
* prealloc == 0, so we must also check the aligned offset and length.
|
||||||
|
*/
|
||||||
|
if (whichfork == XFS_DATA_FORK && prealloc)
|
||||||
|
xfs_inode_set_eofblocks_tag(ip);
|
||||||
|
if (whichfork == XFS_COW_FORK && (prealloc || aoff < off || alen > len))
|
||||||
|
xfs_inode_set_cowblocks_tag(ip);
|
||||||
|
|
||||||
ASSERT(got->br_startoff <= aoff);
|
ASSERT(got->br_startoff <= aoff);
|
||||||
ASSERT(got->br_startoff + got->br_blockcount >= aoff + alen);
|
ASSERT(got->br_startoff + got->br_blockcount >= aoff + alen);
|
||||||
ASSERT(isnullstartblock(got->br_startblock));
|
ASSERT(isnullstartblock(got->br_startblock));
|
||||||
|
|
|
@ -238,7 +238,7 @@ int xfs_bmap_shift_extents(struct xfs_trans *tp, struct xfs_inode *ip,
|
||||||
int num_exts);
|
int num_exts);
|
||||||
int xfs_bmap_split_extent(struct xfs_inode *ip, xfs_fileoff_t split_offset);
|
int xfs_bmap_split_extent(struct xfs_inode *ip, xfs_fileoff_t split_offset);
|
||||||
int xfs_bmapi_reserve_delalloc(struct xfs_inode *ip, int whichfork,
|
int xfs_bmapi_reserve_delalloc(struct xfs_inode *ip, int whichfork,
|
||||||
xfs_fileoff_t aoff, xfs_filblks_t len,
|
xfs_fileoff_t off, xfs_filblks_t len, xfs_filblks_t prealloc,
|
||||||
struct xfs_bmbt_irec *got, xfs_extnum_t *lastx, int eof);
|
struct xfs_bmbt_irec *got, xfs_extnum_t *lastx, int eof);
|
||||||
|
|
||||||
enum xfs_bmap_intent_type {
|
enum xfs_bmap_intent_type {
|
||||||
|
|
|
@ -93,7 +93,7 @@ xfs_ascii_ci_compname(
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct xfs_nameops xfs_ascii_ci_nameops = {
|
static const struct xfs_nameops xfs_ascii_ci_nameops = {
|
||||||
.hashname = xfs_ascii_ci_hashname,
|
.hashname = xfs_ascii_ci_hashname,
|
||||||
.compname = xfs_ascii_ci_compname,
|
.compname = xfs_ascii_ci_compname,
|
||||||
};
|
};
|
||||||
|
|
|
@ -71,6 +71,7 @@ typedef unsigned int xfs_buf_flags_t;
|
||||||
{ XBF_READ, "READ" }, \
|
{ XBF_READ, "READ" }, \
|
||||||
{ XBF_WRITE, "WRITE" }, \
|
{ XBF_WRITE, "WRITE" }, \
|
||||||
{ XBF_READ_AHEAD, "READ_AHEAD" }, \
|
{ XBF_READ_AHEAD, "READ_AHEAD" }, \
|
||||||
|
{ XBF_NO_IOACCT, "NO_IOACCT" }, \
|
||||||
{ XBF_ASYNC, "ASYNC" }, \
|
{ XBF_ASYNC, "ASYNC" }, \
|
||||||
{ XBF_DONE, "DONE" }, \
|
{ XBF_DONE, "DONE" }, \
|
||||||
{ XBF_STALE, "STALE" }, \
|
{ XBF_STALE, "STALE" }, \
|
||||||
|
|
|
@ -133,7 +133,7 @@ xfs_icreate_item_committing(
|
||||||
/*
|
/*
|
||||||
* This is the ops vector shared by all buf log items.
|
* This is the ops vector shared by all buf log items.
|
||||||
*/
|
*/
|
||||||
static struct xfs_item_ops xfs_icreate_item_ops = {
|
static const struct xfs_item_ops xfs_icreate_item_ops = {
|
||||||
.iop_size = xfs_icreate_item_size,
|
.iop_size = xfs_icreate_item_size,
|
||||||
.iop_format = xfs_icreate_item_format,
|
.iop_format = xfs_icreate_item_format,
|
||||||
.iop_pin = xfs_icreate_item_pin,
|
.iop_pin = xfs_icreate_item_pin,
|
||||||
|
|
|
@ -536,10 +536,11 @@ xfs_file_iomap_begin_delay(
|
||||||
xfs_fileoff_t offset_fsb = XFS_B_TO_FSBT(mp, offset);
|
xfs_fileoff_t offset_fsb = XFS_B_TO_FSBT(mp, offset);
|
||||||
xfs_fileoff_t maxbytes_fsb =
|
xfs_fileoff_t maxbytes_fsb =
|
||||||
XFS_B_TO_FSB(mp, mp->m_super->s_maxbytes);
|
XFS_B_TO_FSB(mp, mp->m_super->s_maxbytes);
|
||||||
xfs_fileoff_t end_fsb, orig_end_fsb;
|
xfs_fileoff_t end_fsb;
|
||||||
int error = 0, eof = 0;
|
int error = 0, eof = 0;
|
||||||
struct xfs_bmbt_irec got;
|
struct xfs_bmbt_irec got;
|
||||||
xfs_extnum_t idx;
|
xfs_extnum_t idx;
|
||||||
|
xfs_fsblock_t prealloc_blocks = 0;
|
||||||
|
|
||||||
ASSERT(!XFS_IS_REALTIME_INODE(ip));
|
ASSERT(!XFS_IS_REALTIME_INODE(ip));
|
||||||
ASSERT(!xfs_get_extsz_hint(ip));
|
ASSERT(!xfs_get_extsz_hint(ip));
|
||||||
|
@ -594,33 +595,32 @@ xfs_file_iomap_begin_delay(
|
||||||
* the lower level functions are updated.
|
* the lower level functions are updated.
|
||||||
*/
|
*/
|
||||||
count = min_t(loff_t, count, 1024 * PAGE_SIZE);
|
count = min_t(loff_t, count, 1024 * PAGE_SIZE);
|
||||||
end_fsb = orig_end_fsb =
|
end_fsb = min(XFS_B_TO_FSB(mp, offset + count), maxbytes_fsb);
|
||||||
min(XFS_B_TO_FSB(mp, offset + count), maxbytes_fsb);
|
|
||||||
|
|
||||||
if (eof) {
|
if (eof) {
|
||||||
xfs_fsblock_t prealloc_blocks;
|
|
||||||
|
|
||||||
prealloc_blocks = xfs_iomap_prealloc_size(ip, offset, count, idx);
|
prealloc_blocks = xfs_iomap_prealloc_size(ip, offset, count, idx);
|
||||||
if (prealloc_blocks) {
|
if (prealloc_blocks) {
|
||||||
xfs_extlen_t align;
|
xfs_extlen_t align;
|
||||||
xfs_off_t end_offset;
|
xfs_off_t end_offset;
|
||||||
|
xfs_fileoff_t p_end_fsb;
|
||||||
|
|
||||||
end_offset = XFS_WRITEIO_ALIGN(mp, offset + count - 1);
|
end_offset = XFS_WRITEIO_ALIGN(mp, offset + count - 1);
|
||||||
end_fsb = XFS_B_TO_FSBT(mp, end_offset) +
|
p_end_fsb = XFS_B_TO_FSBT(mp, end_offset) +
|
||||||
prealloc_blocks;
|
prealloc_blocks;
|
||||||
|
|
||||||
align = xfs_eof_alignment(ip, 0);
|
align = xfs_eof_alignment(ip, 0);
|
||||||
if (align)
|
if (align)
|
||||||
end_fsb = roundup_64(end_fsb, align);
|
p_end_fsb = roundup_64(p_end_fsb, align);
|
||||||
|
|
||||||
end_fsb = min(end_fsb, maxbytes_fsb);
|
p_end_fsb = min(p_end_fsb, maxbytes_fsb);
|
||||||
ASSERT(end_fsb > offset_fsb);
|
ASSERT(p_end_fsb > offset_fsb);
|
||||||
|
prealloc_blocks = p_end_fsb - end_fsb;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
error = xfs_bmapi_reserve_delalloc(ip, XFS_DATA_FORK, offset_fsb,
|
error = xfs_bmapi_reserve_delalloc(ip, XFS_DATA_FORK, offset_fsb,
|
||||||
end_fsb - offset_fsb, &got, &idx, eof);
|
end_fsb - offset_fsb, prealloc_blocks, &got, &idx, eof);
|
||||||
switch (error) {
|
switch (error) {
|
||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
|
@ -628,8 +628,8 @@ xfs_file_iomap_begin_delay(
|
||||||
case -EDQUOT:
|
case -EDQUOT:
|
||||||
/* retry without any preallocation */
|
/* retry without any preallocation */
|
||||||
trace_xfs_delalloc_enospc(ip, offset, count);
|
trace_xfs_delalloc_enospc(ip, offset, count);
|
||||||
if (end_fsb != orig_end_fsb) {
|
if (prealloc_blocks) {
|
||||||
end_fsb = orig_end_fsb;
|
prealloc_blocks = 0;
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
/*FALLTHRU*/
|
/*FALLTHRU*/
|
||||||
|
@ -637,13 +637,6 @@ xfs_file_iomap_begin_delay(
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Tag the inode as speculatively preallocated so we can reclaim this
|
|
||||||
* space on demand, if necessary.
|
|
||||||
*/
|
|
||||||
if (end_fsb != orig_end_fsb)
|
|
||||||
xfs_inode_set_eofblocks_tag(ip);
|
|
||||||
|
|
||||||
trace_xfs_iomap_alloc(ip, offset, count, 0, &got);
|
trace_xfs_iomap_alloc(ip, offset, count, 0, &got);
|
||||||
done:
|
done:
|
||||||
if (isnullstartblock(got.br_startblock))
|
if (isnullstartblock(got.br_startblock))
|
||||||
|
|
|
@ -245,11 +245,9 @@ xfs_reflink_reserve_cow(
|
||||||
{
|
{
|
||||||
struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK);
|
struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK);
|
||||||
struct xfs_bmbt_irec got;
|
struct xfs_bmbt_irec got;
|
||||||
xfs_fileoff_t end_fsb, orig_end_fsb;
|
|
||||||
int error = 0;
|
int error = 0;
|
||||||
bool eof = false, trimmed;
|
bool eof = false, trimmed;
|
||||||
xfs_extnum_t idx;
|
xfs_extnum_t idx;
|
||||||
xfs_extlen_t align;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Search the COW fork extent list first. This serves two purposes:
|
* Search the COW fork extent list first. This serves two purposes:
|
||||||
|
@ -287,33 +285,12 @@ xfs_reflink_reserve_cow(
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
end_fsb = orig_end_fsb = imap->br_startoff + imap->br_blockcount;
|
|
||||||
|
|
||||||
align = xfs_eof_alignment(ip, xfs_get_cowextsz_hint(ip));
|
|
||||||
if (align)
|
|
||||||
end_fsb = roundup_64(end_fsb, align);
|
|
||||||
|
|
||||||
retry:
|
|
||||||
error = xfs_bmapi_reserve_delalloc(ip, XFS_COW_FORK, imap->br_startoff,
|
error = xfs_bmapi_reserve_delalloc(ip, XFS_COW_FORK, imap->br_startoff,
|
||||||
end_fsb - imap->br_startoff, &got, &idx, eof);
|
imap->br_blockcount, 0, &got, &idx, eof);
|
||||||
switch (error) {
|
if (error == -ENOSPC || error == -EDQUOT)
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
case -ENOSPC:
|
|
||||||
case -EDQUOT:
|
|
||||||
/* retry without any preallocation */
|
|
||||||
trace_xfs_reflink_cow_enospc(ip, imap);
|
trace_xfs_reflink_cow_enospc(ip, imap);
|
||||||
if (end_fsb != orig_end_fsb) {
|
if (error)
|
||||||
end_fsb = orig_end_fsb;
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
/*FALLTHRU*/
|
|
||||||
default:
|
|
||||||
return error;
|
return error;
|
||||||
}
|
|
||||||
|
|
||||||
if (end_fsb != orig_end_fsb)
|
|
||||||
xfs_inode_set_cowblocks_tag(ip);
|
|
||||||
|
|
||||||
trace_xfs_reflink_cow_alloc(ip, &got);
|
trace_xfs_reflink_cow_alloc(ip, &got);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1317,8 +1294,14 @@ xfs_reflink_remap_range(
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len == 0)
|
/* Zero length dedupe exits immediately; reflink goes to EOF. */
|
||||||
|
if (len == 0) {
|
||||||
|
if (is_dedupe) {
|
||||||
|
ret = 0;
|
||||||
|
goto out_unlock;
|
||||||
|
}
|
||||||
len = isize - pos_in;
|
len = isize - pos_in;
|
||||||
|
}
|
||||||
|
|
||||||
/* Ensure offsets don't wrap and the input is inside i_size */
|
/* Ensure offsets don't wrap and the input is inside i_size */
|
||||||
if (pos_in + len < pos_in || pos_out + len < pos_out ||
|
if (pos_in + len < pos_in || pos_out + len < pos_out ||
|
||||||
|
|
Loading…
Reference in New Issue