Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
243c64b2
Commit
243c64b2
authored
Apr 11, 2004
by
Andrew Morton
Committed by
Linus Torvalds
Apr 11, 2004
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] feed devfs through Lindent
Nobody seems to have any outstanding work against devfs, so...
parent
77b92f5b
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
1467 additions
and
1450 deletions
+1467
-1450
fs/devfs/base.c
fs/devfs/base.c
+1438
-1419
fs/devfs/util.c
fs/devfs/util.c
+1
-1
include/linux/devfs_fs.h
include/linux/devfs_fs.h
+15
-17
include/linux/devfs_fs_kernel.h
include/linux/devfs_fs_kernel.h
+13
-13
No files found.
fs/devfs/base.c
View file @
243c64b2
...
...
@@ -753,22 +753,19 @@
typedef
struct
devfs_entry
*
devfs_handle_t
;
struct
directory_type
{
struct
directory_type
{
rwlock_t
lock
;
/* Lock for searching(R)/updating(W) */
struct
devfs_entry
*
first
;
struct
devfs_entry
*
last
;
unsigned
char
no_more_additions
:
1
;
};
struct
symlink_type
{
struct
symlink_type
{
unsigned
int
length
;
/* Not including the NULL-termimator */
char
*
linkname
;
/* This is NULL-terminated */
};
struct
devfs_inode
/* This structure is for "persistent" inode storage */
{
struct
devfs_inode
{
/* This structure is for "persistent" inode storage */
struct
dentry
*
dentry
;
struct
timespec
atime
;
struct
timespec
mtime
;
...
...
@@ -778,28 +775,25 @@ struct devfs_inode /* This structure is for "persistent" inode storage */
gid_t
gid
;
};
struct
devfs_entry
{
struct
devfs_entry
{
#ifdef CONFIG_DEVFS_DEBUG
unsigned
int
magic_number
;
#endif
void
*
info
;
atomic_t
refcount
;
/* When this drops to zero, it's unused */
union
{
union
{
struct
directory_type
dir
;
dev_t
dev
;
struct
symlink_type
symlink
;
const
char
*
name
;
/* Only used for (mode == 0) */
}
u
;
}
u
;
struct
devfs_entry
*
prev
;
/* Previous entry in the parent directory */
struct
devfs_entry
*
next
;
/* Next entry in the parent directory */
struct
devfs_entry
*
parent
;
/* The parent directory */
struct
devfs_inode
inode
;
umode_t
mode
;
unsigned
short
namelen
;
/* I think 64k+ filenames are a way off... */
unsigned
char
vfs
:
1
;
/* Whether the VFS may delete the entry */
unsigned
char
vfs
:
1
;
/* Whether the VFS may delete the entry */
char
name
[
1
];
/* This is just a dummy: the allocated array
is bigger. This is NULL-terminated */
};
...
...
@@ -807,8 +801,7 @@ struct devfs_entry
/* The root of the device tree */
static
struct
devfs_entry
*
root_entry
;
struct
devfsd_buf_entry
{
struct
devfsd_buf_entry
{
struct
devfs_entry
*
de
;
/* The name is generated with this */
unsigned
short
type
;
/* The type of event */
umode_t
mode
;
...
...
@@ -817,8 +810,7 @@ struct devfsd_buf_entry
struct
devfsd_buf_entry
*
next
;
};
struct
fs_info
/* This structure is for the mounted devfs */
{
struct
fs_info
{
/* This structure is for the mounted devfs */
struct
super_block
*
sb
;
spinlock_t
devfsd_buffer_lock
;
/* Lock when inserting/deleting events */
struct
devfsd_buf_entry
*
devfsd_first_event
;
...
...
@@ -834,7 +826,7 @@ struct fs_info /* This structure is for the mounted devfs */
wait_queue_head_t
revalidate_wait_queue
;
/* Wake when devfsd sleeps */
};
static
struct
fs_info
fs_info
=
{.
devfsd_buffer_lock
=
SPIN_LOCK_UNLOCKED
};
static
struct
fs_info
fs_info
=
{.
devfsd_buffer_lock
=
SPIN_LOCK_UNLOCKED
};
static
kmem_cache_t
*
devfsd_buf_cache
;
#ifdef CONFIG_DEVFS_DEBUG
static
unsigned
int
devfs_debug_init
__initdata
=
DEBUG_NONE
;
...
...
@@ -844,7 +836,7 @@ static unsigned int stat_num_entries;
static
unsigned
int
stat_num_bytes
;
#endif
static
unsigned
char
poison_array
[
8
]
=
{
0x5a
,
0x5a
,
0x5a
,
0x5a
,
0x5a
,
0x5a
,
0x5a
,
0x5a
};
{
0x5a
,
0x5a
,
0x5a
,
0x5a
,
0x5a
,
0x5a
,
0x5a
,
0x5a
};
#ifdef CONFIG_DEVFS_MOUNT
static
unsigned
int
boot_options
=
OPTION_MOUNT
;
...
...
@@ -853,45 +845,41 @@ static unsigned int boot_options = OPTION_NONE;
#endif
/* Forward function declarations */
static
devfs_handle_t
_devfs_walk_path
(
struct
devfs_entry
*
dir
,
static
devfs_handle_t
_devfs_walk_path
(
struct
devfs_entry
*
dir
,
const
char
*
name
,
int
namelen
,
int
traverse_symlink
);
static
ssize_t
devfsd_read
(
struct
file
*
file
,
char
*
buf
,
size_t
len
,
loff_t
*
ppos
);
static
int
devfsd_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
static
ssize_t
devfsd_read
(
struct
file
*
file
,
char
*
buf
,
size_t
len
,
loff_t
*
ppos
);
static
int
devfsd_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
);
static
int
devfsd_close
(
struct
inode
*
inode
,
struct
file
*
file
);
static
int
devfsd_close
(
struct
inode
*
inode
,
struct
file
*
file
);
#ifdef CONFIG_DEVFS_DEBUG
static
ssize_t
stat_read
(
struct
file
*
file
,
char
*
buf
,
size_t
len
,
loff_t
*
ppos
);
static
struct
file_operations
stat_fops
=
{
static
ssize_t
stat_read
(
struct
file
*
file
,
char
*
buf
,
size_t
len
,
loff_t
*
ppos
);
static
struct
file_operations
stat_fops
=
{
.
read
=
stat_read
,
};
#endif
/* Devfs daemon file operations */
static
struct
file_operations
devfsd_fops
=
{
static
struct
file_operations
devfsd_fops
=
{
.
read
=
devfsd_read
,
.
ioctl
=
devfsd_ioctl
,
.
release
=
devfsd_close
,
};
/* Support functions follow */
/**
* devfs_get - Get a reference to a devfs entry.
* @de: The devfs entry.
*/
static
struct
devfs_entry
*
devfs_get
(
struct
devfs_entry
*
de
)
static
struct
devfs_entry
*
devfs_get
(
struct
devfs_entry
*
de
)
{
VERIFY_ENTRY
(
de
);
if
(
de
)
atomic_inc
(
&
de
->
refcount
);
VERIFY_ENTRY
(
de
);
if
(
de
)
atomic_inc
(
&
de
->
refcount
);
return
de
;
}
/* End Function devfs_get */
...
...
@@ -900,27 +888,33 @@ static struct devfs_entry *devfs_get (struct devfs_entry *de)
* @de: The handle to the devfs entry.
*/
static
void
devfs_put
(
devfs_handle_t
de
)
static
void
devfs_put
(
devfs_handle_t
de
)
{
if
(
!
de
)
return
;
VERIFY_ENTRY
(
de
);
if
(
de
->
info
==
POISON_PTR
)
OOPS
(
"(%p): poisoned pointer
\n
"
,
de
);
if
(
!
atomic_dec_and_test
(
&
de
->
refcount
)
)
return
;
if
(
de
==
root_entry
)
OOPS
(
"(%p): root entry being freed
\n
"
,
de
);
DPRINTK
(
DEBUG_FREE
,
"(%s): de: %p, parent: %p
\"
%s
\"\n
"
,
if
(
!
de
)
return
;
VERIFY_ENTRY
(
de
);
if
(
de
->
info
==
POISON_PTR
)
OOPS
(
"(%p): poisoned pointer
\n
"
,
de
);
if
(
!
atomic_dec_and_test
(
&
de
->
refcount
))
return
;
if
(
de
==
root_entry
)
OOPS
(
"(%p): root entry being freed
\n
"
,
de
);
DPRINTK
(
DEBUG_FREE
,
"(%s): de: %p, parent: %p
\"
%s
\"\n
"
,
de
->
name
,
de
,
de
->
parent
,
de
->
parent
?
de
->
parent
->
name
:
"no parent"
);
if
(
S_ISLNK
(
de
->
mode
)
)
kfree
(
de
->
u
.
symlink
.
linkname
);
WRITE_ENTRY_MAGIC
(
de
,
0
);
if
(
S_ISLNK
(
de
->
mode
))
kfree
(
de
->
u
.
symlink
.
linkname
);
WRITE_ENTRY_MAGIC
(
de
,
0
);
#ifdef CONFIG_DEVFS_DEBUG
spin_lock
(
&
stat_lock
);
spin_lock
(
&
stat_lock
);
--
stat_num_entries
;
stat_num_bytes
-=
sizeof
*
de
+
de
->
namelen
;
if
(
S_ISLNK
(
de
->
mode
)
)
stat_num_bytes
-=
de
->
u
.
symlink
.
length
+
1
;
spin_unlock
(
&
stat_lock
);
if
(
S_ISLNK
(
de
->
mode
))
stat_num_bytes
-=
de
->
u
.
symlink
.
length
+
1
;
spin_unlock
(
&
stat_lock
);
#endif
de
->
info
=
POISON_PTR
;
kfree
(
de
);
kfree
(
de
);
}
/* End Function devfs_put */
/**
...
...
@@ -934,27 +928,26 @@ static void devfs_put (devfs_handle_t de)
* An implicit devfs_get() is performed on the returned entry.
*/
static
struct
devfs_entry
*
_devfs_search_dir
(
struct
devfs_entry
*
dir
,
static
struct
devfs_entry
*
_devfs_search_dir
(
struct
devfs_entry
*
dir
,
const
char
*
name
,
unsigned
int
namelen
)
{
struct
devfs_entry
*
curr
;
if
(
!
S_ISDIR
(
dir
->
mode
)
)
{
PRINTK
(
"(%s): not a directory
\n
"
,
dir
->
name
);
if
(
!
S_ISDIR
(
dir
->
mode
))
{
PRINTK
(
"(%s): not a directory
\n
"
,
dir
->
name
);
return
NULL
;
}
for
(
curr
=
dir
->
u
.
dir
.
first
;
curr
!=
NULL
;
curr
=
curr
->
next
)
{
if
(
curr
->
namelen
!=
namelen
)
continue
;
if
(
memcmp
(
curr
->
name
,
name
,
namelen
)
==
0
)
break
;
for
(
curr
=
dir
->
u
.
dir
.
first
;
curr
!=
NULL
;
curr
=
curr
->
next
)
{
if
(
curr
->
namelen
!=
namelen
)
continue
;
if
(
memcmp
(
curr
->
name
,
name
,
namelen
)
==
0
)
break
;
/* Not found: try the next one */
}
return
devfs_get
(
curr
);
return
devfs_get
(
curr
);
}
/* End Function _devfs_search_dir */
/**
* _devfs_alloc_entry - Allocate a devfs entry.
* @name: the name of the entry
...
...
@@ -965,7 +958,7 @@ static struct devfs_entry *_devfs_search_dir (struct devfs_entry *dir,
* %NULL.
*/
static
struct
devfs_entry
*
_devfs_alloc_entry
(
const
char
*
name
,
static
struct
devfs_entry
*
_devfs_alloc_entry
(
const
char
*
name
,
unsigned
int
namelen
,
umode_t
mode
)
{
...
...
@@ -973,29 +966,31 @@ static struct devfs_entry *_devfs_alloc_entry (const char *name,
static
unsigned
long
inode_counter
=
FIRST_INODE
;
static
spinlock_t
counter_lock
=
SPIN_LOCK_UNLOCKED
;
if
(
name
&&
(
namelen
<
1
)
)
namelen
=
strlen
(
name
);
if
(
(
new
=
kmalloc
(
sizeof
*
new
+
namelen
,
GFP_KERNEL
)
)
==
NULL
)
if
(
name
&&
(
namelen
<
1
))
namelen
=
strlen
(
name
);
if
((
new
=
kmalloc
(
sizeof
*
new
+
namelen
,
GFP_KERNEL
))
==
NULL
)
return
NULL
;
memset
(
new
,
0
,
sizeof
*
new
+
namelen
);
/* Will set '\0' on name */
memset
(
new
,
0
,
sizeof
*
new
+
namelen
);
/* Will set '\0' on name */
new
->
mode
=
mode
;
if
(
S_ISDIR
(
mode
)
)
rwlock_init
(
&
new
->
u
.
dir
.
lock
);
atomic_set
(
&
new
->
refcount
,
1
);
spin_lock
(
&
counter_lock
);
if
(
S_ISDIR
(
mode
))
rwlock_init
(
&
new
->
u
.
dir
.
lock
);
atomic_set
(
&
new
->
refcount
,
1
);
spin_lock
(
&
counter_lock
);
new
->
inode
.
ino
=
inode_counter
++
;
spin_unlock
(
&
counter_lock
);
if
(
name
)
memcpy
(
new
->
name
,
name
,
namelen
);
spin_unlock
(
&
counter_lock
);
if
(
name
)
memcpy
(
new
->
name
,
name
,
namelen
);
new
->
namelen
=
namelen
;
WRITE_ENTRY_MAGIC
(
new
,
MAGIC_VALUE
);
WRITE_ENTRY_MAGIC
(
new
,
MAGIC_VALUE
);
#ifdef CONFIG_DEVFS_DEBUG
spin_lock
(
&
stat_lock
);
spin_lock
(
&
stat_lock
);
++
stat_num_entries
;
stat_num_bytes
+=
sizeof
*
new
+
namelen
;
spin_unlock
(
&
stat_lock
);
spin_unlock
(
&
stat_lock
);
#endif
return
new
;
}
/* End Function _devfs_alloc_entry */
/**
* _devfs_append_entry - Append a devfs entry to a directory's child list.
* @dir: The directory to add to.
...
...
@@ -1009,41 +1004,46 @@ static struct devfs_entry *_devfs_alloc_entry (const char *name,
* On failure, an implicit devfs_put() is performed on %de.
*/
static
int
_devfs_append_entry
(
devfs_handle_t
dir
,
devfs_handle_t
de
,
devfs_handle_t
*
old_de
)
static
int
_devfs_append_entry
(
devfs_handle_t
dir
,
devfs_handle_t
de
,
devfs_handle_t
*
old_de
)
{
int
retval
;
if
(
old_de
)
*
old_de
=
NULL
;
if
(
!
S_ISDIR
(
dir
->
mode
)
)
{
PRINTK
(
"(%s): dir:
\"
%s
\"
is not a directory
\n
"
,
de
->
name
,
dir
->
name
);
devfs_put
(
de
);
if
(
old_de
)
*
old_de
=
NULL
;
if
(
!
S_ISDIR
(
dir
->
mode
))
{
PRINTK
(
"(%s): dir:
\"
%s
\"
is not a directory
\n
"
,
de
->
name
,
dir
->
name
);
devfs_put
(
de
);
return
-
ENOTDIR
;
}
write_lock
(
&
dir
->
u
.
dir
.
lock
);
if
(
dir
->
u
.
dir
.
no_more_additions
)
retval
=
-
ENOENT
;
else
{
write_lock
(
&
dir
->
u
.
dir
.
lock
);
if
(
dir
->
u
.
dir
.
no_more_additions
)
retval
=
-
ENOENT
;
else
{
struct
devfs_entry
*
old
;
old
=
_devfs_search_dir
(
dir
,
de
->
name
,
de
->
namelen
);
if
(
old_de
)
*
old_de
=
old
;
else
devfs_put
(
old
);
if
(
old
==
NULL
)
{
old
=
_devfs_search_dir
(
dir
,
de
->
name
,
de
->
namelen
);
if
(
old_de
)
*
old_de
=
old
;
else
devfs_put
(
old
);
if
(
old
==
NULL
)
{
de
->
parent
=
dir
;
de
->
prev
=
dir
->
u
.
dir
.
last
;
/* Append to the directory's list of children */
if
(
dir
->
u
.
dir
.
first
==
NULL
)
dir
->
u
.
dir
.
first
=
de
;
else
dir
->
u
.
dir
.
last
->
next
=
de
;
if
(
dir
->
u
.
dir
.
first
==
NULL
)
dir
->
u
.
dir
.
first
=
de
;
else
dir
->
u
.
dir
.
last
->
next
=
de
;
dir
->
u
.
dir
.
last
=
de
;
retval
=
0
;
}
else
retval
=
-
EEXIST
;
}
else
retval
=
-
EEXIST
;
}
write_unlock
(
&
dir
->
u
.
dir
.
lock
);
if
(
retval
)
devfs_put
(
de
);
write_unlock
(
&
dir
->
u
.
dir
.
lock
);
if
(
retval
)
devfs_put
(
de
);
return
retval
;
}
/* End Function _devfs_append_entry */
...
...
@@ -1067,7 +1067,7 @@ static struct devfs_entry *_devfs_get_root_entry(void)
return
root_entry
;
new
=
_devfs_alloc_entry
(
NULL
,
0
,
MODE_DIR
);
if
(
new
==
NULL
)
if
(
new
==
NULL
)
return
NULL
;
spin_lock
(
&
root_lock
);
...
...
@@ -1096,139 +1096,131 @@ static struct devfs_entry *_devfs_get_root_entry(void)
* An implicit devfs_get() is performed on the returned entry.
*/
static
struct
devfs_entry
*
_devfs_descend
(
struct
devfs_entry
*
dir
,
static
struct
devfs_entry
*
_devfs_descend
(
struct
devfs_entry
*
dir
,
const
char
*
name
,
int
namelen
,
int
*
next_pos
)
{
const
char
*
stop
,
*
ptr
;
struct
devfs_entry
*
entry
;
if
(
(
namelen
>=
3
)
&&
(
strncmp
(
name
,
"../"
,
3
)
==
0
)
)
{
/* Special-case going to parent directory */
if
((
namelen
>=
3
)
&&
(
strncmp
(
name
,
"../"
,
3
)
==
0
))
{
/* Special-case going to parent directory */
*
next_pos
=
3
;
return
devfs_get
(
dir
->
parent
);
return
devfs_get
(
dir
->
parent
);
}
stop
=
name
+
namelen
;
/* Search for a possible '/' */
for
(
ptr
=
name
;
(
ptr
<
stop
)
&&
(
*
ptr
!=
'/'
);
++
ptr
)
;
for
(
ptr
=
name
;
(
ptr
<
stop
)
&&
(
*
ptr
!=
'/'
);
++
ptr
)
;
*
next_pos
=
ptr
-
name
;
read_lock
(
&
dir
->
u
.
dir
.
lock
);
entry
=
_devfs_search_dir
(
dir
,
name
,
*
next_pos
);
read_unlock
(
&
dir
->
u
.
dir
.
lock
);
read_lock
(
&
dir
->
u
.
dir
.
lock
);
entry
=
_devfs_search_dir
(
dir
,
name
,
*
next_pos
);
read_unlock
(
&
dir
->
u
.
dir
.
lock
);
return
entry
;
}
/* End Function _devfs_descend */
static
devfs_handle_t
_devfs_make_parent_for_leaf
(
struct
devfs_entry
*
dir
,
static
devfs_handle_t
_devfs_make_parent_for_leaf
(
struct
devfs_entry
*
dir
,
const
char
*
name
,
int
namelen
,
int
*
leaf_pos
)
{
int
next_pos
=
0
;
if
(
dir
==
NULL
)
dir
=
_devfs_get_root_entry
();
if
(
dir
==
NULL
)
return
NULL
;
devfs_get
(
dir
);
if
(
dir
==
NULL
)
dir
=
_devfs_get_root_entry
();
if
(
dir
==
NULL
)
return
NULL
;
devfs_get
(
dir
);
/* Search for possible trailing component and ignore it */
for
(
--
namelen
;
(
namelen
>
0
)
&&
(
name
[
namelen
]
!=
'/'
);
--
namelen
)
;
for
(
--
namelen
;
(
namelen
>
0
)
&&
(
name
[
namelen
]
!=
'/'
);
--
namelen
)
;
*
leaf_pos
=
(
name
[
namelen
]
==
'/'
)
?
(
namelen
+
1
)
:
0
;
for
(;
namelen
>
0
;
name
+=
next_pos
,
namelen
-=
next_pos
)
{
for
(;
namelen
>
0
;
name
+=
next_pos
,
namelen
-=
next_pos
)
{
struct
devfs_entry
*
de
,
*
old
=
NULL
;
if
(
(
de
=
_devfs_descend
(
dir
,
name
,
namelen
,
&
next_pos
)
)
==
NULL
)
{
de
=
_devfs_alloc_entry
(
name
,
next_pos
,
MODE_DIR
);
devfs_get
(
de
);
if
(
!
de
||
_devfs_append_entry
(
dir
,
de
,
&
old
)
)
{
devfs_put
(
de
);
if
(
!
old
||
!
S_ISDIR
(
old
->
mode
)
)
{
devfs_put
(
old
);
devfs_put
(
dir
);
if
((
de
=
_devfs_descend
(
dir
,
name
,
namelen
,
&
next_pos
))
==
NULL
)
{
de
=
_devfs_alloc_entry
(
name
,
next_pos
,
MODE_DIR
);
devfs_get
(
de
);
if
(
!
de
||
_devfs_append_entry
(
dir
,
de
,
&
old
))
{
devfs_put
(
de
);
if
(
!
old
||
!
S_ISDIR
(
old
->
mode
))
{
devfs_put
(
old
);
devfs_put
(
dir
);
return
NULL
;
}
de
=
old
;
/* Use the existing directory */
}
}
if
(
de
==
dir
->
parent
)
{
devfs_put
(
dir
);
devfs_put
(
de
);
if
(
de
==
dir
->
parent
)
{
devfs_put
(
dir
);
devfs_put
(
de
);
return
NULL
;
}
devfs_put
(
dir
);
devfs_put
(
dir
);
dir
=
de
;
if
(
name
[
next_pos
]
==
'/'
)
++
next_pos
;
if
(
name
[
next_pos
]
==
'/'
)
++
next_pos
;
}
return
dir
;
}
/* End Function _devfs_make_parent_for_leaf */
static
devfs_handle_t
_devfs_prepare_leaf
(
devfs_handle_t
*
dir
,
static
devfs_handle_t
_devfs_prepare_leaf
(
devfs_handle_t
*
dir
,
const
char
*
name
,
umode_t
mode
)
{
int
namelen
,
leaf_pos
;
struct
devfs_entry
*
de
;
namelen
=
strlen
(
name
);
if
(
(
*
dir
=
_devfs_make_parent_for_leaf
(
*
dir
,
name
,
namelen
,
&
leaf_pos
)
)
==
NULL
)
{
PRINTK
(
"(%s): could not create parent path
\n
"
,
name
);
namelen
=
strlen
(
name
);
if
((
*
dir
=
_devfs_make_parent_for_leaf
(
*
dir
,
name
,
namelen
,
&
leaf_pos
))
==
NULL
)
{
PRINTK
(
"(%s): could not create parent path
\n
"
,
name
);
return
NULL
;
}
if
(
(
de
=
_devfs_alloc_entry
(
name
+
leaf_pos
,
namelen
-
leaf_pos
,
mode
)
)
==
NULL
)
{
PRINTK
(
"(%s): could not allocate entry
\n
"
,
name
);
devfs_put
(
*
dir
);
if
((
de
=
_devfs_alloc_entry
(
name
+
leaf_pos
,
namelen
-
leaf_pos
,
mode
))
==
NULL
)
{
PRINTK
(
"(%s): could not allocate entry
\n
"
,
name
);
devfs_put
(
*
dir
);
return
NULL
;
}
return
de
;
}
/* End Function _devfs_prepare_leaf */
static
devfs_handle_t
_devfs_walk_path
(
struct
devfs_entry
*
dir
,
static
devfs_handle_t
_devfs_walk_path
(
struct
devfs_entry
*
dir
,
const
char
*
name
,
int
namelen
,
int
traverse_symlink
)
{
int
next_pos
=
0
;
if
(
dir
==
NULL
)
dir
=
_devfs_get_root_entry
();
if
(
dir
==
NULL
)
return
NULL
;
devfs_get
(
dir
);
for
(;
namelen
>
0
;
name
+=
next_pos
,
namelen
-=
next_pos
)
{
if
(
dir
==
NULL
)
dir
=
_devfs_get_root_entry
();
if
(
dir
==
NULL
)
return
NULL
;
devfs_get
(
dir
);
for
(;
namelen
>
0
;
name
+=
next_pos
,
namelen
-=
next_pos
)
{
struct
devfs_entry
*
de
,
*
link
;
if
(
!
S_ISDIR
(
dir
->
mode
))
{
devfs_put
(
dir
);
if
(
!
S_ISDIR
(
dir
->
mode
))
{
devfs_put
(
dir
);
return
NULL
;
}
if
(
(
de
=
_devfs_descend
(
dir
,
name
,
namelen
,
&
next_pos
)
)
==
NULL
)
{
devfs_put
(
dir
);
if
((
de
=
_devfs_descend
(
dir
,
name
,
namelen
,
&
next_pos
))
==
NULL
)
{
devfs_put
(
dir
);
return
NULL
;
}
if
(
S_ISLNK
(
de
->
mode
)
&&
traverse_symlink
)
{
/* Need to follow the link: this is a stack chomper */
if
(
S_ISLNK
(
de
->
mode
)
&&
traverse_symlink
)
{
/* Need to follow the link: this is a stack chomper */
/* FIXME what if it puts outside of mounted tree? */
link
=
_devfs_walk_path
(
dir
,
de
->
u
.
symlink
.
linkname
,
link
=
_devfs_walk_path
(
dir
,
de
->
u
.
symlink
.
linkname
,
de
->
u
.
symlink
.
length
,
TRUE
);
devfs_put
(
de
);
if
(
!
link
)
{
devfs_put
(
dir
);
devfs_put
(
de
);
if
(
!
link
)
{
devfs_put
(
dir
);
return
NULL
;
}
de
=
link
;
}
devfs_put
(
dir
);
devfs_put
(
dir
);
dir
=
de
;
if
(
name
[
next_pos
]
==
'/'
)
++
next_pos
;
if
(
name
[
next_pos
]
==
'/'
)
++
next_pos
;
}
return
dir
;
}
/* End Function _devfs_walk_path */
...
...
@@ -1244,41 +1236,38 @@ static devfs_handle_t _devfs_walk_path (struct devfs_entry *dir,
* devfs_get() is performed.
*/
static
struct
devfs_entry
*
_devfs_find_entry
(
devfs_handle_t
dir
,
static
struct
devfs_entry
*
_devfs_find_entry
(
devfs_handle_t
dir
,
const
char
*
name
,
int
traverse_symlink
)
{
unsigned
int
namelen
=
strlen
(
name
);
unsigned
int
namelen
=
strlen
(
name
);
if
(
name
[
0
]
==
'/'
)
{
if
(
name
[
0
]
==
'/'
)
{
/* Skip leading pathname component */
if
(
namelen
<
2
)
{
PRINTK
(
"(%s): too short
\n
"
,
name
);
if
(
namelen
<
2
)
{
PRINTK
(
"(%s): too short
\n
"
,
name
);
return
NULL
;
}
for
(
++
name
,
--
namelen
;
(
*
name
!=
'/'
)
&&
(
namelen
>
0
);
++
name
,
--
namelen
);
if
(
namelen
<
2
)
{
PRINTK
(
"(%s): too short
\n
"
,
name
);
++
name
,
--
namelen
)
;
if
(
namelen
<
2
)
{
PRINTK
(
"(%s): too short
\n
"
,
name
);
return
NULL
;
}
++
name
;
--
namelen
;
}
return
_devfs_walk_path
(
dir
,
name
,
namelen
,
traverse_symlink
);
return
_devfs_walk_path
(
dir
,
name
,
namelen
,
traverse_symlink
);
}
/* End Function _devfs_find_entry */
static
struct
devfs_entry
*
get_devfs_entry_from_vfs_inode
(
struct
inode
*
inode
)
static
struct
devfs_entry
*
get_devfs_entry_from_vfs_inode
(
struct
inode
*
inode
)
{
if
(
inode
==
NULL
)
return
NULL
;
VERIFY_ENTRY
(
(
struct
devfs_entry
*
)
inode
->
u
.
generic_ip
);
if
(
inode
==
NULL
)
return
NULL
;
VERIFY_ENTRY
((
struct
devfs_entry
*
)
inode
->
u
.
generic_ip
);
return
inode
->
u
.
generic_ip
;
}
/* End Function get_devfs_entry_from_vfs_inode */
/**
* free_dentry - Free the dentry for a device entry and invalidate inode.
* @de: The entry.
...
...
@@ -1287,21 +1276,22 @@ static struct devfs_entry *get_devfs_entry_from_vfs_inode (struct inode *inode)
* parent directory.
*/
static
void
free_dentry
(
struct
devfs_entry
*
de
)
static
void
free_dentry
(
struct
devfs_entry
*
de
)
{
struct
dentry
*
dentry
=
de
->
inode
.
dentry
;
if
(
!
dentry
)
return
;
spin_lock
(
&
dcache_lock
);
dget_locked
(
dentry
);
spin_unlock
(
&
dcache_lock
);
if
(
!
dentry
)
return
;
spin_lock
(
&
dcache_lock
);
dget_locked
(
dentry
);
spin_unlock
(
&
dcache_lock
);
/* Forcefully remove the inode */
if
(
dentry
->
d_inode
!=
NULL
)
dentry
->
d_inode
->
i_nlink
=
0
;
d_drop
(
dentry
);
dput
(
dentry
);
if
(
dentry
->
d_inode
!=
NULL
)
dentry
->
d_inode
->
i_nlink
=
0
;
d_drop
(
dentry
);
dput
(
dentry
);
}
/* End Function free_dentry */
/**
* is_devfsd_or_child - Test if the current process is devfsd or one of its children.
* @fs_info: The filesystem information.
...
...
@@ -1309,26 +1299,25 @@ static void free_dentry (struct devfs_entry *de)
* Returns %TRUE if devfsd or child, else %FALSE.
*/
static
int
is_devfsd_or_child
(
struct
fs_info
*
fs_info
)
static
int
is_devfsd_or_child
(
struct
fs_info
*
fs_info
)
{
struct
task_struct
*
p
=
current
;
if
(
p
==
fs_info
->
devfsd_task
)
return
(
TRUE
);
if
(
process_group
(
p
)
==
fs_info
->
devfsd_pgrp
)
return
(
TRUE
);
read_lock
(
&
tasklist_lock
);
for
(
;
p
!=
&
init_task
;
p
=
p
->
real_parent
)
{
if
(
p
==
fs_info
->
devfsd_task
)
{
read_unlock
(
&
tasklist_lock
);
return
(
TRUE
);
if
(
process_group
(
p
)
==
fs_info
->
devfsd_pgrp
)
return
(
TRUE
);
read_lock
(
&
tasklist_lock
);
for
(;
p
!=
&
init_task
;
p
=
p
->
real_parent
)
{
if
(
p
==
fs_info
->
devfsd_task
)
{
read_unlock
(
&
tasklist_lock
);
return
(
TRUE
);
}
}
read_unlock
(
&
tasklist_lock
);
read_unlock
(
&
tasklist_lock
);
return
(
FALSE
);
}
/* End Function is_devfsd_or_child */
/**
* devfsd_queue_empty - Test if devfsd has work pending in its event queue.
* @fs_info: The filesystem information.
...
...
@@ -1336,12 +1325,11 @@ static int is_devfsd_or_child (struct fs_info *fs_info)
* Returns %TRUE if the queue is empty, else %FALSE.
*/
static
inline
int
devfsd_queue_empty
(
struct
fs_info
*
fs_info
)
static
inline
int
devfsd_queue_empty
(
struct
fs_info
*
fs_info
)
{
return
(
fs_info
->
devfsd_last_event
)
?
FALSE
:
TRUE
;
}
/* End Function devfsd_queue_empty */
/**
* wait_for_devfsd_finished - Wait for devfsd to finish processing its event queue.
* @fs_info: The filesystem information.
...
...
@@ -1349,23 +1337,26 @@ static inline int devfsd_queue_empty (struct fs_info *fs_info)
* Returns %TRUE if no more waiting will be required, else %FALSE.
*/
static
int
wait_for_devfsd_finished
(
struct
fs_info
*
fs_info
)
static
int
wait_for_devfsd_finished
(
struct
fs_info
*
fs_info
)
{
DECLARE_WAITQUEUE
(
wait
,
current
);
if
(
fs_info
->
devfsd_task
==
NULL
)
return
(
TRUE
);
if
(
devfsd_queue_empty
(
fs_info
)
&&
fs_info
->
devfsd_sleeping
)
return
TRUE
;
if
(
is_devfsd_or_child
(
fs_info
)
)
return
(
FALSE
);
set_current_state
(
TASK_UNINTERRUPTIBLE
);
add_wait_queue
(
&
fs_info
->
revalidate_wait_queue
,
&
wait
);
if
(
!
devfsd_queue_empty
(
fs_info
)
||
!
fs_info
->
devfsd_sleeping
)
if
(
fs_info
->
devfsd_task
)
schedule
();
remove_wait_queue
(
&
fs_info
->
revalidate_wait_queue
,
&
wait
);
__set_current_state
(
TASK_RUNNING
);
DECLARE_WAITQUEUE
(
wait
,
current
);
if
(
fs_info
->
devfsd_task
==
NULL
)
return
(
TRUE
);
if
(
devfsd_queue_empty
(
fs_info
)
&&
fs_info
->
devfsd_sleeping
)
return
TRUE
;
if
(
is_devfsd_or_child
(
fs_info
))
return
(
FALSE
);
set_current_state
(
TASK_UNINTERRUPTIBLE
);
add_wait_queue
(
&
fs_info
->
revalidate_wait_queue
,
&
wait
);
if
(
!
devfsd_queue_empty
(
fs_info
)
||
!
fs_info
->
devfsd_sleeping
)
if
(
fs_info
->
devfsd_task
)
schedule
();
remove_wait_queue
(
&
fs_info
->
revalidate_wait_queue
,
&
wait
);
__set_current_state
(
TASK_RUNNING
);
return
(
TRUE
);
}
/* End Function wait_for_devfsd_finished */
/**
* devfsd_notify_de - Notify the devfsd daemon of a change.
* @de: The devfs entry that has changed. This and all parent entries will
...
...
@@ -1379,36 +1370,38 @@ static int wait_for_devfsd_finished (struct fs_info *fs_info)
* Returns %TRUE if an event was queued and devfsd woken up, else %FALSE.
*/
static
int
devfsd_notify_de
(
struct
devfs_entry
*
de
,
static
int
devfsd_notify_de
(
struct
devfs_entry
*
de
,
unsigned
short
type
,
umode_t
mode
,
uid_t
uid
,
gid_t
gid
,
struct
fs_info
*
fs_info
)
{
struct
devfsd_buf_entry
*
entry
;
struct
devfs_entry
*
curr
;
if
(
!
(
fs_info
->
devfsd_event_mask
&
(
1
<<
type
)
)
)
return
(
FALSE
);
if
(
(
entry
=
kmem_cache_alloc
(
devfsd_buf_cache
,
SLAB_KERNEL
)
)
==
NULL
)
{
atomic_inc
(
&
fs_info
->
devfsd_overrun_count
);
if
(
!
(
fs_info
->
devfsd_event_mask
&
(
1
<<
type
)))
return
(
FALSE
);
if
((
entry
=
kmem_cache_alloc
(
devfsd_buf_cache
,
SLAB_KERNEL
))
==
NULL
)
{
atomic_inc
(
&
fs_info
->
devfsd_overrun_count
);
return
(
FALSE
);
}
for
(
curr
=
de
;
curr
!=
NULL
;
curr
=
curr
->
parent
)
devfs_get
(
curr
);
for
(
curr
=
de
;
curr
!=
NULL
;
curr
=
curr
->
parent
)
devfs_get
(
curr
);
entry
->
de
=
de
;
entry
->
type
=
type
;
entry
->
mode
=
mode
;
entry
->
uid
=
uid
;
entry
->
gid
=
gid
;
entry
->
next
=
NULL
;
spin_lock
(
&
fs_info
->
devfsd_buffer_lock
);
if
(
!
fs_info
->
devfsd_first_event
)
fs_info
->
devfsd_first_event
=
entry
;
if
(
fs_info
->
devfsd_last_event
)
fs_info
->
devfsd_last_event
->
next
=
entry
;
spin_lock
(
&
fs_info
->
devfsd_buffer_lock
);
if
(
!
fs_info
->
devfsd_first_event
)
fs_info
->
devfsd_first_event
=
entry
;
if
(
fs_info
->
devfsd_last_event
)
fs_info
->
devfsd_last_event
->
next
=
entry
;
fs_info
->
devfsd_last_event
=
entry
;
spin_unlock
(
&
fs_info
->
devfsd_buffer_lock
);
wake_up_interruptible
(
&
fs_info
->
devfsd_wait_queue
);
spin_unlock
(
&
fs_info
->
devfsd_buffer_lock
);
wake_up_interruptible
(
&
fs_info
->
devfsd_wait_queue
);
return
(
TRUE
);
}
/* End Function devfsd_notify_de */
/**
* devfsd_notify - Notify the devfsd daemon of a change.
* @de: The devfs entry that has changed.
...
...
@@ -1417,7 +1410,7 @@ static int devfsd_notify_de (struct devfs_entry *de,
* the event.
*/
static
void
devfsd_notify
(
struct
devfs_entry
*
de
,
unsigned
short
type
)
static
void
devfsd_notify
(
struct
devfs_entry
*
de
,
unsigned
short
type
)
{
devfsd_notify_de
(
de
,
type
,
de
->
mode
,
current
->
euid
,
current
->
egid
,
&
fs_info
);
...
...
@@ -1474,7 +1467,6 @@ int devfs_mk_bdev(dev_t dev, umode_t mode, const char *fmt, ...)
EXPORT_SYMBOL
(
devfs_mk_bdev
);
int
devfs_mk_cdev
(
dev_t
dev
,
umode_t
mode
,
const
char
*
fmt
,
...)
{
va_list
args
;
...
...
@@ -1491,7 +1483,6 @@ int devfs_mk_cdev(dev_t dev, umode_t mode, const char *fmt, ...)
EXPORT_SYMBOL
(
devfs_mk_cdev
);
/**
* _devfs_unhook - Unhook a device entry from its parents list
* @de: The entry to unhook.
...
...
@@ -1501,22 +1492,26 @@ EXPORT_SYMBOL(devfs_mk_cdev);
* The caller must have a write lock on the parent directory.
*/
static
int
_devfs_unhook
(
struct
devfs_entry
*
de
)
static
int
_devfs_unhook
(
struct
devfs_entry
*
de
)
{
struct
devfs_entry
*
parent
;
if
(
!
de
||
(
de
->
prev
==
de
)
)
return
FALSE
;
if
(
!
de
||
(
de
->
prev
==
de
))
return
FALSE
;
parent
=
de
->
parent
;
if
(
de
->
prev
==
NULL
)
parent
->
u
.
dir
.
first
=
de
->
next
;
else
de
->
prev
->
next
=
de
->
next
;
if
(
de
->
next
==
NULL
)
parent
->
u
.
dir
.
last
=
de
->
prev
;
else
de
->
next
->
prev
=
de
->
prev
;
if
(
de
->
prev
==
NULL
)
parent
->
u
.
dir
.
first
=
de
->
next
;
else
de
->
prev
->
next
=
de
->
next
;
if
(
de
->
next
==
NULL
)
parent
->
u
.
dir
.
last
=
de
->
prev
;
else
de
->
next
->
prev
=
de
->
prev
;
de
->
prev
=
de
;
/* Indicate we're unhooked */
de
->
next
=
NULL
;
/* Force early termination for <devfs_readdir> */
return
TRUE
;
}
/* End Function _devfs_unhook */
/**
* _devfs_unregister - Unregister a device entry from its parent.
* @dir: The parent directory.
...
...
@@ -1526,84 +1521,84 @@ static int _devfs_unhook (struct devfs_entry *de)
* unlocked by this function.
*/
static
void
_devfs_unregister
(
struct
devfs_entry
*
dir
,
struct
devfs_entry
*
de
)
static
void
_devfs_unregister
(
struct
devfs_entry
*
dir
,
struct
devfs_entry
*
de
)
{
int
unhooked
=
_devfs_unhook
(
de
);
write_unlock
(
&
dir
->
u
.
dir
.
lock
);
if
(
!
unhooked
)
return
;
devfs_get
(
dir
);
devfsd_notify
(
de
,
DEVFSD_NOTIFY_UNREGISTERED
);
free_dentry
(
de
);
devfs_put
(
dir
);
if
(
!
S_ISDIR
(
de
->
mode
)
)
return
;
while
(
TRUE
)
/* Recursively unregister: this is a stack chomper */
{
int
unhooked
=
_devfs_unhook
(
de
);
write_unlock
(
&
dir
->
u
.
dir
.
lock
);
if
(
!
unhooked
)
return
;
devfs_get
(
dir
);
devfsd_notify
(
de
,
DEVFSD_NOTIFY_UNREGISTERED
);
free_dentry
(
de
);
devfs_put
(
dir
);
if
(
!
S_ISDIR
(
de
->
mode
))
return
;
while
(
TRUE
)
{
/* Recursively unregister: this is a stack chomper */
struct
devfs_entry
*
child
;
write_lock
(
&
de
->
u
.
dir
.
lock
);
write_lock
(
&
de
->
u
.
dir
.
lock
);
de
->
u
.
dir
.
no_more_additions
=
TRUE
;
child
=
de
->
u
.
dir
.
first
;
VERIFY_ENTRY
(
child
);
_devfs_unregister
(
de
,
child
);
if
(
!
child
)
break
;
DPRINTK
(
DEBUG_UNREGISTER
,
"(%s): child: %p refcount: %d
\n
"
,
child
->
name
,
child
,
atomic_read
(
&
child
->
refcount
)
);
devfs_put
(
child
);
VERIFY_ENTRY
(
child
);
_devfs_unregister
(
de
,
child
);
if
(
!
child
)
break
;
DPRINTK
(
DEBUG_UNREGISTER
,
"(%s): child: %p refcount: %d
\n
"
,
child
->
name
,
child
,
atomic_read
(
&
child
->
refcount
));
devfs_put
(
child
);
}
}
/* End Function _devfs_unregister */
static
int
devfs_do_symlink
(
devfs_handle_t
dir
,
const
char
*
name
,
const
char
*
link
,
devfs_handle_t
*
handle
)
static
int
devfs_do_symlink
(
devfs_handle_t
dir
,
const
char
*
name
,
const
char
*
link
,
devfs_handle_t
*
handle
)
{
int
err
;
unsigned
int
linklength
;
char
*
newlink
;
struct
devfs_entry
*
de
;
if
(
handle
!=
NULL
)
*
handle
=
NULL
;
if
(
name
==
NULL
)
{
PRINTK
(
"(): NULL name pointer
\n
"
);
if
(
handle
!=
NULL
)
*
handle
=
NULL
;
if
(
name
==
NULL
)
{
PRINTK
(
"(): NULL name pointer
\n
"
);
return
-
EINVAL
;
}
if
(
link
==
NULL
)
{
PRINTK
(
"(%s): NULL link pointer
\n
"
,
name
);
if
(
link
==
NULL
)
{
PRINTK
(
"(%s): NULL link pointer
\n
"
,
name
);
return
-
EINVAL
;
}
linklength
=
strlen
(
link
);
if
(
(
newlink
=
kmalloc
(
linklength
+
1
,
GFP_KERNEL
)
)
==
NULL
)
linklength
=
strlen
(
link
);
if
((
newlink
=
kmalloc
(
linklength
+
1
,
GFP_KERNEL
))
==
NULL
)
return
-
ENOMEM
;
memcpy
(
newlink
,
link
,
linklength
);
memcpy
(
newlink
,
link
,
linklength
);
newlink
[
linklength
]
=
'\0'
;
if
(
(
de
=
_devfs_prepare_leaf
(
&
dir
,
name
,
S_IFLNK
|
S_IRUGO
|
S_IXUGO
)
)
==
NULL
)
{
PRINTK
(
"(%s): could not prepare leaf
\n
"
,
name
);
kfree
(
newlink
);
if
((
de
=
_devfs_prepare_leaf
(
&
dir
,
name
,
S_IFLNK
|
S_IRUGO
|
S_IXUGO
))
==
NULL
)
{
PRINTK
(
"(%s): could not prepare leaf
\n
"
,
name
);
kfree
(
newlink
);
return
-
ENOTDIR
;
}
de
->
info
=
NULL
;
de
->
u
.
symlink
.
linkname
=
newlink
;
de
->
u
.
symlink
.
length
=
linklength
;
if
(
(
err
=
_devfs_append_entry
(
dir
,
de
,
NULL
)
)
!=
0
)
{
PRINTK
(
"(%s): could not append to parent, err: %d
\n
"
,
name
,
err
);
devfs_put
(
dir
);
if
((
err
=
_devfs_append_entry
(
dir
,
de
,
NULL
))
!=
0
)
{
PRINTK
(
"(%s): could not append to parent, err: %d
\n
"
,
name
,
err
);
devfs_put
(
dir
);
return
err
;
}
devfs_put
(
dir
);
devfs_put
(
dir
);
#ifdef CONFIG_DEVFS_DEBUG
spin_lock
(
&
stat_lock
);
spin_lock
(
&
stat_lock
);
stat_num_bytes
+=
linklength
+
1
;
spin_unlock
(
&
stat_lock
);
spin_unlock
(
&
stat_lock
);
#endif
if
(
handle
!=
NULL
)
*
handle
=
de
;
if
(
handle
!=
NULL
)
*
handle
=
de
;
return
0
;
}
/* End Function devfs_do_symlink */
/**
* devfs_mk_symlink Create a symbolic link in the devfs namespace.
* @from: The name of the entry.
...
...
@@ -1626,7 +1621,6 @@ int devfs_mk_symlink(const char *from, const char *to)
return
err
;
}
/**
* devfs_mk_dir - Create a directory in the devfs namespace.
* new name is relative to the root of the devfs.
...
...
@@ -1680,7 +1674,6 @@ int devfs_mk_dir(const char *fmt, ...)
return
error
;
}
void
devfs_remove
(
const
char
*
fmt
,
...)
{
char
buf
[
64
];
...
...
@@ -1706,7 +1699,6 @@ void devfs_remove(const char *fmt, ...)
}
}
/**
* devfs_generate_path - Generate a pathname for an entry, relative to the devfs root.
* @de: The devfs entry.
...
...
@@ -1718,24 +1710,27 @@ void devfs_remove(const char *fmt, ...)
* else a negative error code.
*/
static
int
devfs_generate_path
(
devfs_handle_t
de
,
char
*
path
,
int
buflen
)
static
int
devfs_generate_path
(
devfs_handle_t
de
,
char
*
path
,
int
buflen
)
{
int
pos
;
#define NAMEOF(de) ( (de)->mode ? (de)->name : (de)->u.name )
if
(
de
==
NULL
)
return
-
EINVAL
;
VERIFY_ENTRY
(
de
);
if
(
de
->
namelen
>=
buflen
)
return
-
ENAMETOOLONG
;
/* Must be first */
if
(
de
==
NULL
)
return
-
EINVAL
;
VERIFY_ENTRY
(
de
);
if
(
de
->
namelen
>=
buflen
)
return
-
ENAMETOOLONG
;
/* Must be first */
path
[
buflen
-
1
]
=
'\0'
;
if
(
de
->
parent
==
NULL
)
return
buflen
-
1
;
/* Don't prepend root */
if
(
de
->
parent
==
NULL
)
return
buflen
-
1
;
/* Don't prepend root */
pos
=
buflen
-
de
->
namelen
-
1
;
memcpy
(
path
+
pos
,
NAMEOF
(
de
),
de
->
namelen
);
for
(
de
=
de
->
parent
;
de
->
parent
!=
NULL
;
de
=
de
->
parent
)
{
if
(
pos
-
de
->
namelen
-
1
<
0
)
return
-
ENAMETOOLONG
;
memcpy
(
path
+
pos
,
NAMEOF
(
de
),
de
->
namelen
);
for
(
de
=
de
->
parent
;
de
->
parent
!=
NULL
;
de
=
de
->
parent
)
{
if
(
pos
-
de
->
namelen
-
1
<
0
)
return
-
ENAMETOOLONG
;
path
[
--
pos
]
=
'/'
;
pos
-=
de
->
namelen
;
memcpy
(
path
+
pos
,
NAMEOF
(
de
),
de
->
namelen
);
memcpy
(
path
+
pos
,
NAMEOF
(
de
),
de
->
namelen
);
}
return
pos
;
}
/* End Function devfs_generate_path */
...
...
@@ -1745,59 +1740,59 @@ static int devfs_generate_path (devfs_handle_t de, char *path, int buflen)
* @str: The boot options after the "devfs=".
*/
static
int
__init
devfs_setup
(
char
*
str
)
static
int
__init
devfs_setup
(
char
*
str
)
{
static
struct
{
static
struct
{
char
*
name
;
unsigned
int
mask
;
unsigned
int
*
opt
;
}
devfs_options_tab
[]
__initdata
=
{
}
devfs_options_tab
[]
__initdata
=
{
#ifdef CONFIG_DEVFS_DEBUG
{
"dall"
,
DEBUG_ALL
,
&
devfs_debug_init
},
{
"dmod"
,
DEBUG_MODULE_LOAD
,
&
devfs_debug_init
},
{
"dreg"
,
DEBUG_REGISTER
,
&
devfs_debug_init
},
{
"dunreg"
,
DEBUG_UNREGISTER
,
&
devfs_debug_init
},
{
"dfree"
,
DEBUG_FREE
,
&
devfs_debug_init
},
{
"diget"
,
DEBUG_I_GET
,
&
devfs_debug_init
},
{
"dchange"
,
DEBUG_SET_FLAGS
,
&
devfs_debug_init
},
{
"dsread"
,
DEBUG_S_READ
,
&
devfs_debug_init
},
{
"dichange"
,
DEBUG_I_CHANGE
,
&
devfs_debug_init
},
{
"dimknod"
,
DEBUG_I_MKNOD
,
&
devfs_debug_init
},
{
"dilookup"
,
DEBUG_I_LOOKUP
,
&
devfs_debug_init
},
{
"diunlink"
,
DEBUG_I_UNLINK
,
&
devfs_debug_init
},
{
"dall"
,
DEBUG_ALL
,
&
devfs_debug_init
},
{
"dmod"
,
DEBUG_MODULE_LOAD
,
&
devfs_debug_init
},
{
"dreg"
,
DEBUG_REGISTER
,
&
devfs_debug_init
},
{
"dunreg"
,
DEBUG_UNREGISTER
,
&
devfs_debug_init
},
{
"dfree"
,
DEBUG_FREE
,
&
devfs_debug_init
},
{
"diget"
,
DEBUG_I_GET
,
&
devfs_debug_init
},
{
"dchange"
,
DEBUG_SET_FLAGS
,
&
devfs_debug_init
},
{
"dsread"
,
DEBUG_S_READ
,
&
devfs_debug_init
},
{
"dichange"
,
DEBUG_I_CHANGE
,
&
devfs_debug_init
},
{
"dimknod"
,
DEBUG_I_MKNOD
,
&
devfs_debug_init
},
{
"dilookup"
,
DEBUG_I_LOOKUP
,
&
devfs_debug_init
},
{
"diunlink"
,
DEBUG_I_UNLINK
,
&
devfs_debug_init
},
#endif
/* CONFIG_DEVFS_DEBUG */
{
"mount"
,
OPTION_MOUNT
,
&
boot_options
},
{
NULL
,
0
,
NULL
}
{
"mount"
,
OPTION_MOUNT
,
&
boot_options
},
{
NULL
,
0
,
NULL
}
};
while
(
(
*
str
!=
'\0'
)
&&
!
isspace
(
*
str
)
)
{
while
((
*
str
!=
'\0'
)
&&
!
isspace
(
*
str
))
{
int
i
,
found
=
0
,
invert
=
0
;
if
(
strncmp
(
str
,
"no"
,
2
)
==
0
)
{
if
(
strncmp
(
str
,
"no"
,
2
)
==
0
)
{
invert
=
1
;
str
+=
2
;
}
for
(
i
=
0
;
devfs_options_tab
[
i
].
name
!=
NULL
;
i
++
)
{
int
len
=
strlen
(
devfs_options_tab
[
i
].
name
);
for
(
i
=
0
;
devfs_options_tab
[
i
].
name
!=
NULL
;
i
++
)
{
int
len
=
strlen
(
devfs_options_tab
[
i
].
name
);
if
(
strncmp
(
str
,
devfs_options_tab
[
i
].
name
,
len
)
==
0
)
{
if
(
strncmp
(
str
,
devfs_options_tab
[
i
].
name
,
len
)
==
0
)
{
if
(
invert
)
*
devfs_options_tab
[
i
].
opt
&=
~
devfs_options_tab
[
i
].
mask
;
*
devfs_options_tab
[
i
].
opt
&=
~
devfs_options_tab
[
i
].
mask
;
else
*
devfs_options_tab
[
i
].
opt
|=
devfs_options_tab
[
i
].
mask
;
*
devfs_options_tab
[
i
].
opt
|=
devfs_options_tab
[
i
].
mask
;
str
+=
len
;
found
=
1
;
break
;
}
}
if
(
!
found
)
return
0
;
/* No match */
if
(
*
str
!=
','
)
return
0
;
/* No more options */
if
(
!
found
)
return
0
;
/* No match */
if
(
*
str
!=
','
)
return
0
;
/* No more options */
++
str
;
}
return
1
;
...
...
@@ -1809,7 +1804,6 @@ EXPORT_SYMBOL(devfs_mk_symlink);
EXPORT_SYMBOL
(
devfs_mk_dir
);
EXPORT_SYMBOL
(
devfs_remove
);
/**
* try_modload - Notify devfsd of an inode lookup by a non-devfsd process.
* @parent: The parent devfs entry.
...
...
@@ -1822,27 +1816,27 @@ EXPORT_SYMBOL(devfs_remove);
* Returns 0 on success (event was queued), else a negative error code.
*/
static
int
try_modload
(
struct
devfs_entry
*
parent
,
struct
fs_info
*
fs_info
,
static
int
try_modload
(
struct
devfs_entry
*
parent
,
struct
fs_info
*
fs_info
,
const
char
*
name
,
unsigned
namelen
,
struct
devfs_entry
*
buf
)
{
if
(
!
(
fs_info
->
devfsd_event_mask
&
(
1
<<
DEVFSD_NOTIFY_LOOKUP
)
)
)
if
(
!
(
fs_info
->
devfsd_event_mask
&
(
1
<<
DEVFSD_NOTIFY_LOOKUP
)))
return
-
ENOENT
;
if
(
is_devfsd_or_child
(
fs_info
))
return
-
ENOENT
;
if
(
is_devfsd_or_child
(
fs_info
)
)
return
-
ENOENT
;
memset
(
buf
,
0
,
sizeof
*
buf
);
atomic_set
(
&
buf
->
refcount
,
1
);
memset
(
buf
,
0
,
sizeof
*
buf
);
atomic_set
(
&
buf
->
refcount
,
1
);
buf
->
parent
=
parent
;
buf
->
namelen
=
namelen
;
buf
->
u
.
name
=
name
;
WRITE_ENTRY_MAGIC
(
buf
,
MAGIC_VALUE
);
if
(
!
devfsd_notify_de
(
buf
,
DEVFSD_NOTIFY_LOOKUP
,
0
,
current
->
euid
,
current
->
egid
,
fs_info
)
)
WRITE_ENTRY_MAGIC
(
buf
,
MAGIC_VALUE
);
if
(
!
devfsd_notify_de
(
buf
,
DEVFSD_NOTIFY_LOOKUP
,
0
,
current
->
euid
,
current
->
egid
,
fs_info
)
)
return
-
ENOENT
;
/* Possible success: event has been queued */
return
0
;
}
/* End Function try_modload */
/* Superblock operations follow */
static
struct
inode_operations
devfs_iops
;
...
...
@@ -1851,23 +1845,26 @@ static struct file_operations devfs_fops;
static
struct
file_operations
devfs_dir_fops
;
static
struct
inode_operations
devfs_symlink_iops
;
static
int
devfs_notify_change
(
struct
dentry
*
dentry
,
struct
iattr
*
iattr
)
static
int
devfs_notify_change
(
struct
dentry
*
dentry
,
struct
iattr
*
iattr
)
{
int
retval
;
struct
devfs_entry
*
de
;
struct
inode
*
inode
=
dentry
->
d_inode
;
struct
fs_info
*
fs_info
=
inode
->
i_sb
->
s_fs_info
;
de
=
get_devfs_entry_from_vfs_inode
(
inode
);
if
(
de
==
NULL
)
return
-
ENODEV
;
retval
=
inode_change_ok
(
inode
,
iattr
);
if
(
retval
!=
0
)
return
retval
;
retval
=
inode_setattr
(
inode
,
iattr
);
if
(
retval
!=
0
)
return
retval
;
DPRINTK
(
DEBUG_I_CHANGE
,
"(%d): VFS inode: %p devfs_entry: %p
\n
"
,
(
int
)
inode
->
i_ino
,
inode
,
de
);
DPRINTK
(
DEBUG_I_CHANGE
,
"(): mode: 0%o uid: %d gid: %d
\n
"
,
(
int
)
inode
->
i_mode
,
(
int
)
inode
->
i_uid
,
(
int
)
inode
->
i_gid
);
de
=
get_devfs_entry_from_vfs_inode
(
inode
);
if
(
de
==
NULL
)
return
-
ENODEV
;
retval
=
inode_change_ok
(
inode
,
iattr
);
if
(
retval
!=
0
)
return
retval
;
retval
=
inode_setattr
(
inode
,
iattr
);
if
(
retval
!=
0
)
return
retval
;
DPRINTK
(
DEBUG_I_CHANGE
,
"(%d): VFS inode: %p devfs_entry: %p
\n
"
,
(
int
)
inode
->
i_ino
,
inode
,
de
);
DPRINTK
(
DEBUG_I_CHANGE
,
"(): mode: 0%o uid: %d gid: %d
\n
"
,
(
int
)
inode
->
i_mode
,
(
int
)
inode
->
i_uid
,
(
int
)
inode
->
i_gid
);
/* Inode is not on hash chains, thus must save permissions here rather
than in a write_inode() method */
de
->
mode
=
inode
->
i_mode
;
...
...
@@ -1876,20 +1873,18 @@ static int devfs_notify_change (struct dentry *dentry, struct iattr *iattr)
de
->
inode
.
atime
=
inode
->
i_atime
;
de
->
inode
.
mtime
=
inode
->
i_mtime
;
de
->
inode
.
ctime
=
inode
->
i_ctime
;
if
(
(
iattr
->
ia_valid
&
(
ATTR_MODE
|
ATTR_UID
|
ATTR_GID
)
)
&&
!
is_devfsd_or_child
(
fs_info
)
)
devfsd_notify_de
(
de
,
DEVFSD_NOTIFY_CHANGE
,
inode
->
i_mode
,
if
((
iattr
->
ia_valid
&
(
ATTR_MODE
|
ATTR_UID
|
ATTR_GID
)
)
&&
!
is_devfsd_or_child
(
fs_info
)
)
devfsd_notify_de
(
de
,
DEVFSD_NOTIFY_CHANGE
,
inode
->
i_mode
,
inode
->
i_uid
,
inode
->
i_gid
,
fs_info
);
return
0
;
}
/* End Function devfs_notify_change */
static
struct
super_operations
devfs_sops
=
{
static
struct
super_operations
devfs_sops
=
{
.
drop_inode
=
generic_delete_inode
,
.
statfs
=
simple_statfs
,
};
/**
* _devfs_get_vfs_inode - Get a VFS inode.
* @sb: The super block.
...
...
@@ -1900,35 +1895,34 @@ static struct super_operations devfs_sops =
* performed if the inode is created.
*/
static
struct
inode
*
_devfs_get_vfs_inode
(
struct
super_block
*
sb
,
static
struct
inode
*
_devfs_get_vfs_inode
(
struct
super_block
*
sb
,
struct
devfs_entry
*
de
,
struct
dentry
*
dentry
)
{
struct
inode
*
inode
;
if
(
de
->
prev
==
de
)
return
NULL
;
/* Quick check to see if unhooked */
if
(
(
inode
=
new_inode
(
sb
)
)
==
NULL
)
{
PRINTK
(
"(%s): new_inode() failed, de: %p
\n
"
,
de
->
name
,
de
);
if
(
de
->
prev
==
de
)
return
NULL
;
/* Quick check to see if unhooked */
if
((
inode
=
new_inode
(
sb
))
==
NULL
)
{
PRINTK
(
"(%s): new_inode() failed, de: %p
\n
"
,
de
->
name
,
de
);
return
NULL
;
}
if
(
de
->
parent
)
{
read_lock
(
&
de
->
parent
->
u
.
dir
.
lock
);
if
(
de
->
prev
!=
de
)
de
->
inode
.
dentry
=
dentry
;
/* Not unhooked */
read_unlock
(
&
de
->
parent
->
u
.
dir
.
lock
);
}
else
de
->
inode
.
dentry
=
dentry
;
/* Root: no locking needed */
if
(
de
->
inode
.
dentry
!=
dentry
)
{
/* Must have been unhooked */
iput
(
inode
);
if
(
de
->
parent
)
{
read_lock
(
&
de
->
parent
->
u
.
dir
.
lock
);
if
(
de
->
prev
!=
de
)
de
->
inode
.
dentry
=
dentry
;
/* Not unhooked */
read_unlock
(
&
de
->
parent
->
u
.
dir
.
lock
);
}
else
de
->
inode
.
dentry
=
dentry
;
/* Root: no locking needed */
if
(
de
->
inode
.
dentry
!=
dentry
)
{
/* Must have been unhooked */
iput
(
inode
);
return
NULL
;
}
/* FIXME where is devfs_put? */
inode
->
u
.
generic_ip
=
devfs_get
(
de
);
inode
->
u
.
generic_ip
=
devfs_get
(
de
);
inode
->
i_ino
=
de
->
inode
.
ino
;
DPRINTK
(
DEBUG_I_GET
,
"(%d): VFS inode: %p devfs_entry: %p
\n
"
,
(
int
)
inode
->
i_ino
,
inode
,
de
);
DPRINTK
(
DEBUG_I_GET
,
"(%d): VFS inode: %p devfs_entry: %p
\n
"
,
(
int
)
inode
->
i_ino
,
inode
,
de
);
inode
->
i_blocks
=
0
;
inode
->
i_blksize
=
FAKE_BLOCK_SIZE
;
inode
->
i_op
=
&
devfs_iops
;
...
...
@@ -1956,15 +1950,14 @@ static struct inode *_devfs_get_vfs_inode (struct super_block *sb,
inode
->
i_atime
=
de
->
inode
.
atime
;
inode
->
i_mtime
=
de
->
inode
.
mtime
;
inode
->
i_ctime
=
de
->
inode
.
ctime
;
DPRINTK
(
DEBUG_I_GET
,
"(): mode: 0%o uid: %d gid: %d
\n
"
,
(
int
)
inode
->
i_mode
,
(
int
)
inode
->
i_uid
,
(
int
)
inode
->
i_gid
);
DPRINTK
(
DEBUG_I_GET
,
"(): mode: 0%o uid: %d gid: %d
\n
"
,
(
int
)
inode
->
i_mode
,
(
int
)
inode
->
i_uid
,
(
int
)
inode
->
i_gid
);
return
inode
;
}
/* End Function _devfs_get_vfs_inode */
/* File operations for device entries follow */
static
int
devfs_readdir
(
struct
file
*
file
,
void
*
dirent
,
filldir_t
filldir
)
static
int
devfs_readdir
(
struct
file
*
file
,
void
*
dirent
,
filldir_t
filldir
)
{
int
err
,
count
;
int
stored
=
0
;
...
...
@@ -1973,52 +1966,60 @@ static int devfs_readdir (struct file *file, void *dirent, filldir_t filldir)
struct
inode
*
inode
=
file
->
f_dentry
->
d_inode
;
fs_info
=
inode
->
i_sb
->
s_fs_info
;
parent
=
get_devfs_entry_from_vfs_inode
(
file
->
f_dentry
->
d_inode
);
if
(
(
long
)
file
->
f_pos
<
0
)
return
-
EINVAL
;
DPRINTK
(
DEBUG_F_READDIR
,
"(%s): fs_info: %p pos: %ld
\n
"
,
parent
->
name
,
fs_info
,
(
long
)
file
->
f_pos
);
switch
(
(
long
)
file
->
f_pos
)
{
parent
=
get_devfs_entry_from_vfs_inode
(
file
->
f_dentry
->
d_inode
);
if
((
long
)
file
->
f_pos
<
0
)
return
-
EINVAL
;
DPRINTK
(
DEBUG_F_READDIR
,
"(%s): fs_info: %p pos: %ld
\n
"
,
parent
->
name
,
fs_info
,
(
long
)
file
->
f_pos
);
switch
((
long
)
file
->
f_pos
)
{
case
0
:
err
=
(
*
filldir
)
(
dirent
,
".."
,
2
,
file
->
f_pos
,
parent_ino
(
file
->
f_dentry
),
DT_DIR
);
if
(
err
==
-
EINVAL
)
break
;
if
(
err
<
0
)
return
err
;
parent_ino
(
file
->
f_dentry
),
DT_DIR
);
if
(
err
==
-
EINVAL
)
break
;
if
(
err
<
0
)
return
err
;
file
->
f_pos
++
;
++
stored
;
/* Fall through */
case
1
:
err
=
(
*
filldir
)
(
dirent
,
"."
,
1
,
file
->
f_pos
,
inode
->
i_ino
,
DT_DIR
);
if
(
err
==
-
EINVAL
)
break
;
if
(
err
<
0
)
return
err
;
err
=
(
*
filldir
)
(
dirent
,
"."
,
1
,
file
->
f_pos
,
inode
->
i_ino
,
DT_DIR
);
if
(
err
==
-
EINVAL
)
break
;
if
(
err
<
0
)
return
err
;
file
->
f_pos
++
;
++
stored
;
/* Fall through */
default:
/* Skip entries */
count
=
file
->
f_pos
-
2
;
read_lock
(
&
parent
->
u
.
dir
.
lock
);
read_lock
(
&
parent
->
u
.
dir
.
lock
);
for
(
de
=
parent
->
u
.
dir
.
first
;
de
&&
(
count
>
0
);
de
=
de
->
next
)
--
count
;
devfs_get
(
de
);
read_unlock
(
&
parent
->
u
.
dir
.
lock
);
devfs_get
(
de
);
read_unlock
(
&
parent
->
u
.
dir
.
lock
);
/* Now add all remaining entries */
while
(
de
)
{
while
(
de
)
{
err
=
(
*
filldir
)
(
dirent
,
de
->
name
,
de
->
namelen
,
file
->
f_pos
,
de
->
inode
.
ino
,
de
->
mode
>>
12
);
if
(
err
<
0
)
devfs_put
(
de
);
else
{
file
->
f_pos
,
de
->
inode
.
ino
,
de
->
mode
>>
12
);
if
(
err
<
0
)
devfs_put
(
de
);
else
{
file
->
f_pos
++
;
++
stored
;
}
if
(
err
==
-
EINVAL
)
break
;
if
(
err
<
0
)
return
err
;
read_lock
(
&
parent
->
u
.
dir
.
lock
);
next
=
devfs_get
(
de
->
next
);
read_unlock
(
&
parent
->
u
.
dir
.
lock
);
devfs_put
(
de
);
if
(
err
==
-
EINVAL
)
break
;
if
(
err
<
0
)
return
err
;
read_lock
(
&
parent
->
u
.
dir
.
lock
);
next
=
devfs_get
(
de
->
next
);
read_unlock
(
&
parent
->
u
.
dir
.
lock
);
devfs_put
(
de
);
de
=
next
;
}
break
;
...
...
@@ -2027,7 +2028,7 @@ static int devfs_readdir (struct file *file, void *dirent, filldir_t filldir)
}
/* End Function devfs_readdir */
/* Open devfs specific special files */
static
int
devfs_open
(
struct
inode
*
inode
,
struct
file
*
file
)
static
int
devfs_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
int
err
;
int
minor
=
MINOR
(
inode
->
i_rdev
);
...
...
@@ -2059,29 +2060,25 @@ static int devfs_open (struct inode *inode, struct file *file)
return
err
;
}
/* End Function devfs_open */
static
struct
file_operations
devfs_fops
=
{
static
struct
file_operations
devfs_fops
=
{
.
open
=
devfs_open
,
};
static
struct
file_operations
devfs_dir_fops
=
{
static
struct
file_operations
devfs_dir_fops
=
{
.
read
=
generic_read_dir
,
.
readdir
=
devfs_readdir
,
};
/* Dentry operations for device entries follow */
/**
* devfs_d_release - Callback for when a dentry is freed.
* @dentry: The dentry.
*/
static
void
devfs_d_release
(
struct
dentry
*
dentry
)
static
void
devfs_d_release
(
struct
dentry
*
dentry
)
{
DPRINTK
(
DEBUG_D_RELEASE
,
"(%p): inode: %p
\n
"
,
dentry
,
dentry
->
d_inode
);
DPRINTK
(
DEBUG_D_RELEASE
,
"(%p): inode: %p
\n
"
,
dentry
,
dentry
->
d_inode
);
}
/* End Function devfs_d_release */
/**
...
...
@@ -2090,34 +2087,33 @@ static void devfs_d_release (struct dentry *dentry)
* @inode: The inode.
*/
static
void
devfs_d_iput
(
struct
dentry
*
dentry
,
struct
inode
*
inode
)
static
void
devfs_d_iput
(
struct
dentry
*
dentry
,
struct
inode
*
inode
)
{
struct
devfs_entry
*
de
;
de
=
get_devfs_entry_from_vfs_inode
(
inode
);
DPRINTK
(
DEBUG_D_IPUT
,
"(%s): dentry: %p inode: %p de: %p de->dentry: %p
\n
"
,
de
->
name
,
dentry
,
inode
,
de
,
de
->
inode
.
dentry
);
if
(
de
->
inode
.
dentry
&&
(
de
->
inode
.
dentry
!=
dentry
)
)
OOPS
(
"(%s): de: %p dentry: %p de->dentry: %p
\n
"
,
de
=
get_devfs_entry_from_vfs_inode
(
inode
);
DPRINTK
(
DEBUG_D_IPUT
,
"(%s): dentry: %p inode: %p de: %p de->dentry: %p
\n
"
,
de
->
name
,
dentry
,
inode
,
de
,
de
->
inode
.
dentry
);
if
(
de
->
inode
.
dentry
&&
(
de
->
inode
.
dentry
!=
dentry
))
OOPS
(
"(%s): de: %p dentry: %p de->dentry: %p
\n
"
,
de
->
name
,
de
,
dentry
,
de
->
inode
.
dentry
);
de
->
inode
.
dentry
=
NULL
;
iput
(
inode
);
devfs_put
(
de
);
iput
(
inode
);
devfs_put
(
de
);
}
/* End Function devfs_d_iput */
static
int
devfs_d_delete
(
struct
dentry
*
dentry
);
static
int
devfs_d_delete
(
struct
dentry
*
dentry
);
static
struct
dentry_operations
devfs_dops
=
{
static
struct
dentry_operations
devfs_dops
=
{
.
d_delete
=
devfs_d_delete
,
.
d_release
=
devfs_d_release
,
.
d_iput
=
devfs_d_iput
,
};
static
int
devfs_d_revalidate_wait
(
struct
dentry
*
dentry
,
struct
nameidata
*
);
static
int
devfs_d_revalidate_wait
(
struct
dentry
*
dentry
,
struct
nameidata
*
);
static
struct
dentry_operations
devfs_wait_dops
=
{
static
struct
dentry_operations
devfs_wait_dops
=
{
.
d_delete
=
devfs_d_delete
,
.
d_release
=
devfs_d_release
,
.
d_iput
=
devfs_d_iput
,
...
...
@@ -2129,35 +2125,35 @@ static struct dentry_operations devfs_wait_dops =
* @dentry: The dentry.
*/
static
int
devfs_d_delete
(
struct
dentry
*
dentry
)
static
int
devfs_d_delete
(
struct
dentry
*
dentry
)
{
struct
inode
*
inode
=
dentry
->
d_inode
;
if
(
dentry
->
d_op
==
&
devfs_wait_dops
)
dentry
->
d_op
=
&
devfs_dops
;
if
(
dentry
->
d_op
==
&
devfs_wait_dops
)
dentry
->
d_op
=
&
devfs_dops
;
/* Unhash dentry if negative (has no inode) */
if
(
inode
==
NULL
)
{
DPRINTK
(
DEBUG_D_DELETE
,
"(%p): dropping negative dentry
\n
"
,
dentry
);
if
(
inode
==
NULL
)
{
DPRINTK
(
DEBUG_D_DELETE
,
"(%p): dropping negative dentry
\n
"
,
dentry
);
return
1
;
}
return
0
;
}
/* End Function devfs_d_delete */
struct
devfs_lookup_struct
{
struct
devfs_lookup_struct
{
devfs_handle_t
de
;
wait_queue_head_t
wait_queue
;
};
/* XXX: this doesn't handle the case where we got a negative dentry
but a devfs entry has been registered in the meanwhile */
static
int
devfs_d_revalidate_wait
(
struct
dentry
*
dentry
,
struct
nameidata
*
nd
)
static
int
devfs_d_revalidate_wait
(
struct
dentry
*
dentry
,
struct
nameidata
*
nd
)
{
struct
inode
*
dir
=
dentry
->
d_parent
->
d_inode
;
struct
fs_info
*
fs_info
=
dir
->
i_sb
->
s_fs_info
;
devfs_handle_t
parent
=
get_devfs_entry_from_vfs_inode
(
dir
);
devfs_handle_t
parent
=
get_devfs_entry_from_vfs_inode
(
dir
);
struct
devfs_lookup_struct
*
lookup_info
=
dentry
->
d_fsdata
;
DECLARE_WAITQUEUE
(
wait
,
current
);
DECLARE_WAITQUEUE
(
wait
,
current
);
int
need_lock
;
/*
...
...
@@ -2187,48 +2183,45 @@ static int devfs_d_revalidate_wait (struct dentry *dentry, struct nameidata *nd)
if
(
need_lock
)
down
(
&
dir
->
i_sem
);
if
(
is_devfsd_or_child
(
fs_info
)
)
{
if
(
is_devfsd_or_child
(
fs_info
))
{
devfs_handle_t
de
=
lookup_info
->
de
;
struct
inode
*
inode
;
DPRINTK
(
DEBUG_I_LOOKUP
,
DPRINTK
(
DEBUG_I_LOOKUP
,
"(%s): dentry: %p inode: %p de: %p by:
\"
%s
\"\n
"
,
dentry
->
d_name
.
name
,
dentry
,
dentry
->
d_inode
,
de
,
current
->
comm
);
if
(
dentry
->
d_inode
)
goto
out
;
if
(
de
==
NULL
)
{
read_lock
(
&
parent
->
u
.
dir
.
lock
);
de
=
_devfs_search_dir
(
parent
,
dentry
->
d_name
.
name
,
if
(
de
==
NULL
)
{
read_lock
(
&
parent
->
u
.
dir
.
lock
);
de
=
_devfs_search_dir
(
parent
,
dentry
->
d_name
.
name
,
dentry
->
d_name
.
len
);
read_unlock
(
&
parent
->
u
.
dir
.
lock
);
read_unlock
(
&
parent
->
u
.
dir
.
lock
);
if
(
de
==
NULL
)
goto
out
;
lookup_info
->
de
=
de
;
}
/* Create an inode, now that the driver information is available */
inode
=
_devfs_get_vfs_inode
(
dir
->
i_sb
,
de
,
dentry
);
inode
=
_devfs_get_vfs_inode
(
dir
->
i_sb
,
de
,
dentry
);
if
(
!
inode
)
goto
out
;
DPRINTK
(
DEBUG_I_LOOKUP
,
DPRINTK
(
DEBUG_I_LOOKUP
,
"(%s): new VFS inode(%u): %p de: %p by:
\"
%s
\"\n
"
,
de
->
name
,
de
->
inode
.
ino
,
inode
,
de
,
current
->
comm
);
d_instantiate
(
dentry
,
inode
);
d_instantiate
(
dentry
,
inode
);
goto
out
;
}
if
(
lookup_info
==
NULL
)
goto
out
;
/* Early termination */
read_lock
(
&
parent
->
u
.
dir
.
lock
);
if
(
dentry
->
d_fsdata
)
{
set_current_state
(
TASK_UNINTERRUPTIBLE
);
add_wait_queue
(
&
lookup_info
->
wait_queue
,
&
wait
);
read_unlock
(
&
parent
->
u
.
dir
.
lock
);
read_lock
(
&
parent
->
u
.
dir
.
lock
);
if
(
dentry
->
d_fsdata
)
{
set_current_state
(
TASK_UNINTERRUPTIBLE
);
add_wait_queue
(
&
lookup_info
->
wait_queue
,
&
wait
);
read_unlock
(
&
parent
->
u
.
dir
.
lock
);
/* at this point it is always (hopefully) locked */
up
(
&
dir
->
i_sem
);
schedule
();
schedule
();
down
(
&
dir
->
i_sem
);
/*
* This does not need nor should remove wait from wait_queue.
...
...
@@ -2239,19 +2232,19 @@ static int devfs_d_revalidate_wait (struct dentry *dentry, struct nameidata *nd)
* at this point is buggy.
*/
}
else
read_unlock
(
&
parent
->
u
.
dir
.
lock
);
}
else
read_unlock
(
&
parent
->
u
.
dir
.
lock
);
out:
out:
if
(
need_lock
)
up
(
&
dir
->
i_sem
);
return
1
;
}
/* End Function devfs_d_revalidate_wait */
/* Inode operations for device entries follow */
static
struct
dentry
*
devfs_lookup
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
struct
nameidata
*
nd
)
static
struct
dentry
*
devfs_lookup
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
struct
nameidata
*
nd
)
{
struct
devfs_entry
tmp
;
/* Must stay in scope until devfsd idle again */
struct
devfs_lookup_struct
lookup_info
;
...
...
@@ -2264,94 +2257,96 @@ static struct dentry *devfs_lookup (struct inode *dir, struct dentry *dentry, st
up on any error */
dentry
->
d_op
=
&
devfs_dops
;
/* First try to get the devfs entry for this directory */
parent
=
get_devfs_entry_from_vfs_inode
(
dir
);
DPRINTK
(
DEBUG_I_LOOKUP
,
"(%s): dentry: %p parent: %p by:
\"
%s
\"\n
"
,
parent
=
get_devfs_entry_from_vfs_inode
(
dir
);
DPRINTK
(
DEBUG_I_LOOKUP
,
"(%s): dentry: %p parent: %p by:
\"
%s
\"\n
"
,
dentry
->
d_name
.
name
,
dentry
,
parent
,
current
->
comm
);
if
(
parent
==
NULL
)
return
ERR_PTR
(
-
ENOENT
);
read_lock
(
&
parent
->
u
.
dir
.
lock
);
de
=
_devfs_search_dir
(
parent
,
dentry
->
d_name
.
name
,
dentry
->
d_name
.
len
);
read_unlock
(
&
parent
->
u
.
dir
.
lock
);
if
(
parent
==
NULL
)
return
ERR_PTR
(
-
ENOENT
);
read_lock
(
&
parent
->
u
.
dir
.
lock
);
de
=
_devfs_search_dir
(
parent
,
dentry
->
d_name
.
name
,
dentry
->
d_name
.
len
);
read_unlock
(
&
parent
->
u
.
dir
.
lock
);
lookup_info
.
de
=
de
;
init_waitqueue_head
(
&
lookup_info
.
wait_queue
);
init_waitqueue_head
(
&
lookup_info
.
wait_queue
);
dentry
->
d_fsdata
=
&
lookup_info
;
if
(
de
==
NULL
)
{
/* Try with devfsd. For any kind of failure, leave a negative dentry
if
(
de
==
NULL
)
{
/* Try with devfsd. For any kind of failure, leave a negative dentry
so someone else can deal with it (in the case where the sysadmin
does a mknod()). It's important to do this before hashing the
dentry, so that the devfsd queue is filled before revalidates
can start */
if
(
try_modload
(
parent
,
fs_info
,
dentry
->
d_name
.
name
,
dentry
->
d_name
.
len
,
&
tmp
)
<
0
)
{
/* Lookup event was not queued to devfsd */
d_add
(
dentry
,
NULL
);
if
(
try_modload
(
parent
,
fs_info
,
dentry
->
d_name
.
name
,
dentry
->
d_name
.
len
,
&
tmp
)
<
0
)
{
/* Lookup event was not queued to devfsd */
d_add
(
dentry
,
NULL
);
return
NULL
;
}
}
dentry
->
d_op
=
&
devfs_wait_dops
;
d_add
(
dentry
,
NULL
);
/* Open the floodgates */
d_add
(
dentry
,
NULL
);
/* Open the floodgates */
/* Unlock directory semaphore, which will release any waiters. They
will get the hashed dentry, and may be forced to wait for
revalidation */
up
(
&
dir
->
i_sem
);
wait_for_devfsd_finished
(
fs_info
);
/* If I'm not devfsd, must wait */
down
(
&
dir
->
i_sem
);
/* Grab it again because them's the rules */
up
(
&
dir
->
i_sem
);
wait_for_devfsd_finished
(
fs_info
);
/* If I'm not devfsd, must wait */
down
(
&
dir
->
i_sem
);
/* Grab it again because them's the rules */
de
=
lookup_info
.
de
;
/* If someone else has been so kind as to make the inode, we go home
early */
if
(
dentry
->
d_inode
)
goto
out
;
if
(
de
==
NULL
)
{
read_lock
(
&
parent
->
u
.
dir
.
lock
);
de
=
_devfs_search_dir
(
parent
,
dentry
->
d_name
.
name
,
if
(
dentry
->
d_inode
)
goto
out
;
if
(
de
==
NULL
)
{
read_lock
(
&
parent
->
u
.
dir
.
lock
);
de
=
_devfs_search_dir
(
parent
,
dentry
->
d_name
.
name
,
dentry
->
d_name
.
len
);
read_unlock
(
&
parent
->
u
.
dir
.
lock
);
if
(
de
==
NULL
)
goto
out
;
read_unlock
(
&
parent
->
u
.
dir
.
lock
);
if
(
de
==
NULL
)
goto
out
;
/* OK, there's an entry now, but no VFS inode yet */
}
/* Create an inode, now that the driver information is available */
inode
=
_devfs_get_vfs_inode
(
dir
->
i_sb
,
de
,
dentry
);
if
(
!
inode
)
{
retval
=
ERR_PTR
(
-
ENOMEM
);
inode
=
_devfs_get_vfs_inode
(
dir
->
i_sb
,
de
,
dentry
);
if
(
!
inode
)
{
retval
=
ERR_PTR
(
-
ENOMEM
);
goto
out
;
}
DPRINTK
(
DEBUG_I_LOOKUP
,
"(%s): new VFS inode(%u): %p de: %p by:
\"
%s
\"\n
"
,
de
->
name
,
de
->
inode
.
ino
,
inode
,
de
,
current
->
comm
);
d_instantiate
(
dentry
,
inode
);
out:
write_lock
(
&
parent
->
u
.
dir
.
lock
);
DPRINTK
(
DEBUG_I_LOOKUP
,
"(%s): new VFS inode(%u): %p de: %p by:
\"
%s
\"\n
"
,
de
->
name
,
de
->
inode
.
ino
,
inode
,
de
,
current
->
comm
);
d_instantiate
(
dentry
,
inode
);
out:
write_lock
(
&
parent
->
u
.
dir
.
lock
);
dentry
->
d_op
=
&
devfs_dops
;
dentry
->
d_fsdata
=
NULL
;
wake_up
(
&
lookup_info
.
wait_queue
);
write_unlock
(
&
parent
->
u
.
dir
.
lock
);
devfs_put
(
de
);
wake_up
(
&
lookup_info
.
wait_queue
);
write_unlock
(
&
parent
->
u
.
dir
.
lock
);
devfs_put
(
de
);
return
retval
;
}
/* End Function devfs_lookup */
static
int
devfs_unlink
(
struct
inode
*
dir
,
struct
dentry
*
dentry
)
static
int
devfs_unlink
(
struct
inode
*
dir
,
struct
dentry
*
dentry
)
{
int
unhooked
;
struct
devfs_entry
*
de
;
struct
inode
*
inode
=
dentry
->
d_inode
;
struct
fs_info
*
fs_info
=
dir
->
i_sb
->
s_fs_info
;
de
=
get_devfs_entry_from_vfs_inode
(
inode
);
DPRINTK
(
DEBUG_I_UNLINK
,
"(%s): de: %p
\n
"
,
dentry
->
d_name
.
name
,
de
);
if
(
de
==
NULL
)
return
-
ENOENT
;
if
(
!
de
->
vfs
)
return
-
EPERM
;
write_lock
(
&
de
->
parent
->
u
.
dir
.
lock
);
unhooked
=
_devfs_unhook
(
de
);
write_unlock
(
&
de
->
parent
->
u
.
dir
.
lock
);
if
(
!
unhooked
)
return
-
ENOENT
;
if
(
!
is_devfsd_or_child
(
fs_info
)
)
devfsd_notify_de
(
de
,
DEVFSD_NOTIFY_DELETE
,
inode
->
i_mode
,
de
=
get_devfs_entry_from_vfs_inode
(
inode
);
DPRINTK
(
DEBUG_I_UNLINK
,
"(%s): de: %p
\n
"
,
dentry
->
d_name
.
name
,
de
);
if
(
de
==
NULL
)
return
-
ENOENT
;
if
(
!
de
->
vfs
)
return
-
EPERM
;
write_lock
(
&
de
->
parent
->
u
.
dir
.
lock
);
unhooked
=
_devfs_unhook
(
de
);
write_unlock
(
&
de
->
parent
->
u
.
dir
.
lock
);
if
(
!
unhooked
)
return
-
ENOENT
;
if
(
!
is_devfsd_or_child
(
fs_info
))
devfsd_notify_de
(
de
,
DEVFSD_NOTIFY_DELETE
,
inode
->
i_mode
,
inode
->
i_uid
,
inode
->
i_gid
,
fs_info
);
free_dentry
(
de
);
devfs_put
(
de
);
free_dentry
(
de
);
devfs_put
(
de
);
return
0
;
}
/* End Function devfs_unlink */
static
int
devfs_symlink
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
static
int
devfs_symlink
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
const
char
*
symname
)
{
int
err
;
...
...
@@ -2360,30 +2355,32 @@ static int devfs_symlink (struct inode *dir, struct dentry *dentry,
struct
inode
*
inode
;
/* First try to get the devfs entry for this directory */
parent
=
get_devfs_entry_from_vfs_inode
(
dir
);
if
(
parent
==
NULL
)
return
-
ENOENT
;
err
=
devfs_do_symlink
(
parent
,
dentry
->
d_name
.
name
,
symname
,
&
de
);
DPRINTK
(
DEBUG_DISABLED
,
"(%s): errcode from <devfs_do_symlink>: %d
\n
"
,
parent
=
get_devfs_entry_from_vfs_inode
(
dir
);
if
(
parent
==
NULL
)
return
-
ENOENT
;
err
=
devfs_do_symlink
(
parent
,
dentry
->
d_name
.
name
,
symname
,
&
de
);
DPRINTK
(
DEBUG_DISABLED
,
"(%s): errcode from <devfs_do_symlink>: %d
\n
"
,
dentry
->
d_name
.
name
,
err
);
if
(
err
<
0
)
return
err
;
if
(
err
<
0
)
return
err
;
de
->
vfs
=
TRUE
;
de
->
inode
.
uid
=
current
->
euid
;
de
->
inode
.
gid
=
current
->
egid
;
de
->
inode
.
atime
=
CURRENT_TIME
;
de
->
inode
.
mtime
=
CURRENT_TIME
;
de
->
inode
.
ctime
=
CURRENT_TIME
;
if
(
(
inode
=
_devfs_get_vfs_inode
(
dir
->
i_sb
,
de
,
dentry
)
)
==
NULL
)
if
((
inode
=
_devfs_get_vfs_inode
(
dir
->
i_sb
,
de
,
dentry
))
==
NULL
)
return
-
ENOMEM
;
DPRINTK
(
DEBUG_DISABLED
,
"(%s): new VFS inode(%u): %p dentry: %p
\n
"
,
DPRINTK
(
DEBUG_DISABLED
,
"(%s): new VFS inode(%u): %p dentry: %p
\n
"
,
dentry
->
d_name
.
name
,
de
->
inode
.
ino
,
inode
,
dentry
);
d_instantiate
(
dentry
,
inode
);
if
(
!
is_devfsd_or_child
(
fs_info
)
)
devfsd_notify_de
(
de
,
DEVFSD_NOTIFY_CREATE
,
inode
->
i_mode
,
d_instantiate
(
dentry
,
inode
);
if
(
!
is_devfsd_or_child
(
fs_info
)
)
devfsd_notify_de
(
de
,
DEVFSD_NOTIFY_CREATE
,
inode
->
i_mode
,
inode
->
i_uid
,
inode
->
i_gid
,
fs_info
);
return
0
;
}
/* End Function devfs_symlink */
static
int
devfs_mkdir
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
int
mode
)
static
int
devfs_mkdir
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
int
mode
)
{
int
err
;
struct
fs_info
*
fs_info
=
dir
->
i_sb
->
s_fs_info
;
...
...
@@ -2391,61 +2388,72 @@ static int devfs_mkdir (struct inode *dir, struct dentry *dentry, int mode)
struct
inode
*
inode
;
mode
=
(
mode
&
~
S_IFMT
)
|
S_IFDIR
;
/* VFS doesn't pass S_IFMT part */
parent
=
get_devfs_entry_from_vfs_inode
(
dir
);
if
(
parent
==
NULL
)
return
-
ENOENT
;
de
=
_devfs_alloc_entry
(
dentry
->
d_name
.
name
,
dentry
->
d_name
.
len
,
mode
);
if
(
!
de
)
return
-
ENOMEM
;
parent
=
get_devfs_entry_from_vfs_inode
(
dir
);
if
(
parent
==
NULL
)
return
-
ENOENT
;
de
=
_devfs_alloc_entry
(
dentry
->
d_name
.
name
,
dentry
->
d_name
.
len
,
mode
);
if
(
!
de
)
return
-
ENOMEM
;
de
->
vfs
=
TRUE
;
if
(
(
err
=
_devfs_append_entry
(
parent
,
de
,
NULL
)
)
!=
0
)
if
((
err
=
_devfs_append_entry
(
parent
,
de
,
NULL
))
!=
0
)
return
err
;
de
->
inode
.
uid
=
current
->
euid
;
de
->
inode
.
gid
=
current
->
egid
;
de
->
inode
.
atime
=
CURRENT_TIME
;
de
->
inode
.
mtime
=
CURRENT_TIME
;
de
->
inode
.
ctime
=
CURRENT_TIME
;
if
(
(
inode
=
_devfs_get_vfs_inode
(
dir
->
i_sb
,
de
,
dentry
)
)
==
NULL
)
if
((
inode
=
_devfs_get_vfs_inode
(
dir
->
i_sb
,
de
,
dentry
))
==
NULL
)
return
-
ENOMEM
;
DPRINTK
(
DEBUG_DISABLED
,
"(%s): new VFS inode(%u): %p dentry: %p
\n
"
,
DPRINTK
(
DEBUG_DISABLED
,
"(%s): new VFS inode(%u): %p dentry: %p
\n
"
,
dentry
->
d_name
.
name
,
de
->
inode
.
ino
,
inode
,
dentry
);
d_instantiate
(
dentry
,
inode
);
if
(
!
is_devfsd_or_child
(
fs_info
)
)
devfsd_notify_de
(
de
,
DEVFSD_NOTIFY_CREATE
,
inode
->
i_mode
,
d_instantiate
(
dentry
,
inode
);
if
(
!
is_devfsd_or_child
(
fs_info
)
)
devfsd_notify_de
(
de
,
DEVFSD_NOTIFY_CREATE
,
inode
->
i_mode
,
inode
->
i_uid
,
inode
->
i_gid
,
fs_info
);
return
0
;
}
/* End Function devfs_mkdir */
static
int
devfs_rmdir
(
struct
inode
*
dir
,
struct
dentry
*
dentry
)
static
int
devfs_rmdir
(
struct
inode
*
dir
,
struct
dentry
*
dentry
)
{
int
err
=
0
;
struct
devfs_entry
*
de
;
struct
fs_info
*
fs_info
=
dir
->
i_sb
->
s_fs_info
;
struct
inode
*
inode
=
dentry
->
d_inode
;
if
(
dir
->
i_sb
->
s_fs_info
!=
inode
->
i_sb
->
s_fs_info
)
return
-
EINVAL
;
de
=
get_devfs_entry_from_vfs_inode
(
inode
);
if
(
de
==
NULL
)
return
-
ENOENT
;
if
(
!
S_ISDIR
(
de
->
mode
)
)
return
-
ENOTDIR
;
if
(
!
de
->
vfs
)
return
-
EPERM
;
if
(
dir
->
i_sb
->
s_fs_info
!=
inode
->
i_sb
->
s_fs_info
)
return
-
EINVAL
;
de
=
get_devfs_entry_from_vfs_inode
(
inode
);
if
(
de
==
NULL
)
return
-
ENOENT
;
if
(
!
S_ISDIR
(
de
->
mode
))
return
-
ENOTDIR
;
if
(
!
de
->
vfs
)
return
-
EPERM
;
/* First ensure the directory is empty and will stay that way */
write_lock
(
&
de
->
u
.
dir
.
lock
);
if
(
de
->
u
.
dir
.
first
)
err
=
-
ENOTEMPTY
;
else
de
->
u
.
dir
.
no_more_additions
=
TRUE
;
write_unlock
(
&
de
->
u
.
dir
.
lock
);
if
(
err
)
return
err
;
write_lock
(
&
de
->
u
.
dir
.
lock
);
if
(
de
->
u
.
dir
.
first
)
err
=
-
ENOTEMPTY
;
else
de
->
u
.
dir
.
no_more_additions
=
TRUE
;
write_unlock
(
&
de
->
u
.
dir
.
lock
);
if
(
err
)
return
err
;
/* Now unhook the directory from its parent */
write_lock
(
&
de
->
parent
->
u
.
dir
.
lock
);
if
(
!
_devfs_unhook
(
de
)
)
err
=
-
ENOENT
;
write_unlock
(
&
de
->
parent
->
u
.
dir
.
lock
);
if
(
err
)
return
err
;
if
(
!
is_devfsd_or_child
(
fs_info
)
)
devfsd_notify_de
(
de
,
DEVFSD_NOTIFY_DELETE
,
inode
->
i_mode
,
write_lock
(
&
de
->
parent
->
u
.
dir
.
lock
);
if
(
!
_devfs_unhook
(
de
))
err
=
-
ENOENT
;
write_unlock
(
&
de
->
parent
->
u
.
dir
.
lock
);
if
(
err
)
return
err
;
if
(
!
is_devfsd_or_child
(
fs_info
))
devfsd_notify_de
(
de
,
DEVFSD_NOTIFY_DELETE
,
inode
->
i_mode
,
inode
->
i_uid
,
inode
->
i_gid
,
fs_info
);
free_dentry
(
de
);
devfs_put
(
de
);
free_dentry
(
de
);
devfs_put
(
de
);
return
0
;
}
/* End Function devfs_rmdir */
static
int
devfs_mknod
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
int
mode
,
static
int
devfs_mknod
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
int
mode
,
dev_t
rdev
)
{
int
err
;
...
...
@@ -2453,62 +2461,64 @@ static int devfs_mknod (struct inode *dir, struct dentry *dentry, int mode,
struct
devfs_entry
*
parent
,
*
de
;
struct
inode
*
inode
;
DPRINTK
(
DEBUG_I_MKNOD
,
"(%s): mode: 0%o dev: %u:%u
\n
"
,
DPRINTK
(
DEBUG_I_MKNOD
,
"(%s): mode: 0%o dev: %u:%u
\n
"
,
dentry
->
d_name
.
name
,
mode
,
MAJOR
(
rdev
),
MINOR
(
rdev
));
parent
=
get_devfs_entry_from_vfs_inode
(
dir
);
if
(
parent
==
NULL
)
return
-
ENOENT
;
de
=
_devfs_alloc_entry
(
dentry
->
d_name
.
name
,
dentry
->
d_name
.
len
,
mode
);
if
(
!
de
)
return
-
ENOMEM
;
parent
=
get_devfs_entry_from_vfs_inode
(
dir
);
if
(
parent
==
NULL
)
return
-
ENOENT
;
de
=
_devfs_alloc_entry
(
dentry
->
d_name
.
name
,
dentry
->
d_name
.
len
,
mode
);
if
(
!
de
)
return
-
ENOMEM
;
de
->
vfs
=
TRUE
;
if
(
S_ISCHR
(
mode
)
||
S_ISBLK
(
mode
))
de
->
u
.
dev
=
rdev
;
if
(
(
err
=
_devfs_append_entry
(
parent
,
de
,
NULL
)
)
!=
0
)
if
((
err
=
_devfs_append_entry
(
parent
,
de
,
NULL
))
!=
0
)
return
err
;
de
->
inode
.
uid
=
current
->
euid
;
de
->
inode
.
gid
=
current
->
egid
;
de
->
inode
.
atime
=
CURRENT_TIME
;
de
->
inode
.
mtime
=
CURRENT_TIME
;
de
->
inode
.
ctime
=
CURRENT_TIME
;
if
(
(
inode
=
_devfs_get_vfs_inode
(
dir
->
i_sb
,
de
,
dentry
)
)
==
NULL
)
if
((
inode
=
_devfs_get_vfs_inode
(
dir
->
i_sb
,
de
,
dentry
))
==
NULL
)
return
-
ENOMEM
;
DPRINTK
(
DEBUG_I_MKNOD
,
": new VFS inode(%u): %p dentry: %p
\n
"
,
DPRINTK
(
DEBUG_I_MKNOD
,
": new VFS inode(%u): %p dentry: %p
\n
"
,
de
->
inode
.
ino
,
inode
,
dentry
);
d_instantiate
(
dentry
,
inode
);
if
(
!
is_devfsd_or_child
(
fs_info
)
)
devfsd_notify_de
(
de
,
DEVFSD_NOTIFY_CREATE
,
inode
->
i_mode
,
d_instantiate
(
dentry
,
inode
);
if
(
!
is_devfsd_or_child
(
fs_info
)
)
devfsd_notify_de
(
de
,
DEVFSD_NOTIFY_CREATE
,
inode
->
i_mode
,
inode
->
i_uid
,
inode
->
i_gid
,
fs_info
);
return
0
;
}
/* End Function devfs_mknod */
static
int
devfs_readlink
(
struct
dentry
*
dentry
,
char
*
buffer
,
int
buflen
)
static
int
devfs_readlink
(
struct
dentry
*
dentry
,
char
*
buffer
,
int
buflen
)
{
int
err
;
struct
devfs_entry
*
de
;
de
=
get_devfs_entry_from_vfs_inode
(
dentry
->
d_inode
);
if
(
!
de
)
return
-
ENODEV
;
err
=
vfs_readlink
(
dentry
,
buffer
,
buflen
,
de
->
u
.
symlink
.
linkname
);
de
=
get_devfs_entry_from_vfs_inode
(
dentry
->
d_inode
);
if
(
!
de
)
return
-
ENODEV
;
err
=
vfs_readlink
(
dentry
,
buffer
,
buflen
,
de
->
u
.
symlink
.
linkname
);
return
err
;
}
/* End Function devfs_readlink */
static
int
devfs_follow_link
(
struct
dentry
*
dentry
,
struct
nameidata
*
nd
)
static
int
devfs_follow_link
(
struct
dentry
*
dentry
,
struct
nameidata
*
nd
)
{
int
err
;
struct
devfs_entry
*
de
;
de
=
get_devfs_entry_from_vfs_inode
(
dentry
->
d_inode
);
if
(
!
de
)
return
-
ENODEV
;
err
=
vfs_follow_link
(
nd
,
de
->
u
.
symlink
.
linkname
);
de
=
get_devfs_entry_from_vfs_inode
(
dentry
->
d_inode
);
if
(
!
de
)
return
-
ENODEV
;
err
=
vfs_follow_link
(
nd
,
de
->
u
.
symlink
.
linkname
);
return
err
;
}
/* End Function devfs_follow_link */
static
struct
inode_operations
devfs_iops
=
{
static
struct
inode_operations
devfs_iops
=
{
.
setattr
=
devfs_notify_change
,
};
static
struct
inode_operations
devfs_dir_iops
=
{
static
struct
inode_operations
devfs_dir_iops
=
{
.
lookup
=
devfs_lookup
,
.
unlink
=
devfs_unlink
,
.
symlink
=
devfs_symlink
,
...
...
@@ -2518,49 +2528,50 @@ static struct inode_operations devfs_dir_iops =
.
setattr
=
devfs_notify_change
,
};
static
struct
inode_operations
devfs_symlink_iops
=
{
static
struct
inode_operations
devfs_symlink_iops
=
{
.
readlink
=
devfs_readlink
,
.
follow_link
=
devfs_follow_link
,
.
setattr
=
devfs_notify_change
,
};
static
int
devfs_fill_super
(
struct
super_block
*
sb
,
void
*
data
,
int
silent
)
static
int
devfs_fill_super
(
struct
super_block
*
sb
,
void
*
data
,
int
silent
)
{
struct
inode
*
root_inode
=
NULL
;
if
(
_devfs_get_root_entry
()
==
NULL
)
goto
out_no_root
;
atomic_set
(
&
fs_info
.
devfsd_overrun_count
,
0
);
init_waitqueue_head
(
&
fs_info
.
devfsd_wait_queue
);
init_waitqueue_head
(
&
fs_info
.
revalidate_wait_queue
);
if
(
_devfs_get_root_entry
()
==
NULL
)
goto
out_no_root
;
atomic_set
(
&
fs_info
.
devfsd_overrun_count
,
0
);
init_waitqueue_head
(
&
fs_info
.
devfsd_wait_queue
);
init_waitqueue_head
(
&
fs_info
.
revalidate_wait_queue
);
fs_info
.
sb
=
sb
;
sb
->
s_fs_info
=
&
fs_info
;
sb
->
s_blocksize
=
1024
;
sb
->
s_blocksize_bits
=
10
;
sb
->
s_magic
=
DEVFS_SUPER_MAGIC
;
sb
->
s_op
=
&
devfs_sops
;
if
(
(
root_inode
=
_devfs_get_vfs_inode
(
sb
,
root_entry
,
NULL
)
)
==
NULL
)
if
((
root_inode
=
_devfs_get_vfs_inode
(
sb
,
root_entry
,
NULL
))
==
NULL
)
goto
out_no_root
;
sb
->
s_root
=
d_alloc_root
(
root_inode
);
if
(
!
sb
->
s_root
)
goto
out_no_root
;
DPRINTK
(
DEBUG_S_READ
,
"(): made devfs ptr: %p
\n
"
,
sb
->
s_fs_info
);
sb
->
s_root
=
d_alloc_root
(
root_inode
);
if
(
!
sb
->
s_root
)
goto
out_no_root
;
DPRINTK
(
DEBUG_S_READ
,
"(): made devfs ptr: %p
\n
"
,
sb
->
s_fs_info
);
return
0
;
out_no_root:
PRINTK
(
"(): get root inode failed
\n
"
);
if
(
root_inode
)
iput
(
root_inode
);
out_no_root:
PRINTK
(
"(): get root inode failed
\n
"
);
if
(
root_inode
)
iput
(
root_inode
);
return
-
EINVAL
;
}
/* End Function devfs_fill_super */
static
struct
super_block
*
devfs_get_sb
(
struct
file_system_type
*
fs_type
,
int
flags
,
const
char
*
dev_name
,
void
*
data
)
static
struct
super_block
*
devfs_get_sb
(
struct
file_system_type
*
fs_type
,
int
flags
,
const
char
*
dev_name
,
void
*
data
)
{
return
get_sb_single
(
fs_type
,
flags
,
data
,
devfs_fill_super
);
return
get_sb_single
(
fs_type
,
flags
,
data
,
devfs_fill_super
);
}
static
struct
file_system_type
devfs_fs_type
=
{
static
struct
file_system_type
devfs_fs_type
=
{
.
name
=
DEVFS_NAME
,
.
get_sb
=
devfs_get_sb
,
.
kill_sb
=
kill_anon_super
,
...
...
@@ -2568,8 +2579,8 @@ static struct file_system_type devfs_fs_type =
/* File operations for devfsd follow */
static
ssize_t
devfsd_read
(
struct
file
*
file
,
char
*
buf
,
size_t
len
,
loff_t
*
ppos
)
static
ssize_t
devfsd_read
(
struct
file
*
file
,
char
*
buf
,
size_t
len
,
loff_t
*
ppos
)
{
int
done
=
FALSE
;
int
ival
;
...
...
@@ -2578,35 +2589,35 @@ static ssize_t devfsd_read (struct file *file, char *buf, size_t len,
struct
devfsd_buf_entry
*
entry
;
struct
fs_info
*
fs_info
=
file
->
f_dentry
->
d_inode
->
i_sb
->
s_fs_info
;
struct
devfsd_notify_struct
*
info
=
fs_info
->
devfsd_info
;
DECLARE_WAITQUEUE
(
wait
,
current
);
DECLARE_WAITQUEUE
(
wait
,
current
);
/* Can't seek (pread) on this device */
if
(
ppos
!=
&
file
->
f_pos
)
return
-
ESPIPE
;
if
(
ppos
!=
&
file
->
f_pos
)
return
-
ESPIPE
;
/* Verify the task has grabbed the queue */
if
(
fs_info
->
devfsd_task
!=
current
)
return
-
EPERM
;
if
(
fs_info
->
devfsd_task
!=
current
)
return
-
EPERM
;
info
->
major
=
0
;
info
->
minor
=
0
;
/* Block for a new entry */
set_current_state
(
TASK_INTERRUPTIBLE
);
add_wait_queue
(
&
fs_info
->
devfsd_wait_queue
,
&
wait
);
while
(
devfsd_queue_empty
(
fs_info
)
)
{
set_current_state
(
TASK_INTERRUPTIBLE
);
add_wait_queue
(
&
fs_info
->
devfsd_wait_queue
,
&
wait
);
while
(
devfsd_queue_empty
(
fs_info
))
{
fs_info
->
devfsd_sleeping
=
TRUE
;
wake_up
(
&
fs_info
->
revalidate_wait_queue
);
schedule
();
wake_up
(
&
fs_info
->
revalidate_wait_queue
);
schedule
();
fs_info
->
devfsd_sleeping
=
FALSE
;
if
(
signal_pending
(
current
)
)
{
remove_wait_queue
(
&
fs_info
->
devfsd_wait_queue
,
&
wait
);
__set_current_state
(
TASK_RUNNING
);
if
(
signal_pending
(
current
))
{
remove_wait_queue
(
&
fs_info
->
devfsd_wait_queue
,
&
wait
);
__set_current_state
(
TASK_RUNNING
);
return
-
EINTR
;
}
set_current_state
(
TASK_INTERRUPTIBLE
);
set_current_state
(
TASK_INTERRUPTIBLE
);
}
remove_wait_queue
(
&
fs_info
->
devfsd_wait_queue
,
&
wait
);
__set_current_state
(
TASK_RUNNING
);
remove_wait_queue
(
&
fs_info
->
devfsd_wait_queue
,
&
wait
);
__set_current_state
(
TASK_RUNNING
);
/* Now play with the data */
ival
=
atomic_read
(
&
fs_info
->
devfsd_overrun_count
);
ival
=
atomic_read
(
&
fs_info
->
devfsd_overrun_count
);
info
->
overrun_count
=
ival
;
entry
=
fs_info
->
devfsd_first_event
;
info
->
type
=
entry
->
type
;
...
...
@@ -2618,109 +2629,111 @@ static ssize_t devfsd_read (struct file *file, char *buf, size_t len,
info
->
major
=
MAJOR
(
de
->
u
.
dev
);
info
->
minor
=
MINOR
(
de
->
u
.
dev
);
}
pos
=
devfs_generate_path
(
de
,
info
->
devname
,
DEVFS_PATHLEN
);
if
(
pos
<
0
)
return
pos
;
pos
=
devfs_generate_path
(
de
,
info
->
devname
,
DEVFS_PATHLEN
);
if
(
pos
<
0
)
return
pos
;
info
->
namelen
=
DEVFS_PATHLEN
-
pos
-
1
;
if
(
info
->
mode
==
0
)
info
->
mode
=
de
->
mode
;
devname_offset
=
info
->
devname
-
(
char
*
)
info
;
if
(
info
->
mode
==
0
)
info
->
mode
=
de
->
mode
;
devname_offset
=
info
->
devname
-
(
char
*
)
info
;
rpos
=
*
ppos
;
if
(
rpos
<
devname_offset
)
{
if
(
rpos
<
devname_offset
)
{
/* Copy parts of the header */
tlen
=
devname_offset
-
rpos
;
if
(
tlen
>
len
)
tlen
=
len
;
if
(
copy_to_user
(
buf
,
(
char
*
)
info
+
rpos
,
tlen
)
)
{
if
(
tlen
>
len
)
tlen
=
len
;
if
(
copy_to_user
(
buf
,
(
char
*
)
info
+
rpos
,
tlen
))
{
return
-
EFAULT
;
}
rpos
+=
tlen
;
buf
+=
tlen
;
len
-=
tlen
;
}
if
(
(
rpos
>=
devname_offset
)
&&
(
len
>
0
)
)
{
if
((
rpos
>=
devname_offset
)
&&
(
len
>
0
))
{
/* Copy the name */
tlen
=
info
->
namelen
+
1
;
if
(
tlen
>
len
)
tlen
=
len
;
else
done
=
TRUE
;
if
(
copy_to_user
(
buf
,
info
->
devname
+
pos
+
rpos
-
devname_offset
,
tlen
)
)
{
if
(
tlen
>
len
)
tlen
=
len
;
else
done
=
TRUE
;
if
(
copy_to_user
(
buf
,
info
->
devname
+
pos
+
rpos
-
devname_offset
,
tlen
))
{
return
-
EFAULT
;
}
rpos
+=
tlen
;
}
tlen
=
rpos
-
*
ppos
;
if
(
done
)
{
if
(
done
)
{
devfs_handle_t
parent
;
spin_lock
(
&
fs_info
->
devfsd_buffer_lock
);
spin_lock
(
&
fs_info
->
devfsd_buffer_lock
);
fs_info
->
devfsd_first_event
=
entry
->
next
;
if
(
entry
->
next
==
NULL
)
fs_info
->
devfsd_last_event
=
NULL
;
spin_unlock
(
&
fs_info
->
devfsd_buffer_lock
)
;
for
(;
de
!=
NULL
;
de
=
parent
)
{
if
(
entry
->
next
==
NULL
)
fs_info
->
devfsd_last_event
=
NULL
;
spin_unlock
(
&
fs_info
->
devfsd_buffer_lock
);
for
(;
de
!=
NULL
;
de
=
parent
)
{
parent
=
de
->
parent
;
devfs_put
(
de
);
devfs_put
(
de
);
}
kmem_cache_free
(
devfsd_buf_cache
,
entry
);
if
(
ival
>
0
)
atomic_sub
(
ival
,
&
fs_info
->
devfsd_overrun_count
);
kmem_cache_free
(
devfsd_buf_cache
,
entry
);
if
(
ival
>
0
)
atomic_sub
(
ival
,
&
fs_info
->
devfsd_overrun_count
);
*
ppos
=
0
;
}
else
*
ppos
=
rpos
;
}
else
*
ppos
=
rpos
;
return
tlen
;
}
/* End Function devfsd_read */
static
int
devfsd_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
static
int
devfsd_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
int
ival
;
struct
fs_info
*
fs_info
=
inode
->
i_sb
->
s_fs_info
;
switch
(
cmd
)
{
switch
(
cmd
)
{
case
DEVFSDIOC_GET_PROTO_REV
:
ival
=
DEVFSD_PROTOCOL_REVISION_KERNEL
;
if
(
copy_to_user
(
(
void
*
)
arg
,
&
ival
,
sizeof
ival
)
)
return
-
EFAULT
;
if
(
copy_to_user
((
void
*
)
arg
,
&
ival
,
sizeof
ival
))
return
-
EFAULT
;
break
;
case
DEVFSDIOC_SET_EVENT_MASK
:
/* Ensure only one reader has access to the queue. This scheme will
work even if the global kernel lock were to be removed, because it
doesn't matter who gets in first, as long as only one gets it */
if
(
fs_info
->
devfsd_task
==
NULL
)
{
if
(
fs_info
->
devfsd_task
==
NULL
)
{
static
spinlock_t
lock
=
SPIN_LOCK_UNLOCKED
;
if
(
!
spin_trylock
(
&
lock
)
)
return
-
EBUSY
;
if
(
fs_info
->
devfsd_task
!=
NULL
)
{
/* We lost the race... */
spin_unlock
(
&
lock
);
if
(
!
spin_trylock
(
&
lock
))
return
-
EBUSY
;
if
(
fs_info
->
devfsd_task
!=
NULL
)
{
/* We lost the race... */
spin_unlock
(
&
lock
);
return
-
EBUSY
;
}
fs_info
->
devfsd_task
=
current
;
spin_unlock
(
&
lock
);
fs_info
->
devfsd_pgrp
=
(
process_group
(
current
)
==
current
->
pid
)
?
process_group
(
current
)
:
0
;
spin_unlock
(
&
lock
);
fs_info
->
devfsd_pgrp
=
(
process_group
(
current
)
==
current
->
pid
)
?
process_group
(
current
)
:
0
;
fs_info
->
devfsd_file
=
file
;
fs_info
->
devfsd_info
=
kmalloc
(
sizeof
*
fs_info
->
devfsd_info
,
GFP_KERNEL
);
if
(
!
fs_info
->
devfsd_info
)
{
devfsd_close
(
inode
,
file
);
fs_info
->
devfsd_info
=
kmalloc
(
sizeof
*
fs_info
->
devfsd_info
,
GFP_KERNEL
);
if
(
!
fs_info
->
devfsd_info
)
{
devfsd_close
(
inode
,
file
);
return
-
ENOMEM
;
}
}
else
if
(
fs_info
->
devfsd_task
!=
current
)
return
-
EBUSY
;
}
else
if
(
fs_info
->
devfsd_task
!=
current
)
return
-
EBUSY
;
fs_info
->
devfsd_event_mask
=
arg
;
/* Let the masses come forth */
break
;
case
DEVFSDIOC_RELEASE_EVENT_QUEUE
:
if
(
fs_info
->
devfsd_file
!=
file
)
return
-
EPERM
;
return
devfsd_close
(
inode
,
file
);
/*break;*/
if
(
fs_info
->
devfsd_file
!=
file
)
return
-
EPERM
;
return
devfsd_close
(
inode
,
file
);
/*break; */
#ifdef CONFIG_DEVFS_DEBUG
case
DEVFSDIOC_SET_DEBUG_MASK
:
if
(
copy_from_user
(
&
ival
,
(
void
*
)
arg
,
sizeof
ival
)
)
return
-
EFAULT
;
if
(
copy_from_user
(
&
ival
,
(
void
*
)
arg
,
sizeof
ival
))
return
-
EFAULT
;
devfs_debug
=
ival
;
break
;
#endif
...
...
@@ -2730,49 +2743,52 @@ static int devfsd_ioctl (struct inode *inode, struct file *file,
return
0
;
}
/* End Function devfsd_ioctl */
static
int
devfsd_close
(
struct
inode
*
inode
,
struct
file
*
file
)
static
int
devfsd_close
(
struct
inode
*
inode
,
struct
file
*
file
)
{
struct
devfsd_buf_entry
*
entry
,
*
next
;
struct
fs_info
*
fs_info
=
inode
->
i_sb
->
s_fs_info
;
if
(
fs_info
->
devfsd_file
!=
file
)
return
0
;
if
(
fs_info
->
devfsd_file
!=
file
)
return
0
;
fs_info
->
devfsd_event_mask
=
0
;
fs_info
->
devfsd_file
=
NULL
;
spin_lock
(
&
fs_info
->
devfsd_buffer_lock
);
spin_lock
(
&
fs_info
->
devfsd_buffer_lock
);
entry
=
fs_info
->
devfsd_first_event
;
fs_info
->
devfsd_first_event
=
NULL
;
fs_info
->
devfsd_last_event
=
NULL
;
if
(
fs_info
->
devfsd_info
)
{
kfree
(
fs_info
->
devfsd_info
);
if
(
fs_info
->
devfsd_info
)
{
kfree
(
fs_info
->
devfsd_info
);
fs_info
->
devfsd_info
=
NULL
;
}
spin_unlock
(
&
fs_info
->
devfsd_buffer_lock
);
spin_unlock
(
&
fs_info
->
devfsd_buffer_lock
);
fs_info
->
devfsd_pgrp
=
0
;
fs_info
->
devfsd_task
=
NULL
;
wake_up
(
&
fs_info
->
revalidate_wait_queue
);
for
(;
entry
;
entry
=
next
)
{
wake_up
(
&
fs_info
->
revalidate_wait_queue
);
for
(;
entry
;
entry
=
next
)
{
next
=
entry
->
next
;
kmem_cache_free
(
devfsd_buf_cache
,
entry
);
kmem_cache_free
(
devfsd_buf_cache
,
entry
);
}
return
0
;
}
/* End Function devfsd_close */
#ifdef CONFIG_DEVFS_DEBUG
static
ssize_t
stat_read
(
struct
file
*
file
,
char
*
buf
,
size_t
len
,
loff_t
*
ppos
)
static
ssize_t
stat_read
(
struct
file
*
file
,
char
*
buf
,
size_t
len
,
loff_t
*
ppos
)
{
ssize_t
num
;
char
txt
[
80
];
num
=
sprintf
(
txt
,
"Number of entries: %u number of bytes: %u
\n
"
,
num
=
sprintf
(
txt
,
"Number of entries: %u number of bytes: %u
\n
"
,
stat_num_entries
,
stat_num_bytes
)
+
1
;
/* Can't seek (pread) on this device */
if
(
ppos
!=
&
file
->
f_pos
)
return
-
ESPIPE
;
if
(
*
ppos
>=
num
)
return
0
;
if
(
*
ppos
+
len
>
num
)
len
=
num
-
*
ppos
;
if
(
copy_to_user
(
buf
,
txt
+
*
ppos
,
len
)
)
return
-
EFAULT
;
if
(
ppos
!=
&
file
->
f_pos
)
return
-
ESPIPE
;
if
(
*
ppos
>=
num
)
return
0
;
if
(
*
ppos
+
len
>
num
)
len
=
num
-
*
ppos
;
if
(
copy_to_user
(
buf
,
txt
+
*
ppos
,
len
))
return
-
EFAULT
;
*
ppos
+=
len
;
return
len
;
}
/* End Function stat_read */
...
...
@@ -2793,7 +2809,7 @@ static int __init init_devfs_fs(void)
printk
(
KERN_INFO
"%s: %s Richard Gooch (rgooch@atnf.csiro.au)
\n
"
,
DEVFS_NAME
,
DEVFS_VERSION
);
devfsd_buf_cache
=
kmem_cache_create
(
"devfsd_event"
,
sizeof
(
struct
devfsd_buf_entry
),
sizeof
(
struct
devfsd_buf_entry
),
0
,
0
,
NULL
,
NULL
);
if
(
!
devfsd_buf_cache
)
OOPS
(
"(): unable to allocate event slab
\n
"
);
...
...
@@ -2809,32 +2825,35 @@ static int __init init_devfs_fs(void)
return
major
;
/* And create the entry for ".devfsd" */
devfsd
=
_devfs_alloc_entry
(
".devfsd"
,
0
,
S_IFCHR
|
S_IRUSR
|
S_IWUSR
);
if
(
devfsd
==
NULL
)
devfsd
=
_devfs_alloc_entry
(
".devfsd"
,
0
,
S_IFCHR
|
S_IRUSR
|
S_IWUSR
);
if
(
devfsd
==
NULL
)
return
-
ENOMEM
;
devfsd
->
u
.
dev
=
MKDEV
(
major
,
0
);
_devfs_append_entry
(
root_entry
,
devfsd
,
NULL
);
#ifdef CONFIG_DEVFS_DEBUG
stat
=
_devfs_alloc_entry
(
".stat"
,
0
,
S_IFCHR
|
S_IRUGO
);
if
(
stat
==
NULL
)
stat
=
_devfs_alloc_entry
(
".stat"
,
0
,
S_IFCHR
|
S_IRUGO
);
if
(
stat
==
NULL
)
return
-
ENOMEM
;
stat
->
u
.
dev
=
MKDEV
(
major
,
1
);
_devfs_append_entry
(
root_entry
,
stat
,
NULL
);
_devfs_append_entry
(
root_entry
,
stat
,
NULL
);
#endif
err
=
register_filesystem
(
&
devfs_fs_type
);
return
err
;
}
/* End Function init_devfs_fs */
void
__init
mount_devfs_fs
(
void
)
void
__init
mount_devfs_fs
(
void
)
{
int
err
;
if
(
!
(
boot_options
&
OPTION_MOUNT
)
)
return
;
err
=
do_mount
(
"none"
,
"/dev"
,
"devfs"
,
0
,
NULL
);
if
(
err
==
0
)
printk
(
KERN_INFO
"Mounted devfs on /dev
\n
"
);
else
PRINTK
(
"(): unable to mount devfs, err: %d
\n
"
,
err
);
if
(
!
(
boot_options
&
OPTION_MOUNT
))
return
;
err
=
do_mount
(
"none"
,
"/dev"
,
"devfs"
,
0
,
NULL
);
if
(
err
==
0
)
printk
(
KERN_INFO
"Mounted devfs on /dev
\n
"
);
else
PRINTK
(
"(): unable to mount devfs, err: %d
\n
"
,
err
);
}
/* End Function mount_devfs_fs */
module_init
(
init_devfs_fs
)
fs/devfs/util.c
View file @
243c64b2
...
...
@@ -73,7 +73,6 @@
#include <linux/genhd.h>
#include <asm/bitops.h>
int
devfs_register_tape
(
const
char
*
name
)
{
char
tname
[
32
],
dest
[
64
];
...
...
@@ -86,6 +85,7 @@ int devfs_register_tape(const char *name)
return
n
;
}
EXPORT_SYMBOL
(
devfs_register_tape
);
void
devfs_unregister_tape
(
int
num
)
...
...
include/linux/devfs_fs.h
View file @
243c64b2
...
...
@@ -25,8 +25,7 @@
#define DEVFS_PATHLEN 1024
/* Never change this otherwise the
binary interface will change */
struct
devfsd_notify_struct
{
/* Use native C types to ensure same types in kernel and user space */
struct
devfsd_notify_struct
{
/* Use native C types to ensure same types in kernel and user space */
unsigned
int
type
;
/* DEVFSD_NOTIFY_* value */
unsigned
int
mode
;
/* Mode of the inode or device entry */
unsigned
int
major
;
/* Major number of device entry */
...
...
@@ -39,5 +38,4 @@ struct devfsd_notify_struct
char
devname
[
DEVFS_PATHLEN
];
/* This will be '\0' terminated */
};
#endif
/* _LINUX_DEVFS_FS_H */
include/linux/devfs_fs_kernel.h
View file @
243c64b2
...
...
@@ -12,14 +12,14 @@
#ifdef CONFIG_DEVFS_FS
extern
int
devfs_mk_bdev
(
dev_t
dev
,
umode_t
mode
,
const
char
*
fmt
,
...)
__attribute__
((
format
(
printf
,
3
,
4
)));
__attribute__
((
format
(
printf
,
3
,
4
)));
extern
int
devfs_mk_cdev
(
dev_t
dev
,
umode_t
mode
,
const
char
*
fmt
,
...)
__attribute__
((
format
(
printf
,
3
,
4
)));
__attribute__
((
format
(
printf
,
3
,
4
)));
extern
int
devfs_mk_symlink
(
const
char
*
name
,
const
char
*
link
);
extern
int
devfs_mk_dir
(
const
char
*
fmt
,
...)
__attribute__
((
format
(
printf
,
1
,
2
)));
__attribute__
((
format
(
printf
,
1
,
2
)));
extern
void
devfs_remove
(
const
char
*
fmt
,
...)
__attribute__
((
format
(
printf
,
1
,
2
)));
__attribute__
((
format
(
printf
,
1
,
2
)));
extern
int
devfs_register_tape
(
const
char
*
name
);
extern
void
devfs_unregister_tape
(
int
num
);
extern
void
mount_devfs_fs
(
void
);
...
...
@@ -32,7 +32,7 @@ static inline int devfs_mk_cdev(dev_t dev, umode_t mode, const char *fmt, ...)
{
return
0
;
}
static
inline
int
devfs_mk_symlink
(
const
char
*
name
,
const
char
*
link
)
static
inline
int
devfs_mk_symlink
(
const
char
*
name
,
const
char
*
link
)
{
return
0
;
}
...
...
@@ -43,14 +43,14 @@ static inline int devfs_mk_dir(const char *fmt, ...)
static
inline
void
devfs_remove
(
const
char
*
fmt
,
...)
{
}
static
inline
int
devfs_register_tape
(
const
char
*
name
)
static
inline
int
devfs_register_tape
(
const
char
*
name
)
{
return
-
1
;
}
static
inline
void
devfs_unregister_tape
(
int
num
)
{
}
static
inline
void
mount_devfs_fs
(
void
)
static
inline
void
mount_devfs_fs
(
void
)
{
return
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment