The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/smbfs/smbfs_vfsops.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2000-2001, Boris Popov
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 3. All advertising materials mentioning features or use of this software
   14  *    must display the following acknowledgement:
   15  *    This product includes software developed by Boris Popov.
   16  * 4. Neither the name of the author nor the names of any co-contributors
   17  *    may be used to endorse or promote products derived from this software
   18  *    without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  *
   32  * $FreeBSD$
   33  */
   34 #include "opt_netsmb.h"
   35 #ifndef NETSMB
   36 #error "SMBFS requires option NETSMB"
   37 #endif
   38 
   39 #include <sys/param.h>
   40 #include <sys/systm.h>
   41 #include <sys/proc.h>
   42 #include <sys/bio.h>
   43 #include <sys/buf.h>
   44 #include <sys/kernel.h>
   45 #include <sys/sysctl.h>
   46 #include <sys/vnode.h>
   47 #include <sys/mount.h>
   48 #include <sys/stat.h>
   49 #include <sys/malloc.h>
   50 #include <sys/module.h>
   51 
   52 
   53 #include <netsmb/smb.h>
   54 #include <netsmb/smb_conn.h>
   55 #include <netsmb/smb_subr.h>
   56 #include <netsmb/smb_dev.h>
   57 
   58 #include <fs/smbfs/smbfs.h>
   59 #include <fs/smbfs/smbfs_node.h>
   60 #include <fs/smbfs/smbfs_subr.h>
   61 
   62 int smbfs_debuglevel = 0;
   63 
   64 static int smbfs_version = SMBFS_VERSION;
   65 
   66 #ifdef SMBFS_USEZONE
   67 #include <vm/vm.h>
   68 #include <vm/vm_extern.h>
   69 
   70 vm_zone_t smbfsmount_zone;
   71 #endif
   72 
   73 SYSCTL_NODE(_vfs, OID_AUTO, smbfs, CTLFLAG_RW, 0, "SMB/CIFS filesystem");
   74 SYSCTL_INT(_vfs_smbfs, OID_AUTO, version, CTLFLAG_RD, &smbfs_version, 0, "");
   75 SYSCTL_INT(_vfs_smbfs, OID_AUTO, debuglevel, CTLFLAG_RW, &smbfs_debuglevel, 0, "");
   76 
   77 static MALLOC_DEFINE(M_SMBFSHASH, "SMBFS hash", "SMBFS hash table");
   78 
   79 static vfs_init_t       smbfs_init;
   80 static vfs_uninit_t     smbfs_uninit;
   81 static vfs_omount_t     smbfs_omount;
   82 static vfs_start_t      smbfs_start;
   83 static vfs_root_t       smbfs_root;
   84 static vfs_quotactl_t   smbfs_quotactl;
   85 static vfs_statfs_t     smbfs_statfs;
   86 static vfs_unmount_t    smbfs_unmount;
   87 
   88 static struct vfsops smbfs_vfsops = {
   89         .vfs_init =             smbfs_init,
   90         .vfs_omount =           smbfs_omount,
   91         .vfs_quotactl =         smbfs_quotactl,
   92         .vfs_root =             smbfs_root,
   93         .vfs_start =            smbfs_start,
   94         .vfs_statfs =           smbfs_statfs,
   95         .vfs_sync =             vfs_stdsync,
   96         .vfs_uninit =           smbfs_uninit,
   97         .vfs_unmount =          smbfs_unmount,
   98 };
   99 
  100 
  101 VFS_SET(smbfs_vfsops, smbfs, VFCF_NETWORK);
  102 
  103 MODULE_DEPEND(smbfs, netsmb, NSMB_VERSION, NSMB_VERSION, NSMB_VERSION);
  104 MODULE_DEPEND(smbfs, libiconv, 1, 1, 2);
  105 MODULE_DEPEND(smbfs, libmchain, 1, 1, 1);
  106 
  107 int smbfs_pbuf_freecnt = -1;    /* start out unlimited */
  108 
  109 static int
  110 smbfs_omount(struct mount *mp, char *path, caddr_t data, struct thread *td)
  111 {
  112         struct smbfs_args args;           /* will hold data from mount request */
  113         struct smbmount *smp = NULL;
  114         struct smb_vc *vcp;
  115         struct smb_share *ssp = NULL;
  116         struct vnode *vp;
  117         struct smb_cred scred;
  118         int error;
  119         char *pc, *pe;
  120 
  121         if (data == NULL) {
  122                 printf("missing data argument\n");
  123                 return EINVAL;
  124         }
  125         if (mp->mnt_flag & MNT_UPDATE) {
  126                 printf("MNT_UPDATE not implemented");
  127                 return EOPNOTSUPP;
  128         }
  129         error = copyin(data, (caddr_t)&args, sizeof(struct smbfs_args));
  130         if (error)
  131                 return error;
  132         if (args.version != SMBFS_VERSION) {
  133                 printf("mount version mismatch: kernel=%d, mount=%d\n",
  134                     SMBFS_VERSION, args.version);
  135                 return EINVAL;
  136         }
  137         smb_makescred(&scred, td, td->td_ucred);
  138         error = smb_dev2share(args.dev, SMBM_EXEC, &scred, &ssp);
  139         if (error) {
  140                 printf("invalid device handle %d (%d)\n", args.dev, error);
  141                 return error;
  142         }
  143         vcp = SSTOVC(ssp);
  144         smb_share_unlock(ssp, 0, td);
  145         mp->mnt_stat.f_iosize = SSTOVC(ssp)->vc_txmax;
  146 
  147 #ifdef SMBFS_USEZONE
  148         smp = zalloc(smbfsmount_zone);
  149 #else
  150         MALLOC(smp, struct smbmount*, sizeof(*smp), M_SMBFSDATA,
  151             M_WAITOK|M_USE_RESERVE);
  152 #endif
  153         if (smp == NULL) {
  154                 printf("could not alloc smbmount\n");
  155                 error = ENOMEM;
  156                 goto bad;
  157         }
  158         bzero(smp, sizeof(*smp));
  159         mp->mnt_data = (qaddr_t)smp;
  160         smp->sm_hash = hashinit(desiredvnodes, M_SMBFSHASH, &smp->sm_hashlen);
  161         if (smp->sm_hash == NULL)
  162                 goto bad;
  163         lockinit(&smp->sm_hashlock, PVFS, "smbfsh", 0, 0);
  164         smp->sm_share = ssp;
  165         smp->sm_root = NULL;
  166         smp->sm_args = args;
  167         smp->sm_caseopt = args.caseopt;
  168         smp->sm_args.file_mode = (smp->sm_args.file_mode &
  169                             (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFREG;
  170         smp->sm_args.dir_mode  = (smp->sm_args.dir_mode &
  171                             (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFDIR;
  172 
  173 /*      simple_lock_init(&smp->sm_npslock);*/
  174         pc = mp->mnt_stat.f_mntfromname;
  175         pe = pc + sizeof(mp->mnt_stat.f_mntfromname);
  176         bzero(pc, MNAMELEN);
  177         *pc++ = '/';
  178         *pc++ = '/';
  179         pc=index(strncpy(pc, vcp->vc_username, pe - pc - 2), 0);
  180         if (pc < pe-1) {
  181                 *(pc++) = '@';
  182                 pc = index(strncpy(pc, vcp->vc_srvname, pe - pc - 2), 0);
  183                 if (pc < pe - 1) {
  184                         *(pc++) = '/';
  185                         strncpy(pc, ssp->ss_name, pe - pc - 2);
  186                 }
  187         }
  188         /* protect against invalid mount points */
  189         smp->sm_args.mount_point[sizeof(smp->sm_args.mount_point) - 1] = '\0';
  190         vfs_getnewfsid(mp);
  191         error = smbfs_root(mp, &vp, td);
  192         if (error)
  193                 goto bad;
  194         VOP_UNLOCK(vp, 0, td);
  195         SMBVDEBUG("root.v_usecount = %d\n", vrefcnt(vp));
  196 
  197 #ifdef DIAGNOSTICS
  198         SMBERROR("mp=%p\n", mp);
  199 #endif
  200         return error;
  201 bad:
  202         if (smp) {
  203                 if (smp->sm_hash)
  204                         free(smp->sm_hash, M_SMBFSHASH);
  205                 lockdestroy(&smp->sm_hashlock);
  206 #ifdef SMBFS_USEZONE
  207                 zfree(smbfsmount_zone, smp);
  208 #else
  209                 free(smp, M_SMBFSDATA);
  210 #endif
  211         }
  212         if (ssp)
  213                 smb_share_put(ssp, &scred);
  214         return error;
  215 }
  216 
  217 /* Unmount the filesystem described by mp. */
  218 static int
  219 smbfs_unmount(struct mount *mp, int mntflags, struct thread *td)
  220 {
  221         struct smbmount *smp = VFSTOSMBFS(mp);
  222         struct smb_cred scred;
  223         int error, flags;
  224 
  225         SMBVDEBUG("smbfs_unmount: flags=%04x\n", mntflags);
  226         flags = 0;
  227         if (mntflags & MNT_FORCE)
  228                 flags |= FORCECLOSE;
  229         /*
  230          * Keep trying to flush the vnode list for the mount while 
  231          * some are still busy and we are making progress towards
  232          * making them not busy. This is needed because smbfs vnodes
  233          * reference their parent directory but may appear after their
  234          * parent in the list; one pass over the vnode list is not
  235          * sufficient in this case.
  236          */
  237         do {
  238                 smp->sm_didrele = 0;
  239                 /* There is 1 extra root vnode reference from smbfs_mount(). */
  240                 error = vflush(mp, 1, flags, td);
  241         } while (error == EBUSY && smp->sm_didrele != 0);
  242         if (error)
  243                 return error;
  244         smb_makescred(&scred, td, td->td_ucred);
  245         smb_share_put(smp->sm_share, &scred);
  246         mp->mnt_data = (qaddr_t)0;
  247 
  248         if (smp->sm_hash)
  249                 free(smp->sm_hash, M_SMBFSHASH);
  250         lockdestroy(&smp->sm_hashlock);
  251 #ifdef SMBFS_USEZONE
  252         zfree(smbfsmount_zone, smp);
  253 #else
  254         free(smp, M_SMBFSDATA);
  255 #endif
  256         mp->mnt_flag &= ~MNT_LOCAL;
  257         return error;
  258 }
  259 
  260 /* 
  261  * Return locked root vnode of a filesystem
  262  */
  263 static int
  264 smbfs_root(struct mount *mp, struct vnode **vpp, struct thread *td)
  265 {
  266         struct smbmount *smp = VFSTOSMBFS(mp);
  267         struct vnode *vp;
  268         struct smbnode *np;
  269         struct smbfattr fattr;
  270         struct ucred *cred = td->td_ucred;
  271         struct smb_cred scred;
  272         int error;
  273 
  274         if (smp == NULL) {
  275                 SMBERROR("smp == NULL (bug in umount)\n");
  276                 return EINVAL;
  277         }
  278         if (smp->sm_root) {
  279                 *vpp = SMBTOV(smp->sm_root);
  280                 return vget(*vpp, LK_EXCLUSIVE | LK_RETRY, td);
  281         }
  282         smb_makescred(&scred, td, cred);
  283         error = smbfs_smb_lookup(NULL, NULL, 0, &fattr, &scred);
  284         if (error)
  285                 return error;
  286         error = smbfs_nget(mp, NULL, "TheRooT", 7, &fattr, &vp);
  287         if (error)
  288                 return error;
  289         ASSERT_VOP_LOCKED(vp, "smbfs_root");
  290         vp->v_vflag |= VV_ROOT;
  291         np = VTOSMB(vp);
  292         smp->sm_root = np;
  293         *vpp = vp;
  294         return 0;
  295 }
  296 
  297 /*
  298  * Vfs start routine, a no-op.
  299  */
  300 /* ARGSUSED */
  301 static int
  302 smbfs_start(mp, flags, td)
  303         struct mount *mp;
  304         int flags;
  305         struct thread *td;
  306 {
  307         SMBVDEBUG("flags=%04x\n", flags);
  308         return 0;
  309 }
  310 
  311 /*
  312  * Do operations associated with quotas, not supported
  313  */
  314 /* ARGSUSED */
  315 static int
  316 smbfs_quotactl(mp, cmd, uid, arg, td)
  317         struct mount *mp;
  318         int cmd;
  319         uid_t uid;
  320         caddr_t arg;
  321         struct thread *td;
  322 {
  323         SMBVDEBUG("return EOPNOTSUPP\n");
  324         return EOPNOTSUPP;
  325 }
  326 
  327 /*ARGSUSED*/
  328 int
  329 smbfs_init(struct vfsconf *vfsp)
  330 {
  331 #ifdef SMBFS_USEZONE
  332         smbfsmount_zone = zinit("SMBFSMOUNT", sizeof(struct smbmount), 0, 0, 1);
  333 #endif
  334         smbfs_pbuf_freecnt = nswbuf / 2 + 1;
  335         SMBVDEBUG("done.\n");
  336         return 0;
  337 }
  338 
  339 /*ARGSUSED*/
  340 int
  341 smbfs_uninit(struct vfsconf *vfsp)
  342 {
  343 
  344         SMBVDEBUG("done.\n");
  345         return 0;
  346 }
  347 
  348 /*
  349  * smbfs_statfs call
  350  */
  351 int
  352 smbfs_statfs(struct mount *mp, struct statfs *sbp, struct thread *td)
  353 {
  354         struct smbmount *smp = VFSTOSMBFS(mp);
  355         struct smbnode *np = smp->sm_root;
  356         struct smb_share *ssp = smp->sm_share;
  357         struct smb_cred scred;
  358         int error = 0;
  359 
  360         if (np == NULL)
  361                 return EINVAL;
  362         
  363         sbp->f_iosize = SSTOVC(ssp)->vc_txmax;          /* optimal transfer block size */
  364         smb_makescred(&scred, td, td->td_ucred);
  365 
  366         if (SMB_DIALECT(SSTOVC(ssp)) >= SMB_DIALECT_LANMAN2_0)
  367                 error = smbfs_smb_statfs2(ssp, sbp, &scred);
  368         else
  369                 error = smbfs_smb_statfs(ssp, sbp, &scred);
  370         if (error)
  371                 return error;
  372         sbp->f_flags = 0;               /* copy of mount exported flags */
  373         if (sbp != &mp->mnt_stat) {
  374                 sbp->f_fsid = mp->mnt_stat.f_fsid;      /* filesystem id */
  375                 sbp->f_owner = mp->mnt_stat.f_owner;    /* user that mounted the filesystem */
  376                 sbp->f_type = mp->mnt_vfc->vfc_typenum; /* type of filesystem */
  377                 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
  378                 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
  379         }
  380         strncpy(sbp->f_fstypename, mp->mnt_vfc->vfc_name, MFSNAMELEN);
  381         return 0;
  382 }

Cache object: 63090b7fbf0f71781d6701bf4d8af065


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.