Commit 198a1ca3 authored by Mark Fasheh's avatar Mark Fasheh

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: default avatarMark Fasheh <mfasheh@suse.com>
Acked-by: default avatarJoel Becker <joel.becker@oracle.com>
parent e7c17e43
...@@ -276,7 +276,7 @@ void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, ...@@ -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)OCFS2_I(inode)->ip_blkno,
(unsigned long long)le64_to_cpu(fe->i_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)) { if (fe->i_flags & cpu_to_le32(OCFS2_SYSTEM_FL)) {
OCFS2_I(inode)->ip_flags |= OCFS2_INODE_SYSTEM_FILE; OCFS2_I(inode)->ip_flags |= OCFS2_INODE_SYSTEM_FILE;
...@@ -1215,7 +1215,7 @@ int ocfs2_mark_inode_dirty(handle_t *handle, ...@@ -1215,7 +1215,7 @@ int ocfs2_mark_inode_dirty(handle_t *handle,
spin_unlock(&OCFS2_I(inode)->ip_lock); spin_unlock(&OCFS2_I(inode)->ip_lock);
fe->i_size = cpu_to_le64(i_size_read(inode)); 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_uid = cpu_to_le32(inode->i_uid);
fe->i_gid = cpu_to_le32(inode->i_gid); fe->i_gid = cpu_to_le32(inode->i_gid);
fe->i_mode = cpu_to_le16(inode->i_mode); fe->i_mode = cpu_to_le16(inode->i_mode);
...@@ -1252,7 +1252,7 @@ void ocfs2_refresh_inode(struct inode *inode, ...@@ -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_I(inode)->ip_dyn_features = le16_to_cpu(fe->i_dyn_features);
ocfs2_set_inode_flags(inode); ocfs2_set_inode_flags(inode);
i_size_write(inode, le64_to_cpu(fe->i_size)); 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_uid = le32_to_cpu(fe->i_uid);
inode->i_gid = le32_to_cpu(fe->i_gid); inode->i_gid = le32_to_cpu(fe->i_gid);
inode->i_mode = le16_to_cpu(fe->i_mode); inode->i_mode = le16_to_cpu(fe->i_mode);
......
...@@ -255,13 +255,13 @@ static int ocfs2_mknod(struct inode *dir, ...@@ -255,13 +255,13 @@ static int ocfs2_mknod(struct inode *dir,
return status; 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; status = -EMLINK;
goto leave; goto leave;
} }
dirfe = (struct ocfs2_dinode *) parent_fe_bh->b_data; 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. */ /* can't make a file in a deleted directory. */
status = -ENOENT; status = -ENOENT;
goto leave; goto leave;
...@@ -381,7 +381,7 @@ static int ocfs2_mknod(struct inode *dir, ...@@ -381,7 +381,7 @@ static int ocfs2_mknod(struct inode *dir,
mlog_errno(status); mlog_errno(status);
goto leave; goto leave;
} }
le16_add_cpu(&dirfe->i_links_count, 1); ocfs2_add_links_count(dirfe, 1);
status = ocfs2_journal_dirty(handle, parent_fe_bh); status = ocfs2_journal_dirty(handle, parent_fe_bh);
if (status < 0) { if (status < 0) {
mlog_errno(status); mlog_errno(status);
...@@ -529,7 +529,8 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb, ...@@ -529,7 +529,8 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
fe->i_mode = cpu_to_le16(inode->i_mode); fe->i_mode = cpu_to_le16(inode->i_mode);
if (S_ISCHR(inode->i_mode) || S_ISBLK(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->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; fe->i_last_eb_blk = 0;
strcpy(fe->i_signature, OCFS2_INODE_SIGNATURE); strcpy(fe->i_signature, OCFS2_INODE_SIGNATURE);
...@@ -668,7 +669,7 @@ static int ocfs2_link(struct dentry *old_dentry, ...@@ -668,7 +669,7 @@ static int ocfs2_link(struct dentry *old_dentry,
} }
fe = (struct ocfs2_dinode *) fe_bh->b_data; 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; err = -EMLINK;
goto out_unlock_inode; goto out_unlock_inode;
} }
...@@ -690,13 +691,13 @@ static int ocfs2_link(struct dentry *old_dentry, ...@@ -690,13 +691,13 @@ static int ocfs2_link(struct dentry *old_dentry,
inc_nlink(inode); inc_nlink(inode);
inode->i_ctime = CURRENT_TIME; 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 = cpu_to_le64(inode->i_ctime.tv_sec);
fe->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec); fe->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec);
err = ocfs2_journal_dirty(handle, fe_bh); err = ocfs2_journal_dirty(handle, fe_bh);
if (err < 0) { if (err < 0) {
le16_add_cpu(&fe->i_links_count, -1); ocfs2_add_links_count(fe, -1);
drop_nlink(inode); drop_nlink(inode);
mlog_errno(err); mlog_errno(err);
goto out_commit; goto out_commit;
...@@ -706,7 +707,7 @@ static int ocfs2_link(struct dentry *old_dentry, ...@@ -706,7 +707,7 @@ static int ocfs2_link(struct dentry *old_dentry,
OCFS2_I(inode)->ip_blkno, OCFS2_I(inode)->ip_blkno,
parent_fe_bh, &lookup); parent_fe_bh, &lookup);
if (err) { if (err) {
le16_add_cpu(&fe->i_links_count, -1); ocfs2_add_links_count(fe, -1);
drop_nlink(inode); drop_nlink(inode);
mlog_errno(err); mlog_errno(err);
goto out_commit; goto out_commit;
...@@ -895,7 +896,7 @@ static int ocfs2_unlink(struct inode *dir, ...@@ -895,7 +896,7 @@ static int ocfs2_unlink(struct inode *dir,
if (S_ISDIR(inode->i_mode)) if (S_ISDIR(inode->i_mode))
drop_nlink(inode); drop_nlink(inode);
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); status = ocfs2_journal_dirty(handle, fe_bh);
if (status < 0) { if (status < 0) {
...@@ -1139,7 +1140,7 @@ static int ocfs2_rename(struct inode *old_dir, ...@@ -1139,7 +1140,7 @@ static int ocfs2_rename(struct inode *old_dir,
} }
if (!new_inode && new_dir != 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; status = -EMLINK;
goto bail; goto bail;
} }
...@@ -1293,7 +1294,7 @@ static int ocfs2_rename(struct inode *old_dir, ...@@ -1293,7 +1294,7 @@ static int ocfs2_rename(struct inode *old_dir,
} }
if (S_ISDIR(new_inode->i_mode) || 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, status = ocfs2_orphan_add(osb, handle, new_inode,
newfe, orphan_name, newfe, orphan_name,
&orphan_insert, orphan_dir); &orphan_insert, orphan_dir);
...@@ -1313,9 +1314,9 @@ static int ocfs2_rename(struct inode *old_dir, ...@@ -1313,9 +1314,9 @@ static int ocfs2_rename(struct inode *old_dir,
new_dir->i_version++; new_dir->i_version++;
if (S_ISDIR(new_inode->i_mode)) if (S_ISDIR(new_inode->i_mode))
newfe->i_links_count = 0; ocfs2_set_links_count(newfe, 0);
else else
le16_add_cpu(&newfe->i_links_count, -1); ocfs2_add_links_count(newfe, -1);
status = ocfs2_journal_dirty(handle, newfe_bh); status = ocfs2_journal_dirty(handle, newfe_bh);
if (status < 0) { if (status < 0) {
...@@ -1412,11 +1413,10 @@ static int ocfs2_rename(struct inode *old_dir, ...@@ -1412,11 +1413,10 @@ static int ocfs2_rename(struct inode *old_dir,
old_dir_bh, old_dir_bh,
OCFS2_JOURNAL_ACCESS_WRITE); OCFS2_JOURNAL_ACCESS_WRITE);
fe = (struct ocfs2_dinode *) old_dir_bh->b_data; 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); status = ocfs2_journal_dirty(handle, old_dir_bh);
} }
} }
ocfs2_dentry_move(old_dentry, new_dentry, old_dir, new_dir); ocfs2_dentry_move(old_dentry, new_dentry, old_dir, new_dir);
status = 0; status = 0;
bail: bail:
...@@ -1614,7 +1614,7 @@ static int ocfs2_symlink(struct inode *dir, ...@@ -1614,7 +1614,7 @@ static int ocfs2_symlink(struct inode *dir,
} }
dirfe = (struct ocfs2_dinode *) parent_fe_bh->b_data; 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. */ /* can't make a file in a deleted directory. */
status = -ENOENT; status = -ENOENT;
goto bail; goto bail;
...@@ -1932,8 +1932,8 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb, ...@@ -1932,8 +1932,8 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
* underneath us... */ * underneath us... */
orphan_fe = (struct ocfs2_dinode *) orphan_dir_bh->b_data; orphan_fe = (struct ocfs2_dinode *) orphan_dir_bh->b_data;
if (S_ISDIR(inode->i_mode)) if (S_ISDIR(inode->i_mode))
le16_add_cpu(&orphan_fe->i_links_count, 1); ocfs2_add_links_count(orphan_fe, 1);
orphan_dir_inode->i_nlink = le16_to_cpu(orphan_fe->i_links_count); orphan_dir_inode->i_nlink = ocfs2_read_links_count(orphan_fe);
status = ocfs2_journal_dirty(handle, orphan_dir_bh); status = ocfs2_journal_dirty(handle, orphan_dir_bh);
if (status < 0) { if (status < 0) {
...@@ -2016,8 +2016,8 @@ int ocfs2_orphan_del(struct ocfs2_super *osb, ...@@ -2016,8 +2016,8 @@ int ocfs2_orphan_del(struct ocfs2_super *osb,
/* do the i_nlink dance! :) */ /* do the i_nlink dance! :) */
orphan_fe = (struct ocfs2_dinode *) orphan_dir_bh->b_data; orphan_fe = (struct ocfs2_dinode *) orphan_dir_bh->b_data;
if (S_ISDIR(inode->i_mode)) if (S_ISDIR(inode->i_mode))
le16_add_cpu(&orphan_fe->i_links_count, -1); ocfs2_add_links_count(orphan_fe, -1);
orphan_dir_inode->i_nlink = le16_to_cpu(orphan_fe->i_links_count); orphan_dir_inode->i_nlink = ocfs2_read_links_count(orphan_fe);
status = ocfs2_journal_dirty(handle, orphan_dir_bh); status = ocfs2_journal_dirty(handle, orphan_dir_bh);
if (status < 0) { if (status < 0) {
......
...@@ -408,6 +408,44 @@ static inline int ocfs2_supports_indexed_dirs(struct ocfs2_super *osb) ...@@ -408,6 +408,44 @@ static inline int ocfs2_supports_indexed_dirs(struct ocfs2_super *osb)
return 0; 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 /* set / clear functions because cluster events can make these happen
* in parallel so we want the transitions to be atomic. this also * in parallel so we want the transitions to be atomic. this also
* means that any future flags osb_flags must be protected by spinlock * 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] = { ...@@ -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_DIR_MIN_REC_LEN OCFS2_DIR_REC_LEN(1)
#define OCFS2_LINK_MAX 32000 #define OCFS2_LINK_MAX 32000
#define OCFS2_DX_LINK_MAX ((1U << 31) - 1U)
#define OCFS2_LINKS_HI_SHIFT 16
#define S_SHIFT 12 #define S_SHIFT 12
static unsigned char ocfs2_type_by_mode[S_IFMT >> S_SHIFT] = { static unsigned char ocfs2_type_by_mode[S_IFMT >> S_SHIFT] = {
...@@ -686,7 +688,7 @@ struct ocfs2_dinode { ...@@ -686,7 +688,7 @@ struct ocfs2_dinode {
belongs to */ belongs to */
__le16 i_suballoc_bit; /* Bit offset in suballocator __le16 i_suballoc_bit; /* Bit offset in suballocator
block group */ block group */
/*10*/ __le16 i_reserved0; /*10*/ __le16 i_links_count_hi; /* High 16 bits of links count */
__le16 i_xattr_inline_size; __le16 i_xattr_inline_size;
__le32 i_clusters; /* Cluster count */ __le32 i_clusters; /* Cluster count */
__le32 i_uid; /* Owner UID */ __le32 i_uid; /* Owner UID */
......
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