__releases(dentry->d_inode->i_lock)
{
struct inode *inode = dentry->d_inode;
-- bool hashed = !d_unhashed(dentry);
-- if (hashed)
-- raw_write_seqcount_begin(&dentry->d_seq);
++ raw_write_seqcount_begin(&dentry->d_seq);
__d_clear_type_and_inode(dentry);
hlist_del_init(&dentry->d_u.d_alias);
-- if (hashed)
-- raw_write_seqcount_end(&dentry->d_seq);
++ raw_write_seqcount_end(&dentry->d_seq);
spin_unlock(&dentry->d_lock);
spin_unlock(&inode->i_lock);
if (!inode->i_nlink)
if (dentry->d_lockref.count > 1) {
dentry->d_lockref.count--;
spin_unlock(&dentry->d_lock);
- - return 1;
+ + return true;
}
- - return 0;
+ + return false;
}
/*
* If we weren't the last ref, we're done.
*/
if (ret)
- - return 1;
+ + return true;
/*
* Careful, careful. The reference count went down
/* Nothing to do? Dropping the reference was all we needed? */
if (d_flags == (DCACHE_REFERENCED | DCACHE_LRU_LIST) && !d_unhashed(dentry))
- - return 1;
+ + return true;
/*
* Not the fast normal case? Get the lock. We've already decremented
*/
if (dentry->d_lockref.count) {
spin_unlock(&dentry->d_lock);
- - return 1;
+ + return true;
}
/*
* set it to 1.
*/
dentry->d_lockref.count = 1;
- - return 0;
+ + return false;
}
spin_lock(&inode->i_lock);
__d_instantiate(entry, inode);
WARN_ON(!(inode->i_state & I_NEW));
-- inode->i_state &= ~I_NEW;
++ inode->i_state &= ~I_NEW & ~I_CREATING;
smp_mb();
wake_up_bit(&inode->i_state, __I_NEW);
spin_unlock(&inode->i_lock);
}
EXPORT_SYMBOL(d_instantiate_new);
--/**
-- * d_instantiate_no_diralias - instantiate a non-aliased dentry
-- * @entry: dentry to complete
-- * @inode: inode to attach to this dentry
-- *
-- * Fill in inode information in the entry. If a directory alias is found, then
-- * return an error (and drop inode). Together with d_materialise_unique() this
-- * guarantees that a directory inode may never have more than one alias.
-- */
--int d_instantiate_no_diralias(struct dentry *entry, struct inode *inode)
--{
-- BUG_ON(!hlist_unhashed(&entry->d_u.d_alias));
--
-- security_d_instantiate(entry, inode);
-- spin_lock(&inode->i_lock);
-- if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry)) {
-- spin_unlock(&inode->i_lock);
-- iput(inode);
-- return -EBUSY;
-- }
-- __d_instantiate(entry, inode);
-- spin_unlock(&inode->i_lock);
--
-- return 0;
--}
--EXPORT_SYMBOL(d_instantiate_no_diralias);
--
struct dentry *d_make_root(struct inode *root_inode)
{
struct dentry *res = NULL;
if (root_inode) {
res = d_alloc_anon(root_inode->i_sb);
-- if (res)
++ if (res) {
++ res->d_flags |= DCACHE_RCUACCESS;
d_instantiate(res, root_inode);
-- else
++ } else {
iput(root_inode);
++ }
}
return res;
}
}
EXPORT_SYMBOL(d_exact_alias);
-- /**
-- * dentry_update_name_case - update case insensitive dentry with a new name
-- * @dentry: dentry to be updated
-- * @name: new name
-- *
-- * Update a case insensitive dentry with new case of name.
-- *
-- * dentry must have been returned by d_lookup with name @name. Old and new
-- * name lengths must match (ie. no d_compare which allows mismatched name
-- * lengths).
-- *
-- * Parent inode i_mutex must be held over d_lookup and into this call (to
-- * keep renames and concurrent inserts, and readdir(2) away).
-- */
-- void dentry_update_name_case(struct dentry *dentry, const struct qstr *name)
-- {
-- BUG_ON(!inode_is_locked(dentry->d_parent->d_inode));
-- BUG_ON(dentry->d_name.len != name->len); /* d_lookup gives this */
--
-- spin_lock(&dentry->d_lock);
-- write_seqcount_begin(&dentry->d_seq);
-- memcpy((unsigned char *)dentry->d_name.name, name->name, name->len);
-- write_seqcount_end(&dentry->d_seq);
-- spin_unlock(&dentry->d_lock);
-- }
-- EXPORT_SYMBOL(dentry_update_name_case);
--
static void swap_names(struct dentry *dentry, struct dentry *target)
{
if (unlikely(dname_external(target))) {
{
int err;
++ if (IS_ERR(name))
++ return PTR_ERR(name);
while (*name=='/')
name++;
if (!*name)
}
}
++/* must be paired with terminate_walk() */
static const char *path_init(struct nameidata *nd, unsigned flags)
{
const char *s = nd->name->name;
if (!*s)
flags &= ~LOOKUP_RCU;
++ if (flags & LOOKUP_RCU)
++ rcu_read_lock();
nd->last_type = LAST_ROOT; /* if there are only slashes... */
nd->flags = flags | LOOKUP_JUMPED | LOOKUP_PARENT;
nd->path = nd->root;
nd->inode = inode;
if (flags & LOOKUP_RCU) {
-- rcu_read_lock();
nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq);
nd->root_seq = nd->seq;
nd->m_seq = read_seqbegin(&mount_lock);
nd->m_seq = read_seqbegin(&mount_lock);
if (*s == '/') {
-- if (flags & LOOKUP_RCU)
-- rcu_read_lock();
set_root(nd);
if (likely(!nd_jump_root(nd)))
return s;
-- nd->root.mnt = NULL;
-- rcu_read_unlock();
return ERR_PTR(-ECHILD);
} else if (nd->dfd == AT_FDCWD) {
if (flags & LOOKUP_RCU) {
struct fs_struct *fs = current->fs;
unsigned seq;
-- rcu_read_lock();
--
do {
seq = read_seqcount_begin(&fs->seq);
nd->path = fs->pwd;
dentry = f.file->f_path.dentry;
-- if (*s) {
-- if (!d_can_lookup(dentry)) {
-- fdput(f);
-- return ERR_PTR(-ENOTDIR);
-- }
++ if (*s && unlikely(!d_can_lookup(dentry))) {
++ fdput(f);
++ return ERR_PTR(-ENOTDIR);
}
nd->path = f.file->f_path;
if (flags & LOOKUP_RCU) {
-- rcu_read_lock();
nd->inode = nd->path.dentry->d_inode;
nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq);
} else {
const char *s = path_init(nd, flags);
int err;
-- if (IS_ERR(s))
-- return PTR_ERR(s);
--
-- if (unlikely(flags & LOOKUP_DOWN)) {
++ if (unlikely(flags & LOOKUP_DOWN) && !IS_ERR(s)) {
err = handle_lookup_down(nd);
-- if (unlikely(err < 0)) {
-- terminate_walk(nd);
-- return err;
-- }
++ if (unlikely(err < 0))
++ s = ERR_PTR(err);
}
while (!(err = link_path_walk(s, nd))
&& ((err = lookup_last(nd)) > 0)) {
s = trailing_symlink(nd);
-- if (IS_ERR(s)) {
-- err = PTR_ERR(s);
-- break;
-- }
}
if (!err)
err = complete_walk(nd);
struct path *parent)
{
const char *s = path_init(nd, flags);
-- int err;
-- if (IS_ERR(s))
-- return PTR_ERR(s);
-- err = link_path_walk(s, nd);
++ int err = link_path_walk(s, nd);
if (!err)
err = complete_walk(nd);
if (!err) {
{
const char *s = path_init(nd, flags);
int err;
-- if (IS_ERR(s))
-- return PTR_ERR(s);
++
while (!(err = link_path_walk(s, nd)) &&
(err = mountpoint_last(nd)) > 0) {
s = trailing_symlink(nd);
-- if (IS_ERR(s)) {
-- err = PTR_ERR(s);
-- break;
-- }
}
if (!err) {
*path = nd->path;
* Returns 0 if successful. The file will have been created and attached to
* @file by the filesystem calling finish_open().
*
-- * Returns 1 if the file was looked up only or didn't need creating. The
-- * caller will need to perform the open themselves. @path will have been
-- * updated to point to the new dentry. This may be negative.
++ * If the file was looked up only or didn't need creating, FMODE_OPENED won't
++ * be set. The caller will need to perform the open themselves. @path will
++ * have been updated to point to the new dentry. This may be negative.
*
* Returns an error code otherwise.
*/
static int atomic_open(struct nameidata *nd, struct dentry *dentry,
struct path *path, struct file *file,
const struct open_flags *op,
-- int open_flag, umode_t mode,
-- int *opened)
++ int open_flag, umode_t mode)
{
struct dentry *const DENTRY_NOT_SET = (void *) -1UL;
struct inode *dir = nd->path.dentry->d_inode;
file->f_path.dentry = DENTRY_NOT_SET;
file->f_path.mnt = nd->path.mnt;
error = dir->i_op->atomic_open(dir, dentry, file,
-- open_to_namei_flags(open_flag),
-- mode, opened);
++ open_to_namei_flags(open_flag), mode);
d_lookup_done(dentry);
if (!error) {
-- /*
-- * We didn't have the inode before the open, so check open
-- * permission here.
-- */
-- int acc_mode = op->acc_mode;
-- if (*opened & FILE_CREATED) {
-- WARN_ON(!(open_flag & O_CREAT));
-- fsnotify_create(dir, dentry);
-- acc_mode = 0;
-- }
-- error = may_open(&file->f_path, acc_mode, open_flag);
-- if (WARN_ON(error > 0))
-- error = -EINVAL;
-- } else if (error > 0) {
-- if (WARN_ON(file->f_path.dentry == DENTRY_NOT_SET)) {
++ if (file->f_mode & FMODE_OPENED) {
++ /*
++ * We didn't have the inode before the open, so check open
++ * permission here.
++ */
++ int acc_mode = op->acc_mode;
++ if (file->f_mode & FMODE_CREATED) {
++ WARN_ON(!(open_flag & O_CREAT));
++ fsnotify_create(dir, dentry);
++ acc_mode = 0;
++ }
++ error = may_open(&file->f_path, acc_mode, open_flag);
++ if (WARN_ON(error > 0))
++ error = -EINVAL;
++ } else if (WARN_ON(file->f_path.dentry == DENTRY_NOT_SET)) {
error = -EIO;
} else {
if (file->f_path.dentry) {
dput(dentry);
dentry = file->f_path.dentry;
}
-- if (*opened & FILE_CREATED)
++ if (file->f_mode & FMODE_CREATED)
fsnotify_create(dir, dentry);
if (unlikely(d_is_negative(dentry))) {
error = -ENOENT;
} else {
path->dentry = dentry;
path->mnt = nd->path.mnt;
-- return 1;
++ return 0;
}
}
}
/*
* Look up and maybe create and open the last component.
*
-- * Must be called with i_mutex held on parent.
- *
- * Returns 0 if the file was successfully atomically created (if necessary) and
- * opened. In this case the file will be returned attached to @file.
- *
- * Returns 1 if the file was not completely opened at this time, though lookups
- * and creations will have been performed and the dentry returned in @path will
- * be positive upon return if O_CREAT was specified. If O_CREAT wasn't
- * specified then a negative dentry may be returned.
++ * Must be called with parent locked (exclusive in O_CREAT case).
*
- * Returns 0 if the file was successfully atomically created (if necessary) and
- * opened. In this case the file will be returned attached to @file.
- * An error code is returned otherwise.
++ * Returns 0 on success, that is, if
++ * the file was successfully atomically created (if necessary) and opened, or
++ * the file was not completely opened at this time, though lookups and
++ * creations were performed.
++ * These case are distinguished by presence of FMODE_OPENED on file->f_mode.
++ * In the latter case dentry returned in @path might be negative if O_CREAT
++ * hadn't been specified.
*
- * Returns 1 if the file was not completely opened at this time, though lookups
- * and creations will have been performed and the dentry returned in @path will
- * be positive upon return if O_CREAT was specified. If O_CREAT wasn't
- * specified then a negative dentry may be returned.
- *
- * An error code is returned otherwise.
- *
-- * FILE_CREATE will be set in @*opened if the dentry was created and will be
-- * cleared otherwise prior to returning.
++ * An error code is returned on failure.
*/
static int lookup_open(struct nameidata *nd, struct path *path,
struct file *file,
const struct open_flags *op,
-- bool got_write, int *opened)
++ bool got_write)
{
struct dentry *dir = nd->path.dentry;
struct inode *dir_inode = dir->d_inode;
if (unlikely(IS_DEADDIR(dir_inode)))
return -ENOENT;
-- *opened &= ~FILE_CREATED;
++ file->f_mode &= ~FMODE_CREATED;
dentry = d_lookup(dir, &nd->last);
for (;;) {
if (!dentry) {
if (dir_inode->i_op->atomic_open) {
error = atomic_open(nd, dentry, path, file, op, open_flag,
-- mode, opened);
++ mode);
if (unlikely(error == -ENOENT) && create_error)
error = create_error;
return error;
/* Negative dentry, just create the file */
if (!dentry->d_inode && (open_flag & O_CREAT)) {
-- *opened |= FILE_CREATED;
++ file->f_mode |= FMODE_CREATED;
audit_inode_child(dir_inode, dentry, AUDIT_TYPE_CHILD_CREATE);
if (!dir_inode->i_op->create) {
error = -EACCES;
out_no_open:
path->dentry = dentry;
path->mnt = nd->path.mnt;
-- return 1;
++ return 0;
out_dput:
dput(dentry);
* Handle the last step of open()
*/
static int do_last(struct nameidata *nd,
-- struct file *file, const struct open_flags *op,
-- int *opened)
++ struct file *file, const struct open_flags *op)
{
struct dentry *dir = nd->path.dentry;
int open_flag = op->open_flag;
inode_lock(dir->d_inode);
else
inode_lock_shared(dir->d_inode);
-- error = lookup_open(nd, &path, file, op, got_write, opened);
++ error = lookup_open(nd, &path, file, op, got_write);
if (open_flag & O_CREAT)
inode_unlock(dir->d_inode);
else
inode_unlock_shared(dir->d_inode);
-- if (error <= 0) {
-- if (error)
-- goto out;
++ if (error)
++ goto out;
-- if ((*opened & FILE_CREATED) ||
++ if (file->f_mode & FMODE_OPENED) {
++ if ((file->f_mode & FMODE_CREATED) ||
!S_ISREG(file_inode(file)->i_mode))
will_truncate = false;
goto opened;
}
-- if (*opened & FILE_CREATED) {
++ if (file->f_mode & FMODE_CREATED) {
/* Don't check for write permission, don't truncate */
open_flag &= ~O_TRUNC;
will_truncate = false;
error = may_open(&nd->path, acc_mode, open_flag);
if (error)
goto out;
-- BUG_ON(*opened & FILE_OPENED); /* once it's opened, it's opened */
-- error = vfs_open(&nd->path, file, current_cred());
++ BUG_ON(file->f_mode & FMODE_OPENED); /* once it's opened, it's opened */
++ error = vfs_open(&nd->path, file);
if (error)
goto out;
-- *opened |= FILE_OPENED;
opened:
-- error = open_check_o_direct(file);
-- if (!error)
-- error = ima_file_check(file, op->acc_mode, *opened);
++ error = ima_file_check(file, op->acc_mode);
if (!error && will_truncate)
error = handle_truncate(file);
out:
-- if (unlikely(error) && (*opened & FILE_OPENED))
-- fput(file);
if (unlikely(error > 0)) {
WARN_ON(1);
error = -EINVAL;
static int do_tmpfile(struct nameidata *nd, unsigned flags,
const struct open_flags *op,
-- struct file *file, int *opened)
++ struct file *file)
{
struct dentry *child;
struct path path;
if (error)
goto out2;
file->f_path.mnt = path.mnt;
-- error = finish_open(file, child, NULL, opened);
-- if (error)
-- goto out2;
-- error = open_check_o_direct(file);
-- if (error)
-- fput(file);
++ error = finish_open(file, child, NULL);
out2:
mnt_drop_write(path.mnt);
out:
int error = path_lookupat(nd, flags, &path);
if (!error) {
audit_inode(nd->name, path.dentry, 0);
-- error = vfs_open(&path, file, current_cred());
++ error = vfs_open(&path, file);
path_put(&path);
}
return error;
static struct file *path_openat(struct nameidata *nd,
const struct open_flags *op, unsigned flags)
{
-- const char *s;
struct file *file;
-- int opened = 0;
int error;
-- file = get_empty_filp();
++ file = alloc_empty_file(op->open_flag, current_cred());
if (IS_ERR(file))
return file;
-- file->f_flags = op->open_flag;
--
if (unlikely(file->f_flags & __O_TMPFILE)) {
-- error = do_tmpfile(nd, flags, op, file, &opened);
-- goto out2;
-- }
--
-- if (unlikely(file->f_flags & O_PATH)) {
++ error = do_tmpfile(nd, flags, op, file);
++ } else if (unlikely(file->f_flags & O_PATH)) {
error = do_o_path(nd, flags, file);
-- if (!error)
-- opened |= FILE_OPENED;
-- goto out2;
-- }
--
-- s = path_init(nd, flags);
-- if (IS_ERR(s)) {
-- put_filp(file);
-- return ERR_CAST(s);
-- }
-- while (!(error = link_path_walk(s, nd)) &&
-- (error = do_last(nd, file, op, &opened)) > 0) {
-- nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);
-- s = trailing_symlink(nd);
-- if (IS_ERR(s)) {
-- error = PTR_ERR(s);
-- break;
++ } else {
++ const char *s = path_init(nd, flags);
++ while (!(error = link_path_walk(s, nd)) &&
++ (error = do_last(nd, file, op)) > 0) {
++ nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);
++ s = trailing_symlink(nd);
}
++ terminate_walk(nd);
}
-- terminate_walk(nd);
--out2:
-- if (!(opened & FILE_OPENED)) {
-- BUG_ON(!error);
-- put_filp(file);
++ if (likely(!error)) {
++ if (likely(file->f_mode & FMODE_OPENED))
++ return file;
++ WARN_ON(1);
++ error = -EINVAL;
}
-- if (unlikely(error)) {
-- if (error == -EOPENSTALE) {
-- if (flags & LOOKUP_RCU)
-- error = -ECHILD;
-- else
-- error = -ESTALE;
-- }
-- file = ERR_PTR(error);
++ fput(file);
++ if (error == -EOPENSTALE) {
++ if (flags & LOOKUP_RCU)
++ error = -ECHILD;
++ else
++ error = -ESTALE;
}
-- return file;
++ return ERR_PTR(error);
}
struct file *do_filp_open(int dfd, struct filename *pathname,
return len;
}
- -/*
- - * A helper for ->readlink(). This should be used *ONLY* for symlinks that
- - * have ->get_link() not calling nd_jump_link(). Using (or not using) it
- - * for any given inode is up to filesystem.
- - */
- -static int generic_readlink(struct dentry *dentry, char __user *buffer,
- - int buflen)
- -{
- - DEFINE_DELAYED_CALL(done);
- - struct inode *inode = d_inode(dentry);
- - const char *link = inode->i_link;
- - int res;
- -
- - if (!link) {
- - link = inode->i_op->get_link(dentry, inode, &done);
- - if (IS_ERR(link))
- - return PTR_ERR(link);
- - }
- - res = readlink_copy(buffer, buflen, link);
- - do_delayed_call(&done);
- - return res;
- -}
- -
/**
* vfs_readlink - copy symlink body into userspace buffer
* @dentry: dentry on which to get symbolic link
int vfs_readlink(struct dentry *dentry, char __user *buffer, int buflen)
{
struct inode *inode = d_inode(dentry);
+ + DEFINE_DELAYED_CALL(done);
+ + const char *link;
+ + int res;
if (unlikely(!(inode->i_opflags & IOP_DEFAULT_READLINK))) {
if (unlikely(inode->i_op->readlink))
spin_unlock(&inode->i_lock);
}
- - return generic_readlink(dentry, buffer, buflen);
+ + link = inode->i_link;
+ + if (!link) {
+ + link = inode->i_op->get_link(dentry, inode, &done);
+ + if (IS_ERR(link))
+ + return PTR_ERR(link);
+ + }
+ + res = readlink_copy(buffer, buflen, link);
+ + do_delayed_call(&done);
+ + return res;
}
EXPORT_SYMBOL(vfs_readlink);
/* Has write method(s) */
#define FMODE_CAN_WRITE ((__force fmode_t)0x40000)
++#define FMODE_OPENED ((__force fmode_t)0x80000)
++#define FMODE_CREATED ((__force fmode_t)0x100000)
++
/* File was opened by fanotify and shouldn't generate fanotify events */
#define FMODE_NONOTIFY ((__force fmode_t)0x4000000)
/*
* Write life time hint values.
+ + * Stored in struct inode as u8.
*/
enum rw_hint {
WRITE_LIFE_NOT_SET = 0,
struct timespec64 i_ctime;
spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */
unsigned short i_bytes;
- - unsigned int i_blkbits;
- - enum rw_hint i_write_hint;
+ + u8 i_blkbits;
+ + u8 i_write_hint;
blkcnt_t i_blocks;
#ifdef __NEED_I_SIZE_ORDERED
return hlist_unhashed(&inode->i_hash);
}
++/*
++ * __mark_inode_dirty expects inodes to be hashed. Since we don't
++ * want special inodes in the fileset inode space, we make them
++ * appear hashed, but do not put on any lists. hlist_del()
++ * will work fine and require no locking.
++ */
++static inline void inode_fake_hash(struct inode *inode)
++{
++ hlist_add_fake(&inode->i_hash);
++}
++
/*
* inode->i_mutex nesting subclasses for the lock validator:
*
int (*iterate) (struct file *, struct dir_context *);
int (*iterate_shared) (struct file *, struct dir_context *);
__poll_t (*poll) (struct file *, struct poll_table_struct *);
-- struct wait_queue_head * (*get_poll_head)(struct file *, __poll_t);
-- __poll_t (*poll_mask) (struct file *, __poll_t);
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
int (*mmap) (struct file *, struct vm_area_struct *);
int (*update_time)(struct inode *, struct timespec64 *, int);
int (*atomic_open)(struct inode *, struct dentry *,
struct file *, unsigned open_flag,
-- umode_t create_mode, int *opened);
++ umode_t create_mode);
int (*tmpfile) (struct inode *, struct dentry *, umode_t);
int (*set_acl)(struct inode *, struct posix_acl *, int);
} ____cacheline_aligned;
* I_OVL_INUSE Used by overlayfs to get exclusive ownership on upper
* and work dirs among overlayfs mounts.
*
++ * I_CREATING New object's inode in the middle of setting up.
++ *
* Q: What is the difference between I_WILL_FREE and I_FREEING?
*/
#define I_DIRTY_SYNC (1 << 0)
#define __I_DIRTY_TIME_EXPIRED 12
#define I_DIRTY_TIME_EXPIRED (1 << __I_DIRTY_TIME_EXPIRED)
#define I_WB_SWITCH (1 << 13)
--#define I_OVL_INUSE (1 << 14)
++#define I_OVL_INUSE (1 << 14)
++#define I_CREATING (1 << 15)
#define I_DIRTY_INODE (I_DIRTY_SYNC | I_DIRTY_DATASYNC)
#define I_DIRTY (I_DIRTY_INODE | I_DIRTY_PAGES)
extern struct file *file_open_root(struct dentry *, struct vfsmount *,
const char *, int, umode_t);
extern struct file * dentry_open(const struct path *, int, const struct cred *);
++static inline struct file *file_clone_open(struct file *file)
++{
++ return dentry_open(&file->f_path, file->f_flags, file->f_cred);
++}
extern int filp_close(struct file *, fl_owner_t id);
extern struct filename *getname_flags(const char __user *, int, int *);
extern struct filename *getname_kernel(const char *);
extern void putname(struct filename *name);
--enum {
-- FILE_CREATED = 1,
-- FILE_OPENED = 2
--};
extern int finish_open(struct file *file, struct dentry *dentry,
-- int (*open)(struct inode *, struct file *),
-- int *opened);
++ int (*open)(struct inode *, struct file *));
extern int finish_no_open(struct file *file, struct dentry *dentry);
/* fs/ioctl.c */
extern bool filemap_range_has_page(struct address_space *, loff_t lstart,
loff_t lend);
- -extern int __must_check file_fdatawait_range(struct file *file, loff_t lstart,
- - loff_t lend);
extern int filemap_write_and_wait(struct address_space *mapping);
extern int filemap_write_and_wait_range(struct address_space *mapping,
loff_t lstart, loff_t lend);
static inline void lockdep_annotate_inode_mutex_key(struct inode *inode) { };
#endif
extern void unlock_new_inode(struct inode *);
++extern void discard_new_inode(struct inode *);
extern unsigned int get_next_ino(void);
extern void evict_inodes(struct super_block *sb);