diff options
Diffstat (limited to 'xlators/nfs/server/src/nfs-common.c')
| -rw-r--r-- | xlators/nfs/server/src/nfs-common.c | 269 |
1 files changed, 173 insertions, 96 deletions
diff --git a/xlators/nfs/server/src/nfs-common.c b/xlators/nfs/server/src/nfs-common.c index 9f68f7146..f74396ee8 100644 --- a/xlators/nfs/server/src/nfs-common.c +++ b/xlators/nfs/server/src/nfs-common.c @@ -1,20 +1,11 @@ /* - Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com> + Copyright (c) 2010-2011 Gluster, Inc. <http://www.gluster.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. */ #ifndef _CONFIG_H @@ -88,13 +79,13 @@ nfs_mntpath_to_xlator (xlator_list_t *cl, char *path) { char volname[MNTPATHLEN]; char *volptr = NULL; - int pathlen = 0; + size_t pathlen; xlator_t *targetxl = NULL; if ((!cl) || (!path)) return NULL; - strcpy (volname, path); + strncpy (volname, path, MNTPATHLEN); pathlen = strlen (volname); gf_log (GF_NFS, GF_LOG_TRACE, "Subvolume search: %s", path); if (volname[0] == '/') @@ -102,7 +93,7 @@ nfs_mntpath_to_xlator (xlator_list_t *cl, char *path) else volptr = &volname[0]; - if (volname[pathlen - 1] == '/') + if (pathlen && volname[pathlen - 1] == '/') volname[pathlen - 1] = '\0'; while (cl) { @@ -131,7 +122,7 @@ nfs_zero_filled_stat (struct iatt *buf) * we've already mapped the root ino to 1 so it is not guaranteed to be * 0. */ - if ((buf->ia_nlink == 0) && (buf->ia_type == 0)) + if ((buf->ia_nlink == 0) && (buf->ia_ctime == 0)) return 1; return 0; @@ -141,53 +132,18 @@ nfs_zero_filled_stat (struct iatt *buf) void nfs_loc_wipe (loc_t *loc) { - if (!loc) - return; - - if (loc->path) { - GF_FREE ((char *)loc->path); - loc->path = NULL; - } - - if (loc->parent) { - inode_unref (loc->parent); - loc->parent = NULL; - } - - if (loc->inode) { - inode_unref (loc->inode); - loc->inode = NULL; - } - - loc->ino = 0; + loc_wipe (loc); } int nfs_loc_copy (loc_t *dst, loc_t *src) { - int ret = -1; - - dst->ino = src->ino; - - if (src->inode) - dst->inode = inode_ref (src->inode); - - if (src->parent) - dst->parent = inode_ref (src->parent); - - dst->path = gf_strdup (src->path); + int ret = -1; - if (!dst->path) - goto out; + ret = loc_copy (dst, src); - dst->name = strrchr (dst->path, '/'); - if (dst->name) - dst->name++; - - ret = 0; -out: - return ret; + return ret; } @@ -201,24 +157,24 @@ nfs_loc_fill (loc_t *loc, inode_t *inode, inode_t *parent, char *path) if (inode) { loc->inode = inode_ref (inode); - loc->ino = inode->ino; + if (!uuid_is_null (inode->gfid)) + uuid_copy (loc->gfid, inode->gfid); } if (parent) loc->parent = inode_ref (parent); - loc->path = gf_strdup (path); - if (!loc->path) { - gf_log (GF_NFS, GF_LOG_ERROR, "strdup failed"); - goto loc_wipe; + if (path) { + loc->path = gf_strdup (path); + if (!loc->path) { + gf_log (GF_NFS, GF_LOG_ERROR, "strdup failed"); + goto loc_wipe; + } + loc->name = strrchr (loc->path, '/'); + if (loc->name) + loc->name++; } - loc->name = strrchr (loc->path, '/'); - if (loc->name) - loc->name++; - else - goto loc_wipe; - ret = 0; loc_wipe: if (ret < 0) @@ -229,7 +185,7 @@ loc_wipe: int -nfs_inode_loc_fill (inode_t *inode, loc_t *loc) +nfs_inode_loc_fill (inode_t *inode, loc_t *loc, int how) { char *resolvedpath = NULL; inode_t *parent = NULL; @@ -238,35 +194,47 @@ nfs_inode_loc_fill (inode_t *inode, loc_t *loc) if ((!inode) || (!loc)) return ret; - if ((inode) && (inode->ino == 1)) - goto ignore_parent; - - parent = inode_parent (inode, 0, NULL); - if (!parent) - goto err; + /* If gfid is not null, then the inode is already linked to + * the inode table, and not a newly created one. For newly + * created inode, inode_path returns null gfid as the path. + */ + if (!uuid_is_null (inode->gfid)) { + ret = inode_path (inode, NULL, &resolvedpath); + if (ret < 0) { + gf_log (GF_NFS, GF_LOG_ERROR, "path resolution failed " + "%s", resolvedpath); + goto err; + } + } -ignore_parent: - ret = inode_path (inode, NULL, &resolvedpath); - if (ret < 0) - goto err; + if (resolvedpath == NULL) { + char tmp_path[GFID_STR_PFX_LEN + 1] = {0,}; + snprintf (tmp_path, sizeof (tmp_path), "<gfid:%s>", + uuid_utoa (loc->gfid)); + resolvedpath = gf_strdup (tmp_path); + } else { + parent = inode_parent (inode, loc->pargfid, NULL); + } ret = nfs_loc_fill (loc, inode, parent, resolvedpath); - if (ret < 0) + if (ret < 0) { + gf_log (GF_NFS, GF_LOG_ERROR, "loc fill resolution failed %s", + resolvedpath); goto err; + } + ret = 0; err: if (parent) inode_unref (parent); - if (resolvedpath) - GF_FREE (resolvedpath); + GF_FREE (resolvedpath); return ret; } - int -nfs_ino_loc_fill (inode_table_t *itable, uint64_t ino, uint64_t gen, loc_t *loc) +nfs_gfid_loc_fill (inode_table_t *itable, uuid_t gfid, loc_t *loc, int how) { int ret = -EFAULT; inode_t *inode = NULL; @@ -274,13 +242,35 @@ nfs_ino_loc_fill (inode_table_t *itable, uint64_t ino, uint64_t gen, loc_t *loc) if (!loc) return ret; - inode = inode_get (itable, ino, gen); + inode = inode_find (itable, gfid); if (!inode) { - ret = -ENOENT; - goto err; - } + gf_log (GF_NFS, GF_LOG_TRACE, "Inode not found in itable, will try to create one."); + if (how == NFS_RESOLVE_CREATE) { + gf_log (GF_NFS, GF_LOG_TRACE, "Inode needs to be created."); + inode = inode_new (itable); + if (!inode) { + gf_log (GF_NFS, GF_LOG_ERROR, "Failed to " + "allocate memory"); + ret = -ENOMEM; + goto err; + } + + } else { + gf_log (GF_NFS, GF_LOG_ERROR, "Inode not found in itable and no creation was requested."); + ret = -ENOENT; + goto err; + } + } else { + gf_log (GF_NFS, GF_LOG_TRACE, "Inode was found in the itable."); + } - ret = nfs_inode_loc_fill (inode, loc); + uuid_copy (loc->gfid, gfid); + + ret = nfs_inode_loc_fill (inode, loc, how); + if (ret < 0) { + gf_log (GF_NFS, GF_LOG_ERROR, "Inode loc filling failed.: %s", strerror (-ret)); + goto err; + } err: if (inode) @@ -290,6 +280,17 @@ err: int +nfs_root_loc_fill (inode_table_t *itable, loc_t *loc) +{ + uuid_t rootgfid = {0, }; + + rootgfid[15] = 1; + return nfs_gfid_loc_fill (itable, rootgfid, loc, NFS_RESOLVE_EXIST); +} + + + +int nfs_parent_inode_loc_fill (inode_t *parent, inode_t *entryinode, char *entry, loc_t *loc) { @@ -300,11 +301,14 @@ nfs_parent_inode_loc_fill (inode_t *parent, inode_t *entryinode, char *entry, return ret; ret = inode_path (parent, entry, &path); - if (ret < 0) + if (ret < 0) { + gf_log (GF_NFS, GF_LOG_ERROR, "path resolution failed %s", + path); goto err; + } ret = nfs_loc_fill (loc, entryinode, parent, path); - + GF_FREE (path); err: return ret; } @@ -317,7 +321,7 @@ err: * On other errors, return -3. 0 on success. */ int -nfs_entry_loc_fill (inode_table_t *itable, ino_t ino, uint64_t gen, char *entry, +nfs_entry_loc_fill (inode_table_t *itable, uuid_t pargfid, char *entry, loc_t *loc, int how) { inode_t *parent = NULL; @@ -329,13 +333,15 @@ nfs_entry_loc_fill (inode_table_t *itable, ino_t ino, uint64_t gen, char *entry, if ((!itable) || (!entry) || (!loc)) return ret; - parent = inode_get (itable, ino, gen); + parent = inode_find (itable, pargfid); ret = -1; /* Will need hard resolution now */ if (!parent) goto err; + uuid_copy (loc->pargfid, pargfid); + ret = -2; entryinode = inode_grep (itable, parent, entry); if (!entryinode) { @@ -363,13 +369,18 @@ nfs_entry_loc_fill (inode_table_t *itable, ino_t ino, uint64_t gen, char *entry, ret = inode_path (parent, entry, &resolvedpath); if (ret < 0) { + gf_log (GF_NFS, GF_LOG_ERROR, "path resolution failed %s", + resolvedpath); ret = -3; goto err; } ret = nfs_loc_fill (loc, entryinode, parent, resolvedpath); - if (ret < 0) + if (ret < 0) { + gf_log (GF_NFS, GF_LOG_ERROR, "loc_fill failed %s", + resolvedpath); ret = -3; + } err: if (parent) @@ -378,11 +389,77 @@ err: if (entryinode) inode_unref (entryinode); - if (resolvedpath) - GF_FREE (resolvedpath); + GF_FREE (resolvedpath); return ret; } +uint32_t +nfs_hash_gfid (uuid_t gfid) +{ + uint32_t hash = 0; + uint64_t msb64 = 0; + uint64_t lsb64 = 0; + uint32_t a1 = 0; + uint32_t a2 = 0; + uint32_t a3 = 0; + uint32_t a4 = 0; + uint32_t b1 = 0; + uint32_t b2 = 0; + + if (__is_root_gfid (gfid)) + return 0x1; + + memcpy (&msb64, &gfid[8], 8); + memcpy (&lsb64, &gfid[0], 8); + + a1 = (msb64 << 32); + a2 = (msb64 >> 32); + a3 = (lsb64 << 32); + a4 = (lsb64 >> 32); + + b1 = a1 ^ a4; + b2 = a2 ^ a3; + + hash = b1 ^ b2; + + return hash; +} + + +void +nfs_fix_generation (xlator_t *this, inode_t *inode) +{ + uint64_t raw_ctx = 0; + struct nfs_inode_ctx *ictx = NULL; + struct nfs_state *priv = NULL; + int ret = -1; + if (!inode) { + return; + } + priv = this->private; + + if (inode_ctx_get(inode,this,&raw_ctx) == 0) { + ictx = (struct nfs_inode_ctx *)raw_ctx; + ictx->generation = priv->generation; + } + else { + ictx = GF_CALLOC (1, sizeof (struct nfs_inode_ctx), + gf_nfs_mt_inode_ctx); + if (!ictx) { + gf_log (this->name, GF_LOG_ERROR, + "could not allocate nfs inode ctx"); + return; + } + INIT_LIST_HEAD(&ictx->shares); + ictx->generation = priv->generation; + ret = inode_ctx_put (inode, this, (uint64_t)ictx); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "could not store nfs inode ctx"); + return; + } + } +} |
