Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+72 -45
+2 -4
fs/xfs/libxfs/xfs_alloc.c
··· 1008 1008 struct xfs_alloc_arg *args, 1009 1009 struct xfs_alloc_cur *acur) 1010 1010 { 1011 - struct xfs_agf __maybe_unused *agf = args->agbp->b_addr; 1012 1011 int error; 1013 1012 1014 1013 ASSERT(acur->cnt && acur->bnolt); 1015 1014 ASSERT(acur->bno >= acur->rec_bno); 1016 1015 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)); 1018 1017 1019 1018 error = xfs_alloc_fixup_trees(acur->cnt, acur->bnolt, acur->rec_bno, 1020 1019 acur->rec_len, acur->bno, acur->len, 0); ··· 1216 1217 xfs_alloc_ag_vextent_exact( 1217 1218 xfs_alloc_arg_t *args) /* allocation argument structure */ 1218 1219 { 1219 - struct xfs_agf __maybe_unused *agf = args->agbp->b_addr; 1220 1220 struct xfs_btree_cur *bno_cur;/* by block-number btree cursor */ 1221 1221 struct xfs_btree_cur *cnt_cur;/* by count btree cursor */ 1222 1222 int error; ··· 1295 1297 */ 1296 1298 cnt_cur = xfs_cntbt_init_cursor(args->mp, args->tp, args->agbp, 1297 1299 args->pag); 1298 - ASSERT(args->agbno + args->len <= be32_to_cpu(agf->agf_length)); 1300 + ASSERT(xfs_verify_agbext(args->pag, args->agbno, args->len)); 1299 1301 error = xfs_alloc_fixup_trees(cnt_cur, bno_cur, fbno, flen, args->agbno, 1300 1302 args->len, XFSA_FIXUP_BNO_OK); 1301 1303 if (error) {
+18 -20
fs/xfs/libxfs/xfs_attr.c
··· 329 329 return nblks; 330 330 } 331 331 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) 338 336 { 339 - struct xfs_mount *mp = args->dp->i_mount; 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 + }; 340 344 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 - } 345 + return ret; 352 346 } 353 347 354 348 /* ··· 1000 1006 struct xfs_trans_res tres; 1001 1007 int error, local; 1002 1008 int rmt_blks = 0; 1003 - unsigned int total; 1009 + unsigned int total = 0; 1004 1010 1005 1011 ASSERT(!args->trans); 1006 1012 ··· 1027 1033 1028 1034 if (!local) 1029 1035 rmt_blks = xfs_attr3_rmt_blocks(mp, args->valuelen); 1036 + 1037 + tres = xfs_attr_set_resv(args); 1038 + total = args->total; 1030 1039 break; 1031 1040 case XFS_ATTRUPDATE_REMOVE: 1032 1041 XFS_STATS_INC(mp, xs_attr_remove); 1033 1042 rmt_blks = xfs_attr3_max_rmt_blocks(mp); 1043 + tres = M_RES(mp)->tr_attrrm; 1044 + total = XFS_ATTRRM_SPACE_RES(mp); 1034 1045 break; 1035 1046 } 1036 1047 ··· 1043 1044 * Root fork attributes can use reserved data blocks for this 1044 1045 * operation if necessary 1045 1046 */ 1046 - xfs_init_attr_trans(args, &tres, &total); 1047 1047 error = xfs_trans_alloc_inode(dp, &tres, total, 0, rsvd, &args->trans); 1048 1048 if (error) 1049 1049 return error;
+1 -2
fs/xfs/libxfs/xfs_attr.h
··· 565 565 bool xfs_attr_namecheck(unsigned int attr_flags, const void *name, 566 566 size_t length); 567 567 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); 570 569 571 570 /* 572 571 * Check to see if the attr should be upgraded from non-existent or shortform to
+1
fs/xfs/libxfs/xfs_bmap.c
··· 6383 6383 error = xfs_defer_finish(tpp); 6384 6384 if (error) 6385 6385 goto out; 6386 + cond_resched(); 6386 6387 } 6387 6388 out: 6388 6389 return error;
+24 -4
fs/xfs/libxfs/xfs_inode_buf.c
··· 374 374 /* 375 375 * For fork types that can contain local data, check that the fork 376 376 * 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. 380 377 */ 381 378 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)) { 383 385 if (be64_to_cpu(dip->di_size) <= fork_size && 384 386 fork_format != XFS_DINODE_FMT_LOCAL) 385 387 return __this_address; 386 388 } 387 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)) { 397 + if (be64_to_cpu(dip->di_size) <= fork_size && 398 + fork_format != XFS_DINODE_FMT_EXTENTS && 399 + fork_format != XFS_DINODE_FMT_LOCAL) 400 + return __this_address; 401 + } 402 + 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 + */ 388 408 if (be64_to_cpu(dip->di_size) > fork_size && 389 409 fork_format == XFS_DINODE_FMT_LOCAL) 390 410 return __this_address;
+1 -1
fs/xfs/scrub/scrub.c
··· 856 856 if (vec_bytes > PAGE_SIZE) 857 857 return -ENOMEM; 858 858 859 - uvectors = (void __user *)(uintptr_t)head.svh_vectors; 859 + uvectors = u64_to_user_ptr(head.svh_vectors); 860 860 vectors = memdup_user(uvectors, vec_bytes); 861 861 if (IS_ERR(vectors)) 862 862 return PTR_ERR(vectors);
+6 -3
fs/xfs/scrub/xfarray.c
··· 822 822 823 823 /* Grab the first folio that backs this array element. */ 824 824 if (!si->folio) { 825 + struct folio *folio; 825 826 loff_t next_pos; 826 827 827 - si->folio = xfile_get_folio(si->array->xfile, idx_pos, 828 + folio = xfile_get_folio(si->array->xfile, idx_pos, 828 829 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; 831 833 832 834 si->first_folio_idx = xfarray_idx(si->array, 833 835 folio_pos(si->folio) + si->array->obj_size - 1); ··· 1050 1048 1051 1049 out_free: 1052 1050 trace_xfarray_sort_stats(si, error); 1051 + xfarray_sort_scan_done(si); 1053 1052 kvfree(si); 1054 1053 return error; 1055 1054 }
+15 -2
fs/xfs/xfs_attr_item.c
··· 746 746 struct xfs_attri_log_format *attrp; 747 747 struct xfs_attri_log_nameval *nv = attrip->attri_nameval; 748 748 int error; 749 - int total; 749 + unsigned int total = 0; 750 750 751 751 /* 752 752 * First check the validity of the attr described by the ATTRI. If any ··· 763 763 return PTR_ERR(attr); 764 764 args = attr->xattri_da_args; 765 765 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 + } 767 780 resv = xlog_recover_resv(&resv); 768 781 error = xfs_trans_alloc(mp, &resv, total, 0, XFS_TRANS_RESERVE, &tp); 769 782 if (error)
+1 -6
fs/xfs/xfs_handle.c
··· 773 773 trace_xfs_getparents_expand_lastrec(gpx->ip, gp, &gpx->context, gpr); 774 774 } 775 775 776 - static inline void __user *u64_to_uptr(u64 val) 777 - { 778 - return (void __user *)(uintptr_t)val; 779 - } 780 - 781 776 /* Retrieve the parent pointers for a given inode. */ 782 777 STATIC int 783 778 xfs_getparents( ··· 857 862 ASSERT(gpx->context.firstu <= gpx->gph.gph_request.gp_bufsize); 858 863 859 864 /* Copy the records to userspace. */ 860 - if (copy_to_user(u64_to_uptr(gpx->gph.gph_request.gp_buffer), 865 + if (copy_to_user(u64_to_user_ptr(gpx->gph.gph_request.gp_buffer), 861 866 gpx->krecords, gpx->context.firstu)) 862 867 error = -EFAULT; 863 868
+2 -3
fs/xfs/xfs_iwalk.c
··· 351 351 int *has_more) 352 352 { 353 353 struct xfs_mount *mp = iwag->mp; 354 - struct xfs_inobt_rec_incore *irec; 355 354 xfs_agino_t next_agino; 356 355 int error; 357 356 ··· 360 361 361 362 /* Delete cursor but remember the last record we cached... */ 362 363 xfs_iwalk_del_inobt(iwag->tp, curpp, agi_bpp, 0); 363 - irec = &iwag->recs[iwag->nr_recs - 1]; 364 - ASSERT(next_agino >= irec->ir_startino + XFS_INODES_PER_CHUNK); 364 + ASSERT(next_agino >= iwag->recs[iwag->nr_recs - 1].ir_startino + 365 + XFS_INODES_PER_CHUNK); 365 366 366 367 if (iwag->drop_trans) { 367 368 xfs_trans_cancel(iwag->tp);
+1
fs/xfs/xfs_reflink.c
··· 1387 1387 destoff += imap.br_blockcount; 1388 1388 len -= imap.br_blockcount; 1389 1389 remapped_len += imap.br_blockcount; 1390 + cond_resched(); 1390 1391 } 1391 1392 1392 1393 if (error)