Merge remote-tracking branch 'ovl/misc' into work.misc

This commit is contained in:
Al Viro 2016-10-08 11:00:01 -04:00
commit f334bcd94b
25 changed files with 170 additions and 101 deletions

View File

@ -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 */

View File

@ -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);

View File

@ -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;
}

View File

@ -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,

View File

@ -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;
}
@ -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:

View File

@ -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;

View File

@ -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));
}
@ -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); */
@ -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;

View File

@ -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);

View File

@ -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);
@ -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;

View File

@ -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
@ -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;
@ -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);
@ -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);
@ -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);

View File

@ -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:
*/
@ -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;
@ -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))
@ -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))

View File

@ -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
*/

View File

@ -139,6 +139,11 @@
#define IS_LEASE(fl) (fl->fl_flags & (FL_LEASE|FL_DELEG|FL_LAYOUT))
#define IS_OFDLCK(fl) (fl->fl_flags & FL_OFDLCK)
static inline bool is_remote_lock(struct file *filp)
{
return likely(!(filp->f_path.dentry->d_sb->s_flags & MS_NOREMOTELOCK));
}
static bool lease_breaking(struct file_lock *fl)
{
return fl->fl_flags & (FL_UNLOCK_PENDING | FL_DOWNGRADE_PENDING);
@ -791,7 +796,7 @@ posix_test_lock(struct file *filp, struct file_lock *fl)
{
struct file_lock *cfl;
struct file_lock_context *ctx;
struct inode *inode = file_inode(filp);
struct inode *inode = locks_inode(filp);
ctx = smp_load_acquire(&inode->i_flctx);
if (!ctx || list_empty_careful(&ctx->flc_posix)) {
@ -1192,7 +1197,7 @@ static int posix_lock_inode(struct inode *inode, struct file_lock *request,
int posix_lock_file(struct file *filp, struct file_lock *fl,
struct file_lock *conflock)
{
return posix_lock_inode(file_inode(filp), fl, conflock);
return posix_lock_inode(locks_inode(filp), fl, conflock);
}
EXPORT_SYMBOL(posix_lock_file);
@ -1232,7 +1237,7 @@ static int posix_lock_inode_wait(struct inode *inode, struct file_lock *fl)
int locks_mandatory_locked(struct file *file)
{
int ret;
struct inode *inode = file_inode(file);
struct inode *inode = locks_inode(file);
struct file_lock_context *ctx;
struct file_lock *fl;
@ -1572,7 +1577,7 @@ EXPORT_SYMBOL(lease_get_mtime);
int fcntl_getlease(struct file *filp)
{
struct file_lock *fl;
struct inode *inode = file_inode(filp);
struct inode *inode = locks_inode(filp);
struct file_lock_context *ctx;
int type = F_UNLCK;
LIST_HEAD(dispose);
@ -1580,7 +1585,7 @@ int fcntl_getlease(struct file *filp)
ctx = smp_load_acquire(&inode->i_flctx);
if (ctx && !list_empty_careful(&ctx->flc_lease)) {
spin_lock(&ctx->flc_lock);
time_out_leases(file_inode(filp), &dispose);
time_out_leases(inode, &dispose);
list_for_each_entry(fl, &ctx->flc_lease, fl_list) {
if (fl->fl_file != filp)
continue;
@ -1613,7 +1618,8 @@ check_conflicting_open(const struct dentry *dentry, const long arg, int flags)
if (flags & FL_LAYOUT)
return 0;
if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0))
if ((arg == F_RDLCK) &&
(atomic_read(&d_real_inode(dentry)->i_writecount) > 0))
return -EAGAIN;
if ((arg == F_WRLCK) && ((d_count(dentry) > 1) ||
@ -1628,7 +1634,7 @@ generic_add_lease(struct file *filp, long arg, struct file_lock **flp, void **pr
{
struct file_lock *fl, *my_fl = NULL, *lease;
struct dentry *dentry = filp->f_path.dentry;
struct inode *inode = file_inode(filp);
struct inode *inode = dentry->d_inode;
struct file_lock_context *ctx;
bool is_deleg = (*flp)->fl_flags & FL_DELEG;
int error;
@ -1742,7 +1748,7 @@ static int generic_delete_lease(struct file *filp, void *owner)
{
int error = -EAGAIN;
struct file_lock *fl, *victim = NULL;
struct inode *inode = file_inode(filp);
struct inode *inode = locks_inode(filp);
struct file_lock_context *ctx;
LIST_HEAD(dispose);
@ -1782,7 +1788,7 @@ static int generic_delete_lease(struct file *filp, void *owner)
int generic_setlease(struct file *filp, long arg, struct file_lock **flp,
void **priv)
{
struct inode *inode = file_inode(filp);
struct inode *inode = locks_inode(filp);
int error;
if ((!uid_eq(current_fsuid(), inode->i_uid)) && !capable(CAP_LEASE))
@ -1830,7 +1836,7 @@ EXPORT_SYMBOL(generic_setlease);
int
vfs_setlease(struct file *filp, long arg, struct file_lock **lease, void **priv)
{
if (filp->f_op->setlease)
if (filp->f_op->setlease && is_remote_lock(filp))
return filp->f_op->setlease(filp, arg, lease, priv);
else
return generic_setlease(filp, arg, lease, priv);
@ -1979,7 +1985,7 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd)
if (error)
goto out_free;
if (f.file->f_op->flock)
if (f.file->f_op->flock && is_remote_lock(f.file))
error = f.file->f_op->flock(f.file,
(can_sleep) ? F_SETLKW : F_SETLK,
lock);
@ -2005,7 +2011,7 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd)
*/
int vfs_test_lock(struct file *filp, struct file_lock *fl)
{
if (filp->f_op->lock)
if (filp->f_op->lock && is_remote_lock(filp))
return filp->f_op->lock(filp, F_GETLK, fl);
posix_test_lock(filp, fl);
return 0;
@ -2129,7 +2135,7 @@ int fcntl_getlk(struct file *filp, unsigned int cmd, struct flock __user *l)
*/
int vfs_lock_file(struct file *filp, unsigned int cmd, struct file_lock *fl, struct file_lock *conf)
{
if (filp->f_op->lock)
if (filp->f_op->lock && is_remote_lock(filp))
return filp->f_op->lock(filp, cmd, fl);
else
return posix_lock_file(filp, fl, conf);
@ -2191,7 +2197,7 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd,
if (file_lock == NULL)
return -ENOLCK;
inode = file_inode(filp);
inode = locks_inode(filp);
/*
* This might block, so we do it before checking the inode.
@ -2343,7 +2349,7 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd,
if (copy_from_user(&flock, l, sizeof(flock)))
goto out;
inode = file_inode(filp);
inode = locks_inode(filp);
/* Don't allow mandatory locks on files that may be memory mapped
* and shared.
@ -2426,6 +2432,7 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd,
void locks_remove_posix(struct file *filp, fl_owner_t owner)
{
int error;
struct inode *inode = locks_inode(filp);
struct file_lock lock;
struct file_lock_context *ctx;
@ -2434,7 +2441,7 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner)
* posix_lock_file(). Another process could be setting a lock on this
* file at the same time, but we wouldn't remove that lock anyway.
*/
ctx = smp_load_acquire(&file_inode(filp)->i_flctx);
ctx = smp_load_acquire(&inode->i_flctx);
if (!ctx || list_empty(&ctx->flc_posix))
return;
@ -2452,7 +2459,7 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner)
if (lock.fl_ops && lock.fl_ops->fl_release_private)
lock.fl_ops->fl_release_private(&lock);
trace_locks_remove_posix(file_inode(filp), &lock, error);
trace_locks_remove_posix(inode, &lock, error);
}
EXPORT_SYMBOL(locks_remove_posix);
@ -2469,12 +2476,12 @@ locks_remove_flock(struct file *filp, struct file_lock_context *flctx)
.fl_type = F_UNLCK,
.fl_end = OFFSET_MAX,
};
struct inode *inode = file_inode(filp);
struct inode *inode = locks_inode(filp);
if (list_empty(&flctx->flc_flock))
return;
if (filp->f_op->flock)
if (filp->f_op->flock && is_remote_lock(filp))
filp->f_op->flock(filp, F_SETLKW, &fl);
else
flock_lock_inode(inode, &fl);
@ -2508,7 +2515,7 @@ void locks_remove_file(struct file *filp)
{
struct file_lock_context *ctx;
ctx = smp_load_acquire(&file_inode(filp)->i_flctx);
ctx = smp_load_acquire(&locks_inode(filp)->i_flctx);
if (!ctx)
return;
@ -2552,7 +2559,7 @@ EXPORT_SYMBOL(posix_unblock_lock);
*/
int vfs_cancel_lock(struct file *filp, struct file_lock *fl)
{
if (filp->f_op->lock)
if (filp->f_op->lock && is_remote_lock(filp))
return filp->f_op->lock(filp, F_CANCELLK, fl);
return 0;
}
@ -2580,7 +2587,7 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl,
fl_pid = fl->fl_pid;
if (fl->fl_file != NULL)
inode = file_inode(fl->fl_file);
inode = locks_inode(fl->fl_file);
seq_printf(f, "%lld:%s ", id, pfx);
if (IS_POSIX(fl)) {
@ -2682,7 +2689,7 @@ static void __show_fd_locks(struct seq_file *f,
void show_fd_locks(struct seq_file *f,
struct file *filp, struct files_struct *files)
{
struct inode *inode = file_inode(filp);
struct inode *inode = locks_inode(filp);
struct file_lock_context *ctx;
int id = 0;

View File

@ -1015,7 +1015,7 @@ const char *get_link(struct nameidata *nd)
if (!(nd->flags & LOOKUP_RCU)) {
touch_atime(&last->link);
cond_resched();
} else if (atime_needs_update(&last->link, inode)) {
} else if (atime_needs_update_rcu(&last->link, inode)) {
if (unlikely(unlazy_walk(nd, NULL, 0)))
return ERR_PTR(-ECHILD);
touch_atime(&last->link);

View File

@ -2700,7 +2700,7 @@ long do_mount(const char *dev_name, const char __user *dir_name,
flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE | MS_BORN |
MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT |
MS_STRICTATIME);
MS_STRICTATIME | MS_NOREMOTELOCK);
if (flags & MS_REMOUNT)
retval = do_remount(&path, flags & ~MS_REMOUNT, mnt_flags,

View File

@ -68,6 +68,7 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
long vfs_truncate(const struct path *path, loff_t length)
{
struct inode *inode;
struct dentry *upperdentry;
long error;
inode = path->dentry->d_inode;
@ -90,7 +91,17 @@ long vfs_truncate(const struct path *path, loff_t length)
if (IS_APPEND(inode))
goto mnt_drop_write_and_out;
error = get_write_access(inode);
/*
* If this is an overlayfs then do as if opening the file so we get
* write access on the upper inode, not on the overlay inode. For
* non-overlay filesystems d_real() is an identity function.
*/
upperdentry = d_real(path->dentry, NULL, O_WRONLY);
error = PTR_ERR(upperdentry);
if (IS_ERR(upperdentry))
goto mnt_drop_write_and_out;
error = get_write_access(upperdentry->d_inode);
if (error)
goto mnt_drop_write_and_out;
@ -109,7 +120,7 @@ long vfs_truncate(const struct path *path, loff_t length)
error = do_truncate(path->dentry, length, 0, NULL);
put_write_and_out:
put_write_access(inode);
put_write_access(upperdentry->d_inode);
mnt_drop_write_and_out:
mnt_drop_write(path->mnt);
out:
@ -726,7 +737,7 @@ static int do_dentry_open(struct file *f,
if (error)
goto cleanup_all;
error = break_lease(inode, f->f_flags);
error = break_lease(locks_inode(f), f->f_flags);
if (error)
goto cleanup_all;

View File

@ -1320,7 +1320,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
sb->s_xattr = ovl_xattr_handlers;
sb->s_root = root_dentry;
sb->s_fs_info = ufs;
sb->s_flags |= MS_POSIXACL;
sb->s_flags |= MS_POSIXACL | MS_NOREMOTELOCK;
return 0;

View File

@ -598,13 +598,14 @@ posix_acl_create(struct inode *dir, umode_t *mode,
if (IS_ERR(p))
return PTR_ERR(p);
ret = -ENOMEM;
clone = posix_acl_clone(p, GFP_NOFS);
if (!clone)
goto no_mem;
goto err_release;
ret = posix_acl_create_masq(clone, mode);
if (ret < 0)
goto no_mem_clone;
goto err_release_clone;
if (ret == 0)
posix_acl_release(clone);
@ -618,11 +619,11 @@ posix_acl_create(struct inode *dir, umode_t *mode,
return 0;
no_mem_clone:
err_release_clone:
posix_acl_release(clone);
no_mem:
err_release:
posix_acl_release(p);
return -ENOMEM;
return ret;
}
EXPORT_SYMBOL_GPL(posix_acl_create);

View File

@ -87,21 +87,7 @@ static int utimes_common(struct path *path, struct timespec *times)
*/
newattrs.ia_valid |= ATTR_TIMES_SET;
} else {
/*
* If times is NULL (or both times are UTIME_NOW),
* then we need to check permissions, because
* inode_change_ok() won't do it.
*/
error = -EPERM;
if (IS_IMMUTABLE(inode))
goto mnt_drop_write_and_out;
error = -EACCES;
if (!inode_owner_or_capable(inode)) {
error = inode_permission(inode, MAY_WRITE);
if (error)
goto mnt_drop_write_and_out;
}
newattrs.ia_valid |= ATTR_TOUCH;
}
retry_deleg:
inode_lock(inode);
@ -113,7 +99,6 @@ static int utimes_common(struct path *path, struct timespec *times)
goto retry_deleg;
}
mnt_drop_write_and_out:
mnt_drop_write(path->mnt);
out:
return error;

View File

@ -584,9 +584,10 @@ static inline struct dentry *d_real(struct dentry *dentry,
* If dentry is on an union/overlay, then return the underlying, real inode.
* Otherwise return d_inode().
*/
static inline struct inode *d_real_inode(struct dentry *dentry)
static inline struct inode *d_real_inode(const struct dentry *dentry)
{
return d_backing_inode(d_real(dentry, NULL, 0));
/* This usage of d_real() results in const dentry */
return d_backing_inode(d_real((struct dentry *) dentry, NULL, 0));
}

View File

@ -224,6 +224,7 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
#define ATTR_KILL_PRIV (1 << 14)
#define ATTR_OPEN (1 << 15) /* Truncating from open(O_TRUNC) */
#define ATTR_TIMES_SET (1 << 16)
#define ATTR_TOUCH (1 << 17)
/*
* Whiteout is represented by a char device. The following constants define the
@ -1064,6 +1065,18 @@ struct file_lock_context {
extern void send_sigio(struct fown_struct *fown, int fd, int band);
/*
* Return the inode to use for locking
*
* For overlayfs this should be the overlay inode, not the real inode returned
* by file_inode(). For any other fs file_inode(filp) and locks_inode(filp) are
* equal.
*/
static inline struct inode *locks_inode(const struct file *f)
{
return f->f_path.dentry->d_inode;
}
#ifdef CONFIG_FILE_LOCKING
extern int fcntl_getlk(struct file *, unsigned int, struct flock __user *);
extern int fcntl_setlk(unsigned int, struct file *, unsigned int,
@ -1251,7 +1264,7 @@ static inline struct dentry *file_dentry(const struct file *file)
static inline int locks_lock_file_wait(struct file *filp, struct file_lock *fl)
{
return locks_lock_inode_wait(file_inode(filp), fl);
return locks_lock_inode_wait(locks_inode(filp), fl);
}
struct fasync_struct {
@ -2006,7 +2019,6 @@ enum file_time_flags {
S_VERSION = 8,
};
extern bool atime_needs_update(const struct path *, struct inode *);
extern void touch_atime(const struct path *);
static inline void file_accessed(struct file *file)
{
@ -2155,7 +2167,7 @@ static inline int mandatory_lock(struct inode *ino)
static inline int locks_verify_locked(struct file *file)
{
if (mandatory_lock(file_inode(file)))
if (mandatory_lock(locks_inode(file)))
return locks_mandatory_locked(file);
return 0;
}

View File

@ -29,7 +29,11 @@ static inline int fsnotify_parent(struct path *path, struct dentry *dentry, __u3
static inline int fsnotify_perm(struct file *file, int mask)
{
struct path *path = &file->f_path;
struct inode *inode = file_inode(file);
/*
* Do not use file_inode() here or anywhere in this file to get the
* inode. That would break *notity on overlayfs.
*/
struct inode *inode = path->dentry->d_inode;
__u32 fsnotify_mask = 0;
int ret;
@ -173,7 +177,7 @@ static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry)
static inline void fsnotify_access(struct file *file)
{
struct path *path = &file->f_path;
struct inode *inode = file_inode(file);
struct inode *inode = path->dentry->d_inode;
__u32 mask = FS_ACCESS;
if (S_ISDIR(inode->i_mode))
@ -191,7 +195,7 @@ static inline void fsnotify_access(struct file *file)
static inline void fsnotify_modify(struct file *file)
{
struct path *path = &file->f_path;
struct inode *inode = file_inode(file);
struct inode *inode = path->dentry->d_inode;
__u32 mask = FS_MODIFY;
if (S_ISDIR(inode->i_mode))
@ -209,7 +213,7 @@ static inline void fsnotify_modify(struct file *file)
static inline void fsnotify_open(struct file *file)
{
struct path *path = &file->f_path;
struct inode *inode = file_inode(file);
struct inode *inode = path->dentry->d_inode;
__u32 mask = FS_OPEN;
if (S_ISDIR(inode->i_mode))
@ -225,7 +229,7 @@ static inline void fsnotify_open(struct file *file)
static inline void fsnotify_close(struct file *file)
{
struct path *path = &file->f_path;
struct inode *inode = file_inode(file);
struct inode *inode = path->dentry->d_inode;
fmode_t mode = file->f_mode;
__u32 mask = (mode & FMODE_WRITE) ? FS_CLOSE_WRITE : FS_CLOSE_NOWRITE;

View File

@ -132,6 +132,7 @@ struct inodes_stat_t {
#define MS_LAZYTIME (1<<25) /* Update the on-disk [acm]times lazily */
/* These sb flags are internal to the kernel */
#define MS_NOREMOTELOCK (1<<27)
#define MS_NOSEC (1<<28)
#define MS_BORN (1<<29)
#define MS_ACTIVE (1<<30)

View File

@ -190,7 +190,7 @@ int ima_appraise_measurement(enum ima_hooks func,
{
static const char op[] = "appraise_data";
char *cause = "unknown";
struct dentry *dentry = file->f_path.dentry;
struct dentry *dentry = file_dentry(file);
struct inode *inode = d_backing_inode(dentry);
enum integrity_status status = INTEGRITY_UNKNOWN;
int rc = xattr_len, hash_start = 0;
@ -295,7 +295,7 @@ int ima_appraise_measurement(enum ima_hooks func,
*/
void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file)
{
struct dentry *dentry = file->f_path.dentry;
struct dentry *dentry = file_dentry(file);
int rc = 0;
/* do not collect and update hash for digital signatures */

View File

@ -228,7 +228,7 @@ static int process_measurement(struct file *file, char *buf, loff_t size,
if ((action & IMA_APPRAISE_SUBMASK) ||
strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) != 0)
/* read 'security.ima' */
xattr_len = ima_read_xattr(file->f_path.dentry, &xattr_value);
xattr_len = ima_read_xattr(file_dentry(file), &xattr_value);
hash_algo = ima_get_hash_algo(xattr_value, xattr_len);