Btrfs: ensure tmpfile inode is always persisted with link count of 0
If we open a file with O_TMPFILE, don't do any further operation on it (so that the inode item isn't updated) and then force a transaction commit, we get a persisted inode item with a link count of 1, and not 0 as it should be. Steps to reproduce it (requires a modern xfs_io with -T support): $ mkfs.btrfs -f /dev/sdd $ mount -o /dev/sdd /mnt $ xfs_io -T /mnt & $ sync Then btrfs-debug-tree shows the inode item with a link count of 1: $ btrfs-debug-tree /dev/sdd (...) fs tree key (FS_TREE ROOT_ITEM 0) leaf 29556736 items 4 free space 15851 generation 6 owner 5 fs uuid f164d01b-1b92-481d-a4e4-435fb0f843d0 chunk uuid 0e3d0e56-bcca-4a1c-aa5f-cec2c6f4f7a6 item 0 key (256 INODE_ITEM 0) itemoff 16123 itemsize 160 inode generation 3 transid 6 size 0 block group 0 mode 40755 links 1 item 1 key (256 INODE_REF 256) itemoff 16111 itemsize 12 inode ref index 0 namelen 2 name: .. item 2 key (257 INODE_ITEM 0) itemoff 15951 itemsize 160 inode generation 6 transid 6 size 0 block group 0 mode 100600 links 1 item 3 key (ORPHAN ORPHAN_ITEM 257) itemoff 15951 itemsize 0 orphan item checksum tree key (CSUM_TREE ROOT_ITEM 0) (...) Signed-off-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: Chris Mason <clm@fb.com>
This commit is contained in:
parent
9c3b306e1c
commit
5762b5c958
|
@ -5641,6 +5641,13 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
|
|||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
/*
|
||||
* O_TMPFILE, set link count to 0, so that after this point,
|
||||
* we fill in an inode item with the correct link count.
|
||||
*/
|
||||
if (!name)
|
||||
set_nlink(inode, 0);
|
||||
|
||||
/*
|
||||
* we have to initialize this early, so we can reclaim the inode
|
||||
* number if we fail afterwards in this function.
|
||||
|
@ -9007,6 +9014,14 @@ static int btrfs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
|
|||
if (ret)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* We set number of links to 0 in btrfs_new_inode(), and here we set
|
||||
* it to 1 because d_tmpfile() will issue a warning if the count is 0,
|
||||
* through:
|
||||
*
|
||||
* d_tmpfile() -> inode_dec_link_count() -> drop_nlink()
|
||||
*/
|
||||
set_nlink(inode, 1);
|
||||
d_tmpfile(dentry, inode);
|
||||
mark_inode_dirty(inode);
|
||||
|
||||
|
|
Loading…
Reference in New Issue