Skip to content

Commit

Permalink
Merge remote-tracking branch 'ovl/misc' into work.misc
Browse files Browse the repository at this point in the history
  • Loading branch information
Al Viro committed Oct 8, 2016
2 parents 73e8fb2 + 814184f commit f334bcd
Show file tree
Hide file tree
Showing 25 changed files with 170 additions and 101 deletions.
15 changes: 15 additions & 0 deletions fs/attr.c
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,21 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de
return -EPERM;
}

/*
* If utimes(2) and friends are called with times == NULL (or both
* times are UTIME_NOW), then we need to check for write permission
*/
if (ia_valid & ATTR_TOUCH) {
if (IS_IMMUTABLE(inode))
return -EPERM;

if (!inode_owner_or_capable(inode)) {
error = inode_permission(inode, MAY_WRITE);
if (error)
return error;
}
}

if ((ia_valid & ATTR_MODE)) {
umode_t amode = attr->ia_mode;
/* Flag setting protected by i_mutex */
Expand Down
1 change: 0 additions & 1 deletion fs/btrfs/ctree.h
Original file line number Diff line number Diff line change
Expand Up @@ -3161,7 +3161,6 @@ int btrfs_prealloc_file_range_trans(struct inode *inode,
struct btrfs_trans_handle *trans, int mode,
u64 start, u64 num_bytes, u64 min_size,
loff_t actual_len, u64 *alloc_hint);
int btrfs_inode_check_errors(struct inode *inode);
extern const struct dentry_operations btrfs_dentry_operations;
#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
void btrfs_test_inode_set_ops(struct inode *inode);
Expand Down
2 changes: 1 addition & 1 deletion fs/btrfs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -2040,7 +2040,7 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
* flags for any errors that might have happened while doing
* writeback of file data.
*/
ret = btrfs_inode_check_errors(inode);
ret = filemap_check_errors(inode->i_mapping);
inode_unlock(inode);
goto out;
}
Expand Down
15 changes: 0 additions & 15 deletions fs/btrfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -10543,21 +10543,6 @@ static int btrfs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)

}

/* Inspired by filemap_check_errors() */
int btrfs_inode_check_errors(struct inode *inode)
{
int ret = 0;

if (test_bit(AS_ENOSPC, &inode->i_mapping->flags) &&
test_and_clear_bit(AS_ENOSPC, &inode->i_mapping->flags))
ret = -ENOSPC;
if (test_bit(AS_EIO, &inode->i_mapping->flags) &&
test_and_clear_bit(AS_EIO, &inode->i_mapping->flags))
ret = -EIO;

return ret;
}

static const struct inode_operations btrfs_dir_inode_operations = {
.getattr = btrfs_getattr,
.lookup = btrfs_lookup,
Expand Down
4 changes: 2 additions & 2 deletions fs/btrfs/tree-log.c
Original file line number Diff line number Diff line change
Expand Up @@ -3961,7 +3961,7 @@ static int wait_ordered_extents(struct btrfs_trans_handle *trans,
* i_mapping flags, so that the next fsync won't get
* an outdated io error too.
*/
btrfs_inode_check_errors(inode);
filemap_check_errors(inode->i_mapping);
*ordered_io_error = true;
break;
}
Expand Down Expand Up @@ -4198,7 +4198,7 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans,
* without writing to the log tree and the fsync must report the
* file data write error and not commit the current transaction.
*/
ret = btrfs_inode_check_errors(inode);
ret = filemap_check_errors(inode->i_mapping);
if (ret)
ctx->io_err = ret;
process:
Expand Down
10 changes: 10 additions & 0 deletions fs/cifs/cifsfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ cifs_uniqueid_to_ino_t(u64 fileid)

}

static inline void cifs_set_time(struct dentry *dentry, unsigned long time)
{
dentry->d_fsdata = (void *) time;
}

static inline unsigned long cifs_get_time(struct dentry *dentry)
{
return (unsigned long) dentry->d_fsdata;
}

extern struct file_system_type cifs_fs_type;
extern const struct address_space_operations cifs_addr_ops;
extern const struct address_space_operations cifs_addr_ops_smallbuf;
Expand Down
6 changes: 3 additions & 3 deletions fs/cifs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ renew_parental_timestamps(struct dentry *direntry)
/* BB check if there is a way to get the kernel to do this or if we
really need this */
do {
direntry->d_time = jiffies;
cifs_set_time(direntry, jiffies);
direntry = direntry->d_parent;
} while (!IS_ROOT(direntry));
}
Expand Down Expand Up @@ -802,7 +802,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,

} else if (rc == -ENOENT) {
rc = 0;
direntry->d_time = jiffies;
cifs_set_time(direntry, jiffies);
d_add(direntry, NULL);
/* if it was once a directory (but how can we tell?) we could do
shrink_dcache_parent(direntry); */
Expand Down Expand Up @@ -862,7 +862,7 @@ cifs_d_revalidate(struct dentry *direntry, unsigned int flags)
if (flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
return 0;

if (time_after(jiffies, direntry->d_time + HZ) || !lookupCacheEnabled)
if (time_after(jiffies, cifs_get_time(direntry) + HZ) || !lookupCacheEnabled)
return 0;

return 1;
Expand Down
2 changes: 1 addition & 1 deletion fs/cifs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1951,7 +1951,7 @@ int cifs_revalidate_dentry_attr(struct dentry *dentry)

cifs_dbg(FYI, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld\n",
full_path, inode, inode->i_count.counter,
dentry, dentry->d_time, jiffies);
dentry, cifs_get_time(dentry), jiffies);

if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
Expand Down
7 changes: 2 additions & 5 deletions fs/f2fs/node.c
Original file line number Diff line number Diff line change
Expand Up @@ -1513,7 +1513,7 @@ int wait_on_node_pages_writeback(struct f2fs_sb_info *sbi, nid_t ino)
{
pgoff_t index = 0, end = ULONG_MAX;
struct pagevec pvec;
int ret2 = 0, ret = 0;
int ret2, ret = 0;

pagevec_init(&pvec, 0);

Expand Down Expand Up @@ -1542,10 +1542,7 @@ int wait_on_node_pages_writeback(struct f2fs_sb_info *sbi, nid_t ino)
cond_resched();
}

if (unlikely(test_and_clear_bit(AS_ENOSPC, &NODE_MAPPING(sbi)->flags)))
ret2 = -ENOSPC;
if (unlikely(test_and_clear_bit(AS_EIO, &NODE_MAPPING(sbi)->flags)))
ret2 = -EIO;
ret2 = filemap_check_errors(NODE_MAPPING(sbi));
if (!ret)
ret = ret2;
return ret;
Expand Down
19 changes: 15 additions & 4 deletions fs/fat/namei_vfat.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,17 @@
#include <linux/namei.h>
#include "fat.h"

static inline unsigned long vfat_d_version(struct dentry *dentry)
{
return (unsigned long) dentry->d_fsdata;
}

static inline void vfat_d_version_set(struct dentry *dentry,
unsigned long version)
{
dentry->d_fsdata = (void *) version;
}

/*
* If new entry was created in the parent, it could create the 8.3
* alias (the shortname of logname). So, the parent may have the
Expand All @@ -33,7 +44,7 @@ static int vfat_revalidate_shortname(struct dentry *dentry)
{
int ret = 1;
spin_lock(&dentry->d_lock);
if (dentry->d_time != d_inode(dentry->d_parent)->i_version)
if (vfat_d_version(dentry) != d_inode(dentry->d_parent)->i_version)
ret = 0;
spin_unlock(&dentry->d_lock);
return ret;
Expand Down Expand Up @@ -759,7 +770,7 @@ static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry,
out:
mutex_unlock(&MSDOS_SB(sb)->s_lock);
if (!inode)
dentry->d_time = dir->i_version;
vfat_d_version_set(dentry, dir->i_version);
return d_splice_alias(inode, dentry);
error:
mutex_unlock(&MSDOS_SB(sb)->s_lock);
Expand Down Expand Up @@ -823,7 +834,7 @@ static int vfat_rmdir(struct inode *dir, struct dentry *dentry)
clear_nlink(inode);
inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC;
fat_detach(inode);
dentry->d_time = dir->i_version;
vfat_d_version_set(dentry, dir->i_version);
out:
mutex_unlock(&MSDOS_SB(sb)->s_lock);

Expand All @@ -849,7 +860,7 @@ static int vfat_unlink(struct inode *dir, struct dentry *dentry)
clear_nlink(inode);
inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC;
fat_detach(inode);
dentry->d_time = dir->i_version;
vfat_d_version_set(dentry, dir->i_version);
out:
mutex_unlock(&MSDOS_SB(sb)->s_lock);

Expand Down
33 changes: 27 additions & 6 deletions fs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1562,17 +1562,37 @@ sector_t bmap(struct inode *inode, sector_t block)
}
EXPORT_SYMBOL(bmap);

/*
* Update times in overlayed inode from underlying real inode
*/
static void update_ovl_inode_times(struct dentry *dentry, struct inode *inode,
bool rcu)
{
if (!rcu) {
struct inode *realinode = d_real_inode(dentry);

if (unlikely(inode != realinode) &&
(!timespec_equal(&inode->i_mtime, &realinode->i_mtime) ||
!timespec_equal(&inode->i_ctime, &realinode->i_ctime))) {
inode->i_mtime = realinode->i_mtime;
inode->i_ctime = realinode->i_ctime;
}
}
}

/*
* With relative atime, only update atime if the previous atime is
* earlier than either the ctime or mtime or if at least a day has
* passed since the last atime update.
*/
static int relatime_need_update(struct vfsmount *mnt, struct inode *inode,
struct timespec now)
static int relatime_need_update(const struct path *path, struct inode *inode,
struct timespec now, bool rcu)
{

if (!(mnt->mnt_flags & MNT_RELATIME))
if (!(path->mnt->mnt_flags & MNT_RELATIME))
return 1;

update_ovl_inode_times(path->dentry, inode, rcu);
/*
* Is mtime younger than atime? If yes, update atime:
*/
Expand Down Expand Up @@ -1639,7 +1659,8 @@ static int update_time(struct inode *inode, struct timespec *time, int flags)
* This function automatically handles read only file systems and media,
* as well as the "noatime" flag and inode specific "noatime" markers.
*/
bool atime_needs_update(const struct path *path, struct inode *inode)
bool __atime_needs_update(const struct path *path, struct inode *inode,
bool rcu)
{
struct vfsmount *mnt = path->mnt;
struct timespec now;
Expand All @@ -1665,7 +1686,7 @@ bool atime_needs_update(const struct path *path, struct inode *inode)

now = current_fs_time(inode->i_sb);

if (!relatime_need_update(mnt, inode, now))
if (!relatime_need_update(path, inode, now, rcu))
return false;

if (timespec_equal(&inode->i_atime, &now))
Expand All @@ -1680,7 +1701,7 @@ void touch_atime(const struct path *path)
struct inode *inode = d_inode(path->dentry);
struct timespec now;

if (!atime_needs_update(path, inode))
if (!__atime_needs_update(path, inode, false))
return;

if (!sb_start_write_trylock(inode->i_sb))
Expand Down
9 changes: 9 additions & 0 deletions fs/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,15 @@ extern long prune_icache_sb(struct super_block *sb, struct shrink_control *sc);
extern void inode_add_lru(struct inode *inode);
extern int dentry_needs_remove_privs(struct dentry *dentry);

extern bool __atime_needs_update(const struct path *, struct inode *, bool);
static inline bool atime_needs_update_rcu(const struct path *path,
struct inode *inode)
{
return __atime_needs_update(path, inode, true);
}

extern bool atime_needs_update_rcu(const struct path *, struct inode *);

/*
* fs-writeback.c
*/
Expand Down
Loading

0 comments on commit f334bcd

Please sign in to comment.