#include <linux/mount.h>
 #include <linux/statfs.h>
 #include <linux/ctype.h>
+#include <linux/xattr.h>
 #include "internal.h"
 
 static int cachefiles_daemon_add_cache(struct cachefiles_cache *caches);
        if (d_is_negative(root) ||
            !d_backing_inode(root)->i_op->lookup ||
            !d_backing_inode(root)->i_op->mkdir ||
-           !d_backing_inode(root)->i_op->setxattr ||
-           !d_backing_inode(root)->i_op->getxattr ||
+           !(d_backing_inode(root)->i_opflags & IOP_XATTR) ||
            !root->d_sb->s_op->statfs ||
            !root->d_sb->s_op->sync_fs)
                goto error_unsupported;
 
 #include <linux/namei.h>
 #include <linux/security.h>
 #include <linux/slab.h>
+#include <linux/xattr.h>
 #include "internal.h"
 
 #define CACHEFILES_KEYBUF_SIZE 512
        }
 
        ret = -EPERM;
-       if (!d_backing_inode(subdir)->i_op->setxattr ||
-           !d_backing_inode(subdir)->i_op->getxattr ||
+       if (!(d_backing_inode(subdir)->i_opflags & IOP_XATTR) ||
            !d_backing_inode(subdir)->i_op->lookup ||
            !d_backing_inode(subdir)->i_op->mkdir ||
            !d_backing_inode(subdir)->i_op->create ||
 
                  const char *name, const void *value,
                  size_t size, int flags)
 {
-       int rc = 0;
+       int rc;
        struct dentry *lower_dentry;
 
        lower_dentry = ecryptfs_dentry_to_lower(dentry);
-       if (!d_inode(lower_dentry)->i_op->setxattr) {
+       if (!(d_inode(lower_dentry)->i_opflags & IOP_XATTR)) {
                rc = -EOPNOTSUPP;
                goto out;
        }
-
        rc = vfs_setxattr(lower_dentry, name, value, size, flags);
        if (!rc && inode)
                fsstack_copy_attr_all(inode, d_inode(lower_dentry));
 ecryptfs_getxattr_lower(struct dentry *lower_dentry, struct inode *lower_inode,
                        const char *name, void *value, size_t size)
 {
-       int rc = 0;
+       int rc;
 
-       if (!lower_inode->i_op->getxattr) {
+       if (!(lower_inode->i_opflags & IOP_XATTR)) {
                rc = -EOPNOTSUPP;
                goto out;
        }
        inode_lock(lower_inode);
-       rc = lower_inode->i_op->getxattr(lower_dentry, lower_inode,
-                                        name, value, size);
+       rc = __vfs_getxattr(lower_dentry, lower_inode, name, value, size);
        inode_unlock(lower_inode);
 out:
        return rc;
 static int ecryptfs_removexattr(struct dentry *dentry, struct inode *inode,
                                const char *name)
 {
-       int rc = 0;
+       int rc;
        struct dentry *lower_dentry;
        struct inode *lower_inode;
 
        lower_dentry = ecryptfs_dentry_to_lower(dentry);
        lower_inode = ecryptfs_inode_to_lower(inode);
-       if (!lower_inode->i_op->removexattr) {
+       if (!(lower_inode->i_opflags & IOP_XATTR)) {
                rc = -EOPNOTSUPP;
                goto out;
        }
        inode_lock(lower_inode);
-       rc = lower_inode->i_op->removexattr(lower_dentry, name);
+       rc = __vfs_removexattr(lower_dentry, name);
        inode_unlock(lower_inode);
 out:
        return rc;
 
 #include <linux/file.h>
 #include <linux/scatterlist.h>
 #include <linux/slab.h>
+#include <linux/xattr.h>
 #include <asm/unaligned.h>
 #include "ecryptfs_kernel.h"
 
        struct inode *lower_inode = d_inode(lower_dentry);
        int rc;
 
-       if (!lower_inode->i_op->getxattr || !lower_inode->i_op->setxattr) {
+       if (!(lower_inode->i_opflags & IOP_XATTR)) {
                printk(KERN_WARNING
                       "No support for setting xattr in lower filesystem\n");
                rc = -ENOSYS;
                goto out;
        }
        inode_lock(lower_inode);
-       size = lower_inode->i_op->getxattr(lower_dentry, lower_inode,
-                                          ECRYPTFS_XATTR_NAME,
-                                          xattr_virt, PAGE_SIZE);
+       size = __vfs_getxattr(lower_dentry, lower_inode, ECRYPTFS_XATTR_NAME,
+                             xattr_virt, PAGE_SIZE);
        if (size < 0)
                size = 8;
        put_unaligned_be64(i_size_read(ecryptfs_inode), xattr_virt);
-       rc = lower_inode->i_op->setxattr(lower_dentry, lower_inode,
-                                        ECRYPTFS_XATTR_NAME,
-                                        xattr_virt, size, 0);
+       rc = __vfs_setxattr(lower_dentry, lower_inode, ECRYPTFS_XATTR_NAME,
+                           xattr_virt, size, 0);
        inode_unlock(lower_inode);
        if (rc)
                printk(KERN_ERR "Error whilst attempting to write inode size "
 
        char *buf, *name, *value = NULL;
        int uninitialized_var(error);
 
-       if (!old->d_inode->i_op->getxattr ||
-           !new->d_inode->i_op->getxattr)
+       if (!(old->d_inode->i_opflags & IOP_XATTR) ||
+           !(new->d_inode->i_opflags & IOP_XATTR))
                return 0;
 
        list_size = vfs_listxattr(old, NULL, 0);
 
        char val;
        struct inode *inode = dentry->d_inode;
 
-       if (!S_ISDIR(inode->i_mode) || !inode->i_op->getxattr)
+       if (!S_ISDIR(inode->i_mode) || !(inode->i_opflags & IOP_XATTR))
                return false;
 
-       res = inode->i_op->getxattr(dentry, inode, OVL_XATTR_OPAQUE, &val, 1);
+       res = __vfs_getxattr(dentry, inode, OVL_XATTR_OPAQUE, &val, 1);
        if (res == 1 && val == 'y')
                return true;
 
 
        return inode_permission(inode, mask);
 }
 
+int
+__vfs_setxattr(struct dentry *dentry, struct inode *inode, const char *name,
+              const void *value, size_t size, int flags)
+{
+       if (!inode->i_op->setxattr)
+               return -EOPNOTSUPP;
+       return inode->i_op->setxattr(dentry, inode, name, value, size, flags);
+}
+EXPORT_SYMBOL(__vfs_setxattr);
+
 /**
  *  __vfs_setxattr_noperm - perform setxattr operation without performing
  *  permission checks.
        if (issec)
                inode->i_flags &= ~S_NOSEC;
        if (inode->i_op->setxattr) {
-               error = inode->i_op->setxattr(dentry, inode, name, value, size, flags);
+               error = __vfs_setxattr(dentry, inode, name, value, size, flags);
                if (!error) {
                        fsnotify_xattr(dentry);
                        security_inode_post_setxattr(dentry, name, value,
        return error;
 }
 
+ssize_t
+__vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name,
+              void *value, size_t size)
+{
+       if (!inode->i_op->getxattr)
+               return -EOPNOTSUPP;
+       return inode->i_op->getxattr(dentry, inode, name, value, size);
+}
+EXPORT_SYMBOL(__vfs_getxattr);
+
 ssize_t
 vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
 {
                return ret;
        }
 nolsm:
-       if (inode->i_op->getxattr)
-               error = inode->i_op->getxattr(dentry, inode, name, value, size);
-       else
-               error = -EOPNOTSUPP;
-
-       return error;
-
+       return __vfs_getxattr(dentry, inode, name, value, size);
 }
 EXPORT_SYMBOL_GPL(vfs_getxattr);
 
 EXPORT_SYMBOL_GPL(vfs_listxattr);
 
 int
-vfs_removexattr(struct dentry *dentry, const char *name)
+__vfs_removexattr(struct dentry *dentry, const char *name)
 {
        struct inode *inode = dentry->d_inode;
-       int error;
 
        if (!inode->i_op->removexattr)
                return -EOPNOTSUPP;
+       return inode->i_op->removexattr(dentry, name);
+}
+EXPORT_SYMBOL(__vfs_removexattr);
+
+int
+vfs_removexattr(struct dentry *dentry, const char *name)
+{
+       struct inode *inode = dentry->d_inode;
+       int error;
 
        error = xattr_permission(inode, name, MAY_WRITE);
        if (error)
        if (error)
                goto out;
 
-       error = inode->i_op->removexattr(dentry, name);
+       error = __vfs_removexattr(dentry, name);
 
        if (!error) {
                fsnotify_xattr(dentry);
 
 };
 
 ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t);
+ssize_t __vfs_getxattr(struct dentry *, struct inode *, const char *, void *, size_t);
 ssize_t vfs_getxattr(struct dentry *, const char *, void *, size_t);
 ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size);
+int __vfs_setxattr(struct dentry *, struct inode *, const char *, const void *, size_t, int);
 int __vfs_setxattr_noperm(struct dentry *, const char *, const void *, size_t, int);
 int vfs_setxattr(struct dentry *, const char *, const void *, size_t, int);
+int __vfs_removexattr(struct dentry *, const char *);
 int vfs_removexattr(struct dentry *, const char *);
 
 ssize_t generic_getxattr(struct dentry *dentry, struct inode *inode, const char *name, void *buffer, size_t size);
 
        struct inode *inode = d_backing_inode(dentry);
        int error;
 
-       if (!inode->i_op->getxattr)
-              return 0;
-
-       error = inode->i_op->getxattr(dentry, inode, XATTR_NAME_CAPS, NULL, 0);
-       if (error <= 0)
-               return 0;
-       return 1;
+       error = __vfs_getxattr(dentry, inode, XATTR_NAME_CAPS, NULL, 0);
+       return error > 0;
 }
 
 /**
  */
 int cap_inode_killpriv(struct dentry *dentry)
 {
-       struct inode *inode = d_backing_inode(dentry);
-
-       if (!inode->i_op->removexattr)
-              return 0;
+       int error;
 
-       return inode->i_op->removexattr(dentry, XATTR_NAME_CAPS);
+       error = __vfs_removexattr(dentry, XATTR_NAME_CAPS);
+       if (error == -EOPNOTSUPP)
+               error = 0;
+       return error;
 }
 
 /*
 
        memset(cpu_caps, 0, sizeof(struct cpu_vfs_cap_data));
 
-       if (!inode || !inode->i_op->getxattr)
+       if (!inode)
                return -ENODATA;
 
-       size = inode->i_op->getxattr((struct dentry *)dentry, inode,
-                                    XATTR_NAME_CAPS, &caps, XATTR_CAPS_SZ);
+       size = __vfs_getxattr((struct dentry *)dentry, inode,
+                             XATTR_NAME_CAPS, &caps, XATTR_CAPS_SZ);
        if (size == -ENODATA || size == -EOPNOTSUPP)
                /* no data, that's ok */
                return -ENODATA;
 
        int error;
        int size;
 
-       if (!inode->i_op->getxattr)
+       if (!(inode->i_opflags & IOP_XATTR))
                return -EOPNOTSUPP;
+
        desc = init_desc(type);
        if (IS_ERR(desc))
                return PTR_ERR(desc);
                rc = __vfs_setxattr_noperm(dentry, XATTR_NAME_EVM,
                                           &xattr_data,
                                           sizeof(xattr_data), 0);
-       } else if (rc == -ENODATA && inode->i_op->removexattr) {
-               rc = inode->i_op->removexattr(dentry, XATTR_NAME_EVM);
+       } else if (rc == -ENODATA && (inode->i_opflags & IOP_XATTR)) {
+               rc = __vfs_removexattr(dentry, XATTR_NAME_EVM);
        }
        return rc;
 }
 
        int error;
        int count = 0;
 
-       if (!inode->i_op->getxattr)
+       if (!(inode->i_opflags & IOP_XATTR))
                return -EOPNOTSUPP;
 
        for (xattr = evm_config_xattrnames; *xattr != NULL; xattr++) {
-               error = inode->i_op->getxattr(dentry, inode, *xattr, NULL, 0);
+               error = __vfs_getxattr(dentry, inode, *xattr, NULL, 0);
                if (error < 0) {
                        if (error == -ENODATA)
                                continue;
 
 int ima_read_xattr(struct dentry *dentry,
                   struct evm_ima_xattr_data **xattr_value)
 {
-       struct inode *inode = d_backing_inode(dentry);
-
-       if (!inode->i_op->getxattr)
-               return 0;
+       ssize_t ret;
 
-       return vfs_getxattr_alloc(dentry, XATTR_NAME_IMA, (char **)xattr_value,
-                                 0, GFP_NOFS);
+       ret = vfs_getxattr_alloc(dentry, XATTR_NAME_IMA, (char **)xattr_value,
+                                0, GFP_NOFS);
+       if (ret == -EOPNOTSUPP)
+               ret = 0;
+       return ret;
 }
 
 /*
        enum integrity_status status = INTEGRITY_UNKNOWN;
        int rc = xattr_len, hash_start = 0;
 
-       if (!inode->i_op->getxattr)
+       if (!(inode->i_opflags & IOP_XATTR))
                return INTEGRITY_UNKNOWN;
 
        if (rc <= 0) {
 {
        struct inode *inode = d_backing_inode(dentry);
        struct integrity_iint_cache *iint;
-       int must_appraise, rc;
+       int must_appraise;
 
        if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode)
-           || !inode->i_op->removexattr)
+           || !(inode->i_opflags & IOP_XATTR))
                return;
 
        must_appraise = ima_must_appraise(inode, MAY_ACCESS, POST_SETATTR);
                        iint->flags |= IMA_APPRAISE;
        }
        if (!must_appraise)
-               rc = inode->i_op->removexattr(dentry, XATTR_NAME_IMA);
-       return;
+               __vfs_removexattr(dentry, XATTR_NAME_IMA);
 }
 
 /*
 
                   the root directory.  -ENODATA is ok, as this may be
                   the first boot of the SELinux kernel before we have
                   assigned xattr values to the filesystem. */
-               if (!root_inode->i_op->getxattr) {
+               if (!(root_inode->i_opflags & IOP_XATTR)) {
                        printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
                               "xattr support\n", sb->s_id, sb->s_type->name);
                        rc = -EOPNOTSUPP;
                        goto out;
                }
-               rc = root_inode->i_op->getxattr(root, root_inode,
-                                               XATTR_NAME_SELINUX, NULL, 0);
+
+               rc = __vfs_getxattr(root, root_inode, XATTR_NAME_SELINUX, NULL, 0);
                if (rc < 0 && rc != -ENODATA) {
                        if (rc == -EOPNOTSUPP)
                                printk(KERN_WARNING "SELinux: (dev %s, type "
        case SECURITY_FS_USE_NATIVE:
                break;
        case SECURITY_FS_USE_XATTR:
-               if (!inode->i_op->getxattr) {
+               if (!(inode->i_opflags & IOP_XATTR)) {
                        isec->sid = sbsec->def_sid;
                        break;
                }
-
                /* Need a dentry, since the xattr API requires one.
                   Life would be simpler if we could just pass the inode. */
                if (opt_dentry) {
                        goto out_unlock;
                }
                context[len] = '\0';
-               rc = inode->i_op->getxattr(dentry, inode, XATTR_NAME_SELINUX,
-                                          context, len);
+               rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len);
                if (rc == -ERANGE) {
                        kfree(context);
 
                        /* Need a larger buffer.  Query for the right size. */
-                       rc = inode->i_op->getxattr(dentry, inode, XATTR_NAME_SELINUX,
-                                                  NULL, 0);
+                       rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, NULL, 0);
                        if (rc < 0) {
                                dput(dentry);
                                goto out_unlock;
                                goto out_unlock;
                        }
                        context[len] = '\0';
-                       rc = inode->i_op->getxattr(dentry, inode,
-                                                  XATTR_NAME_SELINUX,
-                                                  context, len);
+                       rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len);
                }
                dput(dentry);
                if (rc < 0) {
 
        char *buffer;
        struct smack_known *skp = NULL;
 
-       if (ip->i_op->getxattr == NULL)
+       if (!(ip->i_opflags & IOP_XATTR))
                return ERR_PTR(-EOPNOTSUPP);
 
        buffer = kzalloc(SMK_LONGLABEL, GFP_KERNEL);
        if (buffer == NULL)
                return ERR_PTR(-ENOMEM);
 
-       rc = ip->i_op->getxattr(dp, ip, name, buffer, SMK_LONGLABEL);
+       rc = __vfs_getxattr(dp, ip, name, buffer, SMK_LONGLABEL);
        if (rc < 0)
                skp = ERR_PTR(rc);
        else if (rc == 0)
                 * It would be curious if the label of the task
                 * does not match that assigned.
                 */
-               if (inode->i_op->getxattr == NULL)
-                       break;
+               if (!(inode->i_opflags & IOP_XATTR))
+                       break;
                /*
                 * Get the dentry for xattr.
                 */
                         */
                        if (isp->smk_flags & SMK_INODE_CHANGED) {
                                isp->smk_flags &= ~SMK_INODE_CHANGED;
-                               rc = inode->i_op->setxattr(dp, inode,
+                               rc = __vfs_setxattr(dp, inode,
                                        XATTR_NAME_SMACKTRANSMUTE,
                                        TRANS_TRUE, TRANS_TRUE_SIZE,
                                        0);
                        } else {
-                               rc = inode->i_op->getxattr(dp, inode,
+                               rc = __vfs_getxattr(dp, inode,
                                        XATTR_NAME_SMACKTRANSMUTE, trattr,
                                        TRANS_TRUE_SIZE);
                                if (rc >= 0 && strncmp(trattr, TRANS_TRUE,