nfs: Add generic nfs translator
Signed-off-by: Shehjar Tikoo <shehjart@gluster.com> Signed-off-by: Anand V. Avati <avati@dev.gluster.com> BUG: 399 (NFS translator with Mount v3 and NFS v3 support) URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=399
This commit is contained in:
parent
8b2949db0d
commit
c4fd1cf732
@ -110,6 +110,8 @@ AC_CONFIG_FILES([Makefile
|
||||
xlators/nfs/Makefile
|
||||
xlators/nfs/lib/Makefile
|
||||
xlators/nfs/lib/src/Makefile
|
||||
xlators/nfs/server/Makefile
|
||||
xlators/nfs/server/src/Makefile
|
||||
glusterfs.spec])
|
||||
|
||||
AC_CANONICAL_HOST
|
||||
|
@ -1,3 +1,3 @@
|
||||
SUBDIRS = lib
|
||||
SUBDIRS = lib server
|
||||
|
||||
CLEANFILES =
|
||||
|
3
xlators/nfs/server/Makefile.am
Normal file
3
xlators/nfs/server/Makefile.am
Normal file
@ -0,0 +1,3 @@
|
||||
SUBDIRS = src
|
||||
|
||||
CLEANFILES =
|
14
xlators/nfs/server/src/Makefile.am
Normal file
14
xlators/nfs/server/src/Makefile.am
Normal file
@ -0,0 +1,14 @@
|
||||
xlator_LTLIBRARIES = server.la
|
||||
xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/nfs
|
||||
rpclibdir = $(top_srcdir)/xlators/nfs/lib/src/
|
||||
server_la_LDFLAGS = -module -avoidversion
|
||||
server_la_SOURCES = nfs.c nfs-common.c nfs-fops.c nfs-inodes.c nfs-generics.c
|
||||
server_la_LIBADD = $(top_builddir)/xlators/nfs/lib/src/librpcsvc.la $(top_builddir)/libglusterfs/src/libglusterfs.la
|
||||
|
||||
noinst_HEADERS = nfs.h nfs-common.h nfs-fops.h nfs-inodes.h nfs-generics.h
|
||||
|
||||
AM_CFLAGS = -fPIC -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -Wall -D$(GF_HOST_OS)\
|
||||
-I$(top_srcdir)/libglusterfs/src -shared -nostartfiles $(GF_CFLAGS)\
|
||||
-I$(rpclibdir) -L$(xlatordir)/ -I$(CONTRIBDIR)/rbtree
|
||||
|
||||
CLEANFILES =
|
379
xlators/nfs/server/src/nfs-common.c
Normal file
379
xlators/nfs/server/src/nfs-common.c
Normal file
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
76
xlators/nfs/server/src/nfs-common.h
Normal file
76
xlators/nfs/server/src/nfs-common.h
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
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 _NFS_COMMON_H_
|
||||
#define _NFS_COMMON_H_
|
||||
|
||||
#ifndef _CONFIG_H
|
||||
#define _CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include "xlator.h"
|
||||
#include "rpcsvc.h"
|
||||
#include "iatt.h"
|
||||
|
||||
#define NFS_PATH_MAX PATH_MAX
|
||||
#define NFS_NAME_MAX NAME_MAX
|
||||
|
||||
#define NFS_DEFAULT_CREATE_MODE 0644
|
||||
|
||||
extern xlator_t *
|
||||
nfs_xlid_to_xlator (xlator_list_t *cl, uint8_t xlid);
|
||||
|
||||
extern uint16_t
|
||||
nfs_xlator_to_xlid (xlator_list_t *cl, xlator_t *xl);
|
||||
|
||||
extern xlator_t *
|
||||
nfs_path_to_xlator (xlator_list_t *cl, char *path);
|
||||
|
||||
extern xlator_t *
|
||||
nfs_mntpath_to_xlator (xlator_list_t *cl, char *path);
|
||||
|
||||
extern int
|
||||
nfs_zero_filled_stat (struct iatt *buf);
|
||||
|
||||
extern void
|
||||
nfs_loc_wipe (loc_t *loc);
|
||||
|
||||
extern int
|
||||
nfs_loc_copy (loc_t *dst, loc_t *src);
|
||||
|
||||
extern int
|
||||
nfs_loc_fill (loc_t *loc, inode_t *inode, inode_t *parent, char *path);
|
||||
|
||||
#define NFS_RESOLVE_EXIST 1
|
||||
#define NFS_RESOLVE_CREATE 2
|
||||
|
||||
extern int
|
||||
nfs_inode_loc_fill (inode_t *inode, loc_t *loc);
|
||||
|
||||
extern int
|
||||
nfs_ino_loc_fill (inode_table_t *itable, uint64_t ino, uint64_t gen, loc_t *l);
|
||||
|
||||
extern int
|
||||
nfs_entry_loc_fill (inode_table_t *itable, ino_t ino, uint64_t gen, char *entry,
|
||||
loc_t *loc, int how);
|
||||
|
||||
#endif
|
1441
xlators/nfs/server/src/nfs-fops.c
Normal file
1441
xlators/nfs/server/src/nfs-fops.c
Normal file
File diff suppressed because it is too large
Load Diff
259
xlators/nfs/server/src/nfs-fops.h
Normal file
259
xlators/nfs/server/src/nfs-fops.h
Normal file
@ -0,0 +1,259 @@
|
||||
/*
|
||||
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 _NFS_FOPS_H_
|
||||
#define _NFS_FOPS_H_
|
||||
|
||||
#ifndef _CONFIG_H
|
||||
#define _CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "dict.h"
|
||||
#include "xlator.h"
|
||||
#include "iobuf.h"
|
||||
#include "call-stub.h"
|
||||
#include "stack.h"
|
||||
#include "nfs.h"
|
||||
#include "nfs-common.h"
|
||||
#include <semaphore.h>
|
||||
|
||||
/* This structure used to communicate state between a fop and its callback.
|
||||
* The problem is, when we're calling a fop in the nfs op handler, the callback
|
||||
* is the NFS protocol's callback and we have to perform all GlusterFS
|
||||
* inode, inode table, fd_ts and fd table operations in the NFS callback. That
|
||||
* approach soon gets extremely complicated and confusing because, then we have
|
||||
* to try and separate in our heads which source lines in those callbacks are
|
||||
* required for serving the NFS op and which ones are needed for satisfying
|
||||
* GlusterFS requirements. This structure allows us avoid performing GlusterFS
|
||||
* state maintenance operations inside the fops layer itself. Now, before
|
||||
* we call the callback registered by the NFS operation, a hidden fops-layer
|
||||
* specific callback is called which performs the state maintenance and then
|
||||
* calls the NFS callback.
|
||||
*
|
||||
* These are allocated from a mem-pool stored in the nfs xlator's state.
|
||||
* i.e. struct nfs_state.
|
||||
* That is initiated in nfs_init_subvolumes in nfs.c.
|
||||
*/
|
||||
struct nfs_fop_local {
|
||||
/* The local sent along by the user of the fop. */
|
||||
void *proglocal;
|
||||
|
||||
/* The address of the callback supplied by the user. After our
|
||||
* callback is executed this one is called.
|
||||
* The exact cast destination of this pointer will depend on the
|
||||
* fop that is being called.
|
||||
*/
|
||||
void *progcbk;
|
||||
|
||||
/* Used only for write requests. */
|
||||
struct iobref *iobref;
|
||||
|
||||
inode_t *parent;
|
||||
inode_t *newparent;
|
||||
inode_t *inode;
|
||||
|
||||
/* Set to 1 by nfs-inodes layer, which uses this to decide whether to
|
||||
* link the newly allocated inode into the itable, in case the fop was
|
||||
* successful.
|
||||
*/
|
||||
int newinode;
|
||||
|
||||
/* Used by nfs-fops layer in order to determine whether to funge the
|
||||
* ino in a dir's stbuf. This funging of root ino is needed to ensure
|
||||
* that the root ino remains 1 even when the NFS server has been
|
||||
* restarted. Note that in distribute, a fresh lookup and a revalidate
|
||||
* on the root inode returns two different inode numbers and this we
|
||||
* need to handle by ourself.
|
||||
*/
|
||||
int rootinode;
|
||||
|
||||
/* This member is used to determine whether the new parent of a file
|
||||
* being renamed is the root directory. If yes, the ino is funged.
|
||||
*/
|
||||
int newrootinode;
|
||||
int newrootparentinode;
|
||||
|
||||
/* Determines whether to funge the ino in the post and pre parent
|
||||
* stbufs for a file/dir where the parent directory could be the root
|
||||
* dir. Needed here because of the same reason as above.
|
||||
*/
|
||||
int rootparentinode;
|
||||
|
||||
char path[NFS_NAME_MAX];
|
||||
char newpath[NFS_NAME_MAX];
|
||||
};
|
||||
|
||||
extern struct nfs_fop_local *
|
||||
nfs_fop_local_init (xlator_t *xl);
|
||||
|
||||
extern void
|
||||
nfs_fop_local_wipe (xlator_t *xl, struct nfs_fop_local *l);
|
||||
|
||||
#define xlator_top_private(xl) ((struct nfs_state *)((xlator_t *)(xl)->ctx->top)->private)
|
||||
|
||||
#define prog_data_to_nfl(xla, nflocal, fram, pcbk, plocal) \
|
||||
do { \
|
||||
nflocal = nfs_fop_local_init (xla); \
|
||||
if (nflocal) { \
|
||||
nflocal->proglocal = plocal; \
|
||||
nflocal->progcbk = pcbk; \
|
||||
if (fram) \
|
||||
((call_frame_t *)fram)->local = nflocal; \
|
||||
} \
|
||||
} while (0) \
|
||||
|
||||
|
||||
|
||||
#define nfl_to_prog_data(xla, nflocal, pcbk, fram) \
|
||||
do { \
|
||||
nflocal = fram->local; \
|
||||
fram->local = nflocal->proglocal; \
|
||||
pcbk = nflocal->progcbk; \
|
||||
nfs_fop_local_wipe (xla, nflocal); \
|
||||
} while (0) \
|
||||
|
||||
#define nfs_fop_handle_local_init(fram, xla, nfloc, cbck,prgloc,retval,lab) \
|
||||
do { \
|
||||
prog_data_to_nfl (xla, nfloc, fram, cbck, prgloc); \
|
||||
if (!nfloc) { \
|
||||
gf_log (GF_NFS,GF_LOG_ERROR,"Failed to init local");\
|
||||
retval = -ENOMEM; \
|
||||
goto lab; \
|
||||
} \
|
||||
} while (0) \
|
||||
|
||||
extern int
|
||||
nfs_fop_fstat (xlator_t *xl, nfs_user_t *nfu, fd_t *fd,
|
||||
fop_stat_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_fop_readdirp (xlator_t *xl, nfs_user_t *nfu, fd_t *dirfd,
|
||||
size_t bufsize, off_t offset, fop_readdir_cbk_t cbk,
|
||||
void *local);
|
||||
extern int
|
||||
nfs_fop_lookup (xlator_t *xl, nfs_user_t *nfu, loc_t *loc,
|
||||
fop_lookup_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_fop_create (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc, int flags,
|
||||
mode_t mode, fd_t *fd, fop_create_cbk_t cbk, void *local);
|
||||
extern int
|
||||
nfs_fop_flush (xlator_t *xl, nfs_user_t *nfu, fd_t *fd,
|
||||
fop_flush_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_fop_mkdir (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc, mode_t mode,
|
||||
fop_mkdir_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_fop_truncate (xlator_t *xl, nfs_user_t *nfu, loc_t *loc, off_t offset,
|
||||
fop_truncate_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_fop_read (xlator_t *xl, nfs_user_t *nfu, fd_t *fd, size_t size,
|
||||
off_t offset, fop_readv_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_fop_fsync (xlator_t *xl, nfs_user_t *nfu, fd_t *fd, int32_t datasync,
|
||||
fop_fsync_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_fop_write (xlator_t *xl, nfs_user_t *nfu, fd_t *fd, struct iobuf *srciob,
|
||||
struct iovec *vector, int32_t count, off_t offset,
|
||||
fop_writev_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_fop_open (xlator_t *xl, nfs_user_t *nfu, loc_t *loc, int32_t flags,
|
||||
fd_t *fd, int32_t wbflags, fop_open_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_fop_rename (xlator_t *xl, nfs_user_t *nfu, loc_t *oldloc,
|
||||
loc_t *newloc, fop_rename_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_fop_link (xlator_t *xl, nfs_user_t *nfu, loc_t *oldloc, loc_t *newloc,
|
||||
fop_link_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_fop_unlink (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
|
||||
fop_unlink_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_fop_rmdir (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
|
||||
fop_rmdir_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_fop_mknod (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc, mode_t mode,
|
||||
dev_t dev, fop_mknod_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_fop_readlink (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
|
||||
size_t size, fop_readlink_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_fop_symlink (xlator_t *xl, nfs_user_t *nfu, char *target,
|
||||
loc_t *pathloc, fop_symlink_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_fop_setattr (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
|
||||
struct iatt *buf, int32_t valid, fop_setattr_cbk_t cbk,
|
||||
void *local);
|
||||
|
||||
extern int
|
||||
nfs_fop_statfs (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
|
||||
fop_statfs_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_fop_opendir (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,fd_t *dirfd,
|
||||
fop_opendir_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_fop_stat (xlator_t *xl, nfs_user_t *nfu, loc_t *loc,
|
||||
fop_stat_cbk_t cbk, void *local);
|
||||
|
||||
/* Synchronous equivalents of some of the fops above.
|
||||
*/
|
||||
|
||||
/* sfl = sync fop local
|
||||
* Structure used to turn async fops into sync calls for certain NFS ops
|
||||
* that need blocking operations.
|
||||
*/
|
||||
typedef struct nfs_syncfop {
|
||||
sem_t replysig;
|
||||
call_stub_t *replystub;
|
||||
} nfs_syncfop_t;
|
||||
|
||||
extern nfs_syncfop_t *
|
||||
nfs_syncfop_init ();
|
||||
|
||||
extern call_stub_t *
|
||||
nfs_syncfop_wait (nfs_syncfop_t *s);
|
||||
|
||||
extern void
|
||||
nfs_syncfop_notify (nfs_syncfop_t *s);
|
||||
|
||||
extern call_stub_t *
|
||||
nfs_fop_lookup_sync (xlator_t *xl, nfs_user_t *nfu, loc_t *loc);
|
||||
|
||||
extern call_stub_t *
|
||||
nfs_fop_readdirp_sync (xlator_t *fopxl, nfs_user_t *nfu, fd_t *dirfd,
|
||||
off_t offset, size_t bufsize);
|
||||
|
||||
#endif
|
1067
xlators/nfs/server/src/nfs-generics.c
Normal file
1067
xlators/nfs/server/src/nfs-generics.c
Normal file
File diff suppressed because it is too large
Load Diff
174
xlators/nfs/server/src/nfs-generics.h
Normal file
174
xlators/nfs/server/src/nfs-generics.h
Normal file
@ -0,0 +1,174 @@
|
||||
/*
|
||||
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 _NFS_GENERICS_H_
|
||||
#define _NFS_GENERICS_H_
|
||||
|
||||
#ifndef _CONFIG_H
|
||||
#define _CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "nfs.h"
|
||||
#include "xlator.h"
|
||||
#include "nfs-fops.h"
|
||||
#include "nfs-inodes.h"
|
||||
|
||||
struct nfs_direntcache {
|
||||
gf_dirent_t entries; /* Head of list of cached dirents. */
|
||||
gf_dirent_t *next; /* Pointer to the next entry that
|
||||
* should be sent by readdir */
|
||||
uint64_t prev_off; /* Offset where the next read will
|
||||
* happen.
|
||||
*/
|
||||
};
|
||||
|
||||
/* WE're trying to abstract the fops interface from the NFS xlator so that
|
||||
* different NFS versions can simply call a standard interface and have fop
|
||||
* interface dependent functions be handled internally.
|
||||
* This structure is part of such an abstraction. The fops layer stores any
|
||||
* state is requires in the fd. For eg, the dirent cache for a directory fd_t.
|
||||
*/
|
||||
typedef struct nfs_fop_fdcontext {
|
||||
pthread_mutex_t lock;
|
||||
size_t dirent_bufsize;
|
||||
off_t offset;
|
||||
struct nfs_direntcache *dcache;
|
||||
xlator_t *dirvol;
|
||||
} nfs_fdctx_t;
|
||||
|
||||
extern int
|
||||
nfs_fstat (xlator_t *xl, nfs_user_t *nfu, fd_t *fd, fop_stat_cbk_t cbk,
|
||||
void *local);
|
||||
|
||||
extern int
|
||||
nfs_readdirp (xlator_t *xl, nfs_user_t *nfu, fd_t *dirfd, size_t bufsize,
|
||||
off_t offset, fop_readdir_cbk_t cbk, void *local);
|
||||
|
||||
|
||||
extern int
|
||||
nfs_lookup (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
|
||||
fop_lookup_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_create (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc, int flags,
|
||||
mode_t mode, fop_create_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_flush (xlator_t *xl, nfs_user_t *nfu, fd_t *fd, fop_flush_cbk_t cbk,
|
||||
void *local);
|
||||
|
||||
extern int
|
||||
nfs_mkdir (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc, mode_t mode,
|
||||
fop_mkdir_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_truncate (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc, off_t offset,
|
||||
fop_truncate_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_read (xlator_t *xl, nfs_user_t *nfu, fd_t *fd, size_t size,
|
||||
off_t offset, fop_readv_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_fsync (xlator_t *xl, nfs_user_t *nfu, fd_t *fd, int32_t datasync,
|
||||
fop_fsync_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_write (xlator_t *xl, nfs_user_t *nfu, fd_t *fd, struct iobuf *srciob,
|
||||
struct iovec *vector, int32_t count, off_t offset,
|
||||
fop_writev_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_open (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc, int32_t flags,
|
||||
fop_open_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_rename (xlator_t *xl, nfs_user_t *nfu, loc_t *oldloc, loc_t *newloc,
|
||||
fop_rename_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_link (xlator_t *xl, nfs_user_t *nfu, loc_t *oldloc, loc_t *newloc,
|
||||
fop_link_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_unlink (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
|
||||
fop_unlink_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_rmdir (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
|
||||
fop_rmdir_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_mknod (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc, mode_t mode,
|
||||
dev_t dev, fop_mknod_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_readlink (xlator_t *xl, nfs_user_t *nfu, loc_t *linkloc,
|
||||
fop_readlink_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_setattr (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
|
||||
struct iatt *buf, int32_t valid, fop_setattr_cbk_t cbk,
|
||||
void *local);
|
||||
|
||||
extern int
|
||||
nfs_statfs (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
|
||||
fop_statfs_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_stat (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc, fop_stat_cbk_t cbk
|
||||
, void *local);
|
||||
|
||||
extern int
|
||||
nfs_symlink (xlator_t *xl, nfs_user_t *nfu, char *target, loc_t *linkloc,
|
||||
fop_symlink_cbk_t cbk, void *local);
|
||||
|
||||
/* Synchronous equivalents */
|
||||
|
||||
extern call_stub_t *
|
||||
nfs_open_sync (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
|
||||
int32_t flags);
|
||||
|
||||
extern int
|
||||
nfs_readdir_sync (xlator_t *nfsx, xlator_t *fopxl, nfs_user_t *nfu,
|
||||
fd_t *dirfd, gf_dirent_t *entry);
|
||||
|
||||
extern call_stub_t *
|
||||
nfs_flush_sync (xlator_t *xl, nfs_user_t *nfu, fd_t *fd);
|
||||
|
||||
extern call_stub_t *
|
||||
nfs_write_sync (xlator_t *xl, nfs_user_t *nfu, fd_t *fd, struct iobuf *srciob,
|
||||
struct iovec *vec, int count, off_t offset);
|
||||
|
||||
extern call_stub_t *
|
||||
nfs_fsync_sync (xlator_t *xl, nfs_user_t *nfu, fd_t *fd, int32_t datasync);
|
||||
|
||||
extern call_stub_t *
|
||||
nfs_read_sync (xlator_t *xl, nfs_user_t *nfu, fd_t *fd, size_t size,
|
||||
off_t offset);
|
||||
|
||||
extern call_stub_t *
|
||||
nfs_opendir_sync (xlator_t *nfsx, xlator_t *fopxl, nfs_user_t *nfu,
|
||||
loc_t *dirloc, size_t bufsize);
|
||||
|
||||
extern int
|
||||
nfs_opendir (xlator_t *fopxl, nfs_user_t *nfu, loc_t *pathloc,
|
||||
fop_opendir_cbk_t cbk, void *local);
|
||||
#endif
|
571
xlators/nfs/server/src/nfs-inodes.c
Normal file
571
xlators/nfs/server/src/nfs-inodes.c
Normal file
@ -0,0 +1,571 @@
|
||||
/*
|
||||
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 "string.h"
|
||||
|
||||
#include "inode.h"
|
||||
#include "nfs.h"
|
||||
#include "nfs-inodes.h"
|
||||
#include "nfs-fops.h"
|
||||
#include "xlator.h"
|
||||
|
||||
#include <libgen.h>
|
||||
|
||||
void
|
||||
nfl_inodes_init (struct nfs_fop_local *nfl, inode_t *inode, inode_t *parent,
|
||||
inode_t *newparent, const char *name, const char *newname)
|
||||
{
|
||||
if (!nfl)
|
||||
return;
|
||||
|
||||
if (inode)
|
||||
nfl->inode = inode_ref (inode);
|
||||
|
||||
if (parent)
|
||||
nfl->parent = inode_ref (parent);
|
||||
|
||||
if (newparent)
|
||||
nfl->newparent = inode_ref (newparent);
|
||||
|
||||
if (name)
|
||||
strcpy (nfl->path, name);
|
||||
|
||||
if (newname)
|
||||
strcpy (nfl->newpath, newname);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int32_t
|
||||
nfs_inode_create_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
|
||||
int32_t op_ret, int32_t op_errno, fd_t *fd, inode_t *inode
|
||||
, struct iatt *buf, struct iatt *preparent,
|
||||
struct iatt *postparent)
|
||||
{
|
||||
struct nfs_fop_local *nfl = frame->local;
|
||||
fop_create_cbk_t progcbk = NULL;
|
||||
|
||||
if (op_ret == -1)
|
||||
goto do_not_link;
|
||||
|
||||
inode_link (inode, nfl->parent, nfl->path, buf);
|
||||
|
||||
do_not_link:
|
||||
/* NFS does not need it, upper layers should not expect the pointer to
|
||||
* be a valid fd.
|
||||
*/
|
||||
fd_unref (fd);
|
||||
|
||||
nfl_to_prog_data (this, nfl, progcbk, frame);
|
||||
if (progcbk)
|
||||
progcbk (frame, cookie, this, op_ret, op_errno, fd, inode, buf,
|
||||
preparent, postparent);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
nfs_inode_create (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc, int flags,
|
||||
int mode, fop_create_cbk_t cbk, void *local)
|
||||
{
|
||||
struct nfs_fop_local *nfl = NULL;
|
||||
int ret = -EFAULT;
|
||||
fd_t *newfd = NULL;
|
||||
|
||||
if ((!xl) || (!pathloc) || (!nfu))
|
||||
return ret;
|
||||
|
||||
nfs_fop_handle_local_init (NULL, xl, nfl, cbk, local, ret, err);
|
||||
|
||||
newfd = fd_create (pathloc->inode, 0);
|
||||
if (!newfd) {
|
||||
gf_log (GF_NFS, GF_LOG_ERROR, "Failed to create new fd");
|
||||
ret = -ENOMEM;
|
||||
goto wipe_nfl;
|
||||
}
|
||||
|
||||
/* The parent and base name will be needed to link the new inode
|
||||
* into the inode table.
|
||||
*/
|
||||
nfl_inodes_init (nfl, pathloc->inode, pathloc->parent, NULL,
|
||||
pathloc->name, NULL);
|
||||
ret = nfs_fop_create (xl, nfu, pathloc, flags, mode, newfd,
|
||||
nfs_inode_create_cbk, nfl);
|
||||
wipe_nfl:
|
||||
if (ret < 0)
|
||||
nfs_fop_local_wipe (xl, nfl);
|
||||
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int32_t
|
||||
nfs_inode_mkdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
|
||||
int32_t op_ret, int32_t op_errno, inode_t *inode,
|
||||
struct iatt *buf, struct iatt *preparent,
|
||||
struct iatt *postparent)
|
||||
{
|
||||
struct nfs_fop_local *nfl = frame->local;
|
||||
fop_mkdir_cbk_t progcbk = NULL;
|
||||
|
||||
if (op_ret == -1)
|
||||
goto do_not_link;
|
||||
|
||||
inode_link (inode, nfl->parent, nfl->path, buf);
|
||||
|
||||
do_not_link:
|
||||
nfl_to_prog_data (this, nfl, progcbk, frame);
|
||||
if (progcbk)
|
||||
progcbk (frame, cookie, this, op_ret, op_errno, inode, buf,
|
||||
preparent, postparent);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nfs_inode_mkdir (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc, int mode,
|
||||
fop_mkdir_cbk_t cbk, void *local)
|
||||
{
|
||||
struct nfs_fop_local *nfl = NULL;
|
||||
int ret = -EFAULT;
|
||||
|
||||
if ((!xl) || (!pathloc) || (!nfu))
|
||||
return ret;
|
||||
|
||||
nfs_fop_handle_local_init (NULL, xl, nfl, cbk, local, ret, err);
|
||||
nfl_inodes_init (nfl, pathloc->inode, pathloc->parent, NULL,
|
||||
pathloc->name, NULL);
|
||||
ret = nfs_fop_mkdir (xl, nfu, pathloc, mode, nfs_inode_mkdir_cbk,
|
||||
nfl);
|
||||
if (ret < 0)
|
||||
nfs_fop_local_wipe (xl, nfl);
|
||||
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int32_t
|
||||
nfs_inode_open_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
|
||||
int32_t op_ret, int32_t op_errno, fd_t *fd)
|
||||
{
|
||||
|
||||
struct nfs_fop_local *nfl = NULL;
|
||||
fop_open_cbk_t progcbk = NULL;
|
||||
|
||||
if ((op_ret == -1) && (fd))
|
||||
fd_unref (fd);
|
||||
/* Not needed here since the fd is cached in higher layers and the bind
|
||||
* must happen atomically when the fd gets added to the fd LRU.
|
||||
*/
|
||||
/* else
|
||||
fd_bind (fd);
|
||||
*/
|
||||
nfl_to_prog_data (this, nfl, progcbk, frame);
|
||||
if (progcbk)
|
||||
progcbk (frame, cookie, this, op_ret, op_errno, fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
nfs_inode_open (xlator_t *xl, nfs_user_t *nfu, loc_t *loc, int32_t flags,
|
||||
int32_t wbflags, fop_open_cbk_t cbk, void *local)
|
||||
{
|
||||
struct nfs_fop_local *nfl = NULL;
|
||||
fd_t *newfd = NULL;
|
||||
int ret = -EFAULT;
|
||||
|
||||
if ((!xl) || (!loc) || (!nfu))
|
||||
return ret;
|
||||
|
||||
newfd = fd_create (loc->inode, 0);
|
||||
if (!newfd) {
|
||||
gf_log (GF_NFS, GF_LOG_ERROR, "Failed to create fd");
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
nfs_fop_handle_local_init (NULL, xl, nfl, cbk, local, ret, fd_err);
|
||||
ret = nfs_fop_open (xl, nfu, loc, flags, newfd, wbflags,
|
||||
nfs_inode_open_cbk, nfl);
|
||||
|
||||
if (ret < 0)
|
||||
nfs_fop_local_wipe (xl, nfl);
|
||||
|
||||
fd_err:
|
||||
if (ret < 0)
|
||||
if (newfd)
|
||||
fd_unref (newfd);
|
||||
|
||||
err:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int32_t
|
||||
nfs_inode_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
|
||||
int32_t op_ret, int32_t op_errno, struct iatt *buf,
|
||||
struct iatt *preoldparent, struct iatt *postoldparent,
|
||||
struct iatt *prenewparent, struct iatt *postnewparent)
|
||||
{
|
||||
struct nfs_fop_local *nfl = NULL;
|
||||
fop_rename_cbk_t progcbk = NULL;
|
||||
|
||||
nfl = frame->local;
|
||||
if (op_ret == -1)
|
||||
goto do_not_link;
|
||||
|
||||
inode_rename (this->itable, nfl->parent, nfl->path, nfl->newparent,
|
||||
nfl->newpath, nfl->inode, buf);
|
||||
|
||||
do_not_link:
|
||||
nfl_to_prog_data (this, nfl, progcbk, frame);
|
||||
if (progcbk)
|
||||
progcbk (frame, cookie, this, op_ret, op_errno, buf,
|
||||
preoldparent, postoldparent, prenewparent,
|
||||
postnewparent);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
nfs_inode_rename (xlator_t *xl, nfs_user_t *nfu, loc_t *oldloc,
|
||||
loc_t *newloc, fop_rename_cbk_t cbk, void *local)
|
||||
{
|
||||
struct nfs_fop_local *nfl = NULL;
|
||||
int ret = -EFAULT;
|
||||
|
||||
if ((!xl) || (!oldloc) || (!newloc))
|
||||
return ret;
|
||||
|
||||
nfs_fop_handle_local_init (NULL, xl, nfl, cbk, local, ret, err);
|
||||
nfl_inodes_init (nfl, oldloc->inode, oldloc->parent, newloc->parent,
|
||||
oldloc->name, newloc->name);
|
||||
ret = nfs_fop_rename (xl, nfu, oldloc, newloc, nfs_inode_rename_cbk
|
||||
, nfl);
|
||||
|
||||
err:
|
||||
if (ret < 0)
|
||||
nfs_fop_local_wipe (xl, nfl);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int32_t
|
||||
nfs_inode_link_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
|
||||
int32_t op_ret, int32_t op_errno, inode_t *inode,
|
||||
struct iatt *buf, struct iatt *preparent,
|
||||
struct iatt *postparent)
|
||||
{
|
||||
struct nfs_fop_local *nfl = NULL;
|
||||
fop_link_cbk_t progcbk = NULL;
|
||||
|
||||
if (op_ret == -1)
|
||||
goto do_not_link;
|
||||
|
||||
nfl = frame->local;
|
||||
inode_link (inode, nfl->newparent, nfl->path, buf);
|
||||
|
||||
do_not_link:
|
||||
nfl_to_prog_data (this, nfl, progcbk, frame);
|
||||
if (progcbk)
|
||||
progcbk (frame, cookie, this, op_ret, op_errno, inode, buf,
|
||||
preparent, postparent);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
nfs_inode_link (xlator_t *xl, nfs_user_t *nfu, loc_t *oldloc,
|
||||
loc_t *newloc, fop_link_cbk_t cbk, void *local)
|
||||
{
|
||||
struct nfs_fop_local *nfl = NULL;
|
||||
int ret = -EFAULT;
|
||||
|
||||
if ((!xl) || (!oldloc) || (!newloc) || (!nfu))
|
||||
return -EFAULT;
|
||||
|
||||
nfs_fop_handle_local_init (NULL, xl, nfl, cbk, local, ret, err);
|
||||
nfl_inodes_init (nfl, NULL, NULL, newloc->parent, newloc->name, NULL);
|
||||
ret = nfs_fop_link (xl, nfu, oldloc, newloc, nfs_inode_link_cbk,
|
||||
nfl);
|
||||
|
||||
err:
|
||||
if (ret < 0)
|
||||
nfs_fop_local_wipe (xl, nfl);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int32_t
|
||||
nfs_inode_unlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
|
||||
int32_t op_ret, int32_t op_errno, struct iatt *preparent,
|
||||
struct iatt *postparent)
|
||||
{
|
||||
struct nfs_fop_local *nfl = NULL;
|
||||
fop_unlink_cbk_t progcbk = NULL;
|
||||
|
||||
nfl = frame->local;
|
||||
|
||||
if (op_ret == -1)
|
||||
goto do_not_unlink;
|
||||
|
||||
inode_unlink (nfl->inode, nfl->parent, nfl->path);
|
||||
|
||||
do_not_unlink:
|
||||
nfl_to_prog_data (this, nfl, progcbk, frame);
|
||||
if (progcbk)
|
||||
progcbk (frame, cookie, this, op_ret, op_errno, preparent,
|
||||
postparent);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
nfs_inode_unlink (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
|
||||
fop_unlink_cbk_t cbk, void *local)
|
||||
{
|
||||
struct nfs_fop_local *nfl = NULL;
|
||||
int ret = -EFAULT;
|
||||
|
||||
if ((!xl) || (!pathloc) || (!nfu))
|
||||
return -EFAULT;
|
||||
|
||||
nfs_fop_handle_local_init (NULL, xl, nfl, cbk, local, ret, err);
|
||||
nfl_inodes_init (nfl, pathloc->inode, pathloc->parent, NULL,
|
||||
pathloc->name, NULL);
|
||||
ret = nfs_fop_unlink (xl, nfu, pathloc, nfs_inode_unlink_cbk, nfl);
|
||||
|
||||
err:
|
||||
if (ret < 0)
|
||||
nfs_fop_local_wipe (xl, nfl);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int32_t
|
||||
nfs_inode_rmdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
|
||||
int32_t op_ret, int32_t op_errno, struct iatt *preparent,
|
||||
struct iatt *postparent)
|
||||
{
|
||||
struct nfs_fop_local *nfl = NULL;
|
||||
fop_rmdir_cbk_t progcbk = NULL;
|
||||
|
||||
nfl = frame->local;
|
||||
|
||||
if (op_ret == -1)
|
||||
goto do_not_unlink;
|
||||
|
||||
inode_unlink (nfl->inode, nfl->parent, nfl->path);
|
||||
|
||||
do_not_unlink:
|
||||
nfl_to_prog_data (this, nfl, progcbk, frame);
|
||||
if (progcbk)
|
||||
progcbk (frame, cookie, this, op_ret, op_errno, preparent,
|
||||
postparent);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
nfs_inode_rmdir (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
|
||||
fop_rmdir_cbk_t cbk, void *local)
|
||||
{
|
||||
struct nfs_fop_local *nfl = NULL;
|
||||
int ret = -EFAULT;
|
||||
|
||||
if ((!xl) || (!pathloc) || (!nfu))
|
||||
return ret;
|
||||
|
||||
nfs_fop_handle_local_init (NULL, xl, nfl, cbk, local, ret, err);
|
||||
nfl_inodes_init (nfl, pathloc->inode, pathloc->parent, NULL,
|
||||
pathloc->name, NULL);
|
||||
|
||||
ret = nfs_fop_rmdir (xl, nfu, pathloc, nfs_inode_rmdir_cbk, nfl);
|
||||
|
||||
err:
|
||||
if (ret < 0)
|
||||
nfs_fop_local_wipe (xl, nfl);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int32_t
|
||||
nfs_inode_mknod_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
|
||||
int32_t op_ret, int32_t op_errno, inode_t *inode,
|
||||
struct iatt *buf, struct iatt *preparent,
|
||||
struct iatt *postparent)
|
||||
{
|
||||
struct nfs_fop_local *nfl = NULL;
|
||||
fop_mknod_cbk_t progcbk = NULL;
|
||||
|
||||
nfl = frame->local;
|
||||
|
||||
if (op_ret == -1)
|
||||
goto do_not_link;
|
||||
|
||||
inode_link (inode, nfl->parent, nfl->path, buf);
|
||||
|
||||
do_not_link:
|
||||
nfl_to_prog_data (this, nfl, progcbk, frame);
|
||||
if (progcbk)
|
||||
progcbk (frame, cookie, this, op_ret, op_errno, inode, buf,
|
||||
preparent, postparent);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
nfs_inode_mknod (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
|
||||
mode_t mode, dev_t dev, fop_mknod_cbk_t cbk, void *local)
|
||||
{
|
||||
struct nfs_fop_local *nfl = NULL;
|
||||
int ret = -EFAULT;
|
||||
|
||||
if ((!xl) || (!pathloc) || (!nfu))
|
||||
return ret;
|
||||
|
||||
nfs_fop_handle_local_init (NULL, xl, nfl, cbk, local, ret, err);
|
||||
nfl_inodes_init (nfl, pathloc->inode, pathloc->parent, NULL,
|
||||
pathloc->name, NULL);
|
||||
|
||||
ret = nfs_fop_mknod (xl, nfu, pathloc, mode, dev, nfs_inode_mknod_cbk,
|
||||
nfl);
|
||||
|
||||
err:
|
||||
if (ret < 0)
|
||||
nfs_fop_local_wipe (xl, nfl);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int32_t
|
||||
nfs_inode_symlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
|
||||
int32_t op_ret, int32_t op_errno, inode_t *inode,
|
||||
struct iatt *buf, struct iatt *preparent,
|
||||
struct iatt *postparent)
|
||||
{
|
||||
struct nfs_fop_local *nfl = NULL;
|
||||
fop_symlink_cbk_t progcbk = NULL;
|
||||
|
||||
nfl = frame->local;
|
||||
if (op_ret == -1)
|
||||
goto do_not_link;
|
||||
|
||||
inode_link (inode, nfl->parent, nfl->path, buf);
|
||||
|
||||
do_not_link:
|
||||
nfl_to_prog_data (this, nfl, progcbk, frame);
|
||||
if (progcbk)
|
||||
progcbk (frame, cookie, this, op_ret, op_errno, inode, buf,
|
||||
preparent, postparent);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
nfs_inode_symlink (xlator_t *xl, nfs_user_t *nfu, char *target,
|
||||
loc_t *pathloc, fop_symlink_cbk_t cbk, void *local)
|
||||
{
|
||||
struct nfs_fop_local *nfl = NULL;
|
||||
int ret = -EFAULT;
|
||||
|
||||
if ((!xl) || (!target) || (!pathloc) || (!nfu))
|
||||
return ret;
|
||||
|
||||
nfs_fop_handle_local_init (NULL, xl, nfl, cbk, local, ret, err);
|
||||
nfl_inodes_init (nfl, pathloc->inode, pathloc->parent, NULL,
|
||||
pathloc->name, NULL);
|
||||
ret = nfs_fop_symlink (xl, nfu, target, pathloc, nfs_inode_symlink_cbk,
|
||||
nfl);
|
||||
|
||||
err:
|
||||
if (ret < 0)
|
||||
nfs_fop_local_wipe (xl, nfl);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t
|
||||
nfs_inode_opendir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
|
||||
int32_t op_ret, int32_t op_errno, fd_t *fd)
|
||||
{
|
||||
|
||||
struct nfs_fop_local *nfl = NULL;
|
||||
fop_open_cbk_t progcbk = NULL;
|
||||
|
||||
if ((op_ret == -1) && (fd))
|
||||
fd_unref (fd);
|
||||
else
|
||||
fd_bind (fd);
|
||||
|
||||
nfl_to_prog_data (this, nfl, progcbk, frame);
|
||||
|
||||
if (progcbk)
|
||||
progcbk (frame, cookie, this, op_ret, op_errno, fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
nfs_inode_opendir (xlator_t *xl, nfs_user_t *nfu, loc_t *loc,
|
||||
fop_opendir_cbk_t cbk, void *local)
|
||||
{
|
||||
struct nfs_fop_local *nfl = NULL;
|
||||
fd_t *newfd = NULL;
|
||||
int ret = -EFAULT;
|
||||
|
||||
if ((!xl) || (!loc) || (!nfu))
|
||||
return ret;
|
||||
|
||||
newfd = fd_create (loc->inode, 0);
|
||||
if (!newfd) {
|
||||
gf_log (GF_NFS, GF_LOG_ERROR, "Failed to create fd");
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
nfs_fop_handle_local_init (NULL, xl, nfl, cbk, local, ret, err);
|
||||
ret = nfs_fop_opendir (xl, nfu, loc, newfd, nfs_inode_opendir_cbk, nfl);
|
||||
|
||||
err:
|
||||
if (ret < 0) {
|
||||
if (newfd)
|
||||
fd_unref (newfd);
|
||||
nfs_fop_local_wipe (xl, nfl);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
83
xlators/nfs/server/src/nfs-inodes.h
Normal file
83
xlators/nfs/server/src/nfs-inodes.h
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
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 _NFS_INODES_H_
|
||||
#define _NFS_INODES_H_
|
||||
|
||||
#ifndef _CONFIG_H
|
||||
#define _CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "dict.h"
|
||||
#include "xlator.h"
|
||||
#include "iobuf.h"
|
||||
#include "call-stub.h"
|
||||
#include "stack.h"
|
||||
#include "nfs-fops.h"
|
||||
|
||||
|
||||
extern int
|
||||
nfs_link_inode (inode_t *newi, inode_t *parent, char *name,
|
||||
struct iatt *newstat);
|
||||
|
||||
extern int
|
||||
nfs_inode_create (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc, int flags,
|
||||
int mode, fop_create_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_inode_mkdir (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc, int mode,
|
||||
fop_mkdir_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_inode_open (xlator_t *xl, nfs_user_t *nfu, loc_t *loc, int32_t flags,
|
||||
int32_t wbflags, fop_open_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_inode_rename (xlator_t *xl, nfs_user_t *nfu, loc_t *oldloc,
|
||||
loc_t *newloc, fop_rename_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_inode_link (xlator_t *xl, nfs_user_t *nfu, loc_t *oldloc,
|
||||
loc_t *newloc, fop_link_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_inode_unlink (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
|
||||
fop_unlink_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_inode_rmdir (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
|
||||
fop_rmdir_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_inode_symlink (xlator_t *xl, nfs_user_t *nfu, char *target,
|
||||
loc_t *pathloc, fop_symlink_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_inode_opendir (xlator_t *xl, nfs_user_t *nfu, loc_t *loc,
|
||||
fop_opendir_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_inode_mknod (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
|
||||
mode_t mode, dev_t dev, fop_mknod_cbk_t cbk, void *local);
|
||||
|
||||
extern int
|
||||
nfs_inode_lookup (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,
|
||||
fop_lookup_cbk_t cbk, void *local);
|
||||
#endif
|
645
xlators/nfs/server/src/nfs.c
Normal file
645
xlators/nfs/server/src/nfs.c
Normal file
@ -0,0 +1,645 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
|
||||
/* This is the primary translator source for NFS.
|
||||
* Every other protocol version gets initialized from here.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _CONFIG_H
|
||||
#define _CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "defaults.h"
|
||||
#include "rpcsvc.h"
|
||||
#include "dict.h"
|
||||
#include "xlator.h"
|
||||
#include "nfs.h"
|
||||
#include "mem-pool.h"
|
||||
#include "logging.h"
|
||||
#include "nfs-fops.h"
|
||||
#include "inode.h"
|
||||
|
||||
/* Every NFS version must call this function with the init function
|
||||
* for its particular version.
|
||||
*/
|
||||
int
|
||||
nfs_add_initer (struct list_head *list, nfs_version_initer_t init)
|
||||
{
|
||||
struct nfs_initer_list *new = NULL;
|
||||
if ((!list) || (!init))
|
||||
return -1;
|
||||
|
||||
new = CALLOC (1, sizeof (*new));
|
||||
if (!new) {
|
||||
gf_log (GF_NFS, GF_LOG_ERROR, "Memory allocation failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
new->init = init;
|
||||
list_add_tail (&new->list, list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
nfs_deinit_versions (struct list_head *versions, xlator_t *this)
|
||||
{
|
||||
struct nfs_initer_list *version = NULL;
|
||||
struct nfs_initer_list *tmp = NULL;
|
||||
struct nfs_state *nfs = NULL;
|
||||
|
||||
if ((!versions) || (!this))
|
||||
return -1;
|
||||
|
||||
nfs = (struct nfs_state *)this->private;
|
||||
list_for_each_entry_safe (version, tmp, versions, list) {
|
||||
/* TODO: Add version specific destructor.
|
||||
* if (!version->deinit)
|
||||
goto err;
|
||||
|
||||
version->deinit (this);
|
||||
*/
|
||||
if (version->program)
|
||||
rpcsvc_program_unregister (nfs->rpcsvc,
|
||||
*(version->program));
|
||||
|
||||
list_del (&version->list);
|
||||
FREE (version);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
nfs_init_versions (struct nfs_state *nfs, xlator_t *this)
|
||||
{
|
||||
struct nfs_initer_list *version = NULL;
|
||||
struct nfs_initer_list *tmp = NULL;
|
||||
rpcsvc_program_t *prog = NULL;
|
||||
int ret = -1;
|
||||
struct list_head *versions = NULL;
|
||||
|
||||
if ((!nfs) || (!this))
|
||||
return -1;
|
||||
|
||||
gf_log (GF_NFS, GF_LOG_DEBUG, "Initing protocol versions");
|
||||
versions = &nfs->versions;
|
||||
list_for_each_entry_safe (version, tmp, versions, list) {
|
||||
if (!version->init) {
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
prog = version->init (this);
|
||||
version->program = prog;
|
||||
if (!prog) {
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
gf_log (GF_NFS, GF_LOG_DEBUG, "Starting program: %s",
|
||||
prog->progname);
|
||||
ret = rpcsvc_program_register (nfs->rpcsvc, *prog);
|
||||
if (ret == -1) {
|
||||
gf_log (GF_NFS, GF_LOG_ERROR, "Program init failed");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
nfs_add_all_initiators (struct nfs_state *nfs)
|
||||
{
|
||||
/* Add the initializers for all versions. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
nfs_subvolume_started (struct nfs_state *nfs, xlator_t *xl)
|
||||
{
|
||||
int x = 0;
|
||||
int started = 0;
|
||||
|
||||
if ((!nfs) || (!xl))
|
||||
return 1;
|
||||
|
||||
LOCK (&nfs->svinitlock);
|
||||
{
|
||||
for (;x < nfs->allsubvols; ++x) {
|
||||
if (nfs->initedxl[x] == xl) {
|
||||
started = 1;
|
||||
goto unlock;
|
||||
}
|
||||
}
|
||||
}
|
||||
unlock:
|
||||
UNLOCK (&nfs->svinitlock);
|
||||
|
||||
return started;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
nfs_subvolume_set_started (struct nfs_state *nfs, xlator_t *xl)
|
||||
{
|
||||
int x = 0;
|
||||
|
||||
if ((!nfs) || (!xl))
|
||||
return 1;
|
||||
|
||||
LOCK (&nfs->svinitlock);
|
||||
{
|
||||
for (;x < nfs->allsubvols; ++x) {
|
||||
if (nfs->initedxl[x] == NULL) {
|
||||
nfs->initedxl[x] = xl;
|
||||
++nfs->upsubvols;
|
||||
gf_log (GF_NFS, GF_LOG_DEBUG, "Starting up: %s "
|
||||
", vols started till now: %d", xl->name,
|
||||
nfs->upsubvols);
|
||||
goto unlock;
|
||||
}
|
||||
}
|
||||
}
|
||||
unlock:
|
||||
UNLOCK (&nfs->svinitlock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int32_t
|
||||
nfs_start_subvol_lookup_cbk (call_frame_t *frame, void *cookie,
|
||||
xlator_t *this, int32_t op_ret, int32_t op_errno,
|
||||
inode_t *inode, struct iatt *buf, dict_t *xattr,
|
||||
struct iatt *postparent)
|
||||
{
|
||||
struct nfs_state *nfs = NULL;
|
||||
xlator_t *startedxl = NULL;
|
||||
|
||||
if (op_ret == -1) {
|
||||
gf_log (GF_NFS, GF_LOG_CRITICAL, "Failed to lookup root: %s",
|
||||
strerror (op_errno));
|
||||
goto err;
|
||||
}
|
||||
|
||||
nfs = frame->local;
|
||||
startedxl = cookie;
|
||||
gf_log (GF_NFS, GF_LOG_TRACE, "Started %s", startedxl->name);
|
||||
err:
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
nfs_startup_subvolume (struct nfs_state *nfs, xlator_t *xl)
|
||||
{
|
||||
int ret = -1;
|
||||
loc_t rootloc = {0, };
|
||||
nfs_user_t nfu = {0, };
|
||||
|
||||
if ((!nfs) || (!xl))
|
||||
return -1;
|
||||
|
||||
if (nfs_subvolume_started (nfs, xl)) {
|
||||
gf_log (GF_NFS,GF_LOG_TRACE, "Subvolume already started: %s",
|
||||
xl->name);
|
||||
ret = 0;
|
||||
goto err;
|
||||
}
|
||||
|
||||
nfs_subvolume_set_started (nfs, xl);
|
||||
ret = nfs_inode_loc_fill (xl->itable->root, &rootloc);
|
||||
if (ret == -1) {
|
||||
gf_log (GF_NFS, GF_LOG_CRITICAL, "Failed to init root loc");
|
||||
goto err;
|
||||
}
|
||||
|
||||
nfs_user_root_create (&nfu);
|
||||
ret = nfs_fop_lookup (xl, &nfu, &rootloc, nfs_start_subvol_lookup_cbk,
|
||||
(void *)nfs);
|
||||
if (ret < 0) {
|
||||
gf_log (GF_NFS, GF_LOG_CRITICAL, "Failed to lookup root: %s",
|
||||
strerror (-ret));
|
||||
goto err;
|
||||
}
|
||||
|
||||
nfs_loc_wipe (&rootloc);
|
||||
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
nfs_startup_subvolumes (struct nfs_state *nfs)
|
||||
{
|
||||
int ret = -1;
|
||||
xlator_list_t *cl = NULL;
|
||||
if (!nfs)
|
||||
return -1;
|
||||
|
||||
cl = nfs->subvols;
|
||||
while (cl) {
|
||||
gf_log (GF_NFS, GF_LOG_DEBUG, "Starting subvolume: %s",
|
||||
cl->xlator->name);
|
||||
ret = nfs_startup_subvolume (nfs, cl->xlator);
|
||||
if (ret == -1) {
|
||||
gf_log (GF_NFS, GF_LOG_CRITICAL, "Failed to start-up "
|
||||
"xlator: %s", cl->xlator->name);
|
||||
goto err;
|
||||
}
|
||||
cl = cl->next;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
nfs_init_subvolume (struct nfs_state *nfs, xlator_t *xl)
|
||||
{
|
||||
unsigned int lrusize = 0;
|
||||
int ret = -1;
|
||||
|
||||
if ((!nfs) || (!xl))
|
||||
return -1;
|
||||
|
||||
lrusize = nfs->memfactor * GF_NFS_INODE_LRU_MULT;
|
||||
xl->itable = inode_table_new (lrusize, xl);
|
||||
if (!xl->itable) {
|
||||
gf_log (GF_NFS, GF_LOG_CRITICAL, "Failed to allocate "
|
||||
"inode table");
|
||||
goto err;
|
||||
}
|
||||
ret = 0;
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
nfs_init_subvolumes (struct nfs_state *nfs, xlator_list_t *cl)
|
||||
{
|
||||
int ret = -1;
|
||||
unsigned int lrusize = 0;
|
||||
int svcount = 0;
|
||||
|
||||
if ((!nfs) || (!cl))
|
||||
return -1;
|
||||
|
||||
lrusize = nfs->memfactor * GF_NFS_INODE_LRU_MULT;
|
||||
nfs->subvols = cl;
|
||||
gf_log (GF_NFS, GF_LOG_TRACE, "inode table lru: %d", lrusize);
|
||||
|
||||
while (cl) {
|
||||
gf_log (GF_NFS, GF_LOG_DEBUG, "Initing subvolume: %s",
|
||||
cl->xlator->name);
|
||||
ret = nfs_init_subvolume (nfs, cl->xlator);
|
||||
if (ret == -1) {
|
||||
gf_log (GF_NFS, GF_LOG_CRITICAL, "Failed to init "
|
||||
"xlator: %s", cl->xlator->name);
|
||||
goto err;
|
||||
}
|
||||
++svcount;
|
||||
cl = cl->next;
|
||||
}
|
||||
|
||||
LOCK_INIT (&nfs->svinitlock);
|
||||
nfs->initedxl = CALLOC (svcount, sizeof (xlator_t *));
|
||||
if (!nfs->initedxl) {
|
||||
gf_log (GF_NFS, GF_LOG_ERROR, "Failed to allocated inited xls");
|
||||
ret = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
gf_log (GF_NFS, GF_LOG_TRACE, "Inited volumes: %d", svcount);
|
||||
nfs->allsubvols = svcount;
|
||||
ret = 0;
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
nfs_user_root_create (nfs_user_t *newnfu)
|
||||
{
|
||||
if (!newnfu)
|
||||
return -1;
|
||||
|
||||
newnfu->uid = 0;
|
||||
newnfu->gids[0] = 0;
|
||||
newnfu->ngrps = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
nfs_user_create (nfs_user_t *newnfu, uid_t uid, gid_t gid, gid_t *auxgids,
|
||||
int auxcount)
|
||||
{
|
||||
int x = 1;
|
||||
int y = 0;
|
||||
|
||||
/* We test for GF_REQUEST_MAXGROUPS instead of NFS_FOP_NGROUPS because
|
||||
* the latter accounts for the @gid being in @auxgids, which is not the
|
||||
* case here.
|
||||
*/
|
||||
if ((!newnfu) || (auxcount > GF_REQUEST_MAXGROUPS))
|
||||
return -1;
|
||||
|
||||
newnfu->uid = uid;
|
||||
newnfu->gids[0] = gid;
|
||||
newnfu->ngrps = 1;
|
||||
|
||||
gf_log (GF_NFS, GF_LOG_TRACE, "uid: %d, gid %d, gids: %d", uid, gid,
|
||||
auxcount);
|
||||
|
||||
if (!auxgids)
|
||||
return 0;
|
||||
|
||||
for (; y < auxcount; ++x,++y) {
|
||||
newnfu->gids[x] = auxgids[y];
|
||||
++newnfu->ngrps;
|
||||
gf_log (GF_NFS, GF_LOG_TRACE, "gid: %d", auxgids[y]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nfs_request_user_init (nfs_user_t *nfu, rpcsvc_request_t *req)
|
||||
{
|
||||
gid_t *gidarr = NULL;
|
||||
int gids = 0;
|
||||
|
||||
if ((!req) || (!nfu))
|
||||
return;
|
||||
|
||||
gidarr = rpcsvc_auth_unix_auxgids (req, &gids);
|
||||
nfs_user_create (nfu, rpcsvc_request_uid (req), rpcsvc_request_gid (req)
|
||||
, gidarr, gids);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
init (xlator_t *this) {
|
||||
|
||||
struct nfs_state *nfs = NULL;
|
||||
int ret = -1;
|
||||
unsigned int fopspoolsize = 0;
|
||||
|
||||
if (!this)
|
||||
return -1;
|
||||
|
||||
if ((!this->children) || (!this->children->xlator)) {
|
||||
gf_log (GF_NFS, GF_LOG_ERROR, "nfs must have at least one"
|
||||
" child subvolume");
|
||||
return -1;
|
||||
}
|
||||
|
||||
nfs = CALLOC (1, sizeof (*nfs));
|
||||
if (!nfs) {
|
||||
gf_log (GF_NFS, GF_LOG_ERROR, "memory allocation failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* RPC service needs to be started before NFS versions can be inited. */
|
||||
nfs->rpcsvc = rpcsvc_init (this->ctx, this->options);
|
||||
if (!nfs->rpcsvc) {
|
||||
gf_log (GF_NFS, GF_LOG_ERROR, "RPC service init failed");
|
||||
goto free_nfs;
|
||||
}
|
||||
|
||||
nfs->memfactor = GF_NFS_DEFAULT_MEMFACTOR;
|
||||
fopspoolsize = nfs->memfactor * GF_NFS_CONCURRENT_OPS_MULT;
|
||||
/* FIXME: Really saddens me to see this as xlator wide. */
|
||||
nfs->foppool = mem_pool_new (struct nfs_fop_local, fopspoolsize);
|
||||
if (!nfs->foppool) {
|
||||
gf_log (GF_NFS, GF_LOG_CRITICAL, "Failed to allocate fops local"
|
||||
" pool");
|
||||
goto free_rpcsvc;
|
||||
}
|
||||
|
||||
this->private = (void *)nfs;
|
||||
INIT_LIST_HEAD (&nfs->versions);
|
||||
ret = nfs_add_all_initiators (nfs);
|
||||
if (ret == -1) {
|
||||
gf_log (GF_NFS, GF_LOG_ERROR, "Failed to add initiators");
|
||||
goto free_nfs;
|
||||
}
|
||||
|
||||
this->ctx->top = this;
|
||||
ret = nfs_init_subvolumes (nfs, this->children);
|
||||
if (ret == -1) {
|
||||
gf_log (GF_NFS, GF_LOG_CRITICAL, "Failed to init NFS exports");
|
||||
goto free_rpcsvc;
|
||||
}
|
||||
|
||||
free_rpcsvc:
|
||||
/*
|
||||
* rpcsvc_deinit */
|
||||
free_nfs:
|
||||
if (ret == -1)
|
||||
FREE (nfs);
|
||||
|
||||
gf_log (GF_NFS, GF_LOG_DEBUG, "NFS service started");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
notify (xlator_t *this, int32_t event, void *data, ...)
|
||||
{
|
||||
struct nfs_state *nfs = NULL;
|
||||
xlator_t *subvol = NULL;
|
||||
int ret = -1;
|
||||
|
||||
nfs = (struct nfs_state *)this->private;
|
||||
subvol = (xlator_t *)data;
|
||||
|
||||
gf_log (GF_NFS, GF_LOG_TRACE, "Notification received: %d",
|
||||
event);
|
||||
switch (event)
|
||||
{
|
||||
case GF_EVENT_CHILD_UP:
|
||||
{
|
||||
nfs_startup_subvolume (nfs, subvol);
|
||||
if ((nfs->upsubvols == nfs->allsubvols) &&
|
||||
(!nfs->subvols_started)) {
|
||||
nfs->subvols_started = 1;
|
||||
gf_log (GF_NFS, GF_LOG_TRACE, "All children up,"
|
||||
" starting RPC");
|
||||
ret = nfs_init_versions (nfs, this);
|
||||
if (ret == -1)
|
||||
gf_log (GF_NFS, GF_LOG_CRITICAL,
|
||||
"Failed to initialize "
|
||||
"protocols");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case GF_EVENT_PARENT_UP:
|
||||
{
|
||||
default_notify (this, GF_EVENT_PARENT_UP, data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
fini (xlator_t *this)
|
||||
{
|
||||
|
||||
struct nfs_state *nfs = NULL;
|
||||
|
||||
nfs = (struct nfs_state *)this->private;
|
||||
gf_log (GF_NFS, GF_LOG_DEBUG, "NFS service going down");
|
||||
nfs_deinit_versions (&nfs->versions, this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct xlator_cbks cbks = { };
|
||||
struct xlator_mops mops = { };
|
||||
struct xlator_fops fops = { };
|
||||
|
||||
struct volume_options options[] = {
|
||||
{ .key = {"nfs3.read-size"},
|
||||
.type = GF_OPTION_TYPE_SIZET,
|
||||
.description = "Size in which the client should issue read requests"
|
||||
" to the Gluster NFSv3 server. Must be a multiple of"
|
||||
" 4KiB."
|
||||
},
|
||||
{ .key = {"nfs3.write-size"},
|
||||
.type = GF_OPTION_TYPE_SIZET,
|
||||
.description = "Size in which the client should issue write requests"
|
||||
" to the Gluster NFSv3 server. Must be a multiple of"
|
||||
" 4KiB."
|
||||
},
|
||||
{ .key = {"nfs3.readdir-size"},
|
||||
.type = GF_OPTION_TYPE_SIZET,
|
||||
.description = "Size in which the client should issue directory "
|
||||
" reading requests."
|
||||
},
|
||||
{ .key = {"nfs3.*.volume-access"},
|
||||
.type = GF_OPTION_TYPE_STR,
|
||||
.description = "Type of access desired for this subvolume: "
|
||||
" read-only, read-write(default)"
|
||||
},
|
||||
{ .key = {"rpc-auth.auth-unix"},
|
||||
.type = GF_OPTION_TYPE_BOOL,
|
||||
.description = "Disable or enable the AUTH_UNIX authentication type."
|
||||
"Must always be enabled for better interoperability."
|
||||
"However, can be disabled if needed. Enabled by"
|
||||
"default"
|
||||
},
|
||||
{ .key = {"rpc-auth.auth-null"},
|
||||
.type = GF_OPTION_TYPE_BOOL,
|
||||
.description = "Disable or enable the AUTH_NULL authentication type."
|
||||
"Must always be enabled. This option is here only to"
|
||||
" avoid unrecognized option warnings"
|
||||
},
|
||||
{ .key = {"rpc-auth.auth-unix.*"},
|
||||
.type = GF_OPTION_TYPE_BOOL,
|
||||
.description = "Disable or enable the AUTH_UNIX authentication type "
|
||||
"for a particular exported volume over-riding defaults"
|
||||
" and general setting for AUTH_UNIX scheme. Must "
|
||||
"always be enabled for better interoperability."
|
||||
"However, can be disabled if needed. Enabled by"
|
||||
"default."
|
||||
},
|
||||
{ .key = {"rpc-auth.auth-null.*"},
|
||||
.type = GF_OPTION_TYPE_BOOL,
|
||||
.description = "Disable or enable the AUTH_NULL authentication type "
|
||||
"for a particular exported volume over-riding defaults"
|
||||
" and general setting for AUTH_NULL. Must always be "
|
||||
"enabled. This option is here only to avoid "
|
||||
"unrecognized option warnings."
|
||||
},
|
||||
{ .key = {"rpc-auth.addr.allow"},
|
||||
.type = GF_OPTION_TYPE_STR,
|
||||
.description = "Allow a comma separated list of addresses and/or"
|
||||
" hostnames to connect to the server. By default, all"
|
||||
" connections are disallowed. This allows users to "
|
||||
"define a general rule for all exported volumes."
|
||||
},
|
||||
{ .key = {"rpc-auth.addr.reject"},
|
||||
.type = GF_OPTION_TYPE_STR,
|
||||
.description = "Reject a comma separated list of addresses and/or"
|
||||
" hostnames from connecting to the server. By default,"
|
||||
" all connections are disallowed. This allows users to"
|
||||
"define a general rule for all exported volumes."
|
||||
},
|
||||
{ .key = {"rpc-auth.addr.*.allow"},
|
||||
.type = GF_OPTION_TYPE_STR,
|
||||
.description = "Allow a comma separated list of addresses and/or"
|
||||
" hostnames to connect to the server. By default, all"
|
||||
" connections are disallowed. This allows users to "
|
||||
"define a rule for a specific exported volume."
|
||||
},
|
||||
{ .key = {"rpc-auth.addr.*.reject"},
|
||||
.type = GF_OPTION_TYPE_STR,
|
||||
.description = "Reject a comma separated list of addresses and/or"
|
||||
" hostnames from connecting to the server. By default,"
|
||||
" all connections are disallowed. This allows users to"
|
||||
"define a rule for a specific exported volume."
|
||||
},
|
||||
{ .key = {"rpc-auth.ports.insecure"},
|
||||
.type = GF_OPTION_TYPE_BOOL,
|
||||
.description = "Allow client connections from unprivileged ports. By "
|
||||
"default only privileged ports are allowed. This is a"
|
||||
"global setting in case insecure ports are to be "
|
||||
"enabled for all exports using a single option."
|
||||
},
|
||||
{ .key = {"rpc-auth.ports.*.insecure"},
|
||||
.type = GF_OPTION_TYPE_BOOL,
|
||||
.description = "Allow client connections from unprivileged ports. By "
|
||||
"default only privileged ports are allowed. Use this"
|
||||
" option to set enable or disable insecure ports for "
|
||||
"a specific subvolume and to over-ride global setting "
|
||||
" set by the previous option."
|
||||
},
|
||||
{ .key = {"rpc-auth.addr.namelookup"},
|
||||
.type = GF_OPTION_TYPE_BOOL,
|
||||
.description = "Users have the option of turning off name lookup for"
|
||||
" incoming client connections using this option. In some "
|
||||
"setups, the name server can take too long to reply to DNS "
|
||||
"queries resulting in timeouts of mount requests. Use this "
|
||||
"option to turn off name lookups during address "
|
||||
"authentication. Note, turning this off will prevent you from"
|
||||
" using hostnames in rpc-auth.addr.* filters. By default, "
|
||||
" name lookup is on."
|
||||
},
|
||||
{ .key = {NULL} },
|
||||
};
|
||||
|
98
xlators/nfs/server/src/nfs.h
Normal file
98
xlators/nfs/server/src/nfs.h
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
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 __NFS_H__
|
||||
#define __NFS_H__
|
||||
|
||||
#ifndef _CONFIG_H
|
||||
#define _CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "rpcsvc.h"
|
||||
#include "dict.h"
|
||||
#include "xlator.h"
|
||||
|
||||
#define GF_NFS "nfs"
|
||||
|
||||
#define GF_NFS_CONCURRENT_OPS_MULT 15
|
||||
|
||||
#define GF_NFS_INODE_LRU_MULT 6000
|
||||
|
||||
#define GF_RPC_MIN_THREADS 1
|
||||
#define GF_RPC_MAX_THREADS 16
|
||||
|
||||
#define GF_NFS_DEFAULT_MEMFACTOR 15
|
||||
#define GF_NFS_MIN_MEMFACTOR 1
|
||||
#define GF_NFS_MAX_MEMFACTOR 30
|
||||
|
||||
/* Callback into a version-specific NFS protocol.
|
||||
* The return type is used by the nfs.c code to register the protocol.
|
||||
* with the RPC service.
|
||||
*/
|
||||
typedef rpcsvc_program_t *(*nfs_version_initer_t) (xlator_t *nfsx);
|
||||
|
||||
/* List of version-specific protocol initiators */
|
||||
struct nfs_initer_list {
|
||||
struct list_head list;
|
||||
nfs_version_initer_t init;
|
||||
rpcsvc_program_t *program;
|
||||
};
|
||||
|
||||
|
||||
struct nfs_state {
|
||||
rpcsvc_t *rpcsvc;
|
||||
struct list_head versions;
|
||||
struct mem_pool *foppool;
|
||||
unsigned int memfactor;
|
||||
xlator_list_t *subvols;
|
||||
|
||||
gf_lock_t svinitlock;
|
||||
int allsubvols;
|
||||
int upsubvols;
|
||||
xlator_t **initedxl;
|
||||
int subvols_started;
|
||||
};
|
||||
|
||||
|
||||
/* We have one gid more than the glusterfs maximum since we pass the primary
|
||||
* gid as the first element of the array.
|
||||
*/
|
||||
#define NFS_NGROUPS (GF_REQUEST_MAXGROUPS + 1)
|
||||
|
||||
/* Index of the primary gid */
|
||||
#define NFS_PRIMGID_IDX 0
|
||||
|
||||
typedef struct nfs_user_info {
|
||||
uid_t uid;
|
||||
gid_t gids[NFS_NGROUPS];
|
||||
int ngrps;
|
||||
} nfs_user_t;
|
||||
|
||||
extern int
|
||||
nfs_user_root_create (nfs_user_t *newnfu);
|
||||
|
||||
extern int
|
||||
nfs_user_create (nfs_user_t *newnfu, uid_t uid, gid_t gid, gid_t *auxgids,
|
||||
int auxcount);
|
||||
|
||||
extern void
|
||||
nfs_request_user_init (nfs_user_t *nfu, rpcsvc_request_t *req);
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user