199 lines
4.8 KiB
Diff
199 lines
4.8 KiB
Diff
--- a/fs/aufs/branch.c
|
|
+++ b/fs/aufs/branch.c
|
|
@@ -571,22 +571,25 @@
|
|
{
|
|
unsigned long long n;
|
|
struct file **p, *f;
|
|
+ struct au_sphlhead *files;
|
|
+ struct au_finfo *finfo;
|
|
struct super_block *sb = arg;
|
|
|
|
n = 0;
|
|
p = a;
|
|
- lg_global_lock(&files_lglock);
|
|
- do_file_list_for_each_entry(sb, f) {
|
|
- if (au_fi(f)
|
|
- && file_count(f)
|
|
+ files = &au_sbi(sb)->si_files;
|
|
+ spin_lock(&files->spin);
|
|
+ hlist_for_each_entry(finfo, &files->head, fi_hlist) {
|
|
+ f = finfo->fi_file;
|
|
+ if (file_count(f)
|
|
&& !special_file(file_inode(f)->i_mode)) {
|
|
get_file(f);
|
|
*p++ = f;
|
|
n++;
|
|
AuDebugOn(n > max);
|
|
}
|
|
- } while_file_list_for_each_entry;
|
|
- lg_global_unlock(&files_lglock);
|
|
+ }
|
|
+ spin_unlock(&files->spin);
|
|
|
|
return n;
|
|
}
|
|
@@ -1240,7 +1243,13 @@
|
|
continue;
|
|
|
|
/* todo: already flushed? */
|
|
- /* cf. fs/super.c:mark_files_ro() */
|
|
+ /*
|
|
+ * fs/super.c:mark_files_ro() is gone, but aufs keeps its
|
|
+ * approach which resets f_mode and calls mnt_drop_write() and
|
|
+ * file_release_write() for each file, because the branch
|
|
+ * attribute in aufs world is totally different from the native
|
|
+ * fs rw/ro mode.
|
|
+ */
|
|
/* fi_read_lock(file); */
|
|
hfile = &au_fi(file)->fi_htop;
|
|
hf = hfile->hf_file;
|
|
--- a/fs/aufs/file.h
|
|
+++ b/fs/aufs/file.h
|
|
@@ -61,6 +61,9 @@
|
|
atomic_t fi_mmapped;
|
|
};
|
|
struct au_fidir *fi_hdir; /* for dir only */
|
|
+
|
|
+ struct hlist_node fi_hlist;
|
|
+ struct file *fi_file; /* very ugly */
|
|
} ____cacheline_aligned_in_smp;
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
--- a/fs/aufs/sbinfo.c
|
|
+++ b/fs/aufs/sbinfo.c
|
|
@@ -118,6 +118,8 @@
|
|
init_waitqueue_head(&sbinfo->si_plink_wq);
|
|
spin_lock_init(&sbinfo->si_plink_maint_lock);
|
|
|
|
+ au_sphl_init(&sbinfo->si_files);
|
|
+
|
|
/* leave other members for sysaufs and si_mnt. */
|
|
sbinfo->si_sb = sb;
|
|
sb->s_fs_info = sbinfo;
|
|
--- a/fs/aufs/super.h
|
|
+++ b/fs/aufs/super.h
|
|
@@ -108,7 +108,8 @@
|
|
} au_si_pid;
|
|
|
|
/*
|
|
- * dirty approach to protect sb->sb_inodes and ->s_files from remount.
|
|
+ * dirty approach to protect sb->sb_inodes and ->s_files (gone) from
|
|
+ * remount.
|
|
*/
|
|
atomic_long_t si_ninodes, si_nfiles;
|
|
|
|
@@ -188,6 +189,9 @@
|
|
wait_queue_head_t si_plink_wq;
|
|
spinlock_t si_plink_maint_lock;
|
|
pid_t si_plink_maint_pid;
|
|
+
|
|
+ /* file list */
|
|
+ struct au_sphlhead si_files;
|
|
|
|
/*
|
|
* sysfs and lifetime management.
|
|
--- a/fs/aufs/sysrq.c
|
|
+++ b/fs/aufs/sysrq.c
|
|
@@ -30,6 +30,8 @@
|
|
char *plevel;
|
|
struct au_sbinfo *sbinfo;
|
|
struct file *file;
|
|
+ struct au_sphlhead *files;
|
|
+ struct au_finfo *finfo;
|
|
|
|
plevel = au_plevel;
|
|
au_plevel = KERN_WARNING;
|
|
@@ -86,15 +88,17 @@
|
|
}
|
|
#endif
|
|
pr("files\n");
|
|
- lg_global_lock(&files_lglock);
|
|
- do_file_list_for_each_entry(sb, file) {
|
|
+ files = &au_sbi(sb)->si_files;
|
|
+ spin_lock(&files->spin);
|
|
+ hlist_for_each_entry(finfo, &files->head, fi_hlist) {
|
|
umode_t mode;
|
|
|
|
+ file = finfo->fi_file;
|
|
mode = file_inode(file)->i_mode;
|
|
if (!special_file(mode))
|
|
au_dpri_file(file);
|
|
- } while_file_list_for_each_entry;
|
|
- lg_global_unlock(&files_lglock);
|
|
+ }
|
|
+ spin_unlock(&files->spin);
|
|
pr("done\n");
|
|
|
|
#undef pr
|
|
--- a/fs/aufs/vfsub.h
|
|
+++ b/fs/aufs/vfsub.h
|
|
@@ -32,7 +32,6 @@
|
|
|
|
/* copied from linux/fs/internal.h */
|
|
/* todo: BAD approach!! */
|
|
-extern struct lglock vfsmount_lock;
|
|
extern void __mnt_drop_write(struct vfsmount *);
|
|
extern spinlock_t inode_sb_list_lock;
|
|
|
|
-/* copied from linux/fs/file_table.c */
|
|
-extern struct lglock files_lglock;
|
|
-#ifdef CONFIG_SMP
|
|
-/*
|
|
- * These macros iterate all files on all CPUs for a given superblock.
|
|
- * files_lglock must be held globally.
|
|
- */
|
|
-#define do_file_list_for_each_entry(__sb, __file) \
|
|
-{ \
|
|
- int i; \
|
|
- for_each_possible_cpu(i) { \
|
|
- struct list_head *list; \
|
|
- list = per_cpu_ptr((__sb)->s_files, i); \
|
|
- list_for_each_entry((__file), list, f_u.fu_list)
|
|
-
|
|
-#define while_file_list_for_each_entry \
|
|
- } \
|
|
-}
|
|
-
|
|
-#else
|
|
-
|
|
-#define do_file_list_for_each_entry(__sb, __file) \
|
|
-{ \
|
|
- struct list_head *list; \
|
|
- list = &(sb)->s_files; \
|
|
- list_for_each_entry((__file), list, f_u.fu_list)
|
|
-
|
|
-#define while_file_list_for_each_entry \
|
|
-}
|
|
-#endif
|
|
-
|
|
-/* ---------------------------------------------------------------------- */
|
|
-
|
|
/* lock subclass for lower inode */
|
|
/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
|
|
/* reduce? gave up. */
|
|
--- a/fs/aufs/export.c
|
|
+++ b/fs/aufs/export.c
|
|
@@ -301,9 +301,9 @@
|
|
};
|
|
|
|
get_fs_root(current->fs, &root);
|
|
- br_read_lock(&vfsmount_lock);
|
|
+ rcu_read_lock();
|
|
err = iterate_mounts(au_compare_mnt, &args, root.mnt);
|
|
- br_read_unlock(&vfsmount_lock);
|
|
+ rcu_read_unlock();
|
|
path_put(&root);
|
|
AuDebugOn(!err);
|
|
AuDebugOn(!args.mnt);
|
|
--- a/fs/aufs/dcsub.c
|
|
+++ b/fs/aufs/dcsub.c
|
|
@@ -197,7 +197,7 @@
|
|
goto out;
|
|
|
|
/*
|
|
- * vfsmount_lock is unnecessary since this is a traverse in a single
|
|
+ * RCU for vfsmount is unnecessary since this is a traverse in a single
|
|
* mount
|
|
*/
|
|
while (!IS_ROOT(dentry)) {
|