aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorSteve French <sfrench@hera.kernel.org>2005-06-09 17:44:56 -0400
committerSteve French <sfrench@hera.kernel.org>2005-06-09 17:44:56 -0400
commitf5d9b97ee0d6d00a29bf881263510d74291fb862 (patch)
tree90b22e6038da0ad40e54c3f52e8da67189730ae8 /fs
parent3079ca621e9e09f4593c20a9a2f24237c355f683 (diff)
parentcf380ee7308db0f067ceb2ae8b852838788bf453 (diff)
Merge with rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
Diffstat (limited to 'fs')
-rw-r--r--fs/binfmt_flat.c6
-rw-r--r--fs/namei.c153
-rw-r--r--fs/nfs/dir.c49
3 files changed, 124 insertions, 84 deletions
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index f0cd67d9d31b..c8998dc66882 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -520,7 +520,7 @@ static int load_flat_file(struct linux_binprm * bprm,
520 DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n"); 520 DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n");
521 521
522 down_write(&current->mm->mmap_sem); 522 down_write(&current->mm->mmap_sem);
523 textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC, 0, 0); 523 textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC, MAP_SHARED, 0);
524 up_write(&current->mm->mmap_sem); 524 up_write(&current->mm->mmap_sem);
525 if (!textpos || textpos >= (unsigned long) -4096) { 525 if (!textpos || textpos >= (unsigned long) -4096) {
526 if (!textpos) 526 if (!textpos)
@@ -532,7 +532,7 @@ static int load_flat_file(struct linux_binprm * bprm,
532 down_write(&current->mm->mmap_sem); 532 down_write(&current->mm->mmap_sem);
533 realdatastart = do_mmap(0, 0, data_len + extra + 533 realdatastart = do_mmap(0, 0, data_len + extra +
534 MAX_SHARED_LIBS * sizeof(unsigned long), 534 MAX_SHARED_LIBS * sizeof(unsigned long),
535 PROT_READ|PROT_WRITE|PROT_EXEC, 0, 0); 535 PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0);
536 up_write(&current->mm->mmap_sem); 536 up_write(&current->mm->mmap_sem);
537 537
538 if (realdatastart == 0 || realdatastart >= (unsigned long)-4096) { 538 if (realdatastart == 0 || realdatastart >= (unsigned long)-4096) {
@@ -574,7 +574,7 @@ static int load_flat_file(struct linux_binprm * bprm,
574 down_write(&current->mm->mmap_sem); 574 down_write(&current->mm->mmap_sem);
575 textpos = do_mmap(0, 0, text_len + data_len + extra + 575 textpos = do_mmap(0, 0, text_len + data_len + extra +
576 MAX_SHARED_LIBS * sizeof(unsigned long), 576 MAX_SHARED_LIBS * sizeof(unsigned long),
577 PROT_READ | PROT_EXEC | PROT_WRITE, 0, 0); 577 PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0);
578 up_write(&current->mm->mmap_sem); 578 up_write(&current->mm->mmap_sem);
579 if (!textpos || textpos >= (unsigned long) -4096) { 579 if (!textpos || textpos >= (unsigned long) -4096) {
580 if (!textpos) 580 if (!textpos)
diff --git a/fs/namei.c b/fs/namei.c
index dd78f01b6de8..a7f7f44119b3 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -493,12 +493,21 @@ fail:
493 return PTR_ERR(link); 493 return PTR_ERR(link);
494} 494}
495 495
496static inline int __do_follow_link(struct dentry *dentry, struct nameidata *nd) 496struct path {
497 struct vfsmount *mnt;
498 struct dentry *dentry;
499};
500
501static inline int __do_follow_link(struct path *path, struct nameidata *nd)
497{ 502{
498 int error; 503 int error;
504 struct dentry *dentry = path->dentry;
499 505
500 touch_atime(nd->mnt, dentry); 506 touch_atime(path->mnt, dentry);
501 nd_set_link(nd, NULL); 507 nd_set_link(nd, NULL);
508
509 if (path->mnt == nd->mnt)
510 mntget(path->mnt);
502 error = dentry->d_inode->i_op->follow_link(dentry, nd); 511 error = dentry->d_inode->i_op->follow_link(dentry, nd);
503 if (!error) { 512 if (!error) {
504 char *s = nd_get_link(nd); 513 char *s = nd_get_link(nd);
@@ -507,6 +516,8 @@ static inline int __do_follow_link(struct dentry *dentry, struct nameidata *nd)
507 if (dentry->d_inode->i_op->put_link) 516 if (dentry->d_inode->i_op->put_link)
508 dentry->d_inode->i_op->put_link(dentry, nd); 517 dentry->d_inode->i_op->put_link(dentry, nd);
509 } 518 }
519 dput(dentry);
520 mntput(path->mnt);
510 521
511 return error; 522 return error;
512} 523}
@@ -518,7 +529,7 @@ static inline int __do_follow_link(struct dentry *dentry, struct nameidata *nd)
518 * Without that kind of total limit, nasty chains of consecutive 529 * Without that kind of total limit, nasty chains of consecutive
519 * symlinks can cause almost arbitrarily long lookups. 530 * symlinks can cause almost arbitrarily long lookups.
520 */ 531 */
521static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd) 532static inline int do_follow_link(struct path *path, struct nameidata *nd)
522{ 533{
523 int err = -ELOOP; 534 int err = -ELOOP;
524 if (current->link_count >= MAX_NESTED_LINKS) 535 if (current->link_count >= MAX_NESTED_LINKS)
@@ -527,17 +538,20 @@ static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd)
527 goto loop; 538 goto loop;
528 BUG_ON(nd->depth >= MAX_NESTED_LINKS); 539 BUG_ON(nd->depth >= MAX_NESTED_LINKS);
529 cond_resched(); 540 cond_resched();
530 err = security_inode_follow_link(dentry, nd); 541 err = security_inode_follow_link(path->dentry, nd);
531 if (err) 542 if (err)
532 goto loop; 543 goto loop;
533 current->link_count++; 544 current->link_count++;
534 current->total_link_count++; 545 current->total_link_count++;
535 nd->depth++; 546 nd->depth++;
536 err = __do_follow_link(dentry, nd); 547 err = __do_follow_link(path, nd);
537 current->link_count--; 548 current->link_count--;
538 nd->depth--; 549 nd->depth--;
539 return err; 550 return err;
540loop: 551loop:
552 dput(path->dentry);
553 if (path->mnt != nd->mnt)
554 mntput(path->mnt);
541 path_release(nd); 555 path_release(nd);
542 return err; 556 return err;
543} 557}
@@ -565,87 +579,91 @@ int follow_up(struct vfsmount **mnt, struct dentry **dentry)
565/* no need for dcache_lock, as serialization is taken care in 579/* no need for dcache_lock, as serialization is taken care in
566 * namespace.c 580 * namespace.c
567 */ 581 */
568static int follow_mount(struct vfsmount **mnt, struct dentry **dentry) 582static int __follow_mount(struct path *path)
569{ 583{
570 int res = 0; 584 int res = 0;
585 while (d_mountpoint(path->dentry)) {
586 struct vfsmount *mounted = lookup_mnt(path->mnt, path->dentry);
587 if (!mounted)
588 break;
589 dput(path->dentry);
590 if (res)
591 mntput(path->mnt);
592 path->mnt = mounted;
593 path->dentry = dget(mounted->mnt_root);
594 res = 1;
595 }
596 return res;
597}
598
599static void follow_mount(struct vfsmount **mnt, struct dentry **dentry)
600{
571 while (d_mountpoint(*dentry)) { 601 while (d_mountpoint(*dentry)) {
572 struct vfsmount *mounted = lookup_mnt(*mnt, *dentry); 602 struct vfsmount *mounted = lookup_mnt(*mnt, *dentry);
573 if (!mounted) 603 if (!mounted)
574 break; 604 break;
605 dput(*dentry);
575 mntput(*mnt); 606 mntput(*mnt);
576 *mnt = mounted; 607 *mnt = mounted;
577 dput(*dentry);
578 *dentry = dget(mounted->mnt_root); 608 *dentry = dget(mounted->mnt_root);
579 res = 1;
580 } 609 }
581 return res;
582} 610}
583 611
584/* no need for dcache_lock, as serialization is taken care in 612/* no need for dcache_lock, as serialization is taken care in
585 * namespace.c 613 * namespace.c
586 */ 614 */
587static inline int __follow_down(struct vfsmount **mnt, struct dentry **dentry) 615int follow_down(struct vfsmount **mnt, struct dentry **dentry)
588{ 616{
589 struct vfsmount *mounted; 617 struct vfsmount *mounted;
590 618
591 mounted = lookup_mnt(*mnt, *dentry); 619 mounted = lookup_mnt(*mnt, *dentry);
592 if (mounted) { 620 if (mounted) {
621 dput(*dentry);
593 mntput(*mnt); 622 mntput(*mnt);
594 *mnt = mounted; 623 *mnt = mounted;
595 dput(*dentry);
596 *dentry = dget(mounted->mnt_root); 624 *dentry = dget(mounted->mnt_root);
597 return 1; 625 return 1;
598 } 626 }
599 return 0; 627 return 0;
600} 628}
601 629
602int follow_down(struct vfsmount **mnt, struct dentry **dentry) 630static inline void follow_dotdot(struct nameidata *nd)
603{
604 return __follow_down(mnt,dentry);
605}
606
607static inline void follow_dotdot(struct vfsmount **mnt, struct dentry **dentry)
608{ 631{
609 while(1) { 632 while(1) {
610 struct vfsmount *parent; 633 struct vfsmount *parent;
611 struct dentry *old = *dentry; 634 struct dentry *old = nd->dentry;
612 635
613 read_lock(&current->fs->lock); 636 read_lock(&current->fs->lock);
614 if (*dentry == current->fs->root && 637 if (nd->dentry == current->fs->root &&
615 *mnt == current->fs->rootmnt) { 638 nd->mnt == current->fs->rootmnt) {
616 read_unlock(&current->fs->lock); 639 read_unlock(&current->fs->lock);
617 break; 640 break;
618 } 641 }
619 read_unlock(&current->fs->lock); 642 read_unlock(&current->fs->lock);
620 spin_lock(&dcache_lock); 643 spin_lock(&dcache_lock);
621 if (*dentry != (*mnt)->mnt_root) { 644 if (nd->dentry != nd->mnt->mnt_root) {
622 *dentry = dget((*dentry)->d_parent); 645 nd->dentry = dget(nd->dentry->d_parent);
623 spin_unlock(&dcache_lock); 646 spin_unlock(&dcache_lock);
624 dput(old); 647 dput(old);
625 break; 648 break;
626 } 649 }
627 spin_unlock(&dcache_lock); 650 spin_unlock(&dcache_lock);
628 spin_lock(&vfsmount_lock); 651 spin_lock(&vfsmount_lock);
629 parent = (*mnt)->mnt_parent; 652 parent = nd->mnt->mnt_parent;
630 if (parent == *mnt) { 653 if (parent == nd->mnt) {
631 spin_unlock(&vfsmount_lock); 654 spin_unlock(&vfsmount_lock);
632 break; 655 break;
633 } 656 }
634 mntget(parent); 657 mntget(parent);
635 *dentry = dget((*mnt)->mnt_mountpoint); 658 nd->dentry = dget(nd->mnt->mnt_mountpoint);
636 spin_unlock(&vfsmount_lock); 659 spin_unlock(&vfsmount_lock);
637 dput(old); 660 dput(old);
638 mntput(*mnt); 661 mntput(nd->mnt);
639 *mnt = parent; 662 nd->mnt = parent;
640 } 663 }
641 follow_mount(mnt, dentry); 664 follow_mount(&nd->mnt, &nd->dentry);
642} 665}
643 666
644struct path {
645 struct vfsmount *mnt;
646 struct dentry *dentry;
647};
648
649/* 667/*
650 * It's more convoluted than I'd like it to be, but... it's still fairly 668 * It's more convoluted than I'd like it to be, but... it's still fairly
651 * small and for now I'd prefer to have fast path as straight as possible. 669 * small and for now I'd prefer to have fast path as straight as possible.
@@ -664,6 +682,7 @@ static int do_lookup(struct nameidata *nd, struct qstr *name,
664done: 682done:
665 path->mnt = mnt; 683 path->mnt = mnt;
666 path->dentry = dentry; 684 path->dentry = dentry;
685 __follow_mount(path);
667 return 0; 686 return 0;
668 687
669need_lookup: 688need_lookup:
@@ -751,7 +770,7 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
751 case 2: 770 case 2:
752 if (this.name[1] != '.') 771 if (this.name[1] != '.')
753 break; 772 break;
754 follow_dotdot(&nd->mnt, &nd->dentry); 773 follow_dotdot(nd);
755 inode = nd->dentry->d_inode; 774 inode = nd->dentry->d_inode;
756 /* fallthrough */ 775 /* fallthrough */
757 case 1: 776 case 1:
@@ -771,8 +790,6 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
771 err = do_lookup(nd, &this, &next); 790 err = do_lookup(nd, &this, &next);
772 if (err) 791 if (err)
773 break; 792 break;
774 /* Check mountpoints.. */
775 follow_mount(&next.mnt, &next.dentry);
776 793
777 err = -ENOENT; 794 err = -ENOENT;
778 inode = next.dentry->d_inode; 795 inode = next.dentry->d_inode;
@@ -783,10 +800,7 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
783 goto out_dput; 800 goto out_dput;
784 801
785 if (inode->i_op->follow_link) { 802 if (inode->i_op->follow_link) {
786 mntget(next.mnt); 803 err = do_follow_link(&next, nd);
787 err = do_follow_link(next.dentry, nd);
788 dput(next.dentry);
789 mntput(next.mnt);
790 if (err) 804 if (err)
791 goto return_err; 805 goto return_err;
792 err = -ENOENT; 806 err = -ENOENT;
@@ -798,6 +812,8 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
798 break; 812 break;
799 } else { 813 } else {
800 dput(nd->dentry); 814 dput(nd->dentry);
815 if (nd->mnt != next.mnt)
816 mntput(nd->mnt);
801 nd->mnt = next.mnt; 817 nd->mnt = next.mnt;
802 nd->dentry = next.dentry; 818 nd->dentry = next.dentry;
803 } 819 }
@@ -819,7 +835,7 @@ last_component:
819 case 2: 835 case 2:
820 if (this.name[1] != '.') 836 if (this.name[1] != '.')
821 break; 837 break;
822 follow_dotdot(&nd->mnt, &nd->dentry); 838 follow_dotdot(nd);
823 inode = nd->dentry->d_inode; 839 inode = nd->dentry->d_inode;
824 /* fallthrough */ 840 /* fallthrough */
825 case 1: 841 case 1:
@@ -833,19 +849,17 @@ last_component:
833 err = do_lookup(nd, &this, &next); 849 err = do_lookup(nd, &this, &next);
834 if (err) 850 if (err)
835 break; 851 break;
836 follow_mount(&next.mnt, &next.dentry);
837 inode = next.dentry->d_inode; 852 inode = next.dentry->d_inode;
838 if ((lookup_flags & LOOKUP_FOLLOW) 853 if ((lookup_flags & LOOKUP_FOLLOW)
839 && inode && inode->i_op && inode->i_op->follow_link) { 854 && inode && inode->i_op && inode->i_op->follow_link) {
840 mntget(next.mnt); 855 err = do_follow_link(&next, nd);
841 err = do_follow_link(next.dentry, nd);
842 dput(next.dentry);
843 mntput(next.mnt);
844 if (err) 856 if (err)
845 goto return_err; 857 goto return_err;
846 inode = nd->dentry->d_inode; 858 inode = nd->dentry->d_inode;
847 } else { 859 } else {
848 dput(nd->dentry); 860 dput(nd->dentry);
861 if (nd->mnt != next.mnt)
862 mntput(nd->mnt);
849 nd->mnt = next.mnt; 863 nd->mnt = next.mnt;
850 nd->dentry = next.dentry; 864 nd->dentry = next.dentry;
851 } 865 }
@@ -885,6 +899,8 @@ return_base:
885 return 0; 899 return 0;
886out_dput: 900out_dput:
887 dput(next.dentry); 901 dput(next.dentry);
902 if (nd->mnt != next.mnt)
903 mntput(next.mnt);
888 break; 904 break;
889 } 905 }
890 path_release(nd); 906 path_release(nd);
@@ -1398,7 +1414,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
1398int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) 1414int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
1399{ 1415{
1400 int acc_mode, error = 0; 1416 int acc_mode, error = 0;
1401 struct dentry *dentry; 1417 struct path path;
1402 struct dentry *dir; 1418 struct dentry *dir;
1403 int count = 0; 1419 int count = 0;
1404 1420
@@ -1442,23 +1458,24 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
1442 dir = nd->dentry; 1458 dir = nd->dentry;
1443 nd->flags &= ~LOOKUP_PARENT; 1459 nd->flags &= ~LOOKUP_PARENT;
1444 down(&dir->d_inode->i_sem); 1460 down(&dir->d_inode->i_sem);
1445 dentry = __lookup_hash(&nd->last, nd->dentry, nd); 1461 path.dentry = __lookup_hash(&nd->last, nd->dentry, nd);
1462 path.mnt = nd->mnt;
1446 1463
1447do_last: 1464do_last:
1448 error = PTR_ERR(dentry); 1465 error = PTR_ERR(path.dentry);
1449 if (IS_ERR(dentry)) { 1466 if (IS_ERR(path.dentry)) {
1450 up(&dir->d_inode->i_sem); 1467 up(&dir->d_inode->i_sem);
1451 goto exit; 1468 goto exit;
1452 } 1469 }
1453 1470
1454 /* Negative dentry, just create the file */ 1471 /* Negative dentry, just create the file */
1455 if (!dentry->d_inode) { 1472 if (!path.dentry->d_inode) {
1456 if (!IS_POSIXACL(dir->d_inode)) 1473 if (!IS_POSIXACL(dir->d_inode))
1457 mode &= ~current->fs->umask; 1474 mode &= ~current->fs->umask;
1458 error = vfs_create(dir->d_inode, dentry, mode, nd); 1475 error = vfs_create(dir->d_inode, path.dentry, mode, nd);
1459 up(&dir->d_inode->i_sem); 1476 up(&dir->d_inode->i_sem);
1460 dput(nd->dentry); 1477 dput(nd->dentry);
1461 nd->dentry = dentry; 1478 nd->dentry = path.dentry;
1462 if (error) 1479 if (error)
1463 goto exit; 1480 goto exit;
1464 /* Don't check for write permission, don't truncate */ 1481 /* Don't check for write permission, don't truncate */
@@ -1476,22 +1493,24 @@ do_last:
1476 if (flag & O_EXCL) 1493 if (flag & O_EXCL)
1477 goto exit_dput; 1494 goto exit_dput;
1478 1495
1479 if (d_mountpoint(dentry)) { 1496 if (__follow_mount(&path)) {
1480 error = -ELOOP; 1497 error = -ELOOP;
1481 if (flag & O_NOFOLLOW) 1498 if (flag & O_NOFOLLOW)
1482 goto exit_dput; 1499 goto exit_dput;
1483 while (__follow_down(&nd->mnt,&dentry) && d_mountpoint(dentry));
1484 } 1500 }
1485 error = -ENOENT; 1501 error = -ENOENT;
1486 if (!dentry->d_inode) 1502 if (!path.dentry->d_inode)
1487 goto exit_dput; 1503 goto exit_dput;
1488 if (dentry->d_inode->i_op && dentry->d_inode->i_op->follow_link) 1504 if (path.dentry->d_inode->i_op && path.dentry->d_inode->i_op->follow_link)
1489 goto do_link; 1505 goto do_link;
1490 1506
1491 dput(nd->dentry); 1507 dput(nd->dentry);
1492 nd->dentry = dentry; 1508 nd->dentry = path.dentry;
1509 if (nd->mnt != path.mnt)
1510 mntput(nd->mnt);
1511 nd->mnt = path.mnt;
1493 error = -EISDIR; 1512 error = -EISDIR;
1494 if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) 1513 if (path.dentry->d_inode && S_ISDIR(path.dentry->d_inode->i_mode))
1495 goto exit; 1514 goto exit;
1496ok: 1515ok:
1497 error = may_open(nd, acc_mode, flag); 1516 error = may_open(nd, acc_mode, flag);
@@ -1500,7 +1519,9 @@ ok:
1500 return 0; 1519 return 0;
1501 1520
1502exit_dput: 1521exit_dput:
1503 dput(dentry); 1522 dput(path.dentry);
1523 if (nd->mnt != path.mnt)
1524 mntput(path.mnt);
1504exit: 1525exit:
1505 path_release(nd); 1526 path_release(nd);
1506 return error; 1527 return error;
@@ -1520,18 +1541,15 @@ do_link:
1520 * are done. Procfs-like symlinks just set LAST_BIND. 1541 * are done. Procfs-like symlinks just set LAST_BIND.
1521 */ 1542 */
1522 nd->flags |= LOOKUP_PARENT; 1543 nd->flags |= LOOKUP_PARENT;
1523 error = security_inode_follow_link(dentry, nd); 1544 error = security_inode_follow_link(path.dentry, nd);
1524 if (error) 1545 if (error)
1525 goto exit_dput; 1546 goto exit_dput;
1526 error = __do_follow_link(dentry, nd); 1547 error = __do_follow_link(&path, nd);
1527 dput(dentry);
1528 if (error) 1548 if (error)
1529 return error; 1549 return error;
1530 nd->flags &= ~LOOKUP_PARENT; 1550 nd->flags &= ~LOOKUP_PARENT;
1531 if (nd->last_type == LAST_BIND) { 1551 if (nd->last_type == LAST_BIND)
1532 dentry = nd->dentry;
1533 goto ok; 1552 goto ok;
1534 }
1535 error = -EISDIR; 1553 error = -EISDIR;
1536 if (nd->last_type != LAST_NORM) 1554 if (nd->last_type != LAST_NORM)
1537 goto exit; 1555 goto exit;
@@ -1546,7 +1564,8 @@ do_link:
1546 } 1564 }
1547 dir = nd->dentry; 1565 dir = nd->dentry;
1548 down(&dir->d_inode->i_sem); 1566 down(&dir->d_inode->i_sem);
1549 dentry = __lookup_hash(&nd->last, nd->dentry, nd); 1567 path.dentry = __lookup_hash(&nd->last, nd->dentry, nd);
1568 path.mnt = nd->mnt;
1550 putname(nd->last.name); 1569 putname(nd->last.name);
1551 goto do_last; 1570 goto do_last;
1552} 1571}
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 73f96acd5d37..ff6155f5e8d9 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -528,19 +528,39 @@ static inline void nfs_renew_times(struct dentry * dentry)
528 dentry->d_time = jiffies; 528 dentry->d_time = jiffies;
529} 529}
530 530
531/*
532 * Return the intent data that applies to this particular path component
533 *
534 * Note that the current set of intents only apply to the very last
535 * component of the path.
536 * We check for this using LOOKUP_CONTINUE and LOOKUP_PARENT.
537 */
538static inline unsigned int nfs_lookup_check_intent(struct nameidata *nd, unsigned int mask)
539{
540 if (nd->flags & (LOOKUP_CONTINUE|LOOKUP_PARENT))
541 return 0;
542 return nd->flags & mask;
543}
544
545/*
546 * Inode and filehandle revalidation for lookups.
547 *
548 * We force revalidation in the cases where the VFS sets LOOKUP_REVAL,
549 * or if the intent information indicates that we're about to open this
550 * particular file and the "nocto" mount flag is not set.
551 *
552 */
531static inline 553static inline
532int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd) 554int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd)
533{ 555{
534 struct nfs_server *server = NFS_SERVER(inode); 556 struct nfs_server *server = NFS_SERVER(inode);
535 557
536 if (nd != NULL) { 558 if (nd != NULL) {
537 int ndflags = nd->flags;
538 /* VFS wants an on-the-wire revalidation */ 559 /* VFS wants an on-the-wire revalidation */
539 if (ndflags & LOOKUP_REVAL) 560 if (nd->flags & LOOKUP_REVAL)
540 goto out_force; 561 goto out_force;
541 /* This is an open(2) */ 562 /* This is an open(2) */
542 if ((ndflags & LOOKUP_OPEN) && 563 if (nfs_lookup_check_intent(nd, LOOKUP_OPEN) != 0 &&
543 !(ndflags & LOOKUP_CONTINUE) &&
544 !(server->flags & NFS_MOUNT_NOCTO)) 564 !(server->flags & NFS_MOUNT_NOCTO))
545 goto out_force; 565 goto out_force;
546 } 566 }
@@ -560,12 +580,8 @@ static inline
560int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry, 580int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry,
561 struct nameidata *nd) 581 struct nameidata *nd)
562{ 582{
563 int ndflags = 0;
564
565 if (nd)
566 ndflags = nd->flags;
567 /* Don't revalidate a negative dentry if we're creating a new file */ 583 /* Don't revalidate a negative dentry if we're creating a new file */
568 if ((ndflags & LOOKUP_CREATE) && !(ndflags & LOOKUP_CONTINUE)) 584 if (nd != NULL && nfs_lookup_check_intent(nd, LOOKUP_CREATE) != 0)
569 return 0; 585 return 0;
570 return !nfs_check_verifier(dir, dentry); 586 return !nfs_check_verifier(dir, dentry);
571} 587}
@@ -700,12 +716,16 @@ struct dentry_operations nfs_dentry_operations = {
700 .d_iput = nfs_dentry_iput, 716 .d_iput = nfs_dentry_iput,
701}; 717};
702 718
719/*
720 * Use intent information to check whether or not we're going to do
721 * an O_EXCL create using this path component.
722 */
703static inline 723static inline
704int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd) 724int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd)
705{ 725{
706 if (NFS_PROTO(dir)->version == 2) 726 if (NFS_PROTO(dir)->version == 2)
707 return 0; 727 return 0;
708 if (!nd || (nd->flags & LOOKUP_CONTINUE) || !(nd->flags & LOOKUP_CREATE)) 728 if (nd == NULL || nfs_lookup_check_intent(nd, LOOKUP_CREATE) == 0)
709 return 0; 729 return 0;
710 return (nd->intent.open.flags & O_EXCL) != 0; 730 return (nd->intent.open.flags & O_EXCL) != 0;
711} 731}
@@ -772,12 +792,13 @@ struct dentry_operations nfs4_dentry_operations = {
772 .d_iput = nfs_dentry_iput, 792 .d_iput = nfs_dentry_iput,
773}; 793};
774 794
795/*
796 * Use intent information to determine whether we need to substitute
797 * the NFSv4-style stateful OPEN for the LOOKUP call
798 */
775static int is_atomic_open(struct inode *dir, struct nameidata *nd) 799static int is_atomic_open(struct inode *dir, struct nameidata *nd)
776{ 800{
777 if (!nd) 801 if (nd == NULL || nfs_lookup_check_intent(nd, LOOKUP_OPEN) == 0)
778 return 0;
779 /* Check that we are indeed trying to open this file */
780 if ((nd->flags & LOOKUP_CONTINUE) || !(nd->flags & LOOKUP_OPEN))
781 return 0; 802 return 0;
782 /* NFS does not (yet) have a stateful open for directories */ 803 /* NFS does not (yet) have a stateful open for directories */
783 if (nd->flags & LOOKUP_DIRECTORY) 804 if (nd->flags & LOOKUP_DIRECTORY)