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