summaryrefslogtreecommitdiffstats
path: root/fs/minix/namei.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/minix/namei.c')
-rw-r--r--fs/minix/namei.c293
1 files changed, 125 insertions, 168 deletions
diff --git a/fs/minix/namei.c b/fs/minix/namei.c
index b6041ad92..718d3dd07 100644
--- a/fs/minix/namei.c
+++ b/fs/minix/namei.c
@@ -47,9 +47,6 @@ static int minix_match(int len, const char * name,
*offset += info->s_dirsize;
if (!de->inode || len > info->s_namelen)
return 0;
- /* "" means "." ---> so paths like "/usr/lib//libc.a" work */
- if (!len && (de->name[0]=='.') && (de->name[1]=='\0'))
- return 1;
return namecompare(len,info->s_namelen,name,de->name);
}
@@ -104,31 +101,22 @@ static struct buffer_head * minix_find_entry(struct inode * dir,
return NULL;
}
-int minix_lookup(struct inode * dir,const char * name, int len,
- struct inode ** result)
+int minix_lookup(struct inode * dir, struct dentry *dentry)
{
- int ino;
+ struct inode * inode = NULL;
struct minix_dir_entry * de;
struct buffer_head * bh;
- *result = NULL;
- if (!dir)
- return -ENOENT;
- if (!S_ISDIR(dir->i_mode)) {
- iput(dir);
- return -ENOENT;
- }
- if (!(bh = minix_find_entry(dir,name,len,&de))) {
- iput(dir);
- return -ENOENT;
- }
- ino = de->inode;
- brelse(bh);
- if (!(*result = iget(dir->i_sb,ino))) {
- iput(dir);
- return -EACCES;
- }
- iput(dir);
+ bh = minix_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de);
+ if (bh) {
+ unsigned long ino = le32_to_cpu(de->inode);
+ brelse (bh);
+ inode = iget(dir->i_sb, ino);
+
+ if (!inode)
+ return -EACCES;
+ }
+ d_add(dentry, inode);
return 0;
}
@@ -180,7 +168,7 @@ static int minix_add_entry(struct inode * dir,
if (block*bh->b_size + offset > dir->i_size) {
de->inode = 0;
dir->i_size = block*bh->b_size + offset;
- dir->i_dirt = 1;
+ mark_inode_dirty(dir);
}
if (de->inode) {
if (namecompare(namelen, info->s_namelen, name, de->name)) {
@@ -189,7 +177,7 @@ static int minix_add_entry(struct inode * dir,
}
} else {
dir->i_mtime = dir->i_ctime = CURRENT_TIME;
- dir->i_dirt = 1;
+ mark_inode_dirty(dir);
for (i = 0; i < info->s_namelen ; i++)
de->name[i] = (i < namelen) ? name[i] : 0;
dir->i_version = ++event;
@@ -208,42 +196,37 @@ static int minix_add_entry(struct inode * dir,
return 0;
}
-int minix_create(struct inode * dir,const char * name, int len, int mode,
- struct inode ** result)
+int minix_create(struct inode * dir, struct dentry *dentry, int mode)
{
int error;
struct inode * inode;
struct buffer_head * bh;
struct minix_dir_entry * de;
- *result = NULL;
if (!dir)
return -ENOENT;
inode = minix_new_inode(dir);
- if (!inode) {
- iput(dir);
+ if (!inode)
return -ENOSPC;
- }
inode->i_op = &minix_file_inode_operations;
inode->i_mode = mode;
- inode->i_dirt = 1;
- error = minix_add_entry(dir,name,len, &bh ,&de);
+ mark_inode_dirty(inode);
+ error = minix_add_entry(dir, dentry->d_name.name,
+ dentry->d_name.len, &bh ,&de);
if (error) {
inode->i_nlink--;
- inode->i_dirt = 1;
+ mark_inode_dirty(inode);
iput(inode);
- iput(dir);
return error;
}
de->inode = inode->i_ino;
mark_buffer_dirty(bh, 1);
brelse(bh);
- iput(dir);
- *result = inode;
+ d_instantiate(dentry, inode);
return 0;
}
-int minix_mknod(struct inode * dir, const char * name, int len, int mode, int rdev)
+int minix_mknod(struct inode * dir, struct dentry *dentry, int mode, int rdev)
{
int error;
struct inode * inode;
@@ -252,17 +235,15 @@ int minix_mknod(struct inode * dir, const char * name, int len, int mode, int rd
if (!dir)
return -ENOENT;
- bh = minix_find_entry(dir,name,len,&de);
+ bh = minix_find_entry(dir, dentry->d_name.name,
+ dentry->d_name.len, &de);
if (bh) {
brelse(bh);
- iput(dir);
return -EEXIST;
}
inode = minix_new_inode(dir);
- if (!inode) {
- iput(dir);
+ if (!inode)
return -ENOSPC;
- }
inode->i_uid = current->fsuid;
inode->i_mode = mode;
inode->i_op = NULL;
@@ -283,24 +264,22 @@ int minix_mknod(struct inode * dir, const char * name, int len, int mode, int rd
init_fifo(inode);
if (S_ISBLK(mode) || S_ISCHR(mode))
inode->i_rdev = to_kdev_t(rdev);
- inode->i_dirt = 1;
- error = minix_add_entry(dir, name, len, &bh, &de);
+ mark_inode_dirty(inode);
+ error = minix_add_entry(dir, dentry->d_name.name, dentry->d_name.len, &bh, &de);
if (error) {
inode->i_nlink--;
- inode->i_dirt = 1;
+ mark_inode_dirty(inode);
iput(inode);
- iput(dir);
return error;
}
de->inode = inode->i_ino;
mark_buffer_dirty(bh, 1);
brelse(bh);
- iput(dir);
- iput(inode);
+ d_instantiate(dentry, inode);
return 0;
}
-int minix_mkdir(struct inode * dir, const char * name, int len, int mode)
+int minix_mkdir(struct inode * dir, struct dentry *dentry, int mode)
{
int error;
struct inode * inode;
@@ -308,33 +287,26 @@ int minix_mkdir(struct inode * dir, const char * name, int len, int mode)
struct minix_dir_entry * de;
struct minix_sb_info * info;
- if (!dir || !dir->i_sb) {
- iput(dir);
+ if (!dir || !dir->i_sb)
return -EINVAL;
- }
info = &dir->i_sb->u.minix_sb;
- bh = minix_find_entry(dir,name,len,&de);
+ bh = minix_find_entry(dir, dentry->d_name.name,
+ dentry->d_name.len, &de);
if (bh) {
brelse(bh);
- iput(dir);
return -EEXIST;
}
- if (dir->i_nlink >= MINIX_LINK_MAX) {
- iput(dir);
+ if (dir->i_nlink >= MINIX_LINK_MAX)
return -EMLINK;
- }
inode = minix_new_inode(dir);
- if (!inode) {
- iput(dir);
+ if (!inode)
return -ENOSPC;
- }
inode->i_op = &minix_dir_inode_operations;
inode->i_size = 2 * info->s_dirsize;
dir_block = minix_bread(inode,0,1);
if (!dir_block) {
- iput(dir);
inode->i_nlink--;
- inode->i_dirt = 1;
+ mark_inode_dirty(inode);
iput(inode);
return -ENOSPC;
}
@@ -350,10 +322,10 @@ int minix_mkdir(struct inode * dir, const char * name, int len, int mode)
inode->i_mode = S_IFDIR | (mode & 0777 & ~current->fs->umask);
if (dir->i_mode & S_ISGID)
inode->i_mode |= S_ISGID;
- inode->i_dirt = 1;
- error = minix_add_entry(dir, name, len, &bh, &de);
+ mark_inode_dirty(inode);
+ error = minix_add_entry(dir, dentry->d_name.name,
+ dentry->d_name.len, &bh, &de);
if (error) {
- iput(dir);
inode->i_nlink=0;
iput(inode);
return error;
@@ -361,10 +333,9 @@ int minix_mkdir(struct inode * dir, const char * name, int len, int mode)
de->inode = inode->i_ino;
mark_buffer_dirty(bh, 1);
dir->i_nlink++;
- dir->i_dirt = 1;
- iput(dir);
- iput(inode);
+ mark_inode_dirty(dir);
brelse(bh);
+ d_instantiate(dentry, inode);
return 0;
}
@@ -427,7 +398,7 @@ bad_dir:
return 1;
}
-int minix_rmdir(struct inode * dir, const char * name, int len)
+int minix_rmdir(struct inode * dir, struct dentry *dentry)
{
int retval;
struct inode * inode;
@@ -435,13 +406,14 @@ int minix_rmdir(struct inode * dir, const char * name, int len)
struct minix_dir_entry * de;
inode = NULL;
- bh = minix_find_entry(dir,name,len,&de);
+ bh = minix_find_entry(dir, dentry->d_name.name,
+ dentry->d_name.len, &de);
retval = -ENOENT;
if (!bh)
goto end_rmdir;
retval = -EPERM;
- if (!(inode = iget(dir->i_sb, de->inode)))
- goto end_rmdir;
+ inode = dentry->d_inode;
+
if ((dir->i_mode & S_ISVTX) && !fsuser() &&
current->fsuid != inode->i_uid &&
current->fsuid != dir->i_uid)
@@ -462,7 +434,7 @@ int minix_rmdir(struct inode * dir, const char * name, int len)
retval = -ENOENT;
goto end_rmdir;
}
- if (atomic_read(&inode->i_count) > 1) {
+ if (inode->i_count > 1) {
retval = -EBUSY;
goto end_rmdir;
}
@@ -472,19 +444,18 @@ int minix_rmdir(struct inode * dir, const char * name, int len)
dir->i_version = ++event;
mark_buffer_dirty(bh, 1);
inode->i_nlink=0;
- inode->i_dirt=1;
+ mark_inode_dirty(inode);
inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
dir->i_nlink--;
- dir->i_dirt=1;
+ mark_inode_dirty(dir);
+ d_delete(dentry);
retval = 0;
end_rmdir:
- iput(dir);
- iput(inode);
brelse(bh);
return retval;
}
-int minix_unlink(struct inode * dir, const char * name, int len)
+int minix_unlink(struct inode * dir, struct dentry *dentry)
{
int retval;
struct inode * inode;
@@ -494,16 +465,16 @@ int minix_unlink(struct inode * dir, const char * name, int len)
repeat:
retval = -ENOENT;
inode = NULL;
- bh = minix_find_entry(dir,name,len,&de);
+ bh = minix_find_entry(dir, dentry->d_name.name,
+ dentry->d_name.len, &de);
if (!bh)
goto end_unlink;
- if (!(inode = iget(dir->i_sb, de->inode)))
- goto end_unlink;
+ inode = dentry->d_inode;
+
retval = -EPERM;
if (S_ISDIR(inode->i_mode))
goto end_unlink;
if (de->inode != inode->i_ino) {
- iput(inode);
brelse(bh);
current->counter = 0;
schedule();
@@ -527,19 +498,19 @@ repeat:
dir->i_version = ++event;
mark_buffer_dirty(bh, 1);
dir->i_ctime = dir->i_mtime = CURRENT_TIME;
- dir->i_dirt = 1;
+ mark_inode_dirty(dir);
inode->i_nlink--;
inode->i_ctime = dir->i_ctime;
- inode->i_dirt = 1;
+ mark_inode_dirty(inode);
+ d_delete(dentry); /* This also frees the inode */
retval = 0;
end_unlink:
brelse(bh);
- iput(inode);
- iput(dir);
return retval;
}
-int minix_symlink(struct inode * dir, const char * name, int len, const char * symname)
+int minix_symlink(struct inode * dir, struct dentry *dentry,
+ const char * symname)
{
struct minix_dir_entry * de;
struct inode * inode = NULL;
@@ -547,17 +518,15 @@ int minix_symlink(struct inode * dir, const char * name, int len, const char * s
int i;
char c;
- if (!(inode = minix_new_inode(dir))) {
- iput(dir);
+ if (!(inode = minix_new_inode(dir)))
return -ENOSPC;
- }
+
inode->i_mode = S_IFLNK | 0777;
inode->i_op = &minix_symlink_inode_operations;
name_block = minix_bread(inode,0,1);
if (!name_block) {
- iput(dir);
inode->i_nlink--;
- inode->i_dirt = 1;
+ mark_inode_dirty(inode);
iput(inode);
return -ENOSPC;
}
@@ -568,93 +537,81 @@ int minix_symlink(struct inode * dir, const char * name, int len, const char * s
mark_buffer_dirty(name_block, 1);
brelse(name_block);
inode->i_size = i;
- inode->i_dirt = 1;
- bh = minix_find_entry(dir,name,len,&de);
+ mark_inode_dirty(inode);
+ bh = minix_find_entry(dir, dentry->d_name.name,
+ dentry->d_name.len, &de);
if (bh) {
inode->i_nlink--;
- inode->i_dirt = 1;
+ mark_inode_dirty(inode);
iput(inode);
brelse(bh);
- iput(dir);
return -EEXIST;
}
- i = minix_add_entry(dir, name, len, &bh, &de);
+ i = minix_add_entry(dir, dentry->d_name.name,
+ dentry->d_name.len, &bh, &de);
if (i) {
inode->i_nlink--;
- inode->i_dirt = 1;
+ mark_inode_dirty(inode);
iput(inode);
- iput(dir);
return i;
}
de->inode = inode->i_ino;
mark_buffer_dirty(bh, 1);
brelse(bh);
- iput(dir);
- iput(inode);
+ d_instantiate(dentry, inode);
return 0;
}
-int minix_link(struct inode * oldinode, struct inode * dir, const char * name, int len)
+int minix_link(struct inode * inode, struct inode * dir,
+ struct dentry *dentry)
{
int error;
struct minix_dir_entry * de;
struct buffer_head * bh;
- if (S_ISDIR(oldinode->i_mode)) {
- iput(oldinode);
- iput(dir);
+ if (S_ISDIR(inode->i_mode))
return -EPERM;
- }
- if (oldinode->i_nlink >= MINIX_LINK_MAX) {
- iput(oldinode);
- iput(dir);
+
+ if (inode->i_nlink >= MINIX_LINK_MAX)
return -EMLINK;
- }
- bh = minix_find_entry(dir,name,len,&de);
+
+ bh = minix_find_entry(dir, dentry->d_name.name,
+ dentry->d_name.len, &de);
if (bh) {
brelse(bh);
- iput(dir);
- iput(oldinode);
return -EEXIST;
}
- error = minix_add_entry(dir, name, len, &bh, &de);
+ error = minix_add_entry(dir, dentry->d_name.name,
+ dentry->d_name.len, &bh, &de);
if (error) {
- iput(dir);
- iput(oldinode);
+ brelse(bh);
return error;
}
- de->inode = oldinode->i_ino;
+ de->inode = inode->i_ino;
mark_buffer_dirty(bh, 1);
brelse(bh);
- iput(dir);
- oldinode->i_nlink++;
- oldinode->i_ctime = CURRENT_TIME;
- oldinode->i_dirt = 1;
- iput(oldinode);
+ inode->i_nlink++;
+ inode->i_ctime = CURRENT_TIME;
+ mark_inode_dirty(inode);
+ d_instantiate(dentry, inode);
return 0;
}
-static int subdir(struct inode * new_inode, struct inode * old_inode)
+static int subdir(struct dentry * new_dentry, struct dentry * old_dentry)
{
- int ino;
- int result;
+ int result = 0;
- atomic_inc(&new_inode->i_count);
- result = 0;
for (;;) {
- if (new_inode == old_inode) {
- result = 1;
- break;
+ if (new_dentry != old_dentry) {
+ struct dentry * parent = new_dentry->d_parent;
+ if (parent == new_dentry)
+ break;
+ new_dentry = parent;
+ continue;
}
- if (new_inode->i_dev != old_inode->i_dev)
- break;
- ino = new_inode->i_ino;
- if (minix_lookup(new_inode,"..",2,&new_inode))
- break;
- if (new_inode->i_ino == ino)
- break;
+ result = 1;
+ break;
}
- iput(new_inode);
return result;
}
@@ -671,8 +628,8 @@ static int subdir(struct inode * new_inode, struct inode * old_inode)
* Anybody can rename anything with this: the permission checks are left to the
* higher-level routines.
*/
-static int do_minix_rename(struct inode * old_dir, const char * old_name, int old_len,
- struct inode * new_dir, const char * new_name, int new_len)
+static int do_minix_rename(struct inode * old_dir, struct dentry *old_dentry,
+ struct inode * new_dir, struct dentry *new_dentry)
{
struct inode * old_inode, * new_inode;
struct buffer_head * old_bh, * new_bh, * dir_bh;
@@ -686,28 +643,26 @@ try_again:
brelse(old_bh);
brelse(new_bh);
brelse(dir_bh);
- iput(old_inode);
- iput(new_inode);
current->counter = 0;
schedule();
start_up:
old_inode = new_inode = NULL;
old_bh = new_bh = dir_bh = NULL;
- old_bh = minix_find_entry(old_dir,old_name,old_len,&old_de);
+ old_bh = minix_find_entry(old_dir, old_dentry->d_name.name,
+ old_dentry->d_name.len, &old_de);
retval = -ENOENT;
if (!old_bh)
goto end_rename;
- old_inode = __iget(old_dir->i_sb, old_de->inode,0); /* don't cross mnt-points */
- if (!old_inode)
- goto end_rename;
+ old_inode = old_dentry->d_inode;
retval = -EPERM;
if ((old_dir->i_mode & S_ISVTX) &&
current->fsuid != old_inode->i_uid &&
current->fsuid != old_dir->i_uid && !fsuser())
goto end_rename;
- new_bh = minix_find_entry(new_dir,new_name,new_len,&new_de);
+ new_inode = new_dentry->d_inode;
+ new_bh = minix_find_entry(new_dir, new_dentry->d_name.name,
+ new_dentry->d_name.len, &new_de);
if (new_bh) {
- new_inode = __iget(new_dir->i_sb, new_de->inode, 0);
if (!new_inode) {
brelse(new_bh);
new_bh = NULL;
@@ -722,13 +677,13 @@ start_up:
if (!S_ISDIR(old_inode->i_mode))
goto end_rename;
retval = -EINVAL;
- if (subdir(new_dir, old_inode))
+ if (subdir(new_dentry, old_dentry))
goto end_rename;
retval = -ENOTEMPTY;
if (!empty_dir(new_inode))
goto end_rename;
retval = -EBUSY;
- if (atomic_read(&new_inode->i_count) > 1)
+ if (new_inode->i_count > 1)
goto end_rename;
}
retval = -EPERM;
@@ -741,7 +696,7 @@ start_up:
if (new_inode && !S_ISDIR(new_inode->i_mode))
goto end_rename;
retval = -EINVAL;
- if (subdir(new_dir, old_inode))
+ if (subdir(new_dentry, old_dentry))
goto end_rename;
retval = -EIO;
dir_bh = minix_bread(old_inode,0,0);
@@ -754,7 +709,10 @@ start_up:
goto end_rename;
}
if (!new_bh) {
- retval = minix_add_entry(new_dir,new_name,new_len,&new_bh,&new_de);
+ retval = minix_add_entry(new_dir,
+ new_dentry->d_name.name,
+ new_dentry->d_name.len,
+ &new_bh, &new_de);
if (retval)
goto end_rename;
}
@@ -769,15 +727,15 @@ start_up:
old_de->inode = 0;
new_de->inode = old_inode->i_ino;
old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
- old_dir->i_dirt = 1;
+ mark_inode_dirty(old_dir);
old_dir->i_version = ++event;
new_dir->i_ctime = new_dir->i_mtime = CURRENT_TIME;
- new_dir->i_dirt = 1;
+ mark_inode_dirty(new_dir);
new_dir->i_version = ++event;
if (new_inode) {
new_inode->i_nlink--;
new_inode->i_ctime = CURRENT_TIME;
- new_inode->i_dirt = 1;
+ mark_inode_dirty(new_inode);
}
mark_buffer_dirty(old_bh, 1);
mark_buffer_dirty(new_bh, 1);
@@ -785,24 +743,23 @@ start_up:
PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
mark_buffer_dirty(dir_bh, 1);
old_dir->i_nlink--;
- old_dir->i_dirt = 1;
+ mark_inode_dirty(old_dir);
if (new_inode) {
new_inode->i_nlink--;
- new_inode->i_dirt = 1;
+ mark_inode_dirty(new_inode);
} else {
new_dir->i_nlink++;
- new_dir->i_dirt = 1;
+ mark_inode_dirty(new_dir);
}
}
+ /* Update the dcache */
+ d_move(old_dentry, new_dentry->d_parent, &new_dentry->d_name);
+ d_delete(new_dentry);
retval = 0;
end_rename:
brelse(dir_bh);
brelse(old_bh);
brelse(new_bh);
- iput(old_inode);
- iput(new_inode);
- iput(old_dir);
- iput(new_dir);
return retval;
}
@@ -815,8 +772,8 @@ end_rename:
* the same device that races occur: many renames can happen at once, as long
* as they are on different partitions.
*/
-int minix_rename(struct inode * old_dir, const char * old_name, int old_len,
- struct inode * new_dir, const char * new_name, int new_len)
+int minix_rename(struct inode * old_dir, struct dentry *old_dentry,
+ struct inode * new_dir, struct dentry *new_dentry)
{
static struct wait_queue * wait = NULL;
static int lock = 0;
@@ -825,8 +782,8 @@ int minix_rename(struct inode * old_dir, const char * old_name, int old_len,
while (lock)
sleep_on(&wait);
lock = 1;
- result = do_minix_rename(old_dir, old_name, old_len,
- new_dir, new_name, new_len);
+ result = do_minix_rename(old_dir, old_dentry,
+ new_dir, new_dentry);
lock = 0;
wake_up(&wait);
return result;