Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs

* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs:
quota: Pass information that quota is stored in system file to userspace
ext2: protect inode changes in the SETVERSION and SETFLAGS ioctls
jbd: Issue cache flush after checkpointing

+52 -15
+16 -6
fs/ext2/ioctl.c
··· 77 77 flags = flags & EXT2_FL_USER_MODIFIABLE; 78 78 flags |= oldflags & ~EXT2_FL_USER_MODIFIABLE; 79 79 ei->i_flags = flags; 80 - mutex_unlock(&inode->i_mutex); 81 80 82 81 ext2_set_inode_flags(inode); 83 82 inode->i_ctime = CURRENT_TIME_SEC; 83 + mutex_unlock(&inode->i_mutex); 84 + 84 85 mark_inode_dirty(inode); 85 86 setflags_out: 86 87 mnt_drop_write_file(filp); ··· 89 88 } 90 89 case EXT2_IOC_GETVERSION: 91 90 return put_user(inode->i_generation, (int __user *) arg); 92 - case EXT2_IOC_SETVERSION: 91 + case EXT2_IOC_SETVERSION: { 92 + __u32 generation; 93 + 93 94 if (!inode_owner_or_capable(inode)) 94 95 return -EPERM; 95 96 ret = mnt_want_write_file(filp); 96 97 if (ret) 97 98 return ret; 98 - if (get_user(inode->i_generation, (int __user *) arg)) { 99 + if (get_user(generation, (int __user *) arg)) { 99 100 ret = -EFAULT; 100 - } else { 101 - inode->i_ctime = CURRENT_TIME_SEC; 102 - mark_inode_dirty(inode); 101 + goto setversion_out; 103 102 } 103 + 104 + mutex_lock(&inode->i_mutex); 105 + inode->i_ctime = CURRENT_TIME_SEC; 106 + inode->i_generation = generation; 107 + mutex_unlock(&inode->i_mutex); 108 + 109 + mark_inode_dirty(inode); 110 + setversion_out: 104 111 mnt_drop_write_file(filp); 105 112 return ret; 113 + } 106 114 case EXT2_IOC_GETRSVSZ: 107 115 if (test_opt(inode->i_sb, RESERVATION) 108 116 && S_ISREG(inode->i_mode)
+22 -5
fs/jbd/checkpoint.c
··· 453 453 * 454 454 * Return <0 on error, 0 on success, 1 if there was nothing to clean up. 455 455 * 456 - * Called with the journal lock held. 457 - * 458 456 * This is the only part of the journaling code which really needs to be 459 457 * aware of transaction aborts. Checkpointing involves writing to the 460 458 * main filesystem area rather than to the journal, so it can proceed ··· 470 472 if (is_journal_aborted(journal)) 471 473 return 1; 472 474 473 - /* OK, work out the oldest transaction remaining in the log, and 475 + /* 476 + * OK, work out the oldest transaction remaining in the log, and 474 477 * the log block it starts at. 475 478 * 476 479 * If the log is now empty, we need to work out which is the 477 480 * next transaction ID we will write, and where it will 478 - * start. */ 479 - 481 + * start. 482 + */ 480 483 spin_lock(&journal->j_state_lock); 481 484 spin_lock(&journal->j_list_lock); 482 485 transaction = journal->j_checkpoint_transactions; ··· 503 504 spin_unlock(&journal->j_state_lock); 504 505 return 1; 505 506 } 507 + spin_unlock(&journal->j_state_lock); 506 508 509 + /* 510 + * We need to make sure that any blocks that were recently written out 511 + * --- perhaps by log_do_checkpoint() --- are flushed out before we 512 + * drop the transactions from the journal. It's unlikely this will be 513 + * necessary, especially with an appropriately sized journal, but we 514 + * need this to guarantee correctness. Fortunately 515 + * cleanup_journal_tail() doesn't get called all that often. 516 + */ 517 + if (journal->j_flags & JFS_BARRIER) 518 + blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL); 519 + 520 + spin_lock(&journal->j_state_lock); 521 + if (!tid_gt(first_tid, journal->j_tail_sequence)) { 522 + spin_unlock(&journal->j_state_lock); 523 + /* Someone else cleaned up journal so return 0 */ 524 + return 0; 525 + } 507 526 /* OK, update the superblock to recover the freed space. 508 527 * Physical blocks come first: have we wrapped beyond the end of 509 528 * the log? */
+4
fs/jbd/recovery.c
··· 20 20 #include <linux/fs.h> 21 21 #include <linux/jbd.h> 22 22 #include <linux/errno.h> 23 + #include <linux/blkdev.h> 23 24 #endif 24 25 25 26 /* ··· 264 263 err2 = sync_blockdev(journal->j_fs_dev); 265 264 if (!err) 266 265 err = err2; 266 + /* Flush disk caches to get replayed data on the permanent storage */ 267 + if (journal->j_flags & JFS_BARRIER) 268 + blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL); 267 269 268 270 return err; 269 271 }
+5 -3
fs/quota/dquot.c
··· 2125 2125 mutex_unlock(&dqopt->dqio_mutex); 2126 2126 goto out_file_init; 2127 2127 } 2128 + if (dqopt->flags & DQUOT_QUOTA_SYS_FILE) 2129 + dqopt->info[type].dqi_flags |= DQF_SYS_FILE; 2128 2130 mutex_unlock(&dqopt->dqio_mutex); 2129 2131 spin_lock(&dq_state_lock); 2130 2132 dqopt->flags |= dquot_state_flag(flags, type); ··· 2466 2464 spin_lock(&dq_data_lock); 2467 2465 ii->dqi_bgrace = mi->dqi_bgrace; 2468 2466 ii->dqi_igrace = mi->dqi_igrace; 2469 - ii->dqi_flags = mi->dqi_flags & DQF_MASK; 2467 + ii->dqi_flags = mi->dqi_flags & DQF_GETINFO_MASK; 2470 2468 ii->dqi_valid = IIF_ALL; 2471 2469 spin_unlock(&dq_data_lock); 2472 2470 mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); ··· 2492 2490 if (ii->dqi_valid & IIF_IGRACE) 2493 2491 mi->dqi_igrace = ii->dqi_igrace; 2494 2492 if (ii->dqi_valid & IIF_FLAGS) 2495 - mi->dqi_flags = (mi->dqi_flags & ~DQF_MASK) | 2496 - (ii->dqi_flags & DQF_MASK); 2493 + mi->dqi_flags = (mi->dqi_flags & ~DQF_SETINFO_MASK) | 2494 + (ii->dqi_flags & DQF_SETINFO_MASK); 2497 2495 spin_unlock(&dq_data_lock); 2498 2496 mark_info_dirty(sb, type); 2499 2497 /* Force write to disk */
+5 -1
include/linux/quota.h
··· 230 230 struct super_block; 231 231 232 232 #define DQF_MASK 0xffff /* Mask for format specific flags */ 233 - #define DQF_INFO_DIRTY_B 16 233 + #define DQF_GETINFO_MASK 0x1ffff /* Mask for flags passed to userspace */ 234 + #define DQF_SETINFO_MASK 0xffff /* Mask for flags modifiable from userspace */ 235 + #define DQF_SYS_FILE_B 16 236 + #define DQF_SYS_FILE (1 << DQF_SYS_FILE_B) /* Quota file stored as system file */ 237 + #define DQF_INFO_DIRTY_B 31 234 238 #define DQF_INFO_DIRTY (1 << DQF_INFO_DIRTY_B) /* Is info dirty? */ 235 239 236 240 extern void mark_info_dirty(struct super_block *sb, int type);