OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [dnotify.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * Directory notifications for Linux.
3
 *
4
 * Copyright (C) 2000,2001,2002 Stephen Rothwell
5
 *
6
 * This program is free software; you can redistribute it and/or modify it
7
 * under the terms of the GNU General Public License as published by the
8
 * Free Software Foundation; either version 2, or (at your option) any
9
 * later version.
10
 *
11
 * This program is distributed in the hope that it will be useful, but
12
 * WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * General Public License for more details.
15
 */
16
#include <linux/fs.h>
17
#include <linux/sched.h>
18
#include <linux/dnotify.h>
19
#include <linux/init.h>
20
#include <linux/spinlock.h>
21
#include <linux/slab.h>
22
 
23
extern void send_sigio(struct fown_struct *fown, int fd, int band);
24
 
25
int dir_notify_enable = 1;
26
 
27
static rwlock_t dn_lock = RW_LOCK_UNLOCKED;
28
static kmem_cache_t *dn_cache;
29
 
30
static void redo_inode_mask(struct inode *inode)
31
{
32
        unsigned long new_mask;
33
        struct dnotify_struct *dn;
34
 
35
        new_mask = 0;
36
        for (dn = inode->i_dnotify; dn != NULL; dn = dn->dn_next)
37
                new_mask |= dn->dn_mask & ~DN_MULTISHOT;
38
        inode->i_dnotify_mask = new_mask;
39
}
40
 
41
void dnotify_flush(struct file *filp, fl_owner_t id)
42
{
43
        struct dnotify_struct *dn;
44
        struct dnotify_struct **prev;
45
        struct inode *inode;
46
 
47
        inode = filp->f_dentry->d_inode;
48
        if (!S_ISDIR(inode->i_mode))
49
                return;
50
        write_lock(&dn_lock);
51
        prev = &inode->i_dnotify;
52
        while ((dn = *prev) != NULL) {
53
                if ((dn->dn_owner == id) && (dn->dn_filp == filp)) {
54
                        *prev = dn->dn_next;
55
                        redo_inode_mask(inode);
56
                        kmem_cache_free(dn_cache, dn);
57
                        break;
58
                }
59
                prev = &dn->dn_next;
60
        }
61
        write_unlock(&dn_lock);
62
}
63
 
64
int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)
65
{
66
        struct dnotify_struct *dn;
67
        struct dnotify_struct *odn;
68
        struct dnotify_struct **prev;
69
        struct inode *inode;
70
        fl_owner_t id = current->files;
71
 
72
        if ((arg & ~DN_MULTISHOT) == 0) {
73
                dnotify_flush(filp, id);
74
                return 0;
75
        }
76
        if (!dir_notify_enable)
77
                return -EINVAL;
78
        inode = filp->f_dentry->d_inode;
79
        if (!S_ISDIR(inode->i_mode))
80
                return -ENOTDIR;
81
        dn = kmem_cache_alloc(dn_cache, SLAB_KERNEL);
82
        if (dn == NULL)
83
                return -ENOMEM;
84
        write_lock(&dn_lock);
85
        prev = &inode->i_dnotify;
86
        while ((odn = *prev) != NULL) {
87
                if ((odn->dn_owner == id) && (odn->dn_filp == filp)) {
88
                        odn->dn_fd = fd;
89
                        odn->dn_mask |= arg;
90
                        inode->i_dnotify_mask |= arg & ~DN_MULTISHOT;
91
                        kmem_cache_free(dn_cache, dn);
92
                        goto out;
93
                }
94
                prev = &odn->dn_next;
95
        }
96
        filp->f_owner.pid = current->pid;
97
        filp->f_owner.uid = current->uid;
98
        filp->f_owner.euid = current->euid;
99
        dn->dn_mask = arg;
100
        dn->dn_fd = fd;
101
        dn->dn_filp = filp;
102
        dn->dn_owner = id;
103
        inode->i_dnotify_mask |= arg & ~DN_MULTISHOT;
104
        dn->dn_next = inode->i_dnotify;
105
        inode->i_dnotify = dn;
106
out:
107
        write_unlock(&dn_lock);
108
        return 0;
109
}
110
 
111
void __inode_dir_notify(struct inode *inode, unsigned long event)
112
{
113
        struct dnotify_struct * dn;
114
        struct dnotify_struct **prev;
115
        struct fown_struct *    fown;
116
        int                     changed = 0;
117
 
118
        write_lock(&dn_lock);
119
        prev = &inode->i_dnotify;
120
        while ((dn = *prev) != NULL) {
121
                if ((dn->dn_mask & event) == 0) {
122
                        prev = &dn->dn_next;
123
                        continue;
124
                }
125
                fown = &dn->dn_filp->f_owner;
126
                if (fown->pid)
127
                        send_sigio(fown, dn->dn_fd, POLL_MSG);
128
                if (dn->dn_mask & DN_MULTISHOT)
129
                        prev = &dn->dn_next;
130
                else {
131
                        *prev = dn->dn_next;
132
                        changed = 1;
133
                        kmem_cache_free(dn_cache, dn);
134
                }
135
        }
136
        if (changed)
137
                redo_inode_mask(inode);
138
        write_unlock(&dn_lock);
139
}
140
 
141
static int __init dnotify_init(void)
142
{
143
        dn_cache = kmem_cache_create("dnotify_cache",
144
                sizeof(struct dnotify_struct), 0, 0, NULL, NULL);
145
        if (!dn_cache)
146
                panic("cannot create dnotify slab cache");
147
        return 0;
148
}
149
 
150
module_init(dnotify_init)

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.