dir.c 48.5 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0-or-later
L
Linus Torvalds 已提交
2 3
/* dir.c: AFS filesystem directory handling
 *
D
David Howells 已提交
4
 * Copyright (C) 2002, 2018 Red Hat, Inc. All Rights Reserved.
L
Linus Torvalds 已提交
5 6 7 8 9
 * Written by David Howells (dhowells@redhat.com)
 */

#include <linux/kernel.h>
#include <linux/fs.h>
10
#include <linux/namei.h>
L
Linus Torvalds 已提交
11
#include <linux/pagemap.h>
D
David Howells 已提交
12
#include <linux/swap.h>
D
David Howells 已提交
13
#include <linux/ctype.h>
A
Alexey Dobriyan 已提交
14
#include <linux/sched.h>
D
David Howells 已提交
15
#include <linux/task_io_accounting_ops.h>
L
Linus Torvalds 已提交
16
#include "internal.h"
17
#include "afs_fs.h"
18
#include "xdr_fs.h"
L
Linus Torvalds 已提交
19

20
static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
A
Al Viro 已提交
21
				 unsigned int flags);
L
Linus Torvalds 已提交
22
static int afs_dir_open(struct inode *inode, struct file *file);
A
Al Viro 已提交
23
static int afs_readdir(struct file *file, struct dir_context *ctx);
24
static int afs_d_revalidate(struct dentry *dentry, unsigned int flags);
N
Nick Piggin 已提交
25
static int afs_d_delete(const struct dentry *dentry);
26
static void afs_d_iput(struct dentry *dentry, struct inode *inode);
27
static int afs_lookup_one_filldir(struct dir_context *ctx, const char *name, int nlen,
28
				  loff_t fpos, u64 ino, unsigned dtype);
29 30
static int afs_lookup_filldir(struct dir_context *ctx, const char *name, int nlen,
			      loff_t fpos, u64 ino, unsigned dtype);
A
Al Viro 已提交
31
static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
A
Al Viro 已提交
32
		      bool excl);
33
static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode);
34 35 36 37 38 39 40
static int afs_rmdir(struct inode *dir, struct dentry *dentry);
static int afs_unlink(struct inode *dir, struct dentry *dentry);
static int afs_link(struct dentry *from, struct inode *dir,
		    struct dentry *dentry);
static int afs_symlink(struct inode *dir, struct dentry *dentry,
		       const char *content);
static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
41 42
		      struct inode *new_dir, struct dentry *new_dentry,
		      unsigned int flags);
D
David Howells 已提交
43 44 45 46 47 48 49 50
static int afs_dir_releasepage(struct page *page, gfp_t gfp_flags);
static void afs_dir_invalidatepage(struct page *page, unsigned int offset,
				   unsigned int length);

static int afs_dir_set_page_dirty(struct page *page)
{
	BUG(); /* This should never happen. */
}
L
Linus Torvalds 已提交
51

52
const struct file_operations afs_dir_file_operations = {
L
Linus Torvalds 已提交
53
	.open		= afs_dir_open,
D
David Howells 已提交
54
	.release	= afs_release,
A
Al Viro 已提交
55
	.iterate_shared	= afs_readdir,
D
David Howells 已提交
56
	.lock		= afs_lock,
57
	.llseek		= generic_file_llseek,
L
Linus Torvalds 已提交
58 59
};

60
const struct inode_operations afs_dir_inode_operations = {
61 62 63 64 65 66 67
	.create		= afs_create,
	.lookup		= afs_lookup,
	.link		= afs_link,
	.unlink		= afs_unlink,
	.symlink	= afs_symlink,
	.mkdir		= afs_mkdir,
	.rmdir		= afs_rmdir,
68
	.rename		= afs_rename,
D
David Howells 已提交
69
	.permission	= afs_permission,
D
David Howells 已提交
70
	.getattr	= afs_getattr,
71
	.setattr	= afs_setattr,
D
David Howells 已提交
72
	.listxattr	= afs_listxattr,
L
Linus Torvalds 已提交
73 74
};

D
David Howells 已提交
75 76 77 78 79 80
const struct address_space_operations afs_dir_aops = {
	.set_page_dirty	= afs_dir_set_page_dirty,
	.releasepage	= afs_dir_releasepage,
	.invalidatepage	= afs_dir_invalidatepage,
};

A
Al Viro 已提交
81
const struct dentry_operations afs_fs_dentry_operations = {
L
Linus Torvalds 已提交
82 83
	.d_revalidate	= afs_d_revalidate,
	.d_delete	= afs_d_delete,
84
	.d_release	= afs_d_release,
85
	.d_automount	= afs_d_automount,
86
	.d_iput		= afs_d_iput,
L
Linus Torvalds 已提交
87 88
};

89 90 91 92 93 94 95
struct afs_lookup_one_cookie {
	struct dir_context	ctx;
	struct qstr		name;
	bool			found;
	struct afs_fid		fid;
};

96
struct afs_lookup_cookie {
97 98 99 100 101
	struct dir_context	ctx;
	struct qstr		name;
	bool			found;
	bool			one_only;
	unsigned short		nr_fids;
102
	struct inode		**inodes;
103
	struct afs_status_cb	*statuses;
104
	struct afs_fid		fids[50];
L
Linus Torvalds 已提交
105 106 107 108 109
};

/*
 * check that a directory page is valid
 */
D
David Howells 已提交
110 111
static bool afs_dir_check_page(struct afs_vnode *dvnode, struct page *page,
			       loff_t i_size)
L
Linus Torvalds 已提交
112
{
113
	struct afs_xdr_dir_page *dbuf;
D
David Howells 已提交
114
	loff_t latter, off;
L
Linus Torvalds 已提交
115 116
	int tmp, qty;

117 118 119 120 121 122 123 124
	/* Determine how many magic numbers there should be in this page, but
	 * we must take care because the directory may change size under us.
	 */
	off = page_offset(page);
	if (i_size <= off)
		goto checked;

	latter = i_size - off;
L
Linus Torvalds 已提交
125 126 127 128
	if (latter >= PAGE_SIZE)
		qty = PAGE_SIZE;
	else
		qty = latter;
129
	qty /= sizeof(union afs_xdr_dir_block);
L
Linus Torvalds 已提交
130 131

	/* check them */
132
	dbuf = kmap(page);
L
Linus Torvalds 已提交
133
	for (tmp = 0; tmp < qty; tmp++) {
134
		if (dbuf->blocks[tmp].hdr.magic != AFS_DIR_MAGIC) {
135
			printk("kAFS: %s(%lx): bad magic %d/%d is %04hx\n",
D
David Howells 已提交
136
			       __func__, dvnode->vfs_inode.i_ino, tmp, qty,
137
			       ntohs(dbuf->blocks[tmp].hdr.magic));
D
David Howells 已提交
138
			trace_afs_dir_check_failed(dvnode, off, i_size);
139
			kunmap(page);
140
			trace_afs_file_error(dvnode, -EIO, afs_file_error_dir_bad_magic);
L
Linus Torvalds 已提交
141 142
			goto error;
		}
143 144 145 146 147 148

		/* Make sure each block is NUL terminated so we can reasonably
		 * use string functions on it.  The filenames in the page
		 * *should* be NUL-terminated anyway.
		 */
		((u8 *)&dbuf->blocks[tmp])[AFS_DIR_BLOCK_SIZE - 1] = 0;
L
Linus Torvalds 已提交
149 150
	}

151 152
	kunmap(page);

153
checked:
D
David Howells 已提交
154
	afs_stat_v(dvnode, n_read_dir);
155
	return true;
L
Linus Torvalds 已提交
156

D
David Howells 已提交
157
error:
158
	return false;
D
David Howells 已提交
159
}
L
Linus Torvalds 已提交
160

161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
/*
 * Check the contents of a directory that we've just read.
 */
static bool afs_dir_check_pages(struct afs_vnode *dvnode, struct afs_read *req)
{
	struct afs_xdr_dir_page *dbuf;
	unsigned int i, j, qty = PAGE_SIZE / sizeof(union afs_xdr_dir_block);

	for (i = 0; i < req->nr_pages; i++)
		if (!afs_dir_check_page(dvnode, req->pages[i], req->actual_len))
			goto bad;
	return true;

bad:
	pr_warn("DIR %llx:%llx f=%llx l=%llx al=%llx r=%llx\n",
		dvnode->fid.vid, dvnode->fid.vnode,
		req->file_size, req->len, req->actual_len, req->remain);
	pr_warn("DIR %llx %x %x %x\n",
		req->pos, req->index, req->nr_pages, req->offset);

	for (i = 0; i < req->nr_pages; i++) {
		dbuf = kmap(req->pages[i]);
		for (j = 0; j < qty; j++) {
			union afs_xdr_dir_block *block = &dbuf->blocks[j];

			pr_warn("[%02x] %32phN\n", i * qty + j, block);
		}
		kunmap(req->pages[i]);
	}
	return false;
}

L
Linus Torvalds 已提交
193 194 195 196 197 198 199
/*
 * open an AFS directory file
 */
static int afs_dir_open(struct inode *inode, struct file *file)
{
	_enter("{%lu}", inode->i_ino);

200 201
	BUILD_BUG_ON(sizeof(union afs_xdr_dir_block) != 2048);
	BUILD_BUG_ON(sizeof(union afs_xdr_dirent) != 32);
L
Linus Torvalds 已提交
202

203
	if (test_bit(AFS_VNODE_DELETED, &AFS_FS_I(inode)->flags))
L
Linus Torvalds 已提交
204 205
		return -ENOENT;

D
David Howells 已提交
206
	return afs_open(inode, file);
D
David Howells 已提交
207
}
L
Linus Torvalds 已提交
208

D
David Howells 已提交
209 210 211 212 213 214
/*
 * Read the directory into the pagecache in one go, scrubbing the previous
 * contents.  The list of pages is returned, pinning them so that they don't
 * get reclaimed during the iteration.
 */
static struct afs_read *afs_read_dir(struct afs_vnode *dvnode, struct key *key)
D
David Howells 已提交
215
	__acquires(&dvnode->validate_lock)
D
David Howells 已提交
216 217 218 219 220 221 222 223 224
{
	struct afs_read *req;
	loff_t i_size;
	int nr_pages, nr_inline, i, n;
	int ret = -ENOMEM;

retry:
	i_size = i_size_read(&dvnode->vfs_inode);
	if (i_size < 2048)
225 226 227
		return ERR_PTR(afs_bad(dvnode, afs_file_error_dir_small));
	if (i_size > 2048 * 1024) {
		trace_afs_file_error(dvnode, -EFBIG, afs_file_error_dir_big);
D
David Howells 已提交
228
		return ERR_PTR(-EFBIG);
229
	}
D
David Howells 已提交
230 231 232 233 234 235 236 237 238 239 240

	_enter("%llu", i_size);

	/* Get a request record to hold the page list.  We want to hold it
	 * inline if we can, but we don't want to make an order 1 allocation.
	 */
	nr_pages = (i_size + PAGE_SIZE - 1) / PAGE_SIZE;
	nr_inline = nr_pages;
	if (nr_inline > (PAGE_SIZE - sizeof(*req)) / sizeof(struct page *))
		nr_inline = 0;

241
	req = kzalloc(struct_size(req, array, nr_inline), GFP_KERNEL);
D
David Howells 已提交
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297
	if (!req)
		return ERR_PTR(-ENOMEM);

	refcount_set(&req->usage, 1);
	req->nr_pages = nr_pages;
	req->actual_len = i_size; /* May change */
	req->len = nr_pages * PAGE_SIZE; /* We can ask for more than there is */
	req->data_version = dvnode->status.data_version; /* May change */
	if (nr_inline > 0) {
		req->pages = req->array;
	} else {
		req->pages = kcalloc(nr_pages, sizeof(struct page *),
				     GFP_KERNEL);
		if (!req->pages)
			goto error;
	}

	/* Get a list of all the pages that hold or will hold the directory
	 * content.  We need to fill in any gaps that we might find where the
	 * memory reclaimer has been at work.  If there are any gaps, we will
	 * need to reread the entire directory contents.
	 */
	i = 0;
	do {
		n = find_get_pages_contig(dvnode->vfs_inode.i_mapping, i,
					  req->nr_pages - i,
					  req->pages + i);
		_debug("find %u at %u/%u", n, i, req->nr_pages);
		if (n == 0) {
			gfp_t gfp = dvnode->vfs_inode.i_mapping->gfp_mask;

			if (test_and_clear_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
				afs_stat_v(dvnode, n_inval);

			ret = -ENOMEM;
			req->pages[i] = __page_cache_alloc(gfp);
			if (!req->pages[i])
				goto error;
			ret = add_to_page_cache_lru(req->pages[i],
						    dvnode->vfs_inode.i_mapping,
						    i, gfp);
			if (ret < 0)
				goto error;

			set_page_private(req->pages[i], 1);
			SetPagePrivate(req->pages[i]);
			unlock_page(req->pages[i]);
			i++;
		} else {
			i += n;
		}
	} while (i < req->nr_pages);

	/* If we're going to reload, we need to lock all the pages to prevent
	 * races.
	 */
D
David Howells 已提交
298 299 300
	ret = -ERESTARTSYS;
	if (down_read_killable(&dvnode->validate_lock) < 0)
		goto error;
D
David Howells 已提交
301

D
David Howells 已提交
302 303
	if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
		goto success;
D
David Howells 已提交
304

D
David Howells 已提交
305 306 307 308 309
	up_read(&dvnode->validate_lock);
	if (down_write_killable(&dvnode->validate_lock) < 0)
		goto error;

	if (!test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) {
310
		trace_afs_reload_dir(dvnode);
D
David Howells 已提交
311 312
		ret = afs_fetch_data(dvnode, key, req);
		if (ret < 0)
D
David Howells 已提交
313
			goto error_unlock;
D
David Howells 已提交
314 315 316 317 318 319 320 321

		task_io_account_read(PAGE_SIZE * req->nr_pages);

		if (req->len < req->file_size)
			goto content_has_grown;

		/* Validate the data we just read. */
		ret = -EIO;
322 323
		if (!afs_dir_check_pages(dvnode, req))
			goto error_unlock;
D
David Howells 已提交
324 325 326 327 328 329

		// TODO: Trim excess pages

		set_bit(AFS_VNODE_DIR_VALID, &dvnode->flags);
	}

D
David Howells 已提交
330
	downgrade_write(&dvnode->validate_lock);
D
David Howells 已提交
331 332 333 334
success:
	return req;

error_unlock:
D
David Howells 已提交
335
	up_write(&dvnode->validate_lock);
D
David Howells 已提交
336 337 338 339 340 341
error:
	afs_put_read(req);
	_leave(" = %d", ret);
	return ERR_PTR(ret);

content_has_grown:
D
David Howells 已提交
342
	up_write(&dvnode->validate_lock);
D
David Howells 已提交
343 344 345 346
	afs_put_read(req);
	goto retry;
}

L
Linus Torvalds 已提交
347 348 349
/*
 * deal with one block in an AFS directory
 */
350 351
static int afs_dir_iterate_block(struct afs_vnode *dvnode,
				 struct dir_context *ctx,
352
				 union afs_xdr_dir_block *block,
A
Al Viro 已提交
353
				 unsigned blkoff)
L
Linus Torvalds 已提交
354
{
355
	union afs_xdr_dirent *dire;
L
Linus Torvalds 已提交
356 357
	unsigned offset, next, curr;
	size_t nlen;
A
Al Viro 已提交
358
	int tmp;
L
Linus Torvalds 已提交
359

A
Al Viro 已提交
360
	_enter("%u,%x,%p,,",(unsigned)ctx->pos,blkoff,block);
L
Linus Torvalds 已提交
361

362
	curr = (ctx->pos - blkoff) / sizeof(union afs_xdr_dirent);
L
Linus Torvalds 已提交
363 364

	/* walk through the block, an entry at a time */
365 366
	for (offset = (blkoff == 0 ? AFS_DIR_RESV_BLOCKS0 : AFS_DIR_RESV_BLOCKS);
	     offset < AFS_DIR_SLOTS_PER_BLOCK;
L
Linus Torvalds 已提交
367 368 369 370 371
	     offset = next
	     ) {
		next = offset + 1;

		/* skip entries marked unused in the bitmap */
372
		if (!(block->hdr.bitmap[offset / 8] &
L
Linus Torvalds 已提交
373
		      (1 << (offset % 8)))) {
374
			_debug("ENT[%zu.%u]: unused",
375
			       blkoff / sizeof(union afs_xdr_dir_block), offset);
L
Linus Torvalds 已提交
376
			if (offset >= curr)
A
Al Viro 已提交
377
				ctx->pos = blkoff +
378
					next * sizeof(union afs_xdr_dirent);
L
Linus Torvalds 已提交
379 380 381 382 383 384 385
			continue;
		}

		/* got a valid entry */
		dire = &block->dirents[offset];
		nlen = strnlen(dire->u.name,
			       sizeof(*block) -
386
			       offset * sizeof(union afs_xdr_dirent));
L
Linus Torvalds 已提交
387

388
		_debug("ENT[%zu.%u]: %s %zu \"%s\"",
389
		       blkoff / sizeof(union afs_xdr_dir_block), offset,
L
Linus Torvalds 已提交
390 391 392 393
		       (offset < curr ? "skip" : "fill"),
		       nlen, dire->u.name);

		/* work out where the next possible entry is */
394
		for (tmp = nlen; tmp > 15; tmp -= sizeof(union afs_xdr_dirent)) {
395
			if (next >= AFS_DIR_SLOTS_PER_BLOCK) {
396
				_debug("ENT[%zu.%u]:"
L
Linus Torvalds 已提交
397
				       " %u travelled beyond end dir block"
398
				       " (len %u/%zu)",
399
				       blkoff / sizeof(union afs_xdr_dir_block),
L
Linus Torvalds 已提交
400
				       offset, next, tmp, nlen);
401
				return afs_bad(dvnode, afs_file_error_dir_over_end);
L
Linus Torvalds 已提交
402
			}
403
			if (!(block->hdr.bitmap[next / 8] &
L
Linus Torvalds 已提交
404
			      (1 << (next % 8)))) {
405 406
				_debug("ENT[%zu.%u]:"
				       " %u unmarked extension (len %u/%zu)",
407
				       blkoff / sizeof(union afs_xdr_dir_block),
L
Linus Torvalds 已提交
408
				       offset, next, tmp, nlen);
409
				return afs_bad(dvnode, afs_file_error_dir_unmarked_ext);
L
Linus Torvalds 已提交
410 411
			}

412
			_debug("ENT[%zu.%u]: ext %u/%zu",
413
			       blkoff / sizeof(union afs_xdr_dir_block),
L
Linus Torvalds 已提交
414 415 416 417 418 419 420 421 422
			       next, tmp, nlen);
			next++;
		}

		/* skip if starts before the current position */
		if (offset < curr)
			continue;

		/* found the next entry */
A
Al Viro 已提交
423
		if (!dir_emit(ctx, dire->u.name, nlen,
L
Linus Torvalds 已提交
424
			      ntohl(dire->u.vnode),
425 426
			      (ctx->actor == afs_lookup_filldir ||
			       ctx->actor == afs_lookup_one_filldir)?
A
Al Viro 已提交
427
			      ntohl(dire->u.unique) : DT_UNKNOWN)) {
L
Linus Torvalds 已提交
428 429 430 431
			_leave(" = 0 [full]");
			return 0;
		}

432
		ctx->pos = blkoff + next * sizeof(union afs_xdr_dirent);
L
Linus Torvalds 已提交
433 434 435 436
	}

	_leave(" = 1 [more]");
	return 1;
D
David Howells 已提交
437
}
L
Linus Torvalds 已提交
438 439

/*
440
 * iterate through the data blob that lists the contents of an AFS directory
L
Linus Torvalds 已提交
441
 */
A
Al Viro 已提交
442 443
static int afs_dir_iterate(struct inode *dir, struct dir_context *ctx,
			   struct key *key)
L
Linus Torvalds 已提交
444
{
D
David Howells 已提交
445
	struct afs_vnode *dvnode = AFS_FS_I(dir);
446 447
	struct afs_xdr_dir_page *dbuf;
	union afs_xdr_dir_block *dblock;
D
David Howells 已提交
448
	struct afs_read *req;
L
Linus Torvalds 已提交
449 450 451 452
	struct page *page;
	unsigned blkoff, limit;
	int ret;

A
Al Viro 已提交
453
	_enter("{%lu},%u,,", dir->i_ino, (unsigned)ctx->pos);
L
Linus Torvalds 已提交
454

455
	if (test_bit(AFS_VNODE_DELETED, &AFS_FS_I(dir)->flags)) {
L
Linus Torvalds 已提交
456 457 458 459
		_leave(" = -ESTALE");
		return -ESTALE;
	}

D
David Howells 已提交
460 461 462 463
	req = afs_read_dir(dvnode, key);
	if (IS_ERR(req))
		return PTR_ERR(req);

L
Linus Torvalds 已提交
464
	/* round the file position up to the next entry boundary */
465 466
	ctx->pos += sizeof(union afs_xdr_dirent) - 1;
	ctx->pos &= ~(sizeof(union afs_xdr_dirent) - 1);
L
Linus Torvalds 已提交
467 468 469

	/* walk through the blocks in sequence */
	ret = 0;
D
David Howells 已提交
470
	while (ctx->pos < req->actual_len) {
471
		blkoff = ctx->pos & ~(sizeof(union afs_xdr_dir_block) - 1);
L
Linus Torvalds 已提交
472

D
David Howells 已提交
473 474 475 476 477
		/* Fetch the appropriate page from the directory and re-add it
		 * to the LRU.
		 */
		page = req->pages[blkoff / PAGE_SIZE];
		if (!page) {
478
			ret = afs_bad(dvnode, afs_file_error_dir_missing_page);
L
Linus Torvalds 已提交
479 480
			break;
		}
D
David Howells 已提交
481
		mark_page_accessed(page);
L
Linus Torvalds 已提交
482 483 484

		limit = blkoff & ~(PAGE_SIZE - 1);

D
David Howells 已提交
485
		dbuf = kmap(page);
L
Linus Torvalds 已提交
486 487 488 489

		/* deal with the individual blocks stashed on this page */
		do {
			dblock = &dbuf->blocks[(blkoff % PAGE_SIZE) /
490
					       sizeof(union afs_xdr_dir_block)];
491
			ret = afs_dir_iterate_block(dvnode, ctx, dblock, blkoff);
L
Linus Torvalds 已提交
492
			if (ret != 1) {
D
David Howells 已提交
493
				kunmap(page);
L
Linus Torvalds 已提交
494 495 496
				goto out;
			}

497
			blkoff += sizeof(union afs_xdr_dir_block);
L
Linus Torvalds 已提交
498

A
Al Viro 已提交
499
		} while (ctx->pos < dir->i_size && blkoff < limit);
L
Linus Torvalds 已提交
500

D
David Howells 已提交
501
		kunmap(page);
L
Linus Torvalds 已提交
502 503 504
		ret = 0;
	}

D
David Howells 已提交
505
out:
D
David Howells 已提交
506
	up_read(&dvnode->validate_lock);
D
David Howells 已提交
507
	afs_put_read(req);
L
Linus Torvalds 已提交
508 509
	_leave(" = %d", ret);
	return ret;
D
David Howells 已提交
510
}
L
Linus Torvalds 已提交
511 512 513 514

/*
 * read an AFS directory
 */
A
Al Viro 已提交
515
static int afs_readdir(struct file *file, struct dir_context *ctx)
L
Linus Torvalds 已提交
516
{
517
	return afs_dir_iterate(file_inode(file), ctx, afs_file_key(file));
D
David Howells 已提交
518
}
L
Linus Torvalds 已提交
519 520

/*
521
 * Search the directory for a single name
L
Linus Torvalds 已提交
522 523 524
 * - if afs_dir_iterate_block() spots this function, it'll pass the FID
 *   uniquifier through dtype
 */
525 526
static int afs_lookup_one_filldir(struct dir_context *ctx, const char *name,
				  int nlen, loff_t fpos, u64 ino, unsigned dtype)
L
Linus Torvalds 已提交
527
{
528 529
	struct afs_lookup_one_cookie *cookie =
		container_of(ctx, struct afs_lookup_one_cookie, ctx);
L
Linus Torvalds 已提交
530

A
Al Viro 已提交
531 532
	_enter("{%s,%u},%s,%u,,%llu,%u",
	       cookie->name.name, cookie->name.len, name, nlen,
533
	       (unsigned long long) ino, dtype);
L
Linus Torvalds 已提交
534

535
	/* insanity checks first */
536 537
	BUILD_BUG_ON(sizeof(union afs_xdr_dir_block) != 2048);
	BUILD_BUG_ON(sizeof(union afs_xdr_dirent) != 32);
538

A
Al Viro 已提交
539 540
	if (cookie->name.len != nlen ||
	    memcmp(cookie->name.name, name, nlen) != 0) {
L
Linus Torvalds 已提交
541 542 543 544 545 546 547 548 549 550
		_leave(" = 0 [no]");
		return 0;
	}

	cookie->fid.vnode = ino;
	cookie->fid.unique = dtype;
	cookie->found = 1;

	_leave(" = -1 [found]");
	return -1;
D
David Howells 已提交
551
}
L
Linus Torvalds 已提交
552 553

/*
554
 * Do a lookup of a single name in a directory
555
 * - just returns the FID the dentry name maps to if found
L
Linus Torvalds 已提交
556
 */
557 558
static int afs_do_lookup_one(struct inode *dir, struct dentry *dentry,
			     struct afs_fid *fid, struct key *key)
L
Linus Torvalds 已提交
559
{
A
Al Viro 已提交
560
	struct afs_super_info *as = dir->i_sb->s_fs_info;
561 562
	struct afs_lookup_one_cookie cookie = {
		.ctx.actor = afs_lookup_one_filldir,
A
Al Viro 已提交
563 564 565
		.name = dentry->d_name,
		.fid.vid = as->volume->vid
	};
L
Linus Torvalds 已提交
566 567
	int ret;

A
Al Viro 已提交
568
	_enter("{%lu},%p{%pd},", dir->i_ino, dentry, dentry);
L
Linus Torvalds 已提交
569 570

	/* search the directory */
A
Al Viro 已提交
571
	ret = afs_dir_iterate(dir, &cookie.ctx, key);
L
Linus Torvalds 已提交
572
	if (ret < 0) {
573 574
		_leave(" = %d [iter]", ret);
		return ret;
L
Linus Torvalds 已提交
575 576 577 578
	}

	ret = -ENOENT;
	if (!cookie.found) {
579 580
		_leave(" = -ENOENT [not found]");
		return -ENOENT;
L
Linus Torvalds 已提交
581 582
	}

583
	*fid = cookie.fid;
584
	_leave(" = 0 { vn=%llu u=%u }", fid->vnode, fid->unique);
585 586 587
	return 0;
}

588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604
/*
 * search the directory for a name
 * - if afs_dir_iterate_block() spots this function, it'll pass the FID
 *   uniquifier through dtype
 */
static int afs_lookup_filldir(struct dir_context *ctx, const char *name,
			      int nlen, loff_t fpos, u64 ino, unsigned dtype)
{
	struct afs_lookup_cookie *cookie =
		container_of(ctx, struct afs_lookup_cookie, ctx);
	int ret;

	_enter("{%s,%u},%s,%u,,%llu,%u",
	       cookie->name.name, cookie->name.len, name, nlen,
	       (unsigned long long) ino, dtype);

	/* insanity checks first */
605 606
	BUILD_BUG_ON(sizeof(union afs_xdr_dir_block) != 2048);
	BUILD_BUG_ON(sizeof(union afs_xdr_dirent) != 32);
607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636

	if (cookie->found) {
		if (cookie->nr_fids < 50) {
			cookie->fids[cookie->nr_fids].vnode	= ino;
			cookie->fids[cookie->nr_fids].unique	= dtype;
			cookie->nr_fids++;
		}
	} else if (cookie->name.len == nlen &&
		   memcmp(cookie->name.name, name, nlen) == 0) {
		cookie->fids[0].vnode	= ino;
		cookie->fids[0].unique	= dtype;
		cookie->found = 1;
		if (cookie->one_only)
			return -1;
	}

	ret = cookie->nr_fids >= 50 ? -1 : 0;
	_leave(" = %d", ret);
	return ret;
}

/*
 * Do a lookup in a directory.  We make use of bulk lookup to query a slew of
 * files in one go and create inodes for them.  The inode of the file we were
 * asked for is returned.
 */
static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry,
				   struct key *key)
{
	struct afs_lookup_cookie *cookie;
637
	struct afs_cb_interest *dcbi, *cbi = NULL;
638
	struct afs_super_info *as = dir->i_sb->s_fs_info;
639
	struct afs_status_cb *scb;
640
	struct afs_iget_data iget_data;
641
	struct afs_fs_cursor fc;
642
	struct afs_server *server;
643 644
	struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode;
	struct inode *inode = NULL, *ti;
645 646 647 648 649 650 651 652 653 654 655 656 657
	int ret, i;

	_enter("{%lu},%p{%pd},", dir->i_ino, dentry, dentry);

	cookie = kzalloc(sizeof(struct afs_lookup_cookie), GFP_KERNEL);
	if (!cookie)
		return ERR_PTR(-ENOMEM);

	cookie->ctx.actor = afs_lookup_filldir;
	cookie->name = dentry->d_name;
	cookie->nr_fids = 1; /* slot 0 is saved for the fid we actually want */

	read_seqlock_excl(&dvnode->cb_lock);
658 659 660 661 662 663 664 665
	dcbi = rcu_dereference_protected(dvnode->cb_interest,
					 lockdep_is_held(&dvnode->cb_lock.lock));
	if (dcbi) {
		server = dcbi->server;
		if (server &&
		    test_bit(AFS_SERVER_FL_NO_IBULK, &server->flags))
			cookie->one_only = true;
	}
666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682
	read_sequnlock_excl(&dvnode->cb_lock);

	for (i = 0; i < 50; i++)
		cookie->fids[i].vid = as->volume->vid;

	/* search the directory */
	ret = afs_dir_iterate(dir, &cookie->ctx, key);
	if (ret < 0) {
		inode = ERR_PTR(ret);
		goto out;
	}

	inode = ERR_PTR(-ENOENT);
	if (!cookie->found)
		goto out;

	/* Check to see if we already have an inode for the primary fid. */
683 684 685 686 687 688
	iget_data.fid = cookie->fids[0];
	iget_data.volume = dvnode->volume;
	iget_data.cb_v_break = dvnode->volume->cb_v_break;
	iget_data.cb_s_break = 0;
	inode = ilookup5(dir->i_sb, cookie->fids[0].vnode,
			 afs_iget5_test, &iget_data);
689 690 691 692 693
	if (inode)
		goto out;

	/* Need space for examining all the selected files */
	inode = ERR_PTR(-ENOMEM);
694 695
	cookie->statuses = kvcalloc(cookie->nr_fids, sizeof(struct afs_status_cb),
				    GFP_KERNEL);
696 697 698
	if (!cookie->statuses)
		goto out;

699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719
	cookie->inodes = kcalloc(cookie->nr_fids, sizeof(struct inode *),
				 GFP_KERNEL);
	if (!cookie->inodes)
		goto out_s;

	for (i = 1; i < cookie->nr_fids; i++) {
		scb = &cookie->statuses[i];

		/* Find any inodes that already exist and get their
		 * callback counters.
		 */
		iget_data.fid = cookie->fids[i];
		ti = ilookup5_nowait(dir->i_sb, iget_data.fid.vnode,
				     afs_iget5_test, &iget_data);
		if (!IS_ERR_OR_NULL(ti)) {
			vnode = AFS_FS_I(ti);
			scb->cb_break = afs_calc_vnode_cb_break(vnode);
			cookie->inodes[i] = ti;
		}
	}

720 721 722 723 724 725 726 727
	/* Try FS.InlineBulkStatus first.  Abort codes for the individual
	 * lookups contained therein are stored in the reply without aborting
	 * the whole operation.
	 */
	if (cookie->one_only)
		goto no_inline_bulk_status;

	inode = ERR_PTR(-ERESTARTSYS);
728
	if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
729 730 731 732 733 734 735
		while (afs_select_fileserver(&fc)) {
			if (test_bit(AFS_SERVER_FL_NO_IBULK,
				      &fc.cbi->server->flags)) {
				fc.ac.abort_code = RX_INVALID_OPERATION;
				fc.ac.error = -ECONNABORTED;
				break;
			}
736 737
			iget_data.cb_v_break = dvnode->volume->cb_v_break;
			iget_data.cb_s_break = fc.cbi->server->cb_s_break;
738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762
			afs_fs_inline_bulk_status(&fc,
						  afs_v2net(dvnode),
						  cookie->fids,
						  cookie->statuses,
						  cookie->nr_fids, NULL);
		}

		if (fc.ac.error == 0)
			cbi = afs_get_cb_interest(fc.cbi);
		if (fc.ac.abort_code == RX_INVALID_OPERATION)
			set_bit(AFS_SERVER_FL_NO_IBULK, &fc.cbi->server->flags);
		inode = ERR_PTR(afs_end_vnode_operation(&fc));
	}

	if (!IS_ERR(inode))
		goto success;
	if (fc.ac.abort_code != RX_INVALID_OPERATION)
		goto out_c;

no_inline_bulk_status:
	/* We could try FS.BulkStatus next, but this aborts the entire op if
	 * any of the lookups fails - so, for the moment, revert to
	 * FS.FetchStatus for just the primary fid.
	 */
	inode = ERR_PTR(-ERESTARTSYS);
763
	if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
764
		while (afs_select_fileserver(&fc)) {
765 766
			iget_data.cb_v_break = dvnode->volume->cb_v_break;
			iget_data.cb_s_break = fc.cbi->server->cb_s_break;
767
			scb = &cookie->statuses[0];
768 769 770
			afs_fs_fetch_status(&fc,
					    afs_v2net(dvnode),
					    cookie->fids,
771
					    scb,
772 773 774 775 776 777 778 779 780 781 782 783 784 785 786
					    NULL);
		}

		if (fc.ac.error == 0)
			cbi = afs_get_cb_interest(fc.cbi);
		inode = ERR_PTR(afs_end_vnode_operation(&fc));
	}

	if (IS_ERR(inode))
		goto out_c;

success:
	/* Turn all the files into inodes and save the first one - which is the
	 * one we actually want.
	 */
787 788 789
	scb = &cookie->statuses[0];
	if (scb->status.abort_code != 0)
		inode = ERR_PTR(afs_abort_to_error(scb->status.abort_code));
790 791

	for (i = 0; i < cookie->nr_fids; i++) {
792
		struct afs_status_cb *scb = &cookie->statuses[i];
793 794 795 796 797 798 799 800 801

		if (!scb->have_status && !scb->have_error)
			continue;

		if (cookie->inodes[i]) {
			afs_vnode_commit_status(&fc, AFS_FS_I(cookie->inodes[i]),
						scb->cb_break, NULL, scb);
			continue;
		}
802

803
		if (scb->status.abort_code != 0)
804 805
			continue;

806 807
		iget_data.fid = cookie->fids[i];
		ti = afs_iget(dir->i_sb, key, &iget_data, scb, cbi, dvnode);
808 809 810 811 812
		if (!IS_ERR(ti))
			afs_cache_permit(AFS_FS_I(ti), key,
					 0 /* Assume vnode->cb_break is 0 */ +
					 iget_data.cb_v_break,
					 scb);
813 814 815 816 817 818 819 820 821 822
		if (i == 0) {
			inode = ti;
		} else {
			if (!IS_ERR(ti))
				iput(ti);
		}
	}

out_c:
	afs_put_cb_interest(afs_v2net(dvnode), cbi);
823 824 825 826 827 828
	if (cookie->inodes) {
		for (i = 0; i < cookie->nr_fids; i++)
			iput(cookie->inodes[i]);
		kfree(cookie->inodes);
	}
out_s:
829
	kvfree(cookie->statuses);
830 831 832 833 834
out:
	kfree(cookie);
	return inode;
}

835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890
/*
 * Look up an entry in a directory with @sys substitution.
 */
static struct dentry *afs_lookup_atsys(struct inode *dir, struct dentry *dentry,
				       struct key *key)
{
	struct afs_sysnames *subs;
	struct afs_net *net = afs_i2net(dir);
	struct dentry *ret;
	char *buf, *p, *name;
	int len, i;

	_enter("");

	ret = ERR_PTR(-ENOMEM);
	p = buf = kmalloc(AFSNAMEMAX, GFP_KERNEL);
	if (!buf)
		goto out_p;
	if (dentry->d_name.len > 4) {
		memcpy(p, dentry->d_name.name, dentry->d_name.len - 4);
		p += dentry->d_name.len - 4;
	}

	/* There is an ordered list of substitutes that we have to try. */
	read_lock(&net->sysnames_lock);
	subs = net->sysnames;
	refcount_inc(&subs->usage);
	read_unlock(&net->sysnames_lock);

	for (i = 0; i < subs->nr; i++) {
		name = subs->subs[i];
		len = dentry->d_name.len - 4 + strlen(name);
		if (len >= AFSNAMEMAX) {
			ret = ERR_PTR(-ENAMETOOLONG);
			goto out_s;
		}

		strcpy(p, name);
		ret = lookup_one_len(buf, dentry->d_parent, len);
		if (IS_ERR(ret) || d_is_positive(ret))
			goto out_s;
		dput(ret);
	}

	/* We don't want to d_add() the @sys dentry here as we don't want to
	 * the cached dentry to hide changes to the sysnames list.
	 */
	ret = NULL;
out_s:
	afs_put_sysnames(subs);
	kfree(buf);
out_p:
	key_put(key);
	return ret;
}

891 892 893
/*
 * look up an entry in a directory
 */
894
static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
A
Al Viro 已提交
895
				 unsigned int flags)
896
{
897
	struct afs_vnode *dvnode = AFS_FS_I(dir);
898
	struct inode *inode;
899
	struct dentry *d;
D
David Howells 已提交
900
	struct key *key;
901 902
	int ret;

903
	_enter("{%llx:%llu},%p{%pd},",
904
	       dvnode->fid.vid, dvnode->fid.vnode, dentry, dentry);
905

906
	ASSERTCMP(d_inode(dentry), ==, NULL);
907

D
David Howells 已提交
908
	if (dentry->d_name.len >= AFSNAMEMAX) {
909 910 911 912
		_leave(" = -ENAMETOOLONG");
		return ERR_PTR(-ENAMETOOLONG);
	}

913
	if (test_bit(AFS_VNODE_DELETED, &dvnode->flags)) {
914 915 916 917
		_leave(" = -ESTALE");
		return ERR_PTR(-ESTALE);
	}

918
	key = afs_request_key(dvnode->volume->cell);
D
David Howells 已提交
919 920
	if (IS_ERR(key)) {
		_leave(" = %ld [key]", PTR_ERR(key));
921
		return ERR_CAST(key);
D
David Howells 已提交
922 923
	}

924
	ret = afs_validate(dvnode, key);
925 926 927 928 929 930
	if (ret < 0) {
		key_put(key);
		_leave(" = %d [val]", ret);
		return ERR_PTR(ret);
	}

931 932 933 934 935 936 937
	if (dentry->d_name.len >= 4 &&
	    dentry->d_name.name[dentry->d_name.len - 4] == '@' &&
	    dentry->d_name.name[dentry->d_name.len - 3] == 's' &&
	    dentry->d_name.name[dentry->d_name.len - 2] == 'y' &&
	    dentry->d_name.name[dentry->d_name.len - 1] == 's')
		return afs_lookup_atsys(dir, dentry, key);

938
	afs_stat_v(dvnode, n_lookup);
939
	inode = afs_do_lookup(dir, dentry, key);
D
David Howells 已提交
940
	key_put(key);
941 942 943 944 945
	if (inode == ERR_PTR(-ENOENT)) {
		inode = afs_try_auto_mntpt(dentry, dir);
	} else {
		dentry->d_fsdata =
			(void *)(unsigned long)dvnode->status.data_version;
946
	}
947
	d = d_splice_alias(inode, dentry);
D
David Howells 已提交
948
	if (!IS_ERR_OR_NULL(d)) {
949
		d->d_fsdata = dentry->d_fsdata;
D
David Howells 已提交
950 951 952 953 954 955
		trace_afs_lookup(dvnode, &d->d_name,
				 inode ? AFS_FS_I(inode) : NULL);
	} else {
		trace_afs_lookup(dvnode, &dentry->d_name,
				 inode ? AFS_FS_I(inode) : NULL);
	}
956
	return d;
D
David Howells 已提交
957
}
L
Linus Torvalds 已提交
958 959 960 961 962 963

/*
 * check that a dentry lookup hit has found a valid entry
 * - NOTE! the hit can be a negative hit too, so we can't assume we have an
 *   inode
 */
964
static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
L
Linus Torvalds 已提交
965
{
966
	struct afs_vnode *vnode, *dir;
A
Artem Bityutskiy 已提交
967
	struct afs_fid uninitialized_var(fid);
L
Linus Torvalds 已提交
968
	struct dentry *parent;
969
	struct inode *inode;
D
David Howells 已提交
970
	struct key *key;
971
	long dir_version, de_version;
L
Linus Torvalds 已提交
972 973
	int ret;

974
	if (flags & LOOKUP_RCU)
975 976
		return -ECHILD;

977 978
	if (d_really_is_positive(dentry)) {
		vnode = AFS_FS_I(d_inode(dentry));
979
		_enter("{v={%llx:%llu} n=%pd fl=%lx},",
A
Al Viro 已提交
980
		       vnode->fid.vid, vnode->fid.vnode, dentry,
981
		       vnode->flags);
982
	} else {
A
Al Viro 已提交
983
		_enter("{neg n=%pd}", dentry);
984
	}
L
Linus Torvalds 已提交
985

986
	key = afs_request_key(AFS_FS_S(dentry->d_sb)->volume->cell);
D
David Howells 已提交
987 988 989
	if (IS_ERR(key))
		key = NULL;

990 991 992 993 994 995 996 997 998 999
	if (d_really_is_positive(dentry)) {
		inode = d_inode(dentry);
		if (inode) {
			vnode = AFS_FS_I(inode);
			afs_validate(vnode, key);
			if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
				goto out_bad;
		}
	}

L
Linus Torvalds 已提交
1000
	/* lock down the parent dentry so we can peer at it */
1001
	parent = dget_parent(dentry);
1002
	dir = AFS_FS_I(d_inode(parent));
L
Linus Torvalds 已提交
1003

1004
	/* validate the parent directory */
1005
	afs_validate(dir, key);
1006 1007

	if (test_bit(AFS_VNODE_DELETED, &dir->flags)) {
A
Al Viro 已提交
1008
		_debug("%pd: parent dir deleted", dentry);
1009
		goto out_bad_parent;
L
Linus Torvalds 已提交
1010 1011
	}

1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024
	/* We only need to invalidate a dentry if the server's copy changed
	 * behind our back.  If we made the change, it's no problem.  Note that
	 * on a 32-bit system, we only have 32 bits in the dentry to store the
	 * version.
	 */
	dir_version = (long)dir->status.data_version;
	de_version = (long)dentry->d_fsdata;
	if (de_version == dir_version)
		goto out_valid;

	dir_version = (long)dir->invalid_before;
	if (de_version - dir_version >= 0)
		goto out_valid;
L
Linus Torvalds 已提交
1025

1026
	_debug("dir modified");
1027
	afs_stat_v(dir, n_reval);
1028 1029

	/* search the directory for this vnode */
1030
	ret = afs_do_lookup_one(&dir->vfs_inode, dentry, &fid, key);
1031 1032 1033
	switch (ret) {
	case 0:
		/* the filename maps to something */
1034
		if (d_really_is_negative(dentry))
1035 1036 1037
			goto out_bad_parent;
		inode = d_inode(dentry);
		if (is_bad_inode(inode)) {
A
Al Viro 已提交
1038 1039
			printk("kAFS: afs_d_revalidate: %pd2 has bad inode\n",
			       dentry);
1040
			goto out_bad_parent;
L
Linus Torvalds 已提交
1041 1042
		}

1043 1044
		vnode = AFS_FS_I(inode);

L
Linus Torvalds 已提交
1045 1046
		/* if the vnode ID has changed, then the dirent points to a
		 * different file */
1047
		if (fid.vnode != vnode->fid.vnode) {
1048
			_debug("%pd: dirent changed [%llu != %llu]",
A
Al Viro 已提交
1049
			       dentry, fid.vnode,
1050
			       vnode->fid.vnode);
L
Linus Torvalds 已提交
1051 1052 1053 1054
			goto not_found;
		}

		/* if the vnode ID uniqifier has changed, then the file has
1055 1056
		 * been deleted and replaced, and the original vnode ID has
		 * been reused */
1057
		if (fid.unique != vnode->fid.unique) {
A
Al Viro 已提交
1058 1059
			_debug("%pd: file deleted (uq %u -> %u I:%u)",
			       dentry, fid.unique,
1060
			       vnode->fid.unique,
1061 1062
			       vnode->vfs_inode.i_generation);
			write_seqlock(&vnode->cb_lock);
1063
			set_bit(AFS_VNODE_DELETED, &vnode->flags);
1064
			write_sequnlock(&vnode->cb_lock);
1065
			goto not_found;
L
Linus Torvalds 已提交
1066
		}
1067
		goto out_valid;
1068

1069 1070
	case -ENOENT:
		/* the filename is unknown */
A
Al Viro 已提交
1071
		_debug("%pd: dirent not found", dentry);
1072
		if (d_really_is_positive(dentry))
1073 1074
			goto not_found;
		goto out_valid;
L
Linus Torvalds 已提交
1075

1076
	default:
A
Al Viro 已提交
1077 1078
		_debug("failed to iterate dir %pd: %d",
		       parent, ret);
1079
		goto out_bad_parent;
1080 1081
	}

D
David Howells 已提交
1082
out_valid:
1083
	dentry->d_fsdata = (void *)dir_version;
L
Linus Torvalds 已提交
1084
	dput(parent);
D
David Howells 已提交
1085
	key_put(key);
L
Linus Torvalds 已提交
1086 1087 1088 1089
	_leave(" = 1 [valid]");
	return 1;

	/* the dirent, if it exists, now points to a different vnode */
D
David Howells 已提交
1090
not_found:
L
Linus Torvalds 已提交
1091 1092 1093 1094
	spin_lock(&dentry->d_lock);
	dentry->d_flags |= DCACHE_NFSFS_RENAMED;
	spin_unlock(&dentry->d_lock);

1095
out_bad_parent:
A
Al Viro 已提交
1096
	_debug("dropping dentry %pd2", dentry);
L
Linus Torvalds 已提交
1097
	dput(parent);
1098
out_bad:
D
David Howells 已提交
1099
	key_put(key);
L
Linus Torvalds 已提交
1100 1101 1102

	_leave(" = 0 [bad]");
	return 0;
D
David Howells 已提交
1103
}
L
Linus Torvalds 已提交
1104 1105 1106 1107 1108 1109 1110

/*
 * allow the VFS to enquire as to whether a dentry should be unhashed (mustn't
 * sleep)
 * - called from dput() when d_count is going to 0.
 * - return 1 to request dentry be unhashed, 0 otherwise
 */
N
Nick Piggin 已提交
1111
static int afs_d_delete(const struct dentry *dentry)
L
Linus Torvalds 已提交
1112
{
A
Al Viro 已提交
1113
	_enter("%pd", dentry);
L
Linus Torvalds 已提交
1114 1115 1116 1117

	if (dentry->d_flags & DCACHE_NFSFS_RENAMED)
		goto zap;

1118 1119 1120
	if (d_really_is_positive(dentry) &&
	    (test_bit(AFS_VNODE_DELETED,   &AFS_FS_I(d_inode(dentry))->flags) ||
	     test_bit(AFS_VNODE_PSEUDODIR, &AFS_FS_I(d_inode(dentry))->flags)))
1121
		goto zap;
L
Linus Torvalds 已提交
1122 1123 1124 1125

	_leave(" = 0 [keep]");
	return 0;

D
David Howells 已提交
1126
zap:
L
Linus Torvalds 已提交
1127 1128
	_leave(" = 1 [zap]");
	return 1;
D
David Howells 已提交
1129
}
1130

1131 1132 1133 1134 1135 1136 1137 1138 1139 1140
/*
 * Clean up sillyrename files on dentry removal.
 */
static void afs_d_iput(struct dentry *dentry, struct inode *inode)
{
	if (dentry->d_flags & DCACHE_NFSFS_RENAMED)
		afs_silly_iput(dentry, inode);
	iput(inode);
}

1141 1142 1143
/*
 * handle dentry release
 */
1144
void afs_d_release(struct dentry *dentry)
1145
{
A
Al Viro 已提交
1146
	_enter("%pd", dentry);
1147 1148
}

1149 1150 1151 1152 1153
/*
 * Create a new inode for create/mkdir/symlink
 */
static void afs_vnode_new_inode(struct afs_fs_cursor *fc,
				struct dentry *new_dentry,
1154
				struct afs_iget_data *new_data,
1155
				struct afs_status_cb *new_scb)
1156
{
1157
	struct afs_vnode *vnode;
1158 1159 1160 1161 1162 1163
	struct inode *inode;

	if (fc->ac.error < 0)
		return;

	inode = afs_iget(fc->vnode->vfs_inode.i_sb, fc->key,
1164
			 new_data, new_scb, fc->cbi, fc->vnode);
1165 1166 1167 1168 1169 1170 1171 1172
	if (IS_ERR(inode)) {
		/* ENOMEM or EINTR at a really inconvenient time - just abandon
		 * the new directory on the server.
		 */
		fc->ac.error = PTR_ERR(inode);
		return;
	}

1173 1174
	vnode = AFS_FS_I(inode);
	set_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags);
1175 1176
	if (fc->ac.error == 0)
		afs_cache_permit(vnode, fc->key, vnode->cb_break, new_scb);
1177
	d_instantiate(new_dentry, inode);
1178 1179
}

1180 1181 1182 1183 1184 1185 1186 1187
static void afs_prep_for_new_inode(struct afs_fs_cursor *fc,
				   struct afs_iget_data *iget_data)
{
	iget_data->volume = fc->vnode->volume;
	iget_data->cb_v_break = fc->vnode->volume->cb_v_break;
	iget_data->cb_s_break = fc->cbi->server->cb_s_break;
}

1188 1189 1190
/*
 * create a directory on an AFS filesystem
 */
1191
static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
1192
{
1193
	struct afs_iget_data iget_data;
1194
	struct afs_status_cb *scb;
1195 1196
	struct afs_fs_cursor fc;
	struct afs_vnode *dvnode = AFS_FS_I(dir);
1197 1198 1199
	struct key *key;
	int ret;

1200
	mode |= S_IFDIR;
1201

1202
	_enter("{%llx:%llu},{%pd},%ho",
A
Al Viro 已提交
1203
	       dvnode->fid.vid, dvnode->fid.vnode, dentry, mode);
1204

1205 1206 1207 1208 1209
	ret = -ENOMEM;
	scb = kcalloc(2, sizeof(struct afs_status_cb), GFP_KERNEL);
	if (!scb)
		goto error;

1210 1211 1212
	key = afs_request_key(dvnode->volume->cell);
	if (IS_ERR(key)) {
		ret = PTR_ERR(key);
1213
		goto error_scb;
1214 1215
	}

1216
	ret = -ERESTARTSYS;
1217
	if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
1218 1219
		afs_dataversion_t data_version = dvnode->status.data_version + 1;

1220
		while (afs_select_fileserver(&fc)) {
1221
			fc.cb_break = afs_calc_vnode_cb_break(dvnode);
1222
			afs_prep_for_new_inode(&fc, &iget_data);
1223
			afs_fs_create(&fc, dentry->d_name.name, mode,
1224
				      &scb[0], &iget_data.fid, &scb[1]);
1225
		}
1226

1227 1228 1229
		afs_check_for_remote_deletion(&fc, dvnode);
		afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
					&data_version, &scb[0]);
1230
		afs_vnode_new_inode(&fc, dentry, &iget_data, &scb[1]);
1231 1232 1233
		ret = afs_end_vnode_operation(&fc);
		if (ret < 0)
			goto error_key;
1234 1235
	} else {
		goto error_key;
1236 1237
	}

1238 1239
	if (ret == 0 &&
	    test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
1240
		afs_edit_dir_add(dvnode, &dentry->d_name, &iget_data.fid,
1241 1242
				 afs_edit_dir_for_create);

1243
	key_put(key);
1244
	kfree(scb);
1245 1246 1247
	_leave(" = 0");
	return 0;

1248
error_key:
1249
	key_put(key);
1250 1251
error_scb:
	kfree(scb);
1252 1253 1254 1255 1256 1257
error:
	d_drop(dentry);
	_leave(" = %d", ret);
	return ret;
}

1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268
/*
 * Remove a subdir from a directory.
 */
static void afs_dir_remove_subdir(struct dentry *dentry)
{
	if (d_really_is_positive(dentry)) {
		struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry));

		clear_nlink(&vnode->vfs_inode);
		set_bit(AFS_VNODE_DELETED, &vnode->flags);
		clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
1269
		clear_bit(AFS_VNODE_DIR_VALID, &vnode->flags);
1270 1271 1272
	}
}

1273 1274 1275 1276 1277
/*
 * remove a directory from an AFS filesystem
 */
static int afs_rmdir(struct inode *dir, struct dentry *dentry)
{
1278
	struct afs_status_cb *scb;
1279
	struct afs_fs_cursor fc;
1280
	struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode = NULL;
1281 1282 1283
	struct key *key;
	int ret;

1284
	_enter("{%llx:%llu},{%pd}",
A
Al Viro 已提交
1285
	       dvnode->fid.vid, dvnode->fid.vnode, dentry);
1286

1287 1288 1289 1290
	scb = kzalloc(sizeof(struct afs_status_cb), GFP_KERNEL);
	if (!scb)
		return -ENOMEM;

1291 1292 1293 1294 1295 1296
	key = afs_request_key(dvnode->volume->cell);
	if (IS_ERR(key)) {
		ret = PTR_ERR(key);
		goto error;
	}

1297 1298 1299 1300 1301 1302 1303 1304
	/* Try to make sure we have a callback promise on the victim. */
	if (d_really_is_positive(dentry)) {
		vnode = AFS_FS_I(d_inode(dentry));
		ret = afs_validate(vnode, key);
		if (ret < 0)
			goto error_key;
	}

1305 1306 1307 1308 1309 1310
	if (vnode) {
		ret = down_write_killable(&vnode->rmdir_lock);
		if (ret < 0)
			goto error_key;
	}

1311
	ret = -ERESTARTSYS;
1312
	if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
1313 1314
		afs_dataversion_t data_version = dvnode->status.data_version + 1;

1315
		while (afs_select_fileserver(&fc)) {
1316
			fc.cb_break = afs_calc_vnode_cb_break(dvnode);
1317
			afs_fs_remove(&fc, vnode, dentry->d_name.name, true, scb);
1318
		}
1319

1320 1321
		afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
					&data_version, scb);
1322
		ret = afs_end_vnode_operation(&fc);
1323
		if (ret == 0) {
1324
			afs_dir_remove_subdir(dentry);
1325 1326 1327 1328
			if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
				afs_edit_dir_remove(dvnode, &dentry->d_name,
						    afs_edit_dir_for_rmdir);
		}
1329 1330
	}

1331 1332
	if (vnode)
		up_write(&vnode->rmdir_lock);
1333
error_key:
1334 1335
	key_put(key);
error:
1336
	kfree(scb);
1337 1338 1339 1340
	return ret;
}

/*
1341 1342 1343 1344 1345 1346 1347 1348 1349
 * Remove a link to a file or symlink from a directory.
 *
 * If the file was not deleted due to excess hard links, the fileserver will
 * break the callback promise on the file - if it had one - before it returns
 * to us, and if it was deleted, it won't
 *
 * However, if we didn't have a callback promise outstanding, or it was
 * outstanding on a different server, then it won't break it either...
 */
1350 1351
static int afs_dir_remove_link(struct afs_vnode *dvnode, struct dentry *dentry,
			       struct key *key)
1352 1353 1354 1355 1356 1357
{
	int ret = 0;

	if (d_really_is_positive(dentry)) {
		struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry));

1358 1359
		if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) {
			/* Already done */
1360 1361
		} else if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) {
			write_seqlock(&vnode->cb_lock);
D
David Howells 已提交
1362 1363 1364
			drop_nlink(&vnode->vfs_inode);
			if (vnode->vfs_inode.i_nlink == 0) {
				set_bit(AFS_VNODE_DELETED, &vnode->flags);
1365
				__afs_break_callback(vnode, afs_cb_break_for_unlink);
D
David Howells 已提交
1366
			}
1367
			write_sequnlock(&vnode->cb_lock);
1368
			ret = 0;
D
David Howells 已提交
1369
		} else {
1370
			afs_break_callback(vnode, afs_cb_break_for_unlink);
D
David Howells 已提交
1371 1372 1373 1374 1375 1376 1377 1378

			if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
				kdebug("AFS_VNODE_DELETED");

			ret = afs_validate(vnode, key);
			if (ret == -ESTALE)
				ret = 0;
		}
1379 1380 1381 1382 1383 1384 1385 1386
		_debug("nlink %d [val %d]", vnode->vfs_inode.i_nlink, ret);
	}

	return ret;
}

/*
 * Remove a file or symlink from an AFS filesystem.
1387 1388 1389
 */
static int afs_unlink(struct inode *dir, struct dentry *dentry)
{
1390
	struct afs_fs_cursor fc;
1391
	struct afs_status_cb *scb;
1392 1393
	struct afs_vnode *dvnode = AFS_FS_I(dir);
	struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry));
1394
	struct key *key;
1395
	bool need_rehash = false;
1396 1397
	int ret;

1398
	_enter("{%llx:%llu},{%pd}",
A
Al Viro 已提交
1399
	       dvnode->fid.vid, dvnode->fid.vnode, dentry);
1400

D
David Howells 已提交
1401
	if (dentry->d_name.len >= AFSNAMEMAX)
1402
		return -ENAMETOOLONG;
1403

1404 1405 1406 1407 1408
	ret = -ENOMEM;
	scb = kcalloc(2, sizeof(struct afs_status_cb), GFP_KERNEL);
	if (!scb)
		goto error;

1409 1410 1411
	key = afs_request_key(dvnode->volume->cell);
	if (IS_ERR(key)) {
		ret = PTR_ERR(key);
1412
		goto error_scb;
1413 1414
	}

1415
	/* Try to make sure we have a callback promise on the victim. */
1416 1417 1418
	ret = afs_validate(vnode, key);
	if (ret < 0)
		goto error_key;
1419

1420
	spin_lock(&dentry->d_lock);
1421
	if (d_count(dentry) > 1) {
1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434
		spin_unlock(&dentry->d_lock);
		/* Start asynchronous writeout of the inode */
		write_inode_now(d_inode(dentry), 0);
		ret = afs_sillyrename(dvnode, vnode, dentry, key);
		goto error_key;
	}
	if (!d_unhashed(dentry)) {
		/* Prevent a race with RCU lookup. */
		__d_drop(dentry);
		need_rehash = true;
	}
	spin_unlock(&dentry->d_lock);

1435
	ret = -ERESTARTSYS;
1436
	if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
1437
		afs_dataversion_t data_version = dvnode->status.data_version + 1;
1438
		afs_dataversion_t data_version_2 = vnode->status.data_version;
1439

1440
		while (afs_select_fileserver(&fc)) {
1441
			fc.cb_break = afs_calc_vnode_cb_break(dvnode);
1442
			fc.cb_break_2 = afs_calc_vnode_cb_break(vnode);
1443 1444 1445 1446

			if (test_bit(AFS_SERVER_FL_IS_YFS, &fc.cbi->server->flags) &&
			    !test_bit(AFS_SERVER_FL_NO_RM2, &fc.cbi->server->flags)) {
				yfs_fs_remove_file2(&fc, vnode, dentry->d_name.name,
1447
						    &scb[0], &scb[1]);
1448 1449 1450 1451 1452 1453
				if (fc.ac.error != -ECONNABORTED ||
				    fc.ac.abort_code != RXGEN_OPCODE)
					continue;
				set_bit(AFS_SERVER_FL_NO_RM2, &fc.cbi->server->flags);
			}

1454
			afs_fs_remove(&fc, vnode, dentry->d_name.name, false, &scb[0]);
1455
		}
1456

1457 1458
		afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
					&data_version, &scb[0]);
1459 1460
		afs_vnode_commit_status(&fc, vnode, fc.cb_break_2,
					&data_version_2, &scb[1]);
1461
		ret = afs_end_vnode_operation(&fc);
1462 1463
		if (ret == 0 && !(scb[1].have_status || scb[1].have_error))
			ret = afs_dir_remove_link(dvnode, dentry, key);
1464 1465 1466 1467
		if (ret == 0 &&
		    test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
			afs_edit_dir_remove(dvnode, &dentry->d_name,
					    afs_edit_dir_for_unlink);
1468 1469
	}

1470 1471 1472
	if (need_rehash && ret < 0 && ret != -ENOENT)
		d_rehash(dentry);

1473
error_key:
1474
	key_put(key);
1475 1476
error_scb:
	kfree(scb);
1477 1478 1479 1480 1481 1482 1483 1484
error:
	_leave(" = %d", ret);
	return ret;
}

/*
 * create a regular file on an AFS filesystem
 */
A
Al Viro 已提交
1485
static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
A
Al Viro 已提交
1486
		      bool excl)
1487
{
1488
	struct afs_iget_data iget_data;
1489
	struct afs_fs_cursor fc;
1490
	struct afs_status_cb *scb;
1491
	struct afs_vnode *dvnode = AFS_FS_I(dir);
1492 1493 1494
	struct key *key;
	int ret;

1495
	mode |= S_IFREG;
1496

1497
	_enter("{%llx:%llu},{%pd},%ho,",
A
Al Viro 已提交
1498
	       dvnode->fid.vid, dvnode->fid.vnode, dentry, mode);
1499

1500 1501 1502 1503
	ret = -ENAMETOOLONG;
	if (dentry->d_name.len >= AFSNAMEMAX)
		goto error;

1504 1505 1506 1507 1508 1509
	key = afs_request_key(dvnode->volume->cell);
	if (IS_ERR(key)) {
		ret = PTR_ERR(key);
		goto error;
	}

1510 1511 1512 1513 1514
	ret = -ENOMEM;
	scb = kcalloc(2, sizeof(struct afs_status_cb), GFP_KERNEL);
	if (!scb)
		goto error_scb;

1515
	ret = -ERESTARTSYS;
1516
	if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
1517 1518
		afs_dataversion_t data_version = dvnode->status.data_version + 1;

1519
		while (afs_select_fileserver(&fc)) {
1520
			fc.cb_break = afs_calc_vnode_cb_break(dvnode);
1521
			afs_prep_for_new_inode(&fc, &iget_data);
1522
			afs_fs_create(&fc, dentry->d_name.name, mode,
1523
				      &scb[0], &iget_data.fid, &scb[1]);
1524
		}
1525

1526 1527 1528
		afs_check_for_remote_deletion(&fc, dvnode);
		afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
					&data_version, &scb[0]);
1529
		afs_vnode_new_inode(&fc, dentry, &iget_data, &scb[1]);
1530 1531 1532
		ret = afs_end_vnode_operation(&fc);
		if (ret < 0)
			goto error_key;
1533 1534
	} else {
		goto error_key;
1535 1536
	}

1537
	if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
1538
		afs_edit_dir_add(dvnode, &dentry->d_name, &iget_data.fid,
1539 1540
				 afs_edit_dir_for_create);

1541
	kfree(scb);
1542 1543 1544 1545
	key_put(key);
	_leave(" = 0");
	return 0;

1546 1547
error_scb:
	kfree(scb);
1548
error_key:
1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561
	key_put(key);
error:
	d_drop(dentry);
	_leave(" = %d", ret);
	return ret;
}

/*
 * create a hard link between files in an AFS filesystem
 */
static int afs_link(struct dentry *from, struct inode *dir,
		    struct dentry *dentry)
{
1562
	struct afs_fs_cursor fc;
1563 1564 1565
	struct afs_status_cb *scb;
	struct afs_vnode *dvnode = AFS_FS_I(dir);
	struct afs_vnode *vnode = AFS_FS_I(d_inode(from));
1566 1567 1568
	struct key *key;
	int ret;

1569
	_enter("{%llx:%llu},{%llx:%llu},{%pd}",
1570 1571
	       vnode->fid.vid, vnode->fid.vnode,
	       dvnode->fid.vid, dvnode->fid.vnode,
A
Al Viro 已提交
1572
	       dentry);
1573

1574 1575 1576 1577
	ret = -ENAMETOOLONG;
	if (dentry->d_name.len >= AFSNAMEMAX)
		goto error;

1578 1579 1580 1581 1582
	ret = -ENOMEM;
	scb = kcalloc(2, sizeof(struct afs_status_cb), GFP_KERNEL);
	if (!scb)
		goto error;

1583 1584 1585
	key = afs_request_key(dvnode->volume->cell);
	if (IS_ERR(key)) {
		ret = PTR_ERR(key);
1586
		goto error_scb;
1587 1588
	}

1589
	ret = -ERESTARTSYS;
1590
	if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
1591 1592
		afs_dataversion_t data_version = dvnode->status.data_version + 1;

1593 1594
		if (mutex_lock_interruptible_nested(&vnode->io_lock, 1) < 0) {
			afs_end_vnode_operation(&fc);
1595
			goto error_key;
1596 1597 1598
		}

		while (afs_select_fileserver(&fc)) {
1599 1600
			fc.cb_break = afs_calc_vnode_cb_break(dvnode);
			fc.cb_break_2 = afs_calc_vnode_cb_break(vnode);
1601 1602
			afs_fs_link(&fc, vnode, dentry->d_name.name,
				    &scb[0], &scb[1]);
1603 1604
		}

1605 1606 1607 1608
		afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
					&data_version, &scb[0]);
		afs_vnode_commit_status(&fc, vnode, fc.cb_break_2,
					NULL, &scb[1]);
1609 1610 1611 1612 1613 1614 1615
		ihold(&vnode->vfs_inode);
		d_instantiate(dentry, &vnode->vfs_inode);

		mutex_unlock(&vnode->io_lock);
		ret = afs_end_vnode_operation(&fc);
		if (ret < 0)
			goto error_key;
1616 1617
	} else {
		goto error_key;
1618
	}
1619

1620 1621 1622 1623
	if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
		afs_edit_dir_add(dvnode, &dentry->d_name, &vnode->fid,
				 afs_edit_dir_for_link);

1624
	key_put(key);
1625
	kfree(scb);
1626 1627 1628
	_leave(" = 0");
	return 0;

1629
error_key:
1630
	key_put(key);
1631 1632
error_scb:
	kfree(scb);
1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644
error:
	d_drop(dentry);
	_leave(" = %d", ret);
	return ret;
}

/*
 * create a symlink in an AFS filesystem
 */
static int afs_symlink(struct inode *dir, struct dentry *dentry,
		       const char *content)
{
1645
	struct afs_iget_data iget_data;
1646
	struct afs_fs_cursor fc;
1647
	struct afs_status_cb *scb;
1648
	struct afs_vnode *dvnode = AFS_FS_I(dir);
1649 1650 1651
	struct key *key;
	int ret;

1652
	_enter("{%llx:%llu},{%pd},%s",
A
Al Viro 已提交
1653
	       dvnode->fid.vid, dvnode->fid.vnode, dentry,
1654 1655
	       content);

1656 1657 1658 1659
	ret = -ENAMETOOLONG;
	if (dentry->d_name.len >= AFSNAMEMAX)
		goto error;

1660
	ret = -EINVAL;
D
David Howells 已提交
1661
	if (strlen(content) >= AFSPATHMAX)
1662 1663
		goto error;

1664 1665 1666 1667 1668
	ret = -ENOMEM;
	scb = kcalloc(2, sizeof(struct afs_status_cb), GFP_KERNEL);
	if (!scb)
		goto error;

1669 1670 1671
	key = afs_request_key(dvnode->volume->cell);
	if (IS_ERR(key)) {
		ret = PTR_ERR(key);
1672
		goto error_scb;
1673 1674
	}

1675
	ret = -ERESTARTSYS;
1676
	if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
1677 1678
		afs_dataversion_t data_version = dvnode->status.data_version + 1;

1679
		while (afs_select_fileserver(&fc)) {
1680
			fc.cb_break = afs_calc_vnode_cb_break(dvnode);
1681
			afs_prep_for_new_inode(&fc, &iget_data);
1682
			afs_fs_symlink(&fc, dentry->d_name.name, content,
1683
				       &scb[0], &iget_data.fid, &scb[1]);
1684
		}
1685

1686 1687 1688
		afs_check_for_remote_deletion(&fc, dvnode);
		afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
					&data_version, &scb[0]);
1689
		afs_vnode_new_inode(&fc, dentry, &iget_data, &scb[1]);
1690 1691 1692
		ret = afs_end_vnode_operation(&fc);
		if (ret < 0)
			goto error_key;
1693 1694
	} else {
		goto error_key;
1695 1696
	}

1697
	if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
1698
		afs_edit_dir_add(dvnode, &dentry->d_name, &iget_data.fid,
1699 1700
				 afs_edit_dir_for_symlink);

1701
	key_put(key);
1702
	kfree(scb);
1703 1704 1705
	_leave(" = 0");
	return 0;

1706
error_key:
1707
	key_put(key);
1708 1709
error_scb:
	kfree(scb);
1710 1711 1712 1713 1714 1715 1716 1717 1718 1719
error:
	d_drop(dentry);
	_leave(" = %d", ret);
	return ret;
}

/*
 * rename a file in an AFS filesystem and/or move it between directories
 */
static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
1720 1721
		      struct inode *new_dir, struct dentry *new_dentry,
		      unsigned int flags)
1722
{
1723
	struct afs_fs_cursor fc;
1724
	struct afs_status_cb *scb;
1725
	struct afs_vnode *orig_dvnode, *new_dvnode, *vnode;
1726 1727
	struct dentry *tmp = NULL, *rehash = NULL;
	struct inode *new_inode;
1728
	struct key *key;
1729
	bool new_negative = d_is_negative(new_dentry);
1730 1731
	int ret;

1732 1733 1734
	if (flags)
		return -EINVAL;

1735 1736 1737 1738
	/* Don't allow silly-rename files be moved around. */
	if (old_dentry->d_flags & DCACHE_NFSFS_RENAMED)
		return -EINVAL;

1739
	vnode = AFS_FS_I(d_inode(old_dentry));
1740 1741 1742
	orig_dvnode = AFS_FS_I(old_dir);
	new_dvnode = AFS_FS_I(new_dir);

1743
	_enter("{%llx:%llu},{%llx:%llu},{%llx:%llu},{%pd}",
1744 1745 1746
	       orig_dvnode->fid.vid, orig_dvnode->fid.vnode,
	       vnode->fid.vid, vnode->fid.vnode,
	       new_dvnode->fid.vid, new_dvnode->fid.vnode,
A
Al Viro 已提交
1747
	       new_dentry);
1748

1749 1750 1751 1752 1753
	ret = -ENOMEM;
	scb = kcalloc(2, sizeof(struct afs_status_cb), GFP_KERNEL);
	if (!scb)
		goto error;

1754 1755 1756
	key = afs_request_key(orig_dvnode->volume->cell);
	if (IS_ERR(key)) {
		ret = PTR_ERR(key);
1757
		goto error_scb;
1758 1759
	}

1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793
	/* For non-directories, check whether the target is busy and if so,
	 * make a copy of the dentry and then do a silly-rename.  If the
	 * silly-rename succeeds, the copied dentry is hashed and becomes the
	 * new target.
	 */
	if (d_is_positive(new_dentry) && !d_is_dir(new_dentry)) {
		/* To prevent any new references to the target during the
		 * rename, we unhash the dentry in advance.
		 */
		if (!d_unhashed(new_dentry)) {
			d_drop(new_dentry);
			rehash = new_dentry;
		}

		if (d_count(new_dentry) > 2) {
			/* copy the target dentry's name */
			ret = -ENOMEM;
			tmp = d_alloc(new_dentry->d_parent,
				      &new_dentry->d_name);
			if (!tmp)
				goto error_rehash;

			ret = afs_sillyrename(new_dvnode,
					      AFS_FS_I(d_inode(new_dentry)),
					      new_dentry, key);
			if (ret)
				goto error_rehash;

			new_dentry = tmp;
			rehash = NULL;
			new_negative = true;
		}
	}

1794
	ret = -ERESTARTSYS;
1795
	if (afs_begin_vnode_operation(&fc, orig_dvnode, key, true)) {
1796 1797 1798 1799 1800 1801
		afs_dataversion_t orig_data_version;
		afs_dataversion_t new_data_version;
		struct afs_status_cb *new_scb = &scb[1];

		orig_data_version = orig_dvnode->status.data_version + 1;

1802 1803 1804
		if (orig_dvnode != new_dvnode) {
			if (mutex_lock_interruptible_nested(&new_dvnode->io_lock, 1) < 0) {
				afs_end_vnode_operation(&fc);
1805
				goto error_rehash;
1806
			}
1807 1808 1809 1810
			new_data_version = new_dvnode->status.data_version;
		} else {
			new_data_version = orig_data_version;
			new_scb = &scb[0];
1811
		}
1812

1813
		while (afs_select_fileserver(&fc)) {
1814 1815
			fc.cb_break = afs_calc_vnode_cb_break(orig_dvnode);
			fc.cb_break_2 = afs_calc_vnode_cb_break(new_dvnode);
1816
			afs_fs_rename(&fc, old_dentry->d_name.name,
1817
				      new_dvnode, new_dentry->d_name.name,
1818
				      &scb[0], new_scb);
1819 1820
		}

1821 1822 1823 1824 1825
		afs_vnode_commit_status(&fc, orig_dvnode, fc.cb_break,
					&orig_data_version, &scb[0]);
		if (new_dvnode != orig_dvnode) {
			afs_vnode_commit_status(&fc, new_dvnode, fc.cb_break_2,
						&new_data_version, &scb[1]);
1826
			mutex_unlock(&new_dvnode->io_lock);
1827
		}
1828 1829
		ret = afs_end_vnode_operation(&fc);
		if (ret < 0)
1830
			goto error_rehash;
1831 1832
	}

1833
	if (ret == 0) {
1834 1835
		if (rehash)
			d_rehash(rehash);
1836 1837
		if (test_bit(AFS_VNODE_DIR_VALID, &orig_dvnode->flags))
		    afs_edit_dir_remove(orig_dvnode, &old_dentry->d_name,
1838
					afs_edit_dir_for_rename_0);
1839 1840 1841 1842

		if (!new_negative &&
		    test_bit(AFS_VNODE_DIR_VALID, &new_dvnode->flags))
			afs_edit_dir_remove(new_dvnode, &new_dentry->d_name,
1843
					    afs_edit_dir_for_rename_1);
1844 1845 1846

		if (test_bit(AFS_VNODE_DIR_VALID, &new_dvnode->flags))
			afs_edit_dir_add(new_dvnode, &new_dentry->d_name,
1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857
					 &vnode->fid, afs_edit_dir_for_rename_2);

		new_inode = d_inode(new_dentry);
		if (new_inode) {
			spin_lock(&new_inode->i_lock);
			if (new_inode->i_nlink > 0)
				drop_nlink(new_inode);
			spin_unlock(&new_inode->i_lock);
		}
		d_move(old_dentry, new_dentry);
		goto error_tmp;
1858 1859
	}

1860 1861 1862 1863 1864 1865
error_rehash:
	if (rehash)
		d_rehash(rehash);
error_tmp:
	if (tmp)
		dput(tmp);
1866
	key_put(key);
1867 1868
error_scb:
	kfree(scb);
1869 1870 1871 1872
error:
	_leave(" = %d", ret);
	return ret;
}
D
David Howells 已提交
1873 1874 1875 1876 1877 1878 1879 1880 1881

/*
 * Release a directory page and clean up its private state if it's not busy
 * - return true if the page can now be released, false if not
 */
static int afs_dir_releasepage(struct page *page, gfp_t gfp_flags)
{
	struct afs_vnode *dvnode = AFS_FS_I(page->mapping->host);

1882
	_enter("{{%llx:%llu}[%lu]}", dvnode->fid.vid, dvnode->fid.vnode, page->index);
D
David Howells 已提交
1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916

	set_page_private(page, 0);
	ClearPagePrivate(page);

	/* The directory will need reloading. */
	if (test_and_clear_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
		afs_stat_v(dvnode, n_relpg);
	return 1;
}

/*
 * invalidate part or all of a page
 * - release a page and clean up its private data if offset is 0 (indicating
 *   the entire page)
 */
static void afs_dir_invalidatepage(struct page *page, unsigned int offset,
				   unsigned int length)
{
	struct afs_vnode *dvnode = AFS_FS_I(page->mapping->host);

	_enter("{%lu},%u,%u", page->index, offset, length);

	BUG_ON(!PageLocked(page));

	/* The directory will need reloading. */
	if (test_and_clear_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
		afs_stat_v(dvnode, n_inval);

	/* we clean up only if the entire page is being invalidated */
	if (offset == 0 && length == PAGE_SIZE) {
		set_page_private(page, 0);
		ClearPagePrivate(page);
	}
}