summaryrefslogtreecommitdiffstats
path: root/sys/fs/smbfs/smbfs_node.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/fs/smbfs/smbfs_node.c')
-rw-r--r--sys/fs/smbfs/smbfs_node.c47
1 files changed, 38 insertions, 9 deletions
diff --git a/sys/fs/smbfs/smbfs_node.c b/sys/fs/smbfs/smbfs_node.c
index 66696ca..481fa1d 100644
--- a/sys/fs/smbfs/smbfs_node.c
+++ b/sys/fs/smbfs/smbfs_node.c
@@ -98,8 +98,9 @@ smbfs_vnode_cmp(struct vnode *vp, void *_sc)
}
static int
-smbfs_node_alloc(struct mount *mp, struct vnode *dvp,
- const char *name, int nmlen, struct smbfattr *fap, struct vnode **vpp)
+smbfs_node_alloc(struct mount *mp, struct vnode *dvp, const char *dirnm,
+ int dirlen, const char *name, int nmlen, char sep,
+ struct smbfattr *fap, struct vnode **vpp)
{
struct vattr vattr;
struct thread *td = curthread; /* XXX */
@@ -107,12 +108,12 @@ smbfs_node_alloc(struct mount *mp, struct vnode *dvp,
struct smbnode *np, *dnp;
struct vnode *vp, *vp2;
struct smbcmp sc;
- int error;
+ char *p, *rpath;
+ int error, rplen;
sc.n_parent = dvp;
sc.n_nmlen = nmlen;
sc.n_name = name;
- *vpp = NULL;
if (smp->sm_root != NULL && dvp == NULL) {
SMBERROR("do not allocate root vnode twice!\n");
return EINVAL;
@@ -134,7 +135,6 @@ smbfs_node_alloc(struct mount *mp, struct vnode *dvp,
vprint("smbfs_node_alloc: dead parent vnode", dvp);
return EINVAL;
}
- *vpp = NULL;
error = vfs_hash_get(mp, smbfs_hash(name, nmlen), LK_EXCLUSIVE, td,
vpp, smbfs_vnode_cmp, &sc);
if (error)
@@ -173,18 +173,37 @@ smbfs_node_alloc(struct mount *mp, struct vnode *dvp,
return (error);
vp = *vpp;
np = malloc(sizeof *np, M_SMBNODE, M_WAITOK | M_ZERO);
+ rplen = dirlen;
+ if (sep != '\0')
+ rplen++;
+ rplen += nmlen;
+ rpath = malloc(rplen + 1, M_SMBNODENAME, M_WAITOK);
+ p = rpath;
+ bcopy(dirnm, p, dirlen);
+ p += dirlen;
+ if (sep != '\0')
+ *p++ = sep;
+ if (name != NULL) {
+ bcopy(name, p, nmlen);
+ p += nmlen;
+ }
+ *p = '\0';
+ MPASS(p == rpath + rplen);
lockmgr(vp->v_vnlock, LK_EXCLUSIVE, NULL);
/* Vnode initialization */
vp->v_type = fap->fa_attr & SMB_FA_DIR ? VDIR : VREG;
vp->v_data = np;
np->n_vnode = vp;
np->n_mount = VFSTOSMBFS(mp);
+ np->n_rpath = rpath;
+ np->n_rplen = rplen;
np->n_nmlen = nmlen;
np->n_name = smbfs_name_alloc(name, nmlen);
np->n_ino = fap->fa_ino;
if (dvp) {
ASSERT_VOP_LOCKED(dvp, "smbfs_node_alloc");
np->n_parent = dvp;
+ np->n_parentino = VTOSMB(dvp)->n_ino;
if (/*vp->v_type == VDIR &&*/ (dvp->v_vflag & VV_ROOT) == 0) {
vref(dvp);
np->n_flag |= NREFPARENT;
@@ -209,14 +228,22 @@ int
smbfs_nget(struct mount *mp, struct vnode *dvp, const char *name, int nmlen,
struct smbfattr *fap, struct vnode **vpp)
{
- struct smbnode *np;
+ struct smbnode *dnp, *np;
struct vnode *vp;
- int error;
+ int error, sep;
- *vpp = NULL;
- error = smbfs_node_alloc(mp, dvp, name, nmlen, fap, &vp);
+ dnp = (dvp) ? VTOSMB(dvp) : NULL;
+ sep = 0;
+ if (dnp != NULL) {
+ sep = SMBFS_DNP_SEP(dnp);
+ error = smbfs_node_alloc(mp, dvp, dnp->n_rpath, dnp->n_rplen,
+ name, nmlen, sep, fap, &vp);
+ } else
+ error = smbfs_node_alloc(mp, NULL, "\\", 1, name, nmlen,
+ sep, fap, &vp);
if (error)
return error;
+ MPASS(vp != NULL);
np = VTOSMB(vp);
if (fap)
smbfs_attr_cacheenter(vp, fap);
@@ -256,6 +283,8 @@ smbfs_reclaim(ap)
vfs_hash_remove(vp);
if (np->n_name)
smbfs_name_free(np->n_name);
+ if (np->n_rpath)
+ free(np->n_rpath, M_SMBNODENAME);
free(np, M_SMBNODE);
vp->v_data = NULL;
if (dvp != NULL) {
OpenPOWER on IntegriCloud