Skip to content

Commit 4e5a190

Browse files
committed
btrfs-progs: allow new inodes to inherit flags from their parents
Inside btrfs-progs (mostly 'mkfs/rootdir.c') new inodes are created in a different way than the kernel: - A new orphan inode item is created Without knowing the parent inode, thus it will always have the default flags (0). - Link the new inode to a parent Meanwhile inside the kernel, we know exactly the parent inode at new inode creation time, and can inherit the inode flags (NODATACOW/NODATASUM/COMPRESS/etc). Address the missing ability by: - Inherit the parent inode flags when linking an orphan inode The function btrfs_add_link() is called when linking an inode. It can be called to creating the initial link if it's a new and orphan inode. It can also be called to creating extra hard links. If the inode is already orphan, we know it's newly created and should inherit the inode flag from the parent. With this new ability, it will be much easier to implement new per-inode flags (like NODATACOW/NODATASUM) and get them properly passed down. Signed-off-by: Qu Wenruo <[email protected]>
1 parent 2c8f5c7 commit 4e5a190

File tree

1 file changed

+64
-0
lines changed

1 file changed

+64
-0
lines changed

kernel-shared/inode.c

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,59 @@ int btrfs_check_dir_conflict(struct btrfs_root *root, const char *name,
158158
return ret;
159159
}
160160

161+
/* Similiar to btrfs_inherit_iflags(), but different interfaces. */
162+
static int inherit_inode_flags(struct btrfs_trans_handle *trans,
163+
struct btrfs_root *root, u64 ino, u64 parent_ino)
164+
{
165+
struct btrfs_path path = { 0 };
166+
struct btrfs_key key;
167+
struct btrfs_inode_item *iitem;
168+
u64 parent_inode_flags;
169+
u64 child_inode_flags;
170+
int ret;
171+
172+
key.objectid = parent_ino;
173+
key.type = BTRFS_INODE_ITEM_KEY;
174+
key.offset = 0;
175+
176+
ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0);
177+
if (ret > 0)
178+
ret = -ENOENT;
179+
if (ret < 0)
180+
goto out;
181+
182+
iitem = btrfs_item_ptr(path.nodes[0], path.slots[0], struct btrfs_inode_item);
183+
parent_inode_flags = btrfs_inode_flags(path.nodes[0], iitem);
184+
btrfs_release_path(&path);
185+
186+
key.objectid = ino;
187+
188+
ret = btrfs_search_slot(trans, root, &key, &path, 0, 1);
189+
if (ret > 0)
190+
ret = -ENOENT;
191+
if (ret < 0)
192+
goto out;
193+
iitem = btrfs_item_ptr(path.nodes[0], path.slots[0], struct btrfs_inode_item);
194+
child_inode_flags = btrfs_inode_flags(path.nodes[0], iitem);
195+
196+
if (parent_inode_flags & BTRFS_INODE_NOCOMPRESS) {
197+
child_inode_flags &= ~BTRFS_INODE_COMPRESS;
198+
child_inode_flags |= BTRFS_INODE_NOCOMPRESS;
199+
} else if (parent_inode_flags & BTRFS_INODE_COMPRESS){
200+
child_inode_flags &= ~BTRFS_INODE_NOCOMPRESS;
201+
child_inode_flags |= BTRFS_INODE_COMPRESS;
202+
}
203+
if (parent_inode_flags & BTRFS_INODE_NODATACOW) {
204+
child_inode_flags |= BTRFS_INODE_NODATACOW;
205+
if (S_ISREG(btrfs_inode_mode(path.nodes[0], iitem)))
206+
child_inode_flags |= BTRFS_INODE_NODATASUM;
207+
}
208+
btrfs_set_inode_flags(path.nodes[0], iitem, child_inode_flags);
209+
out:
210+
btrfs_release_path(&path);
211+
return ret;
212+
}
213+
161214
/*
162215
* Add dir_item/index for 'parent_ino' if add_backref is true, also insert a
163216
* backref from the ino to parent dir and update the nlink(Kernel version does
@@ -220,6 +273,17 @@ int btrfs_add_link(struct btrfs_trans_handle *trans, struct btrfs_root *root,
220273
nlink);
221274
btrfs_mark_buffer_dirty(path->nodes[0]);
222275
btrfs_release_path(path);
276+
/*
277+
* If this is the first nlink of the inode, meaning the
278+
* inode is newly created under the parent inode, this
279+
* new child inode should inherit the inode flags from
280+
* the parent.
281+
*/
282+
if (nlink == 1) {
283+
ret = inherit_inode_flags(trans, root, ino, parent_ino);
284+
if (ret < 0)
285+
goto out;
286+
}
223287
}
224288
}
225289

0 commit comments

Comments
 (0)