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 <sys/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
;
86 ASSERT32(sizeof (struct statvfs
) == sizeof (struct statvfs32
));
87 ASSERT32(sizeof (struct statvfs64
) == sizeof (struct statvfs64_32
));
89 bzero(&ds64
, sizeof (ds64
));
90 if ((error
= VFS_STATVFS(vfsp
, &ds64
)) != 0)
94 * VFS_STATVFS can return data that is incompatible with the space
95 * available the 32-bit statvfs structure. Check here to see if
96 * it will fit into the 32-bit structure, if not, return EOVERFLOW.
98 * The check for -1 is because some file systems return -1 in the
99 * fields that are irrelevant or nonessential, and we do not want
100 * to return EOVERFLOW for them. For example: df is expected to
101 * show -1 in the output for some of these fields on NFS mounted
104 if (ds64
.f_files
== (fsfilcnt64_t
)-1)
105 ds64
.f_files
= UINT32_MAX
;
106 if (ds64
.f_ffree
== (fsfilcnt64_t
)-1)
107 ds64
.f_ffree
= UINT32_MAX
;
108 if (ds64
.f_favail
== (fsfilcnt64_t
)-1)
109 ds64
.f_favail
= UINT32_MAX
;
110 if (ds64
.f_bavail
== (fsblkcnt64_t
)-1)
111 ds64
.f_bavail
= UINT32_MAX
;
112 if (ds64
.f_bfree
== (fsblkcnt64_t
)-1)
113 ds64
.f_bfree
= UINT32_MAX
;
115 if (ds64
.f_blocks
> UINT32_MAX
|| ds64
.f_bfree
> UINT32_MAX
||
116 ds64
.f_bavail
> UINT32_MAX
|| ds64
.f_files
> UINT32_MAX
||
117 ds64
.f_ffree
> UINT32_MAX
|| ds64
.f_favail
> UINT32_MAX
)
121 * On the 64-bit kernel, even these fields grow to 64-bit
122 * quantities in the statvfs64 structure.
124 if (ds64
.f_namemax
== (ulong_t
)-1l)
125 ds64
.f_namemax
= UINT32_MAX
;
127 if (ds64
.f_bsize
> UINT32_MAX
|| ds64
.f_frsize
> UINT32_MAX
||
128 ds64
.f_fsid
> UINT32_MAX
|| ds64
.f_flag
> UINT32_MAX
||
129 ds64
.f_namemax
> UINT32_MAX
)
133 bzero(&ds32
, sizeof (ds32
));
134 STATVFSCOPY(&ds32
, &ds64
);
135 if (copyout(&ds32
, ubp
, sizeof (ds32
)) != 0)
141 cstatvfs64(struct vfs
*vfsp
, struct statvfs64
*ubp
)
143 struct statvfs64 ds64
;
146 ASSERT64(sizeof (struct statvfs
) == sizeof (struct statvfs64
));
147 bzero(&ds64
, sizeof (ds64
));
148 if ((error
= VFS_STATVFS(vfsp
, &ds64
)) != 0)
150 if (copyout(&ds64
, ubp
, sizeof (ds64
)) != 0)
156 * Native system calls
159 statvfs(char *fname
, struct statvfs
*sbp
)
163 int estale_retry
= 0;
166 if (error
= lookupname(fname
, UIO_USERSPACE
, FOLLOW
, NULLVPP
, &vp
)) {
167 if ((error
== ESTALE
) && fs_need_estale_retry(estale_retry
++))
169 return (set_errno(error
));
172 error
= cstatvfs64(vp
->v_vfsp
, (struct statvfs64
*)sbp
);
174 error
= cstatvfs32(vp
->v_vfsp
, (struct statvfs32
*)sbp
);
178 if ((error
== ESTALE
) && fs_need_estale_retry(estale_retry
++))
180 return (set_errno(error
));
186 fstatvfs(int fdes
, struct statvfs
*sbp
)
191 if ((fp
= getf(fdes
)) == NULL
)
192 return (set_errno(EBADF
));
194 error
= cstatvfs64(fp
->f_vnode
->v_vfsp
, (struct statvfs64
*)sbp
);
196 error
= cstatvfs32(fp
->f_vnode
->v_vfsp
, (struct statvfs32
*)sbp
);
200 return (set_errno(error
));
207 * Large File system calls.
209 * (We deliberately don't have special "large file" system calls in the
210 * 64-bit kernel -- we just use the native versions, since they're just
214 statvfs64(char *fname
, struct statvfs64
*sbp
)
218 int estale_retry
= 0;
221 if (error
= lookupname(fname
, UIO_USERSPACE
, FOLLOW
, NULLVPP
, &vp
)) {
222 if ((error
== ESTALE
) && fs_need_estale_retry(estale_retry
++))
224 return (set_errno(error
));
226 error
= cstatvfs64(vp
->v_vfsp
, sbp
);
229 if ((error
== ESTALE
) && fs_need_estale_retry(estale_retry
++))
231 return (set_errno(error
));
237 fstatvfs64(int fdes
, struct statvfs64
*sbp
)
242 if ((fp
= getf(fdes
)) == NULL
)
243 return (set_errno(EBADF
));
244 error
= cstatvfs64(fp
->f_vnode
->v_vfsp
, sbp
);
247 return (set_errno(error
));
253 #ifdef _SYSCALL32_IMPL
256 cstatvfs64_32(struct vfs
*vfsp
, struct statvfs64_32
*ubp
)
258 struct statvfs64 ds64
;
259 struct statvfs64_32 ds64_32
;
262 bzero(&ds64
, sizeof (ds64
));
263 if ((error
= VFS_STATVFS(vfsp
, &ds64
)) != 0)
267 * On the 64-bit kernel, even these fields grow to 64-bit
268 * quantities in the statvfs64 structure.
270 if (ds64
.f_namemax
== (ulong_t
)-1l)
271 ds64
.f_namemax
= UINT32_MAX
;
273 if (ds64
.f_bsize
> UINT32_MAX
|| ds64
.f_frsize
> UINT32_MAX
||
274 ds64
.f_fsid
> UINT32_MAX
|| ds64
.f_flag
> UINT32_MAX
||
275 ds64
.f_namemax
> UINT32_MAX
)
278 STATVFSCOPY(&ds64_32
, &ds64
);
279 if (copyout(&ds64_32
, ubp
, sizeof (ds64_32
)) != 0)
285 * ILP32 "small file" system calls on LP64 kernel
288 statvfs32(char *fname
, struct statvfs32
*sbp
)
292 int estale_retry
= 0;
295 if (error
= lookupname(fname
, UIO_USERSPACE
, FOLLOW
, NULLVPP
, &vp
)) {
296 if ((error
== ESTALE
) && fs_need_estale_retry(estale_retry
++))
298 return (set_errno(error
));
300 error
= cstatvfs32(vp
->v_vfsp
, sbp
);
303 if ((error
== ESTALE
) && fs_need_estale_retry(estale_retry
++))
305 return (set_errno(error
));
311 fstatvfs32(int fdes
, struct statvfs32
*sbp
)
316 if ((fp
= getf(fdes
)) == NULL
)
317 return (set_errno(EBADF
));
318 error
= cstatvfs32(fp
->f_vnode
->v_vfsp
, sbp
);
321 return (set_errno(error
));
326 * ILP32 Large File system calls on LP64 kernel
329 statvfs64_32(char *fname
, struct statvfs64_32
*sbp
)
333 int estale_retry
= 0;
336 if (error
= lookupname(fname
, UIO_USERSPACE
, FOLLOW
, NULLVPP
, &vp
)) {
337 if ((error
== ESTALE
) && fs_need_estale_retry(estale_retry
++))
339 return (set_errno(error
));
341 error
= cstatvfs64_32(vp
->v_vfsp
, sbp
);
344 if ((error
== ESTALE
) && fs_need_estale_retry(estale_retry
++))
346 return (set_errno(error
));
352 fstatvfs64_32(int fdes
, struct statvfs64_32
*sbp
)
357 if ((fp
= getf(fdes
)) == NULL
)
358 return (set_errno(EBADF
));
359 error
= cstatvfs64_32(fp
->f_vnode
->v_vfsp
, sbp
);
362 return (set_errno(error
));
366 #endif /* _SYSCALL32_IMPL */