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