Lines 75-95
Link Here
|
75 |
KASSERT(((vp)->v_op == &unionfs_vnodeops), \ |
75 |
KASSERT(((vp)->v_op == &unionfs_vnodeops), \ |
76 |
("unionfs: it is not unionfs-vnode")) |
76 |
("unionfs: it is not unionfs-vnode")) |
77 |
|
77 |
|
78 |
/* lockmgr lock <-> reverse table */ |
|
|
79 |
struct lk_lr_table { |
80 |
int lock; |
81 |
int revlock; |
82 |
}; |
83 |
|
84 |
static struct lk_lr_table un_llt[] = { |
85 |
{LK_SHARED, LK_RELEASE}, |
86 |
{LK_EXCLUSIVE, LK_RELEASE}, |
87 |
{LK_UPGRADE, LK_DOWNGRADE}, |
88 |
{LK_DOWNGRADE, LK_UPGRADE}, |
89 |
{0, 0} |
90 |
}; |
91 |
|
92 |
|
93 |
static int |
78 |
static int |
94 |
unionfs_lookup(struct vop_cachedlookup_args *ap) |
79 |
unionfs_lookup(struct vop_cachedlookup_args *ap) |
95 |
{ |
80 |
{ |
Lines 141-147
Link Here
|
141 |
if (udvp != NULLVP) { |
126 |
if (udvp != NULLVP) { |
142 |
dtmpvp = udvp; |
127 |
dtmpvp = udvp; |
143 |
if (ldvp != NULLVP) |
128 |
if (ldvp != NULLVP) |
144 |
VOP_UNLOCK(ldvp, 0); |
129 |
VOP_UNLOCK(ldvp, LK_RELEASE); |
145 |
} |
130 |
} |
146 |
else |
131 |
else |
147 |
dtmpvp = ldvp; |
132 |
dtmpvp = ldvp; |
Lines 149-155
Link Here
|
149 |
error = VOP_LOOKUP(dtmpvp, &vp, cnp); |
134 |
error = VOP_LOOKUP(dtmpvp, &vp, cnp); |
150 |
|
135 |
|
151 |
if (dtmpvp == udvp && ldvp != NULLVP) { |
136 |
if (dtmpvp == udvp && ldvp != NULLVP) { |
152 |
VOP_UNLOCK(udvp, 0); |
137 |
VOP_UNLOCK(udvp, LK_RELEASE); |
153 |
vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); |
138 |
vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); |
154 |
} |
139 |
} |
155 |
|
140 |
|
Lines 161-170
Link Here
|
161 |
*/ |
146 |
*/ |
162 |
if (nameiop == DELETE || nameiop == RENAME || |
147 |
if (nameiop == DELETE || nameiop == RENAME || |
163 |
(cnp->cn_lkflags & LK_TYPE_MASK)) |
148 |
(cnp->cn_lkflags & LK_TYPE_MASK)) |
164 |
VOP_UNLOCK(vp, 0); |
149 |
VOP_UNLOCK(vp, LK_RELEASE); |
165 |
vrele(vp); |
150 |
vrele(vp); |
166 |
|
151 |
|
167 |
VOP_UNLOCK(dvp, 0); |
152 |
VOP_UNLOCK(dvp, LK_RELEASE); |
168 |
*(ap->a_vpp) = dunp->un_dvp; |
153 |
*(ap->a_vpp) = dunp->un_dvp; |
169 |
vref(dunp->un_dvp); |
154 |
vref(dunp->un_dvp); |
170 |
|
155 |
|
Lines 202-208
Link Here
|
202 |
} |
187 |
} |
203 |
if (nameiop == DELETE || nameiop == RENAME || |
188 |
if (nameiop == DELETE || nameiop == RENAME || |
204 |
(cnp->cn_lkflags & LK_TYPE_MASK)) |
189 |
(cnp->cn_lkflags & LK_TYPE_MASK)) |
205 |
VOP_UNLOCK(uvp, 0); |
190 |
VOP_UNLOCK(uvp, LK_RELEASE); |
206 |
} |
191 |
} |
207 |
|
192 |
|
208 |
/* check whiteout */ |
193 |
/* check whiteout */ |
Lines 246-252
Link Here
|
246 |
return (lerror); |
231 |
return (lerror); |
247 |
} |
232 |
} |
248 |
if (cnp->cn_lkflags & LK_TYPE_MASK) |
233 |
if (cnp->cn_lkflags & LK_TYPE_MASK) |
249 |
VOP_UNLOCK(lvp, 0); |
234 |
VOP_UNLOCK(lvp, LK_RELEASE); |
250 |
} |
235 |
} |
251 |
} |
236 |
} |
252 |
|
237 |
|
Lines 281-287
Link Here
|
281 |
goto unionfs_lookup_out; |
266 |
goto unionfs_lookup_out; |
282 |
|
267 |
|
283 |
if (LK_SHARED == (cnp->cn_lkflags & LK_TYPE_MASK)) |
268 |
if (LK_SHARED == (cnp->cn_lkflags & LK_TYPE_MASK)) |
284 |
VOP_UNLOCK(vp, 0); |
269 |
VOP_UNLOCK(vp, LK_RELEASE); |
285 |
if (LK_EXCLUSIVE != VOP_ISLOCKED(vp)) { |
270 |
if (LK_EXCLUSIVE != VOP_ISLOCKED(vp)) { |
286 |
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); |
271 |
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); |
287 |
lockflag = 1; |
272 |
lockflag = 1; |
Lines 289-295
Link Here
|
289 |
error = unionfs_mkshadowdir(MOUNTTOUNIONFSMOUNT(dvp->v_mount), |
274 |
error = unionfs_mkshadowdir(MOUNTTOUNIONFSMOUNT(dvp->v_mount), |
290 |
udvp, VTOUNIONFS(vp), cnp, td); |
275 |
udvp, VTOUNIONFS(vp), cnp, td); |
291 |
if (lockflag != 0) |
276 |
if (lockflag != 0) |
292 |
VOP_UNLOCK(vp, 0); |
277 |
VOP_UNLOCK(vp, LK_RELEASE); |
293 |
if (error != 0) { |
278 |
if (error != 0) { |
294 |
UNIONFSDEBUG("unionfs_lookup: Unable to create shadow dir."); |
279 |
UNIONFSDEBUG("unionfs_lookup: Unable to create shadow dir."); |
295 |
if ((cnp->cn_lkflags & LK_TYPE_MASK) == LK_EXCLUSIVE) |
280 |
if ((cnp->cn_lkflags & LK_TYPE_MASK) == LK_EXCLUSIVE) |
Lines 386-392
Link Here
|
386 |
if (vp->v_type == VSOCK) |
371 |
if (vp->v_type == VSOCK) |
387 |
*(ap->a_vpp) = vp; |
372 |
*(ap->a_vpp) = vp; |
388 |
else { |
373 |
else { |
389 |
VOP_UNLOCK(vp, 0); |
374 |
VOP_UNLOCK(vp, LK_RELEASE); |
390 |
error = unionfs_nodeget(ap->a_dvp->v_mount, vp, NULLVP, |
375 |
error = unionfs_nodeget(ap->a_dvp->v_mount, vp, NULLVP, |
391 |
ap->a_dvp, ap->a_vpp, cnp, curthread); |
376 |
ap->a_dvp, ap->a_vpp, cnp, curthread); |
392 |
vrele(vp); |
377 |
vrele(vp); |
Lines 460-466
Link Here
|
460 |
if (vp->v_type == VSOCK) |
445 |
if (vp->v_type == VSOCK) |
461 |
*(ap->a_vpp) = vp; |
446 |
*(ap->a_vpp) = vp; |
462 |
else { |
447 |
else { |
463 |
VOP_UNLOCK(vp, 0); |
448 |
VOP_UNLOCK(vp, LK_RELEASE); |
464 |
error = unionfs_nodeget(ap->a_dvp->v_mount, vp, NULLVP, |
449 |
error = unionfs_nodeget(ap->a_dvp->v_mount, vp, NULLVP, |
465 |
ap->a_dvp, ap->a_vpp, cnp, curthread); |
450 |
ap->a_dvp, ap->a_vpp, cnp, curthread); |
466 |
vrele(vp); |
451 |
vrele(vp); |
Lines 619-625
Link Here
|
619 |
unionfs_tryrem_node_status(unp, unsp); |
604 |
unionfs_tryrem_node_status(unp, unsp); |
620 |
|
605 |
|
621 |
if (locked != 0) |
606 |
if (locked != 0) |
622 |
VOP_UNLOCK(ap->a_vp, 0); |
607 |
VOP_UNLOCK(ap->a_vp, LK_RELEASE); |
623 |
|
608 |
|
624 |
UNIONFS_INTERNAL_DEBUG("unionfs_close: leave (%d)\n", error); |
609 |
UNIONFS_INTERNAL_DEBUG("unionfs_close: leave (%d)\n", error); |
625 |
|
610 |
|
Lines 914-920
Link Here
|
914 |
unionfs_get_node_status(unp, ap->a_td, &unsp); |
899 |
unionfs_get_node_status(unp, ap->a_td, &unsp); |
915 |
ovp = (unsp->uns_upper_opencnt ? unp->un_uppervp : unp->un_lowervp); |
900 |
ovp = (unsp->uns_upper_opencnt ? unp->un_uppervp : unp->un_lowervp); |
916 |
unionfs_tryrem_node_status(unp, unsp); |
901 |
unionfs_tryrem_node_status(unp, unsp); |
917 |
VOP_UNLOCK(ap->a_vp, 0); |
902 |
VOP_UNLOCK(ap->a_vp, LK_RELEASE); |
918 |
|
903 |
|
919 |
if (ovp == NULLVP) |
904 |
if (ovp == NULLVP) |
920 |
return (EBADF); |
905 |
return (EBADF); |
Lines 941-947
Link Here
|
941 |
unionfs_get_node_status(unp, ap->a_td, &unsp); |
926 |
unionfs_get_node_status(unp, ap->a_td, &unsp); |
942 |
ovp = (unsp->uns_upper_opencnt ? unp->un_uppervp : unp->un_lowervp); |
927 |
ovp = (unsp->uns_upper_opencnt ? unp->un_uppervp : unp->un_lowervp); |
943 |
unionfs_tryrem_node_status(unp, unsp); |
928 |
unionfs_tryrem_node_status(unp, unsp); |
944 |
VOP_UNLOCK(ap->a_vp, 0); |
929 |
VOP_UNLOCK(ap->a_vp, LK_RELEASE); |
945 |
|
930 |
|
946 |
if (ovp == NULLVP) |
931 |
if (ovp == NULLVP) |
947 |
return (EBADF); |
932 |
return (EBADF); |
Lines 1001-1007
Link Here
|
1001 |
ump = NULL; |
986 |
ump = NULL; |
1002 |
vp = uvp = lvp = NULLVP; |
987 |
vp = uvp = lvp = NULLVP; |
1003 |
/* search vnode */ |
988 |
/* search vnode */ |
1004 |
VOP_UNLOCK(ap->a_vp, 0); |
989 |
VOP_UNLOCK(ap->a_vp, LK_RELEASE); |
1005 |
error = unionfs_relookup(udvp, &vp, cnp, &cn, td, |
990 |
error = unionfs_relookup(udvp, &vp, cnp, &cn, td, |
1006 |
cnp->cn_nameptr, strlen(cnp->cn_nameptr), DELETE); |
991 |
cnp->cn_nameptr, strlen(cnp->cn_nameptr), DELETE); |
1007 |
if (error != 0 && error != ENOENT) { |
992 |
if (error != 0 && error != ENOENT) { |
Lines 1204-1210
Link Here
|
1204 |
if ((error = vn_lock(fvp, LK_EXCLUSIVE)) != 0) |
1189 |
if ((error = vn_lock(fvp, LK_EXCLUSIVE)) != 0) |
1205 |
goto unionfs_rename_abort; |
1190 |
goto unionfs_rename_abort; |
1206 |
error = unionfs_copyfile(unp, 1, fcnp->cn_cred, td); |
1191 |
error = unionfs_copyfile(unp, 1, fcnp->cn_cred, td); |
1207 |
VOP_UNLOCK(fvp, 0); |
1192 |
VOP_UNLOCK(fvp, LK_RELEASE); |
1208 |
if (error != 0) |
1193 |
if (error != 0) |
1209 |
goto unionfs_rename_abort; |
1194 |
goto unionfs_rename_abort; |
1210 |
break; |
1195 |
break; |
Lines 1212-1218
Link Here
|
1212 |
if ((error = vn_lock(fvp, LK_EXCLUSIVE)) != 0) |
1197 |
if ((error = vn_lock(fvp, LK_EXCLUSIVE)) != 0) |
1213 |
goto unionfs_rename_abort; |
1198 |
goto unionfs_rename_abort; |
1214 |
error = unionfs_mkshadowdir(ump, rfdvp, unp, fcnp, td); |
1199 |
error = unionfs_mkshadowdir(ump, rfdvp, unp, fcnp, td); |
1215 |
VOP_UNLOCK(fvp, 0); |
1200 |
VOP_UNLOCK(fvp, LK_RELEASE); |
1216 |
if (error != 0) |
1201 |
if (error != 0) |
1217 |
goto unionfs_rename_abort; |
1202 |
goto unionfs_rename_abort; |
1218 |
break; |
1203 |
break; |
Lines 1269-1281
Link Here
|
1269 |
if ((error = vn_lock(fdvp, LK_EXCLUSIVE)) != 0) |
1254 |
if ((error = vn_lock(fdvp, LK_EXCLUSIVE)) != 0) |
1270 |
goto unionfs_rename_abort; |
1255 |
goto unionfs_rename_abort; |
1271 |
error = unionfs_relookup_for_delete(fdvp, fcnp, td); |
1256 |
error = unionfs_relookup_for_delete(fdvp, fcnp, td); |
1272 |
VOP_UNLOCK(fdvp, 0); |
1257 |
VOP_UNLOCK(fdvp, LK_RELEASE); |
1273 |
if (error != 0) |
1258 |
if (error != 0) |
1274 |
goto unionfs_rename_abort; |
1259 |
goto unionfs_rename_abort; |
1275 |
|
1260 |
|
1276 |
/* Locke of tvp is canceled in order to avoid recursive lock. */ |
1261 |
/* Locke of tvp is canceled in order to avoid recursive lock. */ |
1277 |
if (tvp != NULLVP && tvp != tdvp) |
1262 |
if (tvp != NULLVP && tvp != tdvp) |
1278 |
VOP_UNLOCK(tvp, 0); |
1263 |
VOP_UNLOCK(tvp, LK_RELEASE); |
1279 |
error = unionfs_relookup_for_rename(tdvp, tcnp, td); |
1264 |
error = unionfs_relookup_for_rename(tdvp, tcnp, td); |
1280 |
if (tvp != NULLVP && tvp != tdvp) |
1265 |
if (tvp != NULLVP && tvp != tdvp) |
1281 |
vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY); |
1266 |
vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY); |
Lines 1293-1303
Link Here
|
1293 |
} |
1278 |
} |
1294 |
|
1279 |
|
1295 |
if (ltdvp != NULLVP) |
1280 |
if (ltdvp != NULLVP) |
1296 |
VOP_UNLOCK(ltdvp, 0); |
1281 |
VOP_UNLOCK(ltdvp, LK_RELEASE); |
1297 |
if (tdvp != rtdvp) |
1282 |
if (tdvp != rtdvp) |
1298 |
vrele(tdvp); |
1283 |
vrele(tdvp); |
1299 |
if (ltvp != NULLVP) |
1284 |
if (ltvp != NULLVP) |
1300 |
VOP_UNLOCK(ltvp, 0); |
1285 |
VOP_UNLOCK(ltvp, LK_RELEASE); |
1301 |
if (tvp != rtvp && tvp != NULLVP) { |
1286 |
if (tvp != rtvp && tvp != NULLVP) { |
1302 |
if (rtvp == NULLVP) |
1287 |
if (rtvp == NULLVP) |
1303 |
vput(tvp); |
1288 |
vput(tvp); |
Lines 1371-1377
Link Here
|
1371 |
} |
1356 |
} |
1372 |
|
1357 |
|
1373 |
if ((error = VOP_MKDIR(udvp, &uvp, cnp, ap->a_vap)) == 0) { |
1358 |
if ((error = VOP_MKDIR(udvp, &uvp, cnp, ap->a_vap)) == 0) { |
1374 |
VOP_UNLOCK(uvp, 0); |
1359 |
VOP_UNLOCK(uvp, LK_RELEASE); |
1375 |
cnp->cn_lkflags = LK_EXCLUSIVE; |
1360 |
cnp->cn_lkflags = LK_EXCLUSIVE; |
1376 |
error = unionfs_nodeget(ap->a_dvp->v_mount, uvp, NULLVP, |
1361 |
error = unionfs_nodeget(ap->a_dvp->v_mount, uvp, NULLVP, |
1377 |
ap->a_dvp, ap->a_vpp, cnp, td); |
1362 |
ap->a_dvp, ap->a_vpp, cnp, td); |
Lines 1467-1473
Link Here
|
1467 |
if (udvp != NULLVP) { |
1452 |
if (udvp != NULLVP) { |
1468 |
error = VOP_SYMLINK(udvp, &uvp, cnp, ap->a_vap, ap->a_target); |
1453 |
error = VOP_SYMLINK(udvp, &uvp, cnp, ap->a_vap, ap->a_target); |
1469 |
if (error == 0) { |
1454 |
if (error == 0) { |
1470 |
VOP_UNLOCK(uvp, 0); |
1455 |
VOP_UNLOCK(uvp, LK_RELEASE); |
1471 |
cnp->cn_lkflags = LK_EXCLUSIVE; |
1456 |
cnp->cn_lkflags = LK_EXCLUSIVE; |
1472 |
error = unionfs_nodeget(ap->a_dvp->v_mount, uvp, NULLVP, |
1457 |
error = unionfs_nodeget(ap->a_dvp->v_mount, uvp, NULLVP, |
1473 |
ap->a_dvp, ap->a_vpp, cnp, td); |
1458 |
ap->a_dvp, ap->a_vpp, cnp, td); |
Lines 1490-1495
Link Here
|
1490 |
struct unionfs_node *unp; |
1475 |
struct unionfs_node *unp; |
1491 |
struct unionfs_node_status *unsp; |
1476 |
struct unionfs_node_status *unsp; |
1492 |
struct uio *uio; |
1477 |
struct uio *uio; |
|
|
1478 |
struct vnode *vp; |
1493 |
struct vnode *uvp; |
1479 |
struct vnode *uvp; |
1494 |
struct vnode *lvp; |
1480 |
struct vnode *lvp; |
1495 |
struct thread *td; |
1481 |
struct thread *td; |
Lines 1505-1545
Link Here
|
1505 |
error = 0; |
1491 |
error = 0; |
1506 |
eofflag = 0; |
1492 |
eofflag = 0; |
1507 |
locked = 0; |
1493 |
locked = 0; |
1508 |
unp = VTOUNIONFS(ap->a_vp); |
|
|
1509 |
uio = ap->a_uio; |
1494 |
uio = ap->a_uio; |
1510 |
uvp = unp->un_uppervp; |
1495 |
uvp = NULLVP; |
1511 |
lvp = unp->un_lowervp; |
1496 |
lvp = NULLVP; |
1512 |
td = uio->uio_td; |
1497 |
td = uio->uio_td; |
1513 |
ncookies_bk = 0; |
1498 |
ncookies_bk = 0; |
1514 |
cookies_bk = NULL; |
1499 |
cookies_bk = NULL; |
1515 |
|
1500 |
|
1516 |
if (ap->a_vp->v_type != VDIR) |
1501 |
vp = ap->a_vp; |
|
|
1502 |
if (vp->v_type != VDIR) |
1517 |
return (ENOTDIR); |
1503 |
return (ENOTDIR); |
1518 |
|
1504 |
|
1519 |
/* check opaque */ |
|
|
1520 |
if (uvp != NULLVP && lvp != NULLVP) { |
1521 |
if ((error = VOP_GETATTR(uvp, &va, ap->a_cred)) != 0) |
1522 |
goto unionfs_readdir_exit; |
1523 |
if (va.va_flags & OPAQUE) |
1524 |
lvp = NULLVP; |
1525 |
} |
1526 |
|
1527 |
/* check the open count. unionfs needs to open before readdir. */ |
1505 |
/* check the open count. unionfs needs to open before readdir. */ |
1528 |
if (VOP_ISLOCKED(ap->a_vp) != LK_EXCLUSIVE) { |
1506 |
if (VOP_ISLOCKED(vp) != LK_EXCLUSIVE) { |
1529 |
vn_lock(ap->a_vp, LK_UPGRADE | LK_RETRY); |
1507 |
if (vn_lock(vp, LK_UPGRADE) != 0) |
|
|
1508 |
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); |
1530 |
locked = 1; |
1509 |
locked = 1; |
1531 |
} |
1510 |
} |
1532 |
unionfs_get_node_status(unp, td, &unsp); |
1511 |
unp = VTOUNIONFS(vp); |
1533 |
if ((uvp != NULLVP && unsp->uns_upper_opencnt <= 0) || |
1512 |
if (unp == NULL) |
1534 |
(lvp != NULLVP && unsp->uns_lower_opencnt <= 0)) { |
|
|
1535 |
unionfs_tryrem_node_status(unp, unsp); |
1536 |
error = EBADF; |
1513 |
error = EBADF; |
|
|
1514 |
else { |
1515 |
uvp = unp->un_uppervp; |
1516 |
lvp = unp->un_lowervp; |
1517 |
unionfs_get_node_status(unp, td, &unsp); |
1518 |
if ((uvp != NULLVP && unsp->uns_upper_opencnt <= 0) || |
1519 |
(lvp != NULLVP && unsp->uns_lower_opencnt <= 0)) { |
1520 |
unionfs_tryrem_node_status(unp, unsp); |
1521 |
error = EBADF; |
1522 |
} |
1537 |
} |
1523 |
} |
1538 |
if (locked == 1) |
1524 |
if (locked) |
1539 |
vn_lock(ap->a_vp, LK_DOWNGRADE | LK_RETRY); |
1525 |
vn_lock(vp, LK_DOWNGRADE | LK_RETRY); |
1540 |
if (error != 0) |
1526 |
if (error != 0) |
1541 |
goto unionfs_readdir_exit; |
1527 |
goto unionfs_readdir_exit; |
1542 |
|
1528 |
|
|
|
1529 |
/* check opaque */ |
1530 |
if (uvp != NULLVP && lvp != NULLVP) { |
1531 |
if ((error = VOP_GETATTR(uvp, &va, ap->a_cred)) != 0) |
1532 |
goto unionfs_readdir_exit; |
1533 |
if (va.va_flags & OPAQUE) |
1534 |
lvp = NULLVP; |
1535 |
} |
1536 |
|
1543 |
/* upper only */ |
1537 |
/* upper only */ |
1544 |
if (uvp != NULLVP && lvp == NULLVP) { |
1538 |
if (uvp != NULLVP && lvp == NULLVP) { |
1545 |
error = VOP_READDIR(uvp, uio, ap->a_cred, ap->a_eofflag, |
1539 |
error = VOP_READDIR(uvp, uio, ap->a_cred, ap->a_eofflag, |
Lines 1743-1760
Link Here
|
1743 |
} |
1737 |
} |
1744 |
|
1738 |
|
1745 |
static int |
1739 |
static int |
1746 |
unionfs_get_llt_revlock(int flags) |
1740 |
unionfs_islocked(struct vop_islocked_args *ap) |
1747 |
{ |
1741 |
{ |
1748 |
int count; |
1742 |
struct unionfs_node *unp; |
1749 |
|
1743 |
|
1750 |
flags &= LK_TYPE_MASK; |
1744 |
KASSERT_UNIONFS_VNODE(ap->a_vp); |
1751 |
for (count = 0; un_llt[count].lock != 0; count++) { |
1745 |
|
1752 |
if (flags == un_llt[count].lock) { |
1746 |
unp = VTOUNIONFS(ap->a_vp); |
1753 |
return un_llt[count].revlock; |
1747 |
if (unp == NULL) |
1754 |
} |
1748 |
return (vop_stdislocked(ap)); |
|
|
1749 |
|
1750 |
if (unp->un_uppervp != NULLVP) |
1751 |
return (VOP_ISLOCKED(unp->un_uppervp)); |
1752 |
if (unp->un_lowervp != NULLVP) |
1753 |
return (VOP_ISLOCKED(unp->un_lowervp)); |
1754 |
return (vop_stdislocked(ap)); |
1755 |
} |
1756 |
|
1757 |
static int |
1758 |
unionfs_get_llt_revlock(struct vnode *vp, int flags) |
1759 |
{ |
1760 |
int revlock; |
1761 |
|
1762 |
revlock = 0; |
1763 |
|
1764 |
switch (flags & LK_TYPE_MASK) { |
1765 |
case LK_SHARED: |
1766 |
if (VOP_ISLOCKED(vp) == LK_EXCLUSIVE) |
1767 |
revlock = LK_UPGRADE; |
1768 |
else |
1769 |
revlock = LK_RELEASE; |
1770 |
break; |
1771 |
case LK_EXCLUSIVE: |
1772 |
case LK_UPGRADE: |
1773 |
revlock = LK_RELEASE; |
1774 |
break; |
1775 |
case LK_DOWNGRADE: |
1776 |
revlock = LK_UPGRADE; |
1777 |
break; |
1778 |
default: |
1779 |
break; |
1755 |
} |
1780 |
} |
1756 |
|
1781 |
|
1757 |
return 0; |
1782 |
return (revlock); |
|
|
1783 |
} |
1784 |
|
1785 |
/* |
1786 |
* The state of an acquired lock is adjusted similarly to |
1787 |
* the time of error generating. |
1788 |
* flags: LK_RELEASE or LK_UPGRADE |
1789 |
*/ |
1790 |
static void |
1791 |
unionfs_revlock(struct vnode *vp, int flags) |
1792 |
{ |
1793 |
if (flags & LK_RELEASE) |
1794 |
VOP_UNLOCK(vp, flags); |
1795 |
else { |
1796 |
/* UPGRADE */ |
1797 |
if (vn_lock(vp, flags) != 0) |
1798 |
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); |
1799 |
} |
1758 |
} |
1800 |
} |
1759 |
|
1801 |
|
1760 |
static int |
1802 |
static int |
Lines 1763-1768
Link Here
|
1763 |
int error; |
1805 |
int error; |
1764 |
int flags; |
1806 |
int flags; |
1765 |
int revlock; |
1807 |
int revlock; |
|
|
1808 |
int interlock; |
1766 |
int uhold; |
1809 |
int uhold; |
1767 |
struct mount *mp; |
1810 |
struct mount *mp; |
1768 |
struct unionfs_mount *ump; |
1811 |
struct unionfs_mount *ump; |
Lines 1774-1788
Link Here
|
1774 |
KASSERT_UNIONFS_VNODE(ap->a_vp); |
1817 |
KASSERT_UNIONFS_VNODE(ap->a_vp); |
1775 |
|
1818 |
|
1776 |
error = 0; |
1819 |
error = 0; |
|
|
1820 |
interlock = 1; |
1777 |
uhold = 0; |
1821 |
uhold = 0; |
1778 |
flags = ap->a_flags; |
1822 |
flags = ap->a_flags; |
1779 |
vp = ap->a_vp; |
1823 |
vp = ap->a_vp; |
1780 |
|
1824 |
|
1781 |
if (LK_RELEASE == (flags & LK_TYPE_MASK) || !(flags & LK_TYPE_MASK)) |
1825 |
if (LK_RELEASE == (flags & LK_TYPE_MASK) || !(flags & LK_TYPE_MASK)) |
1782 |
return (VOP_UNLOCK(vp, flags)); |
1826 |
return (VOP_UNLOCK(vp, flags | LK_RELEASE)); |
1783 |
|
|
|
1784 |
if ((revlock = unionfs_get_llt_revlock(flags)) == 0) |
1785 |
panic("unknown lock type: 0x%x", flags & LK_TYPE_MASK); |
1786 |
|
1827 |
|
1787 |
if ((flags & LK_INTERLOCK) == 0) |
1828 |
if ((flags & LK_INTERLOCK) == 0) |
1788 |
VI_LOCK(vp); |
1829 |
VI_LOCK(vp); |
Lines 1798-1803
Link Here
|
1798 |
lvp = unp->un_lowervp; |
1839 |
lvp = unp->un_lowervp; |
1799 |
uvp = unp->un_uppervp; |
1840 |
uvp = unp->un_uppervp; |
1800 |
|
1841 |
|
|
|
1842 |
if ((revlock = unionfs_get_llt_revlock(vp, flags)) == 0) |
1843 |
panic("unknown lock type: 0x%x", flags & LK_TYPE_MASK); |
1844 |
|
1801 |
if ((mp->mnt_kern_flag & MNTK_MPSAFE) != 0 && |
1845 |
if ((mp->mnt_kern_flag & MNTK_MPSAFE) != 0 && |
1802 |
(vp->v_iflag & VI_OWEINACT) != 0) |
1846 |
(vp->v_iflag & VI_OWEINACT) != 0) |
1803 |
flags |= LK_NOWAIT; |
1847 |
flags |= LK_NOWAIT; |
Lines 1811-1816
Link Here
|
1811 |
flags |= LK_CANRECURSE; |
1855 |
flags |= LK_CANRECURSE; |
1812 |
|
1856 |
|
1813 |
if (lvp != NULLVP) { |
1857 |
if (lvp != NULLVP) { |
|
|
1858 |
if (uvp != NULLVP && flags & LK_UPGRADE) { |
1859 |
/* Share Lock is once released and a deadlock is avoided. */ |
1860 |
VI_LOCK_FLAGS(uvp, MTX_DUPOK); |
1861 |
vholdl(uvp); |
1862 |
uhold = 1; |
1863 |
VI_UNLOCK(vp); |
1864 |
VOP_UNLOCK(uvp, LK_RELEASE | LK_INTERLOCK); |
1865 |
VI_LOCK(vp); |
1866 |
unp = VTOUNIONFS(vp); |
1867 |
if (unp == NULL) { |
1868 |
/* vnode is released. */ |
1869 |
VI_UNLOCK(vp); |
1870 |
VOP_UNLOCK(lvp, LK_RELEASE); |
1871 |
vdrop(uvp); |
1872 |
return (EBUSY); |
1873 |
} |
1874 |
} |
1814 |
VI_LOCK_FLAGS(lvp, MTX_DUPOK); |
1875 |
VI_LOCK_FLAGS(lvp, MTX_DUPOK); |
1815 |
flags |= LK_INTERLOCK; |
1876 |
flags |= LK_INTERLOCK; |
1816 |
vholdl(lvp); |
1877 |
vholdl(lvp); |
Lines 1823-1841
Link Here
|
1823 |
VI_LOCK(vp); |
1884 |
VI_LOCK(vp); |
1824 |
unp = VTOUNIONFS(vp); |
1885 |
unp = VTOUNIONFS(vp); |
1825 |
if (unp == NULL) { |
1886 |
if (unp == NULL) { |
|
|
1887 |
/* vnode is released. */ |
1826 |
VI_UNLOCK(vp); |
1888 |
VI_UNLOCK(vp); |
1827 |
if (error == 0) |
1889 |
if (error == 0) |
1828 |
VOP_UNLOCK(lvp, 0); |
1890 |
VOP_UNLOCK(lvp, LK_RELEASE); |
1829 |
vdrop(lvp); |
1891 |
vdrop(lvp); |
|
|
1892 |
if (uhold != 0) |
1893 |
vdrop(uvp); |
1830 |
return (vop_stdlock(ap)); |
1894 |
return (vop_stdlock(ap)); |
1831 |
} |
1895 |
} |
1832 |
} |
1896 |
} |
1833 |
|
1897 |
|
1834 |
if (error == 0 && uvp != NULLVP) { |
1898 |
if (error == 0 && uvp != NULLVP) { |
|
|
1899 |
if (uhold && flags & LK_UPGRADE) { |
1900 |
flags &= ~LK_TYPE_MASK; |
1901 |
flags |= LK_EXCLUSIVE; |
1902 |
} |
1835 |
VI_LOCK_FLAGS(uvp, MTX_DUPOK); |
1903 |
VI_LOCK_FLAGS(uvp, MTX_DUPOK); |
1836 |
flags |= LK_INTERLOCK; |
1904 |
flags |= LK_INTERLOCK; |
1837 |
vholdl(uvp); |
1905 |
if (uhold == 0) { |
1838 |
uhold = 1; |
1906 |
vholdl(uvp); |
|
|
1907 |
uhold = 1; |
1908 |
} |
1839 |
|
1909 |
|
1840 |
VI_UNLOCK(vp); |
1910 |
VI_UNLOCK(vp); |
1841 |
ap->a_flags &= ~LK_INTERLOCK; |
1911 |
ap->a_flags &= ~LK_INTERLOCK; |
Lines 1845-1874
Link Here
|
1845 |
VI_LOCK(vp); |
1915 |
VI_LOCK(vp); |
1846 |
unp = VTOUNIONFS(vp); |
1916 |
unp = VTOUNIONFS(vp); |
1847 |
if (unp == NULL) { |
1917 |
if (unp == NULL) { |
|
|
1918 |
/* vnode is released. */ |
1848 |
VI_UNLOCK(vp); |
1919 |
VI_UNLOCK(vp); |
1849 |
if (error == 0) { |
1920 |
if (error == 0) |
1850 |
VOP_UNLOCK(uvp, 0); |
1921 |
VOP_UNLOCK(uvp, LK_RELEASE); |
1851 |
if (lvp != NULLVP) |
|
|
1852 |
VOP_UNLOCK(lvp, 0); |
1853 |
} |
1854 |
if (lvp != NULLVP) |
1855 |
vdrop(lvp); |
1856 |
vdrop(uvp); |
1922 |
vdrop(uvp); |
|
|
1923 |
if (lvp != NULLVP) { |
1924 |
VOP_UNLOCK(lvp, LK_RELEASE); |
1925 |
vdrop(lvp); |
1926 |
} |
1857 |
return (vop_stdlock(ap)); |
1927 |
return (vop_stdlock(ap)); |
1858 |
} |
1928 |
} |
1859 |
|
|
|
1860 |
if (error != 0 && lvp != NULLVP) { |
1929 |
if (error != 0 && lvp != NULLVP) { |
|
|
1930 |
/* rollback */ |
1861 |
VI_UNLOCK(vp); |
1931 |
VI_UNLOCK(vp); |
1862 |
if ((revlock & LK_TYPE_MASK) == LK_RELEASE) |
1932 |
unionfs_revlock(lvp, revlock); |
1863 |
VOP_UNLOCK(lvp, revlock); |
1933 |
interlock = 0; |
1864 |
else |
|
|
1865 |
vn_lock(lvp, revlock | LK_RETRY); |
1866 |
goto unionfs_lock_abort; |
1867 |
} |
1934 |
} |
1868 |
} |
1935 |
} |
1869 |
|
1936 |
|
1870 |
VI_UNLOCK(vp); |
1937 |
if (interlock) |
1871 |
unionfs_lock_abort: |
1938 |
VI_UNLOCK(vp); |
1872 |
if (lvp != NULLVP) |
1939 |
if (lvp != NULLVP) |
1873 |
vdrop(lvp); |
1940 |
vdrop(lvp); |
1874 |
if (uhold != 0) |
1941 |
if (uhold != 0) |
Lines 2013-2019
Link Here
|
2013 |
unionfs_tryrem_node_status(unp, unsp); |
2080 |
unionfs_tryrem_node_status(unp, unsp); |
2014 |
} |
2081 |
} |
2015 |
|
2082 |
|
2016 |
VOP_UNLOCK(vp, 0); |
2083 |
VOP_UNLOCK(vp, LK_RELEASE); |
2017 |
|
2084 |
|
2018 |
error = VOP_ADVLOCK(uvp, ap->a_id, ap->a_op, ap->a_fl, ap->a_flags); |
2085 |
error = VOP_ADVLOCK(uvp, ap->a_id, ap->a_op, ap->a_fl, ap->a_flags); |
2019 |
|
2086 |
|
Lines 2022-2028
Link Here
|
2022 |
return error; |
2089 |
return error; |
2023 |
|
2090 |
|
2024 |
unionfs_advlock_abort: |
2091 |
unionfs_advlock_abort: |
2025 |
VOP_UNLOCK(vp, 0); |
2092 |
VOP_UNLOCK(vp, LK_RELEASE); |
2026 |
|
2093 |
|
2027 |
UNIONFS_INTERNAL_DEBUG("unionfs_advlock: leave (%d)\n", error); |
2094 |
UNIONFS_INTERNAL_DEBUG("unionfs_advlock: leave (%d)\n", error); |
2028 |
|
2095 |
|
Lines 2150-2156
Link Here
|
2150 |
error = VOP_OPENEXTATTR(tvp, ap->a_cred, ap->a_td); |
2217 |
error = VOP_OPENEXTATTR(tvp, ap->a_cred, ap->a_td); |
2151 |
|
2218 |
|
2152 |
if (error == 0) { |
2219 |
if (error == 0) { |
2153 |
vn_lock(vp, LK_UPGRADE | LK_RETRY); |
2220 |
if (vn_lock(vp, LK_UPGRADE) != 0) |
|
|
2221 |
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); |
2154 |
if (tvp == unp->un_uppervp) |
2222 |
if (tvp == unp->un_uppervp) |
2155 |
unp->un_flag |= UNIONFS_OPENEXTU; |
2223 |
unp->un_flag |= UNIONFS_OPENEXTU; |
2156 |
else |
2224 |
else |
Lines 2186-2192
Link Here
|
2186 |
error = VOP_CLOSEEXTATTR(tvp, ap->a_commit, ap->a_cred, ap->a_td); |
2254 |
error = VOP_CLOSEEXTATTR(tvp, ap->a_commit, ap->a_cred, ap->a_td); |
2187 |
|
2255 |
|
2188 |
if (error == 0) { |
2256 |
if (error == 0) { |
2189 |
vn_lock(vp, LK_UPGRADE | LK_RETRY); |
2257 |
if (vn_lock(vp, LK_UPGRADE) != 0) |
|
|
2258 |
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); |
2190 |
if (tvp == unp->un_uppervp) |
2259 |
if (tvp == unp->un_uppervp) |
2191 |
unp->un_flag &= ~UNIONFS_OPENEXTU; |
2260 |
unp->un_flag &= ~UNIONFS_OPENEXTU; |
2192 |
else |
2261 |
else |
Lines 2435-2440
Link Here
|
2435 |
.vop_getextattr = unionfs_getextattr, |
2504 |
.vop_getextattr = unionfs_getextattr, |
2436 |
.vop_getwritemount = unionfs_getwritemount, |
2505 |
.vop_getwritemount = unionfs_getwritemount, |
2437 |
.vop_inactive = unionfs_inactive, |
2506 |
.vop_inactive = unionfs_inactive, |
|
|
2507 |
.vop_islocked = unionfs_islocked, |
2438 |
.vop_ioctl = unionfs_ioctl, |
2508 |
.vop_ioctl = unionfs_ioctl, |
2439 |
.vop_link = unionfs_link, |
2509 |
.vop_link = unionfs_link, |
2440 |
.vop_listextattr = unionfs_listextattr, |
2510 |
.vop_listextattr = unionfs_listextattr, |