Commit 401f0fbd authored by Matthew Wilcox's avatar Matthew Wilcox Committed by Linus Torvalds

[PATCH] Remove fcntl f_op

The newly introduced ->fcntl file_operation is badly thought out,
not to mention undocumented.  This patch replaces it with two better
defined operations -- check_flags and dir_notify.  Any other fcntl()s
that filesystems are interested in can have their own properly typed
f_op method when they need it.
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 15aeed93
......@@ -349,6 +349,8 @@ prototypes:
loff_t *, int);
unsigned long (*get_unmapped_area)(struct file *, unsigned long,
unsigned long, unsigned long, unsigned long);
int (*check_flags)(int);
int (*dir_notify)(struct file *, unsigned long);
};
locking rules:
......@@ -375,6 +377,8 @@ writev: no
sendfile: no
sendpage: no
get_unmapped_area: no
check_flags: no
dir_notify: no
->llseek() locking has moved from llseek to the individual llseek
implementations. If your fs is not using generic_file_llseek, you
......
......@@ -534,18 +534,14 @@ struct file_operations cifs_file_ops = {
.flush = cifs_flush,
.mmap = cifs_file_mmap,
.sendfile = generic_file_sendfile,
#ifdef CONFIG_CIFS_FCNTL
.fcntl = cifs_fcntl,
#endif
.dir_notify = cifs_dir_notify,
};
struct file_operations cifs_dir_ops = {
.readdir = cifs_readdir,
.release = cifs_closedir,
.read = generic_read_dir,
#ifdef CONFIG_CIFS_FCNTL
.fcntl = cifs_fcntl,
#endif
.dir_notify = cifs_dir_notify,
};
static void
......
......@@ -74,7 +74,7 @@ extern int cifs_file_mmap(struct file * , struct vm_area_struct *);
extern struct file_operations cifs_dir_ops;
extern int cifs_dir_open(struct inode *inode, struct file *file);
extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir);
extern long cifs_fcntl(int, unsigned int, unsigned long, struct file *);
extern int cifs_dir_notify(struct file *, unsigned long arg);
/* Functions related to dir entries */
extern struct dentry_operations cifs_dentry_ops;
......
......@@ -28,7 +28,7 @@
#include "cifs_unicode.h"
#include "cifs_debug.h"
int cifs_directory_notify(unsigned long arg, struct file * file)
int cifs_dir_notify(struct file * file, unsigned long arg)
{
int xid;
int rc = -EINVAL;
......@@ -70,53 +70,3 @@ int cifs_directory_notify(unsigned long arg, struct file * file)
FreeXid(xid);
return rc;
}
long cifs_fcntl(int file_desc, unsigned int command, unsigned long arg,
struct file * file)
{
/* Few few file control functions need to be specially mapped. So far
only:
F_NOTIFY (for directory change notification)
And eventually:
F_GETLEASE
F_SETLEASE
need to be mapped here. The others either already are mapped downstream
or do not need to go to the server (client only sideeffects):
F_DUPFD:
F_GETFD:
F_SETFD:
F_GETFL:
F_SETFL:
F_GETLK:
F_SETLK:
F_SETLKW:
F_GETOWN:
F_SETOWN:
F_GETSIG:
F_SETSIG:
*/
long rc = 0;
cFYI(1,("cifs_fcntl: command %d with arg %lx",command,arg)); /* BB removeme BB */
switch (command) {
case F_NOTIFY:
/* let the local call have a chance to fail first */
rc = generic_file_fcntl(file_desc,command,arg,file);
if(rc)
return rc;
else {
/* local call succeeded try to do remote notify to
pick up changes from other clients to server file */
cifs_directory_notify(arg, file);
/* BB add case to long and return rc from above */
return rc;
}
break;
default:
break;
}
return generic_file_fcntl(file_desc,command,arg,file);
}
......@@ -104,6 +104,9 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)
dn->dn_next = inode->i_dnotify;
inode->i_dnotify = dn;
spin_unlock(&inode->i_lock);
if (filp->f_op && filp->f_op->dir_notify)
return filp->f_op->dir_notify(filp, arg);
return 0;
out_free:
......
......@@ -239,6 +239,11 @@ static int setfl(int fd, struct file * filp, unsigned long arg)
return -EINVAL;
}
if (filp->f_op && filp->f_op->check_flags)
error = filp->f_op->check_flags(arg);
if (error)
return error;
lock_kernel();
if ((arg ^ filp->f_flags) & FASYNC) {
if (filp->f_op && filp->f_op->fasync) {
......@@ -287,8 +292,8 @@ void f_delown(struct file *filp)
EXPORT_SYMBOL(f_delown);
long generic_file_fcntl(int fd, unsigned int cmd,
unsigned long arg, struct file *filp)
static long do_fcntl(int fd, unsigned int cmd, unsigned long arg,
struct file *filp)
{
long err = -EINVAL;
......@@ -356,15 +361,6 @@ long generic_file_fcntl(int fd, unsigned int cmd,
}
return err;
}
EXPORT_SYMBOL(generic_file_fcntl);
static long do_fcntl(int fd, unsigned int cmd,
unsigned long arg, struct file *filp)
{
if (filp->f_op && filp->f_op->fcntl)
return filp->f_op->fcntl(fd, cmd, arg, filp);
return generic_file_fcntl(fd, cmd, arg, filp);
}
asmlinkage long sys_fcntl(int fd, unsigned int cmd, unsigned long arg)
{
......
......@@ -33,8 +33,6 @@
#define NFSDBG_FACILITY NFSDBG_FILE
static long nfs_file_fcntl(int fd, unsigned int cmd,
unsigned long arg, struct file *filp);
static int nfs_file_open(struct inode *, struct file *);
static int nfs_file_release(struct inode *, struct file *);
static int nfs_file_mmap(struct file *, struct vm_area_struct *);
......@@ -43,6 +41,7 @@ static ssize_t nfs_file_read(struct kiocb *, char __user *, size_t, loff_t);
static ssize_t nfs_file_write(struct kiocb *, const char __user *, size_t, loff_t);
static int nfs_file_flush(struct file *);
static int nfs_fsync(struct file *, struct dentry *dentry, int datasync);
static int nfs_check_flags(int flags);
struct file_operations nfs_file_operations = {
.llseek = remote_llseek,
......@@ -57,7 +56,7 @@ struct file_operations nfs_file_operations = {
.fsync = nfs_fsync,
.lock = nfs_lock,
.sendfile = nfs_file_sendfile,
.fcntl = nfs_file_fcntl,
.check_flags = nfs_check_flags,
};
struct inode_operations nfs_file_inode_operations = {
......@@ -71,26 +70,12 @@ struct inode_operations nfs_file_inode_operations = {
# define IS_SWAPFILE(inode) (0)
#endif
#define nfs_invalid_flags (O_APPEND | O_DIRECT)
/*
* Check for special cases that NFS doesn't support, and
* pass the rest to the generic fcntl function.
*/
static long
nfs_file_fcntl(int fd, unsigned int cmd,
unsigned long arg, struct file *filp)
static int nfs_check_flags(int flags)
{
switch (cmd) {
case F_SETFL:
if ((filp->f_flags & nfs_invalid_flags) == nfs_invalid_flags)
if (flags & (O_APPEND | O_DIRECT))
return -EINVAL;
break;
default:
break;
}
return generic_file_fcntl(fd, cmd, arg, filp);
return 0;
}
/*
......@@ -101,10 +86,11 @@ nfs_file_open(struct inode *inode, struct file *filp)
{
struct nfs_server *server = NFS_SERVER(inode);
int (*open)(struct inode *, struct file *);
int res = 0;
int res;
if ((filp->f_flags & nfs_invalid_flags) == nfs_invalid_flags)
return -EINVAL;
res = nfs_check_flags(filp->f_flags);
if (!res)
return res;
lock_kernel();
/* Do NFSv4 open() call */
......
......@@ -665,9 +665,6 @@ extern struct list_head file_lock_list;
#include <linux/fcntl.h>
extern long generic_file_fcntl(int fd, unsigned int cmd,
unsigned long arg, struct file *filp);
extern int fcntl_getlk(struct file *, struct flock __user *);
extern int fcntl_setlk(struct file *, unsigned int, struct flock __user *);
......@@ -895,8 +892,8 @@ struct file_operations {
ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *);
ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
long (*fcntl)(int fd, unsigned int cmd,
unsigned long arg, struct file *filp);
int (*check_flags)(int);
int (*dir_notify)(struct file *filp, unsigned long arg);
};
struct inode_operations {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment