2019-05-27 14:55:05 +08:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
2005-05-05 04:29:35 +08:00
|
|
|
* Copyright (C) International Business Machines Corp., 2000-2002
|
|
|
|
* Portions Copyright (C) Christoph Hellwig, 2001-2002
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
|
|
|
|
2010-06-04 17:30:02 +08:00
|
|
|
#include <linux/mm.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <linux/fs.h>
|
2013-12-20 21:16:51 +08:00
|
|
|
#include <linux/posix_acl.h>
|
2010-03-03 22:05:02 +08:00
|
|
|
#include <linux/quotaops.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include "jfs_incore.h"
|
2005-05-05 04:29:35 +08:00
|
|
|
#include "jfs_inode.h"
|
2005-04-17 06:20:36 +08:00
|
|
|
#include "jfs_dmap.h"
|
|
|
|
#include "jfs_txnmgr.h"
|
|
|
|
#include "jfs_xattr.h"
|
|
|
|
#include "jfs_acl.h"
|
|
|
|
#include "jfs_debug.h"
|
|
|
|
|
2011-07-17 08:44:56 +08:00
|
|
|
int jfs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2010-05-26 23:53:25 +08:00
|
|
|
struct inode *inode = file->f_mapping->host;
|
2005-04-17 06:20:36 +08:00
|
|
|
int rc = 0;
|
|
|
|
|
2017-07-08 03:20:52 +08:00
|
|
|
rc = file_write_and_wait_range(file, start, end);
|
2011-07-17 08:44:56 +08:00
|
|
|
if (rc)
|
|
|
|
return rc;
|
|
|
|
|
2016-01-23 04:40:57 +08:00
|
|
|
inode_lock(inode);
|
2015-02-02 13:37:00 +08:00
|
|
|
if (!(inode->i_state & I_DIRTY_ALL) ||
|
2005-04-17 06:20:36 +08:00
|
|
|
(datasync && !(inode->i_state & I_DIRTY_DATASYNC))) {
|
|
|
|
/* Make sure committed changes hit the disk */
|
|
|
|
jfs_flush_journal(JFS_SBI(inode->i_sb)->log, 1);
|
2016-01-23 04:40:57 +08:00
|
|
|
inode_unlock(inode);
|
2005-04-17 06:20:36 +08:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc |= jfs_commit_inode(inode, 1);
|
2016-01-23 04:40:57 +08:00
|
|
|
inode_unlock(inode);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
return rc ? -EIO : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int jfs_open(struct inode *inode, struct file *file)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
2010-03-03 22:05:06 +08:00
|
|
|
if ((rc = dquot_file_open(inode, file)))
|
2005-04-17 06:20:36 +08:00
|
|
|
return rc;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We attempt to allow only one "active" file open per aggregate
|
|
|
|
* group. Otherwise, appending to files in parallel can cause
|
|
|
|
* fragmentation within the files.
|
|
|
|
*
|
|
|
|
* If the file is empty, it was probably just created and going
|
|
|
|
* to be written to. If it has a size, we'll hold off until the
|
|
|
|
* file is actually grown.
|
|
|
|
*/
|
|
|
|
if (S_ISREG(inode->i_mode) && file->f_mode & FMODE_WRITE &&
|
|
|
|
(inode->i_size == 0)) {
|
|
|
|
struct jfs_inode_info *ji = JFS_IP(inode);
|
|
|
|
spin_lock_irq(&ji->ag_lock);
|
|
|
|
if (ji->active_ag == -1) {
|
2011-06-20 23:53:46 +08:00
|
|
|
struct jfs_sb_info *jfs_sb = JFS_SBI(inode->i_sb);
|
|
|
|
ji->active_ag = BLKTOAG(addressPXD(&ji->ixpxd), jfs_sb);
|
2015-05-31 17:53:28 +08:00
|
|
|
atomic_inc(&jfs_sb->bmap->db_active[ji->active_ag]);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
spin_unlock_irq(&ji->ag_lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
static int jfs_release(struct inode *inode, struct file *file)
|
|
|
|
{
|
|
|
|
struct jfs_inode_info *ji = JFS_IP(inode);
|
|
|
|
|
|
|
|
spin_lock_irq(&ji->ag_lock);
|
|
|
|
if (ji->active_ag != -1) {
|
|
|
|
struct bmap *bmap = JFS_SBI(inode->i_sb)->bmap;
|
|
|
|
atomic_dec(&bmap->db_active[ji->active_ag]);
|
|
|
|
ji->active_ag = -1;
|
|
|
|
}
|
|
|
|
spin_unlock_irq(&ji->ag_lock);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-01-21 21:19:43 +08:00
|
|
|
int jfs_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
|
|
|
|
struct iattr *iattr)
|
2010-03-03 22:05:02 +08:00
|
|
|
{
|
2015-03-18 06:25:59 +08:00
|
|
|
struct inode *inode = d_inode(dentry);
|
2010-03-03 22:05:02 +08:00
|
|
|
int rc;
|
|
|
|
|
2021-01-21 21:19:26 +08:00
|
|
|
rc = setattr_prepare(&init_user_ns, dentry, iattr);
|
2010-03-03 22:05:02 +08:00
|
|
|
if (rc)
|
|
|
|
return rc;
|
|
|
|
|
quota: port quota helpers mount ids
Port the is_quota_modification() and dqout_transfer() helper to type
safe vfs{g,u}id_t. Since these helpers are only called by a few
filesystems don't introduce a new helper but simply extend the existing
helpers to pass down the mount's idmapping.
Note, that this is a non-functional change, i.e. nothing will have
happened here or at the end of this series to how quota are done! This
a change necessary because we will at the end of this series make
ownership changes easier to reason about by keeping the original value
in struct iattr for both non-idmapped and idmapped mounts.
For now we always pass the initial idmapping which makes the idmapping
functions these helpers call nops.
This is done because we currently always pass the actual value to be
written to i_{g,u}id via struct iattr. While this allowed us to treat
the {g,u}id values in struct iattr as values that can be directly
written to inode->i_{g,u}id it also increases the potential for
confusion for filesystems.
Now that we are have dedicated types to prevent this confusion we will
ultimately only map the value from the idmapped mount into a filesystem
value that can be written to inode->i_{g,u}id when the filesystem
actually updates the inode. So pass down the initial idmapping until we
finished that conversion at which point we pass down the mount's
idmapping.
Since struct iattr uses an anonymous union with overlapping types as
supported by the C standard, filesystems that haven't converted to
ia_vfs{g,u}id won't see any difference and things will continue to work
as before. In other words, no functional changes intended with this
change.
Link: https://lore.kernel.org/r/20220621141454.2914719-7-brauner@kernel.org
Cc: Seth Forshee <sforshee@digitalocean.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Jan Kara <jack@suse.cz>
Cc: Aleksa Sarai <cyphar@cyphar.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Al Viro <viro@zeniv.linux.org.uk>
CC: linux-fsdevel@vger.kernel.org
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Seth Forshee <sforshee@digitalocean.com>
Signed-off-by: Christian Brauner (Microsoft) <brauner@kernel.org>
2022-06-21 22:14:52 +08:00
|
|
|
if (is_quota_modification(&init_user_ns, inode, iattr)) {
|
2015-07-16 02:53:19 +08:00
|
|
|
rc = dquot_initialize(inode);
|
|
|
|
if (rc)
|
|
|
|
return rc;
|
|
|
|
}
|
2012-02-11 03:40:34 +08:00
|
|
|
if ((iattr->ia_valid & ATTR_UID && !uid_eq(iattr->ia_uid, inode->i_uid)) ||
|
|
|
|
(iattr->ia_valid & ATTR_GID && !gid_eq(iattr->ia_gid, inode->i_gid))) {
|
quota: port quota helpers mount ids
Port the is_quota_modification() and dqout_transfer() helper to type
safe vfs{g,u}id_t. Since these helpers are only called by a few
filesystems don't introduce a new helper but simply extend the existing
helpers to pass down the mount's idmapping.
Note, that this is a non-functional change, i.e. nothing will have
happened here or at the end of this series to how quota are done! This
a change necessary because we will at the end of this series make
ownership changes easier to reason about by keeping the original value
in struct iattr for both non-idmapped and idmapped mounts.
For now we always pass the initial idmapping which makes the idmapping
functions these helpers call nops.
This is done because we currently always pass the actual value to be
written to i_{g,u}id via struct iattr. While this allowed us to treat
the {g,u}id values in struct iattr as values that can be directly
written to inode->i_{g,u}id it also increases the potential for
confusion for filesystems.
Now that we are have dedicated types to prevent this confusion we will
ultimately only map the value from the idmapped mount into a filesystem
value that can be written to inode->i_{g,u}id when the filesystem
actually updates the inode. So pass down the initial idmapping until we
finished that conversion at which point we pass down the mount's
idmapping.
Since struct iattr uses an anonymous union with overlapping types as
supported by the C standard, filesystems that haven't converted to
ia_vfs{g,u}id won't see any difference and things will continue to work
as before. In other words, no functional changes intended with this
change.
Link: https://lore.kernel.org/r/20220621141454.2914719-7-brauner@kernel.org
Cc: Seth Forshee <sforshee@digitalocean.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Jan Kara <jack@suse.cz>
Cc: Aleksa Sarai <cyphar@cyphar.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Al Viro <viro@zeniv.linux.org.uk>
CC: linux-fsdevel@vger.kernel.org
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Seth Forshee <sforshee@digitalocean.com>
Signed-off-by: Christian Brauner (Microsoft) <brauner@kernel.org>
2022-06-21 22:14:52 +08:00
|
|
|
rc = dquot_transfer(&init_user_ns, inode, iattr);
|
2010-03-03 22:05:03 +08:00
|
|
|
if (rc)
|
|
|
|
return rc;
|
2010-03-03 22:05:02 +08:00
|
|
|
}
|
|
|
|
|
2010-06-04 17:30:02 +08:00
|
|
|
if ((iattr->ia_valid & ATTR_SIZE) &&
|
|
|
|
iattr->ia_size != i_size_read(inode)) {
|
2011-06-25 02:29:45 +08:00
|
|
|
inode_dio_wait(inode);
|
|
|
|
|
2012-12-15 18:54:25 +08:00
|
|
|
rc = inode_newsize_ok(inode, iattr->ia_size);
|
2010-06-04 17:30:02 +08:00
|
|
|
if (rc)
|
|
|
|
return rc;
|
2012-12-15 18:54:25 +08:00
|
|
|
|
|
|
|
truncate_setsize(inode, iattr->ia_size);
|
|
|
|
jfs_truncate(inode);
|
2010-06-04 17:30:02 +08:00
|
|
|
}
|
2010-03-03 22:05:02 +08:00
|
|
|
|
2021-01-21 21:19:26 +08:00
|
|
|
setattr_copy(&init_user_ns, inode, iattr);
|
2010-06-04 17:30:02 +08:00
|
|
|
mark_inode_dirty(inode);
|
2010-03-03 22:05:02 +08:00
|
|
|
|
2010-06-04 17:30:02 +08:00
|
|
|
if (iattr->ia_valid & ATTR_MODE)
|
2021-01-21 21:19:27 +08:00
|
|
|
rc = posix_acl_chmod(&init_user_ns, inode, inode->i_mode);
|
2010-03-03 22:05:02 +08:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2007-02-12 16:55:39 +08:00
|
|
|
const struct inode_operations jfs_file_inode_operations = {
|
2005-04-17 06:20:36 +08:00
|
|
|
.listxattr = jfs_listxattr,
|
|
|
|
.setattr = jfs_setattr,
|
2021-04-07 20:36:44 +08:00
|
|
|
.fileattr_get = jfs_fileattr_get,
|
|
|
|
.fileattr_set = jfs_fileattr_set,
|
2010-03-03 22:05:02 +08:00
|
|
|
#ifdef CONFIG_JFS_POSIX_ACL
|
2011-07-23 23:37:31 +08:00
|
|
|
.get_acl = jfs_get_acl,
|
2013-12-20 21:16:51 +08:00
|
|
|
.set_acl = jfs_set_acl,
|
2005-04-17 06:20:36 +08:00
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
2006-03-28 17:56:42 +08:00
|
|
|
const struct file_operations jfs_file_operations = {
|
2005-04-17 06:20:36 +08:00
|
|
|
.open = jfs_open,
|
|
|
|
.llseek = generic_file_llseek,
|
2014-04-03 02:33:16 +08:00
|
|
|
.read_iter = generic_file_read_iter,
|
2014-04-03 15:17:43 +08:00
|
|
|
.write_iter = generic_file_write_iter,
|
2005-04-17 06:20:36 +08:00
|
|
|
.mmap = generic_file_mmap,
|
2006-10-31 01:47:02 +08:00
|
|
|
.splice_read = generic_file_splice_read,
|
2014-04-05 16:27:08 +08:00
|
|
|
.splice_write = iter_file_splice_write,
|
2005-04-17 06:20:36 +08:00
|
|
|
.fsync = jfs_fsync,
|
|
|
|
.release = jfs_release,
|
2008-01-28 06:58:51 +08:00
|
|
|
.unlocked_ioctl = jfs_ioctl,
|
2021-04-07 20:36:44 +08:00
|
|
|
.compat_ioctl = compat_ptr_ioctl,
|
2005-04-17 06:20:36 +08:00
|
|
|
};
|