| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved |
|---|
| 3 | 4 | * Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org> |
|---|
| 4 | 5 | * Copyright 2001-2006 Ian Kent <raven@themaw.net> |
|---|
| 5 | | - * |
|---|
| 6 | | - * This file is part of the Linux kernel and is made available under |
|---|
| 7 | | - * the terms of the GNU General Public License, version 2, or at your |
|---|
| 8 | | - * option, any later version, incorporated herein by reference. |
|---|
| 9 | 6 | */ |
|---|
| 10 | 7 | |
|---|
| 11 | 8 | #include <linux/capability.h> |
|---|
| .. | .. |
|---|
| 63 | 60 | .d_release = autofs_dentry_release, |
|---|
| 64 | 61 | }; |
|---|
| 65 | 62 | |
|---|
| 66 | | -static void autofs_add_active(struct dentry *dentry) |
|---|
| 67 | | -{ |
|---|
| 68 | | - struct autofs_sb_info *sbi = autofs_sbi(dentry->d_sb); |
|---|
| 69 | | - struct autofs_info *ino; |
|---|
| 70 | | - |
|---|
| 71 | | - ino = autofs_dentry_ino(dentry); |
|---|
| 72 | | - if (ino) { |
|---|
| 73 | | - spin_lock(&sbi->lookup_lock); |
|---|
| 74 | | - if (!ino->active_count) { |
|---|
| 75 | | - if (list_empty(&ino->active)) |
|---|
| 76 | | - list_add(&ino->active, &sbi->active_list); |
|---|
| 77 | | - } |
|---|
| 78 | | - ino->active_count++; |
|---|
| 79 | | - spin_unlock(&sbi->lookup_lock); |
|---|
| 80 | | - } |
|---|
| 81 | | -} |
|---|
| 82 | | - |
|---|
| 83 | 63 | static void autofs_del_active(struct dentry *dentry) |
|---|
| 84 | 64 | { |
|---|
| 85 | 65 | struct autofs_sb_info *sbi = autofs_sbi(dentry->d_sb); |
|---|
| 86 | 66 | struct autofs_info *ino; |
|---|
| 87 | 67 | |
|---|
| 88 | 68 | ino = autofs_dentry_ino(dentry); |
|---|
| 89 | | - if (ino) { |
|---|
| 90 | | - spin_lock(&sbi->lookup_lock); |
|---|
| 91 | | - ino->active_count--; |
|---|
| 92 | | - if (!ino->active_count) { |
|---|
| 93 | | - if (!list_empty(&ino->active)) |
|---|
| 94 | | - list_del_init(&ino->active); |
|---|
| 95 | | - } |
|---|
| 96 | | - spin_unlock(&sbi->lookup_lock); |
|---|
| 97 | | - } |
|---|
| 69 | + spin_lock(&sbi->lookup_lock); |
|---|
| 70 | + list_del_init(&ino->active); |
|---|
| 71 | + spin_unlock(&sbi->lookup_lock); |
|---|
| 98 | 72 | } |
|---|
| 99 | 73 | |
|---|
| 100 | 74 | static int autofs_dir_open(struct inode *inode, struct file *file) |
|---|
| .. | .. |
|---|
| 275 | 249 | pr_debug("waiting for mount name=%pd\n", path->dentry); |
|---|
| 276 | 250 | status = autofs_wait(sbi, path, NFY_MOUNT); |
|---|
| 277 | 251 | pr_debug("mount wait done status=%d\n", status); |
|---|
| 252 | + ino->last_used = jiffies; |
|---|
| 253 | + return status; |
|---|
| 278 | 254 | } |
|---|
| 279 | | - ino->last_used = jiffies; |
|---|
| 255 | + if (!(sbi->flags & AUTOFS_SBI_STRICTEXPIRE)) |
|---|
| 256 | + ino->last_used = jiffies; |
|---|
| 280 | 257 | return status; |
|---|
| 281 | 258 | } |
|---|
| 282 | 259 | |
|---|
| .. | .. |
|---|
| 510 | 487 | sbi = autofs_sbi(dir->i_sb); |
|---|
| 511 | 488 | |
|---|
| 512 | 489 | pr_debug("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d\n", |
|---|
| 513 | | - current->pid, task_pgrp_nr(current), sbi->catatonic, |
|---|
| 490 | + current->pid, task_pgrp_nr(current), |
|---|
| 491 | + sbi->flags & AUTOFS_SBI_CATATONIC, |
|---|
| 514 | 492 | autofs_oz_mode(sbi)); |
|---|
| 515 | 493 | |
|---|
| 516 | 494 | active = autofs_lookup_active(dentry); |
|---|
| .. | .. |
|---|
| 526 | 504 | if (!autofs_oz_mode(sbi) && !IS_ROOT(dentry->d_parent)) |
|---|
| 527 | 505 | return ERR_PTR(-ENOENT); |
|---|
| 528 | 506 | |
|---|
| 529 | | - /* Mark entries in the root as mount triggers */ |
|---|
| 530 | | - if (IS_ROOT(dentry->d_parent) && |
|---|
| 531 | | - autofs_type_indirect(sbi->type)) |
|---|
| 532 | | - __managed_dentry_set_managed(dentry); |
|---|
| 533 | | - |
|---|
| 534 | 507 | ino = autofs_new_ino(sbi); |
|---|
| 535 | 508 | if (!ino) |
|---|
| 536 | 509 | return ERR_PTR(-ENOMEM); |
|---|
| 537 | 510 | |
|---|
| 511 | + spin_lock(&sbi->lookup_lock); |
|---|
| 512 | + spin_lock(&dentry->d_lock); |
|---|
| 513 | + /* Mark entries in the root as mount triggers */ |
|---|
| 514 | + if (IS_ROOT(dentry->d_parent) && |
|---|
| 515 | + autofs_type_indirect(sbi->type)) |
|---|
| 516 | + __managed_dentry_set_managed(dentry); |
|---|
| 538 | 517 | dentry->d_fsdata = ino; |
|---|
| 539 | 518 | ino->dentry = dentry; |
|---|
| 540 | 519 | |
|---|
| 541 | | - autofs_add_active(dentry); |
|---|
| 520 | + list_add(&ino->active, &sbi->active_list); |
|---|
| 521 | + spin_unlock(&sbi->lookup_lock); |
|---|
| 522 | + spin_unlock(&dentry->d_lock); |
|---|
| 542 | 523 | } |
|---|
| 543 | 524 | return NULL; |
|---|
| 544 | 525 | } |
|---|
| .. | .. |
|---|
| 563 | 544 | * autofs mount is catatonic but the state of an autofs |
|---|
| 564 | 545 | * file system needs to be preserved over restarts. |
|---|
| 565 | 546 | */ |
|---|
| 566 | | - if (sbi->catatonic) |
|---|
| 547 | + if (sbi->flags & AUTOFS_SBI_CATATONIC) |
|---|
| 567 | 548 | return -EACCES; |
|---|
| 568 | 549 | |
|---|
| 569 | 550 | BUG_ON(!ino); |
|---|
| .. | .. |
|---|
| 588 | 569 | d_add(dentry, inode); |
|---|
| 589 | 570 | |
|---|
| 590 | 571 | dget(dentry); |
|---|
| 591 | | - atomic_inc(&ino->count); |
|---|
| 572 | + ino->count++; |
|---|
| 592 | 573 | p_ino = autofs_dentry_ino(dentry->d_parent); |
|---|
| 593 | | - if (p_ino && !IS_ROOT(dentry)) |
|---|
| 594 | | - atomic_inc(&p_ino->count); |
|---|
| 574 | + p_ino->count++; |
|---|
| 595 | 575 | |
|---|
| 596 | 576 | dir->i_mtime = current_time(dir); |
|---|
| 597 | 577 | |
|---|
| .. | .. |
|---|
| 626 | 606 | * autofs mount is catatonic but the state of an autofs |
|---|
| 627 | 607 | * file system needs to be preserved over restarts. |
|---|
| 628 | 608 | */ |
|---|
| 629 | | - if (sbi->catatonic) |
|---|
| 609 | + if (sbi->flags & AUTOFS_SBI_CATATONIC) |
|---|
| 630 | 610 | return -EACCES; |
|---|
| 631 | 611 | |
|---|
| 632 | | - if (atomic_dec_and_test(&ino->count)) { |
|---|
| 633 | | - p_ino = autofs_dentry_ino(dentry->d_parent); |
|---|
| 634 | | - if (p_ino && !IS_ROOT(dentry)) |
|---|
| 635 | | - atomic_dec(&p_ino->count); |
|---|
| 636 | | - } |
|---|
| 612 | + ino->count--; |
|---|
| 613 | + p_ino = autofs_dentry_ino(dentry->d_parent); |
|---|
| 614 | + p_ino->count--; |
|---|
| 637 | 615 | dput(ino->dentry); |
|---|
| 638 | 616 | |
|---|
| 639 | 617 | d_inode(dentry)->i_size = 0; |
|---|
| .. | .. |
|---|
| 679 | 657 | |
|---|
| 680 | 658 | static void autofs_clear_leaf_automount_flags(struct dentry *dentry) |
|---|
| 681 | 659 | { |
|---|
| 682 | | - struct list_head *d_child; |
|---|
| 683 | 660 | struct dentry *parent; |
|---|
| 684 | 661 | |
|---|
| 685 | 662 | /* flags for dentrys in the root are handled elsewhere */ |
|---|
| .. | .. |
|---|
| 692 | 669 | /* only consider parents below dentrys in the root */ |
|---|
| 693 | 670 | if (IS_ROOT(parent->d_parent)) |
|---|
| 694 | 671 | return; |
|---|
| 695 | | - d_child = &dentry->d_child; |
|---|
| 696 | | - /* Set parent managed if it's becoming empty */ |
|---|
| 697 | | - if (d_child->next == &parent->d_subdirs && |
|---|
| 698 | | - d_child->prev == &parent->d_subdirs) |
|---|
| 672 | + if (autofs_dentry_ino(parent)->count == 2) |
|---|
| 699 | 673 | managed_dentry_set_managed(parent); |
|---|
| 700 | 674 | } |
|---|
| 701 | 675 | |
|---|
| .. | .. |
|---|
| 714 | 688 | * autofs mount is catatonic but the state of an autofs |
|---|
| 715 | 689 | * file system needs to be preserved over restarts. |
|---|
| 716 | 690 | */ |
|---|
| 717 | | - if (sbi->catatonic) |
|---|
| 691 | + if (sbi->flags & AUTOFS_SBI_CATATONIC) |
|---|
| 718 | 692 | return -EACCES; |
|---|
| 719 | 693 | |
|---|
| 720 | | - spin_lock(&sbi->lookup_lock); |
|---|
| 721 | | - if (!simple_empty(dentry)) { |
|---|
| 722 | | - spin_unlock(&sbi->lookup_lock); |
|---|
| 694 | + if (ino->count != 1) |
|---|
| 723 | 695 | return -ENOTEMPTY; |
|---|
| 724 | | - } |
|---|
| 696 | + |
|---|
| 697 | + spin_lock(&sbi->lookup_lock); |
|---|
| 725 | 698 | __autofs_add_expiring(dentry); |
|---|
| 726 | 699 | d_drop(dentry); |
|---|
| 727 | 700 | spin_unlock(&sbi->lookup_lock); |
|---|
| .. | .. |
|---|
| 729 | 702 | if (sbi->version < 5) |
|---|
| 730 | 703 | autofs_clear_leaf_automount_flags(dentry); |
|---|
| 731 | 704 | |
|---|
| 732 | | - if (atomic_dec_and_test(&ino->count)) { |
|---|
| 733 | | - p_ino = autofs_dentry_ino(dentry->d_parent); |
|---|
| 734 | | - if (p_ino && dentry->d_parent != dentry) |
|---|
| 735 | | - atomic_dec(&p_ino->count); |
|---|
| 736 | | - } |
|---|
| 705 | + ino->count--; |
|---|
| 706 | + p_ino = autofs_dentry_ino(dentry->d_parent); |
|---|
| 707 | + p_ino->count--; |
|---|
| 737 | 708 | dput(ino->dentry); |
|---|
| 738 | 709 | d_inode(dentry)->i_size = 0; |
|---|
| 739 | 710 | clear_nlink(d_inode(dentry)); |
|---|
| .. | .. |
|---|
| 759 | 730 | * autofs mount is catatonic but the state of an autofs |
|---|
| 760 | 731 | * file system needs to be preserved over restarts. |
|---|
| 761 | 732 | */ |
|---|
| 762 | | - if (sbi->catatonic) |
|---|
| 733 | + if (sbi->flags & AUTOFS_SBI_CATATONIC) |
|---|
| 763 | 734 | return -EACCES; |
|---|
| 764 | 735 | |
|---|
| 765 | 736 | pr_debug("dentry %p, creating %pd\n", dentry, dentry); |
|---|
| .. | .. |
|---|
| 779 | 750 | autofs_set_leaf_automount_flags(dentry); |
|---|
| 780 | 751 | |
|---|
| 781 | 752 | dget(dentry); |
|---|
| 782 | | - atomic_inc(&ino->count); |
|---|
| 753 | + ino->count++; |
|---|
| 783 | 754 | p_ino = autofs_dentry_ino(dentry->d_parent); |
|---|
| 784 | | - if (p_ino && !IS_ROOT(dentry)) |
|---|
| 785 | | - atomic_inc(&p_ino->count); |
|---|
| 755 | + p_ino->count++; |
|---|
| 786 | 756 | inc_nlink(dir); |
|---|
| 787 | 757 | dir->i_mtime = current_time(dir); |
|---|
| 788 | 758 | |
|---|