Skip to content

Commit 1a5fb64

Browse files
committed
Merge tag 'gfs2-4.12.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2
Pull GFS2 updates from Bob Peterson: "We've got ten GFS2 patches for this merge window. - Andreas Gruenbacher wrote a patch to replace the deprecated call to rhashtable_walk_init with rhashtable_walk_enter. - Andreas also wrote a patch to eliminate redundant code in two of our debugfs sequence files. - Andreas also cleaned up the rhashtable key ugliness Linus pointed out during this cycle, following Linus's suggestions. - Andreas also wrote a patch to take advantage of his new function rhashtable_lookup_get_insert_fast. This makes glock lookup faster and more bullet-proof. - Andreas also wrote a patch to revert a patch in the evict path that caused occasional deadlocks, and is no longer needed. - Andrew Price wrote a patch to re-enable fallocate for the rindex system file to enable gfs2_grow to grow properly on secondary file system grow operations. - I wrote a patch to initialize an inode number field to make certain kernel trace points more understandable. - I also wrote a patch that makes GFS2 file system "withdraw" work more like it should by ignoring operations after a withdraw that would formerly cause a BUG() and kernel panic. - I also reworked the entire truncate/delete algorithm, scrapping the old recursive algorithm in favor of a new non-recursive algorithm. This was done for performance: This way, GFS2 no longer needs to lock multiple resource groups while doing truncates and deletes of files that cross multiple resource group boundaries, allowing for better parallelism. It also solves a problem whereby deleting large files would request a large chunk of kernel memory, which resulted in a get_page_from_freelist warning. - Due to a regression found during testing, I added a new patch to correct 'GFS2: Prevent BUG from occurring when normal Withdraws occur'." * tag 'gfs2-4.12.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2: GFS2: Allow glocks to be unlocked after withdraw GFS2: Non-recursive delete gfs2: Re-enable fallocate for the rindex Revert "GFS2: Wait for iopen glock dequeues" gfs2: Switch to rhashtable_lookup_get_insert_fast GFS2: Temporarily zero i_no_addr when creating a dinode gfs2: Don't pack struct lm_lockname gfs2: Deduplicate gfs2_{glocks,glstats}_open gfs2: Replace rhashtable_walk_init with rhashtable_walk_enter GFS2: Prevent BUG from occurring when normal Withdraws occur
2 parents aeced66 + ed17545 commit 1a5fb64

File tree

8 files changed

+518
-347
lines changed

8 files changed

+518
-347
lines changed

fs/gfs2/bmap.c

Lines changed: 456 additions & 285 deletions
Large diffs are not rendered by default.

fs/gfs2/file.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -911,11 +911,15 @@ static long __gfs2_fallocate(struct file *file, int mode, loff_t offset, loff_t
911911
static long gfs2_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
912912
{
913913
struct inode *inode = file_inode(file);
914+
struct gfs2_sbd *sdp = GFS2_SB(inode);
914915
struct gfs2_inode *ip = GFS2_I(inode);
915916
struct gfs2_holder gh;
916917
int ret;
917918

918-
if ((mode & ~FALLOC_FL_KEEP_SIZE) || gfs2_is_jdata(ip))
919+
if (mode & ~FALLOC_FL_KEEP_SIZE)
920+
return -EOPNOTSUPP;
921+
/* fallocate is needed by gfs2_grow to reserve space in the rindex */
922+
if (gfs2_is_jdata(ip) && inode != sdp->sd_rindex)
919923
return -EOPNOTSUPP;
920924

921925
inode_lock(inode);

fs/gfs2/glock.c

Lines changed: 37 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ static DEFINE_SPINLOCK(lru_lock);
7373

7474
static struct rhashtable_params ht_parms = {
7575
.nelem_hint = GFS2_GL_HASH_SIZE * 3 / 4,
76-
.key_len = sizeof(struct lm_lockname),
76+
.key_len = offsetofend(struct lm_lockname, ln_type),
7777
.key_offset = offsetof(struct gfs2_glock, gl_name),
7878
.head_offset = offsetof(struct gfs2_glock, gl_node),
7979
};
@@ -449,6 +449,9 @@ __acquires(&gl->gl_lockref.lock)
449449
unsigned int lck_flags = (unsigned int)(gh ? gh->gh_flags : 0);
450450
int ret;
451451

452+
if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) &&
453+
target != LM_ST_UNLOCKED)
454+
return;
452455
lck_flags &= (LM_FLAG_TRY | LM_FLAG_TRY_1CB | LM_FLAG_NOEXP |
453456
LM_FLAG_PRIORITY);
454457
GLOCK_BUG_ON(gl, gl->gl_state == target);
@@ -484,7 +487,8 @@ __acquires(&gl->gl_lockref.lock)
484487
}
485488
else if (ret) {
486489
pr_err("lm_lock ret %d\n", ret);
487-
GLOCK_BUG_ON(gl, 1);
490+
GLOCK_BUG_ON(gl, !test_bit(SDF_SHUTDOWN,
491+
&sdp->sd_flags));
488492
}
489493
} else { /* lock_nolock */
490494
finish_xmote(gl, target);
@@ -653,10 +657,10 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
653657
struct lm_lockname name = { .ln_number = number,
654658
.ln_type = glops->go_type,
655659
.ln_sbd = sdp };
656-
struct gfs2_glock *gl, *tmp = NULL;
660+
struct gfs2_glock *gl, *tmp;
657661
struct address_space *mapping;
658662
struct kmem_cache *cachep;
659-
int ret, tries = 0;
663+
int ret = 0;
660664

661665
rcu_read_lock();
662666
gl = rhashtable_lookup_fast(&gl_hash_table, &name, ht_parms);
@@ -721,35 +725,32 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
721725
}
722726

723727
again:
724-
ret = rhashtable_lookup_insert_fast(&gl_hash_table, &gl->gl_node,
725-
ht_parms);
726-
if (ret == 0) {
728+
rcu_read_lock();
729+
tmp = rhashtable_lookup_get_insert_fast(&gl_hash_table, &gl->gl_node,
730+
ht_parms);
731+
if (!tmp) {
727732
*glp = gl;
728-
return 0;
733+
goto out;
729734
}
730-
731-
if (ret == -EEXIST) {
732-
ret = 0;
733-
rcu_read_lock();
734-
tmp = rhashtable_lookup_fast(&gl_hash_table, &name, ht_parms);
735-
if (tmp == NULL || !lockref_get_not_dead(&tmp->gl_lockref)) {
736-
if (++tries < 100) {
737-
rcu_read_unlock();
738-
cond_resched();
739-
goto again;
740-
}
741-
tmp = NULL;
742-
ret = -ENOMEM;
743-
}
744-
rcu_read_unlock();
745-
} else {
746-
WARN_ON_ONCE(ret);
735+
if (IS_ERR(tmp)) {
736+
ret = PTR_ERR(tmp);
737+
goto out_free;
747738
}
739+
if (lockref_get_not_dead(&tmp->gl_lockref)) {
740+
*glp = tmp;
741+
goto out_free;
742+
}
743+
rcu_read_unlock();
744+
cond_resched();
745+
goto again;
746+
747+
out_free:
748748
kfree(gl->gl_lksb.sb_lvbptr);
749749
kmem_cache_free(cachep, gl);
750750
atomic_dec(&sdp->sd_glock_disposal);
751-
*glp = tmp;
752751

752+
out:
753+
rcu_read_unlock();
753754
return ret;
754755
}
755756

@@ -1918,10 +1919,10 @@ static const struct seq_operations gfs2_sbstats_seq_ops = {
19181919

19191920
#define GFS2_SEQ_GOODSIZE min(PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER, 65536UL)
19201921

1921-
static int gfs2_glocks_open(struct inode *inode, struct file *file)
1922+
static int __gfs2_glocks_open(struct inode *inode, struct file *file,
1923+
const struct seq_operations *ops)
19221924
{
1923-
int ret = seq_open_private(file, &gfs2_glock_seq_ops,
1924-
sizeof(struct gfs2_glock_iter));
1925+
int ret = seq_open_private(file, ops, sizeof(struct gfs2_glock_iter));
19251926
if (ret == 0) {
19261927
struct seq_file *seq = file->private_data;
19271928
struct gfs2_glock_iter *gi = seq->private;
@@ -1932,11 +1933,16 @@ static int gfs2_glocks_open(struct inode *inode, struct file *file)
19321933
if (seq->buf)
19331934
seq->size = GFS2_SEQ_GOODSIZE;
19341935
gi->gl = NULL;
1935-
ret = rhashtable_walk_init(&gl_hash_table, &gi->hti, GFP_KERNEL);
1936+
rhashtable_walk_enter(&gl_hash_table, &gi->hti);
19361937
}
19371938
return ret;
19381939
}
19391940

1941+
static int gfs2_glocks_open(struct inode *inode, struct file *file)
1942+
{
1943+
return __gfs2_glocks_open(inode, file, &gfs2_glock_seq_ops);
1944+
}
1945+
19401946
static int gfs2_glocks_release(struct inode *inode, struct file *file)
19411947
{
19421948
struct seq_file *seq = file->private_data;
@@ -1949,20 +1955,7 @@ static int gfs2_glocks_release(struct inode *inode, struct file *file)
19491955

19501956
static int gfs2_glstats_open(struct inode *inode, struct file *file)
19511957
{
1952-
int ret = seq_open_private(file, &gfs2_glstats_seq_ops,
1953-
sizeof(struct gfs2_glock_iter));
1954-
if (ret == 0) {
1955-
struct seq_file *seq = file->private_data;
1956-
struct gfs2_glock_iter *gi = seq->private;
1957-
gi->sdp = inode->i_private;
1958-
gi->last_pos = 0;
1959-
seq->buf = kmalloc(GFS2_SEQ_GOODSIZE, GFP_KERNEL | __GFP_NOWARN);
1960-
if (seq->buf)
1961-
seq->size = GFS2_SEQ_GOODSIZE;
1962-
gi->gl = NULL;
1963-
ret = rhashtable_walk_init(&gl_hash_table, &gi->hti, GFP_KERNEL);
1964-
}
1965-
return ret;
1958+
return __gfs2_glocks_open(inode, file, &gfs2_glstats_seq_ops);
19661959
}
19671960

19681961
static int gfs2_sbstats_open(struct inode *inode, struct file *file)

fs/gfs2/incore.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,11 +203,15 @@ enum {
203203
DFL_DLM_RECOVERY = 6,
204204
};
205205

206+
/*
207+
* We are using struct lm_lockname as an rhashtable key. Avoid holes within
208+
* the struct; padding at the end is fine.
209+
*/
206210
struct lm_lockname {
207-
struct gfs2_sbd *ln_sbd;
208211
u64 ln_number;
212+
struct gfs2_sbd *ln_sbd;
209213
unsigned int ln_type;
210-
} __packed __aligned(sizeof(int));
214+
};
211215

212216
#define lm_name_equal(name1, name2) \
213217
(((name1)->ln_number == (name2)->ln_number) && \

fs/gfs2/inode.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,8 +202,7 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type,
202202
fail_refresh:
203203
ip->i_iopen_gh.gh_flags |= GL_NOCACHE;
204204
ip->i_iopen_gh.gh_gl->gl_object = NULL;
205-
gfs2_glock_dq_wait(&ip->i_iopen_gh);
206-
gfs2_holder_uninit(&ip->i_iopen_gh);
205+
gfs2_glock_dq_uninit(&ip->i_iopen_gh);
207206
fail_put:
208207
if (io_gl)
209208
gfs2_glock_put(io_gl);
@@ -667,6 +666,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
667666
ip->i_height = 0;
668667
ip->i_depth = 0;
669668
ip->i_entries = 0;
669+
ip->i_no_addr = 0; /* Temporarily zero until real addr is assigned */
670670

671671
switch(mode & S_IFMT) {
672672
case S_IFREG:

fs/gfs2/rgrp.c

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -483,13 +483,6 @@ void gfs2_rgrp_verify(struct gfs2_rgrpd *rgd)
483483
}
484484
}
485485

486-
static inline int rgrp_contains_block(struct gfs2_rgrpd *rgd, u64 block)
487-
{
488-
u64 first = rgd->rd_data0;
489-
u64 last = first + rgd->rd_data;
490-
return first <= block && block < last;
491-
}
492-
493486
/**
494487
* gfs2_blk2rgrpd - Find resource group for a given data/meta block number
495488
* @sdp: The GFS2 superblock

fs/gfs2/rgrp.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,5 +83,12 @@ static inline bool gfs2_rs_active(const struct gfs2_blkreserv *rs)
8383
return rs && !RB_EMPTY_NODE(&rs->rs_node);
8484
}
8585

86+
static inline int rgrp_contains_block(struct gfs2_rgrpd *rgd, u64 block)
87+
{
88+
u64 first = rgd->rd_data0;
89+
u64 last = first + rgd->rd_data;
90+
return first <= block && block < last;
91+
}
92+
8693
extern void check_and_update_goal(struct gfs2_inode *ip);
8794
#endif /* __RGRP_DOT_H__ */

fs/gfs2/super.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -793,7 +793,8 @@ static void gfs2_dirty_inode(struct inode *inode, int flags)
793793

794794
if (!(flags & (I_DIRTY_DATASYNC|I_DIRTY_SYNC)))
795795
return;
796-
796+
if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
797+
return;
797798
if (!gfs2_glock_is_locked_by_me(ip->i_gl)) {
798799
ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
799800
if (ret) {
@@ -1538,8 +1539,7 @@ static void gfs2_evict_inode(struct inode *inode)
15381539
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_SKIP, &gh);
15391540
if (unlikely(error)) {
15401541
ip->i_iopen_gh.gh_flags |= GL_NOCACHE;
1541-
gfs2_glock_dq_wait(&ip->i_iopen_gh);
1542-
gfs2_holder_uninit(&ip->i_iopen_gh);
1542+
gfs2_glock_dq_uninit(&ip->i_iopen_gh);
15431543
goto out;
15441544
}
15451545

@@ -1617,7 +1617,7 @@ static void gfs2_evict_inode(struct inode *inode)
16171617
if (gfs2_holder_initialized(&ip->i_iopen_gh)) {
16181618
if (test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags)) {
16191619
ip->i_iopen_gh.gh_flags |= GL_NOCACHE;
1620-
gfs2_glock_dq_wait(&ip->i_iopen_gh);
1620+
gfs2_glock_dq(&ip->i_iopen_gh);
16211621
}
16221622
gfs2_holder_uninit(&ip->i_iopen_gh);
16231623
}
@@ -1639,8 +1639,7 @@ static void gfs2_evict_inode(struct inode *inode)
16391639
if (gfs2_holder_initialized(&ip->i_iopen_gh)) {
16401640
ip->i_iopen_gh.gh_gl->gl_object = NULL;
16411641
ip->i_iopen_gh.gh_flags |= GL_NOCACHE;
1642-
gfs2_glock_dq_wait(&ip->i_iopen_gh);
1643-
gfs2_holder_uninit(&ip->i_iopen_gh);
1642+
gfs2_glock_dq_uninit(&ip->i_iopen_gh);
16441643
}
16451644
}
16461645

0 commit comments

Comments
 (0)