replay-log: add support for replaying ops in target device sector range
[xfstests-dev.git] / src / bstat.c
1 /*
2  * Copyright (c) 2000-2003 Silicon Graphics, Inc.
3  * All Rights Reserved.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it would be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write the Free Software Foundation,
16  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18
19 #include "global.h"
20 #include <xfs/jdm.h>
21
22 void
23 dotime(void *ti, char *s)
24 {
25         char    *c;
26         xfs_bstime_t *t;
27
28         t = (xfs_bstime_t *)ti;
29
30         c = ctime(&t->tv_sec);
31         printf("\t%s %19.19s.%09d %s", s, c, t->tv_nsec, c + 20);
32 }
33
34 void
35 printbstat(xfs_bstat_t *sp)
36 {
37         printf("ino %lld mode %#o nlink %d uid %d gid %d rdev %#x\n",
38                 (long long)sp->bs_ino, sp->bs_mode, sp->bs_nlink,
39                 sp->bs_uid, sp->bs_gid, sp->bs_rdev);
40         printf("\tblksize %d size %lld blocks %lld xflags %#x extsize %d\n",
41                 sp->bs_blksize, (long long)sp->bs_size, (long long)sp->bs_blocks,
42                 sp->bs_xflags, sp->bs_extsize);
43         dotime(&sp->bs_atime, "atime");
44         dotime(&sp->bs_mtime, "mtime");
45         dotime(&sp->bs_ctime, "ctime");
46         printf( "\textents %d %d gen %d\n",
47                 sp->bs_extents, sp->bs_aextents, sp->bs_gen);
48         printf( "\tDMI: event mask 0x%08x state 0x%04x\n",
49                 sp->bs_dmevmask, sp->bs_dmstate);
50 }
51
52 void
53 printstat(struct stat64 *sp)
54 {
55         printf("ino %lld mode %#o nlink %d uid %d gid %d rdev %#x\n",
56                 (long long)sp->st_ino, (unsigned int)sp->st_mode, (int)sp->st_nlink,
57                 (int)sp->st_uid, (int)sp->st_gid, (int)sp->st_rdev);
58         printf("\tblksize %llu size %lld blocks %lld\n",
59                 (unsigned long long)sp->st_blksize, (long long)sp->st_size, (long long)sp->st_blocks);
60         dotime(&sp->st_atime, "atime");
61         dotime(&sp->st_mtime, "mtime");
62         dotime(&sp->st_ctime, "ctime");
63 }
64
65 int
66 main(int argc, char **argv)
67 {
68         __s32           count;
69         int             total = 0;
70         int             fsfd;
71         int             i;
72         __u64           last = 0;
73         char            *name;
74         int             nent;
75         int             debug = 0;
76         int             quiet = 0;
77         int             statit = 0;
78         int             verbose = 0;
79         xfs_bstat_t     *t;
80         int             ret;
81         jdm_fshandle_t  *fshandlep = NULL;
82         int             fd;
83         struct stat64   sb;
84         int nread;
85         char *cc_readlinkbufp;
86         int cc_readlinkbufsz;
87         int             c;
88         xfs_fsop_bulkreq_t bulkreq;
89
90         while ((c = getopt(argc, argv, "cdl:qv")) != -1) {
91                 switch (c) {
92                 case 'q':
93                         quiet = 1;
94                         break;
95                 case 'v':
96                         verbose = 1;
97                         break;
98                 case 'c':
99                         statit = 1;
100                         break;
101                 case 'd':
102                         debug = 1;
103                         break;
104                 case 'l':
105                         last = atoi(optarg);
106                         break;
107                 case '?':
108                 printf("usage: xfs_bstat [-c] [-q] [-v] [ dir [ batch_size ]]\n");
109                 printf("   -c   Check the results against stat(3) output\n");
110                 printf("   -q   Quiet\n");
111                 printf("   -l _num_  Inode to start with\n");
112                 printf("   -v   Verbose output\n");
113                         exit(1);
114                 }
115         }
116         argc -= optind;
117         argv += optind;
118
119         if (argc < 1)
120                 name = ".";
121         else
122                 name = *argv;
123
124         fsfd = open(name, O_RDONLY);
125         if (fsfd < 0) {
126                 perror(name);
127                 exit(1);
128         }
129         if (argc < 2)
130                 nent = 4096;
131         else
132                 nent = atoi(*++argv);
133
134         if (verbose)
135                 printf("Bulkstat test on %s, batch size=%d statcheck=%d\n", 
136                         name, nent, statit);
137
138         if (statit) {
139                 fshandlep = jdm_getfshandle( name );
140                 if (! fshandlep) {
141                         printf("unable to construct sys handle for %s: %s\n",
142                           name, strerror(errno));
143                         return -1;
144                 }
145         }
146
147         t = malloc(nent * sizeof(*t));
148
149         if (verbose)
150                 printf(
151                   "XFS_IOC_FSBULKSTAT test: last=%lld nent=%d\n", (long long)last, nent);
152
153         bulkreq.lastip  = &last;
154         bulkreq.icount  = nent;
155         bulkreq.ubuffer = t;
156         bulkreq.ocount  = &count;
157
158         while ((ret = xfsctl(name, fsfd, XFS_IOC_FSBULKSTAT, &bulkreq)) == 0) {
159                 total += count;
160
161                 if (verbose)
162                         printf(
163             "XFS_IOC_FSBULKSTAT test: last=%lld ret=%d count=%d total=%d\n", 
164                                                 (long long)last, ret, count, total);
165                 if (count == 0)
166                         exit(0);
167
168                 if ( quiet && ! statit )
169                         continue;
170
171                 for (i = 0; i < count; i++) {
172                         if (! quiet) {
173                                 printbstat(&t[i]);
174                         }
175         
176                         if (statit) {
177                                 switch(t[i].bs_mode & S_IFMT) {
178                                 case S_IFLNK:
179                                         cc_readlinkbufsz = MAXPATHLEN;
180                                         cc_readlinkbufp = (char *)calloc( 
181                                                               1, 
182                                                               cc_readlinkbufsz);
183                                         nread = jdm_readlink( 
184                                                    fshandlep,
185                                                    &t[i],
186                                                    cc_readlinkbufp,
187                                                    cc_readlinkbufsz);
188                                         if (verbose && nread > 0)
189                                                 printf(
190                                                  "readlink: ino %lld: <%*s>\n",
191                                                             (long long)t[i].bs_ino,
192                                                             nread,
193                                                             cc_readlinkbufp);
194                                         free(cc_readlinkbufp);
195                                         if ( nread < 0 ) {
196                                                 printf(
197                                               "could not read symlink ino %llu\n",
198                                                       (unsigned long long)t[i].bs_ino );
199                                                 printbstat(&t[i]);
200                                         }
201                                         break;
202
203                                 case S_IFCHR:
204                                 case S_IFBLK:
205                                 case S_IFIFO:
206                                 case S_IFSOCK:
207                                         break;
208
209                                 case S_IFREG:
210                                 case S_IFDIR:
211                                         fd = jdm_open( fshandlep, &t[i], O_RDONLY);
212                                         if (fd < 0) {
213                                                 printf(
214                                         "unable to open handle ino %lld: %s\n",
215                                                   (long long)t[i].bs_ino, strerror(errno));
216                                                 continue;
217                                         }
218                                         if (fstat64(fd, &sb) < 0) {
219                                                 printf(
220                                         "unable to stat ino %lld: %s\n",
221                                                   (long long)t[i].bs_ino, strerror(errno));
222                                         }
223                                         close(fd);
224
225                                         /*
226                                          * Don't compare blksize or blocks, 
227                                          * they are used differently by stat
228                                          * and bstat.
229                                          */
230                                         if ( (t[i].bs_ino != sb.st_ino) ||
231                                              (t[i].bs_mode != sb.st_mode) ||
232                                              (t[i].bs_nlink != sb.st_nlink) ||
233                                              (t[i].bs_uid != sb.st_uid) ||
234                                              (t[i].bs_gid != sb.st_gid) ||
235                                              (t[i].bs_rdev != sb.st_rdev) ||
236                                              (t[i].bs_size != sb.st_size) ||
237                                              /* (t[i].bs_blksize != sb.st_blksize) || */
238                                              (t[i].bs_mtime.tv_sec != sb.st_mtime) ||
239                                              (t[i].bs_ctime.tv_sec != sb.st_ctime) ) {
240                                                 printf("\nstat/bstat missmatch\n");
241                                                 printbstat(&t[i]);
242                                                 printstat(&sb);
243                                         }
244                                 }
245                         }
246                 }
247
248                 if (debug)
249                         break;
250         }
251
252         if (fsfd)
253                 close(fsfd);
254
255         if (ret < 0 )
256                 perror("xfsctl(XFS_IOC_FSBULKSTAT)");
257
258         if (verbose)
259                 printf(
260             "XFS_IOC_FSBULKSTAT test: last=%lld nent=%d ret=%d count=%d\n", 
261                                                (long long)last, nent, ret, count);
262
263         return 1;
264 }