read-only: read-only/worm translator should be in brick graph by default

Problem:
read-only/worm translator is not loaded by default in brick graph because of which
when read-only option is set through volume set volume still remains writable
untill the bricks are restarted as the translator does not have an inmemory flag
to decide whether the read-only/worm option is turned or not.

Solution:
read-only/worm should be loaded by default in brick graph and the read-only/worm
option can be toggled through volume set command. read-only/worm translator now'
has an in-memory flag to decide whether the volume is read-only or not and based
on that either reject the fop or proceed.

Change-Id: Ic79328698f6a72c50433cff15ecadb1a92acc643
BUG: 1134822
Signed-off-by: Atin Mukherjee <amukherj@redhat.com>
Reviewed-on: http://review.gluster.org/8571
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Vijay Bellur <vbellur@redhat.com>
This commit is contained in:
Atin Mukherjee 2014-08-30 16:15:36 +05:30 committed by Vijay Bellur
parent a20101e2e4
commit ef158c75d1
10 changed files with 468 additions and 72 deletions

View File

@ -0,0 +1,67 @@
#!/bin/bash
#Test case: This test checks when a volume is made read-only though volume set
# and bricks are not restarted no write operations can be performed on
# this volume
. $(dirname $0)/../../include.rc
. $(dirname $0)/../../volume.rc
cleanup;
TEST glusterd
TEST pidof glusterd
#Create a volume
TEST $CLI volume create $V0 $H0:$B0/${V0}0;
TEST $CLI volume start $V0
# Mount FUSE and create file/directory, create should succeed as the read-only
# is off by default
TEST glusterfs -s $H0 --volfile-id $V0 $M0
TEST touch $M0/zerobytefile1.txt
TEST mkdir $M0/test_dir1
TEST dd if=/dev/zero of=$M0/file1 bs=1024 count=1024
# turn on read-only option through volume set
TEST gluster volume set $V0 read-only on
# worm feature can't be enabled if read-only is enabled
TEST ! gluster volume set $V0 worm on
# turn off read-only option through volume set
TEST gluster volume set $V0 read-only off
# turn on worm option through volume set
TEST gluster volume set $V0 worm on
# read-only feature can't be enabled if worm is enabled
TEST ! gluster volume set $V0 read-only on
TEST gluster volume set $V0 worm off
TEST gluster volume set $V0 read-only on
# Check whether read-operations can be performed or not
TEST cat $M0/file1
# All write operations should fail now
TEST ! touch $M0/zerobytefile2.txt
TEST ! mkdir $M0/test_dir2
TEST ! dd if=/dev/zero of=$M0/file2 bs=1024 count=1024
# turn off read-only option through volume set
TEST gluster volume set $V0 read-only off
# All write operations should succeed now
TEST touch $M0/zerobytefile2.txt
TEST mkdir $M0/test_dir2
TEST dd if=/dev/zero of=$M0/file2 bs=1024 count=1024
# Turn on worm
TEST gluster volume set $V0 worm on
# unlink should fail now
TEST ! rm -rf $M0/zerobytefile2.txt
cleanup;

View File

@ -2,7 +2,7 @@ xlator_LTLIBRARIES = read-only.la worm.la
xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/features
noinst_HEADERS = read-only-common.h
noinst_HEADERS = read-only.h read-only-mem-types.h read-only-common.h
read_only_la_LDFLAGS = -module -avoid-version

View File

@ -12,14 +12,34 @@
#include "config.h"
#endif
#include "xlator.h"
#include "read-only.h"
#include "read-only-mem-types.h"
#include "defaults.h"
gf_boolean_t
is_readonly_or_worm_enabled (xlator_t *this)
{
read_only_priv_t *priv = NULL;
gf_boolean_t readonly_or_worm_enabled = _gf_false;
priv = this->private;
GF_ASSERT (priv);
readonly_or_worm_enabled = priv->readonly_or_worm_enabled;
return readonly_or_worm_enabled;
}
int32_t
ro_xattrop (call_frame_t *frame, xlator_t *this, loc_t *loc,
gf_xattrop_flags_t flags, dict_t *dict, dict_t *xdata)
{
STACK_UNWIND_STRICT (xattrop, frame, -1, EROFS, NULL, xdata);
if (is_readonly_or_worm_enabled (this))
STACK_UNWIND_STRICT (xattrop, frame, -1, EROFS, NULL, xdata);
else
STACK_WIND_TAIL (frame, FIRST_CHILD (this),
FIRST_CHILD(this)->fops->xattrop,
loc, flags, dict, xdata);
return 0;
}
@ -27,7 +47,13 @@ int32_t
ro_fxattrop (call_frame_t *frame, xlator_t *this,
fd_t *fd, gf_xattrop_flags_t flags, dict_t *dict, dict_t *xdata)
{
STACK_UNWIND_STRICT (fxattrop, frame, -1, EROFS, NULL, xdata);
if (is_readonly_or_worm_enabled (this))
STACK_UNWIND_STRICT (fxattrop, frame, -1, EROFS, NULL, xdata);
else
STACK_WIND_TAIL (frame, FIRST_CHILD (this),
FIRST_CHILD(this)->fops->fxattrop,
fd, flags, dict, xdata);
return 0;
}
@ -36,15 +62,28 @@ ro_entrylk (call_frame_t *frame, xlator_t *this, const char *volume,
loc_t *loc, const char *basename, entrylk_cmd cmd,
entrylk_type type, dict_t *xdata)
{
STACK_UNWIND_STRICT (entrylk, frame, -1, EROFS, xdata);
if (is_readonly_or_worm_enabled (this))
STACK_UNWIND_STRICT (entrylk, frame, -1, EROFS, xdata);
else
STACK_WIND_TAIL (frame, FIRST_CHILD (this),
FIRST_CHILD(this)->fops->entrylk,
volume, loc, basename, cmd, type, xdata);
return 0;
}
int32_t
ro_fentrylk (call_frame_t *frame, xlator_t *this, const char *volume,
fd_t *fd, const char *basename, entrylk_cmd cmd, entrylk_type type, dict_t *xdata)
fd_t *fd, const char *basename, entrylk_cmd cmd, entrylk_type type,
dict_t *xdata)
{
STACK_UNWIND_STRICT (fentrylk, frame, -1, EROFS, xdata);
if (is_readonly_or_worm_enabled (this))
STACK_UNWIND_STRICT (fentrylk, frame, -1, EROFS, xdata);
else
STACK_WIND_TAIL (frame, FIRST_CHILD (this),
FIRST_CHILD(this)->fops->fentrylk,
volume, fd, basename, cmd, type, xdata);
return 0;
}
@ -52,7 +91,13 @@ int32_t
ro_inodelk (call_frame_t *frame, xlator_t *this, const char *volume,
loc_t *loc, int32_t cmd, struct gf_flock *lock, dict_t *xdata)
{
STACK_UNWIND_STRICT (inodelk, frame, -1, EROFS, xdata);
if (is_readonly_or_worm_enabled (this))
STACK_UNWIND_STRICT (inodelk, frame, -1, EROFS, xdata);
else
STACK_WIND_TAIL (frame, FIRST_CHILD (this),
FIRST_CHILD(this)->fops->inodelk,
volume, loc, cmd, lock, xdata);
return 0;
}
@ -60,7 +105,13 @@ int32_t
ro_finodelk (call_frame_t *frame, xlator_t *this, const char *volume,
fd_t *fd, int32_t cmd, struct gf_flock *lock, dict_t *xdata)
{
STACK_UNWIND_STRICT (finodelk, frame, -1, EROFS, xdata);
if (is_readonly_or_worm_enabled (this))
STACK_UNWIND_STRICT (finodelk, frame, -1, EROFS, xdata);
else
STACK_WIND_TAIL (frame, FIRST_CHILD (this),
FIRST_CHILD(this)->fops->finodelk,
volume, fd, cmd, lock, xdata);
return 0;
}
@ -68,7 +119,13 @@ int32_t
ro_lk (call_frame_t *frame, xlator_t *this, fd_t *fd, int cmd,
struct gf_flock *flock, dict_t *xdata)
{
STACK_UNWIND_STRICT (lk, frame, -1, EROFS, NULL, xdata);
if (is_readonly_or_worm_enabled (this))
STACK_UNWIND_STRICT (lk, frame, -1, EROFS, NULL, xdata);
else
STACK_WIND_TAIL (frame, FIRST_CHILD (this),
FIRST_CHILD(this)->fops->lk, fd, cmd, flock,
xdata);
return 0;
}
@ -76,15 +133,29 @@ int32_t
ro_setattr (call_frame_t *frame, xlator_t *this, loc_t *loc,
struct iatt *stbuf, int32_t valid, dict_t *xdata)
{
STACK_UNWIND_STRICT (setattr, frame, -1, EROFS, NULL, NULL, xdata);
return 0;
if (is_readonly_or_worm_enabled (this))
STACK_UNWIND_STRICT (setattr, frame, -1, EROFS, NULL, NULL,
xdata);
else
STACK_WIND_TAIL (frame, FIRST_CHILD (this),
FIRST_CHILD(this)->fops->setattr, loc, stbuf,
valid, xdata);
return 0;
}
int32_t
ro_fsetattr (call_frame_t *frame, xlator_t *this, fd_t *fd,
struct iatt *stbuf, int32_t valid, dict_t *xdata)
{
STACK_UNWIND_STRICT (fsetattr, frame, -1, EROFS, NULL, NULL, xdata);
if (is_readonly_or_worm_enabled (this))
STACK_UNWIND_STRICT (fsetattr, frame, -1, EROFS, NULL, NULL,
xdata);
else
STACK_WIND_TAIL (frame, FIRST_CHILD (this),
FIRST_CHILD(this)->fops->fsetattr, fd, stbuf,
valid, xdata);
return 0;
}
@ -92,14 +163,28 @@ ro_fsetattr (call_frame_t *frame, xlator_t *this, fd_t *fd,
int32_t
ro_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset, dict_t *xdata)
{
STACK_UNWIND_STRICT (truncate, frame, -1, EROFS, NULL, NULL, xdata);
if (is_readonly_or_worm_enabled (this))
STACK_UNWIND_STRICT (truncate, frame, -1, EROFS, NULL, NULL,
xdata);
else
STACK_WIND_TAIL (frame, FIRST_CHILD (this),
FIRST_CHILD(this)->fops->truncate, loc, offset,
xdata);
return 0;
}
int32_t
ro_ftruncate (call_frame_t *frame, xlator_t *this, fd_t *fd, off_t offset, dict_t *xdata)
{
STACK_UNWIND_STRICT (ftruncate, frame, -1, EROFS, NULL, NULL, xdata);
if (is_readonly_or_worm_enabled (this))
STACK_UNWIND_STRICT (ftruncate, frame, -1, EROFS, NULL, NULL,
xdata);
else
STACK_WIND_TAIL (frame, FIRST_CHILD (this),
FIRST_CHILD(this)->fops->ftruncate, fd, offset,
xdata);
return 0;
}
@ -107,8 +192,15 @@ int
ro_mknod (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode,
dev_t rdev, mode_t umask, dict_t *xdata)
{
STACK_UNWIND_STRICT (mknod, frame, -1, EROFS, NULL, NULL, NULL, NULL, xdata);
return 0;
if (is_readonly_or_worm_enabled (this))
STACK_UNWIND_STRICT (mknod, frame, -1, EROFS, NULL, NULL, NULL,
NULL, xdata);
else
STACK_WIND_TAIL (frame, FIRST_CHILD (this),
FIRST_CHILD(this)->fops->mknod, loc, mode,
rdev, umask, xdata);
return 0;
}
@ -116,7 +208,14 @@ int
ro_mkdir (call_frame_t *frame, xlator_t *this, loc_t *loc, mode_t mode,
mode_t umask, dict_t *xdata)
{
STACK_UNWIND_STRICT (mkdir, frame, -1, EROFS, NULL, NULL, NULL, NULL, xdata);
if (is_readonly_or_worm_enabled (this))
STACK_UNWIND_STRICT (mkdir, frame, -1, EROFS, NULL, NULL, NULL,
NULL, xdata);
else
STACK_WIND_TAIL (frame, FIRST_CHILD (this),
FIRST_CHILD(this)->fops->mkdir, loc, mode,
umask, xdata);
return 0;
}
@ -124,7 +223,14 @@ int32_t
ro_unlink (call_frame_t *frame, xlator_t *this, loc_t *loc, int xflag,
dict_t *xdata)
{
STACK_UNWIND_STRICT (unlink, frame, -1, EROFS, NULL, NULL, xdata);
if (is_readonly_or_worm_enabled (this))
STACK_UNWIND_STRICT (unlink, frame, -1, EROFS, NULL, NULL,
xdata);
else
STACK_WIND_TAIL (frame, FIRST_CHILD (this),
FIRST_CHILD(this)->fops->unlink, loc, xflag,
xdata);
return 0;
}
@ -133,7 +239,14 @@ int
ro_rmdir (call_frame_t *frame, xlator_t *this, loc_t *loc, int flags,
dict_t *xdata)
{
STACK_UNWIND_STRICT (rmdir, frame, -1, EROFS, NULL, NULL, xdata);
if (is_readonly_or_worm_enabled (this))
STACK_UNWIND_STRICT (rmdir, frame, -1, EROFS, NULL, NULL,
xdata);
else
STACK_WIND_TAIL (frame, FIRST_CHILD (this),
FIRST_CHILD(this)->fops->rmdir, loc, flags,
xdata);
return 0;
}
@ -142,18 +255,31 @@ int
ro_symlink (call_frame_t *frame, xlator_t *this, const char *linkpath,
loc_t *loc, mode_t umask, dict_t *xdata)
{
STACK_UNWIND_STRICT (symlink, frame, -1, EROFS, NULL, NULL, NULL,
NULL, xdata);
if (is_readonly_or_worm_enabled (this))
STACK_UNWIND_STRICT (symlink, frame, -1, EROFS, NULL, NULL,
NULL, NULL, xdata);
else
STACK_WIND_TAIL (frame, FIRST_CHILD (this),
FIRST_CHILD(this)->fops->symlink, linkpath,
loc, umask, xdata);
return 0;
}
int32_t
ro_rename (call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, dict_t *xdata)
ro_rename (call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc,
dict_t *xdata)
{
STACK_UNWIND_STRICT (rename, frame, -1, EROFS, NULL, NULL, NULL, NULL,
NULL, xdata);
if (is_readonly_or_worm_enabled (this))
STACK_UNWIND_STRICT (rename, frame, -1, EROFS, NULL, NULL, NULL,
NULL, NULL, xdata);
else
STACK_WIND_TAIL (frame, FIRST_CHILD (this),
FIRST_CHILD(this)->fops->rename, oldloc,
newloc, xdata);
return 0;
}
@ -161,7 +287,14 @@ ro_rename (call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, di
int32_t
ro_link (call_frame_t *frame, xlator_t *this, loc_t *oldloc, loc_t *newloc, dict_t *xdata)
{
STACK_UNWIND_STRICT (link, frame, -1, EROFS, NULL, NULL, NULL, NULL, xdata);
if (is_readonly_or_worm_enabled (this))
STACK_UNWIND_STRICT (link, frame, -1, EROFS, NULL, NULL, NULL,
NULL, xdata);
else
STACK_WIND_TAIL (frame, FIRST_CHILD (this),
FIRST_CHILD(this)->fops->link, oldloc, newloc,
xdata);
return 0;
}
@ -169,8 +302,14 @@ int32_t
ro_create (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags,
mode_t mode, mode_t umask, fd_t *fd, dict_t *xdata)
{
STACK_UNWIND_STRICT (create, frame, -1, EROFS, NULL, NULL, NULL,
NULL, NULL, xdata);
if (is_readonly_or_worm_enabled (this))
STACK_UNWIND_STRICT (create, frame, -1, EROFS, NULL, NULL, NULL,
NULL, NULL, xdata);
else
STACK_WIND_TAIL (frame, FIRST_CHILD (this),
FIRST_CHILD(this)->fops->create, loc, flags,
mode, umask, fd, xdata);
return 0;
}
@ -179,16 +318,17 @@ static int32_t
ro_open_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret,
int32_t op_errno, fd_t *fd, dict_t *xdata)
{
STACK_UNWIND_STRICT (open, frame, op_ret, op_errno, fd, xdata);
return 0;
STACK_UNWIND_STRICT (open, frame, op_ret, op_errno, fd, xdata);
return 0;
}
int32_t
ro_open (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags,
fd_t *fd, dict_t *xdata)
{
if (((flags & O_ACCMODE) == O_WRONLY) ||
((flags & O_ACCMODE) == O_RDWR)) {
if (is_readonly_or_worm_enabled (this) &&
(((flags & O_ACCMODE) == O_WRONLY) ||
((flags & O_ACCMODE) == O_RDWR))) {
STACK_UNWIND_STRICT (open, frame, -1, EROFS, NULL, xdata);
return 0;
}
@ -202,23 +342,44 @@ int32_t
ro_fsetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *dict,
int32_t flags, dict_t *xdata)
{
STACK_UNWIND_STRICT (fsetxattr, frame, -1, EROFS, xdata);
return 0;
if (is_readonly_or_worm_enabled (this))
STACK_UNWIND_STRICT (fsetxattr, frame, -1, EROFS, xdata);
else
STACK_WIND_TAIL (frame, FIRST_CHILD (this),
FIRST_CHILD(this)->fops->fsetxattr, fd, dict,
flags, xdata);
return 0;
}
int32_t
ro_fsyncdir (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t flags, dict_t *xdata)
ro_fsyncdir (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t flags,
dict_t *xdata)
{
STACK_UNWIND_STRICT (fsyncdir, frame, -1, EROFS, xdata);
if (is_readonly_or_worm_enabled (this))
STACK_UNWIND_STRICT (fsyncdir, frame, -1, EROFS, xdata);
else
STACK_WIND_TAIL (frame, FIRST_CHILD (this),
FIRST_CHILD(this)->fops->fsyncdir, fd, flags,
xdata);
return 0;
}
int32_t
ro_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, struct iovec *vector,
int32_t count, off_t off, uint32_t flags, struct iobref *iobref, dict_t *xdata)
int32_t count, off_t off, uint32_t flags, struct iobref *iobref,
dict_t *xdata)
{
STACK_UNWIND_STRICT (writev, frame, -1, EROFS, NULL, NULL, xdata);
return 0;
if (is_readonly_or_worm_enabled (this))
STACK_UNWIND_STRICT (writev, frame, -1, EROFS, NULL, NULL,
xdata);
else
STACK_WIND_TAIL (frame, FIRST_CHILD (this),
FIRST_CHILD(this)->fops->writev, fd, vector,
count, off, flags, iobref, xdata);
return 0;
}
@ -226,14 +387,26 @@ int32_t
ro_setxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict,
int32_t flags, dict_t *xdata)
{
STACK_UNWIND_STRICT (setxattr, frame, -1, EROFS, xdata);
return 0;
if (is_readonly_or_worm_enabled (this))
STACK_UNWIND_STRICT (setxattr, frame, -1, EROFS, xdata);
else
STACK_WIND_TAIL (frame, FIRST_CHILD (this),
FIRST_CHILD(this)->fops->setxattr, loc, dict,
flags, xdata);
return 0;
}
int32_t
ro_removexattr (call_frame_t *frame, xlator_t *this, loc_t *loc,
const char *name, dict_t *xdata)
{
STACK_UNWIND_STRICT (removexattr, frame, -1, EROFS, xdata);
if (is_readonly_or_worm_enabled (this))
STACK_UNWIND_STRICT (removexattr, frame, -1, EROFS, xdata);
else
STACK_WIND_TAIL (frame, FIRST_CHILD (this),
FIRST_CHILD(this)->fops->removexattr, loc,
name, xdata);
return 0;
}

View File

@ -15,6 +15,9 @@
#include "xlator.h"
#include "defaults.h"
gf_boolean_t
is_readonly_or_worm_enabled (xlator_t *this);
int32_t
ro_xattrop (call_frame_t *frame, xlator_t *this, loc_t *loc,
gf_xattrop_flags_t flags, dict_t *dict, dict_t *xdata);

View File

@ -0,0 +1,20 @@
/*
Copyright (c) 2014 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 __READONLY_MEM_TYPES_H__
#define __READONLY_MEM_TYPES_H__
#include "mem-types.h"
enum gf_read_only_mem_types_ {
gf_read_only_mt_priv_t = gf_common_mt_end + 1,
gf_read_only_mt_end
};
#endif

View File

@ -12,14 +12,31 @@
#include "config.h"
#endif
#include "xlator.h"
#include "defaults.h"
#include "read-only-common.h"
#include "read-only-mem-types.h"
#include "read-only.h"
int32_t
mem_acct_init (xlator_t *this)
{
int ret = -1;
ret = xlator_mem_acct_init (this, gf_read_only_mt_end + 1);
if (ret)
gf_log (this->name, GF_LOG_ERROR, "Memory accounting "
"initialization failed.");
return ret;
}
int32_t
init (xlator_t *this)
{
if (!this->children || this->children->next) {
int ret = -1;
read_only_priv_t *priv = NULL;
if (!this->children || this->children->next) {
gf_log (this->name, GF_LOG_ERROR,
"translator not configured with exactly one child");
return -1;
@ -30,14 +47,50 @@ init (xlator_t *this)
"dangling volume. check volfile ");
}
return 0;
priv = GF_CALLOC (1, sizeof (*priv), gf_read_only_mt_priv_t);
if (!priv)
goto out;
GF_OPTION_INIT ("read-only", priv->readonly_or_worm_enabled, bool, out);
this->private = priv;
ret = 0;
out:
return ret;
}
int
reconfigure (xlator_t *this, dict_t *options)
{
read_only_priv_t *priv = NULL;
int ret = -1;
gf_boolean_t readonly_or_worm_enabled = _gf_false;
priv = this->private;
GF_ASSERT (priv);
GF_OPTION_RECONF ("read-only", readonly_or_worm_enabled, options, bool,
out);
priv->readonly_or_worm_enabled = readonly_or_worm_enabled;
ret = 0;
out:
gf_log (this->name, GF_LOG_DEBUG, "returning %d", ret);
return ret;
}
void
fini (xlator_t *this)
{
return;
read_only_priv_t *priv = NULL;
priv = this->private;
if (!priv)
return;
this->private = NULL;
GF_FREE (priv);
return;
}
@ -73,5 +126,10 @@ struct xlator_cbks cbks = {
};
struct volume_options options[] = {
{ .key = {NULL} },
{ .key = {"read-only"},
.type = GF_OPTION_TYPE_BOOL,
.default_value = "off",
.description = "When \"on\", makes a volume read-only. It is turned "
"\"off\" by default."
},
};

View File

@ -0,0 +1,21 @@
/*
Copyright (c) 2014 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 __READONLY_H__
#define __READONLY_H__
#include "read-only-mem-types.h"
#include "xlator.h"
typedef struct {
gf_boolean_t readonly_or_worm_enabled;
} read_only_priv_t;
#endif

View File

@ -15,6 +15,21 @@
#include "xlator.h"
#include "defaults.h"
#include "read-only-common.h"
#include "read-only-mem-types.h"
#include "read-only.h"
int32_t
mem_acct_init (xlator_t *this)
{
int ret = -1;
ret = xlator_mem_acct_init (this, gf_read_only_mt_end + 1);
if (ret)
gf_log (this->name, GF_LOG_ERROR, "Memory accounting "
"initialization failed.");
return ret;
}
static int32_t
worm_open_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret,
@ -28,9 +43,10 @@ int32_t
worm_open (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags,
fd_t *fd, dict_t *xdata)
{
if ((((flags & O_ACCMODE) == O_WRONLY) ||
if (is_readonly_or_worm_enabled (this) &&
((((flags & O_ACCMODE) == O_WRONLY) ||
((flags & O_ACCMODE) == O_RDWR)) &&
!(flags & O_APPEND)) {
!(flags & O_APPEND))) {
STACK_UNWIND_STRICT (open, frame, -1, EROFS, NULL, NULL);
return 0;
}
@ -43,6 +59,9 @@ worm_open (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags,
int32_t
init (xlator_t *this)
{
int ret = -1;
read_only_priv_t *priv = NULL;
if (!this->children || this->children->next) {
gf_log (this->name, GF_LOG_ERROR,
"translator not configured with exactly one child");
@ -54,13 +73,49 @@ init (xlator_t *this)
"dangling volume. check volfile ");
}
return 0;
priv = GF_CALLOC (1, sizeof (*priv), gf_read_only_mt_priv_t);
if (!priv)
goto out;
GF_OPTION_INIT ("worm", priv->readonly_or_worm_enabled, bool, out);
this->private = priv;
ret = 0;
out:
return ret;
}
int
reconfigure (xlator_t *this, dict_t *options)
{
read_only_priv_t *priv = NULL;
int ret = -1;
gf_boolean_t readonly_or_worm_enabled = _gf_false;
priv = this->private;
GF_ASSERT (priv);
GF_OPTION_RECONF ("worm", readonly_or_worm_enabled, options, bool, out);
priv->readonly_or_worm_enabled = readonly_or_worm_enabled;
ret = 0;
out:
gf_log (this->name, GF_LOG_DEBUG, "returning %d", ret);
return ret;
}
void
fini (xlator_t *this)
{
read_only_priv_t *priv = NULL;
priv = this->private;
if (!priv)
return;
this->private = NULL;
GF_FREE (priv);
return;
}
@ -84,6 +139,11 @@ struct xlator_fops fops = {
struct xlator_cbks cbks;
struct volume_options options[] = {
{ .key = {NULL} },
{ .key = {"worm"},
.type = GF_OPTION_TYPE_BOOL,
.default_value = "off",
.description = "When \"on\", makes a volume get write once read many "
" feature. It is turned \"off\" by default."
},
};

View File

@ -1852,15 +1852,12 @@ brick_graph_add_ro (volgen_graph_t *graph, glusterd_volinfo_t *volinfo,
goto out;
}
/* Check for read-only volume option, and add it to the graph */
if (dict_get_str_boolean (set_dict, "features.read-only", 0)){
xl = volgen_graph_add (graph, "features/read-only",
volinfo->volname);
if (!xl) {
ret = -1;
goto out;
}
}
xl = volgen_graph_add (graph, "features/read-only", volinfo->volname);
if (!xl)
return -1;
ret = xlator_set_option (xl, "read-only", "off");
if (ret)
return -1;
ret = 0;
@ -1886,15 +1883,9 @@ brick_graph_add_worm (volgen_graph_t *graph, glusterd_volinfo_t *volinfo,
goto out;
}
/* Check for worm volume option, and add it to the graph */
if (dict_get_str_boolean (set_dict, "features.worm", 0)) {
xl = volgen_graph_add (graph, "features/worm",
volinfo->volname);
if (!xl) {
ret = -1;
goto out;
}
}
xl = volgen_graph_add (graph, "features/worm", volinfo->volname);
if (!xl)
return -1;
ret = 0;
@ -3399,6 +3390,10 @@ client_graph_builder (volgen_graph_t *graph, glusterd_volinfo_t *volinfo,
ret = -1;
goto out;
}
ret = xlator_set_option (xl, "read-only", "on");
if (ret)
goto out;
}
/* Check for compress volume option, and add it to the graph on client side */

View File

@ -1547,14 +1547,13 @@ struct volopt_map_entry glusterd_volopt_map[] = {
/* Other options which don't fit any place above */
{ .key = "features.read-only",
.voltype = "features/read-only",
.option = "!read-only",
.value = "off",
.option = "read-only",
.op_version = 1,
.flags = OPT_FLAG_CLIENT_OPT | OPT_FLAG_XLATOR_OPT
},
{ .key = "features.worm",
.voltype = "features/worm",
.option = "!worm",
.option = "worm",
.value = "off",
.op_version = 2,
.flags = OPT_FLAG_CLIENT_OPT | OPT_FLAG_XLATOR_OPT