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

vfs: optimize touch_time() too

Do a similar optimization as earlier for touch_atime. Getting the lock in
mnt_get_write is relatively costly, so try all avenues to avoid it first.

This patch is careful to still only update inode fields inside the lock
region.

This didn't show up in benchmarks, but it's easy enough to do.

[akpm@linux-foundation.org: fix typo in comment]
[hugh.dickins@tiscali.co.uk: fix inverted test of mnt_want_write_file()]
Signed-off-by: Andi Kleen <ak@linux.intel.com>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Valerie Aurora <vaurora@redhat.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Dave Hansen <haveblue@us.ibm.com>
Signed-off-by: Hugh Dickins <hugh.dickins@tiscali.co.uk>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

authored by

Andi Kleen and committed by
Al Viro
ce06e0b2 b12536c2

+23 -20
+23 -20
fs/inode.c
··· 1461 1461 { 1462 1462 struct inode *inode = file->f_path.dentry->d_inode; 1463 1463 struct timespec now; 1464 - int sync_it = 0; 1465 - int err; 1464 + enum { S_MTIME = 1, S_CTIME = 2, S_VERSION = 4 } sync_it = 0; 1466 1465 1466 + /* First try to exhaust all avenues to not sync */ 1467 1467 if (IS_NOCMTIME(inode)) 1468 1468 return; 1469 1469 1470 - err = mnt_want_write_file(file); 1471 - if (err) 1470 + now = current_fs_time(inode->i_sb); 1471 + if (!timespec_equal(&inode->i_mtime, &now)) 1472 + sync_it = S_MTIME; 1473 + 1474 + if (!timespec_equal(&inode->i_ctime, &now)) 1475 + sync_it |= S_CTIME; 1476 + 1477 + if (IS_I_VERSION(inode)) 1478 + sync_it |= S_VERSION; 1479 + 1480 + if (!sync_it) 1472 1481 return; 1473 1482 1474 - now = current_fs_time(inode->i_sb); 1475 - if (!timespec_equal(&inode->i_mtime, &now)) { 1476 - inode->i_mtime = now; 1477 - sync_it = 1; 1478 - } 1483 + /* Finally allowed to write? Takes lock. */ 1484 + if (mnt_want_write_file(file)) 1485 + return; 1479 1486 1480 - if (!timespec_equal(&inode->i_ctime, &now)) { 1481 - inode->i_ctime = now; 1482 - sync_it = 1; 1483 - } 1484 - 1485 - if (IS_I_VERSION(inode)) { 1487 + /* Only change inode inside the lock region */ 1488 + if (sync_it & S_VERSION) 1486 1489 inode_inc_iversion(inode); 1487 - sync_it = 1; 1488 - } 1489 - 1490 - if (sync_it) 1491 - mark_inode_dirty_sync(inode); 1490 + if (sync_it & S_CTIME) 1491 + inode->i_ctime = now; 1492 + if (sync_it & S_MTIME) 1493 + inode->i_mtime = now; 1494 + mark_inode_dirty_sync(inode); 1492 1495 mnt_drop_write(file->f_path.mnt); 1493 1496 } 1494 1497 EXPORT_SYMBOL(file_update_time);