]> www.infradead.org Git - users/hch/misc.git/commitdiff
bcachefs: Hook up RENAME_WHITEOUT in rename.
authorSasha Finkelstein <fnkl.kernel@gmail.com>
Sun, 18 Aug 2024 17:09:02 +0000 (19:09 +0200)
committerKent Overstreet <kent.overstreet@linux.dev>
Sat, 21 Sep 2024 15:35:20 +0000 (11:35 -0400)
This is needed for overlayfs, which is used by container managers.

Signed-off-by: Sasha Finkelstein <fnkl.kernel@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/btree_iter.h
fs/bcachefs/fs-common.c
fs/bcachefs/fs.c
fs/bcachefs/str_hash.h

index 6d87e57745da6f5673f360304d8b8907b7cf5fed..78e63ad7d380e47c481f33bb4f191e0e100c0e03 100644 (file)
@@ -529,6 +529,12 @@ void bch2_set_btree_iter_dontneed(struct btree_iter *);
 
 void *__bch2_trans_kmalloc(struct btree_trans *, size_t);
 
+/**
+ * bch2_trans_kmalloc - allocate memory for use by the current transaction
+ *
+ * Must be called after bch2_trans_begin, which on second and further calls
+ * frees all memory allocated in this transaction
+ */
 static inline void *bch2_trans_kmalloc(struct btree_trans *trans, size_t size)
 {
        size = roundup(size, 8);
index 508d029ac53d067226162bd69ba66f48faabcfa8..7e10a9ddcfd9633d13b9dce2dd0dab8fa58425b4 100644 (file)
@@ -42,7 +42,8 @@ int bch2_create_trans(struct btree_trans *trans,
        if (ret)
                goto err;
 
-       ret = bch2_inode_peek(trans, &dir_iter, dir_u, dir, BTREE_ITER_intent);
+       ret = bch2_inode_peek(trans, &dir_iter, dir_u, dir,
+                             BTREE_ITER_intent|BTREE_ITER_with_updates);
        if (ret)
                goto err;
 
@@ -163,7 +164,7 @@ int bch2_create_trans(struct btree_trans *trans,
                                         name,
                                         dir_target,
                                         &dir_offset,
-                                        STR_HASH_must_create);
+                                        STR_HASH_must_create|BTREE_ITER_with_updates);
                if (ret)
                        goto err;
 
index 866ce1f1a6d1828f7ded58ed386a0712e310119e..dfadfb82399f59fa0b833200bc34291e8ed40081 100644 (file)
@@ -736,15 +736,16 @@ static int bch2_rename2(struct mnt_idmap *idmap,
        struct bch_inode_info *src_inode = to_bch_ei(src_dentry->d_inode);
        struct bch_inode_info *dst_inode = to_bch_ei(dst_dentry->d_inode);
        struct bch_inode_unpacked dst_dir_u, src_dir_u;
-       struct bch_inode_unpacked src_inode_u, dst_inode_u;
+       struct bch_inode_unpacked src_inode_u, dst_inode_u, *whiteout_inode_u;
        struct btree_trans *trans;
        enum bch_rename_mode mode = flags & RENAME_EXCHANGE
                ? BCH_RENAME_EXCHANGE
                : dst_dentry->d_inode
                ? BCH_RENAME_OVERWRITE : BCH_RENAME;
+       bool whiteout = !!(flags & RENAME_WHITEOUT);
        int ret;
 
-       if (flags & ~(RENAME_NOREPLACE|RENAME_EXCHANGE))
+       if (flags & ~(RENAME_NOREPLACE|RENAME_EXCHANGE|RENAME_WHITEOUT))
                return -EINVAL;
 
        if (mode == BCH_RENAME_OVERWRITE) {
@@ -785,18 +786,48 @@ static int bch2_rename2(struct mnt_idmap *idmap,
                if (ret)
                        goto err;
        }
+retry:
+       bch2_trans_begin(trans);
 
-       ret = commit_do(trans, NULL, NULL, 0,
-                       bch2_rename_trans(trans,
-                                         inode_inum(src_dir), &src_dir_u,
-                                         inode_inum(dst_dir), &dst_dir_u,
-                                         &src_inode_u,
-                                         &dst_inode_u,
-                                         &src_dentry->d_name,
-                                         &dst_dentry->d_name,
-                                         mode));
+       ret = bch2_rename_trans(trans,
+                               inode_inum(src_dir), &src_dir_u,
+                               inode_inum(dst_dir), &dst_dir_u,
+                               &src_inode_u,
+                               &dst_inode_u,
+                               &src_dentry->d_name,
+                               &dst_dentry->d_name,
+                               mode);
        if (unlikely(ret))
+               goto err_tx_restart;
+
+       if (whiteout) {
+               whiteout_inode_u = bch2_trans_kmalloc_nomemzero(trans, sizeof(*whiteout_inode_u));
+               ret = PTR_ERR_OR_ZERO(whiteout_inode_u);
+               if (unlikely(ret))
+                       goto err_tx_restart;
+               bch2_inode_init_early(c, whiteout_inode_u);
+
+               ret = bch2_create_trans(trans,
+                                       inode_inum(src_dir), &src_dir_u,
+                                       whiteout_inode_u,
+                                       &src_dentry->d_name,
+                                       from_kuid(i_user_ns(&src_dir->v), current_fsuid()),
+                                       from_kgid(i_user_ns(&src_dir->v), current_fsgid()),
+                                       S_IFCHR|WHITEOUT_MODE, 0,
+                                       NULL, NULL, (subvol_inum) { 0 }, 0) ?:
+                     bch2_quota_acct(c, bch_qid(whiteout_inode_u), Q_INO, 1,
+                                     KEY_TYPE_QUOTA_PREALLOC);
+               if (unlikely(ret))
+                       goto err_tx_restart;
+       }
+
+       ret = bch2_trans_commit(trans, NULL, NULL, 0);
+       if (unlikely(ret)) {
+err_tx_restart:
+               if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
+                       goto retry;
                goto err;
+       }
 
        BUG_ON(src_inode->v.i_ino != src_inode_u.bi_inum);
        BUG_ON(dst_inode &&
index c8c266cb579726ee004ff67290ce61f0301869f1..215eed4cce6d2c4111980c56f88a2b6ec82f4fa2 100644 (file)
@@ -270,7 +270,7 @@ int bch2_hash_set_in_snapshot(struct btree_trans *trans,
                                desc.hash_bkey(info, bkey_i_to_s_c(insert)),
                                snapshot),
                           POS(insert->k.p.inode, U64_MAX),
-                          BTREE_ITER_slots|BTREE_ITER_intent, k, ret) {
+                          BTREE_ITER_slots|BTREE_ITER_intent|flags, k, ret) {
                if (is_visible_key(desc, inum, k)) {
                        if (!desc.cmp_bkey(k, bkey_i_to_s_c(insert)))
                                goto found;