diff options
author | Andy Whitcroft <apw@canonical.com> | 2012-08-03 14:29:05 +0100 |
---|---|---|
committer | John Rigby <john.rigby@linaro.org> | 2012-08-15 23:46:21 -0600 |
commit | 2850de53215f0cd5874827bbdc69e57c8d9f1359 (patch) | |
tree | f2f907827ad8e99e713eb4ee0713fc4320c752c1 | |
parent | b8302b32f59d9168fc6d51a1cda5c746da6a48d6 (diff) |
UBUNTU: ubuntu: AUFS -- update to 4a5e660ed7f5c1d0467c81c535d0fedcfe62d15f
Daniel Alder (4):
Bugfix: au_add_till_max wrongly detects overflow if b==0
New function: au_add_muldiv_till_max
Bugfix: au_statfs_sum calculates wrong sums when different block sizes are used
aufs: au_statfs_sum calculates wrong sums when different block sizes are in use
J. R. Okajima (53):
make aufs-version 3.x
aufs3.x-rcN 20120109
aufs: tiny for 3.3, umode_t
aufs: tiny for 3.3, arg fo show_options()
aufs: for 3.3, support for set_nlink()
aufs: tiny for 3.3, arg for iterate_mounts()
aufs3.x-rcN 20120116
aufs: tiny for 3.3, arg of ->migratepage()
aufs3.x-rcN 20120123
aufs: tiny, wrap around some long lines
aufs3.x-rcN 20120130
aufs: for 3.3, follow the changes in mainline, name_hash in lookup_one_len()
aufs: refine document
aufs: special handling kmem_cache for HNOTIFY
aufs: for 2.6.36, support for async free of fsnotify mark
aufs: possible bugfix in rename(2)
aufs3.x-rcN 20120312
version 3.3
Revert "version 3.3"
aufs: follow the changes in mainline, remove vfsub_set_nlink()
aufs: statfs, support various bsize
aufs3.x-rcN 20120326
aufs: update the donator
aufs: simply follow the changes for 3.4-rcN
aufs3.x-rcN 20120402
aufs: tiny for linux-3.4-rc1
aufs3.x-rcN 20120409
aufs3.x-rcN 20120430
version 3.4
Revert "version 3.4"
aufs3.x-rcN 20120521
aufs: for 3.5-rcN, QSTR_INIT()
aufs3.x-rcN 20120528
aufs: for 3.5-rcN, remove ->trucate_range()
aufs: for 3.5-rcN, implement ->update_time()
aufs: for 3.5-rcN, ->encode_fh()
aufs: for 3.5-rcN, k[ug]id_t
aufs: for 3.5-rcN, two VFS locks
aufs: for 3.5-rcN, security_mmap_file()
aufs: tiny, replace pr_warning() by pr_warn()
aufs: cosmetics for aufs_mmap()
aufs3.x-rcN 20120611
aufs: for 3.5-rcN, new au_security_file_mmap() 1/2
aufs: for 3.5-rcN, call au_security_file_mmap() 2/2
aufs3.x-rcN 20120618
Revert "aufs: for 3.5-rcN, call au_security_file_mmap() 2/2"
Revert "aufs: for 3.5-rcN, new au_security_file_mmap() 1/2"
Revert "aufs: cosmetics for aufs_mmap()"
update the donators
aufs: aufs_mmap() calls security_mmap_file() directly
version 3.5
aufs: bugfix, set iinfo lockdep class in the initialization
aufs3.5 20120730
Justin (1):
Parallel make patch
Signed-off-by: Andy Whitcroft <apw@canonical.com>
34 files changed, 299 insertions, 209 deletions
diff --git a/ubuntu/aufs/BOM b/ubuntu/aufs/BOM index f549f2e3ea1..8b07eecafe0 100644 --- a/ubuntu/aufs/BOM +++ b/ubuntu/aufs/BOM @@ -1,3 +1,3 @@ URL: git://aufs.git.sourceforge.net/gitroot/aufs/aufs3-standalone.git CHANGELOG: -COMMIT: d266b0c5d0693d6383976ee54b9e2c0fa9a3f5b0 +COMMIT: 4a5e660ed7f5c1d0467c81c535d0fedcfe62d15f diff --git a/ubuntu/aufs/branch.c b/ubuntu/aufs/branch.c index 4cfe9e28e2a..1dff345876a 100644 --- a/ubuntu/aufs/branch.c +++ b/ubuntu/aufs/branch.c @@ -251,14 +251,14 @@ static int test_add(struct super_block *sb, struct au_opt_add *add, int remount) if (au_opt_test(au_mntflags(sb), WARN_PERM)) { h_inode = au_h_dptr(root, 0)->d_inode; if ((h_inode->i_mode & S_IALLUGO) != (inode->i_mode & S_IALLUGO) - || h_inode->i_uid != inode->i_uid - || h_inode->i_gid != inode->i_gid) - pr_warning("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n", - add->pathname, - inode->i_uid, inode->i_gid, - (inode->i_mode & S_IALLUGO), - h_inode->i_uid, h_inode->i_gid, - (h_inode->i_mode & S_IALLUGO)); + || !uid_eq(h_inode->i_uid, inode->i_uid) + || !gid_eq(h_inode->i_gid, inode->i_gid)) + pr_warn("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n", + add->pathname, + i_uid_read(inode), i_gid_read(inode), + (inode->i_mode & S_IALLUGO), + i_uid_read(h_inode), i_gid_read(h_inode), + (h_inode->i_mode & S_IALLUGO)); } out: @@ -853,8 +853,8 @@ out_wh: /* revert */ rerr = au_br_init_wh(sb, br, br->br_perm, del->h_path.dentry); if (rerr) - pr_warning("failed re-creating base whiteout, %s. (%d)\n", - del->pathname, rerr); + pr_warn("failed re-creating base whiteout, %s. (%d)\n", + del->pathname, rerr); out: return err; } @@ -965,7 +965,7 @@ static unsigned long long au_farray_cb(void *a, n = 0; p = a; - lg_global_lock(files_lglock); + lg_global_lock(&files_lglock); do_file_list_for_each_entry(sb, f) { if (au_fi(f) && file_count(f) @@ -976,7 +976,7 @@ static unsigned long long au_farray_cb(void *a, AuDebugOn(n > max); } } while_file_list_for_each_entry; - lg_global_unlock(files_lglock); + lg_global_unlock(&files_lglock); return n; } diff --git a/ubuntu/aufs/cpup.c b/ubuntu/aufs/cpup.c index 7bf2672a9cb..4e77c7f36b2 100644 --- a/ubuntu/aufs/cpup.c +++ b/ubuntu/aufs/cpup.c @@ -58,6 +58,11 @@ void au_cpup_attr_nlink(struct inode *inode, int force) && au_plink_test(inode)) return; + /* + * 0 can happen in revalidating. + * h_inode->i_mutex is not held, but it is harmless since once i_nlink + * reaches 0, it will never become positive. + */ set_nlink(inode, h_inode->i_nlink); /* @@ -139,7 +144,7 @@ void au_dtime_revert(struct au_dtime *dt) err = vfsub_notify_change(&dt->dt_h_path, &attr); if (unlikely(err)) - pr_warning("restoring timestamps failed(%d). ignored\n", err); + pr_warn("restoring timestamps failed(%d). ignored\n", err); } /* ---------------------------------------------------------------------- */ diff --git a/ubuntu/aufs/debug.c b/ubuntu/aufs/debug.c index 9c9091d290a..a3c710ef32c 100644 --- a/ubuntu/aufs/debug.c +++ b/ubuntu/aufs/debug.c @@ -478,7 +478,7 @@ int __init au_debug_init(void) AuDebugOn(destr.len < NAME_MAX); #ifdef CONFIG_4KSTACKS - pr_warning("CONFIG_4KSTACKS is defined.\n"); + pr_warn("CONFIG_4KSTACKS is defined.\n"); #endif #ifdef AuForceNoBrs diff --git a/ubuntu/aufs/debug.h b/ubuntu/aufs/debug.h index c4d5610a7f5..0fa01694871 100644 --- a/ubuntu/aufs/debug.h +++ b/ubuntu/aufs/debug.h @@ -25,7 +25,6 @@ #ifdef __KERNEL__ -#include <asm/system.h> #include <linux/module.h> #include <linux/kallsyms.h> #include <linux/sysrq.h> @@ -64,7 +63,7 @@ AuStubInt0(au_debug_test, void) #define AuWarn1(fmt, ...) do { \ static unsigned char _c; \ if (!_c++) \ - pr_warning(fmt, ##__VA_ARGS__); \ + pr_warn(fmt, ##__VA_ARGS__); \ } while (0) #define AuErr1(fmt, ...) do { \ diff --git a/ubuntu/aufs/dentry.c b/ubuntu/aufs/dentry.c index 11ed8c25faf..a79e5d218ac 100644 --- a/ubuntu/aufs/dentry.c +++ b/ubuntu/aufs/dentry.c @@ -346,8 +346,8 @@ out: struct au_iattr { unsigned long i_ino; /* unsigned int i_nlink; */ - uid_t i_uid; - gid_t i_gid; + kuid_t i_uid; + kgid_t i_gid; u64 i_version; /* loff_t i_size; @@ -374,8 +374,8 @@ static int au_iattr_test(struct au_iattr *ia, struct inode *h_inode) { return ia->i_ino != h_inode->i_ino /* || ia->i_nlink != h_inode->i_nlink */ - || ia->i_uid != h_inode->i_uid - || ia->i_gid != h_inode->i_gid + || !uid_eq(ia->i_uid, h_inode->i_uid) + || !uid_eq(ia->i_gid, h_inode->i_gid) || ia->i_version != h_inode->i_version /* || ia->i_size != h_inode->i_size diff --git a/ubuntu/aufs/dir.c b/ubuntu/aufs/dir.c index ec5a236b46d..061e670a7c5 100644 --- a/ubuntu/aufs/dir.c +++ b/ubuntu/aufs/dir.c @@ -33,6 +33,7 @@ void au_add_nlink(struct inode *dir, struct inode *h_dir) nlink += h_dir->i_nlink - 2; if (h_dir->i_nlink < 2) nlink += 2; + /* 0 can happen in revaliding */ set_nlink(dir, nlink); } @@ -46,6 +47,7 @@ void au_sub_nlink(struct inode *dir, struct inode *h_dir) nlink -= h_dir->i_nlink - 2; if (h_dir->i_nlink < 2) nlink -= 2; + /* nlink == 0 means the branch-fs is broken */ set_nlink(dir, nlink); } diff --git a/ubuntu/aufs/export.c b/ubuntu/aufs/export.c index 962d8e04f9e..9c827fdea73 100644 --- a/ubuntu/aufs/export.c +++ b/ubuntu/aufs/export.c @@ -21,11 +21,12 @@ */ #include <linux/exportfs.h> -#include <linux/mnt_namespace.h> +#include <linux/fs_struct.h> #include <linux/namei.h> #include <linux/nsproxy.h> #include <linux/random.h> #include <linux/writeback.h> +#include "../fs/mount.h" #include "aufs.h" union conv { @@ -279,18 +280,16 @@ static int au_compare_mnt(struct vfsmount *mnt, void *arg) static struct vfsmount *au_mnt_get(struct super_block *sb) { int err; + struct path root; struct au_compare_mnt_args args = { .sb = sb }; - struct mnt_namespace *ns; - - br_read_lock(vfsmount_lock); - /* no get/put ?? */ - AuDebugOn(!current->nsproxy); - ns = current->nsproxy->mnt_ns; - AuDebugOn(!ns); - err = iterate_mounts(au_compare_mnt, &args, ns->root); - br_read_unlock(vfsmount_lock); + + get_fs_root(current->fs, &root); + br_read_lock(&vfsmount_lock); + err = iterate_mounts(au_compare_mnt, &args, root.mnt); + br_read_unlock(&vfsmount_lock); + path_put(&root); AuDebugOn(!err); AuDebugOn(!args.mnt); return args.mnt; @@ -657,19 +656,16 @@ out: /* ---------------------------------------------------------------------- */ -static int aufs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len, - int connectable) +static int aufs_encode_fh(struct inode *inode, __u32 *fh, int *max_len, + struct inode *dir) { int err; - aufs_bindex_t bindex, bend; + aufs_bindex_t bindex; struct super_block *sb, *h_sb; - struct inode *inode; - struct dentry *parent, *h_parent; + struct dentry *dentry, *parent, *h_parent; + struct inode *h_dir; struct au_branch *br; - AuDebugOn(au_test_anon(dentry)); - - parent = NULL; err = -ENOSPC; if (unlikely(*max_len <= Fh_tail)) { AuWarn1("NFSv2 client (max_len %d)?\n", *max_len); @@ -677,49 +673,58 @@ static int aufs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len, } err = FILEID_ROOT; - if (IS_ROOT(dentry)) { - AuDebugOn(dentry->d_inode->i_ino != AUFS_ROOT_INO); + if (inode->i_ino == AUFS_ROOT_INO) { + AuDebugOn(inode->i_ino != AUFS_ROOT_INO); goto out; } h_parent = NULL; - err = aufs_read_lock(dentry, AuLock_FLUSH | AuLock_IR | AuLock_GEN); + sb = inode->i_sb; + err = si_read_lock(sb, AuLock_FLUSH); if (unlikely(err)) goto out; - inode = dentry->d_inode; - AuDebugOn(!inode); - sb = dentry->d_sb; #ifdef CONFIG_AUFS_DEBUG if (unlikely(!au_opt_test(au_mntflags(sb), XINO))) AuWarn1("NFS-exporting requires xino\n"); #endif err = -EIO; - parent = dget_parent(dentry); - di_read_lock_parent(parent, !AuLock_IR); - bend = au_dbtaildir(parent); - for (bindex = au_dbstart(parent); bindex <= bend; bindex++) { - h_parent = au_h_dptr(parent, bindex); - if (h_parent) { - dget(h_parent); - break; - } + parent = NULL; + ii_read_lock_child(inode); + bindex = au_ibstart(inode); + if (!dir) { + dentry = d_find_alias(inode); + if (unlikely(!dentry)) + goto out_unlock; + AuDebugOn(au_test_anon(dentry)); + parent = dget_parent(dentry); + dput(dentry); + if (unlikely(!parent)) + goto out_unlock; + dir = parent->d_inode; } + + ii_read_lock_parent(dir); + h_dir = au_h_iptr(dir, bindex); + ii_read_unlock(dir); + if (unlikely(!h_dir)) + goto out_parent; + h_parent = d_find_alias(h_dir); if (unlikely(!h_parent)) - goto out_unlock; + goto out_hparent; err = -EPERM; br = au_sbr(sb, bindex); h_sb = br->br_mnt->mnt_sb; if (unlikely(!h_sb->s_export_op)) { AuErr1("%s branch is not exportable\n", au_sbtype(h_sb)); - goto out_dput; + goto out_hparent; } fh[Fh_br_id] = br->br_id; fh[Fh_sigen] = au_sigen(sb); encode_ino(fh + Fh_ino, inode->i_ino); - encode_ino(fh + Fh_dir_ino, parent->d_inode->i_ino); + encode_ino(fh + Fh_dir_ino, dir->i_ino); fh[Fh_igen] = inode->i_generation; *max_len -= Fh_tail; @@ -734,12 +739,13 @@ static int aufs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len, else AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb)); -out_dput: +out_hparent: dput(h_parent); -out_unlock: - di_read_unlock(parent, !AuLock_IR); +out_parent: dput(parent); - aufs_read_unlock(dentry, AuLock_IR); +out_unlock: + ii_read_unlock(inode); + si_read_unlock(sb); out: if (unlikely(err < 0)) err = 255; diff --git a/ubuntu/aufs/f_op.c b/ubuntu/aufs/f_op.c index 942e71a7781..9abe7662daa 100644 --- a/ubuntu/aufs/f_op.c +++ b/ubuntu/aufs/f_op.c @@ -483,7 +483,6 @@ static unsigned long au_flag_conv(unsigned long flags) static int aufs_mmap(struct file *file, struct vm_area_struct *vma) { int err; - unsigned long prot; aufs_bindex_t bstart; const unsigned char wlock = (file->f_mode & FMODE_WRITE) && (vma->vm_flags & VM_SHARED); @@ -523,9 +522,8 @@ static int aufs_mmap(struct file *file, struct vm_area_struct *vma) lockdep_on(); au_vm_file_reset(vma, h_file); - prot = au_prot_conv(vma->vm_flags); - err = security_file_mmap(h_file, /*reqprot*/prot, prot, - au_flag_conv(vma->vm_flags), vma->vm_start, 0); + err = security_mmap_file(h_file, au_prot_conv(vma->vm_flags), + au_flag_conv(vma->vm_flags)); if (!err) err = h_file->f_op->mmap(h_file, vma); if (unlikely(err)) diff --git a/ubuntu/aufs/f_op_sp.c b/ubuntu/aufs/f_op_sp.c index 48b8aa18af2..ad8cf9621d8 100644 --- a/ubuntu/aufs/f_op_sp.c +++ b/ubuntu/aufs/f_op_sp.c @@ -74,9 +74,6 @@ static ssize_t aufs_aio_write_sp(struct kiocb *kio, const struct iovec *iov, /* do not change the file in kio */ AuDebugOn(!h_file->f_op || !h_file->f_op->aio_write); err = h_file->f_op->aio_write(kio, iov, nv, pos); - if (err > 0 && wbr) - file_update_time(h_file); - return err; } diff --git a/ubuntu/aufs/file.c b/ubuntu/aufs/file.c index 0b9aa487f01..bc46544daea 100644 --- a/ubuntu/aufs/file.c +++ b/ubuntu/aufs/file.c @@ -20,6 +20,9 @@ * handling file/dir, and address_space operation */ +#ifdef CONFIG_AUFS_DEBUG +#include <linux/migrate.h> +#endif #include <linux/pagemap.h> #include "aufs.h" @@ -638,7 +641,7 @@ static void aufs_invalidatepage(struct page *page, unsigned long offset) static int aufs_releasepage(struct page *page, gfp_t gfp) { AuUnsupport(); return 0; } static int aufs_migratepage(struct address_space *mapping, struct page *newpage, - struct page *page) + struct page *page, enum migrate_mode mode) { AuUnsupport(); return 0; } static int aufs_launder_page(struct page *page) { AuUnsupport(); return 0; } diff --git a/ubuntu/aufs/file.h b/ubuntu/aufs/file.h index 8bd6e3bab1a..af51fe1dfaf 100644 --- a/ubuntu/aufs/file.h +++ b/ubuntu/aufs/file.h @@ -227,7 +227,7 @@ static inline void au_set_mmapped(struct file *f) { if (atomic_inc_return(&au_fi(f)->fi_mmapped)) return; - pr_warning("fi_mmapped wrapped around\n"); + pr_warn("fi_mmapped wrapped around\n"); while (!atomic_inc_return(&au_fi(f)->fi_mmapped)) ; } diff --git a/ubuntu/aufs/hfsnotify.c b/ubuntu/aufs/hfsnotify.c index c48c315ac3e..bad303f3c59 100644 --- a/ubuntu/aufs/hfsnotify.c +++ b/ubuntu/aufs/hfsnotify.c @@ -26,15 +26,17 @@ static const __u32 AuHfsnMask = (FS_MOVED_TO | FS_MOVED_FROM | FS_DELETE | FS_CREATE | FS_EVENT_ON_CHILD); static DECLARE_WAIT_QUEUE_HEAD(au_hfsn_wq); +static __cacheline_aligned_in_smp atomic64_t au_hfsn_ifree = ATOMIC64_INIT(0); static void au_hfsn_free_mark(struct fsnotify_mark *mark) { struct au_hnotify *hn = container_of(mark, struct au_hnotify, hn_mark); AuDbg("here\n"); - hn->hn_mark_dead = 1; - smp_mb(); - wake_up_all(&au_hfsn_wq); + au_cache_free_hnotify(hn); + smp_mb__before_atomic_dec(); + atomic64_dec(&au_hfsn_ifree); + wake_up(&au_hfsn_wq); } static int au_hfsn_alloc(struct au_hinode *hinode) @@ -49,7 +51,6 @@ static int au_hfsn_alloc(struct au_hinode *hinode) sb = hn->hn_aufs_inode->i_sb; bindex = au_br_index(sb, hinode->hi_id); br = au_sbr(sb, bindex); - hn->hn_mark_dead = 0; mark = &hn->hn_mark; fsnotify_init_mark(mark, au_hfsn_free_mark); mark->mask = AuHfsnMask; @@ -61,18 +62,20 @@ static int au_hfsn_alloc(struct au_hinode *hinode) /*mnt*/NULL, /*allow_dups*/1); } -static void au_hfsn_free(struct au_hinode *hinode) +static int au_hfsn_free(struct au_hinode *hinode, struct au_hnotify *hn) { - struct au_hnotify *hn; struct fsnotify_mark *mark; + unsigned long long ull; + + ull = atomic64_inc_return(&au_hfsn_ifree); + BUG_ON(!ull); - hn = hinode->hi_notify; mark = &hn->hn_mark; fsnotify_destroy_mark(mark); fsnotify_put_mark(mark); - /* TODO: bad approach */ - wait_event(au_hfsn_wq, hn->hn_mark_dead); + /* free hn by myself */ + return 0; } /* ---------------------------------------------------------------------- */ @@ -140,10 +143,7 @@ static int au_hfsn_handle_event(struct fsnotify_group *group, struct au_hnotify *hnotify; struct inode *h_dir, *h_inode; __u32 mask; - struct qstr h_child_qstr = { - .name = event->file_name, - .len = event->name_len - }; + struct qstr h_child_qstr = QSTR_INIT(event->file_name, event->name_len); AuDebugOn(event->data_type != FSNOTIFY_EVENT_INODE); @@ -236,11 +236,21 @@ out: return err; } +/* ---------------------------------------------------------------------- */ + +static void au_hfsn_fin(void) +{ + AuDbg("au_hfsn_ifree %lld\n", (long long)atomic64_read(&au_hfsn_ifree)); + wait_event(au_hfsn_wq, !atomic64_read(&au_hfsn_ifree)); +} + const struct au_hnotify_op au_hnotify_op = { .ctl = au_hfsn_ctl, .alloc = au_hfsn_alloc, .free = au_hfsn_free, + .fin = au_hfsn_fin, + .reset_br = au_hfsn_reset_br, .fin_br = au_hfsn_fin_br, .init_br = au_hfsn_init_br diff --git a/ubuntu/aufs/hnotify.c b/ubuntu/aufs/hnotify.c index 251588c4c8e..647e01de644 100644 --- a/ubuntu/aufs/hnotify.c +++ b/ubuntu/aufs/hnotify.c @@ -58,9 +58,9 @@ void au_hn_free(struct au_hinode *hinode) hn = hinode->hi_notify; if (hn) { - au_hnotify_op.free(hinode); - au_cache_free_hnotify(hn); hinode->hi_notify = NULL; + if (au_hnotify_op.free(hinode, hn)) + au_cache_free_hnotify(hn); } } @@ -108,7 +108,7 @@ static int hn_xino(struct inode *inode, struct inode *h_inode) err = 0; if (unlikely(inode->i_ino == AUFS_ROOT_INO)) { - pr_warning("branch root dir was changed\n"); + pr_warn("branch root dir was changed\n"); goto out; } @@ -203,7 +203,7 @@ static int hn_gen_by_inode(char *name, unsigned int nlen, struct inode *inode, err = 1; if (unlikely(inode->i_ino == AUFS_ROOT_INO)) { - pr_warning("branch root dir was changed\n"); + pr_warn("branch root dir was changed\n"); err = 0; goto out; } @@ -259,7 +259,7 @@ static int hn_gen_by_name(struct dentry *dentry, const unsigned int isdir) if (IS_ROOT(dentry) /* || (inode && inode->i_ino == AUFS_ROOT_INO) */ ) { - pr_warning("branch root dir was changed\n"); + pr_warn("branch root dir was changed\n"); return 0; } @@ -358,8 +358,8 @@ static int hn_job(struct hn_job_args *a) if (au_ftest_hnjob(a->flags, MNTPNT) && a->dentry && d_mountpoint(a->dentry)) - pr_warning("mount-point %.*s is removed or renamed\n", - AuDLNPair(a->dentry)); + pr_warn("mount-point %.*s is removed or renamed\n", + AuDLNPair(a->dentry)); return 0; } @@ -421,7 +421,7 @@ static struct inode *lookup_wlock_by_ino(struct super_block *sb, goto out; if (unlikely(inode->i_ino == AUFS_ROOT_INO)) { - pr_warning("wrong root branch\n"); + pr_warn("wrong root branch\n"); iput(inode); inode = NULL; goto out; diff --git a/ubuntu/aufs/i_op.c b/ubuntu/aufs/i_op.c index ec50afd99ef..0ec0b52f1f7 100644 --- a/ubuntu/aufs/i_op.c +++ b/ubuntu/aufs/i_op.c @@ -22,6 +22,7 @@ #include <linux/device_cgroup.h> #include <linux/fs_stack.h> +#include <linux/mm.h> #include <linux/namei.h> #include <linux/security.h> #include "aufs.h" @@ -205,18 +206,13 @@ static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry, ret = d_splice_alias(inode, dentry); if (unlikely(IS_ERR(ret) && inode)) { ii_write_unlock(inode); - lc_idx = AuLcNonDir_IIINFO; - if (S_ISLNK(inode->i_mode)) - lc_idx = AuLcSymlink_IIINFO; - else if (S_ISDIR(inode->i_mode)) - lc_idx = AuLcDir_IIINFO; - au_rw_class(&au_ii(inode)->ii_rwsem, au_lc_key + lc_idx); iput(inode); + inode = NULL; } out_unlock: di_write_unlock(dentry); - if (unlikely(IS_ERR(ret) && inode)) { + if (inode) { lc_idx = AuLcNonDir_DIINFO; if (S_ISLNK(inode->i_mode)) lc_idx = AuLcSymlink_DIINFO; @@ -702,7 +698,8 @@ static int aufs_setattr(struct dentry *dentry, struct iattr *ia) goto out_unlock; } else if ((ia->ia_valid & (ATTR_UID | ATTR_GID)) && (ia->ia_valid & ATTR_CTIME)) { - err = security_path_chown(&a->h_path, ia->ia_uid, ia->ia_gid); + err = security_path_chown(&a->h_path, vfsub_ia_uid(ia), + vfsub_ia_gid(ia)); if (unlikely(err)) goto out_unlock; } @@ -752,8 +749,8 @@ static void au_refresh_iattr(struct inode *inode, struct kstat *st, unsigned int n; inode->i_mode = st->mode; - inode->i_uid = st->uid; - inode->i_gid = st->gid; + i_uid_write(inode, st->uid); + i_gid_write(inode, st->gid); inode->i_atime = st->atime; inode->i_mtime = st->mtime; inode->i_ctime = st->ctime; @@ -763,6 +760,7 @@ static void au_refresh_iattr(struct inode *inode, struct kstat *st, n = inode->i_nlink; n -= nlink; n += st->nlink; + /* 0 can happen */ set_nlink(inode, n); } @@ -949,11 +947,25 @@ static void aufs_put_link(struct dentry *dentry __maybe_unused, /* ---------------------------------------------------------------------- */ -static void aufs_truncate_range(struct inode *inode __maybe_unused, - loff_t start __maybe_unused, - loff_t end __maybe_unused) +static int aufs_update_time(struct inode *inode, struct timespec *ts, int flags) { - AuUnsupport(); + int err; + struct super_block *sb; + struct inode *h_inode; + + sb = inode->i_sb; + /* mmap_sem might be acquired already, cf. aufs_mmap() */ + lockdep_off(); + si_read_lock(sb, AuLock_FLUSH); + ii_write_lock_child(inode); + lockdep_on(); + h_inode = au_h_iptr(inode, au_ibstart(inode)); + err = vfsub_update_time(h_inode, ts, flags); + lockdep_off(); + ii_write_unlock(inode); + si_read_unlock(sb); + lockdep_on(); + return err; } /* ---------------------------------------------------------------------- */ @@ -962,9 +974,12 @@ struct inode_operations aufs_symlink_iop = { .permission = aufs_permission, .setattr = aufs_setattr, .getattr = aufs_getattr, + .readlink = aufs_readlink, .follow_link = aufs_follow_link, - .put_link = aufs_put_link + .put_link = aufs_put_link, + + /* .update_time = aufs_update_time */ }; struct inode_operations aufs_dir_iop = { @@ -980,12 +995,15 @@ struct inode_operations aufs_dir_iop = { .permission = aufs_permission, .setattr = aufs_setattr, - .getattr = aufs_getattr + .getattr = aufs_getattr, + + .update_time = aufs_update_time }; struct inode_operations aufs_iop = { .permission = aufs_permission, .setattr = aufs_setattr, .getattr = aufs_getattr, - .truncate_range = aufs_truncate_range + + .update_time = aufs_update_time }; diff --git a/ubuntu/aufs/i_op_add.c b/ubuntu/aufs/i_op_add.c index c5255c6a7b9..2659914cd21 100644 --- a/ubuntu/aufs/i_op_add.c +++ b/ubuntu/aufs/i_op_add.c @@ -215,14 +215,14 @@ struct simple_arg { int type; union { struct { - int mode; + umode_t mode; struct nameidata *nd; } c; struct { const char *symname; } s; struct { - int mode; + umode_t mode; dev_t dev; } m; } u; @@ -309,7 +309,8 @@ out: return err; } -int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) +int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, + dev_t dev) { struct simple_arg arg = { .type = Mknod, @@ -330,7 +331,7 @@ int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) return add_simple(dir, dentry, &arg); } -int aufs_create(struct inode *dir, struct dentry *dentry, int mode, +int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode, struct nameidata *nd) { struct simple_arg arg = { @@ -602,7 +603,7 @@ out: return err; } -int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode) +int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) { int err, rerr; aufs_bindex_t bindex; diff --git a/ubuntu/aufs/i_op_ren.c b/ubuntu/aufs/i_op_ren.c index f253bec7efa..9ed38de7614 100644 --- a/ubuntu/aufs/i_op_ren.c +++ b/ubuntu/aufs/i_op_ren.c @@ -254,8 +254,8 @@ static int au_ren_del_whtmp(struct au_ren_args *a) || au_test_fs_remote(a->h_dst->d_sb)) { err = au_whtmp_rmdir(dir, a->btgt, a->h_dst, &a->whlist); if (unlikely(err)) - pr_warning("failed removing whtmp dir %.*s (%d), " - "ignored.\n", AuDLNPair(a->h_dst), err); + pr_warn("failed removing whtmp dir %.*s (%d), " + "ignored.\n", AuDLNPair(a->h_dst), err); } else { au_nhash_wh_free(&a->thargs->whlist); a->thargs->whlist = a->whlist; @@ -907,6 +907,15 @@ int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry, } else if (unlikely(d_unhashed(a->dst_dentry))) goto out_unlock; + /* + * is it possible? + * yes, it happend (in linux-3.3-rcN) but I don't know why. + * there may exist a problem somewhere else. + */ + err = -EINVAL; + if (unlikely(a->dst_parent->d_inode == a->src_dentry->d_inode)) + goto out_unlock; + au_fset_ren(a->flags, ISSAMEDIR); /* temporary */ di_write_lock_parent(a->dst_parent); diff --git a/ubuntu/aufs/inode.c b/ubuntu/aufs/inode.c index df70edee95c..af6a12ac619 100644 --- a/ubuntu/aufs/inode.c +++ b/ubuntu/aufs/inode.c @@ -326,7 +326,7 @@ struct inode *au_new_inode(struct dentry *dentry, int must_new) struct super_block *sb; struct mutex *mtx; ino_t h_ino, ino; - int err; + int err, lc_idx; aufs_bindex_t bstart; sb = dentry->d_sb; @@ -367,6 +367,13 @@ new_ino: AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW)); if (inode->i_state & I_NEW) { + lc_idx = AuLcNonDir_IIINFO; + if (S_ISLNK(h_inode->i_mode)) + lc_idx = AuLcSymlink_IIINFO; + else if (S_ISDIR(h_inode->i_mode)) + lc_idx = AuLcDir_IIINFO; + au_rw_class(&au_ii(inode)->ii_rwsem, au_lc_key + lc_idx); + ii_write_lock_new_child(inode); err = set_inode(inode, dentry); if (!err) { @@ -456,7 +463,7 @@ int au_test_ro(struct super_block *sb, aufs_bindex_t bindex, int au_test_h_perm(struct inode *h_inode, int mask) { - if (!current_fsuid()) + if (current_fsuid() == GLOBAL_ROOT_GID) return 0; return inode_permission(h_inode, mask); } diff --git a/ubuntu/aufs/inode.h b/ubuntu/aufs/inode.h index 1fe58f63253..faf27cd7322 100644 --- a/ubuntu/aufs/inode.h +++ b/ubuntu/aufs/inode.h @@ -35,7 +35,6 @@ struct au_hnotify { #ifdef CONFIG_AUFS_HFSNOTIFY /* never use fsnotify_add_vfsmount_mark() */ struct fsnotify_mark hn_mark; - int hn_mark_dead; #endif struct inode *hn_aufs_inode; /* no get/put */ #endif @@ -158,13 +157,14 @@ void au_unpin(struct au_pin *pin); /* i_op_add.c */ int au_may_add(struct dentry *dentry, aufs_bindex_t bindex, struct dentry *h_parent, int isdir); -int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev); +int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, + dev_t dev); int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname); -int aufs_create(struct inode *dir, struct dentry *dentry, int mode, +int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode, struct nameidata *nd); int aufs_link(struct dentry *src_dentry, struct inode *dir, struct dentry *dentry); -int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode); +int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode); /* i_op_del.c */ int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup); @@ -455,7 +455,13 @@ struct au_branch; struct au_hnotify_op { void (*ctl)(struct au_hinode *hinode, int do_set); int (*alloc)(struct au_hinode *hinode); - void (*free)(struct au_hinode *hinode); + + /* + * if it returns true, the the caller should free hinode->hi_notify, + * otherwise ->free() frees it. + */ + int (*free)(struct au_hinode *hinode, + struct au_hnotify *hn) __must_check; void (*fin)(void); int (*init)(void); diff --git a/ubuntu/aufs/loop.c b/ubuntu/aufs/loop.c index 317f0e46de3..016276a0624 100644 --- a/ubuntu/aufs/loop.c +++ b/ubuntu/aufs/loop.c @@ -107,8 +107,8 @@ void au_warn_loopback(struct super_block *h_sb) pr: spin_unlock(&spin); - pr_warning("you may want to try another patch for loopback file " - "on %s(0x%lx) branch\n", au_sbtype(h_sb), magic); + pr_warn("you may want to try another patch for loopback file " + "on %s(0x%lx) branch\n", au_sbtype(h_sb), magic); } int au_loopback_init(void) diff --git a/ubuntu/aufs/module.c b/ubuntu/aufs/module.c index ef288b86724..498d2c0217b 100644 --- a/ubuntu/aufs/module.c +++ b/ubuntu/aufs/module.c @@ -65,8 +65,9 @@ static void au_cache_fin(void) { int i; - /* including AuCache_HNOTIFY */ - for (i = 0; i < AuCache_Last; i++) + /* excluding AuCache_HNOTIFY */ + BUILD_BUG_ON(AuCache_HNOTIFY + 1 != AuCache_Last); + for (i = 0; i < AuCache_HNOTIFY; i++) if (au_cachep[i]) { kmem_cache_destroy(au_cachep[i]); au_cachep[i] = NULL; diff --git a/ubuntu/aufs/module.h b/ubuntu/aufs/module.h index 242f4ea3e99..fe7dca5a2b0 100644 --- a/ubuntu/aufs/module.h +++ b/ubuntu/aufs/module.h @@ -74,9 +74,7 @@ enum { AuCache_FINFO, AuCache_VDIR, AuCache_DEHSTR, -#ifdef CONFIG_AUFS_HNOTIFY - AuCache_HNOTIFY, -#endif + AuCache_HNOTIFY, /* must be last */ AuCache_Last }; diff --git a/ubuntu/aufs/opts.c b/ubuntu/aufs/opts.c index 35c18ef307e..c79a38d30f5 100644 --- a/ubuntu/aufs/opts.c +++ b/ubuntu/aufs/opts.c @@ -214,7 +214,7 @@ static int br_attr_val(char *str, match_table_t table, substring_t args[]) else { if (p) *p = '+'; - pr_warning("ignored branch attribute %s\n", str); + pr_warn("ignored branch attribute %s\n", str); break; } if (p) @@ -237,7 +237,7 @@ static int noinline_for_stack br_perm_val(char *perm) if (!val) { if (p) *p = '+'; - pr_warning("ignored branch permission %s\n", perm); + pr_warn("ignored branch permission %s\n", perm); val = AuBrPerm_RO; goto out; } @@ -1123,7 +1123,7 @@ int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts) break; case Opt_ignore: - pr_warning("ignored %s\n", opt_str); + pr_warn("ignored %s\n", opt_str); /*FALLTHROUGH*/ case Opt_ignore_silent: skipped = 1; @@ -1459,14 +1459,14 @@ int au_opts_verify(struct super_block *sb, unsigned long sb_flags, if (!(sb_flags & MS_RDONLY)) { if (unlikely(!au_br_writable(au_sbr_perm(sb, 0)))) - pr_warning("first branch should be rw\n"); + pr_warn("first branch should be rw\n"); if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH))) - pr_warning("shwh should be used with ro\n"); + pr_warn("shwh should be used with ro\n"); } if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HNOTIFY) && !au_opt_test(sbinfo->si_mntflags, XINO)) - pr_warning("udba=*notify requires xino\n"); + pr_warn("udba=*notify requires xino\n"); err = 0; root = sb->s_root; diff --git a/ubuntu/aufs/plink.c b/ubuntu/aufs/plink.c index 6338461902b..0d1131b370d 100644 --- a/ubuntu/aufs/plink.c +++ b/ubuntu/aufs/plink.c @@ -228,9 +228,7 @@ struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex) struct inode *h_dir; int wkq_err; char a[PLINK_NAME_LEN]; - struct qstr tgtname = { - .name = a - }; + struct qstr tgtname = QSTR_INIT(a, 0); AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM)); @@ -239,7 +237,7 @@ struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex) h_dir = h_parent->d_inode; tgtname.len = plink_name(a, sizeof(a), inode, bindex); - if (current_fsuid()) { + if (current_fsuid() != GLOBAL_ROOT_GID) { struct au_do_plink_lkup_args args = { .errp = &h_dentry, .tgtname = &tgtname, @@ -316,9 +314,7 @@ static int whplink(struct dentry *h_dentry, struct inode *inode, struct dentry *h_parent; struct inode *h_dir; char a[PLINK_NAME_LEN]; - struct qstr tgtname = { - .name = a - }; + struct qstr tgtname = QSTR_INIT(a, 0); wbr = au_sbr(inode->i_sb, bindex)->br_wbr; h_parent = wbr->wbr_plink; @@ -326,7 +322,7 @@ static int whplink(struct dentry *h_dentry, struct inode *inode, tgtname.len = plink_name(a, sizeof(a), inode, bindex); /* always superio. */ - if (current_fsuid()) { + if (current_fsuid() != GLOBAL_ROOT_GID) { struct do_whplink_args args = { .errp = &err, .tgt = &tgtname, @@ -414,8 +410,8 @@ void au_plink_append(struct inode *inode, aufs_bindex_t bindex, spin_unlock(&sbinfo->si_plink.spin); if (!found) { cnt++; -// WARN_ONCE(cnt > AUFS_PLINK_WARN, -// "unexpectedly many pseudo links, %d\n", cnt); + WARN_ONCE(cnt > AUFS_PLINK_WARN, + "unexpectedly many pseudo links, %d\n", cnt); err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex)); } else { do_put_plink(tmp, 0); @@ -424,7 +420,7 @@ void au_plink_append(struct inode *inode, aufs_bindex_t bindex, out: if (unlikely(err)) { - pr_warning("err %d, damaged pseudo link.\n", err); + pr_warn("err %d, damaged pseudo link.\n", err); if (tmp) { au_spl_del_rcu(&tmp->list, &sbinfo->si_plink); call_rcu(&tmp->rcu, do_put_plink_rcu); diff --git a/ubuntu/aufs/rdu.c b/ubuntu/aufs/rdu.c index 76565037940..24dc7552529 100644 --- a/ubuntu/aufs/rdu.c +++ b/ubuntu/aufs/rdu.c @@ -95,6 +95,7 @@ static int au_rdu_do(struct file *h_file, struct au_rdu_arg *arg) loff_t offset; struct au_rdu_cookie *cookie = &arg->rdu->cookie; + /* we don't have to care (FMODE_32BITHASH | FMODE_64BITHASH) for ext4 */ offset = vfsub_llseek(h_file, cookie->h_pos, SEEK_SET); err = offset; if (unlikely(offset != cookie->h_pos)) diff --git a/ubuntu/aufs/super.c b/ubuntu/aufs/super.c index c798792b74e..53ad4c26f78 100644 --- a/ubuntu/aufs/super.c +++ b/ubuntu/aufs/super.c @@ -163,7 +163,7 @@ static void au_show_wbr_create(struct seq_file *m, int v, } } -static int au_show_xino(struct seq_file *seq, struct vfsmount *mnt) +static int au_show_xino(struct seq_file *seq, struct super_block *sb) { #ifdef CONFIG_SYSFS return 0; @@ -171,7 +171,6 @@ static int au_show_xino(struct seq_file *seq, struct vfsmount *mnt) int err; const int len = sizeof(AUFS_XINO_FNAME) - 1; aufs_bindex_t bindex, brid; - struct super_block *sb; struct qstr *name; struct file *f; struct dentry *d, *h_root; @@ -180,7 +179,6 @@ static int au_show_xino(struct seq_file *seq, struct vfsmount *mnt) AuRwMustAnyLock(&sbinfo->si_rwsem); err = 0; - sb = mnt->mnt_sb; f = au_sbi(sb)->si_xib; if (!f) goto out; @@ -210,7 +208,7 @@ out: } /* seq_file will re-call me in case of too long string */ -static int aufs_show_options(struct seq_file *m, struct vfsmount *mnt) +static int aufs_show_options(struct seq_file *m, struct dentry *dentry) { int err; unsigned int mnt_flags, v; @@ -235,14 +233,14 @@ static int aufs_show_options(struct seq_file *m, struct vfsmount *mnt) } while (0) /* lock free root dinfo */ - sb = mnt->mnt_sb; + sb = dentry->d_sb; si_noflush_read_lock(sb); sbinfo = au_sbi(sb); seq_printf(m, ",si=%lx", sysaufs_si_id(sbinfo)); mnt_flags = au_mntflags(sb); if (au_opt_test(mnt_flags, XINO)) { - err = au_show_xino(m, mnt); + err = au_show_xino(m, sb); if (unlikely(err)) goto out; } else @@ -305,7 +303,18 @@ static u64 au_add_till_max(u64 a, u64 b) old = a; a += b; - if (old < a) + if (old <= a) + return a; + return ULLONG_MAX; +} + +static u64 au_mul_till_max(u64 a, long mul) +{ + u64 old; + + old = a; + a *= mul; + if (old <= a) return a; return ULLONG_MAX; } @@ -313,25 +322,26 @@ static u64 au_add_till_max(u64 a, u64 b) static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf) { int err; + long bsize, factor; u64 blocks, bfree, bavail, files, ffree; aufs_bindex_t bend, bindex, i; unsigned char shared; struct path h_path; struct super_block *h_sb; + err = 0; + bsize = LONG_MAX; + files = 0; + ffree = 0; blocks = 0; bfree = 0; bavail = 0; - files = 0; - ffree = 0; - - err = 0; bend = au_sbend(sb); - for (bindex = bend; bindex >= 0; bindex--) { + for (bindex = 0; bindex <= bend; bindex++) { h_path.mnt = au_sbr_mnt(sb, bindex); h_sb = h_path.mnt->mnt_sb; shared = 0; - for (i = bindex + 1; !shared && i <= bend; i++) + for (i = 0; !shared && i < bindex; i++) shared = (au_sbr_sb(sb, i) == h_sb); if (shared) continue; @@ -342,18 +352,36 @@ static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf) if (unlikely(err)) goto out; - blocks = au_add_till_max(blocks, buf->f_blocks); - bfree = au_add_till_max(bfree, buf->f_bfree); - bavail = au_add_till_max(bavail, buf->f_bavail); + if (bsize > buf->f_bsize) { + /* + * we will reduce bsize, so we have to expand blocks + * etc. to match them again + */ + factor = (bsize / buf->f_bsize); + blocks = au_mul_till_max(blocks, factor); + bfree = au_mul_till_max(bfree, factor); + bavail = au_mul_till_max(bavail, factor); + bsize = buf->f_bsize; + } + + factor = (buf->f_bsize / bsize); + blocks = au_add_till_max(blocks, + au_mul_till_max(buf->f_blocks, factor)); + bfree = au_add_till_max(bfree, + au_mul_till_max(buf->f_bfree, factor)); + bavail = au_add_till_max(bavail, + au_mul_till_max(buf->f_bavail, factor)); files = au_add_till_max(files, buf->f_files); ffree = au_add_till_max(ffree, buf->f_ffree); } + buf->f_bsize = bsize; buf->f_blocks = blocks; buf->f_bfree = bfree; buf->f_bavail = bavail; buf->f_files = files; buf->f_ffree = ffree; + buf->f_frsize = 0; out: return err; @@ -775,12 +803,12 @@ static int alloc_root(struct super_block *sb) set_nlink(inode, 2); unlock_new_inode(inode); - root = d_alloc_root(inode); + root = d_make_root(inode); if (unlikely(!root)) - goto out_iput; + goto out; err = PTR_ERR(root); if (IS_ERR(root)) - goto out_iput; + goto out; err = au_di_init(root); if (!err) { @@ -788,13 +816,9 @@ static int alloc_root(struct super_block *sb) return 0; /* success */ } dput(root); - goto out; /* do not iput */ -out_iput: - iget_failed(inode); out: return err; - } static int aufs_fill_super(struct super_block *sb, void *raw_data, diff --git a/ubuntu/aufs/sysfs.c b/ubuntu/aufs/sysfs.c index f72519dac36..a4e39f1fce1 100644 --- a/ubuntu/aufs/sysfs.c +++ b/ubuntu/aufs/sysfs.c @@ -251,7 +251,7 @@ void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex) "%d", bindex); err = sysfs_create_file(kobj, &br->br_attr); if (unlikely(err)) - pr_warning("failed %s under sysfs(%d)\n", - br->br_name, err); + pr_warn("failed %s under sysfs(%d)\n", + br->br_name, err); } } diff --git a/ubuntu/aufs/sysrq.c b/ubuntu/aufs/sysrq.c index c481d2b6dd5..a447de4913c 100644 --- a/ubuntu/aufs/sysrq.c +++ b/ubuntu/aufs/sysrq.c @@ -84,14 +84,14 @@ static void sysrq_sb(struct super_block *sb) } #endif printk(KERN_WARNING AUFS_NAME ": files\n"); - lg_global_lock(files_lglock); + lg_global_lock(&files_lglock); do_file_list_for_each_entry(sb, file) { umode_t mode; mode = file->f_dentry->d_inode->i_mode; if (!special_file(mode) || au_special_file(mode)) au_dpri_file(file); } while_file_list_for_each_entry; - lg_global_unlock(files_lglock); + lg_global_unlock(&files_lglock); printk(KERN_WARNING AUFS_NAME ": done\n"); au_plevel = plevel; diff --git a/ubuntu/aufs/vfsub.c b/ubuntu/aufs/vfsub.c index 331ab17fb5c..e2897b60bb6 100644 --- a/ubuntu/aufs/vfsub.c +++ b/ubuntu/aufs/vfsub.c @@ -139,22 +139,19 @@ out: */ int vfsub_name_hash(const char *name, struct qstr *this, int len) { - unsigned long hash; unsigned int c; this->name = name; this->len = len; + this->hash = full_name_hash(name, len); if (!len) return -EACCES; - hash = init_name_hash(); while (len--) { c = *(const unsigned char *)name++; if (c == '/' || c == '\0') return -EACCES; - hash = partial_name_hash(c, hash); } - this->hash = end_name_hash(hash); return 0; } diff --git a/ubuntu/aufs/vfsub.h b/ubuntu/aufs/vfsub.h index ce4d5b683eb..6f65e8aa969 100644 --- a/ubuntu/aufs/vfsub.h +++ b/ubuntu/aufs/vfsub.h @@ -31,12 +31,12 @@ /* copied from linux/fs/internal.h */ /* todo: BAD approach!! */ -DECLARE_BRLOCK(vfsmount_lock); +extern struct lglock vfsmount_lock; extern void file_sb_list_del(struct file *f); extern spinlock_t inode_sb_list_lock; /* copied from linux/fs/file_table.c */ -DECLARE_LGLOCK(files_lglock); +extern struct lglock files_lglock; #ifdef CONFIG_SMP /* * These macros iterate all files on all CPUs for a given superblock. @@ -102,6 +102,19 @@ static inline void vfsub_dead_dir(struct inode *inode) /* ---------------------------------------------------------------------- */ +/* cf. i_[ug]id_read() in linux/include/fs.h */ +static inline uid_t vfsub_ia_uid(struct iattr *ia) +{ + return from_kuid(&init_user_ns, ia->ia_uid); +} + +static inline gid_t vfsub_ia_gid(struct iattr *ia) +{ + return from_kgid(&init_user_ns, ia->ia_gid); +} + +/* ---------------------------------------------------------------------- */ + int vfsub_update_h_iattr(struct path *h_path, int *did); struct file *vfsub_dentry_open(struct path *path, int flags); struct file *vfsub_filp_open(const char *path, int oflags, int mode); @@ -167,10 +180,17 @@ static inline void vfsub_touch_atime(struct vfsmount *h_mnt, .dentry = h_dentry, .mnt = h_mnt }; - touch_atime(h_mnt, h_dentry); + touch_atime(&h_path); vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/ } +static inline int vfsub_update_time(struct inode *h_inode, struct timespec *ts, + int flags) +{ + return update_time(h_inode, ts, flags); + /* no vfsub_update_h_iattr() since we don't have struct path */ +} + long vfsub_splice_to(struct file *in, loff_t *ppos, struct pipe_inode_info *pipe, size_t len, unsigned int flags); diff --git a/ubuntu/aufs/whout.c b/ubuntu/aufs/whout.c index 676486362d5..767b332650a 100644 --- a/ubuntu/aufs/whout.c +++ b/ubuntu/aufs/whout.c @@ -28,10 +28,8 @@ * If a directory contains this file, then it is opaque. We start with the * .wh. flag so that it is blocked by lookup. */ -static struct qstr diropq_name = { - .name = AUFS_WH_DIROPQ, - .len = sizeof(AUFS_WH_DIROPQ) - 1 -}; +static struct qstr diropq_name = QSTR_INIT(AUFS_WH_DIROPQ, + sizeof(AUFS_WH_DIROPQ) - 1); /* * generate whiteout name, which is NOT terminated by NULL. @@ -156,7 +154,7 @@ struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br, goto out_name; dput(dentry); } - /* pr_warning("could not get random name\n"); */ + /* pr_warn("could not get random name\n"); */ dentry = ERR_PTR(-EEXIST); AuDbg("%.*s\n", AuLNPair(&qs)); BUG(); @@ -214,7 +212,7 @@ static int do_unlink_wh(struct inode *h_dir, struct path *h_path) * this may be a violation of unix fs semantics. */ force = (h_dir->i_mode & S_ISVTX) - && h_path->dentry->d_inode->i_uid != current_fsuid(); + && !uid_eq(current_fsuid(), h_path->dentry->d_inode->i_uid); return vfsub_unlink(h_dir, h_path, force); } @@ -274,8 +272,8 @@ static void au_wh_clean(struct inode *h_dir, struct path *whpath, mnt_drop_write(whpath->mnt); } if (unlikely(err)) - pr_warning("failed removing %.*s (%d), ignored.\n", - AuDLNPair(whpath->dentry), err); + pr_warn("failed removing %.*s (%d), ignored.\n", + AuDLNPair(whpath->dentry), err); } static int test_linkable(struct dentry *h_root) @@ -448,18 +446,12 @@ int au_wh_init(struct dentry *h_root, struct au_branch *br, struct inode *h_dir; struct au_wbr *wbr = br->br_wbr; static const struct qstr base_name[] = { - [AuBrWh_BASE] = { - .name = AUFS_BASE_NAME, - .len = sizeof(AUFS_BASE_NAME) - 1 - }, - [AuBrWh_PLINK] = { - .name = AUFS_PLINKDIR_NAME, - .len = sizeof(AUFS_PLINKDIR_NAME) - 1 - }, - [AuBrWh_ORPH] = { - .name = AUFS_ORPHDIR_NAME, - .len = sizeof(AUFS_ORPHDIR_NAME) - 1 - } + [AuBrWh_BASE] = QSTR_INIT(AUFS_BASE_NAME, + sizeof(AUFS_BASE_NAME) - 1), + [AuBrWh_PLINK] = QSTR_INIT(AUFS_PLINKDIR_NAME, + sizeof(AUFS_PLINKDIR_NAME) - 1), + [AuBrWh_ORPH] = QSTR_INIT(AUFS_ORPHDIR_NAME, + sizeof(AUFS_ORPHDIR_NAME) - 1) }; struct au_wh_base base[] = { [AuBrWh_BASE] = { @@ -579,8 +571,8 @@ static void reinit_br_wh(void *arg) mnt_drop_write(a->br->br_mnt); } } else { - pr_warning("%.*s is moved, ignored\n", - AuDLNPair(wbr->wbr_whbase)); + pr_warn("%.*s is moved, ignored\n", + AuDLNPair(wbr->wbr_whbase)); err = 0; } dput(wbr->wbr_whbase); @@ -971,8 +963,8 @@ int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex, return 0; /* success */ } - pr_warning("failed removing %.*s(%d), ignored\n", - AuDLNPair(wh_dentry), err); + pr_warn("failed removing %.*s(%d), ignored\n", + AuDLNPair(wh_dentry), err); return err; } @@ -1042,8 +1034,8 @@ void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex, args->wh_dentry = dget(wh_dentry); wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, sb, /*flags*/0); if (unlikely(wkq_err)) { - pr_warning("rmdir error %.*s (%d), ignored\n", - AuDLNPair(wh_dentry), wkq_err); + pr_warn("rmdir error %.*s (%d), ignored\n", + AuDLNPair(wh_dentry), wkq_err); au_whtmp_rmdir_free(args); } } diff --git a/ubuntu/aufs/wkq.c b/ubuntu/aufs/wkq.c index 91c739f476f..49b59d258f4 100644 --- a/ubuntu/aufs/wkq.c +++ b/ubuntu/aufs/wkq.c @@ -46,7 +46,7 @@ static void wkq_func(struct work_struct *wk) { struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk); - AuDebugOn(current_fsuid()); + AuDebugOn(current_fsuid() != GLOBAL_ROOT_GID); AuDebugOn(rlimit(RLIMIT_FSIZE) != RLIM_INFINITY); wkinfo->func(wkinfo->args); diff --git a/ubuntu/aufs/xino.c b/ubuntu/aufs/xino.c index 2285299293e..c25b719ea78 100644 --- a/ubuntu/aufs/xino.c +++ b/ubuntu/aufs/xino.c @@ -316,7 +316,7 @@ static void xino_do_trunc(void *_args) ii_read_unlock(dir); if (unlikely(err)) - pr_warning("err b%d, (%d)\n", bindex, err); + pr_warn("err b%d, (%d)\n", bindex, err); atomic_dec(&br->br_xino_running); atomic_dec(&br->br_count); si_write_unlock(sb); diff --git a/ubuntu/include/linux/aufs_type.h b/ubuntu/include/linux/aufs_type.h index 2f2fbcdbcce..f8de04b4978 100644 --- a/ubuntu/include/linux/aufs_type.h +++ b/ubuntu/include/linux/aufs_type.h @@ -39,7 +39,7 @@ #include <linux/limits.h> -#define AUFS_VERSION "3.2-20120109" +#define AUFS_VERSION "3.5-20120730" /* todo? move this to linux-2.6.19/include/magic.h */ #define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's') |