Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-or-later
2 : : /* Daemon interface
3 : : *
4 : : * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
5 : : * Written by David Howells (dhowells@redhat.com)
6 : : */
7 : :
8 : : #include <linux/module.h>
9 : : #include <linux/init.h>
10 : : #include <linux/sched.h>
11 : : #include <linux/completion.h>
12 : : #include <linux/slab.h>
13 : : #include <linux/fs.h>
14 : : #include <linux/file.h>
15 : : #include <linux/namei.h>
16 : : #include <linux/poll.h>
17 : : #include <linux/mount.h>
18 : : #include <linux/statfs.h>
19 : : #include <linux/ctype.h>
20 : : #include <linux/string.h>
21 : : #include <linux/fs_struct.h>
22 : : #include "internal.h"
23 : :
24 : : static int cachefiles_daemon_open(struct inode *, struct file *);
25 : : static int cachefiles_daemon_release(struct inode *, struct file *);
26 : : static ssize_t cachefiles_daemon_read(struct file *, char __user *, size_t,
27 : : loff_t *);
28 : : static ssize_t cachefiles_daemon_write(struct file *, const char __user *,
29 : : size_t, loff_t *);
30 : : static __poll_t cachefiles_daemon_poll(struct file *,
31 : : struct poll_table_struct *);
32 : : static int cachefiles_daemon_frun(struct cachefiles_cache *, char *);
33 : : static int cachefiles_daemon_fcull(struct cachefiles_cache *, char *);
34 : : static int cachefiles_daemon_fstop(struct cachefiles_cache *, char *);
35 : : static int cachefiles_daemon_brun(struct cachefiles_cache *, char *);
36 : : static int cachefiles_daemon_bcull(struct cachefiles_cache *, char *);
37 : : static int cachefiles_daemon_bstop(struct cachefiles_cache *, char *);
38 : : static int cachefiles_daemon_cull(struct cachefiles_cache *, char *);
39 : : static int cachefiles_daemon_debug(struct cachefiles_cache *, char *);
40 : : static int cachefiles_daemon_dir(struct cachefiles_cache *, char *);
41 : : static int cachefiles_daemon_inuse(struct cachefiles_cache *, char *);
42 : : static int cachefiles_daemon_secctx(struct cachefiles_cache *, char *);
43 : : static int cachefiles_daemon_tag(struct cachefiles_cache *, char *);
44 : :
45 : : static unsigned long cachefiles_open;
46 : :
47 : : const struct file_operations cachefiles_daemon_fops = {
48 : : .owner = THIS_MODULE,
49 : : .open = cachefiles_daemon_open,
50 : : .release = cachefiles_daemon_release,
51 : : .read = cachefiles_daemon_read,
52 : : .write = cachefiles_daemon_write,
53 : : .poll = cachefiles_daemon_poll,
54 : : .llseek = noop_llseek,
55 : : };
56 : :
57 : : struct cachefiles_daemon_cmd {
58 : : char name[8];
59 : : int (*handler)(struct cachefiles_cache *cache, char *args);
60 : : };
61 : :
62 : : static const struct cachefiles_daemon_cmd cachefiles_daemon_cmds[] = {
63 : : { "bind", cachefiles_daemon_bind },
64 : : { "brun", cachefiles_daemon_brun },
65 : : { "bcull", cachefiles_daemon_bcull },
66 : : { "bstop", cachefiles_daemon_bstop },
67 : : { "cull", cachefiles_daemon_cull },
68 : : { "debug", cachefiles_daemon_debug },
69 : : { "dir", cachefiles_daemon_dir },
70 : : { "frun", cachefiles_daemon_frun },
71 : : { "fcull", cachefiles_daemon_fcull },
72 : : { "fstop", cachefiles_daemon_fstop },
73 : : { "inuse", cachefiles_daemon_inuse },
74 : : { "secctx", cachefiles_daemon_secctx },
75 : : { "tag", cachefiles_daemon_tag },
76 : : { "", NULL }
77 : : };
78 : :
79 : :
80 : : /*
81 : : * do various checks
82 : : */
83 : 0 : static int cachefiles_daemon_open(struct inode *inode, struct file *file)
84 : : {
85 : : struct cachefiles_cache *cache;
86 : :
87 : : _enter("");
88 : :
89 : : /* only the superuser may do this */
90 [ # # ]: 0 : if (!capable(CAP_SYS_ADMIN))
91 : : return -EPERM;
92 : :
93 : : /* the cachefiles device may only be open once at a time */
94 [ # # ]: 0 : if (xchg(&cachefiles_open, 1) == 1)
95 : : return -EBUSY;
96 : :
97 : : /* allocate a cache record */
98 : 0 : cache = kzalloc(sizeof(struct cachefiles_cache), GFP_KERNEL);
99 [ # # ]: 0 : if (!cache) {
100 : 0 : cachefiles_open = 0;
101 : 0 : return -ENOMEM;
102 : : }
103 : :
104 : 0 : mutex_init(&cache->daemon_mutex);
105 : 0 : cache->active_nodes = RB_ROOT;
106 : 0 : rwlock_init(&cache->active_lock);
107 : 0 : init_waitqueue_head(&cache->daemon_pollwq);
108 : :
109 : : /* set default caching limits
110 : : * - limit at 1% free space and/or free files
111 : : * - cull below 5% free space and/or free files
112 : : * - cease culling above 7% free space and/or free files
113 : : */
114 : 0 : cache->frun_percent = 7;
115 : 0 : cache->fcull_percent = 5;
116 : 0 : cache->fstop_percent = 1;
117 : 0 : cache->brun_percent = 7;
118 : 0 : cache->bcull_percent = 5;
119 : 0 : cache->bstop_percent = 1;
120 : :
121 : 0 : file->private_data = cache;
122 : 0 : cache->cachefilesd = file;
123 : 0 : return 0;
124 : : }
125 : :
126 : : /*
127 : : * release a cache
128 : : */
129 : 0 : static int cachefiles_daemon_release(struct inode *inode, struct file *file)
130 : : {
131 : 0 : struct cachefiles_cache *cache = file->private_data;
132 : :
133 : : _enter("");
134 : :
135 [ # # ]: 0 : ASSERT(cache);
136 : :
137 : 0 : set_bit(CACHEFILES_DEAD, &cache->flags);
138 : :
139 : 0 : cachefiles_daemon_unbind(cache);
140 : :
141 [ # # ]: 0 : ASSERT(!cache->active_nodes.rb_node);
142 : :
143 : : /* clean up the control file interface */
144 : 0 : cache->cachefilesd = NULL;
145 : 0 : file->private_data = NULL;
146 : 0 : cachefiles_open = 0;
147 : :
148 : 0 : kfree(cache);
149 : :
150 : : _leave("");
151 : 0 : return 0;
152 : : }
153 : :
154 : : /*
155 : : * read the cache state
156 : : */
157 : 0 : static ssize_t cachefiles_daemon_read(struct file *file, char __user *_buffer,
158 : : size_t buflen, loff_t *pos)
159 : : {
160 : 0 : struct cachefiles_cache *cache = file->private_data;
161 : : unsigned long long b_released;
162 : : unsigned f_released;
163 : : char buffer[256];
164 : : int n;
165 : :
166 : : //_enter(",,%zu,", buflen);
167 : :
168 [ # # ]: 0 : if (!test_bit(CACHEFILES_READY, &cache->flags))
169 : : return 0;
170 : :
171 : : /* check how much space the cache has */
172 : 0 : cachefiles_has_space(cache, 0, 0);
173 : :
174 : : /* summarise */
175 : 0 : f_released = atomic_xchg(&cache->f_released, 0);
176 : 0 : b_released = atomic_long_xchg(&cache->b_released, 0);
177 : 0 : clear_bit(CACHEFILES_STATE_CHANGED, &cache->flags);
178 : :
179 [ # # ]: 0 : n = snprintf(buffer, sizeof(buffer),
180 : : "cull=%c"
181 : : " frun=%llx"
182 : : " fcull=%llx"
183 : : " fstop=%llx"
184 : : " brun=%llx"
185 : : " bcull=%llx"
186 : : " bstop=%llx"
187 : : " freleased=%x"
188 : : " breleased=%llx",
189 : : test_bit(CACHEFILES_CULLING, &cache->flags) ? '1' : '0',
190 : : (unsigned long long) cache->frun,
191 : : (unsigned long long) cache->fcull,
192 : : (unsigned long long) cache->fstop,
193 : : (unsigned long long) cache->brun,
194 : : (unsigned long long) cache->bcull,
195 : : (unsigned long long) cache->bstop,
196 : : f_released,
197 : : b_released);
198 : :
199 [ # # ]: 0 : if (n > buflen)
200 : : return -EMSGSIZE;
201 : :
202 [ # # ]: 0 : if (copy_to_user(_buffer, buffer, n) != 0)
203 : : return -EFAULT;
204 : :
205 : 0 : return n;
206 : : }
207 : :
208 : : /*
209 : : * command the cache
210 : : */
211 : 0 : static ssize_t cachefiles_daemon_write(struct file *file,
212 : : const char __user *_data,
213 : : size_t datalen,
214 : : loff_t *pos)
215 : : {
216 : : const struct cachefiles_daemon_cmd *cmd;
217 : 0 : struct cachefiles_cache *cache = file->private_data;
218 : : ssize_t ret;
219 : : char *data, *args, *cp;
220 : :
221 : : //_enter(",,%zu,", datalen);
222 : :
223 [ # # ]: 0 : ASSERT(cache);
224 : :
225 [ # # ]: 0 : if (test_bit(CACHEFILES_DEAD, &cache->flags))
226 : : return -EIO;
227 : :
228 [ # # ]: 0 : if (datalen < 0 || datalen > PAGE_SIZE - 1)
229 : : return -EOPNOTSUPP;
230 : :
231 : : /* drag the command string into the kernel so we can parse it */
232 : 0 : data = memdup_user_nul(_data, datalen);
233 [ # # ]: 0 : if (IS_ERR(data))
234 : 0 : return PTR_ERR(data);
235 : :
236 : : ret = -EINVAL;
237 [ # # ]: 0 : if (memchr(data, '\0', datalen))
238 : : goto error;
239 : :
240 : : /* strip any newline */
241 : 0 : cp = memchr(data, '\n', datalen);
242 [ # # ]: 0 : if (cp) {
243 [ # # ]: 0 : if (cp == data)
244 : : goto error;
245 : :
246 : 0 : *cp = '\0';
247 : : }
248 : :
249 : : /* parse the command */
250 : : ret = -EOPNOTSUPP;
251 : :
252 [ # # ]: 0 : for (args = data; *args; args++)
253 [ # # ]: 0 : if (isspace(*args))
254 : : break;
255 [ # # ]: 0 : if (*args) {
256 [ # # ]: 0 : if (args == data)
257 : : goto error;
258 : 0 : *args = '\0';
259 : 0 : args = skip_spaces(++args);
260 : : }
261 : :
262 : : /* run the appropriate command handler */
263 [ # # ]: 0 : for (cmd = cachefiles_daemon_cmds; cmd->name[0]; cmd++)
264 [ # # ]: 0 : if (strcmp(cmd->name, data) == 0)
265 : : goto found_command;
266 : :
267 : : error:
268 : 0 : kfree(data);
269 : : //_leave(" = %zd", ret);
270 : 0 : return ret;
271 : :
272 : : found_command:
273 : 0 : mutex_lock(&cache->daemon_mutex);
274 : :
275 : : ret = -EIO;
276 [ # # ]: 0 : if (!test_bit(CACHEFILES_DEAD, &cache->flags))
277 : 0 : ret = cmd->handler(cache, args);
278 : :
279 : 0 : mutex_unlock(&cache->daemon_mutex);
280 : :
281 [ # # ]: 0 : if (ret == 0)
282 : 0 : ret = datalen;
283 : : goto error;
284 : : }
285 : :
286 : : /*
287 : : * poll for culling state
288 : : * - use EPOLLOUT to indicate culling state
289 : : */
290 : 0 : static __poll_t cachefiles_daemon_poll(struct file *file,
291 : : struct poll_table_struct *poll)
292 : : {
293 : 0 : struct cachefiles_cache *cache = file->private_data;
294 : : __poll_t mask;
295 : :
296 : 0 : poll_wait(file, &cache->daemon_pollwq, poll);
297 : : mask = 0;
298 : :
299 [ # # ]: 0 : if (test_bit(CACHEFILES_STATE_CHANGED, &cache->flags))
300 : : mask |= EPOLLIN;
301 : :
302 [ # # ]: 0 : if (test_bit(CACHEFILES_CULLING, &cache->flags))
303 : 0 : mask |= EPOLLOUT;
304 : :
305 : 0 : return mask;
306 : : }
307 : :
308 : : /*
309 : : * give a range error for cache space constraints
310 : : * - can be tail-called
311 : : */
312 : : static int cachefiles_daemon_range_error(struct cachefiles_cache *cache,
313 : : char *args)
314 : : {
315 : 0 : pr_err("Free space limits must be in range 0%%<=stop<cull<run<100%%\n");
316 : :
317 : : return -EINVAL;
318 : : }
319 : :
320 : : /*
321 : : * set the percentage of files at which to stop culling
322 : : * - command: "frun <N>%"
323 : : */
324 : 0 : static int cachefiles_daemon_frun(struct cachefiles_cache *cache, char *args)
325 : : {
326 : : unsigned long frun;
327 : :
328 : : _enter(",%s", args);
329 : :
330 [ # # ]: 0 : if (!*args)
331 : : return -EINVAL;
332 : :
333 : 0 : frun = simple_strtoul(args, &args, 10);
334 [ # # # # ]: 0 : if (args[0] != '%' || args[1] != '\0')
335 : : return -EINVAL;
336 : :
337 [ # # # # ]: 0 : if (frun <= cache->fcull_percent || frun >= 100)
338 : 0 : return cachefiles_daemon_range_error(cache, args);
339 : :
340 : 0 : cache->frun_percent = frun;
341 : 0 : return 0;
342 : : }
343 : :
344 : : /*
345 : : * set the percentage of files at which to start culling
346 : : * - command: "fcull <N>%"
347 : : */
348 : 0 : static int cachefiles_daemon_fcull(struct cachefiles_cache *cache, char *args)
349 : : {
350 : : unsigned long fcull;
351 : :
352 : : _enter(",%s", args);
353 : :
354 [ # # ]: 0 : if (!*args)
355 : : return -EINVAL;
356 : :
357 : 0 : fcull = simple_strtoul(args, &args, 10);
358 [ # # # # ]: 0 : if (args[0] != '%' || args[1] != '\0')
359 : : return -EINVAL;
360 : :
361 [ # # # # ]: 0 : if (fcull <= cache->fstop_percent || fcull >= cache->frun_percent)
362 : 0 : return cachefiles_daemon_range_error(cache, args);
363 : :
364 : 0 : cache->fcull_percent = fcull;
365 : 0 : return 0;
366 : : }
367 : :
368 : : /*
369 : : * set the percentage of files at which to stop allocating
370 : : * - command: "fstop <N>%"
371 : : */
372 : 0 : static int cachefiles_daemon_fstop(struct cachefiles_cache *cache, char *args)
373 : : {
374 : : unsigned long fstop;
375 : :
376 : : _enter(",%s", args);
377 : :
378 [ # # ]: 0 : if (!*args)
379 : : return -EINVAL;
380 : :
381 : 0 : fstop = simple_strtoul(args, &args, 10);
382 [ # # # # ]: 0 : if (args[0] != '%' || args[1] != '\0')
383 : : return -EINVAL;
384 : :
385 [ # # ]: 0 : if (fstop < 0 || fstop >= cache->fcull_percent)
386 : 0 : return cachefiles_daemon_range_error(cache, args);
387 : :
388 : 0 : cache->fstop_percent = fstop;
389 : 0 : return 0;
390 : : }
391 : :
392 : : /*
393 : : * set the percentage of blocks at which to stop culling
394 : : * - command: "brun <N>%"
395 : : */
396 : 0 : static int cachefiles_daemon_brun(struct cachefiles_cache *cache, char *args)
397 : : {
398 : : unsigned long brun;
399 : :
400 : : _enter(",%s", args);
401 : :
402 [ # # ]: 0 : if (!*args)
403 : : return -EINVAL;
404 : :
405 : 0 : brun = simple_strtoul(args, &args, 10);
406 [ # # # # ]: 0 : if (args[0] != '%' || args[1] != '\0')
407 : : return -EINVAL;
408 : :
409 [ # # # # ]: 0 : if (brun <= cache->bcull_percent || brun >= 100)
410 : 0 : return cachefiles_daemon_range_error(cache, args);
411 : :
412 : 0 : cache->brun_percent = brun;
413 : 0 : return 0;
414 : : }
415 : :
416 : : /*
417 : : * set the percentage of blocks at which to start culling
418 : : * - command: "bcull <N>%"
419 : : */
420 : 0 : static int cachefiles_daemon_bcull(struct cachefiles_cache *cache, char *args)
421 : : {
422 : : unsigned long bcull;
423 : :
424 : : _enter(",%s", args);
425 : :
426 [ # # ]: 0 : if (!*args)
427 : : return -EINVAL;
428 : :
429 : 0 : bcull = simple_strtoul(args, &args, 10);
430 [ # # # # ]: 0 : if (args[0] != '%' || args[1] != '\0')
431 : : return -EINVAL;
432 : :
433 [ # # # # ]: 0 : if (bcull <= cache->bstop_percent || bcull >= cache->brun_percent)
434 : 0 : return cachefiles_daemon_range_error(cache, args);
435 : :
436 : 0 : cache->bcull_percent = bcull;
437 : 0 : return 0;
438 : : }
439 : :
440 : : /*
441 : : * set the percentage of blocks at which to stop allocating
442 : : * - command: "bstop <N>%"
443 : : */
444 : 0 : static int cachefiles_daemon_bstop(struct cachefiles_cache *cache, char *args)
445 : : {
446 : : unsigned long bstop;
447 : :
448 : : _enter(",%s", args);
449 : :
450 [ # # ]: 0 : if (!*args)
451 : : return -EINVAL;
452 : :
453 : 0 : bstop = simple_strtoul(args, &args, 10);
454 [ # # # # ]: 0 : if (args[0] != '%' || args[1] != '\0')
455 : : return -EINVAL;
456 : :
457 [ # # ]: 0 : if (bstop < 0 || bstop >= cache->bcull_percent)
458 : 0 : return cachefiles_daemon_range_error(cache, args);
459 : :
460 : 0 : cache->bstop_percent = bstop;
461 : 0 : return 0;
462 : : }
463 : :
464 : : /*
465 : : * set the cache directory
466 : : * - command: "dir <name>"
467 : : */
468 : 0 : static int cachefiles_daemon_dir(struct cachefiles_cache *cache, char *args)
469 : : {
470 : : char *dir;
471 : :
472 : : _enter(",%s", args);
473 : :
474 [ # # ]: 0 : if (!*args) {
475 : 0 : pr_err("Empty directory specified\n");
476 : 0 : return -EINVAL;
477 : : }
478 : :
479 [ # # ]: 0 : if (cache->rootdirname) {
480 : 0 : pr_err("Second cache directory specified\n");
481 : 0 : return -EEXIST;
482 : : }
483 : :
484 : 0 : dir = kstrdup(args, GFP_KERNEL);
485 [ # # ]: 0 : if (!dir)
486 : : return -ENOMEM;
487 : :
488 : 0 : cache->rootdirname = dir;
489 : 0 : return 0;
490 : : }
491 : :
492 : : /*
493 : : * set the cache security context
494 : : * - command: "secctx <ctx>"
495 : : */
496 : 0 : static int cachefiles_daemon_secctx(struct cachefiles_cache *cache, char *args)
497 : : {
498 : : char *secctx;
499 : :
500 : : _enter(",%s", args);
501 : :
502 [ # # ]: 0 : if (!*args) {
503 : 0 : pr_err("Empty security context specified\n");
504 : 0 : return -EINVAL;
505 : : }
506 : :
507 [ # # ]: 0 : if (cache->secctx) {
508 : 0 : pr_err("Second security context specified\n");
509 : 0 : return -EINVAL;
510 : : }
511 : :
512 : 0 : secctx = kstrdup(args, GFP_KERNEL);
513 [ # # ]: 0 : if (!secctx)
514 : : return -ENOMEM;
515 : :
516 : 0 : cache->secctx = secctx;
517 : 0 : return 0;
518 : : }
519 : :
520 : : /*
521 : : * set the cache tag
522 : : * - command: "tag <name>"
523 : : */
524 : 0 : static int cachefiles_daemon_tag(struct cachefiles_cache *cache, char *args)
525 : : {
526 : : char *tag;
527 : :
528 : : _enter(",%s", args);
529 : :
530 [ # # ]: 0 : if (!*args) {
531 : 0 : pr_err("Empty tag specified\n");
532 : 0 : return -EINVAL;
533 : : }
534 : :
535 [ # # ]: 0 : if (cache->tag)
536 : : return -EEXIST;
537 : :
538 : 0 : tag = kstrdup(args, GFP_KERNEL);
539 [ # # ]: 0 : if (!tag)
540 : : return -ENOMEM;
541 : :
542 : 0 : cache->tag = tag;
543 : 0 : return 0;
544 : : }
545 : :
546 : : /*
547 : : * request a node in the cache be culled from the current working directory
548 : : * - command: "cull <name>"
549 : : */
550 : 0 : static int cachefiles_daemon_cull(struct cachefiles_cache *cache, char *args)
551 : : {
552 : : struct path path;
553 : : const struct cred *saved_cred;
554 : : int ret;
555 : :
556 : : _enter(",%s", args);
557 : :
558 [ # # ]: 0 : if (strchr(args, '/'))
559 : : goto inval;
560 : :
561 [ # # ]: 0 : if (!test_bit(CACHEFILES_READY, &cache->flags)) {
562 : 0 : pr_err("cull applied to unready cache\n");
563 : 0 : return -EIO;
564 : : }
565 : :
566 [ # # ]: 0 : if (test_bit(CACHEFILES_DEAD, &cache->flags)) {
567 : 0 : pr_err("cull applied to dead cache\n");
568 : 0 : return -EIO;
569 : : }
570 : :
571 : : /* extract the directory dentry from the cwd */
572 : 0 : get_fs_pwd(current->fs, &path);
573 : :
574 [ # # ]: 0 : if (!d_can_lookup(path.dentry))
575 : : goto notdir;
576 : :
577 : : cachefiles_begin_secure(cache, &saved_cred);
578 : 0 : ret = cachefiles_cull(cache, path.dentry, args);
579 : : cachefiles_end_secure(cache, saved_cred);
580 : :
581 : 0 : path_put(&path);
582 : : _leave(" = %d", ret);
583 : 0 : return ret;
584 : :
585 : : notdir:
586 : 0 : path_put(&path);
587 : 0 : pr_err("cull command requires dirfd to be a directory\n");
588 : 0 : return -ENOTDIR;
589 : :
590 : : inval:
591 : 0 : pr_err("cull command requires dirfd and filename\n");
592 : 0 : return -EINVAL;
593 : : }
594 : :
595 : : /*
596 : : * set debugging mode
597 : : * - command: "debug <mask>"
598 : : */
599 : 0 : static int cachefiles_daemon_debug(struct cachefiles_cache *cache, char *args)
600 : : {
601 : : unsigned long mask;
602 : :
603 : : _enter(",%s", args);
604 : :
605 : 0 : mask = simple_strtoul(args, &args, 0);
606 [ # # ]: 0 : if (args[0] != '\0')
607 : : goto inval;
608 : :
609 : 0 : cachefiles_debug = mask;
610 : : _leave(" = 0");
611 : 0 : return 0;
612 : :
613 : : inval:
614 : 0 : pr_err("debug command requires mask\n");
615 : 0 : return -EINVAL;
616 : : }
617 : :
618 : : /*
619 : : * find out whether an object in the current working directory is in use or not
620 : : * - command: "inuse <name>"
621 : : */
622 : 0 : static int cachefiles_daemon_inuse(struct cachefiles_cache *cache, char *args)
623 : : {
624 : : struct path path;
625 : : const struct cred *saved_cred;
626 : : int ret;
627 : :
628 : : //_enter(",%s", args);
629 : :
630 [ # # ]: 0 : if (strchr(args, '/'))
631 : : goto inval;
632 : :
633 [ # # ]: 0 : if (!test_bit(CACHEFILES_READY, &cache->flags)) {
634 : 0 : pr_err("inuse applied to unready cache\n");
635 : 0 : return -EIO;
636 : : }
637 : :
638 [ # # ]: 0 : if (test_bit(CACHEFILES_DEAD, &cache->flags)) {
639 : 0 : pr_err("inuse applied to dead cache\n");
640 : 0 : return -EIO;
641 : : }
642 : :
643 : : /* extract the directory dentry from the cwd */
644 : 0 : get_fs_pwd(current->fs, &path);
645 : :
646 [ # # ]: 0 : if (!d_can_lookup(path.dentry))
647 : : goto notdir;
648 : :
649 : : cachefiles_begin_secure(cache, &saved_cred);
650 : 0 : ret = cachefiles_check_in_use(cache, path.dentry, args);
651 : : cachefiles_end_secure(cache, saved_cred);
652 : :
653 : 0 : path_put(&path);
654 : : //_leave(" = %d", ret);
655 : 0 : return ret;
656 : :
657 : : notdir:
658 : 0 : path_put(&path);
659 : 0 : pr_err("inuse command requires dirfd to be a directory\n");
660 : 0 : return -ENOTDIR;
661 : :
662 : : inval:
663 : 0 : pr_err("inuse command requires dirfd and filename\n");
664 : 0 : return -EINVAL;
665 : : }
666 : :
667 : : /*
668 : : * see if we have space for a number of pages and/or a number of files in the
669 : : * cache
670 : : */
671 : 0 : int cachefiles_has_space(struct cachefiles_cache *cache,
672 : : unsigned fnr, unsigned bnr)
673 : : {
674 : : struct kstatfs stats;
675 : 0 : struct path path = {
676 : 0 : .mnt = cache->mnt,
677 : 0 : .dentry = cache->mnt->mnt_root,
678 : : };
679 : : int ret;
680 : :
681 : : //_enter("{%llu,%llu,%llu,%llu,%llu,%llu},%u,%u",
682 : : // (unsigned long long) cache->frun,
683 : : // (unsigned long long) cache->fcull,
684 : : // (unsigned long long) cache->fstop,
685 : : // (unsigned long long) cache->brun,
686 : : // (unsigned long long) cache->bcull,
687 : : // (unsigned long long) cache->bstop,
688 : : // fnr, bnr);
689 : :
690 : : /* find out how many pages of blockdev are available */
691 : 0 : memset(&stats, 0, sizeof(stats));
692 : :
693 : 0 : ret = vfs_statfs(&path, &stats);
694 [ # # ]: 0 : if (ret < 0) {
695 [ # # ]: 0 : if (ret == -EIO)
696 : 0 : cachefiles_io_error(cache, "statfs failed");
697 : : _leave(" = %d", ret);
698 : 0 : return ret;
699 : : }
700 : :
701 : 0 : stats.f_bavail >>= cache->bshift;
702 : :
703 : : //_debug("avail %llu,%llu",
704 : : // (unsigned long long) stats.f_ffree,
705 : : // (unsigned long long) stats.f_bavail);
706 : :
707 : : /* see if there is sufficient space */
708 [ # # ]: 0 : if (stats.f_ffree > fnr)
709 : 0 : stats.f_ffree -= fnr;
710 : : else
711 : 0 : stats.f_ffree = 0;
712 : :
713 [ # # ]: 0 : if (stats.f_bavail > bnr)
714 : 0 : stats.f_bavail -= bnr;
715 : : else
716 : 0 : stats.f_bavail = 0;
717 : :
718 : : ret = -ENOBUFS;
719 [ # # # # ]: 0 : if (stats.f_ffree < cache->fstop ||
720 : 0 : stats.f_bavail < cache->bstop)
721 : : goto begin_cull;
722 : :
723 : : ret = 0;
724 [ # # # # ]: 0 : if (stats.f_ffree < cache->fcull ||
725 : 0 : stats.f_bavail < cache->bcull)
726 : : goto begin_cull;
727 : :
728 [ # # # # ]: 0 : if (test_bit(CACHEFILES_CULLING, &cache->flags) &&
729 [ # # ]: 0 : stats.f_ffree >= cache->frun &&
730 [ # # ]: 0 : stats.f_bavail >= cache->brun &&
731 : 0 : test_and_clear_bit(CACHEFILES_CULLING, &cache->flags)
732 : : ) {
733 : : _debug("cease culling");
734 : 0 : cachefiles_state_changed(cache);
735 : : }
736 : :
737 : : //_leave(" = 0");
738 : : return 0;
739 : :
740 : : begin_cull:
741 [ # # ]: 0 : if (!test_and_set_bit(CACHEFILES_CULLING, &cache->flags)) {
742 : : _debug("### CULL CACHE ###");
743 : 0 : cachefiles_state_changed(cache);
744 : : }
745 : :
746 : : _leave(" = %d", ret);
747 : 0 : return ret;
748 : : }
|