Skip to content

Commit bbeb121

Browse files
committed
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()
2 parents f26ee67 + b0c6bcd commit bbeb121

File tree

11 files changed

+73
-46
lines changed

11 files changed

+73
-46
lines changed

fs/xfs/libxfs/xfs_alloc.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,13 +1008,12 @@ xfs_alloc_cur_finish(
10081008
struct xfs_alloc_arg *args,
10091009
struct xfs_alloc_cur *acur)
10101010
{
1011-
struct xfs_agf __maybe_unused *agf = args->agbp->b_addr;
10121011
int error;
10131012

10141013
ASSERT(acur->cnt && acur->bnolt);
10151014
ASSERT(acur->bno >= acur->rec_bno);
10161015
ASSERT(acur->bno + acur->len <= acur->rec_bno + acur->rec_len);
1017-
ASSERT(acur->rec_bno + acur->rec_len <= be32_to_cpu(agf->agf_length));
1016+
ASSERT(xfs_verify_agbext(args->pag, acur->rec_bno, acur->rec_len));
10181017

10191018
error = xfs_alloc_fixup_trees(acur->cnt, acur->bnolt, acur->rec_bno,
10201019
acur->rec_len, acur->bno, acur->len, 0);
@@ -1217,7 +1216,6 @@ STATIC int /* error */
12171216
xfs_alloc_ag_vextent_exact(
12181217
xfs_alloc_arg_t *args) /* allocation argument structure */
12191218
{
1220-
struct xfs_agf __maybe_unused *agf = args->agbp->b_addr;
12211219
struct xfs_btree_cur *bno_cur;/* by block-number btree cursor */
12221220
struct xfs_btree_cur *cnt_cur;/* by count btree cursor */
12231221
int error;
@@ -1297,7 +1295,7 @@ xfs_alloc_ag_vextent_exact(
12971295
*/
12981296
cnt_cur = xfs_cntbt_init_cursor(args->mp, args->tp, args->agbp,
12991297
args->pag);
1300-
ASSERT(args->agbno + args->len <= be32_to_cpu(agf->agf_length));
1298+
ASSERT(xfs_verify_agbext(args->pag, args->agbno, args->len));
13011299
error = xfs_alloc_fixup_trees(cnt_cur, bno_cur, fbno, flen, args->agbno,
13021300
args->len, XFSA_FIXUP_BNO_OK);
13031301
if (error) {

fs/xfs/libxfs/xfs_attr.c

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -329,26 +329,20 @@ xfs_attr_calc_size(
329329
return nblks;
330330
}
331331

332-
/* Initialize transaction reservation for attr operations */
333-
void
334-
xfs_init_attr_trans(
335-
struct xfs_da_args *args,
336-
struct xfs_trans_res *tres,
337-
unsigned int *total)
332+
/* Initialize transaction reservation for an xattr set/replace/upsert */
333+
inline struct xfs_trans_res
334+
xfs_attr_set_resv(
335+
const struct xfs_da_args *args)
338336
{
339-
struct xfs_mount *mp = args->dp->i_mount;
340-
341-
if (args->value) {
342-
tres->tr_logres = M_RES(mp)->tr_attrsetm.tr_logres +
343-
M_RES(mp)->tr_attrsetrt.tr_logres *
344-
args->total;
345-
tres->tr_logcount = XFS_ATTRSET_LOG_COUNT;
346-
tres->tr_logflags = XFS_TRANS_PERM_LOG_RES;
347-
*total = args->total;
348-
} else {
349-
*tres = M_RES(mp)->tr_attrrm;
350-
*total = XFS_ATTRRM_SPACE_RES(mp);
351-
}
337+
struct xfs_mount *mp = args->dp->i_mount;
338+
struct xfs_trans_res ret = {
339+
.tr_logres = M_RES(mp)->tr_attrsetm.tr_logres +
340+
M_RES(mp)->tr_attrsetrt.tr_logres * args->total,
341+
.tr_logcount = XFS_ATTRSET_LOG_COUNT,
342+
.tr_logflags = XFS_TRANS_PERM_LOG_RES,
343+
};
344+
345+
return ret;
352346
}
353347

354348
/*
@@ -1006,7 +1000,7 @@ xfs_attr_set(
10061000
struct xfs_trans_res tres;
10071001
int error, local;
10081002
int rmt_blks = 0;
1009-
unsigned int total;
1003+
unsigned int total = 0;
10101004

10111005
ASSERT(!args->trans);
10121006

@@ -1033,18 +1027,22 @@ xfs_attr_set(
10331027

10341028
if (!local)
10351029
rmt_blks = xfs_attr3_rmt_blocks(mp, args->valuelen);
1030+
1031+
tres = xfs_attr_set_resv(args);
1032+
total = args->total;
10361033
break;
10371034
case XFS_ATTRUPDATE_REMOVE:
10381035
XFS_STATS_INC(mp, xs_attr_remove);
10391036
rmt_blks = xfs_attr3_max_rmt_blocks(mp);
1037+
tres = M_RES(mp)->tr_attrrm;
1038+
total = XFS_ATTRRM_SPACE_RES(mp);
10401039
break;
10411040
}
10421041

10431042
/*
10441043
* Root fork attributes can use reserved data blocks for this
10451044
* operation if necessary
10461045
*/
1047-
xfs_init_attr_trans(args, &tres, &total);
10481046
error = xfs_trans_alloc_inode(dp, &tres, total, 0, rsvd, &args->trans);
10491047
if (error)
10501048
return error;

fs/xfs/libxfs/xfs_attr.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -565,8 +565,7 @@ bool xfs_attr_check_namespace(unsigned int attr_flags);
565565
bool xfs_attr_namecheck(unsigned int attr_flags, const void *name,
566566
size_t length);
567567
int xfs_attr_calc_size(struct xfs_da_args *args, int *local);
568-
void xfs_init_attr_trans(struct xfs_da_args *args, struct xfs_trans_res *tres,
569-
unsigned int *total);
568+
struct xfs_trans_res xfs_attr_set_resv(const struct xfs_da_args *args);
570569

571570
/*
572571
* Check to see if the attr should be upgraded from non-existent or shortform to

fs/xfs/libxfs/xfs_bmap.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6383,6 +6383,7 @@ xfs_bunmapi_range(
63836383
error = xfs_defer_finish(tpp);
63846384
if (error)
63856385
goto out;
6386+
cond_resched();
63866387
}
63876388
out:
63886389
return error;

fs/xfs/libxfs/xfs_inode_buf.c

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -374,17 +374,37 @@ xfs_dinode_verify_fork(
374374
/*
375375
* For fork types that can contain local data, check that the fork
376376
* format matches the size of local data contained within the fork.
377-
*
378-
* For all types, check that when the size says the should be in extent
379-
* or btree format, the inode isn't claiming it is in local format.
380377
*/
381378
if (whichfork == XFS_DATA_FORK) {
382-
if (S_ISDIR(mode) || S_ISLNK(mode)) {
379+
/*
380+
* A directory small enough to fit in the inode must be stored
381+
* in local format. The directory sf <-> extents conversion
382+
* code updates the directory size accordingly.
383+
*/
384+
if (S_ISDIR(mode)) {
385+
if (be64_to_cpu(dip->di_size) <= fork_size &&
386+
fork_format != XFS_DINODE_FMT_LOCAL)
387+
return __this_address;
388+
}
389+
390+
/*
391+
* A symlink with a target small enough to fit in the inode can
392+
* be stored in extents format if xattrs were added (thus
393+
* converting the data fork from shortform to remote format)
394+
* and then removed.
395+
*/
396+
if (S_ISLNK(mode)) {
383397
if (be64_to_cpu(dip->di_size) <= fork_size &&
398+
fork_format != XFS_DINODE_FMT_EXTENTS &&
384399
fork_format != XFS_DINODE_FMT_LOCAL)
385400
return __this_address;
386401
}
387402

403+
/*
404+
* For all types, check that when the size says the fork should
405+
* be in extent or btree format, the inode isn't claiming to be
406+
* in local format.
407+
*/
388408
if (be64_to_cpu(dip->di_size) > fork_size &&
389409
fork_format == XFS_DINODE_FMT_LOCAL)
390410
return __this_address;

fs/xfs/scrub/scrub.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -856,7 +856,7 @@ xfs_ioc_scrubv_metadata(
856856
if (vec_bytes > PAGE_SIZE)
857857
return -ENOMEM;
858858

859-
uvectors = (void __user *)(uintptr_t)head.svh_vectors;
859+
uvectors = u64_to_user_ptr(head.svh_vectors);
860860
vectors = memdup_user(uvectors, vec_bytes);
861861
if (IS_ERR(vectors))
862862
return PTR_ERR(vectors);

fs/xfs/scrub/xfarray.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -822,12 +822,14 @@ xfarray_sort_scan(
822822

823823
/* Grab the first folio that backs this array element. */
824824
if (!si->folio) {
825+
struct folio *folio;
825826
loff_t next_pos;
826827

827-
si->folio = xfile_get_folio(si->array->xfile, idx_pos,
828+
folio = xfile_get_folio(si->array->xfile, idx_pos,
828829
si->array->obj_size, XFILE_ALLOC);
829-
if (IS_ERR(si->folio))
830-
return PTR_ERR(si->folio);
830+
if (IS_ERR(folio))
831+
return PTR_ERR(folio);
832+
si->folio = folio;
831833

832834
si->first_folio_idx = xfarray_idx(si->array,
833835
folio_pos(si->folio) + si->array->obj_size - 1);
@@ -1048,6 +1050,7 @@ xfarray_sort(
10481050

10491051
out_free:
10501052
trace_xfarray_sort_stats(si, error);
1053+
xfarray_sort_scan_done(si);
10511054
kvfree(si);
10521055
return error;
10531056
}

fs/xfs/xfs_attr_item.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -746,7 +746,7 @@ xfs_attr_recover_work(
746746
struct xfs_attri_log_format *attrp;
747747
struct xfs_attri_log_nameval *nv = attrip->attri_nameval;
748748
int error;
749-
int total;
749+
unsigned int total = 0;
750750

751751
/*
752752
* First check the validity of the attr described by the ATTRI. If any
@@ -763,7 +763,20 @@ xfs_attr_recover_work(
763763
return PTR_ERR(attr);
764764
args = attr->xattri_da_args;
765765

766-
xfs_init_attr_trans(args, &resv, &total);
766+
switch (xfs_attr_intent_op(attr)) {
767+
case XFS_ATTRI_OP_FLAGS_PPTR_SET:
768+
case XFS_ATTRI_OP_FLAGS_PPTR_REPLACE:
769+
case XFS_ATTRI_OP_FLAGS_SET:
770+
case XFS_ATTRI_OP_FLAGS_REPLACE:
771+
resv = xfs_attr_set_resv(args);
772+
total = args->total;
773+
break;
774+
case XFS_ATTRI_OP_FLAGS_PPTR_REMOVE:
775+
case XFS_ATTRI_OP_FLAGS_REMOVE:
776+
resv = M_RES(mp)->tr_attrrm;
777+
total = XFS_ATTRRM_SPACE_RES(mp);
778+
break;
779+
}
767780
resv = xlog_recover_resv(&resv);
768781
error = xfs_trans_alloc(mp, &resv, total, 0, XFS_TRANS_RESERVE, &tp);
769782
if (error)

fs/xfs/xfs_handle.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -773,11 +773,6 @@ xfs_getparents_expand_lastrec(
773773
trace_xfs_getparents_expand_lastrec(gpx->ip, gp, &gpx->context, gpr);
774774
}
775775

776-
static inline void __user *u64_to_uptr(u64 val)
777-
{
778-
return (void __user *)(uintptr_t)val;
779-
}
780-
781776
/* Retrieve the parent pointers for a given inode. */
782777
STATIC int
783778
xfs_getparents(
@@ -862,7 +857,7 @@ xfs_getparents(
862857
ASSERT(gpx->context.firstu <= gpx->gph.gph_request.gp_bufsize);
863858

864859
/* Copy the records to userspace. */
865-
if (copy_to_user(u64_to_uptr(gpx->gph.gph_request.gp_buffer),
860+
if (copy_to_user(u64_to_user_ptr(gpx->gph.gph_request.gp_buffer),
866861
gpx->krecords, gpx->context.firstu))
867862
error = -EFAULT;
868863

fs/xfs/xfs_iwalk.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,6 @@ xfs_iwalk_run_callbacks(
351351
int *has_more)
352352
{
353353
struct xfs_mount *mp = iwag->mp;
354-
struct xfs_inobt_rec_incore *irec;
355354
xfs_agino_t next_agino;
356355
int error;
357356

@@ -361,8 +360,8 @@ xfs_iwalk_run_callbacks(
361360

362361
/* Delete cursor but remember the last record we cached... */
363362
xfs_iwalk_del_inobt(iwag->tp, curpp, agi_bpp, 0);
364-
irec = &iwag->recs[iwag->nr_recs - 1];
365-
ASSERT(next_agino >= irec->ir_startino + XFS_INODES_PER_CHUNK);
363+
ASSERT(next_agino >= iwag->recs[iwag->nr_recs - 1].ir_startino +
364+
XFS_INODES_PER_CHUNK);
366365

367366
if (iwag->drop_trans) {
368367
xfs_trans_cancel(iwag->tp);

0 commit comments

Comments
 (0)