linux/fs/jfs/namei.c
<<
>>
Prefs
   1/*
   2 *   Copyright (C) International Business Machines Corp., 2000-2004
   3 *   Portions Copyright (C) Christoph Hellwig, 2001-2002
   4 *
   5 *   This program is free software;  you can redistribute it and/or modify
   6 *   it under the terms of the GNU General Public License as published by
   7 *   the Free Software Foundation; either version 2 of the License, or
   8 *   (at your option) any later version.
   9 *
  10 *   This program is distributed in the hope that it will be useful,
  11 *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
  12 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
  13 *   the GNU General Public License for more details.
  14 *
  15 *   You should have received a copy of the GNU General Public License
  16 *   along with this program;  if not, write to the Free Software
  17 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18 */
  19
  20#include <linux/fs.h>
  21#include <linux/ctype.h>
  22#include <linux/quotaops.h>
  23#include <linux/exportfs.h>
  24#include "jfs_incore.h"
  25#include "jfs_superblock.h"
  26#include "jfs_inode.h"
  27#include "jfs_dinode.h"
  28#include "jfs_dmap.h"
  29#include "jfs_unicode.h"
  30#include "jfs_metapage.h"
  31#include "jfs_xattr.h"
  32#include "jfs_acl.h"
  33#include "jfs_debug.h"
  34
  35/*
  36 * forward references
  37 */
  38const struct dentry_operations jfs_ci_dentry_operations;
  39
  40static s64 commitZeroLink(tid_t, struct inode *);
  41
  42/*
  43 * NAME:        free_ea_wmap(inode)
  44 *
  45 * FUNCTION:    free uncommitted extended attributes from working map
  46 *
  47 */
  48static inline void free_ea_wmap(struct inode *inode)
  49{
  50        dxd_t *ea = &JFS_IP(inode)->ea;
  51
  52        if (ea->flag & DXD_EXTENT) {
  53                /* free EA pages from cache */
  54                invalidate_dxd_metapages(inode, *ea);
  55                dbFree(inode, addressDXD(ea), lengthDXD(ea));
  56        }
  57        ea->flag = 0;
  58}
  59
  60/*
  61 * NAME:        jfs_create(dip, dentry, mode)
  62 *
  63 * FUNCTION:    create a regular file in the parent directory <dip>
  64 *              with name = <from dentry> and mode = <mode>
  65 *
  66 * PARAMETER:   dip     - parent directory vnode
  67 *              dentry  - dentry of new file
  68 *              mode    - create mode (rwxrwxrwx).
  69 *              nd- nd struct
  70 *
  71 * RETURN:      Errors from subroutines
  72 *
  73 */
  74static int jfs_create(struct inode *dip, struct dentry *dentry, int mode,
  75                struct nameidata *nd)
  76{
  77        int rc = 0;
  78        tid_t tid;              /* transaction id */
  79        struct inode *ip = NULL;        /* child directory inode */
  80        ino_t ino;
  81        struct component_name dname;    /* child directory name */
  82        struct btstack btstack;
  83        struct inode *iplist[2];
  84        struct tblock *tblk;
  85
  86        jfs_info("jfs_create: dip:0x%p name:%s", dip, dentry->d_name.name);
  87
  88        /*
  89         * search parent directory for entry/freespace
  90         * (dtSearch() returns parent directory page pinned)
  91         */
  92        if ((rc = get_UCSname(&dname, dentry)))
  93                goto out1;
  94
  95        /*
  96         * Either iAlloc() or txBegin() may block.  Deadlock can occur if we
  97         * block there while holding dtree page, so we allocate the inode &
  98         * begin the transaction before we search the directory.
  99         */
 100        ip = ialloc(dip, mode);
 101        if (IS_ERR(ip)) {
 102                rc = PTR_ERR(ip);
 103                goto out2;
 104        }
 105
 106        tid = txBegin(dip->i_sb, 0);
 107
 108        mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT);
 109        mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD);
 110
 111        rc = jfs_init_acl(tid, ip, dip);
 112        if (rc)
 113                goto out3;
 114
 115        rc = jfs_init_security(tid, ip, dip);
 116        if (rc) {
 117                txAbort(tid, 0);
 118                goto out3;
 119        }
 120
 121        if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE))) {
 122                jfs_err("jfs_create: dtSearch returned %d", rc);
 123                txAbort(tid, 0);
 124                goto out3;
 125        }
 126
 127        tblk = tid_to_tblock(tid);
 128        tblk->xflag |= COMMIT_CREATE;
 129        tblk->ino = ip->i_ino;
 130        tblk->u.ixpxd = JFS_IP(ip)->ixpxd;
 131
 132        iplist[0] = dip;
 133        iplist[1] = ip;
 134
 135        /*
 136         * initialize the child XAD tree root in-line in inode
 137         */
 138        xtInitRoot(tid, ip);
 139
 140        /*
 141         * create entry in parent directory for child directory
 142         * (dtInsert() releases parent directory page)
 143         */
 144        ino = ip->i_ino;
 145        if ((rc = dtInsert(tid, dip, &dname, &ino, &btstack))) {
 146                if (rc == -EIO) {
 147                        jfs_err("jfs_create: dtInsert returned -EIO");
 148                        txAbort(tid, 1);        /* Marks Filesystem dirty */
 149                } else
 150                        txAbort(tid, 0);        /* Filesystem full */
 151                goto out3;
 152        }
 153
 154        ip->i_op = &jfs_file_inode_operations;
 155        ip->i_fop = &jfs_file_operations;
 156        ip->i_mapping->a_ops = &jfs_aops;
 157
 158        mark_inode_dirty(ip);
 159
 160        dip->i_ctime = dip->i_mtime = CURRENT_TIME;
 161
 162        mark_inode_dirty(dip);
 163
 164        rc = txCommit(tid, 2, &iplist[0], 0);
 165
 166      out3:
 167        txEnd(tid);
 168        mutex_unlock(&JFS_IP(ip)->commit_mutex);
 169        mutex_unlock(&JFS_IP(dip)->commit_mutex);
 170        if (rc) {
 171                free_ea_wmap(ip);
 172                ip->i_nlink = 0;
 173                unlock_new_inode(ip);
 174                iput(ip);
 175        } else {
 176                d_instantiate(dentry, ip);
 177                unlock_new_inode(ip);
 178        }
 179
 180      out2:
 181        free_UCSname(&dname);
 182
 183      out1:
 184
 185        jfs_info("jfs_create: rc:%d", rc);
 186        return rc;
 187}
 188
 189
 190/*
 191 * NAME:        jfs_mkdir(dip, dentry, mode)
 192 *
 193 * FUNCTION:    create a child directory in the parent directory <dip>
 194 *              with name = <from dentry> and mode = <mode>
 195 *
 196 * PARAMETER:   dip     - parent directory vnode
 197 *              dentry  - dentry of child directory
 198 *              mode    - create mode (rwxrwxrwx).
 199 *
 200 * RETURN:      Errors from subroutines
 201 *
 202 * note:
 203 * EACCESS: user needs search+write permission on the parent directory
 204 */
 205static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode)
 206{
 207        int rc = 0;
 208        tid_t tid;              /* transaction id */
 209        struct inode *ip = NULL;        /* child directory inode */
 210        ino_t ino;
 211        struct component_name dname;    /* child directory name */
 212        struct btstack btstack;
 213        struct inode *iplist[2];
 214        struct tblock *tblk;
 215
 216        jfs_info("jfs_mkdir: dip:0x%p name:%s", dip, dentry->d_name.name);
 217
 218        /* link count overflow on parent directory ? */
 219        if (dip->i_nlink == JFS_LINK_MAX) {
 220                rc = -EMLINK;
 221                goto out1;
 222        }
 223
 224        /*
 225         * search parent directory for entry/freespace
 226         * (dtSearch() returns parent directory page pinned)
 227         */
 228        if ((rc = get_UCSname(&dname, dentry)))
 229                goto out1;
 230
 231        /*
 232         * Either iAlloc() or txBegin() may block.  Deadlock can occur if we
 233         * block there while holding dtree page, so we allocate the inode &
 234         * begin the transaction before we search the directory.
 235         */
 236        ip = ialloc(dip, S_IFDIR | mode);
 237        if (IS_ERR(ip)) {
 238                rc = PTR_ERR(ip);
 239                goto out2;
 240        }
 241
 242        tid = txBegin(dip->i_sb, 0);
 243
 244        mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT);
 245        mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD);
 246
 247        rc = jfs_init_acl(tid, ip, dip);
 248        if (rc)
 249                goto out3;
 250
 251        rc = jfs_init_security(tid, ip, dip);
 252        if (rc) {
 253                txAbort(tid, 0);
 254                goto out3;
 255        }
 256
 257        if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE))) {
 258                jfs_err("jfs_mkdir: dtSearch returned %d", rc);
 259                txAbort(tid, 0);
 260                goto out3;
 261        }
 262
 263        tblk = tid_to_tblock(tid);
 264        tblk->xflag |= COMMIT_CREATE;
 265        tblk->ino = ip->i_ino;
 266        tblk->u.ixpxd = JFS_IP(ip)->ixpxd;
 267
 268        iplist[0] = dip;
 269        iplist[1] = ip;
 270
 271        /*
 272         * initialize the child directory in-line in inode
 273         */
 274        dtInitRoot(tid, ip, dip->i_ino);
 275
 276        /*
 277         * create entry in parent directory for child directory
 278         * (dtInsert() releases parent directory page)
 279         */
 280        ino = ip->i_ino;
 281        if ((rc = dtInsert(tid, dip, &dname, &ino, &btstack))) {
 282                if (rc == -EIO) {
 283                        jfs_err("jfs_mkdir: dtInsert returned -EIO");
 284                        txAbort(tid, 1);        /* Marks Filesystem dirty */
 285                } else
 286                        txAbort(tid, 0);        /* Filesystem full */
 287                goto out3;
 288        }
 289
 290        ip->i_nlink = 2;        /* for '.' */
 291        ip->i_op = &jfs_dir_inode_operations;
 292        ip->i_fop = &jfs_dir_operations;
 293
 294        mark_inode_dirty(ip);
 295
 296        /* update parent directory inode */
 297        inc_nlink(dip);         /* for '..' from child directory */
 298        dip->i_ctime = dip->i_mtime = CURRENT_TIME;
 299        mark_inode_dirty(dip);
 300
 301        rc = txCommit(tid, 2, &iplist[0], 0);
 302
 303      out3:
 304        txEnd(tid);
 305        mutex_unlock(&JFS_IP(ip)->commit_mutex);
 306        mutex_unlock(&JFS_IP(dip)->commit_mutex);
 307        if (rc) {
 308                free_ea_wmap(ip);
 309                ip->i_nlink = 0;
 310                unlock_new_inode(ip);
 311                iput(ip);
 312        } else {
 313                d_instantiate(dentry, ip);
 314                unlock_new_inode(ip);
 315        }
 316
 317      out2:
 318        free_UCSname(&dname);
 319
 320
 321      out1:
 322
 323        jfs_info("jfs_mkdir: rc:%d", rc);
 324        return rc;
 325}
 326
 327/*
 328 * NAME:        jfs_rmdir(dip, dentry)
 329 *
 330 * FUNCTION:    remove a link to child directory
 331 *
 332 * PARAMETER:   dip     - parent inode
 333 *              dentry  - child directory dentry
 334 *
 335 * RETURN:      -EINVAL - if name is . or ..
 336 *              -EINVAL - if . or .. exist but are invalid.
 337 *              errors from subroutines
 338 *
 339 * note:
 340 * if other threads have the directory open when the last link
 341 * is removed, the "." and ".." entries, if present, are removed before
 342 * rmdir() returns and no new entries may be created in the directory,
 343 * but the directory is not removed until the last reference to
 344 * the directory is released (cf.unlink() of regular file).
 345 */
 346static int jfs_rmdir(struct inode *dip, struct dentry *dentry)
 347{
 348        int rc;
 349        tid_t tid;              /* transaction id */
 350        struct inode *ip = dentry->d_inode;
 351        ino_t ino;
 352        struct component_name dname;
 353        struct inode *iplist[2];
 354        struct tblock *tblk;
 355
 356        jfs_info("jfs_rmdir: dip:0x%p name:%s", dip, dentry->d_name.name);
 357
 358        /* Init inode for quota operations. */
 359        vfs_dq_init(ip);
 360
 361        /* directory must be empty to be removed */
 362        if (!dtEmpty(ip)) {
 363                rc = -ENOTEMPTY;
 364                goto out;
 365        }
 366
 367        if ((rc = get_UCSname(&dname, dentry))) {
 368                goto out;
 369        }
 370
 371        tid = txBegin(dip->i_sb, 0);
 372
 373        mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT);
 374        mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD);
 375
 376        iplist[0] = dip;
 377        iplist[1] = ip;
 378
 379        tblk = tid_to_tblock(tid);
 380        tblk->xflag |= COMMIT_DELETE;
 381        tblk->u.ip = ip;
 382
 383        /*
 384         * delete the entry of target directory from parent directory
 385         */
 386        ino = ip->i_ino;
 387        if ((rc = dtDelete(tid, dip, &dname, &ino, JFS_REMOVE))) {
 388                jfs_err("jfs_rmdir: dtDelete returned %d", rc);
 389                if (rc == -EIO)
 390                        txAbort(tid, 1);
 391                txEnd(tid);
 392                mutex_unlock(&JFS_IP(ip)->commit_mutex);
 393                mutex_unlock(&JFS_IP(dip)->commit_mutex);
 394
 395                goto out2;
 396        }
 397
 398        /* update parent directory's link count corresponding
 399         * to ".." entry of the target directory deleted
 400         */
 401        dip->i_ctime = dip->i_mtime = CURRENT_TIME;
 402        inode_dec_link_count(dip);
 403
 404        /*
 405         * OS/2 could have created EA and/or ACL
 406         */
 407        /* free EA from both persistent and working map */
 408        if (JFS_IP(ip)->ea.flag & DXD_EXTENT) {
 409                /* free EA pages */
 410                txEA(tid, ip, &JFS_IP(ip)->ea, NULL);
 411        }
 412        JFS_IP(ip)->ea.flag = 0;
 413
 414        /* free ACL from both persistent and working map */
 415        if (JFS_IP(ip)->acl.flag & DXD_EXTENT) {
 416                /* free ACL pages */
 417                txEA(tid, ip, &JFS_IP(ip)->acl, NULL);
 418        }
 419        JFS_IP(ip)->acl.flag = 0;
 420
 421        /* mark the target directory as deleted */
 422        clear_nlink(ip);
 423        mark_inode_dirty(ip);
 424
 425        rc = txCommit(tid, 2, &iplist[0], 0);
 426
 427        txEnd(tid);
 428
 429        mutex_unlock(&JFS_IP(ip)->commit_mutex);
 430        mutex_unlock(&JFS_IP(dip)->commit_mutex);
 431
 432        /*
 433         * Truncating the directory index table is not guaranteed.  It
 434         * may need to be done iteratively
 435         */
 436        if (test_cflag(COMMIT_Stale, dip)) {
 437                if (dip->i_size > 1)
 438                        jfs_truncate_nolock(dip, 0);
 439
 440                clear_cflag(COMMIT_Stale, dip);
 441        }
 442
 443      out2:
 444        free_UCSname(&dname);
 445
 446      out:
 447        jfs_info("jfs_rmdir: rc:%d", rc);
 448        return rc;
 449}
 450
 451/*
 452 * NAME:        jfs_unlink(dip, dentry)
 453 *
 454 * FUNCTION:    remove a link to object <vp> named by <name>
 455 *              from parent directory <dvp>
 456 *
 457 * PARAMETER:   dip     - inode of parent directory
 458 *              dentry  - dentry of object to be removed
 459 *
 460 * RETURN:      errors from subroutines
 461 *
 462 * note:
 463 * temporary file: if one or more processes have the file open
 464 * when the last link is removed, the link will be removed before
 465 * unlink() returns, but the removal of the file contents will be
 466 * postponed until all references to the files are closed.
 467 *
 468 * JFS does NOT support unlink() on directories.
 469 *
 470 */
 471static int jfs_unlink(struct inode *dip, struct dentry *dentry)
 472{
 473        int rc;
 474        tid_t tid;              /* transaction id */
 475        struct inode *ip = dentry->d_inode;
 476        ino_t ino;
 477        struct component_name dname;    /* object name */
 478        struct inode *iplist[2];
 479        struct tblock *tblk;
 480        s64 new_size = 0;
 481        int commit_flag;
 482
 483        jfs_info("jfs_unlink: dip:0x%p name:%s", dip, dentry->d_name.name);
 484
 485        /* Init inode for quota operations. */
 486        vfs_dq_init(ip);
 487
 488        if ((rc = get_UCSname(&dname, dentry)))
 489                goto out;
 490
 491        IWRITE_LOCK(ip, RDWRLOCK_NORMAL);
 492
 493        tid = txBegin(dip->i_sb, 0);
 494
 495        mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT);
 496        mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD);
 497
 498        iplist[0] = dip;
 499        iplist[1] = ip;
 500
 501        /*
 502         * delete the entry of target file from parent directory
 503         */
 504        ino = ip->i_ino;
 505        if ((rc = dtDelete(tid, dip, &dname, &ino, JFS_REMOVE))) {
 506                jfs_err("jfs_unlink: dtDelete returned %d", rc);
 507                if (rc == -EIO)
 508                        txAbort(tid, 1);        /* Marks FS Dirty */
 509                txEnd(tid);
 510                mutex_unlock(&JFS_IP(ip)->commit_mutex);
 511                mutex_unlock(&JFS_IP(dip)->commit_mutex);
 512                IWRITE_UNLOCK(ip);
 513                goto out1;
 514        }
 515
 516        ASSERT(ip->i_nlink);
 517
 518        ip->i_ctime = dip->i_ctime = dip->i_mtime = CURRENT_TIME;
 519        mark_inode_dirty(dip);
 520
 521        /* update target's inode */
 522        inode_dec_link_count(ip);
 523
 524        /*
 525         *      commit zero link count object
 526         */
 527        if (ip->i_nlink == 0) {
 528                assert(!test_cflag(COMMIT_Nolink, ip));
 529                /* free block resources */
 530                if ((new_size = commitZeroLink(tid, ip)) < 0) {
 531                        txAbort(tid, 1);        /* Marks FS Dirty */
 532                        txEnd(tid);
 533                        mutex_unlock(&JFS_IP(ip)->commit_mutex);
 534                        mutex_unlock(&JFS_IP(dip)->commit_mutex);
 535                        IWRITE_UNLOCK(ip);
 536                        rc = new_size;
 537                        goto out1;
 538                }
 539                tblk = tid_to_tblock(tid);
 540                tblk->xflag |= COMMIT_DELETE;
 541                tblk->u.ip = ip;
 542        }
 543
 544        /*
 545         * Incomplete truncate of file data can
 546         * result in timing problems unless we synchronously commit the
 547         * transaction.
 548         */
 549        if (new_size)
 550                commit_flag = COMMIT_SYNC;
 551        else
 552                commit_flag = 0;
 553
 554        /*
 555         * If xtTruncate was incomplete, commit synchronously to avoid
 556         * timing complications
 557         */
 558        rc = txCommit(tid, 2, &iplist[0], commit_flag);
 559
 560        txEnd(tid);
 561
 562        mutex_unlock(&JFS_IP(ip)->commit_mutex);
 563        mutex_unlock(&JFS_IP(dip)->commit_mutex);
 564
 565        while (new_size && (rc == 0)) {
 566                tid = txBegin(dip->i_sb, 0);
 567                mutex_lock(&JFS_IP(ip)->commit_mutex);
 568                new_size = xtTruncate_pmap(tid, ip, new_size);
 569                if (new_size < 0) {
 570                        txAbort(tid, 1);        /* Marks FS Dirty */
 571                        rc = new_size;
 572                } else
 573                        rc = txCommit(tid, 2, &iplist[0], COMMIT_SYNC);
 574                txEnd(tid);
 575                mutex_unlock(&JFS_IP(ip)->commit_mutex);
 576        }
 577
 578        if (ip->i_nlink == 0)
 579                set_cflag(COMMIT_Nolink, ip);
 580
 581        IWRITE_UNLOCK(ip);
 582
 583        /*
 584         * Truncating the directory index table is not guaranteed.  It
 585         * may need to be done iteratively
 586         */
 587        if (test_cflag(COMMIT_Stale, dip)) {
 588                if (dip->i_size > 1)
 589                        jfs_truncate_nolock(dip, 0);
 590
 591                clear_cflag(COMMIT_Stale, dip);
 592        }
 593
 594      out1:
 595        free_UCSname(&dname);
 596      out:
 597        jfs_info("jfs_unlink: rc:%d", rc);
 598        return rc;
 599}
 600
 601/*
 602 * NAME:        commitZeroLink()
 603 *
 604 * FUNCTION:    for non-directory, called by jfs_remove(),
 605 *              truncate a regular file, directory or symbolic
 606 *              link to zero length. return 0 if type is not
 607 *              one of these.
 608 *
 609 *              if the file is currently associated with a VM segment
 610 *              only permanent disk and inode map resources are freed,
 611 *              and neither the inode nor indirect blocks are modified
 612 *              so that the resources can be later freed in the work
 613 *              map by ctrunc1.
 614 *              if there is no VM segment on entry, the resources are
 615 *              freed in both work and permanent map.
 616 *              (? for temporary file - memory object is cached even
 617 *              after no reference:
 618 *              reference count > 0 -   )
 619 *
 620 * PARAMETERS:  cd      - pointer to commit data structure.
 621 *                        current inode is the one to truncate.
 622 *
 623 * RETURN:      Errors from subroutines
 624 */
 625static s64 commitZeroLink(tid_t tid, struct inode *ip)
 626{
 627        int filetype;
 628        struct tblock *tblk;
 629
 630        jfs_info("commitZeroLink: tid = %d, ip = 0x%p", tid, ip);
 631
 632        filetype = ip->i_mode & S_IFMT;
 633        switch (filetype) {
 634        case S_IFREG:
 635                break;
 636        case S_IFLNK:
 637                /* fast symbolic link */
 638                if (ip->i_size < IDATASIZE) {
 639                        ip->i_size = 0;
 640                        return 0;
 641                }
 642                break;
 643        default:
 644                assert(filetype != S_IFDIR);
 645                return 0;
 646        }
 647
 648        set_cflag(COMMIT_Freewmap, ip);
 649
 650        /* mark transaction of block map update type */
 651        tblk = tid_to_tblock(tid);
 652        tblk->xflag |= COMMIT_PMAP;
 653
 654        /*
 655         * free EA
 656         */
 657        if (JFS_IP(ip)->ea.flag & DXD_EXTENT)
 658                /* acquire maplock on EA to be freed from block map */
 659                txEA(tid, ip, &JFS_IP(ip)->ea, NULL);
 660
 661        /*
 662         * free ACL
 663         */
 664        if (JFS_IP(ip)->acl.flag & DXD_EXTENT)
 665                /* acquire maplock on EA to be freed from block map */
 666                txEA(tid, ip, &JFS_IP(ip)->acl, NULL);
 667
 668        /*
 669         * free xtree/data (truncate to zero length):
 670         * free xtree/data pages from cache if COMMIT_PWMAP,
 671         * free xtree/data blocks from persistent block map, and
 672         * free xtree/data blocks from working block map if COMMIT_PWMAP;
 673         */
 674        if (ip->i_size)
 675                return xtTruncate_pmap(tid, ip, 0);
 676
 677        return 0;
 678}
 679
 680
 681/*
 682 * NAME:        jfs_free_zero_link()
 683 *
 684 * FUNCTION:    for non-directory, called by iClose(),
 685 *              free resources of a file from cache and WORKING map
 686 *              for a file previously committed with zero link count
 687 *              while associated with a pager object,
 688 *
 689 * PARAMETER:   ip      - pointer to inode of file.
 690 */
 691void jfs_free_zero_link(struct inode *ip)
 692{
 693        int type;
 694
 695        jfs_info("jfs_free_zero_link: ip = 0x%p", ip);
 696
 697        /* return if not reg or symbolic link or if size is
 698         * already ok.
 699         */
 700        type = ip->i_mode & S_IFMT;
 701
 702        switch (type) {
 703        case S_IFREG:
 704                break;
 705        case S_IFLNK:
 706                /* if its contained in inode nothing to do */
 707                if (ip->i_size < IDATASIZE)
 708                        return;
 709                break;
 710        default:
 711                return;
 712        }
 713
 714        /*
 715         * free EA
 716         */
 717        if (JFS_IP(ip)->ea.flag & DXD_EXTENT) {
 718                s64 xaddr = addressDXD(&JFS_IP(ip)->ea);
 719                int xlen = lengthDXD(&JFS_IP(ip)->ea);
 720                struct maplock maplock; /* maplock for COMMIT_WMAP */
 721                struct pxd_lock *pxdlock;       /* maplock for COMMIT_WMAP */
 722
 723                /* free EA pages from cache */
 724                invalidate_dxd_metapages(ip, JFS_IP(ip)->ea);
 725
 726                /* free EA extent from working block map */
 727                maplock.index = 1;
 728                pxdlock = (struct pxd_lock *) & maplock;
 729                pxdlock->flag = mlckFREEPXD;
 730                PXDaddress(&pxdlock->pxd, xaddr);
 731                PXDlength(&pxdlock->pxd, xlen);
 732                txFreeMap(ip, pxdlock, NULL, COMMIT_WMAP);
 733        }
 734
 735        /*
 736         * free ACL
 737         */
 738        if (JFS_IP(ip)->acl.flag & DXD_EXTENT) {
 739                s64 xaddr = addressDXD(&JFS_IP(ip)->acl);
 740                int xlen = lengthDXD(&JFS_IP(ip)->acl);
 741                struct maplock maplock; /* maplock for COMMIT_WMAP */
 742                struct pxd_lock *pxdlock;       /* maplock for COMMIT_WMAP */
 743
 744                invalidate_dxd_metapages(ip, JFS_IP(ip)->acl);
 745
 746                /* free ACL extent from working block map */
 747                maplock.index = 1;
 748                pxdlock = (struct pxd_lock *) & maplock;
 749                pxdlock->flag = mlckFREEPXD;
 750                PXDaddress(&pxdlock->pxd, xaddr);
 751                PXDlength(&pxdlock->pxd, xlen);
 752                txFreeMap(ip, pxdlock, NULL, COMMIT_WMAP);
 753        }
 754
 755        /*
 756         * free xtree/data (truncate to zero length):
 757         * free xtree/data pages from cache, and
 758         * free xtree/data blocks from working block map;
 759         */
 760        if (ip->i_size)
 761                xtTruncate(0, ip, 0, COMMIT_WMAP);
 762}
 763
 764/*
 765 * NAME:        jfs_link(vp, dvp, name, crp)
 766 *
 767 * FUNCTION:    create a link to <vp> by the name = <name>
 768 *              in the parent directory <dvp>
 769 *
 770 * PARAMETER:   vp      - target object
 771 *              dvp     - parent directory of new link
 772 *              name    - name of new link to target object
 773 *              crp     - credential
 774 *
 775 * RETURN:      Errors from subroutines
 776 *
 777 * note:
 778 * JFS does NOT support link() on directories (to prevent circular
 779 * path in the directory hierarchy);
 780 * EPERM: the target object is a directory, and either the caller
 781 * does not have appropriate privileges or the implementation prohibits
 782 * using link() on directories [XPG4.2].
 783 *
 784 * JFS does NOT support links between file systems:
 785 * EXDEV: target object and new link are on different file systems and
 786 * implementation does not support links between file systems [XPG4.2].
 787 */
 788static int jfs_link(struct dentry *old_dentry,
 789             struct inode *dir, struct dentry *dentry)
 790{
 791        int rc;
 792        tid_t tid;
 793        struct inode *ip = old_dentry->d_inode;
 794        ino_t ino;
 795        struct component_name dname;
 796        struct btstack btstack;
 797        struct inode *iplist[2];
 798
 799        jfs_info("jfs_link: %s %s", old_dentry->d_name.name,
 800                 dentry->d_name.name);
 801
 802        if (ip->i_nlink == JFS_LINK_MAX)
 803                return -EMLINK;
 804
 805        if (ip->i_nlink == 0)
 806                return -ENOENT;
 807
 808        tid = txBegin(ip->i_sb, 0);
 809
 810        mutex_lock_nested(&JFS_IP(dir)->commit_mutex, COMMIT_MUTEX_PARENT);
 811        mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD);
 812
 813        /*
 814         * scan parent directory for entry/freespace
 815         */
 816        if ((rc = get_UCSname(&dname, dentry)))
 817                goto out;
 818
 819        if ((rc = dtSearch(dir, &dname, &ino, &btstack, JFS_CREATE)))
 820                goto free_dname;
 821
 822        /*
 823         * create entry for new link in parent directory
 824         */
 825        ino = ip->i_ino;
 826        if ((rc = dtInsert(tid, dir, &dname, &ino, &btstack)))
 827                goto free_dname;
 828
 829        /* update object inode */
 830        inc_nlink(ip);          /* for new link */
 831        ip->i_ctime = CURRENT_TIME;
 832        dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 833        mark_inode_dirty(dir);
 834        atomic_inc(&ip->i_count);
 835
 836        iplist[0] = ip;
 837        iplist[1] = dir;
 838        rc = txCommit(tid, 2, &iplist[0], 0);
 839
 840        if (rc) {
 841                ip->i_nlink--; /* never instantiated */
 842                iput(ip);
 843        } else
 844                d_instantiate(dentry, ip);
 845
 846      free_dname:
 847        free_UCSname(&dname);
 848
 849      out:
 850        txEnd(tid);
 851
 852        mutex_unlock(&JFS_IP(ip)->commit_mutex);
 853        mutex_unlock(&JFS_IP(dir)->commit_mutex);
 854
 855        jfs_info("jfs_link: rc:%d", rc);
 856        return rc;
 857}
 858
 859/*
 860 * NAME:        jfs_symlink(dip, dentry, name)
 861 *
 862 * FUNCTION:    creates a symbolic link to <symlink> by name <name>
 863 *                      in directory <dip>
 864 *
 865 * PARAMETER:   dip     - parent directory vnode
 866 *              dentry  - dentry of symbolic link
 867 *              name    - the path name of the existing object
 868 *                        that will be the source of the link
 869 *
 870 * RETURN:      errors from subroutines
 871 *
 872 * note:
 873 * ENAMETOOLONG: pathname resolution of a symbolic link produced
 874 * an intermediate result whose length exceeds PATH_MAX [XPG4.2]
 875*/
 876
 877static int jfs_symlink(struct inode *dip, struct dentry *dentry,
 878                const char *name)
 879{
 880        int rc;
 881        tid_t tid;
 882        ino_t ino = 0;
 883        struct component_name dname;
 884        int ssize;              /* source pathname size */
 885        struct btstack btstack;
 886        struct inode *ip = dentry->d_inode;
 887        unchar *i_fastsymlink;
 888        s64 xlen = 0;
 889        int bmask = 0, xsize;
 890        s64 extent = 0, xaddr;
 891        struct metapage *mp;
 892        struct super_block *sb;
 893        struct tblock *tblk;
 894
 895        struct inode *iplist[2];
 896
 897        jfs_info("jfs_symlink: dip:0x%p name:%s", dip, name);
 898
 899        ssize = strlen(name) + 1;
 900
 901        /*
 902         * search parent directory for entry/freespace
 903         * (dtSearch() returns parent directory page pinned)
 904         */
 905
 906        if ((rc = get_UCSname(&dname, dentry)))
 907                goto out1;
 908
 909        /*
 910         * allocate on-disk/in-memory inode for symbolic link:
 911         * (iAlloc() returns new, locked inode)
 912         */
 913        ip = ialloc(dip, S_IFLNK | 0777);
 914        if (IS_ERR(ip)) {
 915                rc = PTR_ERR(ip);
 916                goto out2;
 917        }
 918
 919        tid = txBegin(dip->i_sb, 0);
 920
 921        mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT);
 922        mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD);
 923
 924        rc = jfs_init_security(tid, ip, dip);
 925        if (rc)
 926                goto out3;
 927
 928        tblk = tid_to_tblock(tid);
 929        tblk->xflag |= COMMIT_CREATE;
 930        tblk->ino = ip->i_ino;
 931        tblk->u.ixpxd = JFS_IP(ip)->ixpxd;
 932
 933        /* fix symlink access permission
 934         * (dir_create() ANDs in the u.u_cmask,
 935         * but symlinks really need to be 777 access)
 936         */
 937        ip->i_mode |= 0777;
 938
 939        /*
 940         * write symbolic link target path name
 941         */
 942        xtInitRoot(tid, ip);
 943
 944        /*
 945         * write source path name inline in on-disk inode (fast symbolic link)
 946         */
 947
 948        if (ssize <= IDATASIZE) {
 949                ip->i_op = &jfs_symlink_inode_operations;
 950
 951                i_fastsymlink = JFS_IP(ip)->i_inline;
 952                memcpy(i_fastsymlink, name, ssize);
 953                ip->i_size = ssize - 1;
 954
 955                /*
 956                 * if symlink is > 128 bytes, we don't have the space to
 957                 * store inline extended attributes
 958                 */
 959                if (ssize > sizeof (JFS_IP(ip)->i_inline))
 960                        JFS_IP(ip)->mode2 &= ~INLINEEA;
 961
 962                jfs_info("jfs_symlink: fast symlink added  ssize:%d name:%s ",
 963                         ssize, name);
 964        }
 965        /*
 966         * write source path name in a single extent
 967         */
 968        else {
 969                jfs_info("jfs_symlink: allocate extent ip:0x%p", ip);
 970
 971                ip->i_op = &page_symlink_inode_operations;
 972                ip->i_mapping->a_ops = &jfs_aops;
 973
 974                /*
 975                 * even though the data of symlink object (source
 976                 * path name) is treated as non-journaled user data,
 977                 * it is read/written thru buffer cache for performance.
 978                 */
 979                sb = ip->i_sb;
 980                bmask = JFS_SBI(sb)->bsize - 1;
 981                xsize = (ssize + bmask) & ~bmask;
 982                xaddr = 0;
 983                xlen = xsize >> JFS_SBI(sb)->l2bsize;
 984                if ((rc = xtInsert(tid, ip, 0, 0, xlen, &xaddr, 0))) {
 985                        txAbort(tid, 0);
 986                        goto out3;
 987                }
 988                extent = xaddr;
 989                ip->i_size = ssize - 1;
 990                while (ssize) {
 991                        /* This is kind of silly since PATH_MAX == 4K */
 992                        int copy_size = min(ssize, PSIZE);
 993
 994                        mp = get_metapage(ip, xaddr, PSIZE, 1);
 995
 996                        if (mp == NULL) {
 997                                xtTruncate(tid, ip, 0, COMMIT_PWMAP);
 998                                rc = -EIO;
 999                                txAbort(tid, 0);
1000                                goto out3;
1001                        }
1002                        memcpy(mp->data, name, copy_size);
1003                        flush_metapage(mp);
1004                        ssize -= copy_size;
1005                        name += copy_size;
1006                        xaddr += JFS_SBI(sb)->nbperpage;
1007                }
1008        }
1009
1010        /*
1011         * create entry for symbolic link in parent directory
1012         */
1013        rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE);
1014        if (rc == 0) {
1015                ino = ip->i_ino;
1016                rc = dtInsert(tid, dip, &dname, &ino, &btstack);
1017        }
1018        if (rc) {
1019                if (xlen)
1020                        xtTruncate(tid, ip, 0, COMMIT_PWMAP);
1021                txAbort(tid, 0);
1022                /* discard new inode */
1023                goto out3;
1024        }
1025
1026        mark_inode_dirty(ip);
1027
1028        dip->i_ctime = dip->i_mtime = CURRENT_TIME;
1029        mark_inode_dirty(dip);
1030        /*
1031         * commit update of parent directory and link object
1032         */
1033
1034        iplist[0] = dip;
1035        iplist[1] = ip;
1036        rc = txCommit(tid, 2, &iplist[0], 0);
1037
1038      out3:
1039        txEnd(tid);
1040        mutex_unlock(&JFS_IP(ip)->commit_mutex);
1041        mutex_unlock(&JFS_IP(dip)->commit_mutex);
1042        if (rc) {
1043                free_ea_wmap(ip);
1044                ip->i_nlink = 0;
1045                unlock_new_inode(ip);
1046                iput(ip);
1047        } else {
1048                d_instantiate(dentry, ip);
1049                unlock_new_inode(ip);
1050        }
1051
1052      out2:
1053        free_UCSname(&dname);
1054
1055      out1:
1056        jfs_info("jfs_symlink: rc:%d", rc);
1057        return rc;
1058}
1059
1060
1061/*
1062 * NAME:        jfs_rename
1063 *
1064 * FUNCTION:    rename a file or directory
1065 */
1066static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
1067               struct inode *new_dir, struct dentry *new_dentry)
1068{
1069        struct btstack btstack;
1070        ino_t ino;
1071        struct component_name new_dname;
1072        struct inode *new_ip;
1073        struct component_name old_dname;
1074        struct inode *old_ip;
1075        int rc;
1076        tid_t tid;
1077        struct tlock *tlck;
1078        struct dt_lock *dtlck;
1079        struct lv *lv;
1080        int ipcount;
1081        struct inode *iplist[4];
1082        struct tblock *tblk;
1083        s64 new_size = 0;
1084        int commit_flag;
1085
1086
1087        jfs_info("jfs_rename: %s %s", old_dentry->d_name.name,
1088                 new_dentry->d_name.name);
1089
1090        old_ip = old_dentry->d_inode;
1091        new_ip = new_dentry->d_inode;
1092
1093        if ((rc = get_UCSname(&old_dname, old_dentry)))
1094                goto out1;
1095
1096        if ((rc = get_UCSname(&new_dname, new_dentry)))
1097                goto out2;
1098
1099        /*
1100         * Make sure source inode number is what we think it is
1101         */
1102        rc = dtSearch(old_dir, &old_dname, &ino, &btstack, JFS_LOOKUP);
1103        if (rc || (ino != old_ip->i_ino)) {
1104                rc = -ENOENT;
1105                goto out3;
1106        }
1107
1108        /*
1109         * Make sure dest inode number (if any) is what we think it is
1110         */
1111        rc = dtSearch(new_dir, &new_dname, &ino, &btstack, JFS_LOOKUP);
1112        if (!rc) {
1113                if ((!new_ip) || (ino != new_ip->i_ino)) {
1114                        rc = -ESTALE;
1115                        goto out3;
1116                }
1117        } else if (rc != -ENOENT)
1118                goto out3;
1119        else if (new_ip) {
1120                /* no entry exists, but one was expected */
1121                rc = -ESTALE;
1122                goto out3;
1123        }
1124
1125        if (S_ISDIR(old_ip->i_mode)) {
1126                if (new_ip) {
1127                        if (!dtEmpty(new_ip)) {
1128                                rc = -ENOTEMPTY;
1129                                goto out3;
1130                        }
1131                } else if ((new_dir != old_dir) &&
1132                           (new_dir->i_nlink == JFS_LINK_MAX)) {
1133                        rc = -EMLINK;
1134                        goto out3;
1135                }
1136        } else if (new_ip) {
1137                IWRITE_LOCK(new_ip, RDWRLOCK_NORMAL);
1138                /* Init inode for quota operations. */
1139                vfs_dq_init(new_ip);
1140        }
1141
1142        /*
1143         * The real work starts here
1144         */
1145        tid = txBegin(new_dir->i_sb, 0);
1146
1147        /*
1148         * How do we know the locking is safe from deadlocks?
1149         * The vfs does the hard part for us.  Any time we are taking nested
1150         * commit_mutexes, the vfs already has i_mutex held on the parent.
1151         * Here, the vfs has already taken i_mutex on both old_dir and new_dir.
1152         */
1153        mutex_lock_nested(&JFS_IP(new_dir)->commit_mutex, COMMIT_MUTEX_PARENT);
1154        mutex_lock_nested(&JFS_IP(old_ip)->commit_mutex, COMMIT_MUTEX_CHILD);
1155        if (old_dir != new_dir)
1156                mutex_lock_nested(&JFS_IP(old_dir)->commit_mutex,
1157                                  COMMIT_MUTEX_SECOND_PARENT);
1158
1159        if (new_ip) {
1160                mutex_lock_nested(&JFS_IP(new_ip)->commit_mutex,
1161                                  COMMIT_MUTEX_VICTIM);
1162                /*
1163                 * Change existing directory entry to new inode number
1164                 */
1165                ino = new_ip->i_ino;
1166                rc = dtModify(tid, new_dir, &new_dname, &ino,
1167                              old_ip->i_ino, JFS_RENAME);
1168                if (rc)
1169                        goto out4;
1170                drop_nlink(new_ip);
1171                if (S_ISDIR(new_ip->i_mode)) {
1172                        drop_nlink(new_ip);
1173                        if (new_ip->i_nlink) {
1174                                mutex_unlock(&JFS_IP(new_ip)->commit_mutex);
1175                                if (old_dir != new_dir)
1176                                        mutex_unlock(&JFS_IP(old_dir)->commit_mutex);
1177                                mutex_unlock(&JFS_IP(old_ip)->commit_mutex);
1178                                mutex_unlock(&JFS_IP(new_dir)->commit_mutex);
1179                                if (!S_ISDIR(old_ip->i_mode) && new_ip)
1180                                        IWRITE_UNLOCK(new_ip);
1181                                jfs_error(new_ip->i_sb,
1182                                          "jfs_rename: new_ip->i_nlink != 0");
1183                                return -EIO;
1184                        }
1185                        tblk = tid_to_tblock(tid);
1186                        tblk->xflag |= COMMIT_DELETE;
1187                        tblk->u.ip = new_ip;
1188                } else if (new_ip->i_nlink == 0) {
1189                        assert(!test_cflag(COMMIT_Nolink, new_ip));
1190                        /* free block resources */
1191                        if ((new_size = commitZeroLink(tid, new_ip)) < 0) {
1192                                txAbort(tid, 1);        /* Marks FS Dirty */
1193                                rc = new_size;
1194                                goto out4;
1195                        }
1196                        tblk = tid_to_tblock(tid);
1197                        tblk->xflag |= COMMIT_DELETE;
1198                        tblk->u.ip = new_ip;
1199                } else {
1200                        new_ip->i_ctime = CURRENT_TIME;
1201                        mark_inode_dirty(new_ip);
1202                }
1203        } else {
1204                /*
1205                 * Add new directory entry
1206                 */
1207                rc = dtSearch(new_dir, &new_dname, &ino, &btstack,
1208                              JFS_CREATE);
1209                if (rc) {
1210                        jfs_err("jfs_rename didn't expect dtSearch to fail "
1211                                "w/rc = %d", rc);
1212                        goto out4;
1213                }
1214
1215                ino = old_ip->i_ino;
1216                rc = dtInsert(tid, new_dir, &new_dname, &ino, &btstack);
1217                if (rc) {
1218                        if (rc == -EIO)
1219                                jfs_err("jfs_rename: dtInsert returned -EIO");
1220                        goto out4;
1221                }
1222                if (S_ISDIR(old_ip->i_mode))
1223                        inc_nlink(new_dir);
1224        }
1225        /*
1226         * Remove old directory entry
1227         */
1228
1229        ino = old_ip->i_ino;
1230        rc = dtDelete(tid, old_dir, &old_dname, &ino, JFS_REMOVE);
1231        if (rc) {
1232                jfs_err("jfs_rename did not expect dtDelete to return rc = %d",
1233                        rc);
1234                txAbort(tid, 1);        /* Marks Filesystem dirty */
1235                goto out4;
1236        }
1237        if (S_ISDIR(old_ip->i_mode)) {
1238                drop_nlink(old_dir);
1239                if (old_dir != new_dir) {
1240                        /*
1241                         * Change inode number of parent for moved directory
1242                         */
1243
1244                        JFS_IP(old_ip)->i_dtroot.header.idotdot =
1245                                cpu_to_le32(new_dir->i_ino);
1246
1247                        /* Linelock header of dtree */
1248                        tlck = txLock(tid, old_ip,
1249                                    (struct metapage *) &JFS_IP(old_ip)->bxflag,
1250                                      tlckDTREE | tlckBTROOT | tlckRELINK);
1251                        dtlck = (struct dt_lock *) & tlck->lock;
1252                        ASSERT(dtlck->index == 0);
1253                        lv = & dtlck->lv[0];
1254                        lv->offset = 0;
1255                        lv->length = 1;
1256                        dtlck->index++;
1257                }
1258        }
1259
1260        /*
1261         * Update ctime on changed/moved inodes & mark dirty
1262         */
1263        old_ip->i_ctime = CURRENT_TIME;
1264        mark_inode_dirty(old_ip);
1265
1266        new_dir->i_ctime = new_dir->i_mtime = current_fs_time(new_dir->i_sb);
1267        mark_inode_dirty(new_dir);
1268
1269        /* Build list of inodes modified by this transaction */
1270        ipcount = 0;
1271        iplist[ipcount++] = old_ip;
1272        if (new_ip)
1273                iplist[ipcount++] = new_ip;
1274        iplist[ipcount++] = old_dir;
1275
1276        if (old_dir != new_dir) {
1277                iplist[ipcount++] = new_dir;
1278                old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
1279                mark_inode_dirty(old_dir);
1280        }
1281
1282        /*
1283         * Incomplete truncate of file data can
1284         * result in timing problems unless we synchronously commit the
1285         * transaction.
1286         */
1287        if (new_size)
1288                commit_flag = COMMIT_SYNC;
1289        else
1290                commit_flag = 0;
1291
1292        rc = txCommit(tid, ipcount, iplist, commit_flag);
1293
1294      out4:
1295        txEnd(tid);
1296        if (new_ip)
1297                mutex_unlock(&JFS_IP(new_ip)->commit_mutex);
1298        if (old_dir != new_dir)
1299                mutex_unlock(&JFS_IP(old_dir)->commit_mutex);
1300        mutex_unlock(&JFS_IP(old_ip)->commit_mutex);
1301        mutex_unlock(&JFS_IP(new_dir)->commit_mutex);
1302
1303        while (new_size && (rc == 0)) {
1304                tid = txBegin(new_ip->i_sb, 0);
1305                mutex_lock(&JFS_IP(new_ip)->commit_mutex);
1306                new_size = xtTruncate_pmap(tid, new_ip, new_size);
1307                if (new_size < 0) {
1308                        txAbort(tid, 1);
1309                        rc = new_size;
1310                } else
1311                        rc = txCommit(tid, 1, &new_ip, COMMIT_SYNC);
1312                txEnd(tid);
1313                mutex_unlock(&JFS_IP(new_ip)->commit_mutex);
1314        }
1315        if (new_ip && (new_ip->i_nlink == 0))
1316                set_cflag(COMMIT_Nolink, new_ip);
1317      out3:
1318        free_UCSname(&new_dname);
1319      out2:
1320        free_UCSname(&old_dname);
1321      out1:
1322        if (new_ip && !S_ISDIR(new_ip->i_mode))
1323                IWRITE_UNLOCK(new_ip);
1324        /*
1325         * Truncating the directory index table is not guaranteed.  It
1326         * may need to be done iteratively
1327         */
1328        if (test_cflag(COMMIT_Stale, old_dir)) {
1329                if (old_dir->i_size > 1)
1330                        jfs_truncate_nolock(old_dir, 0);
1331
1332                clear_cflag(COMMIT_Stale, old_dir);
1333        }
1334
1335        jfs_info("jfs_rename: returning %d", rc);
1336        return rc;
1337}
1338
1339
1340/*
1341 * NAME:        jfs_mknod
1342 *
1343 * FUNCTION:    Create a special file (device)
1344 */
1345static int jfs_mknod(struct inode *dir, struct dentry *dentry,
1346                int mode, dev_t rdev)
1347{
1348        struct jfs_inode_info *jfs_ip;
1349        struct btstack btstack;
1350        struct component_name dname;
1351        ino_t ino;
1352        struct inode *ip;
1353        struct inode *iplist[2];
1354        int rc;
1355        tid_t tid;
1356        struct tblock *tblk;
1357
1358        if (!new_valid_dev(rdev))
1359                return -EINVAL;
1360
1361        jfs_info("jfs_mknod: %s", dentry->d_name.name);
1362
1363        if ((rc = get_UCSname(&dname, dentry)))
1364                goto out;
1365
1366        ip = ialloc(dir, mode);
1367        if (IS_ERR(ip)) {
1368                rc = PTR_ERR(ip);
1369                goto out1;
1370        }
1371        jfs_ip = JFS_IP(ip);
1372
1373        tid = txBegin(dir->i_sb, 0);
1374
1375        mutex_lock_nested(&JFS_IP(dir)->commit_mutex, COMMIT_MUTEX_PARENT);
1376        mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD);
1377
1378        rc = jfs_init_acl(tid, ip, dir);
1379        if (rc)
1380                goto out3;
1381
1382        rc = jfs_init_security(tid, ip, dir);
1383        if (rc) {
1384                txAbort(tid, 0);
1385                goto out3;
1386        }
1387
1388        if ((rc = dtSearch(dir, &dname, &ino, &btstack, JFS_CREATE))) {
1389                txAbort(tid, 0);
1390                goto out3;
1391        }
1392
1393        tblk = tid_to_tblock(tid);
1394        tblk->xflag |= COMMIT_CREATE;
1395        tblk->ino = ip->i_ino;
1396        tblk->u.ixpxd = JFS_IP(ip)->ixpxd;
1397
1398        ino = ip->i_ino;
1399        if ((rc = dtInsert(tid, dir, &dname, &ino, &btstack))) {
1400                txAbort(tid, 0);
1401                goto out3;
1402        }
1403
1404        ip->i_op = &jfs_file_inode_operations;
1405        jfs_ip->dev = new_encode_dev(rdev);
1406        init_special_inode(ip, ip->i_mode, rdev);
1407
1408        mark_inode_dirty(ip);
1409
1410        dir->i_ctime = dir->i_mtime = CURRENT_TIME;
1411
1412        mark_inode_dirty(dir);
1413
1414        iplist[0] = dir;
1415        iplist[1] = ip;
1416        rc = txCommit(tid, 2, iplist, 0);
1417
1418      out3:
1419        txEnd(tid);
1420        mutex_unlock(&JFS_IP(ip)->commit_mutex);
1421        mutex_unlock(&JFS_IP(dir)->commit_mutex);
1422        if (rc) {
1423                free_ea_wmap(ip);
1424                ip->i_nlink = 0;
1425                unlock_new_inode(ip);
1426                iput(ip);
1427        } else {
1428                d_instantiate(dentry, ip);
1429                unlock_new_inode(ip);
1430        }
1431
1432      out1:
1433        free_UCSname(&dname);
1434
1435      out:
1436        jfs_info("jfs_mknod: returning %d", rc);
1437        return rc;
1438}
1439
1440static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry, struct nameidata *nd)
1441{
1442        struct btstack btstack;
1443        ino_t inum;
1444        struct inode *ip;
1445        struct component_name key;
1446        const char *name = dentry->d_name.name;
1447        int len = dentry->d_name.len;
1448        int rc;
1449
1450        jfs_info("jfs_lookup: name = %s", name);
1451
1452        if (JFS_SBI(dip->i_sb)->mntflag & JFS_OS2)
1453                dentry->d_op = &jfs_ci_dentry_operations;
1454
1455        if ((name[0] == '.') && (len == 1))
1456                inum = dip->i_ino;
1457        else if (strcmp(name, "..") == 0)
1458                inum = PARENT(dip);
1459        else {
1460                if ((rc = get_UCSname(&key, dentry)))
1461                        return ERR_PTR(rc);
1462                rc = dtSearch(dip, &key, &inum, &btstack, JFS_LOOKUP);
1463                free_UCSname(&key);
1464                if (rc == -ENOENT) {
1465                        d_add(dentry, NULL);
1466                        return NULL;
1467                } else if (rc) {
1468                        jfs_err("jfs_lookup: dtSearch returned %d", rc);
1469                        return ERR_PTR(rc);
1470                }
1471        }
1472
1473        ip = jfs_iget(dip->i_sb, inum);
1474        if (IS_ERR(ip)) {
1475                jfs_err("jfs_lookup: iget failed on inum %d", (uint) inum);
1476                return ERR_CAST(ip);
1477        }
1478
1479        dentry = d_splice_alias(ip, dentry);
1480
1481        if (dentry && (JFS_SBI(dip->i_sb)->mntflag & JFS_OS2))
1482                dentry->d_op = &jfs_ci_dentry_operations;
1483
1484        return dentry;
1485}
1486
1487static struct inode *jfs_nfs_get_inode(struct super_block *sb,
1488                u64 ino, u32 generation)
1489{
1490        struct inode *inode;
1491
1492        if (ino == 0)
1493                return ERR_PTR(-ESTALE);
1494        inode = jfs_iget(sb, ino);
1495        if (IS_ERR(inode))
1496                return ERR_CAST(inode);
1497
1498        if (generation && inode->i_generation != generation) {
1499                iput(inode);
1500                return ERR_PTR(-ESTALE);
1501        }
1502
1503        return inode;
1504}
1505
1506struct dentry *jfs_fh_to_dentry(struct super_block *sb, struct fid *fid,
1507                int fh_len, int fh_type)
1508{
1509        return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
1510                                    jfs_nfs_get_inode);
1511}
1512
1513struct dentry *jfs_fh_to_parent(struct super_block *sb, struct fid *fid,
1514                int fh_len, int fh_type)
1515{
1516        return generic_fh_to_parent(sb, fid, fh_len, fh_type,
1517                                    jfs_nfs_get_inode);
1518}
1519
1520struct dentry *jfs_get_parent(struct dentry *dentry)
1521{
1522        unsigned long parent_ino;
1523
1524        parent_ino =
1525                le32_to_cpu(JFS_IP(dentry->d_inode)->i_dtroot.header.idotdot);
1526
1527        return d_obtain_alias(jfs_iget(dentry->d_inode->i_sb, parent_ino));
1528}
1529
1530const struct inode_operations jfs_dir_inode_operations = {
1531        .create         = jfs_create,
1532        .lookup         = jfs_lookup,
1533        .link           = jfs_link,
1534        .unlink         = jfs_unlink,
1535        .symlink        = jfs_symlink,
1536        .mkdir          = jfs_mkdir,
1537        .rmdir          = jfs_rmdir,
1538        .mknod          = jfs_mknod,
1539        .rename         = jfs_rename,
1540        .setxattr       = jfs_setxattr,
1541        .getxattr       = jfs_getxattr,
1542        .listxattr      = jfs_listxattr,
1543        .removexattr    = jfs_removexattr,
1544#ifdef CONFIG_JFS_POSIX_ACL
1545        .setattr        = jfs_setattr,
1546        .check_acl      = jfs_check_acl,
1547#endif
1548};
1549
1550const struct file_operations jfs_dir_operations = {
1551        .read           = generic_read_dir,
1552        .readdir        = jfs_readdir,
1553        .fsync          = jfs_fsync,
1554        .unlocked_ioctl = jfs_ioctl,
1555#ifdef CONFIG_COMPAT
1556        .compat_ioctl   = jfs_compat_ioctl,
1557#endif
1558        .llseek         = generic_file_llseek,
1559};
1560
1561static int jfs_ci_hash(struct dentry *dir, struct qstr *this)
1562{
1563        unsigned long hash;
1564        int i;
1565
1566        hash = init_name_hash();
1567        for (i=0; i < this->len; i++)
1568                hash = partial_name_hash(tolower(this->name[i]), hash);
1569        this->hash = end_name_hash(hash);
1570
1571        return 0;
1572}
1573
1574static int jfs_ci_compare(struct dentry *dir, struct qstr *a, struct qstr *b)
1575{
1576        int i, result = 1;
1577
1578        if (a->len != b->len)
1579                goto out;
1580        for (i=0; i < a->len; i++) {
1581                if (tolower(a->name[i]) != tolower(b->name[i]))
1582                        goto out;
1583        }
1584        result = 0;
1585
1586        /*
1587         * We want creates to preserve case.  A negative dentry, a, that
1588         * has a different case than b may cause a new entry to be created
1589         * with the wrong case.  Since we can't tell if a comes from a negative
1590         * dentry, we blindly replace it with b.  This should be harmless if
1591         * a is not a negative dentry.
1592         */
1593        memcpy((unsigned char *)a->name, b->name, a->len);
1594out:
1595        return result;
1596}
1597
1598const struct dentry_operations jfs_ci_dentry_operations =
1599{
1600        .d_hash = jfs_ci_hash,
1601        .d_compare = jfs_ci_compare,
1602};
1603
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.