]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/snap/snapfs.c
stats: show amount of reclaimable pages (add -r flag)
[plan9front.git] / sys / src / cmd / snap / snapfs.c
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <auth.h>
5 #include <fcall.h>
6 #include <thread.h>
7 #include <9p.h>
8 #include "snap.h"
9
10 typedef struct PD PD;
11 struct PD {
12         int isproc;
13         union {
14                 Proc *p;
15                 Data *d;
16         };
17 };
18
19 PD*
20 PDProc(Proc *p)
21 {
22         PD *pd;
23
24         pd = emalloc(sizeof(*pd));
25         pd->isproc = 1;
26         pd->p = p;
27         return pd;
28 }
29
30 PD*
31 PDData(Data *d)
32 {
33         PD *pd;
34
35         pd = emalloc(sizeof(*pd));
36         pd->isproc = 0;
37         pd->d = d;
38         return pd;
39 }
40
41 void
42 usage(void)
43 {
44         fprint(2, "usage: snapfs [-a] [-m mtpt] file\n");
45         exits("usage");
46 }
47
48 char*
49 memread(Proc *p, File *f, void *buf, long *count, vlong offset)
50 {
51         Page *pg;
52         int po;
53
54         po = offset%Pagesize;
55         if(!(pg = findpage(p, p->pid, f->name[0], offset-po)))
56                 return "address not mapped";
57
58         if(*count > Pagesize-po)
59                 *count = Pagesize-po;
60
61         memmove(buf, pg->data+po, *count);
62         return nil;
63 }
64
65 char*
66 dataread(Data *d, void *buf, long *count, vlong offset)
67 {
68         assert(d != nil);
69
70         if(offset >= d->len) {
71                 *count = 0;
72                 return nil;
73         }
74
75         if(offset+*count >= d->len)
76                 *count = d->len - offset;
77
78         memmove(buf, d->data+offset, *count);
79         return nil;
80 }
81
82 void
83 fsread(Req *r)
84 {
85         char *e;
86         PD *pd;
87         Fid *fid;
88         void *data;
89         vlong offset;
90         long count;
91
92         fid = r->fid;
93         data = r->ofcall.data;
94         offset = r->ifcall.offset;
95         count = r->ifcall.count;
96         pd = fid->file->aux;
97
98         if(pd->isproc)
99                 e = memread(pd->p, fid->file, data, &count, offset);
100         else
101                 e = dataread(pd->d, data, &count, offset);
102
103         if(e == nil)
104                 r->ofcall.count = count;
105         respond(r, e);
106 }
107
108 Srv fs = {
109         .read = fsread,
110 };
111
112 File*
113 ecreatefile(File *a, char *b, char *c, ulong d, void *e)
114 {
115         File *f;
116
117         f = createfile(a, b, c, d, e);
118         if(f == nil)
119                 sysfatal("error creating snap tree: %r");
120         return f;
121 }
122
123 void
124 main(int argc, char **argv)
125 {
126         Biobuf *b;
127         Data *d;
128         File *fdir, *f;
129         Proc *p, *plist;
130         Tree *tree;
131         char *mtpt, buf[32];
132         int i, mflag;
133
134         mtpt = "/proc";
135         mflag = MBEFORE;
136
137         ARGBEGIN{
138         case 'D':
139                 chatty9p++;
140                 break;
141         case 'd':
142                 debug = 1;
143                 break;
144         case 'a':
145                 mflag = MAFTER;
146                 break;
147         case 'm':
148                 mtpt = ARGF();
149                 break;
150         default:
151                 usage();
152         }ARGEND
153
154         if(argc != 1)
155                 usage();
156
157         b = Bopen(argv[0], OREAD);
158         if(b == nil) {
159                 fprint(2, "cannot open \"%s\": %r\n", argv[0]);
160                 exits("Bopen");
161         }
162
163         if((plist = readsnap(b)) == nil) {
164                 fprint(2, "readsnap fails\n");
165                 exits("readsnap");
166         }
167
168         tree = alloctree(nil, nil, DMDIR|0555, nil);
169         fs.tree = tree;
170
171         for(p=plist; p; p=p->link) {
172                 print("process %ld %.*s\n", p->pid, 28, p->d[Pstatus] ? p->d[Pstatus]->data : "");
173
174                 snprint(buf, sizeof buf, "%ld", p->pid);
175                 fdir = ecreatefile(tree->root, buf, nil, DMDIR|0555, nil);
176                 ecreatefile(fdir, "ctl", nil, 0777, nil);
177                 if(p->text)
178                         ecreatefile(fdir, "text", nil, 0777, PDProc(p));
179
180                 ecreatefile(fdir, "mem", nil, 0666, PDProc(p));
181                 for(i=0; i<Npfile; i++) {
182                         if(d = p->d[i]) {
183                                 f = ecreatefile(fdir, pfile[i], nil, 0666, PDData(d));
184                                 f->length = d->len;
185                         }
186                 }
187         }
188
189         postmountsrv(&fs, nil, mtpt, mflag);
190         exits(0);
191 }