summaryrefslogtreecommitdiffstats
path: root/sys/fs/udf/udf_vnops.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/fs/udf/udf_vnops.c')
-rw-r--r--sys/fs/udf/udf_vnops.c44
1 files changed, 30 insertions, 14 deletions
diff --git a/sys/fs/udf/udf_vnops.c b/sys/fs/udf/udf_vnops.c
index a80c3ce..05481bc 100644
--- a/sys/fs/udf/udf_vnops.c
+++ b/sys/fs/udf/udf_vnops.c
@@ -1068,13 +1068,14 @@ udf_lookup(struct vop_cachedlookup_args *a)
long namelen;
ino_t id = 0;
int offset, error = 0;
- int numdirpasses, fsize;
+ int fsize, lkflags, ltype, numdirpasses;
dvp = a->a_dvp;
node = VTON(dvp);
udfmp = node->udfmp;
nameiop = a->a_cnp->cn_nameiop;
flags = a->a_cnp->cn_flags;
+ lkflags = a->a_cnp->cn_lkflags;
nameptr = a->a_cnp->cn_nameptr;
namelen = a->a_cnp->cn_namelen;
fsize = le64toh(node->fentry->inf_len);
@@ -1135,20 +1136,35 @@ lookloop:
/* Did we have a match? */
if (id) {
- if (flags & ISDOTDOT)
- VOP_UNLOCK(dvp, 0);
- error = udf_vget(udfmp->im_mountp, id, LK_EXCLUSIVE, &tdp);
- if (flags & ISDOTDOT)
- vn_lock(dvp, LK_EXCLUSIVE|LK_RETRY);
- if (!error) {
+ /*
+ * Remember where this entry was if it's the final
+ * component.
+ */
+ if ((flags & ISLASTCN) && nameiop == LOOKUP)
+ node->diroff = ds->offset + ds->off;
+ if (numdirpasses == 2)
+ nchstats.ncs_pass2++;
+ udf_closedir(ds);
+
+ if (flags & ISDOTDOT) {
+ error = vn_vget_ino(dvp, id, lkflags, &tdp);
+ } else if (node->hash_id == id) {
+ VREF(dvp); /* we want ourself, ie "." */
/*
- * Remember where this entry was if it's the final
- * component.
+ * When we lookup "." we still can be asked to lock it
+ * differently.
*/
- if ((flags & ISLASTCN) && nameiop == LOOKUP)
- node->diroff = ds->offset + ds->off;
- if (numdirpasses == 2)
- nchstats.ncs_pass2++;
+ ltype = lkflags & LK_TYPE_MASK;
+ if (ltype != VOP_ISLOCKED(dvp)) {
+ if (ltype == LK_EXCLUSIVE)
+ vn_lock(dvp, LK_UPGRADE | LK_RETRY);
+ else /* if (ltype == LK_SHARED) */
+ vn_lock(dvp, LK_DOWNGRADE | LK_RETRY);
+ }
+ tdp = dvp;
+ } else
+ error = udf_vget(udfmp->im_mountp, id, lkflags, &tdp);
+ if (!error) {
*vpp = tdp;
/* Put this entry in the cache */
if (flags & MAKEENTRY)
@@ -1162,6 +1178,7 @@ lookloop:
udf_closedir(ds);
goto lookloop;
}
+ udf_closedir(ds);
/* Enter name into cache as non-existant */
if (flags & MAKEENTRY)
@@ -1175,7 +1192,6 @@ lookloop:
}
}
- udf_closedir(ds);
return (error);
}
OpenPOWER on IntegriCloud