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) ...@@ -149,6 +149,10 @@ static int driverfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
lock_kernel(); lock_kernel();
dentry->d_op = &driverfs_dentry_dir_ops; dentry->d_op = &driverfs_dentry_dir_ops;
res = driverfs_mknod(dir, dentry, mode | S_IFDIR, 0); res = driverfs_mknod(dir, dentry, mode | S_IFDIR, 0);
if (!res) {
dir->i_nlink++;
dentry->d_inode->i_nlink++;
}
unlock_kernel(); unlock_kernel();
return res; return res;
} }
...@@ -206,22 +210,28 @@ static int driverfs_empty(struct dentry *dentry) ...@@ -206,22 +210,28 @@ static int driverfs_empty(struct dentry *dentry)
static int driverfs_unlink(struct inode *dir, 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; struct inode *inode = dentry->d_inode;
lock_kernel(); lock_kernel();
inode->i_nlink--; inode->i_nlink--;
unlock_kernel(); unlock_kernel();
dput(dentry); 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; error = 0;
} }
return error; return error;
} }
#define driverfs_rmdir driverfs_unlink
/** /**
* driverfs_read_file - "read" data from a file. * driverfs_read_file - "read" data from a file.
* @file: file pointer * @file: file pointer
......
...@@ -83,6 +83,12 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin) ...@@ -83,6 +83,12 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin)
return offset; 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 * 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(), * 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) ...@@ -125,7 +131,7 @@ int dcache_readdir(struct file * filp, void * dirent, filldir_t filldir)
continue; continue;
spin_unlock(&dcache_lock); 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; return 0;
spin_lock(&dcache_lock); spin_lock(&dcache_lock);
/* next is still alive */ /* next is still alive */
......
...@@ -130,7 +130,12 @@ static int ramfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int d ...@@ -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) 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) static int ramfs_create(struct inode *dir, struct dentry *dentry, int mode)
...@@ -186,25 +191,30 @@ static int ramfs_empty(struct dentry *dentry) ...@@ -186,25 +191,30 @@ static int ramfs_empty(struct dentry *dentry)
} }
/* /*
* This works for both directories and regular files. * Unlink a ramfs entry
* (non-directories will always have empty subdirs)
*/ */
static int ramfs_unlink(struct inode * dir, struct dentry *dentry) static int ramfs_unlink(struct inode * dir, struct dentry *dentry)
{ {
int retval = -ENOTEMPTY;
if (ramfs_empty(dentry)) {
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
inode->i_nlink--; inode->i_nlink--;
dput(dentry); /* Undo the count from "create" - this does all the work */ 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; retval = 0;
} }
return retval; return retval;
} }
#define ramfs_rmdir ramfs_unlink
/* /*
* The VFS layer already does all the dentry stuff for rename, * The VFS layer already does all the dentry stuff for rename,
* we just have to decrement the usage count for the target if * 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 ...@@ -221,6 +231,10 @@ static int ramfs_rename(struct inode * old_dir, struct dentry *old_dentry, struc
inode->i_nlink--; inode->i_nlink--;
dput(new_dentry); dput(new_dentry);
} }
if (S_ISDIR(old_dentry->d_inode->i_mode)) {
old_dir->i_nlink--;
new_dir->i_nlink++;
}
error = 0; error = 0;
} }
return error; return error;
......
...@@ -701,6 +701,9 @@ extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct de ...@@ -701,6 +701,9 @@ extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct de
/* /*
* File types * File types
*
* NOTE! These match bits 12..15 of stat.st_mode
* (ie "(i_mode >> 12) & 15").
*/ */
#define DT_UNKNOWN 0 #define DT_UNKNOWN 0
#define DT_FIFO 1 #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