Whamcloud - gitweb
5edb4fa8bd225a4945859cc8b68450f4f37d16b4
[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
178 int snap_dev_open(int argc, char **argv)
179 {
180         struct snap_mnt *snaplist;
181         char *dev_name;
182         int rc;
183
184         if (argc != 2) { 
185                 fprintf(stderr, "The argument count is not right \n");
186                 return CMD_HELP;
187         }
188         
189         dev_name = argv[1];
190
191         get_snaplist();
192         list_for_each_entry(snaplist, &snap_list, snap_mnt_list) {
193                 if (!strcmp(&snaplist->device.name[0], dev_name)) {
194                         rc = open_device(&snaplist->device.name[0], 
195                                     snaplist->device.dev);
196                         release_snap_list();    
197                         return rc;
198                 }
199         }
200         release_snap_list();    
201         fprintf(stderr, "%s are not snapdevice\n", dev_name);
202         return (-EINVAL);
203 }
204 int snap_dev_list(int argc, char **argv)
205 {
206         struct snap_mnt *snaplist;
207         int    index = 0;
208
209         if (argc != 1) { 
210                 fprintf(stderr, "The argument count is not right \n");
211                 return CMD_HELP;
212         }
213
214         get_snaplist();
215         printf("index:\t\tmount_point:\t\tdevice:\n");
216         list_for_each_entry(snaplist, &snap_list, snap_mnt_list) {
217                 printf("%d\t\t%s\t\t%s \n", index,
218                         &snaplist->device.mntpt[0], 
219                         &snaplist->device.name[0]);
220                 index++;
221         }
222         release_snap_list();
223         return 0;
224 }
225 static inline void print_snap_table(void * buf)
226 {
227         struct ioc_snap_tbl_data *ptable;
228         int    i;
229
230         ptable = (struct ioc_snap_tbl_data*)buf;
231         
232         printf("There are %d snapshot in the system\n", ptable->count);
233         printf("index\t\tname\t\t\ttime\t\t\n"); 
234         for (i = 0; i < ptable->count; i++) {
235                 struct  tm* local_time;         
236                 char    time[128];
237                 
238                 memset (time, 0, sizeof(time));
239                 local_time = localtime(&ptable->snaps[i].time);
240                 if (local_time) 
241                         strftime(time, sizeof(time), "%a %b %d %Y %H:%M:%S", local_time);                       
242                 printf("%-10d\t%-20s\t%s\n", ptable->snaps[i].index, ptable->snaps[i].name, time); 
243         }
244 }
245 int snap_snap_list(int argc, char **argv)
246 {
247         int i, rc = 0;
248
249         if (argc != 1 && argc != 2) {
250                 fprintf(stderr, "The argument count is not right\n");
251                 return CMD_HELP;
252         }
253         if (open_device_table.count == 0) {
254                 fprintf(stderr, "Please open a snapdevice first\n");
255                 return (-EINVAL);
256         }
257         
258         for (i = 0; i < open_device_table.count; i++) {
259                 struct ioc_snap_tbl_data *snap_ioc_data;
260
261                 IOC_INIT(snap_ioc_data);
262
263                 if (argc == 2) { 
264                         snap_ioc_data->no = atoi(argv[1]);
265                 } else { 
266                         snap_ioc_data->no = 0;
267                 }
268                 
269                 IOC_PACK(sizeof(struct ioc_snap_tbl_data));
270                 
271                 if ((rc = ioctl(open_device_table.device[i].fd, 
272                                 IOC_SNAP_PRINTTABLE, buf))) {
273                         fprintf(stderr, "can not retrive snaptable on device %s failed %d \n", 
274                                 &open_device_table.device[i].name[0], rc);
275                         return (rc);
276                 }
277                 if(((struct ioc_data*)buf)->ioc_bulk)
278                         print_snap_table(((struct ioc_data*)buf)->ioc_bulk);    
279         }
280         return rc;
281 }
282 int snap_snap_add(int argc, char **argv)
283 {
284         int    rc = 0, i;
285         
286         if (argc != 3 && argc !=2) {
287                 fprintf(stderr, "The argument count is not right \n");
288                 return CMD_HELP;
289         }
290
291         if (open_device_table.count == 0) {
292                 fprintf(stderr, "Please open a snapdevice first\n");
293                 return (-EINVAL);
294         }
295         for (i = 0; i < open_device_table.count; i++) {
296                 struct ioc_snap_tbl_data *snap_ioc_data;
297
298                 IOC_INIT(snap_ioc_data);
299
300                 snap_ioc_data->count = 1;
301                 snap_ioc_data->dev = open_device_table.device[i].dev;
302
303                 if (argc == 3) { 
304                         snap_ioc_data->no = atoi(argv[1]);
305                         memcpy(snap_ioc_data->snaps[0].name, 
306                                argv[2], strlen(argv[2]));
307                 } else { 
308                         snap_ioc_data->no = 0;
309                         memcpy(snap_ioc_data->snaps[0].name, 
310                                argv[1], strlen(argv[1]));
311                 }
312                 snap_ioc_data->snaps[0].time = time(NULL);
313                 
314                 IOC_PACK(sizeof(struct ioc_snap_tbl_data) + sizeof(struct snap));
315
316                 if ((rc = ioctl(open_device_table.device[i].fd, 
317                                         IOC_SNAP_ADD, buf))) {
318                         fprintf(stderr, "add %s failed \n", argv[1]);
319                 } else {
320                         fprintf(stderr, "add %s success\n", argv[1]);
321                 }
322         }
323         return rc;
324 }