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

Commit 445e1ced authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-nmw:
  GFS2: Support for I/O barriers
  GFS2: Add UUID to GFS2 sb
  GFS2: high time to take some time over atime
  GFS2: The war on bloat
  GFS2: GFS2 will panic if you misspell any mount options
  GFS2: Direct IO write at end of file error
  GFS2: Use an IS_ERR test rather than a NULL test
  GFS2: Fix race relating to glock min-hold time
  GFS2: Fix & clean up GFS2 rename
  GFS2: rm on multiple nodes causes panic
  GFS2: Fix metafs mounts
  GFS2: Fix debugfs glock file iterator
parents ef5bef35 254db57f
Loading
Loading
Loading
Loading
+8 −7
Original line number Diff line number Diff line
@@ -1265,6 +1265,8 @@ static void blocking_cb(struct gfs2_sbd *sdp, struct lm_lockname *name,
	holdtime = gl->gl_tchange + gl->gl_ops->go_min_hold_time;
	if (time_before(now, holdtime))
		delay = holdtime - now;
	if (test_bit(GLF_REPLY_PENDING, &gl->gl_flags))
		delay = gl->gl_ops->go_min_hold_time;

	spin_lock(&gl->gl_spin);
	handle_callback(gl, state, 1, delay);
@@ -1578,8 +1580,6 @@ static const char *hflags2str(char *buf, unsigned flags, unsigned long iflags)
		*p++ = 'a';
	if (flags & GL_EXACT)
		*p++ = 'E';
	if (flags & GL_ATIME)
		*p++ = 'a';
	if (flags & GL_NOCACHE)
		*p++ = 'c';
	if (test_bit(HIF_HOLDER, &iflags))
@@ -1816,15 +1816,17 @@ static int gfs2_glock_iter_next(struct gfs2_glock_iter *gi)
	if (gl) {
		gi->gl = hlist_entry(gl->gl_list.next,
				     struct gfs2_glock, gl_list);
	} else {
		gi->gl = hlist_entry(gl_hash_table[gi->hash].hb_list.first,
				     struct gfs2_glock, gl_list);
	}
	if (gi->gl)
		gfs2_glock_hold(gi->gl);
	}
	read_unlock(gl_lock_addr(gi->hash));
	if (gl)
		gfs2_glock_put(gl);
	if (gl && gi->gl == NULL)
		gi->hash++;
	while (gi->gl == NULL) {
		gi->hash++;
		if (gi->hash >= GFS2_GL_HASH_SIZE)
			return 1;
		read_lock(gl_lock_addr(gi->hash));
@@ -1833,7 +1835,6 @@ static int gfs2_glock_iter_next(struct gfs2_glock_iter *gi)
		if (gi->gl)
			gfs2_glock_hold(gi->gl);
		read_unlock(gl_lock_addr(gi->hash));
		gi->hash++;
	}

	if (gi->sdp != gi->gl->gl_sbd)
+0 −1
Original line number Diff line number Diff line
@@ -24,7 +24,6 @@
#define GL_ASYNC		0x00000040
#define GL_EXACT		0x00000080
#define GL_SKIP			0x00000100
#define GL_ATIME		0x00000200
#define GL_NOCACHE		0x00000400

#define GLR_TRYFAILED		13
+19 −19
Original line number Diff line number Diff line
@@ -389,17 +389,18 @@ struct gfs2_args {
	char ar_lockproto[GFS2_LOCKNAME_LEN];	/* Name of the Lock Protocol */
	char ar_locktable[GFS2_LOCKNAME_LEN];	/* Name of the Lock Table */
	char ar_hostdata[GFS2_LOCKNAME_LEN];	/* Host specific data */
	int ar_spectator; /* Don't get a journal because we're always RO */
	int ar_ignore_local_fs; /* Don't optimize even if local_fs is 1 */
	int ar_localflocks; /* Let the VFS do flock|fcntl locks for us */
	int ar_localcaching; /* Local-style caching (dangerous on multihost) */
	int ar_debug; /* Oops on errors instead of trying to be graceful */
	int ar_upgrade; /* Upgrade ondisk/multihost format */
	unsigned int ar_spectator:1;		/* Don't get a journal */
	unsigned int ar_ignore_local_fs:1;	/* Ignore optimisations */
	unsigned int ar_localflocks:1;		/* Let the VFS do flock|fcntl */
	unsigned int ar_localcaching:1;		/* Local caching */
	unsigned int ar_debug:1;		/* Oops on errors */
	unsigned int ar_upgrade:1;		/* Upgrade ondisk format */
	unsigned int ar_posix_acl:1;		/* Enable posix acls */
	unsigned int ar_quota:2;		/* off/account/on */
	unsigned int ar_suiddir:1;		/* suiddir support */
	unsigned int ar_data:2;			/* ordered/writeback */
	unsigned int ar_meta:1;			/* mount metafs */
	unsigned int ar_num_glockd;		/* Number of glockd threads */
	int ar_posix_acl; /* Enable posix acls */
	int ar_quota; /* off/account/on */
	int ar_suiddir; /* suiddir support */
	int ar_data; /* ordered/writeback */
};

struct gfs2_tune {
@@ -419,7 +420,6 @@ struct gfs2_tune {
	unsigned int gt_quota_scale_den; /* Denominator */
	unsigned int gt_quota_cache_secs;
	unsigned int gt_quota_quantum; /* Secs between syncs to quota file */
	unsigned int gt_atime_quantum; /* Min secs between atime updates */
	unsigned int gt_new_files_jdata;
	unsigned int gt_max_readahead; /* Max bytes to read-ahead from disk */
	unsigned int gt_stall_secs; /* Detects trouble! */
@@ -432,7 +432,7 @@ enum {
	SDF_JOURNAL_CHECKED	= 0,
	SDF_JOURNAL_LIVE	= 1,
	SDF_SHUTDOWN		= 2,
	SDF_NOATIME		= 3,
	SDF_NOBARRIERS		= 3,
};

#define GFS2_FSNAME_LEN		256
@@ -461,7 +461,6 @@ struct gfs2_sb_host {

struct gfs2_sbd {
	struct super_block *sd_vfs;
	struct super_block *sd_vfs_meta;
	struct kobject sd_kobj;
	unsigned long sd_flags;	/* SDF_... */
	struct gfs2_sb_host sd_sb;
@@ -499,7 +498,9 @@ struct gfs2_sbd {

	/* Inode Stuff */

	struct inode *sd_master_dir;
	struct dentry *sd_master_dir;
	struct dentry *sd_root_dir;

	struct inode *sd_jindex;
	struct inode *sd_inum_inode;
	struct inode *sd_statfs_inode;
@@ -634,7 +635,6 @@ struct gfs2_sbd {
	/* Debugging crud */

	unsigned long sd_last_warning;
	struct vfsmount *sd_gfs2mnt;
	struct dentry *debugfs_dir;    /* debugfs directory */
	struct dentry *debugfs_dentry_glocks; /* for debugfs */
};
+9 −150
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <linux/crc32.h>
#include <linux/lm_interface.h>
#include <linux/security.h>
#include <linux/time.h>

#include "gfs2.h"
#include "incore.h"
@@ -249,6 +250,7 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
{
	struct gfs2_dinode_host *di = &ip->i_di;
	const struct gfs2_dinode *str = buf;
	struct timespec atime;
	u16 height, depth;

	if (unlikely(ip->i_no_addr != be64_to_cpu(str->di_num.no_addr)))
@@ -275,8 +277,10 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
	di->di_size = be64_to_cpu(str->di_size);
	i_size_write(&ip->i_inode, di->di_size);
	gfs2_set_inode_blocks(&ip->i_inode, be64_to_cpu(str->di_blocks));
	ip->i_inode.i_atime.tv_sec = be64_to_cpu(str->di_atime);
	ip->i_inode.i_atime.tv_nsec = be32_to_cpu(str->di_atime_nsec);
	atime.tv_sec = be64_to_cpu(str->di_atime);
	atime.tv_nsec = be32_to_cpu(str->di_atime_nsec);
	if (timespec_compare(&ip->i_inode.i_atime, &atime) < 0)
		ip->i_inode.i_atime = atime;
	ip->i_inode.i_mtime.tv_sec = be64_to_cpu(str->di_mtime);
	ip->i_inode.i_mtime.tv_nsec = be32_to_cpu(str->di_mtime_nsec);
	ip->i_inode.i_ctime.tv_sec = be64_to_cpu(str->di_ctime);
@@ -1033,13 +1037,11 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,

	if (bh)
		brelse(bh);
	if (!inode)
		return ERR_PTR(-ENOMEM);
	return inode;

fail_gunlock2:
	gfs2_glock_dq_uninit(ghs + 1);
	if (inode)
	if (inode && !IS_ERR(inode))
		iput(inode);
fail_gunlock:
	gfs2_glock_dq(ghs);
@@ -1140,54 +1142,6 @@ int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
	return 0;
}

/*
 * gfs2_ok_to_move - check if it's ok to move a directory to another directory
 * @this: move this
 * @to: to here
 *
 * Follow @to back to the root and make sure we don't encounter @this
 * Assumes we already hold the rename lock.
 *
 * Returns: errno
 */

int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to)
{
	struct inode *dir = &to->i_inode;
	struct super_block *sb = dir->i_sb;
	struct inode *tmp;
	struct qstr dotdot;
	int error = 0;

	gfs2_str2qstr(&dotdot, "..");

	igrab(dir);

	for (;;) {
		if (dir == &this->i_inode) {
			error = -EINVAL;
			break;
		}
		if (dir == sb->s_root->d_inode) {
			error = 0;
			break;
		}

		tmp = gfs2_lookupi(dir, &dotdot, 1);
		if (IS_ERR(tmp)) {
			error = PTR_ERR(tmp);
			break;
		}

		iput(dir);
		dir = tmp;
	}

	iput(dir);

	return error;
}

/**
 * gfs2_readlinki - return the contents of a symlink
 * @ip: the symlink's inode
@@ -1207,8 +1161,8 @@ int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len)
	unsigned int x;
	int error;

	gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &i_gh);
	error = gfs2_glock_nq_atime(&i_gh);
	gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &i_gh);
	error = gfs2_glock_nq(&i_gh);
	if (error) {
		gfs2_holder_uninit(&i_gh);
		return error;
@@ -1243,101 +1197,6 @@ int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len)
	return error;
}

/**
 * gfs2_glock_nq_atime - Acquire a hold on an inode's glock, and
 *       conditionally update the inode's atime
 * @gh: the holder to acquire
 *
 * Tests atime (access time) for gfs2_read, gfs2_readdir and gfs2_mmap
 * Update if the difference between the current time and the inode's current
 * atime is greater than an interval specified at mount.
 *
 * Returns: errno
 */

int gfs2_glock_nq_atime(struct gfs2_holder *gh)
{
	struct gfs2_glock *gl = gh->gh_gl;
	struct gfs2_sbd *sdp = gl->gl_sbd;
	struct gfs2_inode *ip = gl->gl_object;
	s64 quantum = gfs2_tune_get(sdp, gt_atime_quantum);
	unsigned int state;
	int flags;
	int error;
	struct timespec tv = CURRENT_TIME;

	if (gfs2_assert_warn(sdp, gh->gh_flags & GL_ATIME) ||
	    gfs2_assert_warn(sdp, !(gh->gh_flags & GL_ASYNC)) ||
	    gfs2_assert_warn(sdp, gl->gl_ops == &gfs2_inode_glops))
		return -EINVAL;

	state = gh->gh_state;
	flags = gh->gh_flags;

	error = gfs2_glock_nq(gh);
	if (error)
		return error;

	if (test_bit(SDF_NOATIME, &sdp->sd_flags) ||
	    (sdp->sd_vfs->s_flags & MS_RDONLY))
		return 0;

	if (tv.tv_sec - ip->i_inode.i_atime.tv_sec >= quantum) {
		gfs2_glock_dq(gh);
		gfs2_holder_reinit(LM_ST_EXCLUSIVE, gh->gh_flags & ~LM_FLAG_ANY,
				   gh);
		error = gfs2_glock_nq(gh);
		if (error)
			return error;

		/* Verify that atime hasn't been updated while we were
		   trying to get exclusive lock. */

		tv = CURRENT_TIME;
		if (tv.tv_sec - ip->i_inode.i_atime.tv_sec >= quantum) {
			struct buffer_head *dibh;
			struct gfs2_dinode *di;

			error = gfs2_trans_begin(sdp, RES_DINODE, 0);
			if (error == -EROFS)
				return 0;
			if (error)
				goto fail;

			error = gfs2_meta_inode_buffer(ip, &dibh);
			if (error)
				goto fail_end_trans;

			ip->i_inode.i_atime = tv;

			gfs2_trans_add_bh(ip->i_gl, dibh, 1);
			di = (struct gfs2_dinode *)dibh->b_data;
			di->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec);
			di->di_atime_nsec = cpu_to_be32(ip->i_inode.i_atime.tv_nsec);
			brelse(dibh);

			gfs2_trans_end(sdp);
		}

		/* If someone else has asked for the glock,
		   unlock and let them have it. Then reacquire
		   in the original state. */
		if (gfs2_glock_is_blocking(gl)) {
			gfs2_glock_dq(gh);
			gfs2_holder_reinit(state, flags, gh);
			return gfs2_glock_nq(gh);
		}
	}

	return 0;

fail_end_trans:
	gfs2_trans_end(sdp);
fail:
	gfs2_glock_dq(gh);
	return error;
}

static int
__gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr)
{
+0 −2
Original line number Diff line number Diff line
@@ -91,9 +91,7 @@ int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name,
int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
		   const struct gfs2_inode *ip);
int gfs2_permission(struct inode *inode, int mask);
int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to);
int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len);
int gfs2_glock_nq_atime(struct gfs2_holder *gh);
int gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr);
struct inode *gfs2_lookup_simple(struct inode *dip, const char *name);
void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf);
Loading