Skip to content

Commit

Permalink
Merge tag 'gfs2-for-5.12' of git://git.kernel.org/pub/scm/linux/kerne…
Browse files Browse the repository at this point in the history
…l/git/gfs2/linux-gfs2

Pull gfs2 updates from Andreas Gruenbacher:

 - Log space and revoke accounting rework to fix some failed asserts.

 - Local resource group glock sharing for better local performance.

 - Add support for version 1802 filesystems: trusted xattr support and
   '-o rgrplvb' mounts by default.

 - Actually synchronize on the inode glock's FREEING bit during withdraw
   ("gfs2: fix glock confusion in function signal_our_withdraw").

 - Fix parallel recovery of multiple journals ("gfs2: keep bios separate
   for each journal").

 - Various other bug fixes.

* tag 'gfs2-for-5.12' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2: (49 commits)
  gfs2: Don't get stuck with I/O plugged in gfs2_ail1_flush
  gfs2: Per-revoke accounting in transactions
  gfs2: Rework the log space allocation logic
  gfs2: Minor calc_reserved cleanup
  gfs2: Use resource group glock sharing
  gfs2: Allow node-wide exclusive glock sharing
  gfs2: Add local resource group locking
  gfs2: Add per-reservation reserved block accounting
  gfs2: Rename rs_{free -> requested} and rd_{reserved -> requested}
  gfs2: Check for active reservation in gfs2_release
  gfs2: Don't search for unreserved space twice
  gfs2: Only pass reservation down to gfs2_rbm_find
  gfs2: Also reflect single-block allocations in rgd->rd_extfail_pt
  gfs2: Recursive gfs2_quota_hold in gfs2_iomap_end
  gfs2: Add trusted xattr support
  gfs2: Enable rgrplvb for sb_fs_format 1802
  gfs2: Don't skip dlm unlock if glock has an lvb
  gfs2: Lock imbalance on error path in gfs2_recover_one
  gfs2: Move function gfs2_ail_empty_tr
  gfs2: Get rid of current_tail()
  ...
  • Loading branch information
torvalds committed Feb 23, 2021
2 parents 7d6beb7 + 17d7768 commit f6e1e1d
Show file tree
Hide file tree
Showing 26 changed files with 967 additions and 662 deletions.
10 changes: 5 additions & 5 deletions fs/gfs2/bmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -1230,6 +1230,9 @@ static int gfs2_iomap_end(struct inode *inode, loff_t pos, loff_t length,

gfs2_inplace_release(ip);

if (ip->i_qadata && ip->i_qadata->qa_qd_num)
gfs2_quota_unlock(ip);

if (length != written && (iomap->flags & IOMAP_F_NEW)) {
/* Deallocate blocks that were just allocated. */
loff_t blockmask = i_blocksize(inode) - 1;
Expand All @@ -1242,9 +1245,6 @@ static int gfs2_iomap_end(struct inode *inode, loff_t pos, loff_t length,
}
}

if (ip->i_qadata && ip->i_qadata->qa_qd_num)
gfs2_quota_unlock(ip);

if (unlikely(!written))
goto out_unlock;

Expand Down Expand Up @@ -1538,13 +1538,13 @@ static int sweep_bh_for_rgrps(struct gfs2_inode *ip, struct gfs2_holder *rd_gh,
goto out;
}
ret = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_EXCLUSIVE,
0, rd_gh);
LM_FLAG_NODE_SCOPE, rd_gh);
if (ret)
goto out;

/* Must be done with the rgrp glock held: */
if (gfs2_rs_active(&ip->i_res) &&
rgd == ip->i_res.rs_rbm.rgd)
rgd == ip->i_res.rs_rgd)
gfs2_rs_deltree(&ip->i_res);
}

Expand Down
8 changes: 4 additions & 4 deletions fs/gfs2/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -716,10 +716,10 @@ static int gfs2_release(struct inode *inode, struct file *file)
kfree(file->private_data);
file->private_data = NULL;

if (file->f_mode & FMODE_WRITE) {
if (gfs2_rs_active(&ip->i_res))
gfs2_rs_delete(ip, &inode->i_writecount);
if (file->f_mode & FMODE_WRITE)
gfs2_qa_put(ip);
}
return 0;
}

Expand Down Expand Up @@ -1112,8 +1112,8 @@ static long __gfs2_fallocate(struct file *file, int mode, loff_t offset, loff_t
goto out_qunlock;

/* check if the selected rgrp limits our max_blks further */
if (ap.allowed && ap.allowed < max_blks)
max_blks = ap.allowed;
if (ip->i_res.rs_reserved < max_blks)
max_blks = ip->i_res.rs_reserved;

/* Almost done. Calculate bytes that can be written using
* max_blks. We also recompute max_bytes, data_blocks and
Expand Down
22 changes: 19 additions & 3 deletions fs/gfs2/glock.c
Original file line number Diff line number Diff line change
Expand Up @@ -313,9 +313,23 @@ void gfs2_glock_put(struct gfs2_glock *gl)
static inline int may_grant(const struct gfs2_glock *gl, const struct gfs2_holder *gh)
{
const struct gfs2_holder *gh_head = list_first_entry(&gl->gl_holders, const struct gfs2_holder, gh_list);
if ((gh->gh_state == LM_ST_EXCLUSIVE ||
gh_head->gh_state == LM_ST_EXCLUSIVE) && gh != gh_head)
return 0;

if (gh != gh_head) {
/**
* Here we make a special exception to grant holders who agree
* to share the EX lock with other holders who also have the
* bit set. If the original holder has the LM_FLAG_NODE_SCOPE bit
* is set, we grant more holders with the bit set.
*/
if (gh_head->gh_state == LM_ST_EXCLUSIVE &&
(gh_head->gh_flags & LM_FLAG_NODE_SCOPE) &&
gh->gh_state == LM_ST_EXCLUSIVE &&
(gh->gh_flags & LM_FLAG_NODE_SCOPE))
return 1;
if ((gh->gh_state == LM_ST_EXCLUSIVE ||
gh_head->gh_state == LM_ST_EXCLUSIVE))
return 0;
}
if (gl->gl_state == gh->gh_state)
return 1;
if (gh->gh_flags & GL_EXACT)
Expand Down Expand Up @@ -2030,6 +2044,8 @@ static const char *hflags2str(char *buf, u16 flags, unsigned long iflags)
*p++ = 'A';
if (flags & LM_FLAG_PRIORITY)
*p++ = 'p';
if (flags & LM_FLAG_NODE_SCOPE)
*p++ = 'n';
if (flags & GL_ASYNC)
*p++ = 'a';
if (flags & GL_EXACT)
Expand Down
6 changes: 6 additions & 0 deletions fs/gfs2/glock.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,19 @@ enum {
* request and directly join the other shared lock. A shared lock request
* without the priority flag might be forced to wait until the deferred
* requested had acquired and released the lock.
*
* LM_FLAG_NODE_SCOPE
* This holder agrees to share the lock within this node. In other words,
* the glock is held in EX mode according to DLM, but local holders on the
* same node can share it.
*/

#define LM_FLAG_TRY 0x0001
#define LM_FLAG_TRY_1CB 0x0002
#define LM_FLAG_NOEXP 0x0004
#define LM_FLAG_ANY 0x0008
#define LM_FLAG_PRIORITY 0x0010
#define LM_FLAG_NODE_SCOPE 0x0020
#define GL_ASYNC 0x0040
#define GL_EXACT 0x0080
#define GL_SKIP 0x0100
Expand Down
38 changes: 12 additions & 26 deletions fs/gfs2/glops.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,16 +86,12 @@ static int gfs2_ail_empty_gl(struct gfs2_glock *gl)
{
struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
struct gfs2_trans tr;
unsigned int revokes;
int ret;

memset(&tr, 0, sizeof(tr));
INIT_LIST_HEAD(&tr.tr_buf);
INIT_LIST_HEAD(&tr.tr_databuf);
INIT_LIST_HEAD(&tr.tr_ail1_list);
INIT_LIST_HEAD(&tr.tr_ail2_list);
tr.tr_revokes = atomic_read(&gl->gl_ail_count);
revokes = atomic_read(&gl->gl_ail_count);

if (!tr.tr_revokes) {
if (!revokes) {
bool have_revokes;
bool log_in_flight;

Expand All @@ -122,20 +118,14 @@ static int gfs2_ail_empty_gl(struct gfs2_glock *gl)
return 0;
}

/* A shortened, inline version of gfs2_trans_begin()
* tr->alloced is not set since the transaction structure is
* on the stack */
tr.tr_reserved = 1 + gfs2_struct2blk(sdp, tr.tr_revokes);
tr.tr_ip = _RET_IP_;
ret = gfs2_log_reserve(sdp, tr.tr_reserved);
if (ret < 0)
return ret;
WARN_ON_ONCE(current->journal_info);
current->journal_info = &tr;

__gfs2_ail_flush(gl, 0, tr.tr_revokes);

memset(&tr, 0, sizeof(tr));
set_bit(TR_ONSTACK, &tr.tr_flags);
ret = __gfs2_trans_begin(&tr, sdp, 0, revokes, _RET_IP_);
if (ret)
goto flush;
__gfs2_ail_flush(gl, 0, revokes);
gfs2_trans_end(sdp);

flush:
gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL |
GFS2_LFC_AIL_EMPTY_GL);
Expand All @@ -146,19 +136,15 @@ void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
{
struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
unsigned int revokes = atomic_read(&gl->gl_ail_count);
unsigned int max_revokes = (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_log_descriptor)) / sizeof(u64);
int ret;

if (!revokes)
return;

while (revokes > max_revokes)
max_revokes += (sdp->sd_sb.sb_bsize - sizeof(struct gfs2_meta_header)) / sizeof(u64);

ret = gfs2_trans_begin(sdp, 0, max_revokes);
ret = gfs2_trans_begin(sdp, 0, revokes);
if (ret)
return;
__gfs2_ail_flush(gl, fsync, max_revokes);
__gfs2_ail_flush(gl, fsync, revokes);
gfs2_trans_end(sdp);
gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL |
GFS2_LFC_AIL_FLUSH);
Expand Down
54 changes: 16 additions & 38 deletions fs/gfs2/incore.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <linux/percpu.h>
#include <linux/lockref.h>
#include <linux/rhashtable.h>
#include <linux/mutex.h>

#define DIO_WAIT 0x00000010
#define DIO_METADATA 0x00000020
Expand Down Expand Up @@ -106,7 +107,8 @@ struct gfs2_rgrpd {
u32 rd_data; /* num of data blocks in rgrp */
u32 rd_bitbytes; /* number of bytes in data bitmaps */
u32 rd_free;
u32 rd_reserved; /* number of blocks reserved */
u32 rd_requested; /* number of blocks in rd_rstree */
u32 rd_reserved; /* number of reserved blocks */
u32 rd_free_clone;
u32 rd_dinodes;
u64 rd_igeneration;
Expand All @@ -122,34 +124,10 @@ struct gfs2_rgrpd {
#define GFS2_RDF_PREFERRED 0x80000000 /* This rgrp is preferred */
#define GFS2_RDF_MASK 0xf0000000 /* mask for internal flags */
spinlock_t rd_rsspin; /* protects reservation related vars */
struct mutex rd_mutex;
struct rb_root rd_rstree; /* multi-block reservation tree */
};

struct gfs2_rbm {
struct gfs2_rgrpd *rgd;
u32 offset; /* The offset is bitmap relative */
int bii; /* Bitmap index */
};

static inline struct gfs2_bitmap *rbm_bi(const struct gfs2_rbm *rbm)
{
return rbm->rgd->rd_bits + rbm->bii;
}

static inline u64 gfs2_rbm_to_block(const struct gfs2_rbm *rbm)
{
BUG_ON(rbm->offset >= rbm->rgd->rd_data);
return rbm->rgd->rd_data0 + (rbm_bi(rbm)->bi_start * GFS2_NBBY) +
rbm->offset;
}

static inline bool gfs2_rbm_eq(const struct gfs2_rbm *rbm1,
const struct gfs2_rbm *rbm2)
{
return (rbm1->rgd == rbm2->rgd) && (rbm1->bii == rbm2->bii) &&
(rbm1->offset == rbm2->offset);
}

enum gfs2_state_bits {
BH_Pinned = BH_PrivateStart,
BH_Escaped = BH_PrivateStart + 1,
Expand Down Expand Up @@ -313,9 +291,11 @@ struct gfs2_qadata { /* quota allocation data */
*/

struct gfs2_blkreserv {
struct rb_node rs_node; /* link to other block reservations */
struct gfs2_rbm rs_rbm; /* Start of reservation */
u32 rs_free; /* how many blocks are still free */
struct rb_node rs_node; /* node within rd_rstree */
struct gfs2_rgrpd *rs_rgd;
u64 rs_start;
u32 rs_requested;
u32 rs_reserved; /* number of reserved blocks */
};

/*
Expand Down Expand Up @@ -490,7 +470,7 @@ struct gfs2_quota_data {
enum {
TR_TOUCHED = 1,
TR_ATTACHED = 2,
TR_ALLOCED = 3,
TR_ONSTACK = 3,
};

struct gfs2_trans {
Expand All @@ -506,7 +486,6 @@ struct gfs2_trans {
unsigned int tr_num_buf_rm;
unsigned int tr_num_databuf_rm;
unsigned int tr_num_revoke;
unsigned int tr_num_revoke_rm;

struct list_head tr_list;
struct list_head tr_databuf;
Expand All @@ -531,6 +510,7 @@ struct gfs2_jdesc {
unsigned int nr_extents;
struct work_struct jd_work;
struct inode *jd_inode;
struct bio *jd_log_bio;
unsigned long jd_flags;
#define JDF_RECOVERY 1
unsigned int jd_jid;
Expand Down Expand Up @@ -585,6 +565,7 @@ struct gfs2_args {
unsigned int ar_errors:2; /* errors=withdraw | panic */
unsigned int ar_nobarrier:1; /* do not send barriers */
unsigned int ar_rgrplvb:1; /* use lvbs for rgrp info */
unsigned int ar_got_rgrplvb:1; /* Was the rgrplvb opt given? */
unsigned int ar_loccookie:1; /* use location based readdir
cookies */
s32 ar_commit; /* Commit interval */
Expand Down Expand Up @@ -821,7 +802,6 @@ struct gfs2_sbd {

struct gfs2_trans *sd_log_tr;
unsigned int sd_log_blks_reserved;
int sd_log_committed_revoke;

atomic_t sd_log_pinned;
unsigned int sd_log_num_revoke;
Expand All @@ -834,24 +814,22 @@ struct gfs2_sbd {
atomic_t sd_log_thresh2;
atomic_t sd_log_blks_free;
atomic_t sd_log_blks_needed;
atomic_t sd_log_revokes_available;
wait_queue_head_t sd_log_waitq;
wait_queue_head_t sd_logd_waitq;

u64 sd_log_sequence;
unsigned int sd_log_head;
unsigned int sd_log_tail;
int sd_log_idle;

struct rw_semaphore sd_log_flush_lock;
atomic_t sd_log_in_flight;
struct bio *sd_log_bio;
wait_queue_head_t sd_log_flush_wait;
int sd_log_error; /* First log error */
wait_queue_head_t sd_withdraw_wait;

atomic_t sd_reserving_log;
wait_queue_head_t sd_reserving_log_wait;

unsigned int sd_log_tail;
unsigned int sd_log_flush_tail;
unsigned int sd_log_head;
unsigned int sd_log_flush_head;

spinlock_t sd_ail_lock;
Expand Down
6 changes: 3 additions & 3 deletions fs/gfs2/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1147,7 +1147,7 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry)
if (!rgd)
goto out_inodes;

gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + 2);
gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, LM_FLAG_NODE_SCOPE, ghs + 2);


error = gfs2_glock_nq(ghs); /* parent */
Expand Down Expand Up @@ -1453,8 +1453,8 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
error = -ENOENT;
goto out_gunlock;
}
error = gfs2_glock_nq_init(nrgd->rd_gl, LM_ST_EXCLUSIVE, 0,
&rd_gh);
error = gfs2_glock_nq_init(nrgd->rd_gl, LM_ST_EXCLUSIVE,
LM_FLAG_NODE_SCOPE, &rd_gh);
if (error)
goto out_gunlock;
}
Expand Down
8 changes: 2 additions & 6 deletions fs/gfs2/lock_dlm.c
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,6 @@ static void gdlm_put_lock(struct gfs2_glock *gl)
{
struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
struct lm_lockstruct *ls = &sdp->sd_lockstruct;
int lvb_needs_unlock = 0;
int error;

if (gl->gl_lksb.sb_lkid == 0) {
Expand All @@ -297,13 +296,10 @@ static void gdlm_put_lock(struct gfs2_glock *gl)
gfs2_sbstats_inc(gl, GFS2_LKS_DCOUNT);
gfs2_update_request_times(gl);

/* don't want to skip dlm_unlock writing the lvb when lock is ex */

if (gl->gl_lksb.sb_lvbptr && (gl->gl_state == LM_ST_EXCLUSIVE))
lvb_needs_unlock = 1;
/* don't want to skip dlm_unlock writing the lvb when lock has one */

if (test_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags) &&
!lvb_needs_unlock) {
!gl->gl_lksb.sb_lvbptr) {
gfs2_glock_free(gl);
return;
}
Expand Down
Loading

0 comments on commit f6e1e1d

Please sign in to comment.