196385742SKent Overstreet // SPDX-License-Identifier: GPL-2.0 296385742SKent Overstreet 396385742SKent Overstreet #include "bcachefs.h" 496385742SKent Overstreet #include "acl.h" 596385742SKent Overstreet #include "btree_update.h" 696385742SKent Overstreet #include "dirent.h" 796385742SKent Overstreet #include "fs-common.h" 896385742SKent Overstreet #include "inode.h" 996385742SKent Overstreet #include "xattr.h" 1096385742SKent Overstreet 1196385742SKent Overstreet #include <linux/posix_acl.h> 1296385742SKent Overstreet 1396385742SKent Overstreet int bch2_create_trans(struct btree_trans *trans, u64 dir_inum, 1496385742SKent Overstreet struct bch_inode_unpacked *dir_u, 1596385742SKent Overstreet struct bch_inode_unpacked *new_inode, 1696385742SKent Overstreet const struct qstr *name, 1796385742SKent Overstreet uid_t uid, gid_t gid, umode_t mode, dev_t rdev, 1896385742SKent Overstreet struct posix_acl *default_acl, 1996385742SKent Overstreet struct posix_acl *acl) 2096385742SKent Overstreet { 2196385742SKent Overstreet struct bch_fs *c = trans->c; 228b53852dSKent Overstreet struct btree_iter *dir_iter = NULL; 23ab2a29ccSKent Overstreet struct btree_iter *inode_iter = NULL; 2496385742SKent Overstreet struct bch_hash_info hash = bch2_hash_info_init(c, new_inode); 25ab2a29ccSKent Overstreet u64 now = bch2_current_time(c); 26ab2a29ccSKent Overstreet u64 dir_offset = 0; 2796385742SKent Overstreet int ret; 2896385742SKent Overstreet 2963fbf458SKent Overstreet dir_iter = bch2_inode_peek(trans, dir_u, dir_inum, BTREE_ITER_INTENT); 308b53852dSKent Overstreet ret = PTR_ERR_OR_ZERO(dir_iter); 318b53852dSKent Overstreet if (ret) 328b53852dSKent Overstreet goto err; 3396385742SKent Overstreet 3496385742SKent Overstreet bch2_inode_init_late(new_inode, now, uid, gid, mode, rdev, dir_u); 3596385742SKent Overstreet 3696385742SKent Overstreet if (!name) 3796385742SKent Overstreet new_inode->bi_flags |= BCH_INODE_UNLINKED; 3896385742SKent Overstreet 39e6ae2727SKent Overstreet inode_iter = bch2_inode_create(trans, new_inode, U32_MAX); 40ab2a29ccSKent Overstreet ret = PTR_ERR_OR_ZERO(inode_iter); 4196385742SKent Overstreet if (ret) 428b53852dSKent Overstreet goto err; 4396385742SKent Overstreet 4496385742SKent Overstreet if (default_acl) { 4596385742SKent Overstreet ret = bch2_set_acl_trans(trans, new_inode, &hash, 4696385742SKent Overstreet default_acl, ACL_TYPE_DEFAULT); 4796385742SKent Overstreet if (ret) 488b53852dSKent Overstreet goto err; 4996385742SKent Overstreet } 5096385742SKent Overstreet 5196385742SKent Overstreet if (acl) { 5296385742SKent Overstreet ret = bch2_set_acl_trans(trans, new_inode, &hash, 5396385742SKent Overstreet acl, ACL_TYPE_ACCESS); 5496385742SKent Overstreet if (ret) 558b53852dSKent Overstreet goto err; 5696385742SKent Overstreet } 5796385742SKent Overstreet 5896385742SKent Overstreet if (name) { 5996385742SKent Overstreet struct bch_hash_info dir_hash = bch2_hash_info_init(c, dir_u); 6096385742SKent Overstreet dir_u->bi_mtime = dir_u->bi_ctime = now; 6196385742SKent Overstreet 6296385742SKent Overstreet if (S_ISDIR(new_inode->bi_mode)) 6396385742SKent Overstreet dir_u->bi_nlink++; 6496385742SKent Overstreet 6596385742SKent Overstreet ret = bch2_inode_write(trans, dir_iter, dir_u); 6696385742SKent Overstreet if (ret) 678b53852dSKent Overstreet goto err; 6896385742SKent Overstreet 6996385742SKent Overstreet ret = bch2_dirent_create(trans, dir_inum, &dir_hash, 7096385742SKent Overstreet mode_to_type(new_inode->bi_mode), 7196385742SKent Overstreet name, new_inode->bi_inum, 72ab2a29ccSKent Overstreet &dir_offset, 7396385742SKent Overstreet BCH_HASH_SET_MUST_CREATE); 7496385742SKent Overstreet if (ret) 758b53852dSKent Overstreet goto err; 7696385742SKent Overstreet } 77ab2a29ccSKent Overstreet 78ab2a29ccSKent Overstreet if (c->sb.version >= bcachefs_metadata_version_inode_backpointers) { 79ab2a29ccSKent Overstreet new_inode->bi_dir = dir_u->bi_inum; 80ab2a29ccSKent Overstreet new_inode->bi_dir_offset = dir_offset; 81ab2a29ccSKent Overstreet } 82ab2a29ccSKent Overstreet 83e6ae2727SKent Overstreet /* XXX use bch2_btree_iter_set_snapshot() */ 84e6ae2727SKent Overstreet inode_iter->snapshot = U32_MAX; 85e6ae2727SKent Overstreet bch2_btree_iter_set_pos(inode_iter, SPOS(0, new_inode->bi_inum, U32_MAX)); 86e6ae2727SKent Overstreet 87ab2a29ccSKent Overstreet ret = bch2_inode_write(trans, inode_iter, new_inode); 888b53852dSKent Overstreet err: 89ab2a29ccSKent Overstreet bch2_trans_iter_put(trans, inode_iter); 908b53852dSKent Overstreet bch2_trans_iter_put(trans, dir_iter); 918b53852dSKent Overstreet return ret; 9296385742SKent Overstreet } 9396385742SKent Overstreet 9463fbf458SKent Overstreet int bch2_link_trans(struct btree_trans *trans, u64 dir_inum, 95184b1dc1SJustin Husted u64 inum, struct bch_inode_unpacked *dir_u, 96184b1dc1SJustin Husted struct bch_inode_unpacked *inode_u, const struct qstr *name) 9796385742SKent Overstreet { 98ab2a29ccSKent Overstreet struct bch_fs *c = trans->c; 998b53852dSKent Overstreet struct btree_iter *dir_iter = NULL, *inode_iter = NULL; 10096385742SKent Overstreet struct bch_hash_info dir_hash; 101ab2a29ccSKent Overstreet u64 now = bch2_current_time(c); 102ab2a29ccSKent Overstreet u64 dir_offset = 0; 1038b53852dSKent Overstreet int ret; 10496385742SKent Overstreet 10596385742SKent Overstreet inode_iter = bch2_inode_peek(trans, inode_u, inum, BTREE_ITER_INTENT); 1068b53852dSKent Overstreet ret = PTR_ERR_OR_ZERO(inode_iter); 1078b53852dSKent Overstreet if (ret) 1088b53852dSKent Overstreet goto err; 10996385742SKent Overstreet 11096385742SKent Overstreet inode_u->bi_ctime = now; 11196385742SKent Overstreet bch2_inode_nlink_inc(inode_u); 11296385742SKent Overstreet 113184b1dc1SJustin Husted dir_iter = bch2_inode_peek(trans, dir_u, dir_inum, 0); 1148b53852dSKent Overstreet ret = PTR_ERR_OR_ZERO(dir_iter); 1158b53852dSKent Overstreet if (ret) 1168b53852dSKent Overstreet goto err; 11763fbf458SKent Overstreet 118184b1dc1SJustin Husted dir_u->bi_mtime = dir_u->bi_ctime = now; 11963fbf458SKent Overstreet 120ab2a29ccSKent Overstreet dir_hash = bch2_hash_info_init(c, dir_u); 12163fbf458SKent Overstreet 1228b53852dSKent Overstreet ret = bch2_dirent_create(trans, dir_inum, &dir_hash, 12396385742SKent Overstreet mode_to_type(inode_u->bi_mode), 124ab2a29ccSKent Overstreet name, inum, &dir_offset, 125ab2a29ccSKent Overstreet BCH_HASH_SET_MUST_CREATE); 126ab2a29ccSKent Overstreet if (ret) 127ab2a29ccSKent Overstreet goto err; 128ab2a29ccSKent Overstreet 129ab2a29ccSKent Overstreet if (c->sb.version >= bcachefs_metadata_version_inode_backpointers) { 130ab2a29ccSKent Overstreet inode_u->bi_dir = dir_inum; 131ab2a29ccSKent Overstreet inode_u->bi_dir_offset = dir_offset; 132ab2a29ccSKent Overstreet } 133ab2a29ccSKent Overstreet 134ab2a29ccSKent Overstreet ret = bch2_inode_write(trans, dir_iter, dir_u) ?: 13596385742SKent Overstreet bch2_inode_write(trans, inode_iter, inode_u); 1368b53852dSKent Overstreet err: 1378b53852dSKent Overstreet bch2_trans_iter_put(trans, dir_iter); 1388b53852dSKent Overstreet bch2_trans_iter_put(trans, inode_iter); 1398b53852dSKent Overstreet return ret; 14096385742SKent Overstreet } 14196385742SKent Overstreet 14296385742SKent Overstreet int bch2_unlink_trans(struct btree_trans *trans, 14396385742SKent Overstreet u64 dir_inum, struct bch_inode_unpacked *dir_u, 14496385742SKent Overstreet struct bch_inode_unpacked *inode_u, 14596385742SKent Overstreet const struct qstr *name) 14696385742SKent Overstreet { 147ab2a29ccSKent Overstreet struct bch_fs *c = trans->c; 1488b53852dSKent Overstreet struct btree_iter *dir_iter = NULL, *dirent_iter = NULL, 1498b53852dSKent Overstreet *inode_iter = NULL; 15096385742SKent Overstreet struct bch_hash_info dir_hash; 151ab2a29ccSKent Overstreet u64 inum, now = bch2_current_time(c); 15296385742SKent Overstreet struct bkey_s_c k; 1538b53852dSKent Overstreet int ret; 15496385742SKent Overstreet 15596385742SKent Overstreet dir_iter = bch2_inode_peek(trans, dir_u, dir_inum, BTREE_ITER_INTENT); 1568b53852dSKent Overstreet ret = PTR_ERR_OR_ZERO(dir_iter); 1578b53852dSKent Overstreet if (ret) 1588b53852dSKent Overstreet goto err; 15996385742SKent Overstreet 160ab2a29ccSKent Overstreet dir_hash = bch2_hash_info_init(c, dir_u); 16196385742SKent Overstreet 16263fbf458SKent Overstreet dirent_iter = __bch2_dirent_lookup_trans(trans, dir_inum, &dir_hash, 16363fbf458SKent Overstreet name, BTREE_ITER_INTENT); 1648b53852dSKent Overstreet ret = PTR_ERR_OR_ZERO(dirent_iter); 1658b53852dSKent Overstreet if (ret) 1668b53852dSKent Overstreet goto err; 16796385742SKent Overstreet 16896385742SKent Overstreet k = bch2_btree_iter_peek_slot(dirent_iter); 16996385742SKent Overstreet inum = le64_to_cpu(bkey_s_c_to_dirent(k).v->d_inum); 17096385742SKent Overstreet 17196385742SKent Overstreet inode_iter = bch2_inode_peek(trans, inode_u, inum, BTREE_ITER_INTENT); 1728b53852dSKent Overstreet ret = PTR_ERR_OR_ZERO(inode_iter); 1738b53852dSKent Overstreet if (ret) 1748b53852dSKent Overstreet goto err; 17596385742SKent Overstreet 176d3ff7fecSKent Overstreet if (inode_u->bi_dir == k.k->p.inode && 177d3ff7fecSKent Overstreet inode_u->bi_dir_offset == k.k->p.offset) { 178d3ff7fecSKent Overstreet inode_u->bi_dir = 0; 179d3ff7fecSKent Overstreet inode_u->bi_dir_offset = 0; 180d3ff7fecSKent Overstreet } 181d3ff7fecSKent Overstreet 18296385742SKent Overstreet dir_u->bi_mtime = dir_u->bi_ctime = inode_u->bi_ctime = now; 18396385742SKent Overstreet dir_u->bi_nlink -= S_ISDIR(inode_u->bi_mode); 18496385742SKent Overstreet bch2_inode_nlink_dec(inode_u); 18596385742SKent Overstreet 1868b53852dSKent Overstreet ret = (S_ISDIR(inode_u->bi_mode) 18796385742SKent Overstreet ? bch2_empty_dir_trans(trans, inum) 18896385742SKent Overstreet : 0) ?: 18996385742SKent Overstreet bch2_dirent_delete_at(trans, &dir_hash, dirent_iter) ?: 19096385742SKent Overstreet bch2_inode_write(trans, dir_iter, dir_u) ?: 19196385742SKent Overstreet bch2_inode_write(trans, inode_iter, inode_u); 1928b53852dSKent Overstreet err: 1938b53852dSKent Overstreet bch2_trans_iter_put(trans, inode_iter); 1948b53852dSKent Overstreet bch2_trans_iter_put(trans, dirent_iter); 1958b53852dSKent Overstreet bch2_trans_iter_put(trans, dir_iter); 1968b53852dSKent Overstreet return ret; 19796385742SKent Overstreet } 19896385742SKent Overstreet 19996385742SKent Overstreet bool bch2_reinherit_attrs(struct bch_inode_unpacked *dst_u, 20096385742SKent Overstreet struct bch_inode_unpacked *src_u) 20196385742SKent Overstreet { 20296385742SKent Overstreet u64 src, dst; 20396385742SKent Overstreet unsigned id; 20496385742SKent Overstreet bool ret = false; 20596385742SKent Overstreet 20696385742SKent Overstreet for (id = 0; id < Inode_opt_nr; id++) { 20796385742SKent Overstreet if (dst_u->bi_fields_set & (1 << id)) 20896385742SKent Overstreet continue; 20996385742SKent Overstreet 21096385742SKent Overstreet src = bch2_inode_opt_get(src_u, id); 21196385742SKent Overstreet dst = bch2_inode_opt_get(dst_u, id); 21296385742SKent Overstreet 21396385742SKent Overstreet if (src == dst) 21496385742SKent Overstreet continue; 21596385742SKent Overstreet 21696385742SKent Overstreet bch2_inode_opt_set(dst_u, id, src); 21796385742SKent Overstreet ret = true; 21896385742SKent Overstreet } 21996385742SKent Overstreet 22096385742SKent Overstreet return ret; 22196385742SKent Overstreet } 22296385742SKent Overstreet 22396385742SKent Overstreet int bch2_rename_trans(struct btree_trans *trans, 22496385742SKent Overstreet u64 src_dir, struct bch_inode_unpacked *src_dir_u, 22596385742SKent Overstreet u64 dst_dir, struct bch_inode_unpacked *dst_dir_u, 22696385742SKent Overstreet struct bch_inode_unpacked *src_inode_u, 22796385742SKent Overstreet struct bch_inode_unpacked *dst_inode_u, 22896385742SKent Overstreet const struct qstr *src_name, 22996385742SKent Overstreet const struct qstr *dst_name, 23096385742SKent Overstreet enum bch_rename_mode mode) 23196385742SKent Overstreet { 232ab2a29ccSKent Overstreet struct bch_fs *c = trans->c; 2338b53852dSKent Overstreet struct btree_iter *src_dir_iter = NULL, *dst_dir_iter = NULL; 2348b53852dSKent Overstreet struct btree_iter *src_inode_iter = NULL, *dst_inode_iter = NULL; 23596385742SKent Overstreet struct bch_hash_info src_hash, dst_hash; 236ab2a29ccSKent Overstreet u64 src_inode, src_offset, dst_inode, dst_offset; 237ab2a29ccSKent Overstreet u64 now = bch2_current_time(c); 23896385742SKent Overstreet int ret; 23996385742SKent Overstreet 24096385742SKent Overstreet src_dir_iter = bch2_inode_peek(trans, src_dir_u, src_dir, 24196385742SKent Overstreet BTREE_ITER_INTENT); 2428b53852dSKent Overstreet ret = PTR_ERR_OR_ZERO(src_dir_iter); 2438b53852dSKent Overstreet if (ret) 2448b53852dSKent Overstreet goto err; 24596385742SKent Overstreet 246ab2a29ccSKent Overstreet src_hash = bch2_hash_info_init(c, src_dir_u); 24796385742SKent Overstreet 24896385742SKent Overstreet if (dst_dir != src_dir) { 24996385742SKent Overstreet dst_dir_iter = bch2_inode_peek(trans, dst_dir_u, dst_dir, 25096385742SKent Overstreet BTREE_ITER_INTENT); 2518b53852dSKent Overstreet ret = PTR_ERR_OR_ZERO(dst_dir_iter); 2528b53852dSKent Overstreet if (ret) 2538b53852dSKent Overstreet goto err; 25496385742SKent Overstreet 255ab2a29ccSKent Overstreet dst_hash = bch2_hash_info_init(c, dst_dir_u); 25696385742SKent Overstreet } else { 25796385742SKent Overstreet dst_dir_u = src_dir_u; 25896385742SKent Overstreet dst_hash = src_hash; 25996385742SKent Overstreet } 26096385742SKent Overstreet 26196385742SKent Overstreet ret = bch2_dirent_rename(trans, 26296385742SKent Overstreet src_dir, &src_hash, 26396385742SKent Overstreet dst_dir, &dst_hash, 264ab2a29ccSKent Overstreet src_name, &src_inode, &src_offset, 265ab2a29ccSKent Overstreet dst_name, &dst_inode, &dst_offset, 26696385742SKent Overstreet mode); 26796385742SKent Overstreet if (ret) 2688b53852dSKent Overstreet goto err; 26996385742SKent Overstreet 27096385742SKent Overstreet src_inode_iter = bch2_inode_peek(trans, src_inode_u, src_inode, 27196385742SKent Overstreet BTREE_ITER_INTENT); 2728b53852dSKent Overstreet ret = PTR_ERR_OR_ZERO(src_inode_iter); 2738b53852dSKent Overstreet if (ret) 2748b53852dSKent Overstreet goto err; 27596385742SKent Overstreet 27696385742SKent Overstreet if (dst_inode) { 27796385742SKent Overstreet dst_inode_iter = bch2_inode_peek(trans, dst_inode_u, dst_inode, 27896385742SKent Overstreet BTREE_ITER_INTENT); 2798b53852dSKent Overstreet ret = PTR_ERR_OR_ZERO(dst_inode_iter); 2808b53852dSKent Overstreet if (ret) 2818b53852dSKent Overstreet goto err; 28296385742SKent Overstreet } 28396385742SKent Overstreet 284ab2a29ccSKent Overstreet if (c->sb.version >= bcachefs_metadata_version_inode_backpointers) { 285ab2a29ccSKent Overstreet src_inode_u->bi_dir = dst_dir_u->bi_inum; 286ab2a29ccSKent Overstreet src_inode_u->bi_dir_offset = dst_offset; 287ab2a29ccSKent Overstreet 288ab2a29ccSKent Overstreet if (mode == BCH_RENAME_EXCHANGE) { 289ab2a29ccSKent Overstreet dst_inode_u->bi_dir = src_dir_u->bi_inum; 290ab2a29ccSKent Overstreet dst_inode_u->bi_dir_offset = src_offset; 291ab2a29ccSKent Overstreet } 292*16ac8c95SKent Overstreet 293*16ac8c95SKent Overstreet if (mode == BCH_RENAME_OVERWRITE && 294*16ac8c95SKent Overstreet dst_inode_u->bi_dir == dst_dir_u->bi_inum && 295*16ac8c95SKent Overstreet dst_inode_u->bi_dir_offset == src_offset) { 296*16ac8c95SKent Overstreet dst_inode_u->bi_dir = 0; 297*16ac8c95SKent Overstreet dst_inode_u->bi_dir_offset = 0; 298*16ac8c95SKent Overstreet } 299ab2a29ccSKent Overstreet } 300ab2a29ccSKent Overstreet 30196385742SKent Overstreet if (mode == BCH_RENAME_OVERWRITE) { 30296385742SKent Overstreet if (S_ISDIR(src_inode_u->bi_mode) != 3038b53852dSKent Overstreet S_ISDIR(dst_inode_u->bi_mode)) { 3048b53852dSKent Overstreet ret = -ENOTDIR; 3058b53852dSKent Overstreet goto err; 3068b53852dSKent Overstreet } 30796385742SKent Overstreet 30896385742SKent Overstreet if (S_ISDIR(dst_inode_u->bi_mode) && 3098b53852dSKent Overstreet bch2_empty_dir_trans(trans, dst_inode)) { 3108b53852dSKent Overstreet ret = -ENOTEMPTY; 3118b53852dSKent Overstreet goto err; 3128b53852dSKent Overstreet } 31396385742SKent Overstreet } 31496385742SKent Overstreet 31596385742SKent Overstreet if (bch2_reinherit_attrs(src_inode_u, dst_dir_u) && 3168b53852dSKent Overstreet S_ISDIR(src_inode_u->bi_mode)) { 3178b53852dSKent Overstreet ret = -EXDEV; 3188b53852dSKent Overstreet goto err; 3198b53852dSKent Overstreet } 32096385742SKent Overstreet 32196385742SKent Overstreet if (mode == BCH_RENAME_EXCHANGE && 32296385742SKent Overstreet bch2_reinherit_attrs(dst_inode_u, src_dir_u) && 3238b53852dSKent Overstreet S_ISDIR(dst_inode_u->bi_mode)) { 3248b53852dSKent Overstreet ret = -EXDEV; 3258b53852dSKent Overstreet goto err; 3268b53852dSKent Overstreet } 32796385742SKent Overstreet 32896385742SKent Overstreet if (S_ISDIR(src_inode_u->bi_mode)) { 32996385742SKent Overstreet src_dir_u->bi_nlink--; 33096385742SKent Overstreet dst_dir_u->bi_nlink++; 33196385742SKent Overstreet } 33296385742SKent Overstreet 33396385742SKent Overstreet if (dst_inode && S_ISDIR(dst_inode_u->bi_mode)) { 33496385742SKent Overstreet dst_dir_u->bi_nlink--; 33596385742SKent Overstreet src_dir_u->bi_nlink += mode == BCH_RENAME_EXCHANGE; 33696385742SKent Overstreet } 33796385742SKent Overstreet 33896385742SKent Overstreet if (mode == BCH_RENAME_OVERWRITE) 33996385742SKent Overstreet bch2_inode_nlink_dec(dst_inode_u); 34096385742SKent Overstreet 34196385742SKent Overstreet src_dir_u->bi_mtime = now; 34296385742SKent Overstreet src_dir_u->bi_ctime = now; 34396385742SKent Overstreet 34496385742SKent Overstreet if (src_dir != dst_dir) { 34596385742SKent Overstreet dst_dir_u->bi_mtime = now; 34696385742SKent Overstreet dst_dir_u->bi_ctime = now; 34796385742SKent Overstreet } 34896385742SKent Overstreet 34996385742SKent Overstreet src_inode_u->bi_ctime = now; 35096385742SKent Overstreet 35196385742SKent Overstreet if (dst_inode) 35296385742SKent Overstreet dst_inode_u->bi_ctime = now; 35396385742SKent Overstreet 3548b53852dSKent Overstreet ret = bch2_inode_write(trans, src_dir_iter, src_dir_u) ?: 35596385742SKent Overstreet (src_dir != dst_dir 35696385742SKent Overstreet ? bch2_inode_write(trans, dst_dir_iter, dst_dir_u) 35796385742SKent Overstreet : 0 ) ?: 35896385742SKent Overstreet bch2_inode_write(trans, src_inode_iter, src_inode_u) ?: 35996385742SKent Overstreet (dst_inode 36096385742SKent Overstreet ? bch2_inode_write(trans, dst_inode_iter, dst_inode_u) 36196385742SKent Overstreet : 0 ); 3628b53852dSKent Overstreet err: 3638b53852dSKent Overstreet bch2_trans_iter_put(trans, dst_inode_iter); 3648b53852dSKent Overstreet bch2_trans_iter_put(trans, src_inode_iter); 3658b53852dSKent Overstreet bch2_trans_iter_put(trans, dst_dir_iter); 3668b53852dSKent Overstreet bch2_trans_iter_put(trans, src_dir_iter); 3678b53852dSKent Overstreet return ret; 36896385742SKent Overstreet } 369