| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* -*- mode: c; c-basic-offset: 8; -*- |
|---|
| 2 | 3 | * vim: noexpandtab sw=8 ts=8 sts=0: |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 19 | 20 | * linux/fs/minix/dir.c |
|---|
| 20 | 21 | * |
|---|
| 21 | 22 | * Copyright (C) 1991, 1992 Linux Torvalds |
|---|
| 22 | | - * |
|---|
| 23 | | - * This program is free software; you can redistribute it and/or |
|---|
| 24 | | - * modify it under the terms of the GNU General Public |
|---|
| 25 | | - * License as published by the Free Software Foundation; either |
|---|
| 26 | | - * version 2 of the License, or (at your option) any later version. |
|---|
| 27 | | - * |
|---|
| 28 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 29 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 30 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|---|
| 31 | | - * General Public License for more details. |
|---|
| 32 | | - * |
|---|
| 33 | | - * You should have received a copy of the GNU General Public |
|---|
| 34 | | - * License along with this program; if not, write to the |
|---|
| 35 | | - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
|---|
| 36 | | - * Boston, MA 021110-1307, USA. |
|---|
| 37 | 23 | */ |
|---|
| 38 | 24 | |
|---|
| 39 | 25 | #include <linux/fs.h> |
|---|
| .. | .. |
|---|
| 212 | 198 | * callers. */ |
|---|
| 213 | 199 | if (S_ISDIR(mode)) |
|---|
| 214 | 200 | set_nlink(inode, 2); |
|---|
| 201 | + mode = mode_strip_sgid(dir, mode); |
|---|
| 215 | 202 | inode_init_owner(inode, dir, mode); |
|---|
| 216 | 203 | status = dquot_initialize(inode); |
|---|
| 217 | 204 | if (status) |
|---|
| .. | .. |
|---|
| 245 | 232 | handle_t *handle = NULL; |
|---|
| 246 | 233 | struct ocfs2_super *osb; |
|---|
| 247 | 234 | struct ocfs2_dinode *dirfe; |
|---|
| 235 | + struct ocfs2_dinode *fe = NULL; |
|---|
| 248 | 236 | struct buffer_head *new_fe_bh = NULL; |
|---|
| 249 | 237 | struct inode *inode = NULL; |
|---|
| 250 | 238 | struct ocfs2_alloc_context *inode_ac = NULL; |
|---|
| .. | .. |
|---|
| 254 | 242 | int want_meta = 0; |
|---|
| 255 | 243 | int xattr_credits = 0; |
|---|
| 256 | 244 | struct ocfs2_security_xattr_info si = { |
|---|
| 245 | + .name = NULL, |
|---|
| 257 | 246 | .enable = 1, |
|---|
| 258 | 247 | }; |
|---|
| 259 | 248 | int did_quota_inode = 0; |
|---|
| .. | .. |
|---|
| 395 | 384 | goto leave; |
|---|
| 396 | 385 | } |
|---|
| 397 | 386 | |
|---|
| 387 | + fe = (struct ocfs2_dinode *) new_fe_bh->b_data; |
|---|
| 398 | 388 | if (S_ISDIR(mode)) { |
|---|
| 399 | 389 | status = ocfs2_fill_new_dir(osb, handle, dir, inode, |
|---|
| 400 | 390 | new_fe_bh, data_ac, meta_ac); |
|---|
| .. | .. |
|---|
| 420 | 410 | |
|---|
| 421 | 411 | if (status < 0) { |
|---|
| 422 | 412 | mlog_errno(status); |
|---|
| 423 | | - goto leave; |
|---|
| 413 | + goto roll_back; |
|---|
| 424 | 414 | } |
|---|
| 425 | 415 | |
|---|
| 426 | 416 | if (si.enable) { |
|---|
| .. | .. |
|---|
| 428 | 418 | meta_ac, data_ac); |
|---|
| 429 | 419 | if (status < 0) { |
|---|
| 430 | 420 | mlog_errno(status); |
|---|
| 431 | | - goto leave; |
|---|
| 421 | + goto roll_back; |
|---|
| 432 | 422 | } |
|---|
| 433 | 423 | } |
|---|
| 434 | 424 | |
|---|
| .. | .. |
|---|
| 441 | 431 | OCFS2_I(dir)->ip_blkno); |
|---|
| 442 | 432 | if (status) { |
|---|
| 443 | 433 | mlog_errno(status); |
|---|
| 444 | | - goto leave; |
|---|
| 434 | + goto roll_back; |
|---|
| 445 | 435 | } |
|---|
| 446 | 436 | |
|---|
| 447 | 437 | dl = dentry->d_fsdata; |
|---|
| .. | .. |
|---|
| 451 | 441 | &lookup); |
|---|
| 452 | 442 | if (status < 0) { |
|---|
| 453 | 443 | mlog_errno(status); |
|---|
| 454 | | - goto leave; |
|---|
| 444 | + goto roll_back; |
|---|
| 455 | 445 | } |
|---|
| 456 | 446 | |
|---|
| 457 | 447 | insert_inode_hash(inode); |
|---|
| 458 | 448 | d_instantiate(dentry, inode); |
|---|
| 459 | 449 | status = 0; |
|---|
| 450 | + |
|---|
| 451 | +roll_back: |
|---|
| 452 | + if (status < 0 && S_ISDIR(mode)) { |
|---|
| 453 | + ocfs2_add_links_count(dirfe, -1); |
|---|
| 454 | + drop_nlink(dir); |
|---|
| 455 | + } |
|---|
| 456 | + |
|---|
| 460 | 457 | leave: |
|---|
| 461 | 458 | if (status < 0 && did_quota_inode) |
|---|
| 462 | 459 | dquot_free_inode(inode); |
|---|
| 463 | | - if (handle) |
|---|
| 460 | + if (handle) { |
|---|
| 461 | + if (status < 0 && fe) |
|---|
| 462 | + ocfs2_set_links_count(fe, 0); |
|---|
| 464 | 463 | ocfs2_commit_trans(osb, handle); |
|---|
| 464 | + } |
|---|
| 465 | 465 | |
|---|
| 466 | 466 | ocfs2_inode_unlock(dir, 1); |
|---|
| 467 | 467 | if (did_block_signals) |
|---|
| .. | .. |
|---|
| 600 | 600 | mlog_errno(status); |
|---|
| 601 | 601 | } |
|---|
| 602 | 602 | |
|---|
| 603 | | - oi->i_sync_tid = handle->h_transaction->t_tid; |
|---|
| 604 | | - oi->i_datasync_tid = handle->h_transaction->t_tid; |
|---|
| 603 | + ocfs2_update_inode_fsync_trans(handle, inode, 1); |
|---|
| 605 | 604 | |
|---|
| 606 | 605 | leave: |
|---|
| 607 | 606 | if (status < 0) { |
|---|
| .. | .. |
|---|
| 639 | 638 | return status; |
|---|
| 640 | 639 | } |
|---|
| 641 | 640 | |
|---|
| 642 | | - status = __ocfs2_mknod_locked(dir, inode, dev, new_fe_bh, |
|---|
| 641 | + return __ocfs2_mknod_locked(dir, inode, dev, new_fe_bh, |
|---|
| 643 | 642 | parent_fe_bh, handle, inode_ac, |
|---|
| 644 | 643 | fe_blkno, suballoc_loc, suballoc_bit); |
|---|
| 645 | | - if (status < 0) { |
|---|
| 646 | | - u64 bg_blkno = ocfs2_which_suballoc_group(fe_blkno, suballoc_bit); |
|---|
| 647 | | - int tmp = ocfs2_free_suballoc_bits(handle, inode_ac->ac_inode, |
|---|
| 648 | | - inode_ac->ac_bh, suballoc_bit, bg_blkno, 1); |
|---|
| 649 | | - if (tmp) |
|---|
| 650 | | - mlog_errno(tmp); |
|---|
| 651 | | - } |
|---|
| 652 | | - |
|---|
| 653 | | - return status; |
|---|
| 654 | 644 | } |
|---|
| 655 | 645 | |
|---|
| 656 | 646 | static int ocfs2_mkdir(struct inode *dir, |
|---|
| .. | .. |
|---|
| 1542 | 1532 | status = ocfs2_add_entry(handle, new_dentry, old_inode, |
|---|
| 1543 | 1533 | OCFS2_I(old_inode)->ip_blkno, |
|---|
| 1544 | 1534 | new_dir_bh, &target_insert); |
|---|
| 1535 | + if (status < 0) { |
|---|
| 1536 | + mlog_errno(status); |
|---|
| 1537 | + goto bail; |
|---|
| 1538 | + } |
|---|
| 1545 | 1539 | } |
|---|
| 1546 | 1540 | |
|---|
| 1547 | 1541 | old_inode->i_ctime = current_time(old_inode); |
|---|
| .. | .. |
|---|
| 1812 | 1806 | int want_clusters = 0; |
|---|
| 1813 | 1807 | int xattr_credits = 0; |
|---|
| 1814 | 1808 | struct ocfs2_security_xattr_info si = { |
|---|
| 1809 | + .name = NULL, |
|---|
| 1815 | 1810 | .enable = 1, |
|---|
| 1816 | 1811 | }; |
|---|
| 1817 | 1812 | int did_quota = 0, did_quota_inode = 0; |
|---|
| .. | .. |
|---|
| 2031 | 2026 | ocfs2_clusters_to_bytes(osb->sb, 1)); |
|---|
| 2032 | 2027 | if (status < 0 && did_quota_inode) |
|---|
| 2033 | 2028 | dquot_free_inode(inode); |
|---|
| 2034 | | - if (handle) |
|---|
| 2029 | + if (handle) { |
|---|
| 2030 | + if (status < 0 && fe) |
|---|
| 2031 | + ocfs2_set_links_count(fe, 0); |
|---|
| 2035 | 2032 | ocfs2_commit_trans(osb, handle); |
|---|
| 2033 | + } |
|---|
| 2036 | 2034 | |
|---|
| 2037 | 2035 | ocfs2_inode_unlock(dir, 1); |
|---|
| 2038 | 2036 | if (did_block_signals) |
|---|
| .. | .. |
|---|
| 2500 | 2498 | struct inode *inode = NULL; |
|---|
| 2501 | 2499 | struct inode *orphan_dir = NULL; |
|---|
| 2502 | 2500 | struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); |
|---|
| 2503 | | - struct ocfs2_dinode *di = NULL; |
|---|
| 2504 | 2501 | handle_t *handle = NULL; |
|---|
| 2505 | 2502 | char orphan_name[OCFS2_ORPHAN_NAMELEN + 1]; |
|---|
| 2506 | 2503 | struct buffer_head *parent_di_bh = NULL; |
|---|
| 2507 | 2504 | struct buffer_head *new_di_bh = NULL; |
|---|
| 2508 | 2505 | struct ocfs2_alloc_context *inode_ac = NULL; |
|---|
| 2509 | 2506 | struct ocfs2_dir_lookup_result orphan_insert = { NULL, }; |
|---|
| 2510 | | - u64 uninitialized_var(di_blkno), suballoc_loc; |
|---|
| 2507 | + u64 di_blkno, suballoc_loc; |
|---|
| 2511 | 2508 | u16 suballoc_bit; |
|---|
| 2512 | 2509 | |
|---|
| 2513 | 2510 | status = ocfs2_inode_lock(dir, &parent_di_bh, 1); |
|---|
| .. | .. |
|---|
| 2566 | 2563 | goto leave; |
|---|
| 2567 | 2564 | } |
|---|
| 2568 | 2565 | |
|---|
| 2569 | | - di = (struct ocfs2_dinode *)new_di_bh->b_data; |
|---|
| 2570 | 2566 | status = ocfs2_orphan_add(osb, handle, inode, new_di_bh, orphan_name, |
|---|
| 2571 | 2567 | &orphan_insert, orphan_dir, false); |
|---|
| 2572 | 2568 | if (status < 0) { |
|---|