Merge branch 'for-linus' of git://oss.sgi.com/xfs/xfs
* 'for-linus' of git://oss.sgi.com/xfs/xfs: xfs: correctly decrement the extent buffer index in xfs_bmap_del_extent xfs: check for valid indices in xfs_iext_get_ext and xfs_iext_idx_to_irec xfs: fix up asserts in xfs_iflush_fork xfs: do not do pointer arithmetic on extent records xfs: do not use unchecked extent indices in xfs_bunmapi xfs: do not use unchecked extent indices in xfs_bmapi xfs: do not use unchecked extent indices in xfs_bmap_add_extent_* xfs: remove if_lastex xfs: remove the unused XFS_BMAPI_RSVBLOCKS flag xfs: do not discard alloc btree blocks xfs: add online discard support
This commit is contained in:
commit
8a0599dd24
|
@ -39,6 +39,12 @@ When mounting an XFS filesystem, the following options are accepted.
|
||||||
drive level write caching to be enabled, for devices that
|
drive level write caching to be enabled, for devices that
|
||||||
support write barriers.
|
support write barriers.
|
||||||
|
|
||||||
|
discard
|
||||||
|
Issue command to let the block device reclaim space freed by the
|
||||||
|
filesystem. This is useful for SSD devices, thinly provisioned
|
||||||
|
LUNs and virtual machine images, but may have a performance
|
||||||
|
impact. This option is incompatible with the nodelaylog option.
|
||||||
|
|
||||||
dmapi
|
dmapi
|
||||||
Enable the DMAPI (Data Management API) event callouts.
|
Enable the DMAPI (Data Management API) event callouts.
|
||||||
Use with the "mtpt" option.
|
Use with the "mtpt" option.
|
||||||
|
|
|
@ -191,3 +191,32 @@ xfs_ioc_trim(
|
||||||
return -XFS_ERROR(EFAULT);
|
return -XFS_ERROR(EFAULT);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
xfs_discard_extents(
|
||||||
|
struct xfs_mount *mp,
|
||||||
|
struct list_head *list)
|
||||||
|
{
|
||||||
|
struct xfs_busy_extent *busyp;
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
|
list_for_each_entry(busyp, list, list) {
|
||||||
|
trace_xfs_discard_extent(mp, busyp->agno, busyp->bno,
|
||||||
|
busyp->length);
|
||||||
|
|
||||||
|
error = -blkdev_issue_discard(mp->m_ddev_targp->bt_bdev,
|
||||||
|
XFS_AGB_TO_DADDR(mp, busyp->agno, busyp->bno),
|
||||||
|
XFS_FSB_TO_BB(mp, busyp->length),
|
||||||
|
GFP_NOFS, 0);
|
||||||
|
if (error && error != EOPNOTSUPP) {
|
||||||
|
xfs_info(mp,
|
||||||
|
"discard failed for extent [0x%llu,%u], error %d",
|
||||||
|
(unsigned long long)busyp->bno,
|
||||||
|
busyp->length,
|
||||||
|
error);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -2,7 +2,9 @@
|
||||||
#define XFS_DISCARD_H 1
|
#define XFS_DISCARD_H 1
|
||||||
|
|
||||||
struct fstrim_range;
|
struct fstrim_range;
|
||||||
|
struct list_head;
|
||||||
|
|
||||||
extern int xfs_ioc_trim(struct xfs_mount *, struct fstrim_range __user *);
|
extern int xfs_ioc_trim(struct xfs_mount *, struct fstrim_range __user *);
|
||||||
|
extern int xfs_discard_extents(struct xfs_mount *, struct list_head *);
|
||||||
|
|
||||||
#endif /* XFS_DISCARD_H */
|
#endif /* XFS_DISCARD_H */
|
||||||
|
|
|
@ -110,8 +110,10 @@ mempool_t *xfs_ioend_pool;
|
||||||
#define MNTOPT_GQUOTANOENF "gqnoenforce"/* group quota limit enforcement */
|
#define MNTOPT_GQUOTANOENF "gqnoenforce"/* group quota limit enforcement */
|
||||||
#define MNTOPT_PQUOTANOENF "pqnoenforce"/* project quota limit enforcement */
|
#define MNTOPT_PQUOTANOENF "pqnoenforce"/* project quota limit enforcement */
|
||||||
#define MNTOPT_QUOTANOENF "qnoenforce" /* same as uqnoenforce */
|
#define MNTOPT_QUOTANOENF "qnoenforce" /* same as uqnoenforce */
|
||||||
#define MNTOPT_DELAYLOG "delaylog" /* Delayed loging enabled */
|
#define MNTOPT_DELAYLOG "delaylog" /* Delayed logging enabled */
|
||||||
#define MNTOPT_NODELAYLOG "nodelaylog" /* Delayed loging disabled */
|
#define MNTOPT_NODELAYLOG "nodelaylog" /* Delayed logging disabled */
|
||||||
|
#define MNTOPT_DISCARD "discard" /* Discard unused blocks */
|
||||||
|
#define MNTOPT_NODISCARD "nodiscard" /* Do not discard unused blocks */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Table driven mount option parser.
|
* Table driven mount option parser.
|
||||||
|
@ -355,6 +357,10 @@ xfs_parseargs(
|
||||||
mp->m_flags |= XFS_MOUNT_DELAYLOG;
|
mp->m_flags |= XFS_MOUNT_DELAYLOG;
|
||||||
} else if (!strcmp(this_char, MNTOPT_NODELAYLOG)) {
|
} else if (!strcmp(this_char, MNTOPT_NODELAYLOG)) {
|
||||||
mp->m_flags &= ~XFS_MOUNT_DELAYLOG;
|
mp->m_flags &= ~XFS_MOUNT_DELAYLOG;
|
||||||
|
} else if (!strcmp(this_char, MNTOPT_DISCARD)) {
|
||||||
|
mp->m_flags |= XFS_MOUNT_DISCARD;
|
||||||
|
} else if (!strcmp(this_char, MNTOPT_NODISCARD)) {
|
||||||
|
mp->m_flags &= ~XFS_MOUNT_DISCARD;
|
||||||
} else if (!strcmp(this_char, "ihashsize")) {
|
} else if (!strcmp(this_char, "ihashsize")) {
|
||||||
xfs_warn(mp,
|
xfs_warn(mp,
|
||||||
"ihashsize no longer used, option is deprecated.");
|
"ihashsize no longer used, option is deprecated.");
|
||||||
|
@ -388,6 +394,13 @@ xfs_parseargs(
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((mp->m_flags & XFS_MOUNT_DISCARD) &&
|
||||||
|
!(mp->m_flags & XFS_MOUNT_DELAYLOG)) {
|
||||||
|
xfs_warn(mp,
|
||||||
|
"the discard option is incompatible with the nodelaylog option");
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef CONFIG_XFS_QUOTA
|
#ifndef CONFIG_XFS_QUOTA
|
||||||
if (XFS_IS_QUOTA_RUNNING(mp)) {
|
if (XFS_IS_QUOTA_RUNNING(mp)) {
|
||||||
xfs_warn(mp, "quota support not available in this kernel.");
|
xfs_warn(mp, "quota support not available in this kernel.");
|
||||||
|
@ -488,6 +501,7 @@ xfs_showargs(
|
||||||
{ XFS_MOUNT_FILESTREAMS, "," MNTOPT_FILESTREAM },
|
{ XFS_MOUNT_FILESTREAMS, "," MNTOPT_FILESTREAM },
|
||||||
{ XFS_MOUNT_GRPID, "," MNTOPT_GRPID },
|
{ XFS_MOUNT_GRPID, "," MNTOPT_GRPID },
|
||||||
{ XFS_MOUNT_DELAYLOG, "," MNTOPT_DELAYLOG },
|
{ XFS_MOUNT_DELAYLOG, "," MNTOPT_DELAYLOG },
|
||||||
|
{ XFS_MOUNT_DISCARD, "," MNTOPT_DISCARD },
|
||||||
{ 0, NULL }
|
{ 0, NULL }
|
||||||
};
|
};
|
||||||
static struct proc_xfs_info xfs_info_unset[] = {
|
static struct proc_xfs_info xfs_info_unset[] = {
|
||||||
|
|
|
@ -187,6 +187,9 @@ struct xfs_busy_extent {
|
||||||
xfs_agnumber_t agno;
|
xfs_agnumber_t agno;
|
||||||
xfs_agblock_t bno;
|
xfs_agblock_t bno;
|
||||||
xfs_extlen_t length;
|
xfs_extlen_t length;
|
||||||
|
unsigned int flags;
|
||||||
|
#define XFS_ALLOC_BUSY_DISCARDED 0x01 /* undergoing a discard op. */
|
||||||
|
#define XFS_ALLOC_BUSY_SKIP_DISCARD 0x02 /* do not discard */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -2469,7 +2469,7 @@ xfs_free_extent(
|
||||||
|
|
||||||
error = xfs_free_ag_extent(tp, args.agbp, args.agno, args.agbno, len, 0);
|
error = xfs_free_ag_extent(tp, args.agbp, args.agno, args.agbno, len, 0);
|
||||||
if (!error)
|
if (!error)
|
||||||
xfs_alloc_busy_insert(tp, args.agno, args.agbno, len);
|
xfs_alloc_busy_insert(tp, args.agno, args.agbno, len, 0);
|
||||||
error0:
|
error0:
|
||||||
xfs_perag_put(args.pag);
|
xfs_perag_put(args.pag);
|
||||||
return error;
|
return error;
|
||||||
|
@ -2480,7 +2480,8 @@ xfs_alloc_busy_insert(
|
||||||
struct xfs_trans *tp,
|
struct xfs_trans *tp,
|
||||||
xfs_agnumber_t agno,
|
xfs_agnumber_t agno,
|
||||||
xfs_agblock_t bno,
|
xfs_agblock_t bno,
|
||||||
xfs_extlen_t len)
|
xfs_extlen_t len,
|
||||||
|
unsigned int flags)
|
||||||
{
|
{
|
||||||
struct xfs_busy_extent *new;
|
struct xfs_busy_extent *new;
|
||||||
struct xfs_busy_extent *busyp;
|
struct xfs_busy_extent *busyp;
|
||||||
|
@ -2504,6 +2505,7 @@ xfs_alloc_busy_insert(
|
||||||
new->bno = bno;
|
new->bno = bno;
|
||||||
new->length = len;
|
new->length = len;
|
||||||
INIT_LIST_HEAD(&new->list);
|
INIT_LIST_HEAD(&new->list);
|
||||||
|
new->flags = flags;
|
||||||
|
|
||||||
/* trace before insert to be able to see failed inserts */
|
/* trace before insert to be able to see failed inserts */
|
||||||
trace_xfs_alloc_busy(tp->t_mountp, agno, bno, len);
|
trace_xfs_alloc_busy(tp->t_mountp, agno, bno, len);
|
||||||
|
@ -2608,6 +2610,18 @@ xfs_alloc_busy_update_extent(
|
||||||
xfs_agblock_t bbno = busyp->bno;
|
xfs_agblock_t bbno = busyp->bno;
|
||||||
xfs_agblock_t bend = bbno + busyp->length;
|
xfs_agblock_t bend = bbno + busyp->length;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This extent is currently being discarded. Give the thread
|
||||||
|
* performing the discard a chance to mark the extent unbusy
|
||||||
|
* and retry.
|
||||||
|
*/
|
||||||
|
if (busyp->flags & XFS_ALLOC_BUSY_DISCARDED) {
|
||||||
|
spin_unlock(&pag->pagb_lock);
|
||||||
|
delay(1);
|
||||||
|
spin_lock(&pag->pagb_lock);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If there is a busy extent overlapping a user allocation, we have
|
* If there is a busy extent overlapping a user allocation, we have
|
||||||
* no choice but to force the log and retry the search.
|
* no choice but to force the log and retry the search.
|
||||||
|
@ -2813,7 +2827,8 @@ restart:
|
||||||
* If this is a metadata allocation, try to reuse the busy
|
* If this is a metadata allocation, try to reuse the busy
|
||||||
* extent instead of trimming the allocation.
|
* extent instead of trimming the allocation.
|
||||||
*/
|
*/
|
||||||
if (!args->userdata) {
|
if (!args->userdata &&
|
||||||
|
!(busyp->flags & XFS_ALLOC_BUSY_DISCARDED)) {
|
||||||
if (!xfs_alloc_busy_update_extent(args->mp, args->pag,
|
if (!xfs_alloc_busy_update_extent(args->mp, args->pag,
|
||||||
busyp, fbno, flen,
|
busyp, fbno, flen,
|
||||||
false))
|
false))
|
||||||
|
@ -2979,10 +2994,16 @@ xfs_alloc_busy_clear_one(
|
||||||
kmem_free(busyp);
|
kmem_free(busyp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove all extents on the passed in list from the busy extents tree.
|
||||||
|
* If do_discard is set skip extents that need to be discarded, and mark
|
||||||
|
* these as undergoing a discard operation instead.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
xfs_alloc_busy_clear(
|
xfs_alloc_busy_clear(
|
||||||
struct xfs_mount *mp,
|
struct xfs_mount *mp,
|
||||||
struct list_head *list)
|
struct list_head *list,
|
||||||
|
bool do_discard)
|
||||||
{
|
{
|
||||||
struct xfs_busy_extent *busyp, *n;
|
struct xfs_busy_extent *busyp, *n;
|
||||||
struct xfs_perag *pag = NULL;
|
struct xfs_perag *pag = NULL;
|
||||||
|
@ -2999,7 +3020,11 @@ xfs_alloc_busy_clear(
|
||||||
agno = busyp->agno;
|
agno = busyp->agno;
|
||||||
}
|
}
|
||||||
|
|
||||||
xfs_alloc_busy_clear_one(mp, pag, busyp);
|
if (do_discard && busyp->length &&
|
||||||
|
!(busyp->flags & XFS_ALLOC_BUSY_SKIP_DISCARD))
|
||||||
|
busyp->flags = XFS_ALLOC_BUSY_DISCARDED;
|
||||||
|
else
|
||||||
|
xfs_alloc_busy_clear_one(mp, pag, busyp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pag) {
|
if (pag) {
|
||||||
|
|
|
@ -137,10 +137,11 @@ xfs_alloc_longest_free_extent(struct xfs_mount *mp,
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
void
|
void
|
||||||
xfs_alloc_busy_insert(struct xfs_trans *tp, xfs_agnumber_t agno,
|
xfs_alloc_busy_insert(struct xfs_trans *tp, xfs_agnumber_t agno,
|
||||||
xfs_agblock_t bno, xfs_extlen_t len);
|
xfs_agblock_t bno, xfs_extlen_t len, unsigned int flags);
|
||||||
|
|
||||||
void
|
void
|
||||||
xfs_alloc_busy_clear(struct xfs_mount *mp, struct list_head *list);
|
xfs_alloc_busy_clear(struct xfs_mount *mp, struct list_head *list,
|
||||||
|
bool do_discard);
|
||||||
|
|
||||||
int
|
int
|
||||||
xfs_alloc_busy_search(struct xfs_mount *mp, xfs_agnumber_t agno,
|
xfs_alloc_busy_search(struct xfs_mount *mp, xfs_agnumber_t agno,
|
||||||
|
|
|
@ -120,7 +120,8 @@ xfs_allocbt_free_block(
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
xfs_alloc_busy_insert(cur->bc_tp, be32_to_cpu(agf->agf_seqno), bno, 1);
|
xfs_alloc_busy_insert(cur->bc_tp, be32_to_cpu(agf->agf_seqno), bno, 1,
|
||||||
|
XFS_ALLOC_BUSY_SKIP_DISCARD);
|
||||||
xfs_trans_agbtree_delta(cur->bc_tp, -1);
|
xfs_trans_agbtree_delta(cur->bc_tp, -1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -69,7 +69,6 @@ typedef struct xfs_bmap_free
|
||||||
#define XFS_BMAPI_ENTIRE 0x004 /* return entire extent, not trimmed */
|
#define XFS_BMAPI_ENTIRE 0x004 /* return entire extent, not trimmed */
|
||||||
#define XFS_BMAPI_METADATA 0x008 /* mapping metadata not user data */
|
#define XFS_BMAPI_METADATA 0x008 /* mapping metadata not user data */
|
||||||
#define XFS_BMAPI_ATTRFORK 0x010 /* use attribute fork not data */
|
#define XFS_BMAPI_ATTRFORK 0x010 /* use attribute fork not data */
|
||||||
#define XFS_BMAPI_RSVBLOCKS 0x020 /* OK to alloc. reserved data blocks */
|
|
||||||
#define XFS_BMAPI_PREALLOC 0x040 /* preallocation op: unwritten space */
|
#define XFS_BMAPI_PREALLOC 0x040 /* preallocation op: unwritten space */
|
||||||
#define XFS_BMAPI_IGSTATE 0x080 /* Ignore state - */
|
#define XFS_BMAPI_IGSTATE 0x080 /* Ignore state - */
|
||||||
/* combine contig. space */
|
/* combine contig. space */
|
||||||
|
@ -87,7 +86,6 @@ typedef struct xfs_bmap_free
|
||||||
{ XFS_BMAPI_ENTIRE, "ENTIRE" }, \
|
{ XFS_BMAPI_ENTIRE, "ENTIRE" }, \
|
||||||
{ XFS_BMAPI_METADATA, "METADATA" }, \
|
{ XFS_BMAPI_METADATA, "METADATA" }, \
|
||||||
{ XFS_BMAPI_ATTRFORK, "ATTRFORK" }, \
|
{ XFS_BMAPI_ATTRFORK, "ATTRFORK" }, \
|
||||||
{ XFS_BMAPI_RSVBLOCKS, "RSVBLOCKS" }, \
|
|
||||||
{ XFS_BMAPI_PREALLOC, "PREALLOC" }, \
|
{ XFS_BMAPI_PREALLOC, "PREALLOC" }, \
|
||||||
{ XFS_BMAPI_IGSTATE, "IGSTATE" }, \
|
{ XFS_BMAPI_IGSTATE, "IGSTATE" }, \
|
||||||
{ XFS_BMAPI_CONTIG, "CONTIG" }, \
|
{ XFS_BMAPI_CONTIG, "CONTIG" }, \
|
||||||
|
|
|
@ -920,7 +920,6 @@ xfs_iread_extents(
|
||||||
/*
|
/*
|
||||||
* We know that the size is valid (it's checked in iformat_btree)
|
* We know that the size is valid (it's checked in iformat_btree)
|
||||||
*/
|
*/
|
||||||
ifp->if_lastex = NULLEXTNUM;
|
|
||||||
ifp->if_bytes = ifp->if_real_bytes = 0;
|
ifp->if_bytes = ifp->if_real_bytes = 0;
|
||||||
ifp->if_flags |= XFS_IFEXTENTS;
|
ifp->if_flags |= XFS_IFEXTENTS;
|
||||||
xfs_iext_add(ifp, 0, nextents);
|
xfs_iext_add(ifp, 0, nextents);
|
||||||
|
@ -2558,12 +2557,9 @@ xfs_iflush_fork(
|
||||||
case XFS_DINODE_FMT_EXTENTS:
|
case XFS_DINODE_FMT_EXTENTS:
|
||||||
ASSERT((ifp->if_flags & XFS_IFEXTENTS) ||
|
ASSERT((ifp->if_flags & XFS_IFEXTENTS) ||
|
||||||
!(iip->ili_format.ilf_fields & extflag[whichfork]));
|
!(iip->ili_format.ilf_fields & extflag[whichfork]));
|
||||||
ASSERT((xfs_iext_get_ext(ifp, 0) != NULL) ||
|
|
||||||
(ifp->if_bytes == 0));
|
|
||||||
ASSERT((xfs_iext_get_ext(ifp, 0) == NULL) ||
|
|
||||||
(ifp->if_bytes > 0));
|
|
||||||
if ((iip->ili_format.ilf_fields & extflag[whichfork]) &&
|
if ((iip->ili_format.ilf_fields & extflag[whichfork]) &&
|
||||||
(ifp->if_bytes > 0)) {
|
(ifp->if_bytes > 0)) {
|
||||||
|
ASSERT(xfs_iext_get_ext(ifp, 0));
|
||||||
ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) > 0);
|
ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) > 0);
|
||||||
(void)xfs_iextents_copy(ip, (xfs_bmbt_rec_t *)cp,
|
(void)xfs_iextents_copy(ip, (xfs_bmbt_rec_t *)cp,
|
||||||
whichfork);
|
whichfork);
|
||||||
|
@ -3112,6 +3108,8 @@ xfs_iext_get_ext(
|
||||||
xfs_extnum_t idx) /* index of target extent */
|
xfs_extnum_t idx) /* index of target extent */
|
||||||
{
|
{
|
||||||
ASSERT(idx >= 0);
|
ASSERT(idx >= 0);
|
||||||
|
ASSERT(idx < ifp->if_bytes / sizeof(xfs_bmbt_rec_t));
|
||||||
|
|
||||||
if ((ifp->if_flags & XFS_IFEXTIREC) && (idx == 0)) {
|
if ((ifp->if_flags & XFS_IFEXTIREC) && (idx == 0)) {
|
||||||
return ifp->if_u1.if_ext_irec->er_extbuf;
|
return ifp->if_u1.if_ext_irec->er_extbuf;
|
||||||
} else if (ifp->if_flags & XFS_IFEXTIREC) {
|
} else if (ifp->if_flags & XFS_IFEXTIREC) {
|
||||||
|
@ -3191,7 +3189,6 @@ xfs_iext_add(
|
||||||
}
|
}
|
||||||
ifp->if_u1.if_extents = ifp->if_u2.if_inline_ext;
|
ifp->if_u1.if_extents = ifp->if_u2.if_inline_ext;
|
||||||
ifp->if_real_bytes = 0;
|
ifp->if_real_bytes = 0;
|
||||||
ifp->if_lastex = nextents + ext_diff;
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Otherwise use a linear (direct) extent list.
|
* Otherwise use a linear (direct) extent list.
|
||||||
|
@ -3886,8 +3883,10 @@ xfs_iext_idx_to_irec(
|
||||||
xfs_extnum_t page_idx = *idxp; /* extent index in target list */
|
xfs_extnum_t page_idx = *idxp; /* extent index in target list */
|
||||||
|
|
||||||
ASSERT(ifp->if_flags & XFS_IFEXTIREC);
|
ASSERT(ifp->if_flags & XFS_IFEXTIREC);
|
||||||
ASSERT(page_idx >= 0 && page_idx <=
|
ASSERT(page_idx >= 0);
|
||||||
ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t));
|
ASSERT(page_idx <= ifp->if_bytes / sizeof(xfs_bmbt_rec_t));
|
||||||
|
ASSERT(page_idx < ifp->if_bytes / sizeof(xfs_bmbt_rec_t) || realloc);
|
||||||
|
|
||||||
nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ;
|
nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ;
|
||||||
erp_idx = 0;
|
erp_idx = 0;
|
||||||
low = 0;
|
low = 0;
|
||||||
|
|
|
@ -67,7 +67,6 @@ typedef struct xfs_ifork {
|
||||||
short if_broot_bytes; /* bytes allocated for root */
|
short if_broot_bytes; /* bytes allocated for root */
|
||||||
unsigned char if_flags; /* per-fork flags */
|
unsigned char if_flags; /* per-fork flags */
|
||||||
unsigned char if_ext_max; /* max # of extent records */
|
unsigned char if_ext_max; /* max # of extent records */
|
||||||
xfs_extnum_t if_lastex; /* last if_extents used */
|
|
||||||
union {
|
union {
|
||||||
xfs_bmbt_rec_host_t *if_extents;/* linear map file exts */
|
xfs_bmbt_rec_host_t *if_extents;/* linear map file exts */
|
||||||
xfs_ext_irec_t *if_ext_irec; /* irec map file exts */
|
xfs_ext_irec_t *if_ext_irec; /* irec map file exts */
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "xfs_mount.h"
|
#include "xfs_mount.h"
|
||||||
#include "xfs_error.h"
|
#include "xfs_error.h"
|
||||||
#include "xfs_alloc.h"
|
#include "xfs_alloc.h"
|
||||||
|
#include "xfs_discard.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Perform initial CIL structure initialisation. If the CIL is not
|
* Perform initial CIL structure initialisation. If the CIL is not
|
||||||
|
@ -361,18 +362,28 @@ xlog_cil_committed(
|
||||||
int abort)
|
int abort)
|
||||||
{
|
{
|
||||||
struct xfs_cil_ctx *ctx = args;
|
struct xfs_cil_ctx *ctx = args;
|
||||||
|
struct xfs_mount *mp = ctx->cil->xc_log->l_mp;
|
||||||
|
|
||||||
xfs_trans_committed_bulk(ctx->cil->xc_log->l_ailp, ctx->lv_chain,
|
xfs_trans_committed_bulk(ctx->cil->xc_log->l_ailp, ctx->lv_chain,
|
||||||
ctx->start_lsn, abort);
|
ctx->start_lsn, abort);
|
||||||
|
|
||||||
xfs_alloc_busy_sort(&ctx->busy_extents);
|
xfs_alloc_busy_sort(&ctx->busy_extents);
|
||||||
xfs_alloc_busy_clear(ctx->cil->xc_log->l_mp, &ctx->busy_extents);
|
xfs_alloc_busy_clear(mp, &ctx->busy_extents,
|
||||||
|
(mp->m_flags & XFS_MOUNT_DISCARD) && !abort);
|
||||||
|
|
||||||
spin_lock(&ctx->cil->xc_cil_lock);
|
spin_lock(&ctx->cil->xc_cil_lock);
|
||||||
list_del(&ctx->committing);
|
list_del(&ctx->committing);
|
||||||
spin_unlock(&ctx->cil->xc_cil_lock);
|
spin_unlock(&ctx->cil->xc_cil_lock);
|
||||||
|
|
||||||
xlog_cil_free_logvec(ctx->lv_chain);
|
xlog_cil_free_logvec(ctx->lv_chain);
|
||||||
|
|
||||||
|
if (!list_empty(&ctx->busy_extents)) {
|
||||||
|
ASSERT(mp->m_flags & XFS_MOUNT_DISCARD);
|
||||||
|
|
||||||
|
xfs_discard_extents(mp, &ctx->busy_extents);
|
||||||
|
xfs_alloc_busy_clear(mp, &ctx->busy_extents, false);
|
||||||
|
}
|
||||||
|
|
||||||
kmem_free(ctx);
|
kmem_free(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -224,6 +224,7 @@ typedef struct xfs_mount {
|
||||||
#define XFS_MOUNT_FS_SHUTDOWN (1ULL << 4) /* atomic stop of all filesystem
|
#define XFS_MOUNT_FS_SHUTDOWN (1ULL << 4) /* atomic stop of all filesystem
|
||||||
operations, typically for
|
operations, typically for
|
||||||
disk errors in metadata */
|
disk errors in metadata */
|
||||||
|
#define XFS_MOUNT_DISCARD (1ULL << 5) /* discard unused blocks */
|
||||||
#define XFS_MOUNT_RETERR (1ULL << 6) /* return alignment errors to
|
#define XFS_MOUNT_RETERR (1ULL << 6) /* return alignment errors to
|
||||||
user */
|
user */
|
||||||
#define XFS_MOUNT_NOALIGN (1ULL << 7) /* turn off stripe alignment
|
#define XFS_MOUNT_NOALIGN (1ULL << 7) /* turn off stripe alignment
|
||||||
|
|
|
@ -609,7 +609,7 @@ xfs_trans_free(
|
||||||
struct xfs_trans *tp)
|
struct xfs_trans *tp)
|
||||||
{
|
{
|
||||||
xfs_alloc_busy_sort(&tp->t_busy);
|
xfs_alloc_busy_sort(&tp->t_busy);
|
||||||
xfs_alloc_busy_clear(tp->t_mountp, &tp->t_busy);
|
xfs_alloc_busy_clear(tp->t_mountp, &tp->t_busy, false);
|
||||||
|
|
||||||
atomic_dec(&tp->t_mountp->m_active_trans);
|
atomic_dec(&tp->t_mountp->m_active_trans);
|
||||||
xfs_trans_free_dqinfo(tp);
|
xfs_trans_free_dqinfo(tp);
|
||||||
|
|
Loading…
Reference in New Issue