linux/fs/udf/namei.c
<<
>>
Prefs
   1/*
   2 * namei.c
   3 *
   4 * PURPOSE
   5 *      Inode name handling routines for the OSTA-UDF(tm) filesystem.
   6 *
   7 * COPYRIGHT
   8 *      This file is distributed under the terms of the GNU General Public
   9 *      License (GPL). Copies of the GPL can be obtained from:
  10 *              ftp://prep.ai.mit.edu/pub/gnu/GPL
  11 *      Each contributing author retains all rights to their own work.
  12 *
  13 *  (C) 1998-2004 Ben Fennema
  14 *  (C) 1999-2000 Stelias Computing Inc
  15 *
  16 * HISTORY
  17 *
  18 *  12/12/98 blf  Created. Split out the lookup code from dir.c
  19 *  04/19/99 blf  link, mknod, symlink support
  20 */
  21
  22#include "udfdecl.h"
  23
  24#include "udf_i.h"
  25#include "udf_sb.h"
  26#include <linux/string.h>
  27#include <linux/errno.h>
  28#include <linux/mm.h>
  29#include <linux/slab.h>
  30#include <linux/buffer_head.h>
  31#include <linux/sched.h>
  32#include <linux/crc-itu-t.h>
  33#include <linux/exportfs.h>
  34
  35static inline int udf_match(int len1, const unsigned char *name1, int len2,
  36                            const unsigned char *name2)
  37{
  38        if (len1 != len2)
  39                return 0;
  40
  41        return !memcmp(name1, name2, len1);
  42}
  43
  44int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi,
  45                 struct fileIdentDesc *sfi, struct udf_fileident_bh *fibh,
  46                 uint8_t *impuse, uint8_t *fileident)
  47{
  48        uint16_t crclen = fibh->eoffset - fibh->soffset - sizeof(struct tag);
  49        uint16_t crc;
  50        int offset;
  51        uint16_t liu = le16_to_cpu(cfi->lengthOfImpUse);
  52        uint8_t lfi = cfi->lengthFileIdent;
  53        int padlen = fibh->eoffset - fibh->soffset - liu - lfi -
  54                sizeof(struct fileIdentDesc);
  55        int adinicb = 0;
  56
  57        if (UDF_I(inode)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
  58                adinicb = 1;
  59
  60        offset = fibh->soffset + sizeof(struct fileIdentDesc);
  61
  62        if (impuse) {
  63                if (adinicb || (offset + liu < 0)) {
  64                        memcpy((uint8_t *)sfi->impUse, impuse, liu);
  65                } else if (offset >= 0) {
  66                        memcpy(fibh->ebh->b_data + offset, impuse, liu);
  67                } else {
  68                        memcpy((uint8_t *)sfi->impUse, impuse, -offset);
  69                        memcpy(fibh->ebh->b_data, impuse - offset,
  70                                liu + offset);
  71                }
  72        }
  73
  74        offset += liu;
  75
  76        if (fileident) {
  77                if (adinicb || (offset + lfi < 0)) {
  78                        memcpy((uint8_t *)sfi->fileIdent + liu, fileident, lfi);
  79                } else if (offset >= 0) {
  80                        memcpy(fibh->ebh->b_data + offset, fileident, lfi);
  81                } else {
  82                        memcpy((uint8_t *)sfi->fileIdent + liu, fileident,
  83                                -offset);
  84                        memcpy(fibh->ebh->b_data, fileident - offset,
  85                                lfi + offset);
  86                }
  87        }
  88
  89        offset += lfi;
  90
  91        if (adinicb || (offset + padlen < 0)) {
  92                memset((uint8_t *)sfi->padding + liu + lfi, 0x00, padlen);
  93        } else if (offset >= 0) {
  94                memset(fibh->ebh->b_data + offset, 0x00, padlen);
  95        } else {
  96                memset((uint8_t *)sfi->padding + liu + lfi, 0x00, -offset);
  97                memset(fibh->ebh->b_data, 0x00, padlen + offset);
  98        }
  99
 100        crc = crc_itu_t(0, (uint8_t *)cfi + sizeof(struct tag),
 101                      sizeof(struct fileIdentDesc) - sizeof(struct tag));
 102
 103        if (fibh->sbh == fibh->ebh) {
 104                crc = crc_itu_t(crc, (uint8_t *)sfi->impUse,
 105                              crclen + sizeof(struct tag) -
 106                              sizeof(struct fileIdentDesc));
 107        } else if (sizeof(struct fileIdentDesc) >= -fibh->soffset) {
 108                crc = crc_itu_t(crc, fibh->ebh->b_data +
 109                                        sizeof(struct fileIdentDesc) +
 110                                        fibh->soffset,
 111                              crclen + sizeof(struct tag) -
 112                                        sizeof(struct fileIdentDesc));
 113        } else {
 114                crc = crc_itu_t(crc, (uint8_t *)sfi->impUse,
 115                              -fibh->soffset - sizeof(struct fileIdentDesc));
 116                crc = crc_itu_t(crc, fibh->ebh->b_data, fibh->eoffset);
 117        }
 118
 119        cfi->descTag.descCRC = cpu_to_le16(crc);
 120        cfi->descTag.descCRCLength = cpu_to_le16(crclen);
 121        cfi->descTag.tagChecksum = udf_tag_checksum(&cfi->descTag);
 122
 123        if (adinicb || (sizeof(struct fileIdentDesc) <= -fibh->soffset)) {
 124                memcpy((uint8_t *)sfi, (uint8_t *)cfi,
 125                        sizeof(struct fileIdentDesc));
 126        } else {
 127                memcpy((uint8_t *)sfi, (uint8_t *)cfi, -fibh->soffset);
 128                memcpy(fibh->ebh->b_data, (uint8_t *)cfi - fibh->soffset,
 129                       sizeof(struct fileIdentDesc) + fibh->soffset);
 130        }
 131
 132        if (adinicb) {
 133                mark_inode_dirty(inode);
 134        } else {
 135                if (fibh->sbh != fibh->ebh)
 136                        mark_buffer_dirty_inode(fibh->ebh, inode);
 137                mark_buffer_dirty_inode(fibh->sbh, inode);
 138        }
 139        return 0;
 140}
 141
 142static struct fileIdentDesc *udf_find_entry(struct inode *dir,
 143                                            const struct qstr *child,
 144                                            struct udf_fileident_bh *fibh,
 145                                            struct fileIdentDesc *cfi)
 146{
 147        struct fileIdentDesc *fi = NULL;
 148        loff_t f_pos;
 149        int block, flen;
 150        unsigned char *fname = NULL;
 151        unsigned char *nameptr;
 152        uint8_t lfi;
 153        uint16_t liu;
 154        loff_t size;
 155        struct kernel_lb_addr eloc;
 156        uint32_t elen;
 157        sector_t offset;
 158        struct extent_position epos = {};
 159        struct udf_inode_info *dinfo = UDF_I(dir);
 160        int isdotdot = child->len == 2 &&
 161                child->name[0] == '.' && child->name[1] == '.';
 162
 163        size = udf_ext0_offset(dir) + dir->i_size;
 164        f_pos = udf_ext0_offset(dir);
 165
 166        fibh->sbh = fibh->ebh = NULL;
 167        fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1);
 168        if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
 169                if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, &epos,
 170                    &eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30))
 171                        goto out_err;
 172                block = udf_get_lb_pblock(dir->i_sb, &eloc, offset);
 173                if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
 174                        if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
 175                                epos.offset -= sizeof(struct short_ad);
 176                        else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
 177                                epos.offset -= sizeof(struct long_ad);
 178                } else
 179                        offset = 0;
 180
 181                fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block);
 182                if (!fibh->sbh)
 183                        goto out_err;
 184        }
 185
 186        fname = kmalloc(UDF_NAME_LEN, GFP_NOFS);
 187        if (!fname)
 188                goto out_err;
 189
 190        while (f_pos < size) {
 191                fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &epos, &eloc,
 192                                        &elen, &offset);
 193                if (!fi)
 194                        goto out_err;
 195
 196                liu = le16_to_cpu(cfi->lengthOfImpUse);
 197                lfi = cfi->lengthFileIdent;
 198
 199                if (fibh->sbh == fibh->ebh) {
 200                        nameptr = fi->fileIdent + liu;
 201                } else {
 202                        int poffset;    /* Unpaded ending offset */
 203
 204                        poffset = fibh->soffset + sizeof(struct fileIdentDesc) +
 205                                        liu + lfi;
 206
 207                        if (poffset >= lfi)
 208                                nameptr = (uint8_t *)(fibh->ebh->b_data +
 209                                                      poffset - lfi);
 210                        else {
 211                                nameptr = fname;
 212                                memcpy(nameptr, fi->fileIdent + liu,
 213                                        lfi - poffset);
 214                                memcpy(nameptr + lfi - poffset,
 215                                        fibh->ebh->b_data, poffset);
 216                        }
 217                }
 218
 219                if ((cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0) {
 220                        if (!UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNDELETE))
 221                                continue;
 222                }
 223
 224                if ((cfi->fileCharacteristics & FID_FILE_CHAR_HIDDEN) != 0) {
 225                        if (!UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNHIDE))
 226                                continue;
 227                }
 228
 229                if ((cfi->fileCharacteristics & FID_FILE_CHAR_PARENT) &&
 230                    isdotdot)
 231                        goto out_ok;
 232
 233                if (!lfi)
 234                        continue;
 235
 236                flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi);
 237                if (flen && udf_match(flen, fname, child->len, child->name))
 238                        goto out_ok;
 239        }
 240
 241out_err:
 242        fi = NULL;
 243        if (fibh->sbh != fibh->ebh)
 244                brelse(fibh->ebh);
 245        brelse(fibh->sbh);
 246out_ok:
 247        brelse(epos.bh);
 248        kfree(fname);
 249
 250        return fi;
 251}
 252
 253static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,
 254                                 unsigned int flags)
 255{
 256        struct inode *inode = NULL;
 257        struct fileIdentDesc cfi;
 258        struct udf_fileident_bh fibh;
 259
 260        if (dentry->d_name.len > UDF_NAME_LEN - 2)
 261                return ERR_PTR(-ENAMETOOLONG);
 262
 263#ifdef UDF_RECOVERY
 264        /* temporary shorthand for specifying files by inode number */
 265        if (!strncmp(dentry->d_name.name, ".B=", 3)) {
 266                struct kernel_lb_addr lb = {
 267                        .logicalBlockNum = 0,
 268                        .partitionReferenceNum =
 269                                simple_strtoul(dentry->d_name.name + 3,
 270                                                NULL, 0),
 271                };
 272                inode = udf_iget(dir->i_sb, lb);
 273                if (!inode) {
 274                        return ERR_PTR(-EACCES);
 275                }
 276        } else
 277#endif /* UDF_RECOVERY */
 278
 279        if (udf_find_entry(dir, &dentry->d_name, &fibh, &cfi)) {
 280                struct kernel_lb_addr loc;
 281
 282                if (fibh.sbh != fibh.ebh)
 283                        brelse(fibh.ebh);
 284                brelse(fibh.sbh);
 285
 286                loc = lelb_to_cpu(cfi.icb.extLocation);
 287                inode = udf_iget(dir->i_sb, &loc);
 288                if (!inode) {
 289                        return ERR_PTR(-EACCES);
 290                }
 291        }
 292
 293        return d_splice_alias(inode, dentry);
 294}
 295
 296static struct fileIdentDesc *udf_add_entry(struct inode *dir,
 297                                           struct dentry *dentry,
 298                                           struct udf_fileident_bh *fibh,
 299                                           struct fileIdentDesc *cfi, int *err)
 300{
 301        struct super_block *sb = dir->i_sb;
 302        struct fileIdentDesc *fi = NULL;
 303        unsigned char *name = NULL;
 304        int namelen;
 305        loff_t f_pos;
 306        loff_t size = udf_ext0_offset(dir) + dir->i_size;
 307        int nfidlen;
 308        uint8_t lfi;
 309        uint16_t liu;
 310        int block;
 311        struct kernel_lb_addr eloc;
 312        uint32_t elen = 0;
 313        sector_t offset;
 314        struct extent_position epos = {};
 315        struct udf_inode_info *dinfo;
 316
 317        fibh->sbh = fibh->ebh = NULL;
 318        name = kmalloc(UDF_NAME_LEN, GFP_NOFS);
 319        if (!name) {
 320                *err = -ENOMEM;
 321                goto out_err;
 322        }
 323
 324        if (dentry) {
 325                if (!dentry->d_name.len) {
 326                        *err = -EINVAL;
 327                        goto out_err;
 328                }
 329                namelen = udf_put_filename(sb, dentry->d_name.name, name,
 330                                                 dentry->d_name.len);
 331                if (!namelen) {
 332                        *err = -ENAMETOOLONG;
 333                        goto out_err;
 334                }
 335        } else {
 336                namelen = 0;
 337        }
 338
 339        nfidlen = (sizeof(struct fileIdentDesc) + namelen + 3) & ~3;
 340
 341        f_pos = udf_ext0_offset(dir);
 342
 343        fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1);
 344        dinfo = UDF_I(dir);
 345        if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
 346                if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, &epos,
 347                    &eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30)) {
 348                        block = udf_get_lb_pblock(dir->i_sb,
 349                                        &dinfo->i_location, 0);
 350                        fibh->soffset = fibh->eoffset = sb->s_blocksize;
 351                        goto add;
 352                }
 353                block = udf_get_lb_pblock(dir->i_sb, &eloc, offset);
 354                if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
 355                        if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
 356                                epos.offset -= sizeof(struct short_ad);
 357                        else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
 358                                epos.offset -= sizeof(struct long_ad);
 359                } else
 360                        offset = 0;
 361
 362                fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block);
 363                if (!fibh->sbh) {
 364                        *err = -EIO;
 365                        goto out_err;
 366                }
 367
 368                block = dinfo->i_location.logicalBlockNum;
 369        }
 370
 371        while (f_pos < size) {
 372                fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &epos, &eloc,
 373                                        &elen, &offset);
 374
 375                if (!fi) {
 376                        *err = -EIO;
 377                        goto out_err;
 378                }
 379
 380                liu = le16_to_cpu(cfi->lengthOfImpUse);
 381                lfi = cfi->lengthFileIdent;
 382
 383                if ((cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0) {
 384                        if (((sizeof(struct fileIdentDesc) +
 385                                        liu + lfi + 3) & ~3) == nfidlen) {
 386                                cfi->descTag.tagSerialNum = cpu_to_le16(1);
 387                                cfi->fileVersionNum = cpu_to_le16(1);
 388                                cfi->fileCharacteristics = 0;
 389                                cfi->lengthFileIdent = namelen;
 390                                cfi->lengthOfImpUse = cpu_to_le16(0);
 391                                if (!udf_write_fi(dir, cfi, fi, fibh, NULL,
 392                                                  name))
 393                                        goto out_ok;
 394                                else {
 395                                        *err = -EIO;
 396                                        goto out_err;
 397                                }
 398                        }
 399                }
 400        }
 401
 402add:
 403        f_pos += nfidlen;
 404
 405        if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB &&
 406            sb->s_blocksize - fibh->eoffset < nfidlen) {
 407                brelse(epos.bh);
 408                epos.bh = NULL;
 409                fibh->soffset -= udf_ext0_offset(dir);
 410                fibh->eoffset -= udf_ext0_offset(dir);
 411                f_pos -= udf_ext0_offset(dir);
 412                if (fibh->sbh != fibh->ebh)
 413                        brelse(fibh->ebh);
 414                brelse(fibh->sbh);
 415                fibh->sbh = fibh->ebh =
 416                                udf_expand_dir_adinicb(dir, &block, err);
 417                if (!fibh->sbh)
 418                        goto out_err;
 419                epos.block = dinfo->i_location;
 420                epos.offset = udf_file_entry_alloc_offset(dir);
 421                /* Load extent udf_expand_dir_adinicb() has created */
 422                udf_current_aext(dir, &epos, &eloc, &elen, 1);
 423        }
 424
 425        /* Entry fits into current block? */
 426        if (sb->s_blocksize - fibh->eoffset >= nfidlen) {
 427                fibh->soffset = fibh->eoffset;
 428                fibh->eoffset += nfidlen;
 429                if (fibh->sbh != fibh->ebh) {
 430                        brelse(fibh->sbh);
 431                        fibh->sbh = fibh->ebh;
 432                }
 433
 434                if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
 435                        block = dinfo->i_location.logicalBlockNum;
 436                        fi = (struct fileIdentDesc *)
 437                                        (dinfo->i_ext.i_data +
 438                                         fibh->soffset -
 439                                         udf_ext0_offset(dir) +
 440                                         dinfo->i_lenEAttr);
 441                } else {
 442                        block = eloc.logicalBlockNum +
 443                                        ((elen - 1) >>
 444                                                dir->i_sb->s_blocksize_bits);
 445                        fi = (struct fileIdentDesc *)
 446                                (fibh->sbh->b_data + fibh->soffset);
 447                }
 448        } else {
 449                /* Round up last extent in the file */
 450                elen = (elen + sb->s_blocksize - 1) & ~(sb->s_blocksize - 1);
 451                if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
 452                        epos.offset -= sizeof(struct short_ad);
 453                else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
 454                        epos.offset -= sizeof(struct long_ad);
 455                udf_write_aext(dir, &epos, &eloc, elen, 1);
 456                dinfo->i_lenExtents = (dinfo->i_lenExtents + sb->s_blocksize
 457                                        - 1) & ~(sb->s_blocksize - 1);
 458
 459                fibh->soffset = fibh->eoffset - sb->s_blocksize;
 460                fibh->eoffset += nfidlen - sb->s_blocksize;
 461                if (fibh->sbh != fibh->ebh) {
 462                        brelse(fibh->sbh);
 463                        fibh->sbh = fibh->ebh;
 464                }
 465
 466                block = eloc.logicalBlockNum + ((elen - 1) >>
 467                                                dir->i_sb->s_blocksize_bits);
 468                fibh->ebh = udf_bread(dir,
 469                                f_pos >> dir->i_sb->s_blocksize_bits, 1, err);
 470                if (!fibh->ebh)
 471                        goto out_err;
 472                /* Extents could have been merged, invalidate our position */
 473                brelse(epos.bh);
 474                epos.bh = NULL;
 475                epos.block = dinfo->i_location;
 476                epos.offset = udf_file_entry_alloc_offset(dir);
 477
 478                if (!fibh->soffset) {
 479                        /* Find the freshly allocated block */
 480                        while (udf_next_aext(dir, &epos, &eloc, &elen, 1) ==
 481                                (EXT_RECORDED_ALLOCATED >> 30))
 482                                ;
 483                        block = eloc.logicalBlockNum + ((elen - 1) >>
 484                                        dir->i_sb->s_blocksize_bits);
 485                        brelse(fibh->sbh);
 486                        fibh->sbh = fibh->ebh;
 487                        fi = (struct fileIdentDesc *)(fibh->sbh->b_data);
 488                } else {
 489                        fi = (struct fileIdentDesc *)
 490                                (fibh->sbh->b_data + sb->s_blocksize +
 491                                        fibh->soffset);
 492                }
 493        }
 494
 495        memset(cfi, 0, sizeof(struct fileIdentDesc));
 496        if (UDF_SB(sb)->s_udfrev >= 0x0200)
 497                udf_new_tag((char *)cfi, TAG_IDENT_FID, 3, 1, block,
 498                            sizeof(struct tag));
 499        else
 500                udf_new_tag((char *)cfi, TAG_IDENT_FID, 2, 1, block,
 501                            sizeof(struct tag));
 502        cfi->fileVersionNum = cpu_to_le16(1);
 503        cfi->lengthFileIdent = namelen;
 504        cfi->lengthOfImpUse = cpu_to_le16(0);
 505        if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name)) {
 506                dir->i_size += nfidlen;
 507                if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
 508                        dinfo->i_lenAlloc += nfidlen;
 509                else {
 510                        /* Find the last extent and truncate it to proper size */
 511                        while (udf_next_aext(dir, &epos, &eloc, &elen, 1) ==
 512                                (EXT_RECORDED_ALLOCATED >> 30))
 513                                ;
 514                        elen -= dinfo->i_lenExtents - dir->i_size;
 515                        if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
 516                                epos.offset -= sizeof(struct short_ad);
 517                        else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
 518                                epos.offset -= sizeof(struct long_ad);
 519                        udf_write_aext(dir, &epos, &eloc, elen, 1);
 520                        dinfo->i_lenExtents = dir->i_size;
 521                }
 522
 523                mark_inode_dirty(dir);
 524                goto out_ok;
 525        } else {
 526                *err = -EIO;
 527                goto out_err;
 528        }
 529
 530out_err:
 531        fi = NULL;
 532        if (fibh->sbh != fibh->ebh)
 533                brelse(fibh->ebh);
 534        brelse(fibh->sbh);
 535out_ok:
 536        brelse(epos.bh);
 537        kfree(name);
 538        return fi;
 539}
 540
 541static int udf_delete_entry(struct inode *inode, struct fileIdentDesc *fi,
 542                            struct udf_fileident_bh *fibh,
 543                            struct fileIdentDesc *cfi)
 544{
 545        cfi->fileCharacteristics |= FID_FILE_CHAR_DELETED;
 546
 547        if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT))
 548                memset(&(cfi->icb), 0x00, sizeof(struct long_ad));
 549
 550        return udf_write_fi(inode, cfi, fi, fibh, NULL, NULL);
 551}
 552
 553static int udf_create(struct inode *dir, struct dentry *dentry, umode_t mode,
 554                      bool excl)
 555{
 556        struct udf_fileident_bh fibh;
 557        struct inode *inode;
 558        struct fileIdentDesc cfi, *fi;
 559        int err;
 560        struct udf_inode_info *iinfo;
 561
 562        inode = udf_new_inode(dir, mode, &err);
 563        if (!inode) {
 564                return err;
 565        }
 566
 567        iinfo = UDF_I(inode);
 568        if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
 569                inode->i_data.a_ops = &udf_adinicb_aops;
 570        else
 571                inode->i_data.a_ops = &udf_aops;
 572        inode->i_op = &udf_file_inode_operations;
 573        inode->i_fop = &udf_file_operations;
 574        mark_inode_dirty(inode);
 575
 576        fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
 577        if (!fi) {
 578                inode_dec_link_count(inode);
 579                iput(inode);
 580                return err;
 581        }
 582        cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
 583        cfi.icb.extLocation = cpu_to_lelb(iinfo->i_location);
 584        *(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
 585                cpu_to_le32(iinfo->i_unique & 0x00000000FFFFFFFFUL);
 586        udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
 587        if (UDF_I(dir)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
 588                mark_inode_dirty(dir);
 589        if (fibh.sbh != fibh.ebh)
 590                brelse(fibh.ebh);
 591        brelse(fibh.sbh);
 592        d_instantiate(dentry, inode);
 593
 594        return 0;
 595}
 596
 597static int udf_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
 598                     dev_t rdev)
 599{
 600        struct inode *inode;
 601        struct udf_fileident_bh fibh;
 602        struct fileIdentDesc cfi, *fi;
 603        int err;
 604        struct udf_inode_info *iinfo;
 605
 606        if (!old_valid_dev(rdev))
 607                return -EINVAL;
 608
 609        err = -EIO;
 610        inode = udf_new_inode(dir, mode, &err);
 611        if (!inode)
 612                goto out;
 613
 614        iinfo = UDF_I(inode);
 615        init_special_inode(inode, mode, rdev);
 616        fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
 617        if (!fi) {
 618                inode_dec_link_count(inode);
 619                iput(inode);
 620                return err;
 621        }
 622        cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
 623        cfi.icb.extLocation = cpu_to_lelb(iinfo->i_location);
 624        *(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
 625                cpu_to_le32(iinfo->i_unique & 0x00000000FFFFFFFFUL);
 626        udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
 627        if (UDF_I(dir)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
 628                mark_inode_dirty(dir);
 629        mark_inode_dirty(inode);
 630
 631        if (fibh.sbh != fibh.ebh)
 632                brelse(fibh.ebh);
 633        brelse(fibh.sbh);
 634        d_instantiate(dentry, inode);
 635        err = 0;
 636
 637out:
 638        return err;
 639}
 640
 641static int udf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 642{
 643        struct inode *inode;
 644        struct udf_fileident_bh fibh;
 645        struct fileIdentDesc cfi, *fi;
 646        int err;
 647        struct udf_inode_info *dinfo = UDF_I(dir);
 648        struct udf_inode_info *iinfo;
 649
 650        err = -EIO;
 651        inode = udf_new_inode(dir, S_IFDIR | mode, &err);
 652        if (!inode)
 653                goto out;
 654
 655        iinfo = UDF_I(inode);
 656        inode->i_op = &udf_dir_inode_operations;
 657        inode->i_fop = &udf_dir_operations;
 658        fi = udf_add_entry(inode, NULL, &fibh, &cfi, &err);
 659        if (!fi) {
 660                inode_dec_link_count(inode);
 661                iput(inode);
 662                goto out;
 663        }
 664        set_nlink(inode, 2);
 665        cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
 666        cfi.icb.extLocation = cpu_to_lelb(dinfo->i_location);
 667        *(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
 668                cpu_to_le32(dinfo->i_unique & 0x00000000FFFFFFFFUL);
 669        cfi.fileCharacteristics =
 670                        FID_FILE_CHAR_DIRECTORY | FID_FILE_CHAR_PARENT;
 671        udf_write_fi(inode, &cfi, fi, &fibh, NULL, NULL);
 672        brelse(fibh.sbh);
 673        mark_inode_dirty(inode);
 674
 675        fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
 676        if (!fi) {
 677                clear_nlink(inode);
 678                mark_inode_dirty(inode);
 679                iput(inode);
 680                goto out;
 681        }
 682        cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
 683        cfi.icb.extLocation = cpu_to_lelb(iinfo->i_location);
 684        *(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
 685                cpu_to_le32(iinfo->i_unique & 0x00000000FFFFFFFFUL);
 686        cfi.fileCharacteristics |= FID_FILE_CHAR_DIRECTORY;
 687        udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
 688        inc_nlink(dir);
 689        mark_inode_dirty(dir);
 690        d_instantiate(dentry, inode);
 691        if (fibh.sbh != fibh.ebh)
 692                brelse(fibh.ebh);
 693        brelse(fibh.sbh);
 694        err = 0;
 695
 696out:
 697        return err;
 698}
 699
 700static int empty_dir(struct inode *dir)
 701{
 702        struct fileIdentDesc *fi, cfi;
 703        struct udf_fileident_bh fibh;
 704        loff_t f_pos;
 705        loff_t size = udf_ext0_offset(dir) + dir->i_size;
 706        int block;
 707        struct kernel_lb_addr eloc;
 708        uint32_t elen;
 709        sector_t offset;
 710        struct extent_position epos = {};
 711        struct udf_inode_info *dinfo = UDF_I(dir);
 712
 713        f_pos = udf_ext0_offset(dir);
 714        fibh.soffset = fibh.eoffset = f_pos & (dir->i_sb->s_blocksize - 1);
 715
 716        if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
 717                fibh.sbh = fibh.ebh = NULL;
 718        else if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits,
 719                              &epos, &eloc, &elen, &offset) ==
 720                                        (EXT_RECORDED_ALLOCATED >> 30)) {
 721                block = udf_get_lb_pblock(dir->i_sb, &eloc, offset);
 722                if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
 723                        if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
 724                                epos.offset -= sizeof(struct short_ad);
 725                        else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
 726                                epos.offset -= sizeof(struct long_ad);
 727                } else
 728                        offset = 0;
 729
 730                fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block);
 731                if (!fibh.sbh) {
 732                        brelse(epos.bh);
 733                        return 0;
 734                }
 735        } else {
 736                brelse(epos.bh);
 737                return 0;
 738        }
 739
 740        while (f_pos < size) {
 741                fi = udf_fileident_read(dir, &f_pos, &fibh, &cfi, &epos, &eloc,
 742                                        &elen, &offset);
 743                if (!fi) {
 744                        if (fibh.sbh != fibh.ebh)
 745                                brelse(fibh.ebh);
 746                        brelse(fibh.sbh);
 747                        brelse(epos.bh);
 748                        return 0;
 749                }
 750
 751                if (cfi.lengthFileIdent &&
 752                    (cfi.fileCharacteristics & FID_FILE_CHAR_DELETED) == 0) {
 753                        if (fibh.sbh != fibh.ebh)
 754                                brelse(fibh.ebh);
 755                        brelse(fibh.sbh);
 756                        brelse(epos.bh);
 757                        return 0;
 758                }
 759        }
 760
 761        if (fibh.sbh != fibh.ebh)
 762                brelse(fibh.ebh);
 763        brelse(fibh.sbh);
 764        brelse(epos.bh);
 765
 766        return 1;
 767}
 768
 769static int udf_rmdir(struct inode *dir, struct dentry *dentry)
 770{
 771        int retval;
 772        struct inode *inode = dentry->d_inode;
 773        struct udf_fileident_bh fibh;
 774        struct fileIdentDesc *fi, cfi;
 775        struct kernel_lb_addr tloc;
 776
 777        retval = -ENOENT;
 778        fi = udf_find_entry(dir, &dentry->d_name, &fibh, &cfi);
 779        if (!fi)
 780                goto out;
 781
 782        retval = -EIO;
 783        tloc = lelb_to_cpu(cfi.icb.extLocation);
 784        if (udf_get_lb_pblock(dir->i_sb, &tloc, 0) != inode->i_ino)
 785                goto end_rmdir;
 786        retval = -ENOTEMPTY;
 787        if (!empty_dir(inode))
 788                goto end_rmdir;
 789        retval = udf_delete_entry(dir, fi, &fibh, &cfi);
 790        if (retval)
 791                goto end_rmdir;
 792        if (inode->i_nlink != 2)
 793                udf_warn(inode->i_sb, "empty directory has nlink != 2 (%d)\n",
 794                         inode->i_nlink);
 795        clear_nlink(inode);
 796        inode->i_size = 0;
 797        inode_dec_link_count(dir);
 798        inode->i_ctime = dir->i_ctime = dir->i_mtime =
 799                                                current_fs_time(dir->i_sb);
 800        mark_inode_dirty(dir);
 801
 802end_rmdir:
 803        if (fibh.sbh != fibh.ebh)
 804                brelse(fibh.ebh);
 805        brelse(fibh.sbh);
 806
 807out:
 808        return retval;
 809}
 810
 811static int udf_unlink(struct inode *dir, struct dentry *dentry)
 812{
 813        int retval;
 814        struct inode *inode = dentry->d_inode;
 815        struct udf_fileident_bh fibh;
 816        struct fileIdentDesc *fi;
 817        struct fileIdentDesc cfi;
 818        struct kernel_lb_addr tloc;
 819
 820        retval = -ENOENT;
 821        fi = udf_find_entry(dir, &dentry->d_name, &fibh, &cfi);
 822        if (!fi)
 823                goto out;
 824
 825        retval = -EIO;
 826        tloc = lelb_to_cpu(cfi.icb.extLocation);
 827        if (udf_get_lb_pblock(dir->i_sb, &tloc, 0) != inode->i_ino)
 828                goto end_unlink;
 829
 830        if (!inode->i_nlink) {
 831                udf_debug("Deleting nonexistent file (%lu), %d\n",
 832                          inode->i_ino, inode->i_nlink);
 833                set_nlink(inode, 1);
 834        }
 835        retval = udf_delete_entry(dir, fi, &fibh, &cfi);
 836        if (retval)
 837                goto end_unlink;
 838        dir->i_ctime = dir->i_mtime = current_fs_time(dir->i_sb);
 839        mark_inode_dirty(dir);
 840        inode_dec_link_count(inode);
 841        inode->i_ctime = dir->i_ctime;
 842        retval = 0;
 843
 844end_unlink:
 845        if (fibh.sbh != fibh.ebh)
 846                brelse(fibh.ebh);
 847        brelse(fibh.sbh);
 848
 849out:
 850        return retval;
 851}
 852
 853static int udf_symlink(struct inode *dir, struct dentry *dentry,
 854                       const char *symname)
 855{
 856        struct inode *inode;
 857        struct pathComponent *pc;
 858        const char *compstart;
 859        struct udf_fileident_bh fibh;
 860        struct extent_position epos = {};
 861        int eoffset, elen = 0;
 862        struct fileIdentDesc *fi;
 863        struct fileIdentDesc cfi;
 864        uint8_t *ea;
 865        int err;
 866        int block;
 867        unsigned char *name = NULL;
 868        int namelen;
 869        struct udf_inode_info *iinfo;
 870        struct super_block *sb = dir->i_sb;
 871
 872        inode = udf_new_inode(dir, S_IFLNK | S_IRWXUGO, &err);
 873        if (!inode)
 874                goto out;
 875
 876        iinfo = UDF_I(inode);
 877        down_write(&iinfo->i_data_sem);
 878        name = kmalloc(UDF_NAME_LEN, GFP_NOFS);
 879        if (!name) {
 880                err = -ENOMEM;
 881                goto out_no_entry;
 882        }
 883
 884        inode->i_data.a_ops = &udf_symlink_aops;
 885        inode->i_op = &udf_symlink_inode_operations;
 886
 887        if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
 888                struct kernel_lb_addr eloc;
 889                uint32_t bsize;
 890
 891                block = udf_new_block(sb, inode,
 892                                iinfo->i_location.partitionReferenceNum,
 893                                iinfo->i_location.logicalBlockNum, &err);
 894                if (!block)
 895                        goto out_no_entry;
 896                epos.block = iinfo->i_location;
 897                epos.offset = udf_file_entry_alloc_offset(inode);
 898                epos.bh = NULL;
 899                eloc.logicalBlockNum = block;
 900                eloc.partitionReferenceNum =
 901                                iinfo->i_location.partitionReferenceNum;
 902                bsize = sb->s_blocksize;
 903                iinfo->i_lenExtents = bsize;
 904                udf_add_aext(inode, &epos, &eloc, bsize, 0);
 905                brelse(epos.bh);
 906
 907                block = udf_get_pblock(sb, block,
 908                                iinfo->i_location.partitionReferenceNum,
 909                                0);
 910                epos.bh = udf_tgetblk(sb, block);
 911                lock_buffer(epos.bh);
 912                memset(epos.bh->b_data, 0x00, bsize);
 913                set_buffer_uptodate(epos.bh);
 914                unlock_buffer(epos.bh);
 915                mark_buffer_dirty_inode(epos.bh, inode);
 916                ea = epos.bh->b_data + udf_ext0_offset(inode);
 917        } else
 918                ea = iinfo->i_ext.i_data + iinfo->i_lenEAttr;
 919
 920        eoffset = sb->s_blocksize - udf_ext0_offset(inode);
 921        pc = (struct pathComponent *)ea;
 922
 923        if (*symname == '/') {
 924                do {
 925                        symname++;
 926                } while (*symname == '/');
 927
 928                pc->componentType = 1;
 929                pc->lengthComponentIdent = 0;
 930                pc->componentFileVersionNum = 0;
 931                elen += sizeof(struct pathComponent);
 932        }
 933
 934        err = -ENAMETOOLONG;
 935
 936        while (*symname) {
 937                if (elen + sizeof(struct pathComponent) > eoffset)
 938                        goto out_no_entry;
 939
 940                pc = (struct pathComponent *)(ea + elen);
 941
 942                compstart = symname;
 943
 944                do {
 945                        symname++;
 946                } while (*symname && *symname != '/');
 947
 948                pc->componentType = 5;
 949                pc->lengthComponentIdent = 0;
 950                pc->componentFileVersionNum = 0;
 951                if (compstart[0] == '.') {
 952                        if ((symname - compstart) == 1)
 953                                pc->componentType = 4;
 954                        else if ((symname - compstart) == 2 &&
 955                                        compstart[1] == '.')
 956                                pc->componentType = 3;
 957                }
 958
 959                if (pc->componentType == 5) {
 960                        namelen = udf_put_filename(sb, compstart, name,
 961                                                   symname - compstart);
 962                        if (!namelen)
 963                                goto out_no_entry;
 964
 965                        if (elen + sizeof(struct pathComponent) + namelen >
 966                                        eoffset)
 967                                goto out_no_entry;
 968                        else
 969                                pc->lengthComponentIdent = namelen;
 970
 971                        memcpy(pc->componentIdent, name, namelen);
 972                }
 973
 974                elen += sizeof(struct pathComponent) + pc->lengthComponentIdent;
 975
 976                if (*symname) {
 977                        do {
 978                                symname++;
 979                        } while (*symname == '/');
 980                }
 981        }
 982
 983        brelse(epos.bh);
 984        inode->i_size = elen;
 985        if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
 986                iinfo->i_lenAlloc = inode->i_size;
 987        else
 988                udf_truncate_tail_extent(inode);
 989        mark_inode_dirty(inode);
 990
 991        fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
 992        if (!fi)
 993                goto out_no_entry;
 994        cfi.icb.extLength = cpu_to_le32(sb->s_blocksize);
 995        cfi.icb.extLocation = cpu_to_lelb(iinfo->i_location);
 996        if (UDF_SB(inode->i_sb)->s_lvid_bh) {
 997                *(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
 998                        cpu_to_le32(lvid_get_unique_id(sb));
 999        }
1000        udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
1001        if (UDF_I(dir)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
1002                mark_inode_dirty(dir);
1003        up_write(&iinfo->i_data_sem);
1004        if (fibh.sbh != fibh.ebh)
1005                brelse(fibh.ebh);
1006        brelse(fibh.sbh);
1007        d_instantiate(dentry, inode);
1008        err = 0;
1009
1010out:
1011        kfree(name);
1012        return err;
1013
1014out_no_entry:
1015        up_write(&iinfo->i_data_sem);
1016        inode_dec_link_count(inode);
1017        iput(inode);
1018        goto out;
1019}
1020
1021static int udf_link(struct dentry *old_dentry, struct inode *dir,
1022                    struct dentry *dentry)
1023{
1024        struct inode *inode = old_dentry->d_inode;
1025        struct udf_fileident_bh fibh;
1026        struct fileIdentDesc cfi, *fi;
1027        int err;
1028
1029        fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
1030        if (!fi) {
1031                return err;
1032        }
1033        cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
1034        cfi.icb.extLocation = cpu_to_lelb(UDF_I(inode)->i_location);
1035        if (UDF_SB(inode->i_sb)->s_lvid_bh) {
1036                *(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
1037                        cpu_to_le32(lvid_get_unique_id(inode->i_sb));
1038        }
1039        udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
1040        if (UDF_I(dir)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
1041                mark_inode_dirty(dir);
1042
1043        if (fibh.sbh != fibh.ebh)
1044                brelse(fibh.ebh);
1045        brelse(fibh.sbh);
1046        inc_nlink(inode);
1047        inode->i_ctime = current_fs_time(inode->i_sb);
1048        mark_inode_dirty(inode);
1049        ihold(inode);
1050        d_instantiate(dentry, inode);
1051
1052        return 0;
1053}
1054
1055/* Anybody can rename anything with this: the permission checks are left to the
1056 * higher-level routines.
1057 */
1058static int udf_rename(struct inode *old_dir, struct dentry *old_dentry,
1059                      struct inode *new_dir, struct dentry *new_dentry)
1060{
1061        struct inode *old_inode = old_dentry->d_inode;
1062        struct inode *new_inode = new_dentry->d_inode;
1063        struct udf_fileident_bh ofibh, nfibh;
1064        struct fileIdentDesc *ofi = NULL, *nfi = NULL, *dir_fi = NULL;
1065        struct fileIdentDesc ocfi, ncfi;
1066        struct buffer_head *dir_bh = NULL;
1067        int retval = -ENOENT;
1068        struct kernel_lb_addr tloc;
1069        struct udf_inode_info *old_iinfo = UDF_I(old_inode);
1070
1071        ofi = udf_find_entry(old_dir, &old_dentry->d_name, &ofibh, &ocfi);
1072        if (ofi) {
1073                if (ofibh.sbh != ofibh.ebh)
1074                        brelse(ofibh.ebh);
1075                brelse(ofibh.sbh);
1076        }
1077        tloc = lelb_to_cpu(ocfi.icb.extLocation);
1078        if (!ofi || udf_get_lb_pblock(old_dir->i_sb, &tloc, 0)
1079            != old_inode->i_ino)
1080                goto end_rename;
1081
1082        nfi = udf_find_entry(new_dir, &new_dentry->d_name, &nfibh, &ncfi);
1083        if (nfi) {
1084                if (!new_inode) {
1085                        if (nfibh.sbh != nfibh.ebh)
1086                                brelse(nfibh.ebh);
1087                        brelse(nfibh.sbh);
1088                        nfi = NULL;
1089                }
1090        }
1091        if (S_ISDIR(old_inode->i_mode)) {
1092                int offset = udf_ext0_offset(old_inode);
1093
1094                if (new_inode) {
1095                        retval = -ENOTEMPTY;
1096                        if (!empty_dir(new_inode))
1097                                goto end_rename;
1098                }
1099                retval = -EIO;
1100                if (old_iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
1101                        dir_fi = udf_get_fileident(
1102                                        old_iinfo->i_ext.i_data -
1103                                          (old_iinfo->i_efe ?
1104                                           sizeof(struct extendedFileEntry) :
1105                                           sizeof(struct fileEntry)),
1106                                        old_inode->i_sb->s_blocksize, &offset);
1107                } else {
1108                        dir_bh = udf_bread(old_inode, 0, 0, &retval);
1109                        if (!dir_bh)
1110                                goto end_rename;
1111                        dir_fi = udf_get_fileident(dir_bh->b_data,
1112                                        old_inode->i_sb->s_blocksize, &offset);
1113                }
1114                if (!dir_fi)
1115                        goto end_rename;
1116                tloc = lelb_to_cpu(dir_fi->icb.extLocation);
1117                if (udf_get_lb_pblock(old_inode->i_sb, &tloc, 0) !=
1118                                old_dir->i_ino)
1119                        goto end_rename;
1120        }
1121        if (!nfi) {
1122                nfi = udf_add_entry(new_dir, new_dentry, &nfibh, &ncfi,
1123                                    &retval);
1124                if (!nfi)
1125                        goto end_rename;
1126        }
1127
1128        /*
1129         * Like most other Unix systems, set the ctime for inodes on a
1130         * rename.
1131         */
1132        old_inode->i_ctime = current_fs_time(old_inode->i_sb);
1133        mark_inode_dirty(old_inode);
1134
1135        /*
1136         * ok, that's it
1137         */
1138        ncfi.fileVersionNum = ocfi.fileVersionNum;
1139        ncfi.fileCharacteristics = ocfi.fileCharacteristics;
1140        memcpy(&(ncfi.icb), &(ocfi.icb), sizeof(struct long_ad));
1141        udf_write_fi(new_dir, &ncfi, nfi, &nfibh, NULL, NULL);
1142
1143        /* The old fid may have moved - find it again */
1144        ofi = udf_find_entry(old_dir, &old_dentry->d_name, &ofibh, &ocfi);
1145        udf_delete_entry(old_dir, ofi, &ofibh, &ocfi);
1146
1147        if (new_inode) {
1148                new_inode->i_ctime = current_fs_time(new_inode->i_sb);
1149                inode_dec_link_count(new_inode);
1150        }
1151        old_dir->i_ctime = old_dir->i_mtime = current_fs_time(old_dir->i_sb);
1152        mark_inode_dirty(old_dir);
1153
1154        if (dir_fi) {
1155                dir_fi->icb.extLocation = cpu_to_lelb(UDF_I(new_dir)->i_location);
1156                udf_update_tag((char *)dir_fi,
1157                                (sizeof(struct fileIdentDesc) +
1158                                le16_to_cpu(dir_fi->lengthOfImpUse) + 3) & ~3);
1159                if (old_iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
1160                        mark_inode_dirty(old_inode);
1161                else
1162                        mark_buffer_dirty_inode(dir_bh, old_inode);
1163
1164                inode_dec_link_count(old_dir);
1165                if (new_inode)
1166                        inode_dec_link_count(new_inode);
1167                else {
1168                        inc_nlink(new_dir);
1169                        mark_inode_dirty(new_dir);
1170                }
1171        }
1172
1173        if (ofi) {
1174                if (ofibh.sbh != ofibh.ebh)
1175                        brelse(ofibh.ebh);
1176                brelse(ofibh.sbh);
1177        }
1178
1179        retval = 0;
1180
1181end_rename:
1182        brelse(dir_bh);
1183        if (nfi) {
1184                if (nfibh.sbh != nfibh.ebh)
1185                        brelse(nfibh.ebh);
1186                brelse(nfibh.sbh);
1187        }
1188
1189        return retval;
1190}
1191
1192static struct dentry *udf_get_parent(struct dentry *child)
1193{
1194        struct kernel_lb_addr tloc;
1195        struct inode *inode = NULL;
1196        struct qstr dotdot = QSTR_INIT("..", 2);
1197        struct fileIdentDesc cfi;
1198        struct udf_fileident_bh fibh;
1199
1200        if (!udf_find_entry(child->d_inode, &dotdot, &fibh, &cfi))
1201                goto out_unlock;
1202
1203        if (fibh.sbh != fibh.ebh)
1204                brelse(fibh.ebh);
1205        brelse(fibh.sbh);
1206
1207        tloc = lelb_to_cpu(cfi.icb.extLocation);
1208        inode = udf_iget(child->d_inode->i_sb, &tloc);
1209        if (!inode)
1210                goto out_unlock;
1211
1212        return d_obtain_alias(inode);
1213out_unlock:
1214        return ERR_PTR(-EACCES);
1215}
1216
1217
1218static struct dentry *udf_nfs_get_inode(struct super_block *sb, u32 block,
1219                                        u16 partref, __u32 generation)
1220{
1221        struct inode *inode;
1222        struct kernel_lb_addr loc;
1223
1224        if (block == 0)
1225                return ERR_PTR(-ESTALE);
1226
1227        loc.logicalBlockNum = block;
1228        loc.partitionReferenceNum = partref;
1229        inode = udf_iget(sb, &loc);
1230
1231        if (inode == NULL)
1232                return ERR_PTR(-ENOMEM);
1233
1234        if (generation && inode->i_generation != generation) {
1235                iput(inode);
1236                return ERR_PTR(-ESTALE);
1237        }
1238        return d_obtain_alias(inode);
1239}
1240
1241static struct dentry *udf_fh_to_dentry(struct super_block *sb,
1242                                       struct fid *fid, int fh_len, int fh_type)
1243{
1244        if ((fh_len != 3 && fh_len != 5) ||
1245            (fh_type != FILEID_UDF_WITH_PARENT &&
1246             fh_type != FILEID_UDF_WITHOUT_PARENT))
1247                return NULL;
1248
1249        return udf_nfs_get_inode(sb, fid->udf.block, fid->udf.partref,
1250                        fid->udf.generation);
1251}
1252
1253static struct dentry *udf_fh_to_parent(struct super_block *sb,
1254                                       struct fid *fid, int fh_len, int fh_type)
1255{
1256        if (fh_len != 5 || fh_type != FILEID_UDF_WITH_PARENT)
1257                return NULL;
1258
1259        return udf_nfs_get_inode(sb, fid->udf.parent_block,
1260                                 fid->udf.parent_partref,
1261                                 fid->udf.parent_generation);
1262}
1263static int udf_encode_fh(struct inode *inode, __u32 *fh, int *lenp,
1264                         struct inode *parent)
1265{
1266        int len = *lenp;
1267        struct kernel_lb_addr location = UDF_I(inode)->i_location;
1268        struct fid *fid = (struct fid *)fh;
1269        int type = FILEID_UDF_WITHOUT_PARENT;
1270
1271        if (parent && (len < 5)) {
1272                *lenp = 5;
1273                return 255;
1274        } else if (len < 3) {
1275                *lenp = 3;
1276                return 255;
1277        }
1278
1279        *lenp = 3;
1280        fid->udf.block = location.logicalBlockNum;
1281        fid->udf.partref = location.partitionReferenceNum;
1282        fid->udf.parent_partref = 0;
1283        fid->udf.generation = inode->i_generation;
1284
1285        if (parent) {
1286                location = UDF_I(parent)->i_location;
1287                fid->udf.parent_block = location.logicalBlockNum;
1288                fid->udf.parent_partref = location.partitionReferenceNum;
1289                fid->udf.parent_generation = inode->i_generation;
1290                *lenp = 5;
1291                type = FILEID_UDF_WITH_PARENT;
1292        }
1293
1294        return type;
1295}
1296
1297const struct export_operations udf_export_ops = {
1298        .encode_fh      = udf_encode_fh,
1299        .fh_to_dentry   = udf_fh_to_dentry,
1300        .fh_to_parent   = udf_fh_to_parent,
1301        .get_parent     = udf_get_parent,
1302};
1303
1304const struct inode_operations udf_dir_inode_operations = {
1305        .lookup                         = udf_lookup,
1306        .create                         = udf_create,
1307        .link                           = udf_link,
1308        .unlink                         = udf_unlink,
1309        .symlink                        = udf_symlink,
1310        .mkdir                          = udf_mkdir,
1311        .rmdir                          = udf_rmdir,
1312        .mknod                          = udf_mknod,
1313        .rename                         = udf_rename,
1314};
1315const struct inode_operations udf_symlink_inode_operations = {
1316        .readlink       = generic_readlink,
1317        .follow_link    = page_follow_link_light,
1318        .put_link       = page_put_link,
1319};
1320
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.