| .. | .. |
|---|
| 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 | |
|---|