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: ...@@ -349,6 +349,8 @@ prototypes:
loff_t *, int); loff_t *, int);
unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long (*get_unmapped_area)(struct file *, unsigned long,
unsigned long, unsigned long, unsigned long); unsigned long, unsigned long, unsigned long);
int (*check_flags)(int);
int (*dir_notify)(struct file *, unsigned long);
}; };
locking rules: locking rules:
...@@ -375,6 +377,8 @@ writev: no ...@@ -375,6 +377,8 @@ writev: no
sendfile: no sendfile: no
sendpage: no sendpage: no
get_unmapped_area: no get_unmapped_area: no
check_flags: no
dir_notify: no
->llseek() locking has moved from llseek to the individual llseek ->llseek() locking has moved from llseek to the individual llseek
implementations. If your fs is not using generic_file_llseek, you implementations. If your fs is not using generic_file_llseek, you
......
...@@ -534,18 +534,14 @@ struct file_operations cifs_file_ops = { ...@@ -534,18 +534,14 @@ struct file_operations cifs_file_ops = {
.flush = cifs_flush, .flush = cifs_flush,
.mmap = cifs_file_mmap, .mmap = cifs_file_mmap,
.sendfile = generic_file_sendfile, .sendfile = generic_file_sendfile,
#ifdef CONFIG_CIFS_FCNTL .dir_notify = cifs_dir_notify,
.fcntl = cifs_fcntl,
#endif
}; };
struct file_operations cifs_dir_ops = { struct file_operations cifs_dir_ops = {
.readdir = cifs_readdir, .readdir = cifs_readdir,
.release = cifs_closedir, .release = cifs_closedir,
.read = generic_read_dir, .read = generic_read_dir,
#ifdef CONFIG_CIFS_FCNTL .dir_notify = cifs_dir_notify,
.fcntl = cifs_fcntl,
#endif
}; };
static void static void
......
...@@ -74,7 +74,7 @@ extern int cifs_file_mmap(struct file * , struct vm_area_struct *); ...@@ -74,7 +74,7 @@ extern int cifs_file_mmap(struct file * , struct vm_area_struct *);
extern struct file_operations cifs_dir_ops; extern struct file_operations cifs_dir_ops;
extern int cifs_dir_open(struct inode *inode, struct file *file); extern int cifs_dir_open(struct inode *inode, struct file *file);
extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir); 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 */ /* Functions related to dir entries */
extern struct dentry_operations cifs_dentry_ops; extern struct dentry_operations cifs_dentry_ops;
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#include "cifs_unicode.h" #include "cifs_unicode.h"
#include "cifs_debug.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 xid;
int rc = -EINVAL; int rc = -EINVAL;
...@@ -70,53 +70,3 @@ int cifs_directory_notify(unsigned long arg, struct file * file) ...@@ -70,53 +70,3 @@ int cifs_directory_notify(unsigned long arg, struct file * file)
FreeXid(xid); FreeXid(xid);
return rc; 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) ...@@ -104,6 +104,9 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)
dn->dn_next = inode->i_dnotify; dn->dn_next = inode->i_dnotify;
inode->i_dnotify = dn; inode->i_dnotify = dn;
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
if (filp->f_op && filp->f_op->dir_notify)
return filp->f_op->dir_notify(filp, arg);
return 0; return 0;
out_free: out_free:
......
...@@ -239,6 +239,11 @@ static int setfl(int fd, struct file * filp, unsigned long arg) ...@@ -239,6 +239,11 @@ static int setfl(int fd, struct file * filp, unsigned long arg)
return -EINVAL; return -EINVAL;
} }
if (filp->f_op && filp->f_op->check_flags)
error = filp->f_op->check_flags(arg);
if (error)
return error;
lock_kernel(); lock_kernel();
if ((arg ^ filp->f_flags) & FASYNC) { if ((arg ^ filp->f_flags) & FASYNC) {
if (filp->f_op && filp->f_op->fasync) { if (filp->f_op && filp->f_op->fasync) {
...@@ -287,8 +292,8 @@ void f_delown(struct file *filp) ...@@ -287,8 +292,8 @@ void f_delown(struct file *filp)
EXPORT_SYMBOL(f_delown); EXPORT_SYMBOL(f_delown);
long generic_file_fcntl(int fd, unsigned int cmd, static long do_fcntl(int fd, unsigned int cmd, unsigned long arg,
unsigned long arg, struct file *filp) struct file *filp)
{ {
long err = -EINVAL; long err = -EINVAL;
...@@ -356,15 +361,6 @@ long generic_file_fcntl(int fd, unsigned int cmd, ...@@ -356,15 +361,6 @@ long generic_file_fcntl(int fd, unsigned int cmd,
} }
return err; 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) asmlinkage long sys_fcntl(int fd, unsigned int cmd, unsigned long arg)
{ {
......
...@@ -33,8 +33,6 @@ ...@@ -33,8 +33,6 @@
#define NFSDBG_FACILITY NFSDBG_FILE #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_open(struct inode *, struct file *);
static int nfs_file_release(struct inode *, struct file *); static int nfs_file_release(struct inode *, struct file *);
static int nfs_file_mmap(struct file *, struct vm_area_struct *); 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); ...@@ -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 ssize_t nfs_file_write(struct kiocb *, const char __user *, size_t, loff_t);
static int nfs_file_flush(struct file *); static int nfs_file_flush(struct file *);
static int nfs_fsync(struct file *, struct dentry *dentry, int datasync); static int nfs_fsync(struct file *, struct dentry *dentry, int datasync);
static int nfs_check_flags(int flags);
struct file_operations nfs_file_operations = { struct file_operations nfs_file_operations = {
.llseek = remote_llseek, .llseek = remote_llseek,
...@@ -57,7 +56,7 @@ struct file_operations nfs_file_operations = { ...@@ -57,7 +56,7 @@ struct file_operations nfs_file_operations = {
.fsync = nfs_fsync, .fsync = nfs_fsync,
.lock = nfs_lock, .lock = nfs_lock,
.sendfile = nfs_file_sendfile, .sendfile = nfs_file_sendfile,
.fcntl = nfs_file_fcntl, .check_flags = nfs_check_flags,
}; };
struct inode_operations nfs_file_inode_operations = { struct inode_operations nfs_file_inode_operations = {
...@@ -71,26 +70,12 @@ struct inode_operations nfs_file_inode_operations = { ...@@ -71,26 +70,12 @@ struct inode_operations nfs_file_inode_operations = {
# define IS_SWAPFILE(inode) (0) # define IS_SWAPFILE(inode) (0)
#endif #endif
#define nfs_invalid_flags (O_APPEND | O_DIRECT) static int nfs_check_flags(int flags)
/*
* 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)
{ {
switch (cmd) { if (flags & (O_APPEND | O_DIRECT))
case F_SETFL: return -EINVAL;
if ((filp->f_flags & nfs_invalid_flags) == nfs_invalid_flags)
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) ...@@ -101,10 +86,11 @@ nfs_file_open(struct inode *inode, struct file *filp)
{ {
struct nfs_server *server = NFS_SERVER(inode); struct nfs_server *server = NFS_SERVER(inode);
int (*open)(struct inode *, struct file *); int (*open)(struct inode *, struct file *);
int res = 0; int res;
if ((filp->f_flags & nfs_invalid_flags) == nfs_invalid_flags) res = nfs_check_flags(filp->f_flags);
return -EINVAL; if (!res)
return res;
lock_kernel(); lock_kernel();
/* Do NFSv4 open() call */ /* Do NFSv4 open() call */
......
...@@ -665,9 +665,6 @@ extern struct list_head file_lock_list; ...@@ -665,9 +665,6 @@ extern struct list_head file_lock_list;
#include <linux/fcntl.h> #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_getlk(struct file *, struct flock __user *);
extern int fcntl_setlk(struct file *, unsigned int, struct flock __user *); extern int fcntl_setlk(struct file *, unsigned int, struct flock __user *);
...@@ -895,8 +892,8 @@ struct file_operations { ...@@ -895,8 +892,8 @@ struct file_operations {
ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *); 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); 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); unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
long (*fcntl)(int fd, unsigned int cmd, int (*check_flags)(int);
unsigned long arg, struct file *filp); int (*dir_notify)(struct file *filp, unsigned long arg);
}; };
struct inode_operations { 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