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