summaryrefslogtreecommitdiffstats
path: root/xlators/nfs/server/src/nfs3-helpers.c
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/nfs/server/src/nfs3-helpers.c')
-rw-r--r--xlators/nfs/server/src/nfs3-helpers.c2825
1 files changed, 1102 insertions, 1723 deletions
diff --git a/xlators/nfs/server/src/nfs3-helpers.c b/xlators/nfs/server/src/nfs3-helpers.c
index e2c16ef0e..468f8f7af 100644
--- a/xlators/nfs/server/src/nfs3-helpers.c
+++ b/xlators/nfs/server/src/nfs3-helpers.c
@@ -1,18 +1,18 @@
/*
- Copyright (c) 2010-2011 Gluster, Inc. <http://www.gluster.com>
+ Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
This file is part of GlusterFS.
GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
+ it under the terms of the GNU Affero 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.
+ Affero General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Affero General Public License
along with this program. If not, see
<http://www.gnu.org/licenses/>.
*/
@@ -102,18 +102,21 @@ struct nfs3stat_strerror nfs3stat_strerror_table[] = {
uint64_t
nfs3_iatt_gfid_to_ino (struct iatt *buf)
{
- uint64_t ino = 0;
+ uuid_t gfid = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
+ uint64_t ino = 0;
if (!buf)
return 0;
- if (gf_nfs_enable_ino32()) {
- ino = (uint32_t )nfs_hash_gfid (buf->ia_gfid);
- goto hashout;
- }
+ if ((buf->ia_ino != 1) && (uuid_compare (buf->ia_gfid, gfid) != 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;
+ memcpy (&ino, &buf->ia_gfid[8], sizeof (uint64_t));
+ } else
+ ino = 1;
hashout:
return ino;
@@ -343,15 +346,25 @@ nfs3_stat_to_fattr3 (struct iatt *buf)
fa.fsid = buf->ia_dev;
fa.fileid = nfs3_iatt_gfid_to_ino (buf);
+ /* 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 = buf->ia_atime_nsec;
+ fa.atime.nseconds = 0;
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;
+ fa.ctime.nseconds = 0;
return fa;
}
@@ -395,10 +408,11 @@ nfs3_stat_to_pre_op_attr (struct iatt *pre)
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;
+ 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;
- poa.pre_op_attr_u.attributes.ctime.nseconds = pre->ia_ctime_nsec;
out:
return poa;
@@ -551,48 +565,171 @@ nfs3_prep_access3args (access3args *args, struct nfs3_fh *fh)
args->object.data.data_val = (void *)fh;
}
-#define POSIX_READ 4
-#define POSIX_WRITE 2
-#define POSIX_EXEC 1
uint32_t
-nfs3_accessbits (int32_t accbits)
+nfs3_owner_accessbits (ia_prot_t prot, ia_type_t type, uint32_t request)
{
- uint32_t accresult = 0;
+ uint32_t accresult = 0;
- if (accbits & POSIX_READ)
+ if (IA_PROT_RUSR (prot) && (request & ACCESS3_READ))
accresult |= ACCESS3_READ;
- if (accbits & POSIX_WRITE)
- accresult |= (ACCESS3_MODIFY | ACCESS3_EXTEND | ACCESS3_DELETE);
+ if (request & ACCESS3_LOOKUP)
+ if ((IA_ISDIR (type)) && (IA_PROT_XUSR (prot)))
+ accresult |= ACCESS3_LOOKUP;
+
+ if ((IA_PROT_WUSR (prot) && (request & ACCESS3_MODIFY)))
+ accresult |= ACCESS3_MODIFY;
+
+ if ((IA_PROT_WUSR (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_XUSR (prot) && (!IA_ISDIR (type)))
+ accresult |= ACCESS3_EXECUTE;
+
+ return accresult;
+}
+
+
+uint32_t
+nfs3_group_accessbits (ia_prot_t prot, ia_type_t type, uint32_t request)
+{
+ uint32_t accresult = 0;
+
+ if (IA_PROT_RGRP (prot) && (request & ACCESS3_READ))
+ accresult |= ACCESS3_READ;
+
+ if (request & ACCESS3_LOOKUP)
+ if ((IA_ISDIR (type)) && IA_PROT_RGRP (prot))
+ accresult |= ACCESS3_LOOKUP;
+
+ if (IA_PROT_WGRP (prot) && (request & ACCESS3_MODIFY))
+ accresult |= ACCESS3_MODIFY;
+
+ 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;
+}
+
+
+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.
+ */
- /* lookup on directory allowed only in case of execute permission */
- if (accbits & POSIX_EXEC)
- accresult |= (ACCESS3_EXECUTE | ACCESS3_LOOKUP);
+ if (request & ACCESS3_EXECUTE)
+ if (IA_PROT_XOTH (prot) && (!IA_ISDIR (type)))
+ accresult |= ACCESS3_EXECUTE;
return accresult;
}
+
uint32_t
-nfs3_request_to_accessbits (int32_t accbits)
+nfs3_superuser_accessbits (ia_prot_t prot, ia_type_t type, uint32_t request)
{
- uint32_t acc_request = 0;
+ 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 (accbits & ACCESS3_READ)
- acc_request |= POSIX_READ;
+ if (request & ACCESS3_EXTEND)
+ accresult |= ACCESS3_EXTEND;
- if (accbits & (ACCESS3_MODIFY | ACCESS3_EXTEND | ACCESS3_DELETE))
- acc_request |= POSIX_WRITE;
+ /* 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;
+}
- /* For lookup on directory check for execute permission */
- if (accbits & (ACCESS3_EXECUTE | ACCESS3_LOOKUP))
- acc_request |= POSIX_EXEC;
- return acc_request;
+uint32_t
+nfs3_stat_to_accessbits (struct iatt *buf, uint32_t request, uid_t uid,
+ gid_t gid, gid_t *auxgids, int gids)
+{
+ uint32_t accresult = 0;
+ ia_prot_t prot = {0, };
+ ia_type_t type = 0;
+ int testgid = -1;
+ int x = 0;
+
+ prot = buf->ia_prot;
+ type = buf->ia_type;
+
+ if (buf->ia_gid == gid)
+ testgid = gid;
+ else {
+ for (; x < gids; ++x) {
+ if (buf->ia_gid == auxgids[x]) {
+ testgid = buf->ia_gid;
+ break;
+ }
+ }
+ }
+
+ 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 ((testgid != -1) && (buf->ia_gid == testgid))
+ 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, int32_t accbits)
+nfs3_fill_access3res (access3res *res, nfsstat3 status, struct iatt *buf,
+ uint32_t accbits, uid_t uid, gid_t gid,
+ uint64_t deviceid, gid_t *gidarr, int gids)
{
+ post_op_attr objattr;
uint32_t accres = 0;
memset (res, 0, sizeof (*res));
@@ -600,8 +737,11 @@ nfs3_fill_access3res (access3res *res, nfsstat3 status, int32_t accbits)
if (status != NFS3_OK)
return;
- accres = nfs3_accessbits (accbits);
+ nfs3_map_deviceid_to_statdev (buf, deviceid);
+ objattr = nfs3_stat_to_post_op_attr (buf);
+ accres = nfs3_stat_to_accessbits (buf, accbits, uid, gid, gidarr, gids);
+ res->access3res_u.resok.obj_attributes = objattr;
res->access3res_u.resok.access = accres;
}
@@ -680,7 +820,7 @@ nfs3_fill_entry3 (gf_dirent_t *entry, struct nfs3_fh *dfh)
/* 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
+ * sense the behavious we provide is similar to the output of the
* command: "stat /.."
*/
entry->d_ino = nfs3_iatt_gfid_to_ino (&entry->d_stat);
@@ -749,7 +889,7 @@ nfs3_fill_entryp3 (gf_dirent_t *entry, struct nfs3_fh *dirfh, uint64_t devid)
/* 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
+ * sense the behavious we provide is similar to the output of the
* command: "stat /.."
*/
entry->d_ino = nfs3_iatt_gfid_to_ino (&entry->d_stat);
@@ -1603,1804 +1743,694 @@ err:
}
-void
-nfs3_stat_to_errstr (uint32_t xid, char *op, nfsstat3 stat, int pstat,
- char *errstr)
-{
- if ((!op) || (!errstr))
- return;
-
- sprintf (errstr, "XID: %x, %s: NFS: %d(%s), POSIX: %d(%s)", xid, op,
- stat, nfsstat3_strerror (stat), pstat, strerror (pstat));
-}
-
-void
-nfs3_log_common_call (uint32_t xid, char *op, struct nfs3_fh *fh)
-{
- char fhstr[1024];
-
- if (gf_log_loglevel < GF_LOG_DEBUG)
- return;
-
- nfs3_fh_to_str (fh, fhstr);
- gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, %s: args: %s", xid, op,
- fhstr);
-}
-
-
-void
-nfs3_log_fh_entry_call (uint32_t xid, char *op, struct nfs3_fh *fh,
- char *name)
+/* 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)
{
- char fhstr[1024];
-
- if (gf_log_loglevel < GF_LOG_DEBUG)
- return;
- nfs3_fh_to_str (fh, fhstr);
- gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, %s: args: %s, name: %s", xid,
- op, fhstr, name);
-}
+ if ((!nfsxl) || (!inode))
+ return -1;
+ inode_ctx_put (inode, nfsxl, GF_NFS3_FD_CACHED);
-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];
-
- if (gf_log_loglevel < GF_LOG_DEBUG)
- return;
- 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);
+ return 0;
}
-
-void
-nfs3_log_create_call (uint32_t xid, struct nfs3_fh *fh, char *name,
- createmode3 mode)
+/* Returns 1 if inode was cached open, otherwise 0 */
+int
+nfs3_cached_inode_opened (xlator_t *nfsxl, inode_t *inode)
{
- char fhstr[1024];
- char *modestr = NULL;
- char exclmode[] = "EXCLUSIVE";
- char unchkd[] = "UNCHECKED";
- char guarded[] = "GUARDED";
-
- if (gf_log_loglevel < GF_LOG_DEBUG)
- return;
- nfs3_fh_to_str (fh, fhstr);
- if (mode == EXCLUSIVE)
- modestr = exclmode;
- else if (mode == GUARDED)
- modestr = guarded;
- else
- modestr = unchkd;
-
- gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, CREATE: args: %s, name: %s,"
- " mode: %s", xid, fhstr, name, modestr);
-}
-
+ int ret = -1;
+ uint64_t cflag = 0;
-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";
+ if ((!nfsxl) || (!inode))
+ return -1;
- if (gf_log_loglevel < GF_LOG_DEBUG)
- return;
- 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;
+ ret = inode_ctx_get (inode, nfsxl, &cflag);
+ if (ret == -1)
+ ret = 0;
+ else if (cflag == GF_NFS3_FD_CACHED)
+ ret = 1;
- gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, MKNOD: args: %s, name: %s,"
- " type: %s", xid, fhstr, name, modestr);
+ return ret;
}
-
-void
-nfs3_log_symlink_call (uint32_t xid, struct nfs3_fh *fh, char *name, char *tgt)
+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)
{
- char fhstr[1024];
-
- if (gf_log_loglevel < GF_LOG_DEBUG)
- return;
- 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);
-}
-
+ nfs3_call_state_t *cs = NULL;
-void
-nfs3_log_link_call (uint32_t xid, struct nfs3_fh *fh, char *name,
- struct nfs3_fh *tgt)
-{
- char dfhstr[1024];
- char tfhstr[1024];
+ cs = frame->local;
+ if (op_ret == -1) {
+ cs->resolve_ret = -1;
+ cs->resolve_errno = op_errno;
+ nfs3_call_resume (cs);
+ goto err;
+ }
- if (gf_log_loglevel < GF_LOG_DEBUG)
- return;
- 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);
+ cs->fd = fd; /* Gets unrefd when the call state is wiped. */
+ 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;
}
-void
-nfs3_log_rw_call (uint32_t xid, char *op, struct nfs3_fh *fh, offset3 offt,
- count3 count, int stablewrite)
+int
+__nfs3_dir_open_and_resume (nfs3_call_state_t *cs)
{
- char fhstr[1024];
+ nfs_user_t nfu = {0, };
+ int ret = -EFAULT;
- if (gf_log_loglevel < GF_LOG_DEBUG)
- return;
- 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");
+ if (!cs)
+ return ret;
+ nfs_user_root_create (&nfu);
+ ret = nfs_opendir (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
+ nfs3_dir_open_cbk, cs);
+ return ret;
}
int
-nfs3_getattr_loglevel (nfsstat3 stat) {
-
- int ll = GF_LOG_DEBUG;
-
- switch (stat) {
-
- case NFS3ERR_PERM:
- ll = GF_LOG_WARNING;
- break;
-
- case NFS3ERR_NOENT:
- ll = GF_LOG_WARNING;
- break;
-
- case NFS3ERR_ACCES:
- 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;
+nfs3_dir_open_and_resume (nfs3_call_state_t *cs, nfs3_resume_fn_t resume)
+{
+ fd_t *fd = NULL;
+ int ret = -EFAULT;
- case NFS3ERR_DQUOT:
- ll = GF_LOG_WARNING;
- break;
+ if ((!cs))
+ return ret;
- default:
- ll = GF_LOG_DEBUG;
- break;
+ 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; /* Gets unrefd when the call state is wiped. */
+ cs->resolve_ret = 0;
+ nfs3_call_resume (cs);
+ ret = 0;
+ goto err;
}
- return ll;
-}
-
-
-int
-nfs3_setattr_loglevel (nfsstat3 stat) {
-
- int ll = GF_LOG_DEBUG;
-
- 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;
+ ret = __nfs3_dir_open_and_resume (cs);
- 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;
+err:
+ return ret;
}
int
-nfs3_lookup_loglevel (nfsstat3 stat) {
-
- int ll = GF_LOG_DEBUG;
-
- switch (stat) {
-
- case NFS3ERR_PERM:
- ll = GF_LOG_WARNING;
- break;
-
- case NFS3ERR_ACCES:
- 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;
+nfs3_flush_call_state (nfs3_call_state_t *cs, fd_t *openedfd)
+{
+ if ((!cs))
+ return -1;
- default:
- ll = GF_LOG_DEBUG;
- break;
+ gf_log (GF_NFS3, GF_LOG_TRACE, "Calling resume");
+ if (openedfd) {
+ gf_log (GF_NFS3, GF_LOG_TRACE, "Opening uncached fd done: %d",
+ openedfd->refcount);
+ cs->fd = fd_ref (openedfd);
+ /* Set resove_ret to 0 so that the error checking in the resume
+ * callback results in a successful read reply when the fd was
+ * opened. If the fd opening failed, the resolve_ret is already
+ * set to -1 in nfs3_file_open_cbk, so that will result in an
+ * error being returned to the nfs client' read request.
+ */
+ cs->resolve_ret = 0;
}
+ list_del (&cs->openwait_q);
+ nfs3_call_resume (cs);
- return ll;
+ return 0;
}
int
-nfs3_access_loglevel (nfsstat3 stat) {
-
- int ll = GF_LOG_DEBUG;
-
- 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;
+nfs3_flush_inode_queue (struct inode_op_queue *inode_q, fd_t *openedfd)
+{
+ nfs3_call_state_t *cstmp = NULL;
+ nfs3_call_state_t *cs = NULL;
- case NFS3ERR_DQUOT:
- ll = GF_LOG_WARNING;
- break;
+ if (!inode_q)
+ return -1;
- default:
- ll = GF_LOG_DEBUG;
- break;
- }
+ list_for_each_entry_safe (cs, cstmp, &inode_q->opq, openwait_q)
+ nfs3_flush_call_state (cs, openedfd);
- return ll;
+ return 0;
}
int
-nfs3_readlink_loglevel (nfsstat3 stat) {
-
- int ll = GF_LOG_DEBUG;
-
- switch (stat) {
-
- 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_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;
+nfs3_flush_open_wait_call_states (nfs3_call_state_t *cs, fd_t *openedfd)
+{
+ struct inode_op_queue *inode_q = NULL;
+ uint64_t ctxaddr = 0;
+ int ret = 0;
- case NFS3ERR_DQUOT:
- ll = GF_LOG_WARNING;
- break;
+ if (!cs)
+ return -1;
- default:
- ll = GF_LOG_DEBUG;
- 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;
}
- return ll;
-}
-
-int
-nfs3_read_loglevel (nfsstat3 stat) {
-
- int ll = GF_LOG_DEBUG;
-
- 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;
+ inode_q = (struct inode_op_queue *)(long)ctxaddr;
+ if (!inode_q)
+ goto out;
- default:
- ll = GF_LOG_DEBUG;
- break;
+ pthread_mutex_lock (&inode_q->qlock);
+ {
+ nfs3_flush_inode_queue (inode_q, openedfd);
}
+ pthread_mutex_unlock (&inode_q->qlock);
- return ll;
+out:
+ return 0;
}
int
-nfs3_write_loglevel (nfsstat3 stat) {
-
- int ll = GF_LOG_DEBUG;
-
- 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;
+__nfs3_fdcache_update_entry (struct nfs3_state *nfs3, fd_t *fd)
+{
+ uint64_t ctxaddr = 0;
+ struct nfs3_fd_entry *fde = NULL;
- case NFS3ERR_DQUOT:
- ll = GF_LOG_WARNING;
- break;
+ if ((!nfs3) || (!fd))
+ return -1;
- default:
- ll = GF_LOG_DEBUG;
- break;
+ 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;
+ if (fde) {
+ list_del (&fde->list);
+ list_add_tail (&fde->list, &nfs3->fdlru);
}
- return ll;
+ return 0;
}
int
-nfs3_create_loglevel (nfsstat3 stat) {
-
- int ll = GF_LOG_DEBUG;
-
- 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_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;
+nfs3_fdcache_update (struct nfs3_state *nfs3, fd_t *fd)
+{
+ if ((!nfs3) || (!fd))
+ return -1;
- default:
- ll = GF_LOG_DEBUG;
- break;
+ LOCK (&nfs3->fdlrulock);
+ {
+ __nfs3_fdcache_update_entry (nfs3, fd);
}
+ UNLOCK (&nfs3->fdlrulock);
- return ll;
+ return 0;
}
int
-nfs3_mkdir_loglevel (nfsstat3 stat) {
-
- int ll = GF_LOG_DEBUG;
-
- switch (stat) {
-
- case NFS3ERR_NOENT:
- 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_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;
+__nfs3_fdcache_remove_entry (struct nfs3_state *nfs3, struct nfs3_fd_entry *fde)
+{
+ if ((!fde) || (!nfs3))
+ return 0;
- default:
- ll = GF_LOG_DEBUG;
- break;
- }
+ 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;
- return ll;
+ return 0;
}
int
-nfs3_symlink_loglevel (nfsstat3 stat) {
-
- 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_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;
+nfs3_fdcache_remove (struct nfs3_state *nfs3, fd_t *fd)
+{
+ struct nfs3_fd_entry *fde = NULL;
+ uint64_t ctxaddr = 0;
- case NFS3ERR_DQUOT:
- ll = GF_LOG_WARNING;
- break;
+ if ((!nfs3) || (!fd))
+ return -1;
- default:
- ll = GF_LOG_DEBUG;
- 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);
- return ll;
+ return 0;
}
int
-nfs3_mknod_loglevel (nfsstat3 stat) {
-
- int ll = GF_LOG_DEBUG;
-
- switch (stat) {
-
- case NFS3ERR_NOENT:
- 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;
+__nfs3_fdcache_replace (struct nfs3_state *nfs3)
+{
+ struct nfs3_fd_entry *fde = NULL;
+ struct nfs3_fd_entry *tmp = NULL;
- case NFS3ERR_NOTDIR:
- ll = GF_LOG_WARNING;
- break;
+ if (!nfs3)
+ return -1;
- case NFS3ERR_ISDIR:
- ll = GF_LOG_WARNING;
- break;
+ if (nfs3->fdcount <= GF_NFS3_FDCACHE_SIZE)
+ return 0;
- case NFS3ERR_INVAL:
- ll = GF_LOG_WARNING;
+ list_for_each_entry_safe (fde, tmp, &nfs3->fdlru, list)
break;
- case NFS3ERR_FBIG:
- ll = GF_LOG_WARNING;
- break;
+ __nfs3_fdcache_remove_entry (nfs3, fde);
- case NFS3ERR_MLINK:
- ll = GF_LOG_WARNING;
- break;
+ return 0;
+}
- case NFS3ERR_NOTEMPTY:
- ll = GF_LOG_WARNING;
- break;
- case NFS3ERR_SERVERFAULT:
- ll = GF_LOG_WARNING;
- break;
- case NFS3ERR_NOTSUPP:
- ll = GF_LOG_WARNING;
- break;
+int
+nfs3_fdcache_add (struct nfs3_state *nfs3, fd_t *fd)
+{
+ struct nfs3_fd_entry *fde = NULL;
+ int ret = -1;
- case NFS3ERR_BADHANDLE:
- ll = GF_LOG_WARNING;
- break;
+ if ((!nfs3) || (!fd))
+ return -1;
- case NFS3ERR_STALE:
- 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;
+ }
- default:
- ll = GF_LOG_DEBUG;
- 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);
- return ll;
+out:
+ return ret;
}
-int
-nfs3_remove_loglevel (nfsstat3 stat) {
-
- int ll = GF_LOG_DEBUG;
-
- switch (stat) {
- 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_INVAL:
- ll = GF_LOG_WARNING;
- break;
-
- case NFS3ERR_NOSPC:
- ll = GF_LOG_WARNING;
- break;
-
- case NFS3ERR_FBIG:
- ll = GF_LOG_WARNING;
- break;
-
- 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;
+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;
- default:
- ll = GF_LOG_DEBUG;
- break;
+ cs = frame->local;
+ if (op_ret == -1) {
+ gf_log (GF_NFS3, GF_LOG_TRACE, "Opening uncached fd failed: "
+ "%s", strerror(op_errno));
+ 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);
}
- return ll;
+ nfs3 = nfs_rpcsvc_request_program_private (cs->req);
+ /* Call states are flushed even when the opening of the file failed.
+ * This allows returning an error for each one of the file io requests
+ * that are currently queued waiting for the open to succeed.
+ */
+ nfs3_flush_open_wait_call_states (cs, fd);
+ if (fd)
+ nfs3_fdcache_add (nfs3, fd);
+ return 0;
}
-int
-nfs3_rmdir_loglevel (nfsstat3 stat) {
-
- int ll = GF_LOG_DEBUG;
-
- switch (stat) {
-
- 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_INVAL:
- ll = GF_LOG_WARNING;
- break;
-
- case NFS3ERR_NOSPC:
- ll = GF_LOG_WARNING;
- break;
-
- case NFS3ERR_FBIG:
- ll = GF_LOG_WARNING;
- break;
+struct inode_op_queue *
+__nfs3_get_inode_queue (nfs3_call_state_t *cs)
+{
+ struct inode_op_queue *inode_q = NULL;
+ int ret = -1;
+ uint64_t ctxaddr = 0;
- case NFS3ERR_MLINK:
- ll = GF_LOG_WARNING;
- break;
+ ret = __inode_ctx_get (cs->resolvedloc.inode, cs->nfsx, &ctxaddr);
+ if (ret == 0) {
+ inode_q = (struct inode_op_queue *)(long)ctxaddr;
+ gf_log (GF_NFS3, GF_LOG_TRACE, "Inode queue already inited");
+ goto err;
+ }
- case NFS3ERR_SERVERFAULT:
- ll = GF_LOG_WARNING;
- break;
+ inode_q = GF_CALLOC (1, sizeof (*inode_q), gf_nfs_mt_inode_q);
+ if (!inode_q) {
+ gf_log (GF_NFS3, GF_LOG_ERROR, "Memory allocation failed");
+ goto err;
+ }
- case NFS3ERR_NOTSUPP:
- ll = GF_LOG_WARNING;
- break;
+ gf_log (GF_NFS3, GF_LOG_TRACE, "Initing inode queue");
+ INIT_LIST_HEAD (&inode_q->opq);
+ pthread_mutex_init (&inode_q->qlock, NULL);
+ __inode_ctx_put (cs->resolvedloc.inode, cs->nfsx, (uintptr_t)inode_q);
- case NFS3ERR_BADHANDLE:
- ll = GF_LOG_WARNING;
- break;
+err:
+ return inode_q;
+}
- case NFS3ERR_STALE:
- ll = GF_LOG_WARNING;
- break;
- case NFS3ERR_DQUOT:
- ll = GF_LOG_WARNING;
- break;
+struct inode_op_queue *
+nfs3_get_inode_queue (nfs3_call_state_t *cs)
+{
+ struct inode_op_queue *inode_q = NULL;
- default:
- ll = GF_LOG_DEBUG;
- break;
+ LOCK (&cs->resolvedloc.inode->lock);
+ {
+ inode_q = __nfs3_get_inode_queue (cs);
}
+ UNLOCK (&cs->resolvedloc.inode->lock);
- return ll;
+ return inode_q;
}
-int
-nfs3_rename_loglevel (nfsstat3 stat) {
-
- 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_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_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;
+#define GF_NFS3_FD_OPEN_INPROGRESS 1
+#define GF_NFS3_FD_NEEDS_OPEN 0
- case NFS3ERR_NOTSUPP:
- ll = GF_LOG_WARNING;
- break;
- case NFS3ERR_BADHANDLE:
- ll = GF_LOG_WARNING;
- break;
+int
+__nfs3_queue_call_state (struct inode_op_queue *inode_q, nfs3_call_state_t *cs)
+{
+ int ret = -1;
- case NFS3ERR_STALE:
- ll = GF_LOG_WARNING;
- break;
+ if (!inode_q)
+ goto err;
- case NFS3ERR_DQUOT:
- ll = GF_LOG_WARNING;
- break;
+ pthread_mutex_lock (&inode_q->qlock);
+ {
+ if (list_empty (&inode_q->opq)) {
+ gf_log (GF_NFS3, GF_LOG_TRACE, "First call in queue");
+ ret = GF_NFS3_FD_NEEDS_OPEN;
+ } else
+ ret = GF_NFS3_FD_OPEN_INPROGRESS;
- default:
- ll = GF_LOG_DEBUG;
- break;
+ gf_log (GF_NFS3, GF_LOG_TRACE, "Queueing call state");
+ list_add_tail (&cs->openwait_q, &inode_q->opq);
}
+ pthread_mutex_unlock (&inode_q->qlock);
- return ll;
+err:
+ return ret;
}
+/* Returns GF_NFS3_FD_NEEDS_OPEN 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 and
+ * GF_NFS3_FD_OPEN_INPROGRESS is returned.
+ *
+ * Returns -1 on error.
+ */
int
-nfs3_link_loglevel (nfsstat3 stat) {
-
- 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;
-
- 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_queue_call_state (nfs3_call_state_t *cs)
+{
+ struct inode_op_queue *inode_q = NULL;
+ int ret = -1;
- default:
- ll = GF_LOG_DEBUG;
- break;
+ inode_q = nfs3_get_inode_queue (cs);
+ if (!inode_q) {
+ gf_log (GF_NFS3, GF_LOG_ERROR, "Failed to get inode op queue");
+ goto err;
}
- return ll;
+ ret = __nfs3_queue_call_state (inode_q, cs);
+
+err:
+ return ret;
}
int
-nfs3_readdir_loglevel (nfsstat3 stat) {
-
- int ll = GF_LOG_DEBUG;
-
- 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;
+__nfs3_file_open_and_resume (nfs3_call_state_t *cs)
+{
+ nfs_user_t nfu = {0, };
+ int ret = -EFAULT;
- case NFS3ERR_DQUOT:
- ll = GF_LOG_WARNING;
- break;
+ if (!cs)
+ return ret;
- default:
- ll = GF_LOG_DEBUG;
- break;
+ ret = nfs3_queue_call_state (cs);
+ if (ret == -1) {
+ gf_log (GF_NFS3, GF_LOG_ERROR, "Error queueing call state");
+ ret = -EFAULT;
+ goto out;
+ } else if (ret == GF_NFS3_FD_OPEN_INPROGRESS) {
+ gf_log (GF_NFS3, GF_LOG_TRACE, "Open in progress. Will wait.");
+ ret = 0;
+ goto out;
}
- return ll;
+ 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;
}
-int
-nfs3_fsstat_loglevel (nfsstat3 stat) {
-
- int ll = GF_LOG_DEBUG;
-
- switch (stat) {
-
- case NFS3ERR_PERM:
- ll = GF_LOG_WARNING;
- break;
-
- case NFS3ERR_NOENT:
- ll = GF_LOG_WARNING;
- break;
-
- case NFS3ERR_ACCES:
- 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;
+fd_t *
+nfs3_fdcache_getfd (struct nfs3_state *nfs3, inode_t *inode)
+{
+ fd_t *fd = NULL;
- case NFS3ERR_ISDIR:
- ll = GF_LOG_WARNING;
- break;
+ if ((!nfs3) || (!inode))
+ return NULL;
- case NFS3ERR_INVAL:
- ll = GF_LOG_WARNING;
- break;
+ fd = fd_lookup (inode, 0);
+ if (fd) {
+ /* 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);
+ } else
+ gf_log (GF_NFS3, GF_LOG_TRACE, "fd not found in state");
- case NFS3ERR_NOSPC:
- ll = GF_LOG_WARNING;
- break;
+ return fd;
+}
- case NFS3ERR_ROFS:
- ll = GF_LOG_WARNING;
- break;
- case NFS3ERR_FBIG:
- ll = GF_LOG_WARNING;
- break;
- case NFS3ERR_MLINK:
- 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;
- case NFS3ERR_NAMETOOLONG:
- ll = GF_LOG_WARNING;
- break;
+ if (!cs)
+ return ret;
- case NFS3ERR_NOTEMPTY:
- ll = GF_LOG_WARNING;
- break;
+ cs->resume_fn = resume;
+ gf_log (GF_NFS3, GF_LOG_TRACE, "Opening: %s", cs->resolvedloc.path);
+ fd = nfs3_fdcache_getfd (cs->nfs3state, cs->resolvedloc.inode);
+ if (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_SERVERFAULT:
- ll = GF_LOG_WARNING;
- break;
+ ret = __nfs3_file_open_and_resume (cs);
- case NFS3ERR_NOTSUPP:
- ll = GF_LOG_WARNING;
- break;
+err:
+ return ret;
+}
- case NFS3ERR_BADHANDLE:
- ll = GF_LOG_WARNING;
- break;
- case NFS3ERR_STALE:
- 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_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;
- }
+void
+nfs3_log_common_call (uint32_t xid, char *op, struct nfs3_fh *fh)
+{
+ char fhstr[1024];
- return ll;
+ nfs3_fh_to_str (fh, fhstr);
+ gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, %s: args: %s", xid, op,
+ fhstr);
}
-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_loglevel (int nfs_op, nfsstat3 stat) {
+void
+nfs3_log_fh_entry_call (uint32_t xid, char *op, struct nfs3_fh *fh,
+ char *name)
+{
+ 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, name: %s", xid,
+ op, fhstr, name);
+}
- switch (nfs_op) {
- case NFS3_GETATTR:
- ll = nfs3_getattr_loglevel (stat);
- break;
- case NFS3_SETATTR:
- ll = nfs3_setattr_loglevel (stat);
- 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 NFS3_LOOKUP:
- ll = nfs3_lookup_loglevel (stat);
- 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 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;
+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 NFS3_WRITE:
- ll = nfs3_write_loglevel (stat);
- break;
+ nfs3_fh_to_str (fh, fhstr);
+ if (mode == EXCLUSIVE)
+ modestr = exclmode;
+ else if (mode == GUARDED)
+ modestr = guarded;
+ else
+ modestr = unchkd;
- case NFS3_CREATE:
- ll = nfs3_create_loglevel (stat);
- break;
+ gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, CREATE: args: %s, name: %s,"
+ " mode: %s", xid, fhstr, name, modestr);
+}
- case NFS3_MKDIR:
- ll = nfs3_mkdir_loglevel (stat);
- break;
- case NFS3_SYMLINK:
- ll = nfs3_symlink_loglevel (stat);
- 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 NFS3_MKNOD:
- ll = nfs3_mknod_loglevel (stat);
- 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 NFS3_REMOVE:
- ll = nfs3_remove_loglevel (stat);
- break;
+ gf_log (GF_NFS3, GF_LOG_DEBUG, "XID: %x, MKNOD: args: %s, name: %s,"
+ " type: %s", xid, fhstr, name, modestr);
+}
- 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;
+void
+nfs3_log_symlink_call (uint32_t xid, struct nfs3_fh *fh, char *name, char *tgt)
+{
+ char fhstr[1024];
- case NFS3_READDIR:
- ll = nfs3_readdir_loglevel (stat);
- 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 NFS3_READDIRP:
- ll = nfs3_readdir_loglevel (stat);
- break;
- case NFS3_FSSTAT:
- ll = nfs3_fsstat_loglevel (stat);
- 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 NFS3_FSINFO:
- ll = nfs3_fsstat_loglevel (stat);
- 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 NFS3_PATHCONF:
- ll = nfs3_fsstat_loglevel (stat);
- break;
- case NFS3_COMMIT:
- ll = nfs3_write_loglevel (stat);
- break;
+void
+nfs3_log_rw_call (uint32_t xid, char *op, struct nfs3_fh *fh, offset3 offt,
+ count3 count, int stablewrite)
+{
+ char fhstr[1024];
- default:
- ll = GF_LOG_DEBUG;
- 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");
- return ll;
}
+
void
-nfs3_log_common_res (uint32_t xid, int op, nfsstat3 stat, int pstat)
+nfs3_log_common_res (uint32_t xid, char *op, nfsstat3 stat, int pstat)
{
char errstr[1024];
- int ll = nfs3_loglevel (op, stat);
- if (gf_log_loglevel < ll)
- return;
- nfs3_stat_to_errstr (xid, nfs3op_strings[op].str, stat, pstat, errstr);
- gf_log (GF_NFS3, ll, "%s", errstr);
+ nfs3_stat_to_errstr (xid, op, stat, pstat, errstr);
+ gf_log (GF_NFS3, GF_LOG_DEBUG, "%s", errstr);
}
void
nfs3_log_readlink_res (uint32_t xid, nfsstat3 stat, int pstat, char *linkpath)
{
char errstr[1024];
- int ll = nfs3_loglevel (NFS3_READLINK, stat);
-
- if (gf_log_loglevel < ll)
- return;
nfs3_stat_to_errstr (xid, "READLINK", stat, pstat, errstr);
- gf_log (GF_NFS3, ll, "%s, target: %s",
- errstr, linkpath);
+ gf_log (GF_NFS3, GF_LOG_DEBUG, "%s, target: %s", errstr, linkpath);
}
@@ -3409,18 +2439,14 @@ nfs3_log_read_res (uint32_t xid, nfsstat3 stat, int pstat, count3 count,
int is_eof, struct iovec *vec, int32_t veccount)
{
char errstr[1024];
- int ll = GF_LOG_DEBUG;
- ll = nfs3_loglevel (NFS3_READ, stat);
- if (gf_log_loglevel < ll)
- return;
nfs3_stat_to_errstr (xid, "READ", stat, pstat, errstr);
if (vec)
- gf_log (GF_NFS3, ll, "%s, count: %"PRIu32", is_eof:"
+ 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, ll, "%s, count: %"PRIu32", is_eof:"
+ gf_log (GF_NFS3, GF_LOG_DEBUG, "%s, count: %"PRIu32", is_eof:"
" %d", errstr, count, is_eof);
}
@@ -3430,32 +2456,25 @@ nfs3_log_write_res (uint32_t xid, nfsstat3 stat, int pstat, count3 count,
int stable, uint64_t wverf)
{
char errstr[1024];
- int ll = nfs3_loglevel (NFS3_WRITE, stat);
-
- if (gf_log_loglevel < ll)
- return;
nfs3_stat_to_errstr (xid, "WRITE", stat, pstat, errstr);
- gf_log (GF_NFS3, ll, "%s, count: %"PRIu32", %s,wverf: %"PRIu64
+ gf_log (GF_NFS3, GF_LOG_DEBUG, "%s, count: %"PRIu32", %s,wverf: %"PRIu64
, errstr, count, (stable == UNSTABLE)?"UNSTABLE":"STABLE",
wverf);
}
void
-nfs3_log_newfh_res (uint32_t xid, int op, nfsstat3 stat, int pstat,
+nfs3_log_newfh_res (uint32_t xid, char *op, nfsstat3 stat, int pstat,
struct nfs3_fh *newfh)
{
char errstr[1024];
char fhstr[1024];
- int ll = nfs3_loglevel (op, stat);
- if (gf_log_loglevel < ll)
- return;
- nfs3_stat_to_errstr (xid, nfs3op_strings[op].str, stat, pstat, errstr);
+ nfs3_stat_to_errstr (xid, op, stat, pstat, errstr);
nfs3_fh_to_str (newfh, fhstr);
- gf_log (GF_NFS3, nfs3_loglevel (op, stat), "%s, %s", errstr, fhstr);
+ gf_log (GF_NFS3, GF_LOG_DEBUG, "%s, %s", errstr, fhstr);
}
@@ -3464,12 +2483,9 @@ nfs3_log_readdir_res (uint32_t xid, nfsstat3 stat, int pstat, uint64_t cverf,
count3 count, int is_eof)
{
char errstr[1024];
- int ll = nfs3_loglevel (NFS3_READDIR, stat);
- if (gf_log_loglevel < ll)
- return;
nfs3_stat_to_errstr (xid, "READDIR", stat, pstat, errstr);
- gf_log (GF_NFS3, ll, "%s, count: %"PRIu32", cverf: %"PRIu64
+ gf_log (GF_NFS3, GF_LOG_DEBUG, "%s, count: %"PRIu32", cverf: %"PRIu64
", is_eof: %d", errstr, count, cverf, is_eof);
}
@@ -3479,12 +2495,9 @@ nfs3_log_readdirp_res (uint32_t xid, nfsstat3 stat, int pstat, uint64_t cverf,
count3 dircount, count3 maxcount, int is_eof)
{
char errstr[1024];
- int ll = nfs3_loglevel (NFS3_READDIRP, stat);
- if (gf_log_loglevel < ll)
- return;
nfs3_stat_to_errstr (xid, "READDIRPLUS", stat, pstat, errstr);
- gf_log (GF_NFS3, ll, "%s, dircount: %"PRIu32", maxcount: %"
+ gf_log (GF_NFS3, GF_LOG_DEBUG, "%s, dircount: %"PRIu32", maxcount: %"
PRIu32", cverf: %"PRIu64", is_eof: %d", errstr, dircount,
maxcount, cverf, is_eof);
}
@@ -3494,12 +2507,9 @@ void
nfs3_log_commit_res (uint32_t xid, nfsstat3 stat, int pstat, uint64_t wverf)
{
char errstr[1024];
- int ll = nfs3_loglevel (NFS3_COMMIT, stat);
- if (gf_log_loglevel < ll)
- return;
nfs3_stat_to_errstr (xid, "COMMIT", stat, pstat, errstr);
- gf_log (GF_NFS3, ll, "%s, wverf: %"PRIu64, errstr, wverf);
+ gf_log (GF_NFS3, GF_LOG_DEBUG, "%s, wverf: %"PRIu64, errstr, wverf);
}
@@ -3509,9 +2519,6 @@ nfs3_log_readdir_call (uint32_t xid, struct nfs3_fh *fh, count3 dircount,
{
char fhstr[1024];
- if (gf_log_loglevel < GF_LOG_DEBUG)
- return;
-
nfs3_fh_to_str (fh, fhstr);
if (maxcount == 0)
@@ -3533,11 +2540,9 @@ nfs3_fh_resolve_inode_done (nfs3_call_state_t *cs, inode_t *inode)
return ret;
gf_log (GF_NFS3, GF_LOG_TRACE, "FH inode resolved");
- ret = nfs_inode_loc_fill (inode, &cs->resolvedloc, NFS_RESOLVE_EXIST);
- if (ret < 0) {
- gf_log (GF_NFS3, GF_LOG_ERROR, "inode loc fill failed");
+ ret = nfs_inode_loc_fill (inode, &cs->resolvedloc);
+ if (ret < 0)
goto err;
- }
nfs3_call_resume (cs);
@@ -3545,6 +2550,55 @@ err:
return ret;
}
+#define GF_NFS3_FHRESOLVE_FOUND 1
+#define GF_NFS3_FHRESOLVE_NOTFOUND 2
+#define GF_NFS3_FHRESOLVE_DIRFOUND 3
+
+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 ((uuid_compare (candidate->d_stat.ia_gfid, fh->gfid)) == 0) {
+ gf_log (GF_NFS3, GF_LOG_TRACE, "Found entry: gfid: %s, "
+ "name: %s, hashcount %d",
+ uuid_utoa (candidate->d_stat.ia_gfid),
+ candidate->d_name, hashidx);
+ ret = GF_NFS3_FHRESOLVE_FOUND;
+ goto found_entry;
+ }
+
+ /* 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_gfid)) {
+ gf_log (GF_NFS3, GF_LOG_TRACE, "Found hash match: %s: %d, "
+ "hashidx: %d", candidate->d_name, entryhash, hashidx);
+ ret = GF_NFS3_FHRESOLVE_DIRFOUND;
+ goto found_entry;
+ }
+
+found_entry:
+
+ return ret;
+}
+
int32_t
nfs3_fh_resolve_entry_lookup_cbk (call_frame_t *frame, void *cookie,
@@ -3561,16 +2615,13 @@ nfs3_fh_resolve_entry_lookup_cbk (call_frame_t *frame, void *cookie,
cs->resolve_errno = op_errno;
if (op_ret == -1) {
- gf_log (GF_NFS3, (op_errno == ENOENT ? GF_LOG_TRACE : GF_LOG_ERROR),
- "Lookup failed: %s: %s",
+ 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);
- 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) {
@@ -3583,8 +2634,44 @@ err:
}
+
+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);
+
+int
+nfs3_fh_resolve_found_entry (nfs3_call_state_t *cs, gf_dirent_t *candidate)
+{
+ int ret = 0;
+ nfs_user_t nfu = {0, };
+ uuid_t gfid = {0, };
+
+ if ((!cs) || (!candidate))
+ return -EFAULT;
+
+ uuid_copy (gfid, cs->resolvedloc.inode->gfid);
+ nfs_loc_wipe (&cs->resolvedloc);
+ ret = nfs_entry_loc_fill (cs->vol->itable, gfid, 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);
+ }
+
+ return ret;
+}
+
+
int32_t
-nfs3_fh_resolve_inode_lookup_cbk (call_frame_t *frame, void *cookie,
+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,
@@ -3598,37 +2685,332 @@ nfs3_fh_resolve_inode_lookup_cbk (call_frame_t *frame, void *cookie,
cs->resolve_errno = op_errno;
if (op_ret == -1) {
- gf_log (GF_NFS3, (op_errno == ENOENT ? GF_LOG_TRACE : GF_LOG_ERROR),
- "Lookup failed: %s: %s",
+ 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);
- 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) {
inode_lookup (linked_inode);
- inode_unref (cs->resolvedloc.inode);
- cs->resolvedloc.inode = linked_inode;
+ inode_unref (linked_inode);
}
+ nfs3_fh_resolve_entry_hard (cs);
- /* 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)
+err:
+ return 0;
+}
+
+
+int
+nfs3_fh_resolve_found_parent (nfs3_call_state_t *cs, gf_dirent_t *candidate)
+{
+ int ret = 0;
+ nfs_user_t nfu = {0, };
+ uuid_t gfid = {0, };
+
+ if ((!cs) || (!candidate))
+ return -EFAULT;
+
+ uuid_copy (gfid, cs->resolvedloc.inode->gfid);
+ nfs_loc_wipe (&cs->resolvedloc);
+ ret = nfs_entry_loc_fill (cs->vol->itable, gfid, 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);
- else
- nfs3_call_resume (cs);
+
+ return ret;
+}
+
+
+int
+nfs3_fh_resolve_found (nfs3_call_state_t *cs, gf_dirent_t *candidate)
+{
+ int ret = 0;
+
+ if ((!cs) || (!candidate))
+ return -EFAULT;
+
+ 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);
+ }
+
+ return ret;
+}
+
+
+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);
+
+ nfs_user_root_create (&nfu);
+ /* Keep this directory fd_t around till we have either:
+ * a. found the entry,
+ * b. exhausted all the entries,
+ * c. decide to step into a child directory.
+ *
+ * This decision is made in nfs3_fh_resolve_check_response.
+ */
+ cs->resolve_dir_fd = fd;
+ gf_log (GF_NFS3, GF_LOG_TRACE, "resolve new fd refed: 0x%lx, ref: %d",
+ (long)cs->resolve_dir_fd, cs->resolve_dir_fd->refcount);
+ ret = nfs_readdirp (cs->nfsx, cs->vol, &nfu, fd, GF_NFS3_DTPREF, 0,
+ nfs3_fh_resolve_readdir_cbk, cs);
+
err:
+ return ret;
+}
+
+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)
+{
+ nfs3_call_state_t *cs = NULL;
+ nfs_user_t nfu = {0, };
+ inode_t *linked_inode = 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, "Dir will be opened: %s",
+ cs->resolvedloc.path);
+
+ nfs_user_root_create (&nfu);
+ linked_inode = inode_link (inode, cs->resolvedloc.parent,
+ cs->resolvedloc.name, buf);
+ if (linked_inode) {
+ inode_lookup (linked_inode);
+ inode_unref (linked_inode);
+ }
+
+ nfs_opendir (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
+ nfs3_fh_resolve_opendir_cbk, cs);
+
+err:
+ return 0;
+}
+
+
+/* Validate the depth of the dir such that we do not end up opening and
+ * reading directories beyond those that are needed for resolving the file
+ * handle.
+ * Returns 1 if fh resolution can continue, 0 otherwise.
+ */
+int
+nfs3_fh_resolve_validate_dirdepth (nfs3_call_state_t *cs)
+{
+ int ret = 1;
+
+ if (!cs)
+ return 0;
+
+ /* This condition will generally never be hit because the
+ * hash-matching scheme will prevent us from going into a
+ * directory that is not part of the hash-array.
+ */
+ 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);
+ ret = 0;
+ goto out;
+ }
+
+ if (cs->hashidx >= GF_NFSFH_MAXHASHES) {
+ gf_log (GF_NFS3, GF_LOG_TRACE, "Hash index beyond max hashes:"
+ " hashidx %d, max: %d", cs->hashidx,
+ GF_NFSFH_MAXHASHES);
+ ret = 0;
+ goto out;
+ }
+
+out:
+ return ret;
+}
+
+
+int
+nfs3_fh_resolve_dir_hard (nfs3_call_state_t *cs, uuid_t dirgfid, char *entry)
+{
+ int ret = -EFAULT;
+ nfs_user_t nfu = {0, };
+
+ if (!cs)
+ return ret;
+
+ cs->hashidx++;
+ nfs_loc_wipe (&cs->resolvedloc);
+ if (!nfs3_fh_resolve_validate_dirdepth (cs)) {
+ gf_log (GF_NFS3, GF_LOG_TRACE, "Dir depth validation failed");
+ nfs3_call_resume_estale (cs);
+ ret = 0;
+ goto out;
+ }
+
+ nfs_user_root_create (&nfu);
+ gf_log (GF_NFS3, GF_LOG_TRACE, "FH hard dir resolution: gfid: %s, "
+ "entry: %s, next hashcount: %d", uuid_utoa (dirgfid), entry,
+ cs->hashidx);
+ ret = nfs_entry_loc_fill (cs->vol->itable, dirgfid, 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;
+}
+
+
+/*
+ * Called in a recursive code path, so if another
+ * directory was opened in an earlier call during fh resolution, we must unref
+ * through this reference before opening another fd_t.
+ */
+#define nfs3_fh_resolve_close_cwd(cst) \
+ do { \
+ if ((cst)->resolve_dir_fd) { \
+ gf_log (GF_NFS3, GF_LOG_TRACE, "resolve fd " \
+ "unrefing: 0x%lx, ref: %d", \
+ (long)(cst)->resolve_dir_fd, \
+ (cst)->resolve_dir_fd->refcount); \
+ fd_unref ((cst)->resolve_dir_fd); \
+ } \
+ } while (0) \
+
+
+int
+nfs3_fh_resolve_check_response (nfs3_call_state_t *cs, gf_dirent_t *candidate,
+ int response, off_t last_offt)
+{
+ int ret = -EFAULT;
+ nfs_user_t nfu = {0, };
+
+ if (!cs)
+ return ret;
+
+ switch (response) {
+
+ case GF_NFS3_FHRESOLVE_DIRFOUND:
+ nfs3_fh_resolve_close_cwd (cs);
+ nfs3_fh_resolve_dir_hard (cs, cs->resolvedloc.inode->gfid,
+ candidate->d_name);
+ break;
+
+ case GF_NFS3_FHRESOLVE_FOUND:
+ nfs3_fh_resolve_close_cwd (cs);
+ nfs3_fh_resolve_found (cs, candidate);
+ break;
+
+ case GF_NFS3_FHRESOLVE_NOTFOUND:
+ nfs_user_root_create (&nfu);
+ nfs_readdirp (cs->nfsx, cs->vol, &nfu, cs->resolve_dir_fd,
+ GF_NFS3_DTPREF, last_offt,
+ nfs3_fh_resolve_readdir_cbk, cs);
+ break;
+ }
+
return 0;
}
+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, gfid: %s",
+ candidate->d_name,
+ uuid_utoa (candidate->d_stat.ia_gfid));
+ ret = nfs3_fh_resolve_check_entry (&cs->resolvefh, candidate,
+ cs->hashidx);
+ if (ret != GF_NFS3_FHRESOLVE_NOTFOUND)
+ break;
+ }
+
+not_found:
+ nfs3_fh_resolve_check_response (cs, candidate, ret, lastoff);
+ 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 = ESTALE;
+ nfs3_call_resume (cs);
+ goto err;
+ }
+
+ nfs3_fh_resolve_search_dir (cs, entries);
+err:
+ 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.
@@ -3642,21 +3024,33 @@ nfs3_fh_resolve_inode_hard (nfs3_call_state_t *cs)
if (!cs)
return ret;
- gf_log (GF_NFS3, GF_LOG_TRACE, "FH hard resolution for: gfid 0x%s",
- uuid_utoa (cs->resolvefh.gfid));
- cs->hardresolved = 1;
+ cs->hashidx++;
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_log (GF_NFS3, GF_LOG_ERROR, "Failed to fill loc using gfid: "
- "%s", strerror (-ret));
+ if (!nfs3_fh_resolve_validate_dirdepth (cs)) {
+ gf_log (GF_NFS3, GF_LOG_TRACE, "Dir depth validation failed");
+ nfs3_call_resume_estale (cs);
+ ret = 0;
goto out;
}
nfs_user_root_create (&nfu);
- ret = nfs_lookup (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
- nfs3_fh_resolve_inode_lookup_cbk, cs);
+ gf_log (GF_NFS3, GF_LOG_TRACE, "FH hard resolution for: gfid 0x%s"
+ ", hashcount: %d, current hashidx %d",
+ uuid_utoa (cs->resolvefh.gfid),
+ cs->resolvefh.hashcount, cs->hashidx);
+ ret = nfs_root_loc_fill (cs->vol->itable, &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);
+ }
out:
return ret;
@@ -3675,8 +3069,8 @@ nfs3_fh_resolve_entry_hard (nfs3_call_state_t *cs)
nfs_loc_wipe (&cs->resolvedloc);
nfs_user_root_create (&nfu);
gf_log (GF_NFS3, GF_LOG_TRACE, "FH hard resolution: gfid: %s "
- ", entry: %s", uuid_utoa (cs->resolvefh.gfid),
- cs->resolventry);
+ ", entry: %s, hashidx: %d", uuid_utoa (cs->resolvefh.gfid),
+ cs->resolventry, cs->hashidx);
ret = nfs_entry_loc_fill (cs->vol->itable, cs->resolvefh.gfid,
cs->resolventry, &cs->resolvedloc,
@@ -3685,22 +3079,13 @@ nfs3_fh_resolve_entry_hard (nfs3_call_state_t *cs)
if (ret == -2) {
gf_log (GF_NFS3, GF_LOG_TRACE, "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 (nfs3_lookup_op (cs) ||
- (nfs3_create_op (cs) && !nfs3_create_exclusive_op (cs))) {
+ if (nfs3_lookup_op (cs)) {
cs->lookuptype = GF_NFS3_FRESH;
cs->resolve_ret = 0;
nfs3_call_resume (cs);
- } else {
- cs->hardresolved = 1;
+ } else
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",
@@ -3724,7 +3109,6 @@ nfs3_fh_resolve_inode (nfs3_call_state_t *cs)
return ret;
gf_log (GF_NFS3, GF_LOG_TRACE, "FH needs inode resolution");
- uuid_copy (cs->resolvedloc.gfid, cs->resolvefh.gfid);
inode = inode_find (cs->vol->itable, cs->resolvefh.gfid);
if (!inode)
ret = nfs3_fh_resolve_inode_hard (cs);
@@ -3791,7 +3175,7 @@ nfs3_fh_resolve_root_lookup_cbk (call_frame_t *frame, void *cookie,
cs->resolve_errno = op_errno;
if (op_ret == -1) {
- gf_log (GF_NFS3, GF_LOG_ERROR, "Root lookup failed: %s",
+ gf_log (GF_NFS3, GF_LOG_TRACE, "Root lookup failed: %s",
strerror (op_errno));
goto err;
} else
@@ -3822,11 +3206,6 @@ nfs3_fh_resolve_root (nfs3_call_state_t *cs)
nfs_user_root_create (&nfu);
gf_log (GF_NFS3, GF_LOG_TRACE, "Root needs lookup");
ret = nfs_root_loc_fill (cs->vol->itable, &cs->resolvedloc);
- if (ret < 0) {
- gf_log (GF_NFS3, GF_LOG_ERROR, "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);