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+
59+ gem_handle = handle_for_shared_bo_fd (dmabuf_fd );
60+ if (gem_handle < 0 ) {
61+ pr_err ("Failed to get handle for dmabuf_fd = %d\n" , dmabuf_fd );
62+ return - EAGAIN ; /* Retry needed */
63+ }
64+
65+ CriuDmabufNode * node = xmalloc (sizeof (* node ));
66+ if (!node ) {
67+ pr_err ("Failed to allocate memory for dmabuf node\n" );
68+ return - ENOMEM ;
69+ }
70+ criu_dmabuf_node__init (node );
71+
72+ node -> gem_handle = gem_handle ;
73+
74+ if (node -> gem_handle < 0 ) {
75+ pr_err ("Failed to get handle for dmabuf_fd\n" );
76+ xfree (node );
77+ return - EINVAL ;
78+ }
79+
80+ /* Serialize metadata to a file */
81+ snprintf (path , sizeof (path ), IMG_DMABUF_FILE , id );
82+ len = criu_dmabuf_node__get_packed_size (node );
83+ buf = xmalloc (len );
84+ if (!buf ) {
85+ pr_err ("Failed to allocate buffer for dmabuf metadata\n" );
86+ xfree (node );
87+ return - ENOMEM ;
88+ }
89+ criu_dmabuf_node__pack (node , buf );
90+ ret = write_img_file (path , buf , len );
91+
92+ xfree (buf );
93+ xfree (node );
94+ return ret ;
95+ }
96+
97+ int amdgpu_plugin_dmabuf_restore (int id ) {
98+ char path [PATH_MAX ];
99+ size_t img_size ;
100+ FILE * img_fp = NULL ;
101+ int ret = 0 ;
102+ CriuDmabufNode * rd = NULL ;
103+ unsigned char * buf = NULL ;
104+ int fd_id ;
105+
106+ snprintf (path , sizeof (path ), IMG_DMABUF_FILE , id );
107+
108+ /* Read serialized metadata */
109+ img_fp = open_img_file (path , false, & img_size );
110+ if (!img_fp ) {
111+ pr_err ("Failed to open dmabuf metadata file: %s\n" , path );
112+ return - EINVAL ;
113+ }
114+
115+ pr_debug ("dmabuf Image file size:%ld\n" , img_size );
116+ buf = xmalloc (img_size );
117+ if (!buf ) {
118+ pr_perror ("Failed to allocate memory" );
119+ return - ENOMEM ;
120+ }
121+
122+ ret = read_fp (img_fp , buf , img_size );
123+ if (ret ) {
124+ pr_perror ("Unable to read from %s" , path );
125+ xfree (buf );
126+ return ret ;
127+ }
128+
129+ rd = criu_dmabuf_node__unpack (NULL , img_size , buf );
130+ if (rd == NULL ) {
131+ pr_perror ("Unable to parse the dmabuf message %d" , id );
132+ xfree (buf );
133+ fclose (img_fp );
134+ return -1 ;
135+ }
136+ fclose (img_fp );
137+
138+ /* Match GEM handle with shared_dmabuf list */
139+ fd_id = amdgpu_id_for_handle (rd -> gem_handle );
140+ if (fd_id == -1 ) {
141+ pr_err ("Failed to find dmabuf_fd for GEM handle = %d\n" ,
142+ rd -> gem_handle );
143+ return 1 ;
144+ }
145+ int dmabuf_fd = fdstore_get (fd_id );
146+ if (dmabuf_fd == -1 ) {
147+ pr_err ("Failed to find dmabuf_fd for GEM handle = %d\n" ,
148+ rd -> gem_handle );
149+ return 1 ; /* Retry needed */
150+ } else {
151+ pr_info ("Restored dmabuf_fd = %d for GEM handle = %d\n" ,
152+ dmabuf_fd , rd -> gem_handle );
153+ }
154+ ret = dmabuf_fd ;
155+
156+ pr_info ("Successfully restored dmabuf_fd %d\n" ,
157+ dmabuf_fd );
158+ criu_dmabuf_node__free_unpacked (rd , NULL );
159+ xfree (buf );
160+ return ret ;
161+ }
162+
163+
164+ int amdgpu_plugin_dmabuf_dump (int dmabuf_fd , int id )
165+ {
166+ int ret ;
167+
168+ ret = __amdgpu_plugin_dmabuf_dump (dmabuf_fd , id );
169+ if (ret == - EAGAIN ) {
170+ struct dmabuf * b = xmalloc (sizeof (* b ));
171+ b -> id = id ;
172+ b -> dmabuf_fd = dmabuf_fd ;
173+ list_add (& b -> node , & dmabuf_list );
174+ return 0 ;
175+ }
176+ return ret ;
177+ }
178+
179+ int try_dump_dmabuf_list ()
180+ {
181+ struct dmabuf * b , * t ;
182+ list_for_each_entry_safe (b , t , & dmabuf_list , node ) {
183+ int ret = __amdgpu_plugin_dmabuf_dump (b -> dmabuf_fd , b -> id );
184+ if (ret == - EAGAIN )
185+ continue ;
186+ else if (ret )
187+ return ret ;
188+ list_del (& b -> node );
189+ xfree (b );
190+ }
191+ return 0 ;
192+ }
193+
194+ int post_dump_dmabuf_check ()
195+ {
196+ if (!list_empty (& dmabuf_list )) {
197+ pr_err ("Not all dma buffers have been dumped\n" );
198+ return -1 ;
199+ }
200+ return 1 ;
201+ }
0 commit comments