"Vincent Vanackere":
> your patch does not apply... are you sure you made it against your last patch
> ?
So here is a plain, enrire patch. remove all my previous patches and
apply this.
Junjiro Okajima
Index: branchman.c
===================================================================
RCS file: /home/cvs/unionfs/unionfs/branchman.c,v
retrieving revision 1.63
diff -u -p -r1.63 branchman.c
--- branchman.c 2 Jun 2006 03:29:26 -0000 1.63
+++ branchman.c 15 Jun 2006 08:43:21 -0000
@@ -212,6 +212,12 @@ int unionfs_ioctl_addbranch(struct inode
print_entry_location();
+#ifdef UNIONFS_IMAP
+ err = -EPERM;
+ if (stopd(inode->i_sb)->usi_persistent)
+ goto out;
+#endif
+
err = -ENOMEM;
addargs = KMALLOC(sizeof(struct unionfs_addbranch_args), GFP_KERNEL);
if (!addargs)
@@ -380,6 +386,12 @@ int unionfs_ioctl_delbranch(struct super
print_entry("branch = %lu ", arg);
lock_dentry(sb->s_root);
+
+#ifdef UNIONFS_IMAP
+ err = -EPERM;
+ if (stopd(sb)->usi_persistent)
+ goto out;
+#endif
err = -EBUSY;
if (sbmax(sb) == 1)
Index: persistent_inode.c
===================================================================
RCS file: /home/cvs/unionfs/unionfs/persistent_inode.c,v
retrieving revision 1.34
diff -u -p -r1.34 persistent_inode.c
--- persistent_inode.c 21 Feb 2006 08:36:24 -0000 1.34
+++ persistent_inode.c 15 Jun 2006 08:43:21 -0000
@@ -495,8 +495,8 @@ static int __write_uin(struct unionfs_sb
fwd = sbi->usi_forwardmap;
ent.fsnum = sbi->usi_bnum_table[bindex];
- ent.inode = ino;
- pos = fwdhdr + fwd_elmnt * hidden_ino;
+ ent.inode = hidden_ino;
+ pos = fwdhdr + fwd_elmnt * ino;
sz = __fwrite(fwd, &ent, fwd_elmnt, &pos);
err = sz;
if (err < 0)
@@ -553,8 +553,8 @@ int read_uin(struct super_block *sb, uin
/* If we haven't found an entry and we have the O_CREAT flag set we
want to
* create a new entry write it out to the file and return its index
*/
- *uino = spd->usi_next_avail++;
mutex_lock(&sb->s_lock);
+ *uino = spd->usi_next_avail++;
err = __write_uin(spd, *uino, branchnum, inode_number);
if (err)
spd->usi_next_avail--;
@@ -600,14 +600,10 @@ int get_lin(struct super_block *sb, ino_
(sizeof(struct fmapent) * inode_number);
oldfs = get_fs();
set_fs(KERNEL_DS);
- bytesread =
- forwardmap->f_op->read(forwardmap, (char __user *)entry,
- sizeof(struct fmapent), &seek_size);
+ bytesread = __fread(forwardmap, entry, sizeof(*entry), &seek_size);
set_fs(oldfs);
- if (bytesread != sizeof(struct fmapent)) {
- entry = ERR_PTR(-EINVAL);
- goto out;
- }
+ if (bytesread != sizeof(*entry))
+ err = -EINVAL;
out:
print_exit_location();
Index: super.c
===================================================================
RCS file: /home/cvs/unionfs/unionfs/super.c,v
retrieving revision 1.93
diff -u -p -r1.93 super.c
--- super.c 1 Jun 2006 21:25:18 -0000 1.93
+++ super.c 15 Jun 2006 08:43:21 -0000
@@ -488,24 +488,294 @@ static int unionfs_show_options(struct s
return ret;
}
-/**
- * The entry given by dentry here is always a directory.
- * We can't just do dentry->d_parent, because it may
- * not be there, since this dentry could have been
- * created by calling d_alloc_anon.
- */
+/* export operations. unionfs cannot handle disconnected dentry,
+ * since it has no hidden dentries. */
+/* un-tested 64 bit inode number */
+
+#define is_anon(d) ((d)->d_flags & DCACHE_DISCONNECTED)
+extern struct export_operations export_op_default;
+
+static void anon_dput(struct dentry *d)
+{
+ if (is_anon(d))
+ d_drop(d);
+ DPUT(d);
+}
+
static struct dentry *unionfs_get_parent(struct dentry *dentry)
{
+ if (!is_anon(dentry)) {
+ struct dentry *p;
+ lock_dentry(dentry);
+ p = GET_PARENT(dentry);
+ unlock_dentry(dentry);
+ return p;
+ }
+ d_drop(dentry);
+ return ERR_PTR(-ESTALE);
+}
- struct dentry *ret;
- struct inode *childinode;
- childinode = dentry->d_inode;
- ret = d_find_alias(childinode);
- return ret;
+static void prepend_path(char **path, const char *name, int len)
+{
+ *path -= len;
+ memcpy(*path, name, len);
+ (*path)--;
+ **path = '/';
+}
+
+struct filldir_arg {
+ int found, called;
+ char *path;
+ ino_t ino, parent_ino;
+};
+
+static int filldir(void *arg, const char *name, int len, loff_t pos, ino_t ino,
+ unsigned int d_type)
+{
+ struct filldir_arg *a = arg;
+
+ a->called++;
+ if (!strcmp(name, "..")) {
+ a->parent_ino = ino;
+ a->found++;
+ } else if (ino == a->ino) {
+ if (strcmp(name, "."))
+ prepend_path(&a->path, name, len);
+ a->found++;
+ }
+ return (a->found == 2)?1:0;
+}
+
+static struct dentry *do_get_dentry(struct super_block *sb, int bindex, int
gen,
+ struct dentry *hidden_root,
+ ino_t hidden_ino, ino_t hidden_parent_ino)
+{
+ struct dentry *dentry, *hidden_parent, *parent;
+ char *path, *p;
+ struct filldir_arg arg = {
+ .ino = hidden_ino,
+ .parent_ino = hidden_parent_ino};
+ int open_flags, err;
+ struct inode *hidden_dir;
+ struct file *hidden_file;
+ struct super_block *hidden_sb;
+
+ print_entry("b%d, g%d, hi%lu, hpi%lu\n",
+ bindex, gen, hidden_ino, hidden_parent_ino);
+
+ dentry = ERR_PTR(-ENOMEM);
+ path = __getname();
+ if (!path)
+ goto out;
+ arg.path = path+PATH_MAX;
+ *arg.path-- = 0;
+
+ open_flags = O_RDONLY | O_DIRECTORY /* | O_NOATIME */ ;
+ if (force_o_largefile())
+ open_flags |= O_LARGEFILE;
+
+ unionfs_read_lock(sb);
+ dentry = ERR_PTR(-ESTALE);
+#if 0
+ if (gen != atomic_read(&stopd(sb)->usi_generation))
+ goto out_unlock;
+#endif
+ lock_dentry(sb->s_root);
+ if (hidden_root != dtohd_index(sb->s_root, bindex)) {
+ unlock_dentry(sb->s_root);
+ goto out_unlock;
+#if 0
+ int bend = dbend(sb->s_root), found = -1;
+ for (bindex = 0; found == -1 && bindex <= bend; bindex++)
+ if (hidden_root == dtohd_index(sb->s_root, bindex))
+ found = bindex;
+ if (found == -1) {
+ unlock_dentry(sb->s_root);
+ goto out_unlock;
+ }
+ hidden_root = dtohd_index(sb->s_root, bindex);
+#endif
+ }
+ unlock_dentry(sb->s_root);
+ hidden_sb = stohs_index(sb, bindex);
+
+ while (1) {
+ dentry = ERR_PTR(-ENOMEM);
+ hidden_dir = iget(hidden_sb, hidden_parent_ino);
+ if (!hidden_dir)
+ goto out_unlock;
+ dentry = (void*)hidden_dir;
+ if (IS_ERR(hidden_dir))
+ goto out_unlock;
+ dentry = ERR_PTR(-ESTALE);
+ if (is_bad_inode(hidden_dir))
+ goto out_unlock;
+
+ dentry = ERR_PTR(-ENOMEM);
+ hidden_parent = d_alloc_anon(hidden_dir);
+ if (!hidden_parent)
+ goto out_unlock;
+ dentry = hidden_parent;
+ if (IS_ERR(hidden_parent))
+ goto out_unlock;
+
+ hidden_file = DENTRY_OPEN(DGET(hidden_parent), NULL,
+ open_flags);
+ dentry = (void*)hidden_file;
+ if (IS_ERR(hidden_file)) {
+ anon_dput(hidden_parent);
+ goto out_unlock;
+ }
+
+ arg.found = 0;
+ while (arg.found != 2) {
+ arg.called = 0;
+ err = vfs_readdir(hidden_file, filldir, &arg);
+ if (!arg.called || err < 0)
+ break;
+ }
+ fput(hidden_file);
+ dentry = ERR_PTR(-ESTALE);
+ if (arg.found != 2) {
+ anon_dput(hidden_parent);
+ goto out_unlock;
+ }
+ if (!is_anon(hidden_parent)) {
+ struct dentry *hp = hidden_parent;
+ while (hp != hidden_root) {
+ struct qstr *p = &hp->d_name;
+ prepend_path(&arg.path, p->name, p->len);
+ hp = hp->d_parent;
+ BUG_ON(is_anon(hp));
+ }
+ hidden_parent_ino = hp->d_inode->i_ino;
+ }
+ anon_dput(hidden_parent);
+ if (hidden_parent_ino == hidden_root->d_inode->i_ino)
+ break;
+ arg.ino = hidden_parent_ino;
+ hidden_parent_ino = arg.parent_ino;
+ };
+
+ parent = DGET(sb->s_root);
+ p = strchr(++arg.path, '/');
+ while (p) {
+ mutex_lock(&parent->d_inode->i_mutex);
+ dentry = LOOKUP_ONE_LEN(arg.path, parent, p-arg.path);
+ mutex_unlock(&parent->d_inode->i_mutex);
+ DPUT(parent);
+ if (IS_ERR(dentry))
+ goto out_unlock;
+ if (!dentry->d_inode || !S_ISDIR(dentry->d_inode->i_mode)) {
+ DPUT(dentry);
+ dentry = ERR_PTR(-ESTALE);
+ goto out_unlock;
+ }
+ parent = dentry;
+ arg.path = p+1;
+ p = strchr(arg.path, '/');
+ }
+ mutex_lock(&parent->d_inode->i_mutex);
+ dentry = LOOKUP_ONE_LEN(arg.path, parent, strlen(arg.path));
+ mutex_unlock(&parent->d_inode->i_mutex);
+ DPUT(parent);
+ if (!IS_ERR(dentry) && !dentry->d_inode) {
+ DPUT(dentry);
+ dentry = ERR_PTR(-ESTALE);
+ }
+
+ out_unlock:
+ unionfs_read_unlock(sb);
+ __putname(path);
+ out:
+ print_exit_pointer(dentry);
+ return dentry;
+}
+
+enum {FhHead = 4, FhGen = FhHead, FhBindex,
+ FhHRoot1, FhHRoot2,
+ FhHIno1, FhHIno2, FhHPIno1, FhHPIno2, FhTail};
+
+static struct dentry *unionfs_get_dentry(struct super_block *sb, void *vobjp)
+{
+ struct dentry *dentry, *hidden_root;
+ __u32 *fh = vobjp;
+ ino_t hidden_ino, hidden_parent_ino;
+
+ print_entry("{i%u, %d, b%d, hi%u, hpi%u}\n",
+ fh[0], fh[FhGen], fh[FhBindex], fh[FhHIno1], fh[FhHPIno1]);
+
+ dentry = export_op_default.get_dentry(sb, vobjp);
+ if (!dentry || IS_ERR(dentry) || (dentry->d_inode && !is_anon(dentry)))
+ return dentry;
+
+ anon_dput(dentry);
+
+ hidden_root = (void*)fh[FhHRoot2];
+ hidden_ino = fh[FhHIno2];
+ hidden_parent_ino = fh[FhHPIno2];
+#if BITS_PER_LONG == 64
+ hidden_root |= fh[FhHRoot1] << 32;
+ hidden_ino |= fh[FhHIno1] << 32;
+ hidden_parent_ino |= fh[FhHPIno1] << 32;
+#elif BITS_PER_LONG == 32
+#else
+#error unknown size
+#endif
+ return do_get_dentry(sb, fh[FhBindex], fh[FhGen], hidden_root,
+ hidden_ino, hidden_parent_ino);
+}
+
+static int unionfs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
+ int connectable)
+{
+ int type, len, bindex;
+ struct super_block *sb;
+ struct dentry *h_root;
+ ino_t h_ino, hp_ino;
+
+ BUG_ON(is_anon(dentry) || is_anon(dentry->d_parent));
+ sb = dentry->d_sb;
+ unionfs_read_lock(sb);
+ lock_dentry(dentry);
+
+ len = *max_len;
+ type = export_op_default.encode_fh(dentry, fh, max_len, connectable);
+ if (type == 255 || *max_len > FhHead || len < FhTail) {
+ type = 255;
+ goto out;
+ }
+
+ *max_len = FhTail;
+ fh[FhGen] = atomic_read(&stopd(sb)->usi_generation);
+ fh[FhBindex] = bindex = dbstart(dentry); // pseudo hardlink??
+ lock_dentry(sb->s_root);
+ h_root = dtohd_index(sb->s_root, bindex);
+ unlock_dentry(sb->s_root);
+ h_ino = itohi_index(dentry->d_inode, bindex)->i_ino;
+ hp_ino = parent_ino(dtohd(dentry));
+ fh[FhHRoot2] = (__u32)h_root;
+ fh[FhHIno2] = h_ino;
+ fh[FhHPIno2] = hp_ino;
+#if BITS_PER_LONG == 64
+ fh[FhHRoot1] = h_root >> 32;
+ fh[FhHIno1] = h_ino >> 32;
+ fh[FhHPIno1] = hp_ino >> 32;
+#elif BITS_PER_LONG == 32
+#else
+#error unknown size
+#endif
+
+ out:
+ unlock_dentry(dentry);
+ unionfs_read_unlock(sb);
+ return type;
}
struct export_operations unionfs_export_ops = {
- .get_parent = unionfs_get_parent
+ .encode_fh = unionfs_encode_fh,
+ .get_parent = unionfs_get_parent,
+ .get_dentry = unionfs_get_dentry
};
struct super_operations unionfs_sops = {
_______________________________________________
unionfs mailing list
[email protected]
http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs