@@ -5872,6 +5872,74 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
5872
5872
return d_splice_alias (inode , dentry );
5873
5873
}
5874
5874
5875
+ /*
5876
+ * Find the highest existing sequence number in a directory and then set the
5877
+ * in-memory index_cnt variable to the first free sequence number.
5878
+ */
5879
+ static int btrfs_set_inode_index_count (struct btrfs_inode * inode )
5880
+ {
5881
+ struct btrfs_root * root = inode -> root ;
5882
+ struct btrfs_key key , found_key ;
5883
+ struct btrfs_path * path ;
5884
+ struct extent_buffer * leaf ;
5885
+ int ret ;
5886
+
5887
+ key .objectid = btrfs_ino (inode );
5888
+ key .type = BTRFS_DIR_INDEX_KEY ;
5889
+ key .offset = (u64 )- 1 ;
5890
+
5891
+ path = btrfs_alloc_path ();
5892
+ if (!path )
5893
+ return - ENOMEM ;
5894
+
5895
+ ret = btrfs_search_slot (NULL , root , & key , path , 0 , 0 );
5896
+ if (ret < 0 )
5897
+ goto out ;
5898
+ /* FIXME: we should be able to handle this */
5899
+ if (ret == 0 )
5900
+ goto out ;
5901
+ ret = 0 ;
5902
+
5903
+ if (path -> slots [0 ] == 0 ) {
5904
+ inode -> index_cnt = BTRFS_DIR_START_INDEX ;
5905
+ goto out ;
5906
+ }
5907
+
5908
+ path -> slots [0 ]-- ;
5909
+
5910
+ leaf = path -> nodes [0 ];
5911
+ btrfs_item_key_to_cpu (leaf , & found_key , path -> slots [0 ]);
5912
+
5913
+ if (found_key .objectid != btrfs_ino (inode ) ||
5914
+ found_key .type != BTRFS_DIR_INDEX_KEY ) {
5915
+ inode -> index_cnt = BTRFS_DIR_START_INDEX ;
5916
+ goto out ;
5917
+ }
5918
+
5919
+ inode -> index_cnt = found_key .offset + 1 ;
5920
+ out :
5921
+ btrfs_free_path (path );
5922
+ return ret ;
5923
+ }
5924
+
5925
+ static int btrfs_get_dir_last_index (struct btrfs_inode * dir , u64 * index )
5926
+ {
5927
+ if (dir -> index_cnt == (u64 )- 1 ) {
5928
+ int ret ;
5929
+
5930
+ ret = btrfs_inode_delayed_dir_index_count (dir );
5931
+ if (ret ) {
5932
+ ret = btrfs_set_inode_index_count (dir );
5933
+ if (ret )
5934
+ return ret ;
5935
+ }
5936
+ }
5937
+
5938
+ * index = dir -> index_cnt ;
5939
+
5940
+ return 0 ;
5941
+ }
5942
+
5875
5943
/*
5876
5944
* All this infrastructure exists because dir_emit can fault, and we are holding
5877
5945
* the tree lock when doing readdir. For now just allocate a buffer and copy
@@ -5884,10 +5952,17 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
5884
5952
static int btrfs_opendir (struct inode * inode , struct file * file )
5885
5953
{
5886
5954
struct btrfs_file_private * private ;
5955
+ u64 last_index ;
5956
+ int ret ;
5957
+
5958
+ ret = btrfs_get_dir_last_index (BTRFS_I (inode ), & last_index );
5959
+ if (ret )
5960
+ return ret ;
5887
5961
5888
5962
private = kzalloc (sizeof (struct btrfs_file_private ), GFP_KERNEL );
5889
5963
if (!private )
5890
5964
return - ENOMEM ;
5965
+ private -> last_index = last_index ;
5891
5966
private -> filldir_buf = kzalloc (PAGE_SIZE , GFP_KERNEL );
5892
5967
if (!private -> filldir_buf ) {
5893
5968
kfree (private );
@@ -5954,7 +6029,8 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
5954
6029
5955
6030
INIT_LIST_HEAD (& ins_list );
5956
6031
INIT_LIST_HEAD (& del_list );
5957
- put = btrfs_readdir_get_delayed_items (inode , & ins_list , & del_list );
6032
+ put = btrfs_readdir_get_delayed_items (inode , private -> last_index ,
6033
+ & ins_list , & del_list );
5958
6034
5959
6035
again :
5960
6036
key .type = BTRFS_DIR_INDEX_KEY ;
@@ -5972,6 +6048,8 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
5972
6048
break ;
5973
6049
if (found_key .offset < ctx -> pos )
5974
6050
continue ;
6051
+ if (found_key .offset > private -> last_index )
6052
+ break ;
5975
6053
if (btrfs_should_delete_dir_index (& del_list , found_key .offset ))
5976
6054
continue ;
5977
6055
di = btrfs_item_ptr (leaf , path -> slots [0 ], struct btrfs_dir_item );
@@ -6107,57 +6185,6 @@ static int btrfs_update_time(struct inode *inode, struct timespec64 *now,
6107
6185
return dirty ? btrfs_dirty_inode (BTRFS_I (inode )) : 0 ;
6108
6186
}
6109
6187
6110
- /*
6111
- * find the highest existing sequence number in a directory
6112
- * and then set the in-memory index_cnt variable to reflect
6113
- * free sequence numbers
6114
- */
6115
- static int btrfs_set_inode_index_count (struct btrfs_inode * inode )
6116
- {
6117
- struct btrfs_root * root = inode -> root ;
6118
- struct btrfs_key key , found_key ;
6119
- struct btrfs_path * path ;
6120
- struct extent_buffer * leaf ;
6121
- int ret ;
6122
-
6123
- key .objectid = btrfs_ino (inode );
6124
- key .type = BTRFS_DIR_INDEX_KEY ;
6125
- key .offset = (u64 )- 1 ;
6126
-
6127
- path = btrfs_alloc_path ();
6128
- if (!path )
6129
- return - ENOMEM ;
6130
-
6131
- ret = btrfs_search_slot (NULL , root , & key , path , 0 , 0 );
6132
- if (ret < 0 )
6133
- goto out ;
6134
- /* FIXME: we should be able to handle this */
6135
- if (ret == 0 )
6136
- goto out ;
6137
- ret = 0 ;
6138
-
6139
- if (path -> slots [0 ] == 0 ) {
6140
- inode -> index_cnt = BTRFS_DIR_START_INDEX ;
6141
- goto out ;
6142
- }
6143
-
6144
- path -> slots [0 ]-- ;
6145
-
6146
- leaf = path -> nodes [0 ];
6147
- btrfs_item_key_to_cpu (leaf , & found_key , path -> slots [0 ]);
6148
-
6149
- if (found_key .objectid != btrfs_ino (inode ) ||
6150
- found_key .type != BTRFS_DIR_INDEX_KEY ) {
6151
- inode -> index_cnt = BTRFS_DIR_START_INDEX ;
6152
- goto out ;
6153
- }
6154
-
6155
- inode -> index_cnt = found_key .offset + 1 ;
6156
- out :
6157
- btrfs_free_path (path );
6158
- return ret ;
6159
- }
6160
-
6161
6188
/*
6162
6189
* helper to find a free sequence number in a given directory. This current
6163
6190
* code is very simple, later versions will do smarter things in the btree
0 commit comments