Commit abd988c4 authored by Linus Torvalds's avatar Linus Torvalds

Make ramfs/driverfs maintain directory nlink counts.

Make dcache filesystems export directory entry types
to readdir.
parent e180b535
......@@ -149,6 +149,10 @@ static int driverfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
lock_kernel();
dentry->d_op = &driverfs_dentry_dir_ops;
res = driverfs_mknod(dir, dentry, mode | S_IFDIR, 0);
if (!res) {
dir->i_nlink++;
dentry->d_inode->i_nlink++;
}
unlock_kernel();
return res;
}
......@@ -206,22 +210,28 @@ static int driverfs_empty(struct dentry *dentry)
static int driverfs_unlink(struct inode *dir, struct dentry *dentry)
{
int error = -ENOTEMPTY;
if (driverfs_empty(dentry)) {
struct inode *inode = dentry->d_inode;
lock_kernel();
inode->i_nlink--;
unlock_kernel();
dput(dentry);
return 0;
}
static int driverfs_rmdir(struct inode *dir, struct dentry *dentry)
{
int error = -ENOTEMPTY;
if (driverfs_empty(dentry)) {
dentry->d_inode->i_nlink--;
driverfs_unlink(dir, dentry);
dir->i_nlink--;
error = 0;
}
return error;
}
#define driverfs_rmdir driverfs_unlink
/**
* driverfs_read_file - "read" data from a file.
* @file: file pointer
......
......@@ -83,6 +83,12 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin)
return offset;
}
/* Relationship between i_mode and the DT_xxx types */
static inline unsigned char dt_type(struct inode *inode)
{
return (inode->i_mode >> 12) & 15;
}
/*
* Directory is locked and all positive dentries in it are safe, since
* for ramfs-type trees they can't go away without unlink() or rmdir(),
......@@ -125,7 +131,7 @@ int dcache_readdir(struct file * filp, void * dirent, filldir_t filldir)
continue;
spin_unlock(&dcache_lock);
if (filldir(dirent, next->d_name.name, next->d_name.len, filp->f_pos, next->d_inode->i_ino, DT_UNKNOWN) < 0)
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)
return 0;
spin_lock(&dcache_lock);
/* next is still alive */
......
......@@ -130,7 +130,12 @@ static int ramfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int d
static int ramfs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
{
return ramfs_mknod(dir, dentry, mode | S_IFDIR, 0);
int retval = ramfs_mknod(dir, dentry, mode | S_IFDIR, 0);
if (!retval) {
dir->i_nlink++;
dentry->d_inode->i_nlink++;
}
return retval;
}
static int ramfs_create(struct inode *dir, struct dentry *dentry, int mode)
......@@ -186,25 +191,30 @@ static int ramfs_empty(struct dentry *dentry)
}
/*
* This works for both directories and regular files.
* (non-directories will always have empty subdirs)
* Unlink a ramfs entry
*/
static int ramfs_unlink(struct inode * dir, struct dentry *dentry)
{
int retval = -ENOTEMPTY;
if (ramfs_empty(dentry)) {
struct inode *inode = dentry->d_inode;
inode->i_nlink--;
dput(dentry); /* Undo the count from "create" - this does all the work */
return 0;
}
static int ramfs_rmdir(struct inode * dir, struct dentry *dentry)
{
int retval = -ENOTEMPTY;
if (ramfs_empty(dentry)) {
dentry->d_inode->i_nlink--;
ramfs_unlink(dir, dentry);
dir->i_nlink--;
retval = 0;
}
return retval;
}
#define ramfs_rmdir ramfs_unlink
/*
* The VFS layer already does all the dentry stuff for rename,
* we just have to decrement the usage count for the target if
......@@ -221,6 +231,10 @@ static int ramfs_rename(struct inode * old_dir, struct dentry *old_dentry, struc
inode->i_nlink--;
dput(new_dentry);
}
if (S_ISDIR(old_dentry->d_inode->i_mode)) {
old_dir->i_nlink--;
new_dir->i_nlink++;
}
error = 0;
}
return error;
......
......@@ -701,6 +701,9 @@ extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct de
/*
* File types
*
* NOTE! These match bits 12..15 of stat.st_mode
* (ie "(i_mode >> 12) & 15").
*/
#define DT_UNKNOWN 0
#define DT_FIFO 1
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment