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