diff options
Diffstat (limited to 'fs/xfs/libxfs/xfs_inode_buf.c')
-rw-r--r-- | fs/xfs/libxfs/xfs_inode_buf.c | 170 |
1 files changed, 111 insertions, 59 deletions
diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c index 1aabfda669b0..9d9559eb2835 100644 --- a/fs/xfs/libxfs/xfs_inode_buf.c +++ b/fs/xfs/libxfs/xfs_inode_buf.c | |||
@@ -195,28 +195,50 @@ xfs_imap_to_bp( | |||
195 | } | 195 | } |
196 | 196 | ||
197 | void | 197 | void |
198 | xfs_dinode_from_disk( | 198 | xfs_inode_from_disk( |
199 | xfs_icdinode_t *to, | 199 | struct xfs_inode *ip, |
200 | xfs_dinode_t *from) | 200 | struct xfs_dinode *from) |
201 | { | 201 | { |
202 | to->di_magic = be16_to_cpu(from->di_magic); | 202 | struct xfs_icdinode *to = &ip->i_d; |
203 | to->di_mode = be16_to_cpu(from->di_mode); | 203 | struct inode *inode = VFS_I(ip); |
204 | to->di_version = from ->di_version; | 204 | |
205 | |||
206 | /* | ||
207 | * Convert v1 inodes immediately to v2 inode format as this is the | ||
208 | * minimum inode version format we support in the rest of the code. | ||
209 | */ | ||
210 | to->di_version = from->di_version; | ||
211 | if (to->di_version == 1) { | ||
212 | set_nlink(inode, be16_to_cpu(from->di_onlink)); | ||
213 | to->di_projid_lo = 0; | ||
214 | to->di_projid_hi = 0; | ||
215 | to->di_version = 2; | ||
216 | } else { | ||
217 | set_nlink(inode, be32_to_cpu(from->di_nlink)); | ||
218 | to->di_projid_lo = be16_to_cpu(from->di_projid_lo); | ||
219 | to->di_projid_hi = be16_to_cpu(from->di_projid_hi); | ||
220 | } | ||
221 | |||
205 | to->di_format = from->di_format; | 222 | to->di_format = from->di_format; |
206 | to->di_onlink = be16_to_cpu(from->di_onlink); | ||
207 | to->di_uid = be32_to_cpu(from->di_uid); | 223 | to->di_uid = be32_to_cpu(from->di_uid); |
208 | to->di_gid = be32_to_cpu(from->di_gid); | 224 | to->di_gid = be32_to_cpu(from->di_gid); |
209 | to->di_nlink = be32_to_cpu(from->di_nlink); | ||
210 | to->di_projid_lo = be16_to_cpu(from->di_projid_lo); | ||
211 | to->di_projid_hi = be16_to_cpu(from->di_projid_hi); | ||
212 | memcpy(to->di_pad, from->di_pad, sizeof(to->di_pad)); | ||
213 | to->di_flushiter = be16_to_cpu(from->di_flushiter); | 225 | to->di_flushiter = be16_to_cpu(from->di_flushiter); |
214 | to->di_atime.t_sec = be32_to_cpu(from->di_atime.t_sec); | 226 | |
215 | to->di_atime.t_nsec = be32_to_cpu(from->di_atime.t_nsec); | 227 | /* |
216 | to->di_mtime.t_sec = be32_to_cpu(from->di_mtime.t_sec); | 228 | * Time is signed, so need to convert to signed 32 bit before |
217 | to->di_mtime.t_nsec = be32_to_cpu(from->di_mtime.t_nsec); | 229 | * storing in inode timestamp which may be 64 bit. Otherwise |
218 | to->di_ctime.t_sec = be32_to_cpu(from->di_ctime.t_sec); | 230 | * a time before epoch is converted to a time long after epoch |
219 | to->di_ctime.t_nsec = be32_to_cpu(from->di_ctime.t_nsec); | 231 | * on 64 bit systems. |
232 | */ | ||
233 | inode->i_atime.tv_sec = (int)be32_to_cpu(from->di_atime.t_sec); | ||
234 | inode->i_atime.tv_nsec = (int)be32_to_cpu(from->di_atime.t_nsec); | ||
235 | inode->i_mtime.tv_sec = (int)be32_to_cpu(from->di_mtime.t_sec); | ||
236 | inode->i_mtime.tv_nsec = (int)be32_to_cpu(from->di_mtime.t_nsec); | ||
237 | inode->i_ctime.tv_sec = (int)be32_to_cpu(from->di_ctime.t_sec); | ||
238 | inode->i_ctime.tv_nsec = (int)be32_to_cpu(from->di_ctime.t_nsec); | ||
239 | inode->i_generation = be32_to_cpu(from->di_gen); | ||
240 | inode->i_mode = be16_to_cpu(from->di_mode); | ||
241 | |||
220 | to->di_size = be64_to_cpu(from->di_size); | 242 | to->di_size = be64_to_cpu(from->di_size); |
221 | to->di_nblocks = be64_to_cpu(from->di_nblocks); | 243 | to->di_nblocks = be64_to_cpu(from->di_nblocks); |
222 | to->di_extsize = be32_to_cpu(from->di_extsize); | 244 | to->di_extsize = be32_to_cpu(from->di_extsize); |
@@ -227,42 +249,96 @@ xfs_dinode_from_disk( | |||
227 | to->di_dmevmask = be32_to_cpu(from->di_dmevmask); | 249 | to->di_dmevmask = be32_to_cpu(from->di_dmevmask); |
228 | to->di_dmstate = be16_to_cpu(from->di_dmstate); | 250 | to->di_dmstate = be16_to_cpu(from->di_dmstate); |
229 | to->di_flags = be16_to_cpu(from->di_flags); | 251 | to->di_flags = be16_to_cpu(from->di_flags); |
230 | to->di_gen = be32_to_cpu(from->di_gen); | ||
231 | 252 | ||
232 | if (to->di_version == 3) { | 253 | if (to->di_version == 3) { |
233 | to->di_changecount = be64_to_cpu(from->di_changecount); | 254 | inode->i_version = be64_to_cpu(from->di_changecount); |
234 | to->di_crtime.t_sec = be32_to_cpu(from->di_crtime.t_sec); | 255 | to->di_crtime.t_sec = be32_to_cpu(from->di_crtime.t_sec); |
235 | to->di_crtime.t_nsec = be32_to_cpu(from->di_crtime.t_nsec); | 256 | to->di_crtime.t_nsec = be32_to_cpu(from->di_crtime.t_nsec); |
236 | to->di_flags2 = be64_to_cpu(from->di_flags2); | 257 | to->di_flags2 = be64_to_cpu(from->di_flags2); |
237 | to->di_ino = be64_to_cpu(from->di_ino); | ||
238 | to->di_lsn = be64_to_cpu(from->di_lsn); | ||
239 | memcpy(to->di_pad2, from->di_pad2, sizeof(to->di_pad2)); | ||
240 | uuid_copy(&to->di_uuid, &from->di_uuid); | ||
241 | } | 258 | } |
242 | } | 259 | } |
243 | 260 | ||
244 | void | 261 | void |
245 | xfs_dinode_to_disk( | 262 | xfs_inode_to_disk( |
246 | xfs_dinode_t *to, | 263 | struct xfs_inode *ip, |
247 | xfs_icdinode_t *from) | 264 | struct xfs_dinode *to, |
265 | xfs_lsn_t lsn) | ||
266 | { | ||
267 | struct xfs_icdinode *from = &ip->i_d; | ||
268 | struct inode *inode = VFS_I(ip); | ||
269 | |||
270 | to->di_magic = cpu_to_be16(XFS_DINODE_MAGIC); | ||
271 | to->di_onlink = 0; | ||
272 | |||
273 | to->di_version = from->di_version; | ||
274 | to->di_format = from->di_format; | ||
275 | to->di_uid = cpu_to_be32(from->di_uid); | ||
276 | to->di_gid = cpu_to_be32(from->di_gid); | ||
277 | to->di_projid_lo = cpu_to_be16(from->di_projid_lo); | ||
278 | to->di_projid_hi = cpu_to_be16(from->di_projid_hi); | ||
279 | |||
280 | memset(to->di_pad, 0, sizeof(to->di_pad)); | ||
281 | to->di_atime.t_sec = cpu_to_be32(inode->i_atime.tv_sec); | ||
282 | to->di_atime.t_nsec = cpu_to_be32(inode->i_atime.tv_nsec); | ||
283 | to->di_mtime.t_sec = cpu_to_be32(inode->i_mtime.tv_sec); | ||
284 | to->di_mtime.t_nsec = cpu_to_be32(inode->i_mtime.tv_nsec); | ||
285 | to->di_ctime.t_sec = cpu_to_be32(inode->i_ctime.tv_sec); | ||
286 | to->di_ctime.t_nsec = cpu_to_be32(inode->i_ctime.tv_nsec); | ||
287 | to->di_nlink = cpu_to_be32(inode->i_nlink); | ||
288 | to->di_gen = cpu_to_be32(inode->i_generation); | ||
289 | to->di_mode = cpu_to_be16(inode->i_mode); | ||
290 | |||
291 | to->di_size = cpu_to_be64(from->di_size); | ||
292 | to->di_nblocks = cpu_to_be64(from->di_nblocks); | ||
293 | to->di_extsize = cpu_to_be32(from->di_extsize); | ||
294 | to->di_nextents = cpu_to_be32(from->di_nextents); | ||
295 | to->di_anextents = cpu_to_be16(from->di_anextents); | ||
296 | to->di_forkoff = from->di_forkoff; | ||
297 | to->di_aformat = from->di_aformat; | ||
298 | to->di_dmevmask = cpu_to_be32(from->di_dmevmask); | ||
299 | to->di_dmstate = cpu_to_be16(from->di_dmstate); | ||
300 | to->di_flags = cpu_to_be16(from->di_flags); | ||
301 | |||
302 | if (from->di_version == 3) { | ||
303 | to->di_changecount = cpu_to_be64(inode->i_version); | ||
304 | to->di_crtime.t_sec = cpu_to_be32(from->di_crtime.t_sec); | ||
305 | to->di_crtime.t_nsec = cpu_to_be32(from->di_crtime.t_nsec); | ||
306 | to->di_flags2 = cpu_to_be64(from->di_flags2); | ||
307 | |||
308 | to->di_ino = cpu_to_be64(ip->i_ino); | ||
309 | to->di_lsn = cpu_to_be64(lsn); | ||
310 | memset(to->di_pad2, 0, sizeof(to->di_pad2)); | ||
311 | uuid_copy(&to->di_uuid, &ip->i_mount->m_sb.sb_meta_uuid); | ||
312 | to->di_flushiter = 0; | ||
313 | } else { | ||
314 | to->di_flushiter = cpu_to_be16(from->di_flushiter); | ||
315 | } | ||
316 | } | ||
317 | |||
318 | void | ||
319 | xfs_log_dinode_to_disk( | ||
320 | struct xfs_log_dinode *from, | ||
321 | struct xfs_dinode *to) | ||
248 | { | 322 | { |
249 | to->di_magic = cpu_to_be16(from->di_magic); | 323 | to->di_magic = cpu_to_be16(from->di_magic); |
250 | to->di_mode = cpu_to_be16(from->di_mode); | 324 | to->di_mode = cpu_to_be16(from->di_mode); |
251 | to->di_version = from ->di_version; | 325 | to->di_version = from->di_version; |
252 | to->di_format = from->di_format; | 326 | to->di_format = from->di_format; |
253 | to->di_onlink = cpu_to_be16(from->di_onlink); | 327 | to->di_onlink = 0; |
254 | to->di_uid = cpu_to_be32(from->di_uid); | 328 | to->di_uid = cpu_to_be32(from->di_uid); |
255 | to->di_gid = cpu_to_be32(from->di_gid); | 329 | to->di_gid = cpu_to_be32(from->di_gid); |
256 | to->di_nlink = cpu_to_be32(from->di_nlink); | 330 | to->di_nlink = cpu_to_be32(from->di_nlink); |
257 | to->di_projid_lo = cpu_to_be16(from->di_projid_lo); | 331 | to->di_projid_lo = cpu_to_be16(from->di_projid_lo); |
258 | to->di_projid_hi = cpu_to_be16(from->di_projid_hi); | 332 | to->di_projid_hi = cpu_to_be16(from->di_projid_hi); |
259 | memcpy(to->di_pad, from->di_pad, sizeof(to->di_pad)); | 333 | memcpy(to->di_pad, from->di_pad, sizeof(to->di_pad)); |
334 | |||
260 | to->di_atime.t_sec = cpu_to_be32(from->di_atime.t_sec); | 335 | to->di_atime.t_sec = cpu_to_be32(from->di_atime.t_sec); |
261 | to->di_atime.t_nsec = cpu_to_be32(from->di_atime.t_nsec); | 336 | to->di_atime.t_nsec = cpu_to_be32(from->di_atime.t_nsec); |
262 | to->di_mtime.t_sec = cpu_to_be32(from->di_mtime.t_sec); | 337 | to->di_mtime.t_sec = cpu_to_be32(from->di_mtime.t_sec); |
263 | to->di_mtime.t_nsec = cpu_to_be32(from->di_mtime.t_nsec); | 338 | to->di_mtime.t_nsec = cpu_to_be32(from->di_mtime.t_nsec); |
264 | to->di_ctime.t_sec = cpu_to_be32(from->di_ctime.t_sec); | 339 | to->di_ctime.t_sec = cpu_to_be32(from->di_ctime.t_sec); |
265 | to->di_ctime.t_nsec = cpu_to_be32(from->di_ctime.t_nsec); | 340 | to->di_ctime.t_nsec = cpu_to_be32(from->di_ctime.t_nsec); |
341 | |||
266 | to->di_size = cpu_to_be64(from->di_size); | 342 | to->di_size = cpu_to_be64(from->di_size); |
267 | to->di_nblocks = cpu_to_be64(from->di_nblocks); | 343 | to->di_nblocks = cpu_to_be64(from->di_nblocks); |
268 | to->di_extsize = cpu_to_be32(from->di_extsize); | 344 | to->di_extsize = cpu_to_be32(from->di_extsize); |
@@ -367,13 +443,10 @@ xfs_iread( | |||
367 | !(mp->m_flags & XFS_MOUNT_IKEEP)) { | 443 | !(mp->m_flags & XFS_MOUNT_IKEEP)) { |
368 | /* initialise the on-disk inode core */ | 444 | /* initialise the on-disk inode core */ |
369 | memset(&ip->i_d, 0, sizeof(ip->i_d)); | 445 | memset(&ip->i_d, 0, sizeof(ip->i_d)); |
370 | ip->i_d.di_magic = XFS_DINODE_MAGIC; | 446 | VFS_I(ip)->i_generation = prandom_u32(); |
371 | ip->i_d.di_gen = prandom_u32(); | 447 | if (xfs_sb_version_hascrc(&mp->m_sb)) |
372 | if (xfs_sb_version_hascrc(&mp->m_sb)) { | ||
373 | ip->i_d.di_version = 3; | 448 | ip->i_d.di_version = 3; |
374 | ip->i_d.di_ino = ip->i_ino; | 449 | else |
375 | uuid_copy(&ip->i_d.di_uuid, &mp->m_sb.sb_meta_uuid); | ||
376 | } else | ||
377 | ip->i_d.di_version = 2; | 450 | ip->i_d.di_version = 2; |
378 | return 0; | 451 | return 0; |
379 | } | 452 | } |
@@ -403,7 +476,7 @@ xfs_iread( | |||
403 | * Otherwise, just get the truly permanent information. | 476 | * Otherwise, just get the truly permanent information. |
404 | */ | 477 | */ |
405 | if (dip->di_mode) { | 478 | if (dip->di_mode) { |
406 | xfs_dinode_from_disk(&ip->i_d, dip); | 479 | xfs_inode_from_disk(ip, dip); |
407 | error = xfs_iformat_fork(ip, dip); | 480 | error = xfs_iformat_fork(ip, dip); |
408 | if (error) { | 481 | if (error) { |
409 | #ifdef DEBUG | 482 | #ifdef DEBUG |
@@ -417,16 +490,10 @@ xfs_iread( | |||
417 | * Partial initialisation of the in-core inode. Just the bits | 490 | * Partial initialisation of the in-core inode. Just the bits |
418 | * that xfs_ialloc won't overwrite or relies on being correct. | 491 | * that xfs_ialloc won't overwrite or relies on being correct. |
419 | */ | 492 | */ |
420 | ip->i_d.di_magic = be16_to_cpu(dip->di_magic); | ||
421 | ip->i_d.di_version = dip->di_version; | 493 | ip->i_d.di_version = dip->di_version; |
422 | ip->i_d.di_gen = be32_to_cpu(dip->di_gen); | 494 | VFS_I(ip)->i_generation = be32_to_cpu(dip->di_gen); |
423 | ip->i_d.di_flushiter = be16_to_cpu(dip->di_flushiter); | 495 | ip->i_d.di_flushiter = be16_to_cpu(dip->di_flushiter); |
424 | 496 | ||
425 | if (dip->di_version == 3) { | ||
426 | ip->i_d.di_ino = be64_to_cpu(dip->di_ino); | ||
427 | uuid_copy(&ip->i_d.di_uuid, &dip->di_uuid); | ||
428 | } | ||
429 | |||
430 | /* | 497 | /* |
431 | * Make sure to pull in the mode here as well in | 498 | * Make sure to pull in the mode here as well in |
432 | * case the inode is released without being used. | 499 | * case the inode is released without being used. |
@@ -434,25 +501,10 @@ xfs_iread( | |||
434 | * the inode is already free and not try to mess | 501 | * the inode is already free and not try to mess |
435 | * with the uninitialized part of it. | 502 | * with the uninitialized part of it. |
436 | */ | 503 | */ |
437 | ip->i_d.di_mode = 0; | 504 | VFS_I(ip)->i_mode = 0; |
438 | } | ||
439 | |||
440 | /* | ||
441 | * Automatically convert version 1 inode formats in memory to version 2 | ||
442 | * inode format. If the inode is modified, it will get logged and | ||
443 | * rewritten as a version 2 inode. We can do this because we set the | ||
444 | * superblock feature bit for v2 inodes unconditionally during mount | ||
445 | * and it means the reast of the code can assume the inode version is 2 | ||
446 | * or higher. | ||
447 | */ | ||
448 | if (ip->i_d.di_version == 1) { | ||
449 | ip->i_d.di_version = 2; | ||
450 | memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad)); | ||
451 | ip->i_d.di_nlink = ip->i_d.di_onlink; | ||
452 | ip->i_d.di_onlink = 0; | ||
453 | xfs_set_projid(ip, 0); | ||
454 | } | 505 | } |
455 | 506 | ||
507 | ASSERT(ip->i_d.di_version >= 2); | ||
456 | ip->i_delayed_blks = 0; | 508 | ip->i_delayed_blks = 0; |
457 | 509 | ||
458 | /* | 510 | /* |