unlink.c 15.0 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13
/*
 *  linux/fs/nfs/unlink.c
 *
 * nfs sillydelete handling
 *
 */

#include <linux/slab.h>
#include <linux/string.h>
#include <linux/dcache.h>
#include <linux/sunrpc/sched.h>
#include <linux/sunrpc/clnt.h>
#include <linux/nfs_fs.h>
14 15
#include <linux/sched.h>
#include <linux/wait.h>
16
#include <linux/namei.h>
L
Linus Torvalds 已提交
17

18
#include "internal.h"
19
#include "nfs4_fs.h"
20 21
#include "iostat.h"
#include "delegation.h"
22

23 24
#include "nfstrace.h"

L
Linus Torvalds 已提交
25
/**
26
 * nfs_free_unlinkdata - release data from a sillydelete operation.
L
Linus Torvalds 已提交
27 28 29
 * @data: pointer to unlink structure.
 */
static void
30
nfs_free_unlinkdata(struct nfs_unlinkdata *data)
L
Linus Torvalds 已提交
31
{
32 33 34 35
	iput(data->dir);
	put_rpccred(data->cred);
	kfree(data->args.name.name);
	kfree(data);
L
Linus Torvalds 已提交
36 37 38 39 40 41 42 43
}

#define NAME_ALLOC_LEN(len)	((len+16) & ~15)
/**
 * nfs_copy_dname - copy dentry name to data structure
 * @dentry: pointer to dentry
 * @data: nfs_unlinkdata
 */
44
static int nfs_copy_dname(struct dentry *dentry, struct nfs_unlinkdata *data)
L
Linus Torvalds 已提交
45 46 47 48
{
	char		*str;
	int		len = dentry->d_name.len;

49
	str = kmemdup(dentry->d_name.name, NAME_ALLOC_LEN(len), GFP_KERNEL);
L
Linus Torvalds 已提交
50
	if (!str)
51 52 53 54
		return -ENOMEM;
	data->args.name.len = len;
	data->args.name.name = str;
	return 0;
L
Linus Torvalds 已提交
55 56
}

T
Trond Myklebust 已提交
57 58 59 60 61 62 63 64 65 66 67 68 69 70
static void nfs_free_dname(struct nfs_unlinkdata *data)
{
	kfree(data->args.name.name);
	data->args.name.name = NULL;
	data->args.name.len = 0;
}

static void nfs_dec_sillycount(struct inode *dir)
{
	struct nfs_inode *nfsi = NFS_I(dir);
	if (atomic_dec_return(&nfsi->silly_count) == 1)
		wake_up(&nfsi->waitqueue);
}

L
Linus Torvalds 已提交
71 72 73 74 75 76
/**
 * nfs_async_unlink_done - Sillydelete post-processing
 * @task: rpc_task of the sillydelete
 *
 * Do the directory attribute update.
 */
77
static void nfs_async_unlink_done(struct rpc_task *task, void *calldata)
L
Linus Torvalds 已提交
78
{
79 80 81
	struct nfs_unlinkdata *data = calldata;
	struct inode *dir = data->dir;

82
	trace_nfs_sillyrename_unlink(data, task->tk_status);
83
	if (!NFS_PROTO(dir)->unlink_done(task, dir))
84
		rpc_restart_call_prepare(task);
L
Linus Torvalds 已提交
85 86 87 88 89 90 91 92 93
}

/**
 * nfs_async_unlink_release - Release the sillydelete data.
 * @task: rpc_task of the sillydelete
 *
 * We need to call nfs_put_unlinkdata as a 'tk_release' task since the
 * rpc_task would be freed too.
 */
94
static void nfs_async_unlink_release(void *calldata)
L
Linus Torvalds 已提交
95
{
96
	struct nfs_unlinkdata	*data = calldata;
97
	struct super_block *sb = data->dir->i_sb;
T
Trond Myklebust 已提交
98 99

	nfs_dec_sillycount(data->dir);
100
	nfs_free_unlinkdata(data);
101
	nfs_sb_deactive(sb);
L
Linus Torvalds 已提交
102 103
}

104
static void nfs_unlink_prepare(struct rpc_task *task, void *calldata)
105 106
{
	struct nfs_unlinkdata *data = calldata;
107
	NFS_PROTO(data->dir)->unlink_rpc_prepare(task, data);
108 109
}

110 111 112
static const struct rpc_call_ops nfs_unlink_ops = {
	.rpc_call_done = nfs_async_unlink_done,
	.rpc_release = nfs_async_unlink_release,
113
	.rpc_call_prepare = nfs_unlink_prepare,
114 115
};

T
Trond Myklebust 已提交
116
static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct nfs_unlinkdata *data)
117
{
118 119 120 121 122
	struct rpc_message msg = {
		.rpc_argp = &data->args,
		.rpc_resp = &data->res,
		.rpc_cred = data->cred,
	};
T
Trond Myklebust 已提交
123
	struct rpc_task_setup task_setup_data = {
124
		.rpc_message = &msg,
T
Trond Myklebust 已提交
125 126
		.callback_ops = &nfs_unlink_ops,
		.callback_data = data,
127
		.workqueue = nfsiod_workqueue,
T
Trond Myklebust 已提交
128 129
		.flags = RPC_TASK_ASYNC,
	};
130
	struct rpc_task *task;
T
Trond Myklebust 已提交
131 132 133 134
	struct dentry *alias;

	alias = d_lookup(parent, &data->args.name);
	if (alias != NULL) {
135
		int ret;
136
		void *devname_garbage = NULL;
137

T
Trond Myklebust 已提交
138 139 140 141 142
		/*
		 * Hey, we raced with lookup... See if we need to transfer
		 * the sillyrename information to the aliased dentry.
		 */
		nfs_free_dname(data);
143
		ret = nfs_copy_dname(alias, data);
T
Trond Myklebust 已提交
144
		spin_lock(&alias->d_lock);
145
		if (ret == 0 && alias->d_inode != NULL &&
146
		    !(alias->d_flags & DCACHE_NFSFS_RENAMED)) {
147
			devname_garbage = alias->d_fsdata;
T
Trond Myklebust 已提交
148
			alias->d_fsdata = data;
T
Trond Myklebust 已提交
149
			alias->d_flags |= DCACHE_NFSFS_RENAMED;
T
Trond Myklebust 已提交
150
			ret = 1;
151 152
		} else
			ret = 0;
T
Trond Myklebust 已提交
153 154 155
		spin_unlock(&alias->d_lock);
		nfs_dec_sillycount(dir);
		dput(alias);
156 157 158 159 160
		/*
		 * If we'd displaced old cached devname, free it.  At that
		 * point dentry is definitely not a root, so we won't need
		 * that anymore.
		 */
161
		kfree(devname_garbage);
T
Trond Myklebust 已提交
162 163 164 165 166 167 168
		return ret;
	}
	data->dir = igrab(dir);
	if (!data->dir) {
		nfs_dec_sillycount(dir);
		return 0;
	}
169
	nfs_sb_active(dir->i_sb);
T
Trond Myklebust 已提交
170
	data->args.fh = NFS_FH(dir);
171
	nfs_fattr_init(data->res.dir_attr);
T
Trond Myklebust 已提交
172

173
	NFS_PROTO(dir)->unlink_setup(&msg, dir);
T
Trond Myklebust 已提交
174

175
	task_setup_data.rpc_client = NFS_CLIENT(dir);
T
Trond Myklebust 已提交
176
	task = rpc_run_task(&task_setup_data);
T
Trond Myklebust 已提交
177
	if (!IS_ERR(task))
178
		rpc_put_task_async(task);
T
Trond Myklebust 已提交
179 180 181 182 183
	return 1;
}

static int nfs_call_unlink(struct dentry *dentry, struct nfs_unlinkdata *data)
{
184 185
	struct dentry *parent;
	struct inode *dir;
T
Trond Myklebust 已提交
186
	int ret = 0;
187 188 189 190 191


	parent = dget_parent(dentry);
	if (parent == NULL)
		goto out_free;
T
Trond Myklebust 已提交
192 193 194 195 196 197 198 199 200 201 202 203 204
	dir = parent->d_inode;
	/* Non-exclusive lock protects against concurrent lookup() calls */
	spin_lock(&dir->i_lock);
	if (atomic_inc_not_zero(&NFS_I(dir)->silly_count) == 0) {
		/* Deferred delete */
		hlist_add_head(&data->list, &NFS_I(dir)->silly_list);
		spin_unlock(&dir->i_lock);
		ret = 1;
		goto out_dput;
	}
	spin_unlock(&dir->i_lock);
	ret = nfs_do_call_unlink(parent, dir, data);
out_dput:
205
	dput(parent);
T
Trond Myklebust 已提交
206 207 208
out_free:
	return ret;
}
209

210 211 212 213 214 215 216
void nfs_wait_on_sillyrename(struct dentry *dentry)
{
	struct nfs_inode *nfsi = NFS_I(dentry->d_inode);

	wait_event(nfsi->waitqueue, atomic_read(&nfsi->silly_count) <= 1);
}

T
Trond Myklebust 已提交
217 218 219
void nfs_block_sillyrename(struct dentry *dentry)
{
	struct nfs_inode *nfsi = NFS_I(dentry->d_inode);
220

T
Trond Myklebust 已提交
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
	wait_event(nfsi->waitqueue, atomic_cmpxchg(&nfsi->silly_count, 1, 0) == 1);
}

void nfs_unblock_sillyrename(struct dentry *dentry)
{
	struct inode *dir = dentry->d_inode;
	struct nfs_inode *nfsi = NFS_I(dir);
	struct nfs_unlinkdata *data;

	atomic_inc(&nfsi->silly_count);
	spin_lock(&dir->i_lock);
	while (!hlist_empty(&nfsi->silly_list)) {
		if (!atomic_inc_not_zero(&nfsi->silly_count))
			break;
		data = hlist_entry(nfsi->silly_list.first, struct nfs_unlinkdata, list);
		hlist_del(&data->list);
		spin_unlock(&dir->i_lock);
		if (nfs_do_call_unlink(dentry, dir, data) == 0)
			nfs_free_unlinkdata(data);
		spin_lock(&dir->i_lock);
	}
	spin_unlock(&dir->i_lock);
243 244
}

L
Linus Torvalds 已提交
245 246
/**
 * nfs_async_unlink - asynchronous unlinking of a file
247
 * @dir: parent directory of dentry
L
Linus Torvalds 已提交
248 249
 * @dentry: dentry to unlink
 */
250
static int
251
nfs_async_unlink(struct inode *dir, struct dentry *dentry)
L
Linus Torvalds 已提交
252
{
253 254
	struct nfs_unlinkdata *data;
	int status = -ENOMEM;
255
	void *devname_garbage = NULL;
L
Linus Torvalds 已提交
256

257
	data = kzalloc(sizeof(*data), GFP_KERNEL);
258
	if (data == NULL)
L
Linus Torvalds 已提交
259 260
		goto out;

261
	data->cred = rpc_lookup_cred();
L
Linus Torvalds 已提交
262 263 264 265
	if (IS_ERR(data->cred)) {
		status = PTR_ERR(data->cred);
		goto out_free;
	}
266
	data->res.dir_attr = &data->dir_attr;
L
Linus Torvalds 已提交
267

268
	status = -EBUSY;
L
Linus Torvalds 已提交
269
	spin_lock(&dentry->d_lock);
270 271
	if (dentry->d_flags & DCACHE_NFSFS_RENAMED)
		goto out_unlock;
L
Linus Torvalds 已提交
272
	dentry->d_flags |= DCACHE_NFSFS_RENAMED;
273
	devname_garbage = dentry->d_fsdata;
274
	dentry->d_fsdata = data;
L
Linus Torvalds 已提交
275
	spin_unlock(&dentry->d_lock);
276 277 278 279 280
	/*
	 * If we'd displaced old cached devname, free it.  At that
	 * point dentry is definitely not a root, so we won't need
	 * that anymore.
	 */
281
	kfree(devname_garbage);
282 283 284 285
	return 0;
out_unlock:
	spin_unlock(&dentry->d_lock);
	put_rpccred(data->cred);
L
Linus Torvalds 已提交
286 287
out_free:
	kfree(data);
288
out:
L
Linus Torvalds 已提交
289 290 291 292 293 294
	return status;
}

/**
 * nfs_complete_unlink - Initialize completion of the sillydelete
 * @dentry: dentry to delete
295
 * @inode: inode
L
Linus Torvalds 已提交
296 297 298 299 300 301
 *
 * Since we're most likely to be called by dentry_iput(), we
 * only use the dentry to find the sillydelete. We then copy the name
 * into the qstr.
 */
void
302
nfs_complete_unlink(struct dentry *dentry, struct inode *inode)
L
Linus Torvalds 已提交
303
{
304
	struct nfs_unlinkdata	*data = NULL;
L
Linus Torvalds 已提交
305 306

	spin_lock(&dentry->d_lock);
307 308 309
	if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
		dentry->d_flags &= ~DCACHE_NFSFS_RENAMED;
		data = dentry->d_fsdata;
310
		dentry->d_fsdata = NULL;
311
	}
L
Linus Torvalds 已提交
312
	spin_unlock(&dentry->d_lock);
313 314 315

	if (data != NULL && (NFS_STALE(inode) || !nfs_call_unlink(dentry, data)))
		nfs_free_unlinkdata(data);
L
Linus Torvalds 已提交
316
}
317

318 319 320 321 322 323 324 325 326
/* Cancel a queued async unlink. Called when a sillyrename run fails. */
static void
nfs_cancel_async_unlink(struct dentry *dentry)
{
	spin_lock(&dentry->d_lock);
	if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
		struct nfs_unlinkdata *data = dentry->d_fsdata;

		dentry->d_flags &= ~DCACHE_NFSFS_RENAMED;
327
		dentry->d_fsdata = NULL;
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
		spin_unlock(&dentry->d_lock);
		nfs_free_unlinkdata(data);
		return;
	}
	spin_unlock(&dentry->d_lock);
}

/**
 * nfs_async_rename_done - Sillyrename post-processing
 * @task: rpc_task of the sillyrename
 * @calldata: nfs_renamedata for the sillyrename
 *
 * Do the directory attribute updates and the d_move
 */
static void nfs_async_rename_done(struct rpc_task *task, void *calldata)
{
	struct nfs_renamedata *data = calldata;
	struct inode *old_dir = data->old_dir;
	struct inode *new_dir = data->new_dir;
347
	struct dentry *old_dentry = data->old_dentry;
348

349 350
	trace_nfs_sillyrename_rename(old_dir, old_dentry,
			new_dir, data->new_dentry, task->tk_status);
351
	if (!NFS_PROTO(old_dir)->rename_done(task, old_dir, new_dir)) {
352
		rpc_restart_call_prepare(task);
353 354 355
		return;
	}

356
	if (task->tk_status != 0)
357
		nfs_cancel_async_unlink(old_dentry);
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383
}

/**
 * nfs_async_rename_release - Release the sillyrename data.
 * @calldata: the struct nfs_renamedata to be released
 */
static void nfs_async_rename_release(void *calldata)
{
	struct nfs_renamedata	*data = calldata;
	struct super_block *sb = data->old_dir->i_sb;

	if (data->old_dentry->d_inode)
		nfs_mark_for_revalidate(data->old_dentry->d_inode);

	dput(data->old_dentry);
	dput(data->new_dentry);
	iput(data->old_dir);
	iput(data->new_dir);
	nfs_sb_deactive(sb);
	put_rpccred(data->cred);
	kfree(data);
}

static void nfs_rename_prepare(struct rpc_task *task, void *calldata)
{
	struct nfs_renamedata *data = calldata;
384
	NFS_PROTO(data->old_dir)->rename_rpc_prepare(task, data);
385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415
}

static const struct rpc_call_ops nfs_rename_ops = {
	.rpc_call_done = nfs_async_rename_done,
	.rpc_release = nfs_async_rename_release,
	.rpc_call_prepare = nfs_rename_prepare,
};

/**
 * nfs_async_rename - perform an asynchronous rename operation
 * @old_dir: directory that currently holds the dentry to be renamed
 * @new_dir: target directory for the rename
 * @old_dentry: original dentry to be renamed
 * @new_dentry: dentry to which the old_dentry should be renamed
 *
 * It's expected that valid references to the dentries and inodes are held
 */
static struct rpc_task *
nfs_async_rename(struct inode *old_dir, struct inode *new_dir,
		 struct dentry *old_dentry, struct dentry *new_dentry)
{
	struct nfs_renamedata *data;
	struct rpc_message msg = { };
	struct rpc_task_setup task_setup_data = {
		.rpc_message = &msg,
		.callback_ops = &nfs_rename_ops,
		.workqueue = nfsiod_workqueue,
		.rpc_client = NFS_CLIENT(old_dir),
		.flags = RPC_TASK_ASYNC,
	};

416
	data = kzalloc(sizeof(*data), GFP_KERNEL);
417 418
	if (data == NULL)
		return ERR_PTR(-ENOMEM);
419
	task_setup_data.callback_data = data;
420 421 422

	data->cred = rpc_lookup_cred();
	if (IS_ERR(data->cred)) {
423
		struct rpc_task *task = ERR_CAST(data->cred);
424 425 426 427 428 429 430 431 432 433
		kfree(data);
		return task;
	}

	msg.rpc_argp = &data->args;
	msg.rpc_resp = &data->res;
	msg.rpc_cred = data->cred;

	/* set up nfs_renamedata */
	data->old_dir = old_dir;
434
	ihold(old_dir);
435
	data->new_dir = new_dir;
436
	ihold(new_dir);
437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455
	data->old_dentry = dget(old_dentry);
	data->new_dentry = dget(new_dentry);
	nfs_fattr_init(&data->old_fattr);
	nfs_fattr_init(&data->new_fattr);

	/* set up nfs_renameargs */
	data->args.old_dir = NFS_FH(old_dir);
	data->args.old_name = &old_dentry->d_name;
	data->args.new_dir = NFS_FH(new_dir);
	data->args.new_name = &new_dentry->d_name;

	/* set up nfs_renameres */
	data->res.old_fattr = &data->old_fattr;
	data->res.new_fattr = &data->new_fattr;

	nfs_sb_active(old_dir->i_sb);

	NFS_PROTO(data->old_dir)->rename_setup(&msg, old_dir);

456
	return rpc_run_task(&task_setup_data);
457 458
}

459 460 461 462 463 464 465 466
#define SILLYNAME_PREFIX ".nfs"
#define SILLYNAME_PREFIX_LEN ((unsigned)sizeof(SILLYNAME_PREFIX) - 1)
#define SILLYNAME_FILEID_LEN ((unsigned)sizeof(u64) << 1)
#define SILLYNAME_COUNTER_LEN ((unsigned)sizeof(unsigned int) << 1)
#define SILLYNAME_LEN (SILLYNAME_PREFIX_LEN + \
		SILLYNAME_FILEID_LEN + \
		SILLYNAME_COUNTER_LEN)

467 468 469 470 471 472 473 474 475 476 477 478
/**
 * nfs_sillyrename - Perform a silly-rename of a dentry
 * @dir: inode of directory that contains dentry
 * @dentry: dentry to be sillyrenamed
 *
 * NFSv2/3 is stateless and the server doesn't know when the client is
 * holding a file open. To prevent application problems when a file is
 * unlinked while it's still open, the client performs a "silly-rename".
 * That is, it renames the file to a hidden file in the same directory,
 * and only performs the unlink once the last reference to it is put.
 *
 * The final cleanup is done during dentry_iput.
479 480 481 482 483 484 485 486
 *
 * (Note: NFSv4 is stateful, and has opens, so in theory an NFSv4 server
 * could take responsibility for keeping open files referenced.  The server
 * would also need to ensure that opened-but-deleted files were kept over
 * reboots.  However, we may not assume a server does so.  (RFC 5661
 * does provide an OPEN4_RESULT_PRESERVE_UNLINKED flag that a server can
 * use to advertise that it does this; some day we may take advantage of
 * it.))
487 488 489 490 491
 */
int
nfs_sillyrename(struct inode *dir, struct dentry *dentry)
{
	static unsigned int sillycounter;
492 493
	unsigned char silly[SILLYNAME_LEN + 1];
	unsigned long long fileid;
494
	struct dentry *sdentry;
495
	struct rpc_task *task;
496 497 498 499
	int            error = -EIO;

	dfprintk(VFS, "NFS: silly-rename(%s/%s, ct=%d)\n",
		dentry->d_parent->d_name.name, dentry->d_name.name,
A
Al Viro 已提交
500
		d_count(dentry));
501 502 503 504 505 506 507 508 509
	nfs_inc_stats(dir, NFSIOS_SILLYRENAME);

	/*
	 * We don't allow a dentry to be silly-renamed twice.
	 */
	error = -EBUSY;
	if (dentry->d_flags & DCACHE_NFSFS_RENAMED)
		goto out;

510
	fileid = NFS_FILEID(dentry->d_inode);
511 512

	/* Return delegation in anticipation of the rename */
513
	NFS_PROTO(dentry->d_inode)->return_delegation(dentry->d_inode);
514 515 516

	sdentry = NULL;
	do {
517
		int slen;
518 519
		dput(sdentry);
		sillycounter++;
520 521 522 523
		slen = scnprintf(silly, sizeof(silly),
				SILLYNAME_PREFIX "%0*llx%0*x",
				SILLYNAME_FILEID_LEN, fileid,
				SILLYNAME_COUNTER_LEN, sillycounter);
524 525 526 527 528 529 530 531 532 533 534 535 536

		dfprintk(VFS, "NFS: trying to rename %s to %s\n",
				dentry->d_name.name, silly);

		sdentry = lookup_one_len(silly, dentry->d_parent, slen);
		/*
		 * N.B. Better to return EBUSY here ... it could be
		 * dangerous to delete the file while it's in use.
		 */
		if (IS_ERR(sdentry))
			goto out;
	} while (sdentry->d_inode != NULL); /* need negative lookup */

537 538 539 540 541 542 543
	/* queue unlink first. Can't do this from rpc_release as it
	 * has to allocate memory
	 */
	error = nfs_async_unlink(dir, dentry);
	if (error)
		goto out_dput;

544 545 546 547 548 549 550 551
	/* populate unlinkdata with the right dname */
	error = nfs_copy_dname(sdentry,
				(struct nfs_unlinkdata *)dentry->d_fsdata);
	if (error) {
		nfs_cancel_async_unlink(dentry);
		goto out_dput;
	}

552 553 554 555 556 557
	/* run the rename task, undo unlink if it fails */
	task = nfs_async_rename(dir, dir, dentry, sdentry);
	if (IS_ERR(task)) {
		error = -EBUSY;
		nfs_cancel_async_unlink(dentry);
		goto out_dput;
558
	}
559 560 561 562 563

	/* wait for the RPC task to complete, unless a SIGKILL intervenes */
	error = rpc_wait_for_completion_task(task);
	if (error == 0)
		error = task->tk_status;
564 565 566 567 568 569 570 571 572 573 574 575
	switch (error) {
	case 0:
		/* The rename succeeded */
		nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
		d_move(dentry, sdentry);
		break;
	case -ERESTARTSYS:
		/* The result of the rename is unknown. Play it safe by
		 * forcing a new lookup */
		d_drop(dentry);
		d_drop(sdentry);
	}
576 577
	rpc_put_task(task);
out_dput:
578 579 580 581
	dput(sdentry);
out:
	return error;
}