aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorBryan Schumaker <bjschuma@netapp.com>2010-10-20 15:44:29 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2010-10-23 15:27:33 -0400
commitbabddc72a9468884ce1a23db3c3d54b0afa299f0 (patch)
treeb176e5795b47c73c47543acdc546da0c38619ddc /fs
parentba8e452a4fe64a51b74d43761e14d99f0666cc45 (diff)
NFS: decode_dirent should use an xdr_stream
Convert nfs*xdr.c to use an xdr stream in decode_dirent. This will prevent a kernel oops that has been occuring when reading a vmapped page. Signed-off-by: Bryan Schumaker <bjschuma@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/dir.c29
-rw-r--r--fs/nfs/internal.h6
-rw-r--r--fs/nfs/nfs2xdr.c39
-rw-r--r--fs/nfs/nfs3xdr.c93
-rw-r--r--fs/nfs/nfs4_fs.h2
-rw-r--r--fs/nfs/nfs4xdr.c71
6 files changed, 201 insertions, 39 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index fd30f185ec01..88cbcda76856 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -171,7 +171,7 @@ struct nfs_cache_array {
171 171
172#define MAX_READDIR_ARRAY ((PAGE_SIZE - sizeof(struct nfs_cache_array)) / sizeof(struct nfs_cache_array_entry)) 172#define MAX_READDIR_ARRAY ((PAGE_SIZE - sizeof(struct nfs_cache_array)) / sizeof(struct nfs_cache_array_entry))
173 173
174typedef __be32 * (*decode_dirent_t)(__be32 *, struct nfs_entry *, int); 174typedef __be32 * (*decode_dirent_t)(struct xdr_stream *, struct nfs_entry *, int);
175typedef struct { 175typedef struct {
176 struct file *file; 176 struct file *file;
177 struct page *page; 177 struct page *page;
@@ -357,13 +357,11 @@ error:
357 357
358/* Fill in an entry based on the xdr code stored in desc->page */ 358/* Fill in an entry based on the xdr code stored in desc->page */
359static 359static
360int xdr_decode(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry, __be32 **ptr) 360int xdr_decode(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry, struct xdr_stream *stream)
361{ 361{
362 __be32 *p = *ptr; 362 __be32 *p = desc->decode(stream, entry, desc->plus);
363 p = desc->decode(p, entry, desc->plus);
364 if (IS_ERR(p)) 363 if (IS_ERR(p))
365 return PTR_ERR(p); 364 return PTR_ERR(p);
366 *ptr = p;
367 365
368 entry->fattr->time_start = desc->timestamp; 366 entry->fattr->time_start = desc->timestamp;
369 entry->fattr->gencount = desc->gencount; 367 entry->fattr->gencount = desc->gencount;
@@ -438,10 +436,23 @@ out:
438/* Perform conversion from xdr to cache array */ 436/* Perform conversion from xdr to cache array */
439static 437static
440void nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry, 438void nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry,
441 struct page *xdr_page, struct page *page) 439 struct page *xdr_page, struct page *page, unsigned int buflen)
442{ 440{
441 struct xdr_stream stream;
442 struct xdr_buf buf;
443 __be32 *ptr = kmap(xdr_page); 443 __be32 *ptr = kmap(xdr_page);
444 while (xdr_decode(desc, entry, &ptr) == 0) { 444
445 buf.head->iov_base = xdr_page;
446 buf.head->iov_len = buflen;
447 buf.tail->iov_len = 0;
448 buf.page_base = 0;
449 buf.page_len = 0;
450 buf.buflen = buf.head->iov_len;
451 buf.len = buf.head->iov_len;
452
453 xdr_init_decode(&stream, &buf, ptr);
454
455 while (xdr_decode(desc, entry, &stream) == 0) {
445 if (nfs_readdir_add_to_array(entry, page) == -1) 456 if (nfs_readdir_add_to_array(entry, page) == -1)
446 break; 457 break;
447 if (desc->plus == 1) 458 if (desc->plus == 1)
@@ -458,6 +469,7 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page,
458 struct file *file = desc->file; 469 struct file *file = desc->file;
459 struct nfs_cache_array *array; 470 struct nfs_cache_array *array;
460 int status = 0; 471 int status = 0;
472 unsigned int array_size = 1;
461 473
462 entry.prev_cookie = 0; 474 entry.prev_cookie = 0;
463 entry.cookie = *desc->dir_cookie; 475 entry.cookie = *desc->dir_cookie;
@@ -476,9 +488,10 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page,
476 goto out_release_array; 488 goto out_release_array;
477 do { 489 do {
478 status = nfs_readdir_xdr_filler(xdr_page, desc, &entry, file, inode); 490 status = nfs_readdir_xdr_filler(xdr_page, desc, &entry, file, inode);
491
479 if (status < 0) 492 if (status < 0)
480 break; 493 break;
481 nfs_readdir_page_filler(desc, &entry, xdr_page, page); 494 nfs_readdir_page_filler(desc, &entry, xdr_page, page, array_size * PAGE_SIZE);
482 } while (array->eof_index < 0 && array->size < MAX_READDIR_ARRAY); 495 } while (array->eof_index < 0 && array->size < MAX_READDIR_ARRAY);
483 496
484 put_page(xdr_page); 497 put_page(xdr_page);
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index c961bc92c107..74b015598a43 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -181,15 +181,15 @@ extern void nfs_destroy_directcache(void);
181/* nfs2xdr.c */ 181/* nfs2xdr.c */
182extern int nfs_stat_to_errno(int); 182extern int nfs_stat_to_errno(int);
183extern struct rpc_procinfo nfs_procedures[]; 183extern struct rpc_procinfo nfs_procedures[];
184extern __be32 * nfs_decode_dirent(__be32 *, struct nfs_entry *, int); 184extern __be32 *nfs_decode_dirent(struct xdr_stream *, struct nfs_entry *, int);
185 185
186/* nfs3xdr.c */ 186/* nfs3xdr.c */
187extern struct rpc_procinfo nfs3_procedures[]; 187extern struct rpc_procinfo nfs3_procedures[];
188extern __be32 *nfs3_decode_dirent(__be32 *, struct nfs_entry *, int); 188extern __be32 *nfs3_decode_dirent(struct xdr_stream *, struct nfs_entry *, int);
189 189
190/* nfs4xdr.c */ 190/* nfs4xdr.c */
191#ifdef CONFIG_NFS_V4 191#ifdef CONFIG_NFS_V4
192extern __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus); 192extern __be32 *nfs4_decode_dirent(struct xdr_stream *, struct nfs_entry *entry, int plus);
193#endif 193#endif
194#ifdef CONFIG_NFS_V4_1 194#ifdef CONFIG_NFS_V4_1
195extern const u32 nfs41_maxread_overhead; 195extern const u32 nfs41_maxread_overhead;
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
index 79c74387a2fe..0210c752e743 100644
--- a/fs/nfs/nfs2xdr.c
+++ b/fs/nfs/nfs2xdr.c
@@ -500,25 +500,56 @@ err_unmap:
500 goto out; 500 goto out;
501} 501}
502 502
503static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
504{
505 dprintk("nfs: %s: prematurely hit end of receive buffer. "
506 "Remaining buffer length is %tu words.\n",
507 func, xdr->end - xdr->p);
508}
509
503__be32 * 510__be32 *
504nfs_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus) 511nfs_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, int plus)
505{ 512{
506 if (!*p++) { 513 __be32 *p;
507 if (!*p) 514 p = xdr_inline_decode(xdr, 4);
515 if (unlikely(!p))
516 goto out_overflow;
517 if (!ntohl(*p++)) {
518 p = xdr_inline_decode(xdr, 4);
519 if (unlikely(!p))
520 goto out_overflow;
521 if (!ntohl(*p++))
508 return ERR_PTR(-EAGAIN); 522 return ERR_PTR(-EAGAIN);
509 entry->eof = 1; 523 entry->eof = 1;
510 return ERR_PTR(-EBADCOOKIE); 524 return ERR_PTR(-EBADCOOKIE);
511 } 525 }
512 526
527 p = xdr_inline_decode(xdr, 8);
528 if (unlikely(!p))
529 goto out_overflow;
530
513 entry->ino = ntohl(*p++); 531 entry->ino = ntohl(*p++);
514 entry->len = ntohl(*p++); 532 entry->len = ntohl(*p++);
533
534 p = xdr_inline_decode(xdr, entry->len + 4);
535 if (unlikely(!p))
536 goto out_overflow;
515 entry->name = (const char *) p; 537 entry->name = (const char *) p;
516 p += XDR_QUADLEN(entry->len); 538 p += XDR_QUADLEN(entry->len);
517 entry->prev_cookie = entry->cookie; 539 entry->prev_cookie = entry->cookie;
518 entry->cookie = ntohl(*p++); 540 entry->cookie = ntohl(*p++);
519 entry->eof = !p[0] && p[1]; 541
542 p = xdr_inline_peek(xdr, 8);
543 if (p != NULL)
544 entry->eof = !p[0] && p[1];
545 else
546 entry->eof = 0;
520 547
521 return p; 548 return p;
549
550out_overflow:
551 print_overflow_msg(__func__, xdr);
552 return ERR_PTR(-EIO);
522} 553}
523 554
524/* 555/*
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index 52b2fda66e63..d562c8d9d56e 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -100,6 +100,13 @@ static const umode_t nfs_type2fmt[] = {
100 [NF3FIFO] = S_IFIFO, 100 [NF3FIFO] = S_IFIFO,
101}; 101};
102 102
103static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
104{
105 dprintk("nfs: %s: prematurely hit end of receive buffer. "
106 "Remaining buffer length is %tu words.\n",
107 func, xdr->end - xdr->p);
108}
109
103/* 110/*
104 * Common NFS XDR functions as inlines 111 * Common NFS XDR functions as inlines
105 */ 112 */
@@ -119,6 +126,29 @@ xdr_decode_fhandle(__be32 *p, struct nfs_fh *fh)
119 return NULL; 126 return NULL;
120} 127}
121 128
129static inline __be32 *
130xdr_decode_fhandle_stream(struct xdr_stream *xdr, struct nfs_fh *fh)
131{
132 __be32 *p;
133 p = xdr_inline_decode(xdr, 4);
134 if (unlikely(!p))
135 goto out_overflow;
136 fh->size = ntohl(*p++);
137
138 if (fh->size <= NFS3_FHSIZE) {
139 p = xdr_inline_decode(xdr, fh->size);
140 if (unlikely(!p))
141 goto out_overflow;
142 memcpy(fh->data, p, fh->size);
143 return p + XDR_QUADLEN(fh->size);
144 }
145 return NULL;
146
147out_overflow:
148 print_overflow_msg(__func__, xdr);
149 return ERR_PTR(-EIO);
150}
151
122/* 152/*
123 * Encode/decode time. 153 * Encode/decode time.
124 */ 154 */
@@ -241,6 +271,26 @@ xdr_decode_post_op_attr(__be32 *p, struct nfs_fattr *fattr)
241} 271}
242 272
243static inline __be32 * 273static inline __be32 *
274xdr_decode_post_op_attr_stream(struct xdr_stream *xdr, struct nfs_fattr *fattr)
275{
276 __be32 *p;
277
278 p = xdr_inline_decode(xdr, 4);
279 if (unlikely(!p))
280 goto out_overflow;
281 if (ntohl(*p++)) {
282 p = xdr_inline_decode(xdr, 84);
283 if (unlikely(!p))
284 goto out_overflow;
285 p = xdr_decode_fattr(p, fattr);
286 }
287 return p;
288out_overflow:
289 print_overflow_msg(__func__, xdr);
290 return ERR_PTR(-EIO);
291}
292
293static inline __be32 *
244xdr_decode_pre_op_attr(__be32 *p, struct nfs_fattr *fattr) 294xdr_decode_pre_op_attr(__be32 *p, struct nfs_fattr *fattr)
245{ 295{
246 if (*p++) 296 if (*p++)
@@ -616,19 +666,33 @@ err_unmap:
616} 666}
617 667
618__be32 * 668__be32 *
619nfs3_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus) 669nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, int plus)
620{ 670{
671 __be32 *p;
621 struct nfs_entry old = *entry; 672 struct nfs_entry old = *entry;
622 673
623 if (!*p++) { 674 p = xdr_inline_decode(xdr, 4);
624 if (!*p) 675 if (unlikely(!p))
676 goto out_overflow;
677 if (!ntohl(*p++)) {
678 p = xdr_inline_decode(xdr, 4);
679 if (unlikely(!p))
680 goto out_overflow;
681 if (!ntohl(*p++))
625 return ERR_PTR(-EAGAIN); 682 return ERR_PTR(-EAGAIN);
626 entry->eof = 1; 683 entry->eof = 1;
627 return ERR_PTR(-EBADCOOKIE); 684 return ERR_PTR(-EBADCOOKIE);
628 } 685 }
629 686
687 p = xdr_inline_decode(xdr, 12);
688 if (unlikely(!p))
689 goto out_overflow;
630 p = xdr_decode_hyper(p, &entry->ino); 690 p = xdr_decode_hyper(p, &entry->ino);
631 entry->len = ntohl(*p++); 691 entry->len = ntohl(*p++);
692
693 p = xdr_inline_decode(xdr, entry->len + 8);
694 if (unlikely(!p))
695 goto out_overflow;
632 entry->name = (const char *) p; 696 entry->name = (const char *) p;
633 p += XDR_QUADLEN(entry->len); 697 p += XDR_QUADLEN(entry->len);
634 entry->prev_cookie = entry->cookie; 698 entry->prev_cookie = entry->cookie;
@@ -636,10 +700,17 @@ nfs3_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
636 700
637 if (plus) { 701 if (plus) {
638 entry->fattr->valid = 0; 702 entry->fattr->valid = 0;
639 p = xdr_decode_post_op_attr(p, entry->fattr); 703 p = xdr_decode_post_op_attr_stream(xdr, entry->fattr);
704 if (IS_ERR(p))
705 goto out_overflow_exit;
640 /* In fact, a post_op_fh3: */ 706 /* In fact, a post_op_fh3: */
707 p = xdr_inline_decode(xdr, 4);
708 if (unlikely(!p))
709 goto out_overflow;
641 if (*p++) { 710 if (*p++) {
642 p = xdr_decode_fhandle(p, entry->fh); 711 p = xdr_decode_fhandle_stream(xdr, entry->fh);
712 if (IS_ERR(p))
713 goto out_overflow_exit;
643 /* Ugh -- server reply was truncated */ 714 /* Ugh -- server reply was truncated */
644 if (p == NULL) { 715 if (p == NULL) {
645 dprintk("NFS: FH truncated\n"); 716 dprintk("NFS: FH truncated\n");
@@ -650,8 +721,18 @@ nfs3_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
650 memset((u8*)(entry->fh), 0, sizeof(*entry->fh)); 721 memset((u8*)(entry->fh), 0, sizeof(*entry->fh));
651 } 722 }
652 723
653 entry->eof = !p[0] && p[1]; 724 p = xdr_inline_peek(xdr, 8);
725 if (p != NULL)
726 entry->eof = !p[0] && p[1];
727 else
728 entry->eof = 0;
729
654 return p; 730 return p;
731
732out_overflow:
733 print_overflow_msg(__func__, xdr);
734out_overflow_exit:
735 return ERR_PTR(-EIO);
655} 736}
656 737
657/* 738/*
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index d24a8e07b5e2..c58ea6377506 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -331,7 +331,7 @@ 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(__be32 *p, struct nfs_entry *entry, int plus); 334extern __be32 *nfs4_decode_dirent(struct xdr_stream *, struct nfs_entry *entry, int plus);
335extern struct rpc_procinfo nfs4_procedures[]; 335extern struct rpc_procinfo nfs4_procedures[];
336 336
337struct nfs4_mount_data; 337struct nfs4_mount_data;
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 6ea5c9392fe4..a4919e999354 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -3950,13 +3950,13 @@ static int decode_lock_denied (struct xdr_stream *xdr, struct file_lock *fl)
3950 __be32 *p; 3950 __be32 *p;
3951 uint32_t namelen, type; 3951 uint32_t namelen, type;
3952 3952
3953 p = xdr_inline_decode(xdr, 32); 3953 p = xdr_inline_decode(xdr, 32); /* read 32 bytes */
3954 if (unlikely(!p)) 3954 if (unlikely(!p))
3955 goto out_overflow; 3955 goto out_overflow;
3956 p = xdr_decode_hyper(p, &offset); 3956 p = xdr_decode_hyper(p, &offset); /* read 2 8-byte long words */
3957 p = xdr_decode_hyper(p, &length); 3957 p = xdr_decode_hyper(p, &length);
3958 type = be32_to_cpup(p++); 3958 type = be32_to_cpup(p++); /* 4 byte read */
3959 if (fl != NULL) { 3959 if (fl != NULL) { /* manipulate file lock */
3960 fl->fl_start = (loff_t)offset; 3960 fl->fl_start = (loff_t)offset;
3961 fl->fl_end = fl->fl_start + (loff_t)length - 1; 3961 fl->fl_end = fl->fl_start + (loff_t)length - 1;
3962 if (length == ~(uint64_t)0) 3962 if (length == ~(uint64_t)0)
@@ -3966,9 +3966,9 @@ static int decode_lock_denied (struct xdr_stream *xdr, struct file_lock *fl)
3966 fl->fl_type = F_RDLCK; 3966 fl->fl_type = F_RDLCK;
3967 fl->fl_pid = 0; 3967 fl->fl_pid = 0;
3968 } 3968 }
3969 p = xdr_decode_hyper(p, &clientid); 3969 p = xdr_decode_hyper(p, &clientid); /* read 8 bytes */
3970 namelen = be32_to_cpup(p); 3970 namelen = be32_to_cpup(p); /* read 4 bytes */ /* have read all 32 bytes now */
3971 p = xdr_inline_decode(xdr, namelen); 3971 p = xdr_inline_decode(xdr, namelen); /* variable size field */
3972 if (likely(p)) 3972 if (likely(p))
3973 return -NFS4ERR_DENIED; 3973 return -NFS4ERR_DENIED;
3974out_overflow: 3974out_overflow:
@@ -5755,21 +5755,33 @@ static int nfs4_xdr_dec_reclaim_complete(struct rpc_rqst *rqstp, uint32_t *p,
5755} 5755}
5756#endif /* CONFIG_NFS_V4_1 */ 5756#endif /* CONFIG_NFS_V4_1 */
5757 5757
5758__be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus) 5758__be32 *nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, int plus)
5759{ 5759{
5760 uint32_t bitmap[2] = {0}; 5760 uint32_t bitmap[2] = {0};
5761 uint32_t len; 5761 uint32_t len;
5762 5762 __be32 *p = xdr_inline_decode(xdr, 4);
5763 if (!*p++) { 5763 if (unlikely(!p))
5764 if (!*p) 5764 goto out_overflow;
5765 if (!ntohl(*p++)) {
5766 p = xdr_inline_decode(xdr, 4);
5767 if (unlikely(!p))
5768 goto out_overflow;
5769 if (!ntohl(*p++))
5765 return ERR_PTR(-EAGAIN); 5770 return ERR_PTR(-EAGAIN);
5766 entry->eof = 1; 5771 entry->eof = 1;
5767 return ERR_PTR(-EBADCOOKIE); 5772 return ERR_PTR(-EBADCOOKIE);
5768 } 5773 }
5769 5774
5775 p = xdr_inline_decode(xdr, 12);
5776 if (unlikely(!p))
5777 goto out_overflow;
5770 entry->prev_cookie = entry->cookie; 5778 entry->prev_cookie = entry->cookie;
5771 p = xdr_decode_hyper(p, &entry->cookie); 5779 p = xdr_decode_hyper(p, &entry->cookie);
5772 entry->len = ntohl(*p++); 5780 entry->len = ntohl(*p++);
5781
5782 p = xdr_inline_decode(xdr, entry->len + 4);
5783 if (unlikely(!p))
5784 goto out_overflow;
5773 entry->name = (const char *) p; 5785 entry->name = (const char *) p;
5774 p += XDR_QUADLEN(entry->len); 5786 p += XDR_QUADLEN(entry->len);
5775 5787
@@ -5782,29 +5794,54 @@ __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
5782 5794
5783 len = ntohl(*p++); /* bitmap length */ 5795 len = ntohl(*p++); /* bitmap length */
5784 if (len-- > 0) { 5796 if (len-- > 0) {
5797 p = xdr_inline_decode(xdr, 4);
5798 if (unlikely(!p))
5799 goto out_overflow;
5785 bitmap[0] = ntohl(*p++); 5800 bitmap[0] = ntohl(*p++);
5786 if (len-- > 0) { 5801 if (len-- > 0) {
5802 p = xdr_inline_decode(xdr, 4);
5803 if (unlikely(!p))
5804 goto out_overflow;
5787 bitmap[1] = ntohl(*p++); 5805 bitmap[1] = ntohl(*p++);
5788 p += len; 5806 p += len;
5789 } 5807 }
5790 } 5808 }
5809 p = xdr_inline_decode(xdr, 4);
5810 if (unlikely(!p))
5811 goto out_overflow;
5791 len = XDR_QUADLEN(ntohl(*p++)); /* attribute buffer length */ 5812 len = XDR_QUADLEN(ntohl(*p++)); /* attribute buffer length */
5792 if (len > 0) { 5813 if (len > 0) {
5793 if (bitmap[0] & FATTR4_WORD0_RDATTR_ERROR) { 5814 if (bitmap[0] & FATTR4_WORD0_RDATTR_ERROR) {
5794 bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR; 5815 bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR;
5795 /* Ignore the return value of rdattr_error for now */ 5816 /* Ignore the return value of rdattr_error for now */
5796 p++; 5817 p = xdr_inline_decode(xdr, 4);
5797 len--; 5818 if (unlikely(!p))
5819 goto out_overflow;
5798 } 5820 }
5799 if (bitmap[0] == 0 && bitmap[1] == FATTR4_WORD1_MOUNTED_ON_FILEID) 5821 if (bitmap[0] == 0 && bitmap[1] == FATTR4_WORD1_MOUNTED_ON_FILEID) {
5822 p = xdr_inline_decode(xdr, 8);
5823 if (unlikely(!p))
5824 goto out_overflow;
5800 xdr_decode_hyper(p, &entry->ino); 5825 xdr_decode_hyper(p, &entry->ino);
5801 else if (bitmap[0] == FATTR4_WORD0_FILEID) 5826 } else if (bitmap[0] == FATTR4_WORD0_FILEID) {
5827 p = xdr_inline_decode(xdr, 8);
5828 if (unlikely(!p))
5829 goto out_overflow;
5802 xdr_decode_hyper(p, &entry->ino); 5830 xdr_decode_hyper(p, &entry->ino);
5803 p += len; 5831 }
5804 } 5832 }
5805 5833
5806 entry->eof = !p[0] && p[1]; 5834 p = xdr_inline_peek(xdr, 8);
5835 if (p != NULL)
5836 entry->eof = !p[0] && p[1];
5837 else
5838 entry->eof = 0;
5839
5807 return p; 5840 return p;
5841
5842out_overflow:
5843 print_overflow_msg(__func__, xdr);
5844 return ERR_PTR(-EIO);
5808} 5845}
5809 5846
5810/* 5847/*