Re: [PATCH v3] f2fs: add an ioctl to disable GC for specific file

2018-01-03 Thread Jaegeuk Kim
On 01/03, Chao Yu wrote:
> On 2018/1/3 11:21, Jaegeuk Kim wrote:
> > This patch gives a flag to disable GC on given file, which would be useful, 
> > when
> > user wants to keep its block map. It also conducts in-place-update for 
> > dontmove
> > file.
> > 
> > Signed-off-by: Jaegeuk Kim 
> > ---
> > 
> > Change log from v2:
> >  - modify ioctl to allow users unpin the file
> > 
> >  fs/f2fs/data.c  |  2 ++
> >  fs/f2fs/f2fs.h  | 28 +-
> >  fs/f2fs/file.c  | 64 
> > +
> >  fs/f2fs/gc.c| 11 +
> >  fs/f2fs/gc.h|  2 ++
> >  fs/f2fs/sysfs.c |  2 ++
> >  include/linux/f2fs_fs.h |  9 ++-
> >  7 files changed, 116 insertions(+), 2 deletions(-)
> > 
> > diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> > index 449b0aaa3905..45f65a5b9871 100644
> > --- a/fs/f2fs/data.c
> > +++ b/fs/f2fs/data.c
> > @@ -1395,6 +1395,8 @@ static inline bool need_inplace_update(struct 
> > f2fs_io_info *fio)
> >  {
> > struct inode *inode = fio->page->mapping->host;
> >  
> > +   if (f2fs_is_pinned_file(inode))
> > +   return true;
> > if (S_ISDIR(inode->i_mode) || f2fs_is_atomic_file(inode))
> > return false;
> > if (is_cold_data(fio->page))
> > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> > index a0e8eec23125..f4b7d73695a7 100644
> > --- a/fs/f2fs/f2fs.h
> > +++ b/fs/f2fs/f2fs.h
> > @@ -350,6 +350,7 @@ static inline bool __has_cursum_space(struct 
> > f2fs_journal *journal,
> >  #define F2FS_IOC_GARBAGE_COLLECT_RANGE _IOW(F2FS_IOCTL_MAGIC, 11,  
> > \
> > struct f2fs_gc_range)
> >  #define F2FS_IOC_GET_FEATURES  _IOR(F2FS_IOCTL_MAGIC, 12, 
> > __u32)
> > +#define F2FS_IOC_SET_PIN_FILE  _IOW(F2FS_IOCTL_MAGIC, 13, 
> > __u32)
> >  
> >  #define F2FS_IOC_SET_ENCRYPTION_POLICY FS_IOC_SET_ENCRYPTION_POLICY
> >  #define F2FS_IOC_GET_ENCRYPTION_POLICY FS_IOC_GET_ENCRYPTION_POLICY
> > @@ -587,7 +588,10 @@ struct f2fs_inode_info {
> > unsigned long i_flags;  /* keep an inode flags for ioctl */
> > unsigned char i_advise; /* use to give file attribute hints */
> > unsigned char i_dir_level;  /* use for dentry level for large dir */
> > -   unsigned int i_current_depth;   /* use only in directory structure */
> > +   union {
> > +   unsigned int i_current_depth;   /* only for directory depth */
> > +   unsigned short i_gc_failures;   /* only for regular file */
> > +   };
> > unsigned int i_pino;/* parent inode number */
> > umode_t i_acl_mode; /* keep file acl mode temporarily */
> >  
> > @@ -1133,6 +1137,9 @@ struct f2fs_sb_info {
> > /* threshold for converting bg victims for fg */
> > u64 fggc_threshold;
> >  
> > +   /* threshold for gc trials on pinned files */
> > +   u64 gc_pin_file_threshold;
> > +
> > /* maximum # of trials to find a victim segment for SSR and GC */
> > unsigned int max_victim_search;
> >  
> > @@ -2124,6 +2131,7 @@ enum {
> > FI_HOT_DATA,/* indicate file is hot */
> > FI_EXTRA_ATTR,  /* indicate file has extra attribute */
> > FI_PROJ_INHERIT,/* indicate file inherits projectid */
> > +   FI_PIN_FILE,/* indicate file should not be gced */
> >  };
> >  
> >  static inline void __mark_inode_dirty_flag(struct inode *inode,
> > @@ -2137,6 +2145,7 @@ static inline void __mark_inode_dirty_flag(struct 
> > inode *inode,
> > return;
> > case FI_DATA_EXIST:
> > case FI_INLINE_DOTS:
> > +   case FI_PIN_FILE:
> > f2fs_mark_inode_dirty_sync(inode, true);
> > }
> >  }
> > @@ -2217,6 +2226,13 @@ static inline void f2fs_i_depth_write(struct inode 
> > *inode, unsigned int depth)
> > f2fs_mark_inode_dirty_sync(inode, true);
> >  }
> >  
> > +static inline void f2fs_i_gc_failures_write(struct inode *inode,
> > +   unsigned int count)
> > +{
> > +   F2FS_I(inode)->i_gc_failures = count;
> > +   f2fs_mark_inode_dirty_sync(inode, true);
> > +}
> > +
> >  static inline void f2fs_i_xnid_write(struct inode *inode, nid_t xnid)
> >  {
> > F2FS_I(inode)->i_xattr_nid = xnid;
> > @@ -2245,6 +2261,8 @@ static inline void get_inline_info(struct inode 
> > *inode, struct f2fs_inode *ri)
> > set_bit(FI_INLINE_DOTS, &fi->flags);
> > if (ri->i_inline & F2FS_EXTRA_ATTR)
> > set_bit(FI_EXTRA_ATTR, &fi->flags);
> > +   if (ri->i_inline & F2FS_PIN_FILE)
> > +   set_bit(FI_PIN_FILE, &fi->flags);
> >  }
> >  
> >  static inline void set_raw_inline(struct inode *inode, struct f2fs_inode 
> > *ri)
> > @@ -2263,6 +2281,8 @@ static inline void set_raw_inline(struct inode 
> > *inode, struct f2fs_inode *ri)
> > ri->i_inline |= F2FS_INLINE_DOTS;
> > if (is_inode_flag_set(inode, FI_EXTRA_ATTR))
> > ri->i_inline |= F2FS_EXTRA

Re: [PATCH v3] f2fs: add an ioctl to disable GC for specific file

2018-01-02 Thread Chao Yu
On 2018/1/3 11:21, Jaegeuk Kim wrote:
> This patch gives a flag to disable GC on given file, which would be useful, 
> when
> user wants to keep its block map. It also conducts in-place-update for 
> dontmove
> file.
> 
> Signed-off-by: Jaegeuk Kim 
> ---
> 
> Change log from v2:
>  - modify ioctl to allow users unpin the file
> 
>  fs/f2fs/data.c  |  2 ++
>  fs/f2fs/f2fs.h  | 28 +-
>  fs/f2fs/file.c  | 64 
> +
>  fs/f2fs/gc.c| 11 +
>  fs/f2fs/gc.h|  2 ++
>  fs/f2fs/sysfs.c |  2 ++
>  include/linux/f2fs_fs.h |  9 ++-
>  7 files changed, 116 insertions(+), 2 deletions(-)
> 
> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> index 449b0aaa3905..45f65a5b9871 100644
> --- a/fs/f2fs/data.c
> +++ b/fs/f2fs/data.c
> @@ -1395,6 +1395,8 @@ static inline bool need_inplace_update(struct 
> f2fs_io_info *fio)
>  {
>   struct inode *inode = fio->page->mapping->host;
>  
> + if (f2fs_is_pinned_file(inode))
> + return true;
>   if (S_ISDIR(inode->i_mode) || f2fs_is_atomic_file(inode))
>   return false;
>   if (is_cold_data(fio->page))
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index a0e8eec23125..f4b7d73695a7 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -350,6 +350,7 @@ static inline bool __has_cursum_space(struct f2fs_journal 
> *journal,
>  #define F2FS_IOC_GARBAGE_COLLECT_RANGE   _IOW(F2FS_IOCTL_MAGIC, 11,  
> \
>   struct f2fs_gc_range)
>  #define F2FS_IOC_GET_FEATURES_IOR(F2FS_IOCTL_MAGIC, 12, 
> __u32)
> +#define F2FS_IOC_SET_PIN_FILE_IOW(F2FS_IOCTL_MAGIC, 13, 
> __u32)
>  
>  #define F2FS_IOC_SET_ENCRYPTION_POLICY   FS_IOC_SET_ENCRYPTION_POLICY
>  #define F2FS_IOC_GET_ENCRYPTION_POLICY   FS_IOC_GET_ENCRYPTION_POLICY
> @@ -587,7 +588,10 @@ struct f2fs_inode_info {
>   unsigned long i_flags;  /* keep an inode flags for ioctl */
>   unsigned char i_advise; /* use to give file attribute hints */
>   unsigned char i_dir_level;  /* use for dentry level for large dir */
> - unsigned int i_current_depth;   /* use only in directory structure */
> + union {
> + unsigned int i_current_depth;   /* only for directory depth */
> + unsigned short i_gc_failures;   /* only for regular file */
> + };
>   unsigned int i_pino;/* parent inode number */
>   umode_t i_acl_mode; /* keep file acl mode temporarily */
>  
> @@ -1133,6 +1137,9 @@ struct f2fs_sb_info {
>   /* threshold for converting bg victims for fg */
>   u64 fggc_threshold;
>  
> + /* threshold for gc trials on pinned files */
> + u64 gc_pin_file_threshold;
> +
>   /* maximum # of trials to find a victim segment for SSR and GC */
>   unsigned int max_victim_search;
>  
> @@ -2124,6 +2131,7 @@ enum {
>   FI_HOT_DATA,/* indicate file is hot */
>   FI_EXTRA_ATTR,  /* indicate file has extra attribute */
>   FI_PROJ_INHERIT,/* indicate file inherits projectid */
> + FI_PIN_FILE,/* indicate file should not be gced */
>  };
>  
>  static inline void __mark_inode_dirty_flag(struct inode *inode,
> @@ -2137,6 +2145,7 @@ static inline void __mark_inode_dirty_flag(struct inode 
> *inode,
>   return;
>   case FI_DATA_EXIST:
>   case FI_INLINE_DOTS:
> + case FI_PIN_FILE:
>   f2fs_mark_inode_dirty_sync(inode, true);
>   }
>  }
> @@ -2217,6 +2226,13 @@ static inline void f2fs_i_depth_write(struct inode 
> *inode, unsigned int depth)
>   f2fs_mark_inode_dirty_sync(inode, true);
>  }
>  
> +static inline void f2fs_i_gc_failures_write(struct inode *inode,
> + unsigned int count)
> +{
> + F2FS_I(inode)->i_gc_failures = count;
> + f2fs_mark_inode_dirty_sync(inode, true);
> +}
> +
>  static inline void f2fs_i_xnid_write(struct inode *inode, nid_t xnid)
>  {
>   F2FS_I(inode)->i_xattr_nid = xnid;
> @@ -2245,6 +2261,8 @@ static inline void get_inline_info(struct inode *inode, 
> struct f2fs_inode *ri)
>   set_bit(FI_INLINE_DOTS, &fi->flags);
>   if (ri->i_inline & F2FS_EXTRA_ATTR)
>   set_bit(FI_EXTRA_ATTR, &fi->flags);
> + if (ri->i_inline & F2FS_PIN_FILE)
> + set_bit(FI_PIN_FILE, &fi->flags);
>  }
>  
>  static inline void set_raw_inline(struct inode *inode, struct f2fs_inode *ri)
> @@ -2263,6 +2281,8 @@ static inline void set_raw_inline(struct inode *inode, 
> struct f2fs_inode *ri)
>   ri->i_inline |= F2FS_INLINE_DOTS;
>   if (is_inode_flag_set(inode, FI_EXTRA_ATTR))
>   ri->i_inline |= F2FS_EXTRA_ATTR;
> + if (is_inode_flag_set(inode, FI_PIN_FILE))
> + ri->i_inline |= F2FS_PIN_FILE;
>  }
>  
>  static inline int f2fs_has_extra_attr(struct inode *ino

Re: [PATCH v3] f2fs: add an ioctl to disable GC for specific file

2018-01-02 Thread Jaegeuk Kim
This patch gives a flag to disable GC on given file, which would be useful, when
user wants to keep its block map. It also conducts in-place-update for dontmove
file.

Signed-off-by: Jaegeuk Kim 
---

Change log from v2:
 - modify ioctl to allow users unpin the file

 fs/f2fs/data.c  |  2 ++
 fs/f2fs/f2fs.h  | 28 +-
 fs/f2fs/file.c  | 64 +
 fs/f2fs/gc.c| 11 +
 fs/f2fs/gc.h|  2 ++
 fs/f2fs/sysfs.c |  2 ++
 include/linux/f2fs_fs.h |  9 ++-
 7 files changed, 116 insertions(+), 2 deletions(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 449b0aaa3905..45f65a5b9871 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1395,6 +1395,8 @@ static inline bool need_inplace_update(struct 
f2fs_io_info *fio)
 {
struct inode *inode = fio->page->mapping->host;
 
+   if (f2fs_is_pinned_file(inode))
+   return true;
if (S_ISDIR(inode->i_mode) || f2fs_is_atomic_file(inode))
return false;
if (is_cold_data(fio->page))
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index a0e8eec23125..f4b7d73695a7 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -350,6 +350,7 @@ static inline bool __has_cursum_space(struct f2fs_journal 
*journal,
 #define F2FS_IOC_GARBAGE_COLLECT_RANGE _IOW(F2FS_IOCTL_MAGIC, 11,  \
struct f2fs_gc_range)
 #define F2FS_IOC_GET_FEATURES  _IOR(F2FS_IOCTL_MAGIC, 12, __u32)
+#define F2FS_IOC_SET_PIN_FILE  _IOW(F2FS_IOCTL_MAGIC, 13, __u32)
 
 #define F2FS_IOC_SET_ENCRYPTION_POLICY FS_IOC_SET_ENCRYPTION_POLICY
 #define F2FS_IOC_GET_ENCRYPTION_POLICY FS_IOC_GET_ENCRYPTION_POLICY
@@ -587,7 +588,10 @@ struct f2fs_inode_info {
unsigned long i_flags;  /* keep an inode flags for ioctl */
unsigned char i_advise; /* use to give file attribute hints */
unsigned char i_dir_level;  /* use for dentry level for large dir */
-   unsigned int i_current_depth;   /* use only in directory structure */
+   union {
+   unsigned int i_current_depth;   /* only for directory depth */
+   unsigned short i_gc_failures;   /* only for regular file */
+   };
unsigned int i_pino;/* parent inode number */
umode_t i_acl_mode; /* keep file acl mode temporarily */
 
@@ -1133,6 +1137,9 @@ struct f2fs_sb_info {
/* threshold for converting bg victims for fg */
u64 fggc_threshold;
 
+   /* threshold for gc trials on pinned files */
+   u64 gc_pin_file_threshold;
+
/* maximum # of trials to find a victim segment for SSR and GC */
unsigned int max_victim_search;
 
@@ -2124,6 +2131,7 @@ enum {
FI_HOT_DATA,/* indicate file is hot */
FI_EXTRA_ATTR,  /* indicate file has extra attribute */
FI_PROJ_INHERIT,/* indicate file inherits projectid */
+   FI_PIN_FILE,/* indicate file should not be gced */
 };
 
 static inline void __mark_inode_dirty_flag(struct inode *inode,
@@ -2137,6 +2145,7 @@ static inline void __mark_inode_dirty_flag(struct inode 
*inode,
return;
case FI_DATA_EXIST:
case FI_INLINE_DOTS:
+   case FI_PIN_FILE:
f2fs_mark_inode_dirty_sync(inode, true);
}
 }
@@ -2217,6 +2226,13 @@ static inline void f2fs_i_depth_write(struct inode 
*inode, unsigned int depth)
f2fs_mark_inode_dirty_sync(inode, true);
 }
 
+static inline void f2fs_i_gc_failures_write(struct inode *inode,
+   unsigned int count)
+{
+   F2FS_I(inode)->i_gc_failures = count;
+   f2fs_mark_inode_dirty_sync(inode, true);
+}
+
 static inline void f2fs_i_xnid_write(struct inode *inode, nid_t xnid)
 {
F2FS_I(inode)->i_xattr_nid = xnid;
@@ -2245,6 +2261,8 @@ static inline void get_inline_info(struct inode *inode, 
struct f2fs_inode *ri)
set_bit(FI_INLINE_DOTS, &fi->flags);
if (ri->i_inline & F2FS_EXTRA_ATTR)
set_bit(FI_EXTRA_ATTR, &fi->flags);
+   if (ri->i_inline & F2FS_PIN_FILE)
+   set_bit(FI_PIN_FILE, &fi->flags);
 }
 
 static inline void set_raw_inline(struct inode *inode, struct f2fs_inode *ri)
@@ -2263,6 +2281,8 @@ static inline void set_raw_inline(struct inode *inode, 
struct f2fs_inode *ri)
ri->i_inline |= F2FS_INLINE_DOTS;
if (is_inode_flag_set(inode, FI_EXTRA_ATTR))
ri->i_inline |= F2FS_EXTRA_ATTR;
+   if (is_inode_flag_set(inode, FI_PIN_FILE))
+   ri->i_inline |= F2FS_PIN_FILE;
 }
 
 static inline int f2fs_has_extra_attr(struct inode *inode)
@@ -2308,6 +2328,11 @@ static inline int f2fs_has_inline_dots(struct inode 
*inode)
return is_inode_flag_set(inode, FI_INLINE_DOTS);
 }
 
+static inline bool f2fs_is_pinned_file(struct inode *inode)
+{
+   return i