1. 05 Sep, 2023 28 commits
    • Bob Peterson's avatar
      gfs2: Introduce new quota=quiet mount option · eef46ab7
      Bob Peterson authored
      This patch adds a new mount option quota=quiet which is the same as
      quota=on but it suppresses gfs2 quota error messages.
      Signed-off-by: default avatarBob Peterson <rpeterso@redhat.com>
      Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
      eef46ab7
    • Andreas Gruenbacher's avatar
      gfs2: Add device name to gfs2_logd and gfs2_quotad · 267d1a01
      Andreas Gruenbacher authored
      Add the device name to the names of the gfs2_logd and gfs2_quotad kernel
      threads to allow for easier identification.
      Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
      267d1a01
    • Andreas Gruenbacher's avatar
    • Andreas Gruenbacher's avatar
      gfs2: Rename "gfs_recovery" workqueue to "gfs2_recovery" · 5c0dc371
      Andreas Gruenbacher authored
      Rename the "gfs_recovery" workqueue to "gfs2_recovery", and
      gfs_recovery_wq to gfs2_recovery_wq.
      Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
      5c0dc371
    • Andreas Gruenbacher's avatar
      gfs2: Fix withdraw race · e3da6be3
      Andreas Gruenbacher authored
      Function gfs2_withdraw() tries to synchronize concurrent callers by
      atomically setting the SDF_WITHDRAWN flag in the first caller, setting
      the SDF_WITHDRAW_IN_PROG flag to indicate that a withdraw is in
      progress, performing the actual withdraw, and clearing the
      SDF_WITHDRAW_IN_PROG flag when done.  All other callers wait for the
      SDF_WITHDRAW_IN_PROG flag to be cleared before returning.
      
      This leaves a small window in which callers can find the SDF_WITHDRAWN
      flag set before the SDF_WITHDRAW_IN_PROG flag has been set, causing them
      to return prematurely, before the withdraw has been completed.
      
      Fix that by setting the SDF_WITHDRAWN and SDF_WITHDRAW_IN_PROG flags
      atomically.
      Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
      e3da6be3
    • Andreas Gruenbacher's avatar
      gfs2: Sanitize kthread stopping · fe0690f0
      Andreas Gruenbacher authored
      Immediately stop the logd and quotad kernel threads when a filesystem
      withdraw is detected: those threads aren't doing anything useful after a
      withdraw.  (Depends on the extra logd and quotad task struct references
      held since commit 7a109f383fa3 ("gfs2: Fix asynchronous thread
      destruction").)
      
      In addition, check for kthread_should_stop() in the wait condition in
      gfs2_quotad() to stop immediately when kthread_stop() is called.
      Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
      fe0690f0
    • Andreas Gruenbacher's avatar
      gfs2: Switch to wait_event in gfs2_quotad · e4a8b548
      Andreas Gruenbacher authored
      In gfs2_quotad(), switch from an open-coded wait loop to
      wait_event_interruptible_timeout().
      Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
      e4a8b548
    • Andreas Gruenbacher's avatar
      gfs2: Fix asynchronous thread destruction · fe4f7940
      Andreas Gruenbacher authored
      The kernel threads are currently stopped and destroyed synchronously by
      gfs2_make_fs_ro() and gfs2_put_super(), and asynchronously by
      signal_our_withdraw(), with no synchronization, so the synchronous and
      asynchronous contexts can race with each other.
      
      First, when creating the kernel threads, take an extra task struct
      reference so that the task struct won't go away immediately when they
      terminate.  This allows those kthreads to terminate immediately when
      they're done rather than hanging around as zombies until they are reaped
      by kthread_stop().  When kthread_stop() is called on a terminated
      kthread, it will return immediately.
      
      Second, in signal_our_withdraw(), once the SDF_JOURNAL_LIVE flag has
      been cleared, wake up the logd and quotad wait queues instead of
      stopping the logd and quotad kthreads.  The kthreads are then expected
      to terminate automatically within short time, but if they cannot, they
      will not block the withdraw.
      
      For example, if a user process and one of the kthread decide to withdraw
      at the same time, only one of them will perform the actual withdraw and
      the other will wait for it to be done.  If the kthread ends up being the
      one to wait, the withdrawing user process won't be able to stop it.
      Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
      fe4f7940
    • Andreas Gruenbacher's avatar
      gfs2: Stop using gfs2_make_fs_ro for withdraw · f66af88e
      Andreas Gruenbacher authored
      [   81.372851][ T5532] CPU: 1 PID: 5532 Comm: syz-executor.0 Not tainted 6.2.0-rc1-syzkaller-dirty #0
      [   81.382080][ T5532] Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/12/2023
      [   81.392343][ T5532] Call Trace:
      [   81.395654][ T5532]  <TASK>
      [   81.398603][ T5532]  dump_stack_lvl+0x1b1/0x290
      [   81.418421][ T5532]  gfs2_assert_warn_i+0x19a/0x2e0
      [   81.423480][ T5532]  gfs2_quota_cleanup+0x4c6/0x6b0
      [   81.428611][ T5532]  gfs2_make_fs_ro+0x517/0x610
      [   81.457802][ T5532]  gfs2_withdraw+0x609/0x1540
      [   81.481452][ T5532]  gfs2_inode_refresh+0xb2d/0xf60
      [   81.506658][ T5532]  gfs2_instantiate+0x15e/0x220
      [   81.511504][ T5532]  gfs2_glock_wait+0x1d9/0x2a0
      [   81.516352][ T5532]  do_sync+0x485/0xc80
      [   81.554943][ T5532]  gfs2_quota_sync+0x3da/0x8b0
      [   81.559738][ T5532]  gfs2_sync_fs+0x49/0xb0
      [   81.564063][ T5532]  sync_filesystem+0xe8/0x220
      [   81.568740][ T5532]  generic_shutdown_super+0x6b/0x310
      [   81.574112][ T5532]  kill_block_super+0x79/0xd0
      [   81.578779][ T5532]  deactivate_locked_super+0xa7/0xf0
      [   81.584064][ T5532]  cleanup_mnt+0x494/0x520
      [   81.593753][ T5532]  task_work_run+0x243/0x300
      [   81.608837][ T5532]  exit_to_user_mode_loop+0x124/0x150
      [   81.614232][ T5532]  exit_to_user_mode_prepare+0xb2/0x140
      [   81.619820][ T5532]  syscall_exit_to_user_mode+0x26/0x60
      [   81.625287][ T5532]  do_syscall_64+0x49/0xb0
      [   81.629710][ T5532]  entry_SYSCALL_64_after_hwframe+0x63/0xcd
      
      In this backtrace, gfs2_quota_sync() takes quota data references and
      then calls do_sync().  Function do_sync() encounters filesystem
      corruption and withdraws the filesystem, which (among other things) calls
      gfs2_quota_cleanup().  Function gfs2_quota_cleanup() wrongly assumes
      that nobody is holding any quota data references anymore, and destroys
      all quota data objects.  When gfs2_quota_sync() then resumes and
      dereferences the quota data objects it is holding, those objects are no
      longer there.
      
      Function gfs2_quota_cleanup() deals with resource deallocation and can
      easily be delayed until gfs2_put_super() in the case of a filesystem
      withdraw.  In fact, most of the other work gfs2_make_fs_ro() does is
      unnecessary during a withdraw as well, so change signal_our_withdraw()
      to skip gfs2_make_fs_ro() and perform the necessary steps directly
      instead.
      
      Thanks to Edward Adam Davis <eadavis@sina.com> for the initial patches.
      
      Link: https://lore.kernel.org/all/0000000000002b5e2405f14e860f@google.com
      Reported-by: syzbot+3f6a670108ce43356017@syzkaller.appspotmail.com
      Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
      f66af88e
    • Andreas Gruenbacher's avatar
      gfs2: Free quota data objects synchronously · a475c5dd
      Andreas Gruenbacher authored
      In gfs2_quota_cleanup(), wait for the quota data objects to be freed
      before returning.  Otherwise, there is no guarantee that the quota data
      objects will be gone when their kmem cache is destroyed.
      Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
      a475c5dd
    • Andreas Gruenbacher's avatar
      gfs2: Fix initial quota data refcount · bb73ae8f
      Andreas Gruenbacher authored
      Fix the refcount of quota data objects created directly by
      gfs2_quota_init(): those are placed into the in-memory quota "database"
      for eventual syncing to the main quota file, but they are not actively
      held and should thus have an initial refcount of 0.
      Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
      bb73ae8f
    • Andreas Gruenbacher's avatar
      gfs2: No more quota complaints after withdraw · fae2e73a
      Andreas Gruenbacher authored
      Once a filesystem is withdrawn, don't complain about quota changes
      that can't be synced to the main quota file anymore.
      Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
      fae2e73a
    • Andreas Gruenbacher's avatar
      gfs2: Factor out duplicate quota data disposal code · faada74a
      Andreas Gruenbacher authored
      Rename gfs2_qd_dispose() to gfs2_qd_dispose_list().  Move some code
      duplicated in gfs2_qd_dispose_list() and gfs2_quota_cleanup() into a
      new gfs2_qd_dispose() function.
      Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
      faada74a
    • Andreas Gruenbacher's avatar
      gfs2: Use gfs2_qd_dispose in gfs2_quota_cleanup · 961fe342
      Andreas Gruenbacher authored
      Change gfs2_quota_cleanup() to move the quota data objects to dispose of
      on a dispose list and call gfs2_qd_dispose() on that list, like
      gfs2_qd_shrink_scan() does, instead of disposing of the quota data
      objects directly.
      
      This may look a bit pointless by itself, but it will make more sense in
      combination with a fix that follows.
      Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
      961fe342
    • Andreas Gruenbacher's avatar
      gfs2: Fix wrong quota shrinker return value · 6b0e9a5f
      Andreas Gruenbacher authored
      Function gfs2_qd_isolate must only return LRU_REMOVED when removing the
      item from the lru list; otherwise, the number of items on the list will
      go wrong.
      Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
      6b0e9a5f
    • Andreas Gruenbacher's avatar
      gfs2: Rename SDF_DEACTIVATING to SDF_KILL · e7beb8b6
      Andreas Gruenbacher authored
      Rename the SDF_DEACTIVATING flag to SDF_KILL to make it more obvious
      that this relates to the kill_sb filesystem operation.
      Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
      e7beb8b6
    • Andreas Gruenbacher's avatar
      gfs2: Rename sd_{ glock => kill }_wait · 3c69c437
      Andreas Gruenbacher authored
      Rename sd_glock_wait to sd_kill_wait: we'll use it for other things
      related to "killing" a filesystem on unmount soon (kill_sb).
      Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
      3c69c437
    • Bob Peterson's avatar
      gfs2: Use qd_sbd more consequently · 481f6e7d
      Bob Peterson authored
      Before this patch many of the functions in quota.c got their superblock
      pointer, sdp, from the quota_data's glock pointer. That's silly because
      the qd already has its own pointer to the superblock (qd_sbd).
      
      This patch changes references to use that instead, eliminating a level
      of indirection.
      Signed-off-by: default avatarBob Peterson <rpeterso@redhat.com>
      Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
      481f6e7d
    • Andreas Gruenbacher's avatar
      gfs2: journal flush threshold fixes and cleanup · db77789b
      Andreas Gruenbacher authored
      Commit f07b3520 ("GFS2: Made logd daemon take into account log
      demand") changed gfs2_ail_flush_reqd() and gfs2_jrnl_flush_reqd() to
      take sd_log_blks_needed into account, but the checks in
      gfs2_log_commit() were not updated correspondingly.
      
      Once that is fixed, gfs2_jrnl_flush_reqd() and gfs2_ail_flush_reqd() can
      be used in gfs2_log_commit().  Make those two helpers available to
      gfs2_log_commit() by defining them above gfs2_log_commit().
      Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
      db77789b
    • Andreas Gruenbacher's avatar
      gfs2: Fix logd wakeup on I/O error · b6b8f72a
      Andreas Gruenbacher authored
      When quotad detects an I/O error, it sets sd_log_error and then it wakes
      up logd to withdraw the filesystem.  However, logd doesn't wake up when
      sd_log_error is set.  Fix that.
      Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
      b6b8f72a
    • Andreas Gruenbacher's avatar
      gfs2: low-memory forced flush fixes · b74cd55a
      Andreas Gruenbacher authored
      First, function gfs2_ail_flush_reqd checks the SDF_FORCE_AIL_FLUSH flag
      to determine if an AIL flush should be forced in low-memory situations.
      However, it also immediately clears the flag, and when called repeatedly
      as in function gfs2_logd, the flag will be lost.  Fix that by pulling
      the SDF_FORCE_AIL_FLUSH flag check out of gfs2_ail_flush_reqd.
      
      Second, function gfs2_writepages sets the SDF_FORCE_AIL_FLUSH flag
      whether or not enough pages were written.  If enough pages could be
      written, flushing the AIL is unnecessary, though.
      
      Third, gfs2_writepages doesn't wake up logd after setting the
      SDF_FORCE_AIL_FLUSH flag, so it can take a long time for logd to react.
      It would be preferable to wake up logd, but that hurts the performance
      of some workloads and we don't quite understand why so far, so don't
      wake up logd so far.
      
      Fixes: b066a4ee ("gfs2: forcibly flush ail to relieve memory pressure")
      Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
      b74cd55a
    • Andreas Gruenbacher's avatar
      gfs2: Switch to wait_event in gfs2_logd · 6df373b0
      Andreas Gruenbacher authored
      In gfs2_logd(), switch from an open-coded wait loop to
      wait_event_interruptible_timeout().
      Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
      6df373b0
    • Bob Peterson's avatar
      gfs2: conversion deadlock do_promote bypass · 66fa9912
      Bob Peterson authored
      Consider the following case:
      1. A glock is held in shared mode.
      2. A process requests the glock in exclusive mode (rename).
      3. Before the lock is granted, more processes (read / ls) request the
         glock in shared mode again.
      4. gfs2 sends a request to dlm for the lock in exclusive mode because
         that holder is at the head of the queue.
      5. Somehow the dlm request gets canceled, so dlm sends us back a
         response with state == LM_ST_SHARED and LM_OUT_CANCELED.  So at that
         point, the glock is still held in shared mode.
      6. finish_xmote gets called to process the response from dlm. It detects
         that the glock is not in the requested mode and no demote is in
         progress, so it moves the canceled holder to the tail of the queue
         and finds the new holder at the head of the queue.  That holder is
         requesting the glock in shared mode.
      7. finish_xmote calls do_xmote to transition the glock into shared mode,
         but the glock is already in shared mode and so do_xmote complains
         about that with:
      	GLOCK_BUG_ON(gl, gl->gl_state == gl->gl_target);
      
      Instead, in finish_xmote, after moving the canceled holder to the tail
      of the queue, check if any new holders can be granted.  Only call
      do_xmote to repeat the dlm request if the holder at the head of the
      queue is requesting the glock in a mode that is incompatible with the
      mode the glock is currently held in.
      Signed-off-by: default avatarBob Peterson <rpeterso@redhat.com>
      Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
      66fa9912
    • Andreas Gruenbacher's avatar
      gfs2: Remove LM_FLAG_PRIORITY flag · 0b93bac2
      Andreas Gruenbacher authored
      The last user of this flag was removed in commit b77b4a48 ("gfs2:
      Rework freeze / thaw logic").
      Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
      0b93bac2
    • Andreas Gruenbacher's avatar
      gfs2: do_promote cleanup · de3e7f97
      Andreas Gruenbacher authored
      Change function do_promote to return true on success, and false
      otherwise.
      Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
      de3e7f97
    • Andreas Gruenbacher's avatar
      gfs: Don't use GFP_NOFS in gfs2_unstuff_dinode · dc0b9435
      Andreas Gruenbacher authored
      Revert the rest of commit 220cca2a ("GFS2: Change truncate page
      allocation to be GFP_NOFS"):
      
      In gfs2_unstuff_dinode(), there is no need to carry out the page cache
      allocation under GFP_NOFS because inodes on the "regular" filesystem are
      never un-inlined under memory pressure, so switch back from
      find_or_create_page() to grab_cache_page() here as well.
      
      Inodes on the "metadata" filesystem can theoretically be un-inlined
      under memory pressure, but any page cache allocations in that context
      would happen in GFP_NOFS context because those inodes have
      inode->i_mapping->gfp_mask set to GFP_NOFS (see the previous patch).
      Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
      dc0b9435
    • Andreas Gruenbacher's avatar
      gfs2: Use mapping->gfp_mask for metadata inodes · 111c7d27
      Andreas Gruenbacher authored
      Set mapping->gfp mask to GFP_NOFS for all metadata inodes so that
      allocating pages in the address space of those inodes won't call back
      into the filesystem.  This allows to switch back from
      find_or_create_page() to grab_cache_page() in two places.
      
      Partially reverts commit 220cca2a ("GFS2: Change truncate page
      allocation to be GFP_NOFS").
      
      Thanks to Dan Carpenter <dan.carpenter@linaro.org> for pointing out a
      Smatch static checker warning.
      Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
      111c7d27
    • Minjie Du's avatar
      gfs2: increase usage of folio_next_index() helper · 5f02d168
      Minjie Du authored
      Simplify code pattern of 'folio->index + folio_nr_pages(folio)' by using
      the existing helper folio_next_index().
      Signed-off-by: default avatarMinjie Du <duminjie@vivo.com>
      Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
      5f02d168
  2. 08 Aug, 2023 3 commits
  3. 07 Aug, 2023 9 commits