Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
[pandora-kernel.git] / fs / udf / dir.c
index 8d8643a..62dc270 100644 (file)
 static int do_udf_readdir(struct inode *dir, struct file *filp,
                          filldir_t filldir, void *dirent)
 {
-       struct udf_fileident_bh fibh;
+       struct udf_fileident_bh fibh = { .sbh = NULL, .ebh = NULL};
        struct fileIdentDesc *fi = NULL;
        struct fileIdentDesc cfi;
        int block, iblock;
        loff_t nf_pos = (filp->f_pos - 1) << 2;
        int flen;
-       char fname[UDF_NAME_LEN];
+       char *fname = NULL;
        char *nameptr;
        uint16_t liu;
        uint8_t lfi;
@@ -54,23 +54,32 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
        kernel_lb_addr eloc;
        uint32_t elen;
        sector_t offset;
-       int i, num;
+       int i, num, ret = 0;
        unsigned int dt_type;
        struct extent_position epos = { NULL, 0, {0, 0} };
        struct udf_inode_info *iinfo;
 
        if (nf_pos >= size)
-               return 0;
+               goto out;
+
+       fname = kmalloc(UDF_NAME_LEN, GFP_NOFS);
+       if (!fname) {
+               ret = -ENOMEM;
+               goto out;
+       }
 
        if (nf_pos == 0)
                nf_pos = udf_ext0_offset(dir);
 
        fibh.soffset = fibh.eoffset = nf_pos & (dir->i_sb->s_blocksize - 1);
        iinfo = UDF_I(dir);
-       if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
-               fibh.sbh = fibh.ebh = NULL;
-       } else if (inode_bmap(dir, nf_pos >> dir->i_sb->s_blocksize_bits,
-                             &epos, &eloc, &elen, &offset) == (EXT_RECORDED_ALLOCATED >> 30)) {
+       if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
+               if (inode_bmap(dir, nf_pos >> dir->i_sb->s_blocksize_bits,
+                   &epos, &eloc, &elen, &offset)
+                   != (EXT_RECORDED_ALLOCATED >> 30)) {
+                       ret = -ENOENT;
+                       goto out;
+               }
                block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
                if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
                        if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
@@ -83,8 +92,8 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
                }
 
                if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block))) {
-                       brelse(epos.bh);
-                       return -EIO;
+                       ret = -EIO;
+                       goto out;
                }
 
                if (!(offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9)) - 1))) {
@@ -105,9 +114,6 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
                                        brelse(bha[i]);
                        }
                }
-       } else {
-               brelse(epos.bh);
-               return -ENOENT;
        }
 
        while (nf_pos < size) {
@@ -115,13 +121,8 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
 
                fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &epos, &eloc,
                                        &elen, &offset);
-               if (!fi) {
-                       if (fibh.sbh != fibh.ebh)
-                               brelse(fibh.ebh);
-                       brelse(fibh.sbh);
-                       brelse(epos.bh);
-                       return 0;
-               }
+               if (!fi)
+                       goto out;
 
                liu = le16_to_cpu(cfi.lengthOfImpUse);
                lfi = cfi.lengthFileIdent;
@@ -167,53 +168,23 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
                        dt_type = DT_UNKNOWN;
                }
 
-               if (flen) {
-                       if (filldir(dirent, fname, flen, filp->f_pos, iblock, dt_type) < 0) {
-                               if (fibh.sbh != fibh.ebh)
-                                       brelse(fibh.ebh);
-                               brelse(fibh.sbh);
-                               brelse(epos.bh);
-                               return 0;
-                       }
-               }
+               if (flen && filldir(dirent, fname, flen, filp->f_pos,
+                                   iblock, dt_type) < 0)
+                       goto out;
        } /* end while */
 
        filp->f_pos = (nf_pos >> 2) + 1;
 
+out:
        if (fibh.sbh != fibh.ebh)
                brelse(fibh.ebh);
        brelse(fibh.sbh);
        brelse(epos.bh);
+       kfree(fname);
 
-       return 0;
+       return ret;
 }
 
-/*
- * udf_readdir
- *
- * PURPOSE
- *     Read a directory entry.
- *
- * DESCRIPTION
- *     Optional - sys_getdents() will return -ENOTDIR if this routine is not
- *     available.
- *
- *     Refer to sys_getdents() in fs/readdir.c
- *     sys_getdents() -> .
- *
- * PRE-CONDITIONS
- *     filp                    Pointer to directory file.
- *     buf                     Pointer to directory entry buffer.
- *     filldir                 Pointer to filldir function.
- *
- * POST-CONDITIONS
- *     <return>                >=0 on success.
- *
- * HISTORY
- *     July 1, 1997 - Andrew E. Mileski
- *     Written, tested, and released.
- */
-
 static int udf_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
        struct inode *dir = filp->f_path.dentry->d_inode;