diff options
Diffstat (limited to 'fs/nfs/dir.c')
-rw-r--r-- | fs/nfs/dir.c | 162 |
1 files changed, 97 insertions, 65 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 07ac3847e562..f0a384e2ae63 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/mount.h> | 34 | #include <linux/mount.h> |
35 | #include <linux/sched.h> | 35 | #include <linux/sched.h> |
36 | #include <linux/vmalloc.h> | 36 | #include <linux/vmalloc.h> |
37 | #include <linux/kmemleak.h> | ||
37 | 38 | ||
38 | #include "delegation.h" | 39 | #include "delegation.h" |
39 | #include "iostat.h" | 40 | #include "iostat.h" |
@@ -161,6 +162,7 @@ struct nfs_cache_array_entry { | |||
161 | u64 cookie; | 162 | u64 cookie; |
162 | u64 ino; | 163 | u64 ino; |
163 | struct qstr string; | 164 | struct qstr string; |
165 | unsigned char d_type; | ||
164 | }; | 166 | }; |
165 | 167 | ||
166 | struct nfs_cache_array { | 168 | struct nfs_cache_array { |
@@ -170,8 +172,6 @@ struct nfs_cache_array { | |||
170 | struct nfs_cache_array_entry array[0]; | 172 | struct nfs_cache_array_entry array[0]; |
171 | }; | 173 | }; |
172 | 174 | ||
173 | #define MAX_READDIR_ARRAY ((PAGE_SIZE - sizeof(struct nfs_cache_array)) / sizeof(struct nfs_cache_array_entry)) | ||
174 | |||
175 | typedef __be32 * (*decode_dirent_t)(struct xdr_stream *, struct nfs_entry *, struct nfs_server *, int); | 175 | typedef __be32 * (*decode_dirent_t)(struct xdr_stream *, struct nfs_entry *, struct nfs_server *, int); |
176 | typedef struct { | 176 | typedef struct { |
177 | struct file *file; | 177 | struct file *file; |
@@ -194,9 +194,13 @@ typedef struct { | |||
194 | static | 194 | static |
195 | struct nfs_cache_array *nfs_readdir_get_array(struct page *page) | 195 | struct nfs_cache_array *nfs_readdir_get_array(struct page *page) |
196 | { | 196 | { |
197 | void *ptr; | ||
197 | if (page == NULL) | 198 | if (page == NULL) |
198 | return ERR_PTR(-EIO); | 199 | return ERR_PTR(-EIO); |
199 | return (struct nfs_cache_array *)kmap(page); | 200 | ptr = kmap(page); |
201 | if (ptr == NULL) | ||
202 | return ERR_PTR(-ENOMEM); | ||
203 | return ptr; | ||
200 | } | 204 | } |
201 | 205 | ||
202 | static | 206 | static |
@@ -213,6 +217,9 @@ int nfs_readdir_clear_array(struct page *page, gfp_t mask) | |||
213 | { | 217 | { |
214 | struct nfs_cache_array *array = nfs_readdir_get_array(page); | 218 | struct nfs_cache_array *array = nfs_readdir_get_array(page); |
215 | int i; | 219 | int i; |
220 | |||
221 | if (IS_ERR(array)) | ||
222 | return PTR_ERR(array); | ||
216 | for (i = 0; i < array->size; i++) | 223 | for (i = 0; i < array->size; i++) |
217 | kfree(array->array[i].string.name); | 224 | kfree(array->array[i].string.name); |
218 | nfs_readdir_release_array(page); | 225 | nfs_readdir_release_array(page); |
@@ -231,6 +238,11 @@ int nfs_readdir_make_qstr(struct qstr *string, const char *name, unsigned int le | |||
231 | string->name = kmemdup(name, len, GFP_KERNEL); | 238 | string->name = kmemdup(name, len, GFP_KERNEL); |
232 | if (string->name == NULL) | 239 | if (string->name == NULL) |
233 | return -ENOMEM; | 240 | return -ENOMEM; |
241 | /* | ||
242 | * Avoid a kmemleak false positive. The pointer to the name is stored | ||
243 | * in a page cache page which kmemleak does not scan. | ||
244 | */ | ||
245 | kmemleak_not_leak(string->name); | ||
234 | string->hash = full_name_hash(name, len); | 246 | string->hash = full_name_hash(name, len); |
235 | return 0; | 247 | return 0; |
236 | } | 248 | } |
@@ -244,20 +256,24 @@ int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page) | |||
244 | 256 | ||
245 | if (IS_ERR(array)) | 257 | if (IS_ERR(array)) |
246 | return PTR_ERR(array); | 258 | return PTR_ERR(array); |
247 | ret = -EIO; | ||
248 | if (array->size >= MAX_READDIR_ARRAY) | ||
249 | goto out; | ||
250 | 259 | ||
251 | cache_entry = &array->array[array->size]; | 260 | cache_entry = &array->array[array->size]; |
261 | |||
262 | /* Check that this entry lies within the page bounds */ | ||
263 | ret = -ENOSPC; | ||
264 | if ((char *)&cache_entry[1] - (char *)page_address(page) > PAGE_SIZE) | ||
265 | goto out; | ||
266 | |||
252 | cache_entry->cookie = entry->prev_cookie; | 267 | cache_entry->cookie = entry->prev_cookie; |
253 | cache_entry->ino = entry->ino; | 268 | cache_entry->ino = entry->ino; |
269 | cache_entry->d_type = entry->d_type; | ||
254 | ret = nfs_readdir_make_qstr(&cache_entry->string, entry->name, entry->len); | 270 | ret = nfs_readdir_make_qstr(&cache_entry->string, entry->name, entry->len); |
255 | if (ret) | 271 | if (ret) |
256 | goto out; | 272 | goto out; |
257 | array->last_cookie = entry->cookie; | 273 | array->last_cookie = entry->cookie; |
274 | array->size++; | ||
258 | if (entry->eof == 1) | 275 | if (entry->eof == 1) |
259 | array->eof_index = array->size; | 276 | array->eof_index = array->size; |
260 | array->size++; | ||
261 | out: | 277 | out: |
262 | nfs_readdir_release_array(page); | 278 | nfs_readdir_release_array(page); |
263 | return ret; | 279 | return ret; |
@@ -272,7 +288,7 @@ int nfs_readdir_search_for_pos(struct nfs_cache_array *array, nfs_readdir_descri | |||
272 | if (diff < 0) | 288 | if (diff < 0) |
273 | goto out_eof; | 289 | goto out_eof; |
274 | if (diff >= array->size) { | 290 | if (diff >= array->size) { |
275 | if (array->eof_index > 0) | 291 | if (array->eof_index >= 0) |
276 | goto out_eof; | 292 | goto out_eof; |
277 | desc->current_index += array->size; | 293 | desc->current_index += array->size; |
278 | return -EAGAIN; | 294 | return -EAGAIN; |
@@ -281,8 +297,6 @@ int nfs_readdir_search_for_pos(struct nfs_cache_array *array, nfs_readdir_descri | |||
281 | index = (unsigned int)diff; | 297 | index = (unsigned int)diff; |
282 | *desc->dir_cookie = array->array[index].cookie; | 298 | *desc->dir_cookie = array->array[index].cookie; |
283 | desc->cache_entry_index = index; | 299 | desc->cache_entry_index = index; |
284 | if (index == array->eof_index) | ||
285 | desc->eof = 1; | ||
286 | return 0; | 300 | return 0; |
287 | out_eof: | 301 | out_eof: |
288 | desc->eof = 1; | 302 | desc->eof = 1; |
@@ -296,17 +310,17 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des | |||
296 | int status = -EAGAIN; | 310 | int status = -EAGAIN; |
297 | 311 | ||
298 | for (i = 0; i < array->size; i++) { | 312 | for (i = 0; i < array->size; i++) { |
299 | if (i == array->eof_index) { | ||
300 | desc->eof = 1; | ||
301 | status = -EBADCOOKIE; | ||
302 | } | ||
303 | if (array->array[i].cookie == *desc->dir_cookie) { | 313 | if (array->array[i].cookie == *desc->dir_cookie) { |
304 | desc->cache_entry_index = i; | 314 | desc->cache_entry_index = i; |
305 | status = 0; | 315 | status = 0; |
306 | break; | 316 | goto out; |
307 | } | 317 | } |
308 | } | 318 | } |
309 | 319 | if (i == array->eof_index) { | |
320 | desc->eof = 1; | ||
321 | status = -EBADCOOKIE; | ||
322 | } | ||
323 | out: | ||
310 | return status; | 324 | return status; |
311 | } | 325 | } |
312 | 326 | ||
@@ -381,13 +395,9 @@ int xdr_decode(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry, struct x | |||
381 | static | 395 | static |
382 | int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry) | 396 | int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry) |
383 | { | 397 | { |
384 | struct nfs_inode *node; | ||
385 | if (dentry->d_inode == NULL) | 398 | if (dentry->d_inode == NULL) |
386 | goto different; | 399 | goto different; |
387 | node = NFS_I(dentry->d_inode); | 400 | if (nfs_compare_fh(entry->fh, NFS_FH(dentry->d_inode)) != 0) |
388 | if (node->fh.size != entry->fh->size) | ||
389 | goto different; | ||
390 | if (strncmp(node->fh.data, entry->fh->data, node->fh.size) != 0) | ||
391 | goto different; | 401 | goto different; |
392 | return 1; | 402 | return 1; |
393 | different: | 403 | different: |
@@ -449,14 +459,15 @@ out: | |||
449 | 459 | ||
450 | /* Perform conversion from xdr to cache array */ | 460 | /* Perform conversion from xdr to cache array */ |
451 | static | 461 | static |
452 | void nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry, | 462 | int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry, |
453 | void *xdr_page, struct page *page, unsigned int buflen) | 463 | void *xdr_page, struct page *page, unsigned int buflen) |
454 | { | 464 | { |
455 | struct xdr_stream stream; | 465 | struct xdr_stream stream; |
456 | struct xdr_buf buf; | 466 | struct xdr_buf buf; |
457 | __be32 *ptr = xdr_page; | 467 | __be32 *ptr = xdr_page; |
458 | int status; | ||
459 | struct nfs_cache_array *array; | 468 | struct nfs_cache_array *array; |
469 | unsigned int count = 0; | ||
470 | int status; | ||
460 | 471 | ||
461 | buf.head->iov_base = xdr_page; | 472 | buf.head->iov_base = xdr_page; |
462 | buf.head->iov_len = buflen; | 473 | buf.head->iov_len = buflen; |
@@ -471,21 +482,32 @@ void nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *e | |||
471 | 482 | ||
472 | do { | 483 | do { |
473 | status = xdr_decode(desc, entry, &stream); | 484 | status = xdr_decode(desc, entry, &stream); |
474 | if (status != 0) | 485 | if (status != 0) { |
486 | if (status == -EAGAIN) | ||
487 | status = 0; | ||
475 | break; | 488 | break; |
489 | } | ||
490 | |||
491 | count++; | ||
476 | 492 | ||
477 | if (nfs_readdir_add_to_array(entry, page) == -1) | ||
478 | break; | ||
479 | if (desc->plus == 1) | 493 | if (desc->plus == 1) |
480 | nfs_prime_dcache(desc->file->f_path.dentry, entry); | 494 | nfs_prime_dcache(desc->file->f_path.dentry, entry); |
495 | |||
496 | status = nfs_readdir_add_to_array(entry, page); | ||
497 | if (status != 0) | ||
498 | break; | ||
481 | } while (!entry->eof); | 499 | } while (!entry->eof); |
482 | 500 | ||
483 | if (status == -EBADCOOKIE && entry->eof) { | 501 | if (count == 0 || (status == -EBADCOOKIE && entry->eof == 1)) { |
484 | array = nfs_readdir_get_array(page); | 502 | array = nfs_readdir_get_array(page); |
485 | array->eof_index = array->size - 1; | 503 | if (!IS_ERR(array)) { |
486 | status = 0; | 504 | array->eof_index = array->size; |
487 | nfs_readdir_release_array(page); | 505 | status = 0; |
506 | nfs_readdir_release_array(page); | ||
507 | } else | ||
508 | status = PTR_ERR(array); | ||
488 | } | 509 | } |
510 | return status; | ||
489 | } | 511 | } |
490 | 512 | ||
491 | static | 513 | static |
@@ -537,7 +559,7 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, | |||
537 | struct nfs_entry entry; | 559 | struct nfs_entry entry; |
538 | struct file *file = desc->file; | 560 | struct file *file = desc->file; |
539 | struct nfs_cache_array *array; | 561 | struct nfs_cache_array *array; |
540 | int status = 0; | 562 | int status = -ENOMEM; |
541 | unsigned int array_size = ARRAY_SIZE(pages); | 563 | unsigned int array_size = ARRAY_SIZE(pages); |
542 | 564 | ||
543 | entry.prev_cookie = 0; | 565 | entry.prev_cookie = 0; |
@@ -549,6 +571,10 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, | |||
549 | goto out; | 571 | goto out; |
550 | 572 | ||
551 | array = nfs_readdir_get_array(page); | 573 | array = nfs_readdir_get_array(page); |
574 | if (IS_ERR(array)) { | ||
575 | status = PTR_ERR(array); | ||
576 | goto out; | ||
577 | } | ||
552 | memset(array, 0, sizeof(struct nfs_cache_array)); | 578 | memset(array, 0, sizeof(struct nfs_cache_array)); |
553 | array->eof_index = -1; | 579 | array->eof_index = -1; |
554 | 580 | ||
@@ -556,12 +582,19 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, | |||
556 | if (!pages_ptr) | 582 | if (!pages_ptr) |
557 | goto out_release_array; | 583 | goto out_release_array; |
558 | do { | 584 | do { |
585 | unsigned int pglen; | ||
559 | status = nfs_readdir_xdr_filler(pages, desc, &entry, file, inode); | 586 | status = nfs_readdir_xdr_filler(pages, desc, &entry, file, inode); |
560 | 587 | ||
561 | if (status < 0) | 588 | if (status < 0) |
562 | break; | 589 | break; |
563 | nfs_readdir_page_filler(desc, &entry, pages_ptr, page, array_size * PAGE_SIZE); | 590 | pglen = status; |
564 | } while (array->eof_index < 0 && array->size < MAX_READDIR_ARRAY); | 591 | status = nfs_readdir_page_filler(desc, &entry, pages_ptr, page, pglen); |
592 | if (status < 0) { | ||
593 | if (status == -ENOSPC) | ||
594 | status = 0; | ||
595 | break; | ||
596 | } | ||
597 | } while (array->eof_index < 0); | ||
565 | 598 | ||
566 | nfs_readdir_free_large_page(pages_ptr, pages, array_size); | 599 | nfs_readdir_free_large_page(pages_ptr, pages, array_size); |
567 | out_release_array: | 600 | out_release_array: |
@@ -582,8 +615,10 @@ static | |||
582 | int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page* page) | 615 | int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page* page) |
583 | { | 616 | { |
584 | struct inode *inode = desc->file->f_path.dentry->d_inode; | 617 | struct inode *inode = desc->file->f_path.dentry->d_inode; |
618 | int ret; | ||
585 | 619 | ||
586 | if (nfs_readdir_xdr_to_array(desc, page, inode) < 0) | 620 | ret = nfs_readdir_xdr_to_array(desc, page, inode); |
621 | if (ret < 0) | ||
587 | goto error; | 622 | goto error; |
588 | SetPageUptodate(page); | 623 | SetPageUptodate(page); |
589 | 624 | ||
@@ -595,7 +630,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page* page) | |||
595 | return 0; | 630 | return 0; |
596 | error: | 631 | error: |
597 | unlock_page(page); | 632 | unlock_page(page); |
598 | return -EIO; | 633 | return ret; |
599 | } | 634 | } |
600 | 635 | ||
601 | static | 636 | static |
@@ -608,12 +643,8 @@ void cache_page_release(nfs_readdir_descriptor_t *desc) | |||
608 | static | 643 | static |
609 | struct page *get_cache_page(nfs_readdir_descriptor_t *desc) | 644 | struct page *get_cache_page(nfs_readdir_descriptor_t *desc) |
610 | { | 645 | { |
611 | struct page *page; | 646 | return read_cache_page(desc->file->f_path.dentry->d_inode->i_mapping, |
612 | page = read_cache_page(desc->file->f_path.dentry->d_inode->i_mapping, | ||
613 | desc->page_index, (filler_t *)nfs_readdir_filler, desc); | 647 | desc->page_index, (filler_t *)nfs_readdir_filler, desc); |
614 | if (IS_ERR(page)) | ||
615 | desc->eof = 1; | ||
616 | return page; | ||
617 | } | 648 | } |
618 | 649 | ||
619 | /* | 650 | /* |
@@ -639,8 +670,10 @@ int find_cache_page(nfs_readdir_descriptor_t *desc) | |||
639 | static inline | 670 | static inline |
640 | int readdir_search_pagecache(nfs_readdir_descriptor_t *desc) | 671 | int readdir_search_pagecache(nfs_readdir_descriptor_t *desc) |
641 | { | 672 | { |
642 | int res = -EAGAIN; | 673 | int res; |
643 | 674 | ||
675 | if (desc->page_index == 0) | ||
676 | desc->current_index = 0; | ||
644 | while (1) { | 677 | while (1) { |
645 | res = find_cache_page(desc); | 678 | res = find_cache_page(desc); |
646 | if (res != -EAGAIN) | 679 | if (res != -EAGAIN) |
@@ -666,35 +699,36 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent, | |||
666 | int i = 0; | 699 | int i = 0; |
667 | int res = 0; | 700 | int res = 0; |
668 | struct nfs_cache_array *array = NULL; | 701 | struct nfs_cache_array *array = NULL; |
669 | unsigned int d_type = DT_UNKNOWN; | ||
670 | struct dentry *dentry = NULL; | ||
671 | 702 | ||
672 | array = nfs_readdir_get_array(desc->page); | 703 | array = nfs_readdir_get_array(desc->page); |
704 | if (IS_ERR(array)) { | ||
705 | res = PTR_ERR(array); | ||
706 | goto out; | ||
707 | } | ||
673 | 708 | ||
674 | for (i = desc->cache_entry_index; i < array->size; i++) { | 709 | for (i = desc->cache_entry_index; i < array->size; i++) { |
675 | d_type = DT_UNKNOWN; | 710 | struct nfs_cache_array_entry *ent; |
676 | 711 | ||
677 | res = filldir(dirent, array->array[i].string.name, | 712 | ent = &array->array[i]; |
678 | array->array[i].string.len, file->f_pos, | 713 | if (filldir(dirent, ent->string.name, ent->string.len, |
679 | nfs_compat_user_ino64(array->array[i].ino), d_type); | 714 | file->f_pos, nfs_compat_user_ino64(ent->ino), |
680 | if (res < 0) | 715 | ent->d_type) < 0) { |
716 | desc->eof = 1; | ||
681 | break; | 717 | break; |
718 | } | ||
682 | file->f_pos++; | 719 | file->f_pos++; |
683 | desc->cache_entry_index = i; | 720 | desc->cache_entry_index = i; |
684 | if (i < (array->size-1)) | 721 | if (i < (array->size-1)) |
685 | *desc->dir_cookie = array->array[i+1].cookie; | 722 | *desc->dir_cookie = array->array[i+1].cookie; |
686 | else | 723 | else |
687 | *desc->dir_cookie = array->last_cookie; | 724 | *desc->dir_cookie = array->last_cookie; |
688 | if (i == array->eof_index) { | ||
689 | desc->eof = 1; | ||
690 | break; | ||
691 | } | ||
692 | } | 725 | } |
726 | if (i == array->eof_index) | ||
727 | desc->eof = 1; | ||
693 | 728 | ||
694 | nfs_readdir_release_array(desc->page); | 729 | nfs_readdir_release_array(desc->page); |
730 | out: | ||
695 | cache_page_release(desc); | 731 | cache_page_release(desc); |
696 | if (dentry != NULL) | ||
697 | dput(dentry); | ||
698 | dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n", | 732 | dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n", |
699 | (unsigned long long)*desc->dir_cookie, res); | 733 | (unsigned long long)*desc->dir_cookie, res); |
700 | return res; | 734 | return res; |
@@ -729,13 +763,13 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, | |||
729 | goto out; | 763 | goto out; |
730 | } | 764 | } |
731 | 765 | ||
732 | if (nfs_readdir_xdr_to_array(desc, page, inode) == -1) { | ||
733 | status = -EIO; | ||
734 | goto out_release; | ||
735 | } | ||
736 | |||
737 | desc->page_index = 0; | 766 | desc->page_index = 0; |
738 | desc->page = page; | 767 | desc->page = page; |
768 | |||
769 | status = nfs_readdir_xdr_to_array(desc, page, inode); | ||
770 | if (status < 0) | ||
771 | goto out_release; | ||
772 | |||
739 | status = nfs_do_filldir(desc, dirent, filldir); | 773 | status = nfs_do_filldir(desc, dirent, filldir); |
740 | 774 | ||
741 | out: | 775 | out: |
@@ -786,14 +820,14 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
786 | res = readdir_search_pagecache(desc); | 820 | res = readdir_search_pagecache(desc); |
787 | 821 | ||
788 | if (res == -EBADCOOKIE) { | 822 | if (res == -EBADCOOKIE) { |
823 | res = 0; | ||
789 | /* This means either end of directory */ | 824 | /* This means either end of directory */ |
790 | if (*desc->dir_cookie && desc->eof == 0) { | 825 | if (*desc->dir_cookie && desc->eof == 0) { |
791 | /* Or that the server has 'lost' a cookie */ | 826 | /* Or that the server has 'lost' a cookie */ |
792 | res = uncached_readdir(desc, dirent, filldir); | 827 | res = uncached_readdir(desc, dirent, filldir); |
793 | if (res >= 0) | 828 | if (res == 0) |
794 | continue; | 829 | continue; |
795 | } | 830 | } |
796 | res = 0; | ||
797 | break; | 831 | break; |
798 | } | 832 | } |
799 | if (res == -ETOOSMALL && desc->plus) { | 833 | if (res == -ETOOSMALL && desc->plus) { |
@@ -808,10 +842,8 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
808 | break; | 842 | break; |
809 | 843 | ||
810 | res = nfs_do_filldir(desc, dirent, filldir); | 844 | res = nfs_do_filldir(desc, dirent, filldir); |
811 | if (res < 0) { | 845 | if (res < 0) |
812 | res = 0; | ||
813 | break; | 846 | break; |
814 | } | ||
815 | } | 847 | } |
816 | out: | 848 | out: |
817 | nfs_unblock_sillyrename(dentry); | 849 | nfs_unblock_sillyrename(dentry); |
@@ -1345,12 +1377,12 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry | |||
1345 | res = NULL; | 1377 | res = NULL; |
1346 | goto out; | 1378 | goto out; |
1347 | /* This turned out not to be a regular file */ | 1379 | /* This turned out not to be a regular file */ |
1348 | case -EISDIR: | ||
1349 | case -ENOTDIR: | 1380 | case -ENOTDIR: |
1350 | goto no_open; | 1381 | goto no_open; |
1351 | case -ELOOP: | 1382 | case -ELOOP: |
1352 | if (!(nd->intent.open.flags & O_NOFOLLOW)) | 1383 | if (!(nd->intent.open.flags & O_NOFOLLOW)) |
1353 | goto no_open; | 1384 | goto no_open; |
1385 | /* case -EISDIR: */ | ||
1354 | /* case -EINVAL: */ | 1386 | /* case -EINVAL: */ |
1355 | default: | 1387 | default: |
1356 | res = ERR_CAST(inode); | 1388 | res = ERR_CAST(inode); |