diff options
-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 | } |