fedora-ize | 2 pkg/Makefile.am | 2 pkg/cloudfs.spec.in | 21 +---- pkg/configure.ac | 2 scripts/cloudfs | 13 ++- scripts/volfilter.py | 9 +- xlators/cluster/cloud/src/cloud.c | 6 + xlators/encryption/crypt/src/crypt.c | 136 ++++++++++++++++++++++++----------- xlators/encryption/crypt/src/crypt.h | 1 xlators/features/oplock/src/oplock.c | 2 10 files changed, 132 insertions(+), 62 deletions(-)
New commits: commit a2786b98842257a29b197e5d416713e01b7c4000 Author: Jeff Darcy jdarcy@redhat.com Date: Thu Feb 3 17:27:06 2011 -0500
Packaging changes (mostly from rpmlint).
diff --git a/fedora-ize b/fedora-ize index c5bca93..a5ac4b9 100755 --- a/fedora-ize +++ b/fedora-ize @@ -20,6 +20,8 @@ cp -r xlators/encryption/crypt/src $work/crypt/ cp -r xlators/features/oplock/src $work/oplock/ cp -r xlators/cluster/login/src $work/login/ cp pkg/* $work/ +cp scripts/cloudfs $work/ +cp scripts/volfilter.py $work/
# Configure just enough to get a decent specfile. cd $work diff --git a/pkg/Makefile.am b/pkg/Makefile.am index 0c83e6c..8fe762f 100644 --- a/pkg/Makefile.am +++ b/pkg/Makefile.am @@ -1,3 +1,5 @@ +bin_SCRIPTS = cloudfs +python_PYTHON = volfilter.py EXTRA_DIST = autogen.sh COPYING cloudfs.spec
SUBDIRS = cloud crypt oplock login diff --git a/pkg/cloudfs.spec.in b/pkg/cloudfs.spec.in index 3e0a705..30c8a3f 100644 --- a/pkg/cloudfs.spec.in +++ b/pkg/cloudfs.spec.in @@ -9,14 +9,12 @@ Summary: Cloud File System Name: @PACKAGE_NAME@ Version: @PACKAGE_VERSION@ Release: %{release} -License: AGPLv3+ +License: AGPLv3 +Group: Applications/File Group: System Environment/Base Vendor: Red Hat -Packager: @PACKAGE_BUGREPORT@ URL: http://cloudfs.org -Source0: cloudfs-0.5.tgz -Source1: volfilter.py -Source2: cloudfs +Source0: http://cloudfs.org/dist/0.5/cloudfs-0.5.tgz BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
Requires: glusterfs >= 3.1.1 @@ -31,10 +29,6 @@ BuildRequires: openssl-devel CloudFS is a cloud-capable filesystem based on GlusterFS (http://gluster.org) with additional authentication/encryption/multi-tenancy features.
-Summary: CloudFS -Group: Applications/File -Provides: cloudfs = %{version}-%{release} - %prep %setup -q -n %{name}-%{version}
@@ -48,14 +42,11 @@ Provides: cloudfs = %{version}-%{release} %install %{__rm} -rf %{buildroot} %{__make} install DESTDIR=%{buildroot} -%{__install} -D -p -m 0644 %{SOURCE1} \ - %{buildroot}%{python_sitelib}/volfilter.py -%{__install} -D -p -m 0755 %{SOURCE2} \ - %{buildroot}%{_bindir}/cloudfs
# Remove unwanted files from all the shared libraries find %{buildroot}%{_libdir} -name '*.a' -delete find %{buildroot}%{_libdir} -name '*.la' -delete +find %{buildroot}%{_libdir} -name '*.so.0.0.0' | xargs strip
%clean %{__rm} -rf %{buildroot} @@ -66,10 +57,10 @@ find %{buildroot}%{_libdir} -name '*.la' -delete %{_libdir}/glusterfs/@GLUSTER_VERSION@/xlator/cluster/*.so* %{_libdir}/glusterfs/@GLUSTER_VERSION@/xlator/encryption/*.so* %{_libdir}/glusterfs/@GLUSTER_VERSION@/xlator/features/*.so* -%{python_sitelib}/volfilter.py +%{python_sitelib}/volfilter.py* %{_bindir}/cloudfs
%changelog -* Fri Jan 21 2011 Jeff Darcy jdarcy@redhat.com - 0.5 +* Fri Jan 21 2011 Jeff Darcy jdarcy@redhat.com - 0.5-1 - Original version based on GlusterFS 3.1.1
diff --git a/pkg/configure.ac b/pkg/configure.ac index d53fafa..bc64915 100644 --- a/pkg/configure.ac +++ b/pkg/configure.ac @@ -20,6 +20,8 @@ AM_INIT_AUTOMAKE
AM_CONFIG_HEADER([config.h])
+AM_PATH_PYTHON([]) + AC_CONFIG_FILES([Makefile cloud/Makefile crypt/Makefile
commit 84de7f10d03e37f33b15579e6d42d6aedc571a92 Author: Jeff Darcy jdarcy@redhat.com Date: Thu Jan 27 20:33:49 2011 -0500
Allow statfs even when unbound.
Without this, DHT gets errors back as it's trying to get disk-full information so that it can avoid over-filling a subvolume. This seems more important than the minor amount of information leakage from the pre-binding dummy subvolume (which will in almost all cases be the same actul local filesystem as the real per-tenant subvolumes).
diff --git a/xlators/cluster/cloud/src/cloud.c b/xlators/cluster/cloud/src/cloud.c index 5cdbd3f..0bddb3a 100644 --- a/xlators/cluster/cloud/src/cloud.c +++ b/xlators/cluster/cloud/src/cloud.c @@ -192,12 +192,14 @@ cloud_stat (call_frame_t *frame, xlator_t *this, loc_t *loc) return 0; }
+#if 0 int32_t cloud_statfs (call_frame_t *frame, xlator_t *this, loc_t *loc) { STACK_UNWIND_STRICT (statfs, frame, -1, EPERM, NULL); return 0; } +#endif
int cloud_symlink (call_frame_t *frame, xlator_t *this, const char *linkpath, @@ -495,7 +497,11 @@ struct xlator_fops fops = { .rmdir = cloud_rmdir, .setattr = cloud_setattr, .stat = cloud_stat, + /* + * Allow statfs, because it's fairly harmless and blocking it confuses + * DHT's capacity-balancing code. .statfs = cloud_statfs, + */ .symlink = cloud_symlink, .truncate = cloud_truncate, .unlink = cloud_unlink,
commit a0f1109e5bc5bf5e077925ef07d8d34c32d0f733 Author: Jeff Darcy jdarcy@redhat.com Date: Thu Jan 27 20:31:22 2011 -0500
Insert crypt above write-behind to avoid excessive conflict retries.
While conflicts are handled now, write-behind can cause an awful lot of "self conflicts" (where one of two simultaneous writes breaks the other's oplock). This brings the conflict/retry count down to a more reasonable level.
diff --git a/scripts/cloudfs b/scripts/cloudfs index d8abe72..4b6615c 100755 --- a/scripts/cloudfs +++ b/scripts/cloudfs @@ -92,6 +92,7 @@ def cloudify_server (volfile, users): for user, pw in users: new_stack = copy_stack(last.subvols[0],user) volfilter.push_filter(graph,new_stack,"features/oplock") + new_stack.name = user subvols.append(new_stack)
# One cloud to bring them all... @@ -182,9 +183,14 @@ def do_init_crypt (): for td in to_do: volfilter.delete(graph,td) to_do = [xl for xl in graph.itervalues() - if xl.type == "protocol/client"] - for td in to_do: - volfilter.push_filter(graph,td,"encryption/crypt",opts) + if xl.type == "performance/write-behind"] + if to_do: + for td in to_do: + # Nice to push below io-stats etc. if we can + volfilter.push_filter(graph,td,"encryption/crypt",opts) + else: + # Might as well push it on top. + volfilter.push_filter(graph,last,"encryption/crypt",opts) volfilter.generate(graph,last,file(vfname,"w"))
if len(sys.argv) < 3:
commit f9a4fd656c857406ae0db0ba541c20454f393211 Author: Jeff Darcy jdarcy@redhat.com Date: Thu Jan 27 17:33:26 2011 -0500
Implement retries when conflicts are detected.
diff --git a/xlators/encryption/crypt/src/crypt.c b/xlators/encryption/crypt/src/crypt.c index 6110816..d2d3be1 100644 --- a/xlators/encryption/crypt/src/crypt.c +++ b/xlators/encryption/crypt/src/crypt.c @@ -31,6 +31,13 @@
#include "crypt.h"
+/* Forward decls so crypt_launch can retry. */ +int32_t +crypt_rmw_done (call_frame_t *frame, xlator_t *this); +int32_t +crypt_lock_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno); + /* * The "lame" stuff is just for testing (makes it easier to verify correctness * of contents) and must be enabled by hand. @@ -86,7 +93,7 @@ lame_decrypt_iovec (crypt_private_t *priv, struct iovec *vector, int count) */
void -good_encrypt (crypt_private_t *priv, char * buf, int len) +good_crypt_buf (crypt_private_t *priv, char * buf, int len, int dir) { DES_cblock ivec; int num; @@ -94,8 +101,9 @@ good_encrypt (crypt_private_t *priv, char * buf, int len) while (len >= priv->block_size) { memset(&ivec,0,sizeof(ivec)); num = 0; - DES_cfb64_encrypt((const unsigned char *)buf,(unsigned char *)buf, - priv->block_size,&priv->sched,&ivec,&num,1); + DES_cfb64_encrypt((const unsigned char *)buf, + (unsigned char *)buf, priv->block_size, + &priv->sched,&ivec,&num,dir); buf += priv->block_size; len -= priv->block_size; } @@ -103,18 +111,25 @@ good_encrypt (crypt_private_t *priv, char * buf, int len) if (len > 0) { memset(&ivec,0,sizeof(ivec)); num = 0; - DES_cfb64_encrypt((const unsigned char *)buf,(unsigned char *)buf, - len,&priv->sched, &ivec,&num,1); + DES_cfb64_encrypt((const unsigned char *)buf, + (unsigned char *)buf,len,&priv->sched,&ivec,&num,dir); } }
-/* - * We don't need good_decrypt because good_decrypt_iovec just does the - * looping internally. - */ +void +good_encrypt (crypt_private_t *priv, char * buf, int len) +{ + good_crypt_buf(priv,buf,len,1); +}
void -good_decrypt_iovec (crypt_private_t *priv, struct iovec *vector, int count) +good_decrypt (crypt_private_t *priv, char * buf, int len) +{ + good_crypt_buf(priv,buf,len,0); +} + +void +good_crypt_iov (crypt_private_t *priv, struct iovec *vector, int count, int dir) { DES_cblock ivec; int num; @@ -137,7 +152,7 @@ good_decrypt_iovec (crypt_private_t *priv, struct iovec *vector, int count) } DES_cfb64_encrypt((const unsigned char *)buf, (unsigned char *)buf, - bytes,&priv->sched,&ivec,&num,0); + bytes,&priv->sched,&ivec,&num,dir); buf += bytes; b_resid = (b_resid + bytes) % priv->block_size; if (!b_resid) { @@ -147,6 +162,18 @@ good_decrypt_iovec (crypt_private_t *priv, struct iovec *vector, int count) } }
+void +good_encrypt_iovec (crypt_private_t *priv, struct iovec *vector, int count) +{ + good_crypt_iov(priv,vector,count,1); +} + +void +good_decrypt_iovec (crypt_private_t *priv, struct iovec *vector, int count) +{ + good_crypt_iov(priv,vector,count,0); +} + int32_t crypt_readv_cbk (call_frame_t *frame, void *cookie, @@ -344,6 +371,48 @@ err: }
int32_t +crypt_launch (call_frame_t *frame, xlator_t *this) +{ + crypt_wlocal_t *local = frame->local; + crypt_private_t *priv = this->private; + int32_t op_errno = ENOMEM; + + local->call_count = (local->head_resid != 0) + (local->tail_resid != 0); + + /* Check for the only case which doesn't require a lock. */ + if (!local->call_count) { + /* Head and tail were encrypted on the previous pass. */ + good_decrypt(priv,local->head_data,priv->block_size); + good_encrypt(priv,local->head_data,priv->block_size); + return crypt_rmw_done(frame,this); + } + + local->xattr = get_new_dict(); + if (!local->xattr) { + op_errno = ENOMEM; + goto err; + } + + if (dict_set_str(local->xattr,"trusted.glusterfs.lock","fubar") != 0) { + op_errno = EIO; + dict_unref(local->xattr); + goto err; + } + + local->op_ret = 0; + + STACK_WIND (frame, crypt_lock_cbk, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->fsetxattr, + local->fd, local->xattr, 0); + + return 0; + +err: + STACK_UNWIND_STRICT(writev,frame,-1,op_errno,NULL,NULL); + return 0; +} + +int32_t crypt_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this, @@ -357,9 +426,15 @@ crypt_writev_cbk (call_frame_t *frame, /* * This is where we might get an error indicating that somebody else * wrote to the file between our read and write. In that case, we - * would simply re-start at the lock call. + * simply re-start at the lock call. */
+ if ((op_ret < 0) && (op_errno == EBUSY)) { + gf_log(this->name,GF_LOG_WARNING,"retrying conflicted write"); + local->is_retry = _gf_true; + return crypt_launch(frame,this); + } + if (op_ret > local->orig_size) { op_ret = local->orig_size; } @@ -425,10 +500,12 @@ crypt_rmw_done (call_frame_t *frame, xlator_t *this) b_offset = 0; to_go = local->vector[v_index].iov_len - v_offset; while (to_go >= priv->block_size) { - good_encrypt(priv, - (char *)(local->vector[v_index].iov_base) - + v_offset + b_offset, - priv->block_size); + if (!local->is_retry) { + good_encrypt(priv, + (char *)(local->vector[v_index].iov_base) + + v_offset + b_offset, + priv->block_size); + } b_offset += priv->block_size; to_go -= priv->block_size; } @@ -480,6 +557,7 @@ crypt_rmw_done (call_frame_t *frame, xlator_t *this) goto err; } } + /* * We always start our writes at block boundaries, so we subtract the * "residue" before passing the offset to the next translator. Since @@ -671,31 +749,9 @@ crypt_writev (call_frame_t *frame, } local->head_resid = head_resid; local->tail_resid = tail_resid; - local->call_count = (head_resid != 0) + (tail_resid != 0);
- /* Check for the only case which doesn't require a lock. */ - if (!local->call_count) { - return crypt_rmw_done(frame,this); - } - - local->xattr = get_new_dict(); - if (!local->xattr) { - op_errno = ENOMEM; - goto err; - } - - if (dict_set_str(local->xattr,"trusted.glusterfs.lock","fubar") != 0) { - op_errno = EIO; - dict_unref(local->xattr); - goto err; - } - - local->op_ret = 0; - - STACK_WIND (frame, crypt_lock_cbk, FIRST_CHILD(this), - FIRST_CHILD(this)->fops->fsetxattr, fd, local->xattr, 0); - - return 0; + local->is_retry = _gf_false; + return crypt_launch(frame,this);
err: STACK_UNWIND_STRICT(writev,frame,-1,op_errno,NULL,NULL); diff --git a/xlators/encryption/crypt/src/crypt.h b/xlators/encryption/crypt/src/crypt.h index 0c6548c..fde242b 100644 --- a/xlators/encryption/crypt/src/crypt.h +++ b/xlators/encryption/crypt/src/crypt.h @@ -61,6 +61,7 @@ typedef struct { size_t head_resid; size_t tail_resid; dict_t *xattr; + gf_boolean_t is_retry; } crypt_wlocal_t;
#endif /* __CRYPT_H__ */ diff --git a/xlators/features/oplock/src/oplock.c b/xlators/features/oplock/src/oplock.c index 940398e..402e6ea 100644 --- a/xlators/features/oplock/src/oplock.c +++ b/xlators/features/oplock/src/oplock.c @@ -148,6 +148,7 @@ oplock_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, struct iovec *vect
entry = fetch_op_lock(&priv->locks,inode,state->conn); if (entry) { + LIST_REMOVE(entry,links); if (entry->value != inode->gen) { gf_log(this->name,GF_LOG_DEBUG, "would reject write for %d from %p", @@ -155,7 +156,6 @@ oplock_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, struct iovec *vect op_errno = EBUSY; goto err; } - LIST_REMOVE(entry,links); FREE(entry); } ++(inode->gen);
commit 5beada814cdbb2bc104669892a322890838fff56 Author: Jeff Darcy jdarcy@redhat.com Date: Thu Jan 27 17:33:11 2011 -0500
Make slightly less ugly volume names.
diff --git a/scripts/cloudfs b/scripts/cloudfs index 30d73bd..d8abe72 100755 --- a/scripts/cloudfs +++ b/scripts/cloudfs @@ -127,7 +127,6 @@ def do_init (): voldir = "" for gdir in glusterd_dirs: probe = "%s/vols/%s" % (gdir, volname) - print "trying %s" % probe if os.access(probe,os.X_OK): voldir = probe break diff --git a/scripts/volfilter.py b/scripts/volfilter.py index 7453c32..98ab20e 100755 --- a/scripts/volfilter.py +++ b/scripts/volfilter.py @@ -85,15 +85,20 @@ def generate (graph, last, stream=sys.stdout): print >> stream, "end-volume"
def push_filter (graph, old_xl, filt_type, opts={}): - suffix = string.split(old_xl.type,"/")[1] - new_xl = Translator(old_xl.name+"-"+suffix) + suffix = "-" + old_xl.type.split("/")[1] + if len(old_xl.name) > len(suffix): + if old_xl.name[-len(suffix):] == suffix: + old_xl.name = old_xl.name[:-len(suffix)] + new_xl = Translator(old_xl.name+suffix) new_xl.type = old_xl.type new_xl.opts = old_xl.opts new_xl.subvols = old_xl.subvols graph[new_xl.name] = new_xl + old_xl.name += ("-" + filt_type.split("/")[1]) old_xl.type = filt_type old_xl.opts = opts old_xl.subvols = [new_xl] + graph[old_xl.name] = old_xl
def delete (graph, victim): if len(victim.subvols) != 1: