dir.c 52.9 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
/*
 *  linux/fs/nfs/dir.c
 *
 *  Copyright (C) 1992  Rick Sladkey
 *
 *  nfs directory handling functions
 *
 * 10 Apr 1996	Added silly rename for unlink	--okir
 * 28 Sep 1996	Improved directory cache --okir
 * 23 Aug 1997  Claus Heine claus@momo.math.rwth-aachen.de 
 *              Re-implemented silly rename for unlink, newly implemented
 *              silly rename for nfs_rename() following the suggestions
 *              of Olaf Kirch (okir) found in this file.
 *              Following Linus comments on my original hack, this version
 *              depends only on the dcache stuff and doesn't touch the inode
 *              layer (iput() and friends).
 *  6 Jun 1999	Cache readdir lookups in the page cache. -DaveM
 */

#include <linux/time.h>
#include <linux/errno.h>
#include <linux/stat.h>
#include <linux/fcntl.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/sunrpc/clnt.h>
#include <linux/nfs_fs.h>
#include <linux/nfs_mount.h>
#include <linux/pagemap.h>
32
#include <linux/pagevec.h>
Linus Torvalds's avatar
Linus Torvalds committed
33
#include <linux/namei.h>
34
#include <linux/mount.h>
Alexey Dobriyan's avatar
Alexey Dobriyan committed
35
#include <linux/sched.h>
Linus Torvalds's avatar
Linus Torvalds committed
36

37
#include "nfs4_fs.h"
Linus Torvalds's avatar
Linus Torvalds committed
38
#include "delegation.h"
39
#include "iostat.h"
40
#include "internal.h"
Linus Torvalds's avatar
Linus Torvalds committed
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55

/* #define NFS_DEBUG_VERBOSE 1 */

static int nfs_opendir(struct inode *, struct file *);
static int nfs_readdir(struct file *, void *, filldir_t);
static struct dentry *nfs_lookup(struct inode *, struct dentry *, struct nameidata *);
static int nfs_create(struct inode *, struct dentry *, int, struct nameidata *);
static int nfs_mkdir(struct inode *, struct dentry *, int);
static int nfs_rmdir(struct inode *, struct dentry *);
static int nfs_unlink(struct inode *, struct dentry *);
static int nfs_symlink(struct inode *, struct dentry *, const char *);
static int nfs_link(struct dentry *, struct inode *, struct dentry *);
static int nfs_mknod(struct inode *, struct dentry *, int, dev_t);
static int nfs_rename(struct inode *, struct dentry *,
		      struct inode *, struct dentry *);
56
static int nfs_fsync_dir(struct file *, int);
57
static loff_t nfs_llseek_dir(struct file *, loff_t, int);
Linus Torvalds's avatar
Linus Torvalds committed
58

59
const struct file_operations nfs_dir_operations = {
60
	.llseek		= nfs_llseek_dir,
Linus Torvalds's avatar
Linus Torvalds committed
61 62 63 64 65 66 67
	.read		= generic_read_dir,
	.readdir	= nfs_readdir,
	.open		= nfs_opendir,
	.release	= nfs_release,
	.fsync		= nfs_fsync_dir,
};

68
const struct inode_operations nfs_dir_inode_operations = {
Linus Torvalds's avatar
Linus Torvalds committed
69 70 71 72 73 74 75 76 77 78 79 80 81 82
	.create		= nfs_create,
	.lookup		= nfs_lookup,
	.link		= nfs_link,
	.unlink		= nfs_unlink,
	.symlink	= nfs_symlink,
	.mkdir		= nfs_mkdir,
	.rmdir		= nfs_rmdir,
	.mknod		= nfs_mknod,
	.rename		= nfs_rename,
	.permission	= nfs_permission,
	.getattr	= nfs_getattr,
	.setattr	= nfs_setattr,
};

83
#ifdef CONFIG_NFS_V3
84
const struct inode_operations nfs3_dir_inode_operations = {
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
	.create		= nfs_create,
	.lookup		= nfs_lookup,
	.link		= nfs_link,
	.unlink		= nfs_unlink,
	.symlink	= nfs_symlink,
	.mkdir		= nfs_mkdir,
	.rmdir		= nfs_rmdir,
	.mknod		= nfs_mknod,
	.rename		= nfs_rename,
	.permission	= nfs_permission,
	.getattr	= nfs_getattr,
	.setattr	= nfs_setattr,
	.listxattr	= nfs3_listxattr,
	.getxattr	= nfs3_getxattr,
	.setxattr	= nfs3_setxattr,
	.removexattr	= nfs3_removexattr,
};
#endif  /* CONFIG_NFS_V3 */

Linus Torvalds's avatar
Linus Torvalds committed
104 105 106
#ifdef CONFIG_NFS_V4

static struct dentry *nfs_atomic_lookup(struct inode *, struct dentry *, struct nameidata *);
107
const struct inode_operations nfs4_dir_inode_operations = {
Linus Torvalds's avatar
Linus Torvalds committed
108 109 110 111 112 113 114 115 116 117 118 119
	.create		= nfs_create,
	.lookup		= nfs_atomic_lookup,
	.link		= nfs_link,
	.unlink		= nfs_unlink,
	.symlink	= nfs_symlink,
	.mkdir		= nfs_mkdir,
	.rmdir		= nfs_rmdir,
	.mknod		= nfs_mknod,
	.rename		= nfs_rename,
	.permission	= nfs_permission,
	.getattr	= nfs_getattr,
	.setattr	= nfs_setattr,
120 121 122
	.getxattr       = nfs4_getxattr,
	.setxattr       = nfs4_setxattr,
	.listxattr      = nfs4_listxattr,
Linus Torvalds's avatar
Linus Torvalds committed
123 124 125 126 127 128 129 130 131 132
};

#endif /* CONFIG_NFS_V4 */

/*
 * Open file
 */
static int
nfs_opendir(struct inode *inode, struct file *filp)
{
133
	int res;
Linus Torvalds's avatar
Linus Torvalds committed
134

135
	dfprintk(FILE, "NFS: open dir(%s/%s)\n",
136 137 138 139
			filp->f_path.dentry->d_parent->d_name.name,
			filp->f_path.dentry->d_name.name);

	nfs_inc_stats(inode, NFSIOS_VFSOPEN);
Chuck Lever's avatar
Chuck Lever committed
140

Linus Torvalds's avatar
Linus Torvalds committed
141
	/* Call generic open code in order to cache credentials */
142
	res = nfs_open(inode, filp);
Linus Torvalds's avatar
Linus Torvalds committed
143 144 145
	return res;
}

146
typedef __be32 * (*decode_dirent_t)(__be32 *, struct nfs_entry *, int);
Linus Torvalds's avatar
Linus Torvalds committed
147 148 149 150
typedef struct {
	struct file	*file;
	struct page	*page;
	unsigned long	page_index;
151
	__be32		*ptr;
152 153
	u64		*dir_cookie;
	loff_t		current_index;
Linus Torvalds's avatar
Linus Torvalds committed
154 155 156
	struct nfs_entry *entry;
	decode_dirent_t	decode;
	int		plus;
157
	unsigned long	timestamp;
158
	unsigned long	gencount;
159
	int		timestamp_valid;
Linus Torvalds's avatar
Linus Torvalds committed
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
} nfs_readdir_descriptor_t;

/* Now we cache directories properly, by stuffing the dirent
 * data directly in the page cache.
 *
 * Inode invalidation due to refresh etc. takes care of
 * _everything_, no sloppy entry flushing logic, no extraneous
 * copying, network direct to page cache, the way it was meant
 * to be.
 *
 * NOTE: Dirent information verification is done always by the
 *	 page-in of the RPC reply, nowhere else, this simplies
 *	 things substantially.
 */
static
int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
{
	struct file	*file = desc->file;
178
	struct inode	*inode = file->f_path.dentry->d_inode;
Linus Torvalds's avatar
Linus Torvalds committed
179
	struct rpc_cred	*cred = nfs_file_cred(file);
180
	unsigned long	timestamp, gencount;
Linus Torvalds's avatar
Linus Torvalds committed
181 182
	int		error;

Chuck Lever's avatar
Chuck Lever committed
183
	dfprintk(DIRCACHE, "NFS: %s: reading cookie %Lu into page %lu\n",
184
			__func__, (long long)desc->entry->cookie,
Chuck Lever's avatar
Chuck Lever committed
185
			page->index);
Linus Torvalds's avatar
Linus Torvalds committed
186 187 188

 again:
	timestamp = jiffies;
189
	gencount = nfs_inc_attr_generation_counter();
190
	error = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred, desc->entry->cookie, page,
Linus Torvalds's avatar
Linus Torvalds committed
191 192 193 194 195
					  NFS_SERVER(inode)->dtsize, desc->plus);
	if (error < 0) {
		/* We requested READDIRPLUS, but the server doesn't grok it */
		if (error == -ENOTSUPP && desc->plus) {
			NFS_SERVER(inode)->caps &= ~NFS_CAP_READDIRPLUS;
Benny Halevy's avatar
Benny Halevy committed
196
			clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags);
Linus Torvalds's avatar
Linus Torvalds committed
197 198 199 200 201
			desc->plus = 0;
			goto again;
		}
		goto error;
	}
202
	desc->timestamp = timestamp;
203
	desc->gencount = gencount;
204
	desc->timestamp_valid = 1;
Linus Torvalds's avatar
Linus Torvalds committed
205 206 207
	SetPageUptodate(page);
	/* Ensure consistent page alignment of the data.
	 * Note: assumes we have exclusive access to this mapping either
208
	 *	 through inode->i_mutex or some other mechanism.
Linus Torvalds's avatar
Linus Torvalds committed
209
	 */
210
	if (invalidate_inode_pages2_range(inode->i_mapping, page->index + 1, -1) < 0) {
211 212 213
		/* Should never happen */
		nfs_zap_mapping(inode, inode->i_mapping);
	}
Linus Torvalds's avatar
Linus Torvalds committed
214 215 216 217 218 219 220 221 222 223
	unlock_page(page);
	return 0;
 error:
	unlock_page(page);
	return -EIO;
}

static inline
int dir_decode(nfs_readdir_descriptor_t *desc)
{
224
	__be32	*p = desc->ptr;
Linus Torvalds's avatar
Linus Torvalds committed
225 226 227 228
	p = desc->decode(p, desc->entry, desc->plus);
	if (IS_ERR(p))
		return PTR_ERR(p);
	desc->ptr = p;
229
	if (desc->timestamp_valid) {
230
		desc->entry->fattr->time_start = desc->timestamp;
231 232
		desc->entry->fattr->gencount = desc->gencount;
	} else
233
		desc->entry->fattr->valid &= ~NFS_ATTR_FATTR;
Linus Torvalds's avatar
Linus Torvalds committed
234 235 236 237 238 239 240 241 242 243 244 245 246 247
	return 0;
}

static inline
void dir_page_release(nfs_readdir_descriptor_t *desc)
{
	kunmap(desc->page);
	page_cache_release(desc->page);
	desc->page = NULL;
	desc->ptr = NULL;
}

/*
 * Given a pointer to a buffer that has already been filled by a call
248
 * to readdir, find the next entry with cookie '*desc->dir_cookie'.
Linus Torvalds's avatar
Linus Torvalds committed
249 250 251 252 253 254
 *
 * If the end of the buffer has been reached, return -EAGAIN, if not,
 * return the offset within the buffer of the next entry to be
 * read.
 */
static inline
255
int find_dirent(nfs_readdir_descriptor_t *desc)
Linus Torvalds's avatar
Linus Torvalds committed
256 257 258 259 260 261
{
	struct nfs_entry *entry = desc->entry;
	int		loop_count = 0,
			status;

	while((status = dir_decode(desc)) == 0) {
Chuck Lever's avatar
Chuck Lever committed
262
		dfprintk(DIRCACHE, "NFS: %s: examining cookie %Lu\n",
263
				__func__, (unsigned long long)entry->cookie);
264
		if (entry->prev_cookie == *desc->dir_cookie)
Linus Torvalds's avatar
Linus Torvalds committed
265 266 267 268 269 270 271 272 273 274
			break;
		if (loop_count++ > 200) {
			loop_count = 0;
			schedule();
		}
	}
	return status;
}

/*
275
 * Given a pointer to a buffer that has already been filled by a call
276
 * to readdir, find the entry at offset 'desc->file->f_pos'.
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
 *
 * If the end of the buffer has been reached, return -EAGAIN, if not,
 * return the offset within the buffer of the next entry to be
 * read.
 */
static inline
int find_dirent_index(nfs_readdir_descriptor_t *desc)
{
	struct nfs_entry *entry = desc->entry;
	int		loop_count = 0,
			status;

	for(;;) {
		status = dir_decode(desc);
		if (status)
			break;

Chuck Lever's avatar
Chuck Lever committed
294 295
		dfprintk(DIRCACHE, "NFS: found cookie %Lu at index %Ld\n",
				(unsigned long long)entry->cookie, desc->current_index);
296

297 298
		if (desc->file->f_pos == desc->current_index) {
			*desc->dir_cookie = entry->cookie;
299 300 301 302 303 304 305 306 307 308 309 310 311 312
			break;
		}
		desc->current_index++;
		if (loop_count++ > 200) {
			loop_count = 0;
			schedule();
		}
	}
	return status;
}

/*
 * Find the given page, and call find_dirent() or find_dirent_index in
 * order to try to return the next entry.
Linus Torvalds's avatar
Linus Torvalds committed
313 314 315 316
 */
static inline
int find_dirent_page(nfs_readdir_descriptor_t *desc)
{
317
	struct inode	*inode = desc->file->f_path.dentry->d_inode;
Linus Torvalds's avatar
Linus Torvalds committed
318 319 320
	struct page	*page;
	int		status;

Chuck Lever's avatar
Chuck Lever committed
321
	dfprintk(DIRCACHE, "NFS: %s: searching page %ld for target %Lu\n",
322
			__func__, desc->page_index,
Chuck Lever's avatar
Chuck Lever committed
323
			(long long) *desc->dir_cookie);
Linus Torvalds's avatar
Linus Torvalds committed
324

325 326 327 328
	/* If we find the page in the page_cache, we cannot be sure
	 * how fresh the data is, so we will ignore readdir_plus attributes.
	 */
	desc->timestamp_valid = 0;
Linus Torvalds's avatar
Linus Torvalds committed
329 330 331 332 333 334 335 336 337 338
	page = read_cache_page(inode->i_mapping, desc->page_index,
			       (filler_t *)nfs_readdir_filler, desc);
	if (IS_ERR(page)) {
		status = PTR_ERR(page);
		goto out;
	}

	/* NOTE: Someone else may have changed the READDIRPLUS flag */
	desc->page = page;
	desc->ptr = kmap(page);		/* matching kunmap in nfs_do_filldir */
339
	if (*desc->dir_cookie != 0)
340 341 342
		status = find_dirent(desc);
	else
		status = find_dirent_index(desc);
Linus Torvalds's avatar
Linus Torvalds committed
343 344 345
	if (status < 0)
		dir_page_release(desc);
 out:
346
	dfprintk(DIRCACHE, "NFS: %s: returns %d\n", __func__, status);
Linus Torvalds's avatar
Linus Torvalds committed
347 348 349 350 351 352 353
	return status;
}

/*
 * Recurse through the page cache pages, and return a
 * filled nfs_entry structure of the next directory entry if possible.
 *
354 355
 * The target for the search is '*desc->dir_cookie' if non-0,
 * 'desc->file->f_pos' otherwise
Linus Torvalds's avatar
Linus Torvalds committed
356 357 358 359 360 361 362
 */
static inline
int readdir_search_pagecache(nfs_readdir_descriptor_t *desc)
{
	int		loop_count = 0;
	int		res;

363
	/* Always search-by-index from the beginning of the cache */
364
	if (*desc->dir_cookie == 0) {
Chuck Lever's avatar
Chuck Lever committed
365 366
		dfprintk(DIRCACHE, "NFS: readdir_search_pagecache() searching for offset %Ld\n",
				(long long)desc->file->f_pos);
367 368 369 370
		desc->page_index = 0;
		desc->entry->cookie = desc->entry->prev_cookie = 0;
		desc->entry->eof = 0;
		desc->current_index = 0;
371
	} else
Chuck Lever's avatar
Chuck Lever committed
372 373
		dfprintk(DIRCACHE, "NFS: readdir_search_pagecache() searching for cookie %Lu\n",
				(unsigned long long)*desc->dir_cookie);
374

Linus Torvalds's avatar
Linus Torvalds committed
375 376 377 378 379 380 381 382 383 384 385
	for (;;) {
		res = find_dirent_page(desc);
		if (res != -EAGAIN)
			break;
		/* Align to beginning of next page */
		desc->page_index ++;
		if (loop_count++ > 200) {
			loop_count = 0;
			schedule();
		}
	}
Chuck Lever's avatar
Chuck Lever committed
386

387
	dfprintk(DIRCACHE, "NFS: %s: returns %d\n", __func__, res);
Linus Torvalds's avatar
Linus Torvalds committed
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407
	return res;
}

static inline unsigned int dt_type(struct inode *inode)
{
	return (inode->i_mode >> 12) & 15;
}

static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc);

/*
 * Once we've found the start of the dirent within a page: fill 'er up...
 */
static 
int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent,
		   filldir_t filldir)
{
	struct file	*file = desc->file;
	struct nfs_entry *entry = desc->entry;
	struct dentry	*dentry = NULL;
408
	u64		fileid;
Linus Torvalds's avatar
Linus Torvalds committed
409 410 411
	int		loop_count = 0,
			res;

Chuck Lever's avatar
Chuck Lever committed
412 413
	dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling starting @ cookie %Lu\n",
			(unsigned long long)entry->cookie);
Linus Torvalds's avatar
Linus Torvalds committed
414 415 416 417 418

	for(;;) {
		unsigned d_type = DT_UNKNOWN;
		/* Note: entry->prev_cookie contains the cookie for
		 *	 retrieving the current dirent on the server */
419
		fileid = entry->ino;
Linus Torvalds's avatar
Linus Torvalds committed
420 421 422 423 424 425 426 427 428

		/* Get a dentry if we have one */
		if (dentry != NULL)
			dput(dentry);
		dentry = nfs_readdir_lookup(desc);

		/* Use readdirplus info */
		if (dentry != NULL && dentry->d_inode != NULL) {
			d_type = dt_type(dentry->d_inode);
429
			fileid = NFS_FILEID(dentry->d_inode);
Linus Torvalds's avatar
Linus Torvalds committed
430 431 432
		}

		res = filldir(dirent, entry->name, entry->len, 
433 434
			      file->f_pos, nfs_compat_user_ino64(fileid),
			      d_type);
Linus Torvalds's avatar
Linus Torvalds committed
435 436
		if (res < 0)
			break;
437
		file->f_pos++;
438
		*desc->dir_cookie = entry->cookie;
Linus Torvalds's avatar
Linus Torvalds committed
439 440 441 442 443 444 445 446 447 448 449 450
		if (dir_decode(desc) != 0) {
			desc->page_index ++;
			break;
		}
		if (loop_count++ > 200) {
			loop_count = 0;
			schedule();
		}
	}
	dir_page_release(desc);
	if (dentry != NULL)
		dput(dentry);
Chuck Lever's avatar
Chuck Lever committed
451 452
	dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n",
			(unsigned long long)*desc->dir_cookie, res);
Linus Torvalds's avatar
Linus Torvalds committed
453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472
	return res;
}

/*
 * If we cannot find a cookie in our cache, we suspect that this is
 * because it points to a deleted file, so we ask the server to return
 * whatever it thinks is the next entry. We then feed this to filldir.
 * If all goes well, we should then be able to find our way round the
 * cache on the next call to readdir_search_pagecache();
 *
 * NOTE: we cannot add the anonymous page to the pagecache because
 *	 the data it contains might not be page aligned. Besides,
 *	 we should already have a complete representation of the
 *	 directory in the page cache by the time we get here.
 */
static inline
int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
		     filldir_t filldir)
{
	struct file	*file = desc->file;
473
	struct inode	*inode = file->f_path.dentry->d_inode;
Linus Torvalds's avatar
Linus Torvalds committed
474 475 476
	struct rpc_cred	*cred = nfs_file_cred(file);
	struct page	*page = NULL;
	int		status;
477
	unsigned long	timestamp, gencount;
Linus Torvalds's avatar
Linus Torvalds committed
478

Chuck Lever's avatar
Chuck Lever committed
479 480
	dfprintk(DIRCACHE, "NFS: uncached_readdir() searching for cookie %Lu\n",
			(unsigned long long)*desc->dir_cookie);
Linus Torvalds's avatar
Linus Torvalds committed
481 482 483 484 485 486

	page = alloc_page(GFP_HIGHUSER);
	if (!page) {
		status = -ENOMEM;
		goto out;
	}
487
	timestamp = jiffies;
488
	gencount = nfs_inc_attr_generation_counter();
489 490
	status = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred,
						*desc->dir_cookie, page,
Linus Torvalds's avatar
Linus Torvalds committed
491 492 493 494
						NFS_SERVER(inode)->dtsize,
						desc->plus);
	desc->page = page;
	desc->ptr = kmap(page);		/* matching kunmap in nfs_do_filldir */
495
	if (status >= 0) {
496
		desc->timestamp = timestamp;
497
		desc->gencount = gencount;
498
		desc->timestamp_valid = 1;
Linus Torvalds's avatar
Linus Torvalds committed
499
		if ((status = dir_decode(desc)) == 0)
500
			desc->entry->prev_cookie = *desc->dir_cookie;
Linus Torvalds's avatar
Linus Torvalds committed
501 502 503 504 505 506 507 508 509 510 511 512 513
	} else
		status = -EIO;
	if (status < 0)
		goto out_release;

	status = nfs_do_filldir(desc, dirent, filldir);

	/* Reset read descriptor so it searches the page cache from
	 * the start upon the next call to readdir_search_pagecache() */
	desc->page_index = 0;
	desc->entry->cookie = desc->entry->prev_cookie = 0;
	desc->entry->eof = 0;
 out:
Chuck Lever's avatar
Chuck Lever committed
514
	dfprintk(DIRCACHE, "NFS: %s: returns %d\n",
515
			__func__, status);
Linus Torvalds's avatar
Linus Torvalds committed
516 517 518 519 520 521
	return status;
 out_release:
	dir_page_release(desc);
	goto out;
}

522 523 524
/* The file offset position represents the dirent entry number.  A
   last cookie cache takes care of the common case of reading the
   whole directory.
Linus Torvalds's avatar
Linus Torvalds committed
525 526 527
 */
static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
528
	struct dentry	*dentry = filp->f_path.dentry;
Linus Torvalds's avatar
Linus Torvalds committed
529 530 531 532
	struct inode	*inode = dentry->d_inode;
	nfs_readdir_descriptor_t my_desc,
			*desc = &my_desc;
	struct nfs_entry my_entry;
533
	int res = -ENOMEM;
Linus Torvalds's avatar
Linus Torvalds committed
534

535
	dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n",
Chuck Lever's avatar
Chuck Lever committed
536 537
			dentry->d_parent->d_name.name, dentry->d_name.name,
			(long long)filp->f_pos);
538 539
	nfs_inc_stats(inode, NFSIOS_VFSGETDENTS);

Linus Torvalds's avatar
Linus Torvalds committed
540
	/*
541
	 * filp->f_pos points to the dirent entry number.
542
	 * *desc->dir_cookie has the cookie for the next entry. We have
543 544
	 * to either find the entry with the appropriate number or
	 * revalidate the cookie.
Linus Torvalds's avatar
Linus Torvalds committed
545 546 547 548
	 */
	memset(desc, 0, sizeof(*desc));

	desc->file = filp;
549
	desc->dir_cookie = &nfs_file_open_context(filp)->dir_cookie;
Linus Torvalds's avatar
Linus Torvalds committed
550 551 552 553 554
	desc->decode = NFS_PROTO(inode)->decode_dirent;
	desc->plus = NFS_USE_READDIRPLUS(inode);

	my_entry.cookie = my_entry.prev_cookie = 0;
	my_entry.eof = 0;
555 556 557 558 559
	my_entry.fh = nfs_alloc_fhandle();
	my_entry.fattr = nfs_alloc_fattr();
	if (my_entry.fh == NULL || my_entry.fattr == NULL)
		goto out_alloc_failed;

Linus Torvalds's avatar
Linus Torvalds committed
560 561
	desc->entry = &my_entry;

562
	nfs_block_sillyrename(dentry);
563
	res = nfs_revalidate_mapping(inode, filp->f_mapping);
564 565 566
	if (res < 0)
		goto out;

Linus Torvalds's avatar
Linus Torvalds committed
567 568
	while(!desc->entry->eof) {
		res = readdir_search_pagecache(desc);
569

Linus Torvalds's avatar
Linus Torvalds committed
570 571
		if (res == -EBADCOOKIE) {
			/* This means either end of directory */
572
			if (*desc->dir_cookie && desc->entry->cookie != *desc->dir_cookie) {
Linus Torvalds's avatar
Linus Torvalds committed
573 574 575 576 577 578 579 580 581
				/* Or that the server has 'lost' a cookie */
				res = uncached_readdir(desc, dirent, filldir);
				if (res >= 0)
					continue;
			}
			res = 0;
			break;
		}
		if (res == -ETOOSMALL && desc->plus) {
Benny Halevy's avatar
Benny Halevy committed
582
			clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags);
Linus Torvalds's avatar
Linus Torvalds committed
583 584 585 586 587 588 589 590 591 592 593 594 595 596
			nfs_zap_caches(inode);
			desc->plus = 0;
			desc->entry->eof = 0;
			continue;
		}
		if (res < 0)
			break;

		res = nfs_do_filldir(desc, dirent, filldir);
		if (res < 0) {
			res = 0;
			break;
		}
	}
597
out:
598
	nfs_unblock_sillyrename(dentry);
Chuck Lever's avatar
Chuck Lever committed
599 600
	if (res > 0)
		res = 0;
601 602 603 604
out_alloc_failed:
	nfs_free_fattr(my_entry.fattr);
	nfs_free_fhandle(my_entry.fh);
	dfprintk(FILE, "NFS: readdir(%s/%s) returns %d\n",
Chuck Lever's avatar
Chuck Lever committed
605 606 607
			dentry->d_parent->d_name.name, dentry->d_name.name,
			res);
	return res;
Linus Torvalds's avatar
Linus Torvalds committed
608 609
}

610
static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin)
611
{
612 613 614
	struct dentry *dentry = filp->f_path.dentry;
	struct inode *inode = dentry->d_inode;

615
	dfprintk(FILE, "NFS: llseek dir(%s/%s, %lld, %d)\n",
616 617 618 619 620
			dentry->d_parent->d_name.name,
			dentry->d_name.name,
			offset, origin);

	mutex_lock(&inode->i_mutex);
621 622 623 624 625 626 627 628 629 630 631 632
	switch (origin) {
		case 1:
			offset += filp->f_pos;
		case 0:
			if (offset >= 0)
				break;
		default:
			offset = -EINVAL;
			goto out;
	}
	if (offset != filp->f_pos) {
		filp->f_pos = offset;
633
		nfs_file_open_context(filp)->dir_cookie = 0;
634 635
	}
out:
636
	mutex_unlock(&inode->i_mutex);
637 638 639
	return offset;
}

Linus Torvalds's avatar
Linus Torvalds committed
640 641 642 643
/*
 * All directory operations under NFS are synchronous, so fsync()
 * is a dummy operation.
 */
644
static int nfs_fsync_dir(struct file *filp, int datasync)
Linus Torvalds's avatar
Linus Torvalds committed
645
{
646 647
	struct dentry *dentry = filp->f_path.dentry;

648
	dfprintk(FILE, "NFS: fsync dir(%s/%s) datasync %d\n",
Chuck Lever's avatar
Chuck Lever committed
649 650 651
			dentry->d_parent->d_name.name, dentry->d_name.name,
			datasync);

652
	nfs_inc_stats(dentry->d_inode, NFSIOS_VFSFSYNC);
Linus Torvalds's avatar
Linus Torvalds committed
653 654 655
	return 0;
}

656 657 658 659 660 661 662 663 664 665 666 667
/**
 * nfs_force_lookup_revalidate - Mark the directory as having changed
 * @dir - pointer to directory inode
 *
 * This forces the revalidation code in nfs_lookup_revalidate() to do a
 * full lookup on all child dentries of 'dir' whenever a change occurs
 * on the server that might have invalidated our dcache.
 *
 * The caller should be holding dir->i_lock
 */
void nfs_force_lookup_revalidate(struct inode *dir)
{
668
	NFS_I(dir)->cache_change_attribute++;
669 670
}

Linus Torvalds's avatar
Linus Torvalds committed
671 672 673 674 675
/*
 * A check for whether or not the parent directory has changed.
 * In the case it has, we assume that the dentries are untrustworthy
 * and may need to be looked up again.
 */
676
static int nfs_check_verifier(struct inode *dir, struct dentry *dentry)
Linus Torvalds's avatar
Linus Torvalds committed
677 678 679
{
	if (IS_ROOT(dentry))
		return 1;
680 681
	if (NFS_SERVER(dir)->flags & NFS_MOUNT_LOOKUP_CACHE_NONE)
		return 0;
682 683 684 685 686 687 688 689
	if (!nfs_verify_change_attribute(dir, dentry->d_time))
		return 0;
	/* Revalidate nfsi->cache_change_attribute before we declare a match */
	if (nfs_revalidate_inode(NFS_SERVER(dir), dir) < 0)
		return 0;
	if (!nfs_verify_change_attribute(dir, dentry->d_time))
		return 0;
	return 1;
Linus Torvalds's avatar
Linus Torvalds committed
690 691
}

692 693 694 695 696 697 698 699 700 701 702 703 704 705
/*
 * Return the intent data that applies to this particular path component
 *
 * Note that the current set of intents only apply to the very last
 * component of the path.
 * We check for this using LOOKUP_CONTINUE and LOOKUP_PARENT.
 */
static inline unsigned int nfs_lookup_check_intent(struct nameidata *nd, unsigned int mask)
{
	if (nd->flags & (LOOKUP_CONTINUE|LOOKUP_PARENT))
		return 0;
	return nd->flags & mask;
}

706 707 708 709 710 711 712 713
/*
 * Use intent information to check whether or not we're going to do
 * an O_EXCL create using this path component.
 */
static int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd)
{
	if (NFS_PROTO(dir)->version == 2)
		return 0;
714
	return nd && nfs_lookup_check_intent(nd, LOOKUP_EXCL);
715 716
}

717 718 719 720 721 722 723 724
/*
 * Inode and filehandle revalidation for lookups.
 *
 * We force revalidation in the cases where the VFS sets LOOKUP_REVAL,
 * or if the intent information indicates that we're about to open this
 * particular file and the "nocto" mount flag is not set.
 *
 */
Linus Torvalds's avatar
Linus Torvalds committed
725 726 727 728 729
static inline
int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd)
{
	struct nfs_server *server = NFS_SERVER(inode);

730 731
	if (test_bit(NFS_INO_MOUNTPOINT, &NFS_I(inode)->flags))
		return 0;
Linus Torvalds's avatar
Linus Torvalds committed
732 733
	if (nd != NULL) {
		/* VFS wants an on-the-wire revalidation */
734
		if (nd->flags & LOOKUP_REVAL)
Linus Torvalds's avatar
Linus Torvalds committed
735 736
			goto out_force;
		/* This is an open(2) */
737
		if (nfs_lookup_check_intent(nd, LOOKUP_OPEN) != 0 &&
738 739 740
				!(server->flags & NFS_MOUNT_NOCTO) &&
				(S_ISREG(inode->i_mode) ||
				 S_ISDIR(inode->i_mode)))
Linus Torvalds's avatar
Linus Torvalds committed
741
			goto out_force;
742
		return 0;
Linus Torvalds's avatar
Linus Torvalds committed
743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760
	}
	return nfs_revalidate_inode(server, inode);
out_force:
	return __nfs_revalidate_inode(server, inode);
}

/*
 * We judge how long we want to trust negative
 * dentries by looking at the parent inode mtime.
 *
 * If parent mtime has changed, we revalidate, else we wait for a
 * period corresponding to the parent's attribute cache timeout value.
 */
static inline
int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry,
		       struct nameidata *nd)
{
	/* Don't revalidate a negative dentry if we're creating a new file */
761
	if (nd != NULL && nfs_lookup_check_intent(nd, LOOKUP_CREATE) != 0)
Linus Torvalds's avatar
Linus Torvalds committed
762
		return 0;
763 764
	if (NFS_SERVER(dir)->flags & NFS_MOUNT_LOOKUP_CACHE_NONEG)
		return 1;
Linus Torvalds's avatar
Linus Torvalds committed
765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783
	return !nfs_check_verifier(dir, dentry);
}

/*
 * This is called every time the dcache has a lookup hit,
 * and we should check whether we can really trust that
 * lookup.
 *
 * NOTE! The hit can be a negative hit too, don't assume
 * we have an inode!
 *
 * If the parent directory is seen to have changed, we throw out the
 * cached dentry and do a new lookup.
 */
static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
{
	struct inode *dir;
	struct inode *inode;
	struct dentry *parent;
784 785
	struct nfs_fh *fhandle = NULL;
	struct nfs_fattr *fattr = NULL;
Linus Torvalds's avatar
Linus Torvalds committed
786 787 788 789
	int error;

	parent = dget_parent(dentry);
	dir = parent->d_inode;
790
	nfs_inc_stats(dir, NFSIOS_DENTRYREVALIDATE);
Linus Torvalds's avatar
Linus Torvalds committed
791 792 793 794 795 796 797 798 799
	inode = dentry->d_inode;

	if (!inode) {
		if (nfs_neg_need_reval(dir, dentry, nd))
			goto out_bad;
		goto out_valid;
	}

	if (is_bad_inode(inode)) {
Chuck Lever's avatar
Chuck Lever committed
800
		dfprintk(LOOKUPCACHE, "%s: %s/%s has dud inode\n",
801
				__func__, dentry->d_parent->d_name.name,
Chuck Lever's avatar
Chuck Lever committed
802
				dentry->d_name.name);
Linus Torvalds's avatar
Linus Torvalds committed
803 804 805
		goto out_bad;
	}

806 807 808
	if (nfs_have_delegation(inode, FMODE_READ))
		goto out_set_verifier;

Linus Torvalds's avatar
Linus Torvalds committed
809
	/* Force a full look up iff the parent directory has changed */
810
	if (!nfs_is_exclusive_create(dir, nd) && nfs_check_verifier(dir, dentry)) {
Linus Torvalds's avatar
Linus Torvalds committed
811 812 813 814 815 816 817 818
		if (nfs_lookup_verify_inode(inode, nd))
			goto out_zap_parent;
		goto out_valid;
	}

	if (NFS_STALE(inode))
		goto out_bad;

819 820 821 822 823 824 825
	error = -ENOMEM;
	fhandle = nfs_alloc_fhandle();
	fattr = nfs_alloc_fattr();
	if (fhandle == NULL || fattr == NULL)
		goto out_error;

	error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr);
Linus Torvalds's avatar
Linus Torvalds committed
826 827
	if (error)
		goto out_bad;
828
	if (nfs_compare_fh(NFS_FH(inode), fhandle))
Linus Torvalds's avatar
Linus Torvalds committed
829
		goto out_bad;
830
	if ((error = nfs_refresh_inode(inode, fattr)) != 0)
Linus Torvalds's avatar
Linus Torvalds committed
831 832
		goto out_bad;

833 834
	nfs_free_fattr(fattr);
	nfs_free_fhandle(fhandle);
835
out_set_verifier:
836
	nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
Linus Torvalds's avatar
Linus Torvalds committed
837 838
 out_valid:
	dput(parent);
Chuck Lever's avatar
Chuck Lever committed
839
	dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) is valid\n",
840
			__func__, dentry->d_parent->d_name.name,
Chuck Lever's avatar
Chuck Lever committed
841
			dentry->d_name.name);
Linus Torvalds's avatar
Linus Torvalds committed
842 843 844 845
	return 1;
out_zap_parent:
	nfs_zap_caches(dir);
 out_bad:
846
	nfs_mark_for_revalidate(dir);
Linus Torvalds's avatar
Linus Torvalds committed
847 848 849 850 851 852
	if (inode && S_ISDIR(inode->i_mode)) {
		/* Purge readdir caches. */
		nfs_zap_caches(inode);
		/* If we have submounts, don't unhash ! */
		if (have_submounts(dentry))
			goto out_valid;
853 854
		if (dentry->d_flags & DCACHE_DISCONNECTED)
			goto out_valid;
Linus Torvalds's avatar
Linus Torvalds committed
855 856 857
		shrink_dcache_parent(dentry);
	}
	d_drop(dentry);
858 859
	nfs_free_fattr(fattr);
	nfs_free_fhandle(fhandle);
Linus Torvalds's avatar
Linus Torvalds committed
860
	dput(parent);
Chuck Lever's avatar
Chuck Lever committed
861
	dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) is invalid\n",
862
			__func__, dentry->d_parent->d_name.name,
Chuck Lever's avatar
Chuck Lever committed
863
			dentry->d_name.name);
Linus Torvalds's avatar
Linus Torvalds committed
864
	return 0;
865 866 867 868 869 870 871 872
out_error:
	nfs_free_fattr(fattr);
	nfs_free_fhandle(fhandle);
	dput(parent);
	dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) lookup returned error %d\n",
			__func__, dentry->d_parent->d_name.name,
			dentry->d_name.name, error);
	return error;
Linus Torvalds's avatar
Linus Torvalds committed
873 874 875 876 877 878 879 880 881 882 883
}

/*
 * This is called from dput() when d_count is going to 0.
 */
static int nfs_dentry_delete(struct dentry *dentry)
{
	dfprintk(VFS, "NFS: dentry_delete(%s/%s, %x)\n",
		dentry->d_parent->d_name.name, dentry->d_name.name,
		dentry->d_flags);

884 885 886 887
	/* Unhash any dentry with a stale inode */
	if (dentry->d_inode != NULL && NFS_STALE(dentry->d_inode))
		return 1;

Linus Torvalds's avatar
Linus Torvalds committed
888 889 890 891 892 893 894 895 896 897 898 899 900
	if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
		/* Unhash it, so that ->d_iput() would be called */
		return 1;
	}
	if (!(dentry->d_sb->s_flags & MS_ACTIVE)) {
		/* Unhash it, so that ancestors of killed async unlink
		 * files will be cleaned up during umount */
		return 1;
	}
	return 0;

}

901 902 903 904 905 906 907 908
static void nfs_drop_nlink(struct inode *inode)
{
	spin_lock(&inode->i_lock);
	if (inode->i_nlink > 0)
		drop_nlink(inode);
	spin_unlock(&inode->i_lock);
}

Linus Torvalds's avatar
Linus Torvalds committed
909 910 911 912 913 914
/*
 * Called when the dentry loses inode.
 * We use it to clean up silly-renamed files.
 */
static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode)
{
915 916 917 918
	if (S_ISDIR(inode->i_mode))
		/* drop any readdir cache as it could easily be old */
		NFS_I(inode)->cache_validity |= NFS_INO_INVALID_DATA;

Linus Torvalds's avatar
Linus Torvalds committed
919
	if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
920
		drop_nlink(inode);
921
		nfs_complete_unlink(dentry, inode);
Linus Torvalds's avatar
Linus Torvalds committed
922 923 924 925
	}
	iput(inode);
}

Al Viro's avatar
Al Viro committed
926
const struct dentry_operations nfs_dentry_operations = {
Linus Torvalds's avatar
Linus Torvalds committed
927 928 929 930 931 932 933 934
	.d_revalidate	= nfs_lookup_revalidate,
	.d_delete	= nfs_dentry_delete,
	.d_iput		= nfs_dentry_iput,
};

static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
{
	struct dentry *res;
935
	struct dentry *parent;
Linus Torvalds's avatar
Linus Torvalds committed
936
	struct inode *inode = NULL;
937 938
	struct nfs_fh *fhandle = NULL;
	struct nfs_fattr *fattr = NULL;
Linus Torvalds's avatar
Linus Torvalds committed
939 940 941 942
	int error;

	dfprintk(VFS, "NFS: lookup(%s/%s)\n",
		dentry->d_parent->d_name.name, dentry->d_name.name);
943
	nfs_inc_stats(dir, NFSIOS_VFSLOOKUP);
Linus Torvalds's avatar
Linus Torvalds committed
944 945 946 947 948 949 950

	res = ERR_PTR(-ENAMETOOLONG);
	if (dentry->d_name.len > NFS_SERVER(dir)->namelen)
		goto out;

	dentry->d_op = NFS_PROTO(dir)->dentry_ops;

951 952 953 954 955 956 957
	/*
	 * If we're doing an exclusive create, optimize away the lookup
	 * but don't hash the dentry.
	 */
	if (nfs_is_exclusive_create(dir, nd)) {
		d_instantiate(dentry, NULL);
		res = NULL;
958
		goto out;
959
	}
Linus Torvalds's avatar
Linus Torvalds committed
960

961 962 963 964 965 966
	res = ERR_PTR(-ENOMEM);
	fhandle = nfs_alloc_fhandle();
	fattr = nfs_alloc_fattr();
	if (fhandle == NULL || fattr == NULL)
		goto out;

967 968 969
	parent = dentry->d_parent;
	/* Protect against concurrent sillydeletes */
	nfs_block_sillyrename(parent);
970
	error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr);
Linus Torvalds's avatar
Linus Torvalds committed
971 972 973 974
	if (error == -ENOENT)
		goto no_entry;
	if (error < 0) {
		res = ERR_PTR(error);
975
		goto out_unblock_sillyrename;
Linus Torvalds's avatar
Linus Torvalds committed
976
	}
977
	inode = nfs_fhget(dentry->d_sb, fhandle, fattr);
978 979
	res = (struct dentry *)inode;
	if (IS_ERR(res))
980
		goto out_unblock_sillyrename;
981

Linus Torvalds's avatar
Linus Torvalds committed
982
no_entry:
983
	res = d_materialise_unique(dentry, inode);
984 985
	if (res != NULL) {
		if (IS_ERR(res))
986
			goto out_unblock_sillyrename;
Linus Torvalds's avatar
Linus Torvalds committed
987
		dentry = res;
988
	}
Linus Torvalds's avatar
Linus Torvalds committed
989
	nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
990 991
out_unblock_sillyrename:
	nfs_unblock_sillyrename(parent);
Linus Torvalds's avatar
Linus Torvalds committed
992
out:
993 994
	nfs_free_fattr(fattr);
	nfs_free_fhandle(fhandle);
Linus Torvalds's avatar
Linus Torvalds committed
995 996 997 998 999 1000
	return res;
}

#ifdef CONFIG_NFS_V4
static int nfs_open_revalidate(struct dentry *, struct nameidata *);

Al Viro's avatar
Al Viro committed
1001
const struct dentry_operations nfs4_dentry_operations = {
Linus Torvalds's avatar
Linus Torvalds committed
1002 1003 1004 1005 1006
	.d_revalidate	= nfs_open_revalidate,
	.d_delete	= nfs_dentry_delete,
	.d_iput		= nfs_dentry_iput,
};

1007 1008 1009 1010
/*
 * Use intent information to determine whether we need to substitute
 * the NFSv4-style stateful OPEN for the LOOKUP call
 */
1011
static int is_atomic_open(struct nameidata *nd)
Linus Torvalds's avatar
Linus Torvalds committed
1012
{
1013
	if (nd == NULL || nfs_lookup_check_intent(nd, LOOKUP_OPEN) == 0)
Linus Torvalds's avatar
Linus Torvalds committed
1014 1015 1016 1017 1018
		return 0;
	/* NFS does not (yet) have a stateful open for directories */
	if (nd->flags & LOOKUP_DIRECTORY)
		return 0;
	/* Are we trying to write to a read only partition? */
1019 1020
	if (__mnt_is_readonly(nd->path.mnt) &&
	    (nd->intent.open.flags & (O_CREAT|O_TRUNC|FMODE_WRITE)))
Linus Torvalds's avatar
Linus Torvalds committed
1021 1022 1023 1024 1025 1026 1027 1028 1029
		return 0;
	return 1;
}

static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
	struct dentry *res = NULL;
	int error;

Chuck Lever's avatar
Chuck Lever committed
1030 1031 1032
	dfprintk(VFS, "NFS: atomic_lookup(%s/%ld), %s\n",
			dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);

Linus Torvalds's avatar
Linus Torvalds committed
1033
	/* Check that we are indeed trying to open this file */
1034
	if (!is_atomic_open(nd))
Linus Torvalds's avatar
Linus Torvalds committed
1035 1036 1037 1038 1039 1040 1041 1042
		goto no_open;

	if (dentry->d_name.len > NFS_SERVER(dir)->namelen) {
		res = ERR_PTR(-ENAMETOOLONG);
		goto out;
	}
	dentry->d_op = NFS_PROTO(dir)->dentry_ops;

1043 1044
	/* Let vfs_create() deal with O_EXCL. Instantiate, but don't hash
	 * the dentry. */
1045
	if (nd->flags & LOOKUP_EXCL) {
1046
		d_instantiate(dentry, NULL);
1047 1048
		goto out;
	}
Linus Torvalds's avatar
Linus Torvalds committed
1049 1050

	/* Open the file on the server */
1051
	res = nfs4_atomic_open(dir, dentry, nd);
1052 1053
	if (IS_ERR(res)) {
		error = PTR_ERR(res);
Linus Torvalds's avatar
Linus Torvalds committed
1054 1055 1056
		switch (error) {
			/* Make a negative dentry */
			case -ENOENT:
1057 1058
				res = NULL;
				goto out;
Linus Torvalds's avatar
Linus Torvalds committed
1059
			/* This turned out not to be a regular file */
1060
			case -EISDIR:
1061 1062
			case -ENOTDIR:
				goto no_open;
Linus Torvalds's avatar
Linus Torvalds committed
1063 1064 1065 1066 1067 1068 1069
			case -ELOOP:
				if (!(nd->intent.open.flags & O_NOFOLLOW))
					goto no_open;
			/* case -EINVAL: */
			default:
				goto out;
		}
1070
	} else if (res != NULL)
Linus Torvalds's avatar
Linus Torvalds committed
1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084
		dentry = res;
out:
	return res;
no_open:
	return nfs_lookup(dir, dentry, nd);
}

static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
{
	struct dentry *parent = NULL;
	struct inode *inode = dentry->d_inode;
	struct inode *dir;
	int openflags, ret = 0;

1085
	if (!is_atomic_open(nd) || d_mountpoint(dentry))
1086
		goto no_open;
Linus Torvalds's avatar
Linus Torvalds committed
1087 1088 1089 1090 1091
	parent = dget_parent(dentry);
	dir = parent->d_inode;
	/* We can't create new files in nfs_open_revalidate(), so we
	 * optimize away revalidation of negative dentries.
	 */
1092 1093 1094
	if (inode == NULL) {
		if (!nfs_neg_need_reval(dir, dentry, nd))
			ret = 1;
Linus Torvalds's avatar
Linus Torvalds committed
1095
		goto out;
1096 1097
	}

Linus Torvalds's avatar
Linus Torvalds committed
1098 1099
	/* NFS only supports OPEN on regular files */
	if (!S_ISREG(inode->i_mode))
1100
		goto no_open_dput;
Linus Torvalds's avatar
Linus Torvalds committed
1101 1102 1103
	openflags = nd->intent.open.flags;
	/* We cannot do exclusive creation on a positive dentry */
	if ((openflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL))
1104
		goto no_open_dput;
Linus Torvalds's avatar
Linus Torvalds committed
1105 1106 1107 1108
	/* We can't create new files, or truncate existing ones here */
	openflags &= ~(O_CREAT|O_TRUNC);

	/*
1109
	 * Note: we're not holding inode->i_mutex and so may be racing with
Linus Torvalds's avatar
Linus Torvalds committed
1110 1111 1112
	 * operations that change the directory. We therefore save the
	 * change attribute *before* we do the RPC call.
	 */
1113
	ret = nfs4_open_revalidate(dir, dentry, openflags, nd);
Linus Torvalds's avatar
Linus Torvalds committed
1114 1115 1116 1117 1118
out:
	dput(parent);
	if (!ret)
		d_drop(dentry);
	return ret;
1119
no_open_dput:
Linus Torvalds's avatar
Linus Torvalds committed
1120
	dput(parent);
1121
no_open:
Linus Torvalds's avatar
Linus Torvalds committed
1122 1123 1124 1125 1126 1127
	return nfs_lookup_revalidate(dentry, nd);
}
#endif /* CONFIG_NFSV4 */

static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc)
{
1128
	struct dentry *parent = desc->file->f_path.dentry;
Linus Torvalds's avatar
Linus Torvalds committed
1129 1130 1131 1132 1133 1134 1135 1136
	struct inode *dir = parent->d_inode;
	struct nfs_entry *entry = desc->entry;
	struct dentry *dentry, *alias;
	struct qstr name = {
		.name = entry->name,
		.len = entry->len,
	};
	struct inode *inode;
1137
	unsigned long verf = nfs_save_change_attribute(dir);
Linus Torvalds's avatar
Linus Torvalds committed
1138 1139 1140 1141 1142 1143 1144 1145 1146 1147

	switch (name.len) {
		case 2:
			if (name.name[0] == '.' && name.name[1] == '.')
				return dget_parent(parent);
			break;
		case 1:
			if (name.name[0] == '.')
				return dget(parent);
	}
1148 1149 1150 1151 1152 1153 1154 1155

	spin_lock(&dir->i_lock);
	if (NFS_I(dir)->cache_validity & NFS_INO_INVALID_DATA) {
		spin_unlock(&dir->i_lock);
		return NULL;
	}
	spin_unlock(&dir->i_lock);

Linus Torvalds's avatar
Linus Torvalds committed
1156 1157
	name.hash = full_name_hash(name.name, name.len);
	dentry = d_lookup(parent, &name);
1158
	if (dentry != NULL) {
1159 1160 1161 1162 1163 1164 1165 1166 1167 1168
		/* Is this a positive dentry that matches the readdir info? */
		if (dentry->d_inode != NULL &&
				(NFS_FILEID(dentry->d_inode) == entry->ino ||
				d_mountpoint(dentry))) {
			if (!desc->plus || entry->fh->size == 0)
				return dentry;
			if (nfs_compare_fh(NFS_FH(dentry->d_inode),
						entry->fh) == 0)
				goto out_renew;
		}
1169 1170 1171 1172
		/* No, so d_drop to allow one to be created */
		d_drop(dentry);
		dput(dentry);
	}
Linus Torvalds's avatar
Linus Torvalds committed
1173 1174
	if (!desc->plus || !(entry->fattr->valid & NFS_AT