Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'gfs2-4.17.fixes2' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2

Pull more gfs2 updates from Bob Peterson:
"We decided to request the latest three patches to be merged into this
merge window while it's still open.

- The first patch adds a new function to lockref:
lockref_put_not_zero

- The second patch fixes GFS2's glock dump code so it uses the new
lockref function. This fixes a problem whereby lock dumps could
miss glocks.

- I made a minor patch to update some comments and fix the lock
ordering text in our gfs2-glocks.txt Documentation file"

* tag 'gfs2-4.17.fixes2' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2:
GFS2: Minor improvements to comments and documentation
gfs2: Stop using rhashtable_walk_peek
lockref: Add lockref_put_not_zero

+62 -23
+3 -2
Documentation/filesystems/gfs2-glocks.txt
··· 100 100 101 101 Glock locking order within GFS2: 102 102 103 - 1. i_mutex (if required) 103 + 1. i_rwsem (if required) 104 104 2. Rename glock (for rename only) 105 105 3. Inode glock(s) 106 106 (Parents before children, inodes at "same level" with same parent in 107 107 lock number order) 108 108 4. Rgrp glock(s) (for (de)allocation operations) 109 109 5. Transaction glock (via gfs2_trans_begin) for non-read operations 110 - 6. Page lock (always last, very important!) 110 + 6. i_rw_mutex (if required) 111 + 7. Page lock (always last, very important!) 111 112 112 113 There are two glocks per inode. One deals with access to the inode 113 114 itself (locking order as above), and the other, known as the iopen
+1 -1
fs/gfs2/bmap.c
··· 1744 1744 * @newsize: the size to make the file 1745 1745 * 1746 1746 * The file size can grow, shrink, or stay the same size. This 1747 - * is called holding i_mutex and an exclusive glock on the inode 1747 + * is called holding i_rwsem and an exclusive glock on the inode 1748 1748 * in question. 1749 1749 * 1750 1750 * Returns: errno
+28 -19
fs/gfs2/glock.c
··· 1923 1923 1924 1924 static void gfs2_glock_iter_next(struct gfs2_glock_iter *gi, loff_t n) 1925 1925 { 1926 - if (n == 0) 1927 - gi->gl = rhashtable_walk_peek(&gi->hti); 1928 - else { 1929 - gi->gl = rhashtable_walk_next(&gi->hti); 1930 - n--; 1926 + struct gfs2_glock *gl = gi->gl; 1927 + 1928 + if (gl) { 1929 + if (n == 0) 1930 + return; 1931 + if (!lockref_put_not_zero(&gl->gl_lockref)) 1932 + gfs2_glock_queue_put(gl); 1931 1933 } 1932 1934 for (;;) { 1933 - if (IS_ERR_OR_NULL(gi->gl)) { 1934 - if (!gi->gl) 1935 - return; 1936 - if (PTR_ERR(gi->gl) != -EAGAIN) { 1937 - gi->gl = NULL; 1938 - return; 1935 + gl = rhashtable_walk_next(&gi->hti); 1936 + if (IS_ERR_OR_NULL(gl)) { 1937 + if (gl == ERR_PTR(-EAGAIN)) { 1938 + n = 1; 1939 + continue; 1939 1940 } 1940 - n = 0; 1941 - } else if (gi->sdp == gi->gl->gl_name.ln_sbd && 1942 - !__lockref_is_dead(&gi->gl->gl_lockref)) { 1943 - if (!n--) 1944 - break; 1941 + gl = NULL; 1942 + break; 1945 1943 } 1946 - gi->gl = rhashtable_walk_next(&gi->hti); 1944 + if (gl->gl_name.ln_sbd != gi->sdp) 1945 + continue; 1946 + if (n <= 1) { 1947 + if (!lockref_get_not_dead(&gl->gl_lockref)) 1948 + continue; 1949 + break; 1950 + } else { 1951 + if (__lockref_is_dead(&gl->gl_lockref)) 1952 + continue; 1953 + n--; 1954 + } 1947 1955 } 1956 + gi->gl = gl; 1948 1957 } 1949 1958 1950 1959 static void *gfs2_glock_seq_start(struct seq_file *seq, loff_t *pos) ··· 1997 1988 { 1998 1989 struct gfs2_glock_iter *gi = seq->private; 1999 1990 2000 - gi->gl = NULL; 2001 1991 rhashtable_walk_stop(&gi->hti); 2002 1992 } 2003 1993 ··· 2084 2076 struct seq_file *seq = file->private_data; 2085 2077 struct gfs2_glock_iter *gi = seq->private; 2086 2078 2087 - gi->gl = NULL; 2079 + if (gi->gl) 2080 + gfs2_glock_put(gi->gl); 2088 2081 rhashtable_walk_exit(&gi->hti); 2089 2082 return seq_release_private(inode, file); 2090 2083 }
+1 -1
fs/gfs2/ops_fstype.c
··· 825 825 goto fail_rindex; 826 826 } 827 827 /* 828 - * i_mutex on quota files is special. Since this inode is hidden system 828 + * i_rwsem on quota files is special. Since this inode is hidden system 829 829 * file, we are safe to define locking ourselves. 830 830 */ 831 831 lockdep_set_class(&sdp->sd_quota_inode->i_rwsem,
+1
include/linux/lockref.h
··· 37 37 extern void lockref_get(struct lockref *); 38 38 extern int lockref_put_return(struct lockref *); 39 39 extern int lockref_get_not_zero(struct lockref *); 40 + extern int lockref_put_not_zero(struct lockref *); 40 41 extern int lockref_get_or_lock(struct lockref *); 41 42 extern int lockref_put_or_lock(struct lockref *); 42 43
+28
lib/lockref.c
··· 81 81 EXPORT_SYMBOL(lockref_get_not_zero); 82 82 83 83 /** 84 + * lockref_put_not_zero - Decrements count unless count <= 1 before decrement 85 + * @lockref: pointer to lockref structure 86 + * Return: 1 if count updated successfully or 0 if count would become zero 87 + */ 88 + int lockref_put_not_zero(struct lockref *lockref) 89 + { 90 + int retval; 91 + 92 + CMPXCHG_LOOP( 93 + new.count--; 94 + if (old.count <= 1) 95 + return 0; 96 + , 97 + return 1; 98 + ); 99 + 100 + spin_lock(&lockref->lock); 101 + retval = 0; 102 + if (lockref->count > 1) { 103 + lockref->count--; 104 + retval = 1; 105 + } 106 + spin_unlock(&lockref->lock); 107 + return retval; 108 + } 109 + EXPORT_SYMBOL(lockref_put_not_zero); 110 + 111 + /** 84 112 * lockref_get_or_lock - Increments count unless the count is 0 or dead 85 113 * @lockref: pointer to lockref structure 86 114 * Return: 1 if count updated successfully or 0 if count was zero