All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/3] xfs: add O_TMPFILE support
@ 2013-12-18  0:22 Zhi Yong Wu
  2013-12-18  0:22 ` [PATCH v2 1/3] xfs: factor prid related codes into xfs_get_initial_prid() Zhi Yong Wu
                   ` (4 more replies)
  0 siblings, 5 replies; 14+ messages in thread
From: Zhi Yong Wu @ 2013-12-18  0:22 UTC (permalink / raw)
  To: xfs; +Cc: Zhi Yong Wu

From: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>

HI, folks

  It's time to post the latest revision out, welcome to any constructive comment, thanks.

  If anyone is interested in playing with it, you can get this patchset from my dev git on github:
  git://github.com/wuzhy/kernel.git xfs_tmpfile

  The patchset was tested against the code snippet from Andy Lutomirski and other test cases:
  http://lwn.net/Articles/562296/
  If you have any other better test cases, please let me know, thanks.

#include <stdio.h>
#include <err.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

#define __O_TMPFILE 020000000
#define O_DIRECTORY 0200000
#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
#define AT_EMPTY_PATH 0x1000

int main(int argc, char **argv)
{
   char buf[128];

   if (argc != 3)
     errx(1, "Usage: flinktest PATH linkat|proc");

   int fd = open(".", O_TMPFILE | O_RDWR, 0600);
   if (fd == -1)
     err(1, "O_TMPFILE");
   else
     printf("fd #: %d\n", fd);

   write(fd, "test", 4);

   if (!strcmp(argv[2], "linkat")) {
     if (linkat(fd, "", AT_FDCWD, argv[1], AT_EMPTY_PATH) != 0)
       err(1, "linkat");
   } else if (!strcmp(argv[2], "proc")) {
     sprintf(buf, "/proc/self/fd/%d", fd);
     if (linkat(AT_FDCWD, buf, AT_FDCWD, argv[1], AT_SYMLINK_FOLLOW) != 0)
       err(1, "linkat");
   } else {
     errx(1, "invalid mode");
   }

   return 0;
}

Changelog from v1:
 - Fixed one chunk of the comments from Christoph Hellwig and Jeff Liu.

v1:
 - Addressed the comments from Dave Chinner and Christoph Hellwig.

Zhi Yong Wu (3):
  xfs: factor prid related codes into xfs_get_initial_prid()
  xfs: add O_TMPFILE support
  xfs: allow linkat() on O_TMPFILE files

 fs/xfs/xfs_inode.c      |  123 ++++++++++++++++++++++++++++++++++++++++++++--
 fs/xfs/xfs_inode.h      |   12 +++++
 fs/xfs/xfs_iops.c       |   16 ++++++
 fs/xfs/xfs_shared.h     |    4 +-
 fs/xfs/xfs_symlink.c    |    5 +--
 fs/xfs/xfs_trans_resv.c |   55 +++++++++++++++++++--
 fs/xfs/xfs_trans_resv.h |    2 +
 7 files changed, 202 insertions(+), 15 deletions(-)

-- 
1.7.6.5

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* [PATCH v2 1/3] xfs: factor prid related codes into xfs_get_initial_prid()
  2013-12-18  0:22 [PATCH v2 0/3] xfs: add O_TMPFILE support Zhi Yong Wu
@ 2013-12-18  0:22 ` Zhi Yong Wu
  2013-12-18  0:22 ` [PATCH v2 2/3] xfs: add O_TMPFILE support Zhi Yong Wu
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 14+ messages in thread
From: Zhi Yong Wu @ 2013-12-18  0:22 UTC (permalink / raw)
  To: xfs; +Cc: Zhi Yong Wu

From: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>

It will be reused by the O_TMPFILE creation function.

Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>
---
 fs/xfs/xfs_inode.c   |    6 +-----
 fs/xfs/xfs_inode.h   |   10 ++++++++++
 fs/xfs/xfs_symlink.c |    5 +----
 3 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 001aa89..c79b875 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -42,7 +42,6 @@
 #include "xfs_bmap_util.h"
 #include "xfs_error.h"
 #include "xfs_quota.h"
-#include "xfs_dinode.h"
 #include "xfs_filestream.h"
 #include "xfs_cksum.h"
 #include "xfs_trace.h"
@@ -1169,10 +1168,7 @@ xfs_create(
 	if (XFS_FORCED_SHUTDOWN(mp))
 		return XFS_ERROR(EIO);
 
-	if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
-		prid = xfs_get_projid(dp);
-	else
-		prid = XFS_PROJID_DEFAULT;
+	prid = xfs_get_initial_prid(dp);
 
 	/*
 	 * Make sure that we have allocated dquot(s) on disk.
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 9e6efccb..6c58349 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -20,6 +20,7 @@
 
 #include "xfs_inode_buf.h"
 #include "xfs_inode_fork.h"
+#include "xfs_dinode.h"
 
 /*
  * Kernel only inode definitions
@@ -192,6 +193,15 @@ xfs_set_projid(struct xfs_inode *ip,
 	ip->i_d.di_projid_lo = (__uint16_t) (projid & 0xffff);
 }
 
+static inline prid_t
+xfs_get_initial_prid(struct xfs_inode *dp)
+{
+	if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
+		return xfs_get_projid(dp);
+
+	return XFS_PROJID_DEFAULT;
+}
+
 /*
  * In-core inode flags.
  */
diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c
index 14e58f2..13140c7 100644
--- a/fs/xfs/xfs_symlink.c
+++ b/fs/xfs/xfs_symlink.c
@@ -208,10 +208,7 @@ xfs_symlink(
 		return XFS_ERROR(ENAMETOOLONG);
 
 	udqp = gdqp = NULL;
-	if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
-		prid = xfs_get_projid(dp);
-	else
-		prid = XFS_PROJID_DEFAULT;
+	prid = xfs_get_initial_prid(dp);
 
 	/*
 	 * Make sure that we have allocated dquot(s) on disk.
-- 
1.7.6.5

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* [PATCH v2 2/3] xfs: add O_TMPFILE support
  2013-12-18  0:22 [PATCH v2 0/3] xfs: add O_TMPFILE support Zhi Yong Wu
  2013-12-18  0:22 ` [PATCH v2 1/3] xfs: factor prid related codes into xfs_get_initial_prid() Zhi Yong Wu
@ 2013-12-18  0:22 ` Zhi Yong Wu
  2013-12-24  0:55   ` Dave Chinner
  2013-12-18  0:22 ` [PATCH v2 3/3] xfs: allow linkat() on O_TMPFILE files Zhi Yong Wu
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 14+ messages in thread
From: Zhi Yong Wu @ 2013-12-18  0:22 UTC (permalink / raw)
  To: xfs; +Cc: Zhi Yong Wu

From: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>

Add two functions xfs_create_tmpfile() and xfs_vn_tmpfile()
to support O_TMPFILE file creation.

In contrast to xfs_create(), xfs_create_tmpfile() has a different
log reservation to the regular file creation because there is no
directory modification, and doesn't check if an entry can be added
to the directory, but the reservation quotas is required appropriately,
and finally its inode is added to the unlinked list.

xfs_vn_tmpfile() add one O_TMPFILE method to VFS interface and directly
invoke xfs_create_tmpfile().

Signed-off-by: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>
---
 fs/xfs/xfs_inode.c      |  107 +++++++++++++++++++++++++++++++++++++++++++++++
 fs/xfs/xfs_inode.h      |    2 +
 fs/xfs/xfs_iops.c       |   16 +++++++
 fs/xfs/xfs_shared.h     |    4 +-
 fs/xfs/xfs_trans_resv.c |   36 +++++++++++++++-
 fs/xfs/xfs_trans_resv.h |    2 +
 6 files changed, 164 insertions(+), 3 deletions(-)

diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index c79b875..ac133ea 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1333,6 +1333,113 @@ xfs_create(
 }
 
 int
+xfs_create_tmpfile(
+	struct xfs_inode	*dp,
+	struct dentry		*dentry,
+	umode_t			mode)
+{
+	struct xfs_mount	*mp = dp->i_mount;
+	struct xfs_inode	*ip = NULL;
+	struct xfs_trans	*tp = NULL;
+	int			error;
+	uint			cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
+	prid_t                  prid;
+	struct xfs_dquot	*udqp = NULL;
+	struct xfs_dquot	*gdqp = NULL;
+	struct xfs_dquot	*pdqp = NULL;
+	struct xfs_trans_res	*tres;
+	uint			resblks;
+
+	if (XFS_FORCED_SHUTDOWN(mp))
+		return XFS_ERROR(EIO);
+
+	prid = xfs_get_initial_prid(dp);
+
+	/*
+	 * Make sure that we have allocated dquot(s) on disk.
+	 */
+	error = xfs_qm_vop_dqalloc(dp, xfs_kuid_to_uid(current_fsuid()),
+				xfs_kgid_to_gid(current_fsgid()), prid,
+				XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT,
+				&udqp, &gdqp, &pdqp);
+	if (error)
+		return error;
+
+	resblks = XFS_IALLOC_SPACE_RES(mp);
+	tp = xfs_trans_alloc(mp, XFS_TRANS_CREATE_TMPFILE);
+
+	tres = &M_RES(mp)->tr_create_tmpfile;
+	error = xfs_trans_reserve(tp, tres, resblks, 0);
+	if (error == ENOSPC) {
+		/* No space at all so try a "no-allocation" reservation */
+		resblks = 0;
+		error = xfs_trans_reserve(tp, tres, 0, 0);
+	}
+	if (error) {
+		cancel_flags = 0;
+		goto out_trans_cancel;
+	}
+
+	error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp,
+						pdqp, resblks, 1, 0);
+	if (error)
+		goto out_trans_cancel;
+
+	error = xfs_dir_ialloc(&tp, dp, mode, 1, 0,
+				prid, resblks > 0, &ip, NULL);
+	if (error) {
+		if (error == ENOSPC)
+			goto out_trans_cancel;
+		goto out_trans_abort;
+	}
+
+	if (mp->m_flags & XFS_MOUNT_WSYNC)
+		xfs_trans_set_sync(tp);
+
+	/*
+	 * Attach the dquot(s) to the inodes and modify them incore.
+	 * These ids of the inode couldn't have changed since the new
+	 * inode has been locked ever since it was created.
+	 */
+	xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp);
+
+	ip->i_d.di_nlink--;
+	d_tmpfile(dentry, VFS_I(ip));
+	error = xfs_iunlink(tp, ip);
+	if (error)
+		goto out_trans_abort;
+
+	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
+	if (error)
+		goto out_release_inode;
+
+	xfs_qm_dqrele(udqp);
+	xfs_qm_dqrele(gdqp);
+	xfs_qm_dqrele(pdqp);
+
+	return 0;
+
+ out_trans_abort:
+	cancel_flags |= XFS_TRANS_ABORT;
+ out_trans_cancel:
+	xfs_trans_cancel(tp, cancel_flags);
+ out_release_inode:
+	/*
+	 * Wait until after the current transaction is aborted to
+	 * release the inode.  This prevents recursive transactions
+	 * and deadlocks from xfs_inactive.
+	 */
+	if (ip)
+		IRELE(ip);
+
+	xfs_qm_dqrele(udqp);
+	xfs_qm_dqrele(gdqp);
+	xfs_qm_dqrele(pdqp);
+
+	return error;
+}
+
+int
 xfs_link(
 	xfs_inode_t		*tdp,
 	xfs_inode_t		*sip,
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 6c58349..3a97820 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -333,6 +333,8 @@ int		xfs_lookup(struct xfs_inode *dp, struct xfs_name *name,
 			   struct xfs_inode **ipp, struct xfs_name *ci_name);
 int		xfs_create(struct xfs_inode *dp, struct xfs_name *name,
 			   umode_t mode, xfs_dev_t rdev, struct xfs_inode **ipp);
+int		xfs_create_tmpfile(struct xfs_inode *dp, struct dentry *dentry,
+			   umode_t mode);
 int		xfs_remove(struct xfs_inode *dp, struct xfs_name *name,
 			   struct xfs_inode *ip);
 int		xfs_link(struct xfs_inode *tdp, struct xfs_inode *sip,
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index 27e0e54..5ea7f85 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -39,6 +39,7 @@
 #include "xfs_da_btree.h"
 #include "xfs_dir2_priv.h"
 #include "xfs_dinode.h"
+#include "xfs_trans_space.h"
 
 #include <linux/capability.h>
 #include <linux/xattr.h>
@@ -1050,6 +1051,19 @@ xfs_vn_fiemap(
 	return 0;
 }
 
+STATIC int
+xfs_vn_tmpfile(
+	struct inode	*dir,
+	struct dentry	*dentry,
+	umode_t		mode)
+{
+	int		error;
+
+	error = xfs_create_tmpfile(XFS_I(dir), dentry, mode);
+
+	return -error;
+}
+
 static const struct inode_operations xfs_inode_operations = {
 	.get_acl		= xfs_get_acl,
 	.getattr		= xfs_vn_getattr,
@@ -1086,6 +1100,7 @@ static const struct inode_operations xfs_dir_inode_operations = {
 	.removexattr		= generic_removexattr,
 	.listxattr		= xfs_vn_listxattr,
 	.update_time		= xfs_vn_update_time,
+	.tmpfile		= xfs_vn_tmpfile,
 };
 
 static const struct inode_operations xfs_dir_ci_inode_operations = {
@@ -1112,6 +1127,7 @@ static const struct inode_operations xfs_dir_ci_inode_operations = {
 	.removexattr		= generic_removexattr,
 	.listxattr		= xfs_vn_listxattr,
 	.update_time		= xfs_vn_update_time,
+	.tmpfile		= xfs_vn_tmpfile,
 };
 
 static const struct inode_operations xfs_symlink_inode_operations = {
diff --git a/fs/xfs/xfs_shared.h b/fs/xfs/xfs_shared.h
index 8c5035a1..4484e51 100644
--- a/fs/xfs/xfs_shared.h
+++ b/fs/xfs/xfs_shared.h
@@ -104,7 +104,8 @@ extern const struct xfs_buf_ops xfs_symlink_buf_ops;
 #define	XFS_TRANS_SB_COUNT		41
 #define	XFS_TRANS_CHECKPOINT		42
 #define	XFS_TRANS_ICREATE		43
-#define	XFS_TRANS_TYPE_MAX		43
+#define	XFS_TRANS_CREATE_TMPFILE	44
+#define	XFS_TRANS_TYPE_MAX		44
 /* new transaction types need to be reflected in xfs_logprint(8) */
 
 #define XFS_TRANS_TYPES \
@@ -112,6 +113,7 @@ extern const struct xfs_buf_ops xfs_symlink_buf_ops;
 	{ XFS_TRANS_SETATTR_SIZE,	"SETATTR_SIZE" }, \
 	{ XFS_TRANS_INACTIVE,		"INACTIVE" }, \
 	{ XFS_TRANS_CREATE,		"CREATE" }, \
+	{ XFS_TRANS_CREATE_TMPFILE,	"CREATE_TMPFILE" }, \
 	{ XFS_TRANS_CREATE_TRUNC,	"CREATE_TRUNC" }, \
 	{ XFS_TRANS_TRUNCATE_FILE,	"TRUNCATE_FILE" }, \
 	{ XFS_TRANS_REMOVE,		"REMOVE" }, \
diff --git a/fs/xfs/xfs_trans_resv.c b/fs/xfs/xfs_trans_resv.c
index 2fd59c0..bd3b4b7 100644
--- a/fs/xfs/xfs_trans_resv.c
+++ b/fs/xfs/xfs_trans_resv.c
@@ -229,6 +229,18 @@ xfs_calc_link_reservation(
 }
 
 /*
+ * For adding an inode to unlinked list we can modify:
+ *    the agi hash list: sector size
+ *    the unlinked inode: inode size
+ */
+STATIC uint
+xfs_calc_iunlink_add_reservation(xfs_mount_t *mp)
+{
+	return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
+		xfs_calc_inode_res(mp, 1);
+}
+
+/*
  * For removing a directory entry we can modify:
  *    the parent directory inode: inode size
  *    the removed inode: inode size
@@ -245,10 +257,11 @@ xfs_calc_remove_reservation(
 	struct xfs_mount	*mp)
 {
 	return XFS_DQUOT_LOGRES(mp) +
-		MAX((xfs_calc_inode_res(mp, 2) +
+		xfs_calc_iunlink_add_reservation(mp) +
+		MAX((xfs_calc_inode_res(mp, 1) +
 		     xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp),
 				      XFS_FSB_TO_B(mp, 1))),
-		    (xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) +
+		    (xfs_calc_buf_res(4, mp->m_sb.sb_sectsize) +
 		     xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 2),
 				      XFS_FSB_TO_B(mp, 1))));
 }
@@ -343,6 +356,20 @@ xfs_calc_create_reservation(
 
 }
 
+STATIC uint
+xfs_calc_create_tmpfile_reservation(
+	struct xfs_mount        *mp)
+{
+	uint	res = XFS_DQUOT_LOGRES(mp);
+
+	if (xfs_sb_version_hascrc(&mp->m_sb))
+		res += xfs_calc_icreate_resv_alloc(mp);
+	else
+		res += xfs_calc_create_resv_alloc(mp);
+
+	return res + xfs_calc_iunlink_add_reservation(mp);
+}
+
 /*
  * Making a new directory is the same as creating a new file.
  */
@@ -729,6 +756,11 @@ xfs_trans_resv_calc(
 	resp->tr_create.tr_logcount = XFS_CREATE_LOG_COUNT;
 	resp->tr_create.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
 
+	resp->tr_create_tmpfile.tr_logres =
+			xfs_calc_create_tmpfile_reservation(mp);
+	resp->tr_create_tmpfile.tr_logcount = XFS_CREATE_TMPFILE_LOG_COUNT;
+	resp->tr_create_tmpfile.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
+
 	resp->tr_mkdir.tr_logres = xfs_calc_mkdir_reservation(mp);
 	resp->tr_mkdir.tr_logcount = XFS_MKDIR_LOG_COUNT;
 	resp->tr_mkdir.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
diff --git a/fs/xfs/xfs_trans_resv.h b/fs/xfs/xfs_trans_resv.h
index de7de9a..285621d 100644
--- a/fs/xfs/xfs_trans_resv.h
+++ b/fs/xfs/xfs_trans_resv.h
@@ -38,6 +38,7 @@ struct xfs_trans_resv {
 	struct xfs_trans_res	tr_remove;	/* unlink trans */
 	struct xfs_trans_res	tr_symlink;	/* symlink trans */
 	struct xfs_trans_res	tr_create;	/* create trans */
+	struct xfs_trans_res	tr_create_tmpfile; /* create O_TMPFILE trans */
 	struct xfs_trans_res	tr_mkdir;	/* mkdir trans */
 	struct xfs_trans_res	tr_ifree;	/* inode free trans */
 	struct xfs_trans_res	tr_ichange;	/* inode update trans */
@@ -100,6 +101,7 @@ struct xfs_trans_resv {
 #define	XFS_ITRUNCATE_LOG_COUNT		2
 #define XFS_INACTIVE_LOG_COUNT		2
 #define	XFS_CREATE_LOG_COUNT		2
+#define	XFS_CREATE_TMPFILE_LOG_COUNT	2
 #define	XFS_MKDIR_LOG_COUNT		3
 #define	XFS_SYMLINK_LOG_COUNT		3
 #define	XFS_REMOVE_LOG_COUNT		2
-- 
1.7.6.5

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* [PATCH v2 3/3] xfs: allow linkat() on O_TMPFILE files
  2013-12-18  0:22 [PATCH v2 0/3] xfs: add O_TMPFILE support Zhi Yong Wu
  2013-12-18  0:22 ` [PATCH v2 1/3] xfs: factor prid related codes into xfs_get_initial_prid() Zhi Yong Wu
  2013-12-18  0:22 ` [PATCH v2 2/3] xfs: add O_TMPFILE support Zhi Yong Wu
@ 2013-12-18  0:22 ` Zhi Yong Wu
  2013-12-24  0:55   ` Dave Chinner
  2013-12-23  1:45 ` [PATCH v2 0/3] xfs: add O_TMPFILE support Zhi Yong Wu
  2013-12-26  8:51 ` Christoph Hellwig
  4 siblings, 1 reply; 14+ messages in thread
From: Zhi Yong Wu @ 2013-12-18  0:22 UTC (permalink / raw)
  To: xfs; +Cc: Zhi Yong Wu

From: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>

The VFS allows an anonymous temporary file to be named at a later
time via a linkat() syscall. The inodes for O_TMPFILE files are
are marked with a special flag I_LINKABLE and have a zero link count.

To support this in XFS, xfs_link() detects if this flag I_LINKABLE
is set and behaves appropriately when detected. So in this case,
its transaciton reservation takes into account the additional
overhead of removing the inode from the unlinked list. Then the
inode is removed from the unlinked list and the directory entry
is added. Finally its link count is bumped accordingly.

Signed-off-by: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>
---
 fs/xfs/xfs_inode.c      |   10 +++++++++-
 fs/xfs/xfs_trans_resv.c |   19 +++++++++++++++++--
 2 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index ac133ea..b08b5a8 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -61,6 +61,8 @@ kmem_zone_t *xfs_inode_zone;
 
 STATIC int xfs_iflush_int(xfs_inode_t *, xfs_buf_t *);
 
+STATIC int xfs_iunlink_remove(xfs_trans_t *, xfs_inode_t *);
+
 /*
  * helper function to extract extent size hint from inode
  */
@@ -1118,7 +1120,7 @@ xfs_bumplink(
 {
 	xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG);
 
-	ASSERT(ip->i_d.di_nlink > 0);
+	ASSERT(ip->i_d.di_nlink > 0 || (VFS_I(ip)->i_state & I_LINKABLE));
 	ip->i_d.di_nlink++;
 	inc_nlink(VFS_I(ip));
 	if ((ip->i_d.di_version == 1) &&
@@ -1504,6 +1506,12 @@ xfs_link(
 
 	xfs_bmap_init(&free_list, &first_block);
 
+	if (sip->i_d.di_nlink == 0) {
+		error = xfs_iunlink_remove(tp, sip);
+		if (error)
+			goto abort_return;
+	}
+
 	error = xfs_dir_createname(tp, tdp, target_name, sip->i_ino,
 					&first_block, &free_list, resblks);
 	if (error)
diff --git a/fs/xfs/xfs_trans_resv.c b/fs/xfs/xfs_trans_resv.c
index bd3b4b7..76f9a02 100644
--- a/fs/xfs/xfs_trans_resv.c
+++ b/fs/xfs/xfs_trans_resv.c
@@ -204,6 +204,20 @@ xfs_calc_rename_reservation(
 }
 
 /*
+ * For removing an inode from unlinked list at first, we can modify:
+ *    the agi hash list and counters: sector size
+ *    the on disk inode before ours in the agi hash list: inode cluster size
+ */
+STATIC uint
+xfs_calc_iunlink_remove_reservation(
+	struct xfs_mount        *mp)
+{
+	return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
+		MAX((__uint16_t)XFS_FSB_TO_B(mp, 1),
+			(__uint16_t)XFS_INODE_CLUSTER_SIZE(mp));
+}
+
+/*
  * For creating a link to an inode:
  *    the parent directory inode: inode size
  *    the linked inode: inode size
@@ -220,6 +234,7 @@ xfs_calc_link_reservation(
 	struct xfs_mount	*mp)
 {
 	return XFS_DQUOT_LOGRES(mp) +
+		xfs_calc_iunlink_remove_reservation(mp) +
 		MAX((xfs_calc_inode_res(mp, 2) +
 		     xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp),
 				      XFS_FSB_TO_B(mp, 1))),
@@ -410,9 +425,9 @@ xfs_calc_ifree_reservation(
 {
 	return XFS_DQUOT_LOGRES(mp) +
 		xfs_calc_inode_res(mp, 1) +
-		xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) +
+		xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
 		xfs_calc_buf_res(1, XFS_FSB_TO_B(mp, 1)) +
-		max_t(uint, XFS_FSB_TO_B(mp, 1), XFS_INODE_CLUSTER_SIZE(mp)) +
+		xfs_calc_iunlink_remove_reservation(mp) +
 		xfs_calc_buf_res(1, 0) +
 		xfs_calc_buf_res(2 + XFS_IALLOC_BLOCKS(mp) +
 				 mp->m_in_maxlevels, 0) +
-- 
1.7.6.5

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* Re: [PATCH v2 0/3] xfs: add O_TMPFILE support
  2013-12-18  0:22 [PATCH v2 0/3] xfs: add O_TMPFILE support Zhi Yong Wu
                   ` (2 preceding siblings ...)
  2013-12-18  0:22 ` [PATCH v2 3/3] xfs: allow linkat() on O_TMPFILE files Zhi Yong Wu
@ 2013-12-23  1:45 ` Zhi Yong Wu
  2013-12-26  8:51 ` Christoph Hellwig
  4 siblings, 0 replies; 14+ messages in thread
From: Zhi Yong Wu @ 2013-12-23  1:45 UTC (permalink / raw)
  To: xfstests; +Cc: Zhi Yong Wu

ping?


On Wed, Dec 18, 2013 at 8:22 AM, Zhi Yong Wu <zwu.kernel@gmail.com> wrote:
> From: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>
>
> HI, folks
>
>   It's time to post the latest revision out, welcome to any constructive comment, thanks.
>
>   If anyone is interested in playing with it, you can get this patchset from my dev git on github:
>   git://github.com/wuzhy/kernel.git xfs_tmpfile
>
>   The patchset was tested against the code snippet from Andy Lutomirski and other test cases:
>   http://lwn.net/Articles/562296/
>   If you have any other better test cases, please let me know, thanks.
>
> #include <stdio.h>
> #include <err.h>
> #include <fcntl.h>
> #include <unistd.h>
> #include <string.h>
>
> #define __O_TMPFILE 020000000
> #define O_DIRECTORY 0200000
> #define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
> #define AT_EMPTY_PATH 0x1000
>
> int main(int argc, char **argv)
> {
>    char buf[128];
>
>    if (argc != 3)
>      errx(1, "Usage: flinktest PATH linkat|proc");
>
>    int fd = open(".", O_TMPFILE | O_RDWR, 0600);
>    if (fd == -1)
>      err(1, "O_TMPFILE");
>    else
>      printf("fd #: %d\n", fd);
>
>    write(fd, "test", 4);
>
>    if (!strcmp(argv[2], "linkat")) {
>      if (linkat(fd, "", AT_FDCWD, argv[1], AT_EMPTY_PATH) != 0)
>        err(1, "linkat");
>    } else if (!strcmp(argv[2], "proc")) {
>      sprintf(buf, "/proc/self/fd/%d", fd);
>      if (linkat(AT_FDCWD, buf, AT_FDCWD, argv[1], AT_SYMLINK_FOLLOW) != 0)
>        err(1, "linkat");
>    } else {
>      errx(1, "invalid mode");
>    }
>
>    return 0;
> }
>
> Changelog from v1:
>  - Fixed one chunk of the comments from Christoph Hellwig and Jeff Liu.
>
> v1:
>  - Addressed the comments from Dave Chinner and Christoph Hellwig.
>
> Zhi Yong Wu (3):
>   xfs: factor prid related codes into xfs_get_initial_prid()
>   xfs: add O_TMPFILE support
>   xfs: allow linkat() on O_TMPFILE files
>
>  fs/xfs/xfs_inode.c      |  123 ++++++++++++++++++++++++++++++++++++++++++++--
>  fs/xfs/xfs_inode.h      |   12 +++++
>  fs/xfs/xfs_iops.c       |   16 ++++++
>  fs/xfs/xfs_shared.h     |    4 +-
>  fs/xfs/xfs_symlink.c    |    5 +--
>  fs/xfs/xfs_trans_resv.c |   55 +++++++++++++++++++--
>  fs/xfs/xfs_trans_resv.h |    2 +
>  7 files changed, 202 insertions(+), 15 deletions(-)
>
> --
> 1.7.6.5
>
> _______________________________________________
> xfs mailing list
> xfs@oss.sgi.com
> http://oss.sgi.com/mailman/listinfo/xfs



-- 
Regards,

Zhi Yong Wu

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* Re: [PATCH v2 2/3] xfs: add O_TMPFILE support
  2013-12-18  0:22 ` [PATCH v2 2/3] xfs: add O_TMPFILE support Zhi Yong Wu
@ 2013-12-24  0:55   ` Dave Chinner
  2013-12-24  1:58     ` Zhi Yong Wu
  0 siblings, 1 reply; 14+ messages in thread
From: Dave Chinner @ 2013-12-24  0:55 UTC (permalink / raw)
  To: Zhi Yong Wu; +Cc: Zhi Yong Wu, xfs

On Wed, Dec 18, 2013 at 08:22:40AM +0800, Zhi Yong Wu wrote:
> From: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>
> 
> Add two functions xfs_create_tmpfile() and xfs_vn_tmpfile()
> to support O_TMPFILE file creation.
> 
> In contrast to xfs_create(), xfs_create_tmpfile() has a different
> log reservation to the regular file creation because there is no
> directory modification, and doesn't check if an entry can be added
> to the directory, but the reservation quotas is required appropriately,
> and finally its inode is added to the unlinked list.
> 
> xfs_vn_tmpfile() add one O_TMPFILE method to VFS interface and directly
> invoke xfs_create_tmpfile().

There's minor stuff I could ask you to change, but I think this is
good enough for initial support of O_TMPFILE.

Reviewed-by: Dave Chinner <dchinner@redhat.com>

-- 
Dave Chinner
david@fromorbit.com

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* Re: [PATCH v2 3/3] xfs: allow linkat() on O_TMPFILE files
  2013-12-18  0:22 ` [PATCH v2 3/3] xfs: allow linkat() on O_TMPFILE files Zhi Yong Wu
@ 2013-12-24  0:55   ` Dave Chinner
  0 siblings, 0 replies; 14+ messages in thread
From: Dave Chinner @ 2013-12-24  0:55 UTC (permalink / raw)
  To: Zhi Yong Wu; +Cc: Zhi Yong Wu, xfs

On Wed, Dec 18, 2013 at 08:22:41AM +0800, Zhi Yong Wu wrote:
> From: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>
> 
> The VFS allows an anonymous temporary file to be named at a later
> time via a linkat() syscall. The inodes for O_TMPFILE files are
> are marked with a special flag I_LINKABLE and have a zero link count.
> 
> To support this in XFS, xfs_link() detects if this flag I_LINKABLE
> is set and behaves appropriately when detected. So in this case,
> its transaciton reservation takes into account the additional
> overhead of removing the inode from the unlinked list. Then the
> inode is removed from the unlinked list and the directory entry
> is added. Finally its link count is bumped accordingly.
> 
> Signed-off-by: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>

Looks good.

Reviewed-by: Dave Chinner <dchinner@redhat.com>

-- 
Dave Chinner
david@fromorbit.com

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* Re: [PATCH v2 2/3] xfs: add O_TMPFILE support
  2013-12-24  0:55   ` Dave Chinner
@ 2013-12-24  1:58     ` Zhi Yong Wu
  0 siblings, 0 replies; 14+ messages in thread
From: Zhi Yong Wu @ 2013-12-24  1:58 UTC (permalink / raw)
  To: Dave Chinner, Christoph Hellwig; +Cc: Zhi Yong Wu, xfstests

On Tue, Dec 24, 2013 at 8:55 AM, Dave Chinner <david@fromorbit.com> wrote:
> On Wed, Dec 18, 2013 at 08:22:40AM +0800, Zhi Yong Wu wrote:
>> From: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>
>>
>> Add two functions xfs_create_tmpfile() and xfs_vn_tmpfile()
>> to support O_TMPFILE file creation.
>>
>> In contrast to xfs_create(), xfs_create_tmpfile() has a different
>> log reservation to the regular file creation because there is no
>> directory modification, and doesn't check if an entry can be added
>> to the directory, but the reservation quotas is required appropriately,
>> and finally its inode is added to the unlinked list.
>>
>> xfs_vn_tmpfile() add one O_TMPFILE method to VFS interface and directly
>> invoke xfs_create_tmpfile().
>
> There's minor stuff I could ask you to change, but I think this is
> good enough for initial support of O_TMPFILE.
>
> Reviewed-by: Dave Chinner <dchinner@redhat.com>
Great, thanks a lot for your amazing Chrismas gift. Dave and
Christoph, Merry Chrismas!

>
> --
> Dave Chinner
> david@fromorbit.com



-- 
Regards,

Zhi Yong Wu

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* Re: [PATCH v2 0/3] xfs: add O_TMPFILE support
  2013-12-18  0:22 [PATCH v2 0/3] xfs: add O_TMPFILE support Zhi Yong Wu
                   ` (3 preceding siblings ...)
  2013-12-23  1:45 ` [PATCH v2 0/3] xfs: add O_TMPFILE support Zhi Yong Wu
@ 2013-12-26  8:51 ` Christoph Hellwig
  2013-12-28 10:04     ` Zhi Yong Wu
  2014-01-07 20:49   ` Ben Myers
  4 siblings, 2 replies; 14+ messages in thread
From: Christoph Hellwig @ 2013-12-26  8:51 UTC (permalink / raw)
  To: Zhi Yong Wu; +Cc: linux-api, Zhi Yong Wu, xfs

Both patches looks good to me,

Reviewed-by: Christoph Hellwig <hch@lst.de>

But now we need to make sure we can exercise it, which will need
support for tmpfile and flink commands in xfs_io.

And tests that use those commands in xfstests.  At a minimum I'd
suggest:

 - test creating read-only/read-write/executable files
 - check how permission bits actually work for O_TMPFILE and
   enforce that (unfortunately I can't find any documentation for that)
 - check that creating non-regular files is properly rejected
 - check that flink works on O_TMPFILE files, but doesn't work on
   on other files

For an additional XFS-specific test I'd recommend:

 - creating a tmpfile, use src/godown to force the filesystem down and
   check that repair recoveres the unlinked inode list
 - creating a tmpfile, flinking it, use src/godown to force the
   filesystem down and check that repair does not have to recover
   the unlink inode list.

On Wed, Dec 18, 2013 at 08:22:38AM +0800, Zhi Yong Wu wrote:
> From: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>
> 
> HI, folks
> 
>   It's time to post the latest revision out, welcome to any constructive comment, thanks.
> 
>   If anyone is interested in playing with it, you can get this patchset from my dev git on github:
>   git://github.com/wuzhy/kernel.git xfs_tmpfile
> 
>   The patchset was tested against the code snippet from Andy Lutomirski and other test cases:
>   http://lwn.net/Articles/562296/
>   If you have any other better test cases, please let me know, thanks.
> 
> #include <stdio.h>
> #include <err.h>
> #include <fcntl.h>
> #include <unistd.h>
> #include <string.h>
> 
> #define __O_TMPFILE 020000000
> #define O_DIRECTORY 0200000
> #define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
> #define AT_EMPTY_PATH 0x1000
> 
> int main(int argc, char **argv)
> {
>    char buf[128];
> 
>    if (argc != 3)
>      errx(1, "Usage: flinktest PATH linkat|proc");
> 
>    int fd = open(".", O_TMPFILE | O_RDWR, 0600);
>    if (fd == -1)
>      err(1, "O_TMPFILE");
>    else
>      printf("fd #: %d\n", fd);
> 
>    write(fd, "test", 4);
> 
>    if (!strcmp(argv[2], "linkat")) {
>      if (linkat(fd, "", AT_FDCWD, argv[1], AT_EMPTY_PATH) != 0)
>        err(1, "linkat");
>    } else if (!strcmp(argv[2], "proc")) {
>      sprintf(buf, "/proc/self/fd/%d", fd);
>      if (linkat(AT_FDCWD, buf, AT_FDCWD, argv[1], AT_SYMLINK_FOLLOW) != 0)
>        err(1, "linkat");
>    } else {
>      errx(1, "invalid mode");
>    }
> 
>    return 0;
> }
> 
> Changelog from v1:
>  - Fixed one chunk of the comments from Christoph Hellwig and Jeff Liu.
> 
> v1:
>  - Addressed the comments from Dave Chinner and Christoph Hellwig.
> 
> Zhi Yong Wu (3):
>   xfs: factor prid related codes into xfs_get_initial_prid()
>   xfs: add O_TMPFILE support
>   xfs: allow linkat() on O_TMPFILE files
> 
>  fs/xfs/xfs_inode.c      |  123 ++++++++++++++++++++++++++++++++++++++++++++--
>  fs/xfs/xfs_inode.h      |   12 +++++
>  fs/xfs/xfs_iops.c       |   16 ++++++
>  fs/xfs/xfs_shared.h     |    4 +-
>  fs/xfs/xfs_symlink.c    |    5 +--
>  fs/xfs/xfs_trans_resv.c |   55 +++++++++++++++++++--
>  fs/xfs/xfs_trans_resv.h |    2 +
>  7 files changed, 202 insertions(+), 15 deletions(-)
> 
> -- 
> 1.7.6.5
> 
> _______________________________________________
> xfs mailing list
> xfs@oss.sgi.com
> http://oss.sgi.com/mailman/listinfo/xfs
---end quoted text---

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* Re: [PATCH v2 0/3] xfs: add O_TMPFILE support
@ 2013-12-28 10:04     ` Zhi Yong Wu
  0 siblings, 0 replies; 14+ messages in thread
From: Zhi Yong Wu @ 2013-12-28 10:04 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linux-api, Zhi Yong Wu, xfstests

On Thu, Dec 26, 2013 at 4:51 PM, Christoph Hellwig <hch@infradead.org> wrote:
> Both patches looks good to me,
>
> Reviewed-by: Christoph Hellwig <hch@lst.de>
Indeed thanks for your review. ok, i will place them to my TODO list.

>
> But now we need to make sure we can exercise it, which will need
> support for tmpfile and flink commands in xfs_io.
>
> And tests that use those commands in xfstests.  At a minimum I'd
> suggest:
>
>  - test creating read-only/read-write/executable files
>  - check how permission bits actually work for O_TMPFILE and
>    enforce that (unfortunately I can't find any documentation for that)
>  - check that creating non-regular files is properly rejected
>  - check that flink works on O_TMPFILE files, but doesn't work on
>    on other files
>
> For an additional XFS-specific test I'd recommend:
>
>  - creating a tmpfile, use src/godown to force the filesystem down and
>    check that repair recoveres the unlinked inode list
>  - creating a tmpfile, flinking it, use src/godown to force the
>    filesystem down and check that repair does not have to recover
>    the unlink inode list.
>
> On Wed, Dec 18, 2013 at 08:22:38AM +0800, Zhi Yong Wu wrote:
>> From: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>
>>
>> HI, folks
>>
>>   It's time to post the latest revision out, welcome to any constructive comment, thanks.
>>
>>   If anyone is interested in playing with it, you can get this patchset from my dev git on github:
>>   git://github.com/wuzhy/kernel.git xfs_tmpfile
>>
>>   The patchset was tested against the code snippet from Andy Lutomirski and other test cases:
>>   http://lwn.net/Articles/562296/
>>   If you have any other better test cases, please let me know, thanks.
>>
>> #include <stdio.h>
>> #include <err.h>
>> #include <fcntl.h>
>> #include <unistd.h>
>> #include <string.h>
>>
>> #define __O_TMPFILE 020000000
>> #define O_DIRECTORY 0200000
>> #define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
>> #define AT_EMPTY_PATH 0x1000
>>
>> int main(int argc, char **argv)
>> {
>>    char buf[128];
>>
>>    if (argc != 3)
>>      errx(1, "Usage: flinktest PATH linkat|proc");
>>
>>    int fd = open(".", O_TMPFILE | O_RDWR, 0600);
>>    if (fd == -1)
>>      err(1, "O_TMPFILE");
>>    else
>>      printf("fd #: %d\n", fd);
>>
>>    write(fd, "test", 4);
>>
>>    if (!strcmp(argv[2], "linkat")) {
>>      if (linkat(fd, "", AT_FDCWD, argv[1], AT_EMPTY_PATH) != 0)
>>        err(1, "linkat");
>>    } else if (!strcmp(argv[2], "proc")) {
>>      sprintf(buf, "/proc/self/fd/%d", fd);
>>      if (linkat(AT_FDCWD, buf, AT_FDCWD, argv[1], AT_SYMLINK_FOLLOW) != 0)
>>        err(1, "linkat");
>>    } else {
>>      errx(1, "invalid mode");
>>    }
>>
>>    return 0;
>> }
>>
>> Changelog from v1:
>>  - Fixed one chunk of the comments from Christoph Hellwig and Jeff Liu.
>>
>> v1:
>>  - Addressed the comments from Dave Chinner and Christoph Hellwig.
>>
>> Zhi Yong Wu (3):
>>   xfs: factor prid related codes into xfs_get_initial_prid()
>>   xfs: add O_TMPFILE support
>>   xfs: allow linkat() on O_TMPFILE files
>>
>>  fs/xfs/xfs_inode.c      |  123 ++++++++++++++++++++++++++++++++++++++++++++--
>>  fs/xfs/xfs_inode.h      |   12 +++++
>>  fs/xfs/xfs_iops.c       |   16 ++++++
>>  fs/xfs/xfs_shared.h     |    4 +-
>>  fs/xfs/xfs_symlink.c    |    5 +--
>>  fs/xfs/xfs_trans_resv.c |   55 +++++++++++++++++++--
>>  fs/xfs/xfs_trans_resv.h |    2 +
>>  7 files changed, 202 insertions(+), 15 deletions(-)
>>
>> --
>> 1.7.6.5
>>
>> _______________________________________________
>> xfs mailing list
>> xfs@oss.sgi.com
>> http://oss.sgi.com/mailman/listinfo/xfs
> ---end quoted text---



-- 
Regards,

Zhi Yong Wu

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* Re: [PATCH v2 0/3] xfs: add O_TMPFILE support
@ 2013-12-28 10:04     ` Zhi Yong Wu
  0 siblings, 0 replies; 14+ messages in thread
From: Zhi Yong Wu @ 2013-12-28 10:04 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: xfstests, Zhi Yong Wu, linux-api-u79uwXL29TY76Z2rM5mHXA

On Thu, Dec 26, 2013 at 4:51 PM, Christoph Hellwig <hch-wEGCiKHe2LqWVfeAwA7xHQ@public.gmane.org> wrote:
> Both patches looks good to me,
>
> Reviewed-by: Christoph Hellwig <hch-jcswGhMUV9g@public.gmane.org>
Indeed thanks for your review. ok, i will place them to my TODO list.

>
> But now we need to make sure we can exercise it, which will need
> support for tmpfile and flink commands in xfs_io.
>
> And tests that use those commands in xfstests.  At a minimum I'd
> suggest:
>
>  - test creating read-only/read-write/executable files
>  - check how permission bits actually work for O_TMPFILE and
>    enforce that (unfortunately I can't find any documentation for that)
>  - check that creating non-regular files is properly rejected
>  - check that flink works on O_TMPFILE files, but doesn't work on
>    on other files
>
> For an additional XFS-specific test I'd recommend:
>
>  - creating a tmpfile, use src/godown to force the filesystem down and
>    check that repair recoveres the unlinked inode list
>  - creating a tmpfile, flinking it, use src/godown to force the
>    filesystem down and check that repair does not have to recover
>    the unlink inode list.
>
> On Wed, Dec 18, 2013 at 08:22:38AM +0800, Zhi Yong Wu wrote:
>> From: Zhi Yong Wu <wuzhy-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
>>
>> HI, folks
>>
>>   It's time to post the latest revision out, welcome to any constructive comment, thanks.
>>
>>   If anyone is interested in playing with it, you can get this patchset from my dev git on github:
>>   git://github.com/wuzhy/kernel.git xfs_tmpfile
>>
>>   The patchset was tested against the code snippet from Andy Lutomirski and other test cases:
>>   http://lwn.net/Articles/562296/
>>   If you have any other better test cases, please let me know, thanks.
>>
>> #include <stdio.h>
>> #include <err.h>
>> #include <fcntl.h>
>> #include <unistd.h>
>> #include <string.h>
>>
>> #define __O_TMPFILE 020000000
>> #define O_DIRECTORY 0200000
>> #define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
>> #define AT_EMPTY_PATH 0x1000
>>
>> int main(int argc, char **argv)
>> {
>>    char buf[128];
>>
>>    if (argc != 3)
>>      errx(1, "Usage: flinktest PATH linkat|proc");
>>
>>    int fd = open(".", O_TMPFILE | O_RDWR, 0600);
>>    if (fd == -1)
>>      err(1, "O_TMPFILE");
>>    else
>>      printf("fd #: %d\n", fd);
>>
>>    write(fd, "test", 4);
>>
>>    if (!strcmp(argv[2], "linkat")) {
>>      if (linkat(fd, "", AT_FDCWD, argv[1], AT_EMPTY_PATH) != 0)
>>        err(1, "linkat");
>>    } else if (!strcmp(argv[2], "proc")) {
>>      sprintf(buf, "/proc/self/fd/%d", fd);
>>      if (linkat(AT_FDCWD, buf, AT_FDCWD, argv[1], AT_SYMLINK_FOLLOW) != 0)
>>        err(1, "linkat");
>>    } else {
>>      errx(1, "invalid mode");
>>    }
>>
>>    return 0;
>> }
>>
>> Changelog from v1:
>>  - Fixed one chunk of the comments from Christoph Hellwig and Jeff Liu.
>>
>> v1:
>>  - Addressed the comments from Dave Chinner and Christoph Hellwig.
>>
>> Zhi Yong Wu (3):
>>   xfs: factor prid related codes into xfs_get_initial_prid()
>>   xfs: add O_TMPFILE support
>>   xfs: allow linkat() on O_TMPFILE files
>>
>>  fs/xfs/xfs_inode.c      |  123 ++++++++++++++++++++++++++++++++++++++++++++--
>>  fs/xfs/xfs_inode.h      |   12 +++++
>>  fs/xfs/xfs_iops.c       |   16 ++++++
>>  fs/xfs/xfs_shared.h     |    4 +-
>>  fs/xfs/xfs_symlink.c    |    5 +--
>>  fs/xfs/xfs_trans_resv.c |   55 +++++++++++++++++++--
>>  fs/xfs/xfs_trans_resv.h |    2 +
>>  7 files changed, 202 insertions(+), 15 deletions(-)
>>
>> --
>> 1.7.6.5
>>
>> _______________________________________________
>> xfs mailing list
>> xfs-VZNHf3L845pBDgjK7y7TUQ@public.gmane.org
>> http://oss.sgi.com/mailman/listinfo/xfs
> ---end quoted text---



-- 
Regards,

Zhi Yong Wu

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

* Re: [PATCH v2 0/3] xfs: add O_TMPFILE support
  2013-12-26  8:51 ` Christoph Hellwig
  2013-12-28 10:04     ` Zhi Yong Wu
@ 2014-01-07 20:49   ` Ben Myers
  2014-01-07 20:51     ` Christoph Hellwig
  1 sibling, 1 reply; 14+ messages in thread
From: Ben Myers @ 2014-01-07 20:49 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: Zhi Yong Wu, linux-api, Zhi Yong Wu, xfs

Hey Christoph,

On Thu, Dec 26, 2013 at 12:51:34AM -0800, Christoph Hellwig wrote:
> Both patches looks good to me,
> 
> Reviewed-by: Christoph Hellwig <hch@lst.de>
> 
> But now we need to make sure we can exercise it, which will need
> support for tmpfile and flink commands in xfs_io.

Are you suggesting that we hold off on this until such time as the tests are
completed?
 
Thanks,
	Ben

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* Re: [PATCH v2 0/3] xfs: add O_TMPFILE support
  2014-01-07 20:49   ` Ben Myers
@ 2014-01-07 20:51     ` Christoph Hellwig
  0 siblings, 0 replies; 14+ messages in thread
From: Christoph Hellwig @ 2014-01-07 20:51 UTC (permalink / raw)
  To: Ben Myers; +Cc: Christoph Hellwig, Zhi Yong Wu, xfs, Zhi Yong Wu, linux-api

On Tue, Jan 07, 2014 at 02:49:38PM -0600, Ben Myers wrote:
> Are you suggesting that we hold off on this until such time as the tests are
> completed?

Yes.  Code that doesn't come with proper test coverage usually tends to
be buggy.

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* [PATCH v2 2/3] xfs: add O_TMPFILE support
  2013-12-18  0:15 Zhi Yong Wu
@ 2013-12-18  0:15 ` Zhi Yong Wu
  0 siblings, 0 replies; 14+ messages in thread
From: Zhi Yong Wu @ 2013-12-18  0:15 UTC (permalink / raw)
  To: xfs; +Cc: Zhi Yong Wu

From: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>

Add two functions xfs_create_tmpfile() and xfs_vn_tmpfile()
to support O_TMPFILE file creation.

In contrast to xfs_create(), xfs_create_tmpfile() has a different
log reservation to the regular file creation because there is no
directory modification, and doesn't check if an entry can be added
to the directory, but the reservation quotas is required appropriately,
and finally its inode is added to the unlinked list.

xfs_vn_tmpfile() add one O_TMPFILE method to VFS interface and directly
invoke xfs_create_tmpfile().

Signed-off-by: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>
---
 fs/xfs/xfs_inode.c      |  107 +++++++++++++++++++++++++++++++++++++++++++++++
 fs/xfs/xfs_inode.h      |    2 +
 fs/xfs/xfs_iops.c       |   16 +++++++
 fs/xfs/xfs_shared.h     |    4 +-
 fs/xfs/xfs_trans_resv.c |   36 +++++++++++++++-
 fs/xfs/xfs_trans_resv.h |    2 +
 6 files changed, 164 insertions(+), 3 deletions(-)

diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index c79b875..ac133ea 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1333,6 +1333,113 @@ xfs_create(
 }
 
 int
+xfs_create_tmpfile(
+	struct xfs_inode	*dp,
+	struct dentry		*dentry,
+	umode_t			mode)
+{
+	struct xfs_mount	*mp = dp->i_mount;
+	struct xfs_inode	*ip = NULL;
+	struct xfs_trans	*tp = NULL;
+	int			error;
+	uint			cancel_flags = XFS_TRANS_RELEASE_LOG_RES;
+	prid_t                  prid;
+	struct xfs_dquot	*udqp = NULL;
+	struct xfs_dquot	*gdqp = NULL;
+	struct xfs_dquot	*pdqp = NULL;
+	struct xfs_trans_res	*tres;
+	uint			resblks;
+
+	if (XFS_FORCED_SHUTDOWN(mp))
+		return XFS_ERROR(EIO);
+
+	prid = xfs_get_initial_prid(dp);
+
+	/*
+	 * Make sure that we have allocated dquot(s) on disk.
+	 */
+	error = xfs_qm_vop_dqalloc(dp, xfs_kuid_to_uid(current_fsuid()),
+				xfs_kgid_to_gid(current_fsgid()), prid,
+				XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT,
+				&udqp, &gdqp, &pdqp);
+	if (error)
+		return error;
+
+	resblks = XFS_IALLOC_SPACE_RES(mp);
+	tp = xfs_trans_alloc(mp, XFS_TRANS_CREATE_TMPFILE);
+
+	tres = &M_RES(mp)->tr_create_tmpfile;
+	error = xfs_trans_reserve(tp, tres, resblks, 0);
+	if (error == ENOSPC) {
+		/* No space at all so try a "no-allocation" reservation */
+		resblks = 0;
+		error = xfs_trans_reserve(tp, tres, 0, 0);
+	}
+	if (error) {
+		cancel_flags = 0;
+		goto out_trans_cancel;
+	}
+
+	error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp,
+						pdqp, resblks, 1, 0);
+	if (error)
+		goto out_trans_cancel;
+
+	error = xfs_dir_ialloc(&tp, dp, mode, 1, 0,
+				prid, resblks > 0, &ip, NULL);
+	if (error) {
+		if (error == ENOSPC)
+			goto out_trans_cancel;
+		goto out_trans_abort;
+	}
+
+	if (mp->m_flags & XFS_MOUNT_WSYNC)
+		xfs_trans_set_sync(tp);
+
+	/*
+	 * Attach the dquot(s) to the inodes and modify them incore.
+	 * These ids of the inode couldn't have changed since the new
+	 * inode has been locked ever since it was created.
+	 */
+	xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp);
+
+	ip->i_d.di_nlink--;
+	d_tmpfile(dentry, VFS_I(ip));
+	error = xfs_iunlink(tp, ip);
+	if (error)
+		goto out_trans_abort;
+
+	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
+	if (error)
+		goto out_release_inode;
+
+	xfs_qm_dqrele(udqp);
+	xfs_qm_dqrele(gdqp);
+	xfs_qm_dqrele(pdqp);
+
+	return 0;
+
+ out_trans_abort:
+	cancel_flags |= XFS_TRANS_ABORT;
+ out_trans_cancel:
+	xfs_trans_cancel(tp, cancel_flags);
+ out_release_inode:
+	/*
+	 * Wait until after the current transaction is aborted to
+	 * release the inode.  This prevents recursive transactions
+	 * and deadlocks from xfs_inactive.
+	 */
+	if (ip)
+		IRELE(ip);
+
+	xfs_qm_dqrele(udqp);
+	xfs_qm_dqrele(gdqp);
+	xfs_qm_dqrele(pdqp);
+
+	return error;
+}
+
+int
 xfs_link(
 	xfs_inode_t		*tdp,
 	xfs_inode_t		*sip,
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 6c58349..3a97820 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -333,6 +333,8 @@ int		xfs_lookup(struct xfs_inode *dp, struct xfs_name *name,
 			   struct xfs_inode **ipp, struct xfs_name *ci_name);
 int		xfs_create(struct xfs_inode *dp, struct xfs_name *name,
 			   umode_t mode, xfs_dev_t rdev, struct xfs_inode **ipp);
+int		xfs_create_tmpfile(struct xfs_inode *dp, struct dentry *dentry,
+			   umode_t mode);
 int		xfs_remove(struct xfs_inode *dp, struct xfs_name *name,
 			   struct xfs_inode *ip);
 int		xfs_link(struct xfs_inode *tdp, struct xfs_inode *sip,
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index 27e0e54..5ea7f85 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -39,6 +39,7 @@
 #include "xfs_da_btree.h"
 #include "xfs_dir2_priv.h"
 #include "xfs_dinode.h"
+#include "xfs_trans_space.h"
 
 #include <linux/capability.h>
 #include <linux/xattr.h>
@@ -1050,6 +1051,19 @@ xfs_vn_fiemap(
 	return 0;
 }
 
+STATIC int
+xfs_vn_tmpfile(
+	struct inode	*dir,
+	struct dentry	*dentry,
+	umode_t		mode)
+{
+	int		error;
+
+	error = xfs_create_tmpfile(XFS_I(dir), dentry, mode);
+
+	return -error;
+}
+
 static const struct inode_operations xfs_inode_operations = {
 	.get_acl		= xfs_get_acl,
 	.getattr		= xfs_vn_getattr,
@@ -1086,6 +1100,7 @@ static const struct inode_operations xfs_dir_inode_operations = {
 	.removexattr		= generic_removexattr,
 	.listxattr		= xfs_vn_listxattr,
 	.update_time		= xfs_vn_update_time,
+	.tmpfile		= xfs_vn_tmpfile,
 };
 
 static const struct inode_operations xfs_dir_ci_inode_operations = {
@@ -1112,6 +1127,7 @@ static const struct inode_operations xfs_dir_ci_inode_operations = {
 	.removexattr		= generic_removexattr,
 	.listxattr		= xfs_vn_listxattr,
 	.update_time		= xfs_vn_update_time,
+	.tmpfile		= xfs_vn_tmpfile,
 };
 
 static const struct inode_operations xfs_symlink_inode_operations = {
diff --git a/fs/xfs/xfs_shared.h b/fs/xfs/xfs_shared.h
index 8c5035a1..4484e51 100644
--- a/fs/xfs/xfs_shared.h
+++ b/fs/xfs/xfs_shared.h
@@ -104,7 +104,8 @@ extern const struct xfs_buf_ops xfs_symlink_buf_ops;
 #define	XFS_TRANS_SB_COUNT		41
 #define	XFS_TRANS_CHECKPOINT		42
 #define	XFS_TRANS_ICREATE		43
-#define	XFS_TRANS_TYPE_MAX		43
+#define	XFS_TRANS_CREATE_TMPFILE	44
+#define	XFS_TRANS_TYPE_MAX		44
 /* new transaction types need to be reflected in xfs_logprint(8) */
 
 #define XFS_TRANS_TYPES \
@@ -112,6 +113,7 @@ extern const struct xfs_buf_ops xfs_symlink_buf_ops;
 	{ XFS_TRANS_SETATTR_SIZE,	"SETATTR_SIZE" }, \
 	{ XFS_TRANS_INACTIVE,		"INACTIVE" }, \
 	{ XFS_TRANS_CREATE,		"CREATE" }, \
+	{ XFS_TRANS_CREATE_TMPFILE,	"CREATE_TMPFILE" }, \
 	{ XFS_TRANS_CREATE_TRUNC,	"CREATE_TRUNC" }, \
 	{ XFS_TRANS_TRUNCATE_FILE,	"TRUNCATE_FILE" }, \
 	{ XFS_TRANS_REMOVE,		"REMOVE" }, \
diff --git a/fs/xfs/xfs_trans_resv.c b/fs/xfs/xfs_trans_resv.c
index 2fd59c0..bd3b4b7 100644
--- a/fs/xfs/xfs_trans_resv.c
+++ b/fs/xfs/xfs_trans_resv.c
@@ -229,6 +229,18 @@ xfs_calc_link_reservation(
 }
 
 /*
+ * For adding an inode to unlinked list we can modify:
+ *    the agi hash list: sector size
+ *    the unlinked inode: inode size
+ */
+STATIC uint
+xfs_calc_iunlink_add_reservation(xfs_mount_t *mp)
+{
+	return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) +
+		xfs_calc_inode_res(mp, 1);
+}
+
+/*
  * For removing a directory entry we can modify:
  *    the parent directory inode: inode size
  *    the removed inode: inode size
@@ -245,10 +257,11 @@ xfs_calc_remove_reservation(
 	struct xfs_mount	*mp)
 {
 	return XFS_DQUOT_LOGRES(mp) +
-		MAX((xfs_calc_inode_res(mp, 2) +
+		xfs_calc_iunlink_add_reservation(mp) +
+		MAX((xfs_calc_inode_res(mp, 1) +
 		     xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp),
 				      XFS_FSB_TO_B(mp, 1))),
-		    (xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) +
+		    (xfs_calc_buf_res(4, mp->m_sb.sb_sectsize) +
 		     xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 2),
 				      XFS_FSB_TO_B(mp, 1))));
 }
@@ -343,6 +356,20 @@ xfs_calc_create_reservation(
 
 }
 
+STATIC uint
+xfs_calc_create_tmpfile_reservation(
+	struct xfs_mount        *mp)
+{
+	uint	res = XFS_DQUOT_LOGRES(mp);
+
+	if (xfs_sb_version_hascrc(&mp->m_sb))
+		res += xfs_calc_icreate_resv_alloc(mp);
+	else
+		res += xfs_calc_create_resv_alloc(mp);
+
+	return res + xfs_calc_iunlink_add_reservation(mp);
+}
+
 /*
  * Making a new directory is the same as creating a new file.
  */
@@ -729,6 +756,11 @@ xfs_trans_resv_calc(
 	resp->tr_create.tr_logcount = XFS_CREATE_LOG_COUNT;
 	resp->tr_create.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
 
+	resp->tr_create_tmpfile.tr_logres =
+			xfs_calc_create_tmpfile_reservation(mp);
+	resp->tr_create_tmpfile.tr_logcount = XFS_CREATE_TMPFILE_LOG_COUNT;
+	resp->tr_create_tmpfile.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
+
 	resp->tr_mkdir.tr_logres = xfs_calc_mkdir_reservation(mp);
 	resp->tr_mkdir.tr_logcount = XFS_MKDIR_LOG_COUNT;
 	resp->tr_mkdir.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
diff --git a/fs/xfs/xfs_trans_resv.h b/fs/xfs/xfs_trans_resv.h
index de7de9a..285621d 100644
--- a/fs/xfs/xfs_trans_resv.h
+++ b/fs/xfs/xfs_trans_resv.h
@@ -38,6 +38,7 @@ struct xfs_trans_resv {
 	struct xfs_trans_res	tr_remove;	/* unlink trans */
 	struct xfs_trans_res	tr_symlink;	/* symlink trans */
 	struct xfs_trans_res	tr_create;	/* create trans */
+	struct xfs_trans_res	tr_create_tmpfile; /* create O_TMPFILE trans */
 	struct xfs_trans_res	tr_mkdir;	/* mkdir trans */
 	struct xfs_trans_res	tr_ifree;	/* inode free trans */
 	struct xfs_trans_res	tr_ichange;	/* inode update trans */
@@ -100,6 +101,7 @@ struct xfs_trans_resv {
 #define	XFS_ITRUNCATE_LOG_COUNT		2
 #define XFS_INACTIVE_LOG_COUNT		2
 #define	XFS_CREATE_LOG_COUNT		2
+#define	XFS_CREATE_TMPFILE_LOG_COUNT	2
 #define	XFS_MKDIR_LOG_COUNT		3
 #define	XFS_SYMLINK_LOG_COUNT		3
 #define	XFS_REMOVE_LOG_COUNT		2
-- 
1.7.6.5

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

end of thread, other threads:[~2014-01-07 20:51 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-12-18  0:22 [PATCH v2 0/3] xfs: add O_TMPFILE support Zhi Yong Wu
2013-12-18  0:22 ` [PATCH v2 1/3] xfs: factor prid related codes into xfs_get_initial_prid() Zhi Yong Wu
2013-12-18  0:22 ` [PATCH v2 2/3] xfs: add O_TMPFILE support Zhi Yong Wu
2013-12-24  0:55   ` Dave Chinner
2013-12-24  1:58     ` Zhi Yong Wu
2013-12-18  0:22 ` [PATCH v2 3/3] xfs: allow linkat() on O_TMPFILE files Zhi Yong Wu
2013-12-24  0:55   ` Dave Chinner
2013-12-23  1:45 ` [PATCH v2 0/3] xfs: add O_TMPFILE support Zhi Yong Wu
2013-12-26  8:51 ` Christoph Hellwig
2013-12-28 10:04   ` Zhi Yong Wu
2013-12-28 10:04     ` Zhi Yong Wu
2014-01-07 20:49   ` Ben Myers
2014-01-07 20:51     ` Christoph Hellwig
  -- strict thread matches above, loose matches on Subject: below --
2013-12-18  0:15 Zhi Yong Wu
2013-12-18  0:15 ` [PATCH v2 2/3] " Zhi Yong Wu

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.