Skip to content

Commit 27b31de

Browse files
committed
Merge tag 'xfs-6.10-fixes-5' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
Pull xfs fixes from Chandan Babu: - Always free only post-EOF delayed allocations for files with the XFS_DIFLAG_PREALLOC or APPEND flags set. - Do not align cow fork delalloc to cowextsz hint when running low on space. - Allow zero-size symlinks and directories as long as the link count is zero. - Change XFS_IOC_EXCHANGE_RANGE to be a _IOW only ioctl. This was ioctl was introduced during v6.10 developement cycle. - xfs_init_new_inode() now creates an attribute fork on a newly created inode even if ATTR feature flag is not enabled. * tag 'xfs-6.10-fixes-5' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: xfs: honor init_xattrs in xfs_init_new_inode for !ATTR fs xfs: fix direction in XFS_IOC_EXCHANGE_RANGE xfs: allow unlinked symlinks and dirs with zero size xfs: restrict when we try to align cow fork delalloc to cowextsz hints xfs: fix freeing speculative preallocations for preallocated files
2 parents ebe70b3 + 673cd88 commit 27b31de

File tree

8 files changed

+95
-53
lines changed

8 files changed

+95
-53
lines changed

fs/xfs/libxfs/xfs_bmap.c

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4058,20 +4058,32 @@ xfs_bmapi_reserve_delalloc(
40584058
xfs_extlen_t indlen;
40594059
uint64_t fdblocks;
40604060
int error;
4061-
xfs_fileoff_t aoff = off;
4061+
xfs_fileoff_t aoff;
4062+
bool use_cowextszhint =
4063+
whichfork == XFS_COW_FORK && !prealloc;
40624064

4065+
retry:
40634066
/*
40644067
* Cap the alloc length. Keep track of prealloc so we know whether to
40654068
* tag the inode before we return.
40664069
*/
4070+
aoff = off;
40674071
alen = XFS_FILBLKS_MIN(len + prealloc, XFS_MAX_BMBT_EXTLEN);
40684072
if (!eof)
40694073
alen = XFS_FILBLKS_MIN(alen, got->br_startoff - aoff);
40704074
if (prealloc && alen >= len)
40714075
prealloc = alen - len;
40724076

4073-
/* Figure out the extent size, adjust alen */
4074-
if (whichfork == XFS_COW_FORK) {
4077+
/*
4078+
* If we're targetting the COW fork but aren't creating a speculative
4079+
* posteof preallocation, try to expand the reservation to align with
4080+
* the COW extent size hint if there's sufficient free space.
4081+
*
4082+
* Unlike the data fork, the CoW cancellation functions will free all
4083+
* the reservations at inactivation, so we don't require that every
4084+
* delalloc reservation have a dirty pagecache.
4085+
*/
4086+
if (use_cowextszhint) {
40754087
struct xfs_bmbt_irec prev;
40764088
xfs_extlen_t extsz = xfs_get_cowextsz_hint(ip);
40774089

@@ -4090,7 +4102,7 @@ xfs_bmapi_reserve_delalloc(
40904102
*/
40914103
error = xfs_quota_reserve_blkres(ip, alen);
40924104
if (error)
4093-
return error;
4105+
goto out;
40944106

40954107
/*
40964108
* Split changing sb for alen and indlen since they could be coming
@@ -4140,6 +4152,17 @@ xfs_bmapi_reserve_delalloc(
41404152
out_unreserve_quota:
41414153
if (XFS_IS_QUOTA_ON(mp))
41424154
xfs_quota_unreserve_blkres(ip, alen);
4155+
out:
4156+
if (error == -ENOSPC || error == -EDQUOT) {
4157+
trace_xfs_delalloc_enospc(ip, off, len);
4158+
4159+
if (prealloc || use_cowextszhint) {
4160+
/* retry without any preallocation */
4161+
use_cowextszhint = false;
4162+
prealloc = 0;
4163+
goto retry;
4164+
}
4165+
}
41434166
return error;
41444167
}
41454168

fs/xfs/libxfs/xfs_fs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -996,7 +996,7 @@ struct xfs_getparents_by_handle {
996996
#define XFS_IOC_FSGEOMETRY _IOR ('X', 126, struct xfs_fsop_geom)
997997
#define XFS_IOC_BULKSTAT _IOR ('X', 127, struct xfs_bulkstat_req)
998998
#define XFS_IOC_INUMBERS _IOR ('X', 128, struct xfs_inumbers_req)
999-
#define XFS_IOC_EXCHANGE_RANGE _IOWR('X', 129, struct xfs_exchange_range)
999+
#define XFS_IOC_EXCHANGE_RANGE _IOW ('X', 129, struct xfs_exchange_range)
10001000
/* XFS_IOC_GETFSUUID ---------- deprecated 140 */
10011001

10021002

fs/xfs/libxfs/xfs_inode_buf.c

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -379,10 +379,13 @@ xfs_dinode_verify_fork(
379379
/*
380380
* A directory small enough to fit in the inode must be stored
381381
* in local format. The directory sf <-> extents conversion
382-
* code updates the directory size accordingly.
382+
* code updates the directory size accordingly. Directories
383+
* being truncated have zero size and are not subject to this
384+
* check.
383385
*/
384386
if (S_ISDIR(mode)) {
385-
if (be64_to_cpu(dip->di_size) <= fork_size &&
387+
if (dip->di_size &&
388+
be64_to_cpu(dip->di_size) <= fork_size &&
386389
fork_format != XFS_DINODE_FMT_LOCAL)
387390
return __this_address;
388391
}
@@ -528,9 +531,19 @@ xfs_dinode_verify(
528531
if (mode && xfs_mode_to_ftype(mode) == XFS_DIR3_FT_UNKNOWN)
529532
return __this_address;
530533

531-
/* No zero-length symlinks/dirs. */
532-
if ((S_ISLNK(mode) || S_ISDIR(mode)) && di_size == 0)
533-
return __this_address;
534+
/*
535+
* No zero-length symlinks/dirs unless they're unlinked and hence being
536+
* inactivated.
537+
*/
538+
if ((S_ISLNK(mode) || S_ISDIR(mode)) && di_size == 0) {
539+
if (dip->di_version > 1) {
540+
if (dip->di_nlink)
541+
return __this_address;
542+
} else {
543+
if (dip->di_onlink)
544+
return __this_address;
545+
}
546+
}
534547

535548
fa = xfs_dinode_verify_nrext64(mp, dip);
536549
if (fa)

fs/xfs/xfs_bmap_util.c

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -486,13 +486,11 @@ xfs_bmap_punch_delalloc_range(
486486

487487
/*
488488
* Test whether it is appropriate to check an inode for and free post EOF
489-
* blocks. The 'force' parameter determines whether we should also consider
490-
* regular files that are marked preallocated or append-only.
489+
* blocks.
491490
*/
492491
bool
493492
xfs_can_free_eofblocks(
494-
struct xfs_inode *ip,
495-
bool force)
493+
struct xfs_inode *ip)
496494
{
497495
struct xfs_bmbt_irec imap;
498496
struct xfs_mount *mp = ip->i_mount;
@@ -526,11 +524,11 @@ xfs_can_free_eofblocks(
526524
return false;
527525

528526
/*
529-
* Do not free real preallocated or append-only files unless the file
530-
* has delalloc blocks and we are forced to remove them.
527+
* Only free real extents for inodes with persistent preallocations or
528+
* the append-only flag.
531529
*/
532530
if (ip->i_diflags & (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND))
533-
if (!force || ip->i_delayed_blks == 0)
531+
if (ip->i_delayed_blks == 0)
534532
return false;
535533

536534
/*
@@ -584,6 +582,22 @@ xfs_free_eofblocks(
584582
/* Wait on dio to ensure i_size has settled. */
585583
inode_dio_wait(VFS_I(ip));
586584

585+
/*
586+
* For preallocated files only free delayed allocations.
587+
*
588+
* Note that this means we also leave speculative preallocations in
589+
* place for preallocated files.
590+
*/
591+
if (ip->i_diflags & (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) {
592+
if (ip->i_delayed_blks) {
593+
xfs_bmap_punch_delalloc_range(ip,
594+
round_up(XFS_ISIZE(ip), mp->m_sb.sb_blocksize),
595+
LLONG_MAX);
596+
}
597+
xfs_inode_clear_eofblocks_tag(ip);
598+
return 0;
599+
}
600+
587601
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
588602
if (error) {
589603
ASSERT(xfs_is_shutdown(mp));
@@ -891,7 +905,7 @@ xfs_prepare_shift(
891905
* Trim eofblocks to avoid shifting uninitialized post-eof preallocation
892906
* into the accessible region of the file.
893907
*/
894-
if (xfs_can_free_eofblocks(ip, true)) {
908+
if (xfs_can_free_eofblocks(ip)) {
895909
error = xfs_free_eofblocks(ip);
896910
if (error)
897911
return error;

fs/xfs/xfs_bmap_util.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ int xfs_insert_file_space(struct xfs_inode *, xfs_off_t offset,
6363
xfs_off_t len);
6464

6565
/* EOF block manipulation functions */
66-
bool xfs_can_free_eofblocks(struct xfs_inode *ip, bool force);
66+
bool xfs_can_free_eofblocks(struct xfs_inode *ip);
6767
int xfs_free_eofblocks(struct xfs_inode *ip);
6868

6969
int xfs_swap_extents(struct xfs_inode *ip, struct xfs_inode *tip,

fs/xfs/xfs_icache.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1155,7 +1155,7 @@ xfs_inode_free_eofblocks(
11551155
}
11561156
*lockflags |= XFS_IOLOCK_EXCL;
11571157

1158-
if (xfs_can_free_eofblocks(ip, false))
1158+
if (xfs_can_free_eofblocks(ip))
11591159
return xfs_free_eofblocks(ip);
11601160

11611161
/* inode could be preallocated or append-only */

fs/xfs/xfs_inode.c

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include "xfs_pnfs.h"
4343
#include "xfs_parent.h"
4444
#include "xfs_xattr.h"
45+
#include "xfs_sb.h"
4546

4647
struct kmem_cache *xfs_inode_cache;
4748

@@ -870,9 +871,16 @@ xfs_init_new_inode(
870871
* this saves us from needing to run a separate transaction to set the
871872
* fork offset in the immediate future.
872873
*/
873-
if (init_xattrs && xfs_has_attr(mp)) {
874+
if (init_xattrs) {
874875
ip->i_forkoff = xfs_default_attroffset(ip) >> 3;
875876
xfs_ifork_init_attr(ip, XFS_DINODE_FMT_EXTENTS, 0);
877+
878+
if (!xfs_has_attr(mp)) {
879+
spin_lock(&mp->m_sb_lock);
880+
xfs_add_attr(mp);
881+
spin_unlock(&mp->m_sb_lock);
882+
xfs_log_sb(tp);
883+
}
876884
}
877885

878886
/*
@@ -1595,7 +1603,7 @@ xfs_release(
15951603
if (!xfs_ilock_nowait(ip, XFS_IOLOCK_EXCL))
15961604
return 0;
15971605

1598-
if (xfs_can_free_eofblocks(ip, false)) {
1606+
if (xfs_can_free_eofblocks(ip)) {
15991607
/*
16001608
* Check if the inode is being opened, written and closed
16011609
* frequently and we have delayed allocation blocks outstanding
@@ -1856,15 +1864,13 @@ xfs_inode_needs_inactive(
18561864

18571865
/*
18581866
* This file isn't being freed, so check if there are post-eof blocks
1859-
* to free. @force is true because we are evicting an inode from the
1860-
* cache. Post-eof blocks must be freed, lest we end up with broken
1861-
* free space accounting.
1867+
* to free.
18621868
*
18631869
* Note: don't bother with iolock here since lockdep complains about
18641870
* acquiring it in reclaim context. We have the only reference to the
18651871
* inode at this point anyways.
18661872
*/
1867-
return xfs_can_free_eofblocks(ip, true);
1873+
return xfs_can_free_eofblocks(ip);
18681874
}
18691875

18701876
/*
@@ -1947,15 +1953,11 @@ xfs_inactive(
19471953

19481954
if (VFS_I(ip)->i_nlink != 0) {
19491955
/*
1950-
* force is true because we are evicting an inode from the
1951-
* cache. Post-eof blocks must be freed, lest we end up with
1952-
* broken free space accounting.
1953-
*
19541956
* Note: don't bother with iolock here since lockdep complains
19551957
* about acquiring it in reclaim context. We have the only
19561958
* reference to the inode at this point anyways.
19571959
*/
1958-
if (xfs_can_free_eofblocks(ip, true))
1960+
if (xfs_can_free_eofblocks(ip))
19591961
error = xfs_free_eofblocks(ip);
19601962

19611963
goto out;

fs/xfs/xfs_iomap.c

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,33 +1148,23 @@ xfs_buffered_write_iomap_begin(
11481148
}
11491149
}
11501150

1151-
retry:
1152-
error = xfs_bmapi_reserve_delalloc(ip, allocfork, offset_fsb,
1153-
end_fsb - offset_fsb, prealloc_blocks,
1154-
allocfork == XFS_DATA_FORK ? &imap : &cmap,
1155-
allocfork == XFS_DATA_FORK ? &icur : &ccur,
1156-
allocfork == XFS_DATA_FORK ? eof : cow_eof);
1157-
switch (error) {
1158-
case 0:
1159-
break;
1160-
case -ENOSPC:
1161-
case -EDQUOT:
1162-
/* retry without any preallocation */
1163-
trace_xfs_delalloc_enospc(ip, offset, count);
1164-
if (prealloc_blocks) {
1165-
prealloc_blocks = 0;
1166-
goto retry;
1167-
}
1168-
fallthrough;
1169-
default:
1170-
goto out_unlock;
1171-
}
1172-
11731151
if (allocfork == XFS_COW_FORK) {
1152+
error = xfs_bmapi_reserve_delalloc(ip, allocfork, offset_fsb,
1153+
end_fsb - offset_fsb, prealloc_blocks, &cmap,
1154+
&ccur, cow_eof);
1155+
if (error)
1156+
goto out_unlock;
1157+
11741158
trace_xfs_iomap_alloc(ip, offset, count, allocfork, &cmap);
11751159
goto found_cow;
11761160
}
11771161

1162+
error = xfs_bmapi_reserve_delalloc(ip, allocfork, offset_fsb,
1163+
end_fsb - offset_fsb, prealloc_blocks, &imap, &icur,
1164+
eof);
1165+
if (error)
1166+
goto out_unlock;
1167+
11781168
/*
11791169
* Flag newly allocated delalloc blocks with IOMAP_F_NEW so we punch
11801170
* them out if the write happens to fail.

0 commit comments

Comments
 (0)