1+ #include <errno.h>
2+ #include <fcntl.h>
3+ #include <stdlib.h>
4+ #include <stdint.h>
5+ #include <stdbool.h>
6+ #include <string.h>
7+ #include <stdio.h>
8+ #include <unistd.h>
9+
10+ #include <sys/stat.h>
11+ #include <sys/mman.h>
12+ #include <sys/types.h>
13+ #include <linux/limits.h>
14+
15+ #include "common/list.h"
16+ #include "criu-amdgpu.pb-c.h"
17+
18+ #include "xmalloc.h"
19+ #include "criu-log.h"
20+ #include "amdgpu_plugin_drm.h"
21+ #include "amdgpu_plugin_util.h"
22+ #include "amdgpu_plugin_dmabuf.h"
23+ #include "fdstore.h"
24+
25+ #include "util.h"
26+ #include "common/scm.h"
27+
28+ struct dmabuf {
29+ int id ;
30+ int dmabuf_fd ;
31+ struct list_head node ;
32+ };
33+
34+ static LIST_HEAD (dmabuf_list );
35+
36+ /* Return < 0 for error, > 0 for "not a dmabuf" and 0 "is a dmabuf" */
37+ int get_dmabuf_info (int fd , struct stat * st )
38+ {
39+ char path [PATH_MAX ];
40+
41+ if (read_fd_link (fd , path , sizeof (path )) < 0 )
42+ return -1 ;
43+
44+ if (strncmp (path , DMABUF_LINK , strlen (DMABUF_LINK )) != 0 )
45+ return 1 ;
46+
47+ return 0 ;
48+ }
49+
50+ int __amdgpu_plugin_dmabuf_dump (int dmabuf_fd , int id )
51+ {
52+ int ret = 0 ;
53+ char path [PATH_MAX ];
54+ size_t len = 0 ;
55+ unsigned char * buf = NULL ;
56+ int gem_handle ;
57+
58+ pr_info ("TWI: Dumping dmabuf fd = %d\n" , dmabuf_fd );
59+
60+ gem_handle = handle_for_shared_bo_fd (dmabuf_fd );
61+ if (gem_handle < 0 ) {
62+ pr_err ("Failed to get handle for dmabuf_fd = %d\n" , dmabuf_fd );
63+ return - EAGAIN ; /* Retry needed */
64+ }
65+
66+ CriuDmabufNode * node = xmalloc (sizeof (* node ));
67+ if (!node ) {
68+ pr_err ("Failed to allocate memory for dmabuf node\n" );
69+ return - ENOMEM ;
70+ }
71+ criu_dmabuf_node__init (node );
72+
73+ node -> gem_handle = gem_handle ;
74+
75+ if (node -> gem_handle < 0 ) {
76+ pr_err ("Failed to get handle for dmabuf_fd\n" );
77+ xfree (node );
78+ return - EINVAL ;
79+ }
80+
81+ /* Serialize metadata to a file */
82+ snprintf (path , sizeof (path ), IMG_DMABUF_FILE , id );
83+ len = criu_dmabuf_node__get_packed_size (node );
84+ buf = xmalloc (len );
85+ if (!buf ) {
86+ pr_err ("Failed to allocate buffer for dmabuf metadata\n" );
87+ xfree (node );
88+ return - ENOMEM ;
89+ }
90+ criu_dmabuf_node__pack (node , buf );
91+ ret = write_img_file (path , buf , len );
92+
93+ xfree (buf );
94+ xfree (node );
95+ return ret ;
96+ }
97+
98+ int amdgpu_plugin_dmabuf_restore (int id )
99+ {
100+ char path [PATH_MAX ];
101+ size_t img_size ;
102+ FILE * img_fp = NULL ;
103+ int ret = 0 ;
104+ CriuDmabufNode * rd = NULL ;
105+ unsigned char * buf = NULL ;
106+ int fd_id ;
107+
108+ snprintf (path , sizeof (path ), IMG_DMABUF_FILE , id );
109+
110+ pr_info ("TWI: Restoring dmabuf fd, id = %d\n" , id );
111+
112+ /* Read serialized metadata */
113+ img_fp = open_img_file (path , false, & img_size );
114+ if (!img_fp ) {
115+ pr_err ("Failed to open dmabuf metadata file: %s\n" , path );
116+ return - EINVAL ;
117+ }
118+
119+ pr_debug ("dmabuf Image file size:%ld\n" , img_size );
120+ buf = xmalloc (img_size );
121+ if (!buf ) {
122+ pr_perror ("Failed to allocate memory" );
123+ return - ENOMEM ;
124+ }
125+
126+ ret = read_fp (img_fp , buf , img_size );
127+ if (ret ) {
128+ pr_perror ("Unable to read from %s" , path );
129+ xfree (buf );
130+ return ret ;
131+ }
132+
133+ rd = criu_dmabuf_node__unpack (NULL , img_size , buf );
134+ if (rd == NULL ) {
135+ pr_perror ("Unable to parse the dmabuf message %d" , id );
136+ xfree (buf );
137+ fclose (img_fp );
138+ return -1 ;
139+ }
140+ fclose (img_fp );
141+
142+ pr_info ("TWI: dmabuf node gem_handle = %d\n" , rd -> gem_handle );
143+
144+ /* Match GEM handle with shared_dmabuf list */
145+ fd_id = amdgpu_id_for_handle (rd -> gem_handle );
146+ if (fd_id == -1 ) {
147+ pr_err ("Failed to find dmabuf_fd for GEM handle = %d\n" ,
148+ rd -> gem_handle );
149+ return 1 ;
150+ }
151+ int dmabuf_fd = fdstore_get (fd_id );
152+ pr_info ("TWI: dmabuf node fd_id = %d, dmabuf_fd = %d\n" , fd_id , dmabuf_fd );
153+ if (dmabuf_fd == -1 ) {
154+ pr_err ("Failed to find dmabuf_fd for GEM handle = %d\n" ,
155+ rd -> gem_handle );
156+ return 1 ; /* Retry needed */
157+ } else {
158+ pr_info ("Restored dmabuf_fd = %d for GEM handle = %d\n" ,
159+ dmabuf_fd , rd -> gem_handle );
160+ }
161+ ret = dmabuf_fd ;
162+
163+ pr_info ("Successfully restored dmabuf_fd %d\n" ,
164+ dmabuf_fd );
165+ criu_dmabuf_node__free_unpacked (rd , NULL );
166+ xfree (buf );
167+ return ret ;
168+ }
169+
170+ int amdgpu_plugin_dmabuf_dump (int dmabuf_fd , int id )
171+ {
172+ int ret ;
173+
174+ ret = __amdgpu_plugin_dmabuf_dump (dmabuf_fd , id );
175+ if (ret == - EAGAIN ) {
176+ struct dmabuf * b = xmalloc (sizeof (* b ));
177+ b -> id = id ;
178+ b -> dmabuf_fd = dmabuf_fd ;
179+ list_add (& b -> node , & dmabuf_list );
180+ return 0 ;
181+ }
182+ return ret ;
183+ }
184+
185+ int try_dump_dmabuf_list ()
186+ {
187+ struct dmabuf * b , * t ;
188+ list_for_each_entry_safe (b , t , & dmabuf_list , node ) {
189+ int ret = __amdgpu_plugin_dmabuf_dump (b -> dmabuf_fd , b -> id );
190+ if (ret == - EAGAIN )
191+ continue ;
192+ else if (ret )
193+ return ret ;
194+ list_del (& b -> node );
195+ xfree (b );
196+ }
197+ return 0 ;
198+ }
199+
200+ int post_dump_dmabuf_check ()
201+ {
202+ if (!list_empty (& dmabuf_list )) {
203+ pr_err ("Not all dma buffers have been dumped\n" );
204+ return -1 ;
205+ }
206+ return 1 ;
207+ }
0 commit comments