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

Commit 1715ac63 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull GFS2 update from Steven Whitehouse:
 "In contrast to recent merge windows, there are a number of interesting
  features this time:

  There is a set of patches to improve performance in relation to block
  reservations.  Some correctness fixes for fallocate, and an update to
  the freeze/thaw code which greatly simplyfies this code path.  In
  addition there is a set of clean ups from Al Viro too"

* tag 'gfs2-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-nmw:
  GFS2: gfs2_atomic_open(): simplify the use of finish_no_open()
  GFS2: gfs2_dir_get_hash_table(): avoiding deferred vfree() is easy here...
  GFS2: use kvfree() instead of open-coding it
  GFS2: gfs2_create_inode(): don't bother with d_splice_alias()
  GFS2: bugger off early if O_CREAT open finds a directory
  GFS2: Deletion of unnecessary checks before two function calls
  GFS2: update freeze code to use freeze/thaw_super on all nodes
  fs: add freeze_super/thaw_super fs hooks
  GFS2: Update timestamps on fallocate
  GFS2: Update i_size properly on fallocate
  GFS2: Use inode_newsize_ok and get_write_access in fallocate
  GFS2: If we use up our block reservation, request more next time
  GFS2: Only increase rs_sizehint
  GFS2: Set of distributed preferences for rgrps
  GFS2: directly return gfs2_dir_check()
parents 08e2fb6c ec7d879c
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -235,6 +235,9 @@ struct super_block *freeze_bdev(struct block_device *bdev)
	sb = get_active_super(bdev);
	if (!sb)
		goto out;
	if (sb->s_op->freeze_super)
		error = sb->s_op->freeze_super(sb);
	else
		error = freeze_super(sb);
	if (error) {
		deactivate_super(sb);
@@ -272,6 +275,9 @@ int thaw_bdev(struct block_device *bdev, struct super_block *sb)
	if (!sb)
		goto out;

	if (sb->s_op->thaw_super)
		error = sb->s_op->thaw_super(sb);
	else
		error = thaw_super(sb);
	if (error) {
		bdev->bd_fsfreeze_count++;
+8 −31
Original line number Diff line number Diff line
@@ -365,23 +365,17 @@ static __be64 *gfs2_dir_get_hash_table(struct gfs2_inode *ip)

	ret = gfs2_dir_read_data(ip, hc, hsize);
	if (ret < 0) {
		if (is_vmalloc_addr(hc))
			vfree(hc);
		else
			kfree(hc);
		kvfree(hc);
		return ERR_PTR(ret);
	}

	spin_lock(&inode->i_lock);
	if (ip->i_hash_cache) {
		if (is_vmalloc_addr(hc))
			vfree(hc);
		else
			kfree(hc);
	} else {
	if (likely(!ip->i_hash_cache)) {
		ip->i_hash_cache = hc;
		hc = NULL;
	}
	spin_unlock(&inode->i_lock);
	kvfree(hc);

	return ip->i_hash_cache;
}
@@ -396,10 +390,7 @@ void gfs2_dir_hash_inval(struct gfs2_inode *ip)
{
	__be64 *hc = ip->i_hash_cache;
	ip->i_hash_cache = NULL;
	if (is_vmalloc_addr(hc))
		vfree(hc);
	else
		kfree(hc);
	kvfree(hc);
}

static inline int gfs2_dirent_sentinel(const struct gfs2_dirent *dent)
@@ -1168,10 +1159,7 @@ static int dir_double_exhash(struct gfs2_inode *dip)
	gfs2_dinode_out(dip, dibh->b_data);
	brelse(dibh);
out_kfree:
	if (is_vmalloc_addr(hc2))
		vfree(hc2);
	else
		kfree(hc2);
	kvfree(hc2);
	return error;
}

@@ -1302,14 +1290,6 @@ static void *gfs2_alloc_sort_buffer(unsigned size)
	return ptr;
}

static void gfs2_free_sort_buffer(void *ptr)
{
	if (is_vmalloc_addr(ptr))
		vfree(ptr);
	else
		kfree(ptr);
}

static int gfs2_dir_read_leaf(struct inode *inode, struct dir_context *ctx,
			      int *copied, unsigned *depth,
			      u64 leaf_no)
@@ -1393,7 +1373,7 @@ static int gfs2_dir_read_leaf(struct inode *inode, struct dir_context *ctx,
out_free:
	for(i = 0; i < leaf; i++)
		brelse(larr[i]);
	gfs2_free_sort_buffer(larr);
	kvfree(larr);
out:
	return error;
}
@@ -2004,10 +1984,7 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len,
	gfs2_rlist_free(&rlist);
	gfs2_quota_unhold(dip);
out:
	if (is_vmalloc_addr(ht))
		vfree(ht);
	else
		kfree(ht);
	kvfree(ht);
	return error;
}

+52 −31
Original line number Diff line number Diff line
@@ -337,6 +337,7 @@ 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);
}

@@ -728,7 +729,6 @@ static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len,
	struct gfs2_inode *ip = GFS2_I(inode);
	struct buffer_head *dibh;
	int error;
	loff_t size = len;
	unsigned int nr_blks;
	sector_t lblock = offset >> inode->i_blkbits;

@@ -762,11 +762,6 @@ static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len,
			goto out;
		}
	}
	if (offset + size > inode->i_size && !(mode & FALLOC_FL_KEEP_SIZE))
		i_size_write(inode, offset + size);

	mark_inode_dirty(inode);

out:
	brelse(dibh);
	return error;
@@ -796,8 +791,7 @@ static void calc_max_reserv(struct gfs2_inode *ip, loff_t max, loff_t *len,
	}
}

static long gfs2_fallocate(struct file *file, int mode, loff_t offset,
			   loff_t len)
static long __gfs2_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
{
	struct inode *inode = file_inode(file);
	struct gfs2_sbd *sdp = GFS2_SB(inode);
@@ -811,14 +805,9 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset,
	loff_t bsize_mask = ~((loff_t)sdp->sd_sb.sb_bsize - 1);
	loff_t next = (offset + len - 1) >> sdp->sd_sb.sb_bsize_shift;
	loff_t max_chunk_size = UINT_MAX & bsize_mask;
	struct gfs2_holder gh;

	next = (next + 1) << sdp->sd_sb.sb_bsize_shift;

	/* We only support the FALLOC_FL_KEEP_SIZE mode */
	if (mode & ~FALLOC_FL_KEEP_SIZE)
		return -EOPNOTSUPP;

	offset &= bsize_mask;

	len = next - offset;
@@ -829,17 +818,6 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset,
	if (bytes == 0)
		bytes = sdp->sd_sb.sb_bsize;

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

	mutex_lock(&inode->i_mutex);

	gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
	error = gfs2_glock_nq(&gh);
	if (unlikely(error))
		goto out_uninit;

	gfs2_size_hint(file, offset, len);

	while (len > 0) {
@@ -852,8 +830,7 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset,
		}
		error = gfs2_quota_lock_check(ip);
		if (error)
			goto out_unlock;

			return error;
retry:
		gfs2_write_calc_reserv(ip, bytes, &data_blocks, &ind_blocks);

@@ -895,20 +872,64 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset,
		gfs2_quota_unlock(ip);
	}

	if (error == 0)
		error = generic_write_sync(file, pos, count);
	goto out_unlock;
	if (!(mode & FALLOC_FL_KEEP_SIZE) && (pos + count) > inode->i_size) {
		i_size_write(inode, pos + count);
		/* Marks the inode as dirty */
		file_update_time(file);
	}

	return generic_write_sync(file, pos, count);

out_trans_fail:
	gfs2_inplace_release(ip);
out_qunlock:
	gfs2_quota_unlock(ip);
	return error;
}

static long gfs2_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
{
	struct inode *inode = file_inode(file);
	struct gfs2_inode *ip = GFS2_I(inode);
	struct gfs2_holder gh;
	int ret;

	if (mode & ~FALLOC_FL_KEEP_SIZE)
		return -EOPNOTSUPP;

	mutex_lock(&inode->i_mutex);

	gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
	ret = gfs2_glock_nq(&gh);
	if (ret)
		goto out_uninit;

	if (!(mode & FALLOC_FL_KEEP_SIZE) &&
	    (offset + len) > inode->i_size) {
		ret = inode_newsize_ok(inode, offset + len);
		if (ret)
			goto out_unlock;
	}

	ret = get_write_access(inode);
	if (ret)
		goto out_unlock;

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

	ret = __gfs2_fallocate(file, mode, offset, len);
	if (ret)
		gfs2_rs_deltree(ip->i_res);
out_putw:
	put_write_access(inode);
out_unlock:
	gfs2_glock_dq(&gh);
out_uninit:
	gfs2_holder_uninit(&gh);
	mutex_unlock(&inode->i_mutex);
	return error;
	return ret;
}

#ifdef CONFIG_GFS2_FS_LOCKING_DLM
+1 −2
Original line number Diff line number Diff line
@@ -836,7 +836,6 @@ void gfs2_holder_reinit(unsigned int state, unsigned flags, struct gfs2_holder *
	gh->gh_flags = flags;
	gh->gh_iflags = 0;
	gh->gh_ip = _RET_IP_;
	if (gh->gh_owner_pid)
	put_pid(gh->gh_owner_pid);
	gh->gh_owner_pid = get_pid(task_pid(current));
}
+12 −14
Original line number Diff line number Diff line
@@ -28,6 +28,8 @@
#include "trans.h"
#include "dir.h"

struct workqueue_struct *gfs2_freeze_wq;

static void gfs2_ail_error(struct gfs2_glock *gl, const struct buffer_head *bh)
{
	fs_err(gl->gl_sbd, "AIL buffer %p: blocknr %llu state 0x%08lx mapping %p page state 0x%lx\n",
@@ -94,11 +96,8 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl)
         * on the stack */
	tr.tr_reserved = 1 + gfs2_struct2blk(sdp, tr.tr_revokes, sizeof(u64));
	tr.tr_ip = _RET_IP_;
	sb_start_intwrite(sdp->sd_vfs);
	if (gfs2_log_reserve(sdp, tr.tr_reserved) < 0) {
		sb_end_intwrite(sdp->sd_vfs);
	if (gfs2_log_reserve(sdp, tr.tr_reserved) < 0)
		return;
	}
	WARN_ON_ONCE(current->journal_info);
	current->journal_info = &tr;

@@ -469,20 +468,19 @@ static void inode_go_dump(struct seq_file *seq, const struct gfs2_glock *gl)

static void freeze_go_sync(struct gfs2_glock *gl)
{
	int error = 0;
	struct gfs2_sbd *sdp = gl->gl_sbd;
	DEFINE_WAIT(wait);

	if (gl->gl_state == LM_ST_SHARED &&
	    test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) {
		atomic_set(&sdp->sd_log_freeze, 1);
		wake_up(&sdp->sd_logd_waitq);
		do {
			prepare_to_wait(&sdp->sd_log_frozen_wait, &wait,
					TASK_UNINTERRUPTIBLE);
			if (atomic_read(&sdp->sd_log_freeze))
				io_schedule();
		} while(atomic_read(&sdp->sd_log_freeze));
		finish_wait(&sdp->sd_log_frozen_wait, &wait);
		atomic_set(&sdp->sd_freeze_state, SFS_STARTING_FREEZE);
		error = freeze_super(sdp->sd_vfs);
		if (error) {
			printk(KERN_INFO "GFS2: couldn't freeze filesystem: %d\n", error);
			gfs2_assert_withdraw(sdp, 0);
		}
		queue_work(gfs2_freeze_wq, &sdp->sd_freeze_work);
		gfs2_log_flush(sdp, NULL, FREEZE_FLUSH);
	}
}

Loading