ocfs2: core atime update functions
authorTiger Yang <tiger.yang@oracle.com>
Wed, 15 Nov 2006 07:48:42 +0000 (15:48 +0800)
committerMark Fasheh <mark.fasheh@oracle.com>
Sat, 2 Dec 2006 02:28:51 +0000 (18:28 -0800)
This patch adds the core routines for updating atime in ocfs2.

Signed-off-by: Tiger Yang <tiger.yang@oracle.com>
Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
fs/ocfs2/dlmglue.c
fs/ocfs2/dlmglue.h
fs/ocfs2/file.c
fs/ocfs2/file.h
fs/ocfs2/inode.c
fs/ocfs2/ocfs2.h
fs/ocfs2/super.c

index 7a22118..69fba16 100644 (file)
@@ -49,6 +49,7 @@
 #include "dcache.h"
 #include "dlmglue.h"
 #include "extent_map.h"
+#include "file.h"
 #include "heartbeat.h"
 #include "inode.h"
 #include "journal.h"
@@ -1723,6 +1724,44 @@ int ocfs2_meta_lock_with_page(struct inode *inode,
        return ret;
 }
 
+int ocfs2_meta_lock_atime(struct inode *inode,
+                         struct vfsmount *vfsmnt,
+                         int *level)
+{
+       int ret;
+
+       mlog_entry_void();
+       ret = ocfs2_meta_lock(inode, NULL, 0);
+       if (ret < 0) {
+               mlog_errno(ret);
+               return ret;
+       }
+
+       /*
+        * If we should update atime, we will get EX lock,
+        * otherwise we just get PR lock.
+        */
+       if (ocfs2_should_update_atime(inode, vfsmnt)) {
+               struct buffer_head *bh = NULL;
+
+               ocfs2_meta_unlock(inode, 0);
+               ret = ocfs2_meta_lock(inode, &bh, 1);
+               if (ret < 0) {
+                       mlog_errno(ret);
+                       return ret;
+               }
+               *level = 1;
+               if (ocfs2_should_update_atime(inode, vfsmnt))
+                       ocfs2_update_inode_atime(inode, bh);
+               if (bh)
+                       brelse(bh);
+       } else
+               *level = 0;
+
+       mlog_exit(ret);
+       return ret;
+}
+
 void ocfs2_meta_unlock(struct inode *inode,
                       int ex)
 {
index a1165ed..c343fca 100644 (file)
@@ -80,6 +80,9 @@ void ocfs2_data_unlock(struct inode *inode,
                       int write);
 int ocfs2_rw_lock(struct inode *inode, int write);
 void ocfs2_rw_unlock(struct inode *inode, int write);
+int ocfs2_meta_lock_atime(struct inode *inode,
+                         struct vfsmount *vfsmnt,
+                         int *level);
 int ocfs2_meta_lock_full(struct inode *inode,
                         struct buffer_head **ret_bh,
                         int ex,
index b32cdb3..e82288f 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/uio.h>
 #include <linux/sched.h>
 #include <linux/pipe_fs_i.h>
+#include <linux/mount.h>
 
 #define MLOG_MASK_PREFIX ML_INODE
 #include <cluster/masklog.h>
@@ -135,6 +136,57 @@ bail:
        return (err < 0) ? -EIO : 0;
 }
 
+int ocfs2_should_update_atime(struct inode *inode,
+                             struct vfsmount *vfsmnt)
+{
+       struct timespec now;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+
+       if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb))
+               return 0;
+
+       if ((inode->i_flags & S_NOATIME) ||
+           ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode)))
+               return 0;
+
+       if ((vfsmnt->mnt_flags & MNT_NOATIME) ||
+           ((vfsmnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode)))
+               return 0;
+
+       now = CURRENT_TIME;
+       if ((now.tv_sec - inode->i_atime.tv_sec <= osb->s_atime_quantum))
+               return 0;
+       else
+               return 1;
+}
+
+int ocfs2_update_inode_atime(struct inode *inode,
+                            struct buffer_head *bh)
+{
+       int ret;
+       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
+       handle_t *handle;
+
+       mlog_entry_void();
+
+       handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
+       if (handle == NULL) {
+               ret = -ENOMEM;
+               mlog_errno(ret);
+               goto out;
+       }
+
+       inode->i_atime = CURRENT_TIME;
+       ret = ocfs2_mark_inode_dirty(handle, inode, bh);
+       if (ret < 0)
+               mlog_errno(ret);
+
+       ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle);
+out:
+       mlog_exit(ret);
+       return ret;
+}
+
 int ocfs2_set_inode_size(handle_t *handle,
                         struct inode *inode,
                         struct buffer_head *fe_bh,
index 84f8b97..475ed8a 100644 (file)
@@ -54,4 +54,9 @@ int ocfs2_set_inode_size(handle_t *handle,
                         struct buffer_head *fe_bh,
                         u64 new_i_size);
 
+int ocfs2_should_update_atime(struct inode *inode,
+                             struct vfsmount *vfsmnt);
+int ocfs2_update_inode_atime(struct inode *inode,
+                            struct buffer_head *bh);
+
 #endif /* OCFS2_FILE_H */
index ad4d4a1..42e361f 100644 (file)
@@ -360,7 +360,6 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
                                  inode);
 
        ocfs2_set_inode_flags(inode);
-       inode->i_flags |= S_NOATIME;
 
        status = 0;
 bail:
index 553e702..0788837 100644 (file)
@@ -180,6 +180,7 @@ enum ocfs2_mount_options
 #define OCFS2_OSB_SOFT_RO      0x0001
 #define OCFS2_OSB_HARD_RO      0x0002
 #define OCFS2_OSB_ERROR_FS     0x0004
+#define OCFS2_DEFAULT_ATIME_QUANTUM    60
 
 struct ocfs2_journal;
 struct ocfs2_super
@@ -218,6 +219,7 @@ struct ocfs2_super
        unsigned long osb_flags;
 
        unsigned long s_mount_opt;
+       unsigned int s_atime_quantum;
 
        u16 max_slots;
        s16 node_num;
index d9b1eb6..b099257 100644 (file)
@@ -139,6 +139,7 @@ enum {
        Opt_hb_local,
        Opt_data_ordered,
        Opt_data_writeback,
+       Opt_atime_quantum,
        Opt_err,
 };
 
@@ -152,6 +153,7 @@ static match_table_t tokens = {
        {Opt_hb_local, OCFS2_HB_LOCAL},
        {Opt_data_ordered, "data=ordered"},
        {Opt_data_writeback, "data=writeback"},
+       {Opt_atime_quantum, "atime_quantum=%u"},
        {Opt_err, NULL}
 };
 
@@ -705,6 +707,7 @@ static int ocfs2_parse_options(struct super_block *sb,
        while ((p = strsep(&options, ",")) != NULL) {
                int token, option;
                substring_t args[MAX_OPT_ARGS];
+               struct ocfs2_super * osb = OCFS2_SB(sb);
 
                if (!*p)
                        continue;
@@ -745,6 +748,16 @@ static int ocfs2_parse_options(struct super_block *sb,
                case Opt_data_writeback:
                        *mount_opt |= OCFS2_MOUNT_DATA_WRITEBACK;
                        break;
+               case Opt_atime_quantum:
+                       if (match_int(&args[0], &option)) {
+                               status = 0;
+                               goto bail;
+                       }
+                       if (option >= 0)
+                               osb->s_atime_quantum = option;
+                       else
+                               osb->s_atime_quantum = OCFS2_DEFAULT_ATIME_QUANTUM;
+                       break;
                default:
                        mlog(ML_ERROR,
                             "Unrecognized mount option \"%s\" "
@@ -1265,6 +1278,8 @@ static int ocfs2_initialize_super(struct super_block *sb,
        init_waitqueue_head(&osb->checkpoint_event);
        atomic_set(&osb->needs_checkpoint, 0);
 
+       osb->s_atime_quantum = OCFS2_DEFAULT_ATIME_QUANTUM;
+
        osb->node_num = O2NM_INVALID_NODE_NUM;
        osb->slot_num = OCFS2_INVALID_SLOT;