Skip to content

Commit 719ee34

Browse files
committed
GFS2: high time to take some time over atime
Until now, we've used the same scheme as GFS1 for atime. This has failed since atime is a per vfsmnt flag, not a per fs flag and as such the "noatime" flag was not getting passed down to the filesystems. This patch removes all the "special casing" around atime updates and we simply use the VFS's atime code. The net result is that GFS2 will now support all the same atime related mount options of any other filesystem on a per-vfsmnt basis. We do lose the "lazy atime" updates, but we gain "relatime". We could add lazy atime to the VFS at a later date, if there is a requirement for that variant still - I suspect relatime will be enough. Also we lose about 100 lines of code after this patch has been applied, and I have a suspicion that it will speed things up a bit, even when atime is "on". So it seems like a nice clean up as well. From a user perspective, everything stays the same except the loss of the per-fs atime quantum tweekable (ought to be per-vfsmnt at the very least, and to be honest I don't think anybody ever used it) and that a number of options which were ignored before now work correctly. Please let me know if you've got any comments. I'm pushing this out early so that you can all see what my plans are. Signed-off-by: Steven Whitehouse <[email protected]>
1 parent 37ec89e commit 719ee34

File tree

10 files changed

+65
-167
lines changed

10 files changed

+65
-167
lines changed

fs/gfs2/glock.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1580,8 +1580,6 @@ static const char *hflags2str(char *buf, unsigned flags, unsigned long iflags)
15801580
*p++ = 'a';
15811581
if (flags & GL_EXACT)
15821582
*p++ = 'E';
1583-
if (flags & GL_ATIME)
1584-
*p++ = 'a';
15851583
if (flags & GL_NOCACHE)
15861584
*p++ = 'c';
15871585
if (test_bit(HIF_HOLDER, &iflags))

fs/gfs2/glock.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
#define GL_ASYNC 0x00000040
2525
#define GL_EXACT 0x00000080
2626
#define GL_SKIP 0x00000100
27-
#define GL_ATIME 0x00000200
2827
#define GL_NOCACHE 0x00000400
2928

3029
#define GLR_TRYFAILED 13

fs/gfs2/incore.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,6 @@ struct gfs2_tune {
420420
unsigned int gt_quota_scale_den; /* Denominator */
421421
unsigned int gt_quota_cache_secs;
422422
unsigned int gt_quota_quantum; /* Secs between syncs to quota file */
423-
unsigned int gt_atime_quantum; /* Min secs between atime updates */
424423
unsigned int gt_new_files_jdata;
425424
unsigned int gt_max_readahead; /* Max bytes to read-ahead from disk */
426425
unsigned int gt_stall_secs; /* Detects trouble! */
@@ -433,7 +432,6 @@ enum {
433432
SDF_JOURNAL_CHECKED = 0,
434433
SDF_JOURNAL_LIVE = 1,
435434
SDF_SHUTDOWN = 2,
436-
SDF_NOATIME = 3,
437435
};
438436

439437
#define GFS2_FSNAME_LEN 256

fs/gfs2/inode.c

Lines changed: 8 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <linux/crc32.h>
1919
#include <linux/lm_interface.h>
2020
#include <linux/security.h>
21+
#include <linux/time.h>
2122

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

254256
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)
275277
di->di_size = be64_to_cpu(str->di_size);
276278
i_size_write(&ip->i_inode, di->di_size);
277279
gfs2_set_inode_blocks(&ip->i_inode, be64_to_cpu(str->di_blocks));
278-
ip->i_inode.i_atime.tv_sec = be64_to_cpu(str->di_atime);
279-
ip->i_inode.i_atime.tv_nsec = be32_to_cpu(str->di_atime_nsec);
280+
atime.tv_sec = be64_to_cpu(str->di_atime);
281+
atime.tv_nsec = be32_to_cpu(str->di_atime_nsec);
282+
if (timespec_compare(&ip->i_inode.i_atime, &atime) < 0)
283+
ip->i_inode.i_atime = atime;
280284
ip->i_inode.i_mtime.tv_sec = be64_to_cpu(str->di_mtime);
281285
ip->i_inode.i_mtime.tv_nsec = be32_to_cpu(str->di_mtime_nsec);
282286
ip->i_inode.i_ctime.tv_sec = be64_to_cpu(str->di_ctime);
@@ -1157,8 +1161,8 @@ int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len)
11571161
unsigned int x;
11581162
int error;
11591163

1160-
gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &i_gh);
1161-
error = gfs2_glock_nq_atime(&i_gh);
1164+
gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &i_gh);
1165+
error = gfs2_glock_nq(&i_gh);
11621166
if (error) {
11631167
gfs2_holder_uninit(&i_gh);
11641168
return error;
@@ -1193,101 +1197,6 @@ int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len)
11931197
return error;
11941198
}
11951199

1196-
/**
1197-
* gfs2_glock_nq_atime - Acquire a hold on an inode's glock, and
1198-
* conditionally update the inode's atime
1199-
* @gh: the holder to acquire
1200-
*
1201-
* Tests atime (access time) for gfs2_read, gfs2_readdir and gfs2_mmap
1202-
* Update if the difference between the current time and the inode's current
1203-
* atime is greater than an interval specified at mount.
1204-
*
1205-
* Returns: errno
1206-
*/
1207-
1208-
int gfs2_glock_nq_atime(struct gfs2_holder *gh)
1209-
{
1210-
struct gfs2_glock *gl = gh->gh_gl;
1211-
struct gfs2_sbd *sdp = gl->gl_sbd;
1212-
struct gfs2_inode *ip = gl->gl_object;
1213-
s64 quantum = gfs2_tune_get(sdp, gt_atime_quantum);
1214-
unsigned int state;
1215-
int flags;
1216-
int error;
1217-
struct timespec tv = CURRENT_TIME;
1218-
1219-
if (gfs2_assert_warn(sdp, gh->gh_flags & GL_ATIME) ||
1220-
gfs2_assert_warn(sdp, !(gh->gh_flags & GL_ASYNC)) ||
1221-
gfs2_assert_warn(sdp, gl->gl_ops == &gfs2_inode_glops))
1222-
return -EINVAL;
1223-
1224-
state = gh->gh_state;
1225-
flags = gh->gh_flags;
1226-
1227-
error = gfs2_glock_nq(gh);
1228-
if (error)
1229-
return error;
1230-
1231-
if (test_bit(SDF_NOATIME, &sdp->sd_flags) ||
1232-
(sdp->sd_vfs->s_flags & MS_RDONLY))
1233-
return 0;
1234-
1235-
if (tv.tv_sec - ip->i_inode.i_atime.tv_sec >= quantum) {
1236-
gfs2_glock_dq(gh);
1237-
gfs2_holder_reinit(LM_ST_EXCLUSIVE, gh->gh_flags & ~LM_FLAG_ANY,
1238-
gh);
1239-
error = gfs2_glock_nq(gh);
1240-
if (error)
1241-
return error;
1242-
1243-
/* Verify that atime hasn't been updated while we were
1244-
trying to get exclusive lock. */
1245-
1246-
tv = CURRENT_TIME;
1247-
if (tv.tv_sec - ip->i_inode.i_atime.tv_sec >= quantum) {
1248-
struct buffer_head *dibh;
1249-
struct gfs2_dinode *di;
1250-
1251-
error = gfs2_trans_begin(sdp, RES_DINODE, 0);
1252-
if (error == -EROFS)
1253-
return 0;
1254-
if (error)
1255-
goto fail;
1256-
1257-
error = gfs2_meta_inode_buffer(ip, &dibh);
1258-
if (error)
1259-
goto fail_end_trans;
1260-
1261-
ip->i_inode.i_atime = tv;
1262-
1263-
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
1264-
di = (struct gfs2_dinode *)dibh->b_data;
1265-
di->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec);
1266-
di->di_atime_nsec = cpu_to_be32(ip->i_inode.i_atime.tv_nsec);
1267-
brelse(dibh);
1268-
1269-
gfs2_trans_end(sdp);
1270-
}
1271-
1272-
/* If someone else has asked for the glock,
1273-
unlock and let them have it. Then reacquire
1274-
in the original state. */
1275-
if (gfs2_glock_is_blocking(gl)) {
1276-
gfs2_glock_dq(gh);
1277-
gfs2_holder_reinit(state, flags, gh);
1278-
return gfs2_glock_nq(gh);
1279-
}
1280-
}
1281-
1282-
return 0;
1283-
1284-
fail_end_trans:
1285-
gfs2_trans_end(sdp);
1286-
fail:
1287-
gfs2_glock_dq(gh);
1288-
return error;
1289-
}
1290-
12911200
static int
12921201
__gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr)
12931202
{

fs/gfs2/inode.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
9292
const struct gfs2_inode *ip);
9393
int gfs2_permission(struct inode *inode, int mask);
9494
int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len);
95-
int gfs2_glock_nq_atime(struct gfs2_holder *gh);
9695
int gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr);
9796
struct inode *gfs2_lookup_simple(struct inode *dip, const char *name);
9897
void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf);

fs/gfs2/ops_address.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -512,8 +512,8 @@ static int gfs2_readpage(struct file *file, struct page *page)
512512
int error;
513513

514514
unlock_page(page);
515-
gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh);
516-
error = gfs2_glock_nq_atime(&gh);
515+
gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
516+
error = gfs2_glock_nq(&gh);
517517
if (unlikely(error))
518518
goto out;
519519
error = AOP_TRUNCATED_PAGE;
@@ -594,8 +594,8 @@ static int gfs2_readpages(struct file *file, struct address_space *mapping,
594594
struct gfs2_holder gh;
595595
int ret;
596596

597-
gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh);
598-
ret = gfs2_glock_nq_atime(&gh);
597+
gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
598+
ret = gfs2_glock_nq(&gh);
599599
if (unlikely(ret))
600600
goto out_uninit;
601601
if (!gfs2_is_stuffed(ip))
@@ -636,8 +636,8 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,
636636
unsigned to = from + len;
637637
struct page *page;
638638

639-
gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_ATIME, &ip->i_gh);
640-
error = gfs2_glock_nq_atime(&ip->i_gh);
639+
gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &ip->i_gh);
640+
error = gfs2_glock_nq(&ip->i_gh);
641641
if (unlikely(error))
642642
goto out_uninit;
643643

@@ -1000,8 +1000,8 @@ static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb,
10001000
* unfortunately have the option of only flushing a range like
10011001
* the VFS does.
10021002
*/
1003-
gfs2_holder_init(ip->i_gl, LM_ST_DEFERRED, GL_ATIME, &gh);
1004-
rv = gfs2_glock_nq_atime(&gh);
1003+
gfs2_holder_init(ip->i_gl, LM_ST_DEFERRED, 0, &gh);
1004+
rv = gfs2_glock_nq(&gh);
10051005
if (rv)
10061006
return rv;
10071007
rv = gfs2_ok_for_dio(ip, rw, offset);

fs/gfs2/ops_file.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,8 @@ static int gfs2_readdir(struct file *file, void *dirent, filldir_t filldir)
8989
u64 offset = file->f_pos;
9090
int error;
9191

92-
gfs2_holder_init(dip->i_gl, LM_ST_SHARED, GL_ATIME, &d_gh);
93-
error = gfs2_glock_nq_atime(&d_gh);
92+
gfs2_holder_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh);
93+
error = gfs2_glock_nq(&d_gh);
9494
if (error) {
9595
gfs2_holder_uninit(&d_gh);
9696
return error;
@@ -153,8 +153,8 @@ static int gfs2_get_flags(struct file *filp, u32 __user *ptr)
153153
int error;
154154
u32 fsflags;
155155

156-
gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh);
157-
error = gfs2_glock_nq_atime(&gh);
156+
gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
157+
error = gfs2_glock_nq(&gh);
158158
if (error)
159159
return error;
160160

@@ -351,8 +351,8 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct page *page)
351351
struct gfs2_alloc *al;
352352
int ret;
353353

354-
gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_ATIME, &gh);
355-
ret = gfs2_glock_nq_atime(&gh);
354+
gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
355+
ret = gfs2_glock_nq(&gh);
356356
if (ret)
357357
goto out;
358358

@@ -434,8 +434,8 @@ static int gfs2_mmap(struct file *file, struct vm_area_struct *vma)
434434
struct gfs2_holder i_gh;
435435
int error;
436436

437-
gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &i_gh);
438-
error = gfs2_glock_nq_atime(&i_gh);
437+
gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &i_gh);
438+
error = gfs2_glock_nq(&i_gh);
439439
if (error) {
440440
gfs2_holder_uninit(&i_gh);
441441
return error;

fs/gfs2/ops_fstype.c

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ static void gfs2_tune_init(struct gfs2_tune *gt)
7070
gt->gt_quota_scale_den = 1;
7171
gt->gt_quota_cache_secs = 300;
7272
gt->gt_quota_quantum = 60;
73-
gt->gt_atime_quantum = 3600;
7473
gt->gt_new_files_jdata = 0;
7574
gt->gt_max_readahead = 1 << 18;
7675
gt->gt_stall_secs = 600;
@@ -135,22 +134,6 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
135134
return sdp;
136135
}
137136

138-
static void init_vfs(struct super_block *sb, unsigned noatime)
139-
{
140-
struct gfs2_sbd *sdp = sb->s_fs_info;
141-
142-
sb->s_magic = GFS2_MAGIC;
143-
sb->s_op = &gfs2_super_ops;
144-
sb->s_export_op = &gfs2_export_ops;
145-
sb->s_time_gran = 1;
146-
sb->s_maxbytes = MAX_LFS_FILESIZE;
147-
148-
if (sb->s_flags & (MS_NOATIME | MS_NODIRATIME))
149-
set_bit(noatime, &sdp->sd_flags);
150-
151-
/* Don't let the VFS update atimes. GFS2 handles this itself. */
152-
sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
153-
}
154137

155138
/**
156139
* gfs2_check_sb - Check superblock
@@ -1100,7 +1083,11 @@ static int fill_super(struct super_block *sb, void *data, int silent)
11001083
goto fail;
11011084
}
11021085

1103-
init_vfs(sb, SDF_NOATIME);
1086+
sb->s_magic = GFS2_MAGIC;
1087+
sb->s_op = &gfs2_super_ops;
1088+
sb->s_export_op = &gfs2_export_ops;
1089+
sb->s_time_gran = 1;
1090+
sb->s_maxbytes = MAX_LFS_FILESIZE;
11041091

11051092
/* Set up the buffer cache and fill in some fake block size values
11061093
to allow us to read-in the on-disk superblock. */

fs/gfs2/ops_super.c

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <linux/gfs2_ondisk.h>
2121
#include <linux/crc32.h>
2222
#include <linux/lm_interface.h>
23+
#include <linux/time.h>
2324

2425
#include "gfs2.h"
2526
#include "incore.h"
@@ -38,6 +39,7 @@
3839
#include "dir.h"
3940
#include "eattr.h"
4041
#include "bmap.h"
42+
#include "meta_io.h"
4143

4244
/**
4345
* gfs2_write_inode - Make sure the inode is stable on the disk
@@ -50,16 +52,41 @@
5052
static int gfs2_write_inode(struct inode *inode, int sync)
5153
{
5254
struct gfs2_inode *ip = GFS2_I(inode);
53-
54-
/* Check this is a "normal" inode */
55-
if (test_bit(GIF_USER, &ip->i_flags)) {
56-
if (current->flags & PF_MEMALLOC)
57-
return 0;
58-
if (sync)
59-
gfs2_log_flush(GFS2_SB(inode), ip->i_gl);
55+
struct gfs2_sbd *sdp = GFS2_SB(inode);
56+
struct gfs2_holder gh;
57+
struct buffer_head *bh;
58+
struct timespec atime;
59+
struct gfs2_dinode *di;
60+
int ret = 0;
61+
62+
/* Check this is a "normal" inode, etc */
63+
if (!test_bit(GIF_USER, &ip->i_flags) ||
64+
(current->flags & PF_MEMALLOC))
65+
return 0;
66+
ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
67+
if (ret)
68+
goto do_flush;
69+
ret = gfs2_trans_begin(sdp, RES_DINODE, 0);
70+
if (ret)
71+
goto do_unlock;
72+
ret = gfs2_meta_inode_buffer(ip, &bh);
73+
if (ret == 0) {
74+
di = (struct gfs2_dinode *)bh->b_data;
75+
atime.tv_sec = be64_to_cpu(di->di_atime);
76+
atime.tv_nsec = be32_to_cpu(di->di_atime_nsec);
77+
if (timespec_compare(&inode->i_atime, &atime) > 0) {
78+
gfs2_trans_add_bh(ip->i_gl, bh, 1);
79+
gfs2_dinode_out(ip, bh->b_data);
80+
}
81+
brelse(bh);
6082
}
61-
62-
return 0;
83+
gfs2_trans_end(sdp);
84+
do_unlock:
85+
gfs2_glock_dq_uninit(&gh);
86+
do_flush:
87+
if (sync != 0)
88+
gfs2_log_flush(GFS2_SB(inode), ip->i_gl);
89+
return ret;
6390
}
6491

6592
/**
@@ -297,14 +324,6 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data)
297324
}
298325
}
299326

300-
if (*flags & (MS_NOATIME | MS_NODIRATIME))
301-
set_bit(SDF_NOATIME, &sdp->sd_flags);
302-
else
303-
clear_bit(SDF_NOATIME, &sdp->sd_flags);
304-
305-
/* Don't let the VFS update atimes. GFS2 handles this itself. */
306-
*flags |= MS_NOATIME | MS_NODIRATIME;
307-
308327
return error;
309328
}
310329

0 commit comments

Comments
 (0)