static int autofs_root_rmdir(struct inode *dir, struct dentry *dentry) { struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb); struct autofs_dirhash *dh = &sbi->dirhash; struct autofs_dir_ent *ent; lock_kernel(); if (!autofs_oz_mode(sbi)) { unlock_kernel(); return -EACCES; } ent = autofs_hash_lookup(dh, &dentry->d_name); if (!ent) { unlock_kernel(); return -ENOENT; } if ((unsigned int)ent->ino < AUTOFS_FIRST_DIR_INO) { unlock_kernel(); return -ENOTDIR; /* Not a directory */ } if (ent->dentry != dentry) { printk("autofs_rmdir: odentry != dentry for entry %s\n", dentry->d_name.name); } dentry->d_time = (unsigned long)(struct autofs_dir_ent *)NULL; autofs_hash_delete(ent); drop_nlink(dir); d_drop(dentry); unlock_kernel(); return 0; }
/* * NOTE! * * Normal filesystems would do a "d_delete()" to tell the VFS dcache * that the file no longer exists. However, doing that means that the * VFS layer can turn the dentry into a negative dentry, which we * obviously do not want (we're dropping the entry not because it * doesn't exist, but because it has timed out). * * Also see autofs_root_rmdir().. */ static int autofs_root_unlink(struct inode *dir, struct dentry *dentry) { struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb); struct autofs_dirhash *dh = &sbi->dirhash; struct autofs_dir_ent *ent; unsigned int n; /* This allows root to remove symlinks */ if ( !autofs_oz_mode(sbi) && !capable(CAP_SYS_ADMIN) ) return -EACCES; ent = autofs_hash_lookup(dh, &dentry->d_name); if ( !ent ) return -ENOENT; n = ent->ino - AUTOFS_FIRST_SYMLINK; if ( n >= AUTOFS_MAX_SYMLINKS ) return -EISDIR; /* It's a directory, dummy */ if ( !test_bit(n,sbi->symlink_bitmap) ) return -EINVAL; /* Nonexistent symlink? Shouldn't happen */ dentry->d_time = (unsigned long)(struct autofs_dirhash *)NULL; autofs_hash_delete(ent); clear_bit(n,sbi->symlink_bitmap); kfree(sbi->symlink[n].data); d_drop(dentry); return 0; }