Skip to content

Commit

Permalink
Merge tag 'xfs-5.18-merge-2' of git://git.kernel.org/pub/scm/fs/xfs/x…
Browse files Browse the repository at this point in the history
…fs-linux

Pull xfs updates from Darrick Wong:
 "The biggest change this cycle is bringing XFS' inode attribute setting
  code back towards alignment with what the VFS does. IOWs, setgid bit
  handling should be a closer match with ext4 and btrfs behavior.

  The rest of the branch is bug fixes around the filesystem -- patching
  gaps in quota enforcement, removing bogus selinux audit messages, and
  fixing log corruption and problems with log recovery. There will be a
  second pull request later on in the merge window with more bug fixes.

  Dave Chinner will be taking over as XFS maintainer for one release
  cycle, starting from the day 5.18-rc1 drops until 5.19-rc1 is tagged
  so that I can focus on starting a massive design review for the
  (feature complete after five years) online repair feature.

  Summary:

   - Fix some incorrect mapping state being passed to iomap during COW

   - Don't create bogus selinux audit messages when deciding to degrade
     gracefully due to lack of privilege

   - Fix setattr implementation to use VFS helpers so that we drop
     setgid consistently with the other filesystems

   - Fix link/unlink/rename to check quota limits

   - Constify xfs_name_dotdot to prevent abuse of in-kernel symbols

   - Fix log livelock between the AIL and inodegc threads during
     recovery

   - Fix a log stall when the AIL races with pushers

   - Fix stalls in CIL flushes due to pinned inode cluster buffers
     during recovery

   - Fix log corruption due to incorrect usage of xfs_is_shutdown vs
     xlog_is_shutdown because during an induced fs shutdown, AIL
     writeback must continue until the log is shut down, even if the
     filesystem has already shut down"

* tag 'xfs-5.18-merge-2' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux:
  xfs: xfs_is_shutdown vs xlog_is_shutdown cage fight
  xfs: AIL should be log centric
  xfs: log items should have a xlog pointer, not a mount
  xfs: async CIL flushes need pending pushes to be made stable
  xfs: xfs_ail_push_all_sync() stalls when racing with updates
  xfs: check buffer pin state after locking in delwri_submit
  xfs: log worker needs to start before intent/unlink recovery
  xfs: constify xfs_name_dotdot
  xfs: constify the name argument to various directory functions
  xfs: reserve quota for target dir expansion when renaming files
  xfs: reserve quota for dir expansion when linking/unlinking files
  xfs: refactor user/group quota chown in xfs_setattr_nonsize
  xfs: use setattr_copy to set vfs inode attributes
  xfs: don't generate selinux audit messages for capability testing
  xfs: add missing cmap->br_state = XFS_EXT_NORM update
  • Loading branch information
torvalds committed Mar 25, 2022
2 parents f0614ee + 01728b4 commit b1b07ba
Show file tree
Hide file tree
Showing 27 changed files with 344 additions and 211 deletions.
36 changes: 20 additions & 16 deletions fs/xfs/libxfs/xfs_dir2.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@
#include "xfs_error.h"
#include "xfs_trace.h"

struct xfs_name xfs_name_dotdot = { (unsigned char *)"..", 2, XFS_DIR3_FT_DIR };
const struct xfs_name xfs_name_dotdot = {
.name = (const unsigned char *)"..",
.len = 2,
.type = XFS_DIR3_FT_DIR,
};

/*
* Convert inode mode to directory entry filetype
Expand Down Expand Up @@ -54,10 +58,10 @@ xfs_mode_to_ftype(
*/
xfs_dahash_t
xfs_ascii_ci_hashname(
struct xfs_name *name)
const struct xfs_name *name)
{
xfs_dahash_t hash;
int i;
xfs_dahash_t hash;
int i;

for (i = 0, hash = 0; i < name->len; i++)
hash = tolower(name->name[i]) ^ rol32(hash, 7);
Expand Down Expand Up @@ -243,7 +247,7 @@ int
xfs_dir_createname(
struct xfs_trans *tp,
struct xfs_inode *dp,
struct xfs_name *name,
const struct xfs_name *name,
xfs_ino_t inum, /* new entry inode number */
xfs_extlen_t total) /* bmap's total block count */
{
Expand Down Expand Up @@ -337,16 +341,16 @@ xfs_dir_cilookup_result(

int
xfs_dir_lookup(
xfs_trans_t *tp,
xfs_inode_t *dp,
struct xfs_name *name,
xfs_ino_t *inum, /* out: inode number */
struct xfs_name *ci_name) /* out: actual name if CI match */
struct xfs_trans *tp,
struct xfs_inode *dp,
const struct xfs_name *name,
xfs_ino_t *inum, /* out: inode number */
struct xfs_name *ci_name) /* out: actual name if CI match */
{
struct xfs_da_args *args;
int rval;
int v; /* type-checking value */
int lock_mode;
struct xfs_da_args *args;
int rval;
int v; /* type-checking value */
int lock_mode;

ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
XFS_STATS_INC(dp->i_mount, xs_dir_lookup);
Expand Down Expand Up @@ -475,7 +479,7 @@ int
xfs_dir_replace(
struct xfs_trans *tp,
struct xfs_inode *dp,
struct xfs_name *name, /* name of entry to replace */
const struct xfs_name *name, /* name of entry to replace */
xfs_ino_t inum, /* new inode number */
xfs_extlen_t total) /* bmap's total block count */
{
Expand Down Expand Up @@ -728,7 +732,7 @@ xfs_dir2_namecheck(
xfs_dahash_t
xfs_dir2_hashname(
struct xfs_mount *mp,
struct xfs_name *name)
const struct xfs_name *name)
{
if (unlikely(xfs_has_asciici(mp)))
return xfs_ascii_ci_hashname(name);
Expand Down
8 changes: 4 additions & 4 deletions fs/xfs/libxfs/xfs_dir2.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ struct xfs_dir2_data_unused;
struct xfs_dir3_icfree_hdr;
struct xfs_dir3_icleaf_hdr;

extern struct xfs_name xfs_name_dotdot;
extern const struct xfs_name xfs_name_dotdot;

/*
* Convert inode mode to directory entry filetype
Expand All @@ -39,16 +39,16 @@ extern int xfs_dir_isempty(struct xfs_inode *dp);
extern int xfs_dir_init(struct xfs_trans *tp, struct xfs_inode *dp,
struct xfs_inode *pdp);
extern int xfs_dir_createname(struct xfs_trans *tp, struct xfs_inode *dp,
struct xfs_name *name, xfs_ino_t inum,
const struct xfs_name *name, xfs_ino_t inum,
xfs_extlen_t tot);
extern int xfs_dir_lookup(struct xfs_trans *tp, struct xfs_inode *dp,
struct xfs_name *name, xfs_ino_t *inum,
const struct xfs_name *name, xfs_ino_t *inum,
struct xfs_name *ci_name);
extern int xfs_dir_removename(struct xfs_trans *tp, struct xfs_inode *dp,
struct xfs_name *name, xfs_ino_t ino,
xfs_extlen_t tot);
extern int xfs_dir_replace(struct xfs_trans *tp, struct xfs_inode *dp,
struct xfs_name *name, xfs_ino_t inum,
const struct xfs_name *name, xfs_ino_t inum,
xfs_extlen_t tot);
extern int xfs_dir_canenter(struct xfs_trans *tp, struct xfs_inode *dp,
struct xfs_name *name);
Expand Down
5 changes: 3 additions & 2 deletions fs/xfs/libxfs/xfs_dir2_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ struct xfs_dir3_icfree_hdr {
};

/* xfs_dir2.c */
xfs_dahash_t xfs_ascii_ci_hashname(struct xfs_name *name);
xfs_dahash_t xfs_ascii_ci_hashname(const struct xfs_name *name);
enum xfs_dacmp xfs_ascii_ci_compname(struct xfs_da_args *args,
const unsigned char *name, int len);
extern int xfs_dir2_grow_inode(struct xfs_da_args *args, int space,
Expand Down Expand Up @@ -201,7 +201,8 @@ xfs_dir2_data_entsize(
return round_up(len, XFS_DIR2_DATA_ALIGN);
}

xfs_dahash_t xfs_dir2_hashname(struct xfs_mount *mp, struct xfs_name *name);
xfs_dahash_t xfs_dir2_hashname(struct xfs_mount *mp,
const struct xfs_name *name);
enum xfs_dacmp xfs_dir2_compname(struct xfs_da_args *args,
const unsigned char *name, int len);

Expand Down
2 changes: 1 addition & 1 deletion fs/xfs/xfs_bmap_item.c
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ xfs_bui_item_recover(
struct xfs_bui_log_item *buip = BUI_ITEM(lip);
struct xfs_trans *tp;
struct xfs_inode *ip = NULL;
struct xfs_mount *mp = lip->li_mountp;
struct xfs_mount *mp = lip->li_log->l_mp;
struct xfs_map_extent *bmap;
struct xfs_bud_log_item *budp;
xfs_filblks_t count;
Expand Down
45 changes: 35 additions & 10 deletions fs/xfs/xfs_buf.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "xfs_trace.h"
#include "xfs_log.h"
#include "xfs_log_recover.h"
#include "xfs_log_priv.h"
#include "xfs_trans.h"
#include "xfs_buf_item.h"
#include "xfs_errortag.h"
Expand Down Expand Up @@ -813,7 +814,15 @@ xfs_buf_read_map(
* buffer.
*/
if (error) {
if (!xfs_is_shutdown(target->bt_mount))
/*
* Check against log shutdown for error reporting because
* metadata writeback may require a read first and we need to
* report errors in metadata writeback until the log is shut
* down. High level transaction read functions already check
* against mount shutdown, anyway, so we only need to be
* concerned about low level IO interactions here.
*/
if (!xlog_is_shutdown(target->bt_mount->m_log))
xfs_buf_ioerror_alert(bp, fa);

bp->b_flags &= ~XBF_DONE;
Expand Down Expand Up @@ -1174,10 +1183,10 @@ xfs_buf_ioend_handle_error(
struct xfs_error_cfg *cfg;

/*
* If we've already decided to shutdown the filesystem because of I/O
* errors, there's no point in giving this a retry.
* If we've already shutdown the journal because of I/O errors, there's
* no point in giving this a retry.
*/
if (xfs_is_shutdown(mp))
if (xlog_is_shutdown(mp->m_log))
goto out_stale;

xfs_buf_ioerror_alert_ratelimited(bp);
Expand Down Expand Up @@ -1588,8 +1597,23 @@ __xfs_buf_submit(

ASSERT(!(bp->b_flags & _XBF_DELWRI_Q));

/* on shutdown we stale and complete the buffer immediately */
if (xfs_is_shutdown(bp->b_mount)) {
/*
* On log shutdown we stale and complete the buffer immediately. We can
* be called to read the superblock before the log has been set up, so
* be careful checking the log state.
*
* Checking the mount shutdown state here can result in the log tail
* moving inappropriately on disk as the log may not yet be shut down.
* i.e. failing this buffer on mount shutdown can remove it from the AIL
* and move the tail of the log forwards without having written this
* buffer to disk. This corrupts the log tail state in memory, and
* because the log may not be shut down yet, it can then be propagated
* to disk before the log is shutdown. Hence we check log shutdown
* state here rather than mount state to avoid corrupting the log tail
* on shutdown.
*/
if (bp->b_mount->m_log &&
xlog_is_shutdown(bp->b_mount->m_log)) {
xfs_buf_ioend_fail(bp);
return -EIO;
}
Expand Down Expand Up @@ -1803,10 +1827,10 @@ xfs_buftarg_drain(
* If one or more failed buffers were freed, that means dirty metadata
* was thrown away. This should only ever happen after I/O completion
* handling has elevated I/O error(s) to permanent failures and shuts
* down the fs.
* down the journal.
*/
if (write_fail) {
ASSERT(xfs_is_shutdown(btp->bt_mount));
ASSERT(xlog_is_shutdown(btp->bt_mount->m_log));
xfs_alert(btp->bt_mount,
"Please run xfs_repair to determine the extent of the problem.");
}
Expand Down Expand Up @@ -2089,12 +2113,13 @@ xfs_buf_delwri_submit_buffers(
blk_start_plug(&plug);
list_for_each_entry_safe(bp, n, buffer_list, b_list) {
if (!wait_list) {
if (!xfs_buf_trylock(bp))
continue;
if (xfs_buf_ispinned(bp)) {
xfs_buf_unlock(bp);
pinned++;
continue;
}
if (!xfs_buf_trylock(bp))
continue;
} else {
xfs_buf_lock(bp);
}
Expand Down
5 changes: 3 additions & 2 deletions fs/xfs/xfs_buf_item.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "xfs_dquot.h"
#include "xfs_trace.h"
#include "xfs_log.h"
#include "xfs_log_priv.h"


struct kmem_cache *xfs_buf_item_cache;
Expand Down Expand Up @@ -428,7 +429,7 @@ xfs_buf_item_format(
* occurs during recovery.
*/
if (bip->bli_flags & XFS_BLI_INODE_BUF) {
if (xfs_has_v3inodes(lip->li_mountp) ||
if (xfs_has_v3inodes(lip->li_log->l_mp) ||
!((bip->bli_flags & XFS_BLI_INODE_ALLOC_BUF) &&
xfs_log_item_in_current_chkpt(lip)))
bip->__bli_format.blf_flags |= XFS_BLF_INODE_BUF;
Expand Down Expand Up @@ -616,7 +617,7 @@ xfs_buf_item_put(
* that case, the bli is freed on buffer writeback completion.
*/
aborted = test_bit(XFS_LI_ABORTED, &lip->li_flags) ||
xfs_is_shutdown(lip->li_mountp);
xlog_is_shutdown(lip->li_log);
dirty = bip->bli_flags & XFS_BLI_DIRTY;
if (dirty && !aborted)
return false;
Expand Down
2 changes: 1 addition & 1 deletion fs/xfs/xfs_extfree_item.c
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,7 @@ xfs_efi_item_recover(
struct list_head *capture_list)
{
struct xfs_efi_log_item *efip = EFI_ITEM(lip);
struct xfs_mount *mp = lip->li_mountp;
struct xfs_mount *mp = lip->li_log->l_mp;
struct xfs_efd_log_item *efdp;
struct xfs_trans *tp;
struct xfs_extent *extp;
Expand Down
4 changes: 2 additions & 2 deletions fs/xfs/xfs_fsmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -864,8 +864,8 @@ xfs_getfsmap(
!xfs_getfsmap_is_valid_device(mp, &head->fmh_keys[1]))
return -EINVAL;

use_rmap = capable(CAP_SYS_ADMIN) &&
xfs_has_rmapbt(mp);
use_rmap = xfs_has_rmapbt(mp) &&
has_capability_noaudit(current, CAP_SYS_ADMIN);
head->fmh_entries = 0;

/* Set up our device handlers. */
Expand Down
10 changes: 9 additions & 1 deletion fs/xfs/xfs_icache.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "xfs_reflink.h"
#include "xfs_ialloc.h"
#include "xfs_ag.h"
#include "xfs_log_priv.h"

#include <linux/iversion.h>

Expand Down Expand Up @@ -873,7 +874,14 @@ xfs_reclaim_inode(
if (xfs_iflags_test_and_set(ip, XFS_IFLUSHING))
goto out_iunlock;

if (xfs_is_shutdown(ip->i_mount)) {
/*
* Check for log shutdown because aborting the inode can move the log
* tail and corrupt in memory state. This is fine if the log is shut
* down, but if the log is still active and only the mount is shut down
* then the in-memory log tail movement caused by the abort can be
* incorrectly propagated to disk.
*/
if (xlog_is_shutdown(ip->i_mount->m_log)) {
xfs_iunpin_wait(ip);
xfs_iflush_abort(ip);
goto reclaim;
Expand Down
Loading

0 comments on commit b1b07ba

Please sign in to comment.