]> Pileus Git - ~andy/linux/commitdiff
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 28 Jan 2014 16:38:04 +0000 (08:38 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 28 Jan 2014 16:38:04 +0000 (08:38 -0800)
Pull vfs updates from Al Viro:
 "Assorted stuff; the biggest pile here is Christoph's ACL series.  Plus
  assorted cleanups and fixes all over the place...

  There will be another pile later this week"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (43 commits)
  __dentry_path() fixes
  vfs: Remove second variable named error in __dentry_path
  vfs: Is mounted should be testing mnt_ns for NULL or error.
  Fix race when checking i_size on direct i/o read
  hfsplus: remove can_set_xattr
  nfsd: use get_acl and ->set_acl
  fs: remove generic_acl
  nfs: use generic posix ACL infrastructure for v3 Posix ACLs
  gfs2: use generic posix ACL infrastructure
  jfs: use generic posix ACL infrastructure
  xfs: use generic posix ACL infrastructure
  reiserfs: use generic posix ACL infrastructure
  ocfs2: use generic posix ACL infrastructure
  jffs2: use generic posix ACL infrastructure
  hfsplus: use generic posix ACL infrastructure
  f2fs: use generic posix ACL infrastructure
  ext2/3/4: use generic posix ACL infrastructure
  btrfs: use generic posix ACL infrastructure
  fs: make posix_acl_create more useful
  fs: make posix_acl_chmod more useful
  ...

20 files changed:
1  2 
fs/Makefile
fs/btrfs/inode.c
fs/ext4/inode.c
fs/f2fs/f2fs.h
fs/f2fs/file.c
fs/f2fs/namei.c
fs/f2fs/xattr.c
fs/fuse/file.c
fs/gfs2/inode.c
fs/hfsplus/inode.c
fs/ocfs2/file.c
fs/ocfs2/namei.c
fs/posix_acl.c
fs/reiserfs/reiserfs.h
fs/xfs/xfs_iops.c
include/linux/posix_acl.h
include/linux/rcupdate.h
kernel/rcu/update.c
mm/filemap.c
mm/shmem.c

diff --combined fs/Makefile
index 39a824f44e7c17c807988ca970a2eefbe2113ece,5bebad4b01c622bc41038ac64bdb1cbd5b865c30..47ac07bb4acc6b44b318776c44e7a6cd7bf79113
@@@ -42,9 -42,8 +42,8 @@@ obj-$(CONFIG_BINFMT_SOM)      += binfmt_som.
  obj-$(CONFIG_BINFMT_FLAT)     += binfmt_flat.o
  
  obj-$(CONFIG_FS_MBCACHE)      += mbcache.o
- obj-$(CONFIG_FS_POSIX_ACL)    += posix_acl.o xattr_acl.o
+ obj-$(CONFIG_FS_POSIX_ACL)    += posix_acl.o
  obj-$(CONFIG_NFS_COMMON)      += nfs_common/
- obj-$(CONFIG_GENERIC_ACL)     += generic_acl.o
  obj-$(CONFIG_COREDUMP)                += coredump.o
  obj-$(CONFIG_SYSCTL)          += drop_caches.o
  
@@@ -53,7 -52,7 +52,7 @@@ obj-$(CONFIG_FHANDLE)         += fhandle.
  obj-y                         += quota/
  
  obj-$(CONFIG_PROC_FS)         += proc/
 -obj-$(CONFIG_SYSFS)           += sysfs/
 +obj-$(CONFIG_SYSFS)           += sysfs/ kernfs/
  obj-$(CONFIG_CONFIGFS_FS)     += configfs/
  obj-y                         += devpts/
  
diff --combined fs/btrfs/inode.c
index 471a4f7f4044d4171f823e996ff89b68d237abb0,b1314300d9fcfd3f2c563ad91182d3584305c664..514b291b135405dd1fbd21f9a8e4edc1b161f5af
@@@ -4354,12 -4354,8 +4354,12 @@@ static int btrfs_setsize(struct inode *
         * these flags set.  For all other operations the VFS set these flags
         * explicitly if it wants a timestamp update.
         */
 -      if (newsize != oldsize && (!(mask & (ATTR_CTIME | ATTR_MTIME))))
 -              inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb);
 +      if (newsize != oldsize) {
 +              inode_inc_iversion(inode);
 +              if (!(mask & (ATTR_CTIME | ATTR_MTIME)))
 +                      inode->i_ctime = inode->i_mtime =
 +                              current_fs_time(inode->i_sb);
 +      }
  
        if (newsize > oldsize) {
                truncate_pagecache(inode, newsize);
@@@ -4468,7 -4464,7 +4468,7 @@@ static int btrfs_setattr(struct dentry 
                err = btrfs_dirty_inode(inode);
  
                if (!err && attr->ia_valid & ATTR_MODE)
-                       err = btrfs_acl_chmod(inode);
+                       err = posix_acl_chmod(inode, inode->i_mode);
        }
  
        return err;
@@@ -8653,12 -8649,14 +8653,14 @@@ static const struct inode_operations bt
        .removexattr    = btrfs_removexattr,
        .permission     = btrfs_permission,
        .get_acl        = btrfs_get_acl,
+       .set_acl        = btrfs_set_acl,
        .update_time    = btrfs_update_time,
  };
  static const struct inode_operations btrfs_dir_ro_inode_operations = {
        .lookup         = btrfs_lookup,
        .permission     = btrfs_permission,
        .get_acl        = btrfs_get_acl,
+       .set_acl        = btrfs_set_acl,
        .update_time    = btrfs_update_time,
  };
  
@@@ -8728,6 -8726,7 +8730,7 @@@ static const struct inode_operations bt
        .permission     = btrfs_permission,
        .fiemap         = btrfs_fiemap,
        .get_acl        = btrfs_get_acl,
+       .set_acl        = btrfs_set_acl,
        .update_time    = btrfs_update_time,
  };
  static const struct inode_operations btrfs_special_inode_operations = {
        .listxattr      = btrfs_listxattr,
        .removexattr    = btrfs_removexattr,
        .get_acl        = btrfs_get_acl,
+       .set_acl        = btrfs_set_acl,
        .update_time    = btrfs_update_time,
  };
  static const struct inode_operations btrfs_symlink_inode_operations = {
        .getxattr       = btrfs_getxattr,
        .listxattr      = btrfs_listxattr,
        .removexattr    = btrfs_removexattr,
-       .get_acl        = btrfs_get_acl,
        .update_time    = btrfs_update_time,
  };
  
diff --combined fs/ext4/inode.c
index 31fa964742bcba1b0f9dbd494e469feb56ee8428,23983c2cf95971a07ac58e4926906af36b602d1b..fe4793e754d11b2963740751be9864d0b45fbd2e
@@@ -4586,10 -4586,6 +4586,10 @@@ int ext4_setattr(struct dentry *dentry
                        if (attr->ia_size > sbi->s_bitmap_maxbytes)
                                return -EFBIG;
                }
 +
 +              if (IS_I_VERSION(inode) && attr->ia_size != inode->i_size)
 +                      inode_inc_iversion(inode);
 +
                if (S_ISREG(inode->i_mode) &&
                    (attr->ia_size < inode->i_size)) {
                        if (ext4_should_order_data(inode)) {
                ext4_orphan_del(NULL, inode);
  
        if (!rc && (ia_valid & ATTR_MODE))
-               rc = ext4_acl_chmod(inode);
+               rc = posix_acl_chmod(inode, inode->i_mode);
  
  err_out:
        ext4_std_error(inode->i_sb, error);
diff --combined fs/f2fs/f2fs.h
index af51a0bd2dee4c267e715d8d39c38b917b115743,934b59cf819e5d3001d66642e70cc8f7a4acaa9c..fc3c558cb4f3d5a71b8ed03016e838cf5ec84cdf
  
  #ifdef CONFIG_F2FS_CHECK_FS
  #define f2fs_bug_on(condition)        BUG_ON(condition)
 +#define f2fs_down_write(x, y) down_write_nest_lock(x, y)
  #else
  #define f2fs_bug_on(condition)
 +#define f2fs_down_write(x, y) down_write(x)
  #endif
  
  /*
@@@ -39,7 -37,6 +39,7 @@@
  #define F2FS_MOUNT_POSIX_ACL          0x00000020
  #define F2FS_MOUNT_DISABLE_EXT_IDENTIFY       0x00000040
  #define F2FS_MOUNT_INLINE_XATTR               0x00000080
 +#define F2FS_MOUNT_INLINE_DATA                0x00000100
  
  #define clear_opt(sbi, option)        (sbi->mount_opt.opt &= ~F2FS_MOUNT_##option)
  #define set_opt(sbi, option)  (sbi->mount_opt.opt |= F2FS_MOUNT_##option)
@@@ -100,13 -97,6 +100,13 @@@ struct dir_inode_entry 
        struct inode *inode;    /* vfs inode pointer */
  };
  
 +/* for the list of blockaddresses to be discarded */
 +struct discard_entry {
 +      struct list_head list;  /* list head */
 +      block_t blkaddr;        /* block address to be discarded */
 +      int len;                /* # of consecutive blocks of the discard */
 +};
 +
  /* for the list of fsync inodes, used only during recovery */
  struct fsync_inode_entry {
        struct list_head list;  /* list head */
@@@ -165,15 -155,13 +165,15 @@@ enum 
        LOOKUP_NODE,                    /* look up a node without readahead */
        LOOKUP_NODE_RA,                 /*
                                         * look up a node with readahead called
 -                                       * by get_datablock_ro.
 +                                       * by get_data_block.
                                         */
  };
  
  #define F2FS_LINK_MAX         32000   /* maximum link count per file */
  
  /* for in-memory extent cache entry */
 +#define F2FS_MIN_EXTENT_LEN   16      /* minimum extent length */
 +
  struct extent_info {
        rwlock_t ext_lock;      /* rwlock for consistency */
        unsigned int fofs;      /* start offset in a file */
@@@ -320,14 -308,6 +320,14 @@@ struct f2fs_sm_info 
  
        /* a threshold to reclaim prefree segments */
        unsigned int rec_prefree_segments;
 +
 +      /* for small discard management */
 +      struct list_head discard_list;          /* 4KB discard list */
 +      int nr_discards;                        /* # of discards in the list */
 +      int max_discards;                       /* max. discards to be issued */
 +
 +      unsigned int ipu_policy;        /* in-place-update policy */
 +      unsigned int min_ipu_util;      /* in-place-update threshold */
  };
  
  /*
@@@ -358,7 -338,6 +358,7 @@@ enum count_type 
   *                    with waiting the bio's completion
   * ...                        Only can be used with META.
   */
 +#define PAGE_TYPE_OF_BIO(type)        ((type) > META ? META : (type))
  enum page_type {
        DATA,
        NODE,
        META_FLUSH,
  };
  
 +struct f2fs_io_info {
 +      enum page_type type;    /* contains DATA/NODE/META/META_FLUSH */
 +      int rw;                 /* contains R/RS/W/WS with REQ_META/REQ_PRIO */
 +};
 +
 +#define is_read_io(rw)        (((rw) & 1) == READ)
 +struct f2fs_bio_info {
 +      struct f2fs_sb_info *sbi;       /* f2fs superblock */
 +      struct bio *bio;                /* bios to merge */
 +      sector_t last_block_in_bio;     /* last block number */
 +      struct f2fs_io_info fio;        /* store buffered io info. */
 +      struct mutex io_mutex;          /* mutex for bio */
 +};
 +
  struct f2fs_sb_info {
        struct super_block *sb;                 /* pointer to VFS super block */
        struct proc_dir_entry *s_proc;          /* proc entry */
  
        /* for segment-related operations */
        struct f2fs_sm_info *sm_info;           /* segment manager */
 -      struct bio *bio[NR_PAGE_TYPE];          /* bios to merge */
 -      sector_t last_block_in_bio[NR_PAGE_TYPE];       /* last block number */
 -      struct rw_semaphore bio_sem;            /* IO semaphore */
 +
 +      /* for bio operations */
 +      struct f2fs_bio_info read_io;                   /* for read bios */
 +      struct f2fs_bio_info write_io[NR_PAGE_TYPE];    /* for write bios */
  
        /* for checkpoint */
        struct f2fs_checkpoint *ckpt;           /* raw checkpoint pointer */
  
        /* for orphan inode management */
        struct list_head orphan_inode_list;     /* orphan inode list */
 -      struct mutex orphan_inode_mutex;        /* for orphan inode list */
 +      spinlock_t orphan_inode_lock;           /* for orphan inode list */
        unsigned int n_orphans;                 /* # of orphan inodes */
 +      unsigned int max_orphans;               /* max orphan inodes */
  
        /* for directory inode management */
        struct list_head dir_inode_list;        /* dir inode list */
        struct f2fs_gc_kthread  *gc_thread;     /* GC thread */
        unsigned int cur_victim_sec;            /* current victim section num */
  
 +      /* maximum # of trials to find a victim segment for SSR and GC */
 +      unsigned int max_victim_search;
 +
        /*
         * for stat information.
         * one is for the LFS mode, and the other is for the SSR mode.
        unsigned int segment_count[2];          /* # of allocated segments */
        unsigned int block_count[2];            /* # of allocated blocks */
        int total_hit_ext, read_hit_ext;        /* extent cache hit ratio */
 +      int inline_inode;                       /* # of inline_data inodes */
        int bg_gc;                              /* background gc calls */
        unsigned int n_dirty_dirs;              /* # of dir inodes */
  #endif
@@@ -503,11 -462,6 +503,11 @@@ static inline struct f2fs_node *F2FS_NO
        return (struct f2fs_node *)page_address(page);
  }
  
 +static inline struct f2fs_inode *F2FS_INODE(struct page *page)
 +{
 +      return &((struct f2fs_node *)page_address(page))->i;
 +}
 +
  static inline struct f2fs_nm_info *NM_I(struct f2fs_sb_info *sbi)
  {
        return (struct f2fs_nm_info *)(sbi->nm_info);
@@@ -533,16 -487,6 +533,16 @@@ static inline struct dirty_seglist_inf
        return (struct dirty_seglist_info *)(SM_I(sbi)->dirty_info);
  }
  
 +static inline struct address_space *META_MAPPING(struct f2fs_sb_info *sbi)
 +{
 +      return sbi->meta_inode->i_mapping;
 +}
 +
 +static inline struct address_space *NODE_MAPPING(struct f2fs_sb_info *sbi)
 +{
 +      return sbi->node_inode->i_mapping;
 +}
 +
  static inline void F2FS_SET_SB_DIRT(struct f2fs_sb_info *sbi)
  {
        sbi->s_dirty = 1;
@@@ -590,7 -534,7 +590,7 @@@ static inline void f2fs_unlock_op(struc
  
  static inline void f2fs_lock_all(struct f2fs_sb_info *sbi)
  {
 -      down_write_nest_lock(&sbi->cp_rwsem, &sbi->cp_mutex);
 +      f2fs_down_write(&sbi->cp_rwsem, &sbi->cp_mutex);
  }
  
  static inline void f2fs_unlock_all(struct f2fs_sb_info *sbi)
  static inline int check_nid_range(struct f2fs_sb_info *sbi, nid_t nid)
  {
        WARN_ON((nid >= NM_I(sbi)->max_nid));
 -      if (nid >= NM_I(sbi)->max_nid)
 +      if (unlikely(nid >= NM_I(sbi)->max_nid))
                return -EINVAL;
        return 0;
  }
  static inline int F2FS_HAS_BLOCKS(struct inode *inode)
  {
        if (F2FS_I(inode)->i_xattr_nid)
 -              return (inode->i_blocks > F2FS_DEFAULT_ALLOCATED_BLOCKS + 1);
 +              return inode->i_blocks > F2FS_DEFAULT_ALLOCATED_BLOCKS + 1;
        else
 -              return (inode->i_blocks > F2FS_DEFAULT_ALLOCATED_BLOCKS);
 +              return inode->i_blocks > F2FS_DEFAULT_ALLOCATED_BLOCKS;
  }
  
  static inline bool inc_valid_block_count(struct f2fs_sb_info *sbi,
        spin_lock(&sbi->stat_lock);
        valid_block_count =
                sbi->total_valid_block_count + (block_t)count;
 -      if (valid_block_count > sbi->user_block_count) {
 +      if (unlikely(valid_block_count > sbi->user_block_count)) {
                spin_unlock(&sbi->stat_lock);
                return false;
        }
        return true;
  }
  
 -static inline int dec_valid_block_count(struct f2fs_sb_info *sbi,
 +static inline void dec_valid_block_count(struct f2fs_sb_info *sbi,
                                                struct inode *inode,
                                                blkcnt_t count)
  {
        inode->i_blocks -= count;
        sbi->total_valid_block_count -= (block_t)count;
        spin_unlock(&sbi->stat_lock);
 -      return 0;
  }
  
  static inline void inc_page_count(struct f2fs_sb_info *sbi, int count_type)
@@@ -741,48 -686,50 +741,48 @@@ static inline block_t __start_sum_addr(
  }
  
  static inline bool inc_valid_node_count(struct f2fs_sb_info *sbi,
 -                                              struct inode *inode,
 -                                              unsigned int count)
 +                                              struct inode *inode)
  {
        block_t valid_block_count;
        unsigned int valid_node_count;
  
        spin_lock(&sbi->stat_lock);
  
 -      valid_block_count = sbi->total_valid_block_count + (block_t)count;
 -      sbi->alloc_valid_block_count += (block_t)count;
 -      valid_node_count = sbi->total_valid_node_count + count;
 -
 -      if (valid_block_count > sbi->user_block_count) {
 +      valid_block_count = sbi->total_valid_block_count + 1;
 +      if (unlikely(valid_block_count > sbi->user_block_count)) {
                spin_unlock(&sbi->stat_lock);
                return false;
        }
  
 -      if (valid_node_count > sbi->total_node_count) {
 +      valid_node_count = sbi->total_valid_node_count + 1;
 +      if (unlikely(valid_node_count > sbi->total_node_count)) {
                spin_unlock(&sbi->stat_lock);
                return false;
        }
  
        if (inode)
 -              inode->i_blocks += count;
 -      sbi->total_valid_node_count = valid_node_count;
 -      sbi->total_valid_block_count = valid_block_count;
 +              inode->i_blocks++;
 +
 +      sbi->alloc_valid_block_count++;
 +      sbi->total_valid_node_count++;
 +      sbi->total_valid_block_count++;
        spin_unlock(&sbi->stat_lock);
  
        return true;
  }
  
  static inline void dec_valid_node_count(struct f2fs_sb_info *sbi,
 -                                              struct inode *inode,
 -                                              unsigned int count)
 +                                              struct inode *inode)
  {
        spin_lock(&sbi->stat_lock);
  
 -      f2fs_bug_on(sbi->total_valid_block_count < count);
 -      f2fs_bug_on(sbi->total_valid_node_count < count);
 -      f2fs_bug_on(inode->i_blocks < count);
 +      f2fs_bug_on(!sbi->total_valid_block_count);
 +      f2fs_bug_on(!sbi->total_valid_node_count);
 +      f2fs_bug_on(!inode->i_blocks);
  
 -      inode->i_blocks -= count;
 -      sbi->total_valid_node_count -= count;
 -      sbi->total_valid_block_count -= (block_t)count;
 +      inode->i_blocks--;
 +      sbi->total_valid_node_count--;
 +      sbi->total_valid_block_count--;
  
        spin_unlock(&sbi->stat_lock);
  }
@@@ -804,12 -751,13 +804,12 @@@ static inline void inc_valid_inode_coun
        spin_unlock(&sbi->stat_lock);
  }
  
 -static inline int dec_valid_inode_count(struct f2fs_sb_info *sbi)
 +static inline void dec_valid_inode_count(struct f2fs_sb_info *sbi)
  {
        spin_lock(&sbi->stat_lock);
        f2fs_bug_on(!sbi->total_valid_inode_count);
        sbi->total_valid_inode_count--;
        spin_unlock(&sbi->stat_lock);
 -      return 0;
  }
  
  static inline unsigned int valid_inode_count(struct f2fs_sb_info *sbi)
  
  static inline void f2fs_put_page(struct page *page, int unlock)
  {
 -      if (!page || IS_ERR(page))
 +      if (!page)
                return;
  
        if (unlock) {
@@@ -928,9 -876,7 +928,9 @@@ enum 
        FI_NO_ALLOC,            /* should not allocate any blocks */
        FI_UPDATE_DIR,          /* should update inode block for consistency */
        FI_DELAY_IPUT,          /* used for the recovery */
 +      FI_NO_EXTENT,           /* not to use the extent cache */
        FI_INLINE_XATTR,        /* used for inline xattr */
 +      FI_INLINE_DATA,         /* used for inline data*/
  };
  
  static inline void set_inode_flag(struct f2fs_inode_info *fi, int flag)
@@@ -968,8 -914,6 +968,8 @@@ static inline void get_inline_info(stru
  {
        if (ri->i_inline & F2FS_INLINE_XATTR)
                set_inode_flag(fi, FI_INLINE_XATTR);
 +      if (ri->i_inline & F2FS_INLINE_DATA)
 +              set_inode_flag(fi, FI_INLINE_DATA);
  }
  
  static inline void set_raw_inline(struct f2fs_inode_info *fi,
  
        if (is_inode_flag_set(fi, FI_INLINE_XATTR))
                ri->i_inline |= F2FS_INLINE_XATTR;
 +      if (is_inode_flag_set(fi, FI_INLINE_DATA))
 +              ri->i_inline |= F2FS_INLINE_DATA;
  }
  
  static inline unsigned int addrs_per_inode(struct f2fs_inode_info *fi)
@@@ -1006,29 -948,20 +1006,33 @@@ static inline int inline_xattr_size(str
                return 0;
  }
  
 +static inline int f2fs_has_inline_data(struct inode *inode)
 +{
 +      return is_inode_flag_set(F2FS_I(inode), FI_INLINE_DATA);
 +}
 +
 +static inline void *inline_data_addr(struct page *page)
 +{
 +      struct f2fs_inode *ri;
 +      ri = (struct f2fs_inode *)page_address(page);
 +      return (void *)&(ri->i_addr[1]);
 +}
 +
  static inline int f2fs_readonly(struct super_block *sb)
  {
        return sb->s_flags & MS_RDONLY;
  }
  
+ #define get_inode_mode(i) \
+       ((is_inode_flag_set(F2FS_I(i), FI_ACL_MODE)) ? \
+        (F2FS_I(i)->i_acl_mode) : ((i)->i_mode))
  /*
   * file.c
   */
  int f2fs_sync_file(struct file *, loff_t, loff_t, int);
  void truncate_data_blocks(struct dnode_of_data *);
 +int truncate_blocks(struct inode *, u64);
  void f2fs_truncate(struct inode *);
  int f2fs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
  int f2fs_setattr(struct dentry *, struct iattr *);
@@@ -1098,7 -1031,7 +1102,7 @@@ int get_dnode_of_data(struct dnode_of_d
  int truncate_inode_blocks(struct inode *, pgoff_t);
  int truncate_xattr_node(struct inode *, struct page *);
  int wait_on_node_pages_writeback(struct f2fs_sb_info *, nid_t);
 -int remove_inode_page(struct inode *);
 +void remove_inode_page(struct inode *);
  struct page *new_inode_page(struct inode *, const struct qstr *);
  struct page *new_node_page(struct dnode_of_data *, unsigned int, struct page *);
  void ra_node_page(struct f2fs_sb_info *, nid_t);
@@@ -1130,19 -1063,19 +1134,19 @@@ void clear_prefree_segments(struct f2fs
  int npages_for_summary_flush(struct f2fs_sb_info *);
  void allocate_new_segments(struct f2fs_sb_info *);
  struct page *get_sum_page(struct f2fs_sb_info *, unsigned int);
 -struct bio *f2fs_bio_alloc(struct block_device *, int);
 -void f2fs_submit_bio(struct f2fs_sb_info *, enum page_type, bool);
 -void f2fs_wait_on_page_writeback(struct page *, enum page_type, bool);
  void write_meta_page(struct f2fs_sb_info *, struct page *);
 -void write_node_page(struct f2fs_sb_info *, struct page *, unsigned int,
 -                                      block_t, block_t *);
 -void write_data_page(struct inode *, struct page *, struct dnode_of_data*,
 -                                      block_t, block_t *);
 -void rewrite_data_page(struct f2fs_sb_info *, struct page *, block_t);
 +void write_node_page(struct f2fs_sb_info *, struct page *,
 +              struct f2fs_io_info *, unsigned int, block_t, block_t *);
 +void write_data_page(struct page *, struct dnode_of_data *, block_t *,
 +                                      struct f2fs_io_info *);
 +void rewrite_data_page(struct page *, block_t, struct f2fs_io_info *);
  void recover_data_page(struct f2fs_sb_info *, struct page *,
                                struct f2fs_summary *, block_t, block_t);
  void rewrite_node_page(struct f2fs_sb_info *, struct page *,
                                struct f2fs_summary *, block_t, block_t);
 +void allocate_data_block(struct f2fs_sb_info *, struct page *,
 +              block_t, block_t *, struct f2fs_summary *, int);
 +void f2fs_wait_on_page_writeback(struct page *, enum page_type);
  void write_data_summaries(struct f2fs_sb_info *, block_t);
  void write_node_summaries(struct f2fs_sb_info *, block_t);
  int lookup_journal_in_cursum(struct f2fs_summary_block *,
  void flush_sit_entries(struct f2fs_sb_info *);
  int build_segment_manager(struct f2fs_sb_info *);
  void destroy_segment_manager(struct f2fs_sb_info *);
 +int __init create_segment_manager_caches(void);
 +void destroy_segment_manager_caches(void);
  
  /*
   * checkpoint.c
@@@ -1163,7 -1094,7 +1167,7 @@@ int acquire_orphan_inode(struct f2fs_sb
  void release_orphan_inode(struct f2fs_sb_info *);
  void add_orphan_inode(struct f2fs_sb_info *, nid_t);
  void remove_orphan_inode(struct f2fs_sb_info *, nid_t);
 -int recover_orphan_inodes(struct f2fs_sb_info *);
 +void recover_orphan_inodes(struct f2fs_sb_info *);
  int get_valid_checkpoint(struct f2fs_sb_info *);
  void set_dirty_dir_page(struct inode *, struct page *);
  void add_dirty_dir_inode(struct inode *);
@@@ -1178,17 -1109,13 +1182,17 @@@ void destroy_checkpoint_caches(void)
  /*
   * data.c
   */
 +void f2fs_submit_merged_bio(struct f2fs_sb_info *, enum page_type, int);
 +int f2fs_submit_page_bio(struct f2fs_sb_info *, struct page *, block_t, int);
 +void f2fs_submit_page_mbio(struct f2fs_sb_info *, struct page *, block_t,
 +                                              struct f2fs_io_info *);
  int reserve_new_block(struct dnode_of_data *);
 +int f2fs_reserve_block(struct dnode_of_data *, pgoff_t);
  void update_extent_cache(block_t, struct dnode_of_data *);
  struct page *find_data_page(struct inode *, pgoff_t, bool);
  struct page *get_lock_data_page(struct inode *, pgoff_t);
  struct page *get_new_data_page(struct inode *, struct page *, pgoff_t, bool);
 -int f2fs_readpage(struct f2fs_sb_info *, struct page *, block_t, int);
 -int do_write_data_page(struct page *);
 +int do_write_data_page(struct page *, struct f2fs_io_info *);
  
  /*
   * gc.c
@@@ -1221,7 -1148,7 +1225,7 @@@ struct f2fs_stat_info 
        int ndirty_node, ndirty_dent, ndirty_dirs, ndirty_meta;
        int nats, sits, fnids;
        int total_count, utilization;
 -      int bg_gc;
 +      int bg_gc, inline_inode;
        unsigned int valid_count, valid_node_count, valid_inode_count;
        unsigned int bimodal, avg_vblocks;
        int util_free, util_valid, util_invalid;
  
  static inline struct f2fs_stat_info *F2FS_STAT(struct f2fs_sb_info *sbi)
  {
 -      return (struct f2fs_stat_info*)sbi->stat_info;
 +      return (struct f2fs_stat_info *)sbi->stat_info;
  }
  
  #define stat_inc_call_count(si)               ((si)->call_count++)
  #define stat_dec_dirty_dir(sbi)               ((sbi)->n_dirty_dirs--)
  #define stat_inc_total_hit(sb)                ((F2FS_SB(sb))->total_hit_ext++)
  #define stat_inc_read_hit(sb)         ((F2FS_SB(sb))->read_hit_ext++)
 +#define stat_inc_inline_inode(inode)                                  \
 +      do {                                                            \
 +              if (f2fs_has_inline_data(inode))                        \
 +                      ((F2FS_SB(inode->i_sb))->inline_inode++);       \
 +      } while (0)
 +#define stat_dec_inline_inode(inode)                                  \
 +      do {                                                            \
 +              if (f2fs_has_inline_data(inode))                        \
 +                      ((F2FS_SB(inode->i_sb))->inline_inode--);       \
 +      } while (0)
 +
  #define stat_inc_seg_type(sbi, curseg)                                        \
                ((sbi)->segment_count[(curseg)->alloc_type]++)
  #define stat_inc_block_count(sbi, curseg)                             \
@@@ -1304,8 -1220,6 +1308,8 @@@ void f2fs_destroy_root_stats(void)
  #define stat_dec_dirty_dir(sbi)
  #define stat_inc_total_hit(sb)
  #define stat_inc_read_hit(sb)
 +#define stat_inc_inline_inode(inode)
 +#define stat_dec_inline_inode(inode)
  #define stat_inc_seg_type(sbi, curseg)
  #define stat_inc_block_count(sbi, curseg)
  #define stat_inc_seg_count(si, type)
@@@ -1328,13 -1242,4 +1332,13 @@@ extern const struct address_space_opera
  extern const struct inode_operations f2fs_dir_inode_operations;
  extern const struct inode_operations f2fs_symlink_inode_operations;
  extern const struct inode_operations f2fs_special_inode_operations;
 +
 +/*
 + * inline.c
 + */
 +bool f2fs_may_inline(struct inode *);
 +int f2fs_read_inline_data(struct inode *, struct page *);
 +int f2fs_convert_inline_data(struct inode *, pgoff_t);
 +int f2fs_write_inline_data(struct inode *, struct page *, unsigned int);
 +int recover_inline_data(struct inode *, struct page *);
  #endif
diff --combined fs/f2fs/file.c
index 85e91ca88d5791835d25dffe6fc0932f9640203b,cf835e05f39b8dad9e3ecad4c03161bda42d5d55..0dfcef53a6ed830e442f8c174ea166b0d1b2eabd
@@@ -33,6 -33,7 +33,6 @@@ static int f2fs_vm_page_mkwrite(struct 
        struct page *page = vmf->page;
        struct inode *inode = file_inode(vma->vm_file);
        struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
 -      block_t old_blk_addr;
        struct dnode_of_data dn;
        int err;
  
        /* block allocation */
        f2fs_lock_op(sbi);
        set_new_dnode(&dn, inode, NULL, NULL, 0);
 -      err = get_dnode_of_data(&dn, page->index, ALLOC_NODE);
 -      if (err) {
 -              f2fs_unlock_op(sbi);
 -              goto out;
 -      }
 -
 -      old_blk_addr = dn.data_blkaddr;
 -
 -      if (old_blk_addr == NULL_ADDR) {
 -              err = reserve_new_block(&dn);
 -              if (err) {
 -                      f2fs_put_dnode(&dn);
 -                      f2fs_unlock_op(sbi);
 -                      goto out;
 -              }
 -      }
 -      f2fs_put_dnode(&dn);
 +      err = f2fs_reserve_block(&dn, page->index);
        f2fs_unlock_op(sbi);
 +      if (err)
 +              goto out;
  
        file_update_time(vma->vm_file);
        lock_page(page);
 -      if (page->mapping != inode->i_mapping ||
 +      if (unlikely(page->mapping != inode->i_mapping ||
                        page_offset(page) > i_size_read(inode) ||
 -                      !PageUptodate(page)) {
 +                      !PageUptodate(page))) {
                unlock_page(page);
                err = -EFAULT;
                goto out;
@@@ -115,12 -130,12 +115,12 @@@ int f2fs_sync_file(struct file *file, l
        int ret = 0;
        bool need_cp = false;
        struct writeback_control wbc = {
 -              .sync_mode = WB_SYNC_ALL,
 +              .sync_mode = WB_SYNC_NONE,
                .nr_to_write = LONG_MAX,
                .for_reclaim = 0,
        };
  
 -      if (f2fs_readonly(inode->i_sb))
 +      if (unlikely(f2fs_readonly(inode->i_sb)))
                return 0;
  
        trace_f2fs_sync_file_enter(inode);
@@@ -202,7 -217,7 +202,7 @@@ int truncate_data_blocks_range(struct d
        raw_node = F2FS_NODE(dn->node_page);
        addr = blkaddr_in_node(raw_node) + ofs;
  
 -      for ( ; count > 0; count--, addr++, dn->ofs_in_node++) {
 +      for (; count > 0; count--, addr++, dn->ofs_in_node++) {
                block_t blkaddr = le32_to_cpu(*addr);
                if (blkaddr == NULL_ADDR)
                        continue;
@@@ -241,7 -256,7 +241,7 @@@ static void truncate_partial_data_page(
                return;
  
        lock_page(page);
 -      if (page->mapping != inode->i_mapping) {
 +      if (unlikely(page->mapping != inode->i_mapping)) {
                f2fs_put_page(page, 1);
                return;
        }
        f2fs_put_page(page, 1);
  }
  
 -static int truncate_blocks(struct inode *inode, u64 from)
 +int truncate_blocks(struct inode *inode, u64 from)
  {
        struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
        unsigned int blocksize = inode->i_sb->s_blocksize;
        struct dnode_of_data dn;
        pgoff_t free_from;
 -      int count = 0;
 -      int err;
 +      int count = 0, err = 0;
  
        trace_f2fs_truncate_blocks_enter(inode, from);
  
 +      if (f2fs_has_inline_data(inode))
 +              goto done;
 +
        free_from = (pgoff_t)
                        ((from + blocksize - 1) >> (sbi->log_blocksize));
  
        f2fs_lock_op(sbi);
 +
        set_new_dnode(&dn, inode, NULL, NULL, 0);
        err = get_dnode_of_data(&dn, free_from, LOOKUP_NODE);
        if (err) {
  free_next:
        err = truncate_inode_blocks(inode, free_from);
        f2fs_unlock_op(sbi);
 -
 +done:
        /* lastly zero out the first data page */
        truncate_partial_data_page(inode, from);
  
@@@ -370,10 -382,6 +370,10 @@@ int f2fs_setattr(struct dentry *dentry
  
        if ((attr->ia_valid & ATTR_SIZE) &&
                        attr->ia_size != i_size_read(inode)) {
 +              err = f2fs_convert_inline_data(inode, attr->ia_size);
 +              if (err)
 +                      return err;
 +
                truncate_setsize(inode, attr->ia_size);
                f2fs_truncate(inode);
                f2fs_balance_fs(F2FS_SB(inode->i_sb));
        __setattr_copy(inode, attr);
  
        if (attr->ia_valid & ATTR_MODE) {
-               err = f2fs_acl_chmod(inode);
+               err = posix_acl_chmod(inode, get_inode_mode(inode));
                if (err || is_inode_flag_set(fi, FI_ACL_MODE)) {
                        inode->i_mode = fi->i_acl_mode;
                        clear_inode_flag(fi, FI_ACL_MODE);
@@@ -397,6 -405,7 +397,7 @@@ const struct inode_operations f2fs_file
        .getattr        = f2fs_getattr,
        .setattr        = f2fs_setattr,
        .get_acl        = f2fs_get_acl,
+       .set_acl        = f2fs_set_acl,
  #ifdef CONFIG_F2FS_FS_XATTR
        .setxattr       = generic_setxattr,
        .getxattr       = generic_getxattr,
@@@ -451,16 -460,12 +452,16 @@@ int truncate_hole(struct inode *inode, 
        return 0;
  }
  
 -static int punch_hole(struct inode *inode, loff_t offset, loff_t len, int mode)
 +static int punch_hole(struct inode *inode, loff_t offset, loff_t len)
  {
        pgoff_t pg_start, pg_end;
        loff_t off_start, off_end;
        int ret = 0;
  
 +      ret = f2fs_convert_inline_data(inode, MAX_INLINE_DATA + 1);
 +      if (ret)
 +              return ret;
 +
        pg_start = ((unsigned long long) offset) >> PAGE_CACHE_SHIFT;
        pg_end = ((unsigned long long) offset + len) >> PAGE_CACHE_SHIFT;
  
                }
        }
  
 -      if (!(mode & FALLOC_FL_KEEP_SIZE) &&
 -              i_size_read(inode) <= (offset + len)) {
 -              i_size_write(inode, offset);
 -              mark_inode_dirty(inode);
 -      }
 -
        return ret;
  }
  
@@@ -511,10 -522,6 +512,10 @@@ static int expand_inode_data(struct ino
        if (ret)
                return ret;
  
 +      ret = f2fs_convert_inline_data(inode, offset + len);
 +      if (ret)
 +              return ret;
 +
        pg_start = ((unsigned long long) offset) >> PAGE_CACHE_SHIFT;
        pg_end = ((unsigned long long) offset + len) >> PAGE_CACHE_SHIFT;
  
  
                f2fs_lock_op(sbi);
                set_new_dnode(&dn, inode, NULL, NULL, 0);
 -              ret = get_dnode_of_data(&dn, index, ALLOC_NODE);
 -              if (ret) {
 -                      f2fs_unlock_op(sbi);
 -                      break;
 -              }
 -
 -              if (dn.data_blkaddr == NULL_ADDR) {
 -                      ret = reserve_new_block(&dn);
 -                      if (ret) {
 -                              f2fs_put_dnode(&dn);
 -                              f2fs_unlock_op(sbi);
 -                              break;
 -                      }
 -              }
 -              f2fs_put_dnode(&dn);
 +              ret = f2fs_reserve_block(&dn, index);
                f2fs_unlock_op(sbi);
 +              if (ret)
 +                      break;
  
                if (pg_start == pg_end)
                        new_size = offset + len;
@@@ -560,7 -579,7 +561,7 @@@ static long f2fs_fallocate(struct file 
                return -EOPNOTSUPP;
  
        if (mode & FALLOC_FL_PUNCH_HOLE)
 -              ret = punch_hole(inode, offset, len, mode);
 +              ret = punch_hole(inode, offset, len);
        else
                ret = expand_inode_data(inode, offset, len, mode);
  
diff --combined fs/f2fs/namei.c
index 3d32f2969c5e047f54ffe9aec4b73dc132d9a8ca,5846eeb22ce5c15b576ea2c2f7c7307fac2424f8..397d459e97bf9f1ee2107c1079f02a282a47e5fa
@@@ -424,13 -424,11 +424,13 @@@ static int f2fs_rename(struct inode *ol
                }
  
                f2fs_set_link(new_dir, new_entry, new_page, old_inode);
 +              F2FS_I(old_inode)->i_pino = new_dir->i_ino;
  
                new_inode->i_ctime = CURRENT_TIME;
                if (old_dir_entry)
                        drop_nlink(new_inode);
                drop_nlink(new_inode);
 +              mark_inode_dirty(new_inode);
  
                if (!new_inode->i_nlink)
                        add_orphan_inode(sbi, new_inode->i_ino);
                if (old_dir != new_dir) {
                        f2fs_set_link(old_inode, old_dir_entry,
                                                old_dir_page, new_dir);
 +                      F2FS_I(old_inode)->i_pino = new_dir->i_ino;
 +                      update_inode_page(old_inode);
                } else {
                        kunmap(old_dir_page);
                        f2fs_put_page(old_dir_page, 0);
                }
                drop_nlink(old_dir);
 +              mark_inode_dirty(old_dir);
                update_inode_page(old_dir);
        }
  
@@@ -501,6 -496,7 +501,7 @@@ const struct inode_operations f2fs_dir_
        .getattr        = f2fs_getattr,
        .setattr        = f2fs_setattr,
        .get_acl        = f2fs_get_acl,
+       .set_acl        = f2fs_set_acl,
  #ifdef CONFIG_F2FS_FS_XATTR
        .setxattr       = generic_setxattr,
        .getxattr       = generic_getxattr,
@@@ -527,6 -523,7 +528,7 @@@ const struct inode_operations f2fs_spec
        .getattr        = f2fs_getattr,
        .setattr        = f2fs_setattr,
        .get_acl        = f2fs_get_acl,
+       .set_acl        = f2fs_set_acl,
  #ifdef CONFIG_F2FS_FS_XATTR
        .setxattr       = generic_setxattr,
        .getxattr       = generic_getxattr,
diff --combined fs/f2fs/xattr.c
index b0fb8a27f3da6fe3b810eca732361953aeebc030,e2b929954081303f25356237b7e486cf31913c90..89d0422a91a88fea51ecf5935d31c2920545f8a6
@@@ -21,6 -21,7 +21,7 @@@
  #include <linux/rwsem.h>
  #include <linux/f2fs_fs.h>
  #include <linux/security.h>
+ #include <linux/posix_acl_xattr.h>
  #include "f2fs.h"
  #include "xattr.h"
  
@@@ -216,8 -217,8 +217,8 @@@ const struct xattr_handler f2fs_xattr_s
  static const struct xattr_handler *f2fs_xattr_handler_map[] = {
        [F2FS_XATTR_INDEX_USER] = &f2fs_xattr_user_handler,
  #ifdef CONFIG_F2FS_FS_POSIX_ACL
-       [F2FS_XATTR_INDEX_POSIX_ACL_ACCESS] = &f2fs_xattr_acl_access_handler,
-       [F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT] = &f2fs_xattr_acl_default_handler,
+       [F2FS_XATTR_INDEX_POSIX_ACL_ACCESS] = &posix_acl_access_xattr_handler,
+       [F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT] = &posix_acl_default_xattr_handler,
  #endif
        [F2FS_XATTR_INDEX_TRUSTED] = &f2fs_xattr_trusted_handler,
  #ifdef CONFIG_F2FS_FS_SECURITY
  const struct xattr_handler *f2fs_xattr_handlers[] = {
        &f2fs_xattr_user_handler,
  #ifdef CONFIG_F2FS_FS_POSIX_ACL
-       &f2fs_xattr_acl_access_handler,
-       &f2fs_xattr_acl_default_handler,
+       &posix_acl_access_xattr_handler,
+       &posix_acl_default_xattr_handler,
  #endif
        &f2fs_xattr_trusted_handler,
  #ifdef CONFIG_F2FS_FS_SECURITY
@@@ -522,7 -523,7 +523,7 @@@ static int __f2fs_setxattr(struct inod
                if (found)
                        free = free + ENTRY_SIZE(here);
  
 -              if (free < newsize) {
 +              if (unlikely(free < newsize)) {
                        error = -ENOSPC;
                        goto exit;
                }
diff --combined fs/fuse/file.c
index 74f6ca50050447832b4fbe41d8ee2f2a8bf4fa1f,89fdfd1919af90a87cd8e3e607e13cb507d1f4a3..77bcc303c3aeb9214ba4b13098da14fb8bcbe20b
@@@ -127,15 -127,7 +127,15 @@@ static void fuse_file_put(struct fuse_f
        if (atomic_dec_and_test(&ff->count)) {
                struct fuse_req *req = ff->reserved_req;
  
 -              if (sync) {
 +              if (ff->fc->no_open) {
 +                      /*
 +                       * Drop the release request when client does not
 +                       * implement 'open'
 +                       */
 +                      req->background = 0;
 +                      path_put(&req->misc.release.path);
 +                      fuse_put_request(ff->fc, req);
 +              } else if (sync) {
                        req->background = 0;
                        fuse_request_send(ff->fc, req);
                        path_put(&req->misc.release.path);
  int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file,
                 bool isdir)
  {
 -      struct fuse_open_out outarg;
        struct fuse_file *ff;
 -      int err;
        int opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN;
  
        ff = fuse_file_alloc(fc);
        if (!ff)
                return -ENOMEM;
  
 -      err = fuse_send_open(fc, nodeid, file, opcode, &outarg);
 -      if (err) {
 -              fuse_file_free(ff);
 -              return err;
 +      ff->fh = 0;
 +      ff->open_flags = FOPEN_KEEP_CACHE; /* Default for no-open */
 +      if (!fc->no_open || isdir) {
 +              struct fuse_open_out outarg;
 +              int err;
 +
 +              err = fuse_send_open(fc, nodeid, file, opcode, &outarg);
 +              if (!err) {
 +                      ff->fh = outarg.fh;
 +                      ff->open_flags = outarg.open_flags;
 +
 +              } else if (err != -ENOSYS || isdir) {
 +                      fuse_file_free(ff);
 +                      return err;
 +              } else {
 +                      fc->no_open = 1;
 +              }
        }
  
        if (isdir)
 -              outarg.open_flags &= ~FOPEN_DIRECT_IO;
 +              ff->open_flags &= ~FOPEN_DIRECT_IO;
  
 -      ff->fh = outarg.fh;
        ff->nodeid = nodeid;
 -      ff->open_flags = outarg.open_flags;
        file->private_data = fuse_file_get(ff);
  
        return 0;
@@@ -704,7 -687,7 +704,7 @@@ static int fuse_readpage(struct file *f
                SetPageUptodate(page);
        }
  
 -      fuse_invalidate_attr(inode); /* atime changed */
 +      fuse_invalidate_atime(inode);
   out:
        unlock_page(page);
        return err;
@@@ -733,7 -716,7 +733,7 @@@ static void fuse_readpages_end(struct f
                        fuse_read_update_size(inode, pos,
                                              req->misc.read.attr_ver);
                }
 -              fuse_invalidate_attr(inode); /* atime changed */
 +              fuse_invalidate_atime(inode);
        }
  
        for (i = 0; i < req->num_pages; i++) {
@@@ -2727,6 -2710,9 +2727,9 @@@ fuse_direct_IO(int rw, struct kiocb *io
        inode = file->f_mapping->host;
        i_size = i_size_read(inode);
  
+       if ((rw == READ) && (offset > i_size))
+               return 0;
        /* optimization for short read */
        if (async_dio && rw != WRITE && offset + count > i_size) {
                if (offset >= i_size)
diff --combined fs/gfs2/inode.c
index 890588c7fb33f79208c3f4203eaf88dadeba8772,d573125d1021c31072099a596bd3b33bbd2ac4e7..5c524180c98e85a50e8e4c63ce233f71ff82ea39
@@@ -149,7 -149,7 +149,7 @@@ struct inode *gfs2_inode_lookup(struct 
        ip = GFS2_I(inode);
  
        if (!inode)
 -              return ERR_PTR(-ENOBUFS);
 +              return ERR_PTR(-ENOMEM);
  
        if (inode->i_state & I_NEW) {
                struct gfs2_sbd *sdp = GFS2_SB(inode);
@@@ -469,36 -469,14 +469,36 @@@ static void init_dinode(struct gfs2_ino
        brelse(dibh);
  }
  
 +/**
 + * gfs2_trans_da_blocks - Calculate number of blocks to link inode
 + * @dip: The directory we are linking into
 + * @da: The dir add information
 + * @nr_inodes: The number of inodes involved
 + *
 + * This calculate the number of blocks we need to reserve in a
 + * transaction to link @nr_inodes into a directory. In most cases
 + * @nr_inodes will be 2 (the directory plus the inode being linked in)
 + * but in case of rename, 4 may be required.
 + *
 + * Returns: Number of blocks
 + */
 +
 +static unsigned gfs2_trans_da_blks(const struct gfs2_inode *dip,
 +                                 const struct gfs2_diradd *da,
 +                                 unsigned nr_inodes)
 +{
 +      return da->nr_blocks + gfs2_rg_blocks(dip, da->nr_blocks) +
 +             (nr_inodes * RES_DINODE) + RES_QUOTA + RES_STATFS;
 +}
 +
  static int link_dinode(struct gfs2_inode *dip, const struct qstr *name,
 -                     struct gfs2_inode *ip, int arq)
 +                     struct gfs2_inode *ip, struct gfs2_diradd *da)
  {
        struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
 -      struct gfs2_alloc_parms ap = { .target = sdp->sd_max_dirres, };
 +      struct gfs2_alloc_parms ap = { .target = da->nr_blocks, };
        int error;
  
 -      if (arq) {
 +      if (da->nr_blocks) {
                error = gfs2_quota_lock_check(dip);
                if (error)
                        goto fail_quota_locks;
                if (error)
                        goto fail_quota_locks;
  
 -              error = gfs2_trans_begin(sdp, sdp->sd_max_dirres +
 -                                       dip->i_rgd->rd_length +
 -                                       2 * RES_DINODE +
 -                                       RES_STATFS + RES_QUOTA, 0);
 +              error = gfs2_trans_begin(sdp, gfs2_trans_da_blks(dip, da, 2), 0);
                if (error)
                        goto fail_ipreserv;
        } else {
                        goto fail_quota_locks;
        }
  
 -      error = gfs2_dir_add(&dip->i_inode, name, ip);
 +      error = gfs2_dir_add(&dip->i_inode, name, ip, da);
        if (error)
                goto fail_end_trans;
  
@@@ -571,6 -552,7 +571,7 @@@ static int gfs2_create_inode(struct ino
                             unsigned int size, int excl, int *opened)
  {
        const struct qstr *name = &dentry->d_name;
+       struct posix_acl *default_acl, *acl;
        struct gfs2_holder ghs[2];
        struct inode *inode = NULL;
        struct gfs2_inode *dip = GFS2_I(dir), *ip;
        struct dentry *d;
        int error;
        u32 aflags = 0;
 -      int arq;
 +      struct gfs2_diradd da = { .bh = NULL, };
  
        if (!name->len || name->len > GFS2_FNAMESIZE)
                return -ENAMETOOLONG;
        error = PTR_ERR(inode);
        if (!IS_ERR(inode)) {
                d = d_splice_alias(inode, dentry);
 +              error = PTR_ERR(d);
 +              if (IS_ERR(d))
 +                      goto fail_gunlock;
                error = 0;
                if (file) {
                        if (S_ISREG(inode->i_mode)) {
                goto fail_gunlock;
        }
  
 -      arq = error = gfs2_diradd_alloc_required(dir, name);
 +      error = gfs2_diradd_alloc_required(dir, name, &da);
        if (error < 0)
                goto fail_gunlock;
  
        if (!inode)
                goto fail_gunlock;
  
+       error = posix_acl_create(dir, &mode, &default_acl, &acl);
+       if (error)
+               goto fail_free_vfs_inode;
        ip = GFS2_I(inode);
        error = gfs2_rs_alloc(ip);
        if (error)
-               goto fail_free_inode;
+               goto fail_free_acls;
  
        inode->i_mode = mode;
        set_nlink(inode, S_ISDIR(mode) ? 2 : 1);
        gfs2_set_iop(inode);
        insert_inode_hash(inode);
  
-       error = gfs2_acl_create(dip, inode);
+       if (default_acl) {
+               error = gfs2_set_acl(inode, default_acl, ACL_TYPE_DEFAULT);
+               posix_acl_release(default_acl);
+       }
+       if (acl) {
+               if (!error)
+                       error = gfs2_set_acl(inode, acl, ACL_TYPE_ACCESS);
+               posix_acl_release(acl);
+       }
        if (error)
                goto fail_gunlock3;
  
        if (error)
                goto fail_gunlock3;
  
 -      error = link_dinode(dip, name, ip, arq);
 +      error = link_dinode(dip, name, ip, &da);
        if (error)
                goto fail_gunlock3;
  
@@@ -738,10 -730,15 +752,16 @@@ fail_free_inode
        if (ip->i_gl)
                gfs2_glock_put(ip->i_gl);
        gfs2_rs_delete(ip, NULL);
+ fail_free_acls:
+       if (default_acl)
+               posix_acl_release(default_acl);
+       if (acl)
+               posix_acl_release(acl);
+ fail_free_vfs_inode:
        free_inode_nonrcu(inode);
        inode = NULL;
  fail_gunlock:
 +      gfs2_dir_no_add(&da);
        gfs2_glock_dq_uninit(ghs);
        if (inode && !IS_ERR(inode)) {
                clear_nlink(inode);
@@@ -802,11 -799,6 +822,11 @@@ static struct dentry *__gfs2_lookup(str
        }
  
        d = d_splice_alias(inode, dentry);
 +      if (IS_ERR(d)) {
 +              iput(inode);
 +              gfs2_glock_dq_uninit(&gh);
 +              return d;
 +      }
        if (file && S_ISREG(inode->i_mode))
                error = finish_open(file, dentry, gfs2_open_common, opened);
  
@@@ -845,7 -837,7 +865,7 @@@ static int gfs2_link(struct dentry *old
        struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_holder ghs[2];
        struct buffer_head *dibh;
 -      int alloc_required;
 +      struct gfs2_diradd da = { .bh = NULL, };
        int error;
  
        if (S_ISDIR(inode->i_mode))
        if (ip->i_inode.i_nlink == (u32)-1)
                goto out_gunlock;
  
 -      alloc_required = error = gfs2_diradd_alloc_required(dir, &dentry->d_name);
 +      error = gfs2_diradd_alloc_required(dir, &dentry->d_name, &da);
        if (error < 0)
                goto out_gunlock;
 -      error = 0;
  
 -      if (alloc_required) {
 -              struct gfs2_alloc_parms ap = { .target = sdp->sd_max_dirres, };
 +      if (da.nr_blocks) {
 +              struct gfs2_alloc_parms ap = { .target = da.nr_blocks, };
                error = gfs2_quota_lock_check(dip);
                if (error)
                        goto out_gunlock;
                if (error)
                        goto out_gunlock_q;
  
 -              error = gfs2_trans_begin(sdp, sdp->sd_max_dirres +
 -                                       gfs2_rg_blocks(dip, sdp->sd_max_dirres) +
 -                                       2 * RES_DINODE + RES_STATFS +
 -                                       RES_QUOTA, 0);
 +              error = gfs2_trans_begin(sdp, gfs2_trans_da_blks(dip, &da, 2), 0);
                if (error)
                        goto out_ipres;
        } else {
        if (error)
                goto out_end_trans;
  
 -      error = gfs2_dir_add(dir, &dentry->d_name, ip);
 +      error = gfs2_dir_add(dir, &dentry->d_name, ip, &da);
        if (error)
                goto out_brelse;
  
@@@ -943,13 -939,12 +963,13 @@@ out_brelse
  out_end_trans:
        gfs2_trans_end(sdp);
  out_ipres:
 -      if (alloc_required)
 +      if (da.nr_blocks)
                gfs2_inplace_release(dip);
  out_gunlock_q:
 -      if (alloc_required)
 +      if (da.nr_blocks)
                gfs2_quota_unlock(dip);
  out_gunlock:
 +      gfs2_dir_no_add(&da);
        gfs2_glock_dq(ghs + 1);
  out_child:
        gfs2_glock_dq(ghs);
@@@ -1279,7 -1274,7 +1299,7 @@@ static int gfs2_rename(struct inode *od
        struct gfs2_rgrpd *nrgd;
        unsigned int num_gh;
        int dir_rename = 0;
 -      int alloc_required = 0;
 +      struct gfs2_diradd da = { .nr_blocks = 0, };
        unsigned int x;
        int error;
  
                        goto out_gunlock;
        }
  
 -      if (nip == NULL)
 -              alloc_required = gfs2_diradd_alloc_required(ndir, &ndentry->d_name);
 -      error = alloc_required;
 -      if (error < 0)
 -              goto out_gunlock;
 +      if (nip == NULL) {
 +              error = gfs2_diradd_alloc_required(ndir, &ndentry->d_name, &da);
 +              if (error)
 +                      goto out_gunlock;
 +      }
  
 -      if (alloc_required) {
 -              struct gfs2_alloc_parms ap = { .target = sdp->sd_max_dirres, };
 +      if (da.nr_blocks) {
 +              struct gfs2_alloc_parms ap = { .target = da.nr_blocks, };
                error = gfs2_quota_lock_check(ndip);
                if (error)
                        goto out_gunlock;
                if (error)
                        goto out_gunlock_q;
  
 -              error = gfs2_trans_begin(sdp, sdp->sd_max_dirres +
 -                                       gfs2_rg_blocks(ndip, sdp->sd_max_dirres) +
 -                                       4 * RES_DINODE + 4 * RES_LEAF +
 -                                       RES_STATFS + RES_QUOTA + 4, 0);
 +              error = gfs2_trans_begin(sdp, gfs2_trans_da_blks(ndip, &da, 4) +
 +                                       4 * RES_LEAF + 4, 0);
                if (error)
                        goto out_ipreserv;
        } else {
        if (error)
                goto out_end_trans;
  
 -      error = gfs2_dir_add(ndir, &ndentry->d_name, ip);
 +      error = gfs2_dir_add(ndir, &ndentry->d_name, ip, &da);
        if (error)
                goto out_end_trans;
  
  out_end_trans:
        gfs2_trans_end(sdp);
  out_ipreserv:
 -      if (alloc_required)
 +      if (da.nr_blocks)
                gfs2_inplace_release(ndip);
  out_gunlock_q:
 -      if (alloc_required)
 +      if (da.nr_blocks)
                gfs2_quota_unlock(ndip);
  out_gunlock:
 +      gfs2_dir_no_add(&da);
        while (x--) {
                gfs2_glock_dq(ghs + x);
                gfs2_holder_uninit(ghs + x);
@@@ -1631,22 -1627,10 +1651,22 @@@ static int setattr_chown(struct inode *
        if (!(attr->ia_valid & ATTR_GID) || gid_eq(ogid, ngid))
                ogid = ngid = NO_GID_QUOTA_CHANGE;
  
 -      error = gfs2_quota_lock(ip, nuid, ngid);
 +      error = get_write_access(inode);
        if (error)
                return error;
  
 +      error = gfs2_rs_alloc(ip);
 +      if (error)
 +              goto out;
 +
 +      error = gfs2_rindex_update(sdp);
 +      if (error)
 +              goto out;
 +
 +      error = gfs2_quota_lock(ip, nuid, ngid);
 +      if (error)
 +              goto out;
 +
        if (!uid_eq(ouid, NO_UID_QUOTA_CHANGE) ||
            !gid_eq(ogid, NO_GID_QUOTA_CHANGE)) {
                error = gfs2_quota_check(ip, nuid, ngid);
@@@ -1673,8 -1657,6 +1693,8 @@@ out_end_trans
        gfs2_trans_end(sdp);
  out_gunlock_q:
        gfs2_quota_unlock(ip);
 +out:
 +      put_write_access(inode);
        return error;
  }
  
@@@ -1716,10 -1698,11 +1736,11 @@@ static int gfs2_setattr(struct dentry *
                error = gfs2_setattr_size(inode, attr->ia_size);
        else if (attr->ia_valid & (ATTR_UID | ATTR_GID))
                error = setattr_chown(inode, attr);
-       else if ((attr->ia_valid & ATTR_MODE) && IS_POSIXACL(inode))
-               error = gfs2_acl_chmod(ip, attr);
-       else
+       else {
                error = gfs2_setattr_simple(inode, attr);
+               if (!error && attr->ia_valid & ATTR_MODE)
+                       error = posix_acl_chmod(inode, inode->i_mode);
+       }
  
  out:
        if (!error)
@@@ -1879,6 -1862,7 +1900,7 @@@ const struct inode_operations gfs2_file
        .removexattr = gfs2_removexattr,
        .fiemap = gfs2_fiemap,
        .get_acl = gfs2_get_acl,
+       .set_acl = gfs2_set_acl,
  };
  
  const struct inode_operations gfs2_dir_iops = {
        .removexattr = gfs2_removexattr,
        .fiemap = gfs2_fiemap,
        .get_acl = gfs2_get_acl,
+       .set_acl = gfs2_set_acl,
        .atomic_open = gfs2_atomic_open,
  };
  
@@@ -1915,6 -1900,5 +1938,5 @@@ const struct inode_operations gfs2_syml
        .listxattr = gfs2_listxattr,
        .removexattr = gfs2_removexattr,
        .fiemap = gfs2_fiemap,
-       .get_acl = gfs2_get_acl,
  };
  
diff --combined fs/hfsplus/inode.c
index 3ebda928229cb375486da2a05f15e860b5380fbc,2e10993fa9667f42b703768b466037ff6bdc6fc3..4551cbd6bd43aaaebbde666c22c726c76112ab6e
@@@ -178,6 -178,64 +178,6 @@@ const struct dentry_operations hfsplus_
        .d_compare    = hfsplus_compare_dentry,
  };
  
 -static struct dentry *hfsplus_file_lookup(struct inode *dir,
 -              struct dentry *dentry, unsigned int flags)
 -{
 -      struct hfs_find_data fd;
 -      struct super_block *sb = dir->i_sb;
 -      struct inode *inode = NULL;
 -      struct hfsplus_inode_info *hip;
 -      int err;
 -
 -      if (HFSPLUS_IS_RSRC(dir) || strcmp(dentry->d_name.name, "rsrc"))
 -              goto out;
 -
 -      inode = HFSPLUS_I(dir)->rsrc_inode;
 -      if (inode)
 -              goto out;
 -
 -      inode = new_inode(sb);
 -      if (!inode)
 -              return ERR_PTR(-ENOMEM);
 -
 -      hip = HFSPLUS_I(inode);
 -      inode->i_ino = dir->i_ino;
 -      INIT_LIST_HEAD(&hip->open_dir_list);
 -      mutex_init(&hip->extents_lock);
 -      hip->extent_state = 0;
 -      hip->flags = 0;
 -      hip->userflags = 0;
 -      set_bit(HFSPLUS_I_RSRC, &hip->flags);
 -
 -      err = hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);
 -      if (!err) {
 -              err = hfsplus_find_cat(sb, dir->i_ino, &fd);
 -              if (!err)
 -                      err = hfsplus_cat_read_inode(inode, &fd);
 -              hfs_find_exit(&fd);
 -      }
 -      if (err) {
 -              iput(inode);
 -              return ERR_PTR(err);
 -      }
 -      hip->rsrc_inode = dir;
 -      HFSPLUS_I(dir)->rsrc_inode = inode;
 -      igrab(dir);
 -
 -      /*
 -       * __mark_inode_dirty expects inodes to be hashed.  Since we don't
 -       * want resource fork inodes in the regular inode space, we make them
 -       * appear hashed, but do not put on any lists.  hlist_del()
 -       * will work fine and require no locking.
 -       */
 -      hlist_add_fake(&inode->i_hash);
 -
 -      mark_inode_dirty(inode);
 -out:
 -      d_add(dentry, inode);
 -      return NULL;
 -}
 -
  static void hfsplus_get_perms(struct inode *inode,
                struct hfsplus_perm *perms, int dir)
  {
@@@ -261,7 -319,7 +261,7 @@@ static int hfsplus_setattr(struct dentr
        mark_inode_dirty(inode);
  
        if (attr->ia_valid & ATTR_MODE) {
-               error = hfsplus_posix_acl_chmod(inode);
+               error = posix_acl_chmod(inode, inode->i_mode);
                if (unlikely(error))
                        return error;
        }
@@@ -327,6 -385,7 +327,6 @@@ int hfsplus_file_fsync(struct file *fil
  }
  
  static const struct inode_operations hfsplus_file_inode_operations = {
 -      .lookup         = hfsplus_file_lookup,
        .setattr        = hfsplus_setattr,
        .setxattr       = generic_setxattr,
        .getxattr       = generic_getxattr,
        .removexattr    = hfsplus_removexattr,
  #ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
        .get_acl        = hfsplus_get_posix_acl,
+       .set_acl        = hfsplus_set_posix_acl,
  #endif
  };
  
diff --combined fs/ocfs2/file.c
index f42eecef64781ecac5af385adbb9a91b19f02e51,014a38e9006b34d370daa55c9a3590bc1dae0f6f..d77d71ead8d12071a52b1f0f63c66f1077c93f84
@@@ -1236,7 -1236,7 +1236,7 @@@ bail
                dqput(transfer_to[qtype]);
  
        if (!status && attr->ia_valid & ATTR_MODE) {
-               status = ocfs2_acl_chmod(inode);
+               status = posix_acl_chmod(inode, inode->i_mode);
                if (status < 0)
                        mlog_errno(status);
        }
@@@ -1869,8 -1869,7 +1869,8 @@@ static int __ocfs2_change_file_space(st
        }
        size = sr->l_start + sr->l_len;
  
 -      if (cmd == OCFS2_IOC_RESVSP || cmd == OCFS2_IOC_RESVSP64) {
 +      if (cmd == OCFS2_IOC_RESVSP || cmd == OCFS2_IOC_RESVSP64 ||
 +          cmd == OCFS2_IOC_UNRESVSP || cmd == OCFS2_IOC_UNRESVSP64) {
                if (sr->l_len <= 0) {
                        ret = -EINVAL;
                        goto out_inode_unlock;
@@@ -2662,6 -2661,7 +2662,7 @@@ const struct inode_operations ocfs2_fil
        .removexattr    = generic_removexattr,
        .fiemap         = ocfs2_fiemap,
        .get_acl        = ocfs2_iop_get_acl,
+       .set_acl        = ocfs2_iop_set_acl,
  };
  
  const struct inode_operations ocfs2_special_file_iops = {
        .getattr        = ocfs2_getattr,
        .permission     = ocfs2_permission,
        .get_acl        = ocfs2_iop_get_acl,
+       .set_acl        = ocfs2_iop_set_acl,
  };
  
  /*
diff --combined fs/ocfs2/namei.c
index 41513a4e98e462b0da59fe29787f0352eb7b2eaf,c975eed2e713f1f3562fc541154ab0f74a170858..f4d609be940086794ff8e64b1ed7cd832ba517f5
@@@ -230,6 -230,7 +230,7 @@@ static int ocfs2_mknod(struct inode *di
        struct ocfs2_dir_lookup_result lookup = { NULL, };
        sigset_t oldset;
        int did_block_signals = 0;
+       struct posix_acl *default_acl = NULL, *acl = NULL;
  
        trace_ocfs2_mknod(dir, dentry, dentry->d_name.len, dentry->d_name.name,
                          (unsigned long long)OCFS2_I(dir)->ip_blkno,
                goto leave;
        }
  
+       status = posix_acl_create(dir, &mode, &default_acl, &acl);
+       if (status) {
+               mlog_errno(status);
+               goto leave;
+       }
        handle = ocfs2_start_trans(osb, ocfs2_mknod_credits(osb->sb,
                                                            S_ISDIR(mode),
                                                            xattr_credits));
                inc_nlink(dir);
        }
  
-       status = ocfs2_init_acl(handle, inode, dir, new_fe_bh, parent_fe_bh,
-                               meta_ac, data_ac);
+       if (default_acl) {
+               status = ocfs2_set_acl(handle, inode, new_fe_bh,
+                                      ACL_TYPE_DEFAULT, default_acl,
+                                      meta_ac, data_ac);
+       }
+       if (!status && acl) {
+               status = ocfs2_set_acl(handle, inode, new_fe_bh,
+                                      ACL_TYPE_ACCESS, acl,
+                                      meta_ac, data_ac);
+       }
        if (status < 0) {
                mlog_errno(status);
                goto leave;
        d_instantiate(dentry, inode);
        status = 0;
  leave:
+       if (default_acl)
+               posix_acl_release(default_acl);
+       if (acl)
+               posix_acl_release(acl);
        if (status < 0 && did_quota_inode)
                dquot_free_inode(inode);
        if (handle)
@@@ -948,7 -968,7 +968,7 @@@ leave
        ocfs2_free_dir_lookup_result(&orphan_insert);
        ocfs2_free_dir_lookup_result(&lookup);
  
 -      if (status && (status != -ENOTEMPTY))
 +      if (status && (status != -ENOTEMPTY) && (status != -ENOENT))
                mlog_errno(status);
  
        return status;
@@@ -2504,4 -2524,5 +2524,5 @@@ const struct inode_operations ocfs2_dir
        .removexattr    = generic_removexattr,
        .fiemap         = ocfs2_fiemap,
        .get_acl        = ocfs2_iop_get_acl,
+       .set_acl        = ocfs2_iop_set_acl,
  };
diff --combined fs/posix_acl.c
index 551e61ba15b6047c909594968163eaf26c8cb605,f40df9b665fbc970ee863a20ba779b2ce16073f4..38bae5a0ea257ebc414aef89727f3a652d904c96
@@@ -1,10 -1,8 +1,8 @@@
  /*
-  * linux/fs/posix_acl.c
+  * Copyright (C) 2002,2003 by Andreas Gruenbacher <a.gruenbacher@computer.org>
   *
-  *  Copyright (C) 2002 by Andreas Gruenbacher <a.gruenbacher@computer.org>
-  *
-  *  Fixes from William Schumacher incorporated on 15 March 2001.
-  *     (Reported by Charles Bertsch, <CBertsch@microtest.com>).
+  * Fixes from William Schumacher incorporated on 15 March 2001.
+  *    (Reported by Charles Bertsch, <CBertsch@microtest.com>).
   */
  
  /*
  #include <linux/fs.h>
  #include <linux/sched.h>
  #include <linux/posix_acl.h>
+ #include <linux/posix_acl_xattr.h>
+ #include <linux/xattr.h>
  #include <linux/export.h>
- #include <linux/errno.h>
+ #include <linux/user_namespace.h>
  
 -EXPORT_SYMBOL(posix_acl_init);
 -EXPORT_SYMBOL(posix_acl_alloc);
 -EXPORT_SYMBOL(posix_acl_valid);
 -EXPORT_SYMBOL(posix_acl_equiv_mode);
 -EXPORT_SYMBOL(posix_acl_from_mode);
 +struct posix_acl **acl_by_type(struct inode *inode, int type)
 +{
 +      switch (type) {
 +      case ACL_TYPE_ACCESS:
 +              return &inode->i_acl;
 +      case ACL_TYPE_DEFAULT:
 +              return &inode->i_default_acl;
 +      default:
 +              BUG();
 +      }
 +}
 +EXPORT_SYMBOL(acl_by_type);
 +
 +struct posix_acl *get_cached_acl(struct inode *inode, int type)
 +{
 +      struct posix_acl **p = acl_by_type(inode, type);
 +      struct posix_acl *acl = ACCESS_ONCE(*p);
 +      if (acl) {
 +              spin_lock(&inode->i_lock);
 +              acl = *p;
 +              if (acl != ACL_NOT_CACHED)
 +                      acl = posix_acl_dup(acl);
 +              spin_unlock(&inode->i_lock);
 +      }
 +      return acl;
 +}
 +EXPORT_SYMBOL(get_cached_acl);
 +
 +struct posix_acl *get_cached_acl_rcu(struct inode *inode, int type)
 +{
 +      return rcu_dereference(*acl_by_type(inode, type));
 +}
 +EXPORT_SYMBOL(get_cached_acl_rcu);
 +
 +void set_cached_acl(struct inode *inode, int type, struct posix_acl *acl)
 +{
 +      struct posix_acl **p = acl_by_type(inode, type);
 +      struct posix_acl *old;
 +      spin_lock(&inode->i_lock);
 +      old = *p;
 +      rcu_assign_pointer(*p, posix_acl_dup(acl));
 +      spin_unlock(&inode->i_lock);
 +      if (old != ACL_NOT_CACHED)
 +              posix_acl_release(old);
 +}
 +EXPORT_SYMBOL(set_cached_acl);
 +
 +void forget_cached_acl(struct inode *inode, int type)
 +{
 +      struct posix_acl **p = acl_by_type(inode, type);
 +      struct posix_acl *old;
 +      spin_lock(&inode->i_lock);
 +      old = *p;
 +      *p = ACL_NOT_CACHED;
 +      spin_unlock(&inode->i_lock);
 +      if (old != ACL_NOT_CACHED)
 +              posix_acl_release(old);
 +}
 +EXPORT_SYMBOL(forget_cached_acl);
 +
 +void forget_all_cached_acls(struct inode *inode)
 +{
 +      struct posix_acl *old_access, *old_default;
 +      spin_lock(&inode->i_lock);
 +      old_access = inode->i_acl;
 +      old_default = inode->i_default_acl;
 +      inode->i_acl = inode->i_default_acl = ACL_NOT_CACHED;
 +      spin_unlock(&inode->i_lock);
 +      if (old_access != ACL_NOT_CACHED)
 +              posix_acl_release(old_access);
 +      if (old_default != ACL_NOT_CACHED)
 +              posix_acl_release(old_default);
 +}
 +EXPORT_SYMBOL(forget_all_cached_acls);
  
+ struct posix_acl *get_acl(struct inode *inode, int type)
+ {
+       struct posix_acl *acl;
+       acl = get_cached_acl(inode, type);
+       if (acl != ACL_NOT_CACHED)
+               return acl;
+       if (!IS_POSIXACL(inode))
+               return NULL;
+       /*
+        * A filesystem can force a ACL callback by just never filling the
+        * ACL cache. But normally you'd fill the cache either at inode
+        * instantiation time, or on the first ->get_acl call.
+        *
+        * If the filesystem doesn't have a get_acl() function at all, we'll
+        * just create the negative cache entry.
+        */
+       if (!inode->i_op->get_acl) {
+               set_cached_acl(inode, type, NULL);
+               return NULL;
+       }
+       return inode->i_op->get_acl(inode, type);
+ }
+ EXPORT_SYMBOL(get_acl);
  /*
   * Init a fresh posix_acl
   */
@@@ -106,7 -63,6 +132,7 @@@ posix_acl_init(struct posix_acl *acl, i
        atomic_set(&acl->a_refcount, 1);
        acl->a_count = count;
  }
 +EXPORT_SYMBOL(posix_acl_init);
  
  /*
   * Allocate a new ACL with the specified number of entries.
@@@ -121,7 -77,6 +147,7 @@@ posix_acl_alloc(int count, gfp_t flags
                posix_acl_init(acl, count);
        return acl;
  }
 +EXPORT_SYMBOL(posix_acl_alloc);
  
  /*
   * Clone an ACL.
@@@ -149,6 -104,8 +175,6 @@@ posix_acl_valid(const struct posix_acl 
  {
        const struct posix_acl_entry *pa, *pe;
        int state = ACL_USER_OBJ;
 -      kuid_t prev_uid = INVALID_UID;
 -      kgid_t prev_gid = INVALID_GID;
        int needs_mask = 0;
  
        FOREACH_ACL_ENTRY(pa, acl, pe) {
                                        return -EINVAL;
                                if (!uid_valid(pa->e_uid))
                                        return -EINVAL;
 -                              if (uid_valid(prev_uid) &&
 -                                  uid_lte(pa->e_uid, prev_uid))
 -                                      return -EINVAL;
 -                              prev_uid = pa->e_uid;
                                needs_mask = 1;
                                break;
  
                                        return -EINVAL;
                                if (!gid_valid(pa->e_gid))
                                        return -EINVAL;
 -                              if (gid_valid(prev_gid) &&
 -                                  gid_lte(pa->e_gid, prev_gid))
 -                                      return -EINVAL;
 -                              prev_gid = pa->e_gid;
                                needs_mask = 1;
                                break;
  
                return 0;
        return -EINVAL;
  }
 +EXPORT_SYMBOL(posix_acl_valid);
  
  /*
   * Returns 0 if the acl can be exactly represented in the traditional
@@@ -248,7 -212,6 +274,7 @@@ posix_acl_equiv_mode(const struct posix
                  *mode_p = (*mode_p & ~S_IRWXUGO) | mode;
          return not_equiv;
  }
 +EXPORT_SYMBOL(posix_acl_equiv_mode);
  
  /*
   * Create an ACL representing the file mode permission bits of an inode.
@@@ -270,7 -233,6 +296,7 @@@ posix_acl_from_mode(umode_t mode, gfp_
        acl->a_entries[2].e_perm = (mode & S_IRWXO);
        return acl;
  }
 +EXPORT_SYMBOL(posix_acl_from_mode);
  
  /*
   * Return 0 if current is granted want access to the inode
@@@ -402,7 -364,7 +428,7 @@@ static int posix_acl_create_masq(struc
  /*
   * Modify the ACL for the chmod syscall.
   */
- static int posix_acl_chmod_masq(struct posix_acl *acl, umode_t mode)
+ static int __posix_acl_chmod_masq(struct posix_acl *acl, umode_t mode)
  {
        struct posix_acl_entry *group_obj = NULL, *mask_obj = NULL;
        struct posix_acl_entry *pa, *pe;
  }
  
  int
- posix_acl_create(struct posix_acl **acl, gfp_t gfp, umode_t *mode_p)
__posix_acl_create(struct posix_acl **acl, gfp_t gfp, umode_t *mode_p)
  {
        struct posix_acl *clone = posix_acl_clone(*acl, gfp);
        int err = -ENOMEM;
        *acl = clone;
        return err;
  }
- EXPORT_SYMBOL(posix_acl_create);
+ EXPORT_SYMBOL(__posix_acl_create);
  
  int
- posix_acl_chmod(struct posix_acl **acl, gfp_t gfp, umode_t mode)
__posix_acl_chmod(struct posix_acl **acl, gfp_t gfp, umode_t mode)
  {
        struct posix_acl *clone = posix_acl_clone(*acl, gfp);
        int err = -ENOMEM;
        if (clone) {
-               err = posix_acl_chmod_masq(clone, mode);
+               err = __posix_acl_chmod_masq(clone, mode);
                if (err) {
                        posix_acl_release(clone);
                        clone = NULL;
        *acl = clone;
        return err;
  }
+ EXPORT_SYMBOL(__posix_acl_chmod);
+ int
+ posix_acl_chmod(struct inode *inode, umode_t mode)
+ {
+       struct posix_acl *acl;
+       int ret = 0;
+       if (!IS_POSIXACL(inode))
+               return 0;
+       if (!inode->i_op->set_acl)
+               return -EOPNOTSUPP;
+       acl = get_acl(inode, ACL_TYPE_ACCESS);
+       if (IS_ERR_OR_NULL(acl))
+               return PTR_ERR(acl);
+       ret = __posix_acl_chmod(&acl, GFP_KERNEL, mode);
+       if (ret)
+               return ret;
+       ret = inode->i_op->set_acl(inode, acl, ACL_TYPE_ACCESS);
+       posix_acl_release(acl);
+       return ret;
+ }
  EXPORT_SYMBOL(posix_acl_chmod);
+ int
+ posix_acl_create(struct inode *dir, umode_t *mode,
+               struct posix_acl **default_acl, struct posix_acl **acl)
+ {
+       struct posix_acl *p;
+       int ret;
+       if (S_ISLNK(*mode) || !IS_POSIXACL(dir))
+               goto no_acl;
+       p = get_acl(dir, ACL_TYPE_DEFAULT);
+       if (IS_ERR(p))
+               return PTR_ERR(p);
+       if (!p) {
+               *mode &= ~current_umask();
+               goto no_acl;
+       }
+       *acl = posix_acl_clone(p, GFP_NOFS);
+       if (!*acl)
+               return -ENOMEM;
+       ret = posix_acl_create_masq(*acl, mode);
+       if (ret < 0) {
+               posix_acl_release(*acl);
+               return -ENOMEM;
+       }
+       if (ret == 0) {
+               posix_acl_release(*acl);
+               *acl = NULL;
+       }
+       if (!S_ISDIR(*mode)) {
+               posix_acl_release(p);
+               *default_acl = NULL;
+       } else {
+               *default_acl = p;
+       }
+       return 0;
+ no_acl:
+       *default_acl = NULL;
+       *acl = NULL;
+       return 0;
+ }
+ EXPORT_SYMBOL_GPL(posix_acl_create);
+ /*
+  * Fix up the uids and gids in posix acl extended attributes in place.
+  */
+ static void posix_acl_fix_xattr_userns(
+       struct user_namespace *to, struct user_namespace *from,
+       void *value, size_t size)
+ {
+       posix_acl_xattr_header *header = (posix_acl_xattr_header *)value;
+       posix_acl_xattr_entry *entry = (posix_acl_xattr_entry *)(header+1), *end;
+       int count;
+       kuid_t uid;
+       kgid_t gid;
+       if (!value)
+               return;
+       if (size < sizeof(posix_acl_xattr_header))
+               return;
+       if (header->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION))
+               return;
+       count = posix_acl_xattr_count(size);
+       if (count < 0)
+               return;
+       if (count == 0)
+               return;
+       for (end = entry + count; entry != end; entry++) {
+               switch(le16_to_cpu(entry->e_tag)) {
+               case ACL_USER:
+                       uid = make_kuid(from, le32_to_cpu(entry->e_id));
+                       entry->e_id = cpu_to_le32(from_kuid(to, uid));
+                       break;
+               case ACL_GROUP:
+                       gid = make_kgid(from, le32_to_cpu(entry->e_id));
+                       entry->e_id = cpu_to_le32(from_kgid(to, gid));
+                       break;
+               default:
+                       break;
+               }
+       }
+ }
+ void posix_acl_fix_xattr_from_user(void *value, size_t size)
+ {
+       struct user_namespace *user_ns = current_user_ns();
+       if (user_ns == &init_user_ns)
+               return;
+       posix_acl_fix_xattr_userns(&init_user_ns, user_ns, value, size);
+ }
+ void posix_acl_fix_xattr_to_user(void *value, size_t size)
+ {
+       struct user_namespace *user_ns = current_user_ns();
+       if (user_ns == &init_user_ns)
+               return;
+       posix_acl_fix_xattr_userns(user_ns, &init_user_ns, value, size);
+ }
+ /*
+  * Convert from extended attribute to in-memory representation.
+  */
+ struct posix_acl *
+ posix_acl_from_xattr(struct user_namespace *user_ns,
+                    const void *value, size_t size)
+ {
+       posix_acl_xattr_header *header = (posix_acl_xattr_header *)value;
+       posix_acl_xattr_entry *entry = (posix_acl_xattr_entry *)(header+1), *end;
+       int count;
+       struct posix_acl *acl;
+       struct posix_acl_entry *acl_e;
+       if (!value)
+               return NULL;
+       if (size < sizeof(posix_acl_xattr_header))
+                return ERR_PTR(-EINVAL);
+       if (header->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION))
+               return ERR_PTR(-EOPNOTSUPP);
+       count = posix_acl_xattr_count(size);
+       if (count < 0)
+               return ERR_PTR(-EINVAL);
+       if (count == 0)
+               return NULL;
+       
+       acl = posix_acl_alloc(count, GFP_NOFS);
+       if (!acl)
+               return ERR_PTR(-ENOMEM);
+       acl_e = acl->a_entries;
+       
+       for (end = entry + count; entry != end; acl_e++, entry++) {
+               acl_e->e_tag  = le16_to_cpu(entry->e_tag);
+               acl_e->e_perm = le16_to_cpu(entry->e_perm);
+               switch(acl_e->e_tag) {
+                       case ACL_USER_OBJ:
+                       case ACL_GROUP_OBJ:
+                       case ACL_MASK:
+                       case ACL_OTHER:
+                               break;
+                       case ACL_USER:
+                               acl_e->e_uid =
+                                       make_kuid(user_ns,
+                                                 le32_to_cpu(entry->e_id));
+                               if (!uid_valid(acl_e->e_uid))
+                                       goto fail;
+                               break;
+                       case ACL_GROUP:
+                               acl_e->e_gid =
+                                       make_kgid(user_ns,
+                                                 le32_to_cpu(entry->e_id));
+                               if (!gid_valid(acl_e->e_gid))
+                                       goto fail;
+                               break;
+                       default:
+                               goto fail;
+               }
+       }
+       return acl;
+ fail:
+       posix_acl_release(acl);
+       return ERR_PTR(-EINVAL);
+ }
+ EXPORT_SYMBOL (posix_acl_from_xattr);
+ /*
+  * Convert from in-memory to extended attribute representation.
+  */
+ int
+ posix_acl_to_xattr(struct user_namespace *user_ns, const struct posix_acl *acl,
+                  void *buffer, size_t size)
+ {
+       posix_acl_xattr_header *ext_acl = (posix_acl_xattr_header *)buffer;
+       posix_acl_xattr_entry *ext_entry = ext_acl->a_entries;
+       int real_size, n;
+       real_size = posix_acl_xattr_size(acl->a_count);
+       if (!buffer)
+               return real_size;
+       if (real_size > size)
+               return -ERANGE;
+       
+       ext_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
+       for (n=0; n < acl->a_count; n++, ext_entry++) {
+               const struct posix_acl_entry *acl_e = &acl->a_entries[n];
+               ext_entry->e_tag  = cpu_to_le16(acl_e->e_tag);
+               ext_entry->e_perm = cpu_to_le16(acl_e->e_perm);
+               switch(acl_e->e_tag) {
+               case ACL_USER:
+                       ext_entry->e_id =
+                               cpu_to_le32(from_kuid(user_ns, acl_e->e_uid));
+                       break;
+               case ACL_GROUP:
+                       ext_entry->e_id =
+                               cpu_to_le32(from_kgid(user_ns, acl_e->e_gid));
+                       break;
+               default:
+                       ext_entry->e_id = cpu_to_le32(ACL_UNDEFINED_ID);
+                       break;
+               }
+       }
+       return real_size;
+ }
+ EXPORT_SYMBOL (posix_acl_to_xattr);
+ static int
+ posix_acl_xattr_get(struct dentry *dentry, const char *name,
+               void *value, size_t size, int type)
+ {
+       struct posix_acl *acl;
+       int error;
+       if (!IS_POSIXACL(dentry->d_inode))
+               return -EOPNOTSUPP;
+       if (S_ISLNK(dentry->d_inode->i_mode))
+               return -EOPNOTSUPP;
+       acl = get_acl(dentry->d_inode, type);
+       if (IS_ERR(acl))
+               return PTR_ERR(acl);
+       if (acl == NULL)
+               return -ENODATA;
+       error = posix_acl_to_xattr(&init_user_ns, acl, value, size);
+       posix_acl_release(acl);
+       return error;
+ }
+ static int
+ posix_acl_xattr_set(struct dentry *dentry, const char *name,
+               const void *value, size_t size, int flags, int type)
+ {
+       struct inode *inode = dentry->d_inode;
+       struct posix_acl *acl = NULL;
+       int ret;
+       if (!IS_POSIXACL(inode))
+               return -EOPNOTSUPP;
+       if (!inode->i_op->set_acl)
+               return -EOPNOTSUPP;
+       if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
+               return value ? -EACCES : 0;
+       if (!inode_owner_or_capable(inode))
+               return -EPERM;
+       if (value) {
+               acl = posix_acl_from_xattr(&init_user_ns, value, size);
+               if (IS_ERR(acl))
+                       return PTR_ERR(acl);
+               if (acl) {
+                       ret = posix_acl_valid(acl);
+                       if (ret)
+                               goto out;
+               }
+       }
+       ret = inode->i_op->set_acl(inode, acl, type);
+ out:
+       posix_acl_release(acl);
+       return ret;
+ }
+ static size_t
+ posix_acl_xattr_list(struct dentry *dentry, char *list, size_t list_size,
+               const char *name, size_t name_len, int type)
+ {
+       const char *xname;
+       size_t size;
+       if (!IS_POSIXACL(dentry->d_inode))
+               return -EOPNOTSUPP;
+       if (S_ISLNK(dentry->d_inode->i_mode))
+               return -EOPNOTSUPP;
+       if (type == ACL_TYPE_ACCESS)
+               xname = POSIX_ACL_XATTR_ACCESS;
+       else
+               xname = POSIX_ACL_XATTR_DEFAULT;
+       size = strlen(xname) + 1;
+       if (list && size <= list_size)
+               memcpy(list, xname, size);
+       return size;
+ }
+ const struct xattr_handler posix_acl_access_xattr_handler = {
+       .prefix = POSIX_ACL_XATTR_ACCESS,
+       .flags = ACL_TYPE_ACCESS,
+       .list = posix_acl_xattr_list,
+       .get = posix_acl_xattr_get,
+       .set = posix_acl_xattr_set,
+ };
+ EXPORT_SYMBOL_GPL(posix_acl_access_xattr_handler);
+ const struct xattr_handler posix_acl_default_xattr_handler = {
+       .prefix = POSIX_ACL_XATTR_DEFAULT,
+       .flags = ACL_TYPE_DEFAULT,
+       .list = posix_acl_xattr_list,
+       .get = posix_acl_xattr_get,
+       .set = posix_acl_xattr_set,
+ };
+ EXPORT_SYMBOL_GPL(posix_acl_default_xattr_handler);
+ int simple_set_acl(struct inode *inode, struct posix_acl *acl, int type)
+ {
+       int error;
+       if (type == ACL_TYPE_ACCESS) {
+               error = posix_acl_equiv_mode(acl, &inode->i_mode);
+               if (error < 0)
+                       return 0;
+               if (error == 0)
+                       acl = NULL;
+       }
+       inode->i_ctime = CURRENT_TIME;
+       set_cached_acl(inode, type, acl);
+       return 0;
+ }
+ int simple_acl_create(struct inode *dir, struct inode *inode)
+ {
+       struct posix_acl *default_acl, *acl;
+       int error;
+       error = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
+       if (error)
+               return error;
+       set_cached_acl(inode, ACL_TYPE_DEFAULT, default_acl);
+       set_cached_acl(inode, ACL_TYPE_ACCESS, acl);
+       if (default_acl)
+               posix_acl_release(default_acl);
+       if (acl)
+               posix_acl_release(acl);
+       return 0;
+ }
diff --combined fs/reiserfs/reiserfs.h
index dfb617b2bad2ae1ada39a9ff36684793cfed51f1,24f068c33b4871f8366b8af899e2f176a24ea928..8d06adf899488a53e13e97b5d2973ca536e430b0
@@@ -608,14 -608,6 +608,6 @@@ int reiserfs_resize(struct super_block 
  
  #define SB_DISK_JOURNAL_HEAD(s) (SB_JOURNAL(s)->j_header_bh->)
  
- /* A safe version of the "bdevname", which returns the "s_id" field of
-  * a superblock or else "Null superblock" if the super block is NULL.
-  */
- static inline char *reiserfs_bdevname(struct super_block *s)
- {
-       return (s == NULL) ? "Null superblock" : s->s_id;
- }
  #define reiserfs_is_journal_aborted(journal) (unlikely (__reiserfs_is_journal_aborted (journal)))
  static inline int __reiserfs_is_journal_aborted(struct reiserfs_journal
                                                *journal)
@@@ -1958,6 -1950,8 +1950,6 @@@ struct treepath var = {.path_length = I
  #define MAX_US_INT 0xffff
  
  // reiserfs version 2 has max offset 60 bits. Version 1 - 32 bit offset
 -#define U32_MAX (~(__u32)0)
 -
  static inline loff_t max_reiserfs_offset(struct inode *inode)
  {
        if (get_inode_item_key_version(inode) == KEY_FORMAT_3_5)
diff --combined fs/xfs/xfs_iops.c
index 0ce1d759156e48ae092d566d30e713d7e597f29c,d47fbee3121e50fe9a0b4104fcb6df75c21e13be..f35d5c953ff953dcde133c4b55568d1920db3589
@@@ -123,7 -123,7 +123,7 @@@ xfs_vn_mknod
  {
        struct inode    *inode;
        struct xfs_inode *ip = NULL;
-       struct posix_acl *default_acl = NULL;
+       struct posix_acl *default_acl, *acl;
        struct xfs_name name;
        int             error;
  
                rdev = 0;
        }
  
-       if (IS_POSIXACL(dir)) {
-               default_acl = xfs_get_acl(dir, ACL_TYPE_DEFAULT);
-               if (IS_ERR(default_acl))
-                       return PTR_ERR(default_acl);
-               if (!default_acl)
-                       mode &= ~current_umask();
-       }
+       error = posix_acl_create(dir, &mode, &default_acl, &acl);
+       if (error)
+               return error;
  
        xfs_dentry_to_name(&name, dentry, mode);
        error = xfs_create(XFS_I(dir), &name, mode, rdev, &ip);
        if (unlikely(error))
                goto out_cleanup_inode;
  
+ #ifdef CONFIG_XFS_POSIX_ACL
        if (default_acl) {
-               error = -xfs_inherit_acl(inode, default_acl);
-               default_acl = NULL;
-               if (unlikely(error))
+               error = xfs_set_acl(inode, default_acl, ACL_TYPE_DEFAULT);
+               if (error)
                        goto out_cleanup_inode;
        }
+       if (acl) {
+               error = xfs_set_acl(inode, acl, ACL_TYPE_ACCESS);
+               if (error)
+                       goto out_cleanup_inode;
+       }
+ #endif
  
        d_instantiate(dentry, inode);
+  out_free_acl:
+       if (default_acl)
+               posix_acl_release(default_acl);
+       if (acl)
+               posix_acl_release(acl);
        return -error;
  
   out_cleanup_inode:
        xfs_cleanup_inode(dir, inode, dentry);
-  out_free_acl:
-       posix_acl_release(default_acl);
-       return -error;
+       goto out_free_acl;
  }
  
  STATIC int
@@@ -391,18 -394,6 +394,6 @@@ xfs_vn_follow_link
        return NULL;
  }
  
- STATIC void
- xfs_vn_put_link(
-       struct dentry   *dentry,
-       struct nameidata *nd,
-       void            *p)
- {
-       char            *s = nd_get_link(nd);
-       if (!IS_ERR(s))
-               kfree(s);
- }
  STATIC int
  xfs_vn_getattr(
        struct vfsmount         *mnt,
  
  static void
  xfs_setattr_mode(
 -      struct xfs_trans        *tp,
        struct xfs_inode        *ip,
        struct iattr            *iattr)
  {
 -      struct inode    *inode = VFS_I(ip);
 -      umode_t         mode = iattr->ia_mode;
 +      struct inode            *inode = VFS_I(ip);
 +      umode_t                 mode = iattr->ia_mode;
  
 -      ASSERT(tp);
        ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
  
        ip->i_d.di_mode &= S_IFMT;
        inode->i_mode |= mode & ~S_IFMT;
  }
  
 +static void
 +xfs_setattr_time(
 +      struct xfs_inode        *ip,
 +      struct iattr            *iattr)
 +{
 +      struct inode            *inode = VFS_I(ip);
 +
 +      ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
 +
 +      if (iattr->ia_valid & ATTR_ATIME) {
 +              inode->i_atime = iattr->ia_atime;
 +              ip->i_d.di_atime.t_sec = iattr->ia_atime.tv_sec;
 +              ip->i_d.di_atime.t_nsec = iattr->ia_atime.tv_nsec;
 +      }
 +      if (iattr->ia_valid & ATTR_CTIME) {
 +              inode->i_ctime = iattr->ia_ctime;
 +              ip->i_d.di_ctime.t_sec = iattr->ia_ctime.tv_sec;
 +              ip->i_d.di_ctime.t_nsec = iattr->ia_ctime.tv_nsec;
 +      }
 +      if (iattr->ia_valid & ATTR_MTIME) {
 +              inode->i_mtime = iattr->ia_mtime;
 +              ip->i_d.di_mtime.t_sec = iattr->ia_mtime.tv_sec;
 +              ip->i_d.di_mtime.t_nsec = iattr->ia_mtime.tv_nsec;
 +      }
 +}
 +
  int
  xfs_setattr_nonsize(
        struct xfs_inode        *ip,
                }
        }
  
 -      /*
 -       * Change file access modes.
 -       */
        if (mask & ATTR_MODE)
 -              xfs_setattr_mode(tp, ip, iattr);
 -
 -      /*
 -       * Change file access or modified times.
 -       */
 -      if (mask & ATTR_ATIME) {
 -              inode->i_atime = iattr->ia_atime;
 -              ip->i_d.di_atime.t_sec = iattr->ia_atime.tv_sec;
 -              ip->i_d.di_atime.t_nsec = iattr->ia_atime.tv_nsec;
 -      }
 -      if (mask & ATTR_CTIME) {
 -              inode->i_ctime = iattr->ia_ctime;
 -              ip->i_d.di_ctime.t_sec = iattr->ia_ctime.tv_sec;
 -              ip->i_d.di_ctime.t_nsec = iattr->ia_ctime.tv_nsec;
 -      }
 -      if (mask & ATTR_MTIME) {
 -              inode->i_mtime = iattr->ia_mtime;
 -              ip->i_d.di_mtime.t_sec = iattr->ia_mtime.tv_sec;
 -              ip->i_d.di_mtime.t_nsec = iattr->ia_mtime.tv_nsec;
 -      }
 +              xfs_setattr_mode(ip, iattr);
 +      if (mask & (ATTR_ATIME|ATTR_CTIME|ATTR_MTIME))
 +              xfs_setattr_time(ip, iattr);
  
        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
  
         *           Posix ACL code seems to care about this issue either.
         */
        if ((mask & ATTR_MODE) && !(flags & XFS_ATTR_NOACL)) {
-               error = -xfs_acl_chmod(inode);
+               error = -posix_acl_chmod(inode, inode->i_mode);
                if (error)
                        return XFS_ERROR(error);
        }
@@@ -872,10 -859,22 +863,10 @@@ xfs_setattr_size
                xfs_inode_clear_eofblocks_tag(ip);
        }
  
 -      /*
 -       * Change file access modes.
 -       */
        if (mask & ATTR_MODE)
 -              xfs_setattr_mode(tp, ip, iattr);
 -
 -      if (mask & ATTR_CTIME) {
 -              inode->i_ctime = iattr->ia_ctime;
 -              ip->i_d.di_ctime.t_sec = iattr->ia_ctime.tv_sec;
 -              ip->i_d.di_ctime.t_nsec = iattr->ia_ctime.tv_nsec;
 -      }
 -      if (mask & ATTR_MTIME) {
 -              inode->i_mtime = iattr->ia_mtime;
 -              ip->i_d.di_mtime.t_sec = iattr->ia_mtime.tv_sec;
 -              ip->i_d.di_mtime.t_nsec = iattr->ia_mtime.tv_nsec;
 -      }
 +              xfs_setattr_mode(ip, iattr);
 +      if (mask & (ATTR_ATIME|ATTR_CTIME|ATTR_MTIME))
 +              xfs_setattr_time(ip, iattr);
  
        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
  
@@@ -1045,6 -1044,7 +1036,7 @@@ xfs_vn_fiemap
  
  static const struct inode_operations xfs_inode_operations = {
        .get_acl                = xfs_get_acl,
+       .set_acl                = xfs_set_acl,
        .getattr                = xfs_vn_getattr,
        .setattr                = xfs_vn_setattr,
        .setxattr               = generic_setxattr,
@@@ -1072,6 -1072,7 +1064,7 @@@ static const struct inode_operations xf
        .mknod                  = xfs_vn_mknod,
        .rename                 = xfs_vn_rename,
        .get_acl                = xfs_get_acl,
+       .set_acl                = xfs_set_acl,
        .getattr                = xfs_vn_getattr,
        .setattr                = xfs_vn_setattr,
        .setxattr               = generic_setxattr,
@@@ -1098,6 -1099,7 +1091,7 @@@ static const struct inode_operations xf
        .mknod                  = xfs_vn_mknod,
        .rename                 = xfs_vn_rename,
        .get_acl                = xfs_get_acl,
+       .set_acl                = xfs_set_acl,
        .getattr                = xfs_vn_getattr,
        .setattr                = xfs_vn_setattr,
        .setxattr               = generic_setxattr,
  static const struct inode_operations xfs_symlink_inode_operations = {
        .readlink               = generic_readlink,
        .follow_link            = xfs_vn_follow_link,
-       .put_link               = xfs_vn_put_link,
-       .get_acl                = xfs_get_acl,
+       .put_link               = kfree_put_link,
        .getattr                = xfs_vn_getattr,
        .setattr                = xfs_vn_setattr,
        .setxattr               = generic_setxattr,
index 833099bf8090a24f5be28f6b074c918d5d677119,6b12b3d57e908d0b3627a016491de7f891489d67..3e96a6a7610338ff8ddd825a21ddc9bc5fe52e8b
@@@ -39,6 -39,9 +39,6 @@@ struct posix_acl_entry 
        union {
                kuid_t          e_uid;
                kgid_t          e_gid;
 -#ifndef CONFIG_UIDGID_STRICT_TYPE_CHECKS
 -              unsigned int    e_id;
 -#endif
        };
  };
  
@@@ -85,25 -88,124 +85,60 @@@ extern int posix_acl_valid(const struc
  extern int posix_acl_permission(struct inode *, const struct posix_acl *, int);
  extern struct posix_acl *posix_acl_from_mode(umode_t, gfp_t);
  extern int posix_acl_equiv_mode(const struct posix_acl *, umode_t *);
- extern int posix_acl_create(struct posix_acl **, gfp_t, umode_t *);
- extern int posix_acl_chmod(struct posix_acl **, gfp_t, umode_t);
+ extern int __posix_acl_create(struct posix_acl **, gfp_t, umode_t *);
+ extern int __posix_acl_chmod(struct posix_acl **, gfp_t, umode_t);
  
  extern struct posix_acl *get_posix_acl(struct inode *, int);
  extern int set_posix_acl(struct inode *, int, struct posix_acl *);
  
 -static inline struct posix_acl **acl_by_type(struct inode *inode, int type)
 -{
 -      switch (type) {
 -      case ACL_TYPE_ACCESS:
 -              return &inode->i_acl;
 -      case ACL_TYPE_DEFAULT:
 -              return &inode->i_default_acl;
 -      default:
 -              BUG();
 -      }
 -}
 -
 -static inline struct posix_acl *get_cached_acl(struct inode *inode, int type)
 -{
 -      struct posix_acl **p = acl_by_type(inode, type);
 -      struct posix_acl *acl = ACCESS_ONCE(*p);
 -      if (acl) {
 -              spin_lock(&inode->i_lock);
 -              acl = *p;
 -              if (acl != ACL_NOT_CACHED)
 -                      acl = posix_acl_dup(acl);
 -              spin_unlock(&inode->i_lock);
 -      }
 -      return acl;
 -}
 -
 -static inline struct posix_acl *get_cached_acl_rcu(struct inode *inode, int type)
 -{
 -      return rcu_dereference(*acl_by_type(inode, type));
 -}
 -
 -static inline void set_cached_acl(struct inode *inode,
 -                                int type,
 -                                struct posix_acl *acl)
 -{
 -      struct posix_acl **p = acl_by_type(inode, type);
 -      struct posix_acl *old;
 -      spin_lock(&inode->i_lock);
 -      old = *p;
 -      rcu_assign_pointer(*p, posix_acl_dup(acl));
 -      spin_unlock(&inode->i_lock);
 -      if (old != ACL_NOT_CACHED)
 -              posix_acl_release(old);
 -}
 -
 -static inline void forget_cached_acl(struct inode *inode, int type)
 -{
 -      struct posix_acl **p = acl_by_type(inode, type);
 -      struct posix_acl *old;
 -      spin_lock(&inode->i_lock);
 -      old = *p;
 -      *p = ACL_NOT_CACHED;
 -      spin_unlock(&inode->i_lock);
 -      if (old != ACL_NOT_CACHED)
 -              posix_acl_release(old);
 -}
 -
 -static inline void forget_all_cached_acls(struct inode *inode)
 -{
 -      struct posix_acl *old_access, *old_default;
 -      spin_lock(&inode->i_lock);
 -      old_access = inode->i_acl;
 -      old_default = inode->i_default_acl;
 -      inode->i_acl = inode->i_default_acl = ACL_NOT_CACHED;
 -      spin_unlock(&inode->i_lock);
 -      if (old_access != ACL_NOT_CACHED)
 -              posix_acl_release(old_access);
 -      if (old_default != ACL_NOT_CACHED)
 -              posix_acl_release(old_default);
 -}
+ #ifdef CONFIG_FS_POSIX_ACL
+ extern int posix_acl_chmod(struct inode *, umode_t);
+ extern int posix_acl_create(struct inode *, umode_t *, struct posix_acl **,
+               struct posix_acl **);
+ extern int simple_set_acl(struct inode *, struct posix_acl *, int);
+ extern int simple_acl_create(struct inode *, struct inode *);
 +struct posix_acl **acl_by_type(struct inode *inode, int type);
 +struct posix_acl *get_cached_acl(struct inode *inode, int type);
 +struct posix_acl *get_cached_acl_rcu(struct inode *inode, int type);
 +void set_cached_acl(struct inode *inode, int type, struct posix_acl *acl);
 +void forget_cached_acl(struct inode *inode, int type);
 +void forget_all_cached_acls(struct inode *inode);
  
  static inline void cache_no_acl(struct inode *inode)
  {
- #ifdef CONFIG_FS_POSIX_ACL
        inode->i_acl = NULL;
        inode->i_default_acl = NULL;
- #endif
  }
+ #else
+ static inline int posix_acl_chmod(struct inode *inode, umode_t mode)
+ {
+       return 0;
+ }
+ #define simple_set_acl                NULL
+ static inline int simple_acl_create(struct inode *dir, struct inode *inode)
+ {
+       return 0;
+ }
+ static inline void cache_no_acl(struct inode *inode)
+ {
+ }
+ static inline int posix_acl_create(struct inode *inode, umode_t *mode,
+               struct posix_acl **default_acl, struct posix_acl **acl)
+ {
+       *default_acl = *acl = NULL;
+       return 0;
+ }
+ static inline void forget_all_cached_acls(struct inode *inode)
+ {
+ }
+ #endif /* CONFIG_FS_POSIX_ACL */
+ struct posix_acl *get_acl(struct inode *inode, int type);
  
  #endif  /* __LINUX_POSIX_ACL_H */
diff --combined include/linux/rcupdate.h
index 3e355c688618e66391d535de3e183bf9c9ec8cba,a2482cf90b6b1cfcfd20666914ef1a900c437578..72bf3a01a4ee67ac8908212c3de3897d383a2161
@@@ -50,13 -50,13 +50,13 @@@ extern int rcutorture_runnable; /* for 
  #endif /* #ifdef CONFIG_RCU_TORTURE_TEST */
  
  #if defined(CONFIG_TREE_RCU) || defined(CONFIG_TREE_PREEMPT_RCU)
 -extern void rcutorture_record_test_transition(void);
 -extern void rcutorture_record_progress(unsigned long vernum);
 -extern void do_trace_rcu_torture_read(const char *rcutorturename,
 -                                    struct rcu_head *rhp,
 -                                    unsigned long secs,
 -                                    unsigned long c_old,
 -                                    unsigned long c);
 +void rcutorture_record_test_transition(void);
 +void rcutorture_record_progress(unsigned long vernum);
 +void do_trace_rcu_torture_read(const char *rcutorturename,
 +                             struct rcu_head *rhp,
 +                             unsigned long secs,
 +                             unsigned long c_old,
 +                             unsigned long c);
  #else
  static inline void rcutorture_record_test_transition(void)
  {
@@@ -65,11 -65,11 +65,11 @@@ static inline void rcutorture_record_pr
  {
  }
  #ifdef CONFIG_RCU_TRACE
 -extern void do_trace_rcu_torture_read(const char *rcutorturename,
 -                                    struct rcu_head *rhp,
 -                                    unsigned long secs,
 -                                    unsigned long c_old,
 -                                    unsigned long c);
 +void do_trace_rcu_torture_read(const char *rcutorturename,
 +                             struct rcu_head *rhp,
 +                             unsigned long secs,
 +                             unsigned long c_old,
 +                             unsigned long c);
  #else
  #define do_trace_rcu_torture_read(rcutorturename, rhp, secs, c_old, c) \
        do { } while (0)
   * if CPU A and CPU B are the same CPU (but again only if the system has
   * more than one CPU).
   */
 -extern void call_rcu(struct rcu_head *head,
 -                            void (*func)(struct rcu_head *head));
 +void call_rcu(struct rcu_head *head,
 +            void (*func)(struct rcu_head *head));
  
  #else /* #ifdef CONFIG_PREEMPT_RCU */
  
   * See the description of call_rcu() for more detailed information on
   * memory ordering guarantees.
   */
 -extern void call_rcu_bh(struct rcu_head *head,
 -                      void (*func)(struct rcu_head *head));
 +void call_rcu_bh(struct rcu_head *head,
 +               void (*func)(struct rcu_head *head));
  
  /**
   * call_rcu_sched() - Queue an RCU for invocation after sched grace period.
   * See the description of call_rcu() for more detailed information on
   * memory ordering guarantees.
   */
 -extern void call_rcu_sched(struct rcu_head *head,
 -                         void (*func)(struct rcu_head *rcu));
 +void call_rcu_sched(struct rcu_head *head,
 +                  void (*func)(struct rcu_head *rcu));
  
 -extern void synchronize_sched(void);
 +void synchronize_sched(void);
  
  #ifdef CONFIG_PREEMPT_RCU
  
 -extern void __rcu_read_lock(void);
 -extern void __rcu_read_unlock(void);
 -extern void rcu_read_unlock_special(struct task_struct *t);
 +void __rcu_read_lock(void);
 +void __rcu_read_unlock(void);
 +void rcu_read_unlock_special(struct task_struct *t);
  void synchronize_rcu(void);
  
  /*
@@@ -216,19 -216,19 +216,19 @@@ static inline int rcu_preempt_depth(voi
  #endif /* #else #ifdef CONFIG_PREEMPT_RCU */
  
  /* Internal to kernel */
 -extern void rcu_init(void);
 -extern void rcu_sched_qs(int cpu);
 -extern void rcu_bh_qs(int cpu);
 -extern void rcu_check_callbacks(int cpu, int user);
 +void rcu_init(void);
 +void rcu_sched_qs(int cpu);
 +void rcu_bh_qs(int cpu);
 +void rcu_check_callbacks(int cpu, int user);
  struct notifier_block;
 -extern void rcu_idle_enter(void);
 -extern void rcu_idle_exit(void);
 -extern void rcu_irq_enter(void);
 -extern void rcu_irq_exit(void);
 +void rcu_idle_enter(void);
 +void rcu_idle_exit(void);
 +void rcu_irq_enter(void);
 +void rcu_irq_exit(void);
  
  #ifdef CONFIG_RCU_USER_QS
 -extern void rcu_user_enter(void);
 -extern void rcu_user_exit(void);
 +void rcu_user_enter(void);
 +void rcu_user_exit(void);
  #else
  static inline void rcu_user_enter(void) { }
  static inline void rcu_user_exit(void) { }
@@@ -262,7 -262,7 +262,7 @@@ static inline void rcu_user_hooks_switc
        } while (0)
  
  #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) || defined(CONFIG_SMP)
 -extern bool __rcu_is_watching(void);
 +bool __rcu_is_watching(void);
  #endif /* #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) || defined(CONFIG_SMP) */
  
  /*
@@@ -289,8 -289,8 +289,8 @@@ void wait_rcu_gp(call_rcu_func_t crf)
   * initialization.
   */
  #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD
 -extern void init_rcu_head_on_stack(struct rcu_head *head);
 -extern void destroy_rcu_head_on_stack(struct rcu_head *head);
 +void init_rcu_head_on_stack(struct rcu_head *head);
 +void destroy_rcu_head_on_stack(struct rcu_head *head);
  #else /* !CONFIG_DEBUG_OBJECTS_RCU_HEAD */
  static inline void init_rcu_head_on_stack(struct rcu_head *head)
  {
@@@ -325,7 -325,6 +325,7 @@@ static inline void rcu_lock_release(str
  extern struct lockdep_map rcu_lock_map;
  extern struct lockdep_map rcu_bh_lock_map;
  extern struct lockdep_map rcu_sched_lock_map;
 +extern struct lockdep_map rcu_callback_map;
  extern int debug_lockdep_rcu_enabled(void);
  
  /**
@@@ -363,7 -362,7 +363,7 @@@ static inline int rcu_read_lock_held(vo
   * rcu_read_lock_bh_held() is defined out of line to avoid #include-file
   * hell.
   */
 -extern int rcu_read_lock_bh_held(void);
 +int rcu_read_lock_bh_held(void);
  
  /**
   * rcu_read_lock_sched_held() - might we be in RCU-sched read-side critical section?
@@@ -449,8 -448,6 +449,6 @@@ static inline int rcu_read_lock_sched_h
  
  #ifdef CONFIG_PROVE_RCU
  
- int rcu_my_thread_group_empty(void);
  /**
   * rcu_lockdep_assert - emit lockdep splat if specified condition not met
   * @c: condition to check
@@@ -549,48 -546,10 +547,48 @@@ static inline void rcu_preempt_sleep_ch
                smp_read_barrier_depends(); \
                (_________p1); \
        })
 -#define __rcu_assign_pointer(p, v, space) \
 +
 +/**
 + * RCU_INITIALIZER() - statically initialize an RCU-protected global variable
 + * @v: The value to statically initialize with.
 + */
 +#define RCU_INITIALIZER(v) (typeof(*(v)) __force __rcu *)(v)
 +
 +/**
 + * rcu_assign_pointer() - assign to RCU-protected pointer
 + * @p: pointer to assign to
 + * @v: value to assign (publish)
 + *
 + * Assigns the specified value to the specified RCU-protected
 + * pointer, ensuring that any concurrent RCU readers will see
 + * any prior initialization.
 + *
 + * Inserts memory barriers on architectures that require them
 + * (which is most of them), and also prevents the compiler from
 + * reordering the code that initializes the structure after the pointer
 + * assignment.  More importantly, this call documents which pointers
 + * will be dereferenced by RCU read-side code.
 + *
 + * In some special cases, you may use RCU_INIT_POINTER() instead
 + * of rcu_assign_pointer().  RCU_INIT_POINTER() is a bit faster due
 + * to the fact that it does not constrain either the CPU or the compiler.
 + * That said, using RCU_INIT_POINTER() when you should have used
 + * rcu_assign_pointer() is a very bad thing that results in
 + * impossible-to-diagnose memory corruption.  So please be careful.
 + * See the RCU_INIT_POINTER() comment header for details.
 + *
 + * Note that rcu_assign_pointer() evaluates each of its arguments only
 + * once, appearances notwithstanding.  One of the "extra" evaluations
 + * is in typeof() and the other visible only to sparse (__CHECKER__),
 + * neither of which actually execute the argument.  As with most cpp
 + * macros, this execute-arguments-only-once property is important, so
 + * please be careful when making changes to rcu_assign_pointer() and the
 + * other macros that it invokes.
 + */
 +#define rcu_assign_pointer(p, v) \
        do { \
                smp_wmb(); \
 -              (p) = (typeof(*v) __force space *)(v); \
 +              ACCESS_ONCE(p) = RCU_INITIALIZER(v); \
        } while (0)
  
  
@@@ -928,6 -887,32 +926,6 @@@ static inline notrace void rcu_read_unl
        preempt_enable_notrace();
  }
  
 -/**
 - * rcu_assign_pointer() - assign to RCU-protected pointer
 - * @p: pointer to assign to
 - * @v: value to assign (publish)
 - *
 - * Assigns the specified value to the specified RCU-protected
 - * pointer, ensuring that any concurrent RCU readers will see
 - * any prior initialization.
 - *
 - * Inserts memory barriers on architectures that require them
 - * (which is most of them), and also prevents the compiler from
 - * reordering the code that initializes the structure after the pointer
 - * assignment.  More importantly, this call documents which pointers
 - * will be dereferenced by RCU read-side code.
 - *
 - * In some special cases, you may use RCU_INIT_POINTER() instead
 - * of rcu_assign_pointer().  RCU_INIT_POINTER() is a bit faster due
 - * to the fact that it does not constrain either the CPU or the compiler.
 - * That said, using RCU_INIT_POINTER() when you should have used
 - * rcu_assign_pointer() is a very bad thing that results in
 - * impossible-to-diagnose memory corruption.  So please be careful.
 - * See the RCU_INIT_POINTER() comment header for details.
 - */
 -#define rcu_assign_pointer(p, v) \
 -      __rcu_assign_pointer((p), (v), __rcu)
 -
  /**
   * RCU_INIT_POINTER() - initialize an RCU protected pointer
   *
   */
  #define RCU_INIT_POINTER(p, v) \
        do { \
 -              p = (typeof(*v) __force __rcu *)(v); \
 +              p = RCU_INITIALIZER(v); \
        } while (0)
  
  /**
   * GCC-style initialization for an RCU-protected pointer in a structure field.
   */
  #define RCU_POINTER_INITIALIZER(p, v) \
 -              .p = (typeof(*v) __force __rcu *)(v)
 +              .p = RCU_INITIALIZER(v)
  
  /*
   * Does the specified offset indicate that the corresponding rcu_head
        __kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head))
  
  #ifdef CONFIG_RCU_NOCB_CPU
 -extern bool rcu_is_nocb_cpu(int cpu);
 +bool rcu_is_nocb_cpu(int cpu);
  #else
  static inline bool rcu_is_nocb_cpu(int cpu) { return false; }
  #endif /* #else #ifdef CONFIG_RCU_NOCB_CPU */
  
  /* Only for use by adaptive-ticks code. */
  #ifdef CONFIG_NO_HZ_FULL_SYSIDLE
 -extern bool rcu_sys_is_idle(void);
 -extern void rcu_sysidle_force_exit(void);
 +bool rcu_sys_is_idle(void);
 +void rcu_sysidle_force_exit(void);
  #else /* #ifdef CONFIG_NO_HZ_FULL_SYSIDLE */
  
  static inline bool rcu_sys_is_idle(void)
diff --combined kernel/rcu/update.c
index 802365ccd591826a60e08009a3927c9bed8c69bf,a3596c8ec9e49ab4e58c36ddb60211d9f929aa36..c54609faf233ba21a49835d32a9132eb56853f14
@@@ -128,11 -128,6 +128,11 @@@ struct lockdep_map rcu_sched_lock_map 
        STATIC_LOCKDEP_MAP_INIT("rcu_read_lock_sched", &rcu_sched_lock_key);
  EXPORT_SYMBOL_GPL(rcu_sched_lock_map);
  
 +static struct lock_class_key rcu_callback_key;
 +struct lockdep_map rcu_callback_map =
 +      STATIC_LOCKDEP_MAP_INIT("rcu_callback", &rcu_callback_key);
 +EXPORT_SYMBOL_GPL(rcu_callback_map);
 +
  int notrace debug_lockdep_rcu_enabled(void)
  {
        return rcu_scheduler_active && debug_locks &&
@@@ -200,17 -195,6 +200,6 @@@ void wait_rcu_gp(call_rcu_func_t crf
  }
  EXPORT_SYMBOL_GPL(wait_rcu_gp);
  
- #ifdef CONFIG_PROVE_RCU
- /*
-  * wrapper function to avoid #include problems.
-  */
- int rcu_my_thread_group_empty(void)
- {
-       return thread_group_empty(current);
- }
- EXPORT_SYMBOL_GPL(rcu_my_thread_group_empty);
- #endif /* #ifdef CONFIG_PROVE_RCU */
  #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD
  static inline void debug_init_rcu_head(struct rcu_head *head)
  {
diff --combined mm/filemap.c
index 7a7f3e0db7384515b6e266029ef930e5c775ec0d,01842867c9d27bbb42ffabaffcb7ed9596164e7b..d56d3c145b9f26d3210ec8ad17430be6c46af2a9
@@@ -409,9 -409,9 +409,9 @@@ int replace_page_cache_page(struct pag
  {
        int error;
  
 -      VM_BUG_ON(!PageLocked(old));
 -      VM_BUG_ON(!PageLocked(new));
 -      VM_BUG_ON(new->mapping);
 +      VM_BUG_ON_PAGE(!PageLocked(old), old);
 +      VM_BUG_ON_PAGE(!PageLocked(new), new);
 +      VM_BUG_ON_PAGE(new->mapping, new);
  
        error = radix_tree_preload(gfp_mask & ~__GFP_HIGHMEM);
        if (!error) {
@@@ -461,8 -461,8 +461,8 @@@ int add_to_page_cache_locked(struct pag
  {
        int error;
  
 -      VM_BUG_ON(!PageLocked(page));
 -      VM_BUG_ON(PageSwapBacked(page));
 +      VM_BUG_ON_PAGE(!PageLocked(page), page);
 +      VM_BUG_ON_PAGE(PageSwapBacked(page), page);
  
        error = mem_cgroup_cache_charge(page, current->mm,
                                        gfp_mask & GFP_RECLAIM_MASK);
@@@ -607,7 -607,7 +607,7 @@@ EXPORT_SYMBOL_GPL(add_page_wait_queue)
   */
  void unlock_page(struct page *page)
  {
 -      VM_BUG_ON(!PageLocked(page));
 +      VM_BUG_ON_PAGE(!PageLocked(page), page);
        clear_bit_unlock(PG_locked, &page->flags);
        smp_mb__after_clear_bit();
        wake_up_page(page, PG_locked);
@@@ -760,7 -760,7 +760,7 @@@ repeat
                        page_cache_release(page);
                        goto repeat;
                }
 -              VM_BUG_ON(page->index != offset);
 +              VM_BUG_ON_PAGE(page->index != offset, page);
        }
        return page;
  }
@@@ -1428,30 -1428,28 +1428,28 @@@ generic_file_aio_read(struct kiocb *ioc
                if (!count)
                        goto out; /* skip atime */
                size = i_size_read(inode);
-               if (pos < size) {
-                       retval = filemap_write_and_wait_range(mapping, pos,
+               retval = filemap_write_and_wait_range(mapping, pos,
                                        pos + iov_length(iov, nr_segs) - 1);
-                       if (!retval) {
-                               retval = mapping->a_ops->direct_IO(READ, iocb,
-                                                       iov, pos, nr_segs);
-                       }
-                       if (retval > 0) {
-                               *ppos = pos + retval;
-                               count -= retval;
-                       }
+               if (!retval) {
+                       retval = mapping->a_ops->direct_IO(READ, iocb,
+                                                          iov, pos, nr_segs);
+               }
+               if (retval > 0) {
+                       *ppos = pos + retval;
+                       count -= retval;
+               }
  
-                       /*
-                        * Btrfs can have a short DIO read if we encounter
-                        * compressed extents, so if there was an error, or if
-                        * we've already read everything we wanted to, or if
-                        * there was a short read because we hit EOF, go ahead
-                        * and return.  Otherwise fallthrough to buffered io for
-                        * the rest of the read.
-                        */
-                       if (retval < 0 || !count || *ppos >= size) {
-                               file_accessed(filp);
-                               goto out;
-                       }
+               /*
+                * Btrfs can have a short DIO read if we encounter
+                * compressed extents, so if there was an error, or if
+                * we've already read everything we wanted to, or if
+                * there was a short read because we hit EOF, go ahead
+                * and return.  Otherwise fallthrough to buffered io for
+                * the rest of the read.
+                */
+               if (retval < 0 || !count || *ppos >= size) {
+                       file_accessed(filp);
+                       goto out;
                }
        }
  
@@@ -1656,7 -1654,7 +1654,7 @@@ retry_find
                put_page(page);
                goto retry_find;
        }
 -      VM_BUG_ON(page->index != offset);
 +      VM_BUG_ON_PAGE(page->index != offset, page);
  
        /*
         * We have a locked page in the page cache, now we need to check
diff --combined mm/shmem.c
index 8156f95ec0cfc638d93e8f6175e107384c83d7dd,b21ca543458c244e8a28c75305e14c88f12aeb4d..1f18c9d0d93ea270ab01054b2febbdd6a7eb6f56
@@@ -45,7 -45,7 +45,7 @@@ static struct vfsmount *shm_mnt
  #include <linux/xattr.h>
  #include <linux/exportfs.h>
  #include <linux/posix_acl.h>
- #include <linux/generic_acl.h>
+ #include <linux/posix_acl_xattr.h>
  #include <linux/mman.h>
  #include <linux/string.h>
  #include <linux/slab.h>
@@@ -285,8 -285,8 +285,8 @@@ static int shmem_add_to_page_cache(stru
  {
        int error;
  
 -      VM_BUG_ON(!PageLocked(page));
 -      VM_BUG_ON(!PageSwapBacked(page));
 +      VM_BUG_ON_PAGE(!PageLocked(page), page);
 +      VM_BUG_ON_PAGE(!PageSwapBacked(page), page);
  
        page_cache_get(page);
        page->mapping = mapping;
@@@ -491,7 -491,7 +491,7 @@@ static void shmem_undo_range(struct ino
                                continue;
                        if (!unfalloc || !PageUptodate(page)) {
                                if (page->mapping == mapping) {
 -                                      VM_BUG_ON(PageWriteback(page));
 +                                      VM_BUG_ON_PAGE(PageWriteback(page), page);
                                        truncate_inode_page(mapping, page);
                                }
                        }
                        lock_page(page);
                        if (!unfalloc || !PageUptodate(page)) {
                                if (page->mapping == mapping) {
 -                                      VM_BUG_ON(PageWriteback(page));
 +                                      VM_BUG_ON_PAGE(PageWriteback(page), page);
                                        truncate_inode_page(mapping, page);
                                }
                        }
@@@ -620,10 -620,8 +620,8 @@@ static int shmem_setattr(struct dentry 
        }
  
        setattr_copy(inode, attr);
- #ifdef CONFIG_TMPFS_POSIX_ACL
        if (attr->ia_valid & ATTR_MODE)
-               error = generic_acl_chmod(inode);
- #endif
+               error = posix_acl_chmod(inode, inode->i_mode);
        return error;
  }
  
@@@ -1937,22 -1935,14 +1935,14 @@@ shmem_mknod(struct inode *dir, struct d
  
        inode = shmem_get_inode(dir->i_sb, dir, mode, dev, VM_NORESERVE);
        if (inode) {
- #ifdef CONFIG_TMPFS_POSIX_ACL
-               error = generic_acl_init(inode, dir);
-               if (error) {
-                       iput(inode);
-                       return error;
-               }
- #endif
+               error = simple_acl_create(dir, inode);
+               if (error)
+                       goto out_iput;
                error = security_inode_init_security(inode, dir,
                                                     &dentry->d_name,
                                                     shmem_initxattrs, NULL);
-               if (error) {
-                       if (error != -EOPNOTSUPP) {
-                               iput(inode);
-                               return error;
-                       }
-               }
+               if (error && error != -EOPNOTSUPP)
+                       goto out_iput;
  
                error = 0;
                dir->i_size += BOGO_DIRENT_SIZE;
                dget(dentry); /* Extra count - pin the dentry in core */
        }
        return error;
+ out_iput:
+       iput(inode);
+       return error;
  }
  
  static int
@@@ -1974,24 -1967,17 +1967,17 @@@ shmem_tmpfile(struct inode *dir, struc
                error = security_inode_init_security(inode, dir,
                                                     NULL,
                                                     shmem_initxattrs, NULL);
-               if (error) {
-                       if (error != -EOPNOTSUPP) {
-                               iput(inode);
-                               return error;
-                       }
-               }
- #ifdef CONFIG_TMPFS_POSIX_ACL
-               error = generic_acl_init(inode, dir);
-               if (error) {
-                       iput(inode);
-                       return error;
-               }
- #else
-               error = 0;
- #endif
+               if (error && error != -EOPNOTSUPP)
+                       goto out_iput;
+               error = simple_acl_create(dir, inode);
+               if (error)
+                       goto out_iput;
                d_tmpfile(dentry, inode);
        }
        return error;
+ out_iput:
+       iput(inode);
+       return error;
  }
  
  static int shmem_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
@@@ -2223,8 -2209,8 +2209,8 @@@ static int shmem_initxattrs(struct inod
  
  static const struct xattr_handler *shmem_xattr_handlers[] = {
  #ifdef CONFIG_TMPFS_POSIX_ACL
-       &generic_acl_access_handler,
-       &generic_acl_default_handler,
+       &posix_acl_access_xattr_handler,
+       &posix_acl_default_xattr_handler,
  #endif
        NULL
  };
@@@ -2740,6 -2726,7 +2726,7 @@@ static const struct inode_operations sh
        .getxattr       = shmem_getxattr,
        .listxattr      = shmem_listxattr,
        .removexattr    = shmem_removexattr,
+       .set_acl        = simple_set_acl,
  #endif
  };
  
@@@ -2764,6 -2751,7 +2751,7 @@@ static const struct inode_operations sh
  #endif
  #ifdef CONFIG_TMPFS_POSIX_ACL
        .setattr        = shmem_setattr,
+       .set_acl        = simple_set_acl,
  #endif
  };
  
@@@ -2776,6 -2764,7 +2764,7 @@@ static const struct inode_operations sh
  #endif
  #ifdef CONFIG_TMPFS_POSIX_ACL
        .setattr        = shmem_setattr,
+       .set_acl        = simple_set_acl,
  #endif
  };