History

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()

Linus Torvalds committed 2 years ago

Commit bbeb1212 parents f26ee67 b0c6bcd11 files · +73 −46Browse files

Unified · Split

11 files
  1. fs/xfs/libxfs/xfs_alloc.c +2 −4
  2. fs/xfs/libxfs/xfs_attr.c +19 −21
  3. fs/xfs/libxfs/xfs_attr.h +1 −2
  4. fs/xfs/libxfs/xfs_bmap.c +1 −0
  5. fs/xfs/libxfs/xfs_inode_buf.c +24 −4
  6. fs/xfs/scrub/scrub.c +1 −1
  7. fs/xfs/scrub/xfarray.c +6 −3
  8. fs/xfs/xfs_attr_item.c +15 −2
  9. fs/xfs/xfs_handle.c +1 −6
  10. fs/xfs/xfs_iwalk.c +2 −3
  11. fs/xfs/xfs_reflink.c +1 −0
fs/xfs/libxfs/xfs_alloc.c+2−4
@@ -1008,13 +1008,12 @@ xfs_alloc_cur_finish( · 1007 unmodified lines
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 */ · 196 unmodified lines
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( · 73 unmodified lines
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+19−21
@@ -329,26 +329,20 @@ xfs_attr_calc_size( · 328 unmodified lines
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( · 651 unmodified lines
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,10 +1027,15 @@ xfs_attr_set( · 20 unmodified lines
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
@@ -1044,7 +1043,6 @@ xfs_attr_set( · 1 unmodified line
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+1−2
@@ -565,8 +565,7 @@ bool xfs_attr_check_namespace(unsigned int attr_flags); · 564 unmodified lines
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+1−0
@@ -6383,6 +6383,7 @@ xfs_bunmapi_range( · 6382 unmodified lines
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+24−4
@@ -374,17 +374,37 @@ xfs_dinode_verify_fork( · 373 unmodified lines
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+1−1
@@ -856,7 +856,7 @@ xfs_ioc_scrubv_metadata( · 855 unmodified lines
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+6−3
@@ -822,12 +822,14 @@ xfarray_sort_scan( · 821 unmodified lines
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( · 214 unmodified lines
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+15−2
@@ -746,7 +746,7 @@ xfs_attr_recover_work( · 745 unmodified lines
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( · 10 unmodified lines
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+1−6
@@ -773,11 +773,6 @@ xfs_getparents_expand_lastrec( · 772 unmodified lines
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( · 78 unmodified lines
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+2−3
@@ -351,7 +351,6 @@ xfs_iwalk_run_callbacks( · 350 unmodified lines
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( · 3 unmodified lines
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);
fs/xfs/xfs_reflink.c+1−0
@@ -1387,6 +1387,7 @@ xfs_reflink_remap_blocks( · 1386 unmodified lines
13871387 destoff += imap.br_blockcount;
13881388 len -= imap.br_blockcount;
13891389 remapped_len += imap.br_blockcount;
1390+ cond_resched();
13901391 }
13911392
13921393 if (error)