@@ -92,14 +92,13 @@ EXPORT_SYMBOL(dcache_dir_close);
92
92
/*
93
93
* Returns an element of siblings' list.
94
94
* We are looking for <count>th positive after <p>; if
95
- * found, dentry is grabbed and passed to caller via *<res>.
96
- * If no such element exists, the anchor of list is returned
97
- * and *<res> is set to NULL.
95
+ * found, dentry is grabbed and returned to caller.
96
+ * If no such element exists, NULL is returned.
98
97
*/
99
- static struct list_head * scan_positives (struct dentry * cursor ,
98
+ static struct dentry * scan_positives (struct dentry * cursor ,
100
99
struct list_head * p ,
101
100
loff_t count ,
102
- struct dentry * * res )
101
+ struct dentry * last )
103
102
{
104
103
struct dentry * dentry = cursor -> d_parent , * found = NULL ;
105
104
@@ -127,9 +126,8 @@ static struct list_head *scan_positives(struct dentry *cursor,
127
126
}
128
127
}
129
128
spin_unlock (& dentry -> d_lock );
130
- dput (* res );
131
- * res = found ;
132
- return p ;
129
+ dput (last );
130
+ return found ;
133
131
}
134
132
135
133
loff_t dcache_dir_lseek (struct file * file , loff_t offset , int whence )
@@ -149,25 +147,22 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int whence)
149
147
if (offset != file -> f_pos ) {
150
148
struct dentry * cursor = file -> private_data ;
151
149
struct dentry * to = NULL ;
152
- struct list_head * p ;
153
150
154
- file -> f_pos = offset ;
155
151
inode_lock_shared (dentry -> d_inode );
156
152
157
- if (file -> f_pos > 2 ) {
158
- p = scan_positives (cursor , & dentry -> d_subdirs ,
159
- file -> f_pos - 2 , & to );
160
- spin_lock (& dentry -> d_lock );
161
- list_move (& cursor -> d_child , p );
162
- spin_unlock (& dentry -> d_lock );
163
- } else {
164
- spin_lock (& dentry -> d_lock );
153
+ if (offset > 2 )
154
+ to = scan_positives (cursor , & dentry -> d_subdirs ,
155
+ offset - 2 , NULL );
156
+ spin_lock (& dentry -> d_lock );
157
+ if (to )
158
+ list_move (& cursor -> d_child , & to -> d_child );
159
+ else
165
160
list_del_init (& cursor -> d_child );
166
- spin_unlock (& dentry -> d_lock );
167
- }
168
-
161
+ spin_unlock (& dentry -> d_lock );
169
162
dput (to );
170
163
164
+ file -> f_pos = offset ;
165
+
171
166
inode_unlock_shared (dentry -> d_inode );
172
167
}
173
168
return offset ;
@@ -199,17 +194,23 @@ int dcache_readdir(struct file *file, struct dir_context *ctx)
199
194
200
195
if (ctx -> pos == 2 )
201
196
p = anchor ;
202
- else
197
+ else if (! list_empty ( & cursor -> d_child ))
203
198
p = & cursor -> d_child ;
199
+ else
200
+ return 0 ;
204
201
205
- while ((p = scan_positives (cursor , p , 1 , & next )) != anchor ) {
202
+ while ((next = scan_positives (cursor , p , 1 , next )) != NULL ) {
206
203
if (!dir_emit (ctx , next -> d_name .name , next -> d_name .len ,
207
204
d_inode (next )-> i_ino , dt_type (d_inode (next ))))
208
205
break ;
209
206
ctx -> pos ++ ;
207
+ p = & next -> d_child ;
210
208
}
211
209
spin_lock (& dentry -> d_lock );
212
- list_move_tail (& cursor -> d_child , p );
210
+ if (next )
211
+ list_move_tail (& cursor -> d_child , & next -> d_child );
212
+ else
213
+ list_del_init (& cursor -> d_child );
213
214
spin_unlock (& dentry -> d_lock );
214
215
dput (next );
215
216
0 commit comments