mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 10:37:35 +03:00
zfs_rename: support RENAME_* flags
Implement support for Linux's RENAME_* flags (for renameat2). Aside from being quite useful for userspace (providing race-free ways to exchange paths and implement mv --no-clobber), they are used by overlayfs and are thus required in order to use overlayfs-on-ZFS. In order for us to represent the new renameat2(2) flags in the ZIL, we create two new transaction types for the two flags which need transactional-level support (RENAME_EXCHANGE and RENAME_WHITEOUT). RENAME_NOREPLACE does not need any ZIL support because we know that if the operation succeeded before creating the ZIL entry, there was no file to be clobbered and thus it can be treated as a regular TX_RENAME. Reviewed-by: Ryan Moeller <ryan@iXsystems.com> Reviewed-by: Alexander Motin <mav@FreeBSD.org> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Pavel Snajdr <snajpa@snajpa.net> Signed-off-by: Aleksa Sarai <cyphar@cyphar.com> Closes #12209 Closes #14070
This commit is contained in:
committed by
Brian Behlendorf
parent
e015d6cc0b
commit
dbf6108b4d
@@ -41,7 +41,8 @@ extern int zfs_rmdir(znode_t *dzp, const char *name, znode_t *cwd,
|
||||
extern int zfs_setattr(znode_t *zp, vattr_t *vap, int flag, cred_t *cr,
|
||||
zuserns_t *mnt_ns);
|
||||
extern int zfs_rename(znode_t *sdzp, const char *snm, znode_t *tdzp,
|
||||
const char *tnm, cred_t *cr, int flags, zuserns_t *mnt_ns);
|
||||
const char *tnm, cred_t *cr, int flags, uint64_t rflags, vattr_t *wo_vap,
|
||||
zuserns_t *mnt_ns);
|
||||
extern int zfs_symlink(znode_t *dzp, const char *name, vattr_t *vap,
|
||||
const char *link, znode_t **zpp, cred_t *cr, int flags, zuserns_t *mnt_ns);
|
||||
extern int zfs_link(znode_t *tdzp, znode_t *sp,
|
||||
|
||||
@@ -324,6 +324,19 @@ static inline void zfs_gid_write(struct inode *ip, gid_t gid)
|
||||
ip->i_gid = make_kgid(kcred->user_ns, gid);
|
||||
}
|
||||
|
||||
/*
|
||||
* 3.15 API change
|
||||
*/
|
||||
#ifndef RENAME_NOREPLACE
|
||||
#define RENAME_NOREPLACE (1 << 0) /* Don't overwrite target */
|
||||
#endif
|
||||
#ifndef RENAME_EXCHANGE
|
||||
#define RENAME_EXCHANGE (1 << 1) /* Exchange source and dest */
|
||||
#endif
|
||||
#ifndef RENAME_WHITEOUT
|
||||
#define RENAME_WHITEOUT (1 << 2) /* Whiteout source */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 4.9 API change
|
||||
*/
|
||||
|
||||
@@ -120,6 +120,16 @@ extern uint32_t zone_get_hostid(void *zone);
|
||||
extern void spl_setup(void);
|
||||
extern void spl_cleanup(void);
|
||||
|
||||
/*
|
||||
* Only handles the first 4096 majors and first 256 minors. We don't have a
|
||||
* libc for the kernel module so we define this inline.
|
||||
*/
|
||||
static inline dev_t
|
||||
makedev(unsigned int major, unsigned int minor)
|
||||
{
|
||||
return ((major & 0xFFF) << 8) | (minor & 0xFF);
|
||||
}
|
||||
|
||||
#define highbit(x) __fls(x)
|
||||
#define lowbit(x) __ffs(x)
|
||||
|
||||
|
||||
@@ -61,7 +61,8 @@ extern int zfs_getattr_fast(struct user_namespace *, struct inode *ip,
|
||||
extern int zfs_setattr(znode_t *zp, vattr_t *vap, int flag, cred_t *cr,
|
||||
zuserns_t *mnt_ns);
|
||||
extern int zfs_rename(znode_t *sdzp, char *snm, znode_t *tdzp,
|
||||
char *tnm, cred_t *cr, int flags, zuserns_t *mnt_ns);
|
||||
char *tnm, cred_t *cr, int flags, uint64_t rflags, vattr_t *wo_vap,
|
||||
zuserns_t *mnt_ns);
|
||||
extern int zfs_symlink(znode_t *dzp, char *name, vattr_t *vap,
|
||||
char *link, znode_t **zpp, cred_t *cr, int flags, zuserns_t *mnt_ns);
|
||||
extern int zfs_readlink(struct inode *ip, zfs_uio_t *uio, cred_t *cr);
|
||||
|
||||
@@ -42,7 +42,11 @@ extern void zpl_vap_init(vattr_t *vap, struct inode *dir,
|
||||
umode_t mode, cred_t *cr, zuserns_t *mnt_ns);
|
||||
|
||||
extern const struct inode_operations zpl_inode_operations;
|
||||
#ifdef HAVE_RENAME2_OPERATIONS_WRAPPER
|
||||
extern const struct inode_operations_wrapper zpl_dir_inode_operations;
|
||||
#else
|
||||
extern const struct inode_operations zpl_dir_inode_operations;
|
||||
#endif
|
||||
extern const struct inode_operations zpl_symlink_inode_operations;
|
||||
extern const struct inode_operations zpl_special_inode_operations;
|
||||
|
||||
|
||||
@@ -299,6 +299,12 @@ extern void zfs_log_symlink(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
|
||||
extern void zfs_log_rename(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
|
||||
znode_t *sdzp, const char *sname, znode_t *tdzp, const char *dname,
|
||||
znode_t *szp);
|
||||
extern void zfs_log_rename_exchange(zilog_t *zilog, dmu_tx_t *tx,
|
||||
uint64_t txtype, znode_t *sdzp, const char *sname, znode_t *tdzp,
|
||||
const char *dname, znode_t *szp);
|
||||
extern void zfs_log_rename_whiteout(zilog_t *zilog, dmu_tx_t *tx,
|
||||
uint64_t txtype, znode_t *sdzp, const char *sname, znode_t *tdzp,
|
||||
const char *dname, znode_t *szp, znode_t *wzp);
|
||||
extern void zfs_log_write(zilog_t *zilog, dmu_tx_t *tx, int txtype,
|
||||
znode_t *zp, offset_t off, ssize_t len, int ioflag,
|
||||
zil_callback_t callback, void *callback_data);
|
||||
|
||||
+16
-1
@@ -164,7 +164,9 @@ typedef enum zil_create {
|
||||
#define TX_MKDIR_ACL_ATTR 19 /* mkdir with ACL + attrs */
|
||||
#define TX_WRITE2 20 /* dmu_sync EALREADY write */
|
||||
#define TX_SETSAXATTR 21 /* Set sa xattrs on file */
|
||||
#define TX_MAX_TYPE 22 /* Max transaction type */
|
||||
#define TX_RENAME_EXCHANGE 22 /* Atomic swap via renameat2 */
|
||||
#define TX_RENAME_WHITEOUT 23 /* Atomic whiteout via renameat2 */
|
||||
#define TX_MAX_TYPE 24 /* Max transaction type */
|
||||
|
||||
/*
|
||||
* The transactions for mkdir, symlink, remove, rmdir, link, and rename
|
||||
@@ -317,6 +319,19 @@ typedef struct {
|
||||
/* 2 strings: names of source and destination follow this */
|
||||
} lr_rename_t;
|
||||
|
||||
typedef struct {
|
||||
lr_rename_t lr_rename; /* common rename portion */
|
||||
/* members related to the whiteout file (based on lr_create_t) */
|
||||
uint64_t lr_wfoid; /* obj id of the new whiteout file */
|
||||
uint64_t lr_wmode; /* mode of object */
|
||||
uint64_t lr_wuid; /* uid of whiteout */
|
||||
uint64_t lr_wgid; /* gid of whiteout */
|
||||
uint64_t lr_wgen; /* generation (txg of creation) */
|
||||
uint64_t lr_wcrtime[2]; /* creation time */
|
||||
uint64_t lr_wrdev; /* always makedev(0, 0) */
|
||||
/* 2 strings: names of source and destination follow this */
|
||||
} lr_rename_whiteout_t;
|
||||
|
||||
typedef struct {
|
||||
lr_t lr_common; /* common portion of log record */
|
||||
uint64_t lr_foid; /* file object to write */
|
||||
|
||||
Reference in New Issue
Block a user