Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

udf: Convert udf_readdir() to new directory iteration

Convert udf_readdir() to new directory iteration functions.

Signed-off-by: Jan Kara <jack@suse.cz>

Jan Kara 7cd7a36a d16076d9

+27 -121
+27 -121
fs/udf/dir.c
··· 39 39 static int udf_readdir(struct file *file, struct dir_context *ctx) 40 40 { 41 41 struct inode *dir = file_inode(file); 42 - struct udf_inode_info *iinfo = UDF_I(dir); 43 - struct udf_fileident_bh fibh = { .sbh = NULL, .ebh = NULL}; 44 - struct fileIdentDesc *fi = NULL; 45 - struct fileIdentDesc cfi; 46 - udf_pblk_t block, iblock; 47 42 loff_t nf_pos, emit_pos = 0; 48 43 int flen; 49 - unsigned char *fname = NULL, *copy_name = NULL; 50 - unsigned char *nameptr; 51 - uint16_t liu; 52 - uint8_t lfi; 53 - loff_t size = udf_ext0_offset(dir) + dir->i_size; 54 - struct buffer_head *tmp, *bha[16]; 55 - struct kernel_lb_addr eloc; 56 - uint32_t elen; 57 - sector_t offset; 58 - int i, num, ret = 0; 59 - struct extent_position epos = { NULL, 0, {0, 0} }; 44 + unsigned char *fname = NULL; 45 + int ret = 0; 60 46 struct super_block *sb = dir->i_sb; 61 47 bool pos_valid = false; 48 + struct udf_fileident_iter iter; 62 49 63 50 if (ctx->pos == 0) { 64 51 if (!dir_emit_dot(file, ctx)) ··· 53 66 ctx->pos = 1; 54 67 } 55 68 nf_pos = (ctx->pos - 1) << 2; 56 - if (nf_pos >= size) 69 + if (nf_pos >= dir->i_size) 57 70 goto out; 58 71 59 72 /* ··· 77 90 goto out; 78 91 } 79 92 80 - if (nf_pos == 0) 81 - nf_pos = udf_ext0_offset(dir); 82 - 83 - fibh.soffset = fibh.eoffset = nf_pos & (sb->s_blocksize - 1); 84 - if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { 85 - if (inode_bmap(dir, nf_pos >> sb->s_blocksize_bits, 86 - &epos, &eloc, &elen, &offset) 87 - != (EXT_RECORDED_ALLOCATED >> 30)) { 88 - ret = -ENOENT; 89 - goto out; 90 - } 91 - block = udf_get_lb_pblock(sb, &eloc, offset); 92 - if ((++offset << sb->s_blocksize_bits) < elen) { 93 - if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) 94 - epos.offset -= sizeof(struct short_ad); 95 - else if (iinfo->i_alloc_type == 96 - ICBTAG_FLAG_AD_LONG) 97 - epos.offset -= sizeof(struct long_ad); 98 - } else { 99 - offset = 0; 100 - } 101 - 102 - if (!(fibh.sbh = fibh.ebh = udf_tread(sb, block))) { 103 - ret = -EIO; 104 - goto out; 105 - } 106 - 107 - if (!(offset & ((16 >> (sb->s_blocksize_bits - 9)) - 1))) { 108 - i = 16 >> (sb->s_blocksize_bits - 9); 109 - if (i + offset > (elen >> sb->s_blocksize_bits)) 110 - i = (elen >> sb->s_blocksize_bits) - offset; 111 - for (num = 0; i > 0; i--) { 112 - block = udf_get_lb_pblock(sb, &eloc, offset + i); 113 - tmp = udf_tgetblk(sb, block); 114 - if (tmp && !buffer_uptodate(tmp) && !buffer_locked(tmp)) 115 - bha[num++] = tmp; 116 - else 117 - brelse(tmp); 118 - } 119 - if (num) { 120 - bh_readahead_batch(num, bha, REQ_RAHEAD); 121 - for (i = 0; i < num; i++) 122 - brelse(bha[i]); 123 - } 124 - } 125 - } 126 - 127 - while (nf_pos < size) { 93 + for (ret = udf_fiiter_init(&iter, dir, nf_pos); 94 + !ret && iter.pos < dir->i_size; 95 + ret = udf_fiiter_advance(&iter)) { 128 96 struct kernel_lb_addr tloc; 129 - loff_t cur_pos = nf_pos; 97 + udf_pblk_t iblock; 130 98 131 - /* Update file position only if we got past the current one */ 132 - if (nf_pos >= emit_pos) { 133 - ctx->pos = (nf_pos >> 2) + 1; 134 - pos_valid = true; 135 - } 136 - 137 - fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &epos, &eloc, 138 - &elen, &offset); 139 - if (!fi) 140 - goto out; 141 99 /* Still not at offset where user asked us to read from? */ 142 - if (cur_pos < emit_pos) 100 + if (iter.pos < emit_pos) 143 101 continue; 144 102 145 - liu = le16_to_cpu(cfi.lengthOfImpUse); 146 - lfi = cfi.lengthFileIdent; 103 + /* Update file position only if we got past the current one */ 104 + pos_valid = true; 105 + ctx->pos = (iter.pos >> 2) + 1; 147 106 148 - if (fibh.sbh == fibh.ebh) { 149 - nameptr = udf_get_fi_ident(fi); 150 - } else { 151 - int poffset; /* Unpaded ending offset */ 152 - 153 - poffset = fibh.soffset + sizeof(struct fileIdentDesc) + liu + lfi; 154 - 155 - if (poffset >= lfi) { 156 - nameptr = (char *)(fibh.ebh->b_data + poffset - lfi); 157 - } else { 158 - if (!copy_name) { 159 - copy_name = kmalloc(UDF_NAME_LEN, 160 - GFP_NOFS); 161 - if (!copy_name) { 162 - ret = -ENOMEM; 163 - goto out; 164 - } 165 - } 166 - nameptr = copy_name; 167 - memcpy(nameptr, udf_get_fi_ident(fi), 168 - lfi - poffset); 169 - memcpy(nameptr + lfi - poffset, 170 - fibh.ebh->b_data, poffset); 171 - } 172 - } 173 - 174 - if ((cfi.fileCharacteristics & FID_FILE_CHAR_DELETED) != 0) { 107 + if (iter.fi.fileCharacteristics & FID_FILE_CHAR_DELETED) { 175 108 if (!UDF_QUERY_FLAG(sb, UDF_FLAG_UNDELETE)) 176 109 continue; 177 110 } 178 111 179 - if ((cfi.fileCharacteristics & FID_FILE_CHAR_HIDDEN) != 0) { 112 + if (iter.fi.fileCharacteristics & FID_FILE_CHAR_HIDDEN) { 180 113 if (!UDF_QUERY_FLAG(sb, UDF_FLAG_UNHIDE)) 181 114 continue; 182 115 } 183 116 184 - if (cfi.fileCharacteristics & FID_FILE_CHAR_PARENT) { 117 + if (iter.fi.fileCharacteristics & FID_FILE_CHAR_PARENT) { 185 118 if (!dir_emit_dotdot(file, ctx)) 186 - goto out; 119 + goto out_iter; 187 120 continue; 188 121 } 189 122 190 - flen = udf_get_filename(sb, nameptr, lfi, fname, UDF_NAME_LEN); 123 + flen = udf_get_filename(sb, iter.name, 124 + iter.fi.lengthFileIdent, fname, UDF_NAME_LEN); 191 125 if (flen < 0) 192 126 continue; 193 127 194 - tloc = lelb_to_cpu(cfi.icb.extLocation); 128 + tloc = lelb_to_cpu(iter.fi.icb.extLocation); 195 129 iblock = udf_get_lb_pblock(sb, &tloc, 0); 196 130 if (!dir_emit(ctx, fname, flen, iblock, DT_UNKNOWN)) 197 - goto out; 198 - } /* end while */ 131 + goto out_iter; 132 + } 199 133 200 - ctx->pos = (nf_pos >> 2) + 1; 201 - pos_valid = true; 202 - 134 + if (!ret) { 135 + ctx->pos = (iter.pos >> 2) + 1; 136 + pos_valid = true; 137 + } 138 + out_iter: 139 + udf_fiiter_release(&iter); 203 140 out: 204 141 if (pos_valid) 205 142 file->f_version = inode_query_iversion(dir); 206 - if (fibh.sbh != fibh.ebh) 207 - brelse(fibh.ebh); 208 - brelse(fibh.sbh); 209 - brelse(epos.bh); 210 143 kfree(fname); 211 - kfree(copy_name); 212 144 213 145 return ret; 214 146 }