/* Copyright (C) 2008 Emmanuel Varoquaux
This file is part of XOS.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see . */
#include "file_system_instance_struct.h"
#include "file_system_struct.h"
#include "device_struct.h"
#include
#include
#include
#include
#include
#include
#include
#include
static struct file_system_instance_struct *first = NULL;
static struct file_system_instance_struct *last = NULL;
static void insert(struct file_system_instance_struct *file_system_instance)
{
file_system_instance->previous = last;
file_system_instance->next = NULL;
if (last)
last->next = file_system_instance;
else
first = file_system_instance;
last = file_system_instance;
}
static void remove(struct file_system_instance_struct *file_system_instance)
{
if (file_system_instance->previous)
file_system_instance->previous->next = file_system_instance->next;
else
first = file_system_instance->next;
if (file_system_instance->next)
file_system_instance->next->previous = file_system_instance->previous;
else
last = file_system_instance->previous;
}
int file_system_instance_init(struct file_system_instance_struct *file_system_instance, const struct file_system_struct *file_system, char *device_path, struct device_struct *device, const struct file_struct *mount_point)
{
void *data;
int rv;
file_system_instance->file_system = file_system;
file_system_instance->device_path = device_path;
switch (file_system->type) {
case FT_NONE:
if ((rv = file_system->mount(NULL, &file_system_instance->data)) < 0)
return rv;
break;
case FT_BLK:
if (!device || device->type != FT_BLK)
return -ENOTBLK;
file_system_instance->device = device;
if (device->count) {
if (device->file_system != file_system)
return -EBUSY;
}
else {
if ((rv = file_system->mount(device, &data)) < 0)
return rv;
device->file_system = file_system;
device->data = data;
}
device->count++;
file_system_instance->data = device->data;
break;
}
file_system_instance->count = 0;
file_system_instance->mount_point = mount_point;
insert(file_system_instance);
return 0;
}
void file_system_instance_destroy(struct file_system_instance_struct *file_system_instance)
{
assert(file_system_instance->count == 0);
remove(file_system_instance);
switch (file_system_instance->file_system->type) {
case FT_NONE:
file_system_instance->file_system->umount(file_system_instance->data);
break;
case FT_BLK:
file_system_instance->device->count--;
if (!file_system_instance->device->count) {
file_system_instance->file_system->umount(file_system_instance->device->data);
file_system_instance->device->file_system = NULL;
file_system_instance->device->data = NULL;
}
break;
}
if (file_system_instance->device_path)
kfree(file_system_instance->device_path, strlen(file_system_instance->device_path) + 1);
}
void file_system_instance_hold(struct file_system_instance_struct *file_system_instance)
{
file_system_instance->count++;
}
void file_system_instance_release(struct file_system_instance_struct *file_system_instance)
{
assert(file_system_instance->count > 0);
file_system_instance->count--;
}
int file_system_instance_is_busy(const struct file_system_instance_struct *file_system_instance)
{
return file_system_instance->count > 1; /* ne pas compter la reference courante */
}
/* procfs */
int print_mounts(char *buf, unsigned int size)
{
char *s;
const struct file_system_instance_struct *fsi;
char *path;
unsigned int n;
int rv;
s = buf;
for (fsi = first; fsi; fsi = fsi->next) {
if ((rv = get_path(fsi->mount_point, &path) < 0))
return rv;
n = snprintf(s, size, "%s %s %s\n", fsi->device_path ? : "none", path, fsi->file_system->name);
s += n;
size = size > n ? size - n : 0;
kfree(path, strlen(path) + 1);
}
return s - buf;
}