/*
* Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
* Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
*/
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/completion.h>
#include <linux/buffer_head.h>
#include <linux/namei.h>
#include <linux/utsname.h>
#include <linux/mm.h>
#include <linux/xattr.h>
#include <linux/posix_acl.h>
#include <asm/semaphore.h>
#include <asm/uaccess.h>
#include "gfs2.h"
#include "acl.h"
#include "bmap.h"
#include "dir.h"
#include "eaops.h"
#include "eattr.h"
#include "glock.h"
#include "inode.h"
#include "meta_io.h"
#include "ops_dentry.h"
#include "ops_inode.h"
#include "page.h"
#include "quota.h"
#include "rgrp.h"
#include "trans.h"
#include "unlinked.h"
/**
* gfs2_create - Create a file
* @dir: The directory in which to create the file
* @dentry: The dentry of the new file
* @mode: The mode of the new file
*
* Returns: errno
*/
static int gfs2_create(struct inode *dir, struct dentry *dentry,
int mode, struct nameidata *nd)
{
struct gfs2_inode *dip = get_v2ip(dir), *ip;
struct gfs2_sbd *sdp = dip->i_sbd;
struct gfs2_holder ghs[2];
struct inode *inode;
int new = 1;
int error;
atomic_inc(&sdp->sd_ops_inode);
gfs2_holder_init(dip->i_gl, 0, 0, ghs);
for (;;) {
error = gfs2_createi(ghs, &dentry->d_name, S_IFREG | mode);
if (!error) {
ip = get_gl2ip(ghs[1].gh_gl);
gfs2_trans_end(sdp);
if (dip->i_alloc.al_rgd)
gfs2_inplace_release(dip);
gfs2_quota_unlock(dip);
gfs2_alloc_put(dip);
gfs2_glock_dq_uninit_m(2, ghs);
break;
} else if (error != -EEXIST ||
(nd->intent.open.flags & O_EXCL)) {
gfs2_holder_uninit(ghs);
return error;
}
error = gfs2_lookupi(dip, &dentry->d_name, 0, &ip);
if (!error) {
new = 0;
gfs2_holder_uninit(ghs);
break;
} else if (error != -ENOENT) {
gfs2_holder_uninit(ghs);
return error;
}
}
inode = gfs2_ip2v(ip);
gfs2_inode_put(ip);
if (!inode)
return -ENOMEM;
d_instantiate(dentry, inode);
if <