diff options
Diffstat (limited to 'xlators/nfs/server/src/nfs-common.c')
-rw-r--r-- | xlators/nfs/server/src/nfs-common.c | 379 |
1 files changed, 379 insertions, 0 deletions
diff --git a/xlators/nfs/server/src/nfs-common.c b/xlators/nfs/server/src/nfs-common.c new file mode 100644 index 00000000000..3623f041c14 --- /dev/null +++ b/xlators/nfs/server/src/nfs-common.c @@ -0,0 +1,379 @@ +/* + Copyright (c) 2010 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/>. +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "rpcsvc.h" +#include "dict.h" +#include "xlator.h" +#include "xdr-nfs3.h" +#include "msg-nfs3.h" +#include "iobuf.h" +#include "nfs-common.h" +#include "nfs-fops.h" +#include "rpcsvc.h" +#include "iatt.h" + +#include <libgen.h> + +xlator_t * +nfs_xlid_to_xlator (xlator_list_t *cl, uint8_t xlid) +{ + xlator_t *xl = NULL; + uint8_t id = 0; + + while (id <= xlid) { + if (!cl) { + xl = NULL; + break; + } + + xl = cl->xlator; + cl = cl->next; + id++; + } + + return xl; +} + + +xlator_t * +nfs_path_to_xlator (xlator_list_t *cl, char *path) +{ + return NULL; +} + + +uint16_t +nfs_xlator_to_xlid (xlator_list_t *cl, xlator_t *xl) +{ + uint16_t xlid = 0; + + if ((!cl) || (!xl)) + return 0; + + while (cl) { + if (xl == cl->xlator) + break; + cl = cl->next; + ++xlid; + } + + return xlid; +} + + +xlator_t * +nfs_mntpath_to_xlator (xlator_list_t *cl, char *path) +{ + char volname[MNTPATHLEN]; + char *volptr = NULL; + int pathlen = 0; + xlator_t *targetxl = NULL; + + if ((!cl) || (!path)) + return NULL; + + strcpy (volname, path); + pathlen = strlen (volname); + gf_log (GF_NFS, GF_LOG_TRACE, "Subvolume search: %s", path); + if (volname[0] == '/') + volptr = &volname[1]; + else + volptr = &volname[0]; + + if (volname[pathlen - 1] == '/') + volname[pathlen - 1] = '\0'; + + while (cl) { + if (strcmp (volptr, cl->xlator->name) == 0) { + targetxl = cl->xlator; + break; + } + + cl = cl->next; + } + + return targetxl; + +} + + +/* Returns 1 if the stat seems to be filled with zeroes. */ +int +nfs_zero_filled_stat (struct iatt *buf) +{ + if (!buf) + return 1; + + /* Do not use st_dev because it is transformed to store the xlator id + * in place of the device number. Do not use st_ino because by this time + * 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)) + return 1; + + return 0; +} + + +void +nfs_loc_wipe (loc_t *loc) +{ + if (!loc) + return; + + if (loc->path) { + FREE (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; +} + + +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 = strdup (src->path); + + if (!dst->path) + goto out; + + dst->name = strrchr (dst->path, '/'); + if (dst->name) + dst->name++; + + ret = 0; +out: + return ret; +} + + +int +nfs_loc_fill (loc_t *loc, inode_t *inode, inode_t *parent, char *path) +{ + int ret = -EFAULT; + + if (!loc) + return ret; + + if (inode) { + loc->inode = inode_ref (inode); + loc->ino = inode->ino; + } + + if (parent) + loc->parent = inode_ref (parent); + + loc->path = 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++; + else + goto loc_wipe; + + ret = 0; +loc_wipe: + if (ret < 0) + nfs_loc_wipe (loc); + + return ret; +} + + +int +nfs_inode_loc_fill (inode_t *inode, loc_t *loc) +{ + char *resolvedpath = NULL; + inode_t *parent = NULL; + int ret = -EFAULT; + + if ((!inode) || (!loc)) + return ret; + + if ((inode) && (inode->ino == 1)) + goto ignore_parent; + + parent = inode_parent (inode, 0, NULL); + if (!parent) + goto err; + +ignore_parent: + ret = inode_path (inode, NULL, &resolvedpath); + if (ret < 0) + goto err; + + ret = nfs_loc_fill (loc, inode, parent, resolvedpath); + if (ret < 0) + goto err; + +err: + if (parent) + inode_unref (parent); + + if (resolvedpath) + FREE (resolvedpath); + + return ret; +} + + +int +nfs_ino_loc_fill (inode_table_t *itable, uint64_t ino, uint64_t gen, loc_t *loc) +{ + int ret = -EFAULT; + inode_t *inode = NULL; + + if (!loc) + return ret; + + inode = inode_get (itable, ino, gen); + if (!inode) { + ret = -ENOENT; + goto err; + } + + ret = nfs_inode_loc_fill (inode, loc); + +err: + if (inode) + inode_unref (inode); + return ret; +} + + +int +nfs_parent_inode_loc_fill (inode_t *parent, inode_t *entryinode, char *entry, + loc_t *loc) +{ + int ret = -EFAULT; + char *path = NULL; + + if ((!parent) || (!entry) || (!loc) || (!entryinode)) + return ret; + + ret = inode_path (parent, entry, &path); + if (ret < 0) + goto err; + + ret = nfs_loc_fill (loc, entryinode, parent, path); + +err: + return ret; +} + + +/* Returns -1 if parent is not available, return -2 if the entry is not + * available. In case the return is going to be -2, and how = NFS_RESOLVE_CREATE + * it does however fill in the loc so that it can be used to perform a lookup + * fop for the entry. + * 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, + loc_t *loc, int how) +{ + inode_t *parent = NULL; + inode_t *entryinode = NULL; + int ret = -3; + char *resolvedpath = NULL; + + if ((!itable) || (!entry) || (!loc)) + return ret; + + parent = inode_get (itable, ino, gen); + + ret = -1; + /* Will need hard resolution now */ + if (!parent) + goto err; + + ret = -2; + entryinode = inode_grep (itable, parent, entry); + if (!entryinode) { + if (how != NFS_RESOLVE_CREATE) + goto err; + else { + /* Even though we'll create the inode and the loc for + * a missing inode, we still need to return -2 so + * that the caller can use the filled loc to call + * lookup. + */ + entryinode = inode_new (itable); + nfs_parent_inode_loc_fill (parent, entryinode, entry, + loc); + goto err; + } + } + + ret = inode_path (parent, entry, &resolvedpath); + if (ret < 0) { + ret = -3; + goto err; + } + + ret = nfs_loc_fill (loc, entryinode, parent, resolvedpath); + if (ret < 0) + ret = -3; + +err: + if (parent) + inode_unref (parent); + + if (entryinode) + inode_unref (entryinode); + + if (resolvedpath) + FREE (resolvedpath); + + return ret; +} + + + |