diff options
author | David Chinner <david@fromorbit.com> | 2008-10-30 02:36:14 -0400 |
---|---|---|
committer | Lachlan McIlroy <lachlan@sgi.com> | 2008-10-30 02:36:14 -0400 |
commit | bf904248a2adb3f3be4eb4fb1837ce3bb28cca76 (patch) | |
tree | 288306924f640f19d881166a3b50fa59b6e9e7e7 /fs | |
parent | 8290c35f87304a6b73d4fd17b03580b4f7425de8 (diff) |
[XFS] Combine the XFS and Linux inodes
To avoid issues with different lifecycles of XFS and Linux inodes, embedd
the linux inode inside the XFS inode. This means that the linux inode has
the same lifecycle as the XFS inode, even when it has been released by the
OS. XFS inodes don't live much longer than this (a short stint in reclaim
at most), so there isn't significant memory usage penalties here.
Version 3 o kill xfs_icount()
Version 2 o remove unused commented out code from xfs_iget(). o kill
useless cast in VFS_I()
SGI-PV: 988141
SGI-Modid: xfs-linux-melb:xfs-kern:32323a
Signed-off-by: David Chinner <david@fromorbit.com>
Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
Signed-off-by: Christoph Hellwig <hch@infradead.org>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_iops.c | 17 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_super.c | 47 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_vnode.c | 15 | ||||
-rw-r--r-- | fs/xfs/xfs_iget.c | 167 | ||||
-rw-r--r-- | fs/xfs/xfs_inode.c | 43 | ||||
-rw-r--r-- | fs/xfs/xfs_inode.h | 9 | ||||
-rw-r--r-- | fs/xfs/xfs_vnodeops.c | 13 |
7 files changed, 108 insertions, 203 deletions
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index 3bfb3c0f8e29..37bb1012aff1 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c | |||
@@ -64,14 +64,14 @@ xfs_synchronize_atime( | |||
64 | { | 64 | { |
65 | struct inode *inode = VFS_I(ip); | 65 | struct inode *inode = VFS_I(ip); |
66 | 66 | ||
67 | if (inode) { | 67 | if (!(inode->i_state & I_CLEAR)) { |
68 | ip->i_d.di_atime.t_sec = (__int32_t)inode->i_atime.tv_sec; | 68 | ip->i_d.di_atime.t_sec = (__int32_t)inode->i_atime.tv_sec; |
69 | ip->i_d.di_atime.t_nsec = (__int32_t)inode->i_atime.tv_nsec; | 69 | ip->i_d.di_atime.t_nsec = (__int32_t)inode->i_atime.tv_nsec; |
70 | } | 70 | } |
71 | } | 71 | } |
72 | 72 | ||
73 | /* | 73 | /* |
74 | * If the linux inode exists, mark it dirty. | 74 | * If the linux inode is valid, mark it dirty. |
75 | * Used when commiting a dirty inode into a transaction so that | 75 | * Used when commiting a dirty inode into a transaction so that |
76 | * the inode will get written back by the linux code | 76 | * the inode will get written back by the linux code |
77 | */ | 77 | */ |
@@ -81,7 +81,7 @@ xfs_mark_inode_dirty_sync( | |||
81 | { | 81 | { |
82 | struct inode *inode = VFS_I(ip); | 82 | struct inode *inode = VFS_I(ip); |
83 | 83 | ||
84 | if (inode) | 84 | if (!(inode->i_state & (I_WILL_FREE|I_FREEING|I_CLEAR))) |
85 | mark_inode_dirty_sync(inode); | 85 | mark_inode_dirty_sync(inode); |
86 | } | 86 | } |
87 | 87 | ||
@@ -766,12 +766,21 @@ xfs_diflags_to_iflags( | |||
766 | * When reading existing inodes from disk this is called directly | 766 | * When reading existing inodes from disk this is called directly |
767 | * from xfs_iget, when creating a new inode it is called from | 767 | * from xfs_iget, when creating a new inode it is called from |
768 | * xfs_ialloc after setting up the inode. | 768 | * xfs_ialloc after setting up the inode. |
769 | * | ||
770 | * We are always called with an uninitialised linux inode here. | ||
771 | * We need to initialise the necessary fields and take a reference | ||
772 | * on it. | ||
769 | */ | 773 | */ |
770 | void | 774 | void |
771 | xfs_setup_inode( | 775 | xfs_setup_inode( |
772 | struct xfs_inode *ip) | 776 | struct xfs_inode *ip) |
773 | { | 777 | { |
774 | struct inode *inode = ip->i_vnode; | 778 | struct inode *inode = &ip->i_vnode; |
779 | |||
780 | inode->i_ino = ip->i_ino; | ||
781 | inode->i_state = I_NEW|I_LOCK; | ||
782 | inode_add_to_lists(ip->i_mount->m_super, inode); | ||
783 | ASSERT(atomic_read(&inode->i_count) == 1); | ||
775 | 784 | ||
776 | inode->i_mode = ip->i_d.di_mode; | 785 | inode->i_mode = ip->i_d.di_mode; |
777 | inode->i_nlink = ip->i_d.di_nlink; | 786 | inode->i_nlink = ip->i_d.di_nlink; |
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index b87e45577a58..c6ef684bf2e3 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c | |||
@@ -72,7 +72,6 @@ | |||
72 | 72 | ||
73 | static struct quotactl_ops xfs_quotactl_operations; | 73 | static struct quotactl_ops xfs_quotactl_operations; |
74 | static struct super_operations xfs_super_operations; | 74 | static struct super_operations xfs_super_operations; |
75 | static kmem_zone_t *xfs_vnode_zone; | ||
76 | static kmem_zone_t *xfs_ioend_zone; | 75 | static kmem_zone_t *xfs_ioend_zone; |
77 | mempool_t *xfs_ioend_pool; | 76 | mempool_t *xfs_ioend_pool; |
78 | 77 | ||
@@ -867,29 +866,24 @@ xfsaild_stop( | |||
867 | } | 866 | } |
868 | 867 | ||
869 | 868 | ||
870 | 869 | /* Catch misguided souls that try to use this interface on XFS */ | |
871 | STATIC struct inode * | 870 | STATIC struct inode * |
872 | xfs_fs_alloc_inode( | 871 | xfs_fs_alloc_inode( |
873 | struct super_block *sb) | 872 | struct super_block *sb) |
874 | { | 873 | { |
875 | return kmem_zone_alloc(xfs_vnode_zone, KM_SLEEP); | 874 | BUG(); |
876 | } | 875 | } |
877 | 876 | ||
877 | /* | ||
878 | * we need to provide an empty inode free function to prevent | ||
879 | * the generic code from trying to free our combined inode. | ||
880 | */ | ||
878 | STATIC void | 881 | STATIC void |
879 | xfs_fs_destroy_inode( | 882 | xfs_fs_destroy_inode( |
880 | struct inode *inode) | 883 | struct inode *inode) |
881 | { | ||
882 | kmem_zone_free(xfs_vnode_zone, inode); | ||
883 | } | ||
884 | |||
885 | STATIC void | ||
886 | xfs_fs_inode_init_once( | ||
887 | void *vnode) | ||
888 | { | 884 | { |
889 | inode_init_once((struct inode *)vnode); | ||
890 | } | 885 | } |
891 | 886 | ||
892 | |||
893 | /* | 887 | /* |
894 | * Slab object creation initialisation for the XFS inode. | 888 | * Slab object creation initialisation for the XFS inode. |
895 | * This covers only the idempotent fields in the XFS inode; | 889 | * This covers only the idempotent fields in the XFS inode; |
@@ -898,13 +892,18 @@ xfs_fs_inode_init_once( | |||
898 | * fields in the xfs inode that left in the initialise state | 892 | * fields in the xfs inode that left in the initialise state |
899 | * when freeing the inode. | 893 | * when freeing the inode. |
900 | */ | 894 | */ |
901 | void | 895 | STATIC void |
902 | xfs_inode_init_once( | 896 | xfs_fs_inode_init_once( |
903 | void *inode) | 897 | void *inode) |
904 | { | 898 | { |
905 | struct xfs_inode *ip = inode; | 899 | struct xfs_inode *ip = inode; |
906 | 900 | ||
907 | memset(ip, 0, sizeof(struct xfs_inode)); | 901 | memset(ip, 0, sizeof(struct xfs_inode)); |
902 | |||
903 | /* vfs inode */ | ||
904 | inode_init_once(VFS_I(ip)); | ||
905 | |||
906 | /* xfs inode */ | ||
908 | atomic_set(&ip->i_iocount, 0); | 907 | atomic_set(&ip->i_iocount, 0); |
909 | atomic_set(&ip->i_pincount, 0); | 908 | atomic_set(&ip->i_pincount, 0); |
910 | spin_lock_init(&ip->i_flags_lock); | 909 | spin_lock_init(&ip->i_flags_lock); |
@@ -975,8 +974,6 @@ xfs_fs_clear_inode( | |||
975 | if (xfs_reclaim(ip)) | 974 | if (xfs_reclaim(ip)) |
976 | panic("%s: cannot reclaim 0x%p\n", __func__, inode); | 975 | panic("%s: cannot reclaim 0x%p\n", __func__, inode); |
977 | } | 976 | } |
978 | |||
979 | ASSERT(XFS_I(inode) == NULL); | ||
980 | } | 977 | } |
981 | 978 | ||
982 | STATIC void | 979 | STATIC void |
@@ -1829,16 +1826,10 @@ xfs_free_trace_bufs(void) | |||
1829 | STATIC int __init | 1826 | STATIC int __init |
1830 | xfs_init_zones(void) | 1827 | xfs_init_zones(void) |
1831 | { | 1828 | { |
1832 | xfs_vnode_zone = kmem_zone_init_flags(sizeof(struct inode), "xfs_vnode", | ||
1833 | KM_ZONE_HWALIGN | KM_ZONE_RECLAIM | | ||
1834 | KM_ZONE_SPREAD, | ||
1835 | xfs_fs_inode_init_once); | ||
1836 | if (!xfs_vnode_zone) | ||
1837 | goto out; | ||
1838 | 1829 | ||
1839 | xfs_ioend_zone = kmem_zone_init(sizeof(xfs_ioend_t), "xfs_ioend"); | 1830 | xfs_ioend_zone = kmem_zone_init(sizeof(xfs_ioend_t), "xfs_ioend"); |
1840 | if (!xfs_ioend_zone) | 1831 | if (!xfs_ioend_zone) |
1841 | goto out_destroy_vnode_zone; | 1832 | goto out; |
1842 | 1833 | ||
1843 | xfs_ioend_pool = mempool_create_slab_pool(4 * MAX_BUF_PER_PAGE, | 1834 | xfs_ioend_pool = mempool_create_slab_pool(4 * MAX_BUF_PER_PAGE, |
1844 | xfs_ioend_zone); | 1835 | xfs_ioend_zone); |
@@ -1854,6 +1845,7 @@ xfs_init_zones(void) | |||
1854 | "xfs_bmap_free_item"); | 1845 | "xfs_bmap_free_item"); |
1855 | if (!xfs_bmap_free_item_zone) | 1846 | if (!xfs_bmap_free_item_zone) |
1856 | goto out_destroy_log_ticket_zone; | 1847 | goto out_destroy_log_ticket_zone; |
1848 | |||
1857 | xfs_btree_cur_zone = kmem_zone_init(sizeof(xfs_btree_cur_t), | 1849 | xfs_btree_cur_zone = kmem_zone_init(sizeof(xfs_btree_cur_t), |
1858 | "xfs_btree_cur"); | 1850 | "xfs_btree_cur"); |
1859 | if (!xfs_btree_cur_zone) | 1851 | if (!xfs_btree_cur_zone) |
@@ -1901,8 +1893,8 @@ xfs_init_zones(void) | |||
1901 | 1893 | ||
1902 | xfs_inode_zone = | 1894 | xfs_inode_zone = |
1903 | kmem_zone_init_flags(sizeof(xfs_inode_t), "xfs_inode", | 1895 | kmem_zone_init_flags(sizeof(xfs_inode_t), "xfs_inode", |
1904 | KM_ZONE_HWALIGN | KM_ZONE_RECLAIM | | 1896 | KM_ZONE_HWALIGN | KM_ZONE_RECLAIM | KM_ZONE_SPREAD, |
1905 | KM_ZONE_SPREAD, xfs_inode_init_once); | 1897 | xfs_fs_inode_init_once); |
1906 | if (!xfs_inode_zone) | 1898 | if (!xfs_inode_zone) |
1907 | goto out_destroy_efi_zone; | 1899 | goto out_destroy_efi_zone; |
1908 | 1900 | ||
@@ -1950,8 +1942,6 @@ xfs_init_zones(void) | |||
1950 | mempool_destroy(xfs_ioend_pool); | 1942 | mempool_destroy(xfs_ioend_pool); |
1951 | out_destroy_ioend_zone: | 1943 | out_destroy_ioend_zone: |
1952 | kmem_zone_destroy(xfs_ioend_zone); | 1944 | kmem_zone_destroy(xfs_ioend_zone); |
1953 | out_destroy_vnode_zone: | ||
1954 | kmem_zone_destroy(xfs_vnode_zone); | ||
1955 | out: | 1945 | out: |
1956 | return -ENOMEM; | 1946 | return -ENOMEM; |
1957 | } | 1947 | } |
@@ -1976,7 +1966,6 @@ xfs_destroy_zones(void) | |||
1976 | kmem_zone_destroy(xfs_log_ticket_zone); | 1966 | kmem_zone_destroy(xfs_log_ticket_zone); |
1977 | mempool_destroy(xfs_ioend_pool); | 1967 | mempool_destroy(xfs_ioend_pool); |
1978 | kmem_zone_destroy(xfs_ioend_zone); | 1968 | kmem_zone_destroy(xfs_ioend_zone); |
1979 | kmem_zone_destroy(xfs_vnode_zone); | ||
1980 | 1969 | ||
1981 | } | 1970 | } |
1982 | 1971 | ||
diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c index ac827d231490..ad18262d651b 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.c +++ b/fs/xfs/linux-2.6/xfs_vnode.c | |||
@@ -84,25 +84,12 @@ vn_ioerror( | |||
84 | 84 | ||
85 | #ifdef XFS_INODE_TRACE | 85 | #ifdef XFS_INODE_TRACE |
86 | 86 | ||
87 | /* | ||
88 | * Reference count of Linux inode if present, -1 if the xfs_inode | ||
89 | * has no associated Linux inode. | ||
90 | */ | ||
91 | static inline int xfs_icount(struct xfs_inode *ip) | ||
92 | { | ||
93 | struct inode *inode = VFS_I(ip); | ||
94 | |||
95 | if (inode) | ||
96 | return atomic_read(&inode->i_count); | ||
97 | return -1; | ||
98 | } | ||
99 | |||
100 | #define KTRACE_ENTER(ip, vk, s, line, ra) \ | 87 | #define KTRACE_ENTER(ip, vk, s, line, ra) \ |
101 | ktrace_enter( (ip)->i_trace, \ | 88 | ktrace_enter( (ip)->i_trace, \ |
102 | /* 0 */ (void *)(__psint_t)(vk), \ | 89 | /* 0 */ (void *)(__psint_t)(vk), \ |
103 | /* 1 */ (void *)(s), \ | 90 | /* 1 */ (void *)(s), \ |
104 | /* 2 */ (void *)(__psint_t) line, \ | 91 | /* 2 */ (void *)(__psint_t) line, \ |
105 | /* 3 */ (void *)(__psint_t)xfs_icount(ip), \ | 92 | /* 3 */ (void *)(__psint_t)atomic_read(&VFS_I(ip)->i_count), \ |
106 | /* 4 */ (void *)(ra), \ | 93 | /* 4 */ (void *)(ra), \ |
107 | /* 5 */ NULL, \ | 94 | /* 5 */ NULL, \ |
108 | /* 6 */ (void *)(__psint_t)current_cpu(), \ | 95 | /* 6 */ (void *)(__psint_t)current_cpu(), \ |
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index b2539b17c954..c4414e8bce8d 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c | |||
@@ -44,77 +44,65 @@ | |||
44 | */ | 44 | */ |
45 | static int | 45 | static int |
46 | xfs_iget_cache_hit( | 46 | xfs_iget_cache_hit( |
47 | struct inode *inode, | ||
48 | struct xfs_perag *pag, | 47 | struct xfs_perag *pag, |
49 | struct xfs_inode *ip, | 48 | struct xfs_inode *ip, |
50 | int flags, | 49 | int flags, |
51 | int lock_flags) __releases(pag->pag_ici_lock) | 50 | int lock_flags) __releases(pag->pag_ici_lock) |
52 | { | 51 | { |
53 | struct xfs_mount *mp = ip->i_mount; | 52 | struct xfs_mount *mp = ip->i_mount; |
54 | struct inode *old_inode; | ||
55 | int error = 0; | 53 | int error = 0; |
56 | 54 | ||
57 | /* | 55 | /* |
58 | * If INEW is set this inode is being set up | 56 | * If INEW is set this inode is being set up |
57 | * If IRECLAIM is set this inode is being torn down | ||
59 | * Pause and try again. | 58 | * Pause and try again. |
60 | */ | 59 | */ |
61 | if (xfs_iflags_test(ip, XFS_INEW)) { | 60 | if (xfs_iflags_test(ip, (XFS_INEW|XFS_IRECLAIM))) { |
62 | error = EAGAIN; | 61 | error = EAGAIN; |
63 | XFS_STATS_INC(xs_ig_frecycle); | 62 | XFS_STATS_INC(xs_ig_frecycle); |
64 | goto out_error; | 63 | goto out_error; |
65 | } | 64 | } |
66 | 65 | ||
67 | old_inode = ip->i_vnode; | 66 | /* If IRECLAIMABLE is set, we've torn down the vfs inode part */ |
68 | if (old_inode == NULL) { | 67 | if (xfs_iflags_test(ip, XFS_IRECLAIMABLE)) { |
68 | |||
69 | /* | 69 | /* |
70 | * If IRECLAIM is set this inode is | 70 | * If lookup is racing with unlink, then we should return an |
71 | * on its way out of the system, | 71 | * error immediately so we don't remove it from the reclaim |
72 | * we need to pause and try again. | 72 | * list and potentially leak the inode. |
73 | */ | 73 | */ |
74 | if (xfs_iflags_test(ip, XFS_IRECLAIM)) { | 74 | |
75 | error = EAGAIN; | 75 | if ((ip->i_d.di_mode == 0) && !(flags & XFS_IGET_CREATE)) { |
76 | XFS_STATS_INC(xs_ig_frecycle); | 76 | error = ENOENT; |
77 | goto out_error; | 77 | goto out_error; |
78 | } | 78 | } |
79 | ASSERT(xfs_iflags_test(ip, XFS_IRECLAIMABLE)); | 79 | |
80 | xfs_itrace_exit_tag(ip, "xfs_iget.alloc"); | ||
80 | 81 | ||
81 | /* | 82 | /* |
82 | * If lookup is racing with unlink, then we | 83 | * We need to re-initialise the VFS inode as it has been |
83 | * should return an error immediately so we | 84 | * 'freed' by the VFS. Do this here so we can deal with |
84 | * don't remove it from the reclaim list and | 85 | * errors cleanly, then tag it so it can be set up correctly |
85 | * potentially leak the inode. | 86 | * later. |
86 | */ | 87 | */ |
87 | if ((ip->i_d.di_mode == 0) && | 88 | if (!inode_init_always(mp->m_super, VFS_I(ip))) { |
88 | !(flags & XFS_IGET_CREATE)) { | 89 | error = ENOMEM; |
89 | error = ENOENT; | ||
90 | goto out_error; | 90 | goto out_error; |
91 | } | 91 | } |
92 | xfs_itrace_exit_tag(ip, "xfs_iget.alloc"); | 92 | xfs_iflags_set(ip, XFS_INEW); |
93 | |||
94 | xfs_iflags_clear(ip, XFS_IRECLAIMABLE); | 93 | xfs_iflags_clear(ip, XFS_IRECLAIMABLE); |
95 | read_unlock(&pag->pag_ici_lock); | 94 | read_unlock(&pag->pag_ici_lock); |
96 | 95 | ||
97 | XFS_MOUNT_ILOCK(mp); | 96 | XFS_MOUNT_ILOCK(mp); |
98 | list_del_init(&ip->i_reclaim); | 97 | list_del_init(&ip->i_reclaim); |
99 | XFS_MOUNT_IUNLOCK(mp); | 98 | XFS_MOUNT_IUNLOCK(mp); |
100 | 99 | } else if (!igrab(VFS_I(ip))) { | |
101 | } else if (inode != old_inode) { | 100 | /* If the VFS inode is being torn down, pause and try again. */ |
102 | /* The inode is being torn down, pause and | 101 | error = EAGAIN; |
103 | * try again. | 102 | XFS_STATS_INC(xs_ig_frecycle); |
104 | */ | 103 | goto out_error; |
105 | if (old_inode->i_state & (I_FREEING | I_CLEAR)) { | ||
106 | error = EAGAIN; | ||
107 | XFS_STATS_INC(xs_ig_frecycle); | ||
108 | goto out_error; | ||
109 | } | ||
110 | /* Chances are the other vnode (the one in the inode) is being torn | ||
111 | * down right now, and we landed on top of it. Question is, what do | ||
112 | * we do? Unhook the old inode and hook up the new one? | ||
113 | */ | ||
114 | cmn_err(CE_PANIC, | ||
115 | "xfs_iget_core: ambiguous vns: vp/0x%p, invp/0x%p", | ||
116 | old_inode, inode); | ||
117 | } else { | 104 | } else { |
105 | /* we've got a live one */ | ||
118 | read_unlock(&pag->pag_ici_lock); | 106 | read_unlock(&pag->pag_ici_lock); |
119 | } | 107 | } |
120 | 108 | ||
@@ -215,11 +203,11 @@ out_destroy: | |||
215 | /* | 203 | /* |
216 | * Look up an inode by number in the given file system. | 204 | * Look up an inode by number in the given file system. |
217 | * The inode is looked up in the cache held in each AG. | 205 | * The inode is looked up in the cache held in each AG. |
218 | * If the inode is found in the cache, attach it to the provided | 206 | * If the inode is found in the cache, initialise the vfs inode |
219 | * vnode. | 207 | * if necessary. |
220 | * | 208 | * |
221 | * If it is not in core, read it in from the file system's device, | 209 | * If it is not in core, read it in from the file system's device, |
222 | * add it to the cache and attach the provided vnode. | 210 | * add it to the cache and initialise the vfs inode. |
223 | * | 211 | * |
224 | * The inode is locked according to the value of the lock_flags parameter. | 212 | * The inode is locked according to the value of the lock_flags parameter. |
225 | * This flag parameter indicates how and if the inode's IO lock and inode lock | 213 | * This flag parameter indicates how and if the inode's IO lock and inode lock |
@@ -236,9 +224,8 @@ out_destroy: | |||
236 | * bno -- the block number starting the buffer containing the inode, | 224 | * bno -- the block number starting the buffer containing the inode, |
237 | * if known (as by bulkstat), else 0. | 225 | * if known (as by bulkstat), else 0. |
238 | */ | 226 | */ |
239 | STATIC int | 227 | int |
240 | xfs_iget_core( | 228 | xfs_iget( |
241 | struct inode *inode, | ||
242 | xfs_mount_t *mp, | 229 | xfs_mount_t *mp, |
243 | xfs_trans_t *tp, | 230 | xfs_trans_t *tp, |
244 | xfs_ino_t ino, | 231 | xfs_ino_t ino, |
@@ -269,7 +256,7 @@ again: | |||
269 | ip = radix_tree_lookup(&pag->pag_ici_root, agino); | 256 | ip = radix_tree_lookup(&pag->pag_ici_root, agino); |
270 | 257 | ||
271 | if (ip) { | 258 | if (ip) { |
272 | error = xfs_iget_cache_hit(inode, pag, ip, flags, lock_flags); | 259 | error = xfs_iget_cache_hit(pag, ip, flags, lock_flags); |
273 | if (error) | 260 | if (error) |
274 | goto out_error_or_again; | 261 | goto out_error_or_again; |
275 | } else { | 262 | } else { |
@@ -283,23 +270,16 @@ again: | |||
283 | } | 270 | } |
284 | xfs_put_perag(mp, pag); | 271 | xfs_put_perag(mp, pag); |
285 | 272 | ||
286 | ASSERT(ip->i_df.if_ext_max == | ||
287 | XFS_IFORK_DSIZE(ip) / sizeof(xfs_bmbt_rec_t)); | ||
288 | |||
289 | xfs_iflags_set(ip, XFS_IMODIFIED); | 273 | xfs_iflags_set(ip, XFS_IMODIFIED); |
290 | *ipp = ip; | 274 | *ipp = ip; |
291 | 275 | ||
292 | /* | 276 | ASSERT(ip->i_df.if_ext_max == |
293 | * Set up the Linux with the Linux inode. | 277 | XFS_IFORK_DSIZE(ip) / sizeof(xfs_bmbt_rec_t)); |
294 | */ | ||
295 | ip->i_vnode = inode; | ||
296 | inode->i_private = ip; | ||
297 | |||
298 | /* | 278 | /* |
299 | * If we have a real type for an on-disk inode, we can set ops(&unlock) | 279 | * If we have a real type for an on-disk inode, we can set ops(&unlock) |
300 | * now. If it's a new inode being created, xfs_ialloc will handle it. | 280 | * now. If it's a new inode being created, xfs_ialloc will handle it. |
301 | */ | 281 | */ |
302 | if (ip->i_d.di_mode != 0) | 282 | if (xfs_iflags_test(ip, XFS_INEW) && ip->i_d.di_mode != 0) |
303 | xfs_setup_inode(ip); | 283 | xfs_setup_inode(ip); |
304 | return 0; | 284 | return 0; |
305 | 285 | ||
@@ -314,75 +294,6 @@ out_error_or_again: | |||
314 | 294 | ||
315 | 295 | ||
316 | /* | 296 | /* |
317 | * The 'normal' internal xfs_iget, if needed it will | ||
318 | * 'allocate', or 'get', the vnode. | ||
319 | */ | ||
320 | int | ||
321 | xfs_iget( | ||
322 | xfs_mount_t *mp, | ||
323 | xfs_trans_t *tp, | ||
324 | xfs_ino_t ino, | ||
325 | uint flags, | ||
326 | uint lock_flags, | ||
327 | xfs_inode_t **ipp, | ||
328 | xfs_daddr_t bno) | ||
329 | { | ||
330 | struct inode *inode; | ||
331 | xfs_inode_t *ip; | ||
332 | int error; | ||
333 | |||
334 | XFS_STATS_INC(xs_ig_attempts); | ||
335 | |||
336 | retry: | ||
337 | inode = iget_locked(mp->m_super, ino); | ||
338 | if (!inode) | ||
339 | /* If we got no inode we are out of memory */ | ||
340 | return ENOMEM; | ||
341 | |||
342 | if (inode->i_state & I_NEW) { | ||
343 | XFS_STATS_INC(vn_active); | ||
344 | XFS_STATS_INC(vn_alloc); | ||
345 | |||
346 | error = xfs_iget_core(inode, mp, tp, ino, flags, | ||
347 | lock_flags, ipp, bno); | ||
348 | if (error) { | ||
349 | make_bad_inode(inode); | ||
350 | if (inode->i_state & I_NEW) | ||
351 | unlock_new_inode(inode); | ||
352 | iput(inode); | ||
353 | } | ||
354 | return error; | ||
355 | } | ||
356 | |||
357 | /* | ||
358 | * If the inode is not fully constructed due to | ||
359 | * filehandle mismatches wait for the inode to go | ||
360 | * away and try again. | ||
361 | * | ||
362 | * iget_locked will call __wait_on_freeing_inode | ||
363 | * to wait for the inode to go away. | ||
364 | */ | ||
365 | if (is_bad_inode(inode)) { | ||
366 | iput(inode); | ||
367 | delay(1); | ||
368 | goto retry; | ||
369 | } | ||
370 | |||
371 | ip = XFS_I(inode); | ||
372 | if (!ip) { | ||
373 | iput(inode); | ||
374 | delay(1); | ||
375 | goto retry; | ||
376 | } | ||
377 | |||
378 | if (lock_flags != 0) | ||
379 | xfs_ilock(ip, lock_flags); | ||
380 | XFS_STATS_INC(xs_ig_found); | ||
381 | *ipp = ip; | ||
382 | return 0; | ||
383 | } | ||
384 | |||
385 | /* | ||
386 | * Look for the inode corresponding to the given ino in the hash table. | 297 | * Look for the inode corresponding to the given ino in the hash table. |
387 | * If it is there and its i_transp pointer matches tp, return it. | 298 | * If it is there and its i_transp pointer matches tp, return it. |
388 | * Otherwise, return NULL. | 299 | * Otherwise, return NULL. |
@@ -482,14 +393,6 @@ xfs_ireclaim(xfs_inode_t *ip) | |||
482 | XFS_QM_DQDETACH(ip->i_mount, ip); | 393 | XFS_QM_DQDETACH(ip->i_mount, ip); |
483 | 394 | ||
484 | /* | 395 | /* |
485 | * Pull our behavior descriptor from the vnode chain. | ||
486 | */ | ||
487 | if (ip->i_vnode) { | ||
488 | ip->i_vnode->i_private = NULL; | ||
489 | ip->i_vnode = NULL; | ||
490 | } | ||
491 | |||
492 | /* | ||
493 | * Free all memory associated with the inode. | 396 | * Free all memory associated with the inode. |
494 | */ | 397 | */ |
495 | xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); | 398 | xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); |
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index bc33762abc49..99d9118c4a41 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
@@ -813,6 +813,16 @@ xfs_inode_alloc( | |||
813 | ASSERT(!spin_is_locked(&ip->i_flags_lock)); | 813 | ASSERT(!spin_is_locked(&ip->i_flags_lock)); |
814 | ASSERT(list_empty(&ip->i_reclaim)); | 814 | ASSERT(list_empty(&ip->i_reclaim)); |
815 | 815 | ||
816 | /* | ||
817 | * initialise the VFS inode here to get failures | ||
818 | * out of the way early. | ||
819 | */ | ||
820 | if (!inode_init_always(mp->m_super, VFS_I(ip))) { | ||
821 | kmem_zone_free(xfs_inode_zone, ip); | ||
822 | return NULL; | ||
823 | } | ||
824 | |||
825 | /* initialise the xfs inode */ | ||
816 | ip->i_ino = ino; | 826 | ip->i_ino = ino; |
817 | ip->i_mount = mp; | 827 | ip->i_mount = mp; |
818 | ip->i_blkno = 0; | 828 | ip->i_blkno = 0; |
@@ -1086,6 +1096,7 @@ xfs_ialloc( | |||
1086 | uint flags; | 1096 | uint flags; |
1087 | int error; | 1097 | int error; |
1088 | timespec_t tv; | 1098 | timespec_t tv; |
1099 | int filestreams = 0; | ||
1089 | 1100 | ||
1090 | /* | 1101 | /* |
1091 | * Call the space management code to pick | 1102 | * Call the space management code to pick |
@@ -1093,9 +1104,8 @@ xfs_ialloc( | |||
1093 | */ | 1104 | */ |
1094 | error = xfs_dialloc(tp, pip ? pip->i_ino : 0, mode, okalloc, | 1105 | error = xfs_dialloc(tp, pip ? pip->i_ino : 0, mode, okalloc, |
1095 | ialloc_context, call_again, &ino); | 1106 | ialloc_context, call_again, &ino); |
1096 | if (error != 0) { | 1107 | if (error) |
1097 | return error; | 1108 | return error; |
1098 | } | ||
1099 | if (*call_again || ino == NULLFSINO) { | 1109 | if (*call_again || ino == NULLFSINO) { |
1100 | *ipp = NULL; | 1110 | *ipp = NULL; |
1101 | return 0; | 1111 | return 0; |
@@ -1109,9 +1119,8 @@ xfs_ialloc( | |||
1109 | */ | 1119 | */ |
1110 | error = xfs_trans_iget(tp->t_mountp, tp, ino, | 1120 | error = xfs_trans_iget(tp->t_mountp, tp, ino, |
1111 | XFS_IGET_CREATE, XFS_ILOCK_EXCL, &ip); | 1121 | XFS_IGET_CREATE, XFS_ILOCK_EXCL, &ip); |
1112 | if (error != 0) { | 1122 | if (error) |
1113 | return error; | 1123 | return error; |
1114 | } | ||
1115 | ASSERT(ip != NULL); | 1124 | ASSERT(ip != NULL); |
1116 | 1125 | ||
1117 | ip->i_d.di_mode = (__uint16_t)mode; | 1126 | ip->i_d.di_mode = (__uint16_t)mode; |
@@ -1192,13 +1201,12 @@ xfs_ialloc( | |||
1192 | flags |= XFS_ILOG_DEV; | 1201 | flags |= XFS_ILOG_DEV; |
1193 | break; | 1202 | break; |
1194 | case S_IFREG: | 1203 | case S_IFREG: |
1195 | if (pip && xfs_inode_is_filestream(pip)) { | 1204 | /* |
1196 | error = xfs_filestream_associate(pip, ip); | 1205 | * we can't set up filestreams until after the VFS inode |
1197 | if (error < 0) | 1206 | * is set up properly. |
1198 | return -error; | 1207 | */ |
1199 | if (!error) | 1208 | if (pip && xfs_inode_is_filestream(pip)) |
1200 | xfs_iflags_set(ip, XFS_IFILESTREAM); | 1209 | filestreams = 1; |
1201 | } | ||
1202 | /* fall through */ | 1210 | /* fall through */ |
1203 | case S_IFDIR: | 1211 | case S_IFDIR: |
1204 | if (pip && (pip->i_d.di_flags & XFS_DIFLAG_ANY)) { | 1212 | if (pip && (pip->i_d.di_flags & XFS_DIFLAG_ANY)) { |
@@ -1264,6 +1272,15 @@ xfs_ialloc( | |||
1264 | /* now that we have an i_mode we can setup inode ops and unlock */ | 1272 | /* now that we have an i_mode we can setup inode ops and unlock */ |
1265 | xfs_setup_inode(ip); | 1273 | xfs_setup_inode(ip); |
1266 | 1274 | ||
1275 | /* now we have set up the vfs inode we can associate the filestream */ | ||
1276 | if (filestreams) { | ||
1277 | error = xfs_filestream_associate(pip, ip); | ||
1278 | if (error < 0) | ||
1279 | return -error; | ||
1280 | if (!error) | ||
1281 | xfs_iflags_set(ip, XFS_IFILESTREAM); | ||
1282 | } | ||
1283 | |||
1267 | *ipp = ip; | 1284 | *ipp = ip; |
1268 | return 0; | 1285 | return 0; |
1269 | } | 1286 | } |
@@ -2650,6 +2667,10 @@ xfs_idestroy_fork( | |||
2650 | * It must free the inode itself and any buffers allocated for | 2667 | * It must free the inode itself and any buffers allocated for |
2651 | * if_extents/if_data and if_broot. It must also free the lock | 2668 | * if_extents/if_data and if_broot. It must also free the lock |
2652 | * associated with the inode. | 2669 | * associated with the inode. |
2670 | * | ||
2671 | * Note: because we don't initialise everything on reallocation out | ||
2672 | * of the zone, we must ensure we nullify everything correctly before | ||
2673 | * freeing the structure. | ||
2653 | */ | 2674 | */ |
2654 | void | 2675 | void |
2655 | xfs_idestroy( | 2676 | xfs_idestroy( |
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 6fd20fc179a4..345b43a90eb5 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h | |||
@@ -236,7 +236,6 @@ typedef struct xfs_inode { | |||
236 | /* Inode linking and identification information. */ | 236 | /* Inode linking and identification information. */ |
237 | struct xfs_mount *i_mount; /* fs mount struct ptr */ | 237 | struct xfs_mount *i_mount; /* fs mount struct ptr */ |
238 | struct list_head i_reclaim; /* reclaim list */ | 238 | struct list_head i_reclaim; /* reclaim list */ |
239 | struct inode *i_vnode; /* vnode backpointer */ | ||
240 | struct xfs_dquot *i_udquot; /* user dquot */ | 239 | struct xfs_dquot *i_udquot; /* user dquot */ |
241 | struct xfs_dquot *i_gdquot; /* group dquot */ | 240 | struct xfs_dquot *i_gdquot; /* group dquot */ |
242 | 241 | ||
@@ -271,6 +270,10 @@ typedef struct xfs_inode { | |||
271 | xfs_fsize_t i_size; /* in-memory size */ | 270 | xfs_fsize_t i_size; /* in-memory size */ |
272 | xfs_fsize_t i_new_size; /* size when write completes */ | 271 | xfs_fsize_t i_new_size; /* size when write completes */ |
273 | atomic_t i_iocount; /* outstanding I/O count */ | 272 | atomic_t i_iocount; /* outstanding I/O count */ |
273 | |||
274 | /* VFS inode */ | ||
275 | struct inode i_vnode; /* embedded VFS inode */ | ||
276 | |||
274 | /* Trace buffers per inode. */ | 277 | /* Trace buffers per inode. */ |
275 | #ifdef XFS_INODE_TRACE | 278 | #ifdef XFS_INODE_TRACE |
276 | struct ktrace *i_trace; /* general inode trace */ | 279 | struct ktrace *i_trace; /* general inode trace */ |
@@ -298,13 +301,13 @@ typedef struct xfs_inode { | |||
298 | /* Convert from vfs inode to xfs inode */ | 301 | /* Convert from vfs inode to xfs inode */ |
299 | static inline struct xfs_inode *XFS_I(struct inode *inode) | 302 | static inline struct xfs_inode *XFS_I(struct inode *inode) |
300 | { | 303 | { |
301 | return (struct xfs_inode *)inode->i_private; | 304 | return container_of(inode, struct xfs_inode, i_vnode); |
302 | } | 305 | } |
303 | 306 | ||
304 | /* convert from xfs inode to vfs inode */ | 307 | /* convert from xfs inode to vfs inode */ |
305 | static inline struct inode *VFS_I(struct xfs_inode *ip) | 308 | static inline struct inode *VFS_I(struct xfs_inode *ip) |
306 | { | 309 | { |
307 | return (struct inode *)ip->i_vnode; | 310 | return &ip->i_vnode; |
308 | } | 311 | } |
309 | 312 | ||
310 | /* | 313 | /* |
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index a6714579a414..7fb577c9f9d8 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
@@ -2833,6 +2833,7 @@ xfs_reclaim( | |||
2833 | if (!ip->i_update_core && (ip->i_itemp == NULL)) { | 2833 | if (!ip->i_update_core && (ip->i_itemp == NULL)) { |
2834 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 2834 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
2835 | xfs_iflock(ip); | 2835 | xfs_iflock(ip); |
2836 | xfs_iflags_set(ip, XFS_IRECLAIMABLE); | ||
2836 | return xfs_finish_reclaim(ip, 1, XFS_IFLUSH_DELWRI_ELSE_SYNC); | 2837 | return xfs_finish_reclaim(ip, 1, XFS_IFLUSH_DELWRI_ELSE_SYNC); |
2837 | } else { | 2838 | } else { |
2838 | xfs_mount_t *mp = ip->i_mount; | 2839 | xfs_mount_t *mp = ip->i_mount; |
@@ -2841,8 +2842,6 @@ xfs_reclaim( | |||
2841 | XFS_MOUNT_ILOCK(mp); | 2842 | XFS_MOUNT_ILOCK(mp); |
2842 | spin_lock(&ip->i_flags_lock); | 2843 | spin_lock(&ip->i_flags_lock); |
2843 | __xfs_iflags_set(ip, XFS_IRECLAIMABLE); | 2844 | __xfs_iflags_set(ip, XFS_IRECLAIMABLE); |
2844 | VFS_I(ip)->i_private = NULL; | ||
2845 | ip->i_vnode = NULL; | ||
2846 | spin_unlock(&ip->i_flags_lock); | 2845 | spin_unlock(&ip->i_flags_lock); |
2847 | list_add_tail(&ip->i_reclaim, &mp->m_del_inodes); | 2846 | list_add_tail(&ip->i_reclaim, &mp->m_del_inodes); |
2848 | XFS_MOUNT_IUNLOCK(mp); | 2847 | XFS_MOUNT_IUNLOCK(mp); |
@@ -2857,10 +2856,6 @@ xfs_finish_reclaim( | |||
2857 | int sync_mode) | 2856 | int sync_mode) |
2858 | { | 2857 | { |
2859 | xfs_perag_t *pag = xfs_get_perag(ip->i_mount, ip->i_ino); | 2858 | xfs_perag_t *pag = xfs_get_perag(ip->i_mount, ip->i_ino); |
2860 | struct inode *vp = VFS_I(ip); | ||
2861 | |||
2862 | if (vp && VN_BAD(vp)) | ||
2863 | goto reclaim; | ||
2864 | 2859 | ||
2865 | /* The hash lock here protects a thread in xfs_iget_core from | 2860 | /* The hash lock here protects a thread in xfs_iget_core from |
2866 | * racing with us on linking the inode back with a vnode. | 2861 | * racing with us on linking the inode back with a vnode. |
@@ -2870,7 +2865,7 @@ xfs_finish_reclaim( | |||
2870 | write_lock(&pag->pag_ici_lock); | 2865 | write_lock(&pag->pag_ici_lock); |
2871 | spin_lock(&ip->i_flags_lock); | 2866 | spin_lock(&ip->i_flags_lock); |
2872 | if (__xfs_iflags_test(ip, XFS_IRECLAIM) || | 2867 | if (__xfs_iflags_test(ip, XFS_IRECLAIM) || |
2873 | (!__xfs_iflags_test(ip, XFS_IRECLAIMABLE) && vp == NULL)) { | 2868 | !__xfs_iflags_test(ip, XFS_IRECLAIMABLE)) { |
2874 | spin_unlock(&ip->i_flags_lock); | 2869 | spin_unlock(&ip->i_flags_lock); |
2875 | write_unlock(&pag->pag_ici_lock); | 2870 | write_unlock(&pag->pag_ici_lock); |
2876 | if (locked) { | 2871 | if (locked) { |
@@ -2904,15 +2899,13 @@ xfs_finish_reclaim( | |||
2904 | * In the case of a forced shutdown we rely on xfs_iflush() to | 2899 | * In the case of a forced shutdown we rely on xfs_iflush() to |
2905 | * wait for the inode to be unpinned before returning an error. | 2900 | * wait for the inode to be unpinned before returning an error. |
2906 | */ | 2901 | */ |
2907 | if (xfs_iflush(ip, sync_mode) == 0) { | 2902 | if (!is_bad_inode(VFS_I(ip)) && xfs_iflush(ip, sync_mode) == 0) { |
2908 | /* synchronize with xfs_iflush_done */ | 2903 | /* synchronize with xfs_iflush_done */ |
2909 | xfs_iflock(ip); | 2904 | xfs_iflock(ip); |
2910 | xfs_ifunlock(ip); | 2905 | xfs_ifunlock(ip); |
2911 | } | 2906 | } |
2912 | 2907 | ||
2913 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | 2908 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
2914 | |||
2915 | reclaim: | ||
2916 | xfs_ireclaim(ip); | 2909 | xfs_ireclaim(ip); |
2917 | return 0; | 2910 | return 0; |
2918 | } | 2911 | } |