static int __init aufs_init(void) { int err, i; char *p; p = au_esc_chars; for (i = 1; i <= ' '; i++) *p++ = i; *p++ = '\\'; *p++ = '\x7f'; *p = 0; au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE); au_sbilist_init(); sysaufs_brs_init(); au_debug_init(); au_dy_init(); err = sysaufs_init(); if (unlikely(err)) goto out; err = au_procfs_init(); if (unlikely(err)) goto out_sysaufs; err = au_wkq_init(); if (unlikely(err)) goto out_procfs; err = au_hnotify_init(); if (unlikely(err)) goto out_wkq; err = au_sysrq_init(); if (unlikely(err)) goto out_hin; err = au_cache_init(); if (unlikely(err)) goto out_sysrq; err = register_filesystem(&aufs_fs_type); if (unlikely(err)) goto out_cache; /* since we define pr_fmt, call printk directly */ printk(KERN_INFO AUFS_NAME " " AUFS_VERSION "\n"); goto out; /* success */ out_cache: au_cache_fin(); out_sysrq: au_sysrq_fin(); out_hin: au_hnotify_fin(); out_wkq: au_wkq_fin(); out_procfs: au_procfs_fin(); out_sysaufs: sysaufs_fin(); au_dy_fin(); out: return err; }
/* common functions to regular file and dir */ struct file *hidden_open(struct dentry *dentry, aufs_bindex_t bindex, int flags) { struct dentry *hidden_dentry; struct inode *hidden_inode; struct super_block *sb; struct vfsmount *hidden_mnt; struct file *hidden_file; struct aufs_branch *br; loff_t old_size; int udba; LKTRTrace("%.*s, b%d, flags 0%o\n", DLNPair(dentry), bindex, flags); DEBUG_ON(!dentry); hidden_dentry = au_h_dptr_i(dentry, bindex); DEBUG_ON(!hidden_dentry); hidden_inode = hidden_dentry->d_inode; DEBUG_ON(!hidden_inode); sb = dentry->d_sb; udba = au_flag_test(sb, AuFlag_UDBA_INOTIFY); if (unlikely(udba)) { // test here? } br = stobr(sb, bindex); br_get(br); /* drop flags for writing */ if (test_ro(sb, bindex, dentry->d_inode)) flags = au_file_roflags(flags); flags &= ~O_CREAT; spin_lock(&hidden_inode->i_lock); old_size = i_size_read(hidden_inode); spin_unlock(&hidden_inode->i_lock); //DbgSleep(3); dget(hidden_dentry); hidden_mnt = mntget(br->br_mnt); hidden_file = dentry_open(hidden_dentry, hidden_mnt, flags); //if (LktrCond) {fput(hidden_file); hidden_file = ERR_PTR(-1);} if (!IS_ERR(hidden_file)) { #if 0 // remove this if (/* old_size && */ (flags & O_TRUNC)) { au_direval_dec(dentry); if (!IS_ROOT(dentry)) au_direval_dec(dentry->d_parent); } #endif return hidden_file; } br_put(br); TraceErrPtr(hidden_file); return hidden_file; }
/* common functions to regular file and dir */ struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags, struct file *file) { struct file *h_file; struct dentry *h_dentry; struct inode *h_inode; struct super_block *sb; struct au_branch *br; struct path h_path; int err, exec_flag; /* a race condition can happen between open and unlink/rmdir */ h_file = ERR_PTR(-ENOENT); h_dentry = au_h_dptr(dentry, bindex); if (au_test_nfsd() && !h_dentry) goto out; h_inode = h_dentry->d_inode; if (au_test_nfsd() && !h_inode) goto out; spin_lock(&h_dentry->d_lock); err = (!d_unhashed(dentry) && d_unlinked(h_dentry)) || !h_inode /* || !dentry->d_inode->i_nlink */ ; spin_unlock(&h_dentry->d_lock); if (unlikely(err)) goto out; sb = dentry->d_sb; br = au_sbr(sb, bindex); h_file = ERR_PTR(-EACCES); exec_flag = flags & __FMODE_EXEC; if (exec_flag && (br->br_mnt->mnt_flags & MNT_NOEXEC)) goto out; /* drop flags for writing */ if (au_test_ro(sb, bindex, dentry->d_inode)) flags = au_file_roflags(flags); flags &= ~O_CREAT; atomic_inc(&br->br_count); h_path.dentry = h_dentry; h_path.mnt = br->br_mnt; if (!au_special_file(h_inode->i_mode)) h_file = vfsub_dentry_open(&h_path, flags); else { /* this block depends upon the configuration */ di_read_unlock(dentry, AuLock_IR); fi_write_unlock(file); si_read_unlock(sb); h_file = vfsub_dentry_open(&h_path, flags); si_noflush_read_lock(sb); fi_write_lock(file); di_read_lock_child(dentry, AuLock_IR); } if (IS_ERR(h_file)) goto out_br; if (exec_flag) { err = deny_write_access(h_file); if (unlikely(err)) { fput(h_file); h_file = ERR_PTR(err); goto out_br; } } fsnotify_open(h_file); goto out; /* success */ out_br: atomic_dec(&br->br_count); out: return h_file; }
static int __init aufs_init(void) { int err, i; char *p; au_debug_init(); #ifdef CONFIG_AUFS_INO_T_64 BUILD_BUG_ON(sizeof(ino_t) != sizeof(long long)); #else BUILD_BUG_ON(sizeof(ino_t) != sizeof(int)); #endif p = au_esc_chars; for (i = 1; i <= ' '; i++) *p++ = i; *p++ = '\\'; *p++ = '\x7f'; *p = 0; au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE); err = -EINVAL; if (unlikely(aufs_nwkq <= 0)) goto out; err = sysaufs_init(); if (unlikely(err)) goto out; err = au_wkq_init(); if (unlikely(err)) goto out_sysaufs; err = au_inotify_init(); if (unlikely(err)) goto out_wkq; err = au_sysrq_init(); if (unlikely(err)) goto out_inotify; err = create_cache(); if (unlikely(err)) goto out_sysrq; err = register_filesystem(&aufs_fs_type); if (unlikely(err)) goto out_cache; pr_info(AUFS_NAME " " AUFS_VERSION "\n"); return 0; /* success */ out_cache: destroy_cache(); out_sysrq: au_sysrq_fin(); out_inotify: au_inotify_fin(); out_wkq: au_wkq_fin(); out_sysaufs: sysaufs_fin(); out: AuTraceErr(err); return err; }
/* common functions to regular file and dir */ struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags, struct file *file, int force_wr) { struct file *h_file; struct dentry *h_dentry; struct inode *h_inode; struct super_block *sb; struct au_branch *br; struct path h_path; int err, exec_flag; /* a race condition can happen between open and unlink/rmdir */ h_file = ERR_PTR(-ENOENT); h_dentry = au_h_dptr(dentry, bindex); if (au_test_nfsd() && !h_dentry) goto out; h_inode = h_dentry->d_inode; if (au_test_nfsd() && !h_inode) goto out; spin_lock(&h_dentry->d_lock); err = (!d_unhashed(dentry) && d_unlinked(h_dentry)) || !h_inode /* || !dentry->d_inode->i_nlink */ ; spin_unlock(&h_dentry->d_lock); if (unlikely(err)) goto out; sb = dentry->d_sb; br = au_sbr(sb, bindex); h_file = ERR_PTR(-EACCES); exec_flag = flags & __FMODE_EXEC; if (exec_flag && (au_br_mnt(br)->mnt_flags & MNT_NOEXEC)) goto out; /* drop flags for writing */ if (au_test_ro(sb, bindex, dentry->d_inode)) { if (force_wr && !(flags & O_WRONLY)) force_wr = 0; flags = au_file_roflags(flags); if (force_wr) { h_file = ERR_PTR(-EROFS); flags = au_file_roflags(flags); if (unlikely(vfsub_native_ro(h_inode) || IS_APPEND(h_inode))) goto out; flags &= ~O_ACCMODE; flags |= O_WRONLY; } } flags &= ~O_CREAT; atomic_inc(&br->br_count); h_path.dentry = h_dentry; h_path.mnt = au_br_mnt(br); h_file = vfsub_dentry_open(&h_path, flags); if (IS_ERR(h_file)) goto out_br; if (exec_flag) { err = deny_write_access(h_file); if (unlikely(err)) { fput(h_file); h_file = ERR_PTR(err); goto out_br; } } fsnotify_open(h_file); goto out; /* success */ out_br: atomic_dec(&br->br_count); out: return h_file; }