aboutsummaryrefslogtreecommitdiffstats
path: root/fs/udf/dir.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-07-02 12:28:37 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-02 12:28:37 -0400
commit63580e51bb3e7ec459501165884e5f815a7a9322 (patch)
tree2130de984dda95996bc7922734feb465a13fca70 /fs/udf/dir.c
parent7747bd4bceb3079572695d3942294a6c7b265557 (diff)
parentac6614b76478e68173ccf7ad4e9e98035cc9c21d (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull VFS patches (part 1) from Al Viro: "The major change in this pile is ->readdir() replacement with ->iterate(), dealing with ->f_pos races in ->readdir() instances for good. There's a lot more, but I'd prefer to split the pull request into several stages and this is the first obvious cutoff point." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (67 commits) [readdir] constify ->actor [readdir] ->readdir() is gone [readdir] convert ecryptfs [readdir] convert coda [readdir] convert ocfs2 [readdir] convert fatfs [readdir] convert xfs [readdir] convert btrfs [readdir] convert hostfs [readdir] convert afs [readdir] convert ncpfs [readdir] convert hfsplus [readdir] convert hfs [readdir] convert befs [readdir] convert cifs [readdir] convert freevxfs [readdir] convert fuse [readdir] convert hpfs reiserfs: switch reiserfs_readdir_dentry to inode reiserfs: is_privroot_deh() needs only directory inode, actually ...
Diffstat (limited to 'fs/udf/dir.c')
-rw-r--r--fs/udf/dir.c63
1 files changed, 26 insertions, 37 deletions
diff --git a/fs/udf/dir.c b/fs/udf/dir.c
index b3e93f5e17c3..a012c51caffd 100644
--- a/fs/udf/dir.c
+++ b/fs/udf/dir.c
@@ -35,14 +35,16 @@
35#include "udf_i.h" 35#include "udf_i.h"
36#include "udf_sb.h" 36#include "udf_sb.h"
37 37
38static int do_udf_readdir(struct inode *dir, struct file *filp, 38
39 filldir_t filldir, void *dirent) 39static int udf_readdir(struct file *file, struct dir_context *ctx)
40{ 40{
41 struct inode *dir = file_inode(file);
42 struct udf_inode_info *iinfo = UDF_I(dir);
41 struct udf_fileident_bh fibh = { .sbh = NULL, .ebh = NULL}; 43 struct udf_fileident_bh fibh = { .sbh = NULL, .ebh = NULL};
42 struct fileIdentDesc *fi = NULL; 44 struct fileIdentDesc *fi = NULL;
43 struct fileIdentDesc cfi; 45 struct fileIdentDesc cfi;
44 int block, iblock; 46 int block, iblock;
45 loff_t nf_pos = (filp->f_pos - 1) << 2; 47 loff_t nf_pos;
46 int flen; 48 int flen;
47 unsigned char *fname = NULL; 49 unsigned char *fname = NULL;
48 unsigned char *nameptr; 50 unsigned char *nameptr;
@@ -54,10 +56,14 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
54 uint32_t elen; 56 uint32_t elen;
55 sector_t offset; 57 sector_t offset;
56 int i, num, ret = 0; 58 int i, num, ret = 0;
57 unsigned int dt_type;
58 struct extent_position epos = { NULL, 0, {0, 0} }; 59 struct extent_position epos = { NULL, 0, {0, 0} };
59 struct udf_inode_info *iinfo;
60 60
61 if (ctx->pos == 0) {
62 if (!dir_emit_dot(file, ctx))
63 return 0;
64 ctx->pos = 1;
65 }
66 nf_pos = (ctx->pos - 1) << 2;
61 if (nf_pos >= size) 67 if (nf_pos >= size)
62 goto out; 68 goto out;
63 69
@@ -71,7 +77,6 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
71 nf_pos = udf_ext0_offset(dir); 77 nf_pos = udf_ext0_offset(dir);
72 78
73 fibh.soffset = fibh.eoffset = nf_pos & (dir->i_sb->s_blocksize - 1); 79 fibh.soffset = fibh.eoffset = nf_pos & (dir->i_sb->s_blocksize - 1);
74 iinfo = UDF_I(dir);
75 if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { 80 if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
76 if (inode_bmap(dir, nf_pos >> dir->i_sb->s_blocksize_bits, 81 if (inode_bmap(dir, nf_pos >> dir->i_sb->s_blocksize_bits,
77 &epos, &eloc, &elen, &offset) 82 &epos, &eloc, &elen, &offset)
@@ -116,7 +121,9 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
116 } 121 }
117 122
118 while (nf_pos < size) { 123 while (nf_pos < size) {
119 filp->f_pos = (nf_pos >> 2) + 1; 124 struct kernel_lb_addr tloc;
125
126 ctx->pos = (nf_pos >> 2) + 1;
120 127
121 fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &epos, &eloc, 128 fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &epos, &eloc,
122 &elen, &offset); 129 &elen, &offset);
@@ -155,24 +162,22 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
155 } 162 }
156 163
157 if (cfi.fileCharacteristics & FID_FILE_CHAR_PARENT) { 164 if (cfi.fileCharacteristics & FID_FILE_CHAR_PARENT) {
158 iblock = parent_ino(filp->f_path.dentry); 165 if (!dir_emit_dotdot(file, ctx))
159 flen = 2; 166 goto out;
160 memcpy(fname, "..", flen); 167 continue;
161 dt_type = DT_DIR;
162 } else {
163 struct kernel_lb_addr tloc = lelb_to_cpu(cfi.icb.extLocation);
164
165 iblock = udf_get_lb_pblock(dir->i_sb, &tloc, 0);
166 flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi);
167 dt_type = DT_UNKNOWN;
168 } 168 }
169 169
170 if (flen && filldir(dirent, fname, flen, filp->f_pos, 170 flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi);
171 iblock, dt_type) < 0) 171 if (!flen)
172 continue;
173
174 tloc = lelb_to_cpu(cfi.icb.extLocation);
175 iblock = udf_get_lb_pblock(dir->i_sb, &tloc, 0);
176 if (!dir_emit(ctx, fname, flen, iblock, DT_UNKNOWN))
172 goto out; 177 goto out;
173 } /* end while */ 178 } /* end while */
174 179
175 filp->f_pos = (nf_pos >> 2) + 1; 180 ctx->pos = (nf_pos >> 2) + 1;
176 181
177out: 182out:
178 if (fibh.sbh != fibh.ebh) 183 if (fibh.sbh != fibh.ebh)
@@ -184,27 +189,11 @@ out:
184 return ret; 189 return ret;
185} 190}
186 191
187static int udf_readdir(struct file *filp, void *dirent, filldir_t filldir)
188{
189 struct inode *dir = file_inode(filp);
190 int result;
191
192 if (filp->f_pos == 0) {
193 if (filldir(dirent, ".", 1, filp->f_pos, dir->i_ino, DT_DIR) < 0) {
194 return 0;
195 }
196 filp->f_pos++;
197 }
198
199 result = do_udf_readdir(dir, filp, filldir, dirent);
200 return result;
201}
202
203/* readdir and lookup functions */ 192/* readdir and lookup functions */
204const struct file_operations udf_dir_operations = { 193const struct file_operations udf_dir_operations = {
205 .llseek = generic_file_llseek, 194 .llseek = generic_file_llseek,
206 .read = generic_read_dir, 195 .read = generic_read_dir,
207 .readdir = udf_readdir, 196 .iterate = udf_readdir,
208 .unlocked_ioctl = udf_ioctl, 197 .unlocked_ioctl = udf_ioctl,
209 .fsync = generic_file_fsync, 198 .fsync = generic_file_fsync,
210}; 199};