2013-11-10 19:13:19 +04:00
/*
* fs / f2fs / inline . c
* Copyright ( c ) 2013 , Intel Corporation
* Authors : Huajun Li < huajun . li @ intel . com >
* Haicheng Li < haicheng . li @ intel . com >
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
# include <linux/fs.h>
# include <linux/f2fs_fs.h>
# include "f2fs.h"
2015-04-23 20:27:21 +03:00
bool f2fs_may_inline_data ( struct inode * inode )
2013-11-10 19:13:19 +04:00
{
2014-09-03 02:31:18 +04:00
if ( ! test_opt ( F2FS_I_SB ( inode ) , INLINE_DATA ) )
2013-11-10 19:13:19 +04:00
return false ;
2014-10-07 04:39:50 +04:00
if ( f2fs_is_atomic_file ( inode ) )
return false ;
2015-03-19 08:23:48 +03:00
if ( ! S_ISREG ( inode - > i_mode ) & & ! S_ISLNK ( inode - > i_mode ) )
2013-11-10 19:13:19 +04:00
return false ;
2014-11-12 01:10:01 +03:00
if ( i_size_read ( inode ) > MAX_INLINE_DATA )
return false ;
2015-04-22 06:39:58 +03:00
if ( f2fs_encrypted_inode ( inode ) & & S_ISREG ( inode - > i_mode ) )
return false ;
2013-11-10 19:13:19 +04:00
return true ;
}
2015-04-23 20:27:21 +03:00
bool f2fs_may_inline_dentry ( struct inode * inode )
{
if ( ! test_opt ( F2FS_I_SB ( inode ) , INLINE_DENTRY ) )
return false ;
if ( ! S_ISDIR ( inode - > i_mode ) )
return false ;
return true ;
}
2014-10-24 06:48:09 +04:00
void read_inline_data ( struct page * page , struct page * ipage )
2013-11-10 19:13:19 +04:00
{
void * src_addr , * dst_addr ;
2014-10-24 06:48:09 +04:00
if ( PageUptodate ( page ) )
return ;
2013-12-30 14:36:23 +04:00
2014-10-24 06:48:09 +04:00
f2fs_bug_on ( F2FS_P_SB ( page ) , page - > index ) ;
2013-11-10 19:13:19 +04:00
2013-12-30 05:29:06 +04:00
zero_user_segment ( page , MAX_INLINE_DATA , PAGE_CACHE_SIZE ) ;
2013-11-10 19:13:19 +04:00
/* Copy the whole inline data block */
src_addr = inline_data_addr ( ipage ) ;
2014-10-19 10:41:38 +04:00
dst_addr = kmap_atomic ( page ) ;
2013-11-10 19:13:19 +04:00
memcpy ( dst_addr , src_addr , MAX_INLINE_DATA ) ;
2014-10-27 08:59:27 +03:00
flush_dcache_page ( page ) ;
2014-10-19 10:41:38 +04:00
kunmap_atomic ( dst_addr ) ;
2013-11-10 19:13:19 +04:00
SetPageUptodate ( page ) ;
2014-10-24 06:48:09 +04:00
}
2015-03-10 08:16:25 +03:00
bool truncate_inline_inode ( struct page * ipage , u64 from )
2015-01-26 15:22:55 +03:00
{
2015-03-10 08:16:25 +03:00
void * addr ;
if ( from > = MAX_INLINE_DATA )
return false ;
addr = inline_data_addr ( ipage ) ;
2015-01-26 15:22:55 +03:00
f2fs_wait_on_page_writeback ( ipage , NODE ) ;
2015-03-10 08:16:25 +03:00
memset ( addr + from , 0 , MAX_INLINE_DATA - from ) ;
return true ;
2015-01-26 15:22:55 +03:00
}
2014-10-24 06:48:09 +04:00
int f2fs_read_inline_data ( struct inode * inode , struct page * page )
{
struct page * ipage ;
ipage = get_node_page ( F2FS_I_SB ( inode ) , inode - > i_ino ) ;
if ( IS_ERR ( ipage ) ) {
unlock_page ( page ) ;
return PTR_ERR ( ipage ) ;
}
2013-11-10 19:13:19 +04:00
2014-10-24 06:48:09 +04:00
if ( ! f2fs_has_inline_data ( inode ) ) {
f2fs_put_page ( ipage , 1 ) ;
return - EAGAIN ;
}
if ( page - > index )
zero_user_segment ( page , 0 , PAGE_CACHE_SIZE ) ;
else
read_inline_data ( page , ipage ) ;
SetPageUptodate ( page ) ;
f2fs_put_page ( ipage , 1 ) ;
unlock_page ( page ) ;
2013-11-10 19:13:19 +04:00
return 0 ;
}
2014-10-24 06:48:09 +04:00
int f2fs_convert_inline_page ( struct dnode_of_data * dn , struct page * page )
2013-11-10 19:13:19 +04:00
{
void * src_addr , * dst_addr ;
struct f2fs_io_info fio = {
2015-04-24 00:38:15 +03:00
. sbi = F2FS_I_SB ( dn - > inode ) ,
2013-11-10 19:13:19 +04:00
. type = DATA ,
. rw = WRITE_SYNC | REQ_PRIO ,
2015-04-24 00:38:15 +03:00
. page = page ,
2015-04-23 22:04:33 +03:00
. encrypted_page = NULL ,
2013-11-10 19:13:19 +04:00
} ;
2014-11-25 22:34:02 +03:00
int dirty , err ;
2013-11-10 19:13:19 +04:00
2014-10-24 06:48:09 +04:00
f2fs_bug_on ( F2FS_I_SB ( dn - > inode ) , page - > index ) ;
2013-11-10 19:13:19 +04:00
2014-10-24 06:48:09 +04:00
if ( ! f2fs_exist_data ( dn - > inode ) )
goto clear_out ;
2014-08-19 01:41:11 +04:00
2014-10-24 06:48:09 +04:00
err = f2fs_reserve_block ( dn , 0 ) ;
2014-04-16 09:22:50 +04:00
if ( err )
2014-10-24 06:48:09 +04:00
return err ;
2013-11-10 19:13:19 +04:00
2014-04-29 12:35:10 +04:00
f2fs_wait_on_page_writeback ( page , DATA ) ;
2014-10-24 06:48:09 +04:00
if ( PageUptodate ( page ) )
goto no_update ;
2013-12-30 05:29:06 +04:00
zero_user_segment ( page , MAX_INLINE_DATA , PAGE_CACHE_SIZE ) ;
2013-11-10 19:13:19 +04:00
/* Copy the whole inline data block */
2014-10-24 06:48:09 +04:00
src_addr = inline_data_addr ( dn - > inode_page ) ;
2014-10-19 10:41:38 +04:00
dst_addr = kmap_atomic ( page ) ;
2013-11-10 19:13:19 +04:00
memcpy ( dst_addr , src_addr , MAX_INLINE_DATA ) ;
2014-11-18 21:50:21 +03:00
flush_dcache_page ( page ) ;
2014-10-19 10:41:38 +04:00
kunmap_atomic ( dst_addr ) ;
2013-12-27 07:28:59 +04:00
SetPageUptodate ( page ) ;
2014-10-24 06:48:09 +04:00
no_update :
2014-11-25 22:34:02 +03:00
/* clear dirty state */
dirty = clear_page_dirty_for_io ( page ) ;
2013-11-10 19:13:19 +04:00
/* write data page to try to make data consistent */
set_page_writeback ( page ) ;
2014-12-18 06:33:13 +03:00
fio . blk_addr = dn - > data_blkaddr ;
2015-04-24 00:38:15 +03:00
write_data_page ( dn , & fio ) ;
2015-03-19 14:23:32 +03:00
set_data_blkaddr ( dn ) ;
2015-02-05 12:51:34 +03:00
f2fs_update_extent_cache ( dn ) ;
2014-01-10 11:26:14 +04:00
f2fs_wait_on_page_writeback ( page , DATA ) ;
2014-11-25 22:34:02 +03:00
if ( dirty )
inode_dec_dirty_pages ( dn - > inode ) ;
2013-11-10 19:13:19 +04:00
2014-11-26 04:27:38 +03:00
/* this converted inline_data should be recovered. */
set_inode_flag ( F2FS_I ( dn - > inode ) , FI_APPEND_WRITE ) ;
2013-11-10 19:13:19 +04:00
/* clear inline data and flag after data writeback */
2015-03-10 08:16:25 +03:00
truncate_inline_inode ( dn - > inode_page , 0 ) ;
2014-10-24 06:48:09 +04:00
clear_out :
stat_dec_inline_inode ( dn - > inode ) ;
2014-11-11 03:29:14 +03:00
f2fs_clear_inline_inode ( dn - > inode ) ;
2014-10-24 06:48:09 +04:00
sync_inode_page ( dn ) ;
f2fs_put_dnode ( dn ) ;
return 0 ;
2013-11-10 19:13:19 +04:00
}
2014-10-24 06:48:09 +04:00
int f2fs_convert_inline_inode ( struct inode * inode )
2013-11-10 19:13:19 +04:00
{
2014-10-24 06:48:09 +04:00
struct f2fs_sb_info * sbi = F2FS_I_SB ( inode ) ;
struct dnode_of_data dn ;
struct page * ipage , * page ;
int err = 0 ;
2013-11-10 19:13:19 +04:00
2014-10-24 06:48:09 +04:00
page = grab_cache_page ( inode - > i_mapping , 0 ) ;
if ( ! page )
return - ENOMEM ;
2013-11-10 19:13:19 +04:00
2014-10-24 06:48:09 +04:00
f2fs_lock_op ( sbi ) ;
ipage = get_node_page ( sbi , inode - > i_ino ) ;
if ( IS_ERR ( ipage ) ) {
2014-11-18 03:06:55 +03:00
err = PTR_ERR ( ipage ) ;
goto out ;
2014-08-08 03:32:25 +04:00
}
2013-11-10 19:13:19 +04:00
2014-10-24 06:48:09 +04:00
set_new_dnode ( & dn , inode , ipage , ipage , 0 ) ;
if ( f2fs_has_inline_data ( inode ) )
err = f2fs_convert_inline_page ( & dn , page ) ;
f2fs_put_dnode ( & dn ) ;
2014-11-18 03:06:55 +03:00
out :
2014-10-24 06:48:09 +04:00
f2fs_unlock_op ( sbi ) ;
f2fs_put_page ( page , 1 ) ;
2013-11-10 19:13:19 +04:00
return err ;
}
2014-10-24 06:48:09 +04:00
int f2fs_write_inline_data ( struct inode * inode , struct page * page )
2013-11-10 19:13:19 +04:00
{
void * src_addr , * dst_addr ;
struct dnode_of_data dn ;
int err ;
set_new_dnode ( & dn , inode , NULL , NULL , 0 ) ;
err = get_dnode_of_data ( & dn , 0 , LOOKUP_NODE ) ;
if ( err )
return err ;
2014-10-15 21:16:54 +04:00
if ( ! f2fs_has_inline_data ( inode ) ) {
2014-10-24 06:48:09 +04:00
f2fs_put_dnode ( & dn ) ;
return - EAGAIN ;
2014-10-15 21:16:54 +04:00
}
2014-10-24 06:48:09 +04:00
f2fs_bug_on ( F2FS_I_SB ( inode ) , page - > index ) ;
f2fs_wait_on_page_writeback ( dn . inode_page , NODE ) ;
2014-10-19 10:41:38 +04:00
src_addr = kmap_atomic ( page ) ;
2014-10-24 06:48:09 +04:00
dst_addr = inline_data_addr ( dn . inode_page ) ;
memcpy ( dst_addr , src_addr , MAX_INLINE_DATA ) ;
2014-10-19 10:41:38 +04:00
kunmap_atomic ( src_addr ) ;
2013-11-10 19:13:19 +04:00
2014-07-25 18:40:59 +04:00
set_inode_flag ( F2FS_I ( inode ) , FI_APPEND_WRITE ) ;
2014-10-24 06:48:09 +04:00
set_inode_flag ( F2FS_I ( inode ) , FI_DATA_EXIST ) ;
2013-11-10 19:13:19 +04:00
sync_inode_page ( & dn ) ;
f2fs_put_dnode ( & dn ) ;
return 0 ;
}
2013-12-26 07:49:48 +04:00
2014-08-08 03:57:17 +04:00
bool recover_inline_data ( struct inode * inode , struct page * npage )
2013-12-26 07:49:48 +04:00
{
2014-09-03 02:31:18 +04:00
struct f2fs_sb_info * sbi = F2FS_I_SB ( inode ) ;
2013-12-26 07:49:48 +04:00
struct f2fs_inode * ri = NULL ;
void * src_addr , * dst_addr ;
struct page * ipage ;
/*
* The inline_data recovery policy is as follows .
* [ prev . ] [ next ] of inline_data flag
* o o - > recover inline_data
* o x - > remove inline_data , and then recover data blocks
* x o - > remove inline_data , and then recover inline_data
* x x - > recover data blocks
*/
if ( IS_INODE ( npage ) )
ri = F2FS_INODE ( npage ) ;
if ( f2fs_has_inline_data ( inode ) & &
2014-08-08 03:57:17 +04:00
ri & & ( ri - > i_inline & F2FS_INLINE_DATA ) ) {
2013-12-26 07:49:48 +04:00
process_inline :
ipage = get_node_page ( sbi , inode - > i_ino ) ;
2014-09-03 02:52:58 +04:00
f2fs_bug_on ( sbi , IS_ERR ( ipage ) ) ;
2013-12-26 07:49:48 +04:00
2014-04-29 12:28:32 +04:00
f2fs_wait_on_page_writeback ( ipage , NODE ) ;
2013-12-26 07:49:48 +04:00
src_addr = inline_data_addr ( npage ) ;
dst_addr = inline_data_addr ( ipage ) ;
memcpy ( dst_addr , src_addr , MAX_INLINE_DATA ) ;
2014-10-24 06:48:09 +04:00
set_inode_flag ( F2FS_I ( inode ) , FI_INLINE_DATA ) ;
set_inode_flag ( F2FS_I ( inode ) , FI_DATA_EXIST ) ;
2013-12-26 07:49:48 +04:00
update_inode ( inode , ipage ) ;
f2fs_put_page ( ipage , 1 ) ;
2014-08-08 03:57:17 +04:00
return true ;
2013-12-26 07:49:48 +04:00
}
if ( f2fs_has_inline_data ( inode ) ) {
ipage = get_node_page ( sbi , inode - > i_ino ) ;
2014-09-03 02:52:58 +04:00
f2fs_bug_on ( sbi , IS_ERR ( ipage ) ) ;
2015-03-10 08:16:25 +03:00
truncate_inline_inode ( ipage , 0 ) ;
2014-10-24 06:48:09 +04:00
f2fs_clear_inline_inode ( inode ) ;
2013-12-26 07:49:48 +04:00
update_inode ( inode , ipage ) ;
f2fs_put_page ( ipage , 1 ) ;
2014-08-08 03:57:17 +04:00
} else if ( ri & & ( ri - > i_inline & F2FS_INLINE_DATA ) ) {
2014-08-15 03:32:54 +04:00
truncate_blocks ( inode , 0 , false ) ;
2013-12-26 07:49:48 +04:00
goto process_inline ;
}
2014-08-08 03:57:17 +04:00
return false ;
2013-12-26 07:49:48 +04:00
}
2014-09-24 14:17:53 +04:00
struct f2fs_dir_entry * find_in_inline_dir ( struct inode * dir ,
struct qstr * name , struct page * * res_page )
{
struct f2fs_sb_info * sbi = F2FS_SB ( dir - > i_sb ) ;
2014-10-14 04:26:14 +04:00
struct f2fs_inline_dentry * inline_dentry ;
2014-09-24 14:17:53 +04:00
struct f2fs_dir_entry * de ;
2014-10-19 09:52:52 +04:00
struct f2fs_dentry_ptr d ;
2014-10-14 04:26:14 +04:00
struct page * ipage ;
2014-09-24 14:17:53 +04:00
ipage = get_node_page ( sbi , dir - > i_ino ) ;
if ( IS_ERR ( ipage ) )
return NULL ;
2014-10-14 04:26:14 +04:00
inline_dentry = inline_data_addr ( ipage ) ;
2014-09-24 14:17:53 +04:00
2015-04-28 02:26:24 +03:00
make_dentry_ptr ( NULL , & d , ( void * ) inline_dentry , 2 ) ;
2014-10-19 09:52:52 +04:00
de = find_target_dentry ( name , NULL , & d ) ;
2014-09-24 14:17:53 +04:00
unlock_page ( ipage ) ;
2014-10-14 04:26:14 +04:00
if ( de )
* res_page = ipage ;
else
f2fs_put_page ( ipage , 0 ) ;
/*
* For the most part , it should be a bug when name_len is zero .
* We stop here for figuring out where the bugs has occurred .
*/
2014-10-19 09:52:52 +04:00
f2fs_bug_on ( sbi , d . max < 0 ) ;
2014-09-24 14:17:53 +04:00
return de ;
}
struct f2fs_dir_entry * f2fs_parent_inline_dir ( struct inode * dir ,
struct page * * p )
{
struct f2fs_sb_info * sbi = F2FS_I_SB ( dir ) ;
struct page * ipage ;
struct f2fs_dir_entry * de ;
struct f2fs_inline_dentry * dentry_blk ;
ipage = get_node_page ( sbi , dir - > i_ino ) ;
if ( IS_ERR ( ipage ) )
return NULL ;
dentry_blk = inline_data_addr ( ipage ) ;
de = & dentry_blk - > dentry [ 1 ] ;
* p = ipage ;
unlock_page ( ipage ) ;
return de ;
}
int make_empty_inline_dir ( struct inode * inode , struct inode * parent ,
struct page * ipage )
{
struct f2fs_inline_dentry * dentry_blk ;
2014-10-19 10:06:41 +04:00
struct f2fs_dentry_ptr d ;
2014-09-24 14:17:53 +04:00
dentry_blk = inline_data_addr ( ipage ) ;
2015-04-28 02:26:24 +03:00
make_dentry_ptr ( NULL , & d , ( void * ) dentry_blk , 2 ) ;
2014-10-19 10:06:41 +04:00
do_make_empty_dir ( inode , parent , & d ) ;
2014-09-24 14:17:53 +04:00
set_page_dirty ( ipage ) ;
/* update i_size to MAX_INLINE_DATA */
if ( i_size_read ( inode ) < MAX_INLINE_DATA ) {
i_size_write ( inode , MAX_INLINE_DATA ) ;
set_inode_flag ( F2FS_I ( inode ) , FI_UPDATE_DIR ) ;
}
return 0 ;
}
2014-10-21 07:28:49 +04:00
static int f2fs_convert_inline_dir ( struct inode * dir , struct page * ipage ,
2014-09-24 14:17:53 +04:00
struct f2fs_inline_dentry * inline_dentry )
{
struct page * page ;
struct dnode_of_data dn ;
struct f2fs_dentry_block * dentry_blk ;
int err ;
page = grab_cache_page ( dir - > i_mapping , 0 ) ;
if ( ! page )
return - ENOMEM ;
set_new_dnode ( & dn , dir , ipage , NULL , 0 ) ;
err = f2fs_reserve_block ( & dn , 0 ) ;
if ( err )
goto out ;
f2fs_wait_on_page_writeback ( page , DATA ) ;
zero_user_segment ( page , 0 , PAGE_CACHE_SIZE ) ;
2014-10-19 10:41:38 +04:00
dentry_blk = kmap_atomic ( page ) ;
2014-09-24 14:17:53 +04:00
/* copy data from inline dentry block to new dentry block */
memcpy ( dentry_blk - > dentry_bitmap , inline_dentry - > dentry_bitmap ,
INLINE_DENTRY_BITMAP_SIZE ) ;
memcpy ( dentry_blk - > dentry , inline_dentry - > dentry ,
sizeof ( struct f2fs_dir_entry ) * NR_INLINE_DENTRY ) ;
memcpy ( dentry_blk - > filename , inline_dentry - > filename ,
NR_INLINE_DENTRY * F2FS_SLOT_LEN ) ;
2014-10-19 10:41:38 +04:00
kunmap_atomic ( dentry_blk ) ;
2014-09-24 14:17:53 +04:00
SetPageUptodate ( page ) ;
set_page_dirty ( page ) ;
/* clear inline dir and flag after data writeback */
2015-03-10 08:16:25 +03:00
truncate_inline_inode ( ipage , 0 ) ;
2014-10-24 06:48:09 +04:00
2014-10-14 07:00:16 +04:00
stat_dec_inline_dir ( dir ) ;
2014-09-24 14:19:10 +04:00
clear_inode_flag ( F2FS_I ( dir ) , FI_INLINE_DENTRY ) ;
2014-09-24 14:17:53 +04:00
if ( i_size_read ( dir ) < PAGE_CACHE_SIZE ) {
i_size_write ( dir , PAGE_CACHE_SIZE ) ;
set_inode_flag ( F2FS_I ( dir ) , FI_UPDATE_DIR ) ;
}
sync_inode_page ( & dn ) ;
out :
f2fs_put_page ( page , 1 ) ;
return err ;
}
int f2fs_add_inline_entry ( struct inode * dir , const struct qstr * name ,
2015-03-31 01:07:16 +03:00
struct inode * inode , nid_t ino , umode_t mode )
2014-09-24 14:17:53 +04:00
{
struct f2fs_sb_info * sbi = F2FS_I_SB ( dir ) ;
struct page * ipage ;
unsigned int bit_pos ;
f2fs_hash_t name_hash ;
size_t namelen = name - > len ;
struct f2fs_inline_dentry * dentry_blk = NULL ;
2015-02-16 11:17:20 +03:00
struct f2fs_dentry_ptr d ;
2014-09-24 14:17:53 +04:00
int slots = GET_DENTRY_SLOTS ( namelen ) ;
2015-03-31 01:07:16 +03:00
struct page * page = NULL ;
2014-09-24 14:17:53 +04:00
int err = 0 ;
ipage = get_node_page ( sbi , dir - > i_ino ) ;
if ( IS_ERR ( ipage ) )
return PTR_ERR ( ipage ) ;
dentry_blk = inline_data_addr ( ipage ) ;
2014-10-14 03:28:13 +04:00
bit_pos = room_for_filename ( & dentry_blk - > dentry_bitmap ,
slots , NR_INLINE_DENTRY ) ;
2014-09-24 14:17:53 +04:00
if ( bit_pos > = NR_INLINE_DENTRY ) {
err = f2fs_convert_inline_dir ( dir , ipage , dentry_blk ) ;
if ( ! err )
err = - EAGAIN ;
goto out ;
}
2015-03-31 01:07:16 +03:00
if ( inode ) {
down_write ( & F2FS_I ( inode ) - > i_sem ) ;
page = init_inode_metadata ( inode , dir , name , ipage ) ;
if ( IS_ERR ( page ) ) {
err = PTR_ERR ( page ) ;
goto fail ;
}
2014-09-24 14:17:53 +04:00
}
2014-10-14 06:42:53 +04:00
f2fs_wait_on_page_writeback ( ipage , NODE ) ;
2015-02-16 11:17:20 +03:00
name_hash = f2fs_dentry_hash ( name ) ;
2015-04-28 02:26:24 +03:00
make_dentry_ptr ( NULL , & d , ( void * ) dentry_blk , 2 ) ;
2015-03-31 01:07:16 +03:00
f2fs_update_dentry ( ino , mode , & d , name , name_hash , bit_pos ) ;
2015-02-16 11:17:20 +03:00
2014-09-24 14:17:53 +04:00
set_page_dirty ( ipage ) ;
/* we don't need to mark_inode_dirty now */
2015-03-31 01:07:16 +03:00
if ( inode ) {
F2FS_I ( inode ) - > i_pino = dir - > i_ino ;
update_inode ( inode , page ) ;
f2fs_put_page ( page , 1 ) ;
}
2014-09-24 14:17:53 +04:00
update_parent_metadata ( dir , inode , 0 ) ;
fail :
2015-03-31 01:07:16 +03:00
if ( inode )
up_write ( & F2FS_I ( inode ) - > i_sem ) ;
2014-09-24 14:17:53 +04:00
if ( is_inode_flag_set ( F2FS_I ( dir ) , FI_UPDATE_DIR ) ) {
update_inode ( dir , ipage ) ;
clear_inode_flag ( F2FS_I ( dir ) , FI_UPDATE_DIR ) ;
}
out :
f2fs_put_page ( ipage , 1 ) ;
return err ;
}
void f2fs_delete_inline_entry ( struct f2fs_dir_entry * dentry , struct page * page ,
struct inode * dir , struct inode * inode )
{
struct f2fs_inline_dentry * inline_dentry ;
int slots = GET_DENTRY_SLOTS ( le16_to_cpu ( dentry - > name_len ) ) ;
unsigned int bit_pos ;
int i ;
lock_page ( page ) ;
2014-10-14 06:34:26 +04:00
f2fs_wait_on_page_writeback ( page , NODE ) ;
2014-09-24 14:17:53 +04:00
inline_dentry = inline_data_addr ( page ) ;
bit_pos = dentry - inline_dentry - > dentry ;
for ( i = 0 ; i < slots ; i + + )
test_and_clear_bit_le ( bit_pos + i ,
& inline_dentry - > dentry_bitmap ) ;
set_page_dirty ( page ) ;
dir - > i_ctime = dir - > i_mtime = CURRENT_TIME ;
if ( inode )
f2fs_drop_nlink ( dir , inode , page ) ;
f2fs_put_page ( page , 1 ) ;
}
bool f2fs_empty_inline_dir ( struct inode * dir )
{
struct f2fs_sb_info * sbi = F2FS_I_SB ( dir ) ;
struct page * ipage ;
unsigned int bit_pos = 2 ;
struct f2fs_inline_dentry * dentry_blk ;
ipage = get_node_page ( sbi , dir - > i_ino ) ;
if ( IS_ERR ( ipage ) )
return false ;
dentry_blk = inline_data_addr ( ipage ) ;
bit_pos = find_next_bit_le ( & dentry_blk - > dentry_bitmap ,
NR_INLINE_DENTRY ,
bit_pos ) ;
f2fs_put_page ( ipage , 1 ) ;
if ( bit_pos < NR_INLINE_DENTRY )
return false ;
return true ;
}
2015-04-28 02:26:24 +03:00
int f2fs_read_inline_dir ( struct file * file , struct dir_context * ctx ,
struct f2fs_str * fstr )
2014-09-24 14:17:53 +04:00
{
struct inode * inode = file_inode ( file ) ;
struct f2fs_inline_dentry * inline_dentry = NULL ;
struct page * ipage = NULL ;
2014-10-19 09:52:52 +04:00
struct f2fs_dentry_ptr d ;
2014-09-24 14:17:53 +04:00
if ( ctx - > pos = = NR_INLINE_DENTRY )
return 0 ;
2014-10-16 08:29:51 +04:00
ipage = get_node_page ( F2FS_I_SB ( inode ) , inode - > i_ino ) ;
2014-09-24 14:17:53 +04:00
if ( IS_ERR ( ipage ) )
return PTR_ERR ( ipage ) ;
inline_dentry = inline_data_addr ( ipage ) ;
2015-04-28 02:26:24 +03:00
make_dentry_ptr ( inode , & d , ( void * ) inline_dentry , 2 ) ;
2014-10-19 09:52:52 +04:00
2015-04-28 02:26:24 +03:00
if ( ! f2fs_fill_dentries ( ctx , & d , 0 , fstr ) )
2014-10-16 08:29:51 +04:00
ctx - > pos = NR_INLINE_DENTRY ;
2014-09-24 14:17:53 +04:00
2014-10-16 08:29:51 +04:00
f2fs_put_page ( ipage , 1 ) ;
2014-09-24 14:17:53 +04:00
return 0 ;
}