diff options
Diffstat (limited to 'xlators/nfs/server/src/nfs3-helpers.c')
| -rw-r--r-- | xlators/nfs/server/src/nfs3-helpers.c | 5351 |
1 files changed, 3169 insertions, 2182 deletions
diff --git a/xlators/nfs/server/src/nfs3-helpers.c b/xlators/nfs/server/src/nfs3-helpers.c index 95e8601627d..897fb42b071 100644 --- a/xlators/nfs/server/src/nfs3-helpers.c +++ b/xlators/nfs/server/src/nfs3-helpers.c @@ -1,2930 +1,3917 @@ /* - Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com> + Copyright (c) 2010-2011 Gluster, Inc. <http://www.gluster.com> This file is part of GlusterFS. - GlusterFS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ -#ifndef _CONFIG_H -#define _CONFIG_H -#include "config.h" -#endif - #include <inttypes.h> -#include "xlator.h" +#include <glusterfs/xlator.h> #include "nfs3.h" #include "nfs3-fh.h" #include "msg-nfs3.h" -#include "rbthash.h" +#include <glusterfs/rbthash.h> #include "nfs-fops.h" #include "nfs-inodes.h" #include "nfs-generics.h" #include "nfs3-helpers.h" #include "nfs-mem-types.h" -#include "iatt.h" +#include <glusterfs/iatt.h> +#include <glusterfs/common-utils.h> +#include "nfs-messages.h" +#include "mount3.h" #include <string.h> -#define nfs3_call_resume(cst) \ - do { \ - if (((cst)) && (cst)->resume_fn) \ - (cst)->resume_fn (cst); \ - } while (0) \ +extern int +nfs3_set_root_looked_up(struct nfs3_state *nfs3, struct nfs3_fh *rootfh); + +extern int +nfs3_is_root_looked_up(struct nfs3_state *nfs3, struct nfs3_fh *rootfh); -#define nfs3_call_resume_estale(csta) \ - do { \ - (csta)->resolve_ret = -1; \ - (csta)->resolve_errno = ESTALE; \ - nfs3_call_resume (csta); \ - } while (0) \ +#define nfs3_call_resume(cst) \ + do { \ + if (((cst)) && (cst)->resume_fn) \ + (cst)->resume_fn(cst); \ + } while (0) + +#define nfs3_call_resume_estale(csta) \ + do { \ + (csta)->resolve_ret = -1; \ + (csta)->resolve_errno = ESTALE; \ + nfs3_call_resume(csta); \ + } while (0) struct nfs3stat_strerror { - nfsstat3 stat; - char strerror[100]; + nfsstat3 stat; + char strerror[100]; }; - struct nfs3stat_strerror nfs3stat_strerror_table[] = { - { NFS3_OK, "Call completed successfully." }, - { NFS3ERR_PERM, "Not owner" }, - { NFS3ERR_NOENT, "No such file or directory" }, - { NFS3ERR_IO, "I/O error" }, - { NFS3ERR_NXIO, "I/O error" }, - { NFS3ERR_ACCES, "Permission denied" }, - { NFS3ERR_EXIST, "File exists" }, - { NFS3ERR_XDEV, "Attempt to do a cross-device hard link"}, - { NFS3ERR_NODEV, "No such device" }, - { NFS3ERR_NOTDIR, "Not a directory" }, - { NFS3ERR_ISDIR, "Is a directory" }, - { NFS3ERR_INVAL, "Invalid argument for operation" }, - { NFS3ERR_FBIG, "File too large" }, - { NFS3ERR_NOSPC, "No space left on device" }, - { NFS3ERR_ROFS, "Read-only file system" }, - { NFS3ERR_MLINK, "Too many hard links" }, - { NFS3ERR_NAMETOOLONG, "Filename in operation was too long" }, - { NFS3ERR_NOTEMPTY, "Directory not empty" }, - { NFS3ERR_DQUOT, "Resource (quota) hard limit exceeded" }, - { NFS3ERR_STALE, "Invalid file handle" }, - { NFS3ERR_REMOTE, "Too many levels of remote in path" }, - { NFS3ERR_BADHANDLE, "Illegal NFS file handle" }, - { NFS3ERR_NOT_SYNC, "Update synchronization mismatch detected" }, - { NFS3ERR_BAD_COOKIE, "READDIR or READDIRPLUS cookie is stale"}, - { NFS3ERR_NOTSUPP, "Operation is not supported" }, - { NFS3ERR_TOOSMALL, "Buffer or request is too small" }, - { NFS3ERR_SERVERFAULT, "Error occurred on the server or IO Error" }, - { NFS3ERR_BADTYPE, "Type not supported by the server" }, - { NFS3ERR_JUKEBOX, "Cannot complete server initiated request" }, - { -1, "IO Error" }, + {NFS3_OK, "Call completed successfully."}, + {NFS3ERR_PERM, "Not owner"}, + {NFS3ERR_NOENT, "No such file or directory"}, + {NFS3ERR_IO, "I/O error"}, + {NFS3ERR_NXIO, "I/O error"}, + {NFS3ERR_ACCES, "Permission denied"}, + {NFS3ERR_EXIST, "File exists"}, + {NFS3ERR_XDEV, "Attempt to do a cross-device hard link"}, + {NFS3ERR_NODEV, "No such device"}, + {NFS3ERR_NOTDIR, "Not a directory"}, + {NFS3ERR_ISDIR, "Is a directory"}, + {NFS3ERR_INVAL, "Invalid argument for operation"}, + {NFS3ERR_FBIG, "File too large"}, + {NFS3ERR_NOSPC, "No space left on device"}, + {NFS3ERR_ROFS, "Read-only file system"}, + {NFS3ERR_MLINK, "Too many hard links"}, + {NFS3ERR_NAMETOOLONG, "Filename in operation was too long"}, + {NFS3ERR_NOTEMPTY, "Directory not empty"}, + {NFS3ERR_DQUOT, "Resource (quota) hard limit exceeded"}, + {NFS3ERR_STALE, "Invalid file handle"}, + {NFS3ERR_REMOTE, "Too many levels of remote in path"}, + {NFS3ERR_BADHANDLE, "Illegal NFS file handle"}, + {NFS3ERR_NOT_SYNC, "Update synchronization mismatch detected"}, + {NFS3ERR_BAD_COOKIE, "READDIR or READDIRPLUS cookie is stale"}, + {NFS3ERR_NOTSUPP, "Operation is not supported"}, + {NFS3ERR_TOOSMALL, "Buffer or request is too small"}, + {NFS3ERR_SERVERFAULT, "Error occurred on the server or IO Error"}, + {NFS3ERR_BADTYPE, "Type not supported by the server"}, + {NFS3ERR_JUKEBOX, "Cannot complete server initiated request"}, + {NFS3ERR_END_OF_LIST, "IO Error"}, }; +uint64_t +nfs3_iatt_gfid_to_ino(struct iatt *buf) +{ + uint64_t ino = 0; + + if (!buf) + return 0; + + if (gf_nfs_enable_ino32()) { + ino = (uint32_t)nfs_hash_gfid(buf->ia_gfid); + goto hashout; + } + + /* from posix its guaranteed to send unique ino */ + ino = buf->ia_ino; + +hashout: + return ino; +} void -nfs3_map_xlid_to_statdev (struct iatt *ia, uint16_t xlid) +nfs3_map_deviceid_to_statdev(struct iatt *ia, uint64_t deviceid) { - if (!ia) - return; + if (!ia) + return; - ia->ia_dev = xlid; + ia->ia_dev = deviceid; } - struct nfs3_fh -nfs3_extract_nfs3_fh (nfs_fh3 fh) +nfs3_extract_nfs3_fh(nfs_fh3 fh) { - struct nfs3_fh gfh; + struct nfs3_fh gfh; - memcpy (&gfh, fh.data.data_val, fh.data.data_len); - return gfh; + memcpy(&gfh, fh.data.data_val, fh.data.data_len); + return gfh; } - struct nfs3_fh -nfs3_extract_lookup_fh (lookup3args *args) +nfs3_extract_lookup_fh(lookup3args *args) { - return nfs3_extract_nfs3_fh(args->what.dir); + return nfs3_extract_nfs3_fh(args->what.dir); } - char * -nfs3_extract_lookup_name (lookup3args *args) +nfs3_extract_lookup_name(lookup3args *args) { - return args->what.name; + return args->what.name; } - nfsstat3 -nfs3_errno_to_nfsstat3 (int errnum) +nfs3_errno_to_nfsstat3(int errnum) { - nfsstat3 stat = NFS3_OK; - - switch (errnum) { + nfsstat3 stat = NFS3_OK; + switch (errnum) { case 0: - stat = NFS3_OK; - break; + stat = NFS3_OK; + break; case EPERM: - stat = NFS3ERR_PERM; - break; + stat = NFS3ERR_PERM; + break; case ENOENT: - stat = NFS3ERR_NOENT; - break; + stat = NFS3ERR_NOENT; + break; case EACCES: - stat = NFS3ERR_ACCES; - break; + stat = NFS3ERR_ACCES; + break; case EEXIST: - stat = NFS3ERR_EXIST; - break; + stat = NFS3ERR_EXIST; + break; case EXDEV: - stat = NFS3ERR_XDEV; - break; + stat = NFS3ERR_XDEV; + break; case ENODEV: - stat = NFS3ERR_NODEV; - break; + stat = NFS3ERR_NODEV; + break; case EIO: - stat = NFS3ERR_IO; - break; + stat = NFS3ERR_IO; + break; case ENXIO: - stat = NFS3ERR_NXIO; - break; + stat = NFS3ERR_NXIO; + break; case ENOTDIR: - stat = NFS3ERR_NOTDIR; - break; + stat = NFS3ERR_NOTDIR; + break; case EISDIR: - stat = NFS3ERR_ISDIR; - break; + stat = NFS3ERR_ISDIR; + break; case EINVAL: - stat = NFS3ERR_INVAL; - break; + stat = NFS3ERR_INVAL; + break; case ENOSPC: - stat = NFS3ERR_NOSPC; - break; + stat = NFS3ERR_NOSPC; + break; case EROFS: - stat = NFS3ERR_ROFS; - break; + stat = NFS3ERR_ROFS; + break; case EFBIG: - stat = NFS3ERR_FBIG; - break; + stat = NFS3ERR_FBIG; + break; case EMLINK: - stat = NFS3ERR_MLINK; - break; + stat = NFS3ERR_MLINK; + break; case ENAMETOOLONG: - stat = NFS3ERR_NAMETOOLONG; - break; + stat = NFS3ERR_NAMETOOLONG; + break; case ENOTEMPTY: - stat = NFS3ERR_NOTEMPTY; - break; + stat = NFS3ERR_NOTEMPTY; + break; case EFAULT: - stat = NFS3ERR_SERVERFAULT; - break; + stat = NFS3ERR_SERVERFAULT; + break; + case ENOTSUP: case ENOSYS: - stat = NFS3ERR_NOTSUPP; - break; + stat = NFS3ERR_NOTSUPP; + break; case EBADF: - stat = NFS3ERR_BADTYPE; - break; + stat = NFS3ERR_BADTYPE; + break; case ESTALE: - stat = NFS3ERR_STALE; + stat = NFS3ERR_STALE; + break; + + case ENOTCONN: + stat = NFS3ERR_IO; + break; + + case EDQUOT: + stat = NFS3ERR_DQUOT; + break; default: - stat = NFS3ERR_SERVERFAULT; - break; - } + stat = NFS3ERR_SERVERFAULT; + break; + } - return stat; + return stat; } - -void -nfs3_fill_lookup3res_error (lookup3res *res, nfsstat3 stat, - struct iatt *dirstat) +/* + * Special case: If op_ret is -1, it's very unusual op_errno being + * 0 which means something came wrong from upper layer(s). If it + * happens by any means, then set NFS3 status to NFS3ERR_SERVERFAULT. + */ +nfsstat3 +nfs3_cbk_errno_status(int32_t op_ret, int32_t op_errno) { + if ((op_ret == -1) && (op_errno == 0)) { + return NFS3ERR_SERVERFAULT; + } - memset (res, 0, sizeof (*res)); - res->status = stat; - if (!dirstat) { - res->lookup3res_u.resfail.dir_attributes.attributes_follow = FALSE; - } - + return nfs3_errno_to_nfsstat3(op_errno); } -fattr3 -nfs3_stat_to_fattr3 (struct iatt *buf) -{ - fattr3 fa = {0, }; - - if (IA_ISDIR (buf->ia_type)) - fa.type = NF3DIR; - else if (IA_ISREG (buf->ia_type)) - fa.type = NF3REG; - else if (IA_ISCHR (buf->ia_type)) - fa.type = NF3CHR; - else if (IA_ISBLK (buf->ia_type)) - fa.type = NF3BLK; - else if (IA_ISFIFO (buf->ia_type)) - fa.type = NF3FIFO; - else if (IA_ISLNK (buf->ia_type)) - fa.type = NF3LNK; - else if (IA_ISSOCK (buf->ia_type)) - fa.type = NF3SOCK; - - if (IA_PROT_RUSR (buf->ia_prot)) - fa.mode |= NFS3MODE_ROWNER; - if (IA_PROT_WUSR (buf->ia_prot)) - fa.mode |= NFS3MODE_WOWNER; - if (IA_PROT_XUSR (buf->ia_prot)) - fa.mode |= NFS3MODE_XOWNER; - - if (IA_PROT_RGRP (buf->ia_prot)) - fa.mode |= NFS3MODE_RGROUP; - if (IA_PROT_WGRP (buf->ia_prot)) - fa.mode |= NFS3MODE_WGROUP; - if (IA_PROT_XGRP (buf->ia_prot)) - fa.mode |= NFS3MODE_XGROUP; - - if (IA_PROT_ROTH (buf->ia_prot)) - fa.mode |= NFS3MODE_ROTHER; - if (IA_PROT_WOTH (buf->ia_prot)) - fa.mode |= NFS3MODE_WOTHER; - if (IA_PROT_XOTH (buf->ia_prot)) - fa.mode |= NFS3MODE_XOTHER; - - if (IA_PROT_SUID (buf->ia_prot)) - fa.mode |= NFS3MODE_SETXUID; - if (IA_PROT_SGID (buf->ia_prot)) - fa.mode |= NFS3MODE_SETXGID; - if (IA_PROT_STCKY (buf->ia_prot)) - fa.mode |= NFS3MODE_SAVESWAPTXT; - - fa.nlink = buf->ia_nlink; - fa.uid = buf->ia_uid; - fa.gid = buf->ia_gid; - fa.size = buf->ia_size; - fa.used = (buf->ia_blocks * 512); - - if ((IA_ISCHR (buf->ia_type) || IA_ISBLK (buf->ia_type))) { - fa.rdev.specdata1 = ia_major (buf->ia_rdev); - fa.rdev.specdata2 = ia_minor (buf->ia_rdev); - } else { - fa.rdev.specdata1 = 0; - fa.rdev.specdata2 = 0; - } - - fa.fsid = buf->ia_dev; - fa.fileid = buf->ia_ino; - /* FIXME: Handle time resolutions for sub-second granularity */ - if (buf->ia_atime == 9669) { - fa.mtime.seconds = 0; - fa.mtime.nseconds = 0; - fa.atime.seconds = 0; - fa.atime.nseconds = 0; - } else { - fa.mtime.seconds = buf->ia_mtime; - fa.mtime.nseconds = 0; - fa.atime.seconds = buf->ia_atime; - fa.atime.seconds = 0; - fa.atime.nseconds = 0; - } - - fa.atime.seconds = buf->ia_atime; - fa.atime.nseconds = 0; - - fa.ctime.seconds = buf->ia_ctime; - fa.ctime.nseconds = 0; - - return fa; +void +nfs3_fill_lookup3res_error(lookup3res *res, nfsstat3 stat, struct iatt *dirstat) +{ + memset(res, 0, sizeof(*res)); + res->status = stat; + if (!dirstat) { + res->lookup3res_u.resfail.dir_attributes.attributes_follow = FALSE; + } } +void +nfs3_stat_to_fattr3(struct iatt *buf, fattr3 *fa) +{ + if (buf == NULL || fa == NULL) { + errno = EINVAL; + return; + } + + if (IA_ISDIR(buf->ia_type)) + fa->type = NF3DIR; + else if (IA_ISREG(buf->ia_type)) + fa->type = NF3REG; + else if (IA_ISCHR(buf->ia_type)) + fa->type = NF3CHR; + else if (IA_ISBLK(buf->ia_type)) + fa->type = NF3BLK; + else if (IA_ISFIFO(buf->ia_type)) + fa->type = NF3FIFO; + else if (IA_ISLNK(buf->ia_type)) + fa->type = NF3LNK; + else if (IA_ISSOCK(buf->ia_type)) + fa->type = NF3SOCK; + + if (IA_PROT_RUSR(buf->ia_prot)) + fa->mode |= NFS3MODE_ROWNER; + if (IA_PROT_WUSR(buf->ia_prot)) + fa->mode |= NFS3MODE_WOWNER; + if (IA_PROT_XUSR(buf->ia_prot)) + fa->mode |= NFS3MODE_XOWNER; + + if (IA_PROT_RGRP(buf->ia_prot)) + fa->mode |= NFS3MODE_RGROUP; + if (IA_PROT_WGRP(buf->ia_prot)) + fa->mode |= NFS3MODE_WGROUP; + if (IA_PROT_XGRP(buf->ia_prot)) + fa->mode |= NFS3MODE_XGROUP; + + if (IA_PROT_ROTH(buf->ia_prot)) + fa->mode |= NFS3MODE_ROTHER; + if (IA_PROT_WOTH(buf->ia_prot)) + fa->mode |= NFS3MODE_WOTHER; + if (IA_PROT_XOTH(buf->ia_prot)) + fa->mode |= NFS3MODE_XOTHER; + + if (IA_PROT_SUID(buf->ia_prot)) + fa->mode |= NFS3MODE_SETXUID; + if (IA_PROT_SGID(buf->ia_prot)) + fa->mode |= NFS3MODE_SETXGID; + if (IA_PROT_STCKY(buf->ia_prot)) + fa->mode |= NFS3MODE_SAVESWAPTXT; + + fa->nlink = buf->ia_nlink; + fa->uid = buf->ia_uid; + fa->gid = buf->ia_gid; + fa->size = buf->ia_size; + fa->used = (buf->ia_blocks * 512); + + if ((IA_ISCHR(buf->ia_type) || IA_ISBLK(buf->ia_type))) { + fa->rdev.specdata1 = ia_major(buf->ia_rdev); + fa->rdev.specdata2 = ia_minor(buf->ia_rdev); + } else { + fa->rdev.specdata1 = 0; + fa->rdev.specdata2 = 0; + } + + fa->fsid = buf->ia_dev; + fa->fileid = nfs3_iatt_gfid_to_ino(buf); + + fa->atime.seconds = buf->ia_atime; + fa->atime.nseconds = buf->ia_atime_nsec; + + fa->ctime.seconds = buf->ia_ctime; + fa->ctime.nseconds = buf->ia_ctime_nsec; + + fa->mtime.seconds = buf->ia_mtime; + fa->mtime.nseconds = buf->ia_mtime_nsec; +} post_op_attr -nfs3_stat_to_post_op_attr (struct iatt *buf) +nfs3_stat_to_post_op_attr(struct iatt *buf) { - post_op_attr attr = {0, }; - if (!buf) - return attr; + post_op_attr attr = { + 0, + }; + if (!buf) + return attr; - /* Some performance translators return zero-filled stats when they - * do not have up-to-date attributes. Need to handle this by not - * returning these zeroed out attrs. - */ - attr.attributes_follow = FALSE; - if (nfs_zero_filled_stat (buf)) - goto out; + /* Some performance translators return zero-filled stats when they + * do not have up-to-date attributes. Need to handle this by not + * returning these zeroed out attrs. + */ + attr.attributes_follow = FALSE; + if (gf_is_zero_filled_stat(buf)) + goto out; - attr.post_op_attr_u.attributes = nfs3_stat_to_fattr3 (buf); - attr.attributes_follow = TRUE; + nfs3_stat_to_fattr3(buf, &(attr.post_op_attr_u.attributes)); + attr.attributes_follow = TRUE; out: - return attr; + return attr; } - pre_op_attr -nfs3_stat_to_pre_op_attr (struct iatt *pre) -{ - pre_op_attr poa = {0, }; - - /* Some performance translators return zero-filled stats when they - * do not have up-to-date attributes. Need to handle this by not - * returning these zeroed out attrs. - */ - poa.attributes_follow = FALSE; - if (nfs_zero_filled_stat (pre)) - goto out; - - poa.attributes_follow = TRUE; - poa.pre_op_attr_u.attributes.size = pre->ia_size; - if (pre->ia_atime == 9669) - poa.pre_op_attr_u.attributes.mtime.seconds = 0; - else - poa.pre_op_attr_u.attributes.mtime.seconds = pre->ia_mtime; - poa.pre_op_attr_u.attributes.ctime.seconds = pre->ia_ctime; +nfs3_stat_to_pre_op_attr(struct iatt *pre) +{ + pre_op_attr poa = { + 0, + }; + + /* Some performance translators return zero-filled stats when they + * do not have up-to-date attributes. Need to handle this by not + * returning these zeroed out attrs. + */ + poa.attributes_follow = FALSE; + if (gf_is_zero_filled_stat(pre)) + goto out; + + poa.attributes_follow = TRUE; + poa.pre_op_attr_u.attributes.size = pre->ia_size; + poa.pre_op_attr_u.attributes.mtime.seconds = pre->ia_mtime; + poa.pre_op_attr_u.attributes.mtime.nseconds = pre->ia_mtime_nsec; + poa.pre_op_attr_u.attributes.ctime.seconds = pre->ia_ctime; + poa.pre_op_attr_u.attributes.ctime.nseconds = pre->ia_ctime_nsec; out: - return poa; + return poa; } void -nfs3_fill_lookup3res_success (lookup3res *res, nfsstat3 stat, - struct nfs3_fh *fh, struct iatt *buf, - struct iatt *postparent) +nfs3_fill_lookup3res_success(lookup3res *res, nfsstat3 stat, struct nfs3_fh *fh, + struct iatt *buf, struct iatt *postparent) { - post_op_attr obj, dir; - uint32_t fhlen = 0; + post_op_attr obj, dir; + uint32_t fhlen = 0; - res->status = stat; - if (fh) { - res->lookup3res_u.resok.object.data.data_val = (void *)fh; - fhlen = nfs3_fh_compute_size (fh); - res->lookup3res_u.resok.object.data.data_len = fhlen; - } + res->status = stat; + if (fh) { + res->lookup3res_u.resok.object.data.data_val = (void *)fh; + fhlen = nfs3_fh_compute_size(); + res->lookup3res_u.resok.object.data.data_len = fhlen; + } - obj.attributes_follow = FALSE; - dir.attributes_follow = FALSE; - if (buf) { - nfs3_map_xlid_to_statdev (buf, fh->xlatorid); - obj = nfs3_stat_to_post_op_attr (buf); - } - - if (postparent) { - nfs3_map_xlid_to_statdev (postparent, fh->xlatorid); - dir = nfs3_stat_to_post_op_attr (postparent); - } + obj.attributes_follow = FALSE; + dir.attributes_follow = FALSE; + obj = nfs3_stat_to_post_op_attr(buf); + dir = nfs3_stat_to_post_op_attr(postparent); - res->lookup3res_u.resok.obj_attributes = obj; - res->lookup3res_u.resok.dir_attributes = dir; + res->lookup3res_u.resok.obj_attributes = obj; + res->lookup3res_u.resok.dir_attributes = dir; } - void -nfs3_fill_lookup3res (lookup3res *res, nfsstat3 stat, struct nfs3_fh *newfh, - struct iatt *buf, struct iatt *postparent) +nfs3_fill_lookup3res(lookup3res *res, nfsstat3 stat, struct nfs3_fh *newfh, + struct iatt *buf, struct iatt *postparent, + uint64_t deviceid) { - - memset (res, 0, sizeof (*res)); - if (stat != NFS3_OK) - nfs3_fill_lookup3res_error (res, stat, postparent); - else - nfs3_fill_lookup3res_success (res, stat, newfh, buf, - postparent); + memset(res, 0, sizeof(*res)); + nfs3_map_deviceid_to_statdev(buf, deviceid); + nfs3_map_deviceid_to_statdev(postparent, deviceid); + if (stat != NFS3_OK) + nfs3_fill_lookup3res_error(res, stat, postparent); + else + nfs3_fill_lookup3res_success(res, stat, newfh, buf, postparent); } struct nfs3_fh -nfs3_extract_getattr_fh (getattr3args *args) +nfs3_extract_getattr_fh(getattr3args *args) { - return nfs3_extract_nfs3_fh(args->object); + return nfs3_extract_nfs3_fh(args->object); } - void -nfs3_fill_getattr3res (getattr3res *res, nfsstat3 stat, struct iatt *buf, - uint16_t xlid) +nfs3_fill_getattr3res(getattr3res *res, nfsstat3 stat, struct iatt *buf, + uint64_t deviceid) { + memset(res, 0, sizeof(*res)); + res->status = stat; + if (stat != NFS3_OK) + return; - memset (res, 0, sizeof (*res)); - res->status = stat; - if (stat != NFS3_OK) - return; - - nfs3_map_xlid_to_statdev (buf, xlid); - res->getattr3res_u.resok.obj_attributes = nfs3_stat_to_fattr3 (buf); - + nfs3_map_deviceid_to_statdev(buf, deviceid); + nfs3_stat_to_fattr3(buf, &(res->getattr3res_u.resok.obj_attributes)); } - struct nfs3_fh -nfs3_extract_fsinfo_fh (fsinfo3args *args) +nfs3_extract_fsinfo_fh(fsinfo3args *args) { - return nfs3_extract_nfs3_fh (args->fsroot); + return nfs3_extract_nfs3_fh(args->fsroot); } - void -nfs3_fill_fsinfo3res (struct nfs3_state *nfs3, fsinfo3res *res, - nfsstat3 status, struct iatt *fsroot, uint16_t xlid) +nfs3_fill_fsinfo3res(struct nfs3_state *nfs3, fsinfo3res *res, nfsstat3 status, + struct iatt *fsroot, uint64_t deviceid) { - fsinfo3resok resok = {{0}, }; - nfstime3 tdelta = GF_NFS3_TIMEDELTA_SECS; - - memset (res, 0, sizeof (*res)); - res->status = status; - if (status != NFS3_OK) - return; + fsinfo3resok resok = { + {0}, + }; + nfstime3 tdelta = GF_NFS3_TIMEDELTA_SECS; - nfs3_map_xlid_to_statdev (fsroot, xlid); - resok.obj_attributes = nfs3_stat_to_post_op_attr (fsroot); - resok.rtmax = nfs3->readsize; - resok.rtpref = nfs3->readsize; - resok.rtmult = GF_NFS3_RTMULT; - resok.wtmax = nfs3->writesize; - resok.wtpref = nfs3->writesize; - resok.wtmult = GF_NFS3_WTMULT; - resok.dtpref = nfs3->readdirsize; - resok.maxfilesize = GF_NFS3_MAXFILE; - resok.time_delta = tdelta; - resok.properties = GF_NFS3_FS_PROP; + memset(res, 0, sizeof(*res)); + res->status = status; + if (status != NFS3_OK) + return; - res->fsinfo3res_u.resok = resok; + nfs3_map_deviceid_to_statdev(fsroot, deviceid); + resok.obj_attributes = nfs3_stat_to_post_op_attr(fsroot); + resok.rtmax = nfs3->readsize; + resok.rtpref = nfs3->readsize; + resok.rtmult = GF_NFS3_RTMULT; + resok.wtmax = nfs3->writesize; + resok.wtpref = nfs3->writesize; + resok.wtmult = GF_NFS3_WTMULT; + resok.dtpref = nfs3->readdirsize; + resok.maxfilesize = GF_NFS3_MAXFILESIZE; + resok.time_delta = tdelta; + resok.properties = GF_NFS3_FS_PROP; + res->fsinfo3res_u.resok = resok; } - void -nfs3_prep_lookup3args (lookup3args *args, struct nfs3_fh *fh, char *name) +nfs3_prep_lookup3args(lookup3args *args, struct nfs3_fh *fh, char *name) { - memset (args, 0, sizeof (*args)); - args->what.dir.data.data_val = (void *)fh; - args->what.name = name; + memset(args, 0, sizeof(*args)); + args->what.dir.data.data_val = (void *)fh; + args->what.name = name; } - void -nfs3_prep_getattr3args (getattr3args *args, struct nfs3_fh *fh) +nfs3_prep_getattr3args(getattr3args *args, struct nfs3_fh *fh) { - memset (args, 0, sizeof (*args)); - args->object.data.data_val = (void *)fh; + memset(args, 0, sizeof(*args)); + args->object.data.data_val = (void *)fh; } - void -nfs3_prep_fsinfo3args (fsinfo3args *args, struct nfs3_fh *root) +nfs3_prep_fsinfo3args(fsinfo3args *args, struct nfs3_fh *root) { - memset (args, 0, sizeof (*args)); - args->fsroot.data.data_val = (void *)root; + memset(args, 0, sizeof(*args)); + args->fsroot.data.data_val = (void *)root; } - char * nfsstat3_strerror(int stat) { - int i; - for(i = 0; nfs3stat_strerror_table[i].stat != -1; i++) { - if (nfs3stat_strerror_table[i].stat == stat) - return nfs3stat_strerror_table[i].strerror; - } + int i; + for (i = 0; nfs3stat_strerror_table[i].stat != NFS3ERR_END_OF_LIST; i++) { + if (nfs3stat_strerror_table[i].stat == stat) + return nfs3stat_strerror_table[i].strerror; + } - return nfs3stat_strerror_table[i].strerror; + return nfs3stat_strerror_table[i].strerror; } - - void -nfs3_prep_access3args (access3args *args, struct nfs3_fh *fh) +nfs3_prep_access3args(access3args *args, struct nfs3_fh *fh) { - memset (args, 0, sizeof (*args)); - args->object.data.data_val = (void *)fh; + memset(args, 0, sizeof(*args)); + args->object.data.data_val = (void *)fh; } +#define POSIX_READ 4 +#define POSIX_WRITE 2 +#define POSIX_EXEC 1 uint32_t -nfs3_owner_accessbits (ia_prot_t prot, ia_type_t type, uint32_t request) +nfs3_accessbits(int32_t accbits) { - uint32_t accresult = 0; - - if (IA_PROT_RUSR (prot) && (request & ACCESS3_READ)) - accresult |= ACCESS3_READ; - - if (request & ACCESS3_LOOKUP) - if ((IA_ISDIR (type)) && (IA_PROT_XUSR (prot))) - accresult |= ACCESS3_LOOKUP; + uint32_t accresult = 0; - if ((IA_PROT_WUSR (prot) && (request & ACCESS3_MODIFY))) - accresult |= ACCESS3_MODIFY; + if (accbits & POSIX_READ) + accresult |= ACCESS3_READ; - if ((IA_PROT_WUSR (prot) && (request & ACCESS3_EXTEND))) - accresult |= ACCESS3_EXTEND; + if (accbits & POSIX_WRITE) + accresult |= (ACCESS3_MODIFY | ACCESS3_EXTEND | ACCESS3_DELETE); - /* ACCESS3_DELETE is ignored for now since that requires - * knowing the permissions on the parent directory. - */ - - if (request & ACCESS3_EXECUTE) - if (IA_PROT_XUSR (prot) && (!IA_ISDIR (type))) - accresult |= ACCESS3_EXECUTE; + /* lookup on directory allowed only in case of execute permission */ + if (accbits & POSIX_EXEC) + accresult |= (ACCESS3_EXECUTE | ACCESS3_LOOKUP); - return accresult; + return accresult; } - uint32_t -nfs3_group_accessbits (ia_prot_t prot, ia_type_t type, uint32_t request) +nfs3_request_to_accessbits(int32_t accbits) { - uint32_t accresult = 0; + uint32_t acc_request = 0; - if (IA_PROT_RGRP (prot) && (request & ACCESS3_READ)) - accresult |= ACCESS3_READ; + if (accbits & ACCESS3_READ) + acc_request |= POSIX_READ; - if (request & ACCESS3_LOOKUP) - if ((IA_ISDIR (type)) && IA_PROT_RGRP (prot)) - accresult |= ACCESS3_LOOKUP; + if (accbits & (ACCESS3_MODIFY | ACCESS3_EXTEND | ACCESS3_DELETE)) + acc_request |= POSIX_WRITE; - if (IA_PROT_WGRP (prot) && (request & ACCESS3_MODIFY)) - accresult |= ACCESS3_MODIFY; + /* For lookup on directory check for execute permission */ + if (accbits & (ACCESS3_EXECUTE | ACCESS3_LOOKUP)) + acc_request |= POSIX_EXEC; - if (IA_PROT_WGRP (prot) && (request & ACCESS3_EXTEND)) - accresult |= ACCESS3_EXTEND; - - /* ACCESS3_DELETE is ignored for now since that requires - * knowing the permissions on the parent directory. - */ - - if (request & ACCESS3_EXECUTE) - if (IA_PROT_XGRP (prot) && (!IA_ISDIR (type))) - accresult |= ACCESS3_EXECUTE; - - return accresult; + return acc_request; } - - -uint32_t -nfs3_other_accessbits (ia_prot_t prot, ia_type_t type, uint32_t request) -{ - uint32_t accresult = 0; - - if (IA_PROT_ROTH (prot) && (request & ACCESS3_READ)) - accresult |= ACCESS3_READ; - - if (request & ACCESS3_LOOKUP) - if (IA_ISDIR (type) && IA_PROT_ROTH (prot)) - accresult |= ACCESS3_LOOKUP; - - if (IA_PROT_WOTH (prot) && (request & ACCESS3_MODIFY)) - accresult |= ACCESS3_MODIFY; - - if (IA_PROT_WOTH (prot) && (request & ACCESS3_EXTEND)) - accresult |= ACCESS3_EXTEND; - - /* ACCESS3_DELETE is ignored for now since that requires - * knowing the permissions on the parent directory. - */ - - if (request & ACCESS3_EXECUTE) - if (IA_PROT_XOTH (prot) && (!IA_ISDIR (type))) - accresult |= ACCESS3_EXECUTE; - - return accresult; -} - - -uint32_t -nfs3_superuser_accessbits (ia_prot_t prot, ia_type_t type, uint32_t request) -{ - uint32_t accresult = 0; - - if (request & ACCESS3_READ) - accresult |= ACCESS3_READ; - - if (request & ACCESS3_LOOKUP) - if (IA_ISDIR (type)) - accresult |= ACCESS3_LOOKUP; - - if (request & ACCESS3_MODIFY) - accresult |= ACCESS3_MODIFY; - - if (request & ACCESS3_EXTEND) - accresult |= ACCESS3_EXTEND; - - /* ACCESS3_DELETE is ignored for now since that requires - * knowing the permissions on the parent directory. - */ - - if (request & ACCESS3_EXECUTE) - if ((IA_PROT_XOTH (prot) || IA_PROT_XUSR (prot) || - IA_PROT_XGRP (prot)) && (!IA_ISDIR (type))) - accresult |= ACCESS3_EXECUTE; - - return accresult; -} - - -uint32_t -nfs3_stat_to_accessbits (struct iatt *buf, uint32_t request, uid_t uid, - gid_t gid) -{ - uint32_t accresult = 0; - ia_prot_t prot = {0, }; - ia_type_t type = 0; - - prot = buf->ia_prot; - type = buf->ia_type; - - if (uid == 0) - accresult = nfs3_superuser_accessbits (prot, type, request); - else if (buf->ia_uid == uid) - accresult = nfs3_owner_accessbits (prot, type, request); - else if (buf->ia_gid == gid) - accresult = nfs3_group_accessbits (prot, type, request); - else - accresult = nfs3_other_accessbits (prot, type, request); - - return accresult; -} - - void -nfs3_fill_access3res (access3res *res, nfsstat3 status, struct iatt *buf, - uint32_t accbits, uid_t uid, gid_t gid, uint16_t xlid) +nfs3_fill_access3res(access3res *res, nfsstat3 status, int32_t accbits, + int32_t reqaccbits) { - post_op_attr objattr; - uint32_t accres = 0; + uint32_t accres = 0; - memset (res, 0, sizeof (*res)); - res->status = status; - if (status != NFS3_OK) - return; + memset(res, 0, sizeof(*res)); + res->status = status; + if (status != NFS3_OK) + return; - nfs3_map_xlid_to_statdev (buf, xlid); - objattr = nfs3_stat_to_post_op_attr (buf); - accres = nfs3_stat_to_accessbits (buf, accbits, uid, gid); + accres = nfs3_accessbits(accbits); - res->access3res_u.resok.obj_attributes = objattr; - res->access3res_u.resok.access = accres; + /* do not answer what was not asked */ + res->access3res_u.resok.access = accres & reqaccbits; } void -nfs3_prep_readdir3args (readdir3args *ra, struct nfs3_fh *fh) +nfs3_prep_readdir3args(readdir3args *ra, struct nfs3_fh *fh) { - memset (ra, 0, sizeof (*ra)); - ra->dir.data.data_val = (void *)fh; + memset(ra, 0, sizeof(*ra)); + ra->dir.data.data_val = (void *)fh; } - int -nfs3_is_dot_entry (char *entry) +nfs3_is_dot_entry(char *entry) { - int ret = 0; + int ret = 0; - if (!entry) - return 0; + if (!entry) + return 0; - if (strcmp (entry, ".") == 0) - ret = 1; + if (strcmp(entry, ".") == 0) + ret = 1; - return ret; + return ret; } - int -nfs3_is_parentdir_entry (char *entry) +nfs3_is_parentdir_entry(char *entry) { - int ret = 0; + int ret = 0; - if (!entry) - return 0; + if (!entry) + return 0; - if (strcmp (entry, "..") == 0) - ret = 1; + if (strcmp(entry, "..") == 0) + ret = 1; - return ret; + return ret; } - void -nfs3_funge_root_dotdot_dirent (gf_dirent_t *ent, struct nfs3_fh *dfh) +nfs3_funge_root_dotdot_dirent(gf_dirent_t *ent, struct nfs3_fh *dfh) { - if ((!ent) || (!dfh)) - return; - - if (nfs3_fh_is_root_fh (dfh) && - nfs3_is_parentdir_entry (ent->d_name)) { - ent->d_ino = 1; - ent->d_stat.ia_ino = 1; - ent->d_stat.ia_gen = 0; - } + if ((!ent) || (!dfh)) + return; - if (nfs3_fh_is_root_fh (dfh) && - nfs3_is_dot_entry (ent->d_name)) { - ent->d_ino = 1; - ent->d_stat.ia_ino = 1; - ent->d_stat.ia_gen = 0; - } + if (nfs3_fh_is_root_fh(dfh) && nfs3_is_parentdir_entry(ent->d_name)) { + ent->d_ino = 1; + ent->d_stat.ia_ino = 1; + } + if (nfs3_fh_is_root_fh(dfh) && nfs3_is_dot_entry(ent->d_name)) { + ent->d_ino = 1; + ent->d_stat.ia_ino = 1; + } } - entry3 * -nfs3_fill_entry3 (gf_dirent_t *entry, struct nfs3_fh *dfh) -{ - entry3 *ent = NULL; - if ((!entry) || (!dfh)) - return NULL; - - ent = GF_CALLOC (1, sizeof (*ent), gf_nfs_mt_entry3); - if (!ent) - return NULL; - - gf_log (GF_NFS3, GF_LOG_TRACE, "Entry: %s", entry->d_name); - - /* If the entry is . or .., we need to replace the physical ino and gen - * with 1 and 0 respectively if the directory is root. This funging is - * needed because there is no parent directory of the root. In that - * sense the behavious we provide is similar to the output of the - * command: "stat /.." - */ - nfs3_funge_root_dotdot_dirent (entry, dfh); - ent->fileid = entry->d_ino; - ent->cookie = entry->d_off; - ent->name = GF_CALLOC ((strlen (entry->d_name) + 1), sizeof (char), - gf_nfs_mt_char); - if (!ent->name) { - GF_FREE (ent); - ent = NULL; - goto err; - } - strcpy (ent->name, entry->d_name); +nfs3_fill_entry3(gf_dirent_t *entry, struct nfs3_fh *dfh) +{ + entry3 *ent = NULL; + int name_len = 0; + if ((!entry) || (!dfh)) + return NULL; + + ent = GF_CALLOC(1, sizeof(*ent), gf_nfs_mt_entry3); + if (!ent) + return NULL; + + gf_msg_trace(GF_NFS3, 0, "Entry: %s", entry->d_name); + + /* If the entry is . or .., we need to replace the physical ino and gen + * with 1 and 0 respectively if the directory is root. This funging is + * needed because there is no parent directory of the root. In that + * sense the behavior we provide is similar to the output of the + * command: "stat /.." + */ + entry->d_ino = nfs3_iatt_gfid_to_ino(&entry->d_stat); + nfs3_funge_root_dotdot_dirent(entry, dfh); + ent->fileid = entry->d_ino; + ent->cookie = entry->d_off; + name_len = strlen(entry->d_name); + ent->name = GF_MALLOC(name_len + 1, gf_nfs_mt_char); + if (!ent->name) { + GF_FREE(ent); + ent = NULL; + goto err; + } + strcpy(ent->name, entry->d_name); + ent->name[name_len] = '\0'; err: - return ent; + return ent; } - void -nfs3_fill_post_op_fh3 (struct nfs3_fh *fh, post_op_fh3 *pfh) +nfs3_fill_post_op_fh3(struct nfs3_fh *fh, post_op_fh3 *pfh) { - uint32_t fhlen = 0; + uint32_t fhlen = 0; - if ((!fh) || (!pfh)) - return; + if ((!fh) || (!pfh)) + return; - pfh->handle_follows = 1; - fhlen = nfs3_fh_compute_size (fh); - pfh->post_op_fh3_u.handle.data.data_val = (void *)fh; - pfh->post_op_fh3_u.handle.data.data_len = fhlen; + pfh->handle_follows = 1; + fhlen = nfs3_fh_compute_size(); + pfh->post_op_fh3_u.handle.data.data_val = (void *)fh; + pfh->post_op_fh3_u.handle.data.data_len = fhlen; } - post_op_fh3 -nfs3_fh_to_post_op_fh3 (struct nfs3_fh *fh) +nfs3_fh_to_post_op_fh3(struct nfs3_fh *fh) { - post_op_fh3 pfh = {0, }; - char *fhp = NULL; + post_op_fh3 pfh = { + 0, + }; + char *fhp = NULL; - if (!fh) - return pfh; - - pfh.handle_follows = 1; + if (!fh) + return pfh; - fhp = GF_CALLOC (1, sizeof (*fh), gf_nfs_mt_char); - if (!fhp) - return pfh; + pfh.handle_follows = 1; - memcpy (fhp, fh, sizeof (*fh)); - nfs3_fill_post_op_fh3 ((struct nfs3_fh *)fhp, &pfh); + fhp = GF_MALLOC(sizeof(*fh), gf_nfs_mt_char); + if (!fhp) return pfh; -} + memcpy(fhp, fh, sizeof(*fh)); + nfs3_fill_post_op_fh3((struct nfs3_fh *)fhp, &pfh); + return pfh; +} entryp3 * -nfs3_fill_entryp3 (gf_dirent_t *entry, struct nfs3_fh *dirfh) +nfs3_fill_entryp3(gf_dirent_t *entry, struct nfs3_fh *dirfh, uint64_t devid) +{ + entryp3 *ent = NULL; + struct nfs3_fh newfh = { + {0}, + }; + int name_len = 0; + + if ((!entry) || (!dirfh)) + return NULL; + + /* If the entry is . or .., we need to replace the physical ino and gen + * with 1 and 0 respectively if the directory is root. This funging is + * needed because there is no parent directory of the root. In that + * sense the behavior we provide is similar to the output of the + * command: "stat /.." + */ + entry->d_ino = nfs3_iatt_gfid_to_ino(&entry->d_stat); + nfs3_funge_root_dotdot_dirent(entry, dirfh); + gf_msg_trace(GF_NFS3, 0, "Entry: %s, ino: %" PRIu64, entry->d_name, + entry->d_ino); + ent = GF_CALLOC(1, sizeof(*ent), gf_nfs_mt_entryp3); + if (!ent) + return NULL; + + ent->fileid = entry->d_ino; + ent->cookie = entry->d_off; + name_len = strlen(entry->d_name); + ent->name = GF_MALLOC(name_len + 1, gf_nfs_mt_char); + if (!ent->name) { + GF_FREE(ent); + ent = NULL; + goto err; + } + strcpy(ent->name, entry->d_name); + ent->name[name_len] = '\0'; + + nfs3_fh_build_child_fh(dirfh, &entry->d_stat, &newfh); + nfs3_map_deviceid_to_statdev(&entry->d_stat, devid); + /* * + * In tier volume, the readdirp send only to cold subvol + * which will populate in the 'T' file entries in the result. + * For such files an explicit stat call is required, by setting + * following argument client will perform the same. + * + * The inode value for 'T' files and directory is NULL, so just + * skip the check if it is directory. + */ + if (!(IA_ISDIR(entry->d_stat.ia_type)) && (entry->inode == NULL)) + ent->name_attributes.attributes_follow = FALSE; + else + ent->name_attributes = nfs3_stat_to_post_op_attr(&entry->d_stat); + + ent->name_handle = nfs3_fh_to_post_op_fh3(&newfh); +err: + return ent; +} + +void +nfs3_fill_readdir3res(readdir3res *res, nfsstat3 stat, struct nfs3_fh *dirfh, + uint64_t cverf, struct iatt *dirstat, + gf_dirent_t *entries, count3 count, int is_eof, + uint64_t deviceid) { - entryp3 *ent = NULL; - struct nfs3_fh newfh = {{0}, }; + post_op_attr dirattr; + entry3 *ent = NULL; + entry3 *headentry = NULL; + entry3 *preventry = NULL; + count3 filled = 0; + gf_dirent_t *listhead = NULL; - if ((!entry) || (!dirfh)) - return NULL; + memset(res, 0, sizeof(*res)); + res->status = stat; + if (stat != NFS3_OK) + return; - /* If the entry is . or .., we need to replace the physical ino and gen - * with 1 and 0 respectively if the directory is root. This funging is - * needed because there is no parent directory of the root. In that - * sense the behavious we provide is similar to the output of the - * command: "stat /.." - */ - nfs3_funge_root_dotdot_dirent (entry, dirfh); - gf_log (GF_NFS3, GF_LOG_TRACE, "Entry: %s, ino: %"PRIu64, - entry->d_name, entry->d_ino); - ent = GF_CALLOC (1, sizeof (*ent), gf_nfs_mt_entryp3); + nfs3_map_deviceid_to_statdev(dirstat, deviceid); + dirattr = nfs3_stat_to_post_op_attr(dirstat); + res->readdir3res_u.resok.dir_attributes = dirattr; + res->readdir3res_u.resok.reply.eof = (bool_t)is_eof; + memcpy(res->readdir3res_u.resok.cookieverf, &cverf, sizeof(cverf)); + + filled = NFS3_READDIR_RESOK_SIZE; + /* First entry is just the list head */ + listhead = entries; + entries = entries->next; + while (((entries) && (entries != listhead)) && (filled < count)) { + /* + if ((strcmp (entries->d_name, ".") == 0) || + (strcmp (entries->d_name, "..") == 0)) + goto nextentry; + */ + ent = nfs3_fill_entry3(entries, dirfh); if (!ent) - return NULL; - - ent->fileid = entry->d_ino; - ent->cookie = entry->d_off; - ent->name = GF_CALLOC ((strlen (entry->d_name) + 1), sizeof (char), - gf_nfs_mt_char); - if (!ent->name) { - GF_FREE (ent); - ent = NULL; - goto err; - } - strcpy (ent->name, entry->d_name); + break; - nfs3_fh_build_child_fh (dirfh, &entry->d_stat, &newfh); - nfs3_map_xlid_to_statdev (&entry->d_stat, dirfh->xlatorid); - ent->name_attributes = nfs3_stat_to_post_op_attr (&entry->d_stat); - ent->name_handle = nfs3_fh_to_post_op_fh3 (&newfh); -err: - return ent; -} + if (!headentry) + headentry = ent; + if (preventry) { + preventry->nextentry = ent; + preventry = ent; + } else + preventry = ent; -void -nfs3_fill_readdir3res (readdir3res *res, nfsstat3 stat, struct nfs3_fh *dirfh, - uint64_t cverf, struct iatt *dirstat, - gf_dirent_t *entries, count3 count, int is_eof) -{ - post_op_attr dirattr; - entry3 *ent = NULL; - entry3 *headentry = NULL; - entry3 *preventry = NULL; - count3 filled = 0; - gf_dirent_t *listhead = NULL; - - memset (res, 0, sizeof (*res)); - res->status = stat; - if (stat != NFS3_OK) - return; - - nfs3_map_xlid_to_statdev (dirstat, dirfh->xlatorid); - dirattr = nfs3_stat_to_post_op_attr (dirstat); - res->readdir3res_u.resok.dir_attributes = dirattr; - res->readdir3res_u.resok.reply.eof = (bool_t)is_eof; - memcpy (res->readdir3res_u.resok.cookieverf, &cverf, sizeof (cverf)); - - filled = NFS3_READDIR_RESOK_SIZE; - /* First entry is just the list head */ - listhead = entries; + filled += NFS3_ENTRY3_FIXED_SIZE + strlen(ent->name); + // nextentry: entries = entries->next; - while (((entries) && (entries != listhead)) && (filled < count)) { - /* - if ((strcmp (entries->d_name, ".") == 0) || - (strcmp (entries->d_name, "..") == 0)) - goto nextentry; - */ - ent = nfs3_fill_entry3 (entries, dirfh); - if (!ent) - break; - - if (!headentry) - headentry = ent; - - if (preventry) { - preventry->nextentry = ent; - preventry = ent; - } else - preventry = ent; - - filled += NFS3_ENTRY3_FIXED_SIZE + strlen (ent->name); -//nextentry: - entries = entries->next; - } + } - res->readdir3res_u.resok.reply.entries = headentry; + res->readdir3res_u.resok.reply.entries = headentry; - return; + return; } - void -nfs3_fill_readdirp3res (readdirp3res *res, nfsstat3 stat, struct nfs3_fh *dirfh, - uint64_t cverf, struct iatt *dirstat, - gf_dirent_t *entries, count3 dircount, count3 maxcount, - int is_eof) -{ - post_op_attr dirattr; - entryp3 *ent = NULL; - entryp3 *headentry = NULL; - entryp3 *preventry = NULL; - count3 filled = 0; - gf_dirent_t *listhead = NULL; - int fhlen = 0; +nfs3_fill_readdirp3res(readdirp3res *res, nfsstat3 stat, struct nfs3_fh *dirfh, + uint64_t cverf, struct iatt *dirstat, + gf_dirent_t *entries, count3 dircount, count3 maxcount, + int is_eof, uint64_t deviceid) +{ + post_op_attr dirattr; + entryp3 *ent = NULL; + entryp3 *headentry = NULL; + entryp3 *preventry = NULL; + count3 filled = 0; + gf_dirent_t *listhead = NULL; + int fhlen = 0; + + memset(res, 0, sizeof(*res)); + res->status = stat; + if (stat != NFS3_OK) + return; - memset (res, 0, sizeof (*res)); - res->status = stat; - if (stat != NFS3_OK) - return; + nfs3_map_deviceid_to_statdev(dirstat, deviceid); + dirattr = nfs3_stat_to_post_op_attr(dirstat); + res->readdirp3res_u.resok.dir_attributes = dirattr; + res->readdirp3res_u.resok.reply.eof = (bool_t)is_eof; + memcpy(res->readdirp3res_u.resok.cookieverf, &cverf, sizeof(cverf)); + + filled = NFS3_READDIR_RESOK_SIZE; + /* First entry is just the list head */ + listhead = entries; + entries = entries->next; + while (((entries) && (entries != listhead)) && (filled < maxcount)) { + /* Linux does not display . and .. entries unless we provide + * these entries here. + */ + /* if ((strcmp (entries->d_name, ".") == 0) || + (strcmp (entries->d_name, "..") == 0)) + goto nextentry; + */ + ent = nfs3_fill_entryp3(entries, dirfh, deviceid); + if (!ent) + break; + + if (!headentry) + headentry = ent; - nfs3_map_xlid_to_statdev (dirstat, dirfh->xlatorid); - dirattr = nfs3_stat_to_post_op_attr (dirstat); - res->readdirp3res_u.resok.dir_attributes = dirattr; - res->readdirp3res_u.resok.reply.eof = (bool_t)is_eof; - memcpy (res->readdirp3res_u.resok.cookieverf, &cverf, sizeof (cverf)); + if (preventry) { + preventry->nextentry = ent; + preventry = ent; + } else + preventry = ent; - filled = NFS3_READDIR_RESOK_SIZE; - /* First entry is just the list head */ - listhead = entries; + fhlen = ent->name_handle.post_op_fh3_u.handle.data.data_len; + filled += NFS3_ENTRYP3_FIXED_SIZE + fhlen + strlen(ent->name); + // nextentry: entries = entries->next; - while (((entries) && (entries != listhead)) && (filled < maxcount)) { - /* Linux does not display . and .. entries unless we provide - * these entries here. - */ -/* if ((strcmp (entries->d_name, ".") == 0) || - (strcmp (entries->d_name, "..") == 0)) - goto nextentry; - */ - ent = nfs3_fill_entryp3 (entries, dirfh); - if (!ent) - break; - - if (!headentry) - headentry = ent; - - if (preventry) { - preventry->nextentry = ent; - preventry = ent; - } else - preventry = ent; - - fhlen = ent->name_handle.post_op_fh3_u.handle.data.data_len; - filled += NFS3_ENTRYP3_FIXED_SIZE + fhlen + strlen (ent->name); -//nextentry: - entries = entries->next; - } + } - res->readdirp3res_u.resok.reply.entries = headentry; + res->readdirp3res_u.resok.reply.entries = headentry; - return; + return; } - void -nfs3_prep_readdirp3args (readdirp3args *ra, struct nfs3_fh *fh) +nfs3_prep_readdirp3args(readdirp3args *ra, struct nfs3_fh *fh) { - memset (ra, 0, sizeof (*ra)); - ra->dir.data.data_val = (void *)fh; + memset(ra, 0, sizeof(*ra)); + ra->dir.data.data_val = (void *)fh; } void -nfs3_free_readdirp3res (readdirp3res *res) +nfs3_free_readdirp3res(readdirp3res *res) { - entryp3 *ent = NULL; - entryp3 *next = NULL; - - if (!res) - return; + entryp3 *ent = NULL; + entryp3 *next = NULL; - ent = res->readdirp3res_u.resok.reply.entries; - while (ent) { + if (!res) + return; - next = ent->nextentry; - GF_FREE (ent->name); - GF_FREE (ent->name_handle.post_op_fh3_u.handle.data.data_val); - GF_FREE (ent); - ent = next; - } + ent = res->readdirp3res_u.resok.reply.entries; + while (ent) { + next = ent->nextentry; + GF_FREE(ent->name); + GF_FREE(ent->name_handle.post_op_fh3_u.handle.data.data_val); + GF_FREE(ent); + ent = next; + } - return; + return; } - void -nfs3_free_readdir3res (readdir3res *res) +nfs3_free_readdir3res(readdir3res *res) { - entry3 *ent = NULL; - entry3 *next = NULL; - - if (!res) - return; + entry3 *ent = NULL; + entry3 *next = NULL; - ent = res->readdir3res_u.resok.reply.entries; - while (ent) { + if (!res) + return; - next = ent->nextentry; - GF_FREE (ent->name); - GF_FREE (ent); - ent = next; - } + ent = res->readdir3res_u.resok.reply.entries; + while (ent) { + next = ent->nextentry; + GF_FREE(ent->name); + GF_FREE(ent); + ent = next; + } - return; + return; } void -nfs3_prep_fsstat3args (fsstat3args *args, struct nfs3_fh *fh) +nfs3_prep_fsstat3args(fsstat3args *args, struct nfs3_fh *fh) { - memset (args, 0, sizeof (*args)); - args->fsroot.data.data_val = (char *)fh; + memset(args, 0, sizeof(*args)); + args->fsroot.data.data_val = (char *)fh; } - void -nfs3_fill_fsstat3res (fsstat3res *res, nfsstat3 stat, struct statvfs *fsbuf, - struct iatt *postbuf, uint16_t xlid) +nfs3_fill_fsstat3res(fsstat3res *res, nfsstat3 stat, struct statvfs *fsbuf, + struct iatt *postbuf, uint64_t deviceid) { - post_op_attr poa; - fsstat3resok resok; + post_op_attr poa; + fsstat3resok resok; - memset (res, 0, sizeof (*res)); - res->status = stat; - if (stat != NFS3_OK) - return; + memset(res, 0, sizeof(*res)); + res->status = stat; + if (stat != NFS3_OK) + return; - nfs3_map_xlid_to_statdev (postbuf, xlid); - poa = nfs3_stat_to_post_op_attr (postbuf); - resok.tbytes = (size3)(fsbuf->f_frsize * fsbuf->f_blocks); - resok.fbytes = (size3)(fsbuf->f_bsize * fsbuf->f_bfree); - resok.abytes = (size3)(fsbuf->f_bsize * fsbuf->f_bavail); - resok.tfiles = (size3)(fsbuf->f_files); - resok.ffiles = (size3)(fsbuf->f_ffree); - resok.afiles = (size3)(fsbuf->f_favail); - resok.invarsec = 0; + nfs3_map_deviceid_to_statdev(postbuf, deviceid); + poa = nfs3_stat_to_post_op_attr(postbuf); + resok.tbytes = (size3)(fsbuf->f_frsize * fsbuf->f_blocks); + resok.fbytes = (size3)(fsbuf->f_frsize * fsbuf->f_bfree); + resok.abytes = (size3)(fsbuf->f_frsize * fsbuf->f_bavail); + resok.tfiles = (size3)(fsbuf->f_files); + resok.ffiles = (size3)(fsbuf->f_ffree); + resok.afiles = (size3)(fsbuf->f_favail); + resok.invarsec = 0; - resok.obj_attributes = poa; - res->fsstat3res_u.resok = resok; + resok.obj_attributes = poa; + res->fsstat3res_u.resok = resok; } - int32_t -nfs3_sattr3_to_setattr_valid (sattr3 *sattr, struct iatt *buf, mode_t *omode) -{ - int32_t valid = 0; - ia_prot_t prot = {0, }; - mode_t mode = 0; - - if (!sattr) - return 0; - - if (sattr->mode.set_it) { - valid |= GF_SET_ATTR_MODE; - - if (sattr->mode.set_mode3_u.mode & NFS3MODE_ROWNER) { - mode |= S_IRUSR; - prot.owner.read = 1; - } - if (sattr->mode.set_mode3_u.mode & NFS3MODE_WOWNER) { - mode |= S_IWUSR; - prot.owner.write = 1; - } - if (sattr->mode.set_mode3_u.mode & NFS3MODE_XOWNER) { - mode |= S_IXUSR; - prot.owner.exec = 1; - } - - if (sattr->mode.set_mode3_u.mode & NFS3MODE_RGROUP) { - mode |= S_IRGRP; - prot.group.read = 1; - } - if (sattr->mode.set_mode3_u.mode & NFS3MODE_WGROUP) { - mode |= S_IWGRP; - prot.group.write = 1; - } - if (sattr->mode.set_mode3_u.mode & NFS3MODE_XGROUP) { - mode |= S_IXGRP; - prot.group.exec = 1; - } - - if (sattr->mode.set_mode3_u.mode & NFS3MODE_ROTHER) { - mode |= S_IROTH; - prot.other.read = 1; - } - if (sattr->mode.set_mode3_u.mode & NFS3MODE_WOTHER) { - mode |= S_IWOTH; - prot.other.write = 1; - } - if (sattr->mode.set_mode3_u.mode & NFS3MODE_XOTHER) { - mode |= S_IXOTH; - prot.other.exec = 1; - } - - if (sattr->mode.set_mode3_u.mode & NFS3MODE_SETXUID) { - mode |= S_ISUID; - prot.suid = 1; - } - if (sattr->mode.set_mode3_u.mode & NFS3MODE_SETXGID) { - mode |= S_ISGID; - prot.sgid = 1; - } - if (sattr->mode.set_mode3_u.mode & NFS3MODE_SAVESWAPTXT) { - mode |= S_ISVTX; - prot.sticky = 1; - } - - if (buf) - buf->ia_prot = prot; - /* Create fop still requires the old mode_t style argument. */ - if (omode) - *omode = mode; - } +nfs3_sattr3_to_setattr_valid(sattr3 *sattr, struct iatt *buf, mode_t *omode) +{ + int32_t valid = 0; + ia_prot_t prot = { + 0, + }; + mode_t mode = 0; - if (sattr->uid.set_it) { - valid |= GF_SET_ATTR_UID; - if (buf) - buf->ia_uid = sattr->uid.set_uid3_u.uid; - } + if (!sattr) + return 0; - if (sattr->gid.set_it) { - valid |= GF_SET_ATTR_GID; - if (buf) - buf->ia_gid = sattr->gid.set_gid3_u.gid; - } + if (sattr->mode.set_it) { + valid |= GF_SET_ATTR_MODE; - if (sattr->size.set_it) { - valid |= GF_SET_ATTR_SIZE; - if (buf) - buf->ia_size = sattr->size.set_size3_u.size; + if (sattr->mode.set_mode3_u.mode & NFS3MODE_ROWNER) { + mode |= S_IRUSR; + prot.owner.read = 1; } - - if (sattr->atime.set_it == SET_TO_CLIENT_TIME) { - valid |= GF_SET_ATTR_ATIME; - if (buf) - buf->ia_atime = sattr->atime.set_atime_u.atime.seconds; + if (sattr->mode.set_mode3_u.mode & NFS3MODE_WOWNER) { + mode |= S_IWUSR; + prot.owner.write = 1; + } + if (sattr->mode.set_mode3_u.mode & NFS3MODE_XOWNER) { + mode |= S_IXUSR; + prot.owner.exec = 1; } - if (sattr->atime.set_it == SET_TO_SERVER_TIME) { - valid |= GF_SET_ATTR_ATIME; - if (buf) - buf->ia_atime = time (NULL); + if (sattr->mode.set_mode3_u.mode & NFS3MODE_RGROUP) { + mode |= S_IRGRP; + prot.group.read = 1; + } + if (sattr->mode.set_mode3_u.mode & NFS3MODE_WGROUP) { + mode |= S_IWGRP; + prot.group.write = 1; + } + if (sattr->mode.set_mode3_u.mode & NFS3MODE_XGROUP) { + mode |= S_IXGRP; + prot.group.exec = 1; } - if (sattr->mtime.set_it == SET_TO_CLIENT_TIME) { - valid |= GF_SET_ATTR_MTIME; - if (buf) - buf->ia_mtime = sattr->mtime.set_mtime_u.mtime.seconds; + if (sattr->mode.set_mode3_u.mode & NFS3MODE_ROTHER) { + mode |= S_IROTH; + prot.other.read = 1; + } + if (sattr->mode.set_mode3_u.mode & NFS3MODE_WOTHER) { + mode |= S_IWOTH; + prot.other.write = 1; + } + if (sattr->mode.set_mode3_u.mode & NFS3MODE_XOTHER) { + mode |= S_IXOTH; + prot.other.exec = 1; } - if (sattr->mtime.set_it == SET_TO_SERVER_TIME) { - valid |= GF_SET_ATTR_MTIME; - if (buf) - buf->ia_mtime = time (NULL); + if (sattr->mode.set_mode3_u.mode & NFS3MODE_SETXUID) { + mode |= S_ISUID; + prot.suid = 1; + } + if (sattr->mode.set_mode3_u.mode & NFS3MODE_SETXGID) { + mode |= S_ISGID; + prot.sgid = 1; + } + if (sattr->mode.set_mode3_u.mode & NFS3MODE_SAVESWAPTXT) { + mode |= S_ISVTX; + prot.sticky = 1; } - return valid; + if (buf) + buf->ia_prot = prot; + /* Create fop still requires the old mode_t style argument. */ + if (omode) + *omode = mode; + } + + if (sattr->uid.set_it) { + valid |= GF_SET_ATTR_UID; + if (buf) + buf->ia_uid = sattr->uid.set_uid3_u.uid; + } + + if (sattr->gid.set_it) { + valid |= GF_SET_ATTR_GID; + if (buf) + buf->ia_gid = sattr->gid.set_gid3_u.gid; + } + + if (sattr->size.set_it) { + valid |= GF_SET_ATTR_SIZE; + if (buf) + buf->ia_size = sattr->size.set_size3_u.size; + } + + if (sattr->atime.set_it == SET_TO_CLIENT_TIME) { + valid |= GF_SET_ATTR_ATIME; + if (buf) + buf->ia_atime = sattr->atime.set_atime_u.atime.seconds; + } + + if (sattr->atime.set_it == SET_TO_SERVER_TIME) { + valid |= GF_SET_ATTR_ATIME; + if (buf) + buf->ia_atime = gf_time(); + } + + if (sattr->mtime.set_it == SET_TO_CLIENT_TIME) { + valid |= GF_SET_ATTR_MTIME; + if (buf) + buf->ia_mtime = sattr->mtime.set_mtime_u.mtime.seconds; + } + + if (sattr->mtime.set_it == SET_TO_SERVER_TIME) { + valid |= GF_SET_ATTR_MTIME; + if (buf) + buf->ia_mtime = gf_time(); + } + + return valid; } - wcc_data -nfs3_stat_to_wcc_data (struct iatt *pre, struct iatt *post) +nfs3_stat_to_wcc_data(struct iatt *pre, struct iatt *post) { - wcc_data wd = {{0}, }; + wcc_data wd = { + {0}, + }; - if (post) - wd.after = nfs3_stat_to_post_op_attr (post); - if (pre) - wd.before = nfs3_stat_to_pre_op_attr (pre); + if (post) + wd.after = nfs3_stat_to_post_op_attr(post); + if (pre) + wd.before = nfs3_stat_to_pre_op_attr(pre); - return wd; + return wd; } void -nfs3_fill_create3res (create3res *res, nfsstat3 stat, struct nfs3_fh *newfh, - struct iatt *newbuf, struct iatt *preparent, - struct iatt *postparent) +nfs3_fill_create3res(create3res *res, nfsstat3 stat, struct nfs3_fh *newfh, + struct iatt *newbuf, struct iatt *preparent, + struct iatt *postparent, uint64_t deviceid) { - post_op_attr poa = {0, }; - wcc_data dirwcc = {{0}, }; + post_op_attr poa = { + 0, + }; + wcc_data dirwcc = { + {0}, + }; - memset (res, 0, sizeof (*res)); - res->status = stat; - if (stat != NFS3_OK) - return; + memset(res, 0, sizeof(*res)); + res->status = stat; + if (stat != NFS3_OK) + return; - nfs3_fill_post_op_fh3 (newfh, &res->create3res_u.resok.obj); - nfs3_map_xlid_to_statdev (newbuf, newfh->xlatorid); - poa = nfs3_stat_to_post_op_attr (newbuf); - res->create3res_u.resok.obj_attributes = poa; - if (preparent) { - nfs3_map_xlid_to_statdev (preparent, newfh->xlatorid); - nfs3_map_xlid_to_statdev (postparent, newfh->xlatorid); - dirwcc = nfs3_stat_to_wcc_data (preparent, postparent); - } + nfs3_fill_post_op_fh3(newfh, &res->create3res_u.resok.obj); + nfs3_map_deviceid_to_statdev(newbuf, deviceid); + poa = nfs3_stat_to_post_op_attr(newbuf); + res->create3res_u.resok.obj_attributes = poa; + nfs3_map_deviceid_to_statdev(preparent, deviceid); + nfs3_map_deviceid_to_statdev(postparent, deviceid); + dirwcc = nfs3_stat_to_wcc_data(preparent, postparent); - res->create3res_u.resok.dir_wcc = dirwcc; + res->create3res_u.resok.dir_wcc = dirwcc; } void -nfs3_prep_create3args (create3args *args, struct nfs3_fh *fh, char *name) +nfs3_prep_create3args(create3args *args, struct nfs3_fh *fh, char *name) { - - memset (args, 0, sizeof (*args)); - args->where.dir.data.data_val = (void *)fh; - args->where.name = name; + memset(args, 0, sizeof(*args)); + args->where.dir.data.data_val = (void *)fh; + args->where.name = name; } void -nfs3_prep_setattr3args (setattr3args *args, struct nfs3_fh *fh) +nfs3_prep_setattr3args(setattr3args *args, struct nfs3_fh *fh) { - memset (args, 0, sizeof (*args)); - args->object.data.data_val = (void *)fh; + memset(args, 0, sizeof(*args)); + args->object.data.data_val = (void *)fh; } - void -nfs3_fill_setattr3res (setattr3res *res, nfsstat3 stat, struct iatt *preop, - struct iatt *postop, uint16_t xlid) +nfs3_fill_setattr3res(setattr3res *res, nfsstat3 stat, struct iatt *preop, + struct iatt *postop, uint64_t deviceid) { - wcc_data wcc; - memset (res, 0, sizeof (*res)); - res->status = stat; - if (stat != NFS3_OK) - return; + wcc_data wcc; + memset(res, 0, sizeof(*res)); + res->status = stat; + if (stat != NFS3_OK) + return; - nfs3_map_xlid_to_statdev (preop, xlid); - nfs3_map_xlid_to_statdev (postop, xlid); - wcc = nfs3_stat_to_wcc_data (preop, postop); - res->setattr3res_u.resok.obj_wcc = wcc; + nfs3_map_deviceid_to_statdev(preop, deviceid); + nfs3_map_deviceid_to_statdev(postop, deviceid); + wcc = nfs3_stat_to_wcc_data(preop, postop); + res->setattr3res_u.resok.obj_wcc = wcc; } +void +nfs3_prep_mkdir3args(mkdir3args *args, struct nfs3_fh *dirfh, char *name) +{ + memset(args, 0, sizeof(*args)); + args->where.dir.data.data_val = (void *)dirfh; + args->where.name = name; +} void -nfs3_prep_mkdir3args (mkdir3args *args, struct nfs3_fh *dirfh, char *name) +nfs3_fill_mkdir3res(mkdir3res *res, nfsstat3 stat, struct nfs3_fh *fh, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, uint64_t deviceid) { + wcc_data dirwcc; + post_op_attr poa; - memset (args, 0, sizeof (*args)); - args->where.dir.data.data_val = (void *)dirfh; - args->where.name = name; -} + memset(res, 0, sizeof(*res)); + res->status = stat; + if (stat != NFS3_OK) + return; + nfs3_fill_post_op_fh3(fh, &res->mkdir3res_u.resok.obj); + nfs3_map_deviceid_to_statdev(buf, deviceid); + poa = nfs3_stat_to_post_op_attr(buf); + nfs3_map_deviceid_to_statdev(preparent, deviceid); + nfs3_map_deviceid_to_statdev(postparent, deviceid); + dirwcc = nfs3_stat_to_wcc_data(preparent, postparent); + res->mkdir3res_u.resok.obj_attributes = poa; + res->mkdir3res_u.resok.dir_wcc = dirwcc; +} void -nfs3_fill_mkdir3res (mkdir3res *res, nfsstat3 stat, struct nfs3_fh *fh, - struct iatt *buf, struct iatt *preparent, - struct iatt *postparent) +nfs3_prep_symlink3args(symlink3args *args, struct nfs3_fh *dirfh, char *name, + char *target) { - wcc_data dirwcc; - post_op_attr poa; + memset(args, 0, sizeof(*args)); + args->where.dir.data.data_val = (void *)dirfh; + args->where.name = name; + args->symlink.symlink_data = target; +} - memset (res, 0, sizeof (*res)); - res->status = stat; - if (stat != NFS3_OK) - return; +void +nfs3_fill_symlink3res(symlink3res *res, nfsstat3 stat, struct nfs3_fh *fh, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, uint64_t deviceid) +{ + wcc_data dirwcc; + post_op_attr poa; - nfs3_fill_post_op_fh3 (fh, &res->mkdir3res_u.resok.obj); - nfs3_map_xlid_to_statdev (buf, fh->xlatorid); - poa = nfs3_stat_to_post_op_attr (buf); - nfs3_map_xlid_to_statdev (preparent, fh->xlatorid); - nfs3_map_xlid_to_statdev (postparent, fh->xlatorid); - dirwcc = nfs3_stat_to_wcc_data (preparent, postparent); - res->mkdir3res_u.resok.obj_attributes = poa; - res->mkdir3res_u.resok.dir_wcc = dirwcc; + memset(res, 0, sizeof(*res)); + res->status = stat; + if (stat != NFS3_OK) + return; + nfs3_fill_post_op_fh3(fh, &res->symlink3res_u.resok.obj); + nfs3_map_deviceid_to_statdev(buf, deviceid); + poa = nfs3_stat_to_post_op_attr(buf); + nfs3_map_deviceid_to_statdev(postparent, deviceid); + nfs3_map_deviceid_to_statdev(preparent, deviceid); + dirwcc = nfs3_stat_to_wcc_data(preparent, postparent); + res->symlink3res_u.resok.obj_attributes = poa; + res->symlink3res_u.resok.dir_wcc = dirwcc; } - void -nfs3_prep_symlink3args (symlink3args *args, struct nfs3_fh *dirfh, char *name, - char *target) +nfs3_prep_readlink3args(readlink3args *args, struct nfs3_fh *fh) { - memset (args, 0, sizeof (*args)); - args->where.dir.data.data_val = (void *)dirfh; - args->where.name = name; - args->symlink.symlink_data = target; + memset(args, 0, sizeof(*args)); + args->symlink.data.data_val = (void *)fh; } - void -nfs3_fill_symlink3res (symlink3res *res, nfsstat3 stat, struct nfs3_fh *fh, - struct iatt *buf, struct iatt *preparent, - struct iatt *postparent) +nfs3_fill_readlink3res(readlink3res *res, nfsstat3 stat, char *path, + struct iatt *buf, uint64_t deviceid) { - wcc_data dirwcc; - post_op_attr poa; + post_op_attr poa; - memset (res, 0, sizeof (*res)); - res->status = stat; - if (stat != NFS3_OK) - return; + memset(res, 0, sizeof(*res)); + res->status = stat; - nfs3_fill_post_op_fh3 (fh, &res->symlink3res_u.resok.obj); - nfs3_map_xlid_to_statdev (buf, fh->xlatorid); - poa = nfs3_stat_to_post_op_attr (buf); - nfs3_map_xlid_to_statdev (postparent, fh->xlatorid); - nfs3_map_xlid_to_statdev (preparent, fh->xlatorid); - dirwcc = nfs3_stat_to_wcc_data (preparent, postparent); - res->symlink3res_u.resok.obj_attributes = poa; - res->symlink3res_u.resok.dir_wcc = dirwcc; + if (stat != NFS3_OK) + return; + nfs3_map_deviceid_to_statdev(buf, deviceid); + poa = nfs3_stat_to_post_op_attr(buf); + res->readlink3res_u.resok.data = (void *)path; + res->readlink3res_u.resok.symlink_attributes = poa; } +void +nfs3_prep_mknod3args(mknod3args *args, struct nfs3_fh *fh, char *name) +{ + memset(args, 0, sizeof(*args)); + args->where.dir.data.data_val = (void *)fh; + args->where.name = name; +} void -nfs3_prep_readlink3args (readlink3args *args, struct nfs3_fh *fh) +nfs3_fill_mknod3res(mknod3res *res, nfsstat3 stat, struct nfs3_fh *fh, + struct iatt *buf, struct iatt *preparent, + struct iatt *postparent, uint64_t deviceid) { + post_op_attr poa; + wcc_data wccdir; - memset (args, 0, sizeof (*args)); - args->symlink.data.data_val = (void *)fh; -} + memset(res, 0, sizeof(*res)); + res->status = stat; + if (stat != NFS3_OK) + return; + nfs3_fill_post_op_fh3(fh, &res->mknod3res_u.resok.obj); + nfs3_map_deviceid_to_statdev(buf, deviceid); + poa = nfs3_stat_to_post_op_attr(buf); + nfs3_map_deviceid_to_statdev(preparent, deviceid); + nfs3_map_deviceid_to_statdev(postparent, deviceid); + wccdir = nfs3_stat_to_wcc_data(preparent, postparent); + res->mknod3res_u.resok.obj_attributes = poa; + res->mknod3res_u.resok.dir_wcc = wccdir; +} void -nfs3_fill_readlink3res (readlink3res *res, nfsstat3 stat, char *path, - struct iatt *buf, uint16_t xlid) +nfs3_fill_remove3res(remove3res *res, nfsstat3 stat, struct iatt *preparent, + struct iatt *postparent, uint64_t deviceid) { - post_op_attr poa; + wcc_data dirwcc; - memset (res, 0, sizeof (*res)); - res->status = stat; - - if (stat != NFS3_OK) - return; + memset(res, 0, sizeof(*res)); + res->status = stat; + if (stat != NFS3_OK) + return; - nfs3_map_xlid_to_statdev (buf, xlid); - poa = nfs3_stat_to_post_op_attr (buf); - res->readlink3res_u.resok.data = (void *)path; - res->readlink3res_u.resok.symlink_attributes = poa; + nfs3_map_deviceid_to_statdev(preparent, deviceid); + nfs3_map_deviceid_to_statdev(postparent, deviceid); + dirwcc = nfs3_stat_to_wcc_data(preparent, postparent); + res->remove3res_u.resok.dir_wcc = dirwcc; } - void -nfs3_prep_mknod3args (mknod3args *args, struct nfs3_fh *fh, char *name) +nfs3_prep_remove3args(remove3args *args, struct nfs3_fh *fh, char *name) { - memset (args, 0, sizeof (*args)); - args->where.dir.data.data_val = (void *)fh; - args->where.name = name; - + memset(args, 0, sizeof(*args)); + args->object.dir.data.data_val = (void *)fh; + args->object.name = name; } void -nfs3_fill_mknod3res (mknod3res *res, nfsstat3 stat, struct nfs3_fh *fh, - struct iatt *buf, struct iatt *preparent, - struct iatt *postparent) +nfs3_prep_rmdir3args(rmdir3args *args, struct nfs3_fh *fh, char *name) { - post_op_attr poa; - wcc_data wccdir; + memset(args, 0, sizeof(*args)); + args->object.dir.data.data_val = (void *)fh; + args->object.name = name; +} - memset (res, 0, sizeof (*res)); - res->status = stat; - if (stat != NFS3_OK) - return; +void +nfs3_fill_rmdir3res(rmdir3res *res, nfsstat3 stat, struct iatt *preparent, + struct iatt *postparent, uint64_t deviceid) +{ + wcc_data dirwcc; + memset(res, 0, sizeof(*res)); + res->status = stat; - nfs3_fill_post_op_fh3 (fh, &res->mknod3res_u.resok.obj); - nfs3_map_xlid_to_statdev (buf, fh->xlatorid); - poa = nfs3_stat_to_post_op_attr (buf); - nfs3_map_xlid_to_statdev (preparent, fh->xlatorid); - nfs3_map_xlid_to_statdev (postparent, fh->xlatorid); - wccdir = nfs3_stat_to_wcc_data (preparent, postparent); - res->mknod3res_u.resok.obj_attributes = poa; - res->mknod3res_u.resok.dir_wcc = wccdir; + if (stat != NFS3_OK) + return; + nfs3_map_deviceid_to_statdev(postparent, deviceid); + nfs3_map_deviceid_to_statdev(preparent, deviceid); + dirwcc = nfs3_stat_to_wcc_data(preparent, postparent); + res->rmdir3res_u.resok.dir_wcc = dirwcc; } +void +nfs3_prep_link3args(link3args *args, struct nfs3_fh *target, + struct nfs3_fh *dirfh, char *name) +{ + memset(args, 0, sizeof(*args)); + args->file.data.data_val = (void *)target; + args->link.dir.data.data_val = (void *)dirfh; + args->link.name = name; +} void -nfs3_fill_remove3res (remove3res *res, nfsstat3 stat, struct iatt *preparent, - struct iatt *postparent, uint16_t xlid) +nfs3_fill_link3res(link3res *res, nfsstat3 stat, struct iatt *buf, + struct iatt *preparent, struct iatt *postparent, + uint64_t deviceid) { - wcc_data dirwcc; + post_op_attr poa; + wcc_data dirwcc; - memset (res, 0, sizeof (*res)); - res->status = stat; - if (stat != NFS3_OK) - return; + memset(res, 0, sizeof(*res)); + res->status = stat; + if (stat != NFS3_OK) + return; - nfs3_map_xlid_to_statdev (preparent, xlid); - nfs3_map_xlid_to_statdev (postparent, xlid); - dirwcc = nfs3_stat_to_wcc_data (preparent, postparent); - res->remove3res_u.resok.dir_wcc = dirwcc; + nfs3_map_deviceid_to_statdev(preparent, deviceid); + nfs3_map_deviceid_to_statdev(postparent, deviceid); + nfs3_map_deviceid_to_statdev(buf, deviceid); + poa = nfs3_stat_to_post_op_attr(buf); + dirwcc = nfs3_stat_to_wcc_data(preparent, postparent); + res->link3res_u.resok.file_attributes = poa; + res->link3res_u.resok.linkdir_wcc = dirwcc; } - void -nfs3_prep_remove3args (remove3args *args, struct nfs3_fh *fh, char *name) +nfs3_prep_rename3args(rename3args *args, struct nfs3_fh *olddirfh, + char *oldname, struct nfs3_fh *newdirfh, char *newname) { - memset (args, 0, sizeof (*args)); - args->object.dir.data.data_val = (void *)fh; - args->object.name = name; -} + memset(args, 0, sizeof(*args)); + args->from.name = oldname; + args->from.dir.data.data_val = (void *)olddirfh; + args->to.name = newname; + args->to.dir.data.data_val = (void *)newdirfh; +} void -nfs3_prep_rmdir3args (rmdir3args *args, struct nfs3_fh *fh, char *name) +nfs3_fill_rename3res(rename3res *res, nfsstat3 stat, struct iatt *buf, + struct iatt *preoldparent, struct iatt *postoldparent, + struct iatt *prenewparent, struct iatt *postnewparent, + uint64_t deviceid) + { - memset (args, 0, sizeof (*args)); - args->object.dir.data.data_val = (void *)fh; - args->object.name = name; + wcc_data dirwcc; + + memset(res, 0, sizeof(*res)); + res->status = stat; + if (stat != NFS3_OK) + return; + + nfs3_map_deviceid_to_statdev(preoldparent, deviceid); + nfs3_map_deviceid_to_statdev(postoldparent, deviceid); + nfs3_map_deviceid_to_statdev(prenewparent, deviceid); + nfs3_map_deviceid_to_statdev(postnewparent, deviceid); + nfs3_map_deviceid_to_statdev(buf, deviceid); + dirwcc = nfs3_stat_to_wcc_data(preoldparent, postoldparent); + res->rename3res_u.resok.fromdir_wcc = dirwcc; + dirwcc = nfs3_stat_to_wcc_data(prenewparent, postnewparent); + res->rename3res_u.resok.todir_wcc = dirwcc; } +void +nfs3_prep_write3args(write3args *args, struct nfs3_fh *fh) +{ + memset(args, 0, sizeof(*args)); + args->file.data.data_val = (void *)fh; +} void -nfs3_fill_rmdir3res (rmdir3res *res, nfsstat3 stat, struct iatt *preparent, - struct iatt *postparent, uint16_t xlid) +nfs3_fill_write3res(write3res *res, nfsstat3 stat, count3 count, + stable_how stable, uint64_t wverf, struct iatt *prestat, + struct iatt *poststat, uint64_t deviceid) { - wcc_data dirwcc; - memset (res, 0, sizeof (*res)); - res->status = stat; + write3resok resok; + memset(res, 0, sizeof(*res)); + res->status = stat; + if (stat != NFS3_OK) + return; - if (stat != NFS3_OK) - return; + nfs3_map_deviceid_to_statdev(prestat, deviceid); + nfs3_map_deviceid_to_statdev(poststat, deviceid); + resok.file_wcc = nfs3_stat_to_wcc_data(prestat, poststat); + resok.count = count; + resok.committed = stable; + memcpy(resok.verf, &wverf, sizeof(wverf)); - nfs3_map_xlid_to_statdev (postparent, xlid); - nfs3_map_xlid_to_statdev (preparent, xlid); - dirwcc = nfs3_stat_to_wcc_data (preparent, postparent); - res->rmdir3res_u.resok.dir_wcc = dirwcc; + res->write3res_u.resok = resok; } - void -nfs3_prep_link3args (link3args *args, struct nfs3_fh *target, - struct nfs3_fh * dirfh, char *name) +nfs3_prep_commit3args(commit3args *args, struct nfs3_fh *fh) { - memset (args, 0, sizeof (*args)); - args->file.data.data_val = (void *)target; - args->link.dir.data.data_val = (void *)dirfh; - args->link.name = name; + memset(args, 0, sizeof(*args)); + args->file.data.data_val = (void *)fh; } +void +nfs3_fill_commit3res(commit3res *res, nfsstat3 stat, uint64_t wverf, + struct iatt *prestat, struct iatt *poststat, + uint64_t deviceid) +{ + memset(res, 0, sizeof(*res)); + res->status = stat; + if (stat != NFS3_OK) + return; + + nfs3_map_deviceid_to_statdev(poststat, deviceid); + nfs3_map_deviceid_to_statdev(prestat, deviceid); + res->commit3res_u.resok.file_wcc = nfs3_stat_to_wcc_data(prestat, poststat); + memcpy(res->commit3res_u.resok.verf, &wverf, sizeof(wverf)); +} void -nfs3_fill_link3res (link3res *res, nfsstat3 stat, struct iatt *buf, - struct iatt *preparent, struct iatt *postparent, - uint16_t xlid) +nfs3_fill_read3res(read3res *res, nfsstat3 stat, count3 count, + struct iatt *poststat, int is_eof, uint64_t deviceid) { - post_op_attr poa; - wcc_data dirwcc; + post_op_attr poa; - memset (res, 0, sizeof (*res)); - res->status = stat; - if (stat != NFS3_OK) - return; + memset(res, 0, sizeof(*res)); + res->status = stat; + if (stat != NFS3_OK) + return; - nfs3_map_xlid_to_statdev (preparent, xlid); - nfs3_map_xlid_to_statdev (postparent, xlid); - nfs3_map_xlid_to_statdev (buf, xlid); - poa = nfs3_stat_to_post_op_attr (buf); - dirwcc = nfs3_stat_to_wcc_data (preparent, postparent); - res->link3res_u.resok.file_attributes = poa; - res->link3res_u.resok.linkdir_wcc = dirwcc; + nfs3_map_deviceid_to_statdev(poststat, deviceid); + poa = nfs3_stat_to_post_op_attr(poststat); + res->read3res_u.resok.file_attributes = poa; + res->read3res_u.resok.count = count; + res->read3res_u.resok.eof = is_eof; + res->read3res_u.resok.data.data_len = count; } - +void +nfs3_prep_read3args(read3args *args, struct nfs3_fh *fh) +{ + memset(args, 0, sizeof(*args)); + args->file.data.data_val = (void *)fh; +} void -nfs3_prep_rename3args (rename3args *args, struct nfs3_fh *olddirfh, - char *oldname, struct nfs3_fh *newdirfh, char *newname) +nfs3_fill_pathconf3res(pathconf3res *res, nfsstat3 stat, struct iatt *buf, + uint64_t deviceid) { - memset (args, 0, sizeof (*args)); + pathconf3resok resok; - args->from.name = oldname; - args->from.dir.data.data_val = (void *)olddirfh; - args->to.name = newname; - args->to.dir.data.data_val = (void *)newdirfh; + memset(res, 0, sizeof(*res)); + res->status = stat; + if (stat != NFS3_OK) + return; -} + nfs3_map_deviceid_to_statdev(buf, deviceid); + resok.obj_attributes = nfs3_stat_to_post_op_attr(buf); + resok.linkmax = 256; + resok.name_max = NFS_NAME_MAX; + resok.no_trunc = TRUE; + resok.chown_restricted = FALSE; + resok.case_insensitive = FALSE; + resok.case_preserving = TRUE; + res->pathconf3res_u.resok = resok; +} void -nfs3_fill_rename3res (rename3res *res, nfsstat3 stat, struct iatt *buf, - struct iatt *preoldparent, struct iatt *postoldparent, - struct iatt *prenewparent, struct iatt *postnewparent, - uint16_t xlid) +nfs3_prep_pathconf3args(pathconf3args *args, struct nfs3_fh *fh) +{ + memset(args, 0, sizeof(*args)); + args->object.data.data_val = (void *)fh; +} +int +nfs3_verify_dircookie(struct nfs3_state *nfs3, fd_t *dirfd, cookie3 cookie, + uint64_t cverf, nfsstat3 *stat) { - wcc_data dirwcc; + int ret = -1; - memset (res, 0, sizeof (*res)); - res->status = stat; - if (stat != NFS3_OK) - return; + if ((!nfs3) || (!dirfd)) + return -1; - nfs3_map_xlid_to_statdev (preoldparent, xlid); - nfs3_map_xlid_to_statdev (postoldparent, xlid); - nfs3_map_xlid_to_statdev (prenewparent, xlid); - nfs3_map_xlid_to_statdev (postnewparent, xlid); - nfs3_map_xlid_to_statdev (buf, xlid); - dirwcc = nfs3_stat_to_wcc_data (preoldparent, postoldparent); - res->rename3res_u.resok.fromdir_wcc = dirwcc; - dirwcc = nfs3_stat_to_wcc_data (prenewparent, postnewparent); - res->rename3res_u.resok.todir_wcc = dirwcc; -} + /* Can assume that this is first read on the dir, so cookie check + * is successful by default. + */ + if (cookie == 0) + return 0; + gf_msg_trace(GF_NFS3, 0, + "Verifying cookie: cverf: %" PRIu64 ", cookie: %" PRIu64, + cverf, cookie); + /* The cookie bad, no way cverf will be zero with a non-zero cookie. */ + if ((cverf == 0) && (cookie != 0)) { + gf_msg_trace(GF_NFS3, 0, "Bad cookie requested"); + if (stat) + *stat = NFS3ERR_BAD_COOKIE; + goto err; + } + + /* Yes, its true, our cookie is simply the fd_t address. + * NOTE: We used have the check for cookieverf but VMWare client sends + * a readdirp requests even after we've told it that EOF has been + * reached on the directory. This causes a problem because we close a + * dir fd_t after reaching EOF. The next readdirp sent by VMWare + * contains the address of the closed fd_t as cookieverf. Since we + * closed that fd_t, this readdirp results in a new opendir which will + * give an fd_t that will fail this check below. + */ + /* if ((cverf != (uint64_t)dirfd)) { + gf_log (GF_NFS3, GF_LOG_TRACE, "Cookieverf does not match"); + if (stat) + *stat = NFS3ERR_BAD_COOKIE; + goto err; + } + */ + gf_msg_trace(GF_NFS3, 0, "Cookie verified"); + if (stat) + *stat = NFS3_OK; + ret = 0; +err: + return ret; +} void -nfs3_prep_write3args (write3args *args, struct nfs3_fh *fh) +nfs3_stat_to_errstr(uint32_t xid, char *op, nfsstat3 stat, int pstat, + char *errstr, size_t len) { - memset (args, 0, sizeof (*args)); - args->file.data.data_val = (void *)fh; -} + if ((!op) || (!errstr)) + return; + snprintf(errstr, len, "XID: %x, %s: NFS: %d(%s), POSIX: %d(%s)", xid, op, + stat, nfsstat3_strerror(stat), pstat, strerror(pstat)); +} void -nfs3_fill_write3res (write3res *res, nfsstat3 stat, count3 count, - stable_how stable, uint64_t wverf, struct iatt *prestat, - struct iatt *poststat, uint16_t xlid) +nfs3_log_common_call(uint32_t xid, char *op, struct nfs3_fh *fh) { - write3resok resok; - memset (res, 0, sizeof (*res)); - res->status = stat; - if (stat != NFS3_OK) - return; + char fhstr[1024]; - nfs3_map_xlid_to_statdev (prestat, xlid); - nfs3_map_xlid_to_statdev (poststat, xlid); - resok.file_wcc = nfs3_stat_to_wcc_data (prestat, poststat); - resok.count = count; - resok.committed = stable; - memcpy (resok.verf, &wverf, sizeof (wverf)); + if (THIS->ctx->log.loglevel < GF_LOG_DEBUG) + return; - res->write3res_u.resok = resok; + nfs3_fh_to_str(fh, fhstr, sizeof(fhstr)); + gf_msg_debug(GF_NFS3, 0, "XID: %x, %s: args: %s", xid, op, fhstr); } - void -nfs3_prep_commit3args (commit3args *args, struct nfs3_fh *fh) +nfs3_log_fh_entry_call(uint32_t xid, char *op, struct nfs3_fh *fh, char *name) { - memset (args, 0, sizeof (*args)); - args->file.data.data_val = (void *)fh; -} + char fhstr[1024]; + if (THIS->ctx->log.loglevel < GF_LOG_DEBUG) + return; + nfs3_fh_to_str(fh, fhstr, sizeof(fhstr)); + gf_msg_debug(GF_NFS3, 0, "XID: %x, %s: args: %s, name: %s", xid, op, fhstr, + name); +} void -nfs3_fill_commit3res (commit3res *res, nfsstat3 stat, uint64_t wverf, - struct iatt *prestat, struct iatt *poststat,uint16_t xlid) +nfs3_log_rename_call(uint32_t xid, struct nfs3_fh *src, char *sname, + struct nfs3_fh *dst, char *dname) { - memset (res, 0, sizeof (*res)); - res->status = stat; - if (stat != NFS3_OK) - return; + char sfhstr[1024]; + char dfhstr[1024]; - nfs3_map_xlid_to_statdev (poststat, xlid); - nfs3_map_xlid_to_statdev (prestat, xlid); - res->commit3res_u.resok.file_wcc = nfs3_stat_to_wcc_data (prestat, - poststat); - memcpy (res->commit3res_u.resok.verf, &wverf, sizeof (wverf)); + if (THIS->ctx->log.loglevel < GF_LOG_DEBUG) + return; + nfs3_fh_to_str(src, sfhstr, sizeof(sfhstr)); + nfs3_fh_to_str(dst, dfhstr, sizeof(dfhstr)); + gf_msg_debug(GF_NFS3, 0, + "XID: %x, RENAME: args: Src: %s, " + "name: %s, Dst: %s, name: %s", + xid, sfhstr, sname, dfhstr, dname); } void -nfs3_fill_read3res (read3res *res, nfsstat3 stat, count3 count, - struct iatt *poststat, int is_eof, uint16_t xlid) +nfs3_log_create_call(uint32_t xid, struct nfs3_fh *fh, char *name, + createmode3 mode) { - post_op_attr poa; + char fhstr[1024]; + char *modestr = NULL; + char exclmode[] = "EXCLUSIVE"; + char unchkd[] = "UNCHECKED"; + char guarded[] = "GUARDED"; - memset (res, 0, sizeof (*res)); - res->status = stat; - if (stat != NFS3_OK) - return; + if (THIS->ctx->log.loglevel < GF_LOG_DEBUG) + return; + nfs3_fh_to_str(fh, fhstr, sizeof(fhstr)); + if (mode == EXCLUSIVE) + modestr = exclmode; + else if (mode == GUARDED) + modestr = guarded; + else + modestr = unchkd; - nfs3_map_xlid_to_statdev (poststat, xlid); - poa = nfs3_stat_to_post_op_attr (poststat); - res->read3res_u.resok.file_attributes = poa; - res->read3res_u.resok.count = count; - res->read3res_u.resok.eof = is_eof; - res->read3res_u.resok.data.data_len = count; + gf_msg_debug(GF_NFS3, 0, + "XID: %x, CREATE: args: %s, name: %s," + " mode: %s", + xid, fhstr, name, modestr); } - void -nfs3_prep_read3args (read3args *args, struct nfs3_fh *fh) +nfs3_log_mknod_call(uint32_t xid, struct nfs3_fh *fh, char *name, int type) { - memset (args, 0, sizeof (*args)); - args->file.data.data_val = (void *)fh; -} + char fhstr[1024]; + char *modestr = NULL; + char chr[] = "CHAR"; + char blk[] = "BLK"; + char sock[] = "SOCK"; + char fifo[] = "FIFO"; + if (THIS->ctx->log.loglevel < GF_LOG_DEBUG) + return; + nfs3_fh_to_str(fh, fhstr, sizeof(fhstr)); + if (type == NF3CHR) + modestr = chr; + else if (type == NF3BLK) + modestr = blk; + else if (type == NF3SOCK) + modestr = sock; + else + modestr = fifo; + + gf_msg_debug(GF_NFS3, 0, + "XID: %x, MKNOD: args: %s, name: %s," + " type: %s", + xid, fhstr, name, modestr); +} void -nfs3_fill_pathconf3res (pathconf3res *res, nfsstat3 stat, struct iatt *buf, - uint16_t xlid) +nfs3_log_symlink_call(uint32_t xid, struct nfs3_fh *fh, char *name, char *tgt) { - pathconf3resok resok; + char fhstr[1024]; - memset (res, 0, sizeof (*res)); - res->status = stat; - if (stat != NFS3_OK) - return; + if (THIS->ctx->log.loglevel < GF_LOG_DEBUG) + return; + nfs3_fh_to_str(fh, fhstr, sizeof(fhstr)); + gf_msg_debug(GF_NFS3, 0, + "XID: %x, SYMLINK: args: %s, name: %s," + " target: %s", + xid, fhstr, name, tgt); +} - nfs3_map_xlid_to_statdev (buf, xlid); - resok.obj_attributes = nfs3_stat_to_post_op_attr (buf); - resok.linkmax = 256; - resok.name_max = NFS_NAME_MAX; - resok.no_trunc = TRUE; - resok.chown_restricted = FALSE; - resok.case_insensitive = FALSE; - resok.case_preserving = TRUE; +void +nfs3_log_link_call(uint32_t xid, struct nfs3_fh *fh, char *name, + struct nfs3_fh *tgt) +{ + char dfhstr[1024]; + char tfhstr[1024]; - res->pathconf3res_u.resok = resok; + if (THIS->ctx->log.loglevel < GF_LOG_DEBUG) + return; + nfs3_fh_to_str(fh, dfhstr, sizeof(dfhstr)); + nfs3_fh_to_str(tgt, tfhstr, sizeof(tfhstr)); + gf_msg_debug(GF_NFS3, 0, + "XID: %x, LINK: args: %s, name: %s," + " target: %s", + xid, dfhstr, name, tfhstr); } - void -nfs3_prep_pathconf3args (pathconf3args *args, struct nfs3_fh *fh) +nfs3_log_rw_call(uint32_t xid, char *op, struct nfs3_fh *fh, offset3 offt, + count3 count, int stablewrite) { - memset (args, 0, sizeof (*args)); - args->object.data.data_val = (void *)fh; -} + char fhstr[1024]; + if (THIS->ctx->log.loglevel < GF_LOG_DEBUG) + return; + nfs3_fh_to_str(fh, fhstr, sizeof(fhstr)); + if (stablewrite == -1) + gf_msg_debug(GF_NFS3, 0, + "XID: %x, %s: args: %s, offset:" + " %" PRIu64 ", count: %" PRIu32, + xid, op, fhstr, offt, count); + else + gf_msg_debug(GF_NFS3, 0, + "XID: %x, %s: args: %s, offset:" + " %" PRIu64 ", count: %" PRIu32 ", %s", + xid, op, fhstr, offt, count, + (stablewrite == UNSTABLE) ? "UNSTABLE" : "STABLE"); +} int -nfs3_verify_dircookie (struct nfs3_state *nfs3, fd_t *dirfd, cookie3 cookie, - uint64_t cverf, nfsstat3 *stat) +nfs3_getattr_loglevel(nfsstat3 stat) { - int ret = -1; + int ll = GF_LOG_DEBUG; - if ((!nfs3) || (!dirfd)) - return -1; + switch (stat) { + case NFS3ERR_PERM: + ll = GF_LOG_WARNING; + break; - /* Can assume that this is first read on the dir, so cookie check - * is successful by default. - */ - if (cookie == 0) - return 0; - - gf_log (GF_NFS3, GF_LOG_TRACE, "Verifying cookie: cverf: %"PRIu64 - ", cookie: %"PRIu64, cverf, cookie); - /* The cookie bad, no way cverf will be zero with a non-zero cookie. */ - if ((cverf == 0) && (cookie != 0)) { - gf_log (GF_NFS3, GF_LOG_TRACE, "Bad cookie requested"); - if (stat) - *stat = NFS3ERR_BAD_COOKIE; - goto err; - } + case NFS3ERR_NOENT: + ll = GF_LOG_WARNING; + break; - /* Yes, its true, our cookie is simply the fd_t address. - * NOTE: We used have the check for cookieverf but VMWare client sends - * a readdirp requests even after we've told it that EOF has been - * reached on the directory. This causes a problem because we close a - * dir fd_t after reaching EOF. The next readdirp sent by VMWare - * contains the address of the closed fd_t as cookieverf. Since we - * closed that fd_t, this readdirp results in a new opendir which will - * give an fd_t that will fail this check below. - */ -/* if ((cverf != (uint64_t)dirfd)) { - gf_log (GF_NFS3, GF_LOG_TRACE, "Cookieverf does not match"); - if (stat) - *stat = NFS3ERR_BAD_COOKIE; - goto err; - } -*/ - gf_log (GF_NFS3, GF_LOG_TRACE, "Cookie verified"); - if (stat) - *stat = NFS3_OK; - ret = 0; -err: - return ret; -} + case NFS3ERR_ACCES: + ll = GF_LOG_WARNING; + break; + case NFS3ERR_EXIST: + ll = GF_LOG_WARNING; + break; -/* When remove a file, we need to unref the cached fd for an inode but this - * needs to happen only when the file was in fact opened. However, it is - * possible that fd_lookup on a file returns an fd because the file was in - * process of being created(which also returns an fd) but since this fd was not - * opened through this path, in the NFS3 remove path, we'll end up removing the - * reference that belongs to someone else. That means, nfs3 remove path should - * not unref unless it is sure that the file was cached open also. If it was, - * only then perform the fd_unref, else not. - * - * We determine that using a flag in the inode context. - */ -int -nfs3_set_inode_opened (xlator_t *nfsxl, inode_t *inode) -{ - if ((!nfsxl) || (!inode)) - return -1; + case NFS3ERR_XDEV: + ll = GF_LOG_WARNING; + break; - inode_ctx_put (inode, nfsxl, GF_NFS3_FD_CACHED); + case NFS3ERR_NODEV: + ll = GF_LOG_WARNING; + break; - return 0; -} + case NFS3ERR_IO: + ll = GF_LOG_WARNING; + break; + case NFS3ERR_NXIO: + ll = GF_LOG_WARNING; + break; -/* Returns 1 if inode was cached open, otherwise 0 */ -int -nfs3_cached_inode_opened (xlator_t *nfsxl, inode_t *inode) -{ - int ret = -1; - uint64_t cflag = 0; + case NFS3ERR_NOTDIR: + ll = GF_LOG_WARNING; + break; - if ((!nfsxl) || (!inode)) - return -1; + case NFS3ERR_ISDIR: + ll = GF_LOG_WARNING; + break; - ret = inode_ctx_get (inode, nfsxl, &cflag); - if (ret == -1) - ret = 0; - else if (cflag == GF_NFS3_FD_CACHED) - ret = 1; + case NFS3ERR_INVAL: + ll = GF_LOG_WARNING; + break; - return ret; -} + case NFS3ERR_NOSPC: + ll = GF_LOG_WARNING; + break; + case NFS3ERR_ROFS: + ll = GF_LOG_WARNING; + break; -int32_t -nfs3_dir_open_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, fd_t *fd) -{ - nfs3_call_state_t *cs = NULL; + case NFS3ERR_FBIG: + ll = GF_LOG_WARNING; + break; - cs = frame->local; - if (op_ret == -1) { - cs->resolve_ret = -1; - cs->resolve_errno = op_errno; - nfs3_call_resume (cs); - goto err; - } + case NFS3ERR_MLINK: + ll = GF_LOG_WARNING; + break; - cs->fd = fd_ref (fd); - nfs3_set_inode_opened (cs->nfsx, cs->resolvedloc.inode); - gf_log (GF_NFS3, GF_LOG_TRACE, "FD_REF: %d", fd->refcount); - nfs3_call_resume (cs); -err: - return 0; -} + case NFS3ERR_NAMETOOLONG: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOTEMPTY: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_SERVERFAULT: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOTSUPP: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_BADHANDLE: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_STALE: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_DQUOT: + ll = GF_LOG_WARNING; + break; + + default: + ll = GF_LOG_DEBUG; + break; + } + return ll; +} int -__nfs3_dir_open_and_resume (nfs3_call_state_t *cs) +nfs3_setattr_loglevel(nfsstat3 stat) { - nfs_user_t nfu = {0, }; - int ret = -EFAULT; + int ll = GF_LOG_DEBUG; - if (!cs) - return ret; + switch (stat) { + case NFS3ERR_NOENT: + ll = GF_LOG_WARNING; + break; - nfs_user_root_create (&nfu); - ret = nfs_opendir (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, - nfs3_dir_open_cbk, cs); - return ret; -} + case NFS3ERR_EXIST: + ll = GF_LOG_WARNING; + break; + case NFS3ERR_XDEV: + ll = GF_LOG_WARNING; + break; -int -nfs3_dir_open_and_resume (nfs3_call_state_t *cs, nfs3_resume_fn_t resume) -{ - fd_t *fd = NULL; - int ret = -EFAULT; - - if ((!cs)) - return ret; - - cs->resume_fn = resume; - gf_log (GF_NFS3, GF_LOG_TRACE, "Opening: %s", cs->resolvedloc.path); - fd = fd_lookup (cs->resolvedloc.inode, 0); - if (fd) { - gf_log (GF_NFS3, GF_LOG_TRACE, "fd found in state: ref: %d", fd->refcount); - cs->fd = fd_ref (fd); /* Gets unrefd when the call state is wiped. */ - cs->resolve_ret = 0; - nfs3_call_resume (cs); - ret = 0; - goto err; - } + case NFS3ERR_NODEV: + ll = GF_LOG_WARNING; + break; - ret = __nfs3_dir_open_and_resume (cs); + case NFS3ERR_IO: + ll = GF_LOG_WARNING; + break; -err: - return ret; -} + case NFS3ERR_NXIO: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOTDIR: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_ISDIR: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_INVAL: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOSPC: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_ROFS: + ll = GF_LOG_WARNING; + break; + case NFS3ERR_FBIG: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_MLINK: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NAMETOOLONG: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOTEMPTY: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_SERVERFAULT: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOTSUPP: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_BADHANDLE: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_STALE: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_DQUOT: + ll = GF_LOG_WARNING; + break; + + default: + ll = GF_LOG_DEBUG; + break; + } + + return ll; +} int -nfs3_flush_open_wait_call_states (nfs3_call_state_t *cs, fd_t *openedfd) +nfs3_lookup_loglevel(nfsstat3 stat) { - struct list_head *inode_q = NULL; - uint64_t ctxaddr = 0; - int ret = 0; - nfs3_call_state_t *cstmp = NULL; + int ll = GF_LOG_DEBUG; - if (!cs) - return -1; + switch (stat) { + case NFS3ERR_PERM: + ll = GF_LOG_WARNING; + break; - gf_log (GF_NFS3, GF_LOG_TRACE, "Flushing call state"); - ret = inode_ctx_get (cs->resolvedloc.inode, cs->nfsx, &ctxaddr); - if (ret == -1) { - gf_log (GF_NFS3, GF_LOG_TRACE, "No inode queue present"); - goto out; - } + case NFS3ERR_ACCES: + ll = GF_LOG_WARNING; + break; - inode_q = (struct list_head *)(long)ctxaddr; - if (!inode_q) - goto out; - - list_for_each_entry_safe (cs, cstmp, inode_q, openwait_q) { - gf_log (GF_NFS3, GF_LOG_TRACE, "Calling resume"); - cs->resolve_ret = 0; - if (openedfd) { - gf_log (GF_NFS3, GF_LOG_TRACE, "Opening uncached fd done: %d", - openedfd->refcount); - cs->fd = fd_ref (openedfd); - } - nfs3_call_resume (cs); - } + case NFS3ERR_EXIST: + ll = GF_LOG_WARNING; + break; -out: - return 0; -} + case NFS3ERR_XDEV: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NODEV: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_IO: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NXIO: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOTDIR: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_ISDIR: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_INVAL: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOSPC: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_ROFS: + ll = GF_LOG_WARNING; + break; + case NFS3ERR_FBIG: + ll = GF_LOG_WARNING; + break; + case NFS3ERR_MLINK: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NAMETOOLONG: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOTEMPTY: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_SERVERFAULT: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOTSUPP: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_BADHANDLE: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_STALE: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_DQUOT: + ll = GF_LOG_WARNING; + break; + + default: + ll = GF_LOG_DEBUG; + break; + } + + return ll; +} int -__nfs3_fdcache_update_entry (struct nfs3_state *nfs3, fd_t *fd) +nfs3_access_loglevel(nfsstat3 stat) { - uint64_t ctxaddr = 0; - struct nfs3_fd_entry *fde = NULL; + int ll = GF_LOG_DEBUG; - gf_log (GF_NFS3, GF_LOG_TRACE, "Updating fd: 0x%lx", (long int)fd); - fd_ctx_get (fd, nfs3->nfsx, &ctxaddr); - fde = (struct nfs3_fd_entry *)(long)ctxaddr; - list_del (&fde->list); - list_add_tail (&fde->list, &nfs3->fdlru); + switch (stat) { + case NFS3ERR_NOENT: + ll = GF_LOG_WARNING; + break; - return 0; -} + case NFS3ERR_EXIST: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_XDEV: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NODEV: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_IO: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NXIO: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOTDIR: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_ISDIR: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_INVAL: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOSPC: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_ROFS: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_FBIG: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_MLINK: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NAMETOOLONG: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOTEMPTY: + ll = GF_LOG_WARNING; + break; + case NFS3ERR_SERVERFAULT: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOTSUPP: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_BADHANDLE: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_STALE: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_DQUOT: + ll = GF_LOG_WARNING; + break; + + default: + ll = GF_LOG_DEBUG; + break; + } + + return ll; +} int -nfs3_fdcache_update (struct nfs3_state *nfs3, fd_t *fd) +nfs3_readlink_loglevel(nfsstat3 stat) { - if ((!nfs3) || (!fd)) - return -1; + int ll = GF_LOG_DEBUG; - LOCK (&nfs3->fdlrulock); - { - __nfs3_fdcache_update_entry (nfs3, fd); - } - UNLOCK (&nfs3->fdlrulock); + switch (stat) { + case NFS3ERR_EXIST: + ll = GF_LOG_WARNING; + break; - return 0; -} + case NFS3ERR_XDEV: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NODEV: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_IO: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NXIO: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOTDIR: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_ISDIR: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_INVAL: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOSPC: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_ROFS: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_FBIG: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_MLINK: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOTEMPTY: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_SERVERFAULT: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOTSUPP: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_BADHANDLE: + ll = GF_LOG_WARNING; + break; + case NFS3ERR_STALE: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_DQUOT: + ll = GF_LOG_WARNING; + break; + + default: + ll = GF_LOG_DEBUG; + break; + } + + return ll; +} int -__nfs3_fdcache_remove_entry (struct nfs3_state *nfs3, struct nfs3_fd_entry *fde) +nfs3_read_loglevel(nfsstat3 stat) { - gf_log (GF_NFS3, GF_LOG_TRACE, "Removing fd: 0x%lx: %d", - (long int)fde->cachedfd, fde->cachedfd->refcount); - list_del (&fde->list); - fd_ctx_del (fde->cachedfd, nfs3->nfsx, NULL); - fd_unref (fde->cachedfd); - GF_FREE (fde); - --nfs3->fdcount; + int ll = GF_LOG_DEBUG; - return 0; -} + switch (stat) { + case NFS3ERR_NOENT: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_EXIST: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_XDEV: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NODEV: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_IO: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NXIO: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOTDIR: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_ISDIR: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_INVAL: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOSPC: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_ROFS: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_FBIG: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_MLINK: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NAMETOOLONG: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOTEMPTY: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_SERVERFAULT: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOTSUPP: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_BADHANDLE: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_STALE: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_DQUOT: + ll = GF_LOG_WARNING; + break; + default: + ll = GF_LOG_DEBUG; + break; + } + + return ll; +} int -nfs3_fdcache_remove (struct nfs3_state *nfs3, fd_t *fd) +nfs3_write_loglevel(nfsstat3 stat) { - struct nfs3_fd_entry *fde = NULL; - uint64_t ctxaddr = 0; + int ll = GF_LOG_DEBUG; - if ((!nfs3) || (!fd)) - return -1; + switch (stat) { + case NFS3ERR_NOENT: + ll = GF_LOG_WARNING; + break; - LOCK (&nfs3->fdlrulock); - { - fd_ctx_get (fd, nfs3->nfsx, &ctxaddr); - fde = (struct nfs3_fd_entry *)(long)ctxaddr; - __nfs3_fdcache_remove_entry (nfs3, fde); - } - UNLOCK (&nfs3->fdlrulock); + case NFS3ERR_EXIST: + ll = GF_LOG_WARNING; + break; - return 0; -} + case NFS3ERR_XDEV: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NODEV: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_IO: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NXIO: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOTDIR: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_ISDIR: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_INVAL: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOSPC: + ll = GF_LOG_WARNING; + break; + case NFS3ERR_ROFS: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_FBIG: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_MLINK: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NAMETOOLONG: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOTEMPTY: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_SERVERFAULT: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOTSUPP: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_BADHANDLE: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_STALE: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_DQUOT: + ll = GF_LOG_WARNING; + break; + + default: + ll = GF_LOG_DEBUG; + break; + } + + return ll; +} int -__nfs3_fdcache_replace (struct nfs3_state *nfs3) +nfs3_create_loglevel(nfsstat3 stat) { - struct nfs3_fd_entry *fde = NULL; - struct nfs3_fd_entry *tmp = NULL; + int ll = GF_LOG_DEBUG; - if (!nfs3) - return -1; + switch (stat) { + case NFS3ERR_NOENT: + ll = GF_LOG_WARNING; + break; - if (nfs3->fdcount <= GF_NFS3_FDCACHE_SIZE) - return 0; + case NFS3ERR_EXIST: + ll = GF_LOG_WARNING; + break; - list_for_each_entry_safe (fde, tmp, &nfs3->fdlru, list) - break; + case NFS3ERR_XDEV: + ll = GF_LOG_WARNING; + break; - __nfs3_fdcache_remove_entry (nfs3, fde); + case NFS3ERR_NODEV: + ll = GF_LOG_WARNING; + break; - return 0; -} + case NFS3ERR_IO: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NXIO: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOTDIR: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_ISDIR: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_INVAL: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_FBIG: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_MLINK: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOTEMPTY: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_SERVERFAULT: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOTSUPP: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_BADHANDLE: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_STALE: + ll = GF_LOG_WARNING; + break; + default: + ll = GF_LOG_DEBUG; + break; + } + return ll; +} int -nfs3_fdcache_add (struct nfs3_state *nfs3, fd_t *fd) +nfs3_mkdir_loglevel(nfsstat3 stat) { - struct nfs3_fd_entry *fde = NULL; - int ret = -1; + int ll = GF_LOG_DEBUG; - if ((!nfs3) || (!fd)) - return -1; + switch (stat) { + case NFS3ERR_NOENT: + ll = GF_LOG_WARNING; + break; - fde = GF_CALLOC (1, sizeof (*fd), gf_nfs_mt_nfs3_fd_entry); - if (!fde) { - gf_log (GF_NFS3, GF_LOG_ERROR, "fd entry allocation failed"); - goto out; - } + case NFS3ERR_XDEV: + ll = GF_LOG_WARNING; + break; - /* Already refd by caller. */ - fde->cachedfd = fd; - INIT_LIST_HEAD (&fde->list); - - LOCK (&nfs3->fdlrulock); - { - gf_log (GF_NFS3, GF_LOG_TRACE, "Adding fd: 0x%lx", - (long int) fd); - fd_ctx_set (fd, nfs3->nfsx, (uintptr_t)fde); - fd_bind (fd); - list_add_tail (&fde->list, &nfs3->fdlru); - ++nfs3->fdcount; - __nfs3_fdcache_replace (nfs3); - } - UNLOCK (&nfs3->fdlrulock); + case NFS3ERR_NODEV: + ll = GF_LOG_WARNING; + break; -out: - return ret; -} + case NFS3ERR_IO: + ll = GF_LOG_WARNING; + break; + case NFS3ERR_NXIO: + ll = GF_LOG_WARNING; + break; -int32_t -nfs3_file_open_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, fd_t *fd) -{ - nfs3_call_state_t *cs = NULL; - struct nfs3_state *nfs3 = NULL; - - cs = frame->local; - if (op_ret == -1) { - gf_log (GF_NFS3, GF_LOG_TRACE, "Opening uncached fd failed"); - cs->resolve_ret = -1; - cs->resolve_errno = op_errno; - fd = NULL; - } else { - gf_log (GF_NFS3, GF_LOG_TRACE, "Opening uncached fd done: %d", - fd->refcount); - } + case NFS3ERR_NOTDIR: + ll = GF_LOG_WARNING; + break; - nfs3 = rpcsvc_request_program_private (cs->req); - nfs3_flush_open_wait_call_states (cs, fd); - nfs3_fdcache_add (nfs3, fd); - return 0; + case NFS3ERR_ISDIR: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_INVAL: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_FBIG: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_MLINK: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOTEMPTY: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_SERVERFAULT: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOTSUPP: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_BADHANDLE: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_STALE: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_DQUOT: + ll = GF_LOG_WARNING; + break; + + default: + ll = GF_LOG_DEBUG; + break; + } + + return ll; } -/* Returns 1 if the current call is the first one to be queued. If so, the - * caller will need to send the open fop. If this is a non-first call to be - * queued, it means the fd opening is in progress. - * - * Returns 0, if this is a non-first call. - */ int -__nfs3_queue_call_state (nfs3_call_state_t *cs) +nfs3_symlink_loglevel(nfsstat3 stat) { - struct list_head *inode_q = NULL; - int ret = -1; - uint64_t ctxaddr = 0; + int ll = GF_LOG_DEBUG; - ret = __inode_ctx_get (cs->resolvedloc.inode, cs->nfsx, &ctxaddr); - if (ret == 0) { - inode_q = (struct list_head *)(long)ctxaddr; - goto attach_cs; - } + switch (stat) { + case NFS3ERR_XDEV: + ll = GF_LOG_WARNING; + break; - inode_q = GF_CALLOC (1, sizeof (*inode_q), gf_nfs_mt_list_head); - if (!inode_q) - goto err; + case NFS3ERR_NODEV: + ll = GF_LOG_WARNING; + break; - gf_log (GF_NFS3, GF_LOG_TRACE, "Initing inode queue"); - INIT_LIST_HEAD (inode_q); - __inode_ctx_put (cs->resolvedloc.inode, cs->nfsx, (uintptr_t)inode_q); + case NFS3ERR_IO: + ll = GF_LOG_WARNING; + break; -attach_cs: - if (list_empty (inode_q)) { - gf_log (GF_NFS3, GF_LOG_TRACE, "First call in queue"); - ret = 1; - } else - ret = 0; + case NFS3ERR_NXIO: + ll = GF_LOG_WARNING; + break; - gf_log (GF_NFS3, GF_LOG_TRACE, "Queueing call state"); - list_add_tail (&cs->openwait_q, inode_q); + case NFS3ERR_NOTDIR: + ll = GF_LOG_WARNING; + break; -err: - return ret; -} + case NFS3ERR_ISDIR: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_INVAL: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_FBIG: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_MLINK: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOTEMPTY: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_SERVERFAULT: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOTSUPP: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_BADHANDLE: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_STALE: + ll = GF_LOG_WARNING; + break; + case NFS3ERR_DQUOT: + ll = GF_LOG_WARNING; + break; + + default: + ll = GF_LOG_DEBUG; + break; + } + + return ll; +} int -nfs3_queue_call_state (nfs3_call_state_t *cs) +nfs3_mknod_loglevel(nfsstat3 stat) { - int ret = 0; - if (!cs) - return -1; + int ll = GF_LOG_DEBUG; - LOCK (&cs->resolvedloc.inode->lock); - { - ret = __nfs3_queue_call_state (cs); - } - UNLOCK (&cs->resolvedloc.inode->lock); + switch (stat) { + case NFS3ERR_NOENT: + ll = GF_LOG_WARNING; + break; - return ret; -} + case NFS3ERR_XDEV: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NODEV: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_IO: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NXIO: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOTDIR: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_ISDIR: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_INVAL: + ll = GF_LOG_WARNING; + break; + case NFS3ERR_FBIG: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_MLINK: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOTEMPTY: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_SERVERFAULT: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOTSUPP: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_BADHANDLE: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_STALE: + ll = GF_LOG_WARNING; + break; + + default: + ll = GF_LOG_DEBUG; + break; + } + + return ll; +} int -__nfs3_file_open_and_resume (nfs3_call_state_t *cs) +nfs3_remove_loglevel(nfsstat3 stat) { - nfs_user_t nfu = {0, }; - int ret = -EFAULT; + int ll = GF_LOG_DEBUG; - if (!cs) - return ret; + switch (stat) { + case NFS3ERR_EXIST: + ll = GF_LOG_WARNING; + break; - ret = nfs3_queue_call_state (cs); - if (ret != 1) { - ret = 0; - goto out; - } + case NFS3ERR_XDEV: + ll = GF_LOG_WARNING; + break; - nfs_user_root_create (&nfu); - gf_log (GF_NFS3, GF_LOG_TRACE, "Opening uncached fd"); - ret = nfs_open (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, O_RDWR, - nfs3_file_open_cbk, cs); -out: - return ret; -} + case NFS3ERR_NODEV: + ll = GF_LOG_WARNING; + break; + case NFS3ERR_IO: + ll = GF_LOG_WARNING; + break; + case NFS3ERR_NXIO: + ll = GF_LOG_WARNING; + break; -int -nfs3_file_open_and_resume (nfs3_call_state_t *cs, nfs3_resume_fn_t resume) -{ - fd_t *fd = NULL; - int ret = -EFAULT; - struct nfs3_state *nfs3 = NULL; - - if ((!cs)) - return ret; - - cs->resume_fn = resume; - gf_log (GF_NFS3, GF_LOG_TRACE, "Opening: %s", cs->resolvedloc.path); - fd = fd_lookup (cs->resolvedloc.inode, 0); - if (fd) { - nfs3 = rpcsvc_request_program_private (cs->req); - /* Already refd by fd_lookup, so no need to ref again. */ - gf_log (GF_NFS3, GF_LOG_TRACE, "fd found in state: %d", - fd->refcount); - nfs3_fdcache_update (nfs3, fd); - cs->fd = fd; /* Gets unrefd when the call state is wiped. */ - cs->resolve_ret = 0; - nfs3_call_resume (cs); - ret = 0; - goto err; - } + case NFS3ERR_NOTDIR: + ll = GF_LOG_WARNING; + break; - ret = __nfs3_file_open_and_resume (cs); + case NFS3ERR_INVAL: + ll = GF_LOG_WARNING; + break; -err: - return ret; -} + case NFS3ERR_NOSPC: + ll = GF_LOG_WARNING; + break; + case NFS3ERR_FBIG: + ll = GF_LOG_WARNING; + break; -void -nfs3_stat_to_errstr (uint32_t xid, char *op, nfsstat3 stat, int pstat, - char *errstr) -{ - if ((!op) || (!errstr)) - return; + case NFS3ERR_MLINK: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_SERVERFAULT: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOTSUPP: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_BADHANDLE: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_STALE: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_DQUOT: + ll = GF_LOG_WARNING; + break; - sprintf (errstr, "XID: %x, %s: NFS: %d(%s), POSIX: %d(%s)", xid, op, - stat, nfsstat3_strerror (stat), pstat, strerror (pstat)); + default: + ll = GF_LOG_DEBUG; + break; + } + + return ll; } -void -nfs3_log_common_call (uint32_t xid, char *op, struct nfs3_fh *fh) +int +nfs3_rmdir_loglevel(nfsstat3 stat) { - char fhstr[1024]; + int ll = GF_LOG_DEBUG; - nfs3_fh_to_str (fh, fhstr); - gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, %s: args: %s", xid, op, - fhstr); -} + switch (stat) { + case NFS3ERR_EXIST: + ll = GF_LOG_WARNING; + break; + case NFS3ERR_XDEV: + ll = GF_LOG_WARNING; + break; -void -nfs3_log_fh_entry_call (uint32_t xid, char *op, struct nfs3_fh *fh, - char *name) -{ - char fhstr[1024]; + case NFS3ERR_NODEV: + ll = GF_LOG_WARNING; + break; - nfs3_fh_to_str (fh, fhstr); - gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, %s: args: %s, name: %s", xid, - op, fhstr, name); -} + case NFS3ERR_IO: + ll = GF_LOG_WARNING; + break; + case NFS3ERR_NXIO: + ll = GF_LOG_WARNING; + break; -void -nfs3_log_rename_call (uint32_t xid, struct nfs3_fh *src, char *sname, - struct nfs3_fh *dst, char *dname) -{ - char sfhstr[1024]; - char dfhstr[1024]; + case NFS3ERR_NOTDIR: + ll = GF_LOG_WARNING; + break; - nfs3_fh_to_str (src, sfhstr); - nfs3_fh_to_str (dst, dfhstr); - gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, RENAME: args: Src: %s, " - "name: %s, Dst: %s, name: %s", xid, sfhstr, sname, dfhstr, - dname); -} + case NFS3ERR_INVAL: + ll = GF_LOG_WARNING; + break; + case NFS3ERR_NOSPC: + ll = GF_LOG_WARNING; + break; + case NFS3ERR_FBIG: + ll = GF_LOG_WARNING; + break; -void -nfs3_log_create_call (uint32_t xid, struct nfs3_fh *fh, char *name, - createmode3 mode) -{ - char fhstr[1024]; - char *modestr = NULL; - char exclmode[] = "EXCLUSIVE"; - char unchkd[] = "UNCHECKED"; - char guarded[] = "GUARDED"; + case NFS3ERR_MLINK: + ll = GF_LOG_WARNING; + break; - nfs3_fh_to_str (fh, fhstr); - if (mode == EXCLUSIVE) - modestr = exclmode; - else if (mode == GUARDED) - modestr = guarded; - else - modestr = unchkd; + case NFS3ERR_SERVERFAULT: + ll = GF_LOG_WARNING; + break; - gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, CREATE: args: %s, name: %s," - " mode: %s", xid, fhstr, name, modestr); -} + case NFS3ERR_NOTSUPP: + ll = GF_LOG_WARNING; + break; + case NFS3ERR_BADHANDLE: + ll = GF_LOG_WARNING; + break; -void -nfs3_log_mknod_call (uint32_t xid, struct nfs3_fh *fh, char *name, int type) -{ - char fhstr[1024]; - char *modestr = NULL; - char chr[] = "CHAR"; - char blk[] = "BLK"; - char sock[] = "SOCK"; - char fifo[] = "FIFO"; + case NFS3ERR_STALE: + ll = GF_LOG_WARNING; + break; - nfs3_fh_to_str (fh, fhstr); - if (type == NF3CHR) - modestr = chr; - else if (type == NF3BLK) - modestr = blk; - else if (type == NF3SOCK) - modestr = sock; - else - modestr = fifo; + case NFS3ERR_DQUOT: + ll = GF_LOG_WARNING; + break; - gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, MKNOD: args: %s, name: %s," - " type: %s", xid, fhstr, name, modestr); + default: + ll = GF_LOG_DEBUG; + break; + } + + return ll; } +int +nfs3_rename_loglevel(nfsstat3 stat) +{ + int ll = GF_LOG_DEBUG; + switch (stat) { + case NFS3ERR_XDEV: + ll = GF_LOG_WARNING; + break; -void -nfs3_log_symlink_call (uint32_t xid, struct nfs3_fh *fh, char *name, char *tgt) -{ - char fhstr[1024]; + case NFS3ERR_NODEV: + ll = GF_LOG_WARNING; + break; - nfs3_fh_to_str (fh, fhstr); - gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, SYMLINK: args: %s, name: %s," - " target: %s", xid, fhstr, name, tgt); -} + case NFS3ERR_IO: + ll = GF_LOG_WARNING; + break; + case NFS3ERR_NXIO: + ll = GF_LOG_WARNING; + break; -void -nfs3_log_link_call (uint32_t xid, struct nfs3_fh *fh, char *name, - struct nfs3_fh *tgt) -{ - char dfhstr[1024]; - char tfhstr[1024]; + case NFS3ERR_NOTDIR: + ll = GF_LOG_WARNING; + break; - nfs3_fh_to_str (fh, dfhstr); - nfs3_fh_to_str (tgt, tfhstr); - gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, LINK: args: %s, name: %s," - " target: %s", xid, dfhstr, name, tfhstr); -} + case NFS3ERR_ISDIR: + ll = GF_LOG_WARNING; + break; + case NFS3ERR_INVAL: + ll = GF_LOG_WARNING; + break; -void -nfs3_log_rw_call (uint32_t xid, char *op, struct nfs3_fh *fh, offset3 offt, - count3 count, int stablewrite) -{ - char fhstr[1024]; + case NFS3ERR_NOSPC: + ll = GF_LOG_WARNING; + break; - nfs3_fh_to_str (fh, fhstr); - if (stablewrite == -1) - gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, %s: args: %s, offset:" - " %"PRIu64", count: %"PRIu32, xid, op, fhstr, offt, - count); - else - gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, %s: args: %s, offset:" - " %"PRIu64", count: %"PRIu32", %s", xid, op, fhstr, - offt, count, - (stablewrite == UNSTABLE)?"UNSTABLE":"STABLE"); + case NFS3ERR_FBIG: + ll = GF_LOG_WARNING; + break; -} + case NFS3ERR_MLINK: + ll = GF_LOG_WARNING; + break; + case NFS3ERR_NOTEMPTY: + ll = GF_LOG_WARNING; + break; -void -nfs3_log_common_res (uint32_t xid, char *op, nfsstat3 stat, int pstat) -{ - char errstr[1024]; + case NFS3ERR_SERVERFAULT: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOTSUPP: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_BADHANDLE: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_STALE: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_DQUOT: + ll = GF_LOG_WARNING; + break; - nfs3_stat_to_errstr (xid, op, stat, pstat, errstr); - gf_log (GF_NFS3, GF_LOG_DEBUG, "%s", errstr); + default: + ll = GF_LOG_DEBUG; + break; + } + + return ll; } -void -nfs3_log_readlink_res (uint32_t xid, nfsstat3 stat, int pstat, char *linkpath) +int +nfs3_link_loglevel(nfsstat3 stat) { - char errstr[1024]; + int ll = GF_LOG_DEBUG; + + switch (stat) { + case NFS3ERR_XDEV: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NODEV: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_IO: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NXIO: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_INVAL: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_FBIG: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_MLINK: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_NOTEMPTY: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_SERVERFAULT: + ll = GF_LOG_WARNING; + break; - nfs3_stat_to_errstr (xid, "READLINK", stat, pstat, errstr); - gf_log (GF_NFS3, GF_LOG_DEBUG, "%s, target: %s", errstr, linkpath); + case NFS3ERR_NOTSUPP: + ll = GF_LOG_WARNING; + break; + case NFS3ERR_BADHANDLE: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_STALE: + ll = GF_LOG_WARNING; + break; + + case NFS3ERR_DQUOT: + ll = GF_LOG_WARNING; + break; + + default: + ll = GF_LOG_DEBUG; + break; + } + + return ll; } -void -nfs3_log_read_res (uint32_t xid, nfsstat3 stat, int pstat, count3 count, - int is_eof, struct iovec *vec, int32_t veccount) +int +nfs3_readdir_loglevel(nfsstat3 stat) { - char errstr[1024]; + int ll = GF_LOG_DEBUG; - nfs3_stat_to_errstr (xid, "READ", stat, pstat, errstr); - if (vec) - gf_log (GF_NFS3, GF_LOG_DEBUG, "%s, count: %"PRIu32", is_eof:" - " %d, vector: count: %d, len: %zd", errstr, count, - is_eof, veccount, vec->iov_len); - else - gf_log (GF_NFS3, GF_LOG_DEBUG, "%s, count: %"PRIu32", is_eof:" - " %d", errstr, count, is_eof); -} + switch (stat) { + case NFS3ERR_NOENT: + ll = GF_LOG_WARNING; + break; + case NFS3ERR_EXIST: + ll = GF_LOG_WARNING; + break; -void -nfs3_log_write_res (uint32_t xid, nfsstat3 stat, int pstat, count3 count, - int stable, uint64_t wverf) -{ - char errstr[1024]; + case NFS3ERR_XDEV: + ll = GF_LOG_WARNING; + break; - nfs3_stat_to_errstr (xid, "WRITE", stat, pstat, errstr); - gf_log (GF_NFS3, GF_LOG_DEBUG, "%s, count: %"PRIu32", %s,wverf: %"PRIu64 - , errstr, count, (stable == UNSTABLE)?"UNSTABLE":"STABLE", - wverf); -} + case NFS3ERR_NODEV: + ll = GF_LOG_WARNING; + break; + case NFS3ERR_IO: + ll = GF_LOG_WARNING; + break; -void -nfs3_log_newfh_res (uint32_t xid, char *op, nfsstat3 stat, int pstat, - struct nfs3_fh *newfh) -{ - char errstr[1024]; - char fhstr[1024]; + case NFS3ERR_NXIO: + ll = GF_LOG_WARNING; + break; - nfs3_stat_to_errstr (xid, op, stat, pstat, errstr); - nfs3_fh_to_str (newfh, fhstr); + case NFS3ERR_NOTDIR: + ll = GF_LOG_WARNING; + break; - gf_log (GF_NFS3, GF_LOG_DEBUG, "%s, %s", errstr, fhstr); -} + case NFS3ERR_ISDIR: + ll = GF_LOG_WARNING; + break; + case NFS3ERR_INVAL: + ll = GF_LOG_WARNING; + break; -void -nfs3_log_readdir_res (uint32_t xid, nfsstat3 stat, int pstat, uint64_t cverf, - count3 count, int is_eof) -{ - char errstr[1024]; + case NFS3ERR_NOSPC: + ll = GF_LOG_WARNING; + break; - nfs3_stat_to_errstr (xid, "READDIR", stat, pstat, errstr); - gf_log (GF_NFS3, GF_LOG_DEBUG, "%s, count: %"PRIu32", cverf: %"PRIu64 - ", is_eof: %d", errstr, count, cverf, is_eof); -} + case NFS3ERR_ROFS: + ll = GF_LOG_WARNING; + break; + case NFS3ERR_FBIG: + ll = GF_LOG_WARNING; + break; -void -nfs3_log_readdirp_res (uint32_t xid, nfsstat3 stat, int pstat, uint64_t cverf, - count3 dircount, count3 maxcount, int is_eof) -{ - char errstr[1024]; + case NFS3ERR_MLINK: + ll = GF_LOG_WARNING; + break; - nfs3_stat_to_errstr (xid, "READDIRPLUS", stat, pstat, errstr); - gf_log (GF_NFS3, GF_LOG_DEBUG, "%s, dircount: %"PRIu32", maxcount: %" - PRIu32", cverf: %"PRIu64", is_eof: %d", errstr, dircount, - maxcount, cverf, is_eof); -} + case NFS3ERR_NAMETOOLONG: + ll = GF_LOG_WARNING; + break; + case NFS3ERR_NOTEMPTY: + ll = GF_LOG_WARNING; + break; -void -nfs3_log_commit_res (uint32_t xid, nfsstat3 stat, int pstat, uint64_t wverf) -{ - char errstr[1024]; + case NFS3ERR_SERVERFAULT: + ll = GF_LOG_WARNING; + break; - nfs3_stat_to_errstr (xid, "COMMIT", stat, pstat, errstr); - gf_log (GF_NFS3, GF_LOG_DEBUG, "%s, wverf: %"PRIu64, errstr, wverf); -} + case NFS3ERR_NOTSUPP: + ll = GF_LOG_WARNING; + break; + case NFS3ERR_BADHANDLE: + ll = GF_LOG_WARNING; + break; -void -nfs3_log_readdir_call (uint32_t xid, struct nfs3_fh *fh, count3 dircount, - count3 maxcount) -{ - char fhstr[1024]; + case NFS3ERR_STALE: + ll = GF_LOG_WARNING; + break; - nfs3_fh_to_str (fh, fhstr); + case NFS3ERR_DQUOT: + ll = GF_LOG_WARNING; + break; - if (maxcount == 0) - gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, READDIR: args: %s," - " count: %d", xid, fhstr, (uint32_t)dircount); - else - gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, READDIRPLUS: args: %s," - " dircount: %d, maxcount: %d", xid, fhstr, - (uint32_t)dircount, (uint32_t)maxcount); -} + default: + ll = GF_LOG_DEBUG; + break; + } + return ll; +} int -nfs3_fh_resolve_inode_done (nfs3_call_state_t *cs, inode_t *inode) +nfs3_fsstat_loglevel(nfsstat3 stat) { - int ret = -EFAULT; + int ll = GF_LOG_DEBUG; - if ((!cs) || (!inode)) - return ret; + switch (stat) { + case NFS3ERR_PERM: + ll = GF_LOG_WARNING; + break; - gf_log (GF_NFS3, GF_LOG_TRACE, "FH inode resolved"); - ret = nfs_inode_loc_fill (inode, &cs->resolvedloc); - if (ret < 0) - goto err; + case NFS3ERR_NOENT: + ll = GF_LOG_WARNING; + break; - nfs3_call_resume (cs); + case NFS3ERR_ACCES: + ll = GF_LOG_WARNING; + break; -err: - return ret; -} + case NFS3ERR_EXIST: + ll = GF_LOG_WARNING; + break; -#define GF_NFS3_FHRESOLVE_FOUND 1 -#define GF_NFS3_FHRESOLVE_NOTFOUND 2 -#define GF_NFS3_FHRESOLVE_DIRFOUND 3 + case NFS3ERR_XDEV: + ll = GF_LOG_WARNING; + break; -int -nfs3_fh_resolve_check_entry (struct nfs3_fh *fh, gf_dirent_t *candidate, - int hashidx) -{ - struct iatt *ia = NULL; - int ret = GF_NFS3_FHRESOLVE_NOTFOUND; - nfs3_hash_entry_t entryhash = 0; - - if ((!fh) || (!candidate)) - return ret; - - if ((strcmp (candidate->d_name, ".") == 0) || - (strcmp (candidate->d_name, "..") == 0)) - goto found_entry; - - ia = &candidate->d_stat; - if ((ia->ia_gen == fh->gen) && (ia->ia_ino == fh->ino)) { - gf_log (GF_NFS3, GF_LOG_TRACE, "Found entry: gen: %"PRId64 - " ino: %"PRId64", name: %s", ia->ia_gen, ia->ia_ino, - candidate->d_name); - ret = GF_NFS3_FHRESOLVE_FOUND; - goto found_entry; - } + case NFS3ERR_NODEV: + ll = GF_LOG_WARNING; + break; - /* This condition ensures that we never have to be afraid of having - * a directory hash conflict with a file hash. The consequence of - * this condition is that we can now have unlimited files in a directory - * and upto 65536 sub-directories in a directory. - */ - if (!IA_ISDIR (candidate->d_stat.ia_type)) - goto found_entry; - entryhash = fh->entryhash[hashidx]; - if (entryhash == nfs3_fh_hash_entry (ia->ia_ino, ia->ia_gen)) { - gf_log (GF_NFS3, GF_LOG_TRACE, "Found hash match: %s: %d", - candidate->d_name, entryhash); - ret = GF_NFS3_FHRESOLVE_DIRFOUND; - goto found_entry; - } + case NFS3ERR_IO: + ll = GF_LOG_WARNING; + break; -found_entry: + case NFS3ERR_NXIO: + ll = GF_LOG_WARNING; + break; - return ret; -} + case NFS3ERR_NOTDIR: + ll = GF_LOG_WARNING; + break; + case NFS3ERR_ISDIR: + ll = GF_LOG_WARNING; + break; -int32_t -nfs3_fh_resolve_entry_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) -{ - nfs3_call_state_t *cs = NULL; - - cs = frame->local; - cs->resolve_ret = op_ret; - cs->resolve_errno = op_errno; - - if (op_ret == -1) { - gf_log (GF_NFS3, GF_LOG_TRACE, "Lookup failed: %s: %s", - cs->resolvedloc.path, strerror (op_errno)); - goto err; - } else - gf_log (GF_NFS3, GF_LOG_TRACE, "Entry looked up: %s", - cs->resolvedloc.path); + case NFS3ERR_INVAL: + ll = GF_LOG_WARNING; + break; - inode_link (inode, cs->resolvedloc.parent, cs->resolvedloc.name, buf); -err: - nfs3_call_resume (cs); - return 0; -} + case NFS3ERR_NOSPC: + ll = GF_LOG_WARNING; + break; + case NFS3ERR_ROFS: + ll = GF_LOG_WARNING; + break; + case NFS3ERR_FBIG: + ll = GF_LOG_WARNING; + break; -int32_t -nfs3_fh_resolve_readdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, - gf_dirent_t *entries); + case NFS3ERR_MLINK: + ll = GF_LOG_WARNING; + break; -int -nfs3_fh_resolve_found_entry (nfs3_call_state_t *cs, gf_dirent_t *candidate) -{ - uint64_t dirino = 0; - uint64_t dirgen = 0; - int ret = 0; - nfs_user_t nfu = {0, }; - - if ((!cs) || (!candidate)) - return -EFAULT; - - dirino = cs->resolvedloc.inode->ino; - dirgen = cs->resolvedloc.inode->generation; - - nfs_loc_wipe (&cs->resolvedloc); - ret = nfs_entry_loc_fill (cs->vol->itable, dirino, dirgen, - candidate->d_name, &cs->resolvedloc, - NFS_RESOLVE_CREATE); - if (ret == -ENOENT) { - gf_log (GF_NFS3, GF_LOG_TRACE, "Entry not in itable, needs" - " lookup"); - nfs_user_root_create (&nfu); - ret = nfs_lookup (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, - nfs3_fh_resolve_entry_lookup_cbk, - cs); - } else { - gf_log (GF_NFS3, GF_LOG_TRACE, "Entry got from itable"); - nfs3_call_resume (cs); - } + case NFS3ERR_NAMETOOLONG: + ll = GF_LOG_WARNING; + break; - return ret; -} + case NFS3ERR_NOTEMPTY: + ll = GF_LOG_WARNING; + break; + case NFS3ERR_SERVERFAULT: + ll = GF_LOG_WARNING; + break; -int32_t -nfs3_fh_resolve_parent_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) -{ - nfs3_call_state_t *cs = NULL; - - cs = frame->local; - cs->resolve_ret = op_ret; - cs->resolve_errno = op_errno; - - if (op_ret == -1) { - gf_log (GF_NFS3, GF_LOG_TRACE, "Lookup failed: %s: %s", - cs->resolvedloc.path, strerror (op_errno)); - nfs3_call_resume (cs); - goto err; - } else - gf_log (GF_NFS3, GF_LOG_TRACE, "Entry looked up: %s", - cs->resolvedloc.path); + case NFS3ERR_NOTSUPP: + ll = GF_LOG_WARNING; + break; - inode_link (inode, cs->resolvedloc.parent, cs->resolvedloc.name, buf); - nfs3_fh_resolve_entry_hard (cs); + case NFS3ERR_BADHANDLE: + ll = GF_LOG_WARNING; + break; -err: - return 0; -} + case NFS3ERR_STALE: + ll = GF_LOG_WARNING; + break; + case NFS3ERR_DQUOT: + ll = GF_LOG_WARNING; + break; -int -nfs3_fh_resolve_found_parent (nfs3_call_state_t *cs, gf_dirent_t *candidate) -{ - uint64_t dirino = 0; - uint64_t dirgen = 0; - int ret = 0; - nfs_user_t nfu = {0, }; - - if ((!cs) || (!candidate)) - return -EFAULT; - - dirino = cs->resolvedloc.inode->ino; - dirgen = cs->resolvedloc.inode->generation; - - nfs_loc_wipe (&cs->resolvedloc); - ret = nfs_entry_loc_fill (cs->vol->itable, dirino, dirgen, - candidate->d_name, &cs->resolvedloc, - NFS_RESOLVE_CREATE); - if (ret == -ENOENT) { - nfs_user_root_create (&nfu); - ret = nfs_lookup (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, - nfs3_fh_resolve_parent_lookup_cbk, - cs); - } else - nfs3_fh_resolve_entry_hard (cs); + default: + ll = GF_LOG_DEBUG; + break; + } - return ret; + return ll; } +struct nfs3op_str { + int op; + char str[100]; +}; + +struct nfs3op_str nfs3op_strings[] = { + {NFS3_NULL, "NULL"}, {NFS3_GETATTR, "GETATTR"}, + {NFS3_SETATTR, "SETATTR"}, {NFS3_LOOKUP, "LOOKUP"}, + {NFS3_ACCESS, "ACCESS"}, {NFS3_READLINK, "READLINK"}, + {NFS3_READ, "READ"}, {NFS3_WRITE, "WRITE"}, + {NFS3_CREATE, "CREATE"}, {NFS3_MKDIR, "MKDIR"}, + {NFS3_SYMLINK, "SYMLINK"}, {NFS3_MKNOD, "MKNOD"}, + {NFS3_REMOVE, "REMOVE"}, {NFS3_RMDIR, "RMDIR"}, + {NFS3_RENAME, "RENAME"}, {NFS3_LINK, "LINK"}, + {NFS3_READDIR, "READDIR"}, {NFS3_READDIRP, "READDIRP"}, + {NFS3_FSSTAT, "FSSTAT"}, {NFS3_FSINFO, "FSINFO"}, + {NFS3_PATHCONF, "PATHCONF"}, {NFS3_COMMIT, "COMMIT"}, +}; int -nfs3_fh_resolve_found (nfs3_call_state_t *cs, gf_dirent_t *candidate) +nfs3_loglevel(int nfs_op, nfsstat3 stat) { - int ret = 0; + int ll = GF_LOG_DEBUG; - if ((!cs) || (!candidate)) - return -EFAULT; + switch (nfs_op) { + case NFS3_GETATTR: + ll = nfs3_getattr_loglevel(stat); + break; - if (!cs->resolventry) { - gf_log (GF_NFS3, GF_LOG_TRACE, "Candidate entry was found"); - ret = nfs3_fh_resolve_found_entry (cs, candidate); - } else { - gf_log (GF_NFS3, GF_LOG_TRACE, "Entry's parent was found"); - ret = nfs3_fh_resolve_found_parent (cs, candidate); - } + case NFS3_SETATTR: + ll = nfs3_setattr_loglevel(stat); + break; - return ret; + case NFS3_LOOKUP: + ll = nfs3_lookup_loglevel(stat); + break; + + case NFS3_ACCESS: + ll = nfs3_access_loglevel(stat); + break; + + case NFS3_READLINK: + ll = nfs3_readlink_loglevel(stat); + break; + + case NFS3_READ: + ll = nfs3_read_loglevel(stat); + break; + + case NFS3_WRITE: + ll = nfs3_write_loglevel(stat); + break; + + case NFS3_CREATE: + ll = nfs3_create_loglevel(stat); + break; + + case NFS3_MKDIR: + ll = nfs3_mkdir_loglevel(stat); + break; + + case NFS3_SYMLINK: + ll = nfs3_symlink_loglevel(stat); + break; + + case NFS3_MKNOD: + ll = nfs3_mknod_loglevel(stat); + break; + + case NFS3_REMOVE: + ll = nfs3_remove_loglevel(stat); + break; + + case NFS3_RMDIR: + ll = nfs3_rmdir_loglevel(stat); + break; + + case NFS3_RENAME: + ll = nfs3_rename_loglevel(stat); + break; + + case NFS3_LINK: + ll = nfs3_link_loglevel(stat); + break; + + case NFS3_READDIR: + ll = nfs3_readdir_loglevel(stat); + break; + + case NFS3_READDIRP: + ll = nfs3_readdir_loglevel(stat); + break; + + case NFS3_FSSTAT: + ll = nfs3_fsstat_loglevel(stat); + break; + + case NFS3_FSINFO: + ll = nfs3_fsstat_loglevel(stat); + break; + + case NFS3_PATHCONF: + ll = nfs3_fsstat_loglevel(stat); + break; + + case NFS3_COMMIT: + ll = nfs3_write_loglevel(stat); + break; + + default: + ll = GF_LOG_DEBUG; + break; + } + + return ll; } +void +nfs3_log_common_res(uint32_t xid, int op, nfsstat3 stat, int pstat, + const char *path) +{ + char errstr[1024]; + int ll = nfs3_loglevel(op, stat); -int32_t -nfs3_fh_resolve_opendir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, fd_t *fd) -{ - nfs3_call_state_t *cs = NULL; - int ret = -EFAULT; - nfs_user_t nfu = {0, }; - - cs = frame->local; - cs->resolve_ret = op_ret; - cs->resolve_errno = op_errno; - - if (op_ret == -1) { - gf_log (GF_NFS3, GF_LOG_TRACE, "Dir open failed: %s: %s", - cs->resolvedloc.path, strerror (op_errno)); - nfs3_call_resume (cs); - goto err; - } else - gf_log (GF_NFS3, GF_LOG_TRACE, "Reading directory: %s", - cs->resolvedloc.path); + if (THIS->ctx->log.loglevel < ll) + return; + nfs3_stat_to_errstr(xid, nfs3op_strings[op].str, stat, pstat, errstr, + sizeof(errstr)); + if (ll == GF_LOG_DEBUG) + gf_msg_debug(GF_NFS3, 0, "%s => (%s)", path, errstr); + else + gf_msg(GF_NFS3, ll, errno, NFS_MSG_STAT_ERROR, "%s => (%s)", path, + errstr); +} - nfs_user_root_create (&nfu); - /* This function can be called in a recursive code path, so if another - * directory was opened in an earlier call, we must unref through this - * reference before opening another fd_t. - */ - if (cs->resolve_dir_fd) - fd_unref (cs->resolve_dir_fd); +void +nfs3_log_readlink_res(uint32_t xid, nfsstat3 stat, int pstat, char *linkpath, + const char *path) +{ + char errstr[1024]; + int ll = nfs3_loglevel(NFS3_READLINK, stat); - cs->resolve_dir_fd = fd_ref (fd); - ret = nfs_readdirp (cs->nfsx, cs->vol, &nfu, fd, GF_NFS3_DTPREF, 0, - nfs3_fh_resolve_readdir_cbk, cs); + if (THIS->ctx->log.loglevel < ll) + return; -err: - return ret; + nfs3_stat_to_errstr(xid, "READLINK", stat, pstat, errstr, sizeof(errstr)); + if (ll == GF_LOG_DEBUG) + gf_msg_debug(GF_NFS3, 0, "%s => (%s), target: %s", path, errstr, + linkpath); + else + gf_msg(GF_NFS3, ll, errno, NFS_MSG_STAT_ERROR, "%s => (%s) target: %s", + path, errstr, linkpath); } -int32_t -nfs3_fh_resolve_dir_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) +void +nfs3_log_read_res(uint32_t xid, nfsstat3 stat, int pstat, count3 count, + int is_eof, struct iovec *vec, int32_t veccount, + const char *path) { - nfs3_call_state_t *cs = NULL; - nfs_user_t nfu = {0, }; + char errstr[1024]; + int ll = GF_LOG_DEBUG; - cs = frame->local; - cs->resolve_ret = op_ret; - cs->resolve_errno = op_errno; + ll = nfs3_loglevel(NFS3_READ, stat); + if (THIS->ctx->log.loglevel < ll) + return; + nfs3_stat_to_errstr(xid, "READ", stat, pstat, errstr, sizeof(errstr)); + if (vec) + if (ll == GF_LOG_DEBUG) + gf_msg_debug(GF_NFS3, 0, + "%s => (%s), count: %" PRIu32 + ", is_eof:" + " %d, vector: count: %d, len: %zd", + path, errstr, count, is_eof, veccount, vec->iov_len); + else + gf_msg(GF_NFS3, ll, errno, NFS_MSG_STAT_ERROR, + "%s => (%s), count: %" PRIu32 + ", is_eof:" + " %d, vector: count: %d, len: %zd", + path, errstr, count, is_eof, veccount, vec->iov_len); + else if (ll == GF_LOG_DEBUG) + gf_msg_debug(GF_NFS3, 0, + "%s => (%s), count: %" PRIu32 + ", is_eof:" + " %d", + path, errstr, count, is_eof); + else + gf_msg(GF_NFS3, ll, errno, NFS_MSG_STAT_ERROR, + "%s => (%s), count: %" PRIu32 + ", is_eof:" + " %d", + path, errstr, count, is_eof); +} + +void +nfs3_log_write_res(uint32_t xid, nfsstat3 stat, int pstat, count3 count, + int stable, uint64_t wverf, const char *path) +{ + char errstr[1024]; + int ll = nfs3_loglevel(NFS3_WRITE, stat); + + if (THIS->ctx->log.loglevel < ll) + return; - if (op_ret == -1) { - gf_log (GF_NFS3, GF_LOG_TRACE, "Lookup failed: %s: %s", - cs->resolvedloc.path, strerror (op_errno)); - nfs3_call_resume (cs); - goto err; - } else - gf_log (GF_NFS3, GF_LOG_TRACE, "Dir will be opened: %s", - cs->resolvedloc.path); + nfs3_stat_to_errstr(xid, "WRITE", stat, pstat, errstr, sizeof(errstr)); + if (ll == GF_LOG_DEBUG) + gf_msg_debug(GF_NFS3, 0, + "%s => (%s), count: %" PRIu32 + ", %s,wverf: " + "%" PRIu64, + path, errstr, count, + (stable == UNSTABLE) ? "UNSTABLE" : "STABLE", wverf); + else + gf_msg(GF_NFS3, ll, errno, NFS_MSG_STAT_ERROR, + "%s => (%s), count: %" PRIu32 ", %s,wverf: %" PRIu64, path, + errstr, count, (stable == UNSTABLE) ? "UNSTABLE" : "STABLE", + wverf); +} + +void +nfs3_log_newfh_res(uint32_t xid, int op, nfsstat3 stat, int pstat, + struct nfs3_fh *newfh, const char *path) +{ + char errstr[1024]; + char fhstr[1024]; + int ll = nfs3_loglevel(op, stat); - nfs_user_root_create (&nfu); - inode_link (inode, cs->resolvedloc.parent, cs->resolvedloc.name, buf); - nfs_opendir (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, - nfs3_fh_resolve_opendir_cbk, cs); + if (THIS->ctx->log.loglevel < ll) + return; + nfs3_stat_to_errstr(xid, nfs3op_strings[op].str, stat, pstat, errstr, + sizeof(errstr)); + nfs3_fh_to_str(newfh, fhstr, sizeof(fhstr)); -err: - return 0; + if (ll == GF_LOG_DEBUG) + gf_msg_debug(GF_NFS3, 0, "%s => (%s), %s", path, errstr, fhstr); + else + gf_msg(GF_NFS3, nfs3_loglevel(op, stat), errno, NFS_MSG_STAT_ERROR, + "%s => (%s), %s", path, errstr, fhstr); +} + +void +nfs3_log_readdir_res(uint32_t xid, nfsstat3 stat, int pstat, uint64_t cverf, + count3 count, int is_eof, const char *path) +{ + char errstr[1024]; + int ll = nfs3_loglevel(NFS3_READDIR, stat); + + if (THIS->ctx->log.loglevel < ll) + return; + nfs3_stat_to_errstr(xid, "READDIR", stat, pstat, errstr, sizeof(errstr)); + if (ll == GF_LOG_DEBUG) + gf_msg_debug(GF_NFS3, 0, + "%s => (%s), count: %" PRIu32 ", cverf: %" PRIu64 + ", is_eof: %d", + path, errstr, count, cverf, is_eof); + else + gf_msg(GF_NFS3, ll, errno, NFS_MSG_STAT_ERROR, + "%s => (%s), count: %" PRIu32 ", cverf: %" PRIu64 ", is_eof: %d", + path, errstr, count, cverf, is_eof); } +void +nfs3_log_readdirp_res(uint32_t xid, nfsstat3 stat, int pstat, uint64_t cverf, + count3 dircount, count3 maxcount, int is_eof, + const char *path) +{ + char errstr[1024]; + int ll = nfs3_loglevel(NFS3_READDIRP, stat); + if (THIS->ctx->log.loglevel < ll) + return; + nfs3_stat_to_errstr(xid, "READDIRPLUS", stat, pstat, errstr, + sizeof(errstr)); + if (ll == GF_LOG_DEBUG) + gf_msg_debug(GF_NFS3, 0, + "%s => (%s), dircount: %" PRIu32 ", maxcount: %" PRIu32 + ", cverf: %" PRIu64 ", is_eof: %d", + path, errstr, dircount, maxcount, cverf, is_eof); + else + gf_msg(GF_NFS3, ll, errno, NFS_MSG_STAT_ERROR, + "%s => (%s), dircount: %" PRIu32 ", maxcount: %" PRIu32 + ", cverf: %" PRIu64 ", is_eof: %d", + path, errstr, dircount, maxcount, cverf, is_eof); +} -int -nfs3_fh_resolve_dir_hard (nfs3_call_state_t *cs, uint64_t ino, uint64_t gen, - char *entry) -{ - int ret = -EFAULT; - nfs_user_t nfu = {0, }; - - if (!cs) - return ret; - - cs->hashidx++; - nfs_loc_wipe (&cs->resolvedloc); - if (nfs3_fh_hash_index_is_beyond (&cs->resolvefh, cs->hashidx)) { - gf_log (GF_NFS3, GF_LOG_TRACE, "Hash index is beyond: idx %d, " - " fh idx: %d", cs->hashidx, cs->resolvefh.hashcount); - nfs3_call_resume_estale (cs); - ret = 0; - goto out; - } +void +nfs3_log_commit_res(uint32_t xid, nfsstat3 stat, int pstat, uint64_t wverf, + const char *path) +{ + char errstr[1024]; + int ll = nfs3_loglevel(NFS3_COMMIT, stat); - nfs_user_root_create (&nfu); - gf_log (GF_NFS3, GF_LOG_TRACE, "FH hard dir resolution: ino:" - " %"PRIu64", gen: %"PRIu64", entry: %s, hashidx: %d", - ino, gen, entry, cs->hashidx); - ret = nfs_entry_loc_fill (cs->vol->itable, ino, gen, entry, - &cs->resolvedloc, NFS_RESOLVE_CREATE); - - if (ret == 0) { - gf_log (GF_NFS3, GF_LOG_TRACE, "Dir will be opened: %s", - cs->resolvedloc.path); - ret = nfs_opendir (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, - nfs3_fh_resolve_opendir_cbk, cs); - } else if (ret == -ENOENT) { - gf_log (GF_NFS3, GF_LOG_TRACE, "Dir needs lookup: %s", - cs->resolvedloc.path); - ret = nfs_lookup (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, - nfs3_fh_resolve_dir_lookup_cbk, cs); - } -out: - return ret; + if (THIS->ctx->log.loglevel < ll) + return; + nfs3_stat_to_errstr(xid, "COMMIT", stat, pstat, errstr, sizeof(errstr)); + if (ll == GF_LOG_DEBUG) + gf_msg_debug(GF_NFS3, 0, "%s => (%s), wverf: %" PRIu64, path, errstr, + wverf); + else + gf_msg(GF_NFS3, ll, errno, NFS_MSG_STAT_ERROR, + "%s => (%s), wverf: %" PRIu64, path, errstr, wverf); } +void +nfs3_log_readdir_call(uint32_t xid, struct nfs3_fh *fh, count3 dircount, + count3 maxcount) +{ + char fhstr[1024]; -int -nfs3_fh_resolve_check_response (nfs3_call_state_t *cs, gf_dirent_t *candidate, - int response, off_t last_offt) -{ - uint64_t dirino = 0; - uint64_t dirgen = 0; - int ret = -EFAULT; - nfs_user_t nfu = {0, }; - - if (!cs) - return ret; - - dirino = cs->resolvedloc.inode->ino; - dirgen = cs->resolvedloc.inode->generation; - - if (response == GF_NFS3_FHRESOLVE_DIRFOUND) - ret = nfs3_fh_resolve_dir_hard (cs, dirino, dirgen, - candidate->d_name); - else if (response == GF_NFS3_FHRESOLVE_FOUND) - nfs3_fh_resolve_found (cs, candidate); - else if (response == GF_NFS3_FHRESOLVE_NOTFOUND) { - nfs_user_root_create (&nfu); - ret = nfs_readdirp (cs->nfsx, cs->vol, &nfu, cs->resolve_dir_fd, - GF_NFS3_DTPREF, last_offt, - nfs3_fh_resolve_readdir_cbk, cs); - } + if (THIS->ctx->log.loglevel < GF_LOG_DEBUG) + return; - return 0; + nfs3_fh_to_str(fh, fhstr, sizeof(fhstr)); + + if (maxcount == 0) + gf_msg_debug(GF_NFS3, 0, + "XID: %x, READDIR: args: %s," + " count: %d", + xid, fhstr, (uint32_t)dircount); + else + gf_msg_debug(GF_NFS3, 0, + "XID: %x, READDIRPLUS: args: %s," + " dircount: %d, maxcount: %d", + xid, fhstr, (uint32_t)dircount, (uint32_t)maxcount); } int -nfs3_fh_resolve_search_dir (nfs3_call_state_t *cs, gf_dirent_t *entries) -{ - gf_dirent_t *candidate = NULL; - int ret = GF_NFS3_FHRESOLVE_NOTFOUND; - off_t lastoff = 0; - - if ((!cs) || (!entries)) - return -EFAULT; - - if (list_empty (&entries->list)) - goto not_found; - - list_for_each_entry (candidate, &entries->list, list) { - lastoff = candidate->d_off; - gf_log (GF_NFS3, GF_LOG_TRACE, "Candidate: %s, ino: %"PRIu64 - ", gen: %"PRIu64, candidate->d_name, candidate->d_ino, - candidate->d_stat.ia_gen); - ret = nfs3_fh_resolve_check_entry (&cs->resolvefh, candidate, - cs->hashidx); - if (ret != GF_NFS3_FHRESOLVE_NOTFOUND) - break; - } +nfs3_fh_resolve_inode_done(nfs3_call_state_t *cs, inode_t *inode) +{ + int ret = -EFAULT; -not_found: - nfs3_fh_resolve_check_response (cs, candidate, ret, lastoff); + if ((!cs) || (!inode)) return ret; -} + gf_msg_trace(GF_NFS3, 0, "FH inode resolved"); + ret = nfs_inode_loc_fill(inode, &cs->resolvedloc, NFS_RESOLVE_EXIST); + if (ret < 0) { + gf_msg(GF_NFS3, GF_LOG_ERROR, -ret, NFS_MSG_INODE_LOC_FILL_ERROR, + "inode loc fill failed"); + goto err; + } + + nfs3_call_resume(cs); + +err: + return ret; +} int32_t -nfs3_fh_resolve_readdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int32_t op_ret, int32_t op_errno, - gf_dirent_t *entries) -{ - nfs3_call_state_t *cs = NULL; - - cs = frame->local; - if (op_ret <= 0) { - gf_log (GF_NFS3, GF_LOG_TRACE, "Directory read done: %s: %s", - cs->resolvedloc.path, strerror (op_ret)); - cs->resolve_ret = -1; - cs->resolve_errno = ENOENT; - nfs3_call_resume (cs); - goto err; +nfs3_fh_resolve_entry_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) +{ + nfs3_call_state_t *cs = NULL; + inode_t *linked_inode = NULL; + + cs = frame->local; + cs->resolve_ret = op_ret; + cs->resolve_errno = op_errno; + + if (op_ret == -1) { + if (op_errno == ENOENT) { + gf_msg_trace(GF_NFS3, 0, "Lookup failed: %s: %s", + cs->resolvedloc.path, strerror(op_errno)); + } else { + gf_msg(GF_NFS3, GF_LOG_ERROR, op_errno, NFS_MSG_LOOKUP_FAIL, + "Lookup failed: %s: %s", cs->resolvedloc.path, + strerror(op_errno)); } + goto err; + } else + gf_msg_trace(GF_NFS3, 0, "Entry looked up: %s", cs->resolvedloc.path); + + memcpy(&cs->stbuf, buf, sizeof(*buf)); + memcpy(&cs->postparent, postparent, sizeof(*postparent)); + linked_inode = inode_link(inode, cs->resolvedloc.parent, + cs->resolvedloc.name, buf); + if (linked_inode) { + nfs_fix_generation(this, linked_inode); + inode_lookup(linked_inode); + inode_unref(cs->resolvedloc.inode); + cs->resolvedloc.inode = linked_inode; + } else { + /* nfs3_fh_resolve_entry_hard() use to resolve entire path if needed. + * So the ctx for inode obtained from here need to set properly, + * otherwise it may result in a crash. + */ + nfs_fix_generation(this, inode); + } +err: + nfs3_call_resume(cs); + return 0; +} - nfs3_fh_resolve_search_dir (cs, entries); - +int32_t +nfs3_fh_resolve_inode_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) +{ + nfs3_call_state_t *cs = NULL; + inode_t *linked_inode = NULL; + + cs = frame->local; + cs->resolve_ret = op_ret; + cs->resolve_errno = op_errno; + + if (op_ret == -1) { + if (op_errno == ENOENT) { + gf_msg_trace(GF_NFS3, 0, "Lookup failed: %s: %s", + cs->resolvedloc.path, strerror(op_errno)); + } else { + gf_msg(GF_NFS3, GF_LOG_ERROR, op_errno, NFS_MSG_LOOKUP_FAIL, + "Lookup failed: %s: %s", cs->resolvedloc.path, + strerror(op_errno)); + } + nfs3_call_resume(cs); + goto err; + } + + memcpy(&cs->stbuf, buf, sizeof(*buf)); + memcpy(&cs->postparent, buf, sizeof(*postparent)); + linked_inode = inode_link(inode, cs->resolvedloc.parent, + cs->resolvedloc.name, buf); + if (linked_inode) { + nfs_fix_generation(this, linked_inode); + inode_lookup(linked_inode); + inode_unref(cs->resolvedloc.inode); + cs->resolvedloc.inode = linked_inode; + } + + /* If it is an entry lookup and we landed in the callback for hard + * inode resolution, it means the parent inode was not available and + * had to be resolved first. Now that is done, lets head back into + * entry resolution. + */ + if (cs->resolventry) + nfs3_fh_resolve_entry_hard(cs); + else + nfs3_call_resume(cs); err: - return 0; + return 0; } /* Needs no extra argument since it knows that the fh to be resolved is in * resolvefh and that it needs to start looking from the root. */ int -nfs3_fh_resolve_inode_hard (nfs3_call_state_t *cs) -{ - int ret = -EFAULT; - nfs_user_t nfu = {0, }; - - if (!cs) - return ret; - - cs->hashidx++; - nfs_loc_wipe (&cs->resolvedloc); - if (nfs3_fh_hash_index_is_beyond (&cs->resolvefh, cs->hashidx)) { - gf_log (GF_NFS3, GF_LOG_TRACE, "Hash index is beyond: idx %d, " - " fh idx: %d", cs->hashidx, cs->resolvefh.hashcount); - nfs3_call_resume_estale (cs); - ret = 0; - goto out; - } +nfs3_fh_resolve_inode_hard(nfs3_call_state_t *cs) +{ + int ret = -EFAULT; + nfs_user_t nfu = { + 0, + }; - nfs_user_root_create (&nfu); - gf_log (GF_NFS3, GF_LOG_TRACE, "FH hard resolution: ino:" - " %"PRIu64", gen: %"PRIu64", hashidx: %d", cs->resolvefh.ino, - cs->resolvefh.gen, cs->hashidx); - ret = nfs_ino_loc_fill (cs->vol->itable, 1, 0, &cs->resolvedloc); - - if (ret == 0) { - gf_log (GF_NFS3, GF_LOG_TRACE, "Dir will be opened: %s", - cs->resolvedloc.path); - ret = nfs_opendir (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, - nfs3_fh_resolve_opendir_cbk, cs); - } else if (ret == -ENOENT) { - gf_log (GF_NFS3, GF_LOG_TRACE, "Dir needs lookup: %s", - cs->resolvedloc.path); - ret = nfs_lookup (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, - nfs3_fh_resolve_dir_lookup_cbk, cs); - } + if (!cs) + return ret; + + gf_msg_trace(GF_NFS3, 0, "FH hard resolution for: gfid 0x%s", + uuid_utoa(cs->resolvefh.gfid)); + cs->hardresolved = 1; + nfs_loc_wipe(&cs->resolvedloc); + ret = nfs_gfid_loc_fill(cs->vol->itable, cs->resolvefh.gfid, + &cs->resolvedloc, NFS_RESOLVE_CREATE); + if (ret < 0) { + gf_msg(GF_NFS3, GF_LOG_ERROR, -ret, NFS_MSG_INODE_LOC_FILL_ERROR, + "Failed to fill loc using gfid: " + "%s", + strerror(-ret)); + goto out; + } + + nfs_user_root_create(&nfu); + ret = nfs_lookup(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, + nfs3_fh_resolve_inode_lookup_cbk, cs); out: - return ret; + return ret; } - int -nfs3_fh_resolve_entry_hard (nfs3_call_state_t *cs) -{ - int ret = -EFAULT; - nfs_user_t nfu = {0, }; - - if (!cs) - return ret; - - nfs_loc_wipe (&cs->resolvedloc); - nfs_user_root_create (&nfu); - gf_log (GF_NFS3, GF_LOG_TRACE, "FH hard resolution: ino:" - " %"PRIu64", gen: %"PRIu64", entry: %s, hashidx: %d", - cs->resolvefh.ino, cs->resolvefh.gen, cs->resolventry, - cs->hashidx); - - ret = nfs_entry_loc_fill (cs->vol->itable, cs->resolvefh.ino, - cs->resolvefh.gen, cs->resolventry, - &cs->resolvedloc, NFS_RESOLVE_CREATE); - - if (ret == -2) { - gf_log (GF_NFS3, GF_LOG_TRACE, "Entry needs lookup: %s", - cs->resolvedloc.path); - ret = nfs_lookup (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, - nfs3_fh_resolve_entry_lookup_cbk, cs); - ret = 0; - } else if (ret == -1) { - gf_log (GF_NFS3, GF_LOG_TRACE, "Entry needs parent lookup: %s", - cs->resolvedloc.path); - ret = nfs3_fh_resolve_inode_hard (cs); - } else if (ret == 0) { - cs->resolve_ret = 0; - nfs3_call_resume (cs); - } +nfs3_fh_resolve_entry_hard(nfs3_call_state_t *cs) +{ + int ret = -EFAULT; + nfs_user_t nfu = { + 0, + }; + gf_boolean_t freshlookup = _gf_false; + if (!cs) return ret; + + nfs_loc_wipe(&cs->resolvedloc); + nfs_user_root_create(&nfu); + gf_msg_trace(GF_NFS3, 0, + "FH hard resolution: gfid: %s " + ", entry: %s", + uuid_utoa(cs->resolvefh.gfid), cs->resolventry); + + ret = nfs_entry_loc_fill(cs->nfsx, cs->vol->itable, cs->resolvefh.gfid, + cs->resolventry, &cs->resolvedloc, + NFS_RESOLVE_CREATE, &freshlookup); + + if (ret == -2) { + gf_msg_trace(GF_NFS3, 0, "Entry needs lookup: %s", + cs->resolvedloc.path); + /* If the NFS op is lookup, let the resume callback + * handle the sending of the lookup fop. Similarly, + * if the NFS op is create, let the create call + * go ahead in the resume callback so that an EEXIST gets + * handled at posix without an extra fop at this point. + */ + if (freshlookup && + (nfs3_lookup_op(cs) || + (nfs3_create_op(cs) && !nfs3_create_exclusive_op(cs)))) { + cs->lookuptype = GF_NFS3_FRESH; + cs->resolve_ret = 0; + cs->hardresolved = 0; + nfs3_call_resume(cs); + } else { + cs->hardresolved = 1; + nfs_lookup(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, + nfs3_fh_resolve_entry_lookup_cbk, cs); + } + ret = 0; + } else if (ret == -1) { + gf_msg_trace(GF_NFS3, 0, "Entry needs parent lookup: %s", + cs->resolvedloc.path); + ret = nfs3_fh_resolve_inode_hard(cs); + } else if (ret == 0) { + cs->resolve_ret = 0; + nfs3_call_resume(cs); + } + + return ret; } int -nfs3_fh_resolve_inode (nfs3_call_state_t *cs) +nfs3_fh_resolve_inode(nfs3_call_state_t *cs) { - inode_t *inode = NULL; - int ret = -EFAULT; + inode_t *inode = NULL; + int ret = -EFAULT; + xlator_t *this = NULL; - if (!cs) - return ret; + if (!cs) + return ret; - gf_log (GF_NFS3, GF_LOG_TRACE, "FH needs inode resolution"); - inode = inode_get (cs->vol->itable, cs->resolvefh.ino, - cs->resolvefh.gen); - if (!inode) - ret = nfs3_fh_resolve_inode_hard (cs); - else - ret = nfs3_fh_resolve_inode_done (cs, inode); + this = cs->nfsx; + gf_msg_trace(GF_NFS3, 0, "FH needs inode resolution"); + gf_uuid_copy(cs->resolvedloc.gfid, cs->resolvefh.gfid); - if (inode) - inode_unref (inode); + inode = inode_find(cs->vol->itable, cs->resolvefh.gfid); + if (!inode || inode_ctx_get(inode, this, NULL)) + ret = nfs3_fh_resolve_inode_hard(cs); + else + ret = nfs3_fh_resolve_inode_done(cs, inode); - return ret; + if (inode) + inode_unref(inode); + + return ret; } int -nfs3_fh_resolve_entry (nfs3_call_state_t *cs) +nfs3_fh_resolve_entry(nfs3_call_state_t *cs) { - int ret = -EFAULT; + int ret = -EFAULT; - if (!cs) - return ret; - - ret = nfs3_fh_resolve_entry_hard (cs); - if (ret < 0) - nfs3_call_resume_estale (cs); + if (!cs) + return ret; - return 0; + return nfs3_fh_resolve_entry_hard(cs); } int -nfs3_fh_resolve_and_resume (nfs3_call_state_t *cs, struct nfs3_fh *fh, - char *entry, nfs3_resume_fn_t resum_fn) +nfs3_fh_resolve_resume(nfs3_call_state_t *cs) { - int ret = -EFAULT; + int ret = -EFAULT; - if ((!cs) || (!fh)) - return ret; + if (!cs) + return ret; - cs->resume_fn = resum_fn; - cs->resolvefh = *fh; - cs->hashidx = 0; + if (cs->resolve_ret < 0) + goto err_resume_call; - if (!entry) - ret = nfs3_fh_resolve_inode (cs); - else { - cs->resolventry = gf_strdup (entry); - if (!cs->resolventry) - goto err; + if (!cs->resolventry) + ret = nfs3_fh_resolve_inode(cs); + else + ret = nfs3_fh_resolve_entry(cs); - ret = nfs3_fh_resolve_entry (cs); - } +err_resume_call: + if (ret < 0) { + cs->resolve_ret = -1; + cs->resolve_errno = EFAULT; + nfs3_call_resume(cs); + ret = 0; + } + return ret; +} + +int32_t +nfs3_fh_resolve_root_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) +{ + nfs3_call_state_t *cs = NULL; + + cs = frame->local; + cs->resolve_ret = op_ret; + cs->resolve_errno = op_errno; + + if (op_ret == -1) { + gf_msg(GF_NFS3, GF_LOG_ERROR, op_errno, NFS_MSG_LOOKUP_ROOT_FAIL, + "Root lookup failed: %s", strerror(op_errno)); + goto err; + } else + gf_msg_trace(GF_NFS3, 0, "Root looked up: %s", cs->resolvedloc.path); + + nfs3_set_root_looked_up(cs->nfs3state, &cs->resolvefh); err: + nfs3_fh_resolve_resume(cs); + return 0; +} + +int +nfs3_fh_resolve_root(nfs3_call_state_t *cs) +{ + int ret = -EFAULT; + nfs_user_t nfu = { + 0, + }; + + if (!cs) return ret; + + if (nfs3_is_root_looked_up(cs->nfs3state, &cs->resolvefh)) { + ret = nfs3_fh_resolve_resume(cs); + goto out; + } + + nfs_user_root_create(&nfu); + gf_msg_trace(GF_NFS3, 0, "Root needs lookup"); + ret = nfs_root_loc_fill(cs->vol->itable, &cs->resolvedloc); + if (ret < 0) { + gf_msg(GF_NFS3, GF_LOG_ERROR, -ret, NFS_MSG_LOOKUP_ROOT_FAIL, + "Failed to lookup root from itable: %s", strerror(-ret)); + goto out; + } + + ret = nfs_lookup(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, + nfs3_fh_resolve_root_lookup_cbk, cs); + +out: + return ret; } +/** + * __nfs3_fh_auth_get_peer -- Get a peer name from the rpc request object + * + * @peer: Char * to write to + * @req : The request to get host/peer from + */ +int +__nfs3_fh_auth_get_peer(const rpcsvc_request_t *req, char *peer) +{ + struct sockaddr_storage sastorage = { + 0, + }; + rpc_transport_t *trans = NULL; + int ret = 0; + + /* Why do we pass in the peer here and then + * store it rather than malloc() and return a char * ? We want to avoid + * heap allocations in the IO path as much as possible for speed + * so we try to keep all allocations on the stack. + */ + trans = rpcsvc_request_transport(req); + ret = rpcsvc_transport_peeraddr(trans, peer, RPCSVC_PEER_STRLEN, &sastorage, + sizeof(sastorage)); + if (ret != 0) { + gf_msg(GF_NFS3, GF_LOG_WARNING, 0, NFS_MSG_GET_PEER_ADDR_FAIL, + "Failed to get peer addr: %s", gai_strerror(ret)); + } + return ret; +} +/* + * nfs3_fh_auth_nfsop () -- Checks if an nfsop is authorized. + * + * @cs: The NFS call state containing all the relevant information + * + * @return: 0 if authorized + * -EACCES for completely unauthorized fop + * -EROFS for unauthorized write operations (rm, mkdir, write) + */ +int +nfs3_fh_auth_nfsop(nfs3_call_state_t *cs, gf_boolean_t is_write_op) +{ + struct nfs_state *nfs = NULL; + struct mount3_state *ms = NULL; + + nfs = (struct nfs_state *)cs->nfsx->private; + ms = (struct mount3_state *)nfs->mstate; + return mnt3_authenticate_request(ms, cs->req, &cs->resolvefh, NULL, NULL, + NULL, NULL, is_write_op); +} + +int +nfs3_fh_resolve_and_resume(nfs3_call_state_t *cs, struct nfs3_fh *fh, + char *entry, nfs3_resume_fn_t resum_fn) +{ + int ret = -EFAULT; + + if ((!cs) || (!fh)) + return ret; + + cs->resume_fn = resum_fn; + cs->resolvefh = *fh; + cs->hashidx = 0; + + /* Check if the resolution is: + * a. fh resolution + * + * or + * + * b. (fh, basename) resolution + */ + if (entry) { /* b */ + cs->resolventry = gf_strdup(entry); + if (!cs->resolventry) + goto err; + } + + ret = nfs3_fh_resolve_root(cs); +err: + return ret; +} |
