View | Details | Raw Unified | Return to bug 161511
Collapse All | Expand All

(-)/usr/src/sys/fs/unionfs/union_subr.c (-7 / +10 lines)
Lines 350-368 Link Here
350
	uvp = unp->un_uppervp;
350
	uvp = unp->un_uppervp;
351
	dvp = unp->un_dvp;
351
	dvp = unp->un_dvp;
352
	unp->un_lowervp = unp->un_uppervp = NULLVP;
352
	unp->un_lowervp = unp->un_uppervp = NULLVP;
353
354
	vp->v_vnlock = &(vp->v_lock);
353
	vp->v_vnlock = &(vp->v_lock);
355
	vp->v_data = NULL;
354
	vp->v_data = NULL;
356
	lockmgr(vp->v_vnlock, LK_EXCLUSIVE | LK_INTERLOCK, VI_MTX(vp));
355
	vp->v_object = NULL;
356
	VI_UNLOCK(vp);
357
357
	if (lvp != NULLVP)
358
	if (lvp != NULLVP)
358
		VOP_UNLOCK(lvp, 0);
359
		VOP_UNLOCK(lvp, LK_RELEASE);
359
	if (uvp != NULLVP)
360
	if (uvp != NULLVP)
360
		VOP_UNLOCK(uvp, 0);
361
		VOP_UNLOCK(uvp, LK_RELEASE);
361
	vp->v_object = NULL;
362
362
363
	if (dvp != NULLVP && unp->un_hash.le_prev != NULL)
363
	if (dvp != NULLVP && unp->un_hash.le_prev != NULL)
364
		unionfs_rem_cached_vnode(unp, dvp);
364
		unionfs_rem_cached_vnode(unp, dvp);
365
365
366
	if (lockmgr(vp->v_vnlock, LK_EXCLUSIVE, VI_MTX(vp)) != 0)
367
		panic("the lock for deletion is unacquirable.");
368
366
	if (lvp != NULLVP) {
369
	if (lvp != NULLVP) {
367
		vfslocked = VFS_LOCK_GIANT(lvp->v_mount);
370
		vfslocked = VFS_LOCK_GIANT(lvp->v_mount);
368
		vrele(lvp);
371
		vrele(lvp);
Lines 550-556 Link Here
550
		cn->cn_flags |= (cnp->cn_flags & SAVESTART);
553
		cn->cn_flags |= (cnp->cn_flags & SAVESTART);
551
554
552
	vref(dvp);
555
	vref(dvp);
553
	VOP_UNLOCK(dvp, 0);
556
	VOP_UNLOCK(dvp, LK_RELEASE);
554
557
555
	if ((error = relookup(dvp, vpp, cn))) {
558
	if ((error = relookup(dvp, vpp, cn))) {
556
		uma_zfree(namei_zone, cn->cn_pnbuf);
559
		uma_zfree(namei_zone, cn->cn_pnbuf);
Lines 957-963 Link Here
957
	*vpp = vp;
960
	*vpp = vp;
958
961
959
unionfs_vn_create_on_upper_free_out1:
962
unionfs_vn_create_on_upper_free_out1:
960
	VOP_UNLOCK(udvp, 0);
963
	VOP_UNLOCK(udvp, LK_RELEASE);
961
964
962
unionfs_vn_create_on_upper_free_out2:
965
unionfs_vn_create_on_upper_free_out2:
963
	if (cn.cn_flags & HASBUF) {
966
	if (cn.cn_flags & HASBUF) {
(-)/usr/src/sys/fs/unionfs/union_vfsops.c (-3 / +3 lines)
Lines 165-171 Link Here
165
		uid = va.va_uid;
165
		uid = va.va_uid;
166
		gid = va.va_gid;
166
		gid = va.va_gid;
167
	}
167
	}
168
	VOP_UNLOCK(mp->mnt_vnodecovered, 0);
168
	VOP_UNLOCK(mp->mnt_vnodecovered, LK_RELEASE);
169
	if (error)
169
	if (error)
170
		return (error);
170
		return (error);
171
171
Lines 250-256 Link Here
250
	 * Save reference
250
	 * Save reference
251
	 */
251
	 */
252
	if (below) {
252
	if (below) {
253
		VOP_UNLOCK(upperrootvp, 0);
253
		VOP_UNLOCK(upperrootvp, LK_RELEASE);
254
		vn_lock(lowerrootvp, LK_EXCLUSIVE | LK_RETRY);
254
		vn_lock(lowerrootvp, LK_EXCLUSIVE | LK_RETRY);
255
		ump->um_lowervp = upperrootvp;
255
		ump->um_lowervp = upperrootvp;
256
		ump->um_uppervp = lowerrootvp;
256
		ump->um_uppervp = lowerrootvp;
Lines 281-287 Link Here
281
	/*
281
	/*
282
	 * Unlock the node
282
	 * Unlock the node
283
	 */
283
	 */
284
	VOP_UNLOCK(ump->um_uppervp, 0);
284
	VOP_UNLOCK(ump->um_uppervp, LK_RELEASE);
285
285
286
	/*
286
	/*
287
	 * Get the unionfs root vnode.
287
	 * Get the unionfs root vnode.
(-)/usr/src/sys/fs/unionfs/union_vnops.c (-91 / +161 lines)
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,

Return to bug 161511