4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
30 * Portions of this source code were derived from Berkeley 4.3 BSD
31 * under license from the Regents of the University of California.
34 #pragma ident "%Z%%M% %I% %E% SMI"
37 * Get file system statistics (statvfs and fstatvfs).
40 #include <sys/types.h>
41 #include <sys/inttypes.h>
42 #include <sys/t_lock.h>
43 #include <sys/param.h>
44 #include <sys/errno.h>
45 #include <sys/fstyp.h>
46 #include <sys/systm.h>
48 #include <sys/statvfs.h>
49 #include <sys/vnode.h>
51 #include <sys/cmn_err.h>
52 #include <sys/debug.h>
53 #include <sys/pathname.h>
56 #include <fs/fs_subr.h>
58 #define STATVFSCOPY(dst, src) \
59 (dst)->f_bsize = (src)->f_bsize; \
60 (dst)->f_frsize = (src)->f_frsize; \
61 (dst)->f_blocks = (src)->f_blocks; \
62 (dst)->f_bfree = (src)->f_bfree; \
63 (dst)->f_bavail = (src)->f_bavail; \
64 (dst)->f_files = (src)->f_files; \
65 (dst)->f_ffree = (src)->f_ffree; \
66 (dst)->f_favail = (src)->f_favail; \
67 (dst)->f_fsid = (src)->f_fsid; \
68 bcopy((src)->f_basetype, (dst)->f_basetype, \
69 sizeof ((dst)->f_basetype)); \
70 (dst)->f_flag = (src)->f_flag; \
71 (dst)->f_namemax = (src)->f_namemax; \
72 bcopy((src)->f_fstr, (dst)->f_fstr, \
73 sizeof ((dst)->f_fstr))
76 * Common routines for statvfs and fstatvfs.
80 cstatvfs32(struct vfs
*vfsp
, struct statvfs32
*ubp
)
82 struct statvfs64 ds64
;
83 struct statvfs32 ds32
;
87 ASSERT32(sizeof (struct statvfs
) == sizeof (struct statvfs32
));
88 ASSERT32(sizeof (struct statvfs64
) == sizeof (struct statvfs64_32
));
91 bzero(&ds64
, sizeof (ds64
));
92 if ((error
= VFS_STATVFS(vfsp
, &ds64
)) != 0)
96 * VFS_STATVFS can return data that is incompatible with the space
97 * available the 32-bit statvfs structure. Check here to see if
98 * it will fit into the 32-bit structure, if not, return EOVERFLOW.
100 * The check for -1 is because some file systems return -1 in the
101 * fields that are irrelevant or nonessential, and we do not want
102 * to return EOVERFLOW for them. For example: df is expected to
103 * show -1 in the output for some of these fields on NFS mounted
106 if (ds64
.f_files
== (fsfilcnt64_t
)-1)
107 ds64
.f_files
= UINT32_MAX
;
108 if (ds64
.f_ffree
== (fsfilcnt64_t
)-1)
109 ds64
.f_ffree
= UINT32_MAX
;
110 if (ds64
.f_favail
== (fsfilcnt64_t
)-1)
111 ds64
.f_favail
= UINT32_MAX
;
112 if (ds64
.f_bavail
== (fsblkcnt64_t
)-1)
113 ds64
.f_bavail
= UINT32_MAX
;
114 if (ds64
.f_bfree
== (fsblkcnt64_t
)-1)
115 ds64
.f_bfree
= UINT32_MAX
;
117 if (ds64
.f_blocks
> UINT32_MAX
|| ds64
.f_bfree
> UINT32_MAX
||
118 ds64
.f_bavail
> UINT32_MAX
|| ds64
.f_files
> UINT32_MAX
||
119 ds64
.f_ffree
> UINT32_MAX
|| ds64
.f_favail
> UINT32_MAX
)
123 * On the 64-bit kernel, even these fields grow to 64-bit
124 * quantities in the statvfs64 structure.
126 if (ds64
.f_namemax
== (ulong_t
)-1l)
127 ds64
.f_namemax
= UINT32_MAX
;
129 if (ds64
.f_bsize
> UINT32_MAX
|| ds64
.f_frsize
> UINT32_MAX
||
130 ds64
.f_fsid
> UINT32_MAX
|| ds64
.f_flag
> UINT32_MAX
||
131 ds64
.f_namemax
> UINT32_MAX
)
135 bzero(&ds32
, sizeof (ds32
));
136 STATVFSCOPY(&ds32
, &ds64
);
137 if (copyout(&ds32
, ubp
, sizeof (ds32
)) != 0)
143 cstatvfs64(struct vfs
*vfsp
, struct statvfs64
*ubp
)
145 struct statvfs64 ds64
;
149 ASSERT64(sizeof (struct statvfs
) == sizeof (struct statvfs64
));
151 bzero(&ds64
, sizeof (ds64
));
152 if ((error
= VFS_STATVFS(vfsp
, &ds64
)) != 0)
154 if (copyout(&ds64
, ubp
, sizeof (ds64
)) != 0)
160 * Native system calls
163 statvfs(char *fname
, struct statvfs
*sbp
)
167 int estale_retry
= 0;
170 if (error
= lookupname(fname
, UIO_USERSPACE
, FOLLOW
, NULLVPP
, &vp
)) {
171 if ((error
== ESTALE
) && fs_need_estale_retry(estale_retry
++))
173 return (set_errno(error
));
176 error
= cstatvfs64(vp
->v_vfsp
, (struct statvfs64
*)sbp
);
178 error
= cstatvfs32(vp
->v_vfsp
, (struct statvfs32
*)sbp
);
182 if ((error
== ESTALE
) && fs_need_estale_retry(estale_retry
++))
184 return (set_errno(error
));
190 fstatvfs(int fdes
, struct statvfs
*sbp
)
195 if ((fp
= getf(fdes
)) == NULL
)
196 return (set_errno(EBADF
));
198 error
= cstatvfs64(fp
->f_vnode
->v_vfsp
, (struct statvfs64
*)sbp
);
200 error
= cstatvfs32(fp
->f_vnode
->v_vfsp
, (struct statvfs32
*)sbp
);
204 return (set_errno(error
));
211 * Large File system calls.
213 * (We deliberately don't have special "large file" system calls in the
214 * 64-bit kernel -- we just use the native versions, since they're just
218 statvfs64(char *fname
, struct statvfs64
*sbp
)
222 int estale_retry
= 0;
225 if (error
= lookupname(fname
, UIO_USERSPACE
, FOLLOW
, NULLVPP
, &vp
)) {
226 if ((error
== ESTALE
) && fs_need_estale_retry(estale_retry
++))
228 return (set_errno(error
));
230 error
= cstatvfs64(vp
->v_vfsp
, sbp
);
233 if ((error
== ESTALE
) && fs_need_estale_retry(estale_retry
++))
235 return (set_errno(error
));
241 fstatvfs64(int fdes
, struct statvfs64
*sbp
)
246 if ((fp
= getf(fdes
)) == NULL
)
247 return (set_errno(EBADF
));
248 error
= cstatvfs64(fp
->f_vnode
->v_vfsp
, sbp
);
251 return (set_errno(error
));
257 #ifdef _SYSCALL32_IMPL
260 cstatvfs64_32(struct vfs
*vfsp
, struct statvfs64_32
*ubp
)
262 struct statvfs64 ds64
;
263 struct statvfs64_32 ds64_32
;
266 bzero(&ds64
, sizeof (ds64
));
267 if ((error
= VFS_STATVFS(vfsp
, &ds64
)) != 0)
271 * On the 64-bit kernel, even these fields grow to 64-bit
272 * quantities in the statvfs64 structure.
274 if (ds64
.f_namemax
== (ulong_t
)-1l)
275 ds64
.f_namemax
= UINT32_MAX
;
277 if (ds64
.f_bsize
> UINT32_MAX
|| ds64
.f_frsize
> UINT32_MAX
||
278 ds64
.f_fsid
> UINT32_MAX
|| ds64
.f_flag
> UINT32_MAX
||
279 ds64
.f_namemax
> UINT32_MAX
)
282 STATVFSCOPY(&ds64_32
, &ds64
);
283 if (copyout(&ds64_32
, ubp
, sizeof (ds64_32
)) != 0)
289 * ILP32 "small file" system calls on LP64 kernel
292 statvfs32(char *fname
, struct statvfs32
*sbp
)
296 int estale_retry
= 0;
299 if (error
= lookupname(fname
, UIO_USERSPACE
, FOLLOW
, NULLVPP
, &vp
)) {
300 if ((error
== ESTALE
) && fs_need_estale_retry(estale_retry
++))
302 return (set_errno(error
));
304 error
= cstatvfs32(vp
->v_vfsp
, sbp
);
307 if ((error
== ESTALE
) && fs_need_estale_retry(estale_retry
++))
309 return (set_errno(error
));
315 fstatvfs32(int fdes
, struct statvfs32
*sbp
)
320 if ((fp
= getf(fdes
)) == NULL
)
321 return (set_errno(EBADF
));
322 error
= cstatvfs32(fp
->f_vnode
->v_vfsp
, sbp
);
325 return (set_errno(error
));
330 * ILP32 Large File system calls on LP64 kernel
333 statvfs64_32(char *fname
, struct statvfs64_32
*sbp
)
337 int estale_retry
= 0;
340 if (error
= lookupname(fname
, UIO_USERSPACE
, FOLLOW
, NULLVPP
, &vp
)) {
341 if ((error
== ESTALE
) && fs_need_estale_retry(estale_retry
++))
343 return (set_errno(error
));
345 error
= cstatvfs64_32(vp
->v_vfsp
, sbp
);
348 if ((error
== ESTALE
) && fs_need_estale_retry(estale_retry
++))
350 return (set_errno(error
));
356 fstatvfs64_32(int fdes
, struct statvfs64_32
*sbp
)
361 if ((fp
= getf(fdes
)) == NULL
)
362 return (set_errno(EBADF
));
363 error
= cstatvfs64_32(fp
->f_vnode
->v_vfsp
, sbp
);
366 return (set_errno(error
));
370 #endif /* _SYSCALL32_IMPL */