mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-15 13:22:55 +00:00
Merge branch 'xfs-misc-fixes-for-4.4-2' into for-next
This commit is contained in:
commit
2da5c4b05a
@ -1495,9 +1495,13 @@ struct xfs_acl {
|
||||
sizeof(struct xfs_acl_entry) \
|
||||
: 25)
|
||||
|
||||
#define XFS_ACL_MAX_SIZE(mp) \
|
||||
#define XFS_ACL_SIZE(cnt) \
|
||||
(sizeof(struct xfs_acl) + \
|
||||
sizeof(struct xfs_acl_entry) * XFS_ACL_MAX_ENTRIES((mp)))
|
||||
sizeof(struct xfs_acl_entry) * cnt)
|
||||
|
||||
#define XFS_ACL_MAX_SIZE(mp) \
|
||||
XFS_ACL_SIZE(XFS_ACL_MAX_ENTRIES((mp)))
|
||||
|
||||
|
||||
/* On-disk XFS extended attribute names */
|
||||
#define SGI_ACL_FILE "SGI_ACL_FILE"
|
||||
|
@ -37,16 +37,19 @@
|
||||
|
||||
STATIC struct posix_acl *
|
||||
xfs_acl_from_disk(
|
||||
struct xfs_acl *aclp,
|
||||
int max_entries)
|
||||
const struct xfs_acl *aclp,
|
||||
int len,
|
||||
int max_entries)
|
||||
{
|
||||
struct posix_acl_entry *acl_e;
|
||||
struct posix_acl *acl;
|
||||
struct xfs_acl_entry *ace;
|
||||
const struct xfs_acl_entry *ace;
|
||||
unsigned int count, i;
|
||||
|
||||
if (len < sizeof(*aclp))
|
||||
return ERR_PTR(-EFSCORRUPTED);
|
||||
count = be32_to_cpu(aclp->acl_cnt);
|
||||
if (count > max_entries)
|
||||
if (count > max_entries || XFS_ACL_SIZE(count) != len)
|
||||
return ERR_PTR(-EFSCORRUPTED);
|
||||
|
||||
acl = posix_acl_alloc(count, GFP_KERNEL);
|
||||
@ -163,7 +166,7 @@ xfs_get_acl(struct inode *inode, int type)
|
||||
goto out;
|
||||
}
|
||||
|
||||
acl = xfs_acl_from_disk(xfs_acl, XFS_ACL_MAX_ENTRIES(ip->i_mount));
|
||||
acl = xfs_acl_from_disk(xfs_acl, len, XFS_ACL_MAX_ENTRIES(ip->i_mount));
|
||||
if (IS_ERR(acl))
|
||||
goto out;
|
||||
|
||||
|
@ -36,4 +36,7 @@ static inline struct posix_acl *xfs_get_acl(struct inode *inode, int type)
|
||||
# define posix_acl_access_exists(inode) 0
|
||||
# define posix_acl_default_exists(inode) 0
|
||||
#endif /* CONFIG_XFS_POSIX_ACL */
|
||||
|
||||
extern void xfs_forget_acl(struct inode *inode, const char *name, int xflags);
|
||||
|
||||
#endif /* __XFS_ACL_H__ */
|
||||
|
@ -242,19 +242,30 @@ xfs_file_fsync(
|
||||
}
|
||||
|
||||
/*
|
||||
* All metadata updates are logged, which means that we just have
|
||||
* to flush the log up to the latest LSN that touched the inode.
|
||||
* All metadata updates are logged, which means that we just have to
|
||||
* flush the log up to the latest LSN that touched the inode. If we have
|
||||
* concurrent fsync/fdatasync() calls, we need them to all block on the
|
||||
* log force before we clear the ili_fsync_fields field. This ensures
|
||||
* that we don't get a racing sync operation that does not wait for the
|
||||
* metadata to hit the journal before returning. If we race with
|
||||
* clearing the ili_fsync_fields, then all that will happen is the log
|
||||
* force will do nothing as the lsn will already be on disk. We can't
|
||||
* race with setting ili_fsync_fields because that is done under
|
||||
* XFS_ILOCK_EXCL, and that can't happen because we hold the lock shared
|
||||
* until after the ili_fsync_fields is cleared.
|
||||
*/
|
||||
xfs_ilock(ip, XFS_ILOCK_SHARED);
|
||||
if (xfs_ipincount(ip)) {
|
||||
if (!datasync ||
|
||||
(ip->i_itemp->ili_fields & ~XFS_ILOG_TIMESTAMP))
|
||||
(ip->i_itemp->ili_fsync_fields & ~XFS_ILOG_TIMESTAMP))
|
||||
lsn = ip->i_itemp->ili_last_lsn;
|
||||
}
|
||||
xfs_iunlock(ip, XFS_ILOCK_SHARED);
|
||||
|
||||
if (lsn)
|
||||
if (lsn) {
|
||||
error = _xfs_log_force_lsn(mp, lsn, XFS_LOG_SYNC, &log_flushed);
|
||||
ip->i_itemp->ili_fsync_fields = 0;
|
||||
}
|
||||
xfs_iunlock(ip, XFS_ILOCK_SHARED);
|
||||
|
||||
/*
|
||||
* If we only have a single device, and the log force about was
|
||||
|
@ -2365,6 +2365,7 @@ retry:
|
||||
|
||||
iip->ili_last_fields = iip->ili_fields;
|
||||
iip->ili_fields = 0;
|
||||
iip->ili_fsync_fields = 0;
|
||||
iip->ili_logged = 1;
|
||||
xfs_trans_ail_copy_lsn(mp->m_ail, &iip->ili_flush_lsn,
|
||||
&iip->ili_item.li_lsn);
|
||||
@ -3560,6 +3561,7 @@ xfs_iflush_int(
|
||||
*/
|
||||
iip->ili_last_fields = iip->ili_fields;
|
||||
iip->ili_fields = 0;
|
||||
iip->ili_fsync_fields = 0;
|
||||
iip->ili_logged = 1;
|
||||
|
||||
xfs_trans_ail_copy_lsn(mp->m_ail, &iip->ili_flush_lsn,
|
||||
|
@ -719,6 +719,7 @@ xfs_iflush_abort(
|
||||
* attempted.
|
||||
*/
|
||||
iip->ili_fields = 0;
|
||||
iip->ili_fsync_fields = 0;
|
||||
}
|
||||
/*
|
||||
* Release the inode's flush lock since we're done with it.
|
||||
|
@ -34,6 +34,7 @@ typedef struct xfs_inode_log_item {
|
||||
unsigned short ili_logged; /* flushed logged data */
|
||||
unsigned int ili_last_fields; /* fields when flushed */
|
||||
unsigned int ili_fields; /* fields to be logged */
|
||||
unsigned int ili_fsync_fields; /* logged since last fsync */
|
||||
} xfs_inode_log_item_t;
|
||||
|
||||
static inline int xfs_inode_clean(xfs_inode_t *ip)
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "xfs_symlink.h"
|
||||
#include "xfs_trans.h"
|
||||
#include "xfs_pnfs.h"
|
||||
#include "xfs_acl.h"
|
||||
|
||||
#include <linux/capability.h>
|
||||
#include <linux/dcache.h>
|
||||
@ -482,6 +483,7 @@ xfs_attrmulti_attr_set(
|
||||
__uint32_t flags)
|
||||
{
|
||||
unsigned char *kbuf;
|
||||
int error;
|
||||
|
||||
if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
|
||||
return -EPERM;
|
||||
@ -492,7 +494,11 @@ xfs_attrmulti_attr_set(
|
||||
if (IS_ERR(kbuf))
|
||||
return PTR_ERR(kbuf);
|
||||
|
||||
return xfs_attr_set(XFS_I(inode), name, kbuf, len, flags);
|
||||
error = xfs_attr_set(XFS_I(inode), name, kbuf, len, flags);
|
||||
if (!error)
|
||||
xfs_forget_acl(inode, name, flags);
|
||||
kfree(kbuf);
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
@ -501,9 +507,14 @@ xfs_attrmulti_attr_remove(
|
||||
unsigned char *name,
|
||||
__uint32_t flags)
|
||||
{
|
||||
int error;
|
||||
|
||||
if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
|
||||
return -EPERM;
|
||||
return xfs_attr_remove(XFS_I(inode), name, flags);
|
||||
error = xfs_attr_remove(XFS_I(inode), name, flags);
|
||||
if (!error)
|
||||
xfs_forget_acl(inode, name, flags);
|
||||
return error;
|
||||
}
|
||||
|
||||
STATIC int
|
||||
|
@ -47,6 +47,16 @@ static DEFINE_MUTEX(xfs_uuid_table_mutex);
|
||||
static int xfs_uuid_table_size;
|
||||
static uuid_t *xfs_uuid_table;
|
||||
|
||||
void
|
||||
xfs_uuid_table_free(void)
|
||||
{
|
||||
if (xfs_uuid_table_size == 0)
|
||||
return;
|
||||
kmem_free(xfs_uuid_table);
|
||||
xfs_uuid_table = NULL;
|
||||
xfs_uuid_table_size = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* See if the UUID is unique among mounted XFS filesystems.
|
||||
* Mount fails if UUID is nil or a FS with the same UUID is already mounted.
|
||||
|
@ -313,6 +313,7 @@ typedef struct xfs_perag {
|
||||
int pagb_count; /* pagb slots in use */
|
||||
} xfs_perag_t;
|
||||
|
||||
extern void xfs_uuid_table_free(void);
|
||||
extern int xfs_log_sbcount(xfs_mount_t *);
|
||||
extern __uint64_t xfs_default_resblks(xfs_mount_t *mp);
|
||||
extern int xfs_mountfs(xfs_mount_t *mp);
|
||||
|
@ -1925,6 +1925,7 @@ exit_xfs_fs(void)
|
||||
xfs_mru_cache_uninit();
|
||||
xfs_destroy_workqueues();
|
||||
xfs_destroy_zones();
|
||||
xfs_uuid_table_free();
|
||||
}
|
||||
|
||||
module_init(init_xfs_fs);
|
||||
|
@ -497,6 +497,7 @@ xfsaild(
|
||||
long tout = 0; /* milliseconds */
|
||||
|
||||
current->flags |= PF_MEMALLOC;
|
||||
set_freezable();
|
||||
|
||||
while (!kthread_should_stop()) {
|
||||
if (tout && tout <= 20)
|
||||
|
@ -107,6 +107,15 @@ xfs_trans_log_inode(
|
||||
ASSERT(ip->i_itemp != NULL);
|
||||
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
|
||||
|
||||
/*
|
||||
* Record the specific change for fdatasync optimisation. This
|
||||
* allows fdatasync to skip log forces for inodes that are only
|
||||
* timestamp dirty. We do this before the change count so that
|
||||
* the core being logged in this case does not impact on fdatasync
|
||||
* behaviour.
|
||||
*/
|
||||
ip->i_itemp->ili_fsync_fields |= flags;
|
||||
|
||||
/*
|
||||
* First time we log the inode in a transaction, bump the inode change
|
||||
* counter if it is configured for this to occur. We don't use
|
||||
|
@ -53,11 +53,34 @@ xfs_xattr_get(struct dentry *dentry, const char *name,
|
||||
return asize;
|
||||
}
|
||||
|
||||
void
|
||||
xfs_forget_acl(
|
||||
struct inode *inode,
|
||||
const char *name,
|
||||
int xflags)
|
||||
{
|
||||
/*
|
||||
* Invalidate any cached ACLs if the user has bypassed the ACL
|
||||
* interface. We don't validate the content whatsoever so it is caller
|
||||
* responsibility to provide data in valid format and ensure i_mode is
|
||||
* consistent.
|
||||
*/
|
||||
if (xflags & ATTR_ROOT) {
|
||||
#ifdef CONFIG_XFS_POSIX_ACL
|
||||
if (!strcmp(name, SGI_ACL_FILE))
|
||||
forget_cached_acl(inode, ACL_TYPE_ACCESS);
|
||||
else if (!strcmp(name, SGI_ACL_DEFAULT))
|
||||
forget_cached_acl(inode, ACL_TYPE_DEFAULT);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
xfs_xattr_set(struct dentry *dentry, const char *name, const void *value,
|
||||
size_t size, int flags, int xflags)
|
||||
{
|
||||
struct xfs_inode *ip = XFS_I(d_inode(dentry));
|
||||
struct xfs_inode *ip = XFS_I(d_inode(dentry));
|
||||
int error;
|
||||
|
||||
if (strcmp(name, "") == 0)
|
||||
return -EINVAL;
|
||||
@ -70,8 +93,12 @@ xfs_xattr_set(struct dentry *dentry, const char *name, const void *value,
|
||||
|
||||
if (!value)
|
||||
return xfs_attr_remove(ip, (unsigned char *)name, xflags);
|
||||
return xfs_attr_set(ip, (unsigned char *)name,
|
||||
error = xfs_attr_set(ip, (unsigned char *)name,
|
||||
(void *)value, size, xflags);
|
||||
if (!error)
|
||||
xfs_forget_acl(d_inode(dentry), name, xflags);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static const struct xattr_handler xfs_xattr_user_handler = {
|
||||
|
Loading…
Reference in New Issue
Block a user