24
24
#include "xfs_zone_priv.h"
25
25
#include "xfs_zones.h"
26
26
#include "xfs_trace.h"
27
+ #include "xfs_mru_cache.h"
27
28
28
29
void
29
30
xfs_open_zone_put (
@@ -796,6 +797,100 @@ xfs_submit_zoned_bio(
796
797
submit_bio (& ioend -> io_bio );
797
798
}
798
799
800
+ /*
801
+ * Cache the last zone written to for an inode so that it is considered first
802
+ * for subsequent writes.
803
+ */
804
+ struct xfs_zone_cache_item {
805
+ struct xfs_mru_cache_elem mru ;
806
+ struct xfs_open_zone * oz ;
807
+ };
808
+
809
+ static inline struct xfs_zone_cache_item *
810
+ xfs_zone_cache_item (struct xfs_mru_cache_elem * mru )
811
+ {
812
+ return container_of (mru , struct xfs_zone_cache_item , mru );
813
+ }
814
+
815
+ static void
816
+ xfs_zone_cache_free_func (
817
+ void * data ,
818
+ struct xfs_mru_cache_elem * mru )
819
+ {
820
+ struct xfs_zone_cache_item * item = xfs_zone_cache_item (mru );
821
+
822
+ xfs_open_zone_put (item -> oz );
823
+ kfree (item );
824
+ }
825
+
826
+ /*
827
+ * Check if we have a cached last open zone available for the inode and
828
+ * if yes return a reference to it.
829
+ */
830
+ static struct xfs_open_zone *
831
+ xfs_cached_zone (
832
+ struct xfs_mount * mp ,
833
+ struct xfs_inode * ip )
834
+ {
835
+ struct xfs_mru_cache_elem * mru ;
836
+ struct xfs_open_zone * oz ;
837
+
838
+ mru = xfs_mru_cache_lookup (mp -> m_zone_cache , ip -> i_ino );
839
+ if (!mru )
840
+ return NULL ;
841
+ oz = xfs_zone_cache_item (mru )-> oz ;
842
+ if (oz ) {
843
+ /*
844
+ * GC only steals open zones at mount time, so no GC zones
845
+ * should end up in the cache.
846
+ */
847
+ ASSERT (!oz -> oz_is_gc );
848
+ ASSERT (atomic_read (& oz -> oz_ref ) > 0 );
849
+ atomic_inc (& oz -> oz_ref );
850
+ }
851
+ xfs_mru_cache_done (mp -> m_zone_cache );
852
+ return oz ;
853
+ }
854
+
855
+ /*
856
+ * Update the last used zone cache for a given inode.
857
+ *
858
+ * The caller must have a reference on the open zone.
859
+ */
860
+ static void
861
+ xfs_zone_cache_create_association (
862
+ struct xfs_inode * ip ,
863
+ struct xfs_open_zone * oz )
864
+ {
865
+ struct xfs_mount * mp = ip -> i_mount ;
866
+ struct xfs_zone_cache_item * item = NULL ;
867
+ struct xfs_mru_cache_elem * mru ;
868
+
869
+ ASSERT (atomic_read (& oz -> oz_ref ) > 0 );
870
+ atomic_inc (& oz -> oz_ref );
871
+
872
+ mru = xfs_mru_cache_lookup (mp -> m_zone_cache , ip -> i_ino );
873
+ if (mru ) {
874
+ /*
875
+ * If we have an association already, update it to point to the
876
+ * new zone.
877
+ */
878
+ item = xfs_zone_cache_item (mru );
879
+ xfs_open_zone_put (item -> oz );
880
+ item -> oz = oz ;
881
+ xfs_mru_cache_done (mp -> m_zone_cache );
882
+ return ;
883
+ }
884
+
885
+ item = kmalloc (sizeof (* item ), GFP_KERNEL );
886
+ if (!item ) {
887
+ xfs_open_zone_put (oz );
888
+ return ;
889
+ }
890
+ item -> oz = oz ;
891
+ xfs_mru_cache_insert (mp -> m_zone_cache , ip -> i_ino , & item -> mru );
892
+ }
893
+
799
894
void
800
895
xfs_zone_alloc_and_submit (
801
896
struct iomap_ioend * ioend ,
@@ -819,11 +914,16 @@ xfs_zone_alloc_and_submit(
819
914
*/
820
915
if (!* oz && ioend -> io_offset )
821
916
* oz = xfs_last_used_zone (ioend );
917
+ if (!* oz )
918
+ * oz = xfs_cached_zone (mp , ip );
919
+
822
920
if (!* oz ) {
823
921
select_zone :
824
922
* oz = xfs_select_zone (mp , write_hint , pack_tight );
825
923
if (!* oz )
826
924
goto out_error ;
925
+
926
+ xfs_zone_cache_create_association (ip , * oz );
827
927
}
828
928
829
929
alloc_len = xfs_zone_alloc_blocks (* oz , XFS_B_TO_FSB (mp , ioend -> io_size ),
@@ -1211,6 +1311,14 @@ xfs_mount_zones(
1211
1311
error = xfs_zone_gc_mount (mp );
1212
1312
if (error )
1213
1313
goto out_free_zone_info ;
1314
+
1315
+ /*
1316
+ * Set up a mru cache to track inode to open zone for data placement
1317
+ * purposes. The magic values for group count and life time is the
1318
+ * same as the defaults for file streams, which seems sane enough.
1319
+ */
1320
+ xfs_mru_cache_create (& mp -> m_zone_cache , mp ,
1321
+ 5000 , 10 , xfs_zone_cache_free_func );
1214
1322
return 0 ;
1215
1323
1216
1324
out_free_zone_info :
@@ -1224,4 +1332,5 @@ xfs_unmount_zones(
1224
1332
{
1225
1333
xfs_zone_gc_unmount (mp );
1226
1334
xfs_free_zone_info (mp -> m_zone_info );
1335
+ xfs_mru_cache_destroy (mp -> m_zone_cache );
1227
1336
}
0 commit comments