30
30
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31
31
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
32
*/
33
+
34
+ #include <sys/mman.h>
35
+ #include <sys/stat.h>
36
+ #include <sys/types.h>
37
+ #include <fcntl.h>
38
+
33
39
#include <ocf/ocf.h>
34
40
#include <execinfo.h>
35
41
@@ -590,6 +596,195 @@ vbdev_ocf_ctx_log_printf(ocf_logger_t logger, ocf_logger_lvl_t lvl,
590
596
return 0 ;
591
597
}
592
598
599
+ struct ocf_cache_persistent_meta_segment_descriptor {
600
+ int id ;
601
+
602
+ bool valid ;
603
+ size_t size ;
604
+ size_t offset ;
605
+ };
606
+
607
+ #define MAX_SEGMENTS 20
608
+ struct shm_superblock {
609
+ struct ocf_cache_persistent_meta_segment_descriptor segments [MAX_SEGMENTS ];
610
+ };
611
+
612
+
613
+ static ocf_persistent_meta_zone_t
614
+ vbdev_ocf_persistent_meta_init (ocf_cache_t cache , size_t size , bool * load )
615
+ {
616
+ struct vbdev_ocf_cache_ctx * ctx = ocf_cache_get_priv (cache );
617
+ struct ocf_persistent_meta_zone * pmeta ;
618
+ struct stat stat_buf ;
619
+ void * shm ;
620
+ struct shm_superblock * shm_sb ;
621
+ int zone ;
622
+
623
+ size += sizeof (struct shm_superblock );
624
+
625
+ if (!ctx -> create && ctx -> force )
626
+ return NULL ;
627
+
628
+ for (zone = 0 ; zone < MAX_PERSISTENT_ZONES ; zone ++ ) {
629
+ if (!ctx -> persistent_meta [zone ].fd )
630
+ break ;
631
+ }
632
+
633
+ if (zone >= MAX_PERSISTENT_ZONES )
634
+ return NULL ;
635
+
636
+
637
+ pmeta = & ctx -> persistent_meta [zone ];
638
+ * load = false;
639
+
640
+ snprintf (pmeta -> name , NAME_MAX , "/ocf.%s.%u" , ctx -> cache_name , zone );
641
+
642
+ pmeta -> fd = shm_open (pmeta -> name , O_RDWR | O_CREAT , S_IRUSR | S_IWUSR );
643
+ if (pmeta -> fd < 0 ) {
644
+ SPDK_ERRLOG ("Can't open SHM %s\n" , pmeta -> name );
645
+ return NULL ;
646
+ }
647
+
648
+ if (ctx -> force ) {
649
+ SPDK_NOTICELOG ("Using force, truncating SHM %s\n" ,
650
+ pmeta -> name );
651
+ if (ftruncate (pmeta -> fd , 0 ) < 0 ) {
652
+ SPDK_ERRLOG ("Failed to truncate\n" );
653
+ goto err_stat ;
654
+ }
655
+
656
+ } else if (fstat (pmeta -> fd , & stat_buf ) < 0 ) {
657
+ SPDK_ERRLOG ("Can't stat SHM %s\n" , pmeta -> name );
658
+ goto err_stat ;
659
+ }
660
+
661
+ if (!ctx -> force && stat_buf .st_size != 0 ) {
662
+ if (ctx -> create ) {
663
+ SPDK_ERRLOG ("SHM %s found, but no force specified!\n" ,
664
+ pmeta -> name );
665
+ goto err_stat ;
666
+ }
667
+
668
+ * load = true;
669
+ SPDK_NOTICELOG ("Loading from SHM\n" );
670
+ if (stat_buf .st_size < size ) {
671
+ if (ftruncate (pmeta -> fd , size ) < 0 ) {
672
+ SPDK_ERRLOG ("Failed to extend SHM\n" );
673
+ goto err_stat ;
674
+ }
675
+ pmeta -> size = size ;
676
+ } else if (stat_buf .st_size == size ) {
677
+ pmeta -> size = size ;
678
+ } else {
679
+ SPDK_NOTICELOG ("Refusing to shrink SHM\n" );
680
+ pmeta -> size = stat_buf .st_size ;
681
+ }
682
+ } else {
683
+ SPDK_NOTICELOG ("Set SHM size\n" );
684
+ if (ftruncate (pmeta -> fd , size ) < 0 ) {
685
+ SPDK_ERRLOG ("Failed to truncate\n" );
686
+ goto err_stat ;
687
+ }
688
+
689
+ pmeta -> size = size ;
690
+ }
691
+
692
+ shm = mmap (NULL , pmeta -> size , PROT_READ | PROT_WRITE , MAP_SHARED , pmeta -> fd , 0 );
693
+ if (shm == MAP_FAILED ) {
694
+ SPDK_ERRLOG ("Failed to map shm\n" );
695
+ goto err_stat ;
696
+ }
697
+
698
+ pmeta -> data = shm ;
699
+ shm_sb = shm ;
700
+
701
+ if (mlock (shm , pmeta -> size )) {
702
+ SPDK_ERRLOG ("Failed to mlock\n" );
703
+
704
+ goto err_mlock ;
705
+ }
706
+
707
+
708
+ if (!* load ) {
709
+ shm_sb -> segments [0 ].size = sizeof (struct shm_superblock );
710
+ shm_sb -> segments [0 ].offset = 0 ;
711
+ shm_sb -> segments [0 ].id = -1 ;
712
+ shm_sb -> segments [0 ].valid = true;
713
+ }
714
+
715
+ return pmeta ;
716
+
717
+ err_mlock :
718
+ munmap (pmeta -> data , pmeta -> size );
719
+ err_stat :
720
+ close (pmeta -> fd );
721
+ shm_unlink (pmeta -> name );
722
+
723
+ return NULL ;
724
+ }
725
+
726
+ static int
727
+ vbdev_ocf_persistent_meta_deinit (struct ocf_persistent_meta_zone * zone )
728
+ {
729
+ /*
730
+ munmap(zone->data, zone->size);
731
+ close(zone->fd);
732
+ shm_unlink(zone->name);
733
+ */
734
+
735
+ return 0 ;
736
+ }
737
+
738
+ static void *
739
+ vbdev_ocf_persistent_meta_alloc (struct ocf_persistent_meta_zone * zone , size_t size ,
740
+ int alloc_id , bool * load )
741
+ {
742
+ int i ;
743
+ size_t sum = 0 ;
744
+ struct shm_superblock * shm_sb = zone -> data ;
745
+ struct ocf_cache_persistent_meta_segment_descriptor * desc =
746
+ shm_sb -> segments ;
747
+
748
+ alloc_id ++ ;
749
+ * load = false;
750
+
751
+ for (i = 0 ; i < MAX_SEGMENTS ; i ++ ) {
752
+ /* assume no fragmentation */
753
+ if (!desc [i ].valid )
754
+ break ;
755
+
756
+ sum += desc [i ].size ;
757
+
758
+ /* assume no size change */
759
+ if (desc [i ].id == alloc_id ) {
760
+ * load = true;
761
+ return zone -> data + desc [i ].offset ;
762
+ }
763
+ }
764
+
765
+ if (i == MAX_SEGMENTS )
766
+ return NULL ;
767
+
768
+ /* TODO: align */
769
+
770
+ if (sum + size > zone -> size )
771
+ return NULL ;
772
+
773
+ desc [i ].id = alloc_id ;
774
+ desc [i ].offset = sum ;
775
+ desc [i ].size = size ;
776
+ desc [i ].valid = true;
777
+
778
+ return zone -> data + desc [i ].offset ;
779
+ }
780
+
781
+ static int
782
+ vbdev_ocf_persistent_meta_free (struct ocf_persistent_meta_zone * zone , int alloc_id ,
783
+ void * ptr )
784
+ {
785
+ return 0 ;
786
+ }
787
+
593
788
static const struct ocf_ctx_config vbdev_ocf_ctx_cfg = {
594
789
.name = "OCF SPDK" ,
595
790
@@ -613,6 +808,13 @@ static const struct ocf_ctx_config vbdev_ocf_ctx_cfg = {
613
808
.kick = vbdev_ocf_volume_updater_kick ,
614
809
},
615
810
811
+ .persistent_meta = {
812
+ .init = vbdev_ocf_persistent_meta_init ,
813
+ .deinit = vbdev_ocf_persistent_meta_deinit ,
814
+ .alloc = vbdev_ocf_persistent_meta_alloc ,
815
+ .free = vbdev_ocf_persistent_meta_free ,
816
+ },
817
+
616
818
.cleaner = {
617
819
.init = vbdev_ocf_ctx_cleaner_init ,
618
820
.stop = vbdev_ocf_ctx_cleaner_stop ,
0 commit comments