diff options
Diffstat (limited to 'fs/autofs4/root.c')
| -rw-r--r-- | fs/autofs4/root.c | 74 |
1 files changed, 35 insertions, 39 deletions
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 1dba035fc376..014e7aba3b08 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
| @@ -37,6 +37,7 @@ static int autofs4_dir_open(struct inode *inode, struct file *file); | |||
| 37 | static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *); | 37 | static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *); |
| 38 | static struct vfsmount *autofs4_d_automount(struct path *); | 38 | static struct vfsmount *autofs4_d_automount(struct path *); |
| 39 | static int autofs4_d_manage(struct dentry *, bool, bool); | 39 | static int autofs4_d_manage(struct dentry *, bool, bool); |
| 40 | static void autofs4_dentry_release(struct dentry *); | ||
| 40 | 41 | ||
| 41 | const struct file_operations autofs4_root_operations = { | 42 | const struct file_operations autofs4_root_operations = { |
| 42 | .open = dcache_dir_open, | 43 | .open = dcache_dir_open, |
| @@ -138,25 +139,26 @@ out: | |||
| 138 | return dcache_dir_open(inode, file); | 139 | return dcache_dir_open(inode, file); |
| 139 | } | 140 | } |
| 140 | 141 | ||
| 141 | void autofs4_dentry_release(struct dentry *de) | 142 | static void autofs4_dentry_release(struct dentry *de) |
| 142 | { | 143 | { |
| 143 | struct autofs_info *inf; | 144 | struct autofs_info *ino = autofs4_dentry_ino(de); |
| 145 | struct autofs_sb_info *sbi = autofs4_sbi(de->d_sb); | ||
| 144 | 146 | ||
| 145 | DPRINTK("releasing %p", de); | 147 | DPRINTK("releasing %p", de); |
| 146 | 148 | ||
| 147 | inf = autofs4_dentry_ino(de); | 149 | if (!ino) |
| 148 | if (inf) { | 150 | return; |
| 149 | struct autofs_sb_info *sbi = autofs4_sbi(de->d_sb); | 151 | |
| 150 | if (sbi) { | 152 | if (sbi) { |
| 151 | spin_lock(&sbi->lookup_lock); | 153 | spin_lock(&sbi->lookup_lock); |
| 152 | if (!list_empty(&inf->active)) | 154 | if (!list_empty(&ino->active)) |
| 153 | list_del(&inf->active); | 155 | list_del(&ino->active); |
| 154 | if (!list_empty(&inf->expiring)) | 156 | if (!list_empty(&ino->expiring)) |
| 155 | list_del(&inf->expiring); | 157 | list_del(&ino->expiring); |
| 156 | spin_unlock(&sbi->lookup_lock); | 158 | spin_unlock(&sbi->lookup_lock); |
| 157 | } | ||
| 158 | autofs4_free_ino(inf); | ||
| 159 | } | 159 | } |
| 160 | |||
| 161 | autofs4_free_ino(ino); | ||
| 160 | } | 162 | } |
| 161 | 163 | ||
| 162 | static struct dentry *autofs4_lookup_active(struct dentry *dentry) | 164 | static struct dentry *autofs4_lookup_active(struct dentry *dentry) |
| @@ -488,7 +490,8 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s | |||
| 488 | sbi = autofs4_sbi(dir->i_sb); | 490 | sbi = autofs4_sbi(dir->i_sb); |
| 489 | 491 | ||
| 490 | DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d", | 492 | DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d", |
| 491 | current->pid, task_pgrp_nr(current), sbi->catatonic, oz_mode); | 493 | current->pid, task_pgrp_nr(current), sbi->catatonic, |
| 494 | autofs4_oz_mode(sbi)); | ||
| 492 | 495 | ||
| 493 | active = autofs4_lookup_active(dentry); | 496 | active = autofs4_lookup_active(dentry); |
| 494 | if (active) { | 497 | if (active) { |
| @@ -507,7 +510,7 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s | |||
| 507 | if (autofs_type_indirect(sbi->type) && IS_ROOT(dentry->d_parent)) | 510 | if (autofs_type_indirect(sbi->type) && IS_ROOT(dentry->d_parent)) |
| 508 | __managed_dentry_set_managed(dentry); | 511 | __managed_dentry_set_managed(dentry); |
| 509 | 512 | ||
| 510 | ino = autofs4_init_ino(NULL, sbi, 0555); | 513 | ino = autofs4_new_ino(sbi); |
| 511 | if (!ino) | 514 | if (!ino) |
| 512 | return ERR_PTR(-ENOMEM); | 515 | return ERR_PTR(-ENOMEM); |
| 513 | 516 | ||
| @@ -529,6 +532,7 @@ static int autofs4_dir_symlink(struct inode *dir, | |||
| 529 | struct autofs_info *ino = autofs4_dentry_ino(dentry); | 532 | struct autofs_info *ino = autofs4_dentry_ino(dentry); |
| 530 | struct autofs_info *p_ino; | 533 | struct autofs_info *p_ino; |
| 531 | struct inode *inode; | 534 | struct inode *inode; |
| 535 | size_t size = strlen(symname); | ||
| 532 | char *cp; | 536 | char *cp; |
| 533 | 537 | ||
| 534 | DPRINTK("%s <- %.*s", symname, | 538 | DPRINTK("%s <- %.*s", symname, |
| @@ -537,39 +541,35 @@ static int autofs4_dir_symlink(struct inode *dir, | |||
| 537 | if (!autofs4_oz_mode(sbi)) | 541 | if (!autofs4_oz_mode(sbi)) |
| 538 | return -EACCES; | 542 | return -EACCES; |
| 539 | 543 | ||
| 540 | ino = autofs4_init_ino(ino, sbi, S_IFLNK | 0555); | 544 | BUG_ON(!ino); |
| 541 | if (!ino) | 545 | |
| 542 | return -ENOMEM; | 546 | autofs4_clean_ino(ino); |
| 543 | 547 | ||
| 544 | autofs4_del_active(dentry); | 548 | autofs4_del_active(dentry); |
| 545 | 549 | ||
| 546 | ino->size = strlen(symname); | 550 | cp = kmalloc(size + 1, GFP_KERNEL); |
| 547 | cp = kmalloc(ino->size + 1, GFP_KERNEL); | 551 | if (!cp) |
| 548 | if (!cp) { | ||
| 549 | if (!dentry->d_fsdata) | ||
| 550 | kfree(ino); | ||
| 551 | return -ENOMEM; | 552 | return -ENOMEM; |
| 552 | } | ||
| 553 | 553 | ||
| 554 | strcpy(cp, symname); | 554 | strcpy(cp, symname); |
| 555 | 555 | ||
| 556 | inode = autofs4_get_inode(dir->i_sb, ino); | 556 | inode = autofs4_get_inode(dir->i_sb, S_IFLNK | 0555); |
| 557 | if (!inode) { | 557 | if (!inode) { |
| 558 | kfree(cp); | 558 | kfree(cp); |
| 559 | if (!dentry->d_fsdata) | 559 | if (!dentry->d_fsdata) |
| 560 | kfree(ino); | 560 | kfree(ino); |
| 561 | return -ENOMEM; | 561 | return -ENOMEM; |
| 562 | } | 562 | } |
| 563 | inode->i_private = cp; | ||
| 564 | inode->i_size = size; | ||
| 563 | d_add(dentry, inode); | 565 | d_add(dentry, inode); |
| 564 | 566 | ||
| 565 | dentry->d_fsdata = ino; | 567 | dget(dentry); |
| 566 | ino->dentry = dget(dentry); | ||
| 567 | atomic_inc(&ino->count); | 568 | atomic_inc(&ino->count); |
| 568 | p_ino = autofs4_dentry_ino(dentry->d_parent); | 569 | p_ino = autofs4_dentry_ino(dentry->d_parent); |
| 569 | if (p_ino && dentry->d_parent != dentry) | 570 | if (p_ino && dentry->d_parent != dentry) |
| 570 | atomic_inc(&p_ino->count); | 571 | atomic_inc(&p_ino->count); |
| 571 | 572 | ||
| 572 | ino->u.symlink = cp; | ||
| 573 | dir->i_mtime = CURRENT_TIME; | 573 | dir->i_mtime = CURRENT_TIME; |
| 574 | 574 | ||
| 575 | return 0; | 575 | return 0; |
| @@ -732,25 +732,21 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 732 | DPRINTK("dentry %p, creating %.*s", | 732 | DPRINTK("dentry %p, creating %.*s", |
| 733 | dentry, dentry->d_name.len, dentry->d_name.name); | 733 | dentry, dentry->d_name.len, dentry->d_name.name); |
| 734 | 734 | ||
| 735 | ino = autofs4_init_ino(ino, sbi, S_IFDIR | 0555); | 735 | BUG_ON(!ino); |
| 736 | if (!ino) | 736 | |
| 737 | return -ENOMEM; | 737 | autofs4_clean_ino(ino); |
| 738 | 738 | ||
| 739 | autofs4_del_active(dentry); | 739 | autofs4_del_active(dentry); |
| 740 | 740 | ||
| 741 | inode = autofs4_get_inode(dir->i_sb, ino); | 741 | inode = autofs4_get_inode(dir->i_sb, S_IFDIR | 0555); |
| 742 | if (!inode) { | 742 | if (!inode) |
| 743 | if (!dentry->d_fsdata) | ||
| 744 | kfree(ino); | ||
| 745 | return -ENOMEM; | 743 | return -ENOMEM; |
| 746 | } | ||
| 747 | d_add(dentry, inode); | 744 | d_add(dentry, inode); |
| 748 | 745 | ||
| 749 | if (sbi->version < 5) | 746 | if (sbi->version < 5) |
| 750 | autofs_set_leaf_automount_flags(dentry); | 747 | autofs_set_leaf_automount_flags(dentry); |
| 751 | 748 | ||
| 752 | dentry->d_fsdata = ino; | 749 | dget(dentry); |
| 753 | ino->dentry = dget(dentry); | ||
| 754 | atomic_inc(&ino->count); | 750 | atomic_inc(&ino->count); |
| 755 | p_ino = autofs4_dentry_ino(dentry->d_parent); | 751 | p_ino = autofs4_dentry_ino(dentry->d_parent); |
| 756 | if (p_ino && dentry->d_parent != dentry) | 752 | if (p_ino && dentry->d_parent != dentry) |
