diff options
Diffstat (limited to 'xlators/mount/fuse/src/fuse-helpers.c')
| -rw-r--r-- | xlators/mount/fuse/src/fuse-helpers.c | 193 |
1 files changed, 144 insertions, 49 deletions
diff --git a/xlators/mount/fuse/src/fuse-helpers.c b/xlators/mount/fuse/src/fuse-helpers.c index feec23998..4d478b919 100644 --- a/xlators/mount/fuse/src/fuse-helpers.c +++ b/xlators/mount/fuse/src/fuse-helpers.c @@ -1,21 +1,15 @@ /* - Copyright (c) 2010-2011 Gluster, Inc. <http://www.gluster.com> + Copyright (c) 2010-2012 Red Hat, Inc. <http://www.redhat.com> This file is part of GlusterFS. - GlusterFS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + 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. */ +#ifdef __NetBSD__ +#define _KMEMUSER +#endif #include "fuse-bridge.h" #if defined(GF_SOLARIS_HOST_OS) @@ -24,21 +18,15 @@ #include <sys/sysctl.h> #endif -#ifndef GF_REQUEST_MAXGROUPS -#define GF_REQUEST_MAXGROUPS 16 -#endif /* GF_REQUEST_MAXGROUPS */ static void fuse_resolve_wipe (fuse_resolve_t *resolve) { - if (resolve->path) - GF_FREE ((void *)resolve->path); + GF_FREE ((void *)resolve->path); - if (resolve->bname) - GF_FREE ((void *)resolve->bname); + GF_FREE ((void *)resolve->bname); - if (resolve->resolved) - GF_FREE ((void *)resolve->resolved); + GF_FREE ((void *)resolve->resolved); if (resolve->fd) fd_unref (resolve->fd); @@ -151,6 +139,7 @@ get_fuse_state (xlator_t *this, fuse_in_header_t *finh) } +#define FUSE_MAX_AUX_GROUPS 32 /* We can get only up to 32 aux groups from /proc */ void frame_fill_groups (call_frame_t *frame) { @@ -173,6 +162,9 @@ frame_fill_groups (call_frame_t *frame) if (!fp) goto out; + if (call_stack_alloc_groups (frame->root, FUSE_MAX_AUX_GROUPS) != 0) + goto out; + while ((ptr = fgets (line, sizeof line, fp))) { if (strncmp (ptr, "Groups:", 7) != 0) continue; @@ -189,7 +181,7 @@ frame_fill_groups (call_frame_t *frame) if (!endptr || *endptr) break; frame->root->groups[idx++] = id; - if (idx == GF_MAX_AUX_GROUPS) + if (idx == FUSE_MAX_AUX_GROUPS) break; } @@ -205,6 +197,7 @@ out: prcred_t *prcred = (prcred_t *) scratch; FILE *fp = NULL; int ret = 0; + int ngrps; ret = snprintf (filename, sizeof filename, "/proc/%d/cred", frame->root->pid); @@ -213,8 +206,11 @@ out: fp = fopen (filename, "r"); if (fp != NULL) { if (fgets (scratch, sizeof scratch, fp) != NULL) { - frame->root->ngrps = MIN(prcred->pr_ngroups, - GF_REQUEST_MAXGROUPS); + ngrps = MIN(prcred->pr_ngroups, + GF_MAX_AUX_GROUPS); + if (call_stack_alloc_groups (frame->root, + ngrps) != 0) + return; } fclose (fp); } @@ -239,7 +235,9 @@ out: if (sysctl(name, namelen, &kp, &kplen, NULL, 0) != 0) return; - ngroups = MIN(kp.kp_eproc.e_ucred.cr_ngroups, GF_REQUEST_MAXGROUPS); + ngroups = MIN(kp.kp_eproc.e_ucred.cr_ngroups, GF_MAX_AUX_GROUPS); + if (call_stack_alloc_groups (frame->root, ngroups) != 0) + return; for (i = 0; i < ngroups; i++) frame->root->groups[i] = kp.kp_eproc.e_ucred.cr_groups[i]; frame->root->ngrps = ngroups; @@ -248,6 +246,53 @@ out: #endif /* GF_LINUX_HOST_OS */ } +/* + * Get the groups for the PID associated with this frame. If enabled, + * use the gid cache to reduce group list collection. + */ +static void get_groups(fuse_private_t *priv, call_frame_t *frame) +{ + int i; + const gid_list_t *gl; + gid_list_t agl; + + if (-1 == priv->gid_cache_timeout) { + frame->root->ngrps = 0; + return; + } + + if (!priv->gid_cache_timeout) { + frame_fill_groups(frame); + return; + } + + gl = gid_cache_lookup(&priv->gid_cache, frame->root->pid); + if (gl) { + if (call_stack_alloc_groups (frame->root, gl->gl_count) != 0) + return; + frame->root->ngrps = gl->gl_count; + for (i = 0; i < gl->gl_count; i++) + frame->root->groups[i] = gl->gl_list[i]; + gid_cache_release(&priv->gid_cache, gl); + return; + } + + frame_fill_groups (frame); + + agl.gl_id = frame->root->pid; + agl.gl_count = frame->root->ngrps; + agl.gl_list = GF_CALLOC(frame->root->ngrps, sizeof(gid_t), + gf_fuse_mt_gids_t); + if (!agl.gl_list) + return; + + for (i = 0; i < frame->root->ngrps; i++) + agl.gl_list[i] = frame->root->groups[i]; + + if (gid_cache_add(&priv->gid_cache, &agl) != 1) + GF_FREE(agl.gl_list); +} + call_frame_t * get_call_frame_for_req (fuse_state_t *state) { @@ -275,7 +320,7 @@ get_call_frame_for_req (fuse_state_t *state) state->lk_owner); } - frame_fill_groups (frame); + get_groups(priv, frame); if (priv && priv->client_pid_set) frame->root->pid = priv->client_pid; @@ -307,7 +352,9 @@ fuse_ino_to_inode (uint64_t ino, xlator_t *fuse) uint64_t inode_to_fuse_nodeid (inode_t *inode) { - if (!inode || __is_root_gfid (inode->gfid)) + if (!inode) + return 0; + if (__is_root_gfid (inode->gfid)) return 1; return (unsigned long) inode; @@ -402,36 +449,56 @@ fail: return ret; } +/* Use the same logic as the Linux NFS-client */ +#define GF_FUSE_SQUASH_INO(ino) ((uint32_t) ino) ^ (ino >> 32) /* courtesy of folly */ void -gf_fuse_stat2attr (struct iatt *st, struct fuse_attr *fa) +gf_fuse_stat2attr (struct iatt *st, struct fuse_attr *fa, gf_boolean_t enable_ino32) { - fa->ino = st->ia_ino; - fa->size = st->ia_size; - fa->blocks = st->ia_blocks; - fa->atime = st->ia_atime; - fa->mtime = st->ia_mtime; - fa->ctime = st->ia_ctime; - fa->atimensec = st->ia_atime_nsec; - fa->mtimensec = st->ia_mtime_nsec; - fa->ctimensec = st->ia_ctime_nsec; - fa->mode = st_mode_from_ia (st->ia_prot, st->ia_type); - fa->nlink = st->ia_nlink; - fa->uid = st->ia_uid; - fa->gid = st->ia_gid; - fa->rdev = makedev (ia_major (st->ia_rdev), - ia_minor (st->ia_rdev)); + if (enable_ino32) + fa->ino = GF_FUSE_SQUASH_INO(st->ia_ino); + else + fa->ino = st->ia_ino; + + fa->size = st->ia_size; + fa->blocks = st->ia_blocks; + fa->atime = st->ia_atime; + fa->mtime = st->ia_mtime; + fa->ctime = st->ia_ctime; + fa->atimensec = st->ia_atime_nsec; + fa->mtimensec = st->ia_mtime_nsec; + fa->ctimensec = st->ia_ctime_nsec; + fa->mode = st_mode_from_ia (st->ia_prot, st->ia_type); + fa->nlink = st->ia_nlink; + fa->uid = st->ia_uid; + fa->gid = st->ia_gid; + fa->rdev = makedev (ia_major (st->ia_rdev), + ia_minor (st->ia_rdev)); #if FUSE_KERNEL_MINOR_VERSION >= 9 - fa->blksize = st->ia_blksize; + fa->blksize = st->ia_blksize; #endif #ifdef GF_DARWIN_HOST_OS - fa->crtime = (uint64_t)-1; - fa->crtimensec = (uint32_t)-1; - fa->flags = 0; + fa->crtime = (uint64_t)-1; + fa->crtimensec = (uint32_t)-1; + fa->flags = 0; #endif } +void +gf_fuse_fill_dirent (gf_dirent_t *entry, struct fuse_dirent *fde, gf_boolean_t enable_ino32) +{ + if (enable_ino32) + fde->ino = GF_FUSE_SQUASH_INO(entry->d_ino); + else + fde->ino = entry->d_ino; + + fde->off = entry->d_off; + fde->type = entry->d_type; + fde->namelen = strlen (entry->d_name); + strncpy (fde->name, entry->d_name, fde->namelen); +} + static int fuse_do_flip_xattr_ns (char *okey, const char *nns, char **nkey) { @@ -508,3 +575,31 @@ fuse_flip_xattr_ns (fuse_private_t *priv, char *okey, char **nkey) return ret; } + +int +fuse_ignore_xattr_set (fuse_private_t *priv, char *key) +{ + int ret = 0; + + /* don't mess with user namespace */ + if (fnmatch ("user.*", key, FNM_PERIOD) == 0) + goto out; + + if (priv->client_pid != GF_CLIENT_PID_GSYNCD) + goto out; + + /* trusted NS check */ + if (!((fnmatch ("*.glusterfs.*.xtime", key, FNM_PERIOD) == 0) + || (fnmatch ("*.glusterfs.volume-mark", + key, FNM_PERIOD) == 0) + || (fnmatch ("*.glusterfs.volume-mark.*", + key, FNM_PERIOD) == 0))) + ret = -1; + + out: + gf_log ("glusterfs-fuse", GF_LOG_DEBUG, "%s setxattr: key [%s], " + " client pid [%d]", (ret ? "disallowing" : "allowing"), key, + priv->client_pid); + + return ret; +} |
