Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8d753182 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull filesystem fixes from Jan Kara:
 "Notification, writeback, udf, quota fixes

  The notification patches are (with one exception) a fallout of my
  fsnotify rework which went into -rc1 (I've extented LTP to cover these
  cornercases to avoid similar breakage in future).

  The UDF patch is a nasty data corruption Al has recently reported,
  the revert of the writeback patch is due to possibility of violating
  sync(2) guarantees, and a quota bug can lead to corruption of quota
  files in ocfs2"

* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs:
  fsnotify: Allocate overflow events with proper type
  fanotify: Handle overflow in case of permission events
  fsnotify: Fix detection whether overflow event is queued
  Revert "writeback: do not sync data dirtied after sync start"
  quota: Fix race between dqput() and dquot_scan_active()
  udf: Fix data corruption on file type conversion
  inotify: Fix reporting of cookies for inotify events
parents bb7d43b1 ff57cd58
Loading
Loading
Loading
Loading
+11 −22
Original line number Diff line number Diff line
@@ -40,18 +40,13 @@
struct wb_writeback_work {
	long nr_pages;
	struct super_block *sb;
	/*
	 * Write only inodes dirtied before this time. Don't forget to set
	 * older_than_this_is_set when you set this.
	 */
	unsigned long older_than_this;
	unsigned long *older_than_this;
	enum writeback_sync_modes sync_mode;
	unsigned int tagged_writepages:1;
	unsigned int for_kupdate:1;
	unsigned int range_cyclic:1;
	unsigned int for_background:1;
	unsigned int for_sync:1;	/* sync(2) WB_SYNC_ALL writeback */
	unsigned int older_than_this_is_set:1;
	enum wb_reason reason;		/* why was writeback initiated? */

	struct list_head list;		/* pending work list */
@@ -252,10 +247,10 @@ static int move_expired_inodes(struct list_head *delaying_queue,
	int do_sb_sort = 0;
	int moved = 0;

	WARN_ON_ONCE(!work->older_than_this_is_set);
	while (!list_empty(delaying_queue)) {
		inode = wb_inode(delaying_queue->prev);
		if (inode_dirtied_after(inode, work->older_than_this))
		if (work->older_than_this &&
		    inode_dirtied_after(inode, *work->older_than_this))
			break;
		list_move(&inode->i_wb_list, &tmp);
		moved++;
@@ -742,8 +737,6 @@ static long writeback_inodes_wb(struct bdi_writeback *wb, long nr_pages,
		.sync_mode	= WB_SYNC_NONE,
		.range_cyclic	= 1,
		.reason		= reason,
		.older_than_this = jiffies,
		.older_than_this_is_set = 1,
	};

	spin_lock(&wb->list_lock);
@@ -802,13 +795,12 @@ static long wb_writeback(struct bdi_writeback *wb,
{
	unsigned long wb_start = jiffies;
	long nr_pages = work->nr_pages;
	unsigned long oldest_jif;
	struct inode *inode;
	long progress;

	if (!work->older_than_this_is_set) {
		work->older_than_this = jiffies;
		work->older_than_this_is_set = 1;
	}
	oldest_jif = jiffies;
	work->older_than_this = &oldest_jif;

	spin_lock(&wb->list_lock);
	for (;;) {
@@ -842,10 +834,10 @@ static long wb_writeback(struct bdi_writeback *wb,
		 * safe.
		 */
		if (work->for_kupdate) {
			work->older_than_this = jiffies -
			oldest_jif = jiffies -
				msecs_to_jiffies(dirty_expire_interval * 10);
		} else if (work->for_background)
			work->older_than_this = jiffies;
			oldest_jif = jiffies;

		trace_writeback_start(wb->bdi, work);
		if (list_empty(&wb->b_io))
@@ -1358,20 +1350,17 @@ EXPORT_SYMBOL(try_to_writeback_inodes_sb);
/**
 * sync_inodes_sb	-	sync sb inode pages
 * @sb: the superblock
 * @older_than_this:	timestamp
 *
 * This function writes and waits on any dirty inode belonging to this
 * superblock that has been dirtied before given timestamp.
 * super_block.
 */
void sync_inodes_sb(struct super_block *sb, unsigned long older_than_this)
void sync_inodes_sb(struct super_block *sb)
{
	DECLARE_COMPLETION_ONSTACK(done);
	struct wb_writeback_work work = {
		.sb		= sb,
		.sync_mode	= WB_SYNC_ALL,
		.nr_pages	= LONG_MAX,
		.older_than_this = older_than_this,
		.older_than_this_is_set = 1,
		.range_cyclic	= 0,
		.done		= &done,
		.reason		= WB_REASON_SYNC,
+1 −1
Original line number Diff line number Diff line
@@ -86,7 +86,7 @@ static int dnotify_handle_event(struct fsnotify_group *group,
				struct fsnotify_mark *inode_mark,
				struct fsnotify_mark *vfsmount_mark,
				u32 mask, void *data, int data_type,
				const unsigned char *file_name)
				const unsigned char *file_name, u32 cookie)
{
	struct dnotify_mark *dn_mark;
	struct dnotify_struct *dn;
+5 −3
Original line number Diff line number Diff line
@@ -147,7 +147,7 @@ static int fanotify_handle_event(struct fsnotify_group *group,
				 struct fsnotify_mark *inode_mark,
				 struct fsnotify_mark *fanotify_mark,
				 u32 mask, void *data, int data_type,
				 const unsigned char *file_name)
				 const unsigned char *file_name, u32 cookie)
{
	int ret = 0;
	struct fanotify_event_info *event;
@@ -192,10 +192,12 @@ static int fanotify_handle_event(struct fsnotify_group *group,

	ret = fsnotify_add_notify_event(group, fsn_event, fanotify_merge);
	if (ret) {
		BUG_ON(mask & FAN_ALL_PERM_EVENTS);
		/* Permission events shouldn't be merged */
		BUG_ON(ret == 1 && mask & FAN_ALL_PERM_EVENTS);
		/* Our event wasn't used in the end. Free it. */
		fsnotify_destroy_event(group, fsn_event);
		ret = 0;

		return 0;
	}

#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
+13 −0
Original line number Diff line number Diff line
@@ -698,6 +698,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
	struct fsnotify_group *group;
	int f_flags, fd;
	struct user_struct *user;
	struct fanotify_event_info *oevent;

	pr_debug("%s: flags=%d event_f_flags=%d\n",
		__func__, flags, event_f_flags);
@@ -730,8 +731,20 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
	group->fanotify_data.user = user;
	atomic_inc(&user->fanotify_listeners);

	oevent = kmem_cache_alloc(fanotify_event_cachep, GFP_KERNEL);
	if (unlikely(!oevent)) {
		fd = -ENOMEM;
		goto out_destroy_group;
	}
	group->overflow_event = &oevent->fse;
	fsnotify_init_event(group->overflow_event, NULL, FS_Q_OVERFLOW);
	oevent->tgid = get_pid(task_tgid(current));
	oevent->path.mnt = NULL;
	oevent->path.dentry = NULL;

	group->fanotify_data.f_flags = event_f_flags;
#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
	oevent->response = 0;
	mutex_init(&group->fanotify_data.access_mutex);
	init_waitqueue_head(&group->fanotify_data.access_waitq);
	INIT_LIST_HEAD(&group->fanotify_data.access_list);
+1 −1
Original line number Diff line number Diff line
@@ -179,7 +179,7 @@ static int send_to_group(struct inode *to_tell,

	return group->ops->handle_event(group, to_tell, inode_mark,
					vfsmount_mark, mask, data, data_is,
					file_name);
					file_name, cookie);
}

/*
Loading