@@ -1335,12 +1335,15 @@ v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
static int
v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
- struct dentry *dentry)
+ struct dentry *dentry, int flags)
{
int retval;
char name[1 + U32_MAX_DIGITS + 2]; /* sign + number + \n + \0 */
struct p9_fid *oldfid;
+ if (flags)
+ return -EINVAL;
+
p9_debug(P9_DEBUG_VFS, " %lu,%pd,%pd\n",
dir->i_ino, dentry, old_dentry);
@@ -749,12 +749,15 @@ v9fs_vfs_symlink_dotl(struct inode *dir, struct dentry *dentry,
static int
v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir,
- struct dentry *dentry)
+ struct dentry *dentry, int flags)
{
int err;
struct p9_fid *dfid, *oldfid;
struct v9fs_session_info *v9ses;
+ if (flags)
+ return -EINVAL;
+
p9_debug(P9_DEBUG_VFS, "dir ino: %lu, old_name: %pd, new_name: %pd\n",
dir->i_ino, old_dentry, dentry);
@@ -171,7 +171,7 @@ extern int affs_create(struct inode *dir, struct dentry *dentry, umode_t mode, b
extern int affs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode);
extern int affs_rmdir(struct inode *dir, struct dentry *dentry);
extern int affs_link(struct dentry *olddentry, struct inode *dir,
- struct dentry *dentry);
+ struct dentry *dentry, int flags);
extern int affs_symlink(struct inode *dir, struct dentry *dentry,
const char *symname);
extern int affs_rename2(struct inode *old_dir, struct dentry *old_dentry,
@@ -388,10 +388,14 @@ affs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
}
int
-affs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
+affs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry,
+ int flags)
{
struct inode *inode = d_inode(old_dentry);
+ if (flags)
+ return -EINVAL;
+
pr_debug("%s(%lu, %lu, \"%pd\")\n", __func__, inode->i_ino, dir->i_ino,
dentry);
@@ -34,7 +34,7 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode);
static int afs_rmdir(struct inode *dir, struct dentry *dentry);
static int afs_unlink(struct inode *dir, struct dentry *dentry);
static int afs_link(struct dentry *from, struct inode *dir,
- struct dentry *dentry);
+ struct dentry *dentry, int flags);
static int afs_symlink(struct inode *dir, struct dentry *dentry,
const char *content);
static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
@@ -1641,7 +1641,7 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
* create a hard link between files in an AFS filesystem
*/
static int afs_link(struct dentry *from, struct inode *dir,
- struct dentry *dentry)
+ struct dentry *dentry, int flags)
{
struct afs_fs_cursor fc;
struct afs_status_cb *scb;
@@ -1650,6 +1650,9 @@ static int afs_link(struct dentry *from, struct inode *dir,
struct key *key;
int ret;
+ if (flags)
+ return -EINVAL;
+
_enter("{%llx:%llu},{%llx:%llu},{%pd}",
vnode->fid.vid, vnode->fid.vnode,
dvnode->fid.vid, dvnode->fid.vnode,
@@ -39,7 +39,7 @@ static struct dentry *bad_inode_lookup(struct inode *dir,
}
static int bad_inode_link (struct dentry *old_dentry, struct inode *dir,
- struct dentry *dentry)
+ struct dentry *dentry, int flags)
{
return -EIO;
}
@@ -144,13 +144,16 @@ static struct dentry *bfs_lookup(struct inode *dir, struct dentry *dentry,
return d_splice_alias(inode, dentry);
}
-static int bfs_link(struct dentry *old, struct inode *dir,
- struct dentry *new)
+static int bfs_link(struct dentry *old, struct inode *dir, struct dentry *new,
+ int flags)
{
struct inode *inode = d_inode(old);
struct bfs_sb_info *info = BFS_SB(inode->i_sb);
int err;
+ if (flags)
+ return -EINVAL;
+
mutex_lock(&info->bfs_lock);
err = bfs_add_entry(dir, &new->d_name, inode->i_ino);
if (err) {
@@ -6759,7 +6759,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
}
static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
- struct dentry *dentry)
+ struct dentry *dentry, int flags)
{
struct btrfs_trans_handle *trans = NULL;
struct btrfs_root *root = BTRFS_I(dir)->root;
@@ -6769,6 +6769,9 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
int err;
int drop_inode = 0;
+ if (flags)
+ return -EINVAL;
+
/* do not allow sys_link's with other subvols of the same device */
if (root->root_key.objectid != BTRFS_I(inode)->root->root_key.objectid)
return -EXDEV;
@@ -999,13 +999,16 @@ static int ceph_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
}
static int ceph_link(struct dentry *old_dentry, struct inode *dir,
- struct dentry *dentry)
+ struct dentry *dentry, int flags)
{
struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
struct ceph_mds_client *mdsc = fsc->mdsc;
struct ceph_mds_request *req;
int err;
+ if (flags)
+ return -EINVAL;
+
if (ceph_snap(dir) != CEPH_NOSNAP)
return -EROFS;
@@ -69,7 +69,7 @@ extern int cifs_atomic_open(struct inode *, struct dentry *,
extern struct dentry *cifs_lookup(struct inode *, struct dentry *,
unsigned int);
extern int cifs_unlink(struct inode *dir, struct dentry *dentry);
-extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *);
+extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *, int);
extern int cifs_mknod(struct inode *, struct dentry *, umode_t, dev_t);
extern int cifs_mkdir(struct inode *, struct dentry *, umode_t);
extern int cifs_rmdir(struct inode *, struct dentry *);
@@ -516,7 +516,7 @@ smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
int
cifs_hardlink(struct dentry *old_file, struct inode *inode,
- struct dentry *direntry)
+ struct dentry *direntry, int flags)
{
int rc = -EACCES;
unsigned int xid;
@@ -528,6 +528,9 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
struct TCP_Server_Info *server;
struct cifsInodeInfo *cifsInode;
+ if (flags)
+ return -EINVAL;
+
tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink))
return PTR_ERR(tlink);
@@ -200,13 +200,16 @@ static int coda_mkdir(struct inode *dir, struct dentry *de, umode_t mode)
/* try to make de an entry in dir_inodde linked to source_de */
static int coda_link(struct dentry *source_de, struct inode *dir_inode,
- struct dentry *de)
+ struct dentry *de, int flags)
{
struct inode *inode = d_inode(source_de);
const char * name = de->d_name.name;
int len = de->d_name.len;
int error;
+ if (flags)
+ return -EINVAL;
+
if (is_root_inode(dir_inode) && coda_iscontrol(name, len))
return -EPERM;
@@ -422,7 +422,7 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode,
}
static int ecryptfs_link(struct dentry *old_dentry, struct inode *dir,
- struct dentry *new_dentry)
+ struct dentry *new_dentry, int flags)
{
struct dentry *lower_old_dentry;
struct dentry *lower_new_dentry;
@@ -430,6 +430,9 @@ static int ecryptfs_link(struct dentry *old_dentry, struct inode *dir,
u64 file_size_save;
int rc;
+ if (flags)
+ return -EINVAL;
+
file_size_save = i_size_read(d_inode(old_dentry));
lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry);
@@ -196,11 +196,14 @@ static int ext2_symlink (struct inode * dir, struct dentry * dentry,
}
static int ext2_link (struct dentry * old_dentry, struct inode * dir,
- struct dentry *dentry)
+ struct dentry *dentry, int flags)
{
struct inode *inode = d_inode(old_dentry);
int err;
+ if (flags)
+ return -EINVAL;
+
err = dquot_initialize(dir);
if (err)
return err;
@@ -3366,13 +3366,16 @@ static int ext4_symlink(struct inode *dir,
return err;
}
-static int ext4_link(struct dentry *old_dentry,
- struct inode *dir, struct dentry *dentry)
+static int ext4_link(struct dentry *old_dentry, struct inode *dir,
+ struct dentry *dentry, int flags)
{
handle_t *handle;
struct inode *inode = d_inode(old_dentry);
int err, retries = 0;
+ if (flags)
+ return -EINVAL;
+
if (inode->i_nlink >= EXT4_LINK_MAX)
return -EMLINK;
@@ -312,12 +312,15 @@ static int f2fs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
}
static int f2fs_link(struct dentry *old_dentry, struct inode *dir,
- struct dentry *dentry)
+ struct dentry *dentry, int flags)
{
struct inode *inode = d_inode(old_dentry);
struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
int err;
+ if (flags)
+ return -EINVAL;
+
if (unlikely(f2fs_cp_error(sbi)))
return -EIO;
if (!f2fs_is_checkpoint_ready(sbi))
@@ -842,7 +842,7 @@ static int fuse_rename2(struct inode *olddir, struct dentry *oldent,
}
static int fuse_link(struct dentry *entry, struct inode *newdir,
- struct dentry *newent)
+ struct dentry *newent, int flags)
{
int err;
struct fuse_link_in inarg;
@@ -850,6 +850,9 @@ static int fuse_link(struct dentry *entry, struct inode *newdir,
struct fuse_conn *fc = get_fuse_conn(inode);
FUSE_ARGS(args);
+ if (flags)
+ return -EINVAL;
+
memset(&inarg, 0, sizeof(inarg));
inarg.oldnodeid = get_node_id(inode);
args.opcode = FUSE_LINK;
@@ -891,7 +891,7 @@ static struct dentry *gfs2_lookup(struct inode *dir, struct dentry *dentry,
*/
static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
- struct dentry *dentry)
+ struct dentry *dentry, int flags)
{
struct gfs2_inode *dip = GFS2_I(dir);
struct gfs2_sbd *sdp = GFS2_SB(dir);
@@ -902,6 +902,9 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
struct gfs2_diradd da = { .bh = NULL, .save_loc = 1, };
int error;
+ if (flags)
+ return -EINVAL;
+
if (S_ISDIR(inode->i_mode))
return -EPERM;
@@ -298,7 +298,7 @@ static int hfsplus_dir_release(struct inode *inode, struct file *file)
}
static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir,
- struct dentry *dst_dentry)
+ struct dentry *dst_dentry, int flags)
{
struct hfsplus_sb_info *sbi = HFSPLUS_SB(dst_dir->i_sb);
struct inode *inode = d_inode(src_dentry);
@@ -308,6 +308,9 @@ static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir,
u32 cnid, id;
int res;
+ if (flags)
+ return -EINVAL;
+
if (HFSPLUS_IS_RSRC(inode))
return -EPERM;
if (!S_ISREG(inode->i_mode))
@@ -622,11 +622,14 @@ static struct dentry *hostfs_lookup(struct inode *ino, struct dentry *dentry,
}
static int hostfs_link(struct dentry *to, struct inode *ino,
- struct dentry *from)
+ struct dentry *from, int flags)
{
char *from_name, *to_name;
int err;
+ if (flags)
+ return -EOPNOTSUPP;
+
if ((from_name = dentry_name(from)) == NULL)
return -ENOMEM;
to_name = dentry_name(to);
@@ -28,7 +28,7 @@ static int jffs2_create (struct inode *,struct dentry *,umode_t,
bool);
static struct dentry *jffs2_lookup (struct inode *,struct dentry *,
unsigned int);
-static int jffs2_link (struct dentry *,struct inode *,struct dentry *);
+static int jffs2_link (struct dentry *,struct inode *,struct dentry *, int);
static int jffs2_unlink (struct inode *,struct dentry *);
static int jffs2_symlink (struct inode *,struct dentry *,const char *);
static int jffs2_mkdir (struct inode *,struct dentry *,umode_t);
@@ -240,7 +240,8 @@ static int jffs2_unlink(struct inode *dir_i, struct dentry *dentry)
/***********************************************************************/
-static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct dentry *dentry)
+static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i,
+ struct dentry *dentry, int flags)
{
struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dentry->d_sb);
struct jffs2_inode_info *f = JFFS2_INODE_INFO(d_inode(old_dentry));
@@ -249,6 +250,9 @@ static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct de
uint8_t type;
uint32_t now;
+ if (flags)
+ return -EINVAL;
+
/* Don't let people make hard links to bad inodes. */
if (!f->inocache)
return -EIO;
@@ -781,8 +781,8 @@ void jfs_free_zero_link(struct inode *ip)
* EXDEV: target object and new link are on different file systems and
* implementation does not support links between file systems [XPG4.2].
*/
-static int jfs_link(struct dentry *old_dentry,
- struct inode *dir, struct dentry *dentry)
+static int jfs_link(struct dentry *old_dentry, struct inode *dir,
+ struct dentry *dentry, int flags)
{
int rc;
tid_t tid;
@@ -792,6 +792,9 @@ static int jfs_link(struct dentry *old_dentry,
struct btstack btstack;
struct inode *iplist[2];
+ if (flags)
+ return -EINVAL;
+
jfs_info("jfs_link: %pd %pd", old_dentry, dentry);
rc = dquot_initialize(dir);
@@ -318,10 +318,14 @@ int simple_open(struct inode *inode, struct file *file)
}
EXPORT_SYMBOL(simple_open);
-int simple_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
+int simple_link(struct dentry *old_dentry, struct inode *dir,
+ struct dentry *dentry, int flags)
{
struct inode *inode = d_inode(old_dentry);
+ if (flags)
+ return -EINVAL;
+
inode->i_ctime = dir->i_ctime = dir->i_mtime = current_time(inode);
inc_nlink(inode);
ihold(inode);
@@ -99,10 +99,13 @@ static int minix_symlink(struct inode * dir, struct dentry *dentry,
}
static int minix_link(struct dentry * old_dentry, struct inode * dir,
- struct dentry *dentry)
+ struct dentry *dentry, int flags)
{
struct inode *inode = d_inode(old_dentry);
+ if (flags)
+ return -EINVAL;
+
inode->i_ctime = current_time(inode);
inode_inc_link_count(inode);
ihold(inode);
@@ -4181,7 +4181,7 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de
else {
error = try_break_deleg(inode, delegated_inode);
if (!error)
- error = dir->i_op->link(old_dentry, dir, new_dentry);
+ error = dir->i_op->link(old_dentry, dir, new_dentry, 0);
}
if (!error && (inode->i_state & I_LINKABLE)) {
@@ -1991,11 +1991,15 @@ int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
EXPORT_SYMBOL_GPL(nfs_symlink);
int
-nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
+nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry,
+ int flags)
{
struct inode *inode = d_inode(old_dentry);
int error;
+ if (flags)
+ return -EINVAL;
+
dfprintk(VFS, "NFS: link(%pd2 -> %pd2)\n",
old_dentry, dentry);
@@ -356,7 +356,7 @@ int nfs_mkdir(struct inode *, struct dentry *, umode_t);
int nfs_rmdir(struct inode *, struct dentry *);
int nfs_unlink(struct inode *, struct dentry *);
int nfs_symlink(struct inode *, struct dentry *, const char *);
-int nfs_link(struct dentry *, struct inode *, struct dentry *);
+int nfs_link(struct dentry *, struct inode *, struct dentry *, int);
int nfs_mknod(struct inode *, struct dentry *, umode_t, dev_t);
int nfs_rename(struct inode *, struct dentry *,
struct inode *, struct dentry *, unsigned int);
@@ -174,12 +174,15 @@ static int nilfs_symlink(struct inode *dir, struct dentry *dentry,
}
static int nilfs_link(struct dentry *old_dentry, struct inode *dir,
- struct dentry *dentry)
+ struct dentry *dentry, int flags)
{
struct inode *inode = d_inode(old_dentry);
struct nilfs_transaction_info ti;
int err;
+ if (flags)
+ return -EINVAL;
+
err = nilfs_transaction_begin(dir->i_sb, &ti, 1);
if (err)
return err;
@@ -672,7 +672,8 @@ static int ocfs2_create(struct inode *dir,
static int ocfs2_link(struct dentry *old_dentry,
struct inode *dir,
- struct dentry *dentry)
+ struct dentry *dentry,
+ int flags)
{
handle_t *handle;
struct inode *inode = d_inode(old_dentry);
@@ -687,6 +688,9 @@ static int ocfs2_link(struct dentry *old_dentry,
sigset_t oldset;
u64 old_de_ino;
+ if (flags)
+ return -EINVAL;
+
trace_ocfs2_link((unsigned long long)OCFS2_I(inode)->ip_blkno,
old_dentry->d_name.len, old_dentry->d_name.name,
dentry->d_name.len, dentry->d_name.name);
@@ -661,11 +661,14 @@ static int ovl_set_link_redirect(struct dentry *dentry)
}
static int ovl_link(struct dentry *old, struct inode *newdir,
- struct dentry *new)
+ struct dentry *new, int flags)
{
int err;
struct inode *inode;
+ if (flags)
+ return -EINVAL;
+
err = ovl_want_write(old);
if (err)
goto out;
@@ -1195,7 +1195,7 @@ static int reiserfs_symlink(struct inode *parent_dir,
}
static int reiserfs_link(struct dentry *old_dentry, struct inode *dir,
- struct dentry *dentry)
+ struct dentry *dentry, int flags)
{
int retval;
struct inode *inode = d_inode(old_dentry);
@@ -1208,6 +1208,9 @@ static int reiserfs_link(struct dentry *old_dentry, struct inode *dir,
JOURNAL_PER_BALANCE_CNT * 3 +
2 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb);
+ if (flags)
+ return -EINVAL;
+
retval = dquot_initialize(dir);
if (retval)
return retval;
@@ -96,11 +96,14 @@ static int sysv_symlink(struct inode * dir, struct dentry * dentry,
goto out;
}
-static int sysv_link(struct dentry * old_dentry, struct inode * dir,
- struct dentry * dentry)
+static int sysv_link(struct dentry *old_dentry, struct inode *dir,
+ struct dentry *dentry, int flags)
{
struct inode *inode = d_inode(old_dentry);
+ if (flags)
+ return -EINVAL;
+
inode->i_ctime = current_time(inode);
inode_inc_link_count(inode);
ihold(inode);
@@ -683,7 +683,7 @@ static void unlock_2_inodes(struct inode *inode1, struct inode *inode2)
}
static int ubifs_link(struct dentry *old_dentry, struct inode *dir,
- struct dentry *dentry)
+ struct dentry *dentry, int flags)
{
struct ubifs_info *c = dir->i_sb->s_fs_info;
struct inode *inode = d_inode(old_dentry);
@@ -694,6 +694,9 @@ static int ubifs_link(struct dentry *old_dentry, struct inode *dir,
.dirtied_ino_d = ALIGN(ui->data_len, 8) };
struct fscrypt_name nm;
+ if (flags)
+ return -EINVAL;
+
/*
* Budget request settings: new direntry, changing the target inode,
* changing the parent inode.
@@ -1028,13 +1028,16 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
}
static int udf_link(struct dentry *old_dentry, struct inode *dir,
- struct dentry *dentry)
+ struct dentry *dentry, int flags)
{
struct inode *inode = d_inode(old_dentry);
struct udf_fileident_bh fibh;
struct fileIdentDesc cfi, *fi;
int err;
+ if (flags)
+ return -EINVAL;
+
fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
if (!fi) {
return err;
@@ -146,11 +146,14 @@ static int ufs_symlink (struct inode * dir, struct dentry * dentry,
}
static int ufs_link (struct dentry * old_dentry, struct inode * dir,
- struct dentry *dentry)
+ struct dentry *dentry, int flags)
{
struct inode *inode = d_inode(old_dentry);
int error;
+ if (flags)
+ return -EINVAL;
+
inode->i_ctime = current_time(inode);
inode_inc_link_count(inode);
ihold(inode);
@@ -311,12 +311,16 @@ STATIC int
xfs_vn_link(
struct dentry *old_dentry,
struct inode *dir,
- struct dentry *dentry)
+ struct dentry *dentry,
+ int flags)
{
struct inode *inode = d_inode(old_dentry);
struct xfs_name name;
int error;
+ if (flags)
+ return -EINVAL;
+
error = xfs_dentry_mode_to_name(&name, dentry, inode->i_mode);
if (unlikely(error))
return error;
@@ -1869,7 +1869,7 @@ struct inode_operations {
int (*readlink) (struct dentry *, char __user *,int);
int (*create) (struct inode *,struct dentry *, umode_t, bool);
- int (*link) (struct dentry *,struct inode *,struct dentry *);
+ int (*link) (struct dentry *,struct inode *,struct dentry *, int);
int (*unlink) (struct inode *,struct dentry *);
int (*symlink) (struct inode *,struct dentry *,const char *);
int (*mkdir) (struct inode *,struct dentry *,umode_t);
@@ -3298,7 +3298,7 @@ extern int simple_setattr(struct dentry *, struct iattr *);
extern int simple_getattr(const struct path *, struct kstat *, u32, unsigned int);
extern int simple_statfs(struct dentry *, struct kstatfs *);
extern int simple_open(struct inode *inode, struct file *file);
-extern int simple_link(struct dentry *, struct inode *, struct dentry *);
+extern int simple_link(struct dentry *, struct inode *, struct dentry *, int);
extern int simple_unlink(struct inode *, struct dentry *);
extern int simple_rmdir(struct inode *, struct dentry *);
extern int simple_rename(struct inode *, struct dentry *,
@@ -2948,11 +2948,15 @@ static int shmem_create(struct inode *dir, struct dentry *dentry, umode_t mode,
/*
* Link a file..
*/
-static int shmem_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
+static int shmem_link(struct dentry *old_dentry, struct inode *dir,
+ struct dentry *dentry, int flags)
{
struct inode *inode = d_inode(old_dentry);
int ret = 0;
+ if (flags)
+ return -EINVAL;
+
/*
* No ordinary (disk based) filesystem counts links as inodes;
* but each new link needs a new dentry, pinning lowmem, and