diff options
author | Boaz Harrosh <bharrosh@panasas.com> | 2010-02-09 11:43:21 +0200 |
---|---|---|
committer | Boaz Harrosh <bharrosh@panasas.com> | 2010-02-28 03:44:43 -0800 |
commit | 96391e2bae0f8882b6f44809202a68be66e91dce (patch) | |
tree | f2a6ece9b3973143293e1221e992c60b07109429 | |
parent | 86093aaff5be5b214613eb60553e236bdb389c84 (diff) | |
download | op-kernel-dev-96391e2bae0f8882b6f44809202a68be66e91dce.zip op-kernel-dev-96391e2bae0f8882b6f44809202a68be66e91dce.tar.gz |
exofs: Error recovery if object is missing from storage
If an object is referenced by a directory but does not
exist on a target, it is a very serious corruption that
means:
1. Either a power failure with very slim chance of it
happening. Because the directory update is always submitted
much after object creation, but if a directory is written
to one device and the object creation to another it might
theoretically happen.
2. It only ever happened to me while developing with BUGs
causing file corruption. Crashes could also cause it but
they are more like case 1.
In any way the object does not exist, so data is surely lost.
If there is a mix-up in the obj-id or data-map, then lost objects
can be salvaged by off-line fsck. The only recoverable information
is the directory name. By letting it appear as a regular empty file,
with date==0 (1970 Jan 1st) ownership to root, we enable recovery
of the only useful information. And also enable deletion or over-write.
I can see how this can hurt.
Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
-rw-r--r-- | fs/exofs/inode.c | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index 6ca0b01..5514f3c 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c @@ -903,8 +903,18 @@ static int exofs_get_inode(struct super_block *sb, struct exofs_i_info *oi, ios->in_attr_len = ARRAY_SIZE(attrs); ret = exofs_sbi_read(ios); - if (ret) + if (unlikely(ret)) { + EXOFS_ERR("object(0x%llx) corrupted, return empty file=>%d\n", + _LLU(ios->obj.id), ret); + memset(inode, 0, sizeof(*inode)); + inode->i_mode = 0040000 | (0777 & ~022); + /* If object is lost on target we might as well enable it's + * delete. + */ + if ((ret == -ENOENT) || (ret == -EINVAL)) + ret = 0; goto out; + } ret = extract_attr_from_ios(ios, &attrs[0]); if (ret) { |