| .. | .. |
|---|
| 222 | 222 | int ext4_reserve_inode_write(handle_t *handle, struct inode *inode, |
|---|
| 223 | 223 | struct ext4_iloc *iloc); |
|---|
| 224 | 224 | |
|---|
| 225 | | -int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode); |
|---|
| 225 | +#define ext4_mark_inode_dirty(__h, __i) \ |
|---|
| 226 | + __ext4_mark_inode_dirty((__h), (__i), __func__, __LINE__) |
|---|
| 227 | +int __ext4_mark_inode_dirty(handle_t *handle, struct inode *inode, |
|---|
| 228 | + const char *func, unsigned int line); |
|---|
| 226 | 229 | |
|---|
| 227 | 230 | int ext4_expand_extra_isize(struct inode *inode, |
|---|
| 228 | 231 | unsigned int new_extra_isize, |
|---|
| .. | .. |
|---|
| 261 | 264 | __ext4_handle_dirty_super(__func__, __LINE__, (handle), (sb)) |
|---|
| 262 | 265 | |
|---|
| 263 | 266 | handle_t *__ext4_journal_start_sb(struct super_block *sb, unsigned int line, |
|---|
| 264 | | - int type, int blocks, int rsv_blocks); |
|---|
| 267 | + int type, int blocks, int rsv_blocks, |
|---|
| 268 | + int revoke_creds); |
|---|
| 265 | 269 | int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle); |
|---|
| 266 | 270 | |
|---|
| 267 | 271 | #define EXT4_NOJOURNAL_MAX_REF_COUNT ((unsigned long) 4096) |
|---|
| .. | .. |
|---|
| 288 | 292 | return 0; |
|---|
| 289 | 293 | } |
|---|
| 290 | 294 | |
|---|
| 291 | | -static inline int ext4_handle_has_enough_credits(handle_t *handle, int needed) |
|---|
| 295 | +static inline int ext4_free_metadata_revoke_credits(struct super_block *sb, |
|---|
| 296 | + int blocks) |
|---|
| 292 | 297 | { |
|---|
| 293 | | - if (ext4_handle_valid(handle) && handle->h_buffer_credits < needed) |
|---|
| 294 | | - return 0; |
|---|
| 295 | | - return 1; |
|---|
| 298 | + /* Freeing each metadata block can result in freeing one cluster */ |
|---|
| 299 | + return blocks * EXT4_SB(sb)->s_cluster_ratio; |
|---|
| 300 | +} |
|---|
| 301 | + |
|---|
| 302 | +static inline int ext4_trans_default_revoke_credits(struct super_block *sb) |
|---|
| 303 | +{ |
|---|
| 304 | + return ext4_free_metadata_revoke_credits(sb, 8); |
|---|
| 296 | 305 | } |
|---|
| 297 | 306 | |
|---|
| 298 | 307 | #define ext4_journal_start_sb(sb, type, nblocks) \ |
|---|
| 299 | | - __ext4_journal_start_sb((sb), __LINE__, (type), (nblocks), 0) |
|---|
| 308 | + __ext4_journal_start_sb((sb), __LINE__, (type), (nblocks), 0, \ |
|---|
| 309 | + ext4_trans_default_revoke_credits(sb)) |
|---|
| 300 | 310 | |
|---|
| 301 | 311 | #define ext4_journal_start(inode, type, nblocks) \ |
|---|
| 302 | | - __ext4_journal_start((inode), __LINE__, (type), (nblocks), 0) |
|---|
| 312 | + __ext4_journal_start((inode), __LINE__, (type), (nblocks), 0, \ |
|---|
| 313 | + ext4_trans_default_revoke_credits((inode)->i_sb)) |
|---|
| 303 | 314 | |
|---|
| 304 | | -#define ext4_journal_start_with_reserve(inode, type, blocks, rsv_blocks) \ |
|---|
| 305 | | - __ext4_journal_start((inode), __LINE__, (type), (blocks), (rsv_blocks)) |
|---|
| 315 | +#define ext4_journal_start_with_reserve(inode, type, blocks, rsv_blocks)\ |
|---|
| 316 | + __ext4_journal_start((inode), __LINE__, (type), (blocks), (rsv_blocks),\ |
|---|
| 317 | + ext4_trans_default_revoke_credits((inode)->i_sb)) |
|---|
| 318 | + |
|---|
| 319 | +#define ext4_journal_start_with_revoke(inode, type, blocks, revoke_creds) \ |
|---|
| 320 | + __ext4_journal_start((inode), __LINE__, (type), (blocks), 0, \ |
|---|
| 321 | + (revoke_creds)) |
|---|
| 306 | 322 | |
|---|
| 307 | 323 | static inline handle_t *__ext4_journal_start(struct inode *inode, |
|---|
| 308 | 324 | unsigned int line, int type, |
|---|
| 309 | | - int blocks, int rsv_blocks) |
|---|
| 325 | + int blocks, int rsv_blocks, |
|---|
| 326 | + int revoke_creds) |
|---|
| 310 | 327 | { |
|---|
| 311 | 328 | return __ext4_journal_start_sb(inode->i_sb, line, type, blocks, |
|---|
| 312 | | - rsv_blocks); |
|---|
| 329 | + rsv_blocks, revoke_creds); |
|---|
| 313 | 330 | } |
|---|
| 314 | 331 | |
|---|
| 315 | 332 | #define ext4_journal_stop(handle) \ |
|---|
| .. | .. |
|---|
| 321 | 338 | handle_t *__ext4_journal_start_reserved(handle_t *handle, unsigned int line, |
|---|
| 322 | 339 | int type); |
|---|
| 323 | 340 | |
|---|
| 324 | | -static inline void ext4_journal_free_reserved(handle_t *handle) |
|---|
| 325 | | -{ |
|---|
| 326 | | - if (ext4_handle_valid(handle)) |
|---|
| 327 | | - jbd2_journal_free_reserved(handle); |
|---|
| 328 | | -} |
|---|
| 329 | | - |
|---|
| 330 | 341 | static inline handle_t *ext4_journal_current_handle(void) |
|---|
| 331 | 342 | { |
|---|
| 332 | 343 | return journal_current_handle(); |
|---|
| 333 | 344 | } |
|---|
| 334 | 345 | |
|---|
| 335 | | -static inline int ext4_journal_extend(handle_t *handle, int nblocks) |
|---|
| 346 | +static inline int ext4_journal_extend(handle_t *handle, int nblocks, int revoke) |
|---|
| 336 | 347 | { |
|---|
| 337 | 348 | if (ext4_handle_valid(handle)) |
|---|
| 338 | | - return jbd2_journal_extend(handle, nblocks); |
|---|
| 349 | + return jbd2_journal_extend(handle, nblocks, revoke); |
|---|
| 339 | 350 | return 0; |
|---|
| 340 | 351 | } |
|---|
| 341 | 352 | |
|---|
| 342 | | -static inline int ext4_journal_restart(handle_t *handle, int nblocks) |
|---|
| 353 | +static inline int ext4_journal_restart(handle_t *handle, int nblocks, |
|---|
| 354 | + int revoke) |
|---|
| 343 | 355 | { |
|---|
| 344 | 356 | if (ext4_handle_valid(handle)) |
|---|
| 345 | | - return jbd2_journal_restart(handle, nblocks); |
|---|
| 357 | + return jbd2__journal_restart(handle, nblocks, revoke, GFP_NOFS); |
|---|
| 346 | 358 | return 0; |
|---|
| 359 | +} |
|---|
| 360 | + |
|---|
| 361 | +int __ext4_journal_ensure_credits(handle_t *handle, int check_cred, |
|---|
| 362 | + int extend_cred, int revoke_cred); |
|---|
| 363 | + |
|---|
| 364 | + |
|---|
| 365 | +/* |
|---|
| 366 | + * Ensure @handle has at least @check_creds credits available. If not, |
|---|
| 367 | + * transaction will be extended or restarted to contain at least @extend_cred |
|---|
| 368 | + * credits. Before restarting transaction @fn is executed to allow for cleanup |
|---|
| 369 | + * before the transaction is restarted. |
|---|
| 370 | + * |
|---|
| 371 | + * The return value is < 0 in case of error, 0 in case the handle has enough |
|---|
| 372 | + * credits or transaction extension succeeded, 1 in case transaction had to be |
|---|
| 373 | + * restarted. |
|---|
| 374 | + */ |
|---|
| 375 | +#define ext4_journal_ensure_credits_fn(handle, check_cred, extend_cred, \ |
|---|
| 376 | + revoke_cred, fn) \ |
|---|
| 377 | +({ \ |
|---|
| 378 | + __label__ __ensure_end; \ |
|---|
| 379 | + int err = __ext4_journal_ensure_credits((handle), (check_cred), \ |
|---|
| 380 | + (extend_cred), (revoke_cred)); \ |
|---|
| 381 | + \ |
|---|
| 382 | + if (err <= 0) \ |
|---|
| 383 | + goto __ensure_end; \ |
|---|
| 384 | + err = (fn); \ |
|---|
| 385 | + if (err < 0) \ |
|---|
| 386 | + goto __ensure_end; \ |
|---|
| 387 | + err = ext4_journal_restart((handle), (extend_cred), (revoke_cred)); \ |
|---|
| 388 | + if (err == 0) \ |
|---|
| 389 | + err = 1; \ |
|---|
| 390 | +__ensure_end: \ |
|---|
| 391 | + err; \ |
|---|
| 392 | +}) |
|---|
| 393 | + |
|---|
| 394 | +/* |
|---|
| 395 | + * Ensure given handle has at least requested amount of credits available, |
|---|
| 396 | + * possibly restarting transaction if needed. We also make sure the transaction |
|---|
| 397 | + * has space for at least ext4_trans_default_revoke_credits(sb) revoke records |
|---|
| 398 | + * as freeing one or two blocks is very common pattern and requesting this is |
|---|
| 399 | + * very cheap. |
|---|
| 400 | + */ |
|---|
| 401 | +static inline int ext4_journal_ensure_credits(handle_t *handle, int credits, |
|---|
| 402 | + int revoke_creds) |
|---|
| 403 | +{ |
|---|
| 404 | + return ext4_journal_ensure_credits_fn(handle, credits, credits, |
|---|
| 405 | + revoke_creds, 0); |
|---|
| 347 | 406 | } |
|---|
| 348 | 407 | |
|---|
| 349 | 408 | static inline int ext4_journal_blocks_per_page(struct inode *inode) |
|---|
| .. | .. |
|---|
| 401 | 460 | #define EXT4_INODE_ORDERED_DATA_MODE 0x02 /* ordered data mode */ |
|---|
| 402 | 461 | #define EXT4_INODE_WRITEBACK_DATA_MODE 0x04 /* writeback data mode */ |
|---|
| 403 | 462 | |
|---|
| 404 | | -static inline int ext4_inode_journal_mode(struct inode *inode) |
|---|
| 405 | | -{ |
|---|
| 406 | | - if (EXT4_JOURNAL(inode) == NULL) |
|---|
| 407 | | - return EXT4_INODE_WRITEBACK_DATA_MODE; /* writeback */ |
|---|
| 408 | | - /* We do not support data journalling with delayed allocation */ |
|---|
| 409 | | - if (!S_ISREG(inode->i_mode) || |
|---|
| 410 | | - test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA || |
|---|
| 411 | | - (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA) && |
|---|
| 412 | | - !test_opt(inode->i_sb, DELALLOC))) { |
|---|
| 413 | | - /* We do not support data journalling for encrypted data */ |
|---|
| 414 | | - if (S_ISREG(inode->i_mode) && IS_ENCRYPTED(inode)) |
|---|
| 415 | | - return EXT4_INODE_ORDERED_DATA_MODE; /* ordered */ |
|---|
| 416 | | - return EXT4_INODE_JOURNAL_DATA_MODE; /* journal data */ |
|---|
| 417 | | - } |
|---|
| 418 | | - if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA) |
|---|
| 419 | | - return EXT4_INODE_ORDERED_DATA_MODE; /* ordered */ |
|---|
| 420 | | - if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA) |
|---|
| 421 | | - return EXT4_INODE_WRITEBACK_DATA_MODE; /* writeback */ |
|---|
| 422 | | - BUG(); |
|---|
| 423 | | -} |
|---|
| 463 | +int ext4_inode_journal_mode(struct inode *inode); |
|---|
| 424 | 464 | |
|---|
| 425 | 465 | static inline int ext4_should_journal_data(struct inode *inode) |
|---|
| 426 | 466 | { |
|---|
| .. | .. |
|---|
| 435 | 475 | static inline int ext4_should_writeback_data(struct inode *inode) |
|---|
| 436 | 476 | { |
|---|
| 437 | 477 | return ext4_inode_journal_mode(inode) & EXT4_INODE_WRITEBACK_DATA_MODE; |
|---|
| 478 | +} |
|---|
| 479 | + |
|---|
| 480 | +static inline int ext4_free_data_revoke_credits(struct inode *inode, int blocks) |
|---|
| 481 | +{ |
|---|
| 482 | + if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) |
|---|
| 483 | + return 0; |
|---|
| 484 | + if (!ext4_should_journal_data(inode)) |
|---|
| 485 | + return 0; |
|---|
| 486 | + /* |
|---|
| 487 | + * Data blocks in one extent are contiguous, just account for partial |
|---|
| 488 | + * clusters at extent boundaries |
|---|
| 489 | + */ |
|---|
| 490 | + return blocks + 2*(EXT4_SB(inode->i_sb)->s_cluster_ratio - 1); |
|---|
| 438 | 491 | } |
|---|
| 439 | 492 | |
|---|
| 440 | 493 | /* |
|---|
| .. | .. |
|---|
| 456 | 509 | return 0; |
|---|
| 457 | 510 | if (ext4_should_journal_data(inode)) |
|---|
| 458 | 511 | return 0; |
|---|
| 512 | + /* temporary fix to prevent generic/422 test failures */ |
|---|
| 513 | + if (!test_opt(inode->i_sb, DELALLOC)) |
|---|
| 514 | + return 0; |
|---|
| 459 | 515 | return 1; |
|---|
| 460 | 516 | } |
|---|
| 461 | 517 | |
|---|