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: releng/5.0/sys/fs/smbfs/smbfs_vfsops.c 103936 2002-09-25 02:32:42Z jeff $
   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 
   80 static int smbfs_mount(struct mount *, char *, caddr_t,
   81                         struct nameidata *, struct thread *);
   82 static int smbfs_quotactl(struct mount *, int, uid_t, caddr_t, struct thread *);
   83 static int smbfs_root(struct mount *, struct vnode **);
   84 static int smbfs_start(struct mount *, int, struct thread *);
   85 static int smbfs_statfs(struct mount *, struct statfs *, struct thread *);
   86 static int smbfs_sync(struct mount *, int, struct ucred *, struct thread *);
   87 static int smbfs_unmount(struct mount *, int, struct thread *);
   88 static int smbfs_init(struct vfsconf *vfsp);
   89 static int smbfs_uninit(struct vfsconf *vfsp);
   90 
   91 static struct vfsops smbfs_vfsops = {
   92         smbfs_mount,
   93         smbfs_start,
   94         smbfs_unmount,
   95         smbfs_root,
   96         smbfs_quotactl,
   97         smbfs_statfs,
   98         smbfs_sync,
   99         vfs_stdvget,
  100         vfs_stdfhtovp,          /* shouldn't happen */
  101         vfs_stdcheckexp,
  102         vfs_stdvptofh,          /* shouldn't happen */
  103         smbfs_init,
  104         smbfs_uninit,
  105         vfs_stdextattrctl
  106 };
  107 
  108 
  109 VFS_SET(smbfs_vfsops, smbfs, VFCF_NETWORK);
  110 
  111 MODULE_DEPEND(smbfs, netsmb, NSMB_VERSION, NSMB_VERSION, NSMB_VERSION);
  112 MODULE_DEPEND(smbfs, libiconv, 1, 1, 1);
  113 MODULE_DEPEND(smbfs, libmchain, 1, 1, 1);
  114 
  115 int smbfs_pbuf_freecnt = -1;    /* start out unlimited */
  116 
  117 static int
  118 smbfs_mount(struct mount *mp, char *path, caddr_t data, 
  119         struct nameidata *ndp, struct thread *td)
  120 {
  121         struct smbfs_args args;           /* will hold data from mount request */
  122         struct smbmount *smp = NULL;
  123         struct smb_vc *vcp;
  124         struct smb_share *ssp = NULL;
  125         struct vnode *vp;
  126         struct smb_cred scred;
  127 #ifndef FB_CURRENT
  128         size_t size;
  129 #endif
  130         int error;
  131         char *pc, *pe;
  132 
  133         if (data == NULL) {
  134                 printf("missing data argument\n");
  135                 return EINVAL;
  136         }
  137         if (mp->mnt_flag & MNT_UPDATE) {
  138                 printf("MNT_UPDATE not implemented");
  139                 return EOPNOTSUPP;
  140         }
  141         error = copyin(data, (caddr_t)&args, sizeof(struct smbfs_args));
  142         if (error)
  143                 return error;
  144         if (args.version != SMBFS_VERSION) {
  145                 printf("mount version mismatch: kernel=%d, mount=%d\n",
  146                     SMBFS_VERSION, args.version);
  147                 return EINVAL;
  148         }
  149         smb_makescred(&scred, td, td->td_ucred);
  150         error = smb_dev2share(args.dev, SMBM_EXEC, &scred, &ssp);
  151         if (error) {
  152                 printf("invalid device handle %d (%d)\n", args.dev, error);
  153                 return error;
  154         }
  155         vcp = SSTOVC(ssp);
  156         smb_share_unlock(ssp, 0, td);
  157         mp->mnt_stat.f_iosize = SSTOVC(ssp)->vc_txmax;
  158 
  159 #ifdef SMBFS_USEZONE
  160         smp = zalloc(smbfsmount_zone);
  161 #else
  162         MALLOC(smp, struct smbmount*, sizeof(*smp), M_SMBFSDATA, M_USE_RESERVE);
  163 #endif
  164         if (smp == NULL) {
  165                 printf("could not alloc smbmount\n");
  166                 error = ENOMEM;
  167                 goto bad;
  168         }
  169         bzero(smp, sizeof(*smp));
  170         mp->mnt_data = (qaddr_t)smp;
  171         smp->sm_hash = hashinit(desiredvnodes, M_SMBFSHASH, &smp->sm_hashlen);
  172         if (smp->sm_hash == NULL)
  173                 goto bad;
  174         lockinit(&smp->sm_hashlock, PVFS, "smbfsh", 0, 0);
  175         smp->sm_share = ssp;
  176         smp->sm_root = NULL;
  177         smp->sm_args = args;
  178         smp->sm_caseopt = args.caseopt;
  179         smp->sm_args.file_mode = (smp->sm_args.file_mode &
  180                             (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFREG;
  181         smp->sm_args.dir_mode  = (smp->sm_args.dir_mode &
  182                             (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFDIR;
  183 
  184 /*      simple_lock_init(&smp->sm_npslock);*/
  185 #ifndef FB_CURRENT
  186         error = copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
  187         if (error)
  188                 goto bad;
  189         bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
  190 #endif
  191         pc = mp->mnt_stat.f_mntfromname;
  192         pe = pc + sizeof(mp->mnt_stat.f_mntfromname);
  193         bzero(pc, MNAMELEN);
  194         *pc++ = '/';
  195         *pc++ = '/';
  196         pc=index(strncpy(pc, vcp->vc_username, pe - pc - 2), 0);
  197         if (pc < pe-1) {
  198                 *(pc++) = '@';
  199                 pc = index(strncpy(pc, vcp->vc_srvname, pe - pc - 2), 0);
  200                 if (pc < pe - 1) {
  201                         *(pc++) = '/';
  202                         strncpy(pc, ssp->ss_name, pe - pc - 2);
  203                 }
  204         }
  205         /* protect against invalid mount points */
  206         smp->sm_args.mount_point[sizeof(smp->sm_args.mount_point) - 1] = '\0';
  207         vfs_getnewfsid(mp);
  208         error = smbfs_root(mp, &vp);
  209         if (error)
  210                 goto bad;
  211         VOP_UNLOCK(vp, 0, td);
  212         SMBVDEBUG("root.v_usecount = %d\n", vrefcnt(vp));
  213 
  214 #ifdef DIAGNOSTICS
  215         SMBERROR("mp=%p\n", mp);
  216 #endif
  217         return error;
  218 bad:
  219         if (smp) {
  220                 if (smp->sm_hash)
  221                         free(smp->sm_hash, M_SMBFSHASH);
  222                 lockdestroy(&smp->sm_hashlock);
  223 #ifdef SMBFS_USEZONE
  224                 zfree(smbfsmount_zone, smp);
  225 #else
  226                 free(smp, M_SMBFSDATA);
  227 #endif
  228         }
  229         if (ssp)
  230                 smb_share_put(ssp, &scred);
  231         return error;
  232 }
  233 
  234 /* Unmount the filesystem described by mp. */
  235 static int
  236 smbfs_unmount(struct mount *mp, int mntflags, struct thread *td)
  237 {
  238         struct smbmount *smp = VFSTOSMBFS(mp);
  239         struct smb_cred scred;
  240         int error, flags;
  241 
  242         SMBVDEBUG("smbfs_unmount: flags=%04x\n", mntflags);
  243         flags = 0;
  244         if (mntflags & MNT_FORCE)
  245                 flags |= FORCECLOSE;
  246         /* There is 1 extra root vnode reference from smbfs_mount(). */
  247         error = vflush(mp, 1, flags);
  248         if (error)
  249                 return error;
  250         smb_makescred(&scred, td, td->td_ucred);
  251         smb_share_put(smp->sm_share, &scred);
  252         mp->mnt_data = (qaddr_t)0;
  253 
  254         if (smp->sm_hash)
  255                 free(smp->sm_hash, M_SMBFSHASH);
  256         lockdestroy(&smp->sm_hashlock);
  257 #ifdef SMBFS_USEZONE
  258         zfree(smbfsmount_zone, smp);
  259 #else
  260         free(smp, M_SMBFSDATA);
  261 #endif
  262         mp->mnt_flag &= ~MNT_LOCAL;
  263         return error;
  264 }
  265 
  266 /* 
  267  * Return locked root vnode of a filesystem
  268  */
  269 static int
  270 smbfs_root(struct mount *mp, struct vnode **vpp)
  271 {
  272         struct smbmount *smp = VFSTOSMBFS(mp);
  273         struct vnode *vp;
  274         struct smbnode *np;
  275         struct smbfattr fattr;
  276         struct thread *td = curthread;
  277         struct ucred *cred = td->td_ucred;
  278         struct smb_cred scred;
  279         int error;
  280 
  281         if (smp == NULL) {
  282                 SMBERROR("smp == NULL (bug in umount)\n");
  283                 return EINVAL;
  284         }
  285         if (smp->sm_root) {
  286                 *vpp = SMBTOV(smp->sm_root);
  287                 return vget(*vpp, LK_EXCLUSIVE | LK_RETRY, td);
  288         }
  289         smb_makescred(&scred, td, cred);
  290         error = smbfs_smb_lookup(NULL, NULL, 0, &fattr, &scred);
  291         if (error)
  292                 return error;
  293         error = smbfs_nget(mp, NULL, "TheRooT", 7, &fattr, &vp);
  294         if (error)
  295                 return error;
  296         ASSERT_VOP_LOCKED(vp, "smbfs_root");
  297         vp->v_vflag |= VV_ROOT;
  298         np = VTOSMB(vp);
  299         smp->sm_root = np;
  300         *vpp = vp;
  301         return 0;
  302 }
  303 
  304 /*
  305  * Vfs start routine, a no-op.
  306  */
  307 /* ARGSUSED */
  308 static int
  309 smbfs_start(mp, flags, td)
  310         struct mount *mp;
  311         int flags;
  312         struct thread *td;
  313 {
  314         SMBVDEBUG("flags=%04x\n", flags);
  315         return 0;
  316 }
  317 
  318 /*
  319  * Do operations associated with quotas, not supported
  320  */
  321 /* ARGSUSED */
  322 static int
  323 smbfs_quotactl(mp, cmd, uid, arg, td)
  324         struct mount *mp;
  325         int cmd;
  326         uid_t uid;
  327         caddr_t arg;
  328         struct thread *td;
  329 {
  330         SMBVDEBUG("return EOPNOTSUPP\n");
  331         return EOPNOTSUPP;
  332 }
  333 
  334 /*ARGSUSED*/
  335 int
  336 smbfs_init(struct vfsconf *vfsp)
  337 {
  338 #ifndef SMP
  339         int name[2];
  340         int olen, ncpu, plen, error;
  341 
  342         name[0] = CTL_HW;
  343         name[1] = HW_NCPU;
  344         error = kernel_sysctl(curthread, name, 2, &ncpu, &olen, NULL, 0, &plen);
  345         if (error == 0 && ncpu > 1)
  346                 printf("warning: smbfs module compiled without SMP support.");
  347 #endif
  348 
  349 #ifdef SMBFS_USEZONE
  350         smbfsmount_zone = zinit("SMBFSMOUNT", sizeof(struct smbmount), 0, 0, 1);
  351 #endif
  352         smbfs_pbuf_freecnt = nswbuf / 2 + 1;
  353         SMBVDEBUG("done.\n");
  354         return 0;
  355 }
  356 
  357 /*ARGSUSED*/
  358 int
  359 smbfs_uninit(struct vfsconf *vfsp)
  360 {
  361 
  362         SMBVDEBUG("done.\n");
  363         return 0;
  364 }
  365 
  366 /*
  367  * smbfs_statfs call
  368  */
  369 int
  370 smbfs_statfs(struct mount *mp, struct statfs *sbp, struct thread *td)
  371 {
  372         struct smbmount *smp = VFSTOSMBFS(mp);
  373         struct smbnode *np = smp->sm_root;
  374         struct smb_share *ssp = smp->sm_share;
  375         struct smb_cred scred;
  376         int error = 0;
  377 
  378         if (np == NULL)
  379                 return EINVAL;
  380         
  381         sbp->f_iosize = SSTOVC(ssp)->vc_txmax;          /* optimal transfer block size */
  382         sbp->f_spare2 = 0;                      /* placeholder */
  383         smb_makescred(&scred, td, td->td_ucred);
  384 
  385         if (SMB_DIALECT(SSTOVC(ssp)) >= SMB_DIALECT_LANMAN2_0)
  386                 error = smbfs_smb_statfs2(ssp, sbp, &scred);
  387         else
  388                 error = smbfs_smb_statfs(ssp, sbp, &scred);
  389         if (error)
  390                 return error;
  391         sbp->f_flags = 0;               /* copy of mount exported flags */
  392         if (sbp != &mp->mnt_stat) {
  393                 sbp->f_fsid = mp->mnt_stat.f_fsid;      /* filesystem id */
  394                 sbp->f_owner = mp->mnt_stat.f_owner;    /* user that mounted the filesystem */
  395                 sbp->f_type = mp->mnt_vfc->vfc_typenum; /* type of filesystem */
  396                 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
  397                 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
  398         }
  399         strncpy(sbp->f_fstypename, mp->mnt_vfc->vfc_name, MFSNAMELEN);
  400         return 0;
  401 }
  402 
  403 /*
  404  * Flush out the buffer cache
  405  */
  406 /* ARGSUSED */
  407 static int
  408 smbfs_sync(mp, waitfor, cred, td)
  409         struct mount *mp;
  410         int waitfor;
  411         struct ucred *cred;
  412         struct thread *td;
  413 {
  414         struct vnode *vp;
  415         int error, allerror = 0;
  416         /*
  417          * Force stale buffer cache information to be flushed.
  418          */
  419 loop:
  420         for (vp = TAILQ_FIRST(&mp->mnt_nvnodelist);
  421              vp != NULL;
  422              vp = TAILQ_NEXT(vp, v_nmntvnodes)) {
  423                 /*
  424                  * If the vnode that we are about to sync is no longer
  425                  * associated with this mount point, start over.
  426                  */
  427                 if (vp->v_mount != mp)
  428                         goto loop;
  429                 VI_LOCK(vp);
  430 #ifndef FB_RELENG3
  431                 if (VOP_ISLOCKED(vp, NULL) || TAILQ_EMPTY(&vp->v_dirtyblkhd) ||
  432 #else
  433                 if (VOP_ISLOCKED(vp) || TAILQ_EMPTY(&vp->v_dirtyblkhd) ||
  434 #endif
  435                     waitfor == MNT_LAZY) {
  436                         VI_UNLOCK(vp);
  437                         continue;
  438                 }
  439                 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td))
  440                         goto loop;
  441                 error = VOP_FSYNC(vp, cred, waitfor, td);
  442                 if (error)
  443                         allerror = error;
  444                 vput(vp);
  445         }
  446         return (allerror);
  447 }
  448 

Cache object: f419320e7d248995e3b63f50a19faea7


[ 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.