diff options
Diffstat (limited to 'xlators/nfs/server/src/nfs-fops.c')
| -rw-r--r-- | xlators/nfs/server/src/nfs-fops.c | 1441 | 
1 files changed, 1441 insertions, 0 deletions
diff --git a/xlators/nfs/server/src/nfs-fops.c b/xlators/nfs/server/src/nfs-fops.c new file mode 100644 index 00000000000..3d4968a8b17 --- /dev/null +++ b/xlators/nfs/server/src/nfs-fops.c @@ -0,0 +1,1441 @@ +/* +  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 "dict.h" +#include "xlator.h" +#include "iobuf.h" +#include "call-stub.h" +#include "stack.h" +#include "nfs.h" +#include "nfs-fops.h" +#include "inode.h" +#include "nfs-common.h" + +#include <libgen.h> +#include <semaphore.h> + +#define nfs_stack_destroy(fram)                                         \ +        do {                                                            \ +                (fram)->local = NULL;                                   \ +                STACK_DESTROY ((fram)->root);                           \ +        } while (0)                                                     \ + + +struct nfs_fop_local * +nfs_fop_local_init (xlator_t *xl) +{ +        struct nfs_fop_local    *l = NULL; +        struct nfs_state        *nfs = NULL; +        if (!xl) +                return NULL; + +        nfs = xlator_top_private (xl); +        l = mem_get (nfs->foppool); + +        memset (l, 0, sizeof (*l)); +        return l; +} + +void +nfs_fop_local_wipe (xlator_t *xl, struct nfs_fop_local *l) +{ +        struct nfs_state        *nfs = NULL; + +        if ((!xl) || (!l)) +                return; + +        nfs = xlator_top_private (xl); + +        if (l->iobref) +                iobref_unref (l->iobref); + +        if (l->parent) +                inode_unref (l->parent); + +        if (l->inode) +                inode_unref (l->inode); + +        if (l->newparent) +                inode_unref (l->newparent); + +        mem_put (nfs->foppool, l); + +        return; +} + +call_frame_t * +nfs_create_frame (xlator_t *xl, nfs_user_t *nfu) +{ +        call_frame_t    *frame = NULL; +        int             x = 0; +        int             y = 0; + +        if ((!xl) || (!nfu) || (nfu->ngrps > NFS_NGROUPS)) +                return NULL; + +        frame = create_frame (xl, (call_pool_t *)xl->ctx->pool); +        if (!frame) +                goto err; +        frame->root->uid = nfu->uid; +        frame->root->gid = nfu->gids[NFS_PRIMGID_IDX]; +        if (nfu->ngrps == 1) +                goto err;       /* Done, we only got primary gid */ + +        frame->root->ngrps = nfu->ngrps - 1; + +        gf_log (GF_NFS, GF_LOG_TRACE,"uid: %d, gid %d, gids: %d", +                frame->root->uid, frame->root->gid, frame->root->ngrps); +        for(y = 0, x = 1;  y < frame->root->ngrps; x++,y++) { +                gf_log (GF_NFS, GF_LOG_TRACE, "gid: %d", nfu->gids[x]); +                frame->root->groups[y] = nfu->gids[x]; +        } + +err: +        return frame; +} + +#define nfs_fop_handle_frame_create(fram, xla, nfuser, retval, errlabel)      \ +        do {                                                                  \ +                fram = nfs_create_frame (xla, (nfuser));                      \ +                if (!fram) {                                                  \ +                        retval = (-ENOMEM);                                   \ +                        gf_log (GF_NFS, GF_LOG_ERROR,"Frame creation failed");\ +                        goto errlabel;                                        \ +                }                                                             \ +        } while (0)                                                           \ + +/* Look into the  inode and parent inode of a loc and save enough state + * for us to determine in the callback whether to funge the ino in the stat buf + * with 1 for the parent. + */ +#define nfs_fop_save_root_ino(locl, loc)                                    \ +        do {                                                                \ +                if ((loc)->ino == 1)                                        \ +                        (locl)->rootinode = 1;                              \ +                else if (((loc)->parent) && ((loc)->parent->ino == 1))      \ +                        (locl)->rootparentinode = 1;                        \ +        } while (0)                                                         \ + +/* Do the same for an fd */ +#define nfs_fop_save_root_fd_ino(locl, fdesc)                               \ +        do {                                                                \ +                if ((fdesc)->inode->ino == 1)                               \ +                        (locl)->rootinode = 1;                              \ +        } while (0)                                                         \ + + + +/* Use the state saved by the previous macro to funge the ino in the appropriate + * structure. + */ +#define nfs_fop_restore_root_ino(locl, preattr, postattr, prepar, postpar)  \ +        do {                                                                \ +                if ((locl)->rootinode) {                                    \ +                        if ((preattr)) {                                    \ +                                ((struct iatt *)(preattr))->ia_ino = 1;     \ +                                ((struct iatt *)(preattr))->ia_dev = 0;     \ +                        }                                                   \ +                        if ((postattr)) {                                   \ +                                ((struct iatt *)(postattr))->ia_ino = 1;    \ +                                ((struct iatt *)(postattr))->ia_dev = 0;    \ +                        }                                                   \ +                } else if ((locl)->rootparentinode) {                       \ +                        if ((prepar)) {                                     \ +                                ((struct iatt *)(prepar))->ia_ino = 1;      \ +                                ((struct iatt *)(prepar))->ia_dev = 0;      \ +                        }                                                   \ +                        if ((postpar)) {                                    \ +                                ((struct iatt *)(postpar))->ia_ino = 1;     \ +                                ((struct iatt *)(postpar))->ia_dev = 0;     \ +                        }                                                   \ +                }                                                           \ +        } while (0)                                                         \ + +/* If the newly created, inode's parent is root, we'll need to funge the ino + * in the parent attr when we receive them in the callback. + */ +#define nfs_fop_newloc_save_root_ino(locl, newloc)                             \ +        do {                                                                   \ +                if ((newloc)->ino == 1)                                        \ +                        (locl)->newrootinode = 1;                              \ +                else if (((newloc)->parent) && ((newloc)->parent->ino == 1))   \ +                        (locl)->newrootparentinode = 1;                        \ +        } while (0)                                                            \ + + +#define nfs_fop_newloc_restore_root_ino(locl, preattr, postattr, prepar, postpar)  \ +        do {                                                                   \ +                if ((locl)->newrootinode) {                                    \ +                        if ((preattr))                                         \ +                                ((struct iatt *)(preattr))->ia_ino = 1;        \ +                        if ((postattr))                                        \ +                                ((struct iatt *)(postattr))->ia_ino = 1;       \ +                } else if ((locl)->newrootparentinode) {                       \ +                        if ((prepar))                                          \ +                                ((struct iatt *)(prepar))->ia_ino = 1;         \ +                        if ((postpar))                                         \ +                                ((struct iatt *)(postpar))->ia_ino = 1;        \ +                }                                                              \ +        } while (0)                                                            \ + +/* Fops Layer Explained + * The fops layer has three types of functions. They can all be identified by + * their names. Here are the three patterns: + * + * nfs_fop_<fopname> + * This is the lowest level function that knows nothing about states and + * callbacks. At most this is required to create a frame and call the + * fop. The idea here is to provide a convenient way to call fops than + * directly use STACK_WINDs. If this type of interface is used, the caller's + * callback is responsible for doing the relevant GlusterFS state + * maintenance operations on the data returned in the callbacks. + * + * nfs_fop_<fopname>_sync + * These are synchronous versions of the above fops. The idea is that + * if the user wants to wait for the fop to complete, this is the interface to + * use. The caller is responsible for doing the relevant GlusterFS + * state maintenance operations on the call_stub_t that is returned, including + * calling call_stub_destroy. + * + * nfs_<fopname>_sync + * This is help callers avoid the need to pass a pathloc to the + * nfs_fop_<fopname>_sync versions of the same fops. + * + * nfs_<fopname> + * Unlike the nfs_fop_<fopname> variety, this is the stateful type of fop, in + * that it silently performs all the relevant GlusterFS state maintainence + * operations on the data returned to the callbacks, leaving the caller's + * callback to just use the data returned for whatever it needs to do with that + * data, for eg. the nfs_lookup, will take care of looking up the inodes, + * revalidating them if needed and linking new inodes into the table, while + * the caller's callback, for eg, the NFSv3 LOOKUP callback can just use + * the stat bufs returned to create file handle, map the file handle into the + * fh cache and finally encode the fh and the stat bufs into a NFS reply. + * + */ + +int32_t +nfs_fop_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_fop_local    *local = NULL; +        fop_lookup_cbk_t        progcbk; + +        nfl_to_prog_data (this, local, progcbk, frame); +        nfs_fop_restore_root_ino (local, buf, NULL, NULL, postparent); +        if (progcbk) +                progcbk (frame, cookie, this, op_ret, op_errno, inode, buf, +                         xattr, postparent); + +        nfs_stack_destroy (frame); +        return 0; +} + + +int +nfs_fop_lookup (xlator_t *xl, nfs_user_t *nfu, loc_t *loc, +                fop_lookup_cbk_t cbk, void *local) +{ +        call_frame_t            *frame = NULL; +        int                     ret = -EFAULT; +        struct nfs_fop_local    *nfl = NULL; + +        if ((!xl) || (!loc) || (!nfu)) +                return ret; + +        gf_log (GF_NFS, GF_LOG_TRACE, "Lookup: %s", loc->path); +        nfs_fop_handle_frame_create (frame, xl, nfu, ret, err); +        nfs_fop_handle_local_init (frame, xl, nfl, cbk, local, ret, err); +        nfs_fop_save_root_ino (nfl, loc); + +        STACK_WIND_COOKIE  (frame, nfs_fop_lookup_cbk, xl, xl, xl->fops->lookup, +                            loc, NULL); + +        ret = 0; +err: +        if (ret < 0) { +                if (frame) +                        nfs_stack_destroy (frame); +        } + +        return ret; +} + + +int32_t +nfs_fop_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                  int32_t op_ret, int32_t op_errno, struct iatt *buf) +{ +        struct nfs_fop_local    *nfl = NULL; +        fop_stat_cbk_t          progcbk = NULL; + +        nfl_to_prog_data (this, nfl, progcbk, frame); +        nfs_fop_restore_root_ino (nfl, buf, NULL, NULL, NULL); +        if (progcbk) +                progcbk (frame, cookie, this, op_ret, op_errno, buf); + +        nfs_stack_destroy (frame); +        return 0; +} + + +int +nfs_fop_stat (xlator_t *xl, nfs_user_t *nfu, loc_t *loc, +              fop_stat_cbk_t cbk, void *local) +{ +        call_frame_t            *frame = NULL; +        int                     ret = -EFAULT; +        struct nfs_fop_local    *nfl = NULL; + +        if ((!xl) || (!loc) || (!nfu)) +                return ret; + +        gf_log (GF_NFS, GF_LOG_TRACE, "Stat: %s", loc->path); +        nfs_fop_handle_frame_create (frame, xl, nfu, ret, err); +        nfs_fop_handle_local_init (frame, xl, nfl, cbk, local, ret, err); +        nfs_fop_save_root_ino (nfl, loc); + +        STACK_WIND_COOKIE  (frame, nfs_fop_stat_cbk, xl, xl, xl->fops->stat, +                            loc); +        ret = 0; +err: +        if (ret < 0) { +                if (frame) +                        nfs_stack_destroy (frame); +        } + +        return ret; +} + + +int32_t +nfs_fop_fstat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                   int32_t op_ret, int32_t op_errno, struct iatt *buf) +{ +        struct nfs_fop_local    *nfl = NULL; +        fop_fstat_cbk_t         progcbk = NULL; + +        nfl_to_prog_data (this, nfl, progcbk, frame); +        nfs_fop_restore_root_ino (nfl, buf, NULL, NULL, NULL); +        if (progcbk) +                progcbk (frame, cookie, this, op_ret, op_errno, buf); + +        nfs_stack_destroy (frame); +        return 0; +} + + +int +nfs_fop_fstat (xlator_t *xl, nfs_user_t *nfu, fd_t *fd, +               fop_fstat_cbk_t cbk, void *local) +{ +        call_frame_t            *frame = NULL; +        int                     ret = -EFAULT; +        struct nfs_fop_local    *nfl = NULL; + +        if ((!xl) || (!fd) || (!nfu)) +                return ret; + +        gf_log (GF_NFS, GF_LOG_TRACE, "FStat"); +        nfs_fop_handle_frame_create (frame, xl, nfu, ret, err); +        nfs_fop_handle_local_init (frame, xl, nfl, cbk, local, ret, err); +        nfs_fop_save_root_fd_ino (nfl, fd); + +        STACK_WIND_COOKIE  (frame, nfs_fop_fstat_cbk, xl, xl, xl->fops->fstat, +                            fd); + +        ret = 0; +err: +        if (ret < 0) { +                if (frame) +                        nfs_stack_destroy (frame); +        } + +        return ret; +} + + +int32_t +nfs_fop_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_opendir_cbk_t       progcbk = NULL; + +        nfl_to_prog_data (this, nfl, progcbk, frame); +        if (progcbk) +                progcbk (frame, cookie, this, op_ret, op_errno, fd); +        nfs_stack_destroy (frame); +        return 0; +} + + +int +nfs_fop_opendir (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc,fd_t *dirfd, +                 fop_opendir_cbk_t cbk, void *local) +{ +        call_frame_t            *frame = NULL; +        int                     ret = -EFAULT; +        struct nfs_fop_local    *nfl = NULL; + +        if ((!xl) || (!pathloc) || (!dirfd) || (!nfu)) +                return ret; + +        gf_log (GF_NFS, GF_LOG_TRACE, "Opendir: %s", pathloc->path); +        nfs_fop_handle_frame_create (frame, xl, nfu, ret, err); +        nfs_fop_handle_local_init (frame, xl, nfl, cbk, local, ret, err); + +        STACK_WIND_COOKIE (frame, nfs_fop_opendir_cbk, xl, xl, +                           xl->fops->opendir, pathloc, dirfd); +        ret = 0; + +err: +        if (ret < 0) { +                if (frame) +                        nfs_stack_destroy (frame); +        } + +        return ret; +} + +int +nfs_fop_flush_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                   int32_t op_ret, int32_t op_errno) +{ +        struct nfs_fop_local    *nfl = NULL; +        fop_flush_cbk_t         progcbk = NULL; + +        nfl_to_prog_data (this, nfl, progcbk, frame); +        if (progcbk) +                progcbk (frame, cookie, this, op_ret, op_errno); + +        nfs_stack_destroy (frame); +        return 0; +} + + +int +nfs_fop_flush (xlator_t *xl, nfs_user_t *nfu, fd_t *fd, +               fop_flush_cbk_t cbk, void *local) +{ +        call_frame_t            *frame = NULL; +        int                     ret = -EFAULT; +        struct nfs_fop_local    *nfl = NULL; + +        if ((!xl) || (!fd) || (!nfu)) +                return ret; + +        nfs_fop_handle_frame_create (frame, xl, nfu, ret, err); +        nfs_fop_handle_local_init (frame, xl, nfl, cbk, local, ret, err); + +        STACK_WIND_COOKIE (frame, nfs_fop_flush_cbk, xl, xl, xl->fops->flush, +                           fd); +        ret = 0; +err: +        if (ret < 0) { +                if (frame) +                        nfs_stack_destroy (frame); +        } + +        return ret; +} + + +int32_t +nfs_fop_readdirp_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                      int32_t op_ret, int32_t op_errno, gf_dirent_t *entries) +{ +        struct nfs_fop_local    *nfl = NULL; +        fop_readdirp_cbk_t      progcbk = NULL; + +        nfl_to_prog_data (this, nfl, progcbk, frame); +        if (progcbk) +                progcbk (frame, cookie, this, op_ret, op_errno, entries); + +        nfs_stack_destroy (frame); + +        return 0; +} + + +int +nfs_fop_readdirp (xlator_t *xl, nfs_user_t *nfu, fd_t *dirfd, +                  size_t bufsize, off_t offset, fop_readdirp_cbk_t cbk, +                  void *local) +{ +        call_frame_t            *frame = NULL; +        int                     ret = -EFAULT; +        struct nfs_fop_local    *nfl = NULL; + +        if ((!xl) || (!dirfd) || (!nfu)) +                return ret; + +        gf_log (GF_NFS, GF_LOG_TRACE, "readdir"); +        nfs_fop_handle_frame_create (frame, xl, nfu, ret, err); +        nfs_fop_handle_local_init (frame, xl, nfl, cbk, local, ret, err); + +        STACK_WIND_COOKIE (frame, nfs_fop_readdirp_cbk, xl, xl, +                           xl->fops->readdirp, dirfd, bufsize, offset); + +        ret = 0; +err: +        if (ret < 0) { +                if (frame) +                        nfs_stack_destroy (frame); +        } + +        return ret; +} + + +int32_t +nfs_fop_statfs_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                    int32_t op_ret, int32_t op_errno, struct statvfs *buf) +{ + +        struct nfs_fop_local    *nfl = NULL; +        fop_statfs_cbk_t        progcbk = NULL; + +        nfl_to_prog_data (this, nfl, progcbk, frame); +        if (progcbk) +                progcbk (frame, cookie, this, op_ret, op_errno, buf); + +        nfs_stack_destroy (frame); +        return 0; +} + + +int +nfs_fop_statfs (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc, +                fop_statfs_cbk_t cbk, void *local) +{ +        call_frame_t            *frame = NULL; +        int                     ret = -EFAULT; +        struct nfs_fop_local    *nfl = NULL; + +        if ((!xl) || (!pathloc) || (!nfu)) +                return ret; + +        gf_log (GF_NFS, GF_LOG_TRACE, "Statfs: %s", pathloc->path); +        nfs_fop_handle_frame_create (frame, xl, nfu, ret, err); +        nfs_fop_handle_local_init (frame, xl, nfl, cbk, local, ret, err); + +        STACK_WIND_COOKIE  (frame, nfs_fop_statfs_cbk, xl, xl, xl->fops->statfs +                            ,pathloc); +        ret = 0; +err: +        if (ret < 0) { +                if (frame) +                        nfs_stack_destroy (frame); +        } + +        return ret; +} + + +int32_t +nfs_fop_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 = NULL; +        fop_create_cbk_t        progcbk = NULL; + +        nfl_to_prog_data (this, nfl, progcbk, frame); +        nfs_fop_restore_root_ino (nfl, buf, NULL, preparent, postparent); +        if (progcbk) +                progcbk (frame, cookie, this, op_ret, op_errno, fd, inode, buf, +                         preparent, postparent); + +        nfs_stack_destroy (frame); +        return 0; +} + + +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) +{ +        call_frame_t            *frame = NULL; +        int                     ret = -EFAULT; +        struct nfs_fop_local    *nfl = NULL; + +        if ((!xl) || (!pathloc) || (!nfu)) +                return ret; + +        gf_log (GF_NFS, GF_LOG_TRACE, "Create: %s", pathloc->path); +        nfs_fop_handle_frame_create (frame, xl, nfu, ret, err); +        nfs_fop_handle_local_init (frame, xl, nfl, cbk, local, ret, err); +        nfs_fop_save_root_ino (nfl, pathloc); + +        STACK_WIND_COOKIE  (frame, nfs_fop_create_cbk, xl, xl, xl->fops->create +                            , pathloc, flags, mode, fd); +        ret = 0; +err: +        if (ret < 0) { +                if (frame) +                        nfs_stack_destroy (frame); +        } + +        return ret; +} + + +int32_t +nfs_fop_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                     int32_t op_ret, int32_t op_errno, struct iatt *pre, +                     struct iatt *post) +{ +        struct nfs_fop_local    *nfl = NULL; +        fop_setattr_cbk_t       progcbk = NULL; + +        nfl_to_prog_data (this, nfl, progcbk, frame); +        nfs_fop_restore_root_ino (nfl, pre, post, NULL, NULL); +        if (progcbk) +                progcbk (frame, cookie, this, op_ret, op_errno, pre, post); +        nfs_stack_destroy (frame); +        return 0; +} + + + +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) +{ +        call_frame_t            *frame = NULL; +        int                     ret = -EFAULT; +        struct nfs_fop_local    *nfl = NULL; + +        if ((!xl) || (!pathloc) || (!nfu)) +                return ret; + +        gf_log (GF_NFS, GF_LOG_TRACE, "Setattr: %s", pathloc->path); +        nfs_fop_handle_frame_create (frame, xl, nfu, ret, err); +        nfs_fop_handle_local_init (frame, xl, nfl, cbk, local, ret, err); +        nfs_fop_save_root_ino (nfl, pathloc); + +        STACK_WIND_COOKIE (frame, nfs_fop_setattr_cbk, xl, xl, +                           xl->fops->setattr, pathloc, buf, valid); +        ret = 0; +err: +        if (ret < 0) { +                if (frame) +                        nfs_stack_destroy (frame); +        } + +        return ret; +} + + +int32_t +nfs_fop_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 = NULL; +        fop_mkdir_cbk_t         progcbk = NULL; + +        nfl_to_prog_data (this, nfl, progcbk, frame); +        nfs_fop_restore_root_ino (nfl, buf, NULL, preparent, postparent); +        if (progcbk) +                progcbk (frame, cookie, this, op_ret, op_errno, inode, buf, +                         preparent, postparent); +        nfs_stack_destroy (frame); +        return 0; +} + + +int +nfs_fop_mkdir (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc, mode_t mode, +               fop_mkdir_cbk_t cbk, void *local) +{ +        call_frame_t            *frame = NULL; +        int                     ret = -EFAULT; +        struct nfs_fop_local    *nfl = NULL; + +        if ((!xl) || (!pathloc) || (!nfu)) +                return ret; + +        gf_log (GF_NFS, GF_LOG_TRACE, "Mkdir: %s", pathloc->path); +        nfs_fop_handle_frame_create (frame, xl, nfu, ret, err); +        nfs_fop_handle_local_init (frame, xl, nfl, cbk, local, ret, err); +        nfs_fop_save_root_ino (nfl, pathloc); + +        STACK_WIND_COOKIE  (frame, nfs_fop_mkdir_cbk, xl, xl, xl->fops->mkdir, +                            pathloc, mode); +        ret = 0; +err: +        if (ret < 0) { +                if (frame) +                        nfs_stack_destroy (frame); +        } + +        return ret; +} + + +int32_t +nfs_fop_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_to_prog_data (this, nfl, progcbk, frame); +        nfs_fop_restore_root_ino (nfl, buf, NULL, preparent, postparent); +        if (progcbk) +                progcbk (frame, cookie, this, op_ret, op_errno, inode, buf, +                         preparent, postparent); +        nfs_stack_destroy (frame); +        return 0; +} + +int +nfs_fop_symlink (xlator_t *xl, nfs_user_t *nfu, char *target, +                 loc_t *pathloc, fop_symlink_cbk_t cbk, void *local) +{ +        call_frame_t            *frame = NULL; +        int                     ret = -EFAULT; +        struct nfs_fop_local    *nfl = NULL; + +        if ((!xl) || (!pathloc) || (!target) || (!nfu)) +                return ret; + +        gf_log (GF_NFS, GF_LOG_TRACE, "Symlink: %s", pathloc->path); +        nfs_fop_handle_frame_create (frame, xl, nfu, ret, err); +        nfs_fop_handle_local_init (frame, xl, nfl, cbk, local, ret, err); +        nfs_fop_save_root_ino (nfl, pathloc); + +        STACK_WIND_COOKIE  (frame, nfs_fop_symlink_cbk, xl, xl, +                            xl->fops->symlink, target, pathloc); +        ret = 0; +err: +        if (ret < 0) { +                if (frame) +                        nfs_stack_destroy (frame); +        } + +        return ret; +} + + +int32_t +nfs_fop_readlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                      int32_t op_ret, int32_t op_errno, const char *path, +                      struct iatt *buf) +{ +        struct nfs_fop_local    *nfl = NULL; +        fop_readlink_cbk_t      progcbk = NULL; + +        nfl_to_prog_data (this, nfl, progcbk, frame); +        nfs_fop_restore_root_ino (nfl, buf, NULL, NULL, NULL); +        if (progcbk) +                progcbk (frame, cookie, this, op_ret, op_errno, path, buf); +        nfs_stack_destroy (frame); +        return 0; +} + + +int +nfs_fop_readlink (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc, +                  size_t size, fop_readlink_cbk_t cbk, void *local) +{ +        call_frame_t            *frame = NULL; +        int                     ret = -EFAULT; +        struct nfs_fop_local    *nfl = NULL; + +        if ((!xl) || (!pathloc) || (!nfu)) +                return ret; + +        gf_log (GF_NFS, GF_LOG_TRACE, "Readlink: %s", pathloc->path); +        nfs_fop_handle_frame_create (frame, xl, nfu, ret, err); +        nfs_fop_handle_local_init (frame, xl, nfl, cbk, local, ret, err); +        nfs_fop_save_root_ino (nfl, pathloc); + +        STACK_WIND_COOKIE  (frame, nfs_fop_readlink_cbk, xl, xl, +                            xl->fops->readlink, pathloc, size); +        ret = 0; +err: +        if (ret < 0) { +                if (frame) +                        nfs_stack_destroy (frame); +        } + +        return ret; +} + + +int32_t +nfs_fop_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_to_prog_data (this, nfl, progcbk, frame); +        nfs_fop_restore_root_ino (nfl, buf, NULL, preparent, postparent); +        if (progcbk) +                progcbk (frame, cookie, this, op_ret, op_errno, inode, buf, +                         preparent, postparent); +        nfs_stack_destroy (frame); +        return 0; +} + + +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) +{ +        call_frame_t            *frame = NULL; +        int                     ret = -EFAULT; +        struct nfs_fop_local    *nfl = NULL; + +        if ((!xl) || (!pathloc) || (!nfu)) +                return ret; + +        gf_log (GF_NFS, GF_LOG_TRACE, "Mknod: %s", pathloc->path); +        nfs_fop_handle_frame_create (frame, xl, nfu, ret, err); +        nfs_fop_handle_local_init (frame, xl, nfl, cbk, local, ret, err); +        nfs_fop_save_root_ino (nfl, pathloc); + +        STACK_WIND_COOKIE  (frame, nfs_fop_mknod_cbk, xl, xl, xl->fops->mknod, +                            pathloc, mode, dev); +        ret = 0; +err: +        if (ret < 0) { +                if (frame) +                        nfs_stack_destroy (frame); +        } + +        return ret; + +} + +int32_t +nfs_fop_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 = frame->local; +        fop_rmdir_cbk_t         progcbk = NULL; + +        nfl_to_prog_data (this, nfl, progcbk, frame); +        nfs_fop_restore_root_ino (nfl, NULL, NULL, preparent, postparent); +        if (progcbk) +                progcbk (frame, cookie, this, op_ret, op_errno, preparent, +                         postparent); +        nfs_stack_destroy (frame); +        return 0; +} + + + +int +nfs_fop_rmdir (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc, +               fop_rmdir_cbk_t cbk, void *local) +{ +        call_frame_t            *frame = NULL; +        int                     ret = -EFAULT; +        struct nfs_fop_local    *nfl = NULL; + +        if ((!xl) || (!pathloc) || (!nfu)) +                return ret; + +        gf_log (GF_NFS, GF_LOG_TRACE, "Rmdir: %s", pathloc->path); +        nfs_fop_handle_frame_create (frame, xl, nfu, ret, err); +        nfs_fop_handle_local_init (frame, xl, nfl, cbk, local, ret, err); +        nfs_fop_save_root_ino (nfl, pathloc); + +        STACK_WIND_COOKIE  (frame, nfs_fop_rmdir_cbk, xl, xl, xl->fops->rmdir, +                            pathloc); +        ret = 0; +err: +        if (ret < 0) { +                if (frame) +                        nfs_stack_destroy (frame); +        } + +        return ret; + +} + + +int32_t +nfs_fop_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 = frame->local; +        fop_unlink_cbk_t         progcbk = NULL; + +        nfl_to_prog_data (this, nfl, progcbk, frame); +        nfs_fop_restore_root_ino (nfl, NULL, NULL, preparent, postparent); +        if (progcbk) +                progcbk (frame, cookie, this, op_ret, op_errno, preparent, +                         postparent); +        nfs_stack_destroy (frame); +        return 0; +} + + +int +nfs_fop_unlink (xlator_t *xl, nfs_user_t *nfu, loc_t *pathloc, +                fop_unlink_cbk_t cbk, void *local) +{ +        call_frame_t            *frame = NULL; +        int                     ret = -EFAULT; +        struct nfs_fop_local    *nfl = NULL; + +        if ((!xl) || (!pathloc) || (!nfu)) +                return ret; + +        gf_log (GF_NFS, GF_LOG_TRACE, "Unlink: %s", pathloc->path); +        nfs_fop_handle_frame_create (frame, xl, nfu, ret, err); +        nfs_fop_handle_local_init (frame, xl, nfl, cbk, local, ret, err); +        nfs_fop_save_root_ino (nfl, pathloc); + +        STACK_WIND_COOKIE  (frame, nfs_fop_unlink_cbk, xl, xl, xl->fops->unlink, +                            pathloc); +        ret = 0; +err: +        if (ret < 0) { +                if (frame) +                        nfs_stack_destroy (frame); +        } + +        return ret; + +} + + +int32_t +nfs_fop_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; + +        nfl_to_prog_data (this, nfl, progcbk, frame); +        nfs_fop_restore_root_ino (nfl, buf, NULL, preparent, postparent); +        if (progcbk) +                progcbk (frame, cookie, this, op_ret, op_errno, inode, buf, +                         preparent, postparent); + +        nfs_stack_destroy (frame); +        return 0; +} + + +int +nfs_fop_link (xlator_t *xl, nfs_user_t *nfu, loc_t *oldloc, loc_t *newloc, +              fop_link_cbk_t cbk, void *local) +{ +        call_frame_t            *frame = NULL; +        int                     ret = -EFAULT; +        struct nfs_fop_local    *nfl = NULL; + +        if ((!xl) || (!oldloc) || (!newloc) || (!nfu)) +                return ret; + +        gf_log (GF_NFS, GF_LOG_TRACE, "Link: %s -> %s", newloc->path, +                oldloc->path); +        nfs_fop_handle_frame_create (frame, xl, nfu, ret, err); +        nfs_fop_handle_local_init (frame, xl, nfl, cbk, local, ret, err); +        nfs_fop_save_root_ino (nfl, newloc); + +        STACK_WIND_COOKIE (frame, nfs_fop_link_cbk, xl, xl, xl->fops->link, +                           oldloc, newloc); +        ret = 0; +err: +        if (ret < 0) { +                if (frame) +                        nfs_stack_destroy (frame); +        } + +        return ret; +} + + +int32_t +nfs_fop_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_to_prog_data (this, nfl, progcbk, frame); +        /* The preattr arg needs to be NULL instead of @buf because it is +         * possible that the new parent is not root whereas the source dir +         * could've been. That is handled in the next macro. +         */ +        nfs_fop_restore_root_ino (nfl, NULL, NULL, preoldparent, postoldparent); +        nfs_fop_newloc_restore_root_ino (nfl, buf, NULL, prenewparent, +                                         postnewparent); +        if (progcbk) +                progcbk (frame, cookie, this, op_ret, op_errno, buf, +                         preoldparent, postoldparent, prenewparent, +                         postnewparent); +        nfs_stack_destroy (frame); +        return 0; +} + + +int +nfs_fop_rename (xlator_t *xl, nfs_user_t *nfu, loc_t *oldloc, +                loc_t *newloc, fop_rename_cbk_t cbk, void *local) +{ +        call_frame_t            *frame = NULL; +        int                     ret = -EFAULT; +        struct nfs_fop_local    *nfl = NULL; + +        if ((!xl) || (!oldloc) || (!newloc) || (!nfu)) +                return ret; + +        gf_log (GF_NFS, GF_LOG_TRACE, "Rename: %s -> %s", oldloc->path, +                newloc->path); +        nfs_fop_handle_frame_create (frame, xl, nfu, ret, err); +        nfs_fop_handle_local_init (frame, xl, nfl, cbk, local, ret, err); +        nfs_fop_save_root_ino (nfl, oldloc); +        nfs_fop_newloc_save_root_ino (nfl, newloc); + +        STACK_WIND_COOKIE  (frame, nfs_fop_rename_cbk, xl, xl, xl->fops->rename, +                            oldloc, newloc); +        ret = 0; +err: +        if (ret < 0) { +                if (frame) +                        nfs_stack_destroy (frame); +        } + +        return ret; +} + + +int32_t +nfs_fop_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; + +        nfl_to_prog_data (this, nfl, progcbk, frame); +        if (progcbk) +                progcbk (frame, cookie, this, op_ret, op_errno, fd); +        nfs_stack_destroy (frame); + +        return 0; +} + +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) +{ +        call_frame_t            *frame = NULL; +        int                     ret = -EFAULT; +        struct nfs_fop_local    *nfl = NULL; + +        if ((!xl) || (!loc) || (!fd) || (!nfu)) +                return ret; + +        gf_log (GF_NFS, GF_LOG_TRACE, "Open: %s", loc->path); +        nfs_fop_handle_frame_create (frame, xl, nfu, ret, err); +        nfs_fop_handle_local_init (frame, xl, nfl, cbk, local, ret, err); + +        STACK_WIND_COOKIE  (frame, nfs_fop_open_cbk, xl, xl, xl->fops->open, +                            loc, flags, fd, wbflags); +        ret = 0; +err: +        if (ret < 0) { +                if (frame) +                        nfs_stack_destroy (frame); +        } + +        return ret; + +} + + +int32_t +nfs_fop_writev_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                    int32_t op_ret, int32_t op_errno, struct iatt *prebuf, +                    struct iatt *postbuf) +{ +        struct nfs_fop_local    *nfl = NULL; +        fop_writev_cbk_t        progcbk = NULL; + +        nfl_to_prog_data (this, nfl, progcbk, frame); +        nfs_fop_restore_root_ino (nfl, prebuf, postbuf, NULL, NULL); +        if (progcbk) +                progcbk (frame, cookie, this, op_ret, op_errno, prebuf,postbuf); + +        nfs_stack_destroy (frame); + +        return 0; +} + + +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) +{ +        call_frame_t            *frame = NULL; +        int                     ret = -EFAULT; +        struct nfs_fop_local    *nfl = NULL; + +        if ((!xl) || (!fd) || (!vector) || (!nfu) || (!srciob)) +                return ret; + +        nfs_fop_handle_frame_create (frame, xl, nfu, ret, err); +        nfs_fop_handle_local_init (frame, xl, nfl, cbk, local, ret, err); +        nfs_fop_save_root_fd_ino (nfl, fd); + +        nfl->iobref = iobref_new (); +        if (!nfl->iobref) { +                gf_log (GF_NFS, GF_LOG_ERROR, "iobref creation failed"); +                ret = -ENOMEM; +                goto err; +        } + +        iobref_add (nfl->iobref, srciob); +        STACK_WIND_COOKIE  (frame, nfs_fop_writev_cbk, xl, xl, xl->fops->writev +                            , fd, vector, count, offset, nfl->iobref); +        ret = 0; +err: +        if (ret < 0) { +                if (frame) +                        nfs_stack_destroy (frame); +                nfs_fop_local_wipe (xl, nfl); +        } + +        return ret; +} + + +int32_t +nfs_fop_fsync_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                   int32_t op_ret, int32_t op_errno, struct iatt *prebuf, +                   struct iatt *postbuf) +{ +        struct nfs_fop_local    *nfl = NULL; +        fop_fsync_cbk_t         progcbk = NULL; + +        nfl_to_prog_data (this, nfl, progcbk, frame); +        nfs_fop_restore_root_ino (nfl, prebuf, postbuf, NULL, NULL); +        if (progcbk) +                progcbk (frame, cookie, this, op_ret, op_errno, prebuf,postbuf); +        nfs_stack_destroy (frame); +        return 0; +} + + + +int +nfs_fop_fsync (xlator_t *xl, nfs_user_t *nfu, fd_t *fd, int32_t datasync, +               fop_fsync_cbk_t cbk, void *local) +{ +        call_frame_t            *frame = NULL; +        int                     ret = -EFAULT; +        struct nfs_fop_local    *nfl = NULL; + +        if ((!xl) || (!fd)) +                return ret; + +        nfs_fop_handle_frame_create (frame, xl, nfu, ret, err); +        nfs_fop_handle_local_init (frame, xl, nfl, cbk, local, ret, err); +        nfs_fop_save_root_fd_ino (nfl, fd); + +        STACK_WIND_COOKIE (frame, nfs_fop_fsync_cbk, xl, xl, +                           xl->fops->fsync, fd, datasync); +        ret = 0; +err: +        if (ret < 0) { +                if (frame) +                        nfs_stack_destroy (frame); +        } + +        return ret; +} + + +int32_t +nfs_fop_readv_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                   int32_t op_ret, int32_t op_errno, struct iovec *vector, +                   int32_t count, struct iatt *stbuf, struct iobref *iobref) +{ +        struct nfs_fop_local    *nfl = NULL; +        fop_readv_cbk_t         progcbk = NULL; + +        nfl_to_prog_data (this, nfl, progcbk, frame); +        nfs_fop_restore_root_ino (nfl, stbuf, NULL, NULL, NULL); +        if (progcbk) +                progcbk (frame, cookie, this, op_ret, op_errno, vector, count, +                         stbuf, iobref); + +        nfs_stack_destroy (frame); +        return 0; +} + + +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) +{ +        call_frame_t            *frame = NULL; +        int                     ret = -EFAULT; +        struct nfs_fop_local    *nfl = NULL; + +        if ((!xl) || (!fd) || (!nfu)) +                return ret; + +        nfs_fop_handle_frame_create (frame, xl, nfu, ret, err); +        nfs_fop_handle_local_init (frame, xl, nfl, cbk, local, ret, err); +        nfs_fop_save_root_fd_ino (nfl, fd); + +        STACK_WIND_COOKIE (frame, nfs_fop_readv_cbk, xl, xl, xl->fops->readv, fd +                           , size, offset); +        ret = 0; +err: +        if (ret < 0) { +                if (frame) +                        nfs_stack_destroy (frame); +        } + +        return ret; +} + + +int32_t +nfs_fop_truncate_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                      int32_t op_ret, int32_t op_errno, struct iatt *prebuf, +                      struct iatt *postbuf) +{ +        struct nfs_fop_local    *nfl = NULL; +        fop_truncate_cbk_t      progcbk = NULL; + +        nfl_to_prog_data (this, nfl, progcbk, frame); +        nfs_fop_restore_root_ino (nfl, prebuf, postbuf, NULL, NULL); +        if (progcbk) +                progcbk (frame, cookie, this, op_ret, op_errno, prebuf,postbuf); + +        nfs_stack_destroy (frame); +        return 0; +} + + +int +nfs_fop_truncate (xlator_t *xl, nfs_user_t *nfu, loc_t *loc, off_t offset, +                  fop_truncate_cbk_t cbk, void *local) +{ +        call_frame_t            *frame = NULL; +        int                     ret = -EFAULT; +        struct nfs_fop_local    *nfl = NULL; + +        if ((!xl) || (!loc) || (!nfu)) +                return ret; + +        nfs_fop_handle_frame_create (frame, xl, nfu, ret, err); +        nfs_fop_handle_local_init (frame, xl, nfl, cbk, local, ret, err); +        nfs_fop_save_root_ino (nfl, loc); + +        STACK_WIND_COOKIE  (frame, nfs_fop_truncate_cbk, xl, xl, +                            xl->fops->truncate, loc, offset); + +        ret = 0; +err: +        if (ret < 0) { +                if (frame) +                        nfs_stack_destroy (frame); +        } + +        return ret; +} + + +int +nfs_fop_lookup_sync_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) +{ +        nfs_syncfop_t   *sf = frame->local; + +        if (!sf) +                return -1; + +        if (op_ret == -1) +                gf_log (GF_NFS, GF_LOG_TRACE, "Sync lookup failed: %s", +                        strerror (op_errno)); +        else +                gf_log (GF_NFS, GF_LOG_TRACE, "Sync lookup done"); + +        sf->replystub = fop_lookup_cbk_stub (frame, NULL, op_ret, op_errno, +                                             inode, buf, xattr, postparent); +        nfs_syncfop_notify (sf); +        return 0; +} + + +call_stub_t * +nfs_fop_lookup_sync (xlator_t *xl, nfs_user_t *nfu, loc_t *loc) +{ +        nfs_syncfop_t   *sf = NULL; +        call_stub_t     *reply = NULL; +        int             ret = -1; + +        if ((!xl) || (!loc) || (!nfu)) +                return NULL; + +        sf = nfs_syncfop_init (); +        if (!sf) { +                gf_log (GF_NFS, GF_LOG_ERROR, "synclocal init failed"); +                goto err; +        } + +        ret = nfs_fop_lookup (xl, nfu, loc, nfs_fop_lookup_sync_cbk, sf); +        if (ret < 0) { +                gf_log (GF_NFS, GF_LOG_ERROR, "Sync lookup failed"); +                goto err; +        } + +        reply = nfs_syncfop_wait (sf); + +err: +        return reply; +} + + + +int32_t +nfs_fop_readdirp_sync_cbk (call_frame_t *frame, void *cookie, xlator_t *this, +                           int32_t op_ret, int32_t op_errno, +                           gf_dirent_t *entries) +{ +        nfs_syncfop_t   *sf = frame->local; + +        if (op_ret == -1) +                gf_log (GF_NFS, GF_LOG_TRACE, "Sync readdir failed: %s", +                        strerror (op_errno)); +        else +                gf_log (GF_NFS, GF_LOG_TRACE, "Sync readdir done"); + +        sf->replystub = fop_readdirp_cbk_stub (frame, NULL, op_ret, op_errno, +                                               entries); + +        nfs_syncfop_notify (sf); +        return 0; +} + + +/* This function does not update or map the st_dev in the d_stat of all the + * entries that were read. That mapping for the sync version of readdiring + * happens in the dcache. + */ +call_stub_t * +nfs_fop_readdirp_sync (xlator_t *fopxl, nfs_user_t *nfu, fd_t *dirfd, +                       off_t offset, size_t bufsize) +{ +        nfs_syncfop_t           *sf = NULL; +        call_stub_t             *reply = NULL; +        int                     ret = -1; + +        if ((!fopxl) || (!nfu) || (!dirfd)) +                return NULL; + +        sf = nfs_syncfop_init (); +        if (!sf) { +                gf_log (GF_NFS, GF_LOG_ERROR, "sync fop local init failed"); +                goto ret; +        } + +        ret = nfs_fop_readdirp (fopxl, nfu, dirfd, bufsize, offset, +                                nfs_fop_readdirp_sync_cbk, sf); +        if (ret < 0) { +                gf_log (GF_NFS, GF_LOG_ERROR, "Fop readdir failed: %s", +                        strerror (-ret)); +                goto ret; +        } + +        reply = nfs_syncfop_wait (sf); + +ret: +        return reply; +} + + + +nfs_syncfop_t * +nfs_syncfop_init () +{ +        nfs_syncfop_t   *sfl = NULL; + +        sfl = CALLOC (1, sizeof (*sfl)); +        if (!sfl) { +                gf_log (GF_NFS, GF_LOG_ERROR, "Memory allocation failed"); +                return NULL; +        } + +        sem_init (&sfl->replysig, 0, 0); + +        return sfl; +} + + +call_stub_t * +nfs_syncfop_wait (nfs_syncfop_t *s) +{ +        call_stub_t     *replystub = NULL; + +        gf_log (GF_NFS, GF_LOG_TRACE, "Waiting for sync fop"); +        sem_wait (&s->replysig); +        gf_log (GF_NFS, GF_LOG_TRACE, "Sync fop notification received"); +        replystub = s->replystub; +        FREE (s); +        return replystub; +} + + +void +nfs_syncfop_notify (nfs_syncfop_t *s) +{ +        sem_post (&s->replysig); +        gf_log (GF_NFS, GF_LOG_TRACE, "Sync fop notified"); +} + + +  | 
