linux-bk/fs/libfs.c
<<
>>
Prefs
   1/*
   2 *      fs/libfs.c
   3 *      Library for filesystems writers.
   4 */
   5
   6#include <linux/pagemap.h>
   7#include <linux/smp_lock.h>
   8
   9int simple_statfs(struct super_block *sb, struct statfs *buf)
  10{
  11        buf->f_type = sb->s_magic;
  12        buf->f_bsize = PAGE_CACHE_SIZE;
  13        buf->f_namelen = NAME_MAX;
  14        return 0;
  15}
  16
  17/*
  18 * Lookup the data. This is trivial - if the dentry didn't already
  19 * exist, we know it is negative.
  20 */
  21
  22struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry)
  23{
  24        d_add(dentry, NULL);
  25        return NULL;
  26}
  27
  28int simple_sync_file(struct file * file, struct dentry *dentry, int datasync)
  29{
  30        return 0;
  31}
  32 
  33int dcache_dir_open(struct inode *inode, struct file *file)
  34{
  35        static struct qstr cursor_name = {.len = 1, .name = "."};
  36
  37        file->private_data = d_alloc(file->f_dentry, &cursor_name);
  38
  39        return file->private_data ? 0 : -ENOMEM;
  40}
  41
  42int dcache_dir_close(struct inode *inode, struct file *file)
  43{
  44        dput(file->private_data);
  45        return 0;
  46}
  47
  48loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin)
  49{
  50        down(&file->f_dentry->d_inode->i_sem);
  51        switch (origin) {
  52                case 1:
  53                        offset += file->f_pos;
  54                case 0:
  55                        if (offset >= 0)
  56                                break;
  57                default:
  58                        up(&file->f_dentry->d_inode->i_sem);
  59                        return -EINVAL;
  60        }
  61        if (offset != file->f_pos) {
  62                file->f_pos = offset;
  63                if (file->f_pos >= 2) {
  64                        struct list_head *p;
  65                        struct dentry *cursor = file->private_data;
  66                        loff_t n = file->f_pos - 2;
  67
  68                        spin_lock(&dcache_lock);
  69                        p = file->f_dentry->d_subdirs.next;
  70                        while (n && p != &file->f_dentry->d_subdirs) {
  71                                struct dentry *next;
  72                                next = list_entry(p, struct dentry, d_child);
  73                                if (!list_empty(&next->d_hash) && next->d_inode)
  74                                        n--;
  75                                p = p->next;
  76                        }
  77                        list_del(&cursor->d_child);
  78                        list_add_tail(&cursor->d_child, p);
  79                        spin_unlock(&dcache_lock);
  80                }
  81        }
  82        up(&file->f_dentry->d_inode->i_sem);
  83        return offset;
  84}
  85
  86/* Relationship between i_mode and the DT_xxx types */
  87static inline unsigned char dt_type(struct inode *inode)
  88{
  89        return (inode->i_mode >> 12) & 15;
  90}
  91
  92/*
  93 * Directory is locked and all positive dentries in it are safe, since
  94 * for ramfs-type trees they can't go away without unlink() or rmdir(),
  95 * both impossible due to the lock on directory.
  96 */
  97
  98int dcache_readdir(struct file * filp, void * dirent, filldir_t filldir)
  99{
 100        struct dentry *dentry = filp->f_dentry;
 101        struct dentry *cursor = filp->private_data;
 102        struct list_head *p, *q = &cursor->d_child;
 103        ino_t ino;
 104        int i = filp->f_pos;
 105
 106        switch (i) {
 107                case 0:
 108                        ino = dentry->d_inode->i_ino;
 109                        if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0)
 110                                break;
 111                        filp->f_pos++;
 112                        i++;
 113                        /* fallthrough */
 114                case 1:
 115                        ino = parent_ino(dentry);
 116                        if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0)
 117                                break;
 118                        filp->f_pos++;
 119                        i++;
 120                        /* fallthrough */
 121                default:
 122                        spin_lock(&dcache_lock);
 123                        if (filp->f_pos == 2) {
 124                                list_del(q);
 125                                list_add(q, &dentry->d_subdirs);
 126                        }
 127                        for (p=q->next; p != &dentry->d_subdirs; p=p->next) {
 128                                struct dentry *next;
 129                                next = list_entry(p, struct dentry, d_child);
 130                                if (list_empty(&next->d_hash) || !next->d_inode)
 131                                        continue;
 132
 133                                spin_unlock(&dcache_lock);
 134                                if (filldir(dirent, next->d_name.name, next->d_name.len, filp->f_pos, next->d_inode->i_ino, dt_type(next->d_inode)) < 0)
 135                                        return 0;
 136                                spin_lock(&dcache_lock);
 137                                /* next is still alive */
 138                                list_del(q);
 139                                list_add(q, p);
 140                                p = q;
 141                                filp->f_pos++;
 142                        }
 143                        spin_unlock(&dcache_lock);
 144        }
 145        return 0;
 146}
 147
 148ssize_t generic_read_dir(struct file *filp, char *buf, size_t siz, loff_t *ppos)
 149{
 150        return -EISDIR;
 151}
 152
 153struct file_operations simple_dir_operations = {
 154        .open           = dcache_dir_open,
 155        .release        = dcache_dir_close,
 156        .llseek         = dcache_dir_lseek,
 157        .read           = generic_read_dir,
 158        .readdir        = dcache_readdir,
 159};
 160
 161struct inode_operations simple_dir_inode_operations = {
 162        .lookup         = simple_lookup,
 163};
 164
 165/*
 166 * Common helper for pseudo-filesystems (sockfs, pipefs, bdev - stuff that
 167 * will never be mountable)
 168 */
 169struct super_block *
 170get_sb_pseudo(struct file_system_type *fs_type, char *name,
 171        struct super_operations *ops, unsigned long magic)
 172{
 173        struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL);
 174        static struct super_operations default_ops = {.statfs = simple_statfs};
 175        struct dentry *dentry;
 176        struct inode *root;
 177        struct qstr d_name = {.name = name, .len = strlen(name)};
 178
 179        if (IS_ERR(s))
 180                return s;
 181
 182        s->s_flags = MS_NOUSER;
 183        s->s_maxbytes = ~0ULL;
 184        s->s_blocksize = 1024;
 185        s->s_blocksize_bits = 10;
 186        s->s_magic = magic;
 187        s->s_op = ops ? ops : &default_ops;
 188        root = new_inode(s);
 189        if (!root)
 190                goto Enomem;
 191        root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR;
 192        root->i_uid = root->i_gid = 0;
 193        root->i_atime = root->i_mtime = root->i_ctime = CURRENT_TIME;
 194        dentry = d_alloc(NULL, &d_name);
 195        if (!dentry) {
 196                iput(root);
 197                goto Enomem;
 198        }
 199        dentry->d_sb = s;
 200        dentry->d_parent = dentry;
 201        d_instantiate(dentry, root);
 202        s->s_root = dentry;
 203        s->s_flags |= MS_ACTIVE;
 204        return s;
 205
 206Enomem:
 207        up_write(&s->s_umount);
 208        deactivate_super(s);
 209        return ERR_PTR(-ENOMEM);
 210}
 211
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.