- Update to 3.1-rc3.
authorJeff Mahoney <jeffm@suse.com>
Wed, 24 Aug 2011 18:51:06 +0000 (14:51 -0400)
committerJeff Mahoney <jeffm@suse.com>
Wed, 24 Aug 2011 18:51:06 +0000 (14:51 -0400)
  - Eliminated 8 patches.
  - Xen is disabled.

suse-commit: eccefcca39dc56723338addef30fc7aaf160902b

95 files changed:
1  2 
Documentation/kernel-parameters.txt
Documentation/sysctl/kernel.txt
Makefile
arch/ia64/Kconfig
arch/powerpc/kernel/prom_init.c
arch/powerpc/platforms/pseries/setup.c
arch/s390/Kconfig
arch/x86/Kconfig
arch/x86/Makefile
arch/x86/kernel/acpi/boot.c
arch/x86/kernel/apm_32.c
arch/x86/kernel/cpu/perf_event.c
arch/x86/kernel/dumpstack_64.c
arch/x86/kernel/entry_32.S
arch/x86/kernel/entry_64.S
arch/x86/kernel/stacktrace.c
arch/x86/kernel/vmlinux.lds.S
arch/x86/kvm/svm.c
arch/x86/kvm/x86.c
arch/x86/oprofile/backtrace.c
block/genhd.c
drivers/acpi/ec_sys.c
drivers/acpi/thermal.c
drivers/char/Kconfig
drivers/char/Makefile
drivers/connector/cn_proc.c
drivers/hid/hid-core.c
drivers/hid/hid-ids.h
drivers/input/mouse/synaptics.c
drivers/input/mouse/synaptics.h
drivers/md/Kconfig
drivers/md/dm-mpath.c
drivers/md/dm-table.c
drivers/md/dm.c
drivers/net/ehea/ehea_main.c
drivers/net/tulip/tulip_core.c
drivers/net/wireless/b43/main.c
drivers/scsi/device_handler/scsi_dh_rdac.c
drivers/scsi/scsi_devinfo.c
drivers/scsi/scsi_lib.c
drivers/staging/hv/vmbus_drv.c
drivers/tty/n_tty.c
drivers/tty/serial/8250.c
drivers/video/Kconfig
fs/Kconfig
fs/Makefile
fs/ext4/Makefile
fs/ext4/acl.c
fs/ext4/ext4.h
fs/ext4/file.c
fs/ext4/ialloc.c
fs/ext4/inode.c
fs/ext4/namei.c
fs/ext4/richacl.c
fs/ext4/richacl.h
fs/ext4/super.c
fs/namei.c
fs/nfs/dir.c
fs/nfs/inode.c
fs/partitions/check.c
fs/reiserfs/super.c
fs/richacl_base.c
fs/richacl_inode.c
fs/super.c
include/linux/blkdev.h
include/linux/device.h
include/linux/fb.h
include/linux/fs.h
include/linux/genhd.h
include/linux/kernel.h
include/linux/mm.h
include/linux/module.h
include/linux/nfs_fs.h
include/linux/richacl.h
include/scsi/scsi_device.h
init/Kconfig
init/main.c
kernel/Kconfig.preempt
kernel/Makefile
kernel/module.c
kernel/panic.c
kernel/printk.c
kernel/sysctl.c
kernel/sysctl_binary.c
lib/Kconfig.debug
mm/page_alloc.c
mm/thrash.c
mm/truncate.c
net/bridge/br_if.c
scripts/Makefile.build
scripts/Makefile.modpost
scripts/genksyms/genksyms.c
scripts/kconfig/Makefile
scripts/mod/modpost.c
security/apparmor/lsm.c

@@@ -2569,14 -2563,11 +2563,19 @@@ bytes respectively. Such letter suffixe
        unknown_nmi_panic
                        [X86] Cause panic on unknown NMI.
  
 +      unsupported     Allow loading of unsupported kernel modules:
 +                      0 = only allow supported modules,
 +                      1 = warn when loading unsupported modules,
 +                      2 = don't warn.
 +
 +                      CONFIG_ENTERPRISE_SUPPORT must be enabled for this
 +                      to have any effect.
 +
+       usbcore.authorized_default=
+                       [USB] Default USB device authorization:
+                       (default -1 = authorized except for wireless USB,
+                       0 = not authorized, 1 = authorized)
        usbcore.autosuspend=
                        [USB] The autosuspend time delay (in seconds) used
                        for newly-detected USB devices (default 2).  This
Simple merge
diff --cc Makefile
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -1361,23 -1343,7 +1343,22 @@@ static int __init dmi_ignore_irq0_timer
        }
        return 0;
  }
- #endif
  
 +static int __init force_acpi_rsdt(const struct dmi_system_id *d)
 +{
 +      if (!acpi_force) {
 +              printk(KERN_NOTICE "%s detected: force use of acpi=rsdt\n",
 +                     d->ident);
 +              acpi_rsdt_forced = 1;
 +      } else {
 +              printk(KERN_NOTICE
 +                     "Warning: acpi=force overrules DMI blacklist: "
 +                     "acpi=rsdt\n");
 +      }
 +      return 0;
 +
 +}
 +
  /*
   * If your system is blacklisted here, but you find that acpi=force
   * works for you, please contact linux-acpi@vger.kernel.org
Simple merge
Simple merge
@@@ -159,16 -126,13 +127,19 @@@ void dump_trace(struct task_struct *tas
        if (!task)
                task = current;
  
 +      bp = stack_frame(task, regs);
 +      if (try_stack_unwind(task, regs, &stack, &bp, ops, data)) {
 +              put_cpu();
 +              return;
 +      }
 +
        if (!stack) {
-               stack = &dummy;
-               if (task && task != current)
+               if (regs)
+                       stack = (unsigned long *)regs->sp;
+               else if (task && task != current)
                        stack = (unsigned long *)task->thread.sp;
+               else
+                       stack = &dummy;
        }
  
        if (!bp)
Simple merge
@@@ -1224,41 -1208,7 +1208,41 @@@ ENTRY(call_softirq
        CFI_ENDPROC
  END(call_softirq)
  
 +#ifdef CONFIG_STACK_UNWIND
 +ENTRY(arch_unwind_init_running)
 +      CFI_STARTPROC
 +      movq    %r15, R15(%rdi)
 +      movq    %r14, R14(%rdi)
 +      xchgq   %rsi, %rdx
 +      movq    %r13, R13(%rdi)
 +      movq    %r12, R12(%rdi)
 +      xorl    %eax, %eax
 +      movq    %rbp, RBP(%rdi)
 +      movq    %rbx, RBX(%rdi)
 +      movq    (%rsp), %r9
 +      xchgq   %rdx, %rcx
 +      movq    %rax, R11(%rdi)
 +      movq    %rax, R10(%rdi)
 +      movq    %rax, R9(%rdi)
 +      movq    %rax, R8(%rdi)
 +      movq    %rax, RAX(%rdi)
 +      movq    %rax, RCX(%rdi)
 +      movq    %rax, RDX(%rdi)
 +      movq    %rax, RSI(%rdi)
 +      movq    %rax, RDI(%rdi)
 +      movq    %rax, ORIG_RAX(%rdi)
 +      movq    %r9, RIP(%rdi)
 +      leaq    8(%rsp), %r9
 +      movq    $__KERNEL_CS, CS(%rdi)
 +      movq    %rax, EFLAGS(%rdi)
 +      movq    %r9, RSP(%rdi)
 +      movq    $__KERNEL_DS, SS(%rdi)
 +      jmpq    *%rcx
 +      CFI_ENDPROC
 +END(arch_unwind_init_running)
 +#endif
 +
- #ifdef CONFIG_PARAVIRT_XEN
+ #ifdef CONFIG_XEN
  zeroentry xen_hypervisor_callback xen_do_hypervisor_callback
  
  /*
Simple merge
Simple merge
Simple merge
Simple merge
  #include <linux/oprofile.h>
  #include <linux/sched.h>
  #include <linux/mm.h>
+ #include <linux/compat.h>
+ #include <linux/uaccess.h>
  #include <asm/ptrace.h>
- #include <asm/uaccess.h>
  #include <asm/stacktrace.h>
- #include <linux/compat.h>
  
 +static void backtrace_warning_symbol(void *data, char *msg,
 +                                   unsigned long symbol)
 +{
 +      /* Ignore warnings */
 +}
 +
 +static void backtrace_warning(void *data, char *msg)
 +{
 +      /* Ignore warnings */
 +}
 +
  static int backtrace_stack(void *data, char *name)
  {
        /* Yes, we want all stacks */
diff --cc block/genhd.c
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -816,14 -759,9 +759,13 @@@ static int parse_features(struct dm_arg
                        continue;
                }
  
-               if (!strnicmp(param_name, MESG_STR("no_partitions"))) {
++              if (!strcasecmp(arg_name, "no_partitions")) {
 +                      m->features |= FEATURE_NO_PARTITIONS;
 +                      continue;
 +              }
-               if (!strnicmp(param_name, MESG_STR("pg_init_retries")) &&
+               if (!strcasecmp(arg_name, "pg_init_retries") &&
                    (argc >= 1)) {
-                       r = read_param(_params + 1, shift(as),
-                                      &m->pg_init_retries, &ti->error);
+                       r = dm_read_arg(_args + 1, as, &m->pg_init_retries, &ti->error);
                        argc--;
                        continue;
                }
Simple merge
diff --cc drivers/md/dm.c
@@@ -2039,16 -2087,12 +2102,19 @@@ static struct dm_table *__bind(struct m
        old_map = md->map;
        md->map = t;
        dm_table_set_restrictions(t, q, limits);
+       if (merge_is_optional)
+               set_bit(DMF_MERGE_IS_OPTIONAL, &md->flags);
+       else
+               clear_bit(DMF_MERGE_IS_OPTIONAL, &md->flags);
        write_unlock_irqrestore(&md->map_lock, flags);
  
 +      dm_table_get(md->map);
-       if (!(dm_table_get_mode(t) & FMODE_WRITE)) {
++      if (!(dm_table_get_mode(t) & FMODE_WRITE))
 +              set_disk_ro(md->disk, 1);
-       } else {
++      else
 +              set_disk_ro(md->disk, 0);
-       }
 +      dm_table_put(md->map);
 +
        return old_map;
  }
  
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -819,27 -766,7 +767,21 @@@ static const struct pci_device_id micro
  };
  MODULE_DEVICE_TABLE(pci, microsoft_hv_pci_table);
  
- static struct pci_driver hv_bus_driver = {
-       .name =           "hv_bus",
-       .probe =          hv_pci_probe,
-       .id_table =       microsoft_hv_pci_table,
- };
 +static const struct dmi_system_id __initconst
 +hv_vmbus_dmi_table[] __maybe_unused  = {
 +      {
 +              .ident = "Hyper-V",
 +              .matches = {
 +                      DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
 +                      DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"),
 +                      DMI_MATCH(DMI_BOARD_NAME, "Virtual Machine"),
 +              },
 +      },
 +      { },
 +};
 +MODULE_DEVICE_TABLE(dmi, hv_vmbus_dmi_table);
 +
- static int __init hv_pci_init(void)
+ static int __init hv_acpi_init(void)
  {
        int ret;
  
Simple merge
Simple merge
Simple merge
diff --cc fs/Kconfig
Simple merge
diff --cc fs/Makefile
Simple merge
Simple merge
diff --cc fs/ext4/acl.c
@@@ -281,10 -256,7 +256,7 @@@ ext4_init_acl(handle_t *handle, struct 
                if (!acl)
                        inode->i_mode &= ~current_umask();
        }
 -      if (test_opt(inode->i_sb, POSIX_ACL) && acl) {
 +      if (IS_POSIXACL(inode) && acl) {
-               struct posix_acl *clone;
-               mode_t mode;
                if (S_ISDIR(inode->i_mode)) {
                        error = ext4_set_acl(handle, inode,
                                             ACL_TYPE_DEFAULT, acl);
@@@ -330,12 -294,15 +294,15 @@@ cleanup
  int
  ext4_acl_chmod(struct inode *inode)
  {
-       struct posix_acl *acl, *clone;
+       struct posix_acl *acl;
+       handle_t *handle;
+       int retries = 0;
        int error;
  
        if (S_ISLNK(inode->i_mode))
                return -EOPNOTSUPP;
 -      if (!test_opt(inode->i_sb, POSIX_ACL))
 +      if (!IS_POSIXACL(inode))
                return 0;
        acl = ext4_get_acl(inode, ACL_TYPE_ACCESS);
        if (IS_ERR(acl) || !acl)
diff --cc fs/ext4/ext4.h
Simple merge
diff --cc fs/ext4/file.c
@@@ -281,10 -301,7 +302,10 @@@ const struct inode_operations ext4_file
        .listxattr      = ext4_listxattr,
        .removexattr    = generic_removexattr,
  #endif
-       .check_acl      = ext4_check_acl,
+       .get_acl        = ext4_get_acl,
        .fiemap         = ext4_fiemap,
 +      .permission     = ext4_permission,
 +      .may_create     = ext4_may_create,
 +      .may_delete     = ext4_may_delete,
  };
  
Simple merge
diff --cc fs/ext4/inode.c
@@@ -47,7 -43,7 +43,8 @@@
  #include "xattr.h"
  #include "acl.h"
  #include "ext4_extents.h"
+ #include "truncate.h"
 +#include "richacl.h"
  
  #include <trace/events/ext4.h>
  
diff --cc fs/ext4/namei.c
@@@ -2595,11 -2585,8 +2586,11 @@@ const struct inode_operations ext4_dir_
        .listxattr      = ext4_listxattr,
        .removexattr    = generic_removexattr,
  #endif
-       .check_acl      = ext4_check_acl,
+       .get_acl        = ext4_get_acl,
        .fiemap         = ext4_fiemap,
 +      .permission     = ext4_permission,
 +      .may_create     = ext4_may_create,
 +      .may_delete     = ext4_may_delete,
  };
  
  const struct inode_operations ext4_special_inode_operations = {
        .listxattr      = ext4_listxattr,
        .removexattr    = generic_removexattr,
  #endif
-       .check_acl      = ext4_check_acl,
+       .get_acl        = ext4_get_acl,
 +      .permission     = ext4_permission,
 +      .may_create     = ext4_may_create,
 +      .may_delete     = ext4_may_delete,
  };
index a44c2e5,0000000..0cc7d12
mode 100644,000000..100644
--- /dev/null
@@@ -1,294 -1,0 +1,293 @@@
 +/*
 + * Copyright IBM Corporation, 2010
 + * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
 + *
 + * This program is free software; you can redistribute it and/or modify it
 + * under the terms of version 2.1 of the GNU Lesser General Public License
 + * as published by the Free Software Foundation.
 + *
 + * This program is distributed in the hope that it would be useful, but
 + * WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 + *
 + */
 +
 +#include <linux/kernel.h>
 +#include <linux/fs.h>
 +#include <linux/richacl_xattr.h>
 +
 +#include "ext4.h"
 +#include "ext4_jbd2.h"
 +#include "xattr.h"
 +#include "acl.h"
 +#include "richacl.h"
 +
 +static inline struct richacl *
 +ext4_iget_richacl(struct inode *inode)
 +{
 +      struct richacl *acl = EXT4_RICHACL_NOT_CACHED;
 +      struct ext4_inode_info *ei = EXT4_I(inode);
 +
 +      spin_lock(&inode->i_lock);
 +      if (ei->i_richacl != EXT4_RICHACL_NOT_CACHED)
 +              acl = richacl_get(ei->i_richacl);
 +      spin_unlock(&inode->i_lock);
 +
 +      return acl;
 +}
 +
 +static inline void
 +ext4_iset_richacl(struct inode *inode, struct richacl *acl)
 +{
 +      struct ext4_inode_info *ei = EXT4_I(inode);
 +
 +      spin_lock(&inode->i_lock);
 +      if (ei->i_richacl != EXT4_RICHACL_NOT_CACHED)
 +              richacl_put(ei->i_richacl);
 +      ei->i_richacl = richacl_get(acl);
 +      spin_unlock(&inode->i_lock);
 +}
 +
 +static struct richacl *
 +ext4_get_richacl(struct inode *inode)
 +{
 +      const int name_index = EXT4_XATTR_INDEX_RICHACL;
 +      void *value = NULL;
 +      struct richacl *acl;
 +      int retval;
 +
 +      if (!IS_RICHACL(inode))
 +              return ERR_PTR(-EOPNOTSUPP);
 +      acl = ext4_iget_richacl(inode);
 +      if (acl != EXT4_RICHACL_NOT_CACHED)
 +              return acl;
 +      retval = ext4_xattr_get(inode, name_index, "", NULL, 0);
 +      if (retval > 0) {
 +              value = kmalloc(retval, GFP_KERNEL);
 +              if (!value)
 +                      return ERR_PTR(-ENOMEM);
 +              retval = ext4_xattr_get(inode, name_index, "", value, retval);
 +      }
 +      if (retval > 0) {
 +              acl = richacl_from_xattr(value, retval);
 +              if (acl == ERR_PTR(-EINVAL))
 +                      acl = ERR_PTR(-EIO);
 +      } else if (retval == -ENODATA || retval == -ENOSYS)
 +              acl = NULL;
 +      else
 +              acl = ERR_PTR(retval);
 +      kfree(value);
 +
 +      if (!IS_ERR_OR_NULL(acl))
 +              ext4_iset_richacl(inode, acl);
 +
 +      return acl;
 +}
 +
 +static int
 +ext4_set_richacl(handle_t *handle, struct inode *inode, struct richacl *acl)
 +{
 +      const int name_index = EXT4_XATTR_INDEX_RICHACL;
 +      size_t size = 0;
 +      void *value = NULL;
 +      int retval;
 +
 +      if (acl) {
 +              mode_t mode = inode->i_mode;
 +              if (richacl_equiv_mode(acl, &mode) == 0) {
 +                      inode->i_mode = mode;
 +                      ext4_mark_inode_dirty(handle, inode);
 +                      acl = NULL;
 +              }
 +      }
 +      if (acl) {
 +              size = richacl_xattr_size(acl);
 +              value = kmalloc(size, GFP_KERNEL);
 +              if (!value)
 +                      return -ENOMEM;
 +              richacl_to_xattr(acl, value);
 +      }
 +      if (handle)
 +              retval = ext4_xattr_set_handle(handle, inode, name_index, "",
 +                                             value, size, 0);
 +      else
 +              retval = ext4_xattr_set(inode, name_index, "", value, size, 0);
 +      kfree(value);
 +      if (!retval)
 +              ext4_iset_richacl(inode, acl);
 +
 +      return retval;
 +}
 +
 +int
- ext4_richacl_permission(struct inode *inode, unsigned int mask,
-                       unsigned int flags)
++ext4_richacl_permission(struct inode *inode, unsigned int mask)
 +{
 +      struct richacl *acl;
 +      int retval;
 +
 +      if (!IS_RICHACL(inode))
 +              BUG();
 +
 +      acl = ext4_get_richacl(inode);
 +      if (acl && IS_ERR(acl))
 +              retval = PTR_ERR(acl);
 +      else {
-               retval = richacl_inode_permission(inode, acl, mask, flags);
++              retval = richacl_inode_permission(inode, acl, mask);
 +              richacl_put(acl);
 +      }
 +
 +      return retval;
 +}
 +
- int ext4_permission(struct inode *inode, int mask, unsigned int flags)
++int ext4_permission(struct inode *inode, int mask)
 +{
 +      if (IS_RICHACL(inode))
 +              return ext4_richacl_permission(inode,
-                                       richacl_want_to_mask(mask), flags);
++                                      richacl_want_to_mask(mask));
 +      else
-               return generic_permission(inode, mask, flags, ext4_check_acl);
++              return generic_permission(inode, mask);
 +}
 +
 +int ext4_may_create(struct inode *dir, int isdir)
 +{
 +      return richacl_may_create(dir, isdir, ext4_richacl_permission);
 +}
 +
 +int ext4_may_delete(struct inode *dir, struct inode *inode, int replace)
 +{
 +      return richacl_may_delete(dir, inode, replace, ext4_richacl_permission);
 +}
 +
 +int
 +ext4_init_richacl(handle_t *handle, struct inode *inode, struct inode *dir)
 +{
 +      struct richacl *dir_acl = NULL;
 +
 +      if (!S_ISLNK(inode->i_mode)) {
 +              dir_acl = ext4_get_richacl(dir);
 +              if (IS_ERR(dir_acl))
 +                      return PTR_ERR(dir_acl);
 +      }
 +      if (dir_acl) {
 +              struct richacl *acl;
 +              int retval;
 +
 +              acl = richacl_inherit(dir_acl, inode);
 +              richacl_put(dir_acl);
 +
 +              retval = PTR_ERR(acl);
 +              if (acl && !IS_ERR(acl)) {
 +                      retval = ext4_set_richacl(handle, inode, acl);
 +                      richacl_put(acl);
 +              }
 +              return retval;
 +      } else {
 +              inode->i_mode &= ~current_umask();
 +              return 0;
 +      }
 +}
 +
 +int
 +ext4_richacl_chmod(struct inode *inode)
 +{
 +      struct richacl *acl;
 +      int retval;
 +
 +      if (S_ISLNK(inode->i_mode))
 +              return -EOPNOTSUPP;
 +      acl = ext4_get_richacl(inode);
 +      if (IS_ERR_OR_NULL(acl))
 +              return PTR_ERR(acl);
 +      acl = richacl_chmod(acl, inode->i_mode);
 +      if (IS_ERR(acl))
 +              return PTR_ERR(acl);
 +      retval = ext4_set_richacl(NULL, inode, acl);
 +      richacl_put(acl);
 +
 +      return retval;
 +}
 +
 +static size_t
 +ext4_xattr_list_richacl(struct dentry *dentry, char *list, size_t list_len,
 +                      const char *name, size_t name_len, int type)
 +{
 +      const size_t size = sizeof(RICHACL_XATTR);
 +      if (!IS_RICHACL(dentry->d_inode))
 +              return 0;
 +      if (list && size <= list_len)
 +              memcpy(list, RICHACL_XATTR, size);
 +      return size;
 +}
 +
 +static int
 +ext4_xattr_get_richacl(struct dentry *dentry, const char *name, void *buffer,
 +              size_t buffer_size, int type)
 +{
 +      struct richacl *acl;
 +      size_t size;
 +
 +      if (strcmp(name, "") != 0)
 +              return -EINVAL;
 +      acl = ext4_get_richacl(dentry->d_inode);
 +      if (IS_ERR(acl))
 +              return PTR_ERR(acl);
 +      if (acl == NULL)
 +              return -ENODATA;
 +      size = richacl_xattr_size(acl);
 +      if (buffer) {
 +              if (size > buffer_size)
 +                      return -ERANGE;
 +              richacl_to_xattr(acl, buffer);
 +      }
 +      richacl_put(acl);
 +
 +      return size;
 +}
 +
 +static int
 +ext4_xattr_set_richacl(struct dentry *dentry, const char *name,
 +              const void *value, size_t size, int flags, int type)
 +{
 +      handle_t *handle;
 +      struct richacl *acl = NULL;
 +      int retval, retries = 0;
 +      struct inode *inode = dentry->d_inode;
 +
 +      if (!IS_RICHACL(dentry->d_inode))
 +              return -EOPNOTSUPP;
 +      if (S_ISLNK(inode->i_mode))
 +              return -EOPNOTSUPP;
 +      if (strcmp(name, "") != 0)
 +              return -EINVAL;
 +      if (current_fsuid() != inode->i_uid &&
-           ext4_richacl_permission(inode, ACE4_WRITE_ACL, 0) &&
++          ext4_richacl_permission(inode, ACE4_WRITE_ACL) &&
 +          !capable(CAP_FOWNER))
 +              return -EPERM;
 +      if (value) {
 +              acl = richacl_from_xattr(value, size);
 +              if (IS_ERR(acl))
 +                      return PTR_ERR(acl);
 +
 +              inode->i_mode &= ~S_IRWXUGO;
 +              inode->i_mode |= richacl_masks_to_mode(acl);
 +      }
 +
 +retry:
 +      handle = ext4_journal_start(inode, EXT4_DATA_TRANS_BLOCKS(inode->i_sb));
 +      if (IS_ERR(handle))
 +              return PTR_ERR(handle);
 +      ext4_mark_inode_dirty(handle, inode);
 +      retval = ext4_set_richacl(handle, inode, acl);
 +      ext4_journal_stop(handle);
 +      if (retval == ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
 +              goto retry;
 +      richacl_put(acl);
 +      return retval;
 +}
 +
 +const struct xattr_handler ext4_richacl_xattr_handler = {
 +      .prefix = RICHACL_XATTR,
 +      .list   = ext4_xattr_list_richacl,
 +      .get    = ext4_xattr_get_richacl,
 +      .set    = ext4_xattr_set_richacl,
 +};
index fdb1a5b,0000000..00d89f2
mode 100644,000000..100644
--- /dev/null
@@@ -1,56 -1,0 +1,56 @@@
 +/*
 + * Copyright IBM Corporation, 2010
 + * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
 + *
 + * This program is free software; you can redistribute it and/or modify it
 + * under the terms of version 2.1 of the GNU Lesser General Public License
 + * as published by the Free Software Foundation.
 + *
 + * This program is distributed in the hope that it would be useful, but
 + * WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 + *
 + */
 +
 +#ifndef __FS_EXT4_RICHACL_H
 +#define __FS_EXT4_RICHACL_H
 +
 +#include <linux/richacl.h>
 +
 +#ifdef CONFIG_EXT4_FS_RICHACL
 +
 +# define EXT4_IS_RICHACL(inode) IS_RICHACL(inode)
 +
 +/* Value for i_richacl if RICHACL has not been cached */
 +# define EXT4_RICHACL_NOT_CACHED ((void *)-1)
 +
- extern int ext4_permission(struct inode *, int, unsigned int);
- extern int ext4_richacl_permission(struct inode *, unsigned int, unsigned int);
++extern int ext4_permission(struct inode *, int);
++extern int ext4_richacl_permission(struct inode *, unsigned int);
 +extern int ext4_may_create(struct inode *, int);
 +extern int ext4_may_delete(struct inode *, struct inode *, int);
 +extern int ext4_init_richacl(handle_t *, struct inode *, struct inode *);
 +extern int ext4_richacl_chmod(struct inode *);
 +
 +#else  /* CONFIG_FS_EXT4_RICHACL */
 +
 +# define EXT4_IS_RICHACL(inode) (0)
 +
 +# define ext4_permission NULL
 +# define ext4_may_create NULL
 +# define ext4_may_delete NULL
 +# define ext4_richacl_permission NULL
 +
 +static inline int
 +ext4_init_richacl(handle_t *handle, struct inode *inode, struct inode *dir)
 +{
 +      return 0;
 +}
 +
 +static inline int
 +ext4_richacl_chmod(struct inode *inode)
 +{
 +      return 0;
 +}
 +
 +#endif  /* CONFIG_FS_EXT4_RICHACL */
 +#endif  /* __FS_EXT4_RICHACL_H */
diff --cc fs/ext4/super.c
Simple merge
diff --cc fs/namei.c
@@@ -2484,16 -2489,11 +2537,11 @@@ SYSCALL_DEFINE4(mknodat, int, dfd, cons
        if (S_ISDIR(mode))
                return -EPERM;
  
-       error = user_path_parent(dfd, filename, &nd, &tmp);
-       if (error)
-               return error;
+       dentry = user_path_create(dfd, filename, &path, 0);
+       if (IS_ERR(dentry))
+               return PTR_ERR(dentry);
  
-       dentry = lookup_create(&nd, 0);
-       if (IS_ERR(dentry)) {
-               error = PTR_ERR(dentry);
-               goto out_unlock;
-       }
-       if (!IS_ACL(nd.path.dentry->d_inode))
 -      if (!IS_POSIXACL(path.dentry->d_inode))
++      if (!IS_ACL(path.dentry->d_inode))
                mode &= ~current_umask();
        error = may_mknod(mode);
        if (error)
@@@ -2556,38 -2554,29 +2602,29 @@@ int vfs_mkdir(struct inode *dir, struc
  
  SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, int, mode)
  {
-       int error = 0;
-       char * tmp;
        struct dentry *dentry;
-       struct nameidata nd;
-       error = user_path_parent(dfd, pathname, &nd, &tmp);
-       if (error)
-               goto out_err;
+       struct path path;
+       int error;
  
-       dentry = lookup_create(&nd, 1);
-       error = PTR_ERR(dentry);
+       dentry = user_path_create(dfd, pathname, &path, 1);
        if (IS_ERR(dentry))
-               goto out_unlock;
+               return PTR_ERR(dentry);
  
-       if (!IS_ACL(nd.path.dentry->d_inode))
 -      if (!IS_POSIXACL(path.dentry->d_inode))
++      if (!IS_ACL(path.dentry->d_inode))
                mode &= ~current_umask();
-       error = mnt_want_write(nd.path.mnt);
+       error = mnt_want_write(path.mnt);
        if (error)
                goto out_dput;
-       error = security_path_mkdir(&nd.path, dentry, mode);
+       error = security_path_mkdir(&path, dentry, mode);
        if (error)
                goto out_drop_write;
-       error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode);
+       error = vfs_mkdir(path.dentry->d_inode, dentry, mode);
  out_drop_write:
-       mnt_drop_write(nd.path.mnt);
+       mnt_drop_write(path.mnt);
  out_dput:
        dput(dentry);
- out_unlock:
-       mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
-       path_put(&nd.path);
-       putname(tmp);
- out_err:
+       mutex_unlock(&path.dentry->d_inode->i_mutex);
+       path_put(&path);
        return error;
  }
  
diff --cc fs/nfs/dir.c
Simple merge
diff --cc fs/nfs/inode.c
Simple merge
Simple merge
Simple merge
index 9b27c36,0000000..143f0f8
mode 100644,000000..100644
--- /dev/null
@@@ -1,617 -1,0 +1,617 @@@
 +/*
 + * Copyright (C) 2006, 2010  Novell, Inc.
 + * Written by Andreas Gruenbacher <agruen@suse.de>
 + *
 + * This program is free software; you can redistribute it and/or modify it
 + * under the terms of the GNU General Public License as published by the
 + * Free Software Foundation; either version 2, or (at your option) any
 + * later version.
 + *
 + * This program is distributed in the hope that it will be useful, but
 + * WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * General Public License for more details.
 + */
 +
 +#include <linux/sched.h>
 +#include <linux/module.h>
 +#include <linux/fs.h>
 +#include <linux/richacl.h>
 +
 +MODULE_LICENSE("GPL");
 +
 +/*
 + * Special e_who identifiers:  ACEs which have ACE4_SPECIAL_WHO set in
 + * ace->e_flags use these constants in ace->u.e_who.
 + *
 + * For efficiency, we compare pointers instead of comparing strings.
 + */
 +const char richace_owner_who[]          = "OWNER@";
 +EXPORT_SYMBOL_GPL(richace_owner_who);
 +const char richace_group_who[]          = "GROUP@";
 +EXPORT_SYMBOL_GPL(richace_group_who);
 +const char richace_everyone_who[] = "EVERYONE@";
 +EXPORT_SYMBOL_GPL(richace_everyone_who);
 +
 +/**
 + * richacl_alloc  -  allocate a richacl
 + * @count:    number of entries
 + */
 +struct richacl *
 +richacl_alloc(int count)
 +{
 +      size_t size = sizeof(struct richacl) + count * sizeof(struct richace);
 +      struct richacl *acl = kzalloc(size, GFP_KERNEL);
 +
 +      if (acl) {
 +              atomic_set(&acl->a_refcount, 1);
 +              acl->a_count = count;
 +      }
 +      return acl;
 +}
 +EXPORT_SYMBOL_GPL(richacl_alloc);
 +
 +/**
 + * richacl_clone  -  create a copy of a richacl
 + */
 +static struct richacl *
 +richacl_clone(const struct richacl *acl)
 +{
 +      int count = acl->a_count;
 +      size_t size = sizeof(struct richacl) + count * sizeof(struct richace);
 +      struct richacl *dup = kmalloc(size, GFP_KERNEL);
 +
 +      if (dup) {
 +              memcpy(dup, acl, size);
 +              atomic_set(&dup->a_refcount, 1);
 +      }
 +      return dup;
 +}
 +
 +/**
 + * richacl_mask_to_mode  -  compute the file permission bits which correspond to @mask
 + * @mask:     %ACE4_* permission mask
 + *
 + * See richacl_masks_to_mode().
 + */
 +static int
 +richacl_mask_to_mode(unsigned int mask)
 +{
 +      int mode = 0;
 +
 +      if (mask & ACE4_POSIX_MODE_READ)
 +              mode |= MAY_READ;
 +      if (mask & ACE4_POSIX_MODE_WRITE)
 +              mode |= MAY_WRITE;
 +      if (mask & ACE4_POSIX_MODE_EXEC)
 +              mode |= MAY_EXEC;
 +
 +      return mode;
 +}
 +
 +/**
 + * richacl_masks_to_mode  -  compute the file permission bits from the file masks
 + *
 + * When setting a richacl, we set the file permission bits to indicate maximum
 + * permissions: for example, we set the Write permission when a mask contains
 + * ACE4_APPEND_DATA even if it does not also contain ACE4_WRITE_DATA.
 + *
 + * Permissions which are not in ACE4_POSIX_MODE_READ, ACE4_POSIX_MODE_WRITE, or
 + * ACE4_POSIX_MODE_EXEC cannot be represented in the file permission bits.
 + * Such permissions can still be effective, but not for new files or after a
 + * chmod(), and only if they were set explicitly, for example, by setting a
 + * richacl.
 + */
 +int
 +richacl_masks_to_mode(const struct richacl *acl)
 +{
 +      return richacl_mask_to_mode(acl->a_owner_mask) << 6 |
 +             richacl_mask_to_mode(acl->a_group_mask) << 3 |
 +             richacl_mask_to_mode(acl->a_other_mask);
 +}
 +EXPORT_SYMBOL_GPL(richacl_masks_to_mode);
 +
 +/**
 + * richacl_mode_to_mask  - compute a file mask from the lowest three mode bits
 + *
 + * When the file permission bits of a file are set with chmod(), this specifies
 + * the maximum permissions that processes will get.  All permissions beyond
 + * that will be removed from the file masks, and become ineffective.
 + *
 + * We also add in the permissions which are always allowed no matter what the
 + * acl says.
 + */
 +unsigned int
 +richacl_mode_to_mask(mode_t mode)
 +{
 +      unsigned int mask = ACE4_POSIX_ALWAYS_ALLOWED;
 +
 +      if (mode & MAY_READ)
 +              mask |= ACE4_POSIX_MODE_READ;
 +      if (mode & MAY_WRITE)
 +              mask |= ACE4_POSIX_MODE_WRITE;
 +      if (mode & MAY_EXEC)
 +              mask |= ACE4_POSIX_MODE_EXEC;
 +
 +      return mask;
 +}
 +
 +/**
 + * richacl_want_to_mask  - convert the iop->permission want argument to a mask
 + * @want:     @want argument of the permission inode operation
 + *
 + * When checking for append, @want is (MAY_WRITE | MAY_APPEND).
 + *
 + * Richacls use the iop->may_create and iop->may_delete hooks which are
 + * used for checking if creating and deleting files is allowed.  These hooks do
 + * not use richacl_want_to_mask(), so we do not have to deal with mapping
 + * MAY_WRITE to ACE4_ADD_FILE, ACE4_ADD_SUBDIRECTORY, and ACE4_DELETE_CHILD
 + * here.
 + */
 +unsigned int
 +richacl_want_to_mask(int want)
 +{
 +      unsigned int mask = 0;
 +
 +      if (want & MAY_READ)
 +              mask |= ACE4_READ_DATA;
 +      if (want & MAY_APPEND)
 +              mask |= ACE4_APPEND_DATA;
 +      else if (want & MAY_WRITE)
 +              mask |= ACE4_WRITE_DATA;
 +      if (want & MAY_EXEC)
 +              mask |= ACE4_EXECUTE;
 +
 +      return mask;
 +}
 +EXPORT_SYMBOL_GPL(richacl_want_to_mask);
 +
 +/**
 + * richace_is_same_identifier  -  are both identifiers the same?
 + */
 +int
 +richace_is_same_identifier(const struct richace *a, const struct richace *b)
 +{
 +#define WHO_FLAGS (ACE4_SPECIAL_WHO | ACE4_IDENTIFIER_GROUP)
 +      if ((a->e_flags & WHO_FLAGS) != (b->e_flags & WHO_FLAGS))
 +              return 0;
 +      if (a->e_flags & ACE4_SPECIAL_WHO)
 +              return a->u.e_who == b->u.e_who;
 +      else
 +              return a->u.e_id == b->u.e_id;
 +#undef WHO_FLAGS
 +}
 +
 +/**
 + * richacl_set_who  -  set a special who value
 + * @ace:      acl entry
 + * @who:      who value to use
 + */
 +int
 +richace_set_who(struct richace *ace, const char *who)
 +{
 +      if (!strcmp(who, richace_owner_who))
 +              who = richace_owner_who;
 +      else if (!strcmp(who, richace_group_who))
 +              who = richace_group_who;
 +      else if (!strcmp(who, richace_everyone_who))
 +              who = richace_everyone_who;
 +      else
 +              return -EINVAL;
 +
 +      ace->u.e_who = who;
 +      ace->e_flags |= ACE4_SPECIAL_WHO;
 +      ace->e_flags &= ~ACE4_IDENTIFIER_GROUP;
 +      return 0;
 +}
 +EXPORT_SYMBOL_GPL(richace_set_who);
 +
 +/**
 + * richacl_allowed_to_who  -  mask flags allowed to a specific who value
 + *
 + * Computes the mask values allowed to a specific who value, taking
 + * EVERYONE@ entries into account.
 + */
 +static unsigned int richacl_allowed_to_who(struct richacl *acl,
 +                                         struct richace *who)
 +{
 +      struct richace *ace;
 +      unsigned int allowed = 0;
 +
 +      richacl_for_each_entry_reverse(ace, acl) {
 +              if (richace_is_inherit_only(ace))
 +                      continue;
 +              if (richace_is_same_identifier(ace, who) ||
 +                  richace_is_everyone(ace)) {
 +                      if (richace_is_allow(ace))
 +                              allowed |= ace->e_mask;
 +                      else if (richace_is_deny(ace))
 +                              allowed &= ~ace->e_mask;
 +              }
 +      }
 +      return allowed;
 +}
 +
 +/**
 + * richacl_group_class_allowed  -  maximum permissions the group class is allowed
 + *
 + * See richacl_compute_max_masks().
 + */
 +static unsigned int richacl_group_class_allowed(struct richacl *acl)
 +{
 +      struct richace *ace;
 +      unsigned int everyone_allowed = 0, group_class_allowed = 0;
 +      int had_group_ace = 0;
 +
 +      richacl_for_each_entry_reverse(ace, acl) {
 +              if (richace_is_inherit_only(ace) ||
 +                  richace_is_owner(ace))
 +                      continue;
 +
 +              if (richace_is_everyone(ace)) {
 +                      if (richace_is_allow(ace))
 +                              everyone_allowed |= ace->e_mask;
 +                      else if (richace_is_deny(ace))
 +                              everyone_allowed &= ~ace->e_mask;
 +              } else {
 +                      group_class_allowed |=
 +                              richacl_allowed_to_who(acl, ace);
 +
 +                      if (richace_is_group(ace))
 +                              had_group_ace = 1;
 +              }
 +      }
 +      if (!had_group_ace)
 +              group_class_allowed |= everyone_allowed;
 +      return group_class_allowed;
 +}
 +
 +/**
 + * richacl_compute_max_masks  -  compute upper bound masks
 + *
 + * Computes upper bound owner, group, and other masks so that none of
 + * the mask flags allowed by the acl are disabled (for any choice of the
 + * file owner or group membership).
 + */
 +void richacl_compute_max_masks(struct richacl *acl)
 +{
 +      unsigned int gmask = ~0;
 +      struct richace *ace;
 +
 +      /*
 +       * @gmask contains all permissions which the group class is ever
 +       * allowed.  We use it to avoid adding permissions to the group mask
 +       * from everyone@ allow aces which the group class is always denied
 +       * through other aces.  For example, the following acl would otherwise
 +       * result in a group mask or rw:
 +       *
 +       *      group@:w::deny
 +       *      everyone@:rw::allow
 +       *
 +       * Avoid computing @gmask for acls which do not include any group class
 +       * deny aces: in such acls, the group class is never denied any
 +       * permissions from everyone@ allow aces.
 +       */
 +
 +restart:
 +      acl->a_owner_mask = 0;
 +      acl->a_group_mask = 0;
 +      acl->a_other_mask = 0;
 +
 +      richacl_for_each_entry_reverse(ace, acl) {
 +              if (richace_is_inherit_only(ace))
 +                      continue;
 +
 +              if (richace_is_owner(ace)) {
 +                      if (richace_is_allow(ace))
 +                              acl->a_owner_mask |= ace->e_mask;
 +                      else if (richace_is_deny(ace))
 +                              acl->a_owner_mask &= ~ace->e_mask;
 +              } else if (richace_is_everyone(ace)) {
 +                      if (richace_is_allow(ace)) {
 +                              acl->a_owner_mask |= ace->e_mask;
 +                              acl->a_group_mask |= ace->e_mask & gmask;
 +                              acl->a_other_mask |= ace->e_mask;
 +                      } else if (richace_is_deny(ace)) {
 +                              acl->a_owner_mask &= ~ace->e_mask;
 +                              acl->a_group_mask &= ~ace->e_mask;
 +                              acl->a_other_mask &= ~ace->e_mask;
 +                      }
 +              } else {
 +                      if (richace_is_allow(ace)) {
 +                              acl->a_owner_mask |= ace->e_mask & gmask;
 +                              acl->a_group_mask |= ace->e_mask & gmask;
 +                      } else if (richace_is_deny(ace) && gmask == ~0) {
 +                              gmask = richacl_group_class_allowed(acl);
 +                              if (likely(gmask != ~0))  /* should always be true */
 +                                      goto restart;
 +                      }
 +              }
 +      }
 +}
 +EXPORT_SYMBOL_GPL(richacl_compute_max_masks);
 +
 +/**
 + * richacl_chmod  -  update the file masks to reflect the new mode
 + * @mode:     new file permission bits
 + *
 + * Return a copy of @acl where the file masks have been replaced by the file
 + * masks corresponding to the file permission bits in @mode, or returns @acl
 + * itself if the file masks are already up to date.  Takes over a reference
 + * to @acl.
 + */
 +struct richacl *
 +richacl_chmod(struct richacl *acl, mode_t mode)
 +{
 +      unsigned int owner_mask, group_mask, other_mask;
 +      struct richacl *clone;
 +
 +      owner_mask = richacl_mode_to_mask(mode >> 6);
 +      group_mask = richacl_mode_to_mask(mode >> 3);
 +      other_mask = richacl_mode_to_mask(mode);
 +
 +      if (acl->a_owner_mask == owner_mask &&
 +          acl->a_group_mask == group_mask &&
 +          acl->a_other_mask == other_mask &&
 +          (!richacl_is_auto_inherit(acl) || richacl_is_protected(acl)))
 +              return acl;
 +
 +      clone = richacl_clone(acl);
 +      richacl_put(acl);
 +      if (!clone)
 +              return ERR_PTR(-ENOMEM);
 +
 +      clone->a_owner_mask = owner_mask;
 +      clone->a_group_mask = group_mask;
 +      clone->a_other_mask = other_mask;
 +      if (richacl_is_auto_inherit(clone))
 +              clone->a_flags |= ACL4_PROTECTED;
 +
 +      return clone;
 +}
 +EXPORT_SYMBOL_GPL(richacl_chmod);
 +
 +/**
 + * richacl_permission  -  richacl permission check algorithm
 + * @inode:    inode to check
 + * @acl:      rich acl of the inode
 + * @mask:     requested access (ACE4_* bitmask)
 + *
 + * Checks if the current process is granted @mask flags in @acl.
 + */
 +int
 +richacl_permission(struct inode *inode, const struct richacl *acl,
-                  unsigned int mask, unsigned int flags)
++                 unsigned int mask)
 +{
 +      const struct richace *ace;
 +      unsigned int file_mask, requested = mask, denied = 0;
 +      int in_owning_group = in_group_p(inode->i_gid);
 +      int in_owner_or_group_class = in_owning_group;
 +
 +      /*
 +       * A process is
 +       *   - in the owner file class if it owns the file,
 +       *   - in the group file class if it is in the file's owning group or
 +       *     it matches any of the user or group entries, and
 +       *   - in the other file class otherwise.
 +       */
 +
 +      /*
 +       * Check if the acl grants the requested access and determine which
 +       * file class the process is in.
 +       */
 +      richacl_for_each_entry(ace, acl) {
 +              unsigned int ace_mask = ace->e_mask;
 +
 +              if (richace_is_inherit_only(ace))
 +                      continue;
 +              if (richace_is_owner(ace)) {
 +                      if (current_fsuid() != inode->i_uid)
 +                              continue;
 +                      goto is_owner;
 +              } else if (richace_is_group(ace)) {
 +                      if (!in_owning_group)
 +                              continue;
 +              } else if (richace_is_unix_id(ace)) {
 +                      if (ace->e_flags & ACE4_IDENTIFIER_GROUP) {
 +                              if (!in_group_p(ace->u.e_id))
 +                                      continue;
 +                      } else {
 +                              if (current_fsuid() != ace->u.e_id)
 +                                      continue;
 +                      }
 +              } else
 +                      goto is_everyone;
 +
 +              /*
 +               * Apply the group file mask to entries other than OWNER@ and
 +               * EVERYONE@. This is not required for correct access checking
 +               * but ensures that we grant the same permissions as the acl
 +               * computed by richacl_apply_masks() would grant.  See
 +               * richacl_apply_masks() for a more detailed explanation.
 +               */
 +              if (richace_is_allow(ace))
 +                      ace_mask &= acl->a_group_mask;
 +
 +is_owner:
 +              /* The process is in the owner or group file class. */
 +              in_owner_or_group_class = 1;
 +
 +is_everyone:
 +              /* Check which mask flags the ACE allows or denies. */
 +              if (richace_is_deny(ace))
 +                      denied |= ace_mask & mask;
 +              mask &= ~ace_mask;
 +
 +              /*
 +               * Keep going until we know which file class
 +               * the process is in.
 +               */
 +              if (!mask && in_owner_or_group_class)
 +                      break;
 +      }
 +      denied |= mask;
 +
 +      /*
 +       * The file class a process is in determines which file mask applies.
 +       * Check if that file mask also grants the requested access.
 +       */
 +      if (current_fsuid() == inode->i_uid)
 +              file_mask = acl->a_owner_mask;
 +      else if (in_owner_or_group_class)
 +              file_mask = acl->a_group_mask;
 +      else
 +              file_mask = acl->a_other_mask;
 +      denied |= requested & ~file_mask;
 +
 +      return denied ? -EACCES : 0;
 +}
 +EXPORT_SYMBOL_GPL(richacl_permission);
 +
 +/**
 + * richacl_inherit  -  compute the inherited acl of a new file
 + * @dir_acl:  acl of the containing direcory
 + * @inode:    inode of the new file (create mode in i_mode)
 + *
 + * A directory can have acl entries which files and/or directories created
 + * inside the directory will inherit.  This function computes the acl for such
 + * a new file.  If there is no inheritable acl, it will return %NULL.
 + *
 + * The file permission bits in inode->i_mode must be set to the create mode.
 + * If there is an inheritable acl, the maximum permissions that the acl grants
 + * will be computed and permissions not granted by the acl will be removed from
 + * inode->i_mode.  If there is no inheritable acl, the umask will be applied
 + * instead.
 + */
 +struct richacl *
 +richacl_inherit(const struct richacl *dir_acl, struct inode *inode)
 +{
 +      const struct richace *dir_ace;
 +      struct richacl *acl = NULL;
 +      struct richace *ace;
 +      int count = 0;
 +      mode_t mask = ~current_umask();
 +
 +      if (S_ISDIR(inode->i_mode)) {
 +              richacl_for_each_entry(dir_ace, dir_acl) {
 +                      if (!richace_is_inheritable(dir_ace))
 +                              continue;
 +                      count++;
 +              }
 +              if (!count)
 +                      goto mask;
 +              acl = richacl_alloc(count);
 +              if (!acl)
 +                      return ERR_PTR(-ENOMEM);
 +              ace = acl->a_entries;
 +              richacl_for_each_entry(dir_ace, dir_acl) {
 +                      if (!richace_is_inheritable(dir_ace))
 +                              continue;
 +                      memcpy(ace, dir_ace, sizeof(struct richace));
 +                      if (dir_ace->e_flags & ACE4_NO_PROPAGATE_INHERIT_ACE)
 +                              richace_clear_inheritance_flags(ace);
 +                      if ((dir_ace->e_flags & ACE4_FILE_INHERIT_ACE) &&
 +                          !(dir_ace->e_flags & ACE4_DIRECTORY_INHERIT_ACE))
 +                              ace->e_flags |= ACE4_INHERIT_ONLY_ACE;
 +                      ace++;
 +              }
 +      } else {
 +              richacl_for_each_entry(dir_ace, dir_acl) {
 +                      if (!(dir_ace->e_flags & ACE4_FILE_INHERIT_ACE))
 +                              continue;
 +                      count++;
 +              }
 +              if (!count)
 +                      goto mask;
 +              acl = richacl_alloc(count);
 +              if (!acl)
 +                      return ERR_PTR(-ENOMEM);
 +              ace = acl->a_entries;
 +              richacl_for_each_entry(dir_ace, dir_acl) {
 +                      if (!(dir_ace->e_flags & ACE4_FILE_INHERIT_ACE))
 +                              continue;
 +                      memcpy(ace, dir_ace, sizeof(struct richace));
 +                      richace_clear_inheritance_flags(ace);
 +                      /*
 +                       * ACE4_DELETE_CHILD is meaningless for
 +                       * non-directories, so clear it.
 +                       */
 +                      ace->e_mask &= ~ACE4_DELETE_CHILD;
 +                      ace++;
 +              }
 +      }
 +
 +      richacl_compute_max_masks(acl);
 +
 +      /*
 +       * Ensure that the acl will not grant any permissions beyond the create
 +       * mode.
 +       */
 +      acl->a_owner_mask &= richacl_mode_to_mask(inode->i_mode >> 6);
 +      acl->a_group_mask &= richacl_mode_to_mask(inode->i_mode >> 3);
 +      acl->a_other_mask &= richacl_mode_to_mask(inode->i_mode);
 +      mask = ~S_IRWXUGO | richacl_masks_to_mode(acl);
 +
 +      if (richacl_is_auto_inherit(dir_acl)) {
 +              /*
 +               * We need to set ACL4_PROTECTED because we are
 +               * doing an implicit chmod
 +               */
 +              acl->a_flags = ACL4_AUTO_INHERIT | ACL4_PROTECTED;
 +              richacl_for_each_entry(ace, acl)
 +                      ace->e_flags |= ACE4_INHERITED_ACE;
 +      }
 +
 +mask:
 +      inode->i_mode &= mask;
 +      return acl;
 +}
 +EXPORT_SYMBOL_GPL(richacl_inherit);
 +
 +/**
 + * richacl_equiv_mode  -  check if @acl is equivalent to file permission bits
 + * @mode_p:   the file mode (including the file type)
 + *
 + * If @acl can be fully represented by file permission bits, this function
 + * returns 0, and the file permission bits in @mode_p are set to the equivalent
 + * of @acl.
 + *
 + * This function is used to avoid storing richacls on disk if the acl can be
 + * computed from the file permission bits.  It allows user-space to make sure
 + * that a file has no explicit richacl set.
 + */
 +int
 +richacl_equiv_mode(const struct richacl *acl, mode_t *mode_p)
 +{
 +      const struct richace *ace = acl->a_entries;
 +      unsigned int x;
 +      mode_t mode;
 +
 +      if (acl->a_count != 1 ||
 +          acl->a_flags ||
 +          !richace_is_everyone(ace) ||
 +          !richace_is_allow(ace) ||
 +          ace->e_flags & ~ACE4_SPECIAL_WHO)
 +              return -1;
 +
 +      /*
 +       * Figure out the permissions we care about: ACE4_DELETE_CHILD is
 +       * meaningless for non-directories, so we ignore it.
 +       */
 +      x = ~ACE4_POSIX_ALWAYS_ALLOWED;
 +      if (!S_ISDIR(*mode_p))
 +              x &= ~ACE4_DELETE_CHILD;
 +
 +      if ((ace->e_mask & x) != (ACE4_POSIX_MODE_ALL & x))
 +              return -1;
 +
 +      mode = richacl_masks_to_mode(acl);
 +      if ((acl->a_owner_mask & x) != (richacl_mode_to_mask(mode >> 6) & x) ||
 +          (acl->a_group_mask & x) != (richacl_mode_to_mask(mode >> 3) & x) ||
 +          (acl->a_other_mask & x) != (richacl_mode_to_mask(mode) & x))
 +              return -1;
 +
 +      *mode_p = (*mode_p & ~S_IRWXUGO) | mode;
 +      return 0;
 +}
 +EXPORT_SYMBOL_GPL(richacl_equiv_mode);
index cc237f3,0000000..1953a22
mode 100644,000000..100644
--- /dev/null
@@@ -1,198 -1,0 +1,192 @@@
 +/*
 + * Copyright (C) 2010  Novell, Inc.
 + * Written by Andreas Gruenbacher <agruen@suse.de>
 + *
 + * This program is free software; you can redistribute it and/or modify it
 + * under the terms of the GNU General Public License as published by the
 + * Free Software Foundation; either version 2, or (at your option) any
 + * later version.
 + *
 + * This program is distributed in the hope that it will be useful, but
 + * WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * General Public License for more details.
 + */
 +
 +#include <linux/sched.h>
 +#include <linux/module.h>
 +#include <linux/fs.h>
 +#include <linux/richacl.h>
 +
 +/**
 + * richacl_may_create  -  helper for implementing iop->may_create
 + */
 +int
 +richacl_may_create(struct inode *dir, int isdir,
-               int (*richacl_permission)(struct inode *, unsigned int,
-                                         unsigned int))
++              int (*richacl_permission)(struct inode *, unsigned int))
 +{
 +      if (IS_RICHACL(dir))
 +              return richacl_permission(dir,
 +                              ACE4_EXECUTE | (isdir ?
-                               ACE4_ADD_SUBDIRECTORY : ACE4_ADD_FILE), 0);
++                              ACE4_ADD_SUBDIRECTORY : ACE4_ADD_FILE));
 +      else
-               return generic_permission(dir, MAY_WRITE | MAY_EXEC, 0,
-                                         dir->i_op->check_acl);
++              return generic_permission(dir, MAY_WRITE | MAY_EXEC);
 +}
 +EXPORT_SYMBOL(richacl_may_create);
 +
 +static int
 +check_sticky(struct inode *dir, struct inode *inode)
 +{
 +      if (!(dir->i_mode & S_ISVTX))
 +              return 0;
 +      if (inode->i_uid == current_fsuid())
 +              return 0;
 +      if (dir->i_uid == current_fsuid())
 +              return 0;
 +      return !capable(CAP_FOWNER);
 +}
 +
 +/**
 + * richacl_may_delete  -  helper for implementing iop->may_delete
 + */
 +int
 +richacl_may_delete(struct inode *dir, struct inode *inode, int replace,
-                  int (*richacl_permission)(struct inode *, unsigned int,
-                                            unsigned int))
++                 int (*richacl_permission)(struct inode *, unsigned int))
 +{
 +      int error;
 +
 +      if (IS_RICHACL(inode)) {
 +              error = richacl_permission(dir,
-                               ACE4_EXECUTE | ACE4_DELETE_CHILD, 0);
++                              ACE4_EXECUTE | ACE4_DELETE_CHILD);
 +              if (!error && check_sticky(dir, inode))
 +                      error = -EPERM;
-               if (error && !richacl_permission(inode, ACE4_DELETE, 0))
++              if (error && !richacl_permission(inode, ACE4_DELETE))
 +                      error = 0;
 +              if (!error && replace)
 +                      error = richacl_permission(dir,
 +                                      ACE4_EXECUTE | (S_ISDIR(inode->i_mode) ?
-                                       ACE4_ADD_SUBDIRECTORY : ACE4_ADD_FILE),
-                                       0);
++                                      ACE4_ADD_SUBDIRECTORY : ACE4_ADD_FILE));
 +      } else {
-               error = generic_permission(dir, MAY_WRITE | MAY_EXEC, 0,
-                                          dir->i_op->check_acl);
++              error = generic_permission(dir, MAY_WRITE | MAY_EXEC);
 +              if (!error && check_sticky(dir, inode))
 +                      error = -EPERM;
 +      }
 +
 +      return error;
 +}
 +EXPORT_SYMBOL(richacl_may_delete);
 +
 +/**
 + * richacl_inode_permission  -  helper for implementing iop->permission
 + * @inode:    inode to check
 + * @acl:      rich acl of the inode (may be NULL)
 + * @mask:     requested access (ACE4_* bitmask)
 + *
 + * This function is supposed to be used by file systems for implementing the
 + * permission inode operation.
 + */
 +int
 +richacl_inode_permission(struct inode *inode, const struct richacl *acl,
-                        unsigned int mask, unsigned int flags)
++                       unsigned int mask)
 +{
 +      if (acl) {
-               if (!richacl_permission(inode, acl, mask, flags))
++              if (!richacl_permission(inode, acl, mask))
 +                      return 0;
 +      } else {
 +              int mode = inode->i_mode;
 +
 +              if (current_fsuid() == inode->i_uid)
 +                      mode >>= 6;
 +              else if (in_group_p(inode->i_gid))
 +                      mode >>= 3;
 +              if (!(mask & ~richacl_mode_to_mask(mode)))
 +                      return 0;
 +      }
 +
 +      /*
 +       * Keep in sync with the capability checks in generic_permission().
 +       */
 +      if (!(mask & ~ACE4_POSIX_MODE_ALL)) {
 +              /*
 +               * Read/write DACs are always overridable.
 +               * Executable DACs are overridable if at
 +               * least one exec bit is set.
 +               */
 +              if (!(mask & ACE4_POSIX_MODE_EXEC) || execute_ok(inode))
 +                      if (capable(CAP_DAC_OVERRIDE))
 +                              return 0;
 +      }
 +      /*
 +       * Searching includes executable on directories, else just read.
 +       */
 +      if (!(mask & ~(ACE4_READ_DATA | ACE4_LIST_DIRECTORY | ACE4_EXECUTE)) &&
 +          (S_ISDIR(inode->i_mode) || !(mask & ACE4_EXECUTE)))
 +              if (capable(CAP_DAC_READ_SEARCH))
 +                      return 0;
 +
 +      return -EACCES;
 +}
 +EXPORT_SYMBOL_GPL(richacl_inode_permission);
 +
 +/**
 + * richacl_inode_change_ok  -  helper for implementing iop->setattr
 + * @inode:    inode to check
 + * @attr:     requested inode attribute changes
 + * @richacl_permission:       permission function taking an inode and ACE4_* flags
 + *
 + * Keep in sync with inode_change_ok().
 + */
 +int
 +richacl_inode_change_ok(struct inode *inode, struct iattr *attr,
-                       int (*richacl_permission)(struct inode *, unsigned int,
-                                                 unsigned int))
++                      int (*richacl_permission)(struct inode *, unsigned int))
 +{
 +      unsigned int ia_valid = attr->ia_valid;
 +
 +      /* If force is set do it anyway. */
 +      if (ia_valid & ATTR_FORCE)
 +              return 0;
 +
 +      /* Make sure a caller can chown. */
 +      if ((ia_valid & ATTR_UID) &&
 +          (current_fsuid() != inode->i_uid ||
 +           attr->ia_uid != inode->i_uid) &&
 +          (current_fsuid() != attr->ia_uid ||
-            richacl_permission(inode, ACE4_WRITE_OWNER, 0)) &&
++           richacl_permission(inode, ACE4_WRITE_OWNER)) &&
 +          !capable(CAP_CHOWN))
 +              goto error;
 +
 +      /* Make sure caller can chgrp. */
 +      if ((ia_valid & ATTR_GID)) {
 +              int in_group = in_group_p(attr->ia_gid);
 +              if ((current_fsuid() != inode->i_uid ||
 +                  (!in_group && attr->ia_gid != inode->i_gid)) &&
 +                  (!in_group ||
-                    richacl_permission(inode, ACE4_WRITE_OWNER, 0)) &&
++                   richacl_permission(inode, ACE4_WRITE_OWNER)) &&
 +                  !capable(CAP_CHOWN))
 +                      goto error;
 +      }
 +
 +      /* Make sure a caller can chmod. */
 +      if (ia_valid & ATTR_MODE) {
 +              if (current_fsuid() != inode->i_uid &&
-                   richacl_permission(inode, ACE4_WRITE_ACL, 0) &&
++                  richacl_permission(inode, ACE4_WRITE_ACL) &&
 +                  !capable(CAP_FOWNER))
 +                      goto error;
 +              /* Also check the setgid bit! */
 +              if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid :
 +                              inode->i_gid) && !capable(CAP_FSETID))
 +                      attr->ia_mode &= ~S_ISGID;
 +      }
 +
 +      /* Check for setting the inode time. */
 +      if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET)) {
 +              if (current_fsuid() != inode->i_uid &&
-                   richacl_permission(inode, ACE4_WRITE_ATTRIBUTES, 0) &&
++                  richacl_permission(inode, ACE4_WRITE_ATTRIBUTES) &&
 +                  !capable(CAP_FOWNER))
 +                      goto error;
 +      }
 +      return 0;
 +error:
 +      return -EPERM;
 +}
 +EXPORT_SYMBOL_GPL(richacl_inode_change_ok);
diff --cc fs/super.c
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index a90304b,0000000..3da00a2
mode 100644,000000..100644
--- /dev/null
@@@ -1,326 -1,0 +1,322 @@@
 +/*
 + * Copyright (C) 2006, 2010  Novell, Inc.
 + * Written by Andreas Gruenbacher <agruen@suse.de>
 + *
 + * This program is free software; you can redistribute it and/or modify it
 + * under the terms of the GNU General Public License as published by the
 + * Free Software Foundation; either version 2, or (at your option) any
 + * later version.
 + *
 + * This program is distributed in the hope that it will be useful, but
 + * WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * General Public License for more details.
 + */
 +
 +#ifndef __RICHACL_H
 +#define __RICHACL_H
 +#include <linux/slab.h>
 +
 +struct richace {
 +      unsigned short  e_type;
 +      unsigned short  e_flags;
 +      unsigned int    e_mask;
 +      union {
 +              unsigned int    e_id;
 +              const char      *e_who;
 +      } u;
 +};
 +
 +struct richacl {
 +      atomic_t        a_refcount;
 +      unsigned int    a_owner_mask;
 +      unsigned int    a_group_mask;
 +      unsigned int    a_other_mask;
 +      unsigned short  a_count;
 +      unsigned short  a_flags;
 +      struct richace  a_entries[0];
 +};
 +
 +#define richacl_for_each_entry(_ace, _acl) \
 +      for (_ace = _acl->a_entries; \
 +           _ace != _acl->a_entries + _acl->a_count; \
 +           _ace++)
 +
 +#define richacl_for_each_entry_reverse(_ace, _acl) \
 +      for (_ace = _acl->a_entries + _acl->a_count - 1; \
 +           _ace != _acl->a_entries - 1; \
 +           _ace--)
 +
 +/* a_flags values */
 +#define ACL4_AUTO_INHERIT             0x01
 +#define ACL4_PROTECTED                        0x02
 +/*#define ACL4_DEFAULTED                      0x04*/
 +
 +#define ACL4_VALID_FLAGS (    \
 +      ACL4_AUTO_INHERIT |     \
 +      ACL4_PROTECTED)
 +
 +/* e_type values */
 +#define ACE4_ACCESS_ALLOWED_ACE_TYPE  0x0000
 +#define ACE4_ACCESS_DENIED_ACE_TYPE   0x0001
 +/*#define ACE4_SYSTEM_AUDIT_ACE_TYPE  0x0002*/
 +/*#define ACE4_SYSTEM_ALARM_ACE_TYPE  0x0003*/
 +
 +/* e_flags bitflags */
 +#define ACE4_FILE_INHERIT_ACE         0x0001
 +#define ACE4_DIRECTORY_INHERIT_ACE    0x0002
 +#define ACE4_NO_PROPAGATE_INHERIT_ACE 0x0004
 +#define ACE4_INHERIT_ONLY_ACE         0x0008
 +/*#define ACE4_SUCCESSFUL_ACCESS_ACE_FLAG     0x0010*/
 +/*#define ACE4_FAILED_ACCESS_ACE_FLAG 0x0020*/
 +#define ACE4_IDENTIFIER_GROUP         0x0040
 +#define ACE4_INHERITED_ACE            0x0080
 +/* in-memory representation only */
 +#define ACE4_SPECIAL_WHO              0x4000
 +
 +#define ACE4_VALID_FLAGS (                    \
 +      ACE4_FILE_INHERIT_ACE |                 \
 +      ACE4_DIRECTORY_INHERIT_ACE |            \
 +      ACE4_NO_PROPAGATE_INHERIT_ACE |         \
 +      ACE4_INHERIT_ONLY_ACE |                 \
 +      ACE4_IDENTIFIER_GROUP |                 \
 +      ACE4_INHERITED_ACE)
 +
 +/* e_mask bitflags */
 +#define ACE4_READ_DATA                        0x00000001
 +#define ACE4_LIST_DIRECTORY           0x00000001
 +#define ACE4_WRITE_DATA                       0x00000002
 +#define ACE4_ADD_FILE                 0x00000002
 +#define ACE4_APPEND_DATA              0x00000004
 +#define ACE4_ADD_SUBDIRECTORY         0x00000004
 +#define ACE4_READ_NAMED_ATTRS         0x00000008
 +#define ACE4_WRITE_NAMED_ATTRS                0x00000010
 +#define ACE4_EXECUTE                  0x00000020
 +#define ACE4_DELETE_CHILD             0x00000040
 +#define ACE4_READ_ATTRIBUTES          0x00000080
 +#define ACE4_WRITE_ATTRIBUTES         0x00000100
 +#define ACE4_WRITE_RETENTION          0x00000200
 +#define ACE4_WRITE_RETENTION_HOLD     0x00000400
 +#define ACE4_DELETE                   0x00010000
 +#define ACE4_READ_ACL                 0x00020000
 +#define ACE4_WRITE_ACL                        0x00040000
 +#define ACE4_WRITE_OWNER              0x00080000
 +#define ACE4_SYNCHRONIZE              0x00100000
 +
 +/* Valid ACE4_* flags for directories and non-directories */
 +#define ACE4_VALID_MASK (                             \
 +      ACE4_READ_DATA | ACE4_LIST_DIRECTORY |          \
 +      ACE4_WRITE_DATA | ACE4_ADD_FILE |               \
 +      ACE4_APPEND_DATA | ACE4_ADD_SUBDIRECTORY |      \
 +      ACE4_READ_NAMED_ATTRS |                         \
 +      ACE4_WRITE_NAMED_ATTRS |                        \
 +      ACE4_EXECUTE |                                  \
 +      ACE4_DELETE_CHILD |                             \
 +      ACE4_READ_ATTRIBUTES |                          \
 +      ACE4_WRITE_ATTRIBUTES |                         \
 +      ACE4_WRITE_RETENTION |                          \
 +      ACE4_WRITE_RETENTION_HOLD |                     \
 +      ACE4_DELETE |                                   \
 +      ACE4_READ_ACL |                                 \
 +      ACE4_WRITE_ACL |                                \
 +      ACE4_WRITE_OWNER |                              \
 +      ACE4_SYNCHRONIZE)
 +
 +/*
 + * The POSIX permissions are supersets of the following NFSv4 permissions:
 + *
 + *  - MAY_READ maps to READ_DATA or LIST_DIRECTORY, depending on the type
 + *    of the file system object.
 + *
 + *  - MAY_WRITE maps to WRITE_DATA or ACE4_APPEND_DATA for files, and to
 + *    ADD_FILE, ACE4_ADD_SUBDIRECTORY, or ACE4_DELETE_CHILD for directories.
 + *
 + *  - MAY_EXECUTE maps to ACE4_EXECUTE.
 + *
 + *  (Some of these NFSv4 permissions have the same bit values.)
 + */
 +#define ACE4_POSIX_MODE_READ ( \
 +      ACE4_READ_DATA | ACE4_LIST_DIRECTORY)
 +#define ACE4_POSIX_MODE_WRITE ( \
 +      ACE4_WRITE_DATA | ACE4_ADD_FILE | \
 +      ACE4_APPEND_DATA | ACE4_ADD_SUBDIRECTORY | \
 +      ACE4_DELETE_CHILD)
 +#define ACE4_POSIX_MODE_EXEC ( \
 +      ACE4_EXECUTE)
 +#define ACE4_POSIX_MODE_ALL (ACE4_POSIX_MODE_READ | ACE4_POSIX_MODE_WRITE | \
 +                           ACE4_POSIX_MODE_EXEC)
 +
 +/* These permissions are always allowed no matter what the acl says. */
 +#define ACE4_POSIX_ALWAYS_ALLOWED (   \
 +      ACE4_SYNCHRONIZE |              \
 +      ACE4_READ_ATTRIBUTES |          \
 +      ACE4_READ_ACL)
 +
 +/**
 + * richacl_get  -  grab another reference to a richacl handle
 + */
 +static inline struct richacl *
 +richacl_get(struct richacl *acl)
 +{
 +      if (acl)
 +              atomic_inc(&acl->a_refcount);
 +      return acl;
 +}
 +
 +/**
 + * richacl_put  -  free a richacl handle
 + */
 +static inline void
 +richacl_put(struct richacl *acl)
 +{
 +      if (acl && atomic_dec_and_test(&acl->a_refcount))
 +              kfree(acl);
 +}
 +
 +static inline int
 +richacl_is_auto_inherit(const struct richacl *acl)
 +{
 +      return acl->a_flags & ACL4_AUTO_INHERIT;
 +}
 +
 +static inline int
 +richacl_is_protected(const struct richacl *acl)
 +{
 +      return acl->a_flags & ACL4_PROTECTED;
 +}
 +
 +/*
 + * Special e_who identifiers: we use these pointer values in comparisons
 + * instead of doing a strcmp.
 + */
 +extern const char richace_owner_who[];
 +extern const char richace_group_who[];
 +extern const char richace_everyone_who[];
 +
 +/**
 + * richace_is_owner  -  check if @ace is an OWNER@ entry
 + */
 +static inline int
 +richace_is_owner(const struct richace *ace)
 +{
 +      return (ace->e_flags & ACE4_SPECIAL_WHO) &&
 +             ace->u.e_who == richace_owner_who;
 +}
 +
 +/**
 + * richace_is_group  -  check if @ace is a GROUP@ entry
 + */
 +static inline int
 +richace_is_group(const struct richace *ace)
 +{
 +      return (ace->e_flags & ACE4_SPECIAL_WHO) &&
 +             ace->u.e_who == richace_group_who;
 +}
 +
 +/**
 + * richace_is_everyone  -  check if @ace is an EVERYONE@ entry
 + */
 +static inline int
 +richace_is_everyone(const struct richace *ace)
 +{
 +      return (ace->e_flags & ACE4_SPECIAL_WHO) &&
 +             ace->u.e_who == richace_everyone_who;
 +}
 +
 +/**
 + * richace_is_unix_id  -  check if @ace applies to a specific uid or gid
 + */
 +static inline int
 +richace_is_unix_id(const struct richace *ace)
 +{
 +      return !(ace->e_flags & ACE4_SPECIAL_WHO);
 +}
 +
 +/**
 + * richace_is_inherit_only  -  check if @ace is for inheritance only
 + *
 + * ACEs with the %ACE4_INHERIT_ONLY_ACE flag set have no effect during
 + * permission checking.
 + */
 +static inline int
 +richace_is_inherit_only(const struct richace *ace)
 +{
 +      return ace->e_flags & ACE4_INHERIT_ONLY_ACE;
 +}
 +
 +/**
 + * richace_is_inheritable  -  check if @ace is inheritable
 + */
 +static inline int
 +richace_is_inheritable(const struct richace *ace)
 +{
 +      return ace->e_flags & (ACE4_FILE_INHERIT_ACE |
 +                             ACE4_DIRECTORY_INHERIT_ACE);
 +}
 +
 +/**
 + * richace_clear_inheritance_flags  - clear all inheritance flags in @ace
 + */
 +static inline void
 +richace_clear_inheritance_flags(struct richace *ace)
 +{
 +      ace->e_flags &= ~(ACE4_FILE_INHERIT_ACE |
 +                        ACE4_DIRECTORY_INHERIT_ACE |
 +                        ACE4_NO_PROPAGATE_INHERIT_ACE |
 +                        ACE4_INHERIT_ONLY_ACE);
 +}
 +
 +/**
 + * richace_is_allow  -  check if @ace is an %ALLOW type entry
 + */
 +static inline int
 +richace_is_allow(const struct richace *ace)
 +{
 +      return ace->e_type == ACE4_ACCESS_ALLOWED_ACE_TYPE;
 +}
 +
 +/**
 + * richace_is_deny  -  check if @ace is a %DENY type entry
 + */
 +static inline int
 +richace_is_deny(const struct richace *ace)
 +{
 +      return ace->e_type == ACE4_ACCESS_DENIED_ACE_TYPE;
 +}
 +
 +extern struct richacl *richacl_alloc(int);
 +extern int richace_is_same_identifier(const struct richace *,
 +                                    const struct richace *);
 +extern int richace_set_who(struct richace *, const char *);
 +extern int richacl_masks_to_mode(const struct richacl *);
 +extern unsigned int richacl_mode_to_mask(mode_t);
 +extern unsigned int richacl_want_to_mask(int);
 +extern void richacl_compute_max_masks(struct richacl *);
 +extern struct richacl *richacl_chmod(struct richacl *, mode_t);
 +extern int richacl_permission(struct inode *, const struct richacl *,
-                             unsigned int, unsigned int);
++                            unsigned int);
 +extern struct richacl *richacl_inherit(const struct richacl *, struct inode *);
 +extern int richacl_equiv_mode(const struct richacl *, mode_t *);
 +
 +/* richacl_inode.c */
 +
 +#ifdef CONFIG_FS_RICHACL
 +extern int richacl_may_create(struct inode *, int,
-                             int (*)(struct inode *, unsigned int,
-                                     unsigned int));
++                            int (*)(struct inode *, unsigned int));
 +extern int richacl_may_delete(struct inode *, struct inode *, int,
-                             int (*)(struct inode *, unsigned int,
-                                     unsigned int));
++                            int (*)(struct inode *, unsigned int));
 +extern int richacl_inode_permission(struct inode *, const struct richacl *,
-                                   unsigned int, unsigned int);
++                                  unsigned int);
 +extern int richacl_inode_change_ok(struct inode *, struct iattr *,
-                                  int (*)(struct inode *, unsigned int,
-                                          unsigned int));
++                                 int (*)(struct inode *, unsigned int));
 +#else
 +static inline int
 +richacl_inode_change_ok(struct inode *inode, struct iattr *attr,
 +                      int (*richacl_permission)(struct inode *inode,
-                                                 unsigned int mask,
-                                                 unsigned int flags))
++                                                unsigned int mask))
 +{
 +      return -EPERM;
 +}
 +#endif
 +
 +#endif /* __RICHACL_H */
Simple merge
diff --cc init/Kconfig
Simple merge
diff --cc init/main.c
Simple merge
Simple merge
diff --cc kernel/Makefile
Simple merge
diff --cc kernel/module.c
@@@ -1013,40 -975,27 +1013,57 @@@ static struct module_attribute initstat
        .show = show_initstate,
  };
  
+ static ssize_t store_uevent(struct module_attribute *mattr,
+                           struct module_kobject *mk,
+                           const char *buffer, size_t count)
+ {
+       enum kobject_action action;
+       if (kobject_action_type(buffer, count, &action) == 0)
+               kobject_uevent(&mk->kobj, action);
+       return count;
+ }
+ struct module_attribute module_uevent = {
+       .attr = { .name = "uevent", .mode = 0200 },
+       .store = store_uevent,
+ };
 +#ifdef CONFIG_ENTERPRISE_SUPPORT
 +static void setup_modinfo_supported(struct module *mod, const char *s)
 +{
 +      if (!s) {
 +              mod->taints |= (1 << TAINT_NO_SUPPORT);
 +              return;
 +      }
 +
 +      if (strcmp(s, "external") == 0)
 +              mod->taints |= (1 << TAINT_EXTERNAL_SUPPORT);
 +      else if (strcmp(s, "yes"))
 +              mod->taints |= (1 << TAINT_NO_SUPPORT);
 +}
 +
 +static ssize_t show_modinfo_supported(struct module_attribute *mattr,
 +                      struct module *mod, char *buffer)
 +{
 +      return sprintf(buffer, "%s\n", supported_printable(mod->taints));
 +}
 +
 +static struct module_attribute modinfo_supported = {
 +      .attr = { .name = "supported", .mode = 0444 },
 +      .show = show_modinfo_supported,
 +      .setup = setup_modinfo_supported,
 +};
 +#endif
 +
  static struct module_attribute *modinfo_attrs[] = {
        &modinfo_version,
        &modinfo_srcversion,
        &initstate,
+       &module_uevent,
 +#ifdef CONFIG_ENTERPRISE_SUPPORT
 +      &modinfo_supported,
 +#endif
  #ifdef CONFIG_MODULE_UNLOAD
        &refcnt,
  #endif
diff --cc kernel/panic.c
Simple merge
diff --cc kernel/printk.c
Simple merge
diff --cc kernel/sysctl.c
Simple merge
Simple merge
Simple merge
diff --cc mm/page_alloc.c
Simple merge
diff --cc mm/thrash.c
@@@ -54,13 -52,12 +52,15 @@@ static struct mem_cgroup *swap_token_me
  void grab_swap_token(struct mm_struct *mm)
  {
        int current_interval;
 -      unsigned int old_prio = mm->token_priority;
 +      unsigned int old_prio;
+       static unsigned int global_faults;
+       static unsigned int last_aging;
  
        global_faults++;
 +      if (mm == NULL)
 +              return;
  
 +      old_prio = mm->token_priority;
        current_interval = global_faults - mm->faultstamp;
  
        if (!spin_trylock(&swap_token_lock))
diff --cc mm/truncate.c
@@@ -293,15 -290,9 +290,16 @@@ void truncate_inode_pages_range(struct 
                }
                pagevec_release(&pvec);
                mem_cgroup_uncharge_end();
+               index++;
        }
        cleancache_flush_inode(mapping);
 +      /*
 +       * Cycle the tree_lock to make sure all __delete_from_page_cache()
 +       * calls run from page reclaim have finished as well (this handles the
 +       * case when page reclaim took the last page from our range).
 +       */
 +      spin_lock_irq(&mapping->tree_lock);
 +      spin_unlock_irq(&mapping->tree_lock);
  }
  EXPORT_SYMBOL(truncate_inode_pages_range);
  
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge