diff options
Diffstat (limited to 'fs/xfs/xfs_inode_item.c')
-rw-r--r-- | fs/xfs/xfs_inode_item.c | 400 |
1 files changed, 162 insertions, 238 deletions
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index 7c0d391f9a6e..686889b4a1e5 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "xfs_trace.h" | 30 | #include "xfs_trace.h" |
31 | #include "xfs_trans_priv.h" | 31 | #include "xfs_trans_priv.h" |
32 | #include "xfs_dinode.h" | 32 | #include "xfs_dinode.h" |
33 | #include "xfs_log.h" | ||
33 | 34 | ||
34 | 35 | ||
35 | kmem_zone_t *xfs_ili_zone; /* inode log item zone */ | 36 | kmem_zone_t *xfs_ili_zone; /* inode log item zone */ |
@@ -39,27 +40,14 @@ static inline struct xfs_inode_log_item *INODE_ITEM(struct xfs_log_item *lip) | |||
39 | return container_of(lip, struct xfs_inode_log_item, ili_item); | 40 | return container_of(lip, struct xfs_inode_log_item, ili_item); |
40 | } | 41 | } |
41 | 42 | ||
42 | |||
43 | /* | ||
44 | * This returns the number of iovecs needed to log the given inode item. | ||
45 | * | ||
46 | * We need one iovec for the inode log format structure, one for the | ||
47 | * inode core, and possibly one for the inode data/extents/b-tree root | ||
48 | * and one for the inode attribute data/extents/b-tree root. | ||
49 | */ | ||
50 | STATIC void | 43 | STATIC void |
51 | xfs_inode_item_size( | 44 | xfs_inode_item_data_fork_size( |
52 | struct xfs_log_item *lip, | 45 | struct xfs_inode_log_item *iip, |
53 | int *nvecs, | 46 | int *nvecs, |
54 | int *nbytes) | 47 | int *nbytes) |
55 | { | 48 | { |
56 | struct xfs_inode_log_item *iip = INODE_ITEM(lip); | ||
57 | struct xfs_inode *ip = iip->ili_inode; | 49 | struct xfs_inode *ip = iip->ili_inode; |
58 | 50 | ||
59 | *nvecs += 2; | ||
60 | *nbytes += sizeof(struct xfs_inode_log_format) + | ||
61 | xfs_icdinode_size(ip->i_d.di_version); | ||
62 | |||
63 | switch (ip->i_d.di_format) { | 51 | switch (ip->i_d.di_format) { |
64 | case XFS_DINODE_FMT_EXTENTS: | 52 | case XFS_DINODE_FMT_EXTENTS: |
65 | if ((iip->ili_fields & XFS_ILOG_DEXT) && | 53 | if ((iip->ili_fields & XFS_ILOG_DEXT) && |
@@ -70,7 +58,6 @@ xfs_inode_item_size( | |||
70 | *nvecs += 1; | 58 | *nvecs += 1; |
71 | } | 59 | } |
72 | break; | 60 | break; |
73 | |||
74 | case XFS_DINODE_FMT_BTREE: | 61 | case XFS_DINODE_FMT_BTREE: |
75 | if ((iip->ili_fields & XFS_ILOG_DBROOT) && | 62 | if ((iip->ili_fields & XFS_ILOG_DBROOT) && |
76 | ip->i_df.if_broot_bytes > 0) { | 63 | ip->i_df.if_broot_bytes > 0) { |
@@ -78,7 +65,6 @@ xfs_inode_item_size( | |||
78 | *nvecs += 1; | 65 | *nvecs += 1; |
79 | } | 66 | } |
80 | break; | 67 | break; |
81 | |||
82 | case XFS_DINODE_FMT_LOCAL: | 68 | case XFS_DINODE_FMT_LOCAL: |
83 | if ((iip->ili_fields & XFS_ILOG_DDATA) && | 69 | if ((iip->ili_fields & XFS_ILOG_DDATA) && |
84 | ip->i_df.if_bytes > 0) { | 70 | ip->i_df.if_bytes > 0) { |
@@ -90,19 +76,20 @@ xfs_inode_item_size( | |||
90 | case XFS_DINODE_FMT_DEV: | 76 | case XFS_DINODE_FMT_DEV: |
91 | case XFS_DINODE_FMT_UUID: | 77 | case XFS_DINODE_FMT_UUID: |
92 | break; | 78 | break; |
93 | |||
94 | default: | 79 | default: |
95 | ASSERT(0); | 80 | ASSERT(0); |
96 | break; | 81 | break; |
97 | } | 82 | } |
83 | } | ||
98 | 84 | ||
99 | if (!XFS_IFORK_Q(ip)) | 85 | STATIC void |
100 | return; | 86 | xfs_inode_item_attr_fork_size( |
101 | 87 | struct xfs_inode_log_item *iip, | |
88 | int *nvecs, | ||
89 | int *nbytes) | ||
90 | { | ||
91 | struct xfs_inode *ip = iip->ili_inode; | ||
102 | 92 | ||
103 | /* | ||
104 | * Log any necessary attribute data. | ||
105 | */ | ||
106 | switch (ip->i_d.di_aformat) { | 93 | switch (ip->i_d.di_aformat) { |
107 | case XFS_DINODE_FMT_EXTENTS: | 94 | case XFS_DINODE_FMT_EXTENTS: |
108 | if ((iip->ili_fields & XFS_ILOG_AEXT) && | 95 | if ((iip->ili_fields & XFS_ILOG_AEXT) && |
@@ -113,7 +100,6 @@ xfs_inode_item_size( | |||
113 | *nvecs += 1; | 100 | *nvecs += 1; |
114 | } | 101 | } |
115 | break; | 102 | break; |
116 | |||
117 | case XFS_DINODE_FMT_BTREE: | 103 | case XFS_DINODE_FMT_BTREE: |
118 | if ((iip->ili_fields & XFS_ILOG_ABROOT) && | 104 | if ((iip->ili_fields & XFS_ILOG_ABROOT) && |
119 | ip->i_afp->if_broot_bytes > 0) { | 105 | ip->i_afp->if_broot_bytes > 0) { |
@@ -121,7 +107,6 @@ xfs_inode_item_size( | |||
121 | *nvecs += 1; | 107 | *nvecs += 1; |
122 | } | 108 | } |
123 | break; | 109 | break; |
124 | |||
125 | case XFS_DINODE_FMT_LOCAL: | 110 | case XFS_DINODE_FMT_LOCAL: |
126 | if ((iip->ili_fields & XFS_ILOG_ADATA) && | 111 | if ((iip->ili_fields & XFS_ILOG_ADATA) && |
127 | ip->i_afp->if_bytes > 0) { | 112 | ip->i_afp->if_bytes > 0) { |
@@ -129,7 +114,6 @@ xfs_inode_item_size( | |||
129 | *nvecs += 1; | 114 | *nvecs += 1; |
130 | } | 115 | } |
131 | break; | 116 | break; |
132 | |||
133 | default: | 117 | default: |
134 | ASSERT(0); | 118 | ASSERT(0); |
135 | break; | 119 | break; |
@@ -137,98 +121,67 @@ xfs_inode_item_size( | |||
137 | } | 121 | } |
138 | 122 | ||
139 | /* | 123 | /* |
140 | * xfs_inode_item_format_extents - convert in-core extents to on-disk form | 124 | * This returns the number of iovecs needed to log the given inode item. |
141 | * | ||
142 | * For either the data or attr fork in extent format, we need to endian convert | ||
143 | * the in-core extent as we place them into the on-disk inode. In this case, we | ||
144 | * need to do this conversion before we write the extents into the log. Because | ||
145 | * we don't have the disk inode to write into here, we allocate a buffer and | ||
146 | * format the extents into it via xfs_iextents_copy(). We free the buffer in | ||
147 | * the unlock routine after the copy for the log has been made. | ||
148 | * | 125 | * |
149 | * In the case of the data fork, the in-core and on-disk fork sizes can be | 126 | * We need one iovec for the inode log format structure, one for the |
150 | * different due to delayed allocation extents. We only log on-disk extents | 127 | * inode core, and possibly one for the inode data/extents/b-tree root |
151 | * here, so always use the physical fork size to determine the size of the | 128 | * and one for the inode attribute data/extents/b-tree root. |
152 | * buffer we need to allocate. | ||
153 | */ | 129 | */ |
154 | STATIC void | 130 | STATIC void |
155 | xfs_inode_item_format_extents( | 131 | xfs_inode_item_size( |
156 | struct xfs_inode *ip, | 132 | struct xfs_log_item *lip, |
157 | struct xfs_log_iovec *vecp, | 133 | int *nvecs, |
158 | int whichfork, | 134 | int *nbytes) |
159 | int type) | ||
160 | { | 135 | { |
161 | xfs_bmbt_rec_t *ext_buffer; | 136 | struct xfs_inode_log_item *iip = INODE_ITEM(lip); |
137 | struct xfs_inode *ip = iip->ili_inode; | ||
162 | 138 | ||
163 | ext_buffer = kmem_alloc(XFS_IFORK_SIZE(ip, whichfork), KM_SLEEP); | 139 | *nvecs += 2; |
164 | if (whichfork == XFS_DATA_FORK) | 140 | *nbytes += sizeof(struct xfs_inode_log_format) + |
165 | ip->i_itemp->ili_extents_buf = ext_buffer; | 141 | xfs_icdinode_size(ip->i_d.di_version); |
166 | else | ||
167 | ip->i_itemp->ili_aextents_buf = ext_buffer; | ||
168 | 142 | ||
169 | vecp->i_addr = ext_buffer; | 143 | xfs_inode_item_data_fork_size(iip, nvecs, nbytes); |
170 | vecp->i_len = xfs_iextents_copy(ip, ext_buffer, whichfork); | 144 | if (XFS_IFORK_Q(ip)) |
171 | vecp->i_type = type; | 145 | xfs_inode_item_attr_fork_size(iip, nvecs, nbytes); |
172 | } | 146 | } |
173 | 147 | ||
174 | /* | 148 | /* |
175 | * This is called to fill in the vector of log iovecs for the | 149 | * If this is a v1 format inode, then we need to log it as such. This means |
176 | * given inode log item. It fills the first item with an inode | 150 | * that we have to copy the link count from the new field to the old. We |
177 | * log format structure, the second with the on-disk inode structure, | 151 | * don't have to worry about the new fields, because nothing trusts them as |
178 | * and a possible third and/or fourth with the inode data/extents/b-tree | 152 | * long as the old inode version number is there. |
179 | * root and inode attributes data/extents/b-tree root. | ||
180 | */ | 153 | */ |
181 | STATIC void | 154 | STATIC void |
182 | xfs_inode_item_format( | 155 | xfs_inode_item_format_v1_inode( |
183 | struct xfs_log_item *lip, | 156 | struct xfs_inode *ip) |
184 | struct xfs_log_iovec *vecp) | 157 | { |
158 | if (!xfs_sb_version_hasnlink(&ip->i_mount->m_sb)) { | ||
159 | /* | ||
160 | * Convert it back. | ||
161 | */ | ||
162 | ASSERT(ip->i_d.di_nlink <= XFS_MAXLINK_1); | ||
163 | ip->i_d.di_onlink = ip->i_d.di_nlink; | ||
164 | } else { | ||
165 | /* | ||
166 | * The superblock version has already been bumped, | ||
167 | * so just make the conversion to the new inode | ||
168 | * format permanent. | ||
169 | */ | ||
170 | ip->i_d.di_version = 2; | ||
171 | ip->i_d.di_onlink = 0; | ||
172 | memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad)); | ||
173 | } | ||
174 | } | ||
175 | |||
176 | STATIC void | ||
177 | xfs_inode_item_format_data_fork( | ||
178 | struct xfs_inode_log_item *iip, | ||
179 | struct xfs_inode_log_format *ilf, | ||
180 | struct xfs_log_vec *lv, | ||
181 | struct xfs_log_iovec **vecp) | ||
185 | { | 182 | { |
186 | struct xfs_inode_log_item *iip = INODE_ITEM(lip); | ||
187 | struct xfs_inode *ip = iip->ili_inode; | 183 | struct xfs_inode *ip = iip->ili_inode; |
188 | uint nvecs; | ||
189 | size_t data_bytes; | 184 | size_t data_bytes; |
190 | xfs_mount_t *mp; | ||
191 | |||
192 | vecp->i_addr = &iip->ili_format; | ||
193 | vecp->i_len = sizeof(xfs_inode_log_format_t); | ||
194 | vecp->i_type = XLOG_REG_TYPE_IFORMAT; | ||
195 | vecp++; | ||
196 | nvecs = 1; | ||
197 | |||
198 | vecp->i_addr = &ip->i_d; | ||
199 | vecp->i_len = xfs_icdinode_size(ip->i_d.di_version); | ||
200 | vecp->i_type = XLOG_REG_TYPE_ICORE; | ||
201 | vecp++; | ||
202 | nvecs++; | ||
203 | |||
204 | /* | ||
205 | * If this is really an old format inode, then we need to | ||
206 | * log it as such. This means that we have to copy the link | ||
207 | * count from the new field to the old. We don't have to worry | ||
208 | * about the new fields, because nothing trusts them as long as | ||
209 | * the old inode version number is there. If the superblock already | ||
210 | * has a new version number, then we don't bother converting back. | ||
211 | */ | ||
212 | mp = ip->i_mount; | ||
213 | ASSERT(ip->i_d.di_version == 1 || xfs_sb_version_hasnlink(&mp->m_sb)); | ||
214 | if (ip->i_d.di_version == 1) { | ||
215 | if (!xfs_sb_version_hasnlink(&mp->m_sb)) { | ||
216 | /* | ||
217 | * Convert it back. | ||
218 | */ | ||
219 | ASSERT(ip->i_d.di_nlink <= XFS_MAXLINK_1); | ||
220 | ip->i_d.di_onlink = ip->i_d.di_nlink; | ||
221 | } else { | ||
222 | /* | ||
223 | * The superblock version has already been bumped, | ||
224 | * so just make the conversion to the new inode | ||
225 | * format permanent. | ||
226 | */ | ||
227 | ip->i_d.di_version = 2; | ||
228 | ip->i_d.di_onlink = 0; | ||
229 | memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad)); | ||
230 | } | ||
231 | } | ||
232 | 185 | ||
233 | switch (ip->i_d.di_format) { | 186 | switch (ip->i_d.di_format) { |
234 | case XFS_DINODE_FMT_EXTENTS: | 187 | case XFS_DINODE_FMT_EXTENTS: |
@@ -239,36 +192,23 @@ xfs_inode_item_format( | |||
239 | if ((iip->ili_fields & XFS_ILOG_DEXT) && | 192 | if ((iip->ili_fields & XFS_ILOG_DEXT) && |
240 | ip->i_d.di_nextents > 0 && | 193 | ip->i_d.di_nextents > 0 && |
241 | ip->i_df.if_bytes > 0) { | 194 | ip->i_df.if_bytes > 0) { |
195 | struct xfs_bmbt_rec *p; | ||
196 | |||
242 | ASSERT(ip->i_df.if_u1.if_extents != NULL); | 197 | ASSERT(ip->i_df.if_u1.if_extents != NULL); |
243 | ASSERT(ip->i_df.if_bytes / sizeof(xfs_bmbt_rec_t) > 0); | 198 | ASSERT(ip->i_df.if_bytes / sizeof(xfs_bmbt_rec_t) > 0); |
244 | ASSERT(iip->ili_extents_buf == NULL); | 199 | |
245 | 200 | p = xlog_prepare_iovec(lv, vecp, XLOG_REG_TYPE_IEXT); | |
246 | #ifdef XFS_NATIVE_HOST | 201 | data_bytes = xfs_iextents_copy(ip, p, XFS_DATA_FORK); |
247 | if (ip->i_d.di_nextents == ip->i_df.if_bytes / | 202 | xlog_finish_iovec(lv, *vecp, data_bytes); |
248 | (uint)sizeof(xfs_bmbt_rec_t)) { | 203 | |
249 | /* | 204 | ASSERT(data_bytes <= ip->i_df.if_bytes); |
250 | * There are no delayed allocation | 205 | |
251 | * extents, so just point to the | 206 | ilf->ilf_dsize = data_bytes; |
252 | * real extents array. | 207 | ilf->ilf_size++; |
253 | */ | ||
254 | vecp->i_addr = ip->i_df.if_u1.if_extents; | ||
255 | vecp->i_len = ip->i_df.if_bytes; | ||
256 | vecp->i_type = XLOG_REG_TYPE_IEXT; | ||
257 | } else | ||
258 | #endif | ||
259 | { | ||
260 | xfs_inode_item_format_extents(ip, vecp, | ||
261 | XFS_DATA_FORK, XLOG_REG_TYPE_IEXT); | ||
262 | } | ||
263 | ASSERT(vecp->i_len <= ip->i_df.if_bytes); | ||
264 | iip->ili_format.ilf_dsize = vecp->i_len; | ||
265 | vecp++; | ||
266 | nvecs++; | ||
267 | } else { | 208 | } else { |
268 | iip->ili_fields &= ~XFS_ILOG_DEXT; | 209 | iip->ili_fields &= ~XFS_ILOG_DEXT; |
269 | } | 210 | } |
270 | break; | 211 | break; |
271 | |||
272 | case XFS_DINODE_FMT_BTREE: | 212 | case XFS_DINODE_FMT_BTREE: |
273 | iip->ili_fields &= | 213 | iip->ili_fields &= |
274 | ~(XFS_ILOG_DDATA | XFS_ILOG_DEXT | | 214 | ~(XFS_ILOG_DDATA | XFS_ILOG_DEXT | |
@@ -277,80 +217,70 @@ xfs_inode_item_format( | |||
277 | if ((iip->ili_fields & XFS_ILOG_DBROOT) && | 217 | if ((iip->ili_fields & XFS_ILOG_DBROOT) && |
278 | ip->i_df.if_broot_bytes > 0) { | 218 | ip->i_df.if_broot_bytes > 0) { |
279 | ASSERT(ip->i_df.if_broot != NULL); | 219 | ASSERT(ip->i_df.if_broot != NULL); |
280 | vecp->i_addr = ip->i_df.if_broot; | 220 | xlog_copy_iovec(lv, vecp, XLOG_REG_TYPE_IBROOT, |
281 | vecp->i_len = ip->i_df.if_broot_bytes; | 221 | ip->i_df.if_broot, |
282 | vecp->i_type = XLOG_REG_TYPE_IBROOT; | 222 | ip->i_df.if_broot_bytes); |
283 | vecp++; | 223 | ilf->ilf_dsize = ip->i_df.if_broot_bytes; |
284 | nvecs++; | 224 | ilf->ilf_size++; |
285 | iip->ili_format.ilf_dsize = ip->i_df.if_broot_bytes; | ||
286 | } else { | 225 | } else { |
287 | ASSERT(!(iip->ili_fields & | 226 | ASSERT(!(iip->ili_fields & |
288 | XFS_ILOG_DBROOT)); | 227 | XFS_ILOG_DBROOT)); |
289 | iip->ili_fields &= ~XFS_ILOG_DBROOT; | 228 | iip->ili_fields &= ~XFS_ILOG_DBROOT; |
290 | } | 229 | } |
291 | break; | 230 | break; |
292 | |||
293 | case XFS_DINODE_FMT_LOCAL: | 231 | case XFS_DINODE_FMT_LOCAL: |
294 | iip->ili_fields &= | 232 | iip->ili_fields &= |
295 | ~(XFS_ILOG_DEXT | XFS_ILOG_DBROOT | | 233 | ~(XFS_ILOG_DEXT | XFS_ILOG_DBROOT | |
296 | XFS_ILOG_DEV | XFS_ILOG_UUID); | 234 | XFS_ILOG_DEV | XFS_ILOG_UUID); |
297 | if ((iip->ili_fields & XFS_ILOG_DDATA) && | 235 | if ((iip->ili_fields & XFS_ILOG_DDATA) && |
298 | ip->i_df.if_bytes > 0) { | 236 | ip->i_df.if_bytes > 0) { |
299 | ASSERT(ip->i_df.if_u1.if_data != NULL); | ||
300 | ASSERT(ip->i_d.di_size > 0); | ||
301 | |||
302 | vecp->i_addr = ip->i_df.if_u1.if_data; | ||
303 | /* | 237 | /* |
304 | * Round i_bytes up to a word boundary. | 238 | * Round i_bytes up to a word boundary. |
305 | * The underlying memory is guaranteed to | 239 | * The underlying memory is guaranteed to |
306 | * to be there by xfs_idata_realloc(). | 240 | * to be there by xfs_idata_realloc(). |
307 | */ | 241 | */ |
308 | data_bytes = roundup(ip->i_df.if_bytes, 4); | 242 | data_bytes = roundup(ip->i_df.if_bytes, 4); |
309 | ASSERT((ip->i_df.if_real_bytes == 0) || | 243 | ASSERT(ip->i_df.if_real_bytes == 0 || |
310 | (ip->i_df.if_real_bytes == data_bytes)); | 244 | ip->i_df.if_real_bytes == data_bytes); |
311 | vecp->i_len = (int)data_bytes; | 245 | ASSERT(ip->i_df.if_u1.if_data != NULL); |
312 | vecp->i_type = XLOG_REG_TYPE_ILOCAL; | 246 | ASSERT(ip->i_d.di_size > 0); |
313 | vecp++; | 247 | xlog_copy_iovec(lv, vecp, XLOG_REG_TYPE_ILOCAL, |
314 | nvecs++; | 248 | ip->i_df.if_u1.if_data, data_bytes); |
315 | iip->ili_format.ilf_dsize = (unsigned)data_bytes; | 249 | ilf->ilf_dsize = (unsigned)data_bytes; |
250 | ilf->ilf_size++; | ||
316 | } else { | 251 | } else { |
317 | iip->ili_fields &= ~XFS_ILOG_DDATA; | 252 | iip->ili_fields &= ~XFS_ILOG_DDATA; |
318 | } | 253 | } |
319 | break; | 254 | break; |
320 | |||
321 | case XFS_DINODE_FMT_DEV: | 255 | case XFS_DINODE_FMT_DEV: |
322 | iip->ili_fields &= | 256 | iip->ili_fields &= |
323 | ~(XFS_ILOG_DDATA | XFS_ILOG_DBROOT | | 257 | ~(XFS_ILOG_DDATA | XFS_ILOG_DBROOT | |
324 | XFS_ILOG_DEXT | XFS_ILOG_UUID); | 258 | XFS_ILOG_DEXT | XFS_ILOG_UUID); |
325 | if (iip->ili_fields & XFS_ILOG_DEV) { | 259 | if (iip->ili_fields & XFS_ILOG_DEV) |
326 | iip->ili_format.ilf_u.ilfu_rdev = | 260 | ilf->ilf_u.ilfu_rdev = ip->i_df.if_u2.if_rdev; |
327 | ip->i_df.if_u2.if_rdev; | ||
328 | } | ||
329 | break; | 261 | break; |
330 | |||
331 | case XFS_DINODE_FMT_UUID: | 262 | case XFS_DINODE_FMT_UUID: |
332 | iip->ili_fields &= | 263 | iip->ili_fields &= |
333 | ~(XFS_ILOG_DDATA | XFS_ILOG_DBROOT | | 264 | ~(XFS_ILOG_DDATA | XFS_ILOG_DBROOT | |
334 | XFS_ILOG_DEXT | XFS_ILOG_DEV); | 265 | XFS_ILOG_DEXT | XFS_ILOG_DEV); |
335 | if (iip->ili_fields & XFS_ILOG_UUID) { | 266 | if (iip->ili_fields & XFS_ILOG_UUID) |
336 | iip->ili_format.ilf_u.ilfu_uuid = | 267 | ilf->ilf_u.ilfu_uuid = ip->i_df.if_u2.if_uuid; |
337 | ip->i_df.if_u2.if_uuid; | ||
338 | } | ||
339 | break; | 268 | break; |
340 | |||
341 | default: | 269 | default: |
342 | ASSERT(0); | 270 | ASSERT(0); |
343 | break; | 271 | break; |
344 | } | 272 | } |
273 | } | ||
345 | 274 | ||
346 | /* | 275 | STATIC void |
347 | * If there are no attributes associated with the file, then we're done. | 276 | xfs_inode_item_format_attr_fork( |
348 | */ | 277 | struct xfs_inode_log_item *iip, |
349 | if (!XFS_IFORK_Q(ip)) { | 278 | struct xfs_inode_log_format *ilf, |
350 | iip->ili_fields &= | 279 | struct xfs_log_vec *lv, |
351 | ~(XFS_ILOG_ADATA | XFS_ILOG_ABROOT | XFS_ILOG_AEXT); | 280 | struct xfs_log_iovec **vecp) |
352 | goto out; | 281 | { |
353 | } | 282 | struct xfs_inode *ip = iip->ili_inode; |
283 | size_t data_bytes; | ||
354 | 284 | ||
355 | switch (ip->i_d.di_aformat) { | 285 | switch (ip->i_d.di_aformat) { |
356 | case XFS_DINODE_FMT_EXTENTS: | 286 | case XFS_DINODE_FMT_EXTENTS: |
@@ -360,30 +290,22 @@ xfs_inode_item_format( | |||
360 | if ((iip->ili_fields & XFS_ILOG_AEXT) && | 290 | if ((iip->ili_fields & XFS_ILOG_AEXT) && |
361 | ip->i_d.di_anextents > 0 && | 291 | ip->i_d.di_anextents > 0 && |
362 | ip->i_afp->if_bytes > 0) { | 292 | ip->i_afp->if_bytes > 0) { |
293 | struct xfs_bmbt_rec *p; | ||
294 | |||
363 | ASSERT(ip->i_afp->if_bytes / sizeof(xfs_bmbt_rec_t) == | 295 | ASSERT(ip->i_afp->if_bytes / sizeof(xfs_bmbt_rec_t) == |
364 | ip->i_d.di_anextents); | 296 | ip->i_d.di_anextents); |
365 | ASSERT(ip->i_afp->if_u1.if_extents != NULL); | 297 | ASSERT(ip->i_afp->if_u1.if_extents != NULL); |
366 | #ifdef XFS_NATIVE_HOST | 298 | |
367 | /* | 299 | p = xlog_prepare_iovec(lv, vecp, XLOG_REG_TYPE_IATTR_EXT); |
368 | * There are not delayed allocation extents | 300 | data_bytes = xfs_iextents_copy(ip, p, XFS_ATTR_FORK); |
369 | * for attributes, so just point at the array. | 301 | xlog_finish_iovec(lv, *vecp, data_bytes); |
370 | */ | 302 | |
371 | vecp->i_addr = ip->i_afp->if_u1.if_extents; | 303 | ilf->ilf_asize = data_bytes; |
372 | vecp->i_len = ip->i_afp->if_bytes; | 304 | ilf->ilf_size++; |
373 | vecp->i_type = XLOG_REG_TYPE_IATTR_EXT; | ||
374 | #else | ||
375 | ASSERT(iip->ili_aextents_buf == NULL); | ||
376 | xfs_inode_item_format_extents(ip, vecp, | ||
377 | XFS_ATTR_FORK, XLOG_REG_TYPE_IATTR_EXT); | ||
378 | #endif | ||
379 | iip->ili_format.ilf_asize = vecp->i_len; | ||
380 | vecp++; | ||
381 | nvecs++; | ||
382 | } else { | 305 | } else { |
383 | iip->ili_fields &= ~XFS_ILOG_AEXT; | 306 | iip->ili_fields &= ~XFS_ILOG_AEXT; |
384 | } | 307 | } |
385 | break; | 308 | break; |
386 | |||
387 | case XFS_DINODE_FMT_BTREE: | 309 | case XFS_DINODE_FMT_BTREE: |
388 | iip->ili_fields &= | 310 | iip->ili_fields &= |
389 | ~(XFS_ILOG_ADATA | XFS_ILOG_AEXT); | 311 | ~(XFS_ILOG_ADATA | XFS_ILOG_AEXT); |
@@ -392,61 +314,89 @@ xfs_inode_item_format( | |||
392 | ip->i_afp->if_broot_bytes > 0) { | 314 | ip->i_afp->if_broot_bytes > 0) { |
393 | ASSERT(ip->i_afp->if_broot != NULL); | 315 | ASSERT(ip->i_afp->if_broot != NULL); |
394 | 316 | ||
395 | vecp->i_addr = ip->i_afp->if_broot; | 317 | xlog_copy_iovec(lv, vecp, XLOG_REG_TYPE_IATTR_BROOT, |
396 | vecp->i_len = ip->i_afp->if_broot_bytes; | 318 | ip->i_afp->if_broot, |
397 | vecp->i_type = XLOG_REG_TYPE_IATTR_BROOT; | 319 | ip->i_afp->if_broot_bytes); |
398 | vecp++; | 320 | ilf->ilf_asize = ip->i_afp->if_broot_bytes; |
399 | nvecs++; | 321 | ilf->ilf_size++; |
400 | iip->ili_format.ilf_asize = ip->i_afp->if_broot_bytes; | ||
401 | } else { | 322 | } else { |
402 | iip->ili_fields &= ~XFS_ILOG_ABROOT; | 323 | iip->ili_fields &= ~XFS_ILOG_ABROOT; |
403 | } | 324 | } |
404 | break; | 325 | break; |
405 | |||
406 | case XFS_DINODE_FMT_LOCAL: | 326 | case XFS_DINODE_FMT_LOCAL: |
407 | iip->ili_fields &= | 327 | iip->ili_fields &= |
408 | ~(XFS_ILOG_AEXT | XFS_ILOG_ABROOT); | 328 | ~(XFS_ILOG_AEXT | XFS_ILOG_ABROOT); |
409 | 329 | ||
410 | if ((iip->ili_fields & XFS_ILOG_ADATA) && | 330 | if ((iip->ili_fields & XFS_ILOG_ADATA) && |
411 | ip->i_afp->if_bytes > 0) { | 331 | ip->i_afp->if_bytes > 0) { |
412 | ASSERT(ip->i_afp->if_u1.if_data != NULL); | ||
413 | |||
414 | vecp->i_addr = ip->i_afp->if_u1.if_data; | ||
415 | /* | 332 | /* |
416 | * Round i_bytes up to a word boundary. | 333 | * Round i_bytes up to a word boundary. |
417 | * The underlying memory is guaranteed to | 334 | * The underlying memory is guaranteed to |
418 | * to be there by xfs_idata_realloc(). | 335 | * to be there by xfs_idata_realloc(). |
419 | */ | 336 | */ |
420 | data_bytes = roundup(ip->i_afp->if_bytes, 4); | 337 | data_bytes = roundup(ip->i_afp->if_bytes, 4); |
421 | ASSERT((ip->i_afp->if_real_bytes == 0) || | 338 | ASSERT(ip->i_afp->if_real_bytes == 0 || |
422 | (ip->i_afp->if_real_bytes == data_bytes)); | 339 | ip->i_afp->if_real_bytes == data_bytes); |
423 | vecp->i_len = (int)data_bytes; | 340 | ASSERT(ip->i_afp->if_u1.if_data != NULL); |
424 | vecp->i_type = XLOG_REG_TYPE_IATTR_LOCAL; | 341 | xlog_copy_iovec(lv, vecp, XLOG_REG_TYPE_IATTR_LOCAL, |
425 | vecp++; | 342 | ip->i_afp->if_u1.if_data, |
426 | nvecs++; | 343 | data_bytes); |
427 | iip->ili_format.ilf_asize = (unsigned)data_bytes; | 344 | ilf->ilf_asize = (unsigned)data_bytes; |
345 | ilf->ilf_size++; | ||
428 | } else { | 346 | } else { |
429 | iip->ili_fields &= ~XFS_ILOG_ADATA; | 347 | iip->ili_fields &= ~XFS_ILOG_ADATA; |
430 | } | 348 | } |
431 | break; | 349 | break; |
432 | |||
433 | default: | 350 | default: |
434 | ASSERT(0); | 351 | ASSERT(0); |
435 | break; | 352 | break; |
436 | } | 353 | } |
437 | |||
438 | out: | ||
439 | /* | ||
440 | * Now update the log format that goes out to disk from the in-core | ||
441 | * values. We always write the inode core to make the arithmetic | ||
442 | * games in recovery easier, which isn't a big deal as just about any | ||
443 | * transaction would dirty it anyway. | ||
444 | */ | ||
445 | iip->ili_format.ilf_fields = XFS_ILOG_CORE | | ||
446 | (iip->ili_fields & ~XFS_ILOG_TIMESTAMP); | ||
447 | iip->ili_format.ilf_size = nvecs; | ||
448 | } | 354 | } |
449 | 355 | ||
356 | /* | ||
357 | * This is called to fill in the vector of log iovecs for the given inode | ||
358 | * log item. It fills the first item with an inode log format structure, | ||
359 | * the second with the on-disk inode structure, and a possible third and/or | ||
360 | * fourth with the inode data/extents/b-tree root and inode attributes | ||
361 | * data/extents/b-tree root. | ||
362 | */ | ||
363 | STATIC void | ||
364 | xfs_inode_item_format( | ||
365 | struct xfs_log_item *lip, | ||
366 | struct xfs_log_vec *lv) | ||
367 | { | ||
368 | struct xfs_inode_log_item *iip = INODE_ITEM(lip); | ||
369 | struct xfs_inode *ip = iip->ili_inode; | ||
370 | struct xfs_inode_log_format *ilf; | ||
371 | struct xfs_log_iovec *vecp = NULL; | ||
372 | |||
373 | ilf = xlog_prepare_iovec(lv, &vecp, XLOG_REG_TYPE_IFORMAT); | ||
374 | ilf->ilf_type = XFS_LI_INODE; | ||
375 | ilf->ilf_ino = ip->i_ino; | ||
376 | ilf->ilf_blkno = ip->i_imap.im_blkno; | ||
377 | ilf->ilf_len = ip->i_imap.im_len; | ||
378 | ilf->ilf_boffset = ip->i_imap.im_boffset; | ||
379 | ilf->ilf_fields = XFS_ILOG_CORE; | ||
380 | ilf->ilf_size = 2; /* format + core */ | ||
381 | xlog_finish_iovec(lv, vecp, sizeof(struct xfs_inode_log_format)); | ||
382 | |||
383 | if (ip->i_d.di_version == 1) | ||
384 | xfs_inode_item_format_v1_inode(ip); | ||
385 | xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_ICORE, | ||
386 | &ip->i_d, | ||
387 | xfs_icdinode_size(ip->i_d.di_version)); | ||
388 | |||
389 | xfs_inode_item_format_data_fork(iip, ilf, lv, &vecp); | ||
390 | if (XFS_IFORK_Q(ip)) { | ||
391 | xfs_inode_item_format_attr_fork(iip, ilf, lv, &vecp); | ||
392 | } else { | ||
393 | iip->ili_fields &= | ||
394 | ~(XFS_ILOG_ADATA | XFS_ILOG_ABROOT | XFS_ILOG_AEXT); | ||
395 | } | ||
396 | |||
397 | /* update the format with the exact fields we actually logged */ | ||
398 | ilf->ilf_fields |= (iip->ili_fields & ~XFS_ILOG_TIMESTAMP); | ||
399 | } | ||
450 | 400 | ||
451 | /* | 401 | /* |
452 | * This is called to pin the inode associated with the inode log | 402 | * This is called to pin the inode associated with the inode log |
@@ -563,27 +513,6 @@ xfs_inode_item_unlock( | |||
563 | ASSERT(ip->i_itemp != NULL); | 513 | ASSERT(ip->i_itemp != NULL); |
564 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); | 514 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); |
565 | 515 | ||
566 | /* | ||
567 | * If the inode needed a separate buffer with which to log | ||
568 | * its extents, then free it now. | ||
569 | */ | ||
570 | if (iip->ili_extents_buf != NULL) { | ||
571 | ASSERT(ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS); | ||
572 | ASSERT(ip->i_d.di_nextents > 0); | ||
573 | ASSERT(iip->ili_fields & XFS_ILOG_DEXT); | ||
574 | ASSERT(ip->i_df.if_bytes > 0); | ||
575 | kmem_free(iip->ili_extents_buf); | ||
576 | iip->ili_extents_buf = NULL; | ||
577 | } | ||
578 | if (iip->ili_aextents_buf != NULL) { | ||
579 | ASSERT(ip->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS); | ||
580 | ASSERT(ip->i_d.di_anextents > 0); | ||
581 | ASSERT(iip->ili_fields & XFS_ILOG_AEXT); | ||
582 | ASSERT(ip->i_afp->if_bytes > 0); | ||
583 | kmem_free(iip->ili_aextents_buf); | ||
584 | iip->ili_aextents_buf = NULL; | ||
585 | } | ||
586 | |||
587 | lock_flags = iip->ili_lock_flags; | 516 | lock_flags = iip->ili_lock_flags; |
588 | iip->ili_lock_flags = 0; | 517 | iip->ili_lock_flags = 0; |
589 | if (lock_flags) | 518 | if (lock_flags) |
@@ -670,11 +599,6 @@ xfs_inode_item_init( | |||
670 | iip->ili_inode = ip; | 599 | iip->ili_inode = ip; |
671 | xfs_log_item_init(mp, &iip->ili_item, XFS_LI_INODE, | 600 | xfs_log_item_init(mp, &iip->ili_item, XFS_LI_INODE, |
672 | &xfs_inode_item_ops); | 601 | &xfs_inode_item_ops); |
673 | iip->ili_format.ilf_type = XFS_LI_INODE; | ||
674 | iip->ili_format.ilf_ino = ip->i_ino; | ||
675 | iip->ili_format.ilf_blkno = ip->i_imap.im_blkno; | ||
676 | iip->ili_format.ilf_len = ip->i_imap.im_len; | ||
677 | iip->ili_format.ilf_boffset = ip->i_imap.im_boffset; | ||
678 | } | 602 | } |
679 | 603 | ||
680 | /* | 604 | /* |