linux/fs/cachefiles/xattr.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/* CacheFiles extended attribute management
   3 *
   4 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
   5 * Written by David Howells (dhowells@redhat.com)
   6 */
   7
   8#include <linux/module.h>
   9#include <linux/sched.h>
  10#include <linux/file.h>
  11#include <linux/fs.h>
  12#include <linux/fsnotify.h>
  13#include <linux/quotaops.h>
  14#include <linux/xattr.h>
  15#include <linux/slab.h>
  16#include "internal.h"
  17
  18static const char cachefiles_xattr_cache[] =
  19        XATTR_USER_PREFIX "CacheFiles.cache";
  20
  21/*
  22 * check the type label on an object
  23 * - done using xattrs
  24 */
  25int cachefiles_check_object_type(struct cachefiles_object *object)
  26{
  27        struct dentry *dentry = object->dentry;
  28        char type[3], xtype[3];
  29        int ret;
  30
  31        ASSERT(dentry);
  32        ASSERT(d_backing_inode(dentry));
  33
  34        if (!object->fscache.cookie)
  35                strcpy(type, "C3");
  36        else
  37                snprintf(type, 3, "%02x", object->fscache.cookie->def->type);
  38
  39        _enter("%x{%s}", object->fscache.debug_id, type);
  40
  41        /* attempt to install a type label directly */
  42        ret = vfs_setxattr(&init_user_ns, dentry, cachefiles_xattr_cache, type,
  43                           2, XATTR_CREATE);
  44        if (ret == 0) {
  45                _debug("SET"); /* we succeeded */
  46                goto error;
  47        }
  48
  49        if (ret != -EEXIST) {
  50                pr_err("Can't set xattr on %pd [%lu] (err %d)\n",
  51                       dentry, d_backing_inode(dentry)->i_ino,
  52                       -ret);
  53                goto error;
  54        }
  55
  56        /* read the current type label */
  57        ret = vfs_getxattr(&init_user_ns, dentry, cachefiles_xattr_cache, xtype,
  58                           3);
  59        if (ret < 0) {
  60                if (ret == -ERANGE)
  61                        goto bad_type_length;
  62
  63                pr_err("Can't read xattr on %pd [%lu] (err %d)\n",
  64                       dentry, d_backing_inode(dentry)->i_ino,
  65                       -ret);
  66                goto error;
  67        }
  68
  69        /* check the type is what we're expecting */
  70        if (ret != 2)
  71                goto bad_type_length;
  72
  73        if (xtype[0] != type[0] || xtype[1] != type[1])
  74                goto bad_type;
  75
  76        ret = 0;
  77
  78error:
  79        _leave(" = %d", ret);
  80        return ret;
  81
  82bad_type_length:
  83        pr_err("Cache object %lu type xattr length incorrect\n",
  84               d_backing_inode(dentry)->i_ino);
  85        ret = -EIO;
  86        goto error;
  87
  88bad_type:
  89        xtype[2] = 0;
  90        pr_err("Cache object %pd [%lu] type %s not %s\n",
  91               dentry, d_backing_inode(dentry)->i_ino,
  92               xtype, type);
  93        ret = -EIO;
  94        goto error;
  95}
  96
  97/*
  98 * set the state xattr on a cache file
  99 */
 100int cachefiles_set_object_xattr(struct cachefiles_object *object,
 101                                struct cachefiles_xattr *auxdata)
 102{
 103        struct dentry *dentry = object->dentry;
 104        int ret;
 105
 106        ASSERT(dentry);
 107
 108        _enter("%p,#%d", object, auxdata->len);
 109
 110        /* attempt to install the cache metadata directly */
 111        _debug("SET #%u", auxdata->len);
 112
 113        clear_bit(FSCACHE_COOKIE_AUX_UPDATED, &object->fscache.cookie->flags);
 114        ret = vfs_setxattr(&init_user_ns, dentry, cachefiles_xattr_cache,
 115                           &auxdata->type, auxdata->len, XATTR_CREATE);
 116        if (ret < 0 && ret != -ENOMEM)
 117                cachefiles_io_error_obj(
 118                        object,
 119                        "Failed to set xattr with error %d", ret);
 120
 121        _leave(" = %d", ret);
 122        return ret;
 123}
 124
 125/*
 126 * update the state xattr on a cache file
 127 */
 128int cachefiles_update_object_xattr(struct cachefiles_object *object,
 129                                   struct cachefiles_xattr *auxdata)
 130{
 131        struct dentry *dentry = object->dentry;
 132        int ret;
 133
 134        if (!dentry)
 135                return -ESTALE;
 136
 137        _enter("%x,#%d", object->fscache.debug_id, auxdata->len);
 138
 139        /* attempt to install the cache metadata directly */
 140        _debug("SET #%u", auxdata->len);
 141
 142        clear_bit(FSCACHE_COOKIE_AUX_UPDATED, &object->fscache.cookie->flags);
 143        ret = vfs_setxattr(&init_user_ns, dentry, cachefiles_xattr_cache,
 144                           &auxdata->type, auxdata->len, XATTR_REPLACE);
 145        if (ret < 0 && ret != -ENOMEM)
 146                cachefiles_io_error_obj(
 147                        object,
 148                        "Failed to update xattr with error %d", ret);
 149
 150        _leave(" = %d", ret);
 151        return ret;
 152}
 153
 154/*
 155 * check the consistency between the backing cache and the FS-Cache cookie
 156 */
 157int cachefiles_check_auxdata(struct cachefiles_object *object)
 158{
 159        struct cachefiles_xattr *auxbuf;
 160        enum fscache_checkaux validity;
 161        struct dentry *dentry = object->dentry;
 162        ssize_t xlen;
 163        int ret;
 164
 165        ASSERT(dentry);
 166        ASSERT(d_backing_inode(dentry));
 167        ASSERT(object->fscache.cookie->def->check_aux);
 168
 169        auxbuf = kmalloc(sizeof(struct cachefiles_xattr) + 512, GFP_KERNEL);
 170        if (!auxbuf)
 171                return -ENOMEM;
 172
 173        xlen = vfs_getxattr(&init_user_ns, dentry, cachefiles_xattr_cache,
 174                            &auxbuf->type, 512 + 1);
 175        ret = -ESTALE;
 176        if (xlen < 1 ||
 177            auxbuf->type != object->fscache.cookie->def->type)
 178                goto error;
 179
 180        xlen--;
 181        validity = fscache_check_aux(&object->fscache, &auxbuf->data, xlen,
 182                                     i_size_read(d_backing_inode(dentry)));
 183        if (validity != FSCACHE_CHECKAUX_OKAY)
 184                goto error;
 185
 186        ret = 0;
 187error:
 188        kfree(auxbuf);
 189        return ret;
 190}
 191
 192/*
 193 * check the state xattr on a cache file
 194 * - return -ESTALE if the object should be deleted
 195 */
 196int cachefiles_check_object_xattr(struct cachefiles_object *object,
 197                                  struct cachefiles_xattr *auxdata)
 198{
 199        struct cachefiles_xattr *auxbuf;
 200        struct dentry *dentry = object->dentry;
 201        int ret;
 202
 203        _enter("%p,#%d", object, auxdata->len);
 204
 205        ASSERT(dentry);
 206        ASSERT(d_backing_inode(dentry));
 207
 208        auxbuf = kmalloc(sizeof(struct cachefiles_xattr) + 512, cachefiles_gfp);
 209        if (!auxbuf) {
 210                _leave(" = -ENOMEM");
 211                return -ENOMEM;
 212        }
 213
 214        /* read the current type label */
 215        ret = vfs_getxattr(&init_user_ns, dentry, cachefiles_xattr_cache,
 216                           &auxbuf->type, 512 + 1);
 217        if (ret < 0) {
 218                if (ret == -ENODATA)
 219                        goto stale; /* no attribute - power went off
 220                                     * mid-cull? */
 221
 222                if (ret == -ERANGE)
 223                        goto bad_type_length;
 224
 225                cachefiles_io_error_obj(object,
 226                                        "Can't read xattr on %lu (err %d)",
 227                                        d_backing_inode(dentry)->i_ino, -ret);
 228                goto error;
 229        }
 230
 231        /* check the on-disk object */
 232        if (ret < 1)
 233                goto bad_type_length;
 234
 235        if (auxbuf->type != auxdata->type)
 236                goto stale;
 237
 238        auxbuf->len = ret;
 239
 240        /* consult the netfs */
 241        if (object->fscache.cookie->def->check_aux) {
 242                enum fscache_checkaux result;
 243                unsigned int dlen;
 244
 245                dlen = auxbuf->len - 1;
 246
 247                _debug("checkaux %s #%u",
 248                       object->fscache.cookie->def->name, dlen);
 249
 250                result = fscache_check_aux(&object->fscache,
 251                                           &auxbuf->data, dlen,
 252                                           i_size_read(d_backing_inode(dentry)));
 253
 254                switch (result) {
 255                        /* entry okay as is */
 256                case FSCACHE_CHECKAUX_OKAY:
 257                        goto okay;
 258
 259                        /* entry requires update */
 260                case FSCACHE_CHECKAUX_NEEDS_UPDATE:
 261                        break;
 262
 263                        /* entry requires deletion */
 264                case FSCACHE_CHECKAUX_OBSOLETE:
 265                        goto stale;
 266
 267                default:
 268                        BUG();
 269                }
 270
 271                /* update the current label */
 272                ret = vfs_setxattr(&init_user_ns, dentry,
 273                                   cachefiles_xattr_cache, &auxdata->type,
 274                                   auxdata->len, XATTR_REPLACE);
 275                if (ret < 0) {
 276                        cachefiles_io_error_obj(object,
 277                                                "Can't update xattr on %lu"
 278                                                " (error %d)",
 279                                                d_backing_inode(dentry)->i_ino, -ret);
 280                        goto error;
 281                }
 282        }
 283
 284okay:
 285        ret = 0;
 286
 287error:
 288        kfree(auxbuf);
 289        _leave(" = %d", ret);
 290        return ret;
 291
 292bad_type_length:
 293        pr_err("Cache object %lu xattr length incorrect\n",
 294               d_backing_inode(dentry)->i_ino);
 295        ret = -EIO;
 296        goto error;
 297
 298stale:
 299        ret = -ESTALE;
 300        goto error;
 301}
 302
 303/*
 304 * remove the object's xattr to mark it stale
 305 */
 306int cachefiles_remove_object_xattr(struct cachefiles_cache *cache,
 307                                   struct dentry *dentry)
 308{
 309        int ret;
 310
 311        ret = vfs_removexattr(&init_user_ns, dentry, cachefiles_xattr_cache);
 312        if (ret < 0) {
 313                if (ret == -ENOENT || ret == -ENODATA)
 314                        ret = 0;
 315                else if (ret != -ENOMEM)
 316                        cachefiles_io_error(cache,
 317                                            "Can't remove xattr from %lu"
 318                                            " (error %d)",
 319                                            d_backing_inode(dentry)->i_ino, -ret);
 320        }
 321
 322        _leave(" = %d", ret);
 323        return ret;
 324}
 325