.. | .. |
---|
341 | 341 | struct buffer_head *bh) |
---|
342 | 342 | { |
---|
343 | 343 | struct ext4_dir_entry_tail *t; |
---|
| 344 | + int blocksize = EXT4_BLOCK_SIZE(inode->i_sb); |
---|
344 | 345 | |
---|
345 | 346 | #ifdef PARANOID |
---|
346 | 347 | struct ext4_dir_entry *d, *top; |
---|
347 | 348 | |
---|
348 | 349 | d = (struct ext4_dir_entry *)bh->b_data; |
---|
349 | 350 | top = (struct ext4_dir_entry *)(bh->b_data + |
---|
350 | | - (EXT4_BLOCK_SIZE(inode->i_sb) - |
---|
351 | | - sizeof(struct ext4_dir_entry_tail))); |
---|
352 | | - while (d < top && d->rec_len) |
---|
| 351 | + (blocksize - sizeof(struct ext4_dir_entry_tail))); |
---|
| 352 | + while (d < top && ext4_rec_len_from_disk(d->rec_len, blocksize)) |
---|
353 | 353 | d = (struct ext4_dir_entry *)(((void *)d) + |
---|
354 | | - le16_to_cpu(d->rec_len)); |
---|
| 354 | + ext4_rec_len_from_disk(d->rec_len, blocksize)); |
---|
355 | 355 | |
---|
356 | 356 | if (d != top) |
---|
357 | 357 | return NULL; |
---|
.. | .. |
---|
362 | 362 | #endif |
---|
363 | 363 | |
---|
364 | 364 | if (t->det_reserved_zero1 || |
---|
365 | | - le16_to_cpu(t->det_rec_len) != sizeof(struct ext4_dir_entry_tail) || |
---|
| 365 | + (ext4_rec_len_from_disk(t->det_rec_len, blocksize) != |
---|
| 366 | + sizeof(struct ext4_dir_entry_tail)) || |
---|
366 | 367 | t->det_reserved_zero2 || |
---|
367 | 368 | t->det_reserved_ft != EXT4_FT_DIR_CSUM) |
---|
368 | 369 | return NULL; |
---|
.. | .. |
---|
443 | 444 | struct ext4_dir_entry *dp; |
---|
444 | 445 | struct dx_root_info *root; |
---|
445 | 446 | int count_offset; |
---|
| 447 | + int blocksize = EXT4_BLOCK_SIZE(inode->i_sb); |
---|
| 448 | + unsigned int rlen = ext4_rec_len_from_disk(dirent->rec_len, blocksize); |
---|
446 | 449 | |
---|
447 | | - if (le16_to_cpu(dirent->rec_len) == EXT4_BLOCK_SIZE(inode->i_sb)) |
---|
| 450 | + if (rlen == blocksize) |
---|
448 | 451 | count_offset = 8; |
---|
449 | | - else if (le16_to_cpu(dirent->rec_len) == 12) { |
---|
| 452 | + else if (rlen == 12) { |
---|
450 | 453 | dp = (struct ext4_dir_entry *)(((void *)dirent) + 12); |
---|
451 | | - if (le16_to_cpu(dp->rec_len) != |
---|
452 | | - EXT4_BLOCK_SIZE(inode->i_sb) - 12) |
---|
| 454 | + if (ext4_rec_len_from_disk(dp->rec_len, blocksize) != blocksize - 12) |
---|
453 | 455 | return NULL; |
---|
454 | 456 | root = (struct dx_root_info *)(((void *)dp + 12)); |
---|
455 | 457 | if (root->reserved_zero || |
---|
.. | .. |
---|
1012 | 1014 | * If the hash is 1, then continue only if the next page has a |
---|
1013 | 1015 | * continuation hash of any value. This is used for readdir |
---|
1014 | 1016 | * handling. Otherwise, check to see if the hash matches the |
---|
1015 | | - * desired contiuation hash. If it doesn't, return since |
---|
| 1017 | + * desired continuation hash. If it doesn't, return since |
---|
1016 | 1018 | * there's no point to read in the successive index pages. |
---|
1017 | 1019 | */ |
---|
1018 | 1020 | bhash = dx_get_hash(p->at); |
---|
.. | .. |
---|
1299 | 1301 | map_tail--; |
---|
1300 | 1302 | map_tail->hash = h.hash; |
---|
1301 | 1303 | map_tail->offs = ((char *) de - base)>>2; |
---|
1302 | | - map_tail->size = le16_to_cpu(de->rec_len); |
---|
| 1304 | + map_tail->size = ext4_rec_len_from_disk(de->rec_len, |
---|
| 1305 | + blocksize); |
---|
1303 | 1306 | count++; |
---|
1304 | 1307 | cond_resched(); |
---|
1305 | 1308 | } |
---|
1306 | | - /* XXX: do we need to check rec_len == 0 case? -Chris */ |
---|
1307 | 1309 | de = ext4_next_entry(de, blocksize); |
---|
1308 | 1310 | } |
---|
1309 | 1311 | return count; |
---|
.. | .. |
---|
1580 | 1582 | &has_inline_data); |
---|
1581 | 1583 | if (lblk) |
---|
1582 | 1584 | *lblk = 0; |
---|
1583 | | - if (has_inline_data) { |
---|
1584 | | - if (inlined) |
---|
1585 | | - *inlined = 1; |
---|
| 1585 | + if (inlined) |
---|
| 1586 | + *inlined = has_inline_data; |
---|
| 1587 | + if (has_inline_data) |
---|
1586 | 1588 | goto cleanup_and_exit; |
---|
1587 | | - } |
---|
1588 | 1589 | } |
---|
1589 | 1590 | |
---|
1590 | 1591 | if ((namelen <= 2) && (name[0] == '.') && |
---|
.. | .. |
---|
3343 | 3344 | return retval; |
---|
3344 | 3345 | } |
---|
3345 | 3346 | |
---|
3346 | | -int __ext4_unlink(handle_t *handle, struct inode *dir, const struct qstr *d_name, |
---|
3347 | | - struct inode *inode) |
---|
| 3347 | +int __ext4_unlink(struct inode *dir, const struct qstr *d_name, |
---|
| 3348 | + struct inode *inode, |
---|
| 3349 | + struct dentry *dentry /* NULL during fast_commit recovery */) |
---|
3348 | 3350 | { |
---|
3349 | 3351 | int retval = -ENOENT; |
---|
3350 | 3352 | struct buffer_head *bh; |
---|
3351 | 3353 | struct ext4_dir_entry_2 *de; |
---|
| 3354 | + handle_t *handle; |
---|
3352 | 3355 | int skip_remove_dentry = 0; |
---|
3353 | 3356 | ext4_lblk_t lblk; |
---|
3354 | 3357 | |
---|
| 3358 | + /* |
---|
| 3359 | + * Keep this outside the transaction; it may have to set up the |
---|
| 3360 | + * directory's encryption key, which isn't GFP_NOFS-safe. |
---|
| 3361 | + */ |
---|
3355 | 3362 | bh = ext4_find_entry(dir, d_name, &de, NULL, &lblk); |
---|
3356 | 3363 | if (IS_ERR(bh)) |
---|
3357 | 3364 | return PTR_ERR(bh); |
---|
.. | .. |
---|
3368 | 3375 | if (EXT4_SB(inode->i_sb)->s_mount_state & EXT4_FC_REPLAY) |
---|
3369 | 3376 | skip_remove_dentry = 1; |
---|
3370 | 3377 | else |
---|
3371 | | - goto out; |
---|
| 3378 | + goto out_bh; |
---|
| 3379 | + } |
---|
| 3380 | + |
---|
| 3381 | + handle = ext4_journal_start(dir, EXT4_HT_DIR, |
---|
| 3382 | + EXT4_DATA_TRANS_BLOCKS(dir->i_sb)); |
---|
| 3383 | + if (IS_ERR(handle)) { |
---|
| 3384 | + retval = PTR_ERR(handle); |
---|
| 3385 | + goto out_bh; |
---|
3372 | 3386 | } |
---|
3373 | 3387 | |
---|
3374 | 3388 | if (IS_DIRSYNC(dir)) |
---|
.. | .. |
---|
3377 | 3391 | if (!skip_remove_dentry) { |
---|
3378 | 3392 | retval = ext4_delete_entry(handle, dir, de, lblk, bh); |
---|
3379 | 3393 | if (retval) |
---|
3380 | | - goto out; |
---|
| 3394 | + goto out_handle; |
---|
3381 | 3395 | dir->i_ctime = dir->i_mtime = current_time(dir); |
---|
3382 | 3396 | ext4_update_dx_flag(dir); |
---|
3383 | 3397 | retval = ext4_mark_inode_dirty(handle, dir); |
---|
3384 | 3398 | if (retval) |
---|
3385 | | - goto out; |
---|
| 3399 | + goto out_handle; |
---|
3386 | 3400 | } else { |
---|
3387 | 3401 | retval = 0; |
---|
3388 | 3402 | } |
---|
.. | .. |
---|
3395 | 3409 | ext4_orphan_add(handle, inode); |
---|
3396 | 3410 | inode->i_ctime = current_time(inode); |
---|
3397 | 3411 | retval = ext4_mark_inode_dirty(handle, inode); |
---|
3398 | | - |
---|
3399 | | -out: |
---|
| 3412 | + if (dentry && !retval) |
---|
| 3413 | + ext4_fc_track_unlink(handle, dentry); |
---|
| 3414 | +out_handle: |
---|
| 3415 | + ext4_journal_stop(handle); |
---|
| 3416 | +out_bh: |
---|
3400 | 3417 | brelse(bh); |
---|
3401 | 3418 | return retval; |
---|
3402 | 3419 | } |
---|
3403 | 3420 | |
---|
3404 | 3421 | static int ext4_unlink(struct inode *dir, struct dentry *dentry) |
---|
3405 | 3422 | { |
---|
3406 | | - handle_t *handle; |
---|
3407 | 3423 | int retval; |
---|
3408 | 3424 | |
---|
3409 | 3425 | if (unlikely(ext4_forced_shutdown(EXT4_SB(dir->i_sb)))) |
---|
.. | .. |
---|
3421 | 3437 | if (retval) |
---|
3422 | 3438 | goto out_trace; |
---|
3423 | 3439 | |
---|
3424 | | - handle = ext4_journal_start(dir, EXT4_HT_DIR, |
---|
3425 | | - EXT4_DATA_TRANS_BLOCKS(dir->i_sb)); |
---|
3426 | | - if (IS_ERR(handle)) { |
---|
3427 | | - retval = PTR_ERR(handle); |
---|
3428 | | - goto out_trace; |
---|
3429 | | - } |
---|
3430 | | - |
---|
3431 | | - retval = __ext4_unlink(handle, dir, &dentry->d_name, d_inode(dentry)); |
---|
3432 | | - if (!retval) |
---|
3433 | | - ext4_fc_track_unlink(handle, dentry); |
---|
| 3440 | + retval = __ext4_unlink(dir, &dentry->d_name, d_inode(dentry), dentry); |
---|
3434 | 3441 | #ifdef CONFIG_UNICODE |
---|
3435 | 3442 | /* VFS negative dentries are incompatible with Encoding and |
---|
3436 | 3443 | * Case-insensitiveness. Eventually we'll want avoid |
---|
.. | .. |
---|
3441 | 3448 | if (IS_CASEFOLDED(dir)) |
---|
3442 | 3449 | d_invalidate(dentry); |
---|
3443 | 3450 | #endif |
---|
3444 | | - if (handle) |
---|
3445 | | - ext4_journal_stop(handle); |
---|
3446 | 3451 | |
---|
3447 | 3452 | out_trace: |
---|
3448 | 3453 | trace_ext4_unlink_exit(dentry, retval); |
---|
.. | .. |
---|
3795 | 3800 | * so the old->de may no longer valid and need to find it again |
---|
3796 | 3801 | * before reset old inode info. |
---|
3797 | 3802 | */ |
---|
3798 | | - old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, NULL, |
---|
3799 | | - NULL); |
---|
| 3803 | + old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, |
---|
| 3804 | + &old.inlined, NULL); |
---|
3800 | 3805 | if (IS_ERR(old.bh)) |
---|
3801 | 3806 | retval = PTR_ERR(old.bh); |
---|
3802 | 3807 | if (!old.bh) |
---|
.. | .. |
---|
3948 | 3953 | retval = dquot_initialize(old.dir); |
---|
3949 | 3954 | if (retval) |
---|
3950 | 3955 | return retval; |
---|
| 3956 | + retval = dquot_initialize(old.inode); |
---|
| 3957 | + if (retval) |
---|
| 3958 | + return retval; |
---|
3951 | 3959 | retval = dquot_initialize(new.dir); |
---|
3952 | 3960 | if (retval) |
---|
3953 | 3961 | return retval; |
---|
.. | .. |
---|
3960 | 3968 | return retval; |
---|
3961 | 3969 | } |
---|
3962 | 3970 | |
---|
3963 | | - old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, NULL, |
---|
3964 | | - &old.lblk); |
---|
| 3971 | + old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, |
---|
| 3972 | + &old.inlined, &old.lblk); |
---|
3965 | 3973 | if (IS_ERR(old.bh)) |
---|
3966 | 3974 | return PTR_ERR(old.bh); |
---|
| 3975 | + |
---|
3967 | 3976 | /* |
---|
3968 | 3977 | * Check for inode number is _not_ due to possible IO errors. |
---|
3969 | 3978 | * We might rmdir the source, keep it as pwd of some process |
---|
.. | .. |
---|
4151 | 4160 | brelse(old.dir_bh); |
---|
4152 | 4161 | brelse(old.bh); |
---|
4153 | 4162 | brelse(new.bh); |
---|
| 4163 | + |
---|
4154 | 4164 | return retval; |
---|
4155 | 4165 | } |
---|
4156 | 4166 | |
---|