namei.c 16.8 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 60

	if (test_opt(sbi, INLINE_DENTRY) && S_ISDIR(inode->i_mode))
		set_inode_flag(F2FS_I(inode), FI_INLINE_DENTRY);

61
	trace_f2fs_new_inode(inode, 0);
62 63 64 65 66 67 68
	mark_inode_dirty(inode);
	return inode;

out:
	clear_nlink(inode);
	unlock_new_inode(inode);
fail:
69
	trace_f2fs_new_inode(inode, err);
70
	make_bad_inode(inode);
71 72 73 74 75 76 77 78
	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)
{
79 80
	size_t slen = strlen(s);
	size_t sublen = strlen(sub);
81 82

	if (sublen > slen)
83
		return 0;
84

85
	return !strncasecmp(s + slen - sublen, sub, sublen);
86 87
}

J
Jaegeuk Kim 已提交
88
/*
89 90
 * Set multimedia files as cold files for hot/cold data separation
 */
91
static inline void set_cold_files(struct f2fs_sb_info *sbi, struct inode *inode,
92 93 94 95 96 97 98
		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++) {
99
		if (is_multimedia_file(name, extlist[i])) {
100
			file_set_cold(inode);
101 102 103 104 105 106 107 108
			break;
		}
	}
}

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

114 115
	f2fs_balance_fs(sbi);

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

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

	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;

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

	alloc_nid_done(sbi, ino);

136
	d_instantiate(dentry, inode);
137 138 139
	unlock_new_inode(inode);
	return 0;
out:
140
	handle_failed_inode(inode);
141 142 143 144 145 146 147
	return err;
}

static int f2fs_link(struct dentry *old_dentry, struct inode *dir,
		struct dentry *dentry)
{
	struct inode *inode = old_dentry->d_inode;
148
	struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
149
	int err;
150

151 152
	f2fs_balance_fs(sbi);

153
	inode->i_ctime = CURRENT_TIME;
J
Jaegeuk Kim 已提交
154
	ihold(inode);
155 156

	set_inode_flag(F2FS_I(inode), FI_INC_LINK);
157
	f2fs_lock_op(sbi);
158 159 160
	err = f2fs_add_link(dentry, inode);
	if (err)
		goto out;
161
	f2fs_unlock_op(sbi);
162 163 164 165 166 167

	d_instantiate(dentry, inode);
	return 0;
out:
	clear_inode_flag(F2FS_I(inode), FI_INC_LINK);
	iput(inode);
168
	f2fs_unlock_op(sbi);
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
	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;

188
	if (dentry->d_name.len > F2FS_NAME_LEN)
189 190 191 192 193
		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 已提交
194 195
		if (!f2fs_has_inline_dentry(dir))
			kunmap(page);
196 197 198 199 200 201 202 203 204 205 206 207
		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)
{
208
	struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
209 210 211 212 213
	struct inode *inode = dentry->d_inode;
	struct f2fs_dir_entry *de;
	struct page *page;
	int err = -ENOENT;

214
	trace_f2fs_unlink_enter(dir, dentry);
215 216
	f2fs_balance_fs(sbi);

217 218 219 220
	de = f2fs_find_entry(dir, &dentry->d_name, &page);
	if (!de)
		goto fail;

221
	f2fs_lock_op(sbi);
J
Jaegeuk Kim 已提交
222
	err = acquire_orphan_inode(sbi);
223
	if (err) {
224
		f2fs_unlock_op(sbi);
C
Chao Yu 已提交
225 226
		if (!f2fs_has_inline_dentry(dir))
			kunmap(page);
227 228 229
		f2fs_put_page(page, 0);
		goto fail;
	}
230
	f2fs_delete_entry(de, page, dir, inode);
231
	f2fs_unlock_op(sbi);
232

A
arter97 已提交
233
	/* In order to evict this inode, we set it dirty */
234 235
	mark_inode_dirty(inode);
fail:
236
	trace_f2fs_unlink_exit(inode, err);
237 238 239 240 241 242
	return err;
}

static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
					const char *symname)
{
243
	struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
244
	struct inode *inode;
245
	size_t symlen = strlen(symname) + 1;
246
	int err;
247

248 249
	f2fs_balance_fs(sbi);

250 251 252 253 254 255 256
	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;

257
	f2fs_lock_op(sbi);
258 259 260
	err = f2fs_add_link(dentry, inode);
	if (err)
		goto out;
261
	f2fs_unlock_op(sbi);
262 263 264 265 266 267 268 269

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

	d_instantiate(dentry, inode);
	unlock_new_inode(inode);
	return err;
out:
270
	handle_failed_inode(inode);
271 272 273 274 275
	return err;
}

static int f2fs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
{
276
	struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
277
	struct inode *inode;
278
	int err;
279

280 281
	f2fs_balance_fs(sbi);

282 283
	inode = f2fs_new_inode(dir, S_IFDIR | mode);
	if (IS_ERR(inode))
284
		return PTR_ERR(inode);
285 286 287 288

	inode->i_op = &f2fs_dir_inode_operations;
	inode->i_fop = &f2fs_dir_operations;
	inode->i_mapping->a_ops = &f2fs_dblock_aops;
289
	mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_ZERO);
290 291

	set_inode_flag(F2FS_I(inode), FI_INC_LINK);
292
	f2fs_lock_op(sbi);
293 294 295
	err = f2fs_add_link(dentry, inode);
	if (err)
		goto out_fail;
296
	f2fs_unlock_op(sbi);
297

298
	stat_inc_inline_dir(inode);
299 300 301 302 303 304 305 306 307
	alloc_nid_done(sbi, inode->i_ino);

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

	return 0;

out_fail:
	clear_inode_flag(F2FS_I(inode), FI_INC_LINK);
308
	handle_failed_inode(inode);
309 310 311 312 313 314 315 316 317 318 319 320 321 322
	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)
{
323
	struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
324 325 326 327 328 329
	struct inode *inode;
	int err = 0;

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

330 331
	f2fs_balance_fs(sbi);

332 333 334 335 336 337 338
	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;

339
	f2fs_lock_op(sbi);
340 341 342
	err = f2fs_add_link(dentry, inode);
	if (err)
		goto out;
343
	f2fs_unlock_op(sbi);
344 345 346 347 348 349

	alloc_nid_done(sbi, inode->i_ino);
	d_instantiate(dentry, inode);
	unlock_new_inode(inode);
	return 0;
out:
350
	handle_failed_inode(inode);
351 352 353 354 355 356
	return err;
}

static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
			struct inode *new_dir, struct dentry *new_dentry)
{
357
	struct f2fs_sb_info *sbi = F2FS_I_SB(old_dir);
358 359 360
	struct inode *old_inode = old_dentry->d_inode;
	struct inode *new_inode = new_dentry->d_inode;
	struct page *old_dir_page;
J
Jaegeuk Kim 已提交
361
	struct page *old_page, *new_page;
362 363 364
	struct f2fs_dir_entry *old_dir_entry = NULL;
	struct f2fs_dir_entry *old_entry;
	struct f2fs_dir_entry *new_entry;
365
	int err = -ENOENT;
366

367 368
	f2fs_balance_fs(sbi);

369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391
	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;

392 393
		f2fs_lock_op(sbi);

J
Jaegeuk Kim 已提交
394 395 396 397
		err = acquire_orphan_inode(sbi);
		if (err)
			goto put_out_dir;

398
		if (update_dent_inode(old_inode, &new_dentry->d_name)) {
J
Jaegeuk Kim 已提交
399 400
			release_orphan_inode(sbi);
			goto put_out_dir;
401 402
		}

403 404 405
		f2fs_set_link(new_dir, new_entry, new_page, old_inode);

		new_inode->i_ctime = CURRENT_TIME;
406
		down_write(&F2FS_I(new_inode)->i_sem);
407 408 409
		if (old_dir_entry)
			drop_nlink(new_inode);
		drop_nlink(new_inode);
410 411
		up_write(&F2FS_I(new_inode)->i_sem);

412
		mark_inode_dirty(new_inode);
J
Jaegeuk Kim 已提交
413

414 415
		if (!new_inode->i_nlink)
			add_orphan_inode(sbi, new_inode->i_ino);
J
Jaegeuk Kim 已提交
416 417 418
		else
			release_orphan_inode(sbi);

419
		update_inode_page(old_inode);
420
		update_inode_page(new_inode);
421
	} else {
422 423
		f2fs_lock_op(sbi);

424
		err = f2fs_add_link(new_dentry, old_inode);
425 426
		if (err) {
			f2fs_unlock_op(sbi);
427
			goto out_dir;
428
		}
429 430 431

		if (old_dir_entry) {
			inc_nlink(new_dir);
432
			update_inode_page(new_dir);
433 434 435
		}
	}

436 437 438 439
	down_write(&F2FS_I(old_inode)->i_sem);
	file_lost_pino(old_inode);
	up_write(&F2FS_I(old_inode)->i_sem);

440 441 442
	old_inode->i_ctime = CURRENT_TIME;
	mark_inode_dirty(old_inode);

443
	f2fs_delete_entry(old_entry, old_page, old_dir, NULL);
444 445 446 447 448

	if (old_dir_entry) {
		if (old_dir != new_dir) {
			f2fs_set_link(old_inode, old_dir_entry,
						old_dir_page, new_dir);
449
			update_inode_page(old_inode);
450
		} else {
C
Chao Yu 已提交
451 452
			if (!f2fs_has_inline_dentry(old_inode))
				kunmap(old_dir_page);
453 454 455
			f2fs_put_page(old_dir_page, 0);
		}
		drop_nlink(old_dir);
456
		mark_inode_dirty(old_dir);
457
		update_inode_page(old_dir);
458 459
	}

460
	f2fs_unlock_op(sbi);
461 462
	return 0;

J
Jaegeuk Kim 已提交
463
put_out_dir:
464
	f2fs_unlock_op(sbi);
C
Chao Yu 已提交
465 466
	if (!f2fs_has_inline_dentry(new_dir))
		kunmap(new_page);
467
	f2fs_put_page(new_page, 0);
468 469
out_dir:
	if (old_dir_entry) {
C
Chao Yu 已提交
470 471
		if (!f2fs_has_inline_dentry(old_inode))
			kunmap(old_dir_page);
472 473 474
		f2fs_put_page(old_dir_page, 0);
	}
out_old:
C
Chao Yu 已提交
475 476
	if (!f2fs_has_inline_dentry(old_dir))
		kunmap(old_page);
477 478 479 480 481
	f2fs_put_page(old_page, 0);
out:
	return err;
}

C
Chao Yu 已提交
482 483 484
static int f2fs_cross_rename(struct inode *old_dir, struct dentry *old_dentry,
			     struct inode *new_dir, struct dentry *new_dentry)
{
485
	struct f2fs_sb_info *sbi = F2FS_I_SB(old_dir);
C
Chao Yu 已提交
486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 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
	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);
	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 已提交
608 609
		if (!f2fs_has_inline_dentry(new_inode))
			kunmap(new_dir_page);
C
Chao Yu 已提交
610 611 612 613
		f2fs_put_page(new_dir_page, 0);
	}
out_old_dir:
	if (old_dir_entry) {
C
Chao Yu 已提交
614 615
		if (!f2fs_has_inline_dentry(old_inode))
			kunmap(old_dir_page);
C
Chao Yu 已提交
616 617 618
		f2fs_put_page(old_dir_page, 0);
	}
out_new:
C
Chao Yu 已提交
619 620
	if (!f2fs_has_inline_dentry(new_dir))
		kunmap(new_page);
C
Chao Yu 已提交
621 622
	f2fs_put_page(new_page, 0);
out_old:
C
Chao Yu 已提交
623 624
	if (!f2fs_has_inline_dentry(old_dir))
		kunmap(old_page);
C
Chao Yu 已提交
625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647
	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 已提交
648 649
static int f2fs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
{
650
	struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
C
Chao Yu 已提交
651 652 653 654 655 656 657 658 659 660 661 662 663 664 665
	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;
666 667 668 669 670

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

C
Chao Yu 已提交
671 672 673 674 675 676 677 678 679 680 681
	/*
	 * 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;
682 683 684

release_out:
	release_orphan_inode(sbi);
C
Chao Yu 已提交
685
out:
686
	handle_failed_inode(inode);
C
Chao Yu 已提交
687 688 689
	return err;
}

690 691 692 693 694 695 696 697 698
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 已提交
699
	.rename2	= f2fs_rename2,
C
Chao Yu 已提交
700
	.tmpfile	= f2fs_tmpfile,
701
	.getattr	= f2fs_getattr,
702 703
	.setattr	= f2fs_setattr,
	.get_acl	= f2fs_get_acl,
704
	.set_acl	= f2fs_set_acl,
705 706 707 708 709 710 711 712 713 714 715 716
#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,
717
	.getattr	= f2fs_getattr,
718 719 720 721 722 723 724 725 726 727
	.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 = {
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
#ifdef CONFIG_F2FS_FS_XATTR
	.setxattr       = generic_setxattr,
	.getxattr       = generic_getxattr,
	.listxattr	= f2fs_listxattr,
	.removexattr    = generic_removexattr,
#endif
};