forked from Minki/linux
ocfs2: Increase max links count
Since we've now got a directory format capable of handling a large number of entries, we can increase the maximum link count supported. This only gets increased if the directory indexing feature is turned on. Signed-off-by: Mark Fasheh <mfasheh@suse.com> Acked-by: Joel Becker <joel.becker@oracle.com>
This commit is contained in:
parent
e7c17e4309
commit
198a1ca3b7
@ -276,7 +276,7 @@ void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
|
||||
(unsigned long long)OCFS2_I(inode)->ip_blkno,
|
||||
(unsigned long long)le64_to_cpu(fe->i_blkno));
|
||||
|
||||
inode->i_nlink = le16_to_cpu(fe->i_links_count);
|
||||
inode->i_nlink = ocfs2_read_links_count(fe);
|
||||
|
||||
if (fe->i_flags & cpu_to_le32(OCFS2_SYSTEM_FL)) {
|
||||
OCFS2_I(inode)->ip_flags |= OCFS2_INODE_SYSTEM_FILE;
|
||||
@ -1215,7 +1215,7 @@ int ocfs2_mark_inode_dirty(handle_t *handle,
|
||||
spin_unlock(&OCFS2_I(inode)->ip_lock);
|
||||
|
||||
fe->i_size = cpu_to_le64(i_size_read(inode));
|
||||
fe->i_links_count = cpu_to_le16(inode->i_nlink);
|
||||
ocfs2_set_links_count(fe, inode->i_nlink);
|
||||
fe->i_uid = cpu_to_le32(inode->i_uid);
|
||||
fe->i_gid = cpu_to_le32(inode->i_gid);
|
||||
fe->i_mode = cpu_to_le16(inode->i_mode);
|
||||
@ -1252,7 +1252,7 @@ void ocfs2_refresh_inode(struct inode *inode,
|
||||
OCFS2_I(inode)->ip_dyn_features = le16_to_cpu(fe->i_dyn_features);
|
||||
ocfs2_set_inode_flags(inode);
|
||||
i_size_write(inode, le64_to_cpu(fe->i_size));
|
||||
inode->i_nlink = le16_to_cpu(fe->i_links_count);
|
||||
inode->i_nlink = ocfs2_read_links_count(fe);
|
||||
inode->i_uid = le32_to_cpu(fe->i_uid);
|
||||
inode->i_gid = le32_to_cpu(fe->i_gid);
|
||||
inode->i_mode = le16_to_cpu(fe->i_mode);
|
||||
|
@ -255,13 +255,13 @@ static int ocfs2_mknod(struct inode *dir,
|
||||
return status;
|
||||
}
|
||||
|
||||
if (S_ISDIR(mode) && (dir->i_nlink >= OCFS2_LINK_MAX)) {
|
||||
if (S_ISDIR(mode) && (dir->i_nlink >= ocfs2_link_max(osb))) {
|
||||
status = -EMLINK;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
dirfe = (struct ocfs2_dinode *) parent_fe_bh->b_data;
|
||||
if (!dirfe->i_links_count) {
|
||||
if (!ocfs2_read_links_count(dirfe)) {
|
||||
/* can't make a file in a deleted directory. */
|
||||
status = -ENOENT;
|
||||
goto leave;
|
||||
@ -381,7 +381,7 @@ static int ocfs2_mknod(struct inode *dir,
|
||||
mlog_errno(status);
|
||||
goto leave;
|
||||
}
|
||||
le16_add_cpu(&dirfe->i_links_count, 1);
|
||||
ocfs2_add_links_count(dirfe, 1);
|
||||
status = ocfs2_journal_dirty(handle, parent_fe_bh);
|
||||
if (status < 0) {
|
||||
mlog_errno(status);
|
||||
@ -529,7 +529,8 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
|
||||
fe->i_mode = cpu_to_le16(inode->i_mode);
|
||||
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
|
||||
fe->id1.dev1.i_rdev = cpu_to_le64(huge_encode_dev(dev));
|
||||
fe->i_links_count = cpu_to_le16(inode->i_nlink);
|
||||
|
||||
ocfs2_set_links_count(fe, inode->i_nlink);
|
||||
|
||||
fe->i_last_eb_blk = 0;
|
||||
strcpy(fe->i_signature, OCFS2_INODE_SIGNATURE);
|
||||
@ -668,7 +669,7 @@ static int ocfs2_link(struct dentry *old_dentry,
|
||||
}
|
||||
|
||||
fe = (struct ocfs2_dinode *) fe_bh->b_data;
|
||||
if (le16_to_cpu(fe->i_links_count) >= OCFS2_LINK_MAX) {
|
||||
if (ocfs2_read_links_count(fe) >= ocfs2_link_max(osb)) {
|
||||
err = -EMLINK;
|
||||
goto out_unlock_inode;
|
||||
}
|
||||
@ -690,13 +691,13 @@ static int ocfs2_link(struct dentry *old_dentry,
|
||||
|
||||
inc_nlink(inode);
|
||||
inode->i_ctime = CURRENT_TIME;
|
||||
fe->i_links_count = cpu_to_le16(inode->i_nlink);
|
||||
ocfs2_set_links_count(fe, inode->i_nlink);
|
||||
fe->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec);
|
||||
fe->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec);
|
||||
|
||||
err = ocfs2_journal_dirty(handle, fe_bh);
|
||||
if (err < 0) {
|
||||
le16_add_cpu(&fe->i_links_count, -1);
|
||||
ocfs2_add_links_count(fe, -1);
|
||||
drop_nlink(inode);
|
||||
mlog_errno(err);
|
||||
goto out_commit;
|
||||
@ -706,7 +707,7 @@ static int ocfs2_link(struct dentry *old_dentry,
|
||||
OCFS2_I(inode)->ip_blkno,
|
||||
parent_fe_bh, &lookup);
|
||||
if (err) {
|
||||
le16_add_cpu(&fe->i_links_count, -1);
|
||||
ocfs2_add_links_count(fe, -1);
|
||||
drop_nlink(inode);
|
||||
mlog_errno(err);
|
||||
goto out_commit;
|
||||
@ -895,7 +896,7 @@ static int ocfs2_unlink(struct inode *dir,
|
||||
if (S_ISDIR(inode->i_mode))
|
||||
drop_nlink(inode);
|
||||
drop_nlink(inode);
|
||||
fe->i_links_count = cpu_to_le16(inode->i_nlink);
|
||||
ocfs2_set_links_count(fe, inode->i_nlink);
|
||||
|
||||
status = ocfs2_journal_dirty(handle, fe_bh);
|
||||
if (status < 0) {
|
||||
@ -1139,7 +1140,7 @@ static int ocfs2_rename(struct inode *old_dir,
|
||||
}
|
||||
|
||||
if (!new_inode && new_dir != old_dir &&
|
||||
new_dir->i_nlink >= OCFS2_LINK_MAX) {
|
||||
new_dir->i_nlink >= ocfs2_link_max(osb)) {
|
||||
status = -EMLINK;
|
||||
goto bail;
|
||||
}
|
||||
@ -1293,7 +1294,7 @@ static int ocfs2_rename(struct inode *old_dir,
|
||||
}
|
||||
|
||||
if (S_ISDIR(new_inode->i_mode) ||
|
||||
(newfe->i_links_count == cpu_to_le16(1))){
|
||||
(ocfs2_read_links_count(newfe) == 1)) {
|
||||
status = ocfs2_orphan_add(osb, handle, new_inode,
|
||||
newfe, orphan_name,
|
||||
&orphan_insert, orphan_dir);
|
||||
@ -1313,9 +1314,9 @@ static int ocfs2_rename(struct inode *old_dir,
|
||||
new_dir->i_version++;
|
||||
|
||||
if (S_ISDIR(new_inode->i_mode))
|
||||
newfe->i_links_count = 0;
|
||||
ocfs2_set_links_count(newfe, 0);
|
||||
else
|
||||
le16_add_cpu(&newfe->i_links_count, -1);
|
||||
ocfs2_add_links_count(newfe, -1);
|
||||
|
||||
status = ocfs2_journal_dirty(handle, newfe_bh);
|
||||
if (status < 0) {
|
||||
@ -1409,14 +1410,13 @@ static int ocfs2_rename(struct inode *old_dir,
|
||||
} else {
|
||||
struct ocfs2_dinode *fe;
|
||||
status = ocfs2_journal_access_di(handle, old_dir,
|
||||
old_dir_bh,
|
||||
OCFS2_JOURNAL_ACCESS_WRITE);
|
||||
old_dir_bh,
|
||||
OCFS2_JOURNAL_ACCESS_WRITE);
|
||||
fe = (struct ocfs2_dinode *) old_dir_bh->b_data;
|
||||
fe->i_links_count = cpu_to_le16(old_dir->i_nlink);
|
||||
ocfs2_set_links_count(fe, old_dir->i_nlink);
|
||||
status = ocfs2_journal_dirty(handle, old_dir_bh);
|
||||
}
|
||||
}
|
||||
|
||||
ocfs2_dentry_move(old_dentry, new_dentry, old_dir, new_dir);
|
||||
status = 0;
|
||||
bail:
|
||||
@ -1614,7 +1614,7 @@ static int ocfs2_symlink(struct inode *dir,
|
||||
}
|
||||
|
||||
dirfe = (struct ocfs2_dinode *) parent_fe_bh->b_data;
|
||||
if (!dirfe->i_links_count) {
|
||||
if (!ocfs2_read_links_count(dirfe)) {
|
||||
/* can't make a file in a deleted directory. */
|
||||
status = -ENOENT;
|
||||
goto bail;
|
||||
@ -1932,8 +1932,8 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
|
||||
* underneath us... */
|
||||
orphan_fe = (struct ocfs2_dinode *) orphan_dir_bh->b_data;
|
||||
if (S_ISDIR(inode->i_mode))
|
||||
le16_add_cpu(&orphan_fe->i_links_count, 1);
|
||||
orphan_dir_inode->i_nlink = le16_to_cpu(orphan_fe->i_links_count);
|
||||
ocfs2_add_links_count(orphan_fe, 1);
|
||||
orphan_dir_inode->i_nlink = ocfs2_read_links_count(orphan_fe);
|
||||
|
||||
status = ocfs2_journal_dirty(handle, orphan_dir_bh);
|
||||
if (status < 0) {
|
||||
@ -2016,8 +2016,8 @@ int ocfs2_orphan_del(struct ocfs2_super *osb,
|
||||
/* do the i_nlink dance! :) */
|
||||
orphan_fe = (struct ocfs2_dinode *) orphan_dir_bh->b_data;
|
||||
if (S_ISDIR(inode->i_mode))
|
||||
le16_add_cpu(&orphan_fe->i_links_count, -1);
|
||||
orphan_dir_inode->i_nlink = le16_to_cpu(orphan_fe->i_links_count);
|
||||
ocfs2_add_links_count(orphan_fe, -1);
|
||||
orphan_dir_inode->i_nlink = ocfs2_read_links_count(orphan_fe);
|
||||
|
||||
status = ocfs2_journal_dirty(handle, orphan_dir_bh);
|
||||
if (status < 0) {
|
||||
|
@ -408,6 +408,44 @@ static inline int ocfs2_supports_indexed_dirs(struct ocfs2_super *osb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline unsigned int ocfs2_link_max(struct ocfs2_super *osb)
|
||||
{
|
||||
if (ocfs2_supports_indexed_dirs(osb))
|
||||
return OCFS2_DX_LINK_MAX;
|
||||
return OCFS2_LINK_MAX;
|
||||
}
|
||||
|
||||
static inline unsigned int ocfs2_read_links_count(struct ocfs2_dinode *di)
|
||||
{
|
||||
u32 nlink = le16_to_cpu(di->i_links_count);
|
||||
u32 hi = le16_to_cpu(di->i_links_count_hi);
|
||||
|
||||
if (di->i_dyn_features & cpu_to_le16(OCFS2_INDEXED_DIR_FL))
|
||||
nlink |= (hi << OCFS2_LINKS_HI_SHIFT);
|
||||
|
||||
return nlink;
|
||||
}
|
||||
|
||||
static inline void ocfs2_set_links_count(struct ocfs2_dinode *di, u32 nlink)
|
||||
{
|
||||
u16 lo, hi;
|
||||
|
||||
lo = nlink;
|
||||
hi = nlink >> OCFS2_LINKS_HI_SHIFT;
|
||||
|
||||
di->i_links_count = cpu_to_le16(lo);
|
||||
di->i_links_count_hi = cpu_to_le16(hi);
|
||||
}
|
||||
|
||||
static inline void ocfs2_add_links_count(struct ocfs2_dinode *di, int n)
|
||||
{
|
||||
u32 links = ocfs2_read_links_count(di);
|
||||
|
||||
links += n;
|
||||
|
||||
ocfs2_set_links_count(di, links);
|
||||
}
|
||||
|
||||
/* set / clear functions because cluster events can make these happen
|
||||
* in parallel so we want the transitions to be atomic. this also
|
||||
* means that any future flags osb_flags must be protected by spinlock
|
||||
|
@ -419,6 +419,8 @@ static struct ocfs2_system_inode_info ocfs2_system_inodes[NUM_SYSTEM_INODES] = {
|
||||
#define OCFS2_DIR_MIN_REC_LEN OCFS2_DIR_REC_LEN(1)
|
||||
|
||||
#define OCFS2_LINK_MAX 32000
|
||||
#define OCFS2_DX_LINK_MAX ((1U << 31) - 1U)
|
||||
#define OCFS2_LINKS_HI_SHIFT 16
|
||||
|
||||
#define S_SHIFT 12
|
||||
static unsigned char ocfs2_type_by_mode[S_IFMT >> S_SHIFT] = {
|
||||
@ -686,7 +688,7 @@ struct ocfs2_dinode {
|
||||
belongs to */
|
||||
__le16 i_suballoc_bit; /* Bit offset in suballocator
|
||||
block group */
|
||||
/*10*/ __le16 i_reserved0;
|
||||
/*10*/ __le16 i_links_count_hi; /* High 16 bits of links count */
|
||||
__le16 i_xattr_inline_size;
|
||||
__le32 i_clusters; /* Cluster count */
|
||||
__le32 i_uid; /* Owner UID */
|
||||
|
Loading…
Reference in New Issue
Block a user