Commit 5bb71622 authored by J. R. Okajima's avatar J. R. Okajima
Browse files

aufs: hfsplus branch



Special support for filesystems which acquires an inode mutex at final
closing a file, eg, hfsplus.
This trick is very simple and stupid, just to open the file before really
necessary open to tell hfsplus that this is not the final closing.
The caller should call au_h_open_pre() after acquiring the inode mutex,
and au_h_open_post() after releasing it.
Signed-off-by: default avatarJ. R. Okajima <hooanon05g@gmail.com>
parent 44720530
...@@ -138,6 +138,15 @@ config AUFS_SHWH ...@@ -138,6 +138,15 @@ config AUFS_SHWH
sounds like philosophy or something, but in technically it sounds like philosophy or something, but in technically it
simply shows the name of whiteout with keeping its behaviour. simply shows the name of whiteout with keeping its behaviour.
config AUFS_BR_HFSPLUS
bool "Hfsplus as an aufs branch"
depends on HFSPLUS_FS
default y
help
If you want to use hfsplus fs as an aufs branch fs, then enable
this option. This option introduces a small overhead at
copying-up a file on hfsplus.
config AUFS_BDEV_LOOP config AUFS_BDEV_LOOP
bool bool
depends on BLK_DEV_LOOP depends on BLK_DEV_LOOP
......
...@@ -33,5 +33,6 @@ aufs-$(CONFIG_FS_POSIX_ACL) += posix_acl.o ...@@ -33,5 +33,6 @@ aufs-$(CONFIG_FS_POSIX_ACL) += posix_acl.o
aufs-$(CONFIG_AUFS_DIRREN) += dirren.o aufs-$(CONFIG_AUFS_DIRREN) += dirren.o
aufs-$(CONFIG_AUFS_FHSM) += fhsm.o aufs-$(CONFIG_AUFS_FHSM) += fhsm.o
aufs-$(CONFIG_AUFS_RDU) += rdu.o aufs-$(CONFIG_AUFS_RDU) += rdu.o
aufs-$(CONFIG_AUFS_BR_HFSPLUS) += hfsplus.o
aufs-$(CONFIG_AUFS_DEBUG) += debug.o aufs-$(CONFIG_AUFS_DEBUG) += debug.o
aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
...@@ -1092,6 +1092,14 @@ static int au_do_sio_cpup_simple(struct au_cp_generic *cpg) ...@@ -1092,6 +1092,14 @@ static int au_do_sio_cpup_simple(struct au_cp_generic *cpg)
dentry = cpg->dentry; dentry = cpg->dentry;
h_file = NULL; h_file = NULL;
if (au_ftest_cpup(cpg->flags, HOPEN)) {
AuDebugOn(cpg->bsrc < 0);
h_file = au_h_open_pre(dentry, cpg->bsrc, /*force_wr*/0);
err = PTR_ERR(h_file);
if (IS_ERR(h_file))
goto out;
}
parent = dget_parent(dentry); parent = dget_parent(dentry);
h_dir = au_h_iptr(d_inode(parent), cpg->bdst); h_dir = au_h_iptr(d_inode(parent), cpg->bdst);
if (!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE) if (!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE)
...@@ -1108,7 +1116,10 @@ static int au_do_sio_cpup_simple(struct au_cp_generic *cpg) ...@@ -1108,7 +1116,10 @@ static int au_do_sio_cpup_simple(struct au_cp_generic *cpg)
} }
dput(parent); dput(parent);
if (h_file)
au_h_open_post(dentry, cpg->bsrc, h_file);
out:
return err; return err;
} }
...@@ -1281,6 +1292,7 @@ int au_sio_cpup_wh(struct au_cp_generic *cpg, struct file *file) ...@@ -1281,6 +1292,7 @@ int au_sio_cpup_wh(struct au_cp_generic *cpg, struct file *file)
au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0); au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0);
inode_lock_nested(h_tmpdir, AuLsc_I_PARENT3); inode_lock_nested(h_tmpdir, AuLsc_I_PARENT3);
/* todo: au_h_open_pre()? */
pin_orig = cpg->pin; pin_orig = cpg->pin;
au_pin_init(&wh_pin, dentry, bdst, AuLsc_DI_PARENT, au_pin_init(&wh_pin, dentry, bdst, AuLsc_DI_PARENT,
...@@ -1304,6 +1316,7 @@ int au_sio_cpup_wh(struct au_cp_generic *cpg, struct file *file) ...@@ -1304,6 +1316,7 @@ int au_sio_cpup_wh(struct au_cp_generic *cpg, struct file *file)
if (h_orph) { if (h_orph) {
inode_unlock(h_tmpdir); inode_unlock(h_tmpdir);
/* todo: au_h_open_post()? */
au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0); au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0);
au_set_h_dptr(parent, bdst, h_parent); au_set_h_dptr(parent, bdst, h_parent);
AuDebugOn(!pin_orig); AuDebugOn(!pin_orig);
......
...@@ -40,11 +40,18 @@ struct au_cp_generic { ...@@ -40,11 +40,18 @@ struct au_cp_generic {
#define AuCpup_KEEPLINO (1 << 1) /* do not clear the lower xino, #define AuCpup_KEEPLINO (1 << 1) /* do not clear the lower xino,
for link(2) */ for link(2) */
#define AuCpup_RENAME (1 << 2) /* rename after cpup */ #define AuCpup_RENAME (1 << 2) /* rename after cpup */
#define AuCpup_HOPEN (1 << 3) /* call h_open_pre/post() in
cpup */
#define AuCpup_OVERWRITE (1 << 4) /* allow overwriting the #define AuCpup_OVERWRITE (1 << 4) /* allow overwriting the
existing entry */ existing entry */
#define AuCpup_RWDST (1 << 5) /* force write target even if #define AuCpup_RWDST (1 << 5) /* force write target even if
the branch is marked as RO */ the branch is marked as RO */
#ifndef CONFIG_AUFS_BR_HFSPLUS
#undef AuCpup_HOPEN
#define AuCpup_HOPEN 0
#endif
#define au_ftest_cpup(flags, name) ((flags) & AuCpup_##name) #define au_ftest_cpup(flags, name) ((flags) & AuCpup_##name)
#define au_fset_cpup(flags, name) \ #define au_fset_cpup(flags, name) \
do { (flags) |= AuCpup_##name; } while (0) do { (flags) |= AuCpup_##name; } while (0)
......
...@@ -106,7 +106,7 @@ static int au_cmoo(struct dentry *dentry) ...@@ -106,7 +106,7 @@ static int au_cmoo(struct dentry *dentry)
.bsrc = -1, .bsrc = -1,
.len = -1, .len = -1,
.pin = &pin, .pin = &pin,
.flags = AuCpup_DTIME .flags = AuCpup_DTIME | AuCpup_HOPEN
}; };
struct inode *delegated; struct inode *delegated;
struct super_block *sb; struct super_block *sb;
...@@ -403,6 +403,7 @@ int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin) ...@@ -403,6 +403,7 @@ int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin)
struct dentry *parent; struct dentry *parent;
struct inode *inode; struct inode *inode;
struct super_block *sb; struct super_block *sb;
struct file *h_file;
struct au_cp_generic cpg = { struct au_cp_generic cpg = {
.dentry = file->f_path.dentry, .dentry = file->f_path.dentry,
.bdst = -1, .bdst = -1,
...@@ -449,12 +450,22 @@ int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin) ...@@ -449,12 +450,22 @@ int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin)
if (dbtop <= cpg.bdst /* just reopen */ if (dbtop <= cpg.bdst /* just reopen */
|| !d_unhashed(cpg.dentry) /* copyup and reopen */ || !d_unhashed(cpg.dentry) /* copyup and reopen */
) { ) {
di_downgrade_lock(parent, AuLock_IR); h_file = au_h_open_pre(cpg.dentry, cpg.bsrc, /*force_wr*/0);
if (dbtop > cpg.bdst) if (IS_ERR(h_file))
err = au_sio_cpup_simple(&cpg); err = PTR_ERR(h_file);
if (!err) else {
err = au_reopen_nondir(file); di_downgrade_lock(parent, AuLock_IR);
if (dbtop > cpg.bdst)
err = au_sio_cpup_simple(&cpg);
if (!err)
err = au_reopen_nondir(file);
au_h_open_post(cpg.dentry, cpg.bsrc, h_file);
}
} else { /* copyup as wh and reopen */ } else { /* copyup as wh and reopen */
/*
* since writable hfsplus branch is not supported,
* h_open_pre/post() are unnecessary.
*/
err = au_ready_to_write_wh(file, len, cpg.bdst, pin); err = au_ready_to_write_wh(file, len, cpg.bdst, pin);
di_downgrade_lock(parent, AuLock_IR); di_downgrade_lock(parent, AuLock_IR);
} }
......
...@@ -78,6 +78,19 @@ int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file), ...@@ -78,6 +78,19 @@ int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
int au_do_flush(struct file *file, fl_owner_t id, int au_do_flush(struct file *file, fl_owner_t id,
int (*flush)(struct file *file, fl_owner_t id)); int (*flush)(struct file *file, fl_owner_t id));
#ifdef CONFIG_AUFS_BR_HFSPLUS
/* hfsplus.c */
struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex,
int force_wr);
void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
struct file *h_file);
#else
AuStub(struct file *, au_h_open_pre, return NULL, struct dentry *dentry,
aufs_bindex_t bindex, int force_wr)
AuStubVoid(au_h_open_post, struct dentry *dentry, aufs_bindex_t bindex,
struct file *h_file);
#endif
/* f_op.c */ /* f_op.c */
extern const struct file_operations aufs_file_fop; extern const struct file_operations aufs_file_fop;
int au_do_open_nondir(struct file *file, int flags, struct file *h_file); int au_do_open_nondir(struct file *file, int flags, struct file *h_file);
......
...@@ -216,6 +216,15 @@ static inline int au_test_nilfs(struct super_block *sb __maybe_unused) ...@@ -216,6 +216,15 @@ static inline int au_test_nilfs(struct super_block *sb __maybe_unused)
#endif #endif
} }
static inline int au_test_hfsplus(struct super_block *sb __maybe_unused)
{
#if IS_ENABLED(CONFIG_HFSPLUS_FS)
return sb->s_magic == HFSPLUS_SUPER_MAGIC;
#else
return 0;
#endif
}
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
/* /*
* they can't be an aufs branch. * they can't be an aufs branch.
...@@ -256,6 +265,7 @@ static inline int au_test_fs_bad_iattr_size(struct super_block *sb) ...@@ -256,6 +265,7 @@ static inline int au_test_fs_bad_iattr_size(struct super_block *sb)
return au_test_xfs(sb) return au_test_xfs(sb)
|| au_test_btrfs(sb) || au_test_btrfs(sb)
|| au_test_ubifs(sb) || au_test_ubifs(sb)
|| au_test_hfsplus(sb) /* maintained, but incorrect */
/* || au_test_minix(sb) */ /* untested */ /* || au_test_minix(sb) */ /* untested */
; ;
} }
...@@ -276,7 +286,8 @@ static inline int au_test_fs_bad_iattr(struct super_block *sb) ...@@ -276,7 +286,8 @@ static inline int au_test_fs_bad_iattr(struct super_block *sb)
static inline int au_test_fs_no_limit_nlink(struct super_block *sb) static inline int au_test_fs_no_limit_nlink(struct super_block *sb)
{ {
return au_test_tmpfs(sb) return au_test_tmpfs(sb)
|| au_test_ubifs(sb); || au_test_ubifs(sb)
|| au_test_hfsplus(sb);
} }
/* /*
......
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2010-2019 Junjiro R. Okajima
*/
/*
* special support for filesystems which acquires an inode mutex
* at final closing a file, eg, hfsplus.
*
* This trick is very simple and stupid, just to open the file before really
* necessary open to tell hfsplus that this is not the final closing.
* The caller should call au_h_open_pre() after acquiring the inode mutex,
* and au_h_open_post() after releasing it.
*/
#include "aufs.h"
struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex,
int force_wr)
{
struct file *h_file;
struct dentry *h_dentry;
h_dentry = au_h_dptr(dentry, bindex);
AuDebugOn(!h_dentry);
AuDebugOn(d_is_negative(h_dentry));
h_file = NULL;
if (au_test_hfsplus(h_dentry->d_sb)
&& d_is_reg(h_dentry))
h_file = au_h_open(dentry, bindex,
O_RDONLY | O_NOATIME | O_LARGEFILE,
/*file*/NULL, force_wr);
return h_file;
}
void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
struct file *h_file)
{
struct au_branch *br;
if (h_file) {
fput(h_file);
br = au_sbr(dentry->d_sb, bindex);
au_lcnt_dec(&br->br_nfiles);
}
}
...@@ -894,7 +894,7 @@ int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia, ...@@ -894,7 +894,7 @@ int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia,
.bsrc = btop, .bsrc = btop,
.len = sz, .len = sz,
.pin = &a->pin, .pin = &a->pin,
.flags = AuCpup_DTIME .flags = AuCpup_DTIME | AuCpup_HOPEN
}; };
err = au_sio_cpup_simple(&cpg); err = au_sio_cpup_simple(&cpg);
if (!err) if (!err)
......
...@@ -522,7 +522,7 @@ static int au_cpup_before_link(struct dentry *src_dentry, ...@@ -522,7 +522,7 @@ static int au_cpup_before_link(struct dentry *src_dentry,
.bsrc = a->bsrc, .bsrc = a->bsrc,
.len = -1, .len = -1,
.pin = &a->pin, .pin = &a->pin,
.flags = AuCpup_DTIME /* | AuCpup_KEEPLINO */ .flags = AuCpup_DTIME | AuCpup_HOPEN /* | AuCpup_KEEPLINO */
}; };
di_read_lock_parent(a->src_parent, AuLock_IR); di_read_lock_parent(a->src_parent, AuLock_IR);
...@@ -554,6 +554,7 @@ static int au_cpup_or_link(struct dentry *src_dentry, struct dentry *dentry, ...@@ -554,6 +554,7 @@ static int au_cpup_or_link(struct dentry *src_dentry, struct dentry *dentry,
struct dentry *h_src_dentry; struct dentry *h_src_dentry;
struct inode *h_inode, *inode, *delegated; struct inode *h_inode, *inode, *delegated;
struct super_block *sb; struct super_block *sb;
struct file *h_file;
plink = 0; plink = 0;
h_inode = NULL; h_inode = NULL;
...@@ -574,7 +575,10 @@ static int au_cpup_or_link(struct dentry *src_dentry, struct dentry *dentry, ...@@ -574,7 +575,10 @@ static int au_cpup_or_link(struct dentry *src_dentry, struct dentry *dentry,
spin_lock(&dentry->d_lock); spin_lock(&dentry->d_lock);
dentry->d_inode = d_inode(src_dentry); /* tmp */ dentry->d_inode = d_inode(src_dentry); /* tmp */
spin_unlock(&dentry->d_lock); spin_unlock(&dentry->d_lock);
{ /* re-commit later */ h_file = au_h_open_pre(dentry, a->bsrc, /*force_wr*/0);
if (IS_ERR(h_file))
err = PTR_ERR(h_file);
else {
struct au_cp_generic cpg = { struct au_cp_generic cpg = {
.dentry = dentry, .dentry = dentry,
.bdst = a->bdst, .bdst = a->bdst,
...@@ -584,6 +588,7 @@ static int au_cpup_or_link(struct dentry *src_dentry, struct dentry *dentry, ...@@ -584,6 +588,7 @@ static int au_cpup_or_link(struct dentry *src_dentry, struct dentry *dentry,
.flags = AuCpup_KEEPLINO .flags = AuCpup_KEEPLINO
}; };
err = au_sio_cpup_simple(&cpg); err = au_sio_cpup_simple(&cpg);
au_h_open_post(dentry, a->bsrc, h_file);
if (!err) { if (!err) {
dput(a->h_path.dentry); dput(a->h_path.dentry);
a->h_path.dentry = au_h_dptr(dentry, a->bdst); a->h_path.dentry = au_h_dptr(dentry, a->bdst);
......
...@@ -1098,7 +1098,7 @@ int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry, ...@@ -1098,7 +1098,7 @@ int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry,
.bsrc = a->src_btop, .bsrc = a->src_btop,
.len = -1, .len = -1,
.pin = &pin, .pin = &pin,
.flags = AuCpup_DTIME .flags = AuCpup_DTIME | AuCpup_HOPEN
}; };
AuDebugOn(au_dbtop(a->src_dentry) != a->src_btop); AuDebugOn(au_dbtop(a->src_dentry) != a->src_btop);
err = au_sio_cpup_simple(&cpg); err = au_sio_cpup_simple(&cpg);
...@@ -1125,7 +1125,7 @@ int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry, ...@@ -1125,7 +1125,7 @@ int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry,
.bsrc = a->dst_btop, .bsrc = a->dst_btop,
.len = -1, .len = -1,
.pin = &pin, .pin = &pin,
.flags = AuCpup_DTIME .flags = AuCpup_DTIME | AuCpup_HOPEN
}; };
err = au_sio_cpup_simple(&cpg); err = au_sio_cpup_simple(&cpg);
au_unpin(&pin); au_unpin(&pin);
......
...@@ -17,3 +17,9 @@ endif ...@@ -17,3 +17,9 @@ endif
ifdef CONFIG_UBIFS_FS ifdef CONFIG_UBIFS_FS
ccflags-y += -DUBIFS_SUPER_MAGIC=0x24051905 ccflags-y += -DUBIFS_SUPER_MAGIC=0x24051905
endif endif
# defined in ${srctree}/fs/hfsplus/hfsplus_raw.h
# tristate
ifdef CONFIG_HFSPLUS_FS
ccflags-y += -DHFSPLUS_SUPER_MAGIC=0x482b
endif
...@@ -210,7 +210,7 @@ static int au_do_cpdown(const unsigned char dmsg, struct au_mvd_args *a) ...@@ -210,7 +210,7 @@ static int au_do_cpdown(const unsigned char dmsg, struct au_mvd_args *a)
.bsrc = a->mvd_bsrc, .bsrc = a->mvd_bsrc,
.len = -1, .len = -1,
.pin = &a->mvd_pin_dst, .pin = &a->mvd_pin_dst,
.flags = AuCpup_DTIME .flags = AuCpup_DTIME | AuCpup_HOPEN
}; };
AuDbg("b%d, b%d\n", cpg.bsrc, cpg.bdst); AuDbg("b%d, b%d\n", cpg.bsrc, cpg.bdst);
......
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