[Midnightbsd-cvs] src [10021] trunk/sys/fs/smbfs: sync smbfs with freebsd
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Sun May 27 18:08:56 EDT 2018
Revision: 10021
http://svnweb.midnightbsd.org/src/?rev=10021
Author: laffer1
Date: 2018-05-27 18:08:55 -0400 (Sun, 27 May 2018)
Log Message:
-----------
sync smbfs with freebsd
Modified Paths:
--------------
trunk/sys/fs/smbfs/smbfs.h
trunk/sys/fs/smbfs/smbfs_io.c
trunk/sys/fs/smbfs/smbfs_node.c
trunk/sys/fs/smbfs/smbfs_node.h
trunk/sys/fs/smbfs/smbfs_smb.c
trunk/sys/fs/smbfs/smbfs_subr.c
trunk/sys/fs/smbfs/smbfs_subr.h
trunk/sys/fs/smbfs/smbfs_vfsops.c
trunk/sys/fs/smbfs/smbfs_vnops.c
Modified: trunk/sys/fs/smbfs/smbfs.h
===================================================================
--- trunk/sys/fs/smbfs/smbfs.h 2018-05-27 22:08:25 UTC (rev 10020)
+++ trunk/sys/fs/smbfs/smbfs.h 2018-05-27 22:08:55 UTC (rev 10021)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2000-2001 Boris Popov
* All rights reserved.
@@ -23,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/smbfs/smbfs.h 250236 2013-05-04 14:03:18Z davide $
*/
#ifndef _SMBFS_SMBFS_H_
#define _SMBFS_SMBFS_H_
@@ -61,10 +62,6 @@
#include <sys/_sx.h>
-#ifdef MALLOC_DECLARE
-MALLOC_DECLARE(M_SMBFSMNT);
-#endif
-
struct smbnode;
struct smb_share;
struct u_cred;
@@ -79,16 +76,13 @@
mode_t sm_dir_mode;
struct mount * sm_mp;
struct smbnode * sm_root;
+ struct smb_dev * sm_dev;
struct ucred * sm_owner;
uint64_t sm_flags;
long sm_nextino;
struct smb_share * sm_share;
-/* struct simplelock sm_npslock;*/
struct smbnode * sm_npstack[SMBFS_MAXPATHCOMP];
int sm_caseopt;
- struct sx sm_hashlock;
- LIST_HEAD(smbnode_hashhead, smbnode) *sm_hash;
- u_long sm_hashlen;
int sm_didrele;
};
Modified: trunk/sys/fs/smbfs/smbfs_io.c
===================================================================
--- trunk/sys/fs/smbfs/smbfs_io.c 2018-05-27 22:08:25 UTC (rev 10020)
+++ trunk/sys/fs/smbfs/smbfs_io.c 2018-05-27 22:08:55 UTC (rev 10021)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2000-2001 Boris Popov
* All rights reserved.
@@ -23,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/smbfs/smbfs_io.c 250238 2013-05-04 14:27:28Z davide $
*
*/
#include <sys/param.h>
@@ -36,6 +37,7 @@
#include <sys/namei.h>
#include <sys/vnode.h>
#include <sys/dirent.h>
+#include <sys/rwlock.h>
#include <sys/signalvar.h>
#include <sys/sysctl.h>
#include <sys/vmmeter.h>
@@ -75,7 +77,7 @@
{
struct dirent de;
struct componentname cn;
- struct smb_cred scred;
+ struct smb_cred *scred;
struct smbfs_fctx *ctx;
struct vnode *newvp;
struct smbnode *np = VTOSMB(vp);
@@ -84,17 +86,20 @@
np = VTOSMB(vp);
SMBVDEBUG("dirname='%s'\n", np->n_name);
- smb_makescred(&scred, uio->uio_td, cred);
+ scred = smbfs_malloc_scred();
+ smb_makescred(scred, uio->uio_td, cred);
offset = uio->uio_offset / DE_SIZE; /* offset in the directory */
limit = uio->uio_resid / DE_SIZE;
- if (uio->uio_resid < DE_SIZE || uio->uio_offset < 0)
- return EINVAL;
+ if (uio->uio_resid < DE_SIZE || uio->uio_offset < 0) {
+ error = EINVAL;
+ goto out;
+ }
while (limit && offset < 2) {
limit--;
bzero((caddr_t)&de, DE_SIZE);
de.d_reclen = DE_SIZE;
de.d_fileno = (offset == 0) ? np->n_ino :
- (np->n_parent ? VTOSMB(np->n_parent)->n_ino : 2);
+ (np->n_parent ? np->n_parentino : 2);
if (de.d_fileno == 0)
de.d_fileno = 0x7ffffffd + offset;
de.d_namlen = offset + 1;
@@ -104,40 +109,43 @@
de.d_type = DT_DIR;
error = uiomove(&de, DE_SIZE, uio);
if (error)
- return error;
+ goto out;
offset++;
uio->uio_offset += DE_SIZE;
}
- if (limit == 0)
- return 0;
+ if (limit == 0) {
+ error = 0;
+ goto out;
+ }
if (offset != np->n_dirofs || np->n_dirseq == NULL) {
SMBVDEBUG("Reopening search %ld:%ld\n", offset, np->n_dirofs);
if (np->n_dirseq) {
- smbfs_findclose(np->n_dirseq, &scred);
+ smbfs_findclose(np->n_dirseq, scred);
np->n_dirseq = NULL;
}
np->n_dirofs = 2;
error = smbfs_findopen(np, "*", 1,
SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR,
- &scred, &ctx);
+ scred, &ctx);
if (error) {
SMBVDEBUG("can not open search, error = %d", error);
- return error;
+ goto out;
}
np->n_dirseq = ctx;
} else
ctx = np->n_dirseq;
while (np->n_dirofs < offset) {
- error = smbfs_findnext(ctx, offset - np->n_dirofs++, &scred);
+ error = smbfs_findnext(ctx, offset - np->n_dirofs++, scred);
if (error) {
- smbfs_findclose(np->n_dirseq, &scred);
+ smbfs_findclose(np->n_dirseq, scred);
np->n_dirseq = NULL;
- return error == ENOENT ? 0 : error;
+ error = ENOENT ? 0 : error;
+ goto out;
}
}
error = 0;
for (; limit; limit--, offset++) {
- error = smbfs_findnext(ctx, limit, &scred);
+ error = smbfs_findnext(ctx, limit, scred);
if (error)
break;
np->n_dirofs++;
@@ -165,6 +173,8 @@
if (error == ENOENT)
error = 0;
uio->uio_offset = offset * DE_SIZE;
+out:
+ smbfs_free_scred(scred);
return error;
}
@@ -175,7 +185,7 @@
struct smbnode *np = VTOSMB(vp);
struct thread *td;
struct vattr vattr;
- struct smb_cred scred;
+ struct smb_cred *scred;
int error, lks;
/*
@@ -223,8 +233,11 @@
np->n_mtime.tv_sec = vattr.va_mtime.tv_sec;
}
}
- smb_makescred(&scred, td, cred);
- return smb_read(smp->sm_share, np->n_fid, uiop, &scred);
+ scred = smbfs_malloc_scred();
+ smb_makescred(scred, td, cred);
+ error = smb_read(smp->sm_share, np->n_fid, uiop, scred);
+ smbfs_free_scred(scred);
+ return (error);
}
int
@@ -233,7 +246,7 @@
{
struct smbmount *smp = VTOSMBFS(vp);
struct smbnode *np = VTOSMB(vp);
- struct smb_cred scred;
+ struct smb_cred *scred;
struct thread *td;
int error = 0;
@@ -241,7 +254,8 @@
SMBERROR("vn types other than VREG unsupported !\n");
return EIO;
}
- SMBVDEBUG("ofs=%d,resid=%d\n",(int)uiop->uio_offset, uiop->uio_resid);
+ SMBVDEBUG("ofs=%jd,resid=%zd\n", (intmax_t)uiop->uio_offset,
+ uiop->uio_resid);
if (uiop->uio_offset < 0)
return EINVAL;
/* if (uiop->uio_offset + uiop->uio_resid > smp->nm_maxfilesize)
@@ -271,10 +285,13 @@
if (vn_rlimit_fsize(vp, uiop, td))
return (EFBIG);
-
- smb_makescred(&scred, td, cred);
- error = smb_write(smp->sm_share, np->n_fid, uiop, &scred);
- SMBVDEBUG("after: ofs=%d,resid=%d\n",(int)uiop->uio_offset, uiop->uio_resid);
+
+ scred = smbfs_malloc_scred();
+ smb_makescred(scred, td, cred);
+ error = smb_write(smp->sm_share, np->n_fid, uiop, scred);
+ smbfs_free_scred(scred);
+ SMBVDEBUG("after: ofs=%jd,resid=%zd\n", (intmax_t)uiop->uio_offset,
+ uiop->uio_resid);
if (!error) {
if (uiop->uio_offset > np->n_size) {
np->n_size = uiop->uio_offset;
@@ -292,17 +309,19 @@
{
struct smbmount *smp = VFSTOSMBFS(vp->v_mount);
struct smbnode *np = VTOSMB(vp);
- struct uio uio, *uiop = &uio;
+ struct uio *uiop;
struct iovec io;
- struct smb_cred scred;
+ struct smb_cred *scred;
int error = 0;
+ uiop = malloc(sizeof(struct uio), M_SMBFSDATA, M_WAITOK);
uiop->uio_iov = &io;
uiop->uio_iovcnt = 1;
uiop->uio_segflg = UIO_SYSSPACE;
uiop->uio_td = td;
- smb_makescred(&scred, td, cr);
+ scred = smbfs_malloc_scred();
+ smb_makescred(scred, td, cr);
if (bp->b_iocmd == BIO_READ) {
io.iov_len = uiop->uio_resid = bp->b_bcount;
@@ -311,7 +330,7 @@
switch (vp->v_type) {
case VREG:
uiop->uio_offset = ((off_t)bp->b_blkno) * DEV_BSIZE;
- error = smb_read(smp->sm_share, np->n_fid, uiop, &scred);
+ error = smb_read(smp->sm_share, np->n_fid, uiop, scred);
if (error)
break;
if (uiop->uio_resid) {
@@ -338,7 +357,7 @@
uiop->uio_offset = ((off_t)bp->b_blkno) * DEV_BSIZE + bp->b_dirtyoff;
io.iov_base = (char *)bp->b_data + bp->b_dirtyoff;
uiop->uio_rw = UIO_WRITE;
- error = smb_write(smp->sm_share, np->n_fid, uiop, &scred);
+ error = smb_write(smp->sm_share, np->n_fid, uiop, scred);
/*
* For an interrupted write, the buffer is still valid
@@ -378,11 +397,15 @@
} else {
bp->b_resid = 0;
bufdone(bp);
+ free(uiop, M_SMBFSDATA);
+ smbfs_free_scred(scred);
return 0;
}
}
bp->b_resid = uiop->uio_resid;
bufdone(bp);
+ free(uiop, M_SMBFSDATA);
+ smbfs_free_scred(scred);
return error;
}
@@ -413,7 +436,7 @@
struct ucred *cred;
struct smbmount *smp;
struct smbnode *np;
- struct smb_cred scred;
+ struct smb_cred *scred;
vm_object_t object;
vm_page_t *pages, m;
@@ -439,7 +462,7 @@
*/
m = pages[reqpage];
- VM_OBJECT_LOCK(object);
+ VM_OBJECT_WLOCK(object);
if (m->valid != 0) {
for (i = 0; i < npages; ++i) {
if (i != reqpage) {
@@ -448,12 +471,13 @@
vm_page_unlock(pages[i]);
}
}
- VM_OBJECT_UNLOCK(object);
+ VM_OBJECT_WUNLOCK(object);
return 0;
}
- VM_OBJECT_UNLOCK(object);
+ VM_OBJECT_WUNLOCK(object);
- smb_makescred(&scred, td, cred);
+ scred = smbfs_malloc_scred();
+ smb_makescred(scred, td, cred);
bp = getpbuf(&smbfs_pbuf_freecnt);
@@ -472,12 +496,13 @@
uio.uio_rw = UIO_READ;
uio.uio_td = td;
- error = smb_read(smp->sm_share, np->n_fid, &uio, &scred);
+ error = smb_read(smp->sm_share, np->n_fid, &uio, scred);
+ smbfs_free_scred(scred);
pmap_qremove(kva, npages);
relpbuf(bp, &smbfs_pbuf_freecnt);
- VM_OBJECT_LOCK(object);
+ VM_OBJECT_WLOCK(object);
if (error && (uio.uio_resid == count)) {
printf("smbfs_getpages: error %d\n",error);
for (i = 0; i < npages; i++) {
@@ -487,7 +512,7 @@
vm_page_unlock(pages[i]);
}
}
- VM_OBJECT_UNLOCK(object);
+ VM_OBJECT_WUNLOCK(object);
return VM_PAGER_ERROR;
}
@@ -510,7 +535,7 @@
* Read operation filled a partial page.
*/
m->valid = 0;
- vm_page_set_valid(m, 0, size - toff);
+ vm_page_set_valid_range(m, 0, size - toff);
KASSERT(m->dirty == 0,
("smbfs_getpages: page %p is dirty", m));
} else {
@@ -525,7 +550,7 @@
if (i != reqpage)
vm_page_readahead_finish(m);
}
- VM_OBJECT_UNLOCK(object);
+ VM_OBJECT_WUNLOCK(object);
return 0;
#endif /* SMBFS_RWGENERIC */
}
@@ -568,7 +593,7 @@
int *rtvals;
struct smbmount *smp;
struct smbnode *np;
- struct smb_cred scred;
+ struct smb_cred *scred;
vm_page_t *pages;
td = curthread; /* XXX */
@@ -601,10 +626,13 @@
uio.uio_segflg = UIO_SYSSPACE;
uio.uio_rw = UIO_WRITE;
uio.uio_td = td;
- SMBVDEBUG("ofs=%d,resid=%d\n",(int)uio.uio_offset, uio.uio_resid);
+ SMBVDEBUG("ofs=%jd,resid=%zd\n", (intmax_t)uio.uio_offset,
+ uio.uio_resid);
- smb_makescred(&scred, td, cred);
- error = smb_write(smp->sm_share, np->n_fid, &uio, &scred);
+ scred = smbfs_malloc_scred();
+ smb_makescred(scred, td, cred);
+ error = smb_write(smp->sm_share, np->n_fid, &uio, scred);
+ smbfs_free_scred(scred);
/* VOP_CLOSE(vp, FWRITE, cred, td);*/
SMBVDEBUG("paged write done: %d\n", error);
@@ -641,9 +669,9 @@
np->n_flag |= NFLUSHINPROG;
if (vp->v_bufobj.bo_object != NULL) {
- VM_OBJECT_LOCK(vp->v_bufobj.bo_object);
+ VM_OBJECT_WLOCK(vp->v_bufobj.bo_object);
vm_object_page_clean(vp->v_bufobj.bo_object, 0, 0, OBJPC_SYNC);
- VM_OBJECT_UNLOCK(vp->v_bufobj.bo_object);
+ VM_OBJECT_WUNLOCK(vp->v_bufobj.bo_object);
}
error = vinvalbuf(vp, V_SAVE, PCATCH, 0);
Modified: trunk/sys/fs/smbfs/smbfs_node.c
===================================================================
--- trunk/sys/fs/smbfs/smbfs_node.c 2018-05-27 22:08:25 UTC (rev 10020)
+++ trunk/sys/fs/smbfs/smbfs_node.c 2018-05-27 22:08:55 UTC (rev 10021)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2000-2001 Boris Popov
* All rights reserved.
@@ -23,10 +24,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/smbfs/smbfs_node.c 254627 2013-08-21 23:04:48Z ken $
*/
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/fnv_hash.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/malloc.h>
@@ -52,56 +54,17 @@
#include <fs/smbfs/smbfs_node.h>
#include <fs/smbfs/smbfs_subr.h>
-#define SMBFS_NOHASH(smp, hval) (&(smp)->sm_hash[(hval) & (smp)->sm_hashlen])
-#define smbfs_hash_lock(smp) sx_xlock(&smp->sm_hashlock)
-#define smbfs_hash_unlock(smp) sx_xunlock(&smp->sm_hashlock)
-
extern struct vop_vector smbfs_vnodeops; /* XXX -> .h file */
static MALLOC_DEFINE(M_SMBNODE, "smbufs_node", "SMBFS vnode private part");
static MALLOC_DEFINE(M_SMBNODENAME, "smbufs_nname", "SMBFS node name");
-int smbfs_hashprint(struct mount *mp);
-
-#if 0
-#ifdef SYSCTL_DECL
-SYSCTL_DECL(_vfs_smbfs);
-#endif
-SYSCTL_PROC(_vfs_smbfs, OID_AUTO, vnprint, CTLFLAG_WR|CTLTYPE_OPAQUE,
- NULL, 0, smbfs_hashprint, "S,vnlist", "vnode hash");
-#endif
-
-#define FNV_32_PRIME ((u_int32_t) 0x01000193UL)
-#define FNV1_32_INIT ((u_int32_t) 33554467UL)
-
-u_int32_t
+u_int32_t __inline
smbfs_hash(const u_char *name, int nmlen)
{
- u_int32_t v;
-
- for (v = FNV1_32_INIT; nmlen; name++, nmlen--) {
- v *= FNV_32_PRIME;
- v ^= (u_int32_t)*name;
- }
- return v;
+ return (fnv_32_buf(name, nmlen, FNV1_32_INIT));
}
-int
-smbfs_hashprint(struct mount *mp)
-{
- struct smbmount *smp = VFSTOSMBFS(mp);
- struct smbnode_hashhead *nhpp;
- struct smbnode *np;
- int i;
-
- for(i = 0; i <= smp->sm_hashlen; i++) {
- nhpp = &smp->sm_hash[i];
- LIST_FOREACH(np, nhpp, n_hash)
- vprint("", SMBTOV(np));
- }
- return 0;
-}
-
static char *
smbfs_name_alloc(const u_char *name, int nmlen)
{
@@ -108,18 +71,8 @@
u_char *cp;
nmlen++;
-#ifdef SMBFS_NAME_DEBUG
- cp = malloc(nmlen + 2 + sizeof(int), M_SMBNODENAME, M_WAITOK);
- *(int*)cp = nmlen;
- cp += sizeof(int);
- cp[0] = 0xfc;
- cp++;
- bcopy(name, cp, nmlen - 1);
- cp[nmlen] = 0xfe;
-#else
cp = malloc(nmlen, M_SMBNODENAME, M_WAITOK);
bcopy(name, cp, nmlen - 1);
-#endif
cp[nmlen - 1] = 0;
return cp;
}
@@ -127,42 +80,41 @@
static void
smbfs_name_free(u_char *name)
{
-#ifdef SMBFS_NAME_DEBUG
- int nmlen, slen;
- u_char *cp;
- cp = name;
- cp--;
- if (*cp != 0xfc)
- panic("First byte of name entry '%s' corrupted", name);
- cp -= sizeof(int);
- nmlen = *(int*)cp;
- slen = strlen(name) + 1;
- if (nmlen != slen)
- panic("Name length mismatch: was %d, now %d name '%s'",
- nmlen, slen, name);
- if (name[nmlen] != 0xfe)
- panic("Last byte of name entry '%s' corrupted\n", name);
- free(cp, M_SMBNODENAME);
-#else
free(name, M_SMBNODENAME);
-#endif
}
+static int __inline
+smbfs_vnode_cmp(struct vnode *vp, void *_sc)
+{
+ struct smbnode *np;
+ struct smbcmp *sc;
+
+ np = (struct smbnode *) vp->v_data;
+ sc = (struct smbcmp *) _sc;
+ if (np->n_parent != sc->n_parent || np->n_nmlen != sc->n_nmlen ||
+ bcmp(sc->n_name, np->n_name, sc->n_nmlen) != 0)
+ return 1;
+ return 0;
+}
+
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 */
struct smbmount *smp = VFSTOSMBFS(mp);
- struct smbnode_hashhead *nhpp;
- struct smbnode *np, *np2, *dnp;
- struct vnode *vp;
- u_long hashval;
- int error;
+ struct smbnode *np, *dnp;
+ struct vnode *vp, *vp2;
+ struct smbcmp sc;
+ char *p, *rpath;
+ int error, rplen;
- *vpp = NULL;
+ sc.n_parent = dvp;
+ sc.n_nmlen = nmlen;
+ sc.n_name = name;
if (smp->sm_root != NULL && dvp == NULL) {
SMBERROR("do not allocate root vnode twice!\n");
return EINVAL;
@@ -184,22 +136,14 @@
vprint("smbfs_node_alloc: dead parent vnode", dvp);
return EINVAL;
}
- hashval = smbfs_hash(name, nmlen);
-retry:
- smbfs_hash_lock(smp);
-loop:
- nhpp = SMBFS_NOHASH(smp, hashval);
- LIST_FOREACH(np, nhpp, n_hash) {
- vp = SMBTOV(np);
- if (np->n_parent != dvp ||
- np->n_nmlen != nmlen || bcmp(name, np->n_name, nmlen) != 0)
- continue;
- VI_LOCK(vp);
- smbfs_hash_unlock(smp);
- if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td) != 0)
- goto retry;
+ error = vfs_hash_get(mp, smbfs_hash(name, nmlen), LK_EXCLUSIVE, td,
+ vpp, smbfs_vnode_cmp, &sc);
+ if (error)
+ return (error);
+ if (*vpp) {
+ np = VTOSMB(*vpp);
/* Force cached attributes to be refreshed if stale. */
- (void)VOP_GETATTR(vp, &vattr, td->td_ucred);
+ (void)VOP_GETATTR(*vpp, &vattr, td->td_ucred);
/*
* If the file type on the server is inconsistent with
* what it was when we created the vnode, kill the
@@ -206,16 +150,18 @@
* bogus vnode now and fall through to the code below
* to create a new one with the right type.
*/
- if ((vp->v_type == VDIR && (np->n_dosattr & SMB_FA_DIR) == 0) ||
- (vp->v_type == VREG && (np->n_dosattr & SMB_FA_DIR) != 0)) {
- vgone(vp);
- vput(vp);
- break;
+ if (((*vpp)->v_type == VDIR &&
+ (np->n_dosattr & SMB_FA_DIR) == 0) ||
+ ((*vpp)->v_type == VREG &&
+ (np->n_dosattr & SMB_FA_DIR) != 0)) {
+ vgone(*vpp);
+ vput(*vpp);
}
- *vpp = vp;
- return 0;
+ else {
+ SMBVDEBUG("vnode taken from the hashtable\n");
+ return (0);
+ }
}
- smbfs_hash_unlock(smp);
/*
* If we don't have node attributes, then it is an explicit lookup
* for an existing vnode.
@@ -223,29 +169,42 @@
if (fap == NULL)
return ENOENT;
- np = malloc(sizeof *np, M_SMBNODE, M_WAITOK);
- error = getnewvnode("smbfs", mp, &smbfs_vnodeops, &vp);
- if (error) {
- free(np, M_SMBNODE);
- return error;
- }
- error = insmntque(vp, mp); /* XXX: Too early for mpsafe fs */
- if (error != 0) {
- free(np, M_SMBNODE);
+ error = getnewvnode("smbfs", mp, &smbfs_vnodeops, vpp);
+ if (error)
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;
- bzero(np, sizeof(*np));
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;
@@ -252,24 +211,18 @@
}
} else if (vp->v_type == VREG)
SMBERROR("new vnode '%s' born without parent ?\n", np->n_name);
-
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
- VN_LOCK_AREC(vp);
-
- smbfs_hash_lock(smp);
- LIST_FOREACH(np2, nhpp, n_hash) {
- if (np2->n_parent != dvp ||
- np2->n_nmlen != nmlen || bcmp(name, np2->n_name, nmlen) != 0)
- continue;
- vput(vp);
-/* smb_name_free(np->n_name);
- free(np, M_SMBNODE);*/
- goto loop;
+ error = insmntque(vp, mp);
+ if (error) {
+ free(np, M_SMBNODE);
+ return (error);
}
- LIST_INSERT_HEAD(nhpp, np, n_hash);
- smbfs_hash_unlock(smp);
- *vpp = vp;
- return 0;
+ error = vfs_hash_insert(vp, smbfs_hash(name, nmlen), LK_EXCLUSIVE,
+ td, &vp2, smbfs_vnode_cmp, &sc);
+ if (error)
+ return (error);
+ if (vp2 != NULL)
+ *vpp = vp2;
+ return (0);
}
int
@@ -276,14 +229,22 @@
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);
@@ -310,26 +271,23 @@
KASSERT((np->n_flag & NOPEN) == 0, ("file not closed before reclaim"));
- smbfs_hash_lock(smp);
/*
* Destroy the vm object and flush associated pages.
*/
vnode_destroy_vobject(vp);
-
dvp = (np->n_parent && (np->n_flag & NREFPARENT)) ?
np->n_parent : NULL;
-
- if (np->n_hash.le_prev)
- LIST_REMOVE(np, n_hash);
- if (smp->sm_root == np) {
- SMBVDEBUG("root vnode\n");
- smp->sm_root = NULL;
- }
- vp->v_data = NULL;
- smbfs_hash_unlock(smp);
+
+ /*
+ * Remove the vnode from its hash chain.
+ */
+ 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) {
vrele(dvp);
/*
@@ -352,28 +310,30 @@
struct ucred *cred = td->td_ucred;
struct vnode *vp = ap->a_vp;
struct smbnode *np = VTOSMB(vp);
- struct smb_cred scred;
+ struct smb_cred *scred;
struct vattr va;
SMBVDEBUG("%s: %d\n", VTOSMB(vp)->n_name, vrefcnt(vp));
if ((np->n_flag & NOPEN) != 0) {
- smb_makescred(&scred, td, cred);
+ scred = smbfs_malloc_scred();
+ smb_makescred(scred, td, cred);
smbfs_vinvalbuf(vp, td);
if (vp->v_type == VREG) {
VOP_GETATTR(vp, &va, cred);
smbfs_smb_close(np->n_mount->sm_share, np->n_fid,
- &np->n_mtime, &scred);
+ &np->n_mtime, scred);
} else if (vp->v_type == VDIR) {
if (np->n_dirseq != NULL) {
- smbfs_findclose(np->n_dirseq, &scred);
+ smbfs_findclose(np->n_dirseq, scred);
np->n_dirseq = NULL;
}
}
np->n_flag &= ~NOPEN;
smbfs_attr_cacheremove(vp);
+ smbfs_free_scred(scred);
}
if (np->n_flag & NGONE)
- vrecycle(vp, td);
+ vrecycle(vp);
return (0);
}
/*
@@ -411,10 +371,13 @@
if (diff > 2) /* XXX should be configurable */
return ENOENT;
va->va_type = vp->v_type; /* vnode type (for create) */
+ va->va_flags = 0; /* flags defined for file */
if (vp->v_type == VREG) {
va->va_mode = smp->sm_file_mode; /* files access mode and type */
- if (np->n_dosattr & SMB_FA_RDONLY)
+ if (np->n_dosattr & SMB_FA_RDONLY) {
va->va_mode &= ~(S_IWUSR|S_IWGRP|S_IWOTH);
+ va->va_flags |= UF_READONLY;
+ }
} else if (vp->v_type == VDIR) {
va->va_mode = smp->sm_dir_mode; /* files access mode and type */
} else
@@ -431,7 +394,15 @@
va->va_mtime = np->n_mtime;
va->va_atime = va->va_ctime = va->va_mtime; /* time file changed */
va->va_gen = VNOVAL; /* generation number of file */
- va->va_flags = 0; /* flags defined for file */
+ if (np->n_dosattr & SMB_FA_HIDDEN)
+ va->va_flags |= UF_HIDDEN;
+ if (np->n_dosattr & SMB_FA_SYSTEM)
+ va->va_flags |= UF_SYSTEM;
+ /*
+ * We don't set the archive bit for directories.
+ */
+ if ((vp->v_type != VDIR) && (np->n_dosattr & SMB_FA_ARCHIVE))
+ va->va_flags |= UF_ARCHIVE;
va->va_rdev = NODEV; /* device the special file represents */
va->va_bytes = va->va_size; /* bytes of disk space held by file */
va->va_filerev = 0; /* file modification number */
Modified: trunk/sys/fs/smbfs/smbfs_node.h
===================================================================
--- trunk/sys/fs/smbfs/smbfs_node.h 2018-05-27 22:08:25 UTC (rev 10020)
+++ trunk/sys/fs/smbfs/smbfs_node.h 2018-05-27 22:08:55 UTC (rev 10021)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2000-2001 Boris Popov
* All rights reserved.
@@ -23,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/smbfs/smbfs_node.h 243396 2012-11-22 08:58:29Z davide $
*/
#ifndef _FS_SMBFS_NODE_H_
#define _FS_SMBFS_NODE_H_
@@ -53,9 +54,12 @@
struct timespec n_atime; /* last access time */
u_quad_t n_size;
long n_ino;
+ long n_parentino; /* parent inode number */
int n_dosattr;
u_int16_t n_fid; /* file handle */
int n_rwstate; /* granted access mode */
+ int n_rplen;
+ char * n_rpath;
u_char n_nmlen;
u_char * n_name;
struct smbfs_fctx * n_dirseq; /* ff context */
@@ -63,9 +67,17 @@
LIST_ENTRY(smbnode) n_hash;
};
+struct smbcmp {
+ struct vnode * n_parent;
+ int n_nmlen;
+ const char * n_name;
+};
+
#define VTOSMB(vp) ((struct smbnode *)(vp)->v_data)
#define SMBTOV(np) ((struct vnode *)(np)->n_vnode)
+#define SMBFS_DNP_SEP(dnp) ((dnp->n_rplen > 1) ? '\\' : '\0')
+
struct vop_getpages_args;
struct vop_inactive_args;
struct vop_putpages_args;
Modified: trunk/sys/fs/smbfs/smbfs_smb.c
===================================================================
--- trunk/sys/fs/smbfs/smbfs_smb.c 2018-05-27 22:08:25 UTC (rev 10020)
+++ trunk/sys/fs/smbfs/smbfs_smb.c 2018-05-27 22:08:55 UTC (rev 10021)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2000-2001 Boris Popov
* All rights reserved.
@@ -23,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/smbfs/smbfs_smb.c 294263 2016-01-18 11:47:03Z ae $
*/
#include <sys/param.h>
#include <sys/systm.h>
@@ -87,7 +88,7 @@
struct smb_cred *scred)
{
struct smb_share *ssp = np->n_mount->sm_share;
- struct smb_rq rq, *rqp = &rq;
+ struct smb_rq *rqp;
struct mbchain *mbp;
u_char ltype = 0;
int error;
@@ -94,9 +95,10 @@
if (op == SMB_LOCK_SHARED)
ltype |= SMB_LOCKING_ANDX_SHARED_LOCK;
- error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_LOCKING_ANDX, scred);
+
+ error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_LOCKING_ANDX, scred, &rqp);
if (error)
- return error;
+ return (error);
smb_rq_getrequest(rqp, &mbp);
smb_rq_wstart(rqp);
mb_put_uint8(mbp, 0xff); /* secondary command */
@@ -134,13 +136,54 @@
return smbfs_smb_lockandx(np, op, (uintptr_t)id, start, end, scred);
}
-int
-smbfs_smb_statfs2(struct smb_share *ssp, struct statfs *sbp,
+static int
+smbfs_query_info_fs(struct smb_share *ssp, struct statfs *sbp,
struct smb_cred *scred)
{
struct smb_t2rq *t2p;
struct mbchain *mbp;
struct mdchain *mdp;
+ uint32_t bsize, bpu;
+ int64_t units, funits;
+ int error;
+
+ error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_QUERY_FS_INFORMATION,
+ scred, &t2p);
+ if (error)
+ return (error);
+ mbp = &t2p->t2_tparam;
+ mb_init(mbp);
+ mb_put_uint16le(mbp, SMB_QUERY_FS_SIZE_INFO);
+ t2p->t2_maxpcount = 2;
+ t2p->t2_maxdcount = sizeof(int64_t) * 2 + sizeof(uint32_t) * 2;
+ error = smb_t2_request(t2p);
+ if (error) {
+ smb_t2_done(t2p);
+ return (error);
+ }
+ mdp = &t2p->t2_rdata;
+ md_get_int64le(mdp, &units);
+ md_get_int64le(mdp, &funits);
+ md_get_uint32le(mdp, &bpu);
+ md_get_uint32le(mdp, &bsize);
+ sbp->f_bsize = bpu * bsize; /* fundamental filesystem block size */
+ sbp->f_blocks= (uint64_t)units; /* total data blocks in filesystem */
+ sbp->f_bfree = (uint64_t)funits;/* free blocks in fs */
+ sbp->f_bavail= (uint64_t)funits;/* free blocks avail to non-superuser */
+ sbp->f_files = 0xffff; /* total file nodes in filesystem */
+ sbp->f_ffree = 0xffff; /* free file nodes in fs */
+ smb_t2_done(t2p);
+ return (0);
+}
+
+
+static int
+smbfs_query_info_alloc(struct smb_share *ssp, struct statfs *sbp,
+ struct smb_cred *scred)
+{
+ struct smb_t2rq *t2p;
+ struct mbchain *mbp;
+ struct mdchain *mdp;
u_int16_t bsize;
u_int32_t units, bpu, funits;
int error;
@@ -175,18 +218,19 @@
return 0;
}
-int
-smbfs_smb_statfs(struct smb_share *ssp, struct statfs *sbp,
+static int
+smbfs_query_info_disk(struct smb_share *ssp, struct statfs *sbp,
struct smb_cred *scred)
{
- struct smb_rq rq, *rqp = &rq;
+ struct smb_rq *rqp;
struct mdchain *mdp;
u_int16_t units, bpu, bsize, funits;
int error;
- error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_QUERY_INFORMATION_DISK, scred);
+ error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_QUERY_INFORMATION_DISK,
+ scred, &rqp);
if (error)
- return error;
+ return (error);
smb_rq_wstart(rqp);
smb_rq_wend(rqp);
smb_rq_bstart(rqp);
@@ -211,6 +255,20 @@
return 0;
}
+int
+smbfs_smb_statfs(struct smb_share *ssp, struct statfs *sbp,
+ struct smb_cred *scred)
+{
+
+ if (SMB_DIALECT(SSTOVC(ssp)) >= SMB_DIALECT_LANMAN2_0) {
+ if (smbfs_query_info_fs(ssp, sbp, scred) == 0)
+ return (0);
+ if (smbfs_query_info_alloc(ssp, sbp, scred) == 0)
+ return (0);
+ }
+ return (smbfs_query_info_disk(ssp, sbp, scred));
+}
+
static int
smbfs_smb_seteof(struct smbnode *np, int64_t newsize, struct smb_cred *scred)
{
@@ -244,7 +302,7 @@
smb_smb_flush(struct smbnode *np, struct smb_cred *scred)
{
struct smb_share *ssp = np->n_mount->sm_share;
- struct smb_rq rq, *rqp = &rq;
+ struct smb_rq *rqp;
struct mbchain *mbp;
int error;
@@ -251,7 +309,7 @@
if ((np->n_flag & NOPEN) == 0 || !SMBTOV(np) ||
SMBTOV(np)->v_type != VREG)
return 0; /* not a regular open file */
- error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_FLUSH, scred);
+ error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_FLUSH, scred, &rqp);
if (error)
return (error);
smb_rq_getrequest(rqp, &mbp);
@@ -276,26 +334,26 @@
}
int
-smbfs_smb_setfsize(struct smbnode *np, int newsize, struct smb_cred *scred)
+smbfs_smb_setfsize(struct smbnode *np, int64_t newsize, struct smb_cred *scred)
{
struct smb_share *ssp = np->n_mount->sm_share;
- struct smb_rq rq, *rqp = &rq;
+ struct smb_rq *rqp;
struct mbchain *mbp;
int error;
- if (!smbfs_smb_seteof(np, (int64_t) newsize, scred)) {
+ if (!smbfs_smb_seteof(np, newsize, scred)) {
np->n_flag |= NFLUSHWIRE;
return (0);
}
-
- error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_WRITE, scred);
+ /* XXX: We should use SMB_COM_WRITE_ANDX to support large offsets */
+ error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE, scred, &rqp);
if (error)
- return error;
+ return (error);
smb_rq_getrequest(rqp, &mbp);
smb_rq_wstart(rqp);
mb_put_mem(mbp, (caddr_t)&np->n_fid, 2, MB_MSYSTEM);
mb_put_uint16le(mbp, 0);
- mb_put_uint32le(mbp, newsize);
+ mb_put_uint32le(mbp, (uint32_t)newsize);
mb_put_uint16le(mbp, 0);
smb_rq_wend(rqp);
smb_rq_bstart(rqp);
@@ -311,7 +369,7 @@
smbfs_smb_query_info(struct smbnode *np, const char *name, int len,
struct smbfattr *fap, struct smb_cred *scred)
{
- struct smb_rq rq, *rqp = &rq;
+ struct smb_rq *rqp;
struct smb_share *ssp = np->n_mount->sm_share;
struct mbchain *mbp;
struct mdchain *mdp;
@@ -320,9 +378,10 @@
u_int16_t wattr;
u_int32_t lint;
- error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_QUERY_INFORMATION, scred);
+ error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_QUERY_INFORMATION, scred,
+ &rqp);
if (error)
- return error;
+ return (error);
smb_rq_getrequest(rqp, &mbp);
smb_rq_wstart(rqp);
smb_rq_wend(rqp);
@@ -367,15 +426,16 @@
smbfs_smb_setpattr(struct smbnode *np, u_int16_t attr, struct timespec *mtime,
struct smb_cred *scred)
{
- struct smb_rq rq, *rqp = &rq;
+ struct smb_rq *rqp;
struct smb_share *ssp = np->n_mount->sm_share;
struct mbchain *mbp;
u_long time;
int error, svtz;
- error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_SET_INFORMATION, scred);
+ error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_SET_INFORMATION, scred,
+ &rqp);
if (error)
- return error;
+ return (error);
svtz = SSTOVC(ssp)->vc_sopt.sv_tz;
smb_rq_getrequest(rqp, &mbp);
smb_rq_wstart(rqp);
@@ -523,15 +583,16 @@
smbfs_smb_setftime(struct smbnode *np, struct timespec *mtime,
struct timespec *atime, struct smb_cred *scred)
{
- struct smb_rq rq, *rqp = &rq;
+ struct smb_rq *rqp;
struct smb_share *ssp = np->n_mount->sm_share;
struct mbchain *mbp;
u_int16_t date, time;
int error, tzoff;
- error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_SET_INFORMATION2, scred);
+ error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_SET_INFORMATION2, scred,
+ &rqp);
if (error)
- return error;
+ return (error);
tzoff = SSTOVC(ssp)->vc_sopt.sv_tz;
smb_rq_getrequest(rqp, &mbp);
smb_rq_wstart(rqp);
@@ -611,7 +672,7 @@
int
smbfs_smb_open(struct smbnode *np, int accmode, struct smb_cred *scred)
{
- struct smb_rq rq, *rqp = &rq;
+ struct smb_rq *rqp;
struct smb_share *ssp = np->n_mount->sm_share;
struct mbchain *mbp;
struct mdchain *mdp;
@@ -619,9 +680,9 @@
u_int16_t fid, wattr, grantedmode;
int error;
- error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_OPEN, scred);
+ error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_OPEN, scred, &rqp);
if (error)
- return error;
+ return (error);
smb_rq_getrequest(rqp, &mbp);
smb_rq_wstart(rqp);
mb_put_uint16le(mbp, accmode);
@@ -664,14 +725,14 @@
smbfs_smb_close(struct smb_share *ssp, u_int16_t fid, struct timespec *mtime,
struct smb_cred *scred)
{
- struct smb_rq rq, *rqp = &rq;
+ struct smb_rq *rqp;
struct mbchain *mbp;
u_long time;
int error;
- error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CLOSE, scred);
+ error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_CLOSE, scred, &rqp);
if (error)
- return error;
+ return (error);
smb_rq_getrequest(rqp, &mbp);
smb_rq_wstart(rqp);
mb_put_mem(mbp, (caddr_t)&fid, sizeof(fid), MB_MSYSTEM);
@@ -692,7 +753,7 @@
smbfs_smb_create(struct smbnode *dnp, const char *name, int nmlen,
struct smb_cred *scred)
{
- struct smb_rq rq, *rqp = &rq;
+ struct smb_rq *rqp;
struct smb_share *ssp = dnp->n_mount->sm_share;
struct mbchain *mbp;
struct mdchain *mdp;
@@ -702,9 +763,9 @@
u_long tm;
int error;
- error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CREATE, scred);
+ error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_CREATE, scred, &rqp);
if (error)
- return error;
+ return (error);
smb_rq_getrequest(rqp, &mbp);
smb_rq_wstart(rqp);
mb_put_uint16le(mbp, SMB_FA_ARCHIVE); /* attributes */
@@ -737,14 +798,14 @@
int
smbfs_smb_delete(struct smbnode *np, struct smb_cred *scred)
{
- struct smb_rq rq, *rqp = &rq;
+ struct smb_rq *rqp;
struct smb_share *ssp = np->n_mount->sm_share;
struct mbchain *mbp;
int error;
- error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_DELETE, scred);
+ error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_DELETE, scred, &rqp);
if (error)
- return error;
+ return (error);
smb_rq_getrequest(rqp, &mbp);
smb_rq_wstart(rqp);
mb_put_uint16le(mbp, SMB_FA_SYSTEM | SMB_FA_HIDDEN);
@@ -764,14 +825,14 @@
smbfs_smb_rename(struct smbnode *src, struct smbnode *tdnp,
const char *tname, int tnmlen, struct smb_cred *scred)
{
- struct smb_rq rq, *rqp = &rq;
+ struct smb_rq *rqp;
struct smb_share *ssp = src->n_mount->sm_share;
struct mbchain *mbp;
int error;
- error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_RENAME, scred);
+ error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_RENAME, scred, &rqp);
if (error)
- return error;
+ return (error);
smb_rq_getrequest(rqp, &mbp);
smb_rq_wstart(rqp);
mb_put_uint16le(mbp, SMB_FA_SYSTEM | SMB_FA_HIDDEN);
@@ -797,14 +858,14 @@
smbfs_smb_move(struct smbnode *src, struct smbnode *tdnp,
const char *tname, int tnmlen, u_int16_t flags, struct smb_cred *scred)
{
- struct smb_rq rq, *rqp = &rq;
+ struct smb_rq *rqp;
struct smb_share *ssp = src->n_mount->sm_share;
struct mbchain *mbp;
int error;
- error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_MOVE, scred);
+ error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_MOVE, scred, &rqp);
if (error)
- return error;
+ return (error);
smb_rq_getrequest(rqp, &mbp);
smb_rq_wstart(rqp);
mb_put_uint16le(mbp, SMB_TID_UNKNOWN);
@@ -832,14 +893,15 @@
smbfs_smb_mkdir(struct smbnode *dnp, const char *name, int len,
struct smb_cred *scred)
{
- struct smb_rq rq, *rqp = &rq;
+ struct smb_rq *rqp;
struct smb_share *ssp = dnp->n_mount->sm_share;
struct mbchain *mbp;
int error;
- error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CREATE_DIRECTORY, scred);
+ error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_CREATE_DIRECTORY, scred,
+ &rqp);
if (error)
- return error;
+ return (error);
smb_rq_getrequest(rqp, &mbp);
smb_rq_wstart(rqp);
smb_rq_wend(rqp);
@@ -857,14 +919,15 @@
int
smbfs_smb_rmdir(struct smbnode *np, struct smb_cred *scred)
{
- struct smb_rq rq, *rqp = &rq;
+ struct smb_rq *rqp;
struct smb_share *ssp = np->n_mount->sm_share;
struct mbchain *mbp;
int error;
- error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_DELETE_DIRECTORY, scred);
+ error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_DELETE_DIRECTORY, scred,
+ &rqp);
if (error)
- return error;
+ return (error);
smb_rq_getrequest(rqp, &mbp);
smb_rq_wstart(rqp);
smb_rq_wend(rqp);
@@ -897,7 +960,7 @@
}
error = smb_rq_alloc(SSTOCP(ctx->f_ssp), SMB_COM_SEARCH, ctx->f_scred, &rqp);
if (error)
- return error;
+ return (error);
ctx->f_rq = rqp;
smb_rq_getrequest(rqp, &mbp);
smb_rq_wstart(rqp);
@@ -1139,13 +1202,14 @@
static int
smbfs_smb_findclose2(struct smbfs_fctx *ctx)
{
- struct smb_rq rq, *rqp = &rq;
+ struct smb_rq *rqp;
struct mbchain *mbp;
int error;
- error = smb_rq_init(rqp, SSTOCP(ctx->f_ssp), SMB_COM_FIND_CLOSE2, ctx->f_scred);
+ error = smb_rq_alloc(SSTOCP(ctx->f_ssp), SMB_COM_FIND_CLOSE2,
+ ctx->f_scred, &rqp);
if (error)
- return error;
+ return (error);
smb_rq_getrequest(rqp, &mbp);
smb_rq_wstart(rqp);
mb_put_mem(mbp, (caddr_t)&ctx->f_Sid, 2, MB_MSYSTEM);
@@ -1165,8 +1229,6 @@
ctx->f_name = malloc(SMB_MAXFNAMELEN * 2, M_SMBFSDATA, M_WAITOK);
} else
ctx->f_name = malloc(SMB_MAXFNAMELEN, M_SMBFSDATA, M_WAITOK);
- if (ctx->f_name == NULL)
- return ENOMEM;
ctx->f_infolevel = SMB_DIALECT(SSTOVC(ctx->f_ssp)) < SMB_DIALECT_NTLM0_12 ?
SMB_INFO_STANDARD : SMB_FIND_FILE_DIRECTORY_INFO;
ctx->f_attrmask = attr;
@@ -1311,10 +1373,7 @@
struct smbfs_fctx *ctx;
int error;
- ctx = malloc(sizeof(*ctx), M_SMBFSDATA, M_WAITOK);
- if (ctx == NULL)
- return ENOMEM;
- bzero(ctx, sizeof(*ctx));
+ ctx = malloc(sizeof(*ctx), M_SMBFSDATA, M_WAITOK | M_ZERO);
ctx->f_ssp = dnp->n_mount->sm_share;
ctx->f_dnp = dnp;
ctx->f_flags = SMBFS_RDD_FINDFIRST;
@@ -1395,15 +1454,9 @@
fap->fa_ino = 2;
return 0;
}
- if (nmlen == 1 && name[0] == '.') {
- error = smbfs_smb_lookup(dnp, NULL, 0, fap, scred);
- return error;
- } else if (nmlen == 2 && name[0] == '.' && name[1] == '.') {
- error = smbfs_smb_lookup(VTOSMB(dnp->n_parent), NULL, 0, fap,
- scred);
- printf("%s: knows NOTHING about '..'\n", __func__);
- return error;
- }
+ MPASS(!(nmlen == 2 && name[0] == '.' && name[1] == '.'));
+ MPASS(!(nmlen == 1 && name[0] == '.'));
+ ASSERT_VOP_ELOCKED(dnp->n_vnode, "smbfs_smb_lookup");
error = smbfs_findopen(dnp, name, nmlen,
SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR, scred, &ctx);
if (error)
Modified: trunk/sys/fs/smbfs/smbfs_subr.c
===================================================================
--- trunk/sys/fs/smbfs/smbfs_subr.c 2018-05-27 22:08:25 UTC (rev 10020)
+++ trunk/sys/fs/smbfs/smbfs_subr.c 2018-05-27 22:08:55 UTC (rev 10021)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2000-2001 Boris Popov
* All rights reserved.
@@ -23,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/smbfs/smbfs_subr.c 278435 2015-02-09 07:45:46Z dim $
*/
#include <sys/param.h>
#include <sys/systm.h>
@@ -46,6 +47,7 @@
#include <fs/smbfs/smbfs_subr.h>
MALLOC_DEFINE(M_SMBFSDATA, "smbfs_data", "SMBFS private data");
+MALLOC_DEFINE(M_SMBFSCRED, "smbfs_cred", "SMBFS cred data");
void
smb_time_local2server(struct timespec *tsp, int tzoff, u_long *seconds)
@@ -106,44 +108,6 @@
smb_time_server2local(tsp->tv_sec, tzoff, tsp);
}
-static int
-smb_fphelp(struct mbchain *mbp, struct smb_vc *vcp, struct smbnode *np,
- int caseopt)
-{
- struct smbmount *smp= np->n_mount;
- struct smbnode **npp = smp->sm_npstack;
- int i, error = 0;
-
-/* simple_lock(&smp->sm_npslock);*/
- i = 0;
- while (np->n_parent) {
- if (i++ == SMBFS_MAXPATHCOMP) {
-/* simple_unlock(&smp->sm_npslock);*/
- return ENAMETOOLONG;
- }
- *npp++ = np;
- if ((np->n_flag & NREFPARENT) == 0)
- break;
- np = VTOSMB(np->n_parent);
- }
-/* if (i == 0)
- return smb_put_dmem(mbp, vcp, "\\", 2, caseopt);*/
- while (i--) {
- np = *--npp;
- if (SMB_UNICODE_STRINGS(vcp))
- error = mb_put_uint16le(mbp, '\\');
- else
- error = mb_put_uint8(mbp, '\\');
- if (error)
- break;
- error = smb_put_dmem(mbp, vcp, np->n_name, np->n_nmlen, caseopt);
- if (error)
- break;
- }
-/* simple_unlock(&smp->sm_npslock);*/
- return error;
-}
-
int
smbfs_fullpath(struct mbchain *mbp, struct smb_vc *vcp, struct smbnode *dnp,
const char *name, int nmlen)
@@ -159,23 +123,28 @@
if (SMB_DIALECT(vcp) < SMB_DIALECT_LANMAN1_0)
caseopt |= SMB_CS_UPPER;
if (dnp != NULL) {
- error = smb_fphelp(mbp, vcp, dnp, caseopt);
+ error = smb_put_dmem(mbp, vcp, dnp->n_rpath, dnp->n_rplen,
+ caseopt);
if (error)
return error;
+ if (name) {
+ /* Put the separator */
+ if (SMB_UNICODE_STRINGS(vcp))
+ error = mb_put_uint16le(mbp, '\\');
+ else
+ error = mb_put_uint8(mbp, '\\');
+ if (error)
+ return error;
+ /* Put the name */
+ error = smb_put_dmem(mbp, vcp, name, nmlen, caseopt);
+ if (error)
+ return error;
+ }
}
- if (name) {
- if (SMB_UNICODE_STRINGS(vcp))
- error = mb_put_uint16le(mbp, '\\');
- else
- error = mb_put_uint8(mbp, '\\');
- if (error)
- return error;
- error = smb_put_dmem(mbp, vcp, name, nmlen, caseopt);
- if (error)
- return error;
- }
- error = mb_put_uint8(mbp, 0);
- if (SMB_UNICODE_STRINGS(vcp) && error == 0)
+ /* Put NULL terminator. */
+ if (SMB_UNICODE_STRINGS(vcp))
+ error = mb_put_uint16le(mbp, 0);
+ else
error = mb_put_uint8(mbp, 0);
return error;
}
@@ -202,8 +171,8 @@
if (error) return error;
*/
- error = iconv_conv_case
- (vcp->vc_tolocal, (const char **)&ibuf, &ilen, &obuf, &olen, copt);
+ error = iconv_conv_case(vcp->vc_tolocal,
+ __DECONST(const char **, &ibuf), &ilen, &obuf, &olen, copt);
if (error && SMB_UNICODE_STRINGS(vcp)) {
/*
* If using unicode, leaving a file name as it was when
@@ -222,3 +191,15 @@
}
return error;
}
+
+void *
+smbfs_malloc_scred(void)
+{
+ return (malloc(sizeof(struct smb_cred), M_SMBFSCRED, M_WAITOK));
+}
+
+void
+smbfs_free_scred(void *scred)
+{
+ free(scred, M_SMBFSCRED);
+}
Modified: trunk/sys/fs/smbfs/smbfs_subr.h
===================================================================
--- trunk/sys/fs/smbfs/smbfs_subr.h 2018-05-27 22:08:25 UTC (rev 10020)
+++ trunk/sys/fs/smbfs/smbfs_subr.h 2018-05-27 22:08:55 UTC (rev 10021)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2000-2001 Boris Popov
* All rights reserved.
@@ -23,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/smbfs/smbfs_subr.h 294263 2016-01-18 11:47:03Z ae $
*/
#ifndef _FS_SMBFS_SMBFS_SUBR_H_
#define _FS_SMBFS_SMBFS_SUBR_H_
@@ -30,6 +31,7 @@
#ifdef MALLOC_DECLARE
MALLOC_DECLARE(M_SMBFSDATA);
+MALLOC_DECLARE(M_SMBFSCRED);
#endif
#define SMBFSERR(format, args...) printf("%s: "format, __func__ ,## args)
@@ -125,11 +127,10 @@
*/
int smbfs_smb_lock(struct smbnode *np, int op, caddr_t id,
off_t start, off_t end, struct smb_cred *scred);
-int smbfs_smb_statfs2(struct smb_share *ssp, struct statfs *sbp,
- struct smb_cred *scred);
int smbfs_smb_statfs(struct smb_share *ssp, struct statfs *sbp,
struct smb_cred *scred);
-int smbfs_smb_setfsize(struct smbnode *np, int newsize, struct smb_cred *scred);
+int smbfs_smb_setfsize(struct smbnode *np, int64_t newsize,
+ struct smb_cred *scred);
int smbfs_smb_query_info(struct smbnode *np, const char *name, int len,
struct smbfattr *fap, struct smb_cred *scred);
@@ -178,4 +179,6 @@
u_int16_t *dtp, u_int8_t *dhp);
void smb_dos2unixtime (u_int dd, u_int dt, u_int dh, int tzoff, struct timespec *tsp);
+void *smbfs_malloc_scred(void);
+void smbfs_free_scred(void *);
#endif /* !_FS_SMBFS_SMBFS_SUBR_H_ */
Modified: trunk/sys/fs/smbfs/smbfs_vfsops.c
===================================================================
--- trunk/sys/fs/smbfs/smbfs_vfsops.c 2018-05-27 22:08:25 UTC (rev 10020)
+++ trunk/sys/fs/smbfs/smbfs_vfsops.c 2018-05-27 22:08:55 UTC (rev 10021)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2000-2001 Boris Popov
* All rights reserved.
@@ -23,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/smbfs/smbfs_vfsops.c 276002 2014-12-21 11:33:18Z trasz $
*/
#include <sys/param.h>
@@ -54,19 +55,10 @@
static int smbfs_version = SMBFS_VERSION;
-#ifdef SMBFS_USEZONE
-#include <vm/vm.h>
-#include <vm/vm_extern.h>
-
-vm_zone_t smbfsmount_zone;
-#endif
-
SYSCTL_NODE(_vfs, OID_AUTO, smbfs, CTLFLAG_RW, 0, "SMB/CIFS filesystem");
SYSCTL_INT(_vfs_smbfs, OID_AUTO, version, CTLFLAG_RD, &smbfs_version, 0, "");
SYSCTL_INT(_vfs_smbfs, OID_AUTO, debuglevel, CTLFLAG_RW, &smbfs_debuglevel, 0, "");
-static MALLOC_DEFINE(M_SMBFSHASH, "smbfs_hash", "SMBFS hash table");
-
static vfs_init_t smbfs_init;
static vfs_uninit_t smbfs_uninit;
static vfs_cmount_t smbfs_cmount;
@@ -131,7 +123,7 @@
}
static const char *smbfs_opts[] = {
- "dev", "soft", "intr", "strong", "have_nls", "long",
+ "fd", "soft", "intr", "strong", "have_nls", "long",
"mountpoint", "rootpath", "uid", "gid", "file_mode", "dir_mode",
"caseopt", "errmsg", NULL
};
@@ -144,10 +136,12 @@
struct smb_share *ssp = NULL;
struct vnode *vp;
struct thread *td;
- struct smb_cred scred;
+ struct smb_dev *dev;
+ struct smb_cred *scred;
int error, v;
char *pc, *pe;
+ dev = NULL;
td = curthread;
if (mp->mnt_flag & (MNT_UPDATE | MNT_ROOTFS))
return EOPNOTSUPP;
@@ -157,40 +151,31 @@
return (EINVAL);
}
- smb_makescred(&scred, td, td->td_ucred);
- if (1 != vfs_scanopt(mp->mnt_optnew, "dev", "%d", &v)) {
- vfs_mount_error(mp, "No dev option");
+ scred = smbfs_malloc_scred();
+ smb_makescred(scred, td, td->td_ucred);
+
+ /* Ask userspace of `fd`, the file descriptor of this session */
+ if (1 != vfs_scanopt(mp->mnt_optnew, "fd", "%d", &v)) {
+ vfs_mount_error(mp, "No fd option");
+ smbfs_free_scred(scred);
return (EINVAL);
}
- error = smb_dev2share(v, SMBM_EXEC, &scred, &ssp);
+ error = smb_dev2share(v, SMBM_EXEC, scred, &ssp, &dev);
+ smp = malloc(sizeof(*smp), M_SMBFSDATA, M_WAITOK | M_ZERO);
if (error) {
printf("invalid device handle %d (%d)\n", v, error);
- vfs_mount_error(mp, "invalid device handle %d (%d)\n", v, error);
+ vfs_mount_error(mp, "invalid device handle %d %d\n", v, error);
+ smbfs_free_scred(scred);
+ free(smp, M_SMBFSDATA);
return error;
}
vcp = SSTOVC(ssp);
- smb_share_unlock(ssp, 0);
+ smb_share_unlock(ssp);
mp->mnt_stat.f_iosize = SSTOVC(ssp)->vc_txmax;
-
-#ifdef SMBFS_USEZONE
- smp = zalloc(smbfsmount_zone);
-#else
- smp = malloc(sizeof(*smp), M_SMBFSDATA, M_WAITOK);
-#endif
- if (smp == NULL) {
- printf("could not alloc smbmount\n");
- vfs_mount_error(mp, "could not alloc smbmount", v, error);
- error = ENOMEM;
- goto bad;
- }
- bzero(smp, sizeof(*smp));
- mp->mnt_data = smp;
- smp->sm_hash = hashinit(desiredvnodes, M_SMBFSHASH, &smp->sm_hashlen);
- if (smp->sm_hash == NULL)
- goto bad;
- sx_init(&smp->sm_hashlock, "smbfsh");
+ mp->mnt_data = smp;
smp->sm_share = ssp;
smp->sm_root = NULL;
+ smp->sm_dev = dev;
if (1 != vfs_scanopt(mp->mnt_optnew,
"caseopt", "%d", &smp->sm_caseopt)) {
vfs_mount_error(mp, "Invalid caseopt");
@@ -228,16 +213,15 @@
vfs_flagopt(mp->mnt_optnew,
"nolong", &smp->sm_flags, SMBFS_MOUNT_NO_LONG);
-/* simple_lock_init(&smp->sm_npslock);*/
pc = mp->mnt_stat.f_mntfromname;
pe = pc + sizeof(mp->mnt_stat.f_mntfromname);
bzero(pc, MNAMELEN);
*pc++ = '/';
*pc++ = '/';
- pc=index(strncpy(pc, vcp->vc_username, pe - pc - 2), 0);
+ pc = strchr(strncpy(pc, vcp->vc_username, pe - pc - 2), 0);
if (pc < pe-1) {
*(pc++) = '@';
- pc = index(strncpy(pc, vcp->vc_srvname, pe - pc - 2), 0);
+ pc = strchr(strncpy(pc, vcp->vc_srvname, pe - pc - 2), 0);
if (pc < pe - 1) {
*(pc++) = '/';
strncpy(pc, ssp->ss_name, pe - pc - 2);
@@ -255,21 +239,20 @@
#ifdef DIAGNOSTIC
SMBERROR("mp=%p\n", mp);
#endif
+ smbfs_free_scred(scred);
return error;
bad:
- if (smp) {
- if (smp->sm_hash)
- free(smp->sm_hash, M_SMBFSHASH);
- sx_destroy(&smp->sm_hashlock);
-#ifdef SMBFS_USEZONE
- zfree(smbfsmount_zone, smp);
-#else
- free(smp, M_SMBFSDATA);
-#endif
+ if (ssp)
+ smb_share_put(ssp, scred);
+ smbfs_free_scred(scred);
+ SMB_LOCK();
+ if (error && smp->sm_dev == dev) {
+ smp->sm_dev = NULL;
+ sdp_trydestroy(dev);
}
- if (ssp)
- smb_share_put(ssp, &scred);
- return error;
+ SMB_UNLOCK();
+ free(smp, M_SMBFSDATA);
+ return error;
}
/* Unmount the filesystem described by mp. */
@@ -278,7 +261,8 @@
{
struct thread *td;
struct smbmount *smp = VFSTOSMBFS(mp);
- struct smb_cred scred;
+ struct smb_cred *scred;
+ struct smb_dev *dev;
int error, flags;
SMBVDEBUG("smbfs_unmount: flags=%04x\n", mntflags);
@@ -301,24 +285,25 @@
} while (error == EBUSY && smp->sm_didrele != 0);
if (error)
return error;
- smb_makescred(&scred, td, td->td_ucred);
- error = smb_share_lock(smp->sm_share, LK_EXCLUSIVE);
+ scred = smbfs_malloc_scred();
+ smb_makescred(scred, td, td->td_ucred);
+ error = smb_share_lock(smp->sm_share);
if (error)
- return error;
- smb_share_put(smp->sm_share, &scred);
+ goto out;
+ smb_share_put(smp->sm_share, scred);
+ SMB_LOCK();
+ dev = smp->sm_dev;
+ if (!dev)
+ panic("No private data for mount point");
+ sdp_trydestroy(dev);
mp->mnt_data = NULL;
-
- if (smp->sm_hash)
- free(smp->sm_hash, M_SMBFSHASH);
- sx_destroy(&smp->sm_hashlock);
-#ifdef SMBFS_USEZONE
- zfree(smbfsmount_zone, smp);
-#else
+ SMB_UNLOCK();
free(smp, M_SMBFSDATA);
-#endif
MNT_ILOCK(mp);
mp->mnt_flag &= ~MNT_LOCAL;
MNT_IUNLOCK(mp);
+out:
+ smbfs_free_scred(scred);
return error;
}
@@ -334,34 +319,32 @@
struct smbfattr fattr;
struct thread *td;
struct ucred *cred;
- struct smb_cred scred;
+ struct smb_cred *scred;
int error;
td = curthread;
cred = td->td_ucred;
- if (smp == NULL) {
- SMBERROR("smp == NULL (bug in umount)\n");
- vfs_mount_error(mp, "smp == NULL (bug in umount)");
- return EINVAL;
- }
if (smp->sm_root) {
*vpp = SMBTOV(smp->sm_root);
return vget(*vpp, LK_EXCLUSIVE | LK_RETRY, td);
}
- smb_makescred(&scred, td, cred);
- error = smbfs_smb_lookup(NULL, NULL, 0, &fattr, &scred);
+ scred = smbfs_malloc_scred();
+ smb_makescred(scred, td, cred);
+ error = smbfs_smb_lookup(NULL, NULL, 0, &fattr, scred);
if (error)
- return error;
- error = smbfs_nget(mp, NULL, "TheRooT", 7, &fattr, &vp);
+ goto out;
+ error = smbfs_nget(mp, NULL, NULL, 0, &fattr, &vp);
if (error)
- return error;
+ goto out;
ASSERT_VOP_LOCKED(vp, "smbfs_root");
vp->v_vflag |= VV_ROOT;
np = VTOSMB(vp);
smp->sm_root = np;
*vpp = vp;
- return 0;
+out:
+ smbfs_free_scred(scred);
+ return error;
}
/*
@@ -383,9 +366,6 @@
int
smbfs_init(struct vfsconf *vfsp)
{
-#ifdef SMBFS_USEZONE
- smbfsmount_zone = zinit("SMBFSMOUNT", sizeof(struct smbmount), 0, 0, 1);
-#endif
smbfs_pbuf_freecnt = nswbuf / 2 + 1;
SMBVDEBUG("done.\n");
return 0;
@@ -410,8 +390,8 @@
struct smbmount *smp = VFSTOSMBFS(mp);
struct smbnode *np = smp->sm_root;
struct smb_share *ssp = smp->sm_share;
- struct smb_cred scred;
- int error = 0;
+ struct smb_cred *scred;
+ int error;
if (np == NULL) {
vfs_mount_error(mp, "np == NULL");
@@ -419,14 +399,9 @@
}
sbp->f_iosize = SSTOVC(ssp)->vc_txmax; /* optimal transfer block size */
- smb_makescred(&scred, td, td->td_ucred);
-
- if (SMB_DIALECT(SSTOVC(ssp)) >= SMB_DIALECT_LANMAN2_0)
- error = smbfs_smb_statfs2(ssp, sbp, &scred);
- else
- error = smbfs_smb_statfs(ssp, sbp, &scred);
- if (error)
- return error;
- sbp->f_flags = 0; /* copy of mount exported flags */
- return 0;
+ scred = smbfs_malloc_scred();
+ smb_makescred(scred, td, td->td_ucred);
+ error = smbfs_smb_statfs(ssp, sbp, scred);
+ smbfs_free_scred(scred);
+ return (error);
}
Modified: trunk/sys/fs/smbfs/smbfs_vnops.c
===================================================================
--- trunk/sys/fs/smbfs/smbfs_vnops.c 2018-05-27 22:08:25 UTC (rev 10020)
+++ trunk/sys/fs/smbfs/smbfs_vnops.c 2018-05-27 22:08:55 UTC (rev 10021)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*-
* Copyright (c) 2000-2001 Boris Popov
* All rights reserved.
@@ -23,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/smbfs/smbfs_vnops.c 294263 2016-01-18 11:47:03Z ae $
*/
#include <sys/param.h>
#include <sys/systm.h>
@@ -153,7 +154,7 @@
{
struct vnode *vp = ap->a_vp;
struct smbnode *np = VTOSMB(vp);
- struct smb_cred scred;
+ struct smb_cred *scred;
struct vattr vattr;
int mode = ap->a_mode;
int error, accmode;
@@ -197,14 +198,15 @@
accmode = SMB_SM_DENYNONE|SMB_AM_OPENREAD;
if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
accmode = SMB_SM_DENYNONE|SMB_AM_OPENRW;
- smb_makescred(&scred, ap->a_td, ap->a_cred);
- error = smbfs_smb_open(np, accmode, &scred);
+ scred = smbfs_malloc_scred();
+ smb_makescred(scred, ap->a_td, ap->a_cred);
+ error = smbfs_smb_open(np, accmode, scred);
if (error) {
if (mode & FWRITE)
return EACCES;
else if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
accmode = SMB_SM_DENYNONE|SMB_AM_OPENREAD;
- error = smbfs_smb_open(np, accmode, &scred);
+ error = smbfs_smb_open(np, accmode, scred);
}
}
if (error == 0) {
@@ -212,6 +214,7 @@
vnode_create_vobject(ap->a_vp, vattr.va_size, ap->a_td);
}
smbfs_attr_cacheremove(vp);
+ smbfs_free_scred(scred);
return error;
}
@@ -228,12 +231,14 @@
struct vnode *vp = ap->a_vp;
struct thread *td = ap->a_td;
struct smbnode *np = VTOSMB(vp);
- struct smb_cred scred;
+ struct smb_cred *scred;
if (vp->v_type == VDIR && (np->n_flag & NOPEN) != 0 &&
np->n_dirseq != NULL) {
- smb_makescred(&scred, td, ap->a_cred);
- smbfs_findclose(np->n_dirseq, &scred);
+ scred = smbfs_malloc_scred();
+ smb_makescred(scred, td, ap->a_cred);
+ smbfs_findclose(np->n_dirseq, scred);
+ smbfs_free_scred(scred);
np->n_dirseq = NULL;
}
return 0;
@@ -254,7 +259,7 @@
struct smbnode *np = VTOSMB(vp);
struct vattr *va=ap->a_vap;
struct smbfattr fattr;
- struct smb_cred scred;
+ struct smb_cred *scred;
u_quad_t oldsize;
int error;
@@ -263,11 +268,13 @@
if (!error)
return 0;
SMBVDEBUG("not in the cache\n");
- smb_makescred(&scred, curthread, ap->a_cred);
+ scred = smbfs_malloc_scred();
+ smb_makescred(scred, curthread, ap->a_cred);
oldsize = np->n_size;
- error = smbfs_smb_lookup(np, NULL, 0, &fattr, &scred);
+ error = smbfs_smb_lookup(np, NULL, 0, &fattr, scred);
if (error) {
SMBVDEBUG("error %d\n", error);
+ smbfs_free_scred(scred);
return error;
}
smbfs_attr_cacheenter(vp, &fattr);
@@ -274,6 +281,7 @@
smbfs_attr_cachelookup(vp, va);
if (np->n_flag & NOPEN)
np->n_size = oldsize;
+ smbfs_free_scred(scred);
return 0;
}
@@ -289,7 +297,7 @@
struct smbnode *np = VTOSMB(vp);
struct vattr *vap = ap->a_vap;
struct timespec *mtime, *atime;
- struct smb_cred scred;
+ struct smb_cred *scred;
struct smb_share *ssp = np->n_mount->sm_share;
struct smb_vc *vcp = SSTOVC(ssp);
struct thread *td = curthread;
@@ -298,8 +306,6 @@
int old_n_dosattr;
SMBVDEBUG("\n");
- if (vap->va_flags != VNOVAL)
- return EOPNOTSUPP;
isreadonly = (vp->v_mount->mnt_flag & MNT_RDONLY);
/*
* Disallow write attempts if the filesystem is mounted read-only.
@@ -306,20 +312,41 @@
*/
if ((vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL ||
vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL ||
- vap->va_mode != (mode_t)VNOVAL) && isreadonly)
+ vap->va_mode != (mode_t)VNOVAL || vap->va_flags != VNOVAL) &&
+ isreadonly)
return EROFS;
- smb_makescred(&scred, td, ap->a_cred);
+
+ /*
+ * We only support setting four flags. Don't allow setting others.
+ *
+ * We map UF_READONLY to SMB_FA_RDONLY, unlike the MacOS X version
+ * of this code, which maps both UF_IMMUTABLE AND SF_IMMUTABLE to
+ * SMB_FA_RDONLY. The immutable flags have different semantics
+ * than readonly, which is the reason for the difference.
+ */
+ if (vap->va_flags != VNOVAL) {
+ if (vap->va_flags & ~(UF_HIDDEN|UF_SYSTEM|UF_ARCHIVE|
+ UF_READONLY))
+ return EINVAL;
+ }
+
+ scred = smbfs_malloc_scred();
+ smb_makescred(scred, td, ap->a_cred);
if (vap->va_size != VNOVAL) {
switch (vp->v_type) {
case VDIR:
- return EISDIR;
+ error = EISDIR;
+ goto out;
case VREG:
break;
default:
- return EINVAL;
+ error = EINVAL;
+ goto out;
};
- if (isreadonly)
- return EROFS;
+ if (isreadonly) {
+ error = EROFS;
+ goto out;
+ }
doclose = 0;
vnode_pager_setsize(vp, (u_long)vap->va_size);
tsize = np->n_size;
@@ -327,30 +354,66 @@
if ((np->n_flag & NOPEN) == 0) {
error = smbfs_smb_open(np,
SMB_SM_DENYNONE|SMB_AM_OPENRW,
- &scred);
+ scred);
if (error == 0)
doclose = 1;
}
if (error == 0)
- error = smbfs_smb_setfsize(np, vap->va_size, &scred);
+ error = smbfs_smb_setfsize(np,
+ (int64_t)vap->va_size, scred);
if (doclose)
- smbfs_smb_close(ssp, np->n_fid, NULL, &scred);
+ smbfs_smb_close(ssp, np->n_fid, NULL, scred);
if (error) {
np->n_size = tsize;
vnode_pager_setsize(vp, (u_long)tsize);
- return error;
+ goto out;
}
}
- if (vap->va_mode != (mode_t)VNOVAL) {
+ if ((vap->va_flags != VNOVAL) || (vap->va_mode != (mode_t)VNOVAL)) {
old_n_dosattr = np->n_dosattr;
- if (vap->va_mode & S_IWUSR)
- np->n_dosattr &= ~SMB_FA_RDONLY;
- else
- np->n_dosattr |= SMB_FA_RDONLY;
+
+ if (vap->va_mode != (mode_t)VNOVAL) {
+ if (vap->va_mode & S_IWUSR)
+ np->n_dosattr &= ~SMB_FA_RDONLY;
+ else
+ np->n_dosattr |= SMB_FA_RDONLY;
+ }
+
+ if (vap->va_flags != VNOVAL) {
+ if (vap->va_flags & UF_HIDDEN)
+ np->n_dosattr |= SMB_FA_HIDDEN;
+ else
+ np->n_dosattr &= ~SMB_FA_HIDDEN;
+
+ if (vap->va_flags & UF_SYSTEM)
+ np->n_dosattr |= SMB_FA_SYSTEM;
+ else
+ np->n_dosattr &= ~SMB_FA_SYSTEM;
+
+ if (vap->va_flags & UF_ARCHIVE)
+ np->n_dosattr |= SMB_FA_ARCHIVE;
+ else
+ np->n_dosattr &= ~SMB_FA_ARCHIVE;
+
+ /*
+ * We only support setting the immutable / readonly
+ * bit for regular files. According to comments in
+ * the MacOS X version of this code, supporting the
+ * readonly bit on directories doesn't do the same
+ * thing in Windows as in Unix.
+ */
+ if (vp->v_type == VREG) {
+ if (vap->va_flags & UF_READONLY)
+ np->n_dosattr |= SMB_FA_RDONLY;
+ else
+ np->n_dosattr &= ~SMB_FA_RDONLY;
+ }
+ }
+
if (np->n_dosattr != old_n_dosattr) {
- error = smbfs_smb_setpattr(np, np->n_dosattr, NULL, &scred);
+ error = smbfs_smb_setpattr(np, np->n_dosattr, NULL, scred);
if (error)
- return error;
+ goto out;
}
}
mtime = atime = NULL;
@@ -381,7 +444,7 @@
NULL);
if (!error) {
/* error = smbfs_smb_setfattrNT(np, 0,
- mtime, atime, &scred);
+ mtime, atime, scred);
VOP_GETATTR(vp, &vattr, ap->a_cred); */
if (mtime)
np->n_mtime = *mtime;
@@ -388,18 +451,18 @@
VOP_CLOSE(vp, FWRITE, ap->a_cred, td);
}
} else if ((vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS)) {
- error = smbfs_smb_setptime2(np, mtime, atime, 0, &scred);
-/* error = smbfs_smb_setpattrNT(np, 0, mtime, atime, &scred);*/
+ error = smbfs_smb_setptime2(np, mtime, atime, 0, scred);
+/* error = smbfs_smb_setpattrNT(np, 0, mtime, atime, scred);*/
} else if (SMB_DIALECT(vcp) >= SMB_DIALECT_LANMAN2_0) {
- error = smbfs_smb_setptime2(np, mtime, atime, 0, &scred);
+ error = smbfs_smb_setptime2(np, mtime, atime, 0, scred);
} else {
- error = smbfs_smb_setpattr(np, 0, mtime, &scred);
+ error = smbfs_smb_setpattr(np, 0, mtime, scred);
}
} else {
if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) {
- error = smbfs_smb_setfattrNT(np, 0, mtime, atime, &scred);
+ error = smbfs_smb_setfattrNT(np, 0, mtime, atime, scred);
} else if (SMB_DIALECT(vcp) >= SMB_DIALECT_LANMAN1_0) {
- error = smbfs_smb_setftime(np, mtime, atime, &scred);
+ error = smbfs_smb_setftime(np, mtime, atime, scred);
} else {
/*
* I have no idea how to handle this for core
@@ -417,6 +480,8 @@
smbfs_attr_cacheremove(vp); /* invalidate cache */
VOP_GETATTR(vp, vap, ap->a_cred);
np->n_mtime.tv_sec = vap->va_mtime.tv_sec;
+out:
+ smbfs_free_scred(scred);
return error;
}
/*
@@ -452,7 +517,8 @@
struct vnode *vp = ap->a_vp;
struct uio *uio = ap->a_uio;
- SMBVDEBUG("%d,ofs=%d,sz=%d\n",vp->v_type, (int)uio->uio_offset, uio->uio_resid);
+ SMBVDEBUG("%d,ofs=%jd,sz=%zd\n",vp->v_type, (intmax_t)uio->uio_offset,
+ uio->uio_resid);
if (vp->v_type != VREG)
return (EPERM);
return smbfs_writevnode(vp, uio, ap->a_cred,ap->a_ioflag);
@@ -481,7 +547,7 @@
struct vnode *vp;
struct vattr vattr;
struct smbfattr fattr;
- struct smb_cred scred;
+ struct smb_cred *scred;
char *name = cnp->cn_nameptr;
int nmlen = cnp->cn_namelen;
int error;
@@ -493,20 +559,23 @@
return EOPNOTSUPP;
if ((error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred)))
return error;
- smb_makescred(&scred, cnp->cn_thread, cnp->cn_cred);
+ scred = smbfs_malloc_scred();
+ smb_makescred(scred, cnp->cn_thread, cnp->cn_cred);
- error = smbfs_smb_create(dnp, name, nmlen, &scred);
+ error = smbfs_smb_create(dnp, name, nmlen, scred);
if (error)
- return error;
- error = smbfs_smb_lookup(dnp, name, nmlen, &fattr, &scred);
+ goto out;
+ error = smbfs_smb_lookup(dnp, name, nmlen, &fattr, scred);
if (error)
- return error;
+ goto out;
error = smbfs_nget(VTOVFS(dvp), dvp, name, nmlen, &fattr, &vp);
if (error)
- return error;
+ goto out;
*vpp = vp;
if (cnp->cn_flags & MAKEENTRY)
cache_enter(dvp, vp, cnp);
+out:
+ smbfs_free_scred(scred);
return error;
}
@@ -523,16 +592,18 @@
/* struct vnode *dvp = ap->a_dvp;*/
struct componentname *cnp = ap->a_cnp;
struct smbnode *np = VTOSMB(vp);
- struct smb_cred scred;
+ struct smb_cred *scred;
int error;
if (vp->v_type == VDIR || (np->n_flag & NOPEN) != 0 || vrefcnt(vp) != 1)
return EPERM;
- smb_makescred(&scred, cnp->cn_thread, cnp->cn_cred);
- error = smbfs_smb_delete(np, &scred);
+ scred = smbfs_malloc_scred();
+ smb_makescred(scred, cnp->cn_thread, cnp->cn_cred);
+ error = smbfs_smb_delete(np, scred);
if (error == 0)
np->n_flag |= NGONE;
cache_purge(vp);
+ smbfs_free_scred(scred);
return error;
}
@@ -556,10 +627,11 @@
struct vnode *tdvp = ap->a_tdvp;
struct componentname *tcnp = ap->a_tcnp;
/* struct componentname *fcnp = ap->a_fcnp;*/
- struct smb_cred scred;
+ struct smb_cred *scred;
u_int16_t flags = 6;
int error=0;
+ scred = NULL;
/* Check for cross-device rename */
if ((fvp->v_mount != tdvp->v_mount) ||
(tvp && (fvp->v_mount != tvp->v_mount))) {
@@ -577,10 +649,10 @@
} else if (fvp->v_type == VREG) {
flags |= 1;
} else {
- error = EINVAL;
- goto out;
+ return EINVAL;
}
- smb_makescred(&scred, tcnp->cn_thread, tcnp->cn_cred);
+ scred = smbfs_malloc_scred();
+ smb_makescred(scred, tcnp->cn_thread, tcnp->cn_cred);
/*
* It seems that Samba doesn't implement SMB_COM_MOVE call...
*/
@@ -587,7 +659,7 @@
#ifdef notnow
if (SMB_DIALECT(SSTOCN(smp->sm_share)) >= SMB_DIALECT_LANMAN1_0) {
error = smbfs_smb_move(VTOSMB(fvp), VTOSMB(tdvp),
- tcnp->cn_nameptr, tcnp->cn_namelen, flags, &scred);
+ tcnp->cn_nameptr, tcnp->cn_namelen, flags, scred);
} else
#endif
{
@@ -595,13 +667,13 @@
* We have to do the work atomicaly
*/
if (tvp && tvp != fvp) {
- error = smbfs_smb_delete(VTOSMB(tvp), &scred);
+ error = smbfs_smb_delete(VTOSMB(tvp), scred);
if (error)
goto out_cacherem;
VTOSMB(fvp)->n_flag |= NGONE;
}
error = smbfs_smb_rename(VTOSMB(fvp), VTOSMB(tdvp),
- tcnp->cn_nameptr, tcnp->cn_namelen, &scred);
+ tcnp->cn_nameptr, tcnp->cn_namelen, scred);
}
if (fvp->v_type == VDIR) {
@@ -614,6 +686,7 @@
smbfs_attr_cacheremove(fdvp);
smbfs_attr_cacheremove(tdvp);
out:
+ smbfs_free_scred(scred);
if (tdvp == tvp)
vrele(tdvp);
else
@@ -684,7 +757,7 @@
struct componentname *cnp = ap->a_cnp;
struct smbnode *dnp = VTOSMB(dvp);
struct vattr vattr;
- struct smb_cred scred;
+ struct smb_cred *scred;
struct smbfattr fattr;
char *name = cnp->cn_nameptr;
int len = cnp->cn_namelen;
@@ -695,18 +768,21 @@
}
if ((name[0] == '.') && ((len == 1) || ((len == 2) && (name[1] == '.'))))
return EEXIST;
- smb_makescred(&scred, cnp->cn_thread, cnp->cn_cred);
- error = smbfs_smb_mkdir(dnp, name, len, &scred);
+ scred = smbfs_malloc_scred();
+ smb_makescred(scred, cnp->cn_thread, cnp->cn_cred);
+ error = smbfs_smb_mkdir(dnp, name, len, scred);
if (error)
- return error;
- error = smbfs_smb_lookup(dnp, name, len, &fattr, &scred);
+ goto out;
+ error = smbfs_smb_lookup(dnp, name, len, &fattr, scred);
if (error)
- return error;
+ goto out;
error = smbfs_nget(VTOVFS(dvp), dvp, name, len, &fattr, &vp);
if (error)
- return error;
+ goto out;
*ap->a_vpp = vp;
- return 0;
+out:
+ smbfs_free_scred(scred);
+ return error;
}
/*
@@ -726,14 +802,15 @@
/* struct smbmount *smp = VTOSMBFS(vp);*/
struct smbnode *dnp = VTOSMB(dvp);
struct smbnode *np = VTOSMB(vp);
- struct smb_cred scred;
+ struct smb_cred *scred;
int error;
if (dvp == vp)
return EINVAL;
- smb_makescred(&scred, cnp->cn_thread, cnp->cn_cred);
- error = smbfs_smb_rmdir(np, &scred);
+ scred = smbfs_malloc_scred();
+ smb_makescred(scred, cnp->cn_thread, cnp->cn_cred);
+ error = smbfs_smb_rmdir(np, scred);
if (error == 0)
np->n_flag |= NGONE;
dnp->n_flag |= NMODIFIED;
@@ -740,6 +817,7 @@
smbfs_attr_cacheremove(dvp);
/* cache_purge(dvp);*/
cache_purge(vp);
+ smbfs_free_scred(scred);
return error;
}
@@ -935,7 +1013,7 @@
caddr_t id = (caddr_t)1 /* ap->a_id */;
/* int flags = ap->a_flags;*/
struct thread *td = curthread;
- struct smb_cred scred;
+ struct smb_cred *scred;
u_quad_t size;
off_t start, end, oadd;
int error, lkop;
@@ -985,7 +1063,8 @@
return EOVERFLOW;
end = start + oadd;
}
- smb_makescred(&scred, td, td->td_ucred);
+ scred = smbfs_malloc_scred();
+ smb_makescred(scred, td, td->td_ucred);
switch (ap->a_op) {
case F_SETLK:
switch (fl->l_type) {
@@ -999,6 +1078,7 @@
lkop = SMB_LOCK_RELEASE;
break;
default:
+ smbfs_free_scred(scred);
return EINVAL;
}
error = lf_advlock(ap, &vp->v_lockf, size);
@@ -1005,7 +1085,7 @@
if (error)
break;
lkop = SMB_LOCK_EXCL;
- error = smbfs_smb_lock(np, lkop, id, start, end, &scred);
+ error = smbfs_smb_lock(np, lkop, id, start, end, scred);
if (error) {
int oldtype = fl->l_type;
fl->l_type = F_UNLCK;
@@ -1016,14 +1096,16 @@
break;
case F_UNLCK:
lf_advlock(ap, &vp->v_lockf, size);
- error = smbfs_smb_lock(np, SMB_LOCK_RELEASE, id, start, end, &scred);
+ error = smbfs_smb_lock(np, SMB_LOCK_RELEASE, id, start, end, scred);
break;
case F_GETLK:
error = lf_advlock(ap, &vp->v_lockf, size);
break;
default:
+ smbfs_free_scred(scred);
return EINVAL;
}
+ smbfs_free_scred(scred);
return error;
}
@@ -1039,7 +1121,7 @@
* Backslash characters, being a path delimiter, are prohibited
* within a path component even for LOOKUP operations.
*/
- if (index(name, '\\') != NULL)
+ if (strchr(name, '\\') != NULL)
return ENOENT;
if (nameiop == LOOKUP)
@@ -1051,20 +1133,20 @@
*/
if (nmlen > 12)
return ENAMETOOLONG;
- cp = index(name, '.');
+ cp = strchr(name, '.');
if (cp == NULL)
return error;
if (cp == name || (cp - name) > 8)
return error;
- cp = index(cp + 1, '.');
+ cp = strchr(cp + 1, '.');
if (cp != NULL)
return error;
for (cp = name, i = 0; i < nmlen; i++, cp++)
- if (index(badchars83, *cp) != NULL)
+ if (strchr(badchars83, *cp) != NULL)
return error;
}
for (cp = name, i = 0; i < nmlen; i++, cp++)
- if (index(badchars, *cp) != NULL)
+ if (strchr(badchars, *cp) != NULL)
return error;
return 0;
}
@@ -1090,7 +1172,7 @@
struct mount *mp = dvp->v_mount;
struct smbnode *dnp;
struct smbfattr fattr, *fap;
- struct smb_cred scred;
+ struct smb_cred *scred;
char *name = cnp->cn_nameptr;
int flags = cnp->cn_flags;
int nameiop = cnp->cn_nameiop;
@@ -1105,18 +1187,6 @@
SMBFSERR("invalid '..'\n");
return EIO;
}
-#ifdef SMB_VNODE_DEBUG
- {
- char *cp, c;
-
- cp = name + nmlen;
- c = *cp;
- *cp = 0;
- SMBVDEBUG("%d '%s' in '%s' id=d\n", nameiop, name,
- VTOSMB(dvp)->n_name);
- *cp = c;
- }
-#endif
islastcn = flags & ISLASTCN;
if (islastcn && (mp->mnt_flag & MNT_RDONLY) && (nameiop != LOOKUP))
return EROFS;
@@ -1131,7 +1201,7 @@
if (error)
return ENOENT;
- error = cache_lookup(dvp, vpp, cnp);
+ error = cache_lookup(dvp, vpp, cnp, NULL, NULL);
SMBVDEBUG("cache_lookup returned %d\n", error);
if (error > 0)
return error;
@@ -1181,20 +1251,28 @@
*/
error = 0;
*vpp = NULLVP;
- smb_makescred(&scred, td, cnp->cn_cred);
+ scred = smbfs_malloc_scred();
+ smb_makescred(scred, td, cnp->cn_cred);
fap = &fattr;
if (flags & ISDOTDOT) {
- error = smbfs_smb_lookup(VTOSMB(dnp->n_parent), NULL, 0, fap,
- &scred);
- SMBVDEBUG("result of dotdot lookup: %d\n", error);
- } else {
- fap = &fattr;
- error = smbfs_smb_lookup(dnp, name, nmlen, fap, &scred);
-/* if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.')*/
+ /*
+ * In the DOTDOT case, don't go over-the-wire
+ * in order to request attributes. We already
+ * know it's a directory and subsequent call to
+ * smbfs_getattr() will restore consistency.
+ *
+ */
+ SMBVDEBUG("smbfs_smb_lookup: dotdot\n");
+ } else if (isdot) {
+ error = smbfs_smb_lookup(dnp, NULL, 0, fap, scred);
SMBVDEBUG("result of smbfs_smb_lookup: %d\n", error);
}
+ else {
+ error = smbfs_smb_lookup(dnp, name, nmlen, fap, scred);
+ SMBVDEBUG("result of smbfs_smb_lookup: %d\n", error);
+ }
if (error && error != ENOENT)
- return error;
+ goto out;
if (error) { /* entry not found */
/*
* Handle RENAME or CREATE case...
@@ -1202,11 +1280,13 @@
if ((nameiop == CREATE || nameiop == RENAME) && islastcn) {
error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred, td);
if (error)
- return error;
+ goto out;
cnp->cn_flags |= SAVENAME;
- return (EJUSTRETURN);
+ error = EJUSTRETURN;
+ goto out;
}
- return ENOENT;
+ error = ENOENT;
+ goto out;
}/* else {
SMBVDEBUG("Found entry %s with id=%d\n", fap->entryName, fap->dirEntNum);
}*/
@@ -1216,38 +1296,64 @@
if (nameiop == DELETE && islastcn) { /* delete last component */
error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred, td);
if (error)
- return error;
+ goto out;
if (isdot) {
VREF(dvp);
*vpp = dvp;
- return 0;
+ goto out;
}
error = smbfs_nget(mp, dvp, name, nmlen, fap, &vp);
if (error)
- return error;
+ goto out;
*vpp = vp;
cnp->cn_flags |= SAVENAME;
- return 0;
+ goto out;
}
if (nameiop == RENAME && islastcn) {
error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred, td);
if (error)
- return error;
- if (isdot)
- return EISDIR;
+ goto out;
+ if (isdot) {
+ error = EISDIR;
+ goto out;
+ }
error = smbfs_nget(mp, dvp, name, nmlen, fap, &vp);
if (error)
- return error;
+ goto out;
*vpp = vp;
cnp->cn_flags |= SAVENAME;
- return 0;
+ goto out;
}
if (flags & ISDOTDOT) {
+ mp = dvp->v_mount;
+ error = vfs_busy(mp, MBF_NOWAIT);
+ if (error != 0) {
+ vfs_ref(mp);
+ VOP_UNLOCK(dvp, 0);
+ error = vfs_busy(mp, 0);
+ vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
+ vfs_rel(mp);
+ if (error) {
+ error = ENOENT;
+ goto out;
+ }
+ if ((dvp->v_iflag & VI_DOOMED) != 0) {
+ vfs_unbusy(mp);
+ error = ENOENT;
+ goto out;
+ }
+ }
VOP_UNLOCK(dvp, 0);
error = smbfs_nget(mp, dvp, name, nmlen, NULL, &vp);
+ vfs_unbusy(mp);
vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
+ if ((dvp->v_iflag & VI_DOOMED) != 0) {
+ if (error == 0)
+ vput(vp);
+ error = ENOENT;
+ }
if (error)
- return error;
+ goto out;
*vpp = vp;
} else if (isdot) {
vref(dvp);
@@ -1255,7 +1361,7 @@
} else {
error = smbfs_nget(mp, dvp, name, nmlen, fap, &vp);
if (error)
- return error;
+ goto out;
*vpp = vp;
SMBVDEBUG("lookup: getnewvp!\n");
}
@@ -1263,5 +1369,7 @@
/* VTOSMB(*vpp)->n_ctime = VTOSMB(*vpp)->n_vattr.va_ctime.tv_sec;*/
cache_enter(dvp, *vpp, cnp);
}
- return 0;
+out:
+ smbfs_free_scred(scred);
+ return (error);
}
More information about the Midnightbsd-cvs
mailing list