linux/fs/xfs/linux-2.6/xfs_iops.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
   3 * All Rights Reserved.
   4 *
   5 * This program is free software; you can redistribute it and/or
   6 * modify it under the terms of the GNU General Public License as
   7 * published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope that it would be useful,
  10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12 * GNU General Public License for more details.
  13 *
  14 * You should have received a copy of the GNU General Public License
  15 * along with this program; if not, write the Free Software Foundation,
  16 * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  17 */
  18#include "xfs.h"
  19#include "xfs_fs.h"
  20#include "xfs_bit.h"
  21#include "xfs_log.h"
  22#include "xfs_inum.h"
  23#include "xfs_trans.h"
  24#include "xfs_sb.h"
  25#include "xfs_ag.h"
  26#include "xfs_dir2.h"
  27#include "xfs_alloc.h"
  28#include "xfs_dmapi.h"
  29#include "xfs_quota.h"
  30#include "xfs_mount.h"
  31#include "xfs_bmap_btree.h"
  32#include "xfs_alloc_btree.h"
  33#include "xfs_ialloc_btree.h"
  34#include "xfs_dir2_sf.h"
  35#include "xfs_attr_sf.h"
  36#include "xfs_dinode.h"
  37#include "xfs_inode.h"
  38#include "xfs_bmap.h"
  39#include "xfs_btree.h"
  40#include "xfs_ialloc.h"
  41#include "xfs_rtalloc.h"
  42#include "xfs_error.h"
  43#include "xfs_itable.h"
  44#include "xfs_rw.h"
  45#include "xfs_acl.h"
  46#include "xfs_attr.h"
  47#include "xfs_buf_item.h"
  48#include "xfs_utils.h"
  49#include "xfs_vnodeops.h"
  50
  51#include <linux/capability.h>
  52#include <linux/xattr.h>
  53#include <linux/namei.h>
  54#include <linux/security.h>
  55
  56/*
  57 * Bring the atime in the XFS inode uptodate.
  58 * Used before logging the inode to disk or when the Linux inode goes away.
  59 */
  60void
  61xfs_synchronize_atime(
  62        xfs_inode_t     *ip)
  63{
  64        bhv_vnode_t     *vp;
  65
  66        vp = XFS_ITOV_NULL(ip);
  67        if (vp) {
  68                ip->i_d.di_atime.t_sec = (__int32_t)vp->i_atime.tv_sec;
  69                ip->i_d.di_atime.t_nsec = (__int32_t)vp->i_atime.tv_nsec;
  70        }
  71}
  72
  73/*
  74 * Change the requested timestamp in the given inode.
  75 * We don't lock across timestamp updates, and we don't log them but
  76 * we do record the fact that there is dirty information in core.
  77 *
  78 * NOTE -- callers MUST combine XFS_ICHGTIME_MOD or XFS_ICHGTIME_CHG
  79 *              with XFS_ICHGTIME_ACC to be sure that access time
  80 *              update will take.  Calling first with XFS_ICHGTIME_ACC
  81 *              and then XFS_ICHGTIME_MOD may fail to modify the access
  82 *              timestamp if the filesystem is mounted noacctm.
  83 */
  84void
  85xfs_ichgtime(
  86        xfs_inode_t     *ip,
  87        int             flags)
  88{
  89        struct inode    *inode = vn_to_inode(XFS_ITOV(ip));
  90        timespec_t      tv;
  91
  92        nanotime(&tv);
  93        if (flags & XFS_ICHGTIME_MOD) {
  94                inode->i_mtime = tv;
  95                ip->i_d.di_mtime.t_sec = (__int32_t)tv.tv_sec;
  96                ip->i_d.di_mtime.t_nsec = (__int32_t)tv.tv_nsec;
  97        }
  98        if (flags & XFS_ICHGTIME_ACC) {
  99                inode->i_atime = tv;
 100                ip->i_d.di_atime.t_sec = (__int32_t)tv.tv_sec;
 101                ip->i_d.di_atime.t_nsec = (__int32_t)tv.tv_nsec;
 102        }
 103        if (flags & XFS_ICHGTIME_CHG) {
 104                inode->i_ctime = tv;
 105                ip->i_d.di_ctime.t_sec = (__int32_t)tv.tv_sec;
 106                ip->i_d.di_ctime.t_nsec = (__int32_t)tv.tv_nsec;
 107        }
 108
 109        /*
 110         * We update the i_update_core field _after_ changing
 111         * the timestamps in order to coordinate properly with
 112         * xfs_iflush() so that we don't lose timestamp updates.
 113         * This keeps us from having to hold the inode lock
 114         * while doing this.  We use the SYNCHRONIZE macro to
 115         * ensure that the compiler does not reorder the update
 116         * of i_update_core above the timestamp updates above.
 117         */
 118        SYNCHRONIZE();
 119        ip->i_update_core = 1;
 120        if (!(inode->i_state & I_NEW))
 121                mark_inode_dirty_sync(inode);
 122}
 123
 124/*
 125 * Variant on the above which avoids querying the system clock
 126 * in situations where we know the Linux inode timestamps have
 127 * just been updated (and so we can update our inode cheaply).
 128 */
 129void
 130xfs_ichgtime_fast(
 131        xfs_inode_t     *ip,
 132        struct inode    *inode,
 133        int             flags)
 134{
 135        timespec_t      *tvp;
 136
 137        /*
 138         * Atime updates for read() & friends are handled lazily now, and
 139         * explicit updates must go through xfs_ichgtime()
 140         */
 141        ASSERT((flags & XFS_ICHGTIME_ACC) == 0);
 142
 143        /*
 144         * We're not supposed to change timestamps in readonly-mounted
 145         * filesystems.  Throw it away if anyone asks us.
 146         */
 147        if (unlikely(IS_RDONLY(inode)))
 148                return;
 149
 150        if (flags & XFS_ICHGTIME_MOD) {
 151                tvp = &inode->i_mtime;
 152                ip->i_d.di_mtime.t_sec = (__int32_t)tvp->tv_sec;
 153                ip->i_d.di_mtime.t_nsec = (__int32_t)tvp->tv_nsec;
 154        }
 155        if (flags & XFS_ICHGTIME_CHG) {
 156                tvp = &inode->i_ctime;
 157                ip->i_d.di_ctime.t_sec = (__int32_t)tvp->tv_sec;
 158                ip->i_d.di_ctime.t_nsec = (__int32_t)tvp->tv_nsec;
 159        }
 160
 161        /*
 162         * We update the i_update_core field _after_ changing
 163         * the timestamps in order to coordinate properly with
 164         * xfs_iflush() so that we don't lose timestamp updates.
 165         * This keeps us from having to hold the inode lock
 166         * while doing this.  We use the SYNCHRONIZE macro to
 167         * ensure that the compiler does not reorder the update
 168         * of i_update_core above the timestamp updates above.
 169         */
 170        SYNCHRONIZE();
 171        ip->i_update_core = 1;
 172        if (!(inode->i_state & I_NEW))
 173                mark_inode_dirty_sync(inode);
 174}
 175
 176
 177/*
 178 * Pull the link count and size up from the xfs inode to the linux inode
 179 */
 180STATIC void
 181xfs_validate_fields(
 182        struct inode            *inode)
 183{
 184        struct xfs_inode        *ip = XFS_I(inode);
 185        loff_t size;
 186
 187        inode->i_nlink = ip->i_d.di_nlink;
 188        inode->i_blocks =
 189                XFS_FSB_TO_BB(ip->i_mount, ip->i_d.di_nblocks +
 190                                           ip->i_delayed_blks);
 191        /* we're under i_sem so i_size can't change under us */
 192        size = XFS_ISIZE(ip);
 193        if (i_size_read(inode) != size)
 194                i_size_write(inode, size);
 195}
 196
 197/*
 198 * Hook in SELinux.  This is not quite correct yet, what we really need
 199 * here (as we do for default ACLs) is a mechanism by which creation of
 200 * these attrs can be journalled at inode creation time (along with the
 201 * inode, of course, such that log replay can't cause these to be lost).
 202 */
 203STATIC int
 204xfs_init_security(
 205        bhv_vnode_t     *vp,
 206        struct inode    *dir)
 207{
 208        struct inode    *ip = vn_to_inode(vp);
 209        size_t          length;
 210        void            *value;
 211        char            *name;
 212        int             error;
 213
 214        error = security_inode_init_security(ip, dir, &name, &value, &length);
 215        if (error) {
 216                if (error == -EOPNOTSUPP)
 217                        return 0;
 218                return -error;
 219        }
 220
 221        error = xfs_attr_set(XFS_I(ip), name, value,
 222                        length, ATTR_SECURE);
 223        if (!error)
 224                xfs_iflags_set(XFS_I(ip), XFS_IMODIFIED);
 225
 226        kfree(name);
 227        kfree(value);
 228        return error;
 229}
 230
 231/*
 232 * Determine whether a process has a valid fs_struct (kernel daemons
 233 * like knfsd don't have an fs_struct).
 234 *
 235 * XXX(hch):  nfsd is broken, better fix it instead.
 236 */
 237STATIC_INLINE int
 238xfs_has_fs_struct(struct task_struct *task)
 239{
 240        return (task->fs != init_task.fs);
 241}
 242
 243STATIC void
 244xfs_cleanup_inode(
 245        struct inode    *dir,
 246        bhv_vnode_t     *vp,
 247        struct dentry   *dentry,
 248        int             mode)
 249{
 250        struct dentry   teardown = {};
 251
 252        /* Oh, the horror.
 253         * If we can't add the ACL or we fail in
 254         * xfs_init_security we must back out.
 255         * ENOSPC can hit here, among other things.
 256         */
 257        teardown.d_inode = vn_to_inode(vp);
 258        teardown.d_name = dentry->d_name;
 259
 260        if (S_ISDIR(mode))
 261                xfs_rmdir(XFS_I(dir), &teardown);
 262        else
 263                xfs_remove(XFS_I(dir), &teardown);
 264        VN_RELE(vp);
 265}
 266
 267STATIC int
 268xfs_vn_mknod(
 269        struct inode    *dir,
 270        struct dentry   *dentry,
 271        int             mode,
 272        dev_t           rdev)
 273{
 274        struct inode    *ip;
 275        bhv_vnode_t     *vp = NULL, *dvp = vn_from_inode(dir);
 276        xfs_acl_t       *default_acl = NULL;
 277        attrexists_t    test_default_acl = _ACL_DEFAULT_EXISTS;
 278        int             error;
 279
 280        /*
 281         * Irix uses Missed'em'V split, but doesn't want to see
 282         * the upper 5 bits of (14bit) major.
 283         */
 284        if (unlikely(!sysv_valid_dev(rdev) || MAJOR(rdev) & ~0x1ff))
 285                return -EINVAL;
 286
 287        if (unlikely(test_default_acl && test_default_acl(dvp))) {
 288                if (!_ACL_ALLOC(default_acl)) {
 289                        return -ENOMEM;
 290                }
 291                if (!_ACL_GET_DEFAULT(dvp, default_acl)) {
 292                        _ACL_FREE(default_acl);
 293                        default_acl = NULL;
 294                }
 295        }
 296
 297        if (IS_POSIXACL(dir) && !default_acl && xfs_has_fs_struct(current))
 298                mode &= ~current->fs->umask;
 299
 300        switch (mode & S_IFMT) {
 301        case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK:
 302                rdev = sysv_encode_dev(rdev);
 303        case S_IFREG:
 304                error = xfs_create(XFS_I(dir), dentry, mode, rdev, &vp, NULL);
 305                break;
 306        case S_IFDIR:
 307                error = xfs_mkdir(XFS_I(dir), dentry, mode, &vp, NULL);
 308                break;
 309        default:
 310                error = EINVAL;
 311                break;
 312        }
 313
 314        if (unlikely(!error)) {
 315                error = xfs_init_security(vp, dir);
 316                if (error)
 317                        xfs_cleanup_inode(dir, vp, dentry, mode);
 318        }
 319
 320        if (unlikely(default_acl)) {
 321                if (!error) {
 322                        error = _ACL_INHERIT(vp, mode, default_acl);
 323                        if (!error)
 324                                xfs_iflags_set(XFS_I(vp), XFS_IMODIFIED);
 325                        else
 326                                xfs_cleanup_inode(dir, vp, dentry, mode);
 327                }
 328                _ACL_FREE(default_acl);
 329        }
 330
 331        if (likely(!error)) {
 332                ASSERT(vp);
 333                ip = vn_to_inode(vp);
 334
 335                if (S_ISDIR(mode))
 336                        xfs_validate_fields(ip);
 337                d_instantiate(dentry, ip);
 338                xfs_validate_fields(dir);
 339        }
 340        return -error;
 341}
 342
 343STATIC int
 344xfs_vn_create(
 345        struct inode    *dir,
 346        struct dentry   *dentry,
 347        int             mode,
 348        struct nameidata *nd)
 349{
 350        return xfs_vn_mknod(dir, dentry, mode, 0);
 351}
 352
 353STATIC int
 354xfs_vn_mkdir(
 355        struct inode    *dir,
 356        struct dentry   *dentry,
 357        int             mode)
 358{
 359        return xfs_vn_mknod(dir, dentry, mode|S_IFDIR, 0);
 360}
 361
 362STATIC struct dentry *
 363xfs_vn_lookup(
 364        struct inode    *dir,
 365        struct dentry   *dentry,
 366        struct nameidata *nd)
 367{
 368        bhv_vnode_t     *cvp;
 369        int             error;
 370
 371        if (dentry->d_name.len >= MAXNAMELEN)
 372                return ERR_PTR(-ENAMETOOLONG);
 373
 374        error = xfs_lookup(XFS_I(dir), dentry, &cvp);
 375        if (unlikely(error)) {
 376                if (unlikely(error != ENOENT))
 377                        return ERR_PTR(-error);
 378                d_add(dentry, NULL);
 379                return NULL;
 380        }
 381
 382        return d_splice_alias(vn_to_inode(cvp), dentry);
 383}
 384
 385STATIC int
 386xfs_vn_link(
 387        struct dentry   *old_dentry,
 388        struct inode    *dir,
 389        struct dentry   *dentry)
 390{
 391        struct inode    *ip;    /* inode of guy being linked to */
 392        bhv_vnode_t     *vp;    /* vp of name being linked */
 393        int             error;
 394
 395        ip = old_dentry->d_inode;       /* inode being linked to */
 396        vp = vn_from_inode(ip);
 397
 398        VN_HOLD(vp);
 399        error = xfs_link(XFS_I(dir), vp, dentry);
 400        if (unlikely(error)) {
 401                VN_RELE(vp);
 402        } else {
 403                xfs_iflags_set(XFS_I(dir), XFS_IMODIFIED);
 404                xfs_validate_fields(ip);
 405                d_instantiate(dentry, ip);
 406        }
 407        return -error;
 408}
 409
 410STATIC int
 411xfs_vn_unlink(
 412        struct inode    *dir,
 413        struct dentry   *dentry)
 414{
 415        struct inode    *inode;
 416        int             error;
 417
 418        inode = dentry->d_inode;
 419
 420        error = xfs_remove(XFS_I(dir), dentry);
 421        if (likely(!error)) {
 422                xfs_validate_fields(dir);       /* size needs update */
 423                xfs_validate_fields(inode);
 424        }
 425        return -error;
 426}
 427
 428STATIC int
 429xfs_vn_symlink(
 430        struct inode    *dir,
 431        struct dentry   *dentry,
 432        const char      *symname)
 433{
 434        struct inode    *ip;
 435        bhv_vnode_t     *cvp;   /* used to lookup symlink to put in dentry */
 436        int             error;
 437        mode_t          mode;
 438
 439        cvp = NULL;
 440
 441        mode = S_IFLNK |
 442                (irix_symlink_mode ? 0777 & ~current->fs->umask : S_IRWXUGO);
 443
 444        error = xfs_symlink(XFS_I(dir), dentry, (char *)symname, mode,
 445                            &cvp, NULL);
 446        if (likely(!error && cvp)) {
 447                error = xfs_init_security(cvp, dir);
 448                if (likely(!error)) {
 449                        ip = vn_to_inode(cvp);
 450                        d_instantiate(dentry, ip);
 451                        xfs_validate_fields(dir);
 452                        xfs_validate_fields(ip);
 453                } else {
 454                        xfs_cleanup_inode(dir, cvp, dentry, 0);
 455                }
 456        }
 457        return -error;
 458}
 459
 460STATIC int
 461xfs_vn_rmdir(
 462        struct inode    *dir,
 463        struct dentry   *dentry)
 464{
 465        struct inode    *inode = dentry->d_inode;
 466        int             error;
 467
 468        error = xfs_rmdir(XFS_I(dir), dentry);
 469        if (likely(!error)) {
 470                xfs_validate_fields(inode);
 471                xfs_validate_fields(dir);
 472        }
 473        return -error;
 474}
 475
 476STATIC int
 477xfs_vn_rename(
 478        struct inode    *odir,
 479        struct dentry   *odentry,
 480        struct inode    *ndir,
 481        struct dentry   *ndentry)
 482{
 483        struct inode    *new_inode = ndentry->d_inode;
 484        bhv_vnode_t     *tvp;   /* target directory */
 485        int             error;
 486
 487        tvp = vn_from_inode(ndir);
 488
 489        error = xfs_rename(XFS_I(odir), odentry, tvp, ndentry);
 490        if (likely(!error)) {
 491                if (new_inode)
 492                        xfs_validate_fields(new_inode);
 493                xfs_validate_fields(odir);
 494                if (ndir != odir)
 495                        xfs_validate_fields(ndir);
 496        }
 497        return -error;
 498}
 499
 500/*
 501 * careful here - this function can get called recursively, so
 502 * we need to be very careful about how much stack we use.
 503 * uio is kmalloced for this reason...
 504 */
 505STATIC void *
 506xfs_vn_follow_link(
 507        struct dentry           *dentry,
 508        struct nameidata        *nd)
 509{
 510        char                    *link;
 511        int                     error = -ENOMEM;
 512
 513        link = kmalloc(MAXPATHLEN+1, GFP_KERNEL);
 514        if (!link)
 515                goto out_err;
 516
 517        error = -xfs_readlink(XFS_I(dentry->d_inode), link);
 518        if (unlikely(error))
 519                goto out_kfree;
 520
 521        nd_set_link(nd, link);
 522        return NULL;
 523
 524 out_kfree:
 525        kfree(link);
 526 out_err:
 527        nd_set_link(nd, ERR_PTR(error));
 528        return NULL;
 529}
 530
 531STATIC void
 532xfs_vn_put_link(
 533        struct dentry   *dentry,
 534        struct nameidata *nd,
 535        void            *p)
 536{
 537        char            *s = nd_get_link(nd);
 538
 539        if (!IS_ERR(s))
 540                kfree(s);
 541}
 542
 543#ifdef CONFIG_XFS_POSIX_ACL
 544STATIC int
 545xfs_vn_permission(
 546        struct inode    *inode,
 547        int             mode,
 548        struct nameidata *nd)
 549{
 550        return -xfs_access(XFS_I(inode), mode << 6, NULL);
 551}
 552#else
 553#define xfs_vn_permission NULL
 554#endif
 555
 556STATIC int
 557xfs_vn_getattr(
 558        struct vfsmount *mnt,
 559        struct dentry   *dentry,
 560        struct kstat    *stat)
 561{
 562        struct inode    *inode = dentry->d_inode;
 563        bhv_vattr_t     vattr = { .va_mask = XFS_AT_STAT };
 564        int             error;
 565
 566        error = xfs_getattr(XFS_I(inode), &vattr, ATTR_LAZY);
 567        if (likely(!error)) {
 568                stat->size = i_size_read(inode);
 569                stat->dev = inode->i_sb->s_dev;
 570                stat->rdev = (vattr.va_rdev == 0) ? 0 :
 571                                MKDEV(sysv_major(vattr.va_rdev) & 0x1ff,
 572                                      sysv_minor(vattr.va_rdev));
 573                stat->mode = vattr.va_mode;
 574                stat->nlink = vattr.va_nlink;
 575                stat->uid = vattr.va_uid;
 576                stat->gid = vattr.va_gid;
 577                stat->ino = vattr.va_nodeid;
 578                stat->atime = vattr.va_atime;
 579                stat->mtime = vattr.va_mtime;
 580                stat->ctime = vattr.va_ctime;
 581                stat->blocks = vattr.va_nblocks;
 582                stat->blksize = vattr.va_blocksize;
 583        }
 584        return -error;
 585}
 586
 587STATIC int
 588xfs_vn_setattr(
 589        struct dentry   *dentry,
 590        struct iattr    *attr)
 591{
 592        struct inode    *inode = dentry->d_inode;
 593        unsigned int    ia_valid = attr->ia_valid;
 594        bhv_vattr_t     vattr = { 0 };
 595        int             flags = 0;
 596        int             error;
 597
 598        if (ia_valid & ATTR_UID) {
 599                vattr.va_mask |= XFS_AT_UID;
 600                vattr.va_uid = attr->ia_uid;
 601        }
 602        if (ia_valid & ATTR_GID) {
 603                vattr.va_mask |= XFS_AT_GID;
 604                vattr.va_gid = attr->ia_gid;
 605        }
 606        if (ia_valid & ATTR_SIZE) {
 607                vattr.va_mask |= XFS_AT_SIZE;
 608                vattr.va_size = attr->ia_size;
 609        }
 610        if (ia_valid & ATTR_ATIME) {
 611                vattr.va_mask |= XFS_AT_ATIME;
 612                vattr.va_atime = attr->ia_atime;
 613                inode->i_atime = attr->ia_atime;
 614        }
 615        if (ia_valid & ATTR_MTIME) {
 616                vattr.va_mask |= XFS_AT_MTIME;
 617                vattr.va_mtime = attr->ia_mtime;
 618        }
 619        if (ia_valid & ATTR_CTIME) {
 620                vattr.va_mask |= XFS_AT_CTIME;
 621                vattr.va_ctime = attr->ia_ctime;
 622        }
 623        if (ia_valid & ATTR_MODE) {
 624                vattr.va_mask |= XFS_AT_MODE;
 625                vattr.va_mode = attr->ia_mode;
 626                if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
 627                        inode->i_mode &= ~S_ISGID;
 628        }
 629
 630        if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET))
 631                flags |= ATTR_UTIME;
 632#ifdef ATTR_NO_BLOCK
 633        if ((ia_valid & ATTR_NO_BLOCK))
 634                flags |= ATTR_NONBLOCK;
 635#endif
 636
 637        error = xfs_setattr(XFS_I(inode), &vattr, flags, NULL);
 638        if (likely(!error))
 639                __vn_revalidate(vn_from_inode(inode), &vattr);
 640        return -error;
 641}
 642
 643STATIC void
 644xfs_vn_truncate(
 645        struct inode    *inode)
 646{
 647        block_truncate_page(inode->i_mapping, inode->i_size, xfs_get_blocks);
 648}
 649
 650STATIC int
 651xfs_vn_setxattr(
 652        struct dentry   *dentry,
 653        const char      *name,
 654        const void      *data,
 655        size_t          size,
 656        int             flags)
 657{
 658        bhv_vnode_t     *vp = vn_from_inode(dentry->d_inode);
 659        char            *attr = (char *)name;
 660        attrnames_t     *namesp;
 661        int             xflags = 0;
 662        int             error;
 663
 664        namesp = attr_lookup_namespace(attr, attr_namespaces, ATTR_NAMECOUNT);
 665        if (!namesp)
 666                return -EOPNOTSUPP;
 667        attr += namesp->attr_namelen;
 668        error = namesp->attr_capable(vp, NULL);
 669        if (error)
 670                return error;
 671
 672        /* Convert Linux syscall to XFS internal ATTR flags */
 673        if (flags & XATTR_CREATE)
 674                xflags |= ATTR_CREATE;
 675        if (flags & XATTR_REPLACE)
 676                xflags |= ATTR_REPLACE;
 677        xflags |= namesp->attr_flag;
 678        return namesp->attr_set(vp, attr, (void *)data, size, xflags);
 679}
 680
 681STATIC ssize_t
 682xfs_vn_getxattr(
 683        struct dentry   *dentry,
 684        const char      *name,
 685        void            *data,
 686        size_t          size)
 687{
 688        bhv_vnode_t     *vp = vn_from_inode(dentry->d_inode);
 689        char            *attr = (char *)name;
 690        attrnames_t     *namesp;
 691        int             xflags = 0;
 692        ssize_t         error;
 693
 694        namesp = attr_lookup_namespace(attr, attr_namespaces, ATTR_NAMECOUNT);
 695        if (!namesp)
 696                return -EOPNOTSUPP;
 697        attr += namesp->attr_namelen;
 698        error = namesp->attr_capable(vp, NULL);
 699        if (error)
 700                return error;
 701
 702        /* Convert Linux syscall to XFS internal ATTR flags */
 703        if (!size) {
 704                xflags |= ATTR_KERNOVAL;
 705                data = NULL;
 706        }
 707        xflags |= namesp->attr_flag;
 708        return namesp->attr_get(vp, attr, (void *)data, size, xflags);
 709}
 710
 711STATIC ssize_t
 712xfs_vn_listxattr(
 713        struct dentry           *dentry,
 714        char                    *data,
 715        size_t                  size)
 716{
 717        bhv_vnode_t             *vp = vn_from_inode(dentry->d_inode);
 718        int                     error, xflags = ATTR_KERNAMELS;
 719        ssize_t                 result;
 720
 721        if (!size)
 722                xflags |= ATTR_KERNOVAL;
 723        xflags |= capable(CAP_SYS_ADMIN) ? ATTR_KERNFULLS : ATTR_KERNORMALS;
 724
 725        error = attr_generic_list(vp, data, size, xflags, &result);
 726        if (error < 0)
 727                return error;
 728        return result;
 729}
 730
 731STATIC int
 732xfs_vn_removexattr(
 733        struct dentry   *dentry,
 734        const char      *name)
 735{
 736        bhv_vnode_t     *vp = vn_from_inode(dentry->d_inode);
 737        char            *attr = (char *)name;
 738        attrnames_t     *namesp;
 739        int             xflags = 0;
 740        int             error;
 741
 742        namesp = attr_lookup_namespace(attr, attr_namespaces, ATTR_NAMECOUNT);
 743        if (!namesp)
 744                return -EOPNOTSUPP;
 745        attr += namesp->attr_namelen;
 746        error = namesp->attr_capable(vp, NULL);
 747        if (error)
 748                return error;
 749        xflags |= namesp->attr_flag;
 750        return namesp->attr_remove(vp, attr, xflags);
 751}
 752
 753
 754const struct inode_operations xfs_inode_operations = {
 755        .permission             = xfs_vn_permission,
 756        .truncate               = xfs_vn_truncate,
 757        .getattr                = xfs_vn_getattr,
 758        .setattr                = xfs_vn_setattr,
 759        .setxattr               = xfs_vn_setxattr,
 760        .getxattr               = xfs_vn_getxattr,
 761        .listxattr              = xfs_vn_listxattr,
 762        .removexattr            = xfs_vn_removexattr,
 763};
 764
 765const struct inode_operations xfs_dir_inode_operations = {
 766        .create                 = xfs_vn_create,
 767        .lookup                 = xfs_vn_lookup,
 768        .link                   = xfs_vn_link,
 769        .unlink                 = xfs_vn_unlink,
 770        .symlink                = xfs_vn_symlink,
 771        .mkdir                  = xfs_vn_mkdir,
 772        .rmdir                  = xfs_vn_rmdir,
 773        .mknod                  = xfs_vn_mknod,
 774        .rename                 = xfs_vn_rename,
 775        .permission             = xfs_vn_permission,
 776        .getattr                = xfs_vn_getattr,
 777        .setattr                = xfs_vn_setattr,
 778        .setxattr               = xfs_vn_setxattr,
 779        .getxattr               = xfs_vn_getxattr,
 780        .listxattr              = xfs_vn_listxattr,
 781        .removexattr            = xfs_vn_removexattr,
 782};
 783
 784const struct inode_operations xfs_symlink_inode_operations = {
 785        .readlink               = generic_readlink,
 786        .follow_link            = xfs_vn_follow_link,
 787        .put_link               = xfs_vn_put_link,
 788        .permission             = xfs_vn_permission,
 789        .getattr                = xfs_vn_getattr,
 790        .setattr                = xfs_vn_setattr,
 791        .setxattr               = xfs_vn_setxattr,
 792        .getxattr               = xfs_vn_getxattr,
 793        .listxattr              = xfs_vn_listxattr,
 794        .removexattr            = xfs_vn_removexattr,
 795};
 796