From: arnd@arndb.de
To: linux-fsdevel@vger.kernel.org
Cc: linux-kernel@vger.kernel.org, hch@lst.de
Subject: [RFC 4/7] cramfs: allow rmdir
Date: Sat, 31 May 2008 17:20:17 +0200 [thread overview]
Message-ID: <20080531153510.947704691@arndb.de> (raw)
In-Reply-To: 20080531152013.031903990@arndb.de
[-- Attachment #1: 0004-cramfs-allow-rmdir.patch --]
[-- Type: text/plain, Size: 3852 bytes --]
rmdir in cramfs works much like unlink, but we need to check
first that the directory is empty. Since the link count is
always 1, we have to look at the directory contents for that,
but fortunately, we can abuse the readdir logic for that,
to check if at least one entry exists.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
fs/cramfs/inode.c | 71 +++++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 61 insertions(+), 10 deletions(-)
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index 6b9f21f..8c3e8bb 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -326,18 +326,20 @@ static int cramfs_statfs(struct dentry *dentry, struct kstatfs *buf)
/*
* Read a cramfs directory entry.
*/
-static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+static int cramfs_readdir_ondisk(struct dentry *dentry, void *dirent,
+ filldir_t filldir, loff_t *pos)
{
- struct inode *inode = filp->f_path.dentry->d_inode;
+ struct inode *inode = dentry->d_inode;
struct super_block *sb = inode->i_sb;
char *buf;
unsigned int offset;
int copied;
/* Offset within the thing. */
- offset = filp->f_pos;
+ offset = *pos;
if (offset >= inode->i_size)
return 0;
+
/* Directory entries are always 4-byte aligned */
if (offset & 3)
return -EINVAL;
@@ -355,7 +357,7 @@ static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
ino_t ino;
mode_t mode;
int namelen, error;
- struct dentry *dentry;
+ struct dentry *d;
mutex_lock(&read_mutex);
de = cramfs_read(sb, OFFSET(inode) + offset, sizeof(*de)+CRAMFS_MAXPATHLEN);
@@ -382,25 +384,32 @@ static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
namelen--;
}
qstr.len = namelen;
- dentry = d_hash_and_lookup(filp->f_path.dentry, &qstr);
+ d = d_hash_and_lookup(dentry, &qstr);
error = 0;
- if (!dentry || (dentry->d_inode))
- error = filldir(dirent, buf, namelen, offset,
- ino, mode >> 12);
+ if (!d || (d->d_inode))
+ error = filldir(dirent, buf, namelen,
+ offset, ino, mode >> 12);
- dput(dentry);
+ dput(d);
if (error)
break;
offset = nextoffset;
- filp->f_pos = offset;
+ *pos = offset;
copied++;
}
kfree(buf);
+
return 0;
}
+static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+{
+ return cramfs_readdir_ondisk(filp->f_dentry, dirent,
+ filldir, &filp->f_pos);
+}
+
int cramfs_unlink(struct inode *dir, struct dentry *dentry)
{
struct inode *inode = dentry->d_inode;
@@ -414,6 +423,47 @@ int cramfs_unlink(struct inode *dir, struct dentry *dentry)
dget(dentry);
return 0;
}
+
+/*
+ * We use the readdir infrastructure to test whether a directory is
+ * empty or not. cramfs_test_filldir will get called for any on-disk
+ * dentries that have not been unlinked.
+ */
+static int cramfs_test_filldir(void * __buf, const char * name, int namlen,
+ loff_t offset, u64 ino, unsigned int d_type)
+{
+ int *buf = __buf;
+ *buf = 0;
+ return -ENOTEMPTY;
+}
+
+static int cramfs_empty(struct dentry *dentry)
+{
+ loff_t pos = 0;
+ int empty = 1;
+ int ret;
+ if (!dentry->d_inode || !S_ISDIR(dentry->d_inode->i_mode))
+ return 1;
+
+ if (!simple_empty(dentry))
+ return 0;
+
+ ret = cramfs_readdir_ondisk(dentry, &empty, cramfs_test_filldir, &pos);
+ if (ret)
+ return ret;
+
+ return empty;
+}
+
+int cramfs_rmdir(struct inode *dir, struct dentry *dentry)
+{
+ if (!cramfs_empty(dentry))
+ return -ENOTEMPTY;
+
+ cramfs_unlink(dir, dentry);
+ return 0;
+}
+
/*
* Lookup and fill in the inode data..
*/
@@ -536,6 +586,7 @@ static const struct file_operations cramfs_directory_operations = {
static const struct inode_operations cramfs_dir_inode_operations = {
.unlink = cramfs_unlink,
+ .rmdir = cramfs_rmdir,
.lookup = cramfs_lookup,
};
--
1.5.4.3
--
next prev parent reply other threads:[~2008-05-31 15:41 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20080531152013.031903990@arndb.de>
2008-05-31 15:20 ` [RFC 1/7] cramfs: allow remount rw arnd
2008-05-31 15:20 ` [RFC 2/7] cramfs: create unique inode numbers arnd
2008-06-01 16:50 ` Jörn Engel
2008-06-01 21:24 ` Arnd Bergmann
2008-06-02 5:42 ` Jörn Engel
2008-05-31 15:20 ` [RFC 3/7] cramfs: allow unlinking of files arnd
2008-06-01 16:54 ` Jörn Engel
2008-06-01 21:28 ` Arnd Bergmann
2008-05-31 15:20 ` arnd [this message]
2008-05-31 15:20 ` [RFC 5/7] cramfs: allow writing to existing files arnd
2008-05-31 15:20 ` [RFC 6/7] cramfs: read directory entries from dcache arnd
2008-05-31 15:20 ` [RFC 7/7] cramfs: add missing inode operations arnd
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20080531153510.947704691@arndb.de \
--to=arnd@arndb.de \
--cc=hch@lst.de \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox