user servicable snapshots

Change-Id: Idbf27dbe088e646a8ab81cedc5818413795895ea
Signed-off-by: Raghavendra Bhat <raghavendra@redhat.com>
Signed-off-by: Anand Subramanian <anands@redhat.com>
Signed-off-by: Raghavendra Bhat <raghavendra@redhat.com>
Reviewed-on: http://review.gluster.org/7700
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Vijay Bellur <vbellur@redhat.com>
This commit is contained in:
Raghavendra Bhat 2014-05-07 20:13:43 +05:30 committed by Vijay Bellur
parent 58b9edee87
commit cc0378d39f
21 changed files with 4489 additions and 12 deletions

View File

@ -945,6 +945,57 @@ out:
return glfd;
}
int
glfs_h_access (struct glfs *fs, struct glfs_object *object, int mask)
{
int ret = -1;
xlator_t *subvol = NULL;
inode_t *inode = NULL;
loc_t loc = {0, };
/* validate in args */
if ((fs == NULL) || (object == NULL)) {
errno = EINVAL;
goto out;
}
__glfs_entry_fs (fs);
/* get the active volume */
subvol = glfs_active_subvol (fs);
if (!subvol) {
ret = -1;
errno = EIO;
goto out;
}
/* get/refresh the in arg objects inode in correlation to the xlator */
inode = glfs_resolve_inode (fs, subvol, object);
if (!inode) {
errno = ESTALE;
goto out;
}
GLFS_LOC_FILL_INODE (inode, loc, out);
/* fop/op */
ret = syncop_access (subvol, &loc, mask);
DECODE_SYNCOP_ERR (ret);
out:
loc_wipe (&loc);
if (inode)
inode_unref (inode);
glfs_subvol_done (fs, subvol);
return ret;
}
ssize_t
glfs_h_extract_handle (struct glfs_object *object, unsigned char *handle,
int len)

View File

@ -162,6 +162,9 @@ struct glfs_fd *glfs_h_opendir (struct glfs *fs,
struct glfs_fd *glfs_h_open (struct glfs *fs, struct glfs_object *object,
int flags) __THROW;
int
glfs_h_access (struct glfs *fs, struct glfs_object *object, int mask) __THROW;
__END_DECLS
#endif /* !_GLFS_HANDLES_H */

View File

@ -139,6 +139,10 @@ AC_CONFIG_FILES([Makefile
xlators/features/protect/src/Makefile
xlators/features/gfid-access/Makefile
xlators/features/gfid-access/src/Makefile
xlators/features/snapview-server/Makefile
xlators/features/snapview-server/src/Makefile
xlators/features/snapview-client/Makefile
xlators/features/snapview-client/src/Makefile
xlators/playground/Makefile
xlators/playground/template/Makefile
xlators/playground/template/src/Makefile

View File

@ -2174,6 +2174,21 @@ syncop_access_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
return 0;
}
/* posix_acl xlator will respond in different ways for access calls from
fuse and access calls from nfs. For fuse, checking op_ret is sufficient
to check whether the access call is successful or not. But for nfs the
mode of the access that is permitted is put into op_errno before unwind.
With syncop, the caller of syncop_access will not be able to get the
mode of the access despite call being successul (since syncop_access
returns only the op_ret collected in args).
Now, if access call is failed, then args.op_ret is returned to recognise
the failure. But if op_ret is zero, then the mode of access which is
set in args.op_errno is returned. Thus the caller of syncop_access
has to check whether the return value is less than zero or not. If the
return value it got is less than zero, then access call is failed.
If it is not, then the access call is successful and the value the caller
got is the mode of the access.
*/
int
syncop_access (xlator_t *subvol, loc_t *loc, int32_t mask)
{
@ -2184,7 +2199,7 @@ syncop_access (xlator_t *subvol, loc_t *loc, int32_t mask)
if (args.op_ret < 0)
return -args.op_errno;
return args.op_ret;
return args.op_errno;
}

View File

@ -29,6 +29,7 @@
#include "latency.h"
#define FIRST_CHILD(xl) (xl->children->xlator)
#define SECOND_CHILD(xl) (xl->children->next->xlator)
#define GF_SET_ATTR_MODE 0x1
#define GF_SET_ATTR_UID 0x2

View File

@ -22,7 +22,7 @@ TEST rm -f $(gf_get_gfid_backend_file_path $B0/${V0}1 "dir1")
TEST rmdir $B0/${V0}1/dir1/dir2
TEST $CLI volume heal $V0 full
sleep 5
EXPECT_WITHIN $HEAL_TIMEOUT "0" afr_get_pending_heal_count $V0
TEST [ -d $B0/${V0}1/dir1/dir2 ]
TEST [ ! -d $(gf_get_gfid_backend_file_path $B0/${V0}1 "dir1") ]
@ -35,7 +35,15 @@ TEST $CLI volume start $V0
EXPECT 'Started' volinfo_field $V0 'Status';
TEST glusterfs --entry-timeout=0 --attribute-timeout=0 -s $H0 --volfile-id $V0 $M0;
ls -l $M0/
# Till now, protocol/server was not doing inode linking as part of readdirp.
# But pas part of user servicable snapshots patcth, changes to do inode linking
# in protocol/server in readdirp, were introduced. So now to make sure
# the gfid handle of dir1 is healed, explicit lookup has to be sent on it.
# Otherwise, whenever ls -l is done just on the mount point $M0, lookup on the
# entries received as part of readdirp, is not sent, because the inodes for
# those entries were linked as part of readdirp itself. i.e instead of doing
# "ls -l $M0", it has to be the below command.
ls -l $M0/dir1;
TEST [ -h $(gf_get_gfid_backend_file_path $B0/${V0}1 "dir1") ]

View File

@ -1,4 +1,4 @@
SUBDIRS = locks quota read-only mac-compat quiesce marker index barrier \
protect compress changelog gfid-access $(GLUPY_SUBDIR) qemu-block # trash path-converter # filter
protect compress changelog gfid-access $(GLUPY_SUBDIR) qemu-block snapview-client snapview-server # trash path-converter # filter
CLEANFILES =

View File

@ -1013,7 +1013,8 @@ quota_fill_inodectx (xlator_t *this, inode_t *inode, dict_t *dict,
goto unlock;
}
if (loc->name == NULL)
/* do nothing if it is a nameless lookup */
if (loc->name == NULL || !loc->parent)
goto unlock;
list_for_each_entry (dentry, &ctx->parents, next) {

View File

@ -0,0 +1 @@
SUBDIRS = src

View File

@ -0,0 +1,15 @@
xlator_LTLIBRARIES = snapview-client.la
xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/features
snapview_client_la_LDFLAGS = -module -avoid-version
snapview_client_la_SOURCES = snapview-client.c
snapview_client_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la
noinst_HEADERS = snapview-client.h snapview-client-mem-types.h
AM_CPPFLAGS = $(GF_CPPFLAGS) -I$(top_srcdir)/libglusterfs/src
AM_CFLAGS = -Wall $(GF_CFLAGS)
CLEANFILES =

View File

@ -0,0 +1,23 @@
/*
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 _SVC_MEM_TYPES_H
#define _SVC_MEM_TYPES_H
#include "mem-types.h"
enum svc_mem_types {
gf_svc_mt_svc_private_t = gf_common_mt_end + 1,
gf_svc_mt_svc_local_t,
gf_svc_mt_svc_inode_t,
gf_svc_mt_end
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,110 @@
/*
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 __SNAP_VIEW_CLIENT_H__
#define __SNAP_VIEW_CLIENT_H__
#ifndef _CONFIG_H
#define _CONFIG_H
#include "config.h"
#endif
#include "glusterfs.h"
#include "logging.h"
#include "dict.h"
#include "xlator.h"
#include "defaults.h"
#include "snapview-client-mem-types.h"
struct __svc_local {
loc_t loc;
xlator_t *subvolume;
};
typedef struct __svc_local svc_local_t;
void
svc_local_free (svc_local_t *local);
#define SVC_STACK_UNWIND(fop, frame, params ...) do { \
svc_local_t *__local = NULL; \
if (frame) { \
__local = frame->local; \
frame->local = NULL; \
} \
STACK_UNWIND_STRICT (fop, frame, params); \
svc_local_free (__local); \
} while (0)
#define SVC_ENTRY_POINT_SET(this, xdata, op_ret, op_errno, new_xdata, \
priv, ret, label) \
do { \
if (!xdata) { \
xdata = new_xdata = dict_new (); \
if (!new_xdata) { \
gf_log (this->name, GF_LOG_ERROR, \
"failed to allocate new dict"); \
op_ret = -1; \
op_errno = ENOMEM; \
goto label; \
} \
} \
ret = dict_set_str (xdata, "entry-point", "true"); \
if (ret) { \
gf_log (this->name, GF_LOG_ERROR, \
"failed to set dict"); \
op_ret = -1; \
op_errno = ENOMEM; \
goto label; \
} \
} while (0);
#define SVC_GET_SUBVOL_FROM_CTX(this, op_ret, op_errno, inode_type, ret, \
inode, subvolume, label) \
do { \
ret = svc_inode_ctx_get (this, inode, &inode_type); \
if (ret < 0) { \
gf_log (this->name, GF_LOG_ERROR, \
"inode context not found for gfid %s", \
uuid_utoa (inode->gfid)); \
op_ret = -1; \
op_errno = EINVAL; \
goto label; \
} \
\
subvolume = svc_get_subvolume (this, inode_type); \
} while (0);
struct svc_private {
char *path; //might be helpful for samba
};
typedef struct svc_private svc_private_t;
typedef enum {
NORMAL_INODE = 1,
VIRTUAL_INODE
} inode_type_t;
void svc_local_free (svc_local_t *local);
xlator_t *
svc_get_subvolume (xlator_t *this, int inode_type);
int
__svc_inode_ctx_get (xlator_t *this, inode_t *inode, int *inode_type);
int
svc_inode_ctx_get (xlator_t *this, inode_t *inode, int *inode_type);
int32_t
svc_inode_ctx_set (xlator_t *this, inode_t *inode, int inode_type);
void
svc_local_free (svc_local_t *local);
#endif /* __SNAP_VIEW_CLIENT_H__ */

View File

@ -0,0 +1 @@
SUBDIRS = src

View File

@ -0,0 +1,22 @@
xlator_LTLIBRARIES = snapview-server.la
xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/features
snapview_server_la_LDFLAGS = -module -avoid-version
snapview_server_la_SOURCES = snapview-server.c
snapview_server_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la\
$(top_builddir)/api/src/libgfapi.la\
$(RLLIBS) $(top_builddir)/rpc/xdr/src/libgfxdr.la \
$(top_builddir)/rpc/rpc-lib/src/libgfrpc.la
noinst_HEADERS = snapview-server.h snapview-server-mem-types.h
AM_CPPFLAGS = $(GF_CPPFLAGS) -I$(top_srcdir)/libglusterfs/src \
-I$(top_srcdir)/api/src \
-I$(top_srcdir)/rpc/rpc-lib/src \
-I$(top_srcdir)/rpc/xdr/src \
-DDATADIR=\"$(localstatedir)\"
AM_CFLAGS = -Wall $(GF_CFLAGS)
CLEANFILES =

View File

@ -0,0 +1,25 @@
/*
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 __SNAP_VIEW_MEM_TYPES_H
#define __SNAP_VIEW_MEM_TYPES_H
#include "mem-types.h"
enum snapview_mem_types {
gf_svs_mt_priv_t = gf_common_mt_end + 1,
gf_svs_mt_svs_inode_t,
gf_svs_mt_dirents_t,
gf_svs_mt_svs_fd_t,
gf_svs_mt_end
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,88 @@
/*
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 __SNAP_VIEW_H__
#define __SNAP_VIEW_H__
#ifndef _CONFIG_H
#define _CONFIG_H
#include "config.h"
#endif
#include "dict.h"
#include "defaults.h"
#include "mem-types.h"
#include "call-stub.h"
#include "inode.h"
#include "byte-order.h"
#include "iatt.h"
#include <ctype.h>
#include <sys/uio.h>
#include "glusterfs.h"
#include "xlator.h"
#include "logging.h"
#include "glfs.h"
#include "common-utils.h"
#include "glfs-handles.h"
#include "glfs-internal.h"
#include "glusterfs3-xdr.h"
#include "glusterfs-acl.h"
#include "syncop.h"
#include "list.h"
/*
* The max number of snap entries we consider currently
*/
#define SNAP_VIEW_MAX_NUM_SNAPS 128
#define DEFAULT_SVD_LOG_FILE_DIRECTORY DATADIR "/log/glusterfs"
typedef enum {
SNAP_VIEW_ENTRY_POINT_INODE = 0,
SNAP_VIEW_VIRTUAL_INODE
} inode_type_t;
struct svs_inode {
glfs_t *fs;
glfs_object_t *object;
inode_type_t type;
/* used only for entry point directory where gfid of the directory
from where the entry point was entered is saved.
*/
uuid_t pargfid;
struct iatt buf;
};
typedef struct svs_inode svs_inode_t;
struct svs_fd {
glfs_fd_t *fd;
};
typedef struct svs_fd svs_fd_t;
struct snap_dirent {
char name[NAME_MAX];
char uuid[UUID_CANONICAL_FORM_LEN + 1];
glfs_t *fs;
};
typedef struct snap_dirent snap_dirent_t;
struct svs_private {
snap_dirent_t *dirents;
int num_snaps;
};
typedef struct svs_private svs_private_t;
glfs_t *
svs_intialise_snapshot_volume (xlator_t *this, const char *name);
snap_dirent_t *
svs_get_snap_dirent (xlator_t *this, const char *name);
#endif /* __SNAP_VIEW_H__ */

View File

@ -47,6 +47,11 @@ fuse_resolve_loc_touchup (fuse_state_t *state)
} else if (loc->inode) {
ret = inode_path (loc->inode, NULL, &path);
uuid_copy (loc->gfid, loc->inode->gfid);
if (path) {
loc->name = strrchr (path, '/');
if (loc->name)
loc->name++;
}
}
if (ret)
gf_log (THIS->name, GF_LOG_TRACE,

View File

@ -45,8 +45,14 @@ resolve_loc_touchup (call_frame_t *frame)
if (!loc->path) {
if (loc->parent && resolve->bname) {
ret = inode_path (loc->parent, resolve->bname, &path);
loc->name = resolve->bname;
} else if (loc->inode) {
ret = inode_path (loc->inode, NULL, &path);
if (path) {
loc->name = strrchr (path, '/');
if (loc->name)
loc->name++;
}
}
if (ret)
gf_log (frame->this->name, GF_LOG_TRACE,
@ -123,15 +129,29 @@ resolve_gfid_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
goto out;
}
loc_wipe (resolve_loc);
link_inode = inode_link (inode, NULL, NULL, buf);
if (!link_inode)
if (!link_inode) {
loc_wipe (resolve_loc);
goto out;
}
inode_lookup (link_inode);
/* wipe the loc only after the inode has been linked to the inode
table. Otherwise before inode gets linked to the inode table,
inode would have been unrefed (this might have been destroyed
if refcount becomes 0, and put back to mempool). So once the
inode gets destroyed, inode_link is a redundant operation. But
without knowing that the destroyed inode's pointer is saved in
the resolved_loc as parent (while constructing loc for resolving
the entry) and the inode_new call for resolving the entry will
return the same pointer to the inode as the parent (because in
reality the inode is a free inode present in cold list of the
inode mem-pool).
*/
loc_wipe (resolve_loc);
if (uuid_is_null (resolve->pargfid)) {
inode_unref (link_inode);
goto out;
@ -143,13 +163,14 @@ resolve_gfid_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
resolve_loc->name = resolve->bname;
resolve_loc->inode = inode_new (state->itable);
inode_path (resolve_loc->parent, resolve_loc->name,
(char **) &resolve_loc->path);
STACK_WIND (frame, resolve_gfid_entry_cbk,
frame->root->client->bound_xl,
frame->root->client->bound_xl->fops->lookup,
&resolve->resolve_loc, NULL);
&resolve->resolve_loc, state->xdata);
return 0;
out:
resolve_continue (frame);
@ -182,7 +203,7 @@ resolve_gfid (call_frame_t *frame)
STACK_WIND (frame, resolve_gfid_cbk,
frame->root->client->bound_xl,
frame->root->client->bound_xl->fops->lookup,
&resolve->resolve_loc, NULL);
&resolve->resolve_loc, state->xdata);
return 0;
}

View File

@ -1897,6 +1897,8 @@ server_readdirp_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
rpcsvc_request_t *req = NULL;
int ret = 0;
state = CALL_STATE (frame);
GF_PROTOCOL_DICT_SERIALIZE (this, xdata, &rsp.xdata.xdata_val,
rsp.xdata.xdata_len, op_errno, out);
@ -1920,8 +1922,7 @@ server_readdirp_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
}
}
/* TODO: need more clear thoughts before calling this function. */
/* gf_link_inodes_from_dirent (this, state->fd->inode, entries); */
gf_link_inodes_from_dirent (this, state->fd->inode, entries);
out:
rsp.op_ret = op_ret;