diff options
author | Su Yue <suy.fnst@cn.fujitsu.com> | 2017-08-28 15:48:16 +0800 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2017-10-16 20:33:00 +0200 |
commit | cac2b0390de8cd4f9a79ddf7e9a6a6e9522cef56 (patch) | |
tree | ba6d784a3facca5fc85582bdc4044c86be7abf35 | |
parent | 3efc459166ad8d104912ec06c4ec9e0db6b7ef79 (diff) |
btrfs-progs: check: introduce repair_inode_item_missing()
Introduce __create_inode_item() to create a new inode item.
It is called by create_inode_item() and create_inode_item_lowmem().
Function repair_inode_item_missing() just adds a new inode item.
Signed-off-by: Su Yue <suy.fnst@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.com>
-rw-r--r-- | cmds-check.c | 128 |
1 files changed, 96 insertions, 32 deletions
diff --git a/cmds-check.c b/cmds-check.c index 4f3958b9..17ce0bb1 100644 --- a/cmds-check.c +++ b/cmds-check.c @@ -2691,13 +2691,54 @@ static int delete_dir_index(struct btrfs_root *root, return ret; } +static int __create_inode_item(struct btrfs_trans_handle *trans, + struct btrfs_root *root, u64 ino, u64 size, + u64 nbytes, u64 nlink, u32 mode) +{ + struct btrfs_inode_item ii; + time_t now = time(NULL); + int ret; + + btrfs_set_stack_inode_size(&ii, size); + btrfs_set_stack_inode_nbytes(&ii, nbytes); + btrfs_set_stack_inode_nlink(&ii, nlink); + btrfs_set_stack_inode_mode(&ii, mode); + btrfs_set_stack_inode_generation(&ii, trans->transid); + btrfs_set_stack_timespec_nsec(&ii.atime, 0); + btrfs_set_stack_timespec_sec(&ii.ctime, now); + btrfs_set_stack_timespec_nsec(&ii.ctime, 0); + btrfs_set_stack_timespec_sec(&ii.mtime, now); + btrfs_set_stack_timespec_nsec(&ii.mtime, 0); + btrfs_set_stack_timespec_sec(&ii.otime, 0); + btrfs_set_stack_timespec_nsec(&ii.otime, 0); + + ret = btrfs_insert_inode(trans, root, ino, &ii); + ASSERT(!ret); + + warning("root %llu inode %llu recreating inode item, this may " + "be incomplete, please check permissions and content after " + "the fsck completes.\n", (unsigned long long)root->objectid, + (unsigned long long)ino); + + return 0; +} + +static int create_inode_item_lowmem(struct btrfs_trans_handle *trans, + struct btrfs_root *root, u64 ino, + u8 filetype) +{ + u32 mode = (filetype == BTRFS_FT_DIR ? S_IFDIR : S_IFREG) | 0755; + + return __create_inode_item(trans, root, ino, 0, 0, 0, mode); +} + static int create_inode_item(struct btrfs_root *root, - struct inode_record *rec, - int root_dir) + struct inode_record *rec, int root_dir) { struct btrfs_trans_handle *trans; - struct btrfs_inode_item inode_item; - time_t now = time(NULL); + u64 nlink = 0; + u32 mode = 0; + u64 size = 0; int ret; trans = btrfs_start_transaction(root, 1); @@ -2706,18 +2747,7 @@ static int create_inode_item(struct btrfs_root *root, return ret; } - fprintf(stderr, "root %llu inode %llu recreating inode item, this may " - "be incomplete, please check permissions and content after " - "the fsck completes.\n", (unsigned long long)root->objectid, - (unsigned long long)rec->ino); - - memset(&inode_item, 0, sizeof(inode_item)); - btrfs_set_stack_inode_generation(&inode_item, trans->transid); - if (root_dir) - btrfs_set_stack_inode_nlink(&inode_item, 1); - else - btrfs_set_stack_inode_nlink(&inode_item, rec->found_link); - btrfs_set_stack_inode_nbytes(&inode_item, rec->found_size); + nlink = root_dir ? 1 : rec->found_link; if (rec->found_dir_item) { if (rec->found_file_extent) fprintf(stderr, "root %llu inode %llu has both a dir " @@ -2725,23 +2755,15 @@ static int create_inode_item(struct btrfs_root *root, "regular file so setting it as a directory\n", (unsigned long long)root->objectid, (unsigned long long)rec->ino); - btrfs_set_stack_inode_mode(&inode_item, S_IFDIR | 0755); - btrfs_set_stack_inode_size(&inode_item, rec->found_size); + mode = S_IFDIR | 0755; + size = rec->found_size; } else if (!rec->found_dir_item) { - btrfs_set_stack_inode_size(&inode_item, rec->extent_end); - btrfs_set_stack_inode_mode(&inode_item, S_IFREG | 0755); - } - btrfs_set_stack_timespec_sec(&inode_item.atime, now); - btrfs_set_stack_timespec_nsec(&inode_item.atime, 0); - btrfs_set_stack_timespec_sec(&inode_item.ctime, now); - btrfs_set_stack_timespec_nsec(&inode_item.ctime, 0); - btrfs_set_stack_timespec_sec(&inode_item.mtime, now); - btrfs_set_stack_timespec_nsec(&inode_item.mtime, 0); - btrfs_set_stack_timespec_sec(&inode_item.otime, 0); - btrfs_set_stack_timespec_nsec(&inode_item.otime, 0); - - ret = btrfs_insert_inode(trans, root, rec->ino, &inode_item); - BUG_ON(ret); + size = rec->extent_end; + mode = S_IFREG | 0755; + } + + ret = __create_inode_item(trans, root, rec->ino, size, rec->nbytes, + nlink, mode); btrfs_commit_transaction(trans, root); return 0; } @@ -4469,6 +4491,48 @@ static void print_inode_ref_err(struct btrfs_root *root, struct btrfs_key *key, } /* + * Insert the missing inode item. + * + * Returns 0 means success. + * Returns <0 means error. + */ +static int repair_inode_item_missing(struct btrfs_root *root, u64 ino, + u8 filetype) +{ + struct btrfs_key key; + struct btrfs_trans_handle *trans; + struct btrfs_path path; + int ret; + + key.objectid = ino; + key.type = BTRFS_INODE_ITEM_KEY; + key.offset = 0; + + btrfs_init_path(&path); + trans = btrfs_start_transaction(root, 1); + if (IS_ERR(trans)) { + ret = -EIO; + goto out; + } + + ret = btrfs_search_slot(trans, root, &key, &path, 1, 1); + if (ret < 0 || !ret) + goto fail; + + /* insert inode item */ + create_inode_item_lowmem(trans, root, ino, filetype); + ret = 0; +fail: + btrfs_commit_transaction(trans, root); +out: + if (ret) + error("failed to repair root %llu INODE ITEM[%llu] missing", + root->objectid, ino); + btrfs_release_path(&path); + return ret; +} + +/* * Traverse the given INODE_REF and call find_dir_item() to find related * DIR_ITEM/DIR_INDEX. * |