aboutsummaryrefslogtreecommitdiffstats
path: root/fs/inode.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-06-01 13:34:35 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-06-01 13:34:35 -0400
commit1193755ac6328ad240ba987e6ec41d5e8baf0680 (patch)
tree40bf847d7e3ebaa57b107151d14e6cd1d280cc6d /fs/inode.c
parent4edebed86690eb8db9af3ab85baf4a34e73266cc (diff)
parent0ef97dcfce4179a2eba046b855ee2f91d6f1b414 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs changes from Al Viro. "A lot of misc stuff. The obvious groups: * Miklos' atomic_open series; kills the damn abuse of ->d_revalidate() by NFS, which was the major stumbling block for all work in that area. * ripping security_file_mmap() and dealing with deadlocks in the area; sanitizing the neighborhood of vm_mmap()/vm_munmap() in general. * ->encode_fh() switched to saner API; insane fake dentry in mm/cleancache.c gone. * assorted annotations in fs (endianness, __user) * parts of Artem's ->s_dirty work (jff2 and reiserfs parts) * ->update_time() work from Josef. * other bits and pieces all over the place. Normally it would've been in two or three pull requests, but signal.git stuff had eaten a lot of time during this cycle ;-/" Fix up trivial conflicts in Documentation/filesystems/vfs.txt (the 'truncate_range' inode method was removed by the VM changes, the VFS update adds an 'update_time()' method), and in fs/btrfs/ulist.[ch] (due to sparse fix added twice, with other changes nearby). * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (95 commits) nfs: don't open in ->d_revalidate vfs: retry last component if opening stale dentry vfs: nameidata_to_filp(): don't throw away file on error vfs: nameidata_to_filp(): inline __dentry_open() vfs: do_dentry_open(): don't put filp vfs: split __dentry_open() vfs: do_last() common post lookup vfs: do_last(): add audit_inode before open vfs: do_last(): only return EISDIR for O_CREAT vfs: do_last(): check LOOKUP_DIRECTORY vfs: do_last(): make ENOENT exit RCU safe vfs: make follow_link check RCU safe vfs: do_last(): use inode variable vfs: do_last(): inline walk_component() vfs: do_last(): make exit RCU safe vfs: split do_lookup() Btrfs: move over to use ->update_time fs: introduce inode operation ->update_time reiserfs: get rid of resierfs_sync_super reiserfs: mark the superblock as dirty a bit later ...
Diffstat (limited to 'fs/inode.c')
-rw-r--r--fs/inode.c124
1 files changed, 106 insertions, 18 deletions
diff --git a/fs/inode.c b/fs/inode.c
index c474c1d7062b..c99163b1b310 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -1487,10 +1487,30 @@ static int relatime_need_update(struct vfsmount *mnt, struct inode *inode,
1487 return 0; 1487 return 0;
1488} 1488}
1489 1489
1490/*
1491 * This does the actual work of updating an inodes time or version. Must have
1492 * had called mnt_want_write() before calling this.
1493 */
1494static int update_time(struct inode *inode, struct timespec *time, int flags)
1495{
1496 if (inode->i_op->update_time)
1497 return inode->i_op->update_time(inode, time, flags);
1498
1499 if (flags & S_ATIME)
1500 inode->i_atime = *time;
1501 if (flags & S_VERSION)
1502 inode_inc_iversion(inode);
1503 if (flags & S_CTIME)
1504 inode->i_ctime = *time;
1505 if (flags & S_MTIME)
1506 inode->i_mtime = *time;
1507 mark_inode_dirty_sync(inode);
1508 return 0;
1509}
1510
1490/** 1511/**
1491 * touch_atime - update the access time 1512 * touch_atime - update the access time
1492 * @mnt: mount the inode is accessed on 1513 * @path: the &struct path to update
1493 * @dentry: dentry accessed
1494 * 1514 *
1495 * Update the accessed time on an inode and mark it for writeback. 1515 * Update the accessed time on an inode and mark it for writeback.
1496 * This function automatically handles read only file systems and media, 1516 * This function automatically handles read only file systems and media,
@@ -1525,12 +1545,83 @@ void touch_atime(struct path *path)
1525 if (mnt_want_write(mnt)) 1545 if (mnt_want_write(mnt))
1526 return; 1546 return;
1527 1547
1528 inode->i_atime = now; 1548 /*
1529 mark_inode_dirty_sync(inode); 1549 * File systems can error out when updating inodes if they need to
1550 * allocate new space to modify an inode (such is the case for
1551 * Btrfs), but since we touch atime while walking down the path we
1552 * really don't care if we failed to update the atime of the file,
1553 * so just ignore the return value.
1554 */
1555 update_time(inode, &now, S_ATIME);
1530 mnt_drop_write(mnt); 1556 mnt_drop_write(mnt);
1531} 1557}
1532EXPORT_SYMBOL(touch_atime); 1558EXPORT_SYMBOL(touch_atime);
1533 1559
1560/*
1561 * The logic we want is
1562 *
1563 * if suid or (sgid and xgrp)
1564 * remove privs
1565 */
1566int should_remove_suid(struct dentry *dentry)
1567{
1568 umode_t mode = dentry->d_inode->i_mode;
1569 int kill = 0;
1570
1571 /* suid always must be killed */
1572 if (unlikely(mode & S_ISUID))
1573 kill = ATTR_KILL_SUID;
1574
1575 /*
1576 * sgid without any exec bits is just a mandatory locking mark; leave
1577 * it alone. If some exec bits are set, it's a real sgid; kill it.
1578 */
1579 if (unlikely((mode & S_ISGID) && (mode & S_IXGRP)))
1580 kill |= ATTR_KILL_SGID;
1581
1582 if (unlikely(kill && !capable(CAP_FSETID) && S_ISREG(mode)))
1583 return kill;
1584
1585 return 0;
1586}
1587EXPORT_SYMBOL(should_remove_suid);
1588
1589static int __remove_suid(struct dentry *dentry, int kill)
1590{
1591 struct iattr newattrs;
1592
1593 newattrs.ia_valid = ATTR_FORCE | kill;
1594 return notify_change(dentry, &newattrs);
1595}
1596
1597int file_remove_suid(struct file *file)
1598{
1599 struct dentry *dentry = file->f_path.dentry;
1600 struct inode *inode = dentry->d_inode;
1601 int killsuid;
1602 int killpriv;
1603 int error = 0;
1604
1605 /* Fast path for nothing security related */
1606 if (IS_NOSEC(inode))
1607 return 0;
1608
1609 killsuid = should_remove_suid(dentry);
1610 killpriv = security_inode_need_killpriv(dentry);
1611
1612 if (killpriv < 0)
1613 return killpriv;
1614 if (killpriv)
1615 error = security_inode_killpriv(dentry);
1616 if (!error && killsuid)
1617 error = __remove_suid(dentry, killsuid);
1618 if (!error && (inode->i_sb->s_flags & MS_NOSEC))
1619 inode->i_flags |= S_NOSEC;
1620
1621 return error;
1622}
1623EXPORT_SYMBOL(file_remove_suid);
1624
1534/** 1625/**
1535 * file_update_time - update mtime and ctime time 1626 * file_update_time - update mtime and ctime time
1536 * @file: file accessed 1627 * @file: file accessed
@@ -1540,18 +1631,20 @@ EXPORT_SYMBOL(touch_atime);
1540 * usage in the file write path of filesystems, and filesystems may 1631 * usage in the file write path of filesystems, and filesystems may
1541 * choose to explicitly ignore update via this function with the 1632 * choose to explicitly ignore update via this function with the
1542 * S_NOCMTIME inode flag, e.g. for network filesystem where these 1633 * S_NOCMTIME inode flag, e.g. for network filesystem where these
1543 * timestamps are handled by the server. 1634 * timestamps are handled by the server. This can return an error for
1635 * file systems who need to allocate space in order to update an inode.
1544 */ 1636 */
1545 1637
1546void file_update_time(struct file *file) 1638int file_update_time(struct file *file)
1547{ 1639{
1548 struct inode *inode = file->f_path.dentry->d_inode; 1640 struct inode *inode = file->f_path.dentry->d_inode;
1549 struct timespec now; 1641 struct timespec now;
1550 enum { S_MTIME = 1, S_CTIME = 2, S_VERSION = 4 } sync_it = 0; 1642 int sync_it = 0;
1643 int ret;
1551 1644
1552 /* First try to exhaust all avenues to not sync */ 1645 /* First try to exhaust all avenues to not sync */
1553 if (IS_NOCMTIME(inode)) 1646 if (IS_NOCMTIME(inode))
1554 return; 1647 return 0;
1555 1648
1556 now = current_fs_time(inode->i_sb); 1649 now = current_fs_time(inode->i_sb);
1557 if (!timespec_equal(&inode->i_mtime, &now)) 1650 if (!timespec_equal(&inode->i_mtime, &now))
@@ -1564,21 +1657,16 @@ void file_update_time(struct file *file)
1564 sync_it |= S_VERSION; 1657 sync_it |= S_VERSION;
1565 1658
1566 if (!sync_it) 1659 if (!sync_it)
1567 return; 1660 return 0;
1568 1661
1569 /* Finally allowed to write? Takes lock. */ 1662 /* Finally allowed to write? Takes lock. */
1570 if (mnt_want_write_file(file)) 1663 if (mnt_want_write_file(file))
1571 return; 1664 return 0;
1572 1665
1573 /* Only change inode inside the lock region */ 1666 ret = update_time(inode, &now, sync_it);
1574 if (sync_it & S_VERSION)
1575 inode_inc_iversion(inode);
1576 if (sync_it & S_CTIME)
1577 inode->i_ctime = now;
1578 if (sync_it & S_MTIME)
1579 inode->i_mtime = now;
1580 mark_inode_dirty_sync(inode);
1581 mnt_drop_write_file(file); 1667 mnt_drop_write_file(file);
1668
1669 return ret;
1582} 1670}
1583EXPORT_SYMBOL(file_update_time); 1671EXPORT_SYMBOL(file_update_time);
1584 1672