無料Wikiサービス | デモページ
検索

アクセス数
最近のコメント
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
はじめ - ノース
はじめ - ノース
はじめ - 楽打連動ユーザー
はじめ - 楽打連動ユーザー
Adsense
広告情報が設定されていません。

MNT_RELATIME


MNT_RELATIMEはinode->i_atime更新下の条件で、MNT_NOATIMEならMNT_RELATIMEに係る影響ないのに、mntフラグのMNT_RELATIME設定はMNT_NOATIMに係る設定となっていて、MNT_RELATIME自体の設定は実装されていない。

    • mntフラグ設定
mnt_flags = MNT_RELATIME;
if (flags & MS_NOATIME) {
     mnt_flags |= MS_NOATIME;
}
でなく
mnt_flags = 0;
if (flags & MS_NOATIME) {
    mnt_flags |= MS_NOATIME;
 }
 else {
    mnt_flags |= MNT_RELATIME;
}
    • atime更新
if (!mnt->mnt_flags & MNT_NOATIME) {
   if (mnt->mnt_flags & MNT_RELATIME)) {
      if (inode->i_mtime        > inode->i_atime ||
          inode->i_ctime        > inode->i_atime ||
          time - inode->i_atime > 24*60*60)        {
              inode->i_atime = time;
             }
        } 
    }
   else {
       inode->i_atime = time;
    } 
}
これは、mntコマンド属性表示のMNT_RELATIMEならMNT_NOATIMEでない旨とする意味合いの属性とする運用上故かと、従ってMNT_NOATIMEでMNT_RELATIMEと成り得ない。MS_STRICTATIMEは、MNT_RELATIME/MNT_NOATIMEがクリアされ、i_atimeは無条件に更新される。ただしMS_NODIRATIMEならディレクトリは更新されない。mntコマンドの属性表示でMNT_RELATIME/MNT_NOATIMEが表示されていないなら、MS_STRICTATIME。

サンプル

[root@localhost /]# mount /dev/sda5 /mnt5
[root@localhost /]# mount /dev/sda6 /mnt6 -o noatime
[root@localhost /]# mount /dev/sda7 /mnt7 -o strictatime

[root@localhost /]# mount
 :
/dev/sda5 on /mnt5 type ext3 (rw,relatime,data=ordered)
/dev/sda6 on /mnt6 type ext3 (rw,noatime,data=ordered)
/dev/sda7 on /mnt7 type ext3 (rw,data=ordered)

カーネル

mnt_flagsはブロックデバイスに係るフラグ、flagsはファイルシステムに係るフラグで、MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE | MS_BORN | MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT | MS_STRICTATIME以外のフラグはファイルシステムに依存し、mnt bind/mntフラグの変更は、flagsに係る属性のみである。

ファイル/ディレクトリ参照時に、atim更新のfile_accessed()がコールされ、MNT_NOATIMEでないなら、touch_atime()がコールされMNT_RELATIMEに係る条件でatimeが更新される。
#define MS_MGC_VAL 0xC0ED0000
#define MS_MGC_MSK 0xffff0000

#define MS_NOATIME      1024    /* Do not update access times. */
#define MS_NODIRATIME   2048    /* Do not update directory access times */
#define MS_RELATIME     (1<<21) /* Update atime relative to mtime/ctime. */

long do_mount(const char *dev_name, const char *dir_name,
               const char *type_page, unsigned long flags, void *data_page)
{
       struct path path;
       int retval = 0;
       int mnt_flags = 0;

       if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
               flags &= ~MS_MGC_MSK;

       if (!dir_name || !*dir_name || !memchr(dir_name, 0, PAGE_SIZE))
               return -EINVAL;

       if (data_page)
               ((char *)data_page)[PAGE_SIZE - 1] = 0;

       retval = kern_path(dir_name, LOOKUP_FOLLOW, &path);
       if (retval)
               return retval;

       retval = security_sb_mount(dev_name, &path,
                                  type_page, flags, data_page);
       if (retval)
               goto dput_out;

       if (!(flags & MS_NOATIME))
               mnt_flags |= MNT_RELATIME;

       if (flags & MS_NOSUID)
               mnt_flags |= MNT_NOSUID;
       if (flags & MS_NODEV)
               mnt_flags |= MNT_NODEV;
       if (flags & MS_NOEXEC)
               mnt_flags |= MNT_NOEXEC;
       if (flags & MS_NOATIME)
               mnt_flags |= MNT_NOATIME;
       if (flags & MS_NODIRATIME)
               mnt_flags |= MNT_NODIRATIME;
       if (flags & MS_STRICTATIME)
               mnt_flags &= ~(MNT_RELATIME | MNT_NOATIME);
       if (flags & MS_RDONLY)
               mnt_flags |= MNT_READONLY;

       flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE | MS_BORN |
                  MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT |
                  MS_STRICTATIME);

       if (flags & MS_REMOUNT)
               retval = do_remount(&path, flags & ~MS_REMOUNT, mnt_flags,
                                   data_page);
       else if (flags & MS_BIND)
               retval = do_loopback(&path, dev_name, flags & MS_REC);
       else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
               retval = do_change_type(&path, flags);
       else if (flags & MS_MOVE)
               retval = do_move_mount(&path, dev_name);
       else
               retval = do_new_mount(&path, type_page, flags, mnt_flags,
                                     dev_name, data_page);
dput_out:
       path_put(&path);
       return retval;
}
ファイル/ディレクトリ参照時のdo_generic_file_read()/vfs_readdir()からfile_accessed()がコールされ、かかるfileのinode->atimeが更新される。
static inline void file_accessed(struct file *file)
{
       if (!(file->f_flags & O_NOATIME))
               touch_atime(&file->f_path);
}
void touch_atime(struct path *path)
{
       struct vfsmount *mnt = path->mnt;
       struct inode *inode = path->dentry->d_inode;
       struct timespec now;

       if (inode->i_flags & S_NOATIME)
               return;
       if (IS_NOATIME(inode))
               return;
       if ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode))
               return;

       if (mnt->mnt_flags & MNT_NOATIME)
               return;
       if ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode))
               return;

       now = current_fs_time(inode->i_sb);

       if (!relatime_need_update(mnt, inode, now))
               return;

       if (timespec_equal(&inode->i_atime, &now))
               return;

       if (!sb_start_write_trylock(inode->i_sb))
               return;

       if (__mnt_want_write(mnt))
               goto skip_update;

       update_time(inode, &now, S_ATIME);
       __mnt_drop_write(mnt);
skip_update:
       sb_end_write(inode->i_sb);
}

static int relatime_need_update(struct vfsmount *mnt, struct inode *inode,
                            struct timespec now)
{
       if (!(mnt->mnt_flags & MNT_RELATIME))
               return 1;

       if (timespec_compare(&inode->i_mtime, &inode->i_atime) >= 0)
               return 1;

       if (timespec_compare(&inode->i_ctime, &inode->i_atime) >= 0)
               return 1;


       if ((long)(now.tv_sec - inode->i_atime.tv_sec) >= 24*60*60)
               return 1;

       return 0;
}

追記

MNT_NODIRATIMEは、係る配下のinodeがNOATIMEとなるのでなく、ディレクトリ配下のファイル属性のブロックデータ参照時の係る条件で、ディレクトリ配下の全てのinodeをNOATIMEとするなら、ディレクトリをMNT_NOATIMEでbind_mntする事で運営できる。

最終更新 2017/08/20 20:21:28 - north
(2017/08/20 18:50:25 作成)