aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2
diff options
context:
space:
mode:
authorMark Fasheh <mfasheh@suse.com>2008-11-20 20:54:57 -0500
committerMark Fasheh <mfasheh@suse.com>2009-04-03 14:39:16 -0400
commit198a1ca3b735986542c538e38b9499ffcaed7005 (patch)
tree3b02034534c4640e72623088a59d1e942c38e7c3 /fs/ocfs2
parente7c17e43090afe558c40bfb66637744c27bd2aeb (diff)
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>
Diffstat (limited to 'fs/ocfs2')
-rw-r--r--fs/ocfs2/inode.c6
-rw-r--r--fs/ocfs2/namei.c44
-rw-r--r--fs/ocfs2/ocfs2.h38
-rw-r--r--fs/ocfs2/ocfs2_fs.h4
4 files changed, 66 insertions, 26 deletions
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c
index d273c4a51a00..f1f77b2f5947 100644
--- a/fs/ocfs2/inode.c
+++ b/fs/ocfs2/inode.c
@@ -276,7 +276,7 @@ void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
276 (unsigned long long)OCFS2_I(inode)->ip_blkno, 276 (unsigned long long)OCFS2_I(inode)->ip_blkno,
277 (unsigned long long)le64_to_cpu(fe->i_blkno)); 277 (unsigned long long)le64_to_cpu(fe->i_blkno));
278 278
279 inode->i_nlink = le16_to_cpu(fe->i_links_count); 279 inode->i_nlink = ocfs2_read_links_count(fe);
280 280
281 if (fe->i_flags & cpu_to_le32(OCFS2_SYSTEM_FL)) { 281 if (fe->i_flags & cpu_to_le32(OCFS2_SYSTEM_FL)) {
282 OCFS2_I(inode)->ip_flags |= OCFS2_INODE_SYSTEM_FILE; 282 OCFS2_I(inode)->ip_flags |= OCFS2_INODE_SYSTEM_FILE;
@@ -1215,7 +1215,7 @@ int ocfs2_mark_inode_dirty(handle_t *handle,
1215 spin_unlock(&OCFS2_I(inode)->ip_lock); 1215 spin_unlock(&OCFS2_I(inode)->ip_lock);
1216 1216
1217 fe->i_size = cpu_to_le64(i_size_read(inode)); 1217 fe->i_size = cpu_to_le64(i_size_read(inode));
1218 fe->i_links_count = cpu_to_le16(inode->i_nlink); 1218 ocfs2_set_links_count(fe, inode->i_nlink);
1219 fe->i_uid = cpu_to_le32(inode->i_uid); 1219 fe->i_uid = cpu_to_le32(inode->i_uid);
1220 fe->i_gid = cpu_to_le32(inode->i_gid); 1220 fe->i_gid = cpu_to_le32(inode->i_gid);
1221 fe->i_mode = cpu_to_le16(inode->i_mode); 1221 fe->i_mode = cpu_to_le16(inode->i_mode);
@@ -1252,7 +1252,7 @@ void ocfs2_refresh_inode(struct inode *inode,
1252 OCFS2_I(inode)->ip_dyn_features = le16_to_cpu(fe->i_dyn_features); 1252 OCFS2_I(inode)->ip_dyn_features = le16_to_cpu(fe->i_dyn_features);
1253 ocfs2_set_inode_flags(inode); 1253 ocfs2_set_inode_flags(inode);
1254 i_size_write(inode, le64_to_cpu(fe->i_size)); 1254 i_size_write(inode, le64_to_cpu(fe->i_size));
1255 inode->i_nlink = le16_to_cpu(fe->i_links_count); 1255 inode->i_nlink = ocfs2_read_links_count(fe);
1256 inode->i_uid = le32_to_cpu(fe->i_uid); 1256 inode->i_uid = le32_to_cpu(fe->i_uid);
1257 inode->i_gid = le32_to_cpu(fe->i_gid); 1257 inode->i_gid = le32_to_cpu(fe->i_gid);
1258 inode->i_mode = le16_to_cpu(fe->i_mode); 1258 inode->i_mode = le16_to_cpu(fe->i_mode);
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index f911edc8378b..67113cfddc9b 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -255,13 +255,13 @@ static int ocfs2_mknod(struct inode *dir,
255 return status; 255 return status;
256 } 256 }
257 257
258 if (S_ISDIR(mode) && (dir->i_nlink >= OCFS2_LINK_MAX)) { 258 if (S_ISDIR(mode) && (dir->i_nlink >= ocfs2_link_max(osb))) {
259 status = -EMLINK; 259 status = -EMLINK;
260 goto leave; 260 goto leave;
261 } 261 }
262 262
263 dirfe = (struct ocfs2_dinode *) parent_fe_bh->b_data; 263 dirfe = (struct ocfs2_dinode *) parent_fe_bh->b_data;
264 if (!dirfe->i_links_count) { 264 if (!ocfs2_read_links_count(dirfe)) {
265 /* can't make a file in a deleted directory. */ 265 /* can't make a file in a deleted directory. */
266 status = -ENOENT; 266 status = -ENOENT;
267 goto leave; 267 goto leave;
@@ -381,7 +381,7 @@ static int ocfs2_mknod(struct inode *dir,
381 mlog_errno(status); 381 mlog_errno(status);
382 goto leave; 382 goto leave;
383 } 383 }
384 le16_add_cpu(&dirfe->i_links_count, 1); 384 ocfs2_add_links_count(dirfe, 1);
385 status = ocfs2_journal_dirty(handle, parent_fe_bh); 385 status = ocfs2_journal_dirty(handle, parent_fe_bh);
386 if (status < 0) { 386 if (status < 0) {
387 mlog_errno(status); 387 mlog_errno(status);
@@ -529,7 +529,8 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
529 fe->i_mode = cpu_to_le16(inode->i_mode); 529 fe->i_mode = cpu_to_le16(inode->i_mode);
530 if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) 530 if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
531 fe->id1.dev1.i_rdev = cpu_to_le64(huge_encode_dev(dev)); 531 fe->id1.dev1.i_rdev = cpu_to_le64(huge_encode_dev(dev));
532 fe->i_links_count = cpu_to_le16(inode->i_nlink); 532
533 ocfs2_set_links_count(fe, inode->i_nlink);
533 534
534 fe->i_last_eb_blk = 0; 535 fe->i_last_eb_blk = 0;
535 strcpy(fe->i_signature, OCFS2_INODE_SIGNATURE); 536 strcpy(fe->i_signature, OCFS2_INODE_SIGNATURE);
@@ -668,7 +669,7 @@ static int ocfs2_link(struct dentry *old_dentry,
668 } 669 }
669 670
670 fe = (struct ocfs2_dinode *) fe_bh->b_data; 671 fe = (struct ocfs2_dinode *) fe_bh->b_data;
671 if (le16_to_cpu(fe->i_links_count) >= OCFS2_LINK_MAX) { 672 if (ocfs2_read_links_count(fe) >= ocfs2_link_max(osb)) {
672 err = -EMLINK; 673 err = -EMLINK;
673 goto out_unlock_inode; 674 goto out_unlock_inode;
674 } 675 }
@@ -690,13 +691,13 @@ static int ocfs2_link(struct dentry *old_dentry,
690 691
691 inc_nlink(inode); 692 inc_nlink(inode);
692 inode->i_ctime = CURRENT_TIME; 693 inode->i_ctime = CURRENT_TIME;
693 fe->i_links_count = cpu_to_le16(inode->i_nlink); 694 ocfs2_set_links_count(fe, inode->i_nlink);
694 fe->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec); 695 fe->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec);
695 fe->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec); 696 fe->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec);
696 697
697 err = ocfs2_journal_dirty(handle, fe_bh); 698 err = ocfs2_journal_dirty(handle, fe_bh);
698 if (err < 0) { 699 if (err < 0) {
699 le16_add_cpu(&fe->i_links_count, -1); 700 ocfs2_add_links_count(fe, -1);
700 drop_nlink(inode); 701 drop_nlink(inode);
701 mlog_errno(err); 702 mlog_errno(err);
702 goto out_commit; 703 goto out_commit;
@@ -706,7 +707,7 @@ static int ocfs2_link(struct dentry *old_dentry,
706 OCFS2_I(inode)->ip_blkno, 707 OCFS2_I(inode)->ip_blkno,
707 parent_fe_bh, &lookup); 708 parent_fe_bh, &lookup);
708 if (err) { 709 if (err) {
709 le16_add_cpu(&fe->i_links_count, -1); 710 ocfs2_add_links_count(fe, -1);
710 drop_nlink(inode); 711 drop_nlink(inode);
711 mlog_errno(err); 712 mlog_errno(err);
712 goto out_commit; 713 goto out_commit;
@@ -895,7 +896,7 @@ static int ocfs2_unlink(struct inode *dir,
895 if (S_ISDIR(inode->i_mode)) 896 if (S_ISDIR(inode->i_mode))
896 drop_nlink(inode); 897 drop_nlink(inode);
897 drop_nlink(inode); 898 drop_nlink(inode);
898 fe->i_links_count = cpu_to_le16(inode->i_nlink); 899 ocfs2_set_links_count(fe, inode->i_nlink);
899 900
900 status = ocfs2_journal_dirty(handle, fe_bh); 901 status = ocfs2_journal_dirty(handle, fe_bh);
901 if (status < 0) { 902 if (status < 0) {
@@ -1139,7 +1140,7 @@ static int ocfs2_rename(struct inode *old_dir,
1139 } 1140 }
1140 1141
1141 if (!new_inode && new_dir != old_dir && 1142 if (!new_inode && new_dir != old_dir &&
1142 new_dir->i_nlink >= OCFS2_LINK_MAX) { 1143 new_dir->i_nlink >= ocfs2_link_max(osb)) {
1143 status = -EMLINK; 1144 status = -EMLINK;
1144 goto bail; 1145 goto bail;
1145 } 1146 }
@@ -1293,7 +1294,7 @@ static int ocfs2_rename(struct inode *old_dir,
1293 } 1294 }
1294 1295
1295 if (S_ISDIR(new_inode->i_mode) || 1296 if (S_ISDIR(new_inode->i_mode) ||
1296 (newfe->i_links_count == cpu_to_le16(1))){ 1297 (ocfs2_read_links_count(newfe) == 1)) {
1297 status = ocfs2_orphan_add(osb, handle, new_inode, 1298 status = ocfs2_orphan_add(osb, handle, new_inode,
1298 newfe, orphan_name, 1299 newfe, orphan_name,
1299 &orphan_insert, orphan_dir); 1300 &orphan_insert, orphan_dir);
@@ -1313,9 +1314,9 @@ static int ocfs2_rename(struct inode *old_dir,
1313 new_dir->i_version++; 1314 new_dir->i_version++;
1314 1315
1315 if (S_ISDIR(new_inode->i_mode)) 1316 if (S_ISDIR(new_inode->i_mode))
1316 newfe->i_links_count = 0; 1317 ocfs2_set_links_count(newfe, 0);
1317 else 1318 else
1318 le16_add_cpu(&newfe->i_links_count, -1); 1319 ocfs2_add_links_count(newfe, -1);
1319 1320
1320 status = ocfs2_journal_dirty(handle, newfe_bh); 1321 status = ocfs2_journal_dirty(handle, newfe_bh);
1321 if (status < 0) { 1322 if (status < 0) {
@@ -1409,14 +1410,13 @@ static int ocfs2_rename(struct inode *old_dir,
1409 } else { 1410 } else {
1410 struct ocfs2_dinode *fe; 1411 struct ocfs2_dinode *fe;
1411 status = ocfs2_journal_access_di(handle, old_dir, 1412 status = ocfs2_journal_access_di(handle, old_dir,
1412 old_dir_bh, 1413 old_dir_bh,
1413 OCFS2_JOURNAL_ACCESS_WRITE); 1414 OCFS2_JOURNAL_ACCESS_WRITE);
1414 fe = (struct ocfs2_dinode *) old_dir_bh->b_data; 1415 fe = (struct ocfs2_dinode *) old_dir_bh->b_data;
1415 fe->i_links_count = cpu_to_le16(old_dir->i_nlink); 1416 ocfs2_set_links_count(fe, old_dir->i_nlink);
1416 status = ocfs2_journal_dirty(handle, old_dir_bh); 1417 status = ocfs2_journal_dirty(handle, old_dir_bh);
1417 } 1418 }
1418 } 1419 }
1419
1420 ocfs2_dentry_move(old_dentry, new_dentry, old_dir, new_dir); 1420 ocfs2_dentry_move(old_dentry, new_dentry, old_dir, new_dir);
1421 status = 0; 1421 status = 0;
1422bail: 1422bail:
@@ -1614,7 +1614,7 @@ static int ocfs2_symlink(struct inode *dir,
1614 } 1614 }
1615 1615
1616 dirfe = (struct ocfs2_dinode *) parent_fe_bh->b_data; 1616 dirfe = (struct ocfs2_dinode *) parent_fe_bh->b_data;
1617 if (!dirfe->i_links_count) { 1617 if (!ocfs2_read_links_count(dirfe)) {
1618 /* can't make a file in a deleted directory. */ 1618 /* can't make a file in a deleted directory. */
1619 status = -ENOENT; 1619 status = -ENOENT;
1620 goto bail; 1620 goto bail;
@@ -1932,8 +1932,8 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
1932 * underneath us... */ 1932 * underneath us... */
1933 orphan_fe = (struct ocfs2_dinode *) orphan_dir_bh->b_data; 1933 orphan_fe = (struct ocfs2_dinode *) orphan_dir_bh->b_data;
1934 if (S_ISDIR(inode->i_mode)) 1934 if (S_ISDIR(inode->i_mode))
1935 le16_add_cpu(&orphan_fe->i_links_count, 1); 1935 ocfs2_add_links_count(orphan_fe, 1);
1936 orphan_dir_inode->i_nlink = le16_to_cpu(orphan_fe->i_links_count); 1936 orphan_dir_inode->i_nlink = ocfs2_read_links_count(orphan_fe);
1937 1937
1938 status = ocfs2_journal_dirty(handle, orphan_dir_bh); 1938 status = ocfs2_journal_dirty(handle, orphan_dir_bh);
1939 if (status < 0) { 1939 if (status < 0) {
@@ -2016,8 +2016,8 @@ int ocfs2_orphan_del(struct ocfs2_super *osb,
2016 /* do the i_nlink dance! :) */ 2016 /* do the i_nlink dance! :) */
2017 orphan_fe = (struct ocfs2_dinode *) orphan_dir_bh->b_data; 2017 orphan_fe = (struct ocfs2_dinode *) orphan_dir_bh->b_data;
2018 if (S_ISDIR(inode->i_mode)) 2018 if (S_ISDIR(inode->i_mode))
2019 le16_add_cpu(&orphan_fe->i_links_count, -1); 2019 ocfs2_add_links_count(orphan_fe, -1);
2020 orphan_dir_inode->i_nlink = le16_to_cpu(orphan_fe->i_links_count); 2020 orphan_dir_inode->i_nlink = ocfs2_read_links_count(orphan_fe);
2021 2021
2022 status = ocfs2_journal_dirty(handle, orphan_dir_bh); 2022 status = ocfs2_journal_dirty(handle, orphan_dir_bh);
2023 if (status < 0) { 2023 if (status < 0) {
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
index 3749c32c2fc4..fa3c6d3f0bd2 100644
--- a/fs/ocfs2/ocfs2.h
+++ b/fs/ocfs2/ocfs2.h
@@ -408,6 +408,44 @@ static inline int ocfs2_supports_indexed_dirs(struct ocfs2_super *osb)
408 return 0; 408 return 0;
409} 409}
410 410
411static inline unsigned int ocfs2_link_max(struct ocfs2_super *osb)
412{
413 if (ocfs2_supports_indexed_dirs(osb))
414 return OCFS2_DX_LINK_MAX;
415 return OCFS2_LINK_MAX;
416}
417
418static inline unsigned int ocfs2_read_links_count(struct ocfs2_dinode *di)
419{
420 u32 nlink = le16_to_cpu(di->i_links_count);
421 u32 hi = le16_to_cpu(di->i_links_count_hi);
422
423 if (di->i_dyn_features & cpu_to_le16(OCFS2_INDEXED_DIR_FL))
424 nlink |= (hi << OCFS2_LINKS_HI_SHIFT);
425
426 return nlink;
427}
428
429static inline void ocfs2_set_links_count(struct ocfs2_dinode *di, u32 nlink)
430{
431 u16 lo, hi;
432
433 lo = nlink;
434 hi = nlink >> OCFS2_LINKS_HI_SHIFT;
435
436 di->i_links_count = cpu_to_le16(lo);
437 di->i_links_count_hi = cpu_to_le16(hi);
438}
439
440static inline void ocfs2_add_links_count(struct ocfs2_dinode *di, int n)
441{
442 u32 links = ocfs2_read_links_count(di);
443
444 links += n;
445
446 ocfs2_set_links_count(di, links);
447}
448
411/* set / clear functions because cluster events can make these happen 449/* set / clear functions because cluster events can make these happen
412 * in parallel so we want the transitions to be atomic. this also 450 * in parallel so we want the transitions to be atomic. this also
413 * means that any future flags osb_flags must be protected by spinlock 451 * means that any future flags osb_flags must be protected by spinlock
diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h
index d549b1799a61..43da76eff9ae 100644
--- a/fs/ocfs2/ocfs2_fs.h
+++ b/fs/ocfs2/ocfs2_fs.h
@@ -419,6 +419,8 @@ static struct ocfs2_system_inode_info ocfs2_system_inodes[NUM_SYSTEM_INODES] = {
419#define OCFS2_DIR_MIN_REC_LEN OCFS2_DIR_REC_LEN(1) 419#define OCFS2_DIR_MIN_REC_LEN OCFS2_DIR_REC_LEN(1)
420 420
421#define OCFS2_LINK_MAX 32000 421#define OCFS2_LINK_MAX 32000
422#define OCFS2_DX_LINK_MAX ((1U << 31) - 1U)
423#define OCFS2_LINKS_HI_SHIFT 16
422 424
423#define S_SHIFT 12 425#define S_SHIFT 12
424static unsigned char ocfs2_type_by_mode[S_IFMT >> S_SHIFT] = { 426static unsigned char ocfs2_type_by_mode[S_IFMT >> S_SHIFT] = {
@@ -686,7 +688,7 @@ struct ocfs2_dinode {
686 belongs to */ 688 belongs to */
687 __le16 i_suballoc_bit; /* Bit offset in suballocator 689 __le16 i_suballoc_bit; /* Bit offset in suballocator
688 block group */ 690 block group */
689/*10*/ __le16 i_reserved0; 691/*10*/ __le16 i_links_count_hi; /* High 16 bits of links count */
690 __le16 i_xattr_inline_size; 692 __le16 i_xattr_inline_size;
691 __le32 i_clusters; /* Cluster count */ 693 __le32 i_clusters; /* Cluster count */
692 __le32 i_uid; /* Owner UID */ 694 __le32 i_uid; /* Owner UID */