Commit c4eb1b07 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull GFS2 updates from Steven Whitehouse:
 "There are a few bug fixes for various, mostly very minor corner cases,
  plus some interesting new features.

  The new features include atomic_open whose main benefit will be the
  reduction in locking overhead in case of combined lookup/create and
  open operations, sorting the log buffer lists by block number to
  improve the efficiency of AIL writeback, and aggressively issuing
  revokes in gfs2_log_flush to reduce overhead when dropping glocks."

* git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-nmw:
  GFS2: Reserve journal space for quota change in do_grow
  GFS2: Fix fstrim boundary conditions
  GFS2: fix warning message
  GFS2: aggressively issue revokes in gfs2_log_flush
  GFS2: fix regression in dir_double_exhash
  GFS2: Add atomic_open support
  GFS2: Only do one directory search on create
  GFS2: fix error propagation in init_threads()
  GFS2: Remove no-op wrapper function
  GFS2: Cocci spatch "ptr_ret.spatch"
  GFS2: Eliminate gfs2_rg_lops
  GFS2: Sort buffer lists by inplace block number
parents 9e239bb9 a01aedfe
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -1612,6 +1612,10 @@ EXPORT_SYMBOL(d_obtain_alias);
 * If a dentry was found and moved, then it is returned.  Otherwise NULL
 * is returned.  This matches the expected return value of ->lookup.
 *
 * Cluster filesystems may call this function with a negative, hashed dentry.
 * In that case, we know that the inode will be a regular file, and also this
 * will only occur during atomic_open. So we need to check for the dentry
 * being already hashed only in the final case.
 */
struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
{
@@ -1636,8 +1640,11 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
			security_d_instantiate(dentry, inode);
			d_rehash(dentry);
		}
	} else
		d_add(dentry, inode);
	} else {
		d_instantiate(dentry, inode);
		if (d_unhashed(dentry))
			d_rehash(dentry);
	}
	return new;
}
EXPORT_SYMBOL(d_splice_alias);
+3 −1
Original line number Diff line number Diff line
@@ -1232,7 +1232,9 @@ static int do_grow(struct inode *inode, u64 size)
		unstuff = 1;
	}

	error = gfs2_trans_begin(sdp, RES_DINODE + RES_STATFS + RES_RG_BIT, 0);
	error = gfs2_trans_begin(sdp, RES_DINODE + RES_STATFS + RES_RG_BIT +
				 (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF ?
				  0 : RES_QUOTA), 0);
	if (error)
		goto do_grow_release;

+15 −11
Original line number Diff line number Diff line
@@ -1125,13 +1125,14 @@ static int dir_double_exhash(struct gfs2_inode *dip)
	if (IS_ERR(hc))
		return PTR_ERR(hc);

	h = hc2 = kmalloc(hsize_bytes * 2, GFP_NOFS | __GFP_NOWARN);
	hc2 = kmalloc(hsize_bytes * 2, GFP_NOFS | __GFP_NOWARN);
	if (hc2 == NULL)
		hc2 = __vmalloc(hsize_bytes * 2, GFP_NOFS, PAGE_KERNEL);

	if (!hc2)
		return -ENOMEM;

	h = hc2;
	error = gfs2_meta_inode_buffer(dip, &dibh);
	if (error)
		goto out_kfree;
@@ -1547,9 +1548,9 @@ out:

/**
 * gfs2_dir_search - Search a directory
 * @dip: The GFS2 inode
 * @filename:
 * @inode:
 * @dip: The GFS2 dir inode
 * @name: The name we are looking up
 * @fail_on_exist: Fail if the name exists rather than looking it up
 *
 * This routine searches a directory for a file or another directory.
 * Assumes a glock is held on dip.
@@ -1557,22 +1558,25 @@ out:
 * Returns: errno
 */

struct inode *gfs2_dir_search(struct inode *dir, const struct qstr *name)
struct inode *gfs2_dir_search(struct inode *dir, const struct qstr *name,
			      bool fail_on_exist)
{
	struct buffer_head *bh;
	struct gfs2_dirent *dent;
	struct inode *inode;
	u64 addr, formal_ino;
	u16 dtype;

	dent = gfs2_dirent_search(dir, name, gfs2_dirent_find, &bh);
	if (dent) {
		if (IS_ERR(dent))
			return ERR_CAST(dent);
		inode = gfs2_inode_lookup(dir->i_sb, 
				be16_to_cpu(dent->de_type),
				be64_to_cpu(dent->de_inum.no_addr),
				be64_to_cpu(dent->de_inum.no_formal_ino), 0);
		dtype = be16_to_cpu(dent->de_type);
		addr = be64_to_cpu(dent->de_inum.no_addr);
		formal_ino = be64_to_cpu(dent->de_inum.no_formal_ino);
		brelse(bh);
		return inode;
		if (fail_on_exist)
			return ERR_PTR(-EEXIST);
		return gfs2_inode_lookup(dir->i_sb, dtype, addr, formal_ino, 0);
	}
	return ERR_PTR(-ENOENT);
}
+2 −1
Original line number Diff line number Diff line
@@ -18,7 +18,8 @@ struct gfs2_inode;
struct gfs2_inum;

extern struct inode *gfs2_dir_search(struct inode *dir,
				     const struct qstr *filename);
				     const struct qstr *filename,
				     bool fail_on_exist);
extern int gfs2_dir_check(struct inode *dir, const struct qstr *filename,
			  const struct gfs2_inode *ip);
extern int gfs2_dir_add(struct inode *inode, const struct qstr *filename,
+46 −23
Original line number Diff line number Diff line
@@ -531,21 +531,30 @@ static int gfs2_mmap(struct file *file, struct vm_area_struct *vma)
}

/**
 * gfs2_open - open a file
 * @inode: the inode to open
 * @file: the struct file for this opening
 * gfs2_open_common - This is common to open and atomic_open
 * @inode: The inode being opened
 * @file: The file being opened
 *
 * Returns: errno
 * This maybe called under a glock or not depending upon how it has
 * been called. We must always be called under a glock for regular
 * files, however. For other file types, it does not matter whether
 * we hold the glock or not.
 *
 * Returns: Error code or 0 for success
 */

static int gfs2_open(struct inode *inode, struct file *file)
int gfs2_open_common(struct inode *inode, struct file *file)
{
	struct gfs2_inode *ip = GFS2_I(inode);
	struct gfs2_holder i_gh;
	struct gfs2_file *fp;
	int error;
	int ret;

	fp = kzalloc(sizeof(struct gfs2_file), GFP_KERNEL);
	if (S_ISREG(inode->i_mode)) {
		ret = generic_file_open(inode, file);
		if (ret)
			return ret;
	}

	fp = kzalloc(sizeof(struct gfs2_file), GFP_NOFS);
	if (!fp)
		return -ENOMEM;

@@ -553,29 +562,43 @@ static int gfs2_open(struct inode *inode, struct file *file)

	gfs2_assert_warn(GFS2_SB(inode), !file->private_data);
	file->private_data = fp;
	return 0;
}

/**
 * gfs2_open - open a file
 * @inode: the inode to open
 * @file: the struct file for this opening
 *
 * After atomic_open, this function is only used for opening files
 * which are already cached. We must still get the glock for regular
 * files to ensure that we have the file size uptodate for the large
 * file check which is in the common code. That is only an issue for
 * regular files though.
 *
 * Returns: errno
 */

static int gfs2_open(struct inode *inode, struct file *file)
{
	struct gfs2_inode *ip = GFS2_I(inode);
	struct gfs2_holder i_gh;
	int error;
	bool need_unlock = false;

	if (S_ISREG(ip->i_inode.i_mode)) {
		error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY,
					   &i_gh);
		if (error)
			goto fail;

		if (!(file->f_flags & O_LARGEFILE) &&
		    i_size_read(inode) > MAX_NON_LFS) {
			error = -EOVERFLOW;
			goto fail_gunlock;
		}

		gfs2_glock_dq_uninit(&i_gh);
			return error;
		need_unlock = true;
	}

	return 0;
	error = gfs2_open_common(inode, file);

fail_gunlock:
	if (need_unlock)
		gfs2_glock_dq_uninit(&i_gh);
fail:
	file->private_data = NULL;
	kfree(fp);

	return error;
}

Loading