[Ocfs2-devel] [RFC] The reflink(2) system call v4.

Joel Becker Joel.Becker at oracle.com
Fri May 15 13:53:35 PDT 2009


On Fri, May 15, 2009 at 09:42:09AM -0700, Joel Becker wrote:
> On Fri, May 15, 2009 at 11:55:25AM -0400, Stephen Smalley wrote:
> > Consider a program that wants to always preserve attributes on the
> > reflinks it creates.  If the interface allows the program to explicitly
> > request that behavior and returns an error when the request cannot be
> > honored, then the program knows that upon a successful return, the
> > attributes were in fact preserved.  If the interface instead silently
> > selects a behavior based on the current privileges of the process and
> > gives no indication to the caller as to what behavior was selected, then
> > the opportunity for error is great.
> 
> 	I get that.  I'm looking at what the programming interface is.
> What's the standard function for "I want the fallback behavior" called?
> What's the standard function for "I want preserve security" called?
> "int reflink(oldpath, newpath)" has to pick one of the behaviors.  Which
> is it?

	Ok, I've been casting about how to solve the concern and provide
a decent interface.  I'm not about to give up on either.  I think,
though, that we do have to let the application signal its intent to the
system.  And if we're doing that, let's add a little flexibility.
	I think the interface will be this (ignoring the reflinkat(2)
bit for now):

int reflink(const char *oldpath, const char *newpath, int preserve);

- Data and xattrs are reflinked always.
- 'preserve is a bitfield describing which attributes to keep across the
  reflink:
 * REFLINK_ATTR_OWNER - Keeps uid/gid the same.  Requires ownership or
   CAP_CHOWN.
 * REFLINK_ATTR_SECURITY - Keeps the security state (SELinux/SMACK/etc)
   the same.  This requires REFLINK_ATTR_OWNER (the security state makes
   no sense if the ownership changes).  If not set, the filesystem wipes
   all security.* xattrs and reinitializes with
   security_inode_init_security() just like a new file.
 * REFLINK_ATTR_MODE - Keeps the mode bits the same.  Requires ownership
   or CAP_FOWNER.
 * REFLINK_ATTR_ACL - Keeps the ACLs the same.  Requires
   REFLINK_ATTR_MODE, as ACLs have to get adjusted when the mode
   changes, and so you can't keep them the same if the mode wasn't
   preserved.  If not set, the filesystem reinits the ACLs as for a new
   file.
- REFLINK_ATTR_NONE is 0 and REFLINK_ATTR_ALL is ~0.

	That's all the relevant attributes.  The timestamps behave as
already described (ctime is now, mtime matches the source), which is the
only sane behavior for this sort of thing.
	So, a copy program would reflink(source, target,
REFLINK_ATTR_NONE), a snapshot program would reflink(source, target,
REFLINK_ATTR_ALL), and someone wanting the fallback behavior can do it
easily.
	In the kernel, security_inode_reflink() gets passed the preserve
bits.  It's responsible for determining whether REFLINK_ATTR_SECURITY is
allowed (vfs_reflink() will already have asserted REFLINK_ATTR_OWNER).
It may do other checks on the reflink and the preserve bits, that's up
to the LSM.
        For scripting, we add the we add the '-p' and '-P' to "ln -r":

- ln -r == reflink(source, target, REFLINK_ATTR_NONE);
- ln -r -P == reflink(source, target, REFLINK_ATTR_ALL);
- ln -r -p == the fallback behavior.  This is like cp(1), where "cp -p"
  is best-effort.

	Does this make everyone happy?
Joel

-- 

"In the beginning, the universe was created. This has made a lot 
 of people very angry, and is generally considered to have been a 
 bad move."
        - Douglas Adams

Joel Becker
Principal Software Developer
Oracle
E-mail: joel.becker at oracle.com
Phone: (650) 506-8127



More information about the Ocfs2-devel mailing list