aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/acct.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2015-01-10 17:53:21 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2015-01-25 23:17:28 -0500
commit59eda0e07f43c950d31756213b607af673e551f0 (patch)
treef40f7b67133576c36a65a4cba9aca5df68d00f34 /kernel/acct.c
parentfdab684d7202774bfd8762d4a656a553b787c8ec (diff)
new fs_pin killing logics
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'kernel/acct.c')
-rw-r--r--kernel/acct.c81
1 files changed, 34 insertions, 47 deletions
diff --git a/kernel/acct.c b/kernel/acct.c
index cf6588ab517b..e6c10d1a4058 100644
--- a/kernel/acct.c
+++ b/kernel/acct.c
@@ -76,7 +76,6 @@ int acct_parm[3] = {4, 2, 30};
76/* 76/*
77 * External references and all of the globals. 77 * External references and all of the globals.
78 */ 78 */
79static void do_acct_process(struct bsd_acct_struct *acct);
80 79
81struct bsd_acct_struct { 80struct bsd_acct_struct {
82 struct fs_pin pin; 81 struct fs_pin pin;
@@ -91,6 +90,8 @@ struct bsd_acct_struct {
91 struct completion done; 90 struct completion done;
92}; 91};
93 92
93static void do_acct_process(struct bsd_acct_struct *acct);
94
94/* 95/*
95 * Check the amount of free space and suspend/resume accordingly. 96 * Check the amount of free space and suspend/resume accordingly.
96 */ 97 */
@@ -132,13 +133,18 @@ static void acct_put(struct bsd_acct_struct *p)
132 kfree_rcu(p, rcu); 133 kfree_rcu(p, rcu);
133} 134}
134 135
136static inline struct bsd_acct_struct *to_acct(struct fs_pin *p)
137{
138 return p ? container_of(p, struct bsd_acct_struct, pin) : NULL;
139}
140
135static struct bsd_acct_struct *acct_get(struct pid_namespace *ns) 141static struct bsd_acct_struct *acct_get(struct pid_namespace *ns)
136{ 142{
137 struct bsd_acct_struct *res; 143 struct bsd_acct_struct *res;
138again: 144again:
139 smp_rmb(); 145 smp_rmb();
140 rcu_read_lock(); 146 rcu_read_lock();
141 res = ACCESS_ONCE(ns->bacct); 147 res = to_acct(ACCESS_ONCE(ns->bacct));
142 if (!res) { 148 if (!res) {
143 rcu_read_unlock(); 149 rcu_read_unlock();
144 return NULL; 150 return NULL;
@@ -150,7 +156,7 @@ again:
150 } 156 }
151 rcu_read_unlock(); 157 rcu_read_unlock();
152 mutex_lock(&res->lock); 158 mutex_lock(&res->lock);
153 if (!res->ns) { 159 if (res != to_acct(ACCESS_ONCE(ns->bacct))) {
154 mutex_unlock(&res->lock); 160 mutex_unlock(&res->lock);
155 acct_put(res); 161 acct_put(res);
156 goto again; 162 goto again;
@@ -158,6 +164,19 @@ again:
158 return res; 164 return res;
159} 165}
160 166
167static void acct_pin_kill(struct fs_pin *pin)
168{
169 struct bsd_acct_struct *acct = to_acct(pin);
170 mutex_lock(&acct->lock);
171 do_acct_process(acct);
172 schedule_work(&acct->work);
173 wait_for_completion(&acct->done);
174 cmpxchg(&acct->ns->bacct, pin, NULL);
175 mutex_unlock(&acct->lock);
176 pin_remove(pin);
177 acct_put(acct);
178}
179
161static void close_work(struct work_struct *work) 180static void close_work(struct work_struct *work)
162{ 181{
163 struct bsd_acct_struct *acct = container_of(work, struct bsd_acct_struct, work); 182 struct bsd_acct_struct *acct = container_of(work, struct bsd_acct_struct, work);
@@ -168,49 +187,13 @@ static void close_work(struct work_struct *work)
168 complete(&acct->done); 187 complete(&acct->done);
169} 188}
170 189
171static void acct_kill(struct bsd_acct_struct *acct)
172{
173 if (acct) {
174 struct pid_namespace *ns = acct->ns;
175 do_acct_process(acct);
176 INIT_WORK(&acct->work, close_work);
177 init_completion(&acct->done);
178 schedule_work(&acct->work);
179 wait_for_completion(&acct->done);
180 pin_remove(&acct->pin);
181 cmpxchg(&ns->bacct, acct, NULL);
182 acct->ns = NULL;
183 atomic_long_dec(&acct->count);
184 mutex_unlock(&acct->lock);
185 acct_put(acct);
186 }
187}
188
189static void acct_pin_kill(struct fs_pin *pin)
190{
191 struct bsd_acct_struct *acct;
192 acct = container_of(pin, struct bsd_acct_struct, pin);
193 if (!atomic_long_inc_not_zero(&acct->count)) {
194 rcu_read_unlock();
195 cpu_relax();
196 return;
197 }
198 rcu_read_unlock();
199 mutex_lock(&acct->lock);
200 if (!acct->ns) {
201 mutex_unlock(&acct->lock);
202 acct_put(acct);
203 acct = NULL;
204 }
205 acct_kill(acct);
206}
207
208static int acct_on(struct filename *pathname) 190static int acct_on(struct filename *pathname)
209{ 191{
210 struct file *file; 192 struct file *file;
211 struct vfsmount *mnt, *internal; 193 struct vfsmount *mnt, *internal;
212 struct pid_namespace *ns = task_active_pid_ns(current); 194 struct pid_namespace *ns = task_active_pid_ns(current);
213 struct bsd_acct_struct *acct, *old; 195 struct bsd_acct_struct *acct;
196 struct fs_pin *old;
214 int err; 197 int err;
215 198
216 acct = kzalloc(sizeof(struct bsd_acct_struct), GFP_KERNEL); 199 acct = kzalloc(sizeof(struct bsd_acct_struct), GFP_KERNEL);
@@ -252,18 +235,20 @@ static int acct_on(struct filename *pathname)
252 file->f_path.mnt = internal; 235 file->f_path.mnt = internal;
253 236
254 atomic_long_set(&acct->count, 1); 237 atomic_long_set(&acct->count, 1);
255 acct->pin.kill = acct_pin_kill; 238 init_fs_pin(&acct->pin, acct_pin_kill);
256 acct->file = file; 239 acct->file = file;
257 acct->needcheck = jiffies; 240 acct->needcheck = jiffies;
258 acct->ns = ns; 241 acct->ns = ns;
259 mutex_init(&acct->lock); 242 mutex_init(&acct->lock);
243 INIT_WORK(&acct->work, close_work);
244 init_completion(&acct->done);
260 mutex_lock_nested(&acct->lock, 1); /* nobody has seen it yet */ 245 mutex_lock_nested(&acct->lock, 1); /* nobody has seen it yet */
261 pin_insert(&acct->pin, mnt); 246 pin_insert(&acct->pin, mnt);
262 247
263 old = acct_get(ns); 248 rcu_read_lock();
264 ns->bacct = acct; 249 old = xchg(&ns->bacct, &acct->pin);
265 acct_kill(old);
266 mutex_unlock(&acct->lock); 250 mutex_unlock(&acct->lock);
251 pin_kill(old);
267 mnt_drop_write(mnt); 252 mnt_drop_write(mnt);
268 mntput(mnt); 253 mntput(mnt);
269 return 0; 254 return 0;
@@ -299,7 +284,8 @@ SYSCALL_DEFINE1(acct, const char __user *, name)
299 mutex_unlock(&acct_on_mutex); 284 mutex_unlock(&acct_on_mutex);
300 putname(tmp); 285 putname(tmp);
301 } else { 286 } else {
302 acct_kill(acct_get(task_active_pid_ns(current))); 287 rcu_read_lock();
288 pin_kill(task_active_pid_ns(current)->bacct);
303 } 289 }
304 290
305 return error; 291 return error;
@@ -307,7 +293,8 @@ SYSCALL_DEFINE1(acct, const char __user *, name)
307 293
308void acct_exit_ns(struct pid_namespace *ns) 294void acct_exit_ns(struct pid_namespace *ns)
309{ 295{
310 acct_kill(acct_get(ns)); 296 rcu_read_lock();
297 pin_kill(ns->bacct);
311} 298}
312 299
313/* 300/*