Ticket #3723: vm_kernel_29102011.patch

File vm_kernel_29102011.patch, 8.4 KB (added by hamish, 13 years ago)
  • src/system/kernel/vm/VMAnonymousCache.cpp

     
    1717#include <string.h>
    1818#include <unistd.h>
    1919
     20#include <FindDirectory.h>
    2021#include <KernelExport.h>
    2122#include <NodeMonitor.h>
    2223
    2324#include <arch_config.h>
    2425#include <boot_device.h>
     26#include <disk_device_manager/KDiskDevice.h>
     27#include <disk_device_manager/KDiskDeviceManager.h>
     28#include <disk_device_manager/KDiskSystem.h>
     29#include <disk_device_manager/KPartitionVisitor.h>
    2530#include <driver_settings.h>
    2631#include <fs/fd.h>
     32#include <fs/KPath.h>
     33#include <fs_info.h>
    2734#include <fs_interface.h>
    2835#include <heap.h>
    2936#include <kernel_daemon.h>
     
    5360#   define TRACE(x...) do { } while (false)
    5461#endif
    5562
     63static const char* const kDefaultSwapPath = "/var/swap";
     64static const char* const kSwapErrorFilePath = "swaperr";
    5665
    5766// number of free swap blocks the object cache shall minimally have
    5867#define MIN_SWAP_BLOCK_RESERVE  4096
     
    13231332}
    13241333
    13251334
     1335struct VolumeInfo {
     1336    char name[B_FILE_NAME_LENGTH];
     1337    char device[B_FILE_NAME_LENGTH];
     1338    char filesystem[B_OS_NAME_LENGTH];
     1339    off_t capacity;
     1340};
     1341
     1342
     1343class PartitionScorer : public KPartitionVisitor {
     1344public:
     1345    PartitionScorer(VolumeInfo& volumeInfo)
     1346        :
     1347        fBestPartition(NULL),
     1348        fBestScore(-1),
     1349        fVolumeInfo(volumeInfo)
     1350    {
     1351    }
     1352
     1353    virtual bool VisitPre(KPartition* partition)
     1354    {
     1355        if (!partition->ContainsFileSystem())
     1356            return false;
     1357
     1358        KPath path;
     1359        partition->GetPath(&path);
     1360
     1361        int score = 0;
     1362        if (strcmp(fVolumeInfo.name, partition->ContentName()) == 0)
     1363            score += 4;
     1364        if (strcmp(fVolumeInfo.device, path.Path()) == 0)
     1365            score += 3;
     1366        if (fVolumeInfo.capacity == partition->Size())
     1367            score += 2;
     1368        if (strcmp(fVolumeInfo.filesystem, partition->DiskSystem()
     1369            ->ShortName()) == 0)
     1370            score += 1;
     1371        if (score >= 4 && score > fBestScore) {
     1372            fBestPartition = partition;
     1373            fBestScore = score;
     1374        }
     1375
     1376        return false;
     1377    }
     1378
     1379    KPartition* fBestPartition;
     1380private:
     1381    int32       fBestScore;
     1382    VolumeInfo  fVolumeInfo;
     1383};
     1384
     1385
     1386status_t
     1387get_mount_point(KPartition* partition, KPath* mountPoint)
     1388{
     1389    if (!mountPoint || !partition->ContainsFileSystem())
     1390        return B_BAD_VALUE;
     1391
     1392    const char* volumeName = partition->ContentName();
     1393    if (!volumeName || strlen(volumeName) == 0)
     1394        volumeName = partition->Name();
     1395    if (!volumeName || strlen(volumeName) == 0)
     1396        volumeName = "unnamed volume";
     1397
     1398    char basePath[B_PATH_NAME_LENGTH];
     1399    int32 len = snprintf(basePath, sizeof(basePath), "/%s", volumeName);
     1400    for (int32 i = 1; i < len; i++)
     1401        if (basePath[i] == '/')
     1402            basePath[i] = '-';
     1403    char* path = mountPoint->LockBuffer();
     1404    int32 pathLen = mountPoint->BufferSize();
     1405    strncpy(path, basePath, pathLen);
     1406
     1407    struct stat dummy;
     1408    for (int i = 1; ; i++) {
     1409        if (stat(path, &dummy) != 0)
     1410            break;
     1411        snprintf(path, pathLen, "%s%d", basePath, i);
     1412    }
     1413
     1414    mountPoint->UnlockBuffer();
     1415    return B_OK;
     1416}
     1417
     1418
    13261419void
    13271420swap_init_post_modules()
    13281421{
     
    13311424    if (gReadOnlyBootDevice)
    13321425        return;
    13331426
    1334     off_t size = 0;
     1427    bool swapEnabled = true;
     1428    off_t swapSize = 0;
     1429    VolumeInfo selectedVolume = {};
    13351430
     1431    bool loadDefaults = true;
    13361432    void* settings = load_driver_settings("virtual_memory");
    13371433    if (settings != NULL) {
    1338         if (!get_driver_boolean_parameter(settings, "vm", false, false))
    1339             return;
    1340 
    1341         const char* string = get_driver_parameter(settings, "swap_size", NULL,
     1434        const char* enabled = get_driver_parameter(settings, "vm", NULL, NULL);
     1435        const char* size = get_driver_parameter(settings, "swap_size", NULL,
    13421436            NULL);
    1343         size = string ? atoll(string) : 0;
     1437        const char* volume = get_driver_parameter(settings, "swap_volume_name",
     1438            NULL, NULL);
     1439        const char* device = get_driver_parameter(settings,
     1440            "swap_volume_device", NULL, NULL);
     1441        const char* filesystem = get_driver_parameter(settings,
     1442            "swap_volume_filesystem", NULL, NULL);
     1443        const char* capacity = get_driver_parameter(settings,
     1444            "swap_volume_capacity", NULL, NULL);
    13441445
     1446        if (enabled != NULL && size != NULL && device != NULL
     1447            && volume != NULL && filesystem != NULL && capacity != NULL) {
     1448            swapEnabled = get_driver_boolean_parameter(settings, "vm",
     1449                false, false);
     1450            swapSize = atoll(size);
     1451            strncpy(selectedVolume.name, volume, sizeof(selectedVolume.name));
     1452            strncpy(selectedVolume.device, device,
     1453                sizeof(selectedVolume.device));
     1454            strncpy(selectedVolume.filesystem, filesystem,
     1455                sizeof(selectedVolume.filesystem));
     1456            selectedVolume.capacity = atoll(capacity);
     1457            loadDefaults = false;
     1458        }
    13451459        unload_driver_settings(settings);
    1346     } else
    1347         size = (off_t)vm_page_num_pages() * B_PAGE_SIZE * 2;
     1460    }
    13481461
    1349     if (size < B_PAGE_SIZE)
     1462    if (loadDefaults) {
     1463        swapEnabled = true;
     1464        swapSize = (off_t)vm_page_num_pages() * B_PAGE_SIZE * 2;
     1465    }
     1466
     1467    if (!swapEnabled || swapSize < B_PAGE_SIZE)
    13501468        return;
    13511469
    1352     int fd = open("/var/swap", O_RDWR | O_CREAT | O_NOCACHE, S_IRUSR | S_IWUSR);
     1470    dev_t dev = -1;
     1471    if (!loadDefaults) {
     1472        KDiskDeviceManager::CreateDefault();
     1473        KDiskDeviceManager* manager = KDiskDeviceManager::Default();
     1474        PartitionScorer visitor(selectedVolume);
     1475
     1476        KDiskDevice* device;
     1477        int32 cookie = 0;
     1478        while ((device = manager->NextDevice(&cookie)) != NULL) {
     1479            if (device->IsReadOnlyMedia() || device->IsWriteOnce()
     1480                || device->IsRemovable())
     1481                continue;
     1482            device->VisitEachDescendant(&visitor);
     1483        }
     1484
     1485        const char* error = NULL;
     1486        if (!visitor.fBestPartition)
     1487            error = "nfnd";
     1488        else {
     1489            if (visitor.fBestPartition->IsMounted())
     1490                dev = visitor.fBestPartition->VolumeID();
     1491            else {
     1492                KPath devPath, mountPoint;
     1493                visitor.fBestPartition->GetPath(&devPath);
     1494                get_mount_point(visitor.fBestPartition, &mountPoint);
     1495                const char* mountPath = mountPoint.Path();
     1496                mkdir(mountPath, S_IRWXU | S_IRWXG | S_IRWXO);
     1497                dev = _kern_mount(mountPath, devPath.Path(),
     1498                    NULL, 0, NULL, 0);
     1499                if (dev < 0)
     1500                    error = "nmnt";
     1501            }
     1502        }
     1503        if (error != NULL) {
     1504            KPath path;
     1505            if (find_directory(B_COMMON_SETTINGS_DIRECTORY, gBootDevice,
     1506                false, path.LockBuffer(), path.BufferSize()) == B_OK) {
     1507                path.UnlockBuffer();
     1508                path.Append(kSwapErrorFilePath);
     1509                int errorFile = open(path.Path(), O_WRONLY | O_CREAT
     1510                    | O_TRUNC, S_IRUSR | S_IWUSR);
     1511                if (errorFile >= 0) {
     1512                    write(errorFile, error, strlen(error));
     1513                    close(errorFile);
     1514                }
     1515            }
     1516        }
     1517    }
     1518
     1519    if (dev < 0)
     1520        dev = gBootDevice;
     1521
     1522    KPath path;
     1523    struct fs_info info;
     1524    _kern_read_fs_info(dev, &info);
     1525    if (dev == gBootDevice)
     1526        path = kDefaultSwapPath;
     1527    else {
     1528        vfs_entry_ref_to_path(info.dev, info.root,
     1529            ".", path.LockBuffer(), path.BufferSize());
     1530        path.UnlockBuffer();
     1531        path.Append("swap");
     1532    }
     1533
     1534    const char* swapPath = path.Path();
     1535    off_t existingSwapSize = 0;
     1536    struct stat swapStat;
     1537    if (stat(swapPath, &swapStat) == 0)
     1538        existingSwapSize = swapStat.st_size;
     1539
     1540    off_t freeSpace = info.free_blocks * info.block_size + existingSwapSize;
     1541    off_t safeSpace = freeSpace - (off_t)(0.15 * freeSpace);
     1542    if (safeSpace < swapSize)
     1543        swapSize = safeSpace;
     1544
     1545    int fd = open(swapPath, O_RDWR | O_CREAT | O_NOCACHE, S_IRUSR |
     1546        S_IWUSR);
    13531547    if (fd < 0) {
    1354         dprintf("Can't open/create /var/swap: %s\n", strerror(errno));
     1548        dprintf("Can't open/create %s: %s\n", swapPath, strerror(errno));
    13551549        return;
    13561550    }
    13571551
    13581552    struct stat stat;
    1359     stat.st_size = size;
     1553    stat.st_size = swapSize;
    13601554    status_t error = _kern_write_stat(fd, NULL, false, &stat,
    13611555        sizeof(struct stat), B_STAT_SIZE | B_STAT_SIZE_INSECURE);
    1362     if (error != B_OK) {
    1363         dprintf("Failed to resize /var/swap to %lld bytes: %s\n", size,
    1364             strerror(error));
    1365     }
     1556    if (error != B_OK)
     1557        dprintf("Failed to resize %s to %lld bytes: %s\n", swapPath,
     1558            swapSize, strerror(error));
    13661559
    13671560    close(fd);
    13681561
    1369     error = swap_file_add("/var/swap");
     1562    error = swap_file_add(swapPath);
    13701563    if (error != B_OK)
    1371         dprintf("Failed to add swap file /var/swap: %s\n", strerror(error));
     1564        dprintf("Failed to add swap file %s: %s\n", swapPath,
     1565            strerror(error));
    13721566}
    13731567
    13741568
  • src/system/kernel/vm/Jamfile

     
    11SubDir HAIKU_TOP src system kernel vm ;
    22
    33UsePrivateHeaders shared ;
     4UsePrivateHeaders [ FDirName kernel disk_device_manager ] ;
     5UsePrivateHeaders [ FDirName kernel util ] ;
    46
    57UseHeaders [ FDirName $(SUBDIR) $(DOTDOT) device_manager ] ;
    68