From 04e99455ea5bb17ea7c2e7bb0970168efb736242 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 25 Jan 2011 09:06:19 +0000 Subject: xfs: only lock the rt bitmap inode once per allocation Currently both xfs_rtpick_extent and xfs_rtallocate_extent call xfs_trans_iget to grab and lock the rt bitmap inode, which results in a deadlock since the removal of the lock recursion counters in commit "xfs: simplify inode to transaction joining" Fix this by acquiring and locking the inode in xfs_bmap_rtalloc before calling into xfs_rtpick_extent and xfs_rtallocate_extent. Signed-off-by: Christoph Hellwig Signed-off-by: Alex Elder --- fs/xfs/xfs_bmap.c | 11 +++++++++++ fs/xfs/xfs_rtalloc.c | 34 +++++++++++++--------------------- 2 files changed, 24 insertions(+), 21 deletions(-) (limited to 'fs') diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index dc3afd7739ff..2f89af25996f 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -2333,6 +2333,7 @@ xfs_bmap_rtalloc( xfs_extlen_t prod = 0; /* product factor for allocators */ xfs_extlen_t ralen = 0; /* realtime allocation length */ xfs_extlen_t align; /* minimum allocation alignment */ + xfs_inode_t *ip; /* bitmap incore inode */ xfs_rtblock_t rtb; mp = ap->ip->i_mount; @@ -2365,6 +2366,16 @@ xfs_bmap_rtalloc( */ if (ralen * mp->m_sb.sb_rextsize >= MAXEXTLEN) ralen = MAXEXTLEN / mp->m_sb.sb_rextsize; + + /* + * Lock out other modifications to the RT bitmap inode. + */ + error = xfs_trans_iget(mp, ap->tp, mp->m_sb.sb_rbmino, 0, + XFS_ILOCK_EXCL, &ip); + if (error) + return error; + ASSERT(ip == mp->m_rbmip); + /* * If it's an allocation to an empty file at offset 0, * pick an extent that will space things out in the rt area. diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index 12a191385310..037fab140242 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -2075,15 +2075,15 @@ xfs_rtallocate_extent( xfs_extlen_t prod, /* extent product factor */ xfs_rtblock_t *rtblock) /* out: start block allocated */ { + xfs_mount_t *mp = tp->t_mountp; int error; /* error value */ - xfs_inode_t *ip; /* inode for bitmap file */ - xfs_mount_t *mp; /* file system mount structure */ xfs_rtblock_t r; /* result allocated block */ xfs_fsblock_t sb; /* summary file block number */ xfs_buf_t *sumbp; /* summary file block buffer */ + ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL)); ASSERT(minlen > 0 && minlen <= maxlen); - mp = tp->t_mountp; + /* * If prod is set then figure out what to do to minlen and maxlen. */ @@ -2099,12 +2099,7 @@ xfs_rtallocate_extent( return 0; } } - /* - * Lock out other callers by grabbing the bitmap inode lock. - */ - if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0, - XFS_ILOCK_EXCL, &ip))) - return error; + sumbp = NULL; /* * Allocate by size, or near another block, or exactly at some block. @@ -2123,11 +2118,12 @@ xfs_rtallocate_extent( len, &sumbp, &sb, prod, &r); break; default: + error = EIO; ASSERT(0); } - if (error) { + if (error) return error; - } + /* * If it worked, update the superblock. */ @@ -2306,20 +2302,16 @@ xfs_rtpick_extent( xfs_rtblock_t *pick) /* result rt extent */ { xfs_rtblock_t b; /* result block */ - int error; /* error return value */ - xfs_inode_t *ip; /* bitmap incore inode */ int log2; /* log of sequence number */ __uint64_t resid; /* residual after log removed */ __uint64_t seq; /* sequence number of file creation */ __uint64_t *seqp; /* pointer to seqno in inode */ - if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0, - XFS_ILOCK_EXCL, &ip))) - return error; - ASSERT(ip == mp->m_rbmip); - seqp = (__uint64_t *)&ip->i_d.di_atime; - if (!(ip->i_d.di_flags & XFS_DIFLAG_NEWRTBM)) { - ip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM; + ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL)); + + seqp = (__uint64_t *)&mp->m_rbmip->i_d.di_atime; + if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM)) { + mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM; *seqp = 0; } seq = *seqp; @@ -2335,7 +2327,7 @@ xfs_rtpick_extent( b = mp->m_sb.sb_rextents - len; } *seqp = seq + 1; - xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); + xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE); *pick = b; return 0; } -- cgit From 0d8b30ad19bf13197cbcd786e2cd5a2ecef72e68 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 25 Jan 2011 09:06:20 +0000 Subject: xfs: fix xfs_get_extsz_hint for a zero extent size hint We can easily set the extsize flag without setting an extent size hint, or one that evaluates to zero. Historically the di_extsize field was only used when it was non-zero, but the commit "Cleanup inode extent size hint extraction" broke this. Restore the old behaviour, thus fixing xfsqa 090 with a debug kernel. Signed-off-by: Christoph Hellwig Signed-off-by: Alex Elder --- fs/xfs/xfs_rw.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) (limited to 'fs') diff --git a/fs/xfs/xfs_rw.c b/fs/xfs/xfs_rw.c index 56861d5daaef..ccd3adf640ee 100644 --- a/fs/xfs/xfs_rw.c +++ b/fs/xfs/xfs_rw.c @@ -173,17 +173,9 @@ xfs_extlen_t xfs_get_extsz_hint( struct xfs_inode *ip) { - xfs_extlen_t extsz; - - if (unlikely(XFS_IS_REALTIME_INODE(ip))) { - extsz = (ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE) - ? ip->i_d.di_extsize - : ip->i_mount->m_sb.sb_rextsize; - ASSERT(extsz); - } else { - extsz = (ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE) - ? ip->i_d.di_extsize : 0; - } - - return extsz; + if ((ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE) && ip->i_d.di_extsize) + return ip->i_d.di_extsize; + if (XFS_IS_REALTIME_INODE(ip)) + return ip->i_mount->m_sb.sb_rextsize; + return 0; } -- cgit From 9681153b460006923bb1e9d39b05b80ec09d6b4e Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 25 Jan 2011 09:06:21 +0000 Subject: xfs: add lockdep annotations for the rt inodes The rt bitmap and summary inodes do not participate in the normal inode locking protocol. Instead the rt bitmap inode can be locked in any transaction involving rt allocations, and the both of the rt inodes can be locked at the same time. Add specific lockdep subclasses for the rt inodes to prevent lockdep from blowing up. Signed-off-by: Christoph Hellwig Signed-off-by: Alex Elder --- fs/xfs/xfs_bmap.c | 2 +- fs/xfs/xfs_inode.h | 23 +++++++++++++++-------- fs/xfs/xfs_rtalloc.c | 16 ++++++++++------ 3 files changed, 26 insertions(+), 15 deletions(-) (limited to 'fs') diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 2f89af25996f..d8d090665283 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -2371,7 +2371,7 @@ xfs_bmap_rtalloc( * Lock out other modifications to the RT bitmap inode. */ error = xfs_trans_iget(mp, ap->tp, mp->m_sb.sb_rbmino, 0, - XFS_ILOCK_EXCL, &ip); + XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP, &ip); if (error) return error; ASSERT(ip == mp->m_rbmip); diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 5c95fa8ec11d..f753200cef8d 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -409,28 +409,35 @@ static inline void xfs_ifunlock(xfs_inode_t *ip) /* * Flags for lockdep annotations. * - * XFS_I[O]LOCK_PARENT - for operations that require locking two inodes - * (ie directory operations that require locking a directory inode and - * an entry inode). The first inode gets locked with this flag so it - * gets a lockdep subclass of 1 and the second lock will have a lockdep - * subclass of 0. + * XFS_LOCK_PARENT - for directory operations that require locking a + * parent directory inode and a child entry inode. The parent gets locked + * with this flag so it gets a lockdep subclass of 1 and the child entry + * lock will have a lockdep subclass of 0. + * + * XFS_LOCK_RTBITMAP/XFS_LOCK_RTSUM - the realtime device bitmap and summary + * inodes do not participate in the normal lock order, and thus have their + * own subclasses. * * XFS_LOCK_INUMORDER - for locking several inodes at the some time * with xfs_lock_inodes(). This flag is used as the starting subclass * and each subsequent lock acquired will increment the subclass by one. - * So the first lock acquired will have a lockdep subclass of 2, the - * second lock will have a lockdep subclass of 3, and so on. It is + * So the first lock acquired will have a lockdep subclass of 4, the + * second lock will have a lockdep subclass of 5, and so on. It is * the responsibility of the class builder to shift this to the correct * portion of the lock_mode lockdep mask. */ #define XFS_LOCK_PARENT 1 -#define XFS_LOCK_INUMORDER 2 +#define XFS_LOCK_RTBITMAP 2 +#define XFS_LOCK_RTSUM 3 +#define XFS_LOCK_INUMORDER 4 #define XFS_IOLOCK_SHIFT 16 #define XFS_IOLOCK_PARENT (XFS_LOCK_PARENT << XFS_IOLOCK_SHIFT) #define XFS_ILOCK_SHIFT 24 #define XFS_ILOCK_PARENT (XFS_LOCK_PARENT << XFS_ILOCK_SHIFT) +#define XFS_ILOCK_RTBITMAP (XFS_LOCK_RTBITMAP << XFS_ILOCK_SHIFT) +#define XFS_ILOCK_RTSUM (XFS_LOCK_RTSUM << XFS_ILOCK_SHIFT) #define XFS_IOLOCK_DEP_MASK 0x00ff0000 #define XFS_ILOCK_DEP_MASK 0xff000000 diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index 037fab140242..f592ac978186 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -1972,8 +1972,10 @@ xfs_growfs_rt( /* * Lock out other callers by grabbing the bitmap inode lock. */ - if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0, - XFS_ILOCK_EXCL, &ip))) + error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0, + XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP, + &ip); + if (error) goto error_cancel; ASSERT(ip == mp->m_rbmip); /* @@ -1986,8 +1988,9 @@ xfs_growfs_rt( /* * Get the summary inode into the transaction. */ - if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rsumino, 0, - XFS_ILOCK_EXCL, &ip))) + error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rsumino, 0, + XFS_ILOCK_EXCL | XFS_ILOCK_RTSUM, &ip); + if (error) goto error_cancel; ASSERT(ip == mp->m_rsumip); /* @@ -2160,8 +2163,9 @@ xfs_rtfree_extent( /* * Synchronize by locking the bitmap inode. */ - if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0, - XFS_ILOCK_EXCL, &ip))) + error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0, + XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP, &ip); + if (error) return error; #if defined(__KERNEL__) && defined(DEBUG) /* -- cgit From 5bc970e803ad2b1f26771f39376a79dbf0f5bf64 Mon Sep 17 00:00:00 2001 From: Sunil Mushran Date: Tue, 28 Dec 2010 23:26:03 -0800 Subject: ocfs2: Use hrtimer to track ocfs2 fs lock stats Patch makes use of the hrtimer to track times in ocfs2 lock stats. The patch is a bit involved to ensure no additional impact on the memory footprint. The size of ocfs2_inode_cache remains 1280 bytes on 32-bit systems. A related change was to modify the unit of the max wait time from nanosec to microsec allowing us to track max time larger than 4 secs. This change necessitated the bumping of the output version in the debugfs file, locking_state, from 2 to 3. Signed-off-by: Sunil Mushran Signed-off-by: Joel Becker --- fs/ocfs2/dlmglue.c | 97 ++++++++++++++++++++++++++++-------------------------- fs/ocfs2/ocfs2.h | 23 ++++++++----- 2 files changed, 64 insertions(+), 56 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index e8d94d722ecb..7484bb9a3438 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -64,7 +64,7 @@ struct ocfs2_mask_waiter { unsigned long mw_mask; unsigned long mw_goal; #ifdef CONFIG_OCFS2_FS_STATS - unsigned long long mw_lock_start; + ktime_t mw_lock_start; #endif }; @@ -435,44 +435,41 @@ static void ocfs2_remove_lockres_tracking(struct ocfs2_lock_res *res) #ifdef CONFIG_OCFS2_FS_STATS static void ocfs2_init_lock_stats(struct ocfs2_lock_res *res) { - res->l_lock_num_prmode = 0; - res->l_lock_num_prmode_failed = 0; - res->l_lock_total_prmode = 0; - res->l_lock_max_prmode = 0; - res->l_lock_num_exmode = 0; - res->l_lock_num_exmode_failed = 0; - res->l_lock_total_exmode = 0; - res->l_lock_max_exmode = 0; res->l_lock_refresh = 0; + memset(&res->l_lock_prmode, 0, sizeof(struct ocfs2_lock_stats)); + memset(&res->l_lock_exmode, 0, sizeof(struct ocfs2_lock_stats)); } static void ocfs2_update_lock_stats(struct ocfs2_lock_res *res, int level, struct ocfs2_mask_waiter *mw, int ret) { - unsigned long long *num, *sum; - unsigned int *max, *failed; - struct timespec ts = current_kernel_time(); - unsigned long long time = timespec_to_ns(&ts) - mw->mw_lock_start; - - if (level == LKM_PRMODE) { - num = &res->l_lock_num_prmode; - sum = &res->l_lock_total_prmode; - max = &res->l_lock_max_prmode; - failed = &res->l_lock_num_prmode_failed; - } else if (level == LKM_EXMODE) { - num = &res->l_lock_num_exmode; - sum = &res->l_lock_total_exmode; - max = &res->l_lock_max_exmode; - failed = &res->l_lock_num_exmode_failed; - } else + u32 usec; + ktime_t kt; + struct ocfs2_lock_stats *stats; + + if (level == LKM_PRMODE) + stats = &res->l_lock_prmode; + else if (level == LKM_EXMODE) + stats = &res->l_lock_exmode; + else return; - (*num)++; - (*sum) += time; - if (time > *max) - *max = time; + kt = ktime_sub(ktime_get(), mw->mw_lock_start); + usec = ktime_to_us(kt); + + stats->ls_gets++; + stats->ls_total += ktime_to_ns(kt); + /* overflow */ + if (unlikely(stats->ls_gets) == 0) { + stats->ls_gets++; + stats->ls_total = ktime_to_ns(kt); + } + + if (stats->ls_max < usec) + stats->ls_max = usec; + if (ret) - (*failed)++; + stats->ls_fail++; } static inline void ocfs2_track_lock_refresh(struct ocfs2_lock_res *lockres) @@ -482,8 +479,7 @@ static inline void ocfs2_track_lock_refresh(struct ocfs2_lock_res *lockres) static inline void ocfs2_init_start_time(struct ocfs2_mask_waiter *mw) { - struct timespec ts = current_kernel_time(); - mw->mw_lock_start = timespec_to_ns(&ts); + mw->mw_lock_start = ktime_get(); } #else static inline void ocfs2_init_lock_stats(struct ocfs2_lock_res *res) @@ -2869,8 +2865,15 @@ static void *ocfs2_dlm_seq_next(struct seq_file *m, void *v, loff_t *pos) return iter; } -/* So that debugfs.ocfs2 can determine which format is being used */ -#define OCFS2_DLM_DEBUG_STR_VERSION 2 +/* + * Version is used by debugfs.ocfs2 to determine the format being used + * + * New in version 2 + * - Lock stats printed + * New in version 3 + * - Max time in lock stats is in usecs (instead of nsecs) + */ +#define OCFS2_DLM_DEBUG_STR_VERSION 3 static int ocfs2_dlm_seq_show(struct seq_file *m, void *v) { int i; @@ -2912,18 +2915,18 @@ static int ocfs2_dlm_seq_show(struct seq_file *m, void *v) seq_printf(m, "0x%x\t", lvb[i]); #ifdef CONFIG_OCFS2_FS_STATS -# define lock_num_prmode(_l) (_l)->l_lock_num_prmode -# define lock_num_exmode(_l) (_l)->l_lock_num_exmode -# define lock_num_prmode_failed(_l) (_l)->l_lock_num_prmode_failed -# define lock_num_exmode_failed(_l) (_l)->l_lock_num_exmode_failed -# define lock_total_prmode(_l) (_l)->l_lock_total_prmode -# define lock_total_exmode(_l) (_l)->l_lock_total_exmode -# define lock_max_prmode(_l) (_l)->l_lock_max_prmode -# define lock_max_exmode(_l) (_l)->l_lock_max_exmode -# define lock_refresh(_l) (_l)->l_lock_refresh +# define lock_num_prmode(_l) ((_l)->l_lock_prmode.ls_gets) +# define lock_num_exmode(_l) ((_l)->l_lock_exmode.ls_gets) +# define lock_num_prmode_failed(_l) ((_l)->l_lock_prmode.ls_fail) +# define lock_num_exmode_failed(_l) ((_l)->l_lock_exmode.ls_fail) +# define lock_total_prmode(_l) ((_l)->l_lock_prmode.ls_total) +# define lock_total_exmode(_l) ((_l)->l_lock_exmode.ls_total) +# define lock_max_prmode(_l) ((_l)->l_lock_prmode.ls_max) +# define lock_max_exmode(_l) ((_l)->l_lock_exmode.ls_max) +# define lock_refresh(_l) ((_l)->l_lock_refresh) #else -# define lock_num_prmode(_l) (0ULL) -# define lock_num_exmode(_l) (0ULL) +# define lock_num_prmode(_l) (0) +# define lock_num_exmode(_l) (0) # define lock_num_prmode_failed(_l) (0) # define lock_num_exmode_failed(_l) (0) # define lock_total_prmode(_l) (0ULL) @@ -2933,8 +2936,8 @@ static int ocfs2_dlm_seq_show(struct seq_file *m, void *v) # define lock_refresh(_l) (0) #endif /* The following seq_print was added in version 2 of this output */ - seq_printf(m, "%llu\t" - "%llu\t" + seq_printf(m, "%u\t" + "%u\t" "%u\t" "%u\t" "%llu\t" diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index 51cd6898e7f1..4e3d3c1363f3 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h @@ -147,6 +147,17 @@ struct ocfs2_lock_res_ops; typedef void (*ocfs2_lock_callback)(int status, unsigned long data); +#ifdef CONFIG_OCFS2_FS_STATS +struct ocfs2_lock_stats { + u64 ls_total; /* Total wait in NSEC */ + u32 ls_gets; /* Num acquires */ + u32 ls_fail; /* Num failed acquires */ + + /* Storing max wait in usecs saves 24 bytes per inode */ + u32 ls_max; /* Max wait in USEC */ +}; +#endif + struct ocfs2_lock_res { void *l_priv; struct ocfs2_lock_res_ops *l_ops; @@ -182,15 +193,9 @@ struct ocfs2_lock_res { struct list_head l_debug_list; #ifdef CONFIG_OCFS2_FS_STATS - unsigned long long l_lock_num_prmode; /* PR acquires */ - unsigned long long l_lock_num_exmode; /* EX acquires */ - unsigned int l_lock_num_prmode_failed; /* Failed PR gets */ - unsigned int l_lock_num_exmode_failed; /* Failed EX gets */ - unsigned long long l_lock_total_prmode; /* Tot wait for PR */ - unsigned long long l_lock_total_exmode; /* Tot wait for EX */ - unsigned int l_lock_max_prmode; /* Max wait for PR */ - unsigned int l_lock_max_exmode; /* Max wait for EX */ - unsigned int l_lock_refresh; /* Disk refreshes */ + struct ocfs2_lock_stats l_lock_prmode; /* PR mode stats */ + u32 l_lock_refresh; /* Disk refreshes */ + struct ocfs2_lock_stats l_lock_exmode; /* EX mode stats */ #endif #ifdef CONFIG_DEBUG_LOCK_ALLOC struct lockdep_map l_lockdep_map; -- cgit From 1dd9ffc827b8591aabcf5fea6ea83b69e846deb9 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Mon, 24 Jan 2011 23:23:30 +0800 Subject: ocfs2: optimize ocfs2_check_dir_entry() with unlikely() annotations In cad3f00, ext4_check_dir_entry was modified by adding some unlikely. Ted described it as "This function gets called a lot for large directories, and the answer is almost always 'no, no, there's no problem'. This means using unlikely() is a good thing." ext3 added the similar change in commit a4ae309. So change it accordingly in ocfs2. Cc: Joel Becker Signed-off-by: Tao Ma Signed-off-by: Joel Becker --- fs/ocfs2/dir.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index d417b3f9b0c7..41b356fefaa5 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c @@ -322,21 +322,23 @@ static int ocfs2_check_dir_entry(struct inode * dir, const char *error_msg = NULL; const int rlen = le16_to_cpu(de->rec_len); - if (rlen < OCFS2_DIR_REC_LEN(1)) + if (unlikely(rlen < OCFS2_DIR_REC_LEN(1))) error_msg = "rec_len is smaller than minimal"; - else if (rlen % 4 != 0) + else if (unlikely(rlen % 4 != 0)) error_msg = "rec_len % 4 != 0"; - else if (rlen < OCFS2_DIR_REC_LEN(de->name_len)) + else if (unlikely(rlen < OCFS2_DIR_REC_LEN(de->name_len))) error_msg = "rec_len is too small for name_len"; - else if (((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize) + else if (unlikely( + ((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize)) error_msg = "directory entry across blocks"; - if (error_msg != NULL) + if (unlikely(error_msg != NULL)) mlog(ML_ERROR, "bad entry in directory #%llu: %s - " "offset=%lu, inode=%llu, rec_len=%d, name_len=%d\n", (unsigned long long)OCFS2_I(dir)->ip_blkno, error_msg, offset, (unsigned long long)le64_to_cpu(de->inode), rlen, de->name_len); + return error_msg == NULL ? 1 : 0; } -- cgit From 1936a267f1b5a32d4a846608fdcce82ca0f6ac8e Mon Sep 17 00:00:00 2001 From: Tristan Ye Date: Sun, 30 Jan 2011 14:25:59 +0800 Subject: Ocfs2: Using macro to set/clear *FILLED* flags in info handler. It's a best-effort attempt to simplize duplicated codes here. Signed-off-by: Tristan Ye Signed-off-by: Joel Becker --- fs/ocfs2/ioctl.c | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c index 7a4868196152..731cf4670b97 100644 --- a/fs/ocfs2/ioctl.c +++ b/fs/ocfs2/ioctl.c @@ -46,6 +46,22 @@ static inline void __o2info_set_request_error(struct ocfs2_info_request *kreq, #define o2info_set_request_error(a, b) \ __o2info_set_request_error((struct ocfs2_info_request *)&(a), b) +static inline void __o2info_set_request_filled(struct ocfs2_info_request *req) +{ + req->ir_flags |= OCFS2_INFO_FL_FILLED; +} + +#define o2info_set_request_filled(a) \ + __o2info_set_request_filled((struct ocfs2_info_request *)&(a)) + +static inline void __o2info_clear_request_filled(struct ocfs2_info_request *req) +{ + req->ir_flags &= ~OCFS2_INFO_FL_FILLED; +} + +#define o2info_clear_request_filled(a) \ + __o2info_clear_request_filled((struct ocfs2_info_request *)&(a)) + static int ocfs2_get_inode_attr(struct inode *inode, unsigned *flags) { int status; @@ -139,7 +155,8 @@ int ocfs2_info_handle_blocksize(struct inode *inode, goto bail; oib.ib_blocksize = inode->i_sb->s_blocksize; - oib.ib_req.ir_flags |= OCFS2_INFO_FL_FILLED; + + o2info_set_request_filled(oib); if (o2info_to_user(oib, req)) goto bail; @@ -163,7 +180,8 @@ int ocfs2_info_handle_clustersize(struct inode *inode, goto bail; oic.ic_clustersize = osb->s_clustersize; - oic.ic_req.ir_flags |= OCFS2_INFO_FL_FILLED; + + o2info_set_request_filled(oic); if (o2info_to_user(oic, req)) goto bail; @@ -187,7 +205,8 @@ int ocfs2_info_handle_maxslots(struct inode *inode, goto bail; oim.im_max_slots = osb->max_slots; - oim.im_req.ir_flags |= OCFS2_INFO_FL_FILLED; + + o2info_set_request_filled(oim); if (o2info_to_user(oim, req)) goto bail; @@ -211,7 +230,8 @@ int ocfs2_info_handle_label(struct inode *inode, goto bail; memcpy(oil.il_label, osb->vol_label, OCFS2_MAX_VOL_LABEL_LEN); - oil.il_req.ir_flags |= OCFS2_INFO_FL_FILLED; + + o2info_set_request_filled(oil); if (o2info_to_user(oil, req)) goto bail; @@ -235,7 +255,8 @@ int ocfs2_info_handle_uuid(struct inode *inode, goto bail; memcpy(oiu.iu_uuid_str, osb->uuid_str, OCFS2_TEXT_UUID_LEN + 1); - oiu.iu_req.ir_flags |= OCFS2_INFO_FL_FILLED; + + o2info_set_request_filled(oiu); if (o2info_to_user(oiu, req)) goto bail; @@ -261,7 +282,8 @@ int ocfs2_info_handle_fs_features(struct inode *inode, oif.if_compat_features = osb->s_feature_compat; oif.if_incompat_features = osb->s_feature_incompat; oif.if_ro_compat_features = osb->s_feature_ro_compat; - oif.if_req.ir_flags |= OCFS2_INFO_FL_FILLED; + + o2info_set_request_filled(oif); if (o2info_to_user(oif, req)) goto bail; @@ -286,7 +308,7 @@ int ocfs2_info_handle_journal_size(struct inode *inode, oij.ij_journal_size = osb->journal->j_inode->i_size; - oij.ij_req.ir_flags |= OCFS2_INFO_FL_FILLED; + o2info_set_request_filled(oij); if (o2info_to_user(oij, req)) goto bail; @@ -308,7 +330,7 @@ int ocfs2_info_handle_unknown(struct inode *inode, if (o2info_from_user(oir, req)) goto bail; - oir.ir_flags &= ~OCFS2_INFO_FL_FILLED; + o2info_clear_request_filled(oir); if (o2info_to_user(oir, req)) goto bail; -- cgit From ef6b689b63b9f5227ccee6f16dd9ee3faf58a464 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Mon, 21 Feb 2011 11:10:44 +0800 Subject: ocfs2: Remove ENTRY from masklog. ENTRY is used to record the entry of a function. But because it is added in so many functions, if we enable it, the system logs get filled up quickly and cause too much I/O. So actually no one can open it for a production system or even for a test. So for mlog_entry_void, we just remove it. for mlog_entry(...), we replace it with mlog(0,...), and they will be replace by trace event later. Signed-off-by: Tao Ma --- fs/ocfs2/alloc.c | 28 ++-------------- fs/ocfs2/aops.c | 16 ++++----- fs/ocfs2/buffer_head_io.c | 10 +++--- fs/ocfs2/cluster/heartbeat.c | 2 -- fs/ocfs2/cluster/masklog.c | 1 - fs/ocfs2/cluster/masklog.h | 13 +------- fs/ocfs2/dcache.c | 4 +-- fs/ocfs2/dir.c | 20 +++--------- fs/ocfs2/dlm/dlmconvert.c | 6 ++-- fs/ocfs2/dlm/dlmdomain.c | 8 ++--- fs/ocfs2/dlm/dlmlock.c | 10 ++---- fs/ocfs2/dlm/dlmmaster.c | 6 +--- fs/ocfs2/dlm/dlmrecovery.c | 4 --- fs/ocfs2/dlm/dlmunlock.c | 4 +-- fs/ocfs2/dlmglue.c | 78 -------------------------------------------- fs/ocfs2/export.c | 12 +++---- fs/ocfs2/extent_map.c | 8 ++--- fs/ocfs2/file.c | 73 ++++++++++++++++++----------------------- fs/ocfs2/inode.c | 28 +++++++--------- fs/ocfs2/journal.c | 43 +++++++----------------- fs/ocfs2/localalloc.c | 26 +++------------ fs/ocfs2/mmap.c | 2 +- fs/ocfs2/namei.c | 74 ++++++++++++++++++++--------------------- fs/ocfs2/quota_global.c | 14 +++----- fs/ocfs2/quota_local.c | 2 +- fs/ocfs2/resize.c | 8 ++--- fs/ocfs2/slot_map.c | 2 -- fs/ocfs2/suballoc.c | 35 ++++---------------- fs/ocfs2/super.c | 32 ++++-------------- fs/ocfs2/symlink.c | 6 ---- fs/ocfs2/xattr.c | 4 +-- 31 files changed, 161 insertions(+), 418 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index e4984e259cb6..47a6ce84e67f 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c @@ -965,8 +965,6 @@ int ocfs2_num_free_extents(struct ocfs2_super *osb, struct buffer_head *eb_bh = NULL; u64 last_eb_blk = 0; - mlog_entry_void(); - el = et->et_root_el; last_eb_blk = ocfs2_et_get_last_eb_blk(et); @@ -1010,8 +1008,6 @@ static int ocfs2_create_new_meta_bhs(handle_t *handle, OCFS2_SB(ocfs2_metadata_cache_get_super(et->et_ci)); struct ocfs2_extent_block *eb; - mlog_entry_void(); - count = 0; while (count < wanted) { status = ocfs2_claim_metadata(handle, @@ -1173,8 +1169,6 @@ static int ocfs2_add_branch(handle_t *handle, struct ocfs2_extent_list *el; u32 new_cpos, root_end; - mlog_entry_void(); - BUG_ON(!last_eb_bh || !*last_eb_bh); if (eb_bh) { @@ -1353,8 +1347,6 @@ static int ocfs2_shift_tree_depth(handle_t *handle, struct ocfs2_extent_list *root_el; struct ocfs2_extent_list *eb_el; - mlog_entry_void(); - status = ocfs2_create_new_meta_bhs(handle, et, 1, meta_ac, &new_eb_bh); if (status < 0) { @@ -1446,8 +1438,6 @@ static int ocfs2_find_branch_target(struct ocfs2_extent_tree *et, struct buffer_head *bh = NULL; struct buffer_head *lowest_bh = NULL; - mlog_entry_void(); - *target_bh = NULL; el = et->et_root_el; @@ -5795,8 +5785,8 @@ int ocfs2_truncate_log_append(struct ocfs2_super *osb, struct ocfs2_dinode *di; struct ocfs2_truncate_log *tl; - mlog_entry("start_blk = %llu, num_clusters = %u\n", - (unsigned long long)start_blk, num_clusters); + mlog(0, "start_blk = %llu, num_clusters = %u\n", + (unsigned long long)start_blk, num_clusters); BUG_ON(mutex_trylock(&tl_inode->i_mutex)); @@ -5878,8 +5868,6 @@ static int ocfs2_replay_truncate_records(struct ocfs2_super *osb, struct inode *tl_inode = osb->osb_tl_inode; struct buffer_head *tl_bh = osb->osb_tl_bh; - mlog_entry_void(); - di = (struct ocfs2_dinode *) tl_bh->b_data; tl = &di->id2.i_dealloc; i = le16_to_cpu(tl->tl_used) - 1; @@ -5949,8 +5937,6 @@ int __ocfs2_flush_truncate_log(struct ocfs2_super *osb) struct ocfs2_dinode *di; struct ocfs2_truncate_log *tl; - mlog_entry_void(); - BUG_ON(mutex_trylock(&tl_inode->i_mutex)); di = (struct ocfs2_dinode *) tl_bh->b_data; @@ -6032,8 +6018,6 @@ static void ocfs2_truncate_log_worker(struct work_struct *work) container_of(work, struct ocfs2_super, osb_truncate_log_wq.work); - mlog_entry_void(); - status = ocfs2_flush_truncate_log(osb); if (status < 0) mlog_errno(status); @@ -6174,8 +6158,6 @@ int ocfs2_complete_truncate_log_recovery(struct ocfs2_super *osb, struct inode *tl_inode = osb->osb_tl_inode; struct ocfs2_truncate_log *tl; - mlog_entry_void(); - if (OCFS2_I(tl_inode)->ip_blkno == le64_to_cpu(tl_copy->i_blkno)) { mlog(ML_ERROR, "Asked to recover my own truncate log!\n"); return -EINVAL; @@ -6228,8 +6210,6 @@ void ocfs2_truncate_log_shutdown(struct ocfs2_super *osb) int status; struct inode *tl_inode = osb->osb_tl_inode; - mlog_entry_void(); - if (tl_inode) { cancel_delayed_work(&osb->osb_truncate_log_wq); flush_workqueue(ocfs2_wq); @@ -6251,8 +6231,6 @@ int ocfs2_truncate_log_init(struct ocfs2_super *osb) struct inode *tl_inode = NULL; struct buffer_head *tl_bh = NULL; - mlog_entry_void(); - status = ocfs2_get_truncate_log_info(osb, osb->slot_num, &tl_inode, @@ -7005,8 +6983,6 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb, struct ocfs2_extent_tree et; struct ocfs2_cached_dealloc_ctxt dealloc; - mlog_entry_void(); - ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(inode), di_bh); ocfs2_init_dealloc_ctxt(&dealloc); diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 1fbb0e20131b..5dbfc9e45195 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -59,8 +59,8 @@ static int ocfs2_symlink_get_block(struct inode *inode, sector_t iblock, struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); void *kaddr; - mlog_entry("(0x%p, %llu, 0x%p, %d)\n", inode, - (unsigned long long)iblock, bh_result, create); + mlog(0, "(0x%p, %llu, 0x%p, %d)\n", inode, + (unsigned long long)iblock, bh_result, create); BUG_ON(ocfs2_inode_is_fast_symlink(inode)); @@ -136,8 +136,8 @@ int ocfs2_get_block(struct inode *inode, sector_t iblock, u64 p_blkno, count, past_eof; struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - mlog_entry("(0x%p, %llu, 0x%p, %d)\n", inode, - (unsigned long long)iblock, bh_result, create); + mlog(0, "(0x%p, %llu, 0x%p, %d)\n", inode, + (unsigned long long)iblock, bh_result, create); if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_SYSTEM_FILE) mlog(ML_NOTICE, "get_block on system inode 0x%p (%lu)\n", @@ -278,7 +278,7 @@ static int ocfs2_readpage(struct file *file, struct page *page) loff_t start = (loff_t)page->index << PAGE_CACHE_SHIFT; int ret, unlock = 1; - mlog_entry("(0x%p, %lu)\n", file, (page ? page->index : 0)); + mlog(0, "(0x%p, %lu)\n", file, (page ? page->index : 0)); ret = ocfs2_inode_lock_with_page(inode, NULL, 0, page); if (ret != 0) { @@ -398,7 +398,7 @@ static int ocfs2_writepage(struct page *page, struct writeback_control *wbc) { int ret; - mlog_entry("(0x%p)\n", page); + mlog(0, "(0x%p)\n", page); ret = block_write_full_page(page, ocfs2_get_block, wbc); @@ -450,7 +450,7 @@ static sector_t ocfs2_bmap(struct address_space *mapping, sector_t block) int err = 0; struct inode *inode = mapping->host; - mlog_entry("(block = %llu)\n", (unsigned long long)block); + mlog(0, "(block = %llu)\n", (unsigned long long)block); /* We don't need to lock journal system files, since they aren't * accessed concurrently from multiple nodes. @@ -618,8 +618,6 @@ static ssize_t ocfs2_direct_IO(int rw, struct inode *inode = file->f_path.dentry->d_inode->i_mapping->host; int ret; - mlog_entry_void(); - /* * Fallback to buffered I/O if we see an inode without * extents. diff --git a/fs/ocfs2/buffer_head_io.c b/fs/ocfs2/buffer_head_io.c index f9d5d3ffc75a..024bd45b7a48 100644 --- a/fs/ocfs2/buffer_head_io.c +++ b/fs/ocfs2/buffer_head_io.c @@ -55,8 +55,8 @@ int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh, { int ret = 0; - mlog_entry("(bh->b_blocknr = %llu, ci=%p)\n", - (unsigned long long)bh->b_blocknr, ci); + mlog(0, "(bh->b_blocknr = %llu, ci=%p)\n", + (unsigned long long)bh->b_blocknr, ci); BUG_ON(bh->b_blocknr < OCFS2_SUPER_BLOCK_BLKNO); BUG_ON(buffer_jbd(bh)); @@ -186,8 +186,8 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr, struct buffer_head *bh; struct super_block *sb = ocfs2_metadata_cache_get_super(ci); - mlog_entry("(ci=%p, block=(%llu), nr=(%d), flags=%d)\n", - ci, (unsigned long long)block, nr, flags); + mlog(0, "(ci=%p, block=(%llu), nr=(%d), flags=%d)\n", + ci, (unsigned long long)block, nr, flags); BUG_ON(!ci); BUG_ON((flags & OCFS2_BH_READAHEAD) && @@ -408,8 +408,6 @@ int ocfs2_write_super_or_backup(struct ocfs2_super *osb, int ret = 0; struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data; - mlog_entry_void(); - BUG_ON(buffer_jbd(bh)); ocfs2_check_super_or_backup(osb->sb, bh->b_blocknr); diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index b108e863d8f6..929178ce17a2 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c @@ -1658,8 +1658,6 @@ static int o2hb_populate_slot_data(struct o2hb_region *reg) struct o2hb_disk_slot *slot; struct o2hb_disk_heartbeat_block *hb_block; - mlog_entry_void(); - ret = o2hb_read_slots(reg, reg->hr_blocks); if (ret) { mlog_errno(ret); diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index 6c61771469af..bac64570c525 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -80,7 +80,6 @@ struct mlog_attribute { } static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { - define_mask(ENTRY), define_mask(EXIT), define_mask(TCP), define_mask(MSG), diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index 34d6544357d9..6e20877436b9 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -82,7 +82,6 @@ /* bits that are frequently given and infrequently matched in the low word */ /* NOTE: If you add a flag, you need to also update masklog.c! */ -#define ML_ENTRY 0x0000000000000001ULL /* func call entry */ #define ML_EXIT 0x0000000000000002ULL /* func call exit */ #define ML_TCP 0x0000000000000004ULL /* net cluster/tcp.c */ #define ML_MSG 0x0000000000000008ULL /* net network messages */ @@ -124,7 +123,7 @@ #define ML_KTHREAD 0x4000000000000000ULL /* kernel thread activity */ #define MLOG_INITIAL_AND_MASK (ML_ERROR|ML_NOTICE) -#define MLOG_INITIAL_NOT_MASK (ML_ENTRY|ML_EXIT) +#define MLOG_INITIAL_NOT_MASK (ML_EXIT) #ifndef MLOG_MASK_PREFIX #define MLOG_MASK_PREFIX 0 #endif @@ -223,14 +222,6 @@ extern struct mlog_bits mlog_and_bits, mlog_not_bits; } while (0) #if defined(CONFIG_OCFS2_DEBUG_MASKLOG) -#define mlog_entry(fmt, args...) do { \ - mlog(ML_ENTRY, "ENTRY:" fmt , ##args); \ -} while (0) - -#define mlog_entry_void() do { \ - mlog(ML_ENTRY, "ENTRY:\n"); \ -} while (0) - /* * We disable this for sparse. */ @@ -267,8 +258,6 @@ extern struct mlog_bits mlog_and_bits, mlog_not_bits; mlog(ML_EXIT, "EXIT\n"); \ } while (0) #else -#define mlog_entry(...) do { } while (0) -#define mlog_entry_void(...) do { } while (0) #define mlog_exit(...) do { } while (0) #define mlog_exit_ptr(...) do { } while (0) #define mlog_exit_void(...) do { } while (0) diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c index 7eb90403fc8a..67d17a45773b 100644 --- a/fs/ocfs2/dcache.c +++ b/fs/ocfs2/dcache.c @@ -62,8 +62,8 @@ static int ocfs2_dentry_revalidate(struct dentry *dentry, inode = dentry->d_inode; osb = OCFS2_SB(dentry->d_sb); - mlog_entry("(0x%p, '%.*s')\n", dentry, - dentry->d_name.len, dentry->d_name.name); + mlog(0, "(0x%p, '%.*s')\n", dentry, + dentry->d_name.len, dentry->d_name.name); /* For a negative dentry - * check the generation number of the parent and compare with the diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index d417b3f9b0c7..2c983f083f8a 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c @@ -367,8 +367,6 @@ static int inline ocfs2_search_dirblock(struct buffer_head *bh, int de_len; int ret = 0; - mlog_entry_void(); - de_buf = first_de; dlimit = de_buf + bytes; @@ -706,8 +704,6 @@ static struct buffer_head *ocfs2_find_entry_el(const char *name, int namelen, int num = 0; int nblocks, i, err; - mlog_entry_void(); - sb = dir->i_sb; nblocks = i_size_read(dir) >> sb->s_blocksize_bits; @@ -1166,7 +1162,7 @@ static int __ocfs2_delete_entry(handle_t *handle, struct inode *dir, int i, status = -ENOENT; ocfs2_journal_access_func access = ocfs2_journal_access_db; - mlog_entry("(0x%p, 0x%p, 0x%p, 0x%p)\n", handle, dir, de_del, bh); + mlog(0, "(0x%p, 0x%p, 0x%p, 0x%p)\n", handle, dir, de_del, bh); if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL) access = ocfs2_journal_access_di; @@ -1632,8 +1628,6 @@ int __ocfs2_add_entry(handle_t *handle, struct buffer_head *insert_bh = lookup->dl_leaf_bh; char *data_start = insert_bh->b_data; - mlog_entry_void(); - if (!namelen) return -EINVAL; @@ -2028,8 +2022,8 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) struct inode *inode = filp->f_path.dentry->d_inode; int lock_level = 0; - mlog_entry("dirino=%llu\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno); + mlog(0, "dirino=%llu\n", + (unsigned long long)OCFS2_I(inode)->ip_blkno); error = ocfs2_inode_lock_atime(inode, filp->f_vfsmnt, &lock_level); if (lock_level && error >= 0) { @@ -2114,8 +2108,8 @@ int ocfs2_check_dir_for_entry(struct inode *dir, int ret; struct ocfs2_dir_lookup_result lookup = { NULL, }; - mlog_entry("dir %llu, name '%.*s'\n", - (unsigned long long)OCFS2_I(dir)->ip_blkno, namelen, name); + mlog(0, "dir %llu, name '%.*s'\n", + (unsigned long long)OCFS2_I(dir)->ip_blkno, namelen, name); ret = -EEXIST; if (ocfs2_find_entry(name, namelen, dir, &lookup) == 0) @@ -2324,8 +2318,6 @@ static int ocfs2_fill_new_dir_el(struct ocfs2_super *osb, struct buffer_head *new_bh = NULL; struct ocfs2_dir_entry *de; - mlog_entry_void(); - if (ocfs2_new_dir_wants_trailer(inode)) size = ocfs2_dir_trailer_blk_off(parent->i_sb); @@ -3270,8 +3262,6 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb, struct ocfs2_extent_tree et; struct buffer_head *dx_root_bh = lookup->dl_dx_root_bh; - mlog_entry_void(); - if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL) { /* * This would be a code error as an inline directory should diff --git a/fs/ocfs2/dlm/dlmconvert.c b/fs/ocfs2/dlm/dlmconvert.c index 9f30491e5e88..29a886d1e82c 100644 --- a/fs/ocfs2/dlm/dlmconvert.c +++ b/fs/ocfs2/dlm/dlmconvert.c @@ -128,8 +128,8 @@ static enum dlm_status __dlmconvert_master(struct dlm_ctxt *dlm, assert_spin_locked(&res->spinlock); - mlog_entry("type=%d, convert_type=%d, new convert_type=%d\n", - lock->ml.type, lock->ml.convert_type, type); + mlog(0, "type=%d, convert_type=%d, new convert_type=%d\n", + lock->ml.type, lock->ml.convert_type, type); spin_lock(&lock->spinlock); @@ -353,7 +353,7 @@ static enum dlm_status dlm_send_remote_convert_request(struct dlm_ctxt *dlm, struct kvec vec[2]; size_t veclen = 1; - mlog_entry("%.*s\n", res->lockname.len, res->lockname.name); + mlog(0, "%.*s\n", res->lockname.len, res->lockname.name); memset(&convert, 0, sizeof(struct dlm_convert_lock)); convert.node_idx = dlm->node_num; diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c index 7e38a072d720..5391f28d940b 100644 --- a/fs/ocfs2/dlm/dlmdomain.c +++ b/fs/ocfs2/dlm/dlmdomain.c @@ -188,7 +188,7 @@ struct dlm_lock_resource * __dlm_lookup_lockres_full(struct dlm_ctxt *dlm, struct hlist_head *bucket; struct hlist_node *list; - mlog_entry("%.*s\n", len, name); + mlog(0, "%.*s\n", len, name); assert_spin_locked(&dlm->spinlock); @@ -222,7 +222,7 @@ struct dlm_lock_resource * __dlm_lookup_lockres(struct dlm_ctxt *dlm, { struct dlm_lock_resource *res = NULL; - mlog_entry("%.*s\n", len, name); + mlog(0, "%.*s\n", len, name); assert_spin_locked(&dlm->spinlock); @@ -531,7 +531,7 @@ static int dlm_exit_domain_handler(struct o2net_msg *msg, u32 len, void *data, unsigned int node; struct dlm_exit_domain *exit_msg = (struct dlm_exit_domain *) msg->buf; - mlog_entry("%p %u %p", msg, len, data); + mlog(0, "%p %u %p", msg, len, data); if (!dlm_grab(dlm)) return 0; @@ -1553,7 +1553,7 @@ static int dlm_try_to_join_domain(struct dlm_ctxt *dlm) struct domain_join_ctxt *ctxt; enum dlm_query_join_response_code response = JOIN_DISALLOW; - mlog_entry("%p", dlm); + mlog(0, "%p", dlm); ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL); if (!ctxt) { diff --git a/fs/ocfs2/dlm/dlmlock.c b/fs/ocfs2/dlm/dlmlock.c index 7009292aac5a..8d39e0fd66f7 100644 --- a/fs/ocfs2/dlm/dlmlock.c +++ b/fs/ocfs2/dlm/dlmlock.c @@ -128,7 +128,7 @@ static enum dlm_status dlmlock_master(struct dlm_ctxt *dlm, int call_ast = 0, kick_thread = 0; enum dlm_status status = DLM_NORMAL; - mlog_entry("type=%d\n", lock->ml.type); + mlog(0, "type=%d\n", lock->ml.type); spin_lock(&res->spinlock); /* if called from dlm_create_lock_handler, need to @@ -227,8 +227,8 @@ static enum dlm_status dlmlock_remote(struct dlm_ctxt *dlm, enum dlm_status status = DLM_DENIED; int lockres_changed = 1; - mlog_entry("type=%d\n", lock->ml.type); - mlog(0, "lockres %.*s, flags = 0x%x\n", res->lockname.len, + mlog(0, "type=%d, lockres %.*s, flags = 0x%x\n", + lock->ml.type, res->lockname.len, res->lockname.name, flags); spin_lock(&res->spinlock); @@ -308,8 +308,6 @@ static enum dlm_status dlm_send_remote_lock_request(struct dlm_ctxt *dlm, int tmpret, status = 0; enum dlm_status ret; - mlog_entry_void(); - memset(&create, 0, sizeof(create)); create.node_idx = dlm->node_num; create.requested_type = lock->ml.type; @@ -477,8 +475,6 @@ int dlm_create_lock_handler(struct o2net_msg *msg, u32 len, void *data, BUG_ON(!dlm); - mlog_entry_void(); - if (!dlm_grab(dlm)) return DLM_REJECTED; diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c index 59f0f6bdfc62..9d67610dfc74 100644 --- a/fs/ocfs2/dlm/dlmmaster.c +++ b/fs/ocfs2/dlm/dlmmaster.c @@ -426,8 +426,6 @@ static void dlm_mle_release(struct kref *kref) struct dlm_master_list_entry *mle; struct dlm_ctxt *dlm; - mlog_entry_void(); - mle = container_of(kref, struct dlm_master_list_entry, mle_refs); dlm = mle->dlm; @@ -3120,8 +3118,6 @@ static int dlm_add_migration_mle(struct dlm_ctxt *dlm, *oldmle = NULL; - mlog_entry_void(); - assert_spin_locked(&dlm->spinlock); assert_spin_locked(&dlm->master_lock); @@ -3261,7 +3257,7 @@ void dlm_clean_master_list(struct dlm_ctxt *dlm, u8 dead_node) struct hlist_node *list; unsigned int i; - mlog_entry("dlm=%s, dead node=%u\n", dlm->name, dead_node); + mlog(0, "dlm=%s, dead node=%u\n", dlm->name, dead_node); top: assert_spin_locked(&dlm->spinlock); diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c index aaaffbcbe916..6602b23c2ab3 100644 --- a/fs/ocfs2/dlm/dlmrecovery.c +++ b/fs/ocfs2/dlm/dlmrecovery.c @@ -2083,8 +2083,6 @@ static void dlm_finish_local_lockres_recovery(struct dlm_ctxt *dlm, struct hlist_head *bucket; struct dlm_lock_resource *res, *next; - mlog_entry_void(); - assert_spin_locked(&dlm->spinlock); list_for_each_entry_safe(res, next, &dlm->reco.resources, recovering) { @@ -2607,8 +2605,6 @@ static int dlm_send_begin_reco_message(struct dlm_ctxt *dlm, u8 dead_node) int nodenum; int status; - mlog_entry("%u\n", dead_node); - mlog(0, "%s: dead node is %u\n", dlm->name, dead_node); spin_lock(&dlm->spinlock); diff --git a/fs/ocfs2/dlm/dlmunlock.c b/fs/ocfs2/dlm/dlmunlock.c index 817287c6a6db..850aa7e87537 100644 --- a/fs/ocfs2/dlm/dlmunlock.c +++ b/fs/ocfs2/dlm/dlmunlock.c @@ -317,7 +317,7 @@ static enum dlm_status dlm_send_remote_unlock_request(struct dlm_ctxt *dlm, struct kvec vec[2]; size_t veclen = 1; - mlog_entry("%.*s\n", res->lockname.len, res->lockname.name); + mlog(0, "%.*s\n", res->lockname.len, res->lockname.name); if (owner == dlm->node_num) { /* ended up trying to contact ourself. this means @@ -588,8 +588,6 @@ enum dlm_status dlmunlock(struct dlm_ctxt *dlm, struct dlm_lockstatus *lksb, struct dlm_lock *lock = NULL; int call_ast, is_master; - mlog_entry_void(); - if (!lksb) { dlm_error(DLM_BADARGS); return DLM_BADARGS; diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index e8d94d722ecb..c2f3fa1c4722 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -397,8 +397,6 @@ static void ocfs2_build_lock_name(enum ocfs2_lock_type type, { int len; - mlog_entry_void(); - BUG_ON(type >= OCFS2_NUM_LOCK_TYPES); len = snprintf(name, OCFS2_LOCK_ID_MAX_LEN, "%c%s%016llx%08x", @@ -729,8 +727,6 @@ void ocfs2_refcount_lock_res_init(struct ocfs2_lock_res *lockres, void ocfs2_lock_res_free(struct ocfs2_lock_res *res) { - mlog_entry_void(); - if (!(res->l_flags & OCFS2_LOCK_INITIALIZED)) return; @@ -762,8 +758,6 @@ void ocfs2_lock_res_free(struct ocfs2_lock_res *res) static inline void ocfs2_inc_holders(struct ocfs2_lock_res *lockres, int level) { - mlog_entry_void(); - BUG_ON(!lockres); switch(level) { @@ -783,8 +777,6 @@ static inline void ocfs2_inc_holders(struct ocfs2_lock_res *lockres, static inline void ocfs2_dec_holders(struct ocfs2_lock_res *lockres, int level) { - mlog_entry_void(); - BUG_ON(!lockres); switch(level) { @@ -846,8 +838,6 @@ static void lockres_clear_flags(struct ocfs2_lock_res *lockres, static inline void ocfs2_generic_handle_downconvert_action(struct ocfs2_lock_res *lockres) { - mlog_entry_void(); - BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BUSY)); BUG_ON(!(lockres->l_flags & OCFS2_LOCK_ATTACHED)); BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BLOCKED)); @@ -866,8 +856,6 @@ static inline void ocfs2_generic_handle_downconvert_action(struct ocfs2_lock_res static inline void ocfs2_generic_handle_convert_action(struct ocfs2_lock_res *lockres) { - mlog_entry_void(); - BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BUSY)); BUG_ON(!(lockres->l_flags & OCFS2_LOCK_ATTACHED)); @@ -895,8 +883,6 @@ static inline void ocfs2_generic_handle_convert_action(struct ocfs2_lock_res *lo static inline void ocfs2_generic_handle_attach_action(struct ocfs2_lock_res *lockres) { - mlog_entry_void(); - BUG_ON((!(lockres->l_flags & OCFS2_LOCK_BUSY))); BUG_ON(lockres->l_flags & OCFS2_LOCK_ATTACHED); @@ -916,7 +902,6 @@ static int ocfs2_generic_handle_bast(struct ocfs2_lock_res *lockres, int level) { int needs_downconvert = 0; - mlog_entry_void(); assert_spin_locked(&lockres->l_lock); @@ -1151,8 +1136,6 @@ static void ocfs2_unlock_ast(struct ocfs2_dlm_lksb *lksb, int error) struct ocfs2_lock_res *lockres = ocfs2_lksb_to_lock_res(lksb); unsigned long flags; - mlog_entry_void(); - mlog(ML_BASTS, "UNLOCK AST fired for lockres %s, action = %d\n", lockres->l_name, lockres->l_unlock_action); @@ -1233,7 +1216,6 @@ static inline void ocfs2_recover_from_dlm_error(struct ocfs2_lock_res *lockres, { unsigned long flags; - mlog_entry_void(); spin_lock_irqsave(&lockres->l_lock, flags); lockres_clear_flags(lockres, OCFS2_LOCK_BUSY); lockres_clear_flags(lockres, OCFS2_LOCK_UPCONVERT_FINISHING); @@ -1260,8 +1242,6 @@ static int ocfs2_lock_create(struct ocfs2_super *osb, unsigned long flags; unsigned int gen; - mlog_entry_void(); - mlog(0, "lock %s, level = %d, flags = %u\n", lockres->l_name, level, dlm_flags); @@ -1416,8 +1396,6 @@ static int __ocfs2_cluster_lock(struct ocfs2_super *osb, unsigned int gen; int noqueue_attempted = 0; - mlog_entry_void(); - ocfs2_init_mask_waiter(&mw); if (lockres->l_ops->flags & LOCK_TYPE_USES_LVB) @@ -1605,7 +1583,6 @@ static void __ocfs2_cluster_unlock(struct ocfs2_super *osb, { unsigned long flags; - mlog_entry_void(); spin_lock_irqsave(&lockres->l_lock, flags); ocfs2_dec_holders(lockres, level); ocfs2_downconvert_on_unlock(osb, lockres); @@ -1648,8 +1625,6 @@ int ocfs2_create_new_inode_locks(struct inode *inode) BUG_ON(!inode); BUG_ON(!ocfs2_inode_is_new(inode)); - mlog_entry_void(); - mlog(0, "Inode %llu\n", (unsigned long long)OCFS2_I(inode)->ip_blkno); /* NOTE: That we don't increment any of the holder counts, nor @@ -1695,8 +1670,6 @@ int ocfs2_rw_lock(struct inode *inode, int write) BUG_ON(!inode); - mlog_entry_void(); - mlog(0, "inode %llu take %s RW lock\n", (unsigned long long)OCFS2_I(inode)->ip_blkno, write ? "EXMODE" : "PRMODE"); @@ -1725,8 +1698,6 @@ void ocfs2_rw_unlock(struct inode *inode, int write) struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_rw_lockres; struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - mlog_entry_void(); - mlog(0, "inode %llu drop %s RW lock\n", (unsigned long long)OCFS2_I(inode)->ip_blkno, write ? "EXMODE" : "PRMODE"); @@ -1748,8 +1719,6 @@ int ocfs2_open_lock(struct inode *inode) BUG_ON(!inode); - mlog_entry_void(); - mlog(0, "inode %llu take PRMODE open lock\n", (unsigned long long)OCFS2_I(inode)->ip_blkno); @@ -1776,8 +1745,6 @@ int ocfs2_try_open_lock(struct inode *inode, int write) BUG_ON(!inode); - mlog_entry_void(); - mlog(0, "inode %llu try to take %s open lock\n", (unsigned long long)OCFS2_I(inode)->ip_blkno, write ? "EXMODE" : "PRMODE"); @@ -1811,8 +1778,6 @@ void ocfs2_open_unlock(struct inode *inode) struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_open_lockres; struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - mlog_entry_void(); - mlog(0, "inode %llu drop open lock\n", (unsigned long long)OCFS2_I(inode)->ip_blkno); @@ -2043,8 +2008,6 @@ static void ocfs2_downconvert_on_unlock(struct ocfs2_super *osb, { int kick = 0; - mlog_entry_void(); - /* If we know that another node is waiting on our lock, kick * the downconvert thread * pre-emptively when we reach a release * condition. */ @@ -2095,8 +2058,6 @@ static void __ocfs2_stuff_meta_lvb(struct inode *inode) struct ocfs2_lock_res *lockres = &oi->ip_inode_lockres; struct ocfs2_meta_lvb *lvb; - mlog_entry_void(); - lvb = ocfs2_dlm_lvb(&lockres->l_lksb); /* @@ -2145,8 +2106,6 @@ static void ocfs2_refresh_inode_from_lvb(struct inode *inode) struct ocfs2_lock_res *lockres = &oi->ip_inode_lockres; struct ocfs2_meta_lvb *lvb; - mlog_entry_void(); - mlog_meta_lvb(0, lockres); lvb = ocfs2_dlm_lvb(&lockres->l_lksb); @@ -2205,8 +2164,6 @@ static int ocfs2_should_refresh_lock_res(struct ocfs2_lock_res *lockres) unsigned long flags; int status = 0; - mlog_entry_void(); - refresh_check: spin_lock_irqsave(&lockres->l_lock, flags); if (!(lockres->l_flags & OCFS2_LOCK_NEEDS_REFRESH)) { @@ -2237,7 +2194,6 @@ static inline void ocfs2_complete_lock_res_refresh(struct ocfs2_lock_res *lockre int status) { unsigned long flags; - mlog_entry_void(); spin_lock_irqsave(&lockres->l_lock, flags); lockres_clear_flags(lockres, OCFS2_LOCK_REFRESHING); @@ -2260,8 +2216,6 @@ static int ocfs2_inode_lock_update(struct inode *inode, struct ocfs2_dinode *fe; struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - mlog_entry_void(); - if (ocfs2_mount_local(osb)) goto bail; @@ -2374,8 +2328,6 @@ int ocfs2_inode_lock_full_nested(struct inode *inode, BUG_ON(!inode); - mlog_entry_void(); - mlog(0, "inode %llu, take %s META lock\n", (unsigned long long)OCFS2_I(inode)->ip_blkno, ex ? "EXMODE" : "PRMODE"); @@ -2517,7 +2469,6 @@ int ocfs2_inode_lock_atime(struct inode *inode, { int ret; - mlog_entry_void(); ret = ocfs2_inode_lock(inode, NULL, 0); if (ret < 0) { mlog_errno(ret); @@ -2556,8 +2507,6 @@ void ocfs2_inode_unlock(struct inode *inode, struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_inode_lockres; struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - mlog_entry_void(); - mlog(0, "inode %llu drop %s META lock\n", (unsigned long long)OCFS2_I(inode)->ip_blkno, ex ? "EXMODE" : "PRMODE"); @@ -2617,8 +2566,6 @@ int ocfs2_super_lock(struct ocfs2_super *osb, int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR; struct ocfs2_lock_res *lockres = &osb->osb_super_lockres; - mlog_entry_void(); - if (ocfs2_is_hard_readonly(osb)) return -EROFS; @@ -3054,8 +3001,6 @@ int ocfs2_dlm_init(struct ocfs2_super *osb) int status = 0; struct ocfs2_cluster_connection *conn = NULL; - mlog_entry_void(); - if (ocfs2_mount_local(osb)) { osb->node_num = 0; goto local; @@ -3119,8 +3064,6 @@ bail: void ocfs2_dlm_shutdown(struct ocfs2_super *osb, int hangup_pending) { - mlog_entry_void(); - ocfs2_drop_osb_locks(osb); /* @@ -3284,8 +3227,6 @@ int ocfs2_drop_inode_locks(struct inode *inode) { int status, err; - mlog_entry_void(); - /* No need to call ocfs2_mark_lockres_freeing here - * ocfs2_clear_inode has done it for us. */ @@ -3352,8 +3293,6 @@ static int ocfs2_downconvert_lock(struct ocfs2_super *osb, int ret; u32 dlm_flags = DLM_LKF_CONVERT; - mlog_entry_void(); - mlog(ML_BASTS, "lockres %s, level %d => %d\n", lockres->l_name, lockres->l_level, new_level); @@ -3385,8 +3324,6 @@ static int ocfs2_prepare_cancel_convert(struct ocfs2_super *osb, { assert_spin_locked(&lockres->l_lock); - mlog_entry_void(); - if (lockres->l_unlock_action == OCFS2_UNLOCK_CANCEL_CONVERT) { /* If we're already trying to cancel a lock conversion * then just drop the spinlock and allow the caller to @@ -3416,8 +3353,6 @@ static int ocfs2_cancel_convert(struct ocfs2_super *osb, { int ret; - mlog_entry_void(); - ret = ocfs2_dlm_unlock(osb->cconn, &lockres->l_lksb, DLM_LKF_CANCEL); if (ret) { @@ -3443,8 +3378,6 @@ static int ocfs2_unblock_lock(struct ocfs2_super *osb, int set_lvb = 0; unsigned int gen; - mlog_entry_void(); - spin_lock_irqsave(&lockres->l_lock, flags); recheck: @@ -3859,8 +3792,6 @@ static void ocfs2_set_qinfo_lvb(struct ocfs2_lock_res *lockres) struct mem_dqinfo *info = sb_dqinfo(oinfo->dqi_gi.dqi_sb, oinfo->dqi_gi.dqi_type); - mlog_entry_void(); - lvb = ocfs2_dlm_lvb(&lockres->l_lksb); lvb->lvb_version = OCFS2_QINFO_LVB_VERSION; lvb->lvb_bgrace = cpu_to_be32(info->dqi_bgrace); @@ -3879,7 +3810,6 @@ void ocfs2_qinfo_unlock(struct ocfs2_mem_dqinfo *oinfo, int ex) struct ocfs2_super *osb = OCFS2_SB(oinfo->dqi_gi.dqi_sb); int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR; - mlog_entry_void(); if (!ocfs2_is_hard_readonly(osb) && !ocfs2_mount_local(osb)) ocfs2_cluster_unlock(osb, lockres, level); mlog_exit_void(); @@ -3937,8 +3867,6 @@ int ocfs2_qinfo_lock(struct ocfs2_mem_dqinfo *oinfo, int ex) int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR; int status = 0; - mlog_entry_void(); - /* On RO devices, locking really isn't needed... */ if (ocfs2_is_hard_readonly(osb)) { if (ex) @@ -4007,8 +3935,6 @@ static void ocfs2_process_blocked_lock(struct ocfs2_super *osb, * considered valid until we remove the OCFS2_LOCK_QUEUED * flag. */ - mlog_entry_void(); - BUG_ON(!lockres); BUG_ON(!lockres->l_ops); @@ -4049,8 +3975,6 @@ unqueue: static void ocfs2_schedule_blocked_lock(struct ocfs2_super *osb, struct ocfs2_lock_res *lockres) { - mlog_entry_void(); - assert_spin_locked(&lockres->l_lock); if (lockres->l_flags & OCFS2_LOCK_FREEING) { @@ -4080,8 +4004,6 @@ static void ocfs2_downconvert_thread_do_work(struct ocfs2_super *osb) unsigned long processed; struct ocfs2_lock_res *lockres; - mlog_entry_void(); - spin_lock(&osb->dc_task_lock); /* grab this early so we know to try again if a state change and * wake happens part-way through our work */ diff --git a/fs/ocfs2/export.c b/fs/ocfs2/export.c index 254652a9b542..b90c751ba938 100644 --- a/fs/ocfs2/export.c +++ b/fs/ocfs2/export.c @@ -56,7 +56,7 @@ static struct dentry *ocfs2_get_dentry(struct super_block *sb, int status, set; struct dentry *result; - mlog_entry("(0x%p, 0x%p)\n", sb, handle); + mlog(0, "(0x%p, 0x%p)\n", sb, handle); if (blkno == 0) { mlog(0, "nfs wants inode with blkno: 0\n"); @@ -152,8 +152,8 @@ static struct dentry *ocfs2_get_parent(struct dentry *child) struct dentry *parent; struct inode *dir = child->d_inode; - mlog_entry("(0x%p, '%.*s')\n", child, - child->d_name.len, child->d_name.name); + mlog(0, "(0x%p, '%.*s')\n", child, + child->d_name.len, child->d_name.name); mlog(0, "find parent of directory %llu\n", (unsigned long long)OCFS2_I(dir)->ip_blkno); @@ -193,9 +193,9 @@ static int ocfs2_encode_fh(struct dentry *dentry, u32 *fh_in, int *max_len, u32 generation; __le32 *fh = (__force __le32 *) fh_in; - mlog_entry("(0x%p, '%.*s', 0x%p, %d, %d)\n", dentry, - dentry->d_name.len, dentry->d_name.name, - fh, len, connectable); + mlog(0, "(0x%p, '%.*s', 0x%p, %d, %d)\n", dentry, + dentry->d_name.len, dentry->d_name.name, + fh, len, connectable); if (connectable && (len < 6)) { *max_len = 6; diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c index 09e3fdfa6d33..ed9916a9a271 100644 --- a/fs/ocfs2/extent_map.c +++ b/fs/ocfs2/extent_map.c @@ -841,10 +841,10 @@ int ocfs2_read_virt_blocks(struct inode *inode, u64 v_block, int nr, u64 p_block, p_count; int i, count, done = 0; - mlog_entry("(inode = %p, v_block = %llu, nr = %d, bhs = %p, " - "flags = %x, validate = %p)\n", - inode, (unsigned long long)v_block, nr, bhs, flags, - validate); + mlog(0, "(inode = %p, v_block = %llu, nr = %d, bhs = %p, " + "flags = %x, validate = %p)\n", + inode, (unsigned long long)v_block, nr, bhs, flags, + validate); if (((v_block + nr - 1) << inode->i_sb->s_blocksize_bits) >= i_size_read(inode)) { diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index a6651956482e..71375d7b7bbe 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -99,8 +99,8 @@ static int ocfs2_file_open(struct inode *inode, struct file *file) int mode = file->f_flags; struct ocfs2_inode_info *oi = OCFS2_I(inode); - mlog_entry("(0x%p, 0x%p, '%.*s')\n", inode, file, - file->f_path.dentry->d_name.len, file->f_path.dentry->d_name.name); + mlog(0, "(0x%p, 0x%p, '%.*s')\n", inode, file, + file->f_path.dentry->d_name.len, file->f_path.dentry->d_name.name); if (file->f_mode & FMODE_WRITE) dquot_initialize(inode); @@ -143,9 +143,9 @@ static int ocfs2_file_release(struct inode *inode, struct file *file) { struct ocfs2_inode_info *oi = OCFS2_I(inode); - mlog_entry("(0x%p, 0x%p, '%.*s')\n", inode, file, - file->f_path.dentry->d_name.len, - file->f_path.dentry->d_name.name); + mlog(0, "(0x%p, 0x%p, '%.*s')\n", inode, file, + file->f_path.dentry->d_name.len, + file->f_path.dentry->d_name.name); spin_lock(&oi->ip_lock); if (!--oi->ip_open_count) @@ -177,9 +177,9 @@ static int ocfs2_sync_file(struct file *file, int datasync) struct inode *inode = file->f_mapping->host; struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - mlog_entry("(0x%p, %d, 0x%p, '%.*s')\n", file, datasync, - file->f_path.dentry, file->f_path.dentry->d_name.len, - file->f_path.dentry->d_name.name); + mlog(0, "(0x%p, %d, 0x%p, '%.*s')\n", file, datasync, + file->f_path.dentry, file->f_path.dentry->d_name.len, + file->f_path.dentry->d_name.name); if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) { /* @@ -251,8 +251,6 @@ int ocfs2_update_inode_atime(struct inode *inode, handle_t *handle; struct ocfs2_dinode *di = (struct ocfs2_dinode *) bh->b_data; - mlog_entry_void(); - handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); if (IS_ERR(handle)) { ret = PTR_ERR(handle); @@ -291,7 +289,6 @@ static int ocfs2_set_inode_size(handle_t *handle, { int status; - mlog_entry_void(); i_size_write(inode, new_i_size); inode->i_blocks = ocfs2_inode_sector_count(inode); inode->i_ctime = inode->i_mtime = CURRENT_TIME; @@ -375,8 +372,6 @@ static int ocfs2_orphan_for_truncate(struct ocfs2_super *osb, struct ocfs2_dinode *di; u64 cluster_bytes; - mlog_entry_void(); - /* * We need to CoW the cluster contains the offset if it is reflinked * since we will call ocfs2_zero_range_for_truncate later which will @@ -442,9 +437,9 @@ static int ocfs2_truncate_file(struct inode *inode, struct ocfs2_dinode *fe = NULL; struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - mlog_entry("(inode = %llu, new_i_size = %llu\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno, - (unsigned long long)new_i_size); + mlog(0, "(inode = %llu, new_i_size = %llu\n", + (unsigned long long)OCFS2_I(inode)->ip_blkno, + (unsigned long long)new_i_size); /* We trust di_bh because it comes from ocfs2_inode_lock(), which * already validated it */ @@ -578,7 +573,7 @@ static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start, struct ocfs2_extent_tree et; int did_quota = 0; - mlog_entry("(clusters_to_add = %u)\n", clusters_to_add); + mlog(0, "(clusters_to_add = %u)\n", clusters_to_add); /* * This function only exists for file systems which don't @@ -1113,8 +1108,8 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) struct dquot *transfer_to[MAXQUOTAS] = { }; int qtype; - mlog_entry("(0x%p, '%.*s')\n", dentry, - dentry->d_name.len, dentry->d_name.name); + mlog(0, "(0x%p, '%.*s')\n", dentry, + dentry->d_name.len, dentry->d_name.name); /* ensuring we don't even attempt to truncate a symlink */ if (S_ISLNK(inode->i_mode)) @@ -1287,8 +1282,6 @@ int ocfs2_getattr(struct vfsmount *mnt, struct ocfs2_super *osb = sb->s_fs_info; int err; - mlog_entry_void(); - err = ocfs2_inode_revalidate(dentry); if (err) { if (err != -ENOENT) @@ -1314,8 +1307,6 @@ int ocfs2_permission(struct inode *inode, int mask, unsigned int flags) if (flags & IPERM_FLAG_RCU) return -ECHILD; - mlog_entry_void(); - ret = ocfs2_inode_lock(inode, NULL, 0); if (ret) { if (ret != -ENOENT) @@ -1339,8 +1330,8 @@ static int __ocfs2_write_remove_suid(struct inode *inode, struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); struct ocfs2_dinode *di; - mlog_entry("(Inode %llu, mode 0%o)\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno, inode->i_mode); + mlog(0, "(Inode %llu, mode 0%o)\n", + (unsigned long long)OCFS2_I(inode)->ip_blkno, inode->i_mode); handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); if (IS_ERR(handle)) { @@ -2233,10 +2224,10 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, int full_coherency = !(osb->s_mount_opt & OCFS2_MOUNT_COHERENCY_BUFFERED); - mlog_entry("(0x%p, %u, '%.*s')\n", file, - (unsigned int)nr_segs, - file->f_path.dentry->d_name.len, - file->f_path.dentry->d_name.name); + mlog(0, "(0x%p, %u, '%.*s')\n", file, + (unsigned int)nr_segs, + file->f_path.dentry->d_name.len, + file->f_path.dentry->d_name.name); if (iocb->ki_left == 0) return 0; @@ -2438,10 +2429,10 @@ static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe, .u.file = out, }; - mlog_entry("(0x%p, 0x%p, %u, '%.*s')\n", out, pipe, - (unsigned int)len, - out->f_path.dentry->d_name.len, - out->f_path.dentry->d_name.name); + mlog(0, "(0x%p, 0x%p, %u, '%.*s')\n", out, pipe, + (unsigned int)len, + out->f_path.dentry->d_name.len, + out->f_path.dentry->d_name.name); if (pipe->inode) mutex_lock_nested(&pipe->inode->i_mutex, I_MUTEX_PARENT); @@ -2498,10 +2489,10 @@ static ssize_t ocfs2_file_splice_read(struct file *in, int ret = 0, lock_level = 0; struct inode *inode = in->f_path.dentry->d_inode; - mlog_entry("(0x%p, 0x%p, %u, '%.*s')\n", in, pipe, - (unsigned int)len, - in->f_path.dentry->d_name.len, - in->f_path.dentry->d_name.name); + mlog(0, "(0x%p, 0x%p, %u, '%.*s')\n", in, pipe, + (unsigned int)len, + in->f_path.dentry->d_name.len, + in->f_path.dentry->d_name.name); /* * See the comment in ocfs2_file_aio_read() @@ -2529,10 +2520,10 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb, struct file *filp = iocb->ki_filp; struct inode *inode = filp->f_path.dentry->d_inode; - mlog_entry("(0x%p, %u, '%.*s')\n", filp, - (unsigned int)nr_segs, - filp->f_path.dentry->d_name.len, - filp->f_path.dentry->d_name.name); + mlog(0, "(0x%p, %u, '%.*s')\n", filp, + (unsigned int)nr_segs, + filp->f_path.dentry->d_name.len, + filp->f_path.dentry->d_name.name); if (!inode) { ret = -EINVAL; diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index 4068c6c4c6f6..16ee8e96f731 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c @@ -131,7 +131,7 @@ struct inode *ocfs2_iget(struct ocfs2_super *osb, u64 blkno, unsigned flags, struct super_block *sb = osb->sb; struct ocfs2_find_inode_args args; - mlog_entry("(blkno = %llu)\n", (unsigned long long)blkno); + mlog(0, "(blkno = %llu)\n", (unsigned long long)blkno); /* Ok. By now we've either got the offsets passed to us by the * caller, or we just pulled them off the bh. Lets do some @@ -192,7 +192,7 @@ static int ocfs2_find_actor(struct inode *inode, void *opaque) struct ocfs2_inode_info *oi = OCFS2_I(inode); int ret = 0; - mlog_entry("(0x%p, %lu, 0x%p)\n", inode, inode->i_ino, opaque); + mlog(0, "(0x%p, %lu, 0x%p)\n", inode, inode->i_ino, opaque); args = opaque; @@ -218,7 +218,7 @@ static int ocfs2_init_locked_inode(struct inode *inode, void *opaque) static struct lock_class_key ocfs2_quota_ip_alloc_sem_key, ocfs2_file_ip_alloc_sem_key; - mlog_entry("inode = %p, opaque = %p\n", inode, opaque); + mlog(0, "inode = %p, opaque = %p\n", inode, opaque); inode->i_ino = args->fi_ino; OCFS2_I(inode)->ip_blkno = args->fi_blkno; @@ -246,8 +246,8 @@ void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, struct ocfs2_super *osb; int use_plocks = 1; - mlog_entry("(0x%p, size:%llu)\n", inode, - (unsigned long long)le64_to_cpu(fe->i_size)); + mlog(0, "(0x%p, size:%llu)\n", inode, + (unsigned long long)le64_to_cpu(fe->i_size)); sb = inode->i_sb; osb = OCFS2_SB(sb); @@ -394,7 +394,7 @@ static int ocfs2_read_locked_inode(struct inode *inode, int status, can_lock; u32 generation = 0; - mlog_entry("(0x%p, 0x%p)\n", inode, args); + mlog(0, "(0x%p, 0x%p)\n", inode, args); status = -EINVAL; if (inode == NULL || inode->i_sb == NULL) { @@ -551,8 +551,6 @@ static int ocfs2_truncate_for_delete(struct ocfs2_super *osb, struct ocfs2_dinode *fe; handle_t *handle = NULL; - mlog_entry_void(); - fe = (struct ocfs2_dinode *) fe_bh->b_data; /* @@ -980,7 +978,7 @@ static void ocfs2_delete_inode(struct inode *inode) sigset_t oldset; struct buffer_head *di_bh = NULL; - mlog_entry("(inode->i_ino = %lu)\n", inode->i_ino); + mlog(0, "(inode->i_ino = %lu)\n", inode->i_ino); /* When we fail in read_inode() we mark inode as bad. The second test * catches the case when inode allocation fails before allocating @@ -1088,8 +1086,6 @@ static void ocfs2_clear_inode(struct inode *inode) int status; struct ocfs2_inode_info *oi = OCFS2_I(inode); - mlog_entry_void(); - end_writeback(inode); mlog(0, "Clearing inode: %llu, nlink = %u\n", (unsigned long long)OCFS2_I(inode)->ip_blkno, inode->i_nlink); @@ -1204,8 +1200,6 @@ int ocfs2_drop_inode(struct inode *inode) struct ocfs2_inode_info *oi = OCFS2_I(inode); int res; - mlog_entry_void(); - mlog(0, "Drop inode %llu, nlink = %u, ip_flags = 0x%x\n", (unsigned long long)oi->ip_blkno, inode->i_nlink, oi->ip_flags); @@ -1226,8 +1220,8 @@ int ocfs2_inode_revalidate(struct dentry *dentry) struct inode *inode = dentry->d_inode; int status = 0; - mlog_entry("(inode = 0x%p, ino = %llu)\n", inode, - inode ? (unsigned long long)OCFS2_I(inode)->ip_blkno : 0ULL); + mlog(0, "(inode = 0x%p, ino = %llu)\n", inode, + inode ? (unsigned long long)OCFS2_I(inode)->ip_blkno : 0ULL); if (!inode) { mlog(0, "eep, no inode!\n"); @@ -1271,8 +1265,8 @@ int ocfs2_mark_inode_dirty(handle_t *handle, int status; struct ocfs2_dinode *fe = (struct ocfs2_dinode *) bh->b_data; - mlog_entry("(inode %llu)\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno); + mlog(0, "(inode %llu)\n", + (unsigned long long)OCFS2_I(inode)->ip_blkno); status = ocfs2_journal_access_di(handle, INODE_CACHE(inode), bh, OCFS2_JOURNAL_ACCESS_WRITE); diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index faa2303dbf0a..7378277b17a4 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c @@ -303,8 +303,6 @@ static int ocfs2_commit_cache(struct ocfs2_super *osb) unsigned int flushed; struct ocfs2_journal *journal = NULL; - mlog_entry_void(); - journal = osb->journal; /* Flush all pending commits and checkpoint the journal. */ @@ -425,7 +423,6 @@ int ocfs2_extend_trans(handle_t *handle, int nblocks) return 0; old_nblocks = handle->h_buffer_credits; - mlog_entry_void(); mlog(0, "Trying to extend transaction by %d blocks\n", nblocks); @@ -622,12 +619,12 @@ static int __ocfs2_journal_access(handle_t *handle, BUG_ON(!handle); BUG_ON(!bh); - mlog_entry("bh->b_blocknr=%llu, type=%d (\"%s\"), bh->b_size = %zu\n", - (unsigned long long)bh->b_blocknr, type, - (type == OCFS2_JOURNAL_ACCESS_CREATE) ? - "OCFS2_JOURNAL_ACCESS_CREATE" : - "OCFS2_JOURNAL_ACCESS_WRITE", - bh->b_size); + mlog(0, "bh->b_blocknr=%llu, type=%d (\"%s\"), bh->b_size = %zu\n", + (unsigned long long)bh->b_blocknr, type, + (type == OCFS2_JOURNAL_ACCESS_CREATE) ? + "OCFS2_JOURNAL_ACCESS_CREATE" : + "OCFS2_JOURNAL_ACCESS_WRITE", + bh->b_size); /* we can safely remove this assertion after testing. */ if (!buffer_uptodate(bh)) { @@ -737,8 +734,8 @@ void ocfs2_journal_dirty(handle_t *handle, struct buffer_head *bh) { int status; - mlog_entry("(bh->b_blocknr=%llu)\n", - (unsigned long long)bh->b_blocknr); + mlog(0, "(bh->b_blocknr=%llu)\n", + (unsigned long long)bh->b_blocknr); status = jbd2_journal_dirty_metadata(handle, bh); BUG_ON(status); @@ -775,8 +772,6 @@ int ocfs2_journal_init(struct ocfs2_journal *journal, int *dirty) struct ocfs2_super *osb; int inode_lock = 0; - mlog_entry_void(); - BUG_ON(!journal); osb = journal->j_osb; @@ -882,8 +877,6 @@ static int ocfs2_journal_toggle_dirty(struct ocfs2_super *osb, struct buffer_head *bh = journal->j_bh; struct ocfs2_dinode *fe; - mlog_entry_void(); - fe = (struct ocfs2_dinode *)bh->b_data; /* The journal bh on the osb always comes from ocfs2_journal_init() @@ -921,8 +914,6 @@ void ocfs2_journal_shutdown(struct ocfs2_super *osb) struct inode *inode = NULL; int num_running_trans = 0; - mlog_entry_void(); - BUG_ON(!osb); journal = osb->journal; @@ -1024,8 +1015,6 @@ int ocfs2_journal_load(struct ocfs2_journal *journal, int local, int replayed) int status = 0; struct ocfs2_super *osb; - mlog_entry_void(); - BUG_ON(!journal); osb = journal->j_osb; @@ -1070,8 +1059,6 @@ int ocfs2_journal_wipe(struct ocfs2_journal *journal, int full) { int status; - mlog_entry_void(); - BUG_ON(!journal); status = jbd2_journal_wipe(journal->j_journal, full); @@ -1124,8 +1111,6 @@ static int ocfs2_force_read_journal(struct inode *inode) #define CONCURRENT_JOURNAL_FILL 32ULL struct buffer_head *bhs[CONCURRENT_JOURNAL_FILL]; - mlog_entry_void(); - memset(bhs, 0, sizeof(struct buffer_head *) * CONCURRENT_JOURNAL_FILL); num_blocks = ocfs2_blocks_for_bytes(inode->i_sb, inode->i_size); @@ -1194,8 +1179,6 @@ void ocfs2_complete_recovery(struct work_struct *work) struct ocfs2_quota_recovery *qrec; LIST_HEAD(tmp_la_list); - mlog_entry_void(); - mlog(0, "completing recovery from keventd\n"); spin_lock(&journal->j_lock); @@ -1339,8 +1322,6 @@ static int __ocfs2_recovery_thread(void *arg) int rm_quota_used = 0, i; struct ocfs2_quota_recovery *qrec; - mlog_entry_void(); - status = ocfs2_wait_on_mount(osb); if (status < 0) { goto bail; @@ -1461,8 +1442,8 @@ bail: void ocfs2_recovery_thread(struct ocfs2_super *osb, int node_num) { - mlog_entry("(node_num=%d, osb->node_num = %d)\n", - node_num, osb->node_num); + mlog(0, "(node_num=%d, osb->node_num = %d)\n", + node_num, osb->node_num); mutex_lock(&osb->recovery_lock); if (osb->disable_recovery) @@ -1688,8 +1669,8 @@ static int ocfs2_recover_node(struct ocfs2_super *osb, struct ocfs2_dinode *la_copy = NULL; struct ocfs2_dinode *tl_copy = NULL; - mlog_entry("(node_num=%d, slot_num=%d, osb->node_num = %d)\n", - node_num, slot_num, osb->node_num); + mlog(0, "(node_num=%d, slot_num=%d, osb->node_num = %d)\n", + node_num, slot_num, osb->node_num); /* Should not ever be called to recover ourselves -- in that * case we should've called ocfs2_journal_load instead. */ diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c index ec6adbf8f551..5f08c703f354 100644 --- a/fs/ocfs2/localalloc.c +++ b/fs/ocfs2/localalloc.c @@ -291,8 +291,6 @@ int ocfs2_load_local_alloc(struct ocfs2_super *osb) struct inode *inode = NULL; struct ocfs2_local_alloc *la; - mlog_entry_void(); - if (osb->local_alloc_bits == 0) goto bail; @@ -388,8 +386,6 @@ void ocfs2_shutdown_local_alloc(struct ocfs2_super *osb) struct ocfs2_dinode *alloc_copy = NULL; struct ocfs2_dinode *alloc = NULL; - mlog_entry_void(); - cancel_delayed_work(&osb->la_enable_wq); flush_workqueue(ocfs2_wq); @@ -502,7 +498,7 @@ int ocfs2_begin_local_alloc_recovery(struct ocfs2_super *osb, struct inode *inode = NULL; struct ocfs2_dinode *alloc; - mlog_entry("(slot_num = %d)\n", slot_num); + mlog(0, "(slot_num = %d)\n", slot_num); *alloc_copy = NULL; @@ -570,8 +566,6 @@ int ocfs2_complete_local_alloc_recovery(struct ocfs2_super *osb, struct buffer_head *main_bm_bh = NULL; struct inode *main_bm_inode; - mlog_entry_void(); - main_bm_inode = ocfs2_get_system_file_inode(osb, GLOBAL_BITMAP_SYSTEM_INODE, OCFS2_INVALID_SLOT); @@ -640,8 +634,6 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb, struct inode *local_alloc_inode; unsigned int free_bits; - mlog_entry_void(); - BUG_ON(!ac); local_alloc_inode = @@ -749,7 +741,6 @@ int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb, struct ocfs2_dinode *alloc; struct ocfs2_local_alloc *la; - mlog_entry_void(); BUG_ON(ac->ac_which != OCFS2_AC_USE_LOCAL); local_alloc_inode = ac->ac_inode; @@ -799,8 +790,6 @@ static u32 ocfs2_local_alloc_count_bits(struct ocfs2_dinode *alloc) u32 count = 0; struct ocfs2_local_alloc *la = OCFS2_LOCAL_ALLOC(alloc); - mlog_entry_void(); - buffer = la->la_bitmap; for (i = 0; i < le16_to_cpu(la->la_size); i++) count += hweight8(buffer[i]); @@ -820,7 +809,7 @@ static int ocfs2_local_alloc_find_clear_bits(struct ocfs2_super *osb, void *bitmap = NULL; struct ocfs2_reservation_map *resmap = &osb->osb_la_resmap; - mlog_entry("(numbits wanted = %u)\n", *numbits); + mlog(0, "(numbits wanted = %u)\n", *numbits); if (!alloc->id1.bitmap1.i_total) { mlog(0, "No bits in my window!\n"); @@ -903,7 +892,6 @@ static void ocfs2_clear_local_alloc(struct ocfs2_dinode *alloc) { struct ocfs2_local_alloc *la = OCFS2_LOCAL_ALLOC(alloc); int i; - mlog_entry_void(); alloc->id1.bitmap1.i_total = 0; alloc->id1.bitmap1.i_used = 0; @@ -952,9 +940,9 @@ static int ocfs2_sync_local_to_main(struct ocfs2_super *osb, void *bitmap; struct ocfs2_local_alloc *la = OCFS2_LOCAL_ALLOC(alloc); - mlog_entry("total = %u, used = %u\n", - le32_to_cpu(alloc->id1.bitmap1.i_total), - le32_to_cpu(alloc->id1.bitmap1.i_used)); + mlog(0, "total = %u, used = %u\n", + le32_to_cpu(alloc->id1.bitmap1.i_total), + le32_to_cpu(alloc->id1.bitmap1.i_used)); if (!alloc->id1.bitmap1.i_total) { mlog(0, "nothing to sync!\n"); @@ -1148,8 +1136,6 @@ static int ocfs2_local_alloc_new_window(struct ocfs2_super *osb, struct ocfs2_dinode *alloc = NULL; struct ocfs2_local_alloc *la; - mlog_entry_void(); - alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data; la = OCFS2_LOCAL_ALLOC(alloc); @@ -1243,8 +1229,6 @@ static int ocfs2_local_alloc_slide_window(struct ocfs2_super *osb, struct ocfs2_dinode *alloc_copy = NULL; struct ocfs2_alloc_context *ac = NULL; - mlog_entry_void(); - ocfs2_recalc_la_window(osb, OCFS2_LA_EVENT_SLIDE); /* This will lock the main bitmap for us. */ diff --git a/fs/ocfs2/mmap.c b/fs/ocfs2/mmap.c index 7e32db9c2c99..87438e178e11 100644 --- a/fs/ocfs2/mmap.c +++ b/fs/ocfs2/mmap.c @@ -49,7 +49,7 @@ static int ocfs2_fault(struct vm_area_struct *area, struct vm_fault *vmf) sigset_t oldset; int ret; - mlog_entry("(area=%p, page offset=%lu)\n", area, vmf->pgoff); + mlog(0, "(area=%p, page offset=%lu)\n", area, vmf->pgoff); ocfs2_block_signals(&oldset); ret = filemap_fault(area, vmf); diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 849fb4a2e814..fdf5c0b75caa 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c @@ -106,8 +106,8 @@ static struct dentry *ocfs2_lookup(struct inode *dir, struct dentry *dentry, struct dentry *ret; struct ocfs2_inode_info *oi; - mlog_entry("(0x%p, 0x%p, '%.*s')\n", dir, dentry, - dentry->d_name.len, dentry->d_name.name); + mlog(0, "(0x%p, 0x%p, '%.*s')\n", dir, dentry, + dentry->d_name.len, dentry->d_name.name); if (dentry->d_name.len > OCFS2_MAX_FILENAME_LEN) { ret = ERR_PTR(-ENAMETOOLONG); @@ -235,9 +235,9 @@ static int ocfs2_mknod(struct inode *dir, sigset_t oldset; int did_block_signals = 0; - mlog_entry("(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry, mode, - (unsigned long)dev, dentry->d_name.len, - dentry->d_name.name); + mlog(0, "(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry, mode, + (unsigned long)dev, dentry->d_name.len, + dentry->d_name.name); dquot_initialize(dir); @@ -354,9 +354,9 @@ static int ocfs2_mknod(struct inode *dir, goto leave; did_quota_inode = 1; - mlog_entry("(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry, - inode->i_mode, (unsigned long)dev, dentry->d_name.len, - dentry->d_name.name); + mlog(0, "(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry, + inode->i_mode, (unsigned long)dev, dentry->d_name.len, + dentry->d_name.name); /* do the real work now. */ status = ocfs2_mknod_locked(osb, dir, inode, dev, @@ -615,8 +615,8 @@ static int ocfs2_mkdir(struct inode *dir, { int ret; - mlog_entry("(0x%p, 0x%p, %d, '%.*s')\n", dir, dentry, mode, - dentry->d_name.len, dentry->d_name.name); + mlog(0, "(0x%p, 0x%p, %d, '%.*s')\n", dir, dentry, mode, + dentry->d_name.len, dentry->d_name.name); ret = ocfs2_mknod(dir, dentry, mode | S_IFDIR, 0); mlog_exit(ret); @@ -630,8 +630,8 @@ static int ocfs2_create(struct inode *dir, { int ret; - mlog_entry("(0x%p, 0x%p, %d, '%.*s')\n", dir, dentry, mode, - dentry->d_name.len, dentry->d_name.name); + mlog(0, "(0x%p, 0x%p, %d, '%.*s')\n", dir, dentry, mode, + dentry->d_name.len, dentry->d_name.name); ret = ocfs2_mknod(dir, dentry, mode | S_IFREG, 0); mlog_exit(ret); @@ -652,9 +652,9 @@ static int ocfs2_link(struct dentry *old_dentry, struct ocfs2_dir_lookup_result lookup = { NULL, }; sigset_t oldset; - mlog_entry("(inode=%lu, old='%.*s' new='%.*s')\n", inode->i_ino, - old_dentry->d_name.len, old_dentry->d_name.name, - dentry->d_name.len, dentry->d_name.name); + mlog(0, "(inode=%lu, old='%.*s' new='%.*s')\n", inode->i_ino, + old_dentry->d_name.len, old_dentry->d_name.name, + dentry->d_name.len, dentry->d_name.name); if (S_ISDIR(inode->i_mode)) return -EPERM; @@ -809,8 +809,8 @@ static int ocfs2_unlink(struct inode *dir, struct ocfs2_dir_lookup_result lookup = { NULL, }; struct ocfs2_dir_lookup_result orphan_insert = { NULL, }; - mlog_entry("(0x%p, 0x%p, '%.*s')\n", dir, dentry, - dentry->d_name.len, dentry->d_name.name); + mlog(0, "(0x%p, 0x%p, '%.*s')\n", dir, dentry, + dentry->d_name.len, dentry->d_name.name); dquot_initialize(dir); @@ -975,9 +975,9 @@ static int ocfs2_double_lock(struct ocfs2_super *osb, struct buffer_head **tmpbh; struct inode *tmpinode; - mlog_entry("(inode1 = %llu, inode2 = %llu)\n", - (unsigned long long)oi1->ip_blkno, - (unsigned long long)oi2->ip_blkno); + mlog(0, "(inode1 = %llu, inode2 = %llu)\n", + (unsigned long long)oi1->ip_blkno, + (unsigned long long)oi2->ip_blkno); if (*bh1) *bh1 = NULL; @@ -1067,10 +1067,10 @@ static int ocfs2_rename(struct inode *old_dir, /* At some point it might be nice to break this function up a * bit. */ - mlog_entry("(0x%p, 0x%p, 0x%p, 0x%p, from='%.*s' to='%.*s')\n", - old_dir, old_dentry, new_dir, new_dentry, - old_dentry->d_name.len, old_dentry->d_name.name, - new_dentry->d_name.len, new_dentry->d_name.name); + mlog(0, "(0x%p, 0x%p, 0x%p, 0x%p, from='%.*s' to='%.*s')\n", + old_dir, old_dentry, new_dir, new_dentry, + old_dentry->d_name.len, old_dentry->d_name.name, + new_dentry->d_name.len, new_dentry->d_name.name); dquot_initialize(old_dir); dquot_initialize(new_dir); @@ -1501,9 +1501,9 @@ static int ocfs2_create_symlink_data(struct ocfs2_super *osb, * write i_size + 1 bytes. */ blocks = (bytes_left + sb->s_blocksize - 1) >> sb->s_blocksize_bits; - mlog_entry("i_blocks = %llu, i_size = %llu, blocks = %d\n", - (unsigned long long)inode->i_blocks, - i_size_read(inode), blocks); + mlog(0, "i_blocks = %llu, i_size = %llu, blocks = %d\n", + (unsigned long long)inode->i_blocks, + i_size_read(inode), blocks); /* Sanity check -- make sure we're going to fit. */ if (bytes_left > @@ -1610,8 +1610,8 @@ static int ocfs2_symlink(struct inode *dir, sigset_t oldset; int did_block_signals = 0; - mlog_entry("(0x%p, 0x%p, symname='%s' actual='%.*s')\n", dir, - dentry, symname, dentry->d_name.len, dentry->d_name.name); + mlog(0, "(0x%p, 0x%p, symname='%s' actual='%.*s')\n", dir, + dentry, symname, dentry->d_name.len, dentry->d_name.name); dquot_initialize(dir); @@ -1713,9 +1713,9 @@ static int ocfs2_symlink(struct inode *dir, goto bail; did_quota_inode = 1; - mlog_entry("(0x%p, 0x%p, %d, '%.*s')\n", dir, dentry, - inode->i_mode, dentry->d_name.len, - dentry->d_name.name); + mlog(0, "(0x%p, 0x%p, %d, '%.*s')\n", dir, dentry, + inode->i_mode, dentry->d_name.len, + dentry->d_name.name); status = ocfs2_mknod_locked(osb, dir, inode, 0, &new_fe_bh, parent_fe_bh, handle, @@ -1844,8 +1844,6 @@ static int ocfs2_blkno_stringify(u64 blkno, char *name) { int status, namelen; - mlog_entry_void(); - namelen = snprintf(name, OCFS2_ORPHAN_NAMELEN + 1, "%016llx", (long long)blkno); if (namelen <= 0) { @@ -1997,7 +1995,7 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb, struct ocfs2_dinode *orphan_fe; struct ocfs2_dinode *fe = (struct ocfs2_dinode *) fe_bh->b_data; - mlog_entry("(inode->i_ino = %lu)\n", inode->i_ino); + mlog(0, "(inode->i_ino = %lu)\n", inode->i_ino); status = ocfs2_read_inode_block(orphan_dir_inode, &orphan_dir_bh); if (status < 0) { @@ -2078,8 +2076,6 @@ int ocfs2_orphan_del(struct ocfs2_super *osb, int status = 0; struct ocfs2_dir_lookup_result lookup = { NULL, }; - mlog_entry_void(); - status = ocfs2_blkno_stringify(OCFS2_I(inode)->ip_blkno, name); if (status < 0) { mlog_errno(status); @@ -2358,8 +2354,8 @@ int ocfs2_mv_orphaned_inode_to_new(struct inode *dir, struct buffer_head *di_bh = NULL; struct ocfs2_dir_lookup_result lookup = { NULL, }; - mlog_entry("(0x%p, 0x%p, %.*s')\n", dir, dentry, - dentry->d_name.len, dentry->d_name.name); + mlog(0, "(0x%p, 0x%p, %.*s')\n", dir, dentry, + dentry->d_name.len, dentry->d_name.name); status = ocfs2_inode_lock(dir, &parent_di_bh, 1); if (status < 0) { diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c index 4607923eb24c..33397bd7e1bc 100644 --- a/fs/ocfs2/quota_global.c +++ b/fs/ocfs2/quota_global.c @@ -343,8 +343,6 @@ int ocfs2_global_read_info(struct super_block *sb, int type) u64 pcount; int status; - mlog_entry_void(); - /* Read global header */ gqinode = ocfs2_get_system_file_inode(OCFS2_SB(sb), ino[type], OCFS2_INVALID_SLOT); @@ -596,7 +594,7 @@ static int ocfs2_sync_dquot_helper(struct dquot *dquot, unsigned long type) struct ocfs2_super *osb = OCFS2_SB(sb); int status = 0; - mlog_entry("id=%u qtype=%u type=%lu device=%s\n", dquot->dq_id, + mlog(0, "id=%u qtype=%u type=%lu device=%s\n", dquot->dq_id, dquot->dq_type, type, sb->s_id); if (type != dquot->dq_type) goto out; @@ -649,7 +647,7 @@ static int ocfs2_write_dquot(struct dquot *dquot) struct ocfs2_super *osb = OCFS2_SB(dquot->dq_sb); int status = 0; - mlog_entry("id=%u, type=%d", dquot->dq_id, dquot->dq_type); + mlog(0, "id=%u, type=%d", dquot->dq_id, dquot->dq_type); handle = ocfs2_start_trans(osb, OCFS2_QWRITE_CREDITS); if (IS_ERR(handle)) { @@ -688,7 +686,7 @@ static int ocfs2_release_dquot(struct dquot *dquot) struct ocfs2_super *osb = OCFS2_SB(dquot->dq_sb); int status = 0; - mlog_entry("id=%u, type=%d", dquot->dq_id, dquot->dq_type); + mlog(0, "id=%u, type=%d", dquot->dq_id, dquot->dq_type); mutex_lock(&dquot->dq_lock); /* Check whether we are not racing with some other dqget() */ @@ -745,7 +743,7 @@ static int ocfs2_acquire_dquot(struct dquot *dquot) int need_alloc = ocfs2_global_qinit_alloc(sb, type); handle_t *handle; - mlog_entry("id=%u, type=%d", dquot->dq_id, type); + mlog(0, "id=%u, type=%d", dquot->dq_id, type); mutex_lock(&dquot->dq_lock); /* * We need an exclusive lock, because we're going to update use count @@ -831,7 +829,7 @@ static int ocfs2_mark_dquot_dirty(struct dquot *dquot) handle_t *handle; struct ocfs2_super *osb = OCFS2_SB(sb); - mlog_entry("id=%u, type=%d", dquot->dq_id, type); + mlog(0, "id=%u, type=%d", dquot->dq_id, type); /* In case user set some limits, sync dquot immediately to global * quota file so that information propagates quicker */ @@ -879,8 +877,6 @@ static int ocfs2_write_info(struct super_block *sb, int type) int status = 0; struct ocfs2_mem_dqinfo *oinfo = sb_dqinfo(sb, type)->dqi_priv; - mlog_entry_void(); - status = ocfs2_lock_global_qf(oinfo, 1); if (status < 0) goto out; diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c index dc78764ccc4c..a71d68d88667 100644 --- a/fs/ocfs2/quota_local.c +++ b/fs/ocfs2/quota_local.c @@ -475,7 +475,7 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode, struct ocfs2_recovery_chunk *rchunk, *next; qsize_t spacechange, inodechange; - mlog_entry("ino=%lu type=%u", (unsigned long)lqinode->i_ino, type); + mlog(0, "ino=%lu type=%u", (unsigned long)lqinode->i_ino, type); list_for_each_entry_safe(rchunk, next, &(rec->r_list[type]), rc_list) { chunk = rchunk->rc_chunk; diff --git a/fs/ocfs2/resize.c b/fs/ocfs2/resize.c index dacd553d8617..e4a50e3fcb80 100644 --- a/fs/ocfs2/resize.c +++ b/fs/ocfs2/resize.c @@ -103,8 +103,8 @@ static int ocfs2_update_last_group_and_inode(handle_t *handle, u16 cl_bpc = le16_to_cpu(cl->cl_bpc); u16 cl_cpg = le16_to_cpu(cl->cl_cpg); - mlog_entry("(new_clusters=%d, first_new_cluster = %u)\n", - new_clusters, first_new_cluster); + mlog(0, "(new_clusters=%d, first_new_cluster = %u)\n", + new_clusters, first_new_cluster); ret = ocfs2_journal_access_gd(handle, INODE_CACHE(bm_inode), group_bh, OCFS2_JOURNAL_ACCESS_WRITE); @@ -281,8 +281,6 @@ int ocfs2_group_extend(struct inode * inode, int new_clusters) u32 first_new_cluster; u64 lgd_blkno; - mlog_entry_void(); - if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb)) return -EROFS; @@ -472,8 +470,6 @@ int ocfs2_group_add(struct inode *inode, struct ocfs2_new_group_input *input) struct ocfs2_chain_rec *cr; u16 cl_bpc; - mlog_entry_void(); - if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb)) return -EROFS; diff --git a/fs/ocfs2/slot_map.c b/fs/ocfs2/slot_map.c index ab4e0172cc1d..a6016e6b3ca2 100644 --- a/fs/ocfs2/slot_map.c +++ b/fs/ocfs2/slot_map.c @@ -475,8 +475,6 @@ int ocfs2_find_slot(struct ocfs2_super *osb) int slot; struct ocfs2_slot_info *si; - mlog_entry_void(); - si = osb->slot_info; spin_lock(&osb->osb_lock); diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index 71998d4d61d5..dd618496c2c6 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -389,8 +389,6 @@ static int ocfs2_block_group_fill(handle_t *handle, struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) bg_bh->b_data; struct super_block * sb = alloc_inode->i_sb; - mlog_entry_void(); - if (((unsigned long long) bg_bh->b_blocknr) != group_blkno) { ocfs2_error(alloc_inode->i_sb, "group block (%llu) != " "b_blocknr (%llu)", @@ -707,8 +705,6 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb, BUG_ON(ocfs2_is_cluster_bitmap(alloc_inode)); - mlog_entry_void(); - cl = &fe->id2.i_chain; status = ocfs2_reserve_clusters_with_limit(osb, le16_to_cpu(cl->cl_cpg), @@ -814,8 +810,6 @@ static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb, struct ocfs2_dinode *fe; u32 free_bits; - mlog_entry_void(); - alloc_inode = ocfs2_get_system_file_inode(osb, type, slot); if (!alloc_inode) { mlog_errno(-EINVAL); @@ -1189,8 +1183,6 @@ static int ocfs2_reserve_clusters_with_limit(struct ocfs2_super *osb, { int status; - mlog_entry_void(); - *ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL); if (!(*ac)) { status = -ENOMEM; @@ -1357,8 +1349,6 @@ static inline int ocfs2_block_group_set_bits(handle_t *handle, void *bitmap = bg->bg_bitmap; int journal_type = OCFS2_JOURNAL_ACCESS_WRITE; - mlog_entry_void(); - /* All callers get the descriptor via * ocfs2_read_group_descriptor(). Any corruption is a code bug. */ BUG_ON(!OCFS2_IS_VALID_GROUP_DESC(bg)); @@ -1888,8 +1878,6 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_alloc_context *ac, struct ocfs2_chain_list *cl; struct ocfs2_dinode *fe; - mlog_entry_void(); - BUG_ON(ac->ac_bits_given >= ac->ac_bits_wanted); BUG_ON(bits_wanted > (ac->ac_bits_wanted - ac->ac_bits_given)); BUG_ON(!ac->ac_bh); @@ -2201,8 +2189,6 @@ int ocfs2_claim_new_inode(handle_t *handle, int status; struct ocfs2_suballoc_result res; - mlog_entry_void(); - BUG_ON(!ac); BUG_ON(ac->ac_bits_given != 0); BUG_ON(ac->ac_bits_wanted != 1); @@ -2307,8 +2293,6 @@ int __ocfs2_claim_clusters(handle_t *handle, struct ocfs2_suballoc_result res = { .sr_blkno = 0, }; struct ocfs2_super *osb = OCFS2_SB(ac->ac_inode->i_sb); - mlog_entry_void(); - BUG_ON(ac->ac_bits_given >= ac->ac_bits_wanted); BUG_ON(ac->ac_which != OCFS2_AC_USE_LOCAL @@ -2392,8 +2376,6 @@ static int ocfs2_block_group_clear_bits(handle_t *handle, unsigned int tmp; struct ocfs2_group_desc *undo_bg = NULL; - mlog_entry_void(); - /* The caller got this descriptor from * ocfs2_read_group_descriptor(). Any corruption is a code bug. */ BUG_ON(!OCFS2_IS_VALID_GROUP_DESC(bg)); @@ -2463,8 +2445,6 @@ static int _ocfs2_free_suballoc_bits(handle_t *handle, struct buffer_head *group_bh = NULL; struct ocfs2_group_desc *group; - mlog_entry_void(); - /* The alloc_bh comes from ocfs2_free_dinode() or * ocfs2_free_clusters(). The callers have all locked the * allocator and gotten alloc_bh from the lock call. This @@ -2556,11 +2536,8 @@ static int _ocfs2_free_clusters(handle_t *handle, /* You can't ever have a contiguous set of clusters * bigger than a block group bitmap so we never have to worry - * about looping on them. */ - - mlog_entry_void(); - - /* This is expensive. We can safely remove once this stuff has + * about looping on them. + * This is expensive. We can safely remove once this stuff has * gotten tested really well. */ BUG_ON(start_blk != ocfs2_clusters_to_blocks(bitmap_inode->i_sb, ocfs2_blocks_to_clusters(bitmap_inode->i_sb, start_blk))); @@ -2756,7 +2733,7 @@ static int ocfs2_get_suballoc_slot_bit(struct ocfs2_super *osb, u64 blkno, struct buffer_head *inode_bh = NULL; struct ocfs2_dinode *inode_fe; - mlog_entry("blkno: %llu\n", (unsigned long long)blkno); + mlog(0, "blkno: %llu\n", (unsigned long long)blkno); /* dirty read disk */ status = ocfs2_read_blocks_sync(osb, blkno, 1, &inode_bh); @@ -2816,8 +2793,8 @@ static int ocfs2_test_suballoc_bit(struct ocfs2_super *osb, u64 bg_blkno; int status; - mlog_entry("blkno: %llu bit: %u\n", (unsigned long long)blkno, - (unsigned int)bit); + mlog(0, "blkno: %llu bit: %u\n", (unsigned long long)blkno, + (unsigned int)bit); alloc_di = (struct ocfs2_dinode *)alloc_bh->b_data; if ((bit + 1) > ocfs2_bits_per_group(&alloc_di->id2.i_chain)) { @@ -2869,7 +2846,7 @@ int ocfs2_test_inode_bit(struct ocfs2_super *osb, u64 blkno, int *res) struct inode *inode_alloc_inode; struct buffer_head *alloc_bh = NULL; - mlog_entry("blkno: %llu", (unsigned long long)blkno); + mlog(0, "blkno: %llu", (unsigned long long)blkno); status = ocfs2_get_suballoc_slot_bit(osb, blkno, &suballoc_slot, &group_blkno, &suballoc_bit); diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 36c423fb0635..21c4bfdfd739 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -441,8 +441,6 @@ static int ocfs2_init_global_system_inodes(struct ocfs2_super *osb) int status = 0; int i; - mlog_entry_void(); - new = ocfs2_iget(osb, osb->root_blkno, OCFS2_FI_FLAG_SYSFILE, 0); if (IS_ERR(new)) { status = PTR_ERR(new); @@ -488,8 +486,6 @@ static int ocfs2_init_local_system_inodes(struct ocfs2_super *osb) int status = 0; int i; - mlog_entry_void(); - for (i = OCFS2_LAST_GLOBAL_SYSTEM_INODE + 1; i < NUM_SYSTEM_INODES; i++) { @@ -517,8 +513,6 @@ static void ocfs2_release_system_inodes(struct ocfs2_super *osb) int i; struct inode *inode; - mlog_entry_void(); - for (i = 0; i < NUM_GLOBAL_SYSTEM_INODES; i++) { inode = osb->global_system_inodes[i]; if (inode) { @@ -1032,7 +1026,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) char nodestr[8]; struct ocfs2_blockcheck_stats stats; - mlog_entry("%p, %p, %i", sb, data, silent); + mlog(0, "%p, %p, %i", sb, data, silent); if (!ocfs2_parse_options(sb, data, &parsed_options, 0)) { status = -EINVAL; @@ -1320,8 +1314,8 @@ static int ocfs2_parse_options(struct super_block *sb, char *p; u32 tmp; - mlog_entry("remount: %d, options: \"%s\"\n", is_remount, - options ? options : "(none)"); + mlog(0, "remount: %d, options: \"%s\"\n", is_remount, + options ? options : "(none)"); mopt->commit_interval = 0; mopt->mount_opt = OCFS2_MOUNT_NOINTR; @@ -1629,8 +1623,6 @@ static int __init ocfs2_init(void) { int status; - mlog_entry_void(); - ocfs2_print_version(); status = init_ocfs2_uptodate_cache(); @@ -1681,8 +1673,6 @@ leave: static void __exit ocfs2_exit(void) { - mlog_entry_void(); - ocfs2_quota_shutdown(); if (ocfs2_wq) { @@ -1705,7 +1695,7 @@ static void __exit ocfs2_exit(void) static void ocfs2_put_super(struct super_block *sb) { - mlog_entry("(0x%p)\n", sb); + mlog(0, "(0x%p)\n", sb); ocfs2_sync_blockdev(sb); ocfs2_dismount_volume(sb, 0); @@ -1722,7 +1712,7 @@ static int ocfs2_statfs(struct dentry *dentry, struct kstatfs *buf) struct buffer_head *bh = NULL; struct inode *inode = NULL; - mlog_entry("(%p, %p)\n", dentry->d_sb, buf); + mlog(0, "(%p, %p)\n", dentry->d_sb, buf); osb = OCFS2_SB(dentry->d_sb); @@ -1889,8 +1879,6 @@ static int ocfs2_mount_volume(struct super_block *sb) int unlock_super = 0; struct ocfs2_super *osb = OCFS2_SB(sb); - mlog_entry_void(); - if (ocfs2_is_hard_readonly(osb)) goto leave; @@ -1945,7 +1933,7 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err) struct ocfs2_super *osb = NULL; char nodestr[8]; - mlog_entry("(0x%p)\n", sb); + mlog(0, "(0x%p)\n", sb); BUG_ON(!sb); osb = OCFS2_SB(sb); @@ -2097,8 +2085,6 @@ static int ocfs2_initialize_super(struct super_block *sb, struct ocfs2_super *osb; u64 total_blocks; - mlog_entry_void(); - osb = kzalloc(sizeof(struct ocfs2_super), GFP_KERNEL); if (!osb) { status = -ENOMEM; @@ -2403,8 +2389,6 @@ static int ocfs2_verify_volume(struct ocfs2_dinode *di, { int status = -EAGAIN; - mlog_entry_void(); - if (memcmp(di->i_signature, OCFS2_SUPER_BLOCK_SIGNATURE, strlen(OCFS2_SUPER_BLOCK_SIGNATURE)) == 0) { /* We have to do a raw check of the feature here */ @@ -2472,8 +2456,6 @@ static int ocfs2_check_volume(struct ocfs2_super *osb) * recover * ourselves. */ - mlog_entry_void(); - /* Init our journal object. */ status = ocfs2_journal_init(osb->journal, &dirty); if (status < 0) { @@ -2568,8 +2550,6 @@ finally: */ static void ocfs2_delete_osb(struct ocfs2_super *osb) { - mlog_entry_void(); - /* This function assumes that the caller has the main osb resource */ ocfs2_free_slot_info(osb); diff --git a/fs/ocfs2/symlink.c b/fs/ocfs2/symlink.c index 9975457c981f..8a81688c57df 100644 --- a/fs/ocfs2/symlink.c +++ b/fs/ocfs2/symlink.c @@ -62,8 +62,6 @@ static char *ocfs2_fast_symlink_getlink(struct inode *inode, char *link = NULL; struct ocfs2_dinode *fe; - mlog_entry_void(); - status = ocfs2_read_inode_block(inode, bh); if (status < 0) { mlog_errno(status); @@ -88,8 +86,6 @@ static int ocfs2_readlink(struct dentry *dentry, struct buffer_head *bh = NULL; struct inode *inode = dentry->d_inode; - mlog_entry_void(); - link = ocfs2_fast_symlink_getlink(inode, &bh); if (IS_ERR(link)) { ret = PTR_ERR(link); @@ -117,8 +113,6 @@ static void *ocfs2_fast_follow_link(struct dentry *dentry, struct inode *inode = dentry->d_inode; struct buffer_head *bh = NULL; - mlog_entry_void(); - BUG_ON(!ocfs2_inode_is_fast_symlink(inode)); target = ocfs2_fast_symlink_getlink(inode, &bh); if (IS_ERR(target)) { diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index 67cd43914641..81f98b7f7502 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c @@ -5538,7 +5538,7 @@ static int ocfs2_xattr_set_entry_bucket(struct inode *inode, int ret; struct ocfs2_xa_loc loc; - mlog_entry("Set xattr %s in xattr bucket\n", xi->xi_name); + mlog(0, "Set xattr %s in xattr bucket\n", xi->xi_name); ocfs2_init_xattr_bucket_xa_loc(&loc, xs->bucket, xs->not_found ? NULL : xs->here); @@ -5581,7 +5581,7 @@ static int ocfs2_xattr_set_entry_index_block(struct inode *inode, { int ret; - mlog_entry("Set xattr %s in xattr index block\n", xi->xi_name); + mlog(0, "Set xattr %s in xattr index block\n", xi->xi_name); ret = ocfs2_xattr_set_entry_bucket(inode, xi, xs, ctxt); if (!ret) -- cgit From c1e8d35ef5ffb393b94a192034b5e3541e005d75 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Mon, 7 Mar 2011 16:43:21 +0800 Subject: ocfs2: Remove EXIT from masklog. mlog_exit is used to record the exit status of a function. But because it is added in so many functions, if we enable it, the system logs get filled up quickly and cause too much I/O. So actually no one can open it for a production system or even for a test. This patch just try to remove it or change it. So: 1. if all the error paths already use mlog_errno, it is just removed. Otherwise, it will be replaced by mlog_errno. 2. if it is used to print some return value, it is replaced with mlog(0,...). mlog_exit_ptr is changed to mlog(0. All those mlog(0,...) will be replaced with trace events later. Signed-off-by: Tao Ma --- fs/ocfs2/alloc.c | 26 ++++------------ fs/ocfs2/aops.c | 19 +++--------- fs/ocfs2/buffer_head_io.c | 7 +++-- fs/ocfs2/cluster/heartbeat.c | 1 - fs/ocfs2/cluster/masklog.c | 3 +- fs/ocfs2/cluster/masklog.h | 44 --------------------------- fs/ocfs2/dcache.c | 3 +- fs/ocfs2/dir.c | 20 ++++++------- fs/ocfs2/dlm/dlmrecovery.c | 5 +--- fs/ocfs2/dlmglue.c | 71 ++++---------------------------------------- fs/ocfs2/export.c | 6 ++-- fs/ocfs2/extent_map.c | 1 - fs/ocfs2/file.c | 21 ++----------- fs/ocfs2/inode.c | 15 ++-------- fs/ocfs2/ioctl.c | 2 -- fs/ocfs2/journal.c | 19 ------------ fs/ocfs2/localalloc.c | 35 ++++++++++++---------- fs/ocfs2/mmap.c | 2 +- fs/ocfs2/namei.c | 47 +++++++++++++++++++---------- fs/ocfs2/quota_global.c | 17 ++++++----- fs/ocfs2/quota_local.c | 3 +- fs/ocfs2/resize.c | 6 ++-- fs/ocfs2/slot_map.c | 1 - fs/ocfs2/suballoc.c | 54 ++++++++++++++++++++++----------- fs/ocfs2/super.c | 37 +++++++++-------------- fs/ocfs2/symlink.c | 7 +++-- fs/ocfs2/xattr.c | 2 -- 27 files changed, 159 insertions(+), 315 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 47a6ce84e67f..80ffbe3dd32f 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c @@ -985,7 +985,7 @@ int ocfs2_num_free_extents(struct ocfs2_super *osb, bail: brelse(eb_bh); - mlog_exit(retval); + mlog(0, "retval = %d\n", retval); return retval; } @@ -1070,8 +1070,8 @@ bail: brelse(bhs[i]); bhs[i] = NULL; } + mlog_errno(status); } - mlog_exit(status); return status; } @@ -1326,7 +1326,6 @@ bail: kfree(new_eb_bhs); } - mlog_exit(status); return status; } @@ -1407,7 +1406,6 @@ static int ocfs2_shift_tree_depth(handle_t *handle, bail: brelse(new_eb_bh); - mlog_exit(status); return status; } @@ -1493,7 +1491,6 @@ static int ocfs2_find_branch_target(struct ocfs2_extent_tree *et, bail: brelse(bh); - mlog_exit(status); return status; } @@ -4552,7 +4549,7 @@ static int ocfs2_figure_insert_type(struct ocfs2_extent_tree *et, ocfs2_et_get_last_eb_blk(et), &bh); if (ret) { - mlog_exit(ret); + mlog_errno(ret); goto out; } eb = (struct ocfs2_extent_block *) bh->b_data; @@ -4716,7 +4713,6 @@ int ocfs2_insert_extent(handle_t *handle, bail: brelse(last_eb_bh); - mlog_exit(status); return status; } @@ -4818,7 +4814,6 @@ int ocfs2_add_clusters_in_btree(handle_t *handle, } leave: - mlog_exit(status); if (reason_ret) *reason_ret = reason; return status; @@ -5029,7 +5024,7 @@ int ocfs2_split_extent(handle_t *handle, ocfs2_et_get_last_eb_blk(et), &last_eb_bh); if (ret) { - mlog_exit(ret); + mlog_errno(ret); goto out; } @@ -5849,7 +5844,6 @@ int ocfs2_truncate_log_append(struct ocfs2_super *osb, osb->truncated_clusters += num_clusters; bail: - mlog_exit(status); return status; } @@ -5920,7 +5914,6 @@ static int ocfs2_replay_truncate_records(struct ocfs2_super *osb, osb->truncated_clusters = 0; bail: - mlog_exit(status); return status; } @@ -5995,7 +5988,6 @@ out_mutex: iput(data_alloc_inode); out: - mlog_exit(status); return status; } @@ -6023,8 +6015,6 @@ static void ocfs2_truncate_log_worker(struct work_struct *work) mlog_errno(status); else ocfs2_init_steal_slots(osb); - - mlog_exit(status); } #define OCFS2_TRUNCATE_LOG_FLUSH_INTERVAL (2 * HZ) @@ -6070,7 +6060,6 @@ static int ocfs2_get_truncate_log_info(struct ocfs2_super *osb, *tl_inode = inode; *tl_bh = bh; bail: - mlog_exit(status); return status; } @@ -6141,9 +6130,9 @@ bail: if (status < 0 && (*tl_copy)) { kfree(*tl_copy); *tl_copy = NULL; + mlog_errno(status); } - mlog_exit(status); return status; } @@ -6201,7 +6190,6 @@ int ocfs2_complete_truncate_log_recovery(struct ocfs2_super *osb, bail_up: mutex_unlock(&tl_inode->i_mutex); - mlog_exit(status); return status; } @@ -6221,8 +6209,6 @@ void ocfs2_truncate_log_shutdown(struct ocfs2_super *osb) brelse(osb->osb_tl_bh); iput(osb->osb_tl_inode); } - - mlog_exit_void(); } int ocfs2_truncate_log_init(struct ocfs2_super *osb) @@ -6246,7 +6232,6 @@ int ocfs2_truncate_log_init(struct ocfs2_super *osb) osb->osb_tl_bh = tl_bh; osb->osb_tl_inode = tl_inode; - mlog_exit(status); return status; } @@ -7112,7 +7097,6 @@ bail: ocfs2_free_path(path); - mlog_exit(status); return status; } diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 5dbfc9e45195..9551518be435 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -123,7 +123,6 @@ static int ocfs2_symlink_get_block(struct inode *inode, sector_t iblock, bail: brelse(bh); - mlog_exit(err); return err; } @@ -208,7 +207,6 @@ bail: if (err < 0) err = -EIO; - mlog_exit(err); return err; } @@ -323,7 +321,6 @@ out_inode_unlock: out: if (unlock) unlock_page(page); - mlog_exit(ret); return ret; } @@ -402,8 +399,6 @@ static int ocfs2_writepage(struct page *page, struct writeback_control *wbc) ret = block_write_full_page(page, ocfs2_get_block, wbc); - mlog_exit(ret); - return ret; } @@ -484,8 +479,6 @@ static sector_t ocfs2_bmap(struct address_space *mapping, sector_t block) bail: status = err ? 0 : p_blkno; - mlog_exit((int)status); - return status; } @@ -616,7 +609,6 @@ static ssize_t ocfs2_direct_IO(int rw, { struct file *file = iocb->ki_filp; struct inode *inode = file->f_path.dentry->d_inode->i_mapping->host; - int ret; /* * Fallback to buffered I/O if we see an inode without @@ -629,13 +621,10 @@ static ssize_t ocfs2_direct_IO(int rw, if (i_size_read(inode) <= offset) return 0; - ret = __blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, - iov, offset, nr_segs, - ocfs2_direct_IO_get_blocks, - ocfs2_dio_end_io, NULL, 0); - - mlog_exit(ret); - return ret; + return __blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, + iov, offset, nr_segs, + ocfs2_direct_IO_get_blocks, + ocfs2_dio_end_io, NULL, 0); } static void ocfs2_figure_cluster_boundaries(struct ocfs2_super *osb, diff --git a/fs/ocfs2/buffer_head_io.c b/fs/ocfs2/buffer_head_io.c index 024bd45b7a48..c23846dbfc8f 100644 --- a/fs/ocfs2/buffer_head_io.c +++ b/fs/ocfs2/buffer_head_io.c @@ -66,6 +66,7 @@ int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh, * can get modified during recovery even if read-only. */ if (ocfs2_is_hard_readonly(osb)) { ret = -EROFS; + mlog_errno(ret); goto out; } @@ -91,11 +92,11 @@ int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh, * uptodate. */ ret = -EIO; put_bh(bh); + mlog_errno(ret); } ocfs2_metadata_cache_io_unlock(ci); out: - mlog_exit(ret); return ret; } @@ -374,7 +375,6 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr, bail: - mlog_exit(status); return status; } @@ -413,6 +413,7 @@ int ocfs2_write_super_or_backup(struct ocfs2_super *osb, if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb)) { ret = -EROFS; + mlog_errno(ret); goto out; } @@ -432,9 +433,9 @@ int ocfs2_write_super_or_backup(struct ocfs2_super *osb, if (!buffer_uptodate(bh)) { ret = -EIO; put_bh(bh); + mlog_errno(ret); } out: - mlog_exit(ret); return ret; } diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index 929178ce17a2..fc9e96a03a6b 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c @@ -1679,7 +1679,6 @@ static int o2hb_populate_slot_data(struct o2hb_region *reg) } out: - mlog_exit(ret); return ret; } diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index bac64570c525..fdc302ddafe8 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -30,7 +30,7 @@ struct mlog_bits mlog_and_bits = MLOG_BITS_RHS(MLOG_INITIAL_AND_MASK); EXPORT_SYMBOL_GPL(mlog_and_bits); -struct mlog_bits mlog_not_bits = MLOG_BITS_RHS(MLOG_INITIAL_NOT_MASK); +struct mlog_bits mlog_not_bits = MLOG_BITS_RHS(0); EXPORT_SYMBOL_GPL(mlog_not_bits); static ssize_t mlog_mask_show(u64 mask, char *buf) @@ -80,7 +80,6 @@ struct mlog_attribute { } static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { - define_mask(EXIT), define_mask(TCP), define_mask(MSG), define_mask(SOCKET), diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index 6e20877436b9..51ee790c7678 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -82,7 +82,6 @@ /* bits that are frequently given and infrequently matched in the low word */ /* NOTE: If you add a flag, you need to also update masklog.c! */ -#define ML_EXIT 0x0000000000000002ULL /* func call exit */ #define ML_TCP 0x0000000000000004ULL /* net cluster/tcp.c */ #define ML_MSG 0x0000000000000008ULL /* net network messages */ #define ML_SOCKET 0x0000000000000010ULL /* net socket lifetime */ @@ -123,7 +122,6 @@ #define ML_KTHREAD 0x4000000000000000ULL /* kernel thread activity */ #define MLOG_INITIAL_AND_MASK (ML_ERROR|ML_NOTICE) -#define MLOG_INITIAL_NOT_MASK (ML_EXIT) #ifndef MLOG_MASK_PREFIX #define MLOG_MASK_PREFIX 0 #endif @@ -221,48 +219,6 @@ extern struct mlog_bits mlog_and_bits, mlog_not_bits; mlog(ML_ERROR, "status = %lld\n", (long long)_st); \ } while (0) -#if defined(CONFIG_OCFS2_DEBUG_MASKLOG) -/* - * We disable this for sparse. - */ -#if !defined(__CHECKER__) -#define mlog_exit(st) do { \ - if (__builtin_types_compatible_p(typeof(st), unsigned long)) \ - mlog(ML_EXIT, "EXIT: %lu\n", (unsigned long) (st)); \ - else if (__builtin_types_compatible_p(typeof(st), signed long)) \ - mlog(ML_EXIT, "EXIT: %ld\n", (signed long) (st)); \ - else if (__builtin_types_compatible_p(typeof(st), unsigned int) \ - || __builtin_types_compatible_p(typeof(st), unsigned short) \ - || __builtin_types_compatible_p(typeof(st), unsigned char)) \ - mlog(ML_EXIT, "EXIT: %u\n", (unsigned int) (st)); \ - else if (__builtin_types_compatible_p(typeof(st), signed int) \ - || __builtin_types_compatible_p(typeof(st), signed short) \ - || __builtin_types_compatible_p(typeof(st), signed char)) \ - mlog(ML_EXIT, "EXIT: %d\n", (signed int) (st)); \ - else if (__builtin_types_compatible_p(typeof(st), long long)) \ - mlog(ML_EXIT, "EXIT: %lld\n", (long long) (st)); \ - else \ - mlog(ML_EXIT, "EXIT: %llu\n", (unsigned long long) (st)); \ -} while (0) -#else -#define mlog_exit(st) do { \ - mlog(ML_EXIT, "EXIT: %lld\n", (long long) (st)); \ -} while (0) -#endif - -#define mlog_exit_ptr(ptr) do { \ - mlog(ML_EXIT, "EXIT: %p\n", ptr); \ -} while (0) - -#define mlog_exit_void() do { \ - mlog(ML_EXIT, "EXIT\n"); \ -} while (0) -#else -#define mlog_exit(...) do { } while (0) -#define mlog_exit_ptr(...) do { } while (0) -#define mlog_exit_void(...) do { } while (0) -#endif /* defined(CONFIG_OCFS2_DEBUG_MASKLOG) */ - #define mlog_bug_on_msg(cond, fmt, args...) do { \ if (cond) { \ mlog(ML_ERROR, "bug expression: " #cond "\n"); \ diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c index 67d17a45773b..c26551c25e8e 100644 --- a/fs/ocfs2/dcache.c +++ b/fs/ocfs2/dcache.c @@ -123,8 +123,7 @@ valid: ret = 1; bail: - mlog_exit(ret); - + mlog(0, "ret = %d\n", ret); return ret; } diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index 2c983f083f8a..2fc6c3673bea 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c @@ -400,7 +400,7 @@ static int inline ocfs2_search_dirblock(struct buffer_head *bh, } bail: - mlog_exit(ret); + mlog(0, "ret = %d\n", ret); return ret; } @@ -784,7 +784,7 @@ cleanup_and_exit: for (; ra_ptr < ra_max; ra_ptr++) brelse(bh_use[ra_ptr]); - mlog_exit_ptr(ret); + mlog(0, "ret = %p\n", ret); return ret; } @@ -1198,7 +1198,6 @@ static int __ocfs2_delete_entry(handle_t *handle, struct inode *dir, de = (struct ocfs2_dir_entry *)((char *)de + le16_to_cpu(de->rec_len)); } bail: - mlog_exit(status); return status; } @@ -1759,8 +1758,9 @@ int __ocfs2_add_entry(handle_t *handle, * from ever getting here. */ retval = -ENOSPC; bail: + if (retval) + mlog_errno(retval); - mlog_exit(retval); return retval; } @@ -2045,9 +2045,10 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) dirent, filldir, NULL); ocfs2_inode_unlock(inode, lock_level); + if (error) + mlog_errno(error); bail_nolock: - mlog_exit(error); return error; } @@ -2119,7 +2120,8 @@ int ocfs2_check_dir_for_entry(struct inode *dir, bail: ocfs2_free_dir_lookup_result(&lookup); - mlog_exit(ret); + if (ret) + mlog_errno(ret); return ret; } @@ -2372,7 +2374,6 @@ static int ocfs2_fill_new_dir_el(struct ocfs2_super *osb, bail: brelse(new_bh); - mlog_exit(status); return status; } @@ -3227,7 +3228,6 @@ static int ocfs2_do_extend_dir(struct super_block *sb, bail: if (did_quota && status < 0) dquot_free_space_nodirty(dir, ocfs2_clusters_to_bytes(sb, 1)); - mlog_exit(status); return status; } @@ -3426,7 +3426,6 @@ bail: brelse(new_bh); - mlog_exit(status); return status; } @@ -3573,8 +3572,9 @@ next: status = 0; bail: brelse(bh); + if (status) + mlog_errno(status); - mlog_exit(status); return status; } diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c index 6602b23c2ab3..f1beb6fc254d 100644 --- a/fs/ocfs2/dlm/dlmrecovery.c +++ b/fs/ocfs2/dlm/dlmrecovery.c @@ -727,7 +727,6 @@ static int dlm_remaster_locks(struct dlm_ctxt *dlm, u8 dead_node) if (destroy) dlm_destroy_recovery_area(dlm, dead_node); - mlog_exit(status); return status; } @@ -1496,9 +1495,9 @@ leave: kfree(buf); if (item) kfree(item); + mlog_errno(ret); } - mlog_exit(ret); return ret; } @@ -1567,7 +1566,6 @@ leave: dlm_lockres_put(res); } kfree(data); - mlog_exit(ret); } @@ -1986,7 +1984,6 @@ leave: dlm_lock_put(newlock); } - mlog_exit(ret); return ret; } diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index c2f3fa1c4722..7eb4b8da5cbc 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -406,8 +406,6 @@ static void ocfs2_build_lock_name(enum ocfs2_lock_type type, BUG_ON(len != (OCFS2_LOCK_ID_MAX_LEN - 1)); mlog(0, "built lock resource with name: %s\n", name); - - mlog_exit_void(); } static DEFINE_SPINLOCK(ocfs2_dlm_tracking_lock); @@ -752,7 +750,6 @@ void ocfs2_lock_res_free(struct ocfs2_lock_res *res) memset(&res->l_lksb, 0, sizeof(res->l_lksb)); res->l_flags = 0UL; - mlog_exit_void(); } static inline void ocfs2_inc_holders(struct ocfs2_lock_res *lockres, @@ -770,8 +767,6 @@ static inline void ocfs2_inc_holders(struct ocfs2_lock_res *lockres, default: BUG(); } - - mlog_exit_void(); } static inline void ocfs2_dec_holders(struct ocfs2_lock_res *lockres, @@ -791,7 +786,6 @@ static inline void ocfs2_dec_holders(struct ocfs2_lock_res *lockres, default: BUG(); } - mlog_exit_void(); } /* WARNING: This function lives in a world where the only three lock @@ -850,8 +844,6 @@ static inline void ocfs2_generic_handle_downconvert_action(struct ocfs2_lock_res lockres_clear_flags(lockres, OCFS2_LOCK_BLOCKED); } lockres_clear_flags(lockres, OCFS2_LOCK_BUSY); - - mlog_exit_void(); } static inline void ocfs2_generic_handle_convert_action(struct ocfs2_lock_res *lockres) @@ -877,8 +869,6 @@ static inline void ocfs2_generic_handle_convert_action(struct ocfs2_lock_res *lo lockres_or_flags(lockres, OCFS2_LOCK_UPCONVERT_FINISHING); lockres_clear_flags(lockres, OCFS2_LOCK_BUSY); - - mlog_exit_void(); } static inline void ocfs2_generic_handle_attach_action(struct ocfs2_lock_res *lockres) @@ -894,8 +884,6 @@ static inline void ocfs2_generic_handle_attach_action(struct ocfs2_lock_res *loc lockres->l_level = lockres->l_requested; lockres_or_flags(lockres, OCFS2_LOCK_ATTACHED); lockres_clear_flags(lockres, OCFS2_LOCK_BUSY); - - mlog_exit_void(); } static int ocfs2_generic_handle_bast(struct ocfs2_lock_res *lockres, @@ -923,8 +911,7 @@ static int ocfs2_generic_handle_bast(struct ocfs2_lock_res *lockres, if (needs_downconvert) lockres_or_flags(lockres, OCFS2_LOCK_BLOCKED); - - mlog_exit(needs_downconvert); + mlog(0, "needs_downconvert = %d\n", needs_downconvert); return needs_downconvert; } @@ -1145,7 +1132,6 @@ static void ocfs2_unlock_ast(struct ocfs2_dlm_lksb *lksb, int error) "unlock_action %d\n", error, lockres->l_name, lockres->l_unlock_action); spin_unlock_irqrestore(&lockres->l_lock, flags); - mlog_exit_void(); return; } @@ -1169,8 +1155,6 @@ static void ocfs2_unlock_ast(struct ocfs2_dlm_lksb *lksb, int error) lockres->l_unlock_action = OCFS2_UNLOCK_INVALID; wake_up(&lockres->l_event); spin_unlock_irqrestore(&lockres->l_lock, flags); - - mlog_exit_void(); } /* @@ -1226,7 +1210,6 @@ static inline void ocfs2_recover_from_dlm_error(struct ocfs2_lock_res *lockres, spin_unlock_irqrestore(&lockres->l_lock, flags); wake_up(&lockres->l_event); - mlog_exit_void(); } /* Note: If we detect another process working on the lock (i.e., @@ -1273,7 +1256,6 @@ static int ocfs2_lock_create(struct ocfs2_super *osb, mlog(0, "lock %s, return from ocfs2_dlm_lock\n", lockres->l_name); bail: - mlog_exit(ret); return ret; } @@ -1561,7 +1543,6 @@ out: caller_ip); } #endif - mlog_exit(ret); return ret; } @@ -1591,7 +1572,6 @@ static void __ocfs2_cluster_unlock(struct ocfs2_super *osb, if (lockres->l_lockdep_map.key != NULL) rwsem_release(&lockres->l_lockdep_map, 1, caller_ip); #endif - mlog_exit_void(); } static int ocfs2_create_new_lock(struct ocfs2_super *osb, @@ -1658,7 +1638,6 @@ int ocfs2_create_new_inode_locks(struct inode *inode) } bail: - mlog_exit(ret); return ret; } @@ -1674,10 +1653,8 @@ int ocfs2_rw_lock(struct inode *inode, int write) (unsigned long long)OCFS2_I(inode)->ip_blkno, write ? "EXMODE" : "PRMODE"); - if (ocfs2_mount_local(osb)) { - mlog_exit(0); + if (ocfs2_mount_local(osb)) return 0; - } lockres = &OCFS2_I(inode)->ip_rw_lockres; @@ -1688,7 +1665,6 @@ int ocfs2_rw_lock(struct inode *inode, int write) if (status < 0) mlog_errno(status); - mlog_exit(status); return status; } @@ -1704,8 +1680,6 @@ void ocfs2_rw_unlock(struct inode *inode, int write) if (!ocfs2_mount_local(osb)) ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres, level); - - mlog_exit_void(); } /* @@ -1733,7 +1707,6 @@ int ocfs2_open_lock(struct inode *inode) mlog_errno(status); out: - mlog_exit(status); return status; } @@ -1766,7 +1739,6 @@ int ocfs2_try_open_lock(struct inode *inode, int write) level, DLM_LKF_NOQUEUE, 0); out: - mlog_exit(status); return status; } @@ -1792,7 +1764,7 @@ void ocfs2_open_unlock(struct inode *inode) DLM_LOCK_EX); out: - mlog_exit_void(); + return; } static int ocfs2_flock_handle_signal(struct ocfs2_lock_res *lockres, @@ -2028,8 +2000,6 @@ static void ocfs2_downconvert_on_unlock(struct ocfs2_super *osb, if (kick) ocfs2_wake_downconvert_thread(osb); - - mlog_exit_void(); } #define OCFS2_SEC_BITS 34 @@ -2089,8 +2059,6 @@ static void __ocfs2_stuff_meta_lvb(struct inode *inode) out: mlog_meta_lvb(0, lockres); - - mlog_exit_void(); } static void ocfs2_unpack_timespec(struct timespec *spec, @@ -2136,8 +2104,6 @@ static void ocfs2_refresh_inode_from_lvb(struct inode *inode) ocfs2_unpack_timespec(&inode->i_ctime, be64_to_cpu(lvb->lvb_ictime_packed)); spin_unlock(&oi->ip_lock); - - mlog_exit_void(); } static inline int ocfs2_meta_lvb_is_trustable(struct inode *inode, @@ -2184,7 +2150,7 @@ refresh_check: status = 1; bail: - mlog_exit(status); + mlog(0, "status %d\n", status); return status; } @@ -2202,8 +2168,6 @@ static inline void ocfs2_complete_lock_res_refresh(struct ocfs2_lock_res *lockre spin_unlock_irqrestore(&lockres->l_lock, flags); wake_up(&lockres->l_event); - - mlog_exit_void(); } /* may or may not return a bh if it went to disk. */ @@ -2284,7 +2248,6 @@ static int ocfs2_inode_lock_update(struct inode *inode, bail_refresh: ocfs2_complete_lock_res_refresh(lockres, status); bail: - mlog_exit(status); return status; } @@ -2419,7 +2382,6 @@ bail: if (local_bh) brelse(local_bh); - mlog_exit(status); return status; } @@ -2496,7 +2458,6 @@ int ocfs2_inode_lock_atime(struct inode *inode, } else *level = 0; - mlog_exit(ret); return ret; } @@ -2514,8 +2475,6 @@ void ocfs2_inode_unlock(struct inode *inode, if (!ocfs2_is_hard_readonly(OCFS2_SB(inode->i_sb)) && !ocfs2_mount_local(osb)) ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres, level); - - mlog_exit_void(); } int ocfs2_orphan_scan_lock(struct ocfs2_super *osb, u32 *seqno) @@ -2597,7 +2556,6 @@ int ocfs2_super_lock(struct ocfs2_super *osb, ocfs2_track_lock_refresh(lockres); } bail: - mlog_exit(status); return status; } @@ -3057,7 +3015,6 @@ bail: kthread_stop(osb->dc_task); } - mlog_exit(status); return status; } @@ -3086,8 +3043,6 @@ void ocfs2_dlm_shutdown(struct ocfs2_super *osb, osb->cconn = NULL; ocfs2_dlm_shutdown_debug(osb); - - mlog_exit_void(); } static int ocfs2_drop_lock(struct ocfs2_super *osb, @@ -3169,7 +3124,6 @@ static int ocfs2_drop_lock(struct ocfs2_super *osb, ocfs2_wait_on_busy_lock(lockres); out: - mlog_exit(0); return 0; } @@ -3251,7 +3205,6 @@ int ocfs2_drop_inode_locks(struct inode *inode) if (err < 0 && !status) status = err; - mlog_exit(status); return status; } @@ -3314,7 +3267,6 @@ static int ocfs2_downconvert_lock(struct ocfs2_super *osb, ret = 0; bail: - mlog_exit(ret); return ret; } @@ -3362,7 +3314,6 @@ static int ocfs2_cancel_convert(struct ocfs2_super *osb, mlog(ML_BASTS, "lockres %s\n", lockres->l_name); - mlog_exit(ret); return ret; } @@ -3552,14 +3503,14 @@ downconvert: gen); leave: - mlog_exit(ret); + if (ret) + mlog_errno(ret); return ret; leave_requeue: spin_unlock_irqrestore(&lockres->l_lock, flags); ctl->requeue = 1; - mlog_exit(0); return 0; } @@ -3800,8 +3751,6 @@ static void ocfs2_set_qinfo_lvb(struct ocfs2_lock_res *lockres) lvb->lvb_blocks = cpu_to_be32(oinfo->dqi_gi.dqi_blocks); lvb->lvb_free_blk = cpu_to_be32(oinfo->dqi_gi.dqi_free_blk); lvb->lvb_free_entry = cpu_to_be32(oinfo->dqi_gi.dqi_free_entry); - - mlog_exit_void(); } void ocfs2_qinfo_unlock(struct ocfs2_mem_dqinfo *oinfo, int ex) @@ -3812,7 +3761,6 @@ void ocfs2_qinfo_unlock(struct ocfs2_mem_dqinfo *oinfo, int ex) if (!ocfs2_is_hard_readonly(osb) && !ocfs2_mount_local(osb)) ocfs2_cluster_unlock(osb, lockres, level); - mlog_exit_void(); } static int ocfs2_refresh_qinfo(struct ocfs2_mem_dqinfo *oinfo) @@ -3889,7 +3837,6 @@ int ocfs2_qinfo_lock(struct ocfs2_mem_dqinfo *oinfo, int ex) ocfs2_qinfo_unlock(oinfo, ex); ocfs2_complete_lock_res_refresh(lockres, status); bail: - mlog_exit(status); return status; } @@ -3968,8 +3915,6 @@ unqueue: if (ctl.unblock_action != UNBLOCK_CONTINUE && lockres->l_ops->post_unlock) lockres->l_ops->post_unlock(osb, lockres); - - mlog_exit_void(); } static void ocfs2_schedule_blocked_lock(struct ocfs2_super *osb, @@ -3995,8 +3940,6 @@ static void ocfs2_schedule_blocked_lock(struct ocfs2_super *osb, osb->blocked_lock_count++; } spin_unlock(&osb->dc_task_lock); - - mlog_exit_void(); } static void ocfs2_downconvert_thread_do_work(struct ocfs2_super *osb) @@ -4027,8 +3970,6 @@ static void ocfs2_downconvert_thread_do_work(struct ocfs2_super *osb) spin_lock(&osb->dc_task_lock); } spin_unlock(&osb->dc_task_lock); - - mlog_exit_void(); } static int ocfs2_downconvert_thread_lists_empty(struct ocfs2_super *osb) diff --git a/fs/ocfs2/export.c b/fs/ocfs2/export.c index b90c751ba938..96d7ed7f8305 100644 --- a/fs/ocfs2/export.c +++ b/fs/ocfs2/export.c @@ -141,7 +141,7 @@ check_gen: mlog_errno(PTR_ERR(result)); bail: - mlog_exit_ptr(result); + mlog(0, "result = %p\n", result); return result; } @@ -178,7 +178,7 @@ bail_unlock: ocfs2_inode_unlock(dir, 0); bail: - mlog_exit_ptr(parent); + mlog(0, "parent %p\n", parent); return parent; } @@ -243,7 +243,7 @@ static int ocfs2_encode_fh(struct dentry *dentry, u32 *fh_in, int *max_len, *max_len = len; bail: - mlog_exit(type); + mlog(0, "type = %d\n", type); return type; } diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c index ed9916a9a271..7d74d176706a 100644 --- a/fs/ocfs2/extent_map.c +++ b/fs/ocfs2/extent_map.c @@ -897,7 +897,6 @@ int ocfs2_read_virt_blocks(struct inode *inode, u64 v_block, int nr, } out: - mlog_exit(rc); return rc; } diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 71375d7b7bbe..1e1a93aa0526 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -135,7 +135,6 @@ static int ocfs2_file_open(struct inode *inode, struct file *file) } leave: - mlog_exit(status); return status; } @@ -154,8 +153,6 @@ static int ocfs2_file_release(struct inode *inode, struct file *file) ocfs2_free_file_private(inode, file); - mlog_exit(0); - return 0; } @@ -195,7 +192,8 @@ static int ocfs2_sync_file(struct file *file, int datasync) err = jbd2_journal_force_commit(journal); bail: - mlog_exit(err); + if (err) + mlog_errno(err); return (err < 0) ? -EIO : 0; } @@ -278,7 +276,6 @@ int ocfs2_update_inode_atime(struct inode *inode, out_commit: ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle); out: - mlog_exit(ret); return ret; } @@ -300,7 +297,6 @@ static int ocfs2_set_inode_size(handle_t *handle, } bail: - mlog_exit(status); return status; } @@ -424,8 +420,6 @@ static int ocfs2_orphan_for_truncate(struct ocfs2_super *osb, out_commit: ocfs2_commit_trans(osb, handle); out: - - mlog_exit(status); return status; } @@ -520,7 +514,6 @@ bail: if (!status && OCFS2_I(inode)->ip_clusters == 0) status = ocfs2_try_remove_refcount_tree(inode, di_bh); - mlog_exit(status); return status; } @@ -713,7 +706,6 @@ leave: brelse(bh); bh = NULL; - mlog_exit(status); return status; } @@ -1269,7 +1261,6 @@ bail: mlog_errno(status); } - mlog_exit(status); return status; } @@ -1295,8 +1286,6 @@ int ocfs2_getattr(struct vfsmount *mnt, stat->blksize = osb->s_clustersize; bail: - mlog_exit(err); - return err; } @@ -1318,7 +1307,6 @@ int ocfs2_permission(struct inode *inode, int mask, unsigned int flags) ocfs2_inode_unlock(inode, 0); out: - mlog_exit(ret); return ret; } @@ -1359,7 +1347,6 @@ static int __ocfs2_write_remove_suid(struct inode *inode, out_trans: ocfs2_commit_trans(osb, handle); out: - mlog_exit(ret); return ret; } @@ -2393,7 +2380,6 @@ out_sems: if (written) ret = written; - mlog_exit(ret); return ret; } @@ -2476,7 +2462,6 @@ static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe, balance_dirty_pages_ratelimited_nr(mapping, nr_pages); } - mlog_exit(ret); return ret; } @@ -2507,7 +2492,6 @@ static ssize_t ocfs2_file_splice_read(struct file *in, ret = generic_file_splice_read(in, ppos, pipe, len, flags); bail: - mlog_exit(ret); return ret; } @@ -2588,7 +2572,6 @@ bail: } if (rw_level != -1) ocfs2_rw_unlock(inode, rw_level); - mlog_exit(ret); return ret; } diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index 16ee8e96f731..a96e56f12728 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c @@ -172,7 +172,7 @@ bail: if (!IS_ERR(inode)) { mlog(0, "returning inode with number %llu\n", (unsigned long long)OCFS2_I(inode)->ip_blkno); - mlog_exit_ptr(inode); + mlog(0, "inode %p\n", inode); } return inode; @@ -203,7 +203,6 @@ static int ocfs2_find_actor(struct inode *inode, void *opaque) ret = 1; bail: - mlog_exit(ret); return ret; } @@ -235,7 +234,6 @@ static int ocfs2_init_locked_inode(struct inode *inode, void *opaque) lockdep_set_class(&OCFS2_I(inode)->ip_alloc_sem, &ocfs2_file_ip_alloc_sem_key); - mlog_exit(0); return 0; } @@ -381,7 +379,6 @@ void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, if (S_ISDIR(inode->i_mode)) ocfs2_resv_set_type(&OCFS2_I(inode)->ip_la_data_resv, OCFS2_RESV_FLAG_DIR); - mlog_exit_void(); } static int ocfs2_read_locked_inode(struct inode *inode, @@ -534,7 +531,6 @@ bail: if (args && bh) brelse(bh); - mlog_exit(status); return status; } @@ -598,7 +594,6 @@ static int ocfs2_truncate_for_delete(struct ocfs2_super *osb, out: if (handle) ocfs2_commit_trans(osb, handle); - mlog_exit(status); return status; } @@ -1078,7 +1073,7 @@ bail_unlock_nfs_sync: bail_unblock: ocfs2_unblock_signals(&oldset); bail: - mlog_exit_void(); + return; } static void ocfs2_clear_inode(struct inode *inode) @@ -1177,8 +1172,6 @@ static void ocfs2_clear_inode(struct inode *inode) */ jbd2_journal_release_jbd_inode(OCFS2_SB(inode->i_sb)->journal->j_journal, &oi->ip_jinode); - - mlog_exit_void(); } void ocfs2_evict_inode(struct inode *inode) @@ -1208,7 +1201,6 @@ int ocfs2_drop_inode(struct inode *inode) else res = generic_drop_inode(inode); - mlog_exit_void(); return res; } @@ -1248,8 +1240,6 @@ int ocfs2_inode_revalidate(struct dentry *dentry) } ocfs2_inode_unlock(inode, 0); bail: - mlog_exit(status); - return status; } @@ -1296,7 +1286,6 @@ int ocfs2_mark_inode_dirty(handle_t *handle, ocfs2_journal_dirty(handle, bh); leave: - mlog_exit(status); return status; } diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c index 7a4868196152..b4f51e94c8f5 100644 --- a/fs/ocfs2/ioctl.c +++ b/fs/ocfs2/ioctl.c @@ -59,7 +59,6 @@ static int ocfs2_get_inode_attr(struct inode *inode, unsigned *flags) *flags = OCFS2_I(inode)->ip_attr; ocfs2_inode_unlock(inode, 0); - mlog_exit(status); return status; } @@ -125,7 +124,6 @@ bail: brelse(bh); - mlog_exit(status); return status; } diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index 7378277b17a4..956509167bf5 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c @@ -335,7 +335,6 @@ static int ocfs2_commit_cache(struct ocfs2_super *osb) ocfs2_wake_downconvert_thread(osb); wake_up(&journal->j_checkpointed); finally: - mlog_exit(status); return status; } @@ -450,8 +449,6 @@ int ocfs2_extend_trans(handle_t *handle, int nblocks) status = 0; bail: - - mlog_exit(status); return status; } @@ -665,7 +662,6 @@ static int __ocfs2_journal_access(handle_t *handle, mlog(ML_ERROR, "Error %d getting %d access to buffer!\n", status, type); - mlog_exit(status); return status; } @@ -739,8 +735,6 @@ void ocfs2_journal_dirty(handle_t *handle, struct buffer_head *bh) status = jbd2_journal_dirty_metadata(handle, bh); BUG_ON(status); - - mlog_exit_void(); } #define OCFS2_DEFAULT_COMMIT_INTERVAL (HZ * JBD2_DEFAULT_MAX_COMMIT_AGE) @@ -854,7 +848,6 @@ done: } } - mlog_exit(status); return status; } @@ -899,7 +892,6 @@ static int ocfs2_journal_toggle_dirty(struct ocfs2_super *osb, if (status < 0) mlog_errno(status); - mlog_exit(status); return status; } @@ -989,7 +981,6 @@ void ocfs2_journal_shutdown(struct ocfs2_super *osb) done: if (inode) iput(inode); - mlog_exit_void(); } static void ocfs2_clear_journal_error(struct super_block *sb, @@ -1048,7 +1039,6 @@ int ocfs2_journal_load(struct ocfs2_journal *journal, int local, int replayed) osb->commit_task = NULL; done: - mlog_exit(status); return status; } @@ -1072,7 +1062,6 @@ int ocfs2_journal_wipe(struct ocfs2_journal *journal, int full) mlog_errno(status); bail: - mlog_exit(status); return status; } @@ -1146,7 +1135,6 @@ static int ocfs2_force_read_journal(struct inode *inode) bail: for(i = 0; i < CONCURRENT_JOURNAL_FILL; i++) brelse(bhs[i]); - mlog_exit(status); return status; } @@ -1236,7 +1224,6 @@ void ocfs2_complete_recovery(struct work_struct *work) } mlog(0, "Recovery completion\n"); - mlog_exit_void(); } /* NOTE: This function always eats your references to la_dinode and @@ -1432,7 +1419,6 @@ bail: if (rm_quota) kfree(rm_quota); - mlog_exit(status); /* no one is callint kthread_stop() for us so the kthread() api * requires that we call do_exit(). And it isn't exported, but * complete_and_exit() seems to be a minimal wrapper around it. */ @@ -1469,8 +1455,6 @@ void ocfs2_recovery_thread(struct ocfs2_super *osb, int node_num) out: mutex_unlock(&osb->recovery_lock); wake_up(&osb->recovery_event); - - mlog_exit_void(); } static int ocfs2_read_journal_inode(struct ocfs2_super *osb, @@ -1646,7 +1630,6 @@ done: brelse(bh); - mlog_exit(status); return status; } @@ -1716,7 +1699,6 @@ static int ocfs2_recover_node(struct ocfs2_super *osb, status = 0; done: - mlog_exit(status); return status; } @@ -1826,7 +1808,6 @@ int ocfs2_mark_dead_nodes(struct ocfs2_super *osb) status = 0; bail: - mlog_exit(status); return status; } diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c index 5f08c703f354..36636e1c84e7 100644 --- a/fs/ocfs2/localalloc.c +++ b/fs/ocfs2/localalloc.c @@ -364,7 +364,8 @@ bail: mlog(0, "Local alloc window bits = %d\n", osb->local_alloc_bits); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -478,8 +479,6 @@ out: if (alloc_copy) kfree(alloc_copy); - - mlog_exit_void(); } /* @@ -548,7 +547,8 @@ bail: iput(inode); } - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -614,7 +614,8 @@ out_mutex: out: if (!status) ocfs2_init_steal_slots(osb); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -724,7 +725,8 @@ bail: mlog(0, "bits=%d, slot=%d, ret=%d\n", bits_wanted, osb->slot_num, status); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -779,7 +781,8 @@ int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb, ocfs2_journal_dirty(handle, osb->local_alloc_bh); bail: - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -794,7 +797,7 @@ static u32 ocfs2_local_alloc_count_bits(struct ocfs2_dinode *alloc) for (i = 0; i < le16_to_cpu(la->la_size); i++) count += hweight8(buffer[i]); - mlog_exit(count); + mlog(0, "count %u\n", count); return count; } @@ -884,7 +887,7 @@ bail: if (local_resv) ocfs2_resv_discard(resmap, resv); - mlog_exit(bitoff); + mlog(0, "bitoff %d\n", bitoff); return bitoff; } @@ -898,8 +901,6 @@ static void ocfs2_clear_local_alloc(struct ocfs2_dinode *alloc) la->la_bm_off = 0; for(i = 0; i < le16_to_cpu(la->la_size); i++) la->la_bitmap[i] = 0; - - mlog_exit_void(); } #if 0 @@ -995,7 +996,8 @@ static int ocfs2_sync_local_to_main(struct ocfs2_super *osb, } bail: - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -1120,7 +1122,8 @@ bail: *ac = NULL; } - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -1212,7 +1215,8 @@ retry_enospc: mlog(0, "window bits = %u\n", le32_to_cpu(alloc->id1.bitmap1.i_total)); bail: - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -1308,7 +1312,8 @@ bail: if (ac) ocfs2_free_alloc_context(ac); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } diff --git a/fs/ocfs2/mmap.c b/fs/ocfs2/mmap.c index 87438e178e11..49730b51ae45 100644 --- a/fs/ocfs2/mmap.c +++ b/fs/ocfs2/mmap.c @@ -55,7 +55,7 @@ static int ocfs2_fault(struct vm_area_struct *area, struct vm_fault *vmf) ret = filemap_fault(area, vmf); ocfs2_unblock_signals(&oldset); - mlog_exit_ptr(vmf->page); + mlog(0, "%p\n", vmf->page); return ret; } diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index fdf5c0b75caa..8a13226eb1a2 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c @@ -182,7 +182,7 @@ bail_unlock: bail: - mlog_exit_ptr(ret); + mlog(0, "%p\n", ret); return ret; } @@ -466,7 +466,8 @@ leave: iput(inode); } - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -577,7 +578,8 @@ leave: } } - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -618,7 +620,8 @@ static int ocfs2_mkdir(struct inode *dir, mlog(0, "(0x%p, 0x%p, %d, '%.*s')\n", dir, dentry, mode, dentry->d_name.len, dentry->d_name.name); ret = ocfs2_mknod(dir, dentry, mode | S_IFDIR, 0); - mlog_exit(ret); + if (ret) + mlog_errno(ret); return ret; } @@ -633,7 +636,8 @@ static int ocfs2_create(struct inode *dir, mlog(0, "(0x%p, 0x%p, %d, '%.*s')\n", dir, dentry, mode, dentry->d_name.len, dentry->d_name.name); ret = ocfs2_mknod(dir, dentry, mode | S_IFREG, 0); - mlog_exit(ret); + if (ret) + mlog_errno(ret); return ret; } @@ -757,7 +761,8 @@ out: ocfs2_free_dir_lookup_result(&lookup); - mlog_exit(err); + if (err) + mlog_errno(err); return err; } @@ -954,7 +959,8 @@ leave: ocfs2_free_dir_lookup_result(&orphan_insert); ocfs2_free_dir_lookup_result(&lookup); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -1025,7 +1031,8 @@ static int ocfs2_double_lock(struct ocfs2_super *osb, } bail: - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -1476,7 +1483,8 @@ bail: brelse(old_dir_bh); brelse(new_dir_bh); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -1579,7 +1587,8 @@ bail: kfree(bhs); } - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -1835,7 +1844,8 @@ bail: iput(inode); } - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -1865,7 +1875,8 @@ static int ocfs2_blkno_stringify(u64 blkno, char *name) status = 0; bail: - mlog_exit(status); + if (status < 0) + mlog_errno(status); return status; } @@ -1978,7 +1989,8 @@ out: iput(orphan_dir_inode); } - mlog_exit(ret); + if (ret) + mlog_errno(ret); return ret; } @@ -2060,7 +2072,8 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb, leave: brelse(orphan_dir_bh); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -2120,7 +2133,8 @@ int ocfs2_orphan_del(struct ocfs2_super *osb, leave: ocfs2_free_dir_lookup_result(&lookup); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -2472,7 +2486,8 @@ leave: ocfs2_free_dir_lookup_result(&lookup); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c index 33397bd7e1bc..10a49e8a5f03 100644 --- a/fs/ocfs2/quota_global.c +++ b/fs/ocfs2/quota_global.c @@ -402,7 +402,8 @@ int ocfs2_global_read_info(struct super_block *sb, int type) msecs_to_jiffies(oinfo->dqi_syncms)); out_err: - mlog_exit(status); + if (status) + mlog_errno(status); return status; out_unlock: ocfs2_unlock_global_qf(oinfo, 0); @@ -621,7 +622,6 @@ static int ocfs2_sync_dquot_helper(struct dquot *dquot, unsigned long type) out_ilock: ocfs2_unlock_global_qf(oinfo, 1); out: - mlog_exit(status); return status; } @@ -660,7 +660,6 @@ static int ocfs2_write_dquot(struct dquot *dquot) mutex_unlock(&sb_dqopt(dquot->dq_sb)->dqio_mutex); ocfs2_commit_trans(osb, handle); out: - mlog_exit(status); return status; } @@ -722,7 +721,8 @@ out_ilock: ocfs2_unlock_global_qf(oinfo, 1); out: mutex_unlock(&dquot->dq_lock); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -809,7 +809,8 @@ out_dq: set_bit(DQ_ACTIVE_B, &dquot->dq_flags); out: mutex_unlock(&dquot->dq_lock); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -866,7 +867,8 @@ out_dlock: out_ilock: ocfs2_unlock_global_qf(oinfo, 1); out: - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -891,7 +893,8 @@ static int ocfs2_write_info(struct super_block *sb, int type) out_ilock: ocfs2_unlock_global_qf(oinfo, 1); out: - mlog_exit(status); + if (status) + mlog_errno(status); return status; } diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c index a71d68d88667..88ec4516637b 100644 --- a/fs/ocfs2/quota_local.c +++ b/fs/ocfs2/quota_local.c @@ -575,7 +575,8 @@ out_put_bh: } if (status < 0) free_recovery_list(&(rec->r_list[type])); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } diff --git a/fs/ocfs2/resize.c b/fs/ocfs2/resize.c index e4a50e3fcb80..76b37909a4a1 100644 --- a/fs/ocfs2/resize.c +++ b/fs/ocfs2/resize.c @@ -82,7 +82,6 @@ static u16 ocfs2_calc_new_backup_super(struct inode *inode, backups++; } - mlog_exit_void(); return backups; } @@ -176,7 +175,8 @@ out_rollback: le16_add_cpu(&group->bg_free_bits_count, -1 * num_bits); } out: - mlog_exit(ret); + if (ret) + mlog_errno(ret); return ret; } @@ -375,7 +375,6 @@ out_mutex: iput(main_bm_inode); out: - mlog_exit_void(); return ret; } @@ -585,6 +584,5 @@ out_mutex: iput(main_bm_inode); out: - mlog_exit_void(); return ret; } diff --git a/fs/ocfs2/slot_map.c b/fs/ocfs2/slot_map.c index a6016e6b3ca2..93b449ed82f9 100644 --- a/fs/ocfs2/slot_map.c +++ b/fs/ocfs2/slot_map.c @@ -510,7 +510,6 @@ int ocfs2_find_slot(struct ocfs2_super *osb) mlog_errno(status); bail: - mlog_exit(status); return status; } diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index dd618496c2c6..2d722f1fbaa0 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -434,7 +434,8 @@ static int ocfs2_block_group_fill(handle_t *handle, * allocation time. */ bail: - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -792,7 +793,8 @@ bail: brelse(bg_bh); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -884,7 +886,8 @@ static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb, bail: brelse(bh); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -1046,7 +1049,8 @@ bail: *ac = NULL; } - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -1146,7 +1150,8 @@ bail: *ac = NULL; } - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -1221,7 +1226,8 @@ bail: *ac = NULL; } - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -1384,7 +1390,8 @@ static inline int ocfs2_block_group_set_bits(handle_t *handle, ocfs2_journal_dirty(handle, group_bh); bail: - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -1474,7 +1481,8 @@ out_rollback: prev_bg->bg_next_group = cpu_to_le64(prev_bg_ptr); } - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -1860,7 +1868,8 @@ bail: brelse(group_bh); brelse(prev_group_bh); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -1972,7 +1981,8 @@ set_hint: } bail: - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -2009,7 +2019,8 @@ int ocfs2_claim_metadata(handle_t *handle, *num_bits = res.sr_bits; status = 0; bail: - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -2216,7 +2227,8 @@ int ocfs2_claim_new_inode(handle_t *handle, ocfs2_save_inode_ac_group(dir, ac); status = 0; bail: - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -2347,7 +2359,8 @@ int __ocfs2_claim_clusters(handle_t *handle, ac->ac_bits_given += *num_clusters; bail: - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -2491,7 +2504,8 @@ static int _ocfs2_free_suballoc_bits(handle_t *handle, bail: brelse(group_bh); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -2563,7 +2577,8 @@ static int _ocfs2_free_clusters(handle_t *handle, num_clusters); out: - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -2770,7 +2785,8 @@ static int ocfs2_get_suballoc_slot_bit(struct ocfs2_super *osb, u64 blkno, bail: brelse(inode_bh); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -2821,7 +2837,8 @@ static int ocfs2_test_suballoc_bit(struct ocfs2_super *osb, bail: brelse(group_bh); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -2887,6 +2904,7 @@ int ocfs2_test_inode_bit(struct ocfs2_super *osb, u64 blkno, int *res) iput(inode_alloc_inode); brelse(alloc_bh); bail: - mlog_exit(status); + if (status) + mlog_errno(status); return status; } diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 21c4bfdfd739..b21b702c5603 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -476,7 +476,8 @@ static int ocfs2_init_global_system_inodes(struct ocfs2_super *osb) } bail: - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -504,7 +505,8 @@ static int ocfs2_init_local_system_inodes(struct ocfs2_super *osb) } bail: - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -534,7 +536,7 @@ static void ocfs2_release_system_inodes(struct ocfs2_super *osb) } if (!osb->local_system_inodes) - goto out; + return; for (i = 0; i < NUM_LOCAL_SYSTEM_INODES * osb->max_slots; i++) { if (osb->local_system_inodes[i]) { @@ -545,9 +547,6 @@ static void ocfs2_release_system_inodes(struct ocfs2_super *osb) kfree(osb->local_system_inodes); osb->local_system_inodes = NULL; - -out: - mlog_exit(0); } /* We're allocating fs objects, use GFP_NOFS */ @@ -1202,7 +1201,6 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) mlog_errno(status); atomic_set(&osb->vol_state, VOLUME_DISABLED); wake_up(&osb->osb_mount_event); - mlog_exit(status); return status; } } @@ -1216,7 +1214,6 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) /* Start this when the mount is almost sure of being successful */ ocfs2_orphan_scan_start(osb); - mlog_exit(status); return status; read_super_error: @@ -1231,7 +1228,8 @@ read_super_error: ocfs2_dismount_volume(sb, 1); } - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -1532,7 +1530,6 @@ static int ocfs2_parse_options(struct super_block *sb, status = 1; bail: - mlog_exit(status); return status; } @@ -1661,10 +1658,9 @@ leave: ocfs2_quota_shutdown(); ocfs2_free_mem_caches(); exit_ocfs2_uptodate_cache(); + mlog_errno(status); } - mlog_exit(status); - if (status >= 0) { return register_filesystem(&ocfs2_fs_type); } else @@ -1689,8 +1685,6 @@ static void __exit ocfs2_exit(void) unregister_filesystem(&ocfs2_fs_type); exit_ocfs2_uptodate_cache(); - - mlog_exit_void(); } static void ocfs2_put_super(struct super_block *sb) @@ -1699,8 +1693,6 @@ static void ocfs2_put_super(struct super_block *sb) ocfs2_sync_blockdev(sb); ocfs2_dismount_volume(sb, 0); - - mlog_exit_void(); } static int ocfs2_statfs(struct dentry *dentry, struct kstatfs *buf) @@ -1759,7 +1751,8 @@ bail: if (inode) iput(inode); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -1923,7 +1916,6 @@ leave: if (unlock_super) ocfs2_super_unlock(osb, 1); - mlog_exit(status); return status; } @@ -2373,7 +2365,6 @@ static int ocfs2_initialize_super(struct super_block *sb, } bail: - mlog_exit(status); return status; } @@ -2443,7 +2434,8 @@ static int ocfs2_verify_volume(struct ocfs2_dinode *di, } out: - mlog_exit(status); + if (status && status != -EAGAIN) + mlog_errno(status); return status; } @@ -2538,7 +2530,8 @@ finally: if (local_alloc) kfree(local_alloc); - mlog_exit(status); + if (status) + mlog_errno(status); return status; } @@ -2567,8 +2560,6 @@ static void ocfs2_delete_osb(struct ocfs2_super *osb) kfree(osb->uuid_str); ocfs2_put_dlm_debug(osb->osb_dlm_debug); memset(osb, 0, sizeof(struct ocfs2_super)); - - mlog_exit_void(); } /* Put OCFS2 into a readonly state, or (if the user specifies it), diff --git a/fs/ocfs2/symlink.c b/fs/ocfs2/symlink.c index 8a81688c57df..5485b19ec8f2 100644 --- a/fs/ocfs2/symlink.c +++ b/fs/ocfs2/symlink.c @@ -72,7 +72,6 @@ static char *ocfs2_fast_symlink_getlink(struct inode *inode, fe = (struct ocfs2_dinode *) (*bh)->b_data; link = (char *) fe->id2.i_symlink; bail: - mlog_exit(status); return link; } @@ -100,7 +99,8 @@ static int ocfs2_readlink(struct dentry *dentry, brelse(bh); out: - mlog_exit(ret); + if (ret < 0) + mlog_errno(ret); return ret; } @@ -136,7 +136,8 @@ bail: nd_set_link(nd, status ? ERR_PTR(status) : link); brelse(bh); - mlog_exit(status); + if (status) + mlog_errno(status); return NULL; } diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index 81f98b7f7502..d57c7942e4de 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c @@ -5570,7 +5570,6 @@ static int ocfs2_xattr_set_entry_bucket(struct inode *inode, out: - mlog_exit(ret); return ret; } @@ -5637,7 +5636,6 @@ static int ocfs2_xattr_set_entry_index_block(struct inode *inode, mlog_errno(ret); out: - mlog_exit(ret); return ret; } -- cgit From 80a9a84da381087ed89f5fdfc40a513cf9768ac4 Mon Sep 17 00:00:00 2001 From: Wengang Wang Date: Mon, 21 Feb 2011 11:13:14 +0800 Subject: ocfs2: Add ocfs2_trace.h. About one year ago, Wengang Wang tried some first steps to add tracepoints to ocfs2. Hiss original patch is here: http://oss.oracle.com/pipermail/ocfs2-devel/2009-November/005512.html But as Steven Rostedt indicated in his article http://lwn.net/Articles/383362/, we'd better have our trace files resides in fs/ocfs2, so I rewrited the patch using the method Steven mentioned in that article. Signed-off-by: Wengang Wang Signed-off-by: Tao Ma --- fs/ocfs2/ocfs2_trace.h | 16 ++++++++++++++++ fs/ocfs2/super.c | 3 +++ 2 files changed, 19 insertions(+) create mode 100644 fs/ocfs2/ocfs2_trace.h (limited to 'fs') diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h new file mode 100644 index 000000000000..8d4e49aef491 --- /dev/null +++ b/fs/ocfs2/ocfs2_trace.h @@ -0,0 +1,16 @@ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM ocfs2 + +#if !defined(_TRACE_OCFS2_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_OCFS2_H + +#include + + +#endif /* _TRACE_OCFS2_H */ + +/* This part must be outside protection */ +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . +#define TRACE_INCLUDE_FILE ocfs2_trace +#include diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index b21b702c5603..f7e73a029844 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -42,6 +42,9 @@ #include #include +#define CREATE_TRACE_POINTS +#include "ocfs2_trace.h" + #define MLOG_MASK_PREFIX ML_SUPER #include -- cgit From a09d09b8f8d7c8acd46d96e3e9899bd1461fc036 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Tue, 22 Feb 2011 08:21:10 +0800 Subject: ocfs2: Remove mlog(0) from fs/ocfs2/alloc.c This is the first try of replacing debug mlog(0,...) to trace events. Wengang has did some work in his original patch http://oss.oracle.com/pipermail/ocfs2-devel/2009-November/005513.html But he didn't finished it. So this patch removes all mlog(0,...) from alloc.c and adds the corresponding trace events. Different mlogs have different solutions. 1. Some are replaced with trace event directly. 2. Some are replaced and some new parameters are added since I think we need to know the btree owner in that case. 3. Some are combined into one trace events. 4. Some redundant mlogs are removed. What's more, it defines some event classes so that we can use them later. Cc: Wengang Wang Signed-off-by: Tao Ma --- fs/ocfs2/alloc.c | 165 +++++++++++----------- fs/ocfs2/ocfs2_trace.h | 364 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 452 insertions(+), 77 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 80ffbe3dd32f..f0e26c4adc94 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c @@ -50,6 +50,7 @@ #include "uptodate.h" #include "xattr.h" #include "refcounttree.h" +#include "ocfs2_trace.h" #include "buffer_head_io.h" @@ -886,8 +887,7 @@ static int ocfs2_validate_extent_block(struct super_block *sb, struct ocfs2_extent_block *eb = (struct ocfs2_extent_block *)bh->b_data; - mlog(0, "Validating extent block %llu\n", - (unsigned long long)bh->b_blocknr); + trace_ocfs2_validate_extent_block((unsigned long long)bh->b_blocknr); BUG_ON(!buffer_uptodate(bh)); @@ -985,7 +985,7 @@ int ocfs2_num_free_extents(struct ocfs2_super *osb, bail: brelse(eb_bh); - mlog(0, "retval = %d\n", retval); + trace_ocfs2_num_free_extents(retval); return retval; } @@ -1194,8 +1194,11 @@ static int ocfs2_add_branch(handle_t *handle, * from new_cpos). */ if (root_end > new_cpos) { - mlog(0, "adjust the cluster end from %u to %u\n", - root_end, new_cpos); + trace_ocfs2_adjust_rightmost_branch( + (unsigned long long) + ocfs2_metadata_cache_owner(et->et_ci), + root_end, new_cpos); + status = ocfs2_adjust_rightmost_branch(handle, et); if (status) { mlog_errno(status); @@ -1527,7 +1530,10 @@ static int ocfs2_grow_tree(handle_t *handle, struct ocfs2_extent_tree *et, * another tree level */ if (shift) { BUG_ON(bh); - mlog(0, "need to shift tree depth (current = %d)\n", depth); + trace_ocfs2_grow_tree( + (unsigned long long) + ocfs2_metadata_cache_owner(et->et_ci), + depth); /* ocfs2_shift_tree_depth will return us a buffer with * the new extent block (so we can pass that to @@ -1557,7 +1563,6 @@ static int ocfs2_grow_tree(handle_t *handle, struct ocfs2_extent_tree *et, /* call ocfs2_add_branch to add the final part of the tree with * the new data. */ - mlog(0, "add branch. bh = %p\n", bh); ret = ocfs2_add_branch(handle, et, bh, last_eb_bh, meta_ac); if (ret < 0) { @@ -1632,8 +1637,9 @@ static void ocfs2_rotate_leaf(struct ocfs2_extent_list *el, } insert_index = i; - mlog(0, "ins %u: index %d, has_empty %d, next_free %d, count %d\n", - insert_cpos, insert_index, has_empty, next_free, le16_to_cpu(el->l_count)); + trace_ocfs2_rotate_leaf(insert_cpos, insert_index, + has_empty, next_free, + le16_to_cpu(el->l_count)); BUG_ON(insert_index < 0); BUG_ON(insert_index >= le16_to_cpu(el->l_count)); @@ -2046,7 +2052,7 @@ static void ocfs2_complete_edge_insert(handle_t *handle, left_el = path_leaf_el(left_path); right_el = path_leaf_el(right_path); for(i = left_path->p_tree_depth - 1; i > subtree_index; i--) { - mlog(0, "Adjust records at index %u\n", i); + trace_ocfs2_complete_edge_insert(i); /* * One nice property of knowing that all of these @@ -2376,7 +2382,9 @@ static int ocfs2_rotate_tree_right(handle_t *handle, goto out; } - mlog(0, "Insert: %u, first left path cpos: %u\n", insert_cpos, cpos); + trace_ocfs2_rotate_tree_right( + (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci), + insert_cpos, cpos); /* * What we want to do here is: @@ -2405,8 +2413,10 @@ static int ocfs2_rotate_tree_right(handle_t *handle, * rotating subtrees. */ while (cpos && insert_cpos <= cpos) { - mlog(0, "Rotating a tree: ins. cpos: %u, left path cpos: %u\n", - insert_cpos, cpos); + trace_ocfs2_rotate_tree_right( + (unsigned long long) + ocfs2_metadata_cache_owner(et->et_ci), + insert_cpos, cpos); ret = ocfs2_find_path(et->et_ci, left_path, cpos); if (ret) { @@ -2448,10 +2458,10 @@ static int ocfs2_rotate_tree_right(handle_t *handle, start = ocfs2_find_subtree_root(et, left_path, right_path); - mlog(0, "Subtree root at index %d (blk %llu, depth %d)\n", - start, - (unsigned long long) right_path->p_node[start].bh->b_blocknr, - right_path->p_tree_depth); + trace_ocfs2_rotate_subtree(start, + (unsigned long long) + right_path->p_node[start].bh->b_blocknr, + right_path->p_tree_depth); ret = ocfs2_extend_rotate_transaction(handle, start, orig_credits, right_path); @@ -2951,8 +2961,7 @@ static int __ocfs2_rotate_tree_left(handle_t *handle, subtree_root = ocfs2_find_subtree_root(et, left_path, right_path); - mlog(0, "Subtree root at index %d (blk %llu, depth %d)\n", - subtree_root, + trace_ocfs2_rotate_subtree(subtree_root, (unsigned long long) right_path->p_node[subtree_root].bh->b_blocknr, right_path->p_tree_depth); @@ -3976,9 +3985,11 @@ static int ocfs2_append_rec_to_path(handle_t *handle, goto out; } - mlog(0, "Append may need a left path update. cpos: %u, " - "left_cpos: %u\n", le32_to_cpu(insert_rec->e_cpos), - left_cpos); + trace_ocfs2_append_rec_to_path( + (unsigned long long) + ocfs2_metadata_cache_owner(et->et_ci), + le32_to_cpu(insert_rec->e_cpos), + left_cpos); /* * No need to worry if the append is already in the @@ -4665,9 +4676,9 @@ int ocfs2_insert_extent(handle_t *handle, struct ocfs2_insert_type insert = {0, }; struct ocfs2_extent_rec rec; - mlog(0, "add %u clusters at position %u to owner %llu\n", - new_clusters, cpos, - (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci)); + trace_ocfs2_insert_extent_start( + (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci), + cpos, new_clusters); memset(&rec, 0, sizeof(rec)); rec.e_cpos = cpu_to_le32(cpos); @@ -4687,11 +4698,9 @@ int ocfs2_insert_extent(handle_t *handle, goto bail; } - mlog(0, "Insert.appending: %u, Insert.Contig: %u, " - "Insert.contig_index: %d, Insert.free_records: %d, " - "Insert.tree_depth: %d\n", - insert.ins_appending, insert.ins_contig, insert.ins_contig_index, - free_records, insert.ins_tree_depth); + trace_ocfs2_insert_extent(insert.ins_appending, insert.ins_contig, + insert.ins_contig_index, free_records, + insert.ins_tree_depth); if (insert.ins_contig == CONTIG_NONE && free_records == 0) { status = ocfs2_grow_tree(handle, et, @@ -4732,7 +4741,7 @@ int ocfs2_add_clusters_in_btree(handle_t *handle, struct ocfs2_alloc_context *meta_ac, enum ocfs2_alloc_restarted *reason_ret) { - int status = 0; + int status = 0, err = 0; int free_extents; enum ocfs2_alloc_restarted reason = RESTART_NONE; u32 bit_off, num_bits; @@ -4759,14 +4768,14 @@ int ocfs2_add_clusters_in_btree(handle_t *handle, * 2) we are so fragmented, we've needed to add metadata too * many times. */ if (!free_extents && !meta_ac) { - mlog(0, "we haven't reserved any metadata!\n"); + err = -1; status = -EAGAIN; reason = RESTART_META; goto leave; } else if ((!free_extents) && (ocfs2_alloc_context_bits_left(meta_ac) < ocfs2_extend_meta_needed(et->et_root_el))) { - mlog(0, "filesystem is really fragmented...\n"); + err = -2; status = -EAGAIN; reason = RESTART_META; goto leave; @@ -4791,9 +4800,9 @@ int ocfs2_add_clusters_in_btree(handle_t *handle, } block = ocfs2_clusters_to_blocks(osb->sb, bit_off); - mlog(0, "Allocating %u clusters at block %u for owner %llu\n", - num_bits, bit_off, - (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci)); + trace_ocfs2_add_clusters_in_btree( + (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci), + bit_off, num_bits); status = ocfs2_insert_extent(handle, et, *logical_offset, block, num_bits, flags, meta_ac); if (status < 0) { @@ -4807,8 +4816,7 @@ int ocfs2_add_clusters_in_btree(handle_t *handle, *logical_offset += num_bits; if (clusters_to_add) { - mlog(0, "need to alloc once more, wanted = %u\n", - clusters_to_add); + err = clusters_to_add; status = -EAGAIN; reason = RESTART_TRANS; } @@ -4816,6 +4824,7 @@ int ocfs2_add_clusters_in_btree(handle_t *handle, leave: if (reason_ret) *reason_ret = reason; + trace_ocfs2_add_clusters_in_btree_ret(status, reason, err); return status; } @@ -5041,9 +5050,9 @@ int ocfs2_split_extent(handle_t *handle, ctxt.c_has_empty_extent = ocfs2_is_empty_extent(&el->l_recs[0]); - mlog(0, "index: %d, contig: %u, has_empty: %u, split_covers: %u\n", - split_index, ctxt.c_contig_type, ctxt.c_has_empty_extent, - ctxt.c_split_covers_rec); + trace_ocfs2_split_extent(split_index, ctxt.c_contig_type, + ctxt.c_has_empty_extent, + ctxt.c_split_covers_rec); if (ctxt.c_contig_type == CONTIG_NONE) { if (ctxt.c_split_covers_rec) @@ -5177,8 +5186,9 @@ int ocfs2_mark_extent_written(struct inode *inode, { int ret; - mlog(0, "Inode %lu cpos %u, len %u, phys clusters %u\n", - inode->i_ino, cpos, len, phys); + trace_ocfs2_mark_extent_written( + (unsigned long long)OCFS2_I(inode)->ip_blkno, + cpos, len, phys); if (!ocfs2_writes_unwritten_extents(OCFS2_SB(inode->i_sb))) { ocfs2_error(inode->i_sb, "Inode %llu has unwritten extents " @@ -5497,11 +5507,10 @@ int ocfs2_remove_extent(handle_t *handle, BUG_ON(cpos < le32_to_cpu(rec->e_cpos) || trunc_range > rec_range); - mlog(0, "Owner %llu, remove (cpos %u, len %u). Existing index %d " - "(cpos %u, len %u)\n", - (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci), - cpos, len, index, - le32_to_cpu(rec->e_cpos), ocfs2_rec_clusters(el, rec)); + trace_ocfs2_remove_extent( + (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci), + cpos, len, index, le32_to_cpu(rec->e_cpos), + ocfs2_rec_clusters(el, rec)); if (le32_to_cpu(rec->e_cpos) == cpos || rec_range == trunc_range) { ret = ocfs2_truncate_rec(handle, et, path, index, dealloc, @@ -5780,9 +5789,6 @@ int ocfs2_truncate_log_append(struct ocfs2_super *osb, struct ocfs2_dinode *di; struct ocfs2_truncate_log *tl; - mlog(0, "start_blk = %llu, num_clusters = %u\n", - (unsigned long long)start_blk, num_clusters); - BUG_ON(mutex_trylock(&tl_inode->i_mutex)); start_cluster = ocfs2_blocks_to_clusters(osb->sb, start_blk); @@ -5819,10 +5825,9 @@ int ocfs2_truncate_log_append(struct ocfs2_super *osb, goto bail; } - mlog(0, "Log truncate of %u clusters starting at cluster %u to " - "%llu (index = %d)\n", num_clusters, start_cluster, - (unsigned long long)OCFS2_I(tl_inode)->ip_blkno, index); - + trace_ocfs2_truncate_log_append( + (unsigned long long)OCFS2_I(tl_inode)->ip_blkno, index, + start_cluster, num_clusters); if (ocfs2_truncate_log_can_coalesce(tl, start_cluster)) { /* * Move index back to the record we are coalescing with. @@ -5831,9 +5836,10 @@ int ocfs2_truncate_log_append(struct ocfs2_super *osb, index--; num_clusters += le32_to_cpu(tl->tl_recs[index].t_clusters); - mlog(0, "Coalesce with index %u (start = %u, clusters = %u)\n", - index, le32_to_cpu(tl->tl_recs[index].t_start), - num_clusters); + trace_ocfs2_truncate_log_append( + (unsigned long long)OCFS2_I(tl_inode)->ip_blkno, + index, le32_to_cpu(tl->tl_recs[index].t_start), + num_clusters); } else { tl->tl_recs[index].t_start = cpu_to_le32(start_cluster); tl->tl_used = cpu_to_le16(index + 1); @@ -5897,8 +5903,9 @@ static int ocfs2_replay_truncate_records(struct ocfs2_super *osb, /* if start_blk is not set, we ignore the record as * invalid. */ if (start_blk) { - mlog(0, "free record %d, start = %u, clusters = %u\n", - i, le32_to_cpu(rec.t_start), num_clusters); + trace_ocfs2_replay_truncate_records( + (unsigned long long)OCFS2_I(tl_inode)->ip_blkno, + i, le32_to_cpu(rec.t_start), num_clusters); status = ocfs2_free_clusters(handle, data_alloc_inode, data_alloc_bh, start_blk, @@ -5941,8 +5948,9 @@ int __ocfs2_flush_truncate_log(struct ocfs2_super *osb) tl = &di->id2.i_dealloc; num_to_flush = le16_to_cpu(tl->tl_used); - mlog(0, "Flush %u records from truncate log #%llu\n", - num_to_flush, (unsigned long long)OCFS2_I(tl_inode)->ip_blkno); + trace_ocfs2_flush_truncate_log( + (unsigned long long)OCFS2_I(tl_inode)->ip_blkno, + num_to_flush); if (!num_to_flush) { status = 0; goto out; @@ -6079,7 +6087,7 @@ int ocfs2_begin_truncate_log_recovery(struct ocfs2_super *osb, *tl_copy = NULL; - mlog(0, "recover truncate log from slot %d\n", slot_num); + trace_ocfs2_begin_truncate_log_recovery(slot_num); status = ocfs2_get_truncate_log_info(osb, slot_num, &tl_inode, &tl_bh); if (status < 0) { @@ -6096,8 +6104,7 @@ int ocfs2_begin_truncate_log_recovery(struct ocfs2_super *osb, tl = &di->id2.i_dealloc; if (le16_to_cpu(tl->tl_used)) { - mlog(0, "We'll have %u logs to recover\n", - le16_to_cpu(tl->tl_used)); + trace_ocfs2_truncate_log_recovery_num(le16_to_cpu(tl->tl_used)); *tl_copy = kmalloc(tl_bh->b_size, GFP_KERNEL); if (!(*tl_copy)) { @@ -6154,8 +6161,9 @@ int ocfs2_complete_truncate_log_recovery(struct ocfs2_super *osb, tl = &tl_copy->id2.i_dealloc; num_recs = le16_to_cpu(tl->tl_used); - mlog(0, "cleanup %u records from %llu\n", num_recs, - (unsigned long long)le64_to_cpu(tl_copy->i_blkno)); + trace_ocfs2_complete_truncate_log_recovery( + (unsigned long long)le64_to_cpu(tl_copy->i_blkno), + num_recs); mutex_lock(&tl_inode->i_mutex); for(i = 0; i < num_recs; i++) { @@ -6313,8 +6321,8 @@ static int ocfs2_free_cached_blocks(struct ocfs2_super *osb, else bg_blkno = ocfs2_which_suballoc_group(head->free_blk, head->free_bit); - mlog(0, "Free bit: (bit %u, blkno %llu)\n", - head->free_bit, (unsigned long long)head->free_blk); + trace_ocfs2_free_cached_blocks( + (unsigned long long)head->free_blk, head->free_bit); ret = ocfs2_free_suballoc_bits(handle, inode, di_bh, head->free_bit, bg_blkno, 1); @@ -6367,8 +6375,7 @@ int ocfs2_cache_cluster_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt, return ret; } - mlog(0, "Insert clusters: (bit %u, blk %llu)\n", - bit, (unsigned long long)blkno); + trace_ocfs2_cache_cluster_dealloc((unsigned long long)blkno, bit); item->free_blk = blkno; item->free_bit = bit; @@ -6443,8 +6450,8 @@ int ocfs2_run_deallocs(struct ocfs2_super *osb, fl = ctxt->c_first_suballocator; if (fl->f_first) { - mlog(0, "Free items: (type %u, slot %d)\n", - fl->f_inode_type, fl->f_slot); + trace_ocfs2_run_deallocs(fl->f_inode_type, + fl->f_slot); ret2 = ocfs2_free_cached_blocks(osb, fl->f_inode_type, fl->f_slot, @@ -6521,8 +6528,9 @@ int ocfs2_cache_block_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt, goto out; } - mlog(0, "Insert: (type %d, slot %u, bit %u, blk %llu)\n", - type, slot, bit, (unsigned long long)blkno); + trace_ocfs2_cache_block_dealloc(type, slot, + (unsigned long long)suballoc, + (unsigned long long)blkno, bit); item->free_bg = suballoc; item->free_blk = blkno; @@ -7002,8 +7010,11 @@ start: goto bail; } - mlog(0, "inode->ip_clusters = %u, tree_depth = %u\n", - OCFS2_I(inode)->ip_clusters, path->p_tree_depth); + trace_ocfs2_commit_truncate( + (unsigned long long)OCFS2_I(inode)->ip_blkno, + new_highest_cpos, + OCFS2_I(inode)->ip_clusters, + path->p_tree_depth); /* * By now, el will point to the extent list on the bottom most diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 8d4e49aef491..1793b1f71805 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -6,6 +6,370 @@ #include +DECLARE_EVENT_CLASS(ocfs2__int, + TP_PROTO(int num), + TP_ARGS(num), + TP_STRUCT__entry( + __field(int, num) + ), + TP_fast_assign( + __entry->num = num; + ), + TP_printk("%d", __entry->num) +); + +#define DEFINE_OCFS2_INT_EVENT(name) \ +DEFINE_EVENT(ocfs2__int, name, \ + TP_PROTO(int num), \ + TP_ARGS(num)) + +DECLARE_EVENT_CLASS(ocfs2__int_int, + TP_PROTO(int value1, int value2), + TP_ARGS(value1, value2), + TP_STRUCT__entry( + __field(int, value1) + __field(int, value2) + ), + TP_fast_assign( + __entry->value1 = value1; + __entry->value2 = value2; + ), + TP_printk("%d %d", __entry->value1, __entry->value2) +); + +#define DEFINE_OCFS2_INT_INT_EVENT(name) \ +DEFINE_EVENT(ocfs2__int_int, name, \ + TP_PROTO(int val1, int val2), \ + TP_ARGS(val1, val2)) + +DECLARE_EVENT_CLASS(ocfs2__ull_uint, + TP_PROTO(unsigned long long value1, unsigned int value2), + TP_ARGS(value1, value2), + TP_STRUCT__entry( + __field(unsigned long long, value1) + __field(unsigned int, value2) + ), + TP_fast_assign( + __entry->value1 = value1; + __entry->value2 = value2; + ), + TP_printk("%llu %u", __entry->value1, __entry->value2) +); + +#define DEFINE_OCFS2_ULL_UINT_EVENT(name) \ +DEFINE_EVENT(ocfs2__ull_uint, name, \ + TP_PROTO(unsigned long long val1, unsigned int val2), \ + TP_ARGS(val1, val2)) + +/* Trace events for fs/ocfs2/alloc.c. */ +DECLARE_EVENT_CLASS(ocfs2__btree_ops, + TP_PROTO(unsigned long long owner,\ + unsigned int value1, unsigned int value2), + TP_ARGS(owner, value1, value2), + TP_STRUCT__entry( + __field(unsigned long long, owner) + __field(unsigned int, value1) + __field(unsigned int, value2) + ), + TP_fast_assign( + __entry->owner = owner; + __entry->value1 = value1; + __entry->value2 = value2; + ), + TP_printk("%llu %u %u", + __entry->owner, __entry->value1, __entry->value2) +); + +#define DEFINE_OCFS2_BTREE_EVENT(name) \ +DEFINE_EVENT(ocfs2__btree_ops, name, \ + TP_PROTO(unsigned long long owner, \ + unsigned int value1, unsigned int value2), \ + TP_ARGS(owner, value1, value2)) + +DEFINE_OCFS2_BTREE_EVENT(ocfs2_adjust_rightmost_branch); + +DEFINE_OCFS2_BTREE_EVENT(ocfs2_rotate_tree_right); + +DEFINE_OCFS2_BTREE_EVENT(ocfs2_append_rec_to_path); + +DEFINE_OCFS2_BTREE_EVENT(ocfs2_insert_extent_start); + +DEFINE_OCFS2_BTREE_EVENT(ocfs2_add_clusters_in_btree); + +DEFINE_OCFS2_INT_EVENT(ocfs2_num_free_extents); + +DEFINE_OCFS2_INT_EVENT(ocfs2_complete_edge_insert); + +TRACE_EVENT(ocfs2_grow_tree, + TP_PROTO(unsigned long long owner, int depth), + TP_ARGS(owner, depth), + TP_STRUCT__entry( + __field(unsigned long long, owner) + __field(int, depth) + ), + TP_fast_assign( + __entry->owner = owner; + __entry->depth = depth; + ), + TP_printk("%llu %d", __entry->owner, __entry->depth) +); + +TRACE_EVENT(ocfs2_rotate_subtree, + TP_PROTO(int subtree_root, unsigned long long blkno, + int depth), + TP_ARGS(subtree_root, blkno, depth), + TP_STRUCT__entry( + __field(int, subtree_root) + __field(unsigned long long, blkno) + __field(int, depth) + ), + TP_fast_assign( + __entry->subtree_root = subtree_root; + __entry->blkno = blkno; + __entry->depth = depth; + ), + TP_printk("%d %llu %d", __entry->subtree_root, + __entry->blkno, __entry->depth) +); + +TRACE_EVENT(ocfs2_insert_extent, + TP_PROTO(unsigned int ins_appending, unsigned int ins_contig, + int ins_contig_index, int free_records, int ins_tree_depth), + TP_ARGS(ins_appending, ins_contig, ins_contig_index, free_records, + ins_tree_depth), + TP_STRUCT__entry( + __field(unsigned int, ins_appending) + __field(unsigned int, ins_contig) + __field(int, ins_contig_index) + __field(int, free_records) + __field(int, ins_tree_depth) + ), + TP_fast_assign( + __entry->ins_appending = ins_appending; + __entry->ins_contig = ins_contig; + __entry->ins_contig_index = ins_contig_index; + __entry->free_records = free_records; + __entry->ins_tree_depth = ins_tree_depth; + ), + TP_printk("%u %u %d %d %d", + __entry->ins_appending, __entry->ins_contig, + __entry->ins_contig_index, __entry->free_records, + __entry->ins_tree_depth) +); + +TRACE_EVENT(ocfs2_split_extent, + TP_PROTO(int split_index, unsigned int c_contig_type, + unsigned int c_has_empty_extent, + unsigned int c_split_covers_rec), + TP_ARGS(split_index, c_contig_type, + c_has_empty_extent, c_split_covers_rec), + TP_STRUCT__entry( + __field(int, split_index) + __field(unsigned int, c_contig_type) + __field(unsigned int, c_has_empty_extent) + __field(unsigned int, c_split_covers_rec) + ), + TP_fast_assign( + __entry->split_index = split_index; + __entry->c_contig_type = c_contig_type; + __entry->c_has_empty_extent = c_has_empty_extent; + __entry->c_split_covers_rec = c_split_covers_rec; + ), + TP_printk("%d %u %u %u", __entry->split_index, __entry->c_contig_type, + __entry->c_has_empty_extent, __entry->c_split_covers_rec) +); + +TRACE_EVENT(ocfs2_remove_extent, + TP_PROTO(unsigned long long owner, unsigned int cpos, + unsigned int len, int index, + unsigned int e_cpos, unsigned int clusters), + TP_ARGS(owner, cpos, len, index, e_cpos, clusters), + TP_STRUCT__entry( + __field(unsigned long long, owner) + __field(unsigned int, cpos) + __field(unsigned int, len) + __field(int, index) + __field(unsigned int, e_cpos) + __field(unsigned int, clusters) + ), + TP_fast_assign( + __entry->owner = owner; + __entry->cpos = cpos; + __entry->len = len; + __entry->index = index; + __entry->e_cpos = e_cpos; + __entry->clusters = clusters; + ), + TP_printk("%llu %u %u %d %u %u", + __entry->owner, __entry->cpos, __entry->len, __entry->index, + __entry->e_cpos, __entry->clusters) +); + +TRACE_EVENT(ocfs2_commit_truncate, + TP_PROTO(unsigned long long ino, unsigned int new_cpos, + unsigned int clusters, unsigned int depth), + TP_ARGS(ino, new_cpos, clusters, depth), + TP_STRUCT__entry( + __field(unsigned long long, ino) + __field(unsigned int, new_cpos) + __field(unsigned int, clusters) + __field(unsigned int, depth) + ), + TP_fast_assign( + __entry->ino = ino; + __entry->new_cpos = new_cpos; + __entry->clusters = clusters; + __entry->depth = depth; + ), + TP_printk("%llu %u %u %u", + __entry->ino, __entry->new_cpos, + __entry->clusters, __entry->depth) +); + +TRACE_EVENT(ocfs2_validate_extent_block, + TP_PROTO(unsigned long long blkno), + TP_ARGS(blkno), + TP_STRUCT__entry( + __field(unsigned long long, blkno) + ), + TP_fast_assign( + __entry->blkno = blkno; + ), + TP_printk("%llu ", __entry->blkno) +); + +TRACE_EVENT(ocfs2_rotate_leaf, + TP_PROTO(unsigned int insert_cpos, int insert_index, + int has_empty, int next_free, + unsigned int l_count), + TP_ARGS(insert_cpos, insert_index, has_empty, + next_free, l_count), + TP_STRUCT__entry( + __field(unsigned int, insert_cpos) + __field(int, insert_index) + __field(int, has_empty) + __field(int, next_free) + __field(unsigned int, l_count) + ), + TP_fast_assign( + __entry->insert_cpos = insert_cpos; + __entry->insert_index = insert_index; + __entry->has_empty = has_empty; + __entry->next_free = next_free; + __entry->l_count = l_count; + ), + TP_printk("%u %d %d %d %u", __entry->insert_cpos, + __entry->insert_index, __entry->has_empty, + __entry->next_free, __entry->l_count) +); + +TRACE_EVENT(ocfs2_add_clusters_in_btree_ret, + TP_PROTO(int status, int reason, int err), + TP_ARGS(status, reason, err), + TP_STRUCT__entry( + __field(int, status) + __field(int, reason) + __field(int, err) + ), + TP_fast_assign( + __entry->status = status; + __entry->reason = reason; + __entry->err = err; + ), + TP_printk("%d %d %d", __entry->status, + __entry->reason, __entry->err) +); + +TRACE_EVENT(ocfs2_mark_extent_written, + TP_PROTO(unsigned long long owner, unsigned int cpos, + unsigned int len, unsigned int phys), + TP_ARGS(owner, cpos, len, phys), + TP_STRUCT__entry( + __field(unsigned long long, owner) + __field(unsigned int, cpos) + __field(unsigned int, len) + __field(unsigned int, phys) + ), + TP_fast_assign( + __entry->owner = owner; + __entry->cpos = cpos; + __entry->len = len; + __entry->phys = phys; + ), + TP_printk("%llu %u %u %u", + __entry->owner, __entry->cpos, + __entry->len, __entry->phys) +); + +DECLARE_EVENT_CLASS(ocfs2__truncate_log_ops, + TP_PROTO(unsigned long long blkno, int index, + unsigned int start, unsigned int num), + TP_ARGS(blkno, index, start, num), + TP_STRUCT__entry( + __field(unsigned long long, blkno) + __field(int, index) + __field(unsigned int, start) + __field(unsigned int, num) + ), + TP_fast_assign( + __entry->blkno = blkno; + __entry->index = index; + __entry->start = start; + __entry->num = num; + ), + TP_printk("%llu %d %u %u", + __entry->blkno, __entry->index, + __entry->start, __entry->num) +); + +#define DEFINE_OCFS2_TRUNCATE_LOG_OPS_EVENT(name) \ +DEFINE_EVENT(ocfs2__truncate_log_ops, name, \ + TP_PROTO(unsigned long long blkno, int index, \ + unsigned int start, unsigned int num), \ + TP_ARGS(blkno, index, start, num)) + +DEFINE_OCFS2_TRUNCATE_LOG_OPS_EVENT(ocfs2_truncate_log_append); + +DEFINE_OCFS2_TRUNCATE_LOG_OPS_EVENT(ocfs2_replay_truncate_records); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_flush_truncate_log); + +DEFINE_OCFS2_INT_EVENT(ocfs2_begin_truncate_log_recovery); + +DEFINE_OCFS2_INT_EVENT(ocfs2_truncate_log_recovery_num); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_complete_truncate_log_recovery); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_free_cached_blocks); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_cache_cluster_dealloc); + +DEFINE_OCFS2_INT_INT_EVENT(ocfs2_run_deallocs); + +TRACE_EVENT(ocfs2_cache_block_dealloc, + TP_PROTO(int type, int slot, unsigned long long suballoc, + unsigned long long blkno, unsigned int bit), + TP_ARGS(type, slot, suballoc, blkno, bit), + TP_STRUCT__entry( + __field(int, type) + __field(int, slot) + __field(unsigned long long, suballoc) + __field(unsigned long long, blkno) + __field(unsigned int, bit) + ), + TP_fast_assign( + __entry->type = type; + __entry->slot = slot; + __entry->suballoc = suballoc; + __entry->blkno = blkno; + __entry->bit = bit; + ), + TP_printk("%d %d %llu %llu %u", + __entry->type, __entry->slot, __entry->suballoc, + __entry->blkno, __entry->bit) +); + +/* End of trace events for fs/ocfs2/alloc.c. */ #endif /* _TRACE_OCFS2_H */ -- cgit From a04733d8afad9cd0bfb8269173e30d28fb96088e Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Tue, 22 Feb 2011 07:56:45 +0800 Subject: ocfs2: Remove mlog(0) from fs/ocfs2/localalloc.c This is the 2nd step to remove the debug info of DISK_ALLOC. So this patch removes all mlog(0,...) from localalloc.c and adds the corresponding tracepoints. Different mlogs have different solutions. 1. Some are replaced with trace event directly. 2. Some are replaced while some new parameters are added. 3. Some are combined into one trace events. 4. Some redundant mlogs are removed. Signed-off-by: Tao Ma --- fs/ocfs2/localalloc.c | 57 ++++++++++--------------- fs/ocfs2/ocfs2_trace.h | 112 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+), 34 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c index 36636e1c84e7..a311b1f658e2 100644 --- a/fs/ocfs2/localalloc.c +++ b/fs/ocfs2/localalloc.c @@ -43,6 +43,7 @@ #include "suballoc.h" #include "super.h" #include "sysfile.h" +#include "ocfs2_trace.h" #include "buffer_head_io.h" @@ -201,8 +202,7 @@ void ocfs2_la_set_sizes(struct ocfs2_super *osb, int requested_mb) la_max_mb = ocfs2_clusters_to_megabytes(sb, ocfs2_local_alloc_size(sb) * 8); - mlog(0, "requested: %dM, max: %uM, default: %uM\n", - requested_mb, la_max_mb, la_default_mb); + trace_ocfs2_la_set_sizes(requested_mb, la_max_mb, la_default_mb); if (requested_mb == -1) { /* No user request - use defaults */ @@ -276,8 +276,8 @@ int ocfs2_alloc_should_use_local(struct ocfs2_super *osb, u64 bits) ret = 1; bail: - mlog(0, "state=%d, bits=%llu, la_bits=%d, ret=%d\n", - osb->local_alloc_state, (unsigned long long)bits, la_bits, ret); + trace_ocfs2_alloc_should_use_local( + (unsigned long long)bits, osb->local_alloc_state, la_bits, ret); spin_unlock(&osb->osb_lock); return ret; } @@ -362,7 +362,7 @@ bail: if (inode) iput(inode); - mlog(0, "Local alloc window bits = %d\n", osb->local_alloc_bits); + trace_ocfs2_load_local_alloc(osb->local_alloc_bits); if (status) mlog_errno(status); @@ -497,7 +497,7 @@ int ocfs2_begin_local_alloc_recovery(struct ocfs2_super *osb, struct inode *inode = NULL; struct ocfs2_dinode *alloc; - mlog(0, "(slot_num = %d)\n", slot_num); + trace_ocfs2_begin_local_alloc_recovery(slot_num); *alloc_copy = NULL; @@ -705,10 +705,6 @@ int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb, goto bail; } - if (ac->ac_max_block) - mlog(0, "Calling in_range for max block %llu\n", - (unsigned long long)ac->ac_max_block); - ac->ac_inode = local_alloc_inode; /* We should never use localalloc from another slot */ ac->ac_alloc_slot = osb->slot_num; @@ -722,8 +718,9 @@ bail: iput(local_alloc_inode); } - mlog(0, "bits=%d, slot=%d, ret=%d\n", bits_wanted, osb->slot_num, - status); + trace_ocfs2_reserve_local_alloc_bits( + (unsigned long long)ac->ac_max_block, + bits_wanted, osb->slot_num, status); if (status) mlog_errno(status); @@ -797,7 +794,7 @@ static u32 ocfs2_local_alloc_count_bits(struct ocfs2_dinode *alloc) for (i = 0; i < le16_to_cpu(la->la_size); i++) count += hweight8(buffer[i]); - mlog(0, "count %u\n", count); + trace_ocfs2_local_alloc_count_bits(count); return count; } @@ -812,10 +809,7 @@ static int ocfs2_local_alloc_find_clear_bits(struct ocfs2_super *osb, void *bitmap = NULL; struct ocfs2_reservation_map *resmap = &osb->osb_la_resmap; - mlog(0, "(numbits wanted = %u)\n", *numbits); - if (!alloc->id1.bitmap1.i_total) { - mlog(0, "No bits in my window!\n"); bitoff = -1; goto bail; } @@ -875,8 +869,7 @@ static int ocfs2_local_alloc_find_clear_bits(struct ocfs2_super *osb, } } - mlog(0, "Exiting loop, bitoff = %d, numfound = %d\n", bitoff, - numfound); + trace_ocfs2_local_alloc_find_clear_bits_search_bitmap(bitoff, numfound); if (numfound == *numbits) bitoff = startoff - numfound; @@ -887,7 +880,10 @@ bail: if (local_resv) ocfs2_resv_discard(resmap, resv); - mlog(0, "bitoff %d\n", bitoff); + trace_ocfs2_local_alloc_find_clear_bits(*numbits, + le32_to_cpu(alloc->id1.bitmap1.i_total), + bitoff, numfound); + return bitoff; } @@ -941,18 +937,16 @@ static int ocfs2_sync_local_to_main(struct ocfs2_super *osb, void *bitmap; struct ocfs2_local_alloc *la = OCFS2_LOCAL_ALLOC(alloc); - mlog(0, "total = %u, used = %u\n", + trace_ocfs2_sync_local_to_main( le32_to_cpu(alloc->id1.bitmap1.i_total), le32_to_cpu(alloc->id1.bitmap1.i_used)); if (!alloc->id1.bitmap1.i_total) { - mlog(0, "nothing to sync!\n"); goto bail; } if (le32_to_cpu(alloc->id1.bitmap1.i_used) == le32_to_cpu(alloc->id1.bitmap1.i_total)) { - mlog(0, "all bits were taken!\n"); goto bail; } @@ -974,8 +968,7 @@ static int ocfs2_sync_local_to_main(struct ocfs2_super *osb, ocfs2_clusters_to_blocks(osb->sb, start - count); - mlog(0, "freeing %u bits starting at local alloc bit " - "%u (la_start_blk = %llu, blkno = %llu)\n", + trace_ocfs2_sync_local_to_main_free( count, start - count, (unsigned long long)la_start_blk, (unsigned long long)blkno); @@ -1142,12 +1135,9 @@ static int ocfs2_local_alloc_new_window(struct ocfs2_super *osb, alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data; la = OCFS2_LOCAL_ALLOC(alloc); - if (alloc->id1.bitmap1.i_total) - mlog(0, "asking me to alloc a new window over a non-empty " - "one\n"); - - mlog(0, "Allocating %u clusters for a new window.\n", - osb->local_alloc_bits); + trace_ocfs2_local_alloc_new_window( + le32_to_cpu(alloc->id1.bitmap1.i_total), + osb->local_alloc_bits); /* Instruct the allocation code to try the most recently used * cluster group. We'll re-record the group used this pass @@ -1209,10 +1199,9 @@ retry_enospc: ocfs2_resmap_restart(&osb->osb_la_resmap, cluster_count, OCFS2_LOCAL_ALLOC(alloc)->la_bitmap); - mlog(0, "New window allocated:\n"); - mlog(0, "window la_bm_off = %u\n", - OCFS2_LOCAL_ALLOC(alloc)->la_bm_off); - mlog(0, "window bits = %u\n", le32_to_cpu(alloc->id1.bitmap1.i_total)); + trace_ocfs2_local_alloc_new_window_result( + OCFS2_LOCAL_ALLOC(alloc)->la_bm_off, + le32_to_cpu(alloc->id1.bitmap1.i_total)); bail: if (status) diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 1793b1f71805..5bba629766ca 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -23,6 +23,23 @@ DEFINE_EVENT(ocfs2__int, name, \ TP_PROTO(int num), \ TP_ARGS(num)) +DECLARE_EVENT_CLASS(ocfs2__uint, + TP_PROTO(unsigned int num), + TP_ARGS(num), + TP_STRUCT__entry( + __field( unsigned int, num ) + ), + TP_fast_assign( + __entry->num = num; + ), + TP_printk("%u", __entry->num) +); + +#define DEFINE_OCFS2_UINT_EVENT(name) \ +DEFINE_EVENT(ocfs2__uint, name, \ + TP_PROTO(unsigned int num), \ + TP_ARGS(num)) + DECLARE_EVENT_CLASS(ocfs2__int_int, TP_PROTO(int value1, int value2), TP_ARGS(value1, value2), @@ -61,6 +78,55 @@ DEFINE_EVENT(ocfs2__ull_uint, name, \ TP_PROTO(unsigned long long val1, unsigned int val2), \ TP_ARGS(val1, val2)) +DECLARE_EVENT_CLASS(ocfs2__uint_uint_uint, + TP_PROTO(unsigned int value1, unsigned int value2, + unsigned int value3), + TP_ARGS(value1, value2, value3), + TP_STRUCT__entry( + __field( unsigned int, value1 ) + __field( unsigned int, value2 ) + __field( unsigned int, value3 ) + ), + TP_fast_assign( + __entry->value1 = value1; + __entry->value2 = value2; + __entry->value3 = value3; + ), + TP_printk("%u %u %u", __entry->value1, __entry->value2, __entry->value3) +); + +#define DEFINE_OCFS2_UINT_UINT_UINT_EVENT(name) \ +DEFINE_EVENT(ocfs2__uint_uint_uint, name, \ + TP_PROTO(unsigned int value1, unsigned int value2, \ + unsigned int value3), \ + TP_ARGS(value1, value2, value3)) + +DECLARE_EVENT_CLASS(ocfs2__ull_int_int_int, + TP_PROTO(unsigned long long ull, int value1, int value2, int value3), + TP_ARGS(ull, value1, value2, value3), + TP_STRUCT__entry( + __field( unsigned long long, ull ) + __field( int, value1 ) + __field( int, value2 ) + __field( int, value3 ) + ), + TP_fast_assign( + __entry->ull = ull; + __entry->value1 = value1; + __entry->value2 = value2; + __entry->value3 = value3; + ), + TP_printk("%llu %d %d %d", + __entry->ull, __entry->value1, + __entry->value2, __entry->value3) +); + +#define DEFINE_OCFS2_ULL_INT_INT_INT_EVENT(name) \ +DEFINE_EVENT(ocfs2__ull_int_int_int, name, \ + TP_PROTO(unsigned long long ull, int value1, \ + int value2, int value3), \ + TP_ARGS(ull, value1, value2, value3)) + /* Trace events for fs/ocfs2/alloc.c. */ DECLARE_EVENT_CLASS(ocfs2__btree_ops, TP_PROTO(unsigned long long owner,\ @@ -371,6 +437,52 @@ TRACE_EVENT(ocfs2_cache_block_dealloc, /* End of trace events for fs/ocfs2/alloc.c. */ +/* Trace events for fs/ocfs2/localalloc.c. */ + +DEFINE_OCFS2_UINT_UINT_UINT_EVENT(ocfs2_la_set_sizes); + +DEFINE_OCFS2_ULL_INT_INT_INT_EVENT(ocfs2_alloc_should_use_local); + +DEFINE_OCFS2_INT_EVENT(ocfs2_load_local_alloc); + +DEFINE_OCFS2_INT_EVENT(ocfs2_begin_local_alloc_recovery); + +DEFINE_OCFS2_ULL_INT_INT_INT_EVENT(ocfs2_reserve_local_alloc_bits); + +DEFINE_OCFS2_UINT_EVENT(ocfs2_local_alloc_count_bits); + +DEFINE_OCFS2_INT_INT_EVENT(ocfs2_local_alloc_find_clear_bits_search_bitmap); + +DEFINE_OCFS2_ULL_INT_INT_INT_EVENT(ocfs2_local_alloc_find_clear_bits); + +DEFINE_OCFS2_INT_INT_EVENT(ocfs2_sync_local_to_main); + +TRACE_EVENT(ocfs2_sync_local_to_main_free, + TP_PROTO(int count, int bit, unsigned long long start_blk, + unsigned long long blkno), + TP_ARGS(count, bit, start_blk, blkno), + TP_STRUCT__entry( + __field(int, count) + __field(int, bit) + __field(unsigned long long, start_blk) + __field(unsigned long long, blkno) + ), + TP_fast_assign( + __entry->count = count; + __entry->bit = bit; + __entry->start_blk = start_blk; + __entry->blkno = blkno; + ), + TP_printk("%d %d %llu %llu", + __entry->count, __entry->bit, __entry->start_blk, + __entry->blkno) +); + +DEFINE_OCFS2_INT_INT_EVENT(ocfs2_local_alloc_new_window); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_local_alloc_new_window_result); + +/* End of trace events for fs/ocfs2/localalloc.c. */ #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ -- cgit From 2f73e135b83c5001dad84cbd1d445d23fd045b83 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Tue, 22 Feb 2011 08:22:33 +0800 Subject: ocfs2: Remove mlog(0) from fs/ocfs2/suballoc.c This is the 3rd step to remove the debug info of DISK_ALLOC. Signed-off-by: Tao Ma --- fs/ocfs2/ocfs2_trace.h | 212 +++++++++++++++++++++++++++++++++++++++++++++++++ fs/ocfs2/suballoc.c | 107 +++++++++++++------------ 2 files changed, 265 insertions(+), 54 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 5bba629766ca..11980ecba546 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -40,6 +40,23 @@ DEFINE_EVENT(ocfs2__uint, name, \ TP_PROTO(unsigned int num), \ TP_ARGS(num)) +DECLARE_EVENT_CLASS(ocfs2__ull, + TP_PROTO(unsigned long long blkno), + TP_ARGS(blkno), + TP_STRUCT__entry( + __field(unsigned long long, blkno) + ), + TP_fast_assign( + __entry->blkno = blkno; + ), + TP_printk("%llu", __entry->blkno) +); + +#define DEFINE_OCFS2_ULL_EVENT(name) \ +DEFINE_EVENT(ocfs2__ull, name, \ + TP_PROTO(unsigned long long num), \ + TP_ARGS(num)) + DECLARE_EVENT_CLASS(ocfs2__int_int, TP_PROTO(int value1, int value2), TP_ARGS(value1, value2), @@ -59,6 +76,25 @@ DEFINE_EVENT(ocfs2__int_int, name, \ TP_PROTO(int val1, int val2), \ TP_ARGS(val1, val2)) +DECLARE_EVENT_CLASS(ocfs2__uint_uint, + TP_PROTO(unsigned int value1, unsigned int value2), + TP_ARGS(value1, value2), + TP_STRUCT__entry( + __field(unsigned int, value1) + __field(unsigned int, value2) + ), + TP_fast_assign( + __entry->value1 = value1; + __entry->value2 = value2; + ), + TP_printk("%u %u", __entry->value1, __entry->value2) +); + +#define DEFINE_OCFS2_UINT_UINT_EVENT(name) \ +DEFINE_EVENT(ocfs2__uint_uint, name, \ + TP_PROTO(unsigned int val1, unsigned int val2), \ + TP_ARGS(val1, val2)) + DECLARE_EVENT_CLASS(ocfs2__ull_uint, TP_PROTO(unsigned long long value1, unsigned int value2), TP_ARGS(value1, value2), @@ -78,6 +114,49 @@ DEFINE_EVENT(ocfs2__ull_uint, name, \ TP_PROTO(unsigned long long val1, unsigned int val2), \ TP_ARGS(val1, val2)) +DECLARE_EVENT_CLASS(ocfs2__ull_ull, + TP_PROTO(unsigned long long value1, unsigned long long value2), + TP_ARGS(value1, value2), + TP_STRUCT__entry( + __field(unsigned long long, value1) + __field(unsigned long long, value2) + ), + TP_fast_assign( + __entry->value1 = value1; + __entry->value2 = value2; + ), + TP_printk("%llu %llu", __entry->value1, __entry->value2) +); + +#define DEFINE_OCFS2_ULL_ULL_EVENT(name) \ +DEFINE_EVENT(ocfs2__ull_ull, name, \ + TP_PROTO(unsigned long long val1, unsigned long long val2), \ + TP_ARGS(val1, val2)) + +DECLARE_EVENT_CLASS(ocfs2__ull_uint_uint, + TP_PROTO(unsigned long long value1, + unsigned int value2, unsigned int value3), + TP_ARGS(value1, value2, value3), + TP_STRUCT__entry( + __field(unsigned long long, value1) + __field(unsigned int, value2) + __field(unsigned int, value3) + ), + TP_fast_assign( + __entry->value1 = value1; + __entry->value2 = value2; + __entry->value3 = value3; + ), + TP_printk("%llu %u %u", __entry->value1, + __entry->value2, __entry->value3) +); + +#define DEFINE_OCFS2_ULL_UINT_UINT_EVENT(name) \ +DEFINE_EVENT(ocfs2__ull_uint_uint, name, \ + TP_PROTO(unsigned long long val1, \ + unsigned int val2, unsigned int val3), \ + TP_ARGS(val1, val2, val3)) + DECLARE_EVENT_CLASS(ocfs2__uint_uint_uint, TP_PROTO(unsigned int value1, unsigned int value2, unsigned int value3), @@ -127,6 +206,33 @@ DEFINE_EVENT(ocfs2__ull_int_int_int, name, \ int value2, int value3), \ TP_ARGS(ull, value1, value2, value3)) +DECLARE_EVENT_CLASS(ocfs2__ull_uint_uint_uint, + TP_PROTO(unsigned long long ull, unsigned int value1, + unsigned int value2, unsigned int value3), + TP_ARGS(ull, value1, value2, value3), + TP_STRUCT__entry( + __field(unsigned long long, ull) + __field(unsigned int, value1) + __field(unsigned int, value2) + __field(unsigned int, value3) + ), + TP_fast_assign( + __entry->ull = ull; + __entry->value1 = value1; + __entry->value2 = value2; + __entry->value3 = value3; + ), + TP_printk("%llu %u %u %u", + __entry->ull, __entry->value1, + __entry->value2, __entry->value3) +); + +#define DEFINE_OCFS2_ULL_UINT_UINT_UINT_EVENT(name) \ +DEFINE_EVENT(ocfs2__ull_uint_uint_uint, name, \ + TP_PROTO(unsigned long long ull, unsigned int value1, \ + unsigned int value2, unsigned int value3), \ + TP_ARGS(ull, value1, value2, value3)) + /* Trace events for fs/ocfs2/alloc.c. */ DECLARE_EVENT_CLASS(ocfs2__btree_ops, TP_PROTO(unsigned long long owner,\ @@ -483,6 +589,112 @@ DEFINE_OCFS2_INT_INT_EVENT(ocfs2_local_alloc_new_window); DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_local_alloc_new_window_result); /* End of trace events for fs/ocfs2/localalloc.c. */ + +/* Trace events for fs/ocfs2/suballoc.c. */ + +DEFINE_OCFS2_ULL_EVENT(ocfs2_validate_group_descriptor); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_block_group_alloc_contig); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_block_group_alloc_discontig); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_block_group_alloc); + +DEFINE_OCFS2_UINT_UINT_EVENT(ocfs2_reserve_suballoc_bits_nospc); + +DEFINE_OCFS2_UINT_UINT_UINT_EVENT(ocfs2_reserve_suballoc_bits_no_new_group); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_reserve_new_inode_new_group); + +DEFINE_OCFS2_UINT_UINT_EVENT(ocfs2_block_group_set_bits); + +TRACE_EVENT(ocfs2_relink_block_group, + TP_PROTO(unsigned long long i_blkno, unsigned int chain, + unsigned long long bg_blkno, + unsigned long long prev_blkno), + TP_ARGS(i_blkno, chain, bg_blkno, prev_blkno), + TP_STRUCT__entry( + __field(unsigned long long, i_blkno) + __field(unsigned int, chain) + __field(unsigned long long, bg_blkno) + __field(unsigned long long, prev_blkno) + ), + TP_fast_assign( + __entry->i_blkno = i_blkno; + __entry->chain = chain; + __entry->bg_blkno = bg_blkno; + __entry->prev_blkno = prev_blkno; + ), + TP_printk("%llu %u %llu %llu", + __entry->i_blkno, __entry->chain, __entry->bg_blkno, + __entry->prev_blkno) +); + +DEFINE_OCFS2_ULL_UINT_UINT_UINT_EVENT(ocfs2_cluster_group_search_wrong_max_bits); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_cluster_group_search_max_block); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_block_group_search_max_block); + +DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_search_chain_begin); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_search_chain_succ); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_search_chain_end); + +DEFINE_OCFS2_UINT_EVENT(ocfs2_claim_suballoc_bits); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_claim_new_inode_at_loc); + +DEFINE_OCFS2_UINT_UINT_EVENT(ocfs2_block_group_clear_bits); + +TRACE_EVENT(ocfs2_free_suballoc_bits, + TP_PROTO(unsigned long long inode, unsigned long long group, + unsigned int start_bit, unsigned int count), + TP_ARGS(inode, group, start_bit, count), + TP_STRUCT__entry( + __field(unsigned long long, inode) + __field(unsigned long long, group) + __field(unsigned int, start_bit) + __field(unsigned int, count) + ), + TP_fast_assign( + __entry->inode = inode; + __entry->group = group; + __entry->start_bit = start_bit; + __entry->count = count; + ), + TP_printk("%llu %llu %u %u", __entry->inode, __entry->group, + __entry->start_bit, __entry->count) +); + +TRACE_EVENT(ocfs2_free_clusters, + TP_PROTO(unsigned long long bg_blkno, unsigned long long start_blk, + unsigned int start_bit, unsigned int count), + TP_ARGS(bg_blkno, start_blk, start_bit, count), + TP_STRUCT__entry( + __field(unsigned long long, bg_blkno) + __field(unsigned long long, start_blk) + __field(unsigned int, start_bit) + __field(unsigned int, count) + ), + TP_fast_assign( + __entry->bg_blkno = bg_blkno; + __entry->start_blk = start_blk; + __entry->start_bit = start_bit; + __entry->count = count; + ), + TP_printk("%llu %llu %u %u", __entry->bg_blkno, __entry->start_blk, + __entry->start_bit, __entry->count) +); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_get_suballoc_slot_bit); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_test_suballoc_bit); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_test_inode_bit); + +/* End of trace events for fs/ocfs2/suballoc.c. */ #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index 2d722f1fbaa0..94342bd9800d 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -44,6 +44,7 @@ #include "super.h" #include "sysfile.h" #include "uptodate.h" +#include "ocfs2_trace.h" #include "buffer_head_io.h" @@ -308,8 +309,8 @@ static int ocfs2_validate_group_descriptor(struct super_block *sb, int rc; struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data; - mlog(0, "Validating group descriptor %llu\n", - (unsigned long long)bh->b_blocknr); + trace_ocfs2_validate_group_descriptor( + (unsigned long long)bh->b_blocknr); BUG_ON(!buffer_uptodate(bh)); @@ -476,8 +477,8 @@ ocfs2_block_group_alloc_contig(struct ocfs2_super *osb, handle_t *handle, /* setup the group */ bg_blkno = ocfs2_clusters_to_blocks(osb->sb, bit_off); - mlog(0, "new descriptor, record %u, at block %llu\n", - alloc_rec, (unsigned long long)bg_blkno); + trace_ocfs2_block_group_alloc_contig( + (unsigned long long)bg_blkno, alloc_rec); bg_bh = sb_getblk(osb->sb, bg_blkno); if (!bg_bh) { @@ -656,8 +657,8 @@ ocfs2_block_group_alloc_discontig(handle_t *handle, /* setup the group */ bg_blkno = ocfs2_clusters_to_blocks(osb->sb, bit_off); - mlog(0, "new descriptor, record %u, at block %llu\n", - alloc_rec, (unsigned long long)bg_blkno); + trace_ocfs2_block_group_alloc_discontig( + (unsigned long long)bg_blkno, alloc_rec); bg_bh = sb_getblk(osb->sb, bg_blkno); if (!bg_bh) { @@ -727,8 +728,8 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb, } if (last_alloc_group && *last_alloc_group != 0) { - mlog(0, "use old allocation group %llu for block group alloc\n", - (unsigned long long)*last_alloc_group); + trace_ocfs2_block_group_alloc( + (unsigned long long)*last_alloc_group); ac->ac_last_group = *last_alloc_group; } @@ -851,16 +852,15 @@ static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb, if (bits_wanted > free_bits) { /* cluster bitmap never grows */ if (ocfs2_is_cluster_bitmap(alloc_inode)) { - mlog(0, "Disk Full: wanted=%u, free_bits=%u\n", - bits_wanted, free_bits); + trace_ocfs2_reserve_suballoc_bits_nospc(bits_wanted, + free_bits); status = -ENOSPC; goto bail; } if (!(flags & ALLOC_NEW_GROUP)) { - mlog(0, "Alloc File %u Full: wanted=%u, free_bits=%u, " - "and we don't alloc a new group for it.\n", - slot, bits_wanted, free_bits); + trace_ocfs2_reserve_suballoc_bits_no_new_group( + slot, bits_wanted, free_bits); status = -ENOSPC; goto bail; } @@ -1117,8 +1117,8 @@ int ocfs2_reserve_new_inode(struct ocfs2_super *osb, spin_lock(&osb->osb_lock); osb->osb_inode_alloc_group = alloc_group; spin_unlock(&osb->osb_lock); - mlog(0, "after reservation, new allocation group is " - "%llu\n", (unsigned long long)alloc_group); + trace_ocfs2_reserve_new_inode_new_group( + (unsigned long long)alloc_group); /* * Some inodes must be freed by us, so try to allocate @@ -1360,8 +1360,7 @@ static inline int ocfs2_block_group_set_bits(handle_t *handle, BUG_ON(!OCFS2_IS_VALID_GROUP_DESC(bg)); BUG_ON(le16_to_cpu(bg->bg_free_bits_count) < num_bits); - mlog(0, "block_group_set_bits: off = %u, num = %u\n", bit_off, - num_bits); + trace_ocfs2_block_group_set_bits(bit_off, num_bits); if (ocfs2_is_cluster_bitmap(alloc_inode)) journal_type = OCFS2_JOURNAL_ACCESS_UNDO; @@ -1434,10 +1433,10 @@ static int ocfs2_relink_block_group(handle_t *handle, BUG_ON(!OCFS2_IS_VALID_GROUP_DESC(bg)); BUG_ON(!OCFS2_IS_VALID_GROUP_DESC(prev_bg)); - mlog(0, "Suballoc %llu, chain %u, move group %llu to top, prev = %llu\n", - (unsigned long long)le64_to_cpu(fe->i_blkno), chain, - (unsigned long long)le64_to_cpu(bg->bg_blkno), - (unsigned long long)le64_to_cpu(prev_bg->bg_blkno)); + trace_ocfs2_relink_block_group( + (unsigned long long)le64_to_cpu(fe->i_blkno), chain, + (unsigned long long)le64_to_cpu(bg->bg_blkno), + (unsigned long long)le64_to_cpu(prev_bg->bg_blkno)); fe_ptr = le64_to_cpu(fe->id2.i_chain.cl_recs[chain].c_blkno); bg_ptr = le64_to_cpu(bg->bg_next_group); @@ -1523,10 +1522,10 @@ static int ocfs2_cluster_group_search(struct inode *inode, if ((gd_cluster_off + max_bits) > OCFS2_I(inode)->ip_clusters) { max_bits = OCFS2_I(inode)->ip_clusters - gd_cluster_off; - mlog(0, "Desc %llu, bg_bits %u, clusters %u, use %u\n", - (unsigned long long)le64_to_cpu(gd->bg_blkno), - le16_to_cpu(gd->bg_bits), - OCFS2_I(inode)->ip_clusters, max_bits); + trace_ocfs2_cluster_group_search_wrong_max_bits( + (unsigned long long)le64_to_cpu(gd->bg_blkno), + le16_to_cpu(gd->bg_bits), + OCFS2_I(inode)->ip_clusters, max_bits); } ret = ocfs2_block_group_find_clear_bits(OCFS2_SB(inode->i_sb), @@ -1540,9 +1539,9 @@ static int ocfs2_cluster_group_search(struct inode *inode, gd_cluster_off + res->sr_bit_offset + res->sr_bits); - mlog(0, "Checking %llu against %llu\n", - (unsigned long long)blkoff, - (unsigned long long)max_block); + trace_ocfs2_cluster_group_search_max_block( + (unsigned long long)blkoff, + (unsigned long long)max_block); if (blkoff > max_block) return -ENOSPC; } @@ -1586,9 +1585,9 @@ static int ocfs2_block_group_search(struct inode *inode, if (!ret && max_block) { blkoff = le64_to_cpu(bg->bg_blkno) + res->sr_bit_offset + res->sr_bits; - mlog(0, "Checking %llu against %llu\n", - (unsigned long long)blkoff, - (unsigned long long)max_block); + trace_ocfs2_block_group_search_max_block( + (unsigned long long)blkoff, + (unsigned long long)max_block); if (blkoff > max_block) ret = -ENOSPC; } @@ -1754,9 +1753,9 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, struct ocfs2_group_desc *bg; chain = ac->ac_chain; - mlog(0, "trying to alloc %u bits from chain %u, inode %llu\n", - bits_wanted, chain, - (unsigned long long)OCFS2_I(alloc_inode)->ip_blkno); + trace_ocfs2_search_chain_begin( + (unsigned long long)OCFS2_I(alloc_inode)->ip_blkno, + bits_wanted, chain); status = ocfs2_read_group_descriptor(alloc_inode, fe, le64_to_cpu(cl->cl_recs[chain].c_blkno), @@ -1797,8 +1796,8 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, goto bail; } - mlog(0, "alloc succeeds: we give %u bits from block group %llu\n", - res->sr_bits, (unsigned long long)le64_to_cpu(bg->bg_blkno)); + trace_ocfs2_search_chain_succ( + (unsigned long long)le64_to_cpu(bg->bg_blkno), res->sr_bits); res->sr_bg_blkno = le64_to_cpu(bg->bg_blkno); @@ -1859,8 +1858,9 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, goto bail; } - mlog(0, "Allocated %u bits from suballocator %llu\n", res->sr_bits, - (unsigned long long)le64_to_cpu(fe->i_blkno)); + trace_ocfs2_search_chain_end( + (unsigned long long)le64_to_cpu(fe->i_blkno), + res->sr_bits); out_loc_only: *bits_left = le16_to_cpu(bg->bg_free_bits_count); @@ -1942,8 +1942,7 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_alloc_context *ac, goto bail; } - mlog(0, "Search of victim chain %u came up with nothing, " - "trying all chains now.\n", victim); + trace_ocfs2_claim_suballoc_bits(victim); /* If we didn't pick a good victim, then just default to * searching each chain in order. Don't allow chain relinking @@ -2171,8 +2170,8 @@ int ocfs2_claim_new_inode_at_loc(handle_t *handle, goto out; } - mlog(0, "Allocated %u bits from suballocator %llu\n", res->sr_bits, - (unsigned long long)di_blkno); + trace_ocfs2_claim_new_inode_at_loc((unsigned long long)di_blkno, + res->sr_bits); atomic_inc(&OCFS2_SB(ac->ac_inode->i_sb)->alloc_stats.bg_allocs); @@ -2393,7 +2392,7 @@ static int ocfs2_block_group_clear_bits(handle_t *handle, * ocfs2_read_group_descriptor(). Any corruption is a code bug. */ BUG_ON(!OCFS2_IS_VALID_GROUP_DESC(bg)); - mlog(0, "off = %u, num = %u\n", bit_off, num_bits); + trace_ocfs2_block_group_clear_bits(bit_off, num_bits); BUG_ON(undo_fn && !ocfs2_is_cluster_bitmap(alloc_inode)); status = ocfs2_journal_access_gd(handle, INODE_CACHE(alloc_inode), @@ -2466,9 +2465,10 @@ static int _ocfs2_free_suballoc_bits(handle_t *handle, BUG_ON(!OCFS2_IS_VALID_DINODE(fe)); BUG_ON((count + start_bit) > ocfs2_bits_per_group(cl)); - mlog(0, "%llu: freeing %u bits from group %llu, starting at %u\n", - (unsigned long long)OCFS2_I(alloc_inode)->ip_blkno, count, - (unsigned long long)bg_blkno, start_bit); + trace_ocfs2_free_suballoc_bits( + (unsigned long long)OCFS2_I(alloc_inode)->ip_blkno, + (unsigned long long)bg_blkno, + start_bit, count); status = ocfs2_read_group_descriptor(alloc_inode, fe, bg_blkno, &group_bh); @@ -2560,10 +2560,9 @@ static int _ocfs2_free_clusters(handle_t *handle, ocfs2_block_to_cluster_group(bitmap_inode, start_blk, &bg_blkno, &bg_start_bit); - mlog(0, "want to free %u clusters starting at block %llu\n", - num_clusters, (unsigned long long)start_blk); - mlog(0, "bg_blkno = %llu, bg_start_bit = %u\n", - (unsigned long long)bg_blkno, bg_start_bit); + trace_ocfs2_free_clusters((unsigned long long)bg_blkno, + (unsigned long long)start_blk, + bg_start_bit, num_clusters); status = _ocfs2_free_suballoc_bits(handle, bitmap_inode, bitmap_bh, bg_start_bit, bg_blkno, @@ -2748,7 +2747,7 @@ static int ocfs2_get_suballoc_slot_bit(struct ocfs2_super *osb, u64 blkno, struct buffer_head *inode_bh = NULL; struct ocfs2_dinode *inode_fe; - mlog(0, "blkno: %llu\n", (unsigned long long)blkno); + trace_ocfs2_get_suballoc_slot_bit((unsigned long long)blkno); /* dirty read disk */ status = ocfs2_read_blocks_sync(osb, blkno, 1, &inode_bh); @@ -2809,8 +2808,8 @@ static int ocfs2_test_suballoc_bit(struct ocfs2_super *osb, u64 bg_blkno; int status; - mlog(0, "blkno: %llu bit: %u\n", (unsigned long long)blkno, - (unsigned int)bit); + trace_ocfs2_test_suballoc_bit((unsigned long long)blkno, + (unsigned int)bit); alloc_di = (struct ocfs2_dinode *)alloc_bh->b_data; if ((bit + 1) > ocfs2_bits_per_group(&alloc_di->id2.i_chain)) { @@ -2863,7 +2862,7 @@ int ocfs2_test_inode_bit(struct ocfs2_super *osb, u64 blkno, int *res) struct inode *inode_alloc_inode; struct buffer_head *alloc_bh = NULL; - mlog(0, "blkno: %llu", (unsigned long long)blkno); + trace_ocfs2_test_inode_bit((unsigned long long)blkno); status = ocfs2_get_suballoc_slot_bit(osb, blkno, &suballoc_slot, &group_blkno, &suballoc_bit); -- cgit From a5438702ee63b13710c497bb22c7952a7e5d6a52 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Tue, 22 Feb 2011 08:24:01 +0800 Subject: ocfs2: Remove mlog(0) from fs/ocfs2/suballoc.c This is the 4th step to remove the debug info of DISK_ALLOC. Signed-off-by: Tao Ma --- fs/ocfs2/ocfs2_trace.h | 10 ++++++++++ fs/ocfs2/resize.c | 12 +++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 11980ecba546..335edc50f132 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -590,6 +590,16 @@ DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_local_alloc_new_window_result); /* End of trace events for fs/ocfs2/localalloc.c. */ +/* Trace events for fs/ocfs2/resize.c. */ + +DEFINE_OCFS2_UINT_UINT_EVENT(ocfs2_update_last_group_and_inode); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_group_extend); + +DEFINE_OCFS2_ULL_UINT_UINT_UINT_EVENT(ocfs2_group_add); + +/* End of trace events for fs/ocfs2/resize.c. */ + /* Trace events for fs/ocfs2/suballoc.c. */ DEFINE_OCFS2_ULL_EVENT(ocfs2_validate_group_descriptor); diff --git a/fs/ocfs2/resize.c b/fs/ocfs2/resize.c index 76b37909a4a1..761d20da9dcd 100644 --- a/fs/ocfs2/resize.c +++ b/fs/ocfs2/resize.c @@ -39,6 +39,7 @@ #include "super.h" #include "sysfile.h" #include "uptodate.h" +#include "ocfs2_trace.h" #include "buffer_head_io.h" #include "suballoc.h" @@ -102,8 +103,8 @@ static int ocfs2_update_last_group_and_inode(handle_t *handle, u16 cl_bpc = le16_to_cpu(cl->cl_bpc); u16 cl_cpg = le16_to_cpu(cl->cl_cpg); - mlog(0, "(new_clusters=%d, first_new_cluster = %u)\n", - new_clusters, first_new_cluster); + trace_ocfs2_update_last_group_and_inode(new_clusters, + first_new_cluster); ret = ocfs2_journal_access_gd(handle, INODE_CACHE(bm_inode), group_bh, OCFS2_JOURNAL_ACCESS_WRITE); @@ -340,7 +341,8 @@ int ocfs2_group_extend(struct inode * inode, int new_clusters) goto out_unlock; } - mlog(0, "extend the last group at %llu, new clusters = %d\n", + + trace_ocfs2_group_extend( (unsigned long long)le64_to_cpu(group->bg_blkno), new_clusters); handle = ocfs2_start_trans(osb, OCFS2_GROUP_EXTEND_CREDITS); @@ -515,8 +517,8 @@ int ocfs2_group_add(struct inode *inode, struct ocfs2_new_group_input *input) goto out_unlock; } - mlog(0, "Add a new group %llu in chain = %u, length = %u\n", - (unsigned long long)input->group, input->chain, input->clusters); + trace_ocfs2_group_add((unsigned long long)input->group, + input->chain, input->clusters, input->frees); handle = ocfs2_start_trans(osb, OCFS2_GROUP_ADD_CREDITS); if (IS_ERR(handle)) { -- cgit From 81bad69749623062fae2f94e2d98dd43d95a36f4 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Tue, 22 Feb 2011 08:01:27 +0800 Subject: ocfs2: Remove DISK_ALLOC from masklog. Since all 4 files, localalloc.c, suballoc.c, alloc.c and resize.c, which use DISK_ALLOC are changed to trace events, Remove masklog DISK_ALLOC totally. Signed-off-by: Tao Ma --- fs/ocfs2/alloc.c | 1 - fs/ocfs2/cluster/masklog.c | 1 - fs/ocfs2/cluster/masklog.h | 1 - fs/ocfs2/localalloc.c | 1 - fs/ocfs2/resize.c | 1 - fs/ocfs2/suballoc.c | 1 - 6 files changed, 6 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index f0e26c4adc94..b27a0d86f8c5 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c @@ -30,7 +30,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_DISK_ALLOC #include #include "ocfs2.h" diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index fdc302ddafe8..caba07c2dac6 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -93,7 +93,6 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { define_mask(DLM_RECOVERY), define_mask(AIO), define_mask(JOURNAL), - define_mask(DISK_ALLOC), define_mask(SUPER), define_mask(FILE_IO), define_mask(EXTENT_MAP), diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index 51ee790c7678..155835a6b1c3 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -95,7 +95,6 @@ #define ML_DLM_RECOVERY 0x0000000000001000ULL /* dlm master functions */ #define ML_AIO 0x0000000000002000ULL /* ocfs2 aio read and write */ #define ML_JOURNAL 0x0000000000004000ULL /* ocfs2 journalling functions */ -#define ML_DISK_ALLOC 0x0000000000008000ULL /* ocfs2 disk allocation */ #define ML_SUPER 0x0000000000010000ULL /* ocfs2 mount / umount */ #define ML_FILE_IO 0x0000000000020000ULL /* ocfs2 file I/O */ #define ML_EXTENT_MAP 0x0000000000040000ULL /* ocfs2 extent map caching */ diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c index a311b1f658e2..210c35237548 100644 --- a/fs/ocfs2/localalloc.c +++ b/fs/ocfs2/localalloc.c @@ -29,7 +29,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_DISK_ALLOC #include #include "ocfs2.h" diff --git a/fs/ocfs2/resize.c b/fs/ocfs2/resize.c index 761d20da9dcd..ec55add7604a 100644 --- a/fs/ocfs2/resize.c +++ b/fs/ocfs2/resize.c @@ -27,7 +27,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_DISK_ALLOC #include #include "ocfs2.h" diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index 94342bd9800d..ab6e2061074f 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -29,7 +29,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_DISK_ALLOC #include #include "ocfs2.h" -- cgit From 198aac2838731691ca67e15fd8a56f65307d3677 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Tue, 22 Feb 2011 08:20:04 +0800 Subject: ocfs2: Remove masklog ML_REFCOUNT. Change all the "mlog(0," in fs/ocfs2/refcounttree.c to trace events. And finally remove masklog ML_REFCOUNT. Signed-off-by: Tao Ma --- fs/ocfs2/cluster/masklog.c | 1 - fs/ocfs2/cluster/masklog.h | 1 - fs/ocfs2/ocfs2_trace.h | 263 +++++++++++++++++++++++++++++++++++++++++++++ fs/ocfs2/refcounttree.c | 158 ++++++++++++++------------- 4 files changed, 341 insertions(+), 82 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index caba07c2dac6..a961cca12529 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -108,7 +108,6 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { define_mask(EXPORT), define_mask(XATTR), define_mask(QUOTA), - define_mask(REFCOUNT), define_mask(BASTS), define_mask(RESERVATIONS), define_mask(CLUSTER), diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index 155835a6b1c3..845ea2b02f0b 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -110,7 +110,6 @@ #define ML_EXPORT 0x0000000010000000ULL /* ocfs2 export operations */ #define ML_XATTR 0x0000000020000000ULL /* ocfs2 extended attributes */ #define ML_QUOTA 0x0000000040000000ULL /* ocfs2 quota operations */ -#define ML_REFCOUNT 0x0000000080000000ULL /* refcount tree operations */ #define ML_BASTS 0x0000000100000000ULL /* dlmglue asts and basts */ #define ML_RESERVATIONS 0x0000000200000000ULL /* ocfs2 alloc reservations */ #define ML_CLUSTER 0x0000000400000000ULL /* cluster stack */ diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 335edc50f132..a8b57ca7bdb5 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -133,6 +133,30 @@ DEFINE_EVENT(ocfs2__ull_ull, name, \ TP_PROTO(unsigned long long val1, unsigned long long val2), \ TP_ARGS(val1, val2)) +DECLARE_EVENT_CLASS(ocfs2__ull_ull_uint, + TP_PROTO(unsigned long long value1, + unsigned long long value2, unsigned int value3), + TP_ARGS(value1, value2, value3), + TP_STRUCT__entry( + __field(unsigned long long, value1) + __field(unsigned long long, value2) + __field(unsigned int, value3) + ), + TP_fast_assign( + __entry->value1 = value1; + __entry->value2 = value2; + __entry->value3 = value3; + ), + TP_printk("%llu %llu %u", + __entry->value1, __entry->value2, __entry->value3) +); + +#define DEFINE_OCFS2_ULL_ULL_UINT_EVENT(name) \ +DEFINE_EVENT(ocfs2__ull_ull_uint, name, \ + TP_PROTO(unsigned long long val1, \ + unsigned long long val2, unsigned int val3), \ + TP_ARGS(val1, val2, val3)) + DECLARE_EVENT_CLASS(ocfs2__ull_uint_uint, TP_PROTO(unsigned long long value1, unsigned int value2, unsigned int value3), @@ -705,6 +729,245 @@ DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_test_suballoc_bit); DEFINE_OCFS2_ULL_EVENT(ocfs2_test_inode_bit); /* End of trace events for fs/ocfs2/suballoc.c. */ + +/* Trace events for fs/ocfs2/refcounttree.c. */ + +DEFINE_OCFS2_ULL_EVENT(ocfs2_validate_refcount_block); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_purge_refcount_trees); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_create_refcount_tree); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_create_refcount_tree_blkno); + +DEFINE_OCFS2_ULL_INT_INT_INT_EVENT(ocfs2_change_refcount_rec); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_expand_inline_ref_root); + +DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_divide_leaf_refcount_block); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_new_leaf_refcount_block); + +DECLARE_EVENT_CLASS(ocfs2__refcount_tree_ops, + TP_PROTO(unsigned long long blkno, int index, + unsigned long long cpos, + unsigned int clusters, unsigned int refcount), + TP_ARGS(blkno, index, cpos, clusters, refcount), + TP_STRUCT__entry( + __field(unsigned long long, blkno) + __field(int, index) + __field(unsigned long long, cpos) + __field(unsigned int, clusters) + __field(unsigned int, refcount) + ), + TP_fast_assign( + __entry->blkno = blkno; + __entry->index = index; + __entry->cpos = cpos; + __entry->clusters = clusters; + __entry->refcount = refcount; + ), + TP_printk("%llu %d %llu %u %u", __entry->blkno, __entry->index, + __entry->cpos, __entry->clusters, __entry->refcount) +); + +#define DEFINE_OCFS2_REFCOUNT_TREE_OPS_EVENT(name) \ +DEFINE_EVENT(ocfs2__refcount_tree_ops, name, \ + TP_PROTO(unsigned long long blkno, int index, \ + unsigned long long cpos, \ + unsigned int count, unsigned int refcount), \ + TP_ARGS(blkno, index, cpos, count, refcount)) + +DEFINE_OCFS2_REFCOUNT_TREE_OPS_EVENT(ocfs2_insert_refcount_rec); + +TRACE_EVENT(ocfs2_split_refcount_rec, + TP_PROTO(unsigned long long cpos, + unsigned int clusters, unsigned int refcount, + unsigned long long split_cpos, + unsigned int split_clusters, unsigned int split_refcount), + TP_ARGS(cpos, clusters, refcount, + split_cpos, split_clusters, split_refcount), + TP_STRUCT__entry( + __field(unsigned long long, cpos) + __field(unsigned int, clusters) + __field(unsigned int, refcount) + __field(unsigned long long, split_cpos) + __field(unsigned int, split_clusters) + __field(unsigned int, split_refcount) + ), + TP_fast_assign( + __entry->cpos = cpos; + __entry->clusters = clusters; + __entry->refcount = refcount; + __entry->split_cpos = split_cpos; + __entry->split_clusters = split_clusters; + __entry->split_refcount = split_refcount; + ), + TP_printk("%llu %u %u %llu %u %u", + __entry->cpos, __entry->clusters, __entry->refcount, + __entry->split_cpos, __entry->split_clusters, + __entry->split_refcount) +); + +DEFINE_OCFS2_REFCOUNT_TREE_OPS_EVENT(ocfs2_split_refcount_rec_insert); + +DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_increase_refcount_begin); + +DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_increase_refcount_change); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_increase_refcount_insert); + +DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_increase_refcount_split); + +DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_remove_refcount_extent); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_restore_refcount_block); + +DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_decrease_refcount_rec); + +TRACE_EVENT(ocfs2_decrease_refcount, + TP_PROTO(unsigned long long owner, + unsigned long long cpos, + unsigned int len, int delete), + TP_ARGS(owner, cpos, len, delete), + TP_STRUCT__entry( + __field(unsigned long long, owner) + __field(unsigned long long, cpos) + __field(unsigned int, len) + __field(int, delete) + ), + TP_fast_assign( + __entry->owner = owner; + __entry->cpos = cpos; + __entry->len = len; + __entry->delete = delete; + ), + TP_printk("%llu %llu %u %d", + __entry->owner, __entry->cpos, __entry->len, __entry->delete) +); + +DEFINE_OCFS2_ULL_UINT_UINT_UINT_EVENT(ocfs2_mark_extent_refcounted); + +DEFINE_OCFS2_ULL_UINT_UINT_UINT_EVENT(ocfs2_calc_refcount_meta_credits); + +TRACE_EVENT(ocfs2_calc_refcount_meta_credits_iterate, + TP_PROTO(int recs_add, unsigned long long cpos, + unsigned int clusters, unsigned long long r_cpos, + unsigned int r_clusters, unsigned int refcount, int index), + TP_ARGS(recs_add, cpos, clusters, r_cpos, r_clusters, refcount, index), + TP_STRUCT__entry( + __field(int, recs_add) + __field(unsigned long long, cpos) + __field(unsigned int, clusters) + __field(unsigned long long, r_cpos) + __field(unsigned int, r_clusters) + __field(unsigned int, refcount) + __field(int, index) + ), + TP_fast_assign( + __entry->recs_add = recs_add; + __entry->cpos = cpos; + __entry->clusters = clusters; + __entry->r_cpos = r_cpos; + __entry->r_clusters = r_clusters; + __entry->refcount = refcount; + __entry->index = index; + ), + TP_printk("%d %llu %u %llu %u %u %d", + __entry->recs_add, __entry->cpos, __entry->clusters, + __entry->r_cpos, __entry->r_clusters, + __entry->refcount, __entry->index) +); + +DEFINE_OCFS2_INT_INT_EVENT(ocfs2_add_refcount_flag); + +DEFINE_OCFS2_INT_INT_EVENT(ocfs2_prepare_refcount_change_for_del); + +DEFINE_OCFS2_INT_INT_EVENT(ocfs2_lock_refcount_allocators); + +DEFINE_OCFS2_ULL_UINT_UINT_UINT_EVENT(ocfs2_duplicate_clusters_by_page); + +DEFINE_OCFS2_ULL_UINT_UINT_UINT_EVENT(ocfs2_duplicate_clusters_by_jbd); + +TRACE_EVENT(ocfs2_clear_ext_refcount, + TP_PROTO(unsigned long long ino, unsigned int cpos, + unsigned int len, unsigned int p_cluster, + unsigned int ext_flags), + TP_ARGS(ino, cpos, len, p_cluster, ext_flags), + TP_STRUCT__entry( + __field(unsigned long long, ino) + __field(unsigned int, cpos) + __field(unsigned int, len) + __field(unsigned int, p_cluster) + __field(unsigned int, ext_flags) + ), + TP_fast_assign( + __entry->ino = ino; + __entry->cpos = cpos; + __entry->len = len; + __entry->p_cluster = p_cluster; + __entry->ext_flags = ext_flags; + ), + TP_printk("%llu %u %u %u %u", + __entry->ino, __entry->cpos, __entry->len, + __entry->p_cluster, __entry->ext_flags) +); + +TRACE_EVENT(ocfs2_replace_clusters, + TP_PROTO(unsigned long long ino, unsigned int cpos, + unsigned int old, unsigned int new, unsigned int len, + unsigned int ext_flags), + TP_ARGS(ino, cpos, old, new, len, ext_flags), + TP_STRUCT__entry( + __field(unsigned long long, ino) + __field(unsigned int, cpos) + __field(unsigned int, old) + __field(unsigned int, new) + __field(unsigned int, len) + __field(unsigned int, ext_flags) + ), + TP_fast_assign( + __entry->ino = ino; + __entry->cpos = cpos; + __entry->old = old; + __entry->new = new; + __entry->len = len; + __entry->ext_flags = ext_flags; + ), + TP_printk("%llu %u %u %u %u %u", + __entry->ino, __entry->cpos, __entry->old, __entry->new, + __entry->len, __entry->ext_flags) +); + +DEFINE_OCFS2_ULL_UINT_UINT_UINT_EVENT(ocfs2_make_clusters_writable); + +TRACE_EVENT(ocfs2_refcount_cow_hunk, + TP_PROTO(unsigned long long ino, unsigned int cpos, + unsigned int write_len, unsigned int max_cpos, + unsigned int cow_start, unsigned int cow_len), + TP_ARGS(ino, cpos, write_len, max_cpos, cow_start, cow_len), + TP_STRUCT__entry( + __field(unsigned long long, ino) + __field(unsigned int, cpos) + __field(unsigned int, write_len) + __field(unsigned int, max_cpos) + __field(unsigned int, cow_start) + __field(unsigned int, cow_len) + ), + TP_fast_assign( + __entry->ino = ino; + __entry->cpos = cpos; + __entry->write_len = write_len; + __entry->max_cpos = max_cpos; + __entry->cow_start = cow_start; + __entry->cow_len = cow_len; + ), + TP_printk("%llu %u %u %u %u %u", + __entry->ino, __entry->cpos, __entry->write_len, + __entry->max_cpos, __entry->cow_start, __entry->cow_len) +); + +/* End of trace events for fs/ocfs2/refcounttree.c. */ #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c index 29623da133cc..93a81f853e66 100644 --- a/fs/ocfs2/refcounttree.c +++ b/fs/ocfs2/refcounttree.c @@ -16,7 +16,6 @@ */ #include -#define MLOG_MASK_PREFIX ML_REFCOUNT #include #include "ocfs2.h" #include "inode.h" @@ -34,6 +33,7 @@ #include "aops.h" #include "xattr.h" #include "namei.h" +#include "ocfs2_trace.h" #include #include @@ -84,8 +84,7 @@ static int ocfs2_validate_refcount_block(struct super_block *sb, struct ocfs2_refcount_block *rb = (struct ocfs2_refcount_block *)bh->b_data; - mlog(0, "Validating refcount block %llu\n", - (unsigned long long)bh->b_blocknr); + trace_ocfs2_validate_refcount_block((unsigned long long)bh->b_blocknr); BUG_ON(!buffer_uptodate(bh)); @@ -545,8 +544,8 @@ void ocfs2_purge_refcount_trees(struct ocfs2_super *osb) while ((node = rb_last(root)) != NULL) { tree = rb_entry(node, struct ocfs2_refcount_tree, rf_node); - mlog(0, "Purge tree %llu\n", - (unsigned long long) tree->rf_blkno); + trace_ocfs2_purge_refcount_trees( + (unsigned long long) tree->rf_blkno); rb_erase(&tree->rf_node, root); ocfs2_free_refcount_tree(tree); @@ -575,7 +574,8 @@ static int ocfs2_create_refcount_tree(struct inode *inode, BUG_ON(oi->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL); - mlog(0, "create tree for inode %lu\n", inode->i_ino); + trace_ocfs2_create_refcount_tree( + (unsigned long long)OCFS2_I(inode)->ip_blkno); ret = ocfs2_reserve_new_metadata_blocks(osb, 1, &meta_ac); if (ret) { @@ -646,8 +646,7 @@ static int ocfs2_create_refcount_tree(struct inode *inode, di->i_refcount_loc = cpu_to_le64(first_blkno); spin_unlock(&oi->ip_lock); - mlog(0, "created tree for inode %lu, refblock %llu\n", - inode->i_ino, (unsigned long long)first_blkno); + trace_ocfs2_create_refcount_tree_blkno((unsigned long long)first_blkno); ocfs2_journal_dirty(handle, di_bh); @@ -1256,8 +1255,9 @@ static int ocfs2_change_refcount_rec(handle_t *handle, goto out; } - mlog(0, "change index %d, old count %u, change %d\n", index, - le32_to_cpu(rec->r_refcount), change); + trace_ocfs2_change_refcount_rec( + (unsigned long long)ocfs2_metadata_cache_owner(ci), + index, le32_to_cpu(rec->r_refcount), change); le32_add_cpu(&rec->r_refcount, change); if (!rec->r_refcount) { @@ -1353,8 +1353,8 @@ static int ocfs2_expand_inline_ref_root(handle_t *handle, ocfs2_journal_dirty(handle, ref_root_bh); - mlog(0, "new leaf block %llu, used %u\n", (unsigned long long)blkno, - le16_to_cpu(new_rb->rf_records.rl_used)); + trace_ocfs2_expand_inline_ref_root((unsigned long long)blkno, + le16_to_cpu(new_rb->rf_records.rl_used)); *ref_leaf_bh = new_bh; new_bh = NULL; @@ -1466,9 +1466,9 @@ static int ocfs2_divide_leaf_refcount_block(struct buffer_head *ref_leaf_bh, (struct ocfs2_refcount_block *)new_bh->b_data; struct ocfs2_refcount_list *new_rl = &new_rb->rf_records; - mlog(0, "split old leaf refcount block %llu, count = %u, used = %u\n", - (unsigned long long)ref_leaf_bh->b_blocknr, - le32_to_cpu(rl->rl_count), le32_to_cpu(rl->rl_used)); + trace_ocfs2_divide_leaf_refcount_block( + (unsigned long long)ref_leaf_bh->b_blocknr, + le32_to_cpu(rl->rl_count), le32_to_cpu(rl->rl_used)); /* * XXX: Improvement later. @@ -1601,8 +1601,8 @@ static int ocfs2_new_leaf_refcount_block(handle_t *handle, ocfs2_init_refcount_extent_tree(&ref_et, ci, ref_root_bh); - mlog(0, "insert new leaf block %llu at %u\n", - (unsigned long long)new_bh->b_blocknr, new_cpos); + trace_ocfs2_new_leaf_refcount_block( + (unsigned long long)new_bh->b_blocknr, new_cpos); /* Insert the new leaf block with the specific offset cpos. */ ret = ocfs2_insert_extent(handle, &ref_et, new_cpos, new_bh->b_blocknr, @@ -1794,11 +1794,10 @@ static int ocfs2_insert_refcount_rec(handle_t *handle, (le16_to_cpu(rf_list->rl_used) - index) * sizeof(struct ocfs2_refcount_rec)); - mlog(0, "insert refcount record start %llu, len %u, count %u " - "to leaf block %llu at index %d\n", - (unsigned long long)le64_to_cpu(rec->r_cpos), - le32_to_cpu(rec->r_clusters), le32_to_cpu(rec->r_refcount), - (unsigned long long)ref_leaf_bh->b_blocknr, index); + trace_ocfs2_insert_refcount_rec( + (unsigned long long)ref_leaf_bh->b_blocknr, index, + (unsigned long long)le64_to_cpu(rec->r_cpos), + le32_to_cpu(rec->r_clusters), le32_to_cpu(rec->r_refcount)); rf_list->rl_recs[index] = *rec; @@ -1850,10 +1849,12 @@ static int ocfs2_split_refcount_rec(handle_t *handle, BUG_ON(le32_to_cpu(rb->rf_flags) & OCFS2_REFCOUNT_TREE_FL); - mlog(0, "original r_pos %llu, cluster %u, split %llu, cluster %u\n", - le64_to_cpu(orig_rec->r_cpos), le32_to_cpu(orig_rec->r_clusters), - le64_to_cpu(split_rec->r_cpos), - le32_to_cpu(split_rec->r_clusters)); + trace_ocfs2_split_refcount_rec(le64_to_cpu(orig_rec->r_cpos), + le32_to_cpu(orig_rec->r_clusters), + le32_to_cpu(orig_rec->r_refcount), + le64_to_cpu(split_rec->r_cpos), + le32_to_cpu(split_rec->r_clusters), + le32_to_cpu(split_rec->r_refcount)); /* * If we just need to split the header or tail clusters, @@ -1967,12 +1968,11 @@ static int ocfs2_split_refcount_rec(handle_t *handle, if (split_rec->r_refcount) { rf_list->rl_recs[index] = *split_rec; - mlog(0, "insert refcount record start %llu, len %u, count %u " - "to leaf block %llu at index %d\n", - (unsigned long long)le64_to_cpu(split_rec->r_cpos), - le32_to_cpu(split_rec->r_clusters), - le32_to_cpu(split_rec->r_refcount), - (unsigned long long)ref_leaf_bh->b_blocknr, index); + trace_ocfs2_split_refcount_rec_insert( + (unsigned long long)ref_leaf_bh->b_blocknr, index, + (unsigned long long)le64_to_cpu(split_rec->r_cpos), + le32_to_cpu(split_rec->r_clusters), + le32_to_cpu(split_rec->r_refcount)); if (merge) ocfs2_refcount_rec_merge(rb, index); @@ -1997,7 +1997,7 @@ static int __ocfs2_increase_refcount(handle_t *handle, struct ocfs2_refcount_rec rec; unsigned int set_len = 0; - mlog(0, "Tree owner %llu, add refcount start %llu, len %u\n", + trace_ocfs2_increase_refcount_begin( (unsigned long long)ocfs2_metadata_cache_owner(ci), (unsigned long long)cpos, len); @@ -2024,9 +2024,9 @@ static int __ocfs2_increase_refcount(handle_t *handle, */ if (rec.r_refcount && le64_to_cpu(rec.r_cpos) == cpos && set_len <= len) { - mlog(0, "increase refcount rec, start %llu, len %u, " - "count %u\n", (unsigned long long)cpos, set_len, - le32_to_cpu(rec.r_refcount)); + trace_ocfs2_increase_refcount_change( + (unsigned long long)cpos, set_len, + le32_to_cpu(rec.r_refcount)); ret = ocfs2_change_refcount_rec(handle, ci, ref_leaf_bh, index, merge, 1); @@ -2037,7 +2037,7 @@ static int __ocfs2_increase_refcount(handle_t *handle, } else if (!rec.r_refcount) { rec.r_refcount = cpu_to_le32(1); - mlog(0, "insert refcount rec, start %llu, len %u\n", + trace_ocfs2_increase_refcount_insert( (unsigned long long)le64_to_cpu(rec.r_cpos), set_len); ret = ocfs2_insert_refcount_rec(handle, ci, ref_root_bh, @@ -2055,8 +2055,7 @@ static int __ocfs2_increase_refcount(handle_t *handle, rec.r_clusters = cpu_to_le32(set_len); le32_add_cpu(&rec.r_refcount, 1); - mlog(0, "split refcount rec, start %llu, " - "len %u, count %u\n", + trace_ocfs2_increase_refcount_split( (unsigned long long)le64_to_cpu(rec.r_cpos), set_len, le32_to_cpu(rec.r_refcount)); ret = ocfs2_split_refcount_rec(handle, ci, @@ -2095,6 +2094,11 @@ static int ocfs2_remove_refcount_extent(handle_t *handle, BUG_ON(rb->rf_records.rl_used); + trace_ocfs2_remove_refcount_extent( + (unsigned long long)ocfs2_metadata_cache_owner(ci), + (unsigned long long)ref_leaf_bh->b_blocknr, + le32_to_cpu(rb->rf_cpos)); + ocfs2_init_refcount_extent_tree(&et, ci, ref_root_bh); ret = ocfs2_remove_extent(handle, &et, le32_to_cpu(rb->rf_cpos), 1, meta_ac, dealloc); @@ -2137,7 +2141,7 @@ static int ocfs2_remove_refcount_extent(handle_t *handle, if (!rb->rf_list.l_next_free_rec) { BUG_ON(rb->rf_clusters); - mlog(0, "reset refcount tree root %llu to be a record block.\n", + trace_ocfs2_restore_refcount_block( (unsigned long long)ref_root_bh->b_blocknr); rb->rf_flags = 0; @@ -2184,6 +2188,10 @@ static int ocfs2_decrease_refcount_rec(handle_t *handle, BUG_ON(cpos + len > le64_to_cpu(rec->r_cpos) + le32_to_cpu(rec->r_clusters)); + trace_ocfs2_decrease_refcount_rec( + (unsigned long long)ocfs2_metadata_cache_owner(ci), + (unsigned long long)cpos, len); + if (cpos == le64_to_cpu(rec->r_cpos) && len == le32_to_cpu(rec->r_clusters)) ret = ocfs2_change_refcount_rec(handle, ci, @@ -2195,12 +2203,6 @@ static int ocfs2_decrease_refcount_rec(handle_t *handle, le32_add_cpu(&split.r_refcount, -1); - mlog(0, "split refcount rec, start %llu, " - "len %u, count %u, original start %llu, len %u\n", - (unsigned long long)le64_to_cpu(split.r_cpos), - len, le32_to_cpu(split.r_refcount), - (unsigned long long)le64_to_cpu(rec->r_cpos), - le32_to_cpu(rec->r_clusters)); ret = ocfs2_split_refcount_rec(handle, ci, ref_root_bh, ref_leaf_bh, &split, index, 1, @@ -2239,10 +2241,9 @@ static int __ocfs2_decrease_refcount(handle_t *handle, struct super_block *sb = ocfs2_metadata_cache_get_super(ci); struct buffer_head *ref_leaf_bh = NULL; - mlog(0, "Tree owner %llu, decrease refcount start %llu, " - "len %u, delete %u\n", - (unsigned long long)ocfs2_metadata_cache_owner(ci), - (unsigned long long)cpos, len, delete); + trace_ocfs2_decrease_refcount( + (unsigned long long)ocfs2_metadata_cache_owner(ci), + (unsigned long long)cpos, len, delete); while (len) { ret = ocfs2_get_refcount_rec(ci, ref_root_bh, @@ -2352,8 +2353,8 @@ static int ocfs2_mark_extent_refcounted(struct inode *inode, { int ret; - mlog(0, "Inode %lu refcount tree cpos %u, len %u, phys cluster %u\n", - inode->i_ino, cpos, len, phys); + trace_ocfs2_mark_extent_refcounted(OCFS2_I(inode)->ip_blkno, + cpos, len, phys); if (!ocfs2_refcount_tree(OCFS2_SB(inode->i_sb))) { ocfs2_error(inode->i_sb, "Inode %lu want to use refcount " @@ -2392,8 +2393,6 @@ static int ocfs2_calc_refcount_meta_credits(struct super_block *sb, struct buffer_head *ref_leaf_bh = NULL, *prev_bh = NULL; u32 len; - mlog(0, "start_cpos %llu, clusters %u\n", - (unsigned long long)start_cpos, clusters); while (clusters) { ret = ocfs2_get_refcount_rec(ci, ref_root_bh, cpos, clusters, &rec, @@ -2427,12 +2426,11 @@ static int ocfs2_calc_refcount_meta_credits(struct super_block *sb, rb = (struct ocfs2_refcount_block *)ref_leaf_bh->b_data; - mlog(0, "recs_add %d,cpos %llu, clusters %u, rec->r_cpos %llu," - "rec->r_clusters %u, rec->r_refcount %u, index %d\n", - recs_add, (unsigned long long)cpos, clusters, - (unsigned long long)le64_to_cpu(rec.r_cpos), - le32_to_cpu(rec.r_clusters), - le32_to_cpu(rec.r_refcount), index); + trace_ocfs2_calc_refcount_meta_credits_iterate( + recs_add, (unsigned long long)cpos, clusters, + (unsigned long long)le64_to_cpu(rec.r_cpos), + le32_to_cpu(rec.r_clusters), + le32_to_cpu(rec.r_refcount), index); len = min((u64)cpos + clusters, le64_to_cpu(rec.r_cpos) + le32_to_cpu(rec.r_clusters)) - cpos; @@ -2488,7 +2486,6 @@ static int ocfs2_calc_refcount_meta_credits(struct super_block *sb, if (!ref_blocks) goto out; - mlog(0, "we need ref_blocks %d\n", ref_blocks); *meta_add += ref_blocks; *credits += ref_blocks; @@ -2514,6 +2511,10 @@ static int ocfs2_calc_refcount_meta_credits(struct super_block *sb, } out: + + trace_ocfs2_calc_refcount_meta_credits( + (unsigned long long)start_cpos, clusters, + *meta_add, *credits); brelse(ref_leaf_bh); brelse(prev_bh); return ret; @@ -2578,8 +2579,7 @@ int ocfs2_prepare_refcount_change_for_del(struct inode *inode, goto out; } - mlog(0, "reserve new metadata %d blocks, credits = %d\n", - *ref_blocks, *credits); + trace_ocfs2_prepare_refcount_change_for_del(*ref_blocks, *credits); out: brelse(ref_root_bh); @@ -2886,8 +2886,7 @@ static int ocfs2_lock_refcount_allocators(struct super_block *sb, goto out; } - mlog(0, "reserve new metadata %d, clusters %u, credits = %d\n", - meta_add, num_clusters, *credits); + trace_ocfs2_lock_refcount_allocators(meta_add, *credits); ret = ocfs2_reserve_new_metadata_blocks(OCFS2_SB(sb), meta_add, meta_ac); if (ret) { @@ -2937,8 +2936,8 @@ static int ocfs2_duplicate_clusters_by_page(handle_t *handle, loff_t offset, end, map_end; struct address_space *mapping = context->inode->i_mapping; - mlog(0, "old_cluster %u, new %u, len %u at offset %u\n", old_cluster, - new_cluster, new_len, cpos); + trace_ocfs2_duplicate_clusters_by_page(cpos, old_cluster, + new_cluster, new_len); readahead_pages = (ocfs2_cow_contig_clusters(sb) << @@ -3031,8 +3030,8 @@ static int ocfs2_duplicate_clusters_by_jbd(handle_t *handle, struct buffer_head *old_bh = NULL; struct buffer_head *new_bh = NULL; - mlog(0, "old_cluster %u, new %u, len %u\n", old_cluster, - new_cluster, new_len); + trace_ocfs2_duplicate_clusters_by_page(cpos, old_cluster, + new_cluster, new_len); for (i = 0; i < blocks; i++, old_block++, new_block++) { new_bh = sb_getblk(osb->sb, new_block); @@ -3085,8 +3084,8 @@ static int ocfs2_clear_ext_refcount(handle_t *handle, struct super_block *sb = ocfs2_metadata_cache_get_super(et->et_ci); u64 ino = ocfs2_metadata_cache_owner(et->et_ci); - mlog(0, "inode %llu cpos %u, len %u, p_cluster %u, ext_flags %u\n", - (unsigned long long)ino, cpos, len, p_cluster, ext_flags); + trace_ocfs2_clear_ext_refcount((unsigned long long)ino, + cpos, len, p_cluster, ext_flags); memset(&replace_rec, 0, sizeof(replace_rec)); replace_rec.e_cpos = cpu_to_le32(cpos); @@ -3141,8 +3140,8 @@ static int ocfs2_replace_clusters(handle_t *handle, struct ocfs2_caching_info *ci = context->data_et.et_ci; u64 ino = ocfs2_metadata_cache_owner(ci); - mlog(0, "inode %llu, cpos %u, old %u, new %u, len %u, ext_flags %u\n", - (unsigned long long)ino, cpos, old, new, len, ext_flags); + trace_ocfs2_replace_clusters((unsigned long long)ino, + cpos, old, new, len, ext_flags); /*If the old clusters is unwritten, no need to duplicate. */ if (!(ext_flags & OCFS2_EXT_UNWRITTEN)) { @@ -3236,8 +3235,8 @@ static int ocfs2_make_clusters_writable(struct super_block *sb, struct ocfs2_caching_info *ref_ci = &context->ref_tree->rf_ci; struct ocfs2_refcount_rec rec; - mlog(0, "cpos %u, p_cluster %u, num_clusters %u, e_flags %u\n", - cpos, p_cluster, num_clusters, e_flags); + trace_ocfs2_make_clusters_writable(cpos, p_cluster, + num_clusters, e_flags); ret = ocfs2_lock_refcount_allocators(sb, p_cluster, num_clusters, &context->data_et, @@ -3475,9 +3474,9 @@ static int ocfs2_refcount_cow_hunk(struct inode *inode, goto out; } - mlog(0, "CoW inode %lu, cpos %u, write_len %u, cow_start %u, " - "cow_len %u\n", inode->i_ino, - cpos, write_len, cow_start, cow_len); + trace_ocfs2_refcount_cow_hunk(OCFS2_I(inode)->ip_blkno, + cpos, write_len, max_cpos, + cow_start, cow_len); BUG_ON(cow_len == 0); @@ -3756,8 +3755,7 @@ int ocfs2_add_refcount_flag(struct inode *inode, goto out; } - mlog(0, "reserve new metadata %d, credits = %d\n", - ref_blocks, credits); + trace_ocfs2_add_refcount_flag(ref_blocks, credits); if (ref_blocks) { ret = ocfs2_reserve_new_metadata_blocks(OCFS2_SB(inode->i_sb), -- cgit From 9558156bcf8e4750d20034e941213273743ed86a Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Tue, 22 Feb 2011 21:33:59 +0800 Subject: ocfs2: Remove mlog(0) from fs/ocfs2/aops.c Remove all the "mlog(0," in fs/ocfs2/aops.c. Signed-off-by: Tao Ma --- fs/ocfs2/aops.c | 55 +++++++++++----------- fs/ocfs2/ocfs2_trace.h | 124 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 153 insertions(+), 26 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 9551518be435..0d44b7701844 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -29,7 +29,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_FILE_IO #include #include "ocfs2.h" @@ -45,6 +44,7 @@ #include "super.h" #include "symlink.h" #include "refcounttree.h" +#include "ocfs2_trace.h" #include "buffer_head_io.h" @@ -59,8 +59,9 @@ static int ocfs2_symlink_get_block(struct inode *inode, sector_t iblock, struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); void *kaddr; - mlog(0, "(0x%p, %llu, 0x%p, %d)\n", inode, - (unsigned long long)iblock, bh_result, create); + trace_ocfs2_symlink_get_block( + (unsigned long long)OCFS2_I(inode)->ip_blkno, + (unsigned long long)iblock, bh_result, create); BUG_ON(ocfs2_inode_is_fast_symlink(inode)); @@ -135,8 +136,8 @@ int ocfs2_get_block(struct inode *inode, sector_t iblock, u64 p_blkno, count, past_eof; struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - mlog(0, "(0x%p, %llu, 0x%p, %d)\n", inode, - (unsigned long long)iblock, bh_result, create); + trace_ocfs2_get_block((unsigned long long)OCFS2_I(inode)->ip_blkno, + (unsigned long long)iblock, bh_result, create); if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_SYSTEM_FILE) mlog(ML_NOTICE, "get_block on system inode 0x%p (%lu)\n", @@ -198,8 +199,9 @@ int ocfs2_get_block(struct inode *inode, sector_t iblock, } past_eof = ocfs2_blocks_for_bytes(inode->i_sb, i_size_read(inode)); - mlog(0, "Inode %lu, past_eof = %llu\n", inode->i_ino, - (unsigned long long)past_eof); + + trace_ocfs2_get_block_end((unsigned long long)OCFS2_I(inode)->ip_blkno, + (unsigned long long)past_eof); if (create && (iblock >= past_eof)) set_buffer_new(bh_result); @@ -276,7 +278,8 @@ static int ocfs2_readpage(struct file *file, struct page *page) loff_t start = (loff_t)page->index << PAGE_CACHE_SHIFT; int ret, unlock = 1; - mlog(0, "(0x%p, %lu)\n", file, (page ? page->index : 0)); + trace_ocfs2_readpage((unsigned long long)oi->ip_blkno, + (page ? page->index : 0)); ret = ocfs2_inode_lock_with_page(inode, NULL, 0, page); if (ret != 0) { @@ -393,13 +396,11 @@ out_unlock: */ static int ocfs2_writepage(struct page *page, struct writeback_control *wbc) { - int ret; - - mlog(0, "(0x%p)\n", page); - - ret = block_write_full_page(page, ocfs2_get_block, wbc); + trace_ocfs2_writepage( + (unsigned long long)OCFS2_I(page->mapping->host)->ip_blkno, + page->index); - return ret; + return block_write_full_page(page, ocfs2_get_block, wbc); } /* Taken from ext3. We don't necessarily need the full blown @@ -445,7 +446,8 @@ static sector_t ocfs2_bmap(struct address_space *mapping, sector_t block) int err = 0; struct inode *inode = mapping->host; - mlog(0, "(block = %llu)\n", (unsigned long long)block); + trace_ocfs2_bmap((unsigned long long)OCFS2_I(inode)->ip_blkno, + (unsigned long long)block); /* We don't need to lock journal system files, since they aren't * accessed concurrently from multiple nodes. @@ -1521,9 +1523,9 @@ static int ocfs2_try_to_write_inline_data(struct address_space *mapping, struct ocfs2_inode_info *oi = OCFS2_I(inode); struct ocfs2_dinode *di = NULL; - mlog(0, "Inode %llu, write of %u bytes at off %llu. features: 0x%x\n", - (unsigned long long)oi->ip_blkno, len, (unsigned long long)pos, - oi->ip_dyn_features); + trace_ocfs2_try_to_write_inline_data((unsigned long long)oi->ip_blkno, + len, (unsigned long long)pos, + oi->ip_dyn_features); /* * Handle inodes which already have inline data 1st. @@ -1726,6 +1728,13 @@ try_again: di = (struct ocfs2_dinode *)wc->w_di_bh->b_data; + trace_ocfs2_write_begin_nolock( + (unsigned long long)OCFS2_I(inode)->ip_blkno, + (long long)i_size_read(inode), + le32_to_cpu(di->i_clusters), + pos, len, flags, mmap_page, + clusters_to_alloc, extents_to_split); + /* * We set w_target_from, w_target_to here so that * ocfs2_write_end() knows which range in the target page to @@ -1738,12 +1747,6 @@ try_again: * ocfs2_lock_allocators(). It greatly over-estimates * the work to be done. */ - mlog(0, "extend inode %llu, i_size = %lld, di->i_clusters = %u," - " clusters_to_add = %u, extents_to_split = %u\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno, - (long long)i_size_read(inode), le32_to_cpu(di->i_clusters), - clusters_to_alloc, extents_to_split); - ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(inode), wc->w_di_bh); ret = ocfs2_lock_allocators(inode, &et, @@ -1925,8 +1928,8 @@ static void ocfs2_write_end_inline(struct inode *inode, loff_t pos, memcpy(di->id2.i_data.id_data + pos, kaddr + pos, *copied); kunmap_atomic(kaddr, KM_USER0); - mlog(0, "Data written to inode at offset %llu. " - "id_count = %u, copied = %u, i_dyn_features = 0x%x\n", + trace_ocfs2_write_end_inline( + (unsigned long long)OCFS2_I(inode)->ip_blkno, (unsigned long long)pos, *copied, le16_to_cpu(di->id2.i_data.id_count), le16_to_cpu(di->i_dyn_features)); diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index a8b57ca7bdb5..5958da57f8ff 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -968,6 +968,130 @@ TRACE_EVENT(ocfs2_refcount_cow_hunk, ); /* End of trace events for fs/ocfs2/refcounttree.c. */ + +/* Trace events for fs/ocfs2/aops.c. */ + +DECLARE_EVENT_CLASS(ocfs2__get_block, + TP_PROTO(unsigned long long ino, unsigned long long iblock, + void *bh_result, int create), + TP_ARGS(ino, iblock, bh_result, create), + TP_STRUCT__entry( + __field(unsigned long long, ino) + __field(unsigned long long, iblock) + __field(void *, bh_result) + __field(int, create) + ), + TP_fast_assign( + __entry->ino = ino; + __entry->iblock = iblock; + __entry->bh_result = bh_result; + __entry->create = create; + ), + TP_printk("%llu %llu %p %d", + __entry->ino, __entry->iblock, + __entry->bh_result, __entry->create) +); + +#define DEFINE_OCFS2_GET_BLOCK_EVENT(name) \ +DEFINE_EVENT(ocfs2__get_block, name, \ + TP_PROTO(unsigned long long ino, unsigned long long iblock, \ + void *bh_result, int create), \ + TP_ARGS(ino, iblock, bh_result, create)) + +DEFINE_OCFS2_GET_BLOCK_EVENT(ocfs2_symlink_get_block); + +DEFINE_OCFS2_GET_BLOCK_EVENT(ocfs2_get_block); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_get_block_end); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_readpage); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_writepage); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_bmap); + +TRACE_EVENT(ocfs2_try_to_write_inline_data, + TP_PROTO(unsigned long long ino, unsigned int len, + unsigned long long pos, unsigned int flags), + TP_ARGS(ino, len, pos, flags), + TP_STRUCT__entry( + __field(unsigned long long, ino) + __field(unsigned int, len) + __field(unsigned long long, pos) + __field(unsigned int, flags) + ), + TP_fast_assign( + __entry->ino = ino; + __entry->len = len; + __entry->pos = pos; + __entry->flags = flags; + ), + TP_printk("%llu %u %llu 0x%x", + __entry->ino, __entry->len, __entry->pos, __entry->flags) +); + +TRACE_EVENT(ocfs2_write_begin_nolock, + TP_PROTO(unsigned long long ino, + long long i_size, unsigned int i_clusters, + unsigned long long pos, unsigned int len, + unsigned int flags, void *page, + unsigned int clusters, unsigned int extents_to_split), + TP_ARGS(ino, i_size, i_clusters, pos, len, flags, + page, clusters, extents_to_split), + TP_STRUCT__entry( + __field(unsigned long long, ino) + __field(long long, i_size) + __field(unsigned int, i_clusters) + __field(unsigned long long, pos) + __field(unsigned int, len) + __field(unsigned int, flags) + __field(void *, page) + __field(unsigned int, clusters) + __field(unsigned int, extents_to_split) + ), + TP_fast_assign( + __entry->ino = ino; + __entry->i_size = i_size; + __entry->i_clusters = i_clusters; + __entry->pos = pos; + __entry->len = len; + __entry->flags = flags; + __entry->page = page; + __entry->clusters = clusters; + __entry->extents_to_split = extents_to_split; + ), + TP_printk("%llu %lld %u %llu %u %u %p %u %u", + __entry->ino, __entry->i_size, __entry->i_clusters, + __entry->pos, __entry->len, + __entry->flags, __entry->page, __entry->clusters, + __entry->extents_to_split) +); + +TRACE_EVENT(ocfs2_write_end_inline, + TP_PROTO(unsigned long long ino, + unsigned long long pos, unsigned int copied, + unsigned int id_count, unsigned int features), + TP_ARGS(ino, pos, copied, id_count, features), + TP_STRUCT__entry( + __field(unsigned long long, ino) + __field(unsigned long long, pos) + __field(unsigned int, copied) + __field(unsigned int, id_count) + __field(unsigned int, features) + ), + TP_fast_assign( + __entry->ino = ino; + __entry->pos = pos; + __entry->copied = copied; + __entry->id_count = id_count; + __entry->features = features; + ), + TP_printk("%llu %llu %u %u %u", + __entry->ino, __entry->pos, __entry->copied, + __entry->id_count, __entry->features) +); + +/* End of trace events for fs/ocfs2/aops.c. */ #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ -- cgit From 614a9e849ca6ea24843795251cb30af525d5336b Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Tue, 22 Feb 2011 21:59:46 +0800 Subject: ocfs2: Remove FILE_IO from masklog. Change all the "mlog(0," in fs/ocfs2/mmap.c to trace events. And finally remove masklog FILE_IO. Signed-off-by: Tao Ma --- fs/ocfs2/cluster/masklog.c | 1 - fs/ocfs2/cluster/masklog.h | 1 - fs/ocfs2/mmap.c | 7 +++---- fs/ocfs2/ocfs2_trace.h | 25 +++++++++++++++++++++++++ 4 files changed, 28 insertions(+), 6 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index a961cca12529..036e8b8814f7 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -94,7 +94,6 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { define_mask(AIO), define_mask(JOURNAL), define_mask(SUPER), - define_mask(FILE_IO), define_mask(EXTENT_MAP), define_mask(DLM_GLUE), define_mask(BH_IO), diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index 845ea2b02f0b..d07780ab9f8f 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -96,7 +96,6 @@ #define ML_AIO 0x0000000000002000ULL /* ocfs2 aio read and write */ #define ML_JOURNAL 0x0000000000004000ULL /* ocfs2 journalling functions */ #define ML_SUPER 0x0000000000010000ULL /* ocfs2 mount / umount */ -#define ML_FILE_IO 0x0000000000020000ULL /* ocfs2 file I/O */ #define ML_EXTENT_MAP 0x0000000000040000ULL /* ocfs2 extent map caching */ #define ML_DLM_GLUE 0x0000000000080000ULL /* ocfs2 dlm glue layer */ #define ML_BH_IO 0x0000000000100000ULL /* ocfs2 buffer I/O */ diff --git a/fs/ocfs2/mmap.c b/fs/ocfs2/mmap.c index 49730b51ae45..3e9393ca39eb 100644 --- a/fs/ocfs2/mmap.c +++ b/fs/ocfs2/mmap.c @@ -31,7 +31,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_FILE_IO #include #include "ocfs2.h" @@ -42,6 +41,7 @@ #include "inode.h" #include "mmap.h" #include "super.h" +#include "ocfs2_trace.h" static int ocfs2_fault(struct vm_area_struct *area, struct vm_fault *vmf) @@ -49,13 +49,12 @@ static int ocfs2_fault(struct vm_area_struct *area, struct vm_fault *vmf) sigset_t oldset; int ret; - mlog(0, "(area=%p, page offset=%lu)\n", area, vmf->pgoff); - ocfs2_block_signals(&oldset); ret = filemap_fault(area, vmf); ocfs2_unblock_signals(&oldset); - mlog(0, "%p\n", vmf->page); + trace_ocfs2_fault(OCFS2_I(area->vm_file->f_mapping->host)->ip_blkno, + area, vmf->page, vmf->pgoff); return ret; } diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 5958da57f8ff..77148e7a14f8 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -1092,6 +1092,31 @@ TRACE_EVENT(ocfs2_write_end_inline, ); /* End of trace events for fs/ocfs2/aops.c. */ + +/* Trace events for fs/ocfs2/mmap.c. */ + +TRACE_EVENT(ocfs2_fault, + TP_PROTO(unsigned long long ino, + void *area, void *page, unsigned long pgoff), + TP_ARGS(ino, area, page, pgoff), + TP_STRUCT__entry( + __field(unsigned long long, ino) + __field(void *, area) + __field(void *, page) + __field(unsigned long, pgoff) + ), + TP_fast_assign( + __entry->ino = ino; + __entry->area = area; + __entry->page = page; + __entry->pgoff = pgoff; + ), + TP_printk("%llu %p %p %lu", + __entry->ino, __entry->area, __entry->page, __entry->pgoff) +); + +/* End of trace events for fs/ocfs2/mmap.c. */ + #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ -- cgit From da561c9cfa3022f6134ef52686d52931d3d1df3d Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Mon, 21 Feb 2011 11:18:23 +0800 Subject: ocfs2: remove INODE from unused files. As there are no such debug information in fs/ocfs2/ioctl.c, fs/ocfs2/locks.c and fs/ocfs2/sysfile.c, ML_INODE are also removed. Signed-off-by: Tao Ma --- fs/ocfs2/acl.c | 1 - fs/ocfs2/ioctl.c | 1 - fs/ocfs2/locks.c | 1 - 3 files changed, 3 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c index 704f6b1742f3..69786e3eb43c 100644 --- a/fs/ocfs2/acl.c +++ b/fs/ocfs2/acl.c @@ -24,7 +24,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_INODE #include #include "ocfs2.h" diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c index b4f51e94c8f5..d9bfa904d006 100644 --- a/fs/ocfs2/ioctl.c +++ b/fs/ocfs2/ioctl.c @@ -9,7 +9,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_INODE #include #include "ocfs2.h" diff --git a/fs/ocfs2/locks.c b/fs/ocfs2/locks.c index b5cb3ede9408..e57c804069ea 100644 --- a/fs/ocfs2/locks.c +++ b/fs/ocfs2/locks.c @@ -26,7 +26,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_INODE #include #include "ocfs2.h" -- cgit From 468eedde23d6c9335935773f4f5764267d5a7763 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Tue, 22 Feb 2011 22:14:41 +0800 Subject: ocfs2: Remove mlog(0) from fs/ocfs2/file.c This is the 2nd step to remove the debug info of INODE. Signed-off-by: Tao Ma --- fs/ocfs2/file.c | 190 +++++++++++++++++++-------------------- fs/ocfs2/ocfs2_trace.h | 237 +++++++++++++++++++++++++++++++++++++++++++++++++ fs/ocfs2/sysfile.c | 1 - 3 files changed, 330 insertions(+), 98 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 1e1a93aa0526..41565ae52856 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -38,7 +38,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_INODE #include #include "ocfs2.h" @@ -61,6 +60,7 @@ #include "acl.h" #include "quota.h" #include "refcounttree.h" +#include "ocfs2_trace.h" #include "buffer_head_io.h" @@ -99,8 +99,10 @@ static int ocfs2_file_open(struct inode *inode, struct file *file) int mode = file->f_flags; struct ocfs2_inode_info *oi = OCFS2_I(inode); - mlog(0, "(0x%p, 0x%p, '%.*s')\n", inode, file, - file->f_path.dentry->d_name.len, file->f_path.dentry->d_name.name); + trace_ocfs2_file_open(inode, file, file->f_path.dentry, + (unsigned long long)OCFS2_I(inode)->ip_blkno, + file->f_path.dentry->d_name.len, + file->f_path.dentry->d_name.name, mode); if (file->f_mode & FMODE_WRITE) dquot_initialize(inode); @@ -142,13 +144,15 @@ static int ocfs2_file_release(struct inode *inode, struct file *file) { struct ocfs2_inode_info *oi = OCFS2_I(inode); - mlog(0, "(0x%p, 0x%p, '%.*s')\n", inode, file, - file->f_path.dentry->d_name.len, - file->f_path.dentry->d_name.name); - spin_lock(&oi->ip_lock); if (!--oi->ip_open_count) oi->ip_flags &= ~OCFS2_INODE_OPEN_DIRECT; + + trace_ocfs2_file_release(inode, file, file->f_path.dentry, + oi->ip_blkno, + file->f_path.dentry->d_name.len, + file->f_path.dentry->d_name.name, + oi->ip_open_count); spin_unlock(&oi->ip_lock); ocfs2_free_file_private(inode, file); @@ -174,9 +178,11 @@ static int ocfs2_sync_file(struct file *file, int datasync) struct inode *inode = file->f_mapping->host; struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - mlog(0, "(0x%p, %d, 0x%p, '%.*s')\n", file, datasync, - file->f_path.dentry, file->f_path.dentry->d_name.len, - file->f_path.dentry->d_name.name); + trace_ocfs2_sync_file(inode, file, file->f_path.dentry, + OCFS2_I(inode)->ip_blkno, + file->f_path.dentry->d_name.len, + file->f_path.dentry->d_name.name, + (unsigned long long)datasync); if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) { /* @@ -431,14 +437,14 @@ static int ocfs2_truncate_file(struct inode *inode, struct ocfs2_dinode *fe = NULL; struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - mlog(0, "(inode = %llu, new_i_size = %llu\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno, - (unsigned long long)new_i_size); - /* We trust di_bh because it comes from ocfs2_inode_lock(), which * already validated it */ fe = (struct ocfs2_dinode *) di_bh->b_data; + trace_ocfs2_truncate_file((unsigned long long)OCFS2_I(inode)->ip_blkno, + (unsigned long long)le64_to_cpu(fe->i_size), + (unsigned long long)new_i_size); + mlog_bug_on_msg(le64_to_cpu(fe->i_size) != i_size_read(inode), "Inode %llu, inode i_size = %lld != di " "i_size = %llu, i_flags = 0x%x\n", @@ -448,19 +454,14 @@ static int ocfs2_truncate_file(struct inode *inode, le32_to_cpu(fe->i_flags)); if (new_i_size > le64_to_cpu(fe->i_size)) { - mlog(0, "asked to truncate file with size (%llu) to size (%llu)!\n", - (unsigned long long)le64_to_cpu(fe->i_size), - (unsigned long long)new_i_size); + trace_ocfs2_truncate_file_error( + (unsigned long long)le64_to_cpu(fe->i_size), + (unsigned long long)new_i_size); status = -EINVAL; mlog_errno(status); goto bail; } - mlog(0, "inode %llu, i_size = %llu, new_i_size = %llu\n", - (unsigned long long)le64_to_cpu(fe->i_blkno), - (unsigned long long)le64_to_cpu(fe->i_size), - (unsigned long long)new_i_size); - /* lets handle the simple truncate cases before doing any more * cluster locking. */ if (new_i_size == le64_to_cpu(fe->i_size)) @@ -566,8 +567,6 @@ static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start, struct ocfs2_extent_tree et; int did_quota = 0; - mlog(0, "(clusters_to_add = %u)\n", clusters_to_add); - /* * This function only exists for file systems which don't * support holes. @@ -584,11 +583,6 @@ static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start, restart_all: BUG_ON(le32_to_cpu(fe->i_clusters) != OCFS2_I(inode)->ip_clusters); - mlog(0, "extend inode %llu, i_size = %lld, di->i_clusters = %u, " - "clusters_to_add = %u\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno, - (long long)i_size_read(inode), le32_to_cpu(fe->i_clusters), - clusters_to_add); ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(inode), bh); status = ocfs2_lock_allocators(inode, &et, clusters_to_add, 0, &data_ac, &meta_ac); @@ -608,6 +602,12 @@ restart_all: } restarted_transaction: + trace_ocfs2_extend_allocation( + (unsigned long long)OCFS2_I(inode)->ip_blkno, + (unsigned long long)i_size_read(inode), + le32_to_cpu(fe->i_clusters), clusters_to_add, + why, restart_func); + status = dquot_alloc_space_nodirty(inode, ocfs2_clusters_to_bytes(osb->sb, clusters_to_add)); if (status) @@ -654,13 +654,11 @@ restarted_transaction: if (why != RESTART_NONE && clusters_to_add) { if (why == RESTART_META) { - mlog(0, "restarting function.\n"); restart_func = 1; status = 0; } else { BUG_ON(why != RESTART_TRANS); - mlog(0, "restarting transaction.\n"); /* TODO: This can be more intelligent. */ credits = ocfs2_calc_extend_credits(osb->sb, &fe->id2.i_list, @@ -677,11 +675,11 @@ restarted_transaction: } } - mlog(0, "fe: i_clusters = %u, i_size=%llu\n", + trace_ocfs2_extend_allocation_end(OCFS2_I(inode)->ip_blkno, le32_to_cpu(fe->i_clusters), - (unsigned long long)le64_to_cpu(fe->i_size)); - mlog(0, "inode: ip_clusters=%u, i_size=%lld\n", - OCFS2_I(inode)->ip_clusters, (long long)i_size_read(inode)); + (unsigned long long)le64_to_cpu(fe->i_size), + OCFS2_I(inode)->ip_clusters, + (unsigned long long)i_size_read(inode)); leave: if (status < 0 && did_quota) @@ -772,10 +770,11 @@ static int ocfs2_write_zero_page(struct inode *inode, u64 abs_from, if (!zero_to) zero_to = PAGE_CACHE_SIZE; - mlog(0, - "abs_from = %llu, abs_to = %llu, index = %lu, zero_from = %u, zero_to = %u\n", - (unsigned long long)abs_from, (unsigned long long)abs_to, - index, zero_from, zero_to); + trace_ocfs2_write_zero_page( + (unsigned long long)OCFS2_I(inode)->ip_blkno, + (unsigned long long)abs_from, + (unsigned long long)abs_to, + index, zero_from, zero_to); /* We know that zero_from is block aligned */ for (block_start = zero_from; block_start < zero_to; @@ -915,9 +914,10 @@ static int ocfs2_zero_extend_range(struct inode *inode, u64 range_start, u64 next_pos; u64 zero_pos = range_start; - mlog(0, "range_start = %llu, range_end = %llu\n", - (unsigned long long)range_start, - (unsigned long long)range_end); + trace_ocfs2_zero_extend_range( + (unsigned long long)OCFS2_I(inode)->ip_blkno, + (unsigned long long)range_start, + (unsigned long long)range_end); BUG_ON(range_start >= range_end); while (zero_pos < range_end) { @@ -949,9 +949,9 @@ int ocfs2_zero_extend(struct inode *inode, struct buffer_head *di_bh, struct super_block *sb = inode->i_sb; zero_start = ocfs2_align_bytes_to_blocks(sb, i_size_read(inode)); - mlog(0, "zero_start %llu for i_size %llu\n", - (unsigned long long)zero_start, - (unsigned long long)i_size_read(inode)); + trace_ocfs2_zero_extend((unsigned long long)OCFS2_I(inode)->ip_blkno, + (unsigned long long)zero_start, + (unsigned long long)i_size_read(inode)); while (zero_start < zero_to_size) { ret = ocfs2_zero_extend_get_range(inode, di_bh, zero_start, zero_to_size, @@ -1100,30 +1100,20 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) struct dquot *transfer_to[MAXQUOTAS] = { }; int qtype; - mlog(0, "(0x%p, '%.*s')\n", dentry, - dentry->d_name.len, dentry->d_name.name); + trace_ocfs2_setattr(inode, dentry, + (unsigned long long)OCFS2_I(inode)->ip_blkno, + dentry->d_name.len, dentry->d_name.name, + attr->ia_valid, attr->ia_mode, + attr->ia_uid, attr->ia_gid); /* ensuring we don't even attempt to truncate a symlink */ if (S_ISLNK(inode->i_mode)) attr->ia_valid &= ~ATTR_SIZE; - if (attr->ia_valid & ATTR_MODE) - mlog(0, "mode change: %d\n", attr->ia_mode); - if (attr->ia_valid & ATTR_UID) - mlog(0, "uid change: %d\n", attr->ia_uid); - if (attr->ia_valid & ATTR_GID) - mlog(0, "gid change: %d\n", attr->ia_gid); - if (attr->ia_valid & ATTR_SIZE) - mlog(0, "size change...\n"); - if (attr->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_CTIME)) - mlog(0, "time change...\n"); - #define OCFS2_VALID_ATTRS (ATTR_ATIME | ATTR_MTIME | ATTR_CTIME | ATTR_SIZE \ | ATTR_GID | ATTR_UID | ATTR_MODE) - if (!(attr->ia_valid & OCFS2_VALID_ATTRS)) { - mlog(0, "can't handle attrs: 0x%x\n", attr->ia_valid); + if (!(attr->ia_valid & OCFS2_VALID_ATTRS)) return 0; - } status = inode_change_ok(inode, attr); if (status) @@ -1318,8 +1308,9 @@ static int __ocfs2_write_remove_suid(struct inode *inode, struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); struct ocfs2_dinode *di; - mlog(0, "(Inode %llu, mode 0%o)\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno, inode->i_mode); + trace_ocfs2_write_remove_suid( + (unsigned long long)OCFS2_I(inode)->ip_blkno, + inode->i_mode); handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); if (IS_ERR(handle)) { @@ -1525,8 +1516,9 @@ static int ocfs2_zero_partial_clusters(struct inode *inode, * partial clusters here. There's no need to worry about * physical allocation - the zeroing code knows to skip holes. */ - mlog(0, "byte start: %llu, end: %llu\n", - (unsigned long long)start, (unsigned long long)end); + trace_ocfs2_zero_partial_clusters( + (unsigned long long)OCFS2_I(inode)->ip_blkno, + (unsigned long long)start, (unsigned long long)end); /* * If both edges are on a cluster boundary then there's no @@ -1550,8 +1542,8 @@ static int ocfs2_zero_partial_clusters(struct inode *inode, if (tmpend > end) tmpend = end; - mlog(0, "1st range: start: %llu, tmpend: %llu\n", - (unsigned long long)start, (unsigned long long)tmpend); + trace_ocfs2_zero_partial_clusters_range1((unsigned long long)start, + (unsigned long long)tmpend); ret = ocfs2_zero_range_for_truncate(inode, handle, start, tmpend); if (ret) @@ -1565,8 +1557,8 @@ static int ocfs2_zero_partial_clusters(struct inode *inode, */ start = end & ~(osb->s_clustersize - 1); - mlog(0, "2nd range: start: %llu, end: %llu\n", - (unsigned long long)start, (unsigned long long)end); + trace_ocfs2_zero_partial_clusters_range2( + (unsigned long long)start, (unsigned long long)end); ret = ocfs2_zero_range_for_truncate(inode, handle, start, end); if (ret) @@ -1666,6 +1658,11 @@ static int ocfs2_remove_inode_range(struct inode *inode, ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(inode), di_bh); ocfs2_init_dealloc_ctxt(&dealloc); + trace_ocfs2_remove_inode_range( + (unsigned long long)OCFS2_I(inode)->ip_blkno, + (unsigned long long)byte_start, + (unsigned long long)byte_len); + if (byte_len == 0) return 0; @@ -1712,11 +1709,6 @@ static int ocfs2_remove_inode_range(struct inode *inode, trunc_end = (byte_start + byte_len) >> osb->s_clustersize_bits; cluster_in_el = trunc_end; - mlog(0, "Inode: %llu, start: %llu, len: %llu, cstart: %u, cend: %u\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno, - (unsigned long long)byte_start, - (unsigned long long)byte_len, trunc_start, trunc_end); - ret = ocfs2_zero_partial_clusters(inode, byte_start, byte_len); if (ret) { mlog_errno(ret); @@ -2071,7 +2063,7 @@ static int ocfs2_prepare_inode_for_write(struct file *file, int ret = 0, meta_level = 0; struct dentry *dentry = file->f_path.dentry; struct inode *inode = dentry->d_inode; - loff_t saved_pos, end; + loff_t saved_pos = 0, end; /* * We start with a read level meta lock and only jump to an ex @@ -2110,12 +2102,10 @@ static int ocfs2_prepare_inode_for_write(struct file *file, /* work on a copy of ppos until we're sure that we won't have * to recalculate it due to relocking. */ - if (appending) { + if (appending) saved_pos = i_size_read(inode); - mlog(0, "O_APPEND: inode->i_size=%llu\n", saved_pos); - } else { + else saved_pos = *ppos; - } end = saved_pos + count; @@ -2186,6 +2176,10 @@ static int ocfs2_prepare_inode_for_write(struct file *file, *ppos = saved_pos; out_unlock: + trace_ocfs2_prepare_inode_for_write(OCFS2_I(inode)->ip_blkno, + saved_pos, appending, count, + direct_io, has_refcount); + if (meta_level >= 0) ocfs2_inode_unlock(inode, meta_level); @@ -2211,10 +2205,11 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, int full_coherency = !(osb->s_mount_opt & OCFS2_MOUNT_COHERENCY_BUFFERED); - mlog(0, "(0x%p, %u, '%.*s')\n", file, - (unsigned int)nr_segs, - file->f_path.dentry->d_name.len, - file->f_path.dentry->d_name.name); + trace_ocfs2_file_aio_write(inode, file, file->f_path.dentry, + (unsigned long long)OCFS2_I(inode)->ip_blkno, + file->f_path.dentry->d_name.len, + file->f_path.dentry->d_name.name, + (unsigned int)nr_segs); if (iocb->ki_left == 0) return 0; @@ -2415,10 +2410,11 @@ static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe, .u.file = out, }; - mlog(0, "(0x%p, 0x%p, %u, '%.*s')\n", out, pipe, - (unsigned int)len, - out->f_path.dentry->d_name.len, - out->f_path.dentry->d_name.name); + + trace_ocfs2_file_splice_write(inode, out, out->f_path.dentry, + (unsigned long long)OCFS2_I(inode)->ip_blkno, + out->f_path.dentry->d_name.len, + out->f_path.dentry->d_name.name, len); if (pipe->inode) mutex_lock_nested(&pipe->inode->i_mutex, I_MUTEX_PARENT); @@ -2474,10 +2470,10 @@ static ssize_t ocfs2_file_splice_read(struct file *in, int ret = 0, lock_level = 0; struct inode *inode = in->f_path.dentry->d_inode; - mlog(0, "(0x%p, 0x%p, %u, '%.*s')\n", in, pipe, - (unsigned int)len, - in->f_path.dentry->d_name.len, - in->f_path.dentry->d_name.name); + trace_ocfs2_file_splice_read(inode, in, in->f_path.dentry, + (unsigned long long)OCFS2_I(inode)->ip_blkno, + in->f_path.dentry->d_name.len, + in->f_path.dentry->d_name.name, len); /* * See the comment in ocfs2_file_aio_read() @@ -2504,10 +2500,11 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb, struct file *filp = iocb->ki_filp; struct inode *inode = filp->f_path.dentry->d_inode; - mlog(0, "(0x%p, %u, '%.*s')\n", filp, - (unsigned int)nr_segs, - filp->f_path.dentry->d_name.len, - filp->f_path.dentry->d_name.name); + trace_ocfs2_file_aio_read(inode, filp, filp->f_path.dentry, + (unsigned long long)OCFS2_I(inode)->ip_blkno, + filp->f_path.dentry->d_name.len, + filp->f_path.dentry->d_name.name, nr_segs); + if (!inode) { ret = -EINVAL; @@ -2553,8 +2550,7 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb, ocfs2_inode_unlock(inode, lock_level); ret = generic_file_aio_read(iocb, iov, nr_segs, iocb->ki_pos); - if (ret == -EINVAL) - mlog(0, "generic_file_aio_read returned -EINVAL\n"); + trace_generic_file_aio_read_ret(ret); /* buffered aio wouldn't have proper lock coverage today */ BUG_ON(ret == -EIOCBQUEUED && !(filp->f_flags & O_DIRECT)); diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 77148e7a14f8..16013b5588c6 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -204,6 +204,30 @@ DEFINE_EVENT(ocfs2__uint_uint_uint, name, \ unsigned int value3), \ TP_ARGS(value1, value2, value3)) +DECLARE_EVENT_CLASS(ocfs2__ull_ull_ull, + TP_PROTO(unsigned long long value1, + unsigned long long value2, unsigned long long value3), + TP_ARGS(value1, value2, value3), + TP_STRUCT__entry( + __field(unsigned long long, value1) + __field(unsigned long long, value2) + __field(unsigned long long, value3) + ), + TP_fast_assign( + __entry->value1 = value1; + __entry->value2 = value2; + __entry->value3 = value3; + ), + TP_printk("%llu %llu %llu", + __entry->value1, __entry->value2, __entry->value3) +); + +#define DEFINE_OCFS2_ULL_ULL_ULL_EVENT(name) \ +DEFINE_EVENT(ocfs2__ull_ull_ull, name, \ + TP_PROTO(unsigned long long value1, unsigned long long value2, \ + unsigned long long value3), \ + TP_ARGS(value1, value2, value3)) + DECLARE_EVENT_CLASS(ocfs2__ull_int_int_int, TP_PROTO(unsigned long long ull, int value1, int value2, int value3), TP_ARGS(ull, value1, value2, value3), @@ -1117,6 +1141,219 @@ TRACE_EVENT(ocfs2_fault, /* End of trace events for fs/ocfs2/mmap.c. */ +/* Trace events for fs/ocfs2/file.c. */ + +DECLARE_EVENT_CLASS(ocfs2__file_ops, + TP_PROTO(void *inode, void *file, void *dentry, + unsigned long long ino, + unsigned int d_len, const unsigned char *d_name, + unsigned long long para), + TP_ARGS(inode, file, dentry, ino, d_len, d_name, para), + TP_STRUCT__entry( + __field(void *, inode) + __field(void *, file) + __field(void *, dentry) + __field(unsigned long long, ino) + __field(unsigned int, d_len) + __string(d_name, d_name) + __field(unsigned long long, para) + ), + TP_fast_assign( + __entry->inode = inode; + __entry->file = file; + __entry->dentry = dentry; + __entry->ino = ino; + __entry->d_len = d_len; + __assign_str(d_name, d_name); + __entry->para = para; + ), + TP_printk("%p %p %p %llu %llu %.*s", __entry->inode, __entry->file, + __entry->dentry, __entry->ino, __entry->para, + __entry->d_len, __get_str(d_name)) +); + +#define DEFINE_OCFS2_FILE_OPS(name) \ +DEFINE_EVENT(ocfs2__file_ops, name, \ +TP_PROTO(void *inode, void *file, void *dentry, \ + unsigned long long ino, \ + unsigned int d_len, const unsigned char *d_name, \ + unsigned long long mode), \ + TP_ARGS(inode, file, dentry, ino, d_len, d_name, mode)) + +DEFINE_OCFS2_FILE_OPS(ocfs2_file_open); + +DEFINE_OCFS2_FILE_OPS(ocfs2_file_release); + +DEFINE_OCFS2_FILE_OPS(ocfs2_sync_file); + +DEFINE_OCFS2_FILE_OPS(ocfs2_file_aio_write); + +DEFINE_OCFS2_FILE_OPS(ocfs2_file_splice_write); + +DEFINE_OCFS2_FILE_OPS(ocfs2_file_splice_read); + +DEFINE_OCFS2_FILE_OPS(ocfs2_file_aio_read); + +DEFINE_OCFS2_ULL_ULL_ULL_EVENT(ocfs2_truncate_file); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_truncate_file_error); + +TRACE_EVENT(ocfs2_extend_allocation, + TP_PROTO(unsigned long long ip_blkno, unsigned long long size, + unsigned int clusters, unsigned int clusters_to_add, + int why, int restart_func), + TP_ARGS(ip_blkno, size, clusters, clusters_to_add, why, restart_func), + TP_STRUCT__entry( + __field(unsigned long long, ip_blkno) + __field(unsigned long long, size) + __field(unsigned int, clusters) + __field(unsigned int, clusters_to_add) + __field(int, why) + __field(int, restart_func) + ), + TP_fast_assign( + __entry->ip_blkno = ip_blkno; + __entry->size = size; + __entry->clusters = clusters; + __entry->clusters_to_add = clusters_to_add; + __entry->why = why; + __entry->restart_func = restart_func; + ), + TP_printk("%llu %llu %u %u %d %d", + __entry->ip_blkno, __entry->size, __entry->clusters, + __entry->clusters_to_add, __entry->why, __entry->restart_func) +); + +TRACE_EVENT(ocfs2_extend_allocation_end, + TP_PROTO(unsigned long long ino, + unsigned int di_clusters, unsigned long long di_size, + unsigned int ip_clusters, unsigned long long i_size), + TP_ARGS(ino, di_clusters, di_size, ip_clusters, i_size), + TP_STRUCT__entry( + __field(unsigned long long, ino) + __field(unsigned int, di_clusters) + __field(unsigned long long, di_size) + __field(unsigned int, ip_clusters) + __field(unsigned long long, i_size) + ), + TP_fast_assign( + __entry->ino = ino; + __entry->di_clusters = di_clusters; + __entry->di_size = di_size; + __entry->ip_clusters = ip_clusters; + __entry->i_size = i_size; + ), + TP_printk("%llu %u %llu %u %llu", __entry->ino, __entry->di_clusters, + __entry->di_size, __entry->ip_clusters, __entry->i_size) +); + +TRACE_EVENT(ocfs2_write_zero_page, + TP_PROTO(unsigned long long ino, + unsigned long long abs_from, unsigned long long abs_to, + unsigned long index, unsigned int zero_from, + unsigned int zero_to), + TP_ARGS(ino, abs_from, abs_to, index, zero_from, zero_to), + TP_STRUCT__entry( + __field(unsigned long long, ino) + __field(unsigned long long, abs_from) + __field(unsigned long long, abs_to) + __field(unsigned long, index) + __field(unsigned int, zero_from) + __field(unsigned int, zero_to) + ), + TP_fast_assign( + __entry->ino = ino; + __entry->abs_from = abs_from; + __entry->abs_to = abs_to; + __entry->index = index; + __entry->zero_from = zero_from; + __entry->zero_to = zero_to; + ), + TP_printk("%llu %llu %llu %lu %u %u", __entry->ino, + __entry->abs_from, __entry->abs_to, + __entry->index, __entry->zero_from, __entry->zero_to) +); + +DEFINE_OCFS2_ULL_ULL_ULL_EVENT(ocfs2_zero_extend_range); + +DEFINE_OCFS2_ULL_ULL_ULL_EVENT(ocfs2_zero_extend); + +TRACE_EVENT(ocfs2_setattr, + TP_PROTO(void *inode, void *dentry, + unsigned long long ino, + unsigned int d_len, const unsigned char *d_name, + unsigned int ia_valid, unsigned int ia_mode, + unsigned int ia_uid, unsigned int ia_gid), + TP_ARGS(inode, dentry, ino, d_len, d_name, + ia_valid, ia_mode, ia_uid, ia_gid), + TP_STRUCT__entry( + __field(void *, inode) + __field(void *, dentry) + __field(unsigned long long, ino) + __field(unsigned int, d_len) + __string(d_name, d_name) + __field(unsigned int, ia_valid) + __field(unsigned int, ia_mode) + __field(unsigned int, ia_uid) + __field(unsigned int, ia_gid) + ), + TP_fast_assign( + __entry->inode = inode; + __entry->dentry = dentry; + __entry->ino = ino; + __entry->d_len = d_len; + __assign_str(d_name, d_name); + __entry->ia_valid = ia_valid; + __entry->ia_mode = ia_mode; + __entry->ia_uid = ia_uid; + __entry->ia_gid = ia_gid; + ), + TP_printk("%p %p %llu %.*s %u %u %u %u", __entry->inode, + __entry->dentry, __entry->ino, __entry->d_len, + __get_str(d_name), __entry->ia_valid, __entry->ia_mode, + __entry->ia_uid, __entry->ia_gid) +); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_write_remove_suid); + +DEFINE_OCFS2_ULL_ULL_ULL_EVENT(ocfs2_zero_partial_clusters); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_zero_partial_clusters_range1); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_zero_partial_clusters_range2); + +DEFINE_OCFS2_ULL_ULL_ULL_EVENT(ocfs2_remove_inode_range); + +TRACE_EVENT(ocfs2_prepare_inode_for_write, + TP_PROTO(unsigned long long ino, unsigned long long saved_pos, + int appending, unsigned long count, + int *direct_io, int *has_refcount), + TP_ARGS(ino, saved_pos, appending, count, direct_io, has_refcount), + TP_STRUCT__entry( + __field(unsigned long long, ino) + __field(unsigned long long, saved_pos) + __field(int, appending) + __field(unsigned long, count) + __field(int, direct_io) + __field(int, has_refcount) + ), + TP_fast_assign( + __entry->ino = ino; + __entry->saved_pos = saved_pos; + __entry->appending = appending; + __entry->count = count; + __entry->direct_io = direct_io ? *direct_io : -1; + __entry->has_refcount = has_refcount ? *has_refcount : -1; + ), + TP_printk("%llu %llu %d %lu %d %d", __entry->ino, + __entry->saved_pos, __entry->appending, __entry->count, + __entry->direct_io, __entry->has_refcount) +); + +DEFINE_OCFS2_INT_EVENT(generic_file_aio_read_ret); + +/* End of trace events for fs/ocfs2/file.c. */ + #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ diff --git a/fs/ocfs2/sysfile.c b/fs/ocfs2/sysfile.c index 902efb23b6a6..3d635f4bbb20 100644 --- a/fs/ocfs2/sysfile.c +++ b/fs/ocfs2/sysfile.c @@ -27,7 +27,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_INODE #include #include "ocfs2.h" -- cgit From 6218b90e7669d83cb8ad744f3400205d260597f2 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Mon, 21 Feb 2011 11:18:30 +0800 Subject: ocfs2: Little refactoring against ocfs2_iget. ocfs2_iget is used to get/create inode. Only iget5_locked will give us an inode = NULL. So move this check ahead of ocfs2_read_locked_inode so that we don't need to check inode before we read and unlock inode. This is also helpful for trace event(see the next patch). Signed-off-by: Tao Ma --- fs/ocfs2/inode.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index a96e56f12728..8ec0cb01cb7c 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c @@ -152,16 +152,16 @@ struct inode *ocfs2_iget(struct ocfs2_super *osb, u64 blkno, unsigned flags, /* inode was *not* in the inode cache. 2.6.x requires * us to do our own read_inode call and unlock it * afterwards. */ - if (inode && inode->i_state & I_NEW) { - mlog(0, "Inode was not in inode cache, reading it.\n"); - ocfs2_read_locked_inode(inode, &args); - unlock_new_inode(inode); - } if (inode == NULL) { inode = ERR_PTR(-ENOMEM); mlog_errno(PTR_ERR(inode)); goto bail; } + if (inode->i_state & I_NEW) { + mlog(0, "Inode was not in inode cache, reading it.\n"); + ocfs2_read_locked_inode(inode, &args); + unlock_new_inode(inode); + } if (is_bad_inode(inode)) { iput(inode); inode = ERR_PTR(-ESTALE); -- cgit From 64f3b2692724fdbe72697b77887685b5bd3f4a3c Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Tue, 22 Feb 2011 22:24:57 +0800 Subject: ocfs2: Remove masklog ML_INODE. Remove mlog(0) from fs/ocfs2/inode.c and the masklog INODE. Signed-off-by: Tao Ma --- fs/ocfs2/cluster/masklog.c | 1 - fs/ocfs2/cluster/masklog.h | 1 - fs/ocfs2/inode.c | 107 +++++++++++++++-------------------- fs/ocfs2/ocfs2_trace.h | 136 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 182 insertions(+), 63 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index 036e8b8814f7..e18fb801633e 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -99,7 +99,6 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { define_mask(BH_IO), define_mask(UPTODATE), define_mask(NAMEI), - define_mask(INODE), define_mask(VOTE), define_mask(DCACHE), define_mask(CONN), diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index d07780ab9f8f..b76d07786107 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -101,7 +101,6 @@ #define ML_BH_IO 0x0000000000100000ULL /* ocfs2 buffer I/O */ #define ML_UPTODATE 0x0000000000200000ULL /* ocfs2 caching sequence #'s */ #define ML_NAMEI 0x0000000000400000ULL /* ocfs2 directory / namespace */ -#define ML_INODE 0x0000000000800000ULL /* ocfs2 inode manipulation */ #define ML_VOTE 0x0000000001000000ULL /* ocfs2 node messaging */ #define ML_DCACHE 0x0000000002000000ULL /* ocfs2 dcache operations */ #define ML_CONN 0x0000000004000000ULL /* net connection management */ diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index 8ec0cb01cb7c..177d3a6c2a5f 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c @@ -31,7 +31,6 @@ #include -#define MLOG_MASK_PREFIX ML_INODE #include #include "ocfs2.h" @@ -53,6 +52,7 @@ #include "uptodate.h" #include "xattr.h" #include "refcounttree.h" +#include "ocfs2_trace.h" #include "buffer_head_io.h" @@ -131,7 +131,8 @@ struct inode *ocfs2_iget(struct ocfs2_super *osb, u64 blkno, unsigned flags, struct super_block *sb = osb->sb; struct ocfs2_find_inode_args args; - mlog(0, "(blkno = %llu)\n", (unsigned long long)blkno); + trace_ocfs2_iget_begin((unsigned long long)blkno, flags, + sysfile_type); /* Ok. By now we've either got the offsets passed to us by the * caller, or we just pulled them off the bh. Lets do some @@ -157,8 +158,8 @@ struct inode *ocfs2_iget(struct ocfs2_super *osb, u64 blkno, unsigned flags, mlog_errno(PTR_ERR(inode)); goto bail; } + trace_ocfs2_iget5_locked(inode->i_state); if (inode->i_state & I_NEW) { - mlog(0, "Inode was not in inode cache, reading it.\n"); ocfs2_read_locked_inode(inode, &args); unlock_new_inode(inode); } @@ -170,9 +171,8 @@ struct inode *ocfs2_iget(struct ocfs2_super *osb, u64 blkno, unsigned flags, bail: if (!IS_ERR(inode)) { - mlog(0, "returning inode with number %llu\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno); - mlog(0, "inode %p\n", inode); + trace_ocfs2_iget_end(inode, + (unsigned long long)OCFS2_I(inode)->ip_blkno); } return inode; @@ -192,12 +192,12 @@ static int ocfs2_find_actor(struct inode *inode, void *opaque) struct ocfs2_inode_info *oi = OCFS2_I(inode); int ret = 0; - mlog(0, "(0x%p, %lu, 0x%p)\n", inode, inode->i_ino, opaque); - args = opaque; mlog_bug_on_msg(!inode, "No inode in find actor!\n"); + trace_ocfs2_find_actor(inode, inode->i_ino, opaque, args->fi_blkno); + if (oi->ip_blkno != args->fi_blkno) goto bail; @@ -217,8 +217,6 @@ static int ocfs2_init_locked_inode(struct inode *inode, void *opaque) static struct lock_class_key ocfs2_quota_ip_alloc_sem_key, ocfs2_file_ip_alloc_sem_key; - mlog(0, "inode = %p, opaque = %p\n", inode, opaque); - inode->i_ino = args->fi_ino; OCFS2_I(inode)->ip_blkno = args->fi_blkno; if (args->fi_sysfile_type != 0) @@ -244,9 +242,6 @@ void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, struct ocfs2_super *osb; int use_plocks = 1; - mlog(0, "(0x%p, size:%llu)\n", inode, - (unsigned long long)le64_to_cpu(fe->i_size)); - sb = inode->i_sb; osb = OCFS2_SB(sb); @@ -298,20 +293,20 @@ void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, inode->i_nlink = ocfs2_read_links_count(fe); + trace_ocfs2_populate_inode(OCFS2_I(inode)->ip_blkno, + le32_to_cpu(fe->i_flags)); if (fe->i_flags & cpu_to_le32(OCFS2_SYSTEM_FL)) { OCFS2_I(inode)->ip_flags |= OCFS2_INODE_SYSTEM_FILE; inode->i_flags |= S_NOQUOTA; } - + if (fe->i_flags & cpu_to_le32(OCFS2_LOCAL_ALLOC_FL)) { OCFS2_I(inode)->ip_flags |= OCFS2_INODE_BITMAP; - mlog(0, "local alloc inode: i_ino=%lu\n", inode->i_ino); } else if (fe->i_flags & cpu_to_le32(OCFS2_BITMAP_FL)) { OCFS2_I(inode)->ip_flags |= OCFS2_INODE_BITMAP; } else if (fe->i_flags & cpu_to_le32(OCFS2_QUOTA_FL)) { inode->i_flags |= S_NOQUOTA; } else if (fe->i_flags & cpu_to_le32(OCFS2_SUPER_BLOCK_FL)) { - mlog(0, "superblock inode: i_ino=%lu\n", inode->i_ino); /* we can't actually hit this as read_inode can't * handle superblocks today ;-) */ BUG(); @@ -391,8 +386,6 @@ static int ocfs2_read_locked_inode(struct inode *inode, int status, can_lock; u32 generation = 0; - mlog(0, "(0x%p, 0x%p)\n", inode, args); - status = -EINVAL; if (inode == NULL || inode->i_sb == NULL) { mlog(ML_ERROR, "bad inode\n"); @@ -440,6 +433,9 @@ static int ocfs2_read_locked_inode(struct inode *inode, && !(args->fi_flags & OCFS2_FI_FLAG_ORPHAN_RECOVERY) && !ocfs2_mount_local(osb); + trace_ocfs2_read_locked_inode( + (unsigned long long)OCFS2_I(inode)->ip_blkno, can_lock); + /* * To maintain backwards compatibility with older versions of * ocfs2-tools, we still store the generation value for system @@ -689,8 +685,6 @@ static int ocfs2_check_orphan_recovery_state(struct ocfs2_super *osb, spin_lock(&osb->osb_lock); if (ocfs2_node_map_test_bit(osb, &osb->osb_recovering_orphan_dirs, slot)) { - mlog(0, "Recovery is happening on orphan dir %d, will skip " - "this inode\n", slot); ret = -EDEADLK; goto out; } @@ -699,6 +693,7 @@ static int ocfs2_check_orphan_recovery_state(struct ocfs2_super *osb, osb->osb_orphan_wipes[slot]++; out: spin_unlock(&osb->osb_lock); + trace_ocfs2_check_orphan_recovery_state(slot, ret); return ret; } @@ -809,6 +804,10 @@ static int ocfs2_inode_is_valid_to_delete(struct inode *inode) struct ocfs2_inode_info *oi = OCFS2_I(inode); struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); + trace_ocfs2_inode_is_valid_to_delete(current, osb->dc_task, + (unsigned long long)oi->ip_blkno, + oi->ip_flags); + /* We shouldn't be getting here for the root directory * inode.. */ if (inode == osb->root_inode) { @@ -821,11 +820,8 @@ static int ocfs2_inode_is_valid_to_delete(struct inode *inode) * have to skip deleting this guy. That's OK though because * the node who's doing the actual deleting should handle it * anyway. */ - if (current == osb->dc_task) { - mlog(0, "Skipping delete of %lu because we're currently " - "in downconvert\n", inode->i_ino); + if (current == osb->dc_task) goto bail; - } spin_lock(&oi->ip_lock); /* OCFS2 *never* deletes system files. This should technically @@ -840,11 +836,8 @@ static int ocfs2_inode_is_valid_to_delete(struct inode *inode) /* If we have allowd wipe of this inode for another node, it * will be marked here so we can safely skip it. Recovery will * cleanup any inodes we might inadvertantly skip here. */ - if (oi->ip_flags & OCFS2_INODE_SKIP_DELETE) { - mlog(0, "Skipping delete of %lu because another node " - "has done this for us.\n", inode->i_ino); + if (oi->ip_flags & OCFS2_INODE_SKIP_DELETE) goto bail_unlock; - } ret = 1; bail_unlock: @@ -861,28 +854,27 @@ static int ocfs2_query_inode_wipe(struct inode *inode, struct buffer_head *di_bh, int *wipe) { - int status = 0; + int status = 0, reason = 0; struct ocfs2_inode_info *oi = OCFS2_I(inode); struct ocfs2_dinode *di; *wipe = 0; + trace_ocfs2_query_inode_wipe_begin((unsigned long long)oi->ip_blkno, + inode->i_nlink); + /* While we were waiting for the cluster lock in * ocfs2_delete_inode, another node might have asked to delete * the inode. Recheck our flags to catch this. */ if (!ocfs2_inode_is_valid_to_delete(inode)) { - mlog(0, "Skipping delete of %llu because flags changed\n", - (unsigned long long)oi->ip_blkno); + reason = 1; goto bail; } /* Now that we have an up to date inode, we can double check * the link count. */ - if (inode->i_nlink) { - mlog(0, "Skipping delete of %llu because nlink = %u\n", - (unsigned long long)oi->ip_blkno, inode->i_nlink); + if (inode->i_nlink) goto bail; - } /* Do some basic inode verification... */ di = (struct ocfs2_dinode *) di_bh->b_data; @@ -897,9 +889,7 @@ static int ocfs2_query_inode_wipe(struct inode *inode, * ORPHANED_FL not. */ if (di->i_dyn_features & cpu_to_le16(OCFS2_HAS_REFCOUNT_FL)) { - mlog(0, "Reflinked inode %llu is no longer orphaned. " - "it shouldn't be deleted\n", - (unsigned long long)oi->ip_blkno); + reason = 2; goto bail; } @@ -936,8 +926,7 @@ static int ocfs2_query_inode_wipe(struct inode *inode, status = ocfs2_try_open_lock(inode, 1); if (status == -EAGAIN) { status = 0; - mlog(0, "Skipping delete of %llu because it is in use on " - "other nodes\n", (unsigned long long)oi->ip_blkno); + reason = 3; goto bail; } if (status < 0) { @@ -946,11 +935,10 @@ static int ocfs2_query_inode_wipe(struct inode *inode, } *wipe = 1; - mlog(0, "Inode %llu is ok to wipe from orphan dir %u\n", - (unsigned long long)oi->ip_blkno, - le16_to_cpu(di->i_orphaned_slot)); + trace_ocfs2_query_inode_wipe_succ(le16_to_cpu(di->i_orphaned_slot)); bail: + trace_ocfs2_query_inode_wipe_end(status, reason); return status; } @@ -960,8 +948,8 @@ bail: static void ocfs2_cleanup_delete_inode(struct inode *inode, int sync_data) { - mlog(0, "Cleanup inode %llu, sync = %d\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno, sync_data); + trace_ocfs2_cleanup_delete_inode( + (unsigned long long)OCFS2_I(inode)->ip_blkno, sync_data); if (sync_data) write_inode_now(inode, 1); truncate_inode_pages(&inode->i_data, 0); @@ -973,15 +961,15 @@ static void ocfs2_delete_inode(struct inode *inode) sigset_t oldset; struct buffer_head *di_bh = NULL; - mlog(0, "(inode->i_ino = %lu)\n", inode->i_ino); + trace_ocfs2_delete_inode(inode->i_ino, + (unsigned long long)OCFS2_I(inode)->ip_blkno, + is_bad_inode(inode)); /* When we fail in read_inode() we mark inode as bad. The second test * catches the case when inode allocation fails before allocating * a block for inode. */ - if (is_bad_inode(inode) || !OCFS2_I(inode)->ip_blkno) { - mlog(0, "Skipping delete of bad inode\n"); + if (is_bad_inode(inode) || !OCFS2_I(inode)->ip_blkno) goto bail; - } dquot_initialize(inode); @@ -1082,8 +1070,8 @@ static void ocfs2_clear_inode(struct inode *inode) struct ocfs2_inode_info *oi = OCFS2_I(inode); end_writeback(inode); - mlog(0, "Clearing inode: %llu, nlink = %u\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno, inode->i_nlink); + trace_ocfs2_clear_inode((unsigned long long)oi->ip_blkno, + inode->i_nlink); mlog_bug_on_msg(OCFS2_SB(inode->i_sb) == NULL, "Inode=%lu\n", inode->i_ino); @@ -1193,8 +1181,8 @@ int ocfs2_drop_inode(struct inode *inode) struct ocfs2_inode_info *oi = OCFS2_I(inode); int res; - mlog(0, "Drop inode %llu, nlink = %u, ip_flags = 0x%x\n", - (unsigned long long)oi->ip_blkno, inode->i_nlink, oi->ip_flags); + trace_ocfs2_drop_inode((unsigned long long)oi->ip_blkno, + inode->i_nlink, oi->ip_flags); if (oi->ip_flags & OCFS2_INODE_MAYBE_ORPHANED) res = 1; @@ -1212,11 +1200,11 @@ int ocfs2_inode_revalidate(struct dentry *dentry) struct inode *inode = dentry->d_inode; int status = 0; - mlog(0, "(inode = 0x%p, ino = %llu)\n", inode, - inode ? (unsigned long long)OCFS2_I(inode)->ip_blkno : 0ULL); + trace_ocfs2_inode_revalidate(inode, + inode ? (unsigned long long)OCFS2_I(inode)->ip_blkno : 0ULL, + inode ? (unsigned long long)OCFS2_I(inode)->ip_flags : 0); if (!inode) { - mlog(0, "eep, no inode!\n"); status = -ENOENT; goto bail; } @@ -1224,7 +1212,6 @@ int ocfs2_inode_revalidate(struct dentry *dentry) spin_lock(&OCFS2_I(inode)->ip_lock); if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_DELETED) { spin_unlock(&OCFS2_I(inode)->ip_lock); - mlog(0, "inode deleted!\n"); status = -ENOENT; goto bail; } @@ -1255,8 +1242,7 @@ int ocfs2_mark_inode_dirty(handle_t *handle, int status; struct ocfs2_dinode *fe = (struct ocfs2_dinode *) bh->b_data; - mlog(0, "(inode %llu)\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno); + trace_ocfs2_mark_inode_dirty((unsigned long long)OCFS2_I(inode)->ip_blkno); status = ocfs2_journal_access_di(handle, INODE_CACHE(inode), bh, OCFS2_JOURNAL_ACCESS_WRITE); @@ -1328,8 +1314,7 @@ int ocfs2_validate_inode_block(struct super_block *sb, int rc; struct ocfs2_dinode *di = (struct ocfs2_dinode *)bh->b_data; - mlog(0, "Validating dinode %llu\n", - (unsigned long long)bh->b_blocknr); + trace_ocfs2_validate_inode_block((unsigned long long)bh->b_blocknr); BUG_ON(!buffer_uptodate(bh)); diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 16013b5588c6..052057a01ea8 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -114,6 +114,25 @@ DEFINE_EVENT(ocfs2__ull_uint, name, \ TP_PROTO(unsigned long long val1, unsigned int val2), \ TP_ARGS(val1, val2)) +DECLARE_EVENT_CLASS(ocfs2__ull_int, + TP_PROTO(unsigned long long value1, int value2), + TP_ARGS(value1, value2), + TP_STRUCT__entry( + __field(unsigned long long, value1) + __field(int, value2) + ), + TP_fast_assign( + __entry->value1 = value1; + __entry->value2 = value2; + ), + TP_printk("%llu %d", __entry->value1, __entry->value2) +); + +#define DEFINE_OCFS2_ULL_INT_EVENT(name) \ +DEFINE_EVENT(ocfs2__ull_int, name, \ + TP_PROTO(unsigned long long val1, int val2), \ + TP_ARGS(val1, val2)) + DECLARE_EVENT_CLASS(ocfs2__ull_ull, TP_PROTO(unsigned long long value1, unsigned long long value2), TP_ARGS(value1, value2), @@ -1354,6 +1373,123 @@ DEFINE_OCFS2_INT_EVENT(generic_file_aio_read_ret); /* End of trace events for fs/ocfs2/file.c. */ +/* Trace events for fs/ocfs2/inode.c. */ + +TRACE_EVENT(ocfs2_iget_begin, + TP_PROTO(unsigned long long ino, unsigned int flags, int sysfile_type), + TP_ARGS(ino, flags, sysfile_type), + TP_STRUCT__entry( + __field(unsigned long long, ino) + __field(unsigned int, flags) + __field(int, sysfile_type) + ), + TP_fast_assign( + __entry->ino = ino; + __entry->flags = flags; + __entry->sysfile_type = sysfile_type; + ), + TP_printk("%llu %u %d", __entry->ino, + __entry->flags, __entry->sysfile_type) +); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_iget5_locked); + +TRACE_EVENT(ocfs2_iget_end, + TP_PROTO(void *inode, unsigned long long ino), + TP_ARGS(inode, ino), + TP_STRUCT__entry( + __field(void *, inode) + __field(unsigned long long, ino) + ), + TP_fast_assign( + __entry->inode = inode; + __entry->ino = ino; + ), + TP_printk("%p %llu", __entry->inode, __entry->ino) +); + +TRACE_EVENT(ocfs2_find_actor, + TP_PROTO(void *inode, unsigned long long ino, + void *args, unsigned long long fi_blkno), + TP_ARGS(inode, ino, args, fi_blkno), + TP_STRUCT__entry( + __field(void *, inode) + __field(unsigned long long, ino) + __field(void *, args) + __field(unsigned long long, fi_blkno) + ), + TP_fast_assign( + __entry->inode = inode; + __entry->ino = ino; + __entry->args = args; + __entry->fi_blkno = fi_blkno; + ), + TP_printk("%p %llu %p %llu", __entry->inode, __entry->ino, + __entry->args, __entry->fi_blkno) +); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_populate_inode); + +DEFINE_OCFS2_ULL_INT_EVENT(ocfs2_read_locked_inode); + +DEFINE_OCFS2_INT_INT_EVENT(ocfs2_check_orphan_recovery_state); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_validate_inode_block); + +TRACE_EVENT(ocfs2_inode_is_valid_to_delete, + TP_PROTO(void *task, void *dc_task, unsigned long long ino, + unsigned int flags), + TP_ARGS(task, dc_task, ino, flags), + TP_STRUCT__entry( + __field(void *, task) + __field(void *, dc_task) + __field(unsigned long long, ino) + __field(unsigned int, flags) + ), + TP_fast_assign( + __entry->task = task; + __entry->dc_task = dc_task; + __entry->ino = ino; + __entry->flags = flags; + ), + TP_printk("%p %p %llu %u", __entry->task, __entry->dc_task, + __entry->ino, __entry->flags) +); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_query_inode_wipe_begin); + +DEFINE_OCFS2_UINT_EVENT(ocfs2_query_inode_wipe_succ); + +DEFINE_OCFS2_INT_INT_EVENT(ocfs2_query_inode_wipe_end); + +DEFINE_OCFS2_ULL_INT_EVENT(ocfs2_cleanup_delete_inode); + +DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_delete_inode); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_clear_inode); + +DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_drop_inode); + +TRACE_EVENT(ocfs2_inode_revalidate, + TP_PROTO(void *inode, unsigned long long ino, + unsigned int flags), + TP_ARGS(inode, ino, flags), + TP_STRUCT__entry( + __field(void *, inode) + __field(unsigned long long, ino) + __field(unsigned int, flags) + ), + TP_fast_assign( + __entry->inode = inode; + __entry->ino = ino; + __entry->flags = flags; + ), + TP_printk("%p %llu %u", __entry->inode, __entry->ino, __entry->flags) +); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_mark_inode_dirty); + +/* End of trace events for fs/ocfs2/inode.c. */ #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ -- cgit From a716357c47ea1cc4f535356cff2c39edd327136b Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Tue, 22 Feb 2011 22:27:33 +0800 Subject: ocfs2: Remove masklog ML_EXTENT_MAP. Remove mlog(0) from fs/ocfs2/extent_map.c and the masklog EXTENT_MAP. Signed-off-by: Tao Ma --- fs/ocfs2/cluster/masklog.c | 1 - fs/ocfs2/cluster/masklog.h | 1 - fs/ocfs2/extent_map.c | 5 ++--- fs/ocfs2/ocfs2_trace.h | 29 +++++++++++++++++++++++++++++ 4 files changed, 31 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index e18fb801633e..c5ba4373d863 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -94,7 +94,6 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { define_mask(AIO), define_mask(JOURNAL), define_mask(SUPER), - define_mask(EXTENT_MAP), define_mask(DLM_GLUE), define_mask(BH_IO), define_mask(UPTODATE), diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index b76d07786107..e4ca487078b3 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -96,7 +96,6 @@ #define ML_AIO 0x0000000000002000ULL /* ocfs2 aio read and write */ #define ML_JOURNAL 0x0000000000004000ULL /* ocfs2 journalling functions */ #define ML_SUPER 0x0000000000010000ULL /* ocfs2 mount / umount */ -#define ML_EXTENT_MAP 0x0000000000040000ULL /* ocfs2 extent map caching */ #define ML_DLM_GLUE 0x0000000000080000ULL /* ocfs2 dlm glue layer */ #define ML_BH_IO 0x0000000000100000ULL /* ocfs2 buffer I/O */ #define ML_UPTODATE 0x0000000000200000ULL /* ocfs2 caching sequence #'s */ diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c index 7d74d176706a..23457b491e8c 100644 --- a/fs/ocfs2/extent_map.c +++ b/fs/ocfs2/extent_map.c @@ -28,7 +28,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_EXTENT_MAP #include #include "ocfs2.h" @@ -39,6 +38,7 @@ #include "inode.h" #include "super.h" #include "symlink.h" +#include "ocfs2_trace.h" #include "buffer_head_io.h" @@ -841,8 +841,7 @@ int ocfs2_read_virt_blocks(struct inode *inode, u64 v_block, int nr, u64 p_block, p_count; int i, count, done = 0; - mlog(0, "(inode = %p, v_block = %llu, nr = %d, bhs = %p, " - "flags = %x, validate = %p)\n", + trace_ocfs2_read_virt_blocks( inode, (unsigned long long)v_block, nr, bhs, flags, validate); diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 052057a01ea8..a7938505227b 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -1490,6 +1490,35 @@ TRACE_EVENT(ocfs2_inode_revalidate, DEFINE_OCFS2_ULL_EVENT(ocfs2_mark_inode_dirty); /* End of trace events for fs/ocfs2/inode.c. */ + +/* Trace events for fs/ocfs2/extent_map.c. */ + +TRACE_EVENT(ocfs2_read_virt_blocks, + TP_PROTO(void *inode, unsigned long long vblock, int nr, + void *bhs, unsigned int flags, void *validate), + TP_ARGS(inode, vblock, nr, bhs, flags, validate), + TP_STRUCT__entry( + __field(void *, inode) + __field(unsigned long long, vblock) + __field(int, nr) + __field(void *, bhs) + __field(unsigned int, flags) + __field(void *, validate) + ), + TP_fast_assign( + __entry->inode = inode; + __entry->vblock = vblock; + __entry->nr = nr; + __entry->bhs = bhs; + __entry->flags = flags; + __entry->validate = validate; + ), + TP_printk("%p %llu %d %p %x %p", __entry->inode, __entry->vblock, + __entry->nr, __entry->bhs, __entry->flags, __entry->validate) +); + +/* End of trace events for fs/ocfs2/extent_map.c. */ + #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ -- cgit From a8731086eff053b430cddbf5783654dfd700ea06 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Tue, 22 Feb 2011 22:29:08 +0800 Subject: ocfs2: Remove mlog(0) from fs/ocfs2/slot_map.c This is the 1st step to remove the debug info of SUPER. Signed-off-by: Tao Ma --- fs/ocfs2/ocfs2_trace.h | 11 +++++++++++ fs/ocfs2/slot_map.c | 13 +++++-------- 2 files changed, 16 insertions(+), 8 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index a7938505227b..d70471f8ad04 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -1519,6 +1519,17 @@ TRACE_EVENT(ocfs2_read_virt_blocks, /* End of trace events for fs/ocfs2/extent_map.c. */ +/* Trace events for fs/ocfs2/slot_map.c. */ + +DEFINE_OCFS2_UINT_EVENT(ocfs2_refresh_slot_info); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_map_slot_buffers); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_map_slot_buffers_block); + +DEFINE_OCFS2_INT_EVENT(ocfs2_find_slot); + +/* End of trace events for fs/ocfs2/slot_map.c. */ #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ diff --git a/fs/ocfs2/slot_map.c b/fs/ocfs2/slot_map.c index 93b449ed82f9..26fc0014d509 100644 --- a/fs/ocfs2/slot_map.c +++ b/fs/ocfs2/slot_map.c @@ -27,7 +27,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_SUPER #include #include "ocfs2.h" @@ -39,6 +38,7 @@ #include "slot_map.h" #include "super.h" #include "sysfile.h" +#include "ocfs2_trace.h" #include "buffer_head_io.h" @@ -142,8 +142,7 @@ int ocfs2_refresh_slot_info(struct ocfs2_super *osb) BUG_ON(si->si_blocks == 0); BUG_ON(si->si_bh == NULL); - mlog(0, "Refreshing slot map, reading %u block(s)\n", - si->si_blocks); + trace_ocfs2_refresh_slot_info(si->si_blocks); /* * We pass -1 as blocknr because we expect all of si->si_bh to @@ -381,8 +380,7 @@ static int ocfs2_map_slot_buffers(struct ocfs2_super *osb, /* The size checks above should ensure this */ BUG_ON((osb->max_slots / si->si_slots_per_block) > blocks); - mlog(0, "Slot map needs %u buffers for %llu bytes\n", - si->si_blocks, bytes); + trace_ocfs2_map_slot_buffers(bytes, si->si_blocks); si->si_bh = kzalloc(sizeof(struct buffer_head *) * si->si_blocks, GFP_KERNEL); @@ -400,8 +398,7 @@ static int ocfs2_map_slot_buffers(struct ocfs2_super *osb, goto bail; } - mlog(0, "Reading slot map block %u at %llu\n", i, - (unsigned long long)blkno); + trace_ocfs2_map_slot_buffers_block((unsigned long long)blkno, i); bh = NULL; /* Acquire a fresh bh */ status = ocfs2_read_blocks(INODE_CACHE(si->si_inode), blkno, @@ -503,7 +500,7 @@ int ocfs2_find_slot(struct ocfs2_super *osb) osb->slot_num = slot; spin_unlock(&osb->osb_lock); - mlog(0, "taking node slot %d\n", osb->slot_num); + trace_ocfs2_find_slot(osb->slot_num); status = ocfs2_update_disk_slot(osb, si, osb->slot_num); if (status < 0) -- cgit From b5770f98b00e94dd573e3438427de09733fe2039 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Wed, 23 Feb 2011 21:17:39 +0800 Subject: ocfs2: Remove mlog(0) from fs/ocfs2/heartbeat.c This is the 2nd step to remove the debug info of SUPER. Signed-off-by: Tao Ma --- fs/ocfs2/heartbeat.c | 4 ++-- fs/ocfs2/ocfs2_trace.h | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/heartbeat.c b/fs/ocfs2/heartbeat.c index 1aa863dd901f..d8208b20dc53 100644 --- a/fs/ocfs2/heartbeat.c +++ b/fs/ocfs2/heartbeat.c @@ -28,7 +28,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_SUPER #include #include "ocfs2.h" @@ -37,6 +36,7 @@ #include "heartbeat.h" #include "inode.h" #include "journal.h" +#include "ocfs2_trace.h" #include "buffer_head_io.h" @@ -66,7 +66,7 @@ void ocfs2_do_node_down(int node_num, void *data) BUG_ON(osb->node_num == node_num); - mlog(0, "ocfs2: node down event for %d\n", node_num); + trace_ocfs2_do_node_down(node_num); if (!osb->cconn) { /* diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index d70471f8ad04..876b119d3656 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -1530,6 +1530,13 @@ DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_map_slot_buffers_block); DEFINE_OCFS2_INT_EVENT(ocfs2_find_slot); /* End of trace events for fs/ocfs2/slot_map.c. */ + +/* Trace events for fs/ocfs2/heartbeat.c. */ + +DEFINE_OCFS2_INT_EVENT(ocfs2_do_node_down); + +/* End of trace events for fs/ocfs2/heartbeat.c. */ + #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ -- cgit From 32a42d392bf9b8f90f41434ccb3605e958b16251 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Wed, 23 Feb 2011 21:29:08 +0800 Subject: ocfs2: Remove masklog ML_SUPER. Remove mlog(0) from fs/ocfs2/super.c and the masklog SUPER. Signed-off-by: Tao Ma --- fs/ocfs2/cluster/masklog.c | 1 - fs/ocfs2/cluster/masklog.h | 1 - fs/ocfs2/ocfs2_trace.h | 108 +++++++++++++++++++++++++++++++++++++++++++++ fs/ocfs2/super.c | 29 +++++------- 4 files changed, 118 insertions(+), 21 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index c5ba4373d863..ffc0de62a031 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -93,7 +93,6 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { define_mask(DLM_RECOVERY), define_mask(AIO), define_mask(JOURNAL), - define_mask(SUPER), define_mask(DLM_GLUE), define_mask(BH_IO), define_mask(UPTODATE), diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index e4ca487078b3..98d4af95c8fe 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -95,7 +95,6 @@ #define ML_DLM_RECOVERY 0x0000000000001000ULL /* dlm master functions */ #define ML_AIO 0x0000000000002000ULL /* ocfs2 aio read and write */ #define ML_JOURNAL 0x0000000000004000ULL /* ocfs2 journalling functions */ -#define ML_SUPER 0x0000000000010000ULL /* ocfs2 mount / umount */ #define ML_DLM_GLUE 0x0000000000080000ULL /* ocfs2 dlm glue layer */ #define ML_BH_IO 0x0000000000100000ULL /* ocfs2 buffer I/O */ #define ML_UPTODATE 0x0000000000200000ULL /* ocfs2 caching sequence #'s */ diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 876b119d3656..75900635109b 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -57,6 +57,23 @@ DEFINE_EVENT(ocfs2__ull, name, \ TP_PROTO(unsigned long long num), \ TP_ARGS(num)) +DECLARE_EVENT_CLASS(ocfs2__pointer, + TP_PROTO(void *pointer), + TP_ARGS(pointer), + TP_STRUCT__entry( + __field(void *, pointer) + ), + TP_fast_assign( + __entry->pointer = pointer; + ), + TP_printk("%p", __entry->pointer) +); + +#define DEFINE_OCFS2_POINTER_EVENT(name) \ +DEFINE_EVENT(ocfs2__pointer, name, \ + TP_PROTO(void *pointer), \ + TP_ARGS(pointer)) + DECLARE_EVENT_CLASS(ocfs2__int_int, TP_PROTO(int value1, int value2), TP_ARGS(value1, value2), @@ -1537,6 +1554,97 @@ DEFINE_OCFS2_INT_EVENT(ocfs2_do_node_down); /* End of trace events for fs/ocfs2/heartbeat.c. */ +/* Trace events for fs/ocfs2/super.c. */ + +TRACE_EVENT(ocfs2_remount, + TP_PROTO(unsigned long s_flags, unsigned long osb_flags, int flags), + TP_ARGS(s_flags, osb_flags, flags), + TP_STRUCT__entry( + __field(unsigned long, s_flags) + __field(unsigned long, osb_flags) + __field(int, flags) + ), + TP_fast_assign( + __entry->s_flags = s_flags; + __entry->osb_flags = osb_flags; + __entry->flags = flags; + ), + TP_printk("%lu %lu %d", __entry->s_flags, + __entry->osb_flags, __entry->flags) +); + +TRACE_EVENT(ocfs2_fill_super, + TP_PROTO(void *sb, void *data, int silent), + TP_ARGS(sb, data, silent), + TP_STRUCT__entry( + __field(void *, sb) + __field(void *, data) + __field(int, silent) + ), + TP_fast_assign( + __entry->sb = sb; + __entry->data = data; + __entry->silent = silent; + ), + TP_printk("%p %p %d", __entry->sb, + __entry->data, __entry->silent) +); + +TRACE_EVENT(ocfs2_parse_options, + TP_PROTO(int is_remount, char *options), + TP_ARGS(is_remount, options), + TP_STRUCT__entry( + __field(int, is_remount) + __string(options, options) + ), + TP_fast_assign( + __entry->is_remount = is_remount; + __assign_str(options, options); + ), + TP_printk("%d %s", __entry->is_remount, __get_str(options)) +); + +DEFINE_OCFS2_POINTER_EVENT(ocfs2_put_super); + +TRACE_EVENT(ocfs2_statfs, + TP_PROTO(void *sb, void *buf), + TP_ARGS(sb, buf), + TP_STRUCT__entry( + __field(void *, sb) + __field(void *, buf) + ), + TP_fast_assign( + __entry->sb = sb; + __entry->buf = buf; + ), + TP_printk("%p %p", __entry->sb, __entry->buf) +); + +DEFINE_OCFS2_POINTER_EVENT(ocfs2_dismount_volume); + +TRACE_EVENT(ocfs2_initialize_super, + TP_PROTO(char *label, char *uuid_str, unsigned long long root_dir, + unsigned long long system_dir, int cluster_bits), + TP_ARGS(label, uuid_str, root_dir, system_dir, cluster_bits), + TP_STRUCT__entry( + __string(label, label) + __string(uuid_str, uuid_str) + __field(unsigned long long, root_dir) + __field(unsigned long long, system_dir) + __field(int, cluster_bits) + ), + TP_fast_assign( + __assign_str(label, label); + __assign_str(uuid_str, uuid_str); + __entry->root_dir = root_dir; + __entry->system_dir = system_dir; + __entry->cluster_bits = cluster_bits; + ), + TP_printk("%s %s %llu %llu %d", __get_str(label), __get_str(uuid_str), + __entry->root_dir, __entry->system_dir, __entry->cluster_bits) +); + +/* End of trace events for fs/ocfs2/super.c. */ #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index f7e73a029844..0e4083987d2b 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -45,7 +45,6 @@ #define CREATE_TRACE_POINTS #include "ocfs2_trace.h" -#define MLOG_MASK_PREFIX ML_SUPER #include #include "ocfs2.h" @@ -680,12 +679,9 @@ static int ocfs2_remount(struct super_block *sb, int *flags, char *data) } if (*flags & MS_RDONLY) { - mlog(0, "Going to ro mode.\n"); sb->s_flags |= MS_RDONLY; osb->osb_flags |= OCFS2_OSB_SOFT_RO; } else { - mlog(0, "Making ro filesystem writeable.\n"); - if (osb->osb_flags & OCFS2_OSB_ERROR_FS) { mlog(ML_ERROR, "Cannot remount RDWR " "filesystem due to previous errors.\n"); @@ -703,6 +699,7 @@ static int ocfs2_remount(struct super_block *sb, int *flags, char *data) sb->s_flags &= ~MS_RDONLY; osb->osb_flags &= ~OCFS2_OSB_SOFT_RO; } + trace_ocfs2_remount(sb->s_flags, osb->osb_flags, *flags); unlock_osb: spin_unlock(&osb->osb_lock); /* Enable quota accounting after remounting RW */ @@ -1028,7 +1025,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) char nodestr[8]; struct ocfs2_blockcheck_stats stats; - mlog(0, "%p, %p, %i", sb, data, silent); + trace_ocfs2_fill_super(sb, data, silent); if (!ocfs2_parse_options(sb, data, &parsed_options, 0)) { status = -EINVAL; @@ -1315,8 +1312,7 @@ static int ocfs2_parse_options(struct super_block *sb, char *p; u32 tmp; - mlog(0, "remount: %d, options: \"%s\"\n", is_remount, - options ? options : "(none)"); + trace_ocfs2_parse_options(is_remount, options ? options : "(none)"); mopt->commit_interval = 0; mopt->mount_opt = OCFS2_MOUNT_NOINTR; @@ -1692,7 +1688,7 @@ static void __exit ocfs2_exit(void) static void ocfs2_put_super(struct super_block *sb) { - mlog(0, "(0x%p)\n", sb); + trace_ocfs2_put_super(sb); ocfs2_sync_blockdev(sb); ocfs2_dismount_volume(sb, 0); @@ -1707,7 +1703,7 @@ static int ocfs2_statfs(struct dentry *dentry, struct kstatfs *buf) struct buffer_head *bh = NULL; struct inode *inode = NULL; - mlog(0, "(%p, %p)\n", dentry->d_sb, buf); + trace_ocfs2_statfs(dentry->d_sb, buf); osb = OCFS2_SB(dentry->d_sb); @@ -1928,7 +1924,7 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err) struct ocfs2_super *osb = NULL; char nodestr[8]; - mlog(0, "(0x%p)\n", sb); + trace_ocfs2_dismount_volume(sb); BUG_ON(!sb); osb = OCFS2_SB(sb); @@ -2143,7 +2139,6 @@ static int ocfs2_initialize_super(struct super_block *sb, status = -EINVAL; goto bail; } - mlog(0, "max_slots for this device: %u\n", osb->max_slots); ocfs2_orphan_scan_init(osb); @@ -2282,7 +2277,6 @@ static int ocfs2_initialize_super(struct super_block *sb, osb->s_clustersize_bits = le32_to_cpu(di->id2.i_super.s_clustersize_bits); osb->s_clustersize = 1 << osb->s_clustersize_bits; - mlog(0, "clusterbits=%d\n", osb->s_clustersize_bits); if (osb->s_clustersize < OCFS2_MIN_CLUSTERSIZE || osb->s_clustersize > OCFS2_MAX_CLUSTERSIZE) { @@ -2321,11 +2315,10 @@ static int ocfs2_initialize_super(struct super_block *sb, le64_to_cpu(di->id2.i_super.s_first_cluster_group); osb->fs_generation = le32_to_cpu(di->i_fs_generation); osb->uuid_hash = le32_to_cpu(di->id2.i_super.s_uuid_hash); - mlog(0, "vol_label: %s\n", osb->vol_label); - mlog(0, "uuid: %s\n", osb->uuid_str); - mlog(0, "root_blkno=%llu, system_dir_blkno=%llu\n", - (unsigned long long)osb->root_blkno, - (unsigned long long)osb->system_dir_blkno); + trace_ocfs2_initialize_super(osb->vol_label, osb->uuid_str, + (unsigned long long)osb->root_blkno, + (unsigned long long)osb->system_dir_blkno, + osb->s_clustersize_bits); osb->osb_dlm_debug = ocfs2_new_dlm_debug(); if (!osb->osb_dlm_debug) { @@ -2500,8 +2493,6 @@ static int ocfs2_check_volume(struct ocfs2_super *osb) * ourselves as mounted. */ } - mlog(0, "Journal loaded.\n"); - status = ocfs2_load_local_alloc(osb); if (status < 0) { mlog_errno(status); -- cgit From 402b418311f0d20a71451770d764a2e37b08dbcf Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Wed, 23 Feb 2011 22:01:17 +0800 Subject: ocfs2: Remove masklog ML_XATTR. Remove mlog(0) from fs/ocfs2/xattr.c and the masklog ML_XATTR. Signed-off-by: Tao Ma --- fs/ocfs2/cluster/masklog.c | 1 - fs/ocfs2/cluster/masklog.h | 1 - fs/ocfs2/ocfs2_trace.h | 164 +++++++++++++++++++++++++++++++++++++++++++++ fs/ocfs2/xattr.c | 153 +++++++++++++++++++++--------------------- 4 files changed, 239 insertions(+), 80 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index ffc0de62a031..ef140ab7dcf8 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -102,7 +102,6 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { define_mask(CONN), define_mask(QUORUM), define_mask(EXPORT), - define_mask(XATTR), define_mask(QUOTA), define_mask(BASTS), define_mask(RESERVATIONS), diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index 98d4af95c8fe..f574b167e8dc 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -104,7 +104,6 @@ #define ML_CONN 0x0000000004000000ULL /* net connection management */ #define ML_QUORUM 0x0000000008000000ULL /* net connection quorum */ #define ML_EXPORT 0x0000000010000000ULL /* ocfs2 export operations */ -#define ML_XATTR 0x0000000020000000ULL /* ocfs2 extended attributes */ #define ML_QUOTA 0x0000000040000000ULL /* ocfs2 quota operations */ #define ML_BASTS 0x0000000100000000ULL /* dlmglue asts and basts */ #define ML_RESERVATIONS 0x0000000200000000ULL /* ocfs2 alloc reservations */ diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 75900635109b..0fc2840d6fb1 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -74,6 +74,23 @@ DEFINE_EVENT(ocfs2__pointer, name, \ TP_PROTO(void *pointer), \ TP_ARGS(pointer)) +DECLARE_EVENT_CLASS(ocfs2__string, + TP_PROTO(const char *name), + TP_ARGS(name), + TP_STRUCT__entry( + __string(name,name) + ), + TP_fast_assign( + __assign_str(name, name); + ), + TP_printk("%s", __get_str(name)) +); + +#define DEFINE_OCFS2_STRING_EVENT(name) \ +DEFINE_EVENT(ocfs2__string, name, \ + TP_PROTO(const char *name), \ + TP_ARGS(name)) + DECLARE_EVENT_CLASS(ocfs2__int_int, TP_PROTO(int value1, int value2), TP_ARGS(value1, value2), @@ -317,6 +334,33 @@ DEFINE_EVENT(ocfs2__ull_uint_uint_uint, name, \ unsigned int value2, unsigned int value3), \ TP_ARGS(ull, value1, value2, value3)) +DECLARE_EVENT_CLASS(ocfs2__ull_ull_uint_uint, + TP_PROTO(unsigned long long value1, unsigned long long value2, + unsigned int value3, unsigned int value4), + TP_ARGS(value1, value2, value3, value4), + TP_STRUCT__entry( + __field(unsigned long long, value1) + __field(unsigned long long, value2) + __field(unsigned int, value3) + __field(unsigned int, value4) + ), + TP_fast_assign( + __entry->value1 = value1; + __entry->value2 = value2; + __entry->value3 = value3; + __entry->value4 = value4; + ), + TP_printk("%llu %llu %u %u", + __entry->value1, __entry->value2, + __entry->value3, __entry->value4) +); + +#define DEFINE_OCFS2_ULL_ULL_UINT_UINT_EVENT(name) \ +DEFINE_EVENT(ocfs2__ull_ull_uint_uint, name, \ + TP_PROTO(unsigned long long ull, unsigned long long ull1, \ + unsigned int value2, unsigned int value3), \ + TP_ARGS(ull, ull1, value2, value3)) + /* Trace events for fs/ocfs2/alloc.c. */ DECLARE_EVENT_CLASS(ocfs2__btree_ops, TP_PROTO(unsigned long long owner,\ @@ -1645,6 +1689,126 @@ TRACE_EVENT(ocfs2_initialize_super, ); /* End of trace events for fs/ocfs2/super.c. */ + +/* Trace events for fs/ocfs2/xattr.c. */ + +DEFINE_OCFS2_ULL_EVENT(ocfs2_validate_xattr_block); + +DEFINE_OCFS2_UINT_EVENT(ocfs2_xattr_extend_allocation); + +TRACE_EVENT(ocfs2_init_xattr_set_ctxt, + TP_PROTO(const char *name, int meta, int clusters, int credits), + TP_ARGS(name, meta, clusters, credits), + TP_STRUCT__entry( + __string(name, name) + __field(int, meta) + __field(int, clusters) + __field(int, credits) + ), + TP_fast_assign( + __assign_str(name, name); + __entry->meta = meta; + __entry->clusters = clusters; + __entry->credits = credits; + ), + TP_printk("%s %d %d %d", __get_str(name), __entry->meta, + __entry->clusters, __entry->credits) +); + +DECLARE_EVENT_CLASS(ocfs2__xattr_find, + TP_PROTO(unsigned long long ino, const char *name, int name_index, + unsigned int hash, unsigned long long location, + int xe_index), + TP_ARGS(ino, name, name_index, hash, location, xe_index), + TP_STRUCT__entry( + __field(unsigned long long, ino) + __string(name, name) + __field(int, name_index) + __field(unsigned int, hash) + __field(unsigned long long, location) + __field(int, xe_index) + ), + TP_fast_assign( + __entry->ino = ino; + __assign_str(name, name); + __entry->name_index = name_index; + __entry->hash = hash; + __entry->location = location; + __entry->xe_index = xe_index; + ), + TP_printk("%llu %s %d %u %llu %d", __entry->ino, __get_str(name), + __entry->name_index, __entry->hash, __entry->location, + __entry->xe_index) +); + +#define DEFINE_OCFS2_XATTR_FIND_EVENT(name) \ +DEFINE_EVENT(ocfs2__xattr_find, name, \ +TP_PROTO(unsigned long long ino, const char *name, int name_index, \ + unsigned int hash, unsigned long long bucket, \ + int xe_index), \ + TP_ARGS(ino, name, name_index, hash, bucket, xe_index)) + +DEFINE_OCFS2_XATTR_FIND_EVENT(ocfs2_xattr_bucket_find); + +DEFINE_OCFS2_XATTR_FIND_EVENT(ocfs2_xattr_index_block_find); + +DEFINE_OCFS2_XATTR_FIND_EVENT(ocfs2_xattr_index_block_find_rec); + +DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_iterate_xattr_buckets); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_iterate_xattr_bucket); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_cp_xattr_block_to_bucket_begin); + +DEFINE_OCFS2_UINT_UINT_UINT_EVENT(ocfs2_cp_xattr_block_to_bucket_end); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_xattr_create_index_block_begin); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_xattr_create_index_block); + +DEFINE_OCFS2_ULL_UINT_UINT_UINT_EVENT(ocfs2_defrag_xattr_bucket); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_mv_xattr_bucket_cross_cluster); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_divide_xattr_bucket_begin); + +DEFINE_OCFS2_UINT_UINT_UINT_EVENT(ocfs2_divide_xattr_bucket_move); + +DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_cp_xattr_bucket); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_mv_xattr_buckets); + +DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_adjust_xattr_cross_cluster); + +DEFINE_OCFS2_ULL_ULL_UINT_UINT_EVENT(ocfs2_add_new_xattr_cluster_begin); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_add_new_xattr_cluster); + +DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_add_new_xattr_cluster_insert); + +DEFINE_OCFS2_ULL_ULL_UINT_UINT_EVENT(ocfs2_extend_xattr_bucket); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_add_new_xattr_bucket); + +DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_xattr_bucket_value_truncate); + +DEFINE_OCFS2_ULL_ULL_UINT_UINT_EVENT(ocfs2_rm_xattr_cluster); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_reflink_xattr_header); + +DEFINE_OCFS2_ULL_INT_EVENT(ocfs2_create_empty_xattr_block); + +DEFINE_OCFS2_STRING_EVENT(ocfs2_xattr_set_entry_bucket); + +DEFINE_OCFS2_STRING_EVENT(ocfs2_xattr_set_entry_index_block); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_xattr_bucket_value_refcount); + +DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_reflink_xattr_buckets); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_reflink_xattr_rec); + +/* End of trace events for fs/ocfs2/xattr.c. */ #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index d57c7942e4de..52e3dadd3642 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c @@ -37,7 +37,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_XATTR #include #include "ocfs2.h" @@ -57,6 +56,7 @@ #include "xattr.h" #include "refcounttree.h" #include "acl.h" +#include "ocfs2_trace.h" struct ocfs2_xattr_def_value_root { struct ocfs2_xattr_value_root xv; @@ -474,8 +474,7 @@ static int ocfs2_validate_xattr_block(struct super_block *sb, struct ocfs2_xattr_block *xb = (struct ocfs2_xattr_block *)bh->b_data; - mlog(0, "Validating xattr block %llu\n", - (unsigned long long)bh->b_blocknr); + trace_ocfs2_validate_xattr_block((unsigned long long)bh->b_blocknr); BUG_ON(!buffer_uptodate(bh)); @@ -715,11 +714,11 @@ static int ocfs2_xattr_extend_allocation(struct inode *inode, u32 prev_clusters, logical_start = le32_to_cpu(vb->vb_xv->xr_clusters); struct ocfs2_extent_tree et; - mlog(0, "(clusters_to_add for xattr= %u)\n", clusters_to_add); - ocfs2_init_xattr_value_extent_tree(&et, INODE_CACHE(inode), vb); while (clusters_to_add) { + trace_ocfs2_xattr_extend_allocation(clusters_to_add); + status = vb->vb_access(handle, INODE_CACHE(inode), vb->vb_bh, OCFS2_JOURNAL_ACCESS_WRITE); if (status < 0) { @@ -754,8 +753,6 @@ static int ocfs2_xattr_extend_allocation(struct inode *inode, */ BUG_ON(why == RESTART_META); - mlog(0, "restarting xattr value extension for %u" - " clusters,.\n", clusters_to_add); credits = ocfs2_calc_extend_credits(inode->i_sb, &vb->vb_xv->xr_list, clusters_to_add); @@ -3246,8 +3243,8 @@ static int ocfs2_init_xattr_set_ctxt(struct inode *inode, } meta_add += extra_meta; - mlog(0, "Set xattr %s, reserve meta blocks = %d, clusters = %d, " - "credits = %d\n", xi->xi_name, meta_add, clusters_add, *credits); + trace_ocfs2_init_xattr_set_ctxt(xi->xi_name, meta_add, + clusters_add, *credits); if (meta_add) { ret = ocfs2_reserve_new_metadata_blocks(osb, meta_add, @@ -3887,8 +3884,10 @@ static int ocfs2_xattr_bucket_find(struct inode *inode, if (found) { xs->here = &xs->header->xh_entries[index]; - mlog(0, "find xattr %s in bucket %llu, entry = %u\n", name, - (unsigned long long)bucket_blkno(xs->bucket), index); + trace_ocfs2_xattr_bucket_find(OCFS2_I(inode)->ip_blkno, + name, name_index, name_hash, + (unsigned long long)bucket_blkno(xs->bucket), + index); } else ret = -ENODATA; @@ -3915,8 +3914,10 @@ static int ocfs2_xattr_index_block_find(struct inode *inode, if (le16_to_cpu(el->l_next_free_rec) == 0) return -ENODATA; - mlog(0, "find xattr %s, hash = %u, index = %d in xattr tree\n", - name, name_hash, name_index); + trace_ocfs2_xattr_index_block_find(OCFS2_I(inode)->ip_blkno, + name, name_index, name_hash, + (unsigned long long)root_bh->b_blocknr, + -1); ret = ocfs2_xattr_get_rec(inode, name_hash, &p_blkno, &first_hash, &num_clusters, el); @@ -3927,9 +3928,10 @@ static int ocfs2_xattr_index_block_find(struct inode *inode, BUG_ON(p_blkno == 0 || num_clusters == 0 || first_hash > name_hash); - mlog(0, "find xattr extent rec %u clusters from %llu, the first hash " - "in the rec is %u\n", num_clusters, (unsigned long long)p_blkno, - first_hash); + trace_ocfs2_xattr_index_block_find_rec(OCFS2_I(inode)->ip_blkno, + name, name_index, first_hash, + (unsigned long long)p_blkno, + num_clusters); ret = ocfs2_xattr_bucket_find(inode, name_index, name, name_hash, p_blkno, first_hash, num_clusters, xs); @@ -3955,8 +3957,9 @@ static int ocfs2_iterate_xattr_buckets(struct inode *inode, return -ENOMEM; } - mlog(0, "iterating xattr buckets in %u clusters starting from %llu\n", - clusters, (unsigned long long)blkno); + trace_ocfs2_iterate_xattr_buckets( + (unsigned long long)OCFS2_I(inode)->ip_blkno, + (unsigned long long)blkno, clusters); for (i = 0; i < num_buckets; i++, blkno += bucket->bu_blocks) { ret = ocfs2_read_xattr_bucket(bucket, blkno); @@ -3972,8 +3975,7 @@ static int ocfs2_iterate_xattr_buckets(struct inode *inode, if (i == 0) num_buckets = le16_to_cpu(bucket_xh(bucket)->xh_num_buckets); - mlog(0, "iterating xattr bucket %llu, first hash %u\n", - (unsigned long long)blkno, + trace_ocfs2_iterate_xattr_bucket((unsigned long long)blkno, le32_to_cpu(bucket_xh(bucket)->xh_entries[0].xe_name_hash)); if (func) { ret = func(inode, bucket, para); @@ -4173,9 +4175,9 @@ static void ocfs2_cp_xattr_block_to_bucket(struct inode *inode, char *src = xb_bh->b_data; char *target = bucket_block(bucket, blks - 1); - mlog(0, "cp xattr from block %llu to bucket %llu\n", - (unsigned long long)xb_bh->b_blocknr, - (unsigned long long)bucket_blkno(bucket)); + trace_ocfs2_cp_xattr_block_to_bucket_begin( + (unsigned long long)xb_bh->b_blocknr, + (unsigned long long)bucket_blkno(bucket)); for (i = 0; i < blks; i++) memset(bucket_block(bucket, i), 0, blocksize); @@ -4211,8 +4213,7 @@ static void ocfs2_cp_xattr_block_to_bucket(struct inode *inode, for (i = 0; i < count; i++) le16_add_cpu(&xh->xh_entries[i].xe_name_offset, off_change); - mlog(0, "copy entry: start = %u, size = %u, offset_change = %u\n", - offset, size, off_change); + trace_ocfs2_cp_xattr_block_to_bucket_end(offset, size, off_change); sort(target + offset, count, sizeof(struct ocfs2_xattr_entry), cmp_xe, swap_xe); @@ -4261,8 +4262,8 @@ static int ocfs2_xattr_create_index_block(struct inode *inode, struct ocfs2_xattr_tree_root *xr; u16 xb_flags = le16_to_cpu(xb->xb_flags); - mlog(0, "create xattr index block for %llu\n", - (unsigned long long)xb_bh->b_blocknr); + trace_ocfs2_xattr_create_index_block_begin( + (unsigned long long)xb_bh->b_blocknr); BUG_ON(xb_flags & OCFS2_XATTR_INDEXED); BUG_ON(!xs->bucket); @@ -4295,8 +4296,7 @@ static int ocfs2_xattr_create_index_block(struct inode *inode, */ blkno = ocfs2_clusters_to_blocks(inode->i_sb, bit_off); - mlog(0, "allocate 1 cluster from %llu to xattr block\n", - (unsigned long long)blkno); + trace_ocfs2_xattr_create_index_block((unsigned long long)blkno); ret = ocfs2_init_xattr_bucket(xs->bucket, blkno); if (ret) { @@ -4400,8 +4400,7 @@ static int ocfs2_defrag_xattr_bucket(struct inode *inode, entries = (char *)xh->xh_entries; xh_free_start = le16_to_cpu(xh->xh_free_start); - mlog(0, "adjust xattr bucket in %llu, count = %u, " - "xh_free_start = %u, xh_name_value_len = %u.\n", + trace_ocfs2_defrag_xattr_bucket( (unsigned long long)blkno, le16_to_cpu(xh->xh_count), xh_free_start, le16_to_cpu(xh->xh_name_value_len)); @@ -4503,8 +4502,9 @@ static int ocfs2_mv_xattr_bucket_cross_cluster(struct inode *inode, BUG_ON(le16_to_cpu(bucket_xh(first)->xh_num_buckets) < num_buckets); BUG_ON(OCFS2_XATTR_BUCKET_SIZE == OCFS2_SB(sb)->s_clustersize); - mlog(0, "move half of xattrs in cluster %llu to %llu\n", - (unsigned long long)last_cluster_blkno, (unsigned long long)new_blkno); + trace_ocfs2_mv_xattr_bucket_cross_cluster( + (unsigned long long)last_cluster_blkno, + (unsigned long long)new_blkno); ret = ocfs2_mv_xattr_buckets(inode, handle, bucket_blkno(first), last_cluster_blkno, new_blkno, @@ -4614,8 +4614,8 @@ static int ocfs2_divide_xattr_bucket(struct inode *inode, struct ocfs2_xattr_entry *xe; int blocksize = inode->i_sb->s_blocksize; - mlog(0, "move some of xattrs from bucket %llu to %llu\n", - (unsigned long long)blk, (unsigned long long)new_blk); + trace_ocfs2_divide_xattr_bucket_begin((unsigned long long)blk, + (unsigned long long)new_blk); s_bucket = ocfs2_xattr_bucket_new(inode); t_bucket = ocfs2_xattr_bucket_new(inode); @@ -4714,9 +4714,9 @@ static int ocfs2_divide_xattr_bucket(struct inode *inode, */ xe = &xh->xh_entries[start]; len = sizeof(struct ocfs2_xattr_entry) * (count - start); - mlog(0, "mv xattr entry len %d from %d to %d\n", len, - (int)((char *)xe - (char *)xh), - (int)((char *)xh->xh_entries - (char *)xh)); + trace_ocfs2_divide_xattr_bucket_move(len, + (int)((char *)xe - (char *)xh), + (int)((char *)xh->xh_entries - (char *)xh)); memmove((char *)xh->xh_entries, (char *)xe, len); xe = &xh->xh_entries[count - start]; len = sizeof(struct ocfs2_xattr_entry) * start; @@ -4788,9 +4788,9 @@ static int ocfs2_cp_xattr_bucket(struct inode *inode, BUG_ON(s_blkno == t_blkno); - mlog(0, "cp bucket %llu to %llu, target is %d\n", - (unsigned long long)s_blkno, (unsigned long long)t_blkno, - t_is_new); + trace_ocfs2_cp_xattr_bucket((unsigned long long)s_blkno, + (unsigned long long)t_blkno, + t_is_new); s_bucket = ocfs2_xattr_bucket_new(inode); t_bucket = ocfs2_xattr_bucket_new(inode); @@ -4862,8 +4862,8 @@ static int ocfs2_mv_xattr_buckets(struct inode *inode, handle_t *handle, int num_buckets = ocfs2_xattr_buckets_per_cluster(osb); struct ocfs2_xattr_bucket *old_first, *new_first; - mlog(0, "mv xattrs from cluster %llu to %llu\n", - (unsigned long long)last_blk, (unsigned long long)to_blk); + trace_ocfs2_mv_xattr_buckets((unsigned long long)last_blk, + (unsigned long long)to_blk); BUG_ON(start_bucket >= num_buckets); if (start_bucket) { @@ -5013,9 +5013,9 @@ static int ocfs2_adjust_xattr_cross_cluster(struct inode *inode, { int ret; - mlog(0, "adjust xattrs from cluster %llu len %u to %llu\n", - (unsigned long long)bucket_blkno(first), prev_clusters, - (unsigned long long)new_blk); + trace_ocfs2_adjust_xattr_cross_cluster( + (unsigned long long)bucket_blkno(first), + (unsigned long long)new_blk, prev_clusters); if (ocfs2_xattr_buckets_per_cluster(OCFS2_SB(inode->i_sb)) > 1) { ret = ocfs2_mv_xattr_bucket_cross_cluster(inode, @@ -5088,10 +5088,10 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode, struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); struct ocfs2_extent_tree et; - mlog(0, "Add new xattr cluster for %llu, previous xattr hash = %u, " - "previous xattr blkno = %llu\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno, - prev_cpos, (unsigned long long)bucket_blkno(first)); + trace_ocfs2_add_new_xattr_cluster_begin( + (unsigned long long)OCFS2_I(inode)->ip_blkno, + (unsigned long long)bucket_blkno(first), + prev_cpos, prev_clusters); ocfs2_init_xattr_tree_extent_tree(&et, INODE_CACHE(inode), root_bh); @@ -5113,8 +5113,7 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode, BUG_ON(num_bits > clusters_to_add); block = ocfs2_clusters_to_blocks(osb->sb, bit_off); - mlog(0, "Allocating %u clusters at block %u for xattr in inode %llu\n", - num_bits, bit_off, (unsigned long long)OCFS2_I(inode)->ip_blkno); + trace_ocfs2_add_new_xattr_cluster((unsigned long long)block, num_bits); if (bucket_blkno(first) + (prev_clusters * bpc) == block && (prev_clusters + num_bits) << osb->s_clustersize_bits <= @@ -5130,8 +5129,6 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode, */ v_start = prev_cpos + prev_clusters; *num_clusters = prev_clusters + num_bits; - mlog(0, "Add contiguous %u clusters to previous extent rec.\n", - num_bits); } else { ret = ocfs2_adjust_xattr_cross_cluster(inode, handle, @@ -5147,8 +5144,8 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode, } } - mlog(0, "Insert %u clusters at block %llu for xattr at %u\n", - num_bits, (unsigned long long)block, v_start); + trace_ocfs2_add_new_xattr_cluster_insert((unsigned long long)block, + v_start, num_bits); ret = ocfs2_insert_extent(handle, &et, v_start, block, num_bits, 0, ctxt->meta_ac); if (ret < 0) { @@ -5183,9 +5180,9 @@ static int ocfs2_extend_xattr_bucket(struct inode *inode, u64 end_blk; u16 new_bucket = le16_to_cpu(bucket_xh(first)->xh_num_buckets); - mlog(0, "extend xattr bucket in %llu, xattr extend rec starting " - "from %llu, len = %u\n", (unsigned long long)target_blk, - (unsigned long long)bucket_blkno(first), num_clusters); + trace_ocfs2_extend_xattr_bucket((unsigned long long)target_blk, + (unsigned long long)bucket_blkno(first), + num_clusters, new_bucket); /* The extent must have room for an additional bucket */ BUG_ON(new_bucket >= @@ -5265,8 +5262,8 @@ static int ocfs2_add_new_xattr_bucket(struct inode *inode, /* The bucket at the front of the extent */ struct ocfs2_xattr_bucket *first; - mlog(0, "Add new xattr bucket starting from %llu\n", - (unsigned long long)bucket_blkno(target)); + trace_ocfs2_add_new_xattr_bucket( + (unsigned long long)bucket_blkno(target)); /* The first bucket of the original extent */ first = ocfs2_xattr_bucket_new(inode); @@ -5382,8 +5379,8 @@ static int ocfs2_xattr_bucket_value_truncate(struct inode *inode, * modified something. We have to assume they did, and dirty * the whole bucket. This leaves us in a consistent state. */ - mlog(0, "truncate %u in xattr bucket %llu to %d bytes.\n", - xe_off, (unsigned long long)bucket_blkno(bucket), len); + trace_ocfs2_xattr_bucket_value_truncate( + (unsigned long long)bucket_blkno(bucket), xe_off, len); ret = ocfs2_xattr_value_truncate(inode, &vb, len, ctxt); if (ret) { mlog_errno(ret); @@ -5433,8 +5430,9 @@ static int ocfs2_rm_xattr_cluster(struct inode *inode, ocfs2_init_dealloc_ctxt(&dealloc); - mlog(0, "rm xattr extent rec at %u len = %u, start from %llu\n", - cpos, len, (unsigned long long)blkno); + trace_ocfs2_rm_xattr_cluster( + (unsigned long long)OCFS2_I(inode)->ip_blkno, + (unsigned long long)blkno, cpos, len); ocfs2_remove_xattr_clusters_from_cache(INODE_CACHE(inode), blkno, len); @@ -5538,7 +5536,7 @@ static int ocfs2_xattr_set_entry_bucket(struct inode *inode, int ret; struct ocfs2_xa_loc loc; - mlog(0, "Set xattr %s in xattr bucket\n", xi->xi_name); + trace_ocfs2_xattr_set_entry_bucket(xi->xi_name); ocfs2_init_xattr_bucket_xa_loc(&loc, xs->bucket, xs->not_found ? NULL : xs->here); @@ -5580,7 +5578,7 @@ static int ocfs2_xattr_set_entry_index_block(struct inode *inode, { int ret; - mlog(0, "Set xattr %s in xattr index block\n", xi->xi_name); + trace_ocfs2_xattr_set_entry_index_block(xi->xi_name); ret = ocfs2_xattr_set_entry_bucket(inode, xi, xs, ctxt); if (!ret) @@ -6039,9 +6037,9 @@ static int ocfs2_xattr_bucket_value_refcount(struct inode *inode, if (ocfs2_meta_ecc(OCFS2_SB(inode->i_sb))) p = &refcount; - mlog(0, "refcount bucket %llu, count = %u\n", - (unsigned long long)bucket_blkno(bucket), - le16_to_cpu(xh->xh_count)); + trace_ocfs2_xattr_bucket_value_refcount( + (unsigned long long)bucket_blkno(bucket), + le16_to_cpu(xh->xh_count)); for (i = 0; i < le16_to_cpu(xh->xh_count); i++) { xe = &xh->xh_entries[i]; @@ -6337,8 +6335,8 @@ static int ocfs2_reflink_xattr_header(handle_t *handle, u32 clusters, cpos, p_cluster, num_clusters; unsigned int ext_flags = 0; - mlog(0, "reflink xattr in container %llu, count = %u\n", - (unsigned long long)old_bh->b_blocknr, le16_to_cpu(xh->xh_count)); + trace_ocfs2_reflink_xattr_header((unsigned long long)old_bh->b_blocknr, + le16_to_cpu(xh->xh_count)); last = &new_xh->xh_entries[le16_to_cpu(new_xh->xh_count)]; for (i = 0, j = 0; i < le16_to_cpu(xh->xh_count); i++, j++) { @@ -6538,8 +6536,8 @@ static int ocfs2_create_empty_xattr_block(struct inode *inode, goto out; } - mlog(0, "create new xattr block for inode %llu, index = %d\n", - (unsigned long long)fe_bh->b_blocknr, indexed); + trace_ocfs2_create_empty_xattr_block( + (unsigned long long)fe_bh->b_blocknr, indexed); ret = ocfs2_create_xattr_block(inode, fe_bh, &ctxt, indexed, ret_bh); if (ret) @@ -6950,8 +6948,8 @@ static int ocfs2_reflink_xattr_buckets(handle_t *handle, if (ret) mlog_errno(ret); - mlog(0, "insert new xattr extent rec start %llu len %u to %u\n", - (unsigned long long)new_blkno, num_clusters, reflink_cpos); + trace_ocfs2_reflink_xattr_buckets((unsigned long long)new_blkno, + num_clusters, reflink_cpos); len -= num_clusters; blkno += ocfs2_clusters_to_blocks(inode->i_sb, num_clusters); @@ -6980,8 +6978,7 @@ static int ocfs2_reflink_xattr_rec(struct inode *inode, struct ocfs2_alloc_context *data_ac = NULL; struct ocfs2_extent_tree et; - mlog(0, "reflink xattr buckets %llu len %u\n", - (unsigned long long)blkno, len); + trace_ocfs2_reflink_xattr_rec((unsigned long long)blkno, len); ocfs2_init_xattr_tree_extent_tree(&et, INODE_CACHE(args->reflink->new_inode), -- cgit From 2661836e0ca07f57505563ec31aeee20b1758987 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Wed, 23 Feb 2011 22:10:56 +0800 Subject: ocfs2: Remove masklog ML_RESERVATIONS. Remove mlog(0) from fs/ocfs2/reservations.c and the masklog RESERVATIONS. Signed-off-by: Tao Ma --- fs/ocfs2/cluster/masklog.c | 1 - fs/ocfs2/cluster/masklog.h | 1 - fs/ocfs2/ocfs2_trace.h | 116 +++++++++++++++++++++++++++++++++++++++++++++ fs/ocfs2/reservations.c | 57 ++++++++++------------ 4 files changed, 142 insertions(+), 33 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index ef140ab7dcf8..39f2a46810d1 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -104,7 +104,6 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { define_mask(EXPORT), define_mask(QUOTA), define_mask(BASTS), - define_mask(RESERVATIONS), define_mask(CLUSTER), define_mask(ERROR), define_mask(NOTICE), diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index f574b167e8dc..c36b4d8d5aa9 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -106,7 +106,6 @@ #define ML_EXPORT 0x0000000010000000ULL /* ocfs2 export operations */ #define ML_QUOTA 0x0000000040000000ULL /* ocfs2 quota operations */ #define ML_BASTS 0x0000000100000000ULL /* dlmglue asts and basts */ -#define ML_RESERVATIONS 0x0000000200000000ULL /* ocfs2 alloc reservations */ #define ML_CLUSTER 0x0000000400000000ULL /* cluster stack */ /* bits that are infrequently given and frequently matched in the high word */ diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 0fc2840d6fb1..1c040fcbd6e7 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -1809,6 +1809,122 @@ DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_reflink_xattr_buckets); DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_reflink_xattr_rec); /* End of trace events for fs/ocfs2/xattr.c. */ + +/* Trace events for fs/ocfs2/reservations.c. */ + +DEFINE_OCFS2_UINT_UINT_EVENT(ocfs2_resv_insert); + +DEFINE_OCFS2_ULL_UINT_UINT_UINT_EVENT(ocfs2_resmap_find_free_bits_begin); + +DEFINE_OCFS2_UINT_UINT_EVENT(ocfs2_resmap_find_free_bits_end); + +TRACE_EVENT(ocfs2_resv_find_window_begin, + TP_PROTO(unsigned int r_start, unsigned int r_end, unsigned int goal, + unsigned int wanted, int empty_root), + TP_ARGS(r_start, r_end, goal, wanted, empty_root), + TP_STRUCT__entry( + __field(unsigned int, r_start) + __field(unsigned int, r_end) + __field(unsigned int, goal) + __field(unsigned int, wanted) + __field(int, empty_root) + ), + TP_fast_assign( + __entry->r_start = r_start; + __entry->r_end = r_end; + __entry->goal = goal; + __entry->wanted = wanted; + __entry->empty_root = empty_root; + ), + TP_printk("%u %u %u %u %d", __entry->r_start, __entry->r_end, + __entry->goal, __entry->wanted, __entry->empty_root) +); + +DEFINE_OCFS2_UINT_UINT_EVENT(ocfs2_resv_find_window_prev); + +DEFINE_OCFS2_INT_INT_EVENT(ocfs2_resv_find_window_next); + +DEFINE_OCFS2_UINT_UINT_UINT_EVENT(ocfs2_cannibalize_resv_begin); + +TRACE_EVENT(ocfs2_cannibalize_resv_end, + TP_PROTO(unsigned int start, unsigned int end, unsigned int len, + unsigned int last_start, unsigned int last_len), + TP_ARGS(start, end, len, last_start, last_len), + TP_STRUCT__entry( + __field(unsigned int, start) + __field(unsigned int, end) + __field(unsigned int, len) + __field(unsigned int, last_start) + __field(unsigned int, last_len) + ), + TP_fast_assign( + __entry->start = start; + __entry->end = end; + __entry->len = len; + __entry->last_start = last_start; + __entry->last_len = last_len; + ), + TP_printk("%u %u %u %u %u", __entry->start, __entry->end, + __entry->len, __entry->last_start, __entry->last_len) +); + +DEFINE_OCFS2_UINT_UINT_EVENT(ocfs2_resmap_resv_bits); + +TRACE_EVENT(ocfs2_resmap_claimed_bits_begin, + TP_PROTO(unsigned int cstart, unsigned int cend, unsigned int clen, + unsigned int r_start, unsigned int r_end, unsigned int r_len, + unsigned int last_start, unsigned int last_len), + TP_ARGS(cstart, cend, clen, r_start, r_end, + r_len, last_start, last_len), + TP_STRUCT__entry( + __field(unsigned int, cstart) + __field(unsigned int, cend) + __field(unsigned int, clen) + __field(unsigned int, r_start) + __field(unsigned int, r_end) + __field(unsigned int, r_len) + __field(unsigned int, last_start) + __field(unsigned int, last_len) + ), + TP_fast_assign( + __entry->cstart = cstart; + __entry->cend = cend; + __entry->clen = clen; + __entry->r_start = r_start; + __entry->r_end = r_end; + __entry->r_len = r_len; + __entry->last_start = last_start; + __entry->last_len = last_len; + ), + TP_printk("%u %u %u %u %u %u %u %u", + __entry->cstart, __entry->cend, __entry->clen, + __entry->r_start, __entry->r_end, __entry->r_len, + __entry->last_start, __entry->last_len) +); + +TRACE_EVENT(ocfs2_resmap_claimed_bits_end, + TP_PROTO(unsigned int start, unsigned int end, unsigned int len, + unsigned int last_start, unsigned int last_len), + TP_ARGS(start, end, len, last_start, last_len), + TP_STRUCT__entry( + __field(unsigned int, start) + __field(unsigned int, end) + __field(unsigned int, len) + __field(unsigned int, last_start) + __field(unsigned int, last_len) + ), + TP_fast_assign( + __entry->start = start; + __entry->end = end; + __entry->len = len; + __entry->last_start = last_start; + __entry->last_len = last_len; + ), + TP_printk("%u %u %u %u %u", __entry->start, __entry->end, + __entry->len, __entry->last_start, __entry->last_len) +); + +/* End of trace events for fs/ocfs2/reservations.c. */ #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ diff --git a/fs/ocfs2/reservations.c b/fs/ocfs2/reservations.c index 3e78db361bc7..41ffd36c689c 100644 --- a/fs/ocfs2/reservations.c +++ b/fs/ocfs2/reservations.c @@ -30,10 +30,10 @@ #include #include -#define MLOG_MASK_PREFIX ML_RESERVATIONS #include #include "ocfs2.h" +#include "ocfs2_trace.h" #ifdef CONFIG_OCFS2_DEBUG_FS #define OCFS2_CHECK_RESERVATIONS @@ -321,8 +321,7 @@ static void ocfs2_resv_insert(struct ocfs2_reservation_map *resmap, assert_spin_locked(&resv_lock); - mlog(0, "Insert reservation start: %u len: %u\n", new->r_start, - new->r_len); + trace_ocfs2_resv_insert(new->r_start, new->r_len); while (*p) { parent = *p; @@ -423,8 +422,8 @@ static int ocfs2_resmap_find_free_bits(struct ocfs2_reservation_map *resmap, unsigned int best_start, best_len = 0; int offset, start, found; - mlog(0, "Find %u bits within range (%u, len %u) resmap len: %u\n", - wanted, search_start, search_len, resmap->m_bitmap_len); + trace_ocfs2_resmap_find_free_bits_begin(search_start, search_len, + wanted, resmap->m_bitmap_len); found = best_start = best_len = 0; @@ -463,7 +462,7 @@ static int ocfs2_resmap_find_free_bits(struct ocfs2_reservation_map *resmap, *rlen = best_len; *rstart = best_start; - mlog(0, "Found start: %u len: %u\n", best_start, best_len); + trace_ocfs2_resmap_find_free_bits_end(best_start, best_len); return *rlen; } @@ -487,9 +486,8 @@ static void __ocfs2_resv_find_window(struct ocfs2_reservation_map *resmap, * - our window should be last in all reservations * - need to make sure we don't go past end of bitmap */ - - mlog(0, "resv start: %u resv end: %u goal: %u wanted: %u\n", - resv->r_start, ocfs2_resv_end(resv), goal, wanted); + trace_ocfs2_resv_find_window_begin(resv->r_start, ocfs2_resv_end(resv), + goal, wanted, RB_EMPTY_ROOT(root)); assert_spin_locked(&resv_lock); @@ -498,9 +496,6 @@ static void __ocfs2_resv_find_window(struct ocfs2_reservation_map *resmap, * Easiest case - empty tree. We can just take * whatever window of free bits we want. */ - - mlog(0, "Empty root\n"); - clen = ocfs2_resmap_find_free_bits(resmap, wanted, goal, resmap->m_bitmap_len - goal, &cstart, &clen); @@ -524,8 +519,6 @@ static void __ocfs2_resv_find_window(struct ocfs2_reservation_map *resmap, prev_resv = ocfs2_find_resv_lhs(resmap, goal); if (prev_resv == NULL) { - mlog(0, "Goal on LHS of leftmost window\n"); - /* * A NULL here means that the search code couldn't * find a window that starts before goal. @@ -570,13 +563,15 @@ static void __ocfs2_resv_find_window(struct ocfs2_reservation_map *resmap, next_resv = NULL; } + trace_ocfs2_resv_find_window_prev(prev_resv->r_start, + ocfs2_resv_end(prev_resv)); + prev = &prev_resv->r_node; /* Now we do a linear search for a window, starting at 'prev_rsv' */ while (1) { next = rb_next(prev); if (next) { - mlog(0, "One more resv found in linear search\n"); next_resv = rb_entry(next, struct ocfs2_alloc_reservation, r_node); @@ -585,7 +580,6 @@ static void __ocfs2_resv_find_window(struct ocfs2_reservation_map *resmap, gap_end = next_resv->r_start - 1; gap_len = gap_end - gap_start + 1; } else { - mlog(0, "No next node\n"); /* * We're at the rightmost edge of the * tree. See if a reservation between this @@ -596,6 +590,8 @@ static void __ocfs2_resv_find_window(struct ocfs2_reservation_map *resmap, gap_end = resmap->m_bitmap_len - 1; } + trace_ocfs2_resv_find_window_next(next ? next_resv->r_start: -1, + next ? ocfs2_resv_end(next_resv) : -1); /* * No need to check this gap if we have already found * a larger region of free bits. @@ -654,8 +650,9 @@ static void ocfs2_cannibalize_resv(struct ocfs2_reservation_map *resmap, lru_resv = list_first_entry(&resmap->m_lru, struct ocfs2_alloc_reservation, r_lru); - mlog(0, "lru resv: start: %u len: %u end: %u\n", lru_resv->r_start, - lru_resv->r_len, ocfs2_resv_end(lru_resv)); + trace_ocfs2_cannibalize_resv_begin(lru_resv->r_start, + lru_resv->r_len, + ocfs2_resv_end(lru_resv)); /* * Cannibalize (some or all) of the target reservation and @@ -684,10 +681,9 @@ static void ocfs2_cannibalize_resv(struct ocfs2_reservation_map *resmap, resv->r_len = shrink; } - mlog(0, "Reservation now looks like: r_start: %u r_end: %u " - "r_len: %u r_last_start: %u r_last_len: %u\n", - resv->r_start, ocfs2_resv_end(resv), resv->r_len, - resv->r_last_start, resv->r_last_len); + trace_ocfs2_cannibalize_resv_end(resv->r_start, ocfs2_resv_end(resv), + resv->r_len, resv->r_last_start, + resv->r_last_len); ocfs2_resv_insert(resmap, resv); } @@ -748,7 +744,6 @@ int ocfs2_resmap_resv_bits(struct ocfs2_reservation_map *resmap, if ((resv->r_flags & OCFS2_RESV_FLAG_TMP) || wanted < *clen) wanted = *clen; - mlog(0, "empty reservation, find new window\n"); /* * Try to get a window here. If it works, we must fall * through and test the bitmap . This avoids some @@ -757,6 +752,7 @@ int ocfs2_resmap_resv_bits(struct ocfs2_reservation_map *resmap, * that inode. */ ocfs2_resv_find_window(resmap, resv, wanted); + trace_ocfs2_resmap_resv_bits(resv->r_start, resv->r_len); } BUG_ON(ocfs2_resv_empty(resv)); @@ -813,10 +809,10 @@ void ocfs2_resmap_claimed_bits(struct ocfs2_reservation_map *resmap, spin_lock(&resv_lock); - mlog(0, "claim bits: cstart: %u cend: %u clen: %u r_start: %u " - "r_end: %u r_len: %u, r_last_start: %u r_last_len: %u\n", - cstart, cend, clen, resv->r_start, ocfs2_resv_end(resv), - resv->r_len, resv->r_last_start, resv->r_last_len); + trace_ocfs2_resmap_claimed_bits_begin(cstart, cend, clen, resv->r_start, + ocfs2_resv_end(resv), resv->r_len, + resv->r_last_start, + resv->r_last_len); BUG_ON(cstart < resv->r_start); BUG_ON(cstart > ocfs2_resv_end(resv)); @@ -833,10 +829,9 @@ void ocfs2_resmap_claimed_bits(struct ocfs2_reservation_map *resmap, if (!ocfs2_resv_empty(resv)) ocfs2_resv_mark_lru(resmap, resv); - mlog(0, "Reservation now looks like: r_start: %u r_end: %u " - "r_len: %u r_last_start: %u r_last_len: %u\n", - resv->r_start, ocfs2_resv_end(resv), resv->r_len, - resv->r_last_start, resv->r_last_len); + trace_ocfs2_resmap_claimed_bits_end(resv->r_start, ocfs2_resv_end(resv), + resv->r_len, resv->r_last_start, + resv->r_last_len); ocfs2_check_resmap(resmap); -- cgit From 38877a43795d3a834fad827f3d6532ff649e5c45 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Wed, 23 Feb 2011 22:12:48 +0800 Subject: ocfs2: Remove mlog(0) from quota_local.c. Remove mlog(0) from fs/ocfs2/quota_local.c. Signed-off-by: Tao Ma --- fs/ocfs2/ocfs2_trace.h | 10 ++++++++++ fs/ocfs2/quota_local.c | 13 +++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 1c040fcbd6e7..dbd1812f5161 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -1925,6 +1925,16 @@ TRACE_EVENT(ocfs2_resmap_claimed_bits_end, ); /* End of trace events for fs/ocfs2/reservations.c. */ + +/* Trace events for fs/ocfs2/quota_local.c. */ + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_recover_local_quota_file); + +DEFINE_OCFS2_INT_EVENT(ocfs2_finish_quota_recovery); + +DEFINE_OCFS2_ULL_ULL_UINT_EVENT(olq_set_dquot); + +/* End of trace events for fs/ocfs2/quota_local.c. */ #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c index 88ec4516637b..dc8007fc9247 100644 --- a/fs/ocfs2/quota_local.c +++ b/fs/ocfs2/quota_local.c @@ -8,7 +8,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_QUOTA #include #include "ocfs2_fs.h" @@ -23,6 +22,7 @@ #include "quota.h" #include "uptodate.h" #include "super.h" +#include "ocfs2_trace.h" /* Number of local quota structures per block */ static inline unsigned int ol_quota_entries_per_block(struct super_block *sb) @@ -475,7 +475,7 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode, struct ocfs2_recovery_chunk *rchunk, *next; qsize_t spacechange, inodechange; - mlog(0, "ino=%lu type=%u", (unsigned long)lqinode->i_ino, type); + trace_ocfs2_recover_local_quota_file((unsigned long)lqinode->i_ino, type); list_for_each_entry_safe(rchunk, next, &(rec->r_list[type]), rc_list) { chunk = rchunk->rc_chunk; @@ -601,7 +601,7 @@ int ocfs2_finish_quota_recovery(struct ocfs2_super *osb, for (type = 0; type < MAXQUOTAS; type++) { if (list_empty(&(rec->r_list[type]))) continue; - mlog(0, "Recovering quota in slot %d\n", slot_num); + trace_ocfs2_finish_quota_recovery(slot_num); lqinode = ocfs2_get_system_file_inode(osb, ino[type], slot_num); if (!lqinode) { status = -ENOENT; @@ -883,9 +883,10 @@ static void olq_set_dquot(struct buffer_head *bh, void *private) dqblk->dqb_inodemod = cpu_to_le64(od->dq_dquot.dq_dqb.dqb_curinodes - od->dq_originodes); spin_unlock(&dq_data_lock); - mlog(0, "Writing local dquot %u space %lld inodes %lld\n", - od->dq_dquot.dq_id, (long long)le64_to_cpu(dqblk->dqb_spacemod), - (long long)le64_to_cpu(dqblk->dqb_inodemod)); + trace_olq_set_dquot( + (unsigned long long)le64_to_cpu(dqblk->dqb_spacemod), + (unsigned long long)le64_to_cpu(dqblk->dqb_inodemod), + od->dq_dquot.dq_id); } /* Write dquot to local quota file */ -- cgit From 1db986a839d8acf8ad809c876f1154f2e672d3af Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Wed, 23 Feb 2011 22:19:12 +0800 Subject: ocfs2: Remove masklog ML_QUOTA. Remove mlog(0) from fs/ocfs2/quota_global.c and the masklog QUOTA. Signed-off-by: Tao Ma --- fs/ocfs2/cluster/masklog.c | 1 - fs/ocfs2/cluster/masklog.h | 1 - fs/ocfs2/ocfs2_trace.h | 78 ++++++++++++++++++++++++++++++++++++++++++++++ fs/ocfs2/quota_global.c | 24 +++++++------- 4 files changed, 90 insertions(+), 14 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index 39f2a46810d1..90ed4c0ce180 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -102,7 +102,6 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { define_mask(CONN), define_mask(QUORUM), define_mask(EXPORT), - define_mask(QUOTA), define_mask(BASTS), define_mask(CLUSTER), define_mask(ERROR), diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index c36b4d8d5aa9..0e65bae257d6 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -104,7 +104,6 @@ #define ML_CONN 0x0000000004000000ULL /* net connection management */ #define ML_QUORUM 0x0000000008000000ULL /* net connection quorum */ #define ML_EXPORT 0x0000000010000000ULL /* ocfs2 export operations */ -#define ML_QUOTA 0x0000000040000000ULL /* ocfs2 quota operations */ #define ML_BASTS 0x0000000100000000ULL /* dlmglue asts and basts */ #define ML_CLUSTER 0x0000000400000000ULL /* cluster stack */ diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index dbd1812f5161..0f7165914401 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -110,6 +110,25 @@ DEFINE_EVENT(ocfs2__int_int, name, \ TP_PROTO(int val1, int val2), \ TP_ARGS(val1, val2)) +DECLARE_EVENT_CLASS(ocfs2__uint_int, + TP_PROTO(unsigned int value1, int value2), + TP_ARGS(value1, value2), + TP_STRUCT__entry( + __field(unsigned int, value1) + __field(int, value2) + ), + TP_fast_assign( + __entry->value1 = value1; + __entry->value2 = value2; + ), + TP_printk("%u %d", __entry->value1, __entry->value2) +); + +#define DEFINE_OCFS2_UINT_INT_EVENT(name) \ +DEFINE_EVENT(ocfs2__uint_int, name, \ + TP_PROTO(unsigned int val1, int val2), \ + TP_ARGS(val1, val2)) + DECLARE_EVENT_CLASS(ocfs2__uint_uint, TP_PROTO(unsigned int value1, unsigned int value2), TP_ARGS(value1, value2), @@ -1935,6 +1954,65 @@ DEFINE_OCFS2_INT_EVENT(ocfs2_finish_quota_recovery); DEFINE_OCFS2_ULL_ULL_UINT_EVENT(olq_set_dquot); /* End of trace events for fs/ocfs2/quota_local.c. */ + +/* Trace events for fs/ocfs2/quota_global.c. */ + +DEFINE_OCFS2_ULL_EVENT(ocfs2_validate_quota_block); + +TRACE_EVENT(ocfs2_sync_dquot, + TP_PROTO(unsigned int dq_id, long long dqb_curspace, + long long spacechange, long long curinodes, + long long inodechange), + TP_ARGS(dq_id, dqb_curspace, spacechange, curinodes, inodechange), + TP_STRUCT__entry( + __field(unsigned int, dq_id) + __field(long long, dqb_curspace) + __field(long long, spacechange) + __field(long long, curinodes) + __field(long long, inodechange) + ), + TP_fast_assign( + __entry->dq_id = dq_id; + __entry->dqb_curspace = dqb_curspace; + __entry->spacechange = spacechange; + __entry->curinodes = curinodes; + __entry->inodechange = inodechange; + ), + TP_printk("%u %lld %lld %lld %lld", __entry->dq_id, + __entry->dqb_curspace, __entry->spacechange, + __entry->curinodes, __entry->inodechange) +); + +TRACE_EVENT(ocfs2_sync_dquot_helper, + TP_PROTO(unsigned int dq_id, unsigned int dq_type, unsigned long type, + const char *s_id), + TP_ARGS(dq_id, dq_type, type, s_id), + + TP_STRUCT__entry( + __field(unsigned int, dq_id) + __field(unsigned int, dq_type) + __field(unsigned long, type) + __string(s_id, s_id) + ), + TP_fast_assign( + __entry->dq_id = dq_id; + __entry->dq_type = dq_type; + __entry->type = type; + __assign_str(s_id, s_id); + ), + TP_printk("%u %u %lu %s", __entry->dq_id, __entry->dq_type, + __entry->type, __get_str(s_id)) +); + +DEFINE_OCFS2_UINT_INT_EVENT(ocfs2_write_dquot); + +DEFINE_OCFS2_UINT_INT_EVENT(ocfs2_release_dquot); + +DEFINE_OCFS2_UINT_INT_EVENT(ocfs2_acquire_dquot); + +DEFINE_OCFS2_UINT_INT_EVENT(ocfs2_mark_dquot_dirty); + +/* End of trace events for fs/ocfs2/quota_global.c. */ #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c index 10a49e8a5f03..64346f836c09 100644 --- a/fs/ocfs2/quota_global.c +++ b/fs/ocfs2/quota_global.c @@ -11,7 +11,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_QUOTA #include #include "ocfs2_fs.h" @@ -27,6 +26,7 @@ #include "super.h" #include "buffer_head_io.h" #include "quota.h" +#include "ocfs2_trace.h" /* * Locking of quotas with OCFS2 is rather complex. Here are rules that @@ -132,8 +132,7 @@ int ocfs2_validate_quota_block(struct super_block *sb, struct buffer_head *bh) struct ocfs2_disk_dqtrailer *dqt = ocfs2_block_dqtrailer(sb->s_blocksize, bh->b_data); - mlog(0, "Validating quota block %llu\n", - (unsigned long long)bh->b_blocknr); + trace_ocfs2_validate_quota_block((unsigned long long)bh->b_blocknr); BUG_ON(!buffer_uptodate(bh)); @@ -509,9 +508,10 @@ int __ocfs2_sync_dquot(struct dquot *dquot, int freeing) olditime = dquot->dq_dqb.dqb_itime; oldbtime = dquot->dq_dqb.dqb_btime; ocfs2_global_disk2memdqb(dquot, &dqblk); - mlog(0, "Syncing global dquot %u space %lld+%lld, inodes %lld+%lld\n", - dquot->dq_id, dquot->dq_dqb.dqb_curspace, (long long)spacechange, - dquot->dq_dqb.dqb_curinodes, (long long)inodechange); + trace_ocfs2_sync_dquot(dquot->dq_id, dquot->dq_dqb.dqb_curspace, + (long long)spacechange, + dquot->dq_dqb.dqb_curinodes, + (long long)inodechange); if (!test_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags)) dquot->dq_dqb.dqb_curspace += spacechange; if (!test_bit(DQ_LASTSET_B + QIF_INODES_B, &dquot->dq_flags)) @@ -595,8 +595,8 @@ static int ocfs2_sync_dquot_helper(struct dquot *dquot, unsigned long type) struct ocfs2_super *osb = OCFS2_SB(sb); int status = 0; - mlog(0, "id=%u qtype=%u type=%lu device=%s\n", dquot->dq_id, - dquot->dq_type, type, sb->s_id); + trace_ocfs2_sync_dquot_helper(dquot->dq_id, dquot->dq_type, + type, sb->s_id); if (type != dquot->dq_type) goto out; status = ocfs2_lock_global_qf(oinfo, 1); @@ -647,7 +647,7 @@ static int ocfs2_write_dquot(struct dquot *dquot) struct ocfs2_super *osb = OCFS2_SB(dquot->dq_sb); int status = 0; - mlog(0, "id=%u, type=%d", dquot->dq_id, dquot->dq_type); + trace_ocfs2_write_dquot(dquot->dq_id, dquot->dq_type); handle = ocfs2_start_trans(osb, OCFS2_QWRITE_CREDITS); if (IS_ERR(handle)) { @@ -685,7 +685,7 @@ static int ocfs2_release_dquot(struct dquot *dquot) struct ocfs2_super *osb = OCFS2_SB(dquot->dq_sb); int status = 0; - mlog(0, "id=%u, type=%d", dquot->dq_id, dquot->dq_type); + trace_ocfs2_release_dquot(dquot->dq_id, dquot->dq_type); mutex_lock(&dquot->dq_lock); /* Check whether we are not racing with some other dqget() */ @@ -743,7 +743,7 @@ static int ocfs2_acquire_dquot(struct dquot *dquot) int need_alloc = ocfs2_global_qinit_alloc(sb, type); handle_t *handle; - mlog(0, "id=%u, type=%d", dquot->dq_id, type); + trace_ocfs2_acquire_dquot(dquot->dq_id, type); mutex_lock(&dquot->dq_lock); /* * We need an exclusive lock, because we're going to update use count @@ -830,7 +830,7 @@ static int ocfs2_mark_dquot_dirty(struct dquot *dquot) handle_t *handle; struct ocfs2_super *osb = OCFS2_SB(sb); - mlog(0, "id=%u, type=%d", dquot->dq_id, type); + trace_ocfs2_mark_dquot_dirty(dquot->dq_id, type); /* In case user set some limits, sync dquot immediately to global * quota file so that information propagates quicker */ -- cgit From f32037d9bda37ca9a7a179cc1546033d374a8541 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Mon, 21 Feb 2011 11:19:02 +0800 Subject: ocfs2: remove NAMEI from symlink.c No mlog(0,...) in symlink.c, so just remove NAMEI. Signed-off-by: Tao Ma --- fs/ocfs2/symlink.c | 1 - 1 file changed, 1 deletion(-) (limited to 'fs') diff --git a/fs/ocfs2/symlink.c b/fs/ocfs2/symlink.c index 5485b19ec8f2..5d22872e2bb3 100644 --- a/fs/ocfs2/symlink.c +++ b/fs/ocfs2/symlink.c @@ -40,7 +40,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_NAMEI #include #include "ocfs2.h" -- cgit From f1088d471f8d846e817eb4d673212d18d9820c61 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Wed, 23 Feb 2011 22:30:23 +0800 Subject: ocfs2: Remove mlog(0) from fs/ocfs2/dir.c This is the 2nd step to remove the debug info of NAMEI. Signed-off-by: Tao Ma --- fs/ocfs2/dir.c | 83 ++++++++++++++++------------------- fs/ocfs2/ocfs2_trace.h | 116 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 153 insertions(+), 46 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index 2fc6c3673bea..0740752ca31e 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c @@ -43,7 +43,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_NAMEI #include #include "ocfs2.h" @@ -61,6 +60,7 @@ #include "super.h" #include "sysfile.h" #include "uptodate.h" +#include "ocfs2_trace.h" #include "buffer_head_io.h" @@ -400,7 +400,7 @@ static int inline ocfs2_search_dirblock(struct buffer_head *bh, } bail: - mlog(0, "ret = %d\n", ret); + trace_ocfs2_search_dirblock(ret); return ret; } @@ -445,8 +445,7 @@ static int ocfs2_validate_dir_block(struct super_block *sb, * We don't validate dirents here, that's handled * in-place when the code walks them. */ - mlog(0, "Validating dirblock %llu\n", - (unsigned long long)bh->b_blocknr); + trace_ocfs2_validate_dir_block((unsigned long long)bh->b_blocknr); BUG_ON(!buffer_uptodate(bh)); @@ -784,7 +783,7 @@ cleanup_and_exit: for (; ra_ptr < ra_max; ra_ptr++) brelse(bh_use[ra_ptr]); - mlog(0, "ret = %p\n", ret); + trace_ocfs2_find_entry_el(ret); return ret; } @@ -946,11 +945,9 @@ static int ocfs2_dx_dir_search(const char *name, int namelen, goto out; } - mlog(0, "Dir %llu: name: \"%.*s\", lookup of hash: %u.0x%x " - "returns: %llu\n", - (unsigned long long)OCFS2_I(dir)->ip_blkno, - namelen, name, hinfo->major_hash, hinfo->minor_hash, - (unsigned long long)phys); + trace_ocfs2_dx_dir_search((unsigned long long)OCFS2_I(dir)->ip_blkno, + namelen, name, hinfo->major_hash, + hinfo->minor_hash, (unsigned long long)phys); ret = ocfs2_read_dx_leaf(dir, phys, &dx_leaf_bh); if (ret) { @@ -960,9 +957,9 @@ static int ocfs2_dx_dir_search(const char *name, int namelen, dx_leaf = (struct ocfs2_dx_leaf *) dx_leaf_bh->b_data; - mlog(0, "leaf info: num_used: %d, count: %d\n", - le16_to_cpu(dx_leaf->dl_list.de_num_used), - le16_to_cpu(dx_leaf->dl_list.de_count)); + trace_ocfs2_dx_dir_search_leaf_info( + le16_to_cpu(dx_leaf->dl_list.de_num_used), + le16_to_cpu(dx_leaf->dl_list.de_count)); entry_list = &dx_leaf->dl_list; @@ -1162,8 +1159,6 @@ static int __ocfs2_delete_entry(handle_t *handle, struct inode *dir, int i, status = -ENOENT; ocfs2_journal_access_func access = ocfs2_journal_access_db; - mlog(0, "(0x%p, 0x%p, 0x%p, 0x%p)\n", handle, dir, de_del, bh); - if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL) access = ocfs2_journal_access_di; @@ -1343,8 +1338,8 @@ static int ocfs2_delete_entry_dx(handle_t *handle, struct inode *dir, } } - mlog(0, "Dir %llu: delete entry at index: %d\n", - (unsigned long long)OCFS2_I(dir)->ip_blkno, index); + trace_ocfs2_delete_entry_dx((unsigned long long)OCFS2_I(dir)->ip_blkno, + index); ret = __ocfs2_delete_entry(handle, dir, lookup->dl_entry, leaf_bh, leaf_bh->b_data, leaf_bh->b_size); @@ -2022,8 +2017,7 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) struct inode *inode = filp->f_path.dentry->d_inode; int lock_level = 0; - mlog(0, "dirino=%llu\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno); + trace_ocfs2_readdir((unsigned long long)OCFS2_I(inode)->ip_blkno); error = ocfs2_inode_lock_atime(inode, filp->f_vfsmnt, &lock_level); if (lock_level && error >= 0) { @@ -2064,8 +2058,8 @@ int ocfs2_find_files_on_disk(const char *name, { int status = -ENOENT; - mlog(0, "name=%.*s, blkno=%p, inode=%llu\n", namelen, name, blkno, - (unsigned long long)OCFS2_I(inode)->ip_blkno); + trace_ocfs2_find_files_on_disk(namelen, name, blkno, + (unsigned long long)OCFS2_I(inode)->ip_blkno); status = ocfs2_find_entry(name, namelen, inode, lookup); if (status) @@ -2109,8 +2103,8 @@ int ocfs2_check_dir_for_entry(struct inode *dir, int ret; struct ocfs2_dir_lookup_result lookup = { NULL, }; - mlog(0, "dir %llu, name '%.*s'\n", - (unsigned long long)OCFS2_I(dir)->ip_blkno, namelen, name); + trace_ocfs2_check_dir_for_entry( + (unsigned long long)OCFS2_I(dir)->ip_blkno, namelen, name); ret = -EEXIST; if (ocfs2_find_entry(name, namelen, dir, &lookup) == 0) @@ -2402,9 +2396,9 @@ static int ocfs2_dx_dir_attach_index(struct ocfs2_super *osb, goto out; } - mlog(0, "Dir %llu, attach new index block: %llu\n", - (unsigned long long)OCFS2_I(dir)->ip_blkno, - (unsigned long long)dr_blkno); + trace_ocfs2_dx_dir_attach_index( + (unsigned long long)OCFS2_I(dir)->ip_blkno, + (unsigned long long)dr_blkno); dx_root_bh = sb_getblk(osb->sb, dr_blkno); if (dx_root_bh == NULL) { @@ -2504,11 +2498,10 @@ static int ocfs2_dx_dir_format_cluster(struct ocfs2_super *osb, dx_leaf->dl_list.de_count = cpu_to_le16(ocfs2_dx_entries_per_leaf(osb->sb)); - mlog(0, - "Dir %llu, format dx_leaf: %llu, entry count: %u\n", - (unsigned long long)OCFS2_I(dir)->ip_blkno, - (unsigned long long)bh->b_blocknr, - le16_to_cpu(dx_leaf->dl_list.de_count)); + trace_ocfs2_dx_dir_format_cluster( + (unsigned long long)OCFS2_I(dir)->ip_blkno, + (unsigned long long)bh->b_blocknr, + le16_to_cpu(dx_leaf->dl_list.de_count)); ocfs2_journal_dirty(handle, bh); } @@ -2752,12 +2745,11 @@ static void ocfs2_dx_dir_index_root_block(struct inode *dir, ocfs2_dx_dir_name_hash(dir, de->name, de->name_len, &hinfo); - mlog(0, - "dir: %llu, major: 0x%x minor: 0x%x, index: %u, name: %.*s\n", - (unsigned long long)dir->i_ino, hinfo.major_hash, - hinfo.minor_hash, - le16_to_cpu(dx_root->dr_entries.de_num_used), - de->name_len, de->name); + trace_ocfs2_dx_dir_index_root_block( + (unsigned long long)dir->i_ino, + hinfo.major_hash, hinfo.minor_hash, + de->name_len, de->name, + le16_to_cpu(dx_root->dr_entries.de_num_used)); ocfs2_dx_entry_list_insert(&dx_root->dr_entries, &hinfo, dirent_blk); @@ -3310,8 +3302,8 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb, down_write(&OCFS2_I(dir)->ip_alloc_sem); drop_alloc_sem = 1; dir_i_size = i_size_read(dir); - mlog(0, "extending dir %llu (i_size = %lld)\n", - (unsigned long long)OCFS2_I(dir)->ip_blkno, dir_i_size); + trace_ocfs2_extend_dir((unsigned long long)OCFS2_I(dir)->ip_blkno, + dir_i_size); /* dir->i_size is always block aligned. */ spin_lock(&OCFS2_I(dir)->ip_lock); @@ -3805,9 +3797,9 @@ static int ocfs2_dx_dir_rebalance(struct ocfs2_super *osb, struct inode *dir, struct ocfs2_dx_root_block *dx_root; struct ocfs2_dx_leaf *tmp_dx_leaf = NULL; - mlog(0, "DX Dir: %llu, rebalance leaf leaf_blkno: %llu insert: %u\n", - (unsigned long long)OCFS2_I(dir)->ip_blkno, - (unsigned long long)leaf_blkno, insert_hash); + trace_ocfs2_dx_dir_rebalance((unsigned long long)OCFS2_I(dir)->ip_blkno, + (unsigned long long)leaf_blkno, + insert_hash); ocfs2_init_dx_root_extent_tree(&et, INODE_CACHE(dir), dx_root_bh); @@ -3887,8 +3879,7 @@ static int ocfs2_dx_dir_rebalance(struct ocfs2_super *osb, struct inode *dir, goto out_commit; } - mlog(0, "Split leaf (%u) at %u, insert major hash is %u\n", - leaf_cpos, split_hash, insert_hash); + trace_ocfs2_dx_dir_rebalance_split(leaf_cpos, split_hash, insert_hash); /* * We have to carefully order operations here. There are items @@ -4345,8 +4336,8 @@ int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb, unsigned int blocks_wanted = 1; struct buffer_head *bh = NULL; - mlog(0, "getting ready to insert namelen %d into dir %llu\n", - namelen, (unsigned long long)OCFS2_I(dir)->ip_blkno); + trace_ocfs2_prepare_dir_for_insert( + (unsigned long long)OCFS2_I(dir)->ip_blkno, namelen); if (!namelen) { ret = -EINVAL; diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 0f7165914401..25e057e9d14d 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -2013,6 +2013,122 @@ DEFINE_OCFS2_UINT_INT_EVENT(ocfs2_acquire_dquot); DEFINE_OCFS2_UINT_INT_EVENT(ocfs2_mark_dquot_dirty); /* End of trace events for fs/ocfs2/quota_global.c. */ + +/* Trace events for fs/ocfs2/dir.c. */ +DEFINE_OCFS2_INT_EVENT(ocfs2_search_dirblock); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_validate_dir_block); + +DEFINE_OCFS2_POINTER_EVENT(ocfs2_find_entry_el); + +TRACE_EVENT(ocfs2_dx_dir_search, + TP_PROTO(unsigned long long ino, int namelen, const char *name, + unsigned int major_hash, unsigned int minor_hash, + unsigned long long blkno), + TP_ARGS(ino, namelen, name, major_hash, minor_hash, blkno), + TP_STRUCT__entry( + __field(unsigned long long, ino) + __field(int, namelen) + __string(name, name) + __field(unsigned int, major_hash) + __field(unsigned int,minor_hash) + __field(unsigned long long, blkno) + ), + TP_fast_assign( + __entry->ino = ino; + __entry->namelen = namelen; + __assign_str(name, name); + __entry->major_hash = major_hash; + __entry->minor_hash = minor_hash; + __entry->blkno = blkno; + ), + TP_printk("%llu %.*s %u %u %llu", __entry->ino, + __entry->namelen, __get_str(name), + __entry->major_hash, __entry->minor_hash, __entry->blkno) +); + +DEFINE_OCFS2_UINT_UINT_EVENT(ocfs2_dx_dir_search_leaf_info); + +DEFINE_OCFS2_ULL_INT_EVENT(ocfs2_delete_entry_dx); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_readdir); + +TRACE_EVENT(ocfs2_find_files_on_disk, + TP_PROTO(int namelen, const char *name, void *blkno, + unsigned long long dir), + TP_ARGS(namelen, name, blkno, dir), + TP_STRUCT__entry( + __field(int, namelen) + __string(name, name) + __field(void *, blkno) + __field(unsigned long long, dir) + ), + TP_fast_assign( + __entry->namelen = namelen; + __assign_str(name, name); + __entry->blkno = blkno; + __entry->dir = dir; + ), + TP_printk("%.*s %p %llu", __entry->namelen, __get_str(name), + __entry->blkno, __entry->dir) +); + +TRACE_EVENT(ocfs2_check_dir_for_entry, + TP_PROTO(unsigned long long dir, int namelen, const char *name), + TP_ARGS(dir, namelen, name), + TP_STRUCT__entry( + __field(unsigned long long, dir) + __field(int, namelen) + __string(name, name) + ), + TP_fast_assign( + __entry->dir = dir; + __entry->namelen = namelen; + __assign_str(name, name); + ), + TP_printk("%llu %.*s", __entry->dir, + __entry->namelen, __get_str(name)) +); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_dx_dir_attach_index); + +DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_dx_dir_format_cluster); + +TRACE_EVENT(ocfs2_dx_dir_index_root_block, + TP_PROTO(unsigned long long dir, + unsigned int major_hash, unsigned int minor_hash, + int namelen, const char *name, unsigned int num_used), + TP_ARGS(dir, major_hash, minor_hash, namelen, name, num_used), + TP_STRUCT__entry( + __field(unsigned long long, dir) + __field(unsigned int, major_hash) + __field(unsigned int, minor_hash) + __field(int, namelen) + __string(name, name) + __field(unsigned int, num_used) + ), + TP_fast_assign( + __entry->dir = dir; + __entry->major_hash = major_hash; + __entry->minor_hash = minor_hash; + __entry->namelen = namelen; + __assign_str(name, name); + __entry->num_used = num_used; + ), + TP_printk("%llu %x %x %.*s %u", __entry->dir, + __entry->major_hash, __entry->minor_hash, + __entry->namelen, __get_str(name), __entry->num_used) +); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_extend_dir); + +DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_dx_dir_rebalance); + +DEFINE_OCFS2_UINT_UINT_UINT_EVENT(ocfs2_dx_dir_rebalance_split); + +DEFINE_OCFS2_ULL_INT_EVENT(ocfs2_prepare_dir_for_insert); + +/* End of trace events for fs/ocfs2/dir.c. */ #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ -- cgit From 8990e44a2bceaa68018fb13000e3a4497d78a53c Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Wed, 23 Feb 2011 22:45:26 +0800 Subject: ocfs2: Remove masklog ML_NAMEI. Remove mlog(0) from fs/ocfs2/namei.c and the masklog NAMEI finally. Signed-off-by: Tao Ma --- fs/ocfs2/cluster/masklog.c | 1 - fs/ocfs2/cluster/masklog.h | 1 - fs/ocfs2/namei.c | 126 +++++++++++------------- fs/ocfs2/ocfs2_trace.h | 235 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 292 insertions(+), 71 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index 90ed4c0ce180..0668eb6e05d6 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -96,7 +96,6 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { define_mask(DLM_GLUE), define_mask(BH_IO), define_mask(UPTODATE), - define_mask(NAMEI), define_mask(VOTE), define_mask(DCACHE), define_mask(CONN), diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index 0e65bae257d6..a815b55d87a7 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -98,7 +98,6 @@ #define ML_DLM_GLUE 0x0000000000080000ULL /* ocfs2 dlm glue layer */ #define ML_BH_IO 0x0000000000100000ULL /* ocfs2 buffer I/O */ #define ML_UPTODATE 0x0000000000200000ULL /* ocfs2 caching sequence #'s */ -#define ML_NAMEI 0x0000000000400000ULL /* ocfs2 directory / namespace */ #define ML_VOTE 0x0000000001000000ULL /* ocfs2 node messaging */ #define ML_DCACHE 0x0000000002000000ULL /* ocfs2 dcache operations */ #define ML_CONN 0x0000000004000000ULL /* net connection management */ diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 8a13226eb1a2..b6fa9eb2d298 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c @@ -42,7 +42,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_NAMEI #include #include "ocfs2.h" @@ -63,6 +62,7 @@ #include "uptodate.h" #include "xattr.h" #include "acl.h" +#include "ocfs2_trace.h" #include "buffer_head_io.h" @@ -106,17 +106,15 @@ static struct dentry *ocfs2_lookup(struct inode *dir, struct dentry *dentry, struct dentry *ret; struct ocfs2_inode_info *oi; - mlog(0, "(0x%p, 0x%p, '%.*s')\n", dir, dentry, - dentry->d_name.len, dentry->d_name.name); + trace_ocfs2_lookup(dir, dentry, dentry->d_name.len, + dentry->d_name.name, + (unsigned long long)OCFS2_I(dir)->ip_blkno, 0); if (dentry->d_name.len > OCFS2_MAX_FILENAME_LEN) { ret = ERR_PTR(-ENAMETOOLONG); goto bail; } - mlog(0, "find name %.*s in directory %llu\n", dentry->d_name.len, - dentry->d_name.name, (unsigned long long)OCFS2_I(dir)->ip_blkno); - status = ocfs2_inode_lock_nested(dir, NULL, 0, OI_LS_PARENT); if (status < 0) { if (status != -ENOENT) @@ -182,7 +180,7 @@ bail_unlock: bail: - mlog(0, "%p\n", ret); + trace_ocfs2_lookup_ret(ret); return ret; } @@ -235,9 +233,9 @@ static int ocfs2_mknod(struct inode *dir, sigset_t oldset; int did_block_signals = 0; - mlog(0, "(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry, mode, - (unsigned long)dev, dentry->d_name.len, - dentry->d_name.name); + trace_ocfs2_mknod(dir, dentry, dentry->d_name.len, dentry->d_name.name, + (unsigned long long)OCFS2_I(dir)->ip_blkno, + (unsigned long)dev, mode); dquot_initialize(dir); @@ -354,10 +352,6 @@ static int ocfs2_mknod(struct inode *dir, goto leave; did_quota_inode = 1; - mlog(0, "(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry, - inode->i_mode, (unsigned long)dev, dentry->d_name.len, - dentry->d_name.name); - /* do the real work now. */ status = ocfs2_mknod_locked(osb, dir, inode, dev, &new_fe_bh, parent_fe_bh, handle, @@ -436,9 +430,6 @@ leave: if (did_block_signals) ocfs2_unblock_signals(&oldset); - if (status == -ENOSPC) - mlog(0, "Disk is full\n"); - brelse(new_fe_bh); brelse(parent_fe_bh); kfree(si.name); @@ -617,8 +608,8 @@ static int ocfs2_mkdir(struct inode *dir, { int ret; - mlog(0, "(0x%p, 0x%p, %d, '%.*s')\n", dir, dentry, mode, - dentry->d_name.len, dentry->d_name.name); + trace_ocfs2_mkdir(dir, dentry, dentry->d_name.len, dentry->d_name.name, + OCFS2_I(dir)->ip_blkno, mode); ret = ocfs2_mknod(dir, dentry, mode | S_IFDIR, 0); if (ret) mlog_errno(ret); @@ -633,8 +624,8 @@ static int ocfs2_create(struct inode *dir, { int ret; - mlog(0, "(0x%p, 0x%p, %d, '%.*s')\n", dir, dentry, mode, - dentry->d_name.len, dentry->d_name.name); + trace_ocfs2_create(dir, dentry, dentry->d_name.len, dentry->d_name.name, + (unsigned long long)OCFS2_I(dir)->ip_blkno, mode); ret = ocfs2_mknod(dir, dentry, mode | S_IFREG, 0); if (ret) mlog_errno(ret); @@ -656,9 +647,9 @@ static int ocfs2_link(struct dentry *old_dentry, struct ocfs2_dir_lookup_result lookup = { NULL, }; sigset_t oldset; - mlog(0, "(inode=%lu, old='%.*s' new='%.*s')\n", inode->i_ino, - old_dentry->d_name.len, old_dentry->d_name.name, - dentry->d_name.len, dentry->d_name.name); + 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); if (S_ISDIR(inode->i_mode)) return -EPERM; @@ -814,19 +805,17 @@ static int ocfs2_unlink(struct inode *dir, struct ocfs2_dir_lookup_result lookup = { NULL, }; struct ocfs2_dir_lookup_result orphan_insert = { NULL, }; - mlog(0, "(0x%p, 0x%p, '%.*s')\n", dir, dentry, - dentry->d_name.len, dentry->d_name.name); + trace_ocfs2_unlink(dir, dentry, dentry->d_name.len, + dentry->d_name.name, + (unsigned long long)OCFS2_I(dir)->ip_blkno, + (unsigned long long)OCFS2_I(inode)->ip_blkno); dquot_initialize(dir); BUG_ON(dentry->d_parent->d_inode != dir); - mlog(0, "ino = %llu\n", (unsigned long long)OCFS2_I(inode)->ip_blkno); - - if (inode == osb->root_inode) { - mlog(0, "Cannot delete the root directory\n"); + if (inode == osb->root_inode) return -EPERM; - } status = ocfs2_inode_lock_nested(dir, &parent_node_bh, 1, OI_LS_PARENT); @@ -848,9 +837,10 @@ static int ocfs2_unlink(struct inode *dir, if (OCFS2_I(inode)->ip_blkno != blkno) { status = -ENOENT; - mlog(0, "ip_blkno %llu != dirent blkno %llu ip_flags = %x\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno, - (unsigned long long)blkno, OCFS2_I(inode)->ip_flags); + trace_ocfs2_unlink_noent( + (unsigned long long)OCFS2_I(inode)->ip_blkno, + (unsigned long long)blkno, + OCFS2_I(inode)->ip_flags); goto leave; } @@ -981,9 +971,8 @@ static int ocfs2_double_lock(struct ocfs2_super *osb, struct buffer_head **tmpbh; struct inode *tmpinode; - mlog(0, "(inode1 = %llu, inode2 = %llu)\n", - (unsigned long long)oi1->ip_blkno, - (unsigned long long)oi2->ip_blkno); + trace_ocfs2_double_lock((unsigned long long)oi1->ip_blkno, + (unsigned long long)oi2->ip_blkno); if (*bh1) *bh1 = NULL; @@ -994,7 +983,6 @@ static int ocfs2_double_lock(struct ocfs2_super *osb, if (oi1->ip_blkno != oi2->ip_blkno) { if (oi1->ip_blkno < oi2->ip_blkno) { /* switch id1 and id2 around */ - mlog(0, "switching them around...\n"); tmpbh = bh2; bh2 = bh1; bh1 = tmpbh; @@ -1030,6 +1018,10 @@ static int ocfs2_double_lock(struct ocfs2_super *osb, mlog_errno(status); } + trace_ocfs2_double_lock_end( + (unsigned long long)OCFS2_I(inode1)->ip_blkno, + (unsigned long long)OCFS2_I(inode2)->ip_blkno); + bail: if (status) mlog_errno(status); @@ -1074,10 +1066,9 @@ static int ocfs2_rename(struct inode *old_dir, /* At some point it might be nice to break this function up a * bit. */ - mlog(0, "(0x%p, 0x%p, 0x%p, 0x%p, from='%.*s' to='%.*s')\n", - old_dir, old_dentry, new_dir, new_dentry, - old_dentry->d_name.len, old_dentry->d_name.name, - new_dentry->d_name.len, new_dentry->d_name.name); + trace_ocfs2_rename(old_dir, old_dentry, new_dir, new_dentry, + old_dentry->d_name.len, old_dentry->d_name.name, + new_dentry->d_name.len, new_dentry->d_name.name); dquot_initialize(old_dir); dquot_initialize(new_dir); @@ -1234,16 +1225,15 @@ static int ocfs2_rename(struct inode *old_dir, if (!new_inode) { status = -EACCES; - mlog(0, "We found an inode for name %.*s but VFS " - "didn't give us one.\n", new_dentry->d_name.len, - new_dentry->d_name.name); + trace_ocfs2_rename_target_exists(new_dentry->d_name.len, + new_dentry->d_name.name); goto bail; } if (OCFS2_I(new_inode)->ip_blkno != newfe_blkno) { status = -EACCES; - mlog(0, "Inode %llu and dir %llu disagree. flags = %x\n", + trace_ocfs2_rename_disagree( (unsigned long long)OCFS2_I(new_inode)->ip_blkno, (unsigned long long)newfe_blkno, OCFS2_I(new_inode)->ip_flags); @@ -1266,8 +1256,7 @@ static int ocfs2_rename(struct inode *old_dir, newfe = (struct ocfs2_dinode *) newfe_bh->b_data; - mlog(0, "aha rename over existing... new_blkno=%llu " - "newfebh=%p bhblocknr=%llu\n", + trace_ocfs2_rename_over_existing( (unsigned long long)newfe_blkno, newfe_bh, newfe_bh ? (unsigned long long)newfe_bh->b_blocknr : 0ULL); @@ -1509,9 +1498,8 @@ static int ocfs2_create_symlink_data(struct ocfs2_super *osb, * write i_size + 1 bytes. */ blocks = (bytes_left + sb->s_blocksize - 1) >> sb->s_blocksize_bits; - mlog(0, "i_blocks = %llu, i_size = %llu, blocks = %d\n", - (unsigned long long)inode->i_blocks, - i_size_read(inode), blocks); + trace_ocfs2_create_symlink_data((unsigned long long)inode->i_blocks, + i_size_read(inode), blocks); /* Sanity check -- make sure we're going to fit. */ if (bytes_left > @@ -1619,8 +1607,8 @@ static int ocfs2_symlink(struct inode *dir, sigset_t oldset; int did_block_signals = 0; - mlog(0, "(0x%p, 0x%p, symname='%s' actual='%.*s')\n", dir, - dentry, symname, dentry->d_name.len, dentry->d_name.name); + trace_ocfs2_symlink_begin(dir, dentry, symname, + dentry->d_name.len, dentry->d_name.name); dquot_initialize(dir); @@ -1722,9 +1710,10 @@ static int ocfs2_symlink(struct inode *dir, goto bail; did_quota_inode = 1; - mlog(0, "(0x%p, 0x%p, %d, '%.*s')\n", dir, dentry, - inode->i_mode, dentry->d_name.len, - dentry->d_name.name); + trace_ocfs2_symlink_create(dir, dentry, dentry->d_name.len, + dentry->d_name.name, + (unsigned long long)OCFS2_I(dir)->ip_blkno, + inode->i_mode); status = ocfs2_mknod_locked(osb, dir, inode, 0, &new_fe_bh, parent_fe_bh, handle, @@ -1870,8 +1859,7 @@ static int ocfs2_blkno_stringify(u64 blkno, char *name) goto bail; } - mlog(0, "built filename '%s' for orphan dir (len=%d)\n", name, - namelen); + trace_ocfs2_blkno_stringify(blkno, name, namelen); status = 0; bail: @@ -2007,7 +1995,8 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb, struct ocfs2_dinode *orphan_fe; struct ocfs2_dinode *fe = (struct ocfs2_dinode *) fe_bh->b_data; - mlog(0, "(inode->i_ino = %lu)\n", inode->i_ino); + trace_ocfs2_orphan_add_begin( + (unsigned long long)OCFS2_I(inode)->ip_blkno); status = ocfs2_read_inode_block(orphan_dir_inode, &orphan_dir_bh); if (status < 0) { @@ -2066,8 +2055,8 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb, ocfs2_journal_dirty(handle, fe_bh); - mlog(0, "Inode %llu orphaned in slot %d\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno, osb->slot_num); + trace_ocfs2_orphan_add_end((unsigned long long)OCFS2_I(inode)->ip_blkno, + osb->slot_num); leave: brelse(orphan_dir_bh); @@ -2095,9 +2084,9 @@ int ocfs2_orphan_del(struct ocfs2_super *osb, goto leave; } - mlog(0, "removing '%s' from orphan dir %llu (namelen=%d)\n", - name, (unsigned long long)OCFS2_I(orphan_dir_inode)->ip_blkno, - OCFS2_ORPHAN_NAMELEN); + trace_ocfs2_orphan_del( + (unsigned long long)OCFS2_I(orphan_dir_inode)->ip_blkno, + name, OCFS2_ORPHAN_NAMELEN); /* find it's spot in the orphan directory */ status = ocfs2_find_entry(name, OCFS2_ORPHAN_NAMELEN, orphan_dir_inode, @@ -2331,9 +2320,6 @@ leave: iput(orphan_dir); } - if (status == -ENOSPC) - mlog(0, "Disk is full\n"); - if ((status < 0) && inode) { clear_nlink(inode); iput(inode); @@ -2368,8 +2354,10 @@ int ocfs2_mv_orphaned_inode_to_new(struct inode *dir, struct buffer_head *di_bh = NULL; struct ocfs2_dir_lookup_result lookup = { NULL, }; - mlog(0, "(0x%p, 0x%p, %.*s')\n", dir, dentry, - dentry->d_name.len, dentry->d_name.name); + trace_ocfs2_mv_orphaned_inode_to_new(dir, dentry, + dentry->d_name.len, dentry->d_name.name, + (unsigned long long)OCFS2_I(dir)->ip_blkno, + (unsigned long long)OCFS2_I(inode)->ip_blkno); status = ocfs2_inode_lock(dir, &parent_di_bh, 1); if (status < 0) { diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 25e057e9d14d..a98e52ae06ee 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -2129,6 +2129,241 @@ DEFINE_OCFS2_UINT_UINT_UINT_EVENT(ocfs2_dx_dir_rebalance_split); DEFINE_OCFS2_ULL_INT_EVENT(ocfs2_prepare_dir_for_insert); /* End of trace events for fs/ocfs2/dir.c. */ + +/* Trace events for fs/ocfs2/namei.c. */ + +DECLARE_EVENT_CLASS(ocfs2__dentry_ops, + TP_PROTO(void *dir, void *dentry, int name_len, const char *name, + unsigned long long dir_blkno, unsigned long long extra), + TP_ARGS(dir, dentry, name_len, name, dir_blkno, extra), + TP_STRUCT__entry( + __field(void *, dir) + __field(void *, dentry) + __field(int, name_len) + __string(name, name) + __field(unsigned long long, dir_blkno) + __field(unsigned long long, extra) + ), + TP_fast_assign( + __entry->dir = dir; + __entry->dentry = dentry; + __entry->name_len = name_len; + __assign_str(name, name); + __entry->dir_blkno = dir_blkno; + __entry->extra = extra; + ), + TP_printk("%p %p %.*s %llu %llu", __entry->dir, __entry->dentry, + __entry->name_len, __get_str(name), + __entry->dir_blkno, __entry->extra) +); + +#define DEFINE_OCFS2_DENTRY_OPS(name) \ +DEFINE_EVENT(ocfs2__dentry_ops, name, \ +TP_PROTO(void *dir, void *dentry, int name_len, const char *name, \ + unsigned long long dir_blkno, unsigned long long extra), \ + TP_ARGS(dir, dentry, name_len, name, dir_blkno, extra)) + +DEFINE_OCFS2_DENTRY_OPS(ocfs2_lookup); + +DEFINE_OCFS2_DENTRY_OPS(ocfs2_mkdir); + +DEFINE_OCFS2_DENTRY_OPS(ocfs2_create); + +DEFINE_OCFS2_DENTRY_OPS(ocfs2_unlink); + +DEFINE_OCFS2_DENTRY_OPS(ocfs2_symlink_create); + +DEFINE_OCFS2_DENTRY_OPS(ocfs2_mv_orphaned_inode_to_new); + +DEFINE_OCFS2_POINTER_EVENT(ocfs2_lookup_ret); + +TRACE_EVENT(ocfs2_mknod, + TP_PROTO(void *dir, void *dentry, int name_len, const char *name, + unsigned long long dir_blkno, unsigned long dev, int mode), + TP_ARGS(dir, dentry, name_len, name, dir_blkno, dev, mode), + TP_STRUCT__entry( + __field(void *, dir) + __field(void *, dentry) + __field(int, name_len) + __string(name, name) + __field(unsigned long long, dir_blkno) + __field(unsigned long, dev) + __field(int, mode) + ), + TP_fast_assign( + __entry->dir = dir; + __entry->dentry = dentry; + __entry->name_len = name_len; + __assign_str(name, name); + __entry->dir_blkno = dir_blkno; + __entry->dev = dev; + __entry->mode = mode; + ), + TP_printk("%p %p %.*s %llu %lu %d", __entry->dir, __entry->dentry, + __entry->name_len, __get_str(name), + __entry->dir_blkno, __entry->dev, __entry->mode) +); + +TRACE_EVENT(ocfs2_link, + TP_PROTO(unsigned long long ino, int old_len, const char *old_name, + int name_len, const char *name), + TP_ARGS(ino, old_len, old_name, name_len, name), + TP_STRUCT__entry( + __field(unsigned long long, ino) + __field(int, old_len) + __string(old_name, old_name) + __field(int, name_len) + __string(name, name) + ), + TP_fast_assign( + __entry->ino = ino; + __entry->old_len = old_len; + __assign_str(old_name, old_name); + __entry->name_len = name_len; + __assign_str(name, name); + ), + TP_printk("%llu %.*s %.*s", __entry->ino, + __entry->old_len, __get_str(old_name), + __entry->name_len, __get_str(name)) +); + +DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_unlink_noent); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_double_lock); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_double_lock_end); + +TRACE_EVENT(ocfs2_rename, + TP_PROTO(void *old_dir, void *old_dentry, + void *new_dir, void *new_dentry, + int old_len, const char *old_name, + int new_len, const char *new_name), + TP_ARGS(old_dir, old_dentry, new_dir, new_dentry, + old_len, old_name, new_len, new_name), + TP_STRUCT__entry( + __field(void *, old_dir) + __field(void *, old_dentry) + __field(void *, new_dir) + __field(void *, new_dentry) + __field(int, old_len) + __string(old_name, old_name) + __field(int, new_len) + __string(new_name, new_name) + ), + TP_fast_assign( + __entry->old_dir = old_dir; + __entry->old_dentry = old_dentry; + __entry->new_dir = new_dir; + __entry->new_dentry = new_dentry; + __entry->old_len = old_len; + __assign_str(old_name, old_name); + __entry->new_len = new_len; + __assign_str(new_name, new_name); + ), + TP_printk("%p %p %p %p %.*s %.*s", + __entry->old_dir, __entry->old_dentry, + __entry->new_dir, __entry->new_dentry, + __entry->old_len, __get_str(old_name), + __entry->new_len, __get_str(new_name)) +); + +TRACE_EVENT(ocfs2_rename_target_exists, + TP_PROTO(int new_len, const char *new_name), + TP_ARGS(new_len, new_name), + TP_STRUCT__entry( + __field(int, new_len) + __string(new_name, new_name) + ), + TP_fast_assign( + __entry->new_len = new_len; + __assign_str(new_name, new_name); + ), + TP_printk("%.*s", __entry->new_len, __get_str(new_name)) +); + +DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_rename_disagree); + +TRACE_EVENT(ocfs2_rename_over_existing, + TP_PROTO(unsigned long long new_blkno, void *new_bh, + unsigned long long newdi_blkno), + TP_ARGS(new_blkno, new_bh, newdi_blkno), + TP_STRUCT__entry( + __field(unsigned long long, new_blkno) + __field(void *, new_bh) + __field(unsigned long long, newdi_blkno) + ), + TP_fast_assign( + __entry->new_blkno = new_blkno; + __entry->new_bh = new_bh; + __entry->newdi_blkno = newdi_blkno; + ), + TP_printk("%llu %p %llu", __entry->new_blkno, __entry->new_bh, + __entry->newdi_blkno) +); + +DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_create_symlink_data); + +TRACE_EVENT(ocfs2_symlink_begin, + TP_PROTO(void *dir, void *dentry, const char *symname, + int len, const char *name), + TP_ARGS(dir, dentry, symname, len, name), + TP_STRUCT__entry( + __field(void *, dir) + __field(void *, dentry) + __field(const char *, symname) + __field(int, len) + __string(name, name) + ), + TP_fast_assign( + __entry->dir = dir; + __entry->dentry = dentry; + __entry->symname = symname; + __entry->len = len; + __assign_str(name, name); + ), + TP_printk("%p %p %s %.*s", __entry->dir, __entry->dentry, + __entry->symname, __entry->len, __get_str(name)) +); + +TRACE_EVENT(ocfs2_blkno_stringify, + TP_PROTO(unsigned long long blkno, const char *name, int namelen), + TP_ARGS(blkno, name, namelen), + TP_STRUCT__entry( + __field(unsigned long long, blkno) + __string(name, name) + __field(int, namelen) + ), + TP_fast_assign( + __entry->blkno = blkno; + __assign_str(name, name); + __entry->namelen = namelen; + ), + TP_printk("%llu %s %d", __entry->blkno, __get_str(name), + __entry->namelen) +); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_orphan_add_begin); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_orphan_add_end); + +TRACE_EVENT(ocfs2_orphan_del, + TP_PROTO(unsigned long long dir, const char *name, int namelen), + TP_ARGS(dir, name, namelen), + TP_STRUCT__entry( + __field(unsigned long long, dir) + __string(name, name) + __field(int, namelen) + ), + TP_fast_assign( + __entry->dir = dir; + __assign_str(name, name); + __entry->namelen = namelen; + ), + TP_printk("%llu %s %d", __entry->dir, __get_str(name), + __entry->namelen) +); + +/* End of trace events for fs/ocfs2/namei.c. */ #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ -- cgit From a5b8443b34d57c6c6e3f8180d9f88890f3625a4b Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Wed, 23 Feb 2011 22:51:49 +0800 Subject: ocfs2: Remove masklog ML_DCACHE. Remove mlog(0) from fs/ocfs2/dcache.c and the masklog DCACHE. Signed-off-by: Tao Ma --- fs/ocfs2/cluster/masklog.c | 1 - fs/ocfs2/cluster/masklog.h | 1 - fs/ocfs2/dcache.c | 44 ++++++++++----------- fs/ocfs2/ocfs2_trace.h | 99 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 121 insertions(+), 24 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index 0668eb6e05d6..91df3e2571a0 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -97,7 +97,6 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { define_mask(BH_IO), define_mask(UPTODATE), define_mask(VOTE), - define_mask(DCACHE), define_mask(CONN), define_mask(QUORUM), define_mask(EXPORT), diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index a815b55d87a7..c64b0aa59e9d 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -99,7 +99,6 @@ #define ML_BH_IO 0x0000000000100000ULL /* ocfs2 buffer I/O */ #define ML_UPTODATE 0x0000000000200000ULL /* ocfs2 caching sequence #'s */ #define ML_VOTE 0x0000000001000000ULL /* ocfs2 node messaging */ -#define ML_DCACHE 0x0000000002000000ULL /* ocfs2 dcache operations */ #define ML_CONN 0x0000000004000000ULL /* net connection management */ #define ML_QUORUM 0x0000000008000000ULL /* net connection quorum */ #define ML_EXPORT 0x0000000010000000ULL /* ocfs2 export operations */ diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c index c26551c25e8e..e5ba34818332 100644 --- a/fs/ocfs2/dcache.c +++ b/fs/ocfs2/dcache.c @@ -28,7 +28,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_DCACHE #include #include "ocfs2.h" @@ -39,6 +38,7 @@ #include "file.h" #include "inode.h" #include "super.h" +#include "ocfs2_trace.h" void ocfs2_dentry_attach_gen(struct dentry *dentry) { @@ -62,8 +62,8 @@ static int ocfs2_dentry_revalidate(struct dentry *dentry, inode = dentry->d_inode; osb = OCFS2_SB(dentry->d_sb); - mlog(0, "(0x%p, '%.*s')\n", dentry, - dentry->d_name.len, dentry->d_name.name); + trace_ocfs2_dentry_revalidate(dentry, dentry->d_name.len, + dentry->d_name.name); /* For a negative dentry - * check the generation number of the parent and compare with the @@ -73,9 +73,10 @@ static int ocfs2_dentry_revalidate(struct dentry *dentry, unsigned long gen = (unsigned long) dentry->d_fsdata; unsigned long pgen = OCFS2_I(dentry->d_parent->d_inode)->ip_dir_lock_gen; - mlog(0, "negative dentry: %.*s parent gen: %lu " - "dentry gen: %lu\n", - dentry->d_name.len, dentry->d_name.name, pgen, gen); + + trace_ocfs2_dentry_revalidate_negative(dentry->d_name.len, + dentry->d_name.name, + pgen, gen); if (gen != pgen) goto bail; goto valid; @@ -90,8 +91,8 @@ static int ocfs2_dentry_revalidate(struct dentry *dentry, /* did we or someone else delete this inode? */ if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_DELETED) { spin_unlock(&OCFS2_I(inode)->ip_lock); - mlog(0, "inode (%llu) deleted, returning false\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno); + trace_ocfs2_dentry_revalidate_delete( + (unsigned long long)OCFS2_I(inode)->ip_blkno); goto bail; } spin_unlock(&OCFS2_I(inode)->ip_lock); @@ -101,10 +102,9 @@ static int ocfs2_dentry_revalidate(struct dentry *dentry, * inode nlink hits zero, it never goes back. */ if (inode->i_nlink == 0) { - mlog(0, "Inode %llu orphaned, returning false " - "dir = %d\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno, - S_ISDIR(inode->i_mode)); + trace_ocfs2_dentry_revalidate_orphaned( + (unsigned long long)OCFS2_I(inode)->ip_blkno, + S_ISDIR(inode->i_mode)); goto bail; } @@ -113,9 +113,8 @@ static int ocfs2_dentry_revalidate(struct dentry *dentry, * redo it. */ if (!dentry->d_fsdata) { - mlog(0, "Inode %llu doesn't have dentry lock, " - "returning false\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno); + trace_ocfs2_dentry_revalidate_nofsdata( + (unsigned long long)OCFS2_I(inode)->ip_blkno); goto bail; } @@ -123,7 +122,7 @@ valid: ret = 1; bail: - mlog(0, "ret = %d\n", ret); + trace_ocfs2_dentry_revalidate_ret(ret); return ret; } @@ -180,8 +179,8 @@ struct dentry *ocfs2_find_local_alias(struct inode *inode, spin_lock(&dentry->d_lock); if (ocfs2_match_dentry(dentry, parent_blkno, skip_unhashed)) { - mlog(0, "dentry found: %.*s\n", - dentry->d_name.len, dentry->d_name.name); + trace_ocfs2_find_local_alias(dentry->d_name.len, + dentry->d_name.name); dget_dlock(dentry); spin_unlock(&dentry->d_lock); @@ -239,9 +238,8 @@ int ocfs2_dentry_attach_lock(struct dentry *dentry, struct dentry *alias; struct ocfs2_dentry_lock *dl = dentry->d_fsdata; - mlog(0, "Attach \"%.*s\", parent %llu, fsdata: %p\n", - dentry->d_name.len, dentry->d_name.name, - (unsigned long long)parent_blkno, dl); + trace_ocfs2_dentry_attach_lock(dentry->d_name.len, dentry->d_name.name, + (unsigned long long)parent_blkno, dl); /* * Negative dentry. We ignore these for now. @@ -291,7 +289,9 @@ int ocfs2_dentry_attach_lock(struct dentry *dentry, (unsigned long long)parent_blkno, (unsigned long long)dl->dl_parent_blkno); - mlog(0, "Found: %s\n", dl->dl_lockres.l_name); + trace_ocfs2_dentry_attach_lock_found(dl->dl_lockres.l_name, + (unsigned long long)parent_blkno, + (unsigned long long)OCFS2_I(inode)->ip_blkno); goto out_attach; } diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index a98e52ae06ee..6ef3a928023b 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -2364,6 +2364,105 @@ TRACE_EVENT(ocfs2_orphan_del, ); /* End of trace events for fs/ocfs2/namei.c. */ + +/* Trace events for fs/ocfs2/dcache.c. */ + +TRACE_EVENT(ocfs2_dentry_revalidate, + TP_PROTO(void *dentry, int len, const char *name), + TP_ARGS(dentry, len, name), + TP_STRUCT__entry( + __field(void *, dentry) + __field(int, len) + __string(name, name) + ), + TP_fast_assign( + __entry->dentry = dentry; + __entry->len = len; + __assign_str(name, name); + ), + TP_printk("%p %.*s", __entry->dentry, __entry->len, __get_str(name)) +); + +TRACE_EVENT(ocfs2_dentry_revalidate_negative, + TP_PROTO(int len, const char *name, unsigned long pgen, + unsigned long gen), + TP_ARGS(len, name, pgen, gen), + TP_STRUCT__entry( + __field(int, len) + __string(name, name) + __field(unsigned long, pgen) + __field(unsigned long, gen) + ), + TP_fast_assign( + __entry->len = len; + __assign_str(name, name); + __entry->pgen = pgen; + __entry->gen = gen; + ), + TP_printk("%.*s %lu %lu", __entry->len, __get_str(name), + __entry->pgen, __entry->gen) +); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_dentry_revalidate_delete); + +DEFINE_OCFS2_ULL_INT_EVENT(ocfs2_dentry_revalidate_orphaned); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_dentry_revalidate_nofsdata); + +DEFINE_OCFS2_INT_EVENT(ocfs2_dentry_revalidate_ret); + +TRACE_EVENT(ocfs2_find_local_alias, + TP_PROTO(int len, const char *name), + TP_ARGS(len, name), + TP_STRUCT__entry( + __field(int, len) + __string(name, name) + ), + TP_fast_assign( + __entry->len = len; + __assign_str(name, name); + ), + TP_printk("%.*s", __entry->len, __get_str(name)) +); + +TRACE_EVENT(ocfs2_dentry_attach_lock, + TP_PROTO(int len, const char *name, + unsigned long long parent, void *fsdata), + TP_ARGS(len, name, parent, fsdata), + TP_STRUCT__entry( + __field(int, len) + __string(name, name) + __field(unsigned long long, parent) + __field(void *, fsdata) + ), + TP_fast_assign( + __entry->len = len; + __assign_str(name, name); + __entry->parent = parent; + __entry->fsdata = fsdata; + ), + TP_printk("%.*s %llu %p", __entry->len, __get_str(name), + __entry->parent, __entry->fsdata) +); + +TRACE_EVENT(ocfs2_dentry_attach_lock_found, + TP_PROTO(const char *name, unsigned long long parent, + unsigned long long ino), + TP_ARGS(name, parent, ino), + TP_STRUCT__entry( + __string(name, name) + __field(unsigned long long, parent) + __field(unsigned long long, ino) + ), + TP_fast_assign( + __assign_str(name, name); + __entry->parent = parent; + __entry->ino = ino; + ), + TP_printk("%s %llu %llu", __get_str(name), __entry->parent, __entry->ino) +); + +/* End of trace events for fs/ocfs2/dcache.c. */ #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ -- cgit From 781f200cb7a657339c8760984870c252701aa485 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Thu, 24 Feb 2011 13:50:19 +0800 Subject: ocfs2: Remove masklog ML_EXPORT. Remove mlog(0) from fs/ocfs2/export.c and the masklog EXPORT. Signed-off-by: Tao Ma --- fs/ocfs2/cluster/masklog.c | 1 - fs/ocfs2/cluster/masklog.h | 1 - fs/ocfs2/export.c | 47 +++++++++++--------------- fs/ocfs2/ocfs2_trace.h | 82 +++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 101 insertions(+), 30 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index 91df3e2571a0..491923b1e0a6 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -99,7 +99,6 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { define_mask(VOTE), define_mask(CONN), define_mask(QUORUM), - define_mask(EXPORT), define_mask(BASTS), define_mask(CLUSTER), define_mask(ERROR), diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index c64b0aa59e9d..c5bde37cd8b2 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -101,7 +101,6 @@ #define ML_VOTE 0x0000000001000000ULL /* ocfs2 node messaging */ #define ML_CONN 0x0000000004000000ULL /* net connection management */ #define ML_QUORUM 0x0000000008000000ULL /* net connection quorum */ -#define ML_EXPORT 0x0000000010000000ULL /* ocfs2 export operations */ #define ML_BASTS 0x0000000100000000ULL /* dlmglue asts and basts */ #define ML_CLUSTER 0x0000000400000000ULL /* cluster stack */ diff --git a/fs/ocfs2/export.c b/fs/ocfs2/export.c index 96d7ed7f8305..745db42528d5 100644 --- a/fs/ocfs2/export.c +++ b/fs/ocfs2/export.c @@ -26,7 +26,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_EXPORT #include #include "ocfs2.h" @@ -40,6 +39,7 @@ #include "buffer_head_io.h" #include "suballoc.h" +#include "ocfs2_trace.h" struct ocfs2_inode_handle { @@ -56,10 +56,9 @@ static struct dentry *ocfs2_get_dentry(struct super_block *sb, int status, set; struct dentry *result; - mlog(0, "(0x%p, 0x%p)\n", sb, handle); + trace_ocfs2_get_dentry_begin(sb, handle, (unsigned long long)blkno); if (blkno == 0) { - mlog(0, "nfs wants inode with blkno: 0\n"); result = ERR_PTR(-ESTALE); goto bail; } @@ -83,6 +82,7 @@ static struct dentry *ocfs2_get_dentry(struct super_block *sb, } status = ocfs2_test_inode_bit(osb, blkno, &set); + trace_ocfs2_get_dentry_test_bit(status, set); if (status < 0) { if (status == -EINVAL) { /* @@ -90,18 +90,14 @@ static struct dentry *ocfs2_get_dentry(struct super_block *sb, * as an inode, we return -ESTALE to be * nice */ - mlog(0, "test inode bit failed %d\n", status); status = -ESTALE; - } else { + } else mlog(ML_ERROR, "test inode bit failed %d\n", status); - } goto unlock_nfs_sync; } /* If the inode allocator bit is clear, this inode must be stale */ if (!set) { - mlog(0, "inode %llu suballoc bit is clear\n", - (unsigned long long)blkno); status = -ESTALE; goto unlock_nfs_sync; } @@ -114,8 +110,8 @@ unlock_nfs_sync: check_err: if (status < 0) { if (status == -ESTALE) { - mlog(0, "stale inode ino: %llu generation: %u\n", - (unsigned long long)blkno, handle->ih_generation); + trace_ocfs2_get_dentry_stale((unsigned long long)blkno, + handle->ih_generation); } result = ERR_PTR(status); goto bail; @@ -130,8 +126,9 @@ check_err: check_gen: if (handle->ih_generation != inode->i_generation) { iput(inode); - mlog(0, "stale inode ino: %llu generation: %u\n", - (unsigned long long)blkno, handle->ih_generation); + trace_ocfs2_get_dentry_generation((unsigned long long)blkno, + handle->ih_generation, + inode->i_generation); result = ERR_PTR(-ESTALE); goto bail; } @@ -141,7 +138,7 @@ check_gen: mlog_errno(PTR_ERR(result)); bail: - mlog(0, "result = %p\n", result); + trace_ocfs2_get_dentry_end(result); return result; } @@ -152,11 +149,8 @@ static struct dentry *ocfs2_get_parent(struct dentry *child) struct dentry *parent; struct inode *dir = child->d_inode; - mlog(0, "(0x%p, '%.*s')\n", child, - child->d_name.len, child->d_name.name); - - mlog(0, "find parent of directory %llu\n", - (unsigned long long)OCFS2_I(dir)->ip_blkno); + trace_ocfs2_get_parent(child, child->d_name.len, child->d_name.name, + (unsigned long long)OCFS2_I(dir)->ip_blkno); status = ocfs2_inode_lock(dir, NULL, 0); if (status < 0) { @@ -178,7 +172,7 @@ bail_unlock: ocfs2_inode_unlock(dir, 0); bail: - mlog(0, "parent %p\n", parent); + trace_ocfs2_get_parent_end(parent); return parent; } @@ -193,9 +187,9 @@ static int ocfs2_encode_fh(struct dentry *dentry, u32 *fh_in, int *max_len, u32 generation; __le32 *fh = (__force __le32 *) fh_in; - mlog(0, "(0x%p, '%.*s', 0x%p, %d, %d)\n", dentry, - dentry->d_name.len, dentry->d_name.name, - fh, len, connectable); + trace_ocfs2_encode_fh_begin(dentry, dentry->d_name.len, + dentry->d_name.name, + fh, len, connectable); if (connectable && (len < 6)) { *max_len = 6; @@ -210,8 +204,7 @@ static int ocfs2_encode_fh(struct dentry *dentry, u32 *fh_in, int *max_len, blkno = OCFS2_I(inode)->ip_blkno; generation = inode->i_generation; - mlog(0, "Encoding fh: blkno: %llu, generation: %u\n", - (unsigned long long)blkno, generation); + trace_ocfs2_encode_fh_self((unsigned long long)blkno, generation); len = 3; fh[0] = cpu_to_le32((u32)(blkno >> 32)); @@ -236,14 +229,14 @@ static int ocfs2_encode_fh(struct dentry *dentry, u32 *fh_in, int *max_len, len = 6; type = 2; - mlog(0, "Encoding parent: blkno: %llu, generation: %u\n", - (unsigned long long)blkno, generation); + trace_ocfs2_encode_fh_parent((unsigned long long)blkno, + generation); } *max_len = len; bail: - mlog(0, "type = %d\n", type); + trace_ocfs2_encode_fh_type(type); return type; } diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 6ef3a928023b..48839054d5af 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -2461,8 +2461,88 @@ TRACE_EVENT(ocfs2_dentry_attach_lock_found, ), TP_printk("%s %llu %llu", __get_str(name), __entry->parent, __entry->ino) ); - /* End of trace events for fs/ocfs2/dcache.c. */ + +/* Trace events for fs/ocfs2/export.c. */ + +TRACE_EVENT(ocfs2_get_dentry_begin, + TP_PROTO(void *sb, void *handle, unsigned long long blkno), + TP_ARGS(sb, handle, blkno), + TP_STRUCT__entry( + __field(void *, sb) + __field(void *, handle) + __field(unsigned long long, blkno) + ), + TP_fast_assign( + __entry->sb = sb; + __entry->handle = handle; + __entry->blkno = blkno; + ), + TP_printk("%p %p %llu", __entry->sb, __entry->handle, __entry->blkno) +); + +DEFINE_OCFS2_INT_INT_EVENT(ocfs2_get_dentry_test_bit); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_get_dentry_stale); + +DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_get_dentry_generation); + +DEFINE_OCFS2_POINTER_EVENT(ocfs2_get_dentry_end); + +TRACE_EVENT(ocfs2_get_parent, + TP_PROTO(void *child, int len, const char *name, + unsigned long long ino), + TP_ARGS(child, len, name, ino), + TP_STRUCT__entry( + __field(void *, child) + __field(int, len) + __string(name, name) + __field(unsigned long long, ino) + ), + TP_fast_assign( + __entry->child = child; + __entry->len = len; + __assign_str(name, name); + __entry->ino = ino; + ), + TP_printk("%p %.*s %llu", __entry->child, __entry->len, + __get_str(name), __entry->ino) +); + +DEFINE_OCFS2_POINTER_EVENT(ocfs2_get_parent_end); + +TRACE_EVENT(ocfs2_encode_fh_begin, + TP_PROTO(void *dentry, int name_len, const char *name, + void *fh, int len, int connectable), + TP_ARGS(dentry, name_len, name, fh, len, connectable), + TP_STRUCT__entry( + __field(void *, dentry) + __field(int, name_len) + __string(name, name) + __field(void *, fh) + __field(int, len) + __field(int, connectable) + ), + TP_fast_assign( + __entry->dentry = dentry; + __entry->name_len = name_len; + __assign_str(name, name); + __entry->fh = fh; + __entry->len = len; + __entry->connectable = connectable; + ), + TP_printk("%p %.*s %p %d %d", __entry->dentry, __entry->name_len, + __get_str(name), __entry->fh, __entry->len, + __entry->connectable) +); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_encode_fh_self); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_encode_fh_parent); + +DEFINE_OCFS2_INT_EVENT(ocfs2_encode_fh_type); + +/* End of trace events for fs/ocfs2/export.c. */ #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ -- cgit From b41079504c786eb226e7e1e3dc5cc1f37fbd1c2b Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Thu, 24 Feb 2011 14:15:35 +0800 Subject: ocfs2: Remove masklog ML_JOURNAL. Remove mlog(0) from fs/ocfs2/journal.c and the masklog JOURNAL. Signed-off-by: Tao Ma --- fs/ocfs2/cluster/masklog.c | 1 - fs/ocfs2/cluster/masklog.h | 1 - fs/ocfs2/journal.c | 130 +++++++++++++++++++-------------------------- fs/ocfs2/ocfs2_trace.h | 99 ++++++++++++++++++++++++++++++++++ 4 files changed, 153 insertions(+), 78 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index 491923b1e0a6..b64fb67c2999 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -92,7 +92,6 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { define_mask(DLM_MASTER), define_mask(DLM_RECOVERY), define_mask(AIO), - define_mask(JOURNAL), define_mask(DLM_GLUE), define_mask(BH_IO), define_mask(UPTODATE), diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index c5bde37cd8b2..1340ef0ae3e1 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -94,7 +94,6 @@ #define ML_DLM_MASTER 0x0000000000000800ULL /* dlm master functions */ #define ML_DLM_RECOVERY 0x0000000000001000ULL /* dlm master functions */ #define ML_AIO 0x0000000000002000ULL /* ocfs2 aio read and write */ -#define ML_JOURNAL 0x0000000000004000ULL /* ocfs2 journalling functions */ #define ML_DLM_GLUE 0x0000000000080000ULL /* ocfs2 dlm glue layer */ #define ML_BH_IO 0x0000000000100000ULL /* ocfs2 buffer I/O */ #define ML_UPTODATE 0x0000000000200000ULL /* ocfs2 caching sequence #'s */ diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index 956509167bf5..dcc2d9327150 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c @@ -31,7 +31,6 @@ #include #include -#define MLOG_MASK_PREFIX ML_JOURNAL #include #include "ocfs2.h" @@ -52,6 +51,7 @@ #include "quota.h" #include "buffer_head_io.h" +#include "ocfs2_trace.h" DEFINE_SPINLOCK(trans_inc_lock); @@ -308,9 +308,10 @@ static int ocfs2_commit_cache(struct ocfs2_super *osb) /* Flush all pending commits and checkpoint the journal. */ down_write(&journal->j_trans_barrier); - if (atomic_read(&journal->j_num_trans) == 0) { + flushed = atomic_read(&journal->j_num_trans); + trace_ocfs2_commit_cache_begin(flushed); + if (flushed == 0) { up_write(&journal->j_trans_barrier); - mlog(0, "No transactions for me to flush!\n"); goto finally; } @@ -329,8 +330,7 @@ static int ocfs2_commit_cache(struct ocfs2_super *osb) atomic_set(&journal->j_num_trans, 0); up_write(&journal->j_trans_barrier); - mlog(0, "commit_thread: flushed transaction %lu (%u handles)\n", - journal->j_trans_id, flushed); + trace_ocfs2_commit_cache_end(journal->j_trans_id, flushed); ocfs2_wake_downconvert_thread(osb); wake_up(&journal->j_checkpointed); @@ -423,7 +423,7 @@ int ocfs2_extend_trans(handle_t *handle, int nblocks) old_nblocks = handle->h_buffer_credits; - mlog(0, "Trying to extend transaction by %d blocks\n", nblocks); + trace_ocfs2_extend_trans(old_nblocks, nblocks); #ifdef CONFIG_OCFS2_DEBUG_FS status = 1; @@ -436,9 +436,7 @@ int ocfs2_extend_trans(handle_t *handle, int nblocks) #endif if (status > 0) { - mlog(0, - "jbd2_journal_extend failed, trying " - "jbd2_journal_restart\n"); + trace_ocfs2_extend_trans_restart(old_nblocks + nblocks); status = jbd2_journal_restart(handle, old_nblocks + nblocks); if (status < 0) { @@ -616,12 +614,9 @@ static int __ocfs2_journal_access(handle_t *handle, BUG_ON(!handle); BUG_ON(!bh); - mlog(0, "bh->b_blocknr=%llu, type=%d (\"%s\"), bh->b_size = %zu\n", - (unsigned long long)bh->b_blocknr, type, - (type == OCFS2_JOURNAL_ACCESS_CREATE) ? - "OCFS2_JOURNAL_ACCESS_CREATE" : - "OCFS2_JOURNAL_ACCESS_WRITE", - bh->b_size); + trace_ocfs2_journal_access( + (unsigned long long)ocfs2_metadata_cache_owner(ci), + (unsigned long long)bh->b_blocknr, type, bh->b_size); /* we can safely remove this assertion after testing. */ if (!buffer_uptodate(bh)) { @@ -730,8 +725,7 @@ void ocfs2_journal_dirty(handle_t *handle, struct buffer_head *bh) { int status; - mlog(0, "(bh->b_blocknr=%llu)\n", - (unsigned long long)bh->b_blocknr); + trace_ocfs2_journal_dirty((unsigned long long)bh->b_blocknr); status = jbd2_journal_dirty_metadata(handle, bh); BUG_ON(status); @@ -809,10 +803,9 @@ int ocfs2_journal_init(struct ocfs2_journal *journal, int *dirty) goto done; } - mlog(0, "inode->i_size = %lld\n", inode->i_size); - mlog(0, "inode->i_blocks = %llu\n", - (unsigned long long)inode->i_blocks); - mlog(0, "inode->ip_clusters = %u\n", OCFS2_I(inode)->ip_clusters); + trace_ocfs2_journal_init(inode->i_size, + (unsigned long long)inode->i_blocks, + OCFS2_I(inode)->ip_clusters); /* call the kernels journal init function now */ j_journal = jbd2_journal_init_inode(inode); @@ -822,8 +815,7 @@ int ocfs2_journal_init(struct ocfs2_journal *journal, int *dirty) goto done; } - mlog(0, "Returned from jbd2_journal_init_inode\n"); - mlog(0, "j_journal->j_maxlen = %u\n", j_journal->j_maxlen); + trace_ocfs2_journal_init_maxlen(j_journal->j_maxlen); *dirty = (le32_to_cpu(di->id1.journal1.ij_flags) & OCFS2_JOURNAL_DIRTY_FL); @@ -922,10 +914,7 @@ void ocfs2_journal_shutdown(struct ocfs2_super *osb) BUG(); num_running_trans = atomic_read(&(osb->journal->j_num_trans)); - if (num_running_trans > 0) - mlog(0, "Shutting down journal: must wait on %d " - "running transactions!\n", - num_running_trans); + trace_ocfs2_journal_shutdown(num_running_trans); /* Do a commit_cache here. It will flush our journal, *and* * release any locks that are still held. @@ -938,7 +927,7 @@ void ocfs2_journal_shutdown(struct ocfs2_super *osb) * completely destroy the journal. */ if (osb->commit_task) { /* Wait for the commit thread */ - mlog(0, "Waiting for ocfs2commit to exit....\n"); + trace_ocfs2_journal_shutdown_wait(osb->commit_task); kthread_stop(osb->commit_task); osb->commit_task = NULL; } @@ -1158,7 +1147,7 @@ struct ocfs2_la_recovery_item { */ void ocfs2_complete_recovery(struct work_struct *work) { - int ret; + int ret = 0; struct ocfs2_journal *journal = container_of(work, struct ocfs2_journal, j_recovery_work); struct ocfs2_super *osb = journal->j_osb; @@ -1167,7 +1156,8 @@ void ocfs2_complete_recovery(struct work_struct *work) struct ocfs2_quota_recovery *qrec; LIST_HEAD(tmp_la_list); - mlog(0, "completing recovery from keventd\n"); + trace_ocfs2_complete_recovery( + (unsigned long long)OCFS2_I(journal->j_inode)->ip_blkno); spin_lock(&journal->j_lock); list_splice_init(&journal->j_la_cleanups, &tmp_la_list); @@ -1176,15 +1166,18 @@ void ocfs2_complete_recovery(struct work_struct *work) list_for_each_entry_safe(item, n, &tmp_la_list, lri_list) { list_del_init(&item->lri_list); - mlog(0, "Complete recovery for slot %d\n", item->lri_slot); - ocfs2_wait_on_quotas(osb); la_dinode = item->lri_la_dinode; - if (la_dinode) { - mlog(0, "Clean up local alloc %llu\n", - (unsigned long long)le64_to_cpu(la_dinode->i_blkno)); + tl_dinode = item->lri_tl_dinode; + qrec = item->lri_qrec; + trace_ocfs2_complete_recovery_slot(item->lri_slot, + la_dinode ? le64_to_cpu(la_dinode->i_blkno) : 0, + tl_dinode ? le64_to_cpu(tl_dinode->i_blkno) : 0, + qrec); + + if (la_dinode) { ret = ocfs2_complete_local_alloc_recovery(osb, la_dinode); if (ret < 0) @@ -1193,11 +1186,7 @@ void ocfs2_complete_recovery(struct work_struct *work) kfree(la_dinode); } - tl_dinode = item->lri_tl_dinode; if (tl_dinode) { - mlog(0, "Clean up truncate log %llu\n", - (unsigned long long)le64_to_cpu(tl_dinode->i_blkno)); - ret = ocfs2_complete_truncate_log_recovery(osb, tl_dinode); if (ret < 0) @@ -1210,9 +1199,7 @@ void ocfs2_complete_recovery(struct work_struct *work) if (ret < 0) mlog_errno(ret); - qrec = item->lri_qrec; if (qrec) { - mlog(0, "Recovering quota files"); ret = ocfs2_finish_quota_recovery(osb, qrec, item->lri_slot); if (ret < 0) @@ -1223,7 +1210,7 @@ void ocfs2_complete_recovery(struct work_struct *work) kfree(item); } - mlog(0, "Recovery completion\n"); + trace_ocfs2_complete_recovery_end(ret); } /* NOTE: This function always eats your references to la_dinode and @@ -1340,15 +1327,12 @@ restart: * clear it until ocfs2_recover_node() has succeeded. */ node_num = rm->rm_entries[0]; spin_unlock(&osb->osb_lock); - mlog(0, "checking node %d\n", node_num); slot_num = ocfs2_node_num_to_slot(osb, node_num); + trace_ocfs2_recovery_thread_node(node_num, slot_num); if (slot_num == -ENOENT) { status = 0; - mlog(0, "no slot for this node, so no recovery" - "required.\n"); goto skip_recovery; } - mlog(0, "node %d was using slot %d\n", node_num, slot_num); /* It is a bit subtle with quota recovery. We cannot do it * immediately because we have to obtain cluster locks from @@ -1375,7 +1359,7 @@ skip_recovery: spin_lock(&osb->osb_lock); } spin_unlock(&osb->osb_lock); - mlog(0, "All nodes recovered\n"); + trace_ocfs2_recovery_thread_end(status); /* Refresh all journal recovery generations from disk */ status = ocfs2_check_journals_nolocks(osb); @@ -1428,19 +1412,15 @@ bail: void ocfs2_recovery_thread(struct ocfs2_super *osb, int node_num) { - mlog(0, "(node_num=%d, osb->node_num = %d)\n", - node_num, osb->node_num); - mutex_lock(&osb->recovery_lock); - if (osb->disable_recovery) - goto out; - /* People waiting on recovery will wait on - * the recovery map to empty. */ - if (ocfs2_recovery_map_set(osb, node_num)) - mlog(0, "node %d already in recovery map.\n", node_num); + trace_ocfs2_recovery_thread(node_num, osb->node_num, + osb->disable_recovery, osb->recovery_thread_task, + osb->disable_recovery ? + -1 : ocfs2_recovery_map_set(osb, node_num)); - mlog(0, "starting recovery thread...\n"); + if (osb->disable_recovery) + goto out; if (osb->recovery_thread_task) goto out; @@ -1528,7 +1508,7 @@ static int ocfs2_replay_journal(struct ocfs2_super *osb, * If not, it needs recovery. */ if (osb->slot_recovery_generations[slot_num] != slot_reco_gen) { - mlog(0, "Slot %u already recovered (old/new=%u/%u)\n", slot_num, + trace_ocfs2_replay_journal_recovered(slot_num, osb->slot_recovery_generations[slot_num], slot_reco_gen); osb->slot_recovery_generations[slot_num] = slot_reco_gen; status = -EBUSY; @@ -1539,7 +1519,7 @@ static int ocfs2_replay_journal(struct ocfs2_super *osb, status = ocfs2_inode_lock_full(inode, &bh, 1, OCFS2_META_LOCK_RECOVERY); if (status < 0) { - mlog(0, "status returned from ocfs2_inode_lock=%d\n", status); + trace_ocfs2_replay_journal_lock_err(status); if (status != -ERESTARTSYS) mlog(ML_ERROR, "Could not lock journal!\n"); goto done; @@ -1552,7 +1532,7 @@ static int ocfs2_replay_journal(struct ocfs2_super *osb, slot_reco_gen = ocfs2_get_recovery_generation(fe); if (!(flags & OCFS2_JOURNAL_DIRTY_FL)) { - mlog(0, "No recovery required for node %d\n", node_num); + trace_ocfs2_replay_journal_skip(node_num); /* Refresh recovery generation for the slot */ osb->slot_recovery_generations[slot_num] = slot_reco_gen; goto done; @@ -1573,7 +1553,6 @@ static int ocfs2_replay_journal(struct ocfs2_super *osb, goto done; } - mlog(0, "calling journal_init_inode\n"); journal = jbd2_journal_init_inode(inode); if (journal == NULL) { mlog(ML_ERROR, "Linux journal layer error\n"); @@ -1593,7 +1572,6 @@ static int ocfs2_replay_journal(struct ocfs2_super *osb, ocfs2_clear_journal_error(osb->sb, journal, slot_num); /* wipe the journal */ - mlog(0, "flushing the journal.\n"); jbd2_journal_lock_updates(journal); status = jbd2_journal_flush(journal); jbd2_journal_unlock_updates(journal); @@ -1652,8 +1630,7 @@ static int ocfs2_recover_node(struct ocfs2_super *osb, struct ocfs2_dinode *la_copy = NULL; struct ocfs2_dinode *tl_copy = NULL; - mlog(0, "(node_num=%d, slot_num=%d, osb->node_num = %d)\n", - node_num, slot_num, osb->node_num); + trace_ocfs2_recover_node(node_num, slot_num, osb->node_num); /* Should not ever be called to recover ourselves -- in that * case we should've called ocfs2_journal_load instead. */ @@ -1662,9 +1639,7 @@ static int ocfs2_recover_node(struct ocfs2_super *osb, status = ocfs2_replay_journal(osb, node_num, slot_num); if (status < 0) { if (status == -EBUSY) { - mlog(0, "Skipping recovery for slot %u (node %u) " - "as another node has recovered it\n", slot_num, - node_num); + trace_ocfs2_recover_node_skip(slot_num, node_num); status = 0; goto done; } @@ -1771,8 +1746,8 @@ int ocfs2_mark_dead_nodes(struct ocfs2_super *osb) spin_lock(&osb->osb_lock); osb->slot_recovery_generations[i] = gen; - mlog(0, "Slot %u recovery generation is %u\n", i, - osb->slot_recovery_generations[i]); + trace_ocfs2_mark_dead_nodes(i, + osb->slot_recovery_generations[i]); if (i == osb->slot_num) { spin_unlock(&osb->osb_lock); @@ -1846,11 +1821,12 @@ void ocfs2_queue_orphan_scan(struct ocfs2_super *osb) os = &osb->osb_orphan_scan; - mlog(0, "Begin orphan scan\n"); - if (atomic_read(&os->os_state) == ORPHAN_SCAN_INACTIVE) goto out; + trace_ocfs2_queue_orphan_scan_begin(os->os_count, os->os_seqno, + atomic_read(&os->os_state)); + status = ocfs2_orphan_scan_lock(osb, &seqno); if (status < 0) { if (status != -EAGAIN) @@ -1880,7 +1856,8 @@ void ocfs2_queue_orphan_scan(struct ocfs2_super *osb) unlock: ocfs2_orphan_scan_unlock(osb, seqno); out: - mlog(0, "Orphan scan completed\n"); + trace_ocfs2_queue_orphan_scan_end(os->os_count, os->os_seqno, + atomic_read(&os->os_state)); return; } @@ -1964,8 +1941,7 @@ static int ocfs2_orphan_filldir(void *priv, const char *name, int name_len, if (IS_ERR(iter)) return 0; - mlog(0, "queue orphan %llu\n", - (unsigned long long)OCFS2_I(iter)->ip_blkno); + trace_ocfs2_orphan_filldir((unsigned long long)OCFS2_I(iter)->ip_blkno); /* No locking is required for the next_orphan queue as there * is only ever a single process doing orphan recovery. */ OCFS2_I(iter)->ip_next_orphan = p->head; @@ -2081,7 +2057,7 @@ static int ocfs2_recover_orphans(struct ocfs2_super *osb, struct inode *iter; struct ocfs2_inode_info *oi; - mlog(0, "Recover inodes from orphan dir in slot %d\n", slot); + trace_ocfs2_recover_orphans(slot); ocfs2_mark_recovering_orphan_dir(osb, slot); ret = ocfs2_queue_orphans(osb, slot, &inode); @@ -2094,7 +2070,8 @@ static int ocfs2_recover_orphans(struct ocfs2_super *osb, while (inode) { oi = OCFS2_I(inode); - mlog(0, "iput orphan %llu\n", (unsigned long long)oi->ip_blkno); + trace_ocfs2_recover_orphans_iput( + (unsigned long long)oi->ip_blkno); iter = oi->ip_next_orphan; @@ -2132,6 +2109,7 @@ static int __ocfs2_wait_on_mount(struct ocfs2_super *osb, int quota) * MOUNTED flag, but this is set right before * dismount_volume() so we can trust it. */ if (atomic_read(&osb->vol_state) == VOLUME_DISABLED) { + trace_ocfs2_wait_on_mount(VOLUME_DISABLED); mlog(0, "mount error, exiting!\n"); return -EBUSY; } diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 48839054d5af..9d1ca49aa98b 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -2543,6 +2543,105 @@ DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_encode_fh_parent); DEFINE_OCFS2_INT_EVENT(ocfs2_encode_fh_type); /* End of trace events for fs/ocfs2/export.c. */ + +/* Trace events for fs/ocfs2/journal.c. */ + +DEFINE_OCFS2_UINT_EVENT(ocfs2_commit_cache_begin); + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_commit_cache_end); + +DEFINE_OCFS2_INT_INT_EVENT(ocfs2_extend_trans); + +DEFINE_OCFS2_INT_EVENT(ocfs2_extend_trans_restart); + +DEFINE_OCFS2_ULL_ULL_UINT_UINT_EVENT(ocfs2_journal_access); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_journal_dirty); + +DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_journal_init); + +DEFINE_OCFS2_UINT_EVENT(ocfs2_journal_init_maxlen); + +DEFINE_OCFS2_INT_EVENT(ocfs2_journal_shutdown); + +DEFINE_OCFS2_POINTER_EVENT(ocfs2_journal_shutdown_wait); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_complete_recovery); + +DEFINE_OCFS2_INT_EVENT(ocfs2_complete_recovery_end); + +TRACE_EVENT(ocfs2_complete_recovery_slot, + TP_PROTO(int slot, unsigned long long la_ino, + unsigned long long tl_ino, void *qrec), + TP_ARGS(slot, la_ino, tl_ino, qrec), + TP_STRUCT__entry( + __field(int, slot) + __field(unsigned long long, la_ino) + __field(unsigned long long, tl_ino) + __field(void *, qrec) + ), + TP_fast_assign( + __entry->slot = slot; + __entry->la_ino = la_ino; + __entry->tl_ino = tl_ino; + __entry->qrec = qrec; + ), + TP_printk("%d %llu %llu %p", __entry->slot, __entry->la_ino, + __entry->tl_ino, __entry->qrec) +); + +DEFINE_OCFS2_INT_INT_EVENT(ocfs2_recovery_thread_node); + +DEFINE_OCFS2_INT_EVENT(ocfs2_recovery_thread_end); + +TRACE_EVENT(ocfs2_recovery_thread, + TP_PROTO(int node_num, int osb_node_num, int disable, + void *recovery_thread, int map_set), + TP_ARGS(node_num, osb_node_num, disable, recovery_thread, map_set), + TP_STRUCT__entry( + __field(int, node_num) + __field(int, osb_node_num) + __field(int,disable) + __field(void *, recovery_thread) + __field(int,map_set) + ), + TP_fast_assign( + __entry->node_num = node_num; + __entry->osb_node_num = osb_node_num; + __entry->disable = disable; + __entry->recovery_thread = recovery_thread; + __entry->map_set = map_set; + ), + TP_printk("%d %d %d %p %d", __entry->node_num, + __entry->osb_node_num, __entry->disable, + __entry->recovery_thread, __entry->map_set) +); + +DEFINE_OCFS2_UINT_UINT_UINT_EVENT(ocfs2_replay_journal_recovered); + +DEFINE_OCFS2_INT_EVENT(ocfs2_replay_journal_lock_err); + +DEFINE_OCFS2_INT_EVENT(ocfs2_replay_journal_skip); + +DEFINE_OCFS2_UINT_UINT_UINT_EVENT(ocfs2_recover_node); + +DEFINE_OCFS2_UINT_UINT_EVENT(ocfs2_recover_node_skip); + +DEFINE_OCFS2_UINT_UINT_EVENT(ocfs2_mark_dead_nodes); + +DEFINE_OCFS2_UINT_UINT_UINT_EVENT(ocfs2_queue_orphan_scan_begin); + +DEFINE_OCFS2_UINT_UINT_UINT_EVENT(ocfs2_queue_orphan_scan_end); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_orphan_filldir); + +DEFINE_OCFS2_INT_EVENT(ocfs2_recover_orphans); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_recover_orphans_iput); + +DEFINE_OCFS2_INT_EVENT(ocfs2_wait_on_mount); + +/* End of trace events for fs/ocfs2/journal.c. */ #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ -- cgit From 15057e981abb3436c16835af1001447056a809b5 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Thu, 24 Feb 2011 16:09:38 +0800 Subject: ocfs2: Remove masklog ML_BH_IO. Remove mlog(0,...) and mlog(ML_BH_IO,...) from fs/ocfs2/buffer_head_io.c. The masklog BH_IO is removed finally. Signed-off-by: Tao Ma --- fs/ocfs2/buffer_head_io.c | 37 +++++++++++++------------------------ fs/ocfs2/cluster/masklog.c | 1 - fs/ocfs2/cluster/masklog.h | 1 - fs/ocfs2/ocfs2_trace.h | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 26 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/buffer_head_io.c b/fs/ocfs2/buffer_head_io.c index c23846dbfc8f..d1cf9abcd827 100644 --- a/fs/ocfs2/buffer_head_io.c +++ b/fs/ocfs2/buffer_head_io.c @@ -35,8 +35,8 @@ #include "inode.h" #include "journal.h" #include "uptodate.h" - #include "buffer_head_io.h" +#include "ocfs2_trace.h" /* * Bits on bh->b_state used by ocfs2. @@ -55,8 +55,7 @@ int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh, { int ret = 0; - mlog(0, "(bh->b_blocknr = %llu, ci=%p)\n", - (unsigned long long)bh->b_blocknr, ci); + trace_ocfs2_write_block((unsigned long long)bh->b_blocknr, ci); BUG_ON(bh->b_blocknr < OCFS2_SUPER_BLOCK_BLKNO); BUG_ON(buffer_jbd(bh)); @@ -107,10 +106,10 @@ int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block, unsigned int i; struct buffer_head *bh; - if (!nr) { - mlog(ML_BH_IO, "No buffers will be read!\n"); + trace_ocfs2_read_blocks_sync((unsigned long long)block, nr); + + if (!nr) goto bail; - } for (i = 0 ; i < nr ; i++) { if (bhs[i] == NULL) { @@ -124,10 +123,8 @@ int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block, bh = bhs[i]; if (buffer_jbd(bh)) { - mlog(ML_BH_IO, - "trying to sync read a jbd " - "managed bh (blocknr = %llu), skipping\n", - (unsigned long long)bh->b_blocknr); + trace_ocfs2_read_blocks_sync_jbd( + (unsigned long long)bh->b_blocknr); continue; } @@ -187,8 +184,7 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr, struct buffer_head *bh; struct super_block *sb = ocfs2_metadata_cache_get_super(ci); - mlog(0, "(ci=%p, block=(%llu), nr=(%d), flags=%d)\n", - ci, (unsigned long long)block, nr, flags); + trace_ocfs2_read_blocks_begin(ci, (unsigned long long)block, nr, flags); BUG_ON(!ci); BUG_ON((flags & OCFS2_BH_READAHEAD) && @@ -208,7 +204,6 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr, } if (nr == 0) { - mlog(ML_BH_IO, "No buffers will be read!\n"); status = 0; goto bail; } @@ -261,11 +256,10 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr, ignore_cache = 1; } + trace_ocfs2_read_blocks_bh((unsigned long long)bh->b_blocknr, + ignore_cache, buffer_jbd(bh), buffer_dirty(bh)); + if (buffer_jbd(bh)) { - if (ignore_cache) - mlog(ML_BH_IO, "trying to sync read a jbd " - "managed bh (blocknr = %llu)\n", - (unsigned long long)bh->b_blocknr); continue; } @@ -273,9 +267,6 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr, if (buffer_dirty(bh)) { /* This should probably be a BUG, or * at least return an error. */ - mlog(ML_BH_IO, "asking me to sync read a dirty " - "buffer! (blocknr = %llu)\n", - (unsigned long long)bh->b_blocknr); continue; } @@ -368,10 +359,8 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr, } ocfs2_metadata_cache_io_unlock(ci); - mlog(ML_BH_IO, "block=(%llu), nr=(%d), cached=%s, flags=0x%x\n", - (unsigned long long)block, nr, - ((flags & OCFS2_BH_IGNORE_CACHE) || ignore_cache) ? "no" : "yes", - flags); + trace_ocfs2_read_blocks_end((unsigned long long)block, nr, + flags, ignore_cache); bail: diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index b64fb67c2999..d845ccef2408 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -93,7 +93,6 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { define_mask(DLM_RECOVERY), define_mask(AIO), define_mask(DLM_GLUE), - define_mask(BH_IO), define_mask(UPTODATE), define_mask(VOTE), define_mask(CONN), diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index 1340ef0ae3e1..ad267f614528 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -95,7 +95,6 @@ #define ML_DLM_RECOVERY 0x0000000000001000ULL /* dlm master functions */ #define ML_AIO 0x0000000000002000ULL /* ocfs2 aio read and write */ #define ML_DLM_GLUE 0x0000000000080000ULL /* ocfs2 dlm glue layer */ -#define ML_BH_IO 0x0000000000100000ULL /* ocfs2 buffer I/O */ #define ML_UPTODATE 0x0000000000200000ULL /* ocfs2 caching sequence #'s */ #define ML_VOTE 0x0000000001000000ULL /* ocfs2 node messaging */ #define ML_CONN 0x0000000004000000ULL /* net connection management */ diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 9d1ca49aa98b..90dc79a22a59 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -2642,6 +2642,52 @@ DEFINE_OCFS2_ULL_EVENT(ocfs2_recover_orphans_iput); DEFINE_OCFS2_INT_EVENT(ocfs2_wait_on_mount); /* End of trace events for fs/ocfs2/journal.c. */ + +/* Trace events for fs/ocfs2/buffer_head_io.c. */ + +DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_read_blocks_sync); + +DEFINE_OCFS2_ULL_EVENT(ocfs2_read_blocks_sync_jbd); + +DEFINE_OCFS2_ULL_INT_INT_INT_EVENT(ocfs2_read_blocks_bh); + +DEFINE_OCFS2_ULL_INT_INT_INT_EVENT(ocfs2_read_blocks_end); + +TRACE_EVENT(ocfs2_write_block, + TP_PROTO(unsigned long long block, void *ci), + TP_ARGS(block, ci), + TP_STRUCT__entry( + __field(unsigned long long, block) + __field(void *, ci) + ), + TP_fast_assign( + __entry->block = block; + __entry->ci = ci; + ), + TP_printk("%llu %p", __entry->block, __entry->ci) +); + +TRACE_EVENT(ocfs2_read_blocks_begin, + TP_PROTO(void *ci, unsigned long long block, + unsigned int nr, int flags), + TP_ARGS(ci, block, nr, flags), + TP_STRUCT__entry( + __field(void *, ci) + __field(unsigned long long, block) + __field(unsigned int, nr) + __field(int, flags) + ), + TP_fast_assign( + __entry->ci = ci; + __entry->block = block; + __entry->nr = nr; + __entry->flags = flags; + ), + TP_printk("%p %llu %u %d", __entry->ci, __entry->block, + __entry->nr, __entry->flags) +); + +/* End of trace events for fs/ocfs2/buffer_head_io.c. */ #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ -- cgit From d701485a6246486fda0ee58457b82a81562a7bc4 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Thu, 24 Feb 2011 16:22:20 +0800 Subject: ocfs2: Remove masklog ML_UPTODATE. Remove mlog(0,...) and mlog(ML_UPTODATE,...) from fs/ocfs2/uptodate.c and fs/ocfs2/buffer_head_io.c. The masklog UPTODATE is removed finally. Signed-off-by: Tao Ma --- fs/ocfs2/buffer_head_io.c | 3 +- fs/ocfs2/cluster/masklog.c | 1 - fs/ocfs2/cluster/masklog.h | 1 - fs/ocfs2/ocfs2_trace.h | 42 ++++++++++++++++++++++++++ fs/ocfs2/uptodate.c | 73 +++++++++++++++++++++++----------------------- 5 files changed, 79 insertions(+), 41 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/buffer_head_io.c b/fs/ocfs2/buffer_head_io.c index d1cf9abcd827..5d18ad10c27f 100644 --- a/fs/ocfs2/buffer_head_io.c +++ b/fs/ocfs2/buffer_head_io.c @@ -247,8 +247,7 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr, */ if (!ignore_cache && !ocfs2_buffer_uptodate(ci, bh)) { - mlog(ML_UPTODATE, - "bh (%llu), owner %llu not uptodate\n", + trace_ocfs2_read_blocks_from_disk( (unsigned long long)bh->b_blocknr, (unsigned long long)ocfs2_metadata_cache_owner(ci)); /* We're using ignore_cache here to say diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index d845ccef2408..bbea7b6cb4d3 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -93,7 +93,6 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { define_mask(DLM_RECOVERY), define_mask(AIO), define_mask(DLM_GLUE), - define_mask(UPTODATE), define_mask(VOTE), define_mask(CONN), define_mask(QUORUM), diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index ad267f614528..7a86add27f69 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -95,7 +95,6 @@ #define ML_DLM_RECOVERY 0x0000000000001000ULL /* dlm master functions */ #define ML_AIO 0x0000000000002000ULL /* ocfs2 aio read and write */ #define ML_DLM_GLUE 0x0000000000080000ULL /* ocfs2 dlm glue layer */ -#define ML_UPTODATE 0x0000000000200000ULL /* ocfs2 caching sequence #'s */ #define ML_VOTE 0x0000000001000000ULL /* ocfs2 node messaging */ #define ML_CONN 0x0000000004000000ULL /* net connection management */ #define ML_QUORUM 0x0000000008000000ULL /* net connection quorum */ diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 90dc79a22a59..a1dae5bb54ac 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h @@ -2649,6 +2649,8 @@ DEFINE_OCFS2_ULL_UINT_EVENT(ocfs2_read_blocks_sync); DEFINE_OCFS2_ULL_EVENT(ocfs2_read_blocks_sync_jbd); +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_read_blocks_from_disk); + DEFINE_OCFS2_ULL_INT_INT_INT_EVENT(ocfs2_read_blocks_bh); DEFINE_OCFS2_ULL_INT_INT_INT_EVENT(ocfs2_read_blocks_end); @@ -2688,6 +2690,46 @@ TRACE_EVENT(ocfs2_read_blocks_begin, ); /* End of trace events for fs/ocfs2/buffer_head_io.c. */ + +/* Trace events for fs/ocfs2/uptodate.c. */ + +DEFINE_OCFS2_ULL_EVENT(ocfs2_purge_copied_metadata_tree); + +DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_metadata_cache_purge); + +DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_buffer_cached_begin); + +TRACE_EVENT(ocfs2_buffer_cached_end, + TP_PROTO(int index, void *item), + TP_ARGS(index, item), + TP_STRUCT__entry( + __field(int, index) + __field(void *, item) + ), + TP_fast_assign( + __entry->index = index; + __entry->item = item; + ), + TP_printk("%d %p", __entry->index, __entry->item) +); + +DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_append_cache_array); + +DEFINE_OCFS2_ULL_ULL_UINT_EVENT(ocfs2_insert_cache_tree); + +DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_expand_cache); + +DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_set_buffer_uptodate); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_set_buffer_uptodate_begin); + +DEFINE_OCFS2_ULL_UINT_UINT_EVENT(ocfs2_remove_metadata_array); + +DEFINE_OCFS2_ULL_ULL_EVENT(ocfs2_remove_metadata_tree); + +DEFINE_OCFS2_ULL_ULL_UINT_UINT_EVENT(ocfs2_remove_block_from_cache); + +/* End of trace events for fs/ocfs2/uptodate.c. */ #endif /* _TRACE_OCFS2_H */ /* This part must be outside protection */ diff --git a/fs/ocfs2/uptodate.c b/fs/ocfs2/uptodate.c index a0a120e82b97..52eaf33d346f 100644 --- a/fs/ocfs2/uptodate.c +++ b/fs/ocfs2/uptodate.c @@ -54,14 +54,13 @@ #include #include -#define MLOG_MASK_PREFIX ML_UPTODATE - #include #include "ocfs2.h" #include "inode.h" #include "uptodate.h" +#include "ocfs2_trace.h" struct ocfs2_meta_cache_item { struct rb_node c_node; @@ -152,8 +151,8 @@ static unsigned int ocfs2_purge_copied_metadata_tree(struct rb_root *root) while ((node = rb_last(root)) != NULL) { item = rb_entry(node, struct ocfs2_meta_cache_item, c_node); - mlog(0, "Purge item %llu\n", - (unsigned long long) item->c_block); + trace_ocfs2_purge_copied_metadata_tree( + (unsigned long long) item->c_block); rb_erase(&item->c_node, root); kmem_cache_free(ocfs2_uptodate_cachep, item); @@ -180,9 +179,9 @@ void ocfs2_metadata_cache_purge(struct ocfs2_caching_info *ci) tree = !(ci->ci_flags & OCFS2_CACHE_FL_INLINE); to_purge = ci->ci_num_cached; - mlog(0, "Purge %u %s items from Owner %llu\n", to_purge, - tree ? "array" : "tree", - (unsigned long long)ocfs2_metadata_cache_owner(ci)); + trace_ocfs2_metadata_cache_purge( + (unsigned long long)ocfs2_metadata_cache_owner(ci), + to_purge, tree); /* If we're a tree, save off the root so that we can safely * initialize the cache. We do the work to free tree members @@ -249,10 +248,10 @@ static int ocfs2_buffer_cached(struct ocfs2_caching_info *ci, ocfs2_metadata_cache_lock(ci); - mlog(0, "Owner %llu, query block %llu (inline = %u)\n", - (unsigned long long)ocfs2_metadata_cache_owner(ci), - (unsigned long long) bh->b_blocknr, - !!(ci->ci_flags & OCFS2_CACHE_FL_INLINE)); + trace_ocfs2_buffer_cached_begin( + (unsigned long long)ocfs2_metadata_cache_owner(ci), + (unsigned long long) bh->b_blocknr, + !!(ci->ci_flags & OCFS2_CACHE_FL_INLINE)); if (ci->ci_flags & OCFS2_CACHE_FL_INLINE) index = ocfs2_search_cache_array(ci, bh->b_blocknr); @@ -261,7 +260,7 @@ static int ocfs2_buffer_cached(struct ocfs2_caching_info *ci, ocfs2_metadata_cache_unlock(ci); - mlog(0, "index = %d, item = %p\n", index, item); + trace_ocfs2_buffer_cached_end(index, item); return (index != -1) || (item != NULL); } @@ -306,8 +305,9 @@ static void ocfs2_append_cache_array(struct ocfs2_caching_info *ci, { BUG_ON(ci->ci_num_cached >= OCFS2_CACHE_INFO_MAX_ARRAY); - mlog(0, "block %llu takes position %u\n", (unsigned long long) block, - ci->ci_num_cached); + trace_ocfs2_append_cache_array( + (unsigned long long)ocfs2_metadata_cache_owner(ci), + (unsigned long long)block, ci->ci_num_cached); ci->ci_cache.ci_array[ci->ci_num_cached] = block; ci->ci_num_cached++; @@ -324,8 +324,9 @@ static void __ocfs2_insert_cache_tree(struct ocfs2_caching_info *ci, struct rb_node **p = &ci->ci_cache.ci_tree.rb_node; struct ocfs2_meta_cache_item *tmp; - mlog(0, "Insert block %llu num = %u\n", (unsigned long long) block, - ci->ci_num_cached); + trace_ocfs2_insert_cache_tree( + (unsigned long long)ocfs2_metadata_cache_owner(ci), + (unsigned long long)block, ci->ci_num_cached); while(*p) { parent = *p; @@ -389,9 +390,9 @@ static void ocfs2_expand_cache(struct ocfs2_caching_info *ci, tree[i] = NULL; } - mlog(0, "Expanded %llu to a tree cache: flags 0x%x, num = %u\n", - (unsigned long long)ocfs2_metadata_cache_owner(ci), - ci->ci_flags, ci->ci_num_cached); + trace_ocfs2_expand_cache( + (unsigned long long)ocfs2_metadata_cache_owner(ci), + ci->ci_flags, ci->ci_num_cached); } /* Slow path function - memory allocation is necessary. See the @@ -405,9 +406,9 @@ static void __ocfs2_set_buffer_uptodate(struct ocfs2_caching_info *ci, struct ocfs2_meta_cache_item *tree[OCFS2_CACHE_INFO_MAX_ARRAY] = { NULL, }; - mlog(0, "Owner %llu, block %llu, expand = %d\n", - (unsigned long long)ocfs2_metadata_cache_owner(ci), - (unsigned long long)block, expand_tree); + trace_ocfs2_set_buffer_uptodate( + (unsigned long long)ocfs2_metadata_cache_owner(ci), + (unsigned long long)block, expand_tree); new = kmem_cache_alloc(ocfs2_uptodate_cachep, GFP_NOFS); if (!new) { @@ -433,7 +434,6 @@ static void __ocfs2_set_buffer_uptodate(struct ocfs2_caching_info *ci, ocfs2_metadata_cache_lock(ci); if (ocfs2_insert_can_use_array(ci)) { - mlog(0, "Someone cleared the tree underneath us\n"); /* Ok, items were removed from the cache in between * locks. Detect this and revert back to the fast path */ ocfs2_append_cache_array(ci, block); @@ -490,9 +490,9 @@ void ocfs2_set_buffer_uptodate(struct ocfs2_caching_info *ci, if (ocfs2_buffer_cached(ci, bh)) return; - mlog(0, "Owner %llu, inserting block %llu\n", - (unsigned long long)ocfs2_metadata_cache_owner(ci), - (unsigned long long)bh->b_blocknr); + trace_ocfs2_set_buffer_uptodate_begin( + (unsigned long long)ocfs2_metadata_cache_owner(ci), + (unsigned long long)bh->b_blocknr); /* No need to recheck under spinlock - insertion is guarded by * co_io_lock() */ @@ -542,8 +542,9 @@ static void ocfs2_remove_metadata_array(struct ocfs2_caching_info *ci, BUG_ON(index >= ci->ci_num_cached); BUG_ON(!ci->ci_num_cached); - mlog(0, "remove index %d (num_cached = %u\n", index, - ci->ci_num_cached); + trace_ocfs2_remove_metadata_array( + (unsigned long long)ocfs2_metadata_cache_owner(ci), + index, ci->ci_num_cached); ci->ci_num_cached--; @@ -559,8 +560,9 @@ static void ocfs2_remove_metadata_array(struct ocfs2_caching_info *ci, static void ocfs2_remove_metadata_tree(struct ocfs2_caching_info *ci, struct ocfs2_meta_cache_item *item) { - mlog(0, "remove block %llu from tree\n", - (unsigned long long) item->c_block); + trace_ocfs2_remove_metadata_tree( + (unsigned long long)ocfs2_metadata_cache_owner(ci), + (unsigned long long)item->c_block); rb_erase(&item->c_node, &ci->ci_cache.ci_tree); ci->ci_num_cached--; @@ -573,10 +575,10 @@ static void ocfs2_remove_block_from_cache(struct ocfs2_caching_info *ci, struct ocfs2_meta_cache_item *item = NULL; ocfs2_metadata_cache_lock(ci); - mlog(0, "Owner %llu, remove %llu, items = %u, array = %u\n", - (unsigned long long)ocfs2_metadata_cache_owner(ci), - (unsigned long long) block, ci->ci_num_cached, - ci->ci_flags & OCFS2_CACHE_FL_INLINE); + trace_ocfs2_remove_block_from_cache( + (unsigned long long)ocfs2_metadata_cache_owner(ci), + (unsigned long long) block, ci->ci_num_cached, + ci->ci_flags); if (ci->ci_flags & OCFS2_CACHE_FL_INLINE) { index = ocfs2_search_cache_array(ci, block); @@ -626,9 +628,6 @@ int __init init_ocfs2_uptodate_cache(void) if (!ocfs2_uptodate_cachep) return -ENOMEM; - mlog(0, "%u inlined cache items per inode.\n", - OCFS2_CACHE_INFO_MAX_ARRAY); - return 0; } -- cgit From 75ba49ae0637c15880fe8f1c8a89333afa052bd8 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Mon, 21 Feb 2011 11:19:27 +0800 Subject: ocfs2: Remove masklog ML_AIO. There is no user for masklog AIO, so remove it. Signed-off-by: Tao Ma --- fs/ocfs2/cluster/masklog.c | 1 - fs/ocfs2/cluster/masklog.h | 1 - 2 files changed, 2 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index bbea7b6cb4d3..07ac24fd9252 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -91,7 +91,6 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = { define_mask(DLM_THREAD), define_mask(DLM_MASTER), define_mask(DLM_RECOVERY), - define_mask(AIO), define_mask(DLM_GLUE), define_mask(VOTE), define_mask(CONN), diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index 7a86add27f69..0fe96c2830c2 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -93,7 +93,6 @@ #define ML_DLM_THREAD 0x0000000000000400ULL /* dlm domain thread */ #define ML_DLM_MASTER 0x0000000000000800ULL /* dlm master functions */ #define ML_DLM_RECOVERY 0x0000000000001000ULL /* dlm master functions */ -#define ML_AIO 0x0000000000002000ULL /* ocfs2 aio read and write */ #define ML_DLM_GLUE 0x0000000000080000ULL /* ocfs2 dlm glue layer */ #define ML_VOTE 0x0000000001000000ULL /* ocfs2 node messaging */ #define ML_CONN 0x0000000004000000ULL /* net connection management */ -- cgit From b4e1b7e88b2c87c358c2a88bec0c76d25accc604 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Mon, 21 Feb 2011 11:19:43 +0800 Subject: ocfs2: Make the left masklogs compat. Since we have removed almost all of the masklogs in fs/ocfs2/*, make the left masklogs compat. Signed-off-by: Tao Ma --- fs/ocfs2/cluster/masklog.h | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h index 0fe96c2830c2..baa2b9ef7eef 100644 --- a/fs/ocfs2/cluster/masklog.h +++ b/fs/ocfs2/cluster/masklog.h @@ -82,23 +82,23 @@ /* bits that are frequently given and infrequently matched in the low word */ /* NOTE: If you add a flag, you need to also update masklog.c! */ -#define ML_TCP 0x0000000000000004ULL /* net cluster/tcp.c */ -#define ML_MSG 0x0000000000000008ULL /* net network messages */ -#define ML_SOCKET 0x0000000000000010ULL /* net socket lifetime */ -#define ML_HEARTBEAT 0x0000000000000020ULL /* hb all heartbeat tracking */ -#define ML_HB_BIO 0x0000000000000040ULL /* hb io tracing */ -#define ML_DLMFS 0x0000000000000080ULL /* dlm user dlmfs */ -#define ML_DLM 0x0000000000000100ULL /* dlm general debugging */ -#define ML_DLM_DOMAIN 0x0000000000000200ULL /* dlm domain debugging */ -#define ML_DLM_THREAD 0x0000000000000400ULL /* dlm domain thread */ -#define ML_DLM_MASTER 0x0000000000000800ULL /* dlm master functions */ -#define ML_DLM_RECOVERY 0x0000000000001000ULL /* dlm master functions */ -#define ML_DLM_GLUE 0x0000000000080000ULL /* ocfs2 dlm glue layer */ -#define ML_VOTE 0x0000000001000000ULL /* ocfs2 node messaging */ -#define ML_CONN 0x0000000004000000ULL /* net connection management */ -#define ML_QUORUM 0x0000000008000000ULL /* net connection quorum */ -#define ML_BASTS 0x0000000100000000ULL /* dlmglue asts and basts */ -#define ML_CLUSTER 0x0000000400000000ULL /* cluster stack */ +#define ML_TCP 0x0000000000000001ULL /* net cluster/tcp.c */ +#define ML_MSG 0x0000000000000002ULL /* net network messages */ +#define ML_SOCKET 0x0000000000000004ULL /* net socket lifetime */ +#define ML_HEARTBEAT 0x0000000000000008ULL /* hb all heartbeat tracking */ +#define ML_HB_BIO 0x0000000000000010ULL /* hb io tracing */ +#define ML_DLMFS 0x0000000000000020ULL /* dlm user dlmfs */ +#define ML_DLM 0x0000000000000040ULL /* dlm general debugging */ +#define ML_DLM_DOMAIN 0x0000000000000080ULL /* dlm domain debugging */ +#define ML_DLM_THREAD 0x0000000000000100ULL /* dlm domain thread */ +#define ML_DLM_MASTER 0x0000000000000200ULL /* dlm master functions */ +#define ML_DLM_RECOVERY 0x0000000000000400ULL /* dlm master functions */ +#define ML_DLM_GLUE 0x0000000000000800ULL /* ocfs2 dlm glue layer */ +#define ML_VOTE 0x0000000000001000ULL /* ocfs2 node messaging */ +#define ML_CONN 0x0000000000002000ULL /* net connection management */ +#define ML_QUORUM 0x0000000000004000ULL /* net connection quorum */ +#define ML_BASTS 0x0000000000008000ULL /* dlmglue asts and basts */ +#define ML_CLUSTER 0x0000000000010000ULL /* cluster stack */ /* bits that are infrequently given and frequently matched in the high word */ #define ML_ERROR 0x1000000000000000ULL /* sent to KERN_ERR */ -- cgit From da488945f4bf4096f4ab6091938469bd8822cfec Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Mon, 21 Feb 2011 20:39:58 -0500 Subject: ext4: fix compile warnings with EXT4FS_DEBUG enabled Compile 2.6.38-rc1 with turning EXT4FS_DEBUG on, we get following compile warnings. This patch fixes them. CC fs/ext4/hash.o CC fs/ext4/resize.o fs/ext4/resize.c: In function 'setup_new_group_blocks': fs/ext4/resize.c:233:2: warning: format '%#04llx' expects type 'long long unsigned int', but argument 3 has type 'long unsigned int' fs/ext4/resize.c:251:2: warning: format '%#04llx' expects type 'long long unsigned int', but argument 3 has type 'long unsigned int' CC fs/ext4/extents.o CC fs/ext4/ext4_jbd2.o CC fs/ext4/migrate.o Reported-by: Akira Fujita Signed-off-by: "Theodore Ts'o" --- fs/ext4/resize.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 3ecc6e45d2f9..66fec4ee76fa 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -230,7 +230,7 @@ static int setup_new_group_blocks(struct super_block *sb, } /* Zero out all of the reserved backup group descriptor table blocks */ - ext4_debug("clear inode table blocks %#04llx -> %#04llx\n", + ext4_debug("clear inode table blocks %#04llx -> %#04lx\n", block, sbi->s_itb_per_group); err = sb_issue_zeroout(sb, gdblocks + start + 1, reserved_gdb, GFP_NOFS); @@ -248,7 +248,7 @@ static int setup_new_group_blocks(struct super_block *sb, /* Zero out all of the inode table blocks */ block = input->inode_table; - ext4_debug("clear inode table blocks %#04llx -> %#04llx\n", + ext4_debug("clear inode table blocks %#04llx -> %#04lx\n", block, sbi->s_itb_per_group); err = sb_issue_zeroout(sb, block, sbi->s_itb_per_group, GFP_NOFS); if (err) -- cgit From c4d0c3b097f7584772316ee4d64a09fe0e4ddfca Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Mon, 14 Feb 2011 13:45:28 +0000 Subject: xfs: prevent leaking uninitialized stack memory in FSGEOMETRY_V1 The FSGEOMETRY_V1 ioctl (and its compat equivalent) calls out to xfs_fs_geometry() with a version number of 3. This code path does not fill in the logsunit member of the passed xfs_fsop_geom_t, leading to the leaking of four bytes of uninitialized stack data to potentially unprivileged callers. v2 switches to memset() to avoid future issues if structure members change, on suggestion of Dave Chinner. Signed-off-by: Dan Rosenberg Reviewed-by: Eugene Teo Signed-off-by: Alex Elder --- fs/xfs/xfs_fsops.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'fs') diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index cec89dd5d7d2..85668efb3e3e 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -53,6 +53,9 @@ xfs_fs_geometry( xfs_fsop_geom_t *geo, int new_version) { + + memset(geo, 0, sizeof(*geo)); + geo->blocksize = mp->m_sb.sb_blocksize; geo->rtextsize = mp->m_sb.sb_rextsize; geo->agblocks = mp->m_sb.sb_agblocks; -- cgit From 7dc576158d7e5cdff3349f78598fdb4080536342 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Mon, 21 Feb 2011 21:01:42 -0500 Subject: ext4: Fix sparse warning: Using plain integer as NULL pointer This patch fixes the warning "Using plain integer as NULL pointer", generated by sparse, by replacing the offending 0s with NULL. Signed-off-by: Peter Huewe Signed-off-by: "Theodore Ts'o" --- fs/ext4/extents.c | 8 ++++---- fs/ext4/ialloc.c | 2 +- fs/ext4/inode.c | 18 +++++++++--------- fs/ext4/migrate.c | 10 +++++----- fs/ext4/page-io.c | 4 ++-- fs/ext4/super.c | 2 +- fs/ext4/xattr.c | 2 +- 7 files changed, 23 insertions(+), 23 deletions(-) (limited to 'fs') diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index ccce8a7e94ed..d16f6b5a140b 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -1034,7 +1034,7 @@ cleanup: for (i = 0; i < depth; i++) { if (!ablocks[i]) continue; - ext4_free_blocks(handle, inode, 0, ablocks[i], 1, + ext4_free_blocks(handle, inode, NULL, ablocks[i], 1, EXT4_FREE_BLOCKS_METADATA); } } @@ -2059,7 +2059,7 @@ static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode, if (err) return err; ext_debug("index is empty, remove it, free block %llu\n", leaf); - ext4_free_blocks(handle, inode, 0, leaf, 1, + ext4_free_blocks(handle, inode, NULL, leaf, 1, EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); return err; } @@ -2156,7 +2156,7 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode, num = le32_to_cpu(ex->ee_block) + ee_len - from; start = ext4_ext_pblock(ex) + ee_len - num; ext_debug("free last %u blocks starting %llu\n", num, start); - ext4_free_blocks(handle, inode, 0, start, num, flags); + ext4_free_blocks(handle, inode, NULL, start, num, flags); } else if (from == le32_to_cpu(ex->ee_block) && to <= le32_to_cpu(ex->ee_block) + ee_len - 1) { printk(KERN_INFO "strange request: removal %u-%u from %u:%u\n", @@ -3485,7 +3485,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, /* not a good idea to call discard here directly, * but otherwise we'd need to call it every free() */ ext4_discard_preallocations(inode); - ext4_free_blocks(handle, inode, 0, ext4_ext_pblock(&newex), + ext4_free_blocks(handle, inode, NULL, ext4_ext_pblock(&newex), ext4_ext_get_actual_len(&newex), 0); goto out2; } diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index eb9097aec6f0..2fd3b0e41787 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -649,7 +649,7 @@ static int find_group_other(struct super_block *sb, struct inode *parent, *group = parent_group + flex_size; if (*group > ngroups) *group = 0; - return find_group_orlov(sb, parent, group, mode, 0); + return find_group_orlov(sb, parent, group, mode, NULL); } /* diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 9f7f9e49914f..c6c6b7fcb455 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -720,7 +720,7 @@ allocated: return ret; failed_out: for (i = 0; i < index; i++) - ext4_free_blocks(handle, inode, 0, new_blocks[i], 1, 0); + ext4_free_blocks(handle, inode, NULL, new_blocks[i], 1, 0); return ret; } @@ -823,20 +823,20 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode, return err; failed: /* Allocation failed, free what we already allocated */ - ext4_free_blocks(handle, inode, 0, new_blocks[0], 1, 0); + ext4_free_blocks(handle, inode, NULL, new_blocks[0], 1, 0); for (i = 1; i <= n ; i++) { /* * branch[i].bh is newly allocated, so there is no * need to revoke the block, which is why we don't * need to set EXT4_FREE_BLOCKS_METADATA. */ - ext4_free_blocks(handle, inode, 0, new_blocks[i], 1, + ext4_free_blocks(handle, inode, NULL, new_blocks[i], 1, EXT4_FREE_BLOCKS_FORGET); } for (i = n+1; i < indirect_blks; i++) - ext4_free_blocks(handle, inode, 0, new_blocks[i], 1, 0); + ext4_free_blocks(handle, inode, NULL, new_blocks[i], 1, 0); - ext4_free_blocks(handle, inode, 0, new_blocks[i], num, 0); + ext4_free_blocks(handle, inode, NULL, new_blocks[i], num, 0); return err; } @@ -924,7 +924,7 @@ err_out: ext4_free_blocks(handle, inode, where[i].bh, 0, 1, EXT4_FREE_BLOCKS_FORGET); } - ext4_free_blocks(handle, inode, 0, le32_to_cpu(where[num].key), + ext4_free_blocks(handle, inode, NULL, le32_to_cpu(where[num].key), blks, 0); return err; @@ -4228,7 +4228,7 @@ static int ext4_clear_blocks(handle_t *handle, struct inode *inode, for (p = first; p < last; p++) *p = 0; - ext4_free_blocks(handle, inode, 0, block_to_free, count, flags); + ext4_free_blocks(handle, inode, NULL, block_to_free, count, flags); return 0; } @@ -4416,7 +4416,7 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode, * transaction where the data blocks are * actually freed. */ - ext4_free_blocks(handle, inode, 0, nr, 1, + ext4_free_blocks(handle, inode, NULL, nr, 1, EXT4_FREE_BLOCKS_METADATA| EXT4_FREE_BLOCKS_FORGET); @@ -4875,7 +4875,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) return inode; ei = EXT4_I(inode); - iloc.bh = 0; + iloc.bh = NULL; ret = __ext4_get_inode_loc(inode, &iloc, 0); if (ret < 0) diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c index b0a126f23c20..d1bafa57f483 100644 --- a/fs/ext4/migrate.c +++ b/fs/ext4/migrate.c @@ -263,7 +263,7 @@ static int free_dind_blocks(handle_t *handle, for (i = 0; i < max_entries; i++) { if (tmp_idata[i]) { extend_credit_for_blkdel(handle, inode); - ext4_free_blocks(handle, inode, 0, + ext4_free_blocks(handle, inode, NULL, le32_to_cpu(tmp_idata[i]), 1, EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); @@ -271,7 +271,7 @@ static int free_dind_blocks(handle_t *handle, } put_bh(bh); extend_credit_for_blkdel(handle, inode); - ext4_free_blocks(handle, inode, 0, le32_to_cpu(i_data), 1, + ext4_free_blocks(handle, inode, NULL, le32_to_cpu(i_data), 1, EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); return 0; @@ -302,7 +302,7 @@ static int free_tind_blocks(handle_t *handle, } put_bh(bh); extend_credit_for_blkdel(handle, inode); - ext4_free_blocks(handle, inode, 0, le32_to_cpu(i_data), 1, + ext4_free_blocks(handle, inode, NULL, le32_to_cpu(i_data), 1, EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); return 0; @@ -315,7 +315,7 @@ static int free_ind_block(handle_t *handle, struct inode *inode, __le32 *i_data) /* ei->i_data[EXT4_IND_BLOCK] */ if (i_data[0]) { extend_credit_for_blkdel(handle, inode); - ext4_free_blocks(handle, inode, 0, + ext4_free_blocks(handle, inode, NULL, le32_to_cpu(i_data[0]), 1, EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); @@ -428,7 +428,7 @@ static int free_ext_idx(handle_t *handle, struct inode *inode, } put_bh(bh); extend_credit_for_blkdel(handle, inode); - ext4_free_blocks(handle, inode, 0, block, 1, + ext4_free_blocks(handle, inode, NULL, block, 1, EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); return retval; } diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index 955cc309142f..68d92a8f71d7 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c @@ -279,9 +279,9 @@ void ext4_io_submit(struct ext4_io_submit *io) BUG_ON(bio_flagged(io->io_bio, BIO_EOPNOTSUPP)); bio_put(io->io_bio); } - io->io_bio = 0; + io->io_bio = NULL; io->io_op = 0; - io->io_end = 0; + io->io_end = NULL; } static int io_submit_init(struct ext4_io_submit *io, diff --git a/fs/ext4/super.c b/fs/ext4/super.c index f6a318f836b2..ef83457fd4ea 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -1451,7 +1451,7 @@ static int parse_options(char *options, struct super_block *sb, * Initialize args struct so we know whether arg was * found; some options take optional arguments. */ - args[0].to = args[0].from = 0; + args[0].to = args[0].from = NULL; token = match_token(p, tokens, args); switch (token) { case Opt_bsd_df: diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index fc32176eee39..f4c03af05d69 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c @@ -833,7 +833,7 @@ inserted: new_bh = sb_getblk(sb, block); if (!new_bh) { getblk_failed: - ext4_free_blocks(handle, inode, 0, block, 1, + ext4_free_blocks(handle, inode, NULL, block, 1, EXT4_FREE_BLOCKS_METADATA); error = -EIO; goto cleanup; -- cgit From 5dbd571d875d73e087c1eeb3d840cfc653a97422 Mon Sep 17 00:00:00 2001 From: "Alexander V. Lukyanov" Date: Mon, 21 Feb 2011 21:33:21 -0500 Subject: ext4: allow inode_readahead_blks=0 (linux-2.6.37) I cannot disable inode-read-ahead feature of ext4 (on 2.6.37): # echo 0 > /sys/fs/ext4/sda2/inode_readahead_blks bash: echo: write error: Invalid argument On a server with lots of small files and random access this read-ahead makes performance worse, and I'd like to disable it. I work around this problem by using value of 1, but it still reads an extra block. This patch fixes the problem by checking for zero explicitly. Signed-off-by: Alexander V. Lukyanov Signed-off-by: "Theodore Ts'o" --- fs/ext4/super.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/ext4/super.c b/fs/ext4/super.c index ef83457fd4ea..a1ac24b6a758 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -1771,7 +1771,7 @@ set_qf_format: return 0; if (option < 0 || option > (1 << 30)) return 0; - if (!is_power_of_2(option)) { + if (option && !is_power_of_2(option)) { ext4_msg(sb, KERN_ERR, "EXT4-fs: inode_readahead_blks" " must be a power of 2"); @@ -2412,7 +2412,7 @@ static ssize_t inode_readahead_blks_store(struct ext4_attr *a, if (parse_strtoul(buf, 0x40000000, &t)) return -EINVAL; - if (!is_power_of_2(t)) + if (t && !is_power_of_2(t)) return -EINVAL; sbi->s_inode_readahead_blks = t; -- cgit From 5d15765594eeb5d82c5630b3428ea0ac4f7d3c31 Mon Sep 17 00:00:00 2001 From: Lukas Czerner Date: Tue, 15 Feb 2011 17:07:36 +0000 Subject: xfs: check if device support discard in xfs_ioc_trim() Right now we, are relying on the fact that when we attempt to actually do the discard, blkdev_issue_discar() returns -EOPNOTSUPP and the user is informed that the device does not support discard. However, in the case where the we do not hit any suitable free extent to trim in FITRIM code, it will finish without any error. This is very confusing, because it seems that FITRIM was successful even though the device does not actually supports discard. Solution: Check for the discard support before attempt to search for free extents. Signed-off-by: Lukas Czerner Signed-off-by: Alex Elder --- fs/xfs/linux-2.6/xfs_discard.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_discard.c b/fs/xfs/linux-2.6/xfs_discard.c index 05201ae719e5..d61611c88012 100644 --- a/fs/xfs/linux-2.6/xfs_discard.c +++ b/fs/xfs/linux-2.6/xfs_discard.c @@ -152,6 +152,8 @@ xfs_ioc_trim( if (!capable(CAP_SYS_ADMIN)) return -XFS_ERROR(EPERM); + if (!blk_queue_discard(q)) + return -XFS_ERROR(EOPNOTSUPP); if (copy_from_user(&range, urange, sizeof(range))) return -XFS_ERROR(EFAULT); -- cgit From 770c4d81e0d2ca45516ddc9ae0a69565790b5533 Mon Sep 17 00:00:00 2001 From: Sunil Mushran Date: Mon, 21 Feb 2011 14:25:25 -0800 Subject: ocfs2/dlm: Move kmalloc() outside the spinlock In dlm_query_region_handler(), move the kmalloc outside the spinlock. This allows us to use GFP_KERNEL instead of GFP_ATOMIC. Signed-off-by: Sunil Mushran Signed-off-by: Joel Becker --- fs/ocfs2/dlm/dlmdomain.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c index 7e38a072d720..99805d578ab5 100644 --- a/fs/ocfs2/dlm/dlmdomain.c +++ b/fs/ocfs2/dlm/dlmdomain.c @@ -926,9 +926,10 @@ static int dlm_assert_joined_handler(struct o2net_msg *msg, u32 len, void *data, } static int dlm_match_regions(struct dlm_ctxt *dlm, - struct dlm_query_region *qr) + struct dlm_query_region *qr, + char *local, int locallen) { - char *local = NULL, *remote = qr->qr_regions; + char *remote = qr->qr_regions; char *l, *r; int localnr, i, j, foundit; int status = 0; @@ -957,13 +958,8 @@ static int dlm_match_regions(struct dlm_ctxt *dlm, r += O2HB_MAX_REGION_NAME_LEN; } - local = kmalloc(sizeof(qr->qr_regions), GFP_ATOMIC); - if (!local) { - status = -ENOMEM; - goto bail; - } - - localnr = o2hb_get_all_regions(local, O2NM_MAX_REGIONS); + localnr = min(O2NM_MAX_REGIONS, locallen/O2HB_MAX_REGION_NAME_LEN); + localnr = o2hb_get_all_regions(local, (u8)localnr); /* compare local regions with remote */ l = local; @@ -1012,8 +1008,6 @@ static int dlm_match_regions(struct dlm_ctxt *dlm, } bail: - kfree(local); - return status; } @@ -1075,6 +1069,7 @@ static int dlm_query_region_handler(struct o2net_msg *msg, u32 len, { struct dlm_query_region *qr; struct dlm_ctxt *dlm = NULL; + char *local = NULL; int status = 0; int locked = 0; @@ -1083,6 +1078,13 @@ static int dlm_query_region_handler(struct o2net_msg *msg, u32 len, mlog(0, "Node %u queries hb regions on domain %s\n", qr->qr_node, qr->qr_domain); + /* buffer used in dlm_mast_regions() */ + local = kmalloc(sizeof(qr->qr_regions), GFP_KERNEL); + if (!local) { + status = -ENOMEM; + goto bail; + } + status = -EINVAL; spin_lock(&dlm_domain_lock); @@ -1112,13 +1114,15 @@ static int dlm_query_region_handler(struct o2net_msg *msg, u32 len, goto bail; } - status = dlm_match_regions(dlm, qr); + status = dlm_match_regions(dlm, qr, local, sizeof(qr->qr_regions)); bail: if (locked) spin_unlock(&dlm->spinlock); spin_unlock(&dlm_domain_lock); + kfree(local); + return status; } -- cgit From 1050c71e2925ab0cb025e4c89e08b15529a1ee36 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 13 Feb 2011 13:25:31 +0000 Subject: xfs: stop using xfs_trans_iget in the RT allocator During mount we establish references to the RT inodes, which we keep for the lifetime of the filesystem. Instead of using xfs_trans_iget to grab additional references when adding RT inodes to transactions use the combination of xfs_ilock and xfs_trans_ijoin_ref, which archives the same end result with less overhead. Signed-off-by: Christoph Hellwig Reviewed-by: Dave Chinner Signed-off-by: Alex Elder --- fs/xfs/xfs_bmap.c | 8 ++------ fs/xfs/xfs_rtalloc.c | 54 ++++++++++++++++++++-------------------------------- 2 files changed, 23 insertions(+), 39 deletions(-) (limited to 'fs') diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index d8d090665283..e7b441db0530 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -2333,7 +2333,6 @@ xfs_bmap_rtalloc( xfs_extlen_t prod = 0; /* product factor for allocators */ xfs_extlen_t ralen = 0; /* realtime allocation length */ xfs_extlen_t align; /* minimum allocation alignment */ - xfs_inode_t *ip; /* bitmap incore inode */ xfs_rtblock_t rtb; mp = ap->ip->i_mount; @@ -2370,11 +2369,8 @@ xfs_bmap_rtalloc( /* * Lock out other modifications to the RT bitmap inode. */ - error = xfs_trans_iget(mp, ap->tp, mp->m_sb.sb_rbmino, 0, - XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP, &ip); - if (error) - return error; - ASSERT(ip == mp->m_rbmip); + xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL); + xfs_trans_ijoin_ref(ap->tp, mp->m_rbmip, XFS_ILOCK_EXCL); /* * If it's an allocation to an empty file at offset 0, diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index f592ac978186..fbff89344bad 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -76,7 +76,7 @@ xfs_growfs_rt_alloc( xfs_mount_t *mp, /* file system mount point */ xfs_extlen_t oblocks, /* old count of blocks */ xfs_extlen_t nblocks, /* new count of blocks */ - xfs_ino_t ino) /* inode number (bitmap/summary) */ + xfs_inode_t *ip) /* inode (bitmap/summary) */ { xfs_fileoff_t bno; /* block number in file */ xfs_buf_t *bp; /* temporary buffer for zeroing */ @@ -86,7 +86,6 @@ xfs_growfs_rt_alloc( xfs_fsblock_t firstblock; /* first block allocated in xaction */ xfs_bmap_free_t flist; /* list of freed blocks */ xfs_fsblock_t fsbno; /* filesystem block for bno */ - xfs_inode_t *ip; /* pointer to incore inode */ xfs_bmbt_irec_t map; /* block map output */ int nmap; /* number of block maps */ int resblks; /* space reservation */ @@ -112,9 +111,9 @@ xfs_growfs_rt_alloc( /* * Lock the inode. */ - if ((error = xfs_trans_iget(mp, tp, ino, 0, - XFS_ILOCK_EXCL, &ip))) - goto error_cancel; + xfs_ilock(ip, XFS_ILOCK_EXCL); + xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL); + xfs_bmap_init(&flist, &firstblock); /* * Allocate blocks to the bitmap file. @@ -155,9 +154,8 @@ xfs_growfs_rt_alloc( /* * Lock the bitmap inode. */ - if ((error = xfs_trans_iget(mp, tp, ino, 0, - XFS_ILOCK_EXCL, &ip))) - goto error_cancel; + xfs_ilock(ip, XFS_ILOCK_EXCL); + xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL); /* * Get a buffer for the block. */ @@ -1854,7 +1852,6 @@ xfs_growfs_rt( xfs_rtblock_t bmbno; /* bitmap block number */ xfs_buf_t *bp; /* temporary buffer */ int error; /* error return value */ - xfs_inode_t *ip; /* bitmap inode, used as lock */ xfs_mount_t *nmp; /* new (fake) mount structure */ xfs_drfsbno_t nrblocks; /* new number of realtime blocks */ xfs_extlen_t nrbmblocks; /* new number of rt bitmap blocks */ @@ -1918,11 +1915,11 @@ xfs_growfs_rt( /* * Allocate space to the bitmap and summary files, as necessary. */ - if ((error = xfs_growfs_rt_alloc(mp, rbmblocks, nrbmblocks, - mp->m_sb.sb_rbmino))) + error = xfs_growfs_rt_alloc(mp, rbmblocks, nrbmblocks, mp->m_rbmip); + if (error) return error; - if ((error = xfs_growfs_rt_alloc(mp, rsumblocks, nrsumblocks, - mp->m_sb.sb_rsumino))) + error = xfs_growfs_rt_alloc(mp, rsumblocks, nrsumblocks, mp->m_rsumip); + if (error) return error; /* * Allocate a new (fake) mount/sb. @@ -1972,12 +1969,8 @@ xfs_growfs_rt( /* * Lock out other callers by grabbing the bitmap inode lock. */ - error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0, - XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP, - &ip); - if (error) - goto error_cancel; - ASSERT(ip == mp->m_rbmip); + xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL); + xfs_trans_ijoin_ref(tp, mp->m_rbmip, XFS_ILOCK_EXCL); /* * Update the bitmap inode's size. */ @@ -1988,11 +1981,8 @@ xfs_growfs_rt( /* * Get the summary inode into the transaction. */ - error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rsumino, 0, - XFS_ILOCK_EXCL | XFS_ILOCK_RTSUM, &ip); - if (error) - goto error_cancel; - ASSERT(ip == mp->m_rsumip); + xfs_ilock(mp->m_rsumip, XFS_ILOCK_EXCL); + xfs_trans_ijoin_ref(tp, mp->m_rsumip, XFS_ILOCK_EXCL); /* * Update the summary inode's size. */ @@ -2154,7 +2144,6 @@ xfs_rtfree_extent( xfs_extlen_t len) /* length of extent freed */ { int error; /* error value */ - xfs_inode_t *ip; /* bitmap file inode */ xfs_mount_t *mp; /* file system mount structure */ xfs_fsblock_t sb; /* summary file block number */ xfs_buf_t *sumbp; /* summary file block buffer */ @@ -2163,10 +2152,9 @@ xfs_rtfree_extent( /* * Synchronize by locking the bitmap inode. */ - error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0, - XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP, &ip); - if (error) - return error; + xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL); + xfs_trans_ijoin_ref(tp, mp->m_rbmip, XFS_ILOCK_EXCL); + #if defined(__KERNEL__) && defined(DEBUG) /* * Check to see that this whole range is currently allocated. @@ -2199,10 +2187,10 @@ xfs_rtfree_extent( */ if (tp->t_frextents_delta + mp->m_sb.sb_frextents == mp->m_sb.sb_rextents) { - if (!(ip->i_d.di_flags & XFS_DIFLAG_NEWRTBM)) - ip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM; - *(__uint64_t *)&ip->i_d.di_atime = 0; - xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); + if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM)) + mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM; + *(__uint64_t *)&mp->m_rbmip->i_d.di_atime = 0; + xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE); } return 0; } -- cgit From ec3ba85f4083d10e32fe58b46db02d78ef71f6b8 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 13 Feb 2011 13:26:42 +0000 Subject: xfs: more sensible inode refcounting for ialloc Currently we return iodes from xfs_ialloc with just a single reference held. But we need two references, as one is dropped during transaction commit and the second needs to be transfered to the VFS. Change xfs_ialloc to use xfs_iget plus xfs_trans_ijoin_ref to grab two references to the inode, and remove the now superflous IHOLD calls from all callers. This also greatly simplifies the error handling in xfs_create and also allow to remove xfs_trans_iget as no other callers are left. Signed-off-by: Christoph Hellwig Reviewed-by: Dave Chinner Signed-off-by: Alex Elder --- fs/xfs/quota/xfs_qm.c | 7 ------ fs/xfs/xfs_inode.c | 5 ++-- fs/xfs/xfs_trans.h | 2 -- fs/xfs/xfs_trans_inode.c | 22 ----------------- fs/xfs/xfs_vnodeops.c | 61 +++++++++++++----------------------------------- 5 files changed, 19 insertions(+), 78 deletions(-) (limited to 'fs') diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index 206a2815ced6..f517963aec07 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c @@ -1229,13 +1229,6 @@ xfs_qm_qino_alloc( return error; } - /* - * Keep an extra reference to this quota inode. This inode is - * locked exclusively and joined to the transaction already. - */ - ASSERT(xfs_isilocked(*ip, XFS_ILOCK_EXCL)); - IHOLD(*ip); - /* * Make the changes in the superblock, and log those too. * sbfields arg may contain fields other than *QUOTINO; diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index be7cf625421f..c39278b6c871 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1016,8 +1016,8 @@ xfs_ialloc( * This is because we're setting fields here we need * to prevent others from looking at until we're done. */ - error = xfs_trans_iget(tp->t_mountp, tp, ino, - XFS_IGET_CREATE, XFS_ILOCK_EXCL, &ip); + error = xfs_iget(tp->t_mountp, tp, ino, XFS_IGET_CREATE, + XFS_ILOCK_EXCL, &ip); if (error) return error; ASSERT(ip != NULL); @@ -1166,6 +1166,7 @@ xfs_ialloc( /* * Log the new values stuffed into the inode. */ + xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL); xfs_trans_log_inode(tp, ip, flags); /* now that we have an i_mode we can setup inode ops and unlock */ diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index c2042b736b81..06a9759b6352 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -469,8 +469,6 @@ void xfs_trans_inode_buf(xfs_trans_t *, struct xfs_buf *); void xfs_trans_stale_inode_buf(xfs_trans_t *, struct xfs_buf *); void xfs_trans_dquot_buf(xfs_trans_t *, struct xfs_buf *, uint); void xfs_trans_inode_alloc_buf(xfs_trans_t *, struct xfs_buf *); -int xfs_trans_iget(struct xfs_mount *, xfs_trans_t *, - xfs_ino_t , uint, uint, struct xfs_inode **); void xfs_trans_ichgtime(struct xfs_trans *, struct xfs_inode *, int); void xfs_trans_ijoin_ref(struct xfs_trans *, struct xfs_inode *, uint); void xfs_trans_ijoin(struct xfs_trans *, struct xfs_inode *); diff --git a/fs/xfs/xfs_trans_inode.c b/fs/xfs/xfs_trans_inode.c index ccb34532768b..16084d8ea231 100644 --- a/fs/xfs/xfs_trans_inode.c +++ b/fs/xfs/xfs_trans_inode.c @@ -43,28 +43,6 @@ xfs_trans_inode_broot_debug( #define xfs_trans_inode_broot_debug(ip) #endif -/* - * Get an inode and join it to the transaction. - */ -int -xfs_trans_iget( - xfs_mount_t *mp, - xfs_trans_t *tp, - xfs_ino_t ino, - uint flags, - uint lock_flags, - xfs_inode_t **ipp) -{ - int error; - - error = xfs_iget(mp, tp, ino, flags, lock_flags, ipp); - if (!error && tp) { - xfs_trans_ijoin(tp, *ipp); - (*ipp)->i_itemp->ili_lock_flags = lock_flags; - } - return error; -} - /* * Add a locked inode to the transaction. * diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index d8e6f8cd6f0c..258d4f98eb9b 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -1310,7 +1310,7 @@ xfs_create( error = xfs_qm_vop_dqalloc(dp, current_fsuid(), current_fsgid(), prid, XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp); if (error) - goto std_return; + return error; if (is_dir) { rdev = 0; @@ -1389,12 +1389,6 @@ xfs_create( goto out_trans_abort; } - /* - * At this point, we've gotten a newly allocated inode. - * It is locked (and joined to the transaction). - */ - ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); - /* * Now we join the directory inode to the transaction. We do not do it * earlier because xfs_dir_ialloc might commit the previous transaction @@ -1440,22 +1434,13 @@ xfs_create( */ xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp); - /* - * xfs_trans_commit normally decrements the vnode ref count - * when it unlocks the inode. Since we want to return the - * vnode to the caller, we bump the vnode ref count now. - */ - IHOLD(ip); - error = xfs_bmap_finish(&tp, &free_list, &committed); if (error) - goto out_abort_rele; + goto out_bmap_cancel; error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); - if (error) { - IRELE(ip); - goto out_dqrele; - } + if (error) + goto out_release_inode; xfs_qm_dqrele(udqp); xfs_qm_dqrele(gdqp); @@ -1469,27 +1454,21 @@ xfs_create( cancel_flags |= XFS_TRANS_ABORT; out_trans_cancel: xfs_trans_cancel(tp, cancel_flags); - out_dqrele: + out_release_inode: + /* + * Wait until after the current transaction is aborted to + * release the inode. This prevents recursive transactions + * and deadlocks from xfs_inactive. + */ + if (ip) + IRELE(ip); + xfs_qm_dqrele(udqp); xfs_qm_dqrele(gdqp); if (unlock_dp_on_error) xfs_iunlock(dp, XFS_ILOCK_EXCL); - std_return: return error; - - out_abort_rele: - /* - * Wait until after the current transaction is aborted to - * release the inode. This prevents recursive transactions - * and deadlocks from xfs_inactive. - */ - xfs_bmap_cancel(&free_list); - cancel_flags |= XFS_TRANS_ABORT; - xfs_trans_cancel(tp, cancel_flags); - IRELE(ip); - unlock_dp_on_error = B_FALSE; - goto out_dqrele; } #ifdef DEBUG @@ -2114,9 +2093,8 @@ xfs_symlink( XFS_BMAPI_WRITE | XFS_BMAPI_METADATA, &first_block, resblks, mval, &nmaps, &free_list); - if (error) { - goto error1; - } + if (error) + goto error2; if (resblks) resblks -= fs_blocks; @@ -2148,7 +2126,7 @@ xfs_symlink( error = xfs_dir_createname(tp, dp, link_name, ip->i_ino, &first_block, &free_list, resblks); if (error) - goto error1; + goto error2; xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); @@ -2161,13 +2139,6 @@ xfs_symlink( xfs_trans_set_sync(tp); } - /* - * xfs_trans_commit normally decrements the vnode ref count - * when it unlocks the inode. Since we want to return the - * vnode to the caller, we bump the vnode ref count now. - */ - IHOLD(ip); - error = xfs_bmap_finish(&tp, &free_list, &committed); if (error) { goto error2; -- cgit From 20ad9ea9becd34a3c16252ca9d815f2c74f8f30f Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sun, 13 Feb 2011 12:06:34 +0000 Subject: xfs: enable delaylog by default Signed-off-by: Christoph Hellwig Signed-off-by: Dave Chinner Signed-off-by: Alex Elder --- fs/xfs/linux-2.6/xfs_super.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 9731898083ae..7ec1fb8c1316 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -189,6 +189,7 @@ xfs_parseargs( mp->m_flags |= XFS_MOUNT_BARRIER; mp->m_flags |= XFS_MOUNT_COMPAT_IOSIZE; mp->m_flags |= XFS_MOUNT_SMALL_INUMS; + mp->m_flags |= XFS_MOUNT_DELAYLOG; /* * These can be overridden by the mount option parsing. -- cgit From 0b75a840120b1e647e32342e9cc46631410088d5 Mon Sep 17 00:00:00 2001 From: Lukas Czerner Date: Wed, 23 Feb 2011 12:22:49 -0500 Subject: ext4: mark file-local functions and variables as static Signed-off-by: Lukas Czerner Signed-off-by: "Theodore Ts'o" --- fs/ext4/mballoc.c | 3 ++- fs/ext4/super.c | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index d1fe09aea73d..ae4d7f5edbbf 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -4753,7 +4753,8 @@ static int ext4_trim_extent(struct super_block *sb, int start, int count, * bitmap. Then issue a TRIM command on this extent and free the extent in * the group buddy bitmap. This is done until whole group is scanned. */ -ext4_grpblk_t ext4_trim_all_free(struct super_block *sb, struct ext4_buddy *e4b, +static ext4_grpblk_t +ext4_trim_all_free(struct super_block *sb, struct ext4_buddy *e4b, ext4_grpblk_t start, ext4_grpblk_t max, ext4_grpblk_t minblocks) { void *bitmap; diff --git a/fs/ext4/super.c b/fs/ext4/super.c index a1ac24b6a758..1539cf559784 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -54,9 +54,9 @@ static struct proc_dir_entry *ext4_proc_root; static struct kset *ext4_kset; -struct ext4_lazy_init *ext4_li_info; -struct mutex ext4_li_mtx; -struct ext4_features *ext4_feat; +static struct ext4_lazy_init *ext4_li_info; +static struct mutex ext4_li_mtx; +static struct ext4_features *ext4_feat; static int ext4_load_journal(struct super_block *, struct ext4_super_block *, unsigned long journal_devnum); -- cgit From 4143179218960a70d821a425e3c23ce44aa93dee Mon Sep 17 00:00:00 2001 From: Lukas Czerner Date: Wed, 23 Feb 2011 12:42:32 -0500 Subject: ext4: check if device support discard in FITRIM ioctl For a device that does not support discard, the FITRIM ioctl returns -EOPNOTSUPP when blkdev_issue_discard() returns this error code, which is how the user is informed that the device does not support discard. If there are no suitable free extents to be trimmed, then FITRIM will return success even though the device does not support discard, which could confuse the user. So check explicitly if the device supports discard and return an error code at the beginning of the FITRIM ioctl processing. Signed-off-by: Lukas Czerner Signed-off-by: "Theodore Ts'o" --- fs/ext4/ioctl.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'fs') diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index eb3bc2fe647e..25ba7c79d289 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -334,12 +334,16 @@ mext_out: case FITRIM: { struct super_block *sb = inode->i_sb; + struct request_queue *q = bdev_get_queue(sb->s_bdev); struct fstrim_range range; int ret = 0; if (!capable(CAP_SYS_ADMIN)) return -EPERM; + if (!blk_queue_discard(q)) + return -EOPNOTSUPP; + if (copy_from_user(&range, (struct fstrim_range *)arg, sizeof(range))) return -EFAULT; -- cgit From 5c2ed62fd447e2c696e222dcf71d1322bbbc58d4 Mon Sep 17 00:00:00 2001 From: Lukas Czerner Date: Wed, 23 Feb 2011 17:49:51 -0500 Subject: ext4: Adjust minlen with discard_granularity in the FITRIM ioctl Discard granularity tells us the minimum size of extent that can be discarded by the device. If the user supplies a minimum extent that should be discarded (range.minlen) which is smaller than the discard granularity, increase minlen to the discard granularity, since there's no point submitting trim requests that the device will reject anyway. Signed-off-by: Lukas Czerner Signed-off-by: "Theodore Ts'o" --- fs/ext4/ioctl.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'fs') diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index 25ba7c79d289..c052c9f0f3a1 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -348,6 +348,8 @@ mext_out: sizeof(range))) return -EFAULT; + range.minlen = max((unsigned int)range.minlen, + q->limits.discard_granularity); ret = ext4_trim_fs(sb, &range); if (ret < 0) return ret; -- cgit From ea6633369458992241599c9d9ebadffaeddec164 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Wed, 23 Feb 2011 17:51:51 -0500 Subject: ext4: enable acls and user_xattr by default There's no good reason to require the extra step of providing a mount option for acl or user_xattr once the feature is configured on; no other filesystem that I know of requires this. Userspace patches have set these options in default mount options, and this patch makes them default in the kernel. At some point we can start to deprecate the options, perhaps. For now I've removed default mount option checks in show_options() to be explicit about what's set, since it's changing the default, but I'm open to alternatives if desired. Signed-off-by: Eric Sandeen Signed-off-by: "Theodore Ts'o" --- fs/ext4/super.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'fs') diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 1539cf559784..a665d2fb70c1 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -997,13 +997,10 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) if (test_opt(sb, OLDALLOC)) seq_puts(seq, ",oldalloc"); #ifdef CONFIG_EXT4_FS_XATTR - if (test_opt(sb, XATTR_USER) && - !(def_mount_opts & EXT4_DEFM_XATTR_USER)) + if (test_opt(sb, XATTR_USER)) seq_puts(seq, ",user_xattr"); - if (!test_opt(sb, XATTR_USER) && - (def_mount_opts & EXT4_DEFM_XATTR_USER)) { + if (!test_opt(sb, XATTR_USER)) seq_puts(seq, ",nouser_xattr"); - } #endif #ifdef CONFIG_EXT4_FS_POSIX_ACL if (test_opt(sb, POSIX_ACL) && !(def_mount_opts & EXT4_DEFM_ACL)) @@ -3095,13 +3092,12 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) } if (def_mount_opts & EXT4_DEFM_UID16) set_opt(sb, NO_UID32); + /* xattr user namespace & acls are now defaulted on */ #ifdef CONFIG_EXT4_FS_XATTR - if (def_mount_opts & EXT4_DEFM_XATTR_USER) - set_opt(sb, XATTR_USER); + set_opt(sb, XATTR_USER); #endif #ifdef CONFIG_EXT4_FS_POSIX_ACL - if (def_mount_opts & EXT4_DEFM_ACL) - set_opt(sb, POSIX_ACL); + set_opt(sb, POSIX_ACL); #endif if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_DATA) set_opt(sb, JOURNAL_DATA); -- cgit From 84b775a354f640736176b5d966408fc5d5da6665 Mon Sep 17 00:00:00 2001 From: Coly Li Date: Thu, 24 Feb 2011 12:51:59 -0500 Subject: ext4: code cleanup in mb_find_buddy() Current code calculate max no matter whether order is zero, it's unnecessary. This cleanup patch sets max to "1 << (e4b->bd_blkbits + 3)" only when order == 0. Signed-off-by: Coly Li Cc: Alex Tomas Cc: Theodore Tso --- fs/ext4/mballoc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index ae4d7f5edbbf..1791dd4207d5 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -432,9 +432,10 @@ static void *mb_find_buddy(struct ext4_buddy *e4b, int order, int *max) } /* at order 0 we see each particular block */ - *max = 1 << (e4b->bd_blkbits + 3); - if (order == 0) + if (order == 0) { + *max = 1 << (e4b->bd_blkbits + 3); return EXT4_MB_BITMAP(e4b); + } bb = EXT4_MB_BUDDY(e4b) + EXT4_SB(e4b->bd_sb)->s_mb_offsets[order]; *max = EXT4_SB(e4b->bd_sb)->s_mb_maxs[order]; -- cgit From 235772da3e2adb1f4d71f27ec5475093dd38b2ac Mon Sep 17 00:00:00 2001 From: Coly Li Date: Thu, 24 Feb 2011 13:24:18 -0500 Subject: ext4: remove unncessary call mb_find_buddy() in debugging code In __mb_check_buddy(), look at the code below: 591 fstart = -1; 592 buddy = mb_find_buddy(e4b, 0, &max); 593 for (i = 0; i < max; i++) { 594 if (!mb_test_bit(i, buddy)) { 595 MB_CHECK_ASSERT(i >= e4b->bd_info->bb_first_free); 596 if (fstart == -1) { 597 fragments++; 598 fstart = i; 599 } 600 continue; 601 } 602 fstart = -1; 603 /* check used bits only */ 604 for (j = 0; j < e4b->bd_blkbits + 1; j++) { 605 buddy2 = mb_find_buddy(e4b, j, &max2); 606 k = i >> j; 607 MB_CHECK_ASSERT(k < max2); 608 MB_CHECK_ASSERT(mb_test_bit(k, buddy2)); 609 } 610 } 611 MB_CHECK_ASSERT(!EXT4_MB_GRP_NEED_INIT(e4b->bd_info)); 612 MB_CHECK_ASSERT(e4b->bd_info->bb_fragments == fragments); 613 614 grp = ext4_get_group_info(sb, e4b->bd_group); 615 buddy = mb_find_buddy(e4b, 0, &max); On line 592, buddy is fetched by mb_find_buddy() with order 0, between line 593 to line 615, buddy is not changed, therefore there is no need to fetch buddy again from mb_find_buddy() with order 0 again. We can safely remove the second mb_find_buddy() on line 615. Signed-off-by: Coly Li Cc: Alex Tomas Cc: Theodore Tso --- fs/ext4/mballoc.c | 1 - 1 file changed, 1 deletion(-) (limited to 'fs') diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 1791dd4207d5..7de0e2824436 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -617,7 +617,6 @@ static int __mb_check_buddy(struct ext4_buddy *e4b, char *file, MB_CHECK_ASSERT(e4b->bd_info->bb_fragments == fragments); grp = ext4_get_group_info(sb, e4b->bd_group); - buddy = mb_find_buddy(e4b, 0, &max); list_for_each(cur, &grp->bb_prealloc_list) { ext4_group_t groupnr; struct ext4_prealloc_space *pa; -- cgit From 7c786059293335412f99732c6f4c2a886eab25c2 Mon Sep 17 00:00:00 2001 From: Coly Li Date: Thu, 24 Feb 2011 13:24:25 -0500 Subject: mballoc: add comments to ext4_mb_mark_free_simple() This patch adds comments to ext4_mb_mark_free_simple to make it more understandable. Signed-off-by: Coly Li Cc: Alex Tomas Cc: Theodore Tso --- fs/ext4/mballoc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 7de0e2824436..b5235c8a2e78 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -635,7 +635,12 @@ static int __mb_check_buddy(struct ext4_buddy *e4b, char *file, #define mb_check_buddy(e4b) #endif -/* FIXME!! need more doc */ +/* + * Divide blocks started from @first with length @len into + * smaller chunks with power of 2 blocks. + * Clear the bits in bitmap which the blocks of the chunk(s) covered, + * then increase bb_counters[] for corresponded chunk size. + */ static void ext4_mb_mark_free_simple(struct super_block *sb, void *buddy, ext4_grpblk_t first, ext4_grpblk_t len, struct ext4_group_info *grp) -- cgit From 58696f3ab2b23fd6519189875fafdb5d1281eb54 Mon Sep 17 00:00:00 2001 From: Coly Li Date: Thu, 24 Feb 2011 14:10:00 -0500 Subject: ext4: clarify description of ac_g_ex in struct ext4_allocation_context Signed-off-by: Coly Li Cc: Alex Tomas Cc: Theodore Tso --- fs/ext4/mballoc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/ext4/mballoc.h b/fs/ext4/mballoc.h index b619322c76f0..22bd4d7f289b 100644 --- a/fs/ext4/mballoc.h +++ b/fs/ext4/mballoc.h @@ -169,7 +169,7 @@ struct ext4_allocation_context { /* original request */ struct ext4_free_extent ac_o_ex; - /* goal request (after normalization) */ + /* goal request (normalized ac_o_ex) */ struct ext4_free_extent ac_g_ex; /* the best found extent */ -- cgit From 5a54b2f199fdf19533f96c3e285b70c6729e1e4a Mon Sep 17 00:00:00 2001 From: Coly Li Date: Thu, 24 Feb 2011 14:10:05 -0500 Subject: ext4: mballoc: don't replace the current preallocation group unnecessarily In ext4_mb_check_group_pa(), the current preallocation space is replaced with a new preallocation space when the two have the same distance from the goal block. This doesn't actually gain us anything, so change things so that the function only switches to the new preallocation group if its distance from the goal block is strictly smaller than the current preallocaiton group's distance from the goal block. Signed-off-by: Coly Li Signed-off-by: "Theodore Ts'o" --- fs/ext4/mballoc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index b5235c8a2e78..66bee7274d6a 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -3213,7 +3213,7 @@ ext4_mb_check_group_pa(ext4_fsblk_t goal_block, cur_distance = abs(goal_block - cpa->pa_pstart); new_distance = abs(goal_block - pa->pa_pstart); - if (cur_distance < new_distance) + if (cur_distance <= new_distance) return cpa; /* drop the previous reference */ -- cgit From e0fd9b90765f604374c42de8ac59d6584afce264 Mon Sep 17 00:00:00 2001 From: Curt Wohlgemuth Date: Sat, 26 Feb 2011 12:25:52 -0500 Subject: ext4: mark multi-page IO complete on mapping failure In mpage_da_map_and_submit(), if we have a delayed block allocation failure from ext4_map_blocks(), we need to mark the IO as complete, by setting mpd->io_done = 1; Otherwise, we could end up submitting the pages in an outer loop; since they are unlocked on mapping failure in ext4_da_block_invalidatepages(), this will cause a bug check in mpage_da_submit_io(). I tested this by injected failures into ext4_map_blocks(). Without this patch, a simple fsstress run will bug check; with the patch, it works fine. Signed-off-by: Curt Wohlgemuth Signed-off-by: "Theodore Ts'o" --- fs/ext4/inode.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'fs') diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index c6c6b7fcb455..fd369dbce6af 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2314,6 +2314,9 @@ static void mpage_da_map_and_submit(struct mpage_da_data *mpd) /* invalidate all the pages */ ext4_da_block_invalidatepages(mpd, next, mpd->b_size >> mpd->inode->i_blkbits); + + /* Mark this page range as having been completed */ + mpd->io_done = 1; return; } BUG_ON(blks == 0); -- cgit From c7f5938adce6727b9d17785f289c1146bd88d678 Mon Sep 17 00:00:00 2001 From: Curt Wohlgemuth Date: Sat, 26 Feb 2011 12:27:52 -0500 Subject: ext4: fix ext4_da_block_invalidatepages() to handle page range properly If ext4_da_block_invalidatepages() is called because of a failure from ext4_map_blocks() in mpage_da_map_and_submit(), it's supposed to clean up -- including unlock -- all the pages in the mpd structure. But these values may not match up, even on a system in which block size == page size: mpd->b_blocknr != mpd->first_page mpd->b_size != (mpd->next_page - mpd->first_page) ext4_da_block_invalidatepages() has been using b_blocknr and b_size; this patch changes it to use first_page and next_page. Tested: I injected a small number (5%) of failures in ext4_map_blocks() in the case that the flags contain EXT4_GET_BLOCKS_DELALLOC_RESERVE, and ran fsstress on this kernel. Without this patch, I got hung tasks every time. With this patch, I see no hangs in many runs of fsstress. Signed-off-by: Curt Wohlgemuth Signed-off-by: "Theodore Ts'o" --- fs/ext4/inode.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'fs') diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index fd369dbce6af..e878c3a7aaf0 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2165,8 +2165,7 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd, return ret; } -static void ext4_da_block_invalidatepages(struct mpage_da_data *mpd, - sector_t logical, long blk_cnt) +static void ext4_da_block_invalidatepages(struct mpage_da_data *mpd) { int nr_pages, i; pgoff_t index, end; @@ -2174,9 +2173,8 @@ static void ext4_da_block_invalidatepages(struct mpage_da_data *mpd, struct inode *inode = mpd->inode; struct address_space *mapping = inode->i_mapping; - index = logical >> (PAGE_CACHE_SHIFT - inode->i_blkbits); - end = (logical + blk_cnt - 1) >> - (PAGE_CACHE_SHIFT - inode->i_blkbits); + index = mpd->first_page; + end = mpd->next_page - 1; while (index <= end) { nr_pages = pagevec_lookup(&pvec, mapping, index, PAGEVEC_SIZE); if (nr_pages == 0) @@ -2312,8 +2310,7 @@ static void mpage_da_map_and_submit(struct mpage_da_data *mpd) ext4_print_free_blocks(mpd->inode); } /* invalidate all the pages */ - ext4_da_block_invalidatepages(mpd, next, - mpd->b_size >> mpd->inode->i_blkbits); + ext4_da_block_invalidatepages(mpd); /* Mark this page range as having been completed */ mpd->io_done = 1; -- cgit From 6fd7a46781999c32f423025767e43b349b967d57 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 26 Feb 2011 13:53:09 -0500 Subject: ext4: enable mblk_io_submit by default Now that we've fixed the file corruption bug in commit d50bdd5aa55, it's time to enable mblk_io_submit by default. Signed-off-by: "Theodore Ts'o" --- fs/ext4/super.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/ext4/super.c b/fs/ext4/super.c index a665d2fb70c1..33c398785e53 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -1038,8 +1038,8 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) !(def_mount_opts & EXT4_DEFM_NODELALLOC)) seq_puts(seq, ",nodelalloc"); - if (test_opt(sb, MBLK_IO_SUBMIT)) - seq_puts(seq, ",mblk_io_submit"); + if (!test_opt(sb, MBLK_IO_SUBMIT)) + seq_puts(seq, ",nomblk_io_submit"); if (sbi->s_stripe) seq_printf(seq, ",stripe=%lu", sbi->s_stripe); /* @@ -3099,6 +3099,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) #ifdef CONFIG_EXT4_FS_POSIX_ACL set_opt(sb, POSIX_ACL); #endif + set_opt(sb, MBLK_IO_SUBMIT); if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_DATA) set_opt(sb, JOURNAL_DATA); else if ((def_mount_opts & EXT4_DEFM_JMODE) == EXT4_DEFM_JMODE_ORDERED) -- cgit From 8eb9e5ce211de1b98bc84e93258b7db0860a103c Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 26 Feb 2011 14:07:31 -0500 Subject: ext4: fold __mpage_da_writepage() into write_cache_pages_da() Fold the __mpage_da_writepage() function into write_cache_pages_da(). This will give us opportunities to clean up and simplify the resulting code. Signed-off-by: "Theodore Ts'o" --- fs/ext4/inode.c | 206 +++++++++++++++++++++++++------------------------------- 1 file changed, 91 insertions(+), 115 deletions(-) (limited to 'fs') diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index e878c3a7aaf0..fcd08ca0643b 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2437,102 +2437,6 @@ static int ext4_bh_delay_or_unwritten(handle_t *handle, struct buffer_head *bh) return (buffer_delay(bh) || buffer_unwritten(bh)) && buffer_dirty(bh); } -/* - * __mpage_da_writepage - finds extent of pages and blocks - * - * @page: page to consider - * @wbc: not used, we just follow rules - * @data: context - * - * The function finds extents of pages and scan them for all blocks. - */ -static int __mpage_da_writepage(struct page *page, - struct writeback_control *wbc, - struct mpage_da_data *mpd) -{ - struct inode *inode = mpd->inode; - struct buffer_head *bh, *head; - sector_t logical; - - /* - * Can we merge this page to current extent? - */ - if (mpd->next_page != page->index) { - /* - * Nope, we can't. So, we map non-allocated blocks - * and start IO on them - */ - if (mpd->next_page != mpd->first_page) { - mpage_da_map_and_submit(mpd); - /* - * skip rest of the page in the page_vec - */ - redirty_page_for_writepage(wbc, page); - unlock_page(page); - return MPAGE_DA_EXTENT_TAIL; - } - - /* - * Start next extent of pages ... - */ - mpd->first_page = page->index; - - /* - * ... and blocks - */ - mpd->b_size = 0; - mpd->b_state = 0; - mpd->b_blocknr = 0; - } - - mpd->next_page = page->index + 1; - logical = (sector_t) page->index << - (PAGE_CACHE_SHIFT - inode->i_blkbits); - - if (!page_has_buffers(page)) { - mpage_add_bh_to_extent(mpd, logical, PAGE_CACHE_SIZE, - (1 << BH_Dirty) | (1 << BH_Uptodate)); - if (mpd->io_done) - return MPAGE_DA_EXTENT_TAIL; - } else { - /* - * Page with regular buffer heads, just add all dirty ones - */ - head = page_buffers(page); - bh = head; - do { - BUG_ON(buffer_locked(bh)); - /* - * We need to try to allocate - * unmapped blocks in the same page. - * Otherwise we won't make progress - * with the page in ext4_writepage - */ - if (ext4_bh_delay_or_unwritten(NULL, bh)) { - mpage_add_bh_to_extent(mpd, logical, - bh->b_size, - bh->b_state); - if (mpd->io_done) - return MPAGE_DA_EXTENT_TAIL; - } else if (buffer_dirty(bh) && (buffer_mapped(bh))) { - /* - * mapped dirty buffer. We need to update - * the b_state because we look at - * b_state in mpage_da_map_blocks. We don't - * update b_size because if we find an - * unmapped buffer_head later we need to - * use the b_state flag of that buffer_head. - */ - if (mpd->b_size == 0) - mpd->b_state = bh->b_state & BH_FLAGS; - } - logical++; - } while ((bh = bh->b_this_page) != head); - } - - return 0; -} - /* * This is a special get_blocks_t callback which is used by * ext4_da_write_begin(). It will either return mapped block or @@ -2811,18 +2715,17 @@ static int ext4_da_writepages_trans_blocks(struct inode *inode) /* * write_cache_pages_da - walk the list of dirty pages of the given - * address space and call the callback function (which usually writes - * the pages). - * - * This is a forked version of write_cache_pages(). Differences: - * Range cyclic is ignored. - * no_nrwrite_index_update is always presumed true + * address space and accumulate pages that need writing, and call + * mpage_da_map_and_submit to map the pages and then write them. */ static int write_cache_pages_da(struct address_space *mapping, struct writeback_control *wbc, struct mpage_da_data *mpd, pgoff_t *done_index) { + struct inode *inode = mpd->inode; + struct buffer_head *bh, *head; + sector_t logical; int ret = 0; int done = 0; struct pagevec pvec; @@ -2899,17 +2802,90 @@ continue_unlock: if (!clear_page_dirty_for_io(page)) goto continue_unlock; - ret = __mpage_da_writepage(page, wbc, mpd); - if (unlikely(ret)) { - if (ret == AOP_WRITEPAGE_ACTIVATE) { + /* BEGIN __mpage_da_writepage */ + + /* + * Can we merge this page to current extent? + */ + if (mpd->next_page != page->index) { + /* + * Nope, we can't. So, we map + * non-allocated blocks and start IO + * on them + */ + if (mpd->next_page != mpd->first_page) { + mpage_da_map_and_submit(mpd); + /* + * skip rest of the page in the page_vec + */ + redirty_page_for_writepage(wbc, page); unlock_page(page); - ret = 0; - } else { - done = 1; - break; + ret = MPAGE_DA_EXTENT_TAIL; + goto out; } + + /* + * Start next extent of pages and blocks + */ + mpd->first_page = page->index; + mpd->b_size = 0; + mpd->b_state = 0; + mpd->b_blocknr = 0; + } + + mpd->next_page = page->index + 1; + logical = (sector_t) page->index << + (PAGE_CACHE_SHIFT - inode->i_blkbits); + + if (!page_has_buffers(page)) { + mpage_add_bh_to_extent(mpd, logical, PAGE_CACHE_SIZE, + (1 << BH_Dirty) | (1 << BH_Uptodate)); + if (mpd->io_done) { + ret = MPAGE_DA_EXTENT_TAIL; + goto out; + } + } else { + /* + * Page with regular buffer heads, just add all dirty ones + */ + head = page_buffers(page); + bh = head; + do { + BUG_ON(buffer_locked(bh)); + /* + * We need to try to allocate + * unmapped blocks in the same page. + * Otherwise we won't make progress + * with the page in ext4_writepage + */ + if (ext4_bh_delay_or_unwritten(NULL, bh)) { + mpage_add_bh_to_extent(mpd, logical, + bh->b_size, + bh->b_state); + if (mpd->io_done) { + ret = MPAGE_DA_EXTENT_TAIL; + goto out; + } + } else if (buffer_dirty(bh) && (buffer_mapped(bh))) { + /* + * mapped dirty buffer. We need to update + * the b_state because we look at + * b_state in mpage_da_map_blocks. We don't + * update b_size because if we find an + * unmapped buffer_head later we need to + * use the b_state flag of that buffer_head. + */ + if (mpd->b_size == 0) + mpd->b_state = bh->b_state & BH_FLAGS; + } + logical++; + } while ((bh = bh->b_this_page) != head); } + ret = 0; + + /* END __mpage_da_writepage */ + if (nr_to_write > 0) { nr_to_write--; if (nr_to_write == 0 && @@ -2933,6 +2909,10 @@ continue_unlock: cond_resched(); } return ret; +out: + pagevec_release(&pvec); + cond_resched(); + return ret; } @@ -3059,13 +3039,9 @@ retry: } /* - * Now call __mpage_da_writepage to find the next + * Now call write_cache_pages_da() to find the next * contiguous region of logical blocks that need - * blocks to be allocated by ext4. We don't actually - * submit the blocks for I/O here, even though - * write_cache_pages thinks it will, and will set the - * pages as clean for write before calling - * __mpage_da_writepage(). + * blocks to be allocated by ext4 and submit them. */ mpd.b_size = 0; mpd.b_state = 0; -- cgit From 4f01b02c8c4e4111bd1adbcafb5741e8e991f5fd Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 26 Feb 2011 14:07:37 -0500 Subject: ext4: simple cleanups to write_cache_pages_da() Eliminate duplicate code, unneeded variables, etc., to make it easier to understand the code. No behavioral changes were made in this patch. Signed-off-by: "Theodore Ts'o" --- fs/ext4/inode.c | 115 +++++++++++++++++++++++--------------------------------- 1 file changed, 48 insertions(+), 67 deletions(-) (limited to 'fs') diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index fcd08ca0643b..1e718e87f466 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2723,17 +2723,14 @@ static int write_cache_pages_da(struct address_space *mapping, struct mpage_da_data *mpd, pgoff_t *done_index) { - struct inode *inode = mpd->inode; - struct buffer_head *bh, *head; - sector_t logical; - int ret = 0; - int done = 0; - struct pagevec pvec; - unsigned nr_pages; - pgoff_t index; - pgoff_t end; /* Inclusive */ - long nr_to_write = wbc->nr_to_write; - int tag; + struct buffer_head *bh, *head; + struct inode *inode = mpd->inode; + struct pagevec pvec; + unsigned int nr_pages; + sector_t logical; + pgoff_t index, end; + long nr_to_write = wbc->nr_to_write; + int i, tag, ret = 0; pagevec_init(&pvec, 0); index = wbc->range_start >> PAGE_CACHE_SHIFT; @@ -2745,13 +2742,11 @@ static int write_cache_pages_da(struct address_space *mapping, tag = PAGECACHE_TAG_DIRTY; *done_index = index; - while (!done && (index <= end)) { - int i; - + while (index <= end) { nr_pages = pagevec_lookup_tag(&pvec, mapping, &index, tag, min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1); if (nr_pages == 0) - break; + return 0; for (i = 0; i < nr_pages; i++) { struct page *page = pvec.pages[i]; @@ -2763,47 +2758,37 @@ static int write_cache_pages_da(struct address_space *mapping, * mapping. However, page->index will not change * because we have a reference on the page. */ - if (page->index > end) { - done = 1; - break; - } + if (page->index > end) + goto out; *done_index = page->index + 1; lock_page(page); /* - * Page truncated or invalidated. We can freely skip it - * then, even for data integrity operations: the page - * has disappeared concurrently, so there could be no - * real expectation of this data interity operation - * even if there is now a new, dirty page at the same - * pagecache address. + * If the page is no longer dirty, or its + * mapping no longer corresponds to inode we + * are writing (which means it has been + * truncated or invalidated), or the page is + * already under writeback and we are not + * doing a data integrity writeback, skip the page */ - if (unlikely(page->mapping != mapping)) { -continue_unlock: + if (!PageDirty(page) || + (PageWriteback(page) && + (wbc->sync_mode == WB_SYNC_NONE)) || + unlikely(page->mapping != mapping)) { + continue_unlock: unlock_page(page); continue; } - if (!PageDirty(page)) { - /* someone wrote it for us */ - goto continue_unlock; - } - - if (PageWriteback(page)) { - if (wbc->sync_mode != WB_SYNC_NONE) - wait_on_page_writeback(page); - else - goto continue_unlock; - } + if (PageWriteback(page)) + wait_on_page_writeback(page); BUG_ON(PageWriteback(page)); if (!clear_page_dirty_for_io(page)) goto continue_unlock; - /* BEGIN __mpage_da_writepage */ - /* * Can we merge this page to current extent? */ @@ -2820,8 +2805,7 @@ continue_unlock: */ redirty_page_for_writepage(wbc, page); unlock_page(page); - ret = MPAGE_DA_EXTENT_TAIL; - goto out; + goto ret_extent_tail; } /* @@ -2838,15 +2822,15 @@ continue_unlock: (PAGE_CACHE_SHIFT - inode->i_blkbits); if (!page_has_buffers(page)) { - mpage_add_bh_to_extent(mpd, logical, PAGE_CACHE_SIZE, + mpage_add_bh_to_extent(mpd, logical, + PAGE_CACHE_SIZE, (1 << BH_Dirty) | (1 << BH_Uptodate)); - if (mpd->io_done) { - ret = MPAGE_DA_EXTENT_TAIL; - goto out; - } + if (mpd->io_done) + goto ret_extent_tail; } else { /* - * Page with regular buffer heads, just add all dirty ones + * Page with regular buffer heads, + * just add all dirty ones */ head = page_buffers(page); bh = head; @@ -2862,18 +2846,19 @@ continue_unlock: mpage_add_bh_to_extent(mpd, logical, bh->b_size, bh->b_state); - if (mpd->io_done) { - ret = MPAGE_DA_EXTENT_TAIL; - goto out; - } + if (mpd->io_done) + goto ret_extent_tail; } else if (buffer_dirty(bh) && (buffer_mapped(bh))) { /* - * mapped dirty buffer. We need to update - * the b_state because we look at - * b_state in mpage_da_map_blocks. We don't - * update b_size because if we find an - * unmapped buffer_head later we need to - * use the b_state flag of that buffer_head. + * mapped dirty buffer. We need + * to update the b_state + * because we look at b_state + * in mpage_da_map_blocks. We + * don't update b_size because + * if we find an unmapped + * buffer_head later we need to + * use the b_state flag of that + * buffer_head. */ if (mpd->b_size == 0) mpd->b_state = bh->b_state & BH_FLAGS; @@ -2882,14 +2867,10 @@ continue_unlock: } while ((bh = bh->b_this_page) != head); } - ret = 0; - - /* END __mpage_da_writepage */ - if (nr_to_write > 0) { nr_to_write--; if (nr_to_write == 0 && - wbc->sync_mode == WB_SYNC_NONE) { + wbc->sync_mode == WB_SYNC_NONE) /* * We stop writing back only if we are * not doing integrity sync. In case of @@ -2900,15 +2881,15 @@ continue_unlock: * pages, but have not synced all of the * old dirty pages. */ - done = 1; - break; - } + goto out; } } pagevec_release(&pvec); cond_resched(); } - return ret; + return 0; +ret_extent_tail: + ret = MPAGE_DA_EXTENT_TAIL; out: pagevec_release(&pvec); cond_resched(); -- cgit From 9749895644a817cfd28a535bc3ae60e4267bdc50 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 26 Feb 2011 14:08:01 -0500 Subject: ext4: clear the dirty bit for a page in writeback at the last minute Move when we call clear_page_dirty_for_io() to just before we actually write the page. This simplifies the code somewhat, and avoids marking pages as clean and then needing to remark them as dirty later. Signed-off-by: "Theodore Ts'o" --- fs/ext4/inode.c | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) (limited to 'fs') diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 1e718e87f466..ae6e2f43d873 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2060,7 +2060,7 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd, if (nr_pages == 0) break; for (i = 0; i < nr_pages; i++) { - int commit_write = 0, redirty_page = 0; + int commit_write = 0, skip_page = 0; struct page *page = pvec.pages[i]; index = page->index; @@ -2086,14 +2086,12 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd, * If the page does not have buffers (for * whatever reason), try to create them using * __block_write_begin. If this fails, - * redirty the page and move on. + * skip the page and move on. */ if (!page_has_buffers(page)) { if (__block_write_begin(page, 0, len, noalloc_get_block_write)) { - redirty_page: - redirty_page_for_writepage(mpd->wbc, - page); + skip_page: unlock_page(page); continue; } @@ -2104,7 +2102,7 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd, block_start = 0; do { if (!bh) - goto redirty_page; + goto skip_page; if (map && (cur_logical >= map->m_lblk) && (cur_logical <= (map->m_lblk + (map->m_len - 1)))) { @@ -2120,22 +2118,23 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd, clear_buffer_unwritten(bh); } - /* redirty page if block allocation undone */ + /* skip page if block allocation undone */ if (buffer_delay(bh) || buffer_unwritten(bh)) - redirty_page = 1; + skip_page = 1; bh = bh->b_this_page; block_start += bh->b_size; cur_logical++; pblock++; } while (bh != page_bufs); - if (redirty_page) - goto redirty_page; + if (skip_page) + goto skip_page; if (commit_write) /* mark the buffer_heads as dirty & uptodate */ block_commit_write(page, 0, len); + clear_page_dirty_for_io(page); /* * Delalloc doesn't support data journalling, * but eventually maybe we'll lift this @@ -2277,9 +2276,8 @@ static void mpage_da_map_and_submit(struct mpage_da_data *mpd) err = blks; /* * If get block returns EAGAIN or ENOSPC and there - * appears to be free blocks we will call - * ext4_writepage() for all of the pages which will - * just redirty the pages. + * appears to be free blocks we will just let + * mpage_da_submit_io() unlock all of the pages. */ if (err == -EAGAIN) goto submit_io; @@ -2777,7 +2775,6 @@ static int write_cache_pages_da(struct address_space *mapping, (PageWriteback(page) && (wbc->sync_mode == WB_SYNC_NONE)) || unlikely(page->mapping != mapping)) { - continue_unlock: unlock_page(page); continue; } @@ -2786,8 +2783,6 @@ static int write_cache_pages_da(struct address_space *mapping, wait_on_page_writeback(page); BUG_ON(PageWriteback(page)); - if (!clear_page_dirty_for_io(page)) - goto continue_unlock; /* * Can we merge this page to current extent? @@ -2803,7 +2798,6 @@ static int write_cache_pages_da(struct address_space *mapping, /* * skip rest of the page in the page_vec */ - redirty_page_for_writepage(wbc, page); unlock_page(page); goto ret_extent_tail; } -- cgit From ee6ecbcc5d73672217fdea420d182ecb0cdf310c Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 26 Feb 2011 14:08:11 -0500 Subject: ext4: remove page_skipped hackery in ext4_da_writepages() Because the ext4 page writeback codepath had been prematurely calling clear_page_dirty_for_io(), if it turned out that a particular page couldn't be written out during a particular pass of write_cache_pages_da(), the page would have to get redirtied by calling redirty_pages_for_writeback(). Not only was this wasted work, but redirty_page_for_writeback() would increment wbc->pages_skipped to signal to writeback_sb_inodes() that buffers were locked, and that it should skip this inode until later. Since this signal was incorrect in ext4's case --- which was caused by ext4's historically incorrect use of write_cache_pages() --- ext4_da_writepages() saved and restored wbc->skipped_pages to avoid confusing writeback_sb_inodes(). Now that we've fixed ext4 to call clear_page_dirty_for_io() right before initiating the page I/O, we can nuke the page_skipped save/restore hackery, and breathe a sigh of relief. Signed-off-by: "Theodore Ts'o" --- fs/ext4/inode.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'fs') diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index ae6e2f43d873..617c9cbba182 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2900,7 +2900,6 @@ static int ext4_da_writepages(struct address_space *mapping, struct mpage_da_data mpd; struct inode *inode = mapping->host; int pages_written = 0; - long pages_skipped; unsigned int max_pages; int range_cyclic, cycled = 1, io_done = 0; int needed_blocks, ret = 0; @@ -2986,8 +2985,6 @@ static int ext4_da_writepages(struct address_space *mapping, mpd.wbc = wbc; mpd.inode = mapping->host; - pages_skipped = wbc->pages_skipped; - retry: if (wbc->sync_mode == WB_SYNC_ALL) tag_pages_for_writeback(mapping, index, end); @@ -3047,7 +3044,6 @@ retry: * and try again */ jbd2_journal_force_commit_nested(sbi->s_journal); - wbc->pages_skipped = pages_skipped; ret = 0; } else if (ret == MPAGE_DA_EXTENT_TAIL) { /* @@ -3055,7 +3051,6 @@ retry: * rest of the pages */ pages_written += mpd.pages_written; - wbc->pages_skipped = pages_skipped; ret = 0; io_done = 1; } else if (wbc->nr_to_write) @@ -3073,11 +3068,6 @@ retry: wbc->range_end = mapping->writeback_index - 1; goto retry; } - if (pages_skipped != wbc->pages_skipped) - ext4_msg(inode->i_sb, KERN_CRIT, - "This should not happen leaving %s " - "with nr_to_write = %ld ret = %d", - __func__, wbc->nr_to_write, ret); /* Update index */ wbc->range_cyclic = range_cyclic; -- cgit From 78aaced3408141bb7c836f2db0ca435790399da5 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 26 Feb 2011 14:09:14 -0500 Subject: ext4: don't lock the next page in write_cache_pages if not needed If we have accumulated a contiguous region of memory to be written out, and the next page can added to this region, don't bother locking (and then unlocking the page) before writing out the memory. In the unlikely event that the next page was being written back by some other CPU, we can also skip waiting that page to finish writeback. Signed-off-by: "Theodore Ts'o" --- fs/ext4/inode.c | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) (limited to 'fs') diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 617c9cbba182..c2e6af338234 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2761,6 +2761,16 @@ static int write_cache_pages_da(struct address_space *mapping, *done_index = page->index + 1; + /* + * If we can't merge this page, and we have + * accumulated an contiguous region, write it + */ + if ((mpd->next_page != page->index) && + (mpd->next_page != mpd->first_page)) { + mpage_da_map_and_submit(mpd); + goto ret_extent_tail; + } + lock_page(page); /* @@ -2784,24 +2794,7 @@ static int write_cache_pages_da(struct address_space *mapping, BUG_ON(PageWriteback(page)); - /* - * Can we merge this page to current extent? - */ if (mpd->next_page != page->index) { - /* - * Nope, we can't. So, we map - * non-allocated blocks and start IO - * on them - */ - if (mpd->next_page != mpd->first_page) { - mpage_da_map_and_submit(mpd); - /* - * skip rest of the page in the page_vec - */ - unlock_page(page); - goto ret_extent_tail; - } - /* * Start next extent of pages and blocks */ -- cgit From 168fc0223c0e944957b1f31d88c2334fc904baf1 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 26 Feb 2011 14:09:20 -0500 Subject: ext4: move setup of the mpd structure to write_cache_pages_da() Move the initialization of all of the fields of the mpd structure to write_cache_pages_da(). This simplifies the code considerably. Signed-off-by: "Theodore Ts'o" --- fs/ext4/inode.c | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-) (limited to 'fs') diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index c2e6af338234..dcc2287433b6 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2714,7 +2714,8 @@ static int ext4_da_writepages_trans_blocks(struct inode *inode) /* * write_cache_pages_da - walk the list of dirty pages of the given * address space and accumulate pages that need writing, and call - * mpage_da_map_and_submit to map the pages and then write them. + * mpage_da_map_and_submit to map a single contiguous memory region + * and then write them. */ static int write_cache_pages_da(struct address_space *mapping, struct writeback_control *wbc, @@ -2722,7 +2723,7 @@ static int write_cache_pages_da(struct address_space *mapping, pgoff_t *done_index) { struct buffer_head *bh, *head; - struct inode *inode = mpd->inode; + struct inode *inode = mapping->host; struct pagevec pvec; unsigned int nr_pages; sector_t logical; @@ -2730,6 +2731,9 @@ static int write_cache_pages_da(struct address_space *mapping, long nr_to_write = wbc->nr_to_write; int i, tag, ret = 0; + memset(mpd, 0, sizeof(struct mpage_da_data)); + mpd->wbc = wbc; + mpd->inode = inode; pagevec_init(&pvec, 0); index = wbc->range_start >> PAGE_CACHE_SHIFT; end = wbc->range_end >> PAGE_CACHE_SHIFT; @@ -2794,16 +2798,8 @@ static int write_cache_pages_da(struct address_space *mapping, BUG_ON(PageWriteback(page)); - if (mpd->next_page != page->index) { - /* - * Start next extent of pages and blocks - */ + if (mpd->next_page != page->index) mpd->first_page = page->index; - mpd->b_size = 0; - mpd->b_state = 0; - mpd->b_blocknr = 0; - } - mpd->next_page = page->index + 1; logical = (sector_t) page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits); @@ -2975,9 +2971,6 @@ static int ext4_da_writepages(struct address_space *mapping, wbc->nr_to_write = desired_nr_to_write; } - mpd.wbc = wbc; - mpd.inode = mapping->host; - retry: if (wbc->sync_mode == WB_SYNC_ALL) tag_pages_for_writeback(mapping, index, end); @@ -3008,14 +3001,6 @@ retry: * contiguous region of logical blocks that need * blocks to be allocated by ext4 and submit them. */ - mpd.b_size = 0; - mpd.b_state = 0; - mpd.b_blocknr = 0; - mpd.first_page = 0; - mpd.next_page = 0; - mpd.io_done = 0; - mpd.pages_written = 0; - mpd.retval = 0; ret = write_cache_pages_da(mapping, wbc, &mpd, &done_index); /* * If we have a contiguous extent of pages and we -- cgit From a54aa76108619e5d8290b49081c2aaaeff5be9a2 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sun, 27 Feb 2011 16:43:24 -0500 Subject: ext4: don't leave PageWriteback set after memory failure In ext4_bio_write_page(), if the memory allocation for the struct ext4_io_page fails, it returns with the page's PageWriteback flag set. This will end up causing the page not to skip writeback in WB_SYNC_NONE mode, and in WB_SYNC_ALL mode (i.e., on a sync, fsync, or umount) the writeback daemon will get stuck forever on the wait_on_page_writeback() function in write_cache_pages_da(). Or, if journalling is enabled and the file gets deleted, it the journal thread can get stuck in journal_finish_inode_data_buffers() call to filemap_fdatawait(). Another place where things can get hung up is in truncate_inode_pages(), called out of ext4_evict_inode(). Fix this by not setting PageWriteback until after we have successfully allocated the struct ext4_io_page. Signed-off-by: "Theodore Ts'o" --- fs/ext4/page-io.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index 68d92a8f71d7..d5c391ffad7a 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c @@ -381,8 +381,6 @@ int ext4_bio_write_page(struct ext4_io_submit *io, BUG_ON(!PageLocked(page)); BUG_ON(PageWriteback(page)); - set_page_writeback(page); - ClearPageError(page); io_page = kmem_cache_alloc(io_page_cachep, GFP_NOFS); if (!io_page) { @@ -393,6 +391,8 @@ int ext4_bio_write_page(struct ext4_io_submit *io, io_page->p_page = page; atomic_set(&io_page->p_count, 1); get_page(page); + set_page_writeback(page); + ClearPageError(page); for (bh = head = page_buffers(page), block_start = 0; bh != head || !block_start; -- cgit From 4dd89fc6251a6bda2c18e71e7d266e983806579d Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sun, 27 Feb 2011 17:23:47 -0500 Subject: ext4: suppress verbose debugging information if malloc-debug is off If CONFIG_EXT4_DEBUG is enabled, then if a block allocation fails due to disk being full, a verbose debugging message is printed, even if the malloc-debug switch has not been enabled. Suppress the debugging message so that nothing is printed unless malloc-debug has been turned on. Signed-off-by: "Theodore Ts'o" --- fs/ext4/mballoc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 66bee7274d6a..2f6f0dd08fca 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -3912,7 +3912,8 @@ static void ext4_mb_show_ac(struct ext4_allocation_context *ac) struct super_block *sb = ac->ac_sb; ext4_group_t ngroups, i; - if (EXT4_SB(sb)->s_mount_flags & EXT4_MF_FS_ABORTED) + if (!mb_enable_debug || + (EXT4_SB(sb)->s_mount_flags & EXT4_MF_FS_ABORTED)) return; printk(KERN_ERR "EXT4-fs: Can't allocate:" -- cgit From 6d9c85eb700bd3ac59e63bb9de463dea1aca084c Mon Sep 17 00:00:00 2001 From: Yongqiang Yang Date: Sun, 27 Feb 2011 17:25:47 -0500 Subject: ext4: make FIEMAP and delayed allocation play well together Fix the FIEMAP ioctl so that it returns all of the page ranges which are still subject to delayed allocation. We were missing some cases if the file was sparse. Reported by Chris Mason : >We've had reports on btrfs that cp is giving us files full of zeros >instead of actually copying them. It was tracked down to a bug with >the btrfs fiemap implementation where it was returning holes for >delalloc ranges. > >Newer versions of cp are trusting fiemap to tell it where the holes >are, which does seem like a pretty neat trick. > >I decided to give xfs and ext4 a shot with a few tests cases too, xfs >passed with all the ones btrfs was getting wrong, and ext4 got the basic >delalloc case right. >$ mkfs.ext4 /dev/xxx >$ mount /dev/xxx /mnt >$ dd if=/dev/zero of=/mnt/foo bs=1M count=1 >$ fiemap-test foo >ext: 0 logical: [ 0.. 255] phys: 0.. 255 >flags: 0x007 tot: 256 > >Horray! But once we throw a hole in, things go bad: >$ mkfs.ext4 /dev/xxx >$ mount /dev/xxx /mnt >$ dd if=/dev/zero of=/mnt/foo bs=1M count=1 seek=1 >$ fiemap-test foo >< no output > > >We've got a delalloc extent after the hole and ext4 fiemap didn't find >it. If I run sync to kick the delalloc out: >$sync >$ fiemap-test foo >ext: 0 logical: [ 256.. 511] phys: 34048.. 34303 >flags: 0x001 tot: 256 > >fiemap-test is sitting in my /usr/local/bin, and I have no idea how it >got there. It's full of pretty comments so I know it isn't mine, but >you can grab it here: > >http://oss.oracle.com/~mason/fiemap-test.c > >xfsqa has a fiemap program too. After Fix, test results are as follows: ext: 0 logical: [ 256.. 511] phys: 0.. 255 flags: 0x007 tot: 256 ext: 0 logical: [ 256.. 511] phys: 33280.. 33535 flags: 0x001 tot: 256 $ mkfs.ext4 /dev/xxx $ mount /dev/xxx /mnt $ dd if=/dev/zero of=/mnt/foo bs=1M count=1 seek=1 $ sync $ dd if=/dev/zero of=/mnt/foo bs=1M count=1 seek=3 $ dd if=/dev/zero of=/mnt/foo bs=1M count=1 seek=5 $ fiemap-test foo ext: 0 logical: [ 256.. 511] phys: 33280.. 33535 flags: 0x000 tot: 256 ext: 1 logical: [ 768.. 1023] phys: 0.. 255 flags: 0x006 tot: 256 ext: 2 logical: [ 1280.. 1535] phys: 0.. 255 flags: 0x007 tot: 256 Tested-by: Eric Sandeen Reviewed-by: Andreas Dilger Signed-off-by: Yongqiang Yang Signed-off-by: "Theodore Ts'o" --- fs/ext4/extents.c | 187 ++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 148 insertions(+), 39 deletions(-) (limited to 'fs') diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index d16f6b5a140b..9ea1bc64ca6d 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -3775,6 +3775,7 @@ int ext4_convert_unwritten_extents(struct inode *inode, loff_t offset, } return ret > 0 ? ret2 : ret; } + /* * Callback function called for each extent to gather FIEMAP information. */ @@ -3782,38 +3783,162 @@ static int ext4_ext_fiemap_cb(struct inode *inode, struct ext4_ext_path *path, struct ext4_ext_cache *newex, struct ext4_extent *ex, void *data) { - struct fiemap_extent_info *fieinfo = data; - unsigned char blksize_bits = inode->i_sb->s_blocksize_bits; __u64 logical; __u64 physical; __u64 length; + loff_t size; __u32 flags = 0; - int error; + int ret = 0; + struct fiemap_extent_info *fieinfo = data; + unsigned char blksize_bits; - logical = (__u64)newex->ec_block << blksize_bits; + blksize_bits = inode->i_sb->s_blocksize_bits; + logical = (__u64)newex->ec_block << blksize_bits; if (newex->ec_start == 0) { - pgoff_t offset; - struct page *page; + /* + * No extent in extent-tree contains block @newex->ec_start, + * then the block may stay in 1)a hole or 2)delayed-extent. + * + * Holes or delayed-extents are processed as follows. + * 1. lookup dirty pages with specified range in pagecache. + * If no page is got, then there is no delayed-extent and + * return with EXT_CONTINUE. + * 2. find the 1st mapped buffer, + * 3. check if the mapped buffer is both in the request range + * and a delayed buffer. If not, there is no delayed-extent, + * then return. + * 4. a delayed-extent is found, the extent will be collected. + */ + ext4_lblk_t end = 0; + pgoff_t last_offset; + pgoff_t offset; + pgoff_t index; + struct page **pages = NULL; struct buffer_head *bh = NULL; + struct buffer_head *head = NULL; + unsigned int nr_pages = PAGE_SIZE / sizeof(struct page *); + + pages = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (pages == NULL) + return -ENOMEM; offset = logical >> PAGE_SHIFT; - page = find_get_page(inode->i_mapping, offset); - if (!page || !page_has_buffers(page)) - return EXT_CONTINUE; +repeat: + last_offset = offset; + head = NULL; + ret = find_get_pages_tag(inode->i_mapping, &offset, + PAGECACHE_TAG_DIRTY, nr_pages, pages); + + if (!(flags & FIEMAP_EXTENT_DELALLOC)) { + /* First time, try to find a mapped buffer. */ + if (ret == 0) { +out: + for (index = 0; index < ret; index++) + page_cache_release(pages[index]); + /* just a hole. */ + kfree(pages); + return EXT_CONTINUE; + } - bh = page_buffers(page); + /* Try to find the 1st mapped buffer. */ + end = ((__u64)pages[0]->index << PAGE_SHIFT) >> + blksize_bits; + if (!page_has_buffers(pages[0])) + goto out; + head = page_buffers(pages[0]); + if (!head) + goto out; - if (!bh) - return EXT_CONTINUE; + bh = head; + do { + if (buffer_mapped(bh)) { + /* get the 1st mapped buffer. */ + if (end > newex->ec_block + + newex->ec_len) + /* The buffer is out of + * the request range. + */ + goto out; + goto found_mapped_buffer; + } + bh = bh->b_this_page; + end++; + } while (bh != head); - if (buffer_delay(bh)) { - flags |= FIEMAP_EXTENT_DELALLOC; - page_cache_release(page); + /* No mapped buffer found. */ + goto out; } else { - page_cache_release(page); - return EXT_CONTINUE; + /*Find contiguous delayed buffers. */ + if (ret > 0 && pages[0]->index == last_offset) + head = page_buffers(pages[0]); + bh = head; + } + +found_mapped_buffer: + if (bh != NULL && buffer_delay(bh)) { + /* 1st or contiguous delayed buffer found. */ + if (!(flags & FIEMAP_EXTENT_DELALLOC)) { + /* + * 1st delayed buffer found, record + * the start of extent. + */ + flags |= FIEMAP_EXTENT_DELALLOC; + newex->ec_block = end; + logical = (__u64)end << blksize_bits; + } + /* Find contiguous delayed buffers. */ + do { + if (!buffer_delay(bh)) + goto found_delayed_extent; + bh = bh->b_this_page; + end++; + } while (bh != head); + + for (index = 1; index < ret; index++) { + if (!page_has_buffers(pages[index])) { + bh = NULL; + break; + } + head = page_buffers(pages[index]); + if (!head) { + bh = NULL; + break; + } + if (pages[index]->index != + pages[0]->index + index) { + /* Blocks are not contiguous. */ + bh = NULL; + break; + } + bh = head; + do { + if (!buffer_delay(bh)) + /* Delayed-extent ends. */ + goto found_delayed_extent; + bh = bh->b_this_page; + end++; + } while (bh != head); + } + } else if (!(flags & FIEMAP_EXTENT_DELALLOC)) + /* a hole found. */ + goto out; + +found_delayed_extent: + newex->ec_len = min(end - newex->ec_block, + (ext4_lblk_t)EXT_INIT_MAX_LEN); + if (ret == nr_pages && bh != NULL && + newex->ec_len < EXT_INIT_MAX_LEN && + buffer_delay(bh)) { + /* Have not collected an extent and continue. */ + for (index = 0; index < ret; index++) + page_cache_release(pages[index]); + goto repeat; } + + for (index = 0; index < ret; index++) + page_cache_release(pages[index]); + kfree(pages); } physical = (__u64)newex->ec_start << blksize_bits; @@ -3822,32 +3947,16 @@ static int ext4_ext_fiemap_cb(struct inode *inode, struct ext4_ext_path *path, if (ex && ext4_ext_is_uninitialized(ex)) flags |= FIEMAP_EXTENT_UNWRITTEN; - /* - * If this extent reaches EXT_MAX_BLOCK, it must be last. - * - * Or if ext4_ext_next_allocated_block is EXT_MAX_BLOCK, - * this also indicates no more allocated blocks. - * - * XXX this might miss a single-block extent at EXT_MAX_BLOCK - */ - if (ext4_ext_next_allocated_block(path) == EXT_MAX_BLOCK || - newex->ec_block + newex->ec_len - 1 == EXT_MAX_BLOCK) { - loff_t size = i_size_read(inode); - loff_t bs = EXT4_BLOCK_SIZE(inode->i_sb); - + size = i_size_read(inode); + if (logical + length >= size) flags |= FIEMAP_EXTENT_LAST; - if ((flags & FIEMAP_EXTENT_DELALLOC) && - logical+length > size) - length = (size - logical + bs - 1) & ~(bs-1); - } - error = fiemap_fill_next_extent(fieinfo, logical, physical, + ret = fiemap_fill_next_extent(fieinfo, logical, physical, length, flags); - if (error < 0) - return error; - if (error == 1) + if (ret < 0) + return ret; + if (ret == 1) return EXT_BREAK; - return EXT_CONTINUE; } -- cgit From 32a9bb57d7c1fd04ae0f72b8f671501f000a0e9f Mon Sep 17 00:00:00 2001 From: Manish Katiyar Date: Sun, 27 Feb 2011 20:42:06 -0500 Subject: ext4: fix missing iput of root inode for some mount error paths This assures that the root inode is not leaked, and that sb->s_root is NULL, which will prevent generic_shutdown_super() from doing extra work, including call sync_filesystem, which ultimately results in ext4_sync_fs() getting called with an uninitialized struct super, which is the cause of the crash noted in Kernel Bugzilla #26752. https://bugzilla.kernel.org/show_bug.cgi?id=26752 Signed-off-by: Manish Katiyar Signed-off-by: "Theodore Ts'o" --- fs/ext4/super.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 33c398785e53..bd6e86aa82aa 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -3521,17 +3521,16 @@ no_journal: if (IS_ERR(root)) { ext4_msg(sb, KERN_ERR, "get root inode failed"); ret = PTR_ERR(root); + root = NULL; goto failed_mount4; } if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) { - iput(root); ext4_msg(sb, KERN_ERR, "corrupt root inode, run e2fsck"); goto failed_mount4; } sb->s_root = d_alloc_root(root); if (!sb->s_root) { ext4_msg(sb, KERN_ERR, "get root dentry failed"); - iput(root); ret = -ENOMEM; goto failed_mount4; } @@ -3647,6 +3646,8 @@ cantfind_ext4: goto failed_mount; failed_mount4: + iput(root); + sb->s_root = NULL; ext4_msg(sb, KERN_ERR, "mount failed"); destroy_workqueue(EXT4_SB(sb)->dio_unwritten_wq); failed_mount_wq: -- cgit From 8e8eaabefee3ff645b9551ee32c6c54c7d80ad19 Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Sun, 27 Feb 2011 23:32:12 -0500 Subject: ext4: use the nblocks arg to ext4_truncate_restart_trans() nblocks is passed into ext4_truncate_restart_trans() from ext4_ext_truncate_extend_restart() with a value different from the default blocks_for_truncate(), but is being ignored. The two other calls to ext4_truncate_restart_trans() already pass the default value, which is then being recalculated inside the function. Fix the problem by using the passed argument. Signed-off-by: Amir Goldstein --- fs/ext4/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index dcc2287433b6..67e7a3caf9ed 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -173,7 +173,7 @@ int ext4_truncate_restart_trans(handle_t *handle, struct inode *inode, BUG_ON(EXT4_JOURNAL(inode) == NULL); jbd_debug(2, "restarting handle %p\n", handle); up_write(&EXT4_I(inode)->i_data_sem); - ret = ext4_journal_restart(handle, blocks_for_truncate(inode)); + ret = ext4_journal_restart(handle, nblocks); down_write(&EXT4_I(inode)->i_data_sem); ext4_discard_preallocations(inode); -- cgit From d39195c33bb1b5fdcb0f416e8a0b34bfdb07a027 Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Mon, 28 Feb 2011 00:53:45 -0500 Subject: ext4: skip orphan cleanup if fs has unknown ROCOMPAT features Orphan cleanup is currently executed even if the file system has some number of unknown ROCOMPAT features, which deletes inodes and frees blocks, which could be very bad for some RO_COMPAT features, especially the SNAPSHOT feature. This patch skips the orphan cleanup if it contains readonly compatible features not known by this ext4 implementation, which would prevent the fs from being mounted (or remounted) readwrite. Signed-off-by: Amir Goldstein Signed-off-by: "Theodore Ts'o" --- fs/ext4/super.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'fs') diff --git a/fs/ext4/super.c b/fs/ext4/super.c index bd6e86aa82aa..9eaec22aa088 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -75,6 +75,7 @@ static void ext4_write_super(struct super_block *sb); static int ext4_freeze(struct super_block *sb); static struct dentry *ext4_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data); +static int ext4_feature_set_ok(struct super_block *sb, int readonly); static void ext4_destroy_lazyinit_thread(void); static void ext4_unregister_li_request(struct super_block *sb); static void ext4_clear_request_list(void); @@ -2117,6 +2118,13 @@ static void ext4_orphan_cleanup(struct super_block *sb, return; } + /* Check if feature set would not allow a r/w mount */ + if (!ext4_feature_set_ok(sb, 0)) { + ext4_msg(sb, KERN_INFO, "Skipping orphan cleanup due to " + "unknown ROCOMPAT features"); + return; + } + if (EXT4_SB(sb)->s_mount_state & EXT4_ERROR_FS) { if (es->s_last_orphan) jbd_debug(1, "Errors on filesystem, " -- cgit From b616844310a6c8a4ab405d3436bbb6e53cfd852f Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Mon, 28 Feb 2011 13:12:38 -0500 Subject: ext4: optimize ext4_bio_write_page() when no extent conversion is needed If no extent conversion is required, wake up any processes waiting for the page's writeback to be complete and free the ext4_io_end structure directly in ext4_end_bio() instead of dropping it on the linked list (which requires taking a spinlock to queue and dequeue the io_end structure), and waiting for the workqueue to do this work. This removes an extra scheduling delay before process waiting for an fsync() to complete gets woken up, and it also reduces the CPU overhead for a random write workload. Signed-off-by: "Theodore Ts'o" --- fs/ext4/page-io.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'fs') diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index d5c391ffad7a..0cfd03e19d7d 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c @@ -259,6 +259,11 @@ static void ext4_end_bio(struct bio *bio, int error) bi_sector >> (inode->i_blkbits - 9)); } + if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) { + ext4_free_io_end(io_end); + return; + } + /* Add the io_end to per-inode completed io list*/ spin_lock_irqsave(&EXT4_I(inode)->i_completed_io_lock, flags); list_add_tail(&io_end->list, &EXT4_I(inode)->i_completed_io_list); -- cgit From b7fc0ff09d24b372dc04b0c02b80659c0a66fdfe Mon Sep 17 00:00:00 2001 From: Phillip Lougher Date: Mon, 28 Feb 2011 01:45:42 +0000 Subject: Squashfs: extend decompressor framework to handle compression options Extend decompressor framework to handle compression options stored in the filesystem. These options can be used by the relevant decompressor at initialisation time to over-ride defaults. The presence of compression options in the filesystem is indicated by the COMP_OPT filesystem flag. If present the data is read from the filesystem and passed to the decompressor init function. The decompressor init function signature has been extended to take this data. Also update the init function signature in the glib, lzo and xz decompressor wrappers. Signed-off-by: Phillip Lougher --- fs/squashfs/decompressor.c | 34 ++++++++++++++++++++++++++++++++++ fs/squashfs/decompressor.h | 7 +------ fs/squashfs/lzo_wrapper.c | 4 ++-- fs/squashfs/squashfs.h | 1 + fs/squashfs/squashfs_fs.h | 4 ++++ fs/squashfs/super.c | 11 +++++++---- fs/squashfs/xz_wrapper.c | 5 +++-- fs/squashfs/zlib_wrapper.c | 4 ++-- 8 files changed, 54 insertions(+), 16 deletions(-) (limited to 'fs') diff --git a/fs/squashfs/decompressor.c b/fs/squashfs/decompressor.c index a5940e54c4dd..e921bd213738 100644 --- a/fs/squashfs/decompressor.c +++ b/fs/squashfs/decompressor.c @@ -23,6 +23,7 @@ #include #include +#include #include #include "squashfs_fs.h" @@ -74,3 +75,36 @@ const struct squashfs_decompressor *squashfs_lookup_decompressor(int id) return decompressor[i]; } + + +void *squashfs_decompressor_init(struct super_block *sb, unsigned short flags) +{ + struct squashfs_sb_info *msblk = sb->s_fs_info; + void *strm, *buffer = NULL; + int length = 0; + + /* + * Read decompressor specific options from file system if present + */ + if (SQUASHFS_COMP_OPTS(flags)) { + buffer = kmalloc(PAGE_CACHE_SIZE, GFP_KERNEL); + if (buffer == NULL) + return ERR_PTR(-ENOMEM); + + length = squashfs_read_data(sb, &buffer, + sizeof(struct squashfs_super_block), 0, NULL, + PAGE_CACHE_SIZE, 1); + + if (length < 0) { + strm = ERR_PTR(length); + goto finished; + } + } + + strm = msblk->decompressor->init(msblk, buffer, length); + +finished: + kfree(buffer); + + return strm; +} diff --git a/fs/squashfs/decompressor.h b/fs/squashfs/decompressor.h index 3b305a70f7aa..099745ad5691 100644 --- a/fs/squashfs/decompressor.h +++ b/fs/squashfs/decompressor.h @@ -24,7 +24,7 @@ */ struct squashfs_decompressor { - void *(*init)(struct squashfs_sb_info *); + void *(*init)(struct squashfs_sb_info *, void *, int); void (*free)(void *); int (*decompress)(struct squashfs_sb_info *, void **, struct buffer_head **, int, int, int, int, int); @@ -33,11 +33,6 @@ struct squashfs_decompressor { int supported; }; -static inline void *squashfs_decompressor_init(struct squashfs_sb_info *msblk) -{ - return msblk->decompressor->init(msblk); -} - static inline void squashfs_decompressor_free(struct squashfs_sb_info *msblk, void *s) { diff --git a/fs/squashfs/lzo_wrapper.c b/fs/squashfs/lzo_wrapper.c index 7da759e34c52..00f4dfc5f088 100644 --- a/fs/squashfs/lzo_wrapper.c +++ b/fs/squashfs/lzo_wrapper.c @@ -37,7 +37,7 @@ struct squashfs_lzo { void *output; }; -static void *lzo_init(struct squashfs_sb_info *msblk) +static void *lzo_init(struct squashfs_sb_info *msblk, void *buff, int len) { int block_size = max_t(int, msblk->block_size, SQUASHFS_METADATA_SIZE); @@ -58,7 +58,7 @@ failed2: failed: ERROR("Failed to allocate lzo workspace\n"); kfree(stream); - return NULL; + return ERR_PTR(-ENOMEM); } diff --git a/fs/squashfs/squashfs.h b/fs/squashfs/squashfs.h index ba729d808876..1f2e608b8785 100644 --- a/fs/squashfs/squashfs.h +++ b/fs/squashfs/squashfs.h @@ -48,6 +48,7 @@ extern int squashfs_read_table(struct super_block *, void *, u64, int); /* decompressor.c */ extern const struct squashfs_decompressor *squashfs_lookup_decompressor(int); +extern void *squashfs_decompressor_init(struct super_block *, unsigned short); /* export.c */ extern __le64 *squashfs_read_inode_lookup_table(struct super_block *, u64, diff --git a/fs/squashfs/squashfs_fs.h b/fs/squashfs/squashfs_fs.h index 39533feffd6d..4582c568ef4d 100644 --- a/fs/squashfs/squashfs_fs.h +++ b/fs/squashfs/squashfs_fs.h @@ -57,6 +57,7 @@ #define SQUASHFS_ALWAYS_FRAG 5 #define SQUASHFS_DUPLICATE 6 #define SQUASHFS_EXPORT 7 +#define SQUASHFS_COMP_OPT 10 #define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) @@ -81,6 +82,9 @@ #define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ SQUASHFS_EXPORT) +#define SQUASHFS_COMP_OPTS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_COMP_OPT) + /* Max number of types and file types */ #define SQUASHFS_DIR_TYPE 1 #define SQUASHFS_REG_TYPE 2 diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c index 20700b9f2b4c..95467db71a8e 100644 --- a/fs/squashfs/super.c +++ b/fs/squashfs/super.c @@ -199,10 +199,6 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) err = -ENOMEM; - msblk->stream = squashfs_decompressor_init(msblk); - if (msblk->stream == NULL) - goto failed_mount; - msblk->block_cache = squashfs_cache_init("metadata", SQUASHFS_CACHED_BLKS, SQUASHFS_METADATA_SIZE); if (msblk->block_cache == NULL) @@ -215,6 +211,13 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) goto failed_mount; } + msblk->stream = squashfs_decompressor_init(sb, flags); + if (IS_ERR(msblk->stream)) { + err = PTR_ERR(msblk->stream); + msblk->stream = NULL; + goto failed_mount; + } + /* Allocate and read id index table */ msblk->id_table = squashfs_read_id_index_table(sb, le64_to_cpu(sblk->id_table_start), le16_to_cpu(sblk->no_ids)); diff --git a/fs/squashfs/xz_wrapper.c b/fs/squashfs/xz_wrapper.c index c4eb40018256..397adea72eb9 100644 --- a/fs/squashfs/xz_wrapper.c +++ b/fs/squashfs/xz_wrapper.c @@ -38,7 +38,8 @@ struct squashfs_xz { struct xz_buf buf; }; -static void *squashfs_xz_init(struct squashfs_sb_info *msblk) +static void *squashfs_xz_init(struct squashfs_sb_info *msblk, void *buff, + int len) { int block_size = max_t(int, msblk->block_size, SQUASHFS_METADATA_SIZE); @@ -55,7 +56,7 @@ static void *squashfs_xz_init(struct squashfs_sb_info *msblk) failed: ERROR("Failed to allocate xz workspace\n"); kfree(stream); - return NULL; + return ERR_PTR(-ENOMEM); } diff --git a/fs/squashfs/zlib_wrapper.c b/fs/squashfs/zlib_wrapper.c index 4661ae2b1cec..195b0d035e9b 100644 --- a/fs/squashfs/zlib_wrapper.c +++ b/fs/squashfs/zlib_wrapper.c @@ -32,7 +32,7 @@ #include "squashfs.h" #include "decompressor.h" -static void *zlib_init(struct squashfs_sb_info *dummy) +static void *zlib_init(struct squashfs_sb_info *dummy, void *buff, int len) { z_stream *stream = kmalloc(sizeof(z_stream), GFP_KERNEL); if (stream == NULL) @@ -47,7 +47,7 @@ static void *zlib_init(struct squashfs_sb_info *dummy) failed: ERROR("Failed to allocate zlib workspace\n"); kfree(stream); - return NULL; + return ERR_PTR(-ENOMEM); } -- cgit From ff750311d30acc9564ef577050794953eee59f01 Mon Sep 17 00:00:00 2001 From: Phillip Lougher Date: Mon, 28 Feb 2011 15:31:46 +0000 Subject: Squashfs: add compression options support to xz decompressor Pass the dictionary size used to compress datablocks. Using a dictionary size less than the block size saves memory overhead, in many cases without adversely affecting compression ratio. Signed-off-by: Phillip Lougher --- fs/squashfs/xz_wrapper.c | 49 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 8 deletions(-) (limited to 'fs') diff --git a/fs/squashfs/xz_wrapper.c b/fs/squashfs/xz_wrapper.c index 397adea72eb9..06d0d11b482a 100644 --- a/fs/squashfs/xz_wrapper.c +++ b/fs/squashfs/xz_wrapper.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "squashfs_fs.h" #include "squashfs_fs_sb.h" @@ -38,25 +39,57 @@ struct squashfs_xz { struct xz_buf buf; }; +struct comp_opts { + __le32 dictionary_size; + __le32 flags; +}; + static void *squashfs_xz_init(struct squashfs_sb_info *msblk, void *buff, int len) { - int block_size = max_t(int, msblk->block_size, SQUASHFS_METADATA_SIZE); + struct comp_opts *comp_opts = buff; + struct squashfs_xz *stream; + int dict_size = msblk->block_size; + int err, n; + + if (comp_opts) { + /* check compressor options are the expected length */ + if (len < sizeof(*comp_opts)) { + err = -EIO; + goto failed; + } - struct squashfs_xz *stream = kmalloc(sizeof(*stream), GFP_KERNEL); - if (stream == NULL) + dict_size = le32_to_cpu(comp_opts->dictionary_size); + + /* the dictionary size should be 2^n or 2^n+2^(n+1) */ + n = ffs(dict_size) - 1; + if (dict_size != (1 << n) && dict_size != (1 << n) + + (1 << (n + 1))) { + err = -EIO; + goto failed; + } + } + + dict_size = max_t(int, dict_size, SQUASHFS_METADATA_SIZE); + + stream = kmalloc(sizeof(*stream), GFP_KERNEL); + if (stream == NULL) { + err = -ENOMEM; goto failed; + } - stream->state = xz_dec_init(XZ_PREALLOC, block_size); - if (stream->state == NULL) + stream->state = xz_dec_init(XZ_PREALLOC, dict_size); + if (stream->state == NULL) { + kfree(stream); + err = -ENOMEM; goto failed; + } return stream; failed: - ERROR("Failed to allocate xz workspace\n"); - kfree(stream); - return ERR_PTR(-ENOMEM); + ERROR("Failed to initialise xz decompressor\n"); + return ERR_PTR(err); } -- cgit From 681ffe2e4316801529fdafe379743d1d41fe2086 Mon Sep 17 00:00:00 2001 From: Phillip Lougher Date: Mon, 28 Feb 2011 16:21:34 +0000 Subject: Squashfs: Update Kconfig help text to include xz compression Signed-off-by: Phillip Lougher --- fs/squashfs/Kconfig | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'fs') diff --git a/fs/squashfs/Kconfig b/fs/squashfs/Kconfig index aa68a8a31518..efc309fa3035 100644 --- a/fs/squashfs/Kconfig +++ b/fs/squashfs/Kconfig @@ -5,12 +5,12 @@ config SQUASHFS help Saying Y here includes support for SquashFS 4.0 (a Compressed Read-Only File System). Squashfs is a highly compressed read-only - filesystem for Linux. It uses zlib/lzo compression to compress both - files, inodes and directories. Inodes in the system are very small - and all blocks are packed to minimise data overhead. Block sizes - greater than 4K are supported up to a maximum of 1 Mbytes (default - block size 128K). SquashFS 4.0 supports 64 bit filesystems and files - (larger than 4GB), full uid/gid information, hard links and + filesystem for Linux. It uses zlib, lzo or xz compression to + compress both files, inodes and directories. Inodes in the system + are very small and all blocks are packed to minimise data overhead. + Block sizes greater than 4K are supported up to a maximum of 1 Mbytes + (default block size 128K). SquashFS 4.0 supports 64 bit filesystems + and files (larger than 4GB), full uid/gid information, hard links and timestamps. Squashfs is intended for general read-only filesystem use, for -- cgit From 3ad126641c05f93d2fa153bb8ff762fb4cdbb885 Mon Sep 17 00:00:00 2001 From: Phillip Lougher Date: Mon, 28 Feb 2011 16:42:20 +0000 Subject: Squashfs: xz_wrapper doesn't need to include squashfs_fs_i.h anymore Signed-off-by: Phillip Lougher --- fs/squashfs/xz_wrapper.c | 1 - 1 file changed, 1 deletion(-) (limited to 'fs') diff --git a/fs/squashfs/xz_wrapper.c b/fs/squashfs/xz_wrapper.c index 06d0d11b482a..aa47a286d1f8 100644 --- a/fs/squashfs/xz_wrapper.c +++ b/fs/squashfs/xz_wrapper.c @@ -30,7 +30,6 @@ #include "squashfs_fs.h" #include "squashfs_fs_sb.h" -#include "squashfs_fs_i.h" #include "squashfs.h" #include "decompressor.h" -- cgit From 003a3194d36dc22c29cacda4d0c6fede2753c9d0 Mon Sep 17 00:00:00 2001 From: Phillip Lougher Date: Mon, 28 Feb 2011 18:43:48 +0000 Subject: Squashfs: wrap squashfs_mount() definition Squashfs_get_sb() to squashfs_mount() conversion (commit 152a0836) results in line over 80 characters. Signed-off-by: Phillip Lougher --- fs/squashfs/super.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c index 95467db71a8e..5c8184c061a4 100644 --- a/fs/squashfs/super.c +++ b/fs/squashfs/super.c @@ -373,8 +373,8 @@ static void squashfs_put_super(struct super_block *sb) } -static struct dentry *squashfs_mount(struct file_system_type *fs_type, int flags, - const char *dev_name, void *data) +static struct dentry *squashfs_mount(struct file_system_type *fs_type, + int flags, const char *dev_name, void *data) { return mount_bdev(fs_type, flags, dev_name, data, squashfs_fill_super); } -- cgit From eeb2036b8a148629b762ae6d85cff0be8106f081 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Tue, 1 Mar 2011 17:50:00 +0000 Subject: xfs: zero proper structure size for geometry calls Commit 493f3358cb289ccf716c5a14fa5bb52ab75943e5 added this call to xfs_fs_geometry() in order to avoid passing kernel stack data back to user space: + memset(geo, 0, sizeof(*geo)); Unfortunately, one of the callers of that function passes the address of a smaller data type, cast to fit the type that xfs_fs_geometry() requires. As a result, this can happen: Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: f87aca93 Pid: 262, comm: xfs_fsr Not tainted 2.6.38-rc6-493f3358cb2+ #1 Call Trace: [] ? panic+0x50/0x150 [] ? __stack_chk_fail+0x10/0x18 [] ? xfs_ioc_fsgeometry_v1+0x56/0x5d [xfs] Fix this by fixing that one caller to pass the right type and then copy out the subset it is interested in. Note: This patch is an alternative to one originally proposed by Eric Sandeen. Reported-by: Jeffrey Hundstad Signed-off-by: Alex Elder Reviewed-by: Eric Sandeen Tested-by: Jeffrey Hundstad --- fs/xfs/linux-2.6/xfs_ioctl.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index f5e2a19e0f8e..0ca0e3c024d7 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c @@ -695,14 +695,19 @@ xfs_ioc_fsgeometry_v1( xfs_mount_t *mp, void __user *arg) { - xfs_fsop_geom_v1_t fsgeo; + xfs_fsop_geom_t fsgeo; int error; - error = xfs_fs_geometry(mp, (xfs_fsop_geom_t *)&fsgeo, 3); + error = xfs_fs_geometry(mp, &fsgeo, 3); if (error) return -error; - if (copy_to_user(arg, &fsgeo, sizeof(fsgeo))) + /* + * Caller should have passed an argument of type + * xfs_fsop_geom_v1_t. This is a proper subset of the + * xfs_fsop_geom_t that xfs_fs_geometry() fills in. + */ + if (copy_to_user(arg, &fsgeo, sizeof(xfs_fsop_geom_v1_t))) return -XFS_ERROR(EFAULT); return 0; } -- cgit From 10e38391c0e242e53e30094f6c00553418ab2f2e Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Wed, 2 Mar 2011 14:20:59 +1100 Subject: xfs: introduce new logging API. Most of the logging infrastructure in XFS is unneccessary and designed around the infrastructure supplied by Irix rather than Linux. To rationalise the logging interfaces, start by introducing simple printk wrappers similar to the dev_printk() infrastructure. Later patches will convert code to use this new interface. Signed-off-by: Dave Chinner Reviewed-by: Alex Elder Reviewed-by: Christoph Hellwig --- fs/xfs/Makefile | 1 + fs/xfs/linux-2.6/xfs_linux.h | 1 + fs/xfs/linux-2.6/xfs_message.c | 119 +++++++++++++++++++++++++++++++++++++++++ fs/xfs/linux-2.6/xfs_message.h | 34 ++++++++++++ 4 files changed, 155 insertions(+) create mode 100644 fs/xfs/linux-2.6/xfs_message.c create mode 100644 fs/xfs/linux-2.6/xfs_message.h (limited to 'fs') diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index faca44997099..077784ed6a7f 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -105,6 +105,7 @@ xfs-y += $(addprefix $(XFS_LINUX)/, \ xfs_globals.o \ xfs_ioctl.o \ xfs_iops.o \ + xfs_message.o \ xfs_super.o \ xfs_sync.o \ xfs_xattr.o) diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h index 096494997747..1189bfcbcd3e 100644 --- a/fs/xfs/linux-2.6/xfs_linux.h +++ b/fs/xfs/linux-2.6/xfs_linux.h @@ -86,6 +86,7 @@ #include #include #include +#include /* * Feature macros (disable/enable) diff --git a/fs/xfs/linux-2.6/xfs_message.c b/fs/xfs/linux-2.6/xfs_message.c new file mode 100644 index 000000000000..6f3368eec25d --- /dev/null +++ b/fs/xfs/linux-2.6/xfs_message.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2011 Red Hat, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "xfs.h" +#include "xfs_fs.h" +#include "xfs_types.h" +#include "xfs_log.h" +#include "xfs_inum.h" +#include "xfs_trans.h" +#include "xfs_sb.h" +#include "xfs_ag.h" +#include "xfs_mount.h" + +/* + * XFS logging functions + */ +static int +__xfs_printk( + const char *level, + const struct xfs_mount *mp, + struct va_format *vaf) +{ + if (mp && mp->m_fsname) + return printk("%sXFS (%s): %pV\n", level, mp->m_fsname, vaf); + return printk("%sXFS: %pV\n", level, vaf); +} + +int xfs_printk( + const char *level, + const struct xfs_mount *mp, + const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + int r; + + va_start(args, fmt); + + vaf.fmt = fmt; + vaf.va = &args; + + r = __xfs_printk(level, mp, &vaf); + va_end(args); + + return r; +} + +#define define_xfs_printk_level(func, kern_level) \ +int func(const struct xfs_mount *mp, const char *fmt, ...) \ +{ \ + struct va_format vaf; \ + va_list args; \ + int r; \ + \ + va_start(args, fmt); \ + \ + vaf.fmt = fmt; \ + vaf.va = &args; \ + \ + r = __xfs_printk(kern_level, mp, &vaf); \ + va_end(args); \ + \ + return r; \ +} \ + +define_xfs_printk_level(xfs_emerg, KERN_EMERG); +define_xfs_printk_level(xfs_alert, KERN_ALERT); +define_xfs_printk_level(xfs_crit, KERN_CRIT); +define_xfs_printk_level(xfs_err, KERN_ERR); +define_xfs_printk_level(xfs_warn, KERN_WARNING); +define_xfs_printk_level(xfs_notice, KERN_NOTICE); +define_xfs_printk_level(xfs_info, KERN_INFO); +#ifdef DEBUG +define_xfs_printk_level(xfs_debug, KERN_DEBUG); +#endif + +int +xfs_alert_tag( + const struct xfs_mount *mp, + int panic_tag, + const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + int panic = 0; + int r; + + if (xfs_panic_mask && (xfs_panic_mask & panic_tag)) { + xfs_printk(KERN_ALERT, mp, + "XFS: Transforming an alert into a BUG."); + panic = 1; + } + + va_start(args, fmt); + + vaf.fmt = fmt; + vaf.va = &args; + + r = __xfs_printk(KERN_ALERT, mp, &vaf); + va_end(args); + + BUG_ON(panic); + + return r; +} diff --git a/fs/xfs/linux-2.6/xfs_message.h b/fs/xfs/linux-2.6/xfs_message.h new file mode 100644 index 000000000000..8d2df0175304 --- /dev/null +++ b/fs/xfs/linux-2.6/xfs_message.h @@ -0,0 +1,34 @@ +#ifndef __XFS_MESSAGE_H +#define __XFS_MESSAGE_H 1 + +struct xfs_mount; + +extern int xfs_printk(const char *level, const struct xfs_mount *mp, + const char *fmt, ...) + __attribute__ ((format (printf, 3, 4))); +extern int xfs_emerg(const struct xfs_mount *mp, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +extern int xfs_alert(const struct xfs_mount *mp, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +extern int xfs_alert_tag(const struct xfs_mount *mp, int tag, + const char *fmt, ...) + __attribute__ ((format (printf, 3, 4))); +extern int xfs_crit(const struct xfs_mount *mp, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +extern int xfs_err(const struct xfs_mount *mp, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +extern int xfs_warn(const struct xfs_mount *mp, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +extern int xfs_notice(const struct xfs_mount *mp, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +extern int xfs_info(const struct xfs_mount *mp, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); + +#ifdef DEBUG +extern int xfs_debug(const struct xfs_mount *mp, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +#else +#define xfs_debug(mp, fmt, ...) (0) +#endif + +#endif /* __XFS_MESSAGE_H */ -- cgit From 198868f35de99e7197829314076e5465c37e4cc5 Mon Sep 17 00:00:00 2001 From: Mingming Cao Date: Sat, 5 Mar 2011 11:52:45 -0500 Subject: ext4: Use single thread to perform DIO unwritten convertion While running ext4 testing on multiple core, we found there are per cpu ext4-dio-unwritten threads processing conversion from unwritten extents to written for IOs completed from async direct IO patch. Per filesystem is enough, we don't need per cpu threads to work on conversion. Signed-off-by: Mingming Cao --- fs/ext4/super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 9eaec22aa088..b357c2700d72 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -3514,7 +3514,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) percpu_counter_set(&sbi->s_dirtyblocks_counter, 0); no_journal: - EXT4_SB(sb)->dio_unwritten_wq = create_workqueue("ext4-dio-unwritten"); + EXT4_SB(sb)->dio_unwritten_wq = create_singlethread_workqueue("ext4-dio-unwritten"); if (!EXT4_SB(sb)->dio_unwritten_wq) { printk(KERN_ERR "EXT4-fs: failed to create DIO workqueue\n"); goto failed_mount_wq; -- cgit From 4f10700a2e4bb2ff3d3a80f08412e21109e6d4b5 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Mon, 7 Mar 2011 10:00:35 +1100 Subject: xfs: Convert linux-2.6/ files to new logging interface Convert the files in fs/xfs/linux-2.6/ to use the new xfs_ logging format that replaces the old Irix inherited cmn_err() interfaces. While there, also convert naked printk calls to use the relevant xfs logging function to standardise output format. Signed-off-by: Dave Chinner Reviewed-by: Alex Elder Reviewed-by: Christoph Hellwig --- fs/xfs/linux-2.6/kmem.c | 9 +-- fs/xfs/linux-2.6/xfs_aops.c | 6 +- fs/xfs/linux-2.6/xfs_buf.c | 17 +++--- fs/xfs/linux-2.6/xfs_super.c | 127 +++++++++++++++++++----------------------- fs/xfs/linux-2.6/xfs_sync.c | 5 +- fs/xfs/linux-2.6/xfs_sysctl.c | 2 +- 6 files changed, 76 insertions(+), 90 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/kmem.c b/fs/xfs/linux-2.6/kmem.c index 666c9db48eb6..a907de565db3 100644 --- a/fs/xfs/linux-2.6/kmem.c +++ b/fs/xfs/linux-2.6/kmem.c @@ -23,6 +23,7 @@ #include #include "time.h" #include "kmem.h" +#include "xfs_message.h" /* * Greedy allocation. May fail and may return vmalloced memory. @@ -56,8 +57,8 @@ kmem_alloc(size_t size, unsigned int __nocast flags) if (ptr || (flags & (KM_MAYFAIL|KM_NOSLEEP))) return ptr; if (!(++retries % 100)) - printk(KERN_ERR "XFS: possible memory allocation " - "deadlock in %s (mode:0x%x)\n", + xfs_err(NULL, + "possible memory allocation deadlock in %s (mode:0x%x)", __func__, lflags); congestion_wait(BLK_RW_ASYNC, HZ/50); } while (1); @@ -112,8 +113,8 @@ kmem_zone_alloc(kmem_zone_t *zone, unsigned int __nocast flags) if (ptr || (flags & (KM_MAYFAIL|KM_NOSLEEP))) return ptr; if (!(++retries % 100)) - printk(KERN_ERR "XFS: possible memory allocation " - "deadlock in %s (mode:0x%x)\n", + xfs_err(NULL, + "possible memory allocation deadlock in %s (mode:0x%x)", __func__, lflags); congestion_wait(BLK_RW_ASYNC, HZ/50); } while (1); diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index ec7bbb5645b6..8c5c87277456 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -854,7 +854,7 @@ xfs_aops_discard_page( if (XFS_FORCED_SHUTDOWN(ip->i_mount)) goto out_invalidate; - xfs_fs_cmn_err(CE_ALERT, ip->i_mount, + xfs_alert(ip->i_mount, "page discard on page %p, inode 0x%llx, offset %llu.", page, ip->i_ino, offset); @@ -872,7 +872,7 @@ xfs_aops_discard_page( if (error) { /* something screwed, just bail */ if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { - xfs_fs_cmn_err(CE_ALERT, ip->i_mount, + xfs_alert(ip->i_mount, "page discard unable to remove delalloc mapping."); } break; @@ -1411,7 +1411,7 @@ xfs_vm_write_failed( if (error) { /* something screwed, just bail */ if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { - xfs_fs_cmn_err(CE_ALERT, ip->i_mount, + xfs_alert(ip->i_mount, "xfs_vm_write_failed: unable to clean up ino %lld", ip->i_ino); } diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index ac1c7e8378dd..3cc671c8a67f 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c @@ -401,9 +401,8 @@ _xfs_buf_lookup_pages( * handle buffer allocation failures we can't do much. */ if (!(++retries % 100)) - printk(KERN_ERR - "XFS: possible memory allocation " - "deadlock in %s (mode:0x%x)\n", + xfs_err(NULL, + "possible memory allocation deadlock in %s (mode:0x%x)", __func__, gfp_mask); XFS_STATS_INC(xb_page_retries); @@ -615,8 +614,8 @@ xfs_buf_get( if (!(bp->b_flags & XBF_MAPPED)) { error = _xfs_buf_map_pages(bp, flags); if (unlikely(error)) { - printk(KERN_WARNING "%s: failed to map pages\n", - __func__); + xfs_warn(target->bt_mount, + "%s: failed to map pages\n", __func__); goto no_buffer; } } @@ -850,8 +849,8 @@ xfs_buf_get_uncached( error = _xfs_buf_map_pages(bp, XBF_MAPPED); if (unlikely(error)) { - printk(KERN_WARNING "%s: failed to map pages\n", - __func__); + xfs_warn(target->bt_mount, + "%s: failed to map pages\n", __func__); goto fail_free_mem; } @@ -1617,8 +1616,8 @@ xfs_setsize_buftarg_flags( btp->bt_smask = sectorsize - 1; if (set_blocksize(btp->bt_bdev, sectorsize)) { - printk(KERN_WARNING - "XFS: Cannot set_blocksize to %u on device %s\n", + xfs_warn(btp->bt_mount, + "Cannot set_blocksize to %u on device %s\n", sectorsize, XFS_BUFTARG_NAME(btp)); return EINVAL; } diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 7ec1fb8c1316..818c4cf2de86 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -172,6 +172,15 @@ xfs_parseargs( int iosize = 0; __uint8_t iosizelog = 0; + /* + * set up the mount name first so all the errors will refer to the + * correct device. + */ + mp->m_fsname = kstrndup(sb->s_id, MAXNAMELEN, GFP_KERNEL); + if (!mp->m_fsname) + return ENOMEM; + mp->m_fsname_len = strlen(mp->m_fsname) + 1; + /* * Copy binary VFS mount flags we are interested in. */ @@ -208,24 +217,21 @@ xfs_parseargs( if (!strcmp(this_char, MNTOPT_LOGBUFS)) { if (!value || !*value) { - cmn_err(CE_WARN, - "XFS: %s option requires an argument", + xfs_warn(mp, "%s option requires an argument", this_char); return EINVAL; } mp->m_logbufs = simple_strtoul(value, &eov, 10); } else if (!strcmp(this_char, MNTOPT_LOGBSIZE)) { if (!value || !*value) { - cmn_err(CE_WARN, - "XFS: %s option requires an argument", + xfs_warn(mp, "%s option requires an argument", this_char); return EINVAL; } mp->m_logbsize = suffix_strtoul(value, &eov, 10); } else if (!strcmp(this_char, MNTOPT_LOGDEV)) { if (!value || !*value) { - cmn_err(CE_WARN, - "XFS: %s option requires an argument", + xfs_warn(mp, "%s option requires an argument", this_char); return EINVAL; } @@ -233,14 +239,12 @@ xfs_parseargs( if (!mp->m_logname) return ENOMEM; } else if (!strcmp(this_char, MNTOPT_MTPT)) { - cmn_err(CE_WARN, - "XFS: %s option not allowed on this system", + xfs_warn(mp, "%s option not allowed on this system", this_char); return EINVAL; } else if (!strcmp(this_char, MNTOPT_RTDEV)) { if (!value || !*value) { - cmn_err(CE_WARN, - "XFS: %s option requires an argument", + xfs_warn(mp, "%s option requires an argument", this_char); return EINVAL; } @@ -249,8 +253,7 @@ xfs_parseargs( return ENOMEM; } else if (!strcmp(this_char, MNTOPT_BIOSIZE)) { if (!value || !*value) { - cmn_err(CE_WARN, - "XFS: %s option requires an argument", + xfs_warn(mp, "%s option requires an argument", this_char); return EINVAL; } @@ -258,8 +261,7 @@ xfs_parseargs( iosizelog = ffs(iosize) - 1; } else if (!strcmp(this_char, MNTOPT_ALLOCSIZE)) { if (!value || !*value) { - cmn_err(CE_WARN, - "XFS: %s option requires an argument", + xfs_warn(mp, "%s option requires an argument", this_char); return EINVAL; } @@ -281,16 +283,14 @@ xfs_parseargs( mp->m_flags |= XFS_MOUNT_SWALLOC; } else if (!strcmp(this_char, MNTOPT_SUNIT)) { if (!value || !*value) { - cmn_err(CE_WARN, - "XFS: %s option requires an argument", + xfs_warn(mp, "%s option requires an argument", this_char); return EINVAL; } dsunit = simple_strtoul(value, &eov, 10); } else if (!strcmp(this_char, MNTOPT_SWIDTH)) { if (!value || !*value) { - cmn_err(CE_WARN, - "XFS: %s option requires an argument", + xfs_warn(mp, "%s option requires an argument", this_char); return EINVAL; } @@ -298,8 +298,7 @@ xfs_parseargs( } else if (!strcmp(this_char, MNTOPT_64BITINODE)) { mp->m_flags &= ~XFS_MOUNT_SMALL_INUMS; #if !XFS_BIG_INUMS - cmn_err(CE_WARN, - "XFS: %s option not allowed on this system", + xfs_warn(mp, "%s option not allowed on this system", this_char); return EINVAL; #endif @@ -357,20 +356,19 @@ xfs_parseargs( } else if (!strcmp(this_char, MNTOPT_NODELAYLOG)) { mp->m_flags &= ~XFS_MOUNT_DELAYLOG; } else if (!strcmp(this_char, "ihashsize")) { - cmn_err(CE_WARN, - "XFS: ihashsize no longer used, option is deprecated."); + xfs_warn(mp, + "ihashsize no longer used, option is deprecated."); } else if (!strcmp(this_char, "osyncisdsync")) { - cmn_err(CE_WARN, - "XFS: osyncisdsync has no effect, option is deprecated."); + xfs_warn(mp, + "osyncisdsync has no effect, option is deprecated."); } else if (!strcmp(this_char, "osyncisosync")) { - cmn_err(CE_WARN, - "XFS: osyncisosync has no effect, option is deprecated."); + xfs_warn(mp, + "osyncisosync has no effect, option is deprecated."); } else if (!strcmp(this_char, "irixsgid")) { - cmn_err(CE_WARN, - "XFS: irixsgid is now a sysctl(2) variable, option is deprecated."); + xfs_warn(mp, + "irixsgid is now a sysctl(2) variable, option is deprecated."); } else { - cmn_err(CE_WARN, - "XFS: unknown mount option [%s].", this_char); + xfs_warn(mp, "unknown mount option [%s].", this_char); return EINVAL; } } @@ -380,40 +378,37 @@ xfs_parseargs( */ if ((mp->m_flags & XFS_MOUNT_NORECOVERY) && !(mp->m_flags & XFS_MOUNT_RDONLY)) { - cmn_err(CE_WARN, "XFS: no-recovery mounts must be read-only."); + xfs_warn(mp, "no-recovery mounts must be read-only."); return EINVAL; } if ((mp->m_flags & XFS_MOUNT_NOALIGN) && (dsunit || dswidth)) { - cmn_err(CE_WARN, - "XFS: sunit and swidth options incompatible with the noalign option"); + xfs_warn(mp, + "sunit and swidth options incompatible with the noalign option"); return EINVAL; } #ifndef CONFIG_XFS_QUOTA if (XFS_IS_QUOTA_RUNNING(mp)) { - cmn_err(CE_WARN, - "XFS: quota support not available in this kernel."); + xfs_warn(mp, "quota support not available in this kernel."); return EINVAL; } #endif if ((mp->m_qflags & (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE)) && (mp->m_qflags & (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE))) { - cmn_err(CE_WARN, - "XFS: cannot mount with both project and group quota"); + xfs_warn(mp, "cannot mount with both project and group quota"); return EINVAL; } if ((dsunit && !dswidth) || (!dsunit && dswidth)) { - cmn_err(CE_WARN, - "XFS: sunit and swidth must be specified together"); + xfs_warn(mp, "sunit and swidth must be specified together"); return EINVAL; } if (dsunit && (dswidth % dsunit != 0)) { - cmn_err(CE_WARN, - "XFS: stripe width (%d) must be a multiple of the stripe unit (%d)", + xfs_warn(mp, + "stripe width (%d) must be a multiple of the stripe unit (%d)", dswidth, dsunit); return EINVAL; } @@ -439,8 +434,7 @@ done: mp->m_logbufs != 0 && (mp->m_logbufs < XLOG_MIN_ICLOGS || mp->m_logbufs > XLOG_MAX_ICLOGS)) { - cmn_err(CE_WARN, - "XFS: invalid logbufs value: %d [not %d-%d]", + xfs_warn(mp, "invalid logbufs value: %d [not %d-%d]", mp->m_logbufs, XLOG_MIN_ICLOGS, XLOG_MAX_ICLOGS); return XFS_ERROR(EINVAL); } @@ -449,22 +443,16 @@ done: (mp->m_logbsize < XLOG_MIN_RECORD_BSIZE || mp->m_logbsize > XLOG_MAX_RECORD_BSIZE || !is_power_of_2(mp->m_logbsize))) { - cmn_err(CE_WARN, - "XFS: invalid logbufsize: %d [not 16k,32k,64k,128k or 256k]", + xfs_warn(mp, + "invalid logbufsize: %d [not 16k,32k,64k,128k or 256k]", mp->m_logbsize); return XFS_ERROR(EINVAL); } - mp->m_fsname = kstrndup(sb->s_id, MAXNAMELEN, GFP_KERNEL); - if (!mp->m_fsname) - return ENOMEM; - mp->m_fsname_len = strlen(mp->m_fsname) + 1; - if (iosizelog) { if (iosizelog > XFS_MAX_IO_LOG || iosizelog < XFS_MIN_IO_LOG) { - cmn_err(CE_WARN, - "XFS: invalid log iosize: %d [not %d-%d]", + xfs_warn(mp, "invalid log iosize: %d [not %d-%d]", iosizelog, XFS_MIN_IO_LOG, XFS_MAX_IO_LOG); return XFS_ERROR(EINVAL); @@ -611,7 +599,7 @@ xfs_blkdev_get( mp); if (IS_ERR(*bdevp)) { error = PTR_ERR(*bdevp); - printk("XFS: Invalid device [%s], error=%d\n", name, error); + xfs_warn(mp, "Invalid device [%s], error=%d\n", name, error); } return -error; @@ -665,23 +653,23 @@ xfs_mountfs_check_barriers(xfs_mount_t *mp) int error; if (mp->m_logdev_targp != mp->m_ddev_targp) { - xfs_fs_cmn_err(CE_NOTE, mp, + xfs_notice(mp, "Disabling barriers, not supported with external log device"); mp->m_flags &= ~XFS_MOUNT_BARRIER; return; } if (xfs_readonly_buftarg(mp->m_ddev_targp)) { - xfs_fs_cmn_err(CE_NOTE, mp, - "Disabling barriers, underlying device is readonly"); + xfs_notice(mp, + "Disabling barriers, underlying device is readonly"); mp->m_flags &= ~XFS_MOUNT_BARRIER; return; } error = xfs_barrier_test(mp); if (error) { - xfs_fs_cmn_err(CE_NOTE, mp, - "Disabling barriers, trial barrier write failed"); + xfs_notice(mp, + "Disabling barriers, trial barrier write failed"); mp->m_flags &= ~XFS_MOUNT_BARRIER; return; } @@ -744,8 +732,8 @@ xfs_open_devices( goto out_close_logdev; if (rtdev == ddev || rtdev == logdev) { - cmn_err(CE_WARN, - "XFS: Cannot mount filesystem with identical rtdev and ddev/logdev."); + xfs_warn(mp, + "Cannot mount filesystem with identical rtdev and ddev/logdev."); error = EINVAL; goto out_close_rtdev; } @@ -1346,8 +1334,8 @@ xfs_fs_remount( * options that we can't actually change. */ #if 0 - printk(KERN_INFO - "XFS: mount option \"%s\" not supported for remount\n", p); + xfs_info(mp, + "mount option \"%s\" not supported for remount\n", p); return -EINVAL; #else break; @@ -1368,8 +1356,7 @@ xfs_fs_remount( if (mp->m_update_flags) { error = xfs_mount_log_sb(mp, mp->m_update_flags); if (error) { - cmn_err(CE_WARN, - "XFS: failed to write sb changes"); + xfs_warn(mp, "failed to write sb changes"); return error; } mp->m_update_flags = 0; @@ -1453,15 +1440,15 @@ xfs_finish_flags( mp->m_logbsize = mp->m_sb.sb_logsunit; } else if (mp->m_logbsize > 0 && mp->m_logbsize < mp->m_sb.sb_logsunit) { - cmn_err(CE_WARN, - "XFS: logbuf size must be greater than or equal to log stripe size"); + xfs_warn(mp, + "logbuf size must be greater than or equal to log stripe size"); return XFS_ERROR(EINVAL); } } else { /* Fail a mount if the logbuf is larger than 32K */ if (mp->m_logbsize > XLOG_BIG_RECORD_BSIZE) { - cmn_err(CE_WARN, - "XFS: logbuf size for version 1 logs must be 16K or 32K"); + xfs_warn(mp, + "logbuf size for version 1 logs must be 16K or 32K"); return XFS_ERROR(EINVAL); } } @@ -1478,8 +1465,8 @@ xfs_finish_flags( * prohibit r/w mounts of read-only filesystems */ if ((mp->m_sb.sb_flags & XFS_SBF_READONLY) && !ronly) { - cmn_err(CE_WARN, - "XFS: cannot mount a read-only filesystem as read-write"); + xfs_warn(mp, + "cannot mount a read-only filesystem as read-write"); return XFS_ERROR(EROFS); } diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c index e22f0057d21f..6c10f1d2e3d3 100644 --- a/fs/xfs/linux-2.6/xfs_sync.c +++ b/fs/xfs/linux-2.6/xfs_sync.c @@ -425,8 +425,7 @@ xfs_quiesce_attr( /* Push the superblock and write an unmount record */ error = xfs_log_sbcount(mp, 1); if (error) - xfs_fs_cmn_err(CE_WARN, mp, - "xfs_attr_quiesce: failed to log sb changes. " + xfs_warn(mp, "xfs_attr_quiesce: failed to log sb changes. " "Frozen image may not be consistent."); xfs_log_unmount_write(mp); xfs_unmountfs_writesb(mp); @@ -806,7 +805,7 @@ xfs_reclaim_inode( * pass on the error. */ if (error && error != EAGAIN && !XFS_FORCED_SHUTDOWN(ip->i_mount)) { - xfs_fs_cmn_err(CE_WARN, ip->i_mount, + xfs_warn(ip->i_mount, "inode 0x%llx background reclaim flush failed with %d", (long long)ip->i_ino, error); } diff --git a/fs/xfs/linux-2.6/xfs_sysctl.c b/fs/xfs/linux-2.6/xfs_sysctl.c index ee3cee097e7e..ee2d2adaa438 100644 --- a/fs/xfs/linux-2.6/xfs_sysctl.c +++ b/fs/xfs/linux-2.6/xfs_sysctl.c @@ -37,7 +37,7 @@ xfs_stats_clear_proc_handler( ret = proc_dointvec_minmax(ctl, write, buffer, lenp, ppos); if (!ret && write && *valp) { - printk("XFS Clearing xfsstats\n"); + xfs_notice(NULL, "Clearing xfsstats"); for_each_possible_cpu(c) { preempt_disable(); /* save vn_active, it's a universal truth! */ -- cgit From a0fa2b679ecd15b4bdbb46cd2420b6affde91cf9 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Mon, 7 Mar 2011 10:01:35 +1100 Subject: xfs: Convert xlog_warn to new logging interface Convert the xfs log operations to use the new error logging interfaces. This removes the xlog_{warn,panic} wrappers and makes almost all errors emit the device they belong to instead of just refering to "XFS". Signed-off-by: Dave Chinner Reviewed-by: Alex Elder Reviewed-by: Christoph Hellwig --- fs/xfs/quota/xfs_dquot.c | 10 ++- fs/xfs/quota/xfs_qm.c | 2 +- fs/xfs/xfs_log.c | 124 +++++++++++++------------- fs/xfs/xfs_log_priv.h | 4 - fs/xfs/xfs_log_recover.c | 223 +++++++++++++++++++++++------------------------ fs/xfs/xfs_quota.h | 3 +- 6 files changed, 177 insertions(+), 189 deletions(-) (limited to 'fs') diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c index d22aa3103106..773adc80d6b4 100644 --- a/fs/xfs/quota/xfs_dquot.c +++ b/fs/xfs/quota/xfs_dquot.c @@ -544,9 +544,10 @@ xfs_qm_dqtobp( /* * A simple sanity check in case we got a corrupted dquot... */ - if (xfs_qm_dqcheck(ddq, id, dqp->dq_flags & XFS_DQ_ALLTYPES, + error = xfs_qm_dqcheck(mp, ddq, id, dqp->dq_flags & XFS_DQ_ALLTYPES, flags & (XFS_QMOPT_DQREPAIR|XFS_QMOPT_DOWARN), - "dqtobp")) { + "dqtobp"); + if (error) { if (!(flags & XFS_QMOPT_DQREPAIR)) { xfs_trans_brelse(tp, bp); return XFS_ERROR(EIO); @@ -1207,8 +1208,9 @@ xfs_qm_dqflush( /* * A simple sanity check in case we got a corrupted dquot.. */ - if (xfs_qm_dqcheck(&dqp->q_core, be32_to_cpu(ddqp->d_id), 0, - XFS_QMOPT_DOWARN, "dqflush (incore copy)")) { + error = xfs_qm_dqcheck(mp, &dqp->q_core, be32_to_cpu(ddqp->d_id), 0, + XFS_QMOPT_DOWARN, "dqflush (incore copy)"); + if (error) { xfs_buf_relse(bp); xfs_dqfunlock(dqp); xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index f517963aec07..dd5cc5738a2c 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c @@ -1292,7 +1292,7 @@ xfs_qm_reset_dqcounts( * output any warnings because it's perfectly possible to * find uninitialised dquot blks. See comment in xfs_qm_dqcheck. */ - (void) xfs_qm_dqcheck(ddq, id+j, type, XFS_QMOPT_DQREPAIR, + (void) xfs_qm_dqcheck(mp, ddq, id+j, type, XFS_QMOPT_DQREPAIR, "xfs_quotacheck"); ddq->d_bcount = 0; ddq->d_icount = 0; diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index ae6fef1ff563..25efa9b8a602 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -374,11 +374,10 @@ xfs_log_mount( int error; if (!(mp->m_flags & XFS_MOUNT_NORECOVERY)) - cmn_err(CE_NOTE, "XFS mounting filesystem %s", mp->m_fsname); + xfs_notice(mp, "Mounting Filesystem"); else { - cmn_err(CE_NOTE, - "Mounting filesystem \"%s\" in no-recovery mode. Filesystem will be inconsistent.", - mp->m_fsname); + xfs_notice(mp, +"Mounting filesystem in no-recovery mode. Filesystem will be inconsistent."); ASSERT(mp->m_flags & XFS_MOUNT_RDONLY); } @@ -393,7 +392,7 @@ xfs_log_mount( */ error = xfs_trans_ail_init(mp); if (error) { - cmn_err(CE_WARN, "XFS: AIL initialisation failed: error %d", error); + xfs_warn(mp, "AIL initialisation failed: error %d", error); goto out_free_log; } mp->m_log->l_ailp = mp->m_ail; @@ -413,7 +412,8 @@ xfs_log_mount( if (readonly) mp->m_flags |= XFS_MOUNT_RDONLY; if (error) { - cmn_err(CE_WARN, "XFS: log mount/recovery failed: error %d", error); + xfs_warn(mp, "log mount/recovery failed: error %d", + error); goto out_destroy_ail; } } @@ -542,10 +542,8 @@ xfs_log_unmount_write(xfs_mount_t *mp) */ } - if (error) { - xfs_fs_cmn_err(CE_ALERT, mp, - "xfs_log_unmount: unmount record failed"); - } + if (error) + xfs_alert(mp, "%s: unmount record failed", __func__); spin_lock(&log->l_icloglock); @@ -852,7 +850,7 @@ xlog_space_left( * In this case we just want to return the size of the * log as the amount of space left. */ - xfs_fs_cmn_err(CE_ALERT, log->l_mp, + xfs_alert(log->l_mp, "xlog_space_left: head behind tail\n" " tail_cycle = %d, tail_bytes = %d\n" " GH cycle = %d, GH bytes = %d", @@ -1001,7 +999,7 @@ xlog_alloc_log(xfs_mount_t *mp, log = kmem_zalloc(sizeof(xlog_t), KM_MAYFAIL); if (!log) { - xlog_warn("XFS: Log allocation failed: No memory!"); + xfs_warn(mp, "Log allocation failed: No memory!"); goto out; } @@ -1029,24 +1027,24 @@ xlog_alloc_log(xfs_mount_t *mp, if (xfs_sb_version_hassector(&mp->m_sb)) { log2_size = mp->m_sb.sb_logsectlog; if (log2_size < BBSHIFT) { - xlog_warn("XFS: Log sector size too small " - "(0x%x < 0x%x)", log2_size, BBSHIFT); + xfs_warn(mp, "Log sector size too small (0x%x < 0x%x)", + log2_size, BBSHIFT); goto out_free_log; } log2_size -= BBSHIFT; if (log2_size > mp->m_sectbb_log) { - xlog_warn("XFS: Log sector size too large " - "(0x%x > 0x%x)", log2_size, mp->m_sectbb_log); + xfs_warn(mp, "Log sector size too large (0x%x > 0x%x)", + log2_size, mp->m_sectbb_log); goto out_free_log; } /* for larger sector sizes, must have v2 or external log */ if (log2_size && log->l_logBBstart > 0 && !xfs_sb_version_haslogv2(&mp->m_sb)) { - - xlog_warn("XFS: log sector size (0x%x) invalid " - "for configuration.", log2_size); + xfs_warn(mp, + "log sector size (0x%x) invalid for configuration.", + log2_size); goto out_free_log; } } @@ -1563,38 +1561,36 @@ xlog_print_tic_res( "SWAPEXT" }; - xfs_fs_cmn_err(CE_WARN, mp, - "xfs_log_write: reservation summary:\n" - " trans type = %s (%u)\n" - " unit res = %d bytes\n" - " current res = %d bytes\n" - " total reg = %u bytes (o/flow = %u bytes)\n" - " ophdrs = %u (ophdr space = %u bytes)\n" - " ophdr + reg = %u bytes\n" - " num regions = %u\n", - ((ticket->t_trans_type <= 0 || - ticket->t_trans_type > XFS_TRANS_TYPE_MAX) ? - "bad-trans-type" : trans_type_str[ticket->t_trans_type-1]), - ticket->t_trans_type, - ticket->t_unit_res, - ticket->t_curr_res, - ticket->t_res_arr_sum, ticket->t_res_o_flow, - ticket->t_res_num_ophdrs, ophdr_spc, - ticket->t_res_arr_sum + - ticket->t_res_o_flow + ophdr_spc, - ticket->t_res_num); + xfs_warn(mp, + "xfs_log_write: reservation summary:\n" + " trans type = %s (%u)\n" + " unit res = %d bytes\n" + " current res = %d bytes\n" + " total reg = %u bytes (o/flow = %u bytes)\n" + " ophdrs = %u (ophdr space = %u bytes)\n" + " ophdr + reg = %u bytes\n" + " num regions = %u\n", + ((ticket->t_trans_type <= 0 || + ticket->t_trans_type > XFS_TRANS_TYPE_MAX) ? + "bad-trans-type" : trans_type_str[ticket->t_trans_type-1]), + ticket->t_trans_type, + ticket->t_unit_res, + ticket->t_curr_res, + ticket->t_res_arr_sum, ticket->t_res_o_flow, + ticket->t_res_num_ophdrs, ophdr_spc, + ticket->t_res_arr_sum + + ticket->t_res_o_flow + ophdr_spc, + ticket->t_res_num); for (i = 0; i < ticket->t_res_num; i++) { - uint r_type = ticket->t_res_arr[i].r_type; - cmn_err(CE_WARN, - "region[%u]: %s - %u bytes\n", - i, + uint r_type = ticket->t_res_arr[i].r_type; + xfs_warn(mp, "region[%u]: %s - %u bytes\n", i, ((r_type <= 0 || r_type > XLOG_REG_TYPE_MAX) ? "bad-rtype" : res_type_str[r_type-1]), ticket->t_res_arr[i].r_len); } - xfs_cmn_err(XFS_PTAG_LOGRES, CE_ALERT, mp, + xfs_alert_tag(mp, XFS_PTAG_LOGRES, "xfs_log_write: reservation ran out. Need to up reservation"); xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); } @@ -1682,7 +1678,7 @@ xlog_write_setup_ophdr( case XFS_LOG: break; default: - xfs_fs_cmn_err(CE_WARN, log->l_mp, + xfs_warn(log->l_mp, "Bad XFS transaction clientid 0x%x in ticket 0x%p", ophdr->oh_clientid, ticket); return NULL; @@ -2264,7 +2260,7 @@ xlog_state_do_callback( if (repeats > 5000) { flushcnt += repeats; repeats = 0; - xfs_fs_cmn_err(CE_WARN, log->l_mp, + xfs_warn(log->l_mp, "%s: possible infinite loop (%d iterations)", __func__, flushcnt); } @@ -3052,10 +3048,8 @@ xfs_log_force( int error; error = _xfs_log_force(mp, flags, NULL); - if (error) { - xfs_fs_cmn_err(CE_WARN, mp, "xfs_log_force: " - "error %d returned.", error); - } + if (error) + xfs_warn(mp, "%s: error %d returned.", __func__, error); } /* @@ -3204,10 +3198,8 @@ xfs_log_force_lsn( int error; error = _xfs_log_force_lsn(mp, lsn, flags, NULL); - if (error) { - xfs_fs_cmn_err(CE_WARN, mp, "xfs_log_force: " - "error %d returned.", error); - } + if (error) + xfs_warn(mp, "%s: error %d returned.", __func__, error); } /* @@ -3412,7 +3404,7 @@ xlog_verify_dest_ptr( } if (!good_ptr) - xlog_panic("xlog_verify_dest_ptr: invalid ptr"); + xfs_emerg(log->l_mp, "%s: invalid ptr", __func__); } STATIC void @@ -3448,16 +3440,16 @@ xlog_verify_tail_lsn(xlog_t *log, blocks = log->l_logBBsize - (log->l_prev_block - BLOCK_LSN(tail_lsn)); if (blocks < BTOBB(iclog->ic_offset)+BTOBB(log->l_iclog_hsize)) - xlog_panic("xlog_verify_tail_lsn: ran out of log space"); + xfs_emerg(log->l_mp, "%s: ran out of log space", __func__); } else { ASSERT(CYCLE_LSN(tail_lsn)+1 == log->l_prev_cycle); if (BLOCK_LSN(tail_lsn) == log->l_prev_block) - xlog_panic("xlog_verify_tail_lsn: tail wrapped"); + xfs_emerg(log->l_mp, "%s: tail wrapped", __func__); blocks = BLOCK_LSN(tail_lsn) - log->l_prev_block; if (blocks < BTOBB(iclog->ic_offset) + 1) - xlog_panic("xlog_verify_tail_lsn: ran out of log space"); + xfs_emerg(log->l_mp, "%s: ran out of log space", __func__); } } /* xlog_verify_tail_lsn */ @@ -3497,22 +3489,23 @@ xlog_verify_iclog(xlog_t *log, icptr = log->l_iclog; for (i=0; i < log->l_iclog_bufs; i++) { if (icptr == NULL) - xlog_panic("xlog_verify_iclog: invalid ptr"); + xfs_emerg(log->l_mp, "%s: invalid ptr", __func__); icptr = icptr->ic_next; } if (icptr != log->l_iclog) - xlog_panic("xlog_verify_iclog: corrupt iclog ring"); + xfs_emerg(log->l_mp, "%s: corrupt iclog ring", __func__); spin_unlock(&log->l_icloglock); /* check log magic numbers */ if (be32_to_cpu(iclog->ic_header.h_magicno) != XLOG_HEADER_MAGIC_NUM) - xlog_panic("xlog_verify_iclog: invalid magic num"); + xfs_emerg(log->l_mp, "%s: invalid magic num", __func__); ptr = (xfs_caddr_t) &iclog->ic_header; for (ptr += BBSIZE; ptr < ((xfs_caddr_t)&iclog->ic_header) + count; ptr += BBSIZE) { if (be32_to_cpu(*(__be32 *)ptr) == XLOG_HEADER_MAGIC_NUM) - xlog_panic("xlog_verify_iclog: unexpected magic num"); + xfs_emerg(log->l_mp, "%s: unexpected magic num", + __func__); } /* check fields */ @@ -3542,9 +3535,10 @@ xlog_verify_iclog(xlog_t *log, } } if (clientid != XFS_TRANSACTION && clientid != XFS_LOG) - cmn_err(CE_WARN, "xlog_verify_iclog: " - "invalid clientid %d op 0x%p offset 0x%lx", - clientid, ophead, (unsigned long)field_offset); + xfs_warn(log->l_mp, + "%s: invalid clientid %d op 0x%p offset 0x%lx", + __func__, clientid, ophead, + (unsigned long)field_offset); /* check length */ field_offset = (__psint_t) diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h index d5f8be8f4bf6..15dbf1f9c2be 100644 --- a/fs/xfs/xfs_log_priv.h +++ b/fs/xfs/xfs_log_priv.h @@ -87,10 +87,6 @@ static inline uint xlog_get_client_id(__be32 i) return be32_to_cpu(i) >> 24; } -#define xlog_panic(args...) cmn_err(CE_PANIC, ## args) -#define xlog_exit(args...) cmn_err(CE_PANIC, ## args) -#define xlog_warn(args...) cmn_err(CE_WARN, ## args) - /* * In core log state */ diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index aa0ebb776903..0c4a5618e7af 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -92,7 +92,7 @@ xlog_get_bp( int nbblks) { if (!xlog_buf_bbcount_valid(log, nbblks)) { - xlog_warn("XFS: Invalid block length (0x%x) given for buffer", + xfs_warn(log->l_mp, "Invalid block length (0x%x) for buffer", nbblks); XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_HIGH, log->l_mp); return NULL; @@ -160,7 +160,7 @@ xlog_bread_noalign( int error; if (!xlog_buf_bbcount_valid(log, nbblks)) { - xlog_warn("XFS: Invalid block length (0x%x) given for buffer", + xfs_warn(log->l_mp, "Invalid block length (0x%x) for buffer", nbblks); XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_HIGH, log->l_mp); return EFSCORRUPTED; @@ -219,7 +219,7 @@ xlog_bwrite( int error; if (!xlog_buf_bbcount_valid(log, nbblks)) { - xlog_warn("XFS: Invalid block length (0x%x) given for buffer", + xfs_warn(log->l_mp, "Invalid block length (0x%x) for buffer", nbblks); XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_HIGH, log->l_mp); return EFSCORRUPTED; @@ -254,9 +254,9 @@ xlog_header_check_dump( xfs_mount_t *mp, xlog_rec_header_t *head) { - cmn_err(CE_DEBUG, "%s: SB : uuid = %pU, fmt = %d\n", + xfs_debug(mp, "%s: SB : uuid = %pU, fmt = %d\n", __func__, &mp->m_sb.sb_uuid, XLOG_FMT); - cmn_err(CE_DEBUG, " log : uuid = %pU, fmt = %d\n", + xfs_debug(mp, " log : uuid = %pU, fmt = %d\n", &head->h_fs_uuid, be32_to_cpu(head->h_fmt)); } #else @@ -279,15 +279,15 @@ xlog_header_check_recover( * a dirty log created in IRIX. */ if (unlikely(be32_to_cpu(head->h_fmt) != XLOG_FMT)) { - xlog_warn( - "XFS: dirty log written in incompatible format - can't recover"); + xfs_warn(mp, + "dirty log written in incompatible format - can't recover"); xlog_header_check_dump(mp, head); XFS_ERROR_REPORT("xlog_header_check_recover(1)", XFS_ERRLEVEL_HIGH, mp); return XFS_ERROR(EFSCORRUPTED); } else if (unlikely(!uuid_equal(&mp->m_sb.sb_uuid, &head->h_fs_uuid))) { - xlog_warn( - "XFS: dirty log entry has mismatched uuid - can't recover"); + xfs_warn(mp, + "dirty log entry has mismatched uuid - can't recover"); xlog_header_check_dump(mp, head); XFS_ERROR_REPORT("xlog_header_check_recover(2)", XFS_ERRLEVEL_HIGH, mp); @@ -312,9 +312,9 @@ xlog_header_check_mount( * h_fs_uuid is nil, we assume this log was last mounted * by IRIX and continue. */ - xlog_warn("XFS: nil uuid in log - IRIX style log"); + xfs_warn(mp, "nil uuid in log - IRIX style log"); } else if (unlikely(!uuid_equal(&mp->m_sb.sb_uuid, &head->h_fs_uuid))) { - xlog_warn("XFS: log has mismatched uuid - can't recover"); + xfs_warn(mp, "log has mismatched uuid - can't recover"); xlog_header_check_dump(mp, head); XFS_ERROR_REPORT("xlog_header_check_mount", XFS_ERRLEVEL_HIGH, mp); @@ -490,8 +490,8 @@ xlog_find_verify_log_record( for (i = (*last_blk) - 1; i >= 0; i--) { if (i < start_blk) { /* valid log record not found */ - xlog_warn( - "XFS: Log inconsistent (didn't find previous header)"); + xfs_warn(log->l_mp, + "Log inconsistent (didn't find previous header)"); ASSERT(0); error = XFS_ERROR(EIO); goto out; @@ -591,12 +591,12 @@ xlog_find_head( * mkfs etc write a dummy unmount record to a fresh * log so we can store the uuid in there */ - xlog_warn("XFS: totally zeroed log"); + xfs_warn(log->l_mp, "totally zeroed log"); } return 0; } else if (error) { - xlog_warn("XFS: empty log check failed"); + xfs_warn(log->l_mp, "empty log check failed"); return error; } @@ -819,7 +819,7 @@ validate_head: xlog_put_bp(bp); if (error) - xlog_warn("XFS: failed to find log head"); + xfs_warn(log->l_mp, "failed to find log head"); return error; } @@ -912,7 +912,7 @@ xlog_find_tail( } } if (!found) { - xlog_warn("XFS: xlog_find_tail: couldn't find sync record"); + xfs_warn(log->l_mp, "%s: couldn't find sync record", __func__); ASSERT(0); return XFS_ERROR(EIO); } @@ -1028,7 +1028,7 @@ done: xlog_put_bp(bp); if (error) - xlog_warn("XFS: failed to locate log tail"); + xfs_warn(log->l_mp, "failed to locate log tail"); return error; } @@ -1092,7 +1092,8 @@ xlog_find_zeroed( * the first block must be 1. If it's not, maybe we're * not looking at a log... Bail out. */ - xlog_warn("XFS: Log inconsistent or not a log (last==0, first!=1)"); + xfs_warn(log->l_mp, + "Log inconsistent or not a log (last==0, first!=1)"); return XFS_ERROR(EINVAL); } @@ -1506,8 +1507,8 @@ xlog_recover_add_to_trans( if (list_empty(&trans->r_itemq)) { /* we need to catch log corruptions here */ if (*(uint *)dp != XFS_TRANS_HEADER_MAGIC) { - xlog_warn("XFS: xlog_recover_add_to_trans: " - "bad header magic number"); + xfs_warn(log->l_mp, "%s: bad header magic number", + __func__); ASSERT(0); return XFS_ERROR(EIO); } @@ -1534,8 +1535,8 @@ xlog_recover_add_to_trans( if (item->ri_total == 0) { /* first region to be added */ if (in_f->ilf_size == 0 || in_f->ilf_size > XLOG_MAX_REGIONS_IN_ITEM) { - xlog_warn( - "XFS: bad number of regions (%d) in inode log format", + xfs_warn(log->l_mp, + "bad number of regions (%d) in inode log format", in_f->ilf_size); ASSERT(0); return XFS_ERROR(EIO); @@ -1592,8 +1593,9 @@ xlog_recover_reorder_trans( list_move_tail(&item->ri_list, &trans->r_itemq); break; default: - xlog_warn( - "XFS: xlog_recover_reorder_trans: unrecognized type of log operation"); + xfs_warn(log->l_mp, + "%s: unrecognized type of log operation", + __func__); ASSERT(0); return XFS_ERROR(EIO); } @@ -1803,8 +1805,9 @@ xlog_recover_do_inode_buffer( logged_nextp = item->ri_buf[item_index].i_addr + next_unlinked_offset - reg_buf_offset; if (unlikely(*logged_nextp == 0)) { - xfs_fs_cmn_err(CE_ALERT, mp, - "bad inode buffer log record (ptr = 0x%p, bp = 0x%p). XFS trying to replay bad (0) inode di_next_unlinked field", + xfs_alert(mp, + "Bad inode buffer log record (ptr = 0x%p, bp = 0x%p). " + "Trying to replay bad (0) inode di_next_unlinked field.", item, bp); XFS_ERROR_REPORT("xlog_recover_do_inode_buf", XFS_ERRLEVEL_LOW, mp); @@ -1863,17 +1866,17 @@ xlog_recover_do_reg_buffer( if (buf_f->blf_flags & (XFS_BLF_UDQUOT_BUF|XFS_BLF_PDQUOT_BUF|XFS_BLF_GDQUOT_BUF)) { if (item->ri_buf[i].i_addr == NULL) { - cmn_err(CE_ALERT, + xfs_alert(mp, "XFS: NULL dquot in %s.", __func__); goto next; } if (item->ri_buf[i].i_len < sizeof(xfs_disk_dquot_t)) { - cmn_err(CE_ALERT, + xfs_alert(mp, "XFS: dquot too small (%d) in %s.", item->ri_buf[i].i_len, __func__); goto next; } - error = xfs_qm_dqcheck(item->ri_buf[i].i_addr, + error = xfs_qm_dqcheck(mp, item->ri_buf[i].i_addr, -1, 0, XFS_QMOPT_DOWARN, "dquot_buf_recover"); if (error) @@ -1898,6 +1901,7 @@ xlog_recover_do_reg_buffer( */ int xfs_qm_dqcheck( + struct xfs_mount *mp, xfs_disk_dquot_t *ddq, xfs_dqid_t id, uint type, /* used only when IO_dorepair is true */ @@ -1924,14 +1928,14 @@ xfs_qm_dqcheck( */ if (be16_to_cpu(ddq->d_magic) != XFS_DQUOT_MAGIC) { if (flags & XFS_QMOPT_DOWARN) - cmn_err(CE_ALERT, + xfs_alert(mp, "%s : XFS dquot ID 0x%x, magic 0x%x != 0x%x", str, id, be16_to_cpu(ddq->d_magic), XFS_DQUOT_MAGIC); errs++; } if (ddq->d_version != XFS_DQUOT_VERSION) { if (flags & XFS_QMOPT_DOWARN) - cmn_err(CE_ALERT, + xfs_alert(mp, "%s : XFS dquot ID 0x%x, version 0x%x != 0x%x", str, id, ddq->d_version, XFS_DQUOT_VERSION); errs++; @@ -1941,7 +1945,7 @@ xfs_qm_dqcheck( ddq->d_flags != XFS_DQ_PROJ && ddq->d_flags != XFS_DQ_GROUP) { if (flags & XFS_QMOPT_DOWARN) - cmn_err(CE_ALERT, + xfs_alert(mp, "%s : XFS dquot ID 0x%x, unknown flags 0x%x", str, id, ddq->d_flags); errs++; @@ -1949,7 +1953,7 @@ xfs_qm_dqcheck( if (id != -1 && id != be32_to_cpu(ddq->d_id)) { if (flags & XFS_QMOPT_DOWARN) - cmn_err(CE_ALERT, + xfs_alert(mp, "%s : ondisk-dquot 0x%p, ID mismatch: " "0x%x expected, found id 0x%x", str, ddq, id, be32_to_cpu(ddq->d_id)); @@ -1962,9 +1966,8 @@ xfs_qm_dqcheck( be64_to_cpu(ddq->d_blk_softlimit)) { if (!ddq->d_btimer) { if (flags & XFS_QMOPT_DOWARN) - cmn_err(CE_ALERT, - "%s : Dquot ID 0x%x (0x%p) " - "BLK TIMER NOT STARTED", + xfs_alert(mp, + "%s : Dquot ID 0x%x (0x%p) BLK TIMER NOT STARTED", str, (int)be32_to_cpu(ddq->d_id), ddq); errs++; } @@ -1974,9 +1977,8 @@ xfs_qm_dqcheck( be64_to_cpu(ddq->d_ino_softlimit)) { if (!ddq->d_itimer) { if (flags & XFS_QMOPT_DOWARN) - cmn_err(CE_ALERT, - "%s : Dquot ID 0x%x (0x%p) " - "INODE TIMER NOT STARTED", + xfs_alert(mp, + "%s : Dquot ID 0x%x (0x%p) INODE TIMER NOT STARTED", str, (int)be32_to_cpu(ddq->d_id), ddq); errs++; } @@ -1986,9 +1988,8 @@ xfs_qm_dqcheck( be64_to_cpu(ddq->d_rtb_softlimit)) { if (!ddq->d_rtbtimer) { if (flags & XFS_QMOPT_DOWARN) - cmn_err(CE_ALERT, - "%s : Dquot ID 0x%x (0x%p) " - "RTBLK TIMER NOT STARTED", + xfs_alert(mp, + "%s : Dquot ID 0x%x (0x%p) RTBLK TIMER NOT STARTED", str, (int)be32_to_cpu(ddq->d_id), ddq); errs++; } @@ -1999,7 +2000,7 @@ xfs_qm_dqcheck( return errs; if (flags & XFS_QMOPT_DOWARN) - cmn_err(CE_NOTE, "Re-initializing dquot ID 0x%x", id); + xfs_notice(mp, "Re-initializing dquot ID 0x%x", id); /* * Typically, a repair is only requested by quotacheck. @@ -2218,9 +2219,9 @@ xlog_recover_inode_pass2( */ if (unlikely(be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC)) { xfs_buf_relse(bp); - xfs_fs_cmn_err(CE_ALERT, mp, - "xfs_inode_recover: Bad inode magic number, dino ptr = 0x%p, dino bp = 0x%p, ino = %Ld", - dip, bp, in_f->ilf_ino); + xfs_alert(mp, + "%s: Bad inode magic number, dip = 0x%p, dino bp = 0x%p, ino = %Ld", + __func__, dip, bp, in_f->ilf_ino); XFS_ERROR_REPORT("xlog_recover_inode_pass2(1)", XFS_ERRLEVEL_LOW, mp); error = EFSCORRUPTED; @@ -2229,9 +2230,9 @@ xlog_recover_inode_pass2( dicp = item->ri_buf[1].i_addr; if (unlikely(dicp->di_magic != XFS_DINODE_MAGIC)) { xfs_buf_relse(bp); - xfs_fs_cmn_err(CE_ALERT, mp, - "xfs_inode_recover: Bad inode log record, rec ptr 0x%p, ino %Ld", - item, in_f->ilf_ino); + xfs_alert(mp, + "%s: Bad inode log record, rec ptr 0x%p, ino %Ld", + __func__, item, in_f->ilf_ino); XFS_ERROR_REPORT("xlog_recover_inode_pass2(2)", XFS_ERRLEVEL_LOW, mp); error = EFSCORRUPTED; @@ -2263,9 +2264,10 @@ xlog_recover_inode_pass2( XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(3)", XFS_ERRLEVEL_LOW, mp, dicp); xfs_buf_relse(bp); - xfs_fs_cmn_err(CE_ALERT, mp, - "xfs_inode_recover: Bad regular inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", - item, dip, bp, in_f->ilf_ino); + xfs_alert(mp, + "%s: Bad regular inode log record, rec ptr 0x%p, " + "ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", + __func__, item, dip, bp, in_f->ilf_ino); error = EFSCORRUPTED; goto error; } @@ -2276,9 +2278,10 @@ xlog_recover_inode_pass2( XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(4)", XFS_ERRLEVEL_LOW, mp, dicp); xfs_buf_relse(bp); - xfs_fs_cmn_err(CE_ALERT, mp, - "xfs_inode_recover: Bad dir inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", - item, dip, bp, in_f->ilf_ino); + xfs_alert(mp, + "%s: Bad dir inode log record, rec ptr 0x%p, " + "ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", + __func__, item, dip, bp, in_f->ilf_ino); error = EFSCORRUPTED; goto error; } @@ -2287,9 +2290,10 @@ xlog_recover_inode_pass2( XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(5)", XFS_ERRLEVEL_LOW, mp, dicp); xfs_buf_relse(bp); - xfs_fs_cmn_err(CE_ALERT, mp, - "xfs_inode_recover: Bad inode log record, rec ptr 0x%p, dino ptr 0x%p, dino bp 0x%p, ino %Ld, total extents = %d, nblocks = %Ld", - item, dip, bp, in_f->ilf_ino, + xfs_alert(mp, + "%s: Bad inode log record, rec ptr 0x%p, dino ptr 0x%p, " + "dino bp 0x%p, ino %Ld, total extents = %d, nblocks = %Ld", + __func__, item, dip, bp, in_f->ilf_ino, dicp->di_nextents + dicp->di_anextents, dicp->di_nblocks); error = EFSCORRUPTED; @@ -2299,8 +2303,9 @@ xlog_recover_inode_pass2( XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(6)", XFS_ERRLEVEL_LOW, mp, dicp); xfs_buf_relse(bp); - xfs_fs_cmn_err(CE_ALERT, mp, - "xfs_inode_recover: Bad inode log rec ptr 0x%p, dino ptr 0x%p, dino bp 0x%p, ino %Ld, forkoff 0x%x", + xfs_alert(mp, + "%s: Bad inode log record, rec ptr 0x%p, dino ptr 0x%p, " + "dino bp 0x%p, ino %Ld, forkoff 0x%x", __func__, item, dip, bp, in_f->ilf_ino, dicp->di_forkoff); error = EFSCORRUPTED; goto error; @@ -2309,9 +2314,9 @@ xlog_recover_inode_pass2( XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(7)", XFS_ERRLEVEL_LOW, mp, dicp); xfs_buf_relse(bp); - xfs_fs_cmn_err(CE_ALERT, mp, - "xfs_inode_recover: Bad inode log record length %d, rec ptr 0x%p", - item->ri_buf[1].i_len, item); + xfs_alert(mp, + "%s: Bad inode log record length %d, rec ptr 0x%p", + __func__, item->ri_buf[1].i_len, item); error = EFSCORRUPTED; goto error; } @@ -2398,7 +2403,7 @@ xlog_recover_inode_pass2( break; default: - xlog_warn("XFS: xlog_recover_inode_pass2: Invalid flag"); + xfs_warn(log->l_mp, "%s: Invalid flag", __func__); ASSERT(0); xfs_buf_relse(bp); error = EIO; @@ -2467,13 +2472,11 @@ xlog_recover_dquot_pass2( recddq = item->ri_buf[1].i_addr; if (recddq == NULL) { - cmn_err(CE_ALERT, - "XFS: NULL dquot in %s.", __func__); + xfs_alert(log->l_mp, "NULL dquot in %s.", __func__); return XFS_ERROR(EIO); } if (item->ri_buf[1].i_len < sizeof(xfs_disk_dquot_t)) { - cmn_err(CE_ALERT, - "XFS: dquot too small (%d) in %s.", + xfs_alert(log->l_mp, "dquot too small (%d) in %s.", item->ri_buf[1].i_len, __func__); return XFS_ERROR(EIO); } @@ -2498,12 +2501,10 @@ xlog_recover_dquot_pass2( */ dq_f = item->ri_buf[0].i_addr; ASSERT(dq_f); - if ((error = xfs_qm_dqcheck(recddq, - dq_f->qlf_id, - 0, XFS_QMOPT_DOWARN, - "xlog_recover_dquot_pass2 (log copy)"))) { + error = xfs_qm_dqcheck(mp, recddq, dq_f->qlf_id, 0, XFS_QMOPT_DOWARN, + "xlog_recover_dquot_pass2 (log copy)"); + if (error) return XFS_ERROR(EIO); - } ASSERT(dq_f->qlf_len == 1); error = xfs_read_buf(mp, mp->m_ddev_targp, @@ -2523,8 +2524,9 @@ xlog_recover_dquot_pass2( * was among a chunk of dquots created earlier, and we did some * minimal initialization then. */ - if (xfs_qm_dqcheck(ddq, dq_f->qlf_id, 0, XFS_QMOPT_DOWARN, - "xlog_recover_dquot_pass2")) { + error = xfs_qm_dqcheck(mp, ddq, dq_f->qlf_id, 0, XFS_QMOPT_DOWARN, + "xlog_recover_dquot_pass2"); + if (error) { xfs_buf_relse(bp); return XFS_ERROR(EIO); } @@ -2676,9 +2678,8 @@ xlog_recover_commit_pass1( /* nothing to do in pass 1 */ return 0; default: - xlog_warn( - "XFS: invalid item type (%d) xlog_recover_commit_pass1", - ITEM_TYPE(item)); + xfs_warn(log->l_mp, "%s: invalid item type (%d)", + __func__, ITEM_TYPE(item)); ASSERT(0); return XFS_ERROR(EIO); } @@ -2707,9 +2708,8 @@ xlog_recover_commit_pass2( /* nothing to do in pass2 */ return 0; default: - xlog_warn( - "XFS: invalid item type (%d) xlog_recover_commit_pass2", - ITEM_TYPE(item)); + xfs_warn(log->l_mp, "%s: invalid item type (%d)", + __func__, ITEM_TYPE(item)); ASSERT(0); return XFS_ERROR(EIO); } @@ -2751,10 +2751,11 @@ xlog_recover_commit_trans( STATIC int xlog_recover_unmount_trans( + struct log *log, xlog_recover_t *trans) { /* Do nothing now */ - xlog_warn("XFS: xlog_recover_unmount_trans: Unmount LR"); + xfs_warn(log->l_mp, "%s: Unmount LR", __func__); return 0; } @@ -2797,8 +2798,8 @@ xlog_recover_process_data( dp += sizeof(xlog_op_header_t); if (ohead->oh_clientid != XFS_TRANSACTION && ohead->oh_clientid != XFS_LOG) { - xlog_warn( - "XFS: xlog_recover_process_data: bad clientid"); + xfs_warn(log->l_mp, "%s: bad clientid 0x%x", + __func__, ohead->oh_clientid); ASSERT(0); return (XFS_ERROR(EIO)); } @@ -2811,8 +2812,8 @@ xlog_recover_process_data( be64_to_cpu(rhead->h_lsn)); } else { if (dp + be32_to_cpu(ohead->oh_len) > lp) { - xlog_warn( - "XFS: xlog_recover_process_data: bad length"); + xfs_warn(log->l_mp, "%s: bad length 0x%x", + __func__, be32_to_cpu(ohead->oh_len)); WARN_ON(1); return (XFS_ERROR(EIO)); } @@ -2825,7 +2826,7 @@ xlog_recover_process_data( trans, pass); break; case XLOG_UNMOUNT_TRANS: - error = xlog_recover_unmount_trans(trans); + error = xlog_recover_unmount_trans(log, trans); break; case XLOG_WAS_CONT_TRANS: error = xlog_recover_add_to_cont_trans(log, @@ -2833,8 +2834,8 @@ xlog_recover_process_data( be32_to_cpu(ohead->oh_len)); break; case XLOG_START_TRANS: - xlog_warn( - "XFS: xlog_recover_process_data: bad transaction"); + xfs_warn(log->l_mp, "%s: bad transaction", + __func__); ASSERT(0); error = XFS_ERROR(EIO); break; @@ -2844,8 +2845,8 @@ xlog_recover_process_data( dp, be32_to_cpu(ohead->oh_len)); break; default: - xlog_warn( - "XFS: xlog_recover_process_data: bad flag"); + xfs_warn(log->l_mp, "%s: bad flag 0x%x", + __func__, flags); ASSERT(0); error = XFS_ERROR(EIO); break; @@ -3030,8 +3031,7 @@ xlog_recover_clear_agi_bucket( out_abort: xfs_trans_cancel(tp, XFS_TRANS_ABORT); out_error: - xfs_fs_cmn_err(CE_WARN, mp, "xlog_recover_clear_agi_bucket: " - "failed to clear agi %d. Continuing.", agno); + xfs_warn(mp, "%s: failed to clear agi %d. Continuing.", __func__, agno); return; } @@ -3282,7 +3282,7 @@ xlog_valid_rec_header( if (unlikely( (!rhead->h_version || (be32_to_cpu(rhead->h_version) & (~XLOG_VERSION_OKBITS))))) { - xlog_warn("XFS: %s: unrecognised log version (%d).", + xfs_warn(log->l_mp, "%s: unrecognised log version (%d).", __func__, be32_to_cpu(rhead->h_version)); return XFS_ERROR(EIO); } @@ -3740,10 +3740,9 @@ xlog_recover( return error; } - cmn_err(CE_NOTE, - "Starting XFS recovery on filesystem: %s (logdev: %s)", - log->l_mp->m_fsname, log->l_mp->m_logname ? - log->l_mp->m_logname : "internal"); + xfs_notice(log->l_mp, "Starting recovery (logdev: %s)", + log->l_mp->m_logname ? log->l_mp->m_logname + : "internal"); error = xlog_do_recover(log, head_blk, tail_blk); log->l_flags |= XLOG_RECOVERY_NEEDED; @@ -3776,9 +3775,7 @@ xlog_recover_finish( int error; error = xlog_recover_process_efis(log); if (error) { - cmn_err(CE_ALERT, - "Failed to recover EFIs on filesystem: %s", - log->l_mp->m_fsname); + xfs_alert(log->l_mp, "Failed to recover EFIs"); return error; } /* @@ -3793,15 +3790,12 @@ xlog_recover_finish( xlog_recover_check_summary(log); - cmn_err(CE_NOTE, - "Ending XFS recovery on filesystem: %s (logdev: %s)", - log->l_mp->m_fsname, log->l_mp->m_logname ? - log->l_mp->m_logname : "internal"); + xfs_notice(log->l_mp, "Ending recovery (logdev: %s)", + log->l_mp->m_logname ? log->l_mp->m_logname + : "internal"); log->l_flags &= ~XLOG_RECOVERY_NEEDED; } else { - cmn_err(CE_DEBUG, - "Ending clean XFS mount for filesystem: %s\n", - log->l_mp->m_fsname); + xfs_info(log->l_mp, "Ending clean mount"); } return 0; } @@ -3834,10 +3828,8 @@ xlog_recover_check_summary( for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) { error = xfs_read_agf(mp, NULL, agno, 0, &agfbp); if (error) { - xfs_fs_cmn_err(CE_ALERT, mp, - "xlog_recover_check_summary(agf)" - "agf read failed agno %d error %d", - agno, error); + xfs_alert(mp, "%s agf read failed agno %d error %d", + __func__, agno, error); } else { agfp = XFS_BUF_TO_AGF(agfbp); freeblks += be32_to_cpu(agfp->agf_freeblks) + @@ -3846,7 +3838,10 @@ xlog_recover_check_summary( } error = xfs_read_agi(mp, NULL, agno, &agibp); - if (!error) { + if (error) { + xfs_alert(mp, "%s agi read failed agno %d error %d", + __func__, agno, error); + } else { struct xfs_agi *agi = XFS_BUF_TO_AGI(agibp); itotal += be32_to_cpu(agi->agi_count); diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h index 9bb6eda4cd21..a595f29567fe 100644 --- a/fs/xfs/xfs_quota.h +++ b/fs/xfs/xfs_quota.h @@ -382,7 +382,8 @@ static inline int xfs_qm_sync(struct xfs_mount *mp, int flags) xfs_trans_reserve_quota_bydquots(tp, mp, ud, gd, nb, ni, \ f | XFS_QMOPT_RES_REGBLKS) -extern int xfs_qm_dqcheck(xfs_disk_dquot_t *, xfs_dqid_t, uint, uint, char *); +extern int xfs_qm_dqcheck(struct xfs_mount *, xfs_disk_dquot_t *, + xfs_dqid_t, uint, uint, char *); extern int xfs_mount_reset_sbqflags(struct xfs_mount *); #endif /* __KERNEL__ */ -- cgit From 6a19d9393a5402e69fc52f5da8a828b8499a8265 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Mon, 7 Mar 2011 10:02:35 +1100 Subject: xfs: convert xfs_cmn_err to xfs_alert_tag Continue the conversion of the old cmn_err interface be converting all the conditional panic tag errors to xfs_alert_tag() and then removing xfs_cmn_err(). Signed-off-by: Dave Chinner Reviewed-by: Alex Elder Reviewed-by: Christoph Hellwig --- fs/xfs/support/debug.c | 28 ---------------------------- fs/xfs/support/debug.h | 2 -- fs/xfs/xfs_bmap.c | 2 +- fs/xfs/xfs_error.c | 5 ++--- fs/xfs/xfs_error.h | 6 ++---- fs/xfs/xfs_inode.c | 40 ++++++++++++++++++++-------------------- fs/xfs/xfs_iomap.c | 2 +- fs/xfs/xfs_rw.c | 23 +++++++++-------------- fs/xfs/xfs_trans_ail.c | 2 +- 9 files changed, 36 insertions(+), 74 deletions(-) (limited to 'fs') diff --git a/fs/xfs/support/debug.c b/fs/xfs/support/debug.c index 0df88897ef84..feaca739d5cc 100644 --- a/fs/xfs/support/debug.c +++ b/fs/xfs/support/debug.c @@ -64,34 +64,6 @@ xfs_fs_cmn_err( BUG_ON(strncmp(lvl, KERN_EMERG, strlen(KERN_EMERG)) == 0); } -/* All callers to xfs_cmn_err use CE_ALERT, so don't bother testing lvl */ -void -xfs_cmn_err( - int panic_tag, - const char *lvl, - struct xfs_mount *mp, - const char *fmt, - ...) -{ - struct va_format vaf; - va_list args; - int do_panic = 0; - - if (xfs_panic_mask && (xfs_panic_mask & panic_tag)) { - printk(KERN_ALERT "XFS: Transforming an alert into a BUG."); - do_panic = 1; - } - - va_start(args, fmt); - vaf.fmt = fmt; - vaf.va = &args; - - printk(KERN_ALERT "Filesystem %s: %pV", mp->m_fsname, &vaf); - va_end(args); - - BUG_ON(do_panic); -} - void assfail(char *expr, char *file, int line) { diff --git a/fs/xfs/support/debug.h b/fs/xfs/support/debug.h index 05699f67d475..eaeaa17ef4b8 100644 --- a/fs/xfs/support/debug.h +++ b/fs/xfs/support/debug.h @@ -33,8 +33,6 @@ void cmn_err(const char *lvl, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); void xfs_fs_cmn_err( const char *lvl, struct xfs_mount *mp, const char *fmt, ...) __attribute__ ((format (printf, 3, 4))); -void xfs_cmn_err( int panic_tag, const char *lvl, struct xfs_mount *mp, - const char *fmt, ...) __attribute__ ((format (printf, 4, 5))); extern void assfail(char *expr, char *f, int l); diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index e7b441db0530..451b4484795d 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -3526,7 +3526,7 @@ xfs_bmap_search_extents( if (unlikely(!(gotp->br_startblock) && (*lastxp != NULLEXTNUM) && !(XFS_IS_REALTIME_INODE(ip) && fork == XFS_DATA_FORK))) { - xfs_cmn_err(XFS_PTAG_FSBLOCK_ZERO, CE_ALERT, ip->i_mount, + xfs_alert_tag(ip->i_mount, XFS_PTAG_FSBLOCK_ZERO, "Access to block zero in inode %llu " "start_block: %llx start_off: %llx " "blkcnt: %llx extent-state: %x lastx: %x\n", diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c index 4c7db74a05f7..34f0e2d264ea 100644 --- a/fs/xfs/xfs_error.c +++ b/fs/xfs/xfs_error.c @@ -162,9 +162,8 @@ xfs_error_report( inst_t *ra) { if (level <= xfs_error_level) { - xfs_cmn_err(XFS_PTAG_ERROR_REPORT, - CE_ALERT, mp, - "XFS internal error %s at line %d of file %s. Caller 0x%p\n", + xfs_alert_tag(mp, XFS_PTAG_ERROR_REPORT, + "Internal error %s at line %d of file %s. Caller 0x%p\n", tag, linenum, filename, ra); xfs_stack_trace(); diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h index 10dce5475f02..e1ba2d2565b3 100644 --- a/fs/xfs/xfs_error.h +++ b/fs/xfs/xfs_error.h @@ -145,10 +145,8 @@ extern int xfs_errortag_clearall(struct xfs_mount *mp, int loud); #endif /* DEBUG */ /* - * XFS panic tags -- allow a call to xfs_cmn_err() be turned into - * a panic by setting xfs_panic_mask in a - * sysctl. update xfs_max[XFS_PARAM] if - * more are added. + * XFS panic tags -- allow a call to xfs_alert_tag() be turned into + * a panic by setting xfs_panic_mask in a sysctl. */ #define XFS_NO_PTAG 0 #define XFS_PTAG_IFLUSH 0x00000001 diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index c39278b6c871..bf9ca579365c 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -2940,16 +2940,16 @@ xfs_iflush_int( if (XFS_TEST_ERROR(be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC, mp, XFS_ERRTAG_IFLUSH_1, XFS_RANDOM_IFLUSH_1)) { - xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp, - "xfs_iflush: Bad inode %Lu magic number 0x%x, ptr 0x%p", - ip->i_ino, be16_to_cpu(dip->di_magic), dip); + xfs_alert_tag(mp, XFS_PTAG_IFLUSH, + "%s: Bad inode %Lu magic number 0x%x, ptr 0x%p", + __func__, ip->i_ino, be16_to_cpu(dip->di_magic), dip); goto corrupt_out; } if (XFS_TEST_ERROR(ip->i_d.di_magic != XFS_DINODE_MAGIC, mp, XFS_ERRTAG_IFLUSH_2, XFS_RANDOM_IFLUSH_2)) { - xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp, - "xfs_iflush: Bad inode %Lu, ptr 0x%p, magic number 0x%x", - ip->i_ino, ip, ip->i_d.di_magic); + xfs_alert_tag(mp, XFS_PTAG_IFLUSH, + "%s: Bad inode %Lu, ptr 0x%p, magic number 0x%x", + __func__, ip->i_ino, ip, ip->i_d.di_magic); goto corrupt_out; } if ((ip->i_d.di_mode & S_IFMT) == S_IFREG) { @@ -2957,9 +2957,9 @@ xfs_iflush_int( (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS) && (ip->i_d.di_format != XFS_DINODE_FMT_BTREE), mp, XFS_ERRTAG_IFLUSH_3, XFS_RANDOM_IFLUSH_3)) { - xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp, - "xfs_iflush: Bad regular inode %Lu, ptr 0x%p", - ip->i_ino, ip); + xfs_alert_tag(mp, XFS_PTAG_IFLUSH, + "%s: Bad regular inode %Lu, ptr 0x%p", + __func__, ip->i_ino, ip); goto corrupt_out; } } else if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) { @@ -2968,28 +2968,28 @@ xfs_iflush_int( (ip->i_d.di_format != XFS_DINODE_FMT_BTREE) && (ip->i_d.di_format != XFS_DINODE_FMT_LOCAL), mp, XFS_ERRTAG_IFLUSH_4, XFS_RANDOM_IFLUSH_4)) { - xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp, - "xfs_iflush: Bad directory inode %Lu, ptr 0x%p", - ip->i_ino, ip); + xfs_alert_tag(mp, XFS_PTAG_IFLUSH, + "%s: Bad directory inode %Lu, ptr 0x%p", + __func__, ip->i_ino, ip); goto corrupt_out; } } if (XFS_TEST_ERROR(ip->i_d.di_nextents + ip->i_d.di_anextents > ip->i_d.di_nblocks, mp, XFS_ERRTAG_IFLUSH_5, XFS_RANDOM_IFLUSH_5)) { - xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp, - "xfs_iflush: detected corrupt incore inode %Lu, total extents = %d, nblocks = %Ld, ptr 0x%p", - ip->i_ino, + xfs_alert_tag(mp, XFS_PTAG_IFLUSH, + "%s: detected corrupt incore inode %Lu, " + "total extents = %d, nblocks = %Ld, ptr 0x%p", + __func__, ip->i_ino, ip->i_d.di_nextents + ip->i_d.di_anextents, - ip->i_d.di_nblocks, - ip); + ip->i_d.di_nblocks, ip); goto corrupt_out; } if (XFS_TEST_ERROR(ip->i_d.di_forkoff > mp->m_sb.sb_inodesize, mp, XFS_ERRTAG_IFLUSH_6, XFS_RANDOM_IFLUSH_6)) { - xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp, - "xfs_iflush: bad inode %Lu, forkoff 0x%x, ptr 0x%p", - ip->i_ino, ip->i_d.di_forkoff, ip); + xfs_alert_tag(mp, XFS_PTAG_IFLUSH, + "%s: bad inode %Lu, forkoff 0x%x, ptr 0x%p", + __func__, ip->i_ino, ip->i_d.di_forkoff, ip); goto corrupt_out; } /* diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 8a0f044750c3..812646fe1b3e 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -105,7 +105,7 @@ xfs_cmn_err_fsblock_zero( xfs_inode_t *ip, xfs_bmbt_irec_t *imap) { - xfs_cmn_err(XFS_PTAG_FSBLOCK_ZERO, CE_ALERT, ip->i_mount, + xfs_alert_tag(ip->i_mount, XFS_PTAG_FSBLOCK_ZERO, "Access to block zero in inode %llu " "start_block: %llx start_off: %llx " "blkcnt: %llx extent-state: %x\n", diff --git a/fs/xfs/xfs_rw.c b/fs/xfs/xfs_rw.c index ccd3adf640ee..ae6f49613412 100644 --- a/fs/xfs/xfs_rw.c +++ b/fs/xfs/xfs_rw.c @@ -69,25 +69,20 @@ xfs_do_force_shutdown( return; if (flags & SHUTDOWN_CORRUPT_INCORE) { - xfs_cmn_err(XFS_PTAG_SHUTDOWN_CORRUPT, CE_ALERT, mp, - "Corruption of in-memory data detected. Shutting down filesystem: %s", - mp->m_fsname); - if (XFS_ERRLEVEL_HIGH <= xfs_error_level) { + xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_CORRUPT, + "Corruption of in-memory data detected. Shutting down filesystem"); + if (XFS_ERRLEVEL_HIGH <= xfs_error_level) xfs_stack_trace(); - } } else if (!(flags & SHUTDOWN_FORCE_UMOUNT)) { if (logerror) { - xfs_cmn_err(XFS_PTAG_SHUTDOWN_LOGERROR, CE_ALERT, mp, - "Log I/O Error Detected. Shutting down filesystem: %s", - mp->m_fsname); + xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_LOGERROR, + "Log I/O Error Detected. Shutting down filesystem"); } else if (flags & SHUTDOWN_DEVICE_REQ) { - xfs_cmn_err(XFS_PTAG_SHUTDOWN_IOERROR, CE_ALERT, mp, - "All device paths lost. Shutting down filesystem: %s", - mp->m_fsname); + xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_IOERROR, + "All device paths lost. Shutting down filesystem"); } else if (!(flags & SHUTDOWN_REMOTE_REQ)) { - xfs_cmn_err(XFS_PTAG_SHUTDOWN_IOERROR, CE_ALERT, mp, - "I/O Error Detected. Shutting down filesystem: %s", - mp->m_fsname); + xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_IOERROR, + "I/O Error Detected. Shutting down filesystem"); } } if (!(flags & SHUTDOWN_FORCE_UMOUNT)) { diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c index c5bbbc45db91..12aff9584e29 100644 --- a/fs/xfs/xfs_trans_ail.c +++ b/fs/xfs/xfs_trans_ail.c @@ -563,7 +563,7 @@ xfs_trans_ail_delete_bulk( spin_unlock(&ailp->xa_lock); if (!XFS_FORCED_SHUTDOWN(mp)) { - xfs_cmn_err(XFS_PTAG_AILDELETE, CE_ALERT, mp, + xfs_alert_tag(mp, XFS_PTAG_AILDELETE, "%s: attempting to delete a log item that is not in the AIL", __func__); xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); -- cgit From 65333b4c3d46909872796321d15f179cb0e32028 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Mon, 7 Mar 2011 10:03:35 +1100 Subject: xfs: kill xfs_fs_repair_cmn_err() macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In certain cases of inode corruption, the xfs_fs_repair_cmn_err() macro is used to output an extra message in the corruption report. That extra message is "unmount and run xfs_repair", which really applies to any corruption report. Each case that this macro is called (except one) a following call to xfs_corruption_error() is made to optionally dump more information about the error. Hence, move the output of "run xfs_repair" to xfs_corruption_error() so that it is output on all corruption reports. Also, convert the callers of the repair macro that don't call xfs_corruption_error() to call it, hence provide consiѕtent error reporting for all cases where xfs_fs_repair_cmn_err() used to be called. Signed-off-by: Dave Chinner Reviewed-by: Alex Elder Reviewed-by: Christoph Hellwig --- fs/xfs/xfs_bmap.c | 7 +++---- fs/xfs/xfs_error.c | 1 + fs/xfs/xfs_error.h | 3 --- fs/xfs/xfs_inode.c | 37 +++++++++++++++---------------------- 4 files changed, 19 insertions(+), 29 deletions(-) (limited to 'fs') diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 451b4484795d..ded532dc0699 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -4200,12 +4200,11 @@ xfs_bmap_read_extents( num_recs = xfs_btree_get_numrecs(block); if (unlikely(i + num_recs > room)) { ASSERT(i + num_recs <= room); - xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, + xfs_warn(ip->i_mount, "corrupt dinode %Lu, (btree extents).", (unsigned long long) ip->i_ino); - XFS_ERROR_REPORT("xfs_bmap_read_extents(1)", - XFS_ERRLEVEL_LOW, - ip->i_mount); + XFS_CORRUPTION_ERROR("xfs_bmap_read_extents(1)", + XFS_ERRLEVEL_LOW, ip->i_mount, block); goto error0; } XFS_WANT_CORRUPTED_GOTO( diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c index 34f0e2d264ea..03028906f00e 100644 --- a/fs/xfs/xfs_error.c +++ b/fs/xfs/xfs_error.c @@ -183,4 +183,5 @@ xfs_corruption_error( if (level <= xfs_error_level) xfs_hex_dump(p, 16); xfs_error_report(tag, level, mp, filename, linenum, ra); + xfs_alert(mp, "Corruption detected. Unmount and run xfs_repair"); } diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h index e1ba2d2565b3..4c8b5007000a 100644 --- a/fs/xfs/xfs_error.h +++ b/fs/xfs/xfs_error.h @@ -162,9 +162,6 @@ struct xfs_mount; extern void xfs_hex_dump(void *p, int length); -#define xfs_fs_repair_cmn_err(level, mp, fmt, args...) \ - xfs_fs_cmn_err(level, mp, fmt " Unmount and run xfs_repair.", ## args) - #define xfs_fs_mount_cmn_err(f, fmt, args...) \ do { \ if (!(f & XFS_MFSI_QUIET)) \ diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index bf9ca579365c..55169bbfc820 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -317,7 +317,7 @@ xfs_iformat( if (unlikely(be32_to_cpu(dip->di_nextents) + be16_to_cpu(dip->di_anextents) > be64_to_cpu(dip->di_nblocks))) { - xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, + xfs_warn(ip->i_mount, "corrupt dinode %Lu, extent total = %d, nblocks = %Lu.", (unsigned long long)ip->i_ino, (int)(be32_to_cpu(dip->di_nextents) + @@ -330,8 +330,7 @@ xfs_iformat( } if (unlikely(dip->di_forkoff > ip->i_mount->m_sb.sb_inodesize)) { - xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, - "corrupt dinode %Lu, forkoff = 0x%x.", + xfs_warn(ip->i_mount, "corrupt dinode %Lu, forkoff = 0x%x.", (unsigned long long)ip->i_ino, dip->di_forkoff); XFS_CORRUPTION_ERROR("xfs_iformat(2)", XFS_ERRLEVEL_LOW, @@ -341,7 +340,7 @@ xfs_iformat( if (unlikely((ip->i_d.di_flags & XFS_DIFLAG_REALTIME) && !ip->i_mount->m_rtdev_targp)) { - xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, + xfs_warn(ip->i_mount, "corrupt dinode %Lu, has realtime flag set.", ip->i_ino); XFS_CORRUPTION_ERROR("xfs_iformat(realtime)", @@ -373,9 +372,8 @@ xfs_iformat( * no local regular files yet */ if (unlikely((be16_to_cpu(dip->di_mode) & S_IFMT) == S_IFREG)) { - xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, - "corrupt inode %Lu " - "(local format for regular file).", + xfs_warn(ip->i_mount, + "corrupt inode %Lu (local format for regular file).", (unsigned long long) ip->i_ino); XFS_CORRUPTION_ERROR("xfs_iformat(4)", XFS_ERRLEVEL_LOW, @@ -385,9 +383,8 @@ xfs_iformat( di_size = be64_to_cpu(dip->di_size); if (unlikely(di_size > XFS_DFORK_DSIZE(dip, ip->i_mount))) { - xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, - "corrupt inode %Lu " - "(bad size %Ld for local inode).", + xfs_warn(ip->i_mount, + "corrupt inode %Lu (bad size %Ld for local inode).", (unsigned long long) ip->i_ino, (long long) di_size); XFS_CORRUPTION_ERROR("xfs_iformat(5)", @@ -431,9 +428,8 @@ xfs_iformat( size = be16_to_cpu(atp->hdr.totsize); if (unlikely(size < sizeof(struct xfs_attr_sf_hdr))) { - xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, - "corrupt inode %Lu " - "(bad attr fork size %Ld).", + xfs_warn(ip->i_mount, + "corrupt inode %Lu (bad attr fork size %Ld).", (unsigned long long) ip->i_ino, (long long) size); XFS_CORRUPTION_ERROR("xfs_iformat(8)", @@ -488,9 +484,8 @@ xfs_iformat_local( * kmem_alloc() or memcpy() below. */ if (unlikely(size > XFS_DFORK_SIZE(dip, ip->i_mount, whichfork))) { - xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, - "corrupt inode %Lu " - "(bad size %d for local fork, size = %d).", + xfs_warn(ip->i_mount, + "corrupt inode %Lu (bad size %d for local fork, size = %d).", (unsigned long long) ip->i_ino, size, XFS_DFORK_SIZE(dip, ip->i_mount, whichfork)); XFS_CORRUPTION_ERROR("xfs_iformat_local", XFS_ERRLEVEL_LOW, @@ -547,8 +542,7 @@ xfs_iformat_extents( * kmem_alloc() or memcpy() below. */ if (unlikely(size < 0 || size > XFS_DFORK_SIZE(dip, ip->i_mount, whichfork))) { - xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, - "corrupt inode %Lu ((a)extents = %d).", + xfs_warn(ip->i_mount, "corrupt inode %Lu ((a)extents = %d).", (unsigned long long) ip->i_ino, nex); XFS_CORRUPTION_ERROR("xfs_iformat_extents(1)", XFS_ERRLEVEL_LOW, ip->i_mount, dip); @@ -623,11 +617,10 @@ xfs_iformat_btree( || XFS_BMDR_SPACE_CALC(nrecs) > XFS_DFORK_SIZE(dip, ip->i_mount, whichfork) || XFS_IFORK_NEXTENTS(ip, whichfork) > ip->i_d.di_nblocks)) { - xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount, - "corrupt inode %Lu (btree).", + xfs_warn(ip->i_mount, "corrupt inode %Lu (btree).", (unsigned long long) ip->i_ino); - XFS_ERROR_REPORT("xfs_iformat_btree", XFS_ERRLEVEL_LOW, - ip->i_mount); + XFS_CORRUPTION_ERROR("xfs_iformat_btree", XFS_ERRLEVEL_LOW, + ip->i_mount, dip); return XFS_ERROR(EFSCORRUPTED); } -- cgit From af34e09da42801c97f39f768c715f5511d914b52 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Mon, 7 Mar 2011 10:04:35 +1100 Subject: xfs: kill xfs_fs_mount_cmn_err() macro The xfs_fs_mount_cmn_err() hides a simple check as to whether the mount path should output an error or not. Remove the macro and open code the check. Signed-off-by: Dave Chinner Reviewed-by: Alex Elder Reviewed-by: Christoph Hellwig --- fs/xfs/xfs_error.h | 6 ----- fs/xfs/xfs_mount.c | 72 ++++++++++++++++++++++++++++++++---------------------- 2 files changed, 43 insertions(+), 35 deletions(-) (limited to 'fs') diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h index 4c8b5007000a..e8360514c250 100644 --- a/fs/xfs/xfs_error.h +++ b/fs/xfs/xfs_error.h @@ -162,10 +162,4 @@ struct xfs_mount; extern void xfs_hex_dump(void *p, int length); -#define xfs_fs_mount_cmn_err(f, fmt, args...) \ - do { \ - if (!(f & XFS_MFSI_QUIET)) \ - cmn_err(CE_WARN, "XFS: " fmt, ## args); \ - } while (0) - #endif /* __XFS_ERROR_H__ */ diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index d447aef84bc3..1b43ad3d6ddb 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -311,6 +311,8 @@ xfs_mount_validate_sb( xfs_sb_t *sbp, int flags) { + int loud = !(flags & XFS_MFSI_QUIET); + /* * If the log device and data device have the * same device number, the log is internal. @@ -319,28 +321,32 @@ xfs_mount_validate_sb( * a volume filesystem in a non-volume manner. */ if (sbp->sb_magicnum != XFS_SB_MAGIC) { - xfs_fs_mount_cmn_err(flags, "bad magic number"); + if (loud) + xfs_warn(mp, "bad magic number"); return XFS_ERROR(EWRONGFS); } if (!xfs_sb_good_version(sbp)) { - xfs_fs_mount_cmn_err(flags, "bad version"); + if (loud) + xfs_warn(mp, "bad version"); return XFS_ERROR(EWRONGFS); } if (unlikely( sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) { - xfs_fs_mount_cmn_err(flags, - "filesystem is marked as having an external log; " - "specify logdev on the\nmount command line."); + if (loud) + xfs_warn(mp, + "filesystem is marked as having an external log; " + "specify logdev on the mount command line."); return XFS_ERROR(EINVAL); } if (unlikely( sbp->sb_logstart != 0 && mp->m_logdev_targp != mp->m_ddev_targp)) { - xfs_fs_mount_cmn_err(flags, - "filesystem is marked as having an internal log; " - "do not specify logdev on\nthe mount command line."); + if (loud) + xfs_warn(mp, + "filesystem is marked as having an internal log; " + "do not specify logdev on the mount command line."); return XFS_ERROR(EINVAL); } @@ -369,7 +375,8 @@ xfs_mount_validate_sb( (sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE) || (sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE) || (sbp->sb_imax_pct > 100 /* zero sb_imax_pct is valid */))) { - xfs_fs_mount_cmn_err(flags, "SB sanity check 1 failed"); + if (loud) + xfs_warn(mp, "SB sanity check 1 failed"); return XFS_ERROR(EFSCORRUPTED); } @@ -382,7 +389,8 @@ xfs_mount_validate_sb( (xfs_drfsbno_t)sbp->sb_agcount * sbp->sb_agblocks || sbp->sb_dblocks < (xfs_drfsbno_t)(sbp->sb_agcount - 1) * sbp->sb_agblocks + XFS_MIN_AG_BLOCKS)) { - xfs_fs_mount_cmn_err(flags, "SB sanity check 2 failed"); + if (loud) + xfs_warn(mp, "SB sanity check 2 failed"); return XFS_ERROR(EFSCORRUPTED); } @@ -390,12 +398,12 @@ xfs_mount_validate_sb( * Until this is fixed only page-sized or smaller data blocks work. */ if (unlikely(sbp->sb_blocksize > PAGE_SIZE)) { - xfs_fs_mount_cmn_err(flags, - "file system with blocksize %d bytes", - sbp->sb_blocksize); - xfs_fs_mount_cmn_err(flags, - "only pagesize (%ld) or less will currently work.", - PAGE_SIZE); + if (loud) { + xfs_warn(mp, + "File system with blocksize %d bytes. " + "Only pagesize (%ld) or less will currently work.", + sbp->sb_blocksize, PAGE_SIZE); + } return XFS_ERROR(ENOSYS); } @@ -409,21 +417,23 @@ xfs_mount_validate_sb( case 2048: break; default: - xfs_fs_mount_cmn_err(flags, - "inode size of %d bytes not supported", - sbp->sb_inodesize); + if (loud) + xfs_warn(mp, "inode size of %d bytes not supported", + sbp->sb_inodesize); return XFS_ERROR(ENOSYS); } if (xfs_sb_validate_fsb_count(sbp, sbp->sb_dblocks) || xfs_sb_validate_fsb_count(sbp, sbp->sb_rblocks)) { - xfs_fs_mount_cmn_err(flags, - "file system too large to be mounted on this system."); + if (loud) + xfs_warn(mp, + "file system too large to be mounted on this system."); return XFS_ERROR(EFBIG); } if (unlikely(sbp->sb_inprogress)) { - xfs_fs_mount_cmn_err(flags, "file system busy"); + if (loud) + xfs_warn(mp, "file system busy"); return XFS_ERROR(EFSCORRUPTED); } @@ -431,8 +441,9 @@ xfs_mount_validate_sb( * Version 1 directory format has never worked on Linux. */ if (unlikely(!xfs_sb_version_hasdirv2(sbp))) { - xfs_fs_mount_cmn_err(flags, - "file system using version 1 directory format"); + if (loud) + xfs_warn(mp, + "file system using version 1 directory format"); return XFS_ERROR(ENOSYS); } @@ -673,6 +684,7 @@ xfs_readsb(xfs_mount_t *mp, int flags) unsigned int sector_size; xfs_buf_t *bp; int error; + int loud = !(flags & XFS_MFSI_QUIET); ASSERT(mp->m_sb_bp == NULL); ASSERT(mp->m_ddev_targp != NULL); @@ -688,7 +700,8 @@ reread: bp = xfs_buf_read_uncached(mp, mp->m_ddev_targp, XFS_SB_DADDR, sector_size, 0); if (!bp) { - xfs_fs_mount_cmn_err(flags, "SB buffer read failed"); + if (loud) + xfs_warn(mp, "SB buffer read failed"); return EIO; } @@ -699,7 +712,8 @@ reread: xfs_sb_from_disk(&mp->m_sb, XFS_BUF_TO_SBP(bp)); error = xfs_mount_validate_sb(mp, &(mp->m_sb), flags); if (error) { - xfs_fs_mount_cmn_err(flags, "SB validate failed"); + if (loud) + xfs_warn(mp, "SB validate failed"); goto release_buf; } @@ -707,9 +721,9 @@ reread: * We must be able to do sector-sized and sector-aligned IO. */ if (sector_size > mp->m_sb.sb_sectsize) { - xfs_fs_mount_cmn_err(flags, - "device supports only %u byte sectors (not %u)", - sector_size, mp->m_sb.sb_sectsize); + if (loud) + xfs_warn(mp, "device supports %u byte sectors (not %u)", + sector_size, mp->m_sb.sb_sectsize); error = ENOSYS; goto release_buf; } -- cgit From 5348778699bba92bf28b79863e09e7181d8cf95c Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Mon, 7 Mar 2011 10:05:35 +1100 Subject: xfs: convert xfs_fs_cmn_err to new error logging API Continue to clean up the error logging code by converting all the callers of xfs_fs_cmn_err() to the new API. Once done, remove the unused old API function. Signed-off-by: Dave Chinner Reviewed-by: Alex Elder Reviewed-by: Christoph Hellwig --- fs/xfs/quota/xfs_dquot.c | 4 ++-- fs/xfs/quota/xfs_dquot_item.c | 5 ++--- fs/xfs/quota/xfs_qm.c | 13 ++++++------- fs/xfs/support/debug.c | 20 -------------------- fs/xfs/support/debug.h | 2 -- fs/xfs/xfs_bmap.c | 2 +- fs/xfs/xfs_dfrag.c | 4 ++-- fs/xfs/xfs_dir2.c | 2 +- fs/xfs/xfs_fsops.c | 6 +++--- fs/xfs/xfs_ialloc.c | 39 +++++++++++++++++---------------------- fs/xfs/xfs_inode.c | 17 +++++++---------- fs/xfs/xfs_mount.c | 16 ++++++++-------- fs/xfs/xfs_vnodeops.c | 8 ++++---- 13 files changed, 53 insertions(+), 85 deletions(-) (limited to 'fs') diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c index 773adc80d6b4..e1ff7e507670 100644 --- a/fs/xfs/quota/xfs_dquot.c +++ b/fs/xfs/quota/xfs_dquot.c @@ -1393,8 +1393,8 @@ xfs_qm_dqpurge( */ error = xfs_qm_dqflush(dqp, SYNC_WAIT); if (error) - xfs_fs_cmn_err(CE_WARN, mp, - "xfs_qm_dqpurge: dquot %p flush failed", dqp); + xfs_warn(mp, "%s: dquot %p flush failed", + __func__, dqp); xfs_dqflock(dqp); } ASSERT(atomic_read(&dqp->q_pincount) == 0); diff --git a/fs/xfs/quota/xfs_dquot_item.c b/fs/xfs/quota/xfs_dquot_item.c index 2a1f3dc10a02..9e0e2fa3f2c8 100644 --- a/fs/xfs/quota/xfs_dquot_item.c +++ b/fs/xfs/quota/xfs_dquot_item.c @@ -136,9 +136,8 @@ xfs_qm_dquot_logitem_push( */ error = xfs_qm_dqflush(dqp, 0); if (error) - xfs_fs_cmn_err(CE_WARN, dqp->q_mount, - "xfs_qm_dquot_logitem_push: push error %d on dqp %p", - error, dqp); + xfs_warn(dqp->q_mount, "%s: push error %d on dqp %p", + __func__, error, dqp); xfs_dqunlock(dqp); } diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index dd5cc5738a2c..e34dce1ce542 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c @@ -402,14 +402,13 @@ xfs_qm_mount_quotas( * off, but the on disk superblock doesn't know that ! */ ASSERT(!(XFS_IS_QUOTA_RUNNING(mp))); - xfs_fs_cmn_err(CE_ALERT, mp, - "XFS mount_quotas: Superblock update failed!"); + xfs_alert(mp, "%s: Superblock update failed!", + __func__); } } if (error) { - xfs_fs_cmn_err(CE_WARN, mp, - "Failed to initialize disk quotas."); + xfs_warn(mp, "Failed to initialize disk quotas."); return; } @@ -1257,7 +1256,7 @@ xfs_qm_qino_alloc( xfs_mod_sb(tp, sbfields); if ((error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES))) { - xfs_fs_cmn_err(CE_ALERT, mp, "XFS qino_alloc failed!"); + xfs_alert(mp, "%s failed (error %d)!", __func__, error); return error; } return 0; @@ -1930,8 +1929,8 @@ again: */ error = xfs_qm_dqflush(dqp, 0); if (error) { - xfs_fs_cmn_err(CE_WARN, mp, - "xfs_qm_dqreclaim: dquot %p flush failed", dqp); + xfs_warn(mp, "%s: dquot %p flush failed", + __func__, dqp); } goto dqunlock; } diff --git a/fs/xfs/support/debug.c b/fs/xfs/support/debug.c index feaca739d5cc..a1c7141af481 100644 --- a/fs/xfs/support/debug.c +++ b/fs/xfs/support/debug.c @@ -44,26 +44,6 @@ cmn_err( BUG_ON(strncmp(lvl, KERN_EMERG, strlen(KERN_EMERG)) == 0); } -void -xfs_fs_cmn_err( - const char *lvl, - struct xfs_mount *mp, - const char *fmt, - ...) -{ - struct va_format vaf; - va_list args; - - va_start(args, fmt); - vaf.fmt = fmt; - vaf.va = &args; - - printk("%sFilesystem %s: %pV", lvl, mp->m_fsname, &vaf); - va_end(args); - - BUG_ON(strncmp(lvl, KERN_EMERG, strlen(KERN_EMERG)) == 0); -} - void assfail(char *expr, char *file, int line) { diff --git a/fs/xfs/support/debug.h b/fs/xfs/support/debug.h index eaeaa17ef4b8..4a082b9a1161 100644 --- a/fs/xfs/support/debug.h +++ b/fs/xfs/support/debug.h @@ -31,8 +31,6 @@ struct xfs_mount; void cmn_err(const char *lvl, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); -void xfs_fs_cmn_err( const char *lvl, struct xfs_mount *mp, - const char *fmt, ...) __attribute__ ((format (printf, 3, 4))); extern void assfail(char *expr, char *f, int l); diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index ded532dc0699..92612f6b4b3e 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -6150,7 +6150,7 @@ xfs_bmap_punch_delalloc_range( if (error) { /* something screwed, just bail */ if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { - xfs_fs_cmn_err(CE_ALERT, ip->i_mount, + xfs_alert(ip->i_mount, "Failed delalloc mapping lookup ino %lld fsb %lld.", ip->i_ino, start_fsb); } diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c index e60490bc00a6..be628677c288 100644 --- a/fs/xfs/xfs_dfrag.c +++ b/fs/xfs/xfs_dfrag.c @@ -270,9 +270,9 @@ xfs_swap_extents( /* check inode formats now that data is flushed */ error = xfs_swap_extents_check_format(ip, tip); if (error) { - xfs_fs_cmn_err(CE_NOTE, mp, + xfs_notice(mp, "%s: inode 0x%llx format is incompatible for exchanging.", - __FILE__, ip->i_ino); + __func__, ip->i_ino); goto out_unlock; } diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c index a1321bc7f192..dba7a71cedf3 100644 --- a/fs/xfs/xfs_dir2.c +++ b/fs/xfs/xfs_dir2.c @@ -159,7 +159,7 @@ xfs_dir_ino_validate( XFS_AGINO_TO_INO(mp, agno, agino) == ino; if (unlikely(XFS_TEST_ERROR(!ino_ok, mp, XFS_ERRTAG_DIR_INO_VALIDATE, XFS_RANDOM_DIR_INO_VALIDATE))) { - xfs_fs_cmn_err(CE_WARN, mp, "Invalid inode number 0x%Lx", + xfs_warn(mp, "Invalid inode number 0x%Lx", (unsigned long long) ino); XFS_ERROR_REPORT("xfs_dir_ino_validate", XFS_ERRLEVEL_LOW, mp); return XFS_ERROR(EFSCORRUPTED); diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index 85668efb3e3e..9153d2c77caf 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -385,8 +385,8 @@ xfs_growfs_data_private( XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)), XFS_FSS_TO_BB(mp, 1), 0, &bp); if (error) { - xfs_fs_cmn_err(CE_WARN, mp, - "error %d reading secondary superblock for ag %d", + xfs_warn(mp, + "error %d reading secondary superblock for ag %d", error, agno); break; } @@ -399,7 +399,7 @@ xfs_growfs_data_private( if (!(error = xfs_bwrite(mp, bp))) { continue; } else { - xfs_fs_cmn_err(CE_WARN, mp, + xfs_warn(mp, "write error %d updating secondary superblock for ag %d", error, agno); break; /* no point in continuing */ diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c index 0626a32c3447..fc3a2cb2c075 100644 --- a/fs/xfs/xfs_ialloc.c +++ b/fs/xfs/xfs_ialloc.c @@ -1218,10 +1218,9 @@ xfs_imap_lookup( error = xfs_ialloc_read_agi(mp, tp, agno, &agbp); if (error) { - xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: " - "xfs_ialloc_read_agi() returned " - "error %d, agno %d", - error, agno); + xfs_alert(mp, + "%s: xfs_ialloc_read_agi() returned error %d, agno %d", + __func__, error, agno); return error; } @@ -1299,24 +1298,21 @@ xfs_imap( if (flags & XFS_IGET_UNTRUSTED) return XFS_ERROR(EINVAL); if (agno >= mp->m_sb.sb_agcount) { - xfs_fs_cmn_err(CE_ALERT, mp, - "xfs_imap: agno (%d) >= " - "mp->m_sb.sb_agcount (%d)", - agno, mp->m_sb.sb_agcount); + xfs_alert(mp, + "%s: agno (%d) >= mp->m_sb.sb_agcount (%d)", + __func__, agno, mp->m_sb.sb_agcount); } if (agbno >= mp->m_sb.sb_agblocks) { - xfs_fs_cmn_err(CE_ALERT, mp, - "xfs_imap: agbno (0x%llx) >= " - "mp->m_sb.sb_agblocks (0x%lx)", - (unsigned long long) agbno, - (unsigned long) mp->m_sb.sb_agblocks); + xfs_alert(mp, + "%s: agbno (0x%llx) >= mp->m_sb.sb_agblocks (0x%lx)", + __func__, (unsigned long long)agbno, + (unsigned long)mp->m_sb.sb_agblocks); } if (ino != XFS_AGINO_TO_INO(mp, agno, agino)) { - xfs_fs_cmn_err(CE_ALERT, mp, - "xfs_imap: ino (0x%llx) != " - "XFS_AGINO_TO_INO(mp, agno, agino) " - "(0x%llx)", - ino, XFS_AGINO_TO_INO(mp, agno, agino)); + xfs_alert(mp, + "%s: ino (0x%llx) != XFS_AGINO_TO_INO() (0x%llx)", + __func__, ino, + XFS_AGINO_TO_INO(mp, agno, agino)); } xfs_stack_trace(); #endif /* DEBUG */ @@ -1388,10 +1384,9 @@ out_map: */ if ((imap->im_blkno + imap->im_len) > XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks)) { - xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: " - "(imap->im_blkno (0x%llx) + imap->im_len (0x%llx)) > " - " XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks) (0x%llx)", - (unsigned long long) imap->im_blkno, + xfs_alert(mp, + "%s: (im_blkno (0x%llx) + im_len (0x%llx)) > sb_dblocks (0x%llx)", + __func__, (unsigned long long) imap->im_blkno, (unsigned long long) imap->im_len, XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks)); return XFS_ERROR(EINVAL); diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 55169bbfc820..d820ada49b18 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -110,8 +110,8 @@ xfs_inobp_check( dip = (xfs_dinode_t *)xfs_buf_offset(bp, i * mp->m_sb.sb_inodesize); if (!dip->di_next_unlinked) { - xfs_fs_cmn_err(CE_ALERT, mp, - "Detected a bogus zero next_unlinked field in incore inode buffer 0x%p. About to pop an ASSERT.", + xfs_alert(mp, + "Detected bogus zero next_unlinked field in incore inode buffer 0x%p.", bp); ASSERT(dip->di_next_unlinked); } @@ -806,11 +806,9 @@ xfs_iread( */ if (be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC) { #ifdef DEBUG - xfs_fs_cmn_err(CE_ALERT, mp, "xfs_iread: " - "dip->di_magic (0x%x) != " - "XFS_DINODE_MAGIC (0x%x)", - be16_to_cpu(dip->di_magic), - XFS_DINODE_MAGIC); + xfs_alert(mp, + "%s: dip->di_magic (0x%x) != XFS_DINODE_MAGIC (0x%x)", + __func__, be16_to_cpu(dip->di_magic), XFS_DINODE_MAGIC); #endif /* DEBUG */ error = XFS_ERROR(EINVAL); goto out_brelse; @@ -828,9 +826,8 @@ xfs_iread( error = xfs_iformat(ip, dip); if (error) { #ifdef DEBUG - xfs_fs_cmn_err(CE_ALERT, mp, "xfs_iread: " - "xfs_iformat() returned error %d", - error); + xfs_alert(mp, "%s: xfs_iformat() returned error %d", + __func__, error); #endif /* DEBUG */ goto out_brelse; } diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 1b43ad3d6ddb..e39b082eb049 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -881,8 +881,9 @@ xfs_update_alignment(xfs_mount_t *mp) if (mp->m_flags & XFS_MOUNT_RETERR) { return XFS_ERROR(EINVAL); } - xfs_fs_cmn_err(CE_WARN, mp, -"stripe alignment turned off: sunit(%d)/swidth(%d) incompatible with agsize(%d)", + xfs_warn(mp, + "stripe alignment turned off: sunit(%d)/swidth(%d) " + "incompatible with agsize(%d)", mp->m_dalign, mp->m_swidth, sbp->sb_agblocks); @@ -892,9 +893,9 @@ xfs_update_alignment(xfs_mount_t *mp) mp->m_swidth = XFS_BB_TO_FSBT(mp, mp->m_swidth); } else { if (mp->m_flags & XFS_MOUNT_RETERR) { - xfs_fs_cmn_err(CE_WARN, mp, -"stripe alignment turned off: sunit(%d) less than bsize(%d)", - mp->m_dalign, + xfs_warn(mp, + "stripe alignment turned off: sunit(%d) less than bsize(%d)", + mp->m_dalign, mp->m_blockmask +1); return XFS_ERROR(EINVAL); } @@ -1100,7 +1101,7 @@ xfs_mount_reset_sbqflags( return 0; #ifdef QUOTADEBUG - xfs_fs_cmn_err(CE_NOTE, mp, "Writing superblock quota changes"); + xfs_notice(mp, "Writing superblock quota changes"); #endif tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SBCHANGE); @@ -1108,8 +1109,7 @@ xfs_mount_reset_sbqflags( XFS_DEFAULT_LOG_COUNT); if (error) { xfs_trans_cancel(tp, 0); - xfs_fs_cmn_err(CE_ALERT, mp, - "xfs_mount_reset_sbqflags: Superblock update failed!"); + xfs_alert(mp, "%s: Superblock update failed!", __func__); return error; } diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 258d4f98eb9b..e919ae1e9c65 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -1208,12 +1208,12 @@ xfs_inactive( */ error = xfs_bmap_finish(&tp, &free_list, &committed); if (error) - xfs_fs_cmn_err(CE_NOTE, mp, "xfs_inactive: " - "xfs_bmap_finish() returned error %d", error); + xfs_notice(mp, "%s: xfs_bmap_finish returned error %d", + __func__, error); error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); if (error) - xfs_fs_cmn_err(CE_NOTE, mp, "xfs_inactive: " - "xfs_trans_commit() returned error %d", error); + xfs_notice(mp, "%s: xfs_trans_commit returned error %d", + __func__, error); } /* -- cgit From 6d4a8ecb344bddbbb8c71deb4dcea0be6955cfc3 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Mon, 7 Mar 2011 10:06:35 +1100 Subject: xfs: rename xfs_cmn_err_fsblock_zero() The "cmn_err" part of the function name is no longer relevant. Rename the function to xfs_alert_fsblock_zero() to match the new logging API. Signed-off-by: Dave Chinner Reviewed-by: Alex Elder Reviewed-by: Christoph Hellwig --- fs/xfs/xfs_iomap.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 812646fe1b3e..091d82b94c4d 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -101,7 +101,7 @@ xfs_iomap_eof_align_last_fsb( } STATIC int -xfs_cmn_err_fsblock_zero( +xfs_alert_fsblock_zero( xfs_inode_t *ip, xfs_bmbt_irec_t *imap) { @@ -246,7 +246,7 @@ xfs_iomap_write_direct( } if (!(imap->br_startblock || XFS_IS_REALTIME_INODE(ip))) { - error = xfs_cmn_err_fsblock_zero(ip, imap); + error = xfs_alert_fsblock_zero(ip, imap); goto error_out; } @@ -464,7 +464,7 @@ retry: } if (!(imap[0].br_startblock || XFS_IS_REALTIME_INODE(ip))) - return xfs_cmn_err_fsblock_zero(ip, &imap[0]); + return xfs_alert_fsblock_zero(ip, &imap[0]); *ret_imap = imap[0]; return 0; @@ -614,7 +614,7 @@ xfs_iomap_write_allocate( * covers at least part of the callers request */ if (!(imap->br_startblock || XFS_IS_REALTIME_INODE(ip))) - return xfs_cmn_err_fsblock_zero(ip, imap); + return xfs_alert_fsblock_zero(ip, imap); if ((offset_fsb >= imap->br_startoff) && (offset_fsb < (imap->br_startoff + @@ -724,7 +724,7 @@ xfs_iomap_write_unwritten( return XFS_ERROR(error); if (!(imap.br_startblock || XFS_IS_REALTIME_INODE(ip))) - return xfs_cmn_err_fsblock_zero(ip, &imap); + return xfs_alert_fsblock_zero(ip, &imap); if ((numblks_fsb = imap.br_blockcount) == 0) { /* -- cgit From 8221112b4377a3b69f2016b5cc3c550d51dd3139 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Mon, 7 Mar 2011 10:07:35 +1100 Subject: xfs: convert the quota debug prints to new API Signed-off-by: Dave Chinner Reviewed-by: Alex Elder Reviewed-by: Christoph Hellwig --- fs/xfs/quota/xfs_qm_syscalls.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) (limited to 'fs') diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c index bdebc183223e..603ab867259e 100644 --- a/fs/xfs/quota/xfs_qm_syscalls.c +++ b/fs/xfs/quota/xfs_qm_syscalls.c @@ -41,12 +41,6 @@ #include "xfs_qm.h" #include "xfs_trace.h" -#ifdef DEBUG -# define qdprintk(s, args...) cmn_err(CE_DEBUG, s, ## args) -#else -# define qdprintk(s, args...) do { } while (0) -#endif - STATIC int xfs_qm_log_quotaoff(xfs_mount_t *, xfs_qoff_logitem_t **, uint); STATIC int xfs_qm_log_quotaoff_end(xfs_mount_t *, xfs_qoff_logitem_t *, uint); @@ -294,7 +288,8 @@ xfs_qm_scall_trunc_qfiles( int error = 0, error2 = 0; if (!xfs_sb_version_hasquota(&mp->m_sb) || flags == 0) { - qdprintk("qtrunc flags=%x m_qflags=%x\n", flags, mp->m_qflags); + xfs_debug(mp, "%s: flags=%x m_qflags=%x\n", + __func__, flags, mp->m_qflags); return XFS_ERROR(EINVAL); } @@ -331,7 +326,8 @@ xfs_qm_scall_quotaon( sbflags = 0; if (flags == 0) { - qdprintk("quotaon: zero flags, m_qflags=%x\n", mp->m_qflags); + xfs_debug(mp, "%s: zero flags, m_qflags=%x\n", + __func__, mp->m_qflags); return XFS_ERROR(EINVAL); } @@ -352,8 +348,9 @@ xfs_qm_scall_quotaon( (flags & XFS_GQUOTA_ACCT) == 0 && (mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 && (flags & XFS_OQUOTA_ENFD))) { - qdprintk("Can't enforce without acct, flags=%x sbflags=%x\n", - flags, mp->m_sb.sb_qflags); + xfs_debug(mp, + "%s: Can't enforce without acct, flags=%x sbflags=%x\n", + __func__, flags, mp->m_sb.sb_qflags); return XFS_ERROR(EINVAL); } /* @@ -541,7 +538,7 @@ xfs_qm_scall_setqlim( q->qi_bsoftlimit = soft; } } else { - qdprintk("blkhard %Ld < blksoft %Ld\n", hard, soft); + xfs_debug(mp, "blkhard %Ld < blksoft %Ld\n", hard, soft); } hard = (newlim->d_fieldmask & FS_DQ_RTBHARD) ? (xfs_qcnt_t) XFS_BB_TO_FSB(mp, newlim->d_rtb_hardlimit) : @@ -557,7 +554,7 @@ xfs_qm_scall_setqlim( q->qi_rtbsoftlimit = soft; } } else { - qdprintk("rtbhard %Ld < rtbsoft %Ld\n", hard, soft); + xfs_debug(mp, "rtbhard %Ld < rtbsoft %Ld\n", hard, soft); } hard = (newlim->d_fieldmask & FS_DQ_IHARD) ? @@ -574,7 +571,7 @@ xfs_qm_scall_setqlim( q->qi_isoftlimit = soft; } } else { - qdprintk("ihard %Ld < isoft %Ld\n", hard, soft); + xfs_debug(mp, "ihard %Ld < isoft %Ld\n", hard, soft); } /* @@ -1137,8 +1134,8 @@ xfs_qm_internalqcheck_adjust( if (ino == mp->m_sb.sb_uquotino || ino == mp->m_sb.sb_gquotino) { *res = BULKSTAT_RV_NOTHING; - qdprintk("internalqcheck: ino=%llu, uqino=%llu, gqino=%llu\n", - (unsigned long long) ino, + xfs_debug(mp, "%s: ino=%llu, uqino=%llu, gqino=%llu\n", + __func__, (unsigned long long) ino, (unsigned long long) mp->m_sb.sb_uquotino, (unsigned long long) mp->m_sb.sb_gquotino); return XFS_ERROR(EINVAL); -- cgit From 0b932cccbdc09a72aa370456a59b40ecd6b10baf Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Mon, 7 Mar 2011 10:08:35 +1100 Subject: xfs: Convert remaining cmn_err() callers to new API Once converted, kill the remainder of the cmn_err() interface. Signed-off-by: Dave Chinner Reviewed-by: Alex Elder Reviewed-by: Christoph Hellwig --- fs/xfs/quota/xfs_dquot.c | 34 +++++++++++++----------- fs/xfs/quota/xfs_qm.c | 27 +++++++++---------- fs/xfs/quota/xfs_qm_bhv.c | 3 +-- fs/xfs/quota/xfs_qm_syscalls.c | 58 +++++++++++++++++++++------------------- fs/xfs/quota/xfs_trans_dquot.c | 5 ++-- fs/xfs/support/debug.c | 26 ------------------ fs/xfs/support/debug.h | 12 --------- fs/xfs/xfs_bmap.c | 6 ++--- fs/xfs/xfs_buf_item.c | 15 ++++++----- fs/xfs/xfs_da_btree.c | 9 +++---- fs/xfs/xfs_dir2_node.c | 25 +++++++----------- fs/xfs/xfs_error.c | 16 +++++------ fs/xfs/xfs_ialloc.c | 43 ++++++++++++------------------ fs/xfs/xfs_inode.c | 30 +++++++++------------ fs/xfs/xfs_mount.c | 60 +++++++++++++++++------------------------- fs/xfs/xfs_rtalloc.c | 8 +++--- fs/xfs/xfs_rtalloc.h | 2 +- fs/xfs/xfs_rw.c | 17 ++++++------ fs/xfs/xfs_trans_buf.c | 6 ++--- fs/xfs/xfs_vnodeops.c | 5 ++-- 20 files changed, 169 insertions(+), 238 deletions(-) (limited to 'fs') diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c index e1ff7e507670..7e2416478503 100644 --- a/fs/xfs/quota/xfs_dquot.c +++ b/fs/xfs/quota/xfs_dquot.c @@ -828,7 +828,7 @@ xfs_qm_dqget( if (xfs_do_dqerror) { if ((xfs_dqerror_target == mp->m_ddev_targp) && (xfs_dqreq_num++ % xfs_dqerror_mod) == 0) { - cmn_err(CE_DEBUG, "Returning error in dqget"); + xfs_debug(mp, "Returning error in dqget"); return (EIO); } } @@ -1427,36 +1427,38 @@ xfs_qm_dqpurge( void xfs_qm_dqprint(xfs_dquot_t *dqp) { - cmn_err(CE_DEBUG, "-----------KERNEL DQUOT----------------"); - cmn_err(CE_DEBUG, "---- dquotID = %d", + struct xfs_mount *mp = dqp->q_mount; + + xfs_debug(mp, "-----------KERNEL DQUOT----------------"); + xfs_debug(mp, "---- dquotID = %d", (int)be32_to_cpu(dqp->q_core.d_id)); - cmn_err(CE_DEBUG, "---- type = %s", DQFLAGTO_TYPESTR(dqp)); - cmn_err(CE_DEBUG, "---- fs = 0x%p", dqp->q_mount); - cmn_err(CE_DEBUG, "---- blkno = 0x%x", (int) dqp->q_blkno); - cmn_err(CE_DEBUG, "---- boffset = 0x%x", (int) dqp->q_bufoffset); - cmn_err(CE_DEBUG, "---- blkhlimit = %Lu (0x%x)", + xfs_debug(mp, "---- type = %s", DQFLAGTO_TYPESTR(dqp)); + xfs_debug(mp, "---- fs = 0x%p", dqp->q_mount); + xfs_debug(mp, "---- blkno = 0x%x", (int) dqp->q_blkno); + xfs_debug(mp, "---- boffset = 0x%x", (int) dqp->q_bufoffset); + xfs_debug(mp, "---- blkhlimit = %Lu (0x%x)", be64_to_cpu(dqp->q_core.d_blk_hardlimit), (int)be64_to_cpu(dqp->q_core.d_blk_hardlimit)); - cmn_err(CE_DEBUG, "---- blkslimit = %Lu (0x%x)", + xfs_debug(mp, "---- blkslimit = %Lu (0x%x)", be64_to_cpu(dqp->q_core.d_blk_softlimit), (int)be64_to_cpu(dqp->q_core.d_blk_softlimit)); - cmn_err(CE_DEBUG, "---- inohlimit = %Lu (0x%x)", + xfs_debug(mp, "---- inohlimit = %Lu (0x%x)", be64_to_cpu(dqp->q_core.d_ino_hardlimit), (int)be64_to_cpu(dqp->q_core.d_ino_hardlimit)); - cmn_err(CE_DEBUG, "---- inoslimit = %Lu (0x%x)", + xfs_debug(mp, "---- inoslimit = %Lu (0x%x)", be64_to_cpu(dqp->q_core.d_ino_softlimit), (int)be64_to_cpu(dqp->q_core.d_ino_softlimit)); - cmn_err(CE_DEBUG, "---- bcount = %Lu (0x%x)", + xfs_debug(mp, "---- bcount = %Lu (0x%x)", be64_to_cpu(dqp->q_core.d_bcount), (int)be64_to_cpu(dqp->q_core.d_bcount)); - cmn_err(CE_DEBUG, "---- icount = %Lu (0x%x)", + xfs_debug(mp, "---- icount = %Lu (0x%x)", be64_to_cpu(dqp->q_core.d_icount), (int)be64_to_cpu(dqp->q_core.d_icount)); - cmn_err(CE_DEBUG, "---- btimer = %d", + xfs_debug(mp, "---- btimer = %d", (int)be32_to_cpu(dqp->q_core.d_btimer)); - cmn_err(CE_DEBUG, "---- itimer = %d", + xfs_debug(mp, "---- itimer = %d", (int)be32_to_cpu(dqp->q_core.d_itimer)); - cmn_err(CE_DEBUG, "---------------------------"); + xfs_debug(mp, "---------------------------"); } #endif diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index e34dce1ce542..254ee062bd7d 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c @@ -80,7 +80,7 @@ xfs_qm_dquot_list_print( int i = 0; list_for_each_entry(dqp, &mp->m_quotainfo->qi_dqlist_lock, qi_mplist) { - cmn_err(CE_DEBUG, " %d. \"%d (%s)\" " + xfs_debug(mp, " %d. \"%d (%s)\" " "bcnt = %lld, icnt = %lld, refs = %d", i++, be32_to_cpu(dqp->q_core.d_id), DQFLAGTO_TYPESTR(dqp), @@ -205,7 +205,7 @@ xfs_qm_destroy( list_for_each_entry_safe(dqp, n, &xqm->qm_dqfrlist, q_freelist) { xfs_dqlock(dqp); #ifdef QUOTADEBUG - cmn_err(CE_DEBUG, "FREELIST destroy 0x%p", dqp); + xfs_debug(dqp->q_mount, "FREELIST destroy 0x%p", dqp); #endif list_del_init(&dqp->q_freelist); xfs_Gqm->qm_dqfrlist_cnt--; @@ -341,9 +341,7 @@ xfs_qm_mount_quotas( * quotas immediately. */ if (mp->m_sb.sb_rextents) { - cmn_err(CE_NOTE, - "Cannot turn on quotas for realtime filesystem %s", - mp->m_fsname); + xfs_notice(mp, "Cannot turn on quotas for realtime filesystem"); mp->m_qflags = 0; goto write_changes; } @@ -1668,7 +1666,7 @@ xfs_qm_quotacheck( */ ASSERT(list_empty(&mp->m_quotainfo->qi_dqlist)); - cmn_err(CE_NOTE, "XFS quotacheck %s: Please wait.", mp->m_fsname); + xfs_notice(mp, "Quotacheck needed: Please wait."); /* * First we go thru all the dquots on disk, USR and GRP/PRJ, and reset @@ -1746,9 +1744,9 @@ xfs_qm_quotacheck( error_return: if (error) { - cmn_err(CE_WARN, "XFS quotacheck %s: Unsuccessful (Error %d): " - "Disabling quotas.", - mp->m_fsname, error); + xfs_warn(mp, + "Quotacheck: Unsuccessful (Error %d): Disabling quotas.", + error); /* * We must turn off quotas. */ @@ -1756,12 +1754,11 @@ xfs_qm_quotacheck( ASSERT(xfs_Gqm != NULL); xfs_qm_destroy_quotainfo(mp); if (xfs_mount_reset_sbqflags(mp)) { - cmn_err(CE_WARN, "XFS quotacheck %s: " - "Failed to reset quota flags.", mp->m_fsname); + xfs_warn(mp, + "Quotacheck: Failed to reset quota flags."); } - } else { - cmn_err(CE_NOTE, "XFS quotacheck %s: Done.", mp->m_fsname); - } + } else + xfs_notice(mp, "Quotacheck: Done."); return (error); } @@ -2107,7 +2104,7 @@ xfs_qm_write_sb_changes( int error; #ifdef QUOTADEBUG - cmn_err(CE_NOTE, "Writing superblock quota changes :%s", mp->m_fsname); + xfs_notice(mp, "Writing superblock quota changes"); #endif tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SBCHANGE); if ((error = xfs_trans_reserve(tp, 0, diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c index 45b5cb1788ab..774d7ec6df8e 100644 --- a/fs/xfs/quota/xfs_qm_bhv.c +++ b/fs/xfs/quota/xfs_qm_bhv.c @@ -119,8 +119,7 @@ xfs_qm_newmount( (gquotaondisk && !XFS_IS_GQUOTA_ON(mp)) || (!gquotaondisk && XFS_IS_OQUOTA_ON(mp))) && xfs_dev_is_read_only(mp, "changing quota state")) { - cmn_err(CE_WARN, - "XFS: please mount with%s%s%s%s.", + xfs_warn(mp, "please mount with%s%s%s%s.", (!quotaondisk ? "out quota" : ""), (uquotaondisk ? " usrquota" : ""), (pquotaondisk ? " prjquota" : ""), diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c index 603ab867259e..c82f06778a27 100644 --- a/fs/xfs/quota/xfs_qm_syscalls.c +++ b/fs/xfs/quota/xfs_qm_syscalls.c @@ -936,10 +936,11 @@ struct mutex qcheck_lock; #define DQTEST_LIST_PRINT(l, NXT, title) \ { \ xfs_dqtest_t *dqp; int i = 0;\ - cmn_err(CE_DEBUG, "%s (#%d)", title, (int) (l)->qh_nelems); \ + xfs_debug(NULL, "%s (#%d)", title, (int) (l)->qh_nelems); \ for (dqp = (xfs_dqtest_t *)(l)->qh_next; dqp != NULL; \ dqp = (xfs_dqtest_t *)dqp->NXT) { \ - cmn_err(CE_DEBUG, " %d. \"%d (%s)\" bcnt = %d, icnt = %d", \ + xfs_debug(dqp->q_mount, \ + " %d. \"%d (%s)\" bcnt = %d, icnt = %d", \ ++i, dqp->d_id, DQFLAGTO_TYPESTR(dqp), \ dqp->d_bcount, dqp->d_icount); } \ } @@ -963,16 +964,17 @@ xfs_qm_hashinsert(xfs_dqhash_t *h, xfs_dqtest_t *dqp) } STATIC void xfs_qm_dqtest_print( - xfs_dqtest_t *d) + struct xfs_mount *mp, + struct dqtest *d) { - cmn_err(CE_DEBUG, "-----------DQTEST DQUOT----------------"); - cmn_err(CE_DEBUG, "---- dquot ID = %d", d->d_id); - cmn_err(CE_DEBUG, "---- fs = 0x%p", d->q_mount); - cmn_err(CE_DEBUG, "---- bcount = %Lu (0x%x)", + xfs_debug(mp, "-----------DQTEST DQUOT----------------"); + xfs_debug(mp, "---- dquot ID = %d", d->d_id); + xfs_debug(mp, "---- fs = 0x%p", d->q_mount); + xfs_debug(mp, "---- bcount = %Lu (0x%x)", d->d_bcount, (int)d->d_bcount); - cmn_err(CE_DEBUG, "---- icount = %Lu (0x%x)", + xfs_debug(mp, "---- icount = %Lu (0x%x)", d->d_icount, (int)d->d_icount); - cmn_err(CE_DEBUG, "---------------------------"); + xfs_debug(mp, "---------------------------"); } STATIC void @@ -986,12 +988,14 @@ xfs_qm_dqtest_failed( { qmtest_nfails++; if (error) - cmn_err(CE_DEBUG, "quotacheck failed id=%d, err=%d\nreason: %s", - d->d_id, error, reason); + xfs_debug(dqp->q_mount, + "quotacheck failed id=%d, err=%d\nreason: %s", + d->d_id, error, reason); else - cmn_err(CE_DEBUG, "quotacheck failed id=%d (%s) [%d != %d]", - d->d_id, reason, (int)a, (int)b); - xfs_qm_dqtest_print(d); + xfs_debug(dqp->q_mount, + "quotacheck failed id=%d (%s) [%d != %d]", + d->d_id, reason, (int)a, (int)b); + xfs_qm_dqtest_print(dqp->q_mount, d); if (dqp) xfs_qm_dqprint(dqp); } @@ -1018,9 +1022,9 @@ xfs_dqtest_cmp2( be64_to_cpu(dqp->q_core.d_bcount) >= be64_to_cpu(dqp->q_core.d_blk_softlimit)) { if (!dqp->q_core.d_btimer && dqp->q_core.d_id) { - cmn_err(CE_DEBUG, - "%d [%s] [0x%p] BLK TIMER NOT STARTED", - d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount); + xfs_debug(dqp->q_mount, + "%d [%s] BLK TIMER NOT STARTED", + d->d_id, DQFLAGTO_TYPESTR(d)); err++; } } @@ -1028,16 +1032,16 @@ xfs_dqtest_cmp2( be64_to_cpu(dqp->q_core.d_icount) >= be64_to_cpu(dqp->q_core.d_ino_softlimit)) { if (!dqp->q_core.d_itimer && dqp->q_core.d_id) { - cmn_err(CE_DEBUG, - "%d [%s] [0x%p] INO TIMER NOT STARTED", - d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount); + xfs_debug(dqp->q_mount, + "%d [%s] INO TIMER NOT STARTED", + d->d_id, DQFLAGTO_TYPESTR(d)); err++; } } #ifdef QUOTADEBUG if (!err) { - cmn_err(CE_DEBUG, "%d [%s] [0x%p] qchecked", - d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount); + xfs_debug(dqp->q_mount, "%d [%s] qchecked", + d->d_id, DQFLAGTO_TYPESTR(d)); } #endif return (err); @@ -1220,12 +1224,12 @@ xfs_qm_internalqcheck( xfs_qm_internalqcheck_adjust, 0, NULL, &done); if (error) { - cmn_err(CE_DEBUG, "Bulkstat returned error 0x%x", error); + xfs_debug(mp, "Bulkstat returned error 0x%x", error); break; } } while (!done); - cmn_err(CE_DEBUG, "Checking results against system dquots"); + xfs_debug(mp, "Checking results against system dquots"); for (i = 0; i < qmtest_hashmask; i++) { xfs_dqtest_t *d, *n; xfs_dqhash_t *h; @@ -1243,10 +1247,10 @@ xfs_qm_internalqcheck( } if (qmtest_nfails) { - cmn_err(CE_DEBUG, "******** quotacheck failed ********"); - cmn_err(CE_DEBUG, "failures = %d", qmtest_nfails); + xfs_debug(mp, "******** quotacheck failed ********"); + xfs_debug(mp, "failures = %d", qmtest_nfails); } else { - cmn_err(CE_DEBUG, "******** quotacheck successful! ********"); + xfs_debug(mp, "******** quotacheck successful! ********"); } kmem_free(qmtest_udqtab); kmem_free(qmtest_gdqtab); diff --git a/fs/xfs/quota/xfs_trans_dquot.c b/fs/xfs/quota/xfs_trans_dquot.c index 7de91d1b75c0..2a3648731331 100644 --- a/fs/xfs/quota/xfs_trans_dquot.c +++ b/fs/xfs/quota/xfs_trans_dquot.c @@ -643,8 +643,9 @@ xfs_trans_dqresv( (XFS_IS_OQUOTA_ENFORCED(dqp->q_mount) && (XFS_QM_ISPDQ(dqp) || XFS_QM_ISGDQ(dqp))))) { #ifdef QUOTADEBUG - cmn_err(CE_DEBUG, "BLK Res: nblks=%ld + resbcount=%Ld" - " > hardlimit=%Ld?", nblks, *resbcountp, hardlimit); + xfs_debug(mp, + "BLK Res: nblks=%ld + resbcount=%Ld > hardlimit=%Ld?", + nblks, *resbcountp, hardlimit); #endif if (nblks > 0) { /* diff --git a/fs/xfs/support/debug.c b/fs/xfs/support/debug.c index a1c7141af481..79fae3b33bdd 100644 --- a/fs/xfs/support/debug.c +++ b/fs/xfs/support/debug.c @@ -18,32 +18,6 @@ #include #include "debug.h" -/* xfs_mount.h drags a lot of crap in, sorry.. */ -#include "xfs_sb.h" -#include "xfs_inum.h" -#include "xfs_ag.h" -#include "xfs_mount.h" -#include "xfs_error.h" - -void -cmn_err( - const char *lvl, - const char *fmt, - ...) -{ - struct va_format vaf; - va_list args; - - va_start(args, fmt); - vaf.fmt = fmt; - vaf.va = &args; - - printk("%s%pV", lvl, &vaf); - va_end(args); - - BUG_ON(strncmp(lvl, KERN_EMERG, strlen(KERN_EMERG)) == 0); -} - void assfail(char *expr, char *file, int line) { diff --git a/fs/xfs/support/debug.h b/fs/xfs/support/debug.h index 4a082b9a1161..db36be48a43e 100644 --- a/fs/xfs/support/debug.h +++ b/fs/xfs/support/debug.h @@ -20,18 +20,6 @@ #include -struct xfs_mount; - -#define CE_DEBUG KERN_DEBUG -#define CE_CONT KERN_INFO -#define CE_NOTE KERN_NOTICE -#define CE_WARN KERN_WARNING -#define CE_ALERT KERN_ALERT -#define CE_PANIC KERN_EMERG - -void cmn_err(const char *lvl, const char *fmt, ...) - __attribute__ ((format (printf, 2, 3))); - extern void assfail(char *expr, char *f, int l); #define ASSERT_ALWAYS(expr) \ diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 92612f6b4b3e..fa00788de2f5 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -5778,7 +5778,7 @@ xfs_check_block( else thispa = XFS_BMBT_PTR_ADDR(mp, block, j, dmxr); if (*thispa == *pp) { - cmn_err(CE_WARN, "%s: thispa(%d) == pp(%d) %Ld", + xfs_warn(mp, "%s: thispa(%d) == pp(%d) %Ld", __func__, j, i, (unsigned long long)be64_to_cpu(*thispa)); panic("%s: ptrs are equal in node\n", @@ -5943,11 +5943,11 @@ xfs_bmap_check_leaf_extents( return; error0: - cmn_err(CE_WARN, "%s: at error0", __func__); + xfs_warn(mp, "%s: at error0", __func__); if (bp_release) xfs_trans_brelse(NULL, bp); error_norelse: - cmn_err(CE_WARN, "%s: BAD after btree leaves for %d extents", + xfs_warn(mp, "%s: BAD after btree leaves for %d extents", __func__, i); panic("%s: CORRUPTED BTREE OR SOMETHING", __func__); return; diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index 6f8c21ce0d6d..e5413d96f1af 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c @@ -130,10 +130,12 @@ xfs_buf_item_log_check( orig = bip->bli_orig; buffer = XFS_BUF_PTR(bp); for (x = 0; x < XFS_BUF_COUNT(bp); x++) { - if (orig[x] != buffer[x] && !btst(bip->bli_logged, x)) - cmn_err(CE_PANIC, - "xfs_buf_item_log_check bip %x buffer %x orig %x index %d", - bip, bp, orig, x); + if (orig[x] != buffer[x] && !btst(bip->bli_logged, x)) { + xfs_emerg(bp->b_mount, + "%s: bip %x buffer %x orig %x index %d", + __func__, bip, bp, orig, x); + ASSERT(0); + } } } #else @@ -983,10 +985,9 @@ xfs_buf_iodone_callbacks( if (XFS_BUF_TARGET(bp) != lasttarg || time_after(jiffies, (lasttime + 5*HZ))) { lasttime = jiffies; - cmn_err(CE_ALERT, "Device %s, XFS metadata write error" - " block 0x%llx in %s", + xfs_alert(mp, "Device %s: metadata write error block 0x%llx", XFS_BUFTARG_NAME(XFS_BUF_TARGET(bp)), - (__uint64_t)XFS_BUF_ADDR(bp), mp->m_fsname); + (__uint64_t)XFS_BUF_ADDR(bp)); } lasttarg = XFS_BUF_TARGET(bp); diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c index 1c00bedb3175..6102ac6d1dff 100644 --- a/fs/xfs/xfs_da_btree.c +++ b/fs/xfs/xfs_da_btree.c @@ -1995,13 +1995,12 @@ xfs_da_do_buf( error = mappedbno == -2 ? 0 : XFS_ERROR(EFSCORRUPTED); if (unlikely(error == EFSCORRUPTED)) { if (xfs_error_level >= XFS_ERRLEVEL_LOW) { - cmn_err(CE_ALERT, "xfs_da_do_buf: bno %lld\n", - (long long)bno); - cmn_err(CE_ALERT, "dir: inode %lld\n", + xfs_alert(mp, "%s: bno %lld dir: inode %lld", + __func__, (long long)bno, (long long)dp->i_ino); for (i = 0; i < nmap; i++) { - cmn_err(CE_ALERT, - "[%02d] br_startoff %lld br_startblock %lld br_blockcount %lld br_state %d\n", + xfs_alert(mp, +"[%02d] br_startoff %lld br_startblock %lld br_blockcount %lld br_state %d", i, (long long)mapp[i].br_startoff, (long long)mapp[i].br_startblock, diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c index f9a0864b696a..a0aab7d3294f 100644 --- a/fs/xfs/xfs_dir2_node.c +++ b/fs/xfs/xfs_dir2_node.c @@ -899,10 +899,9 @@ xfs_dir2_leafn_rebalance( if(blk2->index < 0) { state->inleaf = 1; blk2->index = 0; - cmn_err(CE_ALERT, - "xfs_dir2_leafn_rebalance: picked the wrong leaf? reverting original leaf: " - "blk1->index %d\n", - blk1->index); + xfs_alert(args->dp->i_mount, + "%s: picked the wrong leaf? reverting original leaf: blk1->index %d\n", + __func__, blk1->index); } } @@ -1641,26 +1640,22 @@ xfs_dir2_node_addname_int( } if (unlikely(xfs_dir2_db_to_fdb(mp, dbno) != fbno)) { - cmn_err(CE_ALERT, - "xfs_dir2_node_addname_int: dir ino " - "%llu needed freesp block %lld for\n" - " data block %lld, got %lld\n" - " ifbno %llu lastfbno %d\n", - (unsigned long long)dp->i_ino, + xfs_alert(mp, + "%s: dir ino " "%llu needed freesp block %lld for\n" + " data block %lld, got %lld ifbno %llu lastfbno %d", + __func__, (unsigned long long)dp->i_ino, (long long)xfs_dir2_db_to_fdb(mp, dbno), (long long)dbno, (long long)fbno, (unsigned long long)ifbno, lastfbno); if (fblk) { - cmn_err(CE_ALERT, - " fblk 0x%p blkno %llu " - "index %d magic 0x%x\n", + xfs_alert(mp, + " fblk 0x%p blkno %llu index %d magic 0x%x", fblk, (unsigned long long)fblk->blkno, fblk->index, fblk->magic); } else { - cmn_err(CE_ALERT, - " ... fblk is NULL\n"); + xfs_alert(mp, " ... fblk is NULL"); } XFS_ERROR_REPORT("xfs_dir2_node_addname_int", XFS_ERRLEVEL_LOW, mp); diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c index 03028906f00e..39f06336b99d 100644 --- a/fs/xfs/xfs_error.c +++ b/fs/xfs/xfs_error.c @@ -48,7 +48,7 @@ xfs_error_trap(int e) break; if (e != xfs_etrap[i]) continue; - cmn_err(CE_NOTE, "xfs_error_trap: error %d", e); + xfs_notice(NULL, "%s: error %d", __func__, e); BUG(); break; } @@ -74,7 +74,7 @@ xfs_error_test(int error_tag, int *fsidp, char *expression, for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) { if (xfs_etest[i] == error_tag && xfs_etest_fsid[i] == fsid) { - cmn_err(CE_WARN, + xfs_warn(NULL, "Injecting error (%s) at file %s, line %d, on filesystem \"%s\"", expression, file, line, xfs_etest_fsname[i]); return 1; @@ -95,14 +95,14 @@ xfs_errortag_add(int error_tag, xfs_mount_t *mp) for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) { if (xfs_etest_fsid[i] == fsid && xfs_etest[i] == error_tag) { - cmn_err(CE_WARN, "XFS error tag #%d on", error_tag); + xfs_warn(mp, "error tag #%d on", error_tag); return 0; } } for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) { if (xfs_etest[i] == 0) { - cmn_err(CE_WARN, "Turned on XFS error tag #%d", + xfs_warn(mp, "Turned on XFS error tag #%d", error_tag); xfs_etest[i] = error_tag; xfs_etest_fsid[i] = fsid; @@ -114,7 +114,7 @@ xfs_errortag_add(int error_tag, xfs_mount_t *mp) } } - cmn_err(CE_WARN, "error tag overflow, too many turned on"); + xfs_warn(mp, "error tag overflow, too many turned on"); return 1; } @@ -133,7 +133,7 @@ xfs_errortag_clearall(xfs_mount_t *mp, int loud) if ((fsid == 0LL || xfs_etest_fsid[i] == fsid) && xfs_etest[i] != 0) { cleared = 1; - cmn_err(CE_WARN, "Clearing XFS error tag #%d", + xfs_warn(mp, "Clearing XFS error tag #%d", xfs_etest[i]); xfs_etest[i] = 0; xfs_etest_fsid[i] = 0LL; @@ -144,9 +144,7 @@ xfs_errortag_clearall(xfs_mount_t *mp, int loud) } if (loud || cleared) - cmn_err(CE_WARN, - "Cleared all XFS error tags for filesystem \"%s\"", - mp->m_fsname); + xfs_warn(mp, "Cleared all XFS error tags for filesystem"); return 0; } diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c index fc3a2cb2c075..84ebeec16642 100644 --- a/fs/xfs/xfs_ialloc.c +++ b/fs/xfs/xfs_ialloc.c @@ -1055,28 +1055,23 @@ xfs_difree( */ agno = XFS_INO_TO_AGNO(mp, inode); if (agno >= mp->m_sb.sb_agcount) { - cmn_err(CE_WARN, - "xfs_difree: agno >= mp->m_sb.sb_agcount (%d >= %d) on %s. Returning EINVAL.", - agno, mp->m_sb.sb_agcount, mp->m_fsname); + xfs_warn(mp, "%s: agno >= mp->m_sb.sb_agcount (%d >= %d).", + __func__, agno, mp->m_sb.sb_agcount); ASSERT(0); return XFS_ERROR(EINVAL); } agino = XFS_INO_TO_AGINO(mp, inode); if (inode != XFS_AGINO_TO_INO(mp, agno, agino)) { - cmn_err(CE_WARN, - "xfs_difree: inode != XFS_AGINO_TO_INO() " - "(%llu != %llu) on %s. Returning EINVAL.", - (unsigned long long)inode, - (unsigned long long)XFS_AGINO_TO_INO(mp, agno, agino), - mp->m_fsname); + xfs_warn(mp, "%s: inode != XFS_AGINO_TO_INO() (%llu != %llu).", + __func__, (unsigned long long)inode, + (unsigned long long)XFS_AGINO_TO_INO(mp, agno, agino)); ASSERT(0); return XFS_ERROR(EINVAL); } agbno = XFS_AGINO_TO_AGBNO(mp, agino); if (agbno >= mp->m_sb.sb_agblocks) { - cmn_err(CE_WARN, - "xfs_difree: agbno >= mp->m_sb.sb_agblocks (%d >= %d) on %s. Returning EINVAL.", - agbno, mp->m_sb.sb_agblocks, mp->m_fsname); + xfs_warn(mp, "%s: agbno >= mp->m_sb.sb_agblocks (%d >= %d).", + __func__, agbno, mp->m_sb.sb_agblocks); ASSERT(0); return XFS_ERROR(EINVAL); } @@ -1085,9 +1080,8 @@ xfs_difree( */ error = xfs_ialloc_read_agi(mp, tp, agno, &agbp); if (error) { - cmn_err(CE_WARN, - "xfs_difree: xfs_ialloc_read_agi() returned an error %d on %s. Returning error.", - error, mp->m_fsname); + xfs_warn(mp, "%s: xfs_ialloc_read_agi() returned error %d.", + __func__, error); return error; } agi = XFS_BUF_TO_AGI(agbp); @@ -1106,17 +1100,15 @@ xfs_difree( * Look for the entry describing this inode. */ if ((error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, &i))) { - cmn_err(CE_WARN, - "xfs_difree: xfs_inobt_lookup returned() an error %d on %s. Returning error.", - error, mp->m_fsname); + xfs_warn(mp, "%s: xfs_inobt_lookup() returned error %d.", + __func__, error); goto error0; } XFS_WANT_CORRUPTED_GOTO(i == 1, error0); error = xfs_inobt_get_rec(cur, &rec, &i); if (error) { - cmn_err(CE_WARN, - "xfs_difree: xfs_inobt_get_rec() returned an error %d on %s. Returning error.", - error, mp->m_fsname); + xfs_warn(mp, "%s: xfs_inobt_get_rec() returned error %d.", + __func__, error); goto error0; } XFS_WANT_CORRUPTED_GOTO(i == 1, error0); @@ -1157,8 +1149,8 @@ xfs_difree( xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, -(ilen - 1)); if ((error = xfs_btree_delete(cur, &i))) { - cmn_err(CE_WARN, "xfs_difree: xfs_btree_delete returned an error %d on %s.\n", - error, mp->m_fsname); + xfs_warn(mp, "%s: xfs_btree_delete returned error %d.", + __func__, error); goto error0; } @@ -1170,9 +1162,8 @@ xfs_difree( error = xfs_inobt_update(cur, &rec); if (error) { - cmn_err(CE_WARN, - "xfs_difree: xfs_inobt_update returned an error %d on %s.", - error, mp->m_fsname); + xfs_warn(mp, "%s: xfs_inobt_update returned error %d.", + __func__, error); goto error0; } diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index d820ada49b18..da871f532236 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -142,10 +142,9 @@ xfs_imap_to_bp( (int)imap->im_len, buf_flags, &bp); if (error) { if (error != EAGAIN) { - cmn_err(CE_WARN, - "xfs_imap_to_bp: xfs_trans_read_buf()returned " - "an error %d on %s. Returning error.", - error, mp->m_fsname); + xfs_warn(mp, + "%s: xfs_trans_read_buf() returned error %d.", + __func__, error); } else { ASSERT(buf_flags & XBF_TRYLOCK); } @@ -180,12 +179,11 @@ xfs_imap_to_bp( XFS_CORRUPTION_ERROR("xfs_imap_to_bp", XFS_ERRLEVEL_HIGH, mp, dip); #ifdef DEBUG - cmn_err(CE_PANIC, - "Device %s - bad inode magic/vsn " - "daddr %lld #%d (magic=%x)", - XFS_BUFTARG_NAME(mp->m_ddev_targp), + xfs_emerg(mp, + "bad inode magic/vsn daddr %lld #%d (magic=%x)", (unsigned long long)imap->im_blkno, i, be16_to_cpu(dip->di_magic)); + ASSERT(0); #endif xfs_trans_brelse(tp, bp); return XFS_ERROR(EFSCORRUPTED); @@ -1811,9 +1809,8 @@ xfs_iunlink_remove( */ error = xfs_itobp(mp, tp, ip, &dip, &ibp, XBF_LOCK); if (error) { - cmn_err(CE_WARN, - "xfs_iunlink_remove: xfs_itobp() returned an error %d on %s. Returning error.", - error, mp->m_fsname); + xfs_warn(mp, "%s: xfs_itobp() returned error %d.", + __func__, error); return error; } next_agino = be32_to_cpu(dip->di_next_unlinked); @@ -1858,9 +1855,9 @@ xfs_iunlink_remove( error = xfs_inotobp(mp, tp, next_ino, &last_dip, &last_ibp, &last_offset, 0); if (error) { - cmn_err(CE_WARN, - "xfs_iunlink_remove: xfs_inotobp() returned an error %d on %s. Returning error.", - error, mp->m_fsname); + xfs_warn(mp, + "%s: xfs_inotobp() returned error %d.", + __func__, error); return error; } next_agino = be32_to_cpu(last_dip->di_next_unlinked); @@ -1873,9 +1870,8 @@ xfs_iunlink_remove( */ error = xfs_itobp(mp, tp, ip, &dip, &ibp, XBF_LOCK); if (error) { - cmn_err(CE_WARN, - "xfs_iunlink_remove: xfs_itobp() returned an error %d on %s. Returning error.", - error, mp->m_fsname); + xfs_warn(mp, "%s: xfs_itobp(2) returned error %d.", + __func__, error); return error; } next_agino = be32_to_cpu(dip->di_next_unlinked); diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index e39b082eb049..bb3f9a7b24ed 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -133,9 +133,7 @@ xfs_uuid_mount( return 0; if (uuid_is_nil(uuid)) { - cmn_err(CE_WARN, - "XFS: Filesystem %s has nil UUID - can't mount", - mp->m_fsname); + xfs_warn(mp, "Filesystem has nil UUID - can't mount"); return XFS_ERROR(EINVAL); } @@ -163,8 +161,7 @@ xfs_uuid_mount( out_duplicate: mutex_unlock(&xfs_uuid_table_mutex); - cmn_err(CE_WARN, "XFS: Filesystem %s has duplicate UUID - can't mount", - mp->m_fsname); + xfs_warn(mp, "Filesystem has duplicate UUID - can't mount"); return XFS_ERROR(EINVAL); } @@ -867,8 +864,7 @@ xfs_update_alignment(xfs_mount_t *mp) if ((BBTOB(mp->m_dalign) & mp->m_blockmask) || (BBTOB(mp->m_swidth) & mp->m_blockmask)) { if (mp->m_flags & XFS_MOUNT_RETERR) { - cmn_err(CE_WARN, - "XFS: alignment check 1 failed"); + xfs_warn(mp, "alignment check 1 failed"); return XFS_ERROR(EINVAL); } mp->m_dalign = mp->m_swidth = 0; @@ -1041,14 +1037,14 @@ xfs_check_sizes(xfs_mount_t *mp) d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks); if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_dblocks) { - cmn_err(CE_WARN, "XFS: filesystem size mismatch detected"); + xfs_warn(mp, "filesystem size mismatch detected"); return XFS_ERROR(EFBIG); } bp = xfs_buf_read_uncached(mp, mp->m_ddev_targp, d - XFS_FSS_TO_BB(mp, 1), BBTOB(XFS_FSS_TO_BB(mp, 1)), 0); if (!bp) { - cmn_err(CE_WARN, "XFS: last sector read failed"); + xfs_warn(mp, "last sector read failed"); return EIO; } xfs_buf_relse(bp); @@ -1056,14 +1052,14 @@ xfs_check_sizes(xfs_mount_t *mp) if (mp->m_logdev_targp != mp->m_ddev_targp) { d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks); if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_logblocks) { - cmn_err(CE_WARN, "XFS: log size mismatch detected"); + xfs_warn(mp, "log size mismatch detected"); return XFS_ERROR(EFBIG); } bp = xfs_buf_read_uncached(mp, mp->m_logdev_targp, d - XFS_FSB_TO_BB(mp, 1), XFS_FSB_TO_B(mp, 1), 0); if (!bp) { - cmn_err(CE_WARN, "XFS: log device read failed"); + xfs_warn(mp, "log device read failed"); return EIO; } xfs_buf_relse(bp); @@ -1175,8 +1171,7 @@ xfs_mountfs( * transaction subsystem is online. */ if (xfs_sb_has_mismatched_features2(sbp)) { - cmn_err(CE_WARN, - "XFS: correcting sb_features alignment problem"); + xfs_warn(mp, "correcting sb_features alignment problem"); sbp->sb_features2 |= sbp->sb_bad_features2; sbp->sb_bad_features2 = sbp->sb_features2; mp->m_update_flags |= XFS_SB_FEATURES2 | XFS_SB_BAD_FEATURES2; @@ -1255,7 +1250,7 @@ xfs_mountfs( */ error = xfs_rtmount_init(mp); if (error) { - cmn_err(CE_WARN, "XFS: RT mount failed"); + xfs_warn(mp, "RT mount failed"); goto out_remove_uuid; } @@ -1286,12 +1281,12 @@ xfs_mountfs( INIT_RADIX_TREE(&mp->m_perag_tree, GFP_ATOMIC); error = xfs_initialize_perag(mp, sbp->sb_agcount, &mp->m_maxagi); if (error) { - cmn_err(CE_WARN, "XFS: Failed per-ag init: %d", error); + xfs_warn(mp, "Failed per-ag init: %d", error); goto out_remove_uuid; } if (!sbp->sb_logblocks) { - cmn_err(CE_WARN, "XFS: no log defined"); + xfs_warn(mp, "no log defined"); XFS_ERROR_REPORT("xfs_mountfs", XFS_ERRLEVEL_LOW, mp); error = XFS_ERROR(EFSCORRUPTED); goto out_free_perag; @@ -1304,7 +1299,7 @@ xfs_mountfs( XFS_FSB_TO_DADDR(mp, sbp->sb_logstart), XFS_FSB_TO_BB(mp, sbp->sb_logblocks)); if (error) { - cmn_err(CE_WARN, "XFS: log mount failed"); + xfs_warn(mp, "log mount failed"); goto out_free_perag; } @@ -1341,16 +1336,14 @@ xfs_mountfs( */ error = xfs_iget(mp, NULL, sbp->sb_rootino, 0, XFS_ILOCK_EXCL, &rip); if (error) { - cmn_err(CE_WARN, "XFS: failed to read root inode"); + xfs_warn(mp, "failed to read root inode"); goto out_log_dealloc; } ASSERT(rip != NULL); if (unlikely((rip->i_d.di_mode & S_IFMT) != S_IFDIR)) { - cmn_err(CE_WARN, "XFS: corrupted root inode"); - cmn_err(CE_WARN, "Device %s - root %llu is not a directory", - XFS_BUFTARG_NAME(mp->m_ddev_targp), + xfs_warn(mp, "corrupted root inode %llu: not a directory", (unsigned long long)rip->i_ino); xfs_iunlock(rip, XFS_ILOCK_EXCL); XFS_ERROR_REPORT("xfs_mountfs_int(2)", XFS_ERRLEVEL_LOW, @@ -1370,7 +1363,7 @@ xfs_mountfs( /* * Free up the root inode. */ - cmn_err(CE_WARN, "XFS: failed to read RT inodes"); + xfs_warn(mp, "failed to read RT inodes"); goto out_rele_rip; } @@ -1382,7 +1375,7 @@ xfs_mountfs( if (mp->m_update_flags && !(mp->m_flags & XFS_MOUNT_RDONLY)) { error = xfs_mount_log_sb(mp, mp->m_update_flags); if (error) { - cmn_err(CE_WARN, "XFS: failed to write sb changes"); + xfs_warn(mp, "failed to write sb changes"); goto out_rtunmount; } } @@ -1403,10 +1396,7 @@ xfs_mountfs( * quotachecked license. */ if (mp->m_sb.sb_qflags & XFS_ALL_QUOTA_ACCT) { - cmn_err(CE_NOTE, - "XFS: resetting qflags for filesystem %s", - mp->m_fsname); - + xfs_notice(mp, "resetting quota flags"); error = xfs_mount_reset_sbqflags(mp); if (error) return error; @@ -1420,7 +1410,7 @@ xfs_mountfs( */ error = xfs_log_mount_finish(mp); if (error) { - cmn_err(CE_WARN, "XFS: log mount finish failed"); + xfs_warn(mp, "log mount finish failed"); goto out_rtunmount; } @@ -1449,8 +1439,8 @@ xfs_mountfs( resblks = xfs_default_resblks(mp); error = xfs_reserve_blocks(mp, &resblks, NULL); if (error) - cmn_err(CE_WARN, "XFS: Unable to allocate reserve " - "blocks. Continuing without a reserve pool."); + xfs_warn(mp, + "Unable to allocate reserve blocks. Continuing without reserve pool."); } return 0; @@ -1539,12 +1529,12 @@ xfs_unmountfs( resblks = 0; error = xfs_reserve_blocks(mp, &resblks, NULL); if (error) - cmn_err(CE_WARN, "XFS: Unable to free reserved block pool. " + xfs_warn(mp, "Unable to free reserved block pool. " "Freespace may not be correct on next mount."); error = xfs_log_sbcount(mp, 1); if (error) - cmn_err(CE_WARN, "XFS: Unable to update superblock counters. " + xfs_warn(mp, "Unable to update superblock counters. " "Freespace may not be correct on next mount."); xfs_unmountfs_writesb(mp); xfs_unmountfs_wait(mp); /* wait for async bufs */ @@ -2027,10 +2017,8 @@ xfs_dev_is_read_only( if (xfs_readonly_buftarg(mp->m_ddev_targp) || xfs_readonly_buftarg(mp->m_logdev_targp) || (mp->m_rtdev_targp && xfs_readonly_buftarg(mp->m_rtdev_targp))) { - cmn_err(CE_NOTE, - "XFS: %s required on read-only device.", message); - cmn_err(CE_NOTE, - "XFS: write access unavailable, cannot proceed."); + xfs_notice(mp, "%s required on read-only device.", message); + xfs_notice(mp, "write access unavailable, cannot proceed."); return EROFS; } return 0; diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index fbff89344bad..8f76fdff4f46 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -2210,8 +2210,8 @@ xfs_rtmount_init( if (sbp->sb_rblocks == 0) return 0; if (mp->m_rtdev_targp == NULL) { - cmn_err(CE_WARN, - "XFS: This filesystem has a realtime volume, use rtdev=device option"); + xfs_warn(mp, + "Filesystem has a realtime volume, use rtdev=device option"); return XFS_ERROR(ENODEV); } mp->m_rsumlevels = sbp->sb_rextslog + 1; @@ -2225,7 +2225,7 @@ xfs_rtmount_init( */ d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_rblocks); if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_rblocks) { - cmn_err(CE_WARN, "XFS: realtime mount -- %llu != %llu", + xfs_warn(mp, "realtime mount -- %llu != %llu", (unsigned long long) XFS_BB_TO_FSB(mp, d), (unsigned long long) mp->m_sb.sb_rblocks); return XFS_ERROR(EFBIG); @@ -2234,7 +2234,7 @@ xfs_rtmount_init( d - XFS_FSB_TO_BB(mp, 1), XFS_FSB_TO_B(mp, 1), 0); if (!bp) { - cmn_err(CE_WARN, "XFS: realtime device size check failed"); + xfs_warn(mp, "realtime device size check failed"); return EIO; } xfs_buf_relse(bp); diff --git a/fs/xfs/xfs_rtalloc.h b/fs/xfs/xfs_rtalloc.h index ff614c29b441..09e1f4f35e97 100644 --- a/fs/xfs/xfs_rtalloc.h +++ b/fs/xfs/xfs_rtalloc.h @@ -154,7 +154,7 @@ xfs_rtmount_init( if (mp->m_sb.sb_rblocks == 0) return 0; - cmn_err(CE_WARN, "XFS: Not built with CONFIG_XFS_RT"); + xfs_warn(mp, "Not built with CONFIG_XFS_RT"); return ENOSYS; } # define xfs_rtmount_inodes(m) (((mp)->m_sb.sb_rblocks == 0)? 0 : (ENOSYS)) diff --git a/fs/xfs/xfs_rw.c b/fs/xfs/xfs_rw.c index ae6f49613412..d6d6fdfe9422 100644 --- a/fs/xfs/xfs_rw.c +++ b/fs/xfs/xfs_rw.c @@ -49,9 +49,9 @@ xfs_do_force_shutdown( logerror = flags & SHUTDOWN_LOG_IO_ERROR; if (!(flags & SHUTDOWN_FORCE_UMOUNT)) { - cmn_err(CE_NOTE, "xfs_force_shutdown(%s,0x%x) called from " - "line %d of file %s. Return address = 0x%p", - mp->m_fsname, flags, lnnum, fname, __return_address); + xfs_notice(mp, + "%s(0x%x) called from line %d of file %s. Return address = 0x%p", + __func__, flags, lnnum, fname, __return_address); } /* * No need to duplicate efforts. @@ -86,8 +86,8 @@ xfs_do_force_shutdown( } } if (!(flags & SHUTDOWN_FORCE_UMOUNT)) { - cmn_err(CE_ALERT, "Please umount the filesystem, " - "and rectify the problem(s)"); + xfs_alert(mp, + "Please umount the filesystem and rectify the problem(s)"); } } @@ -101,10 +101,9 @@ xfs_ioerror_alert( xfs_buf_t *bp, xfs_daddr_t blkno) { - cmn_err(CE_ALERT, - "I/O error in filesystem (\"%s\") meta-data dev %s block 0x%llx" - " (\"%s\") error %d buf count %zd", - (!mp || !mp->m_fsname) ? "(fs name not set)" : mp->m_fsname, + xfs_alert(mp, + "I/O error occurred: meta-data dev %s block 0x%llx" + " (\"%s\") error %d buf count %zd", XFS_BUFTARG_NAME(XFS_BUF_TARGET(bp)), (__uint64_t)blkno, func, XFS_BUF_GETERROR(bp), XFS_BUF_COUNT(bp)); diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c index c47918c302a5..3bea66132334 100644 --- a/fs/xfs/xfs_trans_buf.c +++ b/fs/xfs/xfs_trans_buf.c @@ -305,7 +305,7 @@ xfs_trans_read_buf( if (xfs_error_target == target) { if (((xfs_req_num++) % xfs_error_mod) == 0) { xfs_buf_relse(bp); - cmn_err(CE_DEBUG, "Returning error!\n"); + xfs_debug(mp, "Returning error!"); return XFS_ERROR(EIO); } } @@ -403,7 +403,7 @@ xfs_trans_read_buf( xfs_force_shutdown(tp->t_mountp, SHUTDOWN_META_IO_ERROR); xfs_buf_relse(bp); - cmn_err(CE_DEBUG, "Returning trans error!\n"); + xfs_debug(mp, "Returning trans error!"); return XFS_ERROR(EIO); } } @@ -427,7 +427,7 @@ shutdown_abort: */ #if defined(DEBUG) if (XFS_BUF_ISSTALE(bp) && XFS_BUF_ISDELAYWRITE(bp)) - cmn_err(CE_NOTE, "about to pop assert, bp == 0x%p", bp); + xfs_notice(mp, "about to pop assert, bp == 0x%p", bp); #endif ASSERT((XFS_BUF_BFLAGS(bp) & (XBF_STALE|XBF_DELWRI)) != (XBF_STALE|XBF_DELWRI)); diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index e919ae1e9c65..37d8146ee15b 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -1189,9 +1189,8 @@ xfs_inactive( * inode might be lost for a long time or forever. */ if (!XFS_FORCED_SHUTDOWN(mp)) { - cmn_err(CE_NOTE, - "xfs_inactive: xfs_ifree() returned an error = %d on %s", - error, mp->m_fsname); + xfs_notice(mp, "%s: xfs_ifree returned error %d", + __func__, error); xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR); } xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT); -- cgit From 9130090b5f04f7e7bc29b944e0b1ba494fff3f98 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Mon, 7 Mar 2011 10:09:35 +1100 Subject: xfs: kill support/debug.[ch] The remaining functionality in debug.[ch] is effectively just assert handling, conditional debug definitions and hex dumping. The hex dumping and assert function can be moved into the new printk module, while the rest can be moved into top-level header files. This allows fs/xfs/support/debug.[ch] to be completely removed from the codebase. Signed-off-by: Dave Chinner Reviewed-by: Alex Elder Reviewed-by: Christoph Hellwig --- fs/xfs/Makefile | 4 +--- fs/xfs/linux-2.6/xfs_linux.h | 22 ++++++++++++++++++++- fs/xfs/linux-2.6/xfs_message.c | 14 +++++++++++++ fs/xfs/linux-2.6/xfs_message.h | 4 ++++ fs/xfs/support/debug.c | 33 ------------------------------- fs/xfs/support/debug.h | 45 ------------------------------------------ fs/xfs/xfs_error.h | 4 ---- 7 files changed, 40 insertions(+), 86 deletions(-) delete mode 100644 fs/xfs/support/debug.c delete mode 100644 fs/xfs/support/debug.h (limited to 'fs') diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index 077784ed6a7f..fee7901841e3 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -111,6 +111,4 @@ xfs-y += $(addprefix $(XFS_LINUX)/, \ xfs_xattr.o) # Objects in support/ -xfs-y += $(addprefix support/, \ - debug.o \ - uuid.o) +xfs-y += support/uuid.o diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h index 1189bfcbcd3e..244be9cbfe78 100644 --- a/fs/xfs/linux-2.6/xfs_linux.h +++ b/fs/xfs/linux-2.6/xfs_linux.h @@ -39,7 +39,6 @@ #include #include -#include #include #include @@ -281,4 +280,25 @@ static inline __uint64_t howmany_64(__uint64_t x, __uint32_t y) #define __arch_pack #endif +#define ASSERT_ALWAYS(expr) \ + (unlikely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__)) + +#ifndef DEBUG +#define ASSERT(expr) ((void)0) + +#ifndef STATIC +# define STATIC static noinline +#endif + +#else /* DEBUG */ + +#define ASSERT(expr) \ + (unlikely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__)) + +#ifndef STATIC +# define STATIC noinline +#endif + +#endif /* DEBUG */ + #endif /* __XFS_LINUX__ */ diff --git a/fs/xfs/linux-2.6/xfs_message.c b/fs/xfs/linux-2.6/xfs_message.c index 6f3368eec25d..8fe8cf69d809 100644 --- a/fs/xfs/linux-2.6/xfs_message.c +++ b/fs/xfs/linux-2.6/xfs_message.c @@ -117,3 +117,17 @@ xfs_alert_tag( return r; } + +void +assfail(char *expr, char *file, int line) +{ + xfs_emerg(NULL, "Assertion failed: %s, file: %s, line: %d", + expr, file, line); + BUG(); +} + +void +xfs_hex_dump(void *p, int length) +{ + print_hex_dump(KERN_ALERT, "", DUMP_PREFIX_ADDRESS, 16, 1, p, length, 1); +} diff --git a/fs/xfs/linux-2.6/xfs_message.h b/fs/xfs/linux-2.6/xfs_message.h index 8d2df0175304..e77ffa16745b 100644 --- a/fs/xfs/linux-2.6/xfs_message.h +++ b/fs/xfs/linux-2.6/xfs_message.h @@ -31,4 +31,8 @@ extern int xfs_debug(const struct xfs_mount *mp, const char *fmt, ...) #define xfs_debug(mp, fmt, ...) (0) #endif +extern void assfail(char *expr, char *f, int l); + +extern void xfs_hex_dump(void *p, int length); + #endif /* __XFS_MESSAGE_H */ diff --git a/fs/xfs/support/debug.c b/fs/xfs/support/debug.c deleted file mode 100644 index 79fae3b33bdd..000000000000 --- a/fs/xfs/support/debug.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -#include -#include "debug.h" - -void -assfail(char *expr, char *file, int line) -{ - printk(KERN_CRIT "Assertion failed: %s, file: %s, line: %d\n", expr, - file, line); - BUG(); -} - -void -xfs_hex_dump(void *p, int length) -{ - print_hex_dump(KERN_ALERT, "", DUMP_PREFIX_ADDRESS, 16, 1, p, length, 1); -} diff --git a/fs/xfs/support/debug.h b/fs/xfs/support/debug.h deleted file mode 100644 index db36be48a43e..000000000000 --- a/fs/xfs/support/debug.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2000-2005 Silicon Graphics, Inc. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -#ifndef __XFS_SUPPORT_DEBUG_H__ -#define __XFS_SUPPORT_DEBUG_H__ - -#include - -extern void assfail(char *expr, char *f, int l); - -#define ASSERT_ALWAYS(expr) \ - (unlikely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__)) - -#ifndef DEBUG -#define ASSERT(expr) ((void)0) - -#ifndef STATIC -# define STATIC static noinline -#endif - -#else /* DEBUG */ - -#define ASSERT(expr) \ - (unlikely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__)) - -#ifndef STATIC -# define STATIC noinline -#endif - -#endif /* DEBUG */ -#endif /* __XFS_SUPPORT_DEBUG_H__ */ diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h index e8360514c250..079a367f44ee 100644 --- a/fs/xfs/xfs_error.h +++ b/fs/xfs/xfs_error.h @@ -158,8 +158,4 @@ extern int xfs_errortag_clearall(struct xfs_mount *mp, int loud); #define XFS_PTAG_SHUTDOWN_LOGERROR 0x00000040 #define XFS_PTAG_FSBLOCK_ZERO 0x00000080 -struct xfs_mount; - -extern void xfs_hex_dump(void *p, int length); - #endif /* __XFS_ERROR_H__ */ -- cgit From f32cb53219a956b96a4cd1ee7c6b1b8a48d40e9f Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Mon, 17 Jan 2011 15:45:59 +0900 Subject: locks: use assign_type() Signed-off-by: Namhyung Kim Signed-off-by: J. Bruce Fields --- fs/locks.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'fs') diff --git a/fs/locks.c b/fs/locks.c index 0f3998291f78..2c2d3b804d62 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -415,17 +415,7 @@ static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl, fl->fl_ops = NULL; fl->fl_lmops = NULL; - switch (l->l_type) { - case F_RDLCK: - case F_WRLCK: - case F_UNLCK: - fl->fl_type = l->l_type; - break; - default: - return -EINVAL; - } - - return (0); + return assign_type(fl, l->l_type); } #endif -- cgit From 35079582e72efcabf7c70f3d3ee4f96e6f196606 Mon Sep 17 00:00:00 2001 From: Shan Wei Date: Fri, 14 Jan 2011 17:35:59 +0800 Subject: nfsd: kill unused macro definition These macros had never been used for several years. So, remove them. Signed-off-by: Shan Wei Signed-off-by: J. Bruce Fields --- fs/nfsd/export.c | 1 - fs/nfsd/nfs4idmap.c | 1 - fs/nfsd/nfs4state.c | 2 +- 3 files changed, 1 insertion(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 8b31e5f8795d..ad000aeb21a2 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -299,7 +299,6 @@ svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old) #define EXPORT_HASHBITS 8 #define EXPORT_HASHMAX (1<< EXPORT_HASHBITS) -#define EXPORT_HASHMASK (EXPORT_HASHMAX -1) static struct cache_head *export_table[EXPORT_HASHMAX]; diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c index 6d2c397d458b..55780a22fdbd 100644 --- a/fs/nfsd/nfs4idmap.c +++ b/fs/nfsd/nfs4idmap.c @@ -63,7 +63,6 @@ struct ent { #define ENT_HASHBITS 8 #define ENT_HASHMAX (1 << ENT_HASHBITS) -#define ENT_HASHMASK (ENT_HASHMAX - 1) static void ent_init(struct cache_head *cnew, struct cache_head *citm) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 54b60bfceb8d..c4f2b0f63e46 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -148,7 +148,7 @@ static struct list_head ownerstr_hashtbl[OWNER_HASH_SIZE]; /* hash table for nfs4_file */ #define FILE_HASH_BITS 8 #define FILE_HASH_SIZE (1 << FILE_HASH_BITS) -#define FILE_HASH_MASK (FILE_HASH_SIZE - 1) + /* hash table for (open)nfs4_stateid */ #define STATEID_HASH_BITS 10 #define STATEID_HASH_SIZE (1 << STATEID_HASH_BITS) -- cgit From 46d4cef9cf54f2f8b15216e3f6dad69750c69e0c Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sun, 6 Mar 2011 00:30:35 +0100 Subject: NFSD, VFS: Remove dead code in nfsd_rename() Currently we have the following code in fs/nfsd/vfs.c::nfsd_rename() : ... host_err = nfsd_break_lease(odentry->d_inode); if (host_err) goto out_drop_write; if (ndentry->d_inode) { host_err = nfsd_break_lease(ndentry->d_inode); if (host_err) goto out_drop_write; } if (host_err) goto out_drop_write; ... 'host_err' is guaranteed to be 0 by the time we test 'ndentry->d_inode'. If 'host_err' becomes != 0 inside the 'if' statement, then we goto 'out_drop_write'. So, after the 'if' statement there is no way that 'host_err' can be anything but 0, so the test afterwards is just dead code. This patch removes the dead code. Signed-off-by: Jesper Juhl Signed-off-by: J. Bruce Fields --- fs/nfsd/vfs.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'fs') diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index da1d9701f8e4..9cc626b70fb6 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1749,8 +1749,6 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, if (host_err) goto out_drop_write; } - if (host_err) - goto out_drop_write; host_err = vfs_rename(fdir, odentry, tdir, ndentry); if (!host_err) { host_err = commit_metadata(tfhp); -- cgit From b0b0c0a26e846ae6646af9f59a3d2ea06b49cbc7 Mon Sep 17 00:00:00 2001 From: Kevin Coffman Date: Wed, 2 Mar 2011 19:51:42 -0500 Subject: nfsd: add proc file listing kernel's gss_krb5 enctypes Add a new proc file which lists the encryption types supported by the kernel's gss_krb5 code. Newer MIT Kerberos libraries support the assertion of acceptor subkeys. This enctype information allows user-land (svcgssd) to request that the Kerberos libraries limit the encryption types that it uses when generating the subkeys. Signed-off-by: Kevin Coffman Signed-off-by: J. Bruce Fields --- fs/nfsd/nfsctl.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 33b3e2b06779..35dcfa8eba21 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -12,13 +12,14 @@ #include #include #include +#include #include "idmap.h" #include "nfsd.h" #include "cache.h" /* - * We have a single directory with 9 nodes in it. + * We have a single directory with several nodes in it. */ enum { NFSD_Root = 1, @@ -42,6 +43,7 @@ enum { NFSD_Versions, NFSD_Ports, NFSD_MaxBlkSize, + NFSD_SupportedEnctypes, /* * The below MUST come last. Otherwise we leave a hole in nfsd_files[] * with !CONFIG_NFSD_V4 and simple_fill_super() goes oops @@ -187,6 +189,32 @@ static struct file_operations export_features_operations = { .release = single_release, }; +static int supported_enctypes_show(struct seq_file *m, void *v) +{ + struct gss_api_mech *k5mech; + + k5mech = gss_mech_get_by_name("krb5"); + if (k5mech == NULL) + goto out; + if (k5mech->gm_upcall_enctypes != NULL) + seq_printf(m, k5mech->gm_upcall_enctypes); + gss_mech_put(k5mech); +out: + return 0; +} + +static int supported_enctypes_open(struct inode *inode, struct file *file) +{ + return single_open(file, supported_enctypes_show, NULL); +} + +static struct file_operations supported_enctypes_ops = { + .open = supported_enctypes_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + extern int nfsd_pool_stats_open(struct inode *inode, struct file *file); extern int nfsd_pool_stats_release(struct inode *inode, struct file *file); @@ -1397,6 +1425,7 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent) [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR}, [NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO}, [NFSD_MaxBlkSize] = {"max_block_size", &transaction_ops, S_IWUSR|S_IRUGO}, + [NFSD_SupportedEnctypes] = {"supported_krb5_enctypes", &supported_enctypes_ops, S_IRUGO}, #ifdef CONFIG_NFSD_V4 [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR}, [NFSD_Gracetime] = {"nfsv4gracetime", &transaction_ops, S_IWUSR|S_IRUSR}, -- cgit From 5ece3cafbd88d4da5c734e1810c4a2e6474b57b2 Mon Sep 17 00:00:00 2001 From: Mi Jinlong Date: Fri, 18 Feb 2011 09:08:31 +0800 Subject: nfsd41: modify the members value of nfsd4_op_flags The members of nfsd4_op_flags, (ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS) equals to ALLOWED_AS_FIRST_OP, maybe that's not what we want. OP_PUTROOTFH with op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS, can't appears as the first operation with out SEQUENCE ops. This patch modify the wrong value of ALLOWED_WITHOUT_FH etc which was introduced by f9bb94c4. Cc: stable@kernel.org Reviewed-by: Benny Halevy Signed-off-by: Mi Jinlong Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4proc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index db52546143d1..5fcb1396a7e3 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -984,8 +984,8 @@ typedef __be32(*nfsd4op_func)(struct svc_rqst *, struct nfsd4_compound_state *, void *); enum nfsd4_op_flags { ALLOWED_WITHOUT_FH = 1 << 0, /* No current filehandle required */ - ALLOWED_ON_ABSENT_FS = 2 << 0, /* ops processed on absent fs */ - ALLOWED_AS_FIRST_OP = 3 << 0, /* ops reqired first in compound */ + ALLOWED_ON_ABSENT_FS = 1 << 1, /* ops processed on absent fs */ + ALLOWED_AS_FIRST_OP = 1 << 2, /* ops reqired first in compound */ }; struct nfsd4_operation { -- cgit From 25b18d39cca207f8559af1aac00313deda2d652e Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Fri, 11 Feb 2011 15:23:27 +0900 Subject: nilfs2: decrement inodes count only if raw inode was successfully deleted This fixes the issue that inodes count will not add up after removal of raw inodes fails. Hence, this prevents possible under flow of the inodes count. Signed-off-by: Ryusuke Konishi --- fs/nilfs2/inode.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 2fd440d8d6b8..3a6967d14e1c 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c @@ -707,6 +707,7 @@ void nilfs_evict_inode(struct inode *inode) struct nilfs_transaction_info ti; struct super_block *sb = inode->i_sb; struct nilfs_inode_info *ii = NILFS_I(inode); + int ret; if (inode->i_nlink || !ii->i_root || unlikely(is_bad_inode(inode))) { if (inode->i_data.nrpages) @@ -725,8 +726,9 @@ void nilfs_evict_inode(struct inode *inode) nilfs_mark_inode_dirty(inode); end_writeback(inode); - nilfs_ifile_delete_inode(ii->i_root->ifile, inode->i_ino); - atomic_dec(&ii->i_root->inodes_count); + ret = nilfs_ifile_delete_inode(ii->i_root->ifile, inode->i_ino); + if (!ret) + atomic_dec(&ii->i_root->inodes_count); nilfs_clear_inode(inode); -- cgit From 9954e7af14868b8b79e76b7b88daaf0b3866db33 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Wed, 23 Feb 2011 02:26:17 +0900 Subject: nilfs2: add free entries count only if clear bit operation succeeded Three functions of the current persistent object allocator, nilfs_palloc_commit_free_entry, nilfs_palloc_abort_alloc_entry, and nilfs_palloc_freev functions unconditionally add a counter after doing clear bit operation on a bitmap block. If the clear bit operation overlapped, the counter will not add up. This fixes the issue by making the counter operations conditional. Signed-off-by: Ryusuke Konishi --- fs/nilfs2/alloc.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/nilfs2/alloc.c b/fs/nilfs2/alloc.c index d7fd696e595c..0a0a66d98cce 100644 --- a/fs/nilfs2/alloc.c +++ b/fs/nilfs2/alloc.c @@ -521,8 +521,8 @@ void nilfs_palloc_commit_free_entry(struct inode *inode, group_offset, bitmap)) printk(KERN_WARNING "%s: entry number %llu already freed\n", __func__, (unsigned long long)req->pr_entry_nr); - - nilfs_palloc_group_desc_add_entries(inode, group, desc, 1); + else + nilfs_palloc_group_desc_add_entries(inode, group, desc, 1); kunmap(req->pr_bitmap_bh->b_page); kunmap(req->pr_desc_bh->b_page); @@ -558,8 +558,8 @@ void nilfs_palloc_abort_alloc_entry(struct inode *inode, group_offset, bitmap)) printk(KERN_WARNING "%s: entry number %llu already freed\n", __func__, (unsigned long long)req->pr_entry_nr); - - nilfs_palloc_group_desc_add_entries(inode, group, desc, 1); + else + nilfs_palloc_group_desc_add_entries(inode, group, desc, 1); kunmap(req->pr_bitmap_bh->b_page); kunmap(req->pr_desc_bh->b_page); @@ -665,7 +665,7 @@ int nilfs_palloc_freev(struct inode *inode, __u64 *entry_nrs, size_t nitems) for (j = i, n = 0; (j < nitems) && nilfs_palloc_group_is_in(inode, group, entry_nrs[j]); - j++, n++) { + j++) { nilfs_palloc_group(inode, entry_nrs[j], &group_offset); if (!nilfs_clear_bit_atomic( nilfs_mdt_bgl_lock(inode, group), @@ -674,6 +674,8 @@ int nilfs_palloc_freev(struct inode *inode, __u64 *entry_nrs, size_t nitems) "%s: entry number %llu already freed\n", __func__, (unsigned long long)entry_nrs[j]); + } else { + n++; } } nilfs_palloc_group_desc_add_entries(inode, group, desc, n); -- cgit From f0c9f242f947a37675a883deca7f722cac935b0e Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Thu, 20 Jan 2011 02:09:52 +0900 Subject: nilfs2: use common file attribute macros Replaces uses of own inode flags (i.e. NILFS_SECRM_FL, NILFS_UNRM_FL, NILFS_COMPR_FL, and so forth) with common inode flags, and removes the own flag declarations. Signed-off-by: Ryusuke Konishi --- fs/nilfs2/dir.c | 3 --- fs/nilfs2/inode.c | 14 +++++++------- 2 files changed, 7 insertions(+), 10 deletions(-) (limited to 'fs') diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c index 9d45773b79e6..b72833a2cc1c 100644 --- a/fs/nilfs2/dir.c +++ b/fs/nilfs2/dir.c @@ -440,7 +440,6 @@ void nilfs_set_link(struct inode *dir, struct nilfs_dir_entry *de, nilfs_commit_chunk(page, mapping, from, to); nilfs_put_page(page); dir->i_mtime = dir->i_ctime = CURRENT_TIME; -/* NILFS_I(dir)->i_flags &= ~NILFS_BTREE_FL; */ } /* @@ -531,7 +530,6 @@ got_it: nilfs_set_de_type(de, inode); nilfs_commit_chunk(page, page->mapping, from, to); dir->i_mtime = dir->i_ctime = CURRENT_TIME; -/* NILFS_I(dir)->i_flags &= ~NILFS_BTREE_FL; */ nilfs_mark_inode_dirty(dir); /* OFFSET_CACHE */ out_put: @@ -579,7 +577,6 @@ int nilfs_delete_entry(struct nilfs_dir_entry *dir, struct page *page) dir->inode = 0; nilfs_commit_chunk(page, mapping, from, to); inode->i_ctime = inode->i_mtime = CURRENT_TIME; -/* NILFS_I(inode)->i_flags &= ~NILFS_BTREE_FL; */ out: nilfs_put_page(page); return err; diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 3a6967d14e1c..f61f80c7f7cc 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c @@ -317,9 +317,9 @@ struct inode *nilfs_new_inode(struct inode *dir, int mode) ii->i_flags = NILFS_I(dir)->i_flags; if (S_ISLNK(mode)) - ii->i_flags &= ~(NILFS_IMMUTABLE_FL | NILFS_APPEND_FL); + ii->i_flags &= ~(FS_IMMUTABLE_FL | FS_APPEND_FL); if (!S_ISDIR(mode)) - ii->i_flags &= ~NILFS_DIRSYNC_FL; + ii->i_flags &= ~FS_DIRSYNC_FL; /* ii->i_file_acl = 0; */ /* ii->i_dir_acl = 0; */ @@ -359,17 +359,17 @@ void nilfs_set_inode_flags(struct inode *inode) inode->i_flags &= ~(S_SYNC | S_APPEND | S_IMMUTABLE | S_NOATIME | S_DIRSYNC); - if (flags & NILFS_SYNC_FL) + if (flags & FS_SYNC_FL) inode->i_flags |= S_SYNC; - if (flags & NILFS_APPEND_FL) + if (flags & FS_APPEND_FL) inode->i_flags |= S_APPEND; - if (flags & NILFS_IMMUTABLE_FL) + if (flags & FS_IMMUTABLE_FL) inode->i_flags |= S_IMMUTABLE; #ifndef NILFS_ATIME_DISABLE - if (flags & NILFS_NOATIME_FL) + if (flags & FS_NOATIME_FL) #endif inode->i_flags |= S_NOATIME; - if (flags & NILFS_DIRSYNC_FL) + if (flags & FS_DIRSYNC_FL) inode->i_flags |= S_DIRSYNC; mapping_set_gfp_mask(inode->i_mapping, mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS); -- cgit From 32f4aeb31583a85c1e9a5d6d485055c090cebbfb Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Thu, 20 Jan 2011 02:09:52 +0900 Subject: nilfs2: mark S_NOATIME on inodes only if NOATIME attribute is set At present, nilfs marks S_NOATIME flag on all inodes. This restricts nilfs_set_inode_flags function so that it marks S_NOATIME only if a given inode has an FS_NOATIME_FL flag. Although nilfs does not support atime yet, touch_atime() still safely returns on IS_NOATIME check since MS_NOATIME is always set on sb. Signed-off-by: Ryusuke Konishi --- fs/nilfs2/inode.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'fs') diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index f61f80c7f7cc..2e6ac8e9203a 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c @@ -365,9 +365,7 @@ void nilfs_set_inode_flags(struct inode *inode) inode->i_flags |= S_APPEND; if (flags & FS_IMMUTABLE_FL) inode->i_flags |= S_IMMUTABLE; -#ifndef NILFS_ATIME_DISABLE if (flags & FS_NOATIME_FL) -#endif inode->i_flags |= S_NOATIME; if (flags & FS_DIRSYNC_FL) inode->i_flags |= S_DIRSYNC; -- cgit From b253a3e4f2b8eed69b804952ef926df0ac788595 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Thu, 20 Jan 2011 02:09:53 +0900 Subject: nilfs2: tighten restrictions on inode flags Nilfs has few rectrictions on which flags may be set on which inodes like ext2/3/4 filesystems used to be. Specifically DIRSYNC may only be set on directories and IMMUTABLE and APPEND may not be set on links. Tighten that to disallow TOPDIR being set on non-directories and only NODUMP and NOATIME to be set on non-regular file, non-directories. This introduces a flags masking function like those of extN and uses it during inode creation. Signed-off-by: Ryusuke Konishi --- fs/nilfs2/inode.c | 7 ++----- fs/nilfs2/nilfs.h | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 2e6ac8e9203a..2534af8d2b5c 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c @@ -315,11 +315,8 @@ struct inode *nilfs_new_inode(struct inode *dir, int mode) /* No lock is needed; iget() ensures it. */ } - ii->i_flags = NILFS_I(dir)->i_flags; - if (S_ISLNK(mode)) - ii->i_flags &= ~(FS_IMMUTABLE_FL | FS_APPEND_FL); - if (!S_ISDIR(mode)) - ii->i_flags &= ~FS_DIRSYNC_FL; + ii->i_flags = nilfs_mask_flags( + mode, NILFS_I(dir)->i_flags & NILFS_FL_INHERITED); /* ii->i_file_acl = 0; */ /* ii->i_dir_acl = 0; */ diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h index 777e8fd04304..3e3acb1fdd2f 100644 --- a/fs/nilfs2/nilfs.h +++ b/fs/nilfs2/nilfs.h @@ -212,6 +212,23 @@ static inline int nilfs_init_acl(struct inode *inode, struct inode *dir) #define NILFS_ATIME_DISABLE +/* Flags that should be inherited by new inodes from their parent. */ +#define NILFS_FL_INHERITED \ + (FS_SECRM_FL | FS_UNRM_FL | FS_COMPR_FL | FS_SYNC_FL | \ + FS_IMMUTABLE_FL | FS_APPEND_FL | FS_NODUMP_FL | FS_NOATIME_FL |\ + FS_COMPRBLK_FL | FS_NOCOMP_FL | FS_NOTAIL_FL | FS_DIRSYNC_FL) + +/* Mask out flags that are inappropriate for the given type of inode. */ +static inline __u32 nilfs_mask_flags(umode_t mode, __u32 flags) +{ + if (S_ISDIR(mode)) + return flags; + else if (S_ISREG(mode)) + return flags & ~(FS_DIRSYNC_FL | FS_TOPDIR_FL); + else + return flags & (FS_NODUMP_FL | FS_NOATIME_FL); +} + /* dir.c */ extern int nilfs_add_link(struct dentry *, struct inode *); extern ino_t nilfs_inode_by_name(struct inode *, const struct qstr *); -- cgit From cde98f0f84ccff78e87235cb7b551747d6ad00de Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Thu, 20 Jan 2011 02:09:53 +0900 Subject: nilfs2: implement FS_IOC_GETFLAGS/SETFLAGS/GETVERSION Add support for the standard attributes set via chattr and read via lsattr. These attributes are already in the flags value in the nilfs2 inode, but currently we don't have any ioctl commands that expose them to the userland. Collaterally, this adds the FS_IOC_GETVERSION ioctl for getting i_generation, which allows users to list the file's generation number with "lsattr -v". Signed-off-by: Ryusuke Konishi --- fs/nilfs2/ioctl.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) (limited to 'fs') diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index 496738963fdb..3aad6413aba4 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c @@ -97,6 +97,70 @@ static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs, return ret; } +static int nilfs_ioctl_getflags(struct inode *inode, void __user *argp) +{ + unsigned int flags = NILFS_I(inode)->i_flags & FS_FL_USER_VISIBLE; + + return put_user(flags, (int __user *)argp); +} + +static int nilfs_ioctl_setflags(struct inode *inode, struct file *filp, + void __user *argp) +{ + struct nilfs_transaction_info ti; + unsigned int flags, oldflags; + int ret; + + if (!is_owner_or_cap(inode)) + return -EACCES; + + if (get_user(flags, (int __user *)argp)) + return -EFAULT; + + ret = mnt_want_write(filp->f_path.mnt); + if (ret) + return ret; + + flags = nilfs_mask_flags(inode->i_mode, flags); + + mutex_lock(&inode->i_mutex); + + oldflags = NILFS_I(inode)->i_flags; + + /* + * The IMMUTABLE and APPEND_ONLY flags can only be changed by the + * relevant capability. + */ + ret = -EPERM; + if (((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) && + !capable(CAP_LINUX_IMMUTABLE)) + goto out; + + ret = nilfs_transaction_begin(inode->i_sb, &ti, 0); + if (ret) + goto out; + + NILFS_I(inode)->i_flags = (oldflags & ~FS_FL_USER_MODIFIABLE) | + (flags & FS_FL_USER_MODIFIABLE); + + nilfs_set_inode_flags(inode); + inode->i_ctime = CURRENT_TIME; + if (IS_SYNC(inode)) + nilfs_set_transaction_flag(NILFS_TI_SYNC); + + nilfs_mark_inode_dirty(inode); + ret = nilfs_transaction_commit(inode->i_sb); +out: + mutex_unlock(&inode->i_mutex); + mnt_drop_write(filp->f_path.mnt); + return ret; +} + +static int nilfs_ioctl_getversion(struct inode *inode, void __user *argp) +{ + return put_user(inode->i_generation, (int __user *)argp); +} + static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp, unsigned int cmd, void __user *argp) { @@ -666,6 +730,12 @@ long nilfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) void __user *argp = (void __user *)arg; switch (cmd) { + case FS_IOC_GETFLAGS: + return nilfs_ioctl_getflags(inode, argp); + case FS_IOC_SETFLAGS: + return nilfs_ioctl_setflags(inode, filp, argp); + case FS_IOC_GETVERSION: + return nilfs_ioctl_getversion(inode, argp); case NILFS_IOCTL_CHANGE_CPMODE: return nilfs_ioctl_change_cpmode(inode, filp, cmd, argp); case NILFS_IOCTL_DELETE_CHECKPOINT: -- cgit From 828b1c50ae11e6dda68f8dfefe43b74c7182b157 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Thu, 3 Feb 2011 21:26:17 +0900 Subject: nilfs2: add compat ioctl The current FS_IOC_GETFLAGS/SETFLAGS/GETVERSION will fail if application is 32 bit and kernel is 64 bit. This issue is avoidable by adding compat_ioctl method. Signed-off-by: Ryusuke Konishi --- fs/nilfs2/dir.c | 2 +- fs/nilfs2/file.c | 2 +- fs/nilfs2/ioctl.c | 21 +++++++++++++++++++++ fs/nilfs2/nilfs.h | 1 + 4 files changed, 24 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c index b72833a2cc1c..3a1923943b14 100644 --- a/fs/nilfs2/dir.c +++ b/fs/nilfs2/dir.c @@ -681,7 +681,7 @@ const struct file_operations nilfs_dir_operations = { .readdir = nilfs_readdir, .unlocked_ioctl = nilfs_ioctl, #ifdef CONFIG_COMPAT - .compat_ioctl = nilfs_ioctl, + .compat_ioctl = nilfs_compat_ioctl, #endif /* CONFIG_COMPAT */ .fsync = nilfs_sync_file, diff --git a/fs/nilfs2/file.c b/fs/nilfs2/file.c index 2f560c9fb808..7a5e4ab15c6e 100644 --- a/fs/nilfs2/file.c +++ b/fs/nilfs2/file.c @@ -142,7 +142,7 @@ const struct file_operations nilfs_file_operations = { .aio_write = generic_file_aio_write, .unlocked_ioctl = nilfs_ioctl, #ifdef CONFIG_COMPAT - .compat_ioctl = nilfs_ioctl, + .compat_ioctl = nilfs_compat_ioctl, #endif /* CONFIG_COMPAT */ .mmap = nilfs_file_mmap, .open = generic_file_open, diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index 3aad6413aba4..d89173edd7fe 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c @@ -26,6 +26,7 @@ #include /* capable() */ #include /* copy_from_user(), copy_to_user() */ #include +#include /* compat_ptr() */ #include /* mnt_want_write(), mnt_drop_write() */ #include #include "nilfs.h" @@ -766,3 +767,23 @@ long nilfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return -ENOTTY; } } + +#ifdef CONFIG_COMPAT +long nilfs_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case FS_IOC32_GETFLAGS: + cmd = FS_IOC_GETFLAGS; + break; + case FS_IOC32_SETFLAGS: + cmd = FS_IOC_SETFLAGS; + break; + case FS_IOC32_GETVERSION: + cmd = FS_IOC_GETVERSION; + break; + default: + return -ENOIOCTLCMD; + } + return nilfs_ioctl(filp, cmd, (unsigned long)compat_ptr(arg)); +} +#endif diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h index 3e3acb1fdd2f..45b1fd1d0245 100644 --- a/fs/nilfs2/nilfs.h +++ b/fs/nilfs2/nilfs.h @@ -246,6 +246,7 @@ extern int nilfs_sync_file(struct file *, int); /* ioctl.c */ long nilfs_ioctl(struct file *, unsigned int, unsigned long); +long nilfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg); int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *, struct nilfs_argv *, void **); -- cgit From 4138ec23820012009aecc2b02856c62872dd3c34 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Mon, 24 Jan 2011 00:28:22 +0900 Subject: nilfs2: append blocksize info to warnings during loading super blocks At present, the same warning message can be output twice when nilfs detected a problem on super blocks: NILFS warning: broken superblock. using spare superblock. NILFS warning: broken superblock. using spare superblock. ... This is because these super blocks are reloaded with the block size written in a super block if it differs from the first block size, but this repetition looks somewhat confusing. So, we hint at what is going on by appending block size information to those messages. Reported-by: Wakko Warner Signed-off-by: Ryusuke Konishi --- fs/nilfs2/the_nilfs.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c index ad4ac607cf57..9098909d5cef 100644 --- a/fs/nilfs2/the_nilfs.c +++ b/fs/nilfs2/the_nilfs.c @@ -475,10 +475,13 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs, return -EIO; } printk(KERN_WARNING - "NILFS warning: unable to read primary superblock\n"); - } else if (!sbp[1]) + "NILFS warning: unable to read primary superblock " + "(blocksize = %d)\n", blocksize); + } else if (!sbp[1]) { printk(KERN_WARNING - "NILFS warning: unable to read secondary superblock\n"); + "NILFS warning: unable to read secondary superblock " + "(blocksize = %d)\n", blocksize); + } /* * Compare two super blocks and set 1 in swp if the secondary @@ -505,7 +508,7 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs, if (!valid[!swp]) printk(KERN_WARNING "NILFS warning: broken superblock. " - "using spare superblock.\n"); + "using spare superblock (blocksize = %d).\n", blocksize); if (swp) nilfs_swap_super_block(nilfs); -- cgit From ae191838b0251d73b9d0a7254c6938406f5f6320 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Fri, 4 Feb 2011 01:19:38 +0900 Subject: nilfs2: optimize rec_len functions This is a similar change to those in ext2/ext3 codebase (commit 40a063f6691ce937 and a4ae3094869f18e2, respectively). The addition of 64k block capability in the rec_len_from_disk and rec_len_to_disk functions added a bit of math overhead which slows down file create workloads needlessly when the architecture cannot even support 64k blocks. This will cut the corner. Signed-off-by: Ryusuke Konishi --- fs/nilfs2/ioctl.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs') diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index d89173edd7fe..5471eed5eccb 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c @@ -28,6 +28,7 @@ #include #include /* compat_ptr() */ #include /* mnt_want_write(), mnt_drop_write() */ +#include #include #include "nilfs.h" #include "segment.h" -- cgit From be667377a8b8cd73e1b923f33fb5be4034aa4bfa Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Sat, 5 Mar 2011 00:19:32 +0900 Subject: nilfs2: record used amount of each checkpoint in checkpoint list This records the number of used blocks per checkpoint in each checkpoint entry of cpfile. Even though userland tools can get the block count via nilfs_get_cpinfo ioctl, it was not updated by the nilfs2 kernel code. This fixes the issue and makes it available for userland tools to calculate used amount per checkpoint. Signed-off-by: Ryusuke Konishi Cc: Jiro SEKIBA --- fs/nilfs2/bmap.c | 11 ----------- fs/nilfs2/bmap.h | 3 --- fs/nilfs2/btree.c | 6 +++--- fs/nilfs2/direct.c | 4 ++-- fs/nilfs2/inode.c | 18 ++++++++++++++++++ fs/nilfs2/nilfs.h | 2 ++ 6 files changed, 25 insertions(+), 19 deletions(-) (limited to 'fs') diff --git a/fs/nilfs2/bmap.c b/fs/nilfs2/bmap.c index 3ee67c67cc52..85447a2fab33 100644 --- a/fs/nilfs2/bmap.c +++ b/fs/nilfs2/bmap.c @@ -425,17 +425,6 @@ int nilfs_bmap_test_and_clear_dirty(struct nilfs_bmap *bmap) /* * Internal use only */ - -void nilfs_bmap_add_blocks(const struct nilfs_bmap *bmap, int n) -{ - inode_add_bytes(bmap->b_inode, (1 << bmap->b_inode->i_blkbits) * n); -} - -void nilfs_bmap_sub_blocks(const struct nilfs_bmap *bmap, int n) -{ - inode_sub_bytes(bmap->b_inode, (1 << bmap->b_inode->i_blkbits) * n); -} - __u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *bmap, const struct buffer_head *bh) { diff --git a/fs/nilfs2/bmap.h b/fs/nilfs2/bmap.h index bde1c0aa2e15..40d9f453d31c 100644 --- a/fs/nilfs2/bmap.h +++ b/fs/nilfs2/bmap.h @@ -240,9 +240,6 @@ __u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *, __u64 nilfs_bmap_find_target_seq(const struct nilfs_bmap *, __u64); __u64 nilfs_bmap_find_target_in_group(const struct nilfs_bmap *); -void nilfs_bmap_add_blocks(const struct nilfs_bmap *, int); -void nilfs_bmap_sub_blocks(const struct nilfs_bmap *, int); - /* Assume that bmap semaphore is locked. */ static inline int nilfs_bmap_dirty(const struct nilfs_bmap *bmap) diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c index 300c2bc00c3f..d451ae0e0bf3 100644 --- a/fs/nilfs2/btree.c +++ b/fs/nilfs2/btree.c @@ -1174,7 +1174,7 @@ static int nilfs_btree_insert(struct nilfs_bmap *btree, __u64 key, __u64 ptr) if (ret < 0) goto out; nilfs_btree_commit_insert(btree, path, level, key, ptr); - nilfs_bmap_add_blocks(btree, stats.bs_nblocks); + nilfs_inode_add_blocks(btree->b_inode, stats.bs_nblocks); out: nilfs_btree_free_path(path); @@ -1511,7 +1511,7 @@ static int nilfs_btree_delete(struct nilfs_bmap *btree, __u64 key) if (ret < 0) goto out; nilfs_btree_commit_delete(btree, path, level, dat); - nilfs_bmap_sub_blocks(btree, stats.bs_nblocks); + nilfs_inode_sub_blocks(btree->b_inode, stats.bs_nblocks); out: nilfs_btree_free_path(path); @@ -1776,7 +1776,7 @@ int nilfs_btree_convert_and_insert(struct nilfs_bmap *btree, return ret; nilfs_btree_commit_convert_and_insert(btree, key, ptr, keys, ptrs, n, di, ni, bh); - nilfs_bmap_add_blocks(btree, stats.bs_nblocks); + nilfs_inode_add_blocks(btree->b_inode, stats.bs_nblocks); return 0; } diff --git a/fs/nilfs2/direct.c b/fs/nilfs2/direct.c index 324d80c57518..82f4865e86dd 100644 --- a/fs/nilfs2/direct.c +++ b/fs/nilfs2/direct.c @@ -146,7 +146,7 @@ static int nilfs_direct_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) if (NILFS_BMAP_USE_VBN(bmap)) nilfs_bmap_set_target_v(bmap, key, req.bpr_ptr); - nilfs_bmap_add_blocks(bmap, 1); + nilfs_inode_add_blocks(bmap->b_inode, 1); } return ret; } @@ -168,7 +168,7 @@ static int nilfs_direct_delete(struct nilfs_bmap *bmap, __u64 key) if (!ret) { nilfs_bmap_commit_end_ptr(bmap, &req, dat); nilfs_direct_set_ptr(bmap, key, NILFS_BMAP_INVALID_PTR); - nilfs_bmap_sub_blocks(bmap, 1); + nilfs_inode_sub_blocks(bmap->b_inode, 1); } return ret; } diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 2534af8d2b5c..22a816ba3621 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c @@ -41,6 +41,24 @@ struct nilfs_iget_args { int for_gc; }; +void nilfs_inode_add_blocks(struct inode *inode, int n) +{ + struct nilfs_root *root = NILFS_I(inode)->i_root; + + inode_add_bytes(inode, (1 << inode->i_blkbits) * n); + if (root) + atomic_add(n, &root->blocks_count); +} + +void nilfs_inode_sub_blocks(struct inode *inode, int n) +{ + struct nilfs_root *root = NILFS_I(inode)->i_root; + + inode_sub_bytes(inode, (1 << inode->i_blkbits) * n); + if (root) + atomic_sub(n, &root->blocks_count); +} + /** * nilfs_get_block() - get a file block on the filesystem (callback function) * @inode - inode struct of the target file diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h index 45b1fd1d0245..03ba4d88083f 100644 --- a/fs/nilfs2/nilfs.h +++ b/fs/nilfs2/nilfs.h @@ -251,6 +251,8 @@ int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *, struct nilfs_argv *, void **); /* inode.c */ +void nilfs_inode_add_blocks(struct inode *inode, int n); +void nilfs_inode_sub_blocks(struct inode *inode, int n); extern struct inode *nilfs_new_inode(struct inode *, int); extern void nilfs_free_inode(struct inode *); extern int nilfs_get_block(struct inode *, sector_t, struct buffer_head *, int); -- cgit From df677140281beb608f6748c341af7612f7bfe7a0 Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Tue, 8 Mar 2011 08:28:01 +0100 Subject: block: biovec_slab vs. CONFIG_BLK_DEV_INTEGRITY The block integrity subsystem no longer uses the bio_vec slabs so this code can safely be compiled in. Signed-off-by: Martin K. Petersen Signed-off-by: Jens Axboe --- fs/bio.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/bio.c b/fs/bio.c index 4bd454fa844e..5694b756ed01 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -43,7 +43,7 @@ static mempool_t *bio_split_pool __read_mostly; * unsigned short */ #define BV(x) { .nr_vecs = x, .name = "biovec-"__stringify(x) } -struct biovec_slab bvec_slabs[BIOVEC_NR_POOLS] __read_mostly = { +static struct biovec_slab bvec_slabs[BIOVEC_NR_POOLS] __read_mostly = { BV(1), BV(4), BV(16), BV(64), BV(128), BV(BIO_MAX_PAGES), }; #undef BV @@ -1656,12 +1656,10 @@ static void __init biovec_init_slabs(void) int size; struct biovec_slab *bvs = bvec_slabs + i; -#ifndef CONFIG_BLK_DEV_INTEGRITY if (bvs->nr_vecs <= BIO_INLINE_VECS) { bvs->slab = NULL; continue; } -#endif size = bvs->nr_vecs * sizeof(struct bio_vec); bvs->slab = kmem_cache_create(bvs->name, size, 0, -- cgit From 529d7b2a7fa31e9f7d08bc790d232c3cbe64fa24 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Wed, 2 Mar 2011 23:48:33 -0500 Subject: nfsd4: minor nfs4state.c reshuffling Minor cleanup in preparation for a bugfix--moving some code to avoid forward references, etc. No change in functionality. Cc: stable@kernel.org Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4state.c | 125 +++++++++++++++++++++++++--------------------------- 1 file changed, 61 insertions(+), 64 deletions(-) (limited to 'fs') diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index c4f2b0f63e46..84d2dd327b2d 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -316,64 +316,6 @@ static struct list_head unconf_id_hashtbl[CLIENT_HASH_SIZE]; static struct list_head client_lru; static struct list_head close_lru; -static void unhash_generic_stateid(struct nfs4_stateid *stp) -{ - list_del(&stp->st_hash); - list_del(&stp->st_perfile); - list_del(&stp->st_perstateowner); -} - -static void free_generic_stateid(struct nfs4_stateid *stp) -{ - put_nfs4_file(stp->st_file); - kmem_cache_free(stateid_slab, stp); -} - -static void release_lock_stateid(struct nfs4_stateid *stp) -{ - struct file *file; - - unhash_generic_stateid(stp); - file = find_any_file(stp->st_file); - if (file) - locks_remove_posix(file, (fl_owner_t)stp->st_stateowner); - free_generic_stateid(stp); -} - -static void unhash_lockowner(struct nfs4_stateowner *sop) -{ - struct nfs4_stateid *stp; - - list_del(&sop->so_idhash); - list_del(&sop->so_strhash); - list_del(&sop->so_perstateid); - while (!list_empty(&sop->so_stateids)) { - stp = list_first_entry(&sop->so_stateids, - struct nfs4_stateid, st_perstateowner); - release_lock_stateid(stp); - } -} - -static void release_lockowner(struct nfs4_stateowner *sop) -{ - unhash_lockowner(sop); - nfs4_put_stateowner(sop); -} - -static void -release_stateid_lockowners(struct nfs4_stateid *open_stp) -{ - struct nfs4_stateowner *lock_sop; - - while (!list_empty(&open_stp->st_lockowners)) { - lock_sop = list_entry(open_stp->st_lockowners.next, - struct nfs4_stateowner, so_perstateid); - /* list_del(&open_stp->st_lockowners); */ - BUG_ON(lock_sop->so_is_open_owner); - release_lockowner(lock_sop); - } -} - /* * We store the NONE, READ, WRITE, and BOTH bits separately in the * st_{access,deny}_bmap field of the stateid, in order to track not @@ -446,6 +388,64 @@ static int nfs4_access_bmap_to_omode(struct nfs4_stateid *stp) return nfs4_access_to_omode(access); } +static void unhash_generic_stateid(struct nfs4_stateid *stp) +{ + list_del(&stp->st_hash); + list_del(&stp->st_perfile); + list_del(&stp->st_perstateowner); +} + +static void free_generic_stateid(struct nfs4_stateid *stp) +{ + put_nfs4_file(stp->st_file); + kmem_cache_free(stateid_slab, stp); +} + +static void release_lock_stateid(struct nfs4_stateid *stp) +{ + struct file *file; + + unhash_generic_stateid(stp); + file = find_any_file(stp->st_file); + if (file) + locks_remove_posix(file, (fl_owner_t)stp->st_stateowner); + free_generic_stateid(stp); +} + +static void unhash_lockowner(struct nfs4_stateowner *sop) +{ + struct nfs4_stateid *stp; + + list_del(&sop->so_idhash); + list_del(&sop->so_strhash); + list_del(&sop->so_perstateid); + while (!list_empty(&sop->so_stateids)) { + stp = list_first_entry(&sop->so_stateids, + struct nfs4_stateid, st_perstateowner); + release_lock_stateid(stp); + } +} + +static void release_lockowner(struct nfs4_stateowner *sop) +{ + unhash_lockowner(sop); + nfs4_put_stateowner(sop); +} + +static void +release_stateid_lockowners(struct nfs4_stateid *open_stp) +{ + struct nfs4_stateowner *lock_sop; + + while (!list_empty(&open_stp->st_lockowners)) { + lock_sop = list_entry(open_stp->st_lockowners.next, + struct nfs4_stateowner, so_perstateid); + /* list_del(&open_stp->st_lockowners); */ + BUG_ON(lock_sop->so_is_open_owner); + release_lockowner(lock_sop); + } +} + static void release_open_stateid(struct nfs4_stateid *stp) { int oflag = nfs4_access_bmap_to_omode(stp); @@ -3764,7 +3764,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct file_lock conflock; __be32 status = 0; unsigned int strhashval; - unsigned int cmd; int err; dprintk("NFSD: nfsd4_lock: start=%Ld length=%Ld\n", @@ -3851,8 +3850,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, filp = find_readable_file(lock_stp->st_file); } file_lock.fl_type = F_RDLCK; - cmd = F_SETLK; - break; + break; case NFS4_WRITE_LT: case NFS4_WRITEW_LT: if (find_writeable_file(lock_stp->st_file)) { @@ -3860,8 +3858,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, filp = find_writeable_file(lock_stp->st_file); } file_lock.fl_type = F_WRLCK; - cmd = F_SETLK; - break; + break; default: status = nfserr_inval; goto out; @@ -3885,7 +3882,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, * Note: locks.c uses the BKL to protect the inode's lock list. */ - err = vfs_lock_file(filp, cmd, &file_lock, &conflock); + err = vfs_lock_file(filp, F_SETLK, &file_lock, &conflock); switch (-err) { case 0: /* success! */ update_stateid(&lock_stp->st_stateid); -- cgit From 0997b173609b9229ece28941c118a2a9b278796e Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Wed, 2 Mar 2011 18:01:35 -0500 Subject: nfsd4: fix struct file leak MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure we properly reference count the struct files that a lock depends on, and release them when the lock stateid is released. This fixes a major leak of struct files when using locking over nfsv4. Cc: stable@kernel.org Reported-by: Rick Koshi Tested-by: Ivo Přikryl Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4state.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) (limited to 'fs') diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 84d2dd327b2d..c26dc31fb943 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -397,6 +397,9 @@ static void unhash_generic_stateid(struct nfs4_stateid *stp) static void free_generic_stateid(struct nfs4_stateid *stp) { + int oflag = nfs4_access_bmap_to_omode(stp); + + nfs4_file_put_access(stp->st_file, oflag); put_nfs4_file(stp->st_file); kmem_cache_free(stateid_slab, stp); } @@ -448,11 +451,8 @@ release_stateid_lockowners(struct nfs4_stateid *open_stp) static void release_open_stateid(struct nfs4_stateid *stp) { - int oflag = nfs4_access_bmap_to_omode(stp); - unhash_generic_stateid(stp); release_stateid_lockowners(stp); - nfs4_file_put_access(stp->st_file, oflag); free_generic_stateid(stp); } @@ -3734,6 +3734,7 @@ alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struc stp->st_stateid.si_stateownerid = sop->so_id; stp->st_stateid.si_fileid = fp->fi_id; stp->st_stateid.si_generation = 0; + stp->st_access_bmap = 0; stp->st_deny_bmap = open_stp->st_deny_bmap; stp->st_openstp = open_stp; @@ -3748,6 +3749,17 @@ check_lock_length(u64 offset, u64 length) LOFF_OVERFLOW(offset, length))); } +static void get_lock_access(struct nfs4_stateid *lock_stp, u32 access) +{ + struct nfs4_file *fp = lock_stp->st_file; + int oflag = nfs4_access_to_omode(access); + + if (test_bit(access, &lock_stp->st_access_bmap)) + return; + nfs4_file_get_access(fp, oflag); + __set_bit(access, &lock_stp->st_access_bmap); +} + /* * LOCK operation */ @@ -3845,18 +3857,16 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, switch (lock->lk_type) { case NFS4_READ_LT: case NFS4_READW_LT: - if (find_readable_file(lock_stp->st_file)) { - nfs4_get_vfs_file(rqstp, fp, &cstate->current_fh, NFS4_SHARE_ACCESS_READ); - filp = find_readable_file(lock_stp->st_file); - } + filp = find_readable_file(lock_stp->st_file); + if (filp) + get_lock_access(lock_stp, NFS4_SHARE_ACCESS_READ); file_lock.fl_type = F_RDLCK; break; case NFS4_WRITE_LT: case NFS4_WRITEW_LT: - if (find_writeable_file(lock_stp->st_file)) { - nfs4_get_vfs_file(rqstp, fp, &cstate->current_fh, NFS4_SHARE_ACCESS_WRITE); - filp = find_writeable_file(lock_stp->st_file); - } + filp = find_writeable_file(lock_stp->st_file); + if (filp) + get_lock_access(lock_stp, NFS4_SHARE_ACCESS_WRITE); file_lock.fl_type = F_WRLCK; break; default: -- cgit From 3b2ce58b0f3c1633750529713be0e467282abd78 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Wed, 9 Mar 2011 11:05:07 +0900 Subject: nilfs2: move mount options to nilfs object This moves mount_opt local variable to nilfs object from nilfs_sb_info struct. Signed-off-by: Ryusuke Konishi --- fs/nilfs2/sb.h | 16 --------------- fs/nilfs2/segment.c | 9 +++++---- fs/nilfs2/super.c | 56 ++++++++++++++++++++++++++------------------------- fs/nilfs2/the_nilfs.c | 4 ++-- fs/nilfs2/the_nilfs.h | 18 +++++++++++++++++ 5 files changed, 54 insertions(+), 49 deletions(-) (limited to 'fs') diff --git a/fs/nilfs2/sb.h b/fs/nilfs2/sb.h index 7a17715f215f..d7346c949c81 100644 --- a/fs/nilfs2/sb.h +++ b/fs/nilfs2/sb.h @@ -34,8 +34,6 @@ struct nilfs_sc_info; * NILFS super-block data in memory */ struct nilfs_sb_info { - /* Mount options */ - unsigned long s_mount_opt; uid_t s_resuid; gid_t s_resgid; @@ -68,18 +66,4 @@ static inline struct nilfs_sc_info *NILFS_SC(struct nilfs_sb_info *sbi) return sbi->s_sc_info; } -/* - * Bit operations for the mount option - */ -#define nilfs_clear_opt(sbi, opt) \ - do { (sbi)->s_mount_opt &= ~NILFS_MOUNT_##opt; } while (0) -#define nilfs_set_opt(sbi, opt) \ - do { (sbi)->s_mount_opt |= NILFS_MOUNT_##opt; } while (0) -#define nilfs_test_opt(sbi, opt) ((sbi)->s_mount_opt & NILFS_MOUNT_##opt) -#define nilfs_write_opt(sbi, mask, opt) \ - do { (sbi)->s_mount_opt = \ - (((sbi)->s_mount_opt & ~NILFS_MOUNT_##mask) | \ - NILFS_MOUNT_##opt); \ - } while (0) - #endif /* _NILFS_SB */ diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 2de9f636792a..851bcd3890c8 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -2298,6 +2298,7 @@ int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode, loff_t start, loff_t end) { struct nilfs_sb_info *sbi = NILFS_SB(sb); + struct the_nilfs *nilfs = sbi->s_nilfs; struct nilfs_sc_info *sci = NILFS_SC(sbi); struct nilfs_inode_info *ii; struct nilfs_transaction_info ti; @@ -2310,9 +2311,9 @@ int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode, ii = NILFS_I(inode); if (test_bit(NILFS_I_INODE_DIRTY, &ii->i_state) || - nilfs_test_opt(sbi, STRICT_ORDER) || + nilfs_test_opt(nilfs, STRICT_ORDER) || test_bit(NILFS_SC_UNCLOSED, &sci->sc_flags) || - nilfs_discontinued(sbi->s_nilfs)) { + nilfs_discontinued(nilfs)) { nilfs_transaction_unlock(sbi); err = nilfs_segctor_sync(sci); return err; @@ -2480,14 +2481,14 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv, set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(sci->sc_interval); } - if (nilfs_test_opt(sbi, DISCARD)) { + if (nilfs_test_opt(nilfs, DISCARD)) { int ret = nilfs_discard_segments(nilfs, sci->sc_freesegs, sci->sc_nfreesegs); if (ret) { printk(KERN_WARNING "NILFS warning: error %d on discard request, " "turning discards off for the device\n", ret); - nilfs_clear_opt(sbi, DISCARD); + nilfs_clear_opt(nilfs, DISCARD); } } diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 1673b3d99842..0576cb21d699 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -109,7 +109,7 @@ static void nilfs_set_error(struct nilfs_sb_info *sbi) void nilfs_error(struct super_block *sb, const char *function, const char *fmt, ...) { - struct nilfs_sb_info *sbi = NILFS_SB(sb); + struct the_nilfs *nilfs = sbi->s_nilfs; struct va_format vaf; va_list args; @@ -126,13 +126,13 @@ void nilfs_error(struct super_block *sb, const char *function, if (!(sb->s_flags & MS_RDONLY)) { nilfs_set_error(sbi); - if (nilfs_test_opt(sbi, ERRORS_RO)) { + if (nilfs_test_opt(nilfs, ERRORS_RO)) { printk(KERN_CRIT "Remounting filesystem read-only\n"); sb->s_flags |= MS_RDONLY; } } - if (nilfs_test_opt(sbi, ERRORS_PANIC)) + if (nilfs_test_opt(nilfs, ERRORS_PANIC)) panic("NILFS (device %s): panic forced after error\n", sb->s_id); } @@ -196,7 +196,7 @@ static int nilfs_sync_super(struct nilfs_sb_info *sbi, int flag) retry: set_buffer_dirty(nilfs->ns_sbh[0]); - if (nilfs_test_opt(sbi, BARRIER)) { + if (nilfs_test_opt(nilfs, BARRIER)) { err = __sync_dirty_buffer(nilfs->ns_sbh[0], WRITE_SYNC | WRITE_FLUSH_FUA); } else { @@ -530,22 +530,22 @@ static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf) static int nilfs_show_options(struct seq_file *seq, struct vfsmount *vfs) { struct super_block *sb = vfs->mnt_sb; - struct nilfs_sb_info *sbi = NILFS_SB(sb); + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; struct nilfs_root *root = NILFS_I(vfs->mnt_root->d_inode)->i_root; - if (!nilfs_test_opt(sbi, BARRIER)) + if (!nilfs_test_opt(nilfs, BARRIER)) seq_puts(seq, ",nobarrier"); if (root->cno != NILFS_CPTREE_CURRENT_CNO) seq_printf(seq, ",cp=%llu", (unsigned long long)root->cno); - if (nilfs_test_opt(sbi, ERRORS_PANIC)) + if (nilfs_test_opt(nilfs, ERRORS_PANIC)) seq_puts(seq, ",errors=panic"); - if (nilfs_test_opt(sbi, ERRORS_CONT)) + if (nilfs_test_opt(nilfs, ERRORS_CONT)) seq_puts(seq, ",errors=continue"); - if (nilfs_test_opt(sbi, STRICT_ORDER)) + if (nilfs_test_opt(nilfs, STRICT_ORDER)) seq_puts(seq, ",order=strict"); - if (nilfs_test_opt(sbi, NORECOVERY)) + if (nilfs_test_opt(nilfs, NORECOVERY)) seq_puts(seq, ",norecovery"); - if (nilfs_test_opt(sbi, DISCARD)) + if (nilfs_test_opt(nilfs, DISCARD)) seq_puts(seq, ",discard"); return 0; @@ -594,7 +594,7 @@ static match_table_t tokens = { static int parse_options(char *options, struct super_block *sb, int is_remount) { - struct nilfs_sb_info *sbi = NILFS_SB(sb); + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; char *p; substring_t args[MAX_OPT_ARGS]; @@ -609,29 +609,29 @@ static int parse_options(char *options, struct super_block *sb, int is_remount) token = match_token(p, tokens, args); switch (token) { case Opt_barrier: - nilfs_set_opt(sbi, BARRIER); + nilfs_set_opt(nilfs, BARRIER); break; case Opt_nobarrier: - nilfs_clear_opt(sbi, BARRIER); + nilfs_clear_opt(nilfs, BARRIER); break; case Opt_order: if (strcmp(args[0].from, "relaxed") == 0) /* Ordered data semantics */ - nilfs_clear_opt(sbi, STRICT_ORDER); + nilfs_clear_opt(nilfs, STRICT_ORDER); else if (strcmp(args[0].from, "strict") == 0) /* Strict in-order semantics */ - nilfs_set_opt(sbi, STRICT_ORDER); + nilfs_set_opt(nilfs, STRICT_ORDER); else return 0; break; case Opt_err_panic: - nilfs_write_opt(sbi, ERROR_MODE, ERRORS_PANIC); + nilfs_write_opt(nilfs, ERROR_MODE, ERRORS_PANIC); break; case Opt_err_ro: - nilfs_write_opt(sbi, ERROR_MODE, ERRORS_RO); + nilfs_write_opt(nilfs, ERROR_MODE, ERRORS_RO); break; case Opt_err_cont: - nilfs_write_opt(sbi, ERROR_MODE, ERRORS_CONT); + nilfs_write_opt(nilfs, ERROR_MODE, ERRORS_CONT); break; case Opt_snapshot: if (is_remount) { @@ -642,13 +642,13 @@ static int parse_options(char *options, struct super_block *sb, int is_remount) } break; case Opt_norecovery: - nilfs_set_opt(sbi, NORECOVERY); + nilfs_set_opt(nilfs, NORECOVERY); break; case Opt_discard: - nilfs_set_opt(sbi, DISCARD); + nilfs_set_opt(nilfs, DISCARD); break; case Opt_nodiscard: - nilfs_clear_opt(sbi, DISCARD); + nilfs_clear_opt(nilfs, DISCARD); break; default: printk(KERN_ERR @@ -660,10 +660,12 @@ static int parse_options(char *options, struct super_block *sb, int is_remount) } static inline void -nilfs_set_default_options(struct nilfs_sb_info *sbi, +nilfs_set_default_options(struct super_block *sb, struct nilfs_super_block *sbp) { - sbi->s_mount_opt = + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + + nilfs->ns_mount_opt = NILFS_MOUNT_ERRORS_RO | NILFS_MOUNT_BARRIER; } @@ -736,7 +738,7 @@ int nilfs_store_magic_and_option(struct super_block *sb, sb->s_flags |= MS_NOATIME; #endif - nilfs_set_default_options(sbi, sbp); + nilfs_set_default_options(sb, sbp); sbi->s_resuid = le16_to_cpu(sbp->s_def_resuid); sbi->s_resgid = le16_to_cpu(sbp->s_def_resgid); @@ -1023,7 +1025,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) int err; old_sb_flags = sb->s_flags; - old_mount_opt = sbi->s_mount_opt; + old_mount_opt = nilfs->ns_mount_opt; if (!parse_options(data, sb, 1)) { err = -EINVAL; @@ -1092,7 +1094,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) restore_opts: sb->s_flags = old_sb_flags; - sbi->s_mount_opt = old_mount_opt; + nilfs->ns_mount_opt = old_mount_opt; return err; } diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c index 9098909d5cef..d3775336a16c 100644 --- a/fs/nilfs2/the_nilfs.c +++ b/fs/nilfs2/the_nilfs.c @@ -283,7 +283,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) if (s_flags & MS_RDONLY) { __u64 features; - if (nilfs_test_opt(sbi, NORECOVERY)) { + if (nilfs_test_opt(nilfs, NORECOVERY)) { printk(KERN_INFO "NILFS: norecovery option specified. " "skipping roll-forward recovery\n"); goto skip_recovery; @@ -305,7 +305,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) goto failed_unload; } sbi->s_super->s_flags &= ~MS_RDONLY; - } else if (nilfs_test_opt(sbi, NORECOVERY)) { + } else if (nilfs_test_opt(nilfs, NORECOVERY)) { printk(KERN_ERR "NILFS: recovery cancelled because norecovery " "option was specified for a read/write mount\n"); err = -EINVAL; diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index fd85e4c05c6b..438278041d80 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h @@ -72,6 +72,7 @@ enum { * @ns_cptree: rb-tree of all mounted checkpoints (nilfs_root) * @ns_cptree_lock: lock protecting @ns_cptree * @ns_gc_inodes: dummy inodes to keep live blocks + * @ns_mount_opt: mount options * @ns_blocksize_bits: bit length of block size * @ns_blocksize: block size * @ns_nsegments: number of segments in filesystem @@ -148,6 +149,9 @@ struct the_nilfs { /* GC inode list */ struct list_head ns_gc_inodes; + /* Mount options */ + unsigned long ns_mount_opt; + /* Disk layout information (static) */ unsigned int ns_blocksize_bits; unsigned int ns_blocksize; @@ -180,6 +184,20 @@ THE_NILFS_FNS(DISCONTINUED, discontinued) THE_NILFS_FNS(GC_RUNNING, gc_running) THE_NILFS_FNS(SB_DIRTY, sb_dirty) +/* + * Mount option operations + */ +#define nilfs_clear_opt(nilfs, opt) \ + do { (nilfs)->ns_mount_opt &= ~NILFS_MOUNT_##opt; } while (0) +#define nilfs_set_opt(nilfs, opt) \ + do { (nilfs)->ns_mount_opt |= NILFS_MOUNT_##opt; } while (0) +#define nilfs_test_opt(nilfs, opt) ((nilfs)->ns_mount_opt & NILFS_MOUNT_##opt) +#define nilfs_write_opt(nilfs, mask, opt) \ + do { (nilfs)->ns_mount_opt = \ + (((nilfs)->ns_mount_opt & ~NILFS_MOUNT_##mask) | \ + NILFS_MOUNT_##opt); \ + } while (0) + /** * struct nilfs_root - nilfs root object * @cno: checkpoint number -- cgit From 574e6c3145c5754141361c695b58736c294a8ae1 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Wed, 9 Mar 2011 11:05:07 +0900 Subject: nilfs2: move parameters on nilfs_sb_info into nilfs object This moves four parameter variables on nilfs_sb_info s_resuid, s_resgid, s_interval and s_watermark to the nilfs object. Signed-off-by: Ryusuke Konishi --- fs/nilfs2/sb.h | 7 ------- fs/nilfs2/segment.c | 9 +++++---- fs/nilfs2/super.c | 10 +++++----- fs/nilfs2/the_nilfs.h | 9 +++++++++ 4 files changed, 19 insertions(+), 16 deletions(-) (limited to 'fs') diff --git a/fs/nilfs2/sb.h b/fs/nilfs2/sb.h index d7346c949c81..0512521ba8a4 100644 --- a/fs/nilfs2/sb.h +++ b/fs/nilfs2/sb.h @@ -34,13 +34,6 @@ struct nilfs_sc_info; * NILFS super-block data in memory */ struct nilfs_sb_info { - uid_t s_resuid; - gid_t s_resgid; - - unsigned long s_interval; /* construction interval */ - unsigned long s_watermark; /* threshold of data amount - for the segment construction */ - /* Fundamental members */ struct super_block *s_super; /* reverse pointer to super_block */ struct the_nilfs *s_nilfs; diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 851bcd3890c8..a32d9cb2842a 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -2676,6 +2676,7 @@ static void nilfs_segctor_kill_thread(struct nilfs_sc_info *sci) static struct nilfs_sc_info *nilfs_segctor_new(struct nilfs_sb_info *sbi, struct nilfs_root *root) { + struct the_nilfs *nilfs = sbi->s_nilfs; struct nilfs_sc_info *sci; sci = kzalloc(sizeof(*sci), GFP_KERNEL); @@ -2703,10 +2704,10 @@ static struct nilfs_sc_info *nilfs_segctor_new(struct nilfs_sb_info *sbi, sci->sc_mjcp_freq = HZ * NILFS_SC_DEFAULT_SR_FREQ; sci->sc_watermark = NILFS_SC_DEFAULT_WATERMARK; - if (sbi->s_interval) - sci->sc_interval = sbi->s_interval; - if (sbi->s_watermark) - sci->sc_watermark = sbi->s_watermark; + if (nilfs->ns_interval) + sci->sc_interval = nilfs->ns_interval; + if (nilfs->ns_watermark) + sci->sc_watermark = nilfs->ns_watermark; return sci; } diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 0576cb21d699..2f17a2f9ef9c 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -729,7 +729,7 @@ int nilfs_store_magic_and_option(struct super_block *sb, struct nilfs_super_block *sbp, char *data) { - struct nilfs_sb_info *sbi = NILFS_SB(sb); + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; sb->s_magic = le16_to_cpu(sbp->s_magic); @@ -740,10 +740,10 @@ int nilfs_store_magic_and_option(struct super_block *sb, nilfs_set_default_options(sb, sbp); - sbi->s_resuid = le16_to_cpu(sbp->s_def_resuid); - sbi->s_resgid = le16_to_cpu(sbp->s_def_resgid); - sbi->s_interval = le32_to_cpu(sbp->s_c_interval); - sbi->s_watermark = le32_to_cpu(sbp->s_c_block_max); + nilfs->ns_resuid = le16_to_cpu(sbp->s_def_resuid); + nilfs->ns_resgid = le16_to_cpu(sbp->s_def_resgid); + nilfs->ns_interval = le32_to_cpu(sbp->s_c_interval); + nilfs->ns_watermark = le32_to_cpu(sbp->s_c_block_max); return !parse_options(data, sb, 0) ? -EINVAL : 0 ; } diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index 438278041d80..4a9bf3913c9c 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h @@ -73,6 +73,10 @@ enum { * @ns_cptree_lock: lock protecting @ns_cptree * @ns_gc_inodes: dummy inodes to keep live blocks * @ns_mount_opt: mount options + * @ns_resuid: uid for reserved blocks + * @ns_resgid: gid for reserved blocks + * @ns_interval: checkpoint creation interval + * @ns_watermark: watermark for the number of dirty buffers * @ns_blocksize_bits: bit length of block size * @ns_blocksize: block size * @ns_nsegments: number of segments in filesystem @@ -152,6 +156,11 @@ struct the_nilfs { /* Mount options */ unsigned long ns_mount_opt; + uid_t ns_resuid; + gid_t ns_resgid; + unsigned long ns_interval; + unsigned long ns_watermark; + /* Disk layout information (static) */ unsigned int ns_blocksize_bits; unsigned int ns_blocksize; -- cgit From 693dd321222f03b17668f88ceb0f7d518900191e Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Wed, 9 Mar 2011 11:05:07 +0900 Subject: nilfs2: move s_inode_lock and s_dirty_files into nilfs object Moves s_inode_lock spinlock and s_dirty_files list to nilfs object from nilfs_sb_info structure. Signed-off-by: Ryusuke Konishi --- fs/nilfs2/inode.c | 30 +++++++++---------- fs/nilfs2/sb.h | 3 -- fs/nilfs2/segment.c | 80 +++++++++++++++++++++++++-------------------------- fs/nilfs2/super.c | 3 -- fs/nilfs2/the_nilfs.c | 2 ++ fs/nilfs2/the_nilfs.h | 6 ++++ 6 files changed, 63 insertions(+), 61 deletions(-) (limited to 'fs') diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 22a816ba3621..dd5d6d633ea1 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c @@ -807,18 +807,18 @@ int nilfs_permission(struct inode *inode, int mask, unsigned int flags) int nilfs_load_inode_block(struct inode *inode, struct buffer_head **pbh) { - struct nilfs_sb_info *sbi = NILFS_SB(inode->i_sb); + struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; struct nilfs_inode_info *ii = NILFS_I(inode); int err; - spin_lock(&sbi->s_inode_lock); + spin_lock(&nilfs->ns_inode_lock); if (ii->i_bh == NULL) { - spin_unlock(&sbi->s_inode_lock); + spin_unlock(&nilfs->ns_inode_lock); err = nilfs_ifile_get_inode_block(ii->i_root->ifile, inode->i_ino, pbh); if (unlikely(err)) return err; - spin_lock(&sbi->s_inode_lock); + spin_lock(&nilfs->ns_inode_lock); if (ii->i_bh == NULL) ii->i_bh = *pbh; else { @@ -829,36 +829,36 @@ int nilfs_load_inode_block(struct inode *inode, struct buffer_head **pbh) *pbh = ii->i_bh; get_bh(*pbh); - spin_unlock(&sbi->s_inode_lock); + spin_unlock(&nilfs->ns_inode_lock); return 0; } int nilfs_inode_dirty(struct inode *inode) { struct nilfs_inode_info *ii = NILFS_I(inode); - struct nilfs_sb_info *sbi = NILFS_SB(inode->i_sb); + struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; int ret = 0; if (!list_empty(&ii->i_dirty)) { - spin_lock(&sbi->s_inode_lock); + spin_lock(&nilfs->ns_inode_lock); ret = test_bit(NILFS_I_DIRTY, &ii->i_state) || test_bit(NILFS_I_BUSY, &ii->i_state); - spin_unlock(&sbi->s_inode_lock); + spin_unlock(&nilfs->ns_inode_lock); } return ret; } int nilfs_set_file_dirty(struct inode *inode, unsigned nr_dirty) { - struct nilfs_sb_info *sbi = NILFS_SB(inode->i_sb); struct nilfs_inode_info *ii = NILFS_I(inode); + struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; - atomic_add(nr_dirty, &sbi->s_nilfs->ns_ndirtyblks); + atomic_add(nr_dirty, &nilfs->ns_ndirtyblks); if (test_and_set_bit(NILFS_I_DIRTY, &ii->i_state)) return 0; - spin_lock(&sbi->s_inode_lock); + spin_lock(&nilfs->ns_inode_lock); if (!test_bit(NILFS_I_QUEUED, &ii->i_state) && !test_bit(NILFS_I_BUSY, &ii->i_state)) { /* Because this routine may race with nilfs_dispose_list(), @@ -866,18 +866,18 @@ int nilfs_set_file_dirty(struct inode *inode, unsigned nr_dirty) if (list_empty(&ii->i_dirty) && igrab(inode) == NULL) { /* This will happen when somebody is freeing this inode. */ - nilfs_warning(sbi->s_super, __func__, + nilfs_warning(inode->i_sb, __func__, "cannot get inode (ino=%lu)\n", inode->i_ino); - spin_unlock(&sbi->s_inode_lock); + spin_unlock(&nilfs->ns_inode_lock); return -EINVAL; /* NILFS_I_DIRTY may remain for freeing inode */ } list_del(&ii->i_dirty); - list_add_tail(&ii->i_dirty, &sbi->s_dirty_files); + list_add_tail(&ii->i_dirty, &nilfs->ns_dirty_files); set_bit(NILFS_I_QUEUED, &ii->i_state); } - spin_unlock(&sbi->s_inode_lock); + spin_unlock(&nilfs->ns_inode_lock); return 0; } diff --git a/fs/nilfs2/sb.h b/fs/nilfs2/sb.h index 0512521ba8a4..3232e75fab75 100644 --- a/fs/nilfs2/sb.h +++ b/fs/nilfs2/sb.h @@ -39,10 +39,7 @@ struct nilfs_sb_info { struct the_nilfs *s_nilfs; /* Segment constructor */ - struct list_head s_dirty_files; /* dirty files list */ struct nilfs_sc_info *s_sc_info; /* segment constructor info */ - spinlock_t s_inode_lock; /* Lock for the nilfs inode. - It covers s_dirty_files list */ /* Inode allocator */ spinlock_t s_next_gen_lock; diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index a32d9cb2842a..6ac50d811841 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -104,8 +104,7 @@ struct nilfs_sc_operations { static void nilfs_segctor_start_timer(struct nilfs_sc_info *); static void nilfs_segctor_do_flush(struct nilfs_sc_info *, int); static void nilfs_segctor_do_immediate_flush(struct nilfs_sc_info *); -static void nilfs_dispose_list(struct nilfs_sb_info *, struct list_head *, - int); +static void nilfs_dispose_list(struct the_nilfs *, struct list_head *, int); #define nilfs_cnt32_gt(a, b) \ (typecheck(__u32, a) && typecheck(__u32, b) && \ @@ -325,14 +324,15 @@ static void nilfs_transaction_lock(struct nilfs_sb_info *sbi, static void nilfs_transaction_unlock(struct nilfs_sb_info *sbi) { struct nilfs_transaction_info *ti = current->journal_info; + struct the_nilfs *nilfs = sbi->s_nilfs; BUG_ON(ti == NULL || ti->ti_magic != NILFS_TI_MAGIC); BUG_ON(ti->ti_count > 0); - up_write(&sbi->s_nilfs->ns_segctor_sem); + up_write(&nilfs->ns_segctor_sem); current->journal_info = ti->ti_save; if (!list_empty(&ti->ti_garbage)) - nilfs_dispose_list(sbi, &ti->ti_garbage, 0); + nilfs_dispose_list(nilfs, &ti->ti_garbage, 0); } static void *nilfs_segctor_map_segsum_entry(struct nilfs_sc_info *sci, @@ -714,7 +714,7 @@ static void nilfs_lookup_dirty_node_buffers(struct inode *inode, } } -static void nilfs_dispose_list(struct nilfs_sb_info *sbi, +static void nilfs_dispose_list(struct the_nilfs *nilfs, struct list_head *head, int force) { struct nilfs_inode_info *ii, *n; @@ -722,7 +722,7 @@ static void nilfs_dispose_list(struct nilfs_sb_info *sbi, unsigned nv = 0; while (!list_empty(head)) { - spin_lock(&sbi->s_inode_lock); + spin_lock(&nilfs->ns_inode_lock); list_for_each_entry_safe(ii, n, head, i_dirty) { list_del_init(&ii->i_dirty); if (force) { @@ -733,14 +733,14 @@ static void nilfs_dispose_list(struct nilfs_sb_info *sbi, } else if (test_bit(NILFS_I_DIRTY, &ii->i_state)) { set_bit(NILFS_I_QUEUED, &ii->i_state); list_add_tail(&ii->i_dirty, - &sbi->s_dirty_files); + &nilfs->ns_dirty_files); continue; } ivec[nv++] = ii; if (nv == SC_N_INODEVEC) break; } - spin_unlock(&sbi->s_inode_lock); + spin_unlock(&nilfs->ns_inode_lock); for (pii = ivec; nv > 0; pii++, nv--) iput(&(*pii)->vfs_inode); @@ -773,17 +773,17 @@ static int nilfs_segctor_clean(struct nilfs_sc_info *sci) static int nilfs_segctor_confirm(struct nilfs_sc_info *sci) { - struct nilfs_sb_info *sbi = sci->sc_sbi; + struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs; int ret = 0; - if (nilfs_test_metadata_dirty(sbi->s_nilfs, sci->sc_root)) + if (nilfs_test_metadata_dirty(nilfs, sci->sc_root)) set_bit(NILFS_SC_DIRTY, &sci->sc_flags); - spin_lock(&sbi->s_inode_lock); - if (list_empty(&sbi->s_dirty_files) && nilfs_segctor_clean(sci)) + spin_lock(&nilfs->ns_inode_lock); + if (list_empty(&nilfs->ns_dirty_files) && nilfs_segctor_clean(sci)) ret++; - spin_unlock(&sbi->s_inode_lock); + spin_unlock(&nilfs->ns_inode_lock); return ret; } @@ -1963,30 +1963,30 @@ static int nilfs_segctor_wait(struct nilfs_sc_info *sci) return ret; } -static int nilfs_segctor_check_in_files(struct nilfs_sc_info *sci, - struct nilfs_sb_info *sbi) +static int nilfs_segctor_collect_dirty_files(struct nilfs_sc_info *sci, + struct the_nilfs *nilfs) { struct nilfs_inode_info *ii, *n; struct inode *ifile = sci->sc_root->ifile; - spin_lock(&sbi->s_inode_lock); + spin_lock(&nilfs->ns_inode_lock); retry: - list_for_each_entry_safe(ii, n, &sbi->s_dirty_files, i_dirty) { + list_for_each_entry_safe(ii, n, &nilfs->ns_dirty_files, i_dirty) { if (!ii->i_bh) { struct buffer_head *ibh; int err; - spin_unlock(&sbi->s_inode_lock); + spin_unlock(&nilfs->ns_inode_lock); err = nilfs_ifile_get_inode_block( ifile, ii->vfs_inode.i_ino, &ibh); if (unlikely(err)) { - nilfs_warning(sbi->s_super, __func__, + nilfs_warning(sci->sc_super, __func__, "failed to get inode block.\n"); return err; } nilfs_mdt_mark_buffer_dirty(ibh); nilfs_mdt_mark_dirty(ifile); - spin_lock(&sbi->s_inode_lock); + spin_lock(&nilfs->ns_inode_lock); if (likely(!ii->i_bh)) ii->i_bh = ibh; else @@ -1999,18 +1999,18 @@ static int nilfs_segctor_check_in_files(struct nilfs_sc_info *sci, list_del(&ii->i_dirty); list_add_tail(&ii->i_dirty, &sci->sc_dirty_files); } - spin_unlock(&sbi->s_inode_lock); + spin_unlock(&nilfs->ns_inode_lock); return 0; } -static void nilfs_segctor_check_out_files(struct nilfs_sc_info *sci, - struct nilfs_sb_info *sbi) +static void nilfs_segctor_drop_written_files(struct nilfs_sc_info *sci, + struct the_nilfs *nilfs) { struct nilfs_transaction_info *ti = current->journal_info; struct nilfs_inode_info *ii, *n; - spin_lock(&sbi->s_inode_lock); + spin_lock(&nilfs->ns_inode_lock); list_for_each_entry_safe(ii, n, &sci->sc_dirty_files, i_dirty) { if (!test_and_clear_bit(NILFS_I_UPDATED, &ii->i_state) || test_bit(NILFS_I_DIRTY, &ii->i_state)) @@ -2022,7 +2022,7 @@ static void nilfs_segctor_check_out_files(struct nilfs_sc_info *sci, list_del(&ii->i_dirty); list_add_tail(&ii->i_dirty, &ti->ti_garbage); } - spin_unlock(&sbi->s_inode_lock); + spin_unlock(&nilfs->ns_inode_lock); } /* @@ -2038,7 +2038,7 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode) sci->sc_stage.scnt = NILFS_ST_INIT; sci->sc_cno = nilfs->ns_cno; - err = nilfs_segctor_check_in_files(sci, sbi); + err = nilfs_segctor_collect_dirty_files(sci, nilfs); if (unlikely(err)) goto out; @@ -2116,7 +2116,7 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode) } while (sci->sc_stage.scnt != NILFS_ST_DONE); out: - nilfs_segctor_check_out_files(sci, sbi); + nilfs_segctor_drop_written_files(sci, nilfs); return err; failed_to_write: @@ -2319,14 +2319,14 @@ int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode, return err; } - spin_lock(&sbi->s_inode_lock); + spin_lock(&nilfs->ns_inode_lock); if (!test_bit(NILFS_I_QUEUED, &ii->i_state) && !test_bit(NILFS_I_BUSY, &ii->i_state)) { - spin_unlock(&sbi->s_inode_lock); + spin_unlock(&nilfs->ns_inode_lock); nilfs_transaction_unlock(sbi); return 0; } - spin_unlock(&sbi->s_inode_lock); + spin_unlock(&nilfs->ns_inode_lock); sci->sc_dsync_inode = ii; sci->sc_dsync_start = start; sci->sc_dsync_end = end; @@ -2738,10 +2738,10 @@ static void nilfs_segctor_write_out(struct nilfs_sc_info *sci) */ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci) { - struct nilfs_sb_info *sbi = sci->sc_sbi; + struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs; int flag; - up_write(&sbi->s_nilfs->ns_segctor_sem); + up_write(&nilfs->ns_segctor_sem); spin_lock(&sci->sc_state_lock); nilfs_segctor_kill_thread(sci); @@ -2755,9 +2755,9 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci) WARN_ON(!list_empty(&sci->sc_copied_buffers)); if (!list_empty(&sci->sc_dirty_files)) { - nilfs_warning(sbi->s_super, __func__, + nilfs_warning(sci->sc_super, __func__, "dirty file(s) after the final construction\n"); - nilfs_dispose_list(sbi, &sci->sc_dirty_files, 1); + nilfs_dispose_list(nilfs, &sci->sc_dirty_files, 1); } WARN_ON(!list_empty(&sci->sc_segbufs)); @@ -2765,7 +2765,7 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci) nilfs_put_root(sci->sc_root); - down_write(&sbi->s_nilfs->ns_segctor_sem); + down_write(&nilfs->ns_segctor_sem); del_timer_sync(&sci->sc_timer); kfree(sci); @@ -2829,15 +2829,15 @@ void nilfs_detach_segment_constructor(struct nilfs_sb_info *sbi) } /* Force to free the list of dirty files */ - spin_lock(&sbi->s_inode_lock); - if (!list_empty(&sbi->s_dirty_files)) { - list_splice_init(&sbi->s_dirty_files, &garbage_list); + spin_lock(&nilfs->ns_inode_lock); + if (!list_empty(&nilfs->ns_dirty_files)) { + list_splice_init(&nilfs->ns_dirty_files, &garbage_list); nilfs_warning(sbi->s_super, __func__, "Non empty dirty list after the last " "segment construction\n"); } - spin_unlock(&sbi->s_inode_lock); + spin_unlock(&nilfs->ns_inode_lock); up_write(&nilfs->ns_segctor_sem); - nilfs_dispose_list(sbi, &garbage_list, 1); + nilfs_dispose_list(nilfs, &garbage_list, 1); } diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 2f17a2f9ef9c..6dc8b3cad127 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -943,9 +943,6 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent) if (err) goto failed_nilfs; - spin_lock_init(&sbi->s_inode_lock); - INIT_LIST_HEAD(&sbi->s_dirty_files); - /* * Following initialization is overlapped because * nilfs_sb_info structure has been cleared at the beginning. diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c index d3775336a16c..40239a932dec 100644 --- a/fs/nilfs2/the_nilfs.c +++ b/fs/nilfs2/the_nilfs.c @@ -75,7 +75,9 @@ struct the_nilfs *alloc_nilfs(struct block_device *bdev) nilfs->ns_bdev = bdev; atomic_set(&nilfs->ns_ndirtyblks, 0); init_rwsem(&nilfs->ns_sem); + INIT_LIST_HEAD(&nilfs->ns_dirty_files); INIT_LIST_HEAD(&nilfs->ns_gc_inodes); + spin_lock_init(&nilfs->ns_inode_lock); spin_lock_init(&nilfs->ns_last_segment_lock); nilfs->ns_cptree = RB_ROOT; spin_lock_init(&nilfs->ns_cptree_lock); diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index 4a9bf3913c9c..6106ec5ad89a 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h @@ -71,6 +71,8 @@ enum { * @ns_sufile: segusage file inode * @ns_cptree: rb-tree of all mounted checkpoints (nilfs_root) * @ns_cptree_lock: lock protecting @ns_cptree + * @ns_dirty_files: list of dirty files + * @ns_inode_lock: lock protecting @ns_dirty_files * @ns_gc_inodes: dummy inodes to keep live blocks * @ns_mount_opt: mount options * @ns_resuid: uid for reserved blocks @@ -150,6 +152,10 @@ struct the_nilfs { struct rb_root ns_cptree; spinlock_t ns_cptree_lock; + /* Dirty inode list */ + struct list_head ns_dirty_files; + spinlock_t ns_inode_lock; + /* GC inode list */ struct list_head ns_gc_inodes; -- cgit From 9b1fc4e4973469dd3fab27ba5d78eca1cd5c13fe Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Wed, 9 Mar 2011 11:05:08 +0900 Subject: nilfs2: move next generation counter into nilfs object Moves s_next_generation counter and a spinlock protecting it to nilfs object from nilfs_sb_info structure. Signed-off-by: Ryusuke Konishi --- fs/nilfs2/inode.c | 8 ++++---- fs/nilfs2/sb.h | 4 ---- fs/nilfs2/super.c | 11 ----------- fs/nilfs2/the_nilfs.c | 5 +++++ fs/nilfs2/the_nilfs.h | 6 ++++++ 5 files changed, 15 insertions(+), 19 deletions(-) (limited to 'fs') diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index dd5d6d633ea1..7a3dbe4f229c 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c @@ -295,7 +295,7 @@ const struct address_space_operations nilfs_aops = { struct inode *nilfs_new_inode(struct inode *dir, int mode) { struct super_block *sb = dir->i_sb; - struct nilfs_sb_info *sbi = NILFS_SB(sb); + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; struct inode *inode; struct nilfs_inode_info *ii; struct nilfs_root *root; @@ -340,9 +340,9 @@ struct inode *nilfs_new_inode(struct inode *dir, int mode) /* ii->i_dir_acl = 0; */ ii->i_dir_start_lookup = 0; nilfs_set_inode_flags(inode); - spin_lock(&sbi->s_next_gen_lock); - inode->i_generation = sbi->s_next_generation++; - spin_unlock(&sbi->s_next_gen_lock); + spin_lock(&nilfs->ns_next_gen_lock); + inode->i_generation = nilfs->ns_next_generation++; + spin_unlock(&nilfs->ns_next_gen_lock); insert_inode_hash(inode); err = nilfs_init_acl(inode, dir); diff --git a/fs/nilfs2/sb.h b/fs/nilfs2/sb.h index 3232e75fab75..6f190dfdc649 100644 --- a/fs/nilfs2/sb.h +++ b/fs/nilfs2/sb.h @@ -40,10 +40,6 @@ struct nilfs_sb_info { /* Segment constructor */ struct nilfs_sc_info *s_sc_info; /* segment constructor info */ - - /* Inode allocator */ - spinlock_t s_next_gen_lock; - u32 s_next_generation; }; static inline struct nilfs_sb_info *NILFS_SB(struct super_block *sb) diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 6dc8b3cad127..1368c4293c7f 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include @@ -943,16 +942,6 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent) if (err) goto failed_nilfs; - /* - * Following initialization is overlapped because - * nilfs_sb_info structure has been cleared at the beginning. - * But we reserve them to keep our interest and make ready - * for the future change. - */ - get_random_bytes(&sbi->s_next_generation, - sizeof(sbi->s_next_generation)); - spin_lock_init(&sbi->s_next_gen_lock); - sb->s_op = &nilfs_sops; sb->s_export_op = &nilfs_export_ops; sb->s_root = NULL; diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c index 40239a932dec..1bf695e887a7 100644 --- a/fs/nilfs2/the_nilfs.c +++ b/fs/nilfs2/the_nilfs.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include "nilfs.h" #include "segment.h" @@ -78,6 +79,7 @@ struct the_nilfs *alloc_nilfs(struct block_device *bdev) INIT_LIST_HEAD(&nilfs->ns_dirty_files); INIT_LIST_HEAD(&nilfs->ns_gc_inodes); spin_lock_init(&nilfs->ns_inode_lock); + spin_lock_init(&nilfs->ns_next_gen_lock); spin_lock_init(&nilfs->ns_last_segment_lock); nilfs->ns_cptree = RB_ROOT; spin_lock_init(&nilfs->ns_cptree_lock); @@ -593,6 +595,9 @@ int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data) nilfs->ns_blocksize_bits = sb->s_blocksize_bits; nilfs->ns_blocksize = blocksize; + get_random_bytes(&nilfs->ns_next_generation, + sizeof(nilfs->ns_next_generation)); + err = nilfs_store_disk_layout(nilfs, sbp); if (err) goto failed_sbh; diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index 6106ec5ad89a..3ecc968f2123 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h @@ -74,6 +74,8 @@ enum { * @ns_dirty_files: list of dirty files * @ns_inode_lock: lock protecting @ns_dirty_files * @ns_gc_inodes: dummy inodes to keep live blocks + * @ns_next_generation: next generation number for inodes + * @ns_next_gen_lock: lock protecting @ns_next_generation * @ns_mount_opt: mount options * @ns_resuid: uid for reserved blocks * @ns_resgid: gid for reserved blocks @@ -159,6 +161,10 @@ struct the_nilfs { /* GC inode list */ struct list_head ns_gc_inodes; + /* Inode allocator */ + u32 ns_next_generation; + spinlock_t ns_next_gen_lock; + /* Mount options */ unsigned long ns_mount_opt; -- cgit From 3fd3fe5aeaa171a5638d2bb54a1a170eab7b7cdc Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Wed, 9 Mar 2011 11:05:08 +0900 Subject: nilfs2: move log writer onto nilfs object Log writer is held by the nilfs_sb_info structure. This moves it into nilfs object and replaces all uses of NILFS_SC() accessor. Signed-off-by: Ryusuke Konishi --- fs/nilfs2/sb.h | 9 -------- fs/nilfs2/segment.c | 58 +++++++++++++++++++++++++-------------------------- fs/nilfs2/the_nilfs.h | 6 +++++- 3 files changed, 34 insertions(+), 39 deletions(-) (limited to 'fs') diff --git a/fs/nilfs2/sb.h b/fs/nilfs2/sb.h index 6f190dfdc649..44553f42ebac 100644 --- a/fs/nilfs2/sb.h +++ b/fs/nilfs2/sb.h @@ -28,7 +28,6 @@ #include struct the_nilfs; -struct nilfs_sc_info; /* * NILFS super-block data in memory @@ -37,9 +36,6 @@ struct nilfs_sb_info { /* Fundamental members */ struct super_block *s_super; /* reverse pointer to super_block */ struct the_nilfs *s_nilfs; - - /* Segment constructor */ - struct nilfs_sc_info *s_sc_info; /* segment constructor info */ }; static inline struct nilfs_sb_info *NILFS_SB(struct super_block *sb) @@ -47,9 +43,4 @@ static inline struct nilfs_sb_info *NILFS_SB(struct super_block *sb) return sb->s_fs_info; } -static inline struct nilfs_sc_info *NILFS_SC(struct nilfs_sb_info *sbi) -{ - return sbi->s_sc_info; -} - #endif /* _NILFS_SB */ diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 6ac50d811841..e3d1785faf1b 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -224,8 +224,7 @@ int nilfs_transaction_begin(struct super_block *sb, int nilfs_transaction_commit(struct super_block *sb) { struct nilfs_transaction_info *ti = current->journal_info; - struct nilfs_sb_info *sbi; - struct nilfs_sc_info *sci; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; int err = 0; BUG_ON(ti == NULL || ti->ti_magic != NILFS_TI_MAGIC); @@ -234,16 +233,15 @@ int nilfs_transaction_commit(struct super_block *sb) ti->ti_count--; return 0; } - sbi = NILFS_SB(sb); - sci = NILFS_SC(sbi); - if (sci != NULL) { + if (nilfs->ns_writer) { + struct nilfs_sc_info *sci = nilfs->ns_writer; + if (ti->ti_flags & NILFS_TI_COMMIT) nilfs_segctor_start_timer(sci); - if (atomic_read(&sbi->s_nilfs->ns_ndirtyblks) > - sci->sc_watermark) + if (atomic_read(&nilfs->ns_ndirtyblks) > sci->sc_watermark) nilfs_segctor_do_flush(sci, 0); } - up_read(&sbi->s_nilfs->ns_segctor_sem); + up_read(&nilfs->ns_segctor_sem); current->journal_info = ti->ti_save; if (ti->ti_flags & NILFS_TI_SYNC) @@ -271,9 +269,8 @@ void nilfs_transaction_abort(struct super_block *sb) void nilfs_relax_pressure_in_lock(struct super_block *sb) { - struct nilfs_sb_info *sbi = NILFS_SB(sb); - struct nilfs_sc_info *sci = NILFS_SC(sbi); - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct nilfs_sc_info *sci = nilfs->ns_writer; if (!sci || !sci->sc_flush_request) return; @@ -298,6 +295,8 @@ static void nilfs_transaction_lock(struct nilfs_sb_info *sbi, int gcflag) { struct nilfs_transaction_info *cur_ti = current->journal_info; + struct the_nilfs *nilfs = sbi->s_nilfs; + struct nilfs_sc_info *sci = nilfs->ns_writer; WARN_ON(cur_ti); ti->ti_flags = NILFS_TI_WRITER; @@ -308,11 +307,11 @@ static void nilfs_transaction_lock(struct nilfs_sb_info *sbi, current->journal_info = ti; for (;;) { - down_write(&sbi->s_nilfs->ns_segctor_sem); - if (!test_bit(NILFS_SC_PRIOR_FLUSH, &NILFS_SC(sbi)->sc_flags)) + down_write(&nilfs->ns_segctor_sem); + if (!test_bit(NILFS_SC_PRIOR_FLUSH, &sci->sc_flags)) break; - nilfs_segctor_do_immediate_flush(NILFS_SC(sbi)); + nilfs_segctor_do_immediate_flush(sci); up_write(&sbi->s_nilfs->ns_segctor_sem); yield(); @@ -2169,8 +2168,8 @@ static void nilfs_segctor_do_flush(struct nilfs_sc_info *sci, int bn) */ void nilfs_flush_segment(struct super_block *sb, ino_t ino) { - struct nilfs_sb_info *sbi = NILFS_SB(sb); - struct nilfs_sc_info *sci = NILFS_SC(sbi); + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct nilfs_sc_info *sci = nilfs->ns_writer; if (!sci || nilfs_doing_construction()) return; @@ -2259,8 +2258,8 @@ static void nilfs_segctor_wakeup(struct nilfs_sc_info *sci, int err) */ int nilfs_construct_segment(struct super_block *sb) { - struct nilfs_sb_info *sbi = NILFS_SB(sb); - struct nilfs_sc_info *sci = NILFS_SC(sbi); + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct nilfs_sc_info *sci = nilfs->ns_writer; struct nilfs_transaction_info *ti; int err; @@ -2299,7 +2298,7 @@ int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode, { struct nilfs_sb_info *sbi = NILFS_SB(sb); struct the_nilfs *nilfs = sbi->s_nilfs; - struct nilfs_sc_info *sci = NILFS_SC(sbi); + struct nilfs_sc_info *sci = nilfs->ns_writer; struct nilfs_inode_info *ii; struct nilfs_transaction_info ti; int err = 0; @@ -2445,8 +2444,8 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv, void **kbufs) { struct nilfs_sb_info *sbi = NILFS_SB(sb); - struct nilfs_sc_info *sci = NILFS_SC(sbi); struct the_nilfs *nilfs = sbi->s_nilfs; + struct nilfs_sc_info *sci = nilfs->ns_writer; struct nilfs_transaction_info ti; int err; @@ -2787,9 +2786,10 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci) int nilfs_attach_segment_constructor(struct nilfs_sb_info *sbi, struct nilfs_root *root) { + struct the_nilfs *nilfs = sbi->s_nilfs; int err; - if (NILFS_SC(sbi)) { + if (nilfs->ns_writer) { /* * This happens if the filesystem was remounted * read/write after nilfs_error degenerated it into a @@ -2798,14 +2798,14 @@ int nilfs_attach_segment_constructor(struct nilfs_sb_info *sbi, nilfs_detach_segment_constructor(sbi); } - sbi->s_sc_info = nilfs_segctor_new(sbi, root); - if (!sbi->s_sc_info) + nilfs->ns_writer = nilfs_segctor_new(sbi, root); + if (!nilfs->ns_writer) return -ENOMEM; - err = nilfs_segctor_start_thread(NILFS_SC(sbi)); + err = nilfs_segctor_start_thread(nilfs->ns_writer); if (err) { - kfree(sbi->s_sc_info); - sbi->s_sc_info = NULL; + kfree(nilfs->ns_writer); + nilfs->ns_writer = NULL; } return err; } @@ -2823,9 +2823,9 @@ void nilfs_detach_segment_constructor(struct nilfs_sb_info *sbi) LIST_HEAD(garbage_list); down_write(&nilfs->ns_segctor_sem); - if (NILFS_SC(sbi)) { - nilfs_segctor_destroy(NILFS_SC(sbi)); - sbi->s_sc_info = NULL; + if (nilfs->ns_writer) { + nilfs_segctor_destroy(nilfs->ns_writer); + nilfs->ns_writer = NULL; } /* Force to free the list of dirty files */ diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index 3ecc968f2123..10521b97ded6 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h @@ -33,6 +33,8 @@ #include #include "sb.h" +struct nilfs_sc_info; + /* the_nilfs struct */ enum { THE_NILFS_INIT = 0, /* Information from super_block is set */ @@ -65,7 +67,8 @@ enum { * @ns_last_cno: checkpoint number of the latest segment * @ns_prot_seq: least sequence number of segments which must not be reclaimed * @ns_prev_seq: base sequence number used to decide if advance log cursor - * @ns_segctor_sem: segment constructor semaphore + * @ns_writer: log writer + * @ns_segctor_sem: semaphore protecting log write * @ns_dat: DAT file inode * @ns_cpfile: checkpoint file inode * @ns_sufile: segusage file inode @@ -140,6 +143,7 @@ struct the_nilfs { u64 ns_prot_seq; u64 ns_prev_seq; + struct nilfs_sc_info *ns_writer; struct rw_semaphore ns_segctor_sem; /* -- cgit From d96bbfa28aa7a1d5a5bf549026a594d7a273c5d7 Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Wed, 9 Mar 2011 11:05:08 +0900 Subject: nilfs2: get rid of sc_sbi back pointer Removes sci->sc_sbi which is a back pointer to nilfs_sb_info struct from log writer object (nilfs_sc_info). Signed-off-by: Ryusuke Konishi --- fs/nilfs2/segment.c | 29 ++++++++++++----------------- fs/nilfs2/segment.h | 2 -- 2 files changed, 12 insertions(+), 19 deletions(-) (limited to 'fs') diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index e3d1785faf1b..b14788ec0d15 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -772,7 +772,7 @@ static int nilfs_segctor_clean(struct nilfs_sc_info *sci) static int nilfs_segctor_confirm(struct nilfs_sc_info *sci) { - struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; int ret = 0; if (nilfs_test_metadata_dirty(nilfs, sci->sc_root)) @@ -788,8 +788,7 @@ static int nilfs_segctor_confirm(struct nilfs_sc_info *sci) static void nilfs_segctor_clear_metadata_dirty(struct nilfs_sc_info *sci) { - struct nilfs_sb_info *sbi = sci->sc_sbi; - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; nilfs_mdt_clear_dirty(sci->sc_root->ifile); nilfs_mdt_clear_dirty(nilfs->ns_cpfile); @@ -799,7 +798,7 @@ static void nilfs_segctor_clear_metadata_dirty(struct nilfs_sc_info *sci) static int nilfs_segctor_create_checkpoint(struct nilfs_sc_info *sci) { - struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; struct buffer_head *bh_cp; struct nilfs_checkpoint *raw_cp; int err; @@ -823,8 +822,7 @@ static int nilfs_segctor_create_checkpoint(struct nilfs_sc_info *sci) static int nilfs_segctor_fill_in_checkpoint(struct nilfs_sc_info *sci) { - struct nilfs_sb_info *sbi = sci->sc_sbi; - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; struct buffer_head *bh_cp; struct nilfs_checkpoint *raw_cp; int err; @@ -1048,8 +1046,7 @@ static int nilfs_segctor_scan_file_dsync(struct nilfs_sc_info *sci, static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode) { - struct nilfs_sb_info *sbi = sci->sc_sbi; - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; struct list_head *head; struct nilfs_inode_info *ii; size_t ndone; @@ -1858,7 +1855,7 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci) { struct nilfs_segment_buffer *segbuf; struct page *bd_page = NULL, *fs_page = NULL; - struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; int update_sr = false; list_for_each_entry(segbuf, &sci->sc_write_logs, sb_list) { @@ -2029,8 +2026,7 @@ static void nilfs_segctor_drop_written_files(struct nilfs_sc_info *sci, */ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode) { - struct nilfs_sb_info *sbi = sci->sc_sbi; - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; struct page *failed_page; int err; @@ -2388,7 +2384,7 @@ static void nilfs_segctor_notify(struct nilfs_sc_info *sci, int mode, int err) */ static int nilfs_segctor_construct(struct nilfs_sc_info *sci, int mode) { - struct nilfs_sb_info *sbi = sci->sc_sbi; + struct nilfs_sb_info *sbi = NILFS_SB(sci->sc_super); struct the_nilfs *nilfs = sbi->s_nilfs; struct nilfs_super_block **sbp; int err = 0; @@ -2501,7 +2497,7 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv, static void nilfs_segctor_thread_construct(struct nilfs_sc_info *sci, int mode) { - struct nilfs_sb_info *sbi = sci->sc_sbi; + struct nilfs_sb_info *sbi = NILFS_SB(sci->sc_super); struct nilfs_transaction_info ti; nilfs_transaction_lock(sbi, &ti, 0); @@ -2561,7 +2557,7 @@ static int nilfs_segctor_flush_mode(struct nilfs_sc_info *sci) static int nilfs_segctor_thread(void *arg) { struct nilfs_sc_info *sci = (struct nilfs_sc_info *)arg; - struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; int timeout = 0; sci->sc_timer.data = (unsigned long)current; @@ -2682,7 +2678,6 @@ static struct nilfs_sc_info *nilfs_segctor_new(struct nilfs_sb_info *sbi, if (!sci) return NULL; - sci->sc_sbi = sbi; sci->sc_super = sbi->s_super; nilfs_get_root(root); @@ -2717,7 +2712,7 @@ static void nilfs_segctor_write_out(struct nilfs_sc_info *sci) /* The segctord thread was stopped and its timer was removed. But some tasks remain. */ do { - struct nilfs_sb_info *sbi = sci->sc_sbi; + struct nilfs_sb_info *sbi = NILFS_SB(sci->sc_super); struct nilfs_transaction_info ti; nilfs_transaction_lock(sbi, &ti, 0); @@ -2737,7 +2732,7 @@ static void nilfs_segctor_write_out(struct nilfs_sc_info *sci) */ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci) { - struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; int flag; up_write(&nilfs->ns_segctor_sem); diff --git a/fs/nilfs2/segment.h b/fs/nilfs2/segment.h index cd8056e7cbed..9544aa97dd49 100644 --- a/fs/nilfs2/segment.h +++ b/fs/nilfs2/segment.h @@ -88,7 +88,6 @@ struct nilfs_segsum_pointer { /** * struct nilfs_sc_info - Segment constructor information * @sc_super: Back pointer to super_block struct - * @sc_sbi: Back pointer to nilfs_sb_info struct * @sc_root: root object of the current filesystem tree * @sc_nblk_inc: Block count of current generation * @sc_dirty_files: List of files to be written @@ -131,7 +130,6 @@ struct nilfs_segsum_pointer { */ struct nilfs_sc_info { struct super_block *sc_super; - struct nilfs_sb_info *sc_sbi; struct nilfs_root *sc_root; unsigned long sc_nblk_inc; -- cgit From f7545144c2e3d280139260df934043e0a6ccce6f Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Wed, 9 Mar 2011 11:05:08 +0900 Subject: nilfs2: use sb instance instead of nilfs_sb_info struct This replaces sbi uses with direct reference to sb instance. Signed-off-by: Ryusuke Konishi --- fs/nilfs2/nilfs.h | 10 ++--- fs/nilfs2/recovery.c | 32 +++++++-------- fs/nilfs2/segment.c | 90 ++++++++++++++++++++----------------------- fs/nilfs2/segment.h | 10 ++--- fs/nilfs2/super.c | 105 ++++++++++++++++++++++++-------------------------- fs/nilfs2/the_nilfs.c | 22 +++++------ fs/nilfs2/the_nilfs.h | 5 +-- 7 files changed, 129 insertions(+), 145 deletions(-) (limited to 'fs') diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h index 03ba4d88083f..eba1aaa7fb7b 100644 --- a/fs/nilfs2/nilfs.h +++ b/fs/nilfs2/nilfs.h @@ -295,11 +295,11 @@ extern int nilfs_check_feature_compatibility(struct super_block *, struct nilfs_super_block *); extern void nilfs_set_log_cursor(struct nilfs_super_block *, struct the_nilfs *); -extern struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *, - int flip); -extern int nilfs_commit_super(struct nilfs_sb_info *, int); -extern int nilfs_cleanup_super(struct nilfs_sb_info *); -int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt, +struct nilfs_super_block **nilfs_prepare_super(struct super_block *sb, + int flip); +int nilfs_commit_super(struct super_block *sb, int flag); +int nilfs_cleanup_super(struct super_block *sb); +int nilfs_attach_checkpoint(struct super_block *sb, __u64 cno, int curr_mnt, struct nilfs_root **root); int nilfs_checkpoint_is_mounted(struct super_block *sb, __u64 cno); diff --git a/fs/nilfs2/recovery.c b/fs/nilfs2/recovery.c index 3dfcd3b7d389..ba4a64518f38 100644 --- a/fs/nilfs2/recovery.c +++ b/fs/nilfs2/recovery.c @@ -425,7 +425,7 @@ void nilfs_dispose_segment_list(struct list_head *head) } static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs, - struct nilfs_sb_info *sbi, + struct super_block *sb, struct nilfs_recovery_info *ri) { struct list_head *head = &ri->ri_used_segments; @@ -501,7 +501,7 @@ static int nilfs_recovery_copy_block(struct the_nilfs *nilfs, } static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs, - struct nilfs_sb_info *sbi, + struct super_block *sb, struct nilfs_root *root, struct list_head *head, unsigned long *nr_salvaged_blocks) @@ -514,7 +514,7 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs, int err = 0, err2 = 0; list_for_each_entry_safe(rb, n, head, list) { - inode = nilfs_iget(sbi->s_super, root, rb->ino); + inode = nilfs_iget(sb, root, rb->ino); if (IS_ERR(inode)) { err = PTR_ERR(inode); inode = NULL; @@ -572,11 +572,11 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs, * nilfs_do_roll_forward - salvage logical segments newer than the latest * checkpoint * @nilfs: nilfs object - * @sbi: nilfs_sb_info + * @sb: super block instance * @ri: pointer to a nilfs_recovery_info */ static int nilfs_do_roll_forward(struct the_nilfs *nilfs, - struct nilfs_sb_info *sbi, + struct super_block *sb, struct nilfs_root *root, struct nilfs_recovery_info *ri) { @@ -648,7 +648,7 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs, goto failed; if (flags & NILFS_SS_LOGEND) { err = nilfs_recover_dsync_blocks( - nilfs, sbi, root, &dsync_blocks, + nilfs, sb, root, &dsync_blocks, &nsalvaged_blocks); if (unlikely(err)) goto failed; @@ -681,7 +681,7 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs, if (nsalvaged_blocks) { printk(KERN_INFO "NILFS (device %s): salvaged %lu blocks\n", - sbi->s_super->s_id, nsalvaged_blocks); + sb->s_id, nsalvaged_blocks); ri->ri_need_recovery = NILFS_RECOVERY_ROLLFORWARD_DONE; } out: @@ -695,7 +695,7 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs, printk(KERN_ERR "NILFS (device %s): Error roll-forwarding " "(err=%d, pseg block=%llu). ", - sbi->s_super->s_id, err, (unsigned long long)pseg_start); + sb->s_id, err, (unsigned long long)pseg_start); goto out; } @@ -724,7 +724,7 @@ static void nilfs_finish_roll_forward(struct the_nilfs *nilfs, /** * nilfs_salvage_orphan_logs - salvage logs written after the latest checkpoint * @nilfs: nilfs object - * @sbi: nilfs_sb_info + * @sb: super block instance * @ri: pointer to a nilfs_recovery_info struct to store search results. * * Return Value: On success, 0 is returned. On error, one of the following @@ -741,7 +741,7 @@ static void nilfs_finish_roll_forward(struct the_nilfs *nilfs, * %-ENOMEM - Insufficient memory available. */ int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs, - struct nilfs_sb_info *sbi, + struct super_block *sb, struct nilfs_recovery_info *ri) { struct nilfs_root *root; @@ -750,32 +750,32 @@ int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs, if (ri->ri_lsegs_start == 0 || ri->ri_lsegs_end == 0) return 0; - err = nilfs_attach_checkpoint(sbi, ri->ri_cno, true, &root); + err = nilfs_attach_checkpoint(sb, ri->ri_cno, true, &root); if (unlikely(err)) { printk(KERN_ERR "NILFS: error loading the latest checkpoint.\n"); return err; } - err = nilfs_do_roll_forward(nilfs, sbi, root, ri); + err = nilfs_do_roll_forward(nilfs, sb, root, ri); if (unlikely(err)) goto failed; if (ri->ri_need_recovery == NILFS_RECOVERY_ROLLFORWARD_DONE) { - err = nilfs_prepare_segment_for_recovery(nilfs, sbi, ri); + err = nilfs_prepare_segment_for_recovery(nilfs, sb, ri); if (unlikely(err)) { printk(KERN_ERR "NILFS: Error preparing segments for " "recovery.\n"); goto failed; } - err = nilfs_attach_segment_constructor(sbi, root); + err = nilfs_attach_log_writer(sb, root); if (unlikely(err)) goto failed; set_nilfs_discontinued(nilfs); - err = nilfs_construct_segment(sbi->s_super); - nilfs_detach_segment_constructor(sbi); + err = nilfs_construct_segment(sb); + nilfs_detach_log_writer(sb); if (unlikely(err)) { printk(KERN_ERR "NILFS: Oops! recovery failed. " diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index b14788ec0d15..90e3130303a3 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -181,7 +181,6 @@ int nilfs_transaction_begin(struct super_block *sb, struct nilfs_transaction_info *ti, int vacancy_check) { - struct nilfs_sb_info *sbi; struct the_nilfs *nilfs; int ret = nilfs_prepare_segment_lock(ti); @@ -192,8 +191,7 @@ int nilfs_transaction_begin(struct super_block *sb, vfs_check_frozen(sb, SB_FREEZE_WRITE); - sbi = NILFS_SB(sb); - nilfs = sbi->s_nilfs; + nilfs = NILFS_SB(sb)->s_nilfs; down_read(&nilfs->ns_segctor_sem); if (vacancy_check && nilfs_near_disk_full(nilfs)) { up_read(&nilfs->ns_segctor_sem); @@ -290,12 +288,12 @@ void nilfs_relax_pressure_in_lock(struct super_block *sb) downgrade_write(&nilfs->ns_segctor_sem); } -static void nilfs_transaction_lock(struct nilfs_sb_info *sbi, +static void nilfs_transaction_lock(struct super_block *sb, struct nilfs_transaction_info *ti, int gcflag) { struct nilfs_transaction_info *cur_ti = current->journal_info; - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; struct nilfs_sc_info *sci = nilfs->ns_writer; WARN_ON(cur_ti); @@ -313,17 +311,17 @@ static void nilfs_transaction_lock(struct nilfs_sb_info *sbi, nilfs_segctor_do_immediate_flush(sci); - up_write(&sbi->s_nilfs->ns_segctor_sem); + up_write(&nilfs->ns_segctor_sem); yield(); } if (gcflag) ti->ti_flags |= NILFS_TI_GC; } -static void nilfs_transaction_unlock(struct nilfs_sb_info *sbi) +static void nilfs_transaction_unlock(struct super_block *sb) { struct nilfs_transaction_info *ti = current->journal_info; - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; BUG_ON(ti == NULL || ti->ti_magic != NILFS_TI_MAGIC); BUG_ON(ti->ti_count > 0); @@ -2292,8 +2290,7 @@ int nilfs_construct_segment(struct super_block *sb) int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode, loff_t start, loff_t end) { - struct nilfs_sb_info *sbi = NILFS_SB(sb); - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; struct nilfs_sc_info *sci = nilfs->ns_writer; struct nilfs_inode_info *ii; struct nilfs_transaction_info ti; @@ -2302,14 +2299,14 @@ int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode, if (!sci) return -EROFS; - nilfs_transaction_lock(sbi, &ti, 0); + nilfs_transaction_lock(sb, &ti, 0); ii = NILFS_I(inode); if (test_bit(NILFS_I_INODE_DIRTY, &ii->i_state) || nilfs_test_opt(nilfs, STRICT_ORDER) || test_bit(NILFS_SC_UNCLOSED, &sci->sc_flags) || nilfs_discontinued(nilfs)) { - nilfs_transaction_unlock(sbi); + nilfs_transaction_unlock(sb); err = nilfs_segctor_sync(sci); return err; } @@ -2318,7 +2315,7 @@ int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode, if (!test_bit(NILFS_I_QUEUED, &ii->i_state) && !test_bit(NILFS_I_BUSY, &ii->i_state)) { spin_unlock(&nilfs->ns_inode_lock); - nilfs_transaction_unlock(sbi); + nilfs_transaction_unlock(sb); return 0; } spin_unlock(&nilfs->ns_inode_lock); @@ -2328,7 +2325,7 @@ int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode, err = nilfs_segctor_do_construct(sci, SC_LSEG_DSYNC); - nilfs_transaction_unlock(sbi); + nilfs_transaction_unlock(sb); return err; } @@ -2384,8 +2381,7 @@ static void nilfs_segctor_notify(struct nilfs_sc_info *sci, int mode, int err) */ static int nilfs_segctor_construct(struct nilfs_sc_info *sci, int mode) { - struct nilfs_sb_info *sbi = NILFS_SB(sci->sc_super); - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; struct nilfs_super_block **sbp; int err = 0; @@ -2403,11 +2399,12 @@ static int nilfs_segctor_construct(struct nilfs_sc_info *sci, int mode) nilfs_discontinued(nilfs)) { down_write(&nilfs->ns_sem); err = -EIO; - sbp = nilfs_prepare_super(sbi, + sbp = nilfs_prepare_super(sci->sc_super, nilfs_sb_will_flip(nilfs)); if (likely(sbp)) { nilfs_set_log_cursor(sbp[0], nilfs); - err = nilfs_commit_super(sbi, NILFS_SB_COMMIT); + err = nilfs_commit_super(sci->sc_super, + NILFS_SB_COMMIT); } up_write(&nilfs->ns_sem); } @@ -2439,8 +2436,7 @@ nilfs_remove_written_gcinodes(struct the_nilfs *nilfs, struct list_head *head) int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv, void **kbufs) { - struct nilfs_sb_info *sbi = NILFS_SB(sb); - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; struct nilfs_sc_info *sci = nilfs->ns_writer; struct nilfs_transaction_info ti; int err; @@ -2448,7 +2444,7 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv, if (unlikely(!sci)) return -EROFS; - nilfs_transaction_lock(sbi, &ti, 1); + nilfs_transaction_lock(sb, &ti, 1); err = nilfs_mdt_save_to_shadow_map(nilfs->ns_dat); if (unlikely(err)) @@ -2491,16 +2487,15 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv, sci->sc_freesegs = NULL; sci->sc_nfreesegs = 0; nilfs_mdt_clear_shadow_map(nilfs->ns_dat); - nilfs_transaction_unlock(sbi); + nilfs_transaction_unlock(sb); return err; } static void nilfs_segctor_thread_construct(struct nilfs_sc_info *sci, int mode) { - struct nilfs_sb_info *sbi = NILFS_SB(sci->sc_super); struct nilfs_transaction_info ti; - nilfs_transaction_lock(sbi, &ti, 0); + nilfs_transaction_lock(sci->sc_super, &ti, 0); nilfs_segctor_construct(sci, mode); /* @@ -2511,7 +2506,7 @@ static void nilfs_segctor_thread_construct(struct nilfs_sc_info *sci, int mode) if (test_bit(NILFS_SC_UNCLOSED, &sci->sc_flags)) nilfs_segctor_start_timer(sci); - nilfs_transaction_unlock(sbi); + nilfs_transaction_unlock(sci->sc_super); } static void nilfs_segctor_do_immediate_flush(struct nilfs_sc_info *sci) @@ -2668,17 +2663,17 @@ static void nilfs_segctor_kill_thread(struct nilfs_sc_info *sci) /* * Setup & clean-up functions */ -static struct nilfs_sc_info *nilfs_segctor_new(struct nilfs_sb_info *sbi, +static struct nilfs_sc_info *nilfs_segctor_new(struct super_block *sb, struct nilfs_root *root) { - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; struct nilfs_sc_info *sci; sci = kzalloc(sizeof(*sci), GFP_KERNEL); if (!sci) return NULL; - sci->sc_super = sbi->s_super; + sci->sc_super = sb; nilfs_get_root(root); sci->sc_root = root; @@ -2712,12 +2707,11 @@ static void nilfs_segctor_write_out(struct nilfs_sc_info *sci) /* The segctord thread was stopped and its timer was removed. But some tasks remain. */ do { - struct nilfs_sb_info *sbi = NILFS_SB(sci->sc_super); struct nilfs_transaction_info ti; - nilfs_transaction_lock(sbi, &ti, 0); + nilfs_transaction_lock(sci->sc_super, &ti, 0); ret = nilfs_segctor_construct(sci, SC_LSEG_SR); - nilfs_transaction_unlock(sbi); + nilfs_transaction_unlock(sci->sc_super); } while (ret && retrycount-- > 0); } @@ -2766,22 +2760,21 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci) } /** - * nilfs_attach_segment_constructor - attach a segment constructor - * @sbi: nilfs_sb_info + * nilfs_attach_log_writer - attach log writer + * @sb: super block instance * @root: root object of the current filesystem tree * - * nilfs_attach_segment_constructor() allocates a struct nilfs_sc_info, - * initializes it, and starts the segment constructor. + * This allocates a log writer object, initializes it, and starts the + * log writer. * * Return Value: On success, 0 is returned. On error, one of the following * negative error code is returned. * * %-ENOMEM - Insufficient memory available. */ -int nilfs_attach_segment_constructor(struct nilfs_sb_info *sbi, - struct nilfs_root *root) +int nilfs_attach_log_writer(struct super_block *sb, struct nilfs_root *root) { - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; int err; if (nilfs->ns_writer) { @@ -2790,10 +2783,10 @@ int nilfs_attach_segment_constructor(struct nilfs_sb_info *sbi, * read/write after nilfs_error degenerated it into a * read-only mount. */ - nilfs_detach_segment_constructor(sbi); + nilfs_detach_log_writer(sb); } - nilfs->ns_writer = nilfs_segctor_new(sbi, root); + nilfs->ns_writer = nilfs_segctor_new(sb, root); if (!nilfs->ns_writer) return -ENOMEM; @@ -2806,15 +2799,15 @@ int nilfs_attach_segment_constructor(struct nilfs_sb_info *sbi, } /** - * nilfs_detach_segment_constructor - destroy the segment constructor - * @sbi: nilfs_sb_info + * nilfs_detach_log_writer - destroy log writer + * @sb: super block instance * - * nilfs_detach_segment_constructor() kills the segment constructor daemon, - * frees the struct nilfs_sc_info, and destroy the dirty file list. + * This kills log writer daemon, frees the log writer object, and + * destroys list of dirty files. */ -void nilfs_detach_segment_constructor(struct nilfs_sb_info *sbi) +void nilfs_detach_log_writer(struct super_block *sb) { - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; LIST_HEAD(garbage_list); down_write(&nilfs->ns_segctor_sem); @@ -2827,9 +2820,8 @@ void nilfs_detach_segment_constructor(struct nilfs_sb_info *sbi) spin_lock(&nilfs->ns_inode_lock); if (!list_empty(&nilfs->ns_dirty_files)) { list_splice_init(&nilfs->ns_dirty_files, &garbage_list); - nilfs_warning(sbi->s_super, __func__, - "Non empty dirty list after the last " - "segment construction\n"); + nilfs_warning(sb, __func__, + "Hit dirty file after stopped log writer\n"); } spin_unlock(&nilfs->ns_inode_lock); up_write(&nilfs->ns_segctor_sem); diff --git a/fs/nilfs2/segment.h b/fs/nilfs2/segment.h index 9544aa97dd49..e01998e33b31 100644 --- a/fs/nilfs2/segment.h +++ b/fs/nilfs2/segment.h @@ -233,18 +233,16 @@ extern void nilfs_flush_segment(struct super_block *, ino_t); extern int nilfs_clean_segments(struct super_block *, struct nilfs_argv *, void **); -int nilfs_attach_segment_constructor(struct nilfs_sb_info *sbi, - struct nilfs_root *root); -extern void nilfs_detach_segment_constructor(struct nilfs_sb_info *); +int nilfs_attach_log_writer(struct super_block *sb, struct nilfs_root *root); +void nilfs_detach_log_writer(struct super_block *sb); /* recovery.c */ extern int nilfs_read_super_root_block(struct the_nilfs *, sector_t, struct buffer_head **, int); extern int nilfs_search_super_root(struct the_nilfs *, struct nilfs_recovery_info *); -extern int nilfs_salvage_orphan_logs(struct the_nilfs *, - struct nilfs_sb_info *, - struct nilfs_recovery_info *); +int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs, struct super_block *sb, + struct nilfs_recovery_info *ri); extern void nilfs_dispose_segment_list(struct list_head *); #endif /* _NILFS_SEGMENT_H */ diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 1368c4293c7f..a8cbd695441e 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -71,23 +71,23 @@ struct kmem_cache *nilfs_transaction_cachep; struct kmem_cache *nilfs_segbuf_cachep; struct kmem_cache *nilfs_btree_path_cache; -static int nilfs_setup_super(struct nilfs_sb_info *sbi, int is_mount); +static int nilfs_setup_super(struct super_block *sb, int is_mount); static int nilfs_remount(struct super_block *sb, int *flags, char *data); -static void nilfs_set_error(struct nilfs_sb_info *sbi) +static void nilfs_set_error(struct super_block *sb) { - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; struct nilfs_super_block **sbp; down_write(&nilfs->ns_sem); if (!(nilfs->ns_mount_state & NILFS_ERROR_FS)) { nilfs->ns_mount_state |= NILFS_ERROR_FS; - sbp = nilfs_prepare_super(sbi, 0); + sbp = nilfs_prepare_super(sb, 0); if (likely(sbp)) { sbp[0]->s_state |= cpu_to_le16(NILFS_ERROR_FS); if (sbp[1]) sbp[1]->s_state |= cpu_to_le16(NILFS_ERROR_FS); - nilfs_commit_super(sbi, NILFS_SB_COMMIT_ALL); + nilfs_commit_super(sb, NILFS_SB_COMMIT_ALL); } } up_write(&nilfs->ns_sem); @@ -108,7 +108,7 @@ static void nilfs_set_error(struct nilfs_sb_info *sbi) void nilfs_error(struct super_block *sb, const char *function, const char *fmt, ...) { - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; struct va_format vaf; va_list args; @@ -123,7 +123,7 @@ void nilfs_error(struct super_block *sb, const char *function, va_end(args); if (!(sb->s_flags & MS_RDONLY)) { - nilfs_set_error(sbi); + nilfs_set_error(sb); if (nilfs_test_opt(nilfs, ERRORS_RO)) { printk(KERN_CRIT "Remounting filesystem read-only\n"); @@ -188,9 +188,9 @@ void nilfs_destroy_inode(struct inode *inode) call_rcu(&inode->i_rcu, nilfs_i_callback); } -static int nilfs_sync_super(struct nilfs_sb_info *sbi, int flag) +static int nilfs_sync_super(struct super_block *sb, int flag) { - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; int err; retry: @@ -262,10 +262,10 @@ void nilfs_set_log_cursor(struct nilfs_super_block *sbp, spin_unlock(&nilfs->ns_last_segment_lock); } -struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *sbi, +struct nilfs_super_block **nilfs_prepare_super(struct super_block *sb, int flip) { - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; struct nilfs_super_block **sbp = nilfs->ns_sbp; /* nilfs->ns_sem must be locked by the caller. */ @@ -275,7 +275,7 @@ struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *sbi, memcpy(sbp[0], sbp[1], nilfs->ns_sbsize); } else { printk(KERN_CRIT "NILFS: superblock broke on dev %s\n", - sbi->s_super->s_id); + sb->s_id); return NULL; } } else if (sbp[1] && @@ -289,9 +289,9 @@ struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *sbi, return sbp; } -int nilfs_commit_super(struct nilfs_sb_info *sbi, int flag) +int nilfs_commit_super(struct super_block *sb, int flag) { - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; struct nilfs_super_block **sbp = nilfs->ns_sbp; time_t t; @@ -311,27 +311,28 @@ int nilfs_commit_super(struct nilfs_sb_info *sbi, int flag) nilfs->ns_sbsize)); } clear_nilfs_sb_dirty(nilfs); - return nilfs_sync_super(sbi, flag); + return nilfs_sync_super(sb, flag); } /** * nilfs_cleanup_super() - write filesystem state for cleanup - * @sbi: nilfs_sb_info to be unmounted or degraded to read-only + * @sb: super block instance to be unmounted or degraded to read-only * * This function restores state flags in the on-disk super block. * This will set "clean" flag (i.e. NILFS_VALID_FS) unless the * filesystem was not clean previously. */ -int nilfs_cleanup_super(struct nilfs_sb_info *sbi) +int nilfs_cleanup_super(struct super_block *sb) { + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; struct nilfs_super_block **sbp; int flag = NILFS_SB_COMMIT; int ret = -EIO; - sbp = nilfs_prepare_super(sbi, 0); + sbp = nilfs_prepare_super(sb, 0); if (sbp) { - sbp[0]->s_state = cpu_to_le16(sbi->s_nilfs->ns_mount_state); - nilfs_set_log_cursor(sbp[0], sbi->s_nilfs); + sbp[0]->s_state = cpu_to_le16(nilfs->ns_mount_state); + nilfs_set_log_cursor(sbp[0], nilfs); if (sbp[1] && sbp[0]->s_last_cno == sbp[1]->s_last_cno) { /* * make the "clean" flag also to the opposite @@ -341,7 +342,7 @@ int nilfs_cleanup_super(struct nilfs_sb_info *sbi) sbp[1]->s_state = sbp[0]->s_state; flag = NILFS_SB_COMMIT_ALL; } - ret = nilfs_commit_super(sbi, flag); + ret = nilfs_commit_super(sb, flag); } return ret; } @@ -351,11 +352,11 @@ static void nilfs_put_super(struct super_block *sb) struct nilfs_sb_info *sbi = NILFS_SB(sb); struct the_nilfs *nilfs = sbi->s_nilfs; - nilfs_detach_segment_constructor(sbi); + nilfs_detach_log_writer(sb); if (!(sb->s_flags & MS_RDONLY)) { down_write(&nilfs->ns_sem); - nilfs_cleanup_super(sbi); + nilfs_cleanup_super(sb); up_write(&nilfs->ns_sem); } @@ -371,8 +372,7 @@ static void nilfs_put_super(struct super_block *sb) static int nilfs_sync_fs(struct super_block *sb, int wait) { - struct nilfs_sb_info *sbi = NILFS_SB(sb); - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; struct nilfs_super_block **sbp; int err = 0; @@ -382,10 +382,10 @@ static int nilfs_sync_fs(struct super_block *sb, int wait) down_write(&nilfs->ns_sem); if (nilfs_sb_dirty(nilfs)) { - sbp = nilfs_prepare_super(sbi, nilfs_sb_will_flip(nilfs)); + sbp = nilfs_prepare_super(sb, nilfs_sb_will_flip(nilfs)); if (likely(sbp)) { nilfs_set_log_cursor(sbp[0], nilfs); - nilfs_commit_super(sbi, NILFS_SB_COMMIT); + nilfs_commit_super(sb, NILFS_SB_COMMIT); } } up_write(&nilfs->ns_sem); @@ -393,10 +393,10 @@ static int nilfs_sync_fs(struct super_block *sb, int wait) return err; } -int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt, +int nilfs_attach_checkpoint(struct super_block *sb, __u64 cno, int curr_mnt, struct nilfs_root **rootp) { - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; struct nilfs_root *root; struct nilfs_checkpoint *raw_cp; struct buffer_head *bh_cp; @@ -425,7 +425,7 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt, goto failed; } - err = nilfs_ifile_read(sbi->s_super, root, nilfs->ns_inode_size, + err = nilfs_ifile_read(sb, root, nilfs->ns_inode_size, &raw_cp->cp_ifile_inode, &root->ifile); if (err) goto failed_bh; @@ -449,8 +449,7 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt, static int nilfs_freeze(struct super_block *sb) { - struct nilfs_sb_info *sbi = NILFS_SB(sb); - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; int err; if (sb->s_flags & MS_RDONLY) @@ -458,21 +457,20 @@ static int nilfs_freeze(struct super_block *sb) /* Mark super block clean */ down_write(&nilfs->ns_sem); - err = nilfs_cleanup_super(sbi); + err = nilfs_cleanup_super(sb); up_write(&nilfs->ns_sem); return err; } static int nilfs_unfreeze(struct super_block *sb) { - struct nilfs_sb_info *sbi = NILFS_SB(sb); - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; if (sb->s_flags & MS_RDONLY) return 0; down_write(&nilfs->ns_sem); - nilfs_setup_super(sbi, false); + nilfs_setup_super(sb, false); up_write(&nilfs->ns_sem); return 0; } @@ -668,15 +666,15 @@ nilfs_set_default_options(struct super_block *sb, NILFS_MOUNT_ERRORS_RO | NILFS_MOUNT_BARRIER; } -static int nilfs_setup_super(struct nilfs_sb_info *sbi, int is_mount) +static int nilfs_setup_super(struct super_block *sb, int is_mount) { - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; struct nilfs_super_block **sbp; int max_mnt_count; int mnt_count; /* nilfs->ns_sem must be locked by the caller. */ - sbp = nilfs_prepare_super(sbi, 0); + sbp = nilfs_prepare_super(sb, 0); if (!sbp) return -EIO; @@ -707,7 +705,7 @@ skip_mount_setup: /* synchronize sbp[1] with sbp[0] */ if (sbp[1]) memcpy(sbp[1], sbp[0], nilfs->ns_sbsize); - return nilfs_commit_super(sbi, NILFS_SB_COMMIT_ALL); + return nilfs_commit_super(sb, NILFS_SB_COMMIT_ALL); } struct nilfs_super_block *nilfs_read_super_block(struct super_block *sb, @@ -841,7 +839,7 @@ static int nilfs_attach_snapshot(struct super_block *s, __u64 cno, goto out; } - ret = nilfs_attach_checkpoint(NILFS_SB(s), cno, false, &root); + ret = nilfs_attach_checkpoint(s, cno, false, &root); if (ret) { printk(KERN_ERR "NILFS: error loading snapshot " "(checkpoint number=%llu).\n", @@ -938,7 +936,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent) } sbi->s_nilfs = nilfs; - err = init_nilfs(nilfs, sbi, (char *)data); + err = init_nilfs(nilfs, sb, (char *)data); if (err) goto failed_nilfs; @@ -950,12 +948,12 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent) bdi = sb->s_bdev->bd_inode->i_mapping->backing_dev_info; sb->s_bdi = bdi ? : &default_backing_dev_info; - err = load_nilfs(nilfs, sbi); + err = load_nilfs(nilfs, sb); if (err) goto failed_nilfs; cno = nilfs_last_cno(nilfs); - err = nilfs_attach_checkpoint(sbi, cno, true, &fsroot); + err = nilfs_attach_checkpoint(sb, cno, true, &fsroot); if (err) { printk(KERN_ERR "NILFS: error loading last checkpoint " "(checkpoint number=%llu).\n", (unsigned long long)cno); @@ -963,7 +961,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent) } if (!(sb->s_flags & MS_RDONLY)) { - err = nilfs_attach_segment_constructor(sbi, fsroot); + err = nilfs_attach_log_writer(sb, fsroot); if (err) goto failed_checkpoint; } @@ -976,14 +974,14 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent) if (!(sb->s_flags & MS_RDONLY)) { down_write(&nilfs->ns_sem); - nilfs_setup_super(sbi, true); + nilfs_setup_super(sb, true); up_write(&nilfs->ns_sem); } return 0; failed_segctor: - nilfs_detach_segment_constructor(sbi); + nilfs_detach_log_writer(sb); failed_checkpoint: nilfs_put_root(fsroot); @@ -1004,8 +1002,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent) static int nilfs_remount(struct super_block *sb, int *flags, char *data) { - struct nilfs_sb_info *sbi = NILFS_SB(sb); - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; unsigned long old_sb_flags; unsigned long old_mount_opt; int err; @@ -1031,8 +1028,8 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) goto out; if (*flags & MS_RDONLY) { - /* Shutting down the segment constructor */ - nilfs_detach_segment_constructor(sbi); + /* Shutting down log writer */ + nilfs_detach_log_writer(sb); sb->s_flags |= MS_RDONLY; /* @@ -1040,7 +1037,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) * the RDONLY flag and then mark the partition as valid again. */ down_write(&nilfs->ns_sem); - nilfs_cleanup_super(sbi); + nilfs_cleanup_super(sb); up_write(&nilfs->ns_sem); } else { __u64 features; @@ -1067,12 +1064,12 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) sb->s_flags &= ~MS_RDONLY; root = NILFS_I(sb->s_root->d_inode)->i_root; - err = nilfs_attach_segment_constructor(sbi, root); + err = nilfs_attach_log_writer(sb, root); if (err) goto restore_opts; down_write(&nilfs->ns_sem); - nilfs_setup_super(sbi, true); + nilfs_setup_super(sb, true); up_write(&nilfs->ns_sem); } out: diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c index 1bf695e887a7..d2acd1a651f3 100644 --- a/fs/nilfs2/the_nilfs.c +++ b/fs/nilfs2/the_nilfs.c @@ -201,16 +201,16 @@ static int nilfs_store_log_cursor(struct the_nilfs *nilfs, /** * load_nilfs - load and recover the nilfs * @nilfs: the_nilfs structure to be released - * @sbi: nilfs_sb_info used to recover past segment + * @sb: super block isntance used to recover past segment * * load_nilfs() searches and load the latest super root, * attaches the last segment, and does recovery if needed. * The caller must call this exclusively for simultaneous mounts. */ -int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) +int load_nilfs(struct the_nilfs *nilfs, struct super_block *sb) { struct nilfs_recovery_info ri; - unsigned int s_flags = sbi->s_super->s_flags; + unsigned int s_flags = sb->s_flags; int really_read_only = bdev_read_only(nilfs->ns_bdev); int valid_fs = nilfs_valid_fs(nilfs); int err; @@ -275,7 +275,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) goto scan_error; } - err = nilfs_load_super_root(nilfs, sbi->s_super, ri.ri_super_root); + err = nilfs_load_super_root(nilfs, sb, ri.ri_super_root); if (unlikely(err)) { printk(KERN_ERR "NILFS: error loading super root.\n"); goto failed; @@ -308,7 +308,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) err = -EROFS; goto failed_unload; } - sbi->s_super->s_flags &= ~MS_RDONLY; + sb->s_flags &= ~MS_RDONLY; } else if (nilfs_test_opt(nilfs, NORECOVERY)) { printk(KERN_ERR "NILFS: recovery cancelled because norecovery " "option was specified for a read/write mount\n"); @@ -316,13 +316,13 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) goto failed_unload; } - err = nilfs_salvage_orphan_logs(nilfs, sbi, &ri); + err = nilfs_salvage_orphan_logs(nilfs, sb, &ri); if (err) goto failed_unload; down_write(&nilfs->ns_sem); nilfs->ns_mount_state |= NILFS_VALID_FS; /* set "clean" flag */ - err = nilfs_cleanup_super(sbi); + err = nilfs_cleanup_super(sb); up_write(&nilfs->ns_sem); if (err) { @@ -334,7 +334,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) skip_recovery: nilfs_clear_recovery_info(&ri); - sbi->s_super->s_flags = s_flags; + sb->s_flags = s_flags; return 0; scan_error: @@ -348,7 +348,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) failed: nilfs_clear_recovery_info(&ri); - sbi->s_super->s_flags = s_flags; + sb->s_flags = s_flags; return err; } @@ -526,7 +526,6 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs, /** * init_nilfs - initialize a NILFS instance. * @nilfs: the_nilfs structure - * @sbi: nilfs_sb_info * @sb: super block * @data: mount options * @@ -537,9 +536,8 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs, * Return Value: On success, 0 is returned. On error, a negative error * code is returned. */ -int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data) +int init_nilfs(struct the_nilfs *nilfs, struct super_block *sb, char *data) { - struct super_block *sb = sbi->s_super; struct nilfs_super_block *sbp; int blocksize; int err; diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index 10521b97ded6..793bd272f9e0 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h @@ -267,15 +267,14 @@ static inline int nilfs_sb_will_flip(struct the_nilfs *nilfs) void nilfs_set_last_segment(struct the_nilfs *, sector_t, u64, __u64); struct the_nilfs *alloc_nilfs(struct block_device *bdev); void destroy_nilfs(struct the_nilfs *nilfs); -int init_nilfs(struct the_nilfs *, struct nilfs_sb_info *, char *); -int load_nilfs(struct the_nilfs *, struct nilfs_sb_info *); +int init_nilfs(struct the_nilfs *nilfs, struct super_block *sb, char *data); +int load_nilfs(struct the_nilfs *nilfs, struct super_block *sb); int nilfs_discard_segments(struct the_nilfs *, __u64 *, size_t); int nilfs_count_free_blocks(struct the_nilfs *, sector_t *); struct nilfs_root *nilfs_lookup_root(struct the_nilfs *nilfs, __u64 cno); struct nilfs_root *nilfs_find_or_create_root(struct the_nilfs *nilfs, __u64 cno); void nilfs_put_root(struct nilfs_root *root); -struct nilfs_sb_info *nilfs_find_sbinfo(struct the_nilfs *, int, __u64); int nilfs_near_disk_full(struct the_nilfs *); void nilfs_fall_back_super_block(struct the_nilfs *); void nilfs_swap_super_block(struct the_nilfs *); -- cgit From e3154e9748f0f337e9f6ff9dc7d7bf24d426bd1a Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Wed, 9 Mar 2011 11:05:08 +0900 Subject: nilfs2: get rid of nilfs_sb_info structure This directly uses sb->s_fs_info to keep a nilfs filesystem object and fully removes the intermediate nilfs_sb_info structure. With this change, the hierarchy of on-memory structures of nilfs will be simplified as follows: Before: super_block -> nilfs_sb_info -> the_nilfs -> cptree --+-> nilfs_root (current file system) +-> nilfs_root (snapshot A) +-> nilfs_root (snapshot B) : -> nilfs_sc_info (log writer structure) After: super_block -> the_nilfs -> cptree --+-> nilfs_root (current file system) +-> nilfs_root (snapshot A) +-> nilfs_root (snapshot B) : -> nilfs_sc_info (log writer structure) The reason why we didn't design so from the beginning is because the initial shape also differed from the above. The early hierachy was composed of "per-mount-point" super_block -> nilfs_sb_info pairs and a shared nilfs object. On the kernel 2.6.37, it was changed to the current shape in order to unify super block instances into one per device, and this cleanup became applicable as the result. Signed-off-by: Ryusuke Konishi --- fs/nilfs2/bmap.c | 1 - fs/nilfs2/file.c | 2 +- fs/nilfs2/inode.c | 10 ++++---- fs/nilfs2/ioctl.c | 23 +++++++++---------- fs/nilfs2/mdt.h | 2 +- fs/nilfs2/namei.c | 2 +- fs/nilfs2/nilfs.h | 3 +-- fs/nilfs2/sb.h | 46 ------------------------------------- fs/nilfs2/segment.c | 47 +++++++++++++++++++------------------- fs/nilfs2/segment.h | 2 +- fs/nilfs2/super.c | 63 +++++++++++++++++++-------------------------------- fs/nilfs2/the_nilfs.h | 1 - 12 files changed, 68 insertions(+), 134 deletions(-) delete mode 100644 fs/nilfs2/sb.h (limited to 'fs') diff --git a/fs/nilfs2/bmap.c b/fs/nilfs2/bmap.c index 85447a2fab33..4723f04e9b12 100644 --- a/fs/nilfs2/bmap.c +++ b/fs/nilfs2/bmap.c @@ -25,7 +25,6 @@ #include #include "nilfs.h" #include "bmap.h" -#include "sb.h" #include "btree.h" #include "direct.h" #include "btnode.h" diff --git a/fs/nilfs2/file.c b/fs/nilfs2/file.c index 7a5e4ab15c6e..93589fccdd97 100644 --- a/fs/nilfs2/file.c +++ b/fs/nilfs2/file.c @@ -59,7 +59,7 @@ static int nilfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) struct nilfs_transaction_info ti; int ret; - if (unlikely(nilfs_near_disk_full(NILFS_SB(inode->i_sb)->s_nilfs))) + if (unlikely(nilfs_near_disk_full(inode->i_sb->s_fs_info))) return VM_FAULT_SIGBUS; /* -ENOSPC */ lock_page(page); diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 7a3dbe4f229c..d5625be236a8 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c @@ -295,7 +295,7 @@ const struct address_space_operations nilfs_aops = { struct inode *nilfs_new_inode(struct inode *dir, int mode) { struct super_block *sb = dir->i_sb; - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct inode *inode; struct nilfs_inode_info *ii; struct nilfs_root *root; @@ -433,7 +433,7 @@ static int __nilfs_read_inode(struct super_block *sb, struct nilfs_root *root, unsigned long ino, struct inode *inode) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct buffer_head *bh; struct nilfs_inode *raw_inode; int err; @@ -807,7 +807,7 @@ int nilfs_permission(struct inode *inode, int mask, unsigned int flags) int nilfs_load_inode_block(struct inode *inode, struct buffer_head **pbh) { - struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; + struct the_nilfs *nilfs = inode->i_sb->s_fs_info; struct nilfs_inode_info *ii = NILFS_I(inode); int err; @@ -836,7 +836,7 @@ int nilfs_load_inode_block(struct inode *inode, struct buffer_head **pbh) int nilfs_inode_dirty(struct inode *inode) { struct nilfs_inode_info *ii = NILFS_I(inode); - struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; + struct the_nilfs *nilfs = inode->i_sb->s_fs_info; int ret = 0; if (!list_empty(&ii->i_dirty)) { @@ -851,7 +851,7 @@ int nilfs_inode_dirty(struct inode *inode) int nilfs_set_file_dirty(struct inode *inode, unsigned nr_dirty) { struct nilfs_inode_info *ii = NILFS_I(inode); - struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; + struct the_nilfs *nilfs = inode->i_sb->s_fs_info; atomic_add(nr_dirty, &nilfs->ns_ndirtyblks); diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index 5471eed5eccb..95c04c2f2b3e 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c @@ -166,8 +166,7 @@ static int nilfs_ioctl_getversion(struct inode *inode, void __user *argp) static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp, unsigned int cmd, void __user *argp) { - struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; - struct inode *cpfile = nilfs->ns_cpfile; + struct the_nilfs *nilfs = inode->i_sb->s_fs_info; struct nilfs_transaction_info ti; struct nilfs_cpmode cpmode; int ret; @@ -187,7 +186,7 @@ static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp, nilfs_transaction_begin(inode->i_sb, &ti, 0); ret = nilfs_cpfile_change_cpmode( - cpfile, cpmode.cm_cno, cpmode.cm_mode); + nilfs->ns_cpfile, cpmode.cm_cno, cpmode.cm_mode); if (unlikely(ret < 0)) nilfs_transaction_abort(inode->i_sb); else @@ -203,7 +202,7 @@ static int nilfs_ioctl_delete_checkpoint(struct inode *inode, struct file *filp, unsigned int cmd, void __user *argp) { - struct inode *cpfile = NILFS_SB(inode->i_sb)->s_nilfs->ns_cpfile; + struct the_nilfs *nilfs = inode->i_sb->s_fs_info; struct nilfs_transaction_info ti; __u64 cno; int ret; @@ -220,7 +219,7 @@ nilfs_ioctl_delete_checkpoint(struct inode *inode, struct file *filp, goto out; nilfs_transaction_begin(inode->i_sb, &ti, 0); - ret = nilfs_cpfile_delete_checkpoint(cpfile, cno); + ret = nilfs_cpfile_delete_checkpoint(nilfs->ns_cpfile, cno); if (unlikely(ret < 0)) nilfs_transaction_abort(inode->i_sb); else @@ -246,7 +245,7 @@ nilfs_ioctl_do_get_cpinfo(struct the_nilfs *nilfs, __u64 *posp, int flags, static int nilfs_ioctl_get_cpstat(struct inode *inode, struct file *filp, unsigned int cmd, void __user *argp) { - struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; + struct the_nilfs *nilfs = inode->i_sb->s_fs_info; struct nilfs_cpstat cpstat; int ret; @@ -277,7 +276,7 @@ nilfs_ioctl_do_get_suinfo(struct the_nilfs *nilfs, __u64 *posp, int flags, static int nilfs_ioctl_get_sustat(struct inode *inode, struct file *filp, unsigned int cmd, void __user *argp) { - struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; + struct the_nilfs *nilfs = inode->i_sb->s_fs_info; struct nilfs_sustat sustat; int ret; @@ -333,7 +332,7 @@ nilfs_ioctl_do_get_bdescs(struct the_nilfs *nilfs, __u64 *posp, int flags, static int nilfs_ioctl_get_bdescs(struct inode *inode, struct file *filp, unsigned int cmd, void __user *argp) { - struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; + struct the_nilfs *nilfs = inode->i_sb->s_fs_info; struct nilfs_argv argv; int ret; @@ -402,7 +401,7 @@ static int nilfs_ioctl_move_blocks(struct super_block *sb, struct nilfs_argv *argv, void *buf) { size_t nmembs = argv->v_nmembs; - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct inode *inode; struct nilfs_vdesc *vdesc; struct buffer_head *bh, *n; @@ -616,7 +615,7 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp, ret = PTR_ERR(kbufs[4]); goto out; } - nilfs = NILFS_SB(inode->i_sb)->s_nilfs; + nilfs = inode->i_sb->s_fs_info; for (n = 0; n < 4; n++) { ret = -EINVAL; @@ -689,7 +688,7 @@ static int nilfs_ioctl_sync(struct inode *inode, struct file *filp, return ret; if (argp != NULL) { - nilfs = NILFS_SB(inode->i_sb)->s_nilfs; + nilfs = inode->i_sb->s_fs_info; down_read(&nilfs->ns_segctor_sem); cno = nilfs->ns_cno - 1; up_read(&nilfs->ns_segctor_sem); @@ -707,7 +706,7 @@ static int nilfs_ioctl_get_info(struct inode *inode, struct file *filp, void *, size_t, size_t)) { - struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; + struct the_nilfs *nilfs = inode->i_sb->s_fs_info; struct nilfs_argv argv; int ret; diff --git a/fs/nilfs2/mdt.h b/fs/nilfs2/mdt.h index b13734bf3521..ed68563ec708 100644 --- a/fs/nilfs2/mdt.h +++ b/fs/nilfs2/mdt.h @@ -66,7 +66,7 @@ static inline struct nilfs_mdt_info *NILFS_MDT(const struct inode *inode) static inline struct the_nilfs *NILFS_I_NILFS(struct inode *inode) { - return NILFS_SB(inode->i_sb)->s_nilfs; + return inode->i_sb->s_fs_info; } /* Default GFP flags using highmem */ diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c index 161791d26458..546849b3e88f 100644 --- a/fs/nilfs2/namei.c +++ b/fs/nilfs2/namei.c @@ -482,7 +482,7 @@ static struct dentry *nilfs_get_dentry(struct super_block *sb, u64 cno, if (ino < NILFS_FIRST_INO(sb) && ino != NILFS_ROOT_INO) return ERR_PTR(-ESTALE); - root = nilfs_lookup_root(NILFS_SB(sb)->s_nilfs, cno); + root = nilfs_lookup_root(sb->s_fs_info, cno); if (!root) return ERR_PTR(-ESTALE); diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h index eba1aaa7fb7b..856e8e4e0b74 100644 --- a/fs/nilfs2/nilfs.h +++ b/fs/nilfs2/nilfs.h @@ -30,7 +30,6 @@ #include #include #include "the_nilfs.h" -#include "sb.h" #include "bmap.h" /* @@ -122,7 +121,7 @@ enum { #define NILFS_SYS_INO_BITS \ ((unsigned int)(1 << NILFS_ROOT_INO) | NILFS_MDT_INO_BITS) -#define NILFS_FIRST_INO(sb) (NILFS_SB(sb)->s_nilfs->ns_first_ino) +#define NILFS_FIRST_INO(sb) (((struct the_nilfs *)sb->s_fs_info)->ns_first_ino) #define NILFS_MDT_INODE(sb, ino) \ ((ino) < NILFS_FIRST_INO(sb) && (NILFS_MDT_INO_BITS & (1 << (ino)))) diff --git a/fs/nilfs2/sb.h b/fs/nilfs2/sb.h deleted file mode 100644 index 44553f42ebac..000000000000 --- a/fs/nilfs2/sb.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * sb.h - NILFS on-memory super block structure. - * - * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Written by Ryusuke Konishi - * - */ - -#ifndef _NILFS_SB -#define _NILFS_SB - -#include -#include - -struct the_nilfs; - -/* - * NILFS super-block data in memory - */ -struct nilfs_sb_info { - /* Fundamental members */ - struct super_block *s_super; /* reverse pointer to super_block */ - struct the_nilfs *s_nilfs; -}; - -static inline struct nilfs_sb_info *NILFS_SB(struct super_block *sb) -{ - return sb->s_fs_info; -} - -#endif /* _NILFS_SB */ diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 90e3130303a3..afe4f2183454 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -191,7 +191,7 @@ int nilfs_transaction_begin(struct super_block *sb, vfs_check_frozen(sb, SB_FREEZE_WRITE); - nilfs = NILFS_SB(sb)->s_nilfs; + nilfs = sb->s_fs_info; down_read(&nilfs->ns_segctor_sem); if (vacancy_check && nilfs_near_disk_full(nilfs)) { up_read(&nilfs->ns_segctor_sem); @@ -222,7 +222,7 @@ int nilfs_transaction_begin(struct super_block *sb, int nilfs_transaction_commit(struct super_block *sb) { struct nilfs_transaction_info *ti = current->journal_info; - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; int err = 0; BUG_ON(ti == NULL || ti->ti_magic != NILFS_TI_MAGIC); @@ -252,13 +252,14 @@ int nilfs_transaction_commit(struct super_block *sb) void nilfs_transaction_abort(struct super_block *sb) { struct nilfs_transaction_info *ti = current->journal_info; + struct the_nilfs *nilfs = sb->s_fs_info; BUG_ON(ti == NULL || ti->ti_magic != NILFS_TI_MAGIC); if (ti->ti_count > 0) { ti->ti_count--; return; } - up_read(&NILFS_SB(sb)->s_nilfs->ns_segctor_sem); + up_read(&nilfs->ns_segctor_sem); current->journal_info = ti->ti_save; if (ti->ti_flags & NILFS_TI_DYNAMIC_ALLOC) @@ -267,7 +268,7 @@ void nilfs_transaction_abort(struct super_block *sb) void nilfs_relax_pressure_in_lock(struct super_block *sb) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct nilfs_sc_info *sci = nilfs->ns_writer; if (!sci || !sci->sc_flush_request) @@ -293,7 +294,7 @@ static void nilfs_transaction_lock(struct super_block *sb, int gcflag) { struct nilfs_transaction_info *cur_ti = current->journal_info; - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct nilfs_sc_info *sci = nilfs->ns_writer; WARN_ON(cur_ti); @@ -321,7 +322,7 @@ static void nilfs_transaction_lock(struct super_block *sb, static void nilfs_transaction_unlock(struct super_block *sb) { struct nilfs_transaction_info *ti = current->journal_info; - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; BUG_ON(ti == NULL || ti->ti_magic != NILFS_TI_MAGIC); BUG_ON(ti->ti_count > 0); @@ -770,7 +771,7 @@ static int nilfs_segctor_clean(struct nilfs_sc_info *sci) static int nilfs_segctor_confirm(struct nilfs_sc_info *sci) { - struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; + struct the_nilfs *nilfs = sci->sc_super->s_fs_info; int ret = 0; if (nilfs_test_metadata_dirty(nilfs, sci->sc_root)) @@ -786,7 +787,7 @@ static int nilfs_segctor_confirm(struct nilfs_sc_info *sci) static void nilfs_segctor_clear_metadata_dirty(struct nilfs_sc_info *sci) { - struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; + struct the_nilfs *nilfs = sci->sc_super->s_fs_info; nilfs_mdt_clear_dirty(sci->sc_root->ifile); nilfs_mdt_clear_dirty(nilfs->ns_cpfile); @@ -796,7 +797,7 @@ static void nilfs_segctor_clear_metadata_dirty(struct nilfs_sc_info *sci) static int nilfs_segctor_create_checkpoint(struct nilfs_sc_info *sci) { - struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; + struct the_nilfs *nilfs = sci->sc_super->s_fs_info; struct buffer_head *bh_cp; struct nilfs_checkpoint *raw_cp; int err; @@ -820,7 +821,7 @@ static int nilfs_segctor_create_checkpoint(struct nilfs_sc_info *sci) static int nilfs_segctor_fill_in_checkpoint(struct nilfs_sc_info *sci) { - struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; + struct the_nilfs *nilfs = sci->sc_super->s_fs_info; struct buffer_head *bh_cp; struct nilfs_checkpoint *raw_cp; int err; @@ -1044,7 +1045,7 @@ static int nilfs_segctor_scan_file_dsync(struct nilfs_sc_info *sci, static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode) { - struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; + struct the_nilfs *nilfs = sci->sc_super->s_fs_info; struct list_head *head; struct nilfs_inode_info *ii; size_t ndone; @@ -1853,7 +1854,7 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci) { struct nilfs_segment_buffer *segbuf; struct page *bd_page = NULL, *fs_page = NULL; - struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; + struct the_nilfs *nilfs = sci->sc_super->s_fs_info; int update_sr = false; list_for_each_entry(segbuf, &sci->sc_write_logs, sb_list) { @@ -2024,7 +2025,7 @@ static void nilfs_segctor_drop_written_files(struct nilfs_sc_info *sci, */ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode) { - struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; + struct the_nilfs *nilfs = sci->sc_super->s_fs_info; struct page *failed_page; int err; @@ -2162,7 +2163,7 @@ static void nilfs_segctor_do_flush(struct nilfs_sc_info *sci, int bn) */ void nilfs_flush_segment(struct super_block *sb, ino_t ino) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct nilfs_sc_info *sci = nilfs->ns_writer; if (!sci || nilfs_doing_construction()) @@ -2252,7 +2253,7 @@ static void nilfs_segctor_wakeup(struct nilfs_sc_info *sci, int err) */ int nilfs_construct_segment(struct super_block *sb) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct nilfs_sc_info *sci = nilfs->ns_writer; struct nilfs_transaction_info *ti; int err; @@ -2290,7 +2291,7 @@ int nilfs_construct_segment(struct super_block *sb) int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode, loff_t start, loff_t end) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct nilfs_sc_info *sci = nilfs->ns_writer; struct nilfs_inode_info *ii; struct nilfs_transaction_info ti; @@ -2381,7 +2382,7 @@ static void nilfs_segctor_notify(struct nilfs_sc_info *sci, int mode, int err) */ static int nilfs_segctor_construct(struct nilfs_sc_info *sci, int mode) { - struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; + struct the_nilfs *nilfs = sci->sc_super->s_fs_info; struct nilfs_super_block **sbp; int err = 0; @@ -2436,7 +2437,7 @@ nilfs_remove_written_gcinodes(struct the_nilfs *nilfs, struct list_head *head) int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv, void **kbufs) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct nilfs_sc_info *sci = nilfs->ns_writer; struct nilfs_transaction_info ti; int err; @@ -2552,7 +2553,7 @@ static int nilfs_segctor_flush_mode(struct nilfs_sc_info *sci) static int nilfs_segctor_thread(void *arg) { struct nilfs_sc_info *sci = (struct nilfs_sc_info *)arg; - struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; + struct the_nilfs *nilfs = sci->sc_super->s_fs_info; int timeout = 0; sci->sc_timer.data = (unsigned long)current; @@ -2666,7 +2667,7 @@ static void nilfs_segctor_kill_thread(struct nilfs_sc_info *sci) static struct nilfs_sc_info *nilfs_segctor_new(struct super_block *sb, struct nilfs_root *root) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct nilfs_sc_info *sci; sci = kzalloc(sizeof(*sci), GFP_KERNEL); @@ -2726,7 +2727,7 @@ static void nilfs_segctor_write_out(struct nilfs_sc_info *sci) */ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci) { - struct the_nilfs *nilfs = NILFS_SB(sci->sc_super)->s_nilfs; + struct the_nilfs *nilfs = sci->sc_super->s_fs_info; int flag; up_write(&nilfs->ns_segctor_sem); @@ -2774,7 +2775,7 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci) */ int nilfs_attach_log_writer(struct super_block *sb, struct nilfs_root *root) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; int err; if (nilfs->ns_writer) { @@ -2807,7 +2808,7 @@ int nilfs_attach_log_writer(struct super_block *sb, struct nilfs_root *root) */ void nilfs_detach_log_writer(struct super_block *sb) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; LIST_HEAD(garbage_list); down_write(&nilfs->ns_segctor_sem); diff --git a/fs/nilfs2/segment.h b/fs/nilfs2/segment.h index e01998e33b31..6c02a86745fb 100644 --- a/fs/nilfs2/segment.h +++ b/fs/nilfs2/segment.h @@ -27,7 +27,7 @@ #include #include #include -#include "sb.h" +#include "nilfs.h" struct nilfs_root; diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index a8cbd695441e..062cca065195 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -76,7 +76,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data); static void nilfs_set_error(struct super_block *sb) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct nilfs_super_block **sbp; down_write(&nilfs->ns_sem); @@ -108,7 +108,7 @@ static void nilfs_set_error(struct super_block *sb) void nilfs_error(struct super_block *sb, const char *function, const char *fmt, ...) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct va_format vaf; va_list args; @@ -190,7 +190,7 @@ void nilfs_destroy_inode(struct inode *inode) static int nilfs_sync_super(struct super_block *sb, int flag) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; int err; retry: @@ -265,7 +265,7 @@ void nilfs_set_log_cursor(struct nilfs_super_block *sbp, struct nilfs_super_block **nilfs_prepare_super(struct super_block *sb, int flip) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct nilfs_super_block **sbp = nilfs->ns_sbp; /* nilfs->ns_sem must be locked by the caller. */ @@ -291,7 +291,7 @@ struct nilfs_super_block **nilfs_prepare_super(struct super_block *sb, int nilfs_commit_super(struct super_block *sb, int flag) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct nilfs_super_block **sbp = nilfs->ns_sbp; time_t t; @@ -324,7 +324,7 @@ int nilfs_commit_super(struct super_block *sb, int flag) */ int nilfs_cleanup_super(struct super_block *sb) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct nilfs_super_block **sbp; int flag = NILFS_SB_COMMIT; int ret = -EIO; @@ -349,8 +349,7 @@ int nilfs_cleanup_super(struct super_block *sb) static void nilfs_put_super(struct super_block *sb) { - struct nilfs_sb_info *sbi = NILFS_SB(sb); - struct the_nilfs *nilfs = sbi->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; nilfs_detach_log_writer(sb); @@ -365,14 +364,12 @@ static void nilfs_put_super(struct super_block *sb) iput(nilfs->ns_dat); destroy_nilfs(nilfs); - sbi->s_super = NULL; sb->s_fs_info = NULL; - kfree(sbi); } static int nilfs_sync_fs(struct super_block *sb, int wait) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct nilfs_super_block **sbp; int err = 0; @@ -396,7 +393,7 @@ static int nilfs_sync_fs(struct super_block *sb, int wait) int nilfs_attach_checkpoint(struct super_block *sb, __u64 cno, int curr_mnt, struct nilfs_root **rootp) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct nilfs_root *root; struct nilfs_checkpoint *raw_cp; struct buffer_head *bh_cp; @@ -449,7 +446,7 @@ int nilfs_attach_checkpoint(struct super_block *sb, __u64 cno, int curr_mnt, static int nilfs_freeze(struct super_block *sb) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; int err; if (sb->s_flags & MS_RDONLY) @@ -464,7 +461,7 @@ static int nilfs_freeze(struct super_block *sb) static int nilfs_unfreeze(struct super_block *sb) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; if (sb->s_flags & MS_RDONLY) return 0; @@ -527,7 +524,7 @@ static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf) static int nilfs_show_options(struct seq_file *seq, struct vfsmount *vfs) { struct super_block *sb = vfs->mnt_sb; - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct nilfs_root *root = NILFS_I(vfs->mnt_root->d_inode)->i_root; if (!nilfs_test_opt(nilfs, BARRIER)) @@ -591,7 +588,7 @@ static match_table_t tokens = { static int parse_options(char *options, struct super_block *sb, int is_remount) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; char *p; substring_t args[MAX_OPT_ARGS]; @@ -660,7 +657,7 @@ static inline void nilfs_set_default_options(struct super_block *sb, struct nilfs_super_block *sbp) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; nilfs->ns_mount_opt = NILFS_MOUNT_ERRORS_RO | NILFS_MOUNT_BARRIER; @@ -668,7 +665,7 @@ nilfs_set_default_options(struct super_block *sb, static int nilfs_setup_super(struct super_block *sb, int is_mount) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct nilfs_super_block **sbp; int max_mnt_count; int mnt_count; @@ -726,7 +723,7 @@ int nilfs_store_magic_and_option(struct super_block *sb, struct nilfs_super_block *sbp, char *data) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; sb->s_magic = le16_to_cpu(sbp->s_magic); @@ -821,7 +818,7 @@ static int nilfs_get_root_dentry(struct super_block *sb, static int nilfs_attach_snapshot(struct super_block *s, __u64 cno, struct dentry **root_dentry) { - struct the_nilfs *nilfs = NILFS_SB(s)->s_nilfs; + struct the_nilfs *nilfs = s->s_fs_info; struct nilfs_root *root; int ret; @@ -873,7 +870,7 @@ static int nilfs_try_to_shrink_tree(struct dentry *root_dentry) int nilfs_checkpoint_is_mounted(struct super_block *sb, __u64 cno) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; struct nilfs_root *root; struct inode *inode; struct dentry *dentry; @@ -886,7 +883,7 @@ int nilfs_checkpoint_is_mounted(struct super_block *sb, __u64 cno) return true; /* protect recent checkpoints */ ret = false; - root = nilfs_lookup_root(NILFS_SB(sb)->s_nilfs, cno); + root = nilfs_lookup_root(nilfs, cno); if (root) { inode = nilfs_ilookup(sb, root, NILFS_ROOT_INO); if (inode) { @@ -916,25 +913,16 @@ static int nilfs_fill_super(struct super_block *sb, void *data, int silent) { struct the_nilfs *nilfs; - struct nilfs_sb_info *sbi; struct nilfs_root *fsroot; struct backing_dev_info *bdi; __u64 cno; int err; - sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); - if (!sbi) + nilfs = alloc_nilfs(sb->s_bdev); + if (!nilfs) return -ENOMEM; - sb->s_fs_info = sbi; - sbi->s_super = sb; - - nilfs = alloc_nilfs(sb->s_bdev); - if (!nilfs) { - err = -ENOMEM; - goto failed_sbi; - } - sbi->s_nilfs = nilfs; + sb->s_fs_info = nilfs; err = init_nilfs(nilfs, sb, (char *)data); if (err) @@ -993,16 +981,12 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent) failed_nilfs: destroy_nilfs(nilfs); - - failed_sbi: - sb->s_fs_info = NULL; - kfree(sbi); return err; } static int nilfs_remount(struct super_block *sb, int *flags, char *data) { - struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; + struct the_nilfs *nilfs = sb->s_fs_info; unsigned long old_sb_flags; unsigned long old_mount_opt; int err; @@ -1083,7 +1067,6 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) struct nilfs_super_data { struct block_device *bdev; - struct nilfs_sb_info *sbi; __u64 cno; int flags; }; diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index 793bd272f9e0..f4968145c2a3 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h @@ -31,7 +31,6 @@ #include #include #include -#include "sb.h" struct nilfs_sc_info; -- cgit From 86fa8af69d8e90b7b40b8dab84d168527143ae20 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 4 Mar 2011 12:59:54 +0000 Subject: xfs: clean up the xfs_alloc_compute_aligned calling convention Pass a xfs_alloc_arg structure to xfs_alloc_compute_aligned and derive the alignment and minlen paramters from it. This cleans up the existing callers, and we'll need even more information from the xfs_alloc_arg in subsequent patches. Based on a patch from Dave Chinner. Signed-off-by: Christoph Hellwig Reviewed-by: Dave Chinner Signed-off-by: Alex Elder --- fs/xfs/xfs_alloc.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) (limited to 'fs') diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c index f3227984a9bf..b5af10713dca 100644 --- a/fs/xfs/xfs_alloc.c +++ b/fs/xfs/xfs_alloc.c @@ -147,10 +147,9 @@ xfs_alloc_get_rec( */ STATIC void xfs_alloc_compute_aligned( + xfs_alloc_arg_t *args, /* allocation argument structure */ xfs_agblock_t foundbno, /* starting block in found extent */ xfs_extlen_t foundlen, /* length in found extent */ - xfs_extlen_t alignment, /* alignment for allocation */ - xfs_extlen_t minlen, /* minimum length for allocation */ xfs_agblock_t *resbno, /* result block number */ xfs_extlen_t *reslen) /* result length */ { @@ -158,8 +157,8 @@ xfs_alloc_compute_aligned( xfs_extlen_t diff; xfs_extlen_t len; - if (alignment > 1 && foundlen >= minlen) { - bno = roundup(foundbno, alignment); + if (args->alignment > 1 && foundlen >= args->minlen) { + bno = roundup(foundbno, args->alignment); diff = bno - foundbno; len = diff >= foundlen ? 0 : foundlen - diff; } else { @@ -693,8 +692,7 @@ xfs_alloc_find_best_extent( if (error) goto error0; XFS_WANT_CORRUPTED_GOTO(i == 1, error0); - xfs_alloc_compute_aligned(*sbno, *slen, args->alignment, - args->minlen, &bno, slena); + xfs_alloc_compute_aligned(args, *sbno, *slen, &bno, slena); /* * The good extent is closer than this one. @@ -866,8 +864,8 @@ xfs_alloc_ag_vextent_near( if ((error = xfs_alloc_get_rec(cnt_cur, <bno, <len, &i))) goto error0; XFS_WANT_CORRUPTED_GOTO(i == 1, error0); - xfs_alloc_compute_aligned(ltbno, ltlen, args->alignment, - args->minlen, <bnoa, <lena); + xfs_alloc_compute_aligned(args, ltbno, ltlen, + <bnoa, <lena); if (ltlena < args->minlen) continue; args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen); @@ -987,8 +985,8 @@ xfs_alloc_ag_vextent_near( if ((error = xfs_alloc_get_rec(bno_cur_lt, <bno, <len, &i))) goto error0; XFS_WANT_CORRUPTED_GOTO(i == 1, error0); - xfs_alloc_compute_aligned(ltbno, ltlen, args->alignment, - args->minlen, <bnoa, <lena); + xfs_alloc_compute_aligned(args, ltbno, ltlen, + <bnoa, <lena); if (ltlena >= args->minlen) break; if ((error = xfs_btree_decrement(bno_cur_lt, 0, &i))) @@ -1003,8 +1001,8 @@ xfs_alloc_ag_vextent_near( if ((error = xfs_alloc_get_rec(bno_cur_gt, >bno, >len, &i))) goto error0; XFS_WANT_CORRUPTED_GOTO(i == 1, error0); - xfs_alloc_compute_aligned(gtbno, gtlen, args->alignment, - args->minlen, >bnoa, >lena); + xfs_alloc_compute_aligned(args, gtbno, gtlen, + >bnoa, >lena); if (gtlena >= args->minlen) break; if ((error = xfs_btree_increment(bno_cur_gt, 0, &i))) @@ -1183,8 +1181,7 @@ xfs_alloc_ag_vextent_size( * once aligned; if not, we search left for something better. * This can't happen in the second case above. */ - xfs_alloc_compute_aligned(fbno, flen, args->alignment, args->minlen, - &rbno, &rlen); + xfs_alloc_compute_aligned(args, fbno, flen, &rbno, &rlen); rlen = XFS_EXTLEN_MIN(args->maxlen, rlen); XFS_WANT_CORRUPTED_GOTO(rlen == 0 || (rlen <= flen && rbno + rlen <= fbno + flen), error0); @@ -1209,8 +1206,8 @@ xfs_alloc_ag_vextent_size( XFS_WANT_CORRUPTED_GOTO(i == 1, error0); if (flen < bestrlen) break; - xfs_alloc_compute_aligned(fbno, flen, args->alignment, - args->minlen, &rbno, &rlen); + xfs_alloc_compute_aligned(args, fbno, flen, + &rbno, &rlen); rlen = XFS_EXTLEN_MIN(args->maxlen, rlen); XFS_WANT_CORRUPTED_GOTO(rlen == 0 || (rlen <= flen && rbno + rlen <= fbno + flen), -- cgit From ecb6928fcf969b302929f109e175981df1dba697 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 4 Mar 2011 12:59:55 +0000 Subject: xfs: factor agf counter updates into a helper Updating the AGF and transactions counters is duplicated between allocating and freeing extents. Factor the code into a common helper. Signed-off-by: Christoph Hellwig Reviewed-by: Dave Chinner Signed-off-by: Alex Elder --- fs/xfs/xfs_alloc.c | 129 ++++++++++++++++++++++++++++------------------------- 1 file changed, 68 insertions(+), 61 deletions(-) (limited to 'fs') diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c index b5af10713dca..4bc3c649aee4 100644 --- a/fs/xfs/xfs_alloc.c +++ b/fs/xfs/xfs_alloc.c @@ -463,6 +463,27 @@ xfs_alloc_read_agfl( return 0; } +STATIC int +xfs_alloc_update_counters( + struct xfs_trans *tp, + struct xfs_perag *pag, + struct xfs_buf *agbp, + long len) +{ + struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); + + pag->pagf_freeblks += len; + be32_add_cpu(&agf->agf_freeblks, len); + + xfs_trans_agblocks_delta(tp, len); + if (unlikely(be32_to_cpu(agf->agf_freeblks) > + be32_to_cpu(agf->agf_length))) + return EFSCORRUPTED; + + xfs_alloc_log_agf(tp, agbp, XFS_AGF_FREEBLKS); + return 0; +} + /* * Allocation group level functions. */ @@ -504,49 +525,44 @@ xfs_alloc_ag_vextent( ASSERT(0); /* NOTREACHED */ } - if (error) + + if (error || args->agbno == NULLAGBLOCK) return error; - /* - * If the allocation worked, need to change the agf structure - * (and log it), and the superblock. - */ - if (args->agbno != NULLAGBLOCK) { - xfs_agf_t *agf; /* allocation group freelist header */ - long slen = (long)args->len; - ASSERT(args->len >= args->minlen && args->len <= args->maxlen); - ASSERT(!(args->wasfromfl) || !args->isfl); - ASSERT(args->agbno % args->alignment == 0); - if (!(args->wasfromfl)) { - - agf = XFS_BUF_TO_AGF(args->agbp); - be32_add_cpu(&agf->agf_freeblks, -(args->len)); - xfs_trans_agblocks_delta(args->tp, - -((long)(args->len))); - args->pag->pagf_freeblks -= args->len; - ASSERT(be32_to_cpu(agf->agf_freeblks) <= - be32_to_cpu(agf->agf_length)); - xfs_alloc_log_agf(args->tp, args->agbp, - XFS_AGF_FREEBLKS); - /* - * Search the busylist for these blocks and mark the - * transaction as synchronous if blocks are found. This - * avoids the need to block due to a synchronous log - * force to ensure correct ordering as the synchronous - * transaction will guarantee that for us. - */ - if (xfs_alloc_busy_search(args->mp, args->agno, - args->agbno, args->len)) - xfs_trans_set_sync(args->tp); - } - if (!args->isfl) - xfs_trans_mod_sb(args->tp, - args->wasdel ? XFS_TRANS_SB_RES_FDBLOCKS : - XFS_TRANS_SB_FDBLOCKS, -slen); - XFS_STATS_INC(xs_allocx); - XFS_STATS_ADD(xs_allocb, args->len); + ASSERT(args->len >= args->minlen); + ASSERT(args->len <= args->maxlen); + ASSERT(!args->wasfromfl || !args->isfl); + ASSERT(args->agbno % args->alignment == 0); + + if (!args->wasfromfl) { + error = xfs_alloc_update_counters(args->tp, args->pag, + args->agbp, + -((long)(args->len))); + if (error) + return error; + + /* + * Search the busylist for these blocks and mark the + * transaction as synchronous if blocks are found. This + * avoids the need to block due to a synchronous log + * force to ensure correct ordering as the synchronous + * transaction will guarantee that for us. + */ + if (xfs_alloc_busy_search(args->mp, args->agno, + args->agbno, args->len)) + xfs_trans_set_sync(args->tp); } - return 0; + + if (!args->isfl) { + xfs_trans_mod_sb(args->tp, args->wasdel ? + XFS_TRANS_SB_RES_FDBLOCKS : + XFS_TRANS_SB_FDBLOCKS, + -((long)(args->len))); + } + + XFS_STATS_INC(xs_allocx); + XFS_STATS_ADD(xs_allocb, args->len); + return error; } /* @@ -1385,6 +1401,7 @@ xfs_free_ag_extent( xfs_mount_t *mp; /* mount point struct for filesystem */ xfs_agblock_t nbno; /* new starting block of freespace */ xfs_extlen_t nlen; /* new length of freespace */ + xfs_perag_t *pag; /* per allocation group data */ mp = tp->t_mountp; /* @@ -1583,30 +1600,20 @@ xfs_free_ag_extent( XFS_WANT_CORRUPTED_GOTO(i == 1, error0); xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); cnt_cur = NULL; + /* * Update the freespace totals in the ag and superblock. */ - { - xfs_agf_t *agf; - xfs_perag_t *pag; /* per allocation group data */ - - pag = xfs_perag_get(mp, agno); - pag->pagf_freeblks += len; - xfs_perag_put(pag); - - agf = XFS_BUF_TO_AGF(agbp); - be32_add_cpu(&agf->agf_freeblks, len); - xfs_trans_agblocks_delta(tp, len); - XFS_WANT_CORRUPTED_GOTO( - be32_to_cpu(agf->agf_freeblks) <= - be32_to_cpu(agf->agf_length), - error0); - xfs_alloc_log_agf(tp, agbp, XFS_AGF_FREEBLKS); - if (!isfl) - xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, (long)len); - XFS_STATS_INC(xs_freex); - XFS_STATS_ADD(xs_freeb, len); - } + pag = xfs_perag_get(mp, agno); + error = xfs_alloc_update_counters(tp, pag, agbp, len); + xfs_perag_put(pag); + if (error) + goto error0; + + if (!isfl) + xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, (long)len); + XFS_STATS_INC(xs_freex); + XFS_STATS_ADD(xs_freeb, len); trace_xfs_free_extent(mp, agno, bno, len, isfl, haveleft, haveright); -- cgit From facc31ddc3570a3a0d8951c94f16b898e01b464d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 9 Mar 2011 19:54:27 +0100 Subject: block: Don't implicitly trigger event check on disk_unblock_events() Currently, disk_unblock_events() implicitly kick event check if the block count reaches zero. This behavior is not described in the comment and hinders with future changes. Make the unblocker explicitly check events by calling disk_check_events() as necessary. This patch doesn't cause any behavior difference. Signed-off-by: Tejun Heo Cc: Jens Axboe Cc: Kay Sievers --- fs/block_dev.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs') diff --git a/fs/block_dev.c b/fs/block_dev.c index 889287019599..fffdf86c1757 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1446,6 +1446,7 @@ int blkdev_put(struct block_device *bdev, fmode_t mode) if (bdev_free) { if (bdev->bd_write_holder) { disk_unblock_events(bdev->bd_disk); + disk_check_events(bdev->bd_disk); bdev->bd_write_holder = false; } else disk_check_events(bdev->bd_disk); -- cgit From 6936217cc7e58573026bdba25b1bfb778e8f2267 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 9 Mar 2011 19:54:27 +0100 Subject: block: Don't check events on close unless it was blocked The block event mechanism currently always checks events when the device is being closed regardless of the open mode. The intention was to allow detection of EJECT_REQUEST when a device is closed whether disk event polling is enabled or not. This is unnecessary as, for devices of interest, events are checked from either userland or kernel and in the former case ->check_events() is performed on open of each poll attempt anyway. Furthermore, this unconditional event check on close makes the code susceptible to event loop if the block driver doesn't clear reported events correctly - an event triggers userland to open and close the device which in turn causes another event, rinse and repeat. Check events on close only if it was blocked by excl write open. Signed-off-by: Tejun Heo Cc: Jens Axboe Cc: Kay Sievers --- fs/block_dev.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/block_dev.c b/fs/block_dev.c index fffdf86c1757..7dd2c658d429 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1448,13 +1448,11 @@ int blkdev_put(struct block_device *bdev, fmode_t mode) disk_unblock_events(bdev->bd_disk); disk_check_events(bdev->bd_disk); bdev->bd_write_holder = false; - } else - disk_check_events(bdev->bd_disk); + } } mutex_unlock(&bdev->bd_mutex); - } else - disk_check_events(bdev->bd_disk); + } return __blkdev_put(bdev, mode, 0); } -- cgit From 69e02c59a7d962dced8047401b81a8d897e1702e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 9 Mar 2011 19:54:27 +0100 Subject: block: Don't check events while open is in progress Not all block drivers clear events immediately after reporting. Some do so in ->revalidate_disk() or other steps during ->open(). There is a slim chance event poll may happen between the clearing event check from check_disk_change() and the actual clearing of the events which would result in spurious events. Block event checks while block device open is in progress. There is no need to kick explicit event check afterwards as events are always checked during open. -v2: The original patch could have called disk_unblock_events() with an already released or %NULL @disk causing oops. Fixed by making sure references are put after disk_unblock_events() is called. It also makes the error path of __blkdev_get() a bit simpler. This problem was reported by Jens. Signed-off-by: Tejun Heo Cc: Jens Axboe Cc: Kay Sievers --- fs/block_dev.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'fs') diff --git a/fs/block_dev.c b/fs/block_dev.c index 7dd2c658d429..d42cad2757ae 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1087,6 +1087,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) if (!disk) goto out; + disk_block_events(disk); mutex_lock_nested(&bdev->bd_mutex, for_part); if (!bdev->bd_openers) { bdev->bd_disk = disk; @@ -1108,10 +1109,11 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) */ disk_put_part(bdev->bd_part); bdev->bd_part = NULL; - module_put(disk->fops->owner); - put_disk(disk); bdev->bd_disk = NULL; mutex_unlock(&bdev->bd_mutex); + disk_unblock_events(disk); + module_put(disk->fops->owner); + put_disk(disk); goto restart; } if (ret) @@ -1148,9 +1150,6 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) bd_set_size(bdev, (loff_t)bdev->bd_part->nr_sects << 9); } } else { - module_put(disk->fops->owner); - put_disk(disk); - disk = NULL; if (bdev->bd_contains == bdev) { if (bdev->bd_disk->fops->open) { ret = bdev->bd_disk->fops->open(bdev, mode); @@ -1160,11 +1159,15 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) if (bdev->bd_invalidated) rescan_partitions(bdev->bd_disk, bdev); } + /* only one opener holds refs to the module and disk */ + module_put(disk->fops->owner); + put_disk(disk); } bdev->bd_openers++; if (for_part) bdev->bd_part_count++; mutex_unlock(&bdev->bd_mutex); + disk_unblock_events(disk); return 0; out_clear: @@ -1177,9 +1180,9 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) bdev->bd_contains = NULL; out_unlock_bdev: mutex_unlock(&bdev->bd_mutex); + disk_unblock_events(disk); out: - if (disk) - module_put(disk->fops->owner); + module_put(disk->fops->owner); put_disk(disk); bdput(bdev); -- cgit From 7eaceaccab5f40bbfda044629a6298616aeaed50 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 10 Mar 2011 08:52:07 +0100 Subject: block: remove per-queue plugging Code has been converted over to the new explicit on-stack plugging, and delay users have been converted to use the new API for that. So lets kill off the old plugging along with aops->sync_page(). Signed-off-by: Jens Axboe --- fs/adfs/inode.c | 1 - fs/affs/file.c | 2 - fs/aio.c | 4 +- fs/befs/linuxvfs.c | 1 - fs/bfs/file.c | 1 - fs/block_dev.c | 1 - fs/btrfs/disk-io.c | 79 -------------------------------------- fs/btrfs/inode.c | 1 - fs/btrfs/volumes.c | 91 ++++++-------------------------------------- fs/buffer.c | 31 ++------------- fs/cifs/file.c | 30 --------------- fs/direct-io.c | 5 +-- fs/efs/inode.c | 1 - fs/exofs/inode.c | 1 - fs/ext2/inode.c | 2 - fs/ext3/inode.c | 3 -- fs/ext4/inode.c | 4 -- fs/fat/inode.c | 1 - fs/freevxfs/vxfs_subr.c | 1 - fs/fuse/inode.c | 1 - fs/gfs2/aops.c | 3 -- fs/gfs2/meta_io.c | 1 - fs/hfs/inode.c | 2 - fs/hfsplus/inode.c | 2 - fs/hpfs/file.c | 1 - fs/isofs/inode.c | 1 - fs/jfs/inode.c | 1 - fs/jfs/jfs_metapage.c | 1 - fs/logfs/dev_bdev.c | 2 - fs/minix/inode.c | 1 - fs/nilfs2/btnode.c | 6 +-- fs/nilfs2/gcinode.c | 1 - fs/nilfs2/inode.c | 1 - fs/nilfs2/mdt.c | 9 +---- fs/nilfs2/page.c | 5 +-- fs/nilfs2/page.h | 3 +- fs/ntfs/aops.c | 4 -- fs/ntfs/compress.c | 3 +- fs/ocfs2/aops.c | 1 - fs/ocfs2/cluster/heartbeat.c | 4 -- fs/omfs/file.c | 1 - fs/qnx4/inode.c | 1 - fs/reiserfs/inode.c | 1 - fs/sysv/itree.c | 1 - fs/ubifs/super.c | 1 - fs/udf/file.c | 1 - fs/udf/inode.c | 1 - fs/ufs/inode.c | 1 - fs/ufs/truncate.c | 2 +- fs/xfs/linux-2.6/xfs_aops.c | 1 - fs/xfs/linux-2.6/xfs_buf.c | 13 +++---- 51 files changed, 32 insertions(+), 305 deletions(-) (limited to 'fs') diff --git a/fs/adfs/inode.c b/fs/adfs/inode.c index 65794b8fe79e..1cc84b276131 100644 --- a/fs/adfs/inode.c +++ b/fs/adfs/inode.c @@ -73,7 +73,6 @@ static sector_t _adfs_bmap(struct address_space *mapping, sector_t block) static const struct address_space_operations adfs_aops = { .readpage = adfs_readpage, .writepage = adfs_writepage, - .sync_page = block_sync_page, .write_begin = adfs_write_begin, .write_end = generic_write_end, .bmap = _adfs_bmap diff --git a/fs/affs/file.c b/fs/affs/file.c index 0a90dcd46de2..acf321b70fcd 100644 --- a/fs/affs/file.c +++ b/fs/affs/file.c @@ -429,7 +429,6 @@ static sector_t _affs_bmap(struct address_space *mapping, sector_t block) const struct address_space_operations affs_aops = { .readpage = affs_readpage, .writepage = affs_writepage, - .sync_page = block_sync_page, .write_begin = affs_write_begin, .write_end = generic_write_end, .bmap = _affs_bmap @@ -786,7 +785,6 @@ out: const struct address_space_operations affs_aops_ofs = { .readpage = affs_readpage_ofs, //.writepage = affs_writepage_ofs, - //.sync_page = affs_sync_page_ofs, .write_begin = affs_write_begin_ofs, .write_end = affs_write_end_ofs }; diff --git a/fs/aio.c b/fs/aio.c index fc557a3be0a9..c5ea494ea9e2 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -1550,9 +1550,11 @@ static void aio_batch_free(struct hlist_head *batch_hash) struct hlist_node *pos, *n; int i; + /* + * TODO: kill this + */ for (i = 0; i < AIO_BATCH_HASH_SIZE; i++) { hlist_for_each_entry_safe(abe, pos, n, &batch_hash[i], list) { - blk_run_address_space(abe->mapping); iput(abe->mapping->host); hlist_del(&abe->list); mempool_free(abe, abe_pool); diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index b1d0c794747b..06457ed8f3e7 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c @@ -75,7 +75,6 @@ static const struct inode_operations befs_dir_inode_operations = { static const struct address_space_operations befs_aops = { .readpage = befs_readpage, - .sync_page = block_sync_page, .bmap = befs_bmap, }; diff --git a/fs/bfs/file.c b/fs/bfs/file.c index eb67edd0f8ea..f20e8a71062f 100644 --- a/fs/bfs/file.c +++ b/fs/bfs/file.c @@ -186,7 +186,6 @@ static sector_t bfs_bmap(struct address_space *mapping, sector_t block) const struct address_space_operations bfs_aops = { .readpage = bfs_readpage, .writepage = bfs_writepage, - .sync_page = block_sync_page, .write_begin = bfs_write_begin, .write_end = generic_write_end, .bmap = bfs_bmap, diff --git a/fs/block_dev.c b/fs/block_dev.c index 4fb8a3431531..fffc2c672396 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1520,7 +1520,6 @@ static int blkdev_releasepage(struct page *page, gfp_t wait) static const struct address_space_operations def_blk_aops = { .readpage = blkdev_readpage, .writepage = blkdev_writepage, - .sync_page = block_sync_page, .write_begin = blkdev_write_begin, .write_end = blkdev_write_end, .writepages = generic_writepages, diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index e1aa8d607bc7..ada1f6bd0a57 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -847,7 +847,6 @@ static const struct address_space_operations btree_aops = { .writepages = btree_writepages, .releasepage = btree_releasepage, .invalidatepage = btree_invalidatepage, - .sync_page = block_sync_page, #ifdef CONFIG_MIGRATION .migratepage = btree_migratepage, #endif @@ -1330,82 +1329,6 @@ static int btrfs_congested_fn(void *congested_data, int bdi_bits) return ret; } -/* - * this unplugs every device on the box, and it is only used when page - * is null - */ -static void __unplug_io_fn(struct backing_dev_info *bdi, struct page *page) -{ - struct btrfs_device *device; - struct btrfs_fs_info *info; - - info = (struct btrfs_fs_info *)bdi->unplug_io_data; - list_for_each_entry(device, &info->fs_devices->devices, dev_list) { - if (!device->bdev) - continue; - - bdi = blk_get_backing_dev_info(device->bdev); - if (bdi->unplug_io_fn) - bdi->unplug_io_fn(bdi, page); - } -} - -static void btrfs_unplug_io_fn(struct backing_dev_info *bdi, struct page *page) -{ - struct inode *inode; - struct extent_map_tree *em_tree; - struct extent_map *em; - struct address_space *mapping; - u64 offset; - - /* the generic O_DIRECT read code does this */ - if (1 || !page) { - __unplug_io_fn(bdi, page); - return; - } - - /* - * page->mapping may change at any time. Get a consistent copy - * and use that for everything below - */ - smp_mb(); - mapping = page->mapping; - if (!mapping) - return; - - inode = mapping->host; - - /* - * don't do the expensive searching for a small number of - * devices - */ - if (BTRFS_I(inode)->root->fs_info->fs_devices->open_devices <= 2) { - __unplug_io_fn(bdi, page); - return; - } - - offset = page_offset(page); - - em_tree = &BTRFS_I(inode)->extent_tree; - read_lock(&em_tree->lock); - em = lookup_extent_mapping(em_tree, offset, PAGE_CACHE_SIZE); - read_unlock(&em_tree->lock); - if (!em) { - __unplug_io_fn(bdi, page); - return; - } - - if (em->block_start >= EXTENT_MAP_LAST_BYTE) { - free_extent_map(em); - __unplug_io_fn(bdi, page); - return; - } - offset = offset - em->start; - btrfs_unplug_page(&BTRFS_I(inode)->root->fs_info->mapping_tree, - em->block_start + offset, page); - free_extent_map(em); -} - /* * If this fails, caller must call bdi_destroy() to get rid of the * bdi again. @@ -1420,8 +1343,6 @@ static int setup_bdi(struct btrfs_fs_info *info, struct backing_dev_info *bdi) return err; bdi->ra_pages = default_backing_dev_info.ra_pages; - bdi->unplug_io_fn = btrfs_unplug_io_fn; - bdi->unplug_io_data = info; bdi->congested_fn = btrfs_congested_fn; bdi->congested_data = info; return 0; diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index fb9bd7832b6d..462e08e724b0 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -7218,7 +7218,6 @@ static const struct address_space_operations btrfs_aops = { .writepage = btrfs_writepage, .writepages = btrfs_writepages, .readpages = btrfs_readpages, - .sync_page = block_sync_page, .direct_IO = btrfs_direct_IO, .invalidatepage = btrfs_invalidatepage, .releasepage = btrfs_releasepage, diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index af7dbca15276..6e0e82a1b188 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -162,7 +162,6 @@ static noinline int run_scheduled_bios(struct btrfs_device *device) struct bio *cur; int again = 0; unsigned long num_run; - unsigned long num_sync_run; unsigned long batch_run = 0; unsigned long limit; unsigned long last_waited = 0; @@ -173,11 +172,6 @@ static noinline int run_scheduled_bios(struct btrfs_device *device) limit = btrfs_async_submit_limit(fs_info); limit = limit * 2 / 3; - /* we want to make sure that every time we switch from the sync - * list to the normal list, we unplug - */ - num_sync_run = 0; - loop: spin_lock(&device->io_lock); @@ -223,15 +217,6 @@ loop_lock: spin_unlock(&device->io_lock); - /* - * if we're doing the regular priority list, make sure we unplug - * for any high prio bios we've sent down - */ - if (pending_bios == &device->pending_bios && num_sync_run > 0) { - num_sync_run = 0; - blk_run_backing_dev(bdi, NULL); - } - while (pending) { rmb(); @@ -259,19 +244,11 @@ loop_lock: BUG_ON(atomic_read(&cur->bi_cnt) == 0); - if (cur->bi_rw & REQ_SYNC) - num_sync_run++; - submit_bio(cur->bi_rw, cur); num_run++; batch_run++; - if (need_resched()) { - if (num_sync_run) { - blk_run_backing_dev(bdi, NULL); - num_sync_run = 0; - } + if (need_resched()) cond_resched(); - } /* * we made progress, there is more work to do and the bdi @@ -304,13 +281,8 @@ loop_lock: * against it before looping */ last_waited = ioc->last_waited; - if (need_resched()) { - if (num_sync_run) { - blk_run_backing_dev(bdi, NULL); - num_sync_run = 0; - } + if (need_resched()) cond_resched(); - } continue; } spin_lock(&device->io_lock); @@ -323,22 +295,6 @@ loop_lock: } } - if (num_sync_run) { - num_sync_run = 0; - blk_run_backing_dev(bdi, NULL); - } - /* - * IO has already been through a long path to get here. Checksumming, - * async helper threads, perhaps compression. We've done a pretty - * good job of collecting a batch of IO and should just unplug - * the device right away. - * - * This will help anyone who is waiting on the IO, they might have - * already unplugged, but managed to do so before the bio they - * cared about found its way down here. - */ - blk_run_backing_dev(bdi, NULL); - cond_resched(); if (again) goto loop; @@ -2948,7 +2904,7 @@ static int find_live_mirror(struct map_lookup *map, int first, int num, static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, u64 logical, u64 *length, struct btrfs_multi_bio **multi_ret, - int mirror_num, struct page *unplug_page) + int mirror_num) { struct extent_map *em; struct map_lookup *map; @@ -2980,11 +2936,6 @@ again: em = lookup_extent_mapping(em_tree, logical, *length); read_unlock(&em_tree->lock); - if (!em && unplug_page) { - kfree(multi); - return 0; - } - if (!em) { printk(KERN_CRIT "unable to find logical %llu len %llu\n", (unsigned long long)logical, @@ -3040,13 +2991,13 @@ again: *length = em->len - offset; } - if (!multi_ret && !unplug_page) + if (!multi_ret) goto out; num_stripes = 1; stripe_index = 0; if (map->type & BTRFS_BLOCK_GROUP_RAID1) { - if (unplug_page || (rw & REQ_WRITE)) + if (rw & REQ_WRITE) num_stripes = map->num_stripes; else if (mirror_num) stripe_index = mirror_num - 1; @@ -3068,7 +3019,7 @@ again: stripe_index = do_div(stripe_nr, factor); stripe_index *= map->sub_stripes; - if (unplug_page || (rw & REQ_WRITE)) + if (rw & REQ_WRITE) num_stripes = map->sub_stripes; else if (mirror_num) stripe_index += mirror_num - 1; @@ -3088,22 +3039,10 @@ again: BUG_ON(stripe_index >= map->num_stripes); for (i = 0; i < num_stripes; i++) { - if (unplug_page) { - struct btrfs_device *device; - struct backing_dev_info *bdi; - - device = map->stripes[stripe_index].dev; - if (device->bdev) { - bdi = blk_get_backing_dev_info(device->bdev); - if (bdi->unplug_io_fn) - bdi->unplug_io_fn(bdi, unplug_page); - } - } else { - multi->stripes[i].physical = - map->stripes[stripe_index].physical + - stripe_offset + stripe_nr * map->stripe_len; - multi->stripes[i].dev = map->stripes[stripe_index].dev; - } + multi->stripes[i].physical = + map->stripes[stripe_index].physical + + stripe_offset + stripe_nr * map->stripe_len; + multi->stripes[i].dev = map->stripes[stripe_index].dev; stripe_index++; } if (multi_ret) { @@ -3121,7 +3060,7 @@ int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, struct btrfs_multi_bio **multi_ret, int mirror_num) { return __btrfs_map_block(map_tree, rw, logical, length, multi_ret, - mirror_num, NULL); + mirror_num); } int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree, @@ -3189,14 +3128,6 @@ int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree, return 0; } -int btrfs_unplug_page(struct btrfs_mapping_tree *map_tree, - u64 logical, struct page *page) -{ - u64 length = PAGE_CACHE_SIZE; - return __btrfs_map_block(map_tree, READ, logical, &length, - NULL, 0, page); -} - static void end_bio_multi_stripe(struct bio *bio, int err) { struct btrfs_multi_bio *multi = bio->bi_private; diff --git a/fs/buffer.c b/fs/buffer.c index 2219a76e2caf..f903f2e5b4fe 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -54,23 +54,15 @@ init_buffer(struct buffer_head *bh, bh_end_io_t *handler, void *private) } EXPORT_SYMBOL(init_buffer); -static int sync_buffer(void *word) +static int sleep_on_buffer(void *word) { - struct block_device *bd; - struct buffer_head *bh - = container_of(word, struct buffer_head, b_state); - - smp_mb(); - bd = bh->b_bdev; - if (bd) - blk_run_address_space(bd->bd_inode->i_mapping); io_schedule(); return 0; } void __lock_buffer(struct buffer_head *bh) { - wait_on_bit_lock(&bh->b_state, BH_Lock, sync_buffer, + wait_on_bit_lock(&bh->b_state, BH_Lock, sleep_on_buffer, TASK_UNINTERRUPTIBLE); } EXPORT_SYMBOL(__lock_buffer); @@ -90,7 +82,7 @@ EXPORT_SYMBOL(unlock_buffer); */ void __wait_on_buffer(struct buffer_head * bh) { - wait_on_bit(&bh->b_state, BH_Lock, sync_buffer, TASK_UNINTERRUPTIBLE); + wait_on_bit(&bh->b_state, BH_Lock, sleep_on_buffer, TASK_UNINTERRUPTIBLE); } EXPORT_SYMBOL(__wait_on_buffer); @@ -749,7 +741,7 @@ static int fsync_buffers_list(spinlock_t *lock, struct list_head *list) { struct buffer_head *bh; struct list_head tmp; - struct address_space *mapping, *prev_mapping = NULL; + struct address_space *mapping; int err = 0, err2; INIT_LIST_HEAD(&tmp); @@ -783,10 +775,6 @@ static int fsync_buffers_list(spinlock_t *lock, struct list_head *list) * wait_on_buffer() will do that for us * through sync_buffer(). */ - if (prev_mapping && prev_mapping != mapping) - blk_run_address_space(prev_mapping); - prev_mapping = mapping; - brelse(bh); spin_lock(lock); } @@ -3138,17 +3126,6 @@ out: } EXPORT_SYMBOL(try_to_free_buffers); -void block_sync_page(struct page *page) -{ - struct address_space *mapping; - - smp_mb(); - mapping = page_mapping(page); - if (mapping) - blk_run_backing_dev(mapping->backing_dev_info, page); -} -EXPORT_SYMBOL(block_sync_page); - /* * There are no bdflush tunables left. But distributions are * still running obsolete flush daemons, so we terminate them here. diff --git a/fs/cifs/file.c b/fs/cifs/file.c index e964b1cd5dd0..c27d236738fc 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -1569,34 +1569,6 @@ int cifs_fsync(struct file *file, int datasync) return rc; } -/* static void cifs_sync_page(struct page *page) -{ - struct address_space *mapping; - struct inode *inode; - unsigned long index = page->index; - unsigned int rpages = 0; - int rc = 0; - - cFYI(1, "sync page %p", page); - mapping = page->mapping; - if (!mapping) - return 0; - inode = mapping->host; - if (!inode) - return; */ - -/* fill in rpages then - result = cifs_pagein_inode(inode, index, rpages); */ /* BB finish */ - -/* cFYI(1, "rpages is %d for sync page of Index %ld", rpages, index); - -#if 0 - if (rc < 0) - return rc; - return 0; -#endif -} */ - /* * As file closes, flush all cached write data for this inode checking * for write behind errors. @@ -2510,7 +2482,6 @@ const struct address_space_operations cifs_addr_ops = { .set_page_dirty = __set_page_dirty_nobuffers, .releasepage = cifs_release_page, .invalidatepage = cifs_invalidate_page, - /* .sync_page = cifs_sync_page, */ /* .direct_IO = */ }; @@ -2528,6 +2499,5 @@ const struct address_space_operations cifs_addr_ops_smallbuf = { .set_page_dirty = __set_page_dirty_nobuffers, .releasepage = cifs_release_page, .invalidatepage = cifs_invalidate_page, - /* .sync_page = cifs_sync_page, */ /* .direct_IO = */ }; diff --git a/fs/direct-io.c b/fs/direct-io.c index b044705eedd4..df709b3b860a 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -1110,11 +1110,8 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode, ((rw & READ) || (dio->result == dio->size))) ret = -EIOCBQUEUED; - if (ret != -EIOCBQUEUED) { - /* All IO is now issued, send it on its way */ - blk_run_address_space(inode->i_mapping); + if (ret != -EIOCBQUEUED) dio_await_completion(dio); - } /* * Sync will always be dropping the final ref and completing the diff --git a/fs/efs/inode.c b/fs/efs/inode.c index a8e7797b9477..9c13412e6c99 100644 --- a/fs/efs/inode.c +++ b/fs/efs/inode.c @@ -23,7 +23,6 @@ static sector_t _efs_bmap(struct address_space *mapping, sector_t block) } static const struct address_space_operations efs_aops = { .readpage = efs_readpage, - .sync_page = block_sync_page, .bmap = _efs_bmap }; diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index a7555238c41a..82b94c8f5d22 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c @@ -795,7 +795,6 @@ const struct address_space_operations exofs_aops = { .direct_IO = NULL, /* TODO: Should be trivial to do */ /* With these NULL has special meaning or default is not exported */ - .sync_page = NULL, .get_xip_mem = NULL, .migratepage = NULL, .launder_page = NULL, diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 40ad210a5049..c47f706878b5 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -860,7 +860,6 @@ const struct address_space_operations ext2_aops = { .readpage = ext2_readpage, .readpages = ext2_readpages, .writepage = ext2_writepage, - .sync_page = block_sync_page, .write_begin = ext2_write_begin, .write_end = ext2_write_end, .bmap = ext2_bmap, @@ -880,7 +879,6 @@ const struct address_space_operations ext2_nobh_aops = { .readpage = ext2_readpage, .readpages = ext2_readpages, .writepage = ext2_nobh_writepage, - .sync_page = block_sync_page, .write_begin = ext2_nobh_write_begin, .write_end = nobh_write_end, .bmap = ext2_bmap, diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index ae94f6d949f5..fe2541d250e4 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -1894,7 +1894,6 @@ static const struct address_space_operations ext3_ordered_aops = { .readpage = ext3_readpage, .readpages = ext3_readpages, .writepage = ext3_ordered_writepage, - .sync_page = block_sync_page, .write_begin = ext3_write_begin, .write_end = ext3_ordered_write_end, .bmap = ext3_bmap, @@ -1910,7 +1909,6 @@ static const struct address_space_operations ext3_writeback_aops = { .readpage = ext3_readpage, .readpages = ext3_readpages, .writepage = ext3_writeback_writepage, - .sync_page = block_sync_page, .write_begin = ext3_write_begin, .write_end = ext3_writeback_write_end, .bmap = ext3_bmap, @@ -1926,7 +1924,6 @@ static const struct address_space_operations ext3_journalled_aops = { .readpage = ext3_readpage, .readpages = ext3_readpages, .writepage = ext3_journalled_writepage, - .sync_page = block_sync_page, .write_begin = ext3_write_begin, .write_end = ext3_journalled_write_end, .set_page_dirty = ext3_journalled_set_page_dirty, diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 9f7f9e49914f..9297ad46c465 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -3903,7 +3903,6 @@ static const struct address_space_operations ext4_ordered_aops = { .readpage = ext4_readpage, .readpages = ext4_readpages, .writepage = ext4_writepage, - .sync_page = block_sync_page, .write_begin = ext4_write_begin, .write_end = ext4_ordered_write_end, .bmap = ext4_bmap, @@ -3919,7 +3918,6 @@ static const struct address_space_operations ext4_writeback_aops = { .readpage = ext4_readpage, .readpages = ext4_readpages, .writepage = ext4_writepage, - .sync_page = block_sync_page, .write_begin = ext4_write_begin, .write_end = ext4_writeback_write_end, .bmap = ext4_bmap, @@ -3935,7 +3933,6 @@ static const struct address_space_operations ext4_journalled_aops = { .readpage = ext4_readpage, .readpages = ext4_readpages, .writepage = ext4_writepage, - .sync_page = block_sync_page, .write_begin = ext4_write_begin, .write_end = ext4_journalled_write_end, .set_page_dirty = ext4_journalled_set_page_dirty, @@ -3951,7 +3948,6 @@ static const struct address_space_operations ext4_da_aops = { .readpages = ext4_readpages, .writepage = ext4_writepage, .writepages = ext4_da_writepages, - .sync_page = block_sync_page, .write_begin = ext4_da_write_begin, .write_end = ext4_da_write_end, .bmap = ext4_bmap, diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 86753fe10bd1..f4ff09fb79b1 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -236,7 +236,6 @@ static const struct address_space_operations fat_aops = { .readpages = fat_readpages, .writepage = fat_writepage, .writepages = fat_writepages, - .sync_page = block_sync_page, .write_begin = fat_write_begin, .write_end = fat_write_end, .direct_IO = fat_direct_IO, diff --git a/fs/freevxfs/vxfs_subr.c b/fs/freevxfs/vxfs_subr.c index 1429f3ae1e86..5d318c44f855 100644 --- a/fs/freevxfs/vxfs_subr.c +++ b/fs/freevxfs/vxfs_subr.c @@ -44,7 +44,6 @@ static sector_t vxfs_bmap(struct address_space *, sector_t); const struct address_space_operations vxfs_aops = { .readpage = vxfs_readpage, .bmap = vxfs_bmap, - .sync_page = block_sync_page, }; inline void diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 9e3f68cc1bd1..09e8d51eeb64 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -868,7 +868,6 @@ static int fuse_bdi_init(struct fuse_conn *fc, struct super_block *sb) fc->bdi.name = "fuse"; fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE; - fc->bdi.unplug_io_fn = default_unplug_io_fn; /* fuse does it's own writeback accounting */ fc->bdi.capabilities = BDI_CAP_NO_ACCT_WB; diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c index 4f36f8832b9b..2f87ad27efd0 100644 --- a/fs/gfs2/aops.c +++ b/fs/gfs2/aops.c @@ -1116,7 +1116,6 @@ static const struct address_space_operations gfs2_writeback_aops = { .writepages = gfs2_writeback_writepages, .readpage = gfs2_readpage, .readpages = gfs2_readpages, - .sync_page = block_sync_page, .write_begin = gfs2_write_begin, .write_end = gfs2_write_end, .bmap = gfs2_bmap, @@ -1132,7 +1131,6 @@ static const struct address_space_operations gfs2_ordered_aops = { .writepage = gfs2_ordered_writepage, .readpage = gfs2_readpage, .readpages = gfs2_readpages, - .sync_page = block_sync_page, .write_begin = gfs2_write_begin, .write_end = gfs2_write_end, .set_page_dirty = gfs2_set_page_dirty, @@ -1150,7 +1148,6 @@ static const struct address_space_operations gfs2_jdata_aops = { .writepages = gfs2_jdata_writepages, .readpage = gfs2_readpage, .readpages = gfs2_readpages, - .sync_page = block_sync_page, .write_begin = gfs2_write_begin, .write_end = gfs2_write_end, .set_page_dirty = gfs2_set_page_dirty, diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index 939739c7b3f9..a566331db4e1 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c @@ -94,7 +94,6 @@ static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wb const struct address_space_operations gfs2_meta_aops = { .writepage = gfs2_aspace_writepage, .releasepage = gfs2_releasepage, - .sync_page = block_sync_page, }; /** diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c index dffb4e996643..fff16c968e67 100644 --- a/fs/hfs/inode.c +++ b/fs/hfs/inode.c @@ -150,7 +150,6 @@ static int hfs_writepages(struct address_space *mapping, const struct address_space_operations hfs_btree_aops = { .readpage = hfs_readpage, .writepage = hfs_writepage, - .sync_page = block_sync_page, .write_begin = hfs_write_begin, .write_end = generic_write_end, .bmap = hfs_bmap, @@ -160,7 +159,6 @@ const struct address_space_operations hfs_btree_aops = { const struct address_space_operations hfs_aops = { .readpage = hfs_readpage, .writepage = hfs_writepage, - .sync_page = block_sync_page, .write_begin = hfs_write_begin, .write_end = generic_write_end, .bmap = hfs_bmap, diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index a8df651747f0..b248a6cfcad9 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c @@ -146,7 +146,6 @@ static int hfsplus_writepages(struct address_space *mapping, const struct address_space_operations hfsplus_btree_aops = { .readpage = hfsplus_readpage, .writepage = hfsplus_writepage, - .sync_page = block_sync_page, .write_begin = hfsplus_write_begin, .write_end = generic_write_end, .bmap = hfsplus_bmap, @@ -156,7 +155,6 @@ const struct address_space_operations hfsplus_btree_aops = { const struct address_space_operations hfsplus_aops = { .readpage = hfsplus_readpage, .writepage = hfsplus_writepage, - .sync_page = block_sync_page, .write_begin = hfsplus_write_begin, .write_end = generic_write_end, .bmap = hfsplus_bmap, diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c index c0340887c7ea..9e84257b3ad5 100644 --- a/fs/hpfs/file.c +++ b/fs/hpfs/file.c @@ -120,7 +120,6 @@ static sector_t _hpfs_bmap(struct address_space *mapping, sector_t block) const struct address_space_operations hpfs_aops = { .readpage = hpfs_readpage, .writepage = hpfs_writepage, - .sync_page = block_sync_page, .write_begin = hpfs_write_begin, .write_end = generic_write_end, .bmap = _hpfs_bmap diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index a0f3833c0dbf..3db5ba4568fc 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -1158,7 +1158,6 @@ static sector_t _isofs_bmap(struct address_space *mapping, sector_t block) static const struct address_space_operations isofs_aops = { .readpage = isofs_readpage, - .sync_page = block_sync_page, .bmap = _isofs_bmap }; diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c index 9978803ceedc..eddbb373209e 100644 --- a/fs/jfs/inode.c +++ b/fs/jfs/inode.c @@ -352,7 +352,6 @@ const struct address_space_operations jfs_aops = { .readpages = jfs_readpages, .writepage = jfs_writepage, .writepages = jfs_writepages, - .sync_page = block_sync_page, .write_begin = jfs_write_begin, .write_end = nobh_write_end, .bmap = jfs_bmap, diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c index 48b44bd8267b..6740d34cd82b 100644 --- a/fs/jfs/jfs_metapage.c +++ b/fs/jfs/jfs_metapage.c @@ -583,7 +583,6 @@ static void metapage_invalidatepage(struct page *page, unsigned long offset) const struct address_space_operations jfs_metapage_aops = { .readpage = metapage_readpage, .writepage = metapage_writepage, - .sync_page = block_sync_page, .releasepage = metapage_releasepage, .invalidatepage = metapage_invalidatepage, .set_page_dirty = __set_page_dirty_nobuffers, diff --git a/fs/logfs/dev_bdev.c b/fs/logfs/dev_bdev.c index 723bc5bca09a..1adc8d455f0e 100644 --- a/fs/logfs/dev_bdev.c +++ b/fs/logfs/dev_bdev.c @@ -39,7 +39,6 @@ static int sync_request(struct page *page, struct block_device *bdev, int rw) bio.bi_end_io = request_complete; submit_bio(rw, &bio); - generic_unplug_device(bdev_get_queue(bdev)); wait_for_completion(&complete); return test_bit(BIO_UPTODATE, &bio.bi_flags) ? 0 : -EIO; } @@ -168,7 +167,6 @@ static void bdev_writeseg(struct super_block *sb, u64 ofs, size_t len) } len = PAGE_ALIGN(len); __bdev_writeseg(sb, ofs, ofs >> PAGE_SHIFT, len >> PAGE_SHIFT); - generic_unplug_device(bdev_get_queue(logfs_super(sb)->s_bdev)); } diff --git a/fs/minix/inode.c b/fs/minix/inode.c index ae0b83f476a6..adcdc0a4e182 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c @@ -399,7 +399,6 @@ static sector_t minix_bmap(struct address_space *mapping, sector_t block) static const struct address_space_operations minix_aops = { .readpage = minix_readpage, .writepage = minix_writepage, - .sync_page = block_sync_page, .write_begin = minix_write_begin, .write_end = generic_write_end, .bmap = minix_bmap diff --git a/fs/nilfs2/btnode.c b/fs/nilfs2/btnode.c index 388e9e8f5286..f4f1c08807ed 100644 --- a/fs/nilfs2/btnode.c +++ b/fs/nilfs2/btnode.c @@ -40,14 +40,10 @@ void nilfs_btnode_cache_init_once(struct address_space *btnc) nilfs_mapping_init_once(btnc); } -static const struct address_space_operations def_btnode_aops = { - .sync_page = block_sync_page, -}; - void nilfs_btnode_cache_init(struct address_space *btnc, struct backing_dev_info *bdi) { - nilfs_mapping_init(btnc, bdi, &def_btnode_aops); + nilfs_mapping_init(btnc, bdi); } void nilfs_btnode_cache_clear(struct address_space *btnc) diff --git a/fs/nilfs2/gcinode.c b/fs/nilfs2/gcinode.c index caf9a6a3fb54..1c2a3e23f8b2 100644 --- a/fs/nilfs2/gcinode.c +++ b/fs/nilfs2/gcinode.c @@ -49,7 +49,6 @@ #include "ifile.h" static const struct address_space_operations def_gcinode_aops = { - .sync_page = block_sync_page, }; /* diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 2fd440d8d6b8..c89d5d1ea7c7 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c @@ -262,7 +262,6 @@ nilfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, const struct address_space_operations nilfs_aops = { .writepage = nilfs_writepage, .readpage = nilfs_readpage, - .sync_page = block_sync_page, .writepages = nilfs_writepages, .set_page_dirty = nilfs_set_page_dirty, .readpages = nilfs_readpages, diff --git a/fs/nilfs2/mdt.c b/fs/nilfs2/mdt.c index 6a0e2a189f60..3fdb61d79c9a 100644 --- a/fs/nilfs2/mdt.c +++ b/fs/nilfs2/mdt.c @@ -399,7 +399,6 @@ nilfs_mdt_write_page(struct page *page, struct writeback_control *wbc) static const struct address_space_operations def_mdt_aops = { .writepage = nilfs_mdt_write_page, - .sync_page = block_sync_page, }; static const struct inode_operations def_mdt_iops; @@ -438,10 +437,6 @@ void nilfs_mdt_set_entry_size(struct inode *inode, unsigned entry_size, mi->mi_first_entry_offset = DIV_ROUND_UP(header_size, entry_size); } -static const struct address_space_operations shadow_map_aops = { - .sync_page = block_sync_page, -}; - /** * nilfs_mdt_setup_shadow_map - setup shadow map and bind it to metadata file * @inode: inode of the metadata file @@ -455,9 +450,9 @@ int nilfs_mdt_setup_shadow_map(struct inode *inode, INIT_LIST_HEAD(&shadow->frozen_buffers); nilfs_mapping_init_once(&shadow->frozen_data); - nilfs_mapping_init(&shadow->frozen_data, bdi, &shadow_map_aops); + nilfs_mapping_init(&shadow->frozen_data, bdi); nilfs_mapping_init_once(&shadow->frozen_btnodes); - nilfs_mapping_init(&shadow->frozen_btnodes, bdi, &shadow_map_aops); + nilfs_mapping_init(&shadow->frozen_btnodes, bdi); mi->mi_shadow = shadow; return 0; } diff --git a/fs/nilfs2/page.c b/fs/nilfs2/page.c index 0c432416cfef..3da37cc5de34 100644 --- a/fs/nilfs2/page.c +++ b/fs/nilfs2/page.c @@ -506,15 +506,14 @@ void nilfs_mapping_init_once(struct address_space *mapping) } void nilfs_mapping_init(struct address_space *mapping, - struct backing_dev_info *bdi, - const struct address_space_operations *aops) + struct backing_dev_info *bdi) { mapping->host = NULL; mapping->flags = 0; mapping_set_gfp_mask(mapping, GFP_NOFS); mapping->assoc_mapping = NULL; mapping->backing_dev_info = bdi; - mapping->a_ops = aops; + mapping->a_ops = NULL; } /* diff --git a/fs/nilfs2/page.h b/fs/nilfs2/page.h index 622df27cd891..ba4d6fd40b04 100644 --- a/fs/nilfs2/page.h +++ b/fs/nilfs2/page.h @@ -63,8 +63,7 @@ void nilfs_copy_back_pages(struct address_space *, struct address_space *); void nilfs_clear_dirty_pages(struct address_space *); void nilfs_mapping_init_once(struct address_space *mapping); void nilfs_mapping_init(struct address_space *mapping, - struct backing_dev_info *bdi, - const struct address_space_operations *aops); + struct backing_dev_info *bdi); unsigned nilfs_page_count_clean_buffers(struct page *, unsigned, unsigned); unsigned long nilfs_find_uncommitted_extent(struct inode *inode, sector_t start_blk, diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c index c3c2c7ac9020..0b1e885b8cf8 100644 --- a/fs/ntfs/aops.c +++ b/fs/ntfs/aops.c @@ -1543,8 +1543,6 @@ err_out: */ const struct address_space_operations ntfs_aops = { .readpage = ntfs_readpage, /* Fill page with data. */ - .sync_page = block_sync_page, /* Currently, just unplugs the - disk request queue. */ #ifdef NTFS_RW .writepage = ntfs_writepage, /* Write dirty page to disk. */ #endif /* NTFS_RW */ @@ -1560,8 +1558,6 @@ const struct address_space_operations ntfs_aops = { */ const struct address_space_operations ntfs_mst_aops = { .readpage = ntfs_readpage, /* Fill page with data. */ - .sync_page = block_sync_page, /* Currently, just unplugs the - disk request queue. */ #ifdef NTFS_RW .writepage = ntfs_writepage, /* Write dirty page to disk. */ .set_page_dirty = __set_page_dirty_nobuffers, /* Set the page dirty diff --git a/fs/ntfs/compress.c b/fs/ntfs/compress.c index 6551c7cbad92..ef9ed854255c 100644 --- a/fs/ntfs/compress.c +++ b/fs/ntfs/compress.c @@ -698,8 +698,7 @@ lock_retry_remap: "uptodate! Unplugging the disk queue " "and rescheduling."); get_bh(tbh); - blk_run_address_space(mapping); - schedule(); + io_schedule(); put_bh(tbh); if (unlikely(!buffer_uptodate(tbh))) goto read_err; diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 1fbb0e20131b..daea0359e974 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -2043,7 +2043,6 @@ const struct address_space_operations ocfs2_aops = { .write_begin = ocfs2_write_begin, .write_end = ocfs2_write_end, .bmap = ocfs2_bmap, - .sync_page = block_sync_page, .direct_IO = ocfs2_direct_IO, .invalidatepage = ocfs2_invalidatepage, .releasepage = ocfs2_releasepage, diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index b108e863d8f6..1adab287bd24 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c @@ -367,11 +367,7 @@ static inline void o2hb_bio_wait_dec(struct o2hb_bio_wait_ctxt *wc, static void o2hb_wait_on_io(struct o2hb_region *reg, struct o2hb_bio_wait_ctxt *wc) { - struct address_space *mapping = reg->hr_bdev->bd_inode->i_mapping; - - blk_run_address_space(mapping); o2hb_bio_wait_dec(wc, 1); - wait_for_completion(&wc->wc_io_complete); } diff --git a/fs/omfs/file.c b/fs/omfs/file.c index 8a6d34fa668a..d738a7e493dd 100644 --- a/fs/omfs/file.c +++ b/fs/omfs/file.c @@ -372,7 +372,6 @@ const struct address_space_operations omfs_aops = { .readpages = omfs_readpages, .writepage = omfs_writepage, .writepages = omfs_writepages, - .sync_page = block_sync_page, .write_begin = omfs_write_begin, .write_end = generic_write_end, .bmap = omfs_bmap, diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c index e63b4171d583..2b0646613f5a 100644 --- a/fs/qnx4/inode.c +++ b/fs/qnx4/inode.c @@ -335,7 +335,6 @@ static sector_t qnx4_bmap(struct address_space *mapping, sector_t block) static const struct address_space_operations qnx4_aops = { .readpage = qnx4_readpage, .writepage = qnx4_writepage, - .sync_page = block_sync_page, .write_begin = qnx4_write_begin, .write_end = generic_write_end, .bmap = qnx4_bmap diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 0bae036831e2..03674675f886 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -3212,7 +3212,6 @@ const struct address_space_operations reiserfs_address_space_operations = { .readpages = reiserfs_readpages, .releasepage = reiserfs_releasepage, .invalidatepage = reiserfs_invalidatepage, - .sync_page = block_sync_page, .write_begin = reiserfs_write_begin, .write_end = reiserfs_write_end, .bmap = reiserfs_aop_bmap, diff --git a/fs/sysv/itree.c b/fs/sysv/itree.c index 9ca66276315e..fa8d43c92bb8 100644 --- a/fs/sysv/itree.c +++ b/fs/sysv/itree.c @@ -488,7 +488,6 @@ static sector_t sysv_bmap(struct address_space *mapping, sector_t block) const struct address_space_operations sysv_aops = { .readpage = sysv_readpage, .writepage = sysv_writepage, - .sync_page = block_sync_page, .write_begin = sysv_write_begin, .write_end = generic_write_end, .bmap = sysv_bmap diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 6e11c2975dcf..81368d4d4a2c 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1979,7 +1979,6 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent) */ c->bdi.name = "ubifs", c->bdi.capabilities = BDI_CAP_MAP_COPY; - c->bdi.unplug_io_fn = default_unplug_io_fn; err = bdi_init(&c->bdi); if (err) goto out_close; diff --git a/fs/udf/file.c b/fs/udf/file.c index 89c78486cbbe..94e4553491c9 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c @@ -98,7 +98,6 @@ static int udf_adinicb_write_end(struct file *file, const struct address_space_operations udf_adinicb_aops = { .readpage = udf_adinicb_readpage, .writepage = udf_adinicb_writepage, - .sync_page = block_sync_page, .write_begin = simple_write_begin, .write_end = udf_adinicb_write_end, }; diff --git a/fs/udf/inode.c b/fs/udf/inode.c index c6a2e782b97b..fa96fc0fe12b 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -133,7 +133,6 @@ static sector_t udf_bmap(struct address_space *mapping, sector_t block) const struct address_space_operations udf_aops = { .readpage = udf_readpage, .writepage = udf_writepage, - .sync_page = block_sync_page, .write_begin = udf_write_begin, .write_end = generic_write_end, .bmap = udf_bmap, diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index 2b251f2093af..83b28444eb17 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c @@ -588,7 +588,6 @@ static sector_t ufs_bmap(struct address_space *mapping, sector_t block) const struct address_space_operations ufs_aops = { .readpage = ufs_readpage, .writepage = ufs_writepage, - .sync_page = block_sync_page, .write_begin = ufs_write_begin, .write_end = generic_write_end, .bmap = ufs_bmap diff --git a/fs/ufs/truncate.c b/fs/ufs/truncate.c index a58f9155fc9a..ff0e79276f2d 100644 --- a/fs/ufs/truncate.c +++ b/fs/ufs/truncate.c @@ -481,7 +481,7 @@ int ufs_truncate(struct inode *inode, loff_t old_i_size) break; if (IS_SYNC(inode) && (inode->i_state & I_DIRTY)) ufs_sync_inode (inode); - blk_run_address_space(inode->i_mapping); + blk_flush_plug(current); yield(); } diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index ec7bbb5645b6..83c1c20d145a 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -1495,7 +1495,6 @@ const struct address_space_operations xfs_address_space_operations = { .readpages = xfs_vm_readpages, .writepage = xfs_vm_writepage, .writepages = xfs_vm_writepages, - .sync_page = block_sync_page, .releasepage = xfs_vm_releasepage, .invalidatepage = xfs_vm_invalidatepage, .write_begin = xfs_vm_write_begin, diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index ac1c7e8378dd..4f8f53c4d42c 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c @@ -991,7 +991,7 @@ xfs_buf_lock( if (atomic_read(&bp->b_pin_count) && (bp->b_flags & XBF_STALE)) xfs_log_force(bp->b_target->bt_mount, 0); if (atomic_read(&bp->b_io_remaining)) - blk_run_address_space(bp->b_target->bt_mapping); + blk_flush_plug(current); down(&bp->b_sema); XB_SET_OWNER(bp); @@ -1035,9 +1035,7 @@ xfs_buf_wait_unpin( set_current_state(TASK_UNINTERRUPTIBLE); if (atomic_read(&bp->b_pin_count) == 0) break; - if (atomic_read(&bp->b_io_remaining)) - blk_run_address_space(bp->b_target->bt_mapping); - schedule(); + io_schedule(); } remove_wait_queue(&bp->b_waiters, &wait); set_current_state(TASK_RUNNING); @@ -1443,7 +1441,7 @@ xfs_buf_iowait( trace_xfs_buf_iowait(bp, _RET_IP_); if (atomic_read(&bp->b_io_remaining)) - blk_run_address_space(bp->b_target->bt_mapping); + blk_flush_plug(current); wait_for_completion(&bp->b_iowait); trace_xfs_buf_iowait_done(bp, _RET_IP_); @@ -1667,7 +1665,6 @@ xfs_mapping_buftarg( struct inode *inode; struct address_space *mapping; static const struct address_space_operations mapping_aops = { - .sync_page = block_sync_page, .migratepage = fail_migrate_page, }; @@ -1948,7 +1945,7 @@ xfsbufd( count++; } if (count) - blk_run_address_space(target->bt_mapping); + blk_flush_plug(current); } while (!kthread_should_stop()); @@ -1996,7 +1993,7 @@ xfs_flush_buftarg( if (wait) { /* Expedite and wait for IO to complete. */ - blk_run_address_space(target->bt_mapping); + blk_flush_plug(current); while (!list_empty(&wait_list)) { bp = list_first_entry(&wait_list, struct xfs_buf, b_list); -- cgit From 2ed1a6bcf97a7ed787e6799bf2e80b9e6f51dca7 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 22 Jun 2010 12:52:14 +0200 Subject: fs: make mpage read/write_pages() plug Signed-off-by: Jens Axboe --- fs/mpage.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'fs') diff --git a/fs/mpage.c b/fs/mpage.c index d78455a81ec9..0afc809e46e0 100644 --- a/fs/mpage.c +++ b/fs/mpage.c @@ -364,6 +364,9 @@ mpage_readpages(struct address_space *mapping, struct list_head *pages, sector_t last_block_in_bio = 0; struct buffer_head map_bh; unsigned long first_logical_block = 0; + struct blk_plug plug; + + blk_start_plug(&plug); map_bh.b_state = 0; map_bh.b_size = 0; @@ -385,6 +388,7 @@ mpage_readpages(struct address_space *mapping, struct list_head *pages, BUG_ON(!list_empty(pages)); if (bio) mpage_bio_submit(READ, bio); + blk_finish_plug(&plug); return 0; } EXPORT_SYMBOL(mpage_readpages); @@ -666,8 +670,11 @@ int mpage_writepages(struct address_space *mapping, struct writeback_control *wbc, get_block_t get_block) { + struct blk_plug plug; int ret; + blk_start_plug(&plug); + if (!get_block) ret = generic_writepages(mapping, wbc); else { @@ -682,6 +689,7 @@ mpage_writepages(struct address_space *mapping, if (mpd.bio) mpage_bio_submit(WRITE, mpd.bio); } + blk_finish_plug(&plug); return ret; } EXPORT_SYMBOL(mpage_writepages); -- cgit From 9f5b9425468c85a901d863d241ba5c5dff9b23b8 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Thu, 1 Jul 2010 07:55:01 +0200 Subject: fs: make aio plug Signed-off-by: Shaohua Li Signed-off-by: Jens Axboe --- fs/aio.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'fs') diff --git a/fs/aio.c b/fs/aio.c index c5ea494ea9e2..1476bed1c5fb 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -1660,6 +1660,7 @@ long do_io_submit(aio_context_t ctx_id, long nr, long ret = 0; int i; struct hlist_head batch_hash[AIO_BATCH_HASH_SIZE] = { { 0, }, }; + struct blk_plug plug; if (unlikely(nr < 0)) return -EINVAL; @@ -1676,6 +1677,8 @@ long do_io_submit(aio_context_t ctx_id, long nr, return -EINVAL; } + blk_start_plug(&plug); + /* * AKPM: should this return a partial result if some of the IOs were * successfully submitted? @@ -1698,6 +1701,7 @@ long do_io_submit(aio_context_t ctx_id, long nr, if (ret) break; } + blk_finish_plug(&plug); aio_batch_free(batch_hash); put_ioctx(ctx); -- cgit From cf15900e1209d5b46ec2d24643adbf561830935f Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 2 Mar 2011 20:12:18 -0500 Subject: aio: remove request submission batching This should be useless now that we have on-stack plugging. So lets just kill it. Signed-off-by: Jens Axboe --- fs/aio.c | 75 +++------------------------------------------------------------- 1 file changed, 3 insertions(+), 72 deletions(-) (limited to 'fs') diff --git a/fs/aio.c b/fs/aio.c index 1476bed1c5fb..020de5cb4a67 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -34,8 +34,6 @@ #include #include #include -#include -#include #include #include @@ -65,14 +63,6 @@ static DECLARE_WORK(fput_work, aio_fput_routine); static DEFINE_SPINLOCK(fput_lock); static LIST_HEAD(fput_head); -#define AIO_BATCH_HASH_BITS 3 /* allocated on-stack, so don't go crazy */ -#define AIO_BATCH_HASH_SIZE (1 << AIO_BATCH_HASH_BITS) -struct aio_batch_entry { - struct hlist_node list; - struct address_space *mapping; -}; -mempool_t *abe_pool; - static void aio_kick_handler(struct work_struct *); static void aio_queue_work(struct kioctx *); @@ -86,8 +76,7 @@ static int __init aio_setup(void) kioctx_cachep = KMEM_CACHE(kioctx,SLAB_HWCACHE_ALIGN|SLAB_PANIC); aio_wq = create_workqueue("aio"); - abe_pool = mempool_create_kmalloc_pool(1, sizeof(struct aio_batch_entry)); - BUG_ON(!aio_wq || !abe_pool); + BUG_ON(!aio_wq); pr_debug("aio_setup: sizeof(struct page) = %d\n", (int)sizeof(struct page)); @@ -1512,59 +1501,8 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb, bool compat) return 0; } -static void aio_batch_add(struct address_space *mapping, - struct hlist_head *batch_hash) -{ - struct aio_batch_entry *abe; - struct hlist_node *pos; - unsigned bucket; - - bucket = hash_ptr(mapping, AIO_BATCH_HASH_BITS); - hlist_for_each_entry(abe, pos, &batch_hash[bucket], list) { - if (abe->mapping == mapping) - return; - } - - abe = mempool_alloc(abe_pool, GFP_KERNEL); - - /* - * we should be using igrab here, but - * we don't want to hammer on the global - * inode spinlock just to take an extra - * reference on a file that we must already - * have a reference to. - * - * When we're called, we always have a reference - * on the file, so we must always have a reference - * on the inode, so ihold() is safe here. - */ - ihold(mapping->host); - abe->mapping = mapping; - hlist_add_head(&abe->list, &batch_hash[bucket]); - return; -} - -static void aio_batch_free(struct hlist_head *batch_hash) -{ - struct aio_batch_entry *abe; - struct hlist_node *pos, *n; - int i; - - /* - * TODO: kill this - */ - for (i = 0; i < AIO_BATCH_HASH_SIZE; i++) { - hlist_for_each_entry_safe(abe, pos, n, &batch_hash[i], list) { - iput(abe->mapping->host); - hlist_del(&abe->list); - mempool_free(abe, abe_pool); - } - } -} - static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, - struct iocb *iocb, struct hlist_head *batch_hash, - bool compat) + struct iocb *iocb, bool compat) { struct kiocb *req; struct file *file; @@ -1638,11 +1576,6 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, ; } spin_unlock_irq(&ctx->ctx_lock); - if (req->ki_opcode == IOCB_CMD_PREAD || - req->ki_opcode == IOCB_CMD_PREADV || - req->ki_opcode == IOCB_CMD_PWRITE || - req->ki_opcode == IOCB_CMD_PWRITEV) - aio_batch_add(file->f_mapping, batch_hash); aio_put_req(req); /* drop extra ref to req */ return 0; @@ -1659,7 +1592,6 @@ long do_io_submit(aio_context_t ctx_id, long nr, struct kioctx *ctx; long ret = 0; int i; - struct hlist_head batch_hash[AIO_BATCH_HASH_SIZE] = { { 0, }, }; struct blk_plug plug; if (unlikely(nr < 0)) @@ -1697,12 +1629,11 @@ long do_io_submit(aio_context_t ctx_id, long nr, break; } - ret = io_submit_one(ctx, user_iocb, &tmp, batch_hash, compat); + ret = io_submit_one(ctx, user_iocb, &tmp, compat); if (ret) break; } blk_finish_plug(&plug); - aio_batch_free(batch_hash); put_ioctx(ctx); return i ? i : ret; -- cgit From 721a9602e6607417c6bc15b18e97a2f35266c690 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 9 Mar 2011 11:56:30 +0100 Subject: block: kill off REQ_UNPLUG With the plugging now being explicitly controlled by the submitter, callers need not pass down unplugging hints to the block layer. If they want to unplug, it's because they manually plugged on their own - in which case, they should just unplug at will. Signed-off-by: Jens Axboe --- fs/btrfs/extent_io.c | 2 +- fs/buffer.c | 14 ++++---------- fs/direct-io.c | 2 +- fs/ext4/page-io.c | 3 +-- fs/gfs2/log.c | 4 ++-- fs/gfs2/lops.c | 12 ++++++------ fs/gfs2/meta_io.c | 2 +- fs/jbd/commit.c | 2 +- fs/jbd2/commit.c | 6 +++--- fs/nilfs2/segbuf.c | 2 +- fs/xfs/linux-2.6/xfs_aops.c | 3 +-- 11 files changed, 22 insertions(+), 30 deletions(-) (limited to 'fs') diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 92ac5192c518..b76f7cd47401 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -2182,7 +2182,7 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc, unsigned long nr_written = 0; if (wbc->sync_mode == WB_SYNC_ALL) - write_flags = WRITE_SYNC_PLUG; + write_flags = WRITE_SYNC; else write_flags = WRITE; diff --git a/fs/buffer.c b/fs/buffer.c index f903f2e5b4fe..42534f67d71b 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -767,7 +767,7 @@ static int fsync_buffers_list(spinlock_t *lock, struct list_head *list) * still in flight on potentially older * contents. */ - write_dirty_buffer(bh, WRITE_SYNC_PLUG); + write_dirty_buffer(bh, WRITE_SYNC); /* * Kick off IO for the previous mapping. Note @@ -1602,14 +1602,8 @@ EXPORT_SYMBOL(unmap_underlying_metadata); * prevents this contention from occurring. * * If block_write_full_page() is called with wbc->sync_mode == - * WB_SYNC_ALL, the writes are posted using WRITE_SYNC_PLUG; this - * causes the writes to be flagged as synchronous writes, but the - * block device queue will NOT be unplugged, since usually many pages - * will be pushed to the out before the higher-level caller actually - * waits for the writes to be completed. The various wait functions, - * such as wait_on_writeback_range() will ultimately call sync_page() - * which will ultimately call blk_run_backing_dev(), which will end up - * unplugging the device queue. + * WB_SYNC_ALL, the writes are posted using WRITE_SYNC; this + * causes the writes to be flagged as synchronous writes. */ static int __block_write_full_page(struct inode *inode, struct page *page, get_block_t *get_block, struct writeback_control *wbc, @@ -1622,7 +1616,7 @@ static int __block_write_full_page(struct inode *inode, struct page *page, const unsigned blocksize = 1 << inode->i_blkbits; int nr_underway = 0; int write_op = (wbc->sync_mode == WB_SYNC_ALL ? - WRITE_SYNC_PLUG : WRITE); + WRITE_SYNC : WRITE); BUG_ON(!PageLocked(page)); diff --git a/fs/direct-io.c b/fs/direct-io.c index df709b3b860a..426083136099 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -1173,7 +1173,7 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, struct dio *dio; if (rw & WRITE) - rw = WRITE_ODIRECT_PLUG; + rw = WRITE_ODIRECT; if (bdev) bdev_blkbits = blksize_bits(bdev_logical_block_size(bdev)); diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index 955cc309142f..e2cd90e4bb7c 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c @@ -310,8 +310,7 @@ static int io_submit_init(struct ext4_io_submit *io, io_end->offset = (page->index << PAGE_CACHE_SHIFT) + bh_offset(bh); io->io_bio = bio; - io->io_op = (wbc->sync_mode == WB_SYNC_ALL ? - WRITE_SYNC_PLUG : WRITE); + io->io_op = (wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : WRITE); io->io_next_block = bh->b_blocknr; return 0; } diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index eb01f3575e10..7f1c11202342 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c @@ -121,7 +121,7 @@ __acquires(&sdp->sd_log_lock) lock_buffer(bh); if (test_clear_buffer_dirty(bh)) { bh->b_end_io = end_buffer_write_sync; - submit_bh(WRITE_SYNC_PLUG, bh); + submit_bh(WRITE_SYNC, bh); } else { unlock_buffer(bh); brelse(bh); @@ -647,7 +647,7 @@ static void gfs2_ordered_write(struct gfs2_sbd *sdp) lock_buffer(bh); if (buffer_mapped(bh) && test_clear_buffer_dirty(bh)) { bh->b_end_io = end_buffer_write_sync; - submit_bh(WRITE_SYNC_PLUG, bh); + submit_bh(WRITE_SYNC, bh); } else { unlock_buffer(bh); brelse(bh); diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index bf33f822058d..48b545a1979a 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c @@ -200,7 +200,7 @@ static void buf_lo_before_commit(struct gfs2_sbd *sdp) } gfs2_log_unlock(sdp); - submit_bh(WRITE_SYNC_PLUG, bh); + submit_bh(WRITE_SYNC, bh); gfs2_log_lock(sdp); n = 0; @@ -210,7 +210,7 @@ static void buf_lo_before_commit(struct gfs2_sbd *sdp) gfs2_log_unlock(sdp); lock_buffer(bd2->bd_bh); bh = gfs2_log_fake_buf(sdp, bd2->bd_bh); - submit_bh(WRITE_SYNC_PLUG, bh); + submit_bh(WRITE_SYNC, bh); gfs2_log_lock(sdp); if (++n >= num) break; @@ -352,7 +352,7 @@ static void revoke_lo_before_commit(struct gfs2_sbd *sdp) sdp->sd_log_num_revoke--; if (offset + sizeof(u64) > sdp->sd_sb.sb_bsize) { - submit_bh(WRITE_SYNC_PLUG, bh); + submit_bh(WRITE_SYNC, bh); bh = gfs2_log_get_buf(sdp); mh = (struct gfs2_meta_header *)bh->b_data; @@ -369,7 +369,7 @@ static void revoke_lo_before_commit(struct gfs2_sbd *sdp) } gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke); - submit_bh(WRITE_SYNC_PLUG, bh); + submit_bh(WRITE_SYNC, bh); } static void revoke_lo_before_scan(struct gfs2_jdesc *jd, @@ -571,7 +571,7 @@ static void gfs2_write_blocks(struct gfs2_sbd *sdp, struct buffer_head *bh, ptr = bh_log_ptr(bh); get_bh(bh); - submit_bh(WRITE_SYNC_PLUG, bh); + submit_bh(WRITE_SYNC, bh); gfs2_log_lock(sdp); while(!list_empty(list)) { bd = list_entry(list->next, struct gfs2_bufdata, bd_le.le_list); @@ -597,7 +597,7 @@ static void gfs2_write_blocks(struct gfs2_sbd *sdp, struct buffer_head *bh, } else { bh1 = gfs2_log_fake_buf(sdp, bd->bd_bh); } - submit_bh(WRITE_SYNC_PLUG, bh1); + submit_bh(WRITE_SYNC, bh1); gfs2_log_lock(sdp); ptr += 2; } diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index a566331db4e1..867b713cba92 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c @@ -37,7 +37,7 @@ static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wb struct buffer_head *bh, *head; int nr_underway = 0; int write_op = REQ_META | - (wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC_PLUG : WRITE); + (wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : WRITE); BUG_ON(!PageLocked(page)); BUG_ON(!page_has_buffers(page)); diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index 34a4861c14b8..66be299acb1b 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c @@ -333,7 +333,7 @@ void journal_commit_transaction(journal_t *journal) * instead we rely on sync_buffer() doing the unplug for us. */ if (commit_transaction->t_synchronous_commit) - write_op = WRITE_SYNC_PLUG; + write_op = WRITE_SYNC; spin_lock(&commit_transaction->t_handle_lock); while (commit_transaction->t_updates) { DEFINE_WAIT(wait); diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index f3ad1598b201..3da1cc4346d5 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c @@ -137,9 +137,9 @@ static int journal_submit_commit_record(journal_t *journal, if (journal->j_flags & JBD2_BARRIER && !JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) - ret = submit_bh(WRITE_SYNC_PLUG | WRITE_FLUSH_FUA, bh); + ret = submit_bh(WRITE_SYNC | WRITE_FLUSH_FUA, bh); else - ret = submit_bh(WRITE_SYNC_PLUG, bh); + ret = submit_bh(WRITE_SYNC, bh); *cbh = bh; return ret; @@ -369,7 +369,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) * instead we rely on sync_buffer() doing the unplug for us. */ if (commit_transaction->t_synchronous_commit) - write_op = WRITE_SYNC_PLUG; + write_op = WRITE_SYNC; trace_jbd2_commit_locking(journal, commit_transaction); stats.run.rs_wait = commit_transaction->t_max_wait; stats.run.rs_locked = jiffies; diff --git a/fs/nilfs2/segbuf.c b/fs/nilfs2/segbuf.c index 0f83e93935b2..2853ff20f85a 100644 --- a/fs/nilfs2/segbuf.c +++ b/fs/nilfs2/segbuf.c @@ -509,7 +509,7 @@ static int nilfs_segbuf_write(struct nilfs_segment_buffer *segbuf, * Last BIO is always sent through the following * submission. */ - rw |= REQ_SYNC | REQ_UNPLUG; + rw |= REQ_SYNC; res = nilfs_segbuf_submit_bio(segbuf, &wi, rw); } diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 83c1c20d145a..6bbb0ee33253 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -413,8 +413,7 @@ xfs_submit_ioend_bio( if (xfs_ioend_new_eof(ioend)) xfs_mark_inode_dirty(XFS_I(ioend->io_inode)); - submit_bio(wbc->sync_mode == WB_SYNC_ALL ? - WRITE_SYNC_PLUG : WRITE, bio); + submit_bio(wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : WRITE, bio); } STATIC struct bio * -- cgit From bea9312839c51853a2837336405c829b0bf18f88 Mon Sep 17 00:00:00 2001 From: Tracey Dent Date: Sat, 26 Feb 2011 11:15:13 -0500 Subject: jffs2: remove a trailing white space in commentaries Signed-off-by: Tracey Dent Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- fs/jffs2/xattr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c index 4f9cc0482949..3e93cdd19005 100644 --- a/fs/jffs2/xattr.c +++ b/fs/jffs2/xattr.c @@ -31,7 +31,7 @@ * is used to release xattr name/value pair and detach from c->xattrindex. * reclaim_xattr_datum(c) * is used to reclaim xattr name/value pairs on the xattr name/value pair cache when - * memory usage by cache is over c->xdatum_mem_threshold. Currently, this threshold + * memory usage by cache is over c->xdatum_mem_threshold. Currently, this threshold * is hard coded as 32KiB. * do_verify_xattr_datum(c, xd) * is used to load the xdatum informations without name/value pair from the medium. -- cgit From 0c9ba97318fc9a905bcc1419b6966de061203a70 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Fri, 11 Mar 2011 12:39:51 +0000 Subject: xfs: don't name variables "panic" The new xfs_alert_tag() used a variable named "panic", and that is to be avoided. Rename it. Signed-off-by: Alex Elder Reviewed-by: Dave Chinner --- fs/xfs/linux-2.6/xfs_message.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_message.c b/fs/xfs/linux-2.6/xfs_message.c index 8fe8cf69d809..508e06fd7d1e 100644 --- a/fs/xfs/linux-2.6/xfs_message.c +++ b/fs/xfs/linux-2.6/xfs_message.c @@ -96,13 +96,13 @@ xfs_alert_tag( { struct va_format vaf; va_list args; - int panic = 0; - int r; + int do_panic = 0; + int r; if (xfs_panic_mask && (xfs_panic_mask & panic_tag)) { xfs_printk(KERN_ALERT, mp, "XFS: Transforming an alert into a BUG."); - panic = 1; + do_panic = 1; } va_start(args, fmt); @@ -113,7 +113,7 @@ xfs_alert_tag( r = __xfs_printk(KERN_ALERT, mp, &vaf); va_end(args); - BUG_ON(panic); + BUG_ON(do_panic); return r; } -- cgit From 0a5e5f122c756d1c1a6ca712eda76ea8664e5fd9 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Mon, 14 Mar 2011 20:57:44 -0400 Subject: nfsd: fix compile error "fs/built-in.o: In function `supported_enctypes_show': nfsctl.c:(.text+0x7beb0): undefined reference to `gss_mech_get_by_name' nfsctl.c:(.text+0x7bebc): undefined reference to `gss_mech_put' " Reported-by: Guennadi Liakhovetski Signed-off-by: J. Bruce Fields --- fs/nfsd/nfsctl.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'fs') diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 35dcfa8eba21..1f5eae40f34e 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -189,6 +189,7 @@ static struct file_operations export_features_operations = { .release = single_release, }; +#ifdef CONFIG_SUNRPC_GSS static int supported_enctypes_show(struct seq_file *m, void *v) { struct gss_api_mech *k5mech; @@ -214,6 +215,7 @@ static struct file_operations supported_enctypes_ops = { .llseek = seq_lseek, .release = single_release, }; +#endif /* CONFIG_SUNRPC_GSS */ extern int nfsd_pool_stats_open(struct inode *inode, struct file *file); extern int nfsd_pool_stats_release(struct inode *inode, struct file *file); @@ -1425,7 +1427,9 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent) [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR}, [NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO}, [NFSD_MaxBlkSize] = {"max_block_size", &transaction_ops, S_IWUSR|S_IRUGO}, +#ifdef CONFIG_SUNRPC_GSS [NFSD_SupportedEnctypes] = {"supported_krb5_enctypes", &supported_enctypes_ops, S_IRUGO}, +#endif /* CONFIG_SUNRPC_GSS */ #ifdef CONFIG_NFSD_V4 [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR}, [NFSD_Gracetime] = {"nfsv4gracetime", &transaction_ops, S_IWUSR|S_IRUSR}, -- cgit From 2c722c9a47d1369e2685b85288e78c469a081238 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Thu, 9 Dec 2010 15:55:21 +0100 Subject: exofs: Remove redundant unlikely() IS_ERR() already implies unlikely(), so it can be omitted here. Signed-off-by: Tobias Klauser --- fs/exofs/super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/exofs/super.c b/fs/exofs/super.c index 8c6c4669b381..78f5ad633d3b 100644 --- a/fs/exofs/super.c +++ b/fs/exofs/super.c @@ -495,7 +495,7 @@ static int exofs_read_lookup_dev_table(struct exofs_sb_info **psbi, } od = osduld_info_lookup(&odi); - if (unlikely(IS_ERR(od))) { + if (IS_ERR(od)) { ret = PTR_ERR(od); EXOFS_ERR("ERROR: device requested is not found " "osd_name-%s =>%d\n", odi.osdname, ret); -- cgit From 0a935519cca83f26dc15e7577fa6c2b39606a4ac Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Tue, 26 Oct 2010 17:52:41 +0200 Subject: exofs: Trivial: fix some indentation and debug prints I stumbled on some of these prints in log files so, might just submit the fixes. * All i_ino prints in exofs should be hex * All OSD_ERR prints should end with a "\n" Signed-off-by: Boaz Harrosh --- fs/exofs/dir.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) (limited to 'fs') diff --git a/fs/exofs/dir.c b/fs/exofs/dir.c index dcc941d82d67..d0941c6a1f72 100644 --- a/fs/exofs/dir.c +++ b/fs/exofs/dir.c @@ -124,7 +124,7 @@ out: Ebadsize: EXOFS_ERR("ERROR [exofs_check_page]: " - "size of directory #%lu is not a multiple of chunk size", + "size of directory(0x%lx) is not a multiple of chunk size\n", dir->i_ino ); goto fail; @@ -142,8 +142,8 @@ Espan: goto bad_entry; bad_entry: EXOFS_ERR( - "ERROR [exofs_check_page]: bad entry in directory #%lu: %s - " - "offset=%lu, inode=%llu, rec_len=%d, name_len=%d", + "ERROR [exofs_check_page]: bad entry in directory(0x%lx): %s - " + "offset=%lu, inode=0x%llu, rec_len=%d, name_len=%d\n", dir->i_ino, error, (page->index<inode_no)), rec_len, p->name_len); @@ -151,8 +151,8 @@ bad_entry: Eend: p = (struct exofs_dir_entry *)(kaddr + offs); EXOFS_ERR("ERROR [exofs_check_page]: " - "entry in directory #%lu spans the page boundary" - "offset=%lu, inode=%llu", + "entry in directory(0x%lx) spans the page boundary" + "offset=%lu, inode=0x%llx\n", dir->i_ino, (page->index<inode_no))); fail: @@ -261,9 +261,8 @@ exofs_readdir(struct file *filp, void *dirent, filldir_t filldir) struct page *page = exofs_get_page(inode, n); if (IS_ERR(page)) { - EXOFS_ERR("ERROR: " - "bad page in #%lu", - inode->i_ino); + EXOFS_ERR("ERROR: bad page in directory(0x%lx)\n", + inode->i_ino); filp->f_pos += PAGE_CACHE_SIZE - offset; return PTR_ERR(page); } @@ -283,7 +282,8 @@ exofs_readdir(struct file *filp, void *dirent, filldir_t filldir) for (; (char *)de <= limit; de = exofs_next_entry(de)) { if (de->rec_len == 0) { EXOFS_ERR("ERROR: " - "zero-length directory entry"); + "zero-length entry in directory(0x%lx)\n", + inode->i_ino); exofs_put_page(page); return -EIO; } @@ -342,9 +342,9 @@ struct exofs_dir_entry *exofs_find_entry(struct inode *dir, kaddr += exofs_last_byte(dir, n) - reclen; while ((char *) de <= kaddr) { if (de->rec_len == 0) { - EXOFS_ERR( - "ERROR: exofs_find_entry: " - "zero-length directory entry"); + EXOFS_ERR("ERROR: zero-length entry in " + "directory(0x%lx)\n", + dir->i_ino); exofs_put_page(page); goto out; } @@ -472,7 +472,8 @@ int exofs_add_link(struct dentry *dentry, struct inode *inode) } if (de->rec_len == 0) { EXOFS_ERR("ERROR: exofs_add_link: " - "zero-length directory entry"); + "zero-length entry in directory(0x%lx)\n", + inode->i_ino); err = -EIO; goto out_unlock; } @@ -491,7 +492,8 @@ int exofs_add_link(struct dentry *dentry, struct inode *inode) exofs_put_page(page); } - EXOFS_ERR("exofs_add_link: BAD dentry=%p or inode=%p", dentry, inode); + EXOFS_ERR("exofs_add_link: BAD dentry=%p or inode=0x%lx\n", + dentry, inode->i_ino); return -EINVAL; got_it: @@ -542,7 +544,8 @@ int exofs_delete_entry(struct exofs_dir_entry *dir, struct page *page) while (de < dir) { if (de->rec_len == 0) { EXOFS_ERR("ERROR: exofs_delete_entry:" - "zero-length directory entry"); + "zero-length entry in directory(0x%lx)\n", + inode->i_ino); err = -EIO; goto out; } -- cgit From a8f1418f9e9bd4c487a7b703ff26c5dd5ceb2bf3 Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Mon, 22 Nov 2010 18:02:45 +0200 Subject: exofs: Optimize read_4_write Don't attempt a read passed i_size, just zero the page and be done with it. Signed-off-by: Boaz Harrosh --- fs/exofs/inode.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index a7555238c41a..c8f58a96e597 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c @@ -350,8 +350,10 @@ static int readpage_strip(void *data, struct page *page) if (!pcol->read_4_write) unlock_page(page); - EXOFS_DBGMSG("readpage_strip(0x%lx, 0x%lx) empty page," - " splitting\n", inode->i_ino, page->index); + EXOFS_DBGMSG("readpage_strip(0x%lx) empty page len=%zx " + "read_4_write=%d index=0x%lx end_index=0x%lx " + "splitting\n", inode->i_ino, len, + pcol->read_4_write, page->index, end_index); return read_exec(pcol); } @@ -722,11 +724,28 @@ int exofs_write_begin(struct file *file, struct address_space *mapping, /* read modify write */ if (!PageUptodate(page) && (len != PAGE_CACHE_SIZE)) { + loff_t i_size = i_size_read(mapping->host); + pgoff_t end_index = i_size >> PAGE_CACHE_SHIFT; + size_t rlen; + + if (page->index < end_index) + rlen = PAGE_CACHE_SIZE; + else if (page->index == end_index) + rlen = i_size & ~PAGE_CACHE_MASK; + else + rlen = 0; + + if (!rlen) { + clear_highpage(page); + SetPageUptodate(page); + goto out; + } + ret = _readpage(page, true); if (ret) { /*SetPageError was done by _readpage. Is it ok?*/ unlock_page(page); - EXOFS_DBGMSG("__readpage_filler failed\n"); + EXOFS_DBGMSG("__readpage failed\n"); } } out: -- cgit From 97178b7b6c84bd14660b89474d27931a1ea65c66 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Thu, 25 Nov 2010 12:47:15 +0200 Subject: exofs: simple fsync race fix It is incorrect to test inode dirty bits without participating in the inode writeback protocol. Inode writeback sets I_SYNC and clears I_DIRTY_?, then writes out the particular bits, then clears I_SYNC when it is done. BTW. it may not completely write all pages out, so I_DIRTY_PAGES would get set again. This is a standard pattern used throughout the kernel's writeback caches (I_SYNC ~= I_WRITEBACK, if that makes it clearer). And so it is not possible to determine an inode's dirty status just by checking I_DIRTY bits. Especially not for the purpose of data integrity syncs. Missing the check for these bits means that fsync can complete while writeback to the inode is underway. Inode writeback functions get this right, so call into them rather than try to shortcut things by testing dirty state improperly. Signed-off-by: Nick Piggin Signed-off-by: Boaz Harrosh --- fs/exofs/file.c | 5 ----- fs/exofs/inode.c | 3 ++- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'fs') diff --git a/fs/exofs/file.c b/fs/exofs/file.c index b905c79b4f0a..4c0d6bac9143 100644 --- a/fs/exofs/file.c +++ b/fs/exofs/file.c @@ -48,11 +48,6 @@ static int exofs_file_fsync(struct file *filp, int datasync) struct inode *inode = filp->f_mapping->host; struct super_block *sb; - if (!(inode->i_state & I_DIRTY)) - return 0; - if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) - return 0; - ret = sync_inode_metadata(inode, 1); /* This is a good place to write the sb */ diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index c8f58a96e597..fb9d38056103 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c @@ -1290,7 +1290,8 @@ out: int exofs_write_inode(struct inode *inode, struct writeback_control *wbc) { - return exofs_update_inode(inode, wbc->sync_mode == WB_SYNC_ALL); + /* FIXME: fix fsync and use wbc->sync_mode == WB_SYNC_ALL */ + return exofs_update_inode(inode, 1); } /* -- cgit From 66cd6cad4919f980dd21307d0150ff251762a264 Mon Sep 17 00:00:00 2001 From: "bharrosh@panasas.com" Date: Thu, 7 Oct 2010 14:28:18 -0400 Subject: exofs: Override read-ahead to align on stripe_size * Set all inode->i_mapping->backing_dev_info to point to the per super-block sb->s_bdi. * Calculating a read_ahead that is: - preferable 2 stripes long (Future patch will add a mount option to override this) - Minimum 128K aligned up to stripe-size - Caped to maximum-IO-sizes round down to stripe_size. (Max sizes are governed by max bio-size that fits in a page times number-of-devices) CC: Marc Dionne Signed-off-by: Boaz Harrosh --- fs/exofs/exofs.h | 2 ++ fs/exofs/inode.c | 19 +++++++++++++++---- fs/exofs/super.c | 18 ++++++++++++++++++ 3 files changed, 35 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/exofs/exofs.h b/fs/exofs/exofs.h index 2dc925fa1010..99fcb9126a97 100644 --- a/fs/exofs/exofs.h +++ b/fs/exofs/exofs.h @@ -256,6 +256,8 @@ static inline int exofs_oi_read(struct exofs_i_info *oi, } /* inode.c */ +unsigned exofs_max_io_pages(struct exofs_layout *layout, + unsigned expected_pages); int exofs_setattr(struct dentry *, struct iattr *); int exofs_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index fb9d38056103..681b3cb9b4d8 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c @@ -43,6 +43,17 @@ enum { BIO_MAX_PAGES_KMALLOC = PAGE_SIZE / sizeof(struct page *), }; +unsigned exofs_max_io_pages(struct exofs_layout *layout, + unsigned expected_pages) +{ + unsigned pages = min_t(unsigned, expected_pages, MAX_PAGES_KMALLOC); + + /* TODO: easily support bio chaining */ + pages = min_t(unsigned, pages, + layout->group_width * BIO_MAX_PAGES_KMALLOC); + return pages; +} + struct page_collect { struct exofs_sb_info *sbi; struct inode *inode; @@ -97,8 +108,7 @@ static void _pcol_reset(struct page_collect *pcol) static int pcol_try_alloc(struct page_collect *pcol) { - unsigned pages = min_t(unsigned, pcol->expected_pages, - MAX_PAGES_KMALLOC); + unsigned pages; if (!pcol->ios) { /* First time allocate io_state */ int ret = exofs_get_io_state(&pcol->sbi->layout, &pcol->ios); @@ -108,8 +118,7 @@ static int pcol_try_alloc(struct page_collect *pcol) } /* TODO: easily support bio chaining */ - pages = min_t(unsigned, pages, - pcol->sbi->layout.group_width * BIO_MAX_PAGES_KMALLOC); + pages = exofs_max_io_pages(&pcol->sbi->layout, pcol->expected_pages); for (; pages; pages >>= 1) { pcol->pages = kmalloc(pages * sizeof(struct page *), @@ -1049,6 +1058,7 @@ struct inode *exofs_iget(struct super_block *sb, unsigned long ino) memcpy(oi->i_data, fcb.i_data, sizeof(fcb.i_data)); } + inode->i_mapping->backing_dev_info = sb->s_bdi; if (S_ISREG(inode->i_mode)) { inode->i_op = &exofs_file_inode_operations; inode->i_fop = &exofs_file_operations; @@ -1149,6 +1159,7 @@ struct inode *exofs_new_inode(struct inode *dir, int mode) sbi = sb->s_fs_info; + inode->i_mapping->backing_dev_info = sb->s_bdi; sb->s_dirt = 1; inode_init_owner(inode, dir, mode); inode->i_ino = sbi->s_nextid++; diff --git a/fs/exofs/super.c b/fs/exofs/super.c index 78f5ad633d3b..e87510f4749e 100644 --- a/fs/exofs/super.c +++ b/fs/exofs/super.c @@ -390,6 +390,23 @@ static int _read_and_match_data_map(struct exofs_sb_info *sbi, unsigned numdevs, return 0; } +static unsigned __ra_pages(struct exofs_layout *layout) +{ + const unsigned _MIN_RA = 32; /* min 128K read-ahead */ + unsigned ra_pages = layout->group_width * layout->stripe_unit / + PAGE_SIZE; + unsigned max_io_pages = exofs_max_io_pages(layout, ~0); + + ra_pages *= 2; /* two stripes */ + if (ra_pages < _MIN_RA) + ra_pages = roundup(_MIN_RA, ra_pages / 2); + + if (ra_pages > max_io_pages) + ra_pages = max_io_pages; + + return ra_pages; +} + /* @odi is valid only as long as @fscb_dev is valid */ static int exofs_devs_2_odi(struct exofs_dt_device_info *dt_dev, struct osd_dev_info *odi) @@ -623,6 +640,7 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent) } /* set up operation vectors */ + sbi->bdi.ra_pages = __ra_pages(&sbi->layout); sb->s_bdi = &sbi->bdi; sb->s_fs_info = sbi; sb->s_op = &exofs_sops; -- cgit From 9ed96484311b89360b80a4181d856cbdb21630fd Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Mon, 31 Jan 2011 14:32:14 +0200 Subject: exofs: Add option to mount by osdname If /dev/osd* devices are shuffled because more devices where added, and/or login order has changed. It is hard to mount the FS you want. Add an option to mount by osdname. osdname is any osd-device's osdname as specified to the mkfs.exofs command when formatting the osd-devices. The new mount format is: OPT="osdname=$UUID0,pid=$PID,_netdev" mount -t exofs -o $OPT $DEV_OSD0 $MOUNTDIR if "osdname=" is specified in options above $DEV_OSD0 is ignored and can be empty. Also while at it: Removed some old unused Opt_* enums. Signed-off-by: Boaz Harrosh --- fs/exofs/super.c | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/exofs/super.c b/fs/exofs/super.c index e87510f4749e..474989eeb7d6 100644 --- a/fs/exofs/super.c +++ b/fs/exofs/super.c @@ -48,6 +48,7 @@ * struct to hold what we get from mount options */ struct exofs_mountopt { + bool is_osdname; const char *dev_name; uint64_t pid; int timeout; @@ -56,7 +57,7 @@ struct exofs_mountopt { /* * exofs-specific mount-time options. */ -enum { Opt_pid, Opt_to, Opt_mkfs, Opt_format, Opt_err }; +enum { Opt_name, Opt_pid, Opt_to, Opt_err }; /* * Our mount-time options. These should ideally be 64-bit unsigned, but the @@ -64,6 +65,7 @@ enum { Opt_pid, Opt_to, Opt_mkfs, Opt_format, Opt_err }; * sufficient for most applications now. */ static match_table_t tokens = { + {Opt_name, "osdname=%s"}, {Opt_pid, "pid=%u"}, {Opt_to, "to=%u"}, {Opt_err, NULL} @@ -94,6 +96,14 @@ static int parse_options(char *options, struct exofs_mountopt *opts) token = match_token(p, tokens, args); switch (token) { + case Opt_name: + opts->dev_name = match_strdup(&args[0]); + if (unlikely(!opts->dev_name)) { + EXOFS_ERR("Error allocating dev_name"); + return -ENOMEM; + } + opts->is_osdname = true; + break; case Opt_pid: if (0 == match_strlcpy(str, &args[0], sizeof(str))) return -EINVAL; @@ -575,9 +585,17 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent) goto free_bdi; /* use mount options to fill superblock */ - od = osduld_path_lookup(opts->dev_name); + if (opts->is_osdname) { + struct osd_dev_info odi = {.systemid_len = 0}; + + odi.osdname_len = strlen(opts->dev_name); + odi.osdname = (u8 *)opts->dev_name; + od = osduld_info_lookup(&odi); + } else { + od = osduld_path_lookup(opts->dev_name); + } if (IS_ERR(od)) { - ret = PTR_ERR(od); + ret = -EINVAL; goto free_sbi; } @@ -670,6 +688,8 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent) _exofs_print_device("Mounting", opts->dev_name, sbi->layout.s_ods[0], sbi->layout.s_pid); + if (opts->is_osdname) + kfree(opts->dev_name); return 0; free_sbi: @@ -678,6 +698,8 @@ free_bdi: EXOFS_ERR("Unable to mount exofs on %s pid=0x%llx err=%d\n", opts->dev_name, sbi->layout.s_pid, ret); exofs_free_sbi(sbi); + if (opts->is_osdname) + kfree(opts->dev_name); return ret; } @@ -695,7 +717,8 @@ static struct dentry *exofs_mount(struct file_system_type *type, if (ret) return ERR_PTR(ret); - opts.dev_name = dev_name; + if (!opts.dev_name) + opts.dev_name = dev_name; return mount_nodev(type, flags, &opts, exofs_fill_super); } -- cgit From 1cea312ad49d9cb964179a784fedb1fcfe396283 Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Thu, 3 Feb 2011 17:53:25 +0200 Subject: exofs: Write sbi->s_nextid as part of the Create command Before when creating a new inode, we'd set the sb->s_dirt flag, and sometime later the system would write out s_nextid as part of the sb_info. Also on inode sync we would force the sb sync as well. Define the s_nextid as a new partition attribute and set it every time we create a new object. At mount we read it from it's new place. We now never set sb->s_dirt anywhere in exofs. write_super is actually never called. The call to exofs_write_super from exofs_put_super is also removed because the VFS always calls ->sync_fs before calling ->put_super twice. To stay backward-and-forward compatible we also write the old s_nextid in the super_block object at unmount, and support zero length attribute on mount. This also fixes a BUG where in layouts when group_width was not a divisor of EXOFS_SUPER_ID (0x10000) the s_nextid was not read from the device it was written to. Because of the sliding window layout trick, and because the read was always done from the 0 device but the write was done via the raid engine that might slide the device view. Now we read and write through the raid engine. Signed-off-by: Boaz Harrosh --- fs/exofs/common.h | 18 +++++++- fs/exofs/exofs.h | 4 +- fs/exofs/file.c | 11 +---- fs/exofs/inode.c | 4 +- fs/exofs/super.c | 135 +++++++++++++++++++++++++++++++++++++++++++++++------- 5 files changed, 141 insertions(+), 31 deletions(-) (limited to 'fs') diff --git a/fs/exofs/common.h b/fs/exofs/common.h index f0d520312d8b..5e74ad3d4009 100644 --- a/fs/exofs/common.h +++ b/fs/exofs/common.h @@ -53,10 +53,14 @@ #define EXOFS_ROOT_ID 0x10002 /* object ID for root directory */ /* exofs Application specific page/attribute */ +/* Inode attrs */ # define EXOFS_APAGE_FS_DATA (OSD_APAGE_APP_DEFINED_FIRST + 3) # define EXOFS_ATTR_INODE_DATA 1 # define EXOFS_ATTR_INODE_FILE_LAYOUT 2 # define EXOFS_ATTR_INODE_DIR_LAYOUT 3 +/* Partition attrs */ +# define EXOFS_APAGE_SB_DATA (0xF0000000U + 3) +# define EXOFS_ATTR_SB_STATS 1 /* * The maximum number of files we can have is limited by the size of the @@ -86,8 +90,8 @@ enum { */ enum {EXOFS_FSCB_VER = 1, EXOFS_DT_VER = 1}; struct exofs_fscb { - __le64 s_nextid; /* Highest object ID used */ - __le64 s_numfiles; /* Number of files on fs */ + __le64 s_nextid; /* Only used after mkfs */ + __le64 s_numfiles; /* Only used after mkfs */ __le32 s_version; /* == EXOFS_FSCB_VER */ __le16 s_magic; /* Magic signature */ __le16 s_newfs; /* Non-zero if this is a new fs */ @@ -97,6 +101,16 @@ struct exofs_fscb { __le64 s_dev_table_count; /* == 0 means no dev_table */ } __packed; +/* + * This struct is set on the FS partition's attributes. + * [EXOFS_APAGE_SB_DATA, EXOFS_ATTR_SB_STATS] and is written together + * with the create command, to atomically persist the sb writeable information. + */ +struct exofs_sb_stats { + __le64 s_nextid; /* Highest object ID used */ + __le64 s_numfiles; /* Number of files on fs */ +} __packed; + /* * Describes the raid used in the FS. It is part of the device table. * This here is taken from the pNFS-objects definition. In exofs we diff --git a/fs/exofs/exofs.h b/fs/exofs/exofs.h index 99fcb9126a97..c965806c2821 100644 --- a/fs/exofs/exofs.h +++ b/fs/exofs/exofs.h @@ -77,7 +77,7 @@ struct exofs_layout { * our extension to the in-memory superblock */ struct exofs_sb_info { - struct exofs_fscb s_fscb; /* Written often, pre-allocate*/ + struct exofs_sb_stats s_ess; /* Written often, pre-allocate*/ int s_timeout; /* timeout for OSD operations */ uint64_t s_nextid; /* highest object ID used */ uint32_t s_numfiles; /* number of files on fs */ @@ -281,7 +281,7 @@ int exofs_set_link(struct inode *, struct exofs_dir_entry *, struct page *, struct inode *); /* super.c */ -int exofs_sync_fs(struct super_block *sb, int wait); +int exofs_sbi_write_stats(struct exofs_sb_info *sbi); /********************* * operation vectors * diff --git a/fs/exofs/file.c b/fs/exofs/file.c index 4c0d6bac9143..45ca323d8363 100644 --- a/fs/exofs/file.c +++ b/fs/exofs/file.c @@ -45,17 +45,8 @@ static int exofs_release_file(struct inode *inode, struct file *filp) static int exofs_file_fsync(struct file *filp, int datasync) { int ret; - struct inode *inode = filp->f_mapping->host; - struct super_block *sb; - - ret = sync_inode_metadata(inode, 1); - - /* This is a good place to write the sb */ - /* TODO: Sechedule an sb-sync on create */ - sb = inode->i_sb; - if (sb->s_dirt) - exofs_sync_fs(sb, 1); + ret = sync_inode_metadata(filp->f_mapping->host, 1); return ret; } diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c index 681b3cb9b4d8..0c713cfbebf0 100644 --- a/fs/exofs/inode.c +++ b/fs/exofs/inode.c @@ -1102,6 +1102,7 @@ int __exofs_wait_obj_created(struct exofs_i_info *oi) } return unlikely(is_bad_inode(&oi->vfs_inode)) ? -EIO : 0; } + /* * Callback function from exofs_new_inode(). The important thing is that we * set the obj_created flag so that other methods know that the object exists on @@ -1160,7 +1161,6 @@ struct inode *exofs_new_inode(struct inode *dir, int mode) sbi = sb->s_fs_info; inode->i_mapping->backing_dev_info = sb->s_bdi; - sb->s_dirt = 1; inode_init_owner(inode, dir, mode); inode->i_ino = sbi->s_nextid++; inode->i_blkbits = EXOFS_BLKSHIFT; @@ -1171,6 +1171,8 @@ struct inode *exofs_new_inode(struct inode *dir, int mode) spin_unlock(&sbi->s_next_gen_lock); insert_inode_hash(inode); + exofs_sbi_write_stats(sbi); /* Make sure new sbi->s_nextid is on disk */ + mark_inode_dirty(inode); ret = exofs_get_io_state(&sbi->layout, &ios); diff --git a/fs/exofs/super.c b/fs/exofs/super.c index 474989eeb7d6..5eb0851e5481 100644 --- a/fs/exofs/super.c +++ b/fs/exofs/super.c @@ -213,6 +213,101 @@ static void destroy_inodecache(void) static const struct super_operations exofs_sops; static const struct export_operations exofs_export_ops; +static const struct osd_attr g_attr_sb_stats = ATTR_DEF( + EXOFS_APAGE_SB_DATA, + EXOFS_ATTR_SB_STATS, + sizeof(struct exofs_sb_stats)); + +static int __sbi_read_stats(struct exofs_sb_info *sbi) +{ + struct osd_attr attrs[] = { + [0] = g_attr_sb_stats, + }; + struct exofs_io_state *ios; + int ret; + + ret = exofs_get_io_state(&sbi->layout, &ios); + if (unlikely(ret)) { + EXOFS_ERR("%s: exofs_get_io_state failed.\n", __func__); + return ret; + } + + ios->cred = sbi->s_cred; + + ios->in_attr = attrs; + ios->in_attr_len = ARRAY_SIZE(attrs); + + ret = exofs_sbi_read(ios); + if (unlikely(ret)) { + EXOFS_ERR("Error reading super_block stats => %d\n", ret); + goto out; + } + + ret = extract_attr_from_ios(ios, &attrs[0]); + if (ret) { + EXOFS_ERR("%s: extract_attr of sb_stats failed\n", __func__); + goto out; + } + if (attrs[0].len) { + struct exofs_sb_stats *ess; + + if (unlikely(attrs[0].len != sizeof(*ess))) { + EXOFS_ERR("%s: Wrong version of exofs_sb_stats " + "size(%d) != expected(%zd)\n", + __func__, attrs[0].len, sizeof(*ess)); + goto out; + } + + ess = attrs[0].val_ptr; + sbi->s_nextid = le64_to_cpu(ess->s_nextid); + sbi->s_numfiles = le32_to_cpu(ess->s_numfiles); + } + +out: + exofs_put_io_state(ios); + return ret; +} + +static void stats_done(struct exofs_io_state *ios, void *p) +{ + exofs_put_io_state(ios); + /* Good thanks nothing to do anymore */ +} + +/* Asynchronously write the stats attribute */ +int exofs_sbi_write_stats(struct exofs_sb_info *sbi) +{ + struct osd_attr attrs[] = { + [0] = g_attr_sb_stats, + }; + struct exofs_io_state *ios; + int ret; + + ret = exofs_get_io_state(&sbi->layout, &ios); + if (unlikely(ret)) { + EXOFS_ERR("%s: exofs_get_io_state failed.\n", __func__); + return ret; + } + + sbi->s_ess.s_nextid = cpu_to_le64(sbi->s_nextid); + sbi->s_ess.s_numfiles = cpu_to_le64(sbi->s_numfiles); + attrs[0].val_ptr = &sbi->s_ess; + + ios->cred = sbi->s_cred; + ios->done = stats_done; + ios->private = sbi; + ios->out_attr = attrs; + ios->out_attr_len = ARRAY_SIZE(attrs); + + ret = exofs_sbi_write(ios); + if (unlikely(ret)) { + EXOFS_ERR("%s: exofs_sbi_write failed.\n", __func__); + exofs_put_io_state(ios); + } + + return ret; +} + /* * Write the superblock to the OSD */ @@ -223,18 +318,25 @@ int exofs_sync_fs(struct super_block *sb, int wait) struct exofs_io_state *ios; int ret = -ENOMEM; - lock_super(sb); + fscb = kmalloc(sizeof(*fscb), GFP_KERNEL); + if (unlikely(!fscb)) + return -ENOMEM; + sbi = sb->s_fs_info; - fscb = &sbi->s_fscb; + /* NOTE: We no longer dirty the super_block anywhere in exofs. The + * reason we write the fscb here on unmount is so we can stay backwards + * compatible with fscb->s_version == 1. (What we are not compatible + * with is if a new version FS crashed and then we try to mount an old + * version). Otherwise the exofs_fscb is read-only from mkfs time. All + * the writeable info is set in exofs_sbi_write_stats() above. + */ ret = exofs_get_io_state(&sbi->layout, &ios); - if (ret) + if (unlikely(ret)) goto out; - /* Note: We only write the changing part of the fscb. .i.e upto the - * the fscb->s_dev_table_oid member. There is no read-modify-write - * here. - */ + lock_super(sb); + ios->length = offsetof(struct exofs_fscb, s_dev_table_oid); memset(fscb, 0, ios->length); fscb->s_nextid = cpu_to_le64(sbi->s_nextid); @@ -249,16 +351,17 @@ int exofs_sync_fs(struct super_block *sb, int wait) ios->cred = sbi->s_cred; ret = exofs_sbi_write(ios); - if (unlikely(ret)) { + if (unlikely(ret)) EXOFS_ERR("%s: exofs_sbi_write failed.\n", __func__); - goto out; - } - sb->s_dirt = 0; + else + sb->s_dirt = 0; + + unlock_super(sb); out: EXOFS_DBGMSG("s_nextid=0x%llx ret=%d\n", _LLU(sbi->s_nextid), ret); exofs_put_io_state(ios); - unlock_super(sb); + kfree(fscb); return ret; } @@ -302,9 +405,6 @@ static void exofs_put_super(struct super_block *sb) int num_pend; struct exofs_sb_info *sbi = sb->s_fs_info; - if (sb->s_dirt) - exofs_write_super(sb); - /* make sure there are no pending commands */ for (num_pend = atomic_read(&sbi->s_curr_pending); num_pend > 0; num_pend = atomic_read(&sbi->s_curr_pending)) { @@ -629,6 +729,7 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent) goto free_sbi; sb->s_magic = le16_to_cpu(fscb.s_magic); + /* NOTE: we read below to be backward compatible with old versions */ sbi->s_nextid = le64_to_cpu(fscb.s_nextid); sbi->s_numfiles = le32_to_cpu(fscb.s_numfiles); @@ -639,7 +740,7 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent) ret = -EINVAL; goto free_sbi; } - if (le32_to_cpu(fscb.s_version) != EXOFS_FSCB_VER) { + if (le32_to_cpu(fscb.s_version) > EXOFS_FSCB_VER) { EXOFS_ERR("ERROR: Bad FSCB version expected-%d got-%d\n", EXOFS_FSCB_VER, le32_to_cpu(fscb.s_version)); ret = -EINVAL; @@ -657,6 +758,8 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent) goto free_sbi; } + __sbi_read_stats(sbi); + /* set up operation vectors */ sbi->bdi.ra_pages = __ra_pages(&sbi->layout); sb->s_bdi = &sbi->bdi; -- cgit From a49fb4c3d035ab516507b31ec3bd49263caee14d Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Mon, 7 Feb 2011 18:12:15 +0200 Subject: exofs: deprecate the commands pending counter One leftover from the days of IBM's original code, is an SB counter that counts in-flight asynchronous commands. And a piece of code that waits for the counter to reach zero at unmount. I guess it might have been needed then, cause of some reference missing or something. I'm not removing it yet but am putting a warning message if ever this counter triggers at unmount. If I'll never see it triggers or reported I'll remove the counter for good. (I had this print as a debug output for a long time and never had it trigger) Signed-off-by: Boaz Harrosh --- fs/exofs/super.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'fs') diff --git a/fs/exofs/super.c b/fs/exofs/super.c index 5eb0851e5481..06065bd37fc3 100644 --- a/fs/exofs/super.c +++ b/fs/exofs/super.c @@ -409,6 +409,10 @@ static void exofs_put_super(struct super_block *sb) for (num_pend = atomic_read(&sbi->s_curr_pending); num_pend > 0; num_pend = atomic_read(&sbi->s_curr_pending)) { wait_queue_head_t wq; + + printk(KERN_NOTICE "%s: !!Pending operations in flight. " + "This is a BUG. please report to osd-dev@open-osd.org\n", + __func__); init_waitqueue_head(&wq); wait_event_timeout(wq, (atomic_read(&sbi->s_curr_pending) == 0), -- cgit From 09adc80c611bb8902daa8ccfe34dbbc009d6befe Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 4 Feb 2011 21:38:47 -0800 Subject: ceph: preserve I_COMPLETE across rename d_move puts the renamed dentry at the end of d_subdirs, screwing with our cached dentry directory offsets. We were just clearing I_COMPLETE to avoid any possibility of trouble. However, assigning the renamed dentry an offset at the end of the directory (to match it's new d_subdirs position) is sufficient to maintain correct behavior and hold onto I_COMPLETE. This is especially important for workloads like rsync, which renames files into place. Before, we would lose I_COMPLETE and do MDS lookups for each file. With this patch we only talk to the MDS on create and rename. Signed-off-by: Sage Weil --- fs/ceph/inode.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'fs') diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 193bfa5e9cbd..60456361e07d 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -1030,9 +1030,6 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, dout("fill_trace doing d_move %p -> %p\n", req->r_old_dentry, dn); - /* d_move screws up d_subdirs order */ - ceph_i_clear(dir, CEPH_I_COMPLETE); - d_move(req->r_old_dentry, dn); dout(" src %p '%.*s' dst %p '%.*s'\n", req->r_old_dentry, @@ -1044,12 +1041,15 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, rehashing bug in vfs_rename_dir */ ceph_invalidate_dentry_lease(dn); - /* take overwritten dentry's readdir offset */ - dout("dn %p gets %p offset %lld (old offset %lld)\n", - req->r_old_dentry, dn, ceph_dentry(dn)->offset, + /* + * d_move() puts the renamed dentry at the end of + * d_subdirs. We need to assign it an appropriate + * directory offset so we can behave when holding + * I_COMPLETE. + */ + ceph_set_dentry_offset(req->r_old_dentry); + dout("dn %p gets new offset %lld\n", req->r_old_dentry, ceph_dentry(req->r_old_dentry)->offset); - ceph_dentry(req->r_old_dentry)->offset = - ceph_dentry(dn)->offset; dn = req->r_old_dentry; /* use old_dentry */ in = dn->d_inode; -- cgit From 44cff8a9ee8a974f9e931df910688e7fc1f0b0f9 Mon Sep 17 00:00:00 2001 From: Phillip Lougher Date: Tue, 15 Mar 2011 22:09:55 +0000 Subject: Squashfs: handle corruption of directory structure Handle the rare case where a directory metadata block is uncompressed and corrupted, leading to a kernel oops in directory scanning (memcpy). Normally corruption is detected at the decompression stage and dealt with then, however, this will not happen if: - metadata isn't compressed (users can optionally request no metadata compression), or - the compressed metadata block was larger than the original, in which case the uncompressed version was used, or - the data was corrupt after decompression This patch fixes this by adding some sanity checks against known maximum values. Signed-off-by: Phillip Lougher --- fs/squashfs/dir.c | 9 +++++++++ fs/squashfs/namei.c | 12 ++++++++++++ 2 files changed, 21 insertions(+) (limited to 'fs') diff --git a/fs/squashfs/dir.c b/fs/squashfs/dir.c index 0dc340aa2be9..3f79cd1d0c19 100644 --- a/fs/squashfs/dir.c +++ b/fs/squashfs/dir.c @@ -172,6 +172,11 @@ static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) length += sizeof(dirh); dir_count = le32_to_cpu(dirh.count) + 1; + + /* dir_count should never be larger than 256 */ + if (dir_count > 256) + goto failed_read; + while (dir_count--) { /* * Read directory entry. @@ -183,6 +188,10 @@ static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) size = le16_to_cpu(dire->size) + 1; + /* size should never be larger than SQUASHFS_NAME_LEN */ + if (size > SQUASHFS_NAME_LEN) + goto failed_read; + err = squashfs_read_metadata(inode->i_sb, dire->name, &block, &offset, size); if (err < 0) diff --git a/fs/squashfs/namei.c b/fs/squashfs/namei.c index 7a9464d08cf6..5d922a6701ab 100644 --- a/fs/squashfs/namei.c +++ b/fs/squashfs/namei.c @@ -176,6 +176,11 @@ static struct dentry *squashfs_lookup(struct inode *dir, struct dentry *dentry, length += sizeof(dirh); dir_count = le32_to_cpu(dirh.count) + 1; + + /* dir_count should never be larger than 256 */ + if (dir_count > 256) + goto data_error; + while (dir_count--) { /* * Read directory entry. @@ -187,6 +192,10 @@ static struct dentry *squashfs_lookup(struct inode *dir, struct dentry *dentry, size = le16_to_cpu(dire->size) + 1; + /* size should never be larger than SQUASHFS_NAME_LEN */ + if (size > SQUASHFS_NAME_LEN) + goto data_error; + err = squashfs_read_metadata(dir->i_sb, dire->name, &block, &offset, size); if (err < 0) @@ -228,6 +237,9 @@ exit_lookup: d_add(dentry, inode); return ERR_PTR(0); +data_error: + err = -EIO; + read_failure: ERROR("Unable to read directory block [%llx:%x]\n", squashfs_i(dir)->start + msblk->directory_table, -- cgit From d2b217439fd1d8f7857175f063113f4d1d66306c Mon Sep 17 00:00:00 2001 From: Mi Jinlong Date: Thu, 10 Mar 2011 17:43:37 +0800 Subject: nfs41: make sure nfs server return right ca_maxresponsesize_cached According to rfc5661, ca_maxresponsesize_cached: Like ca_maxresponsesize, but the maximum size of a reply that will be stored in the reply cache (Section 2.10.6.1). For each channel, the server MAY decrease this value, but MUST NOT increase it. the latest kernel(2.6.38-rc8) may increase the value for ignoring request's ca_maxresponsesize_cached value. We should not ignore it. Signed-off-by: Mi Jinlong Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4state.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index c26dc31fb943..a20827804c50 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -608,7 +608,8 @@ static void init_forechannel_attrs(struct nfsd4_channel_attrs *new, struct nfsd4 u32 maxrpc = nfsd_serv->sv_max_mesg; new->maxreqs = numslots; - new->maxresp_cached = slotsize + NFSD_MIN_HDR_SEQ_SZ; + new->maxresp_cached = min_t(u32, req->maxresp_cached, + slotsize + NFSD_MIN_HDR_SEQ_SZ); new->maxreq_sz = min_t(u32, req->maxreq_sz, maxrpc); new->maxresp_sz = min_t(u32, req->maxresp_sz, maxrpc); new->maxops = min_t(u32, req->maxops, NFSD_MAX_OPS_PER_COMPOUND); -- cgit From 688f869ce3bdc892daa993534dc6df18c95df931 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Wed, 16 Mar 2011 17:16:31 -0400 Subject: ext4: Initialize fsync transaction ids in ext4_new_inode() When allocating a new inode, we need to make sure i_sync_tid and i_datasync_tid are initialized. Otherwise, one or both of these two values could be left initialized to zero, which could potentially result in BUG_ON in jbd2_journal_commit_transaction. (This could happen by having journal->commit_request getting set to zero, which could wake up the kjournald process even though there is no running transaction, which then causes a BUG_ON via the J_ASSERT(j_ruinning_transaction != NULL) statement. Signed-off-by: "Theodore Ts'o" --- fs/ext4/ialloc.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'fs') diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 2fd3b0e41787..a679a482c986 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -1054,6 +1054,11 @@ got: } } + if (ext4_handle_valid(handle)) { + ei->i_sync_tid = handle->h_transaction->t_tid; + ei->i_datasync_tid = handle->h_transaction->t_tid; + } + err = ext4_mark_inode_dirty(handle, inode); if (err) { ext4_std_error(sb, err); -- cgit From 4ee2491ed8569f370bf4c1a4c046a6efb8032bd2 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 17 Mar 2011 10:51:40 +0100 Subject: fs: make fsync_buffers_list() plug It used WRITE_SYNC_PLUG before and potentially submits a batch of IO, so lets enable plugging for this case. Signed-off-by: Jens Axboe --- fs/buffer.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'fs') diff --git a/fs/buffer.c b/fs/buffer.c index 42534f67d71b..2e6b1a387b7e 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -743,8 +743,10 @@ static int fsync_buffers_list(spinlock_t *lock, struct list_head *list) struct list_head tmp; struct address_space *mapping; int err = 0, err2; + struct blk_plug plug; INIT_LIST_HEAD(&tmp); + blk_start_plug(&plug); spin_lock(lock); while (!list_empty(list)) { @@ -781,6 +783,10 @@ static int fsync_buffers_list(spinlock_t *lock, struct list_head *list) } } + spin_unlock(lock); + blk_finish_plug(&plug); + spin_lock(lock); + while (!list_empty(&tmp)) { bh = BH_ENTRY(tmp.prev); get_bh(bh); -- cgit From 65ab80279d7c323ce151e858d951e2684df72a97 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 17 Mar 2011 10:56:45 +0100 Subject: jbd: finish conversion from WRITE_SYNC_PLUG to WRITE_SYNC and explicit plugging 'write_op' was still used, even though it was always WRITE_SYNC now. Add plugging around the cases where it submits IO, and flush them before we end up waiting for that IO. Signed-off-by: Jens Axboe --- fs/jbd/commit.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'fs') diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index 66be299acb1b..da871ee084d3 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c @@ -20,6 +20,7 @@ #include #include #include +#include /* * Default IO end handler for temporary BJ_IO buffer_heads. @@ -294,7 +295,7 @@ void journal_commit_transaction(journal_t *journal) int first_tag = 0; int tag_flag; int i; - int write_op = WRITE_SYNC; + struct blk_plug plug; /* * First job: lock down the current transaction and wait for @@ -327,13 +328,6 @@ void journal_commit_transaction(journal_t *journal) spin_lock(&journal->j_state_lock); commit_transaction->t_state = T_LOCKED; - /* - * Use plugged writes here, since we want to submit several before - * we unplug the device. We don't do explicit unplugging in here, - * instead we rely on sync_buffer() doing the unplug for us. - */ - if (commit_transaction->t_synchronous_commit) - write_op = WRITE_SYNC; spin_lock(&commit_transaction->t_handle_lock); while (commit_transaction->t_updates) { DEFINE_WAIT(wait); @@ -418,8 +412,10 @@ void journal_commit_transaction(journal_t *journal) * Now start flushing things to disk, in the order they appear * on the transaction lists. Data blocks go first. */ + blk_start_plug(&plug); err = journal_submit_data_buffers(journal, commit_transaction, - write_op); + WRITE_SYNC); + blk_finish_plug(&plug); /* * Wait for all previously submitted IO to complete. @@ -480,7 +476,9 @@ void journal_commit_transaction(journal_t *journal) err = 0; } - journal_write_revoke_records(journal, commit_transaction, write_op); + blk_start_plug(&plug); + + journal_write_revoke_records(journal, commit_transaction, WRITE_SYNC); /* * If we found any dirty or locked buffers, then we should have @@ -650,7 +648,7 @@ start_journal_io: clear_buffer_dirty(bh); set_buffer_uptodate(bh); bh->b_end_io = journal_end_buffer_io_sync; - submit_bh(write_op, bh); + submit_bh(WRITE_SYNC, bh); } cond_resched(); @@ -661,6 +659,8 @@ start_journal_io: } } + blk_finish_plug(&plug); + /* Lo and behold: we have just managed to send a transaction to the log. Before we can commit it, wait for the IO so far to complete. Control buffers being written are on the -- cgit From 82f04ab47e1d94d78503591a7460b2cad9601ede Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 17 Mar 2011 11:01:52 +0100 Subject: jbd2: finish conversion from WRITE_SYNC_PLUG to WRITE_SYNC and explicit plugging 'write_op' was still used, even though it was always WRITE_SYNC now. Add plugging around the cases where it submits IO, and flush them before we end up waiting for that IO. Signed-off-by: Jens Axboe --- fs/jbd2/commit.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'fs') diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 3da1cc4346d5..fa36d7662b21 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c @@ -329,7 +329,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) int tag_bytes = journal_tag_bytes(journal); struct buffer_head *cbh = NULL; /* For transactional checksums */ __u32 crc32_sum = ~0; - int write_op = WRITE_SYNC; + struct blk_plug plug; /* * First job: lock down the current transaction and wait for @@ -363,13 +363,6 @@ void jbd2_journal_commit_transaction(journal_t *journal) write_lock(&journal->j_state_lock); commit_transaction->t_state = T_LOCKED; - /* - * Use plugged writes here, since we want to submit several before - * we unplug the device. We don't do explicit unplugging in here, - * instead we rely on sync_buffer() doing the unplug for us. - */ - if (commit_transaction->t_synchronous_commit) - write_op = WRITE_SYNC; trace_jbd2_commit_locking(journal, commit_transaction); stats.run.rs_wait = commit_transaction->t_max_wait; stats.run.rs_locked = jiffies; @@ -469,8 +462,10 @@ void jbd2_journal_commit_transaction(journal_t *journal) if (err) jbd2_journal_abort(journal, err); + blk_start_plug(&plug); jbd2_journal_write_revoke_records(journal, commit_transaction, - write_op); + WRITE_SYNC); + blk_finish_plug(&plug); jbd_debug(3, "JBD: commit phase 2\n"); @@ -497,6 +492,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) err = 0; descriptor = NULL; bufs = 0; + blk_start_plug(&plug); while (commit_transaction->t_buffers) { /* Find the next buffer to be journaled... */ @@ -658,7 +654,7 @@ start_journal_io: clear_buffer_dirty(bh); set_buffer_uptodate(bh); bh->b_end_io = journal_end_buffer_io_sync; - submit_bh(write_op, bh); + submit_bh(WRITE_SYNC, bh); } cond_resched(); stats.run.rs_blocks_logged += bufs; @@ -699,6 +695,8 @@ start_journal_io: __jbd2_journal_abort_hard(journal); } + blk_finish_plug(&plug); + /* Lo and behold: we have just managed to send a transaction to the log. Before we can commit it, wait for the IO so far to complete. Control buffers being written are on the -- cgit From a91a2785b200864aef2270ed6a3babac7a253a20 Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Thu, 17 Mar 2011 11:11:05 +0100 Subject: block: Require subsystems to explicitly allocate bio_set integrity mempool MD and DM create a new bio_set for every metadevice. Each bio_set has an integrity mempool attached regardless of whether the metadevice is capable of passing integrity metadata. This is a waste of memory. Instead we defer the allocation decision to MD and DM since we know at metadevice creation time whether integrity passthrough is needed or not. Automatic integrity mempool allocation can then be removed from bioset_create() and we make an explicit integrity allocation for the fs_bio_set. Signed-off-by: Martin K. Petersen Reported-by: Zdenek Kabelac Acked-by: Mike Snitzer Signed-off-by: Jens Axboe --- fs/bio-integrity.c | 3 +++ fs/bio.c | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/bio-integrity.c b/fs/bio-integrity.c index e49cce234c65..9c5e6b2cd11a 100644 --- a/fs/bio-integrity.c +++ b/fs/bio-integrity.c @@ -761,6 +761,9 @@ int bioset_integrity_create(struct bio_set *bs, int pool_size) { unsigned int max_slab = vecs_to_idx(BIO_MAX_PAGES); + if (bs->bio_integrity_pool) + return 0; + bs->bio_integrity_pool = mempool_create_slab_pool(pool_size, bip_slab[max_slab].slab); diff --git a/fs/bio.c b/fs/bio.c index 5694b756ed01..85e2eabb1f81 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -1636,9 +1636,6 @@ struct bio_set *bioset_create(unsigned int pool_size, unsigned int front_pad) if (!bs->bio_pool) goto bad; - if (bioset_integrity_create(bs, pool_size)) - goto bad; - if (!biovec_create_pools(bs, pool_size)) return bs; @@ -1682,6 +1679,9 @@ static int __init init_bio(void) if (!fs_bio_set) panic("bio: can't allocate bios\n"); + if (bioset_integrity_create(fs_bio_set, BIO_POOL_SIZE)) + panic("bio: can't create integrity pool\n"); + bio_split_pool = mempool_create_kmalloc_pool(BIO_SPLIT_ENTRIES, sizeof(struct bio_pair)); if (!bio_split_pool) -- cgit From 95f28604a65b1c40b6c6cd95e58439cd7ded3add Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 17 Mar 2011 11:13:12 +0100 Subject: fs: assign sb->s_bdi to default_backing_dev_info if the bdi is going away We don't have proper reference counting for this yet, so we run into cases where the device is pulled and we OOPS on flushing the fs data. This happens even though the dirty inodes have already been migrated to the default_backing_dev_info. Reported-by: Torsten Hilbrich Tested-by: Torsten Hilbrich Cc: stable@kernel.org Signed-off-by: Jens Axboe --- fs/super.c | 2 ++ fs/sync.c | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/super.c b/fs/super.c index 7e9dd4cc2c01..0d89e93f654e 100644 --- a/fs/super.c +++ b/fs/super.c @@ -71,6 +71,7 @@ static struct super_block *alloc_super(struct file_system_type *type) #else INIT_LIST_HEAD(&s->s_files); #endif + s->s_bdi = &default_backing_dev_info; INIT_LIST_HEAD(&s->s_instances); INIT_HLIST_BL_HEAD(&s->s_anon); INIT_LIST_HEAD(&s->s_inodes); @@ -1003,6 +1004,7 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void } BUG_ON(!mnt->mnt_sb); WARN_ON(!mnt->mnt_sb->s_bdi); + WARN_ON(mnt->mnt_sb->s_bdi == &default_backing_dev_info); mnt->mnt_sb->s_flags |= MS_BORN; error = security_sb_kern_mount(mnt->mnt_sb, flags, secdata); diff --git a/fs/sync.c b/fs/sync.c index ba76b9623e7e..412dc89163d3 100644 --- a/fs/sync.c +++ b/fs/sync.c @@ -33,7 +33,7 @@ static int __sync_filesystem(struct super_block *sb, int wait) * This should be safe, as we require bdi backing to actually * write out data in the first place */ - if (!sb->s_bdi || sb->s_bdi == &noop_backing_dev_info) + if (sb->s_bdi == &noop_backing_dev_info) return 0; if (sb->s_qcop && sb->s_qcop->quota_sync) @@ -79,7 +79,7 @@ EXPORT_SYMBOL_GPL(sync_filesystem); static void sync_one_sb(struct super_block *sb, void *arg) { - if (!(sb->s_flags & MS_RDONLY) && sb->s_bdi) + if (!(sb->s_flags & MS_RDONLY)) __sync_filesystem(sb, *(int *)arg); } /* -- cgit From 0ccd234ca04b09a156f8771af316ac9de2fa7312 Mon Sep 17 00:00:00 2001 From: matt mooney Date: Fri, 14 Jan 2011 06:12:35 -0800 Subject: fs: change to new flag variable Replace EXTRA_CFLAGS with ccflags-y. And change ntfs-objs to ntfs-y for cleaner conditional inclusion. Signed-off-by: matt mooney Acked-by: WANG Cong Signed-off-by: Michal Marek --- fs/affs/Makefile | 2 +- fs/coda/Makefile | 2 +- fs/gfs2/Makefile | 2 +- fs/jfs/Makefile | 2 +- fs/ncpfs/Makefile | 2 +- fs/ntfs/Makefile | 19 +++++++------------ fs/ocfs2/Makefile | 4 ++-- fs/ocfs2/dlm/Makefile | 2 +- fs/ocfs2/dlmfs/Makefile | 2 +- fs/reiserfs/Makefile | 4 +--- fs/xfs/Makefile | 7 ++----- 11 files changed, 19 insertions(+), 29 deletions(-) (limited to 'fs') diff --git a/fs/affs/Makefile b/fs/affs/Makefile index b2c4f54446f3..3988b4a78339 100644 --- a/fs/affs/Makefile +++ b/fs/affs/Makefile @@ -2,7 +2,7 @@ # Makefile for the Linux affs filesystem routines. # -#EXTRA_CFLAGS=-DDEBUG=1 +#ccflags-y := -DDEBUG=1 obj-$(CONFIG_AFFS_FS) += affs.o diff --git a/fs/coda/Makefile b/fs/coda/Makefile index 6c22e61da397..1bab69a0d347 100644 --- a/fs/coda/Makefile +++ b/fs/coda/Makefile @@ -9,4 +9,4 @@ coda-objs := psdev.o cache.o cnode.o inode.o dir.o file.o upcall.o \ # If you want debugging output, please uncomment the following line. -# EXTRA_CFLAGS += -DDEBUG -DDEBUG_SMB_MALLOC=1 +# ccflags-y := -DDEBUG -DDEBUG_SMB_MALLOC=1 diff --git a/fs/gfs2/Makefile b/fs/gfs2/Makefile index 21f7e46da4c0..f3d23ef4e876 100644 --- a/fs/gfs2/Makefile +++ b/fs/gfs2/Makefile @@ -1,4 +1,4 @@ -EXTRA_CFLAGS := -I$(src) +ccflags-y := -I$(src) obj-$(CONFIG_GFS2_FS) += gfs2.o gfs2-y := acl.o bmap.o dir.o xattr.o glock.o \ glops.o inode.o log.o lops.o main.o meta_io.o \ diff --git a/fs/jfs/Makefile b/fs/jfs/Makefile index 3adb6395e42d..a58fa72d7e59 100644 --- a/fs/jfs/Makefile +++ b/fs/jfs/Makefile @@ -13,4 +13,4 @@ jfs-y := super.o file.o inode.o namei.o jfs_mount.o jfs_umount.o \ jfs-$(CONFIG_JFS_POSIX_ACL) += acl.o -EXTRA_CFLAGS += -D_JFS_4K +ccflags-y := -D_JFS_4K diff --git a/fs/ncpfs/Makefile b/fs/ncpfs/Makefile index 68ea095100a8..c66af563f2ce 100644 --- a/fs/ncpfs/Makefile +++ b/fs/ncpfs/Makefile @@ -11,6 +11,6 @@ ncpfs-$(CONFIG_NCPFS_EXTRAS) += symlink.o ncpfs-$(CONFIG_NCPFS_NFS_NS) += symlink.o # If you want debugging output, please uncomment the following line -# EXTRA_CFLAGS += -DDEBUG_NCP=1 +# ccflags-y := -DDEBUG_NCP=1 CFLAGS_ncplib_kernel.o := -finline-functions diff --git a/fs/ntfs/Makefile b/fs/ntfs/Makefile index 4ff028fcfd6e..30206b238433 100644 --- a/fs/ntfs/Makefile +++ b/fs/ntfs/Makefile @@ -2,18 +2,13 @@ obj-$(CONFIG_NTFS_FS) += ntfs.o -ntfs-objs := aops.o attrib.o collate.o compress.o debug.o dir.o file.o \ - index.o inode.o mft.o mst.o namei.o runlist.o super.o sysctl.o \ - unistr.o upcase.o +ntfs-y := aops.o attrib.o collate.o compress.o debug.o dir.o file.o \ + index.o inode.o mft.o mst.o namei.o runlist.o super.o sysctl.o \ + unistr.o upcase.o -EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.30\" +ntfs-$(CONFIG_NTFS_RW) += bitmap.o lcnalloc.o logfile.o quota.o usnjrnl.o -ifeq ($(CONFIG_NTFS_DEBUG),y) -EXTRA_CFLAGS += -DDEBUG -endif +ccflags-y := -DNTFS_VERSION=\"2.1.30\" +ccflags-$(CONFIG_NTFS_DEBUG) += -DDEBUG +ccflags-$(CONFIG_NTFS_RW) += -DNTFS_RW -ifeq ($(CONFIG_NTFS_RW),y) -EXTRA_CFLAGS += -DNTFS_RW - -ntfs-objs += bitmap.o lcnalloc.o logfile.o quota.o usnjrnl.o -endif diff --git a/fs/ocfs2/Makefile b/fs/ocfs2/Makefile index 07d9fd854350..d8a0313e99e6 100644 --- a/fs/ocfs2/Makefile +++ b/fs/ocfs2/Makefile @@ -1,6 +1,6 @@ -EXTRA_CFLAGS += -Ifs/ocfs2 +ccflags-y := -Ifs/ocfs2 -EXTRA_CFLAGS += -DCATCH_BH_JBD_RACES +ccflags-y += -DCATCH_BH_JBD_RACES obj-$(CONFIG_OCFS2_FS) += \ ocfs2.o \ diff --git a/fs/ocfs2/dlm/Makefile b/fs/ocfs2/dlm/Makefile index dcebf0d920fa..c8a044efbb15 100644 --- a/fs/ocfs2/dlm/Makefile +++ b/fs/ocfs2/dlm/Makefile @@ -1,4 +1,4 @@ -EXTRA_CFLAGS += -Ifs/ocfs2 +ccflags-y := -Ifs/ocfs2 obj-$(CONFIG_OCFS2_FS_O2CB) += ocfs2_dlm.o diff --git a/fs/ocfs2/dlmfs/Makefile b/fs/ocfs2/dlmfs/Makefile index df69b4856d0d..f14be89a6701 100644 --- a/fs/ocfs2/dlmfs/Makefile +++ b/fs/ocfs2/dlmfs/Makefile @@ -1,4 +1,4 @@ -EXTRA_CFLAGS += -Ifs/ocfs2 +ccflags-y := -Ifs/ocfs2 obj-$(CONFIG_OCFS2_FS) += ocfs2_dlmfs.o diff --git a/fs/reiserfs/Makefile b/fs/reiserfs/Makefile index 792b3cb2cd18..3c3b00165114 100644 --- a/fs/reiserfs/Makefile +++ b/fs/reiserfs/Makefile @@ -31,9 +31,7 @@ endif # and causing a panic. Since this behavior only affects ppc32, this ifeq # will work around it. If any other architecture displays this behavior, # add it here. -ifeq ($(CONFIG_PPC32),y) -EXTRA_CFLAGS := $(call cc-ifversion, -lt, 0400, -O1) -endif +ccflags-$(CONFIG_PPC32) := $(call cc-ifversion, -lt, 0400, -O1) TAGS: etags *.c diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index faca44997099..82b1371775c0 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -16,14 +16,11 @@ # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # -EXTRA_CFLAGS += -I$(src) -I$(src)/linux-2.6 +ccflags-y := -I$(src) -I$(src)/linux-2.6 +ccflags-$(CONFIG_XFS_DEBUG) += -g XFS_LINUX := linux-2.6 -ifeq ($(CONFIG_XFS_DEBUG),y) - EXTRA_CFLAGS += -g -endif - obj-$(CONFIG_XFS_FS) += xfs.o xfs-y += linux-2.6/xfs_trace.o -- cgit From 9ae78bcc000168251f893b1bf92a848308187695 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Thu, 17 Mar 2011 12:52:33 -0400 Subject: nfsd4: fix comment and remove unused nfsd4_file fields A couple fields here were left over from a previous version of a patch, and are no longer used. Signed-off-by: J. Bruce Fields --- fs/nfsd/state.h | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'fs') diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 2d31224b07bf..6bd2f3c21f2b 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -367,16 +367,12 @@ struct nfs4_file { struct list_head fi_delegations; /* One each for O_RDONLY, O_WRONLY, O_RDWR: */ struct file * fi_fds[3]; - /* One each for O_RDONLY, O_WRONLY: */ - atomic_t fi_access[2]; /* - * Each open stateid contributes 1 to either fi_readers or - * fi_writers, or both, depending on the open mode. A - * delegation also takes an fi_readers reference. Lock - * stateid's take none. + * Each open or lock stateid contributes 1 to either + * fi_access[O_RDONLY], fi_access[O_WRONLY], or both, depending + * on open or lock mode: */ - atomic_t fi_readers; - atomic_t fi_writers; + atomic_t fi_access[2]; struct file *fi_deleg_file; struct file_lock *fi_lease; atomic_t fi_delegees; -- cgit From 5a02ab7c3c4580f94d13c683721039855b67cda6 Mon Sep 17 00:00:00 2001 From: Mi Jinlong Date: Fri, 11 Mar 2011 12:13:55 +0800 Subject: nfsd: wrong index used in inner loop We must not use dummy for index. After the first index, READ32(dummy) will change dummy!!!! Signed-off-by: Mi Jinlong [bfields@redhat.com: Trond points out READ_BUF alone is sufficient.] Cc: stable@kernel.org Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4xdr.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 615f0a9f0600..c6766af00d98 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -1142,7 +1142,7 @@ nfsd4_decode_create_session(struct nfsd4_compoundargs *argp, u32 dummy; char *machine_name; - int i, j; + int i; int nr_secflavs; READ_BUF(16); @@ -1215,8 +1215,6 @@ nfsd4_decode_create_session(struct nfsd4_compoundargs *argp, READ_BUF(4); READ32(dummy); READ_BUF(dummy * 4); - for (j = 0; j < dummy; ++j) - READ32(dummy); break; case RPC_AUTH_GSS: dprintk("RPC_AUTH_GSS callback secflavor " @@ -1232,7 +1230,6 @@ nfsd4_decode_create_session(struct nfsd4_compoundargs *argp, READ_BUF(4); READ32(dummy); READ_BUF(dummy); - p += XDR_QUADLEN(dummy); break; default: dprintk("Illegal callback secflavor\n"); -- cgit From 9f570b8d48b6677b5557d86fb3ca148215e295f2 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Tue, 25 Jan 2011 12:42:37 -0500 Subject: Btrfs: fix formatting in file.c Sorry, but these were bugging me. Just cleanup some of the formatting in file.c. Signed-off-by: Josef Bacik --- fs/btrfs/file.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'fs') diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index f447b783bb84..4d4975592668 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -88,9 +88,8 @@ static noinline int btrfs_copy_from_user(loff_t pos, int num_pages, total_copied += copied; /* Return to btrfs_file_aio_write to fault page */ - if (unlikely(copied == 0)) { + if (unlikely(copied == 0)) break; - } if (unlikely(copied < PAGE_CACHE_SIZE - offset)) { offset += copied; @@ -162,13 +161,14 @@ static noinline int dirty_and_release_pages(struct btrfs_trans_handle *trans, ClearPageChecked(p); set_page_dirty(p); } - if (end_pos > isize) { + + /* + * we've only changed i_size in ram, and we haven't updated + * the disk i_size. There is no need to log the inode + * at this time. + */ + if (end_pos > isize) i_size_write(inode, end_pos); - /* we've only changed i_size in ram, and we haven't updated - * the disk i_size. There is no need to log the inode - * at this time. - */ - } return 0; } -- cgit From d0215f3e5ebb5803cd6ec067b10c5e00a3ad7cfc Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Tue, 25 Jan 2011 14:57:24 -0500 Subject: Btrfs: simplify our write path Our aio_write function is huge and kind of hard to follow at times. So this patch fixes this by breaking out the buffered and direct write paths out into seperate functions so it's a little clearer what's going on. I've also fixed some wrong typing that we had and added the ability to handle getting an error back from btrfs_set_extent_delalloc. Tested this with xfstests and everything came out fine. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/file.c | 355 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 180 insertions(+), 175 deletions(-) (limited to 'fs') diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 4d4975592668..f2a80e570a6c 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -45,14 +45,14 @@ * and be replaced with calls into generic code. */ static noinline int btrfs_copy_from_user(loff_t pos, int num_pages, - int write_bytes, + size_t write_bytes, struct page **prepared_pages, struct iov_iter *i) { size_t copied = 0; + size_t total_copied = 0; int pg = 0; int offset = pos & (PAGE_CACHE_SIZE - 1); - int total_copied = 0; while (write_bytes > 0) { size_t count = min_t(size_t, @@ -129,13 +129,12 @@ static noinline void btrfs_drop_pages(struct page **pages, size_t num_pages) * this also makes the decision about creating an inline extent vs * doing real data extents, marking pages dirty and delalloc as required. */ -static noinline int dirty_and_release_pages(struct btrfs_trans_handle *trans, - struct btrfs_root *root, - struct file *file, - struct page **pages, - size_t num_pages, - loff_t pos, - size_t write_bytes) +static noinline int dirty_and_release_pages(struct btrfs_root *root, + struct file *file, + struct page **pages, + size_t num_pages, + loff_t pos, + size_t write_bytes) { int err = 0; int i; @@ -153,7 +152,8 @@ static noinline int dirty_and_release_pages(struct btrfs_trans_handle *trans, end_of_last_block = start_pos + num_bytes - 1; err = btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block, NULL); - BUG_ON(err); + if (err) + return err; for (i = 0; i < num_pages; i++) { struct page *p = pages[i]; @@ -896,127 +896,38 @@ fail: } -static ssize_t btrfs_file_aio_write(struct kiocb *iocb, - const struct iovec *iov, - unsigned long nr_segs, loff_t pos) +static noinline ssize_t __btrfs_buffered_write(struct file *file, + struct iov_iter *i, + loff_t pos) { - struct file *file = iocb->ki_filp; struct inode *inode = fdentry(file)->d_inode; struct btrfs_root *root = BTRFS_I(inode)->root; struct page **pages = NULL; - struct iov_iter i; - loff_t *ppos = &iocb->ki_pos; - loff_t start_pos; - ssize_t num_written = 0; - ssize_t err = 0; - size_t count; - size_t ocount; - int ret = 0; - int nrptrs; unsigned long first_index; unsigned long last_index; - int will_write; - int buffered = 0; - int copied = 0; - int dirty_pages = 0; - - will_write = ((file->f_flags & O_DSYNC) || IS_SYNC(inode) || - (file->f_flags & O_DIRECT)); - - start_pos = pos; - - vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); - - mutex_lock(&inode->i_mutex); - - err = generic_segment_checks(iov, &nr_segs, &ocount, VERIFY_READ); - if (err) - goto out; - count = ocount; - - current->backing_dev_info = inode->i_mapping->backing_dev_info; - err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode)); - if (err) - goto out; - - if (count == 0) - goto out; - - err = file_remove_suid(file); - if (err) - goto out; - - /* - * If BTRFS flips readonly due to some impossible error - * (fs_info->fs_state now has BTRFS_SUPER_FLAG_ERROR), - * although we have opened a file as writable, we have - * to stop this write operation to ensure FS consistency. - */ - if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) { - err = -EROFS; - goto out; - } - - file_update_time(file); - BTRFS_I(inode)->sequence++; - - if (unlikely(file->f_flags & O_DIRECT)) { - num_written = generic_file_direct_write(iocb, iov, &nr_segs, - pos, ppos, count, - ocount); - /* - * the generic O_DIRECT will update in-memory i_size after the - * DIOs are done. But our endio handlers that update the on - * disk i_size never update past the in memory i_size. So we - * need one more update here to catch any additions to the - * file - */ - if (inode->i_size != BTRFS_I(inode)->disk_i_size) { - btrfs_ordered_update_i_size(inode, inode->i_size, NULL); - mark_inode_dirty(inode); - } - - if (num_written < 0) { - ret = num_written; - num_written = 0; - goto out; - } else if (num_written == count) { - /* pick up pos changes done by the generic code */ - pos = *ppos; - goto out; - } - /* - * We are going to do buffered for the rest of the range, so we - * need to make sure to invalidate the buffered pages when we're - * done. - */ - buffered = 1; - pos += num_written; - } + size_t num_written = 0; + int nrptrs; + int ret; - iov_iter_init(&i, iov, nr_segs, count, num_written); - nrptrs = min((iov_iter_count(&i) + PAGE_CACHE_SIZE - 1) / + nrptrs = min((iov_iter_count(i) + PAGE_CACHE_SIZE - 1) / PAGE_CACHE_SIZE, PAGE_CACHE_SIZE / (sizeof(struct page *))); pages = kmalloc(nrptrs * sizeof(struct page *), GFP_KERNEL); - if (!pages) { - ret = -ENOMEM; - goto out; - } - - /* generic_write_checks can change our pos */ - start_pos = pos; + if (!pages) + return -ENOMEM; first_index = pos >> PAGE_CACHE_SHIFT; - last_index = (pos + iov_iter_count(&i)) >> PAGE_CACHE_SHIFT; + last_index = (pos + iov_iter_count(i)) >> PAGE_CACHE_SHIFT; - while (iov_iter_count(&i) > 0) { + while (iov_iter_count(i) > 0) { size_t offset = pos & (PAGE_CACHE_SIZE - 1); - size_t write_bytes = min(iov_iter_count(&i), + size_t write_bytes = min(iov_iter_count(i), nrptrs * (size_t)PAGE_CACHE_SIZE - offset); size_t num_pages = (write_bytes + offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; + size_t dirty_pages; + size_t copied; WARN_ON(num_pages > nrptrs); memset(pages, 0, sizeof(struct page *) * nrptrs); @@ -1025,15 +936,15 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, * Fault pages before locking them in prepare_pages * to avoid recursive lock */ - if (unlikely(iov_iter_fault_in_readable(&i, write_bytes))) { + if (unlikely(iov_iter_fault_in_readable(i, write_bytes))) { ret = -EFAULT; - goto out; + break; } ret = btrfs_delalloc_reserve_space(inode, num_pages << PAGE_CACHE_SHIFT); if (ret) - goto out; + break; ret = prepare_pages(root, file, pages, num_pages, pos, first_index, last_index, @@ -1041,11 +952,11 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, if (ret) { btrfs_delalloc_release_space(inode, num_pages << PAGE_CACHE_SHIFT); - goto out; + break; } copied = btrfs_copy_from_user(pos, num_pages, - write_bytes, pages, &i); + write_bytes, pages, i); /* * if we have trouble faulting in the pages, fall @@ -1061,6 +972,13 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; + /* + * If we had a short copy we need to release the excess delaloc + * bytes we reserved. We need to increment outstanding_extents + * because btrfs_delalloc_release_space will decrement it, but + * we still have an outstanding extent for the chunk we actually + * managed to copy. + */ if (num_pages > dirty_pages) { if (copied > 0) atomic_inc( @@ -1071,39 +989,157 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, } if (copied > 0) { - dirty_and_release_pages(NULL, root, file, pages, - dirty_pages, pos, copied); + ret = dirty_and_release_pages(root, file, pages, + dirty_pages, pos, + copied); + if (ret) { + btrfs_delalloc_release_space(inode, + dirty_pages << PAGE_CACHE_SHIFT); + btrfs_drop_pages(pages, num_pages); + break; + } } btrfs_drop_pages(pages, num_pages); - if (copied > 0) { - if (will_write) { - filemap_fdatawrite_range(inode->i_mapping, pos, - pos + copied - 1); - } else { - balance_dirty_pages_ratelimited_nr( - inode->i_mapping, - dirty_pages); - if (dirty_pages < - (root->leafsize >> PAGE_CACHE_SHIFT) + 1) - btrfs_btree_balance_dirty(root, 1); - btrfs_throttle(root); - } - } + cond_resched(); + + balance_dirty_pages_ratelimited_nr(inode->i_mapping, + dirty_pages); + if (dirty_pages < (root->leafsize >> PAGE_CACHE_SHIFT) + 1) + btrfs_btree_balance_dirty(root, 1); + btrfs_throttle(root); pos += copied; num_written += copied; + } - cond_resched(); + kfree(pages); + + return num_written ? num_written : ret; +} + +static ssize_t __btrfs_direct_write(struct kiocb *iocb, + const struct iovec *iov, + unsigned long nr_segs, loff_t pos, + loff_t *ppos, size_t count, size_t ocount) +{ + struct file *file = iocb->ki_filp; + struct inode *inode = fdentry(file)->d_inode; + struct iov_iter i; + ssize_t written; + ssize_t written_buffered; + loff_t endbyte; + int err; + + written = generic_file_direct_write(iocb, iov, &nr_segs, pos, ppos, + count, ocount); + + /* + * the generic O_DIRECT will update in-memory i_size after the + * DIOs are done. But our endio handlers that update the on + * disk i_size never update past the in memory i_size. So we + * need one more update here to catch any additions to the + * file + */ + if (inode->i_size != BTRFS_I(inode)->disk_i_size) { + btrfs_ordered_update_i_size(inode, inode->i_size, NULL); + mark_inode_dirty(inode); } + + if (written < 0 || written == count) + return written; + + pos += written; + count -= written; + iov_iter_init(&i, iov, nr_segs, count, written); + written_buffered = __btrfs_buffered_write(file, &i, pos); + if (written_buffered < 0) { + err = written_buffered; + goto out; + } + endbyte = pos + written_buffered - 1; + err = filemap_write_and_wait_range(file->f_mapping, pos, endbyte); + if (err) + goto out; + written += written_buffered; + *ppos = pos + written_buffered; + invalidate_mapping_pages(file->f_mapping, pos >> PAGE_CACHE_SHIFT, + endbyte >> PAGE_CACHE_SHIFT); out: - mutex_unlock(&inode->i_mutex); - if (ret) - err = ret; + return written ? written : err; +} - kfree(pages); - *ppos = pos; +static ssize_t btrfs_file_aio_write(struct kiocb *iocb, + const struct iovec *iov, + unsigned long nr_segs, loff_t pos) +{ + struct file *file = iocb->ki_filp; + struct inode *inode = fdentry(file)->d_inode; + struct btrfs_root *root = BTRFS_I(inode)->root; + loff_t *ppos = &iocb->ki_pos; + ssize_t num_written = 0; + ssize_t err = 0; + size_t count, ocount; + + vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); + + mutex_lock(&inode->i_mutex); + + err = generic_segment_checks(iov, &nr_segs, &ocount, VERIFY_READ); + if (err) { + mutex_unlock(&inode->i_mutex); + goto out; + } + count = ocount; + + current->backing_dev_info = inode->i_mapping->backing_dev_info; + err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode)); + if (err) { + mutex_unlock(&inode->i_mutex); + goto out; + } + + if (count == 0) { + mutex_unlock(&inode->i_mutex); + goto out; + } + + err = file_remove_suid(file); + if (err) { + mutex_unlock(&inode->i_mutex); + goto out; + } + + /* + * If BTRFS flips readonly due to some impossible error + * (fs_info->fs_state now has BTRFS_SUPER_FLAG_ERROR), + * although we have opened a file as writable, we have + * to stop this write operation to ensure FS consistency. + */ + if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) { + mutex_unlock(&inode->i_mutex); + err = -EROFS; + goto out; + } + + file_update_time(file); + BTRFS_I(inode)->sequence++; + + if (unlikely(file->f_flags & O_DIRECT)) { + num_written = __btrfs_direct_write(iocb, iov, nr_segs, + pos, ppos, count, ocount); + } else { + struct iov_iter i; + + iov_iter_init(&i, iov, nr_segs, count, num_written); + + num_written = __btrfs_buffered_write(file, &i, pos); + if (num_written > 0) + *ppos = pos + num_written; + } + + mutex_unlock(&inode->i_mutex); /* * we want to make sure fsync finds this change @@ -1118,43 +1154,12 @@ out: * one running right now. */ BTRFS_I(inode)->last_trans = root->fs_info->generation + 1; - - if (num_written > 0 && will_write) { - struct btrfs_trans_handle *trans; - - err = btrfs_wait_ordered_range(inode, start_pos, num_written); - if (err) + if (num_written > 0 || num_written == -EIOCBQUEUED) { + err = generic_write_sync(file, pos, num_written); + if (err < 0 && num_written > 0) num_written = err; - - if ((file->f_flags & O_DSYNC) || IS_SYNC(inode)) { - trans = btrfs_start_transaction(root, 0); - if (IS_ERR(trans)) { - num_written = PTR_ERR(trans); - goto done; - } - mutex_lock(&inode->i_mutex); - ret = btrfs_log_dentry_safe(trans, root, - file->f_dentry); - mutex_unlock(&inode->i_mutex); - if (ret == 0) { - ret = btrfs_sync_log(trans, root); - if (ret == 0) - btrfs_end_transaction(trans, root); - else - btrfs_commit_transaction(trans, root); - } else if (ret != BTRFS_NO_LOG_SYNC) { - btrfs_commit_transaction(trans, root); - } else { - btrfs_end_transaction(trans, root); - } - } - if (file->f_flags & O_DIRECT && buffered) { - invalidate_mapping_pages(inode->i_mapping, - start_pos >> PAGE_CACHE_SHIFT, - (start_pos + num_written - 1) >> PAGE_CACHE_SHIFT); - } } -done: +out: current->backing_dev_info = NULL; return num_written ? num_written : err; } -- cgit From 4a64001f0047956e283f7ada9843dfc3f3b5d8c8 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Tue, 25 Jan 2011 15:10:08 -0500 Subject: Btrfs: fix how we deal with the pages array in the write path Really we don't need to memset the pages array at all, since we know how many pages we're going to use in the array and pass that around. So don't memset, just trust we're not idiots and we pass num_pages around properly. Signed-off-by: Josef Bacik --- fs/btrfs/file.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index f2a80e570a6c..24a19c2743ca 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -108,8 +108,6 @@ static noinline void btrfs_drop_pages(struct page **pages, size_t num_pages) { size_t i; for (i = 0; i < num_pages; i++) { - if (!pages[i]) - break; /* page checked is some magic around finding pages that * have been modified without going through btrfs_set_page_dirty * clear it here @@ -824,7 +822,6 @@ static noinline int prepare_pages(struct btrfs_root *root, struct file *file, return err; } - memset(pages, 0, num_pages * sizeof(struct page *)); again: for (i = 0; i < num_pages; i++) { pages[i] = grab_cache_page(inode->i_mapping, index + i); @@ -930,7 +927,6 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file, size_t copied; WARN_ON(num_pages > nrptrs); - memset(pages, 0, sizeof(struct page *) * nrptrs); /* * Fault pages before locking them in prepare_pages @@ -946,6 +942,11 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file, if (ret) break; + /* + * This is going to setup the pages array with the number of + * pages we want, so we don't really need to worry about the + * contents of pages from loop to loop + */ ret = prepare_pages(root, file, pages, num_pages, pos, first_index, last_index, write_bytes); -- cgit From 57a45ced94fe48a701361d64230fc16eefa189dd Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Tue, 25 Jan 2011 16:30:38 -0500 Subject: Btrfs: change reserved_extents to an atomic_t We track delayed allocation per inodes via 2 counters, one is outstanding_extents and reserved_extents. Outstanding_extents is already an atomic_t, but reserved_extents is not and is protected by a spinlock. So convert this to an atomic_t and instead of using a spinlock, use atomic_cmpxchg when releasing delalloc bytes. This makes our inode 72 bytes smaller, and reduces locking overhead (albiet it was minimal to begin with). Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/btrfs_inode.h | 3 +-- fs/btrfs/extent-tree.c | 42 ++++++++++++++++++++++++++---------------- fs/btrfs/inode.c | 5 ++--- 3 files changed, 29 insertions(+), 21 deletions(-) (limited to 'fs') diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h index ccc991c542df..57c3bb2884ce 100644 --- a/fs/btrfs/btrfs_inode.h +++ b/fs/btrfs/btrfs_inode.h @@ -136,9 +136,8 @@ struct btrfs_inode { * items we think we'll end up using, and reserved_extents is the number * of extent items we've reserved metadata for. */ - spinlock_t accounting_lock; atomic_t outstanding_extents; - int reserved_extents; + atomic_t reserved_extents; /* * ordered_data_close is set by truncate when a file that used diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 7b3089b5c2df..27376c97d85f 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -3996,6 +3996,7 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) struct btrfs_block_rsv *block_rsv = &root->fs_info->delalloc_block_rsv; u64 to_reserve; int nr_extents; + int reserved_extents; int ret; if (btrfs_transaction_in_commit(root->fs_info)) @@ -4003,25 +4004,24 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) num_bytes = ALIGN(num_bytes, root->sectorsize); - spin_lock(&BTRFS_I(inode)->accounting_lock); nr_extents = atomic_read(&BTRFS_I(inode)->outstanding_extents) + 1; - if (nr_extents > BTRFS_I(inode)->reserved_extents) { - nr_extents -= BTRFS_I(inode)->reserved_extents; + reserved_extents = atomic_read(&BTRFS_I(inode)->reserved_extents); + + if (nr_extents > reserved_extents) { + nr_extents -= reserved_extents; to_reserve = calc_trans_metadata_size(root, nr_extents); } else { nr_extents = 0; to_reserve = 0; } - spin_unlock(&BTRFS_I(inode)->accounting_lock); + to_reserve += calc_csum_metadata_size(inode, num_bytes); ret = reserve_metadata_bytes(NULL, root, block_rsv, to_reserve, 1); if (ret) return ret; - spin_lock(&BTRFS_I(inode)->accounting_lock); - BTRFS_I(inode)->reserved_extents += nr_extents; + atomic_add(nr_extents, &BTRFS_I(inode)->reserved_extents); atomic_inc(&BTRFS_I(inode)->outstanding_extents); - spin_unlock(&BTRFS_I(inode)->accounting_lock); block_rsv_add_bytes(block_rsv, to_reserve, 1); @@ -4036,20 +4036,30 @@ void btrfs_delalloc_release_metadata(struct inode *inode, u64 num_bytes) struct btrfs_root *root = BTRFS_I(inode)->root; u64 to_free; int nr_extents; + int reserved_extents; num_bytes = ALIGN(num_bytes, root->sectorsize); atomic_dec(&BTRFS_I(inode)->outstanding_extents); WARN_ON(atomic_read(&BTRFS_I(inode)->outstanding_extents) < 0); - spin_lock(&BTRFS_I(inode)->accounting_lock); - nr_extents = atomic_read(&BTRFS_I(inode)->outstanding_extents); - if (nr_extents < BTRFS_I(inode)->reserved_extents) { - nr_extents = BTRFS_I(inode)->reserved_extents - nr_extents; - BTRFS_I(inode)->reserved_extents -= nr_extents; - } else { - nr_extents = 0; - } - spin_unlock(&BTRFS_I(inode)->accounting_lock); + reserved_extents = atomic_read(&BTRFS_I(inode)->reserved_extents); + do { + int old, new; + + nr_extents = atomic_read(&BTRFS_I(inode)->outstanding_extents); + if (nr_extents >= reserved_extents) { + nr_extents = 0; + break; + } + old = reserved_extents; + nr_extents = reserved_extents - nr_extents; + new = reserved_extents - nr_extents; + old = atomic_cmpxchg(&BTRFS_I(inode)->reserved_extents, + reserved_extents, new); + if (likely(old == reserved_extents)) + break; + reserved_extents = old; + } while (1); to_free = calc_csum_metadata_size(inode, num_bytes); if (nr_extents > 0) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 9007bbd01dbf..d97b69afbbfb 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -6632,9 +6632,8 @@ struct inode *btrfs_alloc_inode(struct super_block *sb) ei->index_cnt = (u64)-1; ei->last_unlink_trans = 0; - spin_lock_init(&ei->accounting_lock); atomic_set(&ei->outstanding_extents, 0); - ei->reserved_extents = 0; + atomic_set(&ei->reserved_extents, 0); ei->ordered_data_close = 0; ei->orphan_meta_reserved = 0; @@ -6670,7 +6669,7 @@ void btrfs_destroy_inode(struct inode *inode) WARN_ON(!list_empty(&inode->i_dentry)); WARN_ON(inode->i_data.nrpages); WARN_ON(atomic_read(&BTRFS_I(inode)->outstanding_extents)); - WARN_ON(BTRFS_I(inode)->reserved_extents); + WARN_ON(atomic_read(&BTRFS_I(inode)->reserved_extents)); /* * This can happen where we create an inode, but somebody else also -- cgit From dc89e9824464e91fa0b06267864ceabe3186fd8b Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Fri, 28 Jan 2011 17:05:48 -0500 Subject: Btrfs: use a slab for the free space entries Since we alloc/free free space entries a whole lot, lets use a slab to keep track of them. This makes some of my tests slightly faster. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/ctree.h | 1 + fs/btrfs/free-space-cache.c | 34 ++++++++++++++++++---------------- fs/btrfs/inode.c | 10 ++++++++++ 3 files changed, 29 insertions(+), 16 deletions(-) (limited to 'fs') diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 7f78cc78fdd0..2c98d209e6ac 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -40,6 +40,7 @@ extern struct kmem_cache *btrfs_trans_handle_cachep; extern struct kmem_cache *btrfs_transaction_cachep; extern struct kmem_cache *btrfs_bit_radix_cachep; extern struct kmem_cache *btrfs_path_cachep; +extern struct kmem_cache *btrfs_free_space_cachep; struct btrfs_ordered_sum; #define BTRFS_MAGIC "_BHRfS_M" diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index a0390657451b..0282033041e1 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -393,7 +393,8 @@ int load_free_space_cache(struct btrfs_fs_info *fs_info, break; need_loop = 1; - e = kzalloc(sizeof(struct btrfs_free_space), GFP_NOFS); + e = kmem_cache_zalloc(btrfs_free_space_cachep, + GFP_NOFS); if (!e) { kunmap(page); unlock_page(page); @@ -405,7 +406,7 @@ int load_free_space_cache(struct btrfs_fs_info *fs_info, e->bytes = le64_to_cpu(entry->bytes); if (!e->bytes) { kunmap(page); - kfree(e); + kmem_cache_free(btrfs_free_space_cachep, e); unlock_page(page); page_cache_release(page); goto free_cache; @@ -420,7 +421,8 @@ int load_free_space_cache(struct btrfs_fs_info *fs_info, e->bitmap = kzalloc(PAGE_CACHE_SIZE, GFP_NOFS); if (!e->bitmap) { kunmap(page); - kfree(e); + kmem_cache_free( + btrfs_free_space_cachep, e); unlock_page(page); page_cache_release(page); goto free_cache; @@ -1187,7 +1189,7 @@ static void free_bitmap(struct btrfs_block_group_cache *block_group, { unlink_free_space(block_group, bitmap_info); kfree(bitmap_info->bitmap); - kfree(bitmap_info); + kmem_cache_free(btrfs_free_space_cachep, bitmap_info); block_group->total_bitmaps--; recalculate_thresholds(block_group); } @@ -1342,8 +1344,8 @@ new_bitmap: /* no pre-allocated info, allocate a new one */ if (!info) { - info = kzalloc(sizeof(struct btrfs_free_space), - GFP_NOFS); + info = kmem_cache_zalloc(btrfs_free_space_cachep, + GFP_NOFS); if (!info) { spin_lock(&block_group->tree_lock); ret = -ENOMEM; @@ -1365,7 +1367,7 @@ out: if (info) { if (info->bitmap) kfree(info->bitmap); - kfree(info); + kmem_cache_free(btrfs_free_space_cachep, info); } return ret; @@ -1398,7 +1400,7 @@ bool try_merge_free_space(struct btrfs_block_group_cache *block_group, else __unlink_free_space(block_group, right_info); info->bytes += right_info->bytes; - kfree(right_info); + kmem_cache_free(btrfs_free_space_cachep, right_info); merged = true; } @@ -1410,7 +1412,7 @@ bool try_merge_free_space(struct btrfs_block_group_cache *block_group, __unlink_free_space(block_group, left_info); info->offset = left_info->offset; info->bytes += left_info->bytes; - kfree(left_info); + kmem_cache_free(btrfs_free_space_cachep, left_info); merged = true; } @@ -1423,7 +1425,7 @@ int btrfs_add_free_space(struct btrfs_block_group_cache *block_group, struct btrfs_free_space *info; int ret = 0; - info = kzalloc(sizeof(struct btrfs_free_space), GFP_NOFS); + info = kmem_cache_zalloc(btrfs_free_space_cachep, GFP_NOFS); if (!info) return -ENOMEM; @@ -1450,7 +1452,7 @@ int btrfs_add_free_space(struct btrfs_block_group_cache *block_group, link: ret = link_free_space(block_group, info); if (ret) - kfree(info); + kmem_cache_free(btrfs_free_space_cachep, info); out: spin_unlock(&block_group->tree_lock); @@ -1520,7 +1522,7 @@ again: kfree(info->bitmap); block_group->total_bitmaps--; } - kfree(info); + kmem_cache_free(btrfs_free_space_cachep, info); goto out_lock; } @@ -1556,7 +1558,7 @@ again: /* the hole we're creating ends at the end * of the info struct, just free the info */ - kfree(info); + kmem_cache_free(btrfs_free_space_cachep, info); } spin_unlock(&block_group->tree_lock); @@ -1689,7 +1691,7 @@ void btrfs_remove_free_space_cache(struct btrfs_block_group_cache *block_group) unlink_free_space(block_group, info); if (info->bitmap) kfree(info->bitmap); - kfree(info); + kmem_cache_free(btrfs_free_space_cachep, info); if (need_resched()) { spin_unlock(&block_group->tree_lock); cond_resched(); @@ -1722,7 +1724,7 @@ u64 btrfs_find_space_for_alloc(struct btrfs_block_group_cache *block_group, entry->offset += bytes; entry->bytes -= bytes; if (!entry->bytes) - kfree(entry); + kmem_cache_free(btrfs_free_space_cachep, entry); else link_free_space(block_group, entry); } @@ -1884,7 +1886,7 @@ out: block_group->free_space -= bytes; if (entry->bytes == 0) { block_group->free_extents--; - kfree(entry); + kmem_cache_free(btrfs_free_space_cachep, entry); } spin_unlock(&block_group->tree_lock); diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index d97b69afbbfb..2d2e079713d7 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -50,6 +50,7 @@ #include "tree-log.h" #include "compression.h" #include "locking.h" +#include "free-space-cache.h" struct btrfs_iget_args { u64 ino; @@ -70,6 +71,7 @@ static struct kmem_cache *btrfs_inode_cachep; struct kmem_cache *btrfs_trans_handle_cachep; struct kmem_cache *btrfs_transaction_cachep; struct kmem_cache *btrfs_path_cachep; +struct kmem_cache *btrfs_free_space_cachep; #define S_SHIFT 12 static unsigned char btrfs_type_by_mode[S_IFMT >> S_SHIFT] = { @@ -6761,6 +6763,8 @@ void btrfs_destroy_cachep(void) kmem_cache_destroy(btrfs_transaction_cachep); if (btrfs_path_cachep) kmem_cache_destroy(btrfs_path_cachep); + if (btrfs_free_space_cachep) + kmem_cache_destroy(btrfs_free_space_cachep); } int btrfs_init_cachep(void) @@ -6789,6 +6793,12 @@ int btrfs_init_cachep(void) if (!btrfs_path_cachep) goto fail; + btrfs_free_space_cachep = kmem_cache_create("btrfs_free_space_cache", + sizeof(struct btrfs_free_space), 0, + SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL); + if (!btrfs_free_space_cachep) + goto fail; + return 0; fail: btrfs_destroy_cachep(); -- cgit From a41ad394a03b802497958d7c98a9dcf607266645 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Mon, 31 Jan 2011 15:30:16 -0500 Subject: Btrfs: convert to the new truncate sequence ->truncate() is going away, instead all of the work needs to be done in ->setattr(). So this converts us over to do this. It's fairly straightforward, just get rid of our .truncate inode operation and call btrfs_truncate() directly from btrfs_setsize. This works out better for us since truncate can technically return ENOSPC, and before we had no way of letting anybody know. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/ctree.h | 2 +- fs/btrfs/file.c | 5 ++-- fs/btrfs/inode.c | 80 +++++++++++++++++++++++++------------------------------- 3 files changed, 40 insertions(+), 47 deletions(-) (limited to 'fs') diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 2c98d209e6ac..34142d5647df 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -2537,7 +2537,7 @@ void btrfs_orphan_post_snapshot(struct btrfs_trans_handle *trans, struct btrfs_pending_snapshot *pending); void btrfs_orphan_commit_root(struct btrfs_trans_handle *trans, struct btrfs_root *root); -int btrfs_cont_expand(struct inode *inode, loff_t size); +int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size); int btrfs_invalidate_inodes(struct btrfs_root *root); void btrfs_add_delayed_iput(struct inode *inode); void btrfs_run_delayed_iputs(struct btrfs_root *root); diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 24a19c2743ca..3786eca2a905 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -817,7 +817,7 @@ static noinline int prepare_pages(struct btrfs_root *root, struct file *file, last_pos = ((u64)index + num_pages) << PAGE_CACHE_SHIFT; if (start_pos > inode->i_size) { - err = btrfs_cont_expand(inode, start_pos); + err = btrfs_cont_expand(inode, i_size_read(inode), start_pos); if (err) return err; } @@ -1330,7 +1330,8 @@ static long btrfs_fallocate(struct file *file, int mode, goto out; if (alloc_start > inode->i_size) { - ret = btrfs_cont_expand(inode, alloc_start); + ret = btrfs_cont_expand(inode, i_size_read(inode), + alloc_start); if (ret) goto out; } diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 2d2e079713d7..3662ffec17d9 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -84,7 +84,8 @@ static unsigned char btrfs_type_by_mode[S_IFMT >> S_SHIFT] = { [S_IFLNK >> S_SHIFT] = BTRFS_FT_SYMLINK, }; -static void btrfs_truncate(struct inode *inode); +static int btrfs_setsize(struct inode *inode, loff_t newsize); +static int btrfs_truncate(struct inode *inode); static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end); static noinline int cow_file_range(struct inode *inode, struct page *locked_page, @@ -2371,6 +2372,11 @@ void btrfs_orphan_cleanup(struct btrfs_root *root) /* if we have links, this was a truncate, lets do that */ if (inode->i_nlink) { + if (!S_ISREG(inode->i_mode)) { + WARN_ON(1); + iput(inode); + continue; + } nr_truncate++; btrfs_truncate(inode); } else { @@ -3538,7 +3544,7 @@ out: return ret; } -int btrfs_cont_expand(struct inode *inode, loff_t size) +int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size) { struct btrfs_trans_handle *trans; struct btrfs_root *root = BTRFS_I(inode)->root; @@ -3546,7 +3552,7 @@ int btrfs_cont_expand(struct inode *inode, loff_t size) struct extent_map *em = NULL; struct extent_state *cached_state = NULL; u64 mask = root->sectorsize - 1; - u64 hole_start = (inode->i_size + mask) & ~mask; + u64 hole_start = (oldsize + mask) & ~mask; u64 block_end = (size + mask) & ~mask; u64 last_byte; u64 cur_offset; @@ -3617,27 +3623,17 @@ int btrfs_cont_expand(struct inode *inode, loff_t size) return err; } -static int btrfs_setattr_size(struct inode *inode, struct iattr *attr) +static int btrfs_setsize(struct inode *inode, loff_t newsize) { struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_trans_handle *trans; + loff_t oldsize = i_size_read(inode); unsigned long nr; int ret; - if (attr->ia_size == inode->i_size) + if (newsize == oldsize) return 0; - if (attr->ia_size > inode->i_size) { - unsigned long limit; - limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur; - if (attr->ia_size > inode->i_sb->s_maxbytes) - return -EFBIG; - if (limit != RLIM_INFINITY && attr->ia_size > limit) { - send_sig(SIGXFSZ, current, 0); - return -EFBIG; - } - } - trans = btrfs_start_transaction(root, 5); if (IS_ERR(trans)) return PTR_ERR(trans); @@ -3651,16 +3647,16 @@ static int btrfs_setattr_size(struct inode *inode, struct iattr *attr) btrfs_end_transaction(trans, root); btrfs_btree_balance_dirty(root, nr); - if (attr->ia_size > inode->i_size) { - ret = btrfs_cont_expand(inode, attr->ia_size); + if (newsize > oldsize) { + i_size_write(inode, newsize); + btrfs_ordered_update_i_size(inode, i_size_read(inode), NULL); + truncate_pagecache(inode, oldsize, newsize); + ret = btrfs_cont_expand(inode, oldsize, newsize); if (ret) { - btrfs_truncate(inode); + btrfs_setsize(inode, oldsize); return ret; } - i_size_write(inode, attr->ia_size); - btrfs_ordered_update_i_size(inode, inode->i_size, NULL); - trans = btrfs_start_transaction(root, 0); BUG_ON(IS_ERR(trans)); btrfs_set_trans_block_group(trans, inode); @@ -3676,22 +3672,22 @@ static int btrfs_setattr_size(struct inode *inode, struct iattr *attr) nr = trans->blocks_used; btrfs_end_transaction(trans, root); btrfs_btree_balance_dirty(root, nr); - return 0; - } + } else { - /* - * We're truncating a file that used to have good data down to - * zero. Make sure it gets into the ordered flush list so that - * any new writes get down to disk quickly. - */ - if (attr->ia_size == 0) - BTRFS_I(inode)->ordered_data_close = 1; + /* + * We're truncating a file that used to have good data down to + * zero. Make sure it gets into the ordered flush list so that + * any new writes get down to disk quickly. + */ + if (newsize == 0) + BTRFS_I(inode)->ordered_data_close = 1; - /* we don't support swapfiles, so vmtruncate shouldn't fail */ - ret = vmtruncate(inode, attr->ia_size); - BUG_ON(ret); + /* we don't support swapfiles, so vmtruncate shouldn't fail */ + truncate_setsize(inode, newsize); + ret = btrfs_truncate(inode); + } - return 0; + return ret; } static int btrfs_setattr(struct dentry *dentry, struct iattr *attr) @@ -3708,7 +3704,7 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr) return err; if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) { - err = btrfs_setattr_size(inode, attr); + err = btrfs_setsize(inode, attr->ia_size); if (err) return err; } @@ -6478,7 +6474,7 @@ out: return ret; } -static void btrfs_truncate(struct inode *inode) +static int btrfs_truncate(struct inode *inode) { struct btrfs_root *root = BTRFS_I(inode)->root; int ret; @@ -6486,14 +6482,9 @@ static void btrfs_truncate(struct inode *inode) unsigned long nr; u64 mask = root->sectorsize - 1; - if (!S_ISREG(inode->i_mode)) { - WARN_ON(1); - return; - } - ret = btrfs_truncate_page(inode->i_mapping, inode->i_size); if (ret) - return; + return ret; btrfs_wait_ordered_range(inode, inode->i_size & (~mask), (u64)-1); btrfs_ordered_update_i_size(inode, inode->i_size, NULL); @@ -6568,6 +6559,8 @@ static void btrfs_truncate(struct inode *inode) ret = btrfs_end_transaction_throttle(trans, root); BUG_ON(ret); btrfs_btree_balance_dirty(root, nr); + + return ret; } /* @@ -7367,7 +7360,6 @@ static const struct address_space_operations btrfs_symlink_aops = { }; static const struct inode_operations btrfs_file_inode_operations = { - .truncate = btrfs_truncate, .getattr = btrfs_getattr, .setattr = btrfs_setattr, .setxattr = btrfs_setxattr, -- cgit From 3893e33b0bebee2f67d96b6c15259dc884523c20 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Mon, 31 Jan 2011 16:03:11 -0500 Subject: Btrfs: cleanup error handling in the truncate path Now that we can handle having errors in the truncate path lets make sure we return errors instead of doing BUG_ON() and such. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/inode.c | 64 +++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 19 deletions(-) (limited to 'fs') diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 3662ffec17d9..d83025063ee7 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -3597,13 +3597,15 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size) err = btrfs_drop_extents(trans, inode, cur_offset, cur_offset + hole_size, &hint_byte, 1); - BUG_ON(err); + if (err) + break; err = btrfs_insert_file_extent(trans, root, inode->i_ino, cur_offset, 0, 0, hole_size, 0, hole_size, 0, 0, 0); - BUG_ON(err); + if (err) + break; btrfs_drop_extent_cache(inode, hole_start, last_byte - 1, 0); @@ -3641,7 +3643,10 @@ static int btrfs_setsize(struct inode *inode, loff_t newsize) btrfs_set_trans_block_group(trans, inode); ret = btrfs_orphan_add(trans, inode); - BUG_ON(ret); + if (ret) { + btrfs_end_transaction(trans, root); + return ret; + } nr = trans->blocks_used; btrfs_end_transaction(trans, root); @@ -3658,17 +3663,24 @@ static int btrfs_setsize(struct inode *inode, loff_t newsize) } trans = btrfs_start_transaction(root, 0); - BUG_ON(IS_ERR(trans)); + if (IS_ERR(trans)) + return PTR_ERR(trans); + btrfs_set_trans_block_group(trans, inode); trans->block_rsv = root->orphan_block_rsv; BUG_ON(!trans->block_rsv); + /* + * If this fails just leave the orphan item so that it can get + * cleaned up next time we mount. + */ ret = btrfs_update_inode(trans, root, inode); - BUG_ON(ret); - if (inode->i_nlink > 0) { - ret = btrfs_orphan_del(trans, inode); - BUG_ON(ret); + if (ret) { + btrfs_end_transaction(trans, root); + return ret; } + if (inode->i_nlink > 0) + ret = btrfs_orphan_del(trans, inode); nr = trans->blocks_used; btrfs_end_transaction(trans, root); btrfs_btree_balance_dirty(root, nr); @@ -6478,6 +6490,7 @@ static int btrfs_truncate(struct inode *inode) { struct btrfs_root *root = BTRFS_I(inode)->root; int ret; + int err = 0; struct btrfs_trans_handle *trans; unsigned long nr; u64 mask = root->sectorsize - 1; @@ -6490,7 +6503,8 @@ static int btrfs_truncate(struct inode *inode) btrfs_ordered_update_i_size(inode, inode->i_size, NULL); trans = btrfs_start_transaction(root, 0); - BUG_ON(IS_ERR(trans)); + if (IS_ERR(trans)) + return PTR_ERR(trans); btrfs_set_trans_block_group(trans, inode); trans->block_rsv = root->orphan_block_rsv; @@ -6517,29 +6531,38 @@ static int btrfs_truncate(struct inode *inode) while (1) { if (!trans) { trans = btrfs_start_transaction(root, 0); - BUG_ON(IS_ERR(trans)); + if (IS_ERR(trans)) + return PTR_ERR(trans); btrfs_set_trans_block_group(trans, inode); trans->block_rsv = root->orphan_block_rsv; } ret = btrfs_block_rsv_check(trans, root, root->orphan_block_rsv, 0, 5); - if (ret) { - BUG_ON(ret != -EAGAIN); + if (ret == -EAGAIN) { ret = btrfs_commit_transaction(trans, root); - BUG_ON(ret); + if (ret) + return ret; trans = NULL; continue; + } else if (ret) { + err = ret; + break; } ret = btrfs_truncate_inode_items(trans, root, inode, inode->i_size, BTRFS_EXTENT_DATA_KEY); - if (ret != -EAGAIN) + if (ret != -EAGAIN) { + err = ret; break; + } ret = btrfs_update_inode(trans, root, inode); - BUG_ON(ret); + if (ret) { + err = ret; + break; + } nr = trans->blocks_used; btrfs_end_transaction(trans, root); @@ -6549,18 +6572,21 @@ static int btrfs_truncate(struct inode *inode) if (ret == 0 && inode->i_nlink > 0) { ret = btrfs_orphan_del(trans, inode); - BUG_ON(ret); + if (ret) + err = ret; } ret = btrfs_update_inode(trans, root, inode); - BUG_ON(ret); + if (ret && !err) + err = ret; nr = trans->blocks_used; ret = btrfs_end_transaction_throttle(trans, root); - BUG_ON(ret); + if (ret && !err) + err = ret; btrfs_btree_balance_dirty(root, nr); - return ret; + return err; } /* -- cgit From 66b4ffd110f9b48b8d8c1319ee446b53b8d073bf Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Mon, 31 Jan 2011 16:22:42 -0500 Subject: Btrfs: handle errors in btrfs_orphan_cleanup If we cannot truncate an inode for some reason we will never delete the orphan item associated with that inode, which means that we will loop forever in btrfs_orphan_cleanup. Instead of doing this just return error so we fail to mount. It sucks, but hey it's better than hanging. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/ctree.h | 2 +- fs/btrfs/disk-io.c | 15 ++++++++++++--- fs/btrfs/extent-tree.c | 3 ++- fs/btrfs/inode.c | 47 +++++++++++++++++++++++++++++++---------------- fs/btrfs/ioctl.c | 4 +++- fs/btrfs/relocation.c | 2 +- 6 files changed, 50 insertions(+), 23 deletions(-) (limited to 'fs') diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 34142d5647df..841330f3d68d 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -2529,7 +2529,7 @@ int btrfs_update_inode(struct btrfs_trans_handle *trans, struct inode *inode); int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode); int btrfs_orphan_del(struct btrfs_trans_handle *trans, struct inode *inode); -void btrfs_orphan_cleanup(struct btrfs_root *root); +int btrfs_orphan_cleanup(struct btrfs_root *root); void btrfs_orphan_pre_snapshot(struct btrfs_trans_handle *trans, struct btrfs_pending_snapshot *pending, u64 *bytes_to_reserve); diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index e1aa8d607bc7..495b1ac45f8c 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -2058,9 +2058,14 @@ struct btrfs_root *open_ctree(struct super_block *sb, if (!(sb->s_flags & MS_RDONLY)) { down_read(&fs_info->cleanup_work_sem); - btrfs_orphan_cleanup(fs_info->fs_root); - btrfs_orphan_cleanup(fs_info->tree_root); + err = btrfs_orphan_cleanup(fs_info->fs_root); + if (!err) + err = btrfs_orphan_cleanup(fs_info->tree_root); up_read(&fs_info->cleanup_work_sem); + if (err) { + close_ctree(tree_root); + return ERR_PTR(err); + } } return tree_root; @@ -2435,8 +2440,12 @@ int btrfs_cleanup_fs_roots(struct btrfs_fs_info *fs_info) root_objectid = gang[ret - 1]->root_key.objectid + 1; for (i = 0; i < ret; i++) { + int err; + root_objectid = gang[i]->root_key.objectid; - btrfs_orphan_cleanup(gang[i]); + err = btrfs_orphan_cleanup(gang[i]); + if (err) + return err; } root_objectid++; } diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 27376c97d85f..a8f4e8d2ba60 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -7619,7 +7619,8 @@ int btrfs_cleanup_reloc_trees(struct btrfs_root *root) reloc_root = btrfs_read_fs_root_no_name(root->fs_info, &location); BUG_ON(!reloc_root); - btrfs_orphan_cleanup(reloc_root); + ret = btrfs_orphan_cleanup(reloc_root); + BUG_ON(ret); return 0; } diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index d83025063ee7..0600265cb9b0 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -2284,7 +2284,7 @@ int btrfs_orphan_del(struct btrfs_trans_handle *trans, struct inode *inode) * this cleans up any orphans that may be left on the list from the last use * of this root. */ -void btrfs_orphan_cleanup(struct btrfs_root *root) +int btrfs_orphan_cleanup(struct btrfs_root *root) { struct btrfs_path *path; struct extent_buffer *leaf; @@ -2294,10 +2294,13 @@ void btrfs_orphan_cleanup(struct btrfs_root *root) int ret = 0, nr_unlink = 0, nr_truncate = 0; if (cmpxchg(&root->orphan_cleanup_state, 0, ORPHAN_CLEANUP_STARTED)) - return; + return 0; path = btrfs_alloc_path(); - BUG_ON(!path); + if (!path) { + ret = -ENOMEM; + goto out; + } path->reada = -1; key.objectid = BTRFS_ORPHAN_OBJECTID; @@ -2306,11 +2309,8 @@ void btrfs_orphan_cleanup(struct btrfs_root *root) while (1) { ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); - if (ret < 0) { - printk(KERN_ERR "Error searching slot for orphan: %d" - "\n", ret); - break; - } + if (ret < 0) + goto out; /* * if ret == 0 means we found what we were searching for, which @@ -2318,6 +2318,7 @@ void btrfs_orphan_cleanup(struct btrfs_root *root) * find the key and see if we have stuff that matches */ if (ret > 0) { + ret = 0; if (path->slots[0] == 0) break; path->slots[0]--; @@ -2345,7 +2346,10 @@ void btrfs_orphan_cleanup(struct btrfs_root *root) found_key.type = BTRFS_INODE_ITEM_KEY; found_key.offset = 0; inode = btrfs_iget(root->fs_info->sb, &found_key, root, NULL); - BUG_ON(IS_ERR(inode)); + if (IS_ERR(inode)) { + ret = PTR_ERR(inode); + goto out; + } /* * add this inode to the orphan list so btrfs_orphan_del does @@ -2363,7 +2367,10 @@ void btrfs_orphan_cleanup(struct btrfs_root *root) */ if (is_bad_inode(inode)) { trans = btrfs_start_transaction(root, 0); - BUG_ON(IS_ERR(trans)); + if (IS_ERR(trans)) { + ret = PTR_ERR(trans); + goto out; + } btrfs_orphan_del(trans, inode); btrfs_end_transaction(trans, root); iput(inode); @@ -2378,16 +2385,16 @@ void btrfs_orphan_cleanup(struct btrfs_root *root) continue; } nr_truncate++; - btrfs_truncate(inode); + ret = btrfs_truncate(inode); } else { nr_unlink++; } /* this will do delete_inode and everything for us */ iput(inode); + if (ret) + goto out; } - btrfs_free_path(path); - root->orphan_cleanup_state = ORPHAN_CLEANUP_DONE; if (root->orphan_block_rsv) @@ -2396,14 +2403,20 @@ void btrfs_orphan_cleanup(struct btrfs_root *root) if (root->orphan_block_rsv || root->orphan_item_inserted) { trans = btrfs_join_transaction(root, 1); - BUG_ON(IS_ERR(trans)); - btrfs_end_transaction(trans, root); + if (!IS_ERR(trans)) + btrfs_end_transaction(trans, root); } if (nr_unlink) printk(KERN_INFO "btrfs: unlinked %d orphans\n", nr_unlink); if (nr_truncate) printk(KERN_INFO "btrfs: truncated %d orphans\n", nr_truncate); + +out: + if (ret) + printk(KERN_CRIT "btrfs: could not do orphan cleanup %d\n", ret); + btrfs_free_path(path); + return ret; } /* @@ -4156,8 +4169,10 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry) if (!IS_ERR(inode) && root != sub_root) { down_read(&root->fs_info->cleanup_work_sem); if (!(inode->i_sb->s_flags & MS_RDONLY)) - btrfs_orphan_cleanup(sub_root); + ret = btrfs_orphan_cleanup(sub_root); up_read(&root->fs_info->cleanup_work_sem); + if (ret) + inode = ERR_PTR(ret); } return inode; diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 5fdb2abc4fa7..ad9b8c0e930b 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -409,7 +409,9 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, if (ret) goto fail; - btrfs_orphan_cleanup(pending_snapshot->snap); + ret = btrfs_orphan_cleanup(pending_snapshot->snap); + if (ret) + goto fail; parent = dget_parent(dentry); inode = btrfs_lookup_dentry(parent->d_inode, dentry); diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 31ade5802ae8..c863c8447015 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -4209,7 +4209,7 @@ out: if (IS_ERR(fs_root)) err = PTR_ERR(fs_root); else - btrfs_orphan_cleanup(fs_root); + err = btrfs_orphan_cleanup(fs_root); } return err; } -- cgit From ded5db9de78f963979e1605f859de67626f54693 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Fri, 4 Mar 2011 14:09:46 -0500 Subject: Btrfs: make sure to remove the orphan item from the in-memory list This fixes a problem where if truncate fails the inode will still be on the in memory orphan list. This is will make us complain when the inode gets destroyed because it's still on the orphan list. So if we fail just remove us from the in memory list and carry on. Signed-off-by: Josef Bacik --- fs/btrfs/inode.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'fs') diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 0600265cb9b0..3bd0ff63bf30 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -6589,6 +6589,12 @@ static int btrfs_truncate(struct inode *inode) ret = btrfs_orphan_del(trans, inode); if (ret) err = ret; + } else if (ret && inode->i_nlink > 0) { + /* + * Failed to do the truncate, remove us from the in memory + * orphan list. + */ + ret = btrfs_orphan_del(NULL, inode); } ret = btrfs_update_inode(trans, root, inode); -- cgit From f0cd846e9221811d87047f1428cf5226e7236efe Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Fri, 4 Mar 2011 14:37:08 -0500 Subject: Btrfs: only add orphan items when truncating We don't need an orphan item when expanding files, we just need them for truncating them, so only add the orphan item in btrfs_truncate instead of in btrfs_setsize. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/inode.c | 45 ++++++++++++++++++--------------------------- 1 file changed, 18 insertions(+), 27 deletions(-) (limited to 'fs') diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 3bd0ff63bf30..206b60362cec 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -3649,22 +3649,6 @@ static int btrfs_setsize(struct inode *inode, loff_t newsize) if (newsize == oldsize) return 0; - trans = btrfs_start_transaction(root, 5); - if (IS_ERR(trans)) - return PTR_ERR(trans); - - btrfs_set_trans_block_group(trans, inode); - - ret = btrfs_orphan_add(trans, inode); - if (ret) { - btrfs_end_transaction(trans, root); - return ret; - } - - nr = trans->blocks_used; - btrfs_end_transaction(trans, root); - btrfs_btree_balance_dirty(root, nr); - if (newsize > oldsize) { i_size_write(inode, newsize); btrfs_ordered_update_i_size(inode, i_size_read(inode), NULL); @@ -3675,25 +3659,15 @@ static int btrfs_setsize(struct inode *inode, loff_t newsize) return ret; } - trans = btrfs_start_transaction(root, 0); + trans = btrfs_start_transaction(root, 1); if (IS_ERR(trans)) return PTR_ERR(trans); - btrfs_set_trans_block_group(trans, inode); - trans->block_rsv = root->orphan_block_rsv; - BUG_ON(!trans->block_rsv); - - /* - * If this fails just leave the orphan item so that it can get - * cleaned up next time we mount. - */ ret = btrfs_update_inode(trans, root, inode); if (ret) { btrfs_end_transaction(trans, root); return ret; } - if (inode->i_nlink > 0) - ret = btrfs_orphan_del(trans, inode); nr = trans->blocks_used; btrfs_end_transaction(trans, root); btrfs_btree_balance_dirty(root, nr); @@ -6517,6 +6491,23 @@ static int btrfs_truncate(struct inode *inode) btrfs_wait_ordered_range(inode, inode->i_size & (~mask), (u64)-1); btrfs_ordered_update_i_size(inode, inode->i_size, NULL); + trans = btrfs_start_transaction(root, 5); + if (IS_ERR(trans)) + return PTR_ERR(trans); + + btrfs_set_trans_block_group(trans, inode); + + ret = btrfs_orphan_add(trans, inode); + if (ret) { + btrfs_end_transaction(trans, root); + return ret; + } + + nr = trans->blocks_used; + btrfs_end_transaction(trans, root); + btrfs_btree_balance_dirty(root, nr); + + /* Now start a transaction for the truncate */ trans = btrfs_start_transaction(root, 0); if (IS_ERR(trans)) return PTR_ERR(trans); -- cgit From 930f028abe39dfd0849b53131d19c4b67aacbe67 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Fri, 4 Mar 2011 14:41:41 -0500 Subject: Btrfs: use mark_inode_dirty when expanding the file Mark_inode_dirty will call btrfs_dirty_inode which will take care of updating the inode. This makes setsize a little cleaner since we don't have to start a transaction and update the inode in there, we can just call mark_inode_dirty. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/inode.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) (limited to 'fs') diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 206b60362cec..64d57e032b4e 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -3640,10 +3640,7 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size) static int btrfs_setsize(struct inode *inode, loff_t newsize) { - struct btrfs_root *root = BTRFS_I(inode)->root; - struct btrfs_trans_handle *trans; loff_t oldsize = i_size_read(inode); - unsigned long nr; int ret; if (newsize == oldsize) @@ -3659,18 +3656,7 @@ static int btrfs_setsize(struct inode *inode, loff_t newsize) return ret; } - trans = btrfs_start_transaction(root, 1); - if (IS_ERR(trans)) - return PTR_ERR(trans); - - ret = btrfs_update_inode(trans, root, inode); - if (ret) { - btrfs_end_transaction(trans, root); - return ret; - } - nr = trans->blocks_used; - btrfs_end_transaction(trans, root); - btrfs_btree_balance_dirty(root, nr); + mark_inode_dirty(inode); } else { /* -- cgit From 695a0d0da09e75c4475bbb303def159023ef72ca Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Fri, 4 Mar 2011 15:46:53 -0500 Subject: Btrfs: add a comment explaining what btrfs_cont_expand does Everytime I have to deal with btrfs_cont_expand I stare at it for 20 minutes trying to remember what exactly it does and why the hell we need it. So add a comment to save future-Josef some time. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/inode.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'fs') diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 64d57e032b4e..888dbdb3b128 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -3557,6 +3557,12 @@ out: return ret; } +/* + * This function puts in dummy file extents for the area we're creating a hole + * for. So if we are truncating this file to a larger size we need to insert + * these file extents so that btrfs_get_extent will return a EXTENT_MAP_HOLE for + * the range between oldsize and size + */ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size) { struct btrfs_trans_handle *trans; -- cgit From 850265335f792f5d39ab24e5fb7160bac28d77e5 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Tue, 15 Mar 2011 14:52:12 -0400 Subject: Btrfs: return error if the range we want to map is bogus Currently if we have corrupt metadata map_extent_buffer will complain about it, but not return an error so the caller has no idea a problem was hit. Fix this. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/extent_io.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs') diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 714adc4ac4c2..1bbd26b4fc5c 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -3690,6 +3690,7 @@ int map_private_extent_buffer(struct extent_buffer *eb, unsigned long start, "wanted %lu %lu\n", (unsigned long long)eb->start, eb->len, start, min_len); WARN_ON(1); + return -EINVAL; } p = extent_buffer_page(eb, i); -- cgit From a826d6dcb32d811b4c81df57a5ef1367516586b0 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Wed, 16 Mar 2011 13:42:43 -0400 Subject: Btrfs: check items for correctness as we search Currently if we have corrupted items things will blow up in spectacular ways. So as we read in blocks and they are leaves, check the entire leaf to make sure all of the items are correct and point to valid parts in the leaf for the item data the are responsible for. If the item is corrupt we will kick back EIO and not read any of the copies since they are likely to not be correct either. This will catch generic corruptions, it will be up to the individual callers of btrfs_search_slot to make sure their items are right. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/ctree.c | 123 ------------------------------------------------- fs/btrfs/disk-io.c | 90 +++++++++++++++++++++++++++++++++++- fs/btrfs/extent-tree.c | 5 ++ fs/btrfs/extent_io.h | 1 + 4 files changed, 95 insertions(+), 124 deletions(-) (limited to 'fs') diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index b5baff0dccfe..73e53009e126 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -732,122 +732,6 @@ static inline unsigned int leaf_data_end(struct btrfs_root *root, return btrfs_item_offset_nr(leaf, nr - 1); } -/* - * extra debugging checks to make sure all the items in a key are - * well formed and in the proper order - */ -static int check_node(struct btrfs_root *root, struct btrfs_path *path, - int level) -{ - struct extent_buffer *parent = NULL; - struct extent_buffer *node = path->nodes[level]; - struct btrfs_disk_key parent_key; - struct btrfs_disk_key node_key; - int parent_slot; - int slot; - struct btrfs_key cpukey; - u32 nritems = btrfs_header_nritems(node); - - if (path->nodes[level + 1]) - parent = path->nodes[level + 1]; - - slot = path->slots[level]; - BUG_ON(nritems == 0); - if (parent) { - parent_slot = path->slots[level + 1]; - btrfs_node_key(parent, &parent_key, parent_slot); - btrfs_node_key(node, &node_key, 0); - BUG_ON(memcmp(&parent_key, &node_key, - sizeof(struct btrfs_disk_key))); - BUG_ON(btrfs_node_blockptr(parent, parent_slot) != - btrfs_header_bytenr(node)); - } - BUG_ON(nritems > BTRFS_NODEPTRS_PER_BLOCK(root)); - if (slot != 0) { - btrfs_node_key_to_cpu(node, &cpukey, slot - 1); - btrfs_node_key(node, &node_key, slot); - BUG_ON(comp_keys(&node_key, &cpukey) <= 0); - } - if (slot < nritems - 1) { - btrfs_node_key_to_cpu(node, &cpukey, slot + 1); - btrfs_node_key(node, &node_key, slot); - BUG_ON(comp_keys(&node_key, &cpukey) >= 0); - } - return 0; -} - -/* - * extra checking to make sure all the items in a leaf are - * well formed and in the proper order - */ -static int check_leaf(struct btrfs_root *root, struct btrfs_path *path, - int level) -{ - struct extent_buffer *leaf = path->nodes[level]; - struct extent_buffer *parent = NULL; - int parent_slot; - struct btrfs_key cpukey; - struct btrfs_disk_key parent_key; - struct btrfs_disk_key leaf_key; - int slot = path->slots[0]; - - u32 nritems = btrfs_header_nritems(leaf); - - if (path->nodes[level + 1]) - parent = path->nodes[level + 1]; - - if (nritems == 0) - return 0; - - if (parent) { - parent_slot = path->slots[level + 1]; - btrfs_node_key(parent, &parent_key, parent_slot); - btrfs_item_key(leaf, &leaf_key, 0); - - BUG_ON(memcmp(&parent_key, &leaf_key, - sizeof(struct btrfs_disk_key))); - BUG_ON(btrfs_node_blockptr(parent, parent_slot) != - btrfs_header_bytenr(leaf)); - } - if (slot != 0 && slot < nritems - 1) { - btrfs_item_key(leaf, &leaf_key, slot); - btrfs_item_key_to_cpu(leaf, &cpukey, slot - 1); - if (comp_keys(&leaf_key, &cpukey) <= 0) { - btrfs_print_leaf(root, leaf); - printk(KERN_CRIT "slot %d offset bad key\n", slot); - BUG_ON(1); - } - if (btrfs_item_offset_nr(leaf, slot - 1) != - btrfs_item_end_nr(leaf, slot)) { - btrfs_print_leaf(root, leaf); - printk(KERN_CRIT "slot %d offset bad\n", slot); - BUG_ON(1); - } - } - if (slot < nritems - 1) { - btrfs_item_key(leaf, &leaf_key, slot); - btrfs_item_key_to_cpu(leaf, &cpukey, slot + 1); - BUG_ON(comp_keys(&leaf_key, &cpukey) >= 0); - if (btrfs_item_offset_nr(leaf, slot) != - btrfs_item_end_nr(leaf, slot + 1)) { - btrfs_print_leaf(root, leaf); - printk(KERN_CRIT "slot %d offset bad\n", slot); - BUG_ON(1); - } - } - BUG_ON(btrfs_item_offset_nr(leaf, 0) + - btrfs_item_size_nr(leaf, 0) != BTRFS_LEAF_DATA_SIZE(root)); - return 0; -} - -static noinline int check_block(struct btrfs_root *root, - struct btrfs_path *path, int level) -{ - return 0; - if (level == 0) - return check_leaf(root, path, level); - return check_node(root, path, level); -} /* * search for key in the extent_buffer. The items start at offset p, @@ -1188,7 +1072,6 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, } } /* double check we haven't messed things up */ - check_block(root, path, level); if (orig_ptr != btrfs_node_blockptr(path->nodes[level], path->slots[level])) BUG(); @@ -1798,12 +1681,6 @@ cow_done: if (!cow) btrfs_unlock_up_safe(p, level + 1); - ret = check_block(root, p, level); - if (ret) { - ret = -1; - goto done; - } - ret = bin_search(b, key, level, &slot); if (level != 0) { diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 495b1ac45f8c..9f31e110b481 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -323,6 +323,7 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root, int num_copies = 0; int mirror_num = 0; + clear_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags); io_tree = &BTRFS_I(root->fs_info->btree_inode)->io_tree; while (1) { ret = read_extent_buffer_pages(io_tree, eb, start, 1, @@ -331,6 +332,14 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root, !verify_parent_transid(io_tree, eb, parent_transid)) return ret; + /* + * This buffer's crc is fine, but its contents are corrupted, so + * there is no reason to read the other copies, they won't be + * any less wrong. + */ + if (test_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags)) + return ret; + num_copies = btrfs_num_copies(&root->fs_info->mapping_tree, eb->start, eb->len); if (num_copies == 1) @@ -419,6 +428,73 @@ static int check_tree_block_fsid(struct btrfs_root *root, return ret; } +#define CORRUPT(reason, eb, root, slot) \ + printk(KERN_CRIT "btrfs: corrupt leaf, %s: block=%llu," \ + "root=%llu, slot=%d\n", reason, \ + (unsigned long long)btrfs_header_bytenr(eb), \ + (unsigned long long)root->objectid, slot) + +static noinline int check_leaf(struct btrfs_root *root, + struct extent_buffer *leaf) +{ + struct btrfs_key key; + struct btrfs_key leaf_key; + u32 nritems = btrfs_header_nritems(leaf); + int slot; + + if (nritems == 0) + return 0; + + /* Check the 0 item */ + if (btrfs_item_offset_nr(leaf, 0) + btrfs_item_size_nr(leaf, 0) != + BTRFS_LEAF_DATA_SIZE(root)) { + CORRUPT("invalid item offset size pair", leaf, root, 0); + return -EIO; + } + + /* + * Check to make sure each items keys are in the correct order and their + * offsets make sense. We only have to loop through nritems-1 because + * we check the current slot against the next slot, which verifies the + * next slot's offset+size makes sense and that the current's slot + * offset is correct. + */ + for (slot = 0; slot < nritems - 1; slot++) { + btrfs_item_key_to_cpu(leaf, &leaf_key, slot); + btrfs_item_key_to_cpu(leaf, &key, slot + 1); + + /* Make sure the keys are in the right order */ + if (btrfs_comp_cpu_keys(&leaf_key, &key) >= 0) { + CORRUPT("bad key order", leaf, root, slot); + return -EIO; + } + + /* + * Make sure the offset and ends are right, remember that the + * item data starts at the end of the leaf and grows towards the + * front. + */ + if (btrfs_item_offset_nr(leaf, slot) != + btrfs_item_end_nr(leaf, slot + 1)) { + CORRUPT("slot offset bad", leaf, root, slot); + return -EIO; + } + + /* + * Check to make sure that we don't point outside of the leaf, + * just incase all the items are consistent to eachother, but + * all point outside of the leaf. + */ + if (btrfs_item_end_nr(leaf, slot) > + BTRFS_LEAF_DATA_SIZE(root)) { + CORRUPT("slot end outside of leaf", leaf, root, slot); + return -EIO; + } + } + + return 0; +} + #ifdef CONFIG_DEBUG_LOCK_ALLOC void btrfs_set_buffer_lockdep_class(struct extent_buffer *eb, int level) { @@ -485,8 +561,20 @@ static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end, btrfs_set_buffer_lockdep_class(eb, found_level); ret = csum_tree_block(root, eb, 1); - if (ret) + if (ret) { ret = -EIO; + goto err; + } + + /* + * If this is a leaf block and it is corrupt, set the corrupt bit so + * that we don't try and read the other copies of this block, just + * return -EIO. + */ + if (found_level == 0 && check_leaf(root, eb)) { + set_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags); + ret = -EIO; + } end = min_t(u64, eb->len, PAGE_CACHE_SIZE); end = eb->start + end - 1; diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index a8f4e8d2ba60..cd794c35a636 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -4754,6 +4754,11 @@ pin: } } out: + /* + * Deleting the buffer, clear the corrupt flag since it doesn't matter + * anymore. + */ + clear_bit(EXTENT_BUFFER_CORRUPT, &buf->bflags); btrfs_put_block_group(cache); } diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index 9318dfefd59c..f62c5442835d 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h @@ -31,6 +31,7 @@ #define EXTENT_BUFFER_UPTODATE 0 #define EXTENT_BUFFER_BLOCKING 1 #define EXTENT_BUFFER_DIRTY 2 +#define EXTENT_BUFFER_CORRUPT 3 /* these are flags for extent_clear_unlock_delalloc */ #define EXTENT_CLEAR_UNLOCK_PAGE 0x1 -- cgit From 41415730a1050499fbd63b3f7dd59b3a4c3bb91a Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Wed, 16 Mar 2011 13:59:32 -0400 Subject: Btrfs: check return value of btrfs_search_slot properly Doing an audit of where we use btrfs_search_slot only showed one place where we don't check the return value of btrfs_search_slot properly. Just fix mark_extent_written to see if btrfs_search_slot failed and act accordingly. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/file.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'fs') diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 3786eca2a905..a85b044cf39e 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -608,6 +608,8 @@ again: key.offset = split; ret = btrfs_search_slot(trans, root, &key, path, -1, 1); + if (ret < 0) + goto out; if (ret > 0 && path->slots[0] > 0) path->slots[0]--; -- cgit From 22a94d44bd6876a90630338229da6c0436d46593 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Wed, 16 Mar 2011 16:47:17 -0400 Subject: Btrfs: add checks to verify dir items are correct We need to make sure the dir items we get are valid dir items. So any time we try and read one check it with verify_dir_item, which will do various sanity checks to make sure it looks sane. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/ctree.h | 3 +++ fs/btrfs/dir-item.c | 35 +++++++++++++++++++++++++++++++++++ fs/btrfs/inode.c | 3 +++ fs/btrfs/tree-log.c | 7 +++++++ fs/btrfs/xattr.c | 2 ++ 5 files changed, 50 insertions(+) (limited to 'fs') diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 841330f3d68d..6036fdb88c53 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -2393,6 +2393,9 @@ struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans, struct btrfs_path *path, u64 dir, const char *name, u16 name_len, int mod); +int verify_dir_item(struct btrfs_root *root, + struct extent_buffer *leaf, + struct btrfs_dir_item *dir_item); /* orphan.c */ int btrfs_insert_orphan_item(struct btrfs_trans_handle *trans, diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c index f0cad5ae5be7..02c97ad61b6d 100644 --- a/fs/btrfs/dir-item.c +++ b/fs/btrfs/dir-item.c @@ -377,6 +377,9 @@ struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root, leaf = path->nodes[0]; dir_item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_dir_item); + if (verify_dir_item(root, leaf, dir_item)) + return NULL; + total_len = btrfs_item_size_nr(leaf, path->slots[0]); while (cur < total_len) { this_len = sizeof(*dir_item) + @@ -429,3 +432,35 @@ int btrfs_delete_one_dir_name(struct btrfs_trans_handle *trans, } return ret; } + +int verify_dir_item(struct btrfs_root *root, + struct extent_buffer *leaf, + struct btrfs_dir_item *dir_item) +{ + u16 namelen = BTRFS_NAME_LEN; + u8 type = btrfs_dir_type(leaf, dir_item); + + if (type >= BTRFS_FT_MAX) { + printk(KERN_CRIT "btrfs: invalid dir item type: %d\n", + (int)type); + return 1; + } + + if (type == BTRFS_FT_XATTR) + namelen = XATTR_NAME_MAX; + + if (btrfs_dir_name_len(leaf, dir_item) > namelen) { + printk(KERN_CRIT "btrfS: invalid dir item name len: %u\n", + (unsigned)btrfs_dir_data_len(leaf, dir_item)); + return 1; + } + + /* BTRFS_MAX_XATTR_SIZE is the same for all dir items */ + if (btrfs_dir_data_len(leaf, dir_item) > BTRFS_MAX_XATTR_SIZE(root)) { + printk(KERN_CRIT "btrfs: invalid dir item data len: %u\n", + (unsigned)btrfs_dir_data_len(leaf, dir_item)); + return 1; + } + + return 0; +} diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 888dbdb3b128..e010000d4bc9 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -4272,6 +4272,9 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, while (di_cur < di_total) { struct btrfs_key location; + if (verify_dir_item(root, leaf, di)) + break; + name_len = btrfs_dir_name_len(leaf, di); if (name_len <= sizeof(tmp_name)) { name_ptr = tmp_name; diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index a4bbb854dfd2..429cfcfadf90 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -1286,6 +1286,8 @@ static noinline int replay_one_dir_item(struct btrfs_trans_handle *trans, ptr_end = ptr + item_size; while (ptr < ptr_end) { di = (struct btrfs_dir_item *)ptr; + if (verify_dir_item(root, eb, di)) + return -EIO; name_len = btrfs_dir_name_len(eb, di); ret = replay_one_name(trans, root, path, eb, di, key); BUG_ON(ret); @@ -1412,6 +1414,11 @@ again: ptr_end = ptr + item_size; while (ptr < ptr_end) { di = (struct btrfs_dir_item *)ptr; + if (verify_dir_item(root, eb, di)) { + ret = -EIO; + goto out; + } + name_len = btrfs_dir_name_len(eb, di); name = kmalloc(name_len, GFP_NOFS); if (!name) { diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c index a5776531dc2b..e5d22f280956 100644 --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c @@ -242,6 +242,8 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size) break; di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); + if (verify_dir_item(root, leaf, di)) + continue; name_len = btrfs_dir_name_len(leaf, di); total_size += name_len + 1; -- cgit From 4345caba340f051e10847924fc078ae18ed6695c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 19 Mar 2011 13:53:31 +0100 Subject: block: NULL dereference on error path in __blkdev_get() "disk" is always NULL when we goto out. There was a check for this before, but it was removed in 69e02c59a7d9 "block: Don't check events while open is in progress". Signed-off-by: Dan Carpenter Acked-by: Tejun Heo Signed-off-by: Jens Axboe --- fs/block_dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/block_dev.c b/fs/block_dev.c index fbe05cbdd692..7d02afb2b7f4 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1181,9 +1181,9 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) out_unlock_bdev: mutex_unlock(&bdev->bd_mutex); disk_unblock_events(disk); - out: module_put(disk->fops->owner); put_disk(disk); + out: bdput(bdev); return ret; -- cgit From ef6078930263bfcdcfe4dddb2cd85254b4cf4f5c Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Sun, 20 Mar 2011 21:18:44 -0400 Subject: ext4: handle errors in ext4_rename Checking return code from ext4_journal_get_write_access() is important with snapshots, because this function invokes COW, so may return new errors, such as ENOSPC. We move the call to ext4_journal_get_write_access earlier in the function, to simplify error handling in the case that this function returns returns an error. Signed-off-by: Amir Goldstein Signed-off-by: "Theodore Ts'o" --- fs/ext4/namei.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 5485390d32c5..ad87584aa8d2 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -2409,6 +2409,10 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, if (!new_inode && new_dir != old_dir && EXT4_DIR_LINK_MAX(new_dir)) goto end_rename; + BUFFER_TRACE(dir_bh, "get_write_access"); + retval = ext4_journal_get_write_access(handle, dir_bh); + if (retval) + goto end_rename; } if (!new_bh) { retval = ext4_add_entry(handle, new_dentry, old_inode); @@ -2416,7 +2420,9 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, goto end_rename; } else { BUFFER_TRACE(new_bh, "get write access"); - ext4_journal_get_write_access(handle, new_bh); + retval = ext4_journal_get_write_access(handle, new_bh); + if (retval) + goto end_rename; new_de->inode = cpu_to_le32(old_inode->i_ino); if (EXT4_HAS_INCOMPAT_FEATURE(new_dir->i_sb, EXT4_FEATURE_INCOMPAT_FILETYPE)) @@ -2477,8 +2483,6 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, old_dir->i_ctime = old_dir->i_mtime = ext4_current_time(old_dir); ext4_update_dx_flag(old_dir); if (dir_bh) { - BUFFER_TRACE(dir_bh, "get_write_access"); - ext4_journal_get_write_access(handle, dir_bh); PARENT_INO(dir_bh->b_data, new_dir->i_sb->s_blocksize) = cpu_to_le32(new_dir->i_ino); BUFFER_TRACE(dir_bh, "call ext4_handle_dirty_metadata"); -- cgit From 537a03103c67c4688b1e8e6671ad119aec5e2efb Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Sun, 20 Mar 2011 22:57:02 -0400 Subject: ext4: unify the ext4_handle_release_buffer() api There are two wrapper functions which do exactly the same thing: ext4_journal_release_buffer(), and ext4_handle_release_buffer(). In addition, ext4_xattr_block_set() calls jbd2_journal_release_buffer() directly. Unify all of the code to use ext4_handle_release_buffer(), and get rid of ext4_journal_release_buffer(). Signed-off-by: Amir Goldstein Signed-off-by: "Theodore Ts'o" --- fs/ext4/ext4_jbd2.h | 7 ------- fs/ext4/resize.c | 8 ++++---- fs/ext4/xattr.c | 2 +- 3 files changed, 5 insertions(+), 12 deletions(-) (limited to 'fs') diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h index d8b992e658c1..e25e99bf7ee1 100644 --- a/fs/ext4/ext4_jbd2.h +++ b/fs/ext4/ext4_jbd2.h @@ -202,13 +202,6 @@ static inline int ext4_handle_has_enough_credits(handle_t *handle, int needed) return 1; } -static inline void ext4_journal_release_buffer(handle_t *handle, - struct buffer_head *bh) -{ - if (ext4_handle_valid(handle)) - jbd2_journal_release_buffer(handle, bh); -} - static inline handle_t *ext4_journal_start(struct inode *inode, int nblocks) { return ext4_journal_start_sb(inode->i_sb, nblocks); diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 66fec4ee76fa..80bbc9c60c24 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -499,12 +499,12 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, return err; exit_inode: - /* ext4_journal_release_buffer(handle, iloc.bh); */ + /* ext4_handle_release_buffer(handle, iloc.bh); */ brelse(iloc.bh); exit_dindj: - /* ext4_journal_release_buffer(handle, dind); */ + /* ext4_handle_release_buffer(handle, dind); */ exit_sbh: - /* ext4_journal_release_buffer(handle, EXT4_SB(sb)->s_sbh); */ + /* ext4_handle_release_buffer(handle, EXT4_SB(sb)->s_sbh); */ exit_dind: brelse(dind); exit_bh: @@ -586,7 +586,7 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode, /* int j; for (j = 0; j < i; j++) - ext4_journal_release_buffer(handle, primary[j]); + ext4_handle_release_buffer(handle, primary[j]); */ goto exit_bh; } diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index f4c03af05d69..b545ca1c459c 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c @@ -735,7 +735,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, int offset = (char *)s->here - bs->bh->b_data; unlock_buffer(bs->bh); - jbd2_journal_release_buffer(handle, bs->bh); + ext4_handle_release_buffer(handle, bs->bh); if (ce) { mb_cache_entry_release(ce); ce = NULL; -- cgit From d67d1218344009970ba0deb7eb15a3984518ddd0 Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Sun, 20 Mar 2011 22:59:02 -0400 Subject: ext4: handle errors in ext4_clear_blocks() Checking return code from ext4_journal_get_write_access() is important with snapshots, because this function invokes COW, so may return new errors, such as ENOSPC. ext4_clear_blocks() now returns < 0 for fatal errors, in which case, ext4_free_data() is aborted. Signed-off-by: Amir Goldstein Signed-off-by: "Theodore Ts'o" --- fs/ext4/inode.c | 46 ++++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 20 deletions(-) (limited to 'fs') diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 67e7a3caf9ed..fc8c0ce84315 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -4096,6 +4096,9 @@ no_top: * * We release `count' blocks on disk, but (last - first) may be greater * than `count' because there can be holes in there. + * + * Return 0 on success, 1 on invalid block range + * and < 0 on fatal error. */ static int ext4_clear_blocks(handle_t *handle, struct inode *inode, struct buffer_head *bh, @@ -4122,25 +4125,21 @@ static int ext4_clear_blocks(handle_t *handle, struct inode *inode, if (bh) { BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); err = ext4_handle_dirty_metadata(handle, inode, bh); - if (unlikely(err)) { - ext4_std_error(inode->i_sb, err); - return 1; - } + if (unlikely(err)) + goto out_err; } err = ext4_mark_inode_dirty(handle, inode); - if (unlikely(err)) { - ext4_std_error(inode->i_sb, err); - return 1; - } + if (unlikely(err)) + goto out_err; err = ext4_truncate_restart_trans(handle, inode, blocks_for_truncate(inode)); - if (unlikely(err)) { - ext4_std_error(inode->i_sb, err); - return 1; - } + if (unlikely(err)) + goto out_err; if (bh) { BUFFER_TRACE(bh, "retaking write access"); - ext4_journal_get_write_access(handle, bh); + err = ext4_journal_get_write_access(handle, bh); + if (unlikely(err)) + goto out_err; } } @@ -4149,6 +4148,9 @@ static int ext4_clear_blocks(handle_t *handle, struct inode *inode, ext4_free_blocks(handle, inode, NULL, block_to_free, count, flags); return 0; +out_err: + ext4_std_error(inode->i_sb, err); + return err; } /** @@ -4182,7 +4184,7 @@ static void ext4_free_data(handle_t *handle, struct inode *inode, ext4_fsblk_t nr; /* Current block # */ __le32 *p; /* Pointer into inode/ind for current block */ - int err; + int err = 0; if (this_bh) { /* For indirect block */ BUFFER_TRACE(this_bh, "get_write_access"); @@ -4204,9 +4206,10 @@ static void ext4_free_data(handle_t *handle, struct inode *inode, } else if (nr == block_to_free + count) { count++; } else { - if (ext4_clear_blocks(handle, inode, this_bh, - block_to_free, count, - block_to_free_p, p)) + err = ext4_clear_blocks(handle, inode, this_bh, + block_to_free, count, + block_to_free_p, p); + if (err) break; block_to_free = nr; block_to_free_p = p; @@ -4215,9 +4218,12 @@ static void ext4_free_data(handle_t *handle, struct inode *inode, } } - if (count > 0) - ext4_clear_blocks(handle, inode, this_bh, block_to_free, - count, block_to_free_p, p); + if (!err && count > 0) + err = ext4_clear_blocks(handle, inode, this_bh, block_to_free, + count, block_to_free_p, p); + if (err < 0) + /* fatal error */ + return; if (this_bh) { BUFFER_TRACE(this_bh, "call ext4_handle_dirty_metadata"); -- cgit From a56e69c28ad0782a99f3f196e93d57ba5a7e2324 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Sun, 20 Mar 2011 23:16:58 -0400 Subject: ext4: add FITRIM to compat_ioctl. FITRIM isn't added in compat_ioctl. So a 32 bit program can't be executed in a 64 bit platform. Add it in the compat_ioctl. Signed-off-by: Tao Ma Signed-off-by: "Theodore Ts'o" --- fs/ext4/ioctl.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs') diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index c052c9f0f3a1..bb424de9953b 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -427,6 +427,7 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return err; } case EXT4_IOC_MOVE_EXT: + case FITRIM: break; default: return -ENOIOCTLCMD; -- cgit From 27a4f7e61e1eb4f18737926f4a66db7c48349fea Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Mon, 17 Jan 2011 00:48:17 +0900 Subject: vfs: cleanup do_vfs_ioctl() Move declaration of 'inode' to beginning of the function. Since it is referenced directly or indirectly (in case of FIFREEZE/FITHAW/ FS_IOC_FIEMAP) it's not harmful IMHO. And remove unnecessary casts using 'argp' instead. Signed-off-by: Namhyung Kim Signed-off-by: Al Viro --- fs/ioctl.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) (limited to 'fs') diff --git a/fs/ioctl.c b/fs/ioctl.c index 1eebeb72b202..1d9b9fcb2db4 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c @@ -548,6 +548,7 @@ int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, { int error = 0; int __user *argp = (int __user *)arg; + struct inode *inode = filp->f_path.dentry->d_inode; switch (cmd) { case FIOCLEX: @@ -567,13 +568,11 @@ int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, break; case FIOQSIZE: - if (S_ISDIR(filp->f_path.dentry->d_inode->i_mode) || - S_ISREG(filp->f_path.dentry->d_inode->i_mode) || - S_ISLNK(filp->f_path.dentry->d_inode->i_mode)) { - loff_t res = - inode_get_bytes(filp->f_path.dentry->d_inode); - error = copy_to_user((loff_t __user *)arg, &res, - sizeof(res)) ? -EFAULT : 0; + if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode) || + S_ISLNK(inode->i_mode)) { + loff_t res = inode_get_bytes(inode); + error = copy_to_user(argp, &res, sizeof(res)) ? + -EFAULT : 0; } else error = -ENOTTY; break; @@ -590,14 +589,10 @@ int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, return ioctl_fiemap(filp, arg); case FIGETBSZ: - { - struct inode *inode = filp->f_path.dentry->d_inode; - int __user *p = (int __user *)arg; - return put_user(inode->i_sb->s_blocksize, p); - } + return put_user(inode->i_sb->s_blocksize, argp); default: - if (S_ISREG(filp->f_path.dentry->d_inode->i_mode)) + if (S_ISREG(inode->i_mode)) error = file_ioctl(filp, cmd, arg); else error = vfs_ioctl(filp, cmd, arg); -- cgit From 2c3d44dc4a1262168ef31bef22b3aa554c0572d8 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Fri, 21 Jan 2011 13:59:59 +0900 Subject: select: remove unused MAX_SELECT_SECONDS Remove the leftover from the commit 8ff3e8e85fa6 ("select: switch select() and poll() over to hrtimers"). Signed-off-by: Namhyung Kim Acked-by: Arjan van de Ven Signed-off-by: Al Viro --- fs/compat.c | 3 --- fs/select.c | 3 --- 2 files changed, 6 deletions(-) (limited to 'fs') diff --git a/fs/compat.c b/fs/compat.c index c6d31a3bab88..72fe6cda9108 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -1671,9 +1671,6 @@ int compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset, * Update: ERESTARTSYS breaks at least the xview clock binary, so * I'm trying ERESTARTNOHAND which restart only when you want to. */ -#define MAX_SELECT_SECONDS \ - ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1) - int compat_core_sys_select(int n, compat_ulong_t __user *inp, compat_ulong_t __user *outp, compat_ulong_t __user *exp, struct timespec *end_time) diff --git a/fs/select.c b/fs/select.c index e56560d2b08a..d33418fdc858 100644 --- a/fs/select.c +++ b/fs/select.c @@ -517,9 +517,6 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) * Update: ERESTARTSYS breaks at least the xview clock binary, so * I'm trying ERESTARTNOHAND which restart only when you want to. */ -#define MAX_SELECT_SECONDS \ - ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1) - int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, struct timespec *end_time) { -- cgit From eaae668d01e15435cf977cced3975ccc436257fc Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 15 Feb 2011 12:48:09 +0000 Subject: fs/inode: Fix kernel-doc format for inode_init_owner Signed-off-by: Ben Hutchings Signed-off-by: Al Viro --- fs/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/inode.c b/fs/inode.c index 9910c039f026..16fefd373fc2 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -1715,7 +1715,7 @@ void init_special_inode(struct inode *inode, umode_t mode, dev_t rdev) EXPORT_SYMBOL(init_special_inode); /** - * Init uid,gid,mode for new inode according to posix standards + * inode_init_owner - Init uid,gid,mode for new inode according to posix standards * @inode: New inode * @dir: Directory inode * @mode: mode of the new inode -- cgit From ff38c083ad3bb8dbbed80aa9090fcc96bc4af7db Mon Sep 17 00:00:00 2001 From: David Jenni Date: Wed, 23 Feb 2011 16:51:05 +0100 Subject: Filesystem: fifo: Fixed coding style issue. Fixed coding style issue. Signed-off-by: David Jenni Signed-off-by: Al Viro --- fs/fifo.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/fifo.c b/fs/fifo.c index 4e303c22d5ee..b1a524d798e7 100644 --- a/fs/fifo.c +++ b/fs/fifo.c @@ -66,8 +66,7 @@ static int fifo_open(struct inode *inode, struct file *filp) /* suppress POLLHUP until we have * seen a writer */ filp->f_version = pipe->w_counter; - } else - { + } else { wait_for_partner(inode, &pipe->w_counter); if(signal_pending(current)) goto err_rd; -- cgit From 1bef82917c74249ff21982127e57defd6ca2bb1b Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Thu, 24 Feb 2011 17:46:49 +0100 Subject: Small typo fix... Hi, I was backporting the coredump over pipe feature and noticed this small typo, I wish I would have something bigger to contribute... >From 15d6080e0ed4267da103c706917a33b1015e8804 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Thu, 24 Feb 2011 17:42:50 +0100 Subject: [PATCH] fs: Fix a small typo in the comment The function is called umh_pipe_setup not uhm_pipe_setup. Signed-off-by: Holger Hans Peter Freyther Signed-off-by: Al Viro --- fs/exec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/exec.c b/fs/exec.c index ba99e1abb1aa..5e62d26a4fec 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1875,7 +1875,7 @@ static void wait_for_dump_helpers(struct file *file) /* - * uhm_pipe_setup + * umh_pipe_setup * helper function to customize the process used * to collect the core in userspace. Specifically * it sets up a pipe and installs it as fd 0 (stdin) -- cgit From b7ed78f56575074f29ec99d8984f347f6c99c914 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Thu, 10 Mar 2011 11:31:30 -0800 Subject: introduce sys_syncfs to sync a single file system It is frequently useful to sync a single file system, instead of all mounted file systems via sync(2): - On machines with many mounts, it is not at all uncommon for some of them to hang (e.g. unresponsive NFS server). sync(2) will get stuck on those and may never get to the one you do care about (e.g., /). - Some applications write lots of data to the file system and then want to make sure it is flushed to disk. Calling fsync(2) on each file introduces unnecessary ordering constraints that result in a large amount of sub-optimal writeback/flush/commit behavior by the file system. There are currently two ways (that I know of) to sync a single super_block: - BLKFLSBUF ioctl on the block device: That also invalidates the bdev mapping, which isn't usually desirable, and doesn't work for non-block file systems. - 'mount -o remount,rw' will call sync_filesystem as an artifact of the current implemention. Relying on this little-known side effect for something like data safety sounds foolish. Both of these approaches require root privileges, which some applications do not have (nor should they need?) given that sync(2) is an unprivileged operation. This patch introduces a new system call syncfs(2) that takes an fd and syncs only the file system it references. Maybe someday we can $ sync /some/path and not get sync: ignoring all arguments The syscall is motivated by comments by Al and Christoph at the last LSF. syncfs(2) seems like an appropriate name given statfs(2). A similar ioctl was also proposed a while back, see http://marc.info/?l=linux-fsdevel&m=127970513829285&w=2 Signed-off-by: Sage Weil Signed-off-by: Al Viro --- fs/sync.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'fs') diff --git a/fs/sync.c b/fs/sync.c index ba76b9623e7e..92ca208777d5 100644 --- a/fs/sync.c +++ b/fs/sync.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -128,6 +129,29 @@ void emergency_sync(void) } } +/* + * sync a single super + */ +SYSCALL_DEFINE1(syncfs, int, fd) +{ + struct file *file; + struct super_block *sb; + int ret; + int fput_needed; + + file = fget_light(fd, &fput_needed); + if (!file) + return -EBADF; + sb = file->f_dentry->d_sb; + + down_read(&sb->s_umount); + ret = sync_filesystem(sb); + up_read(&sb->s_umount); + + fput_light(file, fput_needed); + return ret; +} + /** * vfs_fsync_range - helper to sync a range of data & metadata to disk * @file: file to sync -- cgit From a872d5101008b091035d579897bccefdeff70def Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Fri, 18 Mar 2011 11:44:48 -0700 Subject: pstore: fix leaking ->i_private Move kfree() of i_private out of ->unlink() and into ->evict_inode() Signed-off-by: Tony Luck Signed-off-by: Al Viro --- fs/pstore/inode.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c index 08342232cb1c..f777f2902c49 100644 --- a/fs/pstore/inode.c +++ b/fs/pstore/inode.c @@ -73,11 +73,16 @@ static int pstore_unlink(struct inode *dir, struct dentry *dentry) struct pstore_private *p = dentry->d_inode->i_private; p->erase(p->id); - kfree(p); return simple_unlink(dir, dentry); } +static void pstore_evict_inode(struct inode *inode) +{ + end_writeback(inode); + kfree(inode->i_private); +} + static const struct inode_operations pstore_dir_inode_operations = { .lookup = simple_lookup, .unlink = pstore_unlink, @@ -110,6 +115,7 @@ static struct inode *pstore_get_inode(struct super_block *sb, static const struct super_operations pstore_ops = { .statfs = simple_statfs, .drop_inode = generic_delete_inode, + .evict_inode = pstore_evict_inode, .show_options = generic_show_options, }; -- cgit From 1c34092adf1feaba25b7c739cc4def2751f4fa05 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sun, 20 Mar 2011 14:22:07 +0300 Subject: nfs: lock() vs unlock() typo These should be spin_unlock() instead of spin_lock(). It's a typo. Signed-off-by: Dan Carpenter Signed-off-by: Al Viro --- fs/nfs/namespace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index c0b8344db0c6..bf1c68009ffd 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c @@ -98,7 +98,7 @@ rename_retry: namelen--; buflen -= namelen; if (buflen < 0) { - spin_lock(&dentry->d_lock); + spin_unlock(&dentry->d_lock); rcu_read_unlock(); goto Elong; } @@ -108,7 +108,7 @@ rename_retry: rcu_read_unlock(); return end; Elong_unlock: - spin_lock(&dentry->d_lock); + spin_unlock(&dentry->d_lock); rcu_read_unlock(); if (read_seqretry(&rename_lock, seq)) goto rename_retry; -- cgit From aa597bc1f9476d0527e35d6dd9b481422e8205a0 Mon Sep 17 00:00:00 2001 From: Andrey Vagin Date: Tue, 8 Feb 2011 00:14:52 +0300 Subject: fs: devpts_pty_new() return -ENOMEM if dentry allocation failed In this case nobody can open a slave point, so will be better return from devpts_pty_new() Now we should not check error code from d_find_alias() in devpts_pty_kill(), because the dentry exists all times. Signed-off-by: Andrey Vagin Signed-off-by: Al Viro --- fs/devpts/inode.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'fs') diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index 1bb547c9cad6..c6bd815dc794 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c @@ -479,6 +479,7 @@ int devpts_pty_new(struct inode *ptmx_inode, struct tty_struct *tty) struct dentry *root = sb->s_root; struct pts_fs_info *fsi = DEVPTS_SB(sb); struct pts_mount_opts *opts = &fsi->mount_opts; + int ret = 0; char s[12]; /* We're supposed to be given the slave end of a pty */ @@ -504,11 +505,14 @@ int devpts_pty_new(struct inode *ptmx_inode, struct tty_struct *tty) if (!IS_ERR(dentry)) { d_add(dentry, inode); fsnotify_create(root->d_inode, dentry); + } else { + iput(inode); + ret = -ENOMEM; } mutex_unlock(&root->d_inode->i_mutex); - return 0; + return ret; } struct tty_struct *devpts_get_tty(struct inode *pts_inode, int number) @@ -544,17 +548,12 @@ void devpts_pty_kill(struct tty_struct *tty) mutex_lock(&root->d_inode->i_mutex); dentry = d_find_alias(inode); - if (IS_ERR(dentry)) - goto out; - - if (dentry) { - inode->i_nlink--; - d_delete(dentry); - dput(dentry); /* d_alloc_name() in devpts_pty_new() */ - } + inode->i_nlink--; + d_delete(dentry); + dput(dentry); /* d_alloc_name() in devpts_pty_new() */ dput(dentry); /* d_find_alias above */ -out: + mutex_unlock(&root->d_inode->i_mutex); } -- cgit From c212f9aaf9101a037fb7f59e75e639437e11d758 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Wed, 19 Jan 2011 21:08:41 +0900 Subject: fs: Use BUG_ON(!mnt) at dentry_open(). dentry_open() requires callers to pass a valid vfsmount. Signed-off-by: Tetsuo Handa Signed-off-by: Al Viro --- fs/open.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) (limited to 'fs') diff --git a/fs/open.c b/fs/open.c index f83ca80cc59a..b52cf013ffa1 100644 --- a/fs/open.c +++ b/fs/open.c @@ -835,17 +835,8 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags, validate_creds(cred); - /* - * We must always pass in a valid mount pointer. Historically - * callers got away with not passing it, but we must enforce this at - * the earliest possible point now to avoid strange problems deep in the - * filesystem stack. - */ - if (!mnt) { - printk(KERN_WARNING "%s called with NULL vfsmount\n", __func__); - dump_stack(); - return ERR_PTR(-EINVAL); - } + /* We must always pass in a valid mount pointer. */ + BUG_ON(!mnt); error = -ENFILE; f = get_empty_filp(); -- cgit From 69b195be51620d72956acbf3029adad5765695dc Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 21 Mar 2011 08:32:53 -0400 Subject: bfs: fix bitmap size argument to find_first_zero_bit() The usage of find_first_zero_bit() in bfs_create() is wrong for two reasons. The bitmap size argument to find_first_zero_bit() is info->si_lasti but the correct bitmap size is info->si_lasti + 1 as info->si_lasti is the last valid index in info->si_imap bitmap. Another problem is that it is impossible to detect that info->si_imap bitmap is full because there is an off-by-one bug in the return value check for find_first_zero_bit(). If no zero bits exist in info->si_imap, find_first_zero_bit() returns info->si_lasti. But the check can't catch it due to the off-by-one. Signed-off-by: Akinobu Mita Acked-by: "Tigran A. Aivazian" Signed-off-by: Andrew Morton Signed-off-by: Al Viro --- fs/bfs/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c index 685ecff3ab31..b14cebfd9047 100644 --- a/fs/bfs/dir.c +++ b/fs/bfs/dir.c @@ -97,7 +97,7 @@ static int bfs_create(struct inode *dir, struct dentry *dentry, int mode, if (!inode) return -ENOSPC; mutex_lock(&info->bfs_lock); - ino = find_first_zero_bit(info->si_imap, info->si_lasti); + ino = find_first_zero_bit(info->si_imap, info->si_lasti + 1); if (ino > info->si_lasti) { mutex_unlock(&info->bfs_lock); iput(inode); -- cgit From 07d5f69b457019eda4ca568923b1d62b7ada89e1 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 21 Mar 2011 13:58:05 +0100 Subject: fuse: reduce size of struct fuse_request Reduce the size of struct fuse_request by removing cuse_init_out from the request structure and allocating it dinamically instead. CC: Tejun Heo Signed-off-by: Miklos Szeredi --- fs/fuse/cuse.c | 12 ++++++++++-- fs/fuse/fuse_i.h | 1 - 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c index 3e87cce5837d..124b697ef09d 100644 --- a/fs/fuse/cuse.c +++ b/fs/fuse/cuse.c @@ -305,7 +305,7 @@ static void cuse_gendev_release(struct device *dev) static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req) { struct cuse_conn *cc = fc_to_cc(fc); - struct cuse_init_out *arg = &req->misc.cuse_init_out; + struct cuse_init_out *arg = req->out.args[0].value; struct page *page = req->pages[0]; struct cuse_devinfo devinfo = { }; struct device *dev; @@ -384,6 +384,7 @@ static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req) dev_set_uevent_suppress(dev, 0); kobject_uevent(&dev->kobj, KOBJ_ADD); out: + kfree(arg); __free_page(page); return; @@ -405,6 +406,7 @@ static int cuse_send_init(struct cuse_conn *cc) struct page *page; struct fuse_conn *fc = &cc->fc; struct cuse_init_in *arg; + void *outarg; BUILD_BUG_ON(CUSE_INIT_INFO_MAX > PAGE_SIZE); @@ -419,6 +421,10 @@ static int cuse_send_init(struct cuse_conn *cc) if (!page) goto err_put_req; + outarg = kzalloc(sizeof(struct cuse_init_out), GFP_KERNEL); + if (!outarg) + goto err_free_page; + arg = &req->misc.cuse_init_in; arg->major = FUSE_KERNEL_VERSION; arg->minor = FUSE_KERNEL_MINOR_VERSION; @@ -429,7 +435,7 @@ static int cuse_send_init(struct cuse_conn *cc) req->in.args[0].value = arg; req->out.numargs = 2; req->out.args[0].size = sizeof(struct cuse_init_out); - req->out.args[0].value = &req->misc.cuse_init_out; + req->out.args[0].value = outarg; req->out.args[1].size = CUSE_INIT_INFO_MAX; req->out.argvar = 1; req->out.argpages = 1; @@ -440,6 +446,8 @@ static int cuse_send_init(struct cuse_conn *cc) return 0; +err_free_page: + __free_page(page); err_put_req: fuse_put_request(fc, req); err: diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index d4286947bc2c..b788becada76 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -272,7 +272,6 @@ struct fuse_req { struct fuse_init_in init_in; struct fuse_init_out init_out; struct cuse_init_in cuse_init_in; - struct cuse_init_out cuse_init_out; struct { struct fuse_read_in in; u64 attr_ver; -- cgit From 357ccf2b69bcefa650a54db83702381d1c9d6959 Mon Sep 17 00:00:00 2001 From: Bryan Green Date: Tue, 1 Mar 2011 16:43:52 -0800 Subject: fuse: wakeup pollers on connection release/abort If a fuse dev connection is broken, wake up any processes that are blocking, in a poll system call, on one of the files in the now defunct filesystem. Signed-off-by: Miklos Szeredi --- fs/fuse/dev.c | 17 +++++++++++++++++ fs/fuse/file.c | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index cf8d28d1fbad..213d3cf4f5e9 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -1910,6 +1910,21 @@ __acquires(fc->lock) kfree(dequeue_forget(fc, 1, NULL)); } +static void end_polls(struct fuse_conn *fc) +{ + struct rb_node *p; + + p = rb_first(&fc->polled_files); + + while (p) { + struct fuse_file *ff; + ff = rb_entry(p, struct fuse_file, polled_node); + wake_up_interruptible_all(&ff->poll_wait); + + p = rb_next(p); + } +} + /* * Abort all requests. * @@ -1937,6 +1952,7 @@ void fuse_abort_conn(struct fuse_conn *fc) fc->blocked = 0; end_io_requests(fc); end_queued_requests(fc); + end_polls(fc); wake_up_all(&fc->waitq); wake_up_all(&fc->blocked_waitq); kill_fasync(&fc->fasync, SIGIO, POLL_IN); @@ -1953,6 +1969,7 @@ int fuse_dev_release(struct inode *inode, struct file *file) fc->connected = 0; fc->blocked = 0; end_queued_requests(fc); + end_polls(fc); wake_up_all(&fc->blocked_waitq); spin_unlock(&fc->lock); fuse_conn_put(fc); diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 9e0832dbb1e3..6ea00734984e 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -222,7 +222,7 @@ static void fuse_prepare_release(struct fuse_file *ff, int flags, int opcode) rb_erase(&ff->polled_node, &fc->polled_files); spin_unlock(&fc->lock); - wake_up_interruptible_sync(&ff->poll_wait); + wake_up_interruptible_all(&ff->poll_wait); inarg->fh = ff->fh; inarg->flags = flags; -- cgit From 19690ddb65dbfc7be1b411fce12d3332acefbfb5 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 21 Mar 2011 13:58:06 +0100 Subject: fuse: make fuse_permission() RCU aware Only bail out of fuse_permission() on IPERM_FLAG_RCU when blocking is actually necessary. CC: Nick Piggin Signed-off-by: Miklos Szeredi --- fs/fuse/dir.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) (limited to 'fs') diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 8bd0ef9286c3..3b84b913b16e 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -970,6 +970,14 @@ static int fuse_access(struct inode *inode, int mask) return err; } +static int fuse_perm_getattr(struct inode *inode, int flags) +{ + if (flags & IPERM_FLAG_RCU) + return -ECHILD; + + return fuse_do_getattr(inode, NULL, NULL); +} + /* * Check permission. The two basic access models of FUSE are: * @@ -989,9 +997,6 @@ static int fuse_permission(struct inode *inode, int mask, unsigned int flags) bool refreshed = false; int err = 0; - if (flags & IPERM_FLAG_RCU) - return -ECHILD; - if (!fuse_allow_task(fc, current)) return -EACCES; @@ -1000,9 +1005,15 @@ static int fuse_permission(struct inode *inode, int mask, unsigned int flags) */ if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) || ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) { - err = fuse_update_attributes(inode, NULL, NULL, &refreshed); - if (err) - return err; + struct fuse_inode *fi = get_fuse_inode(inode); + + if (fi->i_time < get_jiffies_64()) { + refreshed = true; + + err = fuse_perm_getattr(inode, flags); + if (err) + return err; + } } if (fc->flags & FUSE_DEFAULT_PERMISSIONS) { @@ -1012,7 +1023,7 @@ static int fuse_permission(struct inode *inode, int mask, unsigned int flags) attributes. This is also needed, because the root node will at first have no permissions */ if (err == -EACCES && !refreshed) { - err = fuse_do_getattr(inode, NULL, NULL); + err = fuse_perm_getattr(inode, flags); if (!err) err = generic_permission(inode, mask, flags, NULL); @@ -1023,13 +1034,16 @@ static int fuse_permission(struct inode *inode, int mask, unsigned int flags) noticed immediately, only after the attribute timeout has expired */ } else if (mask & (MAY_ACCESS | MAY_CHDIR)) { + if (flags & IPERM_FLAG_RCU) + return -ECHILD; + err = fuse_access(inode, mask); } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) { if (!(inode->i_mode & S_IXUGO)) { if (refreshed) return -EACCES; - err = fuse_do_getattr(inode, NULL, NULL); + err = fuse_perm_getattr(inode, flags); if (!err && !(inode->i_mode & S_IXUGO)) return -EACCES; } -- cgit From e7c0a167860620bd2938366896964f729ddaeaaa Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 21 Mar 2011 13:58:06 +0100 Subject: fuse: make fuse_dentry_revalidate() RCU aware Only bail out of fuse_dentry_revalidate() on LOOKUP_RCU when blocking is actually necessary. CC: Nick Piggin Signed-off-by: Miklos Szeredi --- fs/fuse/dir.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 3b84b913b16e..c6ba49bd95b3 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -158,10 +158,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd) { struct inode *inode; - if (nd && nd->flags & LOOKUP_RCU) - return -ECHILD; - - inode = entry->d_inode; + inode = ACCESS_ONCE(entry->d_inode); if (inode && is_bad_inode(inode)) return 0; else if (fuse_dentry_time(entry) < get_jiffies_64()) { @@ -177,6 +174,9 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd) if (!inode) return 0; + if (nd->flags & LOOKUP_RCU) + return -ECHILD; + fc = get_fuse_conn(inode); req = fuse_get_req(fc); if (IS_ERR(req)) -- cgit From 7d0d2e8e6b6f7da221a25238cf490a095c8c4788 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Fri, 18 Mar 2011 15:13:42 -0400 Subject: Btrfs: check free space in block group before searching for a cluster The free space cluster stuff is heavy duty, so there is no sense in going through the entire song and dance if there isn't enough space in the block group to begin with. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/free-space-cache.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'fs') diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 0282033041e1..f631df870f64 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -1999,6 +1999,16 @@ int btrfs_find_space_cluster(struct btrfs_trans_handle *trans, min_bytes = max(bytes, (bytes + empty_size) >> 2); spin_lock(&block_group->tree_lock); + + /* + * If we know we don't have enough space to make a cluster don't even + * bother doing all the work to try and find one. + */ + if (block_group->free_space < min_bytes) { + spin_unlock(&block_group->tree_lock); + return -ENOSPC; + } + spin_lock(&cluster->lock); /* someone already found a cluster, hooray */ -- cgit From d0a365e84a886ce6b5b7f7a76be0bb24934ec8f0 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Fri, 18 Mar 2011 15:27:43 -0400 Subject: Btrfs: deal with min_bytes appropriately when looking for a cluster We do all this fun stuff with min_bytes, but either don't use it in the case of just normal extents, or use it completely wrong in the case of bitmaps. So fix this for both cases 1) In the extent case, stop looking for space with window_free >= min_bytes instead of bytes + empty_size. 2) In the bitmap case, we were looking for streches of free space that was at least min_bytes in size, which was not right at all. So instead search for stretches of free space that are at least bytes in size (this will make a difference when we have > page size blocks) and then only search for min_bytes amount of free space. Thanks, Reviewed-by: Li Zefan Signed-off-by: Josef Bacik --- fs/btrfs/free-space-cache.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index f631df870f64..63776ae72f9e 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -1910,8 +1910,8 @@ static int btrfs_bitmap_cluster(struct btrfs_block_group_cache *block_group, i = offset_to_bit(entry->offset, block_group->sectorsize, max_t(u64, offset, entry->offset)); - search_bits = bytes_to_bits(min_bytes, block_group->sectorsize); - total_bits = bytes_to_bits(bytes, block_group->sectorsize); + search_bits = bytes_to_bits(bytes, block_group->sectorsize); + total_bits = bytes_to_bits(min_bytes, block_group->sectorsize); again: found_bits = 0; @@ -2034,8 +2034,7 @@ again: if (entry->bitmap && entry->bytes > bytes + empty_size) { ret = btrfs_bitmap_cluster(block_group, entry, cluster, - offset, bytes + empty_size, - min_bytes); + offset, bytes, min_bytes); if (!ret) goto got_it; } @@ -2065,7 +2064,7 @@ again: while (1) { /* out window is just right, lets fill it */ - if (window_free >= bytes + empty_size) + if (window_free >= min_bytes) break; node = rb_next(&last->offset_index); -- cgit From 32cb0840ce8e13901fe71a9a8e834a531802ffc4 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Fri, 18 Mar 2011 16:16:21 -0400 Subject: Btrfs: don't be as aggressive about using bitmaps We have been creating bitmaps for small extents unconditionally forever. This was great when testing to make sure the bitmap stuff was working, but is overkill normally. So instead of always adding small chunks of free space to bitmaps, only start doing it if we go past half of our extent threshold. This will keeps us from creating a bitmap for just one small free extent at the front of the block group, and will make the allocator a little faster as a result. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/free-space-cache.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 63776ae72f9e..4ab35ea0443f 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -1287,9 +1287,22 @@ static int insert_into_bitmap(struct btrfs_block_group_cache *block_group, * If we are below the extents threshold then we can add this as an * extent, and don't have to deal with the bitmap */ - if (block_group->free_extents < block_group->extents_thresh && - info->bytes > block_group->sectorsize * 4) - return 0; + if (block_group->free_extents < block_group->extents_thresh) { + /* + * If this block group has some small extents we don't want to + * use up all of our free slots in the cache with them, we want + * to reserve them to larger extents, however if we have plent + * of cache left then go ahead an dadd them, no sense in adding + * the overhead of a bitmap if we don't have to. + */ + if (info->bytes <= block_group->sectorsize * 4) { + if (block_group->free_extents * 2 <= + block_group->extents_thresh) + return 0; + } else { + return 0; + } + } /* * some block groups are so tiny they can't be enveloped by a bitmap, so -- cgit From 0f60f240d522772467c7d2cebedb910748c78ed4 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 21 Mar 2011 14:28:58 +0000 Subject: FS: lookup_mnt() is only used in the core fs routines now lookup_mnt() is only used in the core fs routines now, so it doesn't need to be globally declared anymore. It isn't exported to modules at the moment, so nothing that can be modularised seems to be using it. Signed-off-by: David Howells Signed-off-by: Al Viro --- fs/internal.h | 1 + 1 file changed, 1 insertion(+) (limited to 'fs') diff --git a/fs/internal.h b/fs/internal.h index 17191546d527..8318059b42c6 100644 --- a/fs/internal.h +++ b/fs/internal.h @@ -64,6 +64,7 @@ extern int copy_mount_string(const void __user *, char **); extern unsigned int mnt_get_count(struct vfsmount *mnt); extern struct vfsmount *__lookup_mnt(struct vfsmount *, struct dentry *, int); +extern struct vfsmount *lookup_mnt(struct path *); extern void mnt_set_mountpoint(struct vfsmount *, struct dentry *, struct vfsmount *); extern void release_mounts(struct list_head *); -- cgit From 21f3b5f1bbc3c27e82a8c9fc9861fa20bcb31f26 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Wed, 19 Jan 2011 09:45:22 -0800 Subject: ceph: remove debugfs debug cruft Whoops! Signed-off-by: Sage Weil --- fs/ceph/debugfs.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'fs') diff --git a/fs/ceph/debugfs.c b/fs/ceph/debugfs.c index 08f65faac112..0dba6915712b 100644 --- a/fs/ceph/debugfs.c +++ b/fs/ceph/debugfs.c @@ -210,8 +210,6 @@ int ceph_fs_debugfs_init(struct ceph_fs_client *fsc) if (!fsc->debugfs_congestion_kb) goto out; - dout("a\n"); - snprintf(name, sizeof(name), "../../bdi/%s", dev_name(fsc->backing_dev_info.dev)); fsc->debugfs_bdi = @@ -221,7 +219,6 @@ int ceph_fs_debugfs_init(struct ceph_fs_client *fsc) if (!fsc->debugfs_bdi) goto out; - dout("b\n"); fsc->debugfs_mdsmap = debugfs_create_file("mdsmap", 0600, fsc->client->debugfs_dir, @@ -230,7 +227,6 @@ int ceph_fs_debugfs_init(struct ceph_fs_client *fsc) if (!fsc->debugfs_mdsmap) goto out; - dout("ca\n"); fsc->debugfs_mdsc = debugfs_create_file("mdsc", 0600, fsc->client->debugfs_dir, @@ -239,7 +235,6 @@ int ceph_fs_debugfs_init(struct ceph_fs_client *fsc) if (!fsc->debugfs_mdsc) goto out; - dout("da\n"); fsc->debugfs_caps = debugfs_create_file("caps", 0400, fsc->client->debugfs_dir, @@ -248,7 +243,6 @@ int ceph_fs_debugfs_init(struct ceph_fs_client *fsc) if (!fsc->debugfs_caps) goto out; - dout("ea\n"); fsc->debugfs_dentry_lru = debugfs_create_file("dentry_lru", 0600, fsc->client->debugfs_dir, -- cgit From ad1fee96cbaf873520064252c5dc3212c9844861 Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Fri, 21 Jan 2011 16:44:03 -0800 Subject: ceph: add ino32 mount option The ino32 mount option forces the ceph fs to report 32 bit ino values. This is useful for 64 bit kernels with 32 bit userspace. Signed-off-by: Yehuda Sadeh --- fs/ceph/dir.c | 11 ++++++---- fs/ceph/inode.c | 9 +++++++- fs/ceph/super.c | 5 +++++ fs/ceph/super.h | 65 +++++++++++++++++++++++++++++++++++++++------------------ 4 files changed, 65 insertions(+), 25 deletions(-) (limited to 'fs') diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index ebafa65a29b6..cbe875d3a522 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -161,7 +161,7 @@ more: filp->f_pos = di->offset; err = filldir(dirent, dentry->d_name.name, dentry->d_name.len, di->offset, - dentry->d_inode->i_ino, + ceph_translate_ino(dentry->d_sb, dentry->d_inode->i_ino), dentry->d_inode->i_mode >> 12); if (last) { @@ -245,15 +245,17 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir) dout("readdir off 0 -> '.'\n"); if (filldir(dirent, ".", 1, ceph_make_fpos(0, 0), - inode->i_ino, inode->i_mode >> 12) < 0) + ceph_translate_ino(inode->i_sb, inode->i_ino), + inode->i_mode >> 12) < 0) return 0; filp->f_pos = 1; off = 1; } if (filp->f_pos == 1) { + ino_t ino = filp->f_dentry->d_parent->d_inode->i_ino; dout("readdir off 1 -> '..'\n"); if (filldir(dirent, "..", 2, ceph_make_fpos(0, 1), - filp->f_dentry->d_parent->d_inode->i_ino, + ceph_translate_ino(inode->i_sb, ino), inode->i_mode >> 12) < 0) return 0; filp->f_pos = 2; @@ -377,7 +379,8 @@ more: if (filldir(dirent, rinfo->dir_dname[off - fi->offset], rinfo->dir_dname_len[off - fi->offset], - pos, ino, ftype) < 0) { + pos, + ceph_translate_ino(inode->i_sb, ino), ftype) < 0) { dout("filldir stopping us...\n"); return 0; } diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 60456361e07d..b54c97da1c43 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -36,6 +36,13 @@ static void ceph_vmtruncate_work(struct work_struct *work); /* * find or create an inode, given the ceph ino number */ +static int ceph_set_ino_cb(struct inode *inode, void *data) +{ + ceph_inode(inode)->i_vino = *(struct ceph_vino *)data; + inode->i_ino = ceph_vino_to_ino(*(struct ceph_vino *)data); + return 0; +} + struct inode *ceph_get_inode(struct super_block *sb, struct ceph_vino vino) { struct inode *inode; @@ -1809,7 +1816,7 @@ int ceph_getattr(struct vfsmount *mnt, struct dentry *dentry, err = ceph_do_getattr(inode, CEPH_STAT_CAP_INODE_ALL); if (!err) { generic_fillattr(inode, stat); - stat->ino = inode->i_ino; + stat->ino = ceph_translate_ino(inode->i_sb, inode->i_ino); if (ceph_snap(inode) != CEPH_NOSNAP) stat->dev = ceph_snap(inode); else diff --git a/fs/ceph/super.c b/fs/ceph/super.c index 9c5085465a63..e39ea78c4894 100644 --- a/fs/ceph/super.c +++ b/fs/ceph/super.c @@ -131,6 +131,7 @@ enum { Opt_rbytes, Opt_norbytes, Opt_noasyncreaddir, + Opt_ino32, }; static match_table_t fsopt_tokens = { @@ -150,6 +151,7 @@ static match_table_t fsopt_tokens = { {Opt_rbytes, "rbytes"}, {Opt_norbytes, "norbytes"}, {Opt_noasyncreaddir, "noasyncreaddir"}, + {Opt_ino32, "ino32"}, {-1, NULL} }; @@ -225,6 +227,9 @@ static int parse_fsopt_token(char *c, void *private) case Opt_noasyncreaddir: fsopt->flags |= CEPH_MOUNT_OPT_NOASYNCREADDIR; break; + case Opt_ino32: + fsopt->flags |= CEPH_MOUNT_OPT_INO32; + break; default: BUG_ON(token); } diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 20b907d76ae2..5405c903704e 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -27,6 +27,7 @@ #define CEPH_MOUNT_OPT_DIRSTAT (1<<4) /* `cat dirname` for stats */ #define CEPH_MOUNT_OPT_RBYTES (1<<5) /* dir st_bytes = rbytes */ #define CEPH_MOUNT_OPT_NOASYNCREADDIR (1<<7) /* no dcache readdir */ +#define CEPH_MOUNT_OPT_INO32 (1<<8) /* 32 bit inos */ #define CEPH_MOUNT_OPT_DEFAULT (CEPH_MOUNT_OPT_RBYTES) @@ -319,6 +320,16 @@ static inline struct ceph_inode_info *ceph_inode(struct inode *inode) return container_of(inode, struct ceph_inode_info, vfs_inode); } +static inline struct ceph_fs_client *ceph_inode_to_client(struct inode *inode) +{ + return (struct ceph_fs_client *)inode->i_sb->s_fs_info; +} + +static inline struct ceph_fs_client *ceph_sb_to_client(struct super_block *sb) +{ + return (struct ceph_fs_client *)sb->s_fs_info; +} + static inline struct ceph_vino ceph_vino(struct inode *inode) { return ceph_inode(inode)->i_vino; @@ -327,19 +338,49 @@ static inline struct ceph_vino ceph_vino(struct inode *inode) /* * ino_t is <64 bits on many architectures, blech. * - * don't include snap in ino hash, at least for now. + * i_ino (kernel inode) st_ino (userspace) + * i386 32 32 + * x86_64+ino32 64 32 + * x86_64 64 64 + */ +static inline u32 ceph_ino_to_ino32(ino_t ino) +{ + ino ^= ino >> (sizeof(ino) * 8 - 32); + if (!ino) + ino = 1; + return ino; +} + +/* + * kernel i_ino value */ static inline ino_t ceph_vino_to_ino(struct ceph_vino vino) { ino_t ino = (ino_t)vino.ino; /* ^ (vino.snap << 20); */ #if BITS_PER_LONG == 32 - ino ^= vino.ino >> (sizeof(u64)-sizeof(ino_t)) * 8; - if (!ino) - ino = 1; + ino = ceph_ino_to_ino32(ino); #endif return ino; } +/* + * user-visible ino (stat, filldir) + */ +#if BITS_PER_LONG == 32 +static inline ino_t ceph_translate_ino(struct super_block *sb, ino_t ino) +{ + return ino; +} +#else +static inline ino_t ceph_translate_ino(struct super_block *sb, ino_t ino) +{ + if (ceph_test_mount_opt(ceph_sb_to_client(sb), INO32)) + ino = ceph_ino_to_ino32(ino); + return ino; +} +#endif + + /* for printf-style formatting */ #define ceph_vinop(i) ceph_inode(i)->i_vino.ino, ceph_inode(i)->i_vino.snap @@ -428,13 +469,6 @@ static inline loff_t ceph_make_fpos(unsigned frag, unsigned off) return ((loff_t)frag << 32) | (loff_t)off; } -static inline int ceph_set_ino_cb(struct inode *inode, void *data) -{ - ceph_inode(inode)->i_vino = *(struct ceph_vino *)data; - inode->i_ino = ceph_vino_to_ino(*(struct ceph_vino *)data); - return 0; -} - /* * caps helpers */ @@ -503,15 +537,6 @@ extern void ceph_reservation_status(struct ceph_fs_client *client, int *total, int *avail, int *used, int *reserved, int *min); -static inline struct ceph_fs_client *ceph_inode_to_client(struct inode *inode) -{ - return (struct ceph_fs_client *)inode->i_sb->s_fs_info; -} - -static inline struct ceph_fs_client *ceph_sb_to_client(struct super_block *sb) -{ - return (struct ceph_fs_client *)sb->s_fs_info; -} /* -- cgit From 80456f8672f7e69d05c01627da03587dc1ea1603 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Thu, 10 Mar 2011 13:33:26 -0800 Subject: ceph: move readahead default to fs/ceph from libceph Signed-off-by: Sage Weil --- fs/ceph/super.c | 4 ++-- fs/ceph/super.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/ceph/super.c b/fs/ceph/super.c index e39ea78c4894..a9e78b4a258c 100644 --- a/fs/ceph/super.c +++ b/fs/ceph/super.c @@ -293,7 +293,7 @@ static int parse_mount_options(struct ceph_mount_options **pfsopt, fsopt->sb_flags = flags; fsopt->flags = CEPH_MOUNT_OPT_DEFAULT; - fsopt->rsize = CEPH_MOUNT_RSIZE_DEFAULT; + fsopt->rsize = CEPH_RSIZE_DEFAULT; fsopt->snapdir_name = kstrdup(CEPH_SNAPDIRNAME_DEFAULT, GFP_KERNEL); fsopt->caps_wanted_delay_min = CEPH_CAPS_WANTED_DELAY_MIN_DEFAULT; fsopt->caps_wanted_delay_max = CEPH_CAPS_WANTED_DELAY_MAX_DEFAULT; @@ -375,7 +375,7 @@ static int ceph_show_options(struct seq_file *m, struct vfsmount *mnt) if (fsopt->wsize) seq_printf(m, ",wsize=%d", fsopt->wsize); - if (fsopt->rsize != CEPH_MOUNT_RSIZE_DEFAULT) + if (fsopt->rsize != CEPH_RSIZE_DEFAULT) seq_printf(m, ",rsize=%d", fsopt->rsize); if (fsopt->congestion_kb != default_congestion_kb()) seq_printf(m, ",write_congestion_kb=%d", fsopt->congestion_kb); diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 5405c903704e..619fe719968f 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -36,6 +36,7 @@ #define ceph_test_mount_opt(fsc, opt) \ (!!((fsc)->mount_options->flags & CEPH_MOUNT_OPT_##opt)) +#define CEPH_RSIZE_DEFAULT (512*1024) /* readahead */ #define CEPH_MAX_READDIR_DEFAULT 1024 #define CEPH_MAX_READDIR_BYTES_DEFAULT (512*1024) #define CEPH_SNAPDIRNAME_DEFAULT ".snap" -- cgit From 78a255654fa7f01945dea0dcedcf5113b3ad9f93 Mon Sep 17 00:00:00 2001 From: Henry C Chang Date: Tue, 15 Mar 2011 09:18:01 +0000 Subject: ceph: remove request from unsafe list if it is canceled/timed out This fixes the list corruption warning like this: ------------[ cut here ]------------ WARNING: at lib/list_debug.c:30 __list_add+0x68/0x81() Hardware name: X8DTU list_add corruption. prev->next should be next (ffff880618931250), but was (null). (prev=ffff880c188b9130). Modules linked in: nfsd lockd nfs_acl auth_rpcgss exportfs ceph libceph libcrc32c sunrpc ipv6 fuse igb i2c_i801 ioatdma i2c_core iTCO_wdt iTCO_vendor_support joydev dca serio_raw usb_storage [last unloaded: scsi_wait_scan] Pid: 10977, comm: smbd Tainted: G W 2.6.32.23-170.Elaster.xendom0.fc12.x86_64 #1 Call Trace: [] warn_slowpath_common+0x7c/0x94 [] warn_slowpath_fmt+0x41/0x43 [] __list_add+0x68/0x81 [] ceph_aio_write+0x614/0x8a2 [ceph] [] do_sync_write+0xe8/0x125 [] ? autoremove_wake_function+0x0/0x39 [] ? selinux_file_permission+0x5c/0xb3 [] ? security_file_permission+0x16/0x18 [] vfs_write+0xae/0x10b [] sys_pwrite64+0x5a/0x76 [] system_call_fastpath+0x16/0x1b ---[ end trace 08573eb9f07ff6f4 ]--- Signed-off-by: Henry C Chang Signed-off-by: Sage Weil --- fs/ceph/file.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'fs') diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 7d0e4a82d898..db5d86309744 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -568,7 +568,14 @@ more: spin_unlock(&ci->i_unsafe_lock); ceph_get_cap_refs(ci, CEPH_CAP_FILE_WR); } + ret = ceph_osdc_wait_request(&fsc->client->osdc, req); + if (ret < 0 && req->r_safe_callback) { + spin_lock(&ci->i_unsafe_lock); + list_del_init(&req->r_unsafe_item); + spin_unlock(&ci->i_unsafe_lock); + ceph_put_cap_refs(ci, CEPH_CAP_FILE_WR); + } } if (file->f_flags & O_DIRECT) -- cgit From 49bcb93236ce1c60d9b7eb21a0aea1999f4d8709 Mon Sep 17 00:00:00 2001 From: Henry C Chang Date: Tue, 15 Mar 2011 09:18:02 +0000 Subject: ceph: add request to the tail of unsafe write list In sync_write_wait(), we assume that the newest request is at the tail of unsafe write list. We should maintain the semantics here. Signed-off-by: Henry C Chang Signed-off-by: Sage Weil --- fs/ceph/file.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/ceph/file.c b/fs/ceph/file.c index db5d86309744..159b512d5a27 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -564,7 +564,8 @@ more: * start_request so that a tid has been assigned. */ spin_lock(&ci->i_unsafe_lock); - list_add(&req->r_unsafe_item, &ci->i_unsafe_writes); + list_add_tail(&req->r_unsafe_item, + &ci->i_unsafe_writes); spin_unlock(&ci->i_unsafe_lock); ceph_get_cap_refs(ci, CEPH_CAP_FILE_WR); } -- cgit From 147851d2dc4d2be2f60d40276d12d7ef82f8a7ce Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 15 Mar 2011 14:57:41 -0700 Subject: ceph: rename dentry_release -> d_release, fix comment Just for consistency's sake. Fix obsolete comment too. Signed-off-by: Sage Weil --- fs/ceph/dir.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'fs') diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index cbe875d3a522..1a867a3601ae 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -1027,14 +1027,13 @@ out_touch: } /* - * When a dentry is released, clear the dir I_COMPLETE if it was part - * of the current dir gen or if this is in the snapshot namespace. + * Release our ceph_dentry_info. */ -static void ceph_dentry_release(struct dentry *dentry) +static void ceph_d_release(struct dentry *dentry) { struct ceph_dentry_info *di = ceph_dentry(dentry); - dout("dentry_release %p\n", dentry); + dout("d_release %p\n", dentry); if (di) { ceph_dentry_lru_del(dentry); if (di->lease_session) @@ -1259,14 +1258,14 @@ const struct inode_operations ceph_dir_iops = { const struct dentry_operations ceph_dentry_ops = { .d_revalidate = ceph_d_revalidate, - .d_release = ceph_dentry_release, + .d_release = ceph_d_release, }; const struct dentry_operations ceph_snapdir_dentry_ops = { .d_revalidate = ceph_snapdir_d_revalidate, - .d_release = ceph_dentry_release, + .d_release = ceph_d_release, }; const struct dentry_operations ceph_snap_dentry_ops = { - .d_release = ceph_dentry_release, + .d_release = ceph_d_release, }; -- cgit From 366f7e7a79b19bd8c4e8f55fdf12b81538d1a7a4 Mon Sep 17 00:00:00 2001 From: "Luck, Tony" Date: Fri, 18 Mar 2011 15:33:43 -0700 Subject: pstore: use mount option instead sysfs to tweak kmsg_bytes /sys/fs is a somewhat strange way to tweak what could more obviously be tuned with a mount option. Suggested-by: Christoph Hellwig Signed-off-by: Tony Luck Signed-off-by: Linus Torvalds --- fs/pstore/inode.c | 68 +++++++++++++++++++++++++++++++++++----------------- fs/pstore/internal.h | 3 +-- fs/pstore/platform.c | 16 +++---------- 3 files changed, 50 insertions(+), 37 deletions(-) (limited to 'fs') diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c index f777f2902c49..977ed2723845 100644 --- a/fs/pstore/inode.c +++ b/fs/pstore/inode.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -112,10 +113,52 @@ static struct inode *pstore_get_inode(struct super_block *sb, return inode; } +enum { + Opt_kmsg_bytes, Opt_err +}; + +static const match_table_t tokens = { + {Opt_kmsg_bytes, "kmsg_bytes=%u"}, + {Opt_err, NULL} +}; + +static void parse_options(char *options) +{ + char *p; + substring_t args[MAX_OPT_ARGS]; + int option; + + if (!options) + return; + + while ((p = strsep(&options, ",")) != NULL) { + int token; + + if (!*p) + continue; + + token = match_token(p, tokens, args); + switch (token) { + case Opt_kmsg_bytes: + if (!match_int(&args[0], &option)) + pstore_set_kmsg_bytes(option); + break; + } + } +} + +static int pstore_remount(struct super_block *sb, int *flags, char *data) +{ + parse_options(data); + + return 0; +} + static const struct super_operations pstore_ops = { .statfs = simple_statfs, .drop_inode = generic_delete_inode, .evict_inode = pstore_evict_inode, + .remount_fs = pstore_remount, .show_options = generic_show_options, }; @@ -215,6 +258,8 @@ int pstore_fill_super(struct super_block *sb, void *data, int silent) sb->s_op = &pstore_ops; sb->s_time_gran = 1; + parse_options(data); + inode = pstore_get_inode(sb, NULL, S_IFDIR | 0755, 0); if (!inode) { err = -ENOMEM; @@ -258,28 +303,7 @@ static struct file_system_type pstore_fs_type = { static int __init init_pstore_fs(void) { - int rc = 0; - struct kobject *pstorefs_kobj; - - pstorefs_kobj = kobject_create_and_add("pstore", fs_kobj); - if (!pstorefs_kobj) { - rc = -ENOMEM; - goto done; - } - - rc = sysfs_create_file(pstorefs_kobj, &pstore_kmsg_bytes_attr.attr); - if (rc) - goto done1; - - rc = register_filesystem(&pstore_fs_type); - if (rc == 0) - goto done; - - sysfs_remove_file(pstorefs_kobj, &pstore_kmsg_bytes_attr.attr); -done1: - kobject_put(pstorefs_kobj); -done: - return rc; + return register_filesystem(&pstore_fs_type); } module_init(init_pstore_fs) diff --git a/fs/pstore/internal.h b/fs/pstore/internal.h index 76c26d2fab29..8c9f23eb1645 100644 --- a/fs/pstore/internal.h +++ b/fs/pstore/internal.h @@ -1,7 +1,6 @@ +extern void pstore_set_kmsg_bytes(int); extern void pstore_get_records(void); extern int pstore_mkfile(enum pstore_type_id, char *psname, u64 id, char *data, size_t size, struct timespec time, int (*erase)(u64)); extern int pstore_is_mounted(void); - -extern struct kobj_attribute pstore_kmsg_bytes_attr; diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 705fdf8abf6e..ce9ad84d5dd9 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -37,24 +37,14 @@ static DEFINE_SPINLOCK(pstore_lock); static struct pstore_info *psinfo; -/* How much of the console log to snapshot. /sys/fs/pstore/kmsg_bytes */ +/* How much of the console log to snapshot */ static unsigned long kmsg_bytes = 10240; -static ssize_t b_show(struct kobject *kobj, - struct kobj_attribute *attr, char *buf) +void pstore_set_kmsg_bytes(int bytes) { - return snprintf(buf, PAGE_SIZE, "%lu\n", kmsg_bytes); + kmsg_bytes = bytes; } -static ssize_t b_store(struct kobject *kobj, struct kobj_attribute *attr, - const char *buf, size_t count) -{ - return (sscanf(buf, "%lu", &kmsg_bytes) > 0) ? count : 0; -} - -struct kobj_attribute pstore_kmsg_bytes_attr = - __ATTR(kmsg_bytes, S_IRUGO | S_IWUSR, b_show, b_store); - /* Tag each group of saved records with a sequence number */ static int oopscount; -- cgit From 21149d611ecd0faf60f4ef94aa2bf8ed872f92bf Mon Sep 17 00:00:00 2001 From: Robin Dong Date: Mon, 21 Mar 2011 20:39:22 -0400 Subject: ext4: add missing space in printk's in __ext4_grp_locked_error() When we do performence-testing on ext4 filesystem, we observed a warning like this: EXT4-fs error (device sda7): ext4_mb_generate_buddy:718: group 259825901 blocks in bitmap, 26057 in gd instead, it should be "group 2598, 25901 blocks in bitmap, 26057 in gd" Reviewed-by: Coly Li Cc: Tao Ma Signed-off-by: Robin Dong Signed-off-by: "Theodore Ts'o" --- fs/ext4/super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/ext4/super.c b/fs/ext4/super.c index b357c2700d72..ccfa6865ea59 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -595,7 +595,7 @@ __acquires(bitlock) vaf.fmt = fmt; vaf.va = &args; - printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: group %u", + printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: group %u, ", sb->s_id, function, line, grp); if (ino) printk(KERN_CONT "inode %lu: ", ino); -- cgit From b31268ac793fd300da66b9c28bbf0a200339ab96 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 21 Mar 2011 17:02:00 -0400 Subject: FS: Use stable writes when not doing a bulk flush If we're only doing a single write, and there are no other unstable writes being queued up, we might want to just flip to using a stable write RPC call. Reviewed-by: NeilBrown Signed-off-by: Trond Myklebust --- fs/nfs/pagelist.c | 3 +++ fs/nfs/write.c | 16 +++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index 23e794410669..fd85618149a1 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c @@ -223,6 +223,7 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc, desc->pg_count = 0; desc->pg_bsize = bsize; desc->pg_base = 0; + desc->pg_moreio = 0; desc->pg_inode = inode; desc->pg_doio = doio; desc->pg_ioflags = io_flags; @@ -335,9 +336,11 @@ int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc, struct nfs_page *req) { while (!nfs_pageio_do_add_request(desc, req)) { + desc->pg_moreio = 1; nfs_pageio_doio(desc); if (desc->pg_error < 0) return 0; + desc->pg_moreio = 0; } return 1; } diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 47a3ad63e0d5..4d686ee53244 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -179,8 +179,8 @@ static int wb_priority(struct writeback_control *wbc) if (wbc->for_reclaim) return FLUSH_HIGHPRI | FLUSH_STABLE; if (wbc->for_kupdate || wbc->for_background) - return FLUSH_LOWPRI; - return 0; + return FLUSH_LOWPRI | FLUSH_COND_STABLE; + return FLUSH_COND_STABLE; } /* @@ -863,7 +863,7 @@ static int nfs_write_rpcsetup(struct nfs_page *req, data->args.context = get_nfs_open_context(req->wb_context); data->args.lock_context = req->wb_lock_context; data->args.stable = NFS_UNSTABLE; - if (how & FLUSH_STABLE) { + if (how & (FLUSH_STABLE | FLUSH_COND_STABLE)) { data->args.stable = NFS_DATA_SYNC; if (!nfs_need_commit(NFS_I(inode))) data->args.stable = NFS_FILE_SYNC; @@ -912,6 +912,12 @@ static int nfs_flush_multi(struct nfs_pageio_descriptor *desc) nfs_list_remove_request(req); + if ((desc->pg_ioflags & FLUSH_COND_STABLE) && + (desc->pg_moreio || NFS_I(desc->pg_inode)->ncommit || + desc->pg_count > wsize)) + desc->pg_ioflags &= ~FLUSH_COND_STABLE; + + nbytes = desc->pg_count; do { size_t len = min(nbytes, wsize); @@ -1002,6 +1008,10 @@ static int nfs_flush_one(struct nfs_pageio_descriptor *desc) if ((!lseg) && list_is_singular(&data->pages)) lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_RW); + if ((desc->pg_ioflags & FLUSH_COND_STABLE) && + (desc->pg_moreio || NFS_I(desc->pg_inode)->ncommit)) + desc->pg_ioflags &= ~FLUSH_COND_STABLE; + /* Set up the argument struct */ ret = nfs_write_rpcsetup(req, data, &nfs_write_full_ops, desc->pg_count, 0, lseg, desc->pg_ioflags); out: -- cgit From b8413f98f997bb3ed7327e6d7117e7e91ce010c3 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 21 Mar 2011 15:37:01 -0400 Subject: NFS: Fix a hang/infinite loop in nfs_wb_page() When one of the two waits in nfs_commit_inode() is interrupted, it returns a non-negative value, which causes nfs_wb_page() to think that the operation was successful causing it to busy-loop rather than exiting. It also causes nfs_file_fsync() to incorrectly report the file as being successfully committed to disk. This patch fixes both problems by ensuring that we return an error if the attempts to wait fail. Signed-off-by: Trond Myklebust Cc: stable@kernel.org --- fs/nfs/write.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) (limited to 'fs') diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 4d686ee53244..55a8c3671233 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -1261,13 +1261,17 @@ void nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data) #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) static int nfs_commit_set_lock(struct nfs_inode *nfsi, int may_wait) { + int ret; + if (!test_and_set_bit(NFS_INO_COMMIT, &nfsi->flags)) return 1; - if (may_wait && !out_of_line_wait_on_bit_lock(&nfsi->flags, - NFS_INO_COMMIT, nfs_wait_bit_killable, - TASK_KILLABLE)) - return 1; - return 0; + if (!may_wait) + return 0; + ret = out_of_line_wait_on_bit_lock(&nfsi->flags, + NFS_INO_COMMIT, + nfs_wait_bit_killable, + TASK_KILLABLE); + return (ret < 0) ? ret : 1; } static void nfs_commit_clear_lock(struct nfs_inode *nfsi) @@ -1443,9 +1447,10 @@ int nfs_commit_inode(struct inode *inode, int how) { LIST_HEAD(head); int may_wait = how & FLUSH_SYNC; - int res = 0; + int res; - if (!nfs_commit_set_lock(NFS_I(inode), may_wait)) + res = nfs_commit_set_lock(NFS_I(inode), may_wait); + if (res <= 0) goto out_mark_dirty; spin_lock(&inode->i_lock); res = nfs_scan_commit(inode, &head, 0, 0); @@ -1454,12 +1459,14 @@ int nfs_commit_inode(struct inode *inode, int how) int error = nfs_commit_list(inode, &head, how); if (error < 0) return error; - if (may_wait) - wait_on_bit(&NFS_I(inode)->flags, NFS_INO_COMMIT, - nfs_wait_bit_killable, - TASK_KILLABLE); - else + if (!may_wait) goto out_mark_dirty; + error = wait_on_bit(&NFS_I(inode)->flags, + NFS_INO_COMMIT, + nfs_wait_bit_killable, + TASK_KILLABLE); + if (error < 0) + return error; } else nfs_commit_clear_lock(NFS_I(inode)); return res; -- cgit From 4596fe07679ff0fae904515691ea747467614871 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Mon, 21 Mar 2011 21:25:13 -0400 Subject: ext4: don't kfree uninitialized s_group_info members We can call kfree on uninitialized members of the s_group_info array on an the error path. We can avoid this by kzalloc'ing the array. This doesn't entirely solve the oops on mount if we fail down this path; failed_mount4: frees the sbi, for one, which gets referenced later in the failed mount paths - I haven't worked that out yet. https://bugzilla.kernel.org/show_bug.cgi?id=30872 Reported-by: Eugene A. Shatokhin Signed-off-by: Eric Sandeen Signed-off-by: "Theodore Ts'o" --- fs/ext4/mballoc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 2f6f0dd08fca..cdc84953f1d4 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -2386,7 +2386,7 @@ static int ext4_mb_init_backend(struct super_block *sb) /* An 8TB filesystem with 64-bit pointers requires a 4096 byte * kmalloc. A 128kb malloc should suffice for a 256TB filesystem. * So a two level scheme suffices for now. */ - sbi->s_group_info = kmalloc(array_size, GFP_KERNEL); + sbi->s_group_info = kzalloc(array_size, GFP_KERNEL); if (sbi->s_group_info == NULL) { printk(KERN_ERR "EXT4-fs: can't allocate buddy meta group\n"); return -ENOMEM; -- cgit From 0562e0bad483d10e9651fbb8f21dc3d0bad57374 Mon Sep 17 00:00:00 2001 From: Jiaying Zhang Date: Mon, 21 Mar 2011 21:38:05 -0400 Subject: ext4: add more tracepoints and use dev_t in the trace buffer - Add more ext4 tracepoints. - Change ext4 tracepoints to use dev_t field with MAJOR/MINOR macros so that we can save 4 bytes in the ring buffer on some platforms. - Add sync_mode to ext4_da_writepages, ext4_da_write_pages, and ext4_da_writepages_result tracepoints. Also remove for_reclaim field from ext4_da_writepages since it is usually not very useful. Signed-off-by: Jiaying Zhang Signed-off-by: "Theodore Ts'o" --- fs/ext4/balloc.c | 3 +++ fs/ext4/extents.c | 13 ++++++++++++- fs/ext4/fsync.c | 14 +++++++++----- fs/ext4/ialloc.c | 1 + fs/ext4/inode.c | 24 +++++++++++++++++++++--- fs/ext4/namei.c | 3 +++ 6 files changed, 49 insertions(+), 9 deletions(-) (limited to 'fs') diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index adf96b822781..97b970e7dd13 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c @@ -21,6 +21,8 @@ #include "ext4_jbd2.h" #include "mballoc.h" +#include + /* * balloc.c contains the blocks allocation and deallocation routines */ @@ -342,6 +344,7 @@ ext4_read_block_bitmap(struct super_block *sb, ext4_group_t block_group) * We do it here so the bitmap uptodate bit * get set with buffer lock held. */ + trace_ext4_read_block_bitmap_load(sb, block_group); set_bitmap_uptodate(bh); if (bh_submit_read(bh) < 0) { put_bh(bh); diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 9ea1bc64ca6d..f46f6e3c02d7 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -44,6 +44,8 @@ #include "ext4_jbd2.h" #include "ext4_extents.h" +#include + static int ext4_ext_truncate_extend_restart(handle_t *handle, struct inode *inode, int needed) @@ -664,6 +666,8 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block, if (unlikely(!bh)) goto err; if (!bh_uptodate_or_lock(bh)) { + trace_ext4_ext_load_extent(inode, block, + path[ppos].p_block); if (bh_submit_read(bh) < 0) { put_bh(bh); goto err; @@ -3297,7 +3301,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, struct ext4_ext_path *path = NULL; struct ext4_extent_header *eh; struct ext4_extent newex, *ex; - ext4_fsblk_t newblock; + ext4_fsblk_t newblock = 0; int err = 0, depth, ret; unsigned int allocated = 0; struct ext4_allocation_request ar; @@ -3305,6 +3309,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, ext_debug("blocks %u/%u requested for inode %lu\n", map->m_lblk, map->m_len, inode->i_ino); + trace_ext4_ext_map_blocks_enter(inode, map->m_lblk, map->m_len, flags); /* check in cache */ if (ext4_ext_in_cache(inode, map->m_lblk, &newex)) { @@ -3525,6 +3530,8 @@ out2: ext4_ext_drop_refs(path); kfree(path); } + trace_ext4_ext_map_blocks_exit(inode, map->m_lblk, + newblock, map->m_len, err ? err : allocated); return err ? err : allocated; } @@ -3658,6 +3665,7 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len) if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) return -EOPNOTSUPP; + trace_ext4_fallocate_enter(inode, offset, len, mode); map.m_lblk = offset >> blkbits; /* * We can't just convert len to max_blocks because @@ -3673,6 +3681,7 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len) ret = inode_newsize_ok(inode, (len + offset)); if (ret) { mutex_unlock(&inode->i_mutex); + trace_ext4_fallocate_exit(inode, offset, max_blocks, ret); return ret; } retry: @@ -3717,6 +3726,8 @@ retry: goto retry; } mutex_unlock(&inode->i_mutex); + trace_ext4_fallocate_exit(inode, offset, max_blocks, + ret > 0 ? ret2 : ret); return ret > 0 ? ret2 : ret; } diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c index 7829b287822a..7f74019d6d77 100644 --- a/fs/ext4/fsync.c +++ b/fs/ext4/fsync.c @@ -164,20 +164,20 @@ int ext4_sync_file(struct file *file, int datasync) J_ASSERT(ext4_journal_current_handle() == NULL); - trace_ext4_sync_file(file, datasync); + trace_ext4_sync_file_enter(file, datasync); if (inode->i_sb->s_flags & MS_RDONLY) return 0; ret = ext4_flush_completed_IO(inode); if (ret < 0) - return ret; + goto out; if (!journal) { ret = generic_file_fsync(file, datasync); if (!ret && !list_empty(&inode->i_dentry)) ext4_sync_parent(inode); - return ret; + goto out; } /* @@ -194,8 +194,10 @@ int ext4_sync_file(struct file *file, int datasync) * (they were dirtied by commit). But that's OK - the blocks are * safe in-journal, which is all fsync() needs to ensure. */ - if (ext4_should_journal_data(inode)) - return ext4_force_commit(inode->i_sb); + if (ext4_should_journal_data(inode)) { + ret = ext4_force_commit(inode->i_sb); + goto out; + } commit_tid = datasync ? ei->i_datasync_tid : ei->i_sync_tid; if (jbd2_log_start_commit(journal, commit_tid)) { @@ -215,5 +217,7 @@ int ext4_sync_file(struct file *file, int datasync) ret = jbd2_log_wait_commit(journal, commit_tid); } else if (journal->j_flags & JBD2_BARRIER) blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL); + out: + trace_ext4_sync_file_exit(inode, ret); return ret; } diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index a679a482c986..254e6b98b5b4 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -152,6 +152,7 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group) * We do it here so the bitmap uptodate bit * get set with buffer lock held. */ + trace_ext4_load_inode_bitmap(sb, block_group); set_bitmap_uptodate(bh); if (bh_submit_read(bh) < 0) { put_bh(bh); diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index fc8c0ce84315..f44307a21136 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -973,6 +973,7 @@ static int ext4_ind_map_blocks(handle_t *handle, struct inode *inode, int count = 0; ext4_fsblk_t first_block = 0; + trace_ext4_ind_map_blocks_enter(inode, map->m_lblk, map->m_len, flags); J_ASSERT(!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))); J_ASSERT(handle != NULL || (flags & EXT4_GET_BLOCKS_CREATE) == 0); depth = ext4_block_to_path(inode, map->m_lblk, offsets, @@ -1058,6 +1059,8 @@ cleanup: partial--; } out: + trace_ext4_ind_map_blocks_exit(inode, map->m_lblk, + map->m_pblk, map->m_len, err); return err; } @@ -3379,6 +3382,7 @@ static sector_t ext4_bmap(struct address_space *mapping, sector_t block) static int ext4_readpage(struct file *file, struct page *page) { + trace_ext4_readpage(page); return mpage_readpage(page, ext4_get_block); } @@ -3413,6 +3417,8 @@ static void ext4_invalidatepage(struct page *page, unsigned long offset) { journal_t *journal = EXT4_JOURNAL(page->mapping->host); + trace_ext4_invalidatepage(page, offset); + /* * free any io_end structure allocated for buffers to be discarded */ @@ -3434,6 +3440,8 @@ static int ext4_releasepage(struct page *page, gfp_t wait) { journal_t *journal = EXT4_JOURNAL(page->mapping->host); + trace_ext4_releasepage(page); + WARN_ON(PageChecked(page)); if (!page_has_buffers(page)) return 0; @@ -3792,11 +3800,16 @@ static ssize_t ext4_direct_IO(int rw, struct kiocb *iocb, { struct file *file = iocb->ki_filp; struct inode *inode = file->f_mapping->host; + ssize_t ret; + trace_ext4_direct_IO_enter(inode, offset, iov_length(iov, nr_segs), rw); if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) - return ext4_ext_direct_IO(rw, iocb, iov, offset, nr_segs); - - return ext4_ind_direct_IO(rw, iocb, iov, offset, nr_segs); + ret = ext4_ext_direct_IO(rw, iocb, iov, offset, nr_segs); + else + ret = ext4_ind_direct_IO(rw, iocb, iov, offset, nr_segs); + trace_ext4_direct_IO_exit(inode, offset, + iov_length(iov, nr_segs), rw, ret); + return ret; } /* @@ -4425,6 +4438,8 @@ void ext4_truncate(struct inode *inode) ext4_lblk_t last_block; unsigned blocksize = inode->i_sb->s_blocksize; + trace_ext4_truncate_enter(inode); + if (!ext4_can_truncate(inode)) return; @@ -4435,6 +4450,7 @@ void ext4_truncate(struct inode *inode) if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) { ext4_ext_truncate(inode); + trace_ext4_truncate_exit(inode); return; } @@ -4564,6 +4580,7 @@ out_stop: ext4_orphan_del(handle, inode); ext4_journal_stop(handle); + trace_ext4_truncate_exit(inode); } /* @@ -4695,6 +4712,7 @@ make_io: * has in-inode xattrs, or we don't have this inode in memory. * Read the block from disk. */ + trace_ext4_load_inode(inode); get_bh(bh); bh->b_end_io = end_buffer_read_sync; submit_bh(READ_META, bh); diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index ad87584aa8d2..f9f83878843a 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -40,6 +40,7 @@ #include "xattr.h" #include "acl.h" +#include /* * define how far ahead to read directories while searching them. */ @@ -2183,6 +2184,7 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry) struct ext4_dir_entry_2 *de; handle_t *handle; + trace_ext4_unlink_enter(dir, dentry); /* Initialize quotas before so that eventual writes go * in separate transaction */ dquot_initialize(dir); @@ -2228,6 +2230,7 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry) end_unlink: ext4_journal_stop(handle); brelse(bh); + trace_ext4_unlink_exit(dentry, retval); return retval; } -- cgit From 1e9bb8808ac11094d711d20d580e7b45a4992d0c Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Tue, 22 Mar 2011 08:35:35 +0100 Subject: block: fix non-atomic access to genhd inflight structures After the stack plugging introduction, these are called lockless. Ensure that the counters are updated atomically. Signed-off-by: Shaohua Li Signed-off-by: Jens Axboe --- fs/partitions/check.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 9c21119512b9..ac546975031f 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -290,7 +290,8 @@ ssize_t part_inflight_show(struct device *dev, { struct hd_struct *p = dev_to_part(dev); - return sprintf(buf, "%8u %8u\n", p->in_flight[0], p->in_flight[1]); + return sprintf(buf, "%8u %8u\n", atomic_read(&p->in_flight[0]), + atomic_read(&p->in_flight[1])); } #ifdef CONFIG_FAIL_MAKE_REQUEST -- cgit From 5a7e0a8cf50cf905403f5a498e86d1f97cfcf51b Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Tue, 8 Mar 2011 16:39:46 +0530 Subject: fs/9p: Fix race in initializing writeback fid When two process open the same file we can end up with both of them allocating the writeback_fid. Add a new mutex which can be used for synchronizing v9fs_inode member values. Signed-off-by: Aneesh Kumar K.V Signed-off-by: Venkateswararao Jujjuri Signed-off-by: Eric Van Hensbergen --- fs/9p/v9fs.h | 1 + fs/9p/vfs_file.c | 3 +++ fs/9p/vfs_inode.c | 4 ++++ fs/9p/vfs_inode_dotl.c | 3 +++ 4 files changed, 11 insertions(+) (limited to 'fs') diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h index bd8496db135b..89657e865162 100644 --- a/fs/9p/v9fs.h +++ b/fs/9p/v9fs.h @@ -130,6 +130,7 @@ struct v9fs_inode { #endif unsigned int cache_validity; struct p9_fid *writeback_fid; + struct mutex v_mutex; struct inode vfs_inode; }; diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index 78bcb97c3425..3337d58d0fc5 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c @@ -90,6 +90,7 @@ int v9fs_file_open(struct inode *inode, struct file *file) } file->private_data = fid; + mutex_lock(&v9inode->v_mutex); if (v9ses->cache && !v9inode->writeback_fid) { /* * clone a fid and add it to writeback_fid @@ -101,10 +102,12 @@ int v9fs_file_open(struct inode *inode, struct file *file) fid = v9fs_writeback_fid(file->f_path.dentry); if (IS_ERR(fid)) { err = PTR_ERR(fid); + mutex_unlock(&v9inode->v_mutex); goto out_error; } v9inode->writeback_fid = (void *) fid; } + mutex_unlock(&v9inode->v_mutex); #ifdef CONFIG_9P_FSCACHE if (v9ses->cache) v9fs_cache_inode_set_cookie(inode, file); diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 8a2c232f708a..c6cef2495f00 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -221,6 +221,7 @@ struct inode *v9fs_alloc_inode(struct super_block *sb) #endif v9inode->writeback_fid = NULL; v9inode->cache_validity = 0; + mutex_init(&v9inode->v_mutex); return &v9inode->vfs_inode; } @@ -650,6 +651,7 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode, /* if we are opening a file, assign the open fid to the file */ if (nd && nd->flags & LOOKUP_OPEN) { v9inode = V9FS_I(dentry->d_inode); + mutex_lock(&v9inode->v_mutex); if (v9ses->cache && !v9inode->writeback_fid) { /* * clone a fid and add it to writeback_fid @@ -661,10 +663,12 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode, inode_fid = v9fs_writeback_fid(dentry); if (IS_ERR(inode_fid)) { err = PTR_ERR(inode_fid); + mutex_unlock(&v9inode->v_mutex); goto error; } v9inode->writeback_fid = (void *) inode_fid; } + mutex_unlock(&v9inode->v_mutex); filp = lookup_instantiate_filp(nd, dentry, generic_file_open); if (IS_ERR(filp)) { err = PTR_ERR(filp); diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index 67c138e94feb..327c578c7ba6 100644 --- a/fs/9p/vfs_inode_dotl.c +++ b/fs/9p/vfs_inode_dotl.c @@ -245,6 +245,7 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode, v9fs_set_create_acl(dentry, dacl, pacl); v9inode = V9FS_I(inode); + mutex_lock(&v9inode->v_mutex); if (v9ses->cache && !v9inode->writeback_fid) { /* * clone a fid and add it to writeback_fid @@ -256,10 +257,12 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode, inode_fid = v9fs_writeback_fid(dentry); if (IS_ERR(inode_fid)) { err = PTR_ERR(inode_fid); + mutex_unlock(&v9inode->v_mutex); goto error; } v9inode->writeback_fid = (void *) inode_fid; } + mutex_unlock(&v9inode->v_mutex); /* Since we are opening a file, assign the open fid to the file */ filp = lookup_instantiate_filp(nd, dentry, generic_file_open); if (IS_ERR(filp)) { -- cgit From 059c138bc79320bd7d6fba91bad4d50eeec9c31f Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Tue, 8 Mar 2011 16:39:48 +0530 Subject: fs/9p: Use truncate_setsize instead of vmtruncate convert vmtruncate usage to truncate_setsize. We also writeback all dirty pages before doing 9p operations and on success call truncate_setsize. This ensure that we continue sanely on failed truncate on the server. The disadvantage is that we are now going to write back the content that get thrown away later as a part of truncate. Signed-off-by: Aneesh Kumar K.V Signed-off-by: Venkateswararao Jujjuri Signed-off-by: Eric Van Hensbergen --- fs/9p/vfs_inode.c | 16 ++++++++++------ fs/9p/vfs_inode_dotl.c | 12 +++++------- 2 files changed, 15 insertions(+), 13 deletions(-) (limited to 'fs') diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index c6cef2495f00..0afbbb450faf 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -971,6 +971,10 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) struct p9_wstat wstat; P9_DPRINTK(P9_DEBUG_VFS, "\n"); + retval = inode_change_ok(dentry->d_inode, iattr); + if (retval) + return retval; + retval = -EPERM; v9ses = v9fs_inode2v9ses(dentry->d_inode); fid = v9fs_fid_lookup(dentry); @@ -997,12 +1001,7 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) if (iattr->ia_valid & ATTR_GID) wstat.n_gid = iattr->ia_gid; } - if ((iattr->ia_valid & ATTR_SIZE) && - iattr->ia_size != i_size_read(dentry->d_inode)) { - retval = vmtruncate(dentry->d_inode, iattr->ia_size); - if (retval) - return retval; - } + /* Write all dirty data */ if (S_ISREG(dentry->d_inode->i_mode)) filemap_write_and_wait(dentry->d_inode->i_mapping); @@ -1010,6 +1009,11 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) retval = p9_client_wstat(fid, &wstat); if (retval < 0) return retval; + + if ((iattr->ia_valid & ATTR_SIZE) && + iattr->ia_size != i_size_read(dentry->d_inode)) + truncate_setsize(dentry->d_inode, iattr->ia_size); + v9fs_invalidate_inode_attr(dentry->d_inode); setattr_copy(dentry->d_inode, iattr); diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index 327c578c7ba6..0a0ac30d51d6 100644 --- a/fs/9p/vfs_inode_dotl.c +++ b/fs/9p/vfs_inode_dotl.c @@ -456,12 +456,6 @@ int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr) if (IS_ERR(fid)) return PTR_ERR(fid); - if ((iattr->ia_valid & ATTR_SIZE) && - iattr->ia_size != i_size_read(dentry->d_inode)) { - retval = vmtruncate(dentry->d_inode, iattr->ia_size); - if (retval) - return retval; - } /* Write all dirty data */ if (S_ISREG(dentry->d_inode->i_mode)) filemap_write_and_wait(dentry->d_inode->i_mapping); @@ -469,8 +463,12 @@ int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr) retval = p9_client_setattr(fid, &p9attr); if (retval < 0) return retval; - v9fs_invalidate_inode_attr(dentry->d_inode); + if ((iattr->ia_valid & ATTR_SIZE) && + iattr->ia_size != i_size_read(dentry->d_inode)) + truncate_setsize(dentry->d_inode, iattr->ia_size); + + v9fs_invalidate_inode_attr(dentry->d_inode); setattr_copy(dentry->d_inode, iattr); mark_inode_dirty(dentry->d_inode); if (iattr->ia_valid & ATTR_MODE) { -- cgit From ea59bb759b8fd240860c37026ab1b998d26ac285 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Tue, 8 Mar 2011 16:39:49 +0530 Subject: fs/9p: Open writeback fid in O_SYNC mode Older version of protocol don't support tsyncfs operation. So for them force a O_SYNC flag on the server Signed-off-by: Aneesh Kumar K.V Signed-off-by: Venkateswararao Jujjuri Signed-off-by: Eric Van Hensbergen --- fs/9p/fid.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/9p/fid.c b/fs/9p/fid.c index cd63e002d826..99a1a7b08634 100644 --- a/fs/9p/fid.c +++ b/fs/9p/fid.c @@ -286,9 +286,11 @@ static struct p9_fid *v9fs_fid_clone_with_uid(struct dentry *dentry, uid_t uid) struct p9_fid *v9fs_writeback_fid(struct dentry *dentry) { - int err; + int err, flags; struct p9_fid *fid; + struct v9fs_session_info *v9ses; + v9ses = v9fs_inode2v9ses(dentry->d_inode); fid = v9fs_fid_clone_with_uid(dentry, 0); if (IS_ERR(fid)) goto error_out; @@ -297,8 +299,17 @@ struct p9_fid *v9fs_writeback_fid(struct dentry *dentry) * dirty pages. We always request for the open fid in read-write * mode so that a partial page write which result in page * read can work. + * + * we don't have a tsyncfs operation for older version + * of protocol. So make sure the write back fid is + * opened in O_SYNC mode. */ - err = p9_client_open(fid, O_RDWR); + if (!v9fs_proto_dotl(v9ses)) + flags = O_RDWR | O_SYNC; + else + flags = O_RDWR; + + err = p9_client_open(fid, flags); if (err < 0) { p9_client_clunk(fid); fid = ERR_PTR(err); -- cgit From 7add697a3d271aa7080513f92dab190c75174b7e Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Tue, 8 Mar 2011 16:39:49 +0530 Subject: fs/9p: Attach writeback_fid on first open with WR flag We don't need writeback fid if we are only doing O_RDONLY open Signed-off-by: Aneesh Kumar K.V Signed-off-by: Venkateswararao Jujjuri Signed-off-by: Eric Van Hensbergen --- fs/9p/vfs_file.c | 3 ++- fs/9p/vfs_inode.c | 3 ++- fs/9p/vfs_inode_dotl.c | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index 3337d58d0fc5..6997eb62fbba 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c @@ -91,7 +91,8 @@ int v9fs_file_open(struct inode *inode, struct file *file) file->private_data = fid; mutex_lock(&v9inode->v_mutex); - if (v9ses->cache && !v9inode->writeback_fid) { + if (v9ses->cache && !v9inode->writeback_fid && + ((file->f_flags & O_ACCMODE) != O_RDONLY)) { /* * clone a fid and add it to writeback_fid * we do it during open time instead of diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 0afbbb450faf..774a20af01ea 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -652,7 +652,8 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode, if (nd && nd->flags & LOOKUP_OPEN) { v9inode = V9FS_I(dentry->d_inode); mutex_lock(&v9inode->v_mutex); - if (v9ses->cache && !v9inode->writeback_fid) { + if (v9ses->cache && !v9inode->writeback_fid && + ((flags & O_ACCMODE) != O_RDONLY)) { /* * clone a fid and add it to writeback_fid * we do it during open time instead of diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index 0a0ac30d51d6..8b616dc3567a 100644 --- a/fs/9p/vfs_inode_dotl.c +++ b/fs/9p/vfs_inode_dotl.c @@ -246,7 +246,8 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode, v9inode = V9FS_I(inode); mutex_lock(&v9inode->v_mutex); - if (v9ses->cache && !v9inode->writeback_fid) { + if (v9ses->cache && !v9inode->writeback_fid && + ((flags & O_ACCMODE) != O_RDONLY)) { /* * clone a fid and add it to writeback_fid * we do it during open time instead of -- cgit From 42869c8adae72366fc6c4f3924ce3d6c3735c4a3 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Tue, 8 Mar 2011 16:39:50 +0530 Subject: fs/9p: Add v9fs_dentry2v9ses Add the new static inline and use the same Signed-off-by: Aneesh Kumar K.V Signed-off-by: Venkateswararao Jujjuri Signed-off-by: Eric Van Hensbergen --- fs/9p/acl.c | 4 ++-- fs/9p/fid.c | 6 +++--- fs/9p/v9fs.h | 5 +++++ fs/9p/vfs_inode.c | 6 +++--- fs/9p/vfs_inode_dotl.c | 4 ++-- fs/9p/vfs_super.c | 2 +- 6 files changed, 16 insertions(+), 11 deletions(-) (limited to 'fs') diff --git a/fs/9p/acl.c b/fs/9p/acl.c index 515455296378..33aa116732c8 100644 --- a/fs/9p/acl.c +++ b/fs/9p/acl.c @@ -262,7 +262,7 @@ static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name, if (strcmp(name, "") != 0) return -EINVAL; - v9ses = v9fs_inode2v9ses(dentry->d_inode); + v9ses = v9fs_dentry2v9ses(dentry); /* * We allow set/get/list of acl when access=client is not specified */ @@ -312,7 +312,7 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name, if (strcmp(name, "") != 0) return -EINVAL; - v9ses = v9fs_inode2v9ses(dentry->d_inode); + v9ses = v9fs_dentry2v9ses(dentry); /* * set the attribute on the remote. Without even looking at the * xattr value. We leave it to the server to validate diff --git a/fs/9p/fid.c b/fs/9p/fid.c index 99a1a7b08634..0ee594569dcc 100644 --- a/fs/9p/fid.c +++ b/fs/9p/fid.c @@ -134,7 +134,7 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry, struct v9fs_session_info *v9ses; struct p9_fid *fid, *old_fid = NULL; - v9ses = v9fs_inode2v9ses(dentry->d_inode); + v9ses = v9fs_dentry2v9ses(dentry); access = v9ses->flags & V9FS_ACCESS_MASK; fid = v9fs_fid_find(dentry, uid, any); if (fid) @@ -237,7 +237,7 @@ struct p9_fid *v9fs_fid_lookup(struct dentry *dentry) int any, access; struct v9fs_session_info *v9ses; - v9ses = v9fs_inode2v9ses(dentry->d_inode); + v9ses = v9fs_dentry2v9ses(dentry); access = v9ses->flags & V9FS_ACCESS_MASK; switch (access) { case V9FS_ACCESS_SINGLE: @@ -290,7 +290,7 @@ struct p9_fid *v9fs_writeback_fid(struct dentry *dentry) struct p9_fid *fid; struct v9fs_session_info *v9ses; - v9ses = v9fs_inode2v9ses(dentry->d_inode); + v9ses = v9fs_dentry2v9ses(dentry); fid = v9fs_fid_clone_with_uid(dentry, 0); if (IS_ERR(fid)) goto error_out; diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h index 89657e865162..9665c2b840e6 100644 --- a/fs/9p/v9fs.h +++ b/fs/9p/v9fs.h @@ -174,6 +174,11 @@ static inline struct v9fs_session_info *v9fs_inode2v9ses(struct inode *inode) return (inode->i_sb->s_fs_info); } +static inline struct v9fs_session_info *v9fs_dentry2v9ses(struct dentry *dentry) +{ + return dentry->d_sb->s_fs_info; +} + static inline int v9fs_proto_dotu(struct v9fs_session_info *v9ses) { return v9ses->flags & V9FS_PROTO_2000U; diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 774a20af01ea..7f6c67703195 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -936,7 +936,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry); err = -EPERM; - v9ses = v9fs_inode2v9ses(dentry->d_inode); + v9ses = v9fs_dentry2v9ses(dentry); if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { generic_fillattr(dentry->d_inode, stat); return 0; @@ -977,7 +977,7 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) return retval; retval = -EPERM; - v9ses = v9fs_inode2v9ses(dentry->d_inode); + v9ses = v9fs_dentry2v9ses(dentry); fid = v9fs_fid_lookup(dentry); if(IS_ERR(fid)) return PTR_ERR(fid); @@ -1139,7 +1139,7 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) P9_DPRINTK(P9_DEBUG_VFS, " %s\n", dentry->d_name.name); retval = -EPERM; - v9ses = v9fs_inode2v9ses(dentry->d_inode); + v9ses = v9fs_dentry2v9ses(dentry); fid = v9fs_fid_lookup(dentry); if (IS_ERR(fid)) return PTR_ERR(fid); diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index 8b616dc3567a..ffbb113d5f33 100644 --- a/fs/9p/vfs_inode_dotl.c +++ b/fs/9p/vfs_inode_dotl.c @@ -395,7 +395,7 @@ v9fs_vfs_getattr_dotl(struct vfsmount *mnt, struct dentry *dentry, P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry); err = -EPERM; - v9ses = v9fs_inode2v9ses(dentry->d_inode); + v9ses = v9fs_dentry2v9ses(dentry); if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { generic_fillattr(dentry->d_inode, stat); return 0; @@ -452,7 +452,7 @@ int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr) p9attr.mtime_nsec = iattr->ia_mtime.tv_nsec; retval = -EPERM; - v9ses = v9fs_inode2v9ses(dentry->d_inode); + v9ses = v9fs_dentry2v9ses(dentry); fid = v9fs_fid_lookup(dentry); if (IS_ERR(fid)) return PTR_ERR(fid); diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 09fd08d1606f..f3eed3383e4f 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c @@ -262,7 +262,7 @@ static int v9fs_statfs(struct dentry *dentry, struct kstatfs *buf) goto done; } - v9ses = v9fs_inode2v9ses(dentry->d_inode); + v9ses = v9fs_dentry2v9ses(dentry); if (v9fs_proto_dotl(v9ses)) { res = p9_client_statfs(fid, &rs); if (res == 0) { -- cgit From aaf0ef1d2bce05cfd06cf29c96a6973df4d0a6a8 Mon Sep 17 00:00:00 2001 From: "M. Mohan Kumar" Date: Wed, 16 Mar 2011 21:40:49 +0530 Subject: 9p: use the updated offset given by generic_write_checks Without this fix, even if a file is opened in O_APPEND mode, data will be written at current file position instead of end of file. Signed-off-by: M. Mohan Kumar Reviewed-by: Aneesh Kumar K.V Signed-off-by: Eric Van Hensbergen --- fs/9p/vfs_file.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index 6997eb62fbba..ffed55817f0c 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c @@ -508,9 +508,12 @@ v9fs_file_write(struct file *filp, const char __user * data, if (!count) goto out; - return v9fs_file_write_internal(filp->f_path.dentry->d_inode, + retval = v9fs_file_write_internal(filp->f_path.dentry->d_inode, filp->private_data, - data, count, offset, 1); + data, count, &origin, 1); + /* update offset on successful write */ + if (retval > 0) + *offset = origin; out: return retval; } -- cgit From 117a91e0f25fd7698e20ac3dfa62086be3dc82a3 Mon Sep 17 00:00:00 2001 From: Phillip Lougher Date: Tue, 22 Mar 2011 23:01:26 +0000 Subject: Squashfs: Use vmalloc rather than kmalloc for zlib workspace Bugzilla bug 31422 reports occasional "page allocation failure. order:4" at Squashfs mount time. Fix this by making zlib workspace allocation use vmalloc rather than kmalloc. Reported-by: Mehmet Giritli Signed-off-by: Phillip Lougher --- fs/squashfs/zlib_wrapper.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/squashfs/zlib_wrapper.c b/fs/squashfs/zlib_wrapper.c index 195b0d035e9b..517688b32ffa 100644 --- a/fs/squashfs/zlib_wrapper.c +++ b/fs/squashfs/zlib_wrapper.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "squashfs_fs.h" #include "squashfs_fs_sb.h" @@ -37,8 +38,7 @@ static void *zlib_init(struct squashfs_sb_info *dummy, void *buff, int len) z_stream *stream = kmalloc(sizeof(z_stream), GFP_KERNEL); if (stream == NULL) goto failed; - stream->workspace = kmalloc(zlib_inflate_workspacesize(), - GFP_KERNEL); + stream->workspace = vmalloc(zlib_inflate_workspacesize()); if (stream->workspace == NULL) goto failed; @@ -56,7 +56,7 @@ static void zlib_free(void *strm) z_stream *stream = strm; if (stream) - kfree(stream->workspace); + vfree(stream->workspace); kfree(stream); } -- cgit From 9f6af27fb693c633cc46d36fc1d85efe6d6fbc17 Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Tue, 22 Mar 2011 16:01:49 -0700 Subject: pstore: cleanups to pstore_dump() pstore_dump() can be called with many different "reason" codes. Save the name of the code in the persistent store record. Also - only worthwhile calling pstore_mkfile for KMSG_DUMP_OOPS - that is the only one where the kernel will continue running. Reviewed-by: Seiji Aguchi Signed-off-by: Tony Luck --- fs/pstore/platform.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index ce9ad84d5dd9..f835a25625ff 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -48,6 +48,10 @@ void pstore_set_kmsg_bytes(int bytes) /* Tag each group of saved records with a sequence number */ static int oopscount; +static char *reason_str[] = { + "Oops", "Panic", "Kexec", "Restart", "Halt", "Poweroff", "Emergency" +}; + /* * callback from kmsg_dump. (s2,l2) has the most recently * written bytes, older bytes are in (s1,l1). Save as much @@ -61,15 +65,20 @@ static void pstore_dump(struct kmsg_dumper *dumper, unsigned long s1_start, s2_start; unsigned long l1_cpy, l2_cpy; unsigned long size, total = 0; - char *dst; + char *dst, *why; u64 id; int hsize, part = 1; + if (reason < ARRAY_SIZE(reason_str)) + why = reason_str[reason]; + else + why = "Unknown"; + mutex_lock(&psinfo->buf_mutex); oopscount++; while (total < kmsg_bytes) { dst = psinfo->buf; - hsize = sprintf(dst, "Oops#%d Part%d\n", oopscount, part++); + hsize = sprintf(dst, "%s#%d Part%d\n", why, oopscount, part++); size = psinfo->bufsize - hsize; dst += hsize; @@ -86,7 +95,7 @@ static void pstore_dump(struct kmsg_dumper *dumper, memcpy(dst + l1_cpy, s2 + s2_start, l2_cpy); id = psinfo->write(PSTORE_TYPE_DMESG, hsize + l1_cpy + l2_cpy); - if (pstore_is_mounted()) + if (reason == KMSG_DUMP_OOPS && pstore_is_mounted()) pstore_mkfile(PSTORE_TYPE_DMESG, psinfo->name, id, psinfo->buf, hsize + l1_cpy + l2_cpy, CURRENT_TIME, psinfo->erase); -- cgit From 4667058b772857069378aa8f417203156e315e82 Mon Sep 17 00:00:00 2001 From: Gusev Vitaliy Date: Wed, 23 Mar 2011 00:40:25 +0300 Subject: nfs4: Fix NULL dereference at d_alloc_and_lookup() d_alloc_and_lookup() calls i_op->lookup method due to rootfh changes his fsid. During mount i_op of NFS root inode is set to nfs_mountpoint_inode_operations, if rpc_ops->getroot() and rpc_ops->getattr() return different fsid. After that nfs_follow_remote_path() raised oops: BUG: unable to handle kernel NULL pointer dereference at (null) IP: [< (null)>] (null) stack trace: d_alloc_and_lookup+0x4c/0x74 do_lookup+0x1e3/0x280 link_path_walk+0x12e/0xab0 nfs4_remote_get_sb+0x56/0x2c0 [nfs] path_walk+0x67/0xe0 vfs_path_lookup+0x8e/0x100 nfs_follow_remote_path+0x16f/0x3e0 [nfs] nfs4_try_mount+0x6f/0xd0 [nfs] nfs_get_sb+0x269/0x400 [nfs] vfs_kern_mount+0x8a/0x1f0 do_kern_mount+0x52/0x130 do_mount+0x20a/0x260 sys_mount+0x90/0xe0 system_call_fastpath+0x16/0x1b So just refresh fsid, as RFC3530 doesn't specify behavior in case of rootfh changes fsid. Signed-off-by: Vitaliy Gusev Signed-off-by: Trond Myklebust --- fs/nfs/getroot.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'fs') diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c index b5ffe8fa291f..79796521cfdc 100644 --- a/fs/nfs/getroot.c +++ b/fs/nfs/getroot.c @@ -199,6 +199,10 @@ struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh) goto out; } + if (fattr->valid & NFS_ATTR_FATTR_FSID && + !nfs_fsid_equal(&server->fsid, &fattr->fsid)) + memcpy(&server->fsid, &fattr->fsid, sizeof(server->fsid)); + inode = nfs_fhget(sb, mntfh, fattr); if (IS_ERR(inode)) { dprintk("nfs_get_root: get root inode failed\n"); -- cgit From 51e816564db151f7f08c739ad69b9d1dbd166663 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Mon, 21 Mar 2011 20:35:49 +0100 Subject: Remove pointless memset in nfsacl_encode() Remove pointless memset() in nfsacl_encode(). Thanks to Trond Myklebust for pointing out that it is not needed since posix_acl_init() will set everything regardless.. Signed-off-by: Jesper Juhl Signed-off-by: Trond Myklebust --- fs/nfs_common/nfsacl.c | 1 - 1 file changed, 1 deletion(-) (limited to 'fs') diff --git a/fs/nfs_common/nfsacl.c b/fs/nfs_common/nfsacl.c index 84c27d69d421..ec0f277be7f5 100644 --- a/fs/nfs_common/nfsacl.c +++ b/fs/nfs_common/nfsacl.c @@ -117,7 +117,6 @@ int nfsacl_encode(struct xdr_buf *buf, unsigned int base, struct inode *inode, * invoked in contexts where a memory allocation failure is * fatal. Fortunately this fake ACL is small enough to * construct on the stack. */ - memset(acl2, 0, sizeof(acl2)); posix_acl_init(acl2, 4); /* Insert entries in canonical order: other orders seem -- cgit From ef6a3c63112e865d632ff7c478ba7c7160cad0d1 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Tue, 22 Mar 2011 16:30:52 -0700 Subject: mm: add replace_page_cache_page() function This function basically does: remove_from_page_cache(old); page_cache_release(old); add_to_page_cache_locked(new); Except it does this atomically, so there's no possibility for the "add" to fail because of a race. If memory cgroups are enabled, then the memory cgroup charge is also moved from the old page to the new. This function is currently used by fuse to move pages into the page cache on read, instead of copying the page contents. [minchan.kim@gmail.com: add freepage() hook to replace_page_cache_page()] Signed-off-by: Miklos Szeredi Acked-by: Rik van Riel Acked-by: KAMEZAWA Hiroyuki Cc: Mel Gorman Signed-off-by: Minchan Kim Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fuse/dev.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'fs') diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 213d3cf4f5e9..640fc229df10 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -737,14 +737,12 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep) if (WARN_ON(PageMlocked(oldpage))) goto out_fallback_unlock; - remove_from_page_cache(oldpage); - page_cache_release(oldpage); - - err = add_to_page_cache_locked(newpage, mapping, index, GFP_KERNEL); + err = replace_page_cache_page(oldpage, newpage, GFP_KERNEL); if (err) { - printk(KERN_WARNING "fuse_try_move_page: failed to add page"); - goto out_fallback_unlock; + unlock_page(newpage); + return err; } + page_cache_get(newpage); if (!(buf->flags & PIPE_BUF_FLAG_LRU)) -- cgit From bd65cb86c98a79bc61afd0d80166005f125e9064 Mon Sep 17 00:00:00 2001 From: Minchan Kim Date: Tue, 22 Mar 2011 16:30:54 -0700 Subject: mm: hugetlbfs: change remove_from_page_cache This patch series changes remove_from_page_cache()'s page ref counting rule. Page cache ref count is decreased in delete_from_page_cache(). So we don't need to decrease the page reference in callers. Signed-off-by: Minchan Kim Cc: William Irwin Acked-by: Hugh Dickins Acked-by: Mel Gorman Reviewed-by: KAMEZAWA Hiroyuki Reviewed-by: Johannes Weiner Reviewed-by: KOSAKI Motohiro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/hugetlbfs/inode.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 9885082b470f..b9eeb1cd03ff 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -332,8 +332,7 @@ static void truncate_huge_page(struct page *page) { cancel_dirty_page(page, /* No IO accounting for huge pages? */0); ClearPageUptodate(page); - remove_from_page_cache(page); - put_page(page); + delete_from_page_cache(page); } static void truncate_hugepages(struct inode *inode, loff_t lstart) -- cgit From 033193275b3ffcfe7f3fde7b569f3d207f6cd6a0 Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Tue, 22 Mar 2011 16:32:56 -0700 Subject: pagewalk: only split huge pages when necessary Right now, if a mm_walk has either ->pte_entry or ->pmd_entry set, it will unconditionally split any transparent huge pages it runs in to. In practice, that means that anyone doing a cat /proc/$pid/smaps will unconditionally break down every huge page in the process and depend on khugepaged to re-collapse it later. This is fairly suboptimal. This patch changes that behavior. It teaches each ->pmd_entry handler (there are five) that they must break down the THPs themselves. Also, the _generic_ code will never break down a THP unless a ->pte_entry handler is actually set. This means that the ->pmd_entry handlers can now choose to deal with THPs without breaking them down. [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Dave Hansen Acked-by: Mel Gorman Acked-by: David Rientjes Reviewed-by: Eric B Munson Tested-by: Eric B Munson Cc: Michael J Wolf Cc: Andrea Arcangeli Cc: Johannes Weiner Cc: Matt Mackall Cc: Jeremy Fitzhardinge Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/proc/task_mmu.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'fs') diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 60b914860f81..78fd3621f565 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -343,6 +343,8 @@ static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, struct page *page; int mapcount; + split_huge_page_pmd(walk->mm, pmd); + pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); for (; addr != end; pte++, addr += PAGE_SIZE) { ptent = *pte; @@ -467,6 +469,8 @@ static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr, spinlock_t *ptl; struct page *page; + split_huge_page_pmd(walk->mm, pmd); + pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); for (; addr != end; pte++, addr += PAGE_SIZE) { ptent = *pte; @@ -623,6 +627,8 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, pte_t *pte; int err = 0; + split_huge_page_pmd(walk->mm, pmd); + /* find the first VMA at or above 'addr' */ vma = find_vma(walk->mm, addr); for (; addr != end; addr += PAGE_SIZE) { -- cgit From ae11c4d9f646064cf086e2f8cd4b3c475df7739c Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Tue, 22 Mar 2011 16:32:58 -0700 Subject: smaps: break out smaps_pte_entry() from smaps_pte_range() We will use smaps_pte_entry() in a moment to handle both small and transparent large pages. But, we must break it out of smaps_pte_range() first. Signed-off-by: Dave Hansen Acked-by: Mel Gorman Acked-by: Johannes Weiner Acked-by: David Rientjes Reviewed-by: Eric B Munson Tested-by: Eric B Munson Cc: Michael J Wolf Cc: Andrea Arcangeli Cc: Matt Mackall Cc: Jeremy Fitzhardinge Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/proc/task_mmu.c | 87 +++++++++++++++++++++++++++++------------------------- 1 file changed, 47 insertions(+), 40 deletions(-) (limited to 'fs') diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 78fd3621f565..5cd06fa3106b 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -333,56 +333,63 @@ struct mem_size_stats { u64 pss; }; -static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, - struct mm_walk *walk) + +static void smaps_pte_entry(pte_t ptent, unsigned long addr, + struct mm_walk *walk) { struct mem_size_stats *mss = walk->private; struct vm_area_struct *vma = mss->vma; - pte_t *pte, ptent; - spinlock_t *ptl; struct page *page; int mapcount; - split_huge_page_pmd(walk->mm, pmd); - - pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); - for (; addr != end; pte++, addr += PAGE_SIZE) { - ptent = *pte; + if (is_swap_pte(ptent)) { + mss->swap += PAGE_SIZE; + return; + } - if (is_swap_pte(ptent)) { - mss->swap += PAGE_SIZE; - continue; - } + if (!pte_present(ptent)) + return; + + page = vm_normal_page(vma, addr, ptent); + if (!page) + return; + + if (PageAnon(page)) + mss->anonymous += PAGE_SIZE; + + mss->resident += PAGE_SIZE; + /* Accumulate the size in pages that have been accessed. */ + if (pte_young(ptent) || PageReferenced(page)) + mss->referenced += PAGE_SIZE; + mapcount = page_mapcount(page); + if (mapcount >= 2) { + if (pte_dirty(ptent) || PageDirty(page)) + mss->shared_dirty += PAGE_SIZE; + else + mss->shared_clean += PAGE_SIZE; + mss->pss += (PAGE_SIZE << PSS_SHIFT) / mapcount; + } else { + if (pte_dirty(ptent) || PageDirty(page)) + mss->private_dirty += PAGE_SIZE; + else + mss->private_clean += PAGE_SIZE; + mss->pss += (PAGE_SIZE << PSS_SHIFT); + } +} - if (!pte_present(ptent)) - continue; +static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, + struct mm_walk *walk) +{ + struct mem_size_stats *mss = walk->private; + struct vm_area_struct *vma = mss->vma; + pte_t *pte; + spinlock_t *ptl; - page = vm_normal_page(vma, addr, ptent); - if (!page) - continue; + split_huge_page_pmd(walk->mm, pmd); - if (PageAnon(page)) - mss->anonymous += PAGE_SIZE; - - mss->resident += PAGE_SIZE; - /* Accumulate the size in pages that have been accessed. */ - if (pte_young(ptent) || PageReferenced(page)) - mss->referenced += PAGE_SIZE; - mapcount = page_mapcount(page); - if (mapcount >= 2) { - if (pte_dirty(ptent) || PageDirty(page)) - mss->shared_dirty += PAGE_SIZE; - else - mss->shared_clean += PAGE_SIZE; - mss->pss += (PAGE_SIZE << PSS_SHIFT) / mapcount; - } else { - if (pte_dirty(ptent) || PageDirty(page)) - mss->private_dirty += PAGE_SIZE; - else - mss->private_clean += PAGE_SIZE; - mss->pss += (PAGE_SIZE << PSS_SHIFT); - } - } + pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); + for (; addr != end; pte++, addr += PAGE_SIZE) + smaps_pte_entry(*pte, addr, walk); pte_unmap_unlock(pte - 1, ptl); cond_resched(); return 0; -- cgit From 3c9acc7849b1eab7ffc75e933404c5f32865d9a2 Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Tue, 22 Mar 2011 16:32:59 -0700 Subject: smaps: pass pte size argument in to smaps_pte_entry() Add an argument to the new smaps_pte_entry() function to let it account in things other than PAGE_SIZE units. I changed all of the PAGE_SIZE sites, even though not all of them can be reached for transparent huge pages, just so this will continue to work without changes as THPs are improved. Signed-off-by: Dave Hansen Acked-by: Mel Gorman Acked-by: Johannes Weiner Acked-by: David Rientjes Reviewed-by: Eric B Munson Tested-by: Eric B Munson Cc: Michael J Wolf Cc: Andrea Arcangeli Cc: Matt Mackall Cc: Jeremy Fitzhardinge Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/proc/task_mmu.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'fs') diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 5cd06fa3106b..d7e2af334076 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -335,7 +335,7 @@ struct mem_size_stats { static void smaps_pte_entry(pte_t ptent, unsigned long addr, - struct mm_walk *walk) + unsigned long ptent_size, struct mm_walk *walk) { struct mem_size_stats *mss = walk->private; struct vm_area_struct *vma = mss->vma; @@ -343,7 +343,7 @@ static void smaps_pte_entry(pte_t ptent, unsigned long addr, int mapcount; if (is_swap_pte(ptent)) { - mss->swap += PAGE_SIZE; + mss->swap += ptent_size; return; } @@ -355,25 +355,25 @@ static void smaps_pte_entry(pte_t ptent, unsigned long addr, return; if (PageAnon(page)) - mss->anonymous += PAGE_SIZE; + mss->anonymous += ptent_size; - mss->resident += PAGE_SIZE; + mss->resident += ptent_size; /* Accumulate the size in pages that have been accessed. */ if (pte_young(ptent) || PageReferenced(page)) - mss->referenced += PAGE_SIZE; + mss->referenced += ptent_size; mapcount = page_mapcount(page); if (mapcount >= 2) { if (pte_dirty(ptent) || PageDirty(page)) - mss->shared_dirty += PAGE_SIZE; + mss->shared_dirty += ptent_size; else - mss->shared_clean += PAGE_SIZE; - mss->pss += (PAGE_SIZE << PSS_SHIFT) / mapcount; + mss->shared_clean += ptent_size; + mss->pss += (ptent_size << PSS_SHIFT) / mapcount; } else { if (pte_dirty(ptent) || PageDirty(page)) - mss->private_dirty += PAGE_SIZE; + mss->private_dirty += ptent_size; else - mss->private_clean += PAGE_SIZE; - mss->pss += (PAGE_SIZE << PSS_SHIFT); + mss->private_clean += ptent_size; + mss->pss += (ptent_size << PSS_SHIFT); } } @@ -389,7 +389,7 @@ static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); for (; addr != end; pte++, addr += PAGE_SIZE) - smaps_pte_entry(*pte, addr, walk); + smaps_pte_entry(*pte, addr, PAGE_SIZE, walk); pte_unmap_unlock(pte - 1, ptl); cond_resched(); return 0; -- cgit From 22e057c5923e60debad318cbeaee33033b110bc8 Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Tue, 22 Mar 2011 16:33:00 -0700 Subject: smaps: teach smaps_pte_range() about THP pmds This adds code to explicitly detect and handle pmd_trans_huge() pmds. It then passes HPAGE_SIZE units in to the smap_pte_entry() function instead of PAGE_SIZE. This means that using /proc/$pid/smaps now will no longer cause THPs to be broken down in to small pages. Signed-off-by: Dave Hansen Reviewed-by: Eric B Munson Tested-by: Eric B Munson Acked-by: Andrea Arcangeli Acked-by: David Rientjes Cc: Mel Gorman Cc: Michael J Wolf Cc: Andrea Arcangeli Cc: Johannes Weiner Cc: Matt Mackall Cc: Jeremy Fitzhardinge Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/proc/task_mmu.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index d7e2af334076..26f9cc00102c 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -7,6 +8,7 @@ #include #include #include +#include #include #include @@ -385,8 +387,25 @@ static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, pte_t *pte; spinlock_t *ptl; - split_huge_page_pmd(walk->mm, pmd); - + spin_lock(&walk->mm->page_table_lock); + if (pmd_trans_huge(*pmd)) { + if (pmd_trans_splitting(*pmd)) { + spin_unlock(&walk->mm->page_table_lock); + wait_split_huge_page(vma->anon_vma, pmd); + } else { + smaps_pte_entry(*(pte_t *)pmd, addr, + HPAGE_PMD_SIZE, walk); + spin_unlock(&walk->mm->page_table_lock); + return 0; + } + } else { + spin_unlock(&walk->mm->page_table_lock); + } + /* + * The mmap_sem held all the way back in m_start() is what + * keeps khugepaged out of here and from collapsing things + * in here. + */ pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); for (; addr != end; pte++, addr += PAGE_SIZE) smaps_pte_entry(*pte, addr, PAGE_SIZE, walk); -- cgit From 4031a219d8913da40ade5a6e5b538cc61e975cc8 Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Tue, 22 Mar 2011 16:33:01 -0700 Subject: smaps: have smaps show transparent huge pages Now that the mere act of _looking_ at /proc/$pid/smaps will not destroy transparent huge pages, tell how much of the VMA is actually mapped with them. This way, we can make sure that we're getting THPs where we expect to see them. Signed-off-by: Dave Hansen Acked-by: Mel Gorman Acked-by: David Rientjes Reviewed-by: Eric B Munson Tested-by: Eric B Munson Cc: Michael J Wolf Cc: Andrea Arcangeli Cc: Johannes Weiner Cc: Matt Mackall Cc: Jeremy Fitzhardinge Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/proc/task_mmu.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'fs') diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 26f9cc00102c..93381aae9363 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -331,6 +331,7 @@ struct mem_size_stats { unsigned long private_dirty; unsigned long referenced; unsigned long anonymous; + unsigned long anonymous_thp; unsigned long swap; u64 pss; }; @@ -396,6 +397,7 @@ static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, smaps_pte_entry(*(pte_t *)pmd, addr, HPAGE_PMD_SIZE, walk); spin_unlock(&walk->mm->page_table_lock); + mss->anonymous_thp += HPAGE_PMD_SIZE; return 0; } } else { @@ -444,6 +446,7 @@ static int show_smap(struct seq_file *m, void *v) "Private_Dirty: %8lu kB\n" "Referenced: %8lu kB\n" "Anonymous: %8lu kB\n" + "AnonHugePages: %8lu kB\n" "Swap: %8lu kB\n" "KernelPageSize: %8lu kB\n" "MMUPageSize: %8lu kB\n" @@ -457,6 +460,7 @@ static int show_smap(struct seq_file *m, void *v) mss.private_dirty >> 10, mss.referenced >> 10, mss.anonymous >> 10, + mss.anonymous_thp >> 10, mss.swap >> 10, vma_kernel_pagesize(vma) >> 10, vma_mmu_pagesize(vma) >> 10, -- cgit From 80cdc6dae76ea67d2b21bdca8df17ef47251eb8b Mon Sep 17 00:00:00 2001 From: Mandeep Singh Baines Date: Tue, 22 Mar 2011 16:33:54 -0700 Subject: fs: use appropriate printk priority levels printk()s without a priority level default to KERN_WARNING. To reduce noise at KERN_WARNING, this patch set the priority level appriopriately for unleveled printks()s. This should be useful to folks that look at dmesg warnings closely. Signed-off-by: Mandeep Singh Baines Cc: Jens Axboe Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/bio.c | 2 +- fs/namespace.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/bio.c b/fs/bio.c index 4bd454fa844e..4cf2a52fbc54 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -111,7 +111,7 @@ static struct kmem_cache *bio_find_or_create_slab(unsigned int extra_size) if (!slab) goto out_unlock; - printk("bio: create slab <%s> at %d\n", bslab->name, entry); + printk(KERN_INFO "bio: create slab <%s> at %d\n", bslab->name, entry); bslab->slab = slab; bslab->slab_ref = 1; bslab->slab_size = sz; diff --git a/fs/namespace.c b/fs/namespace.c index 9263995bf6a1..7dba2ed03429 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -2701,7 +2701,7 @@ void __init mnt_init(void) if (!mount_hashtable) panic("Failed to allocate mount hash table\n"); - printk("Mount-cache hash table entries: %lu\n", HASH_SIZE); + printk(KERN_INFO "Mount-cache hash table entries: %lu\n", HASH_SIZE); for (u = 0; u < HASH_SIZE; u++) INIT_LIST_HEAD(&mount_hashtable[u]); -- cgit From 3fb0e584a68cd1c5085e69be441f2ad032aaee72 Mon Sep 17 00:00:00 2001 From: Davide Libenzi Date: Tue, 22 Mar 2011 16:34:46 -0700 Subject: epoll: move ready event check into proper inline Move the event readiness check into a proper inline, and use it uniformly inside ep_poll() code. Events in the ->ovflist are no less ready than the ones in ->rdllist. Signed-off-by: Davide Libenzi Cc: Shawn Bohrer Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/eventpoll.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/eventpoll.c b/fs/eventpoll.c index ff12f7ac73ef..57298d092f56 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -315,6 +315,19 @@ static void ep_nested_calls_init(struct nested_calls *ncalls) spin_lock_init(&ncalls->lock); } +/** + * ep_events_available - Checks if ready events might be available. + * + * @ep: Pointer to the eventpoll context. + * + * Returns: Returns a value different than zero if ready events are available, + * or zero otherwise. + */ +static inline int ep_events_available(struct eventpoll *ep) +{ + return !list_empty(&ep->rdllist) || ep->ovflist != EP_UNACTIVE_PTR; +} + /** * ep_call_nested - Perform a bound (possibly) nested call, by checking * that the recursion limit is not exceeded, and that @@ -1158,7 +1171,7 @@ retry: spin_lock_irqsave(&ep->lock, flags); res = 0; - if (list_empty(&ep->rdllist)) { + if (!ep_events_available(ep)) { /* * We don't have any available event to return to the caller. * We need to sleep here, and we will be wake up by @@ -1174,7 +1187,7 @@ retry: * to TASK_INTERRUPTIBLE before doing the checks. */ set_current_state(TASK_INTERRUPTIBLE); - if (!list_empty(&ep->rdllist) || timed_out) + if (ep_events_available(ep) || timed_out) break; if (signal_pending(current)) { res = -EINTR; @@ -1192,7 +1205,7 @@ retry: set_current_state(TASK_RUNNING); } /* Is it worth to try to dig for events ? */ - eavail = !list_empty(&ep->rdllist) || ep->ovflist != EP_UNACTIVE_PTR; + eavail = ep_events_available(ep); spin_unlock_irqrestore(&ep->lock, flags); -- cgit From f4d93ad74c18143abd3067ca3c8ffba7d00addf4 Mon Sep 17 00:00:00 2001 From: Shawn Bohrer Date: Tue, 22 Mar 2011 16:34:47 -0700 Subject: epoll: fix compiler warning and optimize the non-blocking path Add a comment to ep_poll(), rename labels a bit clearly, fix a warning of unused variable from gcc and optimize the non-blocking path a little. Hinted-by: Andrew Morton Signed-off-by: Davide Libenzi hannes@cmpxchg.org: : The non-blocking ep_poll path optimization introduced skipping over the : return value setup. : : Initialize it properly, my userspace gets upset by epoll_wait() returning : random things. : : In addition, remove the reinitialization at the fetch_events label, the : return value is garuanteed to be zero when execution reaches there. [hannes@cmpxchg.org: fix initialization] Signed-off-by: Johannes Weiner Cc: Shawn Bohrer Acked-by: Davide Libenzi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/eventpoll.c | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 57298d092f56..ed38801b57a7 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -1148,12 +1148,29 @@ static inline struct timespec ep_set_mstimeout(long ms) return timespec_add_safe(now, ts); } +/** + * ep_poll - Retrieves ready events, and delivers them to the caller supplied + * event buffer. + * + * @ep: Pointer to the eventpoll context. + * @events: Pointer to the userspace buffer where the ready events should be + * stored. + * @maxevents: Size (in terms of number of events) of the caller event buffer. + * @timeout: Maximum timeout for the ready events fetch operation, in + * milliseconds. If the @timeout is zero, the function will not block, + * while if the @timeout is less than zero, the function will block + * until at least one event has been retrieved (or an error + * occurred). + * + * Returns: Returns the number of ready events which have been fetched, or an + * error code, in case of error. + */ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events, int maxevents, long timeout) { - int res, eavail, timed_out = 0; + int res = 0, eavail, timed_out = 0; unsigned long flags; - long slack; + long slack = 0; wait_queue_t wait; ktime_t expires, *to = NULL; @@ -1164,13 +1181,18 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events, to = &expires; *to = timespec_to_ktime(end_time); } else if (timeout == 0) { + /* + * Avoid the unnecessary trip to the wait queue loop, if the + * caller specified a non blocking operation. + */ timed_out = 1; + spin_lock_irqsave(&ep->lock, flags); + goto check_events; } -retry: +fetch_events: spin_lock_irqsave(&ep->lock, flags); - res = 0; if (!ep_events_available(ep)) { /* * We don't have any available event to return to the caller. @@ -1204,6 +1226,7 @@ retry: set_current_state(TASK_RUNNING); } +check_events: /* Is it worth to try to dig for events ? */ eavail = ep_events_available(ep); @@ -1216,7 +1239,7 @@ retry: */ if (!res && eavail && !(res = ep_send_events(ep, events, maxevents)) && !timed_out) - goto retry; + goto fetch_events; return res; } -- cgit From 1a530a6f23f7dca336311ef60c9ca26f3dc63688 Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 22 Mar 2011 16:34:48 -0700 Subject: binfmt_elf: quiet GCC-4.6 'set but not used' warning in load_elf_binary() With GCC-4.6 we get warnings about things being 'set but not used'. In load_elf_binary() this can happen with reloc_func_desc if ELF_PLAT_INIT is defined, but doesn't use the reloc_func_desc argument. Quiet the warning/error by marking reloc_func_desc as __maybe_unused. Signed-off-by: David Daney Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/binfmt_elf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index d5b640ba6cb1..b2fae009a4b7 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -570,7 +570,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) unsigned long elf_entry; unsigned long interp_load_addr = 0; unsigned long start_code, end_code, start_data, end_data; - unsigned long reloc_func_desc = 0; + unsigned long reloc_func_desc __maybe_unused = 0; int executable_stack = EXSTACK_DEFAULT; unsigned long def_flags = 0; struct { -- cgit From 0bc825d240abcaf5ed6e9d59b44215b51718ef5b Mon Sep 17 00:00:00 2001 From: Rakib Mullick Date: Tue, 22 Mar 2011 16:35:00 -0700 Subject: codafs: fix compile warning when CONFIG_SYSCTL=n When CONFIG_SYSCTL=n, we get the following warning: fs/coda/sysctl.c:18: warning: `coda_tabl' defined but not used Fix the warning by making sure coda_table and it's callee function are in the same context. Also clean up the code by removing extra #ifdef. [akpm@linux-foundation.org: remove unneeded stub macros] Signed-off-by: Rakib Mullick Cc: Jan Harkes Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/coda/sysctl.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'fs') diff --git a/fs/coda/sysctl.c b/fs/coda/sysctl.c index c6405ce3c50e..06d27a41807f 100644 --- a/fs/coda/sysctl.c +++ b/fs/coda/sysctl.c @@ -13,7 +13,6 @@ #ifdef CONFIG_SYSCTL static struct ctl_table_header *fs_table_header; -#endif static ctl_table coda_table[] = { { @@ -40,7 +39,6 @@ static ctl_table coda_table[] = { {} }; -#ifdef CONFIG_SYSCTL static ctl_table fs_table[] = { { .procname = "coda", @@ -49,22 +47,18 @@ static ctl_table fs_table[] = { }, {} }; -#endif void coda_sysctl_init(void) { -#ifdef CONFIG_SYSCTL if ( !fs_table_header ) fs_table_header = register_sysctl_table(fs_table); -#endif } void coda_sysctl_clean(void) { -#ifdef CONFIG_SYSCTL if ( fs_table_header ) { unregister_sysctl_table(fs_table_header); fs_table_header = NULL; } -#endif } +#endif -- cgit From 2f09719af705db56032ae480a2d9c32c2a3fcbd3 Mon Sep 17 00:00:00 2001 From: Stuart Swales Date: Tue, 22 Mar 2011 16:35:04 -0700 Subject: adfs: fix E+/F+ dir size > 2048 crashing kernel Kernel crashes in fs/adfs module when accessing directories with a large number of objects on mounted Acorn ADFS E+/F+ format discs (or images) as the existing code writes off the end of the fixed array of struct buffer_head pointers. Additionally, each directory access that didn't crash would leak a buffer as nr_buffers was not adjusted correctly for E+/F+ discs (was always left as one less than required). The patch fixes this by allocating a dynamically-sized set of struct buffer_head pointers if necessary for the E+/F+ case (many directories still do in fact fit in 2048 bytes) and sets the correct nr_buffers so that all buffers are released. Addresses https://bugzilla.kernel.org/show_bug.cgi?id=26072 Tested by tar'ing the contents of my RISC PC's E+ format 20Gb HDD which contains a number of large directories that previously crashed the kernel. Signed-off-by: Stuart Swales Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/adfs/adfs.h | 4 +++ fs/adfs/dir_fplus.c | 101 +++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 84 insertions(+), 21 deletions(-) (limited to 'fs') diff --git a/fs/adfs/adfs.h b/fs/adfs/adfs.h index 2ff622f6f547..58588ddb178c 100644 --- a/fs/adfs/adfs.h +++ b/fs/adfs/adfs.h @@ -79,6 +79,10 @@ struct adfs_dir { int nr_buffers; struct buffer_head *bh[4]; + + /* big directories need allocated buffers */ + struct buffer_head **bh_fplus; + unsigned int pos; unsigned int parent_id; diff --git a/fs/adfs/dir_fplus.c b/fs/adfs/dir_fplus.c index 1796bb352d05..a7f41da8115b 100644 --- a/fs/adfs/dir_fplus.c +++ b/fs/adfs/dir_fplus.c @@ -8,6 +8,7 @@ * published by the Free Software Foundation. */ #include +#include #include "adfs.h" #include "dir_fplus.h" @@ -22,30 +23,53 @@ adfs_fplus_read(struct super_block *sb, unsigned int id, unsigned int sz, struct dir->nr_buffers = 0; + /* start off using fixed bh set - only alloc for big dirs */ + dir->bh_fplus = &dir->bh[0]; + block = __adfs_block_map(sb, id, 0); if (!block) { adfs_error(sb, "dir object %X has a hole at offset 0", id); goto out; } - dir->bh[0] = sb_bread(sb, block); - if (!dir->bh[0]) + dir->bh_fplus[0] = sb_bread(sb, block); + if (!dir->bh_fplus[0]) goto out; dir->nr_buffers += 1; - h = (struct adfs_bigdirheader *)dir->bh[0]->b_data; + h = (struct adfs_bigdirheader *)dir->bh_fplus[0]->b_data; size = le32_to_cpu(h->bigdirsize); if (size != sz) { - printk(KERN_WARNING "adfs: adfs_fplus_read: directory header size\n" - " does not match directory size\n"); + printk(KERN_WARNING "adfs: adfs_fplus_read:" + " directory header size %X\n" + " does not match directory size %X\n", + size, sz); } if (h->bigdirversion[0] != 0 || h->bigdirversion[1] != 0 || h->bigdirversion[2] != 0 || size & 2047 || - h->bigdirstartname != cpu_to_le32(BIGDIRSTARTNAME)) + h->bigdirstartname != cpu_to_le32(BIGDIRSTARTNAME)) { + printk(KERN_WARNING "adfs: dir object %X has" + " malformed dir header\n", id); goto out; + } size >>= sb->s_blocksize_bits; + if (size > sizeof(dir->bh)/sizeof(dir->bh[0])) { + /* this directory is too big for fixed bh set, must allocate */ + struct buffer_head **bh_fplus = + kzalloc(size * sizeof(struct buffer_head *), + GFP_KERNEL); + if (!bh_fplus) { + adfs_error(sb, "not enough memory for" + " dir object %X (%d blocks)", id, size); + goto out; + } + dir->bh_fplus = bh_fplus; + /* copy over the pointer to the block that we've already read */ + dir->bh_fplus[0] = dir->bh[0]; + } + for (blk = 1; blk < size; blk++) { block = __adfs_block_map(sb, id, blk); if (!block) { @@ -53,25 +77,44 @@ adfs_fplus_read(struct super_block *sb, unsigned int id, unsigned int sz, struct goto out; } - dir->bh[blk] = sb_bread(sb, block); - if (!dir->bh[blk]) + dir->bh_fplus[blk] = sb_bread(sb, block); + if (!dir->bh_fplus[blk]) { + adfs_error(sb, "dir object %X failed read for" + " offset %d, mapped block %X", + id, blk, block); goto out; - dir->nr_buffers = blk; + } + + dir->nr_buffers += 1; } - t = (struct adfs_bigdirtail *)(dir->bh[size - 1]->b_data + (sb->s_blocksize - 8)); + t = (struct adfs_bigdirtail *) + (dir->bh_fplus[size - 1]->b_data + (sb->s_blocksize - 8)); if (t->bigdirendname != cpu_to_le32(BIGDIRENDNAME) || t->bigdirendmasseq != h->startmasseq || - t->reserved[0] != 0 || t->reserved[1] != 0) + t->reserved[0] != 0 || t->reserved[1] != 0) { + printk(KERN_WARNING "adfs: dir object %X has " + "malformed dir end\n", id); goto out; + } dir->parent_id = le32_to_cpu(h->bigdirparent); dir->sb = sb; return 0; + out: - for (i = 0; i < dir->nr_buffers; i++) - brelse(dir->bh[i]); + if (dir->bh_fplus) { + for (i = 0; i < dir->nr_buffers; i++) + brelse(dir->bh_fplus[i]); + + if (&dir->bh[0] != dir->bh_fplus) + kfree(dir->bh_fplus); + + dir->bh_fplus = NULL; + } + + dir->nr_buffers = 0; dir->sb = NULL; return ret; } @@ -79,7 +122,8 @@ out: static int adfs_fplus_setpos(struct adfs_dir *dir, unsigned int fpos) { - struct adfs_bigdirheader *h = (struct adfs_bigdirheader *)dir->bh[0]->b_data; + struct adfs_bigdirheader *h = + (struct adfs_bigdirheader *) dir->bh_fplus[0]->b_data; int ret = -ENOENT; if (fpos <= le32_to_cpu(h->bigdirentries)) { @@ -102,21 +146,27 @@ dir_memcpy(struct adfs_dir *dir, unsigned int offset, void *to, int len) partial = sb->s_blocksize - offset; if (partial >= len) - memcpy(to, dir->bh[buffer]->b_data + offset, len); + memcpy(to, dir->bh_fplus[buffer]->b_data + offset, len); else { char *c = (char *)to; remainder = len - partial; - memcpy(c, dir->bh[buffer]->b_data + offset, partial); - memcpy(c + partial, dir->bh[buffer + 1]->b_data, remainder); + memcpy(c, + dir->bh_fplus[buffer]->b_data + offset, + partial); + + memcpy(c + partial, + dir->bh_fplus[buffer + 1]->b_data, + remainder); } } static int adfs_fplus_getnext(struct adfs_dir *dir, struct object_info *obj) { - struct adfs_bigdirheader *h = (struct adfs_bigdirheader *)dir->bh[0]->b_data; + struct adfs_bigdirheader *h = + (struct adfs_bigdirheader *) dir->bh_fplus[0]->b_data; struct adfs_bigdirentry bde; unsigned int offset; int i, ret = -ENOENT; @@ -160,7 +210,7 @@ adfs_fplus_sync(struct adfs_dir *dir) int i; for (i = dir->nr_buffers - 1; i >= 0; i--) { - struct buffer_head *bh = dir->bh[i]; + struct buffer_head *bh = dir->bh_fplus[i]; sync_dirty_buffer(bh); if (buffer_req(bh) && !buffer_uptodate(bh)) err = -EIO; @@ -174,8 +224,17 @@ adfs_fplus_free(struct adfs_dir *dir) { int i; - for (i = 0; i < dir->nr_buffers; i++) - brelse(dir->bh[i]); + if (dir->bh_fplus) { + for (i = 0; i < dir->nr_buffers; i++) + brelse(dir->bh_fplus[i]); + + if (&dir->bh[0] != dir->bh_fplus) + kfree(dir->bh_fplus); + + dir->bh_fplus = NULL; + } + + dir->nr_buffers = 0; dir->sb = NULL; } -- cgit From 7a9730af9c596749425a98eba136152e5be4602a Mon Sep 17 00:00:00 2001 From: Stuart Swales Date: Tue, 22 Mar 2011 16:35:05 -0700 Subject: adfs: improve timestamp precision ADFS (FileCore) storage complies with the RISC OS timestamp specification (40-bit centiseconds since 01 Jan 1900 00:00:00). It is desirable that stored timestamp precision be maintained to facilitate a precise copy of data and metadata from a hard disc (or image thereof) into a RISC OS emulator (such as RPCEmu). This patch implements a full-precision conversion from ADFS to Unix timestamp as the existing driver, for ease of calculation with old 32-bit compilers, uses the common trick of shifting the 40-bits representing centiseconds around into 32-bits representing seconds thereby losing precision. Signed-off-by: Stuart Swales Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/adfs/inode.c | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) (limited to 'fs') diff --git a/fs/adfs/inode.c b/fs/adfs/inode.c index 09fe40198d1c..16d7ef2dffe1 100644 --- a/fs/adfs/inode.c +++ b/fs/adfs/inode.c @@ -174,50 +174,48 @@ adfs_mode2atts(struct super_block *sb, struct inode *inode) /* * Convert an ADFS time to Unix time. ADFS has a 40-bit centi-second time - * referenced to 1 Jan 1900 (til 2248) + * referenced to 1 Jan 1900 (til 2248) so we need to discard 2208988800 seconds + * of time to convert from RISC OS epoch to Unix epoch. */ static void adfs_adfs2unix_time(struct timespec *tv, struct inode *inode) { unsigned int high, low; + /* 01 Jan 1970 00:00:00 (Unix epoch) as nanoseconds since + * 01 Jan 1900 00:00:00 (RISC OS epoch) + */ + static const s64 nsec_unix_epoch_diff_risc_os_epoch = + 2208988800000000000LL; + s64 nsec; if (ADFS_I(inode)->stamped == 0) goto cur_time; - high = ADFS_I(inode)->loadaddr << 24; - low = ADFS_I(inode)->execaddr; + high = ADFS_I(inode)->loadaddr & 0xFF; /* top 8 bits of timestamp */ + low = ADFS_I(inode)->execaddr; /* bottom 32 bits of timestamp */ - high |= low >> 8; - low &= 255; + /* convert 40-bit centi-seconds to 32-bit seconds + * going via nanoseconds to retain precision + */ + nsec = (((s64) high << 32) | (s64) low) * 10000000; /* cs to ns */ /* Files dated pre 01 Jan 1970 00:00:00. */ - if (high < 0x336e996a) + if (nsec < nsec_unix_epoch_diff_risc_os_epoch) goto too_early; - /* Files dated post 18 Jan 2038 03:14:05. */ - if (high >= 0x656e9969) - goto too_late; - - /* discard 2208988800 (0x336e996a00) seconds of time */ - high -= 0x336e996a; + /* convert from RISC OS to Unix epoch */ + nsec -= nsec_unix_epoch_diff_risc_os_epoch; - /* convert 40-bit centi-seconds to 32-bit seconds */ - tv->tv_sec = (((high % 100) << 8) + low) / 100 + (high / 100 << 8); - tv->tv_nsec = 0; + *tv = ns_to_timespec(nsec); return; cur_time: - *tv = CURRENT_TIME_SEC; + *tv = CURRENT_TIME; return; too_early: tv->tv_sec = tv->tv_nsec = 0; return; - - too_late: - tv->tv_sec = 0x7ffffffd; - tv->tv_nsec = 0; - return; } /* -- cgit From da23ef0549d4205ca9b576cf6cce9a80d0c3e43a Mon Sep 17 00:00:00 2001 From: Stuart Swales Date: Tue, 22 Mar 2011 16:35:06 -0700 Subject: adfs: add hexadecimal filetype suffix option ADFS (FileCore) storage complies with the RISC OS filetype specification (12 bits of file type information is stored in the file load address, rather than using a file extension). The existing driver largely ignores this information and does not present it to the end user. It is desirable that stored filetypes be made visible to the end user to facilitate a precise copy of data and metadata from a hard disc (or image thereof) into a RISC OS emulator (such as RPCEmu) or to a network share which can be accessed by real Acorn systems. This patch implements a per-mount filetype suffix option (use -o ftsuffix=1) to present any filetype as a ,xyz hexadecimal suffix on each file. This type suffix is compatible with that used by RISC OS systems that access network servers using NFS client software and by RPCemu's host filing system. Signed-off-by: Stuart Swales Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/adfs/adfs.h | 21 +++++++++++++++++++-- fs/adfs/dir_f.c | 23 ++++++++++++++++++++--- fs/adfs/dir_fplus.c | 18 ++++++++++++++++++ fs/adfs/inode.c | 22 ++++------------------ fs/adfs/super.c | 23 ++++++++++++++++++++--- 5 files changed, 81 insertions(+), 26 deletions(-) (limited to 'fs') diff --git a/fs/adfs/adfs.h b/fs/adfs/adfs.h index 58588ddb178c..a8a58d864f96 100644 --- a/fs/adfs/adfs.h +++ b/fs/adfs/adfs.h @@ -50,6 +50,7 @@ struct adfs_sb_info { gid_t s_gid; /* owner gid */ umode_t s_owner_mask; /* ADFS owner perm -> unix perm */ umode_t s_other_mask; /* ADFS other perm -> unix perm */ + int s_ftsuffix; /* ,xyz hex filetype suffix option */ __u32 s_ids_per_zone; /* max. no ids in one zone */ __u32 s_idlen; /* length of ID in map */ @@ -93,7 +94,7 @@ struct adfs_dir { /* * This is the overall maximum name length */ -#define ADFS_MAX_NAME_LEN 256 +#define ADFS_MAX_NAME_LEN (256 + 4) /* +4 for ,xyz hex filetype suffix */ struct object_info { __u32 parent_id; /* parent object id */ __u32 file_id; /* object id */ @@ -101,10 +102,26 @@ struct object_info { __u32 execaddr; /* execution address */ __u32 size; /* size */ __u8 attr; /* RISC OS attributes */ - unsigned char name_len; /* name length */ + unsigned int name_len; /* name length */ char name[ADFS_MAX_NAME_LEN];/* file name */ + + /* RISC OS file type (12-bit: derived from loadaddr) */ + __u16 filetype; }; +/* RISC OS 12-bit filetype converts to ,xyz hex filename suffix */ +static inline int append_filetype_suffix(char *buf, __u16 filetype) +{ + if (filetype == -1) + return 0; + + *buf++ = ','; + *buf++ = hex_asc_lo(filetype >> 8); + *buf++ = hex_asc_lo(filetype >> 4); + *buf++ = hex_asc_lo(filetype >> 0); + return 4; +} + struct adfs_dir_ops { int (*read)(struct super_block *sb, unsigned int id, unsigned int sz, struct adfs_dir *dir); int (*setpos)(struct adfs_dir *dir, unsigned int fpos); diff --git a/fs/adfs/dir_f.c b/fs/adfs/dir_f.c index bafc71222e25..4bbe853ee50a 100644 --- a/fs/adfs/dir_f.c +++ b/fs/adfs/dir_f.c @@ -52,7 +52,6 @@ static inline int adfs_readname(char *buf, char *ptr, int maxlen) *buf++ = *ptr; ptr++; } - *buf = '\0'; return buf - old_buf; } @@ -208,7 +207,8 @@ release_buffers: * convert a disk-based directory entry to a Linux ADFS directory entry */ static inline void -adfs_dir2obj(struct object_info *obj, struct adfs_direntry *de) +adfs_dir2obj(struct adfs_dir *dir, struct object_info *obj, + struct adfs_direntry *de) { obj->name_len = adfs_readname(obj->name, de->dirobname, ADFS_F_NAME_LEN); obj->file_id = adfs_readval(de->dirinddiscadd, 3); @@ -216,6 +216,23 @@ adfs_dir2obj(struct object_info *obj, struct adfs_direntry *de) obj->execaddr = adfs_readval(de->direxec, 4); obj->size = adfs_readval(de->dirlen, 4); obj->attr = de->newdiratts; + obj->filetype = -1; + + /* + * object is a file and is filetyped and timestamped? + * RISC OS 12-bit filetype is stored in load_address[19:8] + */ + if ((0 == (obj->attr & ADFS_NDA_DIRECTORY)) && + (0xfff00000 == (0xfff00000 & obj->loadaddr))) { + obj->filetype = (__u16) ((0x000fff00 & obj->loadaddr) >> 8); + + /* optionally append the ,xyz hex filetype suffix */ + if (ADFS_SB(dir->sb)->s_ftsuffix) + obj->name_len += + append_filetype_suffix( + &obj->name[obj->name_len], + obj->filetype); + } } /* @@ -260,7 +277,7 @@ __adfs_dir_get(struct adfs_dir *dir, int pos, struct object_info *obj) if (!de.dirobname[0]) return -ENOENT; - adfs_dir2obj(obj, &de); + adfs_dir2obj(dir, obj, &de); return 0; } diff --git a/fs/adfs/dir_fplus.c b/fs/adfs/dir_fplus.c index a7f41da8115b..d9e3bee4e653 100644 --- a/fs/adfs/dir_fplus.c +++ b/fs/adfs/dir_fplus.c @@ -197,6 +197,24 @@ adfs_fplus_getnext(struct adfs_dir *dir, struct object_info *obj) if (obj->name[i] == '/') obj->name[i] = '.'; + obj->filetype = -1; + + /* + * object is a file and is filetyped and timestamped? + * RISC OS 12-bit filetype is stored in load_address[19:8] + */ + if ((0 == (obj->attr & ADFS_NDA_DIRECTORY)) && + (0xfff00000 == (0xfff00000 & obj->loadaddr))) { + obj->filetype = (__u16) ((0x000fff00 & obj->loadaddr) >> 8); + + /* optionally append the ,xyz hex filetype suffix */ + if (ADFS_SB(dir->sb)->s_ftsuffix) + obj->name_len += + append_filetype_suffix( + &obj->name[obj->name_len], + obj->filetype); + } + dir->pos += 1; ret = 0; out: diff --git a/fs/adfs/inode.c b/fs/adfs/inode.c index 16d7ef2dffe1..92444e94f842 100644 --- a/fs/adfs/inode.c +++ b/fs/adfs/inode.c @@ -78,26 +78,13 @@ static const struct address_space_operations adfs_aops = { .bmap = _adfs_bmap }; -static inline unsigned int -adfs_filetype(struct inode *inode) -{ - unsigned int type; - - if (ADFS_I(inode)->stamped) - type = (ADFS_I(inode)->loadaddr >> 8) & 0xfff; - else - type = (unsigned int) -1; - - return type; -} - /* * Convert ADFS attributes and filetype to Linux permission. */ static umode_t adfs_atts2mode(struct super_block *sb, struct inode *inode) { - unsigned int filetype, attr = ADFS_I(inode)->attr; + unsigned int attr = ADFS_I(inode)->attr; umode_t mode, rmask; struct adfs_sb_info *asb = ADFS_SB(sb); @@ -106,9 +93,7 @@ adfs_atts2mode(struct super_block *sb, struct inode *inode) return S_IFDIR | S_IXUGO | mode; } - filetype = adfs_filetype(inode); - - switch (filetype) { + switch (ADFS_I(inode)->filetype) { case 0xfc0: /* LinkFS */ return S_IFLNK|S_IRWXUGO; @@ -277,7 +262,8 @@ adfs_iget(struct super_block *sb, struct object_info *obj) ADFS_I(inode)->loadaddr = obj->loadaddr; ADFS_I(inode)->execaddr = obj->execaddr; ADFS_I(inode)->attr = obj->attr; - ADFS_I(inode)->stamped = ((obj->loadaddr & 0xfff00000) == 0xfff00000); + ADFS_I(inode)->filetype = obj->filetype; + ADFS_I(inode)->stamped = ((obj->loadaddr & 0xfff00000) == 0xfff00000); inode->i_mode = adfs_atts2mode(sb, inode); adfs_adfs2unix_time(&inode->i_mtime, inode); diff --git a/fs/adfs/super.c b/fs/adfs/super.c index 06d7388b477b..c8bf36a1996a 100644 --- a/fs/adfs/super.c +++ b/fs/adfs/super.c @@ -138,17 +138,20 @@ static int adfs_show_options(struct seq_file *seq, struct vfsmount *mnt) seq_printf(seq, ",ownmask=%o", asb->s_owner_mask); if (asb->s_other_mask != ADFS_DEFAULT_OTHER_MASK) seq_printf(seq, ",othmask=%o", asb->s_other_mask); + if (asb->s_ftsuffix != 0) + seq_printf(seq, ",ftsuffix=%u", asb->s_ftsuffix); return 0; } -enum {Opt_uid, Opt_gid, Opt_ownmask, Opt_othmask, Opt_err}; +enum {Opt_uid, Opt_gid, Opt_ownmask, Opt_othmask, Opt_ftsuffix, Opt_err}; static const match_table_t tokens = { {Opt_uid, "uid=%u"}, {Opt_gid, "gid=%u"}, {Opt_ownmask, "ownmask=%o"}, {Opt_othmask, "othmask=%o"}, + {Opt_ftsuffix, "ftsuffix=%u"}, {Opt_err, NULL} }; @@ -189,6 +192,11 @@ static int parse_options(struct super_block *sb, char *options) return -EINVAL; asb->s_other_mask = option; break; + case Opt_ftsuffix: + if (match_int(args, &option)) + return -EINVAL; + asb->s_ftsuffix = option; + break; default: printk("ADFS-fs: unrecognised mount option \"%s\" " "or missing value\n", p); @@ -366,6 +374,7 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent) asb->s_gid = 0; asb->s_owner_mask = ADFS_DEFAULT_OWNER_MASK; asb->s_other_mask = ADFS_DEFAULT_OTHER_MASK; + asb->s_ftsuffix = 0; if (parse_options(sb, data)) goto error; @@ -445,11 +454,13 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent) root_obj.parent_id = root_obj.file_id = le32_to_cpu(dr->root); root_obj.name_len = 0; - root_obj.loadaddr = 0; - root_obj.execaddr = 0; + /* Set root object date as 01 Jan 1987 00:00:00 */ + root_obj.loadaddr = 0xfff0003f; + root_obj.execaddr = 0xec22c000; root_obj.size = ADFS_NEWDIR_SIZE; root_obj.attr = ADFS_NDA_DIRECTORY | ADFS_NDA_OWNER_READ | ADFS_NDA_OWNER_WRITE | ADFS_NDA_PUBLIC_READ; + root_obj.filetype = -1; /* * If this is a F+ disk with variable length directories, @@ -463,6 +474,12 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent) asb->s_dir = &adfs_f_dir_ops; asb->s_namelen = ADFS_F_NAME_LEN; } + /* + * ,xyz hex filetype suffix may be added by driver + * to files that have valid RISC OS filetype + */ + if (asb->s_ftsuffix) + asb->s_namelen += 4; sb->s_d_op = &adfs_dentry_operations; root = adfs_iget(sb, &root_obj); -- cgit From e91f90bb0bb10be9cc8efd09a3cf4ecffcad0db1 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Tue, 22 Mar 2011 16:35:10 -0700 Subject: aio: wake all waiters when destroying ctx The test program below will hang because io_getevents() uses add_wait_queue_exclusive(), which means the wake_up() in io_destroy() only wakes up one of the threads. Fix this by using wake_up_all() in the aio code paths where we want to make sure no one gets stuck. // t.c -- compile with gcc -lpthread -laio t.c #include #include #include #include static const int nthr = 2; void *getev(void *ctx) { struct io_event ev; io_getevents(ctx, 1, 1, &ev, NULL); printf("io_getevents returned\n"); return NULL; } int main(int argc, char *argv[]) { io_context_t ctx = 0; pthread_t thread[nthr]; int i; io_setup(1024, &ctx); for (i = 0; i < nthr; ++i) pthread_create(&thread[i], NULL, getev, ctx); sleep(1); io_destroy(ctx); for (i = 0; i < nthr; ++i) pthread_join(thread[i], NULL); return 0; } Signed-off-by: Roland Dreier Reviewed-by: Jeff Moyer Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/aio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/aio.c b/fs/aio.c index 7f54f43b8f7c..ebb6a22e4e1b 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -520,7 +520,7 @@ static inline void really_put_req(struct kioctx *ctx, struct kiocb *req) ctx->reqs_active--; if (unlikely(!ctx->reqs_active && ctx->dead)) - wake_up(&ctx->wait); + wake_up_all(&ctx->wait); } static void aio_fput_routine(struct work_struct *data) @@ -1229,7 +1229,7 @@ static void io_destroy(struct kioctx *ioctx) * by other CPUs at this point. Right now, we rely on the * locking done by the above calls to ensure this consistency. */ - wake_up(&ioctx->wait); + wake_up_all(&ioctx->wait); put_ioctx(ioctx); /* once for the lookup */ } -- cgit From b12d12596992f608f5506a8dabe4d1299594bd1e Mon Sep 17 00:00:00 2001 From: Andrey Vagin Date: Tue, 22 Mar 2011 16:35:11 -0700 Subject: fs/devpts/inode.c: correctly check d_alloc_name() return code in devpts_pty_new() d_alloc_name return NULL in case error, but we expect errno in devpts_pty_new. Addresses http://bugzilla.openvz.org/show_bug.cgi?id=1758 Signed-off-by: Andrey Vagin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/devpts/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index c6bd815dc794..2f27e578d466 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c @@ -502,7 +502,7 @@ int devpts_pty_new(struct inode *ptmx_inode, struct tty_struct *tty) mutex_lock(&root->d_inode->i_mutex); dentry = d_alloc_name(root, s); - if (!IS_ERR(dentry)) { + if (dentry) { d_add(dentry, inode); fsnotify_create(root->d_inode, dentry); } else { -- cgit From 565d76cb7d5fd7cb010fd690602280a69ab116ef Mon Sep 17 00:00:00 2001 From: Jim Keniston Date: Tue, 22 Mar 2011 16:35:12 -0700 Subject: zlib: slim down zlib_deflate() workspace when possible Instead of always creating a huge (268K) deflate_workspace with the maximum compression parameters (windowBits=15, memLevel=8), allow the caller to obtain a smaller workspace by specifying smaller parameter values. For example, when capturing oops and panic reports to a medium with limited capacity, such as NVRAM, compression may be the only way to capture the whole report. In this case, a small workspace (24K works fine) is a win, whether you allocate the workspace when you need it (i.e., during an oops or panic) or at boot time. I've verified that this patch works with all accepted values of windowBits (positive and negative), memLevel, and compression level. Signed-off-by: Jim Keniston Cc: Herbert Xu Cc: David Miller Cc: Chris Mason Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/btrfs/zlib.c | 3 ++- fs/jffs2/compr_zlib.c | 7 ++++--- fs/logfs/compr.c | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/btrfs/zlib.c b/fs/btrfs/zlib.c index f5ec2d44150d..faccd47c6c46 100644 --- a/fs/btrfs/zlib.c +++ b/fs/btrfs/zlib.c @@ -57,7 +57,8 @@ static struct list_head *zlib_alloc_workspace(void) if (!workspace) return ERR_PTR(-ENOMEM); - workspace->def_strm.workspace = vmalloc(zlib_deflate_workspacesize()); + workspace->def_strm.workspace = vmalloc(zlib_deflate_workspacesize( + MAX_WBITS, MAX_MEM_LEVEL)); workspace->inf_strm.workspace = vmalloc(zlib_inflate_workspacesize()); workspace->buf = kmalloc(PAGE_CACHE_SIZE, GFP_NOFS); if (!workspace->def_strm.workspace || diff --git a/fs/jffs2/compr_zlib.c b/fs/jffs2/compr_zlib.c index fd05a0b9431d..5a001020c542 100644 --- a/fs/jffs2/compr_zlib.c +++ b/fs/jffs2/compr_zlib.c @@ -40,12 +40,13 @@ static z_stream inf_strm, def_strm; static int __init alloc_workspaces(void) { - def_strm.workspace = vmalloc(zlib_deflate_workspacesize()); + def_strm.workspace = vmalloc(zlib_deflate_workspacesize(MAX_WBITS, + MAX_MEM_LEVEL)); if (!def_strm.workspace) { - printk(KERN_WARNING "Failed to allocate %d bytes for deflate workspace\n", zlib_deflate_workspacesize()); + printk(KERN_WARNING "Failed to allocate %d bytes for deflate workspace\n", zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL)); return -ENOMEM; } - D1(printk(KERN_DEBUG "Allocated %d bytes for deflate workspace\n", zlib_deflate_workspacesize())); + D1(printk(KERN_DEBUG "Allocated %d bytes for deflate workspace\n", zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL))); inf_strm.workspace = vmalloc(zlib_inflate_workspacesize()); if (!inf_strm.workspace) { printk(KERN_WARNING "Failed to allocate %d bytes for inflate workspace\n", zlib_inflate_workspacesize()); diff --git a/fs/logfs/compr.c b/fs/logfs/compr.c index 44bbfd249abc..961f02b86d97 100644 --- a/fs/logfs/compr.c +++ b/fs/logfs/compr.c @@ -81,7 +81,7 @@ error: int __init logfs_compr_init(void) { - size_t size = max(zlib_deflate_workspacesize(), + size_t size = max(zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL), zlib_inflate_workspacesize()); stream.workspace = vmalloc(size); if (!stream.workspace) -- cgit From bd23a539d0733c9f9ec3f9fc628491fad2658e82 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 23 Mar 2011 09:56:30 -0400 Subject: fix leaks in path_lookupat() Signed-off-by: Al Viro --- fs/namei.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/namei.c b/fs/namei.c index 5a9a6c3094da..a4dfac650c3c 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1644,13 +1644,16 @@ static int path_lookupat(int dfd, const char *name, err = -ECHILD; } - if (!err) + if (!err) { err = handle_reval_path(nd); + if (err) + path_put(&nd->path); + } if (!err && nd->flags & LOOKUP_DIRECTORY) { if (!nd->inode->i_op->lookup) { path_put(&nd->path); - return -ENOTDIR; + err = -ENOTDIR; } } -- cgit From 6de9843dab3f2a1d4d66d80aa9e5782f80977d20 Mon Sep 17 00:00:00 2001 From: Feng Tang Date: Wed, 23 Mar 2011 14:05:03 -0400 Subject: ext4: remove redundant set_buffer_mapped() in ext4_da_get_block_prep() The map_bh() call will have already set the buffer_head to mapped. Signed-off-by: Feng Tang Signed-off-by: "Theodore Ts'o" --- fs/ext4/inode.c | 1 - 1 file changed, 1 deletion(-) (limited to 'fs') diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index f44307a21136..dec10e2115e0 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2502,7 +2502,6 @@ static int ext4_da_get_block_prep(struct inode *inode, sector_t iblock, * for partial write. */ set_buffer_new(bh); - set_buffer_mapped(bh); } return 0; } -- cgit From 65922cb5ced76ba7182e955d4aada96f93446b1a Mon Sep 17 00:00:00 2001 From: Sergey Senozhatsky Date: Wed, 23 Mar 2011 14:08:27 -0400 Subject: ext4: unused variables cleanup in fs/ext4/extents.c ext4 extents cleanup: . remove unused `*ex' from check_eofblocks_fl . remove unused `*eh' from ext4_ext_map_blocks Signed-off-by: Sergey Senozhatsky Signed-off-by: "Theodore Ts'o" --- fs/ext4/extents.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index f46f6e3c02d7..1763d1ab9ea9 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -3112,14 +3112,13 @@ static int check_eofblocks_fl(handle_t *handle, struct inode *inode, { int i, depth; struct ext4_extent_header *eh; - struct ext4_extent *ex, *last_ex; + struct ext4_extent *last_ex; if (!ext4_test_inode_flag(inode, EXT4_INODE_EOFBLOCKS)) return 0; depth = ext_depth(inode); eh = path[depth].p_hdr; - ex = path[depth].p_ext; if (unlikely(!eh->eh_entries)) { EXT4_ERROR_INODE(inode, "eh->eh_entries == 0 and " @@ -3299,7 +3298,6 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, struct ext4_map_blocks *map, int flags) { struct ext4_ext_path *path = NULL; - struct ext4_extent_header *eh; struct ext4_extent newex, *ex; ext4_fsblk_t newblock = 0; int err = 0, depth, ret; @@ -3357,7 +3355,6 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, err = -EIO; goto out2; } - eh = path[depth].p_hdr; ex = path[depth].p_ext; if (ex) { -- cgit From e47c085afb3d16cbc6a4bfb10a3b074bb7c58998 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Wed, 23 Mar 2011 08:43:09 -0400 Subject: NFS: Ensure that we update the readdir filp->f_pos correctly If we're doing a search by readdir cookie, we need to ensure that the resulting f_pos is updated. To do so, we need to update the desc->current_index, in the same way that we do in the search by file offset case. Signed-off-by: Trond Myklebust --- fs/nfs/dir.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 2c3eb33b904d..c5c71cb62fbd 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -290,7 +290,6 @@ int nfs_readdir_search_for_pos(struct nfs_cache_array *array, nfs_readdir_descri if (diff >= array->size) { if (array->eof_index >= 0) goto out_eof; - desc->current_index += array->size; return -EAGAIN; } @@ -311,6 +310,7 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des for (i = 0; i < array->size; i++) { if (array->array[i].cookie == *desc->dir_cookie) { + desc->file->f_pos = desc->current_index + i; desc->cache_entry_index = i; return 0; } @@ -342,6 +342,7 @@ int nfs_readdir_search_array(nfs_readdir_descriptor_t *desc) if (status == -EAGAIN) { desc->last_cookie = array->last_cookie; + desc->current_index += array->size; desc->page_index++; } nfs_readdir_release_array(desc->page); -- cgit From 480c2006ebb44ae03165695db7b3e38c04e0d102 Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Wed, 23 Mar 2011 14:48:29 -0400 Subject: NFS: Create nfs_open_dir_context nfs_opendir() created a context that held much more information than we need for a readdir. This patch introduces a slimmed-down nfs_open_dir_context that contains only the cookie and the cred used for RPC operations. The new context will eventually be used to help detect readdir loops. Signed-off-by: Bryan Schumaker Signed-off-by: Trond Myklebust --- fs/nfs/dir.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++------- fs/nfs/inode.c | 1 - 2 files changed, 47 insertions(+), 8 deletions(-) (limited to 'fs') diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index c5c71cb62fbd..cda73814f666 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -44,6 +44,7 @@ /* #define NFS_DEBUG_VERBOSE 1 */ static int nfs_opendir(struct inode *, struct file *); +static int nfs_closedir(struct inode *, struct file *); static int nfs_readdir(struct file *, void *, filldir_t); static struct dentry *nfs_lookup(struct inode *, struct dentry *, struct nameidata *); static int nfs_create(struct inode *, struct dentry *, int, struct nameidata *); @@ -64,7 +65,7 @@ const struct file_operations nfs_dir_operations = { .read = generic_read_dir, .readdir = nfs_readdir, .open = nfs_opendir, - .release = nfs_release, + .release = nfs_closedir, .fsync = nfs_fsync_dir, }; @@ -133,13 +134,33 @@ const struct inode_operations nfs4_dir_inode_operations = { #endif /* CONFIG_NFS_V4 */ +static struct nfs_open_dir_context *alloc_nfs_open_dir_context(struct rpc_cred *cred) +{ + struct nfs_open_dir_context *ctx; + ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); + if (ctx != NULL) { + ctx->dir_cookie = 0; + ctx->cred = get_rpccred(cred); + } else + ctx = ERR_PTR(-ENOMEM); + return ctx; +} + +static void put_nfs_open_dir_context(struct nfs_open_dir_context *ctx) +{ + put_rpccred(ctx->cred); + kfree(ctx); +} + /* * Open file */ static int nfs_opendir(struct inode *inode, struct file *filp) { - int res; + int res = 0; + struct nfs_open_dir_context *ctx; + struct rpc_cred *cred; dfprintk(FILE, "NFS: open dir(%s/%s)\n", filp->f_path.dentry->d_parent->d_name.name, @@ -147,8 +168,15 @@ nfs_opendir(struct inode *inode, struct file *filp) nfs_inc_stats(inode, NFSIOS_VFSOPEN); - /* Call generic open code in order to cache credentials */ - res = nfs_open(inode, filp); + cred = rpc_lookup_cred(); + if (IS_ERR(cred)) + return PTR_ERR(cred); + ctx = alloc_nfs_open_dir_context(cred); + if (IS_ERR(ctx)) { + res = PTR_ERR(ctx); + goto out; + } + filp->private_data = ctx; if (filp->f_path.dentry == filp->f_path.mnt->mnt_root) { /* This is a mountpoint, so d_revalidate will never * have been called, so we need to refresh the @@ -156,9 +184,18 @@ nfs_opendir(struct inode *inode, struct file *filp) */ __nfs_revalidate_inode(NFS_SERVER(inode), inode); } +out: + put_rpccred(cred); return res; } +static int +nfs_closedir(struct inode *inode, struct file *filp) +{ + put_nfs_open_dir_context(filp->private_data); + return 0; +} + struct nfs_cache_array_entry { u64 cookie; u64 ino; @@ -355,7 +392,8 @@ static int nfs_readdir_xdr_filler(struct page **pages, nfs_readdir_descriptor_t *desc, struct nfs_entry *entry, struct file *file, struct inode *inode) { - struct rpc_cred *cred = nfs_file_cred(file); + struct nfs_open_dir_context *ctx = file->private_data; + struct rpc_cred *cred = ctx->cred; unsigned long timestamp, gencount; int error; @@ -786,6 +824,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) struct inode *inode = dentry->d_inode; nfs_readdir_descriptor_t my_desc, *desc = &my_desc; + struct nfs_open_dir_context *dir_ctx = filp->private_data; int res; dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n", @@ -802,7 +841,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) memset(desc, 0, sizeof(*desc)); desc->file = filp; - desc->dir_cookie = &nfs_file_open_context(filp)->dir_cookie; + desc->dir_cookie = &dir_ctx->dir_cookie; desc->decode = NFS_PROTO(inode)->decode_dirent; desc->plus = NFS_USE_READDIRPLUS(inode); @@ -854,6 +893,7 @@ static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin) { struct dentry *dentry = filp->f_path.dentry; struct inode *inode = dentry->d_inode; + struct nfs_open_dir_context *dir_ctx = filp->private_data; dfprintk(FILE, "NFS: llseek dir(%s/%s, %lld, %d)\n", dentry->d_parent->d_name.name, @@ -873,7 +913,7 @@ static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin) } if (offset != filp->f_pos) { filp->f_pos = offset; - nfs_file_open_context(filp)->dir_cookie = 0; + dir_ctx->dir_cookie = 0; } out: mutex_unlock(&inode->i_mutex); diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 2f8e61816d75..477a2e512b39 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -639,7 +639,6 @@ struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct rpc_cr ctx->mode = f_mode; ctx->flags = 0; ctx->error = 0; - ctx->dir_cookie = 0; nfs_init_lock_context(&ctx->lock_context); ctx->lock_context.open_context = ctx; INIT_LIST_HEAD(&ctx->list); -- cgit From 8ef2ce3e16d9bec6cf015207c1c82a5b864046ac Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Wed, 23 Mar 2011 15:04:31 -0400 Subject: NFS: Detect loops in a readdir due to bad cookies Some filesystems (such as ext4) can return the same cookie value for multiple files. If we try to start a readdir with one of these cookies, the server will return the first file found with a cookie of the same value. This can cause the client to enter an infinite loop. Signed-off-by: Bryan Schumaker Signed-off-by: Trond Myklebust --- fs/nfs/dir.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index cda73814f666..db87a7d1109b 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -139,7 +139,9 @@ static struct nfs_open_dir_context *alloc_nfs_open_dir_context(struct rpc_cred * struct nfs_open_dir_context *ctx; ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); if (ctx != NULL) { + ctx->duped = 0; ctx->dir_cookie = 0; + ctx->dup_cookie = 0; ctx->cred = get_rpccred(cred); } else ctx = ERR_PTR(-ENOMEM); @@ -321,6 +323,7 @@ int nfs_readdir_search_for_pos(struct nfs_cache_array *array, nfs_readdir_descri { loff_t diff = desc->file->f_pos - desc->current_index; unsigned int index; + struct nfs_open_dir_context *ctx = desc->file->private_data; if (diff < 0) goto out_eof; @@ -333,6 +336,7 @@ int nfs_readdir_search_for_pos(struct nfs_cache_array *array, nfs_readdir_descri index = (unsigned int)diff; *desc->dir_cookie = array->array[index].cookie; desc->cache_entry_index = index; + ctx->duped = 0; return 0; out_eof: desc->eof = 1; @@ -343,11 +347,18 @@ static int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_descriptor_t *desc) { int i; + loff_t new_pos; int status = -EAGAIN; + struct nfs_open_dir_context *ctx = desc->file->private_data; for (i = 0; i < array->size; i++) { if (array->array[i].cookie == *desc->dir_cookie) { - desc->file->f_pos = desc->current_index + i; + new_pos = desc->current_index + i; + if (new_pos < desc->file->f_pos) { + ctx->dup_cookie = *desc->dir_cookie; + ctx->duped = 1; + } + desc->file->f_pos = new_pos; desc->cache_entry_index = i; return 0; } @@ -732,6 +743,20 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent, int i = 0; int res = 0; struct nfs_cache_array *array = NULL; + struct nfs_open_dir_context *ctx = file->private_data; + + if (ctx->duped != 0 && ctx->dup_cookie == *desc->dir_cookie) { + if (printk_ratelimit()) { + pr_notice("NFS: directory %s/%s contains a readdir loop. " + "Please contact your server vendor. " + "Offending cookie: %llu\n", + file->f_dentry->d_parent->d_name.name, + file->f_dentry->d_name.name, + *desc->dir_cookie); + } + res = -ELOOP; + goto out; + } array = nfs_readdir_get_array(desc->page); if (IS_ERR(array)) { @@ -914,6 +939,7 @@ static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin) if (offset != filp->f_pos) { filp->f_pos = offset; dir_ctx->dir_cookie = 0; + dir_ctx->duped = 0; } out: mutex_unlock(&inode->i_mutex); -- cgit From 465d52437d5ce8d4eb9da0d3e3818b51cff163a1 Mon Sep 17 00:00:00 2001 From: Fred Isaman Date: Wed, 23 Mar 2011 13:27:44 +0000 Subject: NFSv4.1: don't send COMMIT to ds for data sync writes Based on consensus reached in Feb 2011 interim IETF meeting regarding use of LAYOUTCOMMIT, it has been decided that a NFS_DATA_SYNC return from a WRITE to data server should not initiate a COMMIT. Signed-off-by: Fred Isaman Signed-off-by: Trond Myklebust --- fs/nfs/write.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 55a8c3671233..92b4a6614fd3 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -474,7 +474,10 @@ nfs_clear_request_commit(struct nfs_page *req) static inline int nfs_write_need_commit(struct nfs_write_data *data) { - return data->verf.committed != NFS_FILE_SYNC; + if (data->verf.committed == NFS_DATA_SYNC) + return data->lseg == NULL; + else + return data->verf.committed != NFS_FILE_SYNC; } static inline -- cgit From 9ace33cdc6562699a780b4716d9d52c55dd2151a Mon Sep 17 00:00:00 2001 From: Fred Isaman Date: Wed, 23 Mar 2011 13:27:45 +0000 Subject: NFSv4.1: rearrange nfs_commit_rpcsetup Reorder nfs_commit_rpcsetup, preparing for a pnfs entry point. Signed-off-by: Fred Isaman Signed-off-by: Trond Myklebust --- fs/nfs/write.c | 60 ++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 33 insertions(+), 27 deletions(-) (limited to 'fs') diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 92b4a6614fd3..bf672faa4885 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -1293,32 +1293,49 @@ static void nfs_commitdata_release(void *data) nfs_commit_free(wdata); } -/* - * Set up the argument/result storage required for the RPC call. - */ -static int nfs_commit_rpcsetup(struct list_head *head, - struct nfs_write_data *data, - int how) +static int nfs_initiate_commit(struct nfs_write_data *data, struct rpc_clnt *clnt, + const struct rpc_call_ops *call_ops, + int how) { - struct nfs_page *first = nfs_list_entry(head->next); - struct inode *inode = first->wb_context->path.dentry->d_inode; - int priority = flush_task_priority(how); struct rpc_task *task; + int priority = flush_task_priority(how); struct rpc_message msg = { .rpc_argp = &data->args, .rpc_resp = &data->res, - .rpc_cred = first->wb_context->cred, + .rpc_cred = data->cred, }; struct rpc_task_setup task_setup_data = { .task = &data->task, - .rpc_client = NFS_CLIENT(inode), + .rpc_client = clnt, .rpc_message = &msg, - .callback_ops = &nfs_commit_ops, + .callback_ops = call_ops, .callback_data = data, .workqueue = nfsiod_workqueue, .flags = RPC_TASK_ASYNC, .priority = priority, }; + /* Set up the initial task struct. */ + NFS_PROTO(data->inode)->commit_setup(data, &msg); + + dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid); + + task = rpc_run_task(&task_setup_data); + if (IS_ERR(task)) + return PTR_ERR(task); + if (how & FLUSH_SYNC) + rpc_wait_for_completion_task(task); + rpc_put_task(task); + return 0; +} + +/* + * Set up the argument/result storage required for the RPC call. + */ +static void nfs_init_commit(struct nfs_write_data *data, + struct list_head *head) +{ + struct nfs_page *first = nfs_list_entry(head->next); + struct inode *inode = first->wb_context->path.dentry->d_inode; /* Set up the RPC argument and reply structs * NB: take care not to mess about with data->commit et al. */ @@ -1326,7 +1343,8 @@ static int nfs_commit_rpcsetup(struct list_head *head, list_splice_init(head, &data->pages); data->inode = inode; - data->cred = msg.rpc_cred; + data->cred = first->wb_context->cred; + data->mds_ops = &nfs_commit_ops; data->args.fh = NFS_FH(data->inode); /* Note: we always request a commit of the entire inode */ @@ -1337,19 +1355,6 @@ static int nfs_commit_rpcsetup(struct list_head *head, data->res.fattr = &data->fattr; data->res.verf = &data->verf; nfs_fattr_init(&data->fattr); - - /* Set up the initial task struct. */ - NFS_PROTO(inode)->commit_setup(data, &msg); - - dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid); - - task = rpc_run_task(&task_setup_data); - if (IS_ERR(task)) - return PTR_ERR(task); - if (how & FLUSH_SYNC) - rpc_wait_for_completion_task(task); - rpc_put_task(task); - return 0; } /* @@ -1367,7 +1372,8 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how) goto out_bad; /* Set up the argument struct */ - return nfs_commit_rpcsetup(head, data, how); + nfs_init_commit(data, head); + return nfs_initiate_commit(data, NFS_CLIENT(inode), data->mds_ops, how); out_bad: while (!list_empty(head)) { req = nfs_list_entry(head->next); -- cgit From 5f452431e229ea14df61b0ac89eed5881414eef9 Mon Sep 17 00:00:00 2001 From: Fred Isaman Date: Wed, 23 Mar 2011 13:27:46 +0000 Subject: NFSv4.1: add callback to nfs4_commit_done Add a callback that the pnfs layout driver can use to do its own error handling of the data server's COMMIT response. Signed-off-by: Fred Isaman Signed-off-by: Trond Myklebust --- fs/nfs/nfs4proc.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 1d84e7088af9..bcc29bdc9bee 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -3195,12 +3195,9 @@ static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_messag msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE]; } -static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data) +static int nfs4_commit_done_cb(struct rpc_task *task, struct nfs_write_data *data) { struct inode *inode = data->inode; - - if (!nfs4_sequence_done(task, &data->res.seq_res)) - return -EAGAIN; if (nfs4_async_handle_error(task, NFS_SERVER(inode), NULL) == -EAGAIN) { nfs_restart_rpc(task, NFS_SERVER(inode)->nfs_client); @@ -3210,11 +3207,20 @@ static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data) return 0; } +static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data) +{ + if (!nfs4_sequence_done(task, &data->res.seq_res)) + return -EAGAIN; + return data->write_done_cb(task, data); +} + static void nfs4_proc_commit_setup(struct nfs_write_data *data, struct rpc_message *msg) { struct nfs_server *server = NFS_SERVER(data->inode); data->args.bitmask = server->cache_consistency_bitmask; + if (!data->write_done_cb) + data->write_done_cb = nfs4_commit_done_cb; data->res.server = server; msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT]; } -- cgit From 64bfeb49bd1c2351a8415f7fe6b25eef208872a5 Mon Sep 17 00:00:00 2001 From: Fred Isaman Date: Wed, 23 Mar 2011 13:27:47 +0000 Subject: NFSv4.1: pull error handling out of nfs_commit_list Create a separate support function for later use by data server commit code. Signed-off-by: Fred Isaman Signed-off-by: Trond Myklebust --- fs/nfs/write.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'fs') diff --git a/fs/nfs/write.c b/fs/nfs/write.c index bf672faa4885..dbc801810e75 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -1357,6 +1357,21 @@ static void nfs_init_commit(struct nfs_write_data *data, nfs_fattr_init(&data->fattr); } +static void nfs_retry_commit(struct list_head *page_list) +{ + struct nfs_page *req; + + while (!list_empty(page_list)) { + req = nfs_list_entry(page_list->next); + nfs_list_remove_request(req); + nfs_mark_request_commit(req); + dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); + dec_bdi_stat(req->wb_page->mapping->backing_dev_info, + BDI_RECLAIMABLE); + nfs_clear_page_tag_locked(req); + } +} + /* * Commit dirty pages */ @@ -1364,7 +1379,6 @@ static int nfs_commit_list(struct inode *inode, struct list_head *head, int how) { struct nfs_write_data *data; - struct nfs_page *req; data = nfs_commitdata_alloc(); @@ -1375,15 +1389,7 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how) nfs_init_commit(data, head); return nfs_initiate_commit(data, NFS_CLIENT(inode), data->mds_ops, how); out_bad: - while (!list_empty(head)) { - req = nfs_list_entry(head->next); - nfs_list_remove_request(req); - nfs_mark_request_commit(req); - dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); - dec_bdi_stat(req->wb_page->mapping->backing_dev_info, - BDI_RECLAIMABLE); - nfs_clear_page_tag_locked(req); - } + nfs_retry_commit(head); nfs_commit_clear_lock(NFS_I(inode)); return -ENOMEM; } -- cgit From 5917ce8440ba0b3f2adee613b5f1258ac5efff02 Mon Sep 17 00:00:00 2001 From: Fred Isaman Date: Wed, 23 Mar 2011 13:27:48 +0000 Subject: NFSv4.1: pull out code from nfs_commit_release Create a separate support function for later use by data server commit code. Signed-off-by: Fred Isaman Signed-off-by: Trond Myklebust --- fs/nfs/write.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/nfs/write.c b/fs/nfs/write.c index dbc801810e75..f5f005e9db48 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -1409,10 +1409,9 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata) return; } -static void nfs_commit_release(void *calldata) +static void nfs_commit_release_pages(struct nfs_write_data *data) { - struct nfs_write_data *data = calldata; - struct nfs_page *req; + struct nfs_page *req; int status = data->task.tk_status; while (!list_empty(&data->pages)) { @@ -1446,6 +1445,13 @@ static void nfs_commit_release(void *calldata) next: nfs_clear_page_tag_locked(req); } +} + +static void nfs_commit_release(void *calldata) +{ + struct nfs_write_data *data = calldata; + + nfs_commit_release_pages(data); nfs_commit_clear_lock(NFS_I(data->inode)); nfs_commitdata_release(calldata); } -- cgit From c879513e91c9e38957f0d9647d22469f1887e4da Mon Sep 17 00:00:00 2001 From: Fred Isaman Date: Wed, 23 Mar 2011 13:27:49 +0000 Subject: NFSv4.1: shift filelayout_free_lseg Move it up to avoid forward declaration in later patch. Signed-off-by: Fred Isaman Signed-off-by: Trond Myklebust --- fs/nfs/nfs4filelayout.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'fs') diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index 428558464817..9401afd5650e 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c @@ -496,6 +496,16 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo, return 0; } +static void +filelayout_free_lseg(struct pnfs_layout_segment *lseg) +{ + struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg); + + dprintk("--> %s\n", __func__); + nfs4_fl_put_deviceid(fl->dsaddr); + _filelayout_free_lseg(fl); +} + static struct pnfs_layout_segment * filelayout_alloc_lseg(struct pnfs_layout_hdr *layoutid, struct nfs4_layoutget_res *lgr) @@ -517,16 +527,6 @@ filelayout_alloc_lseg(struct pnfs_layout_hdr *layoutid, return &fl->generic_hdr; } -static void -filelayout_free_lseg(struct pnfs_layout_segment *lseg) -{ - struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg); - - dprintk("--> %s\n", __func__); - nfs4_fl_put_deviceid(fl->dsaddr); - _filelayout_free_lseg(fl); -} - /* * filelayout_pg_test(). Called by nfs_can_coalesce_requests() * -- cgit From 425eb736cd905181a4dd4dc8d66342a7c7ab2f27 Mon Sep 17 00:00:00 2001 From: Fred Isaman Date: Wed, 23 Mar 2011 13:27:50 +0000 Subject: NFSv4.1: alloc and free commit_buckets Create a preallocated list header to hold nfs_pages for each non-MDS COMMIT destination. Note this is not necessarily each DS, but is basically each pair. Signed-off-by: Fred Isaman Signed-off-by: Trond Myklebust --- fs/nfs/nfs4filelayout.c | 22 ++++++++++++++++++++++ fs/nfs/nfs4filelayout.h | 2 ++ 2 files changed, 24 insertions(+) (limited to 'fs') diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index 9401afd5650e..03ff80c67c6e 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c @@ -503,6 +503,7 @@ filelayout_free_lseg(struct pnfs_layout_segment *lseg) dprintk("--> %s\n", __func__); nfs4_fl_put_deviceid(fl->dsaddr); + kfree(fl->commit_buckets); _filelayout_free_lseg(fl); } @@ -524,6 +525,27 @@ filelayout_alloc_lseg(struct pnfs_layout_hdr *layoutid, _filelayout_free_lseg(fl); return NULL; } + + /* This assumes there is only one IOMODE_RW lseg. What + * we really want to do is have a layout_hdr level + * dictionary of keys, each + * associated with a struct list_head, populated by calls + * to filelayout_write_pagelist(). + * */ + if ((!fl->commit_through_mds) && (lgr->range.iomode == IOMODE_RW)) { + int i; + int size = (fl->stripe_type == STRIPE_SPARSE) ? + fl->dsaddr->ds_num : fl->dsaddr->stripe_count; + + fl->commit_buckets = kcalloc(size, sizeof(struct list_head), GFP_KERNEL); + if (!fl->commit_buckets) { + filelayout_free_lseg(&fl->generic_hdr); + return NULL; + } + fl->number_of_buckets = size; + for (i = 0; i < size; i++) + INIT_LIST_HEAD(&fl->commit_buckets[i]); + } return &fl->generic_hdr; } diff --git a/fs/nfs/nfs4filelayout.h b/fs/nfs/nfs4filelayout.h index ee0c907742b5..085a354e0f08 100644 --- a/fs/nfs/nfs4filelayout.h +++ b/fs/nfs/nfs4filelayout.h @@ -79,6 +79,8 @@ struct nfs4_filelayout_segment { struct nfs4_file_layout_dsaddr *dsaddr; /* Point to GETDEVINFO data */ unsigned int num_fh; struct nfs_fh **fh_array; + struct list_head *commit_buckets; /* Sort commits to ds */ + int number_of_buckets; }; static inline struct nfs4_filelayout_segment * -- cgit From a861a1e1c398fe34701569fd8ac9225dfe0a9a7e Mon Sep 17 00:00:00 2001 From: Fred Isaman Date: Wed, 23 Mar 2011 13:27:51 +0000 Subject: NFSv4.1: add generic layer hooks for pnfs COMMIT We create three major hooks for the pnfs code. pnfs_mark_request_commit() is called during writeback_done from nfs_mark_request_commit, which gives the driver an opportunity to claim it wants control over commiting a particular req. pnfs_choose_commit_list() is called from nfs_scan_list to choose which list a given req should be added to, based on where we intend to send it for COMMIT. It is up to the driver to have preallocated list headers for each destination it may need. pnfs_commit_list() is how the driver actually takes control, it is used instead of nfs_commit_list(). In order to pass information between the above functions, we create a union in nfs_page to hold a lseg (which is possible because the req is not on any list while in transition), and add some flags to indicate if we need to use the pnfs code. Signed-off-by: Fred Isaman Signed-off-by: Trond Myklebust --- fs/nfs/pagelist.c | 5 ++-- fs/nfs/pnfs.h | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ fs/nfs/write.c | 41 +++++++++++++++++++------------ 3 files changed, 102 insertions(+), 17 deletions(-) (limited to 'fs') diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index fd85618149a1..87a593c2b055 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c @@ -398,6 +398,7 @@ int nfs_scan_list(struct nfs_inode *nfsi, pgoff_t idx_end; int found, i; int res; + struct list_head *list; res = 0; if (npages == 0) @@ -418,10 +419,10 @@ int nfs_scan_list(struct nfs_inode *nfsi, idx_start = req->wb_index + 1; if (nfs_set_page_tag_locked(req)) { kref_get(&req->wb_kref); - nfs_list_remove_request(req); radix_tree_tag_clear(&nfsi->nfs_page_tree, req->wb_index, tag); - nfs_list_add_request(req, dst); + list = pnfs_choose_commit_list(req, dst); + nfs_list_add_request(req, list); res++; if (res == INT_MAX) goto out; diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 6380b9405bcd..5370f1b9aa43 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h @@ -74,6 +74,13 @@ struct pnfs_layoutdriver_type { /* test for nfs page cache coalescing */ int (*pg_test)(struct nfs_pageio_descriptor *, struct nfs_page *, struct nfs_page *); + /* Returns true if layoutdriver wants to divert this request to + * driver's commit routine. + */ + bool (*mark_pnfs_commit)(struct pnfs_layout_segment *lseg); + struct list_head * (*choose_commit_list) (struct nfs_page *req); + int (*commit_pagelist)(struct inode *inode, struct list_head *mds_pages, int how); + /* * Return PNFS_ATTEMPTED to indicate the layout code has attempted * I/O, else return PNFS_NOT_ATTEMPTED to fall back to normal NFS @@ -169,6 +176,51 @@ static inline int pnfs_enabled_sb(struct nfs_server *nfss) return nfss->pnfs_curr_ld != NULL; } +static inline void +pnfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg) +{ + if (lseg) { + struct pnfs_layoutdriver_type *ld; + + ld = NFS_SERVER(req->wb_page->mapping->host)->pnfs_curr_ld; + if (ld->mark_pnfs_commit && ld->mark_pnfs_commit(lseg)) { + set_bit(PG_PNFS_COMMIT, &req->wb_flags); + req->wb_commit_lseg = get_lseg(lseg); + } + } +} + +static inline int +pnfs_commit_list(struct inode *inode, struct list_head *mds_pages, int how) +{ + if (!test_and_clear_bit(NFS_INO_PNFS_COMMIT, &NFS_I(inode)->flags)) + return PNFS_NOT_ATTEMPTED; + return NFS_SERVER(inode)->pnfs_curr_ld->commit_pagelist(inode, mds_pages, how); +} + +static inline struct list_head * +pnfs_choose_commit_list(struct nfs_page *req, struct list_head *mds) +{ + struct list_head *rv; + + if (test_and_clear_bit(PG_PNFS_COMMIT, &req->wb_flags)) { + struct inode *inode = req->wb_commit_lseg->pls_layout->plh_inode; + + set_bit(NFS_INO_PNFS_COMMIT, &NFS_I(inode)->flags); + rv = NFS_SERVER(inode)->pnfs_curr_ld->choose_commit_list(req); + /* matched by ref taken when PG_PNFS_COMMIT is set */ + put_lseg(req->wb_commit_lseg); + } else + rv = mds; + return rv; +} + +static inline void pnfs_clear_request_commit(struct nfs_page *req) +{ + if (test_and_clear_bit(PG_PNFS_COMMIT, &req->wb_flags)) + put_lseg(req->wb_commit_lseg); +} + #else /* CONFIG_NFS_V4_1 */ static inline void pnfs_destroy_all_layouts(struct nfs_client *clp) @@ -252,6 +304,27 @@ pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *ino) pgio->pg_test = NULL; } +static inline void +pnfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg) +{ +} + +static inline int +pnfs_commit_list(struct inode *inode, struct list_head *mds_pages, int how) +{ + return PNFS_NOT_ATTEMPTED; +} + +static inline struct list_head * +pnfs_choose_commit_list(struct nfs_page *req, struct list_head *mds) +{ + return mds; +} + +static inline void pnfs_clear_request_commit(struct nfs_page *req) +{ +} + #endif /* CONFIG_NFS_V4_1 */ #endif /* FS_NFS_PNFS_H */ diff --git a/fs/nfs/write.c b/fs/nfs/write.c index f5f005e9db48..6927a18b6891 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -441,7 +441,7 @@ nfs_mark_request_dirty(struct nfs_page *req) * Add a request to the inode's commit list. */ static void -nfs_mark_request_commit(struct nfs_page *req) +nfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg) { struct inode *inode = req->wb_context->path.dentry->d_inode; struct nfs_inode *nfsi = NFS_I(inode); @@ -453,6 +453,7 @@ nfs_mark_request_commit(struct nfs_page *req) NFS_PAGE_TAG_COMMIT); nfsi->ncommit++; spin_unlock(&inode->i_lock); + pnfs_mark_request_commit(req, lseg); inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); inc_bdi_stat(req->wb_page->mapping->backing_dev_info, BDI_RECLAIMABLE); __mark_inode_dirty(inode, I_DIRTY_DATASYNC); @@ -481,10 +482,11 @@ int nfs_write_need_commit(struct nfs_write_data *data) } static inline -int nfs_reschedule_unstable_write(struct nfs_page *req) +int nfs_reschedule_unstable_write(struct nfs_page *req, + struct nfs_write_data *data) { if (test_and_clear_bit(PG_NEED_COMMIT, &req->wb_flags)) { - nfs_mark_request_commit(req); + nfs_mark_request_commit(req, data->lseg); return 1; } if (test_and_clear_bit(PG_NEED_RESCHED, &req->wb_flags)) { @@ -495,7 +497,7 @@ int nfs_reschedule_unstable_write(struct nfs_page *req) } #else static inline void -nfs_mark_request_commit(struct nfs_page *req) +nfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg) { } @@ -512,7 +514,8 @@ int nfs_write_need_commit(struct nfs_write_data *data) } static inline -int nfs_reschedule_unstable_write(struct nfs_page *req) +int nfs_reschedule_unstable_write(struct nfs_page *req, + struct nfs_write_data *data) { return 0; } @@ -615,9 +618,11 @@ static struct nfs_page *nfs_try_to_update_request(struct inode *inode, } if (nfs_clear_request_commit(req) && - radix_tree_tag_clear(&NFS_I(inode)->nfs_page_tree, - req->wb_index, NFS_PAGE_TAG_COMMIT) != NULL) + radix_tree_tag_clear(&NFS_I(inode)->nfs_page_tree, + req->wb_index, NFS_PAGE_TAG_COMMIT) != NULL) { NFS_I(inode)->ncommit--; + pnfs_clear_request_commit(req); + } /* Okay, the request matches. Update the region */ if (offset < req->wb_offset) { @@ -765,11 +770,12 @@ int nfs_updatepage(struct file *file, struct page *page, return status; } -static void nfs_writepage_release(struct nfs_page *req) +static void nfs_writepage_release(struct nfs_page *req, + struct nfs_write_data *data) { struct page *page = req->wb_page; - if (PageError(req->wb_page) || !nfs_reschedule_unstable_write(req)) + if (PageError(req->wb_page) || !nfs_reschedule_unstable_write(req, data)) nfs_inode_remove_request(req); nfs_clear_page_tag_locked(req); nfs_end_page_writeback(page); @@ -1087,7 +1093,7 @@ static void nfs_writeback_release_partial(void *calldata) out: if (atomic_dec_and_test(&req->wb_complete)) - nfs_writepage_release(req); + nfs_writepage_release(req, data); nfs_writedata_release(calldata); } @@ -1154,7 +1160,7 @@ static void nfs_writeback_release_full(void *calldata) if (nfs_write_need_commit(data)) { memcpy(&req->wb_verf, &data->verf, sizeof(req->wb_verf)); - nfs_mark_request_commit(req); + nfs_mark_request_commit(req, data->lseg); dprintk(" marked for commit\n"); goto next; } @@ -1357,14 +1363,15 @@ static void nfs_init_commit(struct nfs_write_data *data, nfs_fattr_init(&data->fattr); } -static void nfs_retry_commit(struct list_head *page_list) +static void nfs_retry_commit(struct list_head *page_list, + struct pnfs_layout_segment *lseg) { struct nfs_page *req; while (!list_empty(page_list)) { req = nfs_list_entry(page_list->next); nfs_list_remove_request(req); - nfs_mark_request_commit(req); + nfs_mark_request_commit(req, lseg); dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); dec_bdi_stat(req->wb_page->mapping->backing_dev_info, BDI_RECLAIMABLE); @@ -1389,7 +1396,7 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how) nfs_init_commit(data, head); return nfs_initiate_commit(data, NFS_CLIENT(inode), data->mds_ops, how); out_bad: - nfs_retry_commit(head); + nfs_retry_commit(head, NULL); nfs_commit_clear_lock(NFS_I(inode)); return -ENOMEM; } @@ -1477,7 +1484,11 @@ int nfs_commit_inode(struct inode *inode, int how) res = nfs_scan_commit(inode, &head, 0, 0); spin_unlock(&inode->i_lock); if (res) { - int error = nfs_commit_list(inode, &head, how); + int error; + + error = pnfs_commit_list(inode, &head, how); + if (error == PNFS_NOT_ATTEMPTED) + error = nfs_commit_list(inode, &head, how); if (error < 0) return error; if (!may_wait) -- cgit From 988b6dceb0ae6d642587c8594529b94f6be0c5ea Mon Sep 17 00:00:00 2001 From: Fred Isaman Date: Wed, 23 Mar 2011 13:27:52 +0000 Subject: NFSv4.1: remove GETATTR from ds commits Any COMMIT compound directed to a data server needs to have the GETATTR calls suppressed. We here, make sure the field we are testing (data->lseg) is set and refcounted correctly. Signed-off-by: Fred Isaman Signed-off-by: Trond Myklebust --- fs/nfs/nfs4proc.c | 8 ++++++-- fs/nfs/nfs4xdr.c | 8 +++++--- fs/nfs/write.c | 7 +++++-- 3 files changed, 16 insertions(+), 7 deletions(-) (limited to 'fs') diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index bcc29bdc9bee..5d61cccc8d4d 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -3217,8 +3217,12 @@ static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data) static void nfs4_proc_commit_setup(struct nfs_write_data *data, struct rpc_message *msg) { struct nfs_server *server = NFS_SERVER(data->inode); - - data->args.bitmask = server->cache_consistency_bitmask; + + if (data->lseg) { + data->args.bitmask = NULL; + data->res.fattr = NULL; + } else + data->args.bitmask = server->cache_consistency_bitmask; if (!data->write_done_cb) data->write_done_cb = nfs4_commit_done_cb; data->res.server = server; diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 0cf560f77884..07cdf925c524 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -2294,7 +2294,8 @@ static void nfs4_xdr_enc_commit(struct rpc_rqst *req, struct xdr_stream *xdr, encode_sequence(xdr, &args->seq_args, &hdr); encode_putfh(xdr, args->fh, &hdr); encode_commit(xdr, args, &hdr); - encode_getfattr(xdr, args->bitmask, &hdr); + if (args->bitmask) + encode_getfattr(xdr, args->bitmask, &hdr); encode_nops(&hdr); } @@ -5723,8 +5724,9 @@ static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, struct xdr_stream *xdr, status = decode_commit(xdr, res); if (status) goto out; - decode_getfattr(xdr, res->fattr, res->server, - !RPC_IS_ASYNC(rqstp->rq_task)); + if (res->fattr) + decode_getfattr(xdr, res->fattr, res->server, + !RPC_IS_ASYNC(rqstp->rq_task)); out: return status; } diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 6927a18b6891..cae5d160d835 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -1295,6 +1295,7 @@ static void nfs_commitdata_release(void *data) { struct nfs_write_data *wdata = data; + put_lseg(wdata->lseg); put_nfs_open_context(wdata->args.context); nfs_commit_free(wdata); } @@ -1338,7 +1339,8 @@ static int nfs_initiate_commit(struct nfs_write_data *data, struct rpc_clnt *cln * Set up the argument/result storage required for the RPC call. */ static void nfs_init_commit(struct nfs_write_data *data, - struct list_head *head) + struct list_head *head, + struct pnfs_layout_segment *lseg) { struct nfs_page *first = nfs_list_entry(head->next); struct inode *inode = first->wb_context->path.dentry->d_inode; @@ -1350,6 +1352,7 @@ static void nfs_init_commit(struct nfs_write_data *data, data->inode = inode; data->cred = first->wb_context->cred; + data->lseg = lseg; /* reference transferred */ data->mds_ops = &nfs_commit_ops; data->args.fh = NFS_FH(data->inode); @@ -1393,7 +1396,7 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how) goto out_bad; /* Set up the argument struct */ - nfs_init_commit(data, head); + nfs_init_commit(data, head, NULL); return nfs_initiate_commit(data, NFS_CLIENT(inode), data->mds_ops, how); out_bad: nfs_retry_commit(head, NULL); -- cgit From e0c2b3801828aadb65dec9f67f7c6b7a675ad007 Mon Sep 17 00:00:00 2001 From: Fred Isaman Date: Wed, 23 Mar 2011 13:27:53 +0000 Subject: NFSv4.1: filelayout driver specific code for COMMIT Implement all the hooks created in the previous patches. This requires exporting quite a few functions and adding a few structure fields. Signed-off-by: Fred Isaman Signed-off-by: Trond Myklebust --- fs/nfs/inode.c | 1 + fs/nfs/internal.h | 14 +++ fs/nfs/nfs4filelayout.c | 235 ++++++++++++++++++++++++++++++++++++++++++++++++ fs/nfs/pnfs.c | 1 + fs/nfs/write.c | 21 +++-- 5 files changed, 265 insertions(+), 7 deletions(-) (limited to 'fs') diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 477a2e512b39..229e586b1a20 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -1470,6 +1470,7 @@ static inline void nfs4_init_once(struct nfs_inode *nfsi) nfsi->delegation_state = 0; init_rwsem(&nfsi->rwsem); nfsi->layout = NULL; + atomic_set(&nfsi->commits_outstanding, 0); #endif } diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index d1ddc23c404d..708705062216 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -276,11 +276,25 @@ extern int nfs_initiate_read(struct nfs_read_data *data, struct rpc_clnt *clnt, extern void nfs_read_prepare(struct rpc_task *task, void *calldata); /* write.c */ +extern void nfs_commit_free(struct nfs_write_data *p); extern int nfs_initiate_write(struct nfs_write_data *data, struct rpc_clnt *clnt, const struct rpc_call_ops *call_ops, int how); extern void nfs_write_prepare(struct rpc_task *task, void *calldata); +extern int nfs_initiate_commit(struct nfs_write_data *data, + struct rpc_clnt *clnt, + const struct rpc_call_ops *call_ops, + int how); +extern void nfs_init_commit(struct nfs_write_data *data, + struct list_head *head, + struct pnfs_layout_segment *lseg); +void nfs_retry_commit(struct list_head *page_list, + struct pnfs_layout_segment *lseg); +void nfs_commit_clear_lock(struct nfs_inode *nfsi); +void nfs_commitdata_release(void *data); +void nfs_commit_release_pages(struct nfs_write_data *data); + #ifdef CONFIG_MIGRATION extern int nfs_migrate_page(struct address_space *, struct page *, struct page *); diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index 03ff80c67c6e..97e75a22af72 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c @@ -213,6 +213,37 @@ static int filelayout_write_done_cb(struct rpc_task *task, return 0; } +/* Fake up some data that will cause nfs_commit_release to retry the writes. */ +static void prepare_to_resend_writes(struct nfs_write_data *data) +{ + struct nfs_page *first = nfs_list_entry(data->pages.next); + + data->task.tk_status = 0; + memcpy(data->verf.verifier, first->wb_verf.verifier, + sizeof(first->wb_verf.verifier)); + data->verf.verifier[0]++; /* ensure verifier mismatch */ +} + +static int filelayout_commit_done_cb(struct rpc_task *task, + struct nfs_write_data *data) +{ + int reset = 0; + + if (filelayout_async_handle_error(task, data->args.context->state, + data->ds_clp, &reset) == -EAGAIN) { + dprintk("%s calling restart ds_clp %p ds_clp->cl_session %p\n", + __func__, data->ds_clp, data->ds_clp->cl_session); + if (reset) { + prepare_to_resend_writes(data); + filelayout_set_lo_fail(data->lseg); + } else + nfs_restart_rpc(task, data->ds_clp); + return -EAGAIN; + } + + return 0; +} + static void filelayout_write_prepare(struct rpc_task *task, void *data) { struct nfs_write_data *wdata = (struct nfs_write_data *)data; @@ -240,6 +271,16 @@ static void filelayout_write_release(void *data) wdata->mds_ops->rpc_release(data); } +static void filelayout_commit_release(void *data) +{ + struct nfs_write_data *wdata = (struct nfs_write_data *)data; + + nfs_commit_release_pages(wdata); + if (atomic_dec_and_test(&NFS_I(wdata->inode)->commits_outstanding)) + nfs_commit_clear_lock(NFS_I(wdata->inode)); + nfs_commitdata_release(wdata); +} + struct rpc_call_ops filelayout_read_call_ops = { .rpc_call_prepare = filelayout_read_prepare, .rpc_call_done = filelayout_read_call_done, @@ -252,6 +293,12 @@ struct rpc_call_ops filelayout_write_call_ops = { .rpc_release = filelayout_write_release, }; +struct rpc_call_ops filelayout_commit_call_ops = { + .rpc_call_prepare = filelayout_write_prepare, + .rpc_call_done = filelayout_write_call_done, + .rpc_release = filelayout_commit_release, +}; + static enum pnfs_try_status filelayout_read_pagelist(struct nfs_read_data *data) { @@ -574,6 +621,191 @@ filelayout_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, return (p_stripe == r_stripe); } +static bool filelayout_mark_pnfs_commit(struct pnfs_layout_segment *lseg) +{ + return !FILELAYOUT_LSEG(lseg)->commit_through_mds; +} + +static u32 select_bucket_index(struct nfs4_filelayout_segment *fl, u32 j) +{ + if (fl->stripe_type == STRIPE_SPARSE) + return nfs4_fl_calc_ds_index(&fl->generic_hdr, j); + else + return j; +} + +struct list_head *filelayout_choose_commit_list(struct nfs_page *req) +{ + struct pnfs_layout_segment *lseg = req->wb_commit_lseg; + struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg); + u32 i, j; + struct list_head *list; + + /* Note that we are calling nfs4_fl_calc_j_index on each page + * that ends up being committed to a data server. An attractive + * alternative is to add a field to nfs_write_data and nfs_page + * to store the value calculated in filelayout_write_pagelist + * and just use that here. + */ + j = nfs4_fl_calc_j_index(lseg, + (loff_t)req->wb_index << PAGE_CACHE_SHIFT); + i = select_bucket_index(fl, j); + list = &fl->commit_buckets[i]; + if (list_empty(list)) { + /* Non-empty buckets hold a reference on the lseg */ + get_lseg(lseg); + } + return list; +} + +static u32 calc_ds_index_from_commit(struct pnfs_layout_segment *lseg, u32 i) +{ + struct nfs4_filelayout_segment *flseg = FILELAYOUT_LSEG(lseg); + + if (flseg->stripe_type == STRIPE_SPARSE) + return i; + else + return nfs4_fl_calc_ds_index(lseg, i); +} + +static struct nfs_fh * +select_ds_fh_from_commit(struct pnfs_layout_segment *lseg, u32 i) +{ + struct nfs4_filelayout_segment *flseg = FILELAYOUT_LSEG(lseg); + + if (flseg->stripe_type == STRIPE_SPARSE) { + if (flseg->num_fh == 1) + i = 0; + else if (flseg->num_fh == 0) + /* Use the MDS OPEN fh set in nfs_read_rpcsetup */ + return NULL; + } + return flseg->fh_array[i]; +} + +static int filelayout_initiate_commit(struct nfs_write_data *data, int how) +{ + struct pnfs_layout_segment *lseg = data->lseg; + struct nfs4_pnfs_ds *ds; + u32 idx; + struct nfs_fh *fh; + + idx = calc_ds_index_from_commit(lseg, data->ds_commit_index); + ds = nfs4_fl_prepare_ds(lseg, idx); + if (!ds) { + printk(KERN_ERR "%s: prepare_ds failed, use MDS\n", __func__); + set_bit(lo_fail_bit(IOMODE_RW), &lseg->pls_layout->plh_flags); + set_bit(lo_fail_bit(IOMODE_READ), &lseg->pls_layout->plh_flags); + prepare_to_resend_writes(data); + data->mds_ops->rpc_release(data); + return -EAGAIN; + } + dprintk("%s ino %lu, how %d\n", __func__, data->inode->i_ino, how); + data->write_done_cb = filelayout_commit_done_cb; + data->ds_clp = ds->ds_clp; + fh = select_ds_fh_from_commit(lseg, data->ds_commit_index); + if (fh) + data->args.fh = fh; + return nfs_initiate_commit(data, ds->ds_clp->cl_rpcclient, + &filelayout_commit_call_ops, how); +} + +/* + * This is only useful while we are using whole file layouts. + */ +static struct pnfs_layout_segment *find_only_write_lseg(struct inode *inode) +{ + struct pnfs_layout_segment *lseg, *rv = NULL; + + spin_lock(&inode->i_lock); + list_for_each_entry(lseg, &NFS_I(inode)->layout->plh_segs, pls_list) + if (lseg->pls_range.iomode == IOMODE_RW) + rv = get_lseg(lseg); + spin_unlock(&inode->i_lock); + return rv; +} + +static int alloc_ds_commits(struct inode *inode, struct list_head *list) +{ + struct pnfs_layout_segment *lseg; + struct nfs4_filelayout_segment *fl; + struct nfs_write_data *data; + int i, j; + + /* Won't need this when non-whole file layout segments are supported + * instead we will use a pnfs_layout_hdr structure */ + lseg = find_only_write_lseg(inode); + if (!lseg) + return 0; + fl = FILELAYOUT_LSEG(lseg); + for (i = 0; i < fl->number_of_buckets; i++) { + if (list_empty(&fl->commit_buckets[i])) + continue; + data = nfs_commitdata_alloc(); + if (!data) + goto out_bad; + data->ds_commit_index = i; + data->lseg = lseg; + list_add(&data->pages, list); + } + put_lseg(lseg); + return 0; + +out_bad: + for (j = i; j < fl->number_of_buckets; j++) { + if (list_empty(&fl->commit_buckets[i])) + continue; + nfs_retry_commit(&fl->commit_buckets[i], lseg); + put_lseg(lseg); /* associated with emptying bucket */ + } + put_lseg(lseg); + /* Caller will clean up entries put on list */ + return -ENOMEM; +} + +/* This follows nfs_commit_list pretty closely */ +static int +filelayout_commit_pagelist(struct inode *inode, struct list_head *mds_pages, + int how) +{ + struct nfs_write_data *data, *tmp; + LIST_HEAD(list); + + if (!list_empty(mds_pages)) { + data = nfs_commitdata_alloc(); + if (!data) + goto out_bad; + data->lseg = NULL; + list_add(&data->pages, &list); + } + + if (alloc_ds_commits(inode, &list)) + goto out_bad; + + list_for_each_entry_safe(data, tmp, &list, pages) { + list_del_init(&data->pages); + atomic_inc(&NFS_I(inode)->commits_outstanding); + if (!data->lseg) { + nfs_init_commit(data, mds_pages, NULL); + nfs_initiate_commit(data, NFS_CLIENT(inode), + data->mds_ops, how); + } else { + nfs_init_commit(data, &FILELAYOUT_LSEG(data->lseg)->commit_buckets[data->ds_commit_index], data->lseg); + filelayout_initiate_commit(data, how); + } + } + return 0; + out_bad: + list_for_each_entry_safe(data, tmp, &list, pages) { + nfs_retry_commit(&data->pages, data->lseg); + list_del_init(&data->pages); + nfs_commit_free(data); + } + nfs_retry_commit(mds_pages, NULL); + nfs_commit_clear_lock(NFS_I(inode)); + return -ENOMEM; +} + static struct pnfs_layoutdriver_type filelayout_type = { .id = LAYOUT_NFSV4_1_FILES, .name = "LAYOUT_NFSV4_1_FILES", @@ -581,6 +813,9 @@ static struct pnfs_layoutdriver_type filelayout_type = { .alloc_lseg = filelayout_alloc_lseg, .free_lseg = filelayout_free_lseg, .pg_test = filelayout_pg_test, + .mark_pnfs_commit = filelayout_mark_pnfs_commit, + .choose_commit_list = filelayout_choose_commit_list, + .commit_pagelist = filelayout_commit_pagelist, .read_pagelist = filelayout_read_pagelist, .write_pagelist = filelayout_write_pagelist, }; diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index f38813a0a295..c67565965f2a 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -259,6 +259,7 @@ put_lseg(struct pnfs_layout_segment *lseg) pnfs_free_lseg_list(&free_me); } } +EXPORT_SYMBOL_GPL(put_lseg); static bool should_free_lseg(u32 lseg_iomode, u32 recall_iomode) diff --git a/fs/nfs/write.c b/fs/nfs/write.c index cae5d160d835..e7aeda0663c5 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -59,6 +59,7 @@ struct nfs_write_data *nfs_commitdata_alloc(void) } return p; } +EXPORT_SYMBOL_GPL(nfs_commitdata_alloc); void nfs_commit_free(struct nfs_write_data *p) { @@ -66,6 +67,7 @@ void nfs_commit_free(struct nfs_write_data *p) kfree(p->pagevec); mempool_free(p, nfs_commit_mempool); } +EXPORT_SYMBOL_GPL(nfs_commit_free); struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount) { @@ -1283,15 +1285,15 @@ static int nfs_commit_set_lock(struct nfs_inode *nfsi, int may_wait) return (ret < 0) ? ret : 1; } -static void nfs_commit_clear_lock(struct nfs_inode *nfsi) +void nfs_commit_clear_lock(struct nfs_inode *nfsi) { clear_bit(NFS_INO_COMMIT, &nfsi->flags); smp_mb__after_clear_bit(); wake_up_bit(&nfsi->flags, NFS_INO_COMMIT); } +EXPORT_SYMBOL_GPL(nfs_commit_clear_lock); - -static void nfs_commitdata_release(void *data) +void nfs_commitdata_release(void *data) { struct nfs_write_data *wdata = data; @@ -1299,8 +1301,9 @@ static void nfs_commitdata_release(void *data) put_nfs_open_context(wdata->args.context); nfs_commit_free(wdata); } +EXPORT_SYMBOL_GPL(nfs_commitdata_release); -static int nfs_initiate_commit(struct nfs_write_data *data, struct rpc_clnt *clnt, +int nfs_initiate_commit(struct nfs_write_data *data, struct rpc_clnt *clnt, const struct rpc_call_ops *call_ops, int how) { @@ -1334,11 +1337,12 @@ static int nfs_initiate_commit(struct nfs_write_data *data, struct rpc_clnt *cln rpc_put_task(task); return 0; } +EXPORT_SYMBOL_GPL(nfs_initiate_commit); /* * Set up the argument/result storage required for the RPC call. */ -static void nfs_init_commit(struct nfs_write_data *data, +void nfs_init_commit(struct nfs_write_data *data, struct list_head *head, struct pnfs_layout_segment *lseg) { @@ -1365,8 +1369,9 @@ static void nfs_init_commit(struct nfs_write_data *data, data->res.verf = &data->verf; nfs_fattr_init(&data->fattr); } +EXPORT_SYMBOL_GPL(nfs_init_commit); -static void nfs_retry_commit(struct list_head *page_list, +void nfs_retry_commit(struct list_head *page_list, struct pnfs_layout_segment *lseg) { struct nfs_page *req; @@ -1381,6 +1386,7 @@ static void nfs_retry_commit(struct list_head *page_list, nfs_clear_page_tag_locked(req); } } +EXPORT_SYMBOL_GPL(nfs_retry_commit); /* * Commit dirty pages @@ -1419,7 +1425,7 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata) return; } -static void nfs_commit_release_pages(struct nfs_write_data *data) +void nfs_commit_release_pages(struct nfs_write_data *data) { struct nfs_page *req; int status = data->task.tk_status; @@ -1456,6 +1462,7 @@ static void nfs_commit_release_pages(struct nfs_write_data *data) nfs_clear_page_tag_locked(req); } } +EXPORT_SYMBOL_GPL(nfs_commit_release_pages); static void nfs_commit_release(void *calldata) { -- cgit From 863a3c6c686d5773f7192a4818769e15db12ce08 Mon Sep 17 00:00:00 2001 From: Andy Adamson Date: Wed, 23 Mar 2011 13:27:54 +0000 Subject: NFSv4.1: layoutcommit The filelayout driver sends LAYOUTCOMMIT only when COMMIT goes to the data server (as opposed to the MDS) and the data server WRITE is not NFS_FILE_SYNC. Only whole file layout support means that there is only one IOMODE_RW layout segment. Signed-off-by: Andy Adamson Signed-off-by: Alexandros Batsakis Signed-off-by: Boaz Harrosh Signed-off-by: Dean Hildebrand Signed-off-by: Fred Isaman Signed-off-by: Mingyang Guo Signed-off-by: Tao Guo Signed-off-by: Zhang Jingwang Tested-by: Boaz Harrosh Signed-off-by: Benny Halevy Signed-off-by: Fred Isaman Signed-off-by: Trond Myklebust --- fs/nfs/file.c | 3 ++ fs/nfs/nfs4_fs.h | 2 + fs/nfs/nfs4filelayout.c | 18 +++++++ fs/nfs/nfs4proc.c | 94 +++++++++++++++++++++++++++++++++++ fs/nfs/nfs4xdr.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++++ fs/nfs/pnfs.c | 94 +++++++++++++++++++++++++++++++++++ fs/nfs/pnfs.h | 9 +++- fs/nfs/write.c | 15 +++++- 8 files changed, 362 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/nfs/file.c b/fs/nfs/file.c index d85a534b15cd..85cb95de5df5 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -326,6 +326,9 @@ nfs_file_fsync(struct file *file, int datasync) ret = xchg(&ctx->error, 0); if (!ret && status < 0) ret = status; + if (!ret && !datasync) + /* application has asked for meta-data sync */ + ret = pnfs_layoutcommit_inode(inode, 1); return ret; } diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index c64be1cff080..1e612d159b71 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -262,6 +262,8 @@ extern int nfs4_proc_destroy_session(struct nfs4_session *); extern int nfs4_init_session(struct nfs_server *server); extern int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo); +extern int nfs4_proc_layoutcommit(struct nfs4_layoutcommit_data *data, + int sync); static inline bool is_ds_only_client(struct nfs_client *clp) diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index 97e75a22af72..fc1a0e9c1270 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c @@ -153,6 +153,23 @@ static int filelayout_read_done_cb(struct rpc_task *task, return 0; } +/* + * We reference the rpc_cred of the first WRITE that triggers the need for + * a LAYOUTCOMMIT, and use it to send the layoutcommit compound. + * rfc5661 is not clear about which credential should be used. + */ +static void +filelayout_set_layoutcommit(struct nfs_write_data *wdata) +{ + if (FILELAYOUT_LSEG(wdata->lseg)->commit_through_mds || + wdata->res.verf->committed == NFS_FILE_SYNC) + return; + + pnfs_set_layoutcommit(wdata); + dprintk("%s ionde %lu pls_end_pos %lu\n", __func__, wdata->inode->i_ino, + (unsigned long) wdata->lseg->pls_end_pos); +} + /* * Call ops for the async read/write cases * In the case of dense layouts, the offset needs to be reset to its @@ -210,6 +227,7 @@ static int filelayout_write_done_cb(struct rpc_task *task, return -EAGAIN; } + filelayout_set_layoutcommit(data); return 0; } diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 5d61cccc8d4d..6f2f40239d10 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -5616,6 +5616,100 @@ int nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *pdev) } EXPORT_SYMBOL_GPL(nfs4_proc_getdeviceinfo); +static void nfs4_layoutcommit_prepare(struct rpc_task *task, void *calldata) +{ + struct nfs4_layoutcommit_data *data = calldata; + struct nfs_server *server = NFS_SERVER(data->args.inode); + + if (nfs4_setup_sequence(server, &data->args.seq_args, + &data->res.seq_res, 1, task)) + return; + rpc_call_start(task); +} + +static void +nfs4_layoutcommit_done(struct rpc_task *task, void *calldata) +{ + struct nfs4_layoutcommit_data *data = calldata; + struct nfs_server *server = NFS_SERVER(data->args.inode); + + if (!nfs4_sequence_done(task, &data->res.seq_res)) + return; + + switch (task->tk_status) { /* Just ignore these failures */ + case NFS4ERR_DELEG_REVOKED: /* layout was recalled */ + case NFS4ERR_BADIOMODE: /* no IOMODE_RW layout for range */ + case NFS4ERR_BADLAYOUT: /* no layout */ + case NFS4ERR_GRACE: /* loca_recalim always false */ + task->tk_status = 0; + } + + if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) { + nfs_restart_rpc(task, server->nfs_client); + return; + } + + if (task->tk_status == 0) + nfs_post_op_update_inode_force_wcc(data->args.inode, + data->res.fattr); +} + +static void nfs4_layoutcommit_release(void *calldata) +{ + struct nfs4_layoutcommit_data *data = calldata; + + /* Matched by references in pnfs_set_layoutcommit */ + put_lseg(data->lseg); + put_rpccred(data->cred); + kfree(data); +} + +static const struct rpc_call_ops nfs4_layoutcommit_ops = { + .rpc_call_prepare = nfs4_layoutcommit_prepare, + .rpc_call_done = nfs4_layoutcommit_done, + .rpc_release = nfs4_layoutcommit_release, +}; + +int +nfs4_proc_layoutcommit(struct nfs4_layoutcommit_data *data, int sync) +{ + struct rpc_message msg = { + .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTCOMMIT], + .rpc_argp = &data->args, + .rpc_resp = &data->res, + .rpc_cred = data->cred, + }; + struct rpc_task_setup task_setup_data = { + .task = &data->task, + .rpc_client = NFS_CLIENT(data->args.inode), + .rpc_message = &msg, + .callback_ops = &nfs4_layoutcommit_ops, + .callback_data = data, + .flags = RPC_TASK_ASYNC, + }; + struct rpc_task *task; + int status = 0; + + dprintk("NFS: %4d initiating layoutcommit call. sync %d " + "lbw: %llu inode %lu\n", + data->task.tk_pid, sync, + data->args.lastbytewritten, + data->args.inode->i_ino); + + task = rpc_run_task(&task_setup_data); + if (IS_ERR(task)) + return PTR_ERR(task); + if (!sync) + goto out; + status = nfs4_wait_for_completion_rpc_task(task); + if (status != 0) + goto out; + status = task->tk_status; +out: + dprintk("%s: status %d\n", __func__, status); + rpc_put_task(task); + return status; +} #endif /* CONFIG_NFS_V4_1 */ struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = { diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 07cdf925c524..207d399c8dee 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -324,6 +324,18 @@ static int nfs4_stat_to_errno(int); #define decode_layoutget_maxsz (op_decode_hdr_maxsz + 8 + \ decode_stateid_maxsz + \ XDR_QUADLEN(PNFS_LAYOUT_MAXSIZE)) +#define encode_layoutcommit_maxsz (op_encode_hdr_maxsz + \ + 2 /* offset */ + \ + 2 /* length */ + \ + 1 /* reclaim */ + \ + encode_stateid_maxsz + \ + 1 /* new offset (true) */ + \ + 2 /* last byte written */ + \ + 1 /* nt_timechanged (false) */ + \ + 1 /* layoutupdate4 layout type */ + \ + 1 /* NULL filelayout layoutupdate4 payload */) +#define decode_layoutcommit_maxsz (op_decode_hdr_maxsz + 3) + #else /* CONFIG_NFS_V4_1 */ #define encode_sequence_maxsz 0 #define decode_sequence_maxsz 0 @@ -727,6 +739,17 @@ static int nfs4_stat_to_errno(int); decode_sequence_maxsz + \ decode_putfh_maxsz + \ decode_layoutget_maxsz) +#define NFS4_enc_layoutcommit_sz (compound_encode_hdr_maxsz + \ + encode_sequence_maxsz +\ + encode_putfh_maxsz + \ + encode_layoutcommit_maxsz + \ + encode_getattr_maxsz) +#define NFS4_dec_layoutcommit_sz (compound_decode_hdr_maxsz + \ + decode_sequence_maxsz + \ + decode_putfh_maxsz + \ + decode_layoutcommit_maxsz + \ + decode_getattr_maxsz) + const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH + compound_encode_hdr_maxsz + @@ -1816,6 +1839,34 @@ encode_layoutget(struct xdr_stream *xdr, hdr->nops++; hdr->replen += decode_layoutget_maxsz; } + +static int +encode_layoutcommit(struct xdr_stream *xdr, + const struct nfs4_layoutcommit_args *args, + struct compound_hdr *hdr) +{ + __be32 *p; + + dprintk("%s: lbw: %llu type: %d\n", __func__, args->lastbytewritten, + NFS_SERVER(args->inode)->pnfs_curr_ld->id); + + p = reserve_space(xdr, 48 + NFS4_STATEID_SIZE); + *p++ = cpu_to_be32(OP_LAYOUTCOMMIT); + /* Only whole file layouts */ + p = xdr_encode_hyper(p, 0); /* offset */ + p = xdr_encode_hyper(p, NFS4_MAX_UINT64); /* length */ + *p++ = cpu_to_be32(0); /* reclaim */ + p = xdr_encode_opaque_fixed(p, args->stateid.data, NFS4_STATEID_SIZE); + *p++ = cpu_to_be32(1); /* newoffset = TRUE */ + p = xdr_encode_hyper(p, args->lastbytewritten); + *p++ = cpu_to_be32(0); /* Never send time_modify_changed */ + *p++ = cpu_to_be32(NFS_SERVER(args->inode)->pnfs_curr_ld->id);/* type */ + *p++ = cpu_to_be32(0); /* no file layout payload */ + + hdr->nops++; + hdr->replen += decode_layoutcommit_maxsz; + return 0; +} #endif /* CONFIG_NFS_V4_1 */ /* @@ -2607,6 +2658,26 @@ static void nfs4_xdr_enc_layoutget(struct rpc_rqst *req, encode_layoutget(xdr, args, &hdr); encode_nops(&hdr); } + +/* + * Encode LAYOUTCOMMIT request + */ +static int nfs4_xdr_enc_layoutcommit(struct rpc_rqst *req, + struct xdr_stream *xdr, + struct nfs4_layoutcommit_args *args) +{ + struct compound_hdr hdr = { + .minorversion = nfs4_xdr_minorversion(&args->seq_args), + }; + + encode_compound_hdr(xdr, req, &hdr); + encode_sequence(xdr, &args->seq_args, &hdr); + encode_putfh(xdr, NFS_FH(args->inode), &hdr); + encode_layoutcommit(xdr, args, &hdr); + encode_getfattr(xdr, args->bitmask, &hdr); + encode_nops(&hdr); + return 0; +} #endif /* CONFIG_NFS_V4_1 */ static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) @@ -5007,6 +5078,35 @@ out_overflow: print_overflow_msg(__func__, xdr); return -EIO; } + +static int decode_layoutcommit(struct xdr_stream *xdr, + struct rpc_rqst *req, + struct nfs4_layoutcommit_res *res) +{ + __be32 *p; + __u32 sizechanged; + int status; + + status = decode_op_hdr(xdr, OP_LAYOUTCOMMIT); + if (status) + return status; + + p = xdr_inline_decode(xdr, 4); + if (unlikely(!p)) + goto out_overflow; + sizechanged = be32_to_cpup(p); + + if (sizechanged) { + /* throw away new size */ + p = xdr_inline_decode(xdr, 8); + if (unlikely(!p)) + goto out_overflow; + } + return 0; +out_overflow: + print_overflow_msg(__func__, xdr); + return -EIO; +} #endif /* CONFIG_NFS_V4_1 */ /* @@ -6068,6 +6168,34 @@ static int nfs4_xdr_dec_layoutget(struct rpc_rqst *rqstp, out: return status; } + +/* + * Decode LAYOUTCOMMIT response + */ +static int nfs4_xdr_dec_layoutcommit(struct rpc_rqst *rqstp, + struct xdr_stream *xdr, + struct nfs4_layoutcommit_res *res) +{ + struct compound_hdr hdr; + int status; + + status = decode_compound_hdr(xdr, &hdr); + if (status) + goto out; + status = decode_sequence(xdr, &res->seq_res, rqstp); + if (status) + goto out; + status = decode_putfh(xdr); + if (status) + goto out; + status = decode_layoutcommit(xdr, rqstp, res); + if (status) + goto out; + decode_getfattr(xdr, res->fattr, res->server, + !RPC_IS_ASYNC(rqstp->rq_task)); +out: + return status; +} #endif /* CONFIG_NFS_V4_1 */ /** @@ -6269,6 +6397,7 @@ struct rpc_procinfo nfs4_procedures[] = { PROC(RECLAIM_COMPLETE, enc_reclaim_complete, dec_reclaim_complete), PROC(GETDEVICEINFO, enc_getdeviceinfo, dec_getdeviceinfo), PROC(LAYOUTGET, enc_layoutget, dec_layoutget), + PROC(LAYOUTCOMMIT, enc_layoutcommit, dec_layoutcommit), #endif /* CONFIG_NFS_V4_1 */ }; diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index c67565965f2a..2a08ca0dddc1 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -946,3 +946,97 @@ pnfs_try_to_read_data(struct nfs_read_data *rdata, dprintk("%s End (trypnfs:%d)\n", __func__, trypnfs); return trypnfs; } + +/* + * Currently there is only one (whole file) write lseg. + */ +static struct pnfs_layout_segment *pnfs_list_write_lseg(struct inode *inode) +{ + struct pnfs_layout_segment *lseg, *rv = NULL; + + list_for_each_entry(lseg, &NFS_I(inode)->layout->plh_segs, pls_list) + if (lseg->pls_range.iomode == IOMODE_RW) + rv = lseg; + return rv; +} + +void +pnfs_set_layoutcommit(struct nfs_write_data *wdata) +{ + struct nfs_inode *nfsi = NFS_I(wdata->inode); + loff_t end_pos = wdata->args.offset + wdata->res.count; + + spin_lock(&nfsi->vfs_inode.i_lock); + if (!test_and_set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) { + /* references matched in nfs4_layoutcommit_release */ + get_lseg(wdata->lseg); + wdata->lseg->pls_lc_cred = + get_rpccred(wdata->args.context->state->owner->so_cred); + mark_inode_dirty_sync(wdata->inode); + dprintk("%s: Set layoutcommit for inode %lu ", + __func__, wdata->inode->i_ino); + } + if (end_pos > wdata->lseg->pls_end_pos) + wdata->lseg->pls_end_pos = end_pos; + spin_unlock(&nfsi->vfs_inode.i_lock); +} +EXPORT_SYMBOL_GPL(pnfs_set_layoutcommit); + +int +pnfs_layoutcommit_inode(struct inode *inode, int sync) +{ + struct nfs4_layoutcommit_data *data; + struct nfs_inode *nfsi = NFS_I(inode); + struct pnfs_layout_segment *lseg; + struct rpc_cred *cred; + loff_t end_pos; + int status = 0; + + dprintk("--> %s inode %lu\n", __func__, inode->i_ino); + + /* Note kzalloc ensures data->res.seq_res.sr_slot == NULL */ + data = kzalloc(sizeof(*data), GFP_NOFS); + spin_lock(&inode->i_lock); + + if (!test_and_clear_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) { + spin_unlock(&inode->i_lock); + kfree(data); + goto out; + } + /* + * Currently only one (whole file) write lseg which is referenced + * in pnfs_set_layoutcommit and will be found. + */ + lseg = pnfs_list_write_lseg(inode); + + end_pos = lseg->pls_end_pos; + cred = lseg->pls_lc_cred; + lseg->pls_end_pos = 0; + lseg->pls_lc_cred = NULL; + + if (!data) { + put_lseg(lseg); + spin_unlock(&inode->i_lock); + put_rpccred(cred); + status = -ENOMEM; + goto out; + } else { + memcpy(&data->args.stateid.data, nfsi->layout->plh_stateid.data, + sizeof(nfsi->layout->plh_stateid.data)); + } + spin_unlock(&inode->i_lock); + + data->args.inode = inode; + data->lseg = lseg; + data->cred = cred; + nfs_fattr_init(&data->fattr); + data->args.bitmask = NFS_SERVER(inode)->cache_consistency_bitmask; + data->res.fattr = &data->fattr; + data->args.lastbytewritten = end_pos - 1; + data->res.server = NFS_SERVER(inode); + + status = nfs4_proc_layoutcommit(data, sync); +out: + dprintk("<-- %s status %d\n", __func__, status); + return status; +} diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 5370f1b9aa43..0806c77862b6 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h @@ -43,6 +43,8 @@ struct pnfs_layout_segment { atomic_t pls_refcount; unsigned long pls_flags; struct pnfs_layout_hdr *pls_layout; + struct rpc_cred *pls_lc_cred; /* LAYOUTCOMMIT credential */ + loff_t pls_end_pos; /* LAYOUTCOMMIT write end */ }; enum pnfs_try_status { @@ -152,7 +154,8 @@ bool pnfs_roc(struct inode *ino); void pnfs_roc_release(struct inode *ino); void pnfs_roc_set_barrier(struct inode *ino, u32 barrier); bool pnfs_roc_drain(struct inode *ino, u32 *barrier); - +void pnfs_set_layoutcommit(struct nfs_write_data *wdata); +int pnfs_layoutcommit_inode(struct inode *inode, int sync); static inline int lo_fail_bit(u32 iomode) { @@ -325,6 +328,10 @@ static inline void pnfs_clear_request_commit(struct nfs_page *req) { } +static inline int pnfs_layoutcommit_inode(struct inode *inode, int sync) +{ + return 0; +} #endif /* CONFIG_NFS_V4_1 */ #endif /* FS_NFS_PNFS_H */ diff --git a/fs/nfs/write.c b/fs/nfs/write.c index e7aeda0663c5..a03c11f9081e 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -1562,7 +1562,20 @@ static int nfs_commit_unstable_pages(struct inode *inode, struct writeback_contr int nfs_write_inode(struct inode *inode, struct writeback_control *wbc) { - return nfs_commit_unstable_pages(inode, wbc); + int ret; + + ret = nfs_commit_unstable_pages(inode, wbc); + if (ret >= 0 && test_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags)) { + int status, sync = wbc->sync_mode; + + if (wbc->nonblocking || wbc->for_background) + sync = 0; + + status = pnfs_layoutcommit_inode(inode, sync); + if (status < 0) + return status; + } + return ret; } /* -- cgit From cccb4d063b263ac0713ab27d98460fda3b4f83ff Mon Sep 17 00:00:00 2001 From: Fred Isaman Date: Wed, 23 Mar 2011 13:27:55 +0000 Subject: NFSv4.1 remove temp code that prevented ds commits Now that all the infrastructure is in place, we will do the right thing if we remove this special casing. Signed-off-by: Fred Isaman Signed-off-by: Trond Myklebust --- fs/nfs/nfs4filelayout.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'fs') diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index fc1a0e9c1270..ffb54a082f3a 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c @@ -385,10 +385,6 @@ filelayout_write_pagelist(struct nfs_write_data *data, int sync) data->inode->i_ino, sync, (size_t) data->args.count, offset, ntohl(ds->ds_ip_addr), ntohs(ds->ds_port)); - /* We can't handle commit to ds yet */ - if (!FILELAYOUT_LSEG(lseg)->commit_through_mds) - data->args.stable = NFS_FILE_SYNC; - data->write_done_cb = filelayout_write_done_cb; data->ds_clp = ds->ds_clp; fh = nfs4_fl_select_ds_fh(lseg, j); -- cgit From 0ba0851714beebb800992e5105a79dc3a4c504b0 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Wed, 23 Mar 2011 15:48:11 -0400 Subject: ext4: fix a BUG in mb_mark_used during trim. In a bs=4096 volume, if we call FITRIM with the following parameter as fstrim_range(start = 102400, len = 134144000, minlen = 10240), we will trigger this BUG_ON: BUG_ON(start + len > (e4b->bd_sb->s_blocksize << 3)); Mar 4 00:55:52 boyu-tm kernel: ------------[ cut here ]------------ Mar 4 00:55:52 boyu-tm kernel: kernel BUG at fs/ext4/mballoc.c:1506! Mar 4 01:21:09 boyu-tm kernel: Code: d4 00 00 00 00 49 89 fe 8b 56 0c 44 8b 7e 04 89 55 c4 48 8b 4f 28 89 d6 44 01 fe 48 63 d6 48 8b 41 18 48 c1 e0 03 48 39 c2 76 04 <0f> 0b eb fe 48 8b 55 b0 8b 47 34 3b 42 08 74 04 0f 0b eb fe 48 Mar 4 01:21:09 boyu-tm kernel: RIP [] mb_mark_used+0x47/0x26c [ext4] Mar 4 01:21:09 boyu-tm kernel: RSP Mar 4 01:21:09 boyu-tm kernel: ---[ end trace 9f461696f6a9dcf2 ]--- Fix this bug by doing the accounting correctly. Cc: Lukas Czerner Signed-off-by: Tao Ma Signed-off-by: "Theodore Ts'o" --- fs/ext4/mballoc.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index cdc84953f1d4..a5837a837a8b 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -4870,10 +4870,15 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range) break; } - if (len >= EXT4_BLOCKS_PER_GROUP(sb)) - len -= (EXT4_BLOCKS_PER_GROUP(sb) - first_block); - else + /* + * For all the groups except the last one, last block will + * always be EXT4_BLOCKS_PER_GROUP(sb), so we only need to + * change it for the last group in which case start + + * len < EXT4_BLOCKS_PER_GROUP(sb). + */ + if (first_block + len < EXT4_BLOCKS_PER_GROUP(sb)) last_block = first_block + len; + len -= last_block - first_block; if (e4b.bd_info->bb_free >= minlen) { cnt = ext4_trim_all_free(sb, &e4b, first_block, -- cgit From 26ec3c646e75ce7a69fda429d68fcbdcd5eacc62 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 15 Feb 2011 21:24:05 -0500 Subject: make sessionid permissions in /proc/*/task/* match those in /proc/* Signed-off-by: Al Viro --- fs/proc/base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/proc/base.c b/fs/proc/base.c index d49c4b5d2c3e..b77236de6d8f 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -3161,7 +3161,7 @@ static const struct pid_entry tid_base_stuff[] = { REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations), #ifdef CONFIG_AUDITSYSCALL REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations), - REG("sessionid", S_IRUSR, proc_sessionid_operations), + REG("sessionid", S_IRUGO, proc_sessionid_operations), #endif #ifdef CONFIG_FAULT_INJECTION REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations), -- cgit From ca6b0bf0e086513b9ee5efc0aa5770ecb57778af Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 15 Feb 2011 22:04:37 -0500 Subject: pagemap: close races with suid execve just use mm_for_maps() Signed-off-by: Al Viro --- fs/proc/base.c | 4 ++-- fs/proc/task_mmu.c | 7 ++----- 2 files changed, 4 insertions(+), 7 deletions(-) (limited to 'fs') diff --git a/fs/proc/base.c b/fs/proc/base.c index b77236de6d8f..df73573e12c9 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -2797,7 +2797,7 @@ static const struct pid_entry tgid_base_stuff[] = { #ifdef CONFIG_PROC_PAGE_MONITOR REG("clear_refs", S_IWUSR, proc_clear_refs_operations), REG("smaps", S_IRUGO, proc_smaps_operations), - REG("pagemap", S_IRUSR, proc_pagemap_operations), + REG("pagemap", S_IRUGO, proc_pagemap_operations), #endif #ifdef CONFIG_SECURITY DIR("attr", S_IRUGO|S_IXUGO, proc_attr_dir_inode_operations, proc_attr_dir_operations), @@ -3133,7 +3133,7 @@ static const struct pid_entry tid_base_stuff[] = { #ifdef CONFIG_PROC_PAGE_MONITOR REG("clear_refs", S_IWUSR, proc_clear_refs_operations), REG("smaps", S_IRUGO, proc_smaps_operations), - REG("pagemap", S_IRUSR, proc_pagemap_operations), + REG("pagemap", S_IRUGO, proc_pagemap_operations), #endif #ifdef CONFIG_SECURITY DIR("attr", S_IRUGO|S_IXUGO, proc_attr_dir_inode_operations, proc_attr_dir_operations), diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 60b914860f81..c966413c139b 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -729,7 +729,8 @@ static ssize_t pagemap_read(struct file *file, char __user *buf, goto out; ret = -EACCES; - if (!ptrace_may_access(task, PTRACE_MODE_READ)) + mm = mm_for_maps(task); + if (!mm) goto out_task; ret = -EINVAL; @@ -742,10 +743,6 @@ static ssize_t pagemap_read(struct file *file, char __user *buf, if (!count) goto out_task; - mm = get_task_mm(task); - if (!mm) - goto out_task; - pm.len = PM_ENTRY_BYTES * (PAGEMAP_WALK_SIZE >> PAGE_SHIFT); pm.buffer = kmalloc(pm.len, GFP_TEMPORARY); ret = -ENOMEM; -- cgit From ec6fd8a4355cda81cd9f06bebc048e83eb514ac7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 15 Feb 2011 22:22:54 -0500 Subject: report errors in /proc/*/*map* sanely Signed-off-by: Al Viro --- fs/proc/base.c | 8 +++++--- fs/proc/task_mmu.c | 10 +++++----- fs/proc/task_nommu.c | 6 +++--- 3 files changed, 13 insertions(+), 11 deletions(-) (limited to 'fs') diff --git a/fs/proc/base.c b/fs/proc/base.c index df73573e12c9..c28281102082 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -225,15 +225,17 @@ static int check_mem_permission(struct task_struct *task) struct mm_struct *mm_for_maps(struct task_struct *task) { struct mm_struct *mm; + int err; - if (mutex_lock_killable(&task->signal->cred_guard_mutex)) - return NULL; + err = mutex_lock_killable(&task->signal->cred_guard_mutex); + if (err) + return ERR_PTR(err); mm = get_task_mm(task); if (mm && mm != current->mm && !ptrace_may_access(task, PTRACE_MODE_READ)) { mmput(mm); - mm = NULL; + mm = ERR_PTR(-EACCES); } mutex_unlock(&task->signal->cred_guard_mutex); diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index c966413c139b..8fed0f88fbf7 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -119,11 +119,11 @@ static void *m_start(struct seq_file *m, loff_t *pos) priv->task = get_pid_task(priv->pid, PIDTYPE_PID); if (!priv->task) - return NULL; + return ERR_PTR(-ESRCH); mm = mm_for_maps(priv->task); - if (!mm) - return NULL; + if (!mm || IS_ERR(mm)) + return mm; down_read(&mm->mmap_sem); tail_vma = get_gate_vma(priv->task); @@ -728,9 +728,9 @@ static ssize_t pagemap_read(struct file *file, char __user *buf, if (!task) goto out; - ret = -EACCES; mm = mm_for_maps(task); - if (!mm) + ret = PTR_ERR(mm); + if (!mm || IS_ERR(mm)) goto out_task; ret = -EINVAL; diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c index b535d3e5d5f1..980de547c070 100644 --- a/fs/proc/task_nommu.c +++ b/fs/proc/task_nommu.c @@ -199,13 +199,13 @@ static void *m_start(struct seq_file *m, loff_t *pos) /* pin the task and mm whilst we play with them */ priv->task = get_pid_task(priv->pid, PIDTYPE_PID); if (!priv->task) - return NULL; + return ERR_PTR(-ESRCH); mm = mm_for_maps(priv->task); - if (!mm) { + if (!mm || IS_ERR(mm)) { put_task_struct(priv->task); priv->task = NULL; - return NULL; + return mm; } down_read(&mm->mmap_sem); -- cgit From d6f64b89d7ff22ce05896ab4a93a653e8d0b123d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 15 Feb 2011 22:26:01 -0500 Subject: close race in /proc/*/environ Switch to mm_for_maps(). Maybe we ought to make it r--r--r--, since we do checks on IO anyway... Signed-off-by: Al Viro --- fs/proc/base.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'fs') diff --git a/fs/proc/base.c b/fs/proc/base.c index c28281102082..fc471b8766d1 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -919,20 +919,18 @@ static ssize_t environ_read(struct file *file, char __user *buf, if (!task) goto out_no_task; - if (!ptrace_may_access(task, PTRACE_MODE_READ)) - goto out; - ret = -ENOMEM; page = (char *)__get_free_page(GFP_TEMPORARY); if (!page) goto out; - ret = 0; - mm = get_task_mm(task); - if (!mm) + mm = mm_for_maps(task); + ret = PTR_ERR(mm); + if (!mm || IS_ERR(mm)) goto out_free; + ret = 0; while (count > 0) { int this_len, retval, max_len; -- cgit From 2fadaef41283aad7100fa73f01998cddaca25833 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 15 Feb 2011 22:52:11 -0500 Subject: auxv: require the target to be tracable (or yourself) same as for environ, except that we didn't do any checks to prevent access after suid execve Signed-off-by: Al Viro --- fs/proc/base.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/proc/base.c b/fs/proc/base.c index fc471b8766d1..e94b58b496f1 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -281,9 +281,9 @@ out: static int proc_pid_auxv(struct task_struct *task, char *buffer) { - int res = 0; - struct mm_struct *mm = get_task_mm(task); - if (mm) { + struct mm_struct *mm = mm_for_maps(task); + int res = PTR_ERR(mm); + if (mm && !IS_ERR(mm)) { unsigned int nwords = 0; do { nwords += 2; -- cgit From 31db58b3ab432f72ea76be58b12e6ffaf627d5db Mon Sep 17 00:00:00 2001 From: Stephen Wilson Date: Sun, 13 Mar 2011 15:49:15 -0400 Subject: mm: arch: make get_gate_vma take an mm_struct instead of a task_struct Morally, the presence of a gate vma is more an attribute of a particular mm than a particular task. Moreover, dropping the dependency on task_struct will help make both existing and future operations on mm's more flexible and convenient. Signed-off-by: Stephen Wilson Reviewed-by: Michel Lespinasse Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Signed-off-by: Al Viro --- fs/binfmt_elf.c | 2 +- fs/proc/task_mmu.c | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index d5b640ba6cb1..bbabdcce1179 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -1906,7 +1906,7 @@ static int elf_core_dump(struct coredump_params *cprm) segs = current->mm->map_count; segs += elf_core_extra_phdrs(); - gate_vma = get_gate_vma(current); + gate_vma = get_gate_vma(current->mm); if (gate_vma != NULL) segs++; diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 8fed0f88fbf7..e73314afc535 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -126,7 +126,7 @@ static void *m_start(struct seq_file *m, loff_t *pos) return mm; down_read(&mm->mmap_sem); - tail_vma = get_gate_vma(priv->task); + tail_vma = get_gate_vma(priv->task->mm); priv->tail_vma = tail_vma; /* Start with last addr hint */ @@ -277,7 +277,8 @@ static int show_map(struct seq_file *m, void *v) show_map_vma(m, vma); if (m->count < m->size) /* vma is copied successfully */ - m->version = (vma != get_gate_vma(task))? vma->vm_start: 0; + m->version = (vma != get_gate_vma(task->mm)) + ? vma->vm_start : 0; return 0; } @@ -436,7 +437,8 @@ static int show_smap(struct seq_file *m, void *v) (unsigned long)(mss.pss >> (10 + PSS_SHIFT)) : 0); if (m->count < m->size) /* vma is copied successfully */ - m->version = (vma != get_gate_vma(task)) ? vma->vm_start : 0; + m->version = (vma != get_gate_vma(task->mm)) + ? vma->vm_start : 0; return 0; } -- cgit From 26947f8c8f9598209001cdcd31bb2162a2e54691 Mon Sep 17 00:00:00 2001 From: Stephen Wilson Date: Sun, 13 Mar 2011 15:49:21 -0400 Subject: proc: disable mem_write after exec This change makes mem_write() observe the same constraints as mem_read(). This is particularly important for mem_write as an accidental leak of the fd across an exec could result in arbitrary modification of the target process' memory. IOW, /proc/pid/mem is implicitly close-on-exec. Signed-off-by: Stephen Wilson Signed-off-by: Al Viro --- fs/proc/base.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'fs') diff --git a/fs/proc/base.c b/fs/proc/base.c index e94b58b496f1..9af49a3984f1 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -850,6 +850,10 @@ static ssize_t mem_write(struct file * file, const char __user *buf, if (check_mem_permission(task)) goto out; + copied = -EIO; + if (file->private_data != (void *)((long)current->self_exec_id)) + goto out; + copied = -ENOMEM; page = (char *)__get_free_page(GFP_TEMPORARY); if (!page) -- cgit From 18f661bcf898742212182d75f22f05b048cc04bb Mon Sep 17 00:00:00 2001 From: Stephen Wilson Date: Sun, 13 Mar 2011 15:49:22 -0400 Subject: proc: hold cred_guard_mutex in check_mem_permission() Avoid a potential race when task exec's and we get a new ->mm but check against the old credentials in ptrace_may_access(). Holding of the mutex is implemented by factoring out the body of the code into a helper function __check_mem_permission(). Performing this factorization now simplifies upcoming changes and minimizes churn in the diff's. Signed-off-by: Stephen Wilson Signed-off-by: Al Viro --- fs/proc/base.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/proc/base.c b/fs/proc/base.c index 9af49a3984f1..013f116b3223 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -191,10 +191,7 @@ static int proc_root_link(struct inode *inode, struct path *path) return result; } -/* - * Return zero if current may access user memory in @task, -error if not. - */ -static int check_mem_permission(struct task_struct *task) +static int __check_mem_permission(struct task_struct *task) { /* * A task can always look at itself, in case it chooses @@ -222,6 +219,27 @@ static int check_mem_permission(struct task_struct *task) return -EPERM; } +/* + * Return zero if current may access user memory in @task, -error if not. + */ +static int check_mem_permission(struct task_struct *task) +{ + int err; + + /* + * Avoid racing if task exec's as we might get a new mm but validate + * against old credentials. + */ + err = mutex_lock_killable(&task->signal->cred_guard_mutex); + if (err) + return err; + + err = __check_mem_permission(task); + mutex_unlock(&task->signal->cred_guard_mutex); + + return err; +} + struct mm_struct *mm_for_maps(struct task_struct *task) { struct mm_struct *mm; -- cgit From 8b0db9db19858b08c46a84540acfd35f6e6487b8 Mon Sep 17 00:00:00 2001 From: Stephen Wilson Date: Sun, 13 Mar 2011 15:49:23 -0400 Subject: proc: make check_mem_permission() return an mm_struct on success This change allows us to take advantage of access_remote_vm(), which in turn eliminates a security issue with the mem_write() implementation. The previous implementation of mem_write() was insecure since the target task could exec a setuid-root binary between the permission check and the actual write. Holding a reference to the target mm_struct eliminates this vulnerability. Signed-off-by: Stephen Wilson Signed-off-by: Al Viro --- fs/proc/base.c | 58 ++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 34 insertions(+), 24 deletions(-) (limited to 'fs') diff --git a/fs/proc/base.c b/fs/proc/base.c index 013f116b3223..e34c3c33b2de 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -191,14 +191,20 @@ static int proc_root_link(struct inode *inode, struct path *path) return result; } -static int __check_mem_permission(struct task_struct *task) +static struct mm_struct *__check_mem_permission(struct task_struct *task) { + struct mm_struct *mm; + + mm = get_task_mm(task); + if (!mm) + return ERR_PTR(-EINVAL); + /* * A task can always look at itself, in case it chooses * to use system calls instead of load instructions. */ if (task == current) - return 0; + return mm; /* * If current is actively ptrace'ing, and would also be @@ -210,20 +216,23 @@ static int __check_mem_permission(struct task_struct *task) match = (tracehook_tracer_task(task) == current); rcu_read_unlock(); if (match && ptrace_may_access(task, PTRACE_MODE_ATTACH)) - return 0; + return mm; } /* * Noone else is allowed. */ - return -EPERM; + mmput(mm); + return ERR_PTR(-EPERM); } /* - * Return zero if current may access user memory in @task, -error if not. + * If current may access user memory in @task return a reference to the + * corresponding mm, otherwise ERR_PTR. */ -static int check_mem_permission(struct task_struct *task) +static struct mm_struct *check_mem_permission(struct task_struct *task) { + struct mm_struct *mm; int err; /* @@ -232,12 +241,12 @@ static int check_mem_permission(struct task_struct *task) */ err = mutex_lock_killable(&task->signal->cred_guard_mutex); if (err) - return err; + return ERR_PTR(err); - err = __check_mem_permission(task); + mm = __check_mem_permission(task); mutex_unlock(&task->signal->cred_guard_mutex); - return err; + return mm; } struct mm_struct *mm_for_maps(struct task_struct *task) @@ -795,18 +804,14 @@ static ssize_t mem_read(struct file * file, char __user * buf, if (!task) goto out_no_task; - if (check_mem_permission(task)) - goto out; - ret = -ENOMEM; page = (char *)__get_free_page(GFP_TEMPORARY); if (!page) goto out; - ret = 0; - - mm = get_task_mm(task); - if (!mm) + mm = check_mem_permission(task); + ret = PTR_ERR(mm); + if (IS_ERR(mm)) goto out_free; ret = -EIO; @@ -820,8 +825,8 @@ static ssize_t mem_read(struct file * file, char __user * buf, int this_len, retval; this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count; - retval = access_process_vm(task, src, page, this_len, 0); - if (!retval || check_mem_permission(task)) { + retval = access_remote_vm(mm, src, page, this_len, 0); + if (!retval) { if (!ret) ret = -EIO; break; @@ -860,22 +865,25 @@ static ssize_t mem_write(struct file * file, const char __user *buf, char *page; struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode); unsigned long dst = *ppos; + struct mm_struct *mm; copied = -ESRCH; if (!task) goto out_no_task; - if (check_mem_permission(task)) - goto out; + mm = check_mem_permission(task); + copied = PTR_ERR(mm); + if (IS_ERR(mm)) + goto out_task; copied = -EIO; if (file->private_data != (void *)((long)current->self_exec_id)) - goto out; + goto out_mm; copied = -ENOMEM; page = (char *)__get_free_page(GFP_TEMPORARY); if (!page) - goto out; + goto out_mm; copied = 0; while (count > 0) { @@ -886,7 +894,7 @@ static ssize_t mem_write(struct file * file, const char __user *buf, copied = -EFAULT; break; } - retval = access_process_vm(task, dst, page, this_len, 1); + retval = access_remote_vm(mm, dst, page, this_len, 1); if (!retval) { if (!copied) copied = -EIO; @@ -899,7 +907,9 @@ static ssize_t mem_write(struct file * file, const char __user *buf, } *ppos = dst; free_page((unsigned long) page); -out: +out_mm: + mmput(mm); +out_task: put_task_struct(task); out_no_task: return copied; -- cgit From 198214a7ee50375fa71a65e518341980cfd4b2f0 Mon Sep 17 00:00:00 2001 From: Stephen Wilson Date: Sun, 13 Mar 2011 15:49:24 -0400 Subject: proc: enable writing to /proc/pid/mem With recent changes there is no longer a security hazard with writing to /proc/pid/mem. Remove the #ifdef. Signed-off-by: Stephen Wilson Signed-off-by: Al Viro --- fs/proc/base.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'fs') diff --git a/fs/proc/base.c b/fs/proc/base.c index e34c3c33b2de..bc15df390ec4 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -854,10 +854,6 @@ out_no_task: return ret; } -#define mem_write NULL - -#ifndef mem_write -/* This is a security hazard */ static ssize_t mem_write(struct file * file, const char __user *buf, size_t count, loff_t *ppos) { @@ -914,7 +910,6 @@ out_task: out_no_task: return copied; } -#endif loff_t mem_lseek(struct file *file, loff_t offset, int orig) { -- cgit From a9712bc12c40c172e393f85a9b2ba8db4bf59509 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 23 Mar 2011 15:52:50 -0400 Subject: deal with races in /proc/*/{syscall,stack,personality} All of those are rw-r--r-- and all are broken for suid - if you open a file before the target does suid-root exec, you'll be still able to access it. For personality it's not a big deal, but for syscall and stack it's a real problem. Fix: check that task is tracable for you at the time of read(). Signed-off-by: Al Viro --- fs/proc/base.c | 69 ++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 19 deletions(-) (limited to 'fs') diff --git a/fs/proc/base.c b/fs/proc/base.c index bc15df390ec4..7d5bb8b9a4ff 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -347,6 +347,23 @@ static int proc_pid_wchan(struct task_struct *task, char *buffer) } #endif /* CONFIG_KALLSYMS */ +static int lock_trace(struct task_struct *task) +{ + int err = mutex_lock_killable(&task->signal->cred_guard_mutex); + if (err) + return err; + if (!ptrace_may_access(task, PTRACE_MODE_ATTACH)) { + mutex_unlock(&task->signal->cred_guard_mutex); + return -EPERM; + } + return 0; +} + +static void unlock_trace(struct task_struct *task) +{ + mutex_unlock(&task->signal->cred_guard_mutex); +} + #ifdef CONFIG_STACKTRACE #define MAX_STACK_TRACE_DEPTH 64 @@ -356,6 +373,7 @@ static int proc_pid_stack(struct seq_file *m, struct pid_namespace *ns, { struct stack_trace trace; unsigned long *entries; + int err; int i; entries = kmalloc(MAX_STACK_TRACE_DEPTH * sizeof(*entries), GFP_KERNEL); @@ -366,15 +384,20 @@ static int proc_pid_stack(struct seq_file *m, struct pid_namespace *ns, trace.max_entries = MAX_STACK_TRACE_DEPTH; trace.entries = entries; trace.skip = 0; - save_stack_trace_tsk(task, &trace); - for (i = 0; i < trace.nr_entries; i++) { - seq_printf(m, "[<%p>] %pS\n", - (void *)entries[i], (void *)entries[i]); + err = lock_trace(task); + if (!err) { + save_stack_trace_tsk(task, &trace); + + for (i = 0; i < trace.nr_entries; i++) { + seq_printf(m, "[<%p>] %pS\n", + (void *)entries[i], (void *)entries[i]); + } + unlock_trace(task); } kfree(entries); - return 0; + return err; } #endif @@ -537,18 +560,22 @@ static int proc_pid_syscall(struct task_struct *task, char *buffer) { long nr; unsigned long args[6], sp, pc; + int res = lock_trace(task); + if (res) + return res; if (task_current_syscall(task, &nr, args, 6, &sp, &pc)) - return sprintf(buffer, "running\n"); - - if (nr < 0) - return sprintf(buffer, "%ld 0x%lx 0x%lx\n", nr, sp, pc); - - return sprintf(buffer, + res = sprintf(buffer, "running\n"); + else if (nr < 0) + res = sprintf(buffer, "%ld 0x%lx 0x%lx\n", nr, sp, pc); + else + res = sprintf(buffer, "%ld 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n", nr, args[0], args[1], args[2], args[3], args[4], args[5], sp, pc); + unlock_trace(task); + return res; } #endif /* CONFIG_HAVE_ARCH_TRACEHOOK */ @@ -2775,8 +2802,12 @@ static int proc_tgid_io_accounting(struct task_struct *task, char *buffer) static int proc_pid_personality(struct seq_file *m, struct pid_namespace *ns, struct pid *pid, struct task_struct *task) { - seq_printf(m, "%08x\n", task->personality); - return 0; + int err = lock_trace(task); + if (!err) { + seq_printf(m, "%08x\n", task->personality); + unlock_trace(task); + } + return err; } /* @@ -2795,7 +2826,7 @@ static const struct pid_entry tgid_base_stuff[] = { REG("environ", S_IRUSR, proc_environ_operations), INF("auxv", S_IRUSR, proc_pid_auxv), ONE("status", S_IRUGO, proc_pid_status), - ONE("personality", S_IRUSR, proc_pid_personality), + ONE("personality", S_IRUGO, proc_pid_personality), INF("limits", S_IRUGO, proc_pid_limits), #ifdef CONFIG_SCHED_DEBUG REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations), @@ -2805,7 +2836,7 @@ static const struct pid_entry tgid_base_stuff[] = { #endif REG("comm", S_IRUGO|S_IWUSR, proc_pid_set_comm_operations), #ifdef CONFIG_HAVE_ARCH_TRACEHOOK - INF("syscall", S_IRUSR, proc_pid_syscall), + INF("syscall", S_IRUGO, proc_pid_syscall), #endif INF("cmdline", S_IRUGO, proc_pid_cmdline), ONE("stat", S_IRUGO, proc_tgid_stat), @@ -2833,7 +2864,7 @@ static const struct pid_entry tgid_base_stuff[] = { INF("wchan", S_IRUGO, proc_pid_wchan), #endif #ifdef CONFIG_STACKTRACE - ONE("stack", S_IRUSR, proc_pid_stack), + ONE("stack", S_IRUGO, proc_pid_stack), #endif #ifdef CONFIG_SCHEDSTATS INF("schedstat", S_IRUGO, proc_pid_schedstat), @@ -3135,14 +3166,14 @@ static const struct pid_entry tid_base_stuff[] = { REG("environ", S_IRUSR, proc_environ_operations), INF("auxv", S_IRUSR, proc_pid_auxv), ONE("status", S_IRUGO, proc_pid_status), - ONE("personality", S_IRUSR, proc_pid_personality), + ONE("personality", S_IRUGO, proc_pid_personality), INF("limits", S_IRUGO, proc_pid_limits), #ifdef CONFIG_SCHED_DEBUG REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations), #endif REG("comm", S_IRUGO|S_IWUSR, proc_pid_set_comm_operations), #ifdef CONFIG_HAVE_ARCH_TRACEHOOK - INF("syscall", S_IRUSR, proc_pid_syscall), + INF("syscall", S_IRUGO, proc_pid_syscall), #endif INF("cmdline", S_IRUGO, proc_pid_cmdline), ONE("stat", S_IRUGO, proc_tid_stat), @@ -3169,7 +3200,7 @@ static const struct pid_entry tid_base_stuff[] = { INF("wchan", S_IRUGO, proc_pid_wchan), #endif #ifdef CONFIG_STACKTRACE - ONE("stack", S_IRUSR, proc_pid_stack), + ONE("stack", S_IRUGO, proc_pid_stack), #endif #ifdef CONFIG_SCHEDSTATS INF("schedstat", S_IRUGO, proc_pid_schedstat), -- cgit From 135a9fcf45f8d41b4ab008114792f4f6c6572675 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 23 Mar 2011 16:41:43 -0700 Subject: fs/adfs/adfs.h: fix unsigned comparison fs/adfs/adfs.h: In function 'append_filetype_suffix': fs/adfs/adfs.h:115: warning: comparison is always false due to limited range of data type Reported-by: Geert Uytterhoeven Cc: Stuart Swales Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/adfs/adfs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/adfs/adfs.h b/fs/adfs/adfs.h index a8a58d864f96..718ac1f440c6 100644 --- a/fs/adfs/adfs.h +++ b/fs/adfs/adfs.h @@ -112,7 +112,7 @@ struct object_info { /* RISC OS 12-bit filetype converts to ,xyz hex filename suffix */ static inline int append_filetype_suffix(char *buf, __u16 filetype) { - if (filetype == -1) + if (filetype == 0xffff) /* no explicit 12-bit file type was set */ return 0; *buf++ = ','; -- cgit From 50e0168cc3406fc1a04d57eb08f500a173d1660d Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Wed, 23 Mar 2011 16:42:07 -0700 Subject: ext4: use little-endian bitops As a preparation for removing ext2 non-atomic bit operations from asm/bitops.h. This converts ext2 non-atomic bit operations to little-endian bit operations. Signed-off-by: Akinobu Mita Acked-by: "Theodore Ts'o" Cc: Andreas Dilger Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext4/ext4.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'fs') diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 3aa0b72b3b94..4daaf2b753f4 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -923,14 +923,14 @@ struct ext4_inode_info { #define test_opt2(sb, opt) (EXT4_SB(sb)->s_mount_opt2 & \ EXT4_MOUNT2_##opt) -#define ext4_set_bit ext2_set_bit +#define ext4_set_bit __test_and_set_bit_le #define ext4_set_bit_atomic ext2_set_bit_atomic -#define ext4_clear_bit ext2_clear_bit +#define ext4_clear_bit __test_and_clear_bit_le #define ext4_clear_bit_atomic ext2_clear_bit_atomic -#define ext4_test_bit ext2_test_bit -#define ext4_find_first_zero_bit ext2_find_first_zero_bit -#define ext4_find_next_zero_bit ext2_find_next_zero_bit -#define ext4_find_next_bit ext2_find_next_bit +#define ext4_test_bit test_bit_le +#define ext4_find_first_zero_bit find_first_zero_bit_le +#define ext4_find_next_zero_bit find_next_zero_bit_le +#define ext4_find_next_bit find_next_bit_le /* * Maximal mount counts between two filesystem checks -- cgit From c4354d0d6812ad6729ac33d3c8bc64585cfdb890 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Wed, 23 Mar 2011 16:42:08 -0700 Subject: ocfs2: use little-endian bitops As a preparation for removing ext2 non-atomic bit operations from asm/bitops.h. This converts ext2 non-atomic bit operations to little-endian bit operations. Signed-off-by: Akinobu Mita Acked-by: Joel Becker Cc: Mark Fasheh Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ocfs2/ocfs2.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index 51cd6898e7f1..1a97ba1ec3fc 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h @@ -831,18 +831,18 @@ static inline unsigned int ocfs2_clusters_to_megabytes(struct super_block *sb, static inline void _ocfs2_set_bit(unsigned int bit, unsigned long *bitmap) { - ext2_set_bit(bit, bitmap); + __test_and_set_bit_le(bit, bitmap); } #define ocfs2_set_bit(bit, addr) _ocfs2_set_bit((bit), (unsigned long *)(addr)) static inline void _ocfs2_clear_bit(unsigned int bit, unsigned long *bitmap) { - ext2_clear_bit(bit, bitmap); + __test_and_clear_bit_le(bit, bitmap); } #define ocfs2_clear_bit(bit, addr) _ocfs2_clear_bit((bit), (unsigned long *)(addr)) -#define ocfs2_test_bit ext2_test_bit -#define ocfs2_find_next_zero_bit ext2_find_next_zero_bit -#define ocfs2_find_next_bit ext2_find_next_bit +#define ocfs2_test_bit test_bit_le +#define ocfs2_find_next_zero_bit find_next_zero_bit_le +#define ocfs2_find_next_bit find_next_bit_le #endif /* OCFS2_H */ -- cgit From a49ebbabb084d345991b72818a119616431416f2 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Wed, 23 Mar 2011 16:42:08 -0700 Subject: nilfs2: use little-endian bitops As a preparation for removing ext2 non-atomic bit operations from asm/bitops.h. This converts ext2 non-atomic bit operations to little-endian bit operations. Signed-off-by: Akinobu Mita Acked-by: Ryusuke Konishi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nilfs2/alloc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/nilfs2/alloc.h b/fs/nilfs2/alloc.h index 9af34a7e6e13..f5fde36b9e28 100644 --- a/fs/nilfs2/alloc.h +++ b/fs/nilfs2/alloc.h @@ -74,7 +74,7 @@ int nilfs_palloc_freev(struct inode *, __u64 *, size_t); #define nilfs_set_bit_atomic ext2_set_bit_atomic #define nilfs_clear_bit_atomic ext2_clear_bit_atomic -#define nilfs_find_next_zero_bit ext2_find_next_zero_bit +#define nilfs_find_next_zero_bit find_next_zero_bit_le /* * persistent object allocator cache -- cgit From 9ad1e1e405fb2c1ff35f2ec67cc6ba4c6765f192 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Wed, 23 Mar 2011 16:42:11 -0700 Subject: udf: use little-endian bitops As a preparation for removing ext2 non-atomic bit operations from asm/bitops.h. This converts ext2 non-atomic bit operations to little-endian bit operations. Signed-off-by: Akinobu Mita Acked-by: Jan Kara Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/udf/balloc.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c index 8994dd041660..95518a9f589e 100644 --- a/fs/udf/balloc.c +++ b/fs/udf/balloc.c @@ -27,11 +27,10 @@ #include "udf_i.h" #include "udf_sb.h" -#define udf_clear_bit(nr, addr) ext2_clear_bit(nr, addr) -#define udf_set_bit(nr, addr) ext2_set_bit(nr, addr) -#define udf_test_bit(nr, addr) ext2_test_bit(nr, addr) -#define udf_find_next_one_bit(addr, size, offset) \ - ext2_find_next_bit((unsigned long *)(addr), size, offset) +#define udf_clear_bit __test_and_clear_bit_le +#define udf_set_bit __test_and_set_bit_le +#define udf_test_bit test_bit_le +#define udf_find_next_one_bit find_next_bit_le static int read_block_bitmap(struct super_block *sb, struct udf_bitmap *bitmap, unsigned int block, -- cgit From 3cdc7125c364b2baad8aba69c058b26d3dca5f52 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Wed, 23 Mar 2011 16:42:11 -0700 Subject: ufs: use little-endian bitops As a preparation for removing ext2 non-atomic bit operations from asm/bitops.h. This converts ext2 non-atomic bit operations to little-endian bit operations. Signed-off-by: Akinobu Mita Cc: Evgeniy Dushistov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ufs/util.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/ufs/util.h b/fs/ufs/util.h index 9f8775ce381c..954175928240 100644 --- a/fs/ufs/util.h +++ b/fs/ufs/util.h @@ -408,7 +408,7 @@ static inline unsigned _ubh_find_next_zero_bit_( for (;;) { count = min_t(unsigned int, size + offset, uspi->s_bpf); size -= count - offset; - pos = ext2_find_next_zero_bit (ubh->bh[base]->b_data, count, offset); + pos = find_next_zero_bit_le(ubh->bh[base]->b_data, count, offset); if (pos < count || !size) break; base++; -- cgit From f312eff8164879e04923d41e9dd23e7850937d85 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Wed, 23 Mar 2011 16:42:14 -0700 Subject: bitops: remove ext2 non-atomic bitops from asm/bitops.h As the result of conversions, there are no users of ext2 non-atomic bit operations except for ext2 filesystem itself. Now we can put them into architecture independent code in ext2 filesystem, and remove from asm/bitops.h for all architectures. Signed-off-by: Akinobu Mita Cc: Jan Kara Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext2/ext2.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'fs') diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h index 1b48c3370872..645be9e7ee47 100644 --- a/fs/ext2/ext2.h +++ b/fs/ext2/ext2.h @@ -174,3 +174,9 @@ ext2_group_first_block_no(struct super_block *sb, unsigned long group_no) return group_no * (ext2_fsblk_t)EXT2_BLOCKS_PER_GROUP(sb) + le32_to_cpu(EXT2_SB(sb)->s_es->s_first_data_block); } + +#define ext2_set_bit __test_and_set_bit_le +#define ext2_clear_bit __test_and_clear_bit_le +#define ext2_test_bit test_bit_le +#define ext2_find_first_zero_bit find_first_zero_bit_le +#define ext2_find_next_zero_bit find_next_zero_bit_le -- cgit From 61f2e7b0f474225b4226772830ae4b29a3a21f8d Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Wed, 23 Mar 2011 16:42:16 -0700 Subject: bitops: remove minix bitops from asm/bitops.h minix bit operations are only used by minix filesystem and useless by other modules. Because byte order of inode and block bitmaps is different on each architecture like below: m68k: big-endian 16bit indexed bitmaps h8300, microblaze, s390, sparc, m68knommu: big-endian 32 or 64bit indexed bitmaps m32r, mips, sh, xtensa: big-endian 32 or 64bit indexed bitmaps for big-endian mode little-endian bitmaps for little-endian mode Others: little-endian bitmaps In order to move minix bit operations from asm/bitops.h to architecture independent code in minix filesystem, this provides two config options. CONFIG_MINIX_FS_BIG_ENDIAN_16BIT_INDEXED is only selected by m68k. CONFIG_MINIX_FS_NATIVE_ENDIAN is selected by the architectures which use native byte order bitmaps (h8300, microblaze, s390, sparc, m68knommu, m32r, mips, sh, xtensa). The architectures which always use little-endian bitmaps do not select these options. Finally, we can remove minix bit operations from asm/bitops.h for all architectures. Signed-off-by: Akinobu Mita Acked-by: Arnd Bergmann Acked-by: Greg Ungerer Cc: Geert Uytterhoeven Cc: Roman Zippel Cc: Andreas Schwab Cc: Martin Schwidefsky Cc: Heiko Carstens Cc: Yoshinori Sato Cc: Michal Simek Cc: "David S. Miller" Cc: Hirokazu Takata Acked-by: Ralf Baechle Acked-by: Paul Mundt Cc: Chris Zankel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/minix/Kconfig | 8 ++++++ fs/minix/minix.h | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) (limited to 'fs') diff --git a/fs/minix/Kconfig b/fs/minix/Kconfig index 0fd7ca994264..6624684dd5de 100644 --- a/fs/minix/Kconfig +++ b/fs/minix/Kconfig @@ -15,3 +15,11 @@ config MINIX_FS module will be called minix. Note that the file system of your root partition (the one containing the directory /) cannot be compiled as a module. + +config MINIX_FS_NATIVE_ENDIAN + def_bool MINIX_FS + depends on H8300 || M32R || MICROBLAZE || MIPS || S390 || SUPERH || SPARC || XTENSA || (M68K && !MMU) + +config MINIX_FS_BIG_ENDIAN_16BIT_INDEXED + def_bool MINIX_FS + depends on M68K && MMU diff --git a/fs/minix/minix.h b/fs/minix/minix.h index 407b1c84911e..341e2122879a 100644 --- a/fs/minix/minix.h +++ b/fs/minix/minix.h @@ -88,4 +88,78 @@ static inline struct minix_inode_info *minix_i(struct inode *inode) return list_entry(inode, struct minix_inode_info, vfs_inode); } +#if defined(CONFIG_MINIX_FS_NATIVE_ENDIAN) && \ + defined(CONFIG_MINIX_FS_BIG_ENDIAN_16BIT_INDEXED) + +#error Minix file system byte order broken + +#elif defined(CONFIG_MINIX_FS_NATIVE_ENDIAN) + +/* + * big-endian 32 or 64 bit indexed bitmaps on big-endian system or + * little-endian bitmaps on little-endian system + */ + +#define minix_test_and_set_bit(nr, addr) \ + __test_and_set_bit((nr), (unsigned long *)(addr)) +#define minix_set_bit(nr, addr) \ + __set_bit((nr), (unsigned long *)(addr)) +#define minix_test_and_clear_bit(nr, addr) \ + __test_and_clear_bit((nr), (unsigned long *)(addr)) +#define minix_test_bit(nr, addr) \ + test_bit((nr), (unsigned long *)(addr)) +#define minix_find_first_zero_bit(addr, size) \ + find_first_zero_bit((unsigned long *)(addr), (size)) + +#elif defined(CONFIG_MINIX_FS_BIG_ENDIAN_16BIT_INDEXED) + +/* + * big-endian 16bit indexed bitmaps + */ + +static inline int minix_find_first_zero_bit(const void *vaddr, unsigned size) +{ + const unsigned short *p = vaddr, *addr = vaddr; + unsigned short num; + + if (!size) + return 0; + + size = (size >> 4) + ((size & 15) > 0); + while (*p++ == 0xffff) { + if (--size == 0) + return (p - addr) << 4; + } + + num = *--p; + return ((p - addr) << 4) + ffz(num); +} + +#define minix_test_and_set_bit(nr, addr) \ + __test_and_set_bit((nr) ^ 16, (unsigned long *)(addr)) +#define minix_set_bit(nr, addr) \ + __set_bit((nr) ^ 16, (unsigned long *)(addr)) +#define minix_test_and_clear_bit(nr, addr) \ + __test_and_clear_bit((nr) ^ 16, (unsigned long *)(addr)) + +static inline int minix_test_bit(int nr, const void *vaddr) +{ + const unsigned short *p = vaddr; + return (p[nr >> 4] & (1U << (nr & 15))) != 0; +} + +#else + +/* + * little-endian bitmaps + */ + +#define minix_test_and_set_bit __test_and_set_bit_le +#define minix_set_bit __set_bit_le +#define minix_test_and_clear_bit __test_and_clear_bit_le +#define minix_test_bit test_bit_le +#define minix_find_first_zero_bit find_first_zero_bit_le + +#endif + #endif /* FS_MINIX_H */ -- cgit From 51e031496d50f87ff519a63cfd4fc2f415f03336 Mon Sep 17 00:00:00 2001 From: Konstantin Khlebnikov Date: Wed, 23 Mar 2011 16:42:48 -0700 Subject: proc: hide kernel addresses via %pK in /proc//stack This file is readable for the task owner. Hide kernel addresses from unprivileged users, leave them function names and offsets. Signed-off-by: Konstantin Khlebnikov Acked-by: Kees Cook Cc: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/proc/base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/proc/base.c b/fs/proc/base.c index d49c4b5d2c3e..c3af15e9c070 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -340,7 +340,7 @@ static int proc_pid_stack(struct seq_file *m, struct pid_namespace *ns, save_stack_trace_tsk(task, &trace); for (i = 0; i < trace.nr_entries; i++) { - seq_printf(m, "[<%p>] %pS\n", + seq_printf(m, "[<%pK>] %pS\n", (void *)entries[i], (void *)entries[i]); } kfree(entries); -- cgit From 0db0c01b53a1a421513f91573241aabafb87802a Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Wed, 23 Mar 2011 16:42:50 -0700 Subject: procfs: fix /proc//maps heap check The current code fails to print the "[heap]" marking if the heap is split into multiple mappings. Fix the check so that the marking is displayed in all possible cases: 1. vma matches exactly the heap 2. the heap vma is merged e.g. with bss 3. the heap vma is splitted e.g. due to locked pages Test cases. In all cases, the process should have mapping(s) with [heap] marking: (1) vma matches exactly the heap #include #include #include int main (void) { if (sbrk(4096) != (void *)-1) { printf("check /proc/%d/maps\n", (int)getpid()); while (1) sleep(1); } return 0; } # ./test1 check /proc/553/maps [1] + Stopped ./test1 # cat /proc/553/maps | head -4 00008000-00009000 r-xp 00000000 01:00 3113640 /test1 00010000-00011000 rw-p 00000000 01:00 3113640 /test1 00011000-00012000 rw-p 00000000 00:00 0 [heap] 4006f000-40070000 rw-p 00000000 00:00 0 (2) the heap vma is merged #include #include #include char foo[4096] = "foo"; char bar[4096]; int main (void) { if (sbrk(4096) != (void *)-1) { printf("check /proc/%d/maps\n", (int)getpid()); while (1) sleep(1); } return 0; } # ./test2 check /proc/556/maps [2] + Stopped ./test2 # cat /proc/556/maps | head -4 00008000-00009000 r-xp 00000000 01:00 3116312 /test2 00010000-00012000 rw-p 00000000 01:00 3116312 /test2 00012000-00014000 rw-p 00000000 00:00 0 [heap] 4004a000-4004b000 rw-p 00000000 00:00 0 (3) the heap vma is splitted (this fails without the patch) #include #include #include #include int main (void) { if ((sbrk(4096) != (void *)-1) && !mlockall(MCL_FUTURE) && (sbrk(4096) != (void *)-1)) { printf("check /proc/%d/maps\n", (int)getpid()); while (1) sleep(1); } return 0; } # ./test3 check /proc/559/maps [1] + Stopped ./test3 # cat /proc/559/maps|head -4 00008000-00009000 r-xp 00000000 01:00 3119108 /test3 00010000-00011000 rw-p 00000000 01:00 3119108 /test3 00011000-00012000 rw-p 00000000 00:00 0 [heap] 00012000-00013000 rw-p 00000000 00:00 0 [heap] It looks like the bug has been there forever, and since it only results in some information missing from a procfile, it does not fulfil the -stable "critical issue" criteria. Signed-off-by: Aaro Koskinen Reviewed-by: KOSAKI Motohiro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/proc/task_mmu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 93381aae9363..636f1a1fdf87 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -251,8 +251,8 @@ static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma) const char *name = arch_vma_name(vma); if (!name) { if (mm) { - if (vma->vm_start <= mm->start_brk && - vma->vm_end >= mm->brk) { + if (vma->vm_start <= mm->brk && + vma->vm_end >= mm->start_brk) { name = "[heap]"; } else if (vma->vm_start <= mm->start_stack && vma->vm_end >= mm->start_stack) { -- cgit From fc3d8767b2b6de955579852d7a150f1734265eaf Mon Sep 17 00:00:00 2001 From: Jovi Zhang Date: Wed, 23 Mar 2011 16:42:51 -0700 Subject: procfs: fix some wrong error code usage [root@wei 1]# cat /proc/1/mem cat: /proc/1/mem: No such process error code -ESRCH is wrong in this situation. Return -EPERM instead. Signed-off-by: Jovi Zhang Reviewed-by: KOSAKI Motohiro Cc: Alexey Dobriyan Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/proc/base.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/proc/base.c b/fs/proc/base.c index c3af15e9c070..daba13653256 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -775,7 +775,8 @@ static ssize_t mem_read(struct file * file, char __user * buf, if (!task) goto out_no_task; - if (check_mem_permission(task)) + ret = check_mem_permission(task); + if (ret) goto out; ret = -ENOMEM; @@ -845,7 +846,8 @@ static ssize_t mem_write(struct file * file, const char __user *buf, if (!task) goto out_no_task; - if (check_mem_permission(task)) + copied = check_mem_permission(task); + if (copied) goto out; copied = -ENOMEM; @@ -917,6 +919,7 @@ static ssize_t environ_read(struct file *file, char __user *buf, if (!task) goto out_no_task; + ret = -EPERM; if (!ptrace_may_access(task, PTRACE_MODE_READ)) goto out; -- cgit From 312ec7e50c4d3f40b3762af651d1aa79a67f556a Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Wed, 23 Mar 2011 16:42:52 -0700 Subject: proc: make struct proc_dir_entry::namelen unsigned int 1. namelen is declared "unsigned short" which hints for "maybe space savings". Indeed in 2.4 struct proc_dir_entry looked like: struct proc_dir_entry { unsigned short low_ino; unsigned short namelen; Now, low_ino is "unsigned int", all savings were gone for a long time. "struct proc_dir_entry" is not that countless to worry about it's size, anyway. 2. converting from unsigned short to int/unsigned int can only create problems, we better play it safe. Space is not really conserved, because of natural alignment for the next field. sizeof(struct proc_dir_entry) remains the same. Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/proc/generic.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 01e07f2a188f..f1281339b6fa 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -28,7 +28,7 @@ DEFINE_SPINLOCK(proc_subdir_lock); -static int proc_match(int len, const char *name, struct proc_dir_entry *de) +static int proc_match(unsigned int len, const char *name, struct proc_dir_entry *de) { if (de->namelen != len) return 0; @@ -303,7 +303,7 @@ static int __xlate_proc_name(const char *name, struct proc_dir_entry **ret, { const char *cp = name, *next; struct proc_dir_entry *de; - int len; + unsigned int len; de = *ret; if (!de) @@ -602,7 +602,7 @@ static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent, { struct proc_dir_entry *ent = NULL; const char *fn = name; - int len; + unsigned int len; /* make sure name is valid */ if (!name || !strlen(name)) goto out; @@ -786,7 +786,7 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent) struct proc_dir_entry **p; struct proc_dir_entry *de = NULL; const char *fn = name; - int len; + unsigned int len; spin_lock(&proc_subdir_lock); if (__xlate_proc_name(name, &parent, &fn) != 0) { -- cgit From 5883f57ca0008ffc93e09cbb9847a1928e50c6f3 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 23 Mar 2011 16:42:53 -0700 Subject: proc: protect mm start_code/end_code in /proc/pid/stat While mm->start_stack was protected from cross-uid viewing (commit f83ce3e6b02d5 ("proc: avoid information leaks to non-privileged processes")), the start_code and end_code values were not. This would allow the text location of a PIE binary to leak, defeating ASLR. Note that the value "1" is used instead of "0" for a protected value since "ps", "killall", and likely other readers of /proc/pid/stat, take start_code of "0" to mean a kernel thread and will misbehave. Thanks to Brad Spengler for pointing this out. Addresses CVE-2011-0726 Signed-off-by: Kees Cook Cc: Cc: Alexey Dobriyan Cc: David Howells Cc: Eugene Teo Cc: Martin Schwidefsky Cc: Brad Spengler Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/proc/array.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/proc/array.c b/fs/proc/array.c index 7c99c1cf7e5c..5e4f776b0917 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -489,8 +489,8 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns, vsize, mm ? get_mm_rss(mm) : 0, rsslim, - mm ? mm->start_code : 0, - mm ? mm->end_code : 0, + mm ? (permitted ? mm->start_code : 1) : 0, + mm ? (permitted ? mm->end_code : 1) : 0, (permitted && mm) ? mm->start_stack : 0, esp, eip, -- cgit From cb16e95fa2996743a6e80a665ed2ed0590bd38cf Mon Sep 17 00:00:00 2001 From: Petr Holasek Date: Wed, 23 Mar 2011 16:43:09 -0700 Subject: sysctl: add some missing input constraint checks Add boundaries of allowed input ranges for: dirty_expire_centisecs, drop_caches, overcommit_memory, page-cluster and panic_on_oom. Signed-off-by: Petr Holasek Acked-by: Dave Young Cc: David Rientjes Cc: Wu Fengguang Cc: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/drop_caches.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/drop_caches.c b/fs/drop_caches.c index 2195c213ab2f..816f88e6b9ce 100644 --- a/fs/drop_caches.c +++ b/fs/drop_caches.c @@ -45,7 +45,11 @@ static void drop_slab(void) int drop_caches_sysctl_handler(ctl_table *table, int write, void __user *buffer, size_t *length, loff_t *ppos) { - proc_dointvec_minmax(table, write, buffer, length, ppos); + int ret; + + ret = proc_dointvec_minmax(table, write, buffer, length, ppos); + if (ret) + return ret; if (write) { if (sysctl_drop_caches & 1) iterate_supers(drop_pagecache_sb, NULL); -- cgit From 4308eebbeb2026827d4492ce8c23d99f7f144a82 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Wed, 23 Mar 2011 16:43:13 -0700 Subject: pidns: call pid_ns_prepare_proc() from create_pid_namespace() Reorganize proc_get_sb() so it can be called before the struct pid of the first process is allocated. Signed-off-by: Eric W. Biederman Signed-off-by: Daniel Lezcano Cc: Oleg Nesterov Cc: Alexey Dobriyan Acked-by: Serge E. Hallyn Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/proc/root.c | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) (limited to 'fs') diff --git a/fs/proc/root.c b/fs/proc/root.c index ef9fa8e24ad6..e5e2bfa7a03b 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -43,17 +43,6 @@ static struct dentry *proc_mount(struct file_system_type *fs_type, struct pid_namespace *ns; struct proc_inode *ei; - if (proc_mnt) { - /* Seed the root directory with a pid so it doesn't need - * to be special in base.c. I would do this earlier but - * the only task alive when /proc is mounted the first time - * is the init_task and it doesn't have any pids. - */ - ei = PROC_I(proc_mnt->mnt_sb->s_root->d_inode); - if (!ei->pid) - ei->pid = find_get_pid(1); - } - if (flags & MS_KERNMOUNT) ns = (struct pid_namespace *)data; else @@ -71,16 +60,16 @@ static struct dentry *proc_mount(struct file_system_type *fs_type, return ERR_PTR(err); } - ei = PROC_I(sb->s_root->d_inode); - if (!ei->pid) { - rcu_read_lock(); - ei->pid = get_pid(find_pid_ns(1, ns)); - rcu_read_unlock(); - } - sb->s_flags |= MS_ACTIVE; } + ei = PROC_I(sb->s_root->d_inode); + if (!ei->pid) { + rcu_read_lock(); + ei->pid = get_pid(find_pid_ns(1, ns)); + rcu_read_unlock(); + } + return dget(sb->s_root); } -- cgit From 52e9fc76d0d4b1e8adeee736172c6c23180059b2 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Wed, 23 Mar 2011 16:43:14 -0700 Subject: procfs: kill the global proc_mnt variable After the previous cleanup in proc_get_sb() the global proc_mnt has no reasons to exists, kill it. Signed-off-by: Oleg Nesterov Signed-off-by: Eric W. Biederman Signed-off-by: Daniel Lezcano Cc: Alexey Dobriyan Acked-by: Serge E. Hallyn Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/proc/inode.c | 2 -- fs/proc/internal.h | 1 - fs/proc/root.c | 7 ++++--- 3 files changed, 4 insertions(+), 6 deletions(-) (limited to 'fs') diff --git a/fs/proc/inode.c b/fs/proc/inode.c index d6a7ca1fdac5..d15aa1b1cc8f 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -46,8 +46,6 @@ static void proc_evict_inode(struct inode *inode) } } -struct vfsmount *proc_mnt; - static struct kmem_cache * proc_inode_cachep; static struct inode *proc_alloc_inode(struct super_block *sb) diff --git a/fs/proc/internal.h b/fs/proc/internal.h index 9ad561ded409..c03e8d3a3a5b 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h @@ -107,7 +107,6 @@ static inline struct proc_dir_entry *pde_get(struct proc_dir_entry *pde) } void pde_put(struct proc_dir_entry *pde); -extern struct vfsmount *proc_mnt; int proc_fill_super(struct super_block *); struct inode *proc_get_inode(struct super_block *, struct proc_dir_entry *); diff --git a/fs/proc/root.c b/fs/proc/root.c index e5e2bfa7a03b..a9000e9cfee5 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -90,19 +90,20 @@ static struct file_system_type proc_fs_type = { void __init proc_root_init(void) { + struct vfsmount *mnt; int err; proc_init_inodecache(); err = register_filesystem(&proc_fs_type); if (err) return; - proc_mnt = kern_mount_data(&proc_fs_type, &init_pid_ns); - if (IS_ERR(proc_mnt)) { + mnt = kern_mount_data(&proc_fs_type, &init_pid_ns); + if (IS_ERR(mnt)) { unregister_filesystem(&proc_fs_type); return; } - init_pid_ns.proc_mnt = proc_mnt; + init_pid_ns.proc_mnt = mnt; proc_symlink("mounts", NULL, "self/mounts"); proc_net_init(); -- cgit From e795b71799ff0b27365020c9ddaa25d0d83f99c8 Mon Sep 17 00:00:00 2001 From: "Serge E. Hallyn" Date: Wed, 23 Mar 2011 16:43:25 -0700 Subject: userns: userns: check user namespace for task->file uid equivalence checks Cheat for now and say all files belong to init_user_ns. Next step will be to let superblocks belong to a user_ns, and derive inode_userns(inode) from inode->i_sb->s_user_ns. Finally we'll introduce more flexible arrangements. Changelog: Feb 15: make is_owner_or_cap take const struct inode Feb 23: make is_owner_or_cap bool [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Serge E. Hallyn Acked-by: "Eric W. Biederman" Acked-by: Daniel Lezcano Acked-by: David Howells Cc: James Morris Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/inode.c | 17 +++++++++++++++++ fs/namei.c | 21 ++++++++++++++++----- 2 files changed, 33 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/inode.c b/fs/inode.c index 16fefd373fc2..a21d5a938a17 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -25,6 +25,7 @@ #include #include #include +#include /* * This is needed for the following functions: @@ -1733,3 +1734,19 @@ void inode_init_owner(struct inode *inode, const struct inode *dir, inode->i_mode = mode; } EXPORT_SYMBOL(inode_init_owner); + +/* + * return true if current either has CAP_FOWNER to the + * file, or owns the file. + */ +bool is_owner_or_cap(const struct inode *inode) +{ + struct user_namespace *ns = inode_userns(inode); + + if (current_user_ns() == ns && current_fsuid() == inode->i_uid) + return true; + if (ns_capable(ns, CAP_FOWNER)) + return true; + return false; +} +EXPORT_SYMBOL(is_owner_or_cap); diff --git a/fs/namei.c b/fs/namei.c index 5a9a6c3094da..dbb45a652ae3 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -183,6 +183,9 @@ static int acl_permission_check(struct inode *inode, int mask, unsigned int flag mask &= MAY_READ | MAY_WRITE | MAY_EXEC; + if (current_user_ns() != inode_userns(inode)) + goto other_perms; + if (current_fsuid() == inode->i_uid) mode >>= 6; else { @@ -196,6 +199,7 @@ static int acl_permission_check(struct inode *inode, int mask, unsigned int flag mode >>= 3; } +other_perms: /* * If the DACs are ok we don't need any capability check. */ @@ -237,7 +241,7 @@ int generic_permission(struct inode *inode, int mask, unsigned int flags, * Executable DACs are overridable if at least one exec bit is set. */ if (!(mask & MAY_EXEC) || execute_ok(inode)) - if (capable(CAP_DAC_OVERRIDE)) + if (ns_capable(inode_userns(inode), CAP_DAC_OVERRIDE)) return 0; /* @@ -245,7 +249,7 @@ int generic_permission(struct inode *inode, int mask, unsigned int flags, */ mask &= MAY_READ | MAY_WRITE | MAY_EXEC; if (mask == MAY_READ || (S_ISDIR(inode->i_mode) && !(mask & MAY_WRITE))) - if (capable(CAP_DAC_READ_SEARCH)) + if (ns_capable(inode_userns(inode), CAP_DAC_READ_SEARCH)) return 0; return -EACCES; @@ -654,6 +658,7 @@ static inline int handle_reval_path(struct nameidata *nd) static inline int exec_permission(struct inode *inode, unsigned int flags) { int ret; + struct user_namespace *ns = inode_userns(inode); if (inode->i_op->permission) { ret = inode->i_op->permission(inode, MAY_EXEC, flags); @@ -666,7 +671,8 @@ static inline int exec_permission(struct inode *inode, unsigned int flags) if (ret == -ECHILD) return ret; - if (capable(CAP_DAC_OVERRIDE) || capable(CAP_DAC_READ_SEARCH)) + if (ns_capable(ns, CAP_DAC_OVERRIDE) || + ns_capable(ns, CAP_DAC_READ_SEARCH)) goto ok; return ret; @@ -1842,11 +1848,15 @@ static inline int check_sticky(struct inode *dir, struct inode *inode) if (!(dir->i_mode & S_ISVTX)) return 0; + if (current_user_ns() != inode_userns(inode)) + goto other_userns; if (inode->i_uid == fsuid) return 0; if (dir->i_uid == fsuid) return 0; - return !capable(CAP_FOWNER); + +other_userns: + return !ns_capable(inode_userns(inode), CAP_FOWNER); } /* @@ -2440,7 +2450,8 @@ int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) if (error) return error; - if ((S_ISCHR(mode) || S_ISBLK(mode)) && !capable(CAP_MKNOD)) + if ((S_ISCHR(mode) || S_ISBLK(mode)) && + !ns_capable(inode_userns(dir), CAP_MKNOD)) return -EPERM; if (!dir->i_op->mknod) -- cgit From 2e1496707560ecf98e9b0604622c0990f94861d3 Mon Sep 17 00:00:00 2001 From: "Serge E. Hallyn" Date: Wed, 23 Mar 2011 16:43:26 -0700 Subject: userns: rename is_owner_or_cap to inode_owner_or_capable And give it a kernel-doc comment. [akpm@linux-foundation.org: btrfs changed in linux-next] Signed-off-by: Serge E. Hallyn Cc: "Eric W. Biederman" Cc: Daniel Lezcano Acked-by: David Howells Cc: James Morris Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/9p/acl.c | 2 +- fs/attr.c | 4 ++-- fs/btrfs/acl.c | 2 +- fs/btrfs/ioctl.c | 4 ++-- fs/ext2/acl.c | 2 +- fs/ext2/ioctl.c | 6 +++--- fs/ext3/acl.c | 2 +- fs/ext3/ioctl.c | 6 +++--- fs/ext4/acl.c | 2 +- fs/ext4/ioctl.c | 8 ++++---- fs/fcntl.c | 2 +- fs/generic_acl.c | 2 +- fs/gfs2/file.c | 2 +- fs/hfsplus/ioctl.c | 2 +- fs/inode.c | 13 ++++++++----- fs/jffs2/acl.c | 2 +- fs/jfs/ioctl.c | 2 +- fs/jfs/xattr.c | 2 +- fs/logfs/file.c | 2 +- fs/namei.c | 2 +- fs/nilfs2/ioctl.c | 2 +- fs/ocfs2/acl.c | 2 +- fs/ocfs2/ioctl.c | 2 +- fs/reiserfs/ioctl.c | 4 ++-- fs/reiserfs/xattr_acl.c | 2 +- fs/ubifs/ioctl.c | 2 +- fs/utimes.c | 2 +- fs/xattr.c | 2 +- 28 files changed, 45 insertions(+), 42 deletions(-) (limited to 'fs') diff --git a/fs/9p/acl.c b/fs/9p/acl.c index 33aa116732c8..535ab6eccb1a 100644 --- a/fs/9p/acl.c +++ b/fs/9p/acl.c @@ -323,7 +323,7 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name, if (S_ISLNK(inode->i_mode)) return -EOPNOTSUPP; - if (!is_owner_or_cap(inode)) + if (!inode_owner_or_capable(inode)) return -EPERM; if (value) { /* update the cached acl value */ diff --git a/fs/attr.c b/fs/attr.c index 7ca41811afa1..1007ed616314 100644 --- a/fs/attr.c +++ b/fs/attr.c @@ -59,7 +59,7 @@ int inode_change_ok(const struct inode *inode, struct iattr *attr) /* Make sure a caller can chmod. */ if (ia_valid & ATTR_MODE) { - if (!is_owner_or_cap(inode)) + if (!inode_owner_or_capable(inode)) return -EPERM; /* Also check the setgid bit! */ if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid : @@ -69,7 +69,7 @@ int inode_change_ok(const struct inode *inode, struct iattr *attr) /* Check for setting the inode time. */ if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)) { - if (!is_owner_or_cap(inode)) + if (!inode_owner_or_capable(inode)) return -EPERM; } diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c index 9c949348510b..de34bfad9ec3 100644 --- a/fs/btrfs/acl.c +++ b/fs/btrfs/acl.c @@ -170,7 +170,7 @@ static int btrfs_xattr_acl_set(struct dentry *dentry, const char *name, int ret; struct posix_acl *acl = NULL; - if (!is_owner_or_cap(dentry->d_inode)) + if (!inode_owner_or_capable(dentry->d_inode)) return -EPERM; if (!IS_POSIXACL(dentry->d_inode)) diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 5fdb2abc4fa7..d1bace3df9b6 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -158,7 +158,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg) FS_SYNC_FL | FS_DIRSYNC_FL)) return -EOPNOTSUPP; - if (!is_owner_or_cap(inode)) + if (!inode_owner_or_capable(inode)) return -EACCES; mutex_lock(&inode->i_mutex); @@ -1077,7 +1077,7 @@ static noinline int btrfs_ioctl_subvol_setflags(struct file *file, if (flags & ~BTRFS_SUBVOL_RDONLY) return -EOPNOTSUPP; - if (!is_owner_or_cap(inode)) + if (!inode_owner_or_capable(inode)) return -EACCES; down_write(&root->fs_info->subvol_sem); diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c index 7b4180554a62..abea5a17c764 100644 --- a/fs/ext2/acl.c +++ b/fs/ext2/acl.c @@ -406,7 +406,7 @@ ext2_xattr_set_acl(struct dentry *dentry, const char *name, const void *value, return -EINVAL; if (!test_opt(dentry->d_sb, POSIX_ACL)) return -EOPNOTSUPP; - if (!is_owner_or_cap(dentry->d_inode)) + if (!inode_owner_or_capable(dentry->d_inode)) return -EPERM; if (value) { diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c index e7431309bdca..f81e250ac5c4 100644 --- a/fs/ext2/ioctl.c +++ b/fs/ext2/ioctl.c @@ -39,7 +39,7 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (ret) return ret; - if (!is_owner_or_cap(inode)) { + if (!inode_owner_or_capable(inode)) { ret = -EACCES; goto setflags_out; } @@ -89,7 +89,7 @@ setflags_out: case EXT2_IOC_GETVERSION: return put_user(inode->i_generation, (int __user *) arg); case EXT2_IOC_SETVERSION: - if (!is_owner_or_cap(inode)) + if (!inode_owner_or_capable(inode)) return -EPERM; ret = mnt_want_write(filp->f_path.mnt); if (ret) @@ -115,7 +115,7 @@ setflags_out: if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode)) return -ENOTTY; - if (!is_owner_or_cap(inode)) + if (!inode_owner_or_capable(inode)) return -EACCES; if (get_user(rsv_window_size, (int __user *)arg)) diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c index e4fa49e6c539..9d021c0d472a 100644 --- a/fs/ext3/acl.c +++ b/fs/ext3/acl.c @@ -435,7 +435,7 @@ ext3_xattr_set_acl(struct dentry *dentry, const char *name, const void *value, return -EINVAL; if (!test_opt(inode->i_sb, POSIX_ACL)) return -EOPNOTSUPP; - if (!is_owner_or_cap(inode)) + if (!inode_owner_or_capable(inode)) return -EPERM; if (value) { diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c index fc080dd561f7..f4090bd2f345 100644 --- a/fs/ext3/ioctl.c +++ b/fs/ext3/ioctl.c @@ -38,7 +38,7 @@ long ext3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) unsigned int oldflags; unsigned int jflag; - if (!is_owner_or_cap(inode)) + if (!inode_owner_or_capable(inode)) return -EACCES; if (get_user(flags, (int __user *) arg)) @@ -123,7 +123,7 @@ flags_out: __u32 generation; int err; - if (!is_owner_or_cap(inode)) + if (!inode_owner_or_capable(inode)) return -EPERM; err = mnt_want_write(filp->f_path.mnt); @@ -192,7 +192,7 @@ setversion_out: if (err) return err; - if (!is_owner_or_cap(inode)) { + if (!inode_owner_or_capable(inode)) { err = -EACCES; goto setrsvsz_out; } diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c index e0270d1f8d82..21eacd7b7d79 100644 --- a/fs/ext4/acl.c +++ b/fs/ext4/acl.c @@ -433,7 +433,7 @@ ext4_xattr_set_acl(struct dentry *dentry, const char *name, const void *value, return -EINVAL; if (!test_opt(inode->i_sb, POSIX_ACL)) return -EOPNOTSUPP; - if (!is_owner_or_cap(inode)) + if (!inode_owner_or_capable(inode)) return -EPERM; if (value) { diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index eb3bc2fe647e..a84faa110bcd 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -38,7 +38,7 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) unsigned int oldflags; unsigned int jflag; - if (!is_owner_or_cap(inode)) + if (!inode_owner_or_capable(inode)) return -EACCES; if (get_user(flags, (int __user *) arg)) @@ -146,7 +146,7 @@ flags_out: __u32 generation; int err; - if (!is_owner_or_cap(inode)) + if (!inode_owner_or_capable(inode)) return -EPERM; err = mnt_want_write(filp->f_path.mnt); @@ -298,7 +298,7 @@ mext_out: case EXT4_IOC_MIGRATE: { int err; - if (!is_owner_or_cap(inode)) + if (!inode_owner_or_capable(inode)) return -EACCES; err = mnt_want_write(filp->f_path.mnt); @@ -320,7 +320,7 @@ mext_out: case EXT4_IOC_ALLOC_DA_BLKS: { int err; - if (!is_owner_or_cap(inode)) + if (!inode_owner_or_capable(inode)) return -EACCES; err = mnt_want_write(filp->f_path.mnt); diff --git a/fs/fcntl.c b/fs/fcntl.c index 6c82e5bac039..22764c7c8382 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -159,7 +159,7 @@ static int setfl(int fd, struct file * filp, unsigned long arg) /* O_NOATIME can only be set by the owner or superuser */ if ((arg & O_NOATIME) && !(filp->f_flags & O_NOATIME)) - if (!is_owner_or_cap(inode)) + if (!inode_owner_or_capable(inode)) return -EPERM; /* required for strict SunOS emulation */ diff --git a/fs/generic_acl.c b/fs/generic_acl.c index 06c48a891832..8f26d1a58912 100644 --- a/fs/generic_acl.c +++ b/fs/generic_acl.c @@ -74,7 +74,7 @@ generic_acl_set(struct dentry *dentry, const char *name, const void *value, return -EINVAL; if (S_ISLNK(inode->i_mode)) return -EOPNOTSUPP; - if (!is_owner_or_cap(inode)) + if (!inode_owner_or_capable(inode)) return -EPERM; if (value) { acl = posix_acl_from_xattr(value, size); diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index 4074b952b059..b2682e073eee 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c @@ -221,7 +221,7 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask) goto out_drop_write; error = -EACCES; - if (!is_owner_or_cap(inode)) + if (!inode_owner_or_capable(inode)) goto out; error = 0; diff --git a/fs/hfsplus/ioctl.c b/fs/hfsplus/ioctl.c index 508ce662ce12..fbaa6690c8e0 100644 --- a/fs/hfsplus/ioctl.c +++ b/fs/hfsplus/ioctl.c @@ -47,7 +47,7 @@ static int hfsplus_ioctl_setflags(struct file *file, int __user *user_flags) if (err) goto out; - if (!is_owner_or_cap(inode)) { + if (!inode_owner_or_capable(inode)) { err = -EACCES; goto out_drop_write; } diff --git a/fs/inode.c b/fs/inode.c index a21d5a938a17..0b3da4a77704 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -1735,11 +1735,14 @@ void inode_init_owner(struct inode *inode, const struct inode *dir, } EXPORT_SYMBOL(inode_init_owner); -/* - * return true if current either has CAP_FOWNER to the - * file, or owns the file. +/** + * inode_owner_or_capable - check current task permissions to inode + * @inode: inode being checked + * + * Return true if current either has CAP_FOWNER to the inode, or + * owns the file. */ -bool is_owner_or_cap(const struct inode *inode) +bool inode_owner_or_capable(const struct inode *inode) { struct user_namespace *ns = inode_userns(inode); @@ -1749,4 +1752,4 @@ bool is_owner_or_cap(const struct inode *inode) return true; return false; } -EXPORT_SYMBOL(is_owner_or_cap); +EXPORT_SYMBOL(inode_owner_or_capable); diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c index 95b79672150a..828a0e1ea438 100644 --- a/fs/jffs2/acl.c +++ b/fs/jffs2/acl.c @@ -402,7 +402,7 @@ static int jffs2_acl_setxattr(struct dentry *dentry, const char *name, if (name[0] != '\0') return -EINVAL; - if (!is_owner_or_cap(dentry->d_inode)) + if (!inode_owner_or_capable(dentry->d_inode)) return -EPERM; if (value) { diff --git a/fs/jfs/ioctl.c b/fs/jfs/ioctl.c index afe222bf300f..6f98a1866776 100644 --- a/fs/jfs/ioctl.c +++ b/fs/jfs/ioctl.c @@ -72,7 +72,7 @@ long jfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (err) return err; - if (!is_owner_or_cap(inode)) { + if (!inode_owner_or_capable(inode)) { err = -EACCES; goto setflags_out; } diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c index 3fa4c32272df..24838f1eeee5 100644 --- a/fs/jfs/xattr.c +++ b/fs/jfs/xattr.c @@ -678,7 +678,7 @@ static int can_set_system_xattr(struct inode *inode, const char *name, struct posix_acl *acl; int rc; - if (!is_owner_or_cap(inode)) + if (!inode_owner_or_capable(inode)) return -EPERM; /* diff --git a/fs/logfs/file.c b/fs/logfs/file.c index e86376b87af1..c2ad7028def4 100644 --- a/fs/logfs/file.c +++ b/fs/logfs/file.c @@ -196,7 +196,7 @@ long logfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (IS_RDONLY(inode)) return -EROFS; - if (!is_owner_or_cap(inode)) + if (!inode_owner_or_capable(inode)) return -EACCES; err = get_user(flags, (int __user *)arg); diff --git a/fs/namei.c b/fs/namei.c index dbb45a652ae3..fc858b1124c2 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2036,7 +2036,7 @@ static int may_open(struct path *path, int acc_mode, int flag) } /* O_NOATIME can only be set by the owner or superuser */ - if (flag & O_NOATIME && !is_owner_or_cap(inode)) + if (flag & O_NOATIME && !inode_owner_or_capable(inode)) return -EPERM; /* diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index 95c04c2f2b3e..f2469ba6246b 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c @@ -113,7 +113,7 @@ static int nilfs_ioctl_setflags(struct inode *inode, struct file *filp, unsigned int flags, oldflags; int ret; - if (!is_owner_or_cap(inode)) + if (!inode_owner_or_capable(inode)) return -EACCES; if (get_user(flags, (int __user *)argp)) diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c index 704f6b1742f3..90f2729b7a5b 100644 --- a/fs/ocfs2/acl.c +++ b/fs/ocfs2/acl.c @@ -497,7 +497,7 @@ static int ocfs2_xattr_set_acl(struct dentry *dentry, const char *name, if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL)) return -EOPNOTSUPP; - if (!is_owner_or_cap(inode)) + if (!inode_owner_or_capable(inode)) return -EPERM; if (value) { diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c index 7a4868196152..09de77ce002a 100644 --- a/fs/ocfs2/ioctl.c +++ b/fs/ocfs2/ioctl.c @@ -82,7 +82,7 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags, } status = -EACCES; - if (!is_owner_or_cap(inode)) + if (!inode_owner_or_capable(inode)) goto bail_unlock; if (!S_ISDIR(inode->i_mode)) diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c index 79265fdc317a..4e153051bc75 100644 --- a/fs/reiserfs/ioctl.c +++ b/fs/reiserfs/ioctl.c @@ -59,7 +59,7 @@ long reiserfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (err) break; - if (!is_owner_or_cap(inode)) { + if (!inode_owner_or_capable(inode)) { err = -EPERM; goto setflags_out; } @@ -103,7 +103,7 @@ setflags_out: err = put_user(inode->i_generation, (int __user *)arg); break; case REISERFS_IOC_SETVERSION: - if (!is_owner_or_cap(inode)) { + if (!inode_owner_or_capable(inode)) { err = -EPERM; break; } diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c index 90d2fcb67a31..3dc38f1206fc 100644 --- a/fs/reiserfs/xattr_acl.c +++ b/fs/reiserfs/xattr_acl.c @@ -26,7 +26,7 @@ posix_acl_set(struct dentry *dentry, const char *name, const void *value, size_t jcreate_blocks; if (!reiserfs_posixacl(inode->i_sb)) return -EOPNOTSUPP; - if (!is_owner_or_cap(inode)) + if (!inode_owner_or_capable(inode)) return -EPERM; if (value) { diff --git a/fs/ubifs/ioctl.c b/fs/ubifs/ioctl.c index 8aacd64957a2..548acf494afd 100644 --- a/fs/ubifs/ioctl.c +++ b/fs/ubifs/ioctl.c @@ -160,7 +160,7 @@ long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (IS_RDONLY(inode)) return -EROFS; - if (!is_owner_or_cap(inode)) + if (!inode_owner_or_capable(inode)) return -EACCES; if (get_user(flags, (int __user *) arg)) diff --git a/fs/utimes.c b/fs/utimes.c index 179b58690657..ba653f3dc1bc 100644 --- a/fs/utimes.c +++ b/fs/utimes.c @@ -95,7 +95,7 @@ static int utimes_common(struct path *path, struct timespec *times) if (IS_IMMUTABLE(inode)) goto mnt_drop_write_and_out; - if (!is_owner_or_cap(inode)) { + if (!inode_owner_or_capable(inode)) { error = inode_permission(inode, MAY_WRITE); if (error) goto mnt_drop_write_and_out; diff --git a/fs/xattr.c b/fs/xattr.c index 01bb8135e14a..a19acdb81cd1 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -59,7 +59,7 @@ xattr_permission(struct inode *inode, const char *name, int mask) if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode)) return -EPERM; if (S_ISDIR(inode->i_mode) && (inode->i_mode & S_ISVTX) && - (mask & MAY_WRITE) && !is_owner_or_cap(inode)) + (mask & MAY_WRITE) && !inode_owner_or_capable(inode)) return -EPERM; } -- cgit From fc5e58c0c4fd86881ec8ba8e46e41a07e25dc7a6 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Thu, 24 Mar 2011 16:14:26 +0200 Subject: UBIFS: use GFP_NOFS properly This patch fixes a brown-paperbag bug which was introduced by me: I used incorrect "GFP_KERNEL | GFP_NOFS" allocation flags to make sure my allocations do not cause write-back. But the correct form is "GFP_NOFS". Signed-off-by: Artem Bityutskiy --- fs/ubifs/debug.c | 2 +- fs/ubifs/lprops.c | 2 +- fs/ubifs/lpt_commit.c | 4 ++-- fs/ubifs/orphan.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index 01c2b028e525..f25a7339f800 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c @@ -818,7 +818,7 @@ void dbg_dump_leb(const struct ubifs_info *c, int lnum) printk(KERN_DEBUG "(pid %d) start dumping LEB %d\n", current->pid, lnum); - buf = __vmalloc(c->leb_size, GFP_KERNEL | GFP_NOFS, PAGE_KERNEL); + buf = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL); if (!buf) { ubifs_err("cannot allocate memory for dumping LEB %d", lnum); return; diff --git a/fs/ubifs/lprops.c b/fs/ubifs/lprops.c index c7b25e2f7764..0ee0847f2421 100644 --- a/fs/ubifs/lprops.c +++ b/fs/ubifs/lprops.c @@ -1094,7 +1094,7 @@ static int scan_check_cb(struct ubifs_info *c, } } - buf = __vmalloc(c->leb_size, GFP_KERNEL | GFP_NOFS, PAGE_KERNEL); + buf = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL); if (!buf) { ubifs_err("cannot allocate memory to scan LEB %d", lnum); goto out; diff --git a/fs/ubifs/lpt_commit.c b/fs/ubifs/lpt_commit.c index 0a3c2c3f5c4a..0c9c69bd983a 100644 --- a/fs/ubifs/lpt_commit.c +++ b/fs/ubifs/lpt_commit.c @@ -1633,7 +1633,7 @@ static int dbg_check_ltab_lnum(struct ubifs_info *c, int lnum) if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS)) return 0; - buf = p = __vmalloc(c->leb_size, GFP_KERNEL | GFP_NOFS, PAGE_KERNEL); + buf = p = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL); if (!buf) { ubifs_err("cannot allocate memory for ltab checking"); return 0; @@ -1885,7 +1885,7 @@ static void dump_lpt_leb(const struct ubifs_info *c, int lnum) printk(KERN_DEBUG "(pid %d) start dumping LEB %d\n", current->pid, lnum); - buf = p = __vmalloc(c->leb_size, GFP_KERNEL | GFP_NOFS, PAGE_KERNEL); + buf = p = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL); if (!buf) { ubifs_err("cannot allocate memory to dump LPT"); return; diff --git a/fs/ubifs/orphan.c b/fs/ubifs/orphan.c index 2cdbd31641d7..09df318e368f 100644 --- a/fs/ubifs/orphan.c +++ b/fs/ubifs/orphan.c @@ -898,7 +898,7 @@ static int dbg_scan_orphans(struct ubifs_info *c, struct check_info *ci) if (c->no_orphs) return 0; - buf = __vmalloc(c->leb_size, GFP_KERNEL | GFP_NOFS, PAGE_KERNEL); + buf = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL); if (!buf) { ubifs_err("cannot allocate memory to check orphans"); return 0; -- cgit From 9d523cafbe0dab5a2b873ecd85c37fec9d1368f3 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 21 Mar 2011 16:16:29 +0200 Subject: UBIFS: kill CONFIG_UBIFS_FS_DEBUG_CHKS Simplify UBIFS configuration menu and kill the option to enable self-check compile-time. We do not really need this because we can do this run-time using the module parameters or the corresponding sysfs interfaces. And there is a value in simplifying the kernel configuration menu which becomes increasingly large. Signed-off-by: Artem Bityutskiy --- fs/ubifs/Kconfig | 9 --------- 1 file changed, 9 deletions(-) (limited to 'fs') diff --git a/fs/ubifs/Kconfig b/fs/ubifs/Kconfig index 1d1859dc3de5..d7440904be17 100644 --- a/fs/ubifs/Kconfig +++ b/fs/ubifs/Kconfig @@ -58,12 +58,3 @@ config UBIFS_FS_DEBUG down UBIFS. You can then further enable / disable individual debugging features using UBIFS module parameters and the corresponding sysfs interfaces. - -config UBIFS_FS_DEBUG_CHKS - bool "Enable extra checks" - depends on UBIFS_FS_DEBUG - help - If extra checks are enabled UBIFS will check the consistency of its - internal data structures during operation. However, UBIFS performance - is dramatically slower when this option is selected especially if the - file system is large. -- cgit From 6ed09c34b7984a978a73a855f4c2e6662acc8bdb Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 23 Mar 2011 10:32:58 +0200 Subject: UBIFS: fix assertion warning and refine comments This patch fixes the following UBIFS assertion warning: UBIFS assert failed in do_readpage at 115 (pid 199) [] (unwind_backtrace+0x0/0xdc) from [] (do_readpage+0x108/0x594 [ubifs]) [] (do_readpage+0x108/0x594 [ubifs]) from [] (ubifs_write_end+0x1c0/0x2e8 [ubifs]) [] (ubifs_write_end+0x1c0/0x2e8 [ubifs]) from [] (generic_file_buffered_write+0x18c/0x270) [] (generic_file_buffered_write+0x18c/0x270) from [] (__generic_file_aio_write+0x478/0x4c0) [] (__generic_file_aio_write+0x478/0x4c0) from [] (generic_file_aio_write+0x68/0xc8) [] (generic_file_aio_write+0x68/0xc8) from [] (ubifs_aio_write+0x178/0x1d8 [ubifs]) [] (ubifs_aio_write+0x178/0x1d8 [ubifs]) from [] (do_sync_write+0xb0/0x100) [] (do_sync_write+0xb0/0x100) from [] (vfs_write+0xac/0x154) [] (vfs_write+0xac/0x154) from [] (sys_write+0x3c/0x68) [] (sys_write+0x3c/0x68) from [] (ret_fast_syscall+0x0/0x2c) The 'PG_checked' flag is used to indicate that the page does not supposedly exist on the media (e.g., a hole or a page beyond the inode size), so it requires slightly bigger budget, because we have to account the indexing size increase. And this flag basically tells that the budget for this page has to be "new page budget". The "new page budget" is slightly bigger than the "existing page budget". The 'do_readpage()' function has the following assertion which sometimes is hit: 'ubifs_assert(!PageChecked(page))'. Obviously, the meaning of this assertion is: "I should not be asked to read a page which does not exist on the media". However, in 'ubifs_write_begin()' we have a small "trick". Notice, that VFS may write pages which were not read yet, so the page data were not loaded from the media to the page cache yet. If VFS tells that it is going to change only some part of the page, we obviously have to load it from the media. However, if VFS tells that it is going to change whole page, we do not read it from the media for optimization purposes. However, since we do not read it, we do not know if it exists on the media or not (a hole, etc). So we set the 'PG_checked' flag to this page to force bigger budget, just in case. So 'ubifs_write_begin()' sets 'PG_checked'. Then we are in 'ubifs_write_end()'. And VFS tells us: "hey, for some reasons I changed my mind and did not change whole page". Frankly, I do not know why this happens, but I hit this somehow on an ARM platform. And this is extremely rare. So in this case UBIFS does the following: 1. Cancels allocated budget. 2. Loads the page from the media by calling 'do_readpage()'. 3. Asks VFS to repeat the whole write operation from the very beginning (call '->write_begin() again, etc). And the assertion warning is hit at the step 2 - remember we have the 'PG_checked' set for this page, and 'do_readpage()' does not like this. So this patch fixes the problem by adding step 1.5 and cleaning the 'PG_checked' before calling 'do_readpage()'. All in all, this patch does not fix any functionality issue, but it silences UBIFS false positive warning which may happen in very very rare cases. And while on it, this patch also improves a commentary which explains the reasons of setting the 'PG_checked' flag for the page. The old commentary was a bit difficult to understand. Signed-off-by: Artem Bityutskiy --- fs/ubifs/file.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c index d77db7e36484..28be1e6a65e8 100644 --- a/fs/ubifs/file.c +++ b/fs/ubifs/file.c @@ -448,10 +448,12 @@ static int ubifs_write_begin(struct file *file, struct address_space *mapping, if (!(pos & ~PAGE_CACHE_MASK) && len == PAGE_CACHE_SIZE) { /* * We change whole page so no need to load it. But we - * have to set the @PG_checked flag to make the further - * code know that the page is new. This might be not - * true, but it is better to budget more than to read - * the page from the media. + * do not know whether this page exists on the media or + * not, so we assume the latter because it requires + * larger budget. The assumption is that it is better + * to budget a bit more than to read the page from the + * media. Thus, we are setting the @PG_checked flag + * here. */ SetPageChecked(page); skipped_read = 1; @@ -559,6 +561,7 @@ static int ubifs_write_end(struct file *file, struct address_space *mapping, dbg_gen("copied %d instead of %d, read page and repeat", copied, len); cancel_budget(c, page, ui, appending); + ClearPageChecked(page); /* * Return 0 to force VFS to repeat the whole operation, or the -- cgit From e73b83f270828630a9ce33728f6ef61c37a82340 Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Thu, 24 Mar 2011 17:12:23 +0000 Subject: NFS: convert call_sync() to a function This patch changes nfs4_call_sync() from a macro into a static inline function. As a macro, the call_sync() function will not do any type checking and depends on the sequence arguments always having the same name. As a function, we get to have type checking and can rename the arguments if we so choose. Signed-off-by: Bryan Schumaker Signed-off-by: Trond Myklebust --- fs/nfs/nfs4proc.c | 53 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 23 deletions(-) (limited to 'fs') diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 1d84e7088af9..e403d7a84466 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -719,9 +719,16 @@ int _nfs4_call_sync(struct nfs_server *server, return rpc_call_sync(server->client, msg, 0); } -#define nfs4_call_sync(server, msg, args, res, cache_reply) \ - (server)->nfs_client->cl_mvops->call_sync((server), (msg), &(args)->seq_args, \ - &(res)->seq_res, (cache_reply)) +static inline +int nfs4_call_sync(struct nfs_server *server, + struct rpc_message *msg, + struct nfs4_sequence_args *args, + struct nfs4_sequence_res *res, + int cache_reply) +{ + return server->nfs_client->cl_mvops->call_sync(server, msg, args, + res, cache_reply); +} static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo) { @@ -1831,7 +1838,7 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, } else memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid)); - status = nfs4_call_sync(server, &msg, &arg, &res, 1); + status = nfs4_call_sync(server, &msg, &arg.seq_args, &res.seq_res, 1); if (status == 0 && state != NULL) renew_lease(server, timestamp); return status; @@ -2090,7 +2097,7 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f }; int status; - status = nfs4_call_sync(server, &msg, &args, &res, 0); + status = nfs4_call_sync(server, &msg, &args.seq_args, &res.seq_res, 0); if (status == 0) { memcpy(server->attr_bitmask, res.attr_bitmask, sizeof(server->attr_bitmask)); server->caps &= ~(NFS_CAP_ACLS|NFS_CAP_HARDLINKS| @@ -2160,7 +2167,7 @@ static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, }; nfs_fattr_init(info->fattr); - return nfs4_call_sync(server, &msg, &args, &res, 0); + return nfs4_call_sync(server, &msg, &args.seq_args, &res.seq_res, 0); } static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, @@ -2249,7 +2256,7 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, }; nfs_fattr_init(fattr); - return nfs4_call_sync(server, &msg, &args, &res, 0); + return nfs4_call_sync(server, &msg, &args.seq_args, &res.seq_res, 0); } static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr) @@ -2333,7 +2340,7 @@ static int _nfs4_proc_lookupfh(struct nfs_server *server, const struct nfs_fh *d nfs_fattr_init(fattr); dprintk("NFS call lookupfh %s\n", name->name); - status = nfs4_call_sync(server, &msg, &args, &res, 0); + status = nfs4_call_sync(server, &msg, &args.seq_args, &res.seq_res, 0); dprintk("NFS reply lookupfh: %d\n", status); return status; } @@ -2421,7 +2428,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry if (res.fattr == NULL) return -ENOMEM; - status = nfs4_call_sync(server, &msg, &args, &res, 0); + status = nfs4_call_sync(server, &msg, &args.seq_args, &res.seq_res, 0); if (!status) { entry->mask = 0; if (res.access & NFS4_ACCESS_READ) @@ -2488,7 +2495,7 @@ static int _nfs4_proc_readlink(struct inode *inode, struct page *page, .rpc_resp = &res, }; - return nfs4_call_sync(NFS_SERVER(inode), &msg, &args, &res, 0); + return nfs4_call_sync(NFS_SERVER(inode), &msg, &args.seq_args, &res.seq_res, 0); } static int nfs4_proc_readlink(struct inode *inode, struct page *page, @@ -2577,7 +2584,7 @@ static int _nfs4_proc_remove(struct inode *dir, struct qstr *name) if (res.dir_attr == NULL) goto out; - status = nfs4_call_sync(server, &msg, &args, &res, 1); + status = nfs4_call_sync(server, &msg, &args.seq_args, &res.seq_res, 1); if (status == 0) { update_changeattr(dir, &res.cinfo); nfs_post_op_update_inode(dir, res.dir_attr); @@ -2678,7 +2685,7 @@ static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, if (res.old_fattr == NULL || res.new_fattr == NULL) goto out; - status = nfs4_call_sync(server, &msg, &arg, &res, 1); + status = nfs4_call_sync(server, &msg, &arg.seq_args, &res.seq_res, 1); if (!status) { update_changeattr(old_dir, &res.old_cinfo); nfs_post_op_update_inode(old_dir, res.old_fattr); @@ -2729,7 +2736,7 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr * if (res.fattr == NULL || res.dir_attr == NULL) goto out; - status = nfs4_call_sync(server, &msg, &arg, &res, 1); + status = nfs4_call_sync(server, &msg, &arg.seq_args, &res.seq_res, 1); if (!status) { update_changeattr(dir, &res.cinfo); nfs_post_op_update_inode(dir, res.dir_attr); @@ -2793,7 +2800,7 @@ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir, static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_createdata *data) { int status = nfs4_call_sync(NFS_SERVER(dir), &data->msg, - &data->arg, &data->res, 1); + &data->arg.seq_args, &data->res.seq_res, 1); if (status == 0) { update_changeattr(dir, &data->res.dir_cinfo); nfs_post_op_update_inode(dir, data->res.dir_fattr); @@ -2905,7 +2912,7 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, (unsigned long long)cookie); nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args); res.pgbase = args.pgbase; - status = nfs4_call_sync(NFS_SERVER(dir), &msg, &args, &res, 0); + status = nfs4_call_sync(NFS_SERVER(dir), &msg, &args.seq_args, &res.seq_res, 0); if (status >= 0) { memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE); status += args.pgbase; @@ -2997,7 +3004,7 @@ static int _nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, }; nfs_fattr_init(fsstat->fattr); - return nfs4_call_sync(server, &msg, &args, &res, 0); + return nfs4_call_sync(server, &msg, &args.seq_args, &res.seq_res, 0); } static int nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsstat *fsstat) @@ -3028,7 +3035,7 @@ static int _nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, .rpc_resp = &res, }; - return nfs4_call_sync(server, &msg, &args, &res, 0); + return nfs4_call_sync(server, &msg, &args.seq_args, &res.seq_res, 0); } static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo) @@ -3073,7 +3080,7 @@ static int _nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle } nfs_fattr_init(pathconf->fattr); - return nfs4_call_sync(server, &msg, &args, &res, 0); + return nfs4_call_sync(server, &msg, &args.seq_args, &res.seq_res, 0); } static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, @@ -3452,7 +3459,7 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu resp_buf = buf; buf_to_pages(buf, buflen, args.acl_pages, &args.acl_pgbase); } - ret = nfs4_call_sync(NFS_SERVER(inode), &msg, &args, &res, 0); + ret = nfs4_call_sync(NFS_SERVER(inode), &msg, &args.seq_args, &res.seq_res, 0); if (ret) goto out_free; if (res.acl_len > args.acl_len) @@ -3527,7 +3534,7 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl if (i < 0) return i; nfs_inode_return_delegation(inode); - ret = nfs4_call_sync(server, &msg, &arg, &res, 1); + ret = nfs4_call_sync(server, &msg, &arg.seq_args, &res.seq_res, 1); /* * Free each page after tx, so the only ref left is @@ -3890,7 +3897,7 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock lsp = request->fl_u.nfs4_fl.owner; arg.lock_owner.id = lsp->ls_id.id; arg.lock_owner.s_dev = server->s_dev; - status = nfs4_call_sync(server, &msg, &arg, &res, 1); + status = nfs4_call_sync(server, &msg, &arg.seq_args, &res.seq_res, 1); switch (status) { case 0: request->fl_type = F_UNLCK; @@ -4618,7 +4625,7 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, nfs_fattr_init(&fs_locations->fattr); fs_locations->server = server; fs_locations->nlocations = 0; - status = nfs4_call_sync(server, &msg, &args, &res, 0); + status = nfs4_call_sync(server, &msg, &args.seq_args, &res.seq_res, 0); nfs_fixup_referral_attributes(&fs_locations->fattr); dprintk("%s: returned status = %d\n", __func__, status); return status; @@ -5586,7 +5593,7 @@ _nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *pdev) int status; dprintk("--> %s\n", __func__); - status = nfs4_call_sync(server, &msg, &args, &res, 0); + status = nfs4_call_sync(server, &msg, &args.seq_args, &res.seq_res, 0); dprintk("<-- %s status=%d\n", __func__, status); return status; -- cgit From 7c5130588d691a3b34d02312f1bd1b6d56fe0100 Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Thu, 24 Mar 2011 17:12:24 +0000 Subject: NFS: lookup supports alternate client A later patch will need to perform a lookup using an alternate client with a different security flavor. This patch adds support for doing that on NFS v4. Signed-off-by: Bryan Schumaker Signed-off-by: Trond Myklebust --- fs/nfs/dir.c | 6 ++-- fs/nfs/internal.h | 6 ++-- fs/nfs/namespace.c | 2 +- fs/nfs/nfs3proc.c | 2 +- fs/nfs/nfs4_fs.h | 3 +- fs/nfs/nfs4proc.c | 86 +++++++++++++++++++++++++++++------------------------- fs/nfs/proc.c | 2 +- 7 files changed, 59 insertions(+), 48 deletions(-) (limited to 'fs') diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index abdf38d5971d..a83cd0d9dfab 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -1068,7 +1068,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd) if (fhandle == NULL || fattr == NULL) goto out_error; - error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); + error = NFS_PROTO(dir)->lookup(NFS_SERVER(dir)->client, dir, &dentry->d_name, fhandle, fattr); if (error) goto out_bad; if (nfs_compare_fh(NFS_FH(inode), fhandle)) @@ -1224,7 +1224,7 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru parent = dentry->d_parent; /* Protect against concurrent sillydeletes */ nfs_block_sillyrename(parent); - error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); + error = NFS_PROTO(dir)->lookup(NFS_SERVER(dir)->client, dir, &dentry->d_name, fhandle, fattr); if (error == -ENOENT) goto no_entry; if (error < 0) { @@ -1562,7 +1562,7 @@ int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle, if (dentry->d_inode) goto out; if (fhandle->size == 0) { - error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); + error = NFS_PROTO(dir)->lookup(NFS_SERVER(dir)->client, dir, &dentry->d_name, fhandle, fattr); if (error) goto out_error; } diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 72e0bddf7a2f..1ec5d0662ede 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -296,12 +296,14 @@ extern int nfs4_init_client(struct nfs_client *clp, rpc_authflavor_t authflavour, int noresvport); extern void nfs4_reset_write(struct rpc_task *task, struct nfs_write_data *data); -extern int _nfs4_call_sync(struct nfs_server *server, +extern int _nfs4_call_sync(struct rpc_clnt *clnt, + struct nfs_server *server, struct rpc_message *msg, struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, int cache_reply); -extern int _nfs4_call_sync_session(struct nfs_server *server, +extern int _nfs4_call_sync_session(struct rpc_clnt *clnt, + struct nfs_server *server, struct rpc_message *msg, struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index bf1c68009ffd..b02720864ded 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c @@ -153,7 +153,7 @@ struct vfsmount *nfs_d_automount(struct path *path) /* Look it up again to get its attributes */ parent = dget_parent(path->dentry); - err = server->nfs_client->rpc_ops->lookup(parent->d_inode, + err = server->nfs_client->rpc_ops->lookup(server->client, parent->d_inode, &path->dentry->d_name, fh, fattr); dput(parent); diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index d0c80d8b3f96..38053d823eb0 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c @@ -141,7 +141,7 @@ nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, } static int -nfs3_proc_lookup(struct inode *dir, struct qstr *name, +nfs3_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr) { struct nfs3_diropargs arg = { diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index c64be1cff080..72e5f1a2883e 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -57,7 +57,8 @@ enum nfs4_session_state { struct nfs4_minor_version_ops { u32 minor_version; - int (*call_sync)(struct nfs_server *server, + int (*call_sync)(struct rpc_clnt *clnt, + struct nfs_server *server, struct rpc_message *msg, struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index e403d7a84466..448657456b68 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -71,7 +71,9 @@ static int _nfs4_proc_open(struct nfs4_opendata *data); static int _nfs4_recover_proc_open(struct nfs4_opendata *data); static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *); -static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr); +static int _nfs4_proc_lookup(struct rpc_clnt *client, struct inode *dir, + const struct qstr *name, struct nfs_fh *fhandle, + struct nfs_fattr *fattr); static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr); static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, struct nfs_fattr *fattr, struct iattr *sattr, @@ -657,7 +659,8 @@ struct rpc_call_ops nfs41_call_priv_sync_ops = { .rpc_call_done = nfs41_call_sync_done, }; -static int nfs4_call_sync_sequence(struct nfs_server *server, +static int nfs4_call_sync_sequence(struct rpc_clnt *clnt, + struct nfs_server *server, struct rpc_message *msg, struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, @@ -673,7 +676,7 @@ static int nfs4_call_sync_sequence(struct nfs_server *server, .cache_reply = cache_reply, }; struct rpc_task_setup task_setup = { - .rpc_client = server->client, + .rpc_client = clnt, .rpc_message = msg, .callback_ops = &nfs41_call_sync_ops, .callback_data = &data @@ -692,13 +695,14 @@ static int nfs4_call_sync_sequence(struct nfs_server *server, return ret; } -int _nfs4_call_sync_session(struct nfs_server *server, +int _nfs4_call_sync_session(struct rpc_clnt *clnt, + struct nfs_server *server, struct rpc_message *msg, struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, int cache_reply) { - return nfs4_call_sync_sequence(server, msg, args, res, cache_reply, 0); + return nfs4_call_sync_sequence(clnt, server, msg, args, res, cache_reply, 0); } #else @@ -709,25 +713,27 @@ static int nfs4_sequence_done(struct rpc_task *task, } #endif /* CONFIG_NFS_V4_1 */ -int _nfs4_call_sync(struct nfs_server *server, +int _nfs4_call_sync(struct rpc_clnt *clnt, + struct nfs_server *server, struct rpc_message *msg, struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, int cache_reply) { args->sa_session = res->sr_session = NULL; - return rpc_call_sync(server->client, msg, 0); + return rpc_call_sync(clnt, msg, 0); } static inline -int nfs4_call_sync(struct nfs_server *server, +int nfs4_call_sync(struct rpc_clnt *clnt, + struct nfs_server *server, struct rpc_message *msg, struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, int cache_reply) { - return server->nfs_client->cl_mvops->call_sync(server, msg, args, - res, cache_reply); + return server->nfs_client->cl_mvops->call_sync(clnt, server, msg, + args, res, cache_reply); } static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo) @@ -1838,7 +1844,7 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, } else memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid)); - status = nfs4_call_sync(server, &msg, &arg.seq_args, &res.seq_res, 1); + status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); if (status == 0 && state != NULL) renew_lease(server, timestamp); return status; @@ -2097,7 +2103,7 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f }; int status; - status = nfs4_call_sync(server, &msg, &args.seq_args, &res.seq_res, 0); + status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); if (status == 0) { memcpy(server->attr_bitmask, res.attr_bitmask, sizeof(server->attr_bitmask)); server->caps &= ~(NFS_CAP_ACLS|NFS_CAP_HARDLINKS| @@ -2167,7 +2173,7 @@ static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, }; nfs_fattr_init(info->fattr); - return nfs4_call_sync(server, &msg, &args.seq_args, &res.seq_res, 0); + return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); } static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, @@ -2256,7 +2262,7 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, }; nfs_fattr_init(fattr); - return nfs4_call_sync(server, &msg, &args.seq_args, &res.seq_res, 0); + return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); } static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr) @@ -2316,9 +2322,9 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, return status; } -static int _nfs4_proc_lookupfh(struct nfs_server *server, const struct nfs_fh *dirfh, - const struct qstr *name, struct nfs_fh *fhandle, - struct nfs_fattr *fattr) +static int _nfs4_proc_lookupfh(struct rpc_clnt *clnt, struct nfs_server *server, + const struct nfs_fh *dirfh, const struct qstr *name, + struct nfs_fh *fhandle, struct nfs_fattr *fattr) { int status; struct nfs4_lookup_arg args = { @@ -2340,7 +2346,7 @@ static int _nfs4_proc_lookupfh(struct nfs_server *server, const struct nfs_fh *d nfs_fattr_init(fattr); dprintk("NFS call lookupfh %s\n", name->name); - status = nfs4_call_sync(server, &msg, &args.seq_args, &res.seq_res, 0); + status = nfs4_call_sync(clnt, server, &msg, &args.seq_args, &res.seq_res, 0); dprintk("NFS reply lookupfh: %d\n", status); return status; } @@ -2352,7 +2358,7 @@ static int nfs4_proc_lookupfh(struct nfs_server *server, struct nfs_fh *dirfh, struct nfs4_exception exception = { }; int err; do { - err = _nfs4_proc_lookupfh(server, dirfh, name, fhandle, fattr); + err = _nfs4_proc_lookupfh(server->client, server, dirfh, name, fhandle, fattr); /* FIXME: !!!! */ if (err == -NFS4ERR_MOVED) { err = -EREMOTE; @@ -2363,26 +2369,28 @@ static int nfs4_proc_lookupfh(struct nfs_server *server, struct nfs_fh *dirfh, return err; } -static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name, - struct nfs_fh *fhandle, struct nfs_fattr *fattr) +static int _nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, + const struct qstr *name, struct nfs_fh *fhandle, + struct nfs_fattr *fattr) { int status; dprintk("NFS call lookup %s\n", name->name); - status = _nfs4_proc_lookupfh(NFS_SERVER(dir), NFS_FH(dir), name, fhandle, fattr); + status = _nfs4_proc_lookupfh(clnt, NFS_SERVER(dir), NFS_FH(dir), name, fhandle, fattr); if (status == -NFS4ERR_MOVED) status = nfs4_get_referral(dir, name, fattr, fhandle); dprintk("NFS reply lookup: %d\n", status); return status; } -static int nfs4_proc_lookup(struct inode *dir, struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr) +static int nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, struct qstr *name, + struct nfs_fh *fhandle, struct nfs_fattr *fattr) { struct nfs4_exception exception = { }; int err; do { err = nfs4_handle_exception(NFS_SERVER(dir), - _nfs4_proc_lookup(dir, name, fhandle, fattr), + _nfs4_proc_lookup(clnt, dir, name, fhandle, fattr), &exception); } while (exception.retry); return err; @@ -2428,7 +2436,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry if (res.fattr == NULL) return -ENOMEM; - status = nfs4_call_sync(server, &msg, &args.seq_args, &res.seq_res, 0); + status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); if (!status) { entry->mask = 0; if (res.access & NFS4_ACCESS_READ) @@ -2495,7 +2503,7 @@ static int _nfs4_proc_readlink(struct inode *inode, struct page *page, .rpc_resp = &res, }; - return nfs4_call_sync(NFS_SERVER(inode), &msg, &args.seq_args, &res.seq_res, 0); + return nfs4_call_sync(NFS_SERVER(inode)->client, NFS_SERVER(inode), &msg, &args.seq_args, &res.seq_res, 0); } static int nfs4_proc_readlink(struct inode *inode, struct page *page, @@ -2584,7 +2592,7 @@ static int _nfs4_proc_remove(struct inode *dir, struct qstr *name) if (res.dir_attr == NULL) goto out; - status = nfs4_call_sync(server, &msg, &args.seq_args, &res.seq_res, 1); + status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 1); if (status == 0) { update_changeattr(dir, &res.cinfo); nfs_post_op_update_inode(dir, res.dir_attr); @@ -2685,7 +2693,7 @@ static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, if (res.old_fattr == NULL || res.new_fattr == NULL) goto out; - status = nfs4_call_sync(server, &msg, &arg.seq_args, &res.seq_res, 1); + status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); if (!status) { update_changeattr(old_dir, &res.old_cinfo); nfs_post_op_update_inode(old_dir, res.old_fattr); @@ -2736,7 +2744,7 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr * if (res.fattr == NULL || res.dir_attr == NULL) goto out; - status = nfs4_call_sync(server, &msg, &arg.seq_args, &res.seq_res, 1); + status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); if (!status) { update_changeattr(dir, &res.cinfo); nfs_post_op_update_inode(dir, res.dir_attr); @@ -2799,7 +2807,7 @@ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir, static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_createdata *data) { - int status = nfs4_call_sync(NFS_SERVER(dir), &data->msg, + int status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &data->msg, &data->arg.seq_args, &data->res.seq_res, 1); if (status == 0) { update_changeattr(dir, &data->res.dir_cinfo); @@ -2912,7 +2920,7 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, (unsigned long long)cookie); nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args); res.pgbase = args.pgbase; - status = nfs4_call_sync(NFS_SERVER(dir), &msg, &args.seq_args, &res.seq_res, 0); + status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &msg, &args.seq_args, &res.seq_res, 0); if (status >= 0) { memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE); status += args.pgbase; @@ -3004,7 +3012,7 @@ static int _nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, }; nfs_fattr_init(fsstat->fattr); - return nfs4_call_sync(server, &msg, &args.seq_args, &res.seq_res, 0); + return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); } static int nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsstat *fsstat) @@ -3035,7 +3043,7 @@ static int _nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, .rpc_resp = &res, }; - return nfs4_call_sync(server, &msg, &args.seq_args, &res.seq_res, 0); + return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); } static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo) @@ -3080,7 +3088,7 @@ static int _nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle } nfs_fattr_init(pathconf->fattr); - return nfs4_call_sync(server, &msg, &args.seq_args, &res.seq_res, 0); + return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); } static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, @@ -3459,7 +3467,7 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu resp_buf = buf; buf_to_pages(buf, buflen, args.acl_pages, &args.acl_pgbase); } - ret = nfs4_call_sync(NFS_SERVER(inode), &msg, &args.seq_args, &res.seq_res, 0); + ret = nfs4_call_sync(NFS_SERVER(inode)->client, NFS_SERVER(inode), &msg, &args.seq_args, &res.seq_res, 0); if (ret) goto out_free; if (res.acl_len > args.acl_len) @@ -3534,7 +3542,7 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl if (i < 0) return i; nfs_inode_return_delegation(inode); - ret = nfs4_call_sync(server, &msg, &arg.seq_args, &res.seq_res, 1); + ret = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); /* * Free each page after tx, so the only ref left is @@ -3897,7 +3905,7 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock lsp = request->fl_u.nfs4_fl.owner; arg.lock_owner.id = lsp->ls_id.id; arg.lock_owner.s_dev = server->s_dev; - status = nfs4_call_sync(server, &msg, &arg.seq_args, &res.seq_res, 1); + status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); switch (status) { case 0: request->fl_type = F_UNLCK; @@ -4625,7 +4633,7 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, nfs_fattr_init(&fs_locations->fattr); fs_locations->server = server; fs_locations->nlocations = 0; - status = nfs4_call_sync(server, &msg, &args.seq_args, &res.seq_res, 0); + status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); nfs_fixup_referral_attributes(&fs_locations->fattr); dprintk("%s: returned status = %d\n", __func__, status); return status; @@ -5593,7 +5601,7 @@ _nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *pdev) int status; dprintk("--> %s\n", __func__); - status = nfs4_call_sync(server, &msg, &args.seq_args, &res.seq_res, 0); + status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); dprintk("<-- %s status=%d\n", __func__, status); return status; diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index b8ec170f2a0f..ac40b8535d7e 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c @@ -177,7 +177,7 @@ nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, } static int -nfs_proc_lookup(struct inode *dir, struct qstr *name, +nfs_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr) { struct nfs_diropargs arg = { -- cgit From 5a5ea0d485c9715c86bf858bbdc5f6d373b3db88 Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Thu, 24 Mar 2011 17:12:29 +0000 Subject: NFS: Add secinfo procedure This patch adds the nfs4 operation secinfo as a valid nfs rpc operation. Signed-off-by: Bryan Schumaker Signed-off-by: Trond Myklebust --- fs/nfs/nfs4proc.c | 35 ++++++++++++++ fs/nfs/nfs4xdr.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 170 insertions(+) (limited to 'fs') diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 448657456b68..0b8bae119976 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -4639,6 +4639,40 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, return status; } +static int _nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct nfs4_secinfo_flavors *flavors) +{ + int status; + struct nfs4_secinfo_arg args = { + .dir_fh = NFS_FH(dir), + .name = name, + }; + struct nfs4_secinfo_res res = { + .flavors = flavors, + }; + struct rpc_message msg = { + .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SECINFO], + .rpc_argp = &args, + .rpc_resp = &res, + }; + + dprintk("NFS call secinfo %s\n", name->name); + status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &msg, &args.seq_args, &res.seq_res, 0); + dprintk("NFS reply secinfo: %d\n", status); + return status; +} + +int nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct nfs4_secinfo_flavors *flavors) +{ + struct nfs4_exception exception = { }; + int err; + do { + err = nfs4_handle_exception(NFS_SERVER(dir), + _nfs4_proc_secinfo(dir, name, flavors), + &exception); + } while (exception.retry); + return err; +} + #ifdef CONFIG_NFS_V4_1 /* * Check the exchange flags returned by the server for invalid flags, having @@ -5756,6 +5790,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = { .close_context = nfs4_close_context, .open_context = nfs4_atomic_open, .init_client = nfs4_init_client, + .secinfo = nfs4_proc_secinfo, }; static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = { diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 0cf560f77884..98afcf947aa4 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -253,6 +254,8 @@ static int nfs4_stat_to_errno(int); (encode_getattr_maxsz) #define decode_fs_locations_maxsz \ (0) +#define encode_secinfo_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz) +#define decode_secinfo_maxsz (op_decode_hdr_maxsz + 4 + (NFS_MAX_SECFLAVORS * (16 + GSS_OID_MAX_LEN))) #if defined(CONFIG_NFS_V4_1) #define NFS4_MAX_MACHINE_NAME_LEN (64) @@ -676,6 +679,14 @@ static int nfs4_stat_to_errno(int); decode_putfh_maxsz + \ decode_lookup_maxsz + \ decode_fs_locations_maxsz) +#define NFS4_enc_secinfo_sz (compound_encode_hdr_maxsz + \ + encode_sequence_maxsz + \ + encode_putfh_maxsz + \ + encode_secinfo_maxsz) +#define NFS4_dec_secinfo_sz (compound_decode_hdr_maxsz + \ + decode_sequence_maxsz + \ + decode_putfh_maxsz + \ + decode_secinfo_maxsz) #if defined(CONFIG_NFS_V4_1) #define NFS4_enc_exchange_id_sz \ (compound_encode_hdr_maxsz + \ @@ -1620,6 +1631,18 @@ static void encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *state hdr->replen += decode_delegreturn_maxsz; } +static void encode_secinfo(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) +{ + int len = name->len; + __be32 *p; + + p = reserve_space(xdr, 8 + len); + *p++ = cpu_to_be32(OP_SECINFO); + xdr_encode_opaque(p, name->name, len); + hdr->nops++; + hdr->replen += decode_secinfo_maxsz; +} + #if defined(CONFIG_NFS_V4_1) /* NFSv4.1 operations */ static void encode_exchange_id(struct xdr_stream *xdr, @@ -2465,6 +2488,24 @@ static void nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, encode_nops(&hdr); } +/* + * Encode SECINFO request + */ +static void nfs4_xdr_enc_secinfo(struct rpc_rqst *req, + struct xdr_stream *xdr, + struct nfs4_secinfo_arg *args) +{ + struct compound_hdr hdr = { + .minorversion = nfs4_xdr_minorversion(&args->seq_args), + }; + + encode_compound_hdr(xdr, req, &hdr); + encode_sequence(xdr, &args->seq_args, &hdr); + encode_putfh(xdr, args->dir_fh, &hdr); + encode_secinfo(xdr, args->name, &hdr); + encode_nops(&hdr); +} + #if defined(CONFIG_NFS_V4_1) /* * EXCHANGE_ID request @@ -4680,6 +4721,73 @@ static int decode_delegreturn(struct xdr_stream *xdr) return decode_op_hdr(xdr, OP_DELEGRETURN); } +static int decode_secinfo_gss(struct xdr_stream *xdr, struct nfs4_secinfo_flavor *flavor) +{ + __be32 *p; + + p = xdr_inline_decode(xdr, 4); + if (unlikely(!p)) + goto out_overflow; + flavor->gss.sec_oid4.len = be32_to_cpup(p); + if (flavor->gss.sec_oid4.len > GSS_OID_MAX_LEN) + goto out_err; + + p = xdr_inline_decode(xdr, flavor->gss.sec_oid4.len); + if (unlikely(!p)) + goto out_overflow; + memcpy(flavor->gss.sec_oid4.data, p, flavor->gss.sec_oid4.len); + + p = xdr_inline_decode(xdr, 8); + if (unlikely(!p)) + goto out_overflow; + flavor->gss.qop4 = be32_to_cpup(p++); + flavor->gss.service = be32_to_cpup(p); + + return 0; + +out_overflow: + print_overflow_msg(__func__, xdr); + return -EIO; +out_err: + return -EINVAL; +} + +static int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res) +{ + struct nfs4_secinfo_flavor *sec_flavor; + int status; + __be32 *p; + int i; + + status = decode_op_hdr(xdr, OP_SECINFO); + p = xdr_inline_decode(xdr, 4); + if (unlikely(!p)) + goto out_overflow; + res->flavors->num_flavors = be32_to_cpup(p); + + for (i = 0; i < res->flavors->num_flavors; i++) { + sec_flavor = &res->flavors->flavors[i]; + if ((char *)&sec_flavor[1] - (char *)res > PAGE_SIZE) + break; + + p = xdr_inline_decode(xdr, 4); + if (unlikely(!p)) + goto out_overflow; + sec_flavor->flavor = be32_to_cpup(p); + + if (sec_flavor->flavor == RPC_AUTH_GSS) { + if (decode_secinfo_gss(xdr, sec_flavor)) + break; + } + } + + return 0; + +out_overflow: + print_overflow_msg(__func__, xdr); + return -EIO; +} + #if defined(CONFIG_NFS_V4_1) static int decode_exchange_id(struct xdr_stream *xdr, struct nfs41_exchange_id_res *res) @@ -5919,6 +6027,32 @@ out: return status; } +/* + * Decode SECINFO response + */ +static int nfs4_xdr_dec_secinfo(struct rpc_rqst *rqstp, + struct xdr_stream *xdr, + struct nfs4_secinfo_res *res) +{ + struct compound_hdr hdr; + int status; + + status = decode_compound_hdr(xdr, &hdr); + if (status) + goto out; + status = decode_sequence(xdr, &res->seq_res, rqstp); + if (status) + goto out; + status = decode_putfh(xdr); + if (status) + goto out; + status = decode_secinfo(xdr, res); + if (status) + goto out; +out: + return status; +} + #if defined(CONFIG_NFS_V4_1) /* * Decode EXCHANGE_ID response @@ -6258,6 +6392,7 @@ struct rpc_procinfo nfs4_procedures[] = { PROC(SETACL, enc_setacl, dec_setacl), PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations), PROC(RELEASE_LOCKOWNER, enc_release_lockowner, dec_release_lockowner), + PROC(SECINFO, enc_secinfo, dec_secinfo), #if defined(CONFIG_NFS_V4_1) PROC(EXCHANGE_ID, enc_exchange_id, dec_exchange_id), PROC(CREATE_SESSION, enc_create_session, dec_create_session), -- cgit From 7ebb931598cd95cccea10d4bc4c0123a464ea565 Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Thu, 24 Mar 2011 17:12:30 +0000 Subject: NFS: use secinfo when crossing mountpoints A submount may use different security than the parent mount does. We should figure out what sec flavor the submount uses at mount time. Signed-off-by: Bryan Schumaker Signed-off-by: Trond Myklebust --- fs/nfs/inode.c | 8 ++-- fs/nfs/internal.h | 7 ++++ fs/nfs/namespace.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++-- fs/nfs/nfs4proc.c | 14 +++++++ fs/nfs/nfs4xdr.c | 11 +++--- 5 files changed, 142 insertions(+), 11 deletions(-) (limited to 'fs') diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 01768e5e2c9b..058d7d63e566 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -254,7 +254,9 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) struct inode *inode = ERR_PTR(-ENOENT); unsigned long hash; - if ((fattr->valid & NFS_ATTR_FATTR_FILEID) == 0) + nfs_attr_check_mountpoint(sb, fattr); + + if ((fattr->valid & NFS_ATTR_FATTR_FILEID) == 0 && (fattr->valid & NFS_ATTR_FATTR_MOUNTPOINT) == 0) goto out_no_inode; if ((fattr->valid & NFS_ATTR_FATTR_TYPE) == 0) goto out_no_inode; @@ -298,8 +300,8 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS)) set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags); /* Deal with crossing mountpoints */ - if ((fattr->valid & NFS_ATTR_FATTR_FSID) - && !nfs_fsid_equal(&NFS_SB(sb)->fsid, &fattr->fsid)) { + if (fattr->valid & NFS_ATTR_FATTR_MOUNTPOINT || + fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) { if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) inode->i_op = &nfs_referral_inode_operations; else diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 1ec5d0662ede..345d86b90e26 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -39,6 +39,12 @@ static inline int nfs4_has_persistent_session(const struct nfs_client *clp) return 0; } +static inline void nfs_attr_check_mountpoint(struct super_block *parent, struct nfs_fattr *fattr) +{ + if (!nfs_fsid_equal(&NFS_SB(parent)->fsid, &fattr->fsid)) + fattr->valid |= NFS_ATTR_FATTR_MOUNTPOINT; +} + struct nfs_clone_mount { const struct super_block *sb; const struct dentry *dentry; @@ -214,6 +220,7 @@ extern const u32 nfs41_maxwrite_overhead; /* nfs4proc.c */ #ifdef CONFIG_NFS_V4 extern struct rpc_procinfo nfs4_procedures[]; +void nfs_fixup_secinfo_attributes(struct nfs_fattr *, struct nfs_fh *); #endif extern int nfs4_init_ds_session(struct nfs_client *clp); diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index b02720864ded..ad92bf731ff5 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "internal.h" #define NFSDBG_FACILITY NFSDBG_VFS @@ -27,7 +28,8 @@ int nfs_mountpoint_expiry_timeout = 500 * HZ; static struct vfsmount *nfs_do_submount(struct dentry *dentry, struct nfs_fh *fh, - struct nfs_fattr *fattr); + struct nfs_fattr *fattr, + rpc_authflavor_t authflavor); /* * nfs_path - reconstruct the path given an arbitrary dentry @@ -116,6 +118,100 @@ Elong: return ERR_PTR(-ENAMETOOLONG); } +#ifdef CONFIG_NFS_V4 +static rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors, struct inode *inode) +{ + struct gss_api_mech *mech; + struct xdr_netobj oid; + int i; + rpc_authflavor_t pseudoflavor = RPC_AUTH_UNIX; + + for (i = 0; i < flavors->num_flavors; i++) { + struct nfs4_secinfo_flavor *flavor; + flavor = &flavors->flavors[i]; + + if (flavor->flavor == RPC_AUTH_NULL || flavor->flavor == RPC_AUTH_UNIX) { + pseudoflavor = flavor->flavor; + break; + } else if (flavor->flavor == RPC_AUTH_GSS) { + oid.len = flavor->gss.sec_oid4.len; + oid.data = flavor->gss.sec_oid4.data; + mech = gss_mech_get_by_OID(&oid); + if (!mech) + continue; + pseudoflavor = gss_svc_to_pseudoflavor(mech, flavor->gss.service); + gss_mech_put(mech); + break; + } + } + + return pseudoflavor; +} + +static rpc_authflavor_t nfs_negotiate_security(const struct dentry *parent, const struct dentry *dentry) +{ + int status = 0; + struct page *page; + struct nfs4_secinfo_flavors *flavors; + int (*secinfo)(struct inode *, const struct qstr *, struct nfs4_secinfo_flavors *); + rpc_authflavor_t flavor = RPC_AUTH_UNIX; + + secinfo = NFS_PROTO(parent->d_inode)->secinfo; + if (secinfo != NULL) { + page = alloc_page(GFP_KERNEL); + if (!page) { + status = -ENOMEM; + goto out; + } + flavors = page_address(page); + status = secinfo(parent->d_inode, &dentry->d_name, flavors); + flavor = nfs_find_best_sec(flavors, dentry->d_inode); + put_page(page); + } + + return flavor; + +out: + status = -ENOMEM; + return status; +} + +static rpc_authflavor_t nfs_lookup_with_sec(struct nfs_server *server, struct dentry *parent, + struct dentry *dentry, struct path *path, + struct nfs_fh *fh, struct nfs_fattr *fattr) +{ + rpc_authflavor_t flavor; + struct rpc_clnt *clone; + struct rpc_auth *auth; + int err; + + flavor = nfs_negotiate_security(parent, path->dentry); + if (flavor < 0) + goto out; + clone = rpc_clone_client(server->client); + auth = rpcauth_create(flavor, clone); + if (!auth) { + flavor = -EIO; + goto out; + } + err = server->nfs_client->rpc_ops->lookup(clone, parent->d_inode, + &path->dentry->d_name, + fh, fattr); + if (err < 0) + flavor = err; +out: + return flavor; +} +#else /* CONFIG_NFS_V4 */ +static inline rpc_authflavor_t nfs_lookup_with_sec(struct nfs_server *server, + struct dentry *parent, struct dentry *dentry, + struct path *path, struct nfs_fh *fh, + struct nfs_fattr *fattr) +{ + return -EPERM; +} +#endif /* CONFIG_NFS_V4 */ + /* * nfs_d_automount - Handle crossing a mountpoint on the server * @path - The mountpoint @@ -136,6 +232,7 @@ struct vfsmount *nfs_d_automount(struct path *path) struct nfs_fh *fh = NULL; struct nfs_fattr *fattr = NULL; int err; + rpc_authflavor_t flavor = 1; dprintk("--> nfs_d_automount()\n"); @@ -156,6 +253,13 @@ struct vfsmount *nfs_d_automount(struct path *path) err = server->nfs_client->rpc_ops->lookup(server->client, parent->d_inode, &path->dentry->d_name, fh, fattr); + if (err == -EPERM) { + flavor = nfs_lookup_with_sec(server, parent, path->dentry, path, fh, fattr); + if (flavor < 0) + err = flavor; + else + err = 0; + } dput(parent); if (err != 0) { mnt = ERR_PTR(err); @@ -165,7 +269,7 @@ struct vfsmount *nfs_d_automount(struct path *path) if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) mnt = nfs_do_refmount(path->dentry); else - mnt = nfs_do_submount(path->dentry, fh, fattr); + mnt = nfs_do_submount(path->dentry, fh, fattr, flavor); if (IS_ERR(mnt)) goto out; @@ -232,17 +336,20 @@ static struct vfsmount *nfs_do_clone_mount(struct nfs_server *server, * @dentry - parent directory * @fh - filehandle for new root dentry * @fattr - attributes for new root inode + * @authflavor - security flavor to use when performing the mount * */ static struct vfsmount *nfs_do_submount(struct dentry *dentry, struct nfs_fh *fh, - struct nfs_fattr *fattr) + struct nfs_fattr *fattr, + rpc_authflavor_t authflavor) { struct nfs_clone_mount mountdata = { .sb = dentry->d_sb, .dentry = dentry, .fh = fh, .fattr = fattr, + .authflavor = authflavor, }; struct vfsmount *mnt = ERR_PTR(-ENOMEM); char *page = (char *) __get_free_page(GFP_USER); diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 0b8bae119976..563463777d9d 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -87,6 +87,8 @@ static int nfs4_map_errors(int err) switch (err) { case -NFS4ERR_RESOURCE: return -EREMOTEIO; + case -NFS4ERR_WRONGSEC: + return -EPERM; case -NFS4ERR_BADOWNER: case -NFS4ERR_BADNAME: return -EINVAL; @@ -2383,6 +2385,16 @@ static int _nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, return status; } +void nfs_fixup_secinfo_attributes(struct nfs_fattr *fattr, struct nfs_fh *fh) +{ + memset(fh, 0, sizeof(struct nfs_fh)); + fattr->fsid.major = 1; + fattr->valid |= NFS_ATTR_FATTR_TYPE | NFS_ATTR_FATTR_MODE | + NFS_ATTR_FATTR_NLINK | NFS_ATTR_FATTR_FSID | NFS_ATTR_FATTR_MOUNTPOINT; + fattr->mode = S_IFDIR | S_IRUGO | S_IXUGO; + fattr->nlink = 2; +} + static int nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr) { @@ -2392,6 +2404,8 @@ static int nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, struct qst err = nfs4_handle_exception(NFS_SERVER(dir), _nfs4_proc_lookup(clnt, dir, name, fhandle, fattr), &exception); + if (err == -EPERM) + nfs_fixup_secinfo_attributes(fattr, fhandle); } while (exception.retry); return err; } diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 98afcf947aa4..21c3004b72d5 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -113,7 +113,7 @@ static int nfs4_stat_to_errno(int); #define encode_restorefh_maxsz (op_encode_hdr_maxsz) #define decode_restorefh_maxsz (op_decode_hdr_maxsz) #define encode_fsinfo_maxsz (encode_getattr_maxsz) -#define decode_fsinfo_maxsz (op_decode_hdr_maxsz + 11) +#define decode_fsinfo_maxsz (op_decode_hdr_maxsz + 15) #define encode_renew_maxsz (op_encode_hdr_maxsz + 3) #define decode_renew_maxsz (op_decode_hdr_maxsz) #define encode_setclientid_maxsz \ @@ -2966,6 +2966,7 @@ static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap) if (unlikely(!p)) goto out_overflow; bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR; + return -be32_to_cpup(p); } return 0; out_overflow: @@ -3953,6 +3954,10 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, fattr->valid |= status; status = decode_attr_error(xdr, bitmap); + if (status == -NFS4ERR_WRONGSEC) { + nfs_fixup_secinfo_attributes(fattr, fh); + status = 0; + } if (status < 0) goto xdr_error; @@ -6314,10 +6319,6 @@ static struct { { NFS4ERR_SYMLINK, -ELOOP }, { NFS4ERR_OP_ILLEGAL, -EOPNOTSUPP }, { NFS4ERR_DEADLOCK, -EDEADLK }, - { NFS4ERR_WRONGSEC, -EPERM }, /* FIXME: this needs - * to be handled by a - * middle-layer. - */ { -1, -EIO } }; -- cgit From 8f70e95f9f4159184f557a1db60c909d7c1bd2e3 Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Thu, 24 Mar 2011 17:12:31 +0000 Subject: NFS: Determine initial mount security When sec= is not presented as a mount option, we should attempt to determine what security flavor the server is using. Signed-off-by: Bryan Schumaker Signed-off-by: Trond Myklebust --- fs/nfs/nfs4proc.c | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 563463777d9d..f9150f03d640 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -2191,15 +2192,43 @@ static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, return err; } +static int nfs4_lookup_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, + struct nfs_fsinfo *info, rpc_authflavor_t flavor) +{ + struct rpc_auth *auth; + int ret; + + auth = rpcauth_create(flavor, server->client); + if (!auth) { + ret = -EIO; + goto out; + } + ret = nfs4_lookup_root(server, fhandle, info); + if (ret < 0) + ret = -EAGAIN; +out: + return ret; +} + /* * get the file handle for the "/" directory on the server */ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *info) { - int status; + int i, len, status = 0; + rpc_authflavor_t flav_array[NFS_MAX_SECFLAVORS + 2]; - status = nfs4_lookup_root(server, fhandle, info); + flav_array[0] = RPC_AUTH_UNIX; + len = gss_mech_list_pseudoflavors(&flav_array[1]); + flav_array[1+len] = RPC_AUTH_NULL; + len += 2; + + for (i = 0; i < len; i++) { + status = nfs4_lookup_root_sec(server, fhandle, info, flav_array[i]); + if (status == 0) + break; + } if (status == 0) status = nfs4_server_capabilities(server, fhandle); if (status == 0) -- cgit From 62a7375e5d77d654695297c4b39d5d740d901184 Mon Sep 17 00:00:00 2001 From: Ian Kent Date: Fri, 25 Mar 2011 01:51:02 +0800 Subject: vfs - check non-mountpoint dentry might block in __follow_mount_rcu() When following a mount in rcu-walk mode we must check if the incoming dentry is telling us it may need to block, even if it isn't actually a mountpoint. Signed-off-by: Ian Kent Signed-off-by: Al Viro --- fs/namei.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/namei.c b/fs/namei.c index d0066e17d45d..3cb616d38d9c 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -992,6 +992,12 @@ int follow_down_one(struct path *path) return 0; } +static inline bool managed_dentry_might_block(struct dentry *dentry) +{ + return (dentry->d_flags & DCACHE_MANAGE_TRANSIT && + dentry->d_op->d_manage(dentry, true) < 0); +} + /* * Skip to top of mountpoint pile in rcuwalk mode. We abort the rcu-walk if we * meet a managed dentry and we're not walking to "..". True is returned to @@ -1000,19 +1006,26 @@ int follow_down_one(struct path *path) static bool __follow_mount_rcu(struct nameidata *nd, struct path *path, struct inode **inode, bool reverse_transit) { - while (d_mountpoint(path->dentry)) { + for (;;) { struct vfsmount *mounted; - if (unlikely(path->dentry->d_flags & DCACHE_MANAGE_TRANSIT) && - !reverse_transit && - path->dentry->d_op->d_manage(path->dentry, true) < 0) + /* + * Don't forget we might have a non-mountpoint managed dentry + * that wants to block transit. + */ + *inode = path->dentry->d_inode; + if (!reverse_transit && + unlikely(managed_dentry_might_block(path->dentry))) return false; + + if (!d_mountpoint(path->dentry)) + break; + mounted = __lookup_mnt(path->mnt, path->dentry, 1); if (!mounted) break; path->mnt = mounted; path->dentry = mounted->mnt_root; nd->seq = read_seqcount_begin(&path->dentry->d_seq); - *inode = path->dentry->d_inode; } if (unlikely(path->dentry->d_flags & DCACHE_NEED_AUTOMOUNT)) -- cgit From 3c3199852905ceb90a70e98777e71d369a5f0823 Mon Sep 17 00:00:00 2001 From: Ian Kent Date: Fri, 25 Mar 2011 01:51:08 +0800 Subject: autofs4 - reinstate last used update on access When direct (and offset) mounts were introduced the the last used timeout could no longer be updated in ->d_revalidate(). This is because covered direct mounts would be followed over without calling the autofs file system. As a result the definition of the busyness check for all entries was changed to be "actually busy" being an open file or working directory within the automount. But now we have a call back in the follow so the last used update on any access can be re-instated. This requires DCACHE_MANAGE_TRANSIT to always be set. Signed-off-by: Ian Kent Signed-off-by: Al Viro --- fs/autofs4/expire.c | 13 ++----------- fs/autofs4/root.c | 35 ++++++++++++----------------------- 2 files changed, 14 insertions(+), 34 deletions(-) (limited to 'fs') diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c index f43100b9662b..c896dd6c1ea9 100644 --- a/fs/autofs4/expire.c +++ b/fs/autofs4/expire.c @@ -294,7 +294,6 @@ struct dentry *autofs4_expire_direct(struct super_block *sb, spin_unlock(&sbi->fs_lock); return NULL; } - managed_dentry_set_transit(root); if (!autofs4_direct_busy(mnt, root, timeout, do_now)) { struct autofs_info *ino = autofs4_dentry_ino(root); ino->flags |= AUTOFS_INF_EXPIRING; @@ -302,7 +301,6 @@ struct dentry *autofs4_expire_direct(struct super_block *sb, spin_unlock(&sbi->fs_lock); return root; } - managed_dentry_clear_transit(root); spin_unlock(&sbi->fs_lock); dput(root); @@ -341,8 +339,7 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb, ino = autofs4_dentry_ino(dentry); /* No point expiring a pending mount */ if (ino->flags & AUTOFS_INF_PENDING) - goto cont; - managed_dentry_set_transit(dentry); + goto next; /* * Case 1: (i) indirect mount or top level pseudo direct mount @@ -402,8 +399,6 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb, } } next: - managed_dentry_clear_transit(dentry); -cont: spin_unlock(&sbi->fs_lock); } return NULL; @@ -484,8 +479,6 @@ int autofs4_expire_run(struct super_block *sb, spin_lock(&sbi->fs_lock); ino = autofs4_dentry_ino(dentry); ino->flags &= ~AUTOFS_INF_EXPIRING; - if (!d_unhashed(dentry)) - managed_dentry_clear_transit(dentry); complete_all(&ino->expire_complete); spin_unlock(&sbi->fs_lock); @@ -513,9 +506,7 @@ int autofs4_do_expire_multi(struct super_block *sb, struct vfsmount *mnt, spin_lock(&sbi->fs_lock); ino->flags &= ~AUTOFS_INF_EXPIRING; spin_lock(&dentry->d_lock); - if (ret) - __managed_dentry_clear_transit(dentry); - else { + if (!ret) { if ((IS_ROOT(dentry) || (autofs_type_indirect(sbi->type) && IS_ROOT(dentry->d_parent))) && diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index e6f84d26f4cf..3a93d3552486 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c @@ -275,17 +275,16 @@ static int autofs4_mount_wait(struct dentry *dentry) { struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); struct autofs_info *ino = autofs4_dentry_ino(dentry); - int status; + int status = 0; if (ino->flags & AUTOFS_INF_PENDING) { DPRINTK("waiting for mount name=%.*s", dentry->d_name.len, dentry->d_name.name); status = autofs4_wait(sbi, dentry, NFY_MOUNT); DPRINTK("mount wait done status=%d", status); - ino->last_used = jiffies; - return status; } - return 0; + ino->last_used = jiffies; + return status; } static int do_expire_wait(struct dentry *dentry) @@ -319,9 +318,12 @@ static struct dentry *autofs4_mountpoint_changed(struct path *path) */ if (autofs_type_indirect(sbi->type) && d_unhashed(dentry)) { struct dentry *parent = dentry->d_parent; + struct autofs_info *ino; struct dentry *new = d_lookup(parent, &dentry->d_name); if (!new) return NULL; + ino = autofs4_dentry_ino(new); + ino->last_used = jiffies; dput(path->dentry); path->dentry = new; } @@ -338,18 +340,6 @@ static struct vfsmount *autofs4_d_automount(struct path *path) DPRINTK("dentry=%p %.*s", dentry, dentry->d_name.len, dentry->d_name.name); - /* - * Someone may have manually umounted this or it was a submount - * that has gone away. - */ - spin_lock(&dentry->d_lock); - if (!d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) { - if (!(dentry->d_flags & DCACHE_MANAGE_TRANSIT) && - (dentry->d_flags & DCACHE_NEED_AUTOMOUNT)) - __managed_dentry_set_transit(path->dentry); - } - spin_unlock(&dentry->d_lock); - /* The daemon never triggers a mount. */ if (autofs4_oz_mode(sbi)) return NULL; @@ -418,18 +408,17 @@ static struct vfsmount *autofs4_d_automount(struct path *path) done: if (!(ino->flags & AUTOFS_INF_EXPIRING)) { /* - * Any needed mounting has been completed and the path updated - * so turn this into a normal dentry so we don't continually - * call ->d_automount() and ->d_manage(). - */ - spin_lock(&dentry->d_lock); - __managed_dentry_clear_transit(dentry); - /* + * Any needed mounting has been completed and the path + * updated so clear DCACHE_NEED_AUTOMOUNT so we don't + * call ->d_automount() on rootless multi-mounts since + * it can lead to an incorrect ELOOP error return. + * * Only clear DMANAGED_AUTOMOUNT for rootless multi-mounts and * symlinks as in all other cases the dentry will be covered by * an actual mount so ->d_automount() won't be called during * the follow. */ + spin_lock(&dentry->d_lock); if ((!d_mountpoint(dentry) && !list_empty(&dentry->d_subdirs)) || (dentry->d_inode && S_ISLNK(dentry->d_inode->i_mode))) -- cgit From f9398c233e3201874395eea8558eb616fb198648 Mon Sep 17 00:00:00 2001 From: Ian Kent Date: Fri, 25 Mar 2011 01:51:14 +0800 Subject: autofs4 - fix dentry leak in autofs4_expire_direct() There is a missing dput() when returning from autofs4_expire_direct() when we see that the dentry is already a pending mount. Signed-off-by: Ian Kent Acked-by: David Howells Signed-off-by: Al Viro --- fs/autofs4/expire.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c index c896dd6c1ea9..c403abcc725b 100644 --- a/fs/autofs4/expire.c +++ b/fs/autofs4/expire.c @@ -290,10 +290,8 @@ struct dentry *autofs4_expire_direct(struct super_block *sb, spin_lock(&sbi->fs_lock); ino = autofs4_dentry_ino(root); /* No point expiring a pending mount */ - if (ino->flags & AUTOFS_INF_PENDING) { - spin_unlock(&sbi->fs_lock); - return NULL; - } + if (ino->flags & AUTOFS_INF_PENDING) + goto out; if (!autofs4_direct_busy(mnt, root, timeout, do_now)) { struct autofs_info *ino = autofs4_dentry_ino(root); ino->flags |= AUTOFS_INF_EXPIRING; @@ -301,6 +299,7 @@ struct dentry *autofs4_expire_direct(struct super_block *sb, spin_unlock(&sbi->fs_lock); return root; } +out: spin_unlock(&sbi->fs_lock); dput(root); -- cgit From d4a85e35d1465da055264407d8395e84483084e6 Mon Sep 17 00:00:00 2001 From: Ian Kent Date: Fri, 25 Mar 2011 01:51:20 +0800 Subject: autofs4 - fix autofs4_expire_indirect() traversal The vfs-scale changes changed the traversal used in autofs4_expire_indirect() from a list to a depth first tree traversal which isn't right. Signed-off-by: Ian Kent Signed-off-by: Al Viro --- fs/autofs4/expire.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c index c403abcc725b..bc482e07b925 100644 --- a/fs/autofs4/expire.c +++ b/fs/autofs4/expire.c @@ -86,6 +86,56 @@ done: return status; } +/* + * Calculate and dget next entry in the subdirs list under root. + */ +static struct dentry *get_next_positive_subdir(struct dentry *prev, + struct dentry *root) +{ + struct list_head *next; + struct dentry *p, *q; + + spin_lock(&autofs4_lock); + + if (prev == NULL) { + spin_lock(&root->d_lock); + prev = dget_dlock(root); + next = prev->d_subdirs.next; + p = prev; + goto start; + } + + p = prev; + spin_lock(&p->d_lock); +again: + next = p->d_u.d_child.next; +start: + if (next == &root->d_subdirs) { + spin_unlock(&p->d_lock); + spin_unlock(&autofs4_lock); + dput(prev); + return NULL; + } + + q = list_entry(next, struct dentry, d_u.d_child); + + spin_lock_nested(&q->d_lock, DENTRY_D_LOCK_NESTED); + /* Negative dentry - try next */ + if (!simple_positive(q)) { + spin_unlock(&p->d_lock); + p = q; + goto again; + } + dget_dlock(q); + spin_unlock(&q->d_lock); + spin_unlock(&p->d_lock); + spin_unlock(&autofs4_lock); + + dput(prev); + + return q; +} + /* * Calculate and dget next entry in top down tree traversal. */ @@ -333,7 +383,7 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb, timeout = sbi->exp_timeout; dentry = NULL; - while ((dentry = get_next_positive_dentry(dentry, root))) { + while ((dentry = get_next_positive_subdir(dentry, root))) { spin_lock(&sbi->fs_lock); ino = autofs4_dentry_ino(dentry); /* No point expiring a pending mount */ -- cgit From 83fb96bfc792e5ca693e53f7fd878d51b8493da8 Mon Sep 17 00:00:00 2001 From: Ian Kent Date: Fri, 25 Mar 2011 01:51:25 +0800 Subject: autofs4 - fix d_manage() return on rcu-walk The daemon never needs to block and, in the rcu-walk case an error return isn't used, so always return zero. Signed-off-by: Ian Kent Signed-off-by: Al Viro --- fs/autofs4/root.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'fs') diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 3a93d3552486..ebbfa0ce6d7b 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c @@ -444,6 +444,8 @@ int autofs4_d_manage(struct dentry *dentry, bool rcu_walk) /* The daemon never waits. */ if (autofs4_oz_mode(sbi)) { + if (rcu_walk) + return 0; if (!d_mountpoint(dentry)) return -EISDIR; return 0; -- cgit From e7854723d0f3626f260c880d8db8e5136f29db19 Mon Sep 17 00:00:00 2001 From: Ian Kent Date: Fri, 25 Mar 2011 01:51:31 +0800 Subject: autofs4 - remove autofs4_lock The autofs4_lock introduced by the rcu-walk changes has unnecessarily broad scope. The locking is better handled by the per-autofs super block lookup_lock. Signed-off-by: Ian Kent Acked-by: David Howells Signed-off-by: Al Viro --- fs/autofs4/autofs_i.h | 2 -- fs/autofs4/expire.c | 18 ++++++++++-------- fs/autofs4/root.c | 25 +++++++------------------ fs/autofs4/waitq.c | 6 +++--- 4 files changed, 20 insertions(+), 31 deletions(-) (limited to 'fs') diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index 54f923792728..475f9c597cb7 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h @@ -61,8 +61,6 @@ do { \ current->pid, __func__, ##args); \ } while (0) -extern spinlock_t autofs4_lock; - /* Unified info structure. This is pointed to by both the dentry and inode structures. Each file in the filesystem has an instance of this structure. It holds a reference to the dentry, so dentries are never diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c index bc482e07b925..450f529a4eae 100644 --- a/fs/autofs4/expire.c +++ b/fs/autofs4/expire.c @@ -92,10 +92,11 @@ done: static struct dentry *get_next_positive_subdir(struct dentry *prev, struct dentry *root) { + struct autofs_sb_info *sbi = autofs4_sbi(root->d_sb); struct list_head *next; struct dentry *p, *q; - spin_lock(&autofs4_lock); + spin_lock(&sbi->lookup_lock); if (prev == NULL) { spin_lock(&root->d_lock); @@ -112,7 +113,7 @@ again: start: if (next == &root->d_subdirs) { spin_unlock(&p->d_lock); - spin_unlock(&autofs4_lock); + spin_unlock(&sbi->lookup_lock); dput(prev); return NULL; } @@ -129,7 +130,7 @@ start: dget_dlock(q); spin_unlock(&q->d_lock); spin_unlock(&p->d_lock); - spin_unlock(&autofs4_lock); + spin_unlock(&sbi->lookup_lock); dput(prev); @@ -142,13 +143,14 @@ start: static struct dentry *get_next_positive_dentry(struct dentry *prev, struct dentry *root) { + struct autofs_sb_info *sbi = autofs4_sbi(root->d_sb); struct list_head *next; struct dentry *p, *ret; if (prev == NULL) return dget(root); - spin_lock(&autofs4_lock); + spin_lock(&sbi->lookup_lock); relock: p = prev; spin_lock(&p->d_lock); @@ -160,7 +162,7 @@ again: if (p == root) { spin_unlock(&p->d_lock); - spin_unlock(&autofs4_lock); + spin_unlock(&sbi->lookup_lock); dput(prev); return NULL; } @@ -190,7 +192,7 @@ again: dget_dlock(ret); spin_unlock(&ret->d_lock); spin_unlock(&p->d_lock); - spin_unlock(&autofs4_lock); + spin_unlock(&sbi->lookup_lock); dput(prev); @@ -459,13 +461,13 @@ found: ino->flags |= AUTOFS_INF_EXPIRING; init_completion(&ino->expire_complete); spin_unlock(&sbi->fs_lock); - spin_lock(&autofs4_lock); + spin_lock(&sbi->lookup_lock); spin_lock(&expired->d_parent->d_lock); spin_lock_nested(&expired->d_lock, DENTRY_D_LOCK_NESTED); list_move(&expired->d_parent->d_subdirs, &expired->d_u.d_child); spin_unlock(&expired->d_lock); spin_unlock(&expired->d_parent->d_lock); - spin_unlock(&autofs4_lock); + spin_unlock(&sbi->lookup_lock); return expired; } diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index ebbfa0ce6d7b..96804a17bbd0 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c @@ -23,8 +23,6 @@ #include "autofs_i.h" -DEFINE_SPINLOCK(autofs4_lock); - static int autofs4_dir_symlink(struct inode *,struct dentry *,const char *); static int autofs4_dir_unlink(struct inode *,struct dentry *); static int autofs4_dir_rmdir(struct inode *,struct dentry *); @@ -125,15 +123,15 @@ static int autofs4_dir_open(struct inode *inode, struct file *file) * autofs file system so just let the libfs routines handle * it. */ - spin_lock(&autofs4_lock); + spin_lock(&sbi->lookup_lock); spin_lock(&dentry->d_lock); if (!d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) { spin_unlock(&dentry->d_lock); - spin_unlock(&autofs4_lock); + spin_unlock(&sbi->lookup_lock); return -ENOENT; } spin_unlock(&dentry->d_lock); - spin_unlock(&autofs4_lock); + spin_unlock(&sbi->lookup_lock); out: return dcache_dir_open(inode, file); @@ -171,7 +169,6 @@ static struct dentry *autofs4_lookup_active(struct dentry *dentry) const unsigned char *str = name->name; struct list_head *p, *head; - spin_lock(&autofs4_lock); spin_lock(&sbi->lookup_lock); head = &sbi->active_list; list_for_each(p, head) { @@ -204,14 +201,12 @@ static struct dentry *autofs4_lookup_active(struct dentry *dentry) dget_dlock(active); spin_unlock(&active->d_lock); spin_unlock(&sbi->lookup_lock); - spin_unlock(&autofs4_lock); return active; } next: spin_unlock(&active->d_lock); } spin_unlock(&sbi->lookup_lock); - spin_unlock(&autofs4_lock); return NULL; } @@ -226,7 +221,6 @@ static struct dentry *autofs4_lookup_expiring(struct dentry *dentry) const unsigned char *str = name->name; struct list_head *p, *head; - spin_lock(&autofs4_lock); spin_lock(&sbi->lookup_lock); head = &sbi->expiring_list; list_for_each(p, head) { @@ -259,14 +253,12 @@ static struct dentry *autofs4_lookup_expiring(struct dentry *dentry) dget_dlock(expiring); spin_unlock(&expiring->d_lock); spin_unlock(&sbi->lookup_lock); - spin_unlock(&autofs4_lock); return expiring; } next: spin_unlock(&expiring->d_lock); } spin_unlock(&sbi->lookup_lock); - spin_unlock(&autofs4_lock); return NULL; } @@ -603,12 +595,12 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry) dir->i_mtime = CURRENT_TIME; - spin_lock(&autofs4_lock); - autofs4_add_expiring(dentry); + spin_lock(&sbi->lookup_lock); + __autofs4_add_expiring(dentry); spin_lock(&dentry->d_lock); __d_drop(dentry); spin_unlock(&dentry->d_lock); - spin_unlock(&autofs4_lock); + spin_unlock(&sbi->lookup_lock); return 0; } @@ -677,20 +669,17 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry) if (!autofs4_oz_mode(sbi)) return -EACCES; - spin_lock(&autofs4_lock); spin_lock(&sbi->lookup_lock); spin_lock(&dentry->d_lock); if (!list_empty(&dentry->d_subdirs)) { spin_unlock(&dentry->d_lock); spin_unlock(&sbi->lookup_lock); - spin_unlock(&autofs4_lock); return -ENOTEMPTY; } __autofs4_add_expiring(dentry); - spin_unlock(&sbi->lookup_lock); __d_drop(dentry); spin_unlock(&dentry->d_lock); - spin_unlock(&autofs4_lock); + spin_unlock(&sbi->lookup_lock); if (sbi->version < 5) autofs_clear_leaf_automount_flags(dentry); diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c index 56010056b2e6..25435987d6ae 100644 --- a/fs/autofs4/waitq.c +++ b/fs/autofs4/waitq.c @@ -197,12 +197,12 @@ rename_retry: seq = read_seqbegin(&rename_lock); rcu_read_lock(); - spin_lock(&autofs4_lock); + spin_lock(&sbi->fs_lock); for (tmp = dentry ; tmp != root ; tmp = tmp->d_parent) len += tmp->d_name.len + 1; if (!len || --len > NAME_MAX) { - spin_unlock(&autofs4_lock); + spin_unlock(&sbi->fs_lock); rcu_read_unlock(); if (read_seqretry(&rename_lock, seq)) goto rename_retry; @@ -218,7 +218,7 @@ rename_retry: p -= tmp->d_name.len; strncpy(p, tmp->d_name.name, tmp->d_name.len); } - spin_unlock(&autofs4_lock); + spin_unlock(&sbi->fs_lock); rcu_read_unlock(); if (read_seqretry(&rename_lock, seq)) goto rename_retry; -- cgit From 3dc8fe4dca9cd3e4aa828ed36451e2bcfd2350da Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Fri, 25 Mar 2011 01:51:37 +0800 Subject: autofs4: Do not potentially dereference NULL pointer returned by fget() in autofs_dev_ioctl_setpipefd() In fs/autofs4/dev-ioctl.c::autofs_dev_ioctl_setpipefd() we call fget(), which may return NULL, but we do not explicitly test for that NULL return so we may end up dereferencing a NULL pointer - bad. When I originally submitted this patch I had chosen EBUSY as the return value to use if this happens. Ian Kent was kind enough to explain why that would most likely be wrong and why EBADF should most likely be used instead. This version of the patch uses EBADF. Signed-off-by: Jesper Juhl Signed-off-by: Ian Kent Signed-off-by: Al Viro --- fs/autofs4/dev-ioctl.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'fs') diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c index 1442da4860e5..509fe1eb66ae 100644 --- a/fs/autofs4/dev-ioctl.c +++ b/fs/autofs4/dev-ioctl.c @@ -372,6 +372,10 @@ static int autofs_dev_ioctl_setpipefd(struct file *fp, return -EBUSY; } else { struct file *pipe = fget(pipefd); + if (!pipe) { + err = -EBADF; + goto out; + } if (!pipe->f_op || !pipe->f_op->write) { err = -EPIPE; fput(pipe); -- cgit From de4b15c7e9fe9fdd1eb6333be0a08c822db1ca0e Mon Sep 17 00:00:00 2001 From: Andy Adamson Date: Sat, 12 Mar 2011 02:58:09 -0500 Subject: NFSv4.1 pnfs_layoutcommit_inode fixes Test NFS_INO_LAYOUTCOMMIT before kzalloc Mark inode dirty to retry LAYOUTCOMMIT on kzalloc failure. Add comments. Signed-off-by: Andy Adamson Signed-off-by: Trond Myklebust --- fs/nfs/pnfs.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) (limited to 'fs') diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 2a08ca0dddc1..ac7112574790 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -982,6 +982,14 @@ pnfs_set_layoutcommit(struct nfs_write_data *wdata) } EXPORT_SYMBOL_GPL(pnfs_set_layoutcommit); +/* + * For the LAYOUT4_NFSV4_1_FILES layout type, NFS_DATA_SYNC WRITEs and + * NFS_UNSTABLE WRITEs with a COMMIT to data servers must store enough + * data to disk to allow the server to recover the data if it crashes. + * LAYOUTCOMMIT is only needed when the NFL4_UFLG_COMMIT_THRU_MDS flag + * is off, and a COMMIT is sent to a data server, or + * if WRITEs to a data server return NFS_DATA_SYNC. + */ int pnfs_layoutcommit_inode(struct inode *inode, int sync) { @@ -994,10 +1002,18 @@ pnfs_layoutcommit_inode(struct inode *inode, int sync) dprintk("--> %s inode %lu\n", __func__, inode->i_ino); + if (!test_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) + return 0; + /* Note kzalloc ensures data->res.seq_res.sr_slot == NULL */ data = kzalloc(sizeof(*data), GFP_NOFS); - spin_lock(&inode->i_lock); + if (!data) { + mark_inode_dirty_sync(inode); + status = -ENOMEM; + goto out; + } + spin_lock(&inode->i_lock); if (!test_and_clear_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) { spin_unlock(&inode->i_lock); kfree(data); @@ -1014,16 +1030,8 @@ pnfs_layoutcommit_inode(struct inode *inode, int sync) lseg->pls_end_pos = 0; lseg->pls_lc_cred = NULL; - if (!data) { - put_lseg(lseg); - spin_unlock(&inode->i_lock); - put_rpccred(cred); - status = -ENOMEM; - goto out; - } else { - memcpy(&data->args.stateid.data, nfsi->layout->plh_stateid.data, - sizeof(nfsi->layout->plh_stateid.data)); - } + memcpy(&data->args.stateid.data, nfsi->layout->plh_stateid.data, + sizeof(nfsi->layout->plh_stateid.data)); spin_unlock(&inode->i_lock); data->args.inode = inode; -- cgit From ef31153786bc1e4304e6b9422cc8b9efef455611 Mon Sep 17 00:00:00 2001 From: Andy Adamson Date: Sat, 12 Mar 2011 02:58:10 -0500 Subject: NFSv4.1 convert layoutcommit sync to boolean Signed-off-by: Andy Adamson Signed-off-by: Trond Myklebust --- fs/nfs/file.c | 2 +- fs/nfs/nfs4_fs.h | 2 +- fs/nfs/nfs4proc.c | 4 ++-- fs/nfs/pnfs.c | 2 +- fs/nfs/pnfs.h | 4 ++-- fs/nfs/write.c | 8 +++++--- 6 files changed, 12 insertions(+), 10 deletions(-) (limited to 'fs') diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 85cb95de5df5..3ac5bd695e5e 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -328,7 +328,7 @@ nfs_file_fsync(struct file *file, int datasync) ret = status; if (!ret && !datasync) /* application has asked for meta-data sync */ - ret = pnfs_layoutcommit_inode(inode, 1); + ret = pnfs_layoutcommit_inode(inode, true); return ret; } diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 1e612d159b71..4414fd7e7d5e 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -263,7 +263,7 @@ extern int nfs4_init_session(struct nfs_server *server); extern int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo); extern int nfs4_proc_layoutcommit(struct nfs4_layoutcommit_data *data, - int sync); + bool sync); static inline bool is_ds_only_client(struct nfs_client *clp) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 6f2f40239d10..43045fa44710 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -5671,7 +5671,7 @@ static const struct rpc_call_ops nfs4_layoutcommit_ops = { }; int -nfs4_proc_layoutcommit(struct nfs4_layoutcommit_data *data, int sync) +nfs4_proc_layoutcommit(struct nfs4_layoutcommit_data *data, bool sync) { struct rpc_message msg = { .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTCOMMIT], @@ -5699,7 +5699,7 @@ nfs4_proc_layoutcommit(struct nfs4_layoutcommit_data *data, int sync) task = rpc_run_task(&task_setup_data); if (IS_ERR(task)) return PTR_ERR(task); - if (!sync) + if (sync == false) goto out; status = nfs4_wait_for_completion_rpc_task(task); if (status != 0) diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index ac7112574790..22c2ddbef420 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -991,7 +991,7 @@ EXPORT_SYMBOL_GPL(pnfs_set_layoutcommit); * if WRITEs to a data server return NFS_DATA_SYNC. */ int -pnfs_layoutcommit_inode(struct inode *inode, int sync) +pnfs_layoutcommit_inode(struct inode *inode, bool sync) { struct nfs4_layoutcommit_data *data; struct nfs_inode *nfsi = NFS_I(inode); diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 0806c77862b6..33b9ae90c6f7 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h @@ -155,7 +155,7 @@ void pnfs_roc_release(struct inode *ino); void pnfs_roc_set_barrier(struct inode *ino, u32 barrier); bool pnfs_roc_drain(struct inode *ino, u32 *barrier); void pnfs_set_layoutcommit(struct nfs_write_data *wdata); -int pnfs_layoutcommit_inode(struct inode *inode, int sync); +int pnfs_layoutcommit_inode(struct inode *inode, bool sync); static inline int lo_fail_bit(u32 iomode) { @@ -328,7 +328,7 @@ static inline void pnfs_clear_request_commit(struct nfs_page *req) { } -static inline int pnfs_layoutcommit_inode(struct inode *inode, int sync) +static inline int pnfs_layoutcommit_inode(struct inode *inode, bool sync) { return 0; } diff --git a/fs/nfs/write.c b/fs/nfs/write.c index a03c11f9081e..85d75254328e 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -1566,10 +1566,12 @@ int nfs_write_inode(struct inode *inode, struct writeback_control *wbc) ret = nfs_commit_unstable_pages(inode, wbc); if (ret >= 0 && test_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags)) { - int status, sync = wbc->sync_mode; + int status; + bool sync = true; - if (wbc->nonblocking || wbc->for_background) - sync = 0; + if (wbc->sync_mode == WB_SYNC_NONE || wbc->nonblocking || + wbc->for_background) + sync = false; status = pnfs_layoutcommit_inode(inode, sync); if (status < 0) -- cgit From 35124a0994fc02545b14b9fa3aad000b3331f1c0 Mon Sep 17 00:00:00 2001 From: Weston Andros Adamson Date: Thu, 24 Mar 2011 16:48:21 -0400 Subject: Cleanup XDR parsing for LAYOUTGET, GETDEVICEINFO changes LAYOUTGET and GETDEVICEINFO XDR parsing to: - not use vmap, which doesn't work on incoherent archs - use xdr_stream parsing for all xdr Signed-off-by: Weston Andros Adamson Signed-off-by: Trond Myklebust --- fs/nfs/nfs4filelayout.c | 53 +++++++++++--- fs/nfs/nfs4filelayoutdev.c | 178 +++++++++++++++++++++++++++++++-------------- fs/nfs/nfs4proc.c | 9 +-- fs/nfs/nfs4xdr.c | 30 +++++--- fs/nfs/pnfs.c | 39 ++++++++++ fs/nfs/pnfs.h | 1 - 6 files changed, 226 insertions(+), 84 deletions(-) (limited to 'fs') diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index ffb54a082f3a..6f8192f4cfc7 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c @@ -502,12 +502,33 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo, struct nfs4_layoutget_res *lgr, struct nfs4_deviceid *id) { - uint32_t *p = (uint32_t *)lgr->layout.buf; + struct xdr_stream stream; + struct xdr_buf buf = { + .pages = lgr->layoutp->pages, + .page_len = lgr->layoutp->len, + .buflen = lgr->layoutp->len, + .len = lgr->layoutp->len, + }; + struct page *scratch; + __be32 *p; uint32_t nfl_util; int i; dprintk("%s: set_layout_map Begin\n", __func__); + scratch = alloc_page(GFP_KERNEL); + if (!scratch) + return -ENOMEM; + + xdr_init_decode(&stream, &buf, NULL); + xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE); + + /* 20 = ufl_util (4), first_stripe_index (4), pattern_offset (8), + * num_fh (4) */ + p = xdr_inline_decode(&stream, NFS4_DEVICEID4_SIZE + 20); + if (unlikely(!p)) + goto out_err; + memcpy(id, p, sizeof(*id)); p += XDR_QUADLEN(NFS4_DEVICEID4_SIZE); print_deviceid(id); @@ -529,32 +550,46 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo, __func__, nfl_util, fl->num_fh, fl->first_stripe_index, fl->pattern_offset); + if (!fl->num_fh) + goto out_err; + fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *), GFP_KERNEL); if (!fl->fh_array) - return -ENOMEM; + goto out_err; for (i = 0; i < fl->num_fh; i++) { /* Do we want to use a mempool here? */ fl->fh_array[i] = kmalloc(sizeof(struct nfs_fh), GFP_KERNEL); - if (!fl->fh_array[i]) { - filelayout_free_fh_array(fl); - return -ENOMEM; - } + if (!fl->fh_array[i]) + goto out_err_free; + + p = xdr_inline_decode(&stream, 4); + if (unlikely(!p)) + goto out_err_free; fl->fh_array[i]->size = be32_to_cpup(p++); if (sizeof(struct nfs_fh) < fl->fh_array[i]->size) { printk(KERN_ERR "Too big fh %d received %d\n", i, fl->fh_array[i]->size); - filelayout_free_fh_array(fl); - return -EIO; + goto out_err_free; } + + p = xdr_inline_decode(&stream, fl->fh_array[i]->size); + if (unlikely(!p)) + goto out_err_free; memcpy(fl->fh_array[i]->data, p, fl->fh_array[i]->size); - p += XDR_QUADLEN(fl->fh_array[i]->size); dprintk("DEBUG: %s: fh len %d\n", __func__, fl->fh_array[i]->size); } + __free_page(scratch); return 0; + +out_err_free: + filelayout_free_fh_array(fl); +out_err: + __free_page(scratch); + return -EIO; } static void diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c index 68143c162e3b..de5350f2b249 100644 --- a/fs/nfs/nfs4filelayoutdev.c +++ b/fs/nfs/nfs4filelayoutdev.c @@ -261,7 +261,7 @@ out: * Currently only support ipv4, and one multi-path address. */ static struct nfs4_pnfs_ds * -decode_and_add_ds(__be32 **pp, struct inode *inode) +decode_and_add_ds(struct xdr_stream *streamp, struct inode *inode) { struct nfs4_pnfs_ds *ds = NULL; char *buf; @@ -269,25 +269,34 @@ decode_and_add_ds(__be32 **pp, struct inode *inode) u32 ip_addr, port; int nlen, rlen, i; int tmp[2]; - __be32 *r_netid, *r_addr, *p = *pp; + __be32 *p; /* r_netid */ + p = xdr_inline_decode(streamp, 4); + if (unlikely(!p)) + goto out_err; nlen = be32_to_cpup(p++); - r_netid = p; - p += XDR_QUADLEN(nlen); - /* r_addr */ - rlen = be32_to_cpup(p++); - r_addr = p; - p += XDR_QUADLEN(rlen); - *pp = p; + p = xdr_inline_decode(streamp, nlen); + if (unlikely(!p)) + goto out_err; /* Check that netid is "tcp" */ - if (nlen != 3 || memcmp((char *)r_netid, "tcp", 3)) { + if (nlen != 3 || memcmp((char *)p, "tcp", 3)) { dprintk("%s: ERROR: non ipv4 TCP r_netid\n", __func__); goto out_err; } + /* r_addr */ + p = xdr_inline_decode(streamp, 4); + if (unlikely(!p)) + goto out_err; + rlen = be32_to_cpup(p); + + p = xdr_inline_decode(streamp, rlen); + if (unlikely(!p)) + goto out_err; + /* ipv6 length plus port is legal */ if (rlen > INET6_ADDRSTRLEN + 8) { dprintk("%s: Invalid address, length %d\n", __func__, @@ -300,7 +309,7 @@ decode_and_add_ds(__be32 **pp, struct inode *inode) goto out_err; } buf[rlen] = '\0'; - memcpy(buf, r_addr, rlen); + memcpy(buf, p, rlen); /* replace the port dots with dashes for the in4_pton() delimiter*/ for (i = 0; i < 2; i++) { @@ -336,90 +345,154 @@ out_err: static struct nfs4_file_layout_dsaddr* decode_device(struct inode *ino, struct pnfs_device *pdev) { - int i, dummy; + int i; u32 cnt, num; u8 *indexp; - __be32 *p = (__be32 *)pdev->area, *indicesp; - struct nfs4_file_layout_dsaddr *dsaddr; + __be32 *p; + u8 *stripe_indices; + u8 max_stripe_index; + struct nfs4_file_layout_dsaddr *dsaddr = NULL; + struct xdr_stream stream; + struct xdr_buf buf = { + .pages = pdev->pages, + .page_len = pdev->pglen, + .buflen = pdev->pglen, + .len = pdev->pglen, + }; + struct page *scratch; + + /* set up xdr stream */ + scratch = alloc_page(GFP_KERNEL); + if (!scratch) + goto out_err; + + xdr_init_decode(&stream, &buf, NULL); + xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE); /* Get the stripe count (number of stripe index) */ - cnt = be32_to_cpup(p++); + p = xdr_inline_decode(&stream, 4); + if (unlikely(!p)) + goto out_err_free_scratch; + + cnt = be32_to_cpup(p); dprintk("%s stripe count %d\n", __func__, cnt); if (cnt > NFS4_PNFS_MAX_STRIPE_CNT) { printk(KERN_WARNING "%s: stripe count %d greater than " "supported maximum %d\n", __func__, cnt, NFS4_PNFS_MAX_STRIPE_CNT); - goto out_err; + goto out_err_free_scratch; + } + + /* read stripe indices */ + stripe_indices = kcalloc(cnt, sizeof(u8), GFP_KERNEL); + if (!stripe_indices) + goto out_err_free_scratch; + + p = xdr_inline_decode(&stream, cnt << 2); + if (unlikely(!p)) + goto out_err_free_stripe_indices; + + indexp = &stripe_indices[0]; + max_stripe_index = 0; + for (i = 0; i < cnt; i++) { + *indexp = be32_to_cpup(p++); + max_stripe_index = max(max_stripe_index, *indexp); + indexp++; } /* Check the multipath list count */ - indicesp = p; - p += XDR_QUADLEN(cnt << 2); - num = be32_to_cpup(p++); + p = xdr_inline_decode(&stream, 4); + if (unlikely(!p)) + goto out_err_free_stripe_indices; + + num = be32_to_cpup(p); dprintk("%s ds_num %u\n", __func__, num); if (num > NFS4_PNFS_MAX_MULTI_CNT) { printk(KERN_WARNING "%s: multipath count %d greater than " "supported maximum %d\n", __func__, num, NFS4_PNFS_MAX_MULTI_CNT); - goto out_err; + goto out_err_free_stripe_indices; } + + /* validate stripe indices are all < num */ + if (max_stripe_index >= num) { + printk(KERN_WARNING "%s: stripe index %u >= num ds %u\n", + __func__, max_stripe_index, num); + goto out_err_free_stripe_indices; + } + dsaddr = kzalloc(sizeof(*dsaddr) + (sizeof(struct nfs4_pnfs_ds *) * (num - 1)), GFP_KERNEL); if (!dsaddr) - goto out_err; - - dsaddr->stripe_indices = kzalloc(sizeof(u8) * cnt, GFP_KERNEL); - if (!dsaddr->stripe_indices) - goto out_err_free; + goto out_err_free_stripe_indices; dsaddr->stripe_count = cnt; + dsaddr->stripe_indices = stripe_indices; + stripe_indices = NULL; dsaddr->ds_num = num; memcpy(&dsaddr->deviceid, &pdev->dev_id, sizeof(pdev->dev_id)); - /* Go back an read stripe indices */ - p = indicesp; - indexp = &dsaddr->stripe_indices[0]; - for (i = 0; i < dsaddr->stripe_count; i++) { - *indexp = be32_to_cpup(p++); - if (*indexp >= num) - goto out_err_free; - indexp++; - } - /* Skip already read multipath list count */ - p++; - for (i = 0; i < dsaddr->ds_num; i++) { int j; + u32 mp_count; + + p = xdr_inline_decode(&stream, 4); + if (unlikely(!p)) + goto out_err_free_deviceid; - dummy = be32_to_cpup(p++); /* multipath count */ - if (dummy > 1) { + mp_count = be32_to_cpup(p); /* multipath count */ + if (mp_count > 1) { printk(KERN_WARNING "%s: Multipath count %d not supported, " "skipping all greater than 1\n", __func__, - dummy); + mp_count); } - for (j = 0; j < dummy; j++) { + for (j = 0; j < mp_count; j++) { if (j == 0) { - dsaddr->ds_list[i] = decode_and_add_ds(&p, ino); + dsaddr->ds_list[i] = decode_and_add_ds(&stream, + ino); if (dsaddr->ds_list[i] == NULL) - goto out_err_free; + goto out_err_free_deviceid; } else { u32 len; /* skip extra multipath */ - len = be32_to_cpup(p++); - p += XDR_QUADLEN(len); - len = be32_to_cpup(p++); - p += XDR_QUADLEN(len); - continue; + + /* read len, skip */ + p = xdr_inline_decode(&stream, 4); + if (unlikely(!p)) + goto out_err_free_deviceid; + len = be32_to_cpup(p); + + p = xdr_inline_decode(&stream, len); + if (unlikely(!p)) + goto out_err_free_deviceid; + + /* read len, skip */ + p = xdr_inline_decode(&stream, 4); + if (unlikely(!p)) + goto out_err_free_deviceid; + len = be32_to_cpup(p); + + p = xdr_inline_decode(&stream, len); + if (unlikely(!p)) + goto out_err_free_deviceid; } } } + + __free_page(scratch); return dsaddr; -out_err_free: +out_err_free_deviceid: nfs4_fl_free_deviceid(dsaddr); + /* stripe_indicies was part of dsaddr */ + goto out_err_free_scratch; +out_err_free_stripe_indices: + kfree(stripe_indices); +out_err_free_scratch: + __free_page(scratch); out_err: dprintk("%s ERROR: returning NULL\n", __func__); return NULL; @@ -498,11 +571,6 @@ get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id) goto out_free; } - /* set pdev->area */ - pdev->area = vmap(pages, max_pages, VM_MAP, PAGE_KERNEL); - if (!pdev->area) - goto out_free; - memcpy(&pdev->dev_id, dev_id, sizeof(*dev_id)); pdev->layout_type = LAYOUT_NFSV4_1_FILES; pdev->pages = pages; @@ -521,8 +589,6 @@ get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id) */ dsaddr = decode_and_add_device(inode, pdev); out_free: - if (pdev->area != NULL) - vunmap(pdev->area); for (i = 0; i < max_pages; i++) __free_page(pages[i]); kfree(pages); diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 43045fa44710..8f071314e94b 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -5526,8 +5526,6 @@ static void nfs4_layoutget_release(void *calldata) struct nfs4_layoutget *lgp = calldata; dprintk("--> %s\n", __func__); - if (lgp->res.layout.buf != NULL) - free_page((unsigned long) lgp->res.layout.buf); put_nfs_open_context(lgp->args.ctx); kfree(calldata); dprintk("<-- %s\n", __func__); @@ -5559,12 +5557,7 @@ int nfs4_proc_layoutget(struct nfs4_layoutget *lgp) dprintk("--> %s\n", __func__); - lgp->res.layout.buf = (void *)__get_free_page(GFP_NOFS); - if (lgp->res.layout.buf == NULL) { - nfs4_layoutget_release(lgp); - return -ENOMEM; - } - + lgp->res.layoutp = &lgp->args.layout; lgp->res.seq_res.sr_slot = NULL; task = rpc_run_task(&task_setup_data); if (IS_ERR(task)) diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 207d399c8dee..40da65e8fa2a 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -2656,6 +2656,10 @@ static void nfs4_xdr_enc_layoutget(struct rpc_rqst *req, encode_sequence(xdr, &args->seq_args, &hdr); encode_putfh(xdr, NFS_FH(args->inode), &hdr); encode_layoutget(xdr, args, &hdr); + + xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, + args->layout.pages, 0, args->layout.pglen); + encode_nops(&hdr); } @@ -5022,6 +5026,9 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, __be32 *p; int status; u32 layout_count; + struct xdr_buf *rcvbuf = &req->rq_rcv_buf; + struct kvec *iov = rcvbuf->head; + u32 hdrlen, recvd; status = decode_op_hdr(xdr, OP_LAYOUTGET); if (status) @@ -5038,17 +5045,14 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, return -EINVAL; } - p = xdr_inline_decode(xdr, 24); + p = xdr_inline_decode(xdr, 28); if (unlikely(!p)) goto out_overflow; p = xdr_decode_hyper(p, &res->range.offset); p = xdr_decode_hyper(p, &res->range.length); res->range.iomode = be32_to_cpup(p++); res->type = be32_to_cpup(p++); - - status = decode_opaque_inline(xdr, &res->layout.len, (char **)&p); - if (unlikely(status)) - return status; + res->layoutp->len = be32_to_cpup(p); dprintk("%s roff:%lu rlen:%lu riomode:%d, lo_type:0x%x, lo.len:%d\n", __func__, @@ -5056,12 +5060,18 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, (unsigned long)res->range.length, res->range.iomode, res->type, - res->layout.len); + res->layoutp->len); + + hdrlen = (u8 *) xdr->p - (u8 *) iov->iov_base; + recvd = req->rq_rcv_buf.len - hdrlen; + if (res->layoutp->len > recvd) { + dprintk("NFS: server cheating in layoutget reply: " + "layout len %u > recvd %u\n", + res->layoutp->len, recvd); + return -EINVAL; + } - /* nfs4_proc_layoutget allocated a single page */ - if (res->layout.len > PAGE_SIZE) - return -ENOMEM; - memcpy(res->layout.buf, p, res->layout.len); + xdr_read_pages(xdr, res->layoutp->len); if (layout_count > 1) { /* We only handle a length one array at the moment. Any diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 22c2ddbef420..d9ab97269ce6 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -472,6 +472,9 @@ send_layoutget(struct pnfs_layout_hdr *lo, struct nfs_server *server = NFS_SERVER(ino); struct nfs4_layoutget *lgp; struct pnfs_layout_segment *lseg = NULL; + struct page **pages = NULL; + int i; + u32 max_resp_sz, max_pages; dprintk("--> %s\n", __func__); @@ -479,6 +482,21 @@ send_layoutget(struct pnfs_layout_hdr *lo, lgp = kzalloc(sizeof(*lgp), GFP_KERNEL); if (lgp == NULL) return NULL; + + /* allocate pages for xdr post processing */ + max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz; + max_pages = max_resp_sz >> PAGE_SHIFT; + + pages = kzalloc(max_pages * sizeof(struct page *), GFP_KERNEL); + if (!pages) + goto out_err_free; + + for (i = 0; i < max_pages; i++) { + pages[i] = alloc_page(GFP_KERNEL); + if (!pages[i]) + goto out_err_free; + } + lgp->args.minlength = NFS4_MAX_UINT64; lgp->args.maxcount = PNFS_LAYOUT_MAXSIZE; lgp->args.range.iomode = iomode; @@ -487,6 +505,8 @@ send_layoutget(struct pnfs_layout_hdr *lo, lgp->args.type = server->pnfs_curr_ld->id; lgp->args.inode = ino; lgp->args.ctx = get_nfs_open_context(ctx); + lgp->args.layout.pages = pages; + lgp->args.layout.pglen = max_pages * PAGE_SIZE; lgp->lsegpp = &lseg; /* Synchronously retrieve layout information from server and @@ -497,7 +517,26 @@ send_layoutget(struct pnfs_layout_hdr *lo, /* remember that LAYOUTGET failed and suspend trying */ set_bit(lo_fail_bit(iomode), &lo->plh_flags); } + + /* free xdr pages */ + for (i = 0; i < max_pages; i++) + __free_page(pages[i]); + kfree(pages); + return lseg; + +out_err_free: + /* free any allocated xdr pages, lgp as it's not used */ + if (pages) { + for (i = 0; i < max_pages; i++) { + if (!pages[i]) + break; + __free_page(pages[i]); + } + kfree(pages); + } + kfree(lgp); + return NULL; } bool pnfs_roc(struct inode *ino) diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 33b9ae90c6f7..bc4827202e7a 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h @@ -109,7 +109,6 @@ struct pnfs_device { unsigned int layout_type; unsigned int mincount; struct page **pages; - void *area; unsigned int pgbase; unsigned int pglen; }; -- cgit From 250df6ed274d767da844a5d9f05720b804240197 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 22 Mar 2011 22:23:36 +1100 Subject: fs: protect inode->i_state with inode->i_lock Protect inode state transitions and validity checks with the inode->i_lock. This enables us to make inode state transitions independently of the inode_lock and is the first step to peeling away the inode_lock from the code. This requires that __iget() is done atomically with i_state checks during list traversals so that we don't race with another thread marking the inode I_FREEING between the state check and grabbing the reference. Also remove the unlock_new_inode() memory barrier optimisation required to avoid taking the inode_lock when clearing I_NEW. Simplify the code by simply taking the inode->i_lock around the state change and wakeup. Because the wakeup is no longer tricky, remove the wake_up_inode() function and open code the wakeup where necessary. Signed-off-by: Dave Chinner Signed-off-by: Al Viro --- fs/block_dev.c | 2 + fs/buffer.c | 2 +- fs/drop_caches.c | 9 ++- fs/fs-writeback.c | 44 +++++++++++---- fs/inode.c | 150 ++++++++++++++++++++++++++++++++++--------------- fs/notify/inode_mark.c | 21 +++++-- fs/quota/dquot.c | 13 +++-- 7 files changed, 169 insertions(+), 72 deletions(-) (limited to 'fs') diff --git a/fs/block_dev.c b/fs/block_dev.c index 889287019599..bc39b18cf3d0 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -56,9 +56,11 @@ static void bdev_inode_switch_bdi(struct inode *inode, struct backing_dev_info *dst) { spin_lock(&inode_lock); + spin_lock(&inode->i_lock); inode->i_data.backing_dev_info = dst; if (inode->i_state & I_DIRTY) list_move(&inode->i_wb_list, &dst->wb.b_dirty); + spin_unlock(&inode->i_lock); spin_unlock(&inode_lock); } diff --git a/fs/buffer.c b/fs/buffer.c index 2219a76e2caf..da666f3148f9 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -1144,7 +1144,7 @@ __getblk_slow(struct block_device *bdev, sector_t block, int size) * inode list. * * mark_buffer_dirty() is atomic. It takes bh->b_page->mapping->private_lock, - * mapping->tree_lock and the global inode_lock. + * mapping->tree_lock and mapping->host->i_lock. */ void mark_buffer_dirty(struct buffer_head *bh) { diff --git a/fs/drop_caches.c b/fs/drop_caches.c index 816f88e6b9ce..6c6f73ba0868 100644 --- a/fs/drop_caches.c +++ b/fs/drop_caches.c @@ -18,11 +18,14 @@ static void drop_pagecache_sb(struct super_block *sb, void *unused) spin_lock(&inode_lock); list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { - if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) - continue; - if (inode->i_mapping->nrpages == 0) + spin_lock(&inode->i_lock); + if ((inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) || + (inode->i_mapping->nrpages == 0)) { + spin_unlock(&inode->i_lock); continue; + } __iget(inode); + spin_unlock(&inode->i_lock); spin_unlock(&inode_lock); invalidate_mapping_pages(inode->i_mapping, 0, -1); iput(toput_inode); diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 59c6e4956786..efd1ebe879cc 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -306,10 +306,12 @@ static void inode_wait_for_writeback(struct inode *inode) wait_queue_head_t *wqh; wqh = bit_waitqueue(&inode->i_state, __I_SYNC); - while (inode->i_state & I_SYNC) { + while (inode->i_state & I_SYNC) { + spin_unlock(&inode->i_lock); spin_unlock(&inode_lock); __wait_on_bit(wqh, &wq, inode_wait, TASK_UNINTERRUPTIBLE); spin_lock(&inode_lock); + spin_lock(&inode->i_lock); } } @@ -333,6 +335,7 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc) unsigned dirty; int ret; + spin_lock(&inode->i_lock); if (!atomic_read(&inode->i_count)) WARN_ON(!(inode->i_state & (I_WILL_FREE|I_FREEING))); else @@ -348,6 +351,7 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc) * completed a full scan of b_io. */ if (wbc->sync_mode != WB_SYNC_ALL) { + spin_unlock(&inode->i_lock); requeue_io(inode); return 0; } @@ -363,6 +367,7 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc) /* Set I_SYNC, reset I_DIRTY_PAGES */ inode->i_state |= I_SYNC; inode->i_state &= ~I_DIRTY_PAGES; + spin_unlock(&inode->i_lock); spin_unlock(&inode_lock); ret = do_writepages(mapping, wbc); @@ -384,8 +389,10 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc) * write_inode() */ spin_lock(&inode_lock); + spin_lock(&inode->i_lock); dirty = inode->i_state & I_DIRTY; inode->i_state &= ~(I_DIRTY_SYNC | I_DIRTY_DATASYNC); + spin_unlock(&inode->i_lock); spin_unlock(&inode_lock); /* Don't write the inode if only I_DIRTY_PAGES was set */ if (dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) { @@ -395,6 +402,7 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc) } spin_lock(&inode_lock); + spin_lock(&inode->i_lock); inode->i_state &= ~I_SYNC; if (!(inode->i_state & I_FREEING)) { if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) { @@ -436,6 +444,7 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc) } } inode_sync_complete(inode); + spin_unlock(&inode->i_lock); return ret; } @@ -506,7 +515,9 @@ static int writeback_sb_inodes(struct super_block *sb, struct bdi_writeback *wb, * kind does not need peridic writeout yet, and for the latter * kind writeout is handled by the freer. */ + spin_lock(&inode->i_lock); if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE)) { + spin_unlock(&inode->i_lock); requeue_io(inode); continue; } @@ -515,10 +526,14 @@ static int writeback_sb_inodes(struct super_block *sb, struct bdi_writeback *wb, * Was this inode dirtied after sync_sb_inodes was called? * This keeps sync from extra jobs and livelock. */ - if (inode_dirtied_after(inode, wbc->wb_start)) + if (inode_dirtied_after(inode, wbc->wb_start)) { + spin_unlock(&inode->i_lock); return 1; + } __iget(inode); + spin_unlock(&inode->i_lock); + pages_skipped = wbc->pages_skipped; writeback_single_inode(inode, wbc); if (wbc->pages_skipped != pages_skipped) { @@ -724,7 +739,9 @@ static long wb_writeback(struct bdi_writeback *wb, if (!list_empty(&wb->b_more_io)) { inode = wb_inode(wb->b_more_io.prev); trace_wbc_writeback_wait(&wbc, wb->bdi); + spin_lock(&inode->i_lock); inode_wait_for_writeback(inode); + spin_unlock(&inode->i_lock); } spin_unlock(&inode_lock); } @@ -1017,6 +1034,7 @@ void __mark_inode_dirty(struct inode *inode, int flags) block_dump___mark_inode_dirty(inode); spin_lock(&inode_lock); + spin_lock(&inode->i_lock); if ((inode->i_state & flags) != flags) { const int was_dirty = inode->i_state & I_DIRTY; @@ -1028,7 +1046,7 @@ void __mark_inode_dirty(struct inode *inode, int flags) * superblock list, based upon its state. */ if (inode->i_state & I_SYNC) - goto out; + goto out_unlock_inode; /* * Only add valid (hashed) inodes to the superblock's @@ -1036,11 +1054,12 @@ void __mark_inode_dirty(struct inode *inode, int flags) */ if (!S_ISBLK(inode->i_mode)) { if (inode_unhashed(inode)) - goto out; + goto out_unlock_inode; } if (inode->i_state & I_FREEING) - goto out; + goto out_unlock_inode; + spin_unlock(&inode->i_lock); /* * If the inode was already on b_dirty/b_io/b_more_io, don't * reposition it (that would break b_dirty time-ordering). @@ -1065,7 +1084,10 @@ void __mark_inode_dirty(struct inode *inode, int flags) inode->dirtied_when = jiffies; list_move(&inode->i_wb_list, &bdi->wb.b_dirty); } + goto out; } +out_unlock_inode: + spin_unlock(&inode->i_lock); out: spin_unlock(&inode_lock); @@ -1111,14 +1133,16 @@ static void wait_sb_inodes(struct super_block *sb) * we still have to wait for that writeout. */ list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { - struct address_space *mapping; + struct address_space *mapping = inode->i_mapping; - if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) - continue; - mapping = inode->i_mapping; - if (mapping->nrpages == 0) + spin_lock(&inode->i_lock); + if ((inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) || + (mapping->nrpages == 0)) { + spin_unlock(&inode->i_lock); continue; + } __iget(inode); + spin_unlock(&inode->i_lock); spin_unlock(&inode_lock); /* * We hold a reference to 'inode' so it couldn't have diff --git a/fs/inode.c b/fs/inode.c index 0b3da4a77704..14b12c4ee026 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -27,6 +27,17 @@ #include #include +/* + * inode locking rules. + * + * inode->i_lock protects: + * inode->i_state, inode->i_hash, __iget() + * + * Lock ordering: + * inode_lock + * inode->i_lock + */ + /* * This is needed for the following functions: * - inode_has_buffers @@ -137,15 +148,6 @@ int proc_nr_inodes(ctl_table *table, int write, } #endif -static void wake_up_inode(struct inode *inode) -{ - /* - * Prevent speculative execution through spin_unlock(&inode_lock); - */ - smp_mb(); - wake_up_bit(&inode->i_state, __I_NEW); -} - /** * inode_init_always - perform inode structure intialisation * @sb: superblock inode belongs to @@ -336,7 +338,7 @@ static void init_once(void *foo) } /* - * inode_lock must be held + * inode->i_lock must be held */ void __iget(struct inode *inode) { @@ -413,7 +415,9 @@ void __insert_inode_hash(struct inode *inode, unsigned long hashval) struct hlist_head *b = inode_hashtable + hash(inode->i_sb, hashval); spin_lock(&inode_lock); + spin_lock(&inode->i_lock); hlist_add_head(&inode->i_hash, b); + spin_unlock(&inode->i_lock); spin_unlock(&inode_lock); } EXPORT_SYMBOL(__insert_inode_hash); @@ -438,7 +442,9 @@ static void __remove_inode_hash(struct inode *inode) void remove_inode_hash(struct inode *inode) { spin_lock(&inode_lock); + spin_lock(&inode->i_lock); hlist_del_init(&inode->i_hash); + spin_unlock(&inode->i_lock); spin_unlock(&inode_lock); } EXPORT_SYMBOL(remove_inode_hash); @@ -495,7 +501,9 @@ static void dispose_list(struct list_head *head) __inode_sb_list_del(inode); spin_unlock(&inode_lock); - wake_up_inode(inode); + spin_lock(&inode->i_lock); + wake_up_bit(&inode->i_state, __I_NEW); + spin_unlock(&inode->i_lock); destroy_inode(inode); } } @@ -518,10 +526,17 @@ void evict_inodes(struct super_block *sb) list_for_each_entry_safe(inode, next, &sb->s_inodes, i_sb_list) { if (atomic_read(&inode->i_count)) continue; - if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE)) + + spin_lock(&inode->i_lock); + if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE)) { + spin_unlock(&inode->i_lock); continue; + } inode->i_state |= I_FREEING; + if (!(inode->i_state & (I_DIRTY | I_SYNC))) + inodes_stat.nr_unused--; + spin_unlock(&inode->i_lock); /* * Move the inode off the IO lists and LRU once I_FREEING is @@ -529,8 +544,6 @@ void evict_inodes(struct super_block *sb) */ list_move(&inode->i_lru, &dispose); list_del_init(&inode->i_wb_list); - if (!(inode->i_state & (I_DIRTY | I_SYNC))) - inodes_stat.nr_unused--; } spin_unlock(&inode_lock); @@ -563,18 +576,26 @@ int invalidate_inodes(struct super_block *sb, bool kill_dirty) spin_lock(&inode_lock); list_for_each_entry_safe(inode, next, &sb->s_inodes, i_sb_list) { - if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE)) + spin_lock(&inode->i_lock); + if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE)) { + spin_unlock(&inode->i_lock); continue; + } if (inode->i_state & I_DIRTY && !kill_dirty) { + spin_unlock(&inode->i_lock); busy = 1; continue; } if (atomic_read(&inode->i_count)) { + spin_unlock(&inode->i_lock); busy = 1; continue; } inode->i_state |= I_FREEING; + if (!(inode->i_state & (I_DIRTY | I_SYNC))) + inodes_stat.nr_unused--; + spin_unlock(&inode->i_lock); /* * Move the inode off the IO lists and LRU once I_FREEING is @@ -582,8 +603,6 @@ int invalidate_inodes(struct super_block *sb, bool kill_dirty) */ list_move(&inode->i_lru, &dispose); list_del_init(&inode->i_wb_list); - if (!(inode->i_state & (I_DIRTY | I_SYNC))) - inodes_stat.nr_unused--; } spin_unlock(&inode_lock); @@ -641,8 +660,10 @@ static void prune_icache(int nr_to_scan) * Referenced or dirty inodes are still in use. Give them * another pass through the LRU as we canot reclaim them now. */ + spin_lock(&inode->i_lock); if (atomic_read(&inode->i_count) || (inode->i_state & ~I_REFERENCED)) { + spin_unlock(&inode->i_lock); list_del_init(&inode->i_lru); inodes_stat.nr_unused--; continue; @@ -650,12 +671,14 @@ static void prune_icache(int nr_to_scan) /* recently referenced inodes get one more pass */ if (inode->i_state & I_REFERENCED) { - list_move(&inode->i_lru, &inode_lru); inode->i_state &= ~I_REFERENCED; + spin_unlock(&inode->i_lock); + list_move(&inode->i_lru, &inode_lru); continue; } if (inode_has_buffers(inode) || inode->i_data.nrpages) { __iget(inode); + spin_unlock(&inode->i_lock); spin_unlock(&inode_lock); if (remove_inode_buffers(inode)) reap += invalidate_mapping_pages(&inode->i_data, @@ -666,11 +689,15 @@ static void prune_icache(int nr_to_scan) if (inode != list_entry(inode_lru.next, struct inode, i_lru)) continue; /* wrong inode or list_empty */ - if (!can_unuse(inode)) + spin_lock(&inode->i_lock); + if (!can_unuse(inode)) { + spin_unlock(&inode->i_lock); continue; + } } WARN_ON(inode->i_state & I_NEW); inode->i_state |= I_FREEING; + spin_unlock(&inode->i_lock); /* * Move the inode off the IO lists and LRU once I_FREEING is @@ -737,11 +764,13 @@ repeat: continue; if (!test(inode, data)) continue; + spin_lock(&inode->i_lock); if (inode->i_state & (I_FREEING|I_WILL_FREE)) { __wait_on_freeing_inode(inode); goto repeat; } __iget(inode); + spin_unlock(&inode->i_lock); return inode; } return NULL; @@ -763,11 +792,13 @@ repeat: continue; if (inode->i_sb != sb) continue; + spin_lock(&inode->i_lock); if (inode->i_state & (I_FREEING|I_WILL_FREE)) { __wait_on_freeing_inode(inode); goto repeat; } __iget(inode); + spin_unlock(&inode->i_lock); return inode; } return NULL; @@ -832,14 +863,23 @@ struct inode *new_inode(struct super_block *sb) inode = alloc_inode(sb); if (inode) { spin_lock(&inode_lock); - __inode_sb_list_add(inode); + spin_lock(&inode->i_lock); inode->i_state = 0; + spin_unlock(&inode->i_lock); + __inode_sb_list_add(inode); spin_unlock(&inode_lock); } return inode; } EXPORT_SYMBOL(new_inode); +/** + * unlock_new_inode - clear the I_NEW state and wake up any waiters + * @inode: new inode to unlock + * + * Called when the inode is fully initialised to clear the new state of the + * inode and wake up anyone waiting for the inode to finish initialisation. + */ void unlock_new_inode(struct inode *inode) { #ifdef CONFIG_DEBUG_LOCK_ALLOC @@ -859,19 +899,11 @@ void unlock_new_inode(struct inode *inode) } } #endif - /* - * This is special! We do not need the spinlock when clearing I_NEW, - * because we're guaranteed that nobody else tries to do anything about - * the state of the inode when it is locked, as we just created it (so - * there can be no old holders that haven't tested I_NEW). - * However we must emit the memory barrier so that other CPUs reliably - * see the clearing of I_NEW after the other inode initialisation has - * completed. - */ - smp_mb(); + spin_lock(&inode->i_lock); WARN_ON(!(inode->i_state & I_NEW)); inode->i_state &= ~I_NEW; - wake_up_inode(inode); + wake_up_bit(&inode->i_state, __I_NEW); + spin_unlock(&inode->i_lock); } EXPORT_SYMBOL(unlock_new_inode); @@ -900,9 +932,11 @@ static struct inode *get_new_inode(struct super_block *sb, if (set(inode, data)) goto set_failed; + spin_lock(&inode->i_lock); + inode->i_state = I_NEW; hlist_add_head(&inode->i_hash, head); + spin_unlock(&inode->i_lock); __inode_sb_list_add(inode); - inode->i_state = I_NEW; spin_unlock(&inode_lock); /* Return the locked inode with I_NEW set, the @@ -947,9 +981,11 @@ static struct inode *get_new_inode_fast(struct super_block *sb, old = find_inode_fast(sb, head, ino); if (!old) { inode->i_ino = ino; + spin_lock(&inode->i_lock); + inode->i_state = I_NEW; hlist_add_head(&inode->i_hash, head); + spin_unlock(&inode->i_lock); __inode_sb_list_add(inode); - inode->i_state = I_NEW; spin_unlock(&inode_lock); /* Return the locked inode with I_NEW set, the @@ -1034,15 +1070,19 @@ EXPORT_SYMBOL(iunique); struct inode *igrab(struct inode *inode) { spin_lock(&inode_lock); - if (!(inode->i_state & (I_FREEING|I_WILL_FREE))) + spin_lock(&inode->i_lock); + if (!(inode->i_state & (I_FREEING|I_WILL_FREE))) { __iget(inode); - else + spin_unlock(&inode->i_lock); + } else { + spin_unlock(&inode->i_lock); /* * Handle the case where s_op->clear_inode is not been * called yet, and somebody is calling igrab * while the inode is getting freed. */ inode = NULL; + } spin_unlock(&inode_lock); return inode; } @@ -1271,7 +1311,6 @@ int insert_inode_locked(struct inode *inode) ino_t ino = inode->i_ino; struct hlist_head *head = inode_hashtable + hash(sb, ino); - inode->i_state |= I_NEW; while (1) { struct hlist_node *node; struct inode *old = NULL; @@ -1281,16 +1320,23 @@ int insert_inode_locked(struct inode *inode) continue; if (old->i_sb != sb) continue; - if (old->i_state & (I_FREEING|I_WILL_FREE)) + spin_lock(&old->i_lock); + if (old->i_state & (I_FREEING|I_WILL_FREE)) { + spin_unlock(&old->i_lock); continue; + } break; } if (likely(!node)) { + spin_lock(&inode->i_lock); + inode->i_state |= I_NEW; hlist_add_head(&inode->i_hash, head); + spin_unlock(&inode->i_lock); spin_unlock(&inode_lock); return 0; } __iget(old); + spin_unlock(&old->i_lock); spin_unlock(&inode_lock); wait_on_inode(old); if (unlikely(!inode_unhashed(old))) { @@ -1308,8 +1354,6 @@ int insert_inode_locked4(struct inode *inode, unsigned long hashval, struct super_block *sb = inode->i_sb; struct hlist_head *head = inode_hashtable + hash(sb, hashval); - inode->i_state |= I_NEW; - while (1) { struct hlist_node *node; struct inode *old = NULL; @@ -1320,16 +1364,23 @@ int insert_inode_locked4(struct inode *inode, unsigned long hashval, continue; if (!test(old, data)) continue; - if (old->i_state & (I_FREEING|I_WILL_FREE)) + spin_lock(&old->i_lock); + if (old->i_state & (I_FREEING|I_WILL_FREE)) { + spin_unlock(&old->i_lock); continue; + } break; } if (likely(!node)) { + spin_lock(&inode->i_lock); + inode->i_state |= I_NEW; hlist_add_head(&inode->i_hash, head); + spin_unlock(&inode->i_lock); spin_unlock(&inode_lock); return 0; } __iget(old); + spin_unlock(&old->i_lock); spin_unlock(&inode_lock); wait_on_inode(old); if (unlikely(!inode_unhashed(old))) { @@ -1375,6 +1426,9 @@ static void iput_final(struct inode *inode) const struct super_operations *op = inode->i_sb->s_op; int drop; + spin_lock(&inode->i_lock); + WARN_ON(inode->i_state & I_NEW); + if (op && op->drop_inode) drop = op->drop_inode(inode); else @@ -1386,21 +1440,23 @@ static void iput_final(struct inode *inode) if (!(inode->i_state & (I_DIRTY|I_SYNC))) { inode_lru_list_add(inode); } + spin_unlock(&inode->i_lock); spin_unlock(&inode_lock); return; } - WARN_ON(inode->i_state & I_NEW); inode->i_state |= I_WILL_FREE; + spin_unlock(&inode->i_lock); spin_unlock(&inode_lock); write_inode_now(inode, 1); spin_lock(&inode_lock); + spin_lock(&inode->i_lock); WARN_ON(inode->i_state & I_NEW); inode->i_state &= ~I_WILL_FREE; __remove_inode_hash(inode); } - WARN_ON(inode->i_state & I_NEW); inode->i_state |= I_FREEING; + spin_unlock(&inode->i_lock); /* * Move the inode off the IO lists and LRU once I_FREEING is @@ -1413,8 +1469,10 @@ static void iput_final(struct inode *inode) spin_unlock(&inode_lock); evict(inode); remove_inode_hash(inode); - wake_up_inode(inode); + spin_lock(&inode->i_lock); + wake_up_bit(&inode->i_state, __I_NEW); BUG_ON(inode->i_state != (I_FREEING | I_CLEAR)); + spin_unlock(&inode->i_lock); destroy_inode(inode); } @@ -1611,9 +1669,8 @@ EXPORT_SYMBOL(inode_wait); * to recheck inode state. * * It doesn't matter if I_NEW is not set initially, a call to - * wake_up_inode() after removing from the hash list will DTRT. - * - * This is called with inode_lock held. + * wake_up_bit(&inode->i_state, __I_NEW) after removing from the hash list + * will DTRT. */ static void __wait_on_freeing_inode(struct inode *inode) { @@ -1621,6 +1678,7 @@ static void __wait_on_freeing_inode(struct inode *inode) DEFINE_WAIT_BIT(wait, &inode->i_state, __I_NEW); wq = bit_waitqueue(&inode->i_state, __I_NEW); prepare_to_wait(wq, &wait.wait, TASK_UNINTERRUPTIBLE); + spin_unlock(&inode->i_lock); spin_unlock(&inode_lock); schedule(); finish_wait(wq, &wait.wait); diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c index 4c29fcf557d1..4dd53fb44124 100644 --- a/fs/notify/inode_mark.c +++ b/fs/notify/inode_mark.c @@ -254,8 +254,11 @@ void fsnotify_unmount_inodes(struct list_head *list) * I_WILL_FREE, or I_NEW which is fine because by that point * the inode cannot have any associated watches. */ - if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) + spin_lock(&inode->i_lock); + if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) { + spin_unlock(&inode->i_lock); continue; + } /* * If i_count is zero, the inode cannot have any watches and @@ -263,8 +266,10 @@ void fsnotify_unmount_inodes(struct list_head *list) * evict all inodes with zero i_count from icache which is * unnecessarily violent and may in fact be illegal to do. */ - if (!atomic_read(&inode->i_count)) + if (!atomic_read(&inode->i_count)) { + spin_unlock(&inode->i_lock); continue; + } need_iput_tmp = need_iput; need_iput = NULL; @@ -274,13 +279,17 @@ void fsnotify_unmount_inodes(struct list_head *list) __iget(inode); else need_iput_tmp = NULL; + spin_unlock(&inode->i_lock); /* In case the dropping of a reference would nuke next_i. */ if ((&next_i->i_sb_list != list) && - atomic_read(&next_i->i_count) && - !(next_i->i_state & (I_FREEING | I_WILL_FREE))) { - __iget(next_i); - need_iput = next_i; + atomic_read(&next_i->i_count)) { + spin_lock(&next_i->i_lock); + if (!(next_i->i_state & (I_FREEING | I_WILL_FREE))) { + __iget(next_i); + need_iput = next_i; + } + spin_unlock(&next_i->i_lock); } /* diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index a2a622e079f0..a1470fda366c 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -902,18 +902,19 @@ static void add_dquot_ref(struct super_block *sb, int type) spin_lock(&inode_lock); list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { - if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) + spin_lock(&inode->i_lock); + if ((inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) || + !atomic_read(&inode->i_writecount) || + !dqinit_needed(inode, type)) { + spin_unlock(&inode->i_lock); continue; + } #ifdef CONFIG_QUOTA_DEBUG if (unlikely(inode_get_rsv_space(inode) > 0)) reserved = 1; #endif - if (!atomic_read(&inode->i_writecount)) - continue; - if (!dqinit_needed(inode, type)) - continue; - __iget(inode); + spin_unlock(&inode->i_lock); spin_unlock(&inode_lock); iput(old_inode); -- cgit From b2b2af8e614b4dcd8aca1369d82ce5ad0461a7b1 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 22 Mar 2011 22:23:37 +1100 Subject: fs: factor inode disposal We have a couple of places that dispose of inodes. factor the disposal into evict() to isolate this code and make it simpler to peel away the inode_lock from the code. While doing this, change the logic flow in iput_final() to separate the different cases that need to be handled to make the transitions the inode goes through more obvious. Signed-off-by: Dave Chinner Signed-off-by: Al Viro --- fs/inode.c | 104 ++++++++++++++++++++++++------------------------------------- 1 file changed, 41 insertions(+), 63 deletions(-) (limited to 'fs') diff --git a/fs/inode.c b/fs/inode.c index 14b12c4ee026..f752a959254b 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -422,17 +422,6 @@ void __insert_inode_hash(struct inode *inode, unsigned long hashval) } EXPORT_SYMBOL(__insert_inode_hash); -/** - * __remove_inode_hash - remove an inode from the hash - * @inode: inode to unhash - * - * Remove an inode from the superblock. - */ -static void __remove_inode_hash(struct inode *inode) -{ - hlist_del_init(&inode->i_hash); -} - /** * remove_inode_hash - remove an inode from the hash * @inode: inode to unhash @@ -462,10 +451,31 @@ void end_writeback(struct inode *inode) } EXPORT_SYMBOL(end_writeback); +/* + * Free the inode passed in, removing it from the lists it is still connected + * to. We remove any pages still attached to the inode and wait for any IO that + * is still in progress before finally destroying the inode. + * + * An inode must already be marked I_FREEING so that we avoid the inode being + * moved back onto lists if we race with other code that manipulates the lists + * (e.g. writeback_single_inode). The caller is responsible for setting this. + * + * An inode must already be removed from the LRU list before being evicted from + * the cache. This should occur atomically with setting the I_FREEING state + * flag, so no inodes here should ever be on the LRU when being evicted. + */ static void evict(struct inode *inode) { const struct super_operations *op = inode->i_sb->s_op; + BUG_ON(!(inode->i_state & I_FREEING)); + BUG_ON(!list_empty(&inode->i_lru)); + + spin_lock(&inode_lock); + list_del_init(&inode->i_wb_list); + __inode_sb_list_del(inode); + spin_unlock(&inode_lock); + if (op->evict_inode) { op->evict_inode(inode); } else { @@ -477,6 +487,15 @@ static void evict(struct inode *inode) bd_forget(inode); if (S_ISCHR(inode->i_mode) && inode->i_cdev) cd_forget(inode); + + remove_inode_hash(inode); + + spin_lock(&inode->i_lock); + wake_up_bit(&inode->i_state, __I_NEW); + BUG_ON(inode->i_state != (I_FREEING | I_CLEAR)); + spin_unlock(&inode->i_lock); + + destroy_inode(inode); } /* @@ -495,16 +514,6 @@ static void dispose_list(struct list_head *head) list_del_init(&inode->i_lru); evict(inode); - - spin_lock(&inode_lock); - __remove_inode_hash(inode); - __inode_sb_list_del(inode); - spin_unlock(&inode_lock); - - spin_lock(&inode->i_lock); - wake_up_bit(&inode->i_state, __I_NEW); - spin_unlock(&inode->i_lock); - destroy_inode(inode); } } @@ -537,13 +546,7 @@ void evict_inodes(struct super_block *sb) if (!(inode->i_state & (I_DIRTY | I_SYNC))) inodes_stat.nr_unused--; spin_unlock(&inode->i_lock); - - /* - * Move the inode off the IO lists and LRU once I_FREEING is - * set so that it won't get moved back on there if it is dirty. - */ list_move(&inode->i_lru, &dispose); - list_del_init(&inode->i_wb_list); } spin_unlock(&inode_lock); @@ -596,13 +599,7 @@ int invalidate_inodes(struct super_block *sb, bool kill_dirty) if (!(inode->i_state & (I_DIRTY | I_SYNC))) inodes_stat.nr_unused--; spin_unlock(&inode->i_lock); - - /* - * Move the inode off the IO lists and LRU once I_FREEING is - * set so that it won't get moved back on there if it is dirty. - */ list_move(&inode->i_lru, &dispose); - list_del_init(&inode->i_wb_list); } spin_unlock(&inode_lock); @@ -699,12 +696,7 @@ static void prune_icache(int nr_to_scan) inode->i_state |= I_FREEING; spin_unlock(&inode->i_lock); - /* - * Move the inode off the IO lists and LRU once I_FREEING is - * set so that it won't get moved back on there if it is dirty. - */ list_move(&inode->i_lru, &freeable); - list_del_init(&inode->i_wb_list); inodes_stat.nr_unused--; } if (current_is_kswapd()) @@ -1434,16 +1426,16 @@ static void iput_final(struct inode *inode) else drop = generic_drop_inode(inode); + if (!drop && (sb->s_flags & MS_ACTIVE)) { + inode->i_state |= I_REFERENCED; + if (!(inode->i_state & (I_DIRTY|I_SYNC))) + inode_lru_list_add(inode); + spin_unlock(&inode->i_lock); + spin_unlock(&inode_lock); + return; + } + if (!drop) { - if (sb->s_flags & MS_ACTIVE) { - inode->i_state |= I_REFERENCED; - if (!(inode->i_state & (I_DIRTY|I_SYNC))) { - inode_lru_list_add(inode); - } - spin_unlock(&inode->i_lock); - spin_unlock(&inode_lock); - return; - } inode->i_state |= I_WILL_FREE; spin_unlock(&inode->i_lock); spin_unlock(&inode_lock); @@ -1452,28 +1444,14 @@ static void iput_final(struct inode *inode) spin_lock(&inode->i_lock); WARN_ON(inode->i_state & I_NEW); inode->i_state &= ~I_WILL_FREE; - __remove_inode_hash(inode); } inode->i_state |= I_FREEING; - spin_unlock(&inode->i_lock); - - /* - * Move the inode off the IO lists and LRU once I_FREEING is - * set so that it won't get moved back on there if it is dirty. - */ inode_lru_list_del(inode); - list_del_init(&inode->i_wb_list); - - __inode_sb_list_del(inode); + spin_unlock(&inode->i_lock); spin_unlock(&inode_lock); + evict(inode); - remove_inode_hash(inode); - spin_lock(&inode->i_lock); - wake_up_bit(&inode->i_state, __I_NEW); - BUG_ON(inode->i_state != (I_FREEING | I_CLEAR)); - spin_unlock(&inode->i_lock); - destroy_inode(inode); } /** -- cgit From 02afc410f363f98ac4f186341e38dcec13fc0e60 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 22 Mar 2011 22:23:38 +1100 Subject: fs: Lock the inode LRU list separately Introduce the inode_lru_lock to protect the inode_lru list. This lock is nested inside the inode->i_lock to allow the inode to be added to the LRU list in iput_final without needing to deal with lock inversions. This keeps iput_final() clean and neat. Further, where marking the inode I_FREEING and removing it from the LRU, move the LRU list manipulation within the inode->i_lock to keep the list manipulation consistent with iput_final. This also means that most of the open coded LRU list removal + unused inode accounting can now use the inode_lru_list_del() wrappers which cleans the code up further. However, this locking change means what the LRU traversal in prune_icache() inverts this lock ordering and needs to use trylock semantics on the inode->i_lock to avoid deadlocking. In these cases, if we fail to lock the inode we move it to the back of the LRU to prevent spinning on it. Signed-off-by: Dave Chinner Signed-off-by: Al Viro --- fs/inode.c | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) (limited to 'fs') diff --git a/fs/inode.c b/fs/inode.c index f752a959254b..b19cb6ee6ca3 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -32,10 +32,13 @@ * * inode->i_lock protects: * inode->i_state, inode->i_hash, __iget() + * inode_lru_lock protects: + * inode_lru, inode->i_lru * * Lock ordering: * inode_lock * inode->i_lock + * inode_lru_lock */ /* @@ -85,6 +88,7 @@ static unsigned int i_hash_shift __read_mostly; */ static LIST_HEAD(inode_lru); +static DEFINE_SPINLOCK(inode_lru_lock); static struct hlist_head *inode_hashtable __read_mostly; /* @@ -356,18 +360,22 @@ EXPORT_SYMBOL(ihold); static void inode_lru_list_add(struct inode *inode) { + spin_lock(&inode_lru_lock); if (list_empty(&inode->i_lru)) { list_add(&inode->i_lru, &inode_lru); inodes_stat.nr_unused++; } + spin_unlock(&inode_lru_lock); } static void inode_lru_list_del(struct inode *inode) { + spin_lock(&inode_lru_lock); if (!list_empty(&inode->i_lru)) { list_del_init(&inode->i_lru); inodes_stat.nr_unused--; } + spin_unlock(&inode_lru_lock); } static inline void __inode_sb_list_add(struct inode *inode) @@ -543,10 +551,9 @@ void evict_inodes(struct super_block *sb) } inode->i_state |= I_FREEING; - if (!(inode->i_state & (I_DIRTY | I_SYNC))) - inodes_stat.nr_unused--; + inode_lru_list_del(inode); spin_unlock(&inode->i_lock); - list_move(&inode->i_lru, &dispose); + list_add(&inode->i_lru, &dispose); } spin_unlock(&inode_lock); @@ -596,10 +603,9 @@ int invalidate_inodes(struct super_block *sb, bool kill_dirty) } inode->i_state |= I_FREEING; - if (!(inode->i_state & (I_DIRTY | I_SYNC))) - inodes_stat.nr_unused--; + inode_lru_list_del(inode); spin_unlock(&inode->i_lock); - list_move(&inode->i_lru, &dispose); + list_add(&inode->i_lru, &dispose); } spin_unlock(&inode_lock); @@ -623,7 +629,7 @@ static int can_unuse(struct inode *inode) /* * Scan `goal' inodes on the unused list for freeable ones. They are moved to a - * temporary list and then are freed outside inode_lock by dispose_list(). + * temporary list and then are freed outside inode_lru_lock by dispose_list(). * * Any inodes which are pinned purely because of attached pagecache have their * pagecache removed. If the inode has metadata buffers attached to @@ -645,6 +651,7 @@ static void prune_icache(int nr_to_scan) down_read(&iprune_sem); spin_lock(&inode_lock); + spin_lock(&inode_lru_lock); for (nr_scanned = 0; nr_scanned < nr_to_scan; nr_scanned++) { struct inode *inode; @@ -653,11 +660,20 @@ static void prune_icache(int nr_to_scan) inode = list_entry(inode_lru.prev, struct inode, i_lru); + /* + * we are inverting the inode_lru_lock/inode->i_lock here, + * so use a trylock. If we fail to get the lock, just move the + * inode to the back of the list so we don't spin on it. + */ + if (!spin_trylock(&inode->i_lock)) { + list_move(&inode->i_lru, &inode_lru); + continue; + } + /* * Referenced or dirty inodes are still in use. Give them * another pass through the LRU as we canot reclaim them now. */ - spin_lock(&inode->i_lock); if (atomic_read(&inode->i_count) || (inode->i_state & ~I_REFERENCED)) { spin_unlock(&inode->i_lock); @@ -676,17 +692,21 @@ static void prune_icache(int nr_to_scan) if (inode_has_buffers(inode) || inode->i_data.nrpages) { __iget(inode); spin_unlock(&inode->i_lock); + spin_unlock(&inode_lru_lock); spin_unlock(&inode_lock); if (remove_inode_buffers(inode)) reap += invalidate_mapping_pages(&inode->i_data, 0, -1); iput(inode); spin_lock(&inode_lock); + spin_lock(&inode_lru_lock); if (inode != list_entry(inode_lru.next, struct inode, i_lru)) continue; /* wrong inode or list_empty */ - spin_lock(&inode->i_lock); + /* avoid lock inversions with trylock */ + if (!spin_trylock(&inode->i_lock)) + continue; if (!can_unuse(inode)) { spin_unlock(&inode->i_lock); continue; @@ -703,6 +723,7 @@ static void prune_icache(int nr_to_scan) __count_vm_events(KSWAPD_INODESTEAL, reap); else __count_vm_events(PGINODESTEAL, reap); + spin_unlock(&inode_lru_lock); spin_unlock(&inode_lock); dispose_list(&freeable); -- cgit From f283c86afe6aa70b733d1ecebad5d9464943b774 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 22 Mar 2011 22:23:39 +1100 Subject: fs: remove inode_lock from iput_final and prune_icache Now that inode state changes are protected by the inode->i_lock and the inode LRU manipulations by the inode_lru_lock, we can remove the inode_lock from prune_icache and the initial part of iput_final(). instead of using the inode_lock to protect the inode during iput_final, use the inode->i_lock instead. This protects the inode against new references being taken while we change the inode state to I_FREEING, as well as preventing prune_icache from grabbing the inode while we are manipulating it. Hence we no longer need the inode_lock in iput_final prior to setting I_FREEING on the inode. For prune_icache, we no longer need the inode_lock to protect the LRU list, and the inodes themselves are protected against freeing races by the inode->i_lock. Hence we can lift the inode_lock from prune_icache as well. Signed-off-by: Dave Chinner Signed-off-by: Al Viro --- fs/inode.c | 17 +++-------------- fs/logfs/inode.c | 2 +- 2 files changed, 4 insertions(+), 15 deletions(-) (limited to 'fs') diff --git a/fs/inode.c b/fs/inode.c index b19cb6ee6ca3..389f5a247599 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -650,7 +650,6 @@ static void prune_icache(int nr_to_scan) unsigned long reap = 0; down_read(&iprune_sem); - spin_lock(&inode_lock); spin_lock(&inode_lru_lock); for (nr_scanned = 0; nr_scanned < nr_to_scan; nr_scanned++) { struct inode *inode; @@ -676,8 +675,8 @@ static void prune_icache(int nr_to_scan) */ if (atomic_read(&inode->i_count) || (inode->i_state & ~I_REFERENCED)) { - spin_unlock(&inode->i_lock); list_del_init(&inode->i_lru); + spin_unlock(&inode->i_lock); inodes_stat.nr_unused--; continue; } @@ -685,20 +684,18 @@ static void prune_icache(int nr_to_scan) /* recently referenced inodes get one more pass */ if (inode->i_state & I_REFERENCED) { inode->i_state &= ~I_REFERENCED; - spin_unlock(&inode->i_lock); list_move(&inode->i_lru, &inode_lru); + spin_unlock(&inode->i_lock); continue; } if (inode_has_buffers(inode) || inode->i_data.nrpages) { __iget(inode); spin_unlock(&inode->i_lock); spin_unlock(&inode_lru_lock); - spin_unlock(&inode_lock); if (remove_inode_buffers(inode)) reap += invalidate_mapping_pages(&inode->i_data, 0, -1); iput(inode); - spin_lock(&inode_lock); spin_lock(&inode_lru_lock); if (inode != list_entry(inode_lru.next, @@ -724,7 +721,6 @@ static void prune_icache(int nr_to_scan) else __count_vm_events(PGINODESTEAL, reap); spin_unlock(&inode_lru_lock); - spin_unlock(&inode_lock); dispose_list(&freeable); up_read(&iprune_sem); @@ -1082,7 +1078,6 @@ EXPORT_SYMBOL(iunique); struct inode *igrab(struct inode *inode) { - spin_lock(&inode_lock); spin_lock(&inode->i_lock); if (!(inode->i_state & (I_FREEING|I_WILL_FREE))) { __iget(inode); @@ -1096,7 +1091,6 @@ struct inode *igrab(struct inode *inode) */ inode = NULL; } - spin_unlock(&inode_lock); return inode; } EXPORT_SYMBOL(igrab); @@ -1439,7 +1433,6 @@ static void iput_final(struct inode *inode) const struct super_operations *op = inode->i_sb->s_op; int drop; - spin_lock(&inode->i_lock); WARN_ON(inode->i_state & I_NEW); if (op && op->drop_inode) @@ -1452,16 +1445,13 @@ static void iput_final(struct inode *inode) if (!(inode->i_state & (I_DIRTY|I_SYNC))) inode_lru_list_add(inode); spin_unlock(&inode->i_lock); - spin_unlock(&inode_lock); return; } if (!drop) { inode->i_state |= I_WILL_FREE; spin_unlock(&inode->i_lock); - spin_unlock(&inode_lock); write_inode_now(inode, 1); - spin_lock(&inode_lock); spin_lock(&inode->i_lock); WARN_ON(inode->i_state & I_NEW); inode->i_state &= ~I_WILL_FREE; @@ -1470,7 +1460,6 @@ static void iput_final(struct inode *inode) inode->i_state |= I_FREEING; inode_lru_list_del(inode); spin_unlock(&inode->i_lock); - spin_unlock(&inode_lock); evict(inode); } @@ -1489,7 +1478,7 @@ void iput(struct inode *inode) if (inode) { BUG_ON(inode->i_state & I_CLEAR); - if (atomic_dec_and_lock(&inode->i_count, &inode_lock)) + if (atomic_dec_and_lock(&inode->i_count, &inode->i_lock)) iput_final(inode); } } diff --git a/fs/logfs/inode.c b/fs/logfs/inode.c index 03b8c240aeda..edfea7a3a747 100644 --- a/fs/logfs/inode.c +++ b/fs/logfs/inode.c @@ -293,7 +293,7 @@ static int logfs_write_inode(struct inode *inode, struct writeback_control *wbc) return ret; } -/* called with inode_lock held */ +/* called with inode->i_lock held */ static int logfs_drop_inode(struct inode *inode) { struct logfs_super *super = logfs_super(inode->i_sb); -- cgit From 55fa6091d83160ca772fc37cebae45d42695a708 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 22 Mar 2011 22:23:40 +1100 Subject: fs: move i_sb_list out from under inode_lock Protect the per-sb inode list with a new global lock inode_sb_list_lock and use it to protect the list manipulations and traversals. This lock replaces the inode_lock as the inodes on the list can be validity checked while holding the inode->i_lock and hence the inode_lock is no longer needed to protect the list. Signed-off-by: Dave Chinner Signed-off-by: Al Viro --- fs/drop_caches.c | 9 +++++---- fs/fs-writeback.c | 21 +++++++++++---------- fs/inode.c | 43 +++++++++++++++++++++++-------------------- fs/internal.h | 2 ++ fs/notify/inode_mark.c | 20 ++++++++++---------- fs/quota/dquot.c | 28 ++++++++++++++++------------ 6 files changed, 67 insertions(+), 56 deletions(-) (limited to 'fs') diff --git a/fs/drop_caches.c b/fs/drop_caches.c index 6c6f73ba0868..98b77c89494c 100644 --- a/fs/drop_caches.c +++ b/fs/drop_caches.c @@ -8,6 +8,7 @@ #include #include #include +#include "internal.h" /* A global variable is a bit ugly, but it keeps the code simple */ int sysctl_drop_caches; @@ -16,7 +17,7 @@ static void drop_pagecache_sb(struct super_block *sb, void *unused) { struct inode *inode, *toput_inode = NULL; - spin_lock(&inode_lock); + spin_lock(&inode_sb_list_lock); list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { spin_lock(&inode->i_lock); if ((inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) || @@ -26,13 +27,13 @@ static void drop_pagecache_sb(struct super_block *sb, void *unused) } __iget(inode); spin_unlock(&inode->i_lock); - spin_unlock(&inode_lock); + spin_unlock(&inode_sb_list_lock); invalidate_mapping_pages(inode->i_mapping, 0, -1); iput(toput_inode); toput_inode = inode; - spin_lock(&inode_lock); + spin_lock(&inode_sb_list_lock); } - spin_unlock(&inode_lock); + spin_unlock(&inode_sb_list_lock); iput(toput_inode); } diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index efd1ebe879cc..5de56a2182bb 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -1123,7 +1123,7 @@ static void wait_sb_inodes(struct super_block *sb) */ WARN_ON(!rwsem_is_locked(&sb->s_umount)); - spin_lock(&inode_lock); + spin_lock(&inode_sb_list_lock); /* * Data integrity sync. Must wait for all pages under writeback, @@ -1143,14 +1143,15 @@ static void wait_sb_inodes(struct super_block *sb) } __iget(inode); spin_unlock(&inode->i_lock); - spin_unlock(&inode_lock); + spin_unlock(&inode_sb_list_lock); + /* - * We hold a reference to 'inode' so it couldn't have - * been removed from s_inodes list while we dropped the - * inode_lock. We cannot iput the inode now as we can - * be holding the last reference and we cannot iput it - * under inode_lock. So we keep the reference and iput - * it later. + * We hold a reference to 'inode' so it couldn't have been + * removed from s_inodes list while we dropped the + * inode_sb_list_lock. We cannot iput the inode now as we can + * be holding the last reference and we cannot iput it under + * inode_sb_list_lock. So we keep the reference and iput it + * later. */ iput(old_inode); old_inode = inode; @@ -1159,9 +1160,9 @@ static void wait_sb_inodes(struct super_block *sb) cond_resched(); - spin_lock(&inode_lock); + spin_lock(&inode_sb_list_lock); } - spin_unlock(&inode_lock); + spin_unlock(&inode_sb_list_lock); iput(old_inode); } diff --git a/fs/inode.c b/fs/inode.c index 389f5a247599..785b1ab23ff0 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -34,10 +34,15 @@ * inode->i_state, inode->i_hash, __iget() * inode_lru_lock protects: * inode_lru, inode->i_lru + * inode_sb_list_lock protects: + * sb->s_inodes, inode->i_sb_list * * Lock ordering: * inode_lock * inode->i_lock + * + * inode_sb_list_lock + * inode->i_lock * inode_lru_lock */ @@ -99,6 +104,8 @@ static struct hlist_head *inode_hashtable __read_mostly; */ DEFINE_SPINLOCK(inode_lock); +__cacheline_aligned_in_smp DEFINE_SPINLOCK(inode_sb_list_lock); + /* * iprune_sem provides exclusion between the icache shrinking and the * umount path. @@ -378,26 +385,23 @@ static void inode_lru_list_del(struct inode *inode) spin_unlock(&inode_lru_lock); } -static inline void __inode_sb_list_add(struct inode *inode) -{ - list_add(&inode->i_sb_list, &inode->i_sb->s_inodes); -} - /** * inode_sb_list_add - add inode to the superblock list of inodes * @inode: inode to add */ void inode_sb_list_add(struct inode *inode) { - spin_lock(&inode_lock); - __inode_sb_list_add(inode); - spin_unlock(&inode_lock); + spin_lock(&inode_sb_list_lock); + list_add(&inode->i_sb_list, &inode->i_sb->s_inodes); + spin_unlock(&inode_sb_list_lock); } EXPORT_SYMBOL_GPL(inode_sb_list_add); -static inline void __inode_sb_list_del(struct inode *inode) +static inline void inode_sb_list_del(struct inode *inode) { + spin_lock(&inode_sb_list_lock); list_del_init(&inode->i_sb_list); + spin_unlock(&inode_sb_list_lock); } static unsigned long hash(struct super_block *sb, unsigned long hashval) @@ -481,9 +485,10 @@ static void evict(struct inode *inode) spin_lock(&inode_lock); list_del_init(&inode->i_wb_list); - __inode_sb_list_del(inode); spin_unlock(&inode_lock); + inode_sb_list_del(inode); + if (op->evict_inode) { op->evict_inode(inode); } else { @@ -539,7 +544,7 @@ void evict_inodes(struct super_block *sb) struct inode *inode, *next; LIST_HEAD(dispose); - spin_lock(&inode_lock); + spin_lock(&inode_sb_list_lock); list_for_each_entry_safe(inode, next, &sb->s_inodes, i_sb_list) { if (atomic_read(&inode->i_count)) continue; @@ -555,7 +560,7 @@ void evict_inodes(struct super_block *sb) spin_unlock(&inode->i_lock); list_add(&inode->i_lru, &dispose); } - spin_unlock(&inode_lock); + spin_unlock(&inode_sb_list_lock); dispose_list(&dispose); @@ -584,7 +589,7 @@ int invalidate_inodes(struct super_block *sb, bool kill_dirty) struct inode *inode, *next; LIST_HEAD(dispose); - spin_lock(&inode_lock); + spin_lock(&inode_sb_list_lock); list_for_each_entry_safe(inode, next, &sb->s_inodes, i_sb_list) { spin_lock(&inode->i_lock); if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE)) { @@ -607,7 +612,7 @@ int invalidate_inodes(struct super_block *sb, bool kill_dirty) spin_unlock(&inode->i_lock); list_add(&inode->i_lru, &dispose); } - spin_unlock(&inode_lock); + spin_unlock(&inode_sb_list_lock); dispose_list(&dispose); @@ -867,16 +872,14 @@ struct inode *new_inode(struct super_block *sb) { struct inode *inode; - spin_lock_prefetch(&inode_lock); + spin_lock_prefetch(&inode_sb_list_lock); inode = alloc_inode(sb); if (inode) { - spin_lock(&inode_lock); spin_lock(&inode->i_lock); inode->i_state = 0; spin_unlock(&inode->i_lock); - __inode_sb_list_add(inode); - spin_unlock(&inode_lock); + inode_sb_list_add(inode); } return inode; } @@ -945,7 +948,7 @@ static struct inode *get_new_inode(struct super_block *sb, inode->i_state = I_NEW; hlist_add_head(&inode->i_hash, head); spin_unlock(&inode->i_lock); - __inode_sb_list_add(inode); + inode_sb_list_add(inode); spin_unlock(&inode_lock); /* Return the locked inode with I_NEW set, the @@ -994,7 +997,7 @@ static struct inode *get_new_inode_fast(struct super_block *sb, inode->i_state = I_NEW; hlist_add_head(&inode->i_hash, head); spin_unlock(&inode->i_lock); - __inode_sb_list_add(inode); + inode_sb_list_add(inode); spin_unlock(&inode_lock); /* Return the locked inode with I_NEW set, the diff --git a/fs/internal.h b/fs/internal.h index 8318059b42c6..7013ae0c88c1 100644 --- a/fs/internal.h +++ b/fs/internal.h @@ -125,6 +125,8 @@ extern long do_handle_open(int mountdirfd, /* * inode.c */ +extern spinlock_t inode_sb_list_lock; + extern int get_nr_dirty_inodes(void); extern void evict_inodes(struct super_block *); extern int invalidate_inodes(struct super_block *, bool); diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c index 4dd53fb44124..fb3b3c5ef0ee 100644 --- a/fs/notify/inode_mark.c +++ b/fs/notify/inode_mark.c @@ -29,6 +29,8 @@ #include #include "fsnotify.h" +#include "../internal.h" + /* * Recalculate the mask of events relevant to a given inode locked. */ @@ -237,15 +239,14 @@ out: * fsnotify_unmount_inodes - an sb is unmounting. handle any watched inodes. * @list: list of inodes being unmounted (sb->s_inodes) * - * Called with inode_lock held, protecting the unmounting super block's list - * of inodes, and with iprune_mutex held, keeping shrink_icache_memory() at bay. - * We temporarily drop inode_lock, however, and CAN block. + * Called during unmount with no locks held, so needs to be safe against + * concurrent modifiers. We temporarily drop inode_sb_list_lock and CAN block. */ void fsnotify_unmount_inodes(struct list_head *list) { struct inode *inode, *next_i, *need_iput = NULL; - spin_lock(&inode_lock); + spin_lock(&inode_sb_list_lock); list_for_each_entry_safe(inode, next_i, list, i_sb_list) { struct inode *need_iput_tmp; @@ -293,12 +294,11 @@ void fsnotify_unmount_inodes(struct list_head *list) } /* - * We can safely drop inode_lock here because we hold + * We can safely drop inode_sb_list_lock here because we hold * references on both inode and next_i. Also no new inodes - * will be added since the umount has begun. Finally, - * iprune_mutex keeps shrink_icache_memory() away. + * will be added since the umount has begun. */ - spin_unlock(&inode_lock); + spin_unlock(&inode_sb_list_lock); if (need_iput_tmp) iput(need_iput_tmp); @@ -310,7 +310,7 @@ void fsnotify_unmount_inodes(struct list_head *list) iput(inode); - spin_lock(&inode_lock); + spin_lock(&inode_sb_list_lock); } - spin_unlock(&inode_lock); + spin_unlock(&inode_sb_list_lock); } diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index a1470fda366c..fcc8ae75d874 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -76,7 +76,7 @@ #include #include #include -#include /* for inode_lock, oddly enough.. */ +#include "../internal.h" /* ugh */ #include @@ -900,7 +900,7 @@ static void add_dquot_ref(struct super_block *sb, int type) int reserved = 0; #endif - spin_lock(&inode_lock); + spin_lock(&inode_sb_list_lock); list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { spin_lock(&inode->i_lock); if ((inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) || @@ -915,19 +915,23 @@ static void add_dquot_ref(struct super_block *sb, int type) #endif __iget(inode); spin_unlock(&inode->i_lock); - spin_unlock(&inode_lock); + spin_unlock(&inode_sb_list_lock); iput(old_inode); __dquot_initialize(inode, type); - /* We hold a reference to 'inode' so it couldn't have been - * removed from s_inodes list while we dropped the inode_lock. - * We cannot iput the inode now as we can be holding the last - * reference and we cannot iput it under inode_lock. So we - * keep the reference and iput it later. */ + + /* + * We hold a reference to 'inode' so it couldn't have been + * removed from s_inodes list while we dropped the + * inode_sb_list_lock We cannot iput the inode now as we can be + * holding the last reference and we cannot iput it under + * inode_sb_list_lock. So we keep the reference and iput it + * later. + */ old_inode = inode; - spin_lock(&inode_lock); + spin_lock(&inode_sb_list_lock); } - spin_unlock(&inode_lock); + spin_unlock(&inode_sb_list_lock); iput(old_inode); #ifdef CONFIG_QUOTA_DEBUG @@ -1008,7 +1012,7 @@ static void remove_dquot_ref(struct super_block *sb, int type, struct inode *inode; int reserved = 0; - spin_lock(&inode_lock); + spin_lock(&inode_sb_list_lock); list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { /* * We have to scan also I_NEW inodes because they can already @@ -1022,7 +1026,7 @@ static void remove_dquot_ref(struct super_block *sb, int type, remove_inode_dquot_ref(inode, type, tofree_head); } } - spin_unlock(&inode_lock); + spin_unlock(&inode_sb_list_lock); #ifdef CONFIG_QUOTA_DEBUG if (reserved) { printk(KERN_WARNING "VFS (%s): Writes happened after quota" -- cgit From a66979abad090b2765a6c6790c9fdeab996833f2 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 22 Mar 2011 22:23:41 +1100 Subject: fs: move i_wb_list out from under inode_lock Protect the inode writeback list with a new global lock inode_wb_list_lock and use it to protect the list manipulations and traversals. This lock replaces the inode_lock as the inodes on the list can be validity checked while holding the inode->i_lock and hence the inode_lock is no longer needed to protect the list. Signed-off-by: Dave Chinner Signed-off-by: Al Viro --- fs/block_dev.c | 4 +-- fs/fs-writeback.c | 76 ++++++++++++++++++++++++++++++++----------------------- fs/inode.c | 12 ++++++--- fs/internal.h | 5 ++++ 4 files changed, 59 insertions(+), 38 deletions(-) (limited to 'fs') diff --git a/fs/block_dev.c b/fs/block_dev.c index bc39b18cf3d0..2bbc0e62102f 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -55,13 +55,13 @@ EXPORT_SYMBOL(I_BDEV); static void bdev_inode_switch_bdi(struct inode *inode, struct backing_dev_info *dst) { - spin_lock(&inode_lock); + spin_lock(&inode_wb_list_lock); spin_lock(&inode->i_lock); inode->i_data.backing_dev_info = dst; if (inode->i_state & I_DIRTY) list_move(&inode->i_wb_list, &dst->wb.b_dirty); spin_unlock(&inode->i_lock); - spin_unlock(&inode_lock); + spin_unlock(&inode_wb_list_lock); } static sector_t max_block(struct block_device *bdev) diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 5de56a2182bb..ed800656356b 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -175,6 +175,17 @@ void bdi_start_background_writeback(struct backing_dev_info *bdi) spin_unlock_bh(&bdi->wb_lock); } +/* + * Remove the inode from the writeback list it is on. + */ +void inode_wb_list_del(struct inode *inode) +{ + spin_lock(&inode_wb_list_lock); + list_del_init(&inode->i_wb_list); + spin_unlock(&inode_wb_list_lock); +} + + /* * Redirty an inode: set its when-it-was dirtied timestamp and move it to the * furthest end of its superblock's dirty-inode list. @@ -188,6 +199,7 @@ static void redirty_tail(struct inode *inode) { struct bdi_writeback *wb = &inode_to_bdi(inode)->wb; + assert_spin_locked(&inode_wb_list_lock); if (!list_empty(&wb->b_dirty)) { struct inode *tail; @@ -205,14 +217,17 @@ static void requeue_io(struct inode *inode) { struct bdi_writeback *wb = &inode_to_bdi(inode)->wb; + assert_spin_locked(&inode_wb_list_lock); list_move(&inode->i_wb_list, &wb->b_more_io); } static void inode_sync_complete(struct inode *inode) { /* - * Prevent speculative execution through spin_unlock(&inode_lock); + * Prevent speculative execution through + * spin_unlock(&inode_wb_list_lock); */ + smp_mb(); wake_up_bit(&inode->i_state, __I_SYNC); } @@ -286,6 +301,7 @@ static void move_expired_inodes(struct list_head *delaying_queue, */ static void queue_io(struct bdi_writeback *wb, unsigned long *older_than_this) { + assert_spin_locked(&inode_wb_list_lock); list_splice_init(&wb->b_more_io, &wb->b_io); move_expired_inodes(&wb->b_dirty, &wb->b_io, older_than_this); } @@ -308,25 +324,23 @@ static void inode_wait_for_writeback(struct inode *inode) wqh = bit_waitqueue(&inode->i_state, __I_SYNC); while (inode->i_state & I_SYNC) { spin_unlock(&inode->i_lock); - spin_unlock(&inode_lock); + spin_unlock(&inode_wb_list_lock); __wait_on_bit(wqh, &wq, inode_wait, TASK_UNINTERRUPTIBLE); - spin_lock(&inode_lock); + spin_lock(&inode_wb_list_lock); spin_lock(&inode->i_lock); } } /* - * Write out an inode's dirty pages. Called under inode_lock. Either the - * caller has ref on the inode (either via __iget or via syscall against an fd) - * or the inode has I_WILL_FREE set (via generic_forget_inode) + * Write out an inode's dirty pages. Called under inode_wb_list_lock. Either + * the caller has an active reference on the inode or the inode has I_WILL_FREE + * set. * * If `wait' is set, wait on the writeout. * * The whole writeout design is quite complex and fragile. We want to avoid * starvation of particular inodes when others are being redirtied, prevent * livelocks, etc. - * - * Called under inode_lock. */ static int writeback_single_inode(struct inode *inode, struct writeback_control *wbc) @@ -368,7 +382,7 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc) inode->i_state |= I_SYNC; inode->i_state &= ~I_DIRTY_PAGES; spin_unlock(&inode->i_lock); - spin_unlock(&inode_lock); + spin_unlock(&inode_wb_list_lock); ret = do_writepages(mapping, wbc); @@ -388,12 +402,10 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc) * due to delalloc, clear dirty metadata flags right before * write_inode() */ - spin_lock(&inode_lock); spin_lock(&inode->i_lock); dirty = inode->i_state & I_DIRTY; inode->i_state &= ~(I_DIRTY_SYNC | I_DIRTY_DATASYNC); spin_unlock(&inode->i_lock); - spin_unlock(&inode_lock); /* Don't write the inode if only I_DIRTY_PAGES was set */ if (dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) { int err = write_inode(inode, wbc); @@ -401,7 +413,7 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc) ret = err; } - spin_lock(&inode_lock); + spin_lock(&inode_wb_list_lock); spin_lock(&inode->i_lock); inode->i_state &= ~I_SYNC; if (!(inode->i_state & I_FREEING)) { @@ -543,10 +555,10 @@ static int writeback_sb_inodes(struct super_block *sb, struct bdi_writeback *wb, */ redirty_tail(inode); } - spin_unlock(&inode_lock); + spin_unlock(&inode_wb_list_lock); iput(inode); cond_resched(); - spin_lock(&inode_lock); + spin_lock(&inode_wb_list_lock); if (wbc->nr_to_write <= 0) { wbc->more_io = 1; return 1; @@ -565,7 +577,7 @@ void writeback_inodes_wb(struct bdi_writeback *wb, if (!wbc->wb_start) wbc->wb_start = jiffies; /* livelock avoidance */ - spin_lock(&inode_lock); + spin_lock(&inode_wb_list_lock); if (!wbc->for_kupdate || list_empty(&wb->b_io)) queue_io(wb, wbc->older_than_this); @@ -583,7 +595,7 @@ void writeback_inodes_wb(struct bdi_writeback *wb, if (ret) break; } - spin_unlock(&inode_lock); + spin_unlock(&inode_wb_list_lock); /* Leave any unwritten inodes on b_io */ } @@ -592,11 +604,11 @@ static void __writeback_inodes_sb(struct super_block *sb, { WARN_ON(!rwsem_is_locked(&sb->s_umount)); - spin_lock(&inode_lock); + spin_lock(&inode_wb_list_lock); if (!wbc->for_kupdate || list_empty(&wb->b_io)) queue_io(wb, wbc->older_than_this); writeback_sb_inodes(sb, wb, wbc, true); - spin_unlock(&inode_lock); + spin_unlock(&inode_wb_list_lock); } /* @@ -735,7 +747,7 @@ static long wb_writeback(struct bdi_writeback *wb, * become available for writeback. Otherwise * we'll just busyloop. */ - spin_lock(&inode_lock); + spin_lock(&inode_wb_list_lock); if (!list_empty(&wb->b_more_io)) { inode = wb_inode(wb->b_more_io.prev); trace_wbc_writeback_wait(&wbc, wb->bdi); @@ -743,7 +755,7 @@ static long wb_writeback(struct bdi_writeback *wb, inode_wait_for_writeback(inode); spin_unlock(&inode->i_lock); } - spin_unlock(&inode_lock); + spin_unlock(&inode_wb_list_lock); } return wrote; @@ -1009,7 +1021,6 @@ void __mark_inode_dirty(struct inode *inode, int flags) { struct super_block *sb = inode->i_sb; struct backing_dev_info *bdi = NULL; - bool wakeup_bdi = false; /* * Don't do this for I_DIRTY_PAGES - that doesn't actually @@ -1033,7 +1044,6 @@ void __mark_inode_dirty(struct inode *inode, int flags) if (unlikely(block_dump)) block_dump___mark_inode_dirty(inode); - spin_lock(&inode_lock); spin_lock(&inode->i_lock); if ((inode->i_state & flags) != flags) { const int was_dirty = inode->i_state & I_DIRTY; @@ -1059,12 +1069,12 @@ void __mark_inode_dirty(struct inode *inode, int flags) if (inode->i_state & I_FREEING) goto out_unlock_inode; - spin_unlock(&inode->i_lock); /* * If the inode was already on b_dirty/b_io/b_more_io, don't * reposition it (that would break b_dirty time-ordering). */ if (!was_dirty) { + bool wakeup_bdi = false; bdi = inode_to_bdi(inode); if (bdi_cap_writeback_dirty(bdi)) { @@ -1081,18 +1091,20 @@ void __mark_inode_dirty(struct inode *inode, int flags) wakeup_bdi = true; } + spin_unlock(&inode->i_lock); + spin_lock(&inode_wb_list_lock); inode->dirtied_when = jiffies; list_move(&inode->i_wb_list, &bdi->wb.b_dirty); + spin_unlock(&inode_wb_list_lock); + + if (wakeup_bdi) + bdi_wakeup_thread_delayed(bdi); + return; } - goto out; } out_unlock_inode: spin_unlock(&inode->i_lock); -out: - spin_unlock(&inode_lock); - if (wakeup_bdi) - bdi_wakeup_thread_delayed(bdi); } EXPORT_SYMBOL(__mark_inode_dirty); @@ -1296,9 +1308,9 @@ int write_inode_now(struct inode *inode, int sync) wbc.nr_to_write = 0; might_sleep(); - spin_lock(&inode_lock); + spin_lock(&inode_wb_list_lock); ret = writeback_single_inode(inode, &wbc); - spin_unlock(&inode_lock); + spin_unlock(&inode_wb_list_lock); if (sync) inode_sync_wait(inode); return ret; @@ -1320,9 +1332,9 @@ int sync_inode(struct inode *inode, struct writeback_control *wbc) { int ret; - spin_lock(&inode_lock); + spin_lock(&inode_wb_list_lock); ret = writeback_single_inode(inode, wbc); - spin_unlock(&inode_lock); + spin_unlock(&inode_wb_list_lock); return ret; } EXPORT_SYMBOL(sync_inode); diff --git a/fs/inode.c b/fs/inode.c index 785b1ab23ff0..239fdc08719e 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -26,6 +26,7 @@ #include #include #include +#include "internal.h" /* * inode locking rules. @@ -36,6 +37,8 @@ * inode_lru, inode->i_lru * inode_sb_list_lock protects: * sb->s_inodes, inode->i_sb_list + * inode_wb_list_lock protects: + * bdi->wb.b_{dirty,io,more_io}, inode->i_wb_list * * Lock ordering: * inode_lock @@ -44,6 +47,9 @@ * inode_sb_list_lock * inode->i_lock * inode_lru_lock + * + * inode_wb_list_lock + * inode->i_lock */ /* @@ -105,6 +111,7 @@ static struct hlist_head *inode_hashtable __read_mostly; DEFINE_SPINLOCK(inode_lock); __cacheline_aligned_in_smp DEFINE_SPINLOCK(inode_sb_list_lock); +__cacheline_aligned_in_smp DEFINE_SPINLOCK(inode_wb_list_lock); /* * iprune_sem provides exclusion between the icache shrinking and the @@ -483,10 +490,7 @@ static void evict(struct inode *inode) BUG_ON(!(inode->i_state & I_FREEING)); BUG_ON(!list_empty(&inode->i_lru)); - spin_lock(&inode_lock); - list_del_init(&inode->i_wb_list); - spin_unlock(&inode_lock); - + inode_wb_list_del(inode); inode_sb_list_del(inode); if (op->evict_inode) { diff --git a/fs/internal.h b/fs/internal.h index 7013ae0c88c1..b29c46e4e32f 100644 --- a/fs/internal.h +++ b/fs/internal.h @@ -127,6 +127,11 @@ extern long do_handle_open(int mountdirfd, */ extern spinlock_t inode_sb_list_lock; +/* + * fs-writeback.c + */ +extern void inode_wb_list_del(struct inode *inode); + extern int get_nr_dirty_inodes(void); extern void evict_inodes(struct super_block *); extern int invalidate_inodes(struct super_block *, bool); -- cgit From 67a23c494621ff1d5431c3bc320947865b224625 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 22 Mar 2011 22:23:42 +1100 Subject: fs: rename inode_lock to inode_hash_lock All that remains of the inode_lock is protecting the inode hash list manipulation and traversals. Rename the inode_lock to inode_hash_lock to reflect it's actual function. Signed-off-by: Dave Chinner Signed-off-by: Al Viro --- fs/inode.c | 111 +++++++++++++++++++++++++--------------------- fs/notify/inode_mark.c | 1 - fs/notify/mark.c | 1 - fs/notify/vfsmount_mark.c | 1 - fs/ntfs/inode.c | 4 +- 5 files changed, 63 insertions(+), 55 deletions(-) (limited to 'fs') diff --git a/fs/inode.c b/fs/inode.c index 239fdc08719e..f9ee4928358f 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -39,10 +39,10 @@ * sb->s_inodes, inode->i_sb_list * inode_wb_list_lock protects: * bdi->wb.b_{dirty,io,more_io}, inode->i_wb_list + * inode_hash_lock protects: + * inode_hashtable, inode->i_hash * * Lock ordering: - * inode_lock - * inode->i_lock * * inode_sb_list_lock * inode->i_lock @@ -50,6 +50,13 @@ * * inode_wb_list_lock * inode->i_lock + * + * inode_hash_lock + * inode_sb_list_lock + * inode->i_lock + * + * iunique_lock + * inode_hash_lock */ /* @@ -85,6 +92,8 @@ static unsigned int i_hash_mask __read_mostly; static unsigned int i_hash_shift __read_mostly; +static struct hlist_head *inode_hashtable __read_mostly; +static __cacheline_aligned_in_smp DEFINE_SPINLOCK(inode_hash_lock); /* * Each inode can be on two separate lists. One is @@ -100,15 +109,6 @@ static unsigned int i_hash_shift __read_mostly; static LIST_HEAD(inode_lru); static DEFINE_SPINLOCK(inode_lru_lock); -static struct hlist_head *inode_hashtable __read_mostly; - -/* - * A simple spinlock to protect the list manipulations. - * - * NOTE! You also have to own the lock if you change - * the i_state of an inode while it is in use.. - */ -DEFINE_SPINLOCK(inode_lock); __cacheline_aligned_in_smp DEFINE_SPINLOCK(inode_sb_list_lock); __cacheline_aligned_in_smp DEFINE_SPINLOCK(inode_wb_list_lock); @@ -433,11 +433,11 @@ void __insert_inode_hash(struct inode *inode, unsigned long hashval) { struct hlist_head *b = inode_hashtable + hash(inode->i_sb, hashval); - spin_lock(&inode_lock); + spin_lock(&inode_hash_lock); spin_lock(&inode->i_lock); hlist_add_head(&inode->i_hash, b); spin_unlock(&inode->i_lock); - spin_unlock(&inode_lock); + spin_unlock(&inode_hash_lock); } EXPORT_SYMBOL(__insert_inode_hash); @@ -449,11 +449,11 @@ EXPORT_SYMBOL(__insert_inode_hash); */ void remove_inode_hash(struct inode *inode) { - spin_lock(&inode_lock); + spin_lock(&inode_hash_lock); spin_lock(&inode->i_lock); hlist_del_init(&inode->i_hash); spin_unlock(&inode->i_lock); - spin_unlock(&inode_lock); + spin_unlock(&inode_hash_lock); } EXPORT_SYMBOL(remove_inode_hash); @@ -778,11 +778,15 @@ static struct inode *find_inode(struct super_block *sb, repeat: hlist_for_each_entry(inode, node, head, i_hash) { - if (inode->i_sb != sb) + spin_lock(&inode->i_lock); + if (inode->i_sb != sb) { + spin_unlock(&inode->i_lock); continue; - if (!test(inode, data)) + } + if (!test(inode, data)) { + spin_unlock(&inode->i_lock); continue; - spin_lock(&inode->i_lock); + } if (inode->i_state & (I_FREEING|I_WILL_FREE)) { __wait_on_freeing_inode(inode); goto repeat; @@ -806,11 +810,15 @@ static struct inode *find_inode_fast(struct super_block *sb, repeat: hlist_for_each_entry(inode, node, head, i_hash) { - if (inode->i_ino != ino) + spin_lock(&inode->i_lock); + if (inode->i_ino != ino) { + spin_unlock(&inode->i_lock); continue; - if (inode->i_sb != sb) + } + if (inode->i_sb != sb) { + spin_unlock(&inode->i_lock); continue; - spin_lock(&inode->i_lock); + } if (inode->i_state & (I_FREEING|I_WILL_FREE)) { __wait_on_freeing_inode(inode); goto repeat; @@ -924,7 +932,7 @@ void unlock_new_inode(struct inode *inode) EXPORT_SYMBOL(unlock_new_inode); /* - * This is called without the inode lock held.. Be careful. + * This is called without the inode hash lock held.. Be careful. * * We no longer cache the sb_flags in i_flags - see fs.h * -- rmk@arm.uk.linux.org @@ -941,7 +949,7 @@ static struct inode *get_new_inode(struct super_block *sb, if (inode) { struct inode *old; - spin_lock(&inode_lock); + spin_lock(&inode_hash_lock); /* We released the lock, so.. */ old = find_inode(sb, head, test, data); if (!old) { @@ -953,7 +961,7 @@ static struct inode *get_new_inode(struct super_block *sb, hlist_add_head(&inode->i_hash, head); spin_unlock(&inode->i_lock); inode_sb_list_add(inode); - spin_unlock(&inode_lock); + spin_unlock(&inode_hash_lock); /* Return the locked inode with I_NEW set, the * caller is responsible for filling in the contents @@ -966,7 +974,7 @@ static struct inode *get_new_inode(struct super_block *sb, * us. Use the old inode instead of the one we just * allocated. */ - spin_unlock(&inode_lock); + spin_unlock(&inode_hash_lock); destroy_inode(inode); inode = old; wait_on_inode(inode); @@ -974,7 +982,7 @@ static struct inode *get_new_inode(struct super_block *sb, return inode; set_failed: - spin_unlock(&inode_lock); + spin_unlock(&inode_hash_lock); destroy_inode(inode); return NULL; } @@ -992,7 +1000,7 @@ static struct inode *get_new_inode_fast(struct super_block *sb, if (inode) { struct inode *old; - spin_lock(&inode_lock); + spin_lock(&inode_hash_lock); /* We released the lock, so.. */ old = find_inode_fast(sb, head, ino); if (!old) { @@ -1002,7 +1010,7 @@ static struct inode *get_new_inode_fast(struct super_block *sb, hlist_add_head(&inode->i_hash, head); spin_unlock(&inode->i_lock); inode_sb_list_add(inode); - spin_unlock(&inode_lock); + spin_unlock(&inode_hash_lock); /* Return the locked inode with I_NEW set, the * caller is responsible for filling in the contents @@ -1015,7 +1023,7 @@ static struct inode *get_new_inode_fast(struct super_block *sb, * us. Use the old inode instead of the one we just * allocated. */ - spin_unlock(&inode_lock); + spin_unlock(&inode_hash_lock); destroy_inode(inode); inode = old; wait_on_inode(inode); @@ -1036,10 +1044,14 @@ static int test_inode_iunique(struct super_block *sb, unsigned long ino) struct hlist_node *node; struct inode *inode; + spin_lock(&inode_hash_lock); hlist_for_each_entry(inode, node, b, i_hash) { - if (inode->i_ino == ino && inode->i_sb == sb) + if (inode->i_ino == ino && inode->i_sb == sb) { + spin_unlock(&inode_hash_lock); return 0; + } } + spin_unlock(&inode_hash_lock); return 1; } @@ -1069,7 +1081,6 @@ ino_t iunique(struct super_block *sb, ino_t max_reserved) static unsigned int counter; ino_t res; - spin_lock(&inode_lock); spin_lock(&iunique_lock); do { if (counter <= max_reserved) @@ -1077,7 +1088,6 @@ ino_t iunique(struct super_block *sb, ino_t max_reserved) res = counter++; } while (!test_inode_iunique(sb, res)); spin_unlock(&iunique_lock); - spin_unlock(&inode_lock); return res; } @@ -1119,7 +1129,7 @@ EXPORT_SYMBOL(igrab); * * Otherwise NULL is returned. * - * Note, @test is called with the inode_lock held, so can't sleep. + * Note, @test is called with the inode_hash_lock held, so can't sleep. */ static struct inode *ifind(struct super_block *sb, struct hlist_head *head, int (*test)(struct inode *, void *), @@ -1127,15 +1137,15 @@ static struct inode *ifind(struct super_block *sb, { struct inode *inode; - spin_lock(&inode_lock); + spin_lock(&inode_hash_lock); inode = find_inode(sb, head, test, data); if (inode) { - spin_unlock(&inode_lock); + spin_unlock(&inode_hash_lock); if (likely(wait)) wait_on_inode(inode); return inode; } - spin_unlock(&inode_lock); + spin_unlock(&inode_hash_lock); return NULL; } @@ -1159,14 +1169,14 @@ static struct inode *ifind_fast(struct super_block *sb, { struct inode *inode; - spin_lock(&inode_lock); + spin_lock(&inode_hash_lock); inode = find_inode_fast(sb, head, ino); if (inode) { - spin_unlock(&inode_lock); + spin_unlock(&inode_hash_lock); wait_on_inode(inode); return inode; } - spin_unlock(&inode_lock); + spin_unlock(&inode_hash_lock); return NULL; } @@ -1189,7 +1199,7 @@ static struct inode *ifind_fast(struct super_block *sb, * * Otherwise NULL is returned. * - * Note, @test is called with the inode_lock held, so can't sleep. + * Note, @test is called with the inode_hash_lock held, so can't sleep. */ struct inode *ilookup5_nowait(struct super_block *sb, unsigned long hashval, int (*test)(struct inode *, void *), void *data) @@ -1217,7 +1227,7 @@ EXPORT_SYMBOL(ilookup5_nowait); * * Otherwise NULL is returned. * - * Note, @test is called with the inode_lock held, so can't sleep. + * Note, @test is called with the inode_hash_lock held, so can't sleep. */ struct inode *ilookup5(struct super_block *sb, unsigned long hashval, int (*test)(struct inode *, void *), void *data) @@ -1268,7 +1278,8 @@ EXPORT_SYMBOL(ilookup); * inode and this is returned locked, hashed, and with the I_NEW flag set. The * file system gets to fill it in before unlocking it via unlock_new_inode(). * - * Note both @test and @set are called with the inode_lock held, so can't sleep. + * Note both @test and @set are called with the inode_hash_lock held, so can't + * sleep. */ struct inode *iget5_locked(struct super_block *sb, unsigned long hashval, int (*test)(struct inode *, void *), @@ -1328,7 +1339,7 @@ int insert_inode_locked(struct inode *inode) while (1) { struct hlist_node *node; struct inode *old = NULL; - spin_lock(&inode_lock); + spin_lock(&inode_hash_lock); hlist_for_each_entry(old, node, head, i_hash) { if (old->i_ino != ino) continue; @@ -1346,12 +1357,12 @@ int insert_inode_locked(struct inode *inode) inode->i_state |= I_NEW; hlist_add_head(&inode->i_hash, head); spin_unlock(&inode->i_lock); - spin_unlock(&inode_lock); + spin_unlock(&inode_hash_lock); return 0; } __iget(old); spin_unlock(&old->i_lock); - spin_unlock(&inode_lock); + spin_unlock(&inode_hash_lock); wait_on_inode(old); if (unlikely(!inode_unhashed(old))) { iput(old); @@ -1372,7 +1383,7 @@ int insert_inode_locked4(struct inode *inode, unsigned long hashval, struct hlist_node *node; struct inode *old = NULL; - spin_lock(&inode_lock); + spin_lock(&inode_hash_lock); hlist_for_each_entry(old, node, head, i_hash) { if (old->i_sb != sb) continue; @@ -1390,12 +1401,12 @@ int insert_inode_locked4(struct inode *inode, unsigned long hashval, inode->i_state |= I_NEW; hlist_add_head(&inode->i_hash, head); spin_unlock(&inode->i_lock); - spin_unlock(&inode_lock); + spin_unlock(&inode_hash_lock); return 0; } __iget(old); spin_unlock(&old->i_lock); - spin_unlock(&inode_lock); + spin_unlock(&inode_hash_lock); wait_on_inode(old); if (unlikely(!inode_unhashed(old))) { iput(old); @@ -1674,10 +1685,10 @@ static void __wait_on_freeing_inode(struct inode *inode) wq = bit_waitqueue(&inode->i_state, __I_NEW); prepare_to_wait(wq, &wait.wait, TASK_UNINTERRUPTIBLE); spin_unlock(&inode->i_lock); - spin_unlock(&inode_lock); + spin_unlock(&inode_hash_lock); schedule(); finish_wait(wq, &wait.wait); - spin_lock(&inode_lock); + spin_lock(&inode_hash_lock); } static __initdata unsigned long ihash_entries; diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c index fb3b3c5ef0ee..07ea8d3e6ea2 100644 --- a/fs/notify/inode_mark.c +++ b/fs/notify/inode_mark.c @@ -22,7 +22,6 @@ #include #include #include -#include /* for inode_lock */ #include diff --git a/fs/notify/mark.c b/fs/notify/mark.c index 325185e514bb..50c00856f730 100644 --- a/fs/notify/mark.c +++ b/fs/notify/mark.c @@ -91,7 +91,6 @@ #include #include #include -#include /* for inode_lock */ #include diff --git a/fs/notify/vfsmount_mark.c b/fs/notify/vfsmount_mark.c index 85eebff6d0d7..e86577d6c5c3 100644 --- a/fs/notify/vfsmount_mark.c +++ b/fs/notify/vfsmount_mark.c @@ -23,7 +23,6 @@ #include #include #include -#include /* for inode_lock */ #include diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index a627ed82c0a3..0b56c6b7ec01 100644 --- a/fs/ntfs/inode.c +++ b/fs/ntfs/inode.c @@ -54,7 +54,7 @@ * * Return 1 if the attributes match and 0 if not. * - * NOTE: This function runs with the inode_lock spin lock held so it is not + * NOTE: This function runs with the inode->i_lock spin lock held so it is not * allowed to sleep. */ int ntfs_test_inode(struct inode *vi, ntfs_attr *na) @@ -98,7 +98,7 @@ int ntfs_test_inode(struct inode *vi, ntfs_attr *na) * * Return 0 on success and -errno on error. * - * NOTE: This function runs with the inode_lock spin lock held so it is not + * NOTE: This function runs with the inode->i_lock spin lock held so it is not * allowed to sleep. (Hence the GFP_ATOMIC allocation.) */ static int ntfs_init_locked_inode(struct inode *vi, ntfs_attr *na) -- cgit From 0f1b1fd86f6fd662e04da3e82a6780b226fcd0d1 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 22 Mar 2011 22:23:43 +1100 Subject: fs: pull inode->i_lock up out of writeback_single_inode First thing we do in writeback_single_inode() is take the i_lock and the last thing we do is drop it. A caller already holds the i_lock, so pull the i_lock out of writeback_single_inode() to reduce the round trips on this lock during inode writeback. Signed-off-by: Dave Chinner Signed-off-by: Al Viro --- fs/fs-writeback.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'fs') diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index ed800656356b..b5ed541fb137 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -332,9 +332,9 @@ static void inode_wait_for_writeback(struct inode *inode) } /* - * Write out an inode's dirty pages. Called under inode_wb_list_lock. Either - * the caller has an active reference on the inode or the inode has I_WILL_FREE - * set. + * Write out an inode's dirty pages. Called under inode_wb_list_lock and + * inode->i_lock. Either the caller has an active reference on the inode or + * the inode has I_WILL_FREE set. * * If `wait' is set, wait on the writeout. * @@ -349,7 +349,9 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc) unsigned dirty; int ret; - spin_lock(&inode->i_lock); + assert_spin_locked(&inode_wb_list_lock); + assert_spin_locked(&inode->i_lock); + if (!atomic_read(&inode->i_count)) WARN_ON(!(inode->i_state & (I_WILL_FREE|I_FREEING))); else @@ -365,7 +367,6 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc) * completed a full scan of b_io. */ if (wbc->sync_mode != WB_SYNC_ALL) { - spin_unlock(&inode->i_lock); requeue_io(inode); return 0; } @@ -456,7 +457,6 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc) } } inode_sync_complete(inode); - spin_unlock(&inode->i_lock); return ret; } @@ -544,7 +544,6 @@ static int writeback_sb_inodes(struct super_block *sb, struct bdi_writeback *wb, } __iget(inode); - spin_unlock(&inode->i_lock); pages_skipped = wbc->pages_skipped; writeback_single_inode(inode, wbc); @@ -555,6 +554,7 @@ static int writeback_sb_inodes(struct super_block *sb, struct bdi_writeback *wb, */ redirty_tail(inode); } + spin_unlock(&inode->i_lock); spin_unlock(&inode_wb_list_lock); iput(inode); cond_resched(); @@ -1309,7 +1309,9 @@ int write_inode_now(struct inode *inode, int sync) might_sleep(); spin_lock(&inode_wb_list_lock); + spin_lock(&inode->i_lock); ret = writeback_single_inode(inode, &wbc); + spin_unlock(&inode->i_lock); spin_unlock(&inode_wb_list_lock); if (sync) inode_sync_wait(inode); @@ -1333,7 +1335,9 @@ int sync_inode(struct inode *inode, struct writeback_control *wbc) int ret; spin_lock(&inode_wb_list_lock); + spin_lock(&inode->i_lock); ret = writeback_single_inode(inode, wbc); + spin_unlock(&inode->i_lock); spin_unlock(&inode_wb_list_lock); return ret; } -- cgit From 0b2d0724e26a335cd326eb7ad552c109116a8795 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 23 Mar 2011 15:03:28 -0400 Subject: fs: simplify iget & friends Merge get_new_inode/get_new_inode_fast into iget5_locked/iget_locked as those were the only callers. Remove the internal ifind/ifind_fast helpers - ifind_fast only had a single caller, and ifind had two callers wanting it to do different things. Also clean up the comments in this area to focus on information important to a developer trying to use it, instead of overloading them with implementation details. Signed-off-by: Christoph Hellwig Signed-off-by: Al Viro --- fs/inode.c | 262 ++++++++++++++++++++----------------------------------------- 1 file changed, 83 insertions(+), 179 deletions(-) (limited to 'fs') diff --git a/fs/inode.c b/fs/inode.c index f9ee4928358f..05a1f75ae791 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -931,20 +931,42 @@ void unlock_new_inode(struct inode *inode) } EXPORT_SYMBOL(unlock_new_inode); -/* - * This is called without the inode hash lock held.. Be careful. +/** + * iget5_locked - obtain an inode from a mounted file system + * @sb: super block of file system + * @hashval: hash value (usually inode number) to get + * @test: callback used for comparisons between inodes + * @set: callback used to initialize a new struct inode + * @data: opaque data pointer to pass to @test and @set + * + * Search for the inode specified by @hashval and @data in the inode cache, + * and if present it is return it with an increased reference count. This is + * a generalized version of iget_locked() for file systems where the inode + * number is not sufficient for unique identification of an inode. + * + * If the inode is not in cache, allocate a new inode and return it locked, + * hashed, and with the I_NEW flag set. The file system gets to fill it in + * before unlocking it via unlock_new_inode(). * - * We no longer cache the sb_flags in i_flags - see fs.h - * -- rmk@arm.uk.linux.org + * Note both @test and @set are called with the inode_hash_lock held, so can't + * sleep. */ -static struct inode *get_new_inode(struct super_block *sb, - struct hlist_head *head, - int (*test)(struct inode *, void *), - int (*set)(struct inode *, void *), - void *data) +struct inode *iget5_locked(struct super_block *sb, unsigned long hashval, + int (*test)(struct inode *, void *), + int (*set)(struct inode *, void *), void *data) { + struct hlist_head *head = inode_hashtable + hash(sb, hashval); struct inode *inode; + spin_lock(&inode_hash_lock); + inode = find_inode(sb, head, test, data); + spin_unlock(&inode_hash_lock); + + if (inode) { + wait_on_inode(inode); + return inode; + } + inode = alloc_inode(sb); if (inode) { struct inode *old; @@ -986,16 +1008,34 @@ set_failed: destroy_inode(inode); return NULL; } +EXPORT_SYMBOL(iget5_locked); -/* - * get_new_inode_fast is the fast path version of get_new_inode, see the - * comment at iget_locked for details. +/** + * iget_locked - obtain an inode from a mounted file system + * @sb: super block of file system + * @ino: inode number to get + * + * Search for the inode specified by @ino in the inode cache and if present + * return it with an increased reference count. This is for file systems + * where the inode number is sufficient for unique identification of an inode. + * + * If the inode is not in cache, allocate a new inode and return it locked, + * hashed, and with the I_NEW flag set. The file system gets to fill it in + * before unlocking it via unlock_new_inode(). */ -static struct inode *get_new_inode_fast(struct super_block *sb, - struct hlist_head *head, unsigned long ino) +struct inode *iget_locked(struct super_block *sb, unsigned long ino) { + struct hlist_head *head = inode_hashtable + hash(sb, ino); struct inode *inode; + spin_lock(&inode_hash_lock); + inode = find_inode_fast(sb, head, ino); + spin_unlock(&inode_hash_lock); + if (inode) { + wait_on_inode(inode); + return inode; + } + inode = alloc_inode(sb); if (inode) { struct inode *old; @@ -1030,6 +1070,7 @@ static struct inode *get_new_inode_fast(struct super_block *sb, } return inode; } +EXPORT_SYMBOL(iget_locked); /* * search the inode cache for a matching inode number. @@ -1113,100 +1154,32 @@ struct inode *igrab(struct inode *inode) EXPORT_SYMBOL(igrab); /** - * ifind - internal function, you want ilookup5() or iget5(). + * ilookup5_nowait - search for an inode in the inode cache * @sb: super block of file system to search - * @head: the head of the list to search + * @hashval: hash value (usually inode number) to search for * @test: callback used for comparisons between inodes * @data: opaque data pointer to pass to @test - * @wait: if true wait for the inode to be unlocked, if false do not - * - * ifind() searches for the inode specified by @data in the inode - * cache. This is a generalized version of ifind_fast() for file systems where - * the inode number is not sufficient for unique identification of an inode. * + * Search for the inode specified by @hashval and @data in the inode cache. * If the inode is in the cache, the inode is returned with an incremented * reference count. * - * Otherwise NULL is returned. + * Note: I_NEW is not waited upon so you have to be very careful what you do + * with the returned inode. You probably should be using ilookup5() instead. * - * Note, @test is called with the inode_hash_lock held, so can't sleep. + * Note: @test is called with the inode_hash_lock held, so can't sleep. */ -static struct inode *ifind(struct super_block *sb, - struct hlist_head *head, int (*test)(struct inode *, void *), - void *data, const int wait) +struct inode *ilookup5_nowait(struct super_block *sb, unsigned long hashval, + int (*test)(struct inode *, void *), void *data) { + struct hlist_head *head = inode_hashtable + hash(sb, hashval); struct inode *inode; spin_lock(&inode_hash_lock); inode = find_inode(sb, head, test, data); - if (inode) { - spin_unlock(&inode_hash_lock); - if (likely(wait)) - wait_on_inode(inode); - return inode; - } - spin_unlock(&inode_hash_lock); - return NULL; -} - -/** - * ifind_fast - internal function, you want ilookup() or iget(). - * @sb: super block of file system to search - * @head: head of the list to search - * @ino: inode number to search for - * - * ifind_fast() searches for the inode @ino in the inode cache. This is for - * file systems where the inode number is sufficient for unique identification - * of an inode. - * - * If the inode is in the cache, the inode is returned with an incremented - * reference count. - * - * Otherwise NULL is returned. - */ -static struct inode *ifind_fast(struct super_block *sb, - struct hlist_head *head, unsigned long ino) -{ - struct inode *inode; - - spin_lock(&inode_hash_lock); - inode = find_inode_fast(sb, head, ino); - if (inode) { - spin_unlock(&inode_hash_lock); - wait_on_inode(inode); - return inode; - } spin_unlock(&inode_hash_lock); - return NULL; -} - -/** - * ilookup5_nowait - search for an inode in the inode cache - * @sb: super block of file system to search - * @hashval: hash value (usually inode number) to search for - * @test: callback used for comparisons between inodes - * @data: opaque data pointer to pass to @test - * - * ilookup5() uses ifind() to search for the inode specified by @hashval and - * @data in the inode cache. This is a generalized version of ilookup() for - * file systems where the inode number is not sufficient for unique - * identification of an inode. - * - * If the inode is in the cache, the inode is returned with an incremented - * reference count. Note, the inode lock is not waited upon so you have to be - * very careful what you do with the returned inode. You probably should be - * using ilookup5() instead. - * - * Otherwise NULL is returned. - * - * Note, @test is called with the inode_hash_lock held, so can't sleep. - */ -struct inode *ilookup5_nowait(struct super_block *sb, unsigned long hashval, - int (*test)(struct inode *, void *), void *data) -{ - struct hlist_head *head = inode_hashtable + hash(sb, hashval); - return ifind(sb, head, test, data, 0); + return inode; } EXPORT_SYMBOL(ilookup5_nowait); @@ -1217,24 +1190,24 @@ EXPORT_SYMBOL(ilookup5_nowait); * @test: callback used for comparisons between inodes * @data: opaque data pointer to pass to @test * - * ilookup5() uses ifind() to search for the inode specified by @hashval and - * @data in the inode cache. This is a generalized version of ilookup() for - * file systems where the inode number is not sufficient for unique - * identification of an inode. - * - * If the inode is in the cache, the inode lock is waited upon and the inode is + * Search for the inode specified by @hashval and @data in the inode cache, + * and if the inode is in the cache, return the inode with an incremented + * reference count. Waits on I_NEW before returning the inode. * returned with an incremented reference count. * - * Otherwise NULL is returned. + * This is a generalized version of ilookup() for file systems where the + * inode number is not sufficient for unique identification of an inode. * - * Note, @test is called with the inode_hash_lock held, so can't sleep. + * Note: @test is called with the inode_hash_lock held, so can't sleep. */ struct inode *ilookup5(struct super_block *sb, unsigned long hashval, int (*test)(struct inode *, void *), void *data) { - struct hlist_head *head = inode_hashtable + hash(sb, hashval); + struct inode *inode = ilookup5_nowait(sb, hashval, test, data); - return ifind(sb, head, test, data, 1); + if (inode) + wait_on_inode(inode); + return inode; } EXPORT_SYMBOL(ilookup5); @@ -1243,92 +1216,23 @@ EXPORT_SYMBOL(ilookup5); * @sb: super block of file system to search * @ino: inode number to search for * - * ilookup() uses ifind_fast() to search for the inode @ino in the inode cache. - * This is for file systems where the inode number is sufficient for unique - * identification of an inode. - * - * If the inode is in the cache, the inode is returned with an incremented - * reference count. - * - * Otherwise NULL is returned. + * Search for the inode @ino in the inode cache, and if the inode is in the + * cache, the inode is returned with an incremented reference count. */ struct inode *ilookup(struct super_block *sb, unsigned long ino) { struct hlist_head *head = inode_hashtable + hash(sb, ino); - - return ifind_fast(sb, head, ino); -} -EXPORT_SYMBOL(ilookup); - -/** - * iget5_locked - obtain an inode from a mounted file system - * @sb: super block of file system - * @hashval: hash value (usually inode number) to get - * @test: callback used for comparisons between inodes - * @set: callback used to initialize a new struct inode - * @data: opaque data pointer to pass to @test and @set - * - * iget5_locked() uses ifind() to search for the inode specified by @hashval - * and @data in the inode cache and if present it is returned with an increased - * reference count. This is a generalized version of iget_locked() for file - * systems where the inode number is not sufficient for unique identification - * of an inode. - * - * If the inode is not in cache, get_new_inode() is called to allocate a new - * inode and this is returned locked, hashed, and with the I_NEW flag set. The - * file system gets to fill it in before unlocking it via unlock_new_inode(). - * - * Note both @test and @set are called with the inode_hash_lock held, so can't - * sleep. - */ -struct inode *iget5_locked(struct super_block *sb, unsigned long hashval, - int (*test)(struct inode *, void *), - int (*set)(struct inode *, void *), void *data) -{ - struct hlist_head *head = inode_hashtable + hash(sb, hashval); struct inode *inode; - inode = ifind(sb, head, test, data, 1); - if (inode) - return inode; - /* - * get_new_inode() will do the right thing, re-trying the search - * in case it had to block at any point. - */ - return get_new_inode(sb, head, test, set, data); -} -EXPORT_SYMBOL(iget5_locked); - -/** - * iget_locked - obtain an inode from a mounted file system - * @sb: super block of file system - * @ino: inode number to get - * - * iget_locked() uses ifind_fast() to search for the inode specified by @ino in - * the inode cache and if present it is returned with an increased reference - * count. This is for file systems where the inode number is sufficient for - * unique identification of an inode. - * - * If the inode is not in cache, get_new_inode_fast() is called to allocate a - * new inode and this is returned locked, hashed, and with the I_NEW flag set. - * The file system gets to fill it in before unlocking it via - * unlock_new_inode(). - */ -struct inode *iget_locked(struct super_block *sb, unsigned long ino) -{ - struct hlist_head *head = inode_hashtable + hash(sb, ino); - struct inode *inode; + spin_lock(&inode_hash_lock); + inode = find_inode_fast(sb, head, ino); + spin_unlock(&inode_hash_lock); - inode = ifind_fast(sb, head, ino); if (inode) - return inode; - /* - * get_new_inode_fast() will do the right thing, re-trying the search - * in case it had to block at any point. - */ - return get_new_inode_fast(sb, head, ino); + wait_on_inode(inode); + return inode; } -EXPORT_SYMBOL(iget_locked); +EXPORT_SYMBOL(ilookup); int insert_inode_locked(struct inode *inode) { -- cgit From 8287889742940cf3c416e755322090d09f2829be Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Sat, 26 Mar 2011 09:13:08 +1100 Subject: xfs: preallocation transactions do not need to be synchronous Preallocation and hole punch transactions are currently synchronous and this is causing performance problems in some cases. The transactions don't need to be synchronous as we don't need to guarantee the preallocation is persistent on disk until a fdatasync, fsync, sync operation occurs. If the file is opened O_SYNC or O_DATASYNC, only then should the transaction be issued synchronously. Signed-off-by: Dave Chinner Reviewed-by: Christoph Hellwig Reviewed-by: Alex Elder --- fs/xfs/linux-2.6/xfs_file.c | 6 +++++- fs/xfs/linux-2.6/xfs_ioctl.c | 4 ++++ fs/xfs/xfs_vnodeops.c | 3 ++- fs/xfs/xfs_vnodeops.h | 1 + 4 files changed, 12 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index a55c1b46b219..52aadfbed132 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c @@ -896,6 +896,7 @@ xfs_file_fallocate( xfs_flock64_t bf; xfs_inode_t *ip = XFS_I(inode); int cmd = XFS_IOC_RESVSP; + int attr_flags = XFS_ATTR_NOLOCK; if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE)) return -EOPNOTSUPP; @@ -918,7 +919,10 @@ xfs_file_fallocate( goto out_unlock; } - error = -xfs_change_file_space(ip, cmd, &bf, 0, XFS_ATTR_NOLOCK); + if (file->f_flags & O_DSYNC) + attr_flags |= XFS_ATTR_SYNC; + + error = -xfs_change_file_space(ip, cmd, &bf, 0, attr_flags); if (error) goto out_unlock; diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index 0ca0e3c024d7..acca2c5ca3fa 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c @@ -624,6 +624,10 @@ xfs_ioc_space( if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) attr_flags |= XFS_ATTR_NONBLOCK; + + if (filp->f_flags & O_DSYNC) + attr_flags |= XFS_ATTR_SYNC; + if (ioflags & IO_INVIS) attr_flags |= XFS_ATTR_DMI; diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 37d8146ee15b..c48b4217ec47 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -2831,7 +2831,8 @@ xfs_change_file_space( ip->i_d.di_flags &= ~XFS_DIFLAG_PREALLOC; xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); - xfs_trans_set_sync(tp); + if (attr_flags & XFS_ATTR_SYNC) + xfs_trans_set_sync(tp); error = xfs_trans_commit(tp, 0); diff --git a/fs/xfs/xfs_vnodeops.h b/fs/xfs/xfs_vnodeops.h index f6702927eee4..3bcd23353d6c 100644 --- a/fs/xfs/xfs_vnodeops.h +++ b/fs/xfs/xfs_vnodeops.h @@ -18,6 +18,7 @@ int xfs_setattr(struct xfs_inode *ip, struct iattr *vap, int flags); #define XFS_ATTR_NONBLOCK 0x02 /* return EAGAIN if operation would block */ #define XFS_ATTR_NOLOCK 0x04 /* Don't grab any conflicting locks */ #define XFS_ATTR_NOACL 0x08 /* Don't call xfs_acl_chmod */ +#define XFS_ATTR_SYNC 0x10 /* synchronous operation required */ int xfs_readlink(struct xfs_inode *ip, char *link); int xfs_release(struct xfs_inode *ip); -- cgit From a19fb380961f209a3a406443686647bcd01bb9a6 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Sat, 26 Mar 2011 09:13:42 +1100 Subject: vmap: flush vmap aliases when mapping fails On 32 bit systems, vmalloc space is limited and XFS can chew through it quickly as the vmalloc space is lazily freed. This can result in failure to map buffers, even when there is apparently large amounts of vmalloc space available. Hence, if we fail to map a buffer, purge the aliases that have not yet been freed to hopefuly free up enough vmalloc space to allow a retry to succeed. Signed-off-by: Dave Chinner Reviewed-by: Christoph Hellwig Reviewed-by: Alex Elder --- fs/xfs/linux-2.6/xfs_buf.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index 3cc671c8a67f..a5a260fab824 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c @@ -455,9 +455,17 @@ _xfs_buf_map_pages( bp->b_addr = page_address(bp->b_pages[0]) + bp->b_offset; bp->b_flags |= XBF_MAPPED; } else if (flags & XBF_MAPPED) { - bp->b_addr = vm_map_ram(bp->b_pages, bp->b_page_count, - -1, PAGE_KERNEL); - if (unlikely(bp->b_addr == NULL)) + int retried = 0; + + do { + bp->b_addr = vm_map_ram(bp->b_pages, bp->b_page_count, + -1, PAGE_KERNEL); + if (bp->b_addr) + break; + vm_unmap_aliases(); + } while (retried++ <= 1); + + if (!bp->b_addr) return -ENOMEM; bp->b_addr += bp->b_offset; bp->b_flags |= XBF_MAPPED; -- cgit From 1bfd8d04190c615bb8d1d98188dead0c09702208 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Sat, 26 Mar 2011 09:13:55 +1100 Subject: xfs: introduce inode cluster buffer trylocks for xfs_iflush There is an ABBA deadlock between synchronous inode flushing in xfs_reclaim_inode and xfs_icluster_free. xfs_icluster_free locks the buffer, then takes inode ilocks, whilst synchronous reclaim takes the ilock followed by the buffer lock in xfs_iflush(). To avoid this deadlock, separate the inode cluster buffer locking semantics from the synchronous inode flush semantics, allowing callers to attempt to lock the buffer but still issue synchronous IO if it can get the buffer. This requires xfs_iflush() calls that currently use non-blocking semantics to pass SYNC_TRYLOCK rather than 0 as the flags parameter. This allows xfs_reclaim_inode to avoid the deadlock on the buffer lock and detect the failure so that it can drop the inode ilock and restart the reclaim attempt on the inode. This allows xfs_ifree_cluster to obtain the inode lock, mark the inode stale and release it and hence defuse the deadlock situation. It also has the pleasant side effect of avoiding IO in xfs_reclaim_inode when it tries to next reclaim the inode as it is now marked stale. Signed-off-by: Dave Chinner Reviewed-by: Christoph Hellwig Reviewed-by: Alex Elder --- fs/xfs/linux-2.6/xfs_super.c | 2 +- fs/xfs/linux-2.6/xfs_sync.c | 30 +++++++++++++++++++++++++++--- fs/xfs/xfs_inode.c | 2 +- fs/xfs/xfs_inode_item.c | 6 +++--- 4 files changed, 32 insertions(+), 8 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 818c4cf2de86..8a70b2a17d6f 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -1078,7 +1078,7 @@ xfs_fs_write_inode( error = 0; goto out_unlock; } - error = xfs_iflush(ip, 0); + error = xfs_iflush(ip, SYNC_TRYLOCK); } out_unlock: diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c index 6c10f1d2e3d3..594cd822d84d 100644 --- a/fs/xfs/linux-2.6/xfs_sync.c +++ b/fs/xfs/linux-2.6/xfs_sync.c @@ -761,8 +761,10 @@ xfs_reclaim_inode( struct xfs_perag *pag, int sync_mode) { - int error = 0; + int error; +restart: + error = 0; xfs_ilock(ip, XFS_ILOCK_EXCL); if (!xfs_iflock_nowait(ip)) { if (!(sync_mode & SYNC_WAIT)) @@ -788,9 +790,31 @@ xfs_reclaim_inode( if (xfs_inode_clean(ip)) goto reclaim; - /* Now we have an inode that needs flushing */ - error = xfs_iflush(ip, sync_mode); + /* + * Now we have an inode that needs flushing. + * + * We do a nonblocking flush here even if we are doing a SYNC_WAIT + * reclaim as we can deadlock with inode cluster removal. + * xfs_ifree_cluster() can lock the inode buffer before it locks the + * ip->i_lock, and we are doing the exact opposite here. As a result, + * doing a blocking xfs_itobp() to get the cluster buffer will result + * in an ABBA deadlock with xfs_ifree_cluster(). + * + * As xfs_ifree_cluser() must gather all inodes that are active in the + * cache to mark them stale, if we hit this case we don't actually want + * to do IO here - we want the inode marked stale so we can simply + * reclaim it. Hence if we get an EAGAIN error on a SYNC_WAIT flush, + * just unlock the inode, back off and try again. Hopefully the next + * pass through will see the stale flag set on the inode. + */ + error = xfs_iflush(ip, SYNC_TRYLOCK | sync_mode); if (sync_mode & SYNC_WAIT) { + if (error == EAGAIN) { + xfs_iunlock(ip, XFS_ILOCK_EXCL); + /* backoff longer than in xfs_ifree_cluster */ + delay(2); + goto restart; + } xfs_iflock(ip); goto reclaim; } diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index da871f532236..742c8330994a 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -2835,7 +2835,7 @@ xfs_iflush( * Get the buffer containing the on-disk inode. */ error = xfs_itobp(mp, NULL, ip, &dip, &bp, - (flags & SYNC_WAIT) ? XBF_LOCK : XBF_TRYLOCK); + (flags & SYNC_TRYLOCK) ? XBF_TRYLOCK : XBF_LOCK); if (error || !bp) { xfs_ifunlock(ip); return error; diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index fd4f398bd6f1..46cc40131d4a 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c @@ -760,11 +760,11 @@ xfs_inode_item_push( * Push the inode to it's backing buffer. This will not remove the * inode from the AIL - a further push will be required to trigger a * buffer push. However, this allows all the dirty inodes to be pushed - * to the buffer before it is pushed to disk. THe buffer IO completion - * will pull th einode from the AIL, mark it clean and unlock the flush + * to the buffer before it is pushed to disk. The buffer IO completion + * will pull the inode from the AIL, mark it clean and unlock the flush * lock. */ - (void) xfs_iflush(ip, 0); + (void) xfs_iflush(ip, SYNC_TRYLOCK); xfs_iunlock(ip, XFS_ILOCK_SHARED); } -- cgit From 7401aafd5019d32a888e5f27332cf580945574bf Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Sat, 26 Mar 2011 09:14:44 +1100 Subject: xfs: xfs_trans_read_buf() should return an error on failure When inside a transaction and we fail to read a buffer, xfs_trans_read_buf returns a null buffer pointer and no error. xfs_do_da_buf() checks the error return, but not the buffer, and as a result this read failure condition causes a panic when it attempts to dereference the non-existant buffer. Make xfs_trans_read_buf() return the same error for this situation regardless of whether it is in a transaction or not. This means every caller does not need to check both the error return and the buffer before proceeding to use the buffer. Signed-off-by: Dave Chinner Reviewed-by: Alex Elder --- fs/xfs/xfs_trans_buf.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c index 3bea66132334..03b3b7f85a3b 100644 --- a/fs/xfs/xfs_trans_buf.c +++ b/fs/xfs/xfs_trans_buf.c @@ -383,7 +383,8 @@ xfs_trans_read_buf( bp = xfs_buf_read(target, blkno, len, flags | XBF_DONT_BLOCK); if (bp == NULL) { *bpp = NULL; - return 0; + return (flags & XBF_TRYLOCK) ? + 0 : XFS_ERROR(ENOMEM); } if (XFS_BUF_GETERROR(bp) != 0) { XFS_BUF_SUPER_STALE(bp); -- cgit From 704b2907c2d47ceb187c0e25a6bbc2174b198f2f Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Sat, 26 Mar 2011 09:14:57 +1100 Subject: xfs: register the inode cache shrinker before quotachecks During mount, we can do a quotacheck that involves a bulkstat pass on all inodes. If there are more inodes in the filesystem than can be held in memory, we require the inode cache shrinker to run to ensure that we don't run out of memory. Unfortunately, the inode cache shrinker is not registered until we get to the end of the superblock setup process, which is after a quotacheck is run if it is needed. Hence we need to register the inode cache shrinker earlier in the mount process so that we don't OOM during mount. This requires that we also initialise the syncd work before we register the shrinker, so we nee dto juggle that around as well. While there, make sure that we have set up the block sizes in the VFS superblock correctly before the quotacheck is run so that any inodes that are cached as a result of the quotacheck have their block size fields set up correctly. Cc: stable@kernel.org Signed-off-by: Dave Chinner Reviewed-by: Alex Elder --- fs/xfs/linux-2.6/xfs_super.c | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 8a70b2a17d6f..1ba5c451da36 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -1539,10 +1539,14 @@ xfs_fs_fill_super( if (error) goto out_free_sb; - error = xfs_mountfs(mp); - if (error) - goto out_filestream_unmount; - + /* + * we must configure the block size in the superblock before we run the + * full mount process as the mount process can lookup and cache inodes. + * For the same reason we must also initialise the syncd and register + * the inode cache shrinker so that inodes can be reclaimed during + * operations like a quotacheck that iterate all inodes in the + * filesystem. + */ sb->s_magic = XFS_SB_MAGIC; sb->s_blocksize = mp->m_sb.sb_blocksize; sb->s_blocksize_bits = ffs(sb->s_blocksize) - 1; @@ -1550,6 +1554,16 @@ xfs_fs_fill_super( sb->s_time_gran = 1; set_posix_acl_flag(sb); + error = xfs_syncd_init(mp); + if (error) + goto out_filestream_unmount; + + xfs_inode_shrinker_register(mp); + + error = xfs_mountfs(mp); + if (error) + goto out_syncd_stop; + root = igrab(VFS_I(mp->m_rootip)); if (!root) { error = ENOENT; @@ -1565,14 +1579,11 @@ xfs_fs_fill_super( goto fail_vnrele; } - error = xfs_syncd_init(mp); - if (error) - goto fail_vnrele; - - xfs_inode_shrinker_register(mp); - return 0; + out_syncd_stop: + xfs_inode_shrinker_unregister(mp); + xfs_syncd_stop(mp); out_filestream_unmount: xfs_filestream_unmount(mp); out_free_sb: @@ -1596,6 +1607,9 @@ xfs_fs_fill_super( } fail_unmount: + xfs_inode_shrinker_unregister(mp); + xfs_syncd_stop(mp); + /* * Blow away any referenced inode in the filestreams cache. * This can and will cause log traffic as inodes go inactive -- cgit From 0e6e847ffe37436e331c132639f9f872febce82e Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Sat, 26 Mar 2011 09:16:45 +1100 Subject: xfs: stop using the page cache to back the buffer cache Now that the buffer cache has it's own LRU, we do not need to use the page cache to provide persistent caching and reclaim infrastructure. Convert the buffer cache to use alloc_pages() instead of the page cache. This will remove all the overhead of page cache management from setup and teardown of the buffers, as well as needing to mark pages accessed as we find buffers in the buffer cache. By avoiding the page cache, we also remove the need to keep state in the page_private(page) field for persistant storage across buffer free/buffer rebuild and so all that code can be removed. This also fixes the long-standing problem of not having enough bits in the page_private field to track all the state needed for a 512 sector/64k page setup. It also removes the need for page locking during reads as the pages are unique to the buffer and nobody else will be attempting to access them. Finally, it removes the buftarg address space lock as a point of global contention on workloads that allocate and free buffers quickly such as when creating or removing large numbers of inodes in parallel. This remove the 16TB limit on filesystem size on 32 bit machines as the page index (32 bit) is no longer used for lookups of metadata buffers - the buffer cache is now solely indexed by disk address which is stored in a 64 bit field in the buffer. Signed-off-by: Dave Chinner Reviewed-by: Alex Elder --- fs/xfs/linux-2.6/xfs_buf.c | 341 +++++++++++---------------------------------- fs/xfs/linux-2.6/xfs_buf.h | 40 +----- 2 files changed, 84 insertions(+), 297 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index a5a260fab824..d45b2cdee6c4 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c @@ -93,75 +93,6 @@ xfs_buf_vmap_len( return (bp->b_page_count * PAGE_SIZE) - bp->b_offset; } -/* - * Page Region interfaces. - * - * For pages in filesystems where the blocksize is smaller than the - * pagesize, we use the page->private field (long) to hold a bitmap - * of uptodate regions within the page. - * - * Each such region is "bytes per page / bits per long" bytes long. - * - * NBPPR == number-of-bytes-per-page-region - * BTOPR == bytes-to-page-region (rounded up) - * BTOPRT == bytes-to-page-region-truncated (rounded down) - */ -#if (BITS_PER_LONG == 32) -#define PRSHIFT (PAGE_CACHE_SHIFT - 5) /* (32 == 1<<5) */ -#elif (BITS_PER_LONG == 64) -#define PRSHIFT (PAGE_CACHE_SHIFT - 6) /* (64 == 1<<6) */ -#else -#error BITS_PER_LONG must be 32 or 64 -#endif -#define NBPPR (PAGE_CACHE_SIZE/BITS_PER_LONG) -#define BTOPR(b) (((unsigned int)(b) + (NBPPR - 1)) >> PRSHIFT) -#define BTOPRT(b) (((unsigned int)(b) >> PRSHIFT)) - -STATIC unsigned long -page_region_mask( - size_t offset, - size_t length) -{ - unsigned long mask; - int first, final; - - first = BTOPR(offset); - final = BTOPRT(offset + length - 1); - first = min(first, final); - - mask = ~0UL; - mask <<= BITS_PER_LONG - (final - first); - mask >>= BITS_PER_LONG - (final); - - ASSERT(offset + length <= PAGE_CACHE_SIZE); - ASSERT((final - first) < BITS_PER_LONG && (final - first) >= 0); - - return mask; -} - -STATIC void -set_page_region( - struct page *page, - size_t offset, - size_t length) -{ - set_page_private(page, - page_private(page) | page_region_mask(offset, length)); - if (page_private(page) == ~0UL) - SetPageUptodate(page); -} - -STATIC int -test_page_region( - struct page *page, - size_t offset, - size_t length) -{ - unsigned long mask = page_region_mask(offset, length); - - return (mask && (page_private(page) & mask) == mask); -} - /* * xfs_buf_lru_add - add a buffer to the LRU. * @@ -332,7 +263,7 @@ xfs_buf_free( ASSERT(list_empty(&bp->b_lru)); - if (bp->b_flags & (_XBF_PAGE_CACHE|_XBF_PAGES)) { + if (bp->b_flags & _XBF_PAGES) { uint i; if (xfs_buf_is_vmapped(bp)) @@ -342,25 +273,22 @@ xfs_buf_free( for (i = 0; i < bp->b_page_count; i++) { struct page *page = bp->b_pages[i]; - if (bp->b_flags & _XBF_PAGE_CACHE) - ASSERT(!PagePrivate(page)); - page_cache_release(page); + __free_page(page); } - } + } else if (bp->b_flags & _XBF_KMEM) + kmem_free(bp->b_addr); _xfs_buf_free_pages(bp); xfs_buf_deallocate(bp); } /* - * Finds all pages for buffer in question and builds it's page list. + * Allocates all the pages for buffer in question and builds it's page list. */ STATIC int -_xfs_buf_lookup_pages( +xfs_buf_allocate_memory( xfs_buf_t *bp, uint flags) { - struct address_space *mapping = bp->b_target->bt_mapping; - size_t blocksize = bp->b_target->bt_bsize; size_t size = bp->b_count_desired; size_t nbytes, offset; gfp_t gfp_mask = xb_to_gfp(flags); @@ -369,29 +297,55 @@ _xfs_buf_lookup_pages( xfs_off_t end; int error; + /* + * for buffers that are contained within a single page, just allocate + * the memory from the heap - there's no need for the complexity of + * page arrays to keep allocation down to order 0. + */ + if (bp->b_buffer_length < PAGE_SIZE) { + bp->b_addr = kmem_alloc(bp->b_buffer_length, xb_to_km(flags)); + if (!bp->b_addr) { + /* low memory - use alloc_page loop instead */ + goto use_alloc_page; + } + + if (((unsigned long)(bp->b_addr + bp->b_buffer_length - 1) & + PAGE_MASK) != + ((unsigned long)bp->b_addr & PAGE_MASK)) { + /* b_addr spans two pages - use alloc_page instead */ + kmem_free(bp->b_addr); + bp->b_addr = NULL; + goto use_alloc_page; + } + bp->b_offset = offset_in_page(bp->b_addr); + bp->b_pages = bp->b_page_array; + bp->b_pages[0] = virt_to_page(bp->b_addr); + bp->b_page_count = 1; + bp->b_flags |= XBF_MAPPED | _XBF_KMEM; + return 0; + } + +use_alloc_page: end = bp->b_file_offset + bp->b_buffer_length; page_count = xfs_buf_btoc(end) - xfs_buf_btoct(bp->b_file_offset); - error = _xfs_buf_get_pages(bp, page_count, flags); if (unlikely(error)) return error; - bp->b_flags |= _XBF_PAGE_CACHE; offset = bp->b_offset; - first = bp->b_file_offset >> PAGE_CACHE_SHIFT; + first = bp->b_file_offset >> PAGE_SHIFT; + bp->b_flags |= _XBF_PAGES; for (i = 0; i < bp->b_page_count; i++) { struct page *page; uint retries = 0; - - retry: - page = find_or_create_page(mapping, first + i, gfp_mask); +retry: + page = alloc_page(gfp_mask); if (unlikely(page == NULL)) { if (flags & XBF_READ_AHEAD) { bp->b_page_count = i; - for (i = 0; i < bp->b_page_count; i++) - unlock_page(bp->b_pages[i]); - return -ENOMEM; + error = ENOMEM; + goto out_free_pages; } /* @@ -412,33 +366,16 @@ _xfs_buf_lookup_pages( XFS_STATS_INC(xb_page_found); - nbytes = min_t(size_t, size, PAGE_CACHE_SIZE - offset); + nbytes = min_t(size_t, size, PAGE_SIZE - offset); size -= nbytes; - - ASSERT(!PagePrivate(page)); - if (!PageUptodate(page)) { - page_count--; - if (blocksize >= PAGE_CACHE_SIZE) { - if (flags & XBF_READ) - bp->b_flags |= _XBF_PAGE_LOCKED; - } else if (!PagePrivate(page)) { - if (test_page_region(page, offset, nbytes)) - page_count++; - } - } - bp->b_pages[i] = page; offset = 0; } + return 0; - if (!(bp->b_flags & _XBF_PAGE_LOCKED)) { - for (i = 0; i < bp->b_page_count; i++) - unlock_page(bp->b_pages[i]); - } - - if (page_count == bp->b_page_count) - bp->b_flags |= XBF_DONE; - +out_free_pages: + for (i = 0; i < bp->b_page_count; i++) + __free_page(bp->b_pages[i]); return error; } @@ -450,8 +387,9 @@ _xfs_buf_map_pages( xfs_buf_t *bp, uint flags) { - /* A single page buffer is always mappable */ + ASSERT(bp->b_flags & _XBF_PAGES); if (bp->b_page_count == 1) { + /* A single page buffer is always mappable */ bp->b_addr = page_address(bp->b_pages[0]) + bp->b_offset; bp->b_flags |= XBF_MAPPED; } else if (flags & XBF_MAPPED) { @@ -576,9 +514,14 @@ found: } } + /* + * if the buffer is stale, clear all the external state associated with + * it. We need to keep flags such as how we allocated the buffer memory + * intact here. + */ if (bp->b_flags & XBF_STALE) { ASSERT((bp->b_flags & _XBF_DELWRI_Q) == 0); - bp->b_flags &= XBF_MAPPED; + bp->b_flags &= XBF_MAPPED | _XBF_KMEM | _XBF_PAGES; } trace_xfs_buf_find(bp, flags, _RET_IP_); @@ -599,7 +542,7 @@ xfs_buf_get( xfs_buf_flags_t flags) { xfs_buf_t *bp, *new_bp; - int error = 0, i; + int error = 0; new_bp = xfs_buf_allocate(flags); if (unlikely(!new_bp)) @@ -607,7 +550,7 @@ xfs_buf_get( bp = _xfs_buf_find(target, ioff, isize, flags, new_bp); if (bp == new_bp) { - error = _xfs_buf_lookup_pages(bp, flags); + error = xfs_buf_allocate_memory(bp, flags); if (error) goto no_buffer; } else { @@ -616,9 +559,6 @@ xfs_buf_get( return NULL; } - for (i = 0; i < bp->b_page_count; i++) - mark_page_accessed(bp->b_pages[i]); - if (!(bp->b_flags & XBF_MAPPED)) { error = _xfs_buf_map_pages(bp, flags); if (unlikely(error)) { @@ -719,8 +659,7 @@ xfs_buf_readahead( { struct backing_dev_info *bdi; - bdi = target->bt_mapping->backing_dev_info; - if (bdi_read_congested(bdi)) + if (bdi_read_congested(target->bt_bdi)) return; xfs_buf_read(target, ioff, isize, @@ -798,10 +737,10 @@ xfs_buf_associate_memory( size_t buflen; int page_count; - pageaddr = (unsigned long)mem & PAGE_CACHE_MASK; + pageaddr = (unsigned long)mem & PAGE_MASK; offset = (unsigned long)mem - pageaddr; - buflen = PAGE_CACHE_ALIGN(len + offset); - page_count = buflen >> PAGE_CACHE_SHIFT; + buflen = PAGE_ALIGN(len + offset); + page_count = buflen >> PAGE_SHIFT; /* Free any previous set of page pointers */ if (bp->b_pages) @@ -818,13 +757,12 @@ xfs_buf_associate_memory( for (i = 0; i < bp->b_page_count; i++) { bp->b_pages[i] = mem_to_page((void *)pageaddr); - pageaddr += PAGE_CACHE_SIZE; + pageaddr += PAGE_SIZE; } bp->b_count_desired = len; bp->b_buffer_length = buflen; bp->b_flags |= XBF_MAPPED; - bp->b_flags &= ~_XBF_PAGE_LOCKED; return 0; } @@ -931,20 +869,7 @@ xfs_buf_rele( /* - * Mutual exclusion on buffers. Locking model: - * - * Buffers associated with inodes for which buffer locking - * is not enabled are not protected by semaphores, and are - * assumed to be exclusively owned by the caller. There is a - * spinlock in the buffer, used by the caller when concurrent - * access is possible. - */ - -/* - * Locks a buffer object, if it is not already locked. Note that this in - * no way locks the underlying pages, so it is only useful for - * synchronizing concurrent use of buffer objects, not for synchronizing - * independent access to the underlying pages. + * Lock a buffer object, if it is not already locked. * * If we come across a stale, pinned, locked buffer, we know that we are * being asked to lock a buffer that has been reallocated. Because it is @@ -978,10 +903,7 @@ xfs_buf_lock_value( } /* - * Locks a buffer object. - * Note that this in no way locks the underlying pages, so it is only - * useful for synchronizing concurrent use of buffer objects, not for - * synchronizing independent access to the underlying pages. + * Lock a buffer object. * * If we come across a stale, pinned, locked buffer, we know that we * are being asked to lock a buffer that has been reallocated. Because @@ -998,7 +920,7 @@ xfs_buf_lock( if (atomic_read(&bp->b_pin_count) && (bp->b_flags & XBF_STALE)) xfs_log_force(bp->b_target->bt_mount, 0); if (atomic_read(&bp->b_io_remaining)) - blk_run_address_space(bp->b_target->bt_mapping); + blk_run_backing_dev(bp->b_target->bt_bdi, NULL); down(&bp->b_sema); XB_SET_OWNER(bp); @@ -1043,7 +965,7 @@ xfs_buf_wait_unpin( if (atomic_read(&bp->b_pin_count) == 0) break; if (atomic_read(&bp->b_io_remaining)) - blk_run_address_space(bp->b_target->bt_mapping); + blk_run_backing_dev(bp->b_target->bt_bdi, NULL); schedule(); } remove_wait_queue(&bp->b_waiters, &wait); @@ -1256,10 +1178,8 @@ _xfs_buf_ioend( xfs_buf_t *bp, int schedule) { - if (atomic_dec_and_test(&bp->b_io_remaining) == 1) { - bp->b_flags &= ~_XBF_PAGE_LOCKED; + if (atomic_dec_and_test(&bp->b_io_remaining) == 1) xfs_buf_ioend(bp, schedule); - } } STATIC void @@ -1268,35 +1188,12 @@ xfs_buf_bio_end_io( int error) { xfs_buf_t *bp = (xfs_buf_t *)bio->bi_private; - unsigned int blocksize = bp->b_target->bt_bsize; - struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; xfs_buf_ioerror(bp, -error); if (!error && xfs_buf_is_vmapped(bp) && (bp->b_flags & XBF_READ)) invalidate_kernel_vmap_range(bp->b_addr, xfs_buf_vmap_len(bp)); - do { - struct page *page = bvec->bv_page; - - ASSERT(!PagePrivate(page)); - if (unlikely(bp->b_error)) { - if (bp->b_flags & XBF_READ) - ClearPageUptodate(page); - } else if (blocksize >= PAGE_CACHE_SIZE) { - SetPageUptodate(page); - } else if (!PagePrivate(page) && - (bp->b_flags & _XBF_PAGE_CACHE)) { - set_page_region(page, bvec->bv_offset, bvec->bv_len); - } - - if (--bvec >= bio->bi_io_vec) - prefetchw(&bvec->bv_page->flags); - - if (bp->b_flags & _XBF_PAGE_LOCKED) - unlock_page(page); - } while (bvec >= bio->bi_io_vec); - _xfs_buf_ioend(bp, 1); bio_put(bio); } @@ -1310,7 +1207,6 @@ _xfs_buf_ioapply( int offset = bp->b_offset; int size = bp->b_count_desired; sector_t sector = bp->b_bn; - unsigned int blocksize = bp->b_target->bt_bsize; total_nr_pages = bp->b_page_count; map_i = 0; @@ -1331,29 +1227,6 @@ _xfs_buf_ioapply( (bp->b_flags & XBF_READ_AHEAD) ? READA : READ; } - /* Special code path for reading a sub page size buffer in -- - * we populate up the whole page, and hence the other metadata - * in the same page. This optimization is only valid when the - * filesystem block size is not smaller than the page size. - */ - if ((bp->b_buffer_length < PAGE_CACHE_SIZE) && - ((bp->b_flags & (XBF_READ|_XBF_PAGE_LOCKED)) == - (XBF_READ|_XBF_PAGE_LOCKED)) && - (blocksize >= PAGE_CACHE_SIZE)) { - bio = bio_alloc(GFP_NOIO, 1); - - bio->bi_bdev = bp->b_target->bt_bdev; - bio->bi_sector = sector - (offset >> BBSHIFT); - bio->bi_end_io = xfs_buf_bio_end_io; - bio->bi_private = bp; - - bio_add_page(bio, bp->b_pages[0], PAGE_CACHE_SIZE, 0); - size = 0; - - atomic_inc(&bp->b_io_remaining); - - goto submit_io; - } next_chunk: atomic_inc(&bp->b_io_remaining); @@ -1367,8 +1240,9 @@ next_chunk: bio->bi_end_io = xfs_buf_bio_end_io; bio->bi_private = bp; + for (; size && nr_pages; nr_pages--, map_i++) { - int rbytes, nbytes = PAGE_CACHE_SIZE - offset; + int rbytes, nbytes = PAGE_SIZE - offset; if (nbytes > size) nbytes = size; @@ -1383,7 +1257,6 @@ next_chunk: total_nr_pages--; } -submit_io: if (likely(bio->bi_size)) { if (xfs_buf_is_vmapped(bp)) { flush_kernel_vmap_range(bp->b_addr, @@ -1393,18 +1266,7 @@ submit_io: if (size) goto next_chunk; } else { - /* - * if we get here, no pages were added to the bio. However, - * we can't just error out here - if the pages are locked then - * we have to unlock them otherwise we can hang on a later - * access to the page. - */ xfs_buf_ioerror(bp, EIO); - if (bp->b_flags & _XBF_PAGE_LOCKED) { - int i; - for (i = 0; i < bp->b_page_count; i++) - unlock_page(bp->b_pages[i]); - } bio_put(bio); } } @@ -1450,7 +1312,7 @@ xfs_buf_iowait( trace_xfs_buf_iowait(bp, _RET_IP_); if (atomic_read(&bp->b_io_remaining)) - blk_run_address_space(bp->b_target->bt_mapping); + blk_run_backing_dev(bp->b_target->bt_bdi, NULL); wait_for_completion(&bp->b_iowait); trace_xfs_buf_iowait_done(bp, _RET_IP_); @@ -1468,8 +1330,8 @@ xfs_buf_offset( return XFS_BUF_PTR(bp) + offset; offset += bp->b_offset; - page = bp->b_pages[offset >> PAGE_CACHE_SHIFT]; - return (xfs_caddr_t)page_address(page) + (offset & (PAGE_CACHE_SIZE-1)); + page = bp->b_pages[offset >> PAGE_SHIFT]; + return (xfs_caddr_t)page_address(page) + (offset & (PAGE_SIZE-1)); } /* @@ -1491,9 +1353,9 @@ xfs_buf_iomove( page = bp->b_pages[xfs_buf_btoct(boff + bp->b_offset)]; cpoff = xfs_buf_poff(boff + bp->b_offset); csize = min_t(size_t, - PAGE_CACHE_SIZE-cpoff, bp->b_count_desired-boff); + PAGE_SIZE-cpoff, bp->b_count_desired-boff); - ASSERT(((csize + cpoff) <= PAGE_CACHE_SIZE)); + ASSERT(((csize + cpoff) <= PAGE_SIZE)); switch (mode) { case XBRW_ZERO: @@ -1606,7 +1468,6 @@ xfs_free_buftarg( xfs_flush_buftarg(btp, 1); if (mp->m_flags & XFS_MOUNT_BARRIER) xfs_blkdev_issue_flush(btp); - iput(btp->bt_mapping->host); kthread_stop(btp->bt_task); kmem_free(btp); @@ -1630,15 +1491,6 @@ xfs_setsize_buftarg_flags( return EINVAL; } - if (verbose && - (PAGE_CACHE_SIZE / BITS_PER_LONG) > sectorsize) { - printk(KERN_WARNING - "XFS: %u byte sectors in use on device %s. " - "This is suboptimal; %u or greater is ideal.\n", - sectorsize, XFS_BUFTARG_NAME(btp), - (unsigned int)PAGE_CACHE_SIZE / BITS_PER_LONG); - } - return 0; } @@ -1653,7 +1505,7 @@ xfs_setsize_buftarg_early( struct block_device *bdev) { return xfs_setsize_buftarg_flags(btp, - PAGE_CACHE_SIZE, bdev_logical_block_size(bdev), 0); + PAGE_SIZE, bdev_logical_block_size(bdev), 0); } int @@ -1665,41 +1517,6 @@ xfs_setsize_buftarg( return xfs_setsize_buftarg_flags(btp, blocksize, sectorsize, 1); } -STATIC int -xfs_mapping_buftarg( - xfs_buftarg_t *btp, - struct block_device *bdev) -{ - struct backing_dev_info *bdi; - struct inode *inode; - struct address_space *mapping; - static const struct address_space_operations mapping_aops = { - .sync_page = block_sync_page, - .migratepage = fail_migrate_page, - }; - - inode = new_inode(bdev->bd_inode->i_sb); - if (!inode) { - printk(KERN_WARNING - "XFS: Cannot allocate mapping inode for device %s\n", - XFS_BUFTARG_NAME(btp)); - return ENOMEM; - } - inode->i_ino = get_next_ino(); - inode->i_mode = S_IFBLK; - inode->i_bdev = bdev; - inode->i_rdev = bdev->bd_dev; - bdi = blk_get_backing_dev_info(bdev); - if (!bdi) - bdi = &default_backing_dev_info; - mapping = &inode->i_data; - mapping->a_ops = &mapping_aops; - mapping->backing_dev_info = bdi; - mapping_set_gfp_mask(mapping, GFP_NOFS); - btp->bt_mapping = mapping; - return 0; -} - STATIC int xfs_alloc_delwrite_queue( xfs_buftarg_t *btp, @@ -1728,12 +1545,14 @@ xfs_alloc_buftarg( btp->bt_mount = mp; btp->bt_dev = bdev->bd_dev; btp->bt_bdev = bdev; + btp->bt_bdi = blk_get_backing_dev_info(bdev); + if (!btp->bt_bdi) + goto error; + INIT_LIST_HEAD(&btp->bt_lru); spin_lock_init(&btp->bt_lru_lock); if (xfs_setsize_buftarg_early(btp, bdev)) goto error; - if (xfs_mapping_buftarg(btp, bdev)) - goto error; if (xfs_alloc_delwrite_queue(btp, fsname)) goto error; btp->bt_shrinker.shrink = xfs_buftarg_shrink; @@ -1955,7 +1774,7 @@ xfsbufd( count++; } if (count) - blk_run_address_space(target->bt_mapping); + blk_run_backing_dev(target->bt_bdi, NULL); } while (!kthread_should_stop()); @@ -2003,7 +1822,7 @@ xfs_flush_buftarg( if (wait) { /* Expedite and wait for IO to complete. */ - blk_run_address_space(target->bt_mapping); + blk_run_backing_dev(target->bt_bdi, NULL); while (!list_empty(&wait_list)) { bp = list_first_entry(&wait_list, struct xfs_buf, b_list); diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h index cbe65950e524..a9a1c4512645 100644 --- a/fs/xfs/linux-2.6/xfs_buf.h +++ b/fs/xfs/linux-2.6/xfs_buf.h @@ -61,30 +61,11 @@ typedef enum { #define XBF_DONT_BLOCK (1 << 16)/* do not block in current thread */ /* flags used only internally */ -#define _XBF_PAGE_CACHE (1 << 17)/* backed by pagecache */ #define _XBF_PAGES (1 << 18)/* backed by refcounted pages */ #define _XBF_RUN_QUEUES (1 << 19)/* run block device task queue */ +#define _XBF_KMEM (1 << 20)/* backed by heap memory */ #define _XBF_DELWRI_Q (1 << 21)/* buffer on delwri queue */ -/* - * Special flag for supporting metadata blocks smaller than a FSB. - * - * In this case we can have multiple xfs_buf_t on a single page and - * need to lock out concurrent xfs_buf_t readers as they only - * serialise access to the buffer. - * - * If the FSB size >= PAGE_CACHE_SIZE case, we have no serialisation - * between reads of the page. Hence we can have one thread read the - * page and modify it, but then race with another thread that thinks - * the page is not up-to-date and hence reads it again. - * - * The result is that the first modifcation to the page is lost. - * This sort of AGF/AGI reading race can happen when unlinking inodes - * that require truncation and results in the AGI unlinked list - * modifications being lost. - */ -#define _XBF_PAGE_LOCKED (1 << 22) - typedef unsigned int xfs_buf_flags_t; #define XFS_BUF_FLAGS \ @@ -100,12 +81,10 @@ typedef unsigned int xfs_buf_flags_t; { XBF_LOCK, "LOCK" }, /* should never be set */\ { XBF_TRYLOCK, "TRYLOCK" }, /* ditto */\ { XBF_DONT_BLOCK, "DONT_BLOCK" }, /* ditto */\ - { _XBF_PAGE_CACHE, "PAGE_CACHE" }, \ { _XBF_PAGES, "PAGES" }, \ { _XBF_RUN_QUEUES, "RUN_QUEUES" }, \ - { _XBF_DELWRI_Q, "DELWRI_Q" }, \ - { _XBF_PAGE_LOCKED, "PAGE_LOCKED" } - + { _XBF_KMEM, "KMEM" }, \ + { _XBF_DELWRI_Q, "DELWRI_Q" } typedef enum { XBT_FORCE_SLEEP = 0, @@ -120,7 +99,7 @@ typedef struct xfs_bufhash { typedef struct xfs_buftarg { dev_t bt_dev; struct block_device *bt_bdev; - struct address_space *bt_mapping; + struct backing_dev_info *bt_bdi; struct xfs_mount *bt_mount; unsigned int bt_bsize; unsigned int bt_sshift; @@ -139,17 +118,6 @@ typedef struct xfs_buftarg { unsigned int bt_lru_nr; } xfs_buftarg_t; -/* - * xfs_buf_t: Buffer structure for pagecache-based buffers - * - * This buffer structure is used by the pagecache buffer management routines - * to refer to an assembly of pages forming a logical buffer. - * - * The buffer structure is used on a temporary basis only, and discarded when - * released. The real data storage is recorded in the pagecache. Buffers are - * hashed to the block device on which the file system resides. - */ - struct xfs_buf; typedef void (*xfs_buf_iodone_t)(struct xfs_buf *); -- cgit From 4e69b598f6cfb0940b75abf7e179d6020e94ad1e Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Mon, 21 Mar 2011 10:11:24 -0400 Subject: Btrfs: cleanup how we setup free space clusters This patch makes the free space cluster refilling code a little easier to understand, and fixes some things with the bitmap part of it. Currently we either want to refill a cluster with 1) All normal extent entries (those without bitmaps) 2) A bitmap entry with enough space The current code has this ugly jump around logic that will first try and fill up the cluster with extent entries and then if it can't do that it will try and find a bitmap to use. So instead split this out into two functions, one that tries to find only normal entries, and one that tries to find bitmaps. This also fixes a suboptimal thing we would do with bitmaps. If we used a bitmap we would just tell the cluster that we were pointing at a bitmap and it would do the tree search in the block group for that entry every time we tried to make an allocation. Instead of doing that now we just add it to the clusters group. I tested this with my ENOSPC tests and xfstests and it survived. Signed-off-by: Josef Bacik --- fs/btrfs/ctree.h | 3 - fs/btrfs/free-space-cache.c | 364 ++++++++++++++++++++++---------------------- 2 files changed, 182 insertions(+), 185 deletions(-) (limited to 'fs') diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 6036fdb88c53..0ee679b6c1b7 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -783,9 +783,6 @@ struct btrfs_free_cluster { /* first extent starting offset */ u64 window_start; - /* if this cluster simply points at a bitmap in the block group */ - bool points_to_bitmap; - struct btrfs_block_group_cache *block_group; /* * when a cluster is allocated from a block group, we put the diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 4ab35ea0443f..f03ef97c3b21 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -1644,30 +1644,28 @@ __btrfs_return_cluster_to_free_space( { struct btrfs_free_space *entry; struct rb_node *node; - bool bitmap; spin_lock(&cluster->lock); if (cluster->block_group != block_group) goto out; - bitmap = cluster->points_to_bitmap; cluster->block_group = NULL; cluster->window_start = 0; list_del_init(&cluster->block_group_list); - cluster->points_to_bitmap = false; - - if (bitmap) - goto out; node = rb_first(&cluster->root); while (node) { + bool bitmap; + entry = rb_entry(node, struct btrfs_free_space, offset_index); node = rb_next(&entry->offset_index); rb_erase(&entry->offset_index, &cluster->root); - BUG_ON(entry->bitmap); - try_merge_free_space(block_group, entry, false); + + bitmap = (entry->bitmap != NULL); + if (!bitmap) + try_merge_free_space(block_group, entry, false); tree_insert_offset(&block_group->free_space_offset, - entry->offset, &entry->offset_index, 0); + entry->offset, &entry->offset_index, bitmap); } cluster->root = RB_ROOT; @@ -1790,50 +1788,24 @@ int btrfs_return_cluster_to_free_space( static u64 btrfs_alloc_from_bitmap(struct btrfs_block_group_cache *block_group, struct btrfs_free_cluster *cluster, + struct btrfs_free_space *entry, u64 bytes, u64 min_start) { - struct btrfs_free_space *entry; int err; u64 search_start = cluster->window_start; u64 search_bytes = bytes; u64 ret = 0; - spin_lock(&block_group->tree_lock); - spin_lock(&cluster->lock); - - if (!cluster->points_to_bitmap) - goto out; - - if (cluster->block_group != block_group) - goto out; - - /* - * search_start is the beginning of the bitmap, but at some point it may - * be a good idea to point to the actual start of the free area in the - * bitmap, so do the offset_to_bitmap trick anyway, and set bitmap_only - * to 1 to make sure we get the bitmap entry - */ - entry = tree_search_offset(block_group, - offset_to_bitmap(block_group, search_start), - 1, 0); - if (!entry || !entry->bitmap) - goto out; - search_start = min_start; search_bytes = bytes; err = search_bitmap(block_group, entry, &search_start, &search_bytes); if (err) - goto out; + return 0; ret = search_start; bitmap_clear_bits(block_group, entry, ret, bytes); - if (entry->bytes == 0) - free_bitmap(block_group, entry); -out: - spin_unlock(&cluster->lock); - spin_unlock(&block_group->tree_lock); return ret; } @@ -1851,10 +1823,6 @@ u64 btrfs_alloc_from_cluster(struct btrfs_block_group_cache *block_group, struct rb_node *node; u64 ret = 0; - if (cluster->points_to_bitmap) - return btrfs_alloc_from_bitmap(block_group, cluster, bytes, - min_start); - spin_lock(&cluster->lock); if (bytes > cluster->max_size) goto out; @@ -1867,9 +1835,9 @@ u64 btrfs_alloc_from_cluster(struct btrfs_block_group_cache *block_group, goto out; entry = rb_entry(node, struct btrfs_free_space, offset_index); - while(1) { - if (entry->bytes < bytes || entry->offset < min_start) { + if (entry->bytes < bytes || + (!entry->bitmap && entry->offset < min_start)) { struct rb_node *node; node = rb_next(&entry->offset_index); @@ -1879,10 +1847,27 @@ u64 btrfs_alloc_from_cluster(struct btrfs_block_group_cache *block_group, offset_index); continue; } - ret = entry->offset; - entry->offset += bytes; - entry->bytes -= bytes; + if (entry->bitmap) { + ret = btrfs_alloc_from_bitmap(block_group, + cluster, entry, bytes, + min_start); + if (ret == 0) { + struct rb_node *node; + node = rb_next(&entry->offset_index); + if (!node) + break; + entry = rb_entry(node, struct btrfs_free_space, + offset_index); + continue; + } + } else { + + ret = entry->offset; + + entry->offset += bytes; + entry->bytes -= bytes; + } if (entry->bytes == 0) rb_erase(&entry->offset_index, &cluster->root); @@ -1899,6 +1884,11 @@ out: block_group->free_space -= bytes; if (entry->bytes == 0) { block_group->free_extents--; + if (entry->bitmap) { + kfree(entry->bitmap); + block_group->total_bitmaps--; + recalculate_thresholds(block_group); + } kmem_cache_free(btrfs_free_space_cachep, entry); } @@ -1919,6 +1909,7 @@ static int btrfs_bitmap_cluster(struct btrfs_block_group_cache *block_group, unsigned long found_bits; unsigned long start = 0; unsigned long total_found = 0; + int ret; bool found = false; i = offset_to_bit(entry->offset, block_group->sectorsize, @@ -1941,7 +1932,7 @@ again: } if (!found_bits) - return -1; + return -ENOSPC; if (!found) { start = i; @@ -1965,11 +1956,144 @@ again: cluster->window_start = start * block_group->sectorsize + entry->offset; - cluster->points_to_bitmap = true; + rb_erase(&entry->offset_index, &block_group->free_space_offset); + ret = tree_insert_offset(&cluster->root, entry->offset, + &entry->offset_index, 1); + BUG_ON(ret); return 0; } +/* + * This searches the block group for just extents to fill the cluster with. + */ +static int setup_cluster_no_bitmap(struct btrfs_block_group_cache *block_group, + struct btrfs_free_cluster *cluster, + u64 offset, u64 bytes, u64 min_bytes) +{ + struct btrfs_free_space *first = NULL; + struct btrfs_free_space *entry = NULL; + struct btrfs_free_space *prev = NULL; + struct btrfs_free_space *last; + struct rb_node *node; + u64 window_start; + u64 window_free; + u64 max_extent; + u64 max_gap = 128 * 1024; + + entry = tree_search_offset(block_group, offset, 0, 1); + if (!entry) + return -ENOSPC; + + /* + * We don't want bitmaps, so just move along until we find a normal + * extent entry. + */ + while (entry->bitmap) { + node = rb_next(&entry->offset_index); + if (!node) + return -ENOSPC; + entry = rb_entry(node, struct btrfs_free_space, offset_index); + } + + window_start = entry->offset; + window_free = entry->bytes; + max_extent = entry->bytes; + first = entry; + last = entry; + prev = entry; + + while (window_free <= min_bytes) { + node = rb_next(&entry->offset_index); + if (!node) + return -ENOSPC; + entry = rb_entry(node, struct btrfs_free_space, offset_index); + + if (entry->bitmap) + continue; + /* + * we haven't filled the empty size and the window is + * very large. reset and try again + */ + if (entry->offset - (prev->offset + prev->bytes) > max_gap || + entry->offset - window_start > (min_bytes * 2)) { + first = entry; + window_start = entry->offset; + window_free = entry->bytes; + last = entry; + max_extent = entry->bytes; + } else { + last = entry; + window_free += entry->bytes; + if (entry->bytes > max_extent) + max_extent = entry->bytes; + } + prev = entry; + } + + cluster->window_start = first->offset; + + node = &first->offset_index; + + /* + * now we've found our entries, pull them out of the free space + * cache and put them into the cluster rbtree + */ + do { + int ret; + + entry = rb_entry(node, struct btrfs_free_space, offset_index); + node = rb_next(&entry->offset_index); + if (entry->bitmap) + continue; + + rb_erase(&entry->offset_index, &block_group->free_space_offset); + ret = tree_insert_offset(&cluster->root, entry->offset, + &entry->offset_index, 0); + BUG_ON(ret); + } while (node && entry != last); + + cluster->max_size = max_extent; + + return 0; +} + +/* + * This specifically looks for bitmaps that may work in the cluster, we assume + * that we have already failed to find extents that will work. + */ +static int setup_cluster_bitmap(struct btrfs_block_group_cache *block_group, + struct btrfs_free_cluster *cluster, + u64 offset, u64 bytes, u64 min_bytes) +{ + struct btrfs_free_space *entry; + struct rb_node *node; + int ret = -ENOSPC; + + if (block_group->total_bitmaps == 0) + return -ENOSPC; + + entry = tree_search_offset(block_group, + offset_to_bitmap(block_group, offset), + 0, 1); + if (!entry) + return -ENOSPC; + + node = &entry->offset_index; + do { + entry = rb_entry(node, struct btrfs_free_space, offset_index); + node = rb_next(&entry->offset_index); + if (!entry->bitmap) + continue; + if (entry->bytes < min_bytes) + continue; + ret = btrfs_bitmap_cluster(block_group, entry, cluster, offset, + bytes, min_bytes); + } while (ret && node); + + return ret; +} + /* * here we try to find a cluster of blocks in a block group. The goal * is to find at least bytes free and up to empty_size + bytes free. @@ -1984,15 +2108,7 @@ int btrfs_find_space_cluster(struct btrfs_trans_handle *trans, struct btrfs_free_cluster *cluster, u64 offset, u64 bytes, u64 empty_size) { - struct btrfs_free_space *entry = NULL; - struct rb_node *node; - struct btrfs_free_space *next; - struct btrfs_free_space *last = NULL; u64 min_bytes; - u64 window_start; - u64 window_free; - u64 max_extent = 0; - bool found_bitmap = false; int ret; /* for metadata, allow allocates with more holes */ @@ -2029,134 +2145,19 @@ int btrfs_find_space_cluster(struct btrfs_trans_handle *trans, ret = 0; goto out; } -again: - entry = tree_search_offset(block_group, offset, found_bitmap, 1); - if (!entry) { - ret = -ENOSPC; - goto out; - } - - /* - * If found_bitmap is true, we exhausted our search for extent entries, - * and we just want to search all of the bitmaps that we can find, and - * ignore any extent entries we find. - */ - while (entry->bitmap || found_bitmap || - (!entry->bitmap && entry->bytes < min_bytes)) { - struct rb_node *node = rb_next(&entry->offset_index); - - if (entry->bitmap && entry->bytes > bytes + empty_size) { - ret = btrfs_bitmap_cluster(block_group, entry, cluster, - offset, bytes, min_bytes); - if (!ret) - goto got_it; - } - - if (!node) { - ret = -ENOSPC; - goto out; - } - entry = rb_entry(node, struct btrfs_free_space, offset_index); - } - - /* - * We already searched all the extent entries from the passed in offset - * to the end and didn't find enough space for the cluster, and we also - * didn't find any bitmaps that met our criteria, just go ahead and exit - */ - if (found_bitmap) { - ret = -ENOSPC; - goto out; - } - - cluster->points_to_bitmap = false; - window_start = entry->offset; - window_free = entry->bytes; - last = entry; - max_extent = entry->bytes; - - while (1) { - /* out window is just right, lets fill it */ - if (window_free >= min_bytes) - break; - - node = rb_next(&last->offset_index); - if (!node) { - if (found_bitmap) - goto again; - ret = -ENOSPC; - goto out; - } - next = rb_entry(node, struct btrfs_free_space, offset_index); - - /* - * we found a bitmap, so if this search doesn't result in a - * cluster, we know to go and search again for the bitmaps and - * start looking for space there - */ - if (next->bitmap) { - if (!found_bitmap) - offset = next->offset; - found_bitmap = true; - last = next; - continue; - } - - /* - * we haven't filled the empty size and the window is - * very large. reset and try again - */ - if (next->offset - (last->offset + last->bytes) > 128 * 1024 || - next->offset - window_start > (bytes + empty_size) * 2) { - entry = next; - window_start = entry->offset; - window_free = entry->bytes; - last = entry; - max_extent = entry->bytes; - } else { - last = next; - window_free += next->bytes; - if (entry->bytes > max_extent) - max_extent = entry->bytes; - } - } - - cluster->window_start = entry->offset; - - /* - * now we've found our entries, pull them out of the free space - * cache and put them into the cluster rbtree - * - * The cluster includes an rbtree, but only uses the offset index - * of each free space cache entry. - */ - while (1) { - node = rb_next(&entry->offset_index); - if (entry->bitmap && node) { - entry = rb_entry(node, struct btrfs_free_space, - offset_index); - continue; - } else if (entry->bitmap && !node) { - break; - } - - rb_erase(&entry->offset_index, &block_group->free_space_offset); - ret = tree_insert_offset(&cluster->root, entry->offset, - &entry->offset_index, 0); - BUG_ON(ret); - if (!node || entry == last) - break; + ret = setup_cluster_no_bitmap(block_group, cluster, offset, bytes, + min_bytes); + if (ret) + ret = setup_cluster_bitmap(block_group, cluster, offset, + bytes, min_bytes); - entry = rb_entry(node, struct btrfs_free_space, offset_index); + if (!ret) { + atomic_inc(&block_group->count); + list_add_tail(&cluster->block_group_list, + &block_group->cluster_list); + cluster->block_group = block_group; } - - cluster->max_size = max_extent; -got_it: - ret = 0; - atomic_inc(&block_group->count); - list_add_tail(&cluster->block_group_list, &block_group->cluster_list); - cluster->block_group = block_group; out: spin_unlock(&cluster->lock); spin_unlock(&block_group->tree_lock); @@ -2173,7 +2174,6 @@ void btrfs_init_free_cluster(struct btrfs_free_cluster *cluster) spin_lock_init(&cluster->refill_lock); cluster->root = RB_ROOT; cluster->max_size = 0; - cluster->points_to_bitmap = false; INIT_LIST_HEAD(&cluster->block_group_list); cluster->block_group = NULL; } -- cgit From 98bc3149fad639c8f50c7110b961a2a2fe085eed Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Tue, 22 Mar 2011 11:00:46 -0400 Subject: Btrfs: don't allocate dip->csums when doing writes When doing direct writes we store the checksums in the ordered sum stuff in the ordered extent for writing them when the write completes, so we don't even use the dip->csums array. So if we're writing, don't bother allocating dip->csums since we won't use it anyway. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/inode.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index e010000d4bc9..570cd44fe91b 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -5944,6 +5944,7 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip, int nr_pages = 0; u32 *csums = dip->csums; int ret = 0; + int write = rw & REQ_WRITE; bio = btrfs_dio_bio_alloc(orig_bio->bi_bdev, start_sector, GFP_NOFS); if (!bio) @@ -5980,7 +5981,8 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip, goto out_err; } - if (!skip_sum) + /* Write's use the ordered csums */ + if (!write && !skip_sum) csums = csums + nr_pages; start_sector += submit_len >> 9; file_offset += submit_len; @@ -6048,7 +6050,8 @@ static void btrfs_submit_direct(int rw, struct bio *bio, struct inode *inode, } dip->csums = NULL; - if (!skip_sum) { + /* Write's use the ordered csum stuff, so we don't need dip->csums */ + if (!write && !skip_sum) { dip->csums = kmalloc(sizeof(u32) * bio->bi_vcnt, GFP_NOFS); if (!dip->csums) { kfree(dip); -- cgit From c0da7aa1a2d8fcafe271a7077599253c8ed94bb2 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Tue, 22 Mar 2011 11:05:07 -0400 Subject: Btrfs: mark the bio with an error if we have a failure in dio I noticed that dio_end_io calls the appropriate endio function with an error, but the endio functions don't actually do anything with that error, they assume that if there was an error then the bio will not be uptodate. So if we had checksum failures we would never pass back EIO. So if there is an error in our endio functions make sure to clear the uptodate flag on the bio. Thanks, Signed-off-by: Josef Bacik --- fs/btrfs/inode.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'fs') diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 570cd44fe91b..e9813bd7d556 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -5744,6 +5744,10 @@ static void btrfs_endio_direct_read(struct bio *bio, int err) kfree(dip->csums); kfree(dip); + + /* If we had a csum failure make sure to clear the uptodate flag */ + if (err) + clear_bit(BIO_UPTODATE, &bio->bi_flags); dio_end_io(bio, err); } @@ -5845,6 +5849,10 @@ out_done: kfree(dip->csums); kfree(dip); + + /* If we had an error make sure to clear the uptodate flag */ + if (err) + clear_bit(BIO_UPTODATE, &bio->bi_flags); dio_end_io(bio, err); } -- cgit From c03e3126e4f9535f4983d727f036440255c43c82 Mon Sep 17 00:00:00 2001 From: Rakib Mullick Date: Fri, 25 Mar 2011 01:57:01 -0700 Subject: codafs: fix build break when CONFIG_PROC_SYSCTL=n Commit 0bc825d240ab ("codafs: fix compile warning when CONFIG_SYSCTL=n") introduces build breakage, when CONFIG_PROC_SYSCTL=n and CONFIG_CODA_FS=y: fs/built-in.o: In function `init_coda': psdev.c:(.init.text+0xc02): undefined reference to `coda_sysctl_init' psdev.c:(.init.text+0xc7c): undefined reference to `coda_sysctl_clean' fs/built-in.o: In function `exit_coda': psdev.c:(.exit.text+0xa9): undefined reference to `coda_sysctl_clean' make: *** [.tmp_vmlinux1] Error 1 Signed-off-by: Rakib Mullick Reported-by: Ingo Molnar Acked-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/coda/sysctl.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'fs') diff --git a/fs/coda/sysctl.c b/fs/coda/sysctl.c index 06d27a41807f..af56ad56a89a 100644 --- a/fs/coda/sysctl.c +++ b/fs/coda/sysctl.c @@ -61,4 +61,13 @@ void coda_sysctl_clean(void) fs_table_header = NULL; } } + +#else +void coda_sysctl_init(void) +{ +} + +void coda_sysctl_clean(void) +{ +} #endif -- cgit From 4d65c520fb4abed970069d18c119cfe85624f46d Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Fri, 25 Mar 2011 14:15:11 -0400 Subject: NFS: Fix a hang in the writeback path Now that the inode scalability patches have been merged, it is no longer safe to call igrab() under the inode->i_lock. Now that we no longer call nfs_clear_request() until the nfs_page is being freed, we know that we are always holding a reference to the nfs_open_context, which again holds a reference to the path, and so the inode cannot be freed until the last nfs_page has been removed from the radix tree and freed. We can therefore skip the igrab()/iput() altogether. Signed-off-by: Trond Myklebust --- fs/nfs/pagelist.c | 4 ++-- fs/nfs/write.c | 13 +++---------- 2 files changed, 5 insertions(+), 12 deletions(-) (limited to 'fs') diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index 87a593c2b055..c80add6e2213 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c @@ -135,14 +135,14 @@ void nfs_clear_page_tag_locked(struct nfs_page *req) nfs_unlock_request(req); } -/** +/* * nfs_clear_request - Free up all resources allocated to the request * @req: * * Release page and open context resources associated with a read/write * request after it has completed. */ -void nfs_clear_request(struct nfs_page *req) +static void nfs_clear_request(struct nfs_page *req) { struct page *page = req->wb_page; struct nfs_open_context *ctx = req->wb_context; diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 85d75254328e..af0c6279a4a7 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -389,11 +389,8 @@ static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req) spin_lock(&inode->i_lock); error = radix_tree_insert(&nfsi->nfs_page_tree, req->wb_index, req); BUG_ON(error); - if (!nfsi->npages) { - igrab(inode); - if (nfs_have_delegation(inode, FMODE_WRITE)) - nfsi->change_attr++; - } + if (!nfsi->npages && nfs_have_delegation(inode, FMODE_WRITE)) + nfsi->change_attr++; set_bit(PG_MAPPED, &req->wb_flags); SetPagePrivate(req->wb_page); set_page_private(req->wb_page, (unsigned long)req); @@ -423,11 +420,7 @@ static void nfs_inode_remove_request(struct nfs_page *req) clear_bit(PG_MAPPED, &req->wb_flags); radix_tree_delete(&nfsi->nfs_page_tree, req->wb_index); nfsi->npages--; - if (!nfsi->npages) { - spin_unlock(&inode->i_lock); - iput(inode); - } else - spin_unlock(&inode->i_lock); + spin_unlock(&inode->i_lock); nfs_release_request(req); } -- cgit From a0e7e3cf7932d6c77de0dc79a40dbaeb8060b544 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Sat, 26 Mar 2011 02:24:35 -0400 Subject: NFS: Don't leak RPC clients in NFSv4 secinfo negotiation Signed-off-by: Trond Myklebust --- fs/nfs/namespace.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index ad92bf731ff5..9166fcb66da2 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c @@ -192,13 +192,15 @@ static rpc_authflavor_t nfs_lookup_with_sec(struct nfs_server *server, struct de auth = rpcauth_create(flavor, clone); if (!auth) { flavor = -EIO; - goto out; + goto out_shutdown; } err = server->nfs_client->rpc_ops->lookup(clone, parent->d_inode, &path->dentry->d_name, fh, fattr); if (err < 0) flavor = err; +out_shutdown: + rpc_shutdown_client(clone); out: return flavor; } -- cgit From 76597cd31470fa130784c78fadb4dab2e624a723 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 27 Mar 2011 19:09:29 -0700 Subject: proc: fix oops on invalid /proc//maps access MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When m_start returns an error, the seq_file logic will still call m_stop with that error entry, so we'd better make sure that we check it before using it as a vma. Introduced by commit ec6fd8a4355c ("report errors in /proc/*/*map* sanely"), which replaced NULL with various ERR_PTR() cases. (On ia64, you happen to get a unaligned fault instead of a page fault, since the address used is generally some random error code like -EPERM) Reported-by: Anca Emanuel Reported-by: Tony Luck Cc: Al Viro Cc: Américo Wang Cc: Stephen Wilson Signed-off-by: Linus Torvalds --- fs/proc/task_mmu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 7c708a418acc..2e7addfd9803 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -182,7 +182,8 @@ static void m_stop(struct seq_file *m, void *v) struct proc_maps_private *priv = m->private; struct vm_area_struct *vma = v; - vma_stop(priv, vma); + if (!IS_ERR(vma)) + vma_stop(priv, vma); if (priv->task) put_task_struct(priv->task); } -- cgit From b6d0ad686da95fa85ce0c583ec35017bf1583563 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 26 Mar 2011 13:27:47 -0700 Subject: fs: fix inode.c kernel-doc warning Fix inode.c kernel-doc fatal error: 2 comment sections have the same name: Error(fs/inode.c:1171): duplicate section name 'Note' Signed-off-by: Randy Dunlap Signed-off-by: Linus Torvalds --- fs/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/inode.c b/fs/inode.c index 05a1f75ae791..5f4e11aaeb5c 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -1167,7 +1167,7 @@ EXPORT_SYMBOL(igrab); * Note: I_NEW is not waited upon so you have to be very careful what you do * with the returned inode. You probably should be using ilookup5() instead. * - * Note: @test is called with the inode_hash_lock held, so can't sleep. + * Note2: @test is called with the inode_hash_lock held, so can't sleep. */ struct inode *ilookup5_nowait(struct super_block *sb, unsigned long hashval, int (*test)(struct inode *, void *), void *data) -- cgit From bd4f0fe8bb7c73c738e1e11bc90d6e2cf9c6e20e Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Wed, 23 Feb 2011 00:14:19 -0600 Subject: eCryptfs: Remove unnecessary grow_file() function When creating a new eCryptfs file, the crypto metadata is written out and then the lower file was being "grown" with 4 kB of encrypted zeroes. I suspect that growing the encrypted file was to prevent an information leak that the unencrypted file was empty. However, the unencrypted file size is stored, in plaintext, in the metadata so growing the file is unnecessary. Signed-off-by: Tyler Hicks --- fs/ecryptfs/crypto.c | 1 + fs/ecryptfs/inode.c | 23 ----------------------- 2 files changed, 1 insertion(+), 23 deletions(-) (limited to 'fs') diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index bfd8b680e648..98a2a314ea68 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -1389,6 +1389,7 @@ int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry) rc = -ENOMEM; goto out; } + /* Zeroed page ensures the in-header unencrypted i_size is set to 0 */ rc = ecryptfs_write_headers_virt(virt, virt_len, &size, crypt_stat, ecryptfs_dentry); if (unlikely(rc)) { diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index b592938a84bc..8fa365acb789 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -142,26 +142,6 @@ out: return rc; } -/** - * grow_file - * @ecryptfs_dentry: the eCryptfs dentry - * - * This is the code which will grow the file to its correct size. - */ -static int grow_file(struct dentry *ecryptfs_dentry) -{ - struct inode *ecryptfs_inode = ecryptfs_dentry->d_inode; - char zero_virt[] = { 0x00 }; - int rc = 0; - - rc = ecryptfs_write(ecryptfs_inode, zero_virt, 0, 1); - i_size_write(ecryptfs_inode, 0); - rc = ecryptfs_write_inode_size_to_metadata(ecryptfs_inode); - ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat.flags |= - ECRYPTFS_NEW_FILE; - return rc; -} - /** * ecryptfs_initialize_file * @@ -202,9 +182,6 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) printk(KERN_ERR "Error writing headers; rc = [%d]\n", rc); goto out; } - rc = grow_file(ecryptfs_dentry); - if (rc) - printk(KERN_ERR "Error growing file; rc = [%d]\n", rc); out: return rc; } -- cgit From fed8859b3ab94274c986cbdf7d27130e0545f02c Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Wed, 23 Feb 2011 00:54:20 -0600 Subject: eCryptfs: Remove ECRYPTFS_NEW_FILE crypt stat flag Now that grow_file() is not called in the ecryptfs_create() path, the ECRYPTFS_NEW_FILE flag is no longer needed. It helped ecryptfs_readpage() know not to decrypt zeroes that were read from the lower file in the grow_file() path. Signed-off-by: Tyler Hicks --- fs/ecryptfs/ecryptfs_kernel.h | 25 ++++++++++++------------- fs/ecryptfs/inode.c | 1 - fs/ecryptfs/mmap.c | 15 ++------------- 3 files changed, 14 insertions(+), 27 deletions(-) (limited to 'fs') diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index e00753496e3e..427478e29760 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h @@ -257,19 +257,18 @@ struct ecryptfs_filename { struct ecryptfs_crypt_stat { #define ECRYPTFS_STRUCT_INITIALIZED 0x00000001 #define ECRYPTFS_POLICY_APPLIED 0x00000002 -#define ECRYPTFS_NEW_FILE 0x00000004 -#define ECRYPTFS_ENCRYPTED 0x00000008 -#define ECRYPTFS_SECURITY_WARNING 0x00000010 -#define ECRYPTFS_ENABLE_HMAC 0x00000020 -#define ECRYPTFS_ENCRYPT_IV_PAGES 0x00000040 -#define ECRYPTFS_KEY_VALID 0x00000080 -#define ECRYPTFS_METADATA_IN_XATTR 0x00000100 -#define ECRYPTFS_VIEW_AS_ENCRYPTED 0x00000200 -#define ECRYPTFS_KEY_SET 0x00000400 -#define ECRYPTFS_ENCRYPT_FILENAMES 0x00000800 -#define ECRYPTFS_ENCFN_USE_MOUNT_FNEK 0x00001000 -#define ECRYPTFS_ENCFN_USE_FEK 0x00002000 -#define ECRYPTFS_UNLINK_SIGS 0x00004000 +#define ECRYPTFS_ENCRYPTED 0x00000004 +#define ECRYPTFS_SECURITY_WARNING 0x00000008 +#define ECRYPTFS_ENABLE_HMAC 0x00000010 +#define ECRYPTFS_ENCRYPT_IV_PAGES 0x00000020 +#define ECRYPTFS_KEY_VALID 0x00000040 +#define ECRYPTFS_METADATA_IN_XATTR 0x00000080 +#define ECRYPTFS_VIEW_AS_ENCRYPTED 0x00000100 +#define ECRYPTFS_KEY_SET 0x00000200 +#define ECRYPTFS_ENCRYPT_FILENAMES 0x00000400 +#define ECRYPTFS_ENCFN_USE_MOUNT_FNEK 0x00000800 +#define ECRYPTFS_ENCFN_USE_FEK 0x00001000 +#define ECRYPTFS_UNLINK_SIGS 0x00002000 u32 flags; unsigned int file_version; size_t iv_bytes; diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 8fa365acb789..f99051b7adab 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -161,7 +161,6 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); goto out; } - crypt_stat->flags |= ECRYPTFS_NEW_FILE; ecryptfs_printk(KERN_DEBUG, "Initializing crypto context\n"); rc = ecryptfs_new_file_context(ecryptfs_dentry); if (rc) { diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index cc64fca89f8d..519af27db059 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c @@ -193,11 +193,7 @@ static int ecryptfs_readpage(struct file *file, struct page *page) &ecryptfs_inode_to_private(page->mapping->host)->crypt_stat; int rc = 0; - if (!crypt_stat - || !(crypt_stat->flags & ECRYPTFS_ENCRYPTED) - || (crypt_stat->flags & ECRYPTFS_NEW_FILE)) { - ecryptfs_printk(KERN_DEBUG, - "Passing through unencrypted page\n"); + if (!crypt_stat || !(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { rc = ecryptfs_read_lower_page_segment(page, page->index, 0, PAGE_CACHE_SIZE, page->mapping->host); @@ -295,8 +291,7 @@ static int ecryptfs_write_begin(struct file *file, struct ecryptfs_crypt_stat *crypt_stat = &ecryptfs_inode_to_private(mapping->host)->crypt_stat; - if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED) - || (crypt_stat->flags & ECRYPTFS_NEW_FILE)) { + if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { rc = ecryptfs_read_lower_page_segment( page, index, 0, PAGE_CACHE_SIZE, mapping->host); if (rc) { @@ -487,12 +482,6 @@ static int ecryptfs_write_end(struct file *file, &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; int rc; - if (crypt_stat->flags & ECRYPTFS_NEW_FILE) { - ecryptfs_printk(KERN_DEBUG, "ECRYPTFS_NEW_FILE flag set in " - "crypt_stat at memory location [%p]\n", crypt_stat); - crypt_stat->flags &= ~(ECRYPTFS_NEW_FILE); - } else - ecryptfs_printk(KERN_DEBUG, "Not a new file\n"); ecryptfs_printk(KERN_DEBUG, "Calling fill_zeros_to_end_of_page" "(page w/ index = [0x%.16lx], to = [%d])\n", index, to); if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { -- cgit From 57db4e8d73ef2b5e94a3f412108dff2576670a8a Mon Sep 17 00:00:00 2001 From: Thieu Le Date: Tue, 8 Mar 2011 16:26:03 -0800 Subject: ecryptfs: modify write path to encrypt page in writepage Change the write path to encrypt the data only when the page is written to disk in ecryptfs_writepage. Previously, ecryptfs encrypts the page in ecryptfs_write_end which means that if there are multiple write requests to the same page, ecryptfs ends up re-encrypting that page over and over again. This patch minimizes the number of encryptions needed. Signed-off-by: Thieu Le [tyhicks: Changed NULL .drop_inode sop pointer to generic_drop_inode] Signed-off-by: Tyler Hicks --- fs/ecryptfs/ecryptfs_kernel.h | 1 - fs/ecryptfs/file.c | 9 ++++++++- fs/ecryptfs/main.c | 2 -- fs/ecryptfs/mmap.c | 41 +++++++++++++++++++++++++++-------------- fs/ecryptfs/read_write.c | 12 ++---------- fs/ecryptfs/super.c | 3 +-- 6 files changed, 38 insertions(+), 30 deletions(-) (limited to 'fs') diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index 427478e29760..3ef5b0030231 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h @@ -296,7 +296,6 @@ struct ecryptfs_inode_info { struct inode vfs_inode; struct inode *wii_inode; struct file *lower_file; - struct mutex lower_file_mutex; struct ecryptfs_crypt_stat crypt_stat; }; diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index 7d1050e254f9..cedc913d11ba 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c @@ -273,7 +273,14 @@ static int ecryptfs_release(struct inode *inode, struct file *file) static int ecryptfs_fsync(struct file *file, int datasync) { - return vfs_fsync(ecryptfs_file_to_lower(file), datasync); + int rc = 0; + + rc = generic_file_fsync(file, datasync); + if (rc) + goto out; + rc = vfs_fsync(ecryptfs_file_to_lower(file), datasync); +out: + return rc; } static int ecryptfs_fasync(int fd, struct file *file, int flag) diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index 758323a0f09a..63e412cf0fa1 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -122,7 +122,6 @@ int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry) ecryptfs_inode_to_private(ecryptfs_dentry->d_inode); int rc = 0; - mutex_lock(&inode_info->lower_file_mutex); if (!inode_info->lower_file) { struct dentry *lower_dentry; struct vfsmount *lower_mnt = @@ -138,7 +137,6 @@ int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry) inode_info->lower_file = NULL; } } - mutex_unlock(&inode_info->lower_file_mutex); return rc; } diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index 519af27db059..5e150131eb9d 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c @@ -62,6 +62,18 @@ static int ecryptfs_writepage(struct page *page, struct writeback_control *wbc) { int rc; + /* + * Refuse to write the page out if we are called from reclaim context + * since our writepage() path may potentially allocate memory when + * calling into the lower fs vfs_write() which may in turn invoke + * us again. + */ + if (current->flags & PF_MEMALLOC) { + redirty_page_for_writepage(wbc, page); + rc = 0; + goto out; + } + rc = ecryptfs_encrypt_page(page); if (rc) { ecryptfs_printk(KERN_WARNING, "Error encrypting " @@ -70,8 +82,8 @@ static int ecryptfs_writepage(struct page *page, struct writeback_control *wbc) goto out; } SetPageUptodate(page); - unlock_page(page); out: + unlock_page(page); return rc; } @@ -481,6 +493,7 @@ static int ecryptfs_write_end(struct file *file, struct ecryptfs_crypt_stat *crypt_stat = &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; int rc; + int need_unlock_page = 1; ecryptfs_printk(KERN_DEBUG, "Calling fill_zeros_to_end_of_page" "(page w/ index = [0x%.16lx], to = [%d])\n", index, to); @@ -501,26 +514,26 @@ static int ecryptfs_write_end(struct file *file, "zeros in page with index = [0x%.16lx]\n", index); goto out; } - rc = ecryptfs_encrypt_page(page); - if (rc) { - ecryptfs_printk(KERN_WARNING, "Error encrypting page (upper " - "index [0x%.16lx])\n", index); - goto out; - } + set_page_dirty(page); + unlock_page(page); + need_unlock_page = 0; if (pos + copied > i_size_read(ecryptfs_inode)) { i_size_write(ecryptfs_inode, pos + copied); ecryptfs_printk(KERN_DEBUG, "Expanded file size to " "[0x%.16llx]\n", (unsigned long long)i_size_read(ecryptfs_inode)); + balance_dirty_pages_ratelimited(mapping); + rc = ecryptfs_write_inode_size_to_metadata(ecryptfs_inode); + if (rc) { + printk(KERN_ERR "Error writing inode size to metadata; " + "rc = [%d]\n", rc); + goto out; + } } - rc = ecryptfs_write_inode_size_to_metadata(ecryptfs_inode); - if (rc) - printk(KERN_ERR "Error writing inode size to metadata; " - "rc = [%d]\n", rc); - else - rc = copied; + rc = copied; out: - unlock_page(page); + if (need_unlock_page) + unlock_page(page); page_cache_release(page); return rc; } diff --git a/fs/ecryptfs/read_write.c b/fs/ecryptfs/read_write.c index db184ef15d3d..85d430963116 100644 --- a/fs/ecryptfs/read_write.c +++ b/fs/ecryptfs/read_write.c @@ -44,15 +44,11 @@ int ecryptfs_write_lower(struct inode *ecryptfs_inode, char *data, ssize_t rc; inode_info = ecryptfs_inode_to_private(ecryptfs_inode); - mutex_lock(&inode_info->lower_file_mutex); BUG_ON(!inode_info->lower_file); - inode_info->lower_file->f_pos = offset; fs_save = get_fs(); set_fs(get_ds()); - rc = vfs_write(inode_info->lower_file, data, size, - &inode_info->lower_file->f_pos); + rc = vfs_write(inode_info->lower_file, data, size, &offset); set_fs(fs_save); - mutex_unlock(&inode_info->lower_file_mutex); mark_inode_dirty_sync(ecryptfs_inode); return rc; } @@ -234,15 +230,11 @@ int ecryptfs_read_lower(char *data, loff_t offset, size_t size, mm_segment_t fs_save; ssize_t rc; - mutex_lock(&inode_info->lower_file_mutex); BUG_ON(!inode_info->lower_file); - inode_info->lower_file->f_pos = offset; fs_save = get_fs(); set_fs(get_ds()); - rc = vfs_read(inode_info->lower_file, data, size, - &inode_info->lower_file->f_pos); + rc = vfs_read(inode_info->lower_file, data, size, &offset); set_fs(fs_save); - mutex_unlock(&inode_info->lower_file_mutex); return rc; } diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c index 3042fe123a34..bacc882e1ae4 100644 --- a/fs/ecryptfs/super.c +++ b/fs/ecryptfs/super.c @@ -55,7 +55,6 @@ static struct inode *ecryptfs_alloc_inode(struct super_block *sb) if (unlikely(!inode_info)) goto out; ecryptfs_init_crypt_stat(&inode_info->crypt_stat); - mutex_init(&inode_info->lower_file_mutex); inode_info->lower_file = NULL; inode = &inode_info->vfs_inode; out: @@ -198,7 +197,7 @@ static int ecryptfs_show_options(struct seq_file *m, struct vfsmount *mnt) const struct super_operations ecryptfs_sops = { .alloc_inode = ecryptfs_alloc_inode, .destroy_inode = ecryptfs_destroy_inode, - .drop_inode = generic_delete_inode, + .drop_inode = generic_drop_inode, .statfs = ecryptfs_statfs, .remount_fs = NULL, .evict_inode = ecryptfs_evict_inode, -- cgit From 50f198ae16ac66508d4b8d5a40967a8507ad19ee Mon Sep 17 00:00:00 2001 From: Tyler Hicks Date: Wed, 9 Mar 2011 11:49:13 -0600 Subject: eCryptfs: Unlock page in write_begin error path Unlock the page in error path of ecryptfs_write_begin(). This may happen, for example, if decryption fails while bring the page up-to-date. Cc: Signed-off-by: Tyler Hicks --- fs/ecryptfs/mmap.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'fs') diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index 5e150131eb9d..6a44148c5fb9 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c @@ -381,6 +381,11 @@ static int ecryptfs_write_begin(struct file *file, && (pos != 0)) zero_user(page, 0, PAGE_CACHE_SIZE); out: + if (unlikely(rc)) { + unlock_page(page); + page_cache_release(page); + *pagep = NULL; + } return rc; } -- cgit From 1821df040ac3cd6a57518739f345da6d50ea9d3f Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Thu, 17 Mar 2011 12:48:50 +0100 Subject: eCryptfs: ecryptfs_keyring_auth_tok_for_sig() bug fix The pointer '(*auth_tok_key)' is set to NULL in case request_key() fails, in order to prevent its use by functions calling ecryptfs_keyring_auth_tok_for_sig(). Signed-off-by: Roberto Sassu Cc: Signed-off-by: Tyler Hicks --- fs/ecryptfs/keystore.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs') diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index c1436cff6f2d..4feb78c23651 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c @@ -1563,6 +1563,7 @@ int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key, printk(KERN_ERR "Could not find key with description: [%s]\n", sig); rc = process_request_key_err(PTR_ERR(*auth_tok_key)); + (*auth_tok_key) = NULL; goto out; } (*auth_tok) = ecryptfs_get_key_payload_data(*auth_tok_key); -- cgit From cf35ca69131d5fc8febb74629d173e0731bf49c0 Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Mon, 21 Mar 2011 16:00:51 +0100 Subject: eCryptfs: removed num_global_auth_toks from ecryptfs_mount_crypt_stat This patch removes the 'num_global_auth_toks' field of the ecryptfs_mount_crypt_stat structure, used to count the number of items in the 'global_auth_tok_list' list. This variable is not needed because there are no checks based upon it. Signed-off-by: Roberto Sassu Signed-off-by: Tyler Hicks --- fs/ecryptfs/crypto.c | 1 - fs/ecryptfs/ecryptfs_kernel.h | 1 - fs/ecryptfs/keystore.c | 1 - 3 files changed, 3 deletions(-) (limited to 'fs') diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 98a2a314ea68..d2a70a4561f9 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -266,7 +266,6 @@ void ecryptfs_destroy_mount_crypt_stat( &mount_crypt_stat->global_auth_tok_list, mount_crypt_stat_list) { list_del(&auth_tok->mount_crypt_stat_list); - mount_crypt_stat->num_global_auth_toks--; if (auth_tok->global_auth_tok_key && !(auth_tok->flags & ECRYPTFS_AUTH_TOK_INVALID)) key_put(auth_tok->global_auth_tok_key); diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index 3ef5b0030231..6c6b8261092e 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h @@ -378,7 +378,6 @@ struct ecryptfs_mount_crypt_stat { u32 flags; struct list_head global_auth_tok_list; struct mutex global_auth_tok_list_mutex; - size_t num_global_auth_toks; size_t global_default_cipher_key_size; size_t global_default_fn_cipher_key_bytes; unsigned char global_default_cipher_name[ECRYPTFS_MAX_CIPHER_NAME_SIZE diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index 4feb78c23651..523e51dec66e 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c @@ -2454,7 +2454,6 @@ ecryptfs_add_global_auth_tok(struct ecryptfs_mount_crypt_stat *mount_crypt_stat, mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex); list_add(&new_auth_tok->mount_crypt_stat_list, &mount_crypt_stat->global_auth_tok_list); - mount_crypt_stat->num_global_auth_toks++; mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex); out: return rc; -- cgit From 7762e230fd31fcc1abc03ba32ee957fadc8eafb4 Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Mon, 21 Mar 2011 16:00:52 +0100 Subject: eCryptfs: modified size of keysig in the ecryptfs_key_sig structure The size of the 'keysig' array is incremented of one byte in order to make room for the NULL character. The 'keysig' variable is used, in the function ecryptfs_generate_key_packet_set(), to find an authentication token with the given signature and is printed a debug message if it cannot be retrieved. Signed-off-by: Roberto Sassu Signed-off-by: Tyler Hicks --- fs/ecryptfs/ecryptfs_kernel.h | 2 +- fs/ecryptfs/keystore.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index 6c6b8261092e..40c93fe41cc3 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h @@ -233,7 +233,7 @@ ecryptfs_get_key_payload_data(struct key *key) struct ecryptfs_key_sig { struct list_head crypt_stat_list; - char keysig[ECRYPTFS_SIG_SIZE_HEX]; + char keysig[ECRYPTFS_SIG_SIZE_HEX + 1]; }; struct ecryptfs_filename { diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index 523e51dec66e..bd139dfad8e7 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c @@ -2425,6 +2425,7 @@ int ecryptfs_add_keysig(struct ecryptfs_crypt_stat *crypt_stat, char *sig) return -ENOMEM; } memcpy(new_key_sig->keysig, sig, ECRYPTFS_SIG_SIZE_HEX); + new_key_sig->keysig[ECRYPTFS_SIG_SIZE_HEX] = '\0'; /* Caller must hold keysig_list_mutex */ list_add(&new_key_sig->crypt_stat_list, &crypt_stat->keysig_list); -- cgit From 0e1fc5ef470cc1d157005c437a434868d59fead4 Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Mon, 21 Mar 2011 16:00:53 +0100 Subject: eCryptfs: verify authentication tokens before their use Authentication tokens content may change if another requestor calls the update() method of the corresponding key. The new function ecryptfs_verify_auth_tok_from_key() retrieves the authentication token from the provided key and verifies if it is still valid before being used to encrypt or decrypt an eCryptfs file. Signed-off-by: Roberto Sassu [tyhicks: Minor formatting changes] Signed-off-by: Tyler Hicks --- fs/ecryptfs/ecryptfs_kernel.h | 1 - fs/ecryptfs/keystore.c | 211 ++++++++++++++++++++++++++---------------- fs/ecryptfs/main.c | 4 +- 3 files changed, 135 insertions(+), 81 deletions(-) (limited to 'fs') diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index 40c93fe41cc3..bd3cafd0949d 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h @@ -331,7 +331,6 @@ struct ecryptfs_global_auth_tok { u32 flags; struct list_head mount_crypt_stat_list; struct key *global_auth_tok_key; - struct ecryptfs_auth_tok *global_auth_tok; unsigned char sig[ECRYPTFS_SIG_SIZE_HEX + 1]; }; diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index bd139dfad8e7..3c4039cc18d1 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c @@ -65,6 +65,24 @@ static int process_request_key_err(long err_code) return rc; } +static int process_find_global_auth_tok_for_sig_err(int err_code) +{ + int rc = err_code; + + switch (err_code) { + case -ENOENT: + ecryptfs_printk(KERN_WARNING, "Missing auth tok\n"); + break; + case -EINVAL: + ecryptfs_printk(KERN_WARNING, "Invalid auth tok\n"); + break; + default: + rc = process_request_key_err(err_code); + break; + } + return rc; +} + /** * ecryptfs_parse_packet_length * @data: Pointer to memory containing length at offset @@ -403,27 +421,117 @@ out: return rc; } +/** + * ecryptfs_verify_version + * @version: The version number to confirm + * + * Returns zero on good version; non-zero otherwise + */ +static int ecryptfs_verify_version(u16 version) +{ + int rc = 0; + unsigned char major; + unsigned char minor; + + major = ((version >> 8) & 0xFF); + minor = (version & 0xFF); + if (major != ECRYPTFS_VERSION_MAJOR) { + ecryptfs_printk(KERN_ERR, "Major version number mismatch. " + "Expected [%d]; got [%d]\n", + ECRYPTFS_VERSION_MAJOR, major); + rc = -EINVAL; + goto out; + } + if (minor != ECRYPTFS_VERSION_MINOR) { + ecryptfs_printk(KERN_ERR, "Minor version number mismatch. " + "Expected [%d]; got [%d]\n", + ECRYPTFS_VERSION_MINOR, minor); + rc = -EINVAL; + goto out; + } +out: + return rc; +} + +/** + * ecryptfs_verify_auth_tok_from_key + * @auth_tok_key: key containing the authentication token + * @auth_tok: authentication token + * + * Returns zero on valid auth tok; -EINVAL otherwise + */ +static int +ecryptfs_verify_auth_tok_from_key(struct key *auth_tok_key, + struct ecryptfs_auth_tok **auth_tok) +{ + int rc = 0; + + (*auth_tok) = ecryptfs_get_key_payload_data(auth_tok_key); + if (ecryptfs_verify_version((*auth_tok)->version)) { + printk(KERN_ERR "Data structure version mismatch. Userspace " + "tools must match eCryptfs kernel module with major " + "version [%d] and minor version [%d]\n", + ECRYPTFS_VERSION_MAJOR, ECRYPTFS_VERSION_MINOR); + rc = -EINVAL; + goto out; + } + if ((*auth_tok)->token_type != ECRYPTFS_PASSWORD + && (*auth_tok)->token_type != ECRYPTFS_PRIVATE_KEY) { + printk(KERN_ERR "Invalid auth_tok structure " + "returned from key query\n"); + rc = -EINVAL; + goto out; + } +out: + return rc; +} + static int ecryptfs_find_global_auth_tok_for_sig( - struct ecryptfs_global_auth_tok **global_auth_tok, + struct key **auth_tok_key, + struct ecryptfs_auth_tok **auth_tok, struct ecryptfs_mount_crypt_stat *mount_crypt_stat, char *sig) { struct ecryptfs_global_auth_tok *walker; int rc = 0; - (*global_auth_tok) = NULL; + (*auth_tok_key) = NULL; + (*auth_tok) = NULL; mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex); list_for_each_entry(walker, &mount_crypt_stat->global_auth_tok_list, mount_crypt_stat_list) { - if (memcmp(walker->sig, sig, ECRYPTFS_SIG_SIZE_HEX) == 0) { - rc = key_validate(walker->global_auth_tok_key); - if (!rc) - (*global_auth_tok) = walker; + if (memcmp(walker->sig, sig, ECRYPTFS_SIG_SIZE_HEX)) + continue; + + if (walker->flags & ECRYPTFS_AUTH_TOK_INVALID) { + rc = -EINVAL; goto out; } + + rc = key_validate(walker->global_auth_tok_key); + if (rc) { + if (rc == -EKEYEXPIRED) + goto out; + goto out_invalid_auth_tok; + } + + rc = ecryptfs_verify_auth_tok_from_key( + walker->global_auth_tok_key, auth_tok); + if (rc) + goto out_invalid_auth_tok; + + (*auth_tok_key) = walker->global_auth_tok_key; + key_get(*auth_tok_key); + goto out; } - rc = -EINVAL; + rc = -ENOENT; + goto out; +out_invalid_auth_tok: + printk(KERN_WARNING "Invalidating auth tok with sig = [%s]\n", sig); + walker->flags |= ECRYPTFS_AUTH_TOK_INVALID; + key_put(walker->global_auth_tok_key); + walker->global_auth_tok_key = NULL; out: mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex); return rc; @@ -451,14 +559,11 @@ ecryptfs_find_auth_tok_for_sig( struct ecryptfs_mount_crypt_stat *mount_crypt_stat, char *sig) { - struct ecryptfs_global_auth_tok *global_auth_tok; int rc = 0; - (*auth_tok_key) = NULL; - (*auth_tok) = NULL; - if (ecryptfs_find_global_auth_tok_for_sig(&global_auth_tok, - mount_crypt_stat, sig)) { - + rc = ecryptfs_find_global_auth_tok_for_sig(auth_tok_key, auth_tok, + mount_crypt_stat, sig); + if (rc == -ENOENT) { /* if the flag ECRYPTFS_GLOBAL_MOUNT_AUTH_TOK_ONLY is set in the * mount_crypt_stat structure, we prevent to use auth toks that * are not inserted through the ecryptfs_add_global_auth_tok @@ -470,8 +575,7 @@ ecryptfs_find_auth_tok_for_sig( rc = ecryptfs_keyring_auth_tok_for_sig(auth_tok_key, auth_tok, sig); - } else - (*auth_tok) = global_auth_tok->global_auth_tok; + } return rc; } @@ -1520,38 +1624,6 @@ out: return rc; } -/** - * ecryptfs_verify_version - * @version: The version number to confirm - * - * Returns zero on good version; non-zero otherwise - */ -static int ecryptfs_verify_version(u16 version) -{ - int rc = 0; - unsigned char major; - unsigned char minor; - - major = ((version >> 8) & 0xFF); - minor = (version & 0xFF); - if (major != ECRYPTFS_VERSION_MAJOR) { - ecryptfs_printk(KERN_ERR, "Major version number mismatch. " - "Expected [%d]; got [%d]\n", - ECRYPTFS_VERSION_MAJOR, major); - rc = -EINVAL; - goto out; - } - if (minor != ECRYPTFS_VERSION_MINOR) { - ecryptfs_printk(KERN_ERR, "Minor version number mismatch. " - "Expected [%d]; got [%d]\n", - ECRYPTFS_VERSION_MINOR, minor); - rc = -EINVAL; - goto out; - } -out: - return rc; -} - int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key, struct ecryptfs_auth_tok **auth_tok, char *sig) @@ -1566,29 +1638,12 @@ int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key, (*auth_tok_key) = NULL; goto out; } - (*auth_tok) = ecryptfs_get_key_payload_data(*auth_tok_key); - if (ecryptfs_verify_version((*auth_tok)->version)) { - printk(KERN_ERR - "Data structure version mismatch. " - "Userspace tools must match eCryptfs " - "kernel module with major version [%d] " - "and minor version [%d]\n", - ECRYPTFS_VERSION_MAJOR, - ECRYPTFS_VERSION_MINOR); - rc = -EINVAL; - goto out_release_key; - } - if ((*auth_tok)->token_type != ECRYPTFS_PASSWORD - && (*auth_tok)->token_type != ECRYPTFS_PRIVATE_KEY) { - printk(KERN_ERR "Invalid auth_tok structure " - "returned from key query\n"); - rc = -EINVAL; - goto out_release_key; - } -out_release_key: + + rc = ecryptfs_verify_auth_tok_from_key(*auth_tok_key, auth_tok); if (rc) { key_put(*auth_tok_key); (*auth_tok_key) = NULL; + goto out; } out: return rc; @@ -2325,7 +2380,7 @@ ecryptfs_generate_key_packet_set(char *dest_base, size_t max) { struct ecryptfs_auth_tok *auth_tok; - struct ecryptfs_global_auth_tok *global_auth_tok; + struct key *auth_tok_key = NULL; struct ecryptfs_mount_crypt_stat *mount_crypt_stat = &ecryptfs_superblock_to_private( ecryptfs_dentry->d_sb)->mount_crypt_stat; @@ -2344,21 +2399,16 @@ ecryptfs_generate_key_packet_set(char *dest_base, list_for_each_entry(key_sig, &crypt_stat->keysig_list, crypt_stat_list) { memset(key_rec, 0, sizeof(*key_rec)); - rc = ecryptfs_find_global_auth_tok_for_sig(&global_auth_tok, + rc = ecryptfs_find_global_auth_tok_for_sig(&auth_tok_key, + &auth_tok, mount_crypt_stat, key_sig->keysig); if (rc) { - printk(KERN_ERR "Error attempting to get the global " - "auth_tok; rc = [%d]\n", rc); + printk(KERN_WARNING "Unable to retrieve auth tok with " + "sig = [%s]\n", key_sig->keysig); + rc = process_find_global_auth_tok_for_sig_err(rc); goto out_free; } - if (global_auth_tok->flags & ECRYPTFS_AUTH_TOK_INVALID) { - printk(KERN_WARNING - "Skipping invalid auth tok with sig = [%s]\n", - global_auth_tok->sig); - continue; - } - auth_tok = global_auth_tok->global_auth_tok; if (auth_tok->token_type == ECRYPTFS_PASSWORD) { rc = write_tag_3_packet((dest_base + (*len)), &max, auth_tok, @@ -2396,6 +2446,8 @@ ecryptfs_generate_key_packet_set(char *dest_base, rc = -EINVAL; goto out_free; } + key_put(auth_tok_key); + auth_tok_key = NULL; } if (likely(max > 0)) { dest_base[(*len)] = 0x00; @@ -2408,6 +2460,9 @@ out_free: out: if (rc) (*len) = 0; + if (auth_tok_key) + key_put(auth_tok_key); + mutex_unlock(&crypt_stat->keysig_list_mutex); return rc; } diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index 63e412cf0fa1..520d05f5ad01 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -239,14 +239,14 @@ static int ecryptfs_init_global_auth_toks( struct ecryptfs_mount_crypt_stat *mount_crypt_stat) { struct ecryptfs_global_auth_tok *global_auth_tok; + struct ecryptfs_auth_tok *auth_tok; int rc = 0; list_for_each_entry(global_auth_tok, &mount_crypt_stat->global_auth_tok_list, mount_crypt_stat_list) { rc = ecryptfs_keyring_auth_tok_for_sig( - &global_auth_tok->global_auth_tok_key, - &global_auth_tok->global_auth_tok, + &global_auth_tok->global_auth_tok_key, &auth_tok, global_auth_tok->sig); if (rc) { printk(KERN_ERR "Could not find valid key in user " -- cgit From 950983fc04e02232e0d25717903461578a755ebb Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Mon, 21 Mar 2011 16:00:54 +0100 Subject: eCryptfs: move ecryptfs_find_auth_tok_for_sig() call before mutex_lock The ecryptfs_find_auth_tok_for_sig() call is moved before the mutex_lock(s->tfm_mutex) instruction in order to avoid possible deadlocks that may occur by holding the lock on the two semaphores 'key->sem' and 's->tfm_mutex' in reverse order. Signed-off-by: Roberto Sassu Signed-off-by: Tyler Hicks --- fs/ecryptfs/keystore.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'fs') diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index 3c4039cc18d1..d95dd505433e 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c @@ -635,6 +635,16 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes, } s->desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; (*packet_size) = 0; + rc = ecryptfs_find_auth_tok_for_sig( + &auth_tok_key, + &s->auth_tok, mount_crypt_stat, + mount_crypt_stat->global_default_fnek_sig); + if (rc) { + printk(KERN_ERR "%s: Error attempting to find auth tok for " + "fnek sig [%s]; rc = [%d]\n", __func__, + mount_crypt_stat->global_default_fnek_sig, rc); + goto out; + } rc = ecryptfs_get_tfm_and_mutex_for_cipher_name( &s->desc.tfm, &s->tfm_mutex, mount_crypt_stat->global_default_fn_cipher_name); @@ -720,16 +730,6 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes, goto out_free_unlock; } dest[s->i++] = s->cipher_code; - rc = ecryptfs_find_auth_tok_for_sig( - &auth_tok_key, - &s->auth_tok, mount_crypt_stat, - mount_crypt_stat->global_default_fnek_sig); - if (rc) { - printk(KERN_ERR "%s: Error attempting to find auth tok for " - "fnek sig [%s]; rc = [%d]\n", __func__, - mount_crypt_stat->global_default_fnek_sig, rc); - goto out_free_unlock; - } /* TODO: Support other key modules than passphrase for * filename encryption */ if (s->auth_tok->token_type != ECRYPTFS_PASSWORD) { @@ -983,6 +983,15 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size, __func__, s->cipher_code); goto out; } + rc = ecryptfs_find_auth_tok_for_sig(&auth_tok_key, + &s->auth_tok, mount_crypt_stat, + s->fnek_sig_hex); + if (rc) { + printk(KERN_ERR "%s: Error attempting to find auth tok for " + "fnek sig [%s]; rc = [%d]\n", __func__, s->fnek_sig_hex, + rc); + goto out; + } rc = ecryptfs_get_tfm_and_mutex_for_cipher_name(&s->desc.tfm, &s->tfm_mutex, s->cipher_string); @@ -1029,15 +1038,6 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size, * >= ECRYPTFS_MAX_IV_BYTES. */ memset(s->iv, 0, ECRYPTFS_MAX_IV_BYTES); s->desc.info = s->iv; - rc = ecryptfs_find_auth_tok_for_sig(&auth_tok_key, - &s->auth_tok, mount_crypt_stat, - s->fnek_sig_hex); - if (rc) { - printk(KERN_ERR "%s: Error attempting to find auth tok for " - "fnek sig [%s]; rc = [%d]\n", __func__, s->fnek_sig_hex, - rc); - goto out_free_unlock; - } /* TODO: Support other key modules than passphrase for * filename encryption */ if (s->auth_tok->token_type != ECRYPTFS_PASSWORD) { -- cgit From b5695d04634fa4ccca7dcbc05bb4a66522f02e0b Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Mon, 21 Mar 2011 16:00:55 +0100 Subject: eCryptfs: write lock requested keys A requested key is write locked in order to prevent modifications on the authentication token while it is being used. Signed-off-by: Roberto Sassu Signed-off-by: Tyler Hicks --- fs/ecryptfs/keystore.c | 26 ++++++++++++++++++++------ fs/ecryptfs/main.c | 4 +++- 2 files changed, 23 insertions(+), 7 deletions(-) (limited to 'fs') diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index d95dd505433e..03e609c45012 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c @@ -516,10 +516,11 @@ ecryptfs_find_global_auth_tok_for_sig( goto out_invalid_auth_tok; } + down_write(&(walker->global_auth_tok_key->sem)); rc = ecryptfs_verify_auth_tok_from_key( walker->global_auth_tok_key, auth_tok); if (rc) - goto out_invalid_auth_tok; + goto out_invalid_auth_tok_unlock; (*auth_tok_key) = walker->global_auth_tok_key; key_get(*auth_tok_key); @@ -527,6 +528,8 @@ ecryptfs_find_global_auth_tok_for_sig( } rc = -ENOENT; goto out; +out_invalid_auth_tok_unlock: + up_write(&(walker->global_auth_tok_key->sem)); out_invalid_auth_tok: printk(KERN_WARNING "Invalidating auth tok with sig = [%s]\n", sig); walker->flags |= ECRYPTFS_AUTH_TOK_INVALID; @@ -869,8 +872,10 @@ out_free_unlock: out_unlock: mutex_unlock(s->tfm_mutex); out: - if (auth_tok_key) + if (auth_tok_key) { + up_write(&(auth_tok_key->sem)); key_put(auth_tok_key); + } kfree(s); return rc; } @@ -1106,8 +1111,10 @@ out: (*filename_size) = 0; (*filename) = NULL; } - if (auth_tok_key) + if (auth_tok_key) { + up_write(&(auth_tok_key->sem)); key_put(auth_tok_key); + } kfree(s); return rc; } @@ -1638,9 +1645,10 @@ int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key, (*auth_tok_key) = NULL; goto out; } - + down_write(&(*auth_tok_key)->sem); rc = ecryptfs_verify_auth_tok_from_key(*auth_tok_key, auth_tok); if (rc) { + up_write(&(*auth_tok_key)->sem); key_put(*auth_tok_key); (*auth_tok_key) = NULL; goto out; @@ -1865,6 +1873,7 @@ int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat, find_next_matching_auth_tok: found_auth_tok = 0; if (auth_tok_key) { + up_write(&(auth_tok_key->sem)); key_put(auth_tok_key); auth_tok_key = NULL; } @@ -1951,8 +1960,10 @@ found_matching_auth_tok: out_wipe_list: wipe_auth_tok_list(&auth_tok_list); out: - if (auth_tok_key) + if (auth_tok_key) { + up_write(&(auth_tok_key->sem)); key_put(auth_tok_key); + } return rc; } @@ -2446,6 +2457,7 @@ ecryptfs_generate_key_packet_set(char *dest_base, rc = -EINVAL; goto out_free; } + up_write(&(auth_tok_key->sem)); key_put(auth_tok_key); auth_tok_key = NULL; } @@ -2460,8 +2472,10 @@ out_free: out: if (rc) (*len) = 0; - if (auth_tok_key) + if (auth_tok_key) { + up_write(&(auth_tok_key->sem)); key_put(auth_tok_key); + } mutex_unlock(&crypt_stat->keysig_list_mutex); return rc; diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index 520d05f5ad01..c27c0ecf90bc 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -254,8 +254,10 @@ static int ecryptfs_init_global_auth_toks( "option: [%s]\n", global_auth_tok->sig); global_auth_tok->flags |= ECRYPTFS_AUTH_TOK_INVALID; goto out; - } else + } else { global_auth_tok->flags &= ~ECRYPTFS_AUTH_TOK_INVALID; + up_write(&(global_auth_tok->global_auth_tok_key)->sem); + } } out: return rc; -- cgit From 240f62c8756df285da11469259b3900f32883168 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Wed, 23 Mar 2011 14:54:42 -0400 Subject: Btrfs: use RCU instead of a spinlock to protect the root node The pointer to the extent buffer for the root of each tree is protected by a spinlock so that we can safely read the pointer and take a reference on the extent buffer. But now that the extent buffers are freed via RCU, we can safely use rcu_read_lock instead. Signed-off-by: Chris Mason --- fs/btrfs/ctree.c | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) (limited to 'fs') diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 73e53009e126..8680110f0a5a 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -147,10 +147,11 @@ noinline void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p) struct extent_buffer *btrfs_root_node(struct btrfs_root *root) { struct extent_buffer *eb; - spin_lock(&root->node_lock); - eb = root->node; + + rcu_read_lock(); + eb = rcu_dereference(root->node); extent_buffer_get(eb); - spin_unlock(&root->node_lock); + rcu_read_unlock(); return eb; } @@ -165,14 +166,8 @@ struct extent_buffer *btrfs_lock_root_node(struct btrfs_root *root) while (1) { eb = btrfs_root_node(root); btrfs_tree_lock(eb); - - spin_lock(&root->node_lock); - if (eb == root->node) { - spin_unlock(&root->node_lock); + if (eb == root->node) break; - } - spin_unlock(&root->node_lock); - btrfs_tree_unlock(eb); free_extent_buffer(eb); } @@ -458,10 +453,8 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans, else parent_start = 0; - spin_lock(&root->node_lock); - root->node = cow; extent_buffer_get(cow); - spin_unlock(&root->node_lock); + rcu_assign_pointer(root->node, cow); btrfs_free_tree_block(trans, root, buf, parent_start, last_ref); @@ -930,9 +923,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, goto enospc; } - spin_lock(&root->node_lock); - root->node = child; - spin_unlock(&root->node_lock); + rcu_assign_pointer(root->node, child); add_root_to_dirty_list(root); btrfs_tree_unlock(child); @@ -2007,10 +1998,8 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans, btrfs_mark_buffer_dirty(c); - spin_lock(&root->node_lock); old = root->node; - root->node = c; - spin_unlock(&root->node_lock); + rcu_assign_pointer(root->node, c); /* the super has an extra ref to root->node */ free_extent_buffer(old); -- cgit From 1abe9b8a138c9988ba8f7bfded6453649a31541f Mon Sep 17 00:00:00 2001 From: liubo Date: Thu, 24 Mar 2011 11:18:59 +0000 Subject: Btrfs: add initial tracepoint support for btrfs Tracepoints can provide insight into why btrfs hits bugs and be greatly helpful for debugging, e.g dd-7822 [000] 2121.641088: btrfs_inode_request: root = 5(FS_TREE), gen = 4, ino = 256, blocks = 8, disk_i_size = 0, last_trans = 8, logged_trans = 0 dd-7822 [000] 2121.641100: btrfs_inode_new: root = 5(FS_TREE), gen = 8, ino = 257, blocks = 0, disk_i_size = 0, last_trans = 0, logged_trans = 0 btrfs-transacti-7804 [001] 2146.935420: btrfs_cow_block: root = 2(EXTENT_TREE), refs = 2, orig_buf = 29368320 (orig_level = 0), cow_buf = 29388800 (cow_level = 0) btrfs-transacti-7804 [001] 2146.935473: btrfs_cow_block: root = 1(ROOT_TREE), refs = 2, orig_buf = 29364224 (orig_level = 0), cow_buf = 29392896 (cow_level = 0) btrfs-transacti-7804 [001] 2146.972221: btrfs_transaction_commit: root = 1(ROOT_TREE), gen = 8 flush-btrfs-2-7821 [001] 2155.824210: btrfs_chunk_alloc: root = 3(CHUNK_TREE), offset = 1103101952, size = 1073741824, num_stripes = 1, sub_stripes = 0, type = DATA flush-btrfs-2-7821 [001] 2155.824241: btrfs_cow_block: root = 2(EXTENT_TREE), refs = 2, orig_buf = 29388800 (orig_level = 0), cow_buf = 29396992 (cow_level = 0) flush-btrfs-2-7821 [001] 2155.824255: btrfs_cow_block: root = 4(DEV_TREE), refs = 2, orig_buf = 29372416 (orig_level = 0), cow_buf = 29401088 (cow_level = 0) flush-btrfs-2-7821 [000] 2155.824329: btrfs_cow_block: root = 3(CHUNK_TREE), refs = 2, orig_buf = 20971520 (orig_level = 0), cow_buf = 20975616 (cow_level = 0) btrfs-endio-wri-7800 [001] 2155.898019: btrfs_cow_block: root = 5(FS_TREE), refs = 2, orig_buf = 29384704 (orig_level = 0), cow_buf = 29405184 (cow_level = 0) btrfs-endio-wri-7800 [001] 2155.898043: btrfs_cow_block: root = 7(CSUM_TREE), refs = 2, orig_buf = 29376512 (orig_level = 0), cow_buf = 29409280 (cow_level = 0) Here is what I have added: 1) ordere_extent: btrfs_ordered_extent_add btrfs_ordered_extent_remove btrfs_ordered_extent_start btrfs_ordered_extent_put These provide critical information to understand how ordered_extents are updated. 2) extent_map: btrfs_get_extent extent_map is used in both read and write cases, and it is useful for tracking how btrfs specific IO is running. 3) writepage: __extent_writepage btrfs_writepage_end_io_hook Pages are cirtical resourses and produce a lot of corner cases during writeback, so it is valuable to know how page is written to disk. 4) inode: btrfs_inode_new btrfs_inode_request btrfs_inode_evict These can show where and when a inode is created, when a inode is evicted. 5) sync: btrfs_sync_file btrfs_sync_fs These show sync arguments. 6) transaction: btrfs_transaction_commit In transaction based filesystem, it will be useful to know the generation and who does commit. 7) back reference and cow: btrfs_delayed_tree_ref btrfs_delayed_data_ref btrfs_delayed_ref_head btrfs_cow_block Btrfs natively supports back references, these tracepoints are helpful on understanding btrfs's COW mechanism. 8) chunk: btrfs_chunk_alloc btrfs_chunk_free Chunk is a link between physical offset and logical offset, and stands for space infomation in btrfs, and these are helpful on tracing space things. 9) reserved_extent: btrfs_reserved_extent_alloc btrfs_reserved_extent_free These can show how btrfs uses its space. Signed-off-by: Liu Bo Signed-off-by: Chris Mason --- fs/btrfs/ctree.c | 3 +++ fs/btrfs/ctree.h | 1 + fs/btrfs/delayed-ref.c | 6 ++++++ fs/btrfs/extent-tree.c | 4 ++++ fs/btrfs/extent_io.c | 2 ++ fs/btrfs/file.c | 1 + fs/btrfs/inode.c | 12 ++++++++++++ fs/btrfs/ordered-data.c | 8 ++++++++ fs/btrfs/super.c | 5 +++++ fs/btrfs/transaction.c | 2 ++ fs/btrfs/volumes.c | 16 +++++----------- fs/btrfs/volumes.h | 11 +++++++++++ 12 files changed, 60 insertions(+), 11 deletions(-) (limited to 'fs') diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 8680110f0a5a..465b5d7d6b48 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -535,6 +535,9 @@ noinline int btrfs_cow_block(struct btrfs_trans_handle *trans, ret = __btrfs_cow_block(trans, root, buf, parent, parent_slot, cow_ret, search_start, 0); + + trace_btrfs_cow_block(root, buf, *cow_ret); + return ret; } diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 0ee679b6c1b7..9d0f59142afa 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include "extent_io.h" #include "extent_map.h" diff --git a/fs/btrfs/delayed-ref.c b/fs/btrfs/delayed-ref.c index e807b143b857..bce28f653899 100644 --- a/fs/btrfs/delayed-ref.c +++ b/fs/btrfs/delayed-ref.c @@ -483,6 +483,8 @@ static noinline int add_delayed_ref_head(struct btrfs_trans_handle *trans, INIT_LIST_HEAD(&head_ref->cluster); mutex_init(&head_ref->mutex); + trace_btrfs_delayed_ref_head(ref, head_ref, action); + existing = tree_insert(&delayed_refs->root, &ref->rb_node); if (existing) { @@ -537,6 +539,8 @@ static noinline int add_delayed_tree_ref(struct btrfs_trans_handle *trans, } full_ref->level = level; + trace_btrfs_delayed_tree_ref(ref, full_ref, action); + existing = tree_insert(&delayed_refs->root, &ref->rb_node); if (existing) { @@ -591,6 +595,8 @@ static noinline int add_delayed_data_ref(struct btrfs_trans_handle *trans, full_ref->objectid = owner; full_ref->offset = offset; + trace_btrfs_delayed_data_ref(ref, full_ref, action); + existing = tree_insert(&delayed_refs->root, &ref->rb_node); if (existing) { diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index cd794c35a636..86ea471d3801 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -5412,6 +5412,8 @@ again: dump_space_info(sinfo, num_bytes, 1); } + trace_btrfs_reserved_extent_alloc(root, ins->objectid, ins->offset); + return ret; } @@ -5433,6 +5435,8 @@ int btrfs_free_reserved_extent(struct btrfs_root *root, u64 start, u64 len) update_reserved_bytes(cache, len, 0, 1); btrfs_put_block_group(cache); + trace_btrfs_reserved_extent_free(root, start, len); + return ret; } diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 1bbd26b4fc5c..77c65a0bea34 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -2192,6 +2192,8 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc, else write_flags = WRITE; + trace___extent_writepage(page, inode, wbc); + WARN_ON(!PageLocked(page)); pg_offset = i_size & (PAGE_CACHE_SIZE - 1); if (page->index > end_index || diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index a85b044cf39e..656bc0a892b1 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -1205,6 +1205,7 @@ int btrfs_sync_file(struct file *file, int datasync) int ret = 0; struct btrfs_trans_handle *trans; + trace_btrfs_sync_file(file, datasync); /* we wait first, since the writeback may change the inode */ root->log_batch++; diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index e9813bd7d556..eaa271484199 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -1787,6 +1787,8 @@ out: static int btrfs_writepage_end_io_hook(struct page *page, u64 start, u64 end, struct extent_state *state, int uptodate) { + trace_btrfs_writepage_end_io_hook(page, start, end, uptodate); + ClearPagePrivate2(page); return btrfs_finish_ordered_io(page->mapping->host, start, end); } @@ -3718,6 +3720,8 @@ void btrfs_evict_inode(struct inode *inode) unsigned long nr; int ret; + trace_btrfs_inode_evict(inode); + truncate_inode_pages(&inode->i_data, 0); if (inode->i_nlink && (btrfs_root_refs(&root->root_item) != 0 || root == root->fs_info->tree_root)) @@ -4510,6 +4514,8 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, return ERR_PTR(-ENOMEM); if (dir) { + trace_btrfs_inode_request(dir); + ret = btrfs_set_inode_index(dir, index); if (ret) { iput(inode); @@ -4584,6 +4590,9 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, insert_inode_hash(inode); inode_tree_add(inode); + + trace_btrfs_inode_new(inode); + return inode; fail: if (dir) @@ -5261,6 +5270,9 @@ insert: } write_unlock(&em_tree->lock); out: + + trace_btrfs_get_extent(root, em); + if (path) btrfs_free_path(path); if (trans) { diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index 083a55477375..a1c940425307 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c @@ -202,6 +202,8 @@ static int __btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, INIT_LIST_HEAD(&entry->list); INIT_LIST_HEAD(&entry->root_extent_list); + trace_btrfs_ordered_extent_add(inode, entry); + spin_lock(&tree->lock); node = tree_insert(&tree->tree, file_offset, &entry->rb_node); @@ -387,6 +389,8 @@ int btrfs_put_ordered_extent(struct btrfs_ordered_extent *entry) struct list_head *cur; struct btrfs_ordered_sum *sum; + trace_btrfs_ordered_extent_put(entry->inode, entry); + if (atomic_dec_and_test(&entry->refs)) { while (!list_empty(&entry->list)) { cur = entry->list.next; @@ -420,6 +424,8 @@ static int __btrfs_remove_ordered_extent(struct inode *inode, spin_lock(&root->fs_info->ordered_extent_lock); list_del_init(&entry->root_extent_list); + trace_btrfs_ordered_extent_remove(inode, entry); + /* * we have no more ordered extents for this inode and * no dirty pages. We can safely remove it from the @@ -585,6 +591,8 @@ void btrfs_start_ordered_extent(struct inode *inode, u64 start = entry->file_offset; u64 end = start + entry->len - 1; + trace_btrfs_ordered_extent_start(inode, entry); + /* * pages in the range can be dirty, clean or writeback. We * start IO on any dirty ones so the wait doesn't stall waiting diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index d39a9895d932..2edfc039f098 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -52,6 +52,9 @@ #include "export.h" #include "compression.h" +#define CREATE_TRACE_POINTS +#include + static const struct super_operations btrfs_super_ops; static const char *btrfs_decode_error(struct btrfs_fs_info *fs_info, int errno, @@ -620,6 +623,8 @@ int btrfs_sync_fs(struct super_block *sb, int wait) struct btrfs_root *root = btrfs_sb(sb); int ret; + trace_btrfs_sync_fs(wait); + if (!wait) { filemap_flush(root->fs_info->btree_inode->i_mapping); return 0; diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 3d73c8d93bbb..5b4bc685bb0e 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -1389,6 +1389,8 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, put_transaction(cur_trans); put_transaction(cur_trans); + trace_btrfs_transaction_commit(root); + mutex_unlock(&root->fs_info->trans_mutex); if (current->journal_info == trans) diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index dd13eb81ee40..8ba3c9ebff93 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -33,17 +33,6 @@ #include "volumes.h" #include "async-thread.h" -struct map_lookup { - u64 type; - int io_align; - int io_width; - int stripe_len; - int sector_size; - int num_stripes; - int sub_stripes; - struct btrfs_bio_stripe stripes[]; -}; - static int init_first_rw_device(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_device *device); @@ -1923,6 +1912,8 @@ static int btrfs_relocate_chunk(struct btrfs_root *root, BUG_ON(ret); + trace_btrfs_chunk_free(root, map, chunk_offset, em->len); + if (map->type & BTRFS_BLOCK_GROUP_SYSTEM) { ret = btrfs_del_sys_chunk(root, chunk_objectid, chunk_offset); BUG_ON(ret); @@ -2650,6 +2641,8 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, *num_bytes = chunk_bytes_by_type(type, calc_size, map->num_stripes, sub_stripes); + trace_btrfs_chunk_alloc(info->chunk_root, map, start, *num_bytes); + em = alloc_extent_map(GFP_NOFS); if (!em) { ret = -ENOMEM; @@ -2758,6 +2751,7 @@ static int __finish_chunk_alloc(struct btrfs_trans_handle *trans, item_size); BUG_ON(ret); } + kfree(chunk); return 0; } diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index 7fb59d45fe8c..7b38d0668b51 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h @@ -145,6 +145,17 @@ struct btrfs_device_info { u64 max_avail; }; +struct map_lookup { + u64 type; + int io_align; + int io_width; + int stripe_len; + int sector_size; + int num_stripes; + int sub_stripes; + struct btrfs_bio_stripe stripes[]; +}; + /* Used to sort the devices by max_avail(descending sort) */ int btrfs_cmp_device_free_bytes(const void *dev_info1, const void *dev_info2); -- cgit From db5b493ac78e46c7b6bad22cd25d8041564cd8ea Mon Sep 17 00:00:00 2001 From: Tsutomu Itoh Date: Wed, 23 Mar 2011 08:14:16 +0000 Subject: Btrfs: cleanup some BUG_ON() This patch changes some BUG_ON() to the error return. (but, most callers still use BUG_ON()) Signed-off-by: Tsutomu Itoh Signed-off-by: Chris Mason --- fs/btrfs/ctree.c | 3 ++- fs/btrfs/disk-io.c | 5 ++++- fs/btrfs/extent-tree.c | 25 ++++++++++++++++++------- fs/btrfs/file-item.c | 3 ++- fs/btrfs/inode-map.c | 3 ++- fs/btrfs/ioctl.c | 5 ++++- fs/btrfs/root-tree.c | 6 ++++-- fs/btrfs/transaction.c | 12 +++++++++--- fs/btrfs/tree-log.c | 15 +++++++++------ 9 files changed, 54 insertions(+), 23 deletions(-) (limited to 'fs') diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 465b5d7d6b48..4edcbe915736 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -3709,7 +3709,8 @@ int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root unsigned long ptr; path = btrfs_alloc_path(); - BUG_ON(!path); + if (!path) + return -ENOMEM; ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size); if (!ret) { leaf = path->nodes[0]; diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 9f31e110b481..00cbb41af660 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1248,7 +1248,10 @@ struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_root *tree_root, root, fs_info, location->objectid); path = btrfs_alloc_path(); - BUG_ON(!path); + if (!path) { + kfree(root); + return ERR_PTR(-ENOMEM); + } ret = btrfs_search_slot(NULL, tree_root, location, path, 0, 0); if (ret == 0) { l = path->nodes[0]; diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 86ea471d3801..a6a8159c5d1e 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -5463,7 +5463,8 @@ static int alloc_reserved_file_extent(struct btrfs_trans_handle *trans, size = sizeof(*extent_item) + btrfs_extent_inline_ref_size(type); path = btrfs_alloc_path(); - BUG_ON(!path); + if (!path) + return -ENOMEM; path->leave_spinning = 1; ret = btrfs_insert_empty_item(trans, fs_info->extent_root, path, @@ -6457,10 +6458,14 @@ int btrfs_drop_subtree(struct btrfs_trans_handle *trans, BUG_ON(root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID); path = btrfs_alloc_path(); - BUG_ON(!path); + if (!path) + return -ENOMEM; wc = kzalloc(sizeof(*wc), GFP_NOFS); - BUG_ON(!wc); + if (!wc) { + btrfs_free_path(path); + return -ENOMEM; + } btrfs_assert_tree_locked(parent); parent_level = btrfs_header_level(parent); @@ -6918,7 +6923,11 @@ static noinline int get_new_locations(struct inode *reloc_inode, } path = btrfs_alloc_path(); - BUG_ON(!path); + if (!path) { + if (exts != *extents) + kfree(exts); + return -ENOMEM; + } cur_pos = extent_key->objectid - offset; last_byte = extent_key->objectid + extent_key->offset; @@ -7442,7 +7451,8 @@ static noinline int replace_extents_in_leaf(struct btrfs_trans_handle *trans, int ret; new_extent = kmalloc(sizeof(*new_extent), GFP_NOFS); - BUG_ON(!new_extent); + if (!new_extent) + return -ENOMEM; ref = btrfs_lookup_leaf_ref(root, leaf->start); BUG_ON(!ref); @@ -7647,7 +7657,8 @@ static noinline int init_reloc_tree(struct btrfs_trans_handle *trans, return 0; root_item = kmalloc(sizeof(*root_item), GFP_NOFS); - BUG_ON(!root_item); + if (!root_item) + return -ENOMEM; ret = btrfs_copy_root(trans, root, root->commit_root, &eb, BTRFS_TREE_RELOC_OBJECTID); @@ -7673,7 +7684,7 @@ static noinline int init_reloc_tree(struct btrfs_trans_handle *trans, reloc_root = btrfs_read_fs_root_no_radix(root->fs_info->tree_root, &root_key); - BUG_ON(!reloc_root); + BUG_ON(IS_ERR(reloc_root)); reloc_root->last_trans = trans->transid; reloc_root->commit_root = NULL; reloc_root->ref_tree = &root->fs_info->reloc_ref_tree; diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index 4f19a3e1bf32..a2134195a85e 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c @@ -48,7 +48,8 @@ int btrfs_insert_file_extent(struct btrfs_trans_handle *trans, struct extent_buffer *leaf; path = btrfs_alloc_path(); - BUG_ON(!path); + if (!path) + return -ENOMEM; file_key.objectid = objectid; file_key.offset = pos; btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_KEY); diff --git a/fs/btrfs/inode-map.c b/fs/btrfs/inode-map.c index c56eb5909172..c05a08f4c411 100644 --- a/fs/btrfs/inode-map.c +++ b/fs/btrfs/inode-map.c @@ -30,7 +30,8 @@ int btrfs_find_highest_inode(struct btrfs_root *root, u64 *objectid) int slot; path = btrfs_alloc_path(); - BUG_ON(!path); + if (!path) + return -ENOMEM; search_key.objectid = BTRFS_LAST_FREE_OBJECTID; search_key.type = -1; diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index ad9b8c0e930b..88d3cb2eaf75 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -2350,12 +2350,15 @@ static noinline long btrfs_ioctl_start_sync(struct file *file, void __user *argp struct btrfs_root *root = BTRFS_I(file->f_dentry->d_inode)->root; struct btrfs_trans_handle *trans; u64 transid; + int ret; trans = btrfs_start_transaction(root, 0); if (IS_ERR(trans)) return PTR_ERR(trans); transid = trans->transid; - btrfs_commit_transaction_async(trans, root, 0); + ret = btrfs_commit_transaction_async(trans, root, 0); + if (ret) + return ret; if (argp) if (copy_to_user(argp, &transid, sizeof(transid))) diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c index 6a1086e83ffc..29b2d7c930eb 100644 --- a/fs/btrfs/root-tree.c +++ b/fs/btrfs/root-tree.c @@ -88,7 +88,8 @@ int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, search_key.offset = (u64)-1; path = btrfs_alloc_path(); - BUG_ON(!path); + if (!path) + return -ENOMEM; ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0); if (ret < 0) goto out; @@ -332,7 +333,8 @@ int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct extent_buffer *leaf; path = btrfs_alloc_path(); - BUG_ON(!path); + if (!path) + return -ENOMEM; ret = btrfs_search_slot(trans, root, key, path, -1, 1); if (ret < 0) goto out; diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 5b4bc685bb0e..ce48eb59d615 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -57,7 +57,8 @@ static noinline int join_transaction(struct btrfs_root *root) if (!cur_trans) { cur_trans = kmem_cache_alloc(btrfs_transaction_cachep, GFP_NOFS); - BUG_ON(!cur_trans); + if (!cur_trans) + return -ENOMEM; root->fs_info->generation++; cur_trans->num_writers = 1; cur_trans->num_joined = 0; @@ -195,7 +196,11 @@ again: wait_current_trans(root); ret = join_transaction(root); - BUG_ON(ret); + if (ret < 0) { + if (type != TRANS_JOIN_NOLOCK) + mutex_unlock(&root->fs_info->trans_mutex); + return ERR_PTR(ret); + } cur_trans = root->fs_info->running_transaction; cur_trans->use_count++; @@ -1156,7 +1161,8 @@ int btrfs_commit_transaction_async(struct btrfs_trans_handle *trans, struct btrfs_transaction *cur_trans; ac = kmalloc(sizeof(*ac), GFP_NOFS); - BUG_ON(!ac); + if (!ac) + return -ENOMEM; INIT_DELAYED_WORK(&ac->work, do_async_commit); ac->root = root; diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 429cfcfadf90..f9425e33e358 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -1828,7 +1828,8 @@ static int walk_log_tree(struct btrfs_trans_handle *trans, int orig_level; path = btrfs_alloc_path(); - BUG_ON(!path); + if (!path) + return -ENOMEM; level = btrfs_header_level(log->node); orig_level = level; @@ -3114,9 +3115,11 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree) .stage = 0, }; - fs_info->log_root_recovering = 1; path = btrfs_alloc_path(); - BUG_ON(!path); + if (!path) + return -ENOMEM; + + fs_info->log_root_recovering = 1; trans = btrfs_start_transaction(fs_info->tree_root, 0); BUG_ON(IS_ERR(trans)); @@ -3124,7 +3127,8 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree) wc.trans = trans; wc.pin = 1; - walk_log_tree(trans, log_root_tree, &wc); + ret = walk_log_tree(trans, log_root_tree, &wc); + BUG_ON(ret); again: key.objectid = BTRFS_TREE_LOG_OBJECTID; @@ -3148,8 +3152,7 @@ again: log = btrfs_read_fs_root_no_radix(log_root_tree, &found_key); - BUG_ON(!log); - + BUG_ON(IS_ERR(log)); tmp_key.objectid = found_key.offset; tmp_key.type = BTRFS_ROOT_ITEM_KEY; -- cgit From 7e75bf3ff3a716d7b21d8fb43bf823115801c1e9 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Fri, 18 Mar 2011 22:56:43 +0000 Subject: btrfs: properly access unaligned checksum buffer On Fri, Mar 18, 2011 at 11:56:53AM -0400, Chris Mason wrote: > Thanks for fielding this one. Does put_unaligned_le32 optimize away on > platforms with efficient access? It would be great if we didn't need > the #ifdef. (quicktest: assembly output is same for put_unaligned_le32 and direct assignment on my x86_64) I was originally following examples in Documentation/unaligned-memory-access.txt. From other code it seems to me that the define CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is intended for larger portions of code. Macros/wrappers for {put,get}_unaligned* are chosen via arch//include/asm/unaligned.h accordingly, therefore it's safe to use put_unaligned_le32 without the ifdef. dave Signed-off-by: Chris Mason --- fs/btrfs/disk-io.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 00cbb41af660..2bdb124333ab 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "compat.h" #include "ctree.h" #include "disk-io.h" @@ -198,7 +199,7 @@ u32 btrfs_csum_data(struct btrfs_root *root, char *data, u32 seed, size_t len) void btrfs_csum_final(u32 crc, char *result) { - *(__le32 *)result = ~cpu_to_le32(crc); + put_unaligned_le32(~crc, result); } /* -- cgit From 97d9a8a420444eb5b5c071d4b3b9c4100a7ae015 Mon Sep 17 00:00:00 2001 From: Tsutomu Itoh Date: Thu, 24 Mar 2011 06:33:21 +0000 Subject: Btrfs: check return value of read_tree_block() This patch is checking return value of read_tree_block(), and if it is NULL, error processing. Signed-off-by: Tsutomu Itoh Signed-off-by: Chris Mason --- fs/btrfs/ctree.c | 3 +++ fs/btrfs/extent-tree.c | 6 ++++++ fs/btrfs/relocation.c | 6 ++++++ 3 files changed, 15 insertions(+) (limited to 'fs') diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 4edcbe915736..84d7ca1fe0ba 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -682,6 +682,8 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, if (!cur) { cur = read_tree_block(root, blocknr, blocksize, gen); + if (!cur) + return -EIO; } else if (!uptodate) { btrfs_read_buffer(cur, gen); } @@ -4087,6 +4089,7 @@ find_next_key: } btrfs_set_path_blocking(path); cur = read_node_slot(root, cur, slot); + BUG_ON(!cur); btrfs_tree_lock(cur); diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index a6a8159c5d1e..5bc658a9d85c 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -6067,6 +6067,8 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans, if (reada && level == 1) reada_walk_down(trans, root, wc, path); next = read_tree_block(root, bytenr, blocksize, generation); + if (!next) + return -EIO; btrfs_tree_lock(next); btrfs_set_lock_blocking(next); } @@ -7937,6 +7939,10 @@ static noinline int relocate_one_extent(struct btrfs_root *extent_root, eb = read_tree_block(found_root, block_start, block_size, 0); + if (!eb) { + ret = -EIO; + goto out; + } btrfs_tree_lock(eb); BUG_ON(level != btrfs_header_level(eb)); diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index c863c8447015..58250e09eb05 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -1724,6 +1724,7 @@ again: eb = read_tree_block(dest, old_bytenr, blocksize, old_ptr_gen); + BUG_ON(!eb); btrfs_tree_lock(eb); if (cow) { ret = btrfs_cow_block(trans, dest, eb, parent, @@ -2513,6 +2514,10 @@ static int do_relocation(struct btrfs_trans_handle *trans, blocksize = btrfs_level_size(root, node->level); generation = btrfs_node_ptr_generation(upper->eb, slot); eb = read_tree_block(root, bytenr, blocksize, generation); + if (!eb) { + err = -EIO; + goto next; + } btrfs_tree_lock(eb); btrfs_set_lock_blocking(eb); @@ -2670,6 +2675,7 @@ static int get_tree_block_key(struct reloc_control *rc, BUG_ON(block->key_ready); eb = read_tree_block(rc->extent_root, block->bytenr, block->key.objectid, block->key.offset); + BUG_ON(!eb); WARN_ON(btrfs_header_level(eb) != block->level); if (block->level == 0) btrfs_item_key_to_cpu(eb, &block->key, 0); -- cgit From fc0e4a314e361af3b13d9320e92c64118f9a3e61 Mon Sep 17 00:00:00 2001 From: Miao Xie Date: Thu, 24 Mar 2011 11:41:21 +0000 Subject: btrfs: use GFP_NOFS instead of GFP_KERNEL In the filesystem context, we must allocate memory by GFP_NOFS, or we may start another filesystem operation and make kswap thread hang up. Signed-off-by: Miao Xie Signed-off-by: Chris Mason --- fs/btrfs/extent-tree.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 5bc658a9d85c..7922f296420d 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -471,7 +471,7 @@ static int cache_block_group(struct btrfs_block_group_cache *cache, if (load_cache_only) return 0; - caching_ctl = kzalloc(sizeof(*caching_ctl), GFP_KERNEL); + caching_ctl = kzalloc(sizeof(*caching_ctl), GFP_NOFS); BUG_ON(!caching_ctl); INIT_LIST_HEAD(&caching_ctl->list); @@ -1743,7 +1743,7 @@ static int remove_extent_backref(struct btrfs_trans_handle *trans, static void btrfs_issue_discard(struct block_device *bdev, u64 start, u64 len) { - blkdev_issue_discard(bdev, start >> 9, len >> 9, GFP_KERNEL, 0); + blkdev_issue_discard(bdev, start >> 9, len >> 9, GFP_NOFS, 0); } static int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr, -- cgit From 75e7cb7fe0c391561bd3af36515be3f3c64a04c6 Mon Sep 17 00:00:00 2001 From: Liu Bo Date: Tue, 22 Mar 2011 10:12:20 +0000 Subject: Btrfs: Per file/directory controls for COW and compression Data compression and data cow are controlled across the entire FS by mount options right now. ioctls are needed to set this on a per file or per directory basis. This has been proposed previously, but VFS developers wanted us to use generic ioctls rather than btrfs-specific ones. According to Chris's comment, there should be just one true compression method(probably LZO) stored in the super. However, before this, we would wait for that one method is stable enough to be adopted into the super. So I list it as a long term goal, and just store it in ram today. After applying this patch, we can use the generic "FS_IOC_SETFLAGS" ioctl to control file and directory's datacow and compression attribute. NOTE: - The compression type is selected by such rules: If we mount btrfs with compress options, ie, zlib/lzo, the type is it. Otherwise, we'll use the default compress type (zlib today). v1->v2: - rebase to the latest btrfs. v2->v3: - fix a problem, i.e. when a file is set NOCOW via mount option, then this NOCOW will be screwed by inheritance from parent directory. Signed-off-by: Liu Bo Signed-off-by: Chris Mason --- fs/btrfs/ctree.h | 1 + fs/btrfs/disk-io.c | 6 ++++++ fs/btrfs/inode.c | 31 ++++++++++++++++++++++++++++--- fs/btrfs/ioctl.c | 41 +++++++++++++++++++++++++++++++++++++---- 4 files changed, 72 insertions(+), 7 deletions(-) (limited to 'fs') diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 9d0f59142afa..8302ecd4197f 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -1282,6 +1282,7 @@ struct btrfs_root { #define BTRFS_INODE_NODUMP (1 << 8) #define BTRFS_INODE_NOATIME (1 << 9) #define BTRFS_INODE_DIRSYNC (1 << 10) +#define BTRFS_INODE_COMPRESS (1 << 11) /* some macros to generate set/get funcs for the struct fields. This * assumes there is a lefoo_to_cpu for every type, so lets make a simple diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 2bdb124333ab..125639ddaffe 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1854,6 +1854,12 @@ struct btrfs_root *open_ctree(struct super_block *sb, btrfs_check_super_valid(fs_info, sb->s_flags & MS_RDONLY); + /* + * In the long term, we'll store the compression type in the super + * block, and it'll be used for per file compression control. + */ + fs_info->compress_type = BTRFS_COMPRESS_ZLIB; + ret = btrfs_parse_options(tree_root, options); if (ret) { err = ret; diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index eaa271484199..7a7a202b82ab 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -384,7 +384,8 @@ again: */ if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NOCOMPRESS) && (btrfs_test_opt(root, COMPRESS) || - (BTRFS_I(inode)->force_compress))) { + (BTRFS_I(inode)->force_compress) || + (BTRFS_I(inode)->flags & BTRFS_INODE_COMPRESS))) { WARN_ON(pages); pages = kzalloc(sizeof(struct page *) * nr_pages, GFP_NOFS); @@ -1256,7 +1257,8 @@ static int run_delalloc_range(struct inode *inode, struct page *locked_page, ret = run_delalloc_nocow(inode, locked_page, start, end, page_started, 0, nr_written); else if (!btrfs_test_opt(root, COMPRESS) && - !(BTRFS_I(inode)->force_compress)) + !(BTRFS_I(inode)->force_compress) && + !(BTRFS_I(inode)->flags & BTRFS_INODE_COMPRESS)) ret = cow_file_range(inode, locked_page, start, end, page_started, nr_written, 1); else @@ -4584,7 +4586,8 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, if ((mode & S_IFREG)) { if (btrfs_test_opt(root, NODATASUM)) BTRFS_I(inode)->flags |= BTRFS_INODE_NODATASUM; - if (btrfs_test_opt(root, NODATACOW)) + if (btrfs_test_opt(root, NODATACOW) || + (BTRFS_I(dir)->flags & BTRFS_INODE_NODATACOW)) BTRFS_I(inode)->flags |= BTRFS_INODE_NODATACOW; } @@ -6866,6 +6869,26 @@ static int btrfs_getattr(struct vfsmount *mnt, return 0; } +/* + * If a file is moved, it will inherit the cow and compression flags of the new + * directory. + */ +static void fixup_inode_flags(struct inode *dir, struct inode *inode) +{ + struct btrfs_inode *b_dir = BTRFS_I(dir); + struct btrfs_inode *b_inode = BTRFS_I(inode); + + if (b_dir->flags & BTRFS_INODE_NODATACOW) + b_inode->flags |= BTRFS_INODE_NODATACOW; + else + b_inode->flags &= ~BTRFS_INODE_NODATACOW; + + if (b_dir->flags & BTRFS_INODE_COMPRESS) + b_inode->flags |= BTRFS_INODE_COMPRESS; + else + b_inode->flags &= ~BTRFS_INODE_COMPRESS; +} + static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry) { @@ -6999,6 +7022,8 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, } } + fixup_inode_flags(new_dir, old_inode); + ret = btrfs_add_link(trans, new_dir, old_inode, new_dentry->d_name.name, new_dentry->d_name.len, 0, index); diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 88d3cb2eaf75..32c980ae0f1c 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -138,6 +138,24 @@ static int btrfs_ioctl_getflags(struct file *file, void __user *arg) return 0; } +static int check_flags(unsigned int flags) +{ + if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \ + FS_NOATIME_FL | FS_NODUMP_FL | \ + FS_SYNC_FL | FS_DIRSYNC_FL | \ + FS_NOCOMP_FL | FS_COMPR_FL | \ + FS_NOCOW_FL | FS_COW_FL)) + return -EOPNOTSUPP; + + if ((flags & FS_NOCOMP_FL) && (flags & FS_COMPR_FL)) + return -EINVAL; + + if ((flags & FS_NOCOW_FL) && (flags & FS_COW_FL)) + return -EINVAL; + + return 0; +} + static int btrfs_ioctl_setflags(struct file *file, void __user *arg) { struct inode *inode = file->f_path.dentry->d_inode; @@ -153,10 +171,9 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg) if (copy_from_user(&flags, arg, sizeof(flags))) return -EFAULT; - if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \ - FS_NOATIME_FL | FS_NODUMP_FL | \ - FS_SYNC_FL | FS_DIRSYNC_FL)) - return -EOPNOTSUPP; + ret = check_flags(flags); + if (ret) + return ret; if (!is_owner_or_cap(inode)) return -EACCES; @@ -201,6 +218,22 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg) else ip->flags &= ~BTRFS_INODE_DIRSYNC; + /* + * The COMPRESS flag can only be changed by users, while the NOCOMPRESS + * flag may be changed automatically if compression code won't make + * things smaller. + */ + if (flags & FS_NOCOMP_FL) { + ip->flags &= ~BTRFS_INODE_COMPRESS; + ip->flags |= BTRFS_INODE_NOCOMPRESS; + } else if (flags & FS_COMPR_FL) { + ip->flags |= BTRFS_INODE_COMPRESS; + ip->flags &= ~BTRFS_INODE_NOCOMPRESS; + } + if (flags & FS_NOCOW_FL) + ip->flags |= BTRFS_INODE_NODATACOW; + else if (flags & FS_COW_FL) + ip->flags &= ~BTRFS_INODE_NODATACOW; trans = btrfs_join_transaction(root, 1); BUG_ON(IS_ERR(trans)); -- cgit From 3ab3564f018b9b265d0258e4a231794bacd5ad85 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Tue, 22 Mar 2011 17:20:26 +0000 Subject: btrfs: return EXDEV when linking from different subvolumes btrfs_link returns EPERM if a cross-subvolume link is attempted. However, in this case I believe EXDEV to be the more appropriate value. >From the link(2) man page: EXDEV oldpath and newpath are not on the same mounted file system. (Linux permits a file system to be mounted at multiple points, but link() does not work across different mount points, even if the same file system is mounted on both.) This matters because an application may have different behaviors based on return codes. Signed-off-by: Mark Fasheh Signed-off-by: Chris Mason --- fs/btrfs/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 7a7a202b82ab..67fd6e9552d3 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -4817,7 +4817,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, /* do not allow sys_link's with other subvols of the same device */ if (root->objectid != BTRFS_I(inode)->root->objectid) - return -EPERM; + return -EXDEV; btrfs_inc_nlink(inode); inode->i_ctime = CURRENT_TIME; -- cgit From b4d00d569a49fcef02195635dbf8d15904b1fb63 Mon Sep 17 00:00:00 2001 From: Li Dongyang Date: Thu, 24 Mar 2011 10:24:25 +0000 Subject: Btrfs: make update_reserved_bytes() public Make the function public as we should update the reserved extents calculations after taking out an extent for trimming. Signed-off-by: Li Dongyang Signed-off-by: Chris Mason --- fs/btrfs/ctree.h | 2 ++ fs/btrfs/extent-tree.c | 16 +++++++--------- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'fs') diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 8302ecd4197f..9e21176cdf57 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -2157,6 +2157,8 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans, u64 root_objectid, u64 owner, u64 offset); int btrfs_free_reserved_extent(struct btrfs_root *root, u64 start, u64 len); +int btrfs_update_reserved_bytes(struct btrfs_block_group_cache *cache, + u64 num_bytes, int reserve, int sinfo); int btrfs_prepare_extent_commit(struct btrfs_trans_handle *trans, struct btrfs_root *root); int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 7922f296420d..0671f5b77eb8 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -36,8 +36,6 @@ static int update_block_group(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 bytenr, u64 num_bytes, int alloc); -static int update_reserved_bytes(struct btrfs_block_group_cache *cache, - u64 num_bytes, int reserve, int sinfo); static int __btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 bytenr, u64 num_bytes, u64 parent, @@ -4233,8 +4231,8 @@ int btrfs_pin_extent(struct btrfs_root *root, * update size of reserved extents. this function may return -EAGAIN * if 'reserve' is true or 'sinfo' is false. */ -static int update_reserved_bytes(struct btrfs_block_group_cache *cache, - u64 num_bytes, int reserve, int sinfo) +int btrfs_update_reserved_bytes(struct btrfs_block_group_cache *cache, + u64 num_bytes, int reserve, int sinfo) { int ret = 0; if (sinfo) { @@ -4714,10 +4712,10 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans, WARN_ON(test_bit(EXTENT_BUFFER_DIRTY, &buf->bflags)); btrfs_add_free_space(cache, buf->start, buf->len); - ret = update_reserved_bytes(cache, buf->len, 0, 0); + ret = btrfs_update_reserved_bytes(cache, buf->len, 0, 0); if (ret == -EAGAIN) { /* block group became read-only */ - update_reserved_bytes(cache, buf->len, 0, 1); + btrfs_update_reserved_bytes(cache, buf->len, 0, 1); goto out; } @@ -5206,7 +5204,7 @@ checks: search_start - offset); BUG_ON(offset > search_start); - ret = update_reserved_bytes(block_group, num_bytes, 1, + ret = btrfs_update_reserved_bytes(block_group, num_bytes, 1, (data & BTRFS_BLOCK_GROUP_DATA)); if (ret == -EAGAIN) { btrfs_add_free_space(block_group, offset, num_bytes); @@ -5432,7 +5430,7 @@ int btrfs_free_reserved_extent(struct btrfs_root *root, u64 start, u64 len) ret = btrfs_discard_extent(root, start, len); btrfs_add_free_space(cache, start, len); - update_reserved_bytes(cache, len, 0, 1); + btrfs_update_reserved_bytes(cache, len, 0, 1); btrfs_put_block_group(cache); trace_btrfs_reserved_extent_free(root, start, len); @@ -5634,7 +5632,7 @@ int btrfs_alloc_logged_file_extent(struct btrfs_trans_handle *trans, put_caching_control(caching_ctl); } - ret = update_reserved_bytes(block_group, ins->offset, 1, 1); + ret = btrfs_update_reserved_bytes(block_group, ins->offset, 1, 1); BUG_ON(ret); btrfs_put_block_group(block_group); ret = alloc_reserved_file_extent(trans, root, 0, root_objectid, -- cgit From fce3bb9a1bd492793170e117c60d5718b7896af4 Mon Sep 17 00:00:00 2001 From: Li Dongyang Date: Thu, 24 Mar 2011 10:24:26 +0000 Subject: Btrfs: make btrfs_map_block() return entire free extent for each device of RAID0/1/10/DUP btrfs_map_block() will only return a single stripe length, but we want the full extent be mapped to each disk when we are trimming the extent, so we add length to btrfs_bio_stripe and fill it if we are mapping for REQ_DISCARD. Signed-off-by: Li Dongyang Signed-off-by: Chris Mason --- fs/btrfs/volumes.c | 150 +++++++++++++++++++++++++++++++++++++++++++++-------- fs/btrfs/volumes.h | 1 + 2 files changed, 129 insertions(+), 22 deletions(-) (limited to 'fs') diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 8ba3c9ebff93..c440c89a470a 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -2956,7 +2956,10 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, struct extent_map_tree *em_tree = &map_tree->map_tree; u64 offset; u64 stripe_offset; + u64 stripe_end_offset; u64 stripe_nr; + u64 stripe_nr_orig; + u64 stripe_nr_end; int stripes_allocated = 8; int stripes_required = 1; int stripe_index; @@ -2965,7 +2968,7 @@ static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, int max_errors = 0; struct btrfs_multi_bio *multi = NULL; - if (multi_ret && !(rw & REQ_WRITE)) + if (multi_ret && !(rw & (REQ_WRITE | REQ_DISCARD))) stripes_allocated = 1; again: if (multi_ret) { @@ -3011,7 +3014,15 @@ again: max_errors = 1; } } - if (multi_ret && (rw & REQ_WRITE) && + if (rw & REQ_DISCARD) { + if (map->type & (BTRFS_BLOCK_GROUP_RAID0 | + BTRFS_BLOCK_GROUP_RAID1 | + BTRFS_BLOCK_GROUP_DUP | + BTRFS_BLOCK_GROUP_RAID10)) { + stripes_required = map->num_stripes; + } + } + if (multi_ret && (rw & (REQ_WRITE | REQ_DISCARD)) && stripes_allocated < stripes_required) { stripes_allocated = map->num_stripes; free_extent_map(em); @@ -3031,12 +3042,15 @@ again: /* stripe_offset is the offset of this block in its stripe*/ stripe_offset = offset - stripe_offset; - if (map->type & (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1 | - BTRFS_BLOCK_GROUP_RAID10 | - BTRFS_BLOCK_GROUP_DUP)) { + if (rw & REQ_DISCARD) + *length = min_t(u64, em->len - offset, *length); + else if (map->type & (BTRFS_BLOCK_GROUP_RAID0 | + BTRFS_BLOCK_GROUP_RAID1 | + BTRFS_BLOCK_GROUP_RAID10 | + BTRFS_BLOCK_GROUP_DUP)) { /* we limit the length of each bio to what fits in a stripe */ *length = min_t(u64, em->len - offset, - map->stripe_len - stripe_offset); + map->stripe_len - stripe_offset); } else { *length = em->len - offset; } @@ -3046,8 +3060,19 @@ again: num_stripes = 1; stripe_index = 0; - if (map->type & BTRFS_BLOCK_GROUP_RAID1) { - if (unplug_page || (rw & REQ_WRITE)) + stripe_nr_orig = stripe_nr; + stripe_nr_end = (offset + *length + map->stripe_len - 1) & + (~(map->stripe_len - 1)); + do_div(stripe_nr_end, map->stripe_len); + stripe_end_offset = stripe_nr_end * map->stripe_len - + (offset + *length); + if (map->type & BTRFS_BLOCK_GROUP_RAID0) { + if (rw & REQ_DISCARD) + num_stripes = min_t(u64, map->num_stripes, + stripe_nr_end - stripe_nr_orig); + stripe_index = do_div(stripe_nr, map->num_stripes); + } else if (map->type & BTRFS_BLOCK_GROUP_RAID1) { + if (unplug_page || (rw & (REQ_WRITE | REQ_DISCARD))) num_stripes = map->num_stripes; else if (mirror_num) stripe_index = mirror_num - 1; @@ -3058,7 +3083,7 @@ again: } } else if (map->type & BTRFS_BLOCK_GROUP_DUP) { - if (rw & REQ_WRITE) + if (rw & (REQ_WRITE | REQ_DISCARD)) num_stripes = map->num_stripes; else if (mirror_num) stripe_index = mirror_num - 1; @@ -3071,6 +3096,10 @@ again: if (unplug_page || (rw & REQ_WRITE)) num_stripes = map->sub_stripes; + else if (rw & REQ_DISCARD) + num_stripes = min_t(u64, map->sub_stripes * + (stripe_nr_end - stripe_nr_orig), + map->num_stripes); else if (mirror_num) stripe_index += mirror_num - 1; else { @@ -3088,24 +3117,101 @@ again: } BUG_ON(stripe_index >= map->num_stripes); - for (i = 0; i < num_stripes; i++) { - if (unplug_page) { - struct btrfs_device *device; - struct backing_dev_info *bdi; - - device = map->stripes[stripe_index].dev; - if (device->bdev) { - bdi = blk_get_backing_dev_info(device->bdev); - if (bdi->unplug_io_fn) - bdi->unplug_io_fn(bdi, unplug_page); - } - } else { + if (rw & REQ_DISCARD) { + for (i = 0; i < num_stripes; i++) { multi->stripes[i].physical = map->stripes[stripe_index].physical + stripe_offset + stripe_nr * map->stripe_len; multi->stripes[i].dev = map->stripes[stripe_index].dev; + + if (map->type & BTRFS_BLOCK_GROUP_RAID0) { + u64 stripes; + int last_stripe = (stripe_nr_end - 1) % + map->num_stripes; + int j; + + for (j = 0; j < map->num_stripes; j++) { + if ((stripe_nr_end - 1 - j) % + map->num_stripes == stripe_index) + break; + } + stripes = stripe_nr_end - 1 - j; + do_div(stripes, map->num_stripes); + multi->stripes[i].length = map->stripe_len * + (stripes - stripe_nr + 1); + + if (i == 0) { + multi->stripes[i].length -= + stripe_offset; + stripe_offset = 0; + } + if (stripe_index == last_stripe) + multi->stripes[i].length -= + stripe_end_offset; + } else if (map->type & BTRFS_BLOCK_GROUP_RAID10) { + u64 stripes; + int j; + int factor = map->num_stripes / + map->sub_stripes; + int last_stripe = (stripe_nr_end - 1) % factor; + last_stripe *= map->sub_stripes; + + for (j = 0; j < factor; j++) { + if ((stripe_nr_end - 1 - j) % factor == + stripe_index / map->sub_stripes) + break; + } + stripes = stripe_nr_end - 1 - j; + do_div(stripes, factor); + multi->stripes[i].length = map->stripe_len * + (stripes - stripe_nr + 1); + + if (i < map->sub_stripes) { + multi->stripes[i].length -= + stripe_offset; + if (i == map->sub_stripes - 1) + stripe_offset = 0; + } + if (stripe_index >= last_stripe && + stripe_index <= (last_stripe + + map->sub_stripes - 1)) { + multi->stripes[i].length -= + stripe_end_offset; + } + } else + multi->stripes[i].length = *length; + + stripe_index++; + if (stripe_index == map->num_stripes) { + /* This could only happen for RAID0/10 */ + stripe_index = 0; + stripe_nr++; + } + } + } else { + for (i = 0; i < num_stripes; i++) { + if (unplug_page) { + struct btrfs_device *device; + struct backing_dev_info *bdi; + + device = map->stripes[stripe_index].dev; + if (device->bdev) { + bdi = blk_get_backing_dev_info(device-> + bdev); + if (bdi->unplug_io_fn) + bdi->unplug_io_fn(bdi, + unplug_page); + } + } else { + multi->stripes[i].physical = + map->stripes[stripe_index].physical + + stripe_offset + + stripe_nr * map->stripe_len; + multi->stripes[i].dev = + map->stripes[stripe_index].dev; + } + stripe_index++; } - stripe_index++; } if (multi_ret) { *multi_ret = multi; diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index 7b38d0668b51..cc2eadaf7a27 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h @@ -126,6 +126,7 @@ struct btrfs_fs_devices { struct btrfs_bio_stripe { struct btrfs_device *dev; u64 physical; + u64 length; /* only used for discard mappings */ }; struct btrfs_multi_bio { -- cgit From 5378e60734f5b7bfe1b43dc191aaf6131c1befe7 Mon Sep 17 00:00:00 2001 From: Li Dongyang Date: Thu, 24 Mar 2011 10:24:27 +0000 Subject: Btrfs: adjust btrfs_discard_extent() return errors and trimmed bytes Callers of btrfs_discard_extent() should check if we are mounted with -o discard, as we want to make fitrim to work even the fs is not mounted with -o discard. Also we should use REQ_DISCARD to map the free extent to get a full mapping, last we only return errors if 1. the error is not a EOPNOTSUPP 2. no device supports discard Signed-off-by: Li Dongyang Signed-off-by: Chris Mason --- fs/btrfs/ctree.h | 2 +- fs/btrfs/disk-io.c | 5 ++++- fs/btrfs/extent-tree.c | 43 ++++++++++++++++++++++++++----------------- 3 files changed, 31 insertions(+), 19 deletions(-) (limited to 'fs') diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 9e21176cdf57..a18b7bc2b22c 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -2229,7 +2229,7 @@ u64 btrfs_account_ro_block_groups_free_space(struct btrfs_space_info *sinfo); int btrfs_error_unpin_extent_range(struct btrfs_root *root, u64 start, u64 end); int btrfs_error_discard_extent(struct btrfs_root *root, u64 bytenr, - u64 num_bytes); + u64 num_bytes, u64 *actual_bytes); int btrfs_force_chunk_alloc(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 type); diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 125639ddaffe..8ecc5419d8b6 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -3054,7 +3054,10 @@ static int btrfs_destroy_pinned_extent(struct btrfs_root *root, break; /* opt_discard */ - ret = btrfs_error_discard_extent(root, start, end + 1 - start); + if (btrfs_test_opt(root, DISCARD)) + ret = btrfs_error_discard_extent(root, start, + end + 1 - start, + NULL); clear_extent_dirty(unpin, start, end, GFP_NOFS); btrfs_error_unpin_extent_range(root, start, end); diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 0671f5b77eb8..e990d2d1ba4a 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -1738,39 +1738,45 @@ static int remove_extent_backref(struct btrfs_trans_handle *trans, return ret; } -static void btrfs_issue_discard(struct block_device *bdev, +static int btrfs_issue_discard(struct block_device *bdev, u64 start, u64 len) { - blkdev_issue_discard(bdev, start >> 9, len >> 9, GFP_NOFS, 0); + return blkdev_issue_discard(bdev, start >> 9, len >> 9, GFP_NOFS, 0); } static int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr, - u64 num_bytes) + u64 num_bytes, u64 *actual_bytes) { int ret; - u64 map_length = num_bytes; + u64 discarded_bytes = 0; struct btrfs_multi_bio *multi = NULL; - if (!btrfs_test_opt(root, DISCARD)) - return 0; /* Tell the block device(s) that the sectors can be discarded */ - ret = btrfs_map_block(&root->fs_info->mapping_tree, READ, - bytenr, &map_length, &multi, 0); + ret = btrfs_map_block(&root->fs_info->mapping_tree, REQ_DISCARD, + bytenr, &num_bytes, &multi, 0); if (!ret) { struct btrfs_bio_stripe *stripe = multi->stripes; int i; - if (map_length > num_bytes) - map_length = num_bytes; for (i = 0; i < multi->num_stripes; i++, stripe++) { - btrfs_issue_discard(stripe->dev->bdev, - stripe->physical, - map_length); + ret = btrfs_issue_discard(stripe->dev->bdev, + stripe->physical, + stripe->length); + if (!ret) + discarded_bytes += stripe->length; + else if (ret != -EOPNOTSUPP) + break; } kfree(multi); } + if (discarded_bytes && ret == -EOPNOTSUPP) + ret = 0; + + if (actual_bytes) + *actual_bytes = discarded_bytes; + return ret; } @@ -4371,7 +4377,9 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, if (ret) break; - ret = btrfs_discard_extent(root, start, end + 1 - start); + if (btrfs_test_opt(root, DISCARD)) + ret = btrfs_discard_extent(root, start, + end + 1 - start, NULL); clear_extent_dirty(unpin, start, end, GFP_NOFS); unpin_extent_range(root, start, end); @@ -5427,7 +5435,8 @@ int btrfs_free_reserved_extent(struct btrfs_root *root, u64 start, u64 len) return -ENOSPC; } - ret = btrfs_discard_extent(root, start, len); + if (btrfs_test_opt(root, DISCARD)) + ret = btrfs_discard_extent(root, start, len, NULL); btrfs_add_free_space(cache, start, len); btrfs_update_reserved_bytes(cache, len, 0, 1); @@ -8765,7 +8774,7 @@ int btrfs_error_unpin_extent_range(struct btrfs_root *root, u64 start, u64 end) } int btrfs_error_discard_extent(struct btrfs_root *root, u64 bytenr, - u64 num_bytes) + u64 num_bytes, u64 *actual_bytes) { - return btrfs_discard_extent(root, bytenr, num_bytes); + return btrfs_discard_extent(root, bytenr, num_bytes, actual_bytes); } -- cgit From f7039b1d5c32241f87a513e33120db36bf30264d Mon Sep 17 00:00:00 2001 From: Li Dongyang Date: Thu, 24 Mar 2011 10:24:28 +0000 Subject: Btrfs: add btrfs_trim_fs() to handle FITRIM We take an free extent out from allocator, trim it, then put it back, but before we trim the block group, we should make sure the block group is cached, so plus a little change to make cache_block_group() run without a transaction. Signed-off-by: Li Dongyang Signed-off-by: Chris Mason --- fs/btrfs/ctree.h | 1 + fs/btrfs/extent-tree.c | 50 +++++++++++++++++++++++- fs/btrfs/free-space-cache.c | 92 +++++++++++++++++++++++++++++++++++++++++++++ fs/btrfs/free-space-cache.h | 2 + fs/btrfs/ioctl.c | 46 +++++++++++++++++++++++ 5 files changed, 190 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index a18b7bc2b22c..93a0191aded6 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -2232,6 +2232,7 @@ int btrfs_error_discard_extent(struct btrfs_root *root, u64 bytenr, u64 num_bytes, u64 *actual_bytes); int btrfs_force_chunk_alloc(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 type); +int btrfs_trim_fs(struct btrfs_root *root, struct fstrim_range *range); /* ctree.c */ int btrfs_bin_search(struct extent_buffer *eb, struct btrfs_key *key, diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index e990d2d1ba4a..1efeda3b2f6f 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -440,7 +440,7 @@ static int cache_block_group(struct btrfs_block_group_cache *cache, * allocate blocks for the tree root we can't do the fast caching since * we likely hold important locks. */ - if (!trans->transaction->in_commit && + if (trans && (!trans->transaction->in_commit) && (root && root != root->fs_info->tree_root)) { spin_lock(&cache->lock); if (cache->cached != BTRFS_CACHE_NO) { @@ -8778,3 +8778,51 @@ int btrfs_error_discard_extent(struct btrfs_root *root, u64 bytenr, { return btrfs_discard_extent(root, bytenr, num_bytes, actual_bytes); } + +int btrfs_trim_fs(struct btrfs_root *root, struct fstrim_range *range) +{ + struct btrfs_fs_info *fs_info = root->fs_info; + struct btrfs_block_group_cache *cache = NULL; + u64 group_trimmed; + u64 start; + u64 end; + u64 trimmed = 0; + int ret = 0; + + cache = btrfs_lookup_block_group(fs_info, range->start); + + while (cache) { + if (cache->key.objectid >= (range->start + range->len)) { + btrfs_put_block_group(cache); + break; + } + + start = max(range->start, cache->key.objectid); + end = min(range->start + range->len, + cache->key.objectid + cache->key.offset); + + if (end - start >= range->minlen) { + if (!block_group_cache_done(cache)) { + ret = cache_block_group(cache, NULL, root, 0); + if (!ret) + wait_block_group_cache_done(cache); + } + ret = btrfs_trim_block_group(cache, + &group_trimmed, + start, + end, + range->minlen); + + trimmed += group_trimmed; + if (ret) { + btrfs_put_block_group(cache); + break; + } + } + + cache = next_block_group(fs_info->tree_root, cache); + } + + range->len = trimmed; + return ret; +} diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index f03ef97c3b21..0037427d8a9d 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -2178,3 +2178,95 @@ void btrfs_init_free_cluster(struct btrfs_free_cluster *cluster) cluster->block_group = NULL; } +int btrfs_trim_block_group(struct btrfs_block_group_cache *block_group, + u64 *trimmed, u64 start, u64 end, u64 minlen) +{ + struct btrfs_free_space *entry = NULL; + struct btrfs_fs_info *fs_info = block_group->fs_info; + u64 bytes = 0; + u64 actually_trimmed; + int ret = 0; + + *trimmed = 0; + + while (start < end) { + spin_lock(&block_group->tree_lock); + + if (block_group->free_space < minlen) { + spin_unlock(&block_group->tree_lock); + break; + } + + entry = tree_search_offset(block_group, start, 0, 1); + if (!entry) + entry = tree_search_offset(block_group, + offset_to_bitmap(block_group, + start), + 1, 1); + + if (!entry || entry->offset >= end) { + spin_unlock(&block_group->tree_lock); + break; + } + + if (entry->bitmap) { + ret = search_bitmap(block_group, entry, &start, &bytes); + if (!ret) { + if (start >= end) { + spin_unlock(&block_group->tree_lock); + break; + } + bytes = min(bytes, end - start); + bitmap_clear_bits(block_group, entry, + start, bytes); + if (entry->bytes == 0) + free_bitmap(block_group, entry); + } else { + start = entry->offset + BITS_PER_BITMAP * + block_group->sectorsize; + spin_unlock(&block_group->tree_lock); + ret = 0; + continue; + } + } else { + start = entry->offset; + bytes = min(entry->bytes, end - start); + unlink_free_space(block_group, entry); + kfree(entry); + } + + spin_unlock(&block_group->tree_lock); + + if (bytes >= minlen) { + int update_ret; + update_ret = btrfs_update_reserved_bytes(block_group, + bytes, 1, 1); + + ret = btrfs_error_discard_extent(fs_info->extent_root, + start, + bytes, + &actually_trimmed); + + btrfs_add_free_space(block_group, + start, bytes); + if (!update_ret) + btrfs_update_reserved_bytes(block_group, + bytes, 0, 1); + + if (ret) + break; + *trimmed += actually_trimmed; + } + start += bytes; + bytes = 0; + + if (fatal_signal_pending(current)) { + ret = -ERESTARTSYS; + break; + } + + cond_resched(); + } + + return ret; +} diff --git a/fs/btrfs/free-space-cache.h b/fs/btrfs/free-space-cache.h index e49ca5c321b5..65c3b935289f 100644 --- a/fs/btrfs/free-space-cache.h +++ b/fs/btrfs/free-space-cache.h @@ -68,4 +68,6 @@ u64 btrfs_alloc_from_cluster(struct btrfs_block_group_cache *block_group, int btrfs_return_cluster_to_free_space( struct btrfs_block_group_cache *block_group, struct btrfs_free_cluster *cluster); +int btrfs_trim_block_group(struct btrfs_block_group_cache *block_group, + u64 *trimmed, u64 start, u64 end, u64 minlen); #endif diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 32c980ae0f1c..649f47d2afb4 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -40,6 +40,7 @@ #include #include #include +#include #include "compat.h" #include "ctree.h" #include "disk-io.h" @@ -258,6 +259,49 @@ static int btrfs_ioctl_getversion(struct file *file, int __user *arg) return put_user(inode->i_generation, arg); } +static noinline int btrfs_ioctl_fitrim(struct file *file, void __user *arg) +{ + struct btrfs_root *root = fdentry(file)->d_sb->s_fs_info; + struct btrfs_fs_info *fs_info = root->fs_info; + struct btrfs_device *device; + struct request_queue *q; + struct fstrim_range range; + u64 minlen = ULLONG_MAX; + u64 num_devices = 0; + int ret; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + mutex_lock(&fs_info->fs_devices->device_list_mutex); + list_for_each_entry(device, &fs_info->fs_devices->devices, dev_list) { + if (!device->bdev) + continue; + q = bdev_get_queue(device->bdev); + if (blk_queue_discard(q)) { + num_devices++; + minlen = min((u64)q->limits.discard_granularity, + minlen); + } + } + mutex_unlock(&fs_info->fs_devices->device_list_mutex); + if (!num_devices) + return -EOPNOTSUPP; + + if (copy_from_user(&range, arg, sizeof(range))) + return -EFAULT; + + range.minlen = max(range.minlen, minlen); + ret = btrfs_trim_fs(root, &range); + if (ret < 0) + return ret; + + if (copy_to_user(arg, &range, sizeof(range))) + return -EFAULT; + + return 0; +} + static noinline int create_subvol(struct btrfs_root *root, struct dentry *dentry, char *name, int namelen, @@ -2426,6 +2470,8 @@ long btrfs_ioctl(struct file *file, unsigned int return btrfs_ioctl_setflags(file, argp); case FS_IOC_GETVERSION: return btrfs_ioctl_getversion(file, argp); + case FITRIM: + return btrfs_ioctl_fitrim(file, argp); case BTRFS_IOC_SNAP_CREATE: return btrfs_ioctl_snap_create(file, argp, 0); case BTRFS_IOC_SNAP_CREATE_V2: -- cgit From c622ae6085d0c6ad834213bbf1477eb311359078 Mon Sep 17 00:00:00 2001 From: liubo Date: Sat, 26 Mar 2011 08:01:12 -0400 Subject: btrfs: make inode ref log recovery faster When we recover from crash via write-ahead log tree and process the inode refs, for each btrfs_inode_ref item, we will 1) check if we already have a perfect match in fs/file tree, if we have, then we're done. 2) search the corresponding back reference in fs/file tree, and check all the names in this back reference to see if they are also in the log to avoid conflict corners. 3) recover the logged inode refs to fs/file tree. In current btrfs, however, - for 2)'s check, once is enough, since the checked back reference will remain unchanged after processing all the inode refs belonged to the key. - it has no need to do another 1) between 2) and 3). I've made a small test to show how it improves, $dd if=/dev/zero of=foobar bs=4K count=1 $sync $make 100 hard links continuously, like ln foobar link_i $fsync foobar $echo b > /proc/sysrq-trigger after reboot $time mount DEV PATH without patch: real 0m0.285s user 0m0.001s sys 0m0.009s with patch: real 0m0.123s user 0m0.000s sys 0m0.010s Changelog v1->v2: - fix double free - pointed by David Sterba Changelog v2->v3: - adjust free order Signed-off-by: Liu Bo Signed-off-by: Chris Mason --- fs/btrfs/tree-log.c | 35 +++++++++++------------------------ 1 file changed, 11 insertions(+), 24 deletions(-) (limited to 'fs') diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index f9425e33e358..c50271ad3157 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -799,12 +799,12 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans, struct inode *dir; int ret; struct btrfs_inode_ref *ref; - struct btrfs_dir_item *di; struct inode *inode; char *name; int namelen; unsigned long ref_ptr; unsigned long ref_end; + int search_done = 0; /* * it is possible that we didn't log all the parent directories @@ -845,7 +845,10 @@ again: * existing back reference, and we don't want to create * dangling pointers in the directory. */ -conflict_again: + + if (search_done) + goto insert; + ret = btrfs_search_slot(NULL, root, key, path, 0, 0); if (ret == 0) { char *victim_name; @@ -886,37 +889,21 @@ conflict_again: ret = btrfs_unlink_inode(trans, root, dir, inode, victim_name, victim_name_len); - kfree(victim_name); - btrfs_release_path(root, path); - goto conflict_again; } kfree(victim_name); ptr = (unsigned long)(victim_ref + 1) + victim_name_len; } BUG_ON(ret); - } - btrfs_release_path(root, path); - - /* look for a conflicting sequence number */ - di = btrfs_lookup_dir_index_item(trans, root, path, dir->i_ino, - btrfs_inode_ref_index(eb, ref), - name, namelen, 0); - if (di && !IS_ERR(di)) { - ret = drop_one_dir_item(trans, root, path, dir, di); - BUG_ON(ret); - } - btrfs_release_path(root, path); - - /* look for a conflicting name */ - di = btrfs_lookup_dir_item(trans, root, path, dir->i_ino, - name, namelen, 0); - if (di && !IS_ERR(di)) { - ret = drop_one_dir_item(trans, root, path, dir, di); - BUG_ON(ret); + /* + * NOTE: we have searched root tree and checked the + * coresponding ref, it does not need to check again. + */ + search_done = 1; } btrfs_release_path(root, path); +insert: /* insert our name */ ret = btrfs_add_link(trans, dir, inode, name, namelen, 0, btrfs_inode_ref_index(eb, ref)); -- cgit From dac97e516c617f9c797f64b0224050b70aea30c7 Mon Sep 17 00:00:00 2001 From: Yoshinori Sano Date: Tue, 15 Feb 2011 12:01:42 +0000 Subject: Btrfs: fix uncheck memory allocations To make Btrfs code more robust, several return value checks where memory allocation can fail are introduced. I use BUG_ON where I don't know how to handle the error properly, which increases the number of using the notorious BUG_ON, though. Signed-off-by: Yoshinori Sano Signed-off-by: Chris Mason --- fs/btrfs/compression.c | 6 ++++++ fs/btrfs/extent-tree.c | 4 ++++ fs/btrfs/inode.c | 2 ++ 3 files changed, 12 insertions(+) (limited to 'fs') diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index 4d2110eafe29..992a4b92083e 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c @@ -340,6 +340,8 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start, WARN_ON(start & ((u64)PAGE_CACHE_SIZE - 1)); cb = kmalloc(compressed_bio_size(root, compressed_len), GFP_NOFS); + if (!cb) + return -ENOMEM; atomic_set(&cb->pending_bios, 0); cb->errors = 0; cb->inode = inode; @@ -354,6 +356,10 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start, bdev = BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev; bio = compressed_bio_alloc(bdev, first_byte, GFP_NOFS); + if(!bio) { + kfree(cb); + return -ENOMEM; + } bio->bi_private = cb; bio->bi_end_io = end_compressed_bio_write; atomic_inc(&cb->pending_bios); diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 1efeda3b2f6f..cd0b69f57375 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -6978,6 +6978,10 @@ static noinline int get_new_locations(struct inode *reloc_inode, struct disk_extent *old = exts; max *= 2; exts = kzalloc(sizeof(*exts) * max, GFP_NOFS); + if (!exts) { + ret = -ENOMEM; + goto out; + } memcpy(exts, old, sizeof(*exts) * nr); if (old != *extents) kfree(old); diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 67fd6e9552d3..f739b256967e 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -290,6 +290,7 @@ static noinline int add_async_extent(struct async_cow *cow, struct async_extent *async_extent; async_extent = kmalloc(sizeof(*async_extent), GFP_NOFS); + BUG_ON(!async_extent); async_extent->start = start; async_extent->ram_size = ram_size; async_extent->compressed_size = compressed_size; @@ -388,6 +389,7 @@ again: (BTRFS_I(inode)->flags & BTRFS_INODE_COMPRESS))) { WARN_ON(pages); pages = kzalloc(sizeof(struct page *) * nr_pages, GFP_NOFS); + BUG_ON(!pages); if (BTRFS_I(inode)->force_compress) compress_type = BTRFS_I(inode)->force_compress; -- cgit From 2d4e6f6ad2b9f84f568d07dae4bdbc7f48a70ad1 Mon Sep 17 00:00:00 2001 From: liubo Date: Thu, 24 Feb 2011 09:38:16 +0000 Subject: Btrfs: fix return value of setflags ioctl setflags ioctl should return error when any checks fail. Signed-off-by: Liu Bo Reviewed-by: David Sterba Signed-off-by: Chris Mason --- fs/btrfs/ioctl.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 649f47d2afb4..6b70e0e2bd1e 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -247,9 +247,11 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg) btrfs_end_transaction(trans, root); mnt_drop_write(file->f_path.mnt); + + ret = 0; out_unlock: mutex_unlock(&inode->i_mutex); - return 0; + return ret; } static int btrfs_ioctl_getversion(struct file *file, int __user *arg) -- cgit From 9f7c43c96727a53bea45f7f2549d897f0a6117b8 Mon Sep 17 00:00:00 2001 From: liubo Date: Mon, 7 Mar 2011 02:13:33 +0000 Subject: Btrfs: fix memory leak of empty filesystem after balance After Josef's patch(commit 3c14874acc71180553fb5aba528e3cf57c5b958b), btrfs will exclude super bytes when reading block groups(by marking a extent state UPTODATE). However, these bytes do not get freed while balance remove unused block groups, and we won't process those removed ones any more, when we do umount and unload the btrfs module, btrfs hits a memory leak. This patch add the missing free operation. Reproduce steps: $ mkfs.btrfs disk $ mount disk /mnt/btrfs -o loop $ btrfs filesystem balance /mnt/btrfs $ umount /mnt/btrfs $ rmmod btrfs Signed-off-by: Liu Bo Signed-off-by: Chris Mason --- fs/btrfs/extent-tree.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'fs') diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index cd0b69f57375..a561060f5ffb 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -8669,6 +8669,12 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, BUG_ON(!block_group); BUG_ON(!block_group->ro); + /* + * Free the reserved super bytes from this block group before + * remove it. + */ + free_excluded_extents(root, block_group); + memcpy(&key, &block_group->key, sizeof(key)); if (block_group->flags & (BTRFS_BLOCK_GROUP_DUP | BTRFS_BLOCK_GROUP_RAID1 | -- cgit From c59021f846881a957ac5afe456d0f59d6a517b61 Mon Sep 17 00:00:00 2001 From: liubo Date: Mon, 7 Mar 2011 02:13:14 +0000 Subject: Btrfs: fix OOPS of empty filesystem after balance btrfs will remove unused block groups after balance. When a empty filesystem is balanced, the block group with tag "DATA" may be dropped, and after umount and mount again, it will not find "DATA" space_info and lead to OOPS. So we initial the necessary space_infos(DATA, SYSTEM, METADATA) to avoid OOPS. Reported-by: Daniel J Blueman Signed-off-by: Liu Bo Signed-off-by: Chris Mason --- fs/btrfs/ctree.h | 1 + fs/btrfs/disk-io.c | 6 ++++++ fs/btrfs/extent-tree.c | 23 +++++++++++++++++++++++ 3 files changed, 30 insertions(+) (limited to 'fs') diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 93a0191aded6..d47ce8307854 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -2234,6 +2234,7 @@ int btrfs_force_chunk_alloc(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 type); int btrfs_trim_fs(struct btrfs_root *root, struct fstrim_range *range); +int btrfs_init_space_info(struct btrfs_fs_info *fs_info); /* ctree.c */ int btrfs_bin_search(struct extent_buffer *eb, struct btrfs_key *key, int level, int *slot); diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 8ecc5419d8b6..b3fc8475870f 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -2065,6 +2065,12 @@ struct btrfs_root *open_ctree(struct super_block *sb, fs_info->metadata_alloc_profile = (u64)-1; fs_info->system_alloc_profile = fs_info->metadata_alloc_profile; + ret = btrfs_init_space_info(fs_info); + if (ret) { + printk(KERN_ERR "Failed to initial space info: %d\n", ret); + goto fail_block_groups; + } + ret = btrfs_read_block_groups(extent_root); if (ret) { printk(KERN_ERR "Failed to read block groups: %d\n", ret); diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index a561060f5ffb..f619c3cb13b7 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -8778,6 +8778,29 @@ out: return ret; } +int btrfs_init_space_info(struct btrfs_fs_info *fs_info) +{ + struct btrfs_space_info *space_info; + int ret; + + ret = update_space_info(fs_info, BTRFS_BLOCK_GROUP_SYSTEM, 0, 0, + &space_info); + if (ret) + return ret; + + ret = update_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA, 0, 0, + &space_info); + if (ret) + return ret; + + ret = update_space_info(fs_info, BTRFS_BLOCK_GROUP_DATA, 0, 0, + &space_info); + if (ret) + return ret; + + return ret; +} + int btrfs_error_unpin_extent_range(struct btrfs_root *root, u64 start, u64 end) { return unpin_extent_range(root, start, end); -- cgit From c2db1073fdf9757e6fd8b4a59d15b6ecc7a2af8a Mon Sep 17 00:00:00 2001 From: Tsutomu Itoh Date: Tue, 1 Mar 2011 06:48:31 +0000 Subject: Btrfs: check return value of btrfs_alloc_path() Adding the check on the return value of btrfs_alloc_path() to several places. And, some of callers are modified by this change. Signed-off-by: Tsutomu Itoh Signed-off-by: Chris Mason --- fs/btrfs/compression.c | 11 +++++++---- fs/btrfs/dir-item.c | 10 ++++++---- fs/btrfs/file-item.c | 2 ++ fs/btrfs/inode.c | 18 ++++++++++++------ 4 files changed, 27 insertions(+), 14 deletions(-) (limited to 'fs') diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index 992a4b92083e..41d1d7c70e29 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c @@ -663,8 +663,9 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, atomic_inc(&cb->pending_bios); if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) { - btrfs_lookup_bio_sums(root, inode, comp_bio, - sums); + ret = btrfs_lookup_bio_sums(root, inode, + comp_bio, sums); + BUG_ON(ret); } sums += (comp_bio->bi_size + root->sectorsize - 1) / root->sectorsize; @@ -689,8 +690,10 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, ret = btrfs_bio_wq_end_io(root->fs_info, comp_bio, 0); BUG_ON(ret); - if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) - btrfs_lookup_bio_sums(root, inode, comp_bio, sums); + if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) { + ret = btrfs_lookup_bio_sums(root, inode, comp_bio, sums); + BUG_ON(ret); + } ret = btrfs_map_bio(root, READ, comp_bio, mirror_num, 0); BUG_ON(ret); diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c index 02c97ad61b6d..c62f02f6ae69 100644 --- a/fs/btrfs/dir-item.c +++ b/fs/btrfs/dir-item.c @@ -151,7 +151,7 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root ret = PTR_ERR(dir_item); if (ret == -EEXIST) goto second_insert; - goto out; + goto out_free; } leaf = path->nodes[0]; @@ -170,7 +170,7 @@ second_insert: /* FIXME, use some real flag for selecting the extra index */ if (root == root->fs_info->tree_root) { ret = 0; - goto out; + goto out_free; } btrfs_release_path(root, path); @@ -180,7 +180,7 @@ second_insert: name, name_len); if (IS_ERR(dir_item)) { ret2 = PTR_ERR(dir_item); - goto out; + goto out_free; } leaf = path->nodes[0]; btrfs_cpu_key_to_disk(&disk_key, location); @@ -192,7 +192,9 @@ second_insert: name_ptr = (unsigned long)(dir_item + 1); write_extent_buffer(leaf, name, name_ptr, name_len); btrfs_mark_buffer_dirty(leaf); -out: + +out_free: + btrfs_free_path(path); if (ret) return ret; diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index a2134195a85e..a6a9d4e8b491 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c @@ -170,6 +170,8 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root, struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; path = btrfs_alloc_path(); + if (!path) + return -ENOMEM; if (bio->bi_size > PAGE_CACHE_SIZE * 8) path->reada = 2; diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index f739b256967e..04e9fffee8cc 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -1467,8 +1467,11 @@ static int btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, if (bio_flags & EXTENT_BIO_COMPRESSED) { return btrfs_submit_compressed_read(inode, bio, mirror_num, bio_flags); - } else if (!skip_sum) - btrfs_lookup_bio_sums(root, inode, bio, NULL); + } else if (!skip_sum) { + ret = btrfs_lookup_bio_sums(root, inode, bio, NULL); + if (ret) + return ret; + } goto mapit; } else if (!skip_sum) { /* csum items have already been cloned */ @@ -1903,10 +1906,10 @@ static int btrfs_io_failed_hook(struct bio *failed_bio, else rw = READ; - BTRFS_I(inode)->io_tree.ops->submit_bio_hook(inode, rw, bio, + ret = BTRFS_I(inode)->io_tree.ops->submit_bio_hook(inode, rw, bio, failrec->last_mirror, failrec->bio_flags, 0); - return 0; + return ret; } /* @@ -5943,9 +5946,12 @@ static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode, __btrfs_submit_bio_start_direct_io, __btrfs_submit_bio_done); goto err; - } else if (!skip_sum) - btrfs_lookup_bio_sums_dio(root, inode, bio, + } else if (!skip_sum) { + ret = btrfs_lookup_bio_sums_dio(root, inode, bio, file_offset, csums); + if (ret) + goto err; + } ret = btrfs_map_bio(root, rw, bio, 0, 1); err: -- cgit From 92986796d84ef939e304099dece32572a755b280 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 4 Mar 2011 17:14:37 +0000 Subject: btrfs: don't mess with i_nlink of unlocked inode in rename() old_inode is not locked; it's not safe to play with its link count. Instead of bumping it and calling btrfs_unlink_inode(), add a variant of the latter that does not do btrfs_drop_nlink()/ btrfs_update_inode(), call it instead of btrfs_inc_nlink()/ btrfs_unlink_inode() and do btrfs_update_inode() ourselves. Signed-off-by: Al Viro Signed-off-by: Chris Mason --- fs/btrfs/inode.c | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) (limited to 'fs') diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 04e9fffee8cc..4822b3132784 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -2664,10 +2664,10 @@ failed: * recovery code. It remove a link in a directory with a given name, and * also drops the back refs in the inode to the directory */ -int btrfs_unlink_inode(struct btrfs_trans_handle *trans, - struct btrfs_root *root, - struct inode *dir, struct inode *inode, - const char *name, int name_len) +static int __btrfs_unlink_inode(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct inode *dir, struct inode *inode, + const char *name, int name_len) { struct btrfs_path *path; int ret = 0; @@ -2739,12 +2739,25 @@ err: btrfs_i_size_write(dir, dir->i_size - name_len * 2); inode->i_ctime = dir->i_mtime = dir->i_ctime = CURRENT_TIME; btrfs_update_inode(trans, root, dir); - btrfs_drop_nlink(inode); - ret = btrfs_update_inode(trans, root, inode); out: return ret; } +int btrfs_unlink_inode(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct inode *dir, struct inode *inode, + const char *name, int name_len) +{ + int ret; + ret = __btrfs_unlink_inode(trans, root, dir, inode, name, name_len); + if (!ret) { + btrfs_drop_nlink(inode); + ret = btrfs_update_inode(trans, root, inode); + } + return ret; +} + + /* helper to check if there is any shared block in the path */ static int check_path_shared(struct btrfs_root *root, struct btrfs_path *path) @@ -6999,11 +7012,12 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, old_dentry->d_name.name, old_dentry->d_name.len); } else { - btrfs_inc_nlink(old_dentry->d_inode); - ret = btrfs_unlink_inode(trans, root, old_dir, - old_dentry->d_inode, - old_dentry->d_name.name, - old_dentry->d_name.len); + ret = __btrfs_unlink_inode(trans, root, old_dir, + old_dentry->d_inode, + old_dentry->d_name.name, + old_dentry->d_name.len); + if (!ret) + ret = btrfs_update_inode(trans, root, old_inode); } BUG_ON(ret); -- cgit From c055e99eea6e4f614267632fac546e7896c0227b Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 4 Mar 2011 17:15:18 +0000 Subject: btrfs: check link counter overflow in link(2) Signed-off-by: Al Viro Signed-off-by: Chris Mason --- fs/btrfs/inode.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'fs') diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 4822b3132784..04babaf31a33 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -4837,6 +4837,9 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, if (root->objectid != BTRFS_I(inode)->root->objectid) return -EXDEV; + if (inode->i_nlink == ~0U) + return -EMLINK; + btrfs_inc_nlink(inode); inode->i_ctime = CURRENT_TIME; -- cgit From 1561deda687eef0e95065f1268d680ddc5976ee7 Mon Sep 17 00:00:00 2001 From: Miao Xie Date: Sun, 27 Mar 2011 16:07:36 +0800 Subject: btrfs: fix possible deadlock by clearing __GFP_FS flag Using the GFP_HIGHUSER_MOVABLE flag to allocate the metadata's page may cause deadlock. Task1 open() ... btrfs_search_slot() ... btrfs_cow_block() ... alloc_page() wait for reclaiming shrink_slab() ... shrink_icache_memory() ... btrfs_evict_inode() ... btrfs_search_slot() If the path is locked by task1, the deadlock happens. So the btree's page cache is different with the file's page cache, it can not allocate pages by GFP_HIGHUSER_MOVABLE flag, we must clear __GFP_FS flag in GFP_HIGHUSER_MOVABLE flag. Reported-by: Itaru Kitayama Signed-off-by: Miao Xie Signed-off-by: Chris Mason --- fs/btrfs/disk-io.c | 2 ++ fs/btrfs/inode.c | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index b3fc8475870f..5cf3aa7b125c 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1724,6 +1724,8 @@ struct btrfs_root *open_ctree(struct super_block *sb, goto fail_bdi; } + fs_info->btree_inode->i_mapping->flags &= ~__GFP_FS; + INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_ATOMIC); INIT_LIST_HEAD(&fs_info->trans_list); INIT_LIST_HEAD(&fs_info->dead_roots); diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 04babaf31a33..06274186b290 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -2536,6 +2536,8 @@ static void btrfs_read_locked_inode(struct inode *inode) BTRFS_I(inode)->flags = btrfs_inode_flags(leaf, inode_item); alloc_group_block = btrfs_inode_block_group(leaf, inode_item); + if (location.objectid == BTRFS_FREE_SPACE_OBJECTID) + inode->i_mapping->flags &= ~__GFP_FS; /* * try to precache a NULL acl entry for files that don't have @@ -4084,7 +4086,6 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location, BTRFS_I(inode)->root = root; memcpy(&BTRFS_I(inode)->location, location, sizeof(*location)); btrfs_read_locked_inode(inode); - inode_tree_add(inode); unlock_new_inode(inode); if (new) -- cgit From d9d04879321af570ea7285c6dad92d9c3cd108a1 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Sun, 27 Mar 2011 21:23:21 -0400 Subject: Btrfs: fix __btrfs_map_block on 32 bit machines Recent changes for discard support didn't compile, this fixes them not to try and % 64 bit numbers. Signed-off-by: Chris Mason --- fs/btrfs/volumes.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'fs') diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index c440c89a470a..8b9fb8c7683d 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -3126,13 +3126,19 @@ again: if (map->type & BTRFS_BLOCK_GROUP_RAID0) { u64 stripes; - int last_stripe = (stripe_nr_end - 1) % - map->num_stripes; + u32 last_stripe = 0; int j; + div_u64_rem(stripe_nr_end - 1, + map->num_stripes, + &last_stripe); + for (j = 0; j < map->num_stripes; j++) { - if ((stripe_nr_end - 1 - j) % - map->num_stripes == stripe_index) + u32 test; + + div_u64_rem(stripe_nr_end - 1 - j, + map->num_stripes, &test); + if (test == stripe_index) break; } stripes = stripe_nr_end - 1 - j; @@ -3153,11 +3159,19 @@ again: int j; int factor = map->num_stripes / map->sub_stripes; - int last_stripe = (stripe_nr_end - 1) % factor; + u32 last_stripe = 0; + + div_u64_rem(stripe_nr_end - 1, + factor, &last_stripe); last_stripe *= map->sub_stripes; for (j = 0; j < factor; j++) { - if ((stripe_nr_end - 1 - j) % factor == + u32 test; + + div_u64_rem(stripe_nr_end - 1 - j, + factor, &test); + + if (test == stripe_index / map->sub_stripes) break; } -- cgit From ed59992e8d91b70053c53d846a76f7e1ac000454 Mon Sep 17 00:00:00 2001 From: Rakib Mullick Date: Fri, 18 Mar 2011 17:01:08 +0600 Subject: fs,ocfs2: Move o2net_get_func_run_time under CONFIG_OCFS2_FS_STATS. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When CONFIG_DEBUG_FS=y and CONFIG_OCFS2_FS_STATS=n, we get the following warning: fs/ocfs2/cluster/tcp.c:213:16: warning: ‘o2net_get_func_run_time’ defined but not used Since o2net_get_func_run_time is only called from o2net_update_recv_stats, so move it under CONFIG_OCFS2_FS_STATS. Signed-off-by: Rakib Mullick Signed-off-by: jlbec --- fs/ocfs2/cluster/tcp.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c index 3b11cb1e38fc..ee04ff5ee603 100644 --- a/fs/ocfs2/cluster/tcp.c +++ b/fs/ocfs2/cluster/tcp.c @@ -210,10 +210,6 @@ static inline void o2net_set_func_stop_time(struct o2net_sock_container *sc) sc->sc_tv_func_stop = ktime_get(); } -static ktime_t o2net_get_func_run_time(struct o2net_sock_container *sc) -{ - return ktime_sub(sc->sc_tv_func_stop, sc->sc_tv_func_start); -} #else /* CONFIG_DEBUG_FS */ # define o2net_init_nst(a, b, c, d, e) # define o2net_set_nst_sock_time(a) @@ -227,10 +223,14 @@ static ktime_t o2net_get_func_run_time(struct o2net_sock_container *sc) # define o2net_set_advance_stop_time(a) # define o2net_set_func_start_time(a) # define o2net_set_func_stop_time(a) -# define o2net_get_func_run_time(a) (ktime_t)0 #endif /* CONFIG_DEBUG_FS */ #ifdef CONFIG_OCFS2_FS_STATS +static ktime_t o2net_get_func_run_time(struct o2net_sock_container *sc) +{ + return ktime_sub(sc->sc_tv_func_stop, sc->sc_tv_func_start); +} + static void o2net_update_send_stats(struct o2net_send_tracking *nst, struct o2net_sock_container *sc) { -- cgit From 272b62c1f0f6f742046e45b50b6fec98860208a0 Mon Sep 17 00:00:00 2001 From: Goldwyn Rodrigues Date: Thu, 17 Feb 2011 09:44:40 -0600 Subject: Treat writes as new when holes span across page boundaries When a hole spans across page boundaries, the next write forces a read of the block. This could end up reading existing garbage data from the disk in ocfs2_map_page_blocks. This leads to non-zero holes. In order to avoid this, mark the writes as new when the holes span across page boundaries. Signed-off-by: Goldwyn Rodrigues Signed-off-by: jlbec --- fs/ocfs2/aops.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'fs') diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 0d44b7701844..b5d7fb9ab1f3 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -1015,6 +1015,12 @@ static int ocfs2_prepare_page_for_write(struct inode *inode, u64 *p_blkno, ocfs2_figure_cluster_boundaries(OCFS2_SB(inode->i_sb), cpos, &cluster_start, &cluster_end); + /* treat the write as new if the a hole/lseek spanned across + * the page boundary. + */ + new = new | ((i_size_read(inode) <= page_offset(page)) && + (page_offset(page) <= user_pos)); + if (page == wc->w_target_page) { map_from = user_pos & (PAGE_CACHE_SIZE - 1); map_to = map_from + user_len; -- cgit From 0444d76ae64fffc7851797fc1b6ebdbb44ac504a Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 29 Mar 2011 18:08:50 +1100 Subject: fs: don't use igrab() while holding i_lock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the incorrect use of igrab() inside the i_lock in NFS and Ceph‥ If we are already holding the i_lock, we have a reference to the inode so we can safely use ihold() to gain an extra reference. This avoids hangs due to lock recursion on the i_lock now that the inode_lock is gone and igrab() uses the i_lock itself. Signed-off-by: Dave Chinner Cc: Al Viro Cc: linux-fsdevel@vger.kernel.org Cc: Ryan Mallon Signed-off-by: Linus Torvalds --- fs/ceph/addr.c | 2 +- fs/ceph/snap.c | 4 ++-- fs/nfs/nfs4state.c | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 561438b6a50c..37368ba2e67c 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -92,7 +92,7 @@ static int ceph_set_page_dirty(struct page *page) ci->i_head_snapc = ceph_get_snap_context(snapc); ++ci->i_wrbuffer_ref_head; if (ci->i_wrbuffer_ref == 0) - igrab(inode); + ihold(inode); ++ci->i_wrbuffer_ref; dout("%p set_page_dirty %p idx %lu head %d/%d -> %d/%d " "snapc %p seq %lld (%d snaps)\n", diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c index f40b9139e437..0aee66b92af3 100644 --- a/fs/ceph/snap.c +++ b/fs/ceph/snap.c @@ -463,8 +463,8 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci) dout("queue_cap_snap %p cap_snap %p queuing under %p\n", inode, capsnap, snapc); - igrab(inode); - + ihold(inode); + atomic_set(&capsnap->nref, 1); capsnap->ci = ci; INIT_LIST_HEAD(&capsnap->ci_item); diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index ab1bf5bb021f..a6804f704d9d 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -590,7 +590,8 @@ nfs4_get_open_state(struct inode *inode, struct nfs4_state_owner *owner) state->owner = owner; atomic_inc(&owner->so_count); list_add(&state->inode_states, &nfsi->open_states); - state->inode = igrab(inode); + ihold(inode); + state->inode = inode; spin_unlock(&inode->i_lock); /* Note: The reclaim code dictates that we add stateless * and read-only stateids to the end of the list */ -- cgit