| @@ -93,45 +93,43 @@ zfs_match_find(zfsvfs_t *zfsvfs, znode_t | | | @@ -93,45 +93,43 @@ zfs_match_find(zfsvfs_t *zfsvfs, znode_t |
93 | dnlc_update(ZTOV(dzp), name, DNLC_NO_VNODE); | | 93 | dnlc_update(ZTOV(dzp), name, DNLC_NO_VNODE); |
94 | | | 94 | |
95 | return (error); | | 95 | return (error); |
96 | } | | 96 | } |
97 | | | 97 | |
98 | /* | | 98 | /* |
99 | * Reference counting for dirlocks. Solaris destroys the condvar as | | 99 | * Reference counting for dirlocks. Solaris destroys the condvar as |
100 | * soon as it broadcasts, which works for them because cv_wait doesn't | | 100 | * soon as it broadcasts, which works for them because cv_wait doesn't |
101 | * need to use the condvar after it is woken, but which is too fast and | | 101 | * need to use the condvar after it is woken, but which is too fast and |
102 | * loose with the abstraction for us in NetBSD. | | 102 | * loose with the abstraction for us in NetBSD. |
103 | */ | | 103 | */ |
104 | | | 104 | |
105 | static int | | 105 | static int |
106 | zfs_dirlock_hold(zfs_dirlock_t *dl, znode_t *dzp) | | 106 | zfs_dirlock_hold(zfs_dirlock_t *dl) |
107 | { | | 107 | { |
108 | | | 108 | |
109 | (void)dzp; /* ignore */ | | 109 | KASSERT(mutex_owned(&dl->dl_dzp->z_lock)); |
110 | KASSERT(mutex_owned(&dzp->z_lock)); | | | |
111 | | | 110 | |
112 | if (dl->dl_refcnt >= ULONG_MAX) /* XXX Name this constant. */ | | 111 | if (dl->dl_refcnt >= ULONG_MAX) /* XXX Name this constant. */ |
113 | return (ENFILE); /* XXX What to do? */ | | 112 | return (ENFILE); /* XXX What to do? */ |
114 | | | 113 | |
115 | dl->dl_refcnt++; | | 114 | dl->dl_refcnt++; |
116 | return (0); | | 115 | return (0); |
117 | } | | 116 | } |
118 | | | 117 | |
119 | static void | | 118 | static void |
120 | zfs_dirlock_rele(zfs_dirlock_t *dl, znode_t *dzp) | | 119 | zfs_dirlock_rele(zfs_dirlock_t *dl) |
121 | { | | 120 | { |
122 | | | 121 | |
123 | (void)dzp; /* ignore */ | | 122 | KASSERT(mutex_owned(&dl->dl_dzp->z_lock)); |
124 | KASSERT(mutex_owned(&dzp->z_lock)); | | | |
125 | KASSERT(dl->dl_refcnt > 0); | | 123 | KASSERT(dl->dl_refcnt > 0); |
126 | | | 124 | |
127 | if (--dl->dl_refcnt == 0) { | | 125 | if (--dl->dl_refcnt == 0) { |
128 | if (dl->dl_namesize != 0) | | 126 | if (dl->dl_namesize != 0) |
129 | kmem_free(dl->dl_name, dl->dl_namesize); | | 127 | kmem_free(dl->dl_name, dl->dl_namesize); |
130 | cv_destroy(&dl->dl_cv); | | 128 | cv_destroy(&dl->dl_cv); |
131 | kmem_free(dl, sizeof(*dl)); | | 129 | kmem_free(dl, sizeof(*dl)); |
132 | } | | 130 | } |
133 | } | | 131 | } |
134 | | | 132 | |
135 | /* | | 133 | /* |
136 | * Lock a directory entry. A dirlock on <dzp, name> protects that name | | 134 | * Lock a directory entry. A dirlock on <dzp, name> protects that name |
137 | * in dzp's directory zap object. As long as you hold a dirlock, you can | | 135 | * in dzp's directory zap object. As long as you hold a dirlock, you can |
| @@ -281,35 +279,35 @@ zfs_dirent_lock(zfs_dirlock_t **dlpp, zn | | | @@ -281,35 +279,35 @@ zfs_dirent_lock(zfs_dirlock_t **dlpp, zn |
281 | cv_init(&dl->dl_cv, NULL, CV_DEFAULT, NULL); | | 279 | cv_init(&dl->dl_cv, NULL, CV_DEFAULT, NULL); |
282 | dl->dl_name = name; | | 280 | dl->dl_name = name; |
283 | dl->dl_sharecnt = 0; | | 281 | dl->dl_sharecnt = 0; |
284 | dl->dl_namelock = 0; | | 282 | dl->dl_namelock = 0; |
285 | dl->dl_namesize = 0; | | 283 | dl->dl_namesize = 0; |
286 | dl->dl_refcnt = 1; | | 284 | dl->dl_refcnt = 1; |
287 | dl->dl_dzp = dzp; | | 285 | dl->dl_dzp = dzp; |
288 | dl->dl_next = dzp->z_dirlocks; | | 286 | dl->dl_next = dzp->z_dirlocks; |
289 | dzp->z_dirlocks = dl; | | 287 | dzp->z_dirlocks = dl; |
290 | break; | | 288 | break; |
291 | } | | 289 | } |
292 | if ((flag & ZSHARED) && dl->dl_sharecnt != 0) | | 290 | if ((flag & ZSHARED) && dl->dl_sharecnt != 0) |
293 | break; | | 291 | break; |
294 | error = zfs_dirlock_hold(dl, dzp); | | 292 | error = zfs_dirlock_hold(dl); |
295 | if (error) { | | 293 | if (error) { |
296 | mutex_exit(&dzp->z_lock); | | 294 | mutex_exit(&dzp->z_lock); |
297 | if (!(flag & ZHAVELOCK)) | | 295 | if (!(flag & ZHAVELOCK)) |
298 | rw_exit(&dzp->z_name_lock); | | 296 | rw_exit(&dzp->z_name_lock); |
299 | return (error); | | 297 | return (error); |
300 | } | | 298 | } |
301 | cv_wait(&dl->dl_cv, &dzp->z_lock); | | 299 | cv_wait(&dl->dl_cv, &dzp->z_lock); |
302 | zfs_dirlock_rele(dl, dzp); | | 300 | zfs_dirlock_rele(dl); |
303 | } | | 301 | } |
304 | | | 302 | |
305 | /* | | 303 | /* |
306 | * If the z_name_lock was NOT held for this dirlock record it. | | 304 | * If the z_name_lock was NOT held for this dirlock record it. |
307 | */ | | 305 | */ |
308 | if (flag & ZHAVELOCK) | | 306 | if (flag & ZHAVELOCK) |
309 | dl->dl_namelock = 1; | | 307 | dl->dl_namelock = 1; |
310 | | | 308 | |
311 | if ((flag & ZSHARED) && ++dl->dl_sharecnt > 1 && dl->dl_namesize == 0) { | | 309 | if ((flag & ZSHARED) && ++dl->dl_sharecnt > 1 && dl->dl_namesize == 0) { |
312 | /* | | 310 | /* |
313 | * We're the second shared reference to dl. Make a copy of | | 311 | * We're the second shared reference to dl. Make a copy of |
314 | * dl_name in case the first thread goes away before we do. | | 312 | * dl_name in case the first thread goes away before we do. |
315 | * Note that we initialize the new name before storing its | | 313 | * Note that we initialize the new name before storing its |
| @@ -391,27 +389,27 @@ zfs_dirent_unlock(zfs_dirlock_t *dl) | | | @@ -391,27 +389,27 @@ zfs_dirent_unlock(zfs_dirlock_t *dl) |
391 | if (!dl->dl_namelock) | | 389 | if (!dl->dl_namelock) |
392 | rw_exit(&dzp->z_name_lock); | | 390 | rw_exit(&dzp->z_name_lock); |
393 | | | 391 | |
394 | if (dl->dl_sharecnt > 1) { | | 392 | if (dl->dl_sharecnt > 1) { |
395 | dl->dl_sharecnt--; | | 393 | dl->dl_sharecnt--; |
396 | mutex_exit(&dzp->z_lock); | | 394 | mutex_exit(&dzp->z_lock); |
397 | return; | | 395 | return; |
398 | } | | 396 | } |
399 | prev_dl = &dzp->z_dirlocks; | | 397 | prev_dl = &dzp->z_dirlocks; |
400 | while ((cur_dl = *prev_dl) != dl) | | 398 | while ((cur_dl = *prev_dl) != dl) |
401 | prev_dl = &cur_dl->dl_next; | | 399 | prev_dl = &cur_dl->dl_next; |
402 | *prev_dl = dl->dl_next; | | 400 | *prev_dl = dl->dl_next; |
403 | cv_broadcast(&dl->dl_cv); | | 401 | cv_broadcast(&dl->dl_cv); |
404 | zfs_dirlock_rele(dl, dzp); | | 402 | zfs_dirlock_rele(dl); |
405 | mutex_exit(&dzp->z_lock); | | 403 | mutex_exit(&dzp->z_lock); |
406 | } | | 404 | } |
407 | | | 405 | |
408 | /* | | 406 | /* |
409 | * Look up an entry in a directory. | | 407 | * Look up an entry in a directory. |
410 | * | | 408 | * |
411 | * NOTE: '.' and '..' are handled as special cases because | | 409 | * NOTE: '.' and '..' are handled as special cases because |
412 | * no directory entries are actually stored for them. If this is | | 410 | * no directory entries are actually stored for them. If this is |
413 | * the root of a filesystem, then '.zfs' is also treated as a | | 411 | * the root of a filesystem, then '.zfs' is also treated as a |
414 | * special pseudo-directory. | | 412 | * special pseudo-directory. |
415 | */ | | 413 | */ |
416 | int | | 414 | int |
417 | zfs_dirlook(znode_t *dzp, char *name, vnode_t **vpp, int flags, | | 415 | zfs_dirlook(znode_t *dzp, char *name, vnode_t **vpp, int flags, |
| @@ -786,27 +784,31 @@ zfs_link_destroy(zfs_dirlock_t *dl, znod | | | @@ -786,27 +784,31 @@ zfs_link_destroy(zfs_dirlock_t *dl, znod |
786 | | | 784 | |
787 | if (vn_vfswlock(vp)) /* prevent new mounts on zp */ | | 785 | if (vn_vfswlock(vp)) /* prevent new mounts on zp */ |
788 | return (EBUSY); | | 786 | return (EBUSY); |
789 | | | 787 | |
790 | if (vn_ismntpt(vp)) { /* don't remove mount point */ | | 788 | if (vn_ismntpt(vp)) { /* don't remove mount point */ |
791 | vn_vfsunlock(vp); | | 789 | vn_vfsunlock(vp); |
792 | return (EBUSY); | | 790 | return (EBUSY); |
793 | } | | 791 | } |
794 | | | 792 | |
795 | mutex_enter(&zp->z_lock); | | 793 | mutex_enter(&zp->z_lock); |
796 | if (zp_is_dir && !zfs_dirempty(zp)) { /* dir not empty */ | | 794 | if (zp_is_dir && !zfs_dirempty(zp)) { /* dir not empty */ |
797 | mutex_exit(&zp->z_lock); | | 795 | mutex_exit(&zp->z_lock); |
798 | vn_vfsunlock(vp); | | 796 | vn_vfsunlock(vp); |
| | | 797 | #ifdef __NetBSD__ /* XXX Make our dumb tests happier... */ |
| | | 798 | return (ENOTEMPTY); |
| | | 799 | #else |
799 | return (EEXIST); | | 800 | return (EEXIST); |
| | | 801 | #endif |
800 | } | | 802 | } |
801 | if (zp->z_phys->zp_links <= zp_is_dir) { | | 803 | if (zp->z_phys->zp_links <= zp_is_dir) { |
802 | zfs_panic_recover("zfs: link count on vnode %p is %u, " | | 804 | zfs_panic_recover("zfs: link count on vnode %p is %u, " |
803 | "should be at least %u", | | 805 | "should be at least %u", |
804 | zp->z_vnode, (int)zp->z_phys->zp_links, | | 806 | zp->z_vnode, (int)zp->z_phys->zp_links, |
805 | zp_is_dir + 1); | | 807 | zp_is_dir + 1); |
806 | zp->z_phys->zp_links = zp_is_dir + 1; | | 808 | zp->z_phys->zp_links = zp_is_dir + 1; |
807 | } | | 809 | } |
808 | if (--zp->z_phys->zp_links == zp_is_dir) { | | 810 | if (--zp->z_phys->zp_links == zp_is_dir) { |
809 | zp->z_unlinked = B_TRUE; | | 811 | zp->z_unlinked = B_TRUE; |
810 | zp->z_phys->zp_links = 0; | | 812 | zp->z_phys->zp_links = 0; |
811 | unlinked = B_TRUE; | | 813 | unlinked = B_TRUE; |
812 | } else { | | 814 | } else { |