summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xlators/nfs/server/src/nfs3-helpers.c82
-rw-r--r--xlators/nfs/server/src/nfs3-helpers.h9
-rw-r--r--xlators/nfs/server/src/nfs3.c44
3 files changed, 96 insertions, 39 deletions
diff --git a/xlators/nfs/server/src/nfs3-helpers.c b/xlators/nfs/server/src/nfs3-helpers.c
index feab7b5e8be..95e8601627d 100644
--- a/xlators/nfs/server/src/nfs3-helpers.c
+++ b/xlators/nfs/server/src/nfs3-helpers.c
@@ -702,11 +702,64 @@ nfs3_prep_readdir3args (readdir3args *ra, struct nfs3_fh *fh)
}
+int
+nfs3_is_dot_entry (char *entry)
+{
+ int ret = 0;
+
+ if (!entry)
+ return 0;
+
+ if (strcmp (entry, ".") == 0)
+ ret = 1;
+
+ return ret;
+}
+
+
+int
+nfs3_is_parentdir_entry (char *entry)
+{
+ int ret = 0;
+
+ if (!entry)
+ return 0;
+
+ if (strcmp (entry, "..") == 0)
+ ret = 1;
+
+ return ret;
+}
+
+
+void
+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 (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;
+ }
+
+}
+
+
entry3 *
-nfs3_fill_entry3 (gf_dirent_t *entry)
+nfs3_fill_entry3 (gf_dirent_t *entry, struct nfs3_fh *dfh)
{
entry3 *ent = NULL;
- if (!entry)
+ if ((!entry) || (!dfh))
return NULL;
ent = GF_CALLOC (1, sizeof (*ent), gf_nfs_mt_entry3);
@@ -714,6 +767,14 @@ nfs3_fill_entry3 (gf_dirent_t *entry)
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),
@@ -775,6 +836,13 @@ nfs3_fill_entryp3 (gf_dirent_t *entry, struct nfs3_fh *dirfh)
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 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);
@@ -802,9 +870,9 @@ err:
void
-nfs3_fill_readdir3res (readdir3res *res, nfsstat3 stat, uint64_t cverf,
- struct iatt *dirstat, gf_dirent_t *entries, count3 count,
- int is_eof, uint16_t xlid)
+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;
@@ -818,7 +886,7 @@ nfs3_fill_readdir3res (readdir3res *res, nfsstat3 stat, uint64_t cverf,
if (stat != NFS3_OK)
return;
- nfs3_map_xlid_to_statdev (dirstat, xlid);
+ 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;
@@ -834,7 +902,7 @@ nfs3_fill_readdir3res (readdir3res *res, nfsstat3 stat, uint64_t cverf,
(strcmp (entries->d_name, "..") == 0))
goto nextentry;
*/
- ent = nfs3_fill_entry3 (entries);
+ ent = nfs3_fill_entry3 (entries, dirfh);
if (!ent)
break;
diff --git a/xlators/nfs/server/src/nfs3-helpers.h b/xlators/nfs/server/src/nfs3-helpers.h
index 26bc11f6ce2..db76b5cce77 100644
--- a/xlators/nfs/server/src/nfs3-helpers.h
+++ b/xlators/nfs/server/src/nfs3-helpers.h
@@ -111,9 +111,9 @@ extern void
nfs3_prep_readdir3args (readdir3args *ra, struct nfs3_fh *fh);
extern void
-nfs3_fill_readdir3res (readdir3res *res, nfsstat3 stat, uint64_t cverf,
- struct iatt *dirstat, gf_dirent_t *entries,count3 count,
- int is_eof, uint16_t xlid);
+nfs3_fill_readdir3res (readdir3res *res, nfsstat3 stat, struct nfs3_fh *dfh,
+ uint64_t cverf, struct iatt *dirstat,
+ gf_dirent_t *entries, count3 count, int is_eof);
extern void
nfs3_prep_readdirp3args (readdirp3args *ra, struct nfs3_fh *fh);
@@ -339,4 +339,7 @@ nfs3_verify_dircookie (struct nfs3_state *nfs3, fd_t *dirfd, cookie3 cookie,
extern int
nfs3_fdcache_remove (struct nfs3_state *nfs3, fd_t *fd);
+
+extern int
+nfs3_is_parentdir_entry (char *entry);
#endif
diff --git a/xlators/nfs/server/src/nfs3.c b/xlators/nfs/server/src/nfs3.c
index 385a4a3747b..f09ed95d9da 100644
--- a/xlators/nfs/server/src/nfs3.c
+++ b/xlators/nfs/server/src/nfs3.c
@@ -993,21 +993,6 @@ nfs3err:
int
-nfs3_is_parentdir_entry (char *entry)
-{
- int ret = 0;
-
- if (!entry)
- return 0;
-
- if (strcmp (entry, "..") == 0)
- ret = 1;
-
- return ret;
-}
-
-
-int
nfs3_lookup (rpcsvc_request_t *req, struct nfs3_fh *fh, int fhlen, char *name)
{
xlator_t *vol = NULL;
@@ -3627,16 +3612,14 @@ nfs3_readdirp_reply (rpcsvc_request_t *req, nfsstat3 stat,struct nfs3_fh *dirfh,
int
-nfs3_readdir_reply (rpcsvc_request_t *req, nfsstat3 stat, uint64_t cverf,
- struct iatt *dirstat, gf_dirent_t *entries, count3 count,
- int is_eof)
+nfs3_readdir_reply (rpcsvc_request_t *req, nfsstat3 stat, struct nfs3_fh *dirfh,
+ uint64_t cverf, struct iatt *dirstat, gf_dirent_t *entries,
+ count3 count, int is_eof)
{
readdir3res res = {0, };
- uint16_t xlid = 0;
- xlid = nfs3_request_xlator_id (req);
- nfs3_fill_readdir3res (&res, stat, cverf, dirstat, entries, count,
- is_eof, xlid);
+ nfs3_fill_readdir3res (&res, stat, dirfh, cverf, dirstat, entries, count
+ , is_eof);
nfs3svc_submit_reply (req, (void *)&res,
(nfs3_serializer) xdr_serialize_readdir3res);
nfs3_free_readdir3res (&res);
@@ -3673,9 +3656,9 @@ nfs3err:
nfs3_log_readdir_res (rpcsvc_request_xid (cs->req), stat,
op_errno, (uintptr_t)cs->fd,
cs->dircount, is_eof);
- nfs3_readdir_reply (cs->req, stat, (uintptr_t)cs->fd,
- buf, &cs->entries, cs->dircount,
- is_eof);
+ nfs3_readdir_reply (cs->req, stat, &cs->parent,
+ (uintptr_t)cs->fd, buf, &cs->entries,
+ cs->dircount, is_eof);
} else {
nfs3_log_readdirp_res (rpcsvc_request_xid (cs->req), stat,
op_errno, (uintptr_t)cs->fd,
@@ -3730,7 +3713,7 @@ err:
if (cs->maxcount == 0) {
nfs3_log_common_res (rpcsvc_request_xid (cs->req), "READDIR",
stat, op_errno);
- nfs3_readdir_reply (cs->req, stat, 0, NULL, NULL, 0, 0);
+ nfs3_readdir_reply (cs->req, stat, NULL, 0, NULL, NULL, 0, 0);
} else {
nfs3_log_common_res (rpcsvc_request_xid (cs->req), "READDIRP"
, stat, op_errno);
@@ -3791,7 +3774,8 @@ nfs3err:
if (cs->maxcount == 0) {
nfs3_log_common_res (rpcsvc_request_xid (cs->req),
"READDIR", stat, -ret);
- nfs3_readdir_reply (cs->req, stat, 0, NULL, NULL, 0, 0);
+ nfs3_readdir_reply (cs->req, stat, NULL, 0, NULL, NULL,
+ 0, 0);
} else {
nfs3_log_common_res (rpcsvc_request_xid (cs->req),
"READDIRP", stat, -ret);
@@ -3826,7 +3810,8 @@ nfs3err:
if (cs->maxcount == 0) {
nfs3_log_common_res (rpcsvc_request_xid (cs->req),
"READDIR", stat, -ret);
- nfs3_readdir_reply (cs->req, stat, 0, NULL, NULL, 0, 0);
+ nfs3_readdir_reply (cs->req, stat, NULL, 0, NULL, NULL,
+ 0, 0);
} else {
nfs3_log_common_res (rpcsvc_request_xid (cs->req),
"READDIRP", stat, -ret);
@@ -3877,7 +3862,8 @@ nfs3err:
if (maxcount == 0) {
nfs3_log_common_res (rpcsvc_request_xid (req), "READDIR"
, stat, -ret);
- nfs3_readdir_reply (req, stat, 0, NULL, NULL, 0, 0);
+ nfs3_readdir_reply (req, stat, NULL, 0, NULL, NULL, 0,
+ 0);
} else {
nfs3_log_common_res (rpcsvc_request_xid (req),"READDIRP"
, stat, -ret);