/* 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; }