~n-muench/ubuntu/quantal/open-vm-tools/open-vm-tools.may2.sid-sync

« back to all changes in this revision

Viewing changes to modules/solaris/vmblock/vfsops.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Baumann
  • Date: 2009-05-30 09:48:43 UTC
  • mfrom: (1.1.5 upstream) (2.4.4 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090530094843-gdpza57r5iqsf124
Tags: 2009.05.22-167859-1
MergingĀ upstreamĀ versionĀ 2009.05.22-167859.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*********************************************************
 
2
 * Copyright (C) 2006 VMware, Inc. All rights reserved.
 
3
 *
 
4
 * The contents of this file are subject to the terms of the Common
 
5
 * Development and Distribution License (the "License") version 1.0
 
6
 * and no later version.  You may not use this file except in
 
7
 * compliance with the License.
 
8
 *
 
9
 * You can obtain a copy of the License at
 
10
 *         http://www.opensource.org/licenses/cddl1.php
 
11
 *
 
12
 * See the License for the specific language governing permissions
 
13
 * and limitations under the License.
 
14
 *
 
15
 *********************************************************/
 
16
 
 
17
 
 
18
/*
 
19
 * vfsops.c --
 
20
 *
 
21
 *      VFS operations for vmblock file system.
 
22
 */
 
23
 
 
24
#include <sys/types.h>
 
25
#include <sys/kmem.h>      /* kmem_zalloc() */
 
26
#include <sys/errno.h>     /* error codes */
 
27
#include <sys/mount.h>     /* MS_OVERLAY */
 
28
#include <sys/sysmacros.h> /* makedevice macro */
 
29
#include <sys/systm.h>     /* cmpldev() */
 
30
#include <sys/policy.h>    /* secpolicy_fs_mount() */
 
31
 
 
32
#include "module.h"
 
33
 
 
34
 
 
35
/*
 
36
 * Variables
 
37
 */
 
38
vfsops_t *vmblockVfsOps;
 
39
 
 
40
static major_t vmblockMajor;
 
41
static minor_t vmblockMinor;
 
42
static kmutex_t vmblockMutex;
 
43
 
 
44
 
 
45
/*
 
46
 * Prototypes
 
47
 */
 
48
int VMBlockVnodeGet(struct vnode **vpp, struct vnode *realVp,
 
49
                    const char *name, size_t nameLen,
 
50
                    struct vnode *dvp, struct vfs *vfsp, Bool isRoot);
 
51
int VMBlockVnodePut(struct vnode *vp);
 
52
static int VMBlockMount(struct vfs *vfsp, struct vnode *vnodep,
 
53
                        struct mounta *mntp, struct cred *credp);
 
54
static int VMBlockUnmount(struct vfs *vfsp, int mflag, struct cred *credp);
 
55
static int VMBlockRoot(struct vfs *vfsp, struct vnode **vnodepp);
 
56
static int VMBlockStatvfs(struct vfs *vfsp, struct statvfs64 *stats);
 
57
 
 
58
 
 
59
 
 
60
/*
 
61
 *----------------------------------------------------------------------------
 
62
 *
 
63
 * VMBlockVnodeGet --
 
64
 *
 
65
 *    Creates a vnode.
 
66
 *
 
67
 *    Note that realVp is assumed to be held (see the comment in the function
 
68
 *    for further explanation).
 
69
 *
 
70
 * Results:
 
71
 *    Returns zero on success and a non-zero error code on failure.  On
 
72
 *    success, vpp is filled in with a new, held vnode.
 
73
 *
 
74
 * Side effects:
 
75
 *    None.
 
76
 *
 
77
 *----------------------------------------------------------------------------
 
78
 */
 
79
 
 
80
int
 
81
VMBlockVnodeGet(struct vnode **vpp,        // OUT: Filled with address of new vnode
 
82
                struct vnode *realVp,      // IN:  Real vnode (assumed held)
 
83
                const char *name,          // IN:  Relative name of the file
 
84
                size_t nameLen,            // IN:  Size of name
 
85
                struct vnode *dvp,         // IN:  Parent directory's vnode
 
86
                struct vfs *vfsp,          // IN:  Filesystem structure
 
87
                Bool isRoot)               // IN:  If is root directory of fs
 
88
{
 
89
   VMBlockVnodeInfo *vip;
 
90
   struct vnode *vp;
 
91
   char *curr;
 
92
   int ret;
 
93
 
 
94
   Debug(VMBLOCK_ENTRY_LOGLEVEL, "VMBlockVnodeGet: entry\n");
 
95
 
 
96
   ASSERT(vpp);
 
97
   ASSERT(realVp);
 
98
   ASSERT(vfsp);
 
99
   ASSERT(name);
 
100
   ASSERT(dvp || isRoot);
 
101
 
 
102
   vp = vn_alloc(KM_SLEEP);
 
103
   if (!vp) {
 
104
      return ENOMEM;
 
105
   }
 
106
 
 
107
   vip = kmem_zalloc(sizeof *vip, KM_SLEEP);
 
108
   vp->v_data = (void *)vip;
 
109
 
 
110
   /*
 
111
    * Store the path that this file redirects to.  For the root vnode we just
 
112
    * store the provided path, but for all others we first copy in the parent
 
113
    * directory's path.
 
114
    */
 
115
   curr = vip->name;
 
116
 
 
117
   if (!isRoot) {
 
118
      VMBlockVnodeInfo *dvip = VPTOVIP(dvp);
 
119
      if (dvip->nameLen + 1 + nameLen + 1 >= sizeof vip->name) {
 
120
         ret = ENAMETOOLONG;
 
121
         goto error;
 
122
      }
 
123
 
 
124
      memcpy(vip->name, dvip->name, dvip->nameLen);
 
125
      vip->name[dvip->nameLen] = '/';
 
126
      curr = vip->name + dvip->nameLen + 1;
 
127
   }
 
128
 
 
129
   if (nameLen + 1 > (sizeof vip->name - (curr - vip->name))) {
 
130
      ret = ENAMETOOLONG;
 
131
      goto error;
 
132
   }
 
133
 
 
134
   memcpy(curr, name, nameLen);
 
135
   curr[nameLen] = '\0';
 
136
   vip->nameLen = nameLen + (curr - vip->name);
 
137
 
 
138
   /*
 
139
    * We require the caller to have held realVp so we don't need VN_HOLD() it
 
140
    * here here even though we VN_RELE() this vnode in VMBlockVnodePut().
 
141
    * Despite seeming awkward, this is more natural since the function that our
 
142
    * caller obtained realVp from provided a held vnode.
 
143
    */
 
144
   vip->realVnode = realVp;
 
145
 
 
146
   /*
 
147
    * Now we'll initialize the vnode.  We need to set the file type, vnode
 
148
    * operations, flags, filesystem pointer, reference count, and device.
 
149
    */
 
150
   /* The root directory is our only directory; the rest are symlinks. */
 
151
   vp->v_type = isRoot ? VDIR : VLNK;
 
152
 
 
153
   vn_setops(vp, vmblockVnodeOps);
 
154
 
 
155
   vp->v_flag  = VNOMAP | VNOMOUNT | VNOSWAP | isRoot ? VROOT : 0;
 
156
   vp->v_vfsp  = vfsp;
 
157
   vp->v_rdev  = NODEV;
 
158
 
 
159
   /* Fill in the provided address with the new vnode. */
 
160
   *vpp = vp;
 
161
 
 
162
   return 0;
 
163
 
 
164
error:
 
165
   kmem_free(vip, sizeof *vip);
 
166
   vn_free(vp);
 
167
   return ret;
 
168
}
 
169
 
 
170
 
 
171
/*
 
172
 *----------------------------------------------------------------------------
 
173
 *
 
174
 * VMBlockVnodePut --
 
175
 *
 
176
 *    Frees state associated with provided vnode.
 
177
 *
 
178
 * Results:
 
179
 *    Zero on success, non-zero error code on failure.
 
180
 *
 
181
 * Side effects:
 
182
 *    None.
 
183
 *
 
184
 *----------------------------------------------------------------------------
 
185
 */
 
186
 
 
187
int
 
188
VMBlockVnodePut(struct vnode *vp)
 
189
{
 
190
   VMBlockVnodeInfo *vip;
 
191
   struct vnode *realVnode;
 
192
 
 
193
   Debug(VMBLOCK_ENTRY_LOGLEVEL, "VMBlockVnodePut: entry (%p)\n", vp);
 
194
 
 
195
   mutex_enter(&vp->v_lock);
 
196
   if (vp->v_count > 1) {
 
197
      vp->v_count--;
 
198
      mutex_exit(&vp->v_lock);
 
199
      return 0;
 
200
   }
 
201
   mutex_exit(&vp->v_lock);
 
202
 
 
203
   vip = (VMBlockVnodeInfo *)vp->v_data;
 
204
   realVnode = vip->realVnode;
 
205
 
 
206
   kmem_free(vip, sizeof *vip);
 
207
   vn_free(vp);
 
208
   /*
 
209
    * VMBlockVnodeGet() doesn't VN_HOLD() the real vnode, but all callers of it
 
210
    * will have the vnode held, so we need to VN_RELE() here.
 
211
    */
 
212
   VN_RELE(realVnode);
 
213
 
 
214
   return 0;
 
215
}
 
216
 
 
217
 
 
218
/*
 
219
 *----------------------------------------------------------------------------
 
220
 *
 
221
 * VMBlockInit --
 
222
 *
 
223
 *    This is the file system initialization routine.  It creates an array of
 
224
 *    fs_operation_def_t for all the vfs operations, then calls vfs_makefsops()
 
225
 *    and vfs_setfsops() to assign them to the file system properly.
 
226
 *
 
227
 * Results:
 
228
 *    Returns zero on success and a non-zero error code on error.
 
229
 *
 
230
 * Side effects:
 
231
 *    None.
 
232
 *
 
233
 *----------------------------------------------------------------------------
 
234
 */
 
235
 
 
236
int
 
237
VMBlockInit(int fstype,    // IN: file system type
 
238
            char *name)    // IN: Name of the file system
 
239
{
 
240
   int ret;
 
241
   static const fs_operation_def_t vfsOpsArr[] = {
 
242
      VMBLOCK_VOP(VFSNAME_MOUNT, vfs_mount, VMBlockMount),
 
243
      VMBLOCK_VOP(VFSNAME_UNMOUNT, vfs_unmount, VMBlockUnmount),
 
244
      VMBLOCK_VOP(VFSNAME_ROOT, vfs_root, VMBlockRoot),
 
245
      VMBLOCK_VOP(VFSNAME_STATVFS, vfs_statvfs, VMBlockStatvfs),
 
246
      { NULL }
 
247
   };
 
248
 
 
249
   if (!name) {
 
250
      Warning("VMBlockInit: received NULL input from kernel.\n");
 
251
      return EINVAL;
 
252
   }
 
253
 
 
254
   Debug(VMBLOCK_ENTRY_LOGLEVEL, "VMBlockInit: fstype=%d, name=\"%s\"\n", fstype, name);
 
255
 
 
256
   /*
 
257
    * Set our file system type and the vfs operations in the kernel's VFS
 
258
    * switch table.
 
259
    */
 
260
   vmblockType = fstype;
 
261
 
 
262
   ret = vfs_setfsops(vmblockType, vfsOpsArr, &vmblockVfsOps);
 
263
   if (ret) {
 
264
      Warning("VMBlockInit: could not set vfs operations.\n");
 
265
      return ret;
 
266
   }
 
267
 
 
268
   ret = vn_make_ops(name, vnodeOpsArr, &vmblockVnodeOps);
 
269
   if (ret) {
 
270
      Warning("VMBlockInit: could not create vnode operations.\n");
 
271
      /*
 
272
       * It's important not to call vfs_freevfsops() here; that's only for
 
273
       * freeing ops created with vfs_makefsops().
 
274
       */
 
275
      vfs_freevfsops_by_type(vmblockType);
 
276
      return ret;
 
277
   }
 
278
 
 
279
   /*
 
280
    * We need to find a unique device number for this instance of the module;
 
281
    * it will be used at each mount to secure a unique device number and file
 
282
    * system identifier.  If one cannot be located, we'll just use zero like
 
283
    * other Solaris file systems.
 
284
    */
 
285
   if ((vmblockMajor = getudev()) == (major_t)-1) {
 
286
        Warning("VMBlockInit: could not obtain unique device.\n");
 
287
        vmblockMajor = 0;
 
288
   }
 
289
   vmblockMinor = 0;
 
290
   mutex_init(&vmblockMutex, NULL, MUTEX_DEFAULT, NULL);
 
291
 
 
292
   return 0;
 
293
}
 
294
 
 
295
 
 
296
/*
 
297
 * VFS Entry Points
 
298
 */
 
299
 
 
300
/*
 
301
 *----------------------------------------------------------------------------
 
302
 *
 
303
 * VMBlockMount --
 
304
 *
 
305
 *   This function is invoked when mount(2) is called on our file system.
 
306
 *   The file system is mounted on the supplied vnode.
 
307
 *
 
308
 * Results:
 
309
 *   Returns zero on success and an appropriate error code on error.
 
310
 *
 
311
 * Side effects:
 
312
 *   The file system is mounted on top of vnodep.
 
313
 *
 
314
 *----------------------------------------------------------------------------
 
315
 */
 
316
 
 
317
static int
 
318
VMBlockMount(struct vfs *vfsp,     // IN: file system to mount
 
319
             struct vnode *vnodep, // IN: Vnode that we are mounting on
 
320
             struct mounta *mntp,  // IN: Arguments to mount(2) from user
 
321
             struct cred *credp)   // IN: Credentials of caller
 
322
{
 
323
   VMBlockMountInfo *mip;
 
324
   int ret;
 
325
 
 
326
   Debug(VMBLOCK_ENTRY_LOGLEVEL, "VMBlockMount: entry\n");
 
327
 
 
328
   /*
 
329
    * These next few checks are done by all other Solaris file systems, so
 
330
    * let's follow their lead.
 
331
    */
 
332
   ret = secpolicy_fs_mount(credp, vnodep, vfsp);
 
333
   if (ret) {
 
334
      Warning("VMBlockMount: mounting security check failed.\n");
 
335
      return ret;
 
336
   }
 
337
 
 
338
   if (vnodep->v_type != VDIR) {
 
339
      Warning("VMBlockMount: not mounting on a directory.\n");
 
340
      return ENOTDIR;
 
341
   }
 
342
 
 
343
   mutex_enter(&vnodep->v_lock);
 
344
   if ((mntp->flags & MS_OVERLAY) == 0 &&
 
345
       (vnodep->v_count != 1 || (vnodep->v_flag & VROOT))) {
 
346
      mutex_exit(&vnodep->v_lock);
 
347
      Warning("VMBlockMount: cannot allow unrequested overlay mount.\n");
 
348
      return EBUSY;
 
349
   }
 
350
   mutex_exit(&vnodep->v_lock);
 
351
 
 
352
   /*
 
353
    * The directory we are redirecting to is specified as the special file
 
354
    * since we have no actual device to mount on.  We store that path in the
 
355
    * mount information structure (note that there's another allocation inside
 
356
    * pn_get() so we must pn_free() that path at unmount time). KM_SLEEP
 
357
    * guarantees our memory allocation will succeed (pn_get() uses this flag
 
358
    * too).
 
359
    */
 
360
   mip = kmem_zalloc(sizeof *mip, KM_SLEEP);
 
361
   ret = pn_get(mntp->spec,
 
362
                (mntp->flags & MS_SYSSPACE) ? UIO_SYSSPACE : UIO_USERSPACE,
 
363
                &mip->redirectPath);
 
364
   if (ret) {
 
365
      Warning("VMBlockMount: could not obtain redirecting directory.\n");
 
366
      kmem_free(mip, sizeof *mip);
 
367
      return ret;
 
368
   }
 
369
 
 
370
   /* Do a lookup on the specified path. */
 
371
   ret = lookupname(mntp->spec,
 
372
                    (mntp->flags & MS_SYSSPACE) ? UIO_SYSSPACE : UIO_USERSPACE,
 
373
                    FOLLOW,
 
374
                    NULLVPP,
 
375
                    &mip->redirectVnode);
 
376
   if (ret) {
 
377
      Warning("VMBlockMount: could not obtain redirecting directory.\n");
 
378
      goto error_lookup;
 
379
   }
 
380
 
 
381
   if (mip->redirectVnode->v_type != VDIR) {
 
382
      Warning("VMBlockMount: not redirecting to a directory.\n");
 
383
      ret = ENOTDIR;
 
384
      goto error;
 
385
   }
 
386
 
 
387
   /*
 
388
    * Initialize our vfs structure.
 
389
    */
 
390
   vfsp->vfs_vnodecovered = vnodep;
 
391
   vfsp->vfs_flag &= ~VFS_UNMOUNTED;
 
392
   vfsp->vfs_flag |= VMBLOCK_VFS_FLAGS;
 
393
   vfsp->vfs_bsize = PAGESIZE;
 
394
   vfsp->vfs_fstype = vmblockType;
 
395
   vfsp->vfs_bcount = 0;
 
396
   /* If we had mount options, we'd call vfs_setmntopt with vfsp->vfs_mntopts */
 
397
 
 
398
   /* Locate a unique device minor number for this mount. */
 
399
   mutex_enter(&vmblockMutex);
 
400
   do {
 
401
      vfsp->vfs_dev = makedevice(vmblockMajor, vmblockMinor);
 
402
      vmblockMinor = (vmblockMinor + 1) & L_MAXMIN32;
 
403
   } while (vfs_devismounted(vfsp->vfs_dev));
 
404
   mutex_exit(&vmblockMutex);
 
405
 
 
406
   vfs_make_fsid(&vfsp->vfs_fsid, vfsp->vfs_dev, vmblockType);
 
407
   vfsp->vfs_data = (caddr_t)mip;
 
408
 
 
409
   /*
 
410
    * Now create the root vnode of the file system.
 
411
    */
 
412
   ret = VMBlockVnodeGet(&mip->root, mip->redirectVnode,
 
413
                         mip->redirectPath.pn_path,
 
414
                         mip->redirectPath.pn_pathlen,
 
415
                         NULL, vfsp, TRUE);
 
416
   if (ret) {
 
417
      Warning("VMBlockMount: couldn't create root vnode.\n");
 
418
      ret = EFAULT;
 
419
      goto error;
 
420
   }
 
421
 
 
422
   VN_HOLD(vfsp->vfs_vnodecovered);
 
423
   return 0;
 
424
 
 
425
error:
 
426
   /* lookupname() provides a held vnode. */
 
427
   VN_RELE(mip->redirectVnode);
 
428
error_lookup:
 
429
   pn_free(&mip->redirectPath);
 
430
   kmem_free(mip, sizeof *mip);
 
431
   return ret;
 
432
}
 
433
 
 
434
 
 
435
/*
 
436
 *----------------------------------------------------------------------------
 
437
 *
 
438
 * VMBlockUnmount --
 
439
 *
 
440
 *    This function is invoked when umount(2) is called on our file system.
 
441
 *
 
442
 * Results:
 
443
 *    Returns zero on success and an error code on error.
 
444
 *
 
445
 * Side effects:
 
446
 *    The root vnode will be freed.
 
447
 *
 
448
 *----------------------------------------------------------------------------
 
449
 */
 
450
 
 
451
static int
 
452
VMBlockUnmount(struct vfs *vfsp,   // IN: This file system
 
453
               int flag,           // IN: Unmount flags
 
454
               struct cred *credp) // IN: Credentials of caller
 
455
{
 
456
   VMBlockMountInfo *mip;
 
457
   int ret;
 
458
 
 
459
   Debug(VMBLOCK_ENTRY_LOGLEVEL, "VMBlockUnmount: entry\n");
 
460
 
 
461
   ret = secpolicy_fs_unmount(credp, vfsp);
 
462
   if (ret) {
 
463
      return ret;
 
464
   }
 
465
 
 
466
   mip = (VMBlockMountInfo *)vfsp->vfs_data;
 
467
 
 
468
   mutex_enter(&mip->root->v_lock);
 
469
   if (mip->root->v_count > 1) {
 
470
      mutex_exit(&mip->root->v_lock);
 
471
      return EBUSY;
 
472
   }
 
473
   mutex_exit(&mip->root->v_lock);
 
474
 
 
475
   VN_RELE(vfsp->vfs_vnodecovered);
 
476
   /*
 
477
    * We don't need to VN_RELE() mip->redirectVnode since it's the realVnode
 
478
    * for mip->root.  That means when we VN_RELE() mip->root and
 
479
    * VMBlockInactive() is called, VMBlockVnodePut() will VN_RELE()
 
480
    * mip->redirectVnode for us.  It's like magic, but better.
 
481
    */
 
482
   VN_RELE(mip->root);
 
483
 
 
484
   pn_free(&mip->redirectPath);
 
485
   kmem_free(mip, sizeof *mip);
 
486
 
 
487
   vfsp->vfs_flag |= VFS_UNMOUNTED;
 
488
 
 
489
   return 0;
 
490
}
 
491
 
 
492
 
 
493
/*
 
494
 *----------------------------------------------------------------------------
 
495
 *
 
496
 * VMBlockRoot --
 
497
 *
 
498
 *    This supplies the root vnode for the file system.
 
499
 *
 
500
 * Results:
 
501
 *    Returns zero on success and an error code on error.  On success vnodepp
 
502
 *    is set to the pointer of the root vnode.
 
503
 *
 
504
 * Side effects:
 
505
 *    The root vnode's reference count is incremented by one.
 
506
 *
 
507
 *----------------------------------------------------------------------------
 
508
 */
 
509
 
 
510
static int
 
511
VMBlockRoot(struct vfs *vfsp,       // IN: file system to find root vnode of
 
512
            struct vnode **vnodepp) // OUT: Set to pointer to root vnode of this fs
 
513
{
 
514
   VMBlockMountInfo *mip;
 
515
 
 
516
   Debug(VMBLOCK_ENTRY_LOGLEVEL, "VMBlockRoot: entry\n");
 
517
 
 
518
   mip = (VMBlockMountInfo *)vfsp->vfs_data;
 
519
 
 
520
   VN_HOLD(mip->root);
 
521
   *vnodepp = mip->root;
 
522
 
 
523
   return 0;
 
524
}
 
525
 
 
526
 
 
527
/*
 
528
 *----------------------------------------------------------------------------
 
529
 *
 
530
 * VMBlockStatvfs --
 
531
 *
 
532
 *    Provides statistics for the provided file system.  The values provided
 
533
 *    by this function are fake.
 
534
 *
 
535
 * Results:
 
536
 *    Returns zero on success and a non-zero error code on exit.
 
537
 *
 
538
 * Side effects:
 
539
 *    None.
 
540
 *
 
541
 *----------------------------------------------------------------------------
 
542
 */
 
543
 
 
544
int
 
545
VMBlockStatvfs(struct vfs *vfsp,         // IN: file system to get statistics for
 
546
               struct statvfs64 *stats)  // OUT: Statistics are placed into this struct
 
547
{
 
548
   dev32_t dev32;
 
549
 
 
550
   Debug(VMBLOCK_ENTRY_LOGLEVEL, "VMBlockStatvfs: entry\n");
 
551
 
 
552
   /* Clear stats struct, then fill it in with our values. */
 
553
   memset(stats, 0, sizeof *stats);
 
554
 
 
555
   /*
 
556
    * Macros in case we need these elsewhere later.
 
557
    *
 
558
    * Since vmblock does not provide any actual storage, we use zero so that
 
559
    * the output of df(1) is pleasant for users.
 
560
    */
 
561
   #define VMBLOCK_BLOCKSIZE       PAGESIZE
 
562
   #define VMBLOCK_BLOCKS_TOTAL    0
 
563
   #define VMBLOCK_BLOCKS_FREE     0
 
564
   #define VMBLOCK_BLOCKS_AVAIL    0
 
565
   #define VMBLOCK_FILES_TOTAL     0
 
566
   #define VMBLOCK_FILES_FREE      0
 
567
   #define VMBLOCK_FILES_AVAIL     0
 
568
 
 
569
   /* Compress the device number to 32-bits for consistency on 64-bit systems. */
 
570
   cmpldev(&dev32, vfsp->vfs_dev);
 
571
 
 
572
   stats->f_bsize   = VMBLOCK_BLOCKSIZE;        /* Preferred fs block size */
 
573
   stats->f_frsize  = VMBLOCK_BLOCKSIZE;        /* Fundamental fs block size */
 
574
   /* Next six are u_longlong_t */
 
575
   stats->f_blocks  = VMBLOCK_BLOCKS_TOTAL;     /* Total blocks on fs */
 
576
   stats->f_bfree   = VMBLOCK_BLOCKS_FREE;      /* Total free blocks */
 
577
   stats->f_bavail  = VMBLOCK_BLOCKS_AVAIL;     /* Total blocks avail to non-root */
 
578
   stats->f_files   = VMBLOCK_FILES_TOTAL;      /* Total files (inodes) */
 
579
   stats->f_ffree   = VMBLOCK_FILES_FREE;       /* Total files free */
 
580
   stats->f_favail  = VMBLOCK_FILES_AVAIL;      /* Total files avail to non-root */
 
581
   stats->f_fsid    = dev32;                    /* file system id */
 
582
   stats->f_flag   &= ST_NOSUID;                /* Flags: we don't support setuid. */
 
583
   stats->f_namemax = MAXNAMELEN;               /* Max filename; use Solaris default. */
 
584
 
 
585
   /* Memset above and -1 of array size as n below ensure NUL termination. */
 
586
   strncpy(stats->f_basetype, VMBLOCK_FS_NAME, sizeof stats->f_basetype - 1);
 
587
   strncpy(stats->f_fstr, VMBLOCK_FS_NAME, sizeof stats->f_fstr - 1);
 
588
 
 
589
   return 0;
 
590
}