Whamcloud - gitweb
current branches now use lnet from HEAD
[fs/lustre-release.git] / lustre / snapfs / utils / snapctl.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <mntent.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <sys/ioctl.h>
7 #include <fcntl.h>
8 #include <unistd.h>
9 #include <errno.h>
10 #include <time.h>
11 #include <string.h>
12 #include <portals/list.h>
13 #include "parser.h"
14 #include "snapctl.h"
15 #include <snapfs_internal.h>
16
17 #define IOC_BUF_MAX_LEN 8192 
18 static char rawbuf[IOC_BUF_MAX_LEN];
19 static char *buf = rawbuf;
20 /*FIXME add this temporary, will use obd_ioc_data later*/
21 #define IOC_INIT(ptr)                                   \
22 do{                                                     \
23         struct ioc_data* pbuf;                          \
24         memset(buf, 0, sizeof(rawbuf));                 \
25         pbuf = (struct ioc_data*)buf;                   \
26         pbuf->ioc_inbuf = pbuf->ioc_bulk;               \
27         ptr = (struct ioc_snap_tbl_data *)pbuf->ioc_bulk; \
28 } while(0)
29
30 #define IOC_PACK(length)                \
31 do{                                             \
32         struct ioc_data* pbuf;                  \
33         pbuf = (struct ioc_data*)buf;           \
34         pbuf->ioc_inlen = length;               \
35 } while (0)
36
37 static struct list_head snap_list;
38 struct open_snap_device open_device_table;
39 struct snap_device snap_device_list[10];
40
41
42 static int get_snaplist()
43 {
44         FILE *mnt_filp = NULL;
45         int  error = 0;
46         
47         /*open mount list*/
48         mnt_filp = setmntent("/etc/mtab", "r");
49
50         if (!mnt_filp) 
51                 return -EINVAL;
52         /*get the mentent and check snap mount*/
53         while (!feof(mnt_filp)) {
54                  struct mntent* entry;
55
56                  entry = getmntent(mnt_filp);
57
58                  if (!entry) continue;
59
60                  if (!strcmp(entry->mnt_type, "snap_current")) {
61                         /*found a snap_mount structure add to the snaplist*/
62                         struct snap_mnt *s_mnt;
63                         char *opt = NULL;
64                         char dev_name[DEV_NAME_MAX_LEN];
65                         struct stat statbuf;
66                         
67                         s_mnt = (struct snap_mnt *) malloc(sizeof(struct snap_mnt));
68                         if (!s_mnt) {
69                                 error = ENOMEM;
70                                 goto exit;
71                         }
72                         memset(s_mnt, 0, sizeof(struct snap_mnt));
73                         memcpy(&s_mnt->device.name[0], entry->mnt_fsname, strlen(entry->mnt_fsname));
74                         memcpy(&s_mnt->device.mntpt[0], entry->mnt_dir, strlen(entry->mnt_dir));
75                         opt = hasmntopt(entry, "loop");
76                         memset(dev_name, 0, DEV_NAME_MAX_LEN);
77                         if (opt) {
78                                 /* Loop device mount find the real dev_name*/
79                                 char *name = opt, *name_dev = dev_name;
80
81                                 while (*name++ != '=');
82                                 while (*name != ',' && *name != ')' && *name ) {
83                                         *name_dev++ = *name++;  
84                                 }
85                 
86                         } else {
87                                 memcpy(dev_name, entry->mnt_fsname, strlen(entry->mnt_fsname)); 
88                         }
89                                 
90                         if ((error = stat(dev_name, &statbuf)) != 0) {
91                                 fprintf(stderr, "can not stat %s", strerror(errno));
92                                 goto exit;
93                         }
94                         s_mnt->device.dev = (unsigned long)statbuf.st_rdev;
95                         list_add(&s_mnt->snap_mnt_list, &snap_list);
96                  }
97         }
98 exit:
99         if (mnt_filp)
100                 endmntent(mnt_filp);
101         return error;
102 }
103
104 static void release_snap_list()
105 {
106         struct snap_mnt *snaplist;
107         
108         list_for_each_entry(snaplist, &snap_list, snap_mnt_list) {
109                 list_del(&snaplist->snap_mnt_list);
110                 free(snaplist);
111         }
112 }
113
114 void init_snap_list()
115 {
116         int i;
117
118         INIT_LIST_HEAD(&snap_list);
119         open_device_table.count = 0;
120         for(i = 0; i < 10; i++) {
121                 memset(&open_device_table.device[i].name[0], 
122                        0, DEV_NAME_MAX_LEN);
123                 open_device_table.device[i].fd = -1;
124         }
125 }
126
127 static int open_device(char *name, unsigned int dev)
128 {
129         int index=0, error = 0, i = 0, found = 0;
130
131         /*XXX Does these information necessary*/
132         for (i = 0; i < open_device_table.count; i++) {
133                 if (!strcmp(&open_device_table.device[i].name[0], name)) {
134                         index = i;
135                         found = 1;
136                         break;
137                 }
138         }
139         if (found == 0) {
140                 open_device_table.device[index].dev = dev;
141                 memset(&open_device_table.device[index].name[0], 
142                        0, DEV_NAME_MAX_LEN);
143                 memcpy(&open_device_table.device[index].name[0], 
144                        name, strlen(name));
145                 open_device_table.count ++;
146         }
147         /*FIXME If there are more than device, how to handle it*/
148         if (open_device_table.device[index].fd < 0) {
149                 /*open device*/
150                 int fd = open(SNAPDEV_NAME, O_RDWR);
151                 
152                 if (fd < 0) {
153                         if (errno == ENOENT) {
154                                 dev_t snap_dev=makedev(SNAP_PSDEV_MAJOR,SNAP_PSDEV_MINOR);  
155                                 /*create snapdevice node*/
156                                 error = mknod(SNAPDEV_NAME, S_IRUSR|S_IWUSR|S_IFCHR, snap_dev);
157                                 if (error) {
158                                         fprintf(stderr, "Can not make node %s :%s \n", 
159                                                 SNAPDEV_NAME, strerror(errno));
160                                         return (-errno);
161                                 }
162                                 if ((fd = open(SNAPDEV_NAME, O_RDWR)) < 0) {
163                                         fprintf(stderr, "Can not open node %s: %s\n", 
164                                                 SNAPDEV_NAME, strerror(errno));
165                                         return (-errno);
166                                 }
167                         } else {
168                                 fprintf(stderr, "Can not open node %s: %s %d \n", 
169                                         SNAPDEV_NAME, strerror(errno), errno);
170                                 return(-errno);
171                         }
172                 }
173                 open_device_table.device[index].fd = fd;
174         }
175         return 0;
176 }
177 static  int open_snap_device(char *name)
178 {
179         struct snap_mnt *snaplist;
180         int rc; 
181         get_snaplist();
182         list_for_each_entry(snaplist, &snap_list, snap_mnt_list) {
183                 if (!strcmp(&snaplist->device.name[0], name)) {
184                         rc = open_device(&snaplist->device.name[0], 
185                                     snaplist->device.dev);
186                         release_snap_list();    
187                         return rc;
188                 }
189         }
190         release_snap_list();    
191         fprintf(stderr, "%s are not snapdevice\n", name);
192         return (-EINVAL);
193 }
194 int snap_dev_open(int argc, char **argv)
195 {
196         char *dev_name;
197         int rc;
198
199         if (argc != 2) { 
200                 fprintf(stderr, "The argument count is not right \n");
201                 return CMD_HELP;
202         }
203         
204         dev_name = argv[1];
205         rc = open_snap_device(dev_name);
206         if (rc)
207                 fprintf(stderr, "%s are not snapdevice\n", dev_name);
208         return (rc);
209 }
210 int snap_dev_list(int argc, char **argv)
211 {
212         struct snap_mnt *snaplist;
213         int    index = 0;
214
215         if (argc != 1) { 
216                 fprintf(stderr, "The argument count is not right \n");
217                 return CMD_HELP;
218         }
219
220         get_snaplist();
221         printf("index:\t\tmount_point:\t\tdevice:\n");
222         list_for_each_entry(snaplist, &snap_list, snap_mnt_list) {
223                 printf("%d\t\t%s\t\t%s \n", index,
224                         &snaplist->device.mntpt[0], 
225                         &snaplist->device.name[0]);
226                 index++;
227         }
228         release_snap_list();
229         return 0;
230 }
231 static inline void print_snap_table(void * buf)
232 {
233         struct ioc_snap_tbl_data *ptable;
234         int    i;
235
236         ptable = (struct ioc_snap_tbl_data*)buf;
237         
238         printf("There are %d snapshot in the system\n", ptable->count);
239         printf("index\t\tname\t\t\ttime\t\t\n"); 
240         for (i = 0; i < ptable->count; i++) {
241                 struct  tm* local_time;         
242                 char    time[128];
243                 
244                 memset (time, 0, sizeof(time));
245                 local_time = localtime(&ptable->snaps[i].time);
246                 if (local_time) 
247                         strftime(time, sizeof(time), "%a %b %d %Y %H:%M:%S", local_time);                       
248                 printf("%-10d\t%-20s\t%s\n", ptable->snaps[i].index, ptable->snaps[i].name, time); 
249         }
250 }
251 int snap_snap_list(int argc, char **argv)
252 {
253         char *dev_name = NULL;
254         int i, rc = 0;
255
256         if (argc != 1 && argc != 2) {
257                 fprintf(stderr, "The argument count is not right\n");
258                 return CMD_HELP;
259         }
260         if (open_device_table.count == 0) {
261                 if (argc == 2) {
262                         dev_name = argv[1];             
263                 }       
264                 if (dev_name) {
265                         rc = open_snap_device(dev_name); 
266                 }
267                 if (!dev_name || rc) {  
268                         fprintf(stderr, "Please open a snapdevice first\n");
269                         return (-EINVAL);
270                 }
271         }
272         for (i = 0; i < open_device_table.count; i++) {
273                 struct ioc_snap_tbl_data *snap_ioc_data;
274
275                 IOC_INIT(snap_ioc_data);
276
277                 if (argc == 2) { 
278                         snap_ioc_data->no = atoi(argv[1]);
279                 } else { 
280                         snap_ioc_data->no = 0;
281                 }
282                 
283                 IOC_PACK(sizeof(struct ioc_snap_tbl_data));
284                 
285                 if ((rc = ioctl(open_device_table.device[i].fd, 
286                                 IOC_SNAP_PRINTTABLE, buf))) {
287                         fprintf(stderr, "can not retrive snaptable on device %s failed %d \n", 
288                                 &open_device_table.device[i].name[0], rc);
289                         return (rc);
290                 }
291                 if(((struct ioc_data*)buf)->ioc_bulk)
292                         print_snap_table(((struct ioc_data*)buf)->ioc_bulk);    
293         }
294         return rc;
295 }
296 int snap_snap_del(int argc, char **argv)
297 {
298         char   *dev_name = NULL, *snap_name = NULL;     
299         int    rc = 0, i;
300         
301         if (argc != 3 && argc !=2) {
302                 fprintf(stderr, "The argument count is not right \n");
303                 return CMD_HELP;
304         }
305         if (open_device_table.count == 0) {
306                 if (argc == 3) {
307                         dev_name = argv[1];             
308                 } else if (argc == 4) {
309                         dev_name = argv[2];
310                 }
311                 if (dev_name) {
312                         rc = open_snap_device(dev_name); 
313                 }
314                 if (!dev_name || rc) {  
315                         fprintf(stderr, "Please open a snapdevice first\n");
316                         return (-EINVAL);
317                 }
318         }
319         for (i = 0; i < open_device_table.count; i++) {
320                 struct ioc_snap_tbl_data *snap_ioc_data;
321
322                 IOC_INIT(snap_ioc_data);
323
324                 snap_ioc_data->count = 1;
325                 snap_ioc_data->dev = open_device_table.device[i].dev;
326
327                 if (argc == 3) { 
328                         snap_ioc_data->no = atoi(argv[1]);
329                         if (!snap_name)
330                                 snap_name = argv[2];
331                 } else { 
332                         snap_ioc_data->no = 0;
333                         if (!snap_name)
334                                 snap_name = argv[1];
335                 }
336                 memcpy(snap_ioc_data->snaps[0].name, 
337                                snap_name, strlen(snap_name));
338
339                 snap_ioc_data->snaps[0].time = time(NULL);
340                 
341                 IOC_PACK(sizeof(struct ioc_snap_tbl_data) + sizeof(struct snap));
342
343                 if ((rc = ioctl(open_device_table.device[i].fd, 
344                                         IOC_SNAP_DELETE, buf))) {
345                         fprintf(stderr, "del %s failed \n", snap_name);
346                 } else {
347                         fprintf(stderr, "del %s success\n", snap_name);
348                 }
349         }
350         return rc;
351 }
352 int snap_snap_add(int argc, char **argv)
353 {
354         char   *dev_name = NULL, *snap_name = NULL;     
355         int    rc = 0, i;
356         
357         if (argc != 3 && argc !=2 && argc !=4) {
358                 fprintf(stderr, "The argument count is not right \n");
359                 return CMD_HELP;
360         }
361         if (open_device_table.count == 0) {
362                 if (argc == 3) {
363                         dev_name = argv[1];             
364                         snap_name = argv[2];
365                 } else if (argc == 4) {
366                         dev_name = argv[2];
367                         snap_name = argv[3];
368                 }
369                 if (dev_name) {
370                         rc = open_snap_device(dev_name); 
371                 }
372                 if (!dev_name || rc) {  
373                         fprintf(stderr, "Please open a snapdevice first\n");
374                         return (-EINVAL);
375                 }
376         }
377         for (i = 0; i < open_device_table.count; i++) {
378                 struct ioc_snap_tbl_data *snap_ioc_data;
379
380                 IOC_INIT(snap_ioc_data);
381
382                 snap_ioc_data->count = 1;
383                 snap_ioc_data->dev = open_device_table.device[i].dev;
384
385                 if (argc == 3) { 
386                         snap_ioc_data->no = atoi(argv[1]);
387                         if (!snap_name)
388                                 snap_name = argv[2];
389                 } else { 
390                         snap_ioc_data->no = 0;
391                         if (!snap_name)
392                                 snap_name = argv[1];
393                 }
394                 memcpy(snap_ioc_data->snaps[0].name, 
395                                snap_name, strlen(snap_name));
396                 snap_ioc_data->snaps[0].time = time(NULL);
397                 
398                 IOC_PACK(sizeof(struct ioc_snap_tbl_data) + sizeof(struct snap));
399
400                 if ((rc = ioctl(open_device_table.device[i].fd, 
401                                         IOC_SNAP_ADD, buf))) {
402                         fprintf(stderr, "add %s failed \n", snap_name);
403                 } else {
404                         fprintf(stderr, "add %s success\n", snap_name);
405                 }
406         }
407         return rc;
408 }