aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Chinner <david@fromorbit.com>2008-10-30 02:36:14 -0400
committerLachlan McIlroy <lachlan@sgi.com>2008-10-30 02:36:14 -0400
commitbf904248a2adb3f3be4eb4fb1837ce3bb28cca76 (patch)
tree288306924f640f19d881166a3b50fa59b6e9e7e7
parent8290c35f87304a6b73d4fd17b03580b4f7425de8 (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>
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.c17
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c47
-rw-r--r--fs/xfs/linux-2.6/xfs_vnode.c15
-rw-r--r--fs/xfs/xfs_iget.c167
-rw-r--r--fs/xfs/xfs_inode.c43
-rw-r--r--fs/xfs/xfs_inode.h9
-rw-r--r--fs/xfs/xfs_vnodeops.c13
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 3bfb3c0f8e2..37bb1012aff 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 */
770void 774void
771xfs_setup_inode( 775xfs_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 b87e45577a5..c6ef684bf2e 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
73static struct quotactl_ops xfs_quotactl_operations; 73static struct quotactl_ops xfs_quotactl_operations;
74static struct super_operations xfs_super_operations; 74static struct super_operations xfs_super_operations;
75static kmem_zone_t *xfs_vnode_zone;
76static kmem_zone_t *xfs_ioend_zone; 75static kmem_zone_t *xfs_ioend_zone;
77mempool_t *xfs_ioend_pool; 76mempool_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 */
871STATIC struct inode * 870STATIC struct inode *
872xfs_fs_alloc_inode( 871xfs_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 */
878STATIC void 881STATIC void
879xfs_fs_destroy_inode( 882xfs_fs_destroy_inode(
880 struct inode *inode) 883 struct inode *inode)
881{
882 kmem_zone_free(xfs_vnode_zone, inode);
883}
884
885STATIC void
886xfs_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 */
901void 895STATIC void
902xfs_inode_init_once( 896xfs_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
982STATIC void 979STATIC void
@@ -1829,16 +1826,10 @@ xfs_free_trace_bufs(void)
1829STATIC int __init 1826STATIC int __init
1830xfs_init_zones(void) 1827xfs_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 ac827d23149..ad18262d651 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 */
91static 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 b2539b17c95..c4414e8bce8 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -44,77 +44,65 @@
44 */ 44 */
45static int 45static int
46xfs_iget_cache_hit( 46xfs_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 */
239STATIC int 227int
240xfs_iget_core( 228xfs_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 */
320int
321xfs_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
336retry:
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 bc33762abc4..99d9118c4a4 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 */
2654void 2675void
2655xfs_idestroy( 2676xfs_idestroy(
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 6fd20fc179a..345b43a90eb 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 */
299static inline struct xfs_inode *XFS_I(struct inode *inode) 302static 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 */
305static inline struct inode *VFS_I(struct xfs_inode *ip) 308static 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 a6714579a41..7fb577c9f9d 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}