Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs pile 1 from Al Viro: "This is _not_ all; in particular, Miklos' and Jan's stuff is not there yet." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (64 commits) ext4: initialization of ext4_li_mtx needs to be done earlier debugfs-related mode_t whack-a-mole hfsplus: add an ioctl to bless files hfsplus: change finder_info to u32 hfsplus: initialise userflags qnx4: new helper - try_extent() qnx4: get rid of qnx4_bread/qnx4_getblk take removal of PF_FORKNOEXEC to flush_old_exec() trim includes in inode.c um: uml_dup_mmap() relies on ->mmap_sem being held, but activate_mm() doesn't hold it um: embed ->stub_pages[] into mmu_context gadgetfs: list_for_each_safe() misuse ocfs2: fix leaks on failure exits in module_init ecryptfs: make register_filesystem() the last potential failure exit ntfs: forgets to unregister sysctls on register_filesystem() failure logfs: missing cleanup on register_filesystem() failure jfs: mising cleanup on register_filesystem() failure make configfs_pin_fs() return root dentry on success configfs: configfs_create_dir() has parent dentry in dentry->d_parent configfs: sanitize configfs_create() ...
This commit is contained in:
commit
e2a0883e40
@ -136,7 +136,7 @@ file.
|
||||
void __iomem *base;
|
||||
};
|
||||
|
||||
struct dentry *debugfs_create_regset32(const char *name, mode_t mode,
|
||||
struct dentry *debugfs_create_regset32(const char *name, umode_t mode,
|
||||
struct dentry *parent,
|
||||
struct debugfs_regset32 *regset);
|
||||
|
||||
|
@ -429,3 +429,9 @@ filemap_write_and_wait_range() so that all dirty pages are synced out properly.
|
||||
You must also keep in mind that ->fsync() is not called with i_mutex held
|
||||
anymore, so if you require i_mutex locking you must make sure to take it and
|
||||
release it yourself.
|
||||
|
||||
--
|
||||
[mandatory]
|
||||
d_alloc_root() is gone, along with a lot of bugs caused by code
|
||||
misusing it. Replacement: d_make_root(inode). The difference is,
|
||||
d_make_root() drops the reference to inode if dentry allocation fails.
|
||||
|
174
Documentation/filesystems/qnx6.txt
Normal file
174
Documentation/filesystems/qnx6.txt
Normal file
@ -0,0 +1,174 @@
|
||||
The QNX6 Filesystem
|
||||
===================
|
||||
|
||||
The qnx6fs is used by newer QNX operating system versions. (e.g. Neutrino)
|
||||
It got introduced in QNX 6.4.0 and is used default since 6.4.1.
|
||||
|
||||
Option
|
||||
======
|
||||
|
||||
mmi_fs Mount filesystem as used for example by Audi MMI 3G system
|
||||
|
||||
Specification
|
||||
=============
|
||||
|
||||
qnx6fs shares many properties with traditional Unix filesystems. It has the
|
||||
concepts of blocks, inodes and directories.
|
||||
On QNX it is possible to create little endian and big endian qnx6 filesystems.
|
||||
This feature makes it possible to create and use a different endianness fs
|
||||
for the target (QNX is used on quite a range of embedded systems) plattform
|
||||
running on a different endianess.
|
||||
The Linux driver handles endianness transparently. (LE and BE)
|
||||
|
||||
Blocks
|
||||
------
|
||||
|
||||
The space in the device or file is split up into blocks. These are a fixed
|
||||
size of 512, 1024, 2048 or 4096, which is decided when the filesystem is
|
||||
created.
|
||||
Blockpointers are 32bit, so the maximum space that can be adressed is
|
||||
2^32 * 4096 bytes or 16TB
|
||||
|
||||
The superblocks
|
||||
---------------
|
||||
|
||||
The superblock contains all global information about the filesystem.
|
||||
Each qnx6fs got two superblocks, each one having a 64bit serial number.
|
||||
That serial number is used to identify the "active" superblock.
|
||||
In write mode with reach new snapshot (after each synchronous write), the
|
||||
serial of the new master superblock is increased (old superblock serial + 1)
|
||||
|
||||
So basically the snapshot functionality is realized by an atomic final
|
||||
update of the serial number. Before updating that serial, all modifications
|
||||
are done by copying all modified blocks during that specific write request
|
||||
(or period) and building up a new (stable) filesystem structure under the
|
||||
inactive superblock.
|
||||
|
||||
Each superblock holds a set of root inodes for the different filesystem
|
||||
parts. (Inode, Bitmap and Longfilenames)
|
||||
Each of these root nodes holds information like total size of the stored
|
||||
data and the adressing levels in that specific tree.
|
||||
If the level value is 0, up to 16 direct blocks can be adressed by each
|
||||
node.
|
||||
Level 1 adds an additional indirect adressing level where each indirect
|
||||
adressing block holds up to blocksize / 4 bytes pointers to data blocks.
|
||||
Level 2 adds an additional indirect adressig block level (so, already up
|
||||
to 16 * 256 * 256 = 1048576 blocks that can be adressed by such a tree)a
|
||||
|
||||
Unused block pointers are always set to ~0 - regardless of root node,
|
||||
indirect adressing blocks or inodes.
|
||||
Data leaves are always on the lowest level. So no data is stored on upper
|
||||
tree levels.
|
||||
|
||||
The first Superblock is located at 0x2000. (0x2000 is the bootblock size)
|
||||
The Audi MMI 3G first superblock directly starts at byte 0.
|
||||
Second superblock position can either be calculated from the superblock
|
||||
information (total number of filesystem blocks) or by taking the highest
|
||||
device address, zeroing the last 3 bytes and then substracting 0x1000 from
|
||||
that address.
|
||||
|
||||
0x1000 is the size reserved for each superblock - regardless of the
|
||||
blocksize of the filesystem.
|
||||
|
||||
Inodes
|
||||
------
|
||||
|
||||
Each object in the filesystem is represented by an inode. (index node)
|
||||
The inode structure contains pointers to the filesystem blocks which contain
|
||||
the data held in the object and all of the metadata about an object except
|
||||
its longname. (filenames longer than 27 characters)
|
||||
The metadata about an object includes the permissions, owner, group, flags,
|
||||
size, number of blocks used, access time, change time and modification time.
|
||||
|
||||
Object mode field is POSIX format. (which makes things easier)
|
||||
|
||||
There are also pointers to the first 16 blocks, if the object data can be
|
||||
adressed with 16 direct blocks.
|
||||
For more than 16 blocks an indirect adressing in form of another tree is
|
||||
used. (scheme is the same as the one used for the superblock root nodes)
|
||||
|
||||
The filesize is stored 64bit. Inode counting starts with 1. (whilst long
|
||||
filename inodes start with 0)
|
||||
|
||||
Directories
|
||||
-----------
|
||||
|
||||
A directory is a filesystem object and has an inode just like a file.
|
||||
It is a specially formatted file containing records which associate each
|
||||
name with an inode number.
|
||||
'.' inode number points to the directory inode
|
||||
'..' inode number points to the parent directory inode
|
||||
Eeach filename record additionally got a filename length field.
|
||||
|
||||
One special case are long filenames or subdirectory names.
|
||||
These got set a filename length field of 0xff in the corresponding directory
|
||||
record plus the longfile inode number also stored in that record.
|
||||
With that longfilename inode number, the longfilename tree can be walked
|
||||
starting with the superblock longfilename root node pointers.
|
||||
|
||||
Special files
|
||||
-------------
|
||||
|
||||
Symbolic links are also filesystem objects with inodes. They got a specific
|
||||
bit in the inode mode field identifying them as symbolic link.
|
||||
The directory entry file inode pointer points to the target file inode.
|
||||
|
||||
Hard links got an inode, a directory entry, but a specific mode bit set,
|
||||
no block pointers and the directory file record pointing to the target file
|
||||
inode.
|
||||
|
||||
Character and block special devices do not exist in QNX as those files
|
||||
are handled by the QNX kernel/drivers and created in /dev independant of the
|
||||
underlaying filesystem.
|
||||
|
||||
Long filenames
|
||||
--------------
|
||||
|
||||
Long filenames are stored in a seperate adressing tree. The staring point
|
||||
is the longfilename root node in the active superblock.
|
||||
Each data block (tree leaves) holds one long filename. That filename is
|
||||
limited to 510 bytes. The first two starting bytes are used as length field
|
||||
for the actual filename.
|
||||
If that structure shall fit for all allowed blocksizes, it is clear why there
|
||||
is a limit of 510 bytes for the actual filename stored.
|
||||
|
||||
Bitmap
|
||||
------
|
||||
|
||||
The qnx6fs filesystem allocation bitmap is stored in a tree under bitmap
|
||||
root node in the superblock and each bit in the bitmap represents one
|
||||
filesystem block.
|
||||
The first block is block 0, which starts 0x1000 after superblock start.
|
||||
So for a normal qnx6fs 0x3000 (bootblock + superblock) is the physical
|
||||
address at which block 0 is located.
|
||||
|
||||
Bits at the end of the last bitmap block are set to 1, if the device is
|
||||
smaller than addressing space in the bitmap.
|
||||
|
||||
Bitmap system area
|
||||
------------------
|
||||
|
||||
The bitmap itself is devided into three parts.
|
||||
First the system area, that is split into two halfs.
|
||||
Then userspace.
|
||||
|
||||
The requirement for a static, fixed preallocated system area comes from how
|
||||
qnx6fs deals with writes.
|
||||
Each superblock got it's own half of the system area. So superblock #1
|
||||
always uses blocks from the lower half whilst superblock #2 just writes to
|
||||
blocks represented by the upper half bitmap system area bits.
|
||||
|
||||
Bitmap blocks, Inode blocks and indirect addressing blocks for those two
|
||||
tree structures are treated as system blocks.
|
||||
|
||||
The rational behind that is that a write request can work on a new snapshot
|
||||
(system area of the inactive - resp. lower serial numbered superblock) while
|
||||
at the same time there is still a complete stable filesystem structer in the
|
||||
other half of the system area.
|
||||
|
||||
When finished with writing (a sync write is completed, the maximum sync leap
|
||||
time or a filesystem sync is requested), serial of the previously inactive
|
||||
superblock atomically is increased and the fs switches over to that - then
|
||||
stable declared - superblock.
|
||||
|
||||
For all data outside the system area, blocks are just copied while writing.
|
@ -218,6 +218,7 @@ Code Seq#(hex) Include File Comments
|
||||
'h' 00-7F conflict! Charon filesystem
|
||||
<mailto:zapman@interlan.net>
|
||||
'h' 00-1F linux/hpet.h conflict!
|
||||
'h' 80-8F fs/hfsplus/ioctl.c
|
||||
'i' 00-3F linux/i2o-dev.h conflict!
|
||||
'i' 0B-1F linux/ipmi.h conflict!
|
||||
'i' 80-8F linux/i8k.h
|
||||
|
@ -46,6 +46,7 @@ static struct linux_binfmt loader_format = {
|
||||
|
||||
static int __init init_loader_binfmt(void)
|
||||
{
|
||||
return insert_binfmt(&loader_format);
|
||||
insert_binfmt(&loader_format);
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(init_loader_binfmt);
|
||||
|
@ -757,9 +757,9 @@ spufs_create_root(struct super_block *sb, void *data)
|
||||
goto out_iput;
|
||||
|
||||
ret = -ENOMEM;
|
||||
sb->s_root = d_alloc_root(inode);
|
||||
sb->s_root = d_make_root(inode);
|
||||
if (!sb->s_root)
|
||||
goto out_iput;
|
||||
goto out;
|
||||
|
||||
return 0;
|
||||
out_iput:
|
||||
@ -828,19 +828,19 @@ static int __init spufs_init(void)
|
||||
ret = spu_sched_init();
|
||||
if (ret)
|
||||
goto out_cache;
|
||||
ret = register_filesystem(&spufs_type);
|
||||
if (ret)
|
||||
goto out_sched;
|
||||
ret = register_spu_syscalls(&spufs_calls);
|
||||
if (ret)
|
||||
goto out_fs;
|
||||
goto out_sched;
|
||||
ret = register_filesystem(&spufs_type);
|
||||
if (ret)
|
||||
goto out_syscalls;
|
||||
|
||||
spufs_init_isolated_loader();
|
||||
|
||||
return 0;
|
||||
|
||||
out_fs:
|
||||
unregister_filesystem(&spufs_type);
|
||||
out_syscalls:
|
||||
unregister_spu_syscalls(&spufs_calls);
|
||||
out_sched:
|
||||
spu_sched_exit();
|
||||
out_cache:
|
||||
|
@ -293,11 +293,9 @@ static int hypfs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
return -ENOMEM;
|
||||
root_inode->i_op = &simple_dir_inode_operations;
|
||||
root_inode->i_fop = &simple_dir_operations;
|
||||
sb->s_root = root_dentry = d_alloc_root(root_inode);
|
||||
if (!root_dentry) {
|
||||
iput(root_inode);
|
||||
sb->s_root = root_dentry = d_make_root(root_inode);
|
||||
if (!root_dentry)
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (MACHINE_IS_VM)
|
||||
rc = hypfs_vm_create_files(sb, root_dentry);
|
||||
else
|
||||
|
@ -12,7 +12,7 @@
|
||||
typedef struct mm_context {
|
||||
struct mm_id id;
|
||||
struct uml_arch_mm_context arch;
|
||||
struct page **stub_pages;
|
||||
struct page *stub_pages[2];
|
||||
} mm_context_t;
|
||||
|
||||
extern void __switch_mm(struct mm_id * mm_idp);
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include <linux/sched.h>
|
||||
#include <asm/mmu.h>
|
||||
|
||||
extern void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm);
|
||||
extern void uml_setup_stubs(struct mm_struct *mm);
|
||||
extern void arch_exit_mmap(struct mm_struct *mm);
|
||||
|
||||
#define deactivate_mm(tsk,mm) do { } while (0)
|
||||
@ -23,7 +23,9 @@ static inline void activate_mm(struct mm_struct *old, struct mm_struct *new)
|
||||
* when the new ->mm is used for the first time.
|
||||
*/
|
||||
__switch_mm(&new->context.id);
|
||||
arch_dup_mmap(old, new);
|
||||
down_write(&new->mmap_sem);
|
||||
uml_setup_stubs(new);
|
||||
up_write(&new->mmap_sem);
|
||||
}
|
||||
|
||||
static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
|
||||
@ -39,6 +41,11 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
|
||||
}
|
||||
}
|
||||
|
||||
static inline void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm)
|
||||
{
|
||||
uml_setup_stubs(mm);
|
||||
}
|
||||
|
||||
static inline void enter_lazy_tlb(struct mm_struct *mm,
|
||||
struct task_struct *tsk)
|
||||
{
|
||||
|
@ -92,8 +92,6 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm)
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
to_mm->stub_pages = NULL;
|
||||
|
||||
return 0;
|
||||
|
||||
out_free:
|
||||
@ -103,7 +101,7 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm)
|
||||
void uml_setup_stubs(struct mm_struct *mm)
|
||||
{
|
||||
struct page **pages;
|
||||
int err, ret;
|
||||
@ -120,29 +118,20 @@ void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm)
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
pages = kmalloc(2 * sizeof(struct page *), GFP_KERNEL);
|
||||
if (pages == NULL) {
|
||||
printk(KERN_ERR "arch_dup_mmap failed to allocate 2 page "
|
||||
"pointers\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
pages[0] = virt_to_page(&__syscall_stub_start);
|
||||
pages[1] = virt_to_page(mm->context.id.stack);
|
||||
mm->context.stub_pages = pages;
|
||||
mm->context.stub_pages[0] = virt_to_page(&__syscall_stub_start);
|
||||
mm->context.stub_pages[1] = virt_to_page(mm->context.id.stack);
|
||||
|
||||
/* dup_mmap already holds mmap_sem */
|
||||
err = install_special_mapping(mm, STUB_START, STUB_END - STUB_START,
|
||||
VM_READ | VM_MAYREAD | VM_EXEC |
|
||||
VM_MAYEXEC | VM_DONTCOPY, pages);
|
||||
VM_MAYEXEC | VM_DONTCOPY,
|
||||
mm->context.stub_pages);
|
||||
if (err) {
|
||||
printk(KERN_ERR "install_special_mapping returned %d\n", err);
|
||||
goto out_free;
|
||||
goto out;
|
||||
}
|
||||
return;
|
||||
|
||||
out_free:
|
||||
kfree(pages);
|
||||
out:
|
||||
force_sigsegv(SIGSEGV, current);
|
||||
}
|
||||
@ -151,8 +140,6 @@ void arch_exit_mmap(struct mm_struct *mm)
|
||||
{
|
||||
pte_t *pte;
|
||||
|
||||
if (mm->context.stub_pages != NULL)
|
||||
kfree(mm->context.stub_pages);
|
||||
pte = virt_to_pte(mm, STUB_CODE);
|
||||
if (pte != NULL)
|
||||
pte_clear(mm, STUB_CODE, pte);
|
||||
|
@ -323,7 +323,6 @@ static int load_aout_binary(struct linux_binprm *bprm, struct pt_regs *regs)
|
||||
}
|
||||
|
||||
install_exec_creds(bprm);
|
||||
current->flags &= ~PF_FORKNOEXEC;
|
||||
|
||||
if (N_MAGIC(ex) == OMAGIC) {
|
||||
unsigned long text_addr, map_size;
|
||||
@ -519,7 +518,8 @@ out:
|
||||
|
||||
static int __init init_aout_binfmt(void)
|
||||
{
|
||||
return register_binfmt(&aout_format);
|
||||
register_binfmt(&aout_format);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit exit_aout_binfmt(void)
|
||||
|
@ -87,7 +87,7 @@
|
||||
static LIST_HEAD(service_processors);
|
||||
|
||||
static struct inode *ibmasmfs_make_inode(struct super_block *sb, int mode);
|
||||
static void ibmasmfs_create_files (struct super_block *sb, struct dentry *root);
|
||||
static void ibmasmfs_create_files (struct super_block *sb);
|
||||
static int ibmasmfs_fill_super (struct super_block *sb, void *data, int silent);
|
||||
|
||||
|
||||
@ -114,7 +114,6 @@ static struct file_system_type ibmasmfs_type = {
|
||||
static int ibmasmfs_fill_super (struct super_block *sb, void *data, int silent)
|
||||
{
|
||||
struct inode *root;
|
||||
struct dentry *root_dentry;
|
||||
|
||||
sb->s_blocksize = PAGE_CACHE_SIZE;
|
||||
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
|
||||
@ -129,14 +128,11 @@ static int ibmasmfs_fill_super (struct super_block *sb, void *data, int silent)
|
||||
root->i_op = &simple_dir_inode_operations;
|
||||
root->i_fop = ibmasmfs_dir_ops;
|
||||
|
||||
root_dentry = d_alloc_root(root);
|
||||
if (!root_dentry) {
|
||||
iput(root);
|
||||
sb->s_root = d_make_root(root);
|
||||
if (!sb->s_root)
|
||||
return -ENOMEM;
|
||||
}
|
||||
sb->s_root = root_dentry;
|
||||
|
||||
ibmasmfs_create_files(sb, root_dentry);
|
||||
ibmasmfs_create_files(sb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -612,7 +608,7 @@ static const struct file_operations remote_settings_fops = {
|
||||
};
|
||||
|
||||
|
||||
static void ibmasmfs_create_files (struct super_block *sb, struct dentry *root)
|
||||
static void ibmasmfs_create_files (struct super_block *sb)
|
||||
{
|
||||
struct list_head *entry;
|
||||
struct service_processor *sp;
|
||||
@ -621,7 +617,7 @@ static void ibmasmfs_create_files (struct super_block *sb, struct dentry *root)
|
||||
struct dentry *dir;
|
||||
struct dentry *remote_dir;
|
||||
sp = list_entry(entry, struct service_processor, node);
|
||||
dir = ibmasmfs_create_dir(sb, root, sp->dirname);
|
||||
dir = ibmasmfs_create_dir(sb, sb->s_root, sp->dirname);
|
||||
if (!dir)
|
||||
continue;
|
||||
|
||||
|
@ -211,18 +211,17 @@ static void __exit ibmasm_exit (void)
|
||||
|
||||
static int __init ibmasm_init(void)
|
||||
{
|
||||
int result;
|
||||
int result = pci_register_driver(&ibmasm_driver);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
result = ibmasmfs_register();
|
||||
if (result) {
|
||||
pci_unregister_driver(&ibmasm_driver);
|
||||
err("Failed to register ibmasmfs file system");
|
||||
return result;
|
||||
}
|
||||
result = pci_register_driver(&ibmasm_driver);
|
||||
if (result) {
|
||||
ibmasmfs_unregister();
|
||||
return result;
|
||||
}
|
||||
|
||||
ibmasm_register_panic_notifier();
|
||||
info(DRIVER_DESC " version " DRIVER_VERSION " loaded");
|
||||
return 0;
|
||||
|
@ -1685,7 +1685,7 @@ static int mmc_add_disk(struct mmc_blk_data *md)
|
||||
|
||||
if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) &&
|
||||
card->ext_csd.boot_ro_lockable) {
|
||||
mode_t mode;
|
||||
umode_t mode;
|
||||
|
||||
if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PWR_WP_DIS)
|
||||
mode = S_IRUGO;
|
||||
|
@ -516,7 +516,7 @@ static const struct file_operations bnad_debugfs_op_drvinfo = {
|
||||
|
||||
struct bnad_debugfs_entry {
|
||||
const char *name;
|
||||
mode_t mode;
|
||||
umode_t mode;
|
||||
const struct file_operations *fops;
|
||||
};
|
||||
|
||||
|
@ -238,7 +238,6 @@ struct dentry *oprofilefs_mkdir(struct super_block *sb,
|
||||
static int oprofilefs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
{
|
||||
struct inode *root_inode;
|
||||
struct dentry *root_dentry;
|
||||
|
||||
sb->s_blocksize = PAGE_CACHE_SIZE;
|
||||
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
|
||||
@ -251,15 +250,11 @@ static int oprofilefs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
return -ENOMEM;
|
||||
root_inode->i_op = &simple_dir_inode_operations;
|
||||
root_inode->i_fop = &simple_dir_operations;
|
||||
root_dentry = d_alloc_root(root_inode);
|
||||
if (!root_dentry) {
|
||||
iput(root_inode);
|
||||
sb->s_root = d_make_root(root_inode);
|
||||
if (!sb->s_root)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
sb->s_root = root_dentry;
|
||||
|
||||
oprofile_create_files(sb, root_dentry);
|
||||
oprofile_create_files(sb, sb->s_root);
|
||||
|
||||
// FIXME: verify kill_litter_super removes our dentries
|
||||
return 0;
|
||||
|
@ -50,7 +50,6 @@
|
||||
static const struct file_operations default_file_operations;
|
||||
static struct vfsmount *usbfs_mount;
|
||||
static int usbfs_mount_count; /* = 0 */
|
||||
static int ignore_mount = 0;
|
||||
|
||||
static struct dentry *devices_usbfs_dentry;
|
||||
static int num_buses; /* = 0 */
|
||||
@ -256,7 +255,7 @@ static int remount(struct super_block *sb, int *flags, char *data)
|
||||
* i.e. it's a simple_pin_fs from create_special_files,
|
||||
* then ignore it.
|
||||
*/
|
||||
if (ignore_mount)
|
||||
if (*flags & MS_KERNMOUNT)
|
||||
return 0;
|
||||
|
||||
if (parse_options(sb, data)) {
|
||||
@ -454,7 +453,6 @@ static const struct super_operations usbfs_ops = {
|
||||
static int usbfs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
{
|
||||
struct inode *inode;
|
||||
struct dentry *root;
|
||||
|
||||
sb->s_blocksize = PAGE_CACHE_SIZE;
|
||||
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
|
||||
@ -462,19 +460,11 @@ static int usbfs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
sb->s_op = &usbfs_ops;
|
||||
sb->s_time_gran = 1;
|
||||
inode = usbfs_get_inode(sb, S_IFDIR | 0755, 0);
|
||||
|
||||
if (!inode) {
|
||||
dbg("%s: could not get inode!",__func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
root = d_alloc_root(inode);
|
||||
if (!root) {
|
||||
sb->s_root = d_make_root(inode);
|
||||
if (!sb->s_root) {
|
||||
dbg("%s: could not get root dentry!",__func__);
|
||||
iput(inode);
|
||||
return -ENOMEM;
|
||||
}
|
||||
sb->s_root = root;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -591,11 +581,6 @@ static int create_special_files (void)
|
||||
struct dentry *parent;
|
||||
int retval;
|
||||
|
||||
/* the simple_pin_fs calls will call remount with no options
|
||||
* without this flag that would overwrite the real mount options (if any)
|
||||
*/
|
||||
ignore_mount = 1;
|
||||
|
||||
/* create the devices special file */
|
||||
retval = simple_pin_fs(&usb_fs_type, &usbfs_mount, &usbfs_mount_count);
|
||||
if (retval) {
|
||||
@ -603,8 +588,6 @@ static int create_special_files (void)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ignore_mount = 0;
|
||||
|
||||
parent = usbfs_mount->mnt_root;
|
||||
devices_usbfs_dentry = fs_create_file ("devices",
|
||||
listmode | S_IFREG, parent,
|
||||
|
@ -1063,13 +1063,9 @@ static int ffs_sb_fill(struct super_block *sb, void *_data, int silent)
|
||||
&simple_dir_operations,
|
||||
&simple_dir_inode_operations,
|
||||
&data->perms);
|
||||
if (unlikely(!inode))
|
||||
sb->s_root = d_make_root(inode);
|
||||
if (unlikely(!sb->s_root))
|
||||
goto Enomem;
|
||||
sb->s_root = d_alloc_root(inode);
|
||||
if (unlikely(!sb->s_root)) {
|
||||
iput(inode);
|
||||
goto Enomem;
|
||||
}
|
||||
|
||||
/* EP0 file */
|
||||
if (unlikely(!ffs_sb_create_file(sb, "ep0", ffs,
|
||||
|
@ -1571,20 +1571,18 @@ delegate:
|
||||
|
||||
static void destroy_ep_files (struct dev_data *dev)
|
||||
{
|
||||
struct list_head *entry, *tmp;
|
||||
|
||||
DBG (dev, "%s %d\n", __func__, dev->state);
|
||||
|
||||
/* dev->state must prevent interference */
|
||||
restart:
|
||||
spin_lock_irq (&dev->lock);
|
||||
list_for_each_safe (entry, tmp, &dev->epfiles) {
|
||||
while (!list_empty(&dev->epfiles)) {
|
||||
struct ep_data *ep;
|
||||
struct inode *parent;
|
||||
struct dentry *dentry;
|
||||
|
||||
/* break link to FS */
|
||||
ep = list_entry (entry, struct ep_data, epfiles);
|
||||
ep = list_first_entry (&dev->epfiles, struct ep_data, epfiles);
|
||||
list_del_init (&ep->epfiles);
|
||||
dentry = ep->dentry;
|
||||
ep->dentry = NULL;
|
||||
@ -1607,8 +1605,7 @@ restart:
|
||||
dput (dentry);
|
||||
mutex_unlock (&parent->i_mutex);
|
||||
|
||||
/* fds may still be open */
|
||||
goto restart;
|
||||
spin_lock_irq (&dev->lock);
|
||||
}
|
||||
spin_unlock_irq (&dev->lock);
|
||||
}
|
||||
@ -2061,10 +2058,8 @@ gadgetfs_fill_super (struct super_block *sb, void *opts, int silent)
|
||||
if (!inode)
|
||||
goto Enomem;
|
||||
inode->i_op = &simple_dir_inode_operations;
|
||||
if (!(sb->s_root = d_alloc_root (inode))) {
|
||||
iput(inode);
|
||||
if (!(sb->s_root = d_make_root (inode)))
|
||||
goto Enomem;
|
||||
}
|
||||
|
||||
/* the ep0 file is named after the controller we expect;
|
||||
* user mode code can use it for sanity checks, like we do.
|
||||
|
16
fs/9p/v9fs.c
16
fs/9p/v9fs.c
@ -594,21 +594,21 @@ static int __init init_v9fs(void)
|
||||
int err;
|
||||
pr_info("Installing v9fs 9p2000 file system support\n");
|
||||
/* TODO: Setup list of registered trasnport modules */
|
||||
err = register_filesystem(&v9fs_fs_type);
|
||||
if (err < 0) {
|
||||
pr_err("Failed to register filesystem\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = v9fs_cache_register();
|
||||
if (err < 0) {
|
||||
pr_err("Failed to register v9fs for caching\n");
|
||||
goto out_fs_unreg;
|
||||
return err;
|
||||
}
|
||||
|
||||
err = v9fs_sysfs_init();
|
||||
if (err < 0) {
|
||||
pr_err("Failed to register with sysfs\n");
|
||||
goto out_cache;
|
||||
}
|
||||
err = register_filesystem(&v9fs_fs_type);
|
||||
if (err < 0) {
|
||||
pr_err("Failed to register filesystem\n");
|
||||
goto out_sysfs_cleanup;
|
||||
}
|
||||
|
||||
@ -617,8 +617,8 @@ static int __init init_v9fs(void)
|
||||
out_sysfs_cleanup:
|
||||
v9fs_sysfs_cleanup();
|
||||
|
||||
out_fs_unreg:
|
||||
unregister_filesystem(&v9fs_fs_type);
|
||||
out_cache:
|
||||
v9fs_cache_unregister();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -155,9 +155,8 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
|
||||
goto release_sb;
|
||||
}
|
||||
|
||||
root = d_alloc_root(inode);
|
||||
root = d_make_root(inode);
|
||||
if (!root) {
|
||||
iput(inode);
|
||||
retval = -ENOMEM;
|
||||
goto release_sb;
|
||||
}
|
||||
|
@ -214,6 +214,7 @@ source "fs/minix/Kconfig"
|
||||
source "fs/omfs/Kconfig"
|
||||
source "fs/hpfs/Kconfig"
|
||||
source "fs/qnx4/Kconfig"
|
||||
source "fs/qnx6/Kconfig"
|
||||
source "fs/romfs/Kconfig"
|
||||
source "fs/pstore/Kconfig"
|
||||
source "fs/sysv/Kconfig"
|
||||
|
@ -102,6 +102,7 @@ obj-$(CONFIG_UBIFS_FS) += ubifs/
|
||||
obj-$(CONFIG_AFFS_FS) += affs/
|
||||
obj-$(CONFIG_ROMFS_FS) += romfs/
|
||||
obj-$(CONFIG_QNX4FS_FS) += qnx4/
|
||||
obj-$(CONFIG_QNX6FS_FS) += qnx6/
|
||||
obj-$(CONFIG_AUTOFS4_FS) += autofs4/
|
||||
obj-$(CONFIG_ADFS_FS) += adfs/
|
||||
obj-$(CONFIG_FUSE_FS) += fuse/
|
||||
|
@ -483,10 +483,9 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
|
||||
sb->s_d_op = &adfs_dentry_operations;
|
||||
root = adfs_iget(sb, &root_obj);
|
||||
sb->s_root = d_alloc_root(root);
|
||||
sb->s_root = d_make_root(root);
|
||||
if (!sb->s_root) {
|
||||
int i;
|
||||
iput(root);
|
||||
for (i = 0; i < asb->s_map_size; i++)
|
||||
brelse(asb->s_map[i].dm_bh);
|
||||
kfree(asb->s_map);
|
||||
|
@ -473,7 +473,7 @@ got_root:
|
||||
root_inode = affs_iget(sb, root_block);
|
||||
if (IS_ERR(root_inode)) {
|
||||
ret = PTR_ERR(root_inode);
|
||||
goto out_error_noinode;
|
||||
goto out_error;
|
||||
}
|
||||
|
||||
if (AFFS_SB(sb)->s_flags & SF_INTL)
|
||||
@ -481,7 +481,7 @@ got_root:
|
||||
else
|
||||
sb->s_d_op = &affs_dentry_operations;
|
||||
|
||||
sb->s_root = d_alloc_root(root_inode);
|
||||
sb->s_root = d_make_root(root_inode);
|
||||
if (!sb->s_root) {
|
||||
printk(KERN_ERR "AFFS: Get root inode failed\n");
|
||||
goto out_error;
|
||||
@ -494,9 +494,6 @@ got_root:
|
||||
* Begin the cascaded cleanup ...
|
||||
*/
|
||||
out_error:
|
||||
if (root_inode)
|
||||
iput(root_inode);
|
||||
out_error_noinode:
|
||||
kfree(sbi->s_bitmap);
|
||||
affs_brelse(root_bh);
|
||||
kfree(sbi->s_prefix);
|
||||
|
@ -301,7 +301,6 @@ static int afs_fill_super(struct super_block *sb,
|
||||
{
|
||||
struct afs_super_info *as = sb->s_fs_info;
|
||||
struct afs_fid fid;
|
||||
struct dentry *root = NULL;
|
||||
struct inode *inode = NULL;
|
||||
int ret;
|
||||
|
||||
@ -327,18 +326,16 @@ static int afs_fill_super(struct super_block *sb,
|
||||
set_bit(AFS_VNODE_AUTOCELL, &AFS_FS_I(inode)->flags);
|
||||
|
||||
ret = -ENOMEM;
|
||||
root = d_alloc_root(inode);
|
||||
if (!root)
|
||||
sb->s_root = d_make_root(inode);
|
||||
if (!sb->s_root)
|
||||
goto error;
|
||||
|
||||
sb->s_d_op = &afs_fs_dentry_operations;
|
||||
sb->s_root = root;
|
||||
|
||||
_leave(" = 0");
|
||||
return 0;
|
||||
|
||||
error:
|
||||
iput(inode);
|
||||
_leave(" = %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
65
fs/aio.c
65
fs/aio.c
@ -199,16 +199,7 @@ static int aio_setup_ring(struct kioctx *ctx)
|
||||
static void ctx_rcu_free(struct rcu_head *head)
|
||||
{
|
||||
struct kioctx *ctx = container_of(head, struct kioctx, rcu_head);
|
||||
unsigned nr_events = ctx->max_reqs;
|
||||
|
||||
kmem_cache_free(kioctx_cachep, ctx);
|
||||
|
||||
if (nr_events) {
|
||||
spin_lock(&aio_nr_lock);
|
||||
BUG_ON(aio_nr - nr_events > aio_nr);
|
||||
aio_nr -= nr_events;
|
||||
spin_unlock(&aio_nr_lock);
|
||||
}
|
||||
}
|
||||
|
||||
/* __put_ioctx
|
||||
@ -217,13 +208,19 @@ static void ctx_rcu_free(struct rcu_head *head)
|
||||
*/
|
||||
static void __put_ioctx(struct kioctx *ctx)
|
||||
{
|
||||
unsigned nr_events = ctx->max_reqs;
|
||||
BUG_ON(ctx->reqs_active);
|
||||
|
||||
cancel_delayed_work(&ctx->wq);
|
||||
cancel_work_sync(&ctx->wq.work);
|
||||
cancel_delayed_work_sync(&ctx->wq);
|
||||
aio_free_ring(ctx);
|
||||
mmdrop(ctx->mm);
|
||||
ctx->mm = NULL;
|
||||
if (nr_events) {
|
||||
spin_lock(&aio_nr_lock);
|
||||
BUG_ON(aio_nr - nr_events > aio_nr);
|
||||
aio_nr -= nr_events;
|
||||
spin_unlock(&aio_nr_lock);
|
||||
}
|
||||
pr_debug("__put_ioctx: freeing %p\n", ctx);
|
||||
call_rcu(&ctx->rcu_head, ctx_rcu_free);
|
||||
}
|
||||
@ -247,7 +244,7 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
|
||||
{
|
||||
struct mm_struct *mm;
|
||||
struct kioctx *ctx;
|
||||
int did_sync = 0;
|
||||
int err = -ENOMEM;
|
||||
|
||||
/* Prevent overflows */
|
||||
if ((nr_events > (0x10000000U / sizeof(struct io_event))) ||
|
||||
@ -256,7 +253,7 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
if ((unsigned long)nr_events > aio_max_nr)
|
||||
if (!nr_events || (unsigned long)nr_events > aio_max_nr)
|
||||
return ERR_PTR(-EAGAIN);
|
||||
|
||||
ctx = kmem_cache_zalloc(kioctx_cachep, GFP_KERNEL);
|
||||
@ -280,25 +277,14 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
|
||||
goto out_freectx;
|
||||
|
||||
/* limit the number of system wide aios */
|
||||
do {
|
||||
spin_lock_bh(&aio_nr_lock);
|
||||
if (aio_nr + nr_events > aio_max_nr ||
|
||||
aio_nr + nr_events < aio_nr)
|
||||
ctx->max_reqs = 0;
|
||||
else
|
||||
aio_nr += ctx->max_reqs;
|
||||
spin_unlock_bh(&aio_nr_lock);
|
||||
if (ctx->max_reqs || did_sync)
|
||||
break;
|
||||
|
||||
/* wait for rcu callbacks to have completed before giving up */
|
||||
synchronize_rcu();
|
||||
did_sync = 1;
|
||||
ctx->max_reqs = nr_events;
|
||||
} while (1);
|
||||
|
||||
if (ctx->max_reqs == 0)
|
||||
spin_lock(&aio_nr_lock);
|
||||
if (aio_nr + nr_events > aio_max_nr ||
|
||||
aio_nr + nr_events < aio_nr) {
|
||||
spin_unlock(&aio_nr_lock);
|
||||
goto out_cleanup;
|
||||
}
|
||||
aio_nr += ctx->max_reqs;
|
||||
spin_unlock(&aio_nr_lock);
|
||||
|
||||
/* now link into global list. */
|
||||
spin_lock(&mm->ioctx_lock);
|
||||
@ -310,16 +296,13 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
|
||||
return ctx;
|
||||
|
||||
out_cleanup:
|
||||
__put_ioctx(ctx);
|
||||
return ERR_PTR(-EAGAIN);
|
||||
|
||||
err = -EAGAIN;
|
||||
aio_free_ring(ctx);
|
||||
out_freectx:
|
||||
mmdrop(mm);
|
||||
kmem_cache_free(kioctx_cachep, ctx);
|
||||
ctx = ERR_PTR(-ENOMEM);
|
||||
|
||||
dprintk("aio: error allocating ioctx %p\n", ctx);
|
||||
return ctx;
|
||||
dprintk("aio: error allocating ioctx %d\n", err);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
/* aio_cancel_all
|
||||
@ -407,10 +390,6 @@ void exit_aio(struct mm_struct *mm)
|
||||
aio_cancel_all(ctx);
|
||||
|
||||
wait_for_all_aios(ctx);
|
||||
/*
|
||||
* Ensure we don't leave the ctx on the aio_wq
|
||||
*/
|
||||
cancel_work_sync(&ctx->wq.work);
|
||||
|
||||
if (1 != atomic_read(&ctx->users))
|
||||
printk(KERN_DEBUG
|
||||
@ -920,7 +899,7 @@ static void aio_kick_handler(struct work_struct *work)
|
||||
unuse_mm(mm);
|
||||
set_fs(oldfs);
|
||||
/*
|
||||
* we're in a worker thread already, don't use queue_delayed_work,
|
||||
* we're in a worker thread already; no point using non-zero delay
|
||||
*/
|
||||
if (requeue)
|
||||
queue_delayed_work(aio_wq, &ctx->wq, 0);
|
||||
|
109
fs/anon_inodes.c
109
fs/anon_inodes.c
@ -39,19 +39,6 @@ static const struct dentry_operations anon_inodefs_dentry_operations = {
|
||||
.d_dname = anon_inodefs_dname,
|
||||
};
|
||||
|
||||
static struct dentry *anon_inodefs_mount(struct file_system_type *fs_type,
|
||||
int flags, const char *dev_name, void *data)
|
||||
{
|
||||
return mount_pseudo(fs_type, "anon_inode:", NULL,
|
||||
&anon_inodefs_dentry_operations, ANON_INODE_FS_MAGIC);
|
||||
}
|
||||
|
||||
static struct file_system_type anon_inode_fs_type = {
|
||||
.name = "anon_inodefs",
|
||||
.mount = anon_inodefs_mount,
|
||||
.kill_sb = kill_anon_super,
|
||||
};
|
||||
|
||||
/*
|
||||
* nop .set_page_dirty method so that people can use .page_mkwrite on
|
||||
* anon inodes.
|
||||
@ -65,6 +52,62 @@ static const struct address_space_operations anon_aops = {
|
||||
.set_page_dirty = anon_set_page_dirty,
|
||||
};
|
||||
|
||||
/*
|
||||
* A single inode exists for all anon_inode files. Contrary to pipes,
|
||||
* anon_inode inodes have no associated per-instance data, so we need
|
||||
* only allocate one of them.
|
||||
*/
|
||||
static struct inode *anon_inode_mkinode(struct super_block *s)
|
||||
{
|
||||
struct inode *inode = new_inode_pseudo(s);
|
||||
|
||||
if (!inode)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
inode->i_ino = get_next_ino();
|
||||
inode->i_fop = &anon_inode_fops;
|
||||
|
||||
inode->i_mapping->a_ops = &anon_aops;
|
||||
|
||||
/*
|
||||
* Mark the inode dirty from the very beginning,
|
||||
* that way it will never be moved to the dirty
|
||||
* list because mark_inode_dirty() will think
|
||||
* that it already _is_ on the dirty list.
|
||||
*/
|
||||
inode->i_state = I_DIRTY;
|
||||
inode->i_mode = S_IRUSR | S_IWUSR;
|
||||
inode->i_uid = current_fsuid();
|
||||
inode->i_gid = current_fsgid();
|
||||
inode->i_flags |= S_PRIVATE;
|
||||
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
|
||||
return inode;
|
||||
}
|
||||
|
||||
static struct dentry *anon_inodefs_mount(struct file_system_type *fs_type,
|
||||
int flags, const char *dev_name, void *data)
|
||||
{
|
||||
struct dentry *root;
|
||||
root = mount_pseudo(fs_type, "anon_inode:", NULL,
|
||||
&anon_inodefs_dentry_operations, ANON_INODE_FS_MAGIC);
|
||||
if (!IS_ERR(root)) {
|
||||
struct super_block *s = root->d_sb;
|
||||
anon_inode_inode = anon_inode_mkinode(s);
|
||||
if (IS_ERR(anon_inode_inode)) {
|
||||
dput(root);
|
||||
deactivate_locked_super(s);
|
||||
root = ERR_CAST(anon_inode_inode);
|
||||
}
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
static struct file_system_type anon_inode_fs_type = {
|
||||
.name = "anon_inodefs",
|
||||
.mount = anon_inodefs_mount,
|
||||
.kill_sb = kill_anon_super,
|
||||
};
|
||||
|
||||
/**
|
||||
* anon_inode_getfile - creates a new file instance by hooking it up to an
|
||||
* anonymous inode, and a dentry that describe the "class"
|
||||
@ -180,38 +223,6 @@ err_put_unused_fd:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(anon_inode_getfd);
|
||||
|
||||
/*
|
||||
* A single inode exists for all anon_inode files. Contrary to pipes,
|
||||
* anon_inode inodes have no associated per-instance data, so we need
|
||||
* only allocate one of them.
|
||||
*/
|
||||
static struct inode *anon_inode_mkinode(void)
|
||||
{
|
||||
struct inode *inode = new_inode_pseudo(anon_inode_mnt->mnt_sb);
|
||||
|
||||
if (!inode)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
inode->i_ino = get_next_ino();
|
||||
inode->i_fop = &anon_inode_fops;
|
||||
|
||||
inode->i_mapping->a_ops = &anon_aops;
|
||||
|
||||
/*
|
||||
* Mark the inode dirty from the very beginning,
|
||||
* that way it will never be moved to the dirty
|
||||
* list because mark_inode_dirty() will think
|
||||
* that it already _is_ on the dirty list.
|
||||
*/
|
||||
inode->i_state = I_DIRTY;
|
||||
inode->i_mode = S_IRUSR | S_IWUSR;
|
||||
inode->i_uid = current_fsuid();
|
||||
inode->i_gid = current_fsgid();
|
||||
inode->i_flags |= S_PRIVATE;
|
||||
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
|
||||
return inode;
|
||||
}
|
||||
|
||||
static int __init anon_inode_init(void)
|
||||
{
|
||||
int error;
|
||||
@ -224,16 +235,8 @@ static int __init anon_inode_init(void)
|
||||
error = PTR_ERR(anon_inode_mnt);
|
||||
goto err_unregister_filesystem;
|
||||
}
|
||||
anon_inode_inode = anon_inode_mkinode();
|
||||
if (IS_ERR(anon_inode_inode)) {
|
||||
error = PTR_ERR(anon_inode_inode);
|
||||
goto err_mntput;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_mntput:
|
||||
kern_unmount(anon_inode_mnt);
|
||||
err_unregister_filesystem:
|
||||
unregister_filesystem(&anon_inode_fs_type);
|
||||
err_exit:
|
||||
|
@ -31,11 +31,11 @@ static int __init init_autofs4_fs(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
autofs_dev_ioctl_init();
|
||||
|
||||
err = register_filesystem(&autofs_fs_type);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
autofs_dev_ioctl_init();
|
||||
autofs_dev_ioctl_exit();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -247,12 +247,9 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
|
||||
if (!ino)
|
||||
goto fail_free;
|
||||
root_inode = autofs4_get_inode(s, S_IFDIR | 0755);
|
||||
if (!root_inode)
|
||||
goto fail_ino;
|
||||
|
||||
root = d_alloc_root(root_inode);
|
||||
root = d_make_root(root_inode);
|
||||
if (!root)
|
||||
goto fail_iput;
|
||||
goto fail_ino;
|
||||
pipe = NULL;
|
||||
|
||||
root->d_fsdata = ino;
|
||||
@ -317,9 +314,6 @@ fail_fput:
|
||||
fail_dput:
|
||||
dput(root);
|
||||
goto fail_free;
|
||||
fail_iput:
|
||||
printk("autofs: get root dentry failed\n");
|
||||
iput(root_inode);
|
||||
fail_ino:
|
||||
kfree(ino);
|
||||
fail_free:
|
||||
|
@ -852,9 +852,8 @@ befs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
ret = PTR_ERR(root);
|
||||
goto unacquire_priv_sbp;
|
||||
}
|
||||
sb->s_root = d_alloc_root(root);
|
||||
sb->s_root = d_make_root(root);
|
||||
if (!sb->s_root) {
|
||||
iput(root);
|
||||
befs_error(sb, "get root inode failed");
|
||||
goto unacquire_priv_sbp;
|
||||
}
|
||||
|
@ -367,9 +367,8 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent)
|
||||
ret = PTR_ERR(inode);
|
||||
goto out2;
|
||||
}
|
||||
s->s_root = d_alloc_root(inode);
|
||||
s->s_root = d_make_root(inode);
|
||||
if (!s->s_root) {
|
||||
iput(inode);
|
||||
ret = -ENOMEM;
|
||||
goto out2;
|
||||
}
|
||||
|
@ -267,7 +267,6 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
|
||||
}
|
||||
|
||||
install_exec_creds(bprm);
|
||||
current->flags &= ~PF_FORKNOEXEC;
|
||||
|
||||
if (N_MAGIC(ex) == OMAGIC) {
|
||||
unsigned long text_addr, map_size;
|
||||
@ -454,7 +453,8 @@ out:
|
||||
|
||||
static int __init init_aout_binfmt(void)
|
||||
{
|
||||
return register_binfmt(&aout_format);
|
||||
register_binfmt(&aout_format);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit exit_aout_binfmt(void)
|
||||
|
@ -712,7 +712,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
|
||||
goto out_free_dentry;
|
||||
|
||||
/* OK, This is the point of no return */
|
||||
current->flags &= ~PF_FORKNOEXEC;
|
||||
current->mm->def_flags = def_flags;
|
||||
|
||||
/* Do this immediately, since STACK_TOP as used in setup_arg_pages
|
||||
@ -934,7 +933,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
|
||||
#endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */
|
||||
|
||||
install_exec_creds(bprm);
|
||||
current->flags &= ~PF_FORKNOEXEC;
|
||||
retval = create_elf_tables(bprm, &loc->elf_ex,
|
||||
load_addr, interp_load_addr);
|
||||
if (retval < 0) {
|
||||
@ -2077,7 +2075,8 @@ out:
|
||||
|
||||
static int __init init_elf_binfmt(void)
|
||||
{
|
||||
return register_binfmt(&elf_format);
|
||||
register_binfmt(&elf_format);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit exit_elf_binfmt(void)
|
||||
|
@ -91,7 +91,8 @@ static struct linux_binfmt elf_fdpic_format = {
|
||||
|
||||
static int __init init_elf_fdpic_binfmt(void)
|
||||
{
|
||||
return register_binfmt(&elf_fdpic_format);
|
||||
register_binfmt(&elf_fdpic_format);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit exit_elf_fdpic_binfmt(void)
|
||||
@ -334,8 +335,6 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm,
|
||||
current->mm->context.exec_fdpic_loadmap = 0;
|
||||
current->mm->context.interp_fdpic_loadmap = 0;
|
||||
|
||||
current->flags &= ~PF_FORKNOEXEC;
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
elf_fdpic_arch_lay_out_mm(&exec_params,
|
||||
&interp_params,
|
||||
@ -413,7 +412,6 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm,
|
||||
#endif
|
||||
|
||||
install_exec_creds(bprm);
|
||||
current->flags &= ~PF_FORKNOEXEC;
|
||||
if (create_elf_fdpic_tables(bprm, current->mm,
|
||||
&exec_params, &interp_params) < 0)
|
||||
goto error_kill;
|
||||
|
@ -100,7 +100,8 @@ static struct linux_binfmt em86_format = {
|
||||
|
||||
static int __init init_em86_binfmt(void)
|
||||
{
|
||||
return register_binfmt(&em86_format);
|
||||
register_binfmt(&em86_format);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit exit_em86_binfmt(void)
|
||||
|
@ -902,7 +902,6 @@ static int load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs)
|
||||
libinfo.lib_list[j].start_data:UNLOADED_LIB;
|
||||
|
||||
install_exec_creds(bprm);
|
||||
current->flags &= ~PF_FORKNOEXEC;
|
||||
|
||||
set_binfmt(&flat_format);
|
||||
|
||||
@ -950,7 +949,8 @@ static int load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs)
|
||||
|
||||
static int __init init_flat_binfmt(void)
|
||||
{
|
||||
return register_binfmt(&flat_format);
|
||||
register_binfmt(&flat_format);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
@ -726,11 +726,8 @@ static struct file_system_type bm_fs_type = {
|
||||
static int __init init_misc_binfmt(void)
|
||||
{
|
||||
int err = register_filesystem(&bm_fs_type);
|
||||
if (!err) {
|
||||
err = insert_binfmt(&misc_format);
|
||||
if (err)
|
||||
unregister_filesystem(&bm_fs_type);
|
||||
}
|
||||
if (!err)
|
||||
insert_binfmt(&misc_format);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -105,7 +105,8 @@ static struct linux_binfmt script_format = {
|
||||
|
||||
static int __init init_script_binfmt(void)
|
||||
{
|
||||
return register_binfmt(&script_format);
|
||||
register_binfmt(&script_format);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit exit_script_binfmt(void)
|
||||
|
@ -225,7 +225,6 @@ load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs)
|
||||
goto out_free;
|
||||
|
||||
/* OK, This is the point of no return */
|
||||
current->flags &= ~PF_FORKNOEXEC;
|
||||
current->personality = PER_HPUX;
|
||||
setup_new_exec(bprm);
|
||||
|
||||
@ -289,7 +288,8 @@ static int load_som_library(struct file *f)
|
||||
|
||||
static int __init init_som_binfmt(void)
|
||||
{
|
||||
return register_binfmt(&som_format);
|
||||
register_binfmt(&som_format);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit exit_som_binfmt(void)
|
||||
|
@ -629,7 +629,6 @@ static int btrfs_fill_super(struct super_block *sb,
|
||||
void *data, int silent)
|
||||
{
|
||||
struct inode *inode;
|
||||
struct dentry *root_dentry;
|
||||
struct btrfs_fs_info *fs_info = btrfs_sb(sb);
|
||||
struct btrfs_key key;
|
||||
int err;
|
||||
@ -660,15 +659,12 @@ static int btrfs_fill_super(struct super_block *sb,
|
||||
goto fail_close;
|
||||
}
|
||||
|
||||
root_dentry = d_alloc_root(inode);
|
||||
if (!root_dentry) {
|
||||
iput(inode);
|
||||
sb->s_root = d_make_root(inode);
|
||||
if (!sb->s_root) {
|
||||
err = -ENOMEM;
|
||||
goto fail_close;
|
||||
}
|
||||
|
||||
sb->s_root = root_dentry;
|
||||
|
||||
save_mount_options(sb, data);
|
||||
cleancache_init_fs(sb);
|
||||
sb->s_flags |= MS_ACTIVE;
|
||||
|
@ -646,7 +646,8 @@ lookup_again:
|
||||
* (this is used to keep track of culling, and atimes are only
|
||||
* updated by read, write and readdir but not lookup or
|
||||
* open) */
|
||||
touch_atime(cache->mnt, next);
|
||||
path.dentry = next;
|
||||
touch_atime(&path);
|
||||
}
|
||||
|
||||
/* open a file interface onto a data file */
|
||||
|
@ -655,9 +655,8 @@ static struct dentry *open_root_dentry(struct ceph_fs_client *fsc,
|
||||
dout("open_root_inode success\n");
|
||||
if (ceph_ino(inode) == CEPH_INO_ROOT &&
|
||||
fsc->sb->s_root == NULL) {
|
||||
root = d_alloc_root(inode);
|
||||
root = d_make_root(inode);
|
||||
if (!root) {
|
||||
iput(inode);
|
||||
root = ERR_PTR(-ENOMEM);
|
||||
goto out;
|
||||
}
|
||||
|
@ -119,12 +119,10 @@ cifs_read_super(struct super_block *sb)
|
||||
|
||||
if (IS_ERR(inode)) {
|
||||
rc = PTR_ERR(inode);
|
||||
inode = NULL;
|
||||
goto out_no_root;
|
||||
}
|
||||
|
||||
sb->s_root = d_alloc_root(inode);
|
||||
|
||||
sb->s_root = d_make_root(inode);
|
||||
if (!sb->s_root) {
|
||||
rc = -ENOMEM;
|
||||
goto out_no_root;
|
||||
@ -147,9 +145,6 @@ cifs_read_super(struct super_block *sb)
|
||||
|
||||
out_no_root:
|
||||
cERROR(1, "cifs_read_super: get root inode failed");
|
||||
if (inode)
|
||||
iput(inode);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -208,13 +208,12 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
|
||||
if (IS_ERR(root)) {
|
||||
error = PTR_ERR(root);
|
||||
printk("Failure of coda_cnode_make for root: error %d\n", error);
|
||||
root = NULL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
printk("coda_read_super: rootinode is %ld dev %s\n",
|
||||
root->i_ino, root->i_sb->s_id);
|
||||
sb->s_root = d_alloc_root(root);
|
||||
sb->s_root = d_make_root(root);
|
||||
if (!sb->s_root) {
|
||||
error = -EINVAL;
|
||||
goto error;
|
||||
@ -222,9 +221,6 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
|
||||
return 0;
|
||||
|
||||
error:
|
||||
if (root)
|
||||
iput(root);
|
||||
|
||||
mutex_lock(&vc->vc_mutex);
|
||||
bdi_destroy(&vc->bdi);
|
||||
vc->vc_sb = NULL;
|
||||
|
@ -58,12 +58,11 @@ struct configfs_dirent {
|
||||
extern struct mutex configfs_symlink_mutex;
|
||||
extern spinlock_t configfs_dirent_lock;
|
||||
|
||||
extern struct vfsmount * configfs_mount;
|
||||
extern struct kmem_cache *configfs_dir_cachep;
|
||||
|
||||
extern int configfs_is_root(struct config_item *item);
|
||||
|
||||
extern struct inode * configfs_new_inode(umode_t mode, struct configfs_dirent *);
|
||||
extern struct inode * configfs_new_inode(umode_t mode, struct configfs_dirent *, struct super_block *);
|
||||
extern int configfs_create(struct dentry *, umode_t mode, int (*init)(struct inode *));
|
||||
extern int configfs_inode_init(void);
|
||||
extern void configfs_inode_exit(void);
|
||||
@ -80,15 +79,15 @@ extern const unsigned char * configfs_get_name(struct configfs_dirent *sd);
|
||||
extern void configfs_drop_dentry(struct configfs_dirent *sd, struct dentry *parent);
|
||||
extern int configfs_setattr(struct dentry *dentry, struct iattr *iattr);
|
||||
|
||||
extern int configfs_pin_fs(void);
|
||||
extern struct dentry *configfs_pin_fs(void);
|
||||
extern void configfs_release_fs(void);
|
||||
|
||||
extern struct rw_semaphore configfs_rename_sem;
|
||||
extern struct super_block * configfs_sb;
|
||||
extern const struct file_operations configfs_dir_operations;
|
||||
extern const struct file_operations configfs_file_operations;
|
||||
extern const struct file_operations bin_fops;
|
||||
extern const struct inode_operations configfs_dir_inode_operations;
|
||||
extern const struct inode_operations configfs_root_inode_operations;
|
||||
extern const struct inode_operations configfs_symlink_inode_operations;
|
||||
extern const struct dentry_operations configfs_dentry_ops;
|
||||
|
||||
|
@ -264,11 +264,13 @@ static int init_symlink(struct inode * inode)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int create_dir(struct config_item * k, struct dentry * p,
|
||||
struct dentry * d)
|
||||
static int create_dir(struct config_item *k, struct dentry *d)
|
||||
{
|
||||
int error;
|
||||
umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO;
|
||||
struct dentry *p = d->d_parent;
|
||||
|
||||
BUG_ON(!k);
|
||||
|
||||
error = configfs_dirent_exists(p->d_fsdata, d->d_name.name);
|
||||
if (!error)
|
||||
@ -304,19 +306,7 @@ static int create_dir(struct config_item * k, struct dentry * p,
|
||||
|
||||
static int configfs_create_dir(struct config_item * item, struct dentry *dentry)
|
||||
{
|
||||
struct dentry * parent;
|
||||
int error = 0;
|
||||
|
||||
BUG_ON(!item);
|
||||
|
||||
if (item->ci_parent)
|
||||
parent = item->ci_parent->ci_dentry;
|
||||
else if (configfs_mount)
|
||||
parent = configfs_mount->mnt_root;
|
||||
else
|
||||
return -EFAULT;
|
||||
|
||||
error = create_dir(item,parent,dentry);
|
||||
int error = create_dir(item, dentry);
|
||||
if (!error)
|
||||
item->ci_dentry = dentry;
|
||||
return error;
|
||||
@ -1079,23 +1069,24 @@ int configfs_depend_item(struct configfs_subsystem *subsys,
|
||||
int ret;
|
||||
struct configfs_dirent *p, *root_sd, *subsys_sd = NULL;
|
||||
struct config_item *s_item = &subsys->su_group.cg_item;
|
||||
struct dentry *root;
|
||||
|
||||
/*
|
||||
* Pin the configfs filesystem. This means we can safely access
|
||||
* the root of the configfs filesystem.
|
||||
*/
|
||||
ret = configfs_pin_fs();
|
||||
if (ret)
|
||||
return ret;
|
||||
root = configfs_pin_fs();
|
||||
if (IS_ERR(root))
|
||||
return PTR_ERR(root);
|
||||
|
||||
/*
|
||||
* Next, lock the root directory. We're going to check that the
|
||||
* subsystem is really registered, and so we need to lock out
|
||||
* configfs_[un]register_subsystem().
|
||||
*/
|
||||
mutex_lock(&configfs_sb->s_root->d_inode->i_mutex);
|
||||
mutex_lock(&root->d_inode->i_mutex);
|
||||
|
||||
root_sd = configfs_sb->s_root->d_fsdata;
|
||||
root_sd = root->d_fsdata;
|
||||
|
||||
list_for_each_entry(p, &root_sd->s_children, s_sibling) {
|
||||
if (p->s_type & CONFIGFS_DIR) {
|
||||
@ -1129,7 +1120,7 @@ int configfs_depend_item(struct configfs_subsystem *subsys,
|
||||
out_unlock_dirent_lock:
|
||||
spin_unlock(&configfs_dirent_lock);
|
||||
out_unlock_fs:
|
||||
mutex_unlock(&configfs_sb->s_root->d_inode->i_mutex);
|
||||
mutex_unlock(&root->d_inode->i_mutex);
|
||||
|
||||
/*
|
||||
* If we succeeded, the fs is pinned via other methods. If not,
|
||||
@ -1183,11 +1174,6 @@ static int configfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
|
||||
struct module *subsys_owner = NULL, *new_item_owner = NULL;
|
||||
char *name;
|
||||
|
||||
if (dentry->d_parent == configfs_sb->s_root) {
|
||||
ret = -EPERM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
sd = dentry->d_parent->d_fsdata;
|
||||
|
||||
/*
|
||||
@ -1359,9 +1345,6 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry)
|
||||
struct module *subsys_owner = NULL, *dead_item_owner = NULL;
|
||||
int ret;
|
||||
|
||||
if (dentry->d_parent == configfs_sb->s_root)
|
||||
return -EPERM;
|
||||
|
||||
sd = dentry->d_fsdata;
|
||||
if (sd->s_type & CONFIGFS_USET_DEFAULT)
|
||||
return -EPERM;
|
||||
@ -1459,6 +1442,11 @@ const struct inode_operations configfs_dir_inode_operations = {
|
||||
.setattr = configfs_setattr,
|
||||
};
|
||||
|
||||
const struct inode_operations configfs_root_inode_operations = {
|
||||
.lookup = configfs_lookup,
|
||||
.setattr = configfs_setattr,
|
||||
};
|
||||
|
||||
#if 0
|
||||
int configfs_rename_dir(struct config_item * item, const char *new_name)
|
||||
{
|
||||
@ -1546,6 +1534,7 @@ static inline unsigned char dt_type(struct configfs_dirent *sd)
|
||||
static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
|
||||
{
|
||||
struct dentry *dentry = filp->f_path.dentry;
|
||||
struct super_block *sb = dentry->d_sb;
|
||||
struct configfs_dirent * parent_sd = dentry->d_fsdata;
|
||||
struct configfs_dirent *cursor = filp->private_data;
|
||||
struct list_head *p, *q = &cursor->s_sibling;
|
||||
@ -1608,7 +1597,7 @@ static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir
|
||||
ino = inode->i_ino;
|
||||
spin_unlock(&configfs_dirent_lock);
|
||||
if (!inode)
|
||||
ino = iunique(configfs_sb, 2);
|
||||
ino = iunique(sb, 2);
|
||||
|
||||
if (filldir(dirent, name, len, filp->f_pos, ino,
|
||||
dt_type(next)) < 0)
|
||||
@ -1680,27 +1669,27 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys)
|
||||
struct config_group *group = &subsys->su_group;
|
||||
struct qstr name;
|
||||
struct dentry *dentry;
|
||||
struct dentry *root;
|
||||
struct configfs_dirent *sd;
|
||||
|
||||
err = configfs_pin_fs();
|
||||
if (err)
|
||||
return err;
|
||||
root = configfs_pin_fs();
|
||||
if (IS_ERR(root))
|
||||
return PTR_ERR(root);
|
||||
|
||||
if (!group->cg_item.ci_name)
|
||||
group->cg_item.ci_name = group->cg_item.ci_namebuf;
|
||||
|
||||
sd = configfs_sb->s_root->d_fsdata;
|
||||
sd = root->d_fsdata;
|
||||
link_group(to_config_group(sd->s_element), group);
|
||||
|
||||
mutex_lock_nested(&configfs_sb->s_root->d_inode->i_mutex,
|
||||
I_MUTEX_PARENT);
|
||||
mutex_lock_nested(&root->d_inode->i_mutex, I_MUTEX_PARENT);
|
||||
|
||||
name.name = group->cg_item.ci_name;
|
||||
name.len = strlen(name.name);
|
||||
name.hash = full_name_hash(name.name, name.len);
|
||||
|
||||
err = -ENOMEM;
|
||||
dentry = d_alloc(configfs_sb->s_root, &name);
|
||||
dentry = d_alloc(root, &name);
|
||||
if (dentry) {
|
||||
d_add(dentry, NULL);
|
||||
|
||||
@ -1717,7 +1706,7 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys)
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&configfs_sb->s_root->d_inode->i_mutex);
|
||||
mutex_unlock(&root->d_inode->i_mutex);
|
||||
|
||||
if (err) {
|
||||
unlink_group(group);
|
||||
@ -1731,13 +1720,14 @@ void configfs_unregister_subsystem(struct configfs_subsystem *subsys)
|
||||
{
|
||||
struct config_group *group = &subsys->su_group;
|
||||
struct dentry *dentry = group->cg_item.ci_dentry;
|
||||
struct dentry *root = dentry->d_sb->s_root;
|
||||
|
||||
if (dentry->d_parent != configfs_sb->s_root) {
|
||||
if (dentry->d_parent != root) {
|
||||
printk(KERN_ERR "configfs: Tried to unregister non-subsystem!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_lock_nested(&configfs_sb->s_root->d_inode->i_mutex,
|
||||
mutex_lock_nested(&root->d_inode->i_mutex,
|
||||
I_MUTEX_PARENT);
|
||||
mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD);
|
||||
mutex_lock(&configfs_symlink_mutex);
|
||||
@ -1754,7 +1744,7 @@ void configfs_unregister_subsystem(struct configfs_subsystem *subsys)
|
||||
|
||||
d_delete(dentry);
|
||||
|
||||
mutex_unlock(&configfs_sb->s_root->d_inode->i_mutex);
|
||||
mutex_unlock(&root->d_inode->i_mutex);
|
||||
|
||||
dput(dentry);
|
||||
|
||||
|
@ -44,8 +44,6 @@
|
||||
static struct lock_class_key default_group_class[MAX_LOCK_DEPTH];
|
||||
#endif
|
||||
|
||||
extern struct super_block * configfs_sb;
|
||||
|
||||
static const struct address_space_operations configfs_aops = {
|
||||
.readpage = simple_readpage,
|
||||
.write_begin = simple_write_begin,
|
||||
@ -132,9 +130,10 @@ static inline void set_inode_attr(struct inode * inode, struct iattr * iattr)
|
||||
inode->i_ctime = iattr->ia_ctime;
|
||||
}
|
||||
|
||||
struct inode *configfs_new_inode(umode_t mode, struct configfs_dirent * sd)
|
||||
struct inode *configfs_new_inode(umode_t mode, struct configfs_dirent *sd,
|
||||
struct super_block *s)
|
||||
{
|
||||
struct inode * inode = new_inode(configfs_sb);
|
||||
struct inode * inode = new_inode(s);
|
||||
if (inode) {
|
||||
inode->i_ino = get_next_ino();
|
||||
inode->i_mapping->a_ops = &configfs_aops;
|
||||
@ -188,36 +187,35 @@ static void configfs_set_inode_lock_class(struct configfs_dirent *sd,
|
||||
int configfs_create(struct dentry * dentry, umode_t mode, int (*init)(struct inode *))
|
||||
{
|
||||
int error = 0;
|
||||
struct inode * inode = NULL;
|
||||
if (dentry) {
|
||||
if (!dentry->d_inode) {
|
||||
struct configfs_dirent *sd = dentry->d_fsdata;
|
||||
if ((inode = configfs_new_inode(mode, sd))) {
|
||||
if (dentry->d_parent && dentry->d_parent->d_inode) {
|
||||
struct inode *p_inode = dentry->d_parent->d_inode;
|
||||
p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME;
|
||||
}
|
||||
configfs_set_inode_lock_class(sd, inode);
|
||||
goto Proceed;
|
||||
}
|
||||
else
|
||||
error = -ENOMEM;
|
||||
} else
|
||||
error = -EEXIST;
|
||||
} else
|
||||
error = -ENOENT;
|
||||
goto Done;
|
||||
struct inode *inode = NULL;
|
||||
struct configfs_dirent *sd;
|
||||
struct inode *p_inode;
|
||||
|
||||
Proceed:
|
||||
if (init)
|
||||
if (!dentry)
|
||||
return -ENOENT;
|
||||
|
||||
if (dentry->d_inode)
|
||||
return -EEXIST;
|
||||
|
||||
sd = dentry->d_fsdata;
|
||||
inode = configfs_new_inode(mode, sd, dentry->d_sb);
|
||||
if (!inode)
|
||||
return -ENOMEM;
|
||||
|
||||
p_inode = dentry->d_parent->d_inode;
|
||||
p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME;
|
||||
configfs_set_inode_lock_class(sd, inode);
|
||||
|
||||
if (init) {
|
||||
error = init(inode);
|
||||
if (!error) {
|
||||
d_instantiate(dentry, inode);
|
||||
if (S_ISDIR(mode) || S_ISLNK(mode))
|
||||
dget(dentry); /* pin link and directory dentries in core */
|
||||
} else
|
||||
iput(inode);
|
||||
Done:
|
||||
if (error) {
|
||||
iput(inode);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
d_instantiate(dentry, inode);
|
||||
if (S_ISDIR(mode) || S_ISLNK(mode))
|
||||
dget(dentry); /* pin link and directory dentries in core */
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -37,8 +37,7 @@
|
||||
/* Random magic number */
|
||||
#define CONFIGFS_MAGIC 0x62656570
|
||||
|
||||
struct vfsmount * configfs_mount = NULL;
|
||||
struct super_block * configfs_sb = NULL;
|
||||
static struct vfsmount *configfs_mount = NULL;
|
||||
struct kmem_cache *configfs_dir_cachep;
|
||||
static int configfs_mnt_count = 0;
|
||||
|
||||
@ -77,12 +76,11 @@ static int configfs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
sb->s_magic = CONFIGFS_MAGIC;
|
||||
sb->s_op = &configfs_ops;
|
||||
sb->s_time_gran = 1;
|
||||
configfs_sb = sb;
|
||||
|
||||
inode = configfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
|
||||
&configfs_root);
|
||||
&configfs_root, sb);
|
||||
if (inode) {
|
||||
inode->i_op = &configfs_dir_inode_operations;
|
||||
inode->i_op = &configfs_root_inode_operations;
|
||||
inode->i_fop = &configfs_dir_operations;
|
||||
/* directory inodes start off with i_nlink == 2 (for "." entry) */
|
||||
inc_nlink(inode);
|
||||
@ -91,10 +89,9 @@ static int configfs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
root = d_alloc_root(inode);
|
||||
root = d_make_root(inode);
|
||||
if (!root) {
|
||||
pr_debug("%s: could not get root dentry!\n",__func__);
|
||||
iput(inode);
|
||||
return -ENOMEM;
|
||||
}
|
||||
config_group_init(&configfs_root_group);
|
||||
@ -118,10 +115,11 @@ static struct file_system_type configfs_fs_type = {
|
||||
.kill_sb = kill_litter_super,
|
||||
};
|
||||
|
||||
int configfs_pin_fs(void)
|
||||
struct dentry *configfs_pin_fs(void)
|
||||
{
|
||||
return simple_pin_fs(&configfs_fs_type, &configfs_mount,
|
||||
int err = simple_pin_fs(&configfs_fs_type, &configfs_mount,
|
||||
&configfs_mnt_count);
|
||||
return err ? ERR_PTR(err) : configfs_mount->mnt_root;
|
||||
}
|
||||
|
||||
void configfs_release_fs(void)
|
||||
|
@ -110,13 +110,13 @@ out:
|
||||
|
||||
|
||||
static int get_target(const char *symname, struct path *path,
|
||||
struct config_item **target)
|
||||
struct config_item **target, struct super_block *sb)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = kern_path(symname, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, path);
|
||||
if (!ret) {
|
||||
if (path->dentry->d_sb == configfs_sb) {
|
||||
if (path->dentry->d_sb == sb) {
|
||||
*target = configfs_get_config_item(path->dentry);
|
||||
if (!*target) {
|
||||
ret = -ENOENT;
|
||||
@ -141,10 +141,6 @@ int configfs_symlink(struct inode *dir, struct dentry *dentry, const char *symna
|
||||
struct config_item *target_item = NULL;
|
||||
struct config_item_type *type;
|
||||
|
||||
ret = -EPERM; /* What lack-of-symlink returns */
|
||||
if (dentry->d_parent == configfs_sb->s_root)
|
||||
goto out;
|
||||
|
||||
sd = dentry->d_parent->d_fsdata;
|
||||
/*
|
||||
* Fake invisibility if dir belongs to a group/default groups hierarchy
|
||||
@ -162,7 +158,7 @@ int configfs_symlink(struct inode *dir, struct dentry *dentry, const char *symna
|
||||
!type->ct_item_ops->allow_link)
|
||||
goto out_put;
|
||||
|
||||
ret = get_target(symname, &path, &target_item);
|
||||
ret = get_target(symname, &path, &target_item, dentry->d_sb);
|
||||
if (ret)
|
||||
goto out_put;
|
||||
|
||||
@ -198,8 +194,6 @@ int configfs_unlink(struct inode *dir, struct dentry *dentry)
|
||||
if (!(sd->s_type & CONFIGFS_ITEM_LINK))
|
||||
goto out;
|
||||
|
||||
BUG_ON(dentry->d_parent == configfs_sb->s_root);
|
||||
|
||||
sl = sd->s_element;
|
||||
|
||||
parent_item = configfs_get_config_item(dentry->d_parent);
|
||||
|
@ -318,11 +318,9 @@ static int cramfs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
root = get_cramfs_inode(sb, &super.root, 0);
|
||||
if (IS_ERR(root))
|
||||
goto out;
|
||||
sb->s_root = d_alloc_root(root);
|
||||
if (!sb->s_root) {
|
||||
iput(root);
|
||||
sb->s_root = d_make_root(root);
|
||||
if (!sb->s_root)
|
||||
goto out;
|
||||
}
|
||||
return 0;
|
||||
out:
|
||||
kfree(sbi);
|
||||
|
24
fs/dcache.c
24
fs/dcache.c
@ -1466,30 +1466,6 @@ struct dentry *d_instantiate_unique(struct dentry *entry, struct inode *inode)
|
||||
|
||||
EXPORT_SYMBOL(d_instantiate_unique);
|
||||
|
||||
/**
|
||||
* d_alloc_root - allocate root dentry
|
||||
* @root_inode: inode to allocate the root for
|
||||
*
|
||||
* Allocate a root ("/") dentry for the inode given. The inode is
|
||||
* instantiated and returned. %NULL is returned if there is insufficient
|
||||
* memory or the inode passed is %NULL.
|
||||
*/
|
||||
|
||||
struct dentry * d_alloc_root(struct inode * root_inode)
|
||||
{
|
||||
struct dentry *res = NULL;
|
||||
|
||||
if (root_inode) {
|
||||
static const struct qstr name = { .name = "/", .len = 1 };
|
||||
|
||||
res = __d_alloc(root_inode->i_sb, &name);
|
||||
if (res)
|
||||
d_instantiate(res, root_inode);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL(d_alloc_root);
|
||||
|
||||
struct dentry *d_make_root(struct inode *root_inode)
|
||||
{
|
||||
struct dentry *res = NULL;
|
||||
|
@ -611,7 +611,7 @@ static const struct file_operations fops_regset32 = {
|
||||
* %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling
|
||||
* code.
|
||||
*/
|
||||
struct dentry *debugfs_create_regset32(const char *name, mode_t mode,
|
||||
struct dentry *debugfs_create_regset32(const char *name, umode_t mode,
|
||||
struct dentry *parent,
|
||||
struct debugfs_regset32 *regset)
|
||||
{
|
||||
|
@ -374,12 +374,11 @@ devpts_fill_super(struct super_block *s, void *data, int silent)
|
||||
inode->i_fop = &simple_dir_operations;
|
||||
set_nlink(inode, 2);
|
||||
|
||||
s->s_root = d_alloc_root(inode);
|
||||
s->s_root = d_make_root(inode);
|
||||
if (s->s_root)
|
||||
return 0;
|
||||
|
||||
printk(KERN_ERR "devpts: get root dentry failed\n");
|
||||
iput(inode);
|
||||
|
||||
fail:
|
||||
return -ENOMEM;
|
||||
|
@ -48,8 +48,7 @@ static ssize_t ecryptfs_read_update_atime(struct kiocb *iocb,
|
||||
unsigned long nr_segs, loff_t pos)
|
||||
{
|
||||
ssize_t rc;
|
||||
struct dentry *lower_dentry;
|
||||
struct vfsmount *lower_vfsmount;
|
||||
struct path lower;
|
||||
struct file *file = iocb->ki_filp;
|
||||
|
||||
rc = generic_file_aio_read(iocb, iov, nr_segs, pos);
|
||||
@ -60,9 +59,9 @@ static ssize_t ecryptfs_read_update_atime(struct kiocb *iocb,
|
||||
if (-EIOCBQUEUED == rc)
|
||||
rc = wait_on_sync_kiocb(iocb);
|
||||
if (rc >= 0) {
|
||||
lower_dentry = ecryptfs_dentry_to_lower(file->f_path.dentry);
|
||||
lower_vfsmount = ecryptfs_dentry_to_lower_mnt(file->f_path.dentry);
|
||||
touch_atime(lower_vfsmount, lower_dentry);
|
||||
lower.dentry = ecryptfs_dentry_to_lower(file->f_path.dentry);
|
||||
lower.mnt = ecryptfs_dentry_to_lower_mnt(file->f_path.dentry);
|
||||
touch_atime(&lower);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
@ -550,9 +550,8 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags
|
||||
if (IS_ERR(inode))
|
||||
goto out_free;
|
||||
|
||||
s->s_root = d_alloc_root(inode);
|
||||
s->s_root = d_make_root(inode);
|
||||
if (!s->s_root) {
|
||||
iput(inode);
|
||||
rc = -ENOMEM;
|
||||
goto out_free;
|
||||
}
|
||||
@ -795,15 +794,10 @@ static int __init ecryptfs_init(void)
|
||||
"Failed to allocate one or more kmem_cache objects\n");
|
||||
goto out;
|
||||
}
|
||||
rc = register_filesystem(&ecryptfs_fs_type);
|
||||
if (rc) {
|
||||
printk(KERN_ERR "Failed to register filesystem\n");
|
||||
goto out_free_kmem_caches;
|
||||
}
|
||||
rc = do_sysfs_registration();
|
||||
if (rc) {
|
||||
printk(KERN_ERR "sysfs registration failed\n");
|
||||
goto out_unregister_filesystem;
|
||||
goto out_free_kmem_caches;
|
||||
}
|
||||
rc = ecryptfs_init_kthread();
|
||||
if (rc) {
|
||||
@ -824,19 +818,24 @@ static int __init ecryptfs_init(void)
|
||||
"rc = [%d]\n", rc);
|
||||
goto out_release_messaging;
|
||||
}
|
||||
rc = register_filesystem(&ecryptfs_fs_type);
|
||||
if (rc) {
|
||||
printk(KERN_ERR "Failed to register filesystem\n");
|
||||
goto out_destroy_crypto;
|
||||
}
|
||||
if (ecryptfs_verbosity > 0)
|
||||
printk(KERN_CRIT "eCryptfs verbosity set to %d. Secret values "
|
||||
"will be written to the syslog!\n", ecryptfs_verbosity);
|
||||
|
||||
goto out;
|
||||
out_destroy_crypto:
|
||||
ecryptfs_destroy_crypto();
|
||||
out_release_messaging:
|
||||
ecryptfs_release_messaging();
|
||||
out_destroy_kthread:
|
||||
ecryptfs_destroy_kthread();
|
||||
out_do_sysfs_unregistration:
|
||||
do_sysfs_unregistration();
|
||||
out_unregister_filesystem:
|
||||
unregister_filesystem(&ecryptfs_fs_type);
|
||||
out_free_kmem_caches:
|
||||
ecryptfs_free_kmem_caches();
|
||||
out:
|
||||
|
@ -184,7 +184,6 @@ static int ecryptfs_show_options(struct seq_file *m, struct dentry *root)
|
||||
const struct super_operations ecryptfs_sops = {
|
||||
.alloc_inode = ecryptfs_alloc_inode,
|
||||
.destroy_inode = ecryptfs_destroy_inode,
|
||||
.drop_inode = generic_drop_inode,
|
||||
.statfs = ecryptfs_statfs,
|
||||
.remount_fs = NULL,
|
||||
.evict_inode = ecryptfs_evict_inode,
|
||||
|
@ -317,10 +317,9 @@ static int efs_fill_super(struct super_block *s, void *d, int silent)
|
||||
goto out_no_fs;
|
||||
}
|
||||
|
||||
s->s_root = d_alloc_root(root);
|
||||
s->s_root = d_make_root(root);
|
||||
if (!(s->s_root)) {
|
||||
printk(KERN_ERR "EFS: get root dentry failed\n");
|
||||
iput(root);
|
||||
ret = -ENOMEM;
|
||||
goto out_no_fs;
|
||||
}
|
||||
|
@ -81,15 +81,13 @@ static atomic_t call_count = ATOMIC_INIT(1);
|
||||
static LIST_HEAD(formats);
|
||||
static DEFINE_RWLOCK(binfmt_lock);
|
||||
|
||||
int __register_binfmt(struct linux_binfmt * fmt, int insert)
|
||||
void __register_binfmt(struct linux_binfmt * fmt, int insert)
|
||||
{
|
||||
if (!fmt)
|
||||
return -EINVAL;
|
||||
BUG_ON(!fmt);
|
||||
write_lock(&binfmt_lock);
|
||||
insert ? list_add(&fmt->lh, &formats) :
|
||||
list_add_tail(&fmt->lh, &formats);
|
||||
write_unlock(&binfmt_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(__register_binfmt);
|
||||
@ -1115,7 +1113,7 @@ int flush_old_exec(struct linux_binprm * bprm)
|
||||
bprm->mm = NULL; /* We're using it now */
|
||||
|
||||
set_fs(USER_DS);
|
||||
current->flags &= ~(PF_RANDOMIZE | PF_KTHREAD);
|
||||
current->flags &= ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD);
|
||||
flush_thread();
|
||||
current->personality &= ~bprm->per_clear;
|
||||
|
||||
|
@ -143,9 +143,6 @@ static int exofs_link(struct dentry *old_dentry, struct inode *dir,
|
||||
{
|
||||
struct inode *inode = old_dentry->d_inode;
|
||||
|
||||
if (inode->i_nlink >= EXOFS_LINK_MAX)
|
||||
return -EMLINK;
|
||||
|
||||
inode->i_ctime = CURRENT_TIME;
|
||||
inode_inc_link_count(inode);
|
||||
ihold(inode);
|
||||
@ -156,10 +153,7 @@ static int exofs_link(struct dentry *old_dentry, struct inode *dir,
|
||||
static int exofs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct inode *inode;
|
||||
int err = -EMLINK;
|
||||
|
||||
if (dir->i_nlink >= EXOFS_LINK_MAX)
|
||||
goto out;
|
||||
int err;
|
||||
|
||||
inode_inc_link_count(dir);
|
||||
|
||||
@ -275,11 +269,6 @@ static int exofs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
if (err)
|
||||
goto out_dir;
|
||||
} else {
|
||||
if (dir_de) {
|
||||
err = -EMLINK;
|
||||
if (new_dir->i_nlink >= EXOFS_LINK_MAX)
|
||||
goto out_dir;
|
||||
}
|
||||
err = exofs_add_link(new_dentry, old_inode);
|
||||
if (err)
|
||||
goto out_dir;
|
||||
|
@ -754,6 +754,7 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
sb->s_blocksize = EXOFS_BLKSIZE;
|
||||
sb->s_blocksize_bits = EXOFS_BLKSHIFT;
|
||||
sb->s_maxbytes = MAX_LFS_FILESIZE;
|
||||
sb->s_max_links = EXOFS_LINK_MAX;
|
||||
atomic_set(&sbi->s_curr_pending, 0);
|
||||
sb->s_bdev = NULL;
|
||||
sb->s_dev = 0;
|
||||
@ -818,9 +819,8 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
ret = PTR_ERR(root);
|
||||
goto free_sbi;
|
||||
}
|
||||
sb->s_root = d_alloc_root(root);
|
||||
sb->s_root = d_make_root(root);
|
||||
if (!sb->s_root) {
|
||||
iput(root);
|
||||
EXOFS_ERR("ERROR: get root inode failed\n");
|
||||
ret = -ENOMEM;
|
||||
goto free_sbi;
|
||||
|
@ -195,9 +195,6 @@ static int ext2_link (struct dentry * old_dentry, struct inode * dir,
|
||||
struct inode *inode = old_dentry->d_inode;
|
||||
int err;
|
||||
|
||||
if (inode->i_nlink >= EXT2_LINK_MAX)
|
||||
return -EMLINK;
|
||||
|
||||
dquot_initialize(dir);
|
||||
|
||||
inode->i_ctime = CURRENT_TIME_SEC;
|
||||
@ -217,10 +214,7 @@ static int ext2_link (struct dentry * old_dentry, struct inode * dir,
|
||||
static int ext2_mkdir(struct inode * dir, struct dentry * dentry, umode_t mode)
|
||||
{
|
||||
struct inode * inode;
|
||||
int err = -EMLINK;
|
||||
|
||||
if (dir->i_nlink >= EXT2_LINK_MAX)
|
||||
goto out;
|
||||
int err;
|
||||
|
||||
dquot_initialize(dir);
|
||||
|
||||
@ -346,11 +340,6 @@ static int ext2_rename (struct inode * old_dir, struct dentry * old_dentry,
|
||||
drop_nlink(new_inode);
|
||||
inode_dec_link_count(new_inode);
|
||||
} else {
|
||||
if (dir_de) {
|
||||
err = -EMLINK;
|
||||
if (new_dir->i_nlink >= EXT2_LINK_MAX)
|
||||
goto out_dir;
|
||||
}
|
||||
err = ext2_add_link(new_dentry, old_inode);
|
||||
if (err)
|
||||
goto out_dir;
|
||||
|
@ -919,6 +919,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
|
||||
}
|
||||
|
||||
sb->s_maxbytes = ext2_max_size(sb->s_blocksize_bits);
|
||||
sb->s_max_links = EXT2_LINK_MAX;
|
||||
|
||||
if (le32_to_cpu(es->s_rev_level) == EXT2_GOOD_OLD_REV) {
|
||||
sbi->s_inode_size = EXT2_GOOD_OLD_INODE_SIZE;
|
||||
@ -1087,9 +1088,8 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
|
||||
goto failed_mount3;
|
||||
}
|
||||
|
||||
sb->s_root = d_alloc_root(root);
|
||||
sb->s_root = d_make_root(root);
|
||||
if (!sb->s_root) {
|
||||
iput(root);
|
||||
ext2_msg(sb, KERN_ERR, "error: get root inode failed");
|
||||
ret = -ENOMEM;
|
||||
goto failed_mount3;
|
||||
|
@ -2046,10 +2046,9 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
|
||||
ext3_msg(sb, KERN_ERR, "error: corrupt root inode, run e2fsck");
|
||||
goto failed_mount3;
|
||||
}
|
||||
sb->s_root = d_alloc_root(root);
|
||||
sb->s_root = d_make_root(root);
|
||||
if (!sb->s_root) {
|
||||
ext3_msg(sb, KERN_ERR, "error: get root dentry failed");
|
||||
iput(root);
|
||||
ret = -ENOMEM;
|
||||
goto failed_mount3;
|
||||
}
|
||||
|
@ -3735,9 +3735,8 @@ no_journal:
|
||||
iput(root);
|
||||
goto failed_mount4;
|
||||
}
|
||||
sb->s_root = d_alloc_root(root);
|
||||
sb->s_root = d_make_root(root);
|
||||
if (!sb->s_root) {
|
||||
iput(root);
|
||||
ext4_msg(sb, KERN_ERR, "get root dentry failed");
|
||||
ret = -ENOMEM;
|
||||
goto failed_mount4;
|
||||
@ -5056,6 +5055,9 @@ static int __init ext4_init_fs(void)
|
||||
{
|
||||
int i, err;
|
||||
|
||||
ext4_li_info = NULL;
|
||||
mutex_init(&ext4_li_mtx);
|
||||
|
||||
ext4_check_flag_values();
|
||||
|
||||
for (i = 0; i < EXT4_WQ_HASH_SZ; i++) {
|
||||
@ -5094,8 +5096,6 @@ static int __init ext4_init_fs(void)
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
ext4_li_info = NULL;
|
||||
mutex_init(&ext4_li_mtx);
|
||||
return 0;
|
||||
out:
|
||||
unregister_as_ext2();
|
||||
|
@ -1496,11 +1496,13 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
|
||||
root_inode->i_ino = MSDOS_ROOT_INO;
|
||||
root_inode->i_version = 1;
|
||||
error = fat_read_root(root_inode);
|
||||
if (error < 0)
|
||||
if (error < 0) {
|
||||
iput(root_inode);
|
||||
goto out_fail;
|
||||
}
|
||||
error = -ENOMEM;
|
||||
insert_inode_hash(root_inode);
|
||||
sb->s_root = d_alloc_root(root_inode);
|
||||
sb->s_root = d_make_root(root_inode);
|
||||
if (!sb->s_root) {
|
||||
fat_msg(sb, KERN_ERR, "get root inode failed");
|
||||
goto out_fail;
|
||||
@ -1516,8 +1518,6 @@ out_invalid:
|
||||
out_fail:
|
||||
if (fat_inode)
|
||||
iput(fat_inode);
|
||||
if (root_inode)
|
||||
iput(root_inode);
|
||||
unload_nls(sbi->nls_io);
|
||||
unload_nls(sbi->nls_disk);
|
||||
if (sbi->options.iocharset != fat_default_iocharset)
|
||||
|
@ -204,7 +204,7 @@ EXPORT_SYMBOL(alloc_file);
|
||||
* to write to @file, along with access to write through
|
||||
* its vfsmount.
|
||||
*/
|
||||
void drop_file_write_access(struct file *file)
|
||||
static void drop_file_write_access(struct file *file)
|
||||
{
|
||||
struct vfsmount *mnt = file->f_path.mnt;
|
||||
struct dentry *dentry = file->f_path.dentry;
|
||||
@ -219,7 +219,6 @@ void drop_file_write_access(struct file *file)
|
||||
mnt_drop_write(mnt);
|
||||
file_release_write(file);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drop_file_write_access);
|
||||
|
||||
/* the real guts of fput() - releasing the last reference to file
|
||||
*/
|
||||
|
@ -224,9 +224,8 @@ static int vxfs_fill_super(struct super_block *sbp, void *dp, int silent)
|
||||
ret = PTR_ERR(root);
|
||||
goto out;
|
||||
}
|
||||
sbp->s_root = d_alloc_root(root);
|
||||
sbp->s_root = d_make_root(root);
|
||||
if (!sbp->s_root) {
|
||||
iput(root);
|
||||
printk(KERN_WARNING "vxfs: unable to get root dentry.\n");
|
||||
goto out_free_ilist;
|
||||
}
|
||||
|
@ -26,11 +26,11 @@ void set_fs_root(struct fs_struct *fs, struct path *path)
|
||||
{
|
||||
struct path old_root;
|
||||
|
||||
path_get_longterm(path);
|
||||
spin_lock(&fs->lock);
|
||||
write_seqcount_begin(&fs->seq);
|
||||
old_root = fs->root;
|
||||
fs->root = *path;
|
||||
path_get_longterm(path);
|
||||
write_seqcount_end(&fs->seq);
|
||||
spin_unlock(&fs->lock);
|
||||
if (old_root.dentry)
|
||||
@ -45,11 +45,11 @@ void set_fs_pwd(struct fs_struct *fs, struct path *path)
|
||||
{
|
||||
struct path old_pwd;
|
||||
|
||||
path_get_longterm(path);
|
||||
spin_lock(&fs->lock);
|
||||
write_seqcount_begin(&fs->seq);
|
||||
old_pwd = fs->pwd;
|
||||
fs->pwd = *path;
|
||||
path_get_longterm(path);
|
||||
write_seqcount_end(&fs->seq);
|
||||
spin_unlock(&fs->lock);
|
||||
|
||||
@ -57,6 +57,14 @@ void set_fs_pwd(struct fs_struct *fs, struct path *path)
|
||||
path_put_longterm(&old_pwd);
|
||||
}
|
||||
|
||||
static inline int replace_path(struct path *p, const struct path *old, const struct path *new)
|
||||
{
|
||||
if (likely(p->dentry != old->dentry || p->mnt != old->mnt))
|
||||
return 0;
|
||||
*p = *new;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void chroot_fs_refs(struct path *old_root, struct path *new_root)
|
||||
{
|
||||
struct task_struct *g, *p;
|
||||
@ -68,21 +76,16 @@ void chroot_fs_refs(struct path *old_root, struct path *new_root)
|
||||
task_lock(p);
|
||||
fs = p->fs;
|
||||
if (fs) {
|
||||
int hits = 0;
|
||||
spin_lock(&fs->lock);
|
||||
write_seqcount_begin(&fs->seq);
|
||||
if (fs->root.dentry == old_root->dentry
|
||||
&& fs->root.mnt == old_root->mnt) {
|
||||
path_get_longterm(new_root);
|
||||
fs->root = *new_root;
|
||||
count++;
|
||||
}
|
||||
if (fs->pwd.dentry == old_root->dentry
|
||||
&& fs->pwd.mnt == old_root->mnt) {
|
||||
path_get_longterm(new_root);
|
||||
fs->pwd = *new_root;
|
||||
count++;
|
||||
}
|
||||
hits += replace_path(&fs->root, old_root, new_root);
|
||||
hits += replace_path(&fs->pwd, old_root, new_root);
|
||||
write_seqcount_end(&fs->seq);
|
||||
while (hits--) {
|
||||
count++;
|
||||
path_get_longterm(new_root);
|
||||
}
|
||||
spin_unlock(&fs->lock);
|
||||
}
|
||||
task_unlock(p);
|
||||
@ -107,10 +110,8 @@ void exit_fs(struct task_struct *tsk)
|
||||
int kill;
|
||||
task_lock(tsk);
|
||||
spin_lock(&fs->lock);
|
||||
write_seqcount_begin(&fs->seq);
|
||||
tsk->fs = NULL;
|
||||
kill = !--fs->users;
|
||||
write_seqcount_end(&fs->seq);
|
||||
spin_unlock(&fs->lock);
|
||||
task_unlock(tsk);
|
||||
if (kill)
|
||||
|
@ -988,14 +988,9 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
|
||||
|
||||
err = -ENOMEM;
|
||||
root = fuse_get_root_inode(sb, d.rootmode);
|
||||
if (!root)
|
||||
root_dentry = d_make_root(root);
|
||||
if (!root_dentry)
|
||||
goto err_put_conn;
|
||||
|
||||
root_dentry = d_alloc_root(root);
|
||||
if (!root_dentry) {
|
||||
iput(root);
|
||||
goto err_put_conn;
|
||||
}
|
||||
/* only now - we want root dentry with NULL ->d_op */
|
||||
sb->s_d_op = &fuse_dentry_operations;
|
||||
|
||||
|
@ -431,10 +431,9 @@ static int gfs2_lookup_root(struct super_block *sb, struct dentry **dptr,
|
||||
fs_err(sdp, "can't read in %s inode: %ld\n", name, PTR_ERR(inode));
|
||||
return PTR_ERR(inode);
|
||||
}
|
||||
dentry = d_alloc_root(inode);
|
||||
dentry = d_make_root(inode);
|
||||
if (!dentry) {
|
||||
fs_err(sdp, "can't alloc %s dentry\n", name);
|
||||
iput(inode);
|
||||
return -ENOMEM;
|
||||
}
|
||||
*dptr = dentry;
|
||||
|
@ -430,15 +430,13 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
|
||||
sb->s_d_op = &hfs_dentry_operations;
|
||||
res = -ENOMEM;
|
||||
sb->s_root = d_alloc_root(root_inode);
|
||||
sb->s_root = d_make_root(root_inode);
|
||||
if (!sb->s_root)
|
||||
goto bail_iput;
|
||||
goto bail_no_root;
|
||||
|
||||
/* everything's okay */
|
||||
return 0;
|
||||
|
||||
bail_iput:
|
||||
iput(root_inode);
|
||||
bail_no_root:
|
||||
printk(KERN_ERR "hfs: get root inode failed.\n");
|
||||
bail:
|
||||
|
@ -316,6 +316,11 @@ static inline unsigned short hfsplus_min_io_size(struct super_block *sb)
|
||||
#define HFSPLUS_IOC_EXT2_SETFLAGS FS_IOC_SETFLAGS
|
||||
|
||||
|
||||
/*
|
||||
* hfs+-specific ioctl for making the filesystem bootable
|
||||
*/
|
||||
#define HFSPLUS_IOC_BLESS _IO('h', 0x80)
|
||||
|
||||
/*
|
||||
* Functions in any *.c used in other files
|
||||
*/
|
||||
|
@ -117,7 +117,7 @@ struct hfsplus_vh {
|
||||
__be32 write_count;
|
||||
__be64 encodings_bmp;
|
||||
|
||||
u8 finder_info[32];
|
||||
u32 finder_info[8];
|
||||
|
||||
struct hfsplus_fork_raw alloc_file;
|
||||
struct hfsplus_fork_raw ext_file;
|
||||
|
@ -193,6 +193,7 @@ static struct dentry *hfsplus_file_lookup(struct inode *dir,
|
||||
mutex_init(&hip->extents_lock);
|
||||
hip->extent_state = 0;
|
||||
hip->flags = 0;
|
||||
hip->userflags = 0;
|
||||
set_bit(HFSPLUS_I_RSRC, &hip->flags);
|
||||
|
||||
err = hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);
|
||||
@ -400,6 +401,7 @@ struct inode *hfsplus_new_inode(struct super_block *sb, umode_t mode)
|
||||
atomic_set(&hip->opencnt, 0);
|
||||
hip->extent_state = 0;
|
||||
hip->flags = 0;
|
||||
hip->userflags = 0;
|
||||
memset(hip->first_extents, 0, sizeof(hfsplus_extent_rec));
|
||||
memset(hip->cached_extents, 0, sizeof(hfsplus_extent_rec));
|
||||
hip->alloc_blocks = 0;
|
||||
|
@ -20,6 +20,38 @@
|
||||
#include <asm/uaccess.h>
|
||||
#include "hfsplus_fs.h"
|
||||
|
||||
/*
|
||||
* "Blessing" an HFS+ filesystem writes metadata to the superblock informing
|
||||
* the platform firmware which file to boot from
|
||||
*/
|
||||
static int hfsplus_ioctl_bless(struct file *file, int __user *user_flags)
|
||||
{
|
||||
struct dentry *dentry = file->f_path.dentry;
|
||||
struct inode *inode = dentry->d_inode;
|
||||
struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
|
||||
struct hfsplus_vh *vh = sbi->s_vhdr;
|
||||
struct hfsplus_vh *bvh = sbi->s_backup_vhdr;
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
mutex_lock(&sbi->vh_mutex);
|
||||
|
||||
/* Directory containing the bootable system */
|
||||
vh->finder_info[0] = bvh->finder_info[0] =
|
||||
cpu_to_be32(parent_ino(dentry));
|
||||
|
||||
/* Bootloader */
|
||||
vh->finder_info[1] = bvh->finder_info[1] = cpu_to_be32(inode->i_ino);
|
||||
|
||||
/* Per spec, the OS X system folder - same as finder_info[0] here */
|
||||
vh->finder_info[5] = bvh->finder_info[5] =
|
||||
cpu_to_be32(parent_ino(dentry));
|
||||
|
||||
mutex_unlock(&sbi->vh_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
|
||||
{
|
||||
struct inode *inode = file->f_path.dentry->d_inode;
|
||||
@ -108,6 +140,8 @@ long hfsplus_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
return hfsplus_ioctl_getflags(file, argp);
|
||||
case HFSPLUS_IOC_EXT2_SETFLAGS:
|
||||
return hfsplus_ioctl_setflags(file, argp);
|
||||
case HFSPLUS_IOC_BLESS:
|
||||
return hfsplus_ioctl_bless(file, argp);
|
||||
default:
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
@ -465,6 +465,13 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
|
||||
goto out_put_alloc_file;
|
||||
}
|
||||
|
||||
sb->s_d_op = &hfsplus_dentry_operations;
|
||||
sb->s_root = d_make_root(root);
|
||||
if (!sb->s_root) {
|
||||
err = -ENOMEM;
|
||||
goto out_put_alloc_file;
|
||||
}
|
||||
|
||||
str.len = sizeof(HFSP_HIDDENDIR_NAME) - 1;
|
||||
str.name = HFSP_HIDDENDIR_NAME;
|
||||
err = hfs_find_init(sbi->cat_tree, &fd);
|
||||
@ -515,13 +522,6 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
|
||||
}
|
||||
}
|
||||
|
||||
sb->s_d_op = &hfsplus_dentry_operations;
|
||||
sb->s_root = d_alloc_root(root);
|
||||
if (!sb->s_root) {
|
||||
err = -ENOMEM;
|
||||
goto out_put_hidden_dir;
|
||||
}
|
||||
|
||||
unload_nls(sbi->nls);
|
||||
sbi->nls = nls;
|
||||
return 0;
|
||||
@ -529,7 +529,8 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
|
||||
out_put_hidden_dir:
|
||||
iput(sbi->hidden_dir);
|
||||
out_put_root:
|
||||
iput(root);
|
||||
dput(sb->s_root);
|
||||
sb->s_root = NULL;
|
||||
out_put_alloc_file:
|
||||
iput(sbi->alloc_file);
|
||||
out_close_cat_tree:
|
||||
|
@ -966,9 +966,9 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent)
|
||||
}
|
||||
|
||||
err = -ENOMEM;
|
||||
sb->s_root = d_alloc_root(root_inode);
|
||||
sb->s_root = d_make_root(root_inode);
|
||||
if (sb->s_root == NULL)
|
||||
goto out_put;
|
||||
goto out;
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -625,11 +625,9 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
|
||||
hpfs_init_inode(root);
|
||||
hpfs_read_inode(root);
|
||||
unlock_new_inode(root);
|
||||
s->s_root = d_alloc_root(root);
|
||||
if (!s->s_root) {
|
||||
iput(root);
|
||||
s->s_root = d_make_root(root);
|
||||
if (!s->s_root)
|
||||
goto bail0;
|
||||
}
|
||||
|
||||
/*
|
||||
* find the root directory's . pointer & finish filling in the inode
|
||||
|
@ -726,17 +726,12 @@ static int hppfs_fill_super(struct super_block *sb, void *d, int silent)
|
||||
|
||||
err = -ENOMEM;
|
||||
root_inode = get_inode(sb, dget(proc_mnt->mnt_root));
|
||||
if (!root_inode)
|
||||
goto out_mntput;
|
||||
|
||||
sb->s_root = d_alloc_root(root_inode);
|
||||
sb->s_root = d_make_root(root_inode);
|
||||
if (!sb->s_root)
|
||||
goto out_iput;
|
||||
goto out_mntput;
|
||||
|
||||
return 0;
|
||||
|
||||
out_iput:
|
||||
iput(root_inode);
|
||||
out_mntput:
|
||||
mntput(proc_mnt);
|
||||
out:
|
||||
|
@ -831,8 +831,6 @@ bad_val:
|
||||
static int
|
||||
hugetlbfs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
{
|
||||
struct inode * inode;
|
||||
struct dentry * root;
|
||||
int ret;
|
||||
struct hugetlbfs_config config;
|
||||
struct hugetlbfs_sb_info *sbinfo;
|
||||
@ -865,16 +863,9 @@ hugetlbfs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
sb->s_magic = HUGETLBFS_MAGIC;
|
||||
sb->s_op = &hugetlbfs_ops;
|
||||
sb->s_time_gran = 1;
|
||||
inode = hugetlbfs_get_root(sb, &config);
|
||||
if (!inode)
|
||||
sb->s_root = d_make_root(hugetlbfs_get_root(sb, &config));
|
||||
if (!sb->s_root)
|
||||
goto out_free;
|
||||
|
||||
root = d_alloc_root(inode);
|
||||
if (!root) {
|
||||
iput(inode);
|
||||
goto out_free;
|
||||
}
|
||||
sb->s_root = root;
|
||||
return 0;
|
||||
out_free:
|
||||
kfree(sbinfo);
|
||||
|
28
fs/inode.c
28
fs/inode.c
@ -2,29 +2,19 @@
|
||||
* (C) 1997 Linus Torvalds
|
||||
* (C) 1999 Andrea Arcangeli <andrea@suse.de> (dynamic inode allocation)
|
||||
*/
|
||||
#include <linux/export.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/dcache.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/writeback.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/backing-dev.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/rwsem.h>
|
||||
#include <linux/hash.h>
|
||||
#include <linux/swap.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/fsnotify.h>
|
||||
#include <linux/mount.h>
|
||||
#include <linux/async.h>
|
||||
#include <linux/posix_acl.h>
|
||||
#include <linux/prefetch.h>
|
||||
#include <linux/ima.h>
|
||||
#include <linux/cred.h>
|
||||
#include <linux/buffer_head.h> /* for inode_has_buffers */
|
||||
#include <linux/ratelimit.h>
|
||||
#include "internal.h"
|
||||
@ -1368,17 +1358,6 @@ int generic_delete_inode(struct inode *inode)
|
||||
}
|
||||
EXPORT_SYMBOL(generic_delete_inode);
|
||||
|
||||
/*
|
||||
* Normal UNIX filesystem behaviour: delete the
|
||||
* inode when the usage count drops to zero, and
|
||||
* i_nlink is zero.
|
||||
*/
|
||||
int generic_drop_inode(struct inode *inode)
|
||||
{
|
||||
return !inode->i_nlink || inode_unhashed(inode);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(generic_drop_inode);
|
||||
|
||||
/*
|
||||
* Called when we're dropping the last reference
|
||||
* to an inode.
|
||||
@ -1510,9 +1489,10 @@ static int relatime_need_update(struct vfsmount *mnt, struct inode *inode,
|
||||
* This function automatically handles read only file systems and media,
|
||||
* as well as the "noatime" flag and inode specific "noatime" markers.
|
||||
*/
|
||||
void touch_atime(struct vfsmount *mnt, struct dentry *dentry)
|
||||
void touch_atime(struct path *path)
|
||||
{
|
||||
struct inode *inode = dentry->d_inode;
|
||||
struct vfsmount *mnt = path->mnt;
|
||||
struct inode *inode = path->dentry->d_inode;
|
||||
struct timespec now;
|
||||
|
||||
if (inode->i_flags & S_NOATIME)
|
||||
|
@ -947,9 +947,8 @@ root_found:
|
||||
s->s_d_op = &isofs_dentry_ops[table];
|
||||
|
||||
/* get the root dentry */
|
||||
s->s_root = d_alloc_root(inode);
|
||||
s->s_root = d_make_root(inode);
|
||||
if (!(s->s_root)) {
|
||||
iput(inode);
|
||||
error = -ENOMEM;
|
||||
goto out_no_inode;
|
||||
}
|
||||
|
@ -561,9 +561,9 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent)
|
||||
ret = -ENOMEM;
|
||||
|
||||
D1(printk(KERN_DEBUG "jffs2_do_fill_super(): d_alloc_root()\n"));
|
||||
sb->s_root = d_alloc_root(root_i);
|
||||
sb->s_root = d_make_root(root_i);
|
||||
if (!sb->s_root)
|
||||
goto out_root_i;
|
||||
goto out_root;
|
||||
|
||||
sb->s_maxbytes = 0xFFFFFFFF;
|
||||
sb->s_blocksize = PAGE_CACHE_SIZE;
|
||||
@ -573,8 +573,6 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent)
|
||||
jffs2_start_garbage_collect_thread(c);
|
||||
return 0;
|
||||
|
||||
out_root_i:
|
||||
iput(root_i);
|
||||
out_root:
|
||||
jffs2_free_ino_caches(c);
|
||||
jffs2_free_raw_node_refs(c);
|
||||
|
@ -220,12 +220,6 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, umode_t mode)
|
||||
|
||||
dquot_initialize(dip);
|
||||
|
||||
/* link count overflow on parent directory ? */
|
||||
if (dip->i_nlink == JFS_LINK_MAX) {
|
||||
rc = -EMLINK;
|
||||
goto out1;
|
||||
}
|
||||
|
||||
/*
|
||||
* search parent directory for entry/freespace
|
||||
* (dtSearch() returns parent directory page pinned)
|
||||
@ -806,9 +800,6 @@ static int jfs_link(struct dentry *old_dentry,
|
||||
jfs_info("jfs_link: %s %s", old_dentry->d_name.name,
|
||||
dentry->d_name.name);
|
||||
|
||||
if (ip->i_nlink == JFS_LINK_MAX)
|
||||
return -EMLINK;
|
||||
|
||||
dquot_initialize(dir);
|
||||
|
||||
tid = txBegin(ip->i_sb, 0);
|
||||
@ -1138,10 +1129,6 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
rc = -ENOTEMPTY;
|
||||
goto out3;
|
||||
}
|
||||
} else if ((new_dir != old_dir) &&
|
||||
(new_dir->i_nlink == JFS_LINK_MAX)) {
|
||||
rc = -EMLINK;
|
||||
goto out3;
|
||||
}
|
||||
} else if (new_ip) {
|
||||
IWRITE_LOCK(new_ip, RDWRLOCK_NORMAL);
|
||||
|
@ -441,6 +441,7 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
return -ENOMEM;
|
||||
|
||||
sb->s_fs_info = sbi;
|
||||
sb->s_max_links = JFS_LINK_MAX;
|
||||
sbi->sb = sb;
|
||||
sbi->uid = sbi->gid = sbi->umask = -1;
|
||||
|
||||
@ -521,7 +522,7 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
ret = PTR_ERR(inode);
|
||||
goto out_no_rw;
|
||||
}
|
||||
sb->s_root = d_alloc_root(inode);
|
||||
sb->s_root = d_make_root(inode);
|
||||
if (!sb->s_root)
|
||||
goto out_no_root;
|
||||
|
||||
@ -539,7 +540,6 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
|
||||
out_no_root:
|
||||
jfs_err("jfs_read_super: get root dentry failed");
|
||||
iput(inode);
|
||||
|
||||
out_no_rw:
|
||||
rc = jfs_umount(sb);
|
||||
@ -860,8 +860,14 @@ static int __init init_jfs_fs(void)
|
||||
jfs_proc_init();
|
||||
#endif
|
||||
|
||||
return register_filesystem(&jfs_fs_type);
|
||||
rc = register_filesystem(&jfs_fs_type);
|
||||
if (!rc)
|
||||
return 0;
|
||||
|
||||
#ifdef PROC_FS_JFS
|
||||
jfs_proc_clean();
|
||||
#endif
|
||||
kthread_stop(jfsSyncThread);
|
||||
kill_committask:
|
||||
for (i = 0; i < commit_threads; i++)
|
||||
kthread_stop(jfsCommitThread[i]);
|
||||
|
@ -491,11 +491,9 @@ int simple_fill_super(struct super_block *s, unsigned long magic,
|
||||
inode->i_op = &simple_dir_inode_operations;
|
||||
inode->i_fop = &simple_dir_operations;
|
||||
set_nlink(inode, 2);
|
||||
root = d_alloc_root(inode);
|
||||
if (!root) {
|
||||
iput(inode);
|
||||
root = d_make_root(inode);
|
||||
if (!root)
|
||||
return -ENOMEM;
|
||||
}
|
||||
for (i = 0; !files->name || files->name[0]; i++, files++) {
|
||||
if (!files->name)
|
||||
continue;
|
||||
@ -536,7 +534,7 @@ int simple_pin_fs(struct file_system_type *type, struct vfsmount **mount, int *c
|
||||
spin_lock(&pin_fs_lock);
|
||||
if (unlikely(!*mount)) {
|
||||
spin_unlock(&pin_fs_lock);
|
||||
mnt = vfs_kern_mount(type, 0, type->name, NULL);
|
||||
mnt = vfs_kern_mount(type, MS_KERNMOUNT, type->name, NULL);
|
||||
if (IS_ERR(mnt))
|
||||
return PTR_ERR(mnt);
|
||||
spin_lock(&pin_fs_lock);
|
||||
|
@ -558,9 +558,6 @@ static int logfs_link(struct dentry *old_dentry, struct inode *dir,
|
||||
{
|
||||
struct inode *inode = old_dentry->d_inode;
|
||||
|
||||
if (inode->i_nlink >= LOGFS_LINK_MAX)
|
||||
return -EMLINK;
|
||||
|
||||
inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
|
||||
ihold(inode);
|
||||
inc_nlink(inode);
|
||||
|
@ -315,11 +315,9 @@ static int logfs_get_sb_final(struct super_block *sb)
|
||||
if (IS_ERR(rootdir))
|
||||
goto fail;
|
||||
|
||||
sb->s_root = d_alloc_root(rootdir);
|
||||
if (!sb->s_root) {
|
||||
iput(rootdir);
|
||||
sb->s_root = d_make_root(rootdir);
|
||||
if (!sb->s_root)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* at that point we know that ->put_super() will be called */
|
||||
super->s_erase_page = alloc_pages(GFP_KERNEL, 0);
|
||||
@ -542,6 +540,7 @@ static struct dentry *logfs_get_sb_device(struct logfs_super *super,
|
||||
* the filesystem incompatible with 32bit systems.
|
||||
*/
|
||||
sb->s_maxbytes = (1ull << 43) - 1;
|
||||
sb->s_max_links = LOGFS_LINK_MAX;
|
||||
sb->s_op = &logfs_super_operations;
|
||||
sb->s_flags = flags | MS_NOATIME;
|
||||
|
||||
@ -627,7 +626,10 @@ static int __init logfs_init(void)
|
||||
if (ret)
|
||||
goto out2;
|
||||
|
||||
return register_filesystem(&logfs_fs_type);
|
||||
ret = register_filesystem(&logfs_fs_type);
|
||||
if (!ret)
|
||||
return 0;
|
||||
logfs_destroy_inode_cache();
|
||||
out2:
|
||||
logfs_compr_exit();
|
||||
out1:
|
||||
|
@ -190,24 +190,24 @@ static int minix_fill_super(struct super_block *s, void *data, int silent)
|
||||
sbi->s_version = MINIX_V1;
|
||||
sbi->s_dirsize = 16;
|
||||
sbi->s_namelen = 14;
|
||||
sbi->s_link_max = MINIX_LINK_MAX;
|
||||
s->s_max_links = MINIX_LINK_MAX;
|
||||
} else if (s->s_magic == MINIX_SUPER_MAGIC2) {
|
||||
sbi->s_version = MINIX_V1;
|
||||
sbi->s_dirsize = 32;
|
||||
sbi->s_namelen = 30;
|
||||
sbi->s_link_max = MINIX_LINK_MAX;
|
||||
s->s_max_links = MINIX_LINK_MAX;
|
||||
} else if (s->s_magic == MINIX2_SUPER_MAGIC) {
|
||||
sbi->s_version = MINIX_V2;
|
||||
sbi->s_nzones = ms->s_zones;
|
||||
sbi->s_dirsize = 16;
|
||||
sbi->s_namelen = 14;
|
||||
sbi->s_link_max = MINIX2_LINK_MAX;
|
||||
s->s_max_links = MINIX2_LINK_MAX;
|
||||
} else if (s->s_magic == MINIX2_SUPER_MAGIC2) {
|
||||
sbi->s_version = MINIX_V2;
|
||||
sbi->s_nzones = ms->s_zones;
|
||||
sbi->s_dirsize = 32;
|
||||
sbi->s_namelen = 30;
|
||||
sbi->s_link_max = MINIX2_LINK_MAX;
|
||||
s->s_max_links = MINIX2_LINK_MAX;
|
||||
} else if ( *(__u16 *)(bh->b_data + 24) == MINIX3_SUPER_MAGIC) {
|
||||
m3s = (struct minix3_super_block *) bh->b_data;
|
||||
s->s_magic = m3s->s_magic;
|
||||
@ -221,9 +221,9 @@ static int minix_fill_super(struct super_block *s, void *data, int silent)
|
||||
sbi->s_dirsize = 64;
|
||||
sbi->s_namelen = 60;
|
||||
sbi->s_version = MINIX_V3;
|
||||
sbi->s_link_max = MINIX2_LINK_MAX;
|
||||
sbi->s_mount_state = MINIX_VALID_FS;
|
||||
sb_set_blocksize(s, m3s->s_blocksize);
|
||||
s->s_max_links = MINIX2_LINK_MAX;
|
||||
} else
|
||||
goto out_no_fs;
|
||||
|
||||
@ -254,14 +254,6 @@ static int minix_fill_super(struct super_block *s, void *data, int silent)
|
||||
minix_set_bit(0,sbi->s_imap[0]->b_data);
|
||||
minix_set_bit(0,sbi->s_zmap[0]->b_data);
|
||||
|
||||
/* set up enough so that it can read an inode */
|
||||
s->s_op = &minix_sops;
|
||||
root_inode = minix_iget(s, MINIX_ROOT_INO);
|
||||
if (IS_ERR(root_inode)) {
|
||||
ret = PTR_ERR(root_inode);
|
||||
goto out_no_root;
|
||||
}
|
||||
|
||||
/* Apparently minix can create filesystems that allocate more blocks for
|
||||
* the bitmaps than needed. We simply ignore that, but verify it didn't
|
||||
* create one with not enough blocks and bail out if so.
|
||||
@ -270,7 +262,7 @@ static int minix_fill_super(struct super_block *s, void *data, int silent)
|
||||
if (sbi->s_imap_blocks < block) {
|
||||
printk("MINIX-fs: file system does not have enough "
|
||||
"imap blocks allocated. Refusing to mount\n");
|
||||
goto out_iput;
|
||||
goto out_no_bitmap;
|
||||
}
|
||||
|
||||
block = minix_blocks_needed(
|
||||
@ -279,13 +271,21 @@ static int minix_fill_super(struct super_block *s, void *data, int silent)
|
||||
if (sbi->s_zmap_blocks < block) {
|
||||
printk("MINIX-fs: file system does not have enough "
|
||||
"zmap blocks allocated. Refusing to mount.\n");
|
||||
goto out_iput;
|
||||
goto out_no_bitmap;
|
||||
}
|
||||
|
||||
/* set up enough so that it can read an inode */
|
||||
s->s_op = &minix_sops;
|
||||
root_inode = minix_iget(s, MINIX_ROOT_INO);
|
||||
if (IS_ERR(root_inode)) {
|
||||
ret = PTR_ERR(root_inode);
|
||||
goto out_no_root;
|
||||
}
|
||||
|
||||
ret = -ENOMEM;
|
||||
s->s_root = d_alloc_root(root_inode);
|
||||
s->s_root = d_make_root(root_inode);
|
||||
if (!s->s_root)
|
||||
goto out_iput;
|
||||
goto out_no_root;
|
||||
|
||||
if (!(s->s_flags & MS_RDONLY)) {
|
||||
if (sbi->s_version != MINIX_V3) /* s_state is now out from V3 sb */
|
||||
@ -301,10 +301,6 @@ static int minix_fill_super(struct super_block *s, void *data, int silent)
|
||||
|
||||
return 0;
|
||||
|
||||
out_iput:
|
||||
iput(root_inode);
|
||||
goto out_freemap;
|
||||
|
||||
out_no_root:
|
||||
if (!silent)
|
||||
printk("MINIX-fs: get root inode failed\n");
|
||||
|
@ -34,7 +34,6 @@ struct minix_sb_info {
|
||||
unsigned long s_max_size;
|
||||
int s_dirsize;
|
||||
int s_namelen;
|
||||
int s_link_max;
|
||||
struct buffer_head ** s_imap;
|
||||
struct buffer_head ** s_zmap;
|
||||
struct buffer_head * s_sbh;
|
||||
|
@ -94,9 +94,6 @@ static int minix_link(struct dentry * old_dentry, struct inode * dir,
|
||||
{
|
||||
struct inode *inode = old_dentry->d_inode;
|
||||
|
||||
if (inode->i_nlink >= minix_sb(inode->i_sb)->s_link_max)
|
||||
return -EMLINK;
|
||||
|
||||
inode->i_ctime = CURRENT_TIME_SEC;
|
||||
inode_inc_link_count(inode);
|
||||
ihold(inode);
|
||||
@ -106,10 +103,7 @@ static int minix_link(struct dentry * old_dentry, struct inode * dir,
|
||||
static int minix_mkdir(struct inode * dir, struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct inode * inode;
|
||||
int err = -EMLINK;
|
||||
|
||||
if (dir->i_nlink >= minix_sb(dir->i_sb)->s_link_max)
|
||||
goto out;
|
||||
int err;
|
||||
|
||||
inode_inc_link_count(dir);
|
||||
|
||||
@ -181,7 +175,6 @@ static int minix_rmdir(struct inode * dir, struct dentry *dentry)
|
||||
static int minix_rename(struct inode * old_dir, struct dentry *old_dentry,
|
||||
struct inode * new_dir, struct dentry *new_dentry)
|
||||
{
|
||||
struct minix_sb_info * info = minix_sb(old_dir->i_sb);
|
||||
struct inode * old_inode = old_dentry->d_inode;
|
||||
struct inode * new_inode = new_dentry->d_inode;
|
||||
struct page * dir_page = NULL;
|
||||
@ -219,11 +212,6 @@ static int minix_rename(struct inode * old_dir, struct dentry *old_dentry,
|
||||
drop_nlink(new_inode);
|
||||
inode_dec_link_count(new_inode);
|
||||
} else {
|
||||
if (dir_de) {
|
||||
err = -EMLINK;
|
||||
if (new_dir->i_nlink >= info->s_link_max)
|
||||
goto out_dir;
|
||||
}
|
||||
err = minix_add_link(new_dentry, old_inode);
|
||||
if (err)
|
||||
goto out_dir;
|
||||
|
15
fs/namei.c
15
fs/namei.c
@ -642,7 +642,7 @@ follow_link(struct path *link, struct nameidata *nd, void **p)
|
||||
cond_resched();
|
||||
current->total_link_count++;
|
||||
|
||||
touch_atime(link->mnt, dentry);
|
||||
touch_atime(link);
|
||||
nd_set_link(nd, NULL);
|
||||
|
||||
error = security_inode_follow_link(link->dentry, nd);
|
||||
@ -2691,6 +2691,7 @@ SYSCALL_DEFINE3(mknod, const char __user *, filename, umode_t, mode, unsigned, d
|
||||
int vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
int error = may_create(dir, dentry);
|
||||
unsigned max_links = dir->i_sb->s_max_links;
|
||||
|
||||
if (error)
|
||||
return error;
|
||||
@ -2703,6 +2704,9 @@ int vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (max_links && dir->i_nlink >= max_links)
|
||||
return -EMLINK;
|
||||
|
||||
error = dir->i_op->mkdir(dir, dentry, mode);
|
||||
if (!error)
|
||||
fsnotify_mkdir(dir, dentry);
|
||||
@ -3033,6 +3037,7 @@ SYSCALL_DEFINE2(symlink, const char __user *, oldname, const char __user *, newn
|
||||
int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
|
||||
{
|
||||
struct inode *inode = old_dentry->d_inode;
|
||||
unsigned max_links = dir->i_sb->s_max_links;
|
||||
int error;
|
||||
|
||||
if (!inode)
|
||||
@ -3063,6 +3068,8 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de
|
||||
/* Make sure we don't allow creating hardlink to an unlinked file */
|
||||
if (inode->i_nlink == 0)
|
||||
error = -ENOENT;
|
||||
else if (max_links && inode->i_nlink >= max_links)
|
||||
error = -EMLINK;
|
||||
else
|
||||
error = dir->i_op->link(old_dentry, dir, new_dentry);
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
@ -3172,6 +3179,7 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
|
||||
{
|
||||
int error = 0;
|
||||
struct inode *target = new_dentry->d_inode;
|
||||
unsigned max_links = new_dir->i_sb->s_max_links;
|
||||
|
||||
/*
|
||||
* If we are going to change the parent - check write permissions,
|
||||
@ -3195,6 +3203,11 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
|
||||
if (d_mountpoint(old_dentry) || d_mountpoint(new_dentry))
|
||||
goto out;
|
||||
|
||||
error = -EMLINK;
|
||||
if (max_links && !target && new_dir != old_dir &&
|
||||
new_dir->i_nlink >= max_links)
|
||||
goto out;
|
||||
|
||||
if (target)
|
||||
shrink_dcache_parent(new_dentry);
|
||||
error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
|
||||
|
@ -716,13 +716,11 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
|
||||
if (!root_inode)
|
||||
goto out_disconnect;
|
||||
DPRINTK("ncp_fill_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
|
||||
sb->s_root = d_alloc_root(root_inode);
|
||||
sb->s_root = d_make_root(root_inode);
|
||||
if (!sb->s_root)
|
||||
goto out_no_root;
|
||||
goto out_disconnect;
|
||||
return 0;
|
||||
|
||||
out_no_root:
|
||||
iput(root_inode);
|
||||
out_disconnect:
|
||||
ncp_lock_server(server);
|
||||
ncp_disconnect(server);
|
||||
|
@ -49,11 +49,9 @@ static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *i
|
||||
{
|
||||
/* The mntroot acts as the dummy root dentry for this superblock */
|
||||
if (sb->s_root == NULL) {
|
||||
sb->s_root = d_alloc_root(inode);
|
||||
if (sb->s_root == NULL) {
|
||||
iput(inode);
|
||||
sb->s_root = d_make_root(inode);
|
||||
if (sb->s_root == NULL)
|
||||
return -ENOMEM;
|
||||
}
|
||||
ihold(inode);
|
||||
/*
|
||||
* Ensure that this dentry is invisible to d_find_alias().
|
||||
|
@ -72,7 +72,7 @@ int nfsd_fault_inject_init(void)
|
||||
{
|
||||
unsigned int i;
|
||||
struct nfsd_fault_inject_op *op;
|
||||
mode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
|
||||
umode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
|
||||
|
||||
debug_dir = debugfs_create_dir("nfsd", NULL);
|
||||
if (!debug_dir)
|
||||
|
@ -1541,30 +1541,31 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
|
||||
__be32
|
||||
nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp)
|
||||
{
|
||||
struct dentry *dentry;
|
||||
struct inode *inode;
|
||||
mm_segment_t oldfs;
|
||||
__be32 err;
|
||||
int host_err;
|
||||
struct path path;
|
||||
|
||||
err = fh_verify(rqstp, fhp, S_IFLNK, NFSD_MAY_NOP);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
dentry = fhp->fh_dentry;
|
||||
inode = dentry->d_inode;
|
||||
path.mnt = fhp->fh_export->ex_path.mnt;
|
||||
path.dentry = fhp->fh_dentry;
|
||||
inode = path.dentry->d_inode;
|
||||
|
||||
err = nfserr_inval;
|
||||
if (!inode->i_op->readlink)
|
||||
goto out;
|
||||
|
||||
touch_atime(fhp->fh_export->ex_path.mnt, dentry);
|
||||
touch_atime(&path);
|
||||
/* N.B. Why does this call need a get_fs()??
|
||||
* Remove the set_fs and watch the fireworks:-) --okir
|
||||
*/
|
||||
|
||||
oldfs = get_fs(); set_fs(KERNEL_DS);
|
||||
host_err = inode->i_op->readlink(dentry, buf, *lenp);
|
||||
host_err = inode->i_op->readlink(path.dentry, buf, *lenp);
|
||||
set_fs(oldfs);
|
||||
|
||||
if (host_err < 0)
|
||||
|
@ -193,9 +193,6 @@ static int nilfs_link(struct dentry *old_dentry, struct inode *dir,
|
||||
struct nilfs_transaction_info ti;
|
||||
int err;
|
||||
|
||||
if (inode->i_nlink >= NILFS_LINK_MAX)
|
||||
return -EMLINK;
|
||||
|
||||
err = nilfs_transaction_begin(dir->i_sb, &ti, 1);
|
||||
if (err)
|
||||
return err;
|
||||
@ -219,9 +216,6 @@ static int nilfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
|
||||
struct nilfs_transaction_info ti;
|
||||
int err;
|
||||
|
||||
if (dir->i_nlink >= NILFS_LINK_MAX)
|
||||
return -EMLINK;
|
||||
|
||||
err = nilfs_transaction_begin(dir->i_sb, &ti, 1);
|
||||
if (err)
|
||||
return err;
|
||||
@ -400,11 +394,6 @@ static int nilfs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
drop_nlink(new_inode);
|
||||
nilfs_mark_inode_dirty(new_inode);
|
||||
} else {
|
||||
if (dir_de) {
|
||||
err = -EMLINK;
|
||||
if (new_dir->i_nlink >= NILFS_LINK_MAX)
|
||||
goto out_dir;
|
||||
}
|
||||
err = nilfs_add_link(new_dentry, old_inode);
|
||||
if (err)
|
||||
goto out_dir;
|
||||
|
@ -917,9 +917,8 @@ static int nilfs_get_root_dentry(struct super_block *sb,
|
||||
if (root->cno == NILFS_CPTREE_CURRENT_CNO) {
|
||||
dentry = d_find_alias(inode);
|
||||
if (!dentry) {
|
||||
dentry = d_alloc_root(inode);
|
||||
dentry = d_make_root(inode);
|
||||
if (!dentry) {
|
||||
iput(inode);
|
||||
ret = -ENOMEM;
|
||||
goto failed_dentry;
|
||||
}
|
||||
@ -1059,6 +1058,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
sb->s_export_op = &nilfs_export_ops;
|
||||
sb->s_root = NULL;
|
||||
sb->s_time_gran = 1;
|
||||
sb->s_max_links = NILFS_LINK_MAX;
|
||||
|
||||
bdi = sb->s_bdev->bd_inode->i_mapping->backing_dev_info;
|
||||
sb->s_bdi = bdi ? : &default_backing_dev_info;
|
||||
|
@ -2908,9 +2908,10 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
|
||||
ntfs_error(sb, "Failed to load system files.");
|
||||
goto unl_upcase_iput_tmp_ino_err_out_now;
|
||||
}
|
||||
if ((sb->s_root = d_alloc_root(vol->root_ino))) {
|
||||
/* We grab a reference, simulating an ntfs_iget(). */
|
||||
ihold(vol->root_ino);
|
||||
|
||||
/* We grab a reference, simulating an ntfs_iget(). */
|
||||
ihold(vol->root_ino);
|
||||
if ((sb->s_root = d_make_root(vol->root_ino))) {
|
||||
ntfs_debug("Exiting, status successful.");
|
||||
/* Release the default upcase if it has no users. */
|
||||
mutex_lock(&ntfs_lock);
|
||||
@ -3158,6 +3159,8 @@ static int __init init_ntfs_fs(void)
|
||||
}
|
||||
printk(KERN_CRIT "NTFS: Failed to register NTFS filesystem driver!\n");
|
||||
|
||||
/* Unregister the ntfs sysctls. */
|
||||
ntfs_sysctl(0);
|
||||
sysctl_err_out:
|
||||
kmem_cache_destroy(ntfs_big_inode_cache);
|
||||
big_inode_err_out:
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user