PERFORCE change 182127 for review
Ilya Putsikau
ilya at skunkworks.freebsd.org
Wed Aug 11 18:25:58 UTC 2010
http://p4web.freebsd.org/@@182127?ac=10
Change 182127 by ilya at ilya_triton on 2010/08/09 12:29:53
Update tests, add inotify tests, add linux test output. Fix various bugs found with test cases.
Don't save/lookup full paths use relative paths only, as linux does.
Affected files ...
.. //depot/projects/soc2010/ilya_fsnotify/src/sys/kern/vfs_notify.c#10 edit
.. //depot/projects/soc2010/ilya_fsnotify/src/tools/regression/fsnotify/regress.02.sh#1 add
.. //depot/projects/soc2010/ilya_fsnotify/src/tools/regression/fsnotify/regress.03.sh#1 add
.. //depot/projects/soc2010/ilya_fsnotify/src/tools/regression/fsnotify/regress.04.sh#1 add
.. //depot/projects/soc2010/ilya_fsnotify/src/tools/regression/inotify/Makefile#1 add
.. //depot/projects/soc2010/ilya_fsnotify/src/tools/regression/inotify/inotify-test#1 add
.. //depot/projects/soc2010/ilya_fsnotify/src/tools/regression/inotify/inotify-test.c#1 add
.. //depot/projects/soc2010/ilya_fsnotify/src/tools/regression/inotify/inotify-test.o#1 add
.. //depot/projects/soc2010/ilya_fsnotify/src/tools/regression/inotify/regress.00.out#1 add
.. //depot/projects/soc2010/ilya_fsnotify/src/tools/regression/inotify/regress.00.out-linux#1 add
.. //depot/projects/soc2010/ilya_fsnotify/src/tools/regression/inotify/regress.00.sh#1 add
.. //depot/projects/soc2010/ilya_fsnotify/src/tools/regression/inotify/regress.01.out#1 add
.. //depot/projects/soc2010/ilya_fsnotify/src/tools/regression/inotify/regress.01.out-linux#1 add
.. //depot/projects/soc2010/ilya_fsnotify/src/tools/regression/inotify/regress.01.sh#1 add
.. //depot/projects/soc2010/ilya_fsnotify/src/tools/regression/inotify/regress.02.out#1 add
.. //depot/projects/soc2010/ilya_fsnotify/src/tools/regression/inotify/regress.02.out-linux#1 add
.. //depot/projects/soc2010/ilya_fsnotify/src/tools/regression/inotify/regress.02.sh#1 add
.. //depot/projects/soc2010/ilya_fsnotify/src/tools/regression/inotify/regress.03.out#1 add
.. //depot/projects/soc2010/ilya_fsnotify/src/tools/regression/inotify/regress.03.out-linux#1 add
.. //depot/projects/soc2010/ilya_fsnotify/src/tools/regression/inotify/regress.03.sh#1 add
.. //depot/projects/soc2010/ilya_fsnotify/src/tools/regression/inotify/regress.04.out#1 add
.. //depot/projects/soc2010/ilya_fsnotify/src/tools/regression/inotify/regress.04.out-linux#1 add
.. //depot/projects/soc2010/ilya_fsnotify/src/tools/regression/inotify/regress.04.sh#1 add
.. //depot/projects/soc2010/ilya_fsnotify/src/tools/regression/inotify/regress.m4#1 add
.. //depot/projects/soc2010/ilya_fsnotify/src/tools/regression/inotify/regress.sh#1 add
Differences ...
==== //depot/projects/soc2010/ilya_fsnotify/src/sys/kern/vfs_notify.c#10 (text+ko) ====
@@ -76,11 +76,10 @@
struct mtx nd_mtx;
struct vnode *nd_vnode;
struct mount *nd_mount;
- char *nd_path;
- char *nd_pathfree;
+ char *nd_name;
ino_t nd_ino;
volatile u_int nd_refcnt;
- int nd_pathlen;
+ int nd_namelen;
int nd_watchcount;
u_int nd_supermask;
int nd_flags;
@@ -95,8 +94,8 @@
struct fnevent {
TAILQ_ENTRY(fnevent) ev_queueentry;
struct fnnode *ev_node;
- char *ev_pathfree;
- int ev_pathpos;
+ char *ev_name;
+ int ev_namelen;
int ev_mask;
int ev_cookie;
int ev_handlecount;
@@ -182,7 +181,8 @@
int mask, struct fnwatch **watchpp);
static int session_rmwatch(struct fnsession *ss, int wd);
-static struct fnnode* node_alloc(struct vnode *vp, ino_t ino);
+static struct fnnode* node_alloc(struct vnode *vp, ino_t ino, char *name,
+ int namelen);
static struct fnnode* node_lookup(struct vnode *vp);
static struct fnnode* node_lookupex(struct vnode *vp, ino_t *inop, int flags);
static void node_hold(struct fnnode *node);
@@ -190,15 +190,12 @@
static void node_watchhold(struct fnnode *node);
static void node_watchdrop(struct fnnode *node);
-static void event_copypath(struct fnevent *event, char *path);
-static int event_userpathlen(struct fnevent *event);
static void event_enqueue(struct fnnode *node, struct componentname *cnp,
int *cookiep, int mask);
static void watch_free(struct fnwatch *watch);
-#define NODE_ISDIR 0x0001
-#define NODE_CHANGED 0x0002
+#define NODE_CHANGED 0x0001
#define LOOKUP_VPLOCKED 0x0001
#define LOOKUP_IGNINVAL 0x0002
@@ -339,6 +336,7 @@
while (!TAILQ_EMPTY(&ss->ss_watchlist)) {
watch = TAILQ_FIRST(&ss->ss_watchlist);
watch_free(watch);
+ SESSION_LOCK(ss);
}
SESSION_UNLOCK(ss);
@@ -378,7 +376,7 @@
struct fnwatch *watch;
struct fsnotify_event *fe;
int destroy, len, error;
- char user_buf[sizeof(struct fsnotify_event) + MAXPATHLEN];
+ char user_buf[sizeof(struct fsnotify_event) + NAME_MAX + 1];
printf("fsnotify_read: offset %jd\n", uio->uio_offset);
@@ -413,24 +411,24 @@
}
event = eh->eh_event;
watch = eh->eh_watch;
- fe->len = event_userpathlen(event);
+ fe->len = event->ev_namelen + 1;
len = fe->len + sizeof(struct fsnotify_event);
if (len > uio->uio_resid) {
SESSION_UNLOCK(ss);
break;
}
fe->wd = watch->wt_wd;
- fe->mask = watch->wt_mask & event->ev_mask;
+ fe->mask = (FN_FLAGS | watch->wt_mask) & event->ev_mask;
fe->fileno = event->ev_node->nd_ino;
fe->cookie = event->ev_cookie;
- event_copypath(event, fe->name);
+ memcpy(fe->name, event->ev_name, event->ev_namelen + 1);
destroy = event->ev_mask & FN_DESTROY;
session_drophandle(ss, eh);
if (destroy != 0)
watch_free(watch);
-
- SESSION_UNLOCK(ss);
+ else
+ SESSION_UNLOCK(ss);
MPASS(len <= uio->uio_resid);
error = uiomove(user_buf, len, uio);
@@ -457,7 +455,7 @@
SESSION_LOCK(ss);
TAILQ_FOREACH(eh, &ss->ss_queue, eh_queueentry) {
*nread += sizeof(struct fsnotify_event) +
- event_userpathlen(eh->eh_event);
+ eh->eh_event->ev_namelen;
}
SESSION_UNLOCK(ss);
@@ -472,21 +470,24 @@
struct fnwatch *watch;
struct file *fp;
struct filedesc *fdp;
- struct vnode *vp;
- char *path, *pathfree;
+ struct vnode *vp, *xvp;
+ char *name;
ino_t ino;
int error = 0, vfslocked;
+ u_int namelen;
fdp = td->td_proc->p_fd;
vp = NULL;
FILEDESC_SLOCK(fdp);
fp = fget_locked(fdp, ap->fd);
- if (fp != NULL && fp->f_type == DTYPE_VNODE) {
+ if (fp != NULL && fp->f_type == DTYPE_VNODE)
vp = fp->f_vnode;
- }
FILEDESC_SUNLOCK(fdp);
if (vp == NULL)
return (EBADF);
+ /* FIXME FIXME */
+ if (vp->v_type != VDIR)
+ return (EINVAL);
vfslocked = VFS_LOCK_GIANT(vp->v_mount);
ino = 0;
node = node_lookupex(vp, &ino, LOOKUP_IGNINVAL);
@@ -495,16 +496,21 @@
NODE_UNLOCK(node);
VFS_UNLOCK_GIANT(vfslocked);
} else {
- error = vn_fullpath_global(td, vp, &path, &pathfree);
- VFS_UNLOCK_GIANT(vfslocked);
+ namelen = NAME_MAX;
+ name = malloc(namelen + 1, M_FSNOTIFY, M_WAITOK);
+ xvp = vp;
+ error = vn_vptocnp(&xvp, td->td_ucred, name, &namelen);
if (error == 0) {
- node = node_alloc(vp, ino);
- node->nd_path = path;
- node->nd_pathlen = strlen(path);
- node->nd_pathfree = pathfree;
+ memcpy(name, name + namelen, NAME_MAX - namelen);
+ namelen = NAME_MAX - namelen;
+ name[namelen] = '\0';
+ node = node_alloc(vp, ino, name, namelen);
node_watchhold(node);
+ vdrop(xvp);
NODE_UNLOCK(node);
- }
+ } else
+ free(name, M_FSNOTIFY);
+ VFS_UNLOCK_GIANT(vfslocked);
}
if ((ap->mask & FN_CLOSEFD) != 0) {
@@ -580,6 +586,13 @@
/*
* VFS hooks
*/
+
+static __inline int
+vp_isdir(struct vnode *vp)
+{
+ return (vp->v_type == VDIR ? FN_ISDIR : 0);
+}
+
static void
hook_reclaim(struct vnode *vp)
{
@@ -604,12 +617,13 @@
static void
hook_open(struct vop_open_args *ap)
{
+ struct vnode *vp = ap->a_vp;
struct fnnode *node;
int cookie = 0;
- node = node_lookup(ap->a_vp);
+ node = node_lookup(vp);
if (node != NULL) {
- if ((node->nd_flags & NODE_ISDIR) == 0)
+ if (vp_isdir(vp) == 0)
event_enqueue(node, NULL, &cookie, FN_OPEN);
else
NODE_UNLOCK(node);
@@ -619,12 +633,13 @@
static void
hook_close(struct vop_close_args *ap)
{
+ struct vnode *vp = ap->a_vp;
struct fnnode *node;
int cookie = 0, mask;
- node = node_lookup(ap->a_vp);
+ node = node_lookup(vp);
if (node != NULL) {
- if ((node->nd_flags & NODE_ISDIR) == 0) {
+ if (vp_isdir(vp) == 0) {
mask = (node->nd_flags & NODE_CHANGED) != 0 ?
FN_CLOSE_RW : FN_CLOSE_RO;
event_enqueue(node, NULL, &cookie, mask);
@@ -652,11 +667,12 @@
static void
hook_write(struct vop_write_args *ap)
{
+ struct vnode *vp = ap->a_vp;
struct fnnode *node;
- node = node_lookup(ap->a_vp);
+ node = node_lookup(vp);
if (node != NULL) {
- if ((node->nd_flags & NODE_ISDIR) == 0)
+ if (vp_isdir(vp) == 0)
node->nd_flags |= NODE_CHANGED;
NODE_UNLOCK(node);
}
@@ -665,12 +681,14 @@
static void
hook_setattr(struct vop_setattr_args *ap)
{
+ struct vnode *vp = ap->a_vp;
struct fnnode *node;
int cookie = 0;
- node = node_lookup(ap->a_vp);
+ node = node_lookup(vp);
if (node != NULL) {
- event_enqueue(node, NULL, &cookie, FN_SETATTR);
+ event_enqueue(node, NULL, &cookie,
+ FN_SETATTR | vp_isdir(vp));
}
}
@@ -683,7 +701,8 @@
dirnode = node_lookup(dvp);
if (dirnode != NULL)
- event_enqueue(dirnode, cnp, &cookie, FN_CREATE);
+ event_enqueue(dirnode, cnp, &cookie,
+ FN_CREATE | vp_isdir(vp));
return (0);
}
@@ -698,11 +717,13 @@
node = node_lookup(vp);
if (node != NULL)
- event_enqueue(node, NULL, &cookie, FN_DESTROY | FN_REMOVE);
+ event_enqueue(node, NULL, &cookie,
+ FN_DESTROY | FN_REMOVE | vp_isdir(vp));
dirnode = node_lookup(dvp);
if (dirnode != NULL)
- event_enqueue(dirnode, cnp, &cookie, FN_REMOVE);
+ event_enqueue(dirnode, cnp, &cookie,
+ FN_REMOVE | vp_isdir(vp));
}
static void
@@ -749,13 +770,16 @@
hook_rename(struct vop_rename_args *ap)
{
struct fnnode *fdirnode, *fnode, *tdirnode, *tnode;
+ int dirmask;
int cookie = 0;
+ dirmask = vp_isdir(ap->a_fvp);
+
if (ap->a_tvp != NULL) {
tnode = node_lookupex(ap->a_tvp, NULL, 0);
if (tnode != NULL) {
event_enqueue(tnode, NULL, &cookie,
- FN_DESTROY | FN_REMOVE);
+ FN_DESTROY | FN_REMOVE | dirmask);
}
}
fnode = node_lookupex(ap->a_fvp, NULL, 0);
@@ -767,10 +791,12 @@
fdirnode = node_lookupex(ap->a_fdvp, NULL, 0);
if (fdirnode != NULL)
- event_enqueue(fdirnode, ap->a_fcnp, &cookie, FN_RENAME_FROM);
+ event_enqueue(fdirnode, ap->a_fcnp, &cookie,
+ FN_RENAME_FROM | dirmask);
tdirnode = node_lookupex(ap->a_tdvp, NULL, 0);
if (tdirnode != NULL)
- event_enqueue(tdirnode, ap->a_tcnp, &cookie, FN_RENAME_TO);
+ event_enqueue(tdirnode, ap->a_tcnp, &cookie,
+ FN_RENAME_TO | dirmask);
}
static void
@@ -810,14 +836,15 @@
TAILQ_REMOVE(&ss->ss_watchlist, watch, wt_sessionentry);
watch->wt_session = NULL;
- free_unr(fsnotify_wds, watch->wt_wd);
TAILQ_FOREACH(eh, &ss->ss_queue, eh_queueentry) {
MPASS(eh->eh_watch != watch);
}
- MPASS(watch->wt_session == NULL && watch->wt_node == NULL);
+ MPASS(watch->wt_node == NULL);
printf("watch_free: free %p\n", watch);
+ SESSION_UNLOCK(ss);
+ free_unr(fsnotify_wds, watch->wt_wd);
free(watch, M_FSNOTIFY);
}
@@ -865,7 +892,7 @@
INOHASH_UNLOCK();
}
mtx_destroy(&node->nd_mtx);
- free(node->nd_pathfree, M_TEMP);
+ free(node->nd_name, M_FSNOTIFY);
free(node, M_FSNOTIFY);
}
}
@@ -880,7 +907,7 @@
}
static struct fnnode *
-node_alloc(struct vnode *vp, ino_t ino)
+node_alloc(struct vnode *vp, ino_t ino, char *path, int namelen)
{
struct fnnode *node;
@@ -895,6 +922,8 @@
TAILQ_INIT(&node->nd_watchlist);
node->nd_ino = ino;
+ node->nd_name = path;
+ node->nd_namelen = namelen;
NODE_LOCK(node);
@@ -907,8 +936,6 @@
vholdl(vp);
node->nd_vnode = vp;
vp->v_fnnode = node;
- if (vp->v_type == VDIR)
- node->nd_flags |= NODE_ISDIR;
VI_UNLOCK(vp);
return (node);
@@ -1038,95 +1065,27 @@
return (node_lookupex(vp, NULL, LOOKUP_VPLOCKED));
}
-static int
-node_updatepath(struct fnnode *node)
-{
- struct nameidata ni;
- struct vnode *vp;
- char *path, *pathfree;
- char *npath, *npathfree;
- int vfslocked, error;
-
- /* Should be executed in *single* fsnotify_daemon thread */
- vp = node->nd_vnode;
- if ((vp->v_iflag & VI_DOOMED) != 0 || vp->v_usecount == 0) {
- printf("skip node path update: %p\n", vp);
- return (ENOENT);
- }
-
- printf("node_updatepath: node %p vp %p %s\n",
- node, vp, node->nd_path);
- path = node->nd_path;
- pathfree = node->nd_pathfree;
- npath = npathfree = NULL;
- vhold(vp);
- NODE_UNLOCK(node);
-
- vref(rootvnode);
- NDINIT_ATVP(&ni, LOOKUP, MPSAFE | FOLLOW, UIO_SYSSPACE, path, rootvnode,
- curthread);
- error = namei(&ni);
- if (error == 0) {
- if (vp != ni.ni_vp) {
- printf("fsnotify: vnode was replaced between lookups: %s\n",
- path);
- error = ENOENT;
- }
- NDFREE(&ni, 0);
- }
- if (error != 0) {
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
- error = vn_fullpath_global(curthread, vp, &npath, &npathfree);
- VFS_UNLOCK_GIANT(vfslocked);
- }
-
- if ((vp->v_iflag & VI_DOOMED) != 0) {
- printf("fsnotify: vnode is doomed: %s\n", path);
- error = ENOENT;
- }
- vdrop(vp);
- NODE_LOCK(node);
- if (path != node->nd_path) {
- /* Lookup race */
- free(pathfree, M_TEMP);
- MPASS(node->nd_path != NULL);
- error = 0;
- } else if (error == 0 && npath != NULL) {
- free(node->nd_pathfree, M_TEMP);
- node->nd_path = npath;
- node->nd_pathlen = strlen(npath);
- node->nd_pathfree = npathfree;
- npathfree = NULL;
- }
- if (npathfree != NULL)
- free(npathfree, M_TEMP);
- return (error);
-}
-
static struct fnevent *
event_alloc(struct fnnode *node, char *name, int namelen, int handle_maxsize,
int mask, int cookie)
{
struct fnevent *event;
+ MPASS(namelen > 0 && name != NULL);
MPASS(handle_maxsize > 0);
MPASS(mask != 0);
event = malloc(sizeof(struct fnevent) +
- (sizeof(struct fneventhandle) * handle_maxsize),
+ (sizeof(struct fneventhandle) * handle_maxsize) + namelen + 1,
M_FSNOTIFY, M_WAITOK | M_ZERO);
event->ev_handlemaxsize = handle_maxsize;
event->ev_node = node;
event->ev_mask = mask;
event->ev_cookie = cookie;
- event->ev_pathfree = uma_zalloc(namei_zone, M_WAITOK);
- event->ev_pathpos = MAXPATHLEN - 1 - namelen;
- event->ev_pathfree[MAXPATHLEN - 1] = '\0';
- if (name != NULL) {
- MPASS((node->nd_flags & NODE_ISDIR) != 0);
- memcpy(event->ev_pathfree + event->ev_pathpos, name, namelen);
- }
- printf("event alloc: %p\n", event);
+ event->ev_namelen = namelen;
+ event->ev_name = (char *)(event->ev_handlebuf + handle_maxsize);
+ memcpy(event->ev_name, name, namelen);
+ printf("event alloc: %s\n", event->ev_name);
return (event);
}
@@ -1134,32 +1093,11 @@
static void
event_free(struct fnevent *event)
{
+ printf("event free: %s\n", event->ev_name);
node_drop(event->ev_node);
- uma_zfree(namei_zone, event->ev_pathfree);
free(event, M_FSNOTIFY);
- printf("event free: %p\n", event);
-}
-
-static __inline int
-event_pathlen(struct fnevent *event)
-{
- return (MAXPATHLEN - 1 - event->ev_pathpos);
}
-static __inline int
-event_userpathlen(struct fnevent *event)
-{
- /* Count last zero byte */
- return event_pathlen(event) + 1;
-}
-
-static __inline void
-event_copypath(struct fnevent *event, char *path)
-{
- memcpy(path, event->ev_pathfree + event->ev_pathpos,
- event_userpathlen(event));
-}
-
static void
eventhandle_drop(struct fneventhandle *eh)
{
@@ -1176,24 +1114,6 @@
event_free(eh->eh_event);
}
-static void
-event_prependpath(struct fnevent *event, struct fnnode *node)
-{
- int pos, len;
-
- pos = event->ev_pathpos;
- len = node->nd_pathlen;
- MPASS(len > 0 && node->nd_path[len - 1] != '/');
- MPASS(pos >= len + 1);
-
- if (event_pathlen(event) != 0)
- event->ev_pathfree[--pos] = '/';
- pos -= len;
- memcpy(event->ev_pathfree + pos, node->nd_path, len);
-
- event->ev_pathpos = pos;
-}
-
static int
event_nextcookie(void)
{
@@ -1240,6 +1160,7 @@
if (*cookiep == 0)
*cookiep = event_nextcookie();
+
event = event_alloc(node, nameptr, namelen, watchcount + 1, mask,
*cookiep);
@@ -1258,13 +1179,14 @@
struct fnwatch *w;
mask &= ~FN_FLAGS_INTERNAL;
- if ((mask & FN_FLAGS) != 0) {
- printf("fsnotify: invalid watch mask: %08x\n", mask);
- mask &= ~FN_FLAGS;
+ if ((mask & ~FN_ALL) != 0) {
+ printf("fsnotify: invalid watch mask: %08x -> %08x\n",
+ mask, mask & FN_ALL);
+ mask &= FN_ALL;
}
printf("session_addwatch: %s: node %p session %p\n",
- node->nd_path, node, ss);
+ node->nd_name, node, ss);
watch = malloc(sizeof(struct fnwatch), M_FSNOTIFY, M_WAITOK | M_ZERO);
printf("watch alloc: %p\n", watch);
@@ -1411,13 +1333,6 @@
event_free(event);
continue;
}
- if (node->nd_vnode != NULL &&
- (event->ev_mask & FN_DESTROY) == 0)
- node_updatepath(node);
- else
- printf("fsnotify: vnode not found, reusing cached path: %s\n",
- node->nd_path);
- event_prependpath(event, node);
if (event->ev_mask & FN_DESTROY)
node_detachallwatches(node);
More information about the p4-projects
mailing list