linux/fs/f2fs/xattr.c
<<
>>
Prefs
   1/*
   2 * fs/f2fs/xattr.c
   3 *
   4 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
   5 *             http://www.samsung.com/
   6 *
   7 * Portions of this code from linux/fs/ext2/xattr.c
   8 *
   9 * Copyright (C) 2001-2003 Andreas Gruenbacher <agruen@suse.de>
  10 *
  11 * Fix by Harrison Xing <harrison@mountainviewdata.com>.
  12 * Extended attributes for symlinks and special files added per
  13 *  suggestion of Luka Renko <luka.renko@hermes.si>.
  14 * xattr consolidation Copyright (c) 2004 James Morris <jmorris@redhat.com>,
  15 *  Red Hat Inc.
  16 *
  17 * This program is free software; you can redistribute it and/or modify
  18 * it under the terms of the GNU General Public License version 2 as
  19 * published by the Free Software Foundation.
  20 */
  21#include <linux/rwsem.h>
  22#include <linux/f2fs_fs.h>
  23#include "f2fs.h"
  24#include "xattr.h"
  25
  26static size_t f2fs_xattr_generic_list(struct dentry *dentry, char *list,
  27                size_t list_size, const char *name, size_t name_len, int type)
  28{
  29        struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
  30        int total_len, prefix_len = 0;
  31        const char *prefix = NULL;
  32
  33        switch (type) {
  34        case F2FS_XATTR_INDEX_USER:
  35                if (!test_opt(sbi, XATTR_USER))
  36                        return -EOPNOTSUPP;
  37                prefix = XATTR_USER_PREFIX;
  38                prefix_len = XATTR_USER_PREFIX_LEN;
  39                break;
  40        case F2FS_XATTR_INDEX_TRUSTED:
  41                if (!capable(CAP_SYS_ADMIN))
  42                        return -EPERM;
  43                prefix = XATTR_TRUSTED_PREFIX;
  44                prefix_len = XATTR_TRUSTED_PREFIX_LEN;
  45                break;
  46        default:
  47                return -EINVAL;
  48        }
  49
  50        total_len = prefix_len + name_len + 1;
  51        if (list && total_len <= list_size) {
  52                memcpy(list, prefix, prefix_len);
  53                memcpy(list+prefix_len, name, name_len);
  54                list[prefix_len + name_len] = '\0';
  55        }
  56        return total_len;
  57}
  58
  59static int f2fs_xattr_generic_get(struct dentry *dentry, const char *name,
  60                void *buffer, size_t size, int type)
  61{
  62        struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
  63
  64        switch (type) {
  65        case F2FS_XATTR_INDEX_USER:
  66                if (!test_opt(sbi, XATTR_USER))
  67                        return -EOPNOTSUPP;
  68                break;
  69        case F2FS_XATTR_INDEX_TRUSTED:
  70                if (!capable(CAP_SYS_ADMIN))
  71                        return -EPERM;
  72                break;
  73        default:
  74                return -EINVAL;
  75        }
  76        if (strcmp(name, "") == 0)
  77                return -EINVAL;
  78        return f2fs_getxattr(dentry->d_inode, type, name,
  79                        buffer, size);
  80}
  81
  82static int f2fs_xattr_generic_set(struct dentry *dentry, const char *name,
  83                const void *value, size_t size, int flags, int type)
  84{
  85        struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb);
  86
  87        switch (type) {
  88        case F2FS_XATTR_INDEX_USER:
  89                if (!test_opt(sbi, XATTR_USER))
  90                        return -EOPNOTSUPP;
  91                break;
  92        case F2FS_XATTR_INDEX_TRUSTED:
  93                if (!capable(CAP_SYS_ADMIN))
  94                        return -EPERM;
  95                break;
  96        default:
  97                return -EINVAL;
  98        }
  99        if (strcmp(name, "") == 0)
 100                return -EINVAL;
 101
 102        return f2fs_setxattr(dentry->d_inode, type, name, value, size);
 103}
 104
 105static size_t f2fs_xattr_advise_list(struct dentry *dentry, char *list,
 106                size_t list_size, const char *name, size_t name_len, int type)
 107{
 108        const char *xname = F2FS_SYSTEM_ADVISE_PREFIX;
 109        size_t size;
 110
 111        if (type != F2FS_XATTR_INDEX_ADVISE)
 112                return 0;
 113
 114        size = strlen(xname) + 1;
 115        if (list && size <= list_size)
 116                memcpy(list, xname, size);
 117        return size;
 118}
 119
 120static int f2fs_xattr_advise_get(struct dentry *dentry, const char *name,
 121                void *buffer, size_t size, int type)
 122{
 123        struct inode *inode = dentry->d_inode;
 124
 125        if (strcmp(name, "") != 0)
 126                return -EINVAL;
 127
 128        *((char *)buffer) = F2FS_I(inode)->i_advise;
 129        return sizeof(char);
 130}
 131
 132static int f2fs_xattr_advise_set(struct dentry *dentry, const char *name,
 133                const void *value, size_t size, int flags, int type)
 134{
 135        struct inode *inode = dentry->d_inode;
 136
 137        if (strcmp(name, "") != 0)
 138                return -EINVAL;
 139        if (!inode_owner_or_capable(inode))
 140                return -EPERM;
 141        if (value == NULL)
 142                return -EINVAL;
 143
 144        F2FS_I(inode)->i_advise |= *(char *)value;
 145        return 0;
 146}
 147
 148const struct xattr_handler f2fs_xattr_user_handler = {
 149        .prefix = XATTR_USER_PREFIX,
 150        .flags  = F2FS_XATTR_INDEX_USER,
 151        .list   = f2fs_xattr_generic_list,
 152        .get    = f2fs_xattr_generic_get,
 153        .set    = f2fs_xattr_generic_set,
 154};
 155
 156const struct xattr_handler f2fs_xattr_trusted_handler = {
 157        .prefix = XATTR_TRUSTED_PREFIX,
 158        .flags  = F2FS_XATTR_INDEX_TRUSTED,
 159        .list   = f2fs_xattr_generic_list,
 160        .get    = f2fs_xattr_generic_get,
 161        .set    = f2fs_xattr_generic_set,
 162};
 163
 164const struct xattr_handler f2fs_xattr_advise_handler = {
 165        .prefix = F2FS_SYSTEM_ADVISE_PREFIX,
 166        .flags  = F2FS_XATTR_INDEX_ADVISE,
 167        .list   = f2fs_xattr_advise_list,
 168        .get    = f2fs_xattr_advise_get,
 169        .set    = f2fs_xattr_advise_set,
 170};
 171
 172static const struct xattr_handler *f2fs_xattr_handler_map[] = {
 173        [F2FS_XATTR_INDEX_USER] = &f2fs_xattr_user_handler,
 174#ifdef CONFIG_F2FS_FS_POSIX_ACL
 175        [F2FS_XATTR_INDEX_POSIX_ACL_ACCESS] = &f2fs_xattr_acl_access_handler,
 176        [F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT] = &f2fs_xattr_acl_default_handler,
 177#endif
 178        [F2FS_XATTR_INDEX_TRUSTED] = &f2fs_xattr_trusted_handler,
 179        [F2FS_XATTR_INDEX_ADVISE] = &f2fs_xattr_advise_handler,
 180};
 181
 182const struct xattr_handler *f2fs_xattr_handlers[] = {
 183        &f2fs_xattr_user_handler,
 184#ifdef CONFIG_F2FS_FS_POSIX_ACL
 185        &f2fs_xattr_acl_access_handler,
 186        &f2fs_xattr_acl_default_handler,
 187#endif
 188        &f2fs_xattr_trusted_handler,
 189        &f2fs_xattr_advise_handler,
 190        NULL,
 191};
 192
 193static inline const struct xattr_handler *f2fs_xattr_handler(int name_index)
 194{
 195        const struct xattr_handler *handler = NULL;
 196
 197        if (name_index > 0 && name_index < ARRAY_SIZE(f2fs_xattr_handler_map))
 198                handler = f2fs_xattr_handler_map[name_index];
 199        return handler;
 200}
 201
 202int f2fs_getxattr(struct inode *inode, int name_index, const char *name,
 203                void *buffer, size_t buffer_size)
 204{
 205        struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
 206        struct f2fs_inode_info *fi = F2FS_I(inode);
 207        struct f2fs_xattr_entry *entry;
 208        struct page *page;
 209        void *base_addr;
 210        int error = 0, found = 0;
 211        size_t value_len, name_len;
 212
 213        if (name == NULL)
 214                return -EINVAL;
 215        name_len = strlen(name);
 216
 217        if (!fi->i_xattr_nid)
 218                return -ENODATA;
 219
 220        page = get_node_page(sbi, fi->i_xattr_nid);
 221        base_addr = page_address(page);
 222
 223        list_for_each_xattr(entry, base_addr) {
 224                if (entry->e_name_index != name_index)
 225                        continue;
 226                if (entry->e_name_len != name_len)
 227                        continue;
 228                if (!memcmp(entry->e_name, name, name_len)) {
 229                        found = 1;
 230                        break;
 231                }
 232        }
 233        if (!found) {
 234                error = -ENODATA;
 235                goto cleanup;
 236        }
 237
 238        value_len = le16_to_cpu(entry->e_value_size);
 239
 240        if (buffer && value_len > buffer_size) {
 241                error = -ERANGE;
 242                goto cleanup;
 243        }
 244
 245        if (buffer) {
 246                char *pval = entry->e_name + entry->e_name_len;
 247                memcpy(buffer, pval, value_len);
 248        }
 249        error = value_len;
 250
 251cleanup:
 252        f2fs_put_page(page, 1);
 253        return error;
 254}
 255
 256ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
 257{
 258        struct inode *inode = dentry->d_inode;
 259        struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
 260        struct f2fs_inode_info *fi = F2FS_I(inode);
 261        struct f2fs_xattr_entry *entry;
 262        struct page *page;
 263        void *base_addr;
 264        int error = 0;
 265        size_t rest = buffer_size;
 266
 267        if (!fi->i_xattr_nid)
 268                return 0;
 269
 270        page = get_node_page(sbi, fi->i_xattr_nid);
 271        base_addr = page_address(page);
 272
 273        list_for_each_xattr(entry, base_addr) {
 274                const struct xattr_handler *handler =
 275                        f2fs_xattr_handler(entry->e_name_index);
 276                size_t size;
 277
 278                if (!handler)
 279                        continue;
 280
 281                size = handler->list(dentry, buffer, rest, entry->e_name,
 282                                entry->e_name_len, handler->flags);
 283                if (buffer && size > rest) {
 284                        error = -ERANGE;
 285                        goto cleanup;
 286                }
 287
 288                if (buffer)
 289                        buffer += size;
 290                rest -= size;
 291        }
 292        error = buffer_size - rest;
 293cleanup:
 294        f2fs_put_page(page, 1);
 295        return error;
 296}
 297
 298int f2fs_setxattr(struct inode *inode, int name_index, const char *name,
 299                                        const void *value, size_t value_len)
 300{
 301        struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
 302        struct f2fs_inode_info *fi = F2FS_I(inode);
 303        struct f2fs_xattr_header *header = NULL;
 304        struct f2fs_xattr_entry *here, *last;
 305        struct page *page;
 306        void *base_addr;
 307        int error, found, free, newsize;
 308        size_t name_len;
 309        char *pval;
 310
 311        if (name == NULL)
 312                return -EINVAL;
 313        name_len = strlen(name);
 314
 315        if (value == NULL)
 316                value_len = 0;
 317
 318        if (name_len > 255 || value_len > MAX_VALUE_LEN)
 319                return -ERANGE;
 320
 321        f2fs_balance_fs(sbi);
 322
 323        mutex_lock_op(sbi, NODE_NEW);
 324        if (!fi->i_xattr_nid) {
 325                /* Allocate new attribute block */
 326                struct dnode_of_data dn;
 327
 328                if (!alloc_nid(sbi, &fi->i_xattr_nid)) {
 329                        mutex_unlock_op(sbi, NODE_NEW);
 330                        return -ENOSPC;
 331                }
 332                set_new_dnode(&dn, inode, NULL, NULL, fi->i_xattr_nid);
 333                mark_inode_dirty(inode);
 334
 335                page = new_node_page(&dn, XATTR_NODE_OFFSET);
 336                if (IS_ERR(page)) {
 337                        alloc_nid_failed(sbi, fi->i_xattr_nid);
 338                        fi->i_xattr_nid = 0;
 339                        mutex_unlock_op(sbi, NODE_NEW);
 340                        return PTR_ERR(page);
 341                }
 342
 343                alloc_nid_done(sbi, fi->i_xattr_nid);
 344                base_addr = page_address(page);
 345                header = XATTR_HDR(base_addr);
 346                header->h_magic = cpu_to_le32(F2FS_XATTR_MAGIC);
 347                header->h_refcount = cpu_to_le32(1);
 348        } else {
 349                /* The inode already has an extended attribute block. */
 350                page = get_node_page(sbi, fi->i_xattr_nid);
 351                if (IS_ERR(page)) {
 352                        mutex_unlock_op(sbi, NODE_NEW);
 353                        return PTR_ERR(page);
 354                }
 355
 356                base_addr = page_address(page);
 357                header = XATTR_HDR(base_addr);
 358        }
 359
 360        if (le32_to_cpu(header->h_magic) != F2FS_XATTR_MAGIC) {
 361                error = -EIO;
 362                goto cleanup;
 363        }
 364
 365        /* find entry with wanted name. */
 366        found = 0;
 367        list_for_each_xattr(here, base_addr) {
 368                if (here->e_name_index != name_index)
 369                        continue;
 370                if (here->e_name_len != name_len)
 371                        continue;
 372                if (!memcmp(here->e_name, name, name_len)) {
 373                        found = 1;
 374                        break;
 375                }
 376        }
 377
 378        last = here;
 379
 380        while (!IS_XATTR_LAST_ENTRY(last))
 381                last = XATTR_NEXT_ENTRY(last);
 382
 383        newsize = XATTR_ALIGN(sizeof(struct f2fs_xattr_entry) +
 384                        name_len + value_len);
 385
 386        /* 1. Check space */
 387        if (value) {
 388                /* If value is NULL, it is remove operation.
 389                 * In case of update operation, we caculate free.
 390                 */
 391                free = MIN_OFFSET - ((char *)last - (char *)header);
 392                if (found)
 393                        free = free - ENTRY_SIZE(here);
 394
 395                if (free < newsize) {
 396                        error = -ENOSPC;
 397                        goto cleanup;
 398                }
 399        }
 400
 401        /* 2. Remove old entry */
 402        if (found) {
 403                /* If entry is found, remove old entry.
 404                 * If not found, remove operation is not needed.
 405                 */
 406                struct f2fs_xattr_entry *next = XATTR_NEXT_ENTRY(here);
 407                int oldsize = ENTRY_SIZE(here);
 408
 409                memmove(here, next, (char *)last - (char *)next);
 410                last = (struct f2fs_xattr_entry *)((char *)last - oldsize);
 411                memset(last, 0, oldsize);
 412        }
 413
 414        /* 3. Write new entry */
 415        if (value) {
 416                /* Before we come here, old entry is removed.
 417                 * We just write new entry. */
 418                memset(last, 0, newsize);
 419                last->e_name_index = name_index;
 420                last->e_name_len = name_len;
 421                memcpy(last->e_name, name, name_len);
 422                pval = last->e_name + name_len;
 423                memcpy(pval, value, value_len);
 424                last->e_value_size = cpu_to_le16(value_len);
 425        }
 426
 427        set_page_dirty(page);
 428        f2fs_put_page(page, 1);
 429
 430        if (is_inode_flag_set(fi, FI_ACL_MODE)) {
 431                inode->i_mode = fi->i_acl_mode;
 432                inode->i_ctime = CURRENT_TIME;
 433                clear_inode_flag(fi, FI_ACL_MODE);
 434        }
 435        f2fs_write_inode(inode, NULL);
 436        mutex_unlock_op(sbi, NODE_NEW);
 437
 438        return 0;
 439cleanup:
 440        f2fs_put_page(page, 1);
 441        mutex_unlock_op(sbi, NODE_NEW);
 442        return error;
 443}
 444