summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorRobert Nagy <robert@cvs.openbsd.org>2012-02-16 08:58:50 +0000
committerRobert Nagy <robert@cvs.openbsd.org>2012-02-16 08:58:50 +0000
commite8b689240a88d49e322682c8fb04402eb9584e0d (patch)
tree557f9c661441fbd634b623ed230ecaa75afd9c16 /sys
parent43fc412836a0a5c0f6b4e919a315c43cd2fef2c2 (diff)
add kevent support for msdosfs to make applications
monitoring fs mounts happy tested by ajacoutot@ and ok by thib@, krw@
Diffstat (limited to 'sys')
-rw-r--r--sys/msdosfs/msdosfs_vnops.c105
1 files changed, 103 insertions, 2 deletions
diff --git a/sys/msdosfs/msdosfs_vnops.c b/sys/msdosfs/msdosfs_vnops.c
index 8f63fada548..fbe2d384b52 100644
--- a/sys/msdosfs/msdosfs_vnops.c
+++ b/sys/msdosfs/msdosfs_vnops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: msdosfs_vnops.c,v 1.79 2011/07/04 20:35:35 deraadt Exp $ */
+/* $OpenBSD: msdosfs_vnops.c,v 1.80 2012/02/16 08:58:49 robert Exp $ */
/* $NetBSD: msdosfs_vnops.c,v 1.63 1997/10/17 11:24:19 ws Exp $ */
/*-
@@ -78,6 +78,12 @@
static uint32_t fileidhash(uint64_t);
+int msdosfs_kqfilter(void *);
+int filt_msdosfsreadwrite(struct knote *, long);
+int filt_msdosfsvnode(struct knote *, long);
+void filt_msdosfsdetach(struct knote *);
+
+
/*
* Some general notes:
*
@@ -156,6 +162,7 @@ msdosfs_create(void *v)
goto bad;
if ((cnp->cn_flags & SAVESTART) == 0)
pool_put(&namei_pool, cnp->cn_pnbuf);
+ VN_KNOTE(ap->a_dvp, NOTE_WRITE);
vput(ap->a_dvp);
*ap->a_vpp = DETOV(dep);
return (0);
@@ -172,6 +179,7 @@ msdosfs_mknod(void *v)
struct vop_mknod_args *ap = v;
pool_put(&namei_pool, ap->a_cnp->cn_pnbuf);
+ VN_KNOTE(ap->a_dvp, NOTE_WRITE);
vput(ap->a_dvp);
return (EINVAL);
}
@@ -413,6 +421,7 @@ msdosfs_setattr(void *v)
dep->de_Attributes |= ATTR_ARCHIVE;
dep->de_flag |= DE_MODIFIED;
}
+ VN_KNOTE(ap->a_vp, NOTE_ATTRIB);
return (deupdat(dep, 1));
}
@@ -508,6 +517,7 @@ msdosfs_write(void *v)
int n;
int croffset;
int resid;
+ int extended = 0;
uint32_t osize;
int error = 0;
uint32_t count, lastcn;
@@ -583,6 +593,7 @@ msdosfs_write(void *v)
* size ahead of the time to hopefully get a contiguous area.
*/
if (uio->uio_offset + resid > osize) {
+ extended = 1;
count = de_clcount(pmp, uio->uio_offset + resid) -
de_clcount(pmp, osize);
if ((error = extendfile(dep, count, NULL, NULL, 0)) &&
@@ -670,6 +681,12 @@ msdosfs_write(void *v)
dep->de_flag |= DE_UPDATE;
} while (error == 0 && uio->uio_resid > 0);
+ if (resid > uio->uio_resid)
+ VN_KNOTE(ap->a_vp, NOTE_WRITE | (extended ? NOTE_EXTEND : 0));
+
+ if (dep->de_FileSize < osize)
+ VN_KNOTE(ap->a_vp, NOTE_TRUNCATE);
+
/*
* If the write failed and they want us to, truncate the file back
* to the size it was before the write was attempted.
@@ -749,6 +766,10 @@ msdosfs_remove(void *v)
error = EPERM;
else
error = removede(ddep, dep);
+
+ VN_KNOTE(ap->a_vp, NOTE_DELETE);
+ VN_KNOTE(ap->a_dvp, NOTE_WRITE);
+
#ifdef MSDOSFS_DEBUG
printf("msdosfs_remove(), dep %08x, v_usecount %d\n", dep, ap->a_vp->v_usecount);
#endif
@@ -915,6 +936,7 @@ abortit:
ip->de_flag |= DE_RENAME;
doingdirectory++;
}
+ VN_KNOTE(fdvp, NOTE_WRITE); /* XXX right place? */
/*
* When the target exists, both the directory
@@ -962,6 +984,8 @@ abortit:
xp = tvp ? VTODE(tvp) : NULL;
}
+ VN_KNOTE(tdvp, NOTE_WRITE);
+
if (xp != NULL) {
/*
* Target must be empty if a directory and have no links
@@ -984,6 +1008,7 @@ abortit:
}
if ((error = removede(dp, xp)) != 0)
goto bad1;
+ VN_KNOTE(tvp, NOTE_DELETE);
vput(tvp);
xp = NULL;
}
@@ -1122,6 +1147,8 @@ abortit:
}
}
+ VN_KNOTE(fvp, NOTE_RENAME);
+
bad:
VOP_UNLOCK(fvp, 0, p);
vrele(fdvp);
@@ -1261,6 +1288,7 @@ msdosfs_mkdir(void *v)
goto bad;
if ((cnp->cn_flags & SAVESTART) == 0)
pool_put(&namei_pool, cnp->cn_pnbuf);
+ VN_KNOTE(ap->a_dvp, NOTE_WRITE | NOTE_LINK);
vput(ap->a_dvp);
*ap->a_vpp = DETOV(dep);
return (0);
@@ -1305,6 +1333,9 @@ msdosfs_rmdir(void *v)
error = ENOTEMPTY;
goto out;
}
+
+ VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
+
/*
* Delete the entry from the directory. For dos filesystems this
* gets rid of the directory entry on disk, the in memory copy
@@ -1331,6 +1362,7 @@ msdosfs_rmdir(void *v)
out:
if (dvp)
vput(dvp);
+ VN_KNOTE(vp, NOTE_DELETE);
vput(vp);
return (error);
}
@@ -1826,6 +1858,7 @@ struct vops msdosfs_vops = {
.vop_write = msdosfs_write,
.vop_ioctl = msdosfs_ioctl,
.vop_poll = msdosfs_poll,
+ .vop_kqfilter = msdosfs_kqfilter,
.vop_fsync = msdosfs_fsync,
.vop_remove = msdosfs_remove,
.vop_link = msdosfs_link,
@@ -1846,5 +1879,73 @@ struct vops msdosfs_vops = {
.vop_islocked = msdosfs_islocked,
.vop_pathconf = msdosfs_pathconf,
.vop_advlock = msdosfs_advlock,
- .vop_bwrite = vop_generic_bwrite
+ .vop_bwrite = vop_generic_bwrite
};
+
+struct filterops msdosfsreadwrite_filtops =
+ { 1, NULL, filt_msdosfsdetach, filt_msdosfsreadwrite };
+struct filterops msdosfsvnode_filtops =
+ { 1, NULL, filt_msdosfsdetach, filt_msdosfsvnode };
+
+int
+msdosfs_kqfilter(void *v)
+{
+ struct vop_kqfilter_args *ap = v;
+ struct vnode *vp = ap->a_vp;
+ struct knote *kn = ap->a_kn;
+
+ switch (kn->kn_filter) {
+ case EVFILT_READ:
+ kn->kn_fop = &msdosfsreadwrite_filtops;
+ break;
+ case EVFILT_WRITE:
+ kn->kn_fop = &msdosfsreadwrite_filtops;
+ break;
+ case EVFILT_VNODE:
+ kn->kn_fop = &msdosfsvnode_filtops;
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ kn->kn_hook = (caddr_t)vp;
+
+ SLIST_INSERT_HEAD(&vp->v_selectinfo.si_note, kn, kn_selnext);
+
+ return (0);
+}
+
+void
+filt_msdosfsdetach(struct knote *kn)
+{
+ struct vnode *vp = (struct vnode *)kn->kn_hook;
+
+ SLIST_REMOVE(&vp->v_selectinfo.si_note, kn, knote, kn_selnext);
+}
+
+int
+filt_msdosfsreadwrite(struct knote *kn, long hint)
+{
+ /*
+ * filesystem is gone, so set the EOF flag and schedule
+ * the knote for deletion.
+ */
+ if (hint == NOTE_REVOKE) {
+ kn->kn_flags |= (EV_EOF | EV_ONESHOT);
+ return (1);
+ }
+
+ return (kn->kn_data != 0);
+}
+
+int
+filt_msdosfsvnode(struct knote *kn, long hint)
+{
+ if (kn->kn_sfflags & hint)
+ kn->kn_fflags |= hint;
+ if (hint == NOTE_REVOKE) {
+ kn->kn_flags |= EV_EOF;
+ return (1);
+ }
+ return (kn->kn_fflags != 0);
+}