mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 12:11:40 +00:00
Bug fixes for 6.10-rc2:
* Fix a livelock by dropping an xfarray sortinfo folio when an error is encountered. * During extended attribute operations, Initialize transaction reservation computation based on attribute operation code. * Relax symbolic link's ondisk verification code to allow symbolic links with short remote targets. * Prevent soft lockups when unmapping file ranges and also during remapping blocks during a reflink operation. * Fix compilation warnings when XFS is built with W=1 option. Signed-off-by: Chandan Babu R <chandanbabu@kernel.org> -----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQQjMC4mbgVeU7MxEIYH7y4RirJu9AUCZlbRngAKCRAH7y4RirJu 9DFfAP0aQYHIGOUx6YCvucoLtIRWYqaxDvgWPjLrtaeiUSmY7AEA1M4BVl/2Svkj hgs1/qqU8WGze/KqdG/aJbJS0ZqJKAU= =gxY4 -----END PGP SIGNATURE----- Merge tag 'xfs-6.10-fixes-1' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux Pull xfs fixes from Chandan Babu: - Fix a livelock by dropping an xfarray sortinfo folio when an error is encountered - During extended attribute operations, Initialize transaction reservation computation based on attribute operation code - Relax symbolic link's ondisk verification code to allow symbolic links with short remote targets - Prevent soft lockups when unmapping file ranges and also during remapping blocks during a reflink operation - Fix compilation warnings when XFS is built with W=1 option * tag 'xfs-6.10-fixes-1' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: xfs: Add cond_resched to block unmap range and reflink remap path xfs: don't open-code u64_to_user_ptr xfs: allow symlinks with short remote targets xfs: fix xfs_init_attr_trans not handling explicit operation codes xfs: drop xfarray sortinfo folio on error xfs: Stop using __maybe_unused in xfs_alloc.c xfs: Clear W=1 warning in xfs_iwalk_run_callbacks()
This commit is contained in:
commit
bbeb1219ee
@ -1008,13 +1008,12 @@ xfs_alloc_cur_finish(
|
||||
struct xfs_alloc_arg *args,
|
||||
struct xfs_alloc_cur *acur)
|
||||
{
|
||||
struct xfs_agf __maybe_unused *agf = args->agbp->b_addr;
|
||||
int error;
|
||||
|
||||
ASSERT(acur->cnt && acur->bnolt);
|
||||
ASSERT(acur->bno >= acur->rec_bno);
|
||||
ASSERT(acur->bno + acur->len <= acur->rec_bno + acur->rec_len);
|
||||
ASSERT(acur->rec_bno + acur->rec_len <= be32_to_cpu(agf->agf_length));
|
||||
ASSERT(xfs_verify_agbext(args->pag, acur->rec_bno, acur->rec_len));
|
||||
|
||||
error = xfs_alloc_fixup_trees(acur->cnt, acur->bnolt, acur->rec_bno,
|
||||
acur->rec_len, acur->bno, acur->len, 0);
|
||||
@ -1217,7 +1216,6 @@ STATIC int /* error */
|
||||
xfs_alloc_ag_vextent_exact(
|
||||
xfs_alloc_arg_t *args) /* allocation argument structure */
|
||||
{
|
||||
struct xfs_agf __maybe_unused *agf = args->agbp->b_addr;
|
||||
struct xfs_btree_cur *bno_cur;/* by block-number btree cursor */
|
||||
struct xfs_btree_cur *cnt_cur;/* by count btree cursor */
|
||||
int error;
|
||||
@ -1297,7 +1295,7 @@ xfs_alloc_ag_vextent_exact(
|
||||
*/
|
||||
cnt_cur = xfs_cntbt_init_cursor(args->mp, args->tp, args->agbp,
|
||||
args->pag);
|
||||
ASSERT(args->agbno + args->len <= be32_to_cpu(agf->agf_length));
|
||||
ASSERT(xfs_verify_agbext(args->pag, args->agbno, args->len));
|
||||
error = xfs_alloc_fixup_trees(cnt_cur, bno_cur, fbno, flen, args->agbno,
|
||||
args->len, XFSA_FIXUP_BNO_OK);
|
||||
if (error) {
|
||||
|
@ -329,26 +329,20 @@ xfs_attr_calc_size(
|
||||
return nblks;
|
||||
}
|
||||
|
||||
/* Initialize transaction reservation for attr operations */
|
||||
void
|
||||
xfs_init_attr_trans(
|
||||
struct xfs_da_args *args,
|
||||
struct xfs_trans_res *tres,
|
||||
unsigned int *total)
|
||||
/* Initialize transaction reservation for an xattr set/replace/upsert */
|
||||
inline struct xfs_trans_res
|
||||
xfs_attr_set_resv(
|
||||
const struct xfs_da_args *args)
|
||||
{
|
||||
struct xfs_mount *mp = args->dp->i_mount;
|
||||
struct xfs_mount *mp = args->dp->i_mount;
|
||||
struct xfs_trans_res ret = {
|
||||
.tr_logres = M_RES(mp)->tr_attrsetm.tr_logres +
|
||||
M_RES(mp)->tr_attrsetrt.tr_logres * args->total,
|
||||
.tr_logcount = XFS_ATTRSET_LOG_COUNT,
|
||||
.tr_logflags = XFS_TRANS_PERM_LOG_RES,
|
||||
};
|
||||
|
||||
if (args->value) {
|
||||
tres->tr_logres = M_RES(mp)->tr_attrsetm.tr_logres +
|
||||
M_RES(mp)->tr_attrsetrt.tr_logres *
|
||||
args->total;
|
||||
tres->tr_logcount = XFS_ATTRSET_LOG_COUNT;
|
||||
tres->tr_logflags = XFS_TRANS_PERM_LOG_RES;
|
||||
*total = args->total;
|
||||
} else {
|
||||
*tres = M_RES(mp)->tr_attrrm;
|
||||
*total = XFS_ATTRRM_SPACE_RES(mp);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1006,7 +1000,7 @@ xfs_attr_set(
|
||||
struct xfs_trans_res tres;
|
||||
int error, local;
|
||||
int rmt_blks = 0;
|
||||
unsigned int total;
|
||||
unsigned int total = 0;
|
||||
|
||||
ASSERT(!args->trans);
|
||||
|
||||
@ -1033,10 +1027,15 @@ xfs_attr_set(
|
||||
|
||||
if (!local)
|
||||
rmt_blks = xfs_attr3_rmt_blocks(mp, args->valuelen);
|
||||
|
||||
tres = xfs_attr_set_resv(args);
|
||||
total = args->total;
|
||||
break;
|
||||
case XFS_ATTRUPDATE_REMOVE:
|
||||
XFS_STATS_INC(mp, xs_attr_remove);
|
||||
rmt_blks = xfs_attr3_max_rmt_blocks(mp);
|
||||
tres = M_RES(mp)->tr_attrrm;
|
||||
total = XFS_ATTRRM_SPACE_RES(mp);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1044,7 +1043,6 @@ xfs_attr_set(
|
||||
* Root fork attributes can use reserved data blocks for this
|
||||
* operation if necessary
|
||||
*/
|
||||
xfs_init_attr_trans(args, &tres, &total);
|
||||
error = xfs_trans_alloc_inode(dp, &tres, total, 0, rsvd, &args->trans);
|
||||
if (error)
|
||||
return error;
|
||||
|
@ -565,8 +565,7 @@ bool xfs_attr_check_namespace(unsigned int attr_flags);
|
||||
bool xfs_attr_namecheck(unsigned int attr_flags, const void *name,
|
||||
size_t length);
|
||||
int xfs_attr_calc_size(struct xfs_da_args *args, int *local);
|
||||
void xfs_init_attr_trans(struct xfs_da_args *args, struct xfs_trans_res *tres,
|
||||
unsigned int *total);
|
||||
struct xfs_trans_res xfs_attr_set_resv(const struct xfs_da_args *args);
|
||||
|
||||
/*
|
||||
* Check to see if the attr should be upgraded from non-existent or shortform to
|
||||
|
@ -6383,6 +6383,7 @@ xfs_bunmapi_range(
|
||||
error = xfs_defer_finish(tpp);
|
||||
if (error)
|
||||
goto out;
|
||||
cond_resched();
|
||||
}
|
||||
out:
|
||||
return error;
|
||||
|
@ -374,17 +374,37 @@ xfs_dinode_verify_fork(
|
||||
/*
|
||||
* For fork types that can contain local data, check that the fork
|
||||
* format matches the size of local data contained within the fork.
|
||||
*
|
||||
* For all types, check that when the size says the should be in extent
|
||||
* or btree format, the inode isn't claiming it is in local format.
|
||||
*/
|
||||
if (whichfork == XFS_DATA_FORK) {
|
||||
if (S_ISDIR(mode) || S_ISLNK(mode)) {
|
||||
/*
|
||||
* A directory small enough to fit in the inode must be stored
|
||||
* in local format. The directory sf <-> extents conversion
|
||||
* code updates the directory size accordingly.
|
||||
*/
|
||||
if (S_ISDIR(mode)) {
|
||||
if (be64_to_cpu(dip->di_size) <= fork_size &&
|
||||
fork_format != XFS_DINODE_FMT_LOCAL)
|
||||
return __this_address;
|
||||
}
|
||||
|
||||
/*
|
||||
* A symlink with a target small enough to fit in the inode can
|
||||
* be stored in extents format if xattrs were added (thus
|
||||
* converting the data fork from shortform to remote format)
|
||||
* and then removed.
|
||||
*/
|
||||
if (S_ISLNK(mode)) {
|
||||
if (be64_to_cpu(dip->di_size) <= fork_size &&
|
||||
fork_format != XFS_DINODE_FMT_EXTENTS &&
|
||||
fork_format != XFS_DINODE_FMT_LOCAL)
|
||||
return __this_address;
|
||||
}
|
||||
|
||||
/*
|
||||
* For all types, check that when the size says the fork should
|
||||
* be in extent or btree format, the inode isn't claiming to be
|
||||
* in local format.
|
||||
*/
|
||||
if (be64_to_cpu(dip->di_size) > fork_size &&
|
||||
fork_format == XFS_DINODE_FMT_LOCAL)
|
||||
return __this_address;
|
||||
|
@ -856,7 +856,7 @@ xfs_ioc_scrubv_metadata(
|
||||
if (vec_bytes > PAGE_SIZE)
|
||||
return -ENOMEM;
|
||||
|
||||
uvectors = (void __user *)(uintptr_t)head.svh_vectors;
|
||||
uvectors = u64_to_user_ptr(head.svh_vectors);
|
||||
vectors = memdup_user(uvectors, vec_bytes);
|
||||
if (IS_ERR(vectors))
|
||||
return PTR_ERR(vectors);
|
||||
|
@ -822,12 +822,14 @@ xfarray_sort_scan(
|
||||
|
||||
/* Grab the first folio that backs this array element. */
|
||||
if (!si->folio) {
|
||||
struct folio *folio;
|
||||
loff_t next_pos;
|
||||
|
||||
si->folio = xfile_get_folio(si->array->xfile, idx_pos,
|
||||
folio = xfile_get_folio(si->array->xfile, idx_pos,
|
||||
si->array->obj_size, XFILE_ALLOC);
|
||||
if (IS_ERR(si->folio))
|
||||
return PTR_ERR(si->folio);
|
||||
if (IS_ERR(folio))
|
||||
return PTR_ERR(folio);
|
||||
si->folio = folio;
|
||||
|
||||
si->first_folio_idx = xfarray_idx(si->array,
|
||||
folio_pos(si->folio) + si->array->obj_size - 1);
|
||||
@ -1048,6 +1050,7 @@ xfarray_sort(
|
||||
|
||||
out_free:
|
||||
trace_xfarray_sort_stats(si, error);
|
||||
xfarray_sort_scan_done(si);
|
||||
kvfree(si);
|
||||
return error;
|
||||
}
|
||||
|
@ -746,7 +746,7 @@ xfs_attr_recover_work(
|
||||
struct xfs_attri_log_format *attrp;
|
||||
struct xfs_attri_log_nameval *nv = attrip->attri_nameval;
|
||||
int error;
|
||||
int total;
|
||||
unsigned int total = 0;
|
||||
|
||||
/*
|
||||
* First check the validity of the attr described by the ATTRI. If any
|
||||
@ -763,7 +763,20 @@ xfs_attr_recover_work(
|
||||
return PTR_ERR(attr);
|
||||
args = attr->xattri_da_args;
|
||||
|
||||
xfs_init_attr_trans(args, &resv, &total);
|
||||
switch (xfs_attr_intent_op(attr)) {
|
||||
case XFS_ATTRI_OP_FLAGS_PPTR_SET:
|
||||
case XFS_ATTRI_OP_FLAGS_PPTR_REPLACE:
|
||||
case XFS_ATTRI_OP_FLAGS_SET:
|
||||
case XFS_ATTRI_OP_FLAGS_REPLACE:
|
||||
resv = xfs_attr_set_resv(args);
|
||||
total = args->total;
|
||||
break;
|
||||
case XFS_ATTRI_OP_FLAGS_PPTR_REMOVE:
|
||||
case XFS_ATTRI_OP_FLAGS_REMOVE:
|
||||
resv = M_RES(mp)->tr_attrrm;
|
||||
total = XFS_ATTRRM_SPACE_RES(mp);
|
||||
break;
|
||||
}
|
||||
resv = xlog_recover_resv(&resv);
|
||||
error = xfs_trans_alloc(mp, &resv, total, 0, XFS_TRANS_RESERVE, &tp);
|
||||
if (error)
|
||||
|
@ -773,11 +773,6 @@ xfs_getparents_expand_lastrec(
|
||||
trace_xfs_getparents_expand_lastrec(gpx->ip, gp, &gpx->context, gpr);
|
||||
}
|
||||
|
||||
static inline void __user *u64_to_uptr(u64 val)
|
||||
{
|
||||
return (void __user *)(uintptr_t)val;
|
||||
}
|
||||
|
||||
/* Retrieve the parent pointers for a given inode. */
|
||||
STATIC int
|
||||
xfs_getparents(
|
||||
@ -862,7 +857,7 @@ xfs_getparents(
|
||||
ASSERT(gpx->context.firstu <= gpx->gph.gph_request.gp_bufsize);
|
||||
|
||||
/* Copy the records to userspace. */
|
||||
if (copy_to_user(u64_to_uptr(gpx->gph.gph_request.gp_buffer),
|
||||
if (copy_to_user(u64_to_user_ptr(gpx->gph.gph_request.gp_buffer),
|
||||
gpx->krecords, gpx->context.firstu))
|
||||
error = -EFAULT;
|
||||
|
||||
|
@ -351,7 +351,6 @@ xfs_iwalk_run_callbacks(
|
||||
int *has_more)
|
||||
{
|
||||
struct xfs_mount *mp = iwag->mp;
|
||||
struct xfs_inobt_rec_incore *irec;
|
||||
xfs_agino_t next_agino;
|
||||
int error;
|
||||
|
||||
@ -361,8 +360,8 @@ xfs_iwalk_run_callbacks(
|
||||
|
||||
/* Delete cursor but remember the last record we cached... */
|
||||
xfs_iwalk_del_inobt(iwag->tp, curpp, agi_bpp, 0);
|
||||
irec = &iwag->recs[iwag->nr_recs - 1];
|
||||
ASSERT(next_agino >= irec->ir_startino + XFS_INODES_PER_CHUNK);
|
||||
ASSERT(next_agino >= iwag->recs[iwag->nr_recs - 1].ir_startino +
|
||||
XFS_INODES_PER_CHUNK);
|
||||
|
||||
if (iwag->drop_trans) {
|
||||
xfs_trans_cancel(iwag->tp);
|
||||
|
@ -1387,6 +1387,7 @@ xfs_reflink_remap_blocks(
|
||||
destoff += imap.br_blockcount;
|
||||
len -= imap.br_blockcount;
|
||||
remapped_len += imap.br_blockcount;
|
||||
cond_resched();
|
||||
}
|
||||
|
||||
if (error)
|
||||
|
Loading…
Reference in New Issue
Block a user