aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_inode_item.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_inode_item.c')
-rw-r--r--fs/xfs/xfs_inode_item.c400
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
35kmem_zone_t *xfs_ili_zone; /* inode log item zone */ 36kmem_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 */
50STATIC void 43STATIC void
51xfs_inode_item_size( 44xfs_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)) 85STATIC void
100 return; 86xfs_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 */
154STATIC void 130STATIC void
155xfs_inode_item_format_extents( 131xfs_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 */
181STATIC void 154STATIC void
182xfs_inode_item_format( 155xfs_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
176STATIC void
177xfs_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 /* 275STATIC void
347 * If there are no attributes associated with the file, then we're done. 276xfs_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
438out:
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 */
363STATIC void
364xfs_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/*