diff options
author | Filipe Manana <fdmanana@suse.com> | 2014-07-31 19:10:32 -0400 |
---|---|---|
committer | Chris Mason <clm@fb.com> | 2014-08-21 10:55:23 -0400 |
commit | 5762b5c958abbecb7fb9f4596a6476d1ce91ecf6 (patch) | |
tree | 95d976192dcee56ac34c23433a333aa20cd54650 /fs/btrfs/inode.c | |
parent | 9c3b306e1c9e6be4be09e99a8fe2227d1005effc (diff) |
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>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 15 |
1 files changed, 15 insertions, 0 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 6dd6e50d143a..57c3129ee2a2 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -5642,6 +5642,13 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, | |||
5642 | } | 5642 | } |
5643 | 5643 | ||
5644 | /* | 5644 | /* |
5645 | * O_TMPFILE, set link count to 0, so that after this point, | ||
5646 | * we fill in an inode item with the correct link count. | ||
5647 | */ | ||
5648 | if (!name) | ||
5649 | set_nlink(inode, 0); | ||
5650 | |||
5651 | /* | ||
5645 | * we have to initialize this early, so we can reclaim the inode | 5652 | * we have to initialize this early, so we can reclaim the inode |
5646 | * number if we fail afterwards in this function. | 5653 | * number if we fail afterwards in this function. |
5647 | */ | 5654 | */ |
@@ -9007,6 +9014,14 @@ static int btrfs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) | |||
9007 | if (ret) | 9014 | if (ret) |
9008 | goto out; | 9015 | goto out; |
9009 | 9016 | ||
9017 | /* | ||
9018 | * We set number of links to 0 in btrfs_new_inode(), and here we set | ||
9019 | * it to 1 because d_tmpfile() will issue a warning if the count is 0, | ||
9020 | * through: | ||
9021 | * | ||
9022 | * d_tmpfile() -> inode_dec_link_count() -> drop_nlink() | ||
9023 | */ | ||
9024 | set_nlink(inode, 1); | ||
9010 | d_tmpfile(dentry, inode); | 9025 | d_tmpfile(dentry, inode); |
9011 | mark_inode_dirty(inode); | 9026 | mark_inode_dirty(inode); |
9012 | 9027 | ||