linux-api.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* RFC: renameat(): Add a RENAME_REMOVE flag to unlink hardlinks
@ 2014-11-21 14:17 Pádraig Brady
       [not found] ` <546F4981.8080907-V8g9lnOeT5ydJdNcDFJN0w@public.gmane.org>
  0 siblings, 1 reply; 15+ messages in thread
From: Pádraig Brady @ 2014-11-21 14:17 UTC (permalink / raw)
  To: Linux API

[-- Attachment #1: Type: text/plain, Size: 438 bytes --]

If 'a' and 'b' are hardlinks, then the command `mv a b & mv b a`
can result in both being removed as mv needs to emulate the
move with an unlink of the source file.  This can only be done
without races in the kernel and so mv was recently changed
to not allow this operation at all.  mv could safely reintroduce
this feature by leveraging a new flag for renameat() for which
an illustrative/untested patch is attached.

thanks,
Pádraig.

[-- Attachment #2: renameat_REMOVE.patch --]
[-- Type: text/x-patch, Size: 2618 bytes --]

>From 26d552617b00b3ffcd3b4646467cab5cb02f33ad Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C3=A1draig=20Brady?= <P@draigBrady.com>
Date: Fri, 21 Nov 2014 14:09:54 +0000
Subject: [PATCH] renameat: Add RENAME_REMOVE flag to unlink source if hardlink
 to dest

This operation can't be done in userspace with unlink without races,
as overlapping rename operations could remove both hardlinks.
---
 Documentation/filesystems/vfs.txt |  1 +
 fs/namei.c                        | 11 +++++++----
 include/uapi/linux/fs.h           |  1 +
 3 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index 20bf204..2daa41a 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -430,6 +430,7 @@ otherwise noted.
 	(2) RENAME_EXCHANGE: exchange source and target.  Both must
 	exist; this is checked by the VFS.  Unlike plain rename,
 	source and target may be of different type.
+	(4) RENAME_REMOVE: unlink source even if a hardlink to dest.
 
   readlink: called by the readlink(2) system call. Only required if
 	you want to support reading symbolic links
diff --git a/fs/namei.c b/fs/namei.c
index db5fe86..caed596 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -4074,8 +4074,10 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 	bool new_is_dir = false;
 	unsigned max_links = new_dir->i_sb->s_max_links;
 
-	if (source == target)
-		return 0;
+	if (source == target) {
+		if (old_dentry == new_dentry || !(flags & RENAME_REMOVE))
+			return 0;
+        }
 
 	error = may_delete(old_dir, old_dentry, is_dir);
 	if (error)
@@ -4210,10 +4212,11 @@ SYSCALL_DEFINE5(renameat2, int, olddfd, const char __user *, oldname,
 	bool should_retry = false;
 	int error;
 
-	if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT))
+	if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE |
+		      RENAME_WHITEOUT | RENAME_REMOVE))
 		return -EINVAL;
 
-	if ((flags & (RENAME_NOREPLACE | RENAME_WHITEOUT)) &&
+	if ((flags & (RENAME_NOREPLACE | RENAME_WHITEOUT | RENAME_REMOVE)) &&
 	    (flags & RENAME_EXCHANGE))
 		return -EINVAL;
 
diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h
index 3735fa0..601d901 100644
--- a/include/uapi/linux/fs.h
+++ b/include/uapi/linux/fs.h
@@ -38,6 +38,7 @@
 #define RENAME_NOREPLACE	(1 << 0)	/* Don't overwrite target */
 #define RENAME_EXCHANGE		(1 << 1)	/* Exchange source and dest */
 #define RENAME_WHITEOUT		(1 << 2)	/* Whiteout source */
+#define RENAME_REMOVE		(1 << 3)	/* Remove source hardlink */
 
 struct fstrim_range {
 	__u64 start;
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2014-11-22  1:57 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-11-21 14:17 RFC: renameat(): Add a RENAME_REMOVE flag to unlink hardlinks Pádraig Brady
     [not found] ` <546F4981.8080907-V8g9lnOeT5ydJdNcDFJN0w@public.gmane.org>
2014-11-21 18:09   ` Andy Lutomirski
     [not found]     ` <CALCETrXvVxvG+s39v+NMdvfkeb8YjbYjb6UXgDFg5ifYOjeKsA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2014-11-21 18:39       ` Pádraig Brady
2014-11-21 19:55         ` Andy Lutomirski
2014-11-21 20:48           ` Pádraig Brady
2014-11-21 21:18             ` Eric Blake
     [not found]               ` <546FAC18.5020200-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2014-11-21 21:29                 ` Andy Lutomirski
     [not found]                   ` <CALCETrUByDgug68FP=cnj-iwSXvbEEHp=S4a=WhQPFmuKc2pNw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2014-11-21 22:20                     ` Pádraig Brady
     [not found]                       ` <546FBAC6.6020407-V8g9lnOeT5ydJdNcDFJN0w@public.gmane.org>
2014-11-21 22:30                         ` Al Viro
2014-11-21 22:40                           ` Andy Lutomirski
     [not found]                             ` <CALCETrW0c1UzkVQgEE_je5BtVhdWRmNaYk4HCQk+t6AWvpC-FA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2014-11-22  1:29                               ` Pádraig Brady
     [not found]                                 ` <546FE6E1.7040703-V8g9lnOeT5ydJdNcDFJN0w@public.gmane.org>
2014-11-22  1:31                                   ` Andy Lutomirski
2014-11-22  1:50                                   ` Al Viro
     [not found]                                     ` <20141122015010.GW7996-3bDd1+5oDREiFSDQTTA3OLVCufUGDwFn@public.gmane.org>
2014-11-22  1:51                                       ` Andy Lutomirski
2014-11-22  1:57                                         ` Al Viro

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).