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:
+8
-8
@@ -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;
|
||||
}
|
||||
|
||||
+1
-2
@@ -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/
|
||||
|
||||
+1
-2
@@ -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);
|
||||
|
||||
+2
-5
@@ -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);
|
||||
|
||||
+2
-5
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
+56
-53
@@ -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:
|
||||
|
||||
+3
-3
@@ -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;
|
||||
}
|
||||
|
||||
+2
-8
@@ -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:
|
||||
|
||||
+1
-2
@@ -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;
|
||||
}
|
||||
|
||||
+1
-2
@@ -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;
|
||||
}
|
||||
|
||||
+2
-2
@@ -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)
|
||||
|
||||
+2
-3
@@ -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;
|
||||
|
||||
+2
-1
@@ -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)
|
||||
|
||||
+2
-2
@@ -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;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
+2
-5
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -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)
|
||||
|
||||
+2
-2
@@ -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)
|
||||
|
||||
+2
-6
@@ -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 */
|
||||
|
||||
+1
-2
@@ -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;
|
||||
}
|
||||
|
||||
+1
-6
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+1
-5
@@ -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;
|
||||
|
||||
|
||||
+31
-41
@@ -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);
|
||||
|
||||
|
||||
+30
-32
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+7
-9
@@ -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);
|
||||
|
||||
+2
-4
@@ -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
@@ -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;
|
||||
|
||||
+1
-1
@@ -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)
|
||||
{
|
||||
|
||||
+1
-2
@@ -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;
|
||||
|
||||
+4
-5
@@ -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;
|
||||
}
|
||||
|
||||
+9
-10
@@ -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,
|
||||
|
||||
+1
-2
@@ -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;
|
||||
|
||||
|
||||
+1
-12
@@ -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;
|
||||
|
||||
+2
-2
@@ -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;
|
||||
|
||||
+1
-12
@@ -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;
|
||||
|
||||
+2
-2
@@ -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;
|
||||
|
||||
+1
-2
@@ -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;
|
||||
}
|
||||
|
||||
+4
-4
@@ -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();
|
||||
|
||||
+4
-4
@@ -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)
|
||||
|
||||
+1
-2
@@ -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;
|
||||
}
|
||||
|
||||
+17
-16
@@ -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)
|
||||
|
||||
+2
-7
@@ -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;
|
||||
|
||||
+2
-4
@@ -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;
|
||||
}
|
||||
|
||||
+9
-8
@@ -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;
|
||||
|
||||
|
||||
+2
-4
@@ -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
|
||||
|
||||
+2
-7
@@ -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:
|
||||
|
||||
+2
-11
@@ -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);
|
||||
|
||||
+4
-24
@@ -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)
|
||||
|
||||
+1
-2
@@ -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;
|
||||
}
|
||||
|
||||
+2
-4
@@ -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);
|
||||
|
||||
+9
-3
@@ -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]);
|
||||
|
||||
+3
-5
@@ -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);
|
||||
|
||||
+7
-5
@@ -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:
|
||||
|
||||
+17
-21
@@ -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;
|
||||
|
||||
+1
-13
@@ -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;
|
||||
|
||||
+14
-1
@@ -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);
|
||||
|
||||
+2
-4
@@ -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);
|
||||
|
||||
+2
-4
@@ -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)
|
||||
|
||||
+6
-5
@@ -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;
|
||||
|
||||
+2
-2
@@ -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;
|
||||
|
||||
+6
-3
@@ -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:
|
||||
|
||||
+2
-12
@@ -582,24 +582,14 @@ static int dlmfs_fill_super(struct super_block * sb,
|
||||
void * data,
|
||||
int silent)
|
||||
{
|
||||
struct inode * inode;
|
||||
struct dentry * root;
|
||||
|
||||
sb->s_maxbytes = MAX_LFS_FILESIZE;
|
||||
sb->s_blocksize = PAGE_CACHE_SIZE;
|
||||
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
|
||||
sb->s_magic = DLMFS_MAGIC;
|
||||
sb->s_op = &dlmfs_ops;
|
||||
inode = dlmfs_get_root_inode(sb);
|
||||
if (!inode)
|
||||
sb->s_root = d_make_root(dlmfs_get_root_inode(sb));
|
||||
if (!sb->s_root)
|
||||
return -ENOMEM;
|
||||
|
||||
root = d_alloc_root(inode);
|
||||
if (!root) {
|
||||
iput(inode);
|
||||
return -ENOMEM;
|
||||
}
|
||||
sb->s_root = root;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+25
-26
@@ -1154,19 +1154,19 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
|
||||
}
|
||||
|
||||
status = ocfs2_mount_volume(sb);
|
||||
if (osb->root_inode)
|
||||
inode = igrab(osb->root_inode);
|
||||
|
||||
if (status < 0)
|
||||
goto read_super_error;
|
||||
|
||||
if (osb->root_inode)
|
||||
inode = igrab(osb->root_inode);
|
||||
|
||||
if (!inode) {
|
||||
status = -EIO;
|
||||
mlog_errno(status);
|
||||
goto read_super_error;
|
||||
}
|
||||
|
||||
root = d_alloc_root(inode);
|
||||
root = d_make_root(inode);
|
||||
if (!root) {
|
||||
status = -ENOMEM;
|
||||
mlog_errno(status);
|
||||
@@ -1220,9 +1220,6 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
|
||||
read_super_error:
|
||||
brelse(bh);
|
||||
|
||||
if (inode)
|
||||
iput(inode);
|
||||
|
||||
if (osb) {
|
||||
atomic_set(&osb->vol_state, VOLUME_DISABLED);
|
||||
wake_up(&osb->osb_mount_event);
|
||||
@@ -1627,21 +1624,17 @@ static int __init ocfs2_init(void)
|
||||
init_waitqueue_head(&ocfs2__ioend_wq[i]);
|
||||
|
||||
status = init_ocfs2_uptodate_cache();
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto leave;
|
||||
}
|
||||
if (status < 0)
|
||||
goto out1;
|
||||
|
||||
status = ocfs2_initialize_mem_caches();
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
goto leave;
|
||||
}
|
||||
if (status < 0)
|
||||
goto out2;
|
||||
|
||||
ocfs2_wq = create_singlethread_workqueue("ocfs2_wq");
|
||||
if (!ocfs2_wq) {
|
||||
status = -ENOMEM;
|
||||
goto leave;
|
||||
goto out3;
|
||||
}
|
||||
|
||||
ocfs2_debugfs_root = debugfs_create_dir("ocfs2", NULL);
|
||||
@@ -1653,17 +1646,23 @@ static int __init ocfs2_init(void)
|
||||
ocfs2_set_locking_protocol();
|
||||
|
||||
status = register_quota_format(&ocfs2_quota_format);
|
||||
leave:
|
||||
if (status < 0) {
|
||||
ocfs2_free_mem_caches();
|
||||
exit_ocfs2_uptodate_cache();
|
||||
mlog_errno(status);
|
||||
}
|
||||
if (status < 0)
|
||||
goto out4;
|
||||
status = register_filesystem(&ocfs2_fs_type);
|
||||
if (!status)
|
||||
return 0;
|
||||
|
||||
if (status >= 0) {
|
||||
return register_filesystem(&ocfs2_fs_type);
|
||||
} else
|
||||
return -1;
|
||||
unregister_quota_format(&ocfs2_quota_format);
|
||||
out4:
|
||||
destroy_workqueue(ocfs2_wq);
|
||||
debugfs_remove(ocfs2_debugfs_root);
|
||||
out3:
|
||||
ocfs2_free_mem_caches();
|
||||
out2:
|
||||
exit_ocfs2_uptodate_cache();
|
||||
out1:
|
||||
mlog_errno(status);
|
||||
return status;
|
||||
}
|
||||
|
||||
static void __exit ocfs2_exit(void)
|
||||
|
||||
+2
-4
@@ -539,11 +539,9 @@ static int omfs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
goto out_brelse_bh2;
|
||||
}
|
||||
|
||||
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_brelse_bh2;
|
||||
}
|
||||
printk(KERN_DEBUG "omfs: Mounted volume %s\n", omfs_rb->r_name);
|
||||
|
||||
ret = 0;
|
||||
|
||||
@@ -408,13 +408,12 @@ static int openprom_fill_super(struct super_block *s, void *data, int silent)
|
||||
oi->type = op_inode_node;
|
||||
oi->u.node = of_find_node_by_path("/");
|
||||
|
||||
s->s_root = d_alloc_root(root_inode);
|
||||
s->s_root = d_make_root(root_inode);
|
||||
if (!s->s_root)
|
||||
goto out_no_root_dentry;
|
||||
return 0;
|
||||
|
||||
out_no_root_dentry:
|
||||
iput(root_inode);
|
||||
ret = -ENOMEM;
|
||||
out_no_root:
|
||||
printk("openprom_fill_super: get root inode failed\n");
|
||||
|
||||
+3
-13
@@ -486,8 +486,6 @@ struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de)
|
||||
|
||||
int proc_fill_super(struct super_block *s)
|
||||
{
|
||||
struct inode * root_inode;
|
||||
|
||||
s->s_flags |= MS_NODIRATIME | MS_NOSUID | MS_NOEXEC;
|
||||
s->s_blocksize = 1024;
|
||||
s->s_blocksize_bits = 10;
|
||||
@@ -496,19 +494,11 @@ int proc_fill_super(struct super_block *s)
|
||||
s->s_time_gran = 1;
|
||||
|
||||
pde_get(&proc_root);
|
||||
root_inode = proc_get_inode(s, &proc_root);
|
||||
if (!root_inode)
|
||||
goto out_no_root;
|
||||
root_inode->i_uid = 0;
|
||||
root_inode->i_gid = 0;
|
||||
s->s_root = d_alloc_root(root_inode);
|
||||
if (!s->s_root)
|
||||
goto out_no_root;
|
||||
return 0;
|
||||
s->s_root = d_make_root(proc_get_inode(s, &proc_root));
|
||||
if (s->s_root)
|
||||
return 0;
|
||||
|
||||
out_no_root:
|
||||
printk("proc_read_super: get root inode failed\n");
|
||||
iput(root_inode);
|
||||
pde_put(&proc_root);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
+7
-18
@@ -278,9 +278,7 @@ fail:
|
||||
|
||||
int pstore_fill_super(struct super_block *sb, void *data, int silent)
|
||||
{
|
||||
struct inode *inode = NULL;
|
||||
struct dentry *root;
|
||||
int err;
|
||||
struct inode *inode;
|
||||
|
||||
save_mount_options(sb, data);
|
||||
|
||||
@@ -296,26 +294,17 @@ int pstore_fill_super(struct super_block *sb, void *data, int silent)
|
||||
parse_options(data);
|
||||
|
||||
inode = pstore_get_inode(sb, NULL, S_IFDIR | 0755, 0);
|
||||
if (!inode) {
|
||||
err = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
/* override ramfs "dir" options so we catch unlink(2) */
|
||||
inode->i_op = &pstore_dir_inode_operations;
|
||||
|
||||
root = d_alloc_root(inode);
|
||||
sb->s_root = root;
|
||||
if (!root) {
|
||||
err = -ENOMEM;
|
||||
goto fail;
|
||||
if (inode) {
|
||||
/* override ramfs "dir" options so we catch unlink(2) */
|
||||
inode->i_op = &pstore_dir_inode_operations;
|
||||
}
|
||||
sb->s_root = d_make_root(inode);
|
||||
if (!sb->s_root)
|
||||
return -ENOMEM;
|
||||
|
||||
pstore_get_records(0);
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
iput(inode);
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct dentry *pstore_mount(struct file_system_type *fs_type,
|
||||
|
||||
+17
-71
@@ -52,38 +52,6 @@ static int qnx4_remount(struct super_block *sb, int *flags, char *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct buffer_head *qnx4_getblk(struct inode *inode, int nr,
|
||||
int create)
|
||||
{
|
||||
struct buffer_head *result = NULL;
|
||||
|
||||
if ( nr >= 0 )
|
||||
nr = qnx4_block_map( inode, nr );
|
||||
if (nr) {
|
||||
result = sb_getblk(inode->i_sb, nr);
|
||||
return result;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct buffer_head *qnx4_bread(struct inode *inode, int block, int create)
|
||||
{
|
||||
struct buffer_head *bh;
|
||||
|
||||
bh = qnx4_getblk(inode, block, create);
|
||||
if (!bh || buffer_uptodate(bh)) {
|
||||
return bh;
|
||||
}
|
||||
ll_rw_block(READ, 1, &bh);
|
||||
wait_on_buffer(bh);
|
||||
if (buffer_uptodate(bh)) {
|
||||
return bh;
|
||||
}
|
||||
brelse(bh);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int qnx4_get_block( struct inode *inode, sector_t iblock, struct buffer_head *bh, int create )
|
||||
{
|
||||
unsigned long phys;
|
||||
@@ -98,23 +66,31 @@ static int qnx4_get_block( struct inode *inode, sector_t iblock, struct buffer_h
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline u32 try_extent(qnx4_xtnt_t *extent, u32 *offset)
|
||||
{
|
||||
u32 size = le32_to_cpu(extent->xtnt_size);
|
||||
if (*offset < size)
|
||||
return le32_to_cpu(extent->xtnt_blk) + *offset - 1;
|
||||
*offset -= size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long qnx4_block_map( struct inode *inode, long iblock )
|
||||
{
|
||||
int ix;
|
||||
long offset, i_xblk;
|
||||
unsigned long block = 0;
|
||||
long i_xblk;
|
||||
struct buffer_head *bh = NULL;
|
||||
struct qnx4_xblk *xblk = NULL;
|
||||
struct qnx4_inode_entry *qnx4_inode = qnx4_raw_inode(inode);
|
||||
u16 nxtnt = le16_to_cpu(qnx4_inode->di_num_xtnts);
|
||||
u32 offset = iblock;
|
||||
u32 block = try_extent(&qnx4_inode->di_first_xtnt, &offset);
|
||||
|
||||
if ( iblock < le32_to_cpu(qnx4_inode->di_first_xtnt.xtnt_size) ) {
|
||||
if (block) {
|
||||
// iblock is in the first extent. This is easy.
|
||||
block = le32_to_cpu(qnx4_inode->di_first_xtnt.xtnt_blk) + iblock - 1;
|
||||
} else {
|
||||
// iblock is beyond first extent. We have to follow the extent chain.
|
||||
i_xblk = le32_to_cpu(qnx4_inode->di_xblk);
|
||||
offset = iblock - le32_to_cpu(qnx4_inode->di_first_xtnt.xtnt_size);
|
||||
ix = 0;
|
||||
while ( --nxtnt > 0 ) {
|
||||
if ( ix == 0 ) {
|
||||
@@ -130,12 +106,11 @@ unsigned long qnx4_block_map( struct inode *inode, long iblock )
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
if ( offset < le32_to_cpu(xblk->xblk_xtnts[ix].xtnt_size) ) {
|
||||
block = try_extent(&xblk->xblk_xtnts[ix], &offset);
|
||||
if (block) {
|
||||
// got it!
|
||||
block = le32_to_cpu(xblk->xblk_xtnts[ix].xtnt_blk) + offset - 1;
|
||||
break;
|
||||
}
|
||||
offset -= le32_to_cpu(xblk->xblk_xtnts[ix].xtnt_size);
|
||||
if ( ++ix >= xblk->xblk_num_xtnts ) {
|
||||
i_xblk = le32_to_cpu(xblk->xblk_next_xblk);
|
||||
ix = 0;
|
||||
@@ -260,15 +235,13 @@ static int qnx4_fill_super(struct super_block *s, void *data, int silent)
|
||||
}
|
||||
|
||||
ret = -ENOMEM;
|
||||
s->s_root = d_alloc_root(root);
|
||||
s->s_root = d_make_root(root);
|
||||
if (s->s_root == NULL)
|
||||
goto outi;
|
||||
goto outb;
|
||||
|
||||
brelse(bh);
|
||||
return 0;
|
||||
|
||||
outi:
|
||||
iput(root);
|
||||
outb:
|
||||
kfree(qs->BitMap);
|
||||
out:
|
||||
@@ -288,44 +261,17 @@ static void qnx4_put_super(struct super_block *sb)
|
||||
return;
|
||||
}
|
||||
|
||||
static int qnx4_writepage(struct page *page, struct writeback_control *wbc)
|
||||
{
|
||||
return block_write_full_page(page,qnx4_get_block, wbc);
|
||||
}
|
||||
|
||||
static int qnx4_readpage(struct file *file, struct page *page)
|
||||
{
|
||||
return block_read_full_page(page,qnx4_get_block);
|
||||
}
|
||||
|
||||
static int qnx4_write_begin(struct file *file, struct address_space *mapping,
|
||||
loff_t pos, unsigned len, unsigned flags,
|
||||
struct page **pagep, void **fsdata)
|
||||
{
|
||||
struct qnx4_inode_info *qnx4_inode = qnx4_i(mapping->host);
|
||||
int ret;
|
||||
|
||||
*pagep = NULL;
|
||||
ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
|
||||
qnx4_get_block,
|
||||
&qnx4_inode->mmu_private);
|
||||
if (unlikely(ret)) {
|
||||
loff_t isize = mapping->host->i_size;
|
||||
if (pos + len > isize)
|
||||
vmtruncate(mapping->host, isize);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
static sector_t qnx4_bmap(struct address_space *mapping, sector_t block)
|
||||
{
|
||||
return generic_block_bmap(mapping,block,qnx4_get_block);
|
||||
}
|
||||
static const struct address_space_operations qnx4_aops = {
|
||||
.readpage = qnx4_readpage,
|
||||
.writepage = qnx4_writepage,
|
||||
.write_begin = qnx4_write_begin,
|
||||
.write_end = generic_write_end,
|
||||
.bmap = qnx4_bmap
|
||||
};
|
||||
|
||||
|
||||
+3
-6
@@ -39,10 +39,6 @@ static int qnx4_match(int len, const char *name,
|
||||
} else {
|
||||
namelen = QNX4_SHORT_NAME_MAX;
|
||||
}
|
||||
/* "" means "." ---> so paths like "/usr/lib//libc.a" work */
|
||||
if (!len && (de->di_fname[0] == '.') && (de->di_fname[1] == '\0')) {
|
||||
return 1;
|
||||
}
|
||||
thislen = strlen( de->di_fname );
|
||||
if ( thislen > namelen )
|
||||
thislen = namelen;
|
||||
@@ -72,7 +68,9 @@ static struct buffer_head *qnx4_find_entry(int len, struct inode *dir,
|
||||
block = offset = blkofs = 0;
|
||||
while (blkofs * QNX4_BLOCK_SIZE + offset < dir->i_size) {
|
||||
if (!bh) {
|
||||
bh = qnx4_bread(dir, blkofs, 0);
|
||||
block = qnx4_block_map(dir, blkofs);
|
||||
if (block)
|
||||
bh = sb_bread(dir->i_sb, block);
|
||||
if (!bh) {
|
||||
blkofs++;
|
||||
continue;
|
||||
@@ -80,7 +78,6 @@ static struct buffer_head *qnx4_find_entry(int len, struct inode *dir,
|
||||
}
|
||||
*res_dir = (struct qnx4_inode_entry *) (bh->b_data + offset);
|
||||
if (qnx4_match(len, name, bh, &offset)) {
|
||||
block = qnx4_block_map( dir, blkofs );
|
||||
*ino = block * QNX4_INODES_PER_BLOCK +
|
||||
(offset / QNX4_DIR_ENTRY_SIZE) - 1;
|
||||
return bh;
|
||||
|
||||
@@ -27,8 +27,6 @@ extern struct dentry *qnx4_lookup(struct inode *dir, struct dentry *dentry, stru
|
||||
extern unsigned long qnx4_count_free_blocks(struct super_block *sb);
|
||||
extern unsigned long qnx4_block_map(struct inode *inode, long iblock);
|
||||
|
||||
extern struct buffer_head *qnx4_bread(struct inode *, int, int);
|
||||
|
||||
extern const struct inode_operations qnx4_dir_inode_operations;
|
||||
extern const struct file_operations qnx4_dir_operations;
|
||||
extern int qnx4_is_free(struct super_block *sb, long block);
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
config QNX6FS_FS
|
||||
tristate "QNX6 file system support (read only)"
|
||||
depends on BLOCK && CRC32
|
||||
help
|
||||
This is the file system used by the real-time operating systems
|
||||
QNX 6 (also called QNX RTP).
|
||||
Further information is available at <http://www.qnx.com/>.
|
||||
Say Y if you intend to mount QNX hard disks or floppies formatted
|
||||
with a mkqnx6fs.
|
||||
However, keep in mind that this currently is a readonly driver!
|
||||
|
||||
To compile this file system support as a module, choose M here: the
|
||||
module will be called qnx6.
|
||||
|
||||
If you don't know whether you need it, then you don't need it:
|
||||
answer N.
|
||||
|
||||
config QNX6FS_DEBUG
|
||||
bool "QNX6 debugging information"
|
||||
depends on QNX6FS_FS
|
||||
help
|
||||
Turns on extended debugging output.
|
||||
|
||||
If you are not a developer working on the QNX6FS, you probably don't
|
||||
want this:
|
||||
answer N.
|
||||
@@ -0,0 +1,7 @@
|
||||
#
|
||||
# Makefile for the linux qnx4-filesystem routines.
|
||||
#
|
||||
|
||||
obj-$(CONFIG_QNX6FS_FS) += qnx6.o
|
||||
|
||||
qnx6-objs := inode.o dir.o namei.o super_mmi.o
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
This is a snapshot of the QNX6 filesystem for Linux.
|
||||
Please send diffs and remarks to <chaosman@ontika.net> .
|
||||
|
||||
Credits :
|
||||
|
||||
Al Viro <viro@ZenIV.linux.org.uk> (endless patience with me & support ;))
|
||||
Kai Bankett <chaosman@ontika.net> (Maintainer)
|
||||
+291
@@ -0,0 +1,291 @@
|
||||
/*
|
||||
* QNX6 file system, Linux implementation.
|
||||
*
|
||||
* Version : 1.0.0
|
||||
*
|
||||
* History :
|
||||
*
|
||||
* 01-02-2012 by Kai Bankett (chaosman@ontika.net) : first release.
|
||||
* 16-02-2012 pagemap extension by Al Viro
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qnx6.h"
|
||||
|
||||
static unsigned qnx6_lfile_checksum(char *name, unsigned size)
|
||||
{
|
||||
unsigned crc = 0;
|
||||
char *end = name + size;
|
||||
while (name < end) {
|
||||
crc = ((crc >> 1) + *(name++)) ^
|
||||
((crc & 0x00000001) ? 0x80000000 : 0);
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
static struct page *qnx6_get_page(struct inode *dir, unsigned long n)
|
||||
{
|
||||
struct address_space *mapping = dir->i_mapping;
|
||||
struct page *page = read_mapping_page(mapping, n, NULL);
|
||||
if (!IS_ERR(page))
|
||||
kmap(page);
|
||||
return page;
|
||||
}
|
||||
|
||||
static inline unsigned long dir_pages(struct inode *inode)
|
||||
{
|
||||
return (inode->i_size+PAGE_CACHE_SIZE-1)>>PAGE_CACHE_SHIFT;
|
||||
}
|
||||
|
||||
static unsigned last_entry(struct inode *inode, unsigned long page_nr)
|
||||
{
|
||||
unsigned long last_byte = inode->i_size;
|
||||
last_byte -= page_nr << PAGE_CACHE_SHIFT;
|
||||
if (last_byte > PAGE_CACHE_SIZE)
|
||||
last_byte = PAGE_CACHE_SIZE;
|
||||
return last_byte / QNX6_DIR_ENTRY_SIZE;
|
||||
}
|
||||
|
||||
static struct qnx6_long_filename *qnx6_longname(struct super_block *sb,
|
||||
struct qnx6_long_dir_entry *de,
|
||||
struct page **p)
|
||||
{
|
||||
struct qnx6_sb_info *sbi = QNX6_SB(sb);
|
||||
u32 s = fs32_to_cpu(sbi, de->de_long_inode); /* in block units */
|
||||
u32 n = s >> (PAGE_CACHE_SHIFT - sb->s_blocksize_bits); /* in pages */
|
||||
/* within page */
|
||||
u32 offs = (s << sb->s_blocksize_bits) & ~PAGE_CACHE_MASK;
|
||||
struct address_space *mapping = sbi->longfile->i_mapping;
|
||||
struct page *page = read_mapping_page(mapping, n, NULL);
|
||||
if (IS_ERR(page))
|
||||
return ERR_CAST(page);
|
||||
kmap(*p = page);
|
||||
return (struct qnx6_long_filename *)(page_address(page) + offs);
|
||||
}
|
||||
|
||||
static int qnx6_dir_longfilename(struct inode *inode,
|
||||
struct qnx6_long_dir_entry *de,
|
||||
void *dirent, loff_t pos,
|
||||
unsigned de_inode, filldir_t filldir)
|
||||
{
|
||||
struct qnx6_long_filename *lf;
|
||||
struct super_block *s = inode->i_sb;
|
||||
struct qnx6_sb_info *sbi = QNX6_SB(s);
|
||||
struct page *page;
|
||||
int lf_size;
|
||||
|
||||
if (de->de_size != 0xff) {
|
||||
/* error - long filename entries always have size 0xff
|
||||
in direntry */
|
||||
printk(KERN_ERR "qnx6: invalid direntry size (%i).\n",
|
||||
de->de_size);
|
||||
return 0;
|
||||
}
|
||||
lf = qnx6_longname(s, de, &page);
|
||||
if (IS_ERR(lf)) {
|
||||
printk(KERN_ERR "qnx6:Error reading longname\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
lf_size = fs16_to_cpu(sbi, lf->lf_size);
|
||||
|
||||
if (lf_size > QNX6_LONG_NAME_MAX) {
|
||||
QNX6DEBUG((KERN_INFO "file %s\n", lf->lf_fname));
|
||||
printk(KERN_ERR "qnx6:Filename too long (%i)\n", lf_size);
|
||||
qnx6_put_page(page);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* calc & validate longfilename checksum
|
||||
mmi 3g filesystem does not have that checksum */
|
||||
if (!test_opt(s, MMI_FS) && fs32_to_cpu(sbi, de->de_checksum) !=
|
||||
qnx6_lfile_checksum(lf->lf_fname, lf_size))
|
||||
printk(KERN_INFO "qnx6: long filename checksum error.\n");
|
||||
|
||||
QNX6DEBUG((KERN_INFO "qnx6_readdir:%.*s inode:%u\n",
|
||||
lf_size, lf->lf_fname, de_inode));
|
||||
if (filldir(dirent, lf->lf_fname, lf_size, pos, de_inode,
|
||||
DT_UNKNOWN) < 0) {
|
||||
qnx6_put_page(page);
|
||||
return 0;
|
||||
}
|
||||
|
||||
qnx6_put_page(page);
|
||||
/* success */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int qnx6_readdir(struct file *filp, void *dirent, filldir_t filldir)
|
||||
{
|
||||
struct inode *inode = filp->f_path.dentry->d_inode;
|
||||
struct super_block *s = inode->i_sb;
|
||||
struct qnx6_sb_info *sbi = QNX6_SB(s);
|
||||
loff_t pos = filp->f_pos & (QNX6_DIR_ENTRY_SIZE - 1);
|
||||
unsigned long npages = dir_pages(inode);
|
||||
unsigned long n = pos >> PAGE_CACHE_SHIFT;
|
||||
unsigned start = (pos & ~PAGE_CACHE_MASK) / QNX6_DIR_ENTRY_SIZE;
|
||||
bool done = false;
|
||||
|
||||
if (filp->f_pos >= inode->i_size)
|
||||
return 0;
|
||||
|
||||
for ( ; !done && n < npages; n++, start = 0) {
|
||||
struct page *page = qnx6_get_page(inode, n);
|
||||
int limit = last_entry(inode, n);
|
||||
struct qnx6_dir_entry *de;
|
||||
int i = start;
|
||||
|
||||
if (IS_ERR(page)) {
|
||||
printk(KERN_ERR "qnx6_readdir: read failed\n");
|
||||
filp->f_pos = (n + 1) << PAGE_CACHE_SHIFT;
|
||||
return PTR_ERR(page);
|
||||
}
|
||||
de = ((struct qnx6_dir_entry *)page_address(page)) + start;
|
||||
for (; i < limit; i++, de++, pos += QNX6_DIR_ENTRY_SIZE) {
|
||||
int size = de->de_size;
|
||||
u32 no_inode = fs32_to_cpu(sbi, de->de_inode);
|
||||
|
||||
if (!no_inode || !size)
|
||||
continue;
|
||||
|
||||
if (size > QNX6_SHORT_NAME_MAX) {
|
||||
/* long filename detected
|
||||
get the filename from long filename
|
||||
structure / block */
|
||||
if (!qnx6_dir_longfilename(inode,
|
||||
(struct qnx6_long_dir_entry *)de,
|
||||
dirent, pos, no_inode,
|
||||
filldir)) {
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
QNX6DEBUG((KERN_INFO "qnx6_readdir:%.*s"
|
||||
" inode:%u\n", size, de->de_fname,
|
||||
no_inode));
|
||||
if (filldir(dirent, de->de_fname, size,
|
||||
pos, no_inode, DT_UNKNOWN)
|
||||
< 0) {
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
qnx6_put_page(page);
|
||||
}
|
||||
filp->f_pos = pos;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* check if the long filename is correct.
|
||||
*/
|
||||
static unsigned qnx6_long_match(int len, const char *name,
|
||||
struct qnx6_long_dir_entry *de, struct inode *dir)
|
||||
{
|
||||
struct super_block *s = dir->i_sb;
|
||||
struct qnx6_sb_info *sbi = QNX6_SB(s);
|
||||
struct page *page;
|
||||
int thislen;
|
||||
struct qnx6_long_filename *lf = qnx6_longname(s, de, &page);
|
||||
|
||||
if (IS_ERR(lf))
|
||||
return 0;
|
||||
|
||||
thislen = fs16_to_cpu(sbi, lf->lf_size);
|
||||
if (len != thislen) {
|
||||
qnx6_put_page(page);
|
||||
return 0;
|
||||
}
|
||||
if (memcmp(name, lf->lf_fname, len) == 0) {
|
||||
qnx6_put_page(page);
|
||||
return fs32_to_cpu(sbi, de->de_inode);
|
||||
}
|
||||
qnx6_put_page(page);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* check if the filename is correct.
|
||||
*/
|
||||
static unsigned qnx6_match(struct super_block *s, int len, const char *name,
|
||||
struct qnx6_dir_entry *de)
|
||||
{
|
||||
struct qnx6_sb_info *sbi = QNX6_SB(s);
|
||||
if (memcmp(name, de->de_fname, len) == 0)
|
||||
return fs32_to_cpu(sbi, de->de_inode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
unsigned qnx6_find_entry(int len, struct inode *dir, const char *name,
|
||||
struct page **res_page)
|
||||
{
|
||||
struct super_block *s = dir->i_sb;
|
||||
struct qnx6_inode_info *ei = QNX6_I(dir);
|
||||
struct page *page = NULL;
|
||||
unsigned long start, n;
|
||||
unsigned long npages = dir_pages(dir);
|
||||
unsigned ino;
|
||||
struct qnx6_dir_entry *de;
|
||||
struct qnx6_long_dir_entry *lde;
|
||||
|
||||
*res_page = NULL;
|
||||
|
||||
if (npages == 0)
|
||||
return 0;
|
||||
start = ei->i_dir_start_lookup;
|
||||
if (start >= npages)
|
||||
start = 0;
|
||||
n = start;
|
||||
|
||||
do {
|
||||
page = qnx6_get_page(dir, n);
|
||||
if (!IS_ERR(page)) {
|
||||
int limit = last_entry(dir, n);
|
||||
int i;
|
||||
|
||||
de = (struct qnx6_dir_entry *)page_address(page);
|
||||
for (i = 0; i < limit; i++, de++) {
|
||||
if (len <= QNX6_SHORT_NAME_MAX) {
|
||||
/* short filename */
|
||||
if (len != de->de_size)
|
||||
continue;
|
||||
ino = qnx6_match(s, len, name, de);
|
||||
if (ino)
|
||||
goto found;
|
||||
} else if (de->de_size == 0xff) {
|
||||
/* deal with long filename */
|
||||
lde = (struct qnx6_long_dir_entry *)de;
|
||||
ino = qnx6_long_match(len,
|
||||
name, lde, dir);
|
||||
if (ino)
|
||||
goto found;
|
||||
} else
|
||||
printk(KERN_ERR "qnx6: undefined "
|
||||
"filename size in inode.\n");
|
||||
}
|
||||
qnx6_put_page(page);
|
||||
}
|
||||
|
||||
if (++n >= npages)
|
||||
n = 0;
|
||||
} while (n != start);
|
||||
return 0;
|
||||
|
||||
found:
|
||||
*res_page = page;
|
||||
ei->i_dir_start_lookup = n;
|
||||
return ino;
|
||||
}
|
||||
|
||||
const struct file_operations qnx6_dir_operations = {
|
||||
.llseek = generic_file_llseek,
|
||||
.read = generic_read_dir,
|
||||
.readdir = qnx6_readdir,
|
||||
.fsync = generic_file_fsync,
|
||||
};
|
||||
|
||||
const struct inode_operations qnx6_dir_inode_operations = {
|
||||
.lookup = qnx6_lookup,
|
||||
};
|
||||
+698
@@ -0,0 +1,698 @@
|
||||
/*
|
||||
* QNX6 file system, Linux implementation.
|
||||
*
|
||||
* Version : 1.0.0
|
||||
*
|
||||
* History :
|
||||
*
|
||||
* 01-02-2012 by Kai Bankett (chaosman@ontika.net) : first release.
|
||||
* 16-02-2012 pagemap extension by Al Viro
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/highuid.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/buffer_head.h>
|
||||
#include <linux/writeback.h>
|
||||
#include <linux/statfs.h>
|
||||
#include <linux/parser.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/mount.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/mpage.h>
|
||||
#include "qnx6.h"
|
||||
|
||||
static const struct super_operations qnx6_sops;
|
||||
|
||||
static void qnx6_put_super(struct super_block *sb);
|
||||
static struct inode *qnx6_alloc_inode(struct super_block *sb);
|
||||
static void qnx6_destroy_inode(struct inode *inode);
|
||||
static int qnx6_remount(struct super_block *sb, int *flags, char *data);
|
||||
static int qnx6_statfs(struct dentry *dentry, struct kstatfs *buf);
|
||||
static int qnx6_show_options(struct seq_file *seq, struct dentry *root);
|
||||
|
||||
static const struct super_operations qnx6_sops = {
|
||||
.alloc_inode = qnx6_alloc_inode,
|
||||
.destroy_inode = qnx6_destroy_inode,
|
||||
.put_super = qnx6_put_super,
|
||||
.statfs = qnx6_statfs,
|
||||
.remount_fs = qnx6_remount,
|
||||
.show_options = qnx6_show_options,
|
||||
};
|
||||
|
||||
static int qnx6_show_options(struct seq_file *seq, struct dentry *root)
|
||||
{
|
||||
struct super_block *sb = root->d_sb;
|
||||
struct qnx6_sb_info *sbi = QNX6_SB(sb);
|
||||
|
||||
if (sbi->s_mount_opt & QNX6_MOUNT_MMI_FS)
|
||||
seq_puts(seq, ",mmi_fs");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qnx6_remount(struct super_block *sb, int *flags, char *data)
|
||||
{
|
||||
*flags |= MS_RDONLY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned qnx6_get_devblock(struct super_block *sb, __fs32 block)
|
||||
{
|
||||
struct qnx6_sb_info *sbi = QNX6_SB(sb);
|
||||
return fs32_to_cpu(sbi, block) + sbi->s_blks_off;
|
||||
}
|
||||
|
||||
static unsigned qnx6_block_map(struct inode *inode, unsigned iblock);
|
||||
|
||||
static int qnx6_get_block(struct inode *inode, sector_t iblock,
|
||||
struct buffer_head *bh, int create)
|
||||
{
|
||||
unsigned phys;
|
||||
|
||||
QNX6DEBUG((KERN_INFO "qnx6: qnx6_get_block inode=[%ld] iblock=[%ld]\n",
|
||||
inode->i_ino, (unsigned long)iblock));
|
||||
|
||||
phys = qnx6_block_map(inode, iblock);
|
||||
if (phys) {
|
||||
/* logical block is before EOF */
|
||||
map_bh(bh, inode->i_sb, phys);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qnx6_check_blockptr(__fs32 ptr)
|
||||
{
|
||||
if (ptr == ~(__fs32)0) {
|
||||
printk(KERN_ERR "qnx6: hit unused blockpointer.\n");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int qnx6_readpage(struct file *file, struct page *page)
|
||||
{
|
||||
return mpage_readpage(page, qnx6_get_block);
|
||||
}
|
||||
|
||||
static int qnx6_readpages(struct file *file, struct address_space *mapping,
|
||||
struct list_head *pages, unsigned nr_pages)
|
||||
{
|
||||
return mpage_readpages(mapping, pages, nr_pages, qnx6_get_block);
|
||||
}
|
||||
|
||||
/*
|
||||
* returns the block number for the no-th element in the tree
|
||||
* inodebits requred as there are multiple inodes in one inode block
|
||||
*/
|
||||
static unsigned qnx6_block_map(struct inode *inode, unsigned no)
|
||||
{
|
||||
struct super_block *s = inode->i_sb;
|
||||
struct qnx6_sb_info *sbi = QNX6_SB(s);
|
||||
struct qnx6_inode_info *ei = QNX6_I(inode);
|
||||
unsigned block = 0;
|
||||
struct buffer_head *bh;
|
||||
__fs32 ptr;
|
||||
int levelptr;
|
||||
int ptrbits = sbi->s_ptrbits;
|
||||
int bitdelta;
|
||||
u32 mask = (1 << ptrbits) - 1;
|
||||
int depth = ei->di_filelevels;
|
||||
int i;
|
||||
|
||||
bitdelta = ptrbits * depth;
|
||||
levelptr = no >> bitdelta;
|
||||
|
||||
if (levelptr > QNX6_NO_DIRECT_POINTERS - 1) {
|
||||
printk(KERN_ERR "qnx6:Requested file block number (%u) too big.",
|
||||
no);
|
||||
return 0;
|
||||
}
|
||||
|
||||
block = qnx6_get_devblock(s, ei->di_block_ptr[levelptr]);
|
||||
|
||||
for (i = 0; i < depth; i++) {
|
||||
bh = sb_bread(s, block);
|
||||
if (!bh) {
|
||||
printk(KERN_ERR "qnx6:Error reading block (%u)\n",
|
||||
block);
|
||||
return 0;
|
||||
}
|
||||
bitdelta -= ptrbits;
|
||||
levelptr = (no >> bitdelta) & mask;
|
||||
ptr = ((__fs32 *)bh->b_data)[levelptr];
|
||||
|
||||
if (!qnx6_check_blockptr(ptr))
|
||||
return 0;
|
||||
|
||||
block = qnx6_get_devblock(s, ptr);
|
||||
brelse(bh);
|
||||
}
|
||||
return block;
|
||||
}
|
||||
|
||||
static int qnx6_statfs(struct dentry *dentry, struct kstatfs *buf)
|
||||
{
|
||||
struct super_block *sb = dentry->d_sb;
|
||||
struct qnx6_sb_info *sbi = QNX6_SB(sb);
|
||||
u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
|
||||
|
||||
buf->f_type = sb->s_magic;
|
||||
buf->f_bsize = sb->s_blocksize;
|
||||
buf->f_blocks = fs32_to_cpu(sbi, sbi->sb->sb_num_blocks);
|
||||
buf->f_bfree = fs32_to_cpu(sbi, sbi->sb->sb_free_blocks);
|
||||
buf->f_files = fs32_to_cpu(sbi, sbi->sb->sb_num_inodes);
|
||||
buf->f_ffree = fs32_to_cpu(sbi, sbi->sb->sb_free_inodes);
|
||||
buf->f_bavail = buf->f_bfree;
|
||||
buf->f_namelen = QNX6_LONG_NAME_MAX;
|
||||
buf->f_fsid.val[0] = (u32)id;
|
||||
buf->f_fsid.val[1] = (u32)(id >> 32);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the root directory of the filesystem to make sure
|
||||
* it really _is_ a qnx6 filesystem, and to check the size
|
||||
* of the directory entry.
|
||||
*/
|
||||
static const char *qnx6_checkroot(struct super_block *s)
|
||||
{
|
||||
static char match_root[2][3] = {".\0\0", "..\0"};
|
||||
int i, error = 0;
|
||||
struct qnx6_dir_entry *dir_entry;
|
||||
struct inode *root = s->s_root->d_inode;
|
||||
struct address_space *mapping = root->i_mapping;
|
||||
struct page *page = read_mapping_page(mapping, 0, NULL);
|
||||
if (IS_ERR(page))
|
||||
return "error reading root directory";
|
||||
kmap(page);
|
||||
dir_entry = page_address(page);
|
||||
for (i = 0; i < 2; i++) {
|
||||
/* maximum 3 bytes - due to match_root limitation */
|
||||
if (strncmp(dir_entry[i].de_fname, match_root[i], 3))
|
||||
error = 1;
|
||||
}
|
||||
qnx6_put_page(page);
|
||||
if (error)
|
||||
return "error reading root directory.";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_QNX6FS_DEBUG
|
||||
void qnx6_superblock_debug(struct qnx6_super_block *sb, struct super_block *s)
|
||||
{
|
||||
struct qnx6_sb_info *sbi = QNX6_SB(s);
|
||||
|
||||
QNX6DEBUG((KERN_INFO "magic: %08x\n",
|
||||
fs32_to_cpu(sbi, sb->sb_magic)));
|
||||
QNX6DEBUG((KERN_INFO "checksum: %08x\n",
|
||||
fs32_to_cpu(sbi, sb->sb_checksum)));
|
||||
QNX6DEBUG((KERN_INFO "serial: %llx\n",
|
||||
fs64_to_cpu(sbi, sb->sb_serial)));
|
||||
QNX6DEBUG((KERN_INFO "flags: %08x\n",
|
||||
fs32_to_cpu(sbi, sb->sb_flags)));
|
||||
QNX6DEBUG((KERN_INFO "blocksize: %08x\n",
|
||||
fs32_to_cpu(sbi, sb->sb_blocksize)));
|
||||
QNX6DEBUG((KERN_INFO "num_inodes: %08x\n",
|
||||
fs32_to_cpu(sbi, sb->sb_num_inodes)));
|
||||
QNX6DEBUG((KERN_INFO "free_inodes: %08x\n",
|
||||
fs32_to_cpu(sbi, sb->sb_free_inodes)));
|
||||
QNX6DEBUG((KERN_INFO "num_blocks: %08x\n",
|
||||
fs32_to_cpu(sbi, sb->sb_num_blocks)));
|
||||
QNX6DEBUG((KERN_INFO "free_blocks: %08x\n",
|
||||
fs32_to_cpu(sbi, sb->sb_free_blocks)));
|
||||
QNX6DEBUG((KERN_INFO "inode_levels: %02x\n",
|
||||
sb->Inode.levels));
|
||||
}
|
||||
#endif
|
||||
|
||||
enum {
|
||||
Opt_mmifs,
|
||||
Opt_err
|
||||
};
|
||||
|
||||
static const match_table_t tokens = {
|
||||
{Opt_mmifs, "mmi_fs"},
|
||||
{Opt_err, NULL}
|
||||
};
|
||||
|
||||
static int qnx6_parse_options(char *options, struct super_block *sb)
|
||||
{
|
||||
char *p;
|
||||
struct qnx6_sb_info *sbi = QNX6_SB(sb);
|
||||
substring_t args[MAX_OPT_ARGS];
|
||||
|
||||
if (!options)
|
||||
return 1;
|
||||
|
||||
while ((p = strsep(&options, ",")) != NULL) {
|
||||
int token;
|
||||
if (!*p)
|
||||
continue;
|
||||
|
||||
token = match_token(p, tokens, args);
|
||||
switch (token) {
|
||||
case Opt_mmifs:
|
||||
set_opt(sbi->s_mount_opt, MMI_FS);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct buffer_head *qnx6_check_first_superblock(struct super_block *s,
|
||||
int offset, int silent)
|
||||
{
|
||||
struct qnx6_sb_info *sbi = QNX6_SB(s);
|
||||
struct buffer_head *bh;
|
||||
struct qnx6_super_block *sb;
|
||||
|
||||
/* Check the superblock signatures
|
||||
start with the first superblock */
|
||||
bh = sb_bread(s, offset);
|
||||
if (!bh) {
|
||||
printk(KERN_ERR "qnx6: unable to read the first superblock\n");
|
||||
return NULL;
|
||||
}
|
||||
sb = (struct qnx6_super_block *)bh->b_data;
|
||||
if (fs32_to_cpu(sbi, sb->sb_magic) != QNX6_SUPER_MAGIC) {
|
||||
sbi->s_bytesex = BYTESEX_BE;
|
||||
if (fs32_to_cpu(sbi, sb->sb_magic) == QNX6_SUPER_MAGIC) {
|
||||
/* we got a big endian fs */
|
||||
QNX6DEBUG((KERN_INFO "qnx6: fs got different"
|
||||
" endianess.\n"));
|
||||
return bh;
|
||||
} else
|
||||
sbi->s_bytesex = BYTESEX_LE;
|
||||
if (!silent) {
|
||||
if (offset == 0) {
|
||||
printk(KERN_ERR "qnx6: wrong signature (magic)"
|
||||
" in superblock #1.\n");
|
||||
} else {
|
||||
printk(KERN_INFO "qnx6: wrong signature (magic)"
|
||||
" at position (0x%lx) - will try"
|
||||
" alternative position (0x0000).\n",
|
||||
offset * s->s_blocksize);
|
||||
}
|
||||
}
|
||||
brelse(bh);
|
||||
return NULL;
|
||||
}
|
||||
return bh;
|
||||
}
|
||||
|
||||
static struct inode *qnx6_private_inode(struct super_block *s,
|
||||
struct qnx6_root_node *p);
|
||||
|
||||
static int qnx6_fill_super(struct super_block *s, void *data, int silent)
|
||||
{
|
||||
struct buffer_head *bh1 = NULL, *bh2 = NULL;
|
||||
struct qnx6_super_block *sb1 = NULL, *sb2 = NULL;
|
||||
struct qnx6_sb_info *sbi;
|
||||
struct inode *root;
|
||||
const char *errmsg;
|
||||
struct qnx6_sb_info *qs;
|
||||
int ret = -EINVAL;
|
||||
u64 offset;
|
||||
int bootblock_offset = QNX6_BOOTBLOCK_SIZE;
|
||||
|
||||
qs = kzalloc(sizeof(struct qnx6_sb_info), GFP_KERNEL);
|
||||
if (!qs)
|
||||
return -ENOMEM;
|
||||
s->s_fs_info = qs;
|
||||
|
||||
/* Superblock always is 512 Byte long */
|
||||
if (!sb_set_blocksize(s, QNX6_SUPERBLOCK_SIZE)) {
|
||||
printk(KERN_ERR "qnx6: unable to set blocksize\n");
|
||||
goto outnobh;
|
||||
}
|
||||
|
||||
/* parse the mount-options */
|
||||
if (!qnx6_parse_options((char *) data, s)) {
|
||||
printk(KERN_ERR "qnx6: invalid mount options.\n");
|
||||
goto outnobh;
|
||||
}
|
||||
if (test_opt(s, MMI_FS)) {
|
||||
sb1 = qnx6_mmi_fill_super(s, silent);
|
||||
if (sb1)
|
||||
goto mmi_success;
|
||||
else
|
||||
goto outnobh;
|
||||
}
|
||||
sbi = QNX6_SB(s);
|
||||
sbi->s_bytesex = BYTESEX_LE;
|
||||
/* Check the superblock signatures
|
||||
start with the first superblock */
|
||||
bh1 = qnx6_check_first_superblock(s,
|
||||
bootblock_offset / QNX6_SUPERBLOCK_SIZE, silent);
|
||||
if (!bh1) {
|
||||
/* try again without bootblock offset */
|
||||
bh1 = qnx6_check_first_superblock(s, 0, silent);
|
||||
if (!bh1) {
|
||||
printk(KERN_ERR "qnx6: unable to read the first superblock\n");
|
||||
goto outnobh;
|
||||
}
|
||||
/* seems that no bootblock at partition start */
|
||||
bootblock_offset = 0;
|
||||
}
|
||||
sb1 = (struct qnx6_super_block *)bh1->b_data;
|
||||
|
||||
#ifdef CONFIG_QNX6FS_DEBUG
|
||||
qnx6_superblock_debug(sb1, s);
|
||||
#endif
|
||||
|
||||
/* checksum check - start at byte 8 and end at byte 512 */
|
||||
if (fs32_to_cpu(sbi, sb1->sb_checksum) !=
|
||||
crc32_be(0, (char *)(bh1->b_data + 8), 504)) {
|
||||
printk(KERN_ERR "qnx6: superblock #1 checksum error\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* set new blocksize */
|
||||
if (!sb_set_blocksize(s, fs32_to_cpu(sbi, sb1->sb_blocksize))) {
|
||||
printk(KERN_ERR "qnx6: unable to set blocksize\n");
|
||||
goto out;
|
||||
}
|
||||
/* blocksize invalidates bh - pull it back in */
|
||||
brelse(bh1);
|
||||
bh1 = sb_bread(s, bootblock_offset >> s->s_blocksize_bits);
|
||||
if (!bh1)
|
||||
goto outnobh;
|
||||
sb1 = (struct qnx6_super_block *)bh1->b_data;
|
||||
|
||||
/* calculate second superblock blocknumber */
|
||||
offset = fs32_to_cpu(sbi, sb1->sb_num_blocks) +
|
||||
(bootblock_offset >> s->s_blocksize_bits) +
|
||||
(QNX6_SUPERBLOCK_AREA >> s->s_blocksize_bits);
|
||||
|
||||
/* set bootblock offset */
|
||||
sbi->s_blks_off = (bootblock_offset >> s->s_blocksize_bits) +
|
||||
(QNX6_SUPERBLOCK_AREA >> s->s_blocksize_bits);
|
||||
|
||||
/* next the second superblock */
|
||||
bh2 = sb_bread(s, offset);
|
||||
if (!bh2) {
|
||||
printk(KERN_ERR "qnx6: unable to read the second superblock\n");
|
||||
goto out;
|
||||
}
|
||||
sb2 = (struct qnx6_super_block *)bh2->b_data;
|
||||
if (fs32_to_cpu(sbi, sb2->sb_magic) != QNX6_SUPER_MAGIC) {
|
||||
if (!silent)
|
||||
printk(KERN_ERR "qnx6: wrong signature (magic)"
|
||||
" in superblock #2.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* checksum check - start at byte 8 and end at byte 512 */
|
||||
if (fs32_to_cpu(sbi, sb2->sb_checksum) !=
|
||||
crc32_be(0, (char *)(bh2->b_data + 8), 504)) {
|
||||
printk(KERN_ERR "qnx6: superblock #2 checksum error\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (fs64_to_cpu(sbi, sb1->sb_serial) >=
|
||||
fs64_to_cpu(sbi, sb2->sb_serial)) {
|
||||
/* superblock #1 active */
|
||||
sbi->sb_buf = bh1;
|
||||
sbi->sb = (struct qnx6_super_block *)bh1->b_data;
|
||||
brelse(bh2);
|
||||
printk(KERN_INFO "qnx6: superblock #1 active\n");
|
||||
} else {
|
||||
/* superblock #2 active */
|
||||
sbi->sb_buf = bh2;
|
||||
sbi->sb = (struct qnx6_super_block *)bh2->b_data;
|
||||
brelse(bh1);
|
||||
printk(KERN_INFO "qnx6: superblock #2 active\n");
|
||||
}
|
||||
mmi_success:
|
||||
/* sanity check - limit maximum indirect pointer levels */
|
||||
if (sb1->Inode.levels > QNX6_PTR_MAX_LEVELS) {
|
||||
printk(KERN_ERR "qnx6: too many inode levels (max %i, sb %i)\n",
|
||||
QNX6_PTR_MAX_LEVELS, sb1->Inode.levels);
|
||||
goto out;
|
||||
}
|
||||
if (sb1->Longfile.levels > QNX6_PTR_MAX_LEVELS) {
|
||||
printk(KERN_ERR "qnx6: too many longfilename levels"
|
||||
" (max %i, sb %i)\n",
|
||||
QNX6_PTR_MAX_LEVELS, sb1->Longfile.levels);
|
||||
goto out;
|
||||
}
|
||||
s->s_op = &qnx6_sops;
|
||||
s->s_magic = QNX6_SUPER_MAGIC;
|
||||
s->s_flags |= MS_RDONLY; /* Yup, read-only yet */
|
||||
|
||||
/* ease the later tree level calculations */
|
||||
sbi = QNX6_SB(s);
|
||||
sbi->s_ptrbits = ilog2(s->s_blocksize / 4);
|
||||
sbi->inodes = qnx6_private_inode(s, &sb1->Inode);
|
||||
if (!sbi->inodes)
|
||||
goto out;
|
||||
sbi->longfile = qnx6_private_inode(s, &sb1->Longfile);
|
||||
if (!sbi->longfile)
|
||||
goto out1;
|
||||
|
||||
/* prefetch root inode */
|
||||
root = qnx6_iget(s, QNX6_ROOT_INO);
|
||||
if (IS_ERR(root)) {
|
||||
printk(KERN_ERR "qnx6: get inode failed\n");
|
||||
ret = PTR_ERR(root);
|
||||
goto out2;
|
||||
}
|
||||
|
||||
ret = -ENOMEM;
|
||||
s->s_root = d_make_root(root);
|
||||
if (!s->s_root)
|
||||
goto out2;
|
||||
|
||||
ret = -EINVAL;
|
||||
errmsg = qnx6_checkroot(s);
|
||||
if (errmsg != NULL) {
|
||||
if (!silent)
|
||||
printk(KERN_ERR "qnx6: %s\n", errmsg);
|
||||
goto out3;
|
||||
}
|
||||
return 0;
|
||||
|
||||
out3:
|
||||
dput(s->s_root);
|
||||
s->s_root = NULL;
|
||||
out2:
|
||||
iput(sbi->longfile);
|
||||
out1:
|
||||
iput(sbi->inodes);
|
||||
out:
|
||||
if (bh1)
|
||||
brelse(bh1);
|
||||
if (bh2)
|
||||
brelse(bh2);
|
||||
outnobh:
|
||||
kfree(qs);
|
||||
s->s_fs_info = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void qnx6_put_super(struct super_block *sb)
|
||||
{
|
||||
struct qnx6_sb_info *qs = QNX6_SB(sb);
|
||||
brelse(qs->sb_buf);
|
||||
iput(qs->longfile);
|
||||
iput(qs->inodes);
|
||||
kfree(qs);
|
||||
sb->s_fs_info = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
static sector_t qnx6_bmap(struct address_space *mapping, sector_t block)
|
||||
{
|
||||
return generic_block_bmap(mapping, block, qnx6_get_block);
|
||||
}
|
||||
static const struct address_space_operations qnx6_aops = {
|
||||
.readpage = qnx6_readpage,
|
||||
.readpages = qnx6_readpages,
|
||||
.bmap = qnx6_bmap
|
||||
};
|
||||
|
||||
static struct inode *qnx6_private_inode(struct super_block *s,
|
||||
struct qnx6_root_node *p)
|
||||
{
|
||||
struct inode *inode = new_inode(s);
|
||||
if (inode) {
|
||||
struct qnx6_inode_info *ei = QNX6_I(inode);
|
||||
struct qnx6_sb_info *sbi = QNX6_SB(s);
|
||||
inode->i_size = fs64_to_cpu(sbi, p->size);
|
||||
memcpy(ei->di_block_ptr, p->ptr, sizeof(p->ptr));
|
||||
ei->di_filelevels = p->levels;
|
||||
inode->i_mode = S_IFREG | S_IRUSR; /* probably wrong */
|
||||
inode->i_mapping->a_ops = &qnx6_aops;
|
||||
}
|
||||
return inode;
|
||||
}
|
||||
|
||||
struct inode *qnx6_iget(struct super_block *sb, unsigned ino)
|
||||
{
|
||||
struct qnx6_sb_info *sbi = QNX6_SB(sb);
|
||||
struct qnx6_inode_entry *raw_inode;
|
||||
struct inode *inode;
|
||||
struct qnx6_inode_info *ei;
|
||||
struct address_space *mapping;
|
||||
struct page *page;
|
||||
u32 n, offs;
|
||||
|
||||
inode = iget_locked(sb, ino);
|
||||
if (!inode)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
if (!(inode->i_state & I_NEW))
|
||||
return inode;
|
||||
|
||||
ei = QNX6_I(inode);
|
||||
|
||||
inode->i_mode = 0;
|
||||
|
||||
if (ino == 0) {
|
||||
printk(KERN_ERR "qnx6: bad inode number on dev %s: %u is "
|
||||
"out of range\n",
|
||||
sb->s_id, ino);
|
||||
iget_failed(inode);
|
||||
return ERR_PTR(-EIO);
|
||||
}
|
||||
n = (ino - 1) >> (PAGE_CACHE_SHIFT - QNX6_INODE_SIZE_BITS);
|
||||
offs = (ino - 1) & (~PAGE_CACHE_MASK >> QNX6_INODE_SIZE_BITS);
|
||||
mapping = sbi->inodes->i_mapping;
|
||||
page = read_mapping_page(mapping, n, NULL);
|
||||
if (IS_ERR(page)) {
|
||||
printk(KERN_ERR "qnx6: major problem: unable to read inode from "
|
||||
"dev %s\n", sb->s_id);
|
||||
iget_failed(inode);
|
||||
return ERR_CAST(page);
|
||||
}
|
||||
kmap(page);
|
||||
raw_inode = ((struct qnx6_inode_entry *)page_address(page)) + offs;
|
||||
|
||||
inode->i_mode = fs16_to_cpu(sbi, raw_inode->di_mode);
|
||||
inode->i_uid = (uid_t)fs32_to_cpu(sbi, raw_inode->di_uid);
|
||||
inode->i_gid = (gid_t)fs32_to_cpu(sbi, raw_inode->di_gid);
|
||||
inode->i_size = fs64_to_cpu(sbi, raw_inode->di_size);
|
||||
inode->i_mtime.tv_sec = fs32_to_cpu(sbi, raw_inode->di_mtime);
|
||||
inode->i_mtime.tv_nsec = 0;
|
||||
inode->i_atime.tv_sec = fs32_to_cpu(sbi, raw_inode->di_atime);
|
||||
inode->i_atime.tv_nsec = 0;
|
||||
inode->i_ctime.tv_sec = fs32_to_cpu(sbi, raw_inode->di_ctime);
|
||||
inode->i_ctime.tv_nsec = 0;
|
||||
|
||||
/* calc blocks based on 512 byte blocksize */
|
||||
inode->i_blocks = (inode->i_size + 511) >> 9;
|
||||
|
||||
memcpy(&ei->di_block_ptr, &raw_inode->di_block_ptr,
|
||||
sizeof(raw_inode->di_block_ptr));
|
||||
ei->di_filelevels = raw_inode->di_filelevels;
|
||||
|
||||
if (S_ISREG(inode->i_mode)) {
|
||||
inode->i_fop = &generic_ro_fops;
|
||||
inode->i_mapping->a_ops = &qnx6_aops;
|
||||
} else if (S_ISDIR(inode->i_mode)) {
|
||||
inode->i_op = &qnx6_dir_inode_operations;
|
||||
inode->i_fop = &qnx6_dir_operations;
|
||||
inode->i_mapping->a_ops = &qnx6_aops;
|
||||
} else if (S_ISLNK(inode->i_mode)) {
|
||||
inode->i_op = &page_symlink_inode_operations;
|
||||
inode->i_mapping->a_ops = &qnx6_aops;
|
||||
} else
|
||||
init_special_inode(inode, inode->i_mode, 0);
|
||||
qnx6_put_page(page);
|
||||
unlock_new_inode(inode);
|
||||
return inode;
|
||||
}
|
||||
|
||||
static struct kmem_cache *qnx6_inode_cachep;
|
||||
|
||||
static struct inode *qnx6_alloc_inode(struct super_block *sb)
|
||||
{
|
||||
struct qnx6_inode_info *ei;
|
||||
ei = kmem_cache_alloc(qnx6_inode_cachep, GFP_KERNEL);
|
||||
if (!ei)
|
||||
return NULL;
|
||||
return &ei->vfs_inode;
|
||||
}
|
||||
|
||||
static void qnx6_i_callback(struct rcu_head *head)
|
||||
{
|
||||
struct inode *inode = container_of(head, struct inode, i_rcu);
|
||||
INIT_LIST_HEAD(&inode->i_dentry);
|
||||
kmem_cache_free(qnx6_inode_cachep, QNX6_I(inode));
|
||||
}
|
||||
|
||||
static void qnx6_destroy_inode(struct inode *inode)
|
||||
{
|
||||
call_rcu(&inode->i_rcu, qnx6_i_callback);
|
||||
}
|
||||
|
||||
static void init_once(void *foo)
|
||||
{
|
||||
struct qnx6_inode_info *ei = (struct qnx6_inode_info *) foo;
|
||||
|
||||
inode_init_once(&ei->vfs_inode);
|
||||
}
|
||||
|
||||
static int init_inodecache(void)
|
||||
{
|
||||
qnx6_inode_cachep = kmem_cache_create("qnx6_inode_cache",
|
||||
sizeof(struct qnx6_inode_info),
|
||||
0, (SLAB_RECLAIM_ACCOUNT|
|
||||
SLAB_MEM_SPREAD),
|
||||
init_once);
|
||||
if (!qnx6_inode_cachep)
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void destroy_inodecache(void)
|
||||
{
|
||||
kmem_cache_destroy(qnx6_inode_cachep);
|
||||
}
|
||||
|
||||
static struct dentry *qnx6_mount(struct file_system_type *fs_type,
|
||||
int flags, const char *dev_name, void *data)
|
||||
{
|
||||
return mount_bdev(fs_type, flags, dev_name, data, qnx6_fill_super);
|
||||
}
|
||||
|
||||
static struct file_system_type qnx6_fs_type = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "qnx6",
|
||||
.mount = qnx6_mount,
|
||||
.kill_sb = kill_block_super,
|
||||
.fs_flags = FS_REQUIRES_DEV,
|
||||
};
|
||||
|
||||
static int __init init_qnx6_fs(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = init_inodecache();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = register_filesystem(&qnx6_fs_type);
|
||||
if (err) {
|
||||
destroy_inodecache();
|
||||
return err;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "QNX6 filesystem 1.0.0 registered.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit exit_qnx6_fs(void)
|
||||
{
|
||||
unregister_filesystem(&qnx6_fs_type);
|
||||
destroy_inodecache();
|
||||
}
|
||||
|
||||
module_init(init_qnx6_fs)
|
||||
module_exit(exit_qnx6_fs)
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* QNX6 file system, Linux implementation.
|
||||
*
|
||||
* Version : 1.0.0
|
||||
*
|
||||
* History :
|
||||
*
|
||||
* 01-02-2012 by Kai Bankett (chaosman@ontika.net) : first release.
|
||||
* 16-02-2012 pagemap extension by Al Viro
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qnx6.h"
|
||||
|
||||
struct dentry *qnx6_lookup(struct inode *dir, struct dentry *dentry,
|
||||
struct nameidata *nd)
|
||||
{
|
||||
unsigned ino;
|
||||
struct page *page;
|
||||
struct inode *foundinode = NULL;
|
||||
const char *name = dentry->d_name.name;
|
||||
int len = dentry->d_name.len;
|
||||
|
||||
if (len > QNX6_LONG_NAME_MAX)
|
||||
return ERR_PTR(-ENAMETOOLONG);
|
||||
|
||||
ino = qnx6_find_entry(len, dir, name, &page);
|
||||
if (ino) {
|
||||
foundinode = qnx6_iget(dir->i_sb, ino);
|
||||
qnx6_put_page(page);
|
||||
if (IS_ERR(foundinode)) {
|
||||
QNX6DEBUG((KERN_ERR "qnx6: lookup->iget -> "
|
||||
" error %ld\n", PTR_ERR(foundinode)));
|
||||
return ERR_CAST(foundinode);
|
||||
}
|
||||
} else {
|
||||
QNX6DEBUG((KERN_INFO "qnx6_lookup: not found %s\n", name));
|
||||
return NULL;
|
||||
}
|
||||
d_add(dentry, foundinode);
|
||||
return NULL;
|
||||
}
|
||||
+135
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* QNX6 file system, Linux implementation.
|
||||
*
|
||||
* Version : 1.0.0
|
||||
*
|
||||
* History :
|
||||
*
|
||||
* 01-02-2012 by Kai Bankett (chaosman@ontika.net) : first release.
|
||||
* 16-02-2012 page map extension by Al Viro
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/pagemap.h>
|
||||
|
||||
typedef __u16 __bitwise __fs16;
|
||||
typedef __u32 __bitwise __fs32;
|
||||
typedef __u64 __bitwise __fs64;
|
||||
|
||||
#include <linux/qnx6_fs.h>
|
||||
|
||||
#ifdef CONFIG_QNX6FS_DEBUG
|
||||
#define QNX6DEBUG(X) printk X
|
||||
#else
|
||||
#define QNX6DEBUG(X) (void) 0
|
||||
#endif
|
||||
|
||||
struct qnx6_sb_info {
|
||||
struct buffer_head *sb_buf; /* superblock buffer */
|
||||
struct qnx6_super_block *sb; /* our superblock */
|
||||
int s_blks_off; /* blkoffset fs-startpoint */
|
||||
int s_ptrbits; /* indirect pointer bitfield */
|
||||
unsigned long s_mount_opt; /* all mount options */
|
||||
int s_bytesex; /* holds endianess info */
|
||||
struct inode * inodes;
|
||||
struct inode * longfile;
|
||||
};
|
||||
|
||||
struct qnx6_inode_info {
|
||||
__fs32 di_block_ptr[QNX6_NO_DIRECT_POINTERS];
|
||||
__u8 di_filelevels;
|
||||
__u32 i_dir_start_lookup;
|
||||
struct inode vfs_inode;
|
||||
};
|
||||
|
||||
extern struct inode *qnx6_iget(struct super_block *sb, unsigned ino);
|
||||
extern struct dentry *qnx6_lookup(struct inode *dir, struct dentry *dentry,
|
||||
struct nameidata *nd);
|
||||
|
||||
#ifdef CONFIG_QNX6FS_DEBUG
|
||||
extern void qnx6_superblock_debug(struct qnx6_super_block *,
|
||||
struct super_block *);
|
||||
#endif
|
||||
|
||||
extern const struct inode_operations qnx6_dir_inode_operations;
|
||||
extern const struct file_operations qnx6_dir_operations;
|
||||
|
||||
static inline struct qnx6_sb_info *QNX6_SB(struct super_block *sb)
|
||||
{
|
||||
return sb->s_fs_info;
|
||||
}
|
||||
|
||||
static inline struct qnx6_inode_info *QNX6_I(struct inode *inode)
|
||||
{
|
||||
return container_of(inode, struct qnx6_inode_info, vfs_inode);
|
||||
}
|
||||
|
||||
#define clear_opt(o, opt) (o &= ~(QNX6_MOUNT_##opt))
|
||||
#define set_opt(o, opt) (o |= (QNX6_MOUNT_##opt))
|
||||
#define test_opt(sb, opt) (QNX6_SB(sb)->s_mount_opt & \
|
||||
QNX6_MOUNT_##opt)
|
||||
enum {
|
||||
BYTESEX_LE,
|
||||
BYTESEX_BE,
|
||||
};
|
||||
|
||||
static inline __u64 fs64_to_cpu(struct qnx6_sb_info *sbi, __fs64 n)
|
||||
{
|
||||
if (sbi->s_bytesex == BYTESEX_LE)
|
||||
return le64_to_cpu((__force __le64)n);
|
||||
else
|
||||
return be64_to_cpu((__force __be64)n);
|
||||
}
|
||||
|
||||
static inline __fs64 cpu_to_fs64(struct qnx6_sb_info *sbi, __u64 n)
|
||||
{
|
||||
if (sbi->s_bytesex == BYTESEX_LE)
|
||||
return (__force __fs64)cpu_to_le64(n);
|
||||
else
|
||||
return (__force __fs64)cpu_to_be64(n);
|
||||
}
|
||||
|
||||
static inline __u32 fs32_to_cpu(struct qnx6_sb_info *sbi, __fs32 n)
|
||||
{
|
||||
if (sbi->s_bytesex == BYTESEX_LE)
|
||||
return le32_to_cpu((__force __le32)n);
|
||||
else
|
||||
return be32_to_cpu((__force __be32)n);
|
||||
}
|
||||
|
||||
static inline __fs32 cpu_to_fs32(struct qnx6_sb_info *sbi, __u32 n)
|
||||
{
|
||||
if (sbi->s_bytesex == BYTESEX_LE)
|
||||
return (__force __fs32)cpu_to_le32(n);
|
||||
else
|
||||
return (__force __fs32)cpu_to_be32(n);
|
||||
}
|
||||
|
||||
static inline __u16 fs16_to_cpu(struct qnx6_sb_info *sbi, __fs16 n)
|
||||
{
|
||||
if (sbi->s_bytesex == BYTESEX_LE)
|
||||
return le16_to_cpu((__force __le16)n);
|
||||
else
|
||||
return be16_to_cpu((__force __be16)n);
|
||||
}
|
||||
|
||||
static inline __fs16 cpu_to_fs16(struct qnx6_sb_info *sbi, __u16 n)
|
||||
{
|
||||
if (sbi->s_bytesex == BYTESEX_LE)
|
||||
return (__force __fs16)cpu_to_le16(n);
|
||||
else
|
||||
return (__force __fs16)cpu_to_be16(n);
|
||||
}
|
||||
|
||||
extern struct qnx6_super_block *qnx6_mmi_fill_super(struct super_block *s,
|
||||
int silent);
|
||||
|
||||
static inline void qnx6_put_page(struct page *page)
|
||||
{
|
||||
kunmap(page);
|
||||
page_cache_release(page);
|
||||
}
|
||||
|
||||
extern unsigned qnx6_find_entry(int len, struct inode *dir, const char *name,
|
||||
struct page **res_page);
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* QNX6 file system, Linux implementation.
|
||||
*
|
||||
* Version : 1.0.0
|
||||
*
|
||||
* History :
|
||||
*
|
||||
* 01-02-2012 by Kai Bankett (chaosman@ontika.net) : first release.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/buffer_head.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/crc32.h>
|
||||
#include "qnx6.h"
|
||||
|
||||
static void qnx6_mmi_copy_sb(struct qnx6_super_block *qsb,
|
||||
struct qnx6_mmi_super_block *sb)
|
||||
{
|
||||
qsb->sb_magic = sb->sb_magic;
|
||||
qsb->sb_checksum = sb->sb_checksum;
|
||||
qsb->sb_serial = sb->sb_serial;
|
||||
qsb->sb_blocksize = sb->sb_blocksize;
|
||||
qsb->sb_num_inodes = sb->sb_num_inodes;
|
||||
qsb->sb_free_inodes = sb->sb_free_inodes;
|
||||
qsb->sb_num_blocks = sb->sb_num_blocks;
|
||||
qsb->sb_free_blocks = sb->sb_free_blocks;
|
||||
|
||||
/* the rest of the superblock is the same */
|
||||
memcpy(&qsb->Inode, &sb->Inode, sizeof(sb->Inode));
|
||||
memcpy(&qsb->Bitmap, &sb->Bitmap, sizeof(sb->Bitmap));
|
||||
memcpy(&qsb->Longfile, &sb->Longfile, sizeof(sb->Longfile));
|
||||
}
|
||||
|
||||
struct qnx6_super_block *qnx6_mmi_fill_super(struct super_block *s, int silent)
|
||||
{
|
||||
struct buffer_head *bh1, *bh2 = NULL;
|
||||
struct qnx6_mmi_super_block *sb1, *sb2;
|
||||
struct qnx6_super_block *qsb = NULL;
|
||||
struct qnx6_sb_info *sbi;
|
||||
__u64 offset;
|
||||
|
||||
/* Check the superblock signatures
|
||||
start with the first superblock */
|
||||
bh1 = sb_bread(s, 0);
|
||||
if (!bh1) {
|
||||
printk(KERN_ERR "qnx6: Unable to read first mmi superblock\n");
|
||||
return NULL;
|
||||
}
|
||||
sb1 = (struct qnx6_mmi_super_block *)bh1->b_data;
|
||||
sbi = QNX6_SB(s);
|
||||
if (fs32_to_cpu(sbi, sb1->sb_magic) != QNX6_SUPER_MAGIC) {
|
||||
if (!silent) {
|
||||
printk(KERN_ERR "qnx6: wrong signature (magic) in"
|
||||
" superblock #1.\n");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* checksum check - start at byte 8 and end at byte 512 */
|
||||
if (fs32_to_cpu(sbi, sb1->sb_checksum) !=
|
||||
crc32_be(0, (char *)(bh1->b_data + 8), 504)) {
|
||||
printk(KERN_ERR "qnx6: superblock #1 checksum error\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* calculate second superblock blocknumber */
|
||||
offset = fs32_to_cpu(sbi, sb1->sb_num_blocks) + QNX6_SUPERBLOCK_AREA /
|
||||
fs32_to_cpu(sbi, sb1->sb_blocksize);
|
||||
|
||||
/* set new blocksize */
|
||||
if (!sb_set_blocksize(s, fs32_to_cpu(sbi, sb1->sb_blocksize))) {
|
||||
printk(KERN_ERR "qnx6: unable to set blocksize\n");
|
||||
goto out;
|
||||
}
|
||||
/* blocksize invalidates bh - pull it back in */
|
||||
brelse(bh1);
|
||||
bh1 = sb_bread(s, 0);
|
||||
if (!bh1)
|
||||
goto out;
|
||||
sb1 = (struct qnx6_mmi_super_block *)bh1->b_data;
|
||||
|
||||
/* read second superblock */
|
||||
bh2 = sb_bread(s, offset);
|
||||
if (!bh2) {
|
||||
printk(KERN_ERR "qnx6: unable to read the second superblock\n");
|
||||
goto out;
|
||||
}
|
||||
sb2 = (struct qnx6_mmi_super_block *)bh2->b_data;
|
||||
if (fs32_to_cpu(sbi, sb2->sb_magic) != QNX6_SUPER_MAGIC) {
|
||||
if (!silent)
|
||||
printk(KERN_ERR "qnx6: wrong signature (magic) in"
|
||||
" superblock #2.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* checksum check - start at byte 8 and end at byte 512 */
|
||||
if (fs32_to_cpu(sbi, sb2->sb_checksum)
|
||||
!= crc32_be(0, (char *)(bh2->b_data + 8), 504)) {
|
||||
printk(KERN_ERR "qnx6: superblock #1 checksum error\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
qsb = kmalloc(sizeof(*qsb), GFP_KERNEL);
|
||||
if (!qsb) {
|
||||
printk(KERN_ERR "qnx6: unable to allocate memory.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (fs64_to_cpu(sbi, sb1->sb_serial) >
|
||||
fs64_to_cpu(sbi, sb2->sb_serial)) {
|
||||
/* superblock #1 active */
|
||||
qnx6_mmi_copy_sb(qsb, sb1);
|
||||
#ifdef CONFIG_QNX6FS_DEBUG
|
||||
qnx6_superblock_debug(qsb, s);
|
||||
#endif
|
||||
memcpy(bh1->b_data, qsb, sizeof(struct qnx6_super_block));
|
||||
|
||||
sbi->sb_buf = bh1;
|
||||
sbi->sb = (struct qnx6_super_block *)bh1->b_data;
|
||||
brelse(bh2);
|
||||
printk(KERN_INFO "qnx6: superblock #1 active\n");
|
||||
} else {
|
||||
/* superblock #2 active */
|
||||
qnx6_mmi_copy_sb(qsb, sb2);
|
||||
#ifdef CONFIG_QNX6FS_DEBUG
|
||||
qnx6_superblock_debug(qsb, s);
|
||||
#endif
|
||||
memcpy(bh2->b_data, qsb, sizeof(struct qnx6_super_block));
|
||||
|
||||
sbi->sb_buf = bh2;
|
||||
sbi->sb = (struct qnx6_super_block *)bh2->b_data;
|
||||
brelse(bh1);
|
||||
printk(KERN_INFO "qnx6: superblock #2 active\n");
|
||||
}
|
||||
kfree(qsb);
|
||||
|
||||
/* offset for mmi_fs is just SUPERBLOCK_AREA bytes */
|
||||
sbi->s_blks_off = QNX6_SUPERBLOCK_AREA / s->s_blocksize;
|
||||
|
||||
/* success */
|
||||
return sbi->sb;
|
||||
|
||||
out:
|
||||
if (bh1 != NULL)
|
||||
brelse(bh1);
|
||||
if (bh2 != NULL)
|
||||
brelse(bh2);
|
||||
return NULL;
|
||||
}
|
||||
+7
-23
@@ -209,22 +209,19 @@ static int ramfs_parse_options(char *data, struct ramfs_mount_opts *opts)
|
||||
int ramfs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
{
|
||||
struct ramfs_fs_info *fsi;
|
||||
struct inode *inode = NULL;
|
||||
struct dentry *root;
|
||||
struct inode *inode;
|
||||
int err;
|
||||
|
||||
save_mount_options(sb, data);
|
||||
|
||||
fsi = kzalloc(sizeof(struct ramfs_fs_info), GFP_KERNEL);
|
||||
sb->s_fs_info = fsi;
|
||||
if (!fsi) {
|
||||
err = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
if (!fsi)
|
||||
return -ENOMEM;
|
||||
|
||||
err = ramfs_parse_options(data, &fsi->mount_opts);
|
||||
if (err)
|
||||
goto fail;
|
||||
return err;
|
||||
|
||||
sb->s_maxbytes = MAX_LFS_FILESIZE;
|
||||
sb->s_blocksize = PAGE_CACHE_SIZE;
|
||||
@@ -234,24 +231,11 @@ int ramfs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
sb->s_time_gran = 1;
|
||||
|
||||
inode = ramfs_get_inode(sb, NULL, S_IFDIR | fsi->mount_opts.mode, 0);
|
||||
if (!inode) {
|
||||
err = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
root = d_alloc_root(inode);
|
||||
sb->s_root = root;
|
||||
if (!root) {
|
||||
err = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
sb->s_root = d_make_root(inode);
|
||||
if (!sb->s_root)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
kfree(fsi);
|
||||
sb->s_fs_info = NULL;
|
||||
iput(inode);
|
||||
return err;
|
||||
}
|
||||
|
||||
struct dentry *ramfs_mount(struct file_system_type *fs_type,
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/posix_acl.h>
|
||||
|
||||
#define REISERFS_ACL_VERSION 0x0001
|
||||
|
||||
typedef struct {
|
||||
__le16 e_tag;
|
||||
__le16 e_perm;
|
||||
__le32 e_id;
|
||||
} reiserfs_acl_entry;
|
||||
|
||||
typedef struct {
|
||||
__le16 e_tag;
|
||||
__le16 e_perm;
|
||||
} reiserfs_acl_entry_short;
|
||||
|
||||
typedef struct {
|
||||
__le32 a_version;
|
||||
} reiserfs_acl_header;
|
||||
|
||||
static inline size_t reiserfs_acl_size(int count)
|
||||
{
|
||||
if (count <= 4) {
|
||||
return sizeof(reiserfs_acl_header) +
|
||||
count * sizeof(reiserfs_acl_entry_short);
|
||||
} else {
|
||||
return sizeof(reiserfs_acl_header) +
|
||||
4 * sizeof(reiserfs_acl_entry_short) +
|
||||
(count - 4) * sizeof(reiserfs_acl_entry);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int reiserfs_acl_count(size_t size)
|
||||
{
|
||||
ssize_t s;
|
||||
size -= sizeof(reiserfs_acl_header);
|
||||
s = size - 4 * sizeof(reiserfs_acl_entry_short);
|
||||
if (s < 0) {
|
||||
if (size % sizeof(reiserfs_acl_entry_short))
|
||||
return -1;
|
||||
return size / sizeof(reiserfs_acl_entry_short);
|
||||
} else {
|
||||
if (s % sizeof(reiserfs_acl_entry))
|
||||
return -1;
|
||||
return s / sizeof(reiserfs_acl_entry) + 4;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_REISERFS_FS_POSIX_ACL
|
||||
struct posix_acl *reiserfs_get_acl(struct inode *inode, int type);
|
||||
int reiserfs_acl_chmod(struct inode *inode);
|
||||
int reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th,
|
||||
struct inode *dir, struct dentry *dentry,
|
||||
struct inode *inode);
|
||||
int reiserfs_cache_default_acl(struct inode *dir);
|
||||
extern const struct xattr_handler reiserfs_posix_acl_default_handler;
|
||||
extern const struct xattr_handler reiserfs_posix_acl_access_handler;
|
||||
|
||||
#else
|
||||
|
||||
#define reiserfs_cache_default_acl(inode) 0
|
||||
#define reiserfs_get_acl NULL
|
||||
|
||||
static inline int reiserfs_acl_chmod(struct inode *inode)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th,
|
||||
const struct inode *dir, struct dentry *dentry,
|
||||
struct inode *inode)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user