summaryrefslogtreecommitdiffstats
path: root/fs/hfsplus/extents.c
diff options
context:
space:
mode:
authorErnesto A. Fernández <ernesto.mnd.fernandez@gmail.com>2018-10-30 18:06:14 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-10-31 11:54:13 -0400
commitd92915c35bfaf763d78bf1d5ac7f183420e3bd99 (patch)
tree6c55bdd6cdbff28215f7a4df2c61ed31716ca09a /fs/hfsplus/extents.c
parentef75bcc5763d130451a99825f247d301088b790b (diff)
hfsplus: prevent btree data loss on ENOSPC
Inserting or deleting a record in a btree may require splitting several of its nodes. If we hit ENOSPC halfway through, the new nodes will be left orphaned and their records will be lost. This could mean lost inodes, extents or xattrs. Henceforth, check the available disk space before making any changes. This still leaves the potential problem of corruption on ENOMEM. The patch can be tested with xfstests generic/027. Link: http://lkml.kernel.org/r/4596eef22fbda137b4ffa0272d92f0da15364421.1536269129.git.ernesto.mnd.fernandez@gmail.com Signed-off-by: Ernesto A. Fernández <ernesto.mnd.fernandez@gmail.com> Cc: Christoph Hellwig <hch@lst.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/hfsplus/extents.c')
-rw-r--r--fs/hfsplus/extents.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c
index 8e0f59767694..8a8893d522ef 100644
--- a/fs/hfsplus/extents.c
+++ b/fs/hfsplus/extents.c
@@ -100,6 +100,10 @@ static int __hfsplus_ext_write_extent(struct inode *inode,
100 if (hip->extent_state & HFSPLUS_EXT_NEW) { 100 if (hip->extent_state & HFSPLUS_EXT_NEW) {
101 if (res != -ENOENT) 101 if (res != -ENOENT)
102 return res; 102 return res;
103 /* Fail early and avoid ENOSPC during the btree operation */
104 res = hfs_bmap_reserve(fd->tree, fd->tree->depth + 1);
105 if (res)
106 return res;
103 hfs_brec_insert(fd, hip->cached_extents, 107 hfs_brec_insert(fd, hip->cached_extents,
104 sizeof(hfsplus_extent_rec)); 108 sizeof(hfsplus_extent_rec));
105 hip->extent_state &= ~(HFSPLUS_EXT_DIRTY | HFSPLUS_EXT_NEW); 109 hip->extent_state &= ~(HFSPLUS_EXT_DIRTY | HFSPLUS_EXT_NEW);