aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2010-12-14 09:58:11 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2010-12-16 12:37:24 -0500
commit573c4e1ef53a6b891b73cc2257e1604da754a2e4 (patch)
treeb1e01ca46472ac6c936c4a144c3a160d8e1595bb
parent8111f373600cd43b3198b48b9238e3ad2fd9908d (diff)
NFS: Simplify ->decode_dirent() calling sequence
Clean up. The pointer returned by ->decode_dirent() is no longer used as a pointer. The only call site (xdr_decode() in fs/nfs/dir.c) simply extracts the errno value encoded in the pointer. Replace the returned pointer with a standard integer errno return value. Also, pass the "server" argument as part of the nfs_entry instead of as a separate parameter. It's faster to derive "server" in nfs_readdir_xdr_to_array() since we already have the directory's inode handy. "server" ought to be invariant for a set of entries in the same directory, right? The legacy versions of decode_dirent() don't use "server" anyway, so it's wasted work for them to derive and pass "server" for each entry. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Tested-by: J. Bruce Fields <bfields@redhat.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/dir.c15
-rw-r--r--fs/nfs/internal.h9
-rw-r--r--fs/nfs/nfs2xdr.c18
-rw-r--r--fs/nfs/nfs3xdr.c28
-rw-r--r--fs/nfs/nfs4_fs.h1
-rw-r--r--fs/nfs/nfs4xdr.c29
-rw-r--r--include/linux/nfs_xdr.h3
7 files changed, 61 insertions, 42 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 996dd8989a91..3e2123fe79f5 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -172,7 +172,7 @@ struct nfs_cache_array {
172 struct nfs_cache_array_entry array[0]; 172 struct nfs_cache_array_entry array[0];
173}; 173};
174 174
175typedef __be32 * (*decode_dirent_t)(struct xdr_stream *, struct nfs_entry *, struct nfs_server *, int); 175typedef int (*decode_dirent_t)(struct xdr_stream *, struct nfs_entry *, int);
176typedef struct { 176typedef struct {
177 struct file *file; 177 struct file *file;
178 struct page *page; 178 struct page *page;
@@ -378,14 +378,14 @@ error:
378 return error; 378 return error;
379} 379}
380 380
381/* Fill in an entry based on the xdr code stored in desc->page */ 381static int xdr_decode(nfs_readdir_descriptor_t *desc,
382static 382 struct nfs_entry *entry, struct xdr_stream *xdr)
383int xdr_decode(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry, struct xdr_stream *stream)
384{ 383{
385 __be32 *p = desc->decode(stream, entry, NFS_SERVER(desc->file->f_path.dentry->d_inode), desc->plus); 384 int error;
386 if (IS_ERR(p))
387 return PTR_ERR(p);
388 385
386 error = desc->decode(xdr, entry, desc->plus);
387 if (error)
388 return error;
389 entry->fattr->time_start = desc->timestamp; 389 entry->fattr->time_start = desc->timestamp;
390 entry->fattr->gencount = desc->gencount; 390 entry->fattr->gencount = desc->gencount;
391 return 0; 391 return 0;
@@ -566,6 +566,7 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page,
566 entry.eof = 0; 566 entry.eof = 0;
567 entry.fh = nfs_alloc_fhandle(); 567 entry.fh = nfs_alloc_fhandle();
568 entry.fattr = nfs_alloc_fattr(); 568 entry.fattr = nfs_alloc_fattr();
569 entry.server = NFS_SERVER(inode);
569 if (entry.fh == NULL || entry.fattr == NULL) 570 if (entry.fh == NULL || entry.fattr == NULL)
570 goto out; 571 goto out;
571 572
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 6c6a9955bae9..435eae3666bd 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -187,15 +187,18 @@ extern void nfs_destroy_directcache(void);
187/* nfs2xdr.c */ 187/* nfs2xdr.c */
188extern int nfs_stat_to_errno(enum nfs_stat); 188extern int nfs_stat_to_errno(enum nfs_stat);
189extern struct rpc_procinfo nfs_procedures[]; 189extern struct rpc_procinfo nfs_procedures[];
190extern __be32 *nfs2_decode_dirent(struct xdr_stream *, struct nfs_entry *, struct nfs_server *, int); 190extern int nfs2_decode_dirent(struct xdr_stream *,
191 struct nfs_entry *, int);
191 192
192/* nfs3xdr.c */ 193/* nfs3xdr.c */
193extern struct rpc_procinfo nfs3_procedures[]; 194extern struct rpc_procinfo nfs3_procedures[];
194extern __be32 *nfs3_decode_dirent(struct xdr_stream *, struct nfs_entry *, struct nfs_server *, int); 195extern int nfs3_decode_dirent(struct xdr_stream *,
196 struct nfs_entry *, int);
195 197
196/* nfs4xdr.c */ 198/* nfs4xdr.c */
197#ifdef CONFIG_NFS_V4 199#ifdef CONFIG_NFS_V4
198extern __be32 *nfs4_decode_dirent(struct xdr_stream *, struct nfs_entry *, struct nfs_server *, int); 200extern int nfs4_decode_dirent(struct xdr_stream *,
201 struct nfs_entry *, int);
199#endif 202#endif
200#ifdef CONFIG_NFS_V4_1 203#ifdef CONFIG_NFS_V4_1
201extern const u32 nfs41_maxread_overhead; 204extern const u32 nfs41_maxread_overhead;
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
index 0343175fe6c0..a9b848edbd2e 100644
--- a/fs/nfs/nfs2xdr.c
+++ b/fs/nfs/nfs2xdr.c
@@ -936,10 +936,10 @@ static int nfs2_xdr_dec_writeres(struct rpc_rqst *req, __be32 *p,
936 * the local page cache. 936 * the local page cache.
937 * @xdr: XDR stream where entry resides 937 * @xdr: XDR stream where entry resides
938 * @entry: buffer to fill in with entry data 938 * @entry: buffer to fill in with entry data
939 * @server: nfs_server data for this directory
940 * @plus: boolean indicating whether this should be a readdirplus entry 939 * @plus: boolean indicating whether this should be a readdirplus entry
941 * 940 *
942 * Returns the position of the next item in the buffer, or an ERR_PTR. 941 * Returns zero if successful, otherwise a negative errno value is
942 * returned.
943 * 943 *
944 * This function is not invoked during READDIR reply decoding, but 944 * This function is not invoked during READDIR reply decoding, but
945 * rather whenever an application invokes the getdents(2) system call 945 * rather whenever an application invokes the getdents(2) system call
@@ -954,8 +954,8 @@ static int nfs2_xdr_dec_writeres(struct rpc_rqst *req, __be32 *p,
954 * entry *nextentry; 954 * entry *nextentry;
955 * }; 955 * };
956 */ 956 */
957__be32 *nfs2_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, 957int nfs2_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
958 struct nfs_server *server, int plus) 958 int plus)
959{ 959{
960 __be32 *p; 960 __be32 *p;
961 int error; 961 int error;
@@ -968,9 +968,9 @@ __be32 *nfs2_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
968 if (unlikely(p == NULL)) 968 if (unlikely(p == NULL))
969 goto out_overflow; 969 goto out_overflow;
970 if (*p++ == xdr_zero) 970 if (*p++ == xdr_zero)
971 return ERR_PTR(-EAGAIN); 971 return -EAGAIN;
972 entry->eof = 1; 972 entry->eof = 1;
973 return ERR_PTR(-EBADCOOKIE); 973 return -EBADCOOKIE;
974 } 974 }
975 975
976 p = xdr_inline_decode(xdr, 4); 976 p = xdr_inline_decode(xdr, 4);
@@ -980,7 +980,7 @@ __be32 *nfs2_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
980 980
981 error = decode_filename_inline(xdr, &entry->name, &entry->len); 981 error = decode_filename_inline(xdr, &entry->name, &entry->len);
982 if (unlikely(error)) 982 if (unlikely(error))
983 return ERR_PTR(error); 983 return error;
984 984
985 /* 985 /*
986 * The type (size and byte order) of nfscookie isn't defined in 986 * The type (size and byte order) of nfscookie isn't defined in
@@ -999,11 +999,11 @@ __be32 *nfs2_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
999 entry->eof = 0; 999 entry->eof = 0;
1000 if (p != NULL) 1000 if (p != NULL)
1001 entry->eof = (p[0] == xdr_zero) && (p[1] != xdr_zero); 1001 entry->eof = (p[0] == xdr_zero) && (p[1] != xdr_zero);
1002 return p; 1002 return 0;
1003 1003
1004out_overflow: 1004out_overflow:
1005 print_overflow_msg(__func__, xdr); 1005 print_overflow_msg(__func__, xdr);
1006 return ERR_PTR(-EAGAIN); 1006 return -EAGAIN;
1007} 1007}
1008 1008
1009/* 1009/*
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index c97d00fe849a..15c93ccd90c5 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -1970,10 +1970,10 @@ out_status:
1970 * the local page cache 1970 * the local page cache
1971 * @xdr: XDR stream where entry resides 1971 * @xdr: XDR stream where entry resides
1972 * @entry: buffer to fill in with entry data 1972 * @entry: buffer to fill in with entry data
1973 * @server: nfs_server data for this directory
1974 * @plus: boolean indicating whether this should be a readdirplus entry 1973 * @plus: boolean indicating whether this should be a readdirplus entry
1975 * 1974 *
1976 * Returns the position of the next item in the buffer, or an ERR_PTR. 1975 * Returns zero if successful, otherwise a negative errno value is
1976 * returned.
1977 * 1977 *
1978 * This function is not invoked during READDIR reply decoding, but 1978 * This function is not invoked during READDIR reply decoding, but
1979 * rather whenever an application invokes the getdents(2) system call 1979 * rather whenever an application invokes the getdents(2) system call
@@ -2000,8 +2000,8 @@ out_status:
2000 * entryplus3 *nextentry; 2000 * entryplus3 *nextentry;
2001 * }; 2001 * };
2002 */ 2002 */
2003__be32 *nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, 2003int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
2004 struct nfs_server *server, int plus) 2004 int plus)
2005{ 2005{
2006 struct nfs_entry old = *entry; 2006 struct nfs_entry old = *entry;
2007 __be32 *p; 2007 __be32 *p;
@@ -2015,23 +2015,23 @@ __be32 *nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
2015 if (unlikely(p == NULL)) 2015 if (unlikely(p == NULL))
2016 goto out_overflow; 2016 goto out_overflow;
2017 if (*p == xdr_zero) 2017 if (*p == xdr_zero)
2018 return ERR_PTR(-EAGAIN); 2018 return -EAGAIN;
2019 entry->eof = 1; 2019 entry->eof = 1;
2020 return ERR_PTR(-EBADCOOKIE); 2020 return -EBADCOOKIE;
2021 } 2021 }
2022 2022
2023 error = decode_fileid3(xdr, &entry->ino); 2023 error = decode_fileid3(xdr, &entry->ino);
2024 if (unlikely(error)) 2024 if (unlikely(error))
2025 return ERR_PTR(error); 2025 return error;
2026 2026
2027 error = decode_inline_filename3(xdr, &entry->name, &entry->len); 2027 error = decode_inline_filename3(xdr, &entry->name, &entry->len);
2028 if (unlikely(error)) 2028 if (unlikely(error))
2029 return ERR_PTR(error); 2029 return error;
2030 2030
2031 entry->prev_cookie = entry->cookie; 2031 entry->prev_cookie = entry->cookie;
2032 error = decode_cookie3(xdr, &entry->cookie); 2032 error = decode_cookie3(xdr, &entry->cookie);
2033 if (unlikely(error)) 2033 if (unlikely(error))
2034 return ERR_PTR(error); 2034 return error;
2035 2035
2036 entry->d_type = DT_UNKNOWN; 2036 entry->d_type = DT_UNKNOWN;
2037 2037
@@ -2039,7 +2039,7 @@ __be32 *nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
2039 entry->fattr->valid = 0; 2039 entry->fattr->valid = 0;
2040 error = decode_post_op_attr(xdr, entry->fattr); 2040 error = decode_post_op_attr(xdr, entry->fattr);
2041 if (unlikely(error)) 2041 if (unlikely(error))
2042 return ERR_PTR(error); 2042 return error;
2043 if (entry->fattr->valid & NFS_ATTR_FATTR_V3) 2043 if (entry->fattr->valid & NFS_ATTR_FATTR_V3)
2044 entry->d_type = nfs_umode_to_dtype(entry->fattr->mode); 2044 entry->d_type = nfs_umode_to_dtype(entry->fattr->mode);
2045 2045
@@ -2052,7 +2052,7 @@ __be32 *nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
2052 if (unlikely(error)) { 2052 if (unlikely(error)) {
2053 if (error == -E2BIG) 2053 if (error == -E2BIG)
2054 goto out_truncated; 2054 goto out_truncated;
2055 return ERR_PTR(error); 2055 return error;
2056 } 2056 }
2057 } else 2057 } else
2058 zero_nfs_fh3(entry->fh); 2058 zero_nfs_fh3(entry->fh);
@@ -2063,15 +2063,15 @@ __be32 *nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
2063 entry->eof = 0; 2063 entry->eof = 0;
2064 if (p != NULL) 2064 if (p != NULL)
2065 entry->eof = (p[0] == xdr_zero) && (p[1] != xdr_zero); 2065 entry->eof = (p[0] == xdr_zero) && (p[1] != xdr_zero);
2066 return p; 2066 return 0;
2067 2067
2068out_overflow: 2068out_overflow:
2069 print_overflow_msg(__func__, xdr); 2069 print_overflow_msg(__func__, xdr);
2070 return ERR_PTR(-EAGAIN); 2070 return -EAGAIN;
2071out_truncated: 2071out_truncated:
2072 dprintk("NFS: directory entry contains invalid file handle\n"); 2072 dprintk("NFS: directory entry contains invalid file handle\n");
2073 *entry = old; 2073 *entry = old;
2074 return ERR_PTR(-EAGAIN); 2074 return -EAGAIN;
2075} 2075}
2076 2076
2077/* 2077/*
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 9fa496387fdf..7a6eecffcaeb 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -331,7 +331,6 @@ extern void nfs_free_seqid(struct nfs_seqid *seqid);
331extern const nfs4_stateid zero_stateid; 331extern const nfs4_stateid zero_stateid;
332 332
333/* nfs4xdr.c */ 333/* nfs4xdr.c */
334extern __be32 *nfs4_decode_dirent(struct xdr_stream *, struct nfs_entry *, struct nfs_server *, int);
335extern struct rpc_procinfo nfs4_procedures[]; 334extern struct rpc_procinfo nfs4_procedures[];
336 335
337struct nfs4_mount_data; 336struct nfs4_mount_data;
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 868815c55450..be9f00ab0d18 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -6159,8 +6159,22 @@ out:
6159} 6159}
6160#endif /* CONFIG_NFS_V4_1 */ 6160#endif /* CONFIG_NFS_V4_1 */
6161 6161
6162__be32 *nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, 6162/**
6163 struct nfs_server *server, int plus) 6163 * nfs4_decode_dirent - Decode a single NFSv4 directory entry stored in
6164 * the local page cache.
6165 * @xdr: XDR stream where entry resides
6166 * @entry: buffer to fill in with entry data
6167 * @plus: boolean indicating whether this should be a readdirplus entry
6168 *
6169 * Returns zero if successful, otherwise a negative errno value is
6170 * returned.
6171 *
6172 * This function is not invoked during READDIR reply decoding, but
6173 * rather whenever an application invokes the getdents(2) system call
6174 * on a directory already in our cache.
6175 */
6176int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
6177 int plus)
6164{ 6178{
6165 uint32_t bitmap[2] = {0}; 6179 uint32_t bitmap[2] = {0};
6166 uint32_t len; 6180 uint32_t len;
@@ -6172,9 +6186,9 @@ __be32 *nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
6172 if (unlikely(!p)) 6186 if (unlikely(!p))
6173 goto out_overflow; 6187 goto out_overflow;
6174 if (!ntohl(*p++)) 6188 if (!ntohl(*p++))
6175 return ERR_PTR(-EAGAIN); 6189 return -EAGAIN;
6176 entry->eof = 1; 6190 entry->eof = 1;
6177 return ERR_PTR(-EBADCOOKIE); 6191 return -EBADCOOKIE;
6178 } 6192 }
6179 6193
6180 p = xdr_inline_decode(xdr, 12); 6194 p = xdr_inline_decode(xdr, 12);
@@ -6203,7 +6217,8 @@ __be32 *nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
6203 if (decode_attr_length(xdr, &len, &p) < 0) 6217 if (decode_attr_length(xdr, &len, &p) < 0)
6204 goto out_overflow; 6218 goto out_overflow;
6205 6219
6206 if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh, server, 1) < 0) 6220 if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh,
6221 entry->server, 1) < 0)
6207 goto out_overflow; 6222 goto out_overflow;
6208 if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID) 6223 if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID)
6209 entry->ino = entry->fattr->fileid; 6224 entry->ino = entry->fattr->fileid;
@@ -6221,11 +6236,11 @@ __be32 *nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
6221 else 6236 else
6222 entry->eof = 0; 6237 entry->eof = 0;
6223 6238
6224 return p; 6239 return 0;
6225 6240
6226out_overflow: 6241out_overflow:
6227 print_overflow_msg(__func__, xdr); 6242 print_overflow_msg(__func__, xdr);
6228 return ERR_PTR(-EAGAIN); 6243 return -EAGAIN;
6229} 6244}
6230 6245
6231/* 6246/*
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 80f07198a31a..236e7e4b99a0 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -484,6 +484,7 @@ struct nfs_entry {
484 struct nfs_fh * fh; 484 struct nfs_fh * fh;
485 struct nfs_fattr * fattr; 485 struct nfs_fattr * fattr;
486 unsigned char d_type; 486 unsigned char d_type;
487 struct nfs_server * server;
487}; 488};
488 489
489/* 490/*
@@ -1089,7 +1090,7 @@ struct nfs_rpc_ops {
1089 int (*pathconf) (struct nfs_server *, struct nfs_fh *, 1090 int (*pathconf) (struct nfs_server *, struct nfs_fh *,
1090 struct nfs_pathconf *); 1091 struct nfs_pathconf *);
1091 int (*set_capabilities)(struct nfs_server *, struct nfs_fh *); 1092 int (*set_capabilities)(struct nfs_server *, struct nfs_fh *);
1092 __be32 *(*decode_dirent)(struct xdr_stream *, struct nfs_entry *, struct nfs_server *, int plus); 1093 int (*decode_dirent)(struct xdr_stream *, struct nfs_entry *, int);
1093 void (*read_setup) (struct nfs_read_data *, struct rpc_message *); 1094 void (*read_setup) (struct nfs_read_data *, struct rpc_message *);
1094 int (*read_done) (struct rpc_task *, struct nfs_read_data *); 1095 int (*read_done) (struct rpc_task *, struct nfs_read_data *);
1095 void (*write_setup) (struct nfs_write_data *, struct rpc_message *); 1096 void (*write_setup) (struct nfs_write_data *, struct rpc_message *);