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

Cache object: 0040852652907f05d305212c8d40b77c


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