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/bsd/vm/dp_backing_file.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-2007 Apple Inc. All rights reserved.
    3  *
    4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
    5  * 
    6  * This file contains Original Code and/or Modifications of Original Code
    7  * as defined in and that are subject to the Apple Public Source License
    8  * Version 2.0 (the 'License'). You may not use this file except in
    9  * compliance with the License. The rights granted to you under the License
   10  * may not be used to create, or enable the creation or redistribution of,
   11  * unlawful or unlicensed copies of an Apple operating system, or to
   12  * circumvent, violate, or enable the circumvention or violation of, any
   13  * terms of an Apple operating system software license agreement.
   14  * 
   15  * Please obtain a copy of the License at
   16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
   17  * 
   18  * The Original Code and all software distributed under the License are
   19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   23  * Please see the License for the specific language governing rights and
   24  * limitations under the License.
   25  * 
   26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
   27  */
   28 /*
   29  * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce
   30  * support for mandatory and extensible security protections.  This notice
   31  * is included in support of clause 2.2 (b) of the Apple Public License,
   32  * Version 2.0.
   33  */
   34 
   35 #include <sys/param.h>
   36 #include <sys/systm.h>
   37 #include <sys/lock.h>
   38 #include <sys/proc_internal.h>
   39 #include <sys/kauth.h>
   40 #include <sys/buf.h>
   41 #include <sys/uio.h>
   42 #include <sys/vnode_internal.h>
   43 #include <sys/namei.h>
   44 #include <sys/ubc_internal.h>
   45 #include <sys/malloc.h>
   46 
   47 #include <default_pager/default_pager_types.h>
   48 #include <default_pager/default_pager_object.h>
   49 
   50 #include <bsm/audit_kernel.h>
   51 #include <bsm/audit_kevents.h>
   52 
   53 #include <mach/mach_types.h>
   54 #include <mach/host_priv.h>
   55 #include <mach/mach_traps.h>
   56 #include <mach/boolean.h>
   57 
   58 #include <kern/kern_types.h>
   59 #include <kern/host.h>
   60 #include <kern/task.h>
   61 #include <kern/zalloc.h>
   62 #include <kern/kalloc.h>
   63 #include <kern/assert.h>
   64 
   65 #include <libkern/libkern.h>
   66 
   67 #include <vm/vm_pageout.h>
   68 #include <vm/vm_map.h>
   69 #include <vm/vm_kern.h>
   70 #include <vm/vnode_pager.h>
   71 #include <vm/vm_protos.h>
   72 #if CONFIG_MACF
   73 #include <security/mac_framework.h>
   74 #endif
   75 
   76 /*
   77  * temporary support for delayed instantiation
   78  * of default_pager
   79  */
   80 int default_pager_init_flag = 0;
   81 
   82 struct bs_map           bs_port_table[MAX_BACKING_STORE] = { 
   83         {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
   84         {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
   85         {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
   86         {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
   87         {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
   88         {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
   89         {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
   90         {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
   91         {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
   92         {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}};
   93 
   94 /* ###################################################### */
   95 
   96 
   97 /*
   98  *      Routine:        macx_backing_store_recovery
   99  *      Function:
  100  *              Syscall interface to set a tasks privilege
  101  *              level so that it is not subject to 
  102  *              macx_backing_store_suspend
  103  */
  104 int
  105 macx_backing_store_recovery(
  106         struct macx_backing_store_recovery_args *args)
  107 {
  108         int             pid = args->pid;
  109         int             error;
  110         struct proc     *p =  current_proc();
  111         boolean_t       funnel_state;
  112 
  113         funnel_state = thread_funnel_set(kernel_flock, TRUE);
  114         if ((error = suser(kauth_cred_get(), 0)))
  115                 goto backing_store_recovery_return;
  116 
  117         /* for now restrict backing_store_recovery */
  118         /* usage to only present task */
  119         if(pid != proc_selfpid()) {
  120                 error = EINVAL;
  121                 goto backing_store_recovery_return;
  122         }
  123 
  124         task_backing_store_privileged(p->task);
  125 
  126 backing_store_recovery_return:
  127         (void) thread_funnel_set(kernel_flock, FALSE);
  128         return(error);
  129 }
  130 
  131 /*
  132  *      Routine:        macx_backing_store_suspend
  133  *      Function:
  134  *              Syscall interface to stop new demand for 
  135  *              backing store when backing store is low
  136  */
  137 
  138 int
  139 macx_backing_store_suspend(
  140         struct macx_backing_store_suspend_args *args)
  141 {
  142         boolean_t       suspend = args->suspend;
  143         int             error;
  144         boolean_t       funnel_state;
  145 
  146         funnel_state = thread_funnel_set(kernel_flock, TRUE);
  147         if ((error = suser(kauth_cred_get(), 0)))
  148                 goto backing_store_suspend_return;
  149 
  150         vm_backing_store_disable(suspend);
  151 
  152 backing_store_suspend_return:
  153         (void) thread_funnel_set(kernel_flock, FALSE);
  154         return(error);
  155 }
  156 
  157 /*
  158  *      Routine:        macx_swapon
  159  *      Function:
  160  *              Syscall interface to add a file to backing store
  161  */
  162 int
  163 macx_swapon(
  164         struct macx_swapon_args *args)
  165 {
  166         int                     size = args->size;
  167         vnode_t                 vp = (vnode_t)NULL; 
  168         struct nameidata        nd, *ndp;
  169         register int            error;
  170         kern_return_t           kr;
  171         mach_port_t             backing_store;
  172         memory_object_default_t default_pager;
  173         int                     i;
  174         boolean_t               funnel_state;
  175         off_t                   file_size;
  176         vfs_context_t           ctx = vfs_context_current();
  177         struct proc             *p =  current_proc();
  178 
  179         AUDIT_MACH_SYSCALL_ENTER(AUE_SWAPON);
  180         AUDIT_ARG(value, args->priority);
  181 
  182         funnel_state = thread_funnel_set(kernel_flock, TRUE);
  183         ndp = &nd;
  184 
  185         if ((error = suser(kauth_cred_get(), 0)))
  186                 goto swapon_bailout;
  187 
  188         if(default_pager_init_flag == 0) {
  189                 start_def_pager(NULL);
  190                 default_pager_init_flag = 1;
  191         }
  192 
  193         /*
  194          * Get a vnode for the paging area.
  195          */
  196         NDINIT(ndp, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNPATH1,
  197                ((IS_64BIT_PROCESS(p)) ? UIO_USERSPACE64 : UIO_USERSPACE32),
  198                CAST_USER_ADDR_T(args->filename), ctx);
  199 
  200         if ((error = namei(ndp)))
  201                 goto swapon_bailout;
  202         nameidone(ndp);
  203         vp = ndp->ni_vp;
  204 
  205         if (vp->v_type != VREG) {
  206                 error = EINVAL;
  207                 goto swapon_bailout;
  208         }
  209 
  210         /* get file size */
  211         if ((error = vnode_size(vp, &file_size, ctx)) != 0)
  212                 goto swapon_bailout;
  213 #if CONFIG_MACF
  214         vnode_lock(vp);
  215         error = mac_system_check_swapon(vfs_context_ucred(ctx), vp);
  216         vnode_unlock(vp);
  217         if (error)
  218                 goto swapon_bailout;
  219 #endif
  220 
  221         /* resize to desired size if it's too small */
  222         if ((file_size < (off_t)size) && ((error = vnode_setsize(vp, (off_t)size, 0, ctx)) != 0))
  223                 goto swapon_bailout;
  224 
  225         /* add new backing store to list */
  226         i = 0;
  227         while(bs_port_table[i].vp != 0) {
  228                 if(i == MAX_BACKING_STORE)
  229                         break;
  230                 i++;
  231         }
  232         if(i == MAX_BACKING_STORE) {
  233                 error = ENOMEM;
  234                 goto swapon_bailout;
  235         }
  236 
  237         /* remember the vnode. This vnode has namei() reference */
  238         bs_port_table[i].vp = vp;
  239         
  240         /*
  241          * Look to see if we are already paging to this file.
  242          */
  243         /* make certain the copy send of kernel call will work */
  244         default_pager = MEMORY_OBJECT_DEFAULT_NULL;
  245         kr = host_default_memory_manager(host_priv_self(), &default_pager, 0);
  246         if(kr != KERN_SUCCESS) {
  247            error = EAGAIN;
  248            bs_port_table[i].vp = 0;
  249            goto swapon_bailout;
  250         }
  251 
  252         kr = default_pager_backing_store_create(default_pager, 
  253                                         -1, /* default priority */
  254                                         0, /* default cluster size */
  255                                         &backing_store);
  256         memory_object_default_deallocate(default_pager);
  257 
  258         if(kr != KERN_SUCCESS) {
  259            error = ENOMEM;
  260            bs_port_table[i].vp = 0;
  261            goto swapon_bailout;
  262         }
  263 
  264         /*
  265          * NOTE: we are able to supply PAGE_SIZE here instead of
  266          *      an actual record size or block number because:
  267          *      a: we do not support offsets from the beginning of the
  268          *              file (allowing for non page size/record modulo offsets.
  269          *      b: because allow paging will be done modulo page size
  270          */
  271 
  272         kr = default_pager_add_file(backing_store, (vnode_ptr_t) vp,
  273                                 PAGE_SIZE, (int)(file_size/PAGE_SIZE));
  274         if(kr != KERN_SUCCESS) {
  275            bs_port_table[i].vp = 0;
  276            if(kr == KERN_INVALID_ARGUMENT)
  277                 error = EINVAL;
  278            else 
  279                 error = ENOMEM;
  280            goto swapon_bailout;
  281         }
  282         bs_port_table[i].bs = (void *)backing_store;
  283         error = 0;
  284 
  285         /* Mark this vnode as being used for swapfile */
  286         SET(vp->v_flag, VSWAP);
  287 
  288         ubc_setthreadcred(vp, p, current_thread());
  289 
  290         /*
  291          * take a long term reference on the vnode to keep
  292          * vnreclaim() away from this vnode.
  293          */
  294         vnode_ref(vp);
  295 
  296 swapon_bailout:
  297         if (vp) {
  298                 vnode_put(vp);
  299         }
  300         (void) thread_funnel_set(kernel_flock, FALSE);
  301         AUDIT_MACH_SYSCALL_EXIT(error);
  302         return(error);
  303 }
  304 
  305 /*
  306  *      Routine:        macx_swapoff
  307  *      Function:
  308  *              Syscall interface to remove a file from backing store
  309  */
  310 int
  311 macx_swapoff(
  312         struct macx_swapoff_args *args)
  313 {
  314         __unused int    flags = args->flags;
  315         kern_return_t   kr;
  316         mach_port_t     backing_store;
  317 
  318         struct vnode            *vp = 0; 
  319         struct nameidata        nd, *ndp;
  320         struct proc             *p =  current_proc();
  321         int                     i;
  322         int                     error;
  323         boolean_t               funnel_state;
  324         vfs_context_t ctx = vfs_context_current();
  325 
  326         AUDIT_MACH_SYSCALL_ENTER(AUE_SWAPOFF);
  327 
  328         funnel_state = thread_funnel_set(kernel_flock, TRUE);
  329         backing_store = NULL;
  330         ndp = &nd;
  331 
  332         if ((error = suser(kauth_cred_get(), 0)))
  333                 goto swapoff_bailout;
  334 
  335         /*
  336          * Get the vnode for the paging area.
  337          */
  338         NDINIT(ndp, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNPATH1,
  339                ((IS_64BIT_PROCESS(p)) ? UIO_USERSPACE64 : UIO_USERSPACE32),
  340                CAST_USER_ADDR_T(args->filename), ctx);
  341 
  342         if ((error = namei(ndp)))
  343                 goto swapoff_bailout;
  344         nameidone(ndp);
  345         vp = ndp->ni_vp;
  346 
  347         if (vp->v_type != VREG) {
  348                 error = EINVAL;
  349                 goto swapoff_bailout;
  350         }
  351 #if CONFIG_MACF
  352         vnode_lock(vp);
  353         error = mac_system_check_swapoff(vfs_context_ucred(ctx), vp);
  354         vnode_unlock(vp);
  355         if (error)
  356                 goto swapoff_bailout;
  357 #endif
  358 
  359         for(i = 0; i < MAX_BACKING_STORE; i++) {
  360                 if(bs_port_table[i].vp == vp) {
  361                         break;
  362                 }
  363         }
  364         if (i == MAX_BACKING_STORE) {
  365                 error = EINVAL;
  366                 goto swapoff_bailout;
  367         }
  368         backing_store = (mach_port_t)bs_port_table[i].bs;
  369 
  370         kr = default_pager_backing_store_delete(backing_store);
  371         switch (kr) {
  372                 case KERN_SUCCESS:
  373                         error = 0;
  374                         bs_port_table[i].vp = 0;
  375                         /* This vnode is no longer used for swapfile */
  376                         CLR(vp->v_flag, VSWAP);
  377 
  378                         /* get rid of macx_swapon() "long term" reference */
  379                         vnode_rele(vp);
  380 
  381                         break;
  382                 case KERN_FAILURE:
  383                         error = EAGAIN;
  384                         break;
  385                 default:
  386                         error = EAGAIN;
  387                         break;
  388         }
  389 
  390 swapoff_bailout:
  391         /* get rid of macx_swapoff() namei() reference */
  392         if (vp)
  393                 vnode_put(vp);
  394 
  395         (void) thread_funnel_set(kernel_flock, FALSE);
  396         AUDIT_MACH_SYSCALL_EXIT(error);
  397         return(error);
  398 }
  399 
  400 /*
  401  *      Routine:        macx_swapinfo
  402  *      Function:
  403  *              Syscall interface to get general swap statistics
  404  */
  405 int
  406 macx_swapinfo(
  407         memory_object_size_t    *total_p,
  408         memory_object_size_t    *avail_p,
  409         vm_size_t               *pagesize_p,
  410         boolean_t               *encrypted_p)
  411 {
  412         int                     error;
  413         memory_object_default_t default_pager;
  414         default_pager_info_64_t dpi64;
  415         kern_return_t           kr;
  416 
  417         error = 0;
  418 
  419         /*
  420          * Get a handle on the default pager.
  421          */
  422         default_pager = MEMORY_OBJECT_DEFAULT_NULL;
  423         kr = host_default_memory_manager(host_priv_self(), &default_pager, 0);
  424         if (kr != KERN_SUCCESS) {
  425                 error = EAGAIN; /* XXX why EAGAIN ? */
  426                 goto done;
  427         }
  428         if (default_pager == MEMORY_OBJECT_DEFAULT_NULL) {
  429                 /*
  430                  * The default pager has not initialized yet,
  431                  * so it can't be using any swap space at all.
  432                  */
  433                 *total_p = 0;
  434                 *avail_p = 0;
  435                 *pagesize_p = 0;
  436                 *encrypted_p = FALSE;
  437                 goto done;
  438         }
  439         
  440         /*
  441          * Get swap usage data from default pager.
  442          */
  443         kr = default_pager_info_64(default_pager, &dpi64);
  444         if (kr != KERN_SUCCESS) {
  445                 error = ENOTSUP;
  446                 goto done;
  447         }
  448 
  449         /*
  450          * Provide default pager info to caller.
  451          */
  452         *total_p = dpi64.dpi_total_space;
  453         *avail_p = dpi64.dpi_free_space;
  454         *pagesize_p = dpi64.dpi_page_size;
  455         if (dpi64.dpi_flags & DPI_ENCRYPTED) {
  456                 *encrypted_p = TRUE;
  457         } else {
  458                 *encrypted_p = FALSE;
  459         }
  460 
  461 done:
  462         if (default_pager != MEMORY_OBJECT_DEFAULT_NULL) {
  463                 /* release our handle on default pager */
  464                 memory_object_default_deallocate(default_pager);
  465         }
  466         return error;
  467 }

Cache object: 323b7d12783f695e85dc3bc988b76093


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