Commit 8de52778 authored by Al Viro's avatar Al Viro

vfs: check i_nlink limits in vfs_{mkdir,rename_dir,link}

New field of struct super_block - ->s_max_links.  Maximal allowed
value of ->i_nlink or 0; in the latter case all checks still need
to be done in ->link/->mkdir/->rename instances.  Note that this
limit applies both to directoris and to non-directories.
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent c16fa4f2
...@@ -143,9 +143,6 @@ static int exofs_link(struct dentry *old_dentry, struct inode *dir, ...@@ -143,9 +143,6 @@ static int exofs_link(struct dentry *old_dentry, struct inode *dir,
{ {
struct inode *inode = old_dentry->d_inode; struct inode *inode = old_dentry->d_inode;
if (inode->i_nlink >= EXOFS_LINK_MAX)
return -EMLINK;
inode->i_ctime = CURRENT_TIME; inode->i_ctime = CURRENT_TIME;
inode_inc_link_count(inode); inode_inc_link_count(inode);
ihold(inode); ihold(inode);
...@@ -156,10 +153,7 @@ static int exofs_link(struct dentry *old_dentry, struct inode *dir, ...@@ -156,10 +153,7 @@ static int exofs_link(struct dentry *old_dentry, struct inode *dir,
static int exofs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) static int exofs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
{ {
struct inode *inode; struct inode *inode;
int err = -EMLINK; int err;
if (dir->i_nlink >= EXOFS_LINK_MAX)
goto out;
inode_inc_link_count(dir); inode_inc_link_count(dir);
...@@ -275,11 +269,6 @@ static int exofs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -275,11 +269,6 @@ static int exofs_rename(struct inode *old_dir, struct dentry *old_dentry,
if (err) if (err)
goto out_dir; goto out_dir;
} else { } else {
if (dir_de) {
err = -EMLINK;
if (new_dir->i_nlink >= EXOFS_LINK_MAX)
goto out_dir;
}
err = exofs_add_link(new_dentry, old_inode); err = exofs_add_link(new_dentry, old_inode);
if (err) if (err)
goto out_dir; goto out_dir;
......
...@@ -754,6 +754,7 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -754,6 +754,7 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent)
sb->s_blocksize = EXOFS_BLKSIZE; sb->s_blocksize = EXOFS_BLKSIZE;
sb->s_blocksize_bits = EXOFS_BLKSHIFT; sb->s_blocksize_bits = EXOFS_BLKSHIFT;
sb->s_maxbytes = MAX_LFS_FILESIZE; sb->s_maxbytes = MAX_LFS_FILESIZE;
sb->s_max_links = EXOFS_LINK_MAX;
atomic_set(&sbi->s_curr_pending, 0); atomic_set(&sbi->s_curr_pending, 0);
sb->s_bdev = NULL; sb->s_bdev = NULL;
sb->s_dev = 0; sb->s_dev = 0;
......
...@@ -195,9 +195,6 @@ static int ext2_link (struct dentry * old_dentry, struct inode * dir, ...@@ -195,9 +195,6 @@ static int ext2_link (struct dentry * old_dentry, struct inode * dir,
struct inode *inode = old_dentry->d_inode; struct inode *inode = old_dentry->d_inode;
int err; int err;
if (inode->i_nlink >= EXT2_LINK_MAX)
return -EMLINK;
dquot_initialize(dir); dquot_initialize(dir);
inode->i_ctime = CURRENT_TIME_SEC; inode->i_ctime = CURRENT_TIME_SEC;
...@@ -217,10 +214,7 @@ static int ext2_link (struct dentry * old_dentry, struct inode * dir, ...@@ -217,10 +214,7 @@ static int ext2_link (struct dentry * old_dentry, struct inode * dir,
static int ext2_mkdir(struct inode * dir, struct dentry * dentry, umode_t mode) static int ext2_mkdir(struct inode * dir, struct dentry * dentry, umode_t mode)
{ {
struct inode * inode; struct inode * inode;
int err = -EMLINK; int err;
if (dir->i_nlink >= EXT2_LINK_MAX)
goto out;
dquot_initialize(dir); dquot_initialize(dir);
...@@ -346,11 +340,6 @@ static int ext2_rename (struct inode * old_dir, struct dentry * old_dentry, ...@@ -346,11 +340,6 @@ static int ext2_rename (struct inode * old_dir, struct dentry * old_dentry,
drop_nlink(new_inode); drop_nlink(new_inode);
inode_dec_link_count(new_inode); inode_dec_link_count(new_inode);
} else { } else {
if (dir_de) {
err = -EMLINK;
if (new_dir->i_nlink >= EXT2_LINK_MAX)
goto out_dir;
}
err = ext2_add_link(new_dentry, old_inode); err = ext2_add_link(new_dentry, old_inode);
if (err) if (err)
goto out_dir; goto out_dir;
......
...@@ -919,6 +919,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) ...@@ -919,6 +919,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
} }
sb->s_maxbytes = ext2_max_size(sb->s_blocksize_bits); sb->s_maxbytes = ext2_max_size(sb->s_blocksize_bits);
sb->s_max_links = EXT2_LINK_MAX;
if (le32_to_cpu(es->s_rev_level) == EXT2_GOOD_OLD_REV) { if (le32_to_cpu(es->s_rev_level) == EXT2_GOOD_OLD_REV) {
sbi->s_inode_size = EXT2_GOOD_OLD_INODE_SIZE; sbi->s_inode_size = EXT2_GOOD_OLD_INODE_SIZE;
......
...@@ -220,12 +220,6 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, umode_t mode) ...@@ -220,12 +220,6 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, umode_t mode)
dquot_initialize(dip); dquot_initialize(dip);
/* link count overflow on parent directory ? */
if (dip->i_nlink == JFS_LINK_MAX) {
rc = -EMLINK;
goto out1;
}
/* /*
* search parent directory for entry/freespace * search parent directory for entry/freespace
* (dtSearch() returns parent directory page pinned) * (dtSearch() returns parent directory page pinned)
...@@ -806,9 +800,6 @@ static int jfs_link(struct dentry *old_dentry, ...@@ -806,9 +800,6 @@ static int jfs_link(struct dentry *old_dentry,
jfs_info("jfs_link: %s %s", old_dentry->d_name.name, jfs_info("jfs_link: %s %s", old_dentry->d_name.name,
dentry->d_name.name); dentry->d_name.name);
if (ip->i_nlink == JFS_LINK_MAX)
return -EMLINK;
dquot_initialize(dir); dquot_initialize(dir);
tid = txBegin(ip->i_sb, 0); tid = txBegin(ip->i_sb, 0);
...@@ -1138,10 +1129,6 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -1138,10 +1129,6 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
rc = -ENOTEMPTY; rc = -ENOTEMPTY;
goto out3; goto out3;
} }
} else if ((new_dir != old_dir) &&
(new_dir->i_nlink == JFS_LINK_MAX)) {
rc = -EMLINK;
goto out3;
} }
} else if (new_ip) { } else if (new_ip) {
IWRITE_LOCK(new_ip, RDWRLOCK_NORMAL); IWRITE_LOCK(new_ip, RDWRLOCK_NORMAL);
......
...@@ -441,6 +441,7 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -441,6 +441,7 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent)
return -ENOMEM; return -ENOMEM;
sb->s_fs_info = sbi; sb->s_fs_info = sbi;
sb->s_max_links = JFS_LINK_MAX;
sbi->sb = sb; sbi->sb = sb;
sbi->uid = sbi->gid = sbi->umask = -1; sbi->uid = sbi->gid = sbi->umask = -1;
......
...@@ -558,9 +558,6 @@ static int logfs_link(struct dentry *old_dentry, struct inode *dir, ...@@ -558,9 +558,6 @@ static int logfs_link(struct dentry *old_dentry, struct inode *dir,
{ {
struct inode *inode = old_dentry->d_inode; struct inode *inode = old_dentry->d_inode;
if (inode->i_nlink >= LOGFS_LINK_MAX)
return -EMLINK;
inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
ihold(inode); ihold(inode);
inc_nlink(inode); inc_nlink(inode);
......
...@@ -542,6 +542,7 @@ static struct dentry *logfs_get_sb_device(struct logfs_super *super, ...@@ -542,6 +542,7 @@ static struct dentry *logfs_get_sb_device(struct logfs_super *super,
* the filesystem incompatible with 32bit systems. * the filesystem incompatible with 32bit systems.
*/ */
sb->s_maxbytes = (1ull << 43) - 1; sb->s_maxbytes = (1ull << 43) - 1;
sb->s_max_links = LOGFS_LINK_MAX;
sb->s_op = &logfs_super_operations; sb->s_op = &logfs_super_operations;
sb->s_flags = flags | MS_NOATIME; sb->s_flags = flags | MS_NOATIME;
......
...@@ -190,24 +190,24 @@ static int minix_fill_super(struct super_block *s, void *data, int silent) ...@@ -190,24 +190,24 @@ static int minix_fill_super(struct super_block *s, void *data, int silent)
sbi->s_version = MINIX_V1; sbi->s_version = MINIX_V1;
sbi->s_dirsize = 16; sbi->s_dirsize = 16;
sbi->s_namelen = 14; sbi->s_namelen = 14;
sbi->s_link_max = MINIX_LINK_MAX; s->s_max_links = MINIX_LINK_MAX;
} else if (s->s_magic == MINIX_SUPER_MAGIC2) { } else if (s->s_magic == MINIX_SUPER_MAGIC2) {
sbi->s_version = MINIX_V1; sbi->s_version = MINIX_V1;
sbi->s_dirsize = 32; sbi->s_dirsize = 32;
sbi->s_namelen = 30; sbi->s_namelen = 30;
sbi->s_link_max = MINIX_LINK_MAX; s->s_max_links = MINIX_LINK_MAX;
} else if (s->s_magic == MINIX2_SUPER_MAGIC) { } else if (s->s_magic == MINIX2_SUPER_MAGIC) {
sbi->s_version = MINIX_V2; sbi->s_version = MINIX_V2;
sbi->s_nzones = ms->s_zones; sbi->s_nzones = ms->s_zones;
sbi->s_dirsize = 16; sbi->s_dirsize = 16;
sbi->s_namelen = 14; sbi->s_namelen = 14;
sbi->s_link_max = MINIX2_LINK_MAX; s->s_max_links = MINIX2_LINK_MAX;
} else if (s->s_magic == MINIX2_SUPER_MAGIC2) { } else if (s->s_magic == MINIX2_SUPER_MAGIC2) {
sbi->s_version = MINIX_V2; sbi->s_version = MINIX_V2;
sbi->s_nzones = ms->s_zones; sbi->s_nzones = ms->s_zones;
sbi->s_dirsize = 32; sbi->s_dirsize = 32;
sbi->s_namelen = 30; sbi->s_namelen = 30;
sbi->s_link_max = MINIX2_LINK_MAX; s->s_max_links = MINIX2_LINK_MAX;
} else if ( *(__u16 *)(bh->b_data + 24) == MINIX3_SUPER_MAGIC) { } else if ( *(__u16 *)(bh->b_data + 24) == MINIX3_SUPER_MAGIC) {
m3s = (struct minix3_super_block *) bh->b_data; m3s = (struct minix3_super_block *) bh->b_data;
s->s_magic = m3s->s_magic; s->s_magic = m3s->s_magic;
...@@ -221,9 +221,9 @@ static int minix_fill_super(struct super_block *s, void *data, int silent) ...@@ -221,9 +221,9 @@ static int minix_fill_super(struct super_block *s, void *data, int silent)
sbi->s_dirsize = 64; sbi->s_dirsize = 64;
sbi->s_namelen = 60; sbi->s_namelen = 60;
sbi->s_version = MINIX_V3; sbi->s_version = MINIX_V3;
sbi->s_link_max = MINIX2_LINK_MAX;
sbi->s_mount_state = MINIX_VALID_FS; sbi->s_mount_state = MINIX_VALID_FS;
sb_set_blocksize(s, m3s->s_blocksize); sb_set_blocksize(s, m3s->s_blocksize);
s->s_max_links = MINIX2_LINK_MAX;
} else } else
goto out_no_fs; goto out_no_fs;
......
...@@ -34,7 +34,6 @@ struct minix_sb_info { ...@@ -34,7 +34,6 @@ struct minix_sb_info {
unsigned long s_max_size; unsigned long s_max_size;
int s_dirsize; int s_dirsize;
int s_namelen; int s_namelen;
int s_link_max;
struct buffer_head ** s_imap; struct buffer_head ** s_imap;
struct buffer_head ** s_zmap; struct buffer_head ** s_zmap;
struct buffer_head * s_sbh; struct buffer_head * s_sbh;
......
...@@ -94,9 +94,6 @@ static int minix_link(struct dentry * old_dentry, struct inode * dir, ...@@ -94,9 +94,6 @@ static int minix_link(struct dentry * old_dentry, struct inode * dir,
{ {
struct inode *inode = old_dentry->d_inode; struct inode *inode = old_dentry->d_inode;
if (inode->i_nlink >= minix_sb(inode->i_sb)->s_link_max)
return -EMLINK;
inode->i_ctime = CURRENT_TIME_SEC; inode->i_ctime = CURRENT_TIME_SEC;
inode_inc_link_count(inode); inode_inc_link_count(inode);
ihold(inode); ihold(inode);
...@@ -106,10 +103,7 @@ static int minix_link(struct dentry * old_dentry, struct inode * dir, ...@@ -106,10 +103,7 @@ static int minix_link(struct dentry * old_dentry, struct inode * dir,
static int minix_mkdir(struct inode * dir, struct dentry *dentry, umode_t mode) static int minix_mkdir(struct inode * dir, struct dentry *dentry, umode_t mode)
{ {
struct inode * inode; struct inode * inode;
int err = -EMLINK; int err;
if (dir->i_nlink >= minix_sb(dir->i_sb)->s_link_max)
goto out;
inode_inc_link_count(dir); inode_inc_link_count(dir);
...@@ -181,7 +175,6 @@ static int minix_rmdir(struct inode * dir, struct dentry *dentry) ...@@ -181,7 +175,6 @@ static int minix_rmdir(struct inode * dir, struct dentry *dentry)
static int minix_rename(struct inode * old_dir, struct dentry *old_dentry, static int minix_rename(struct inode * old_dir, struct dentry *old_dentry,
struct inode * new_dir, struct dentry *new_dentry) struct inode * new_dir, struct dentry *new_dentry)
{ {
struct minix_sb_info * info = minix_sb(old_dir->i_sb);
struct inode * old_inode = old_dentry->d_inode; struct inode * old_inode = old_dentry->d_inode;
struct inode * new_inode = new_dentry->d_inode; struct inode * new_inode = new_dentry->d_inode;
struct page * dir_page = NULL; struct page * dir_page = NULL;
...@@ -219,11 +212,6 @@ static int minix_rename(struct inode * old_dir, struct dentry *old_dentry, ...@@ -219,11 +212,6 @@ static int minix_rename(struct inode * old_dir, struct dentry *old_dentry,
drop_nlink(new_inode); drop_nlink(new_inode);
inode_dec_link_count(new_inode); inode_dec_link_count(new_inode);
} else { } else {
if (dir_de) {
err = -EMLINK;
if (new_dir->i_nlink >= info->s_link_max)
goto out_dir;
}
err = minix_add_link(new_dentry, old_inode); err = minix_add_link(new_dentry, old_inode);
if (err) if (err)
goto out_dir; goto out_dir;
......
...@@ -2569,6 +2569,7 @@ SYSCALL_DEFINE3(mknod, const char __user *, filename, umode_t, mode, unsigned, d ...@@ -2569,6 +2569,7 @@ SYSCALL_DEFINE3(mknod, const char __user *, filename, umode_t, mode, unsigned, d
int vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) int vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
{ {
int error = may_create(dir, dentry); int error = may_create(dir, dentry);
unsigned max_links = dir->i_sb->s_max_links;
if (error) if (error)
return error; return error;
...@@ -2581,6 +2582,9 @@ int vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) ...@@ -2581,6 +2582,9 @@ int vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
if (error) if (error)
return error; return error;
if (max_links && dir->i_nlink >= max_links)
return -EMLINK;
error = dir->i_op->mkdir(dir, dentry, mode); error = dir->i_op->mkdir(dir, dentry, mode);
if (!error) if (!error)
fsnotify_mkdir(dir, dentry); fsnotify_mkdir(dir, dentry);
...@@ -2911,6 +2915,7 @@ SYSCALL_DEFINE2(symlink, const char __user *, oldname, const char __user *, newn ...@@ -2911,6 +2915,7 @@ SYSCALL_DEFINE2(symlink, const char __user *, oldname, const char __user *, newn
int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
{ {
struct inode *inode = old_dentry->d_inode; struct inode *inode = old_dentry->d_inode;
unsigned max_links = dir->i_sb->s_max_links;
int error; int error;
if (!inode) if (!inode)
...@@ -2941,6 +2946,8 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de ...@@ -2941,6 +2946,8 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de
/* Make sure we don't allow creating hardlink to an unlinked file */ /* Make sure we don't allow creating hardlink to an unlinked file */
if (inode->i_nlink == 0) if (inode->i_nlink == 0)
error = -ENOENT; error = -ENOENT;
else if (max_links && inode->i_nlink >= max_links)
error = -EMLINK;
else else
error = dir->i_op->link(old_dentry, dir, new_dentry); error = dir->i_op->link(old_dentry, dir, new_dentry);
mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex);
...@@ -3050,6 +3057,7 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, ...@@ -3050,6 +3057,7 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
{ {
int error = 0; int error = 0;
struct inode *target = new_dentry->d_inode; struct inode *target = new_dentry->d_inode;
unsigned max_links = new_dir->i_sb->s_max_links;
/* /*
* If we are going to change the parent - check write permissions, * If we are going to change the parent - check write permissions,
...@@ -3073,6 +3081,11 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, ...@@ -3073,6 +3081,11 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
if (d_mountpoint(old_dentry) || d_mountpoint(new_dentry)) if (d_mountpoint(old_dentry) || d_mountpoint(new_dentry))
goto out; goto out;
error = -EMLINK;
if (max_links && !target && new_dir != old_dir &&
new_dir->i_nlink >= max_links)
goto out;
if (target) if (target)
shrink_dcache_parent(new_dentry); shrink_dcache_parent(new_dentry);
error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry); error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
......
...@@ -193,9 +193,6 @@ static int nilfs_link(struct dentry *old_dentry, struct inode *dir, ...@@ -193,9 +193,6 @@ static int nilfs_link(struct dentry *old_dentry, struct inode *dir,
struct nilfs_transaction_info ti; struct nilfs_transaction_info ti;
int err; int err;
if (inode->i_nlink >= NILFS_LINK_MAX)
return -EMLINK;
err = nilfs_transaction_begin(dir->i_sb, &ti, 1); err = nilfs_transaction_begin(dir->i_sb, &ti, 1);
if (err) if (err)
return err; return err;
...@@ -219,9 +216,6 @@ static int nilfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) ...@@ -219,9 +216,6 @@ static int nilfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
struct nilfs_transaction_info ti; struct nilfs_transaction_info ti;
int err; int err;
if (dir->i_nlink >= NILFS_LINK_MAX)
return -EMLINK;
err = nilfs_transaction_begin(dir->i_sb, &ti, 1); err = nilfs_transaction_begin(dir->i_sb, &ti, 1);
if (err) if (err)
return err; return err;
...@@ -400,11 +394,6 @@ static int nilfs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -400,11 +394,6 @@ static int nilfs_rename(struct inode *old_dir, struct dentry *old_dentry,
drop_nlink(new_inode); drop_nlink(new_inode);
nilfs_mark_inode_dirty(new_inode); nilfs_mark_inode_dirty(new_inode);
} else { } else {
if (dir_de) {
err = -EMLINK;
if (new_dir->i_nlink >= NILFS_LINK_MAX)
goto out_dir;
}
err = nilfs_add_link(new_dentry, old_inode); err = nilfs_add_link(new_dentry, old_inode);
if (err) if (err)
goto out_dir; goto out_dir;
......
...@@ -1059,6 +1059,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -1059,6 +1059,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent)
sb->s_export_op = &nilfs_export_ops; sb->s_export_op = &nilfs_export_ops;
sb->s_root = NULL; sb->s_root = NULL;
sb->s_time_gran = 1; sb->s_time_gran = 1;
sb->s_max_links = NILFS_LINK_MAX;
bdi = sb->s_bdev->bd_inode->i_mapping->backing_dev_info; bdi = sb->s_bdev->bd_inode->i_mapping->backing_dev_info;
sb->s_bdi = bdi ? : &default_backing_dev_info; sb->s_bdi = bdi ? : &default_backing_dev_info;
......
...@@ -121,9 +121,6 @@ static int sysv_link(struct dentry * old_dentry, struct inode * dir, ...@@ -121,9 +121,6 @@ static int sysv_link(struct dentry * old_dentry, struct inode * dir,
{ {
struct inode *inode = old_dentry->d_inode; struct inode *inode = old_dentry->d_inode;
if (inode->i_nlink >= SYSV_SB(inode->i_sb)->s_link_max)
return -EMLINK;
inode->i_ctime = CURRENT_TIME_SEC; inode->i_ctime = CURRENT_TIME_SEC;
inode_inc_link_count(inode); inode_inc_link_count(inode);
ihold(inode); ihold(inode);
...@@ -134,10 +131,8 @@ static int sysv_link(struct dentry * old_dentry, struct inode * dir, ...@@ -134,10 +131,8 @@ static int sysv_link(struct dentry * old_dentry, struct inode * dir,
static int sysv_mkdir(struct inode * dir, struct dentry *dentry, umode_t mode) static int sysv_mkdir(struct inode * dir, struct dentry *dentry, umode_t mode)
{ {
struct inode * inode; struct inode * inode;
int err = -EMLINK; int err;
if (dir->i_nlink >= SYSV_SB(dir->i_sb)->s_link_max)
goto out;
inode_inc_link_count(dir); inode_inc_link_count(dir);
inode = sysv_new_inode(dir, S_IFDIR|mode); inode = sysv_new_inode(dir, S_IFDIR|mode);
...@@ -251,11 +246,6 @@ static int sysv_rename(struct inode * old_dir, struct dentry * old_dentry, ...@@ -251,11 +246,6 @@ static int sysv_rename(struct inode * old_dir, struct dentry * old_dentry,
drop_nlink(new_inode); drop_nlink(new_inode);
inode_dec_link_count(new_inode); inode_dec_link_count(new_inode);
} else { } else {
if (dir_de) {
err = -EMLINK;
if (new_dir->i_nlink >= SYSV_SB(new_dir->i_sb)->s_link_max)
goto out_dir;
}
err = sysv_add_link(new_dentry, old_inode); err = sysv_add_link(new_dentry, old_inode);
if (err) if (err)
goto out_dir; goto out_dir;
......
...@@ -44,7 +44,7 @@ enum { ...@@ -44,7 +44,7 @@ enum {
JAN_1_1980 = (10*365 + 2) * 24 * 60 * 60 JAN_1_1980 = (10*365 + 2) * 24 * 60 * 60
}; };
static void detected_xenix(struct sysv_sb_info *sbi) static void detected_xenix(struct sysv_sb_info *sbi, unsigned *max_links)
{ {
struct buffer_head *bh1 = sbi->s_bh1; struct buffer_head *bh1 = sbi->s_bh1;
struct buffer_head *bh2 = sbi->s_bh2; struct buffer_head *bh2 = sbi->s_bh2;
...@@ -59,7 +59,7 @@ static void detected_xenix(struct sysv_sb_info *sbi) ...@@ -59,7 +59,7 @@ static void detected_xenix(struct sysv_sb_info *sbi)
sbd2 = (struct xenix_super_block *) (bh2->b_data - 512); sbd2 = (struct xenix_super_block *) (bh2->b_data - 512);
} }
sbi->s_link_max = XENIX_LINK_MAX; *max_links = XENIX_LINK_MAX;
sbi->s_fic_size = XENIX_NICINOD; sbi->s_fic_size = XENIX_NICINOD;
sbi->s_flc_size = XENIX_NICFREE; sbi->s_flc_size = XENIX_NICFREE;
sbi->s_sbd1 = (char *)sbd1; sbi->s_sbd1 = (char *)sbd1;
...@@ -75,7 +75,7 @@ static void detected_xenix(struct sysv_sb_info *sbi) ...@@ -75,7 +75,7 @@ static void detected_xenix(struct sysv_sb_info *sbi)
sbi->s_nzones = fs32_to_cpu(sbi, sbd1->s_fsize); sbi->s_nzones = fs32_to_cpu(sbi, sbd1->s_fsize);
} }
static void detected_sysv4(struct sysv_sb_info *sbi) static void detected_sysv4(struct sysv_sb_info *sbi, unsigned *max_links)
{ {
struct sysv4_super_block * sbd; struct sysv4_super_block * sbd;
struct buffer_head *bh1 = sbi->s_bh1; struct buffer_head *bh1 = sbi->s_bh1;
...@@ -86,7 +86,7 @@ static void detected_sysv4(struct sysv_sb_info *sbi) ...@@ -86,7 +86,7 @@ static void detected_sysv4(struct sysv_sb_info *sbi)
else else
sbd = (struct sysv4_super_block *) bh2->b_data; sbd = (struct sysv4_super_block *) bh2->b_data;
sbi->s_link_max = SYSV_LINK_MAX; *max_links = SYSV_LINK_MAX;
sbi->s_fic_size = SYSV_NICINOD; sbi->s_fic_size = SYSV_NICINOD;
sbi->s_flc_size = SYSV_NICFREE; sbi->s_flc_size = SYSV_NICFREE;
sbi->s_sbd1 = (char *)sbd; sbi->s_sbd1 = (char *)sbd;
...@@ -103,7 +103,7 @@ static void detected_sysv4(struct sysv_sb_info *sbi) ...@@ -103,7 +103,7 @@ static void detected_sysv4(struct sysv_sb_info *sbi)
sbi->s_nzones = fs32_to_cpu(sbi, sbd->s_fsize); sbi->s_nzones = fs32_to_cpu(sbi, sbd->s_fsize);
} }
static void detected_sysv2(struct sysv_sb_info *sbi) static void detected_sysv2(struct sysv_sb_info *sbi, unsigned *max_links)
{ {
struct sysv2_super_block *sbd; struct sysv2_super_block *sbd;
struct buffer_head *bh1 = sbi->s_bh1; struct buffer_head *bh1 = sbi->s_bh1;
...@@ -114,7 +114,7 @@ static void detected_sysv2(struct sysv_sb_info *sbi) ...@@ -114,7 +114,7 @@ static void detected_sysv2(struct sysv_sb_info *sbi)
else else
sbd = (struct sysv2_super_block *) bh2->b_data; sbd = (struct sysv2_super_block *) bh2->b_data;
sbi->s_link_max = SYSV_LINK_MAX; *max_links = SYSV_LINK_MAX;
sbi->s_fic_size = SYSV_NICINOD; sbi->s_fic_size = SYSV_NICINOD;
sbi->s_flc_size = SYSV_NICFREE; sbi->s_flc_size = SYSV_NICFREE;
sbi->s_sbd1 = (char *)sbd; sbi->s_sbd1 = (char *)sbd;
...@@ -131,14 +131,14 @@ static void detected_sysv2(struct sysv_sb_info *sbi) ...@@ -131,14 +131,14 @@ static void detected_sysv2(struct sysv_sb_info *sbi)
sbi->s_nzones = fs32_to_cpu(sbi, sbd->s_fsize); sbi->s_nzones = fs32_to_cpu(sbi, sbd->s_fsize);
} }
static void detected_coherent(struct sysv_sb_info *sbi) static void detected_coherent(struct sysv_sb_info *sbi, unsigned *max_links)
{ {
struct coh_super_block * sbd; struct coh_super_block * sbd;
struct buffer_head *bh1 = sbi->s_bh1; struct buffer_head *bh1 = sbi->s_bh1;
sbd = (struct coh_super_block *) bh1->b_data; sbd = (struct coh_super_block *) bh1->b_data;
sbi->s_link_max = COH_LINK_MAX; *max_links = COH_LINK_MAX;
sbi->s_fic_size = COH_NICINOD; sbi->s_fic_size = COH_NICINOD;
sbi->s_flc_size = COH_NICFREE; sbi->s_flc_size = COH_NICFREE;
sbi->s_sbd1 = (char *)sbd; sbi->s_sbd1 = (char *)sbd;
...@@ -154,12 +154,12 @@ static void detected_coherent(struct sysv_sb_info *sbi) ...@@ -154,12 +154,12 @@ static void detected_coherent(struct sysv_sb_info *sbi)
sbi->s_nzones = fs32_to_cpu(sbi, sbd->s_fsize); sbi->s_nzones = fs32_to_cpu(sbi, sbd->s_fsize);
} }
static void detected_v7(struct sysv_sb_info *sbi) static void detected_v7(struct sysv_sb_info *sbi, unsigned *max_links)
{ {
struct buffer_head *bh2 = sbi->s_bh2; struct buffer_head *bh2 = sbi->s_bh2;
struct v7_super_block *sbd = (struct v7_super_block *)bh2->b_data; struct v7_super_block *sbd = (struct v7_super_block *)bh2->b_data;
sbi->s_link_max = V7_LINK_MAX; *max_links = V7_LINK_MAX;
sbi->s_fic_size = V7_NICINOD; sbi->s_fic_size = V7_NICINOD;
sbi->s_flc_size = V7_NICFREE; sbi->s_flc_size = V7_NICFREE;
sbi->s_sbd1 = (char *)sbd; sbi->s_sbd1 = (char *)sbd;
...@@ -290,7 +290,7 @@ static char *flavour_names[] = { ...@@ -290,7 +290,7 @@ static char *flavour_names[] = {
[FSTYPE_AFS] = "AFS", [FSTYPE_AFS] = "AFS",
}; };
static void (*flavour_setup[])(struct sysv_sb_info *) = { static void (*flavour_setup[])(struct sysv_sb_info *, unsigned *) = {
[FSTYPE_XENIX] = detected_xenix, [FSTYPE_XENIX] = detected_xenix,
[FSTYPE_SYSV4] = detected_sysv4, [FSTYPE_SYSV4] = detected_sysv4,
[FSTYPE_SYSV2] = detected_sysv2, [FSTYPE_SYSV2] = detected_sysv2,
...@@ -310,7 +310,7 @@ static int complete_read_super(struct super_block *sb, int silent, int size) ...@@ -310,7 +310,7 @@ static int complete_read_super(struct super_block *sb, int silent, int size)
sbi->s_firstinodezone = 2; sbi->s_firstinodezone = 2;
flavour_setup[sbi->s_type](sbi); flavour_setup[sbi->s_type](sbi, &sb->s_max_links);
sbi->s_truncate = 1; sbi->s_truncate = 1;
sbi->s_ndatazones = sbi->s_nzones - sbi->s_firstdatazone; sbi->s_ndatazones = sbi->s_nzones - sbi->s_firstdatazone;
......
...@@ -24,7 +24,6 @@ struct sysv_sb_info { ...@@ -24,7 +24,6 @@ struct sysv_sb_info {
char s_bytesex; /* bytesex (le/be/pdp) */ char s_bytesex; /* bytesex (le/be/pdp) */
char s_truncate; /* if 1: names > SYSV_NAMELEN chars are truncated */ char s_truncate; /* if 1: names > SYSV_NAMELEN chars are truncated */
/* if 0: they are disallowed (ENAMETOOLONG) */ /* if 0: they are disallowed (ENAMETOOLONG) */
nlink_t s_link_max; /* max number of hard links to a file */
unsigned int s_inodes_per_block; /* number of inodes per block */ unsigned int s_inodes_per_block; /* number of inodes per block */
unsigned int s_inodes_per_block_1; /* inodes_per_block - 1 */ unsigned int s_inodes_per_block_1; /* inodes_per_block - 1 */
unsigned int s_inodes_per_block_bits; /* log2(inodes_per_block) */ unsigned int s_inodes_per_block_bits; /* log2(inodes_per_block) */
......
...@@ -32,8 +32,6 @@ ...@@ -32,8 +32,6 @@
#include <linux/crc-itu-t.h> #include <linux/crc-itu-t.h>
#include <linux/exportfs.h> #include <linux/exportfs.h>
enum { UDF_MAX_LINKS = 0xffff };
static inline int udf_match(int len1, const unsigned char *name1, int len2, static inline int udf_match(int len1, const unsigned char *name1, int len2,
const unsigned char *name2) const unsigned char *name2)
{ {
...@@ -649,10 +647,6 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) ...@@ -649,10 +647,6 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
struct udf_inode_info *dinfo = UDF_I(dir); struct udf_inode_info *dinfo = UDF_I(dir);
struct udf_inode_info *iinfo; struct udf_inode_info *iinfo;
err = -EMLINK;
if (dir->i_nlink >= UDF_MAX_LINKS)
goto out;
err = -EIO; err = -EIO;
inode = udf_new_inode(dir, S_IFDIR | mode, &err); inode = udf_new_inode(dir, S_IFDIR | mode, &err);
if (!inode) if (!inode)
...@@ -1032,9 +1026,6 @@ static int udf_link(struct dentry *old_dentry, struct inode *dir, ...@@ -1032,9 +1026,6 @@ static int udf_link(struct dentry *old_dentry, struct inode *dir,
struct fileIdentDesc cfi, *fi; struct fileIdentDesc cfi, *fi;
int err; int err;
if (inode->i_nlink >= UDF_MAX_LINKS)
return -EMLINK;
fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err); fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
if (!fi) { if (!fi) {
return err; return err;
...@@ -1126,10 +1117,6 @@ static int udf_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -1126,10 +1117,6 @@ static int udf_rename(struct inode *old_dir, struct dentry *old_dentry,
if (udf_get_lb_pblock(old_inode->i_sb, &tloc, 0) != if (udf_get_lb_pblock(old_inode->i_sb, &tloc, 0) !=
old_dir->i_ino) old_dir->i_ino)
goto end_rename; goto end_rename;
retval = -EMLINK;
if (!new_inode && new_dir->i_nlink >= UDF_MAX_LINKS)
goto end_rename;
} }
if (!nfi) { if (!nfi) {
nfi = udf_add_entry(new_dir, new_dentry, &nfibh, &ncfi, nfi = udf_add_entry(new_dir, new_dentry, &nfibh, &ncfi,
......
...@@ -75,6 +75,8 @@ ...@@ -75,6 +75,8 @@
#define UDF_DEFAULT_BLOCKSIZE 2048 #define UDF_DEFAULT_BLOCKSIZE 2048
enum { UDF_MAX_LINKS = 0xffff };
/* These are the "meat" - everything else is stuffing */ /* These are the "meat" - everything else is stuffing */
static int udf_fill_super(struct super_block *, void *, int); static int udf_fill_super(struct super_block *, void *, int);
static void udf_put_super(struct super_block *); static void udf_put_super(struct super_block *);
...@@ -2042,6 +2044,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) ...@@ -2042,6 +2044,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
goto error_out; goto error_out;
} }
sb->s_maxbytes = MAX_LFS_FILESIZE; sb->s_maxbytes = MAX_LFS_FILESIZE;
sb->s_max_links = UDF_MAX_LINKS;
return 0; return 0;
error_out: error_out:
......
...@@ -166,10 +166,6 @@ static int ufs_link (struct dentry * old_dentry, struct inode * dir, ...@@ -166,10 +166,6 @@ static int ufs_link (struct dentry * old_dentry, struct inode * dir,
int error; int error;
lock_ufs(dir->i_sb); lock_ufs(dir->i_sb);
if (inode->i_nlink >= UFS_LINK_MAX) {
unlock_ufs(dir->i_sb);
return -EMLINK;
}
inode->i_ctime = CURRENT_TIME_SEC; inode->i_ctime = CURRENT_TIME_SEC;
inode_inc_link_count(inode); inode_inc_link_count(inode);
...@@ -183,10 +179,7 @@ static int ufs_link (struct dentry * old_dentry, struct inode * dir, ...@@ -183,10 +179,7 @@ static int ufs_link (struct dentry * old_dentry, struct inode * dir,
static int ufs_mkdir(struct inode * dir, struct dentry * dentry, umode_t mode) static int ufs_mkdir(struct inode * dir, struct dentry * dentry, umode_t mode)
{ {
struct inode * inode; struct inode * inode;
int err = -EMLINK; int err;
if (dir->i_nlink >= UFS_LINK_MAX)
goto out;
lock_ufs(dir->i_sb); lock_ufs(dir->i_sb);
inode_inc_link_count(dir); inode_inc_link_count(dir);
...@@ -305,11 +298,6 @@ static int ufs_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -305,11 +298,6 @@ static int ufs_rename(struct inode *old_dir, struct dentry *old_dentry,
drop_nlink(new_inode); drop_nlink(new_inode);
inode_dec_link_count(new_inode); inode_dec_link_count(new_inode);
} else { } else {
if (dir_de) {
err = -EMLINK;
if (new_dir->i_nlink >= UFS_LINK_MAX)
goto out_dir;
}
err = ufs_add_link(new_dentry, old_inode); err = ufs_add_link(new_dentry, old_inode);
if (err) if (err)
goto out_dir; goto out_dir;
......
...@@ -1157,6 +1157,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -1157,6 +1157,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
"fast symlink size (%u)\n", uspi->s_maxsymlinklen); "fast symlink size (%u)\n", uspi->s_maxsymlinklen);
uspi->s_maxsymlinklen = maxsymlen; uspi->s_maxsymlinklen = maxsymlen;
} }
sb->s_max_links = UFS_LINK_MAX;
inode = ufs_iget(sb, UFS_ROOTINO); inode = ufs_iget(sb, UFS_ROOTINO);
if (IS_ERR(inode)) { if (IS_ERR(inode)) {
......
...@@ -118,17 +118,6 @@ xfs_rename( ...@@ -118,17 +118,6 @@ xfs_rename(
new_parent = (src_dp != target_dp); new_parent = (src_dp != target_dp);
src_is_directory = S_ISDIR(src_ip->i_d.di_mode); src_is_directory = S_ISDIR(src_ip->i_d.di_mode);
if (src_is_directory) {
/*
* Check for link count overflow on target_dp
*/
if (target_ip == NULL && new_parent &&
target_dp->i_d.di_nlink >= XFS_MAXLINK) {
error = XFS_ERROR(EMLINK);
goto std_return;
}
}
xfs_sort_for_rename(src_dp, target_dp, src_ip, target_ip, xfs_sort_for_rename(src_dp, target_dp, src_ip, target_ip,
inodes, &num_inodes); inodes, &num_inodes);
......
...@@ -1341,6 +1341,7 @@ xfs_fs_fill_super( ...@@ -1341,6 +1341,7 @@ xfs_fs_fill_super(
sb->s_blocksize = mp->m_sb.sb_blocksize; sb->s_blocksize = mp->m_sb.sb_blocksize;
sb->s_blocksize_bits = ffs(sb->s_blocksize) - 1; sb->s_blocksize_bits = ffs(sb->s_blocksize) - 1;
sb->s_maxbytes = xfs_max_file_offset(sb->s_blocksize_bits); sb->s_maxbytes = xfs_max_file_offset(sb->s_blocksize_bits);
sb->s_max_links = XFS_MAXLINK;
sb->s_time_gran = 1; sb->s_time_gran = 1;
set_posix_acl_flag(sb); set_posix_acl_flag(sb);
......
...@@ -296,8 +296,6 @@ xfs_bumplink( ...@@ -296,8 +296,6 @@ xfs_bumplink(
xfs_trans_t *tp, xfs_trans_t *tp,
xfs_inode_t *ip) xfs_inode_t *ip)
{ {
if (ip->i_d.di_nlink >= XFS_MAXLINK)
return XFS_ERROR(EMLINK);
xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG); xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG);
ASSERT(ip->i_d.di_nlink > 0); ASSERT(ip->i_d.di_nlink > 0);
......
...@@ -917,14 +917,6 @@ xfs_create( ...@@ -917,14 +917,6 @@ xfs_create(
xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT); xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
unlock_dp_on_error = B_TRUE; unlock_dp_on_error = B_TRUE;
/*
* Check for directory link count overflow.
*/
if (is_dir && dp->i_d.di_nlink >= XFS_MAXLINK) {
error = XFS_ERROR(EMLINK);
goto out_trans_cancel;
}
xfs_bmap_init(&free_list, &first_block); xfs_bmap_init(&free_list, &first_block);
/* /*
...@@ -1428,14 +1420,6 @@ xfs_link( ...@@ -1428,14 +1420,6 @@ xfs_link(
xfs_trans_ijoin(tp, sip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, sip, XFS_ILOCK_EXCL);
xfs_trans_ijoin(tp, tdp, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, tdp, XFS_ILOCK_EXCL);
/*
* If the source has too many links, we can't make any more to it.
*/
if (sip->i_d.di_nlink >= XFS_MAXLINK) {
error = XFS_ERROR(EMLINK);
goto error_return;
}
/* /*
* If we are using project inheritance, we only allow hard link * If we are using project inheritance, we only allow hard link
* creation in our tree when the project IDs are the same; else * creation in our tree when the project IDs are the same; else
......
...@@ -1459,6 +1459,7 @@ struct super_block { ...@@ -1459,6 +1459,7 @@ struct super_block {
u8 s_uuid[16]; /* UUID */ u8 s_uuid[16]; /* UUID */
void *s_fs_info; /* Filesystem private info */ void *s_fs_info; /* Filesystem private info */
unsigned int s_max_links;
fmode_t s_mode; fmode_t s_mode;
/* Granularity of c/m/atime in ns. /* Granularity of c/m/atime in ns.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment