diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-02-03 13:14:41 -0800 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-02-03 13:14:41 -0800 | 
| commit | 6ec4de89b478043aa1c33f89f68f62ebf61b3e43 (patch) | |
| tree | b12bd5cc52adb750af7330f9de80ec74640d087d | |
| parent | abbbd0211ddfc6e525b00b3c8c84032f705e4a5d (diff) | |
| parent | 7ac07fdaf840f9b141c6d5c286805107227c0e68 (diff) | |
Merge tag 'gfs2-4.16.fixes2' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2
Pull GFS2 fixes from Bob Peterson:
 "Andreas Gruenbacher wrote two additional patches that we would like
  merged in this time. Both are regressions:
   - fix another kernel build dependency problem
   - fix a performance regression in glock dumps"
* tag 'gfs2-4.16.fixes2' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2:
  gfs2: Glock dump performance regression fix
  gfs2: Fix the crc32c dependency
| -rw-r--r-- | fs/gfs2/Kconfig | 3 | ||||
| -rw-r--r-- | fs/gfs2/glock.c | 65 | 
2 files changed, 44 insertions, 24 deletions
diff --git a/fs/gfs2/Kconfig b/fs/gfs2/Kconfig index c0225d4b5435..3ed2b088dcfd 100644 --- a/fs/gfs2/Kconfig +++ b/fs/gfs2/Kconfig @@ -3,8 +3,7 @@ config GFS2_FS  	depends on (64BIT || LBDAF)  	select FS_POSIX_ACL  	select CRC32 -	select CRYPTO -	select CRYPTO_CRC32C +	select LIBCRC32C  	select QUOTACTL  	select FS_IOMAP  	help diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 90af87ff29ba..82fb5583445c 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -1921,19 +1921,29 @@ void gfs2_glock_exit(void)  	destroy_workqueue(gfs2_delete_workqueue);  } -static void gfs2_glock_iter_next(struct gfs2_glock_iter *gi) +static void gfs2_glock_iter_next(struct gfs2_glock_iter *gi, loff_t n)  { -	while ((gi->gl = rhashtable_walk_next(&gi->hti))) { -		if (IS_ERR(gi->gl)) { -			if (PTR_ERR(gi->gl) == -EAGAIN) -				continue; -			gi->gl = NULL; -			return; +	if (n == 0) +		gi->gl = rhashtable_walk_peek(&gi->hti); +	else { +		gi->gl = rhashtable_walk_next(&gi->hti); +		n--; +	} +	for (;;) { +		if (IS_ERR_OR_NULL(gi->gl)) { +			if (!gi->gl) +				return; +			if (PTR_ERR(gi->gl) != -EAGAIN) { +				gi->gl = NULL; +				return; +			} +			n = 0; +		} else if (gi->sdp == gi->gl->gl_name.ln_sbd && +			   !__lockref_is_dead(&gi->gl->gl_lockref)) { +			if (!n--) +				break;  		} -		/* Skip entries for other sb and dead entries */ -		if (gi->sdp == gi->gl->gl_name.ln_sbd && -		    !__lockref_is_dead(&gi->gl->gl_lockref)) -			return; +		gi->gl = rhashtable_walk_next(&gi->hti);  	}  } @@ -1941,18 +1951,24 @@ static void *gfs2_glock_seq_start(struct seq_file *seq, loff_t *pos)  	__acquires(RCU)  {  	struct gfs2_glock_iter *gi = seq->private; -	loff_t n = *pos; +	loff_t n; -	rhashtable_walk_enter(&gl_hash_table, &gi->hti); -	if (rhashtable_walk_start_check(&gi->hti) != 0) -		return NULL; +	/* +	 * We can either stay where we are, skip to the next hash table +	 * entry, or start from the beginning. +	 */ +	if (*pos < gi->last_pos) { +		rhashtable_walk_exit(&gi->hti); +		rhashtable_walk_enter(&gl_hash_table, &gi->hti); +		n = *pos + 1; +	} else { +		n = *pos - gi->last_pos; +	} -	do { -		gfs2_glock_iter_next(gi); -	} while (gi->gl && n--); +	rhashtable_walk_start(&gi->hti); +	gfs2_glock_iter_next(gi, n);  	gi->last_pos = *pos; -  	return gi->gl;  } @@ -1963,8 +1979,7 @@ static void *gfs2_glock_seq_next(struct seq_file *seq, void *iter_ptr,  	(*pos)++;  	gi->last_pos = *pos; -	gfs2_glock_iter_next(gi); - +	gfs2_glock_iter_next(gi, 1);  	return gi->gl;  } @@ -1975,7 +1990,6 @@ static void gfs2_glock_seq_stop(struct seq_file *seq, void *iter_ptr)  	gi->gl = NULL;  	rhashtable_walk_stop(&gi->hti); -	rhashtable_walk_exit(&gi->hti);  }  static int gfs2_glock_seq_show(struct seq_file *seq, void *iter_ptr) @@ -2041,7 +2055,13 @@ static int __gfs2_glocks_open(struct inode *inode, struct file *file,  		seq->buf = kmalloc(GFS2_SEQ_GOODSIZE, GFP_KERNEL | __GFP_NOWARN);  		if (seq->buf)  			seq->size = GFS2_SEQ_GOODSIZE; +		/* +		 * Initially, we are "before" the first hash table entry; the +		 * first call to rhashtable_walk_next gets us the first entry. +		 */ +		gi->last_pos = -1;  		gi->gl = NULL; +		rhashtable_walk_enter(&gl_hash_table, &gi->hti);  	}  	return ret;  } @@ -2057,6 +2077,7 @@ static int gfs2_glocks_release(struct inode *inode, struct file *file)  	struct gfs2_glock_iter *gi = seq->private;  	gi->gl = NULL; +	rhashtable_walk_exit(&gi->hti);  	return seq_release_private(inode, file);  }  | 
