aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorBryan Schumaker <bjschuma@netapp.com>2010-09-24 14:48:42 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2010-10-23 15:27:30 -0400
commitd1bacf9eb2fd0e7ef870acf84b9e3b157dcfa7dc (patch)
tree8b6746ade07c71f0d40c29b76dbe65e999c038f7 /fs
parent8c7597f6ce212bbc8ca05090e21820ffe9792b3d (diff)
NFS: add readdir cache array
This patch adds the readdir cache array and functions to retreive the array stored on a cache page, clear the array by freeing allocated memory, add an entry to the array, and search the array for a given cookie. It then modifies readdir to make use of the new cache array. With the new cache array method, we no longer need some of this code. Finally, nfs_llseek_dir() will set file->f_pos to a value greater than 0 and desc->dir_cookie to zero. When we see this, readdir needs to find the file at position file->f_pos from the start of the directory. Signed-off-by: Bryan Schumaker <bjschuma@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/dir.c632
1 files changed, 309 insertions, 323 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index a847acf4d3cd..f77243907a08 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -55,6 +55,7 @@ static int nfs_rename(struct inode *, struct dentry *,
55 struct inode *, struct dentry *); 55 struct inode *, struct dentry *);
56static int nfs_fsync_dir(struct file *, int); 56static int nfs_fsync_dir(struct file *, int);
57static loff_t nfs_llseek_dir(struct file *, loff_t, int); 57static loff_t nfs_llseek_dir(struct file *, loff_t, int);
58static int nfs_readdir_clear_array(struct page*, gfp_t);
58 59
59const struct file_operations nfs_dir_operations = { 60const struct file_operations nfs_dir_operations = {
60 .llseek = nfs_llseek_dir, 61 .llseek = nfs_llseek_dir,
@@ -80,6 +81,10 @@ const struct inode_operations nfs_dir_inode_operations = {
80 .setattr = nfs_setattr, 81 .setattr = nfs_setattr,
81}; 82};
82 83
84const struct address_space_operations nfs_dir_addr_space_ops = {
85 .releasepage = nfs_readdir_clear_array,
86};
87
83#ifdef CONFIG_NFS_V3 88#ifdef CONFIG_NFS_V3
84const struct inode_operations nfs3_dir_inode_operations = { 89const struct inode_operations nfs3_dir_inode_operations = {
85 .create = nfs_create, 90 .create = nfs_create,
@@ -151,51 +156,188 @@ nfs_opendir(struct inode *inode, struct file *filp)
151 return res; 156 return res;
152} 157}
153 158
159struct nfs_cache_array_entry {
160 u64 cookie;
161 u64 ino;
162 struct qstr string;
163};
164
165struct nfs_cache_array {
166 unsigned int size;
167 int eof_index;
168 u64 last_cookie;
169 struct nfs_cache_array_entry array[0];
170};
171
172#define MAX_READDIR_ARRAY ((PAGE_SIZE - sizeof(struct nfs_cache_array)) / sizeof(struct nfs_cache_array_entry))
173
154typedef __be32 * (*decode_dirent_t)(__be32 *, struct nfs_entry *, int); 174typedef __be32 * (*decode_dirent_t)(__be32 *, struct nfs_entry *, int);
155typedef struct { 175typedef struct {
156 struct file *file; 176 struct file *file;
157 struct page *page; 177 struct page *page;
158 unsigned long page_index; 178 unsigned long page_index;
159 __be32 *ptr;
160 u64 *dir_cookie; 179 u64 *dir_cookie;
161 loff_t current_index; 180 loff_t current_index;
162 struct nfs_entry *entry;
163 decode_dirent_t decode; 181 decode_dirent_t decode;
164 int plus; 182
165 unsigned long timestamp; 183 unsigned long timestamp;
166 unsigned long gencount; 184 unsigned long gencount;
167 int timestamp_valid; 185 unsigned int cache_entry_index;
186 unsigned int plus:1;
187 unsigned int eof:1;
168} nfs_readdir_descriptor_t; 188} nfs_readdir_descriptor_t;
169 189
170/* Now we cache directories properly, by stuffing the dirent 190/*
171 * data directly in the page cache. 191 * The caller is responsible for calling nfs_readdir_release_array(page)
172 *
173 * Inode invalidation due to refresh etc. takes care of
174 * _everything_, no sloppy entry flushing logic, no extraneous
175 * copying, network direct to page cache, the way it was meant
176 * to be.
177 *
178 * NOTE: Dirent information verification is done always by the
179 * page-in of the RPC reply, nowhere else, this simplies
180 * things substantially.
181 */ 192 */
182static 193static
183int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page) 194struct nfs_cache_array *nfs_readdir_get_array(struct page *page)
195{
196 if (page == NULL)
197 return ERR_PTR(-EIO);
198 return (struct nfs_cache_array *)kmap(page);
199}
200
201static
202void nfs_readdir_release_array(struct page *page)
203{
204 kunmap(page);
205}
206
207/*
208 * we are freeing strings created by nfs_add_to_readdir_array()
209 */
210static
211int nfs_readdir_clear_array(struct page *page, gfp_t mask)
212{
213 struct nfs_cache_array *array = nfs_readdir_get_array(page);
214 int i;
215 for (i = 0; i < array->size; i++)
216 kfree(array->array[i].string.name);
217 nfs_readdir_release_array(page);
218 return 0;
219}
220
221/*
222 * the caller is responsible for freeing qstr.name
223 * when called by nfs_readdir_add_to_array, the strings will be freed in
224 * nfs_clear_readdir_array()
225 */
226static
227void nfs_readdir_make_qstr(struct qstr *string, const char *name, unsigned int len)
228{
229 string->len = len;
230 string->name = kmemdup(name, len, GFP_KERNEL);
231 string->hash = full_name_hash(string->name, string->len);
232}
233
234static
235int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page)
236{
237 struct nfs_cache_array *array = nfs_readdir_get_array(page);
238 if (IS_ERR(array))
239 return PTR_ERR(array);
240 if (array->size >= MAX_READDIR_ARRAY) {
241 nfs_readdir_release_array(page);
242 return -EIO;
243 }
244
245 array->array[array->size].cookie = entry->prev_cookie;
246 array->last_cookie = entry->cookie;
247 array->array[array->size].ino = entry->ino;
248 nfs_readdir_make_qstr(&array->array[array->size].string, entry->name, entry->len);
249 if (entry->eof == 1)
250 array->eof_index = array->size;
251 array->size++;
252 nfs_readdir_release_array(page);
253 return 0;
254}
255
256static
257int nfs_readdir_search_for_pos(struct nfs_cache_array *array, nfs_readdir_descriptor_t *desc)
258{
259 loff_t diff = desc->file->f_pos - desc->current_index;
260 unsigned int index;
261
262 if (diff < 0)
263 goto out_eof;
264 if (diff >= array->size) {
265 if (array->eof_index > 0)
266 goto out_eof;
267 desc->current_index += array->size;
268 return -EAGAIN;
269 }
270
271 index = (unsigned int)diff;
272 *desc->dir_cookie = array->array[index].cookie;
273 desc->cache_entry_index = index;
274 if (index == array->eof_index)
275 desc->eof = 1;
276 return 0;
277out_eof:
278 desc->eof = 1;
279 return -EBADCOOKIE;
280}
281
282static
283int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_descriptor_t *desc)
284{
285 int i;
286 int status = -EAGAIN;
287
288 for (i = 0; i < array->size; i++) {
289 if (i == array->eof_index) {
290 desc->eof = 1;
291 status = -EBADCOOKIE;
292 }
293 if (array->array[i].cookie == *desc->dir_cookie) {
294 desc->cache_entry_index = i;
295 status = 0;
296 break;
297 }
298 }
299
300 return status;
301}
302
303static
304int nfs_readdir_search_array(nfs_readdir_descriptor_t *desc)
305{
306 struct nfs_cache_array *array;
307 int status = -EBADCOOKIE;
308
309 if (desc->dir_cookie == NULL)
310 goto out;
311
312 array = nfs_readdir_get_array(desc->page);
313 if (IS_ERR(array)) {
314 status = PTR_ERR(array);
315 goto out;
316 }
317
318 if (*desc->dir_cookie == 0)
319 status = nfs_readdir_search_for_pos(array, desc);
320 else
321 status = nfs_readdir_search_for_cookie(array, desc);
322
323 nfs_readdir_release_array(desc->page);
324out:
325 return status;
326}
327
328/* Fill a page with xdr information before transferring to the cache page */
329static
330int nfs_readdir_xdr_filler(struct page *xdr_page, nfs_readdir_descriptor_t *desc,
331 struct nfs_entry *entry, struct file *file, struct inode *inode)
184{ 332{
185 struct file *file = desc->file;
186 struct inode *inode = file->f_path.dentry->d_inode;
187 struct rpc_cred *cred = nfs_file_cred(file); 333 struct rpc_cred *cred = nfs_file_cred(file);
188 unsigned long timestamp, gencount; 334 unsigned long timestamp, gencount;
189 int error; 335 int error;
190 336
191 dfprintk(DIRCACHE, "NFS: %s: reading cookie %Lu into page %lu\n",
192 __func__, (long long)desc->entry->cookie,
193 page->index);
194
195 again: 337 again:
196 timestamp = jiffies; 338 timestamp = jiffies;
197 gencount = nfs_inc_attr_generation_counter(); 339 gencount = nfs_inc_attr_generation_counter();
198 error = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred, desc->entry->cookie, page, 340 error = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred, entry->cookie, xdr_page,
199 NFS_SERVER(inode)->dtsize, desc->plus); 341 NFS_SERVER(inode)->dtsize, desc->plus);
200 if (error < 0) { 342 if (error < 0) {
201 /* We requested READDIRPLUS, but the server doesn't grok it */ 343 /* We requested READDIRPLUS, but the server doesn't grok it */
@@ -209,190 +351,157 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
209 } 351 }
210 desc->timestamp = timestamp; 352 desc->timestamp = timestamp;
211 desc->gencount = gencount; 353 desc->gencount = gencount;
212 desc->timestamp_valid = 1; 354error:
213 SetPageUptodate(page); 355 return error;
214 /* Ensure consistent page alignment of the data.
215 * Note: assumes we have exclusive access to this mapping either
216 * through inode->i_mutex or some other mechanism.
217 */
218 if (invalidate_inode_pages2_range(inode->i_mapping, page->index + 1, -1) < 0) {
219 /* Should never happen */
220 nfs_zap_mapping(inode, inode->i_mapping);
221 }
222 unlock_page(page);
223 return 0;
224 error:
225 unlock_page(page);
226 return -EIO;
227} 356}
228 357
229static inline 358/* Fill in an entry based on the xdr code stored in desc->page */
230int dir_decode(nfs_readdir_descriptor_t *desc) 359static
360int xdr_decode(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry, __be32 **ptr)
231{ 361{
232 __be32 *p = desc->ptr; 362 __be32 *p = *ptr;
233 p = desc->decode(p, desc->entry, desc->plus); 363 p = desc->decode(p, entry, desc->plus);
234 if (IS_ERR(p)) 364 if (IS_ERR(p))
235 return PTR_ERR(p); 365 return PTR_ERR(p);
236 desc->ptr = p; 366 *ptr = p;
237 if (desc->timestamp_valid) {
238 desc->entry->fattr->time_start = desc->timestamp;
239 desc->entry->fattr->gencount = desc->gencount;
240 } else
241 desc->entry->fattr->valid &= ~NFS_ATTR_FATTR;
242 return 0;
243}
244 367
245static inline 368 entry->fattr->time_start = desc->timestamp;
246void dir_page_release(nfs_readdir_descriptor_t *desc) 369 entry->fattr->gencount = desc->gencount;
247{ 370 return 0;
248 kunmap(desc->page);
249 page_cache_release(desc->page);
250 desc->page = NULL;
251 desc->ptr = NULL;
252} 371}
253 372
254/* 373/* Perform conversion from xdr to cache array */
255 * Given a pointer to a buffer that has already been filled by a call 374static
256 * to readdir, find the next entry with cookie '*desc->dir_cookie'. 375void nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry,
257 * 376 struct page *xdr_page, struct page *page)
258 * If the end of the buffer has been reached, return -EAGAIN, if not,
259 * return the offset within the buffer of the next entry to be
260 * read.
261 */
262static inline
263int find_dirent(nfs_readdir_descriptor_t *desc)
264{ 377{
265 struct nfs_entry *entry = desc->entry; 378 __be32 *ptr = kmap(xdr_page);
266 int loop_count = 0, 379 while (xdr_decode(desc, entry, &ptr) == 0) {
267 status; 380 if (nfs_readdir_add_to_array(entry, page) == -1)
268
269 while((status = dir_decode(desc)) == 0) {
270 dfprintk(DIRCACHE, "NFS: %s: examining cookie %Lu\n",
271 __func__, (unsigned long long)entry->cookie);
272 if (entry->prev_cookie == *desc->dir_cookie)
273 break; 381 break;
274 if (loop_count++ > 200) {
275 loop_count = 0;
276 schedule();
277 }
278 } 382 }
279 return status; 383 kunmap(xdr_page);
280} 384}
281 385
282/* 386static
283 * Given a pointer to a buffer that has already been filled by a call 387int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, struct inode *inode)
284 * to readdir, find the entry at offset 'desc->file->f_pos'.
285 *
286 * If the end of the buffer has been reached, return -EAGAIN, if not,
287 * return the offset within the buffer of the next entry to be
288 * read.
289 */
290static inline
291int find_dirent_index(nfs_readdir_descriptor_t *desc)
292{ 388{
293 struct nfs_entry *entry = desc->entry; 389 struct page *xdr_page;
294 int loop_count = 0, 390 struct nfs_entry entry;
295 status; 391 struct file *file = desc->file;
296 392 struct nfs_cache_array *array;
297 for(;;) { 393 int status = 0;
298 status = dir_decode(desc); 394
299 if (status) 395 entry.prev_cookie = 0;
300 break; 396 entry.cookie = *desc->dir_cookie;
397 entry.eof = 0;
398 entry.fh = nfs_alloc_fhandle();
399 entry.fattr = nfs_alloc_fattr();
400 if (entry.fh == NULL || entry.fattr == NULL)
401 goto out;
301 402
302 dfprintk(DIRCACHE, "NFS: found cookie %Lu at index %Ld\n", 403 array = nfs_readdir_get_array(page);
303 (unsigned long long)entry->cookie, desc->current_index); 404 memset(array, 0, sizeof(struct nfs_cache_array));
405 array->eof_index = -1;
304 406
305 if (desc->file->f_pos == desc->current_index) { 407 xdr_page = alloc_page(GFP_KERNEL);
306 *desc->dir_cookie = entry->cookie; 408 if (!xdr_page)
409 goto out_release_array;
410 do {
411 status = nfs_readdir_xdr_filler(xdr_page, desc, &entry, file, inode);
412 if (status < 0)
307 break; 413 break;
308 } 414 nfs_readdir_page_filler(desc, &entry, xdr_page, page);
309 desc->current_index++; 415 } while (array->eof_index < 0 && array->size < MAX_READDIR_ARRAY);
310 if (loop_count++ > 200) { 416
311 loop_count = 0; 417 put_page(xdr_page);
312 schedule(); 418out_release_array:
313 } 419 nfs_readdir_release_array(page);
314 } 420out:
421 nfs_free_fattr(entry.fattr);
422 nfs_free_fhandle(entry.fh);
315 return status; 423 return status;
316} 424}
317 425
318/* 426/*
319 * Find the given page, and call find_dirent() or find_dirent_index in 427 * Now we cache directories properly, by converting xdr information
320 * order to try to return the next entry. 428 * to an array that can be used for lookups later. This results in
429 * fewer cache pages, since we can store more information on each page.
430 * We only need to convert from xdr once so future lookups are much simpler
321 */ 431 */
322static inline 432static
323int find_dirent_page(nfs_readdir_descriptor_t *desc) 433int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page* page)
324{ 434{
325 struct inode *inode = desc->file->f_path.dentry->d_inode; 435 struct inode *inode = desc->file->f_path.dentry->d_inode;
326 struct page *page;
327 int status;
328 436
329 dfprintk(DIRCACHE, "NFS: %s: searching page %ld for target %Lu\n", 437 if (nfs_readdir_xdr_to_array(desc, page, inode) == -1)
330 __func__, desc->page_index, 438 goto error;
331 (long long) *desc->dir_cookie); 439 SetPageUptodate(page);
332 440
333 /* If we find the page in the page_cache, we cannot be sure 441 if (invalidate_inode_pages2_range(inode->i_mapping, page->index + 1, -1) < 0) {
334 * how fresh the data is, so we will ignore readdir_plus attributes. 442 /* Should never happen */
335 */ 443 nfs_zap_mapping(inode, inode->i_mapping);
336 desc->timestamp_valid = 0;
337 page = read_cache_page(inode->i_mapping, desc->page_index,
338 (filler_t *)nfs_readdir_filler, desc);
339 if (IS_ERR(page)) {
340 status = PTR_ERR(page);
341 goto out;
342 } 444 }
445 unlock_page(page);
446 return 0;
447 error:
448 unlock_page(page);
449 return -EIO;
450}
343 451
344 /* NOTE: Someone else may have changed the READDIRPLUS flag */ 452static
345 desc->page = page; 453void cache_page_release(nfs_readdir_descriptor_t *desc)
346 desc->ptr = kmap(page); /* matching kunmap in nfs_do_filldir */ 454{
347 if (*desc->dir_cookie != 0) 455 page_cache_release(desc->page);
348 status = find_dirent(desc); 456 desc->page = NULL;
349 else 457}
350 status = find_dirent_index(desc); 458
351 if (status < 0) 459static
352 dir_page_release(desc); 460struct page *get_cache_page(nfs_readdir_descriptor_t *desc)
353 out: 461{
354 dfprintk(DIRCACHE, "NFS: %s: returns %d\n", __func__, status); 462 struct page *page;
355 return status; 463 page = read_cache_page(desc->file->f_path.dentry->d_inode->i_mapping,
464 desc->page_index, (filler_t *)nfs_readdir_filler, desc);
465 if (IS_ERR(page))
466 desc->eof = 1;
467 return page;
356} 468}
357 469
358/* 470/*
359 * Recurse through the page cache pages, and return a 471 * Returns 0 if desc->dir_cookie was found on page desc->page_index
360 * filled nfs_entry structure of the next directory entry if possible.
361 *
362 * The target for the search is '*desc->dir_cookie' if non-0,
363 * 'desc->file->f_pos' otherwise
364 */ 472 */
473static
474int find_cache_page(nfs_readdir_descriptor_t *desc)
475{
476 int res;
477
478 desc->page = get_cache_page(desc);
479 if (IS_ERR(desc->page))
480 return PTR_ERR(desc->page);
481
482 res = nfs_readdir_search_array(desc);
483 if (res == 0)
484 return 0;
485 cache_page_release(desc);
486 return res;
487}
488
489/* Search for desc->dir_cookie from the beginning of the page cache */
365static inline 490static inline
366int readdir_search_pagecache(nfs_readdir_descriptor_t *desc) 491int readdir_search_pagecache(nfs_readdir_descriptor_t *desc)
367{ 492{
368 int loop_count = 0; 493 int res = -EAGAIN;
369 int res; 494 desc->page_index = 0;
370
371 /* Always search-by-index from the beginning of the cache */
372 if (*desc->dir_cookie == 0) {
373 dfprintk(DIRCACHE, "NFS: readdir_search_pagecache() searching for offset %Ld\n",
374 (long long)desc->file->f_pos);
375 desc->page_index = 0;
376 desc->entry->cookie = desc->entry->prev_cookie = 0;
377 desc->entry->eof = 0;
378 desc->current_index = 0;
379 } else
380 dfprintk(DIRCACHE, "NFS: readdir_search_pagecache() searching for cookie %Lu\n",
381 (unsigned long long)*desc->dir_cookie);
382 495
383 for (;;) { 496 if (*desc->dir_cookie == 0)
384 res = find_dirent_page(desc); 497 desc->cache_entry_index = 0;
498
499 while (1) {
500 res = find_cache_page(desc);
385 if (res != -EAGAIN) 501 if (res != -EAGAIN)
386 break; 502 break;
387 /* Align to beginning of next page */ 503 desc->page_index++;
388 desc->page_index ++;
389 if (loop_count++ > 200) {
390 loop_count = 0;
391 schedule();
392 }
393 } 504 }
394
395 dfprintk(DIRCACHE, "NFS: %s: returns %d\n", __func__, res);
396 return res; 505 return res;
397} 506}
398 507
@@ -401,8 +510,6 @@ static inline unsigned int dt_type(struct inode *inode)
401 return (inode->i_mode >> 12) & 15; 510 return (inode->i_mode >> 12) & 15;
402} 511}
403 512
404static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc);
405
406/* 513/*
407 * Once we've found the start of the dirent within a page: fill 'er up... 514 * Once we've found the start of the dirent within a page: fill 'er up...
408 */ 515 */
@@ -411,49 +518,36 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent,
411 filldir_t filldir) 518 filldir_t filldir)
412{ 519{
413 struct file *file = desc->file; 520 struct file *file = desc->file;
414 struct nfs_entry *entry = desc->entry; 521 int i = 0;
415 struct dentry *dentry = NULL; 522 int res = 0;
416 u64 fileid; 523 struct nfs_cache_array *array = NULL;
417 int loop_count = 0, 524 unsigned int d_type = DT_UNKNOWN;
418 res; 525 struct dentry *dentry = NULL;
419
420 dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling starting @ cookie %Lu\n",
421 (unsigned long long)entry->cookie);
422
423 for(;;) {
424 unsigned d_type = DT_UNKNOWN;
425 /* Note: entry->prev_cookie contains the cookie for
426 * retrieving the current dirent on the server */
427 fileid = entry->ino;
428
429 /* Get a dentry if we have one */
430 if (dentry != NULL)
431 dput(dentry);
432 dentry = nfs_readdir_lookup(desc);
433
434 /* Use readdirplus info */
435 if (dentry != NULL && dentry->d_inode != NULL) {
436 d_type = dt_type(dentry->d_inode);
437 fileid = NFS_FILEID(dentry->d_inode);
438 }
439 526
440 res = filldir(dirent, entry->name, entry->len, 527 array = nfs_readdir_get_array(desc->page);
441 file->f_pos, nfs_compat_user_ino64(fileid), 528
442 d_type); 529 for (i = desc->cache_entry_index; i < array->size; i++) {
530 d_type = DT_UNKNOWN;
531
532 res = filldir(dirent, array->array[i].string.name,
533 array->array[i].string.len, file->f_pos,
534 nfs_compat_user_ino64(array->array[i].ino), d_type);
443 if (res < 0) 535 if (res < 0)
444 break; 536 break;
445 file->f_pos++; 537 file->f_pos++;
446 *desc->dir_cookie = entry->cookie; 538 desc->cache_entry_index = i;
447 if (dir_decode(desc) != 0) { 539 if (i < (array->size-1))
448 desc->page_index ++; 540 *desc->dir_cookie = array->array[i+1].cookie;
541 else
542 *desc->dir_cookie = array->last_cookie;
543 if (i == array->eof_index) {
544 desc->eof = 1;
449 break; 545 break;
450 } 546 }
451 if (loop_count++ > 200) {
452 loop_count = 0;
453 schedule();
454 }
455 } 547 }
456 dir_page_release(desc); 548
549 nfs_readdir_release_array(desc->page);
550 cache_page_release(desc);
457 if (dentry != NULL) 551 if (dentry != NULL)
458 dput(dentry); 552 dput(dentry);
459 dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n", 553 dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n",
@@ -477,12 +571,9 @@ static inline
477int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, 571int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
478 filldir_t filldir) 572 filldir_t filldir)
479{ 573{
480 struct file *file = desc->file;
481 struct inode *inode = file->f_path.dentry->d_inode;
482 struct rpc_cred *cred = nfs_file_cred(file);
483 struct page *page = NULL; 574 struct page *page = NULL;
484 int status; 575 int status;
485 unsigned long timestamp, gencount; 576 struct inode *inode = desc->file->f_path.dentry->d_inode;
486 577
487 dfprintk(DIRCACHE, "NFS: uncached_readdir() searching for cookie %Lu\n", 578 dfprintk(DIRCACHE, "NFS: uncached_readdir() searching for cookie %Lu\n",
488 (unsigned long long)*desc->dir_cookie); 579 (unsigned long long)*desc->dir_cookie);
@@ -492,38 +583,21 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
492 status = -ENOMEM; 583 status = -ENOMEM;
493 goto out; 584 goto out;
494 } 585 }
495 timestamp = jiffies; 586
496 gencount = nfs_inc_attr_generation_counter(); 587 if (nfs_readdir_xdr_to_array(desc, page, inode) == -1) {
497 status = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred,
498 *desc->dir_cookie, page,
499 NFS_SERVER(inode)->dtsize,
500 desc->plus);
501 desc->page = page;
502 desc->ptr = kmap(page); /* matching kunmap in nfs_do_filldir */
503 if (status >= 0) {
504 desc->timestamp = timestamp;
505 desc->gencount = gencount;
506 desc->timestamp_valid = 1;
507 if ((status = dir_decode(desc)) == 0)
508 desc->entry->prev_cookie = *desc->dir_cookie;
509 } else
510 status = -EIO; 588 status = -EIO;
511 if (status < 0)
512 goto out_release; 589 goto out_release;
590 }
513 591
592 desc->page = page;
514 status = nfs_do_filldir(desc, dirent, filldir); 593 status = nfs_do_filldir(desc, dirent, filldir);
515 594
516 /* Reset read descriptor so it searches the page cache from
517 * the start upon the next call to readdir_search_pagecache() */
518 desc->page_index = 0;
519 desc->entry->cookie = desc->entry->prev_cookie = 0;
520 desc->entry->eof = 0;
521 out: 595 out:
522 dfprintk(DIRCACHE, "NFS: %s: returns %d\n", 596 dfprintk(DIRCACHE, "NFS: %s: returns %d\n",
523 __func__, status); 597 __func__, status);
524 return status; 598 return status;
525 out_release: 599 out_release:
526 dir_page_release(desc); 600 cache_page_release(desc);
527 goto out; 601 goto out;
528} 602}
529 603
@@ -537,7 +611,6 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
537 struct inode *inode = dentry->d_inode; 611 struct inode *inode = dentry->d_inode;
538 nfs_readdir_descriptor_t my_desc, 612 nfs_readdir_descriptor_t my_desc,
539 *desc = &my_desc; 613 *desc = &my_desc;
540 struct nfs_entry my_entry;
541 int res = -ENOMEM; 614 int res = -ENOMEM;
542 615
543 dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n", 616 dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n",
@@ -558,26 +631,17 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
558 desc->decode = NFS_PROTO(inode)->decode_dirent; 631 desc->decode = NFS_PROTO(inode)->decode_dirent;
559 desc->plus = NFS_USE_READDIRPLUS(inode); 632 desc->plus = NFS_USE_READDIRPLUS(inode);
560 633
561 my_entry.cookie = my_entry.prev_cookie = 0;
562 my_entry.eof = 0;
563 my_entry.fh = nfs_alloc_fhandle();
564 my_entry.fattr = nfs_alloc_fattr();
565 if (my_entry.fh == NULL || my_entry.fattr == NULL)
566 goto out_alloc_failed;
567
568 desc->entry = &my_entry;
569
570 nfs_block_sillyrename(dentry); 634 nfs_block_sillyrename(dentry);
571 res = nfs_revalidate_mapping(inode, filp->f_mapping); 635 res = nfs_revalidate_mapping(inode, filp->f_mapping);
572 if (res < 0) 636 if (res < 0)
573 goto out; 637 goto out;
574 638
575 while(!desc->entry->eof) { 639 while (desc->eof != 1) {
576 res = readdir_search_pagecache(desc); 640 res = readdir_search_pagecache(desc);
577 641
578 if (res == -EBADCOOKIE) { 642 if (res == -EBADCOOKIE) {
579 /* This means either end of directory */ 643 /* This means either end of directory */
580 if (*desc->dir_cookie && desc->entry->cookie != *desc->dir_cookie) { 644 if (*desc->dir_cookie && desc->eof == 0) {
581 /* Or that the server has 'lost' a cookie */ 645 /* Or that the server has 'lost' a cookie */
582 res = uncached_readdir(desc, dirent, filldir); 646 res = uncached_readdir(desc, dirent, filldir);
583 if (res >= 0) 647 if (res >= 0)
@@ -590,7 +654,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
590 clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags); 654 clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags);
591 nfs_zap_caches(inode); 655 nfs_zap_caches(inode);
592 desc->plus = 0; 656 desc->plus = 0;
593 desc->entry->eof = 0; 657 desc->eof = 0;
594 continue; 658 continue;
595 } 659 }
596 if (res < 0) 660 if (res < 0)
@@ -606,9 +670,6 @@ out:
606 nfs_unblock_sillyrename(dentry); 670 nfs_unblock_sillyrename(dentry);
607 if (res > 0) 671 if (res > 0)
608 res = 0; 672 res = 0;
609out_alloc_failed:
610 nfs_free_fattr(my_entry.fattr);
611 nfs_free_fhandle(my_entry.fh);
612 dfprintk(FILE, "NFS: readdir(%s/%s) returns %d\n", 673 dfprintk(FILE, "NFS: readdir(%s/%s) returns %d\n",
613 dentry->d_parent->d_name.name, dentry->d_name.name, 674 dentry->d_parent->d_name.name, dentry->d_name.name,
614 res); 675 res);
@@ -1292,81 +1353,6 @@ out_err:
1292 1353
1293#endif /* CONFIG_NFSV4 */ 1354#endif /* CONFIG_NFSV4 */
1294 1355
1295static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc)
1296{
1297 struct dentry *parent = desc->file->f_path.dentry;
1298 struct inode *dir = parent->d_inode;
1299 struct nfs_entry *entry = desc->entry;
1300 struct dentry *dentry, *alias;
1301 struct qstr name = {
1302 .name = entry->name,
1303 .len = entry->len,
1304 };
1305 struct inode *inode;
1306 unsigned long verf = nfs_save_change_attribute(dir);
1307
1308 switch (name.len) {
1309 case 2:
1310 if (name.name[0] == '.' && name.name[1] == '.')
1311 return dget_parent(parent);
1312 break;
1313 case 1:
1314 if (name.name[0] == '.')
1315 return dget(parent);
1316 }
1317
1318 spin_lock(&dir->i_lock);
1319 if (NFS_I(dir)->cache_validity & NFS_INO_INVALID_DATA) {
1320 spin_unlock(&dir->i_lock);
1321 return NULL;
1322 }
1323 spin_unlock(&dir->i_lock);
1324
1325 name.hash = full_name_hash(name.name, name.len);
1326 dentry = d_lookup(parent, &name);
1327 if (dentry != NULL) {
1328 /* Is this a positive dentry that matches the readdir info? */
1329 if (dentry->d_inode != NULL &&
1330 (NFS_FILEID(dentry->d_inode) == entry->ino ||
1331 d_mountpoint(dentry))) {
1332 if (!desc->plus || entry->fh->size == 0)
1333 return dentry;
1334 if (nfs_compare_fh(NFS_FH(dentry->d_inode),
1335 entry->fh) == 0)
1336 goto out_renew;
1337 }
1338 /* No, so d_drop to allow one to be created */
1339 d_drop(dentry);
1340 dput(dentry);
1341 }
1342 if (!desc->plus || !(entry->fattr->valid & NFS_ATTR_FATTR))
1343 return NULL;
1344 if (name.len > NFS_SERVER(dir)->namelen)
1345 return NULL;
1346 /* Note: caller is already holding the dir->i_mutex! */
1347 dentry = d_alloc(parent, &name);
1348 if (dentry == NULL)
1349 return NULL;
1350 dentry->d_op = NFS_PROTO(dir)->dentry_ops;
1351 inode = nfs_fhget(dentry->d_sb, entry->fh, entry->fattr);
1352 if (IS_ERR(inode)) {
1353 dput(dentry);
1354 return NULL;
1355 }
1356
1357 alias = d_materialise_unique(dentry, inode);
1358 if (alias != NULL) {
1359 dput(dentry);
1360 if (IS_ERR(alias))
1361 return NULL;
1362 dentry = alias;
1363 }
1364
1365out_renew:
1366 nfs_set_verifier(dentry, verf);
1367 return dentry;
1368}
1369
1370/* 1356/*
1371 * Code common to create, mkdir, and mknod. 1357 * Code common to create, mkdir, and mknod.
1372 */ 1358 */