diff options
Diffstat (limited to 'fs/dcache.c')
-rw-r--r-- | fs/dcache.c | 82 |
1 files changed, 54 insertions, 28 deletions
diff --git a/fs/dcache.c b/fs/dcache.c index a901c6901bce..89509b5a090e 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/bit_spinlock.h> | 36 | #include <linux/bit_spinlock.h> |
37 | #include <linux/rculist_bl.h> | 37 | #include <linux/rculist_bl.h> |
38 | #include <linux/prefetch.h> | 38 | #include <linux/prefetch.h> |
39 | #include <linux/ratelimit.h> | ||
39 | #include "internal.h" | 40 | #include "internal.h" |
40 | 41 | ||
41 | /* | 42 | /* |
@@ -2383,8 +2384,16 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode) | |||
2383 | actual = __d_unalias(inode, dentry, alias); | 2384 | actual = __d_unalias(inode, dentry, alias); |
2384 | } | 2385 | } |
2385 | write_sequnlock(&rename_lock); | 2386 | write_sequnlock(&rename_lock); |
2386 | if (IS_ERR(actual)) | 2387 | if (IS_ERR(actual)) { |
2388 | if (PTR_ERR(actual) == -ELOOP) | ||
2389 | pr_warn_ratelimited( | ||
2390 | "VFS: Lookup of '%s' in %s %s" | ||
2391 | " would have caused loop\n", | ||
2392 | dentry->d_name.name, | ||
2393 | inode->i_sb->s_type->name, | ||
2394 | inode->i_sb->s_id); | ||
2387 | dput(alias); | 2395 | dput(alias); |
2396 | } | ||
2388 | goto out_nolock; | 2397 | goto out_nolock; |
2389 | } | 2398 | } |
2390 | } | 2399 | } |
@@ -2430,16 +2439,14 @@ static int prepend_name(char **buffer, int *buflen, struct qstr *name) | |||
2430 | /** | 2439 | /** |
2431 | * prepend_path - Prepend path string to a buffer | 2440 | * prepend_path - Prepend path string to a buffer |
2432 | * @path: the dentry/vfsmount to report | 2441 | * @path: the dentry/vfsmount to report |
2433 | * @root: root vfsmnt/dentry (may be modified by this function) | 2442 | * @root: root vfsmnt/dentry |
2434 | * @buffer: pointer to the end of the buffer | 2443 | * @buffer: pointer to the end of the buffer |
2435 | * @buflen: pointer to buffer length | 2444 | * @buflen: pointer to buffer length |
2436 | * | 2445 | * |
2437 | * Caller holds the rename_lock. | 2446 | * Caller holds the rename_lock. |
2438 | * | ||
2439 | * If path is not reachable from the supplied root, then the value of | ||
2440 | * root is changed (without modifying refcounts). | ||
2441 | */ | 2447 | */ |
2442 | static int prepend_path(const struct path *path, struct path *root, | 2448 | static int prepend_path(const struct path *path, |
2449 | const struct path *root, | ||
2443 | char **buffer, int *buflen) | 2450 | char **buffer, int *buflen) |
2444 | { | 2451 | { |
2445 | struct dentry *dentry = path->dentry; | 2452 | struct dentry *dentry = path->dentry; |
@@ -2474,10 +2481,10 @@ static int prepend_path(const struct path *path, struct path *root, | |||
2474 | dentry = parent; | 2481 | dentry = parent; |
2475 | } | 2482 | } |
2476 | 2483 | ||
2477 | out: | ||
2478 | if (!error && !slash) | 2484 | if (!error && !slash) |
2479 | error = prepend(buffer, buflen, "/", 1); | 2485 | error = prepend(buffer, buflen, "/", 1); |
2480 | 2486 | ||
2487 | out: | ||
2481 | br_read_unlock(vfsmount_lock); | 2488 | br_read_unlock(vfsmount_lock); |
2482 | return error; | 2489 | return error; |
2483 | 2490 | ||
@@ -2491,15 +2498,17 @@ global_root: | |||
2491 | WARN(1, "Root dentry has weird name <%.*s>\n", | 2498 | WARN(1, "Root dentry has weird name <%.*s>\n", |
2492 | (int) dentry->d_name.len, dentry->d_name.name); | 2499 | (int) dentry->d_name.len, dentry->d_name.name); |
2493 | } | 2500 | } |
2494 | root->mnt = vfsmnt; | 2501 | if (!slash) |
2495 | root->dentry = dentry; | 2502 | error = prepend(buffer, buflen, "/", 1); |
2503 | if (!error) | ||
2504 | error = vfsmnt->mnt_ns ? 1 : 2; | ||
2496 | goto out; | 2505 | goto out; |
2497 | } | 2506 | } |
2498 | 2507 | ||
2499 | /** | 2508 | /** |
2500 | * __d_path - return the path of a dentry | 2509 | * __d_path - return the path of a dentry |
2501 | * @path: the dentry/vfsmount to report | 2510 | * @path: the dentry/vfsmount to report |
2502 | * @root: root vfsmnt/dentry (may be modified by this function) | 2511 | * @root: root vfsmnt/dentry |
2503 | * @buf: buffer to return value in | 2512 | * @buf: buffer to return value in |
2504 | * @buflen: buffer length | 2513 | * @buflen: buffer length |
2505 | * | 2514 | * |
@@ -2510,10 +2519,10 @@ global_root: | |||
2510 | * | 2519 | * |
2511 | * "buflen" should be positive. | 2520 | * "buflen" should be positive. |
2512 | * | 2521 | * |
2513 | * If path is not reachable from the supplied root, then the value of | 2522 | * If the path is not reachable from the supplied root, return %NULL. |
2514 | * root is changed (without modifying refcounts). | ||
2515 | */ | 2523 | */ |
2516 | char *__d_path(const struct path *path, struct path *root, | 2524 | char *__d_path(const struct path *path, |
2525 | const struct path *root, | ||
2517 | char *buf, int buflen) | 2526 | char *buf, int buflen) |
2518 | { | 2527 | { |
2519 | char *res = buf + buflen; | 2528 | char *res = buf + buflen; |
@@ -2524,7 +2533,28 @@ char *__d_path(const struct path *path, struct path *root, | |||
2524 | error = prepend_path(path, root, &res, &buflen); | 2533 | error = prepend_path(path, root, &res, &buflen); |
2525 | write_sequnlock(&rename_lock); | 2534 | write_sequnlock(&rename_lock); |
2526 | 2535 | ||
2527 | if (error) | 2536 | if (error < 0) |
2537 | return ERR_PTR(error); | ||
2538 | if (error > 0) | ||
2539 | return NULL; | ||
2540 | return res; | ||
2541 | } | ||
2542 | |||
2543 | char *d_absolute_path(const struct path *path, | ||
2544 | char *buf, int buflen) | ||
2545 | { | ||
2546 | struct path root = {}; | ||
2547 | char *res = buf + buflen; | ||
2548 | int error; | ||
2549 | |||
2550 | prepend(&res, &buflen, "\0", 1); | ||
2551 | write_seqlock(&rename_lock); | ||
2552 | error = prepend_path(path, &root, &res, &buflen); | ||
2553 | write_sequnlock(&rename_lock); | ||
2554 | |||
2555 | if (error > 1) | ||
2556 | error = -EINVAL; | ||
2557 | if (error < 0) | ||
2528 | return ERR_PTR(error); | 2558 | return ERR_PTR(error); |
2529 | return res; | 2559 | return res; |
2530 | } | 2560 | } |
@@ -2532,8 +2562,9 @@ char *__d_path(const struct path *path, struct path *root, | |||
2532 | /* | 2562 | /* |
2533 | * same as __d_path but appends "(deleted)" for unlinked files. | 2563 | * same as __d_path but appends "(deleted)" for unlinked files. |
2534 | */ | 2564 | */ |
2535 | static int path_with_deleted(const struct path *path, struct path *root, | 2565 | static int path_with_deleted(const struct path *path, |
2536 | char **buf, int *buflen) | 2566 | const struct path *root, |
2567 | char **buf, int *buflen) | ||
2537 | { | 2568 | { |
2538 | prepend(buf, buflen, "\0", 1); | 2569 | prepend(buf, buflen, "\0", 1); |
2539 | if (d_unlinked(path->dentry)) { | 2570 | if (d_unlinked(path->dentry)) { |
@@ -2570,7 +2601,6 @@ char *d_path(const struct path *path, char *buf, int buflen) | |||
2570 | { | 2601 | { |
2571 | char *res = buf + buflen; | 2602 | char *res = buf + buflen; |
2572 | struct path root; | 2603 | struct path root; |
2573 | struct path tmp; | ||
2574 | int error; | 2604 | int error; |
2575 | 2605 | ||
2576 | /* | 2606 | /* |
@@ -2585,9 +2615,8 @@ char *d_path(const struct path *path, char *buf, int buflen) | |||
2585 | 2615 | ||
2586 | get_fs_root(current->fs, &root); | 2616 | get_fs_root(current->fs, &root); |
2587 | write_seqlock(&rename_lock); | 2617 | write_seqlock(&rename_lock); |
2588 | tmp = root; | 2618 | error = path_with_deleted(path, &root, &res, &buflen); |
2589 | error = path_with_deleted(path, &tmp, &res, &buflen); | 2619 | if (error < 0) |
2590 | if (error) | ||
2591 | res = ERR_PTR(error); | 2620 | res = ERR_PTR(error); |
2592 | write_sequnlock(&rename_lock); | 2621 | write_sequnlock(&rename_lock); |
2593 | path_put(&root); | 2622 | path_put(&root); |
@@ -2608,7 +2637,6 @@ char *d_path_with_unreachable(const struct path *path, char *buf, int buflen) | |||
2608 | { | 2637 | { |
2609 | char *res = buf + buflen; | 2638 | char *res = buf + buflen; |
2610 | struct path root; | 2639 | struct path root; |
2611 | struct path tmp; | ||
2612 | int error; | 2640 | int error; |
2613 | 2641 | ||
2614 | if (path->dentry->d_op && path->dentry->d_op->d_dname) | 2642 | if (path->dentry->d_op && path->dentry->d_op->d_dname) |
@@ -2616,9 +2644,8 @@ char *d_path_with_unreachable(const struct path *path, char *buf, int buflen) | |||
2616 | 2644 | ||
2617 | get_fs_root(current->fs, &root); | 2645 | get_fs_root(current->fs, &root); |
2618 | write_seqlock(&rename_lock); | 2646 | write_seqlock(&rename_lock); |
2619 | tmp = root; | 2647 | error = path_with_deleted(path, &root, &res, &buflen); |
2620 | error = path_with_deleted(path, &tmp, &res, &buflen); | 2648 | if (error > 0) |
2621 | if (!error && !path_equal(&tmp, &root)) | ||
2622 | error = prepend_unreachable(&res, &buflen); | 2649 | error = prepend_unreachable(&res, &buflen); |
2623 | write_sequnlock(&rename_lock); | 2650 | write_sequnlock(&rename_lock); |
2624 | path_put(&root); | 2651 | path_put(&root); |
@@ -2749,19 +2776,18 @@ SYSCALL_DEFINE2(getcwd, char __user *, buf, unsigned long, size) | |||
2749 | write_seqlock(&rename_lock); | 2776 | write_seqlock(&rename_lock); |
2750 | if (!d_unlinked(pwd.dentry)) { | 2777 | if (!d_unlinked(pwd.dentry)) { |
2751 | unsigned long len; | 2778 | unsigned long len; |
2752 | struct path tmp = root; | ||
2753 | char *cwd = page + PAGE_SIZE; | 2779 | char *cwd = page + PAGE_SIZE; |
2754 | int buflen = PAGE_SIZE; | 2780 | int buflen = PAGE_SIZE; |
2755 | 2781 | ||
2756 | prepend(&cwd, &buflen, "\0", 1); | 2782 | prepend(&cwd, &buflen, "\0", 1); |
2757 | error = prepend_path(&pwd, &tmp, &cwd, &buflen); | 2783 | error = prepend_path(&pwd, &root, &cwd, &buflen); |
2758 | write_sequnlock(&rename_lock); | 2784 | write_sequnlock(&rename_lock); |
2759 | 2785 | ||
2760 | if (error) | 2786 | if (error < 0) |
2761 | goto out; | 2787 | goto out; |
2762 | 2788 | ||
2763 | /* Unreachable from current root */ | 2789 | /* Unreachable from current root */ |
2764 | if (!path_equal(&tmp, &root)) { | 2790 | if (error > 0) { |
2765 | error = prepend_unreachable(&cwd, &buflen); | 2791 | error = prepend_unreachable(&cwd, &buflen); |
2766 | if (error) | 2792 | if (error) |
2767 | goto out; | 2793 | goto out; |