namei.c 17.3 KB
Newer Older
J
Jaegeuk Kim 已提交
1
/*
2 3 4 5 6 7 8 9 10 11 12 13 14 15
 * fs/f2fs/namei.c
 *
 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
 *             http://www.samsung.com/
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
#include <linux/fs.h>
#include <linux/f2fs_fs.h>
#include <linux/pagemap.h>
#include <linux/sched.h>
#include <linux/ctype.h>
C
Chao Yu 已提交
16
#include <linux/dcache.h>
17 18

#include "f2fs.h"
19
#include "node.h"
20 21
#include "xattr.h"
#include "acl.h"
22
#include <trace/events/f2fs.h>
23 24 25

static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)
{
26
	struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
27 28 29
	nid_t ino;
	struct inode *inode;
	bool nid_free = false;
30
	int err;
31

32
	inode = new_inode(dir->i_sb);
33 34 35
	if (!inode)
		return ERR_PTR(-ENOMEM);

36
	f2fs_lock_op(sbi);
37
	if (!alloc_nid(sbi, &ino)) {
38
		f2fs_unlock_op(sbi);
39 40 41
		err = -ENOSPC;
		goto fail;
	}
42
	f2fs_unlock_op(sbi);
43

44
	inode_init_owner(inode, dir, mode);
45 46 47 48 49 50 51 52 53 54 55 56

	inode->i_ino = ino;
	inode->i_blocks = 0;
	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
	inode->i_generation = sbi->s_next_generation++;

	err = insert_inode_locked(inode);
	if (err) {
		err = -EINVAL;
		nid_free = true;
		goto out;
	}
C
Chao Yu 已提交
57

58 59
	if (f2fs_may_inline(inode))
		set_inode_flag(F2FS_I(inode), FI_INLINE_DATA);
C
Chao Yu 已提交
60 61 62
	if (test_opt(sbi, INLINE_DENTRY) && S_ISDIR(inode->i_mode))
		set_inode_flag(F2FS_I(inode), FI_INLINE_DENTRY);

63
	trace_f2fs_new_inode(inode, 0);
64 65 66 67 68 69 70
	mark_inode_dirty(inode);
	return inode;

out:
	clear_nlink(inode);
	unlock_new_inode(inode);
fail:
71
	trace_f2fs_new_inode(inode, err);
72
	make_bad_inode(inode);
73 74 75 76 77 78 79 80
	iput(inode);
	if (nid_free)
		alloc_nid_failed(sbi, ino);
	return ERR_PTR(err);
}

static int is_multimedia_file(const unsigned char *s, const char *sub)
{
81 82
	size_t slen = strlen(s);
	size_t sublen = strlen(sub);
83 84

	if (sublen > slen)
85
		return 0;
86

87
	return !strncasecmp(s + slen - sublen, sub, sublen);
88 89
}

J
Jaegeuk Kim 已提交
90
/*
91 92
 * Set multimedia files as cold files for hot/cold data separation
 */
93
static inline void set_cold_files(struct f2fs_sb_info *sbi, struct inode *inode,
94 95 96 97 98 99 100
		const unsigned char *name)
{
	int i;
	__u8 (*extlist)[8] = sbi->raw_super->extension_list;

	int count = le32_to_cpu(sbi->raw_super->extension_count);
	for (i = 0; i < count; i++) {
101
		if (is_multimedia_file(name, extlist[i])) {
102
			file_set_cold(inode);
103 104 105 106 107 108 109 110
			break;
		}
	}
}

static int f2fs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
						bool excl)
{
111
	struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
112 113
	struct inode *inode;
	nid_t ino = 0;
114
	int err;
115

116 117
	f2fs_balance_fs(sbi);

118 119 120 121 122
	inode = f2fs_new_inode(dir, mode);
	if (IS_ERR(inode))
		return PTR_ERR(inode);

	if (!test_opt(sbi, DISABLE_EXT_IDENTIFY))
123
		set_cold_files(sbi, inode, dentry->d_name.name);
124 125 126 127 128 129

	inode->i_op = &f2fs_file_inode_operations;
	inode->i_fop = &f2fs_file_operations;
	inode->i_mapping->a_ops = &f2fs_dblock_aops;
	ino = inode->i_ino;

130
	f2fs_lock_op(sbi);
131 132 133
	err = f2fs_add_link(dentry, inode);
	if (err)
		goto out;
134
	f2fs_unlock_op(sbi);
135 136 137

	alloc_nid_done(sbi, ino);

138
	stat_inc_inline_inode(inode);
139
	d_instantiate(dentry, inode);
140
	unlock_new_inode(inode);
J
Jaegeuk Kim 已提交
141 142 143

	if (IS_DIRSYNC(dir))
		f2fs_sync_fs(sbi->sb, 1);
144 145
	return 0;
out:
146
	handle_failed_inode(inode);
147 148 149 150 151 152 153
	return err;
}

static int f2fs_link(struct dentry *old_dentry, struct inode *dir,
		struct dentry *dentry)
{
	struct inode *inode = old_dentry->d_inode;
154
	struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
155
	int err;
156

157 158
	f2fs_balance_fs(sbi);

159
	inode->i_ctime = CURRENT_TIME;
J
Jaegeuk Kim 已提交
160
	ihold(inode);
161 162

	set_inode_flag(F2FS_I(inode), FI_INC_LINK);
163
	f2fs_lock_op(sbi);
164 165 166
	err = f2fs_add_link(dentry, inode);
	if (err)
		goto out;
167
	f2fs_unlock_op(sbi);
168 169

	d_instantiate(dentry, inode);
J
Jaegeuk Kim 已提交
170 171 172

	if (IS_DIRSYNC(dir))
		f2fs_sync_fs(sbi->sb, 1);
173 174 175 176
	return 0;
out:
	clear_inode_flag(F2FS_I(inode), FI_INC_LINK);
	iput(inode);
177
	f2fs_unlock_op(sbi);
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
	return err;
}

struct dentry *f2fs_get_parent(struct dentry *child)
{
	struct qstr dotdot = QSTR_INIT("..", 2);
	unsigned long ino = f2fs_inode_by_name(child->d_inode, &dotdot);
	if (!ino)
		return ERR_PTR(-ENOENT);
	return d_obtain_alias(f2fs_iget(child->d_inode->i_sb, ino));
}

static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry,
		unsigned int flags)
{
	struct inode *inode = NULL;
	struct f2fs_dir_entry *de;
	struct page *page;

197
	if (dentry->d_name.len > F2FS_NAME_LEN)
198 199 200 201 202
		return ERR_PTR(-ENAMETOOLONG);

	de = f2fs_find_entry(dir, &dentry->d_name, &page);
	if (de) {
		nid_t ino = le32_to_cpu(de->ino);
C
Chao Yu 已提交
203 204
		if (!f2fs_has_inline_dentry(dir))
			kunmap(page);
205 206 207 208 209 210 211 212 213 214 215 216
		f2fs_put_page(page, 0);

		inode = f2fs_iget(dir->i_sb, ino);
		if (IS_ERR(inode))
			return ERR_CAST(inode);
	}

	return d_splice_alias(inode, dentry);
}

static int f2fs_unlink(struct inode *dir, struct dentry *dentry)
{
217
	struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
218 219 220 221 222
	struct inode *inode = dentry->d_inode;
	struct f2fs_dir_entry *de;
	struct page *page;
	int err = -ENOENT;

223
	trace_f2fs_unlink_enter(dir, dentry);
224 225
	f2fs_balance_fs(sbi);

226 227 228 229
	de = f2fs_find_entry(dir, &dentry->d_name, &page);
	if (!de)
		goto fail;

230
	f2fs_lock_op(sbi);
J
Jaegeuk Kim 已提交
231
	err = acquire_orphan_inode(sbi);
232
	if (err) {
233
		f2fs_unlock_op(sbi);
C
Chao Yu 已提交
234 235
		if (!f2fs_has_inline_dentry(dir))
			kunmap(page);
236 237 238
		f2fs_put_page(page, 0);
		goto fail;
	}
239
	f2fs_delete_entry(de, page, dir, inode);
240
	f2fs_unlock_op(sbi);
241

A
arter97 已提交
242
	/* In order to evict this inode, we set it dirty */
243
	mark_inode_dirty(inode);
J
Jaegeuk Kim 已提交
244 245 246

	if (IS_DIRSYNC(dir))
		f2fs_sync_fs(sbi->sb, 1);
247
fail:
248
	trace_f2fs_unlink_exit(inode, err);
249 250 251 252 253 254
	return err;
}

static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
					const char *symname)
{
255
	struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
256
	struct inode *inode;
257
	size_t symlen = strlen(symname) + 1;
258
	int err;
259

260 261
	f2fs_balance_fs(sbi);

262 263 264 265 266 267 268
	inode = f2fs_new_inode(dir, S_IFLNK | S_IRWXUGO);
	if (IS_ERR(inode))
		return PTR_ERR(inode);

	inode->i_op = &f2fs_symlink_inode_operations;
	inode->i_mapping->a_ops = &f2fs_dblock_aops;

269
	f2fs_lock_op(sbi);
270 271 272
	err = f2fs_add_link(dentry, inode);
	if (err)
		goto out;
273
	f2fs_unlock_op(sbi);
274 275 276 277 278 279

	err = page_symlink(inode, symname, symlen);
	alloc_nid_done(sbi, inode->i_ino);

	d_instantiate(dentry, inode);
	unlock_new_inode(inode);
J
Jaegeuk Kim 已提交
280 281 282

	if (IS_DIRSYNC(dir))
		f2fs_sync_fs(sbi->sb, 1);
283 284
	return err;
out:
285
	handle_failed_inode(inode);
286 287 288 289 290
	return err;
}

static int f2fs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
{
291
	struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
292
	struct inode *inode;
293
	int err;
294

295 296
	f2fs_balance_fs(sbi);

297 298
	inode = f2fs_new_inode(dir, S_IFDIR | mode);
	if (IS_ERR(inode))
299
		return PTR_ERR(inode);
300 301 302 303

	inode->i_op = &f2fs_dir_inode_operations;
	inode->i_fop = &f2fs_dir_operations;
	inode->i_mapping->a_ops = &f2fs_dblock_aops;
304
	mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_ZERO);
305 306

	set_inode_flag(F2FS_I(inode), FI_INC_LINK);
307
	f2fs_lock_op(sbi);
308 309 310
	err = f2fs_add_link(dentry, inode);
	if (err)
		goto out_fail;
311
	f2fs_unlock_op(sbi);
312

313
	stat_inc_inline_dir(inode);
314 315 316 317 318
	alloc_nid_done(sbi, inode->i_ino);

	d_instantiate(dentry, inode);
	unlock_new_inode(inode);

J
Jaegeuk Kim 已提交
319 320
	if (IS_DIRSYNC(dir))
		f2fs_sync_fs(sbi->sb, 1);
321 322 323 324
	return 0;

out_fail:
	clear_inode_flag(F2FS_I(inode), FI_INC_LINK);
325
	handle_failed_inode(inode);
326 327 328 329 330 331 332 333 334 335 336 337 338 339
	return err;
}

static int f2fs_rmdir(struct inode *dir, struct dentry *dentry)
{
	struct inode *inode = dentry->d_inode;
	if (f2fs_empty_dir(inode))
		return f2fs_unlink(dir, dentry);
	return -ENOTEMPTY;
}

static int f2fs_mknod(struct inode *dir, struct dentry *dentry,
				umode_t mode, dev_t rdev)
{
340
	struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
341 342 343 344 345 346
	struct inode *inode;
	int err = 0;

	if (!new_valid_dev(rdev))
		return -EINVAL;

347 348
	f2fs_balance_fs(sbi);

349 350 351 352 353 354 355
	inode = f2fs_new_inode(dir, mode);
	if (IS_ERR(inode))
		return PTR_ERR(inode);

	init_special_inode(inode, inode->i_mode, rdev);
	inode->i_op = &f2fs_special_inode_operations;

356
	f2fs_lock_op(sbi);
357 358 359
	err = f2fs_add_link(dentry, inode);
	if (err)
		goto out;
360
	f2fs_unlock_op(sbi);
361 362

	alloc_nid_done(sbi, inode->i_ino);
J
Jaegeuk Kim 已提交
363

364 365
	d_instantiate(dentry, inode);
	unlock_new_inode(inode);
J
Jaegeuk Kim 已提交
366 367 368

	if (IS_DIRSYNC(dir))
		f2fs_sync_fs(sbi->sb, 1);
369 370
	return 0;
out:
371
	handle_failed_inode(inode);
372 373 374 375 376 377
	return err;
}

static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
			struct inode *new_dir, struct dentry *new_dentry)
{
378
	struct f2fs_sb_info *sbi = F2FS_I_SB(old_dir);
379 380 381
	struct inode *old_inode = old_dentry->d_inode;
	struct inode *new_inode = new_dentry->d_inode;
	struct page *old_dir_page;
J
Jaegeuk Kim 已提交
382
	struct page *old_page, *new_page;
383 384 385
	struct f2fs_dir_entry *old_dir_entry = NULL;
	struct f2fs_dir_entry *old_entry;
	struct f2fs_dir_entry *new_entry;
386
	int err = -ENOENT;
387

388 389
	f2fs_balance_fs(sbi);

390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412
	old_entry = f2fs_find_entry(old_dir, &old_dentry->d_name, &old_page);
	if (!old_entry)
		goto out;

	if (S_ISDIR(old_inode->i_mode)) {
		err = -EIO;
		old_dir_entry = f2fs_parent_dir(old_inode, &old_dir_page);
		if (!old_dir_entry)
			goto out_old;
	}

	if (new_inode) {

		err = -ENOTEMPTY;
		if (old_dir_entry && !f2fs_empty_dir(new_inode))
			goto out_dir;

		err = -ENOENT;
		new_entry = f2fs_find_entry(new_dir, &new_dentry->d_name,
						&new_page);
		if (!new_entry)
			goto out_dir;

413 414
		f2fs_lock_op(sbi);

J
Jaegeuk Kim 已提交
415 416 417 418
		err = acquire_orphan_inode(sbi);
		if (err)
			goto put_out_dir;

419
		if (update_dent_inode(old_inode, &new_dentry->d_name)) {
J
Jaegeuk Kim 已提交
420 421
			release_orphan_inode(sbi);
			goto put_out_dir;
422 423
		}

424 425 426
		f2fs_set_link(new_dir, new_entry, new_page, old_inode);

		new_inode->i_ctime = CURRENT_TIME;
427
		down_write(&F2FS_I(new_inode)->i_sem);
428 429 430
		if (old_dir_entry)
			drop_nlink(new_inode);
		drop_nlink(new_inode);
431 432
		up_write(&F2FS_I(new_inode)->i_sem);

433
		mark_inode_dirty(new_inode);
J
Jaegeuk Kim 已提交
434

435 436
		if (!new_inode->i_nlink)
			add_orphan_inode(sbi, new_inode->i_ino);
J
Jaegeuk Kim 已提交
437 438 439
		else
			release_orphan_inode(sbi);

440
		update_inode_page(old_inode);
441
		update_inode_page(new_inode);
442
	} else {
443 444
		f2fs_lock_op(sbi);

445
		err = f2fs_add_link(new_dentry, old_inode);
446 447
		if (err) {
			f2fs_unlock_op(sbi);
448
			goto out_dir;
449
		}
450 451 452

		if (old_dir_entry) {
			inc_nlink(new_dir);
453
			update_inode_page(new_dir);
454 455 456
		}
	}

457 458 459 460
	down_write(&F2FS_I(old_inode)->i_sem);
	file_lost_pino(old_inode);
	up_write(&F2FS_I(old_inode)->i_sem);

461 462 463
	old_inode->i_ctime = CURRENT_TIME;
	mark_inode_dirty(old_inode);

464
	f2fs_delete_entry(old_entry, old_page, old_dir, NULL);
465 466 467 468 469

	if (old_dir_entry) {
		if (old_dir != new_dir) {
			f2fs_set_link(old_inode, old_dir_entry,
						old_dir_page, new_dir);
470
			update_inode_page(old_inode);
471
		} else {
C
Chao Yu 已提交
472 473
			if (!f2fs_has_inline_dentry(old_inode))
				kunmap(old_dir_page);
474 475 476
			f2fs_put_page(old_dir_page, 0);
		}
		drop_nlink(old_dir);
477
		mark_inode_dirty(old_dir);
478
		update_inode_page(old_dir);
479 480
	}

481
	f2fs_unlock_op(sbi);
J
Jaegeuk Kim 已提交
482 483 484

	if (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir))
		f2fs_sync_fs(sbi->sb, 1);
485 486
	return 0;

J
Jaegeuk Kim 已提交
487
put_out_dir:
488
	f2fs_unlock_op(sbi);
C
Chao Yu 已提交
489 490
	if (!f2fs_has_inline_dentry(new_dir))
		kunmap(new_page);
491
	f2fs_put_page(new_page, 0);
492 493
out_dir:
	if (old_dir_entry) {
C
Chao Yu 已提交
494 495
		if (!f2fs_has_inline_dentry(old_inode))
			kunmap(old_dir_page);
496 497 498
		f2fs_put_page(old_dir_page, 0);
	}
out_old:
C
Chao Yu 已提交
499 500
	if (!f2fs_has_inline_dentry(old_dir))
		kunmap(old_page);
501 502 503 504 505
	f2fs_put_page(old_page, 0);
out:
	return err;
}

C
Chao Yu 已提交
506 507 508
static int f2fs_cross_rename(struct inode *old_dir, struct dentry *old_dentry,
			     struct inode *new_dir, struct dentry *new_dentry)
{
509
	struct f2fs_sb_info *sbi = F2FS_I_SB(old_dir);
C
Chao Yu 已提交
510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623
	struct inode *old_inode = old_dentry->d_inode;
	struct inode *new_inode = new_dentry->d_inode;
	struct page *old_dir_page, *new_dir_page;
	struct page *old_page, *new_page;
	struct f2fs_dir_entry *old_dir_entry = NULL, *new_dir_entry = NULL;
	struct f2fs_dir_entry *old_entry, *new_entry;
	int old_nlink = 0, new_nlink = 0;
	int err = -ENOENT;

	f2fs_balance_fs(sbi);

	old_entry = f2fs_find_entry(old_dir, &old_dentry->d_name, &old_page);
	if (!old_entry)
		goto out;

	new_entry = f2fs_find_entry(new_dir, &new_dentry->d_name, &new_page);
	if (!new_entry)
		goto out_old;

	/* prepare for updating ".." directory entry info later */
	if (old_dir != new_dir) {
		if (S_ISDIR(old_inode->i_mode)) {
			err = -EIO;
			old_dir_entry = f2fs_parent_dir(old_inode,
							&old_dir_page);
			if (!old_dir_entry)
				goto out_new;
		}

		if (S_ISDIR(new_inode->i_mode)) {
			err = -EIO;
			new_dir_entry = f2fs_parent_dir(new_inode,
							&new_dir_page);
			if (!new_dir_entry)
				goto out_old_dir;
		}
	}

	/*
	 * If cross rename between file and directory those are not
	 * in the same directory, we will inc nlink of file's parent
	 * later, so we should check upper boundary of its nlink.
	 */
	if ((!old_dir_entry || !new_dir_entry) &&
				old_dir_entry != new_dir_entry) {
		old_nlink = old_dir_entry ? -1 : 1;
		new_nlink = -old_nlink;
		err = -EMLINK;
		if ((old_nlink > 0 && old_inode->i_nlink >= F2FS_LINK_MAX) ||
			(new_nlink > 0 && new_inode->i_nlink >= F2FS_LINK_MAX))
			goto out_new_dir;
	}

	f2fs_lock_op(sbi);

	err = update_dent_inode(old_inode, &new_dentry->d_name);
	if (err)
		goto out_unlock;

	err = update_dent_inode(new_inode, &old_dentry->d_name);
	if (err)
		goto out_undo;

	/* update ".." directory entry info of old dentry */
	if (old_dir_entry)
		f2fs_set_link(old_inode, old_dir_entry, old_dir_page, new_dir);

	/* update ".." directory entry info of new dentry */
	if (new_dir_entry)
		f2fs_set_link(new_inode, new_dir_entry, new_dir_page, old_dir);

	/* update directory entry info of old dir inode */
	f2fs_set_link(old_dir, old_entry, old_page, new_inode);

	down_write(&F2FS_I(old_inode)->i_sem);
	file_lost_pino(old_inode);
	up_write(&F2FS_I(old_inode)->i_sem);

	update_inode_page(old_inode);

	old_dir->i_ctime = CURRENT_TIME;
	if (old_nlink) {
		down_write(&F2FS_I(old_dir)->i_sem);
		if (old_nlink < 0)
			drop_nlink(old_dir);
		else
			inc_nlink(old_dir);
		up_write(&F2FS_I(old_dir)->i_sem);
	}
	mark_inode_dirty(old_dir);
	update_inode_page(old_dir);

	/* update directory entry info of new dir inode */
	f2fs_set_link(new_dir, new_entry, new_page, old_inode);

	down_write(&F2FS_I(new_inode)->i_sem);
	file_lost_pino(new_inode);
	up_write(&F2FS_I(new_inode)->i_sem);

	update_inode_page(new_inode);

	new_dir->i_ctime = CURRENT_TIME;
	if (new_nlink) {
		down_write(&F2FS_I(new_dir)->i_sem);
		if (new_nlink < 0)
			drop_nlink(new_dir);
		else
			inc_nlink(new_dir);
		up_write(&F2FS_I(new_dir)->i_sem);
	}
	mark_inode_dirty(new_dir);
	update_inode_page(new_dir);

	f2fs_unlock_op(sbi);
J
Jaegeuk Kim 已提交
624 625 626

	if (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir))
		f2fs_sync_fs(sbi->sb, 1);
C
Chao Yu 已提交
627 628 629 630 631 632 633 634
	return 0;
out_undo:
	/* Still we may fail to recover name info of f2fs_inode here */
	update_dent_inode(old_inode, &old_dentry->d_name);
out_unlock:
	f2fs_unlock_op(sbi);
out_new_dir:
	if (new_dir_entry) {
C
Chao Yu 已提交
635 636
		if (!f2fs_has_inline_dentry(new_inode))
			kunmap(new_dir_page);
C
Chao Yu 已提交
637 638 639 640
		f2fs_put_page(new_dir_page, 0);
	}
out_old_dir:
	if (old_dir_entry) {
C
Chao Yu 已提交
641 642
		if (!f2fs_has_inline_dentry(old_inode))
			kunmap(old_dir_page);
C
Chao Yu 已提交
643 644 645
		f2fs_put_page(old_dir_page, 0);
	}
out_new:
C
Chao Yu 已提交
646 647
	if (!f2fs_has_inline_dentry(new_dir))
		kunmap(new_page);
C
Chao Yu 已提交
648 649
	f2fs_put_page(new_page, 0);
out_old:
C
Chao Yu 已提交
650 651
	if (!f2fs_has_inline_dentry(old_dir))
		kunmap(old_page);
C
Chao Yu 已提交
652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674
	f2fs_put_page(old_page, 0);
out:
	return err;
}

static int f2fs_rename2(struct inode *old_dir, struct dentry *old_dentry,
			struct inode *new_dir, struct dentry *new_dentry,
			unsigned int flags)
{
	if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE))
		return -EINVAL;

	if (flags & RENAME_EXCHANGE) {
		return f2fs_cross_rename(old_dir, old_dentry,
					 new_dir, new_dentry);
	}
	/*
	 * VFS has already handled the new dentry existence case,
	 * here, we just deal with "RENAME_NOREPLACE" as regular rename.
	 */
	return f2fs_rename(old_dir, old_dentry, new_dir, new_dentry);
}

C
Chao Yu 已提交
675 676
static int f2fs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
{
677
	struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
C
Chao Yu 已提交
678 679 680 681 682 683 684 685 686 687 688 689 690 691 692
	struct inode *inode;
	int err;

	inode = f2fs_new_inode(dir, mode);
	if (IS_ERR(inode))
		return PTR_ERR(inode);

	inode->i_op = &f2fs_file_inode_operations;
	inode->i_fop = &f2fs_file_operations;
	inode->i_mapping->a_ops = &f2fs_dblock_aops;

	f2fs_lock_op(sbi);
	err = acquire_orphan_inode(sbi);
	if (err)
		goto out;
693 694 695 696 697

	err = f2fs_do_tmpfile(inode, dir);
	if (err)
		goto release_out;

C
Chao Yu 已提交
698 699 700 701 702 703 704 705 706 707 708
	/*
	 * add this non-linked tmpfile to orphan list, in this way we could
	 * remove all unused data of tmpfile after abnormal power-off.
	 */
	add_orphan_inode(sbi, inode->i_ino);
	f2fs_unlock_op(sbi);

	alloc_nid_done(sbi, inode->i_ino);
	d_tmpfile(dentry, inode);
	unlock_new_inode(inode);
	return 0;
709 710 711

release_out:
	release_orphan_inode(sbi);
C
Chao Yu 已提交
712
out:
713
	handle_failed_inode(inode);
C
Chao Yu 已提交
714 715 716
	return err;
}

717 718 719 720 721 722 723 724 725
const struct inode_operations f2fs_dir_inode_operations = {
	.create		= f2fs_create,
	.lookup		= f2fs_lookup,
	.link		= f2fs_link,
	.unlink		= f2fs_unlink,
	.symlink	= f2fs_symlink,
	.mkdir		= f2fs_mkdir,
	.rmdir		= f2fs_rmdir,
	.mknod		= f2fs_mknod,
C
Chao Yu 已提交
726
	.rename2	= f2fs_rename2,
C
Chao Yu 已提交
727
	.tmpfile	= f2fs_tmpfile,
728
	.getattr	= f2fs_getattr,
729 730
	.setattr	= f2fs_setattr,
	.get_acl	= f2fs_get_acl,
731
	.set_acl	= f2fs_set_acl,
732 733 734 735 736 737 738 739 740 741 742 743
#ifdef CONFIG_F2FS_FS_XATTR
	.setxattr	= generic_setxattr,
	.getxattr	= generic_getxattr,
	.listxattr	= f2fs_listxattr,
	.removexattr	= generic_removexattr,
#endif
};

const struct inode_operations f2fs_symlink_inode_operations = {
	.readlink       = generic_readlink,
	.follow_link    = page_follow_link_light,
	.put_link       = page_put_link,
744
	.getattr	= f2fs_getattr,
745 746 747 748 749 750 751 752 753 754
	.setattr	= f2fs_setattr,
#ifdef CONFIG_F2FS_FS_XATTR
	.setxattr	= generic_setxattr,
	.getxattr	= generic_getxattr,
	.listxattr	= f2fs_listxattr,
	.removexattr	= generic_removexattr,
#endif
};

const struct inode_operations f2fs_special_inode_operations = {
755
	.getattr	= f2fs_getattr,
756 757
	.setattr        = f2fs_setattr,
	.get_acl	= f2fs_get_acl,
758
	.set_acl	= f2fs_set_acl,
759 760 761 762 763 764 765
#ifdef CONFIG_F2FS_FS_XATTR
	.setxattr       = generic_setxattr,
	.getxattr       = generic_getxattr,
	.listxattr	= f2fs_listxattr,
	.removexattr    = generic_removexattr,
#endif
};