Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4d589677 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull GFS2 updates from Bob Peterson:
 "Here is a list of patches we've accumulated for GFS2 for the current
  upstream merge window.  Last window's set was short, but I warned that
  this one would be bigger, and so it is.  We've got 19 patches:

   - A patch from Abhi Das to propagate the GFS2_DIF_SYSTEM bit so that
     newly added journals don't get flagged, deleted, and recreated by
     fsck.gfs2.

   - Two patches from Andreas Gruenbacher to improve GFS2 performance
     where extended attributes are involved.

   - A patch from Andy Price to fix a suspicious rcu dereference error.

   - Two patches from Ben Marzinski that rework how GFS2's NFS cookies
     are managed.  This fixes readdir problems with nfs-over-gfs2.

   - A patch from Ben Marzinski that fixes a race in unmounting GFS2.

   - A set of four patches from me to move the resource group
     reservations inside the gfs2 inode to improve performance and fix a
     bug whereby get_write_access improperly prevented some operations
     like chown.

   - A patch from me to spinlock-protect the setting of system statfs
     file data.  This was causing small discrepancies between df and du.

   - A patch from me to reintroduce a timeout while clearing glocks
     which was accidentally dropped some time ago.

   - A patch from me to wait for iopen glock dequeues in order to
     improve deleting of files that were unlinked from a different
     cluster node.

   - A patch from me to ensure metadata address spaces get truncated
     when an inode is evicted.

   - A patch from me to fix a bug in which a memory leak could occur in
     some error cases when inodes were trying to be created.

   - A patch to consistently use iopen glocks to transition from the
     unlinked state to the deleted state.

   - A patch to fix a glock reference count error when inode creation
     fails.

   - A patch from Junxiao Bi to fix an flock panic.

   - A patch from Markus Elfring that removes an unnecessary if"

* tag 'gfs2-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2:
  gfs2: fix flock panic issue
  GFS2: Don't do glock put on when inode creation fails
  GFS2: Always use iopen glock for gl_deletes
  GFS2: Release iopen glock in gfs2_create_inode error cases
  GFS2: Truncate address space mapping when deleting an inode
  GFS2: Wait for iopen glock dequeues
  gfs2: clear journal live bit in	gfs2_log_flush
  gfs2: change gfs2 readdir cookie
  gfs2: keep offset when splitting dir leaf blocks
  GFS2: Reintroduce a timeout in function gfs2_gl_hash_clear
  GFS2: Update master statfs buffer with sd_statfs_spin locked
  GFS2: Reduce size of incore inode
  GFS2: Make rgrp reservations part of the gfs2_inode structure
  GFS2: Extract quota data from reservations structure (revert 5407e242)
  gfs2: Extended attribute readahead optimization
  gfs2: Extended attribute readahead
  GFS2: Use rht_for_each_entry_rcu in glock_hash_walk
  GFS2: Delete an unnecessary check before the function call "iput"
  gfs2: Automatically set GFS2_DIF_SYSTEM flag on system files
parents 33caf82a a93a9983
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -914,7 +914,7 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping,
failed:
	gfs2_trans_end(sdp);
	gfs2_inplace_release(ip);
	if (ip->i_res->rs_qa_qd_num)
	if (ip->i_qadata && ip->i_qadata->qa_qd_num)
		gfs2_quota_unlock(ip);
	if (inode == sdp->sd_rindex) {
		gfs2_glock_dq(&m_ip->i_gh);
+4 −9
Original line number Diff line number Diff line
@@ -787,8 +787,8 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
	if (error)
		goto out_rlist;

	if (gfs2_rs_active(ip->i_res)) /* needs to be done with the rgrp glock held */
		gfs2_rs_deltree(ip->i_res);
	if (gfs2_rs_active(&ip->i_res)) /* needs to be done with the rgrp glock held */
		gfs2_rs_deltree(&ip->i_res);

	error = gfs2_trans_begin(sdp, rg_blocks + RES_DINODE +
				 RES_INDIRECT + RES_STATFS + RES_QUOTA,
@@ -1291,13 +1291,9 @@ int gfs2_setattr_size(struct inode *inode, u64 newsize)
	if (ret)
		return ret;

	ret = get_write_access(inode);
	if (ret)
		return ret;

	inode_dio_wait(inode);

	ret = gfs2_rs_alloc(ip);
	ret = gfs2_rsqa_alloc(ip);
	if (ret)
		goto out;

@@ -1307,10 +1303,9 @@ int gfs2_setattr_size(struct inode *inode, u64 newsize)
		goto out;
	}

	gfs2_rs_deltree(ip->i_res);
	ret = do_shrink(inode, oldsize, newsize);
out:
	put_write_access(inode);
	gfs2_rsqa_delete(ip, NULL);
	return ret;
}

+135 −40
Original line number Diff line number Diff line
@@ -82,6 +82,8 @@

#define gfs2_disk_hash2offset(h) (((u64)(h)) >> 1)
#define gfs2_dir_offset2hash(p) ((u32)(((u64)(p)) << 1))
#define GFS2_HASH_INDEX_MASK 0xffffc000
#define GFS2_USE_HASH_FLAG 0x2000

struct qstr gfs2_qdot __read_mostly;
struct qstr gfs2_qdotdot __read_mostly;
@@ -108,7 +110,7 @@ static int gfs2_dir_get_existing_buffer(struct gfs2_inode *ip, u64 block,
	struct buffer_head *bh;
	int error;

	error = gfs2_meta_read(ip->i_gl, block, DIO_WAIT, &bh);
	error = gfs2_meta_read(ip->i_gl, block, DIO_WAIT, 0, &bh);
	if (error)
		return error;
	if (gfs2_metatype_check(GFS2_SB(&ip->i_inode), bh, GFS2_METATYPE_JD)) {
@@ -305,7 +307,7 @@ static int gfs2_dir_read_data(struct gfs2_inode *ip, __be64 *buf,
			BUG_ON(extlen < 1);
			bh = gfs2_meta_ra(ip->i_gl, dblock, extlen);
		} else {
			error = gfs2_meta_read(ip->i_gl, dblock, DIO_WAIT, &bh);
			error = gfs2_meta_read(ip->i_gl, dblock, DIO_WAIT, 0, &bh);
			if (error)
				goto fail;
		}
@@ -443,6 +445,27 @@ static int gfs2_dirent_last(const struct gfs2_dirent *dent,
	return 0;
}

/* Look for the dirent that contains the offset specified in data. Once we
 * find that dirent, there must be space available there for the new dirent */
static int gfs2_dirent_find_offset(const struct gfs2_dirent *dent,
				  const struct qstr *name,
				  void *ptr)
{
	unsigned required = GFS2_DIRENT_SIZE(name->len);
	unsigned actual = GFS2_DIRENT_SIZE(be16_to_cpu(dent->de_name_len));
	unsigned totlen = be16_to_cpu(dent->de_rec_len);

	if (ptr < (void *)dent || ptr >= (void *)dent + totlen)
		return 0;
	if (gfs2_dirent_sentinel(dent))
		actual = 0;
	if (ptr < (void *)dent + actual)
		return -1;
	if ((void *)dent + totlen >= ptr + required)
		return 1;
	return -1;
}

static int gfs2_dirent_find_space(const struct gfs2_dirent *dent,
				  const struct qstr *name,
				  void *opaque)
@@ -682,21 +705,17 @@ static void dirent_del(struct gfs2_inode *dip, struct buffer_head *bh,
	prev->de_rec_len = cpu_to_be16(prev_rec_len);
}

/*
 * Takes a dent from which to grab space as an argument. Returns the
 * newly created dent.
 */
static struct gfs2_dirent *gfs2_init_dirent(struct inode *inode,

static struct gfs2_dirent *do_init_dirent(struct inode *inode,
					  struct gfs2_dirent *dent,
					  const struct qstr *name,
					    struct buffer_head *bh)
					  struct buffer_head *bh,
					  unsigned offset)
{
	struct gfs2_inode *ip = GFS2_I(inode);
	struct gfs2_dirent *ndent;
	unsigned offset = 0, totlen;
	unsigned totlen;

	if (!gfs2_dirent_sentinel(dent))
		offset = GFS2_DIRENT_SIZE(be16_to_cpu(dent->de_name_len));
	totlen = be16_to_cpu(dent->de_rec_len);
	BUG_ON(offset + name->len > totlen);
	gfs2_trans_add_meta(ip->i_gl, bh);
@@ -706,16 +725,35 @@ static struct gfs2_dirent *gfs2_init_dirent(struct inode *inode,
	return ndent;
}

static struct gfs2_dirent *gfs2_dirent_alloc(struct inode *inode,

/*
 * Takes a dent from which to grab space as an argument. Returns the
 * newly created dent.
 */
static struct gfs2_dirent *gfs2_init_dirent(struct inode *inode,
					    struct gfs2_dirent *dent,
					    const struct qstr *name,
					    struct buffer_head *bh)
{
	unsigned offset = 0;

	if (!gfs2_dirent_sentinel(dent))
		offset = GFS2_DIRENT_SIZE(be16_to_cpu(dent->de_name_len));
	return do_init_dirent(inode, dent, name, bh, offset);
}

static struct gfs2_dirent *gfs2_dirent_split_alloc(struct inode *inode,
						   struct buffer_head *bh,
					     const struct qstr *name)
						   const struct qstr *name,
						   void *ptr)
{
	struct gfs2_dirent *dent;
	dent = gfs2_dirent_scan(inode, bh->b_data, bh->b_size,
				gfs2_dirent_find_space, name, NULL);
				gfs2_dirent_find_offset, name, ptr);
	if (!dent || IS_ERR(dent))
		return dent;
	return gfs2_init_dirent(inode, dent, name, bh);
	return do_init_dirent(inode, dent, name, bh,
			      (unsigned)(ptr - (void *)dent));
}

static int get_leaf(struct gfs2_inode *dip, u64 leaf_no,
@@ -723,7 +761,7 @@ static int get_leaf(struct gfs2_inode *dip, u64 leaf_no,
{
	int error;

	error = gfs2_meta_read(dip->i_gl, leaf_no, DIO_WAIT, bhp);
	error = gfs2_meta_read(dip->i_gl, leaf_no, DIO_WAIT, 0, bhp);
	if (!error && gfs2_metatype_check(GFS2_SB(&dip->i_inode), *bhp, GFS2_METATYPE_LF)) {
		/* pr_info("block num=%llu\n", leaf_no); */
		error = -EIO;
@@ -1051,10 +1089,11 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name)
		if (!gfs2_dirent_sentinel(dent) &&
		    be32_to_cpu(dent->de_hash) < divider) {
			struct qstr str;
			void *ptr = ((char *)dent - obh->b_data) + nbh->b_data;
			str.name = (char*)(dent+1);
			str.len = be16_to_cpu(dent->de_name_len);
			str.hash = be32_to_cpu(dent->de_hash);
			new = gfs2_dirent_alloc(inode, nbh, &str);
			new = gfs2_dirent_split_alloc(inode, nbh, &str, ptr);
			if (IS_ERR(new)) {
				error = PTR_ERR(new);
				break;
@@ -1186,10 +1225,10 @@ static int compare_dents(const void *a, const void *b)
	int ret = 0;

	dent_a = *(const struct gfs2_dirent **)a;
	hash_a = be32_to_cpu(dent_a->de_hash);
	hash_a = dent_a->de_cookie;

	dent_b = *(const struct gfs2_dirent **)b;
	hash_b = be32_to_cpu(dent_b->de_hash);
	hash_b = dent_b->de_cookie;

	if (hash_a > hash_b)
		ret = 1;
@@ -1227,19 +1266,20 @@ static int compare_dents(const void *a, const void *b)
 */

static int do_filldir_main(struct gfs2_inode *dip, struct dir_context *ctx,
			   const struct gfs2_dirent **darr, u32 entries,
			   int *copied)
			   struct gfs2_dirent **darr, u32 entries,
			   u32 sort_start, int *copied)
{
	const struct gfs2_dirent *dent, *dent_next;
	u64 off, off_next;
	unsigned int x, y;
	int run = 0;

	sort(darr, entries, sizeof(struct gfs2_dirent *), compare_dents, NULL);
	if (sort_start < entries)
		sort(&darr[sort_start], entries - sort_start,
		     sizeof(struct gfs2_dirent *), compare_dents, NULL);

	dent_next = darr[0];
	off_next = be32_to_cpu(dent_next->de_hash);
	off_next = gfs2_disk_hash2offset(off_next);
	off_next = dent_next->de_cookie;

	for (x = 0, y = 1; x < entries; x++, y++) {
		dent = dent_next;
@@ -1247,8 +1287,7 @@ static int do_filldir_main(struct gfs2_inode *dip, struct dir_context *ctx,

		if (y < entries) {
			dent_next = darr[y];
			off_next = be32_to_cpu(dent_next->de_hash);
			off_next = gfs2_disk_hash2offset(off_next);
			off_next = dent_next->de_cookie;

			if (off < ctx->pos)
				continue;
@@ -1295,6 +1334,40 @@ static void *gfs2_alloc_sort_buffer(unsigned size)
	return ptr;
}


static int gfs2_set_cookies(struct gfs2_sbd *sdp, struct buffer_head *bh,
			    unsigned leaf_nr, struct gfs2_dirent **darr,
			    unsigned entries)
{
	int sort_id = -1;
	int i;
	
	for (i = 0; i < entries; i++) {
		unsigned offset;

		darr[i]->de_cookie = be32_to_cpu(darr[i]->de_hash);
		darr[i]->de_cookie = gfs2_disk_hash2offset(darr[i]->de_cookie);

		if (!sdp->sd_args.ar_loccookie)
			continue;
		offset = (char *)(darr[i]) -
			 (bh->b_data + gfs2_dirent_offset(bh->b_data));
		offset /= GFS2_MIN_DIRENT_SIZE;
		offset += leaf_nr * sdp->sd_max_dents_per_leaf;
		if (offset >= GFS2_USE_HASH_FLAG ||
		    leaf_nr >= GFS2_USE_HASH_FLAG) {
			darr[i]->de_cookie |= GFS2_USE_HASH_FLAG;
			if (sort_id < 0)
				sort_id = i;
			continue;
		}
		darr[i]->de_cookie &= GFS2_HASH_INDEX_MASK;
		darr[i]->de_cookie |= offset;
	}
	return sort_id;
}	


static int gfs2_dir_read_leaf(struct inode *inode, struct dir_context *ctx,
			      int *copied, unsigned *depth,
			      u64 leaf_no)
@@ -1304,12 +1377,11 @@ static int gfs2_dir_read_leaf(struct inode *inode, struct dir_context *ctx,
	struct buffer_head *bh;
	struct gfs2_leaf *lf;
	unsigned entries = 0, entries2 = 0;
	unsigned leaves = 0;
	const struct gfs2_dirent **darr, *dent;
	unsigned leaves = 0, leaf = 0, offset, sort_offset;
	struct gfs2_dirent **darr, *dent;
	struct dirent_gather g;
	struct buffer_head **larr;
	int leaf = 0;
	int error, i;
	int error, i, need_sort = 0, sort_id;
	u64 lfn = leaf_no;

	do {
@@ -1325,6 +1397,11 @@ static int gfs2_dir_read_leaf(struct inode *inode, struct dir_context *ctx,
		brelse(bh);
	} while(lfn);

	if (*depth < GFS2_DIR_MAX_DEPTH || !sdp->sd_args.ar_loccookie) {
		need_sort = 1;
		sort_offset = 0;
	}

	if (!entries)
		return 0;

@@ -1338,8 +1415,8 @@ static int gfs2_dir_read_leaf(struct inode *inode, struct dir_context *ctx,
	larr = gfs2_alloc_sort_buffer((leaves + entries + 99) * sizeof(void *));
	if (!larr)
		goto out;
	darr = (const struct gfs2_dirent **)(larr + leaves);
	g.pdent = darr;
	darr = (struct gfs2_dirent **)(larr + leaves);
	g.pdent = (const struct gfs2_dirent **)darr;
	g.offset = 0;
	lfn = leaf_no;

@@ -1350,6 +1427,7 @@ static int gfs2_dir_read_leaf(struct inode *inode, struct dir_context *ctx,
		lf = (struct gfs2_leaf *)bh->b_data;
		lfn = be64_to_cpu(lf->lf_next);
		if (lf->lf_entries) {
			offset = g.offset;
			entries2 += be16_to_cpu(lf->lf_entries);
			dent = gfs2_dirent_scan(inode, bh->b_data, bh->b_size,
						gfs2_dirent_gather, NULL, &g);
@@ -1367,16 +1445,25 @@ static int gfs2_dir_read_leaf(struct inode *inode, struct dir_context *ctx,
				goto out_free;
			}
			error = 0;
			sort_id = gfs2_set_cookies(sdp, bh, leaf, &darr[offset],
						   be16_to_cpu(lf->lf_entries));
			if (!need_sort && sort_id >= 0) {
				need_sort = 1;
				sort_offset = offset + sort_id;
			}
			larr[leaf++] = bh;
		} else {
			larr[leaf++] = NULL;
			brelse(bh);
		}
	} while(lfn);

	BUG_ON(entries2 != entries);
	error = do_filldir_main(ip, ctx, darr, entries, copied);
	error = do_filldir_main(ip, ctx, darr, entries, need_sort ?
				sort_offset : entries, copied);
out_free:
	for(i = 0; i < leaf; i++)
		if (larr[i])
			brelse(larr[i]);
	kvfree(larr);
out:
@@ -1483,7 +1570,7 @@ int gfs2_dir_read(struct inode *inode, struct dir_context *ctx,
	struct gfs2_inode *dip = GFS2_I(inode);
	struct gfs2_sbd *sdp = GFS2_SB(inode);
	struct dirent_gather g;
	const struct gfs2_dirent **darr, *dent;
	struct gfs2_dirent **darr, *dent;
	struct buffer_head *dibh;
	int copied = 0;
	int error;
@@ -1507,7 +1594,7 @@ int gfs2_dir_read(struct inode *inode, struct dir_context *ctx,
	/* 96 is max number of dirents which can be stuffed into an inode */
	darr = kmalloc(96 * sizeof(struct gfs2_dirent *), GFP_NOFS);
	if (darr) {
		g.pdent = darr;
		g.pdent = (const struct gfs2_dirent **)darr;
		g.offset = 0;
		dent = gfs2_dirent_scan(inode, dibh->b_data, dibh->b_size,
					gfs2_dirent_gather, NULL, &g);
@@ -1524,8 +1611,9 @@ int gfs2_dir_read(struct inode *inode, struct dir_context *ctx,
			error = -EIO;
			goto out;
		}
		gfs2_set_cookies(sdp, dibh, 0, darr, dip->i_entries);
		error = do_filldir_main(dip, ctx, darr,
					dip->i_entries, &copied);
					dip->i_entries, 0, &copied);
out:
		kfree(darr);
	}
@@ -1560,15 +1648,22 @@ struct inode *gfs2_dir_search(struct inode *dir, const struct qstr *name,

	dent = gfs2_dirent_search(dir, name, gfs2_dirent_find, &bh);
	if (dent) {
		struct inode *inode;
		u16 rahead;

		if (IS_ERR(dent))
			return ERR_CAST(dent);
		dtype = be16_to_cpu(dent->de_type);
		rahead = be16_to_cpu(dent->de_rahead);
		addr = be64_to_cpu(dent->de_inum.no_addr);
		formal_ino = be64_to_cpu(dent->de_inum.no_formal_ino);
		brelse(bh);
		if (fail_on_exist)
			return ERR_PTR(-EEXIST);
		return gfs2_inode_lookup(dir->i_sb, dtype, addr, formal_ino, 0);
		inode = gfs2_inode_lookup(dir->i_sb, dtype, addr, formal_ino, 0);
		if (!IS_ERR(inode))
			GFS2_I(inode)->i_rahead = rahead;
		return inode;
	}
	return ERR_PTR(-ENOENT);
}
+16 −18
Original line number Diff line number Diff line
@@ -298,9 +298,9 @@ static int gfs2_set_flags(struct file *filp, u32 __user *ptr)
		gfsflags &= ~GFS2_DIF_TOPDIR;
		if (gfsflags & GFS2_DIF_INHERIT_JDATA)
			gfsflags ^= (GFS2_DIF_JDATA | GFS2_DIF_INHERIT_JDATA);
		return do_gfs2_set_flags(filp, gfsflags, ~0);
		return do_gfs2_set_flags(filp, gfsflags, ~GFS2_DIF_SYSTEM);
	}
	return do_gfs2_set_flags(filp, gfsflags, ~GFS2_DIF_JDATA);
	return do_gfs2_set_flags(filp, gfsflags, ~(GFS2_DIF_SYSTEM | GFS2_DIF_JDATA));
}

static long gfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
@@ -336,8 +336,8 @@ static void gfs2_size_hint(struct file *filep, loff_t offset, size_t size)
	size_t blks = (size + sdp->sd_sb.sb_bsize - 1) >> sdp->sd_sb.sb_bsize_shift;
	int hint = min_t(size_t, INT_MAX, blks);

	if (hint > atomic_read(&ip->i_res->rs_sizehint))
		atomic_set(&ip->i_res->rs_sizehint, hint);
	if (hint > atomic_read(&ip->i_res.rs_sizehint))
		atomic_set(&ip->i_res.rs_sizehint, hint);
}

/**
@@ -397,14 +397,10 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
	/* Update file times before taking page lock */
	file_update_time(vma->vm_file);

	ret = get_write_access(inode);
	ret = gfs2_rsqa_alloc(ip);
	if (ret)
		goto out;

	ret = gfs2_rs_alloc(ip);
	if (ret)
		goto out_write_access;

	gfs2_size_hint(vma->vm_file, pos, PAGE_CACHE_SIZE);

	gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
@@ -486,8 +482,6 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
		set_page_dirty(page);
		wait_for_stable_page(page);
	}
out_write_access:
	put_write_access(inode);
out:
	sb_end_pagefault(inode->i_sb);
	return block_page_mkwrite_return(ret);
@@ -623,7 +617,7 @@ static int gfs2_release(struct inode *inode, struct file *file)
	if (!(file->f_mode & FMODE_WRITE))
		return 0;

	gfs2_rs_delete(ip, &inode->i_writecount);
	gfs2_rsqa_delete(ip, &inode->i_writecount);
	return 0;
}

@@ -703,7 +697,7 @@ static ssize_t gfs2_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
	struct gfs2_inode *ip = GFS2_I(file_inode(file));
	int ret;

	ret = gfs2_rs_alloc(ip);
	ret = gfs2_rsqa_alloc(ip);
	if (ret)
		return ret;

@@ -938,13 +932,14 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset, loff_t le
	if (ret)
		goto out_unlock;

	ret = gfs2_rs_alloc(ip);
	ret = gfs2_rsqa_alloc(ip);
	if (ret)
		goto out_putw;

	ret = __gfs2_fallocate(file, mode, offset, len);
	if (ret)
		gfs2_rs_deltree(ip->i_res);
		gfs2_rs_deltree(&ip->i_res);

out_putw:
	put_write_access(inode);
out_unlock:
@@ -962,7 +957,7 @@ static ssize_t gfs2_file_splice_write(struct pipe_inode_info *pipe,
	int error;
	struct gfs2_inode *ip = GFS2_I(out->f_mapping->host);

	error = gfs2_rs_alloc(ip);
	error = gfs2_rsqa_alloc(ip);
	if (error)
		return (ssize_t)error;

@@ -1018,7 +1013,7 @@ static int do_flock(struct file *file, int cmd, struct file_lock *fl)
	struct gfs2_inode *ip = GFS2_I(file_inode(file));
	struct gfs2_glock *gl;
	unsigned int state;
	int flags;
	u16 flags;
	int error = 0;
	int sleeptime;

@@ -1032,7 +1027,10 @@ static int do_flock(struct file *file, int cmd, struct file_lock *fl)
		if (fl_gh->gh_state == state)
			goto out;
		locks_lock_file_wait(file,
				     &(struct file_lock){.fl_type = F_UNLCK});
				     &(struct file_lock) {
					     .fl_type = F_UNLCK,
					     .fl_flags = FL_FLOCK
				     });
		gfs2_glock_dq(fl_gh);
		gfs2_holder_reinit(state, flags, fl_gh);
	} else {
+10 −8
Original line number Diff line number Diff line
@@ -446,7 +446,7 @@ __acquires(&gl->gl_lockref.lock)
{
	const struct gfs2_glock_operations *glops = gl->gl_ops;
	struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
	unsigned int lck_flags = gh ? gh->gh_flags : 0;
	unsigned int lck_flags = (unsigned int)(gh ? gh->gh_flags : 0);
	int ret;

	lck_flags &= (LM_FLAG_TRY | LM_FLAG_TRY_1CB | LM_FLAG_NOEXP |
@@ -750,7 +750,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
 *
 */

void gfs2_holder_init(struct gfs2_glock *gl, unsigned int state, unsigned flags,
void gfs2_holder_init(struct gfs2_glock *gl, unsigned int state, u16 flags,
		      struct gfs2_holder *gh)
{
	INIT_LIST_HEAD(&gh->gh_list);
@@ -774,7 +774,7 @@ void gfs2_holder_init(struct gfs2_glock *gl, unsigned int state, unsigned flags,
 *
 */

void gfs2_holder_reinit(unsigned int state, unsigned flags, struct gfs2_holder *gh)
void gfs2_holder_reinit(unsigned int state, u16 flags, struct gfs2_holder *gh)
{
	gh->gh_state = state;
	gh->gh_flags = flags;
@@ -1080,7 +1080,7 @@ void gfs2_glock_dq_uninit(struct gfs2_holder *gh)

int gfs2_glock_nq_num(struct gfs2_sbd *sdp, u64 number,
		      const struct gfs2_glock_operations *glops,
		      unsigned int state, int flags, struct gfs2_holder *gh)
		      unsigned int state, u16 flags, struct gfs2_holder *gh)
{
	struct gfs2_glock *gl;
	int error;
@@ -1417,14 +1417,14 @@ static struct shrinker glock_shrinker = {
static void glock_hash_walk(glock_examiner examiner, const struct gfs2_sbd *sdp)
{
	struct gfs2_glock *gl;
	struct rhash_head *pos, *next;
	struct rhash_head *pos;
	const struct bucket_table *tbl;
	int i;

	rcu_read_lock();
	tbl = rht_dereference_rcu(gl_hash_table.tbl, &gl_hash_table);
	for (i = 0; i < tbl->size; i++) {
		rht_for_each_entry_safe(gl, pos, next, tbl, i, gl_node) {
		rht_for_each_entry_rcu(gl, pos, tbl, i, gl_node) {
			if ((gl->gl_name.ln_sbd == sdp) &&
			    lockref_get_not_dead(&gl->gl_lockref))
				examiner(gl);
@@ -1506,7 +1506,9 @@ void gfs2_gl_hash_clear(struct gfs2_sbd *sdp)
	flush_workqueue(glock_workqueue);
	glock_hash_walk(clear_glock, sdp);
	flush_workqueue(glock_workqueue);
	wait_event(sdp->sd_glock_wait, atomic_read(&sdp->sd_glock_disposal) == 0);
	wait_event_timeout(sdp->sd_glock_wait,
			   atomic_read(&sdp->sd_glock_disposal) == 0,
			   HZ * 600);
	glock_hash_walk(dump_glock_func, sdp);
}

@@ -1539,7 +1541,7 @@ static const char *state2str(unsigned state)
	return "??";
}

static const char *hflags2str(char *buf, unsigned flags, unsigned long iflags)
static const char *hflags2str(char *buf, u16 flags, unsigned long iflags)
{
	char *p = buf;
	if (flags & LM_FLAG_TRY)
Loading