This is the mail archive of the
cluster-cvs@sourceware.org
mailing list for the cluster.
RHEL5 - Revert "gfs-kernel: bz457473 - GFS ignore the noatime andnodiratime mount options"
- From: Abhijith Das <adas at fedoraproject dot org>
- To: cluster-cvs-relay at redhat dot com
- Date: Mon, 13 Oct 2008 22:08:12 +0000 (UTC)
- Subject: RHEL5 - Revert "gfs-kernel: bz457473 - GFS ignore the noatime andnodiratime mount options"
Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=adae80e90795c462f15ba1c09d7968afd00a7746
Commit: adae80e90795c462f15ba1c09d7968afd00a7746
Parent: e04ecdfd2250c49b53c0d2ffaa49bf7c7f159131
Author: Abhijith Das <adas@redhat.com>
AuthorDate: Mon Oct 13 17:05:57 2008 -0500
Committer: Abhijith Das <adas@redhat.com>
CommitterDate: Mon Oct 13 17:05:57 2008 -0500
Revert "gfs-kernel: bz457473 - GFS ignore the noatime and nodiratime mount options"
This reverts commit 8e4398703b140d267ff4325785e9a2cde080b527.
---
gfs-kernel/src/gfs/gfs_ondisk.h | 5 +-
gfs-kernel/src/gfs/glock.h | 1 +
gfs-kernel/src/gfs/incore.h | 2 +
gfs-kernel/src/gfs/inode.c | 201 ++++++++++++++++++++++++++++++++++++++-
gfs-kernel/src/gfs/inode.h | 3 +
gfs-kernel/src/gfs/ioctl.c | 6 +
gfs-kernel/src/gfs/ops_file.c | 20 ++--
gfs-kernel/src/gfs/ops_fstype.c | 33 +++++--
gfs-kernel/src/gfs/ops_super.c | 38 ++------
gfs-kernel/src/gfs/super.c | 1 +
10 files changed, 258 insertions(+), 52 deletions(-)
diff --git a/gfs-kernel/src/gfs/gfs_ondisk.h b/gfs-kernel/src/gfs/gfs_ondisk.h
index 97768b4..2ac9dde 100644
--- a/gfs-kernel/src/gfs/gfs_ondisk.h
+++ b/gfs-kernel/src/gfs/gfs_ondisk.h
@@ -392,6 +392,8 @@ struct gfs_quota {
#define GFS_DIF_DIRECTIO (0x00000010)
#define GFS_DIF_IMMUTABLE (0x00000020) /* Can't change file */
#define GFS_DIF_APPENDONLY (0x00000040) /* Can only add to end of file */
+#define GFS_DIF_NOATIME (0x00000080) /* Don't update access time
+ (currently unused/ignored) */
#define GFS_DIF_SYNC (0x00000100) /* Flush to disk, don't cache
(currently unused/ignored) */
#define GFS_DIF_INHERIT_DIRECTIO (0x40000000) /* new files get DIRECTIO flag */
@@ -1245,8 +1247,7 @@ gfs_dinode_in(struct gfs_dinode *dinode, char *buf)
CPIN_32(dinode, str, di_nlink);
CPIN_64(dinode, str, di_size);
CPIN_64(dinode, str, di_blocks);
- if (gfs64_to_cpu(str->di_atime) > dinode->di_atime)
- CPIN_64(dinode, str, di_atime);
+ CPIN_64(dinode, str, di_atime);
CPIN_64(dinode, str, di_mtime);
CPIN_64(dinode, str, di_ctime);
CPIN_32(dinode, str, di_major);
diff --git a/gfs-kernel/src/gfs/glock.h b/gfs-kernel/src/gfs/glock.h
index e8520bc..3fd0ddb 100644
--- a/gfs-kernel/src/gfs/glock.h
+++ b/gfs-kernel/src/gfs/glock.h
@@ -29,6 +29,7 @@
#define GL_EXACT (0x00000080) /* Requested state must == current state
* for lock to be granted */
#define GL_SKIP (0x00000100) /* Don't read from disk after grant */
+#define GL_ATIME (0x00000200) /* Update inode's ATIME after grant */
#define GL_NOCACHE (0x00000400) /* Release glock when done, don't cache */
#define GL_SYNC (0x00000800) /* Sync to disk when no more holders */
#define GL_NOCANCEL (0x00001000) /* Don't ever cancel this request */
diff --git a/gfs-kernel/src/gfs/incore.h b/gfs-kernel/src/gfs/incore.h
index 7c1451a..09c5f50 100644
--- a/gfs-kernel/src/gfs/incore.h
+++ b/gfs-kernel/src/gfs/incore.h
@@ -882,6 +882,7 @@ struct gfs_tune {
unsigned int gt_quota_simul_sync; /* Max # quotavals to sync at once */
unsigned int gt_quota_warn_period; /* Secs between quota warn msgs */
+ unsigned int gt_atime_quantum; /* Min secs between atime updates */
unsigned int gt_quota_quantum; /* Secs between syncs to quota file */
unsigned int gt_quota_scale_num; /* Numerator */
unsigned int gt_quota_scale_den; /* Denominator */
@@ -932,6 +933,7 @@ struct gfs_gl_hash_bucket {
#define SDF_SHUTDOWN (1) /* FS abnormaly shutdown */
/* (Re)mount options from Linux VFS */
+#define SDF_NOATIME (8) /* Don't change access time */
#define SDF_ROFS (9) /* Read-only mode */
/* Journal log dump support */
diff --git a/gfs-kernel/src/gfs/inode.c b/gfs-kernel/src/gfs/inode.c
index bbb89ed..6aeda25 100644
--- a/gfs-kernel/src/gfs/inode.c
+++ b/gfs-kernel/src/gfs/inode.c
@@ -1692,8 +1692,8 @@ gfs_readlinki(struct gfs_inode *ip, char **buf, unsigned int *len)
unsigned int x;
int error;
- gfs_holder_init(ip->i_gl, LM_ST_SHARED, 0, &i_gh);
- error = gfs_glock_nq(&i_gh);
+ gfs_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &i_gh);
+ error = gfs_glock_nq_atime(&i_gh);
if (error) {
gfs_holder_uninit(&i_gh);
return error;
@@ -1731,6 +1731,203 @@ gfs_readlinki(struct gfs_inode *ip, char **buf, unsigned int *len)
}
/**
+ * gfs_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 gfs_read, gfs_readdir and gfs_mmap
+ * Update if the difference between the current time and the inode's current
+ * atime is greater than an interval specified at mount (or default).
+ *
+ * Will not update if GFS mounted NOATIME (this is *the* place where NOATIME
+ * has an effect) or Read-Only.
+ *
+ * Returns: errno
+ */
+
+int
+gfs_glock_nq_atime(struct gfs_holder *gh)
+{
+ struct gfs_glock *gl = gh->gh_gl;
+ struct gfs_sbd *sdp = gl->gl_sbd;
+ struct gfs_inode *ip = get_gl2ip(gl);
+ int64_t curtime, quantum = gfs_tune_get(sdp, gt_atime_quantum);
+ unsigned int state;
+ int flags;
+ int error;
+
+ if (gfs_assert_warn(sdp, gh->gh_flags & GL_ATIME) ||
+ gfs_assert_warn(sdp, !(gh->gh_flags & GL_ASYNC)) ||
+ gfs_assert_warn(sdp, gl->gl_ops == &gfs_inode_glops))
+ return -EINVAL;
+
+ /* Save original request state of lock holder */
+ state = gh->gh_state;
+ flags = gh->gh_flags;
+
+ error = gfs_glock_nq(gh);
+ if (error)
+ return error;
+
+ if (test_bit(SDF_NOATIME, &sdp->sd_flags) ||
+ test_bit(SDF_ROFS, &sdp->sd_flags))
+ return 0;
+
+ curtime = get_seconds();
+ if (curtime - ip->i_di.di_atime >= quantum) {
+ /* Get EX hold (force EX glock via !ANY) to write the dinode */
+ gfs_glock_dq(gh);
+ gfs_holder_reinit(LM_ST_EXCLUSIVE,
+ gh->gh_flags & ~LM_FLAG_ANY,
+ gh);
+ error = gfs_glock_nq(gh);
+ if (error)
+ return error;
+
+ /* Verify that atime hasn't been updated while we were
+ trying to get exclusive lock. */
+
+ curtime = get_seconds();
+ if (curtime - ip->i_di.di_atime >= quantum) {
+ struct buffer_head *dibh;
+
+ error = gfs_trans_begin(sdp, 1, 0);
+ if (error == -EROFS)
+ return 0;
+ if (error)
+ goto fail;
+
+ error = gfs_get_inode_buffer(ip, &dibh);
+ if (error)
+ goto fail_end_trans;
+
+ ip->i_di.di_atime = curtime;
+
+ gfs_trans_add_bh(ip->i_gl, dibh);
+ gfs_dinode_out(&ip->i_di, dibh->b_data);
+ brelse(dibh);
+
+ gfs_trans_end(sdp);
+ }
+
+ /* If someone else has asked for the glock,
+ unlock and let them have it. Then reacquire
+ in the original state. */
+ if (gfs_glock_is_blocking(gl)) {
+ gfs_glock_dq(gh);
+ gfs_holder_reinit(state, flags, gh);
+ return gfs_glock_nq(gh);
+ }
+ }
+
+ return 0;
+
+ fail_end_trans:
+ gfs_trans_end(sdp);
+
+ fail:
+ gfs_glock_dq(gh);
+
+ return error;
+}
+
+/**
+ * glock_compare_atime - Compare two struct gfs_glock structures for gfs_sort()
+ * @arg_a: the first structure
+ * @arg_b: the second structure
+ *
+ * Sort order determined by (in order of priority):
+ * -- lock number
+ * -- lock state (SHARED > EXCLUSIVE or GL_ATIME, which can demand EXCLUSIVE)
+ *
+ * Returns: 1 if A > B
+ * -1 if A < B
+ * 0 if A = B
+ */
+
+static int
+glock_compare_atime(const void *arg_a, const void *arg_b)
+{
+ struct gfs_holder *gh_a = *(struct gfs_holder **)arg_a;
+ struct gfs_holder *gh_b = *(struct gfs_holder **)arg_b;
+ struct lm_lockname *a = &gh_a->gh_gl->gl_name;
+ struct lm_lockname *b = &gh_b->gh_gl->gl_name;
+ int ret = 0;
+
+ if (a->ln_number > b->ln_number)
+ ret = 1;
+ else if (a->ln_number < b->ln_number)
+ ret = -1;
+ else {
+ if (gh_a->gh_state == LM_ST_SHARED &&
+ gh_b->gh_state == LM_ST_EXCLUSIVE)
+ ret = 1;
+ else if (gh_a->gh_state == LM_ST_SHARED &&
+ (gh_b->gh_flags & GL_ATIME))
+ ret = 1;
+ }
+
+ return ret;
+}
+
+/**
+ * gfs_glock_nq_m_atime - acquire multiple glocks where one may need an
+ * atime update
+ * @num_gh: the number of structures
+ * @ghs: an array of struct gfs_holder structures
+ *
+ * Returns: 0 on success (all glocks acquired),
+ * errno on failure (no glocks acquired)
+ */
+
+int
+gfs_glock_nq_m_atime(unsigned int num_gh, struct gfs_holder *ghs)
+{
+ struct gfs_holder **p;
+ unsigned int x;
+ int error = 0;
+
+ if (!num_gh)
+ return 0;
+
+ if (num_gh == 1) {
+ ghs->gh_flags &= ~(LM_FLAG_TRY | GL_ASYNC);
+ if (ghs->gh_flags & GL_ATIME)
+ error = gfs_glock_nq_atime(ghs);
+ else
+ error = gfs_glock_nq(ghs);
+ return error;
+ }
+
+ p = kmalloc(num_gh * sizeof(struct gfs_holder *), GFP_KERNEL);
+ if (!p)
+ return -ENOMEM;
+
+ for (x = 0; x < num_gh; x++)
+ p[x] = &ghs[x];
+
+ gfs_sort(p, num_gh, sizeof(struct gfs_holder *), glock_compare_atime);
+
+ for (x = 0; x < num_gh; x++) {
+ p[x]->gh_flags &= ~(LM_FLAG_TRY | GL_ASYNC);
+
+ if (p[x]->gh_flags & GL_ATIME)
+ error = gfs_glock_nq_atime(p[x]);
+ else
+ error = gfs_glock_nq(p[x]);
+
+ if (error) {
+ while (x--)
+ gfs_glock_dq(p[x]);
+ break;
+ }
+ }
+
+ kfree(p);
+ return error;
+}
+
+/**
* gfs_try_toss_vnode - See if we can toss a vnode from memory
* @ip: the inode
*
diff --git a/gfs-kernel/src/gfs/inode.h b/gfs-kernel/src/gfs/inode.h
index a36729d..e35bdbd 100644
--- a/gfs-kernel/src/gfs/inode.h
+++ b/gfs-kernel/src/gfs/inode.h
@@ -41,6 +41,9 @@ int gfs_unlink_ok(struct gfs_inode *dip, struct qstr *name,
int gfs_ok_to_move(struct gfs_inode *this, struct gfs_inode *to);
int gfs_readlinki(struct gfs_inode *ip, char **buf, unsigned int *len);
+int gfs_glock_nq_atime(struct gfs_holder *gh);
+int gfs_glock_nq_m_atime(unsigned int num_gh, struct gfs_holder *ghs);
+
void gfs_try_toss_vnode(struct gfs_inode *ip);
int gfs_setattr_simple(struct gfs_inode *ip, struct iattr *attr);
diff --git a/gfs-kernel/src/gfs/ioctl.c b/gfs-kernel/src/gfs/ioctl.c
index 3ca3b71..32db45c 100644
--- a/gfs-kernel/src/gfs/ioctl.c
+++ b/gfs-kernel/src/gfs/ioctl.c
@@ -462,6 +462,7 @@ gi_get_tune(struct gfs_inode *ip,
gfs_printf("glock_purge %u\n", gt->gt_glock_purge);
gfs_printf("quota_simul_sync %u\n", gt->gt_quota_simul_sync);
gfs_printf("quota_warn_period %u\n", gt->gt_quota_warn_period);
+ gfs_printf("atime_quantum %u\n", gt->gt_atime_quantum);
gfs_printf("quota_quantum %u\n", gt->gt_quota_quantum);
gfs_printf("quota_scale_num %u\n", gt->gt_quota_scale_num);
gfs_printf("quota_scale_den %u\n", gt->gt_quota_scale_den);
@@ -633,6 +634,11 @@ gi_set_tune(struct gfs_sbd *sdp, struct gfs_ioctl *gi, int from_user)
return -EINVAL;
tune_set(gt_quota_warn_period, x);
+ } else if (strcmp(param, "atime_quantum") == 0) {
+ if (sscanf(value, "%u", &x) != 1)
+ return -EINVAL;
+ tune_set(gt_atime_quantum, x);
+
} else if (strcmp(param, "quota_quantum") == 0) {
if (sscanf(value, "%u", &x) != 1)
return -EINVAL;
diff --git a/gfs-kernel/src/gfs/ops_file.c b/gfs-kernel/src/gfs/ops_file.c
index ed586dc..5df9a81 100644
--- a/gfs-kernel/src/gfs/ops_file.c
+++ b/gfs-kernel/src/gfs/ops_file.c
@@ -378,9 +378,9 @@ do_read_buf(struct file *file, char *buf, size_t size, loff_t *offset,
ssize_t count = 0;
int error;
- gfs_holder_init(ip->i_gl, LM_ST_SHARED, 0, &ghs[num_gh]);
+ gfs_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &ghs[num_gh]);
- error = gfs_glock_nq_m(num_gh + 1, ghs);
+ error = gfs_glock_nq_m_atime(num_gh + 1, ghs);
if (error)
goto out;
@@ -1154,8 +1154,8 @@ readdir_reg(struct file *file, void *dirent, filldir_t filldir)
fdr.fdr_filldir = filldir;
fdr.fdr_opaque = dirent;
- gfs_holder_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh);
- error = gfs_glock_nq(&d_gh);
+ gfs_holder_init(dip->i_gl, LM_ST_SHARED, GL_ATIME, &d_gh);
+ error = gfs_glock_nq_atime(&d_gh);
if (error) {
gfs_holder_uninit(&d_gh);
return error;
@@ -1263,8 +1263,8 @@ readdir_bad(struct file *file, void *dirent, filldir_t filldir)
entries * sizeof(struct filldir_bad_entry);
fdb->fdb_name_size = entries * GFS_FAST_NAME_SIZE;
- gfs_holder_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh);
- error = gfs_glock_nq(&d_gh);
+ gfs_holder_init(dip->i_gl, LM_ST_SHARED, GL_ATIME, &d_gh);
+ error = gfs_glock_nq_atime(&d_gh);
if (error) {
gfs_holder_uninit(&d_gh);
goto out;
@@ -1412,8 +1412,8 @@ gfs_mmap(struct file *file, struct vm_area_struct *vma)
atomic_inc(&ip->i_sbd->sd_ops_file);
- gfs_holder_init(ip->i_gl, LM_ST_SHARED, 0, &i_gh);
- error = gfs_glock_nq(&i_gh);
+ gfs_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &i_gh);
+ error = gfs_glock_nq_atime(&i_gh);
if (error) {
gfs_holder_uninit(&i_gh);
return error;
@@ -1631,9 +1631,9 @@ gfs_sendfile(struct file *in_file, loff_t *offset, size_t count, read_actor_t ac
atomic_inc(&ip->i_sbd->sd_ops_file);
- gfs_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
+ gfs_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh);
- retval = gfs_glock_nq(&gh);
+ retval = gfs_glock_nq_atime(&gh);
if (retval)
goto out;
diff --git a/gfs-kernel/src/gfs/ops_fstype.c b/gfs-kernel/src/gfs/ops_fstype.c
index 8b5f9d1..e01ea32 100644
--- a/gfs-kernel/src/gfs/ops_fstype.c
+++ b/gfs-kernel/src/gfs/ops_fstype.c
@@ -108,6 +108,26 @@ static struct gfs_sbd *init_sbd(struct super_block *sb)
return sdp;
}
+static void init_vfs(struct super_block *sb, unsigned noatime)
+{
+ struct gfs_sbd *sdp = sb->s_fs_info;
+
+ /* Set up Linux Virtual (VFS) Super Block */
+
+ sb->s_magic = GFS_MAGIC;
+ sb->s_op = &gfs_super_ops;
+ sb->s_export_op = &gfs_export_ops;
+
+ /* Don't let the VFS update atimes. GFS handles this itself. */
+ sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
+ sb->s_maxbytes = MAX_LFS_FILESIZE;
+
+ /* If we were mounted with -o acl (to support POSIX access control
+ lists), tell VFS */
+ if (sdp->sd_args.ar_posix_acls)
+ sb->s_flags |= MS_POSIXACL;
+}
+
int init_names(struct gfs_sbd *sdp, int silent)
{
struct gfs_sb *sb = NULL;
@@ -627,18 +647,13 @@ static int fill_super(struct super_block *sb, void *data, int silent)
}
/* Copy VFS mount flags */
+
+ if (sb->s_flags & (MS_NOATIME | MS_NODIRATIME))
+ set_bit(SDF_NOATIME, &sdp->sd_flags);
if (sb->s_flags & MS_RDONLY)
set_bit(SDF_ROFS, &sdp->sd_flags);
- /* Set up Linux Virtual (VFS) Super Block */
- sb->s_magic = GFS_MAGIC;
- sb->s_op = &gfs_super_ops;
- sb->s_export_op = &gfs_export_ops;
-
- /* If we were mounted with -o acl (to support POSIX access control
- * lists), tell VFS */
- if (sdp->sd_args.ar_posix_acls)
- sb->s_flags |= MS_POSIXACL;
+ init_vfs(sb, SDF_NOATIME);
/* Turn off quota stuff if we get the noquota mount option, don't
need to grab the sd_tune lock here since its before anything
diff --git a/gfs-kernel/src/gfs/ops_super.c b/gfs-kernel/src/gfs/ops_super.c
index ec85d0b..7f92691 100644
--- a/gfs-kernel/src/gfs/ops_super.c
+++ b/gfs-kernel/src/gfs/ops_super.c
@@ -39,7 +39,6 @@
#include "super.h"
#include "sys.h"
#include "mount.h"
-#include "trans.h"
/**
* gfs_write_inode - Make sure the inode is stable on the disk
@@ -53,40 +52,13 @@ static int
gfs_write_inode(struct inode *inode, int sync)
{
struct gfs_inode *ip = get_v2ip(inode);
- struct gfs_sbd *sdp = ip->i_sbd;
- struct gfs_holder gh;
- struct buffer_head *bh;
- int64_t atime;
- struct gfs_dinode *di;
- int ret = 0;
atomic_inc(&ip->i_sbd->sd_ops_super);
- ret = gfs_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
- if (ret)
- goto do_flush;
- ret = gfs_trans_begin(sdp, 1, 0);
- if (ret)
- goto do_unlock;
- ret = gfs_get_inode_buffer(ip, &bh);
- if (ret == 0) {
- di = (struct gfs_dinode *) bh->b_data;
- atime = gfs64_to_cpu(di->di_atime);
- if (inode->i_atime.tv_sec > atime) {
- ip->i_di.di_atime = inode->i_atime.tv_sec;
- gfs_trans_add_bh(ip->i_gl, bh);
- gfs_dinode_out(&ip->i_di, bh->b_data);
- }
- brelse(bh);
- }
- gfs_trans_end(sdp);
-do_unlock:
- gfs_glock_dq_uninit(&gh);
-do_flush:
if (ip && sync)
gfs_log_flush_glock(ip->i_gl);
- return ret;
+ return 0;
}
/**
@@ -355,6 +327,11 @@ gfs_remount_fs(struct super_block *sb, int *flags, char *data)
sb->s_flags &= ~MS_POSIXACL;
}
+ if (*flags & (MS_NOATIME | MS_NODIRATIME))
+ set_bit(SDF_NOATIME, &sdp->sd_flags);
+ else
+ clear_bit(SDF_NOATIME, &sdp->sd_flags);
+
if (sdp->sd_args.ar_spectator)
*flags |= MS_RDONLY;
else {
@@ -386,6 +363,9 @@ gfs_remount_fs(struct super_block *sb, int *flags, char *data)
spin_unlock(>->gt_spin);
}
+ /* Don't let the VFS update atimes. GFS handles this itself. */
+ *flags |= MS_NOATIME | MS_NODIRATIME;
+
out:
kfree(args);
return error;
diff --git a/gfs-kernel/src/gfs/super.c b/gfs-kernel/src/gfs/super.c
index 3de0cef..9c7190b 100644
--- a/gfs-kernel/src/gfs/super.c
+++ b/gfs-kernel/src/gfs/super.c
@@ -65,6 +65,7 @@ gfs_tune_init(struct gfs_tune *gt)
gt->gt_glock_purge = 0;
gt->gt_quota_simul_sync = 64;
gt->gt_quota_warn_period = 10;
+ gt->gt_atime_quantum = 3600;
gt->gt_quota_quantum = 60;
gt->gt_quota_scale_num = 1;
gt->gt_quota_scale_den = 1;