ctime: Provide noatime option

Most of the applications are {c|m}time dependant
and very few are atime dependant. So provide noatime
option to not update atime when ctime feature is
enabled.

Also this option has to be enabled with ctime
feature to avoid unnecessary self heal. Since
AFR/EC reads data from single subvolume, atime
is only updated in one subvolume triggering self
heal.

updates: bz#1593538
Change-Id: I085fb33c882296545345f5df194cde7b6cbc337e
Signed-off-by: Kotresh HR <khiremat@redhat.com>
This commit is contained in:
Kotresh HR 2018-09-03 09:07:58 -04:00 committed by Amar Tumballi
parent c006434c4f
commit 89636be4c7
12 changed files with 191 additions and 9 deletions

View File

@ -90,6 +90,7 @@ enum _msgid_comp {
GLFS_MSGID_COMP(QUIESCE, 1),
GLFS_MSGID_COMP(TA, 1),
GLFS_MSGID_COMP(TEMPLATE, 1),
GLFS_MSGID_COMP(UTIME, 1),
/* --- new segments for messages goes above this line --- */

View File

@ -0,0 +1,51 @@
#!/bin/bash
. $(dirname $0)/../../include.rc
. $(dirname $0)/../../volume.rc
. $(dirname $0)/../../afr.rc
cleanup;
function atime_compare {
local atime=$1
local file_name=$2
local atime1=$(stat -c "%X" $file_name)
if [ $atime == $atime1 ]
then
echo "0"
else
echo "1"
fi
}
TEST glusterd
TEST pidof glusterd
TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{0,1,2}
TEST $CLI volume set $V0 performance.stat-prefetch off
TEST $CLI volume set $V0 performance.read-ahead off
TEST $CLI volume set $V0 performance.quick-read off
TEST $CLI volume set $V0 performance.read-after-open off
TEST $CLI volume set $V0 performance.open-behind off
TEST $CLI volume set $V0 performance.write-behind off
TEST $CLI volume set $V0 performance.io-cache off
TEST $CLI volume set $V0 utime on
TEST $CLI volume set $V0 ctime on
TEST $CLI volume start $V0
TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 --entry-timeout=0 $M0;
cd $M0
TEST "echo hello_world > FILE"
atime1=$(stat -c "%X" FILE)
TEST "cat FILE > /dev/null"
EXPECT "0" atime_compare $atime1 FILE
sleep 1
TEST $CLI volume set $V0 noatime off
TEST "cat FILE > /dev/null"
EXPECT "1" atime_compare $atime1 FILE
cd -
cleanup

View File

@ -15,6 +15,8 @@ utime_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la
noinst_HEADERS_utime = $(UTIME_SRC)/utime-helpers.h
noinst_HEADERS_utime += $(UTIME_SRC)/utime.h
noinst_HEADERS_utime += $(UTIME_SRC)/utime-messages.h
noinst_HEADERS_utime += $(UTIME_SRC)/utime-mem-types.h
noinst_HEADERS = $(top_srcdir)/xlators/lib/src/libxlator.h
noinst_HEADERS += $(noinst_HEADERS_utime)

View File

@ -16,7 +16,7 @@ gf_utime_@NAME@ (call_frame_t *frame, xlator_t *this,
{
gl_timespec_get(&frame->root->ctime);
(void) utime_update_attribute_flags(frame, GF_FOP_@UPNAME@);
(void) utime_update_attribute_flags(frame, this, GF_FOP_@UPNAME@);
STACK_WIND (frame, gf_utime_@NAME@_cbk, FIRST_CHILD(this),
FIRST_CHILD(this)->fops->@NAME@, @SHORT_ARGS@);
return 0;
@ -41,7 +41,7 @@ gf_utime_@NAME@ (call_frame_t *frame, xlator_t *this,
{
gl_timespec_get(&frame->root->ctime);
(void) utime_update_attribute_flags(frame, GF_FOP_READ);
(void) utime_update_attribute_flags(frame, this, GF_FOP_READ);
STACK_WIND (frame, gf_utime_@NAME@_cbk, FIRST_CHILD(this),
FIRST_CHILD(this)->fops->@NAME@, @SHORT_ARGS@);
return 0;
@ -55,7 +55,7 @@ gf_utime_@NAME@ (call_frame_t *frame, xlator_t *this,
{
gl_timespec_get(&frame->root->ctime);
(void) utime_update_attribute_flags(frame, GF_FOP_WRITE);
(void) utime_update_attribute_flags(frame, this, GF_FOP_WRITE);
STACK_WIND (frame, gf_utime_@NAME@_cbk, FIRST_CHILD(this),
FIRST_CHILD(this)->fops->@NAME@, @SHORT_ARGS@);
return 0;

View File

@ -9,6 +9,7 @@
*/
#include "utime-helpers.h"
#include "utime.h"
void
gl_timespec_get(struct timespec *ts)
@ -21,12 +22,17 @@ gl_timespec_get(struct timespec *ts)
}
void
utime_update_attribute_flags(call_frame_t *frame, glusterfs_fop_t fop)
utime_update_attribute_flags(call_frame_t *frame, xlator_t *this,
glusterfs_fop_t fop)
{
if (!frame) {
utime_priv_t *utime_priv = NULL;
if (!frame || !this) {
goto out;
}
utime_priv = this->private;
switch (fop) {
case GF_FOP_SETXATTR:
case GF_FOP_FSETXATTR:
@ -42,9 +48,10 @@ utime_update_attribute_flags(call_frame_t *frame, glusterfs_fop_t fop)
case GF_FOP_OPENDIR:
case GF_FOP_OPEN:
case GF_FOP_READ:
frame->root->flags |= MDATA_ATIME;
if (!utime_priv->noatime) {
frame->root->flags |= MDATA_ATIME;
}
break;
case GF_FOP_MKNOD:
case GF_FOP_MKDIR:
case GF_FOP_SYMLINK:

View File

@ -13,12 +13,14 @@
#include "glusterfs-fops.h"
#include "stack.h"
#include "xlator.h"
#include "timespec.h"
#include <time.h>
void
gl_timespec_get(struct timespec *ts);
void
utime_update_attribute_flags(call_frame_t *frame, glusterfs_fop_t fop);
utime_update_attribute_flags(call_frame_t *frame, xlator_t *this,
glusterfs_fop_t fop);
#endif /* _UTIME_HELPERS_H */

View File

@ -0,0 +1,21 @@
/*
Copyright (c) 2018 Red Hat, Inc. <http://www.redhat.com>
This file is part of GlusterFS.
This file is licensed to you under your choice of the GNU Lesser
General Public License, version 3 or any later version (LGPLv3 or
later), or the GNU General Public License, version 2 (GPLv2), in all
cases as published by the Free Software Foundation.
*/
#ifndef __UTIME_MEM_TYPES_H__
#define __UTIME_MEM_TYPES_H__
#include "mem-types.h"
enum gf_utime_mem_types_ {
utime_mt_utime_t = gf_common_mt_end + 1,
utime_mt_end
};
#endif /* __UTIME_MEM_TYPES_H__ */

View File

@ -0,0 +1,28 @@
/*
Copyright (c) 2018 Red Hat, Inc. <http://www.redhat.com>
This file is part of GlusterFS.
This file is licensed to you under your choice of the GNU Lesser
General Public License, version 3 or any later version (LGPLv3 or
later), or the GNU General Public License, version 2 (GPLv2), in all
cases as published by the Free Software Foundation.
*/
#ifndef __UTIME_MESSAGES_H__
#define __UTIME_MESSAGES_H__
#include "glfs-message-id.h"
/* To add new message IDs, append new identifiers at the end of the list.
*
* Never remove a message ID. If it's not used anymore, you can rename it or
* leave it as it is, but not delete it. This is to prevent reutilization of
* IDs by other messages.
*
* The component name must match one of the entries defined in
* glfs-message-id.h.
*/
GLFS_MSGID(UTIME, UTIME_MSG_NO_MEMORY);
#endif /* __UTIME_MESSAGES_H__ */

View File

@ -9,6 +9,8 @@
*/
#include "utime.h"
#include "utime-messages.h"
#include "utime-mem-types.h"
int32_t
gf_utime_invalidate(xlator_t *this, inode_t *inode)
@ -119,22 +121,58 @@ gf_utime_priv(xlator_t *this)
return 0;
}
int32_t
mem_acct_init(xlator_t *this)
{
if (xlator_mem_acct_init(this, utime_mt_end + 1) != 0) {
gf_msg(this->name, GF_LOG_ERROR, ENOMEM, UTIME_MSG_NO_MEMORY,
"Memory accounting initialization failed.");
return -1;
}
return 0;
}
int32_t
init(xlator_t *this)
{
utime_priv_t *utime = NULL;
utime = GF_MALLOC(sizeof(*utime), utime_mt_utime_t);
if (utime == NULL) {
gf_msg(this->name, GF_LOG_ERROR, ENOMEM, UTIME_MSG_NO_MEMORY,
"Failed to allocate private memory.");
return -1;
}
memset(utime, 0, sizeof(*utime));
this->private = utime;
GF_OPTION_INIT("noatime", utime->noatime, bool, err);
return 0;
err:
return -1;
}
void
fini(xlator_t *this)
{
utime_priv_t *utime = NULL;
utime = this->private;
GF_FREE(utime);
return;
}
int32_t
reconfigure(xlator_t *this, dict_t *dict)
reconfigure(xlator_t *this, dict_t *options)
{
utime_priv_t *utime = this->private;
GF_OPTION_RECONF("noatime", utime->noatime, options, bool, err);
return 0;
err:
return -1;
}
int
@ -180,3 +218,15 @@ struct xlator_dumpops dumpops = {
.priv_to_dict = gf_utime_priv_to_dict,
.priv = gf_utime_priv,
};
struct volume_options options[] = {
{.key = {"noatime"},
.type = GF_OPTION_TYPE_BOOL,
.default_value = "on",
.op_version = {GD_OP_VERSION_5_0},
.flags = OPT_FLAG_SETTABLE | OPT_FLAG_CLIENT_OPT | OPT_FLAG_DOC,
.tags = {"ctime"},
.description = "Enable/Disable atime updation when ctime feature is "
"enabled. When noatime is on, atime is not updated with "
"ctime feature enabled and vice versa."},
{.key = {NULL}}};

View File

@ -16,4 +16,8 @@
#include "defaults.h"
#include "utime-autogen-fops.h"
typedef struct utime_priv {
gf_boolean_t noatime;
} utime_priv_t;
#endif /* __UTIME_H__ */

View File

@ -3670,6 +3670,14 @@ struct volopt_map_entry glusterd_volopt_map[] = {
.op_version = GD_OP_VERSION_4_1_0,
.description = "enable/disable utime translator on the volume.",
.flags = VOLOPT_FLAG_CLIENT_OPT | VOLOPT_FLAG_XLATOR_OPT},
{.key = "ctime.noatime",
.voltype = "features/utime",
.validate_fn = validate_boolean,
.value = "on",
.option = "noatime",
.op_version = GD_OP_VERSION_5_0,
.description = "enable/disable noatime option with ctime enabled.",
.flags = VOLOPT_FLAG_CLIENT_OPT | VOLOPT_FLAG_XLATOR_OPT},
{.key = "feature.cloudsync-storetype",
.voltype = "features/cloudsync",
.op_version = GD_OP_VERSION_5_0,

View File

@ -605,6 +605,10 @@ posix_set_ctime(call_frame_t *frame, xlator_t *this, const char *real_path,
if (priv->ctime) {
(void)posix_get_mdata_flag(frame->root->flags, &flag);
if ((flag.ctime == 0) && (flag.mtime == 0) && (flag.atime == 0)) {
goto out;
}
if (frame->root->ctime.tv_sec == 0) {
gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_SETMDATA_FAILED,
"posix set mdata failed, No ctime : %s gfid:%s", real_path,
@ -640,6 +644,9 @@ posix_set_parent_ctime(call_frame_t *frame, xlator_t *this,
if (inode && priv->ctime) {
(void)posix_get_parent_mdata_flag(frame->root->flags, &flag);
if ((flag.ctime == 0) && (flag.mtime == 0) && (flag.atime == 0)) {
goto out;
}
ret = posix_set_mdata_xattr(this, real_path, fd, inode,
&frame->root->ctime, stbuf, &flag,
_gf_false);
@ -649,5 +656,6 @@ posix_set_parent_ctime(call_frame_t *frame, xlator_t *this,
uuid_utoa(inode->gfid));
}
}
out:
return;
}