Deleted Added
full compact
common_kvm.c (231384) common_kvm.c (235602)
1/*-
2 * Copyright (c) 2009 Stanislav Sedov <stas@FreeBSD.org>
3 * Copyright (c) 1988, 1993
4 * The Regents of the University of California. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by the University of
17 * California, Berkeley and its contributors.
18 * 4. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2009 Stanislav Sedov <stas@FreeBSD.org>
3 * Copyright (c) 1988, 1993
4 * The Regents of the University of California. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by the University of
17 * California, Berkeley and its contributors.
18 * 4. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#include <sys/cdefs.h>
36__FBSDID("$FreeBSD: head/lib/libprocstat/common_kvm.c 231384 2012-02-10 13:47:40Z ed $");
36__FBSDID("$FreeBSD: head/lib/libprocstat/common_kvm.c 235602 2012-05-18 10:15:46Z gleb $");
37
38#include <sys/param.h>
39#include <sys/user.h>
40#include <sys/stat.h>
41#include <sys/vnode.h>
42#include <sys/conf.h>
43#define _KERNEL
44#include <sys/pipe.h>
45#include <sys/mount.h>
46#include <ufs/ufs/quota.h>
47#include <ufs/ufs/inode.h>
48#include <fs/devfs/devfs.h>
49#include <fs/devfs/devfs_int.h>
50#undef _KERNEL
51#include <nfs/nfsproto.h>
52#include <nfsclient/nfs.h>
53#include <nfsclient/nfsnode.h>
54
55#include <assert.h>
56#include <err.h>
57#include <kvm.h>
58#include <stddef.h>
59#include <string.h>
60
61#include <libprocstat.h>
62#include "common_kvm.h"
63
64int
65kvm_read_all(kvm_t *kd, unsigned long addr, void *buf, size_t nbytes)
66{
67 ssize_t error;
68
69 if (nbytes >= SSIZE_MAX)
70 return (0);
71 error = kvm_read(kd, addr, buf, nbytes);
72 return (error == (ssize_t)(nbytes));
73}
74
75int
76kdevtoname(kvm_t *kd, struct cdev *dev, char *buf)
77{
78 struct cdev si;
79
80 assert(buf);
81 if (!kvm_read_all(kd, (unsigned long)dev, &si, sizeof(si)))
82 return (1);
83 strlcpy(buf, si.si_name, SPECNAMELEN + 1);
84 return (0);
85}
86
87int
88ufs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn)
89{
90 struct inode inode;
91
92 if (!kvm_read_all(kd, (unsigned long)VTOI(vp), &inode, sizeof(inode))) {
93 warnx("can't read inode at %p", (void *)VTOI(vp));
94 return (1);
95 }
96 /*
97 * The st_dev from stat(2) is a dev_t. These kernel structures
98 * contain cdev pointers. We need to convert to dev_t to make
99 * comparisons
100 */
101 vn->vn_fsid = dev2udev(kd, inode.i_dev);
37
38#include <sys/param.h>
39#include <sys/user.h>
40#include <sys/stat.h>
41#include <sys/vnode.h>
42#include <sys/conf.h>
43#define _KERNEL
44#include <sys/pipe.h>
45#include <sys/mount.h>
46#include <ufs/ufs/quota.h>
47#include <ufs/ufs/inode.h>
48#include <fs/devfs/devfs.h>
49#include <fs/devfs/devfs_int.h>
50#undef _KERNEL
51#include <nfs/nfsproto.h>
52#include <nfsclient/nfs.h>
53#include <nfsclient/nfsnode.h>
54
55#include <assert.h>
56#include <err.h>
57#include <kvm.h>
58#include <stddef.h>
59#include <string.h>
60
61#include <libprocstat.h>
62#include "common_kvm.h"
63
64int
65kvm_read_all(kvm_t *kd, unsigned long addr, void *buf, size_t nbytes)
66{
67 ssize_t error;
68
69 if (nbytes >= SSIZE_MAX)
70 return (0);
71 error = kvm_read(kd, addr, buf, nbytes);
72 return (error == (ssize_t)(nbytes));
73}
74
75int
76kdevtoname(kvm_t *kd, struct cdev *dev, char *buf)
77{
78 struct cdev si;
79
80 assert(buf);
81 if (!kvm_read_all(kd, (unsigned long)dev, &si, sizeof(si)))
82 return (1);
83 strlcpy(buf, si.si_name, SPECNAMELEN + 1);
84 return (0);
85}
86
87int
88ufs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn)
89{
90 struct inode inode;
91
92 if (!kvm_read_all(kd, (unsigned long)VTOI(vp), &inode, sizeof(inode))) {
93 warnx("can't read inode at %p", (void *)VTOI(vp));
94 return (1);
95 }
96 /*
97 * The st_dev from stat(2) is a dev_t. These kernel structures
98 * contain cdev pointers. We need to convert to dev_t to make
99 * comparisons
100 */
101 vn->vn_fsid = dev2udev(kd, inode.i_dev);
102 vn->vn_fileid = (long)inode.i_number;
102 vn->vn_fileid = inode.i_number;
103 vn->vn_mode = (mode_t)inode.i_mode;
103 vn->vn_mode = (mode_t)inode.i_mode;
104 vn->vn_size = (u_long)inode.i_size;
104 vn->vn_size = inode.i_size;
105 return (0);
106}
107
108int
109devfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn)
110{
111 struct devfs_dirent devfs_dirent;
112 struct mount mount;
113
114 if (!kvm_read_all(kd, (unsigned long)getvnodedata(vp), &devfs_dirent,
115 sizeof(devfs_dirent))) {
116 warnx("can't read devfs_dirent at %p",
117 (void *)vp->v_data);
118 return (1);
119 }
120 if (!kvm_read_all(kd, (unsigned long)getvnodemount(vp), &mount,
121 sizeof(mount))) {
122 warnx("can't read mount at %p",
123 (void *)getvnodemount(vp));
124 return (1);
125 }
126 vn->vn_fsid = mount.mnt_stat.f_fsid.val[0];
127 vn->vn_fileid = devfs_dirent.de_inode;
128 vn->vn_mode = (devfs_dirent.de_mode & ~S_IFMT) | S_IFCHR;
129 vn->vn_size = 0;
130 return (0);
131}
132
133int
134nfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn)
135{
136 struct nfsnode nfsnode;
137 mode_t mode;
138
139 if (!kvm_read_all(kd, (unsigned long)VTONFS(vp), &nfsnode,
140 sizeof(nfsnode))) {
141 warnx("can't read nfsnode at %p",
142 (void *)VTONFS(vp));
143 return (1);
144 }
145 vn->vn_fsid = nfsnode.n_vattr.va_fsid;
146 vn->vn_fileid = nfsnode.n_vattr.va_fileid;
147 vn->vn_size = nfsnode.n_size;
148 mode = (mode_t)nfsnode.n_vattr.va_mode;
149 switch (vp->v_type) {
150 case VREG:
151 mode |= S_IFREG;
152 break;
153 case VDIR:
154 mode |= S_IFDIR;
155 break;
156 case VBLK:
157 mode |= S_IFBLK;
158 break;
159 case VCHR:
160 mode |= S_IFCHR;
161 break;
162 case VLNK:
163 mode |= S_IFLNK;
164 break;
165 case VSOCK:
166 mode |= S_IFSOCK;
167 break;
168 case VFIFO:
169 mode |= S_IFIFO;
170 break;
171 default:
172 break;
173 };
174 vn->vn_mode = mode;
175 return (0);
176}
177
178/*
179 * Read the cdev structure in the kernel in order to work out the
180 * associated dev_t
181 */
182dev_t
183dev2udev(kvm_t *kd, struct cdev *dev)
184{
185 struct cdev_priv priv;
186
187 assert(kd);
188 if (kvm_read_all(kd, (unsigned long)cdev2priv(dev), &priv,
189 sizeof(priv))) {
190 return ((dev_t)priv.cdp_inode);
191 } else {
192 warnx("can't convert cdev *%p to a dev_t\n", dev);
193 return (-1);
194 }
195}
196
197void *
198getvnodedata(struct vnode *vp)
199{
200 return (vp->v_data);
201}
202
203struct mount *
204getvnodemount(struct vnode *vp)
205{
206 return (vp->v_mount);
207}
105 return (0);
106}
107
108int
109devfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn)
110{
111 struct devfs_dirent devfs_dirent;
112 struct mount mount;
113
114 if (!kvm_read_all(kd, (unsigned long)getvnodedata(vp), &devfs_dirent,
115 sizeof(devfs_dirent))) {
116 warnx("can't read devfs_dirent at %p",
117 (void *)vp->v_data);
118 return (1);
119 }
120 if (!kvm_read_all(kd, (unsigned long)getvnodemount(vp), &mount,
121 sizeof(mount))) {
122 warnx("can't read mount at %p",
123 (void *)getvnodemount(vp));
124 return (1);
125 }
126 vn->vn_fsid = mount.mnt_stat.f_fsid.val[0];
127 vn->vn_fileid = devfs_dirent.de_inode;
128 vn->vn_mode = (devfs_dirent.de_mode & ~S_IFMT) | S_IFCHR;
129 vn->vn_size = 0;
130 return (0);
131}
132
133int
134nfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn)
135{
136 struct nfsnode nfsnode;
137 mode_t mode;
138
139 if (!kvm_read_all(kd, (unsigned long)VTONFS(vp), &nfsnode,
140 sizeof(nfsnode))) {
141 warnx("can't read nfsnode at %p",
142 (void *)VTONFS(vp));
143 return (1);
144 }
145 vn->vn_fsid = nfsnode.n_vattr.va_fsid;
146 vn->vn_fileid = nfsnode.n_vattr.va_fileid;
147 vn->vn_size = nfsnode.n_size;
148 mode = (mode_t)nfsnode.n_vattr.va_mode;
149 switch (vp->v_type) {
150 case VREG:
151 mode |= S_IFREG;
152 break;
153 case VDIR:
154 mode |= S_IFDIR;
155 break;
156 case VBLK:
157 mode |= S_IFBLK;
158 break;
159 case VCHR:
160 mode |= S_IFCHR;
161 break;
162 case VLNK:
163 mode |= S_IFLNK;
164 break;
165 case VSOCK:
166 mode |= S_IFSOCK;
167 break;
168 case VFIFO:
169 mode |= S_IFIFO;
170 break;
171 default:
172 break;
173 };
174 vn->vn_mode = mode;
175 return (0);
176}
177
178/*
179 * Read the cdev structure in the kernel in order to work out the
180 * associated dev_t
181 */
182dev_t
183dev2udev(kvm_t *kd, struct cdev *dev)
184{
185 struct cdev_priv priv;
186
187 assert(kd);
188 if (kvm_read_all(kd, (unsigned long)cdev2priv(dev), &priv,
189 sizeof(priv))) {
190 return ((dev_t)priv.cdp_inode);
191 } else {
192 warnx("can't convert cdev *%p to a dev_t\n", dev);
193 return (-1);
194 }
195}
196
197void *
198getvnodedata(struct vnode *vp)
199{
200 return (vp->v_data);
201}
202
203struct mount *
204getvnodemount(struct vnode *vp)
205{
206 return (vp->v_mount);
207}