aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Whitcroft <apw@canonical.com>2012-08-03 14:29:05 +0100
committerJohn Rigby <john.rigby@linaro.org>2012-08-15 23:46:21 -0600
commit2850de53215f0cd5874827bbdc69e57c8d9f1359 (patch)
treef2f907827ad8e99e713eb4ee0713fc4320c752c1
parentb8302b32f59d9168fc6d51a1cda5c746da6a48d6 (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>
-rw-r--r--ubuntu/aufs/BOM2
-rw-r--r--ubuntu/aufs/branch.c24
-rw-r--r--ubuntu/aufs/cpup.c7
-rw-r--r--ubuntu/aufs/debug.c2
-rw-r--r--ubuntu/aufs/debug.h3
-rw-r--r--ubuntu/aufs/dentry.c8
-rw-r--r--ubuntu/aufs/dir.c2
-rw-r--r--ubuntu/aufs/export.c86
-rw-r--r--ubuntu/aufs/f_op.c6
-rw-r--r--ubuntu/aufs/f_op_sp.c3
-rw-r--r--ubuntu/aufs/file.c5
-rw-r--r--ubuntu/aufs/file.h2
-rw-r--r--ubuntu/aufs/hfsnotify.c36
-rw-r--r--ubuntu/aufs/hnotify.c16
-rw-r--r--ubuntu/aufs/i_op.c52
-rw-r--r--ubuntu/aufs/i_op_add.c11
-rw-r--r--ubuntu/aufs/i_op_ren.c13
-rw-r--r--ubuntu/aufs/inode.c11
-rw-r--r--ubuntu/aufs/inode.h16
-rw-r--r--ubuntu/aufs/loop.c4
-rw-r--r--ubuntu/aufs/module.c5
-rw-r--r--ubuntu/aufs/module.h4
-rw-r--r--ubuntu/aufs/opts.c12
-rw-r--r--ubuntu/aufs/plink.c18
-rw-r--r--ubuntu/aufs/rdu.c1
-rw-r--r--ubuntu/aufs/super.c70
-rw-r--r--ubuntu/aufs/sysfs.c4
-rw-r--r--ubuntu/aufs/sysrq.c4
-rw-r--r--ubuntu/aufs/vfsub.c5
-rw-r--r--ubuntu/aufs/vfsub.h26
-rw-r--r--ubuntu/aufs/whout.c44
-rw-r--r--ubuntu/aufs/wkq.c2
-rw-r--r--ubuntu/aufs/xino.c2
-rw-r--r--ubuntu/include/linux/aufs_type.h2
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')