lkml.org 
[lkml]   [1998]   [Aug]   [5]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
SubjectRe: DEVFSv50 and /dev/fb? (or /dev/fb/? ???)
   Date: Tue, 4 Aug 1998 16:40:36 -0500 (CDT)
From: Shawn Leas <sleas@ixion.honeywell.com>

Maybe you'll write an LVM and head Heinz off at the pass, too? You are
way to argumentative, not those who are simply trying to drum up support
for it to FINALLY be rolled into the official tree.

Who's being argumentative? I haven't made any ad hominem attacks....

Indeed, I haven't made any arguments because it's clear the devfs folks
are fanatical about the subject. My plan was to actually implement a
better alternative, not just argue about it. The only reason why I
broke my silence was to point out that not all of the "Linux Kernel
Gods" (not my terminology) thought devfs was the greatest thing since
sliced bread, as one person on the mailing list had incorrectly claimed.

My best guess is that devfs is more like GGI in terms some folks who
think its great and some folks who think it's kinda ugly. Obviously
it's different folks, and different objectives; suffice it to say that
not every one agrees.

Specifically, what is ugly about it? Is it intrinsic in nature, or
something fixable? Is the design flawed? Then how? Back up your
complaints with more than "Well, I talked with some unnamed Kernel guys,
and they said..."

... I thought you were complaining that I was being "way too
argumentative". Now you want me to argue about it?

Well, put simply, (1) it's trying to solve a problem in the kernel for
which parts can just as easily be solved in user-space; it puts too much
policy and naming issues in the kernel. (2) The hacks that you need so
that you can save the user/group ownership and permissions are too ugly
to contemplate. (3) Device inodes really do need major and minor device
numbers; programs do look at them, and POSIX guarantees that they exist.


The one problem which devfs is trying to solve which I think is valid is
the question of device partitions, particularly with SCSI. So the
solution that I'm working on is a small module which can be installed on
any kernel (doesn't require a massive kernel patch), which scans all of
the block devices looking for filesystem superblocks/labels for a wide
variety of filesystems, and creates a hierarchy of device files inside
/proc for those filesystems.

Hence you would see block devices with names such as
/proc/volumes/ext2fs/ted_root, and /proc/volumes/ntfs/NT5.0, and so on,
and you can simply put those names in your /etc/fstab file. This way,
you're guaranteed to get the right partitions mounted even if someone
inserts a new disk.

This is much simpler than putting all devices in /dev into a synthentic
filesystem such as devfs, which I continue to think is overkill and
unnecessary. Since it's a loadable kernel module, distributions that
want to use it don't need to install a patch to the 2.2 kernel, but they
can just load the module.

If folks are interested in seeing what I've done to date, it's small and
simple enough that I've appended it below. It's still missing a few
filesystems, such as NTFS and ISO9660, which is why I haven't released
it formally up until now.

- Ted

/*
* fslabel.c
*
* Copyright Theodore Ts'o, 1998.
*
* This file may be redistributed under the terms of the GNU Public
* License.
*/

#ifdef MODVERSIONS
#include <linux/modversions.h>
#endif

#include <linux/module.h>
#include <asm/system.h>
#include <asm/bitops.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/stat.h>
#include <linux/timer.h>
#if (LINUX_VERSION_CODE >= 131343) /* 2.1.15 -- XX get correct version */
#include <linux/init.h>
#else
#define __initfunc(x) x
#endif
#include <linux/genhd.h>
#include <linux/blkdev.h>
#include <linux/msdos_fs.h>
#include <linux/proc_fs.h>
#include <linux/fs.h>

struct vol_label {
int major;
int minor;
int vol_type;
char *label;
unsigned char vol_id[16];
struct proc_dir_entry *proc_ent;
struct vol_label *next;
};

static struct vol_label *vol_head;

#define VOL_EXT2 1
#define VOL_FAT 2
#define VOL_FAT32 3
#define VOL_MAX 4

char *vol_type_name[VOL_MAX] = {
"(root)", "ext2", "fat", "fat32"
};

struct proc_dir_entry *proc_array[VOL_MAX];

/*
* Release a dynamic vol_label
*/
void free_vol_label(struct vol_label *v)
{
if (v->label)
kfree(v->label);
kfree_s(v, sizeof(struct vol_label));
}

/*
* Make a copy of struct vol_label using completely dynamic memory
*/
struct vol_label *copy_vol_label(struct vol_label *v)
{
struct vol_label *ret;

ret = kmalloc(sizeof(struct vol_label), GFP_KERNEL);
if (!ret)
return 0;
memset(ret, 0, sizeof(struct vol_label));
ret->vol_type = v->vol_type;
if (v->label) {
ret->label = kmalloc(strlen(v->label)+1, GFP_KERNEL);
if (!ret->label)
goto errout;
strcpy(ret->label, v->label);
}
memcpy(ret->vol_id, ret->vol_id, sizeof(ret->vol_id));
return ret;
errout:
free_vol_label(v);
return 0;
}

/*
* This fills in the device number for the proc inode.
*
*/
static void vol_fill_inode(struct inode * inode, int fill)
{
struct vol_label *vol;
struct proc_dir_entry * de;

/*
* The fill argument is non-zero when the inode is being
* filled ...we don't need to do anything when it's being
* deleted.
*/
if (!fill)
return;

de = (struct proc_dir_entry *) inode->u.generic_ip;
vol = de->data;
inode->i_rdev = MKDEV(vol->major, vol->minor);
inode->i_op = &blkdev_inode_operations;
}

/*
* Check to see if it's a msdos filesystem; if so, return the label.
*/
struct vol_label *get_msdos_label(unsigned char *page1,
unsigned char *page2)
{
struct fat_boot_sector *b;
static struct vol_label vol;
static char vol_label[9];
int logical_sector_size;
int fat32 = 0;

b = (struct fat_boot_sector *) page1;

if (!b->cluster_size || !b->fats)
return 0;

logical_sector_size = b->sector_size[0] + (b->sector_size[1] << 8);

if ((logical_sector_size < 512) || (logical_sector_size & 0x1FF))
return 0;

if (!b->fat_length && b->fat32_length) {
fat32 = 1;
printk("Fat 32...%d\n", b->info_sector);
}

vol_label[9] = 0;
strncpy(vol_label, b->system_id, 8);

vol.vol_type = fat32 ? VOL_FAT32 : VOL_FAT;
vol.label = vol_label;
memset(vol.vol_id, 0, sizeof(vol.vol_id));

return &vol;
}

/*
* Check to see if it's an ext2 filesystem; if is, return the label.
*/
struct vol_label *get_ext2_label(unsigned char *page1,
unsigned char *page2)
{
struct ext2_super_block *sb;
static struct vol_label vol;

sb = (struct ext2_super_block *) page2;

if (le16_to_cpu(sb->s_magic) != EXT2_SUPER_MAGIC)
return 0;
vol.vol_type = VOL_EXT2;
vol.label = sb->s_volume_name;
memcpy(vol.vol_id, sb->s_uuid, sizeof(vol.vol_id));

return &vol;
}

void scan_partition(int major, int minor)
{
struct buffer_head *bh, *bh2;
unsigned char *page1, *page2;
kdev_t dev;
int i, correct_size;
struct vol_label *vol, *p;

dev = MKDEV(major, minor);

correct_size = BLOCK_SIZE;
if (blksize_size[major]) {
i = blksize_size[major][minor];
if (i)
correct_size = i;
}

bh = bread(dev, 0, correct_size);
page1 = bh->b_data;
if (!bh)
return;
if (correct_size <= 1024) {
bh2 = bread(dev, 1024 / correct_size, correct_size);
page2 = bh2->b_data;
} else {
bh2 = 0;
page2 = bh->b_data + 1024;
}
vol = get_ext2_label(page1, page2);
if (!vol)
vol = get_msdos_label(page1, page2);
if (vol) {
p = copy_vol_label(vol);
if (p) {
p->major = major;
p->minor = minor;
p->next = vol_head;
vol_head = p;
}
#if 0
printk("type = %s, label = %s\n", vol->type,
vol->label);
#endif
}

brelse(bh);
if (bh2)
brelse(bh2);
}


void scan_disks()
{
struct gendisk *g;
int i, end_minor;

for (g = gendisk_head; g; g = g->next) {
#if 0
printk("%s\n", g->major_name);
#endif
end_minor = g->max_nr * g->max_p;
if (!blk_size[g->major]) {
#if 0
printk(" No blk_size array\n");
#endif
continue;
}
for (i = 0; i < end_minor; i++) {
if ((i % g->max_p) == 0)
continue;
if (blk_size[g->major][i] == 0)
continue;
#if 0
printk(" (%d, %d) %d\n", g->major, i,
blk_size[g->major][i]);
#endif
scan_partition(g->major, i);
}
}
}


#ifdef MODULE

int init_module(void)
{
struct vol_label *vol;
int retval = 0;
int vtype;

printk("fslabel driver\n");

scan_disks();

proc_array[0] = create_proc_entry("volumes", S_IFDIR, 0);

if (!vol_head)
printk("No volumes found.\n");

for (vol = vol_head; vol; vol = vol->next) {
printk("type=%d, label=%s, major=%d, minor=%d\n",
vol->vol_type, vol->label, vol->major, vol->minor);
vtype = vol->vol_type;
if (!proc_array[vtype]) {
proc_array[vtype] =
create_proc_entry(vol_type_name[vtype],
S_IFDIR, proc_array[0]);
}
vol->proc_ent = create_proc_entry(vol->label,
S_IFBLK|S_IRUSR|S_IWUSR,
proc_array[vtype]);
vol->proc_ent->data = vol;
vol->proc_ent->fill_inode = vol_fill_inode;
}

return (retval);
}


void cleanup_module(void)
{
struct vol_label *vol, *vol_next;
int i;

for (vol = vol_head; vol; vol = vol_next) {
vol_next = vol->next;
if (vol->proc_ent)
proc_unregister(proc_array[vol->vol_type],
vol->proc_ent->low_ino);
free_vol_label(vol);
}
for (i=1; i < VOL_MAX; i++) {
if (!proc_array[i])
continue;
proc_unregister(proc_array[0], proc_array[i]->low_ino);
}
if (proc_array[0])
remove_proc_entry("volumes", 0);

return;
}

#endif /* MODULE */

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.altern.org/andrebalsa/doc/lkml-faq.html

\
 
 \ /
  Last update: 2005-03-22 13:43    [W:0.172 / U:0.200 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site