+static int
+fdesc_vfs_getattr(__unused mount_t mp, struct vfs_attr *fsap, vfs_context_t context)
+{
+ VFSATTR_RETURN(fsap, f_bsize, DEV_BSIZE);
+ VFSATTR_RETURN(fsap, f_iosize, DEV_BSIZE);
+ VFSATTR_RETURN(fsap, f_blocks, 2);
+ VFSATTR_RETURN(fsap, f_bfree, 0);
+ VFSATTR_RETURN(fsap, f_bavail, 0);
+ VFSATTR_RETURN(fsap, f_fssubtype, 0);
+
+ if (VFSATTR_IS_ACTIVE(fsap, f_objcount) ||
+ VFSATTR_IS_ACTIVE(fsap, f_maxobjcount) ||
+ VFSATTR_IS_ACTIVE(fsap, f_files) ||
+ VFSATTR_IS_ACTIVE(fsap, f_ffree))
+ {
+ proc_t p = vfs_context_proc(context);
+ struct filedesc *fdp;
+ int lim;
+ int i;
+ int last;
+ int freefd;
+
+ /*
+ * Compute number of free file descriptors.
+ * [ Strange results will ensue if the open file
+ * limit is ever reduced below the current number
+ * of open files... ]
+ */
+ lim = p->p_rlimit[RLIMIT_NOFILE].rlim_cur;
+ fdp = p->p_fd;
+ last = min(fdp->fd_nfiles, lim);
+ freefd = 0;
+ for (i = fdp->fd_freefile; i < last; i++)
+ if (fdp->fd_ofiles[i] == NULL &&
+ !(fdp->fd_ofileflags[i] & UF_RESERVED))
+ freefd++;
+
+ /*
+ * Adjust for the fact that the fdesc array may not
+ * have been fully allocated yet.
+ */
+ if (fdp->fd_nfiles < lim)
+ freefd += (lim - fdp->fd_nfiles);
+
+ VFSATTR_RETURN(fsap, f_objcount, lim+1);
+ VFSATTR_RETURN(fsap, f_maxobjcount, lim+1);
+ VFSATTR_RETURN(fsap, f_files, lim+1);
+ VFSATTR_RETURN(fsap, f_ffree, freefd);
+ }
+
+ return 0;
+}
+
+static int
+fdesc_sync(__unused struct mount *mp, __unused int waitfor, __unused vfs_context_t context)