Re: 2.6.29 -mm merge plans

Diego E. 'Flameeyes' Pettenò
2009-01-06T23:27:37Z

[-- Attachment #1.1: Type: text/plain, Size: 774 bytes --]

On Tue, 2009-01-06 at 18:19 -0500, Christoph Hellwig wrote:
> The third one is where I requested a respin, and I'm pretty sure I've
> seen a version with some improvement over the one in your tree. Let's
> get the latests version back on -fsdevel and review it again.
>
> The one in your tree certainly is not ready.

Yes that one wasn't good at all, and I feel sorry for not having noticed
that before sending it in the first place.

I've sent an updated one (which I'm attaching right now too), and this
one I've been using (on both .28 and .27 before, slightly modified)
without any issue at all (fixed the random disappearence of the path on
my laptop from time to time indeed).

Thanks,

--
Diego "Flameeyes" Pettenò
http://blog.flameeyes.eu/

[-- Attachment #1.2: 0001-Add-basic-export-support-to-HFS-filesystem.patch --]
[-- Type: text/x-patch, Size: 5719 bytes --]

From 7f6df1ee70ffdd7ac75f6990463ef3a48582ad8e Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Diego=20E.=20'Flameeyes'=20Petten=C3=B2?= <flameeyes@gmail.com>
Date: Thu, 4 Dec 2008 13:32:06 +0100
Subject: [PATCH] Add basic export support to HFS+ filesystem.
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit

The functions' skeleton is taken from ext2/super.c and seems to work
fine for R/W access to HFS+ non-journaled case-sensitive filesystems.

Signed-off-by: Diego E. 'Flameeyes' Pettenò <flameeyes@gmail.com>
Cc: Roman Zippel <zippel@linux-m68k.org>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Neil Brown <neilb@suse.de>
---
fs/hfsplus/Makefile | 3 +-
fs/hfsplus/export.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++
fs/hfsplus/hfsplus_fs.h | 3 +
fs/hfsplus/super.c | 1 +
4 files changed, 124 insertions(+), 1 deletions(-)
create mode 100644 fs/hfsplus/export.c

diff --git a/fs/hfsplus/Makefile b/fs/hfsplus/Makefile
index 3cc0df7..374131e 100644
--- a/fs/hfsplus/Makefile
+++ b/fs/hfsplus/Makefile
@@ -5,5 +5,6 @@
obj-$(CONFIG_HFSPLUS_FS) += hfsplus.o

hfsplus-objs := super.o options.o inode.o ioctl.o extents.o catalog.o dir.o btree.o \
- bnode.o brec.o bfind.o tables.o unicode.o wrapper.o bitmap.o part_tbl.o
+ bnode.o brec.o bfind.o tables.o unicode.o wrapper.o bitmap.o part_tbl.o \
+ export.o

diff --git a/fs/hfsplus/export.c b/fs/hfsplus/export.c
new file mode 100644
index 0000000..91e5cb9
--- /dev/null
+++ b/fs/hfsplus/export.c
@@ -0,0 +1,118 @@
+/*
+ * linux/fs/hfsplus/export.c
+ *
+ * Copyright (C) 2001
+ * Brad Boyer (flar@allandria.com)
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
+ * (C) 2008 Diego E. Pettenò <flameeyes@gmail.com>
+ *
+ * Export for NFS
+ */
+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/exportfs.h>
+
+#include "hfsplus_fs.h"
+#include "hfsplus_raw.h"
+
+/*
+ * This is very different from most get_parent functions, since HFS+
+ * does not have a ".." entry on their directories.
+ *
+ * Instead, the filesystem uses Catalog Thread Records to connect
+ * directories and files to their ancestors.
+ */
+static struct dentry *hfsplus_get_parent(struct dentry *child)
+{
+ struct super_block *sb;
+ hfsplus_cat_entry entry;
+ struct hfs_find_data fd;
+ struct inode *inode;
+ int err;
+
+ sb = child->d_sb;
+
+ hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd);
+ hfsplus_cat_build_key(sb, fd.search_key, child->d_inode->i_ino, NULL);
+ err = hfs_brec_find(&fd);
+
+ if (err) {
+ printk(KERN_ERR "hfs: unable to find child, call the police\n");
+ goto out;
+ }
+
+ hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, fd.entrylength);
+ if ( be16_to_cpu(entry.type) != HFSPLUS_FOLDER_THREAD) {
+ printk(KERN_ERR "hfs: bad catalog folder thread\n");
+ err = -EIO;
+ goto out;
+ }
+
+ if (fd.entrylength < HFSPLUS_MIN_THREAD_SZ) {
+ printk(KERN_ERR "hfs: truncated catalog thread\n");
+ err = -EIO;
+ goto out;
+ }
+
+ hfs_find_exit(&fd);
+
+ inode = hfsplus_iget(child->d_sb, be32_to_cpu(entry.thread.parentID));
+ if (IS_ERR(inode)) {
+ printk(KERN_ERR "hfs: unable to find parent, call the social services\n");
+ return ERR_CAST(inode);
+ }
+
+ return d_obtain_alias(inode);
+
+out:
+ hfs_find_exit(&fd);
+ return ERR_PTR(err);
+}
+
+static struct inode *hfsplus_export_get_inode(struct super_block *sb,
+ u64 ino, u32 generation)
+{
+ struct inode *inode;
+
+ if (ino < HFSPLUS_FIRSTUSER_CNID && ino != HFSPLUS_ROOT_CNID)
+ return ERR_PTR(-ESTALE);
+
+ inode = hfsplus_iget(sb, ino);
+ if (IS_ERR(inode))
+ return ERR_CAST(inode);
+
+ /* probably superfluous but it does not seem to hurt */
+ if (generation && inode->i_generation != generation) {
+ /* we didn't find the right inode.. */
+ iput(inode);
+ return ERR_PTR(-ESTALE);
+ }
+ return inode;
+}
+
+static struct dentry *hfsplus_fh_to_dentry(struct super_block *sb, struct fid *fid,
+ int fh_len, int fh_type)
+
+{
+ return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
+ hfsplus_export_get_inode);
+}
+
+static struct dentry *hfsplus_fh_to_parent(struct super_block *sb, struct fid *fid,
+ int fh_len, int fh_type)
+
+{
+ return generic_fh_to_parent(sb, fid, fh_len, fh_type,
+ hfsplus_export_get_inode);
+}
+
+/* Yes, most of these are left as NULL!!
+ * A NULL value implies the default, which works with hfs+-like file
+ * systems, but can be improved upon.
+ */
+const struct export_operations hfsplus_export_ops = {
+ .get_parent = hfsplus_get_parent,
+ .fh_to_dentry = hfsplus_fh_to_dentry,
+ .fh_to_parent = hfsplus_fh_to_parent,
+};
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index f027a90..7c78525 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -371,6 +371,9 @@ int hfsplus_read_wrapper(struct super_block *);

int hfs_part_find(struct super_block *, sector_t *, sector_t *);

+/* export.c */
+extern const struct export_operations hfsplus_export_ops;
+
/* access macros */
/*
static inline struct hfsplus_sb_info *HFSPLUS_SB(struct super_block *sb)
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index eb74531..b5d1153 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -345,6 +345,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)

/* Set up operations so we can load metadata */
sb->s_op = &hfsplus_sops;
+ sb->s_export_op = &hfsplus_export_ops;
sb->s_maxbytes = MAX_LFS_FILESIZE;

if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) {
--
1.6.0.6

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 197 bytes --]