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:
Shehjar Tikoo 2010-03-31 07:27:03 +00:00 committed by Anand V. Avati
parent 8b2949db0d
commit c4fd1cf732
14 changed files with 4813 additions and 1 deletions

View File

@ -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

View File

@ -1,3 +1,3 @@
SUBDIRS = lib
SUBDIRS = lib server
CLEANFILES =

View File

@ -0,0 +1,3 @@
SUBDIRS = src
CLEANFILES =

View 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 =

View 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;
}

View 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

File diff suppressed because it is too large Load Diff

View 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

File diff suppressed because it is too large Load Diff

View 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

View 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;
}

View 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

View 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} },
};

View 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