diff options
-rw-r--r-- | fs/dcache.c | 42 | ||||
-rw-r--r-- | fs/namei.c | 95 | ||||
-rw-r--r-- | include/linux/dcache.h | 103 |
3 files changed, 158 insertions, 82 deletions
diff --git a/fs/dcache.c b/fs/dcache.c index fb7bcf3ba5d6..525770e576db 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -343,6 +343,7 @@ static void dentry_unlink_inode(struct dentry * dentry) | |||
343 | __releases(dentry->d_inode->i_lock) | 343 | __releases(dentry->d_inode->i_lock) |
344 | { | 344 | { |
345 | struct inode *inode = dentry->d_inode; | 345 | struct inode *inode = dentry->d_inode; |
346 | __d_clear_type(dentry); | ||
346 | dentry->d_inode = NULL; | 347 | dentry->d_inode = NULL; |
347 | hlist_del_init(&dentry->d_alias); | 348 | hlist_del_init(&dentry->d_alias); |
348 | dentry_rcuwalk_barrier(dentry); | 349 | dentry_rcuwalk_barrier(dentry); |
@@ -1648,14 +1649,42 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op) | |||
1648 | } | 1649 | } |
1649 | EXPORT_SYMBOL(d_set_d_op); | 1650 | EXPORT_SYMBOL(d_set_d_op); |
1650 | 1651 | ||
1652 | static unsigned d_flags_for_inode(struct inode *inode) | ||
1653 | { | ||
1654 | unsigned add_flags = DCACHE_FILE_TYPE; | ||
1655 | |||
1656 | if (!inode) | ||
1657 | return DCACHE_MISS_TYPE; | ||
1658 | |||
1659 | if (S_ISDIR(inode->i_mode)) { | ||
1660 | add_flags = DCACHE_DIRECTORY_TYPE; | ||
1661 | if (unlikely(!(inode->i_opflags & IOP_LOOKUP))) { | ||
1662 | if (unlikely(!inode->i_op->lookup)) | ||
1663 | add_flags = DCACHE_AUTODIR_TYPE; | ||
1664 | else | ||
1665 | inode->i_opflags |= IOP_LOOKUP; | ||
1666 | } | ||
1667 | } else if (unlikely(!(inode->i_opflags & IOP_NOFOLLOW))) { | ||
1668 | if (unlikely(inode->i_op->follow_link)) | ||
1669 | add_flags = DCACHE_SYMLINK_TYPE; | ||
1670 | else | ||
1671 | inode->i_opflags |= IOP_NOFOLLOW; | ||
1672 | } | ||
1673 | |||
1674 | if (unlikely(IS_AUTOMOUNT(inode))) | ||
1675 | add_flags |= DCACHE_NEED_AUTOMOUNT; | ||
1676 | return add_flags; | ||
1677 | } | ||
1678 | |||
1651 | static void __d_instantiate(struct dentry *dentry, struct inode *inode) | 1679 | static void __d_instantiate(struct dentry *dentry, struct inode *inode) |
1652 | { | 1680 | { |
1681 | unsigned add_flags = d_flags_for_inode(inode); | ||
1682 | |||
1653 | spin_lock(&dentry->d_lock); | 1683 | spin_lock(&dentry->d_lock); |
1654 | if (inode) { | 1684 | dentry->d_flags &= ~DCACHE_ENTRY_TYPE; |
1655 | if (unlikely(IS_AUTOMOUNT(inode))) | 1685 | dentry->d_flags |= add_flags; |
1656 | dentry->d_flags |= DCACHE_NEED_AUTOMOUNT; | 1686 | if (inode) |
1657 | hlist_add_head(&dentry->d_alias, &inode->i_dentry); | 1687 | hlist_add_head(&dentry->d_alias, &inode->i_dentry); |
1658 | } | ||
1659 | dentry->d_inode = inode; | 1688 | dentry->d_inode = inode; |
1660 | dentry_rcuwalk_barrier(dentry); | 1689 | dentry_rcuwalk_barrier(dentry); |
1661 | spin_unlock(&dentry->d_lock); | 1690 | spin_unlock(&dentry->d_lock); |
@@ -1860,6 +1889,7 @@ struct dentry *d_obtain_alias(struct inode *inode) | |||
1860 | static const struct qstr anonstring = QSTR_INIT("/", 1); | 1889 | static const struct qstr anonstring = QSTR_INIT("/", 1); |
1861 | struct dentry *tmp; | 1890 | struct dentry *tmp; |
1862 | struct dentry *res; | 1891 | struct dentry *res; |
1892 | unsigned add_flags; | ||
1863 | 1893 | ||
1864 | if (!inode) | 1894 | if (!inode) |
1865 | return ERR_PTR(-ESTALE); | 1895 | return ERR_PTR(-ESTALE); |
@@ -1885,9 +1915,11 @@ struct dentry *d_obtain_alias(struct inode *inode) | |||
1885 | } | 1915 | } |
1886 | 1916 | ||
1887 | /* attach a disconnected dentry */ | 1917 | /* attach a disconnected dentry */ |
1918 | add_flags = d_flags_for_inode(inode) | DCACHE_DISCONNECTED; | ||
1919 | |||
1888 | spin_lock(&tmp->d_lock); | 1920 | spin_lock(&tmp->d_lock); |
1889 | tmp->d_inode = inode; | 1921 | tmp->d_inode = inode; |
1890 | tmp->d_flags |= DCACHE_DISCONNECTED; | 1922 | tmp->d_flags |= add_flags; |
1891 | hlist_add_head(&tmp->d_alias, &inode->i_dentry); | 1923 | hlist_add_head(&tmp->d_alias, &inode->i_dentry); |
1892 | hlist_bl_lock(&tmp->d_sb->s_anon); | 1924 | hlist_bl_lock(&tmp->d_sb->s_anon); |
1893 | hlist_bl_add_head(&tmp->d_hash, &tmp->d_sb->s_anon); | 1925 | hlist_bl_add_head(&tmp->d_hash, &tmp->d_sb->s_anon); |
diff --git a/fs/namei.c b/fs/namei.c index e5c0118ba9f8..e1fa43346c61 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -1501,18 +1501,9 @@ static void terminate_walk(struct nameidata *nd) | |||
1501 | * so we keep a cache of "no, this doesn't need follow_link" | 1501 | * so we keep a cache of "no, this doesn't need follow_link" |
1502 | * for the common case. | 1502 | * for the common case. |
1503 | */ | 1503 | */ |
1504 | static inline int should_follow_link(struct inode *inode, int follow) | 1504 | static inline int should_follow_link(struct dentry *dentry, int follow) |
1505 | { | 1505 | { |
1506 | if (unlikely(!(inode->i_opflags & IOP_NOFOLLOW))) { | 1506 | return unlikely(d_is_symlink(dentry)) ? follow : 0; |
1507 | if (likely(inode->i_op->follow_link)) | ||
1508 | return follow; | ||
1509 | |||
1510 | /* This gets set once for the inode lifetime */ | ||
1511 | spin_lock(&inode->i_lock); | ||
1512 | inode->i_opflags |= IOP_NOFOLLOW; | ||
1513 | spin_unlock(&inode->i_lock); | ||
1514 | } | ||
1515 | return 0; | ||
1516 | } | 1507 | } |
1517 | 1508 | ||
1518 | static inline int walk_component(struct nameidata *nd, struct path *path, | 1509 | static inline int walk_component(struct nameidata *nd, struct path *path, |
@@ -1542,7 +1533,7 @@ static inline int walk_component(struct nameidata *nd, struct path *path, | |||
1542 | if (!inode) | 1533 | if (!inode) |
1543 | goto out_path_put; | 1534 | goto out_path_put; |
1544 | 1535 | ||
1545 | if (should_follow_link(inode, follow)) { | 1536 | if (should_follow_link(path->dentry, follow)) { |
1546 | if (nd->flags & LOOKUP_RCU) { | 1537 | if (nd->flags & LOOKUP_RCU) { |
1547 | if (unlikely(unlazy_walk(nd, path->dentry))) { | 1538 | if (unlikely(unlazy_walk(nd, path->dentry))) { |
1548 | err = -ECHILD; | 1539 | err = -ECHILD; |
@@ -1601,26 +1592,6 @@ static inline int nested_symlink(struct path *path, struct nameidata *nd) | |||
1601 | } | 1592 | } |
1602 | 1593 | ||
1603 | /* | 1594 | /* |
1604 | * We really don't want to look at inode->i_op->lookup | ||
1605 | * when we don't have to. So we keep a cache bit in | ||
1606 | * the inode ->i_opflags field that says "yes, we can | ||
1607 | * do lookup on this inode". | ||
1608 | */ | ||
1609 | static inline int can_lookup(struct inode *inode) | ||
1610 | { | ||
1611 | if (likely(inode->i_opflags & IOP_LOOKUP)) | ||
1612 | return 1; | ||
1613 | if (likely(!inode->i_op->lookup)) | ||
1614 | return 0; | ||
1615 | |||
1616 | /* We do this once for the lifetime of the inode */ | ||
1617 | spin_lock(&inode->i_lock); | ||
1618 | inode->i_opflags |= IOP_LOOKUP; | ||
1619 | spin_unlock(&inode->i_lock); | ||
1620 | return 1; | ||
1621 | } | ||
1622 | |||
1623 | /* | ||
1624 | * We can do the critical dentry name comparison and hashing | 1595 | * We can do the critical dentry name comparison and hashing |
1625 | * operations one word at a time, but we are limited to: | 1596 | * operations one word at a time, but we are limited to: |
1626 | * | 1597 | * |
@@ -1823,7 +1794,7 @@ static int link_path_walk(const char *name, struct nameidata *nd) | |||
1823 | if (err) | 1794 | if (err) |
1824 | return err; | 1795 | return err; |
1825 | } | 1796 | } |
1826 | if (!can_lookup(nd->inode)) { | 1797 | if (!d_is_directory(nd->path.dentry)) { |
1827 | err = -ENOTDIR; | 1798 | err = -ENOTDIR; |
1828 | break; | 1799 | break; |
1829 | } | 1800 | } |
@@ -1841,9 +1812,10 @@ static int path_init(int dfd, const char *name, unsigned int flags, | |||
1841 | nd->flags = flags | LOOKUP_JUMPED; | 1812 | nd->flags = flags | LOOKUP_JUMPED; |
1842 | nd->depth = 0; | 1813 | nd->depth = 0; |
1843 | if (flags & LOOKUP_ROOT) { | 1814 | if (flags & LOOKUP_ROOT) { |
1844 | struct inode *inode = nd->root.dentry->d_inode; | 1815 | struct dentry *root = nd->root.dentry; |
1816 | struct inode *inode = root->d_inode; | ||
1845 | if (*name) { | 1817 | if (*name) { |
1846 | if (!can_lookup(inode)) | 1818 | if (!d_is_directory(root)) |
1847 | return -ENOTDIR; | 1819 | return -ENOTDIR; |
1848 | retval = inode_permission(inode, MAY_EXEC); | 1820 | retval = inode_permission(inode, MAY_EXEC); |
1849 | if (retval) | 1821 | if (retval) |
@@ -1899,7 +1871,7 @@ static int path_init(int dfd, const char *name, unsigned int flags, | |||
1899 | dentry = f.file->f_path.dentry; | 1871 | dentry = f.file->f_path.dentry; |
1900 | 1872 | ||
1901 | if (*name) { | 1873 | if (*name) { |
1902 | if (!can_lookup(dentry->d_inode)) { | 1874 | if (!d_is_directory(dentry)) { |
1903 | fdput(f); | 1875 | fdput(f); |
1904 | return -ENOTDIR; | 1876 | return -ENOTDIR; |
1905 | } | 1877 | } |
@@ -1981,7 +1953,7 @@ static int path_lookupat(int dfd, const char *name, | |||
1981 | err = complete_walk(nd); | 1953 | err = complete_walk(nd); |
1982 | 1954 | ||
1983 | if (!err && nd->flags & LOOKUP_DIRECTORY) { | 1955 | if (!err && nd->flags & LOOKUP_DIRECTORY) { |
1984 | if (!can_lookup(nd->inode)) { | 1956 | if (!d_is_directory(nd->path.dentry)) { |
1985 | path_put(&nd->path); | 1957 | path_put(&nd->path); |
1986 | err = -ENOTDIR; | 1958 | err = -ENOTDIR; |
1987 | } | 1959 | } |
@@ -2273,7 +2245,7 @@ done: | |||
2273 | } | 2245 | } |
2274 | path->dentry = dentry; | 2246 | path->dentry = dentry; |
2275 | path->mnt = mntget(nd->path.mnt); | 2247 | path->mnt = mntget(nd->path.mnt); |
2276 | if (should_follow_link(dentry->d_inode, nd->flags & LOOKUP_FOLLOW)) | 2248 | if (should_follow_link(dentry, nd->flags & LOOKUP_FOLLOW)) |
2277 | return 1; | 2249 | return 1; |
2278 | follow_mount(path); | 2250 | follow_mount(path); |
2279 | error = 0; | 2251 | error = 0; |
@@ -2417,12 +2389,14 @@ static inline int check_sticky(struct inode *dir, struct inode *inode) | |||
2417 | * 10. We don't allow removal of NFS sillyrenamed files; it's handled by | 2389 | * 10. We don't allow removal of NFS sillyrenamed files; it's handled by |
2418 | * nfs_async_unlink(). | 2390 | * nfs_async_unlink(). |
2419 | */ | 2391 | */ |
2420 | static int may_delete(struct inode *dir,struct dentry *victim,int isdir) | 2392 | static int may_delete(struct inode *dir, struct dentry *victim, bool isdir) |
2421 | { | 2393 | { |
2394 | struct inode *inode = victim->d_inode; | ||
2422 | int error; | 2395 | int error; |
2423 | 2396 | ||
2424 | if (!victim->d_inode) | 2397 | if (d_is_negative(victim)) |
2425 | return -ENOENT; | 2398 | return -ENOENT; |
2399 | BUG_ON(!inode); | ||
2426 | 2400 | ||
2427 | BUG_ON(victim->d_parent->d_inode != dir); | 2401 | BUG_ON(victim->d_parent->d_inode != dir); |
2428 | audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE); | 2402 | audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE); |
@@ -2432,15 +2406,16 @@ static int may_delete(struct inode *dir,struct dentry *victim,int isdir) | |||
2432 | return error; | 2406 | return error; |
2433 | if (IS_APPEND(dir)) | 2407 | if (IS_APPEND(dir)) |
2434 | return -EPERM; | 2408 | return -EPERM; |
2435 | if (check_sticky(dir, victim->d_inode)||IS_APPEND(victim->d_inode)|| | 2409 | |
2436 | IS_IMMUTABLE(victim->d_inode) || IS_SWAPFILE(victim->d_inode)) | 2410 | if (check_sticky(dir, inode) || IS_APPEND(inode) || |
2411 | IS_IMMUTABLE(inode) || IS_SWAPFILE(inode)) | ||
2437 | return -EPERM; | 2412 | return -EPERM; |
2438 | if (isdir) { | 2413 | if (isdir) { |
2439 | if (!S_ISDIR(victim->d_inode->i_mode)) | 2414 | if (!d_is_directory(victim) && !d_is_autodir(victim)) |
2440 | return -ENOTDIR; | 2415 | return -ENOTDIR; |
2441 | if (IS_ROOT(victim)) | 2416 | if (IS_ROOT(victim)) |
2442 | return -EBUSY; | 2417 | return -EBUSY; |
2443 | } else if (S_ISDIR(victim->d_inode->i_mode)) | 2418 | } else if (d_is_directory(victim) || d_is_autodir(victim)) |
2444 | return -EISDIR; | 2419 | return -EISDIR; |
2445 | if (IS_DEADDIR(dir)) | 2420 | if (IS_DEADDIR(dir)) |
2446 | return -ENOENT; | 2421 | return -ENOENT; |
@@ -2974,7 +2949,7 @@ retry_lookup: | |||
2974 | /* | 2949 | /* |
2975 | * create/update audit record if it already exists. | 2950 | * create/update audit record if it already exists. |
2976 | */ | 2951 | */ |
2977 | if (path->dentry->d_inode) | 2952 | if (d_is_positive(path->dentry)) |
2978 | audit_inode(name, path->dentry, 0); | 2953 | audit_inode(name, path->dentry, 0); |
2979 | 2954 | ||
2980 | /* | 2955 | /* |
@@ -3003,12 +2978,12 @@ retry_lookup: | |||
3003 | finish_lookup: | 2978 | finish_lookup: |
3004 | /* we _can_ be in RCU mode here */ | 2979 | /* we _can_ be in RCU mode here */ |
3005 | error = -ENOENT; | 2980 | error = -ENOENT; |
3006 | if (!inode) { | 2981 | if (d_is_negative(path->dentry)) { |
3007 | path_to_nameidata(path, nd); | 2982 | path_to_nameidata(path, nd); |
3008 | goto out; | 2983 | goto out; |
3009 | } | 2984 | } |
3010 | 2985 | ||
3011 | if (should_follow_link(inode, !symlink_ok)) { | 2986 | if (should_follow_link(path->dentry, !symlink_ok)) { |
3012 | if (nd->flags & LOOKUP_RCU) { | 2987 | if (nd->flags & LOOKUP_RCU) { |
3013 | if (unlikely(unlazy_walk(nd, path->dentry))) { | 2988 | if (unlikely(unlazy_walk(nd, path->dentry))) { |
3014 | error = -ECHILD; | 2989 | error = -ECHILD; |
@@ -3037,10 +3012,11 @@ finish_open: | |||
3037 | } | 3012 | } |
3038 | audit_inode(name, nd->path.dentry, 0); | 3013 | audit_inode(name, nd->path.dentry, 0); |
3039 | error = -EISDIR; | 3014 | error = -EISDIR; |
3040 | if ((open_flag & O_CREAT) && S_ISDIR(nd->inode->i_mode)) | 3015 | if ((open_flag & O_CREAT) && |
3016 | (d_is_directory(nd->path.dentry) || d_is_autodir(nd->path.dentry))) | ||
3041 | goto out; | 3017 | goto out; |
3042 | error = -ENOTDIR; | 3018 | error = -ENOTDIR; |
3043 | if ((nd->flags & LOOKUP_DIRECTORY) && !can_lookup(nd->inode)) | 3019 | if ((nd->flags & LOOKUP_DIRECTORY) && !d_is_directory(nd->path.dentry)) |
3044 | goto out; | 3020 | goto out; |
3045 | if (!S_ISREG(nd->inode->i_mode)) | 3021 | if (!S_ISREG(nd->inode->i_mode)) |
3046 | will_truncate = false; | 3022 | will_truncate = false; |
@@ -3266,7 +3242,7 @@ struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt, | |||
3266 | nd.root.mnt = mnt; | 3242 | nd.root.mnt = mnt; |
3267 | nd.root.dentry = dentry; | 3243 | nd.root.dentry = dentry; |
3268 | 3244 | ||
3269 | if (dentry->d_inode->i_op->follow_link && op->intent & LOOKUP_OPEN) | 3245 | if (d_is_symlink(dentry) && op->intent & LOOKUP_OPEN) |
3270 | return ERR_PTR(-ELOOP); | 3246 | return ERR_PTR(-ELOOP); |
3271 | 3247 | ||
3272 | file = path_openat(-1, &filename, &nd, op, flags | LOOKUP_RCU); | 3248 | file = path_openat(-1, &filename, &nd, op, flags | LOOKUP_RCU); |
@@ -3316,8 +3292,9 @@ struct dentry *kern_path_create(int dfd, const char *pathname, | |||
3316 | goto unlock; | 3292 | goto unlock; |
3317 | 3293 | ||
3318 | error = -EEXIST; | 3294 | error = -EEXIST; |
3319 | if (dentry->d_inode) | 3295 | if (d_is_positive(dentry)) |
3320 | goto fail; | 3296 | goto fail; |
3297 | |||
3321 | /* | 3298 | /* |
3322 | * Special case - lookup gave negative, but... we had foo/bar/ | 3299 | * Special case - lookup gave negative, but... we had foo/bar/ |
3323 | * From the vfs_mknod() POV we just have a negative dentry - | 3300 | * From the vfs_mknod() POV we just have a negative dentry - |
@@ -3706,7 +3683,7 @@ retry: | |||
3706 | if (nd.last.name[nd.last.len]) | 3683 | if (nd.last.name[nd.last.len]) |
3707 | goto slashes; | 3684 | goto slashes; |
3708 | inode = dentry->d_inode; | 3685 | inode = dentry->d_inode; |
3709 | if (!inode) | 3686 | if (d_is_negative(dentry)) |
3710 | goto slashes; | 3687 | goto slashes; |
3711 | ihold(inode); | 3688 | ihold(inode); |
3712 | error = security_path_unlink(&nd.path, dentry); | 3689 | error = security_path_unlink(&nd.path, dentry); |
@@ -3731,8 +3708,12 @@ exit1: | |||
3731 | return error; | 3708 | return error; |
3732 | 3709 | ||
3733 | slashes: | 3710 | slashes: |
3734 | error = !dentry->d_inode ? -ENOENT : | 3711 | if (d_is_negative(dentry)) |
3735 | S_ISDIR(dentry->d_inode->i_mode) ? -EISDIR : -ENOTDIR; | 3712 | error = -ENOENT; |
3713 | else if (d_is_directory(dentry) || d_is_autodir(dentry)) | ||
3714 | error = -EISDIR; | ||
3715 | else | ||
3716 | error = -ENOTDIR; | ||
3736 | goto exit2; | 3717 | goto exit2; |
3737 | } | 3718 | } |
3738 | 3719 | ||
@@ -4046,7 +4027,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
4046 | struct inode *new_dir, struct dentry *new_dentry) | 4027 | struct inode *new_dir, struct dentry *new_dentry) |
4047 | { | 4028 | { |
4048 | int error; | 4029 | int error; |
4049 | int is_dir = S_ISDIR(old_dentry->d_inode->i_mode); | 4030 | int is_dir = d_is_directory(old_dentry) || d_is_autodir(old_dentry); |
4050 | const unsigned char *old_name; | 4031 | const unsigned char *old_name; |
4051 | 4032 | ||
4052 | if (old_dentry->d_inode == new_dentry->d_inode) | 4033 | if (old_dentry->d_inode == new_dentry->d_inode) |
@@ -4134,10 +4115,10 @@ retry: | |||
4134 | goto exit3; | 4115 | goto exit3; |
4135 | /* source must exist */ | 4116 | /* source must exist */ |
4136 | error = -ENOENT; | 4117 | error = -ENOENT; |
4137 | if (!old_dentry->d_inode) | 4118 | if (d_is_negative(old_dentry)) |
4138 | goto exit4; | 4119 | goto exit4; |
4139 | /* unless the source is a directory trailing slashes give -ENOTDIR */ | 4120 | /* unless the source is a directory trailing slashes give -ENOTDIR */ |
4140 | if (!S_ISDIR(old_dentry->d_inode->i_mode)) { | 4121 | if (!d_is_directory(old_dentry) && !d_is_autodir(old_dentry)) { |
4141 | error = -ENOTDIR; | 4122 | error = -ENOTDIR; |
4142 | if (oldnd.last.name[oldnd.last.len]) | 4123 | if (oldnd.last.name[oldnd.last.len]) |
4143 | goto exit4; | 4124 | goto exit4; |
diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 716c3760ee39..57e87e749a48 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h | |||
@@ -169,13 +169,13 @@ struct dentry_operations { | |||
169 | */ | 169 | */ |
170 | 170 | ||
171 | /* d_flags entries */ | 171 | /* d_flags entries */ |
172 | #define DCACHE_OP_HASH 0x0001 | 172 | #define DCACHE_OP_HASH 0x00000001 |
173 | #define DCACHE_OP_COMPARE 0x0002 | 173 | #define DCACHE_OP_COMPARE 0x00000002 |
174 | #define DCACHE_OP_REVALIDATE 0x0004 | 174 | #define DCACHE_OP_REVALIDATE 0x00000004 |
175 | #define DCACHE_OP_DELETE 0x0008 | 175 | #define DCACHE_OP_DELETE 0x00000008 |
176 | #define DCACHE_OP_PRUNE 0x0010 | 176 | #define DCACHE_OP_PRUNE 0x00000010 |
177 | 177 | ||
178 | #define DCACHE_DISCONNECTED 0x0020 | 178 | #define DCACHE_DISCONNECTED 0x00000020 |
179 | /* This dentry is possibly not currently connected to the dcache tree, in | 179 | /* This dentry is possibly not currently connected to the dcache tree, in |
180 | * which case its parent will either be itself, or will have this flag as | 180 | * which case its parent will either be itself, or will have this flag as |
181 | * well. nfsd will not use a dentry with this bit set, but will first | 181 | * well. nfsd will not use a dentry with this bit set, but will first |
@@ -186,30 +186,38 @@ struct dentry_operations { | |||
186 | * dentry into place and return that dentry rather than the passed one, | 186 | * dentry into place and return that dentry rather than the passed one, |
187 | * typically using d_splice_alias. */ | 187 | * typically using d_splice_alias. */ |
188 | 188 | ||
189 | #define DCACHE_REFERENCED 0x0040 /* Recently used, don't discard. */ | 189 | #define DCACHE_REFERENCED 0x00000040 /* Recently used, don't discard. */ |
190 | #define DCACHE_RCUACCESS 0x0080 /* Entry has ever been RCU-visible */ | 190 | #define DCACHE_RCUACCESS 0x00000080 /* Entry has ever been RCU-visible */ |
191 | 191 | ||
192 | #define DCACHE_CANT_MOUNT 0x0100 | 192 | #define DCACHE_CANT_MOUNT 0x00000100 |
193 | #define DCACHE_GENOCIDE 0x0200 | 193 | #define DCACHE_GENOCIDE 0x00000200 |
194 | #define DCACHE_SHRINK_LIST 0x0400 | 194 | #define DCACHE_SHRINK_LIST 0x00000400 |
195 | 195 | ||
196 | #define DCACHE_OP_WEAK_REVALIDATE 0x0800 | 196 | #define DCACHE_OP_WEAK_REVALIDATE 0x00000800 |
197 | 197 | ||
198 | #define DCACHE_NFSFS_RENAMED 0x1000 | 198 | #define DCACHE_NFSFS_RENAMED 0x00001000 |
199 | /* this dentry has been "silly renamed" and has to be deleted on the last | 199 | /* this dentry has been "silly renamed" and has to be deleted on the last |
200 | * dput() */ | 200 | * dput() */ |
201 | #define DCACHE_COOKIE 0x2000 /* For use by dcookie subsystem */ | 201 | #define DCACHE_COOKIE 0x00002000 /* For use by dcookie subsystem */ |
202 | #define DCACHE_FSNOTIFY_PARENT_WATCHED 0x4000 | 202 | #define DCACHE_FSNOTIFY_PARENT_WATCHED 0x00004000 |
203 | /* Parent inode is watched by some fsnotify listener */ | 203 | /* Parent inode is watched by some fsnotify listener */ |
204 | 204 | ||
205 | #define DCACHE_MOUNTED 0x10000 /* is a mountpoint */ | 205 | #define DCACHE_DENTRY_KILLED 0x00008000 |
206 | #define DCACHE_NEED_AUTOMOUNT 0x20000 /* handle automount on this dir */ | 206 | |
207 | #define DCACHE_MANAGE_TRANSIT 0x40000 /* manage transit from this dirent */ | 207 | #define DCACHE_MOUNTED 0x00010000 /* is a mountpoint */ |
208 | #define DCACHE_NEED_AUTOMOUNT 0x00020000 /* handle automount on this dir */ | ||
209 | #define DCACHE_MANAGE_TRANSIT 0x00040000 /* manage transit from this dirent */ | ||
208 | #define DCACHE_MANAGED_DENTRY \ | 210 | #define DCACHE_MANAGED_DENTRY \ |
209 | (DCACHE_MOUNTED|DCACHE_NEED_AUTOMOUNT|DCACHE_MANAGE_TRANSIT) | 211 | (DCACHE_MOUNTED|DCACHE_NEED_AUTOMOUNT|DCACHE_MANAGE_TRANSIT) |
210 | 212 | ||
211 | #define DCACHE_LRU_LIST 0x80000 | 213 | #define DCACHE_LRU_LIST 0x00080000 |
212 | #define DCACHE_DENTRY_KILLED 0x100000 | 214 | |
215 | #define DCACHE_ENTRY_TYPE 0x00700000 | ||
216 | #define DCACHE_MISS_TYPE 0x00000000 /* Negative dentry */ | ||
217 | #define DCACHE_DIRECTORY_TYPE 0x00100000 /* Normal directory */ | ||
218 | #define DCACHE_AUTODIR_TYPE 0x00200000 /* Lookupless directory (presumed automount) */ | ||
219 | #define DCACHE_SYMLINK_TYPE 0x00300000 /* Symlink */ | ||
220 | #define DCACHE_FILE_TYPE 0x00400000 /* Other file type */ | ||
213 | 221 | ||
214 | extern seqlock_t rename_lock; | 222 | extern seqlock_t rename_lock; |
215 | 223 | ||
@@ -394,6 +402,61 @@ static inline bool d_mountpoint(const struct dentry *dentry) | |||
394 | return dentry->d_flags & DCACHE_MOUNTED; | 402 | return dentry->d_flags & DCACHE_MOUNTED; |
395 | } | 403 | } |
396 | 404 | ||
405 | /* | ||
406 | * Directory cache entry type accessor functions. | ||
407 | */ | ||
408 | static inline void __d_set_type(struct dentry *dentry, unsigned type) | ||
409 | { | ||
410 | dentry->d_flags = (dentry->d_flags & ~DCACHE_ENTRY_TYPE) | type; | ||
411 | } | ||
412 | |||
413 | static inline void __d_clear_type(struct dentry *dentry) | ||
414 | { | ||
415 | __d_set_type(dentry, DCACHE_MISS_TYPE); | ||
416 | } | ||
417 | |||
418 | static inline void d_set_type(struct dentry *dentry, unsigned type) | ||
419 | { | ||
420 | spin_lock(&dentry->d_lock); | ||
421 | __d_set_type(dentry, type); | ||
422 | spin_unlock(&dentry->d_lock); | ||
423 | } | ||
424 | |||
425 | static inline unsigned __d_entry_type(const struct dentry *dentry) | ||
426 | { | ||
427 | return dentry->d_flags & DCACHE_ENTRY_TYPE; | ||
428 | } | ||
429 | |||
430 | static inline bool d_is_directory(const struct dentry *dentry) | ||
431 | { | ||
432 | return __d_entry_type(dentry) == DCACHE_DIRECTORY_TYPE; | ||
433 | } | ||
434 | |||
435 | static inline bool d_is_autodir(const struct dentry *dentry) | ||
436 | { | ||
437 | return __d_entry_type(dentry) == DCACHE_AUTODIR_TYPE; | ||
438 | } | ||
439 | |||
440 | static inline bool d_is_symlink(const struct dentry *dentry) | ||
441 | { | ||
442 | return __d_entry_type(dentry) == DCACHE_SYMLINK_TYPE; | ||
443 | } | ||
444 | |||
445 | static inline bool d_is_file(const struct dentry *dentry) | ||
446 | { | ||
447 | return __d_entry_type(dentry) == DCACHE_FILE_TYPE; | ||
448 | } | ||
449 | |||
450 | static inline bool d_is_negative(const struct dentry *dentry) | ||
451 | { | ||
452 | return __d_entry_type(dentry) == DCACHE_MISS_TYPE; | ||
453 | } | ||
454 | |||
455 | static inline bool d_is_positive(const struct dentry *dentry) | ||
456 | { | ||
457 | return !d_is_negative(dentry); | ||
458 | } | ||
459 | |||
397 | extern int sysctl_vfs_cache_pressure; | 460 | extern int sysctl_vfs_cache_pressure; |
398 | 461 | ||
399 | static inline unsigned long vfs_pressure_ratio(unsigned long val) | 462 | static inline unsigned long vfs_pressure_ratio(unsigned long val) |