diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-11 13:21:34 -0400 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-11 13:21:34 -0400 | 
| commit | ef4a48c513211d842c55e84f7a1c31884b91dcf7 (patch) | |
| tree | 997ecc4d359a7307d6c0e55ab057fe9f9c2b888e | |
| parent | 90d0c376f5ee1927327b267faf15bf970476f09e (diff) | |
| parent | 1b2b32dcdb3df28dd103033c73cac2417fa05845 (diff) | |
Merge tag 'locks-v3.18-1' of git://git.samba.org/jlayton/linux
Pull file locking related changes from Jeff Layton:
 "This release is a little more busy for file locking changes than the
  last:
   - a set of patches from Kinglong Mee to fix the lockowner handling in
     knfsd
   - a pile of cleanups to the internal file lease API.  This should get
     us a bit closer to allowing for setlease methods that can block.
  There are some dependencies between mine and Bruce's trees this cycle,
  and I based my tree on top of the requisite patches in Bruce's tree"
* tag 'locks-v3.18-1' of git://git.samba.org/jlayton/linux: (26 commits)
  locks: fix fcntl_setlease/getlease return when !CONFIG_FILE_LOCKING
  locks: flock_make_lock should return a struct file_lock (or PTR_ERR)
  locks: set fl_owner for leases to filp instead of current->files
  locks: give lm_break a return value
  locks: __break_lease cleanup in preparation of allowing direct removal of leases
  locks: remove i_have_this_lease check from __break_lease
  locks: move freeing of leases outside of i_lock
  locks: move i_lock acquisition into generic_*_lease handlers
  locks: define a lm_setup handler for leases
  locks: plumb a "priv" pointer into the setlease routines
  nfsd: don't keep a pointer to the lease in nfs4_file
  locks: clean up vfs_setlease kerneldoc comments
  locks: generic_delete_lease doesn't need a file_lock at all
  nfsd: fix potential lease memory leak in nfs4_setlease
  locks: close potential race in lease_get_mtime
  security: make security_file_set_fowner, f_setown and __f_setown void return
  locks: consolidate "nolease" routines
  locks: remove lock_may_read and lock_may_write
  lockd: rip out deferred lock handling from testlock codepath
  NFSD: Get reference of lockowner when coping file_lock
  ...
| -rw-r--r-- | Documentation/filesystems/Locking | 11 | ||||
| -rw-r--r-- | Documentation/filesystems/vfs.txt | 7 | ||||
| -rw-r--r-- | drivers/net/tun.c | 4 | ||||
| -rw-r--r-- | drivers/tty/tty_io.c | 3 | ||||
| -rw-r--r-- | fs/cifs/cifsfs.c | 7 | ||||
| -rw-r--r-- | fs/dlm/plock.c | 8 | ||||
| -rw-r--r-- | fs/fcntl.c | 21 | ||||
| -rw-r--r-- | fs/gfs2/file.c | 22 | ||||
| -rw-r--r-- | fs/libfs.c | 18 | ||||
| -rw-r--r-- | fs/lockd/svclock.c | 68 | ||||
| -rw-r--r-- | fs/locks.c | 444 | ||||
| -rw-r--r-- | fs/nfs/file.c | 13 | ||||
| -rw-r--r-- | fs/nfs/internal.h | 1 | ||||
| -rw-r--r-- | fs/nfs/nfs4file.c | 2 | ||||
| -rw-r--r-- | fs/nfsd/nfs4state.c | 104 | ||||
| -rw-r--r-- | fs/nfsd/state.h | 1 | ||||
| -rw-r--r-- | fs/notify/dnotify/dnotify.c | 8 | ||||
| -rw-r--r-- | include/linux/fs.h | 59 | ||||
| -rw-r--r-- | include/linux/lockd/lockd.h | 1 | ||||
| -rw-r--r-- | include/linux/security.h | 8 | ||||
| -rw-r--r-- | include/trace/events/filelock.h | 14 | ||||
| -rw-r--r-- | net/socket.c | 3 | ||||
| -rw-r--r-- | security/capability.c | 4 | ||||
| -rw-r--r-- | security/security.c | 4 | ||||
| -rw-r--r-- | security/selinux/hooks.c | 4 | ||||
| -rw-r--r-- | security/smack/smack_lsm.c | 3 | 
26 files changed, 354 insertions, 488 deletions
| diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index f1997e9da61f..94d93b1f8b53 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking @@ -464,15 +464,12 @@ prototypes:  			size_t, unsigned int);  	ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *,  			size_t, unsigned int); -	int (*setlease)(struct file *, long, struct file_lock **); +	int (*setlease)(struct file *, long, struct file_lock **, void **);  	long (*fallocate)(struct file *, int, loff_t, loff_t);  };  locking rules: -	All may block except for ->setlease. -	No VFS locks held on entry except for ->setlease. - -->setlease has the file_list_lock held and must not sleep. +	All may block.  ->llseek() locking has moved from llseek to the individual llseek  implementations.  If your fs is not using generic_file_llseek, you @@ -496,6 +493,10 @@ components. And there are other reasons why the current interface is a mess...  ->read on directories probably must go away - we should just enforce -EISDIR  in sys_read() and friends. +->setlease operations should call generic_setlease() before or after setting +the lease within the individual filesystem to record the result of the +operation +  --------------------------- dquot_operations -------------------------------  prototypes:  	int (*write_dquot) (struct dquot *); diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index 61d65cc65c54..8be1ea3bdd5a 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt @@ -826,7 +826,7 @@ struct file_operations {  	int (*flock) (struct file *, int, struct file_lock *);  	ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, size_t, unsigned int);  	ssize_t (*splice_read)(struct file *, struct pipe_inode_info *, size_t, unsigned int); -	int (*setlease)(struct file *, long arg, struct file_lock **); +	int (*setlease)(struct file *, long arg, struct file_lock **, void **);  	long (*fallocate)(struct file *, int mode, loff_t offset, loff_t len);  	int (*show_fdinfo)(struct seq_file *m, struct file *f);  }; @@ -895,8 +895,9 @@ otherwise noted.    splice_read: called by the VFS to splice data from file to a pipe. This  	       method is used by the splice(2) system call -  setlease: called by the VFS to set or release a file lock lease. -	    setlease has the file_lock_lock held and must not sleep. +  setlease: called by the VFS to set or release a file lock lease. setlease +	    implementations should call generic_setlease to record or remove +	    the lease in the inode after setting it.    fallocate: called by the VFS to preallocate blocks or punch a hole. diff --git a/drivers/net/tun.c b/drivers/net/tun.c index acaaf6784179..186ce541c657 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -2152,9 +2152,7 @@ static int tun_chr_fasync(int fd, struct file *file, int on)  		goto out;  	if (on) { -		ret = __f_setown(file, task_pid(current), PIDTYPE_PID, 0); -		if (ret) -			goto out; +		__f_setown(file, task_pid(current), PIDTYPE_PID, 0);  		tfile->flags |= TUN_FASYNC;  	} else  		tfile->flags &= ~TUN_FASYNC; diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 2f6f9b5e4891..16a2c0237dd6 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -2186,8 +2186,9 @@ static int __tty_fasync(int fd, struct file *filp, int on)  		}  		get_pid(pid);  		spin_unlock_irqrestore(&tty->ctrl_lock, flags); -		retval = __f_setown(filp, pid, type, 0); +		__f_setown(filp, pid, type, 0);  		put_pid(pid); +		retval = 0;  	}  out:  	return retval; diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 889b98455750..9d7996e8e793 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -813,7 +813,8 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int whence)  	return generic_file_llseek(file, offset, whence);  } -static int cifs_setlease(struct file *file, long arg, struct file_lock **lease) +static int +cifs_setlease(struct file *file, long arg, struct file_lock **lease, void **priv)  {  	/*  	 * Note that this is called by vfs setlease with i_lock held to @@ -829,7 +830,7 @@ static int cifs_setlease(struct file *file, long arg, struct file_lock **lease)  	if (arg == F_UNLCK ||  	    ((arg == F_RDLCK) && CIFS_CACHE_READ(CIFS_I(inode))) ||  	    ((arg == F_WRLCK) && CIFS_CACHE_WRITE(CIFS_I(inode)))) -		return generic_setlease(file, arg, lease); +		return generic_setlease(file, arg, lease, priv);  	else if (tlink_tcon(cfile->tlink)->local_lease &&  		 !CIFS_CACHE_READ(CIFS_I(inode)))  		/* @@ -840,7 +841,7 @@ static int cifs_setlease(struct file *file, long arg, struct file_lock **lease)  		 * knows that the file won't be changed on the server by anyone  		 * else.  		 */ -		return generic_setlease(file, arg, lease); +		return generic_setlease(file, arg, lease, priv);  	else  		return -EAGAIN;  } diff --git a/fs/dlm/plock.c b/fs/dlm/plock.c index f704458ea5f5..e0ab3a93eeff 100644 --- a/fs/dlm/plock.c +++ b/fs/dlm/plock.c @@ -30,7 +30,7 @@ struct plock_op {  struct plock_xop {  	struct plock_op xop; -	void *callback; +	int (*callback)(struct file_lock *fl, int result);  	void *fl;  	void *file;  	struct file_lock flc; @@ -190,7 +190,7 @@ static int dlm_plock_callback(struct plock_op *op)  	struct file *file;  	struct file_lock *fl;  	struct file_lock *flc; -	int (*notify)(void *, void *, int) = NULL; +	int (*notify)(struct file_lock *fl, int result) = NULL;  	struct plock_xop *xop = (struct plock_xop *)op;  	int rv = 0; @@ -209,7 +209,7 @@ static int dlm_plock_callback(struct plock_op *op)  	notify = xop->callback;  	if (op->info.rv) { -		notify(fl, NULL, op->info.rv); +		notify(fl, op->info.rv);  		goto out;  	} @@ -228,7 +228,7 @@ static int dlm_plock_callback(struct plock_op *op)  			  (unsigned long long)op->info.number, file, fl);  	} -	rv = notify(fl, NULL, 0); +	rv = notify(fl, 0);  	if (rv) {  		/* XXX: We need to cancel the fs lock here: */  		log_print("dlm_plock_callback: lock granted after lock request " diff --git a/fs/fcntl.c b/fs/fcntl.c index 22d1c3df61ac..99d440a4a6ba 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -98,26 +98,19 @@ static void f_modown(struct file *filp, struct pid *pid, enum pid_type type,  	write_unlock_irq(&filp->f_owner.lock);  } -int __f_setown(struct file *filp, struct pid *pid, enum pid_type type, +void __f_setown(struct file *filp, struct pid *pid, enum pid_type type,  		int force)  { -	int err; - -	err = security_file_set_fowner(filp); -	if (err) -		return err; - +	security_file_set_fowner(filp);  	f_modown(filp, pid, type, force); -	return 0;  }  EXPORT_SYMBOL(__f_setown); -int f_setown(struct file *filp, unsigned long arg, int force) +void f_setown(struct file *filp, unsigned long arg, int force)  {  	enum pid_type type;  	struct pid *pid;  	int who = arg; -	int result;  	type = PIDTYPE_PID;  	if (who < 0) {  		type = PIDTYPE_PGID; @@ -125,9 +118,8 @@ int f_setown(struct file *filp, unsigned long arg, int force)  	}  	rcu_read_lock();  	pid = find_vpid(who); -	result = __f_setown(filp, pid, type, force); +	__f_setown(filp, pid, type, force);  	rcu_read_unlock(); -	return result;  }  EXPORT_SYMBOL(f_setown); @@ -181,7 +173,7 @@ static int f_setown_ex(struct file *filp, unsigned long arg)  	if (owner.pid && !pid)  		ret = -ESRCH;  	else -		ret = __f_setown(filp, pid, type, 1); +		 __f_setown(filp, pid, type, 1);  	rcu_read_unlock();  	return ret; @@ -302,7 +294,8 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg,  		force_successful_syscall_return();  		break;  	case F_SETOWN: -		err = f_setown(filp, arg, 1); +		f_setown(filp, arg, 1); +		err = 0;  		break;  	case F_GETOWN_EX:  		err = f_getown_ex(filp, arg); diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index 7f4ed3daa38c..80dd44dca028 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c @@ -914,26 +914,6 @@ out_uninit:  #ifdef CONFIG_GFS2_FS_LOCKING_DLM  /** - * gfs2_setlease - acquire/release a file lease - * @file: the file pointer - * @arg: lease type - * @fl: file lock - * - * We don't currently have a way to enforce a lease across the whole - * cluster; until we do, disable leases (by just returning -EINVAL), - * unless the administrator has requested purely local locking. - * - * Locking: called under i_lock - * - * Returns: errno - */ - -static int gfs2_setlease(struct file *file, long arg, struct file_lock **fl) -{ -	return -EINVAL; -} - -/**   * gfs2_lock - acquire/release a posix lock on a file   * @file: the file pointer   * @cmd: either modify or retrieve lock state, possibly wait @@ -1078,7 +1058,7 @@ const struct file_operations gfs2_file_fops = {  	.flock		= gfs2_flock,  	.splice_read	= generic_file_splice_read,  	.splice_write	= iter_file_splice_write, -	.setlease	= gfs2_setlease, +	.setlease	= simple_nosetlease,  	.fallocate	= gfs2_fallocate,  }; diff --git a/fs/libfs.c b/fs/libfs.c index 88e3e00e2eca..171d2846f2a3 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -1075,3 +1075,21 @@ struct inode *alloc_anon_inode(struct super_block *s)  	return inode;  }  EXPORT_SYMBOL(alloc_anon_inode); + +/** + * simple_nosetlease - generic helper for prohibiting leases + * @filp: file pointer + * @arg: type of lease to obtain + * @flp: new lease supplied for insertion + * @priv: private data for lm_setup operation + * + * Generic helper for filesystems that do not wish to allow leases to be set. + * All arguments are ignored and it just returns -EINVAL. + */ +int +simple_nosetlease(struct file *filp, long arg, struct file_lock **flp, +		  void **priv) +{ +	return -EINVAL; +} +EXPORT_SYMBOL(simple_nosetlease); diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index ab798a88ec1d..13db95f54176 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c @@ -245,7 +245,6 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_host *host,  	block->b_daemon = rqstp->rq_server;  	block->b_host   = host;  	block->b_file   = file; -	block->b_fl = NULL;  	file->f_count++;  	/* Add to file's list of blocks */ @@ -295,7 +294,6 @@ static void nlmsvc_free_block(struct kref *kref)  	nlmsvc_freegrantargs(block->b_call);  	nlmsvc_release_call(block->b_call);  	nlm_release_file(block->b_file); -	kfree(block->b_fl);  	kfree(block);  } @@ -508,7 +506,6 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,  		struct nlm_host *host, struct nlm_lock *lock,  		struct nlm_lock *conflock, struct nlm_cookie *cookie)  { -	struct nlm_block 	*block = NULL;  	int			error;  	__be32			ret; @@ -519,63 +516,26 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,  				(long long)lock->fl.fl_start,  				(long long)lock->fl.fl_end); -	/* Get existing block (in case client is busy-waiting) */ -	block = nlmsvc_lookup_block(file, lock); - -	if (block == NULL) { -		struct file_lock *conf = kzalloc(sizeof(*conf), GFP_KERNEL); - -		if (conf == NULL) -			return nlm_granted; -		block = nlmsvc_create_block(rqstp, host, file, lock, cookie); -		if (block == NULL) { -			kfree(conf); -			return nlm_granted; -		} -		block->b_fl = conf; -	} -	if (block->b_flags & B_QUEUED) { -		dprintk("lockd: nlmsvc_testlock deferred block %p flags %d fl %p\n", -			block, block->b_flags, block->b_fl); -		if (block->b_flags & B_TIMED_OUT) { -			nlmsvc_unlink_block(block); -			ret = nlm_lck_denied; -			goto out; -		} -		if (block->b_flags & B_GOT_CALLBACK) { -			nlmsvc_unlink_block(block); -			if (block->b_fl != NULL -					&& block->b_fl->fl_type != F_UNLCK) { -				lock->fl = *block->b_fl; -				goto conf_lock; -			} else { -				ret = nlm_granted; -				goto out; -			} -		} -		ret = nlm_drop_reply; -		goto out; -	} -  	if (locks_in_grace(SVC_NET(rqstp))) {  		ret = nlm_lck_denied_grace_period;  		goto out;  	} +  	error = vfs_test_lock(file->f_file, &lock->fl); -	if (error == FILE_LOCK_DEFERRED) { -		ret = nlmsvc_defer_lock_rqst(rqstp, block); -		goto out; -	}  	if (error) { +		/* We can't currently deal with deferred test requests */ +		if (error == FILE_LOCK_DEFERRED) +			WARN_ON_ONCE(1); +  		ret = nlm_lck_denied_nolocks;  		goto out;  	} +  	if (lock->fl.fl_type == F_UNLCK) {  		ret = nlm_granted;  		goto out;  	} -conf_lock:  	dprintk("lockd: conflicting lock(ty=%d, %Ld-%Ld)\n",  		lock->fl.fl_type, (long long)lock->fl.fl_start,  		(long long)lock->fl.fl_end); @@ -586,10 +546,9 @@ conf_lock:  	conflock->fl.fl_type = lock->fl.fl_type;  	conflock->fl.fl_start = lock->fl.fl_start;  	conflock->fl.fl_end = lock->fl.fl_end; +	locks_release_private(&lock->fl);  	ret = nlm_lck_denied;  out: -	if (block) -		nlmsvc_release_block(block);  	return ret;  } @@ -660,29 +619,22 @@ nlmsvc_cancel_blocked(struct net *net, struct nlm_file *file, struct nlm_lock *l   * This is a callback from the filesystem for VFS file lock requests.   * It will be used if lm_grant is defined and the filesystem can not   * respond to the request immediately. - * For GETLK request it will copy the reply to the nlm_block.   * For SETLK or SETLKW request it will get the local posix lock.   * In all cases it will move the block to the head of nlm_blocked q where   * nlmsvc_retry_blocked() can send back a reply for SETLKW or revisit the   * deferred rpc for GETLK and SETLK.   */  static void -nlmsvc_update_deferred_block(struct nlm_block *block, struct file_lock *conf, -			     int result) +nlmsvc_update_deferred_block(struct nlm_block *block, int result)  {  	block->b_flags |= B_GOT_CALLBACK;  	if (result == 0)  		block->b_granted = 1;  	else  		block->b_flags |= B_TIMED_OUT; -	if (conf) { -		if (block->b_fl) -			__locks_copy_lock(block->b_fl, conf); -	}  } -static int nlmsvc_grant_deferred(struct file_lock *fl, struct file_lock *conf, -					int result) +static int nlmsvc_grant_deferred(struct file_lock *fl, int result)  {  	struct nlm_block *block;  	int rc = -ENOENT; @@ -697,7 +649,7 @@ static int nlmsvc_grant_deferred(struct file_lock *fl, struct file_lock *conf,  					rc = -ENOLCK;  					break;  				} -				nlmsvc_update_deferred_block(block, conf, result); +				nlmsvc_update_deferred_block(block, result);  			} else if (result == 0)  				block->b_granted = 1; diff --git a/fs/locks.c b/fs/locks.c index bb08857f90b5..735b8d3fa78c 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -230,8 +230,12 @@ void locks_release_private(struct file_lock *fl)  			fl->fl_ops->fl_release_private(fl);  		fl->fl_ops = NULL;  	} -	fl->fl_lmops = NULL; +	if (fl->fl_lmops) { +		if (fl->fl_lmops->lm_put_owner) +			fl->fl_lmops->lm_put_owner(fl); +		fl->fl_lmops = NULL; +	}  }  EXPORT_SYMBOL_GPL(locks_release_private); @@ -267,21 +271,10 @@ void locks_init_lock(struct file_lock *fl)  EXPORT_SYMBOL(locks_init_lock); -static void locks_copy_private(struct file_lock *new, struct file_lock *fl) -{ -	if (fl->fl_ops) { -		if (fl->fl_ops->fl_copy_lock) -			fl->fl_ops->fl_copy_lock(new, fl); -		new->fl_ops = fl->fl_ops; -	} -	if (fl->fl_lmops) -		new->fl_lmops = fl->fl_lmops; -} -  /*   * Initialize a new lock from an existing file_lock structure.   */ -void __locks_copy_lock(struct file_lock *new, const struct file_lock *fl) +void locks_copy_conflock(struct file_lock *new, struct file_lock *fl)  {  	new->fl_owner = fl->fl_owner;  	new->fl_pid = fl->fl_pid; @@ -290,22 +283,30 @@ void __locks_copy_lock(struct file_lock *new, const struct file_lock *fl)  	new->fl_type = fl->fl_type;  	new->fl_start = fl->fl_start;  	new->fl_end = fl->fl_end; +	new->fl_lmops = fl->fl_lmops;  	new->fl_ops = NULL; -	new->fl_lmops = NULL; + +	if (fl->fl_lmops) { +		if (fl->fl_lmops->lm_get_owner) +			fl->fl_lmops->lm_get_owner(new, fl); +	}  } -EXPORT_SYMBOL(__locks_copy_lock); +EXPORT_SYMBOL(locks_copy_conflock);  void locks_copy_lock(struct file_lock *new, struct file_lock *fl)  {  	/* "new" must be a freshly-initialized lock */  	WARN_ON_ONCE(new->fl_ops); -	__locks_copy_lock(new, fl); +	locks_copy_conflock(new, fl); +  	new->fl_file = fl->fl_file;  	new->fl_ops = fl->fl_ops; -	new->fl_lmops = fl->fl_lmops; -	locks_copy_private(new, fl); +	if (fl->fl_ops) { +		if (fl->fl_ops->fl_copy_lock) +			fl->fl_ops->fl_copy_lock(new, fl); +	}  }  EXPORT_SYMBOL(locks_copy_lock); @@ -325,17 +326,18 @@ static inline int flock_translate_cmd(int cmd) {  }  /* Fill in a file_lock structure with an appropriate FLOCK lock. */ -static int flock_make_lock(struct file *filp, struct file_lock **lock, -		unsigned int cmd) +static struct file_lock * +flock_make_lock(struct file *filp, unsigned int cmd)  {  	struct file_lock *fl;  	int type = flock_translate_cmd(cmd); +  	if (type < 0) -		return type; +		return ERR_PTR(type);  	fl = locks_alloc_lock();  	if (fl == NULL) -		return -ENOMEM; +		return ERR_PTR(-ENOMEM);  	fl->fl_file = filp;  	fl->fl_owner = filp; @@ -344,8 +346,7 @@ static int flock_make_lock(struct file *filp, struct file_lock **lock,  	fl->fl_type = type;  	fl->fl_end = OFFSET_MAX; -	*lock = fl; -	return 0; +	return fl;  }  static int assign_type(struct file_lock *fl, long type) @@ -426,14 +427,34 @@ static int flock_to_posix_lock(struct file *filp, struct file_lock *fl,  }  /* default lease lock manager operations */ -static void lease_break_callback(struct file_lock *fl) +static bool +lease_break_callback(struct file_lock *fl)  {  	kill_fasync(&fl->fl_fasync, SIGIO, POLL_MSG); +	return false; +} + +static void +lease_setup(struct file_lock *fl, void **priv) +{ +	struct file *filp = fl->fl_file; +	struct fasync_struct *fa = *priv; + +	/* +	 * fasync_insert_entry() returns the old entry if any. If there was no +	 * old entry, then it used "priv" and inserted it into the fasync list. +	 * Clear the pointer to indicate that it shouldn't be freed. +	 */ +	if (!fasync_insert_entry(fa->fa_fd, filp, &fl->fl_fasync, fa)) +		*priv = NULL; + +	__f_setown(filp, task_pid(current), PIDTYPE_PID, 0);  }  static const struct lock_manager_operations lease_manager_ops = {  	.lm_break = lease_break_callback,  	.lm_change = lease_modify, +	.lm_setup = lease_setup,  };  /* @@ -444,7 +465,7 @@ static int lease_init(struct file *filp, long type, struct file_lock *fl)  	if (assign_type(fl, type) != 0)  		return -EINVAL; -	fl->fl_owner = current->files; +	fl->fl_owner = filp;  	fl->fl_pid = current->tgid;  	fl->fl_file = filp; @@ -735,7 +756,7 @@ posix_test_lock(struct file *filp, struct file_lock *fl)  			break;  	}  	if (cfl) { -		__locks_copy_lock(fl, cfl); +		locks_copy_conflock(fl, cfl);  		if (cfl->fl_nspid)  			fl->fl_pid = pid_vnr(cfl->fl_nspid);  	} else @@ -941,7 +962,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str  			if (!posix_locks_conflict(request, fl))  				continue;  			if (conflock) -				__locks_copy_lock(conflock, fl); +				locks_copy_conflock(conflock, fl);  			error = -EAGAIN;  			if (!(request->fl_flags & FL_SLEEP))  				goto out; @@ -1273,7 +1294,7 @@ static void lease_clear_pending(struct file_lock *fl, int arg)  }  /* We already had a lease on this file; just change its type */ -int lease_modify(struct file_lock **before, int arg) +int lease_modify(struct file_lock **before, int arg, struct list_head *dispose)  {  	struct file_lock *fl = *before;  	int error = assign_type(fl, arg); @@ -1292,11 +1313,10 @@ int lease_modify(struct file_lock **before, int arg)  			printk(KERN_ERR "locks_delete_lock: fasync == %p\n", fl->fl_fasync);  			fl->fl_fasync = NULL;  		} -		locks_delete_lock(before, NULL); +		locks_delete_lock(before, dispose);  	}  	return 0;  } -  EXPORT_SYMBOL(lease_modify);  static bool past_time(unsigned long then) @@ -1307,18 +1327,20 @@ static bool past_time(unsigned long then)  	return time_after(jiffies, then);  } -static void time_out_leases(struct inode *inode) +static void time_out_leases(struct inode *inode, struct list_head *dispose)  {  	struct file_lock **before;  	struct file_lock *fl; +	lockdep_assert_held(&inode->i_lock); +  	before = &inode->i_flock;  	while ((fl = *before) && IS_LEASE(fl) && lease_breaking(fl)) {  		trace_time_out_leases(inode, fl);  		if (past_time(fl->fl_downgrade_time)) -			lease_modify(before, F_RDLCK); +			lease_modify(before, F_RDLCK, dispose);  		if (past_time(fl->fl_break_time)) -			lease_modify(before, F_UNLCK); +			lease_modify(before, F_UNLCK, dispose);  		if (fl == *before)	/* lease_modify may have freed fl */  			before = &fl->fl_next;  	} @@ -1331,6 +1353,20 @@ static bool leases_conflict(struct file_lock *lease, struct file_lock *breaker)  	return locks_conflict(breaker, lease);  } +static bool +any_leases_conflict(struct inode *inode, struct file_lock *breaker) +{ +	struct file_lock *fl; + +	lockdep_assert_held(&inode->i_lock); + +	for (fl = inode->i_flock ; fl && IS_LEASE(fl); fl = fl->fl_next) { +		if (leases_conflict(fl, breaker)) +			return true; +	} +	return false; +} +  /**   *	__break_lease	-	revoke all outstanding leases on file   *	@inode: the inode of the file to return @@ -1347,12 +1383,11 @@ static bool leases_conflict(struct file_lock *lease, struct file_lock *breaker)  int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)  {  	int error = 0; -	struct file_lock *new_fl, *flock; -	struct file_lock *fl; +	struct file_lock *new_fl; +	struct file_lock *fl, **before;  	unsigned long break_time; -	int i_have_this_lease = 0; -	bool lease_conflict = false;  	int want_write = (mode & O_ACCMODE) != O_RDONLY; +	LIST_HEAD(dispose);  	new_fl = lease_alloc(NULL, want_write ? F_WRLCK : F_RDLCK);  	if (IS_ERR(new_fl)) @@ -1361,20 +1396,9 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)  	spin_lock(&inode->i_lock); -	time_out_leases(inode); - -	flock = inode->i_flock; -	if ((flock == NULL) || !IS_LEASE(flock)) -		goto out; +	time_out_leases(inode, &dispose); -	for (fl = flock; fl && IS_LEASE(fl); fl = fl->fl_next) { -		if (leases_conflict(fl, new_fl)) { -			lease_conflict = true; -			if (fl->fl_owner == current->files) -				i_have_this_lease = 1; -		} -	} -	if (!lease_conflict) +	if (!any_leases_conflict(inode, new_fl))  		goto out;  	break_time = 0; @@ -1384,7 +1408,9 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)  			break_time++;	/* so that 0 means no break time */  	} -	for (fl = flock; fl && IS_LEASE(fl); fl = fl->fl_next) { +	for (before = &inode->i_flock; +			((fl = *before) != NULL) && IS_LEASE(fl); +			before = &fl->fl_next) {  		if (!leases_conflict(fl, new_fl))  			continue;  		if (want_write) { @@ -1393,51 +1419,56 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)  			fl->fl_flags |= FL_UNLOCK_PENDING;  			fl->fl_break_time = break_time;  		} else { -			if (lease_breaking(flock)) +			if (lease_breaking(inode->i_flock))  				continue;  			fl->fl_flags |= FL_DOWNGRADE_PENDING;  			fl->fl_downgrade_time = break_time;  		} -		fl->fl_lmops->lm_break(fl); +		if (fl->fl_lmops->lm_break(fl)) +			locks_delete_lock(before, &dispose);  	} -	if (i_have_this_lease || (mode & O_NONBLOCK)) { +	fl = inode->i_flock; +	if (!fl || !IS_LEASE(fl)) +		goto out; + +	if (mode & O_NONBLOCK) {  		trace_break_lease_noblock(inode, new_fl);  		error = -EWOULDBLOCK;  		goto out;  	}  restart: -	break_time = flock->fl_break_time; +	break_time = inode->i_flock->fl_break_time;  	if (break_time != 0)  		break_time -= jiffies;  	if (break_time == 0)  		break_time++; -	locks_insert_block(flock, new_fl); +	locks_insert_block(inode->i_flock, new_fl);  	trace_break_lease_block(inode, new_fl);  	spin_unlock(&inode->i_lock); +	locks_dispose_list(&dispose);  	error = wait_event_interruptible_timeout(new_fl->fl_wait,  						!new_fl->fl_next, break_time);  	spin_lock(&inode->i_lock);  	trace_break_lease_unblock(inode, new_fl);  	locks_delete_block(new_fl);  	if (error >= 0) { -		if (error == 0) -			time_out_leases(inode);  		/*  		 * Wait for the next conflicting lease that has not been  		 * broken yet  		 */ -		for (flock = inode->i_flock; flock && IS_LEASE(flock); -				flock = flock->fl_next) { -			if (leases_conflict(new_fl, flock)) -				goto restart; -		} +		if (error == 0) +			time_out_leases(inode, &dispose); +		if (any_leases_conflict(inode, new_fl)) +			goto restart; +  		error = 0;  	}  out:  	spin_unlock(&inode->i_lock); +	locks_dispose_list(&dispose);  	locks_free_lock(new_fl);  	return error;  } @@ -1455,8 +1486,18 @@ EXPORT_SYMBOL(__break_lease);   */  void lease_get_mtime(struct inode *inode, struct timespec *time)  { -	struct file_lock *flock = inode->i_flock; -	if (flock && IS_LEASE(flock) && (flock->fl_type == F_WRLCK)) +	bool has_lease = false; +	struct file_lock *flock; + +	if (inode->i_flock) { +		spin_lock(&inode->i_lock); +		flock = inode->i_flock; +		if (flock && IS_LEASE(flock) && (flock->fl_type == F_WRLCK)) +			has_lease = true; +		spin_unlock(&inode->i_lock); +	} + +	if (has_lease)  		*time = current_fs_time(inode->i_sb);  	else  		*time = inode->i_mtime; @@ -1492,9 +1533,10 @@ int fcntl_getlease(struct file *filp)  	struct file_lock *fl;  	struct inode *inode = file_inode(filp);  	int type = F_UNLCK; +	LIST_HEAD(dispose);  	spin_lock(&inode->i_lock); -	time_out_leases(file_inode(filp)); +	time_out_leases(file_inode(filp), &dispose);  	for (fl = file_inode(filp)->i_flock; fl && IS_LEASE(fl);  			fl = fl->fl_next) {  		if (fl->fl_file == filp) { @@ -1503,6 +1545,7 @@ int fcntl_getlease(struct file *filp)  		}  	}  	spin_unlock(&inode->i_lock); +	locks_dispose_list(&dispose);  	return type;  } @@ -1532,13 +1575,15 @@ check_conflicting_open(const struct dentry *dentry, const long arg)  	return ret;  } -static int generic_add_lease(struct file *filp, long arg, struct file_lock **flp) +static int +generic_add_lease(struct file *filp, long arg, struct file_lock **flp, void **priv)  {  	struct file_lock *fl, **before, **my_before = NULL, *lease;  	struct dentry *dentry = filp->f_path.dentry;  	struct inode *inode = dentry->d_inode;  	bool is_deleg = (*flp)->fl_flags & FL_DELEG;  	int error; +	LIST_HEAD(dispose);  	lease = *flp;  	trace_generic_add_lease(inode, lease); @@ -1561,6 +1606,8 @@ static int generic_add_lease(struct file *filp, long arg, struct file_lock **flp  		return -EINVAL;  	} +	spin_lock(&inode->i_lock); +	time_out_leases(inode, &dispose);  	error = check_conflicting_open(dentry, arg);  	if (error)  		goto out; @@ -1596,10 +1643,11 @@ static int generic_add_lease(struct file *filp, long arg, struct file_lock **flp  	}  	if (my_before != NULL) { -		error = lease->fl_lmops->lm_change(my_before, arg); -		if (!error) -			*flp = *my_before; -		goto out; +		lease = *my_before; +		error = lease->fl_lmops->lm_change(my_before, arg, &dispose); +		if (error) +			goto out; +		goto out_setup;  	}  	error = -EINVAL; @@ -1619,43 +1667,61 @@ static int generic_add_lease(struct file *filp, long arg, struct file_lock **flp  	smp_mb();  	error = check_conflicting_open(dentry, arg);  	if (error) -		locks_unlink_lock(before); +		goto out_unlink; + +out_setup: +	if (lease->fl_lmops->lm_setup) +		lease->fl_lmops->lm_setup(lease, priv);  out: +	spin_unlock(&inode->i_lock); +	locks_dispose_list(&dispose);  	if (is_deleg)  		mutex_unlock(&inode->i_mutex); +	if (!error && !my_before) +		*flp = NULL;  	return error; +out_unlink: +	locks_unlink_lock(before); +	goto out;  } -static int generic_delete_lease(struct file *filp, struct file_lock **flp) +static int generic_delete_lease(struct file *filp)  { +	int error = -EAGAIN;  	struct file_lock *fl, **before;  	struct dentry *dentry = filp->f_path.dentry;  	struct inode *inode = dentry->d_inode; +	LIST_HEAD(dispose); -	trace_generic_delete_lease(inode, *flp); - +	spin_lock(&inode->i_lock); +	time_out_leases(inode, &dispose);  	for (before = &inode->i_flock;  			((fl = *before) != NULL) && IS_LEASE(fl);  			before = &fl->fl_next) { -		if (fl->fl_file != filp) -			continue; -		return (*flp)->fl_lmops->lm_change(before, F_UNLCK); +		if (fl->fl_file == filp) +			break;  	} -	return -EAGAIN; +	trace_generic_delete_lease(inode, fl); +	if (fl) +		error = fl->fl_lmops->lm_change(before, F_UNLCK, &dispose); +	spin_unlock(&inode->i_lock); +	locks_dispose_list(&dispose); +	return error;  }  /**   *	generic_setlease	-	sets a lease on an open file - *	@filp: file pointer - *	@arg: type of lease to obtain - *	@flp: input - file_lock to use, output - file_lock inserted + *	@filp:	file pointer + *	@arg:	type of lease to obtain + *	@flp:	input - file_lock to use, output - file_lock inserted + *	@priv:	private data for lm_setup (may be NULL if lm_setup + *		doesn't require it)   *   *	The (input) flp->fl_lmops->lm_break function is required   *	by break_lease(). - * - *	Called with inode->i_lock held.   */ -int generic_setlease(struct file *filp, long arg, struct file_lock **flp) +int generic_setlease(struct file *filp, long arg, struct file_lock **flp, +			void **priv)  {  	struct dentry *dentry = filp->f_path.dentry;  	struct inode *inode = dentry->d_inode; @@ -1669,83 +1735,52 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)  	if (error)  		return error; -	time_out_leases(inode); - -	BUG_ON(!(*flp)->fl_lmops->lm_break); -  	switch (arg) {  	case F_UNLCK: -		return generic_delete_lease(filp, flp); +		return generic_delete_lease(filp);  	case F_RDLCK:  	case F_WRLCK: -		return generic_add_lease(filp, arg, flp); +		if (!(*flp)->fl_lmops->lm_break) { +			WARN_ON_ONCE(1); +			return -ENOLCK; +		} +		return generic_add_lease(filp, arg, flp, priv);  	default:  		return -EINVAL;  	}  }  EXPORT_SYMBOL(generic_setlease); -static int __vfs_setlease(struct file *filp, long arg, struct file_lock **lease) -{ -	if (filp->f_op->setlease) -		return filp->f_op->setlease(filp, arg, lease); -	else -		return generic_setlease(filp, arg, lease); -} -  /** - *	vfs_setlease        -       sets a lease on an open file - *	@filp: file pointer - *	@arg: type of lease to obtain - *	@lease: file_lock to use - * - *	Call this to establish a lease on the file. - *	The (*lease)->fl_lmops->lm_break operation must be set; if not, - *	break_lease will oops! - * - *	This will call the filesystem's setlease file method, if - *	defined.  Note that there is no getlease method; instead, the - *	filesystem setlease method should call back to setlease() to - *	add a lease to the inode's lease list, where fcntl_getlease() can - *	find it.  Since fcntl_getlease() only reports whether the current - *	task holds a lease, a cluster filesystem need only do this for - *	leases held by processes on this node. - * - *	There is also no break_lease method; filesystems that - *	handle their own leases should break leases themselves from the - *	filesystem's open, create, and (on truncate) setattr methods. - * - *	Warning: the only current setlease methods exist only to disable - *	leases in certain cases.  More vfs changes may be required to - *	allow a full filesystem lease implementation. + * vfs_setlease        -       sets a lease on an open file + * @filp:	file pointer + * @arg:	type of lease to obtain + * @lease:	file_lock to use when adding a lease + * @priv:	private info for lm_setup when adding a lease (may be + * 		NULL if lm_setup doesn't require it) + * + * Call this to establish a lease on the file. The "lease" argument is not + * used for F_UNLCK requests and may be NULL. For commands that set or alter + * an existing lease, the (*lease)->fl_lmops->lm_break operation must be set; + * if not, this function will return -ENOLCK (and generate a scary-looking + * stack trace). + * + * The "priv" pointer is passed directly to the lm_setup function as-is. It + * may be NULL if the lm_setup operation doesn't require it.   */ - -int vfs_setlease(struct file *filp, long arg, struct file_lock **lease) +int +vfs_setlease(struct file *filp, long arg, struct file_lock **lease, void **priv)  { -	struct inode *inode = file_inode(filp); -	int error; - -	spin_lock(&inode->i_lock); -	error = __vfs_setlease(filp, arg, lease); -	spin_unlock(&inode->i_lock); - -	return error; +	if (filp->f_op->setlease) +		return filp->f_op->setlease(filp, arg, lease, priv); +	else +		return generic_setlease(filp, arg, lease, priv);  }  EXPORT_SYMBOL_GPL(vfs_setlease); -static int do_fcntl_delete_lease(struct file *filp) -{ -	struct file_lock fl, *flp = &fl; - -	lease_init(filp, F_UNLCK, flp); - -	return vfs_setlease(filp, F_UNLCK, &flp); -} -  static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg)  { -	struct file_lock *fl, *ret; -	struct inode *inode = file_inode(filp); +	struct file_lock *fl;  	struct fasync_struct *new;  	int error; @@ -1758,26 +1793,9 @@ static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg)  		locks_free_lock(fl);  		return -ENOMEM;  	} -	ret = fl; -	spin_lock(&inode->i_lock); -	error = __vfs_setlease(filp, arg, &ret); -	if (error) -		goto out_unlock; -	if (ret == fl) -		fl = NULL; - -	/* -	 * fasync_insert_entry() returns the old entry if any. -	 * If there was no old entry, then it used 'new' and -	 * inserted it into the fasync list. Clear new so that -	 * we don't release it here. -	 */ -	if (!fasync_insert_entry(fd, filp, &ret->fl_fasync, new)) -		new = NULL; +	new->fa_fd = fd; -	error = __f_setown(filp, task_pid(current), PIDTYPE_PID, 0); -out_unlock: -	spin_unlock(&inode->i_lock); +	error = vfs_setlease(filp, arg, &fl, (void **)&new);  	if (fl)  		locks_free_lock(fl);  	if (new) @@ -1798,7 +1816,7 @@ out_unlock:  int fcntl_setlease(unsigned int fd, struct file *filp, long arg)  {  	if (arg == F_UNLCK) -		return do_fcntl_delete_lease(filp); +		return vfs_setlease(filp, F_UNLCK, NULL, NULL);  	return do_fcntl_add_lease(fd, filp, arg);  } @@ -1867,9 +1885,12 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd)  	    !(f.file->f_mode & (FMODE_READ|FMODE_WRITE)))  		goto out_putf; -	error = flock_make_lock(f.file, &lock, cmd); -	if (error) +	lock = flock_make_lock(f.file, cmd); +	if (IS_ERR(lock)) { +		error = PTR_ERR(lock);  		goto out_putf; +	} +  	if (can_sleep)  		lock->fl_flags |= FL_SLEEP; @@ -1981,11 +2002,13 @@ int fcntl_getlk(struct file *filp, unsigned int cmd, struct flock __user *l)  	if (file_lock.fl_type != F_UNLCK) {  		error = posix_lock_to_flock(&flock, &file_lock);  		if (error) -			goto out; +			goto rel_priv;  	}  	error = -EFAULT;  	if (!copy_to_user(l, &flock, sizeof(flock)))  		error = 0; +rel_priv: +	locks_release_private(&file_lock);  out:  	return error;  } @@ -2206,7 +2229,8 @@ int fcntl_getlk64(struct file *filp, unsigned int cmd, struct flock64 __user *l)  	error = -EFAULT;  	if (!copy_to_user(l, &flock, sizeof(flock)))  		error = 0; -   + +	locks_release_private(&file_lock);  out:  	return error;  } @@ -2369,7 +2393,7 @@ void locks_remove_file(struct file *filp)  	while ((fl = *before) != NULL) {  		if (fl->fl_file == filp) {  			if (IS_LEASE(fl)) { -				lease_modify(before, F_UNLCK); +				lease_modify(before, F_UNLCK, &dispose);  				continue;  			} @@ -2593,86 +2617,6 @@ static int __init proc_locks_init(void)  module_init(proc_locks_init);  #endif -/** - *	lock_may_read - checks that the region is free of locks - *	@inode: the inode that is being read - *	@start: the first byte to read - *	@len: the number of bytes to read - * - *	Emulates Windows locking requirements.  Whole-file - *	mandatory locks (share modes) can prohibit a read and - *	byte-range POSIX locks can prohibit a read if they overlap. - * - *	N.B. this function is only ever called - *	from knfsd and ownership of locks is never checked. - */ -int lock_may_read(struct inode *inode, loff_t start, unsigned long len) -{ -	struct file_lock *fl; -	int result = 1; - -	spin_lock(&inode->i_lock); -	for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { -		if (IS_POSIX(fl)) { -			if (fl->fl_type == F_RDLCK) -				continue; -			if ((fl->fl_end < start) || (fl->fl_start > (start + len))) -				continue; -		} else if (IS_FLOCK(fl)) { -			if (!(fl->fl_type & LOCK_MAND)) -				continue; -			if (fl->fl_type & LOCK_READ) -				continue; -		} else -			continue; -		result = 0; -		break; -	} -	spin_unlock(&inode->i_lock); -	return result; -} - -EXPORT_SYMBOL(lock_may_read); - -/** - *	lock_may_write - checks that the region is free of locks - *	@inode: the inode that is being written - *	@start: the first byte to write - *	@len: the number of bytes to write - * - *	Emulates Windows locking requirements.  Whole-file - *	mandatory locks (share modes) can prohibit a write and - *	byte-range POSIX locks can prohibit a write if they overlap. - * - *	N.B. this function is only ever called - *	from knfsd and ownership of locks is never checked. - */ -int lock_may_write(struct inode *inode, loff_t start, unsigned long len) -{ -	struct file_lock *fl; -	int result = 1; - -	spin_lock(&inode->i_lock); -	for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { -		if (IS_POSIX(fl)) { -			if ((fl->fl_end < start) || (fl->fl_start > (start + len))) -				continue; -		} else if (IS_FLOCK(fl)) { -			if (!(fl->fl_type & LOCK_MAND)) -				continue; -			if (fl->fl_type & LOCK_WRITE) -				continue; -		} else -			continue; -		result = 0; -		break; -	} -	spin_unlock(&inode->i_lock); -	return result; -} - -EXPORT_SYMBOL(lock_may_write); -  static int __init filelock_init(void)  {  	int i; diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 6920127c5eb7..4ea92ce0537f 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -919,17 +919,6 @@ int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)  }  EXPORT_SYMBOL_GPL(nfs_flock); -/* - * There is no protocol support for leases, so we have no way to implement - * them correctly in the face of opens by other clients. - */ -int nfs_setlease(struct file *file, long arg, struct file_lock **fl) -{ -	dprintk("NFS: setlease(%pD2, arg=%ld)\n", file, arg); -	return -EINVAL; -} -EXPORT_SYMBOL_GPL(nfs_setlease); -  const struct file_operations nfs_file_operations = {  	.llseek		= nfs_file_llseek,  	.read		= new_sync_read, @@ -946,6 +935,6 @@ const struct file_operations nfs_file_operations = {  	.splice_read	= nfs_file_splice_read,  	.splice_write	= iter_file_splice_write,  	.check_flags	= nfs_check_flags, -	.setlease	= nfs_setlease, +	.setlease	= simple_nosetlease,  };  EXPORT_SYMBOL_GPL(nfs_file_operations); diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 14ae6f20a172..efaa31c70fbe 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -339,7 +339,6 @@ int nfs_file_release(struct inode *, struct file *);  int nfs_lock(struct file *, int, struct file_lock *);  int nfs_flock(struct file *, int, struct file_lock *);  int nfs_check_flags(int); -int nfs_setlease(struct file *, long, struct file_lock **);  /* inode.c */  extern struct workqueue_struct *nfsiod_workqueue; diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c index a816f0627a6c..3e987ad9ae25 100644 --- a/fs/nfs/nfs4file.c +++ b/fs/nfs/nfs4file.c @@ -131,5 +131,5 @@ const struct file_operations nfs4_file_operations = {  	.splice_read	= nfs_file_splice_read,  	.splice_write	= iter_file_splice_write,  	.check_flags	= nfs_check_flags, -	.setlease	= nfs_setlease, +	.setlease	= simple_nosetlease,  }; diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 5c0cac173068..e9c3afe4b5d3 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -218,6 +218,13 @@ static void nfsd4_put_session(struct nfsd4_session *ses)  	spin_unlock(&nn->client_lock);  } +static inline struct nfs4_stateowner * +nfs4_get_stateowner(struct nfs4_stateowner *sop) +{ +	atomic_inc(&sop->so_count); +	return sop; +} +  static int  same_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner)  { @@ -237,10 +244,8 @@ find_openstateowner_str_locked(unsigned int hashval, struct nfsd4_open *open,  			    so_strhash) {  		if (!so->so_is_open_owner)  			continue; -		if (same_owner_str(so, &open->op_owner)) { -			atomic_inc(&so->so_count); -			return openowner(so); -		} +		if (same_owner_str(so, &open->op_owner)) +			return openowner(nfs4_get_stateowner(so));  	}  	return NULL;  } @@ -678,18 +683,14 @@ nfs4_put_stid(struct nfs4_stid *s)  static void nfs4_put_deleg_lease(struct nfs4_file *fp)  {  	struct file *filp = NULL; -	struct file_lock *fl;  	spin_lock(&fp->fi_lock); -	if (fp->fi_lease && atomic_dec_and_test(&fp->fi_delegees)) { +	if (fp->fi_deleg_file && atomic_dec_and_test(&fp->fi_delegees))  		swap(filp, fp->fi_deleg_file); -		fl = fp->fi_lease; -		fp->fi_lease = NULL; -	}  	spin_unlock(&fp->fi_lock);  	if (filp) { -		vfs_setlease(filp, F_UNLCK, &fl); +		vfs_setlease(filp, F_UNLCK, NULL, NULL);  		fput(filp);  	}  } @@ -1655,7 +1656,7 @@ __destroy_client(struct nfs4_client *clp)  	}  	while (!list_empty(&clp->cl_openowners)) {  		oo = list_entry(clp->cl_openowners.next, struct nfs4_openowner, oo_perclient); -		atomic_inc(&oo->oo_owner.so_count); +		nfs4_get_stateowner(&oo->oo_owner);  		release_openowner(oo);  	}  	nfsd4_shutdown_callback(clp); @@ -3067,8 +3068,8 @@ static void nfsd4_init_file(struct nfs4_file *fp, struct knfsd_fh *fh)  	INIT_LIST_HEAD(&fp->fi_stateids);  	INIT_LIST_HEAD(&fp->fi_delegations);  	fh_copy_shallow(&fp->fi_fhandle, fh); +	fp->fi_deleg_file = NULL;  	fp->fi_had_conflict = false; -	fp->fi_lease = NULL;  	fp->fi_share_deny = 0;  	memset(fp->fi_fds, 0, sizeof(fp->fi_fds));  	memset(fp->fi_access, 0, sizeof(fp->fi_access)); @@ -3136,8 +3137,7 @@ static void nfsd4_cstate_assign_replay(struct nfsd4_compound_state *cstate,  {  	if (!nfsd4_has_session(cstate)) {  		mutex_lock(&so->so_replay.rp_mutex); -		cstate->replay_owner = so; -		atomic_inc(&so->so_count); +		cstate->replay_owner = nfs4_get_stateowner(so);  	}  } @@ -3236,8 +3236,7 @@ static void init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp,  	atomic_inc(&stp->st_stid.sc_count);  	stp->st_stid.sc_type = NFS4_OPEN_STID;  	INIT_LIST_HEAD(&stp->st_locks); -	stp->st_stateowner = &oo->oo_owner; -	atomic_inc(&stp->st_stateowner->so_count); +	stp->st_stateowner = nfs4_get_stateowner(&oo->oo_owner);  	get_nfs4_file(fp);  	stp->st_stid.sc_file = fp;  	stp->st_access_bmap = 0; @@ -3434,18 +3433,20 @@ static void nfsd_break_one_deleg(struct nfs4_delegation *dp)  }  /* Called from break_lease() with i_lock held. */ -static void nfsd_break_deleg_cb(struct file_lock *fl) +static bool +nfsd_break_deleg_cb(struct file_lock *fl)  { +	bool ret = false;  	struct nfs4_file *fp = (struct nfs4_file *)fl->fl_owner;  	struct nfs4_delegation *dp;  	if (!fp) {  		WARN(1, "(%p)->fl_owner NULL\n", fl); -		return; +		return ret;  	}  	if (fp->fi_had_conflict) {  		WARN(1, "duplicate break on %p\n", fp); -		return; +		return ret;  	}  	/*  	 * We don't want the locks code to timeout the lease for us; @@ -3457,24 +3458,23 @@ static void nfsd_break_deleg_cb(struct file_lock *fl)  	spin_lock(&fp->fi_lock);  	fp->fi_had_conflict = true;  	/* -	 * If there are no delegations on the list, then we can't count on this -	 * lease ever being cleaned up. Set the fl_break_time to jiffies so that -	 * time_out_leases will do it ASAP. The fact that fi_had_conflict is now -	 * true should keep any new delegations from being hashed. +	 * If there are no delegations on the list, then return true +	 * so that the lease code will go ahead and delete it.  	 */  	if (list_empty(&fp->fi_delegations)) -		fl->fl_break_time = jiffies; +		ret = true;  	else  		list_for_each_entry(dp, &fp->fi_delegations, dl_perfile)  			nfsd_break_one_deleg(dp);  	spin_unlock(&fp->fi_lock); +	return ret;  } -static -int nfsd_change_deleg_cb(struct file_lock **onlist, int arg) +static int +nfsd_change_deleg_cb(struct file_lock **onlist, int arg, struct list_head *dispose)  {  	if (arg & F_UNLCK) -		return lease_modify(onlist, arg); +		return lease_modify(onlist, arg, dispose);  	else  		return -EAGAIN;  } @@ -3820,7 +3820,7 @@ static struct file_lock *nfs4_alloc_init_lease(struct nfs4_file *fp, int flag)  static int nfs4_setlease(struct nfs4_delegation *dp)  {  	struct nfs4_file *fp = dp->dl_stid.sc_file; -	struct file_lock *fl; +	struct file_lock *fl, *ret;  	struct file *filp;  	int status = 0; @@ -3834,11 +3834,12 @@ static int nfs4_setlease(struct nfs4_delegation *dp)  		return -EBADF;  	}  	fl->fl_file = filp; -	status = vfs_setlease(filp, fl->fl_type, &fl); -	if (status) { +	ret = fl; +	status = vfs_setlease(filp, fl->fl_type, &fl, NULL); +	if (fl)  		locks_free_lock(fl); +	if (status)  		goto out_fput; -	}  	spin_lock(&state_lock);  	spin_lock(&fp->fi_lock);  	/* Did the lease get broken before we took the lock? */ @@ -3846,13 +3847,12 @@ static int nfs4_setlease(struct nfs4_delegation *dp)  	if (fp->fi_had_conflict)  		goto out_unlock;  	/* Race breaker */ -	if (fp->fi_lease) { +	if (fp->fi_deleg_file) {  		status = 0;  		atomic_inc(&fp->fi_delegees);  		hash_delegation_locked(dp, fp);  		goto out_unlock;  	} -	fp->fi_lease = fl;  	fp->fi_deleg_file = filp;  	atomic_set(&fp->fi_delegees, 1);  	hash_delegation_locked(dp, fp); @@ -3885,7 +3885,7 @@ nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh,  	spin_lock(&state_lock);  	spin_lock(&fp->fi_lock);  	dp->dl_stid.sc_file = fp; -	if (!fp->fi_lease) { +	if (!fp->fi_deleg_file) {  		spin_unlock(&fp->fi_lock);  		spin_unlock(&state_lock);  		status = nfs4_setlease(dp); @@ -4929,9 +4929,25 @@ nfs4_transform_lock_offset(struct file_lock *lock)  		lock->fl_end = OFFSET_MAX;  } -/* Hack!: For now, we're defining this just so we can use a pointer to it - * as a unique cookie to identify our (NFSv4's) posix locks. */ +static void nfsd4_fl_get_owner(struct file_lock *dst, struct file_lock *src) +{ +	struct nfs4_lockowner *lo = (struct nfs4_lockowner *)src->fl_owner; +	dst->fl_owner = (fl_owner_t)lockowner(nfs4_get_stateowner(&lo->lo_owner)); +} + +static void nfsd4_fl_put_owner(struct file_lock *fl) +{ +	struct nfs4_lockowner *lo = (struct nfs4_lockowner *)fl->fl_owner; + +	if (lo) { +		nfs4_put_stateowner(&lo->lo_owner); +		fl->fl_owner = NULL; +	} +} +  static const struct lock_manager_operations nfsd_posix_mng_ops  = { +	.lm_get_owner = nfsd4_fl_get_owner, +	.lm_put_owner = nfsd4_fl_put_owner,  };  static inline void @@ -4977,10 +4993,8 @@ find_lockowner_str_locked(clientid_t *clid, struct xdr_netobj *owner,  			    so_strhash) {  		if (so->so_is_open_owner)  			continue; -		if (!same_owner_str(so, owner)) -			continue; -		atomic_inc(&so->so_count); -		return lockowner(so); +		if (same_owner_str(so, owner)) +			return lockowner(nfs4_get_stateowner(so));  	}  	return NULL;  } @@ -5059,8 +5073,7 @@ init_lock_stateid(struct nfs4_ol_stateid *stp, struct nfs4_lockowner *lo,  	atomic_inc(&stp->st_stid.sc_count);  	stp->st_stid.sc_type = NFS4_LOCK_STID; -	stp->st_stateowner = &lo->lo_owner; -	atomic_inc(&lo->lo_owner.so_count); +	stp->st_stateowner = nfs4_get_stateowner(&lo->lo_owner);  	get_nfs4_file(fp);  	stp->st_stid.sc_file = fp;  	stp->st_stid.sc_free = nfs4_free_lock_stateid; @@ -5299,7 +5312,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,  		status = nfserr_openmode;  		goto out;  	} -	file_lock->fl_owner = (fl_owner_t)lock_sop; + +	file_lock->fl_owner = (fl_owner_t)lockowner(nfs4_get_stateowner(&lock_sop->lo_owner));  	file_lock->fl_pid = current->tgid;  	file_lock->fl_file = filp;  	file_lock->fl_flags = FL_POSIX; @@ -5495,7 +5509,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,  	}  	file_lock->fl_type = F_UNLCK; -	file_lock->fl_owner = (fl_owner_t)lockowner(stp->st_stateowner); +	file_lock->fl_owner = (fl_owner_t)lockowner(nfs4_get_stateowner(stp->st_stateowner));  	file_lock->fl_pid = current->tgid;  	file_lock->fl_file = filp;  	file_lock->fl_flags = FL_POSIX; @@ -5602,7 +5616,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,  			}  		} -		atomic_inc(&sop->so_count); +		nfs4_get_stateowner(sop);  		break;  	}  	spin_unlock(&clp->cl_lock); diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 0a47c6a6b301..2712042a66b1 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -486,7 +486,6 @@ struct nfs4_file {  	atomic_t		fi_access[2];  	u32			fi_share_deny;  	struct file		*fi_deleg_file; -	struct file_lock	*fi_lease;  	atomic_t		fi_delegees;  	struct knfsd_fh		fi_fhandle;  	bool			fi_had_conflict; diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c index abc8cbcfe90e..caaaf9dfe353 100644 --- a/fs/notify/dnotify/dnotify.c +++ b/fs/notify/dnotify/dnotify.c @@ -346,13 +346,7 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)  		goto out;  	} -	error = __f_setown(filp, task_pid(current), PIDTYPE_PID, 0); -	if (error) { -		/* if we added, we must shoot */ -		if (dn_mark == new_dn_mark) -			destroy = 1; -		goto out; -	} +	__f_setown(filp, task_pid(current), PIDTYPE_PID, 0);  	error = attach_dn(dn, dn_mark, id, fd, filp, mask);  	/* !error means that we attached the dn to the dn_mark, so don't free it */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 94187721ad41..2023306c620e 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -851,13 +851,7 @@ static inline struct file *get_file(struct file *f)   */  #define FILE_LOCK_DEFERRED 1 -/* - * The POSIX file lock owner is determined by - * the "struct files_struct" in the thread group - * (or NULL for no owner - BSD locks). - * - * Lockd stuffs a "host" pointer into this. - */ +/* legacy typedef, should eventually be removed */  typedef void *fl_owner_t;  struct file_lock_operations { @@ -868,10 +862,13 @@ struct file_lock_operations {  struct lock_manager_operations {  	int (*lm_compare_owner)(struct file_lock *, struct file_lock *);  	unsigned long (*lm_owner_key)(struct file_lock *); +	void (*lm_get_owner)(struct file_lock *, struct file_lock *); +	void (*lm_put_owner)(struct file_lock *);  	void (*lm_notify)(struct file_lock *);	/* unblock callback */ -	int (*lm_grant)(struct file_lock *, struct file_lock *, int); -	void (*lm_break)(struct file_lock *); -	int (*lm_change)(struct file_lock **, int); +	int (*lm_grant)(struct file_lock *, int); +	bool (*lm_break)(struct file_lock *); +	int (*lm_change)(struct file_lock **, int, struct list_head *); +	void (*lm_setup)(struct file_lock *, void **);  };  struct lock_manager { @@ -966,7 +963,7 @@ void locks_free_lock(struct file_lock *fl);  extern void locks_init_lock(struct file_lock *);  extern struct file_lock * locks_alloc_lock(void);  extern void locks_copy_lock(struct file_lock *, struct file_lock *); -extern void __locks_copy_lock(struct file_lock *, const struct file_lock *); +extern void locks_copy_conflock(struct file_lock *, struct file_lock *);  extern void locks_remove_posix(struct file *, fl_owner_t);  extern void locks_remove_file(struct file *);  extern void locks_release_private(struct file_lock *); @@ -980,11 +977,9 @@ extern int vfs_cancel_lock(struct file *filp, struct file_lock *fl);  extern int flock_lock_file_wait(struct file *filp, struct file_lock *fl);  extern int __break_lease(struct inode *inode, unsigned int flags, unsigned int type);  extern void lease_get_mtime(struct inode *, struct timespec *time); -extern int generic_setlease(struct file *, long, struct file_lock **); -extern int vfs_setlease(struct file *, long, struct file_lock **); -extern int lease_modify(struct file_lock **, int); -extern int lock_may_read(struct inode *, loff_t start, unsigned long count); -extern int lock_may_write(struct inode *, loff_t start, unsigned long count); +extern int generic_setlease(struct file *, long, struct file_lock **, void **priv); +extern int vfs_setlease(struct file *, long, struct file_lock **, void **); +extern int lease_modify(struct file_lock **, int, struct list_head *);  #else /* !CONFIG_FILE_LOCKING */  static inline int fcntl_getlk(struct file *file, unsigned int cmd,  			      struct flock __user *user) @@ -1013,12 +1008,12 @@ static inline int fcntl_setlk64(unsigned int fd, struct file *file,  #endif  static inline int fcntl_setlease(unsigned int fd, struct file *filp, long arg)  { -	return 0; +	return -EINVAL;  }  static inline int fcntl_getlease(struct file *filp)  { -	return 0; +	return F_UNLCK;  }  static inline void locks_init_lock(struct file_lock *fl) @@ -1026,7 +1021,7 @@ static inline void locks_init_lock(struct file_lock *fl)  	return;  } -static inline void __locks_copy_lock(struct file_lock *new, struct file_lock *fl) +static inline void locks_copy_conflock(struct file_lock *new, struct file_lock *fl)  {  	return;  } @@ -1100,33 +1095,22 @@ static inline void lease_get_mtime(struct inode *inode, struct timespec *time)  }  static inline int generic_setlease(struct file *filp, long arg, -				    struct file_lock **flp) +				    struct file_lock **flp, void **priv)  {  	return -EINVAL;  }  static inline int vfs_setlease(struct file *filp, long arg, -			       struct file_lock **lease) +			       struct file_lock **lease, void **priv)  {  	return -EINVAL;  } -static inline int lease_modify(struct file_lock **before, int arg) +static inline int lease_modify(struct file_lock **before, int arg, +			       struct list_head *dispose)  {  	return -EINVAL;  } - -static inline int lock_may_read(struct inode *inode, loff_t start, -				unsigned long len) -{ -	return 1; -} - -static inline int lock_may_write(struct inode *inode, loff_t start, -				 unsigned long len) -{ -	return 1; -}  #endif /* !CONFIG_FILE_LOCKING */ @@ -1151,8 +1135,8 @@ extern void fasync_free(struct fasync_struct *);  /* can be called from interrupts */  extern void kill_fasync(struct fasync_struct **, int, int); -extern int __f_setown(struct file *filp, struct pid *, enum pid_type, int force); -extern int f_setown(struct file *filp, unsigned long arg, int force); +extern void __f_setown(struct file *filp, struct pid *, enum pid_type, int force); +extern void f_setown(struct file *filp, unsigned long arg, int force);  extern void f_delown(struct file *filp);  extern pid_t f_getown(struct file *filp);  extern int send_sigurg(struct fown_struct *fown); @@ -1506,7 +1490,7 @@ struct file_operations {  	int (*flock) (struct file *, int, struct file_lock *);  	ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);  	ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); -	int (*setlease)(struct file *, long, struct file_lock **); +	int (*setlease)(struct file *, long, struct file_lock **, void **);  	long (*fallocate)(struct file *file, int mode, loff_t offset,  			  loff_t len);  	int (*show_fdinfo)(struct seq_file *m, struct file *f); @@ -2611,6 +2595,7 @@ extern int simple_write_end(struct file *file, struct address_space *mapping,  			struct page *page, void *fsdata);  extern int always_delete_dentry(const struct dentry *);  extern struct inode *alloc_anon_inode(struct super_block *); +extern int simple_nosetlease(struct file *, long, struct file_lock **, void **);  extern const struct dentry_operations simple_dentry_operations;  extern struct dentry *simple_lookup(struct inode *, struct dentry *, unsigned int flags); diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h index 219d79627c05..ff82a32871b5 100644 --- a/include/linux/lockd/lockd.h +++ b/include/linux/lockd/lockd.h @@ -178,7 +178,6 @@ struct nlm_block {  	unsigned char		b_granted;	/* VFS granted lock */  	struct nlm_file *	b_file;		/* file in question */  	struct cache_req *	b_cache_req;	/* deferred request handling */ -	struct file_lock *	b_fl;		/* set for GETLK */  	struct cache_deferred_req * b_deferred_req;  	unsigned int		b_flags;	/* block flags */  #define B_QUEUED		1	/* lock queued */ diff --git a/include/linux/security.h b/include/linux/security.h index 623f90e5f38d..b10e7af95d3b 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -1559,7 +1559,7 @@ struct security_operations {  	int (*file_lock) (struct file *file, unsigned int cmd);  	int (*file_fcntl) (struct file *file, unsigned int cmd,  			   unsigned long arg); -	int (*file_set_fowner) (struct file *file); +	void (*file_set_fowner) (struct file *file);  	int (*file_send_sigiotask) (struct task_struct *tsk,  				    struct fown_struct *fown, int sig);  	int (*file_receive) (struct file *file); @@ -1834,7 +1834,7 @@ int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,  			   unsigned long prot);  int security_file_lock(struct file *file, unsigned int cmd);  int security_file_fcntl(struct file *file, unsigned int cmd, unsigned long arg); -int security_file_set_fowner(struct file *file); +void security_file_set_fowner(struct file *file);  int security_file_send_sigiotask(struct task_struct *tsk,  				 struct fown_struct *fown, int sig);  int security_file_receive(struct file *file); @@ -2312,9 +2312,9 @@ static inline int security_file_fcntl(struct file *file, unsigned int cmd,  	return 0;  } -static inline int security_file_set_fowner(struct file *file) +static inline void security_file_set_fowner(struct file *file)  { -	return 0; +	return;  }  static inline int security_file_send_sigiotask(struct task_struct *tsk, diff --git a/include/trace/events/filelock.h b/include/trace/events/filelock.h index 59d11c22f076..a0d008070962 100644 --- a/include/trace/events/filelock.h +++ b/include/trace/events/filelock.h @@ -53,15 +53,15 @@ DECLARE_EVENT_CLASS(filelock_lease,  	),  	TP_fast_assign( -		__entry->fl = fl; +		__entry->fl = fl ? fl : NULL;  		__entry->s_dev = inode->i_sb->s_dev;  		__entry->i_ino = inode->i_ino; -		__entry->fl_next = fl->fl_next; -		__entry->fl_owner = fl->fl_owner; -		__entry->fl_flags = fl->fl_flags; -		__entry->fl_type = fl->fl_type; -		__entry->fl_break_time = fl->fl_break_time; -		__entry->fl_downgrade_time = fl->fl_downgrade_time; +		__entry->fl_next = fl ? fl->fl_next : NULL; +		__entry->fl_owner = fl ? fl->fl_owner : NULL; +		__entry->fl_flags = fl ? fl->fl_flags : 0; +		__entry->fl_type = fl ? fl->fl_type : 0; +		__entry->fl_break_time = fl ? fl->fl_break_time : 0; +		__entry->fl_downgrade_time = fl ? fl->fl_downgrade_time : 0;  	),  	TP_printk("fl=0x%p dev=0x%x:0x%x ino=0x%lx fl_next=0x%p fl_owner=0x%p fl_flags=%s fl_type=%s fl_break_time=%lu fl_downgrade_time=%lu", diff --git a/net/socket.c b/net/socket.c index ffd9cb46902b..fe20c319a0bb 100644 --- a/net/socket.c +++ b/net/socket.c @@ -1065,7 +1065,8 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)  			err = -EFAULT;  			if (get_user(pid, (int __user *)argp))  				break; -			err = f_setown(sock->file, pid, 1); +			f_setown(sock->file, pid, 1); +			err = 0;  			break;  		case FIOGETOWN:  		case SIOCGPGRP: diff --git a/security/capability.c b/security/capability.c index a74fde6a7468..d68c57a62bcf 100644 --- a/security/capability.c +++ b/security/capability.c @@ -343,9 +343,9 @@ static int cap_file_fcntl(struct file *file, unsigned int cmd,  	return 0;  } -static int cap_file_set_fowner(struct file *file) +static void cap_file_set_fowner(struct file *file)  { -	return 0; +	return;  }  static int cap_file_send_sigiotask(struct task_struct *tsk, diff --git a/security/security.c b/security/security.c index e41b1a8d7644..18b35c63fc0c 100644 --- a/security/security.c +++ b/security/security.c @@ -775,9 +775,9 @@ int security_file_fcntl(struct file *file, unsigned int cmd, unsigned long arg)  	return security_ops->file_fcntl(file, cmd, arg);  } -int security_file_set_fowner(struct file *file) +void security_file_set_fowner(struct file *file)  { -	return security_ops->file_set_fowner(file); +	security_ops->file_set_fowner(file);  }  int security_file_send_sigiotask(struct task_struct *tsk, diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index b0e940497e23..ada0d0bf3463 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3346,14 +3346,12 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd,  	return err;  } -static int selinux_file_set_fowner(struct file *file) +static void selinux_file_set_fowner(struct file *file)  {  	struct file_security_struct *fsec;  	fsec = file->f_security;  	fsec->fown_sid = current_sid(); - -	return 0;  }  static int selinux_file_send_sigiotask(struct task_struct *tsk, diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index e6ab307ce86e..69e5635d89e5 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -1390,12 +1390,11 @@ static int smack_mmap_file(struct file *file,   * Returns 0   * Further research may be required on this one.   */ -static int smack_file_set_fowner(struct file *file) +static void smack_file_set_fowner(struct file *file)  {  	struct smack_known *skp = smk_of_current();  	file->f_security = skp->smk_known; -	return 0;  }  /** | 
