f2fs: add F2FS_INLINE_DOTS to recover missing dot dentries
If f2fs was corrupted with missing dot dentries, it needs to recover them after fsck.f2fs detection. The underlying precedure is: 1. The fsck.f2fs remains F2FS_INLINE_DOTS flag in directory inode, if it detects missing dot dentries. 2. When f2fs looks up the corrupted directory, it triggers f2fs_add_link with proper inode numbers and their dot and dotdot names. 3. Once f2fs recovers the directory without errors, it removes F2FS_INLINE_DOTS finally. Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
@@ -1246,6 +1246,7 @@ enum {
|
||||
FI_FIRST_BLOCK_WRITTEN, /* indicate #0 data block was written */
|
||||
FI_DROP_CACHE, /* drop dirty page cache */
|
||||
FI_DATA_EXIST, /* indicate data exists */
|
||||
FI_INLINE_DOTS, /* indicate inline dot dentries */
|
||||
};
|
||||
|
||||
static inline void set_inode_flag(struct f2fs_inode_info *fi, int flag)
|
||||
@@ -1282,6 +1283,8 @@ static inline void get_inline_info(struct f2fs_inode_info *fi,
|
||||
set_inode_flag(fi, FI_INLINE_DENTRY);
|
||||
if (ri->i_inline & F2FS_DATA_EXIST)
|
||||
set_inode_flag(fi, FI_DATA_EXIST);
|
||||
if (ri->i_inline & F2FS_INLINE_DOTS)
|
||||
set_inode_flag(fi, FI_INLINE_DOTS);
|
||||
}
|
||||
|
||||
static inline void set_raw_inline(struct f2fs_inode_info *fi,
|
||||
@@ -1297,6 +1300,8 @@ static inline void set_raw_inline(struct f2fs_inode_info *fi,
|
||||
ri->i_inline |= F2FS_INLINE_DENTRY;
|
||||
if (is_inode_flag_set(fi, FI_DATA_EXIST))
|
||||
ri->i_inline |= F2FS_DATA_EXIST;
|
||||
if (is_inode_flag_set(fi, FI_INLINE_DOTS))
|
||||
ri->i_inline |= F2FS_INLINE_DOTS;
|
||||
}
|
||||
|
||||
static inline int f2fs_has_inline_xattr(struct inode *inode)
|
||||
@@ -1342,6 +1347,11 @@ static inline int f2fs_exist_data(struct inode *inode)
|
||||
return is_inode_flag_set(F2FS_I(inode), FI_DATA_EXIST);
|
||||
}
|
||||
|
||||
static inline int f2fs_has_inline_dots(struct inode *inode)
|
||||
{
|
||||
return is_inode_flag_set(F2FS_I(inode), FI_INLINE_DOTS);
|
||||
}
|
||||
|
||||
static inline bool f2fs_is_atomic_file(struct inode *inode)
|
||||
{
|
||||
return is_inode_flag_set(F2FS_I(inode), FI_ATOMIC_FILE);
|
||||
@@ -1440,7 +1450,7 @@ struct dentry *f2fs_get_parent(struct dentry *child);
|
||||
* dir.c
|
||||
*/
|
||||
extern unsigned char f2fs_filetype_table[F2FS_FT_MAX];
|
||||
void set_de_type(struct f2fs_dir_entry *, struct inode *);
|
||||
void set_de_type(struct f2fs_dir_entry *, umode_t);
|
||||
struct f2fs_dir_entry *find_target_dentry(struct qstr *, int *,
|
||||
struct f2fs_dentry_ptr *);
|
||||
bool f2fs_fill_dentries(struct dir_context *, struct f2fs_dentry_ptr *,
|
||||
@@ -1459,9 +1469,10 @@ ino_t f2fs_inode_by_name(struct inode *, struct qstr *);
|
||||
void f2fs_set_link(struct inode *, struct f2fs_dir_entry *,
|
||||
struct page *, struct inode *);
|
||||
int update_dent_inode(struct inode *, const struct qstr *);
|
||||
void f2fs_update_dentry(struct inode *, struct f2fs_dentry_ptr *,
|
||||
void f2fs_update_dentry(nid_t ino, umode_t mode, struct f2fs_dentry_ptr *,
|
||||
const struct qstr *, f2fs_hash_t , unsigned int);
|
||||
int __f2fs_add_link(struct inode *, const struct qstr *, struct inode *);
|
||||
int __f2fs_add_link(struct inode *, const struct qstr *, struct inode *, nid_t,
|
||||
umode_t);
|
||||
void f2fs_delete_entry(struct f2fs_dir_entry *, struct page *, struct inode *,
|
||||
struct inode *);
|
||||
int f2fs_do_tmpfile(struct inode *, struct inode *);
|
||||
@@ -1471,7 +1482,7 @@ bool f2fs_empty_dir(struct inode *);
|
||||
static inline int f2fs_add_link(struct dentry *dentry, struct inode *inode)
|
||||
{
|
||||
return __f2fs_add_link(dentry->d_parent->d_inode, &dentry->d_name,
|
||||
inode);
|
||||
inode, inode->i_ino, inode->i_mode);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1792,7 +1803,8 @@ struct f2fs_dir_entry *find_in_inline_dir(struct inode *, struct qstr *,
|
||||
struct page **);
|
||||
struct f2fs_dir_entry *f2fs_parent_inline_dir(struct inode *, struct page **);
|
||||
int make_empty_inline_dir(struct inode *inode, struct inode *, struct page *);
|
||||
int f2fs_add_inline_entry(struct inode *, const struct qstr *, struct inode *);
|
||||
int f2fs_add_inline_entry(struct inode *, const struct qstr *, struct inode *,
|
||||
nid_t, umode_t);
|
||||
void f2fs_delete_inline_entry(struct f2fs_dir_entry *, struct page *,
|
||||
struct inode *, struct inode *);
|
||||
bool f2fs_empty_inline_dir(struct inode *);
|
||||
|
||||
Reference in New Issue
Block a user