VFS accounting: implement an initialization framework
authorFrancois Tigeot <ftigeot@wolfpond.org>
Sat, 6 Aug 2011 21:02:32 +0000 (23:02 +0200)
committerFrançois Tigeot <ftigeot@wolfpond.org>
Sat, 3 Dec 2011 12:29:49 +0000 (13:29 +0100)
Only enable accounting for a short list of whitelisted filesystem types

sys/conf/files
sys/kern/vfs_default.c
sys/kern/vfs_init.c
sys/kern/vfs_quota.c [new file with mode: 0644]
sys/kern/vfs_vfsops.c
sys/sys/mount.h
sys/sys/vfs_quota.h [new file with mode: 0644]

index d2756ad..3077b98 100644 (file)
@@ -1008,6 +1008,7 @@ kern/vfs_subr.c           standard
 kern/vfs_vm.c          standard
 kern/vfs_lock.c                standard
 kern/vfs_mount.c       standard
+kern/vfs_quota.c       standard
 kern/vfs_sync.c                standard
 kern/vfs_synth.c       standard
 kern/vfs_syscalls.c    standard
index e6e4da4..a32f77f 100644 (file)
@@ -56,6 +56,7 @@
 #include <sys/namei.h>
 #include <sys/nlookup.h>
 #include <sys/mountctl.h>
+#include <sys/vfs_quota.h>
 
 #include <machine/limits.h>
 
@@ -1456,10 +1457,75 @@ vfs_stdextattrctl(struct mount *mp, int cmd, struct vnode *vp,
        return(EOPNOTSUPP);
 }
 
+#define ACCOUNTING_NB_FSTYPES 8
+
+static const char *accounting_fstypes[ACCOUNTING_NB_FSTYPES] = {
+       "ext2fs", "hammer", "hpfs", "mfs", "ntfs", "null", "tmpfs", "ufs" };
+
+int
+vfs_stdac_init(struct mount *mp)
+{
+       const char* fs_type;
+       int i, fstype_ok = 0;
+
+       /* if mounted fs is read-only, do not do anything */
+       if (mp->mnt_flag & MNT_RDONLY)
+               return (0);
+
+       /* is mounted fs type one we want to do some accounting for ? */
+       for (i=0; i<ACCOUNTING_NB_FSTYPES; i++) {
+               fs_type = accounting_fstypes[i];
+               if (strncmp(mp->mnt_stat.f_fstypename, fs_type,
+                                       sizeof(mp->mnt_stat)) == 0) {
+                       fstype_ok = 1;
+                       break;
+               }
+       }
+       if (fstype_ok == 0)
+               return (0);
+
+       kprintf("vfs_quota: enabling accounting for %s\n",
+                                       mp->mnt_stat.f_mntonname);
+       vq_init(mp);
+       return (0);
+}
+
+int
+vfs_stdac_done(struct mount *mp)
+{
+       const char* fs_type;
+       int i, fstype_ok = 0;
+
+       /* if mounted fs is read-only, do not do anything */
+       if (mp->mnt_flag & MNT_RDONLY)
+               return (0);
+
+       /* is mounted fs type one we want to do some accounting for ? */
+       for (i=0; i<ACCOUNTING_NB_FSTYPES; i++) {
+               fs_type = accounting_fstypes[i];
+               if (strncmp(mp->mnt_stat.f_fstypename, fs_type,
+                                       sizeof(mp->mnt_stat)) == 0) {
+                       fstype_ok = 1;
+                       break;
+               }
+       }
+       if (fstype_ok == 0)
+               return (0);
+
+       vq_done(mp);
+       return (0);
+}
+
 int
 vfs_stdaccount(struct mount *mp, uid_t uid, gid_t gid, int64_t delta)
 {
        return(0);
 }
 
+int
+vfs_noaccount(struct mount *mp, uid_t uid, gid_t gid, int64_t delta)
+{
+       return(0);
+}
+
 /* end of vfs default ops */
index 4ac5b5c..020812b 100644 (file)
@@ -420,8 +420,15 @@ vfs_register(struct vfsconf *vfc)
                /* extended attribute control */
                vfsops->vfs_extattrctl = vfs_stdextattrctl;
        }
+
+       /* file system uid and gid accounting */
+       if (vfsops->vfs_acinit == NULL) {
+               vfsops->vfs_acinit = vfs_stdac_init;
+       }
+       if (vfsops->vfs_acdone == NULL) {
+               vfsops->vfs_acdone = vfs_stdac_done;
+       }
        if (vfsops->vfs_account == NULL) {
-               /* file system uid and gid accounting */
                vfsops->vfs_account = vfs_stdaccount;
        }
 
diff --git a/sys/kern/vfs_quota.c b/sys/kern/vfs_quota.c
new file mode 100644 (file)
index 0000000..c7aa371
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2011 François Tigeot <ftigeot@wolpond.org>
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of The DragonFly Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific, prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/sysctl.h>
+#include <sys/mount.h>
+#include <sys/systm.h>
+#include <sys/nlookup.h>
+#include <sys/vnode.h>
+#include <sys/stat.h>
+#include <sys/vfs_quota.h>
+
+/* initializes global accounting data */
+void
+vq_init(struct mount *mp) {
+}
+
+
+void
+vq_done(struct mount *mp) {
+}
index 7b22462..bc5bc8f 100644 (file)
@@ -106,6 +106,10 @@ vfs_start(struct mount *mp, int flags)
 
        VFS_MPLOCK1(mp);
        error = (mp->mnt_op->vfs_start)(mp, flags);
+       if (error == 0)
+               /* do not call vfs_acinit on mount updates */
+               if ((mp->mnt_flag & MNT_UPDATE) == 0)
+                       error = (mp->mnt_op->vfs_acinit)(mp);
        VFS_MPUNLOCK(mp);
        return (error);
 }
@@ -120,7 +124,9 @@ vfs_unmount(struct mount *mp, int mntflags)
        int error;
 
        VFS_MPLOCK1(mp);
-       error = (mp->mnt_op->vfs_unmount)(mp, mntflags);
+       error = (mp->mnt_op->vfs_acdone)(mp); 
+       if (error == 0)
+               error = (mp->mnt_op->vfs_unmount)(mp, mntflags);
        VFS_MPUNLOCK(mp);
        return (error);
 }
index 495314f..2289880 100644 (file)
@@ -62,6 +62,7 @@
 #ifndef _SYS_THREAD_H_
 #include <sys/thread.h>
 #endif
+#include <sys/vfs_quota.h>
 #endif
 
 struct thread;
@@ -501,6 +502,8 @@ typedef int vfs_uninit_t(struct vfsconf *);
 typedef int vfs_extattrctl_t(struct mount *mp, int cmd, struct vnode *vp,
                    int attrnamespace, const char *attrname,
                    struct ucred *cred);
+typedef int vfs_acinit_t(struct mount *mp);
+typedef int vfs_acdone_t(struct mount *mp);
 typedef int vfs_account_t(struct mount *mp,
                        uid_t uid, gid_t gid, int64_t delta);
 
@@ -543,6 +546,8 @@ struct vfsops {
        vfs_uninit_t    *vfs_uninit;
        vfs_extattrctl_t *vfs_extattrctl;
        vfs_statvfs_t   *vfs_statvfs;
+       vfs_acinit_t    *vfs_acinit;
+       vfs_acdone_t    *vfs_acdone;
        vfs_account_t   *vfs_account;
 };
 
@@ -676,7 +681,10 @@ vfs_vptofh_t       vfs_stdvptofh;
 vfs_init_t     vfs_stdinit;
 vfs_uninit_t   vfs_stduninit;
 vfs_extattrctl_t vfs_stdextattrctl;
+vfs_acinit_t   vfs_stdac_init;
+vfs_acdone_t   vfs_stdac_done;
 vfs_account_t  vfs_stdaccount;
+vfs_account_t  vfs_noaccount;
 
 struct vop_access_args;
 int vop_helper_access(struct vop_access_args *ap, uid_t ino_uid, gid_t ino_gid,
diff --git a/sys/sys/vfs_quota.h b/sys/sys/vfs_quota.h
new file mode 100644 (file)
index 0000000..b4676cd
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2011 François Tigeot <ftigeot@wolpond.org>
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The DragonFly Project
+ * by François Tigeot <ftigeot@wolfpond.org>
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of The DragonFly Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific, prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _SYS_VFSQUOTA_H_
+#define _SYS_VFSQUOTA_H_
+
+#include <sys/mount.h>
+
+extern void vq_init(struct mount*);
+extern void vq_done(struct mount*);
+
+#endif
+