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 /*      $NetBSD: smbfs_vfsops.c,v 1.34.2.1 2004/05/29 09:05:38 tron Exp $       */
    2 
    3 /*
    4  * Copyright (c) 2000-2001, Boris Popov
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. All advertising materials mentioning features or use of this software
   16  *    must display the following acknowledgement:
   17  *    This product includes software developed by Boris Popov.
   18  * 4. Neither the name of the author nor the names of any co-contributors
   19  *    may be used to endorse or promote products derived from this software
   20  *    without specific prior written permission.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   32  * SUCH DAMAGE.
   33  *
   34  * FreeBSD: src/sys/fs/smbfs/smbfs_vfsops.c,v 1.5 2001/12/13 13:08:34 sheldonh Exp
   35  */
   36 
   37 #include <sys/cdefs.h>
   38 __KERNEL_RCSID(0, "$NetBSD: smbfs_vfsops.c,v 1.34.2.1 2004/05/29 09:05:38 tron Exp $");
   39 
   40 #ifdef _KERNEL_OPT
   41 #include "opt_quota.h"
   42 #endif
   43 
   44 #include <sys/param.h>
   45 #include <sys/systm.h>
   46 #include <sys/proc.h>
   47 #include <sys/buf.h>
   48 #include <sys/kernel.h>
   49 #include <sys/sysctl.h>
   50 #include <sys/vnode.h>
   51 #include <sys/mount.h>
   52 #include <sys/stat.h>
   53 #include <sys/malloc.h>
   54 
   55 
   56 #include <netsmb/smb.h>
   57 #include <netsmb/smb_conn.h>
   58 #include <netsmb/smb_subr.h>
   59 #include <netsmb/smb_dev.h>
   60 
   61 #include <fs/smbfs/smbfs.h>
   62 #include <fs/smbfs/smbfs_node.h>
   63 #include <fs/smbfs/smbfs_subr.h>
   64 
   65 #ifndef __NetBSD__
   66 SYSCTL_NODE(_vfs, OID_AUTO, smbfs, CTLFLAG_RW, 0, "SMB/CIFS file system");
   67 SYSCTL_INT(_vfs_smbfs, OID_AUTO, version, CTLFLAG_RD, &smbfs_version, 0, "");
   68 #else
   69 SYSCTL_SETUP(sysctl_vfs_samba_setup, "sysctl vfs.samba subtree setup")
   70 {
   71         struct sysctlnode *smb = NULL;
   72 
   73         sysctl_createv(clog, 0, NULL, NULL,
   74                        CTLFLAG_PERMANENT,
   75                        CTLTYPE_NODE, "vfs", NULL,
   76                        NULL, 0, NULL, 0,
   77                        CTL_VFS, CTL_EOL);
   78         sysctl_createv(clog, 0, NULL, &smb,
   79                        CTLFLAG_PERMANENT,
   80                        CTLTYPE_NODE, "samba",
   81                        SYSCTL_DESCR("SMB/CIFS remote file system"),
   82                        NULL, 0, NULL, 0,
   83                        CTL_VFS, CTL_CREATE, CTL_EOL);
   84 
   85         if (smb != NULL)
   86                 sysctl_createv(clog, 0, &smb, NULL,
   87                                CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
   88                                CTLTYPE_INT, "version",
   89                                SYSCTL_DESCR("smbfs version"),
   90                                NULL, SMBFS_VERSION, NULL, 0,
   91                                CTL_CREATE, CTL_EOL);
   92 }
   93 #endif
   94 
   95 static MALLOC_DEFINE(M_SMBFSHASH, "SMBFS hash", "SMBFS hash table");
   96 
   97 int smbfs_mount(struct mount *, const char *, void *,
   98                 struct nameidata *, struct proc *);
   99 int smbfs_quotactl(struct mount *, int, uid_t, caddr_t, struct proc *);
  100 int smbfs_root(struct mount *, struct vnode **);
  101 static int smbfs_setroot(struct mount *);
  102 int smbfs_start(struct mount *, int, struct proc *);
  103 int smbfs_statfs(struct mount *, struct statfs *, struct proc *);
  104 int smbfs_sync(struct mount *, int, struct ucred *, struct proc *);
  105 int smbfs_unmount(struct mount *, int, struct proc *);
  106 void smbfs_init(void);
  107 void smbfs_reinit(void);
  108 void smbfs_done(void);
  109 
  110 int smbfs_vget(struct mount *mp, ino_t ino, struct vnode **vpp);
  111 int smbfs_fhtovp(struct mount *, struct fid *, struct vnode **);
  112 int smbfs_vptofh(struct vnode *, struct fid *);
  113 
  114 extern struct pool smbfs_node_pool;
  115 extern struct vnodeopv_desc smbfs_vnodeop_opv_desc;
  116 
  117 static const struct vnodeopv_desc *smbfs_vnodeopv_descs[] = {
  118         &smbfs_vnodeop_opv_desc,
  119         NULL,
  120 };
  121 
  122 struct vfsops smbfs_vfsops = {
  123         MOUNT_SMBFS,
  124         smbfs_mount,
  125         smbfs_start,
  126         smbfs_unmount,
  127         smbfs_root,
  128         smbfs_quotactl,
  129         smbfs_statfs,
  130         smbfs_sync,
  131         smbfs_vget,
  132         smbfs_fhtovp,
  133         smbfs_vptofh,
  134         smbfs_init,
  135         smbfs_reinit,
  136         smbfs_done,
  137         NULL,
  138         (int (*) (void)) eopnotsupp, /* mountroot */
  139         (int (*) (struct mount *, struct mbuf *, int *, 
  140                   struct ucred **)) eopnotsupp, /* checkexp */
  141         smbfs_vnodeopv_descs,
  142 };
  143 
  144 int
  145 smbfs_mount(struct mount *mp, const char *path, void *data,
  146         struct nameidata *ndp, struct proc *p)
  147 {
  148         struct smbfs_args args;           /* will hold data from mount request */
  149         struct smbmount *smp = NULL;
  150         struct smb_vc *vcp;
  151         struct smb_share *ssp = NULL;
  152         struct smb_cred scred;
  153         int error;
  154 
  155         if (mp->mnt_flag & MNT_GETARGS) {
  156                 smp = VFSTOSMBFS(mp);
  157                 if (smp == NULL)
  158                         return EIO;
  159                 return copyout(&smp->sm_args, data, sizeof(smp->sm_args));
  160         }
  161 
  162         if (mp->mnt_flag & MNT_UPDATE)
  163                 return EOPNOTSUPP;
  164 
  165         error = copyin(data, (caddr_t)&args, sizeof(struct smbfs_args));
  166         if (error)
  167                 return error;
  168 
  169         if (args.version != SMBFS_VERSION) {
  170                 SMBVDEBUG("mount version mismatch: kernel=%d, mount=%d\n",
  171                     SMBFS_VERSION, args.version);
  172                 return EINVAL;
  173         }
  174         smb_makescred(&scred, p, p->p_ucred);
  175         error = smb_dev2share(args.dev_fd, SMBM_EXEC, &scred, &ssp);
  176         if (error)
  177                 return error;
  178         smb_share_unlock(ssp, 0);       /* keep ref, but unlock */
  179         vcp = SSTOVC(ssp);
  180         mp->mnt_stat.f_iosize = vcp->vc_txmax;
  181 
  182         MALLOC(smp, struct smbmount *, sizeof(*smp), M_SMBFSDATA, M_WAITOK);
  183         memset(smp, 0, sizeof(*smp));
  184         mp->mnt_data = smp;
  185 
  186         smp->sm_hash = hashinit(desiredvnodes, HASH_LIST, 
  187                                 M_SMBFSHASH, M_WAITOK, &smp->sm_hashlen);
  188 
  189         lockinit(&smp->sm_hashlock, PVFS, "smbfsh", 0, 0);
  190         smp->sm_share = ssp;
  191         smp->sm_root = NULL;
  192         smp->sm_args = args;
  193         smp->sm_caseopt = args.caseopt;
  194         smp->sm_args.file_mode = (smp->sm_args.file_mode &
  195                             (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFREG;
  196         smp->sm_args.dir_mode  = (smp->sm_args.dir_mode &
  197                             (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFDIR;
  198 
  199         error = set_statfs_info(path, UIO_USERSPACE, NULL, UIO_USERSPACE,
  200             mp, p);
  201         if (error)
  202                 goto bad;
  203         memset(mp->mnt_stat.f_mntfromname, 0, MNAMELEN);
  204         snprintf(mp->mnt_stat.f_mntfromname, MNAMELEN,
  205             "//%s@%s/%s", vcp->vc_username, vcp->vc_srvname, ssp->ss_name);
  206 
  207         vfs_getnewfsid(mp);
  208         return (0);
  209 
  210 bad:
  211         if (smp) {
  212                 if (smp->sm_hash)
  213                         free(smp->sm_hash, M_SMBFSHASH);
  214 #ifdef __NetBSD__
  215                 lockmgr(&smp->sm_hashlock, LK_DRAIN, NULL);
  216 #else
  217                 lockdestroy(&smp->sm_hashlock);
  218 #endif
  219                 FREE(smp, M_SMBFSDATA);
  220         }
  221         if (ssp) {
  222                 smb_share_lock(smp->sm_share, 0);
  223                 smb_share_put(ssp, &scred);
  224         }
  225         return error;
  226 }
  227 
  228 /* Unmount the filesystem described by mp. */
  229 int
  230 smbfs_unmount(struct mount *mp, int mntflags, struct proc *p)
  231 {
  232         struct smbmount *smp = VFSTOSMBFS(mp);
  233         struct smb_cred scred;
  234         int error, flags;
  235 
  236         SMBVDEBUG("smbfs_unmount: flags=%04x\n", mntflags);
  237         flags = 0;
  238         if (mntflags & MNT_FORCE)
  239                 flags |= FORCECLOSE;
  240 #ifdef QUOTA
  241 #endif
  242         /* Drop the extra reference to root vnode. */
  243         if (smp->sm_root) {
  244                 vrele(SMBTOV(smp->sm_root));
  245                 smp->sm_root = NULL;
  246         }
  247 
  248         /* Flush all vnodes. */
  249         if ((error = vflush(mp, NULLVP, flags)) != 0)
  250                 return error;
  251 
  252         smb_makescred(&scred, p, p->p_ucred);
  253         smb_share_lock(smp->sm_share, 0);
  254         smb_share_put(smp->sm_share, &scred);
  255         mp->mnt_data = NULL;
  256 
  257         free(smp->sm_hash, M_SMBFSHASH);
  258 #ifdef __NetBSD__
  259         lockmgr(&smp->sm_hashlock, LK_DRAIN, NULL);
  260 #else
  261         lockdestroy(&smp->sm_hashlock);
  262 #endif
  263         FREE(smp, M_SMBFSDATA);
  264         return error;
  265 }
  266 
  267 /*
  268  * Get root vnode of the smbfs filesystem, and store it in sm_root.
  269  */
  270 static int
  271 smbfs_setroot(struct mount *mp)
  272 {
  273         struct smbmount *smp = VFSTOSMBFS(mp);
  274         struct vnode *vp;
  275         struct smbfattr fattr;
  276         struct proc *p = curproc;
  277         struct ucred *cred = p->p_ucred;
  278         struct smb_cred scred;
  279         int error;
  280 
  281         KASSERT(smp->sm_root == NULL);
  282 
  283         smb_makescred(&scred, p, cred);
  284         error = smbfs_smb_lookup(NULL, NULL, 0, &fattr, &scred);
  285         if (error)
  286                 return error;
  287         error = smbfs_nget(mp, NULL, "TheRooT", 7, &fattr, &vp);
  288         if (error)
  289                 return error;
  290 
  291         /*
  292          * Someone might have already set sm_root while we slept
  293          * in smb_lookup or malloc/getnewvnode.
  294          */
  295         if (smp->sm_root)
  296                 vput(vp);
  297         else {
  298                 vp->v_flag |= VROOT;
  299                 smp->sm_root = VTOSMB(vp);
  300 
  301                 /* Keep reference, but unlock */
  302                 VOP_UNLOCK(vp, 0);
  303         }
  304 
  305         return (0);
  306 }
  307 
  308 /* 
  309  * Return locked root vnode of a filesystem.
  310  */
  311 int
  312 smbfs_root(struct mount *mp, struct vnode **vpp)
  313 {
  314         struct smbmount *smp = VFSTOSMBFS(mp);
  315 
  316         if (__predict_false(!smp->sm_root)) {
  317                 int error = smbfs_setroot(mp);
  318                 if (error)
  319                         return (error);
  320                 /* fallthrough */
  321         }
  322 
  323         KASSERT(smp->sm_root != NULL && SMBTOV(smp->sm_root) != NULL);
  324         *vpp = SMBTOV(smp->sm_root);
  325         return vget(*vpp, LK_EXCLUSIVE | LK_RETRY);
  326 }
  327 
  328 /*
  329  * Make a filesystem operational.
  330  * Nothing to do at the moment.
  331  */
  332 /* ARGSUSED */
  333 int
  334 smbfs_start(mp, flags, p)
  335         struct mount *mp;
  336         int flags;
  337         struct proc *p;
  338 {
  339         SMBVDEBUG("flags=%04x\n", flags);
  340         return 0;
  341 }
  342 
  343 /*
  344  * Do operations associated with quotas, not supported
  345  */
  346 /* ARGSUSED */
  347 int
  348 smbfs_quotactl(mp, cmd, uid, arg, p)
  349         struct mount *mp;
  350         int cmd;
  351         uid_t uid;
  352         caddr_t arg;
  353         struct proc *p;
  354 {
  355         SMBVDEBUG("return EOPNOTSUPP\n");
  356         return EOPNOTSUPP;
  357 }
  358 
  359 void
  360 smbfs_init(void)
  361 {
  362         pool_init(&smbfs_node_pool, sizeof(struct smbnode), 0, 0, 0,
  363                 "smbfsnopl", &pool_allocator_nointr);
  364 
  365 #ifdef _LKM
  366         /* Need explicit attach if LKM */
  367         malloc_type_attach(M_SMBNODENAME);
  368         malloc_type_attach(M_SMBFSDATA);
  369         malloc_type_attach(M_SMBFSHASH);
  370 #endif
  371 
  372         SMBVDEBUG("init.\n");
  373 }
  374 
  375 void
  376 smbfs_reinit(void)
  377 {
  378 
  379         SMBVDEBUG("reinit.\n");
  380 }
  381 
  382 void
  383 smbfs_done(void)
  384 {
  385 
  386         pool_destroy(&smbfs_node_pool);
  387 
  388 #ifdef _LKM
  389         /* Need explicit detach if LKM */
  390         malloc_type_detach(M_SMBNODENAME);
  391         malloc_type_detach(M_SMBFSDATA);
  392         malloc_type_detach(M_SMBFSHASH);
  393 #endif
  394 
  395         SMBVDEBUG("done.\n");
  396 }
  397 
  398 /*
  399  * smbfs_statfs call
  400  */
  401 int
  402 smbfs_statfs(struct mount *mp, struct statfs *sbp, struct proc *p)
  403 {
  404         struct smbmount *smp = VFSTOSMBFS(mp);
  405         struct smb_share *ssp = smp->sm_share;
  406         struct smb_cred scred;
  407         int error = 0;
  408 
  409         sbp->f_iosize = SSTOVC(ssp)->vc_txmax;          /* optimal transfer block size */
  410         smb_makescred(&scred, p, p->p_ucred);
  411 
  412         if (SMB_DIALECT(SSTOVC(ssp)) >= SMB_DIALECT_LANMAN2_0)
  413                 error = smbfs_smb_statfs2(ssp, sbp, &scred);
  414         else
  415                 error = smbfs_smb_statfs(ssp, sbp, &scred);
  416         if (error)
  417                 return error;
  418         sbp->f_flags = 0;               /* copy of mount exported flags */
  419         sbp->f_owner = mp->mnt_stat.f_owner;    /* user that mounted the filesystem */
  420         sbp->f_type = 0;
  421         copy_statfs_info(sbp, mp);
  422         return 0;
  423 }
  424 
  425 /*
  426  * Flush out the buffer cache
  427  */
  428 int
  429 smbfs_sync(mp, waitfor, cred, p)
  430         struct mount *mp;
  431         int waitfor;
  432         struct ucred *cred;
  433         struct proc *p;
  434 {
  435         struct vnode *vp, *nvp;
  436         struct smbnode *np;
  437         int error, allerror = 0;
  438         /*
  439          * Force stale buffer cache information to be flushed.
  440          */
  441         simple_lock(&mntvnode_slock);
  442 loop:
  443         for (vp = LIST_FIRST(&mp->mnt_vnodelist); vp != NULL; vp = nvp) {
  444                 /*
  445                  * If the vnode that we are about to sync is no longer
  446                  * associated with this mount point, start over.
  447                  */
  448                 if (vp->v_mount != mp)
  449                         goto loop;
  450                 simple_lock(&vp->v_interlock);
  451                 nvp = LIST_NEXT(vp, v_mntvnodes);
  452                 np = VTOSMB(vp);
  453                 if ((vp->v_type == VNON || (np->n_flag & NMODIFIED) == 0) &&
  454                     LIST_EMPTY(&vp->v_dirtyblkhd) &&
  455                      vp->v_uobj.uo_npages == 0) {
  456                         simple_unlock(&vp->v_interlock);
  457                         continue;
  458                 }
  459                 simple_unlock(&mntvnode_slock);
  460                 error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK);
  461                 if (error) {
  462                         simple_lock(&mntvnode_slock);
  463                         if (error == ENOENT)
  464                                 goto loop;
  465                         continue;
  466                 }
  467                 error = VOP_FSYNC(vp, cred,
  468                     waitfor == MNT_WAIT ? FSYNC_WAIT : 0, 0, 0, p);
  469                 if (error)
  470                         allerror = error;
  471                 vput(vp);
  472                 simple_lock(&mntvnode_slock);
  473         }
  474         simple_unlock(&mntvnode_slock);
  475         return (allerror);
  476 }
  477 
  478 #if __FreeBSD_version < 400009
  479 /*
  480  * smbfs flat namespace lookup. Unsupported.
  481  */
  482 /* ARGSUSED */
  483 int smbfs_vget(mp, ino, vpp)
  484         struct mount *mp;
  485         ino_t ino;
  486         struct vnode **vpp;
  487 {
  488         return (EOPNOTSUPP);
  489 }
  490 
  491 /* ARGSUSED */
  492 int smbfs_fhtovp(mp, fhp, vpp)
  493         struct mount *mp;
  494         struct fid *fhp;
  495         struct vnode **vpp;
  496 {
  497         return (EINVAL);
  498 }
  499 
  500 /*
  501  * Vnode pointer to File handle, should never happen either
  502  */
  503 /* ARGSUSED */
  504 int
  505 smbfs_vptofh(vp, fhp)
  506         struct vnode *vp;
  507         struct fid *fhp;
  508 {
  509         return (EINVAL);
  510 }
  511 
  512 #endif /* __FreeBSD_version < 400009 */

Cache object: abed475af32f4af5e74e30d65f206b2c


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