]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - fs/aufs/loop.c
UBUNTU: SAUCE: Import aufs driver
[mirror_ubuntu-bionic-kernel.git] / fs / aufs / loop.c
1 /*
2 * Copyright (C) 2005-2017 Junjiro R. Okajima
3 *
4 * This program, aufs is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 /*
19 * support for loopback block device as a branch
20 */
21
22 #include "aufs.h"
23
24 /* added into drivers/block/loop.c */
25 static struct file *(*backing_file_func)(struct super_block *sb);
26
27 /*
28 * test if two lower dentries have overlapping branches.
29 */
30 int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding)
31 {
32 struct super_block *h_sb;
33 struct file *backing_file;
34
35 if (unlikely(!backing_file_func)) {
36 /* don't load "loop" module here */
37 backing_file_func = symbol_get(loop_backing_file);
38 if (unlikely(!backing_file_func))
39 /* "loop" module is not loaded */
40 return 0;
41 }
42
43 h_sb = h_adding->d_sb;
44 backing_file = backing_file_func(h_sb);
45 if (!backing_file)
46 return 0;
47
48 h_adding = backing_file->f_path.dentry;
49 /*
50 * h_adding can be local NFS.
51 * in this case aufs cannot detect the loop.
52 */
53 if (unlikely(h_adding->d_sb == sb))
54 return 1;
55 return !!au_test_subdir(h_adding, sb->s_root);
56 }
57
58 /* true if a kernel thread named 'loop[0-9].*' accesses a file */
59 int au_test_loopback_kthread(void)
60 {
61 int ret;
62 struct task_struct *tsk = current;
63 char c, comm[sizeof(tsk->comm)];
64
65 ret = 0;
66 if (tsk->flags & PF_KTHREAD) {
67 get_task_comm(comm, tsk);
68 c = comm[4];
69 ret = ('0' <= c && c <= '9'
70 && !strncmp(comm, "loop", 4));
71 }
72
73 return ret;
74 }
75
76 /* ---------------------------------------------------------------------- */
77
78 #define au_warn_loopback_step 16
79 static int au_warn_loopback_nelem = au_warn_loopback_step;
80 static unsigned long *au_warn_loopback_array;
81
82 void au_warn_loopback(struct super_block *h_sb)
83 {
84 int i, new_nelem;
85 unsigned long *a, magic;
86 static DEFINE_SPINLOCK(spin);
87
88 magic = h_sb->s_magic;
89 spin_lock(&spin);
90 a = au_warn_loopback_array;
91 for (i = 0; i < au_warn_loopback_nelem && *a; i++)
92 if (a[i] == magic) {
93 spin_unlock(&spin);
94 return;
95 }
96
97 /* h_sb is new to us, print it */
98 if (i < au_warn_loopback_nelem) {
99 a[i] = magic;
100 goto pr;
101 }
102
103 /* expand the array */
104 new_nelem = au_warn_loopback_nelem + au_warn_loopback_step;
105 a = au_kzrealloc(au_warn_loopback_array,
106 au_warn_loopback_nelem * sizeof(unsigned long),
107 new_nelem * sizeof(unsigned long), GFP_ATOMIC,
108 /*may_shrink*/0);
109 if (a) {
110 au_warn_loopback_nelem = new_nelem;
111 au_warn_loopback_array = a;
112 a[i] = magic;
113 goto pr;
114 }
115
116 spin_unlock(&spin);
117 AuWarn1("realloc failed, ignored\n");
118 return;
119
120 pr:
121 spin_unlock(&spin);
122 pr_warn("you may want to try another patch for loopback file "
123 "on %s(0x%lx) branch\n", au_sbtype(h_sb), magic);
124 }
125
126 int au_loopback_init(void)
127 {
128 int err;
129 struct super_block *sb __maybe_unused;
130
131 BUILD_BUG_ON(sizeof(sb->s_magic) != sizeof(unsigned long));
132
133 err = 0;
134 au_warn_loopback_array = kcalloc(au_warn_loopback_step,
135 sizeof(unsigned long), GFP_NOFS);
136 if (unlikely(!au_warn_loopback_array))
137 err = -ENOMEM;
138
139 return err;
140 }
141
142 void au_loopback_fin(void)
143 {
144 if (backing_file_func)
145 symbol_put(loop_backing_file);
146 kfree(au_warn_loopback_array);
147 }
148
149 /* ---------------------------------------------------------------------- */
150
151 /* support the loopback block device insude aufs */
152
153 struct file *aufs_real_loop(struct file *file)
154 {
155 struct file *f;
156
157 BUG_ON(!au_test_aufs(file->f_path.dentry->d_sb));
158 fi_read_lock(file);
159 f = au_hf_top(file);
160 fi_read_unlock(file);
161 AuDebugOn(!f);
162 return f;
163 }