@@ -29,7 +29,7 @@ static int read_file2buffer(char *file_name, char **buffer, size_t *length)
2929 FILE * fd = fopen (file_name , "rb" );
3030
3131 if (!fd )
32- return errno ;
32+ return - errno ;
3333
3434 fseek (fd , 0 , SEEK_END );
3535 size_t length_bytes = ftell (fd );
@@ -39,7 +39,7 @@ static int read_file2buffer(char *file_name, char **buffer, size_t *length)
3939 * buffer = malloc (length_bytes );
4040 if (!* buffer ) {
4141 fclose (fd );
42- return errno ;
42+ return - errno ;
4343 }
4444 * length = fread (* buffer , 1 , length_bytes , fd );
4545 fclose (fd );
@@ -51,99 +51,117 @@ struct config {
5151 bool ctrl_init ;
5252 int data_area ;
5353 char * cfg_file ;
54- bool is_input_file ;
54+ char * binary_file ;
5555};
5656
57+ static void cleanup_json_object (struct json_object * * jobj_ptr )
58+ {
59+ json_free_object (* jobj_ptr );
60+ * jobj_ptr = NULL ;
61+ }
62+
5763int solidigm_get_telemetry_log (int argc , char * * argv , struct command * cmd , struct plugin * plugin )
5864{
5965 const char * desc = "Parse Solidigm Telemetry log" ;
6066 const char * hgen = "Controls when to generate new host initiated report. Default value '1' generates new host initiated report, value '0' causes retrieval of existing log." ;
6167 const char * cgen = "Gather report generated by the controller." ;
6268 const char * dgen = "Pick which telemetry data area to report. Default is 3 to fetch areas 1-3. Valid options are 1, 2, 3, 4." ;
6369 const char * cfile = "JSON configuration file" ;
64- const char * sfile = "data source <device> is binary file containing log dump instead of block or character device" ;
65- struct nvme_dev * dev ;
70+ const char * sfile = "binary file containing log dump" ;
71+ bool has_binary_file = false;
72+
73+ _cleanup_nvme_dev_ struct nvme_dev * dev = NULL ;
74+
75+ _cleanup_free_ struct nvme_telemetry_log * tlog = NULL ;
76+
77+ __attribute__((cleanup (cleanup_json_object ))) struct json_object * configuration = NULL ;
78+
79+ __attribute__((cleanup (cleanup_json_object ))) struct json_object * root =
80+ json_create_object ();
6681
6782 struct telemetry_log tl = {
68- .root = json_create_object (),
69- .log = NULL ,
83+ .root = root ,
7084 };
7185
7286 struct config cfg = {
7387 .host_gen = 1 ,
7488 .ctrl_init = false,
75- .data_area = -1 ,
76- .cfg_file = NULL ,
77- .is_input_file = false,
7889 };
7990
8091 OPT_ARGS (opts ) = {
8192 OPT_UINT ("host-generate" , 'g' , & cfg .host_gen , hgen ),
8293 OPT_FLAG ("controller-init" , 'c' , & cfg .ctrl_init , cgen ),
8394 OPT_UINT ("data-area" , 'd' , & cfg .data_area , dgen ),
8495 OPT_FILE ("config-file" , 'j' , & cfg .cfg_file , cfile ),
85- OPT_FLAG ("source-file" , 's' , & cfg .is_input_file , sfile ),
86- OPT_INCR ("verbose" , 'v' , & nvme_cfg .verbose , verbose ),
96+ OPT_FILE ("source-file" , 's' , & cfg .binary_file , sfile ),
97+ OPT_INCR ("verbose" , 'v' , & nvme_cfg .verbose , verbose ),
8798 OPT_END ()
8899 };
89100
90101 int err = argconfig_parse (argc , argv , desc , opts );
91102
92- if (err )
93- goto ret ;
103+ if (err ) {
104+ nvme_show_status (err );
105+ return err ;
106+ }
94107
95108 /* When not selected on the command line, get minimum data area required */
96- if (cfg .data_area == -1 )
97- cfg .data_area = cfg .cfg_file ? 3 : 1 ;
98-
99- if (cfg .is_input_file ) {
100- if (optind >= argc ) {
101- err = errno = EINVAL ;
102- perror (argv [0 ]);
103- goto ret ;
109+ if (!argconfig_parse_seen (opts , "data-area" ))
110+ cfg .data_area = argconfig_parse_seen (opts , "config-file" ) ? 3 : 1 ;
111+
112+ has_binary_file = argconfig_parse_seen (opts , "source-file" );
113+ if (has_binary_file ) {
114+ // If a binary file is provided, we don't want to open a device.
115+ // GNU getopt() permutes the contents of argv as it scans,
116+ // so that eventually all the nonoptions are at the end.
117+ if (argc > optind ) {
118+ errno = EINVAL ;
119+ err = - errno ;
120+ nvme_show_status (err );
121+ return err ;
104122 }
105- char * binary_file_name = argv [optind ];
106-
107- err = read_file2buffer (binary_file_name , (char * * )& tl .log , & tl .log_size );
123+ err = read_file2buffer (cfg .binary_file , (char * * )& tlog , & tl .log_size );
108124 } else {
109125 err = parse_and_open (& dev , argc , argv , desc , opts );
110126 }
111- if (err )
112- goto ret ;
127+ if (err ) {
128+ nvme_show_status (err );
129+ return err ;
130+ }
113131
114132 if (cfg .host_gen > 1 ) {
115133 SOLIDIGM_LOG_WARNING ("Invalid host-generate value '%d'" , cfg .host_gen );
116- err = EINVAL ;
117- goto close_fd ;
134+ err = - EINVAL ;
135+ nvme_show_status (err );
136+ return err ;
118137 }
119138
120- if (cfg . cfg_file ) {
121- char * conf_str = NULL ;
139+ if (argconfig_parse_seen ( opts , "config-file" ) ) {
140+ _cleanup_free_ char * conf_str = NULL ;
122141 size_t length = 0 ;
123142
124143 err = read_file2buffer (cfg .cfg_file , & conf_str , & length );
125144 if (err ) {
126- SOLIDIGM_LOG_WARNING ("Failed to open JSON configuration file %s: %s!" ,
127- cfg .cfg_file , strerror (err ));
128- goto close_fd ;
145+ nvme_show_status (err );
146+ return err ;
129147 }
130148 struct json_tokener * jstok = json_tokener_new ();
131149
132- tl .configuration = json_tokener_parse_ex (jstok , conf_str , length );
133- free (conf_str );
150+ configuration = json_tokener_parse_ex (jstok , conf_str , length );
134151 if (jstok -> err != json_tokener_success ) {
135152 SOLIDIGM_LOG_WARNING ("Parsing error on JSON configuration file %s: %s (at offset %d)" ,
136153 cfg .cfg_file ,
137154 json_tokener_error_desc (jstok -> err ),
138155 jstok -> char_offset );
139156 json_tokener_free (jstok );
140157 err = EINVAL ;
141- goto close_fd ;
158+ return err ;
142159 }
143160 json_tokener_free (jstok );
161+ tl .configuration = configuration ;
144162 }
145163
146- if (!cfg . is_input_file ) {
164+ if (!has_binary_file ) {
147165 size_t max_data_tx ;
148166 size_t power2 ;
149167 __u8 mdts = 0 ;
@@ -152,11 +170,11 @@ int solidigm_get_telemetry_log(int argc, char **argv, struct command *cmd, struc
152170 if (err < 0 ) {
153171 SOLIDIGM_LOG_WARNING ("identify_ctrl: %s" ,
154172 nvme_strerror (errno ));
155- goto close_fd ;
173+ return err ;
156174 } else if (err > 0 ) {
157175 nvme_show_status (err );
158176 SOLIDIGM_LOG_WARNING ("Failed to acquire identify ctrl %d!" , err );
159- goto close_fd ;
177+ return err ;
160178 }
161179 power2 = max_data_tx / NVME_LOG_PAGE_PDU_SIZE ;
162180 while (power2 && !(1 & power2 )) {
@@ -165,31 +183,22 @@ int solidigm_get_telemetry_log(int argc, char **argv, struct command *cmd, struc
165183 }
166184
167185 err = sldgm_dynamic_telemetry (dev_fd (dev ), cfg .host_gen , cfg .ctrl_init , true,
168- mdts , cfg .data_area , & tl . log , & tl .log_size );
186+ mdts , cfg .data_area , & tlog , & tl .log_size );
169187 if (err < 0 ) {
170188 SOLIDIGM_LOG_WARNING ("get-telemetry-log: %s" ,
171189 nvme_strerror (errno ));
172- goto close_fd ;
190+ return err ;
173191 } else if (err > 0 ) {
174192 nvme_show_status (err );
175193 SOLIDIGM_LOG_WARNING ("Failed to acquire telemetry log %d!" , err );
176- goto close_fd ;
194+ return err ;
177195 }
178196 }
197+ tl .log = tlog ;
179198 solidigm_telemetry_log_data_areas_parse (& tl , cfg .data_area );
180199
181200 json_print_object (tl .root , NULL );
182- json_free_object (tl .root );
183201 printf ("\n" );
184202
185- close_fd :
186- if (!cfg .is_input_file ) {
187- /* Redundant close() to make static code analysis happy */
188- close (dev -> direct .fd );
189- dev_close (dev );
190- }
191- ret :
192- json_free_object (tl .configuration );
193- free (tl .log );
194203 return err ;
195204}
0 commit comments