aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Chinner <david@fromorbit.com>2015-11-02 21:27:58 -0500
committerDave Chinner <david@fromorbit.com>2015-11-02 21:27:58 -0500
commit2da5c4b05ab55225f5d1fcc8c1c37d1918232bf4 (patch)
treef19bd87d6e66c251566be226fdf40c24c168e04a
parentfcd8a399a9d44a637b5ded0eeea14c7933132121 (diff)
parentfc0561cefc04e7803c0f6501ca4f310a502f65b8 (diff)
Merge branch 'xfs-misc-fixes-for-4.4-2' into for-next
-rw-r--r--fs/xfs/libxfs/xfs_format.h8
-rw-r--r--fs/xfs/xfs_acl.c13
-rw-r--r--fs/xfs/xfs_acl.h3
-rw-r--r--fs/xfs/xfs_file.c21
-rw-r--r--fs/xfs/xfs_inode.c2
-rw-r--r--fs/xfs/xfs_inode_item.c1
-rw-r--r--fs/xfs/xfs_inode_item.h1
-rw-r--r--fs/xfs/xfs_ioctl.c15
-rw-r--r--fs/xfs/xfs_mount.c10
-rw-r--r--fs/xfs/xfs_mount.h1
-rw-r--r--fs/xfs/xfs_super.c1
-rw-r--r--fs/xfs/xfs_trans_ail.c1
-rw-r--r--fs/xfs/xfs_trans_inode.c9
-rw-r--r--fs/xfs/xfs_xattr.c31
14 files changed, 101 insertions, 16 deletions
diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
index 8568de163004..8774498ce0ff 100644
--- a/fs/xfs/libxfs/xfs_format.h
+++ b/fs/xfs/libxfs/xfs_format.h
@@ -1495,9 +1495,13 @@ struct xfs_acl {
1495 sizeof(struct xfs_acl_entry) \ 1495 sizeof(struct xfs_acl_entry) \
1496 : 25) 1496 : 25)
1497 1497
1498#define XFS_ACL_MAX_SIZE(mp) \ 1498#define XFS_ACL_SIZE(cnt) \
1499 (sizeof(struct xfs_acl) + \ 1499 (sizeof(struct xfs_acl) + \
1500 sizeof(struct xfs_acl_entry) * XFS_ACL_MAX_ENTRIES((mp))) 1500 sizeof(struct xfs_acl_entry) * cnt)
1501
1502#define XFS_ACL_MAX_SIZE(mp) \
1503 XFS_ACL_SIZE(XFS_ACL_MAX_ENTRIES((mp)))
1504
1501 1505
1502/* On-disk XFS extended attribute names */ 1506/* On-disk XFS extended attribute names */
1503#define SGI_ACL_FILE "SGI_ACL_FILE" 1507#define SGI_ACL_FILE "SGI_ACL_FILE"
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
index 4b641676f258..763e36560681 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -37,16 +37,19 @@
37 37
38STATIC struct posix_acl * 38STATIC struct posix_acl *
39xfs_acl_from_disk( 39xfs_acl_from_disk(
40 struct xfs_acl *aclp, 40 const struct xfs_acl *aclp,
41 int max_entries) 41 int len,
42 int max_entries)
42{ 43{
43 struct posix_acl_entry *acl_e; 44 struct posix_acl_entry *acl_e;
44 struct posix_acl *acl; 45 struct posix_acl *acl;
45 struct xfs_acl_entry *ace; 46 const struct xfs_acl_entry *ace;
46 unsigned int count, i; 47 unsigned int count, i;
47 48
49 if (len < sizeof(*aclp))
50 return ERR_PTR(-EFSCORRUPTED);
48 count = be32_to_cpu(aclp->acl_cnt); 51 count = be32_to_cpu(aclp->acl_cnt);
49 if (count > max_entries) 52 if (count > max_entries || XFS_ACL_SIZE(count) != len)
50 return ERR_PTR(-EFSCORRUPTED); 53 return ERR_PTR(-EFSCORRUPTED);
51 54
52 acl = posix_acl_alloc(count, GFP_KERNEL); 55 acl = posix_acl_alloc(count, GFP_KERNEL);
@@ -163,7 +166,7 @@ xfs_get_acl(struct inode *inode, int type)
163 goto out; 166 goto out;
164 } 167 }
165 168
166 acl = xfs_acl_from_disk(xfs_acl, XFS_ACL_MAX_ENTRIES(ip->i_mount)); 169 acl = xfs_acl_from_disk(xfs_acl, len, XFS_ACL_MAX_ENTRIES(ip->i_mount));
167 if (IS_ERR(acl)) 170 if (IS_ERR(acl))
168 goto out; 171 goto out;
169 172
diff --git a/fs/xfs/xfs_acl.h b/fs/xfs/xfs_acl.h
index 3841b07f27bf..75af0a4d9028 100644
--- a/fs/xfs/xfs_acl.h
+++ b/fs/xfs/xfs_acl.h
@@ -36,4 +36,7 @@ static inline struct posix_acl *xfs_get_acl(struct inode *inode, int type)
36# define posix_acl_access_exists(inode) 0 36# define posix_acl_access_exists(inode) 0
37# define posix_acl_default_exists(inode) 0 37# define posix_acl_default_exists(inode) 0
38#endif /* CONFIG_XFS_POSIX_ACL */ 38#endif /* CONFIG_XFS_POSIX_ACL */
39
40extern void xfs_forget_acl(struct inode *inode, const char *name, int xflags);
41
39#endif /* __XFS_ACL_H__ */ 42#endif /* __XFS_ACL_H__ */
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 2f7b6bd39f61..a3bf4c099dd2 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -242,19 +242,30 @@ xfs_file_fsync(
242 } 242 }
243 243
244 /* 244 /*
245 * All metadata updates are logged, which means that we just have 245 * All metadata updates are logged, which means that we just have to
246 * to flush the log up to the latest LSN that touched the inode. 246 * flush the log up to the latest LSN that touched the inode. If we have
247 * concurrent fsync/fdatasync() calls, we need them to all block on the
248 * log force before we clear the ili_fsync_fields field. This ensures
249 * that we don't get a racing sync operation that does not wait for the
250 * metadata to hit the journal before returning. If we race with
251 * clearing the ili_fsync_fields, then all that will happen is the log
252 * force will do nothing as the lsn will already be on disk. We can't
253 * race with setting ili_fsync_fields because that is done under
254 * XFS_ILOCK_EXCL, and that can't happen because we hold the lock shared
255 * until after the ili_fsync_fields is cleared.
247 */ 256 */
248 xfs_ilock(ip, XFS_ILOCK_SHARED); 257 xfs_ilock(ip, XFS_ILOCK_SHARED);
249 if (xfs_ipincount(ip)) { 258 if (xfs_ipincount(ip)) {
250 if (!datasync || 259 if (!datasync ||
251 (ip->i_itemp->ili_fields & ~XFS_ILOG_TIMESTAMP)) 260 (ip->i_itemp->ili_fsync_fields & ~XFS_ILOG_TIMESTAMP))
252 lsn = ip->i_itemp->ili_last_lsn; 261 lsn = ip->i_itemp->ili_last_lsn;
253 } 262 }
254 xfs_iunlock(ip, XFS_ILOCK_SHARED);
255 263
256 if (lsn) 264 if (lsn) {
257 error = _xfs_log_force_lsn(mp, lsn, XFS_LOG_SYNC, &log_flushed); 265 error = _xfs_log_force_lsn(mp, lsn, XFS_LOG_SYNC, &log_flushed);
266 ip->i_itemp->ili_fsync_fields = 0;
267 }
268 xfs_iunlock(ip, XFS_ILOCK_SHARED);
258 269
259 /* 270 /*
260 * If we only have a single device, and the log force about was 271 * If we only have a single device, and the log force about was
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index a0f2bae6dc1e..8ee393996b7d 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -2365,6 +2365,7 @@ retry:
2365 2365
2366 iip->ili_last_fields = iip->ili_fields; 2366 iip->ili_last_fields = iip->ili_fields;
2367 iip->ili_fields = 0; 2367 iip->ili_fields = 0;
2368 iip->ili_fsync_fields = 0;
2368 iip->ili_logged = 1; 2369 iip->ili_logged = 1;
2369 xfs_trans_ail_copy_lsn(mp->m_ail, &iip->ili_flush_lsn, 2370 xfs_trans_ail_copy_lsn(mp->m_ail, &iip->ili_flush_lsn,
2370 &iip->ili_item.li_lsn); 2371 &iip->ili_item.li_lsn);
@@ -3560,6 +3561,7 @@ xfs_iflush_int(
3560 */ 3561 */
3561 iip->ili_last_fields = iip->ili_fields; 3562 iip->ili_last_fields = iip->ili_fields;
3562 iip->ili_fields = 0; 3563 iip->ili_fields = 0;
3564 iip->ili_fsync_fields = 0;
3563 iip->ili_logged = 1; 3565 iip->ili_logged = 1;
3564 3566
3565 xfs_trans_ail_copy_lsn(mp->m_ail, &iip->ili_flush_lsn, 3567 xfs_trans_ail_copy_lsn(mp->m_ail, &iip->ili_flush_lsn,
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index 62bd80f4edd9..d14b12b8cfef 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -719,6 +719,7 @@ xfs_iflush_abort(
719 * attempted. 719 * attempted.
720 */ 720 */
721 iip->ili_fields = 0; 721 iip->ili_fields = 0;
722 iip->ili_fsync_fields = 0;
722 } 723 }
723 /* 724 /*
724 * Release the inode's flush lock since we're done with it. 725 * Release the inode's flush lock since we're done with it.
diff --git a/fs/xfs/xfs_inode_item.h b/fs/xfs/xfs_inode_item.h
index 488d81254e28..4c7722e325b3 100644
--- a/fs/xfs/xfs_inode_item.h
+++ b/fs/xfs/xfs_inode_item.h
@@ -34,6 +34,7 @@ typedef struct xfs_inode_log_item {
34 unsigned short ili_logged; /* flushed logged data */ 34 unsigned short ili_logged; /* flushed logged data */
35 unsigned int ili_last_fields; /* fields when flushed */ 35 unsigned int ili_last_fields; /* fields when flushed */
36 unsigned int ili_fields; /* fields to be logged */ 36 unsigned int ili_fields; /* fields to be logged */
37 unsigned int ili_fsync_fields; /* logged since last fsync */
37} xfs_inode_log_item_t; 38} xfs_inode_log_item_t;
38 39
39static inline int xfs_inode_clean(xfs_inode_t *ip) 40static inline int xfs_inode_clean(xfs_inode_t *ip)
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index c88ddcadd656..d42738deec6d 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -40,6 +40,7 @@
40#include "xfs_symlink.h" 40#include "xfs_symlink.h"
41#include "xfs_trans.h" 41#include "xfs_trans.h"
42#include "xfs_pnfs.h" 42#include "xfs_pnfs.h"
43#include "xfs_acl.h"
43 44
44#include <linux/capability.h> 45#include <linux/capability.h>
45#include <linux/dcache.h> 46#include <linux/dcache.h>
@@ -482,6 +483,7 @@ xfs_attrmulti_attr_set(
482 __uint32_t flags) 483 __uint32_t flags)
483{ 484{
484 unsigned char *kbuf; 485 unsigned char *kbuf;
486 int error;
485 487
486 if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) 488 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
487 return -EPERM; 489 return -EPERM;
@@ -492,7 +494,11 @@ xfs_attrmulti_attr_set(
492 if (IS_ERR(kbuf)) 494 if (IS_ERR(kbuf))
493 return PTR_ERR(kbuf); 495 return PTR_ERR(kbuf);
494 496
495 return xfs_attr_set(XFS_I(inode), name, kbuf, len, flags); 497 error = xfs_attr_set(XFS_I(inode), name, kbuf, len, flags);
498 if (!error)
499 xfs_forget_acl(inode, name, flags);
500 kfree(kbuf);
501 return error;
496} 502}
497 503
498int 504int
@@ -501,9 +507,14 @@ xfs_attrmulti_attr_remove(
501 unsigned char *name, 507 unsigned char *name,
502 __uint32_t flags) 508 __uint32_t flags)
503{ 509{
510 int error;
511
504 if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) 512 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
505 return -EPERM; 513 return -EPERM;
506 return xfs_attr_remove(XFS_I(inode), name, flags); 514 error = xfs_attr_remove(XFS_I(inode), name, flags);
515 if (!error)
516 xfs_forget_acl(inode, name, flags);
517 return error;
507} 518}
508 519
509STATIC int 520STATIC int
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index eb498ce39f4c..bb753b359bee 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -47,6 +47,16 @@ static DEFINE_MUTEX(xfs_uuid_table_mutex);
47static int xfs_uuid_table_size; 47static int xfs_uuid_table_size;
48static uuid_t *xfs_uuid_table; 48static uuid_t *xfs_uuid_table;
49 49
50void
51xfs_uuid_table_free(void)
52{
53 if (xfs_uuid_table_size == 0)
54 return;
55 kmem_free(xfs_uuid_table);
56 xfs_uuid_table = NULL;
57 xfs_uuid_table_size = 0;
58}
59
50/* 60/*
51 * See if the UUID is unique among mounted XFS filesystems. 61 * See if the UUID is unique among mounted XFS filesystems.
52 * Mount fails if UUID is nil or a FS with the same UUID is already mounted. 62 * Mount fails if UUID is nil or a FS with the same UUID is already mounted.
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 8795272cb662..6db5fc041d4f 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -313,6 +313,7 @@ typedef struct xfs_perag {
313 int pagb_count; /* pagb slots in use */ 313 int pagb_count; /* pagb slots in use */
314} xfs_perag_t; 314} xfs_perag_t;
315 315
316extern void xfs_uuid_table_free(void);
316extern int xfs_log_sbcount(xfs_mount_t *); 317extern int xfs_log_sbcount(xfs_mount_t *);
317extern __uint64_t xfs_default_resblks(xfs_mount_t *mp); 318extern __uint64_t xfs_default_resblks(xfs_mount_t *mp);
318extern int xfs_mountfs(xfs_mount_t *mp); 319extern int xfs_mountfs(xfs_mount_t *mp);
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index b2c252cd7172..0378e22eeae1 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -1925,6 +1925,7 @@ exit_xfs_fs(void)
1925 xfs_mru_cache_uninit(); 1925 xfs_mru_cache_uninit();
1926 xfs_destroy_workqueues(); 1926 xfs_destroy_workqueues();
1927 xfs_destroy_zones(); 1927 xfs_destroy_zones();
1928 xfs_uuid_table_free();
1928} 1929}
1929 1930
1930module_init(init_xfs_fs); 1931module_init(init_xfs_fs);
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c
index 4f18fd92ca13..aa67339b9537 100644
--- a/fs/xfs/xfs_trans_ail.c
+++ b/fs/xfs/xfs_trans_ail.c
@@ -497,6 +497,7 @@ xfsaild(
497 long tout = 0; /* milliseconds */ 497 long tout = 0; /* milliseconds */
498 498
499 current->flags |= PF_MEMALLOC; 499 current->flags |= PF_MEMALLOC;
500 set_freezable();
500 501
501 while (!kthread_should_stop()) { 502 while (!kthread_should_stop()) {
502 if (tout && tout <= 20) 503 if (tout && tout <= 20)
diff --git a/fs/xfs/xfs_trans_inode.c b/fs/xfs/xfs_trans_inode.c
index 17280cd71934..b97f1df910ab 100644
--- a/fs/xfs/xfs_trans_inode.c
+++ b/fs/xfs/xfs_trans_inode.c
@@ -108,6 +108,15 @@ xfs_trans_log_inode(
108 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); 108 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
109 109
110 /* 110 /*
111 * Record the specific change for fdatasync optimisation. This
112 * allows fdatasync to skip log forces for inodes that are only
113 * timestamp dirty. We do this before the change count so that
114 * the core being logged in this case does not impact on fdatasync
115 * behaviour.
116 */
117 ip->i_itemp->ili_fsync_fields |= flags;
118
119 /*
111 * First time we log the inode in a transaction, bump the inode change 120 * First time we log the inode in a transaction, bump the inode change
112 * counter if it is configured for this to occur. We don't use 121 * counter if it is configured for this to occur. We don't use
113 * inode_inc_version() because there is no need for extra locking around 122 * inode_inc_version() because there is no need for extra locking around
diff --git a/fs/xfs/xfs_xattr.c b/fs/xfs/xfs_xattr.c
index c036815183cb..8294f86441bf 100644
--- a/fs/xfs/xfs_xattr.c
+++ b/fs/xfs/xfs_xattr.c
@@ -53,11 +53,34 @@ xfs_xattr_get(struct dentry *dentry, const char *name,
53 return asize; 53 return asize;
54} 54}
55 55
56void
57xfs_forget_acl(
58 struct inode *inode,
59 const char *name,
60 int xflags)
61{
62 /*
63 * Invalidate any cached ACLs if the user has bypassed the ACL
64 * interface. We don't validate the content whatsoever so it is caller
65 * responsibility to provide data in valid format and ensure i_mode is
66 * consistent.
67 */
68 if (xflags & ATTR_ROOT) {
69#ifdef CONFIG_XFS_POSIX_ACL
70 if (!strcmp(name, SGI_ACL_FILE))
71 forget_cached_acl(inode, ACL_TYPE_ACCESS);
72 else if (!strcmp(name, SGI_ACL_DEFAULT))
73 forget_cached_acl(inode, ACL_TYPE_DEFAULT);
74#endif
75 }
76}
77
56static int 78static int
57xfs_xattr_set(struct dentry *dentry, const char *name, const void *value, 79xfs_xattr_set(struct dentry *dentry, const char *name, const void *value,
58 size_t size, int flags, int xflags) 80 size_t size, int flags, int xflags)
59{ 81{
60 struct xfs_inode *ip = XFS_I(d_inode(dentry)); 82 struct xfs_inode *ip = XFS_I(d_inode(dentry));
83 int error;
61 84
62 if (strcmp(name, "") == 0) 85 if (strcmp(name, "") == 0)
63 return -EINVAL; 86 return -EINVAL;
@@ -70,8 +93,12 @@ xfs_xattr_set(struct dentry *dentry, const char *name, const void *value,
70 93
71 if (!value) 94 if (!value)
72 return xfs_attr_remove(ip, (unsigned char *)name, xflags); 95 return xfs_attr_remove(ip, (unsigned char *)name, xflags);
73 return xfs_attr_set(ip, (unsigned char *)name, 96 error = xfs_attr_set(ip, (unsigned char *)name,
74 (void *)value, size, xflags); 97 (void *)value, size, xflags);
98 if (!error)
99 xfs_forget_acl(d_inode(dentry), name, xflags);
100
101 return error;
75} 102}
76 103
77static const struct xattr_handler xfs_xattr_user_handler = { 104static const struct xattr_handler xfs_xattr_user_handler = {