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+
29+ struct dmabuf {
30+ int id ;
31+ int dmabuf_fd ;
32+ struct list_head node ;
33+ };
34+
35+ static LIST_HEAD (dmabuf_list );
36+
37+ /* Return < 0 for error, > 0 for "not a dmabuf" and 0 "is a dmabuf" */
38+ int get_dmabuf_info (int fd , struct stat * st )
39+ {
40+ char path [PATH_MAX ];
41+
42+ if (read_fd_link (fd , path , sizeof (path )) < 0 )
43+ return -1 ;
44+
45+ if (strncmp (path , DMABUF_LINK , strlen (DMABUF_LINK )) != 0 )
46+ return 1 ;
47+
48+ return 0 ;
49+ }
50+
51+ int __amdgpu_plugin_dmabuf_dump (int dmabuf_fd , int id ) {
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+ char path [PATH_MAX ];
100+ size_t img_size ;
101+ FILE * img_fp = NULL ;
102+ int ret = 0 ;
103+ CriuDmabufNode * rd = NULL ;
104+ unsigned char * buf = NULL ;
105+ int fd_id ;
106+
107+ snprintf (path , sizeof (path ), IMG_DMABUF_FILE , id );
108+
109+ pr_info ("TWI: Restoring dmabuf fd, id = %d\n" , id );
110+
111+ /* Read serialized metadata */
112+ img_fp = open_img_file (path , false, & img_size );
113+ if (!img_fp ) {
114+ pr_err ("Failed to open dmabuf metadata file: %s\n" , path );
115+ return - EINVAL ;
116+ }
117+
118+ pr_debug ("dmabuf Image file size:%ld\n" , img_size );
119+ buf = xmalloc (img_size );
120+ if (!buf ) {
121+ pr_perror ("Failed to allocate memory" );
122+ return - ENOMEM ;
123+ }
124+
125+ ret = read_fp (img_fp , buf , img_size );
126+ if (ret ) {
127+ pr_perror ("Unable to read from %s" , path );
128+ xfree (buf );
129+ return ret ;
130+ }
131+
132+ rd = criu_dmabuf_node__unpack (NULL , img_size , buf );
133+ if (rd == NULL ) {
134+ pr_perror ("Unable to parse the dmabuf message %d" , id );
135+ xfree (buf );
136+ fclose (img_fp );
137+ return -1 ;
138+ }
139+ fclose (img_fp );
140+
141+ pr_info ("TWI: dmabuf node gem_handle = %d\n" , rd -> gem_handle );
142+
143+ /* Match GEM handle with shared_dmabuf list */
144+ fd_id = amdgpu_id_for_handle (rd -> gem_handle );
145+ if (fd_id == -1 ) {
146+ pr_err ("Failed to find dmabuf_fd for GEM handle = %d\n" ,
147+ rd -> gem_handle );
148+ return 1 ;
149+ }
150+ int dmabuf_fd = fdstore_get (fd_id );
151+ pr_info ("TWI: dmabuf node fd_id = %d, dmabuf_fd = %d\n" , fd_id , dmabuf_fd );
152+ if (dmabuf_fd == -1 ) {
153+ pr_err ("Failed to find dmabuf_fd for GEM handle = %d\n" ,
154+ rd -> gem_handle );
155+ return 1 ; /* Retry needed */
156+ } else {
157+ pr_info ("Restored dmabuf_fd = %d for GEM handle = %d\n" ,
158+ dmabuf_fd , rd -> gem_handle );
159+ }
160+ ret = dmabuf_fd ;
161+
162+ pr_info ("Successfully restored dmabuf_fd %d\n" ,
163+ dmabuf_fd );
164+ criu_dmabuf_node__free_unpacked (rd , NULL );
165+ xfree (buf );
166+ return ret ;
167+ }
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