Eliminate delegation self-conflicts v2
Subsystems (26)
PATCH 1/10 vfs: remove unnecessary fl_owner_t typedef
In reply to J. Bruce FieldsFrom: "J. Bruce Fields" <[email protected]>
The convention is to avoid this kind of typedef. It doesn't seem useful, and it requires a lot of casts.
--- Documentation/filesystems/vfs.txt | 2 +- arch/ia64/kernel/perfmon.c | 2 +- arch/powerpc/platforms/cell/spufs/file.c | 2 +- arch/tile/kernel/hardwall.c | 2 +- drivers/android/binder.c | 2 +- drivers/char/ps3flash.c | 2 +- drivers/char/xillybus/xillybus_core.c | 2 +- drivers/firmware/efi/capsule-loader.c | 2 +- drivers/input/evdev.c | 2 +- drivers/misc/mic/scif/scif_fd.c | 2 +- drivers/scsi/osst.c | 2 +- drivers/scsi/st.c | 2 +- drivers/staging/lustre/lustre/llite/file.c | 2 +- drivers/usb/class/cdc-wdm.c | 2 +- drivers/usb/usb-skeleton.c | 2 +- fs/afs/internal.h | 2 +- fs/afs/write.c | 2 +- fs/cifs/cifsfs.h | 2 +- fs/cifs/file.c | 4 ++-- fs/ecryptfs/file.c | 2 +- fs/exofs/file.c | 2 +- fs/f2fs/file.c | 2 +- fs/fuse/file.c | 13 ++++++------- fs/fuse/fuse_i.h | 2 +- fs/lockd/clntproc.c | 4 ++-- fs/lockd/svc4proc.c | 2 +- fs/lockd/svcproc.c | 2 +- fs/locks.c | 2 +- fs/nfs/file.c | 2 +- fs/nfs/inode.c | 2 +- fs/nfs/nfs4_fs.h | 2 +- fs/nfs/nfs4file.c | 2 +- fs/nfs/nfs4state.c | 8 ++++---- fs/nfsd/nfs4state.c | 18 +++++++++--------- fs/notify/dnotify/dnotify.c | 6 +++--- fs/open.c | 2 +- include/linux/dnotify.h | 6 +++--- include/linux/fs.h | 17 +++++++---------- include/linux/lockd/lockd.h | 4 ++-- include/linux/nfs_fs.h | 4 ++-- include/trace/events/filelock.h | 6 +++--- ipc/mqueue.c | 2 +- 42 files changed, 74 insertions(+), 78 deletions(-)
Documentation/filesystems/vfs.txt +1 -1
@@ -862,7 +862,7 @@ struct file_operations { int (*mmap) (struct file *, struct vm_area_struct *); int (*mremap)(struct file *, struct vm_area_struct *); int (*open) (struct inode *, struct file *); - int (*flush) (struct file *, fl_owner_t id); + int (*flush) (struct file *, void *id); int (*release) (struct inode *, struct file *); int (*fsync) (struct file *, loff_t, loff_t, int datasync); int (*fasync) (int, struct file *, int);
arch/ia64/kernel/perfmon.c +1 -1
@@ -1809,7 +1809,7 @@ pfm_syswide_cleanup_other_cpu(pfm_context_t *ctx)* When caller is self-monitoring, the context is unloaded. */ static int -pfm_flush (struct file *filp,fl_owner_t id) +pfm_flush (struct file *filp,void *id) {pfm_context_t *ctx;struct task_struct *task;
arch/powerpc/platforms/cell/spufs/file.c +1 -1
@@ -1720,7 +1720,7 @@ static __poll_t spufs_mfc_poll(struct file *file,poll_table *wait)return mask; } -static int spufs_mfc_flush (struct file *file,fl_owner_t id) +static int spufs_mfc_flush (struct file *file,void *id) {struct spu_context *ctx = file->private_data;int ret;
arch/tile/kernel/hardwall.c +1 -1
@@ -1030,7 +1030,7 @@ static long hardwall_compat_ioctl(struct file *file,#endif /* The user process closed the file; revoke access to user networks. */ -static int hardwall_flush (struct file *file,fl_owner_t owner) +static int hardwall_flush (struct file *file,void *owner) {struct hardwall_info *info = file->private_data;struct task_struct *task, *tmp;
drivers/android/binder.c +1 -1
@@ -4776,7 +4776,7 @@ static int binder_open(struct inode *nodp, struct file *filp)return 0 ; } -static int binder_flush (struct file *filp,fl_owner_t id) +static int binder_flush (struct file *filp,void *id) {struct binder_proc *proc = filp->private_data;
drivers/char/ps3flash.c +1 -1
@@ -281,7 +281,7 @@ static ssize_t ps3flash_kernel_write(const void *buf, size_t count,return res; } -static int ps3flash_flush (struct file *file,fl_owner_t id) +static int ps3flash_flush (struct file *file,void *id) {return ps3flash_writeback (ps3flash_dev); }
drivers/char/xillybus/xillybus_core.c +1 -1
@@ -1156,7 +1156,7 @@ static int xillybus_myflush(struct xilly_channel *channel, long timeout)return rc; } -static int xillybus_flush (struct file *filp,fl_owner_t id) +static int xillybus_flush (struct file *filp,void *id) {if (!(filp->f_mode &FMODE_WRITE ))return 0 ;
drivers/firmware/efi/capsule-loader.c +1 -1
@@ -246,7 +246,7 @@ static ssize_t efi_capsule_write(struct file *file, const char __user *buff,* will be treated as upload termination and will free those completed * buffer pages and -ECANCELED will be returned. **/ -static int efi_capsule_flush (struct file *file,fl_owner_t id) +static int efi_capsule_flush (struct file *file,void *id) {int ret =0 ;struct capsule_info *cap_info = file->private_data;
drivers/input/evdev.c +1 -1
@@ -348,7 +348,7 @@ static int evdev_fasync(int fd, struct file *file, int on)return fasync_helper (fd, file, on, &client->fasync); } -static int evdev_flush (struct file *file,fl_owner_t id) +static int evdev_flush (struct file *file,void *id) {struct evdev_client *client = file->private_data;struct evdev *evdev = client->evdev;
drivers/misc/mic/scif/scif_fd.c +1 -1
@@ -48,7 +48,7 @@ static __poll_t scif_fdpoll(struct file *f, poll_table *wait)return __scif_pollfd (f, wait, priv); } -static int scif_fdflush (struct file *f,fl_owner_t id) +static int scif_fdflush (struct file *f,void *id) {struct scif_endpt *ep = f->private_data;
drivers/scsi/osst.c +1 -1
@@ -4822,7 +4822,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp)/* Flush the tape buffer before close */ -static int os_scsi_tape_flush (struct file * filp,fl_owner_t id) +static int os_scsi_tape_flush (struct file * filp,void *id) {int result =0 , result2;struct osst_tape * STp = filp->private_data;
drivers/scsi/st.c +1 -1
@@ -1338,7 +1338,7 @@ static int st_open(struct inode *inode, struct file *filp)/* Flush the tape buffer before close */ -static int st_flush (struct file *filp,fl_owner_t id) +static int st_flush (struct file *filp,void *id) {int result =0 , result2;
unsigned char cmd[MAX_COMMAND_SIZE];
drivers/staging/lustre/lustre/llite/file.c +1 -1
@@ -2281,7 +2281,7 @@ static loff_t ll_file_seek(struct file *file, loff_t offset, int origin) ll_file_maxbytes(inode), eof); } -static int ll_flush (struct file *file,fl_owner_t id) +static int ll_flush (struct file *file,void *id) {struct inode *inode =file_inode (file);struct ll_inode_info *lli =ll_i2info (inode);
drivers/usb/class/cdc-wdm.c +1 -1
@@ -581,7 +581,7 @@ static ssize_t wdm_readreturn rv; } -static int wdm_flush (struct file *file,fl_owner_t id) +static int wdm_flush (struct file *file,void *id) {struct wdm_device *desc = file->private_data;
drivers/usb/usb-skeleton.c +1 -1
@@ -132,7 +132,7 @@ static int skel_release(struct inode *inode, struct file *file)return 0 ; } -static int skel_flush (struct file *file,fl_owner_t id) +static int skel_flush (struct file *file,void *id) {struct usb_skel *dev;int res;
fs/afs/internal.h +1 -1
@@ -947,7 +947,7 @@ extern int afs_writepage(struct page *, struct writeback_control *);extern int afs_writepages (struct address_space *,struct writeback_control *);extern void afs_pages_written_back (struct afs_vnode *,struct afs_call *);extern ssize_t afs_file_write (struct kiocb *,struct iov_iter *); -extern int afs_flush (struct file *,fl_owner_t ); +extern int afs_flush (struct file *,void *);extern int afs_fsync (struct file *,loff_t ,loff_t ,int );extern int afs_page_mkwrite (struct vm_fault *);extern void afs_prune_wb_keys (struct afs_vnode *);
fs/afs/write.c +1 -1
@@ -737,7 +737,7 @@ int afs_fsync(struct file *file, loff_t start, loff_t end, int datasync)* Flush out all outstanding writes on a file opened for writing when it is * closed. */ -int afs_flush (struct file *file,fl_owner_t id) +int afs_flush (struct file *file,void *id) {_enter ("" );
fs/cifs/cifsfs.h +1 -1
@@ -108,7 +108,7 @@ extern ssize_t cifs_strict_writev(struct kiocb *iocb, struct iov_iter *from);extern int cifs_lock (struct file *,int ,struct file_lock *);extern int cifs_fsync (struct file *,loff_t ,loff_t ,int );extern int cifs_strict_fsync (struct file *,loff_t ,loff_t ,int ); -extern int cifs_flush (struct file *,fl_owner_t id); +extern int cifs_flush (struct file *,void *id);extern int cifs_file_mmap (struct file * ,struct vm_area_struct *);extern int cifs_file_strict_mmap (struct file * ,struct vm_area_struct *);extern const struct file_operations cifs_dir_ops;
fs/cifs/file.c +2 -2
@@ -1174,7 +1174,7 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile) }static __u32 -hash_lockowner (fl_owner_t owner) +hash_lockowner (void *owner) {return cifs_lock_secret ^hash32_ptr ((const void *)owner); }
@@ -2393,7 +2393,7 @@ int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync)* As file closes, flush all cached write data for this inode checking * for write behind errors. */ -int cifs_flush (struct file *file,fl_owner_t id) +int cifs_flush (struct file *file,void *id) {struct inode *inode =file_inode (file);int rc =0 ;
fs/ecryptfs/file.c +1 -1
@@ -290,7 +290,7 @@ static int ecryptfs_dir_open(struct inode *inode, struct file *file)return 0 ; } -static int ecryptfs_flush (struct file *file,fl_owner_t td) +static int ecryptfs_flush (struct file *file,void *td) {struct file *lower_file =ecryptfs_file_to_lower (file);
fs/exofs/file.c +1 -1
@@ -58,7 +58,7 @@ static int exofs_file_fsync(struct file *filp, loff_t start, loff_t end,return ret; } -static int exofs_flush (struct file *file,fl_owner_t id) +static int exofs_flush (struct file *file,void *id) {int ret =vfs_fsync (file,0 );/* TODO: Flush the OSD target */
fs/f2fs/file.c +1 -1
@@ -1557,7 +1557,7 @@ static int f2fs_release_file(struct inode *inode, struct file *filp)return 0 ; } -static int f2fs_file_flush (struct file *file,fl_owner_t id) +static int f2fs_file_flush (struct file *file,void *id) {struct inode *inode =file_inode (file);
fs/fuse/file.c +6 -7
@@ -254,8 +254,7 @@ void fuse_release_common(struct file *file, int opcode)if (ff->flock) {struct fuse_release_in *inarg = &req->misc.release.in; inarg->release_flags |=FUSE_RELEASE_FLOCK_UNLOCK ; - inarg->lock_owner =fuse_lock_owner_id (ff->fc, - (fl_owner_t ) file); + inarg->lock_owner =fuse_lock_owner_id (ff->fc, file); }/* Hold inode until release is finished */ req->misc.release.inode =igrab (file_inode (file));
@@ -307,7 +306,7 @@ EXPORT_SYMBOL_GPL(fuse_sync_release);* Scramble the ID space with XTEA, so that the value of the files_struct * pointer is not exposed to userspace. */ -u64 fuse_lock_owner_id (struct fuse_conn *fc,fl_owner_t id) +u64 fuse_lock_owner_id (struct fuse_conn *fc,void *id) {u32 *k = fc->scramble_key;u64 v = (unsigned long ) id;
@@ -390,7 +389,7 @@ static void fuse_sync_writes(struct inode *inode)fuse_release_nowrite (inode); } -static int fuse_flush (struct file *file,fl_owner_t id) +static int fuse_flush (struct file *file,void *id) {struct inode *inode =file_inode (file);struct fuse_conn *fc =get_fuse_conn (inode);
@@ -643,7 +642,7 @@ static size_t fuse_async_req_send(struct fuse_conn *fc, struct fuse_req *req, }static size_t fuse_send_read (struct fuse_req *req,struct fuse_io_priv *io, -loff_t pos,size_t count,fl_owner_t owner) +loff_t pos,size_t count,void *owner) {struct file *file = io->iocb->ki_filp;struct fuse_file *ff = file->private_data;
@@ -958,7 +957,7 @@ static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff, }static size_t fuse_send_write (struct fuse_req *req,struct fuse_io_priv *io, -loff_t pos,size_t count,fl_owner_t owner) +loff_t pos,size_t count,void *owner) {struct kiocb *iocb = io->iocb;struct file *file = iocb->ki_filp;
@@ -1358,7 +1357,7 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter, io->should_dirty = !write &&iter_is_iovec (iter);while (count) {size_t nres; -fl_owner_t owner = current->files; +void *owner = current->files;size_t nbytes =min (count, nmax); err =fuse_get_user_pages (req, iter, &nbytes, write);if (err && !nbytes)
fs/fuse/fuse_i.h +1 -1
@@ -900,7 +900,7 @@ int fuse_valid_type(int m);*/ int fuse_allow_current_process (struct fuse_conn *fc); -u64 fuse_lock_owner_id (struct fuse_conn *fc,fl_owner_t id); +u64 fuse_lock_owner_id (struct fuse_conn *fc,void *id);void fuse_update_ctime (struct inode *inode);
fs/lockd/clntproc.c +2 -2
@@ -81,7 +81,7 @@ static inline uint32_t __nlm_alloc_pid(struct nlm_host *host)return res; } -static struct nlm_lockowner *__nlm_find_lockowner (struct nlm_host *host,fl_owner_t owner) +static struct nlm_lockowner *__nlm_find_lockowner (struct nlm_host *host,void *owner) {struct nlm_lockowner *lockowner;list_for_each_entry (lockowner, &host->h_lockowners, list) {
@@ -92,7 +92,7 @@ static struct nlm_lockowner *__nlm_find_lockowner(struct nlm_host *host, fl_ownereturn NULL ; } -static struct nlm_lockowner *nlm_find_lockowner (struct nlm_host *host,fl_owner_t owner) +static struct nlm_lockowner *nlm_find_lockowner (struct nlm_host *host,void *owner) {struct nlm_lockowner *res, *new =NULL ;
fs/lockd/svc4proc.c +1 -1
@@ -46,7 +46,7 @@ nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,/* Set up the missing parts of the file_lock structure */ lock->fl.fl_file = file->f_file; - lock->fl.fl_owner = (fl_owner_t ) host; + lock->fl.fl_owner = host; lock->fl.fl_lmops = &nlmsvc_lock_operations; }
fs/lockd/svcproc.c +1 -1
@@ -76,7 +76,7 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,/* Set up the missing parts of the file_lock structure */ lock->fl.fl_file = file->f_file; - lock->fl.fl_owner = (fl_owner_t ) host; + lock->fl.fl_owner = host; lock->fl.fl_lmops = &nlmsvc_lock_operations; }
fs/locks.c +1 -1
@@ -2462,7 +2462,7 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd,* from the task's fd array. POSIX locks belonging to this task * are deleted at this time. */ -void locks_remove_posix (struct file *filp,fl_owner_t owner) +void locks_remove_posix (struct file *filp,void *owner) {int error;struct inode *inode =locks_inode (filp);
fs/nfs/file.c +1 -1
@@ -136,7 +136,7 @@ EXPORT_SYMBOL_GPL(nfs_file_llseek);* Flush all dirty pages, and check for write errors. */ static int -nfs_file_flush (struct file *file,fl_owner_t id) +nfs_file_flush (struct file *file,void *id) {struct inode *inode =file_inode (file);
fs/nfs/inode.c +1 -1
@@ -927,7 +927,7 @@ struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, ctx->mode = f_mode; ctx->flags =0 ; ctx->error =0 ; - ctx->flock_owner = (fl_owner_t )filp; + ctx->flock_owner = filp;nfs_init_lock_context (&ctx->lock_context); ctx->lock_context.open_context = ctx;INIT_LIST_HEAD (&ctx->list);
fs/nfs/nfs4_fs.h +1 -1
@@ -146,7 +146,7 @@ struct nfs4_lock_state {struct nfs_seqid_counter ls_seqid;nfs4_stateid ls_stateid;refcount_t ls_count; -fl_owner_t ls_owner; +void * ls_owner; };/* bits for nfs4_state->flags */
fs/nfs/nfs4file.c +1 -1
@@ -107,7 +107,7 @@ nfs4_file_open(struct inode *inode, struct file *filp)* Flush all dirty pages, and check for write errors. */ static int -nfs4_file_flush (struct file *file,fl_owner_t id) +nfs4_file_flush (struct file *file,void *id) {struct inode *inode =file_inode (file);
fs/nfs/nfs4state.c +4 -4
@@ -822,7 +822,7 @@ void nfs4_close_sync(struct nfs4_state *state, fmode_t fmode)*/ static struct nfs4_lock_state *__nfs4_find_lock_state (struct nfs4_state *state, -fl_owner_t fl_owner,fl_owner_t fl_owner2) +void *fl_owner,void *fl_owner2) {struct nfs4_lock_state *pos, *ret =NULL ;list_for_each_entry (pos, &state->lock_states, ls_locks) {
@@ -843,7 +843,7 @@ __nfs4_find_lock_state(struct nfs4_state *state,* exists, return an uninitialized one. * */ -static struct nfs4_lock_state *nfs4_alloc_lock_state (struct nfs4_state *state,fl_owner_t fl_owner) +static struct nfs4_lock_state *nfs4_alloc_lock_state (struct nfs4_state *state,void *fl_owner) {struct nfs4_lock_state *lsp;struct nfs_server *server = state->owner->so_server;
@@ -877,7 +877,7 @@ void nfs4_free_lock_state(struct nfs_server *server, struct nfs4_lock_state *lsp* exists, return an uninitialized one. * */ -static struct nfs4_lock_state *nfs4_get_lock_state (struct nfs4_state *state,fl_owner_t owner) +static struct nfs4_lock_state *nfs4_get_lock_state (struct nfs4_state *state,void *owner) {struct nfs4_lock_state *lsp, *new =NULL ;
@@ -968,7 +968,7 @@ static int nfs4_copy_lock_stateid(nfs4_stateid *dst, const struct nfs_lock_context *l_ctx) {struct nfs4_lock_state *lsp; -fl_owner_t fl_owner, fl_flock_owner; +void *fl_owner, *fl_flock_owner;int ret = -ENOENT ;if (l_ctx ==NULL )
fs/nfsd/nfs4state.c +9 -9
@@ -1204,7 +1204,7 @@ static void nfs4_free_lock_stateid(struct nfs4_stid *stid) file =find_any_file (stp->st_stid.sc_file);if (file) -filp_close (file, (fl_owner_t )lo); +filp_close (file, lo);nfs4_free_ol_stateid (stid); }
@@ -4268,7 +4268,7 @@ static struct file_lock *nfs4_alloc_init_lease(struct nfs4_file *fp, int flag) fl->fl_flags =FL_DELEG ; fl->fl_type = flag ==NFS4_OPEN_DELEGATE_READ ?F_RDLCK :F_WRLCK ; fl->fl_end =OFFSET_MAX ; - fl->fl_owner = (fl_owner_t )fp; + fl->fl_owner = fp; fl->fl_pid = current->tgid;return fl; }
@@ -5563,8 +5563,8 @@ nfs4_transform_lock_offset(struct file_lock *lock) lock->fl_end =OFFSET_MAX ; } -static fl_owner_t -nfsd4_fl_get_owner (fl_owner_t owner) +static void * +nfsd4_fl_get_owner (void *owner) {struct nfs4_lockowner *lo = (struct nfs4_lockowner *)owner;
@@ -5573,7 +5573,7 @@ nfsd4_fl_get_owner(fl_owner_t owner) }static void -nfsd4_fl_put_owner (fl_owner_t owner) +nfsd4_fl_put_owner (void *owner) {struct nfs4_lockowner *lo = (struct nfs4_lockowner *)owner;
@@ -6008,7 +6008,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, file_lock = &nbl->nbl_lock; file_lock->fl_type = fl_type; - file_lock->fl_owner = (fl_owner_t )lockowner (nfs4_get_stateowner (&lock_sop->lo_owner)); + file_lock->fl_owner =lockowner (nfs4_get_stateowner (&lock_sop->lo_owner)); file_lock->fl_pid = current->tgid; file_lock->fl_file = filp; file_lock->fl_flags = fl_flags;
@@ -6162,7 +6162,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, lo =find_lockowner_str (cstate->clp, &lockt->lt_owner);if (lo) - file_lock->fl_owner = (fl_owner_t )lo; + file_lock->fl_owner = lo; file_lock->fl_pid = current->tgid; file_lock->fl_flags =FL_POSIX ;
@@ -6224,7 +6224,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 (nfs4_get_stateowner (stp->st_stateowner)); + file_lock->fl_owner =lockowner (nfs4_get_stateowner (stp->st_stateowner)); file_lock->fl_pid = current->tgid; file_lock->fl_file = filp; file_lock->fl_flags =FL_POSIX ;
@@ -6283,7 +6283,7 @@ check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner)if (flctx && !list_empty_careful (&flctx->flc_posix)) {spin_lock (&flctx->flc_lock);list_for_each_entry (fl, &flctx->flc_posix, fl_list) { -if (fl->fl_owner == (fl_owner_t )lowner) { +if (fl->fl_owner == lowner) { status = true;break ; }
fs/notify/dnotify/dnotify.c +3 -3
@@ -145,7 +145,7 @@ static const struct fsnotify_ops dnotify_fsnotify_ops = {* dnotify_struct. If that was the last dnotify_struct also remove the * fsnotify_mark. */ -void dnotify_flush (struct file *filp,fl_owner_t id) +void dnotify_flush (struct file *filp,void *id) {struct fsnotify_mark *fsn_mark;struct dnotify_mark *dn_mark;
@@ -223,7 +223,7 @@ static __u32 convert_arg(unsigned long arg)* that list, or it |= the mask onto an existing dnofiy_struct. */ static int attach_dn (struct dnotify_struct *dn,struct dnotify_mark *dn_mark, -fl_owner_t id,int fd,struct file *filp,__u32 mask) +void *id,int fd,struct file *filp,__u32 mask) {struct dnotify_struct *odn;
@@ -259,7 +259,7 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)struct fsnotify_mark *new_fsn_mark, *fsn_mark;struct dnotify_struct *dn;struct inode *inode; -fl_owner_t id = current->files; +void *id = current->files;struct file *f;int destroy =0 , error =0 ;__u32 mask;
fs/open.c +1 -1
@@ -1123,7 +1123,7 @@ SYSCALL_DEFINE2(creat, const char __user *, pathname, umode_t, mode)* "id" is the POSIX thread ID. We use the * files pointer for this.. */ -int filp_close (struct file *filp,fl_owner_t id) +int filp_close (struct file *filp,void *id) {int retval =0 ;
include/linux/dnotify.h +3 -3
@@ -14,7 +14,7 @@ struct dnotify_struct {__u32 dn_mask;int dn_fd;struct file * dn_filp; -fl_owner_t dn_owner; +void * dn_owner; };#ifdef __KERNEL__
@@ -30,12 +30,12 @@ struct dnotify_struct { FS_MOVED_FROM | FS_MOVED_TO)extern int dir_notify_enable; -extern void dnotify_flush (struct file *,fl_owner_t ); +extern void dnotify_flush (struct file *,void *);extern int fcntl_dirnotify (int ,struct file *,unsigned long );#else -static inline void dnotify_flush (struct file *filp,fl_owner_t id) +static inline void dnotify_flush (struct file *filp,void *id) { }
include/linux/fs.h +7 -10
@@ -942,9 +942,6 @@ static inline struct file *get_file(struct file *f)*/ #define FILE_LOCK_DEFERRED 1 -/* legacy typedef, should eventually be removed */ -typedef void *fl_owner_t ; -struct file_lock ;struct file_lock_operations {
@@ -955,8 +952,8 @@ 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 *); -fl_owner_t (*lm_get_owner)(fl_owner_t ); -void (*lm_put_owner)(fl_owner_t ); +void *(*lm_get_owner)(void *); +void (*lm_put_owner)(void *);void (*lm_notify)(struct file_lock *);/* unblock callback */ int (*lm_grant)(struct file_lock *,int );bool (*lm_break)(struct file_lock *);
@@ -1004,7 +1001,7 @@ struct file_lock {struct list_head fl_list;/* link into file_lock_context */ struct hlist_node fl_link;/* node in global lists */ struct list_head fl_block;/* circular list of blocked processes */ -fl_owner_t fl_owner; +void *fl_owner;unsigned int fl_flags;unsigned char fl_type;unsigned int fl_pid;
@@ -1080,7 +1077,7 @@ 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_conflock (struct file_lock *,struct file_lock *); -extern void locks_remove_posix (struct file *,fl_owner_t ); +extern void locks_remove_posix (struct file *,void *);extern void locks_remove_file (struct file *);extern void locks_release_private (struct file_lock *);extern void posix_test_lock (struct file *,struct file_lock *);
@@ -1154,7 +1151,7 @@ static inline void locks_copy_lock(struct file_lock *new, struct file_lock *fl)return ; } -static inline void locks_remove_posix (struct file *filp,fl_owner_t owner) +static inline void locks_remove_posix (struct file *filp,void *owner) {return ; }
@@ -1713,7 +1710,7 @@ struct file_operations {int (*mmap) (struct file *,struct vm_area_struct *);unsigned long mmap_supported_flags;int (*open) (struct inode *,struct file *); -int (*flush) (struct file *,fl_owner_t id); +int (*flush) (struct file *,void *id);int (*release) (struct inode *,struct file *);int (*fsync) (struct file *,loff_t ,loff_t ,int datasync);int (*fasync) (int ,struct file *,int );
@@ -2397,7 +2394,7 @@ extern struct file *filp_open(const char *, int, umode_t);extern struct file *file_open_root (struct dentry *,struct vfsmount *,const char *,int ,umode_t );extern struct file *dentry_open (const struct path *,int ,const struct cred *); -extern int filp_close (struct file *,fl_owner_t id); +extern int filp_close (struct file *,void *id);extern struct filename *getname_flags (const char __user *,int ,int *);extern struct filename *getname (const char __user *);
include/linux/lockd/lockd.h +2 -2
@@ -119,14 +119,14 @@ static inline struct sockaddr *nlm_srcaddr(const struct nlm_host *host) }/* -* Map an fl_owner_t into a unique 32-bit "pid" +* Map a lock owner into a unique 32-bit "pid" */ struct nlm_lockowner {struct list_head list;refcount_t count;struct nlm_host *host; -fl_owner_t owner; +void *owner;uint32_t pid; };
include/linux/nfs_fs.h +2 -2
@@ -60,14 +60,14 @@ struct nfs_lock_context {refcount_t count;struct list_head list;struct nfs_open_context *open_context; -fl_owner_t lockowner; +void *lockowner;atomic_t io_count; };struct nfs4_state ;struct nfs_open_context {struct nfs_lock_context lock_context; -fl_owner_t flock_owner; +void *flock_owner;struct dentry *dentry;struct rpc_cred *cred;struct nfs4_state *state;
include/trace/events/filelock.h +3 -3
@@ -69,7 +69,7 @@ DECLARE_EVENT_CLASS(filelock_lock, __field(unsigned long, i_ino) __field(dev_t, s_dev) __field(struct file_lock *, fl_next) - __field(fl_owner_t, fl_owner) + __field(void *, fl_owner) __field(unsigned int, fl_pid) __field(unsigned int, fl_flags) __field(unsigned char, fl_type)
@@ -123,7 +123,7 @@ DECLARE_EVENT_CLASS(filelock_lease, __field(unsigned long, i_ino) __field(dev_t, s_dev) __field(struct file_lock *, fl_next) - __field(fl_owner_t, fl_owner) + __field(void *, fl_owner) __field(unsigned int, fl_flags) __field(unsigned char, fl_type) __field(unsigned long, fl_break_time)
@@ -176,7 +176,7 @@ TRACE_EVENT(generic_add_lease, __field(int, dcount) __field(int, icount) __field(dev_t, s_dev) - __field(fl_owner_t, fl_owner) + __field(void *, fl_owner) __field(unsigned int, fl_flags) __field(unsigned char, fl_type) ),
ipc/mqueue.c +1 -1
@@ -557,7 +557,7 @@ static ssize_t mqueue_read_file(struct file *filp, char __user *u_data,return ret; } -static int mqueue_flush_file (struct file *filp,fl_owner_t id) +static int mqueue_flush_file (struct file *filp,void *id) {struct mqueue_inode_info *info =MQUEUE_I (file_inode (filp));
Signature · 1 line
2.14.3
PATCH 2/10 nfsd: simplify put of fi_deleg_file
In reply to J. Bruce FieldsFrom: "J. Bruce Fields" <[email protected]>
fi_delegees is basically just a reference count on users of fi_deleg_file, which is cleared when fi_delegees goes to zero. The fi_deleg_file check here is redundant. Also add an assertion to make sure we don't have unbalanced puts.
--- fs/nfsd/nfs4state.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
fs/nfsd/nfs4state.c +4 -1
@@ -849,9 +849,12 @@ static void nfs4_put_deleg_lease(struct nfs4_file *fp) {struct file *filp =NULL ; +WARN_ON_ONCE (!fp->fi_delegees); +spin_lock (&fp->fi_lock); -if (fp->fi_deleg_file && --fp->fi_delegees ==0 ) +if (--fp->fi_delegees ==0 ) {swap (filp, fp->fi_deleg_file); + }spin_unlock (&fp->fi_lock);if (filp) {
Signature · 1 line
2.14.3
PATCH 3/10 nfsd: simplify nfs4_put_deleg_lease calls
In reply to J. Bruce FieldsFrom: "J. Bruce Fields" <[email protected]>
Every single caller gets the file out of the delegation, so let's do that once in nfs4_put_deleg_lease.
Plus we'll need it there for other reasons.
--- fs/nfsd/nfs4state.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
fs/nfsd/nfs4state.c +6 -5
@@ -845,9 +845,10 @@ nfs4_inc_and_copy_stateid(stateid_t *dst, struct nfs4_stid *stid)spin_unlock (&stid->sc_lock); } -static void nfs4_put_deleg_lease (struct nfs4_file *fp) +static void nfs4_put_deleg_lease (struct nfs4_delegation *dp) {struct file *filp =NULL ; +struct nfs4_file *fp = dp->dl_stid.sc_file;WARN_ON_ONCE (!fp->fi_delegees);
@@ -962,7 +963,7 @@ static void destroy_delegation(struct nfs4_delegation *dp)spin_unlock (&state_lock);if (unhashed) {put_clnt_odstate (dp->dl_clnt_odstate); -nfs4_put_deleg_lease (dp->dl_stid.sc_file); +nfs4_put_deleg_lease (dp);nfs4_put_stid (&dp->dl_stid); } }
@@ -974,7 +975,7 @@ static void revoke_delegation(struct nfs4_delegation *dp)WARN_ON (!list_empty (&dp->dl_recall_lru));put_clnt_odstate (dp->dl_clnt_odstate); -nfs4_put_deleg_lease (dp->dl_stid.sc_file); +nfs4_put_deleg_lease (dp);if (clp->cl_minorversion ==0 )nfs4_put_stid (&dp->dl_stid);
@@ -1885,7 +1886,7 @@ __destroy_client(struct nfs4_client *clp) dp = list_entry(reaplist.next, struct nfs4_delegation, dl_recall_lru);list_del_init (&dp->dl_recall_lru);put_clnt_odstate (dp->dl_clnt_odstate); -nfs4_put_deleg_lease (dp->dl_stid.sc_file); +nfs4_put_deleg_lease (dp);nfs4_put_stid (&dp->dl_stid); }while (!list_empty (&clp->cl_revoked)) {
@@ -7226,7 +7227,7 @@ nfs4_state_shutdown_net(struct net *net) dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);list_del_init (&dp->dl_recall_lru);put_clnt_odstate (dp->dl_clnt_odstate); -nfs4_put_deleg_lease (dp->dl_stid.sc_file); +nfs4_put_deleg_lease (dp);nfs4_put_stid (&dp->dl_stid); }
Signature · 1 line
2.14.3
cover Eliminate delegation self-conflicts v2
From: "J. Bruce Fields" <[email protected]>
This is my second attempt to fix the NFS server so we don't unnecessarily recall delegations when the operation breaking the delegation comes from the same client that holds the delegation.
To do that we need some way to pass the identity of the breaker down through the VFS. In my first attempt I tried passing that explicitly, but that touches a lot of code. So instead I'm experimenting with adding a field to the cred struct.
Testing has confirmed that this works. (And that the pynfs tests are broken--they *require* the server to break delegations on operations coming from the client, even though that's the less desireable behavior. I'm fixing that...).
J. Bruce Fields (10):
vfs: remove unnecessary fl_owner_t typedef
nfsd: simplify put of fi_deleg_file
nfsd: simplify nfs4_put_deleg_lease calls
nfsd4: set fl_owner to delegation, not file pointer
nfsd4: dp->dl_stid.sc_file doesn't need locking
nfsd: make nfs4_get_existing_delegation less confusing
nfsd: factor out common delegation-destruction code
nfsd: move sc_file assignment into alloc_init_deleg
nfsd: create a separate lease for each delegation
nfsd: clients don't need to break their own delegations
Documentation/filesystems/Locking | 2 + Documentation/filesystems/vfs.txt | 2 +- arch/ia64/kernel/perfmon.c | 2 +- arch/powerpc/platforms/cell/spufs/file.c | 2 +- arch/tile/kernel/hardwall.c | 2 +- drivers/android/binder.c | 2 +- drivers/char/ps3flash.c | 2 +- drivers/char/xillybus/xillybus_core.c | 2 +- drivers/firmware/efi/capsule-loader.c | 2 +- drivers/input/evdev.c | 2 +- drivers/misc/mic/scif/scif_fd.c | 2 +- drivers/scsi/osst.c | 2 +- drivers/scsi/st.c | 2 +- drivers/staging/lustre/lustre/llite/file.c | 2 +- drivers/usb/class/cdc-wdm.c | 2 +- drivers/usb/usb-skeleton.c | 2 +- fs/afs/internal.h | 2 +- fs/afs/write.c | 2 +- fs/cifs/cifsfs.h | 2 +- fs/cifs/file.c | 4 +- fs/ecryptfs/file.c | 2 +- fs/exofs/file.c | 2 +- fs/f2fs/file.c | 2 +- fs/fuse/file.c | 13 +- fs/fuse/fuse_i.h | 2 +- fs/lockd/clntproc.c | 4 +- fs/lockd/svc4proc.c | 2 +- fs/lockd/svcproc.c | 2 +- fs/locks.c | 6 +- fs/nfs/file.c | 2 +- fs/nfs/inode.c | 2 +- fs/nfs/nfs4_fs.h | 2 +- fs/nfs/nfs4file.c | 2 +- fs/nfs/nfs4state.c | 8 +- fs/nfsd/auth.c | 2 + fs/nfsd/nfs4proc.c | 1 + fs/nfsd/nfs4state.c | 267 ++++++++++++----------------- fs/nfsd/nfssvc.c | 1 + fs/notify/dnotify/dnotify.c | 6 +- fs/open.c | 2 +- include/linux/cred.h | 3 + include/linux/dnotify.h | 6 +- include/linux/fs.h | 18 +- include/linux/lockd/lockd.h | 4 +- include/linux/nfs_fs.h | 4 +- include/linux/sunrpc/svc.h | 1 + include/trace/events/filelock.h | 6 +- ipc/mqueue.c | 2 +- 48 files changed, 193 insertions(+), 223 deletions(-)
Signature · 1 line
2.14.3
PATCH 4/10 nfsd4: set fl_owner to delegation, not file pointer
From: "J. Bruce Fields" <[email protected]>
For now this makes no difference, as for files having delegations, there's a one-to-one relationship between an nfs4_file and its nfs4_delegation.
--- fs/nfsd/nfs4state.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-)
fs/nfsd/nfs4state.c +7 -10
@@ -859,7 +859,7 @@ static void nfs4_put_deleg_lease(struct nfs4_delegation *dp)spin_unlock (&fp->fi_lock);if (filp) { -vfs_setlease (filp,F_UNLCK ,NULL , (void **)&fp); +vfs_setlease (filp,F_UNLCK ,NULL , (void **)&dp);fput (filp); } }
@@ -3909,13 +3909,9 @@ 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; +struct nfs4_delegation *dp = (struct nfs4_delegation *)fl->fl_owner; +struct nfs4_file *fp = dp->dl_stid.sc_file; -if (!fp) { -WARN (1 ,"(%p)->fl_owner NULL\n" , fl); -return ret; - }if (fp->fi_had_conflict) {WARN (1 ,"duplicate break on %p\n" , fp);return ret;
@@ -4261,7 +4257,8 @@ static bool nfsd4_cb_channel_good(struct nfs4_client *clp)return clp->cl_minorversion && clp->cl_cb_state ==NFSD4_CB_UNKNOWN ; } -static struct file_lock *nfs4_alloc_init_lease (struct nfs4_file *fp,int flag) +static struct file_lock *nfs4_alloc_init_lease (struct nfs4_delegation *dp, +int flag) {struct file_lock *fl;
@@ -4272,7 +4269,7 @@ static struct file_lock *nfs4_alloc_init_lease(struct nfs4_file *fp, int flag) fl->fl_flags =FL_DELEG ; fl->fl_type = flag ==NFS4_OPEN_DELEGATE_READ ?F_RDLCK :F_WRLCK ; fl->fl_end =OFFSET_MAX ; - fl->fl_owner = fp; + fl->fl_owner = dp; fl->fl_pid = current->tgid;return fl; }
@@ -4296,7 +4293,7 @@ static int nfs4_setlease(struct nfs4_delegation *dp)struct file *filp;int status =0 ; - fl =nfs4_alloc_init_lease (fp,NFS4_OPEN_DELEGATE_READ ); + fl =nfs4_alloc_init_lease (dp,NFS4_OPEN_DELEGATE_READ );if (!fl)return -ENOMEM ; filp =find_readable_file (fp);
Signature · 1 line
2.14.3
PATCH 5/10 nfsd4: dp->dl_stid.sc_file doesn't need locking
In reply to J. Bruce FieldsFrom: "J. Bruce Fields" <[email protected]>
The delegation isn't visible to anyone yet.
--- fs/nfsd/nfs4state.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/nfsd/nfs4state.c +2 -1
@@ -4363,9 +4363,10 @@ nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh,return ERR_PTR (-ENOMEM );get_nfs4_file (fp); + dp->dl_stid.sc_file = fp; +spin_lock (&state_lock);spin_lock (&fp->fi_lock); - dp->dl_stid.sc_file = fp;if (!fp->fi_deleg_file) {spin_unlock (&fp->fi_lock);spin_unlock (&state_lock);
Signature · 1 line
2.14.3
PATCH 6/10 nfsd: make nfs4_get_existing_delegation less confusing
In reply to J. Bruce FieldsFrom: "J. Bruce Fields" <[email protected]>
This doesn't "get" anything.
--- fs/nfsd/nfs4state.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-)
fs/nfsd/nfs4state.c +9 -14
@@ -870,20 +870,16 @@ void nfs4_unhash_stid(struct nfs4_stid *s) }/** -* nfs4_get_existing_delegation - Discover if this delegation already exists +* nfs4_delegation_exists - Discover if this delegation already exists * @clp: a pointer to the nfs4_client we're granting a delegation to * @fp: a pointer to the nfs4_file we're granting a delegation on * * Return: -* On success: NULL if an existing delegation was not found. -* -* On error: -EAGAIN if one was previously granted to this nfs4_client -* for this nfs4_file. -* +* On success: true iff an existing delegation is found */ -static int -nfs4_get_existing_delegation (struct nfs4_client *clp,struct nfs4_file *fp) +static bool +nfs4_delegation_exists (struct nfs4_client *clp,struct nfs4_file *fp) {struct nfs4_delegation *searchdp =NULL ;struct nfs4_client *searchclp =NULL ;
@@ -916,15 +912,13 @@ nfs4_get_existing_delegation(struct nfs4_client *clp, struct nfs4_file *fp)static int hash_delegation_locked (struct nfs4_delegation *dp,struct nfs4_file *fp) { -int status;struct nfs4_client *clp = dp->dl_stid.sc_client;lockdep_assert_held (&state_lock);lockdep_assert_held (&fp->fi_lock); - status =nfs4_get_existing_delegation (clp, fp); -if (status) -return status; +if (nfs4_delegation_exists (clp, fp)) +return -EAGAIN ; ++fp->fi_delegees;refcount_inc (&dp->dl_stid.sc_count); dp->dl_stid.sc_type =NFS4_DELEG_STID ;
@@ -4343,7 +4337,7 @@ static struct nfs4_delegation * nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh, struct nfs4_file *fp, struct nfs4_clnt_odstate *odstate) { - int status; + int status = 0;struct nfs4_delegation *dp;if (fp->fi_had_conflict)
@@ -4351,7 +4345,8 @@ nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh,spin_lock (&state_lock);spin_lock (&fp->fi_lock); - status =nfs4_get_existing_delegation (clp, fp); +if (nfs4_delegation_exists (clp, fp)) + status = -EAGAIN ;spin_unlock (&fp->fi_lock);spin_unlock (&state_lock);
Signature · 1 line
2.14.3
PATCH 7/10 nfsd: factor out common delegation-destruction code
In reply to J. Bruce FieldsFrom: "J. Bruce Fields" <[email protected]>
Pull some duplicated code into a common helper.
This changes the order in destroy_delegation a little, but it looks to me like that shouldn't matter.
--- fs/nfsd/nfs4state.c | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-)
fs/nfsd/nfs4state.c +14 -17
@@ -864,6 +864,13 @@ static void nfs4_put_deleg_lease(struct nfs4_delegation *dp) } } +static void destroy_unhashed_deleg (struct nfs4_delegation *dp) +{ +put_clnt_odstate (dp->dl_clnt_odstate); +nfs4_put_deleg_lease (dp); +nfs4_put_stid (&dp->dl_stid); +} +void nfs4_unhash_stid (struct nfs4_stid *s) { s->sc_type =0 ;
@@ -955,11 +962,8 @@ static void destroy_delegation(struct nfs4_delegation *dp)spin_lock (&state_lock); unhashed =unhash_delegation_locked (dp);spin_unlock (&state_lock); -if (unhashed) { -put_clnt_odstate (dp->dl_clnt_odstate); -nfs4_put_deleg_lease (dp); -nfs4_put_stid (&dp->dl_stid); - } +if (unhashed) +destroy_unhashed_deleg (dp); }static void revoke_delegation (struct nfs4_delegation *dp)
@@ -968,17 +972,14 @@ static void revoke_delegation(struct nfs4_delegation *dp)WARN_ON (!list_empty (&dp->dl_recall_lru)); -put_clnt_odstate (dp->dl_clnt_odstate); -nfs4_put_deleg_lease (dp); - -if (clp->cl_minorversion ==0 ) -nfs4_put_stid (&dp->dl_stid); -else { +if (clp->cl_minorversion) { dp->dl_stid.sc_type =NFS4_REVOKED_DELEG_STID ; +refcount_inc (&dp->dl_stid.sc_count);spin_lock (&clp->cl_lock);list_add (&dp->dl_recall_lru, &clp->cl_revoked);spin_unlock (&clp->cl_lock); } +destroy_unhashed_deleg (dp); }/*
@@ -1879,9 +1880,7 @@ __destroy_client(struct nfs4_client *clp)while (!list_empty (&reaplist)) { dp = list_entry(reaplist.next, struct nfs4_delegation, dl_recall_lru);list_del_init (&dp->dl_recall_lru); -put_clnt_odstate (dp->dl_clnt_odstate); -nfs4_put_deleg_lease (dp); -nfs4_put_stid (&dp->dl_stid); +destroy_unhashed_deleg (dp); }while (!list_empty (&clp->cl_revoked)) { dp = list_entry(clp->cl_revoked.next, struct nfs4_delegation, dl_recall_lru);
@@ -7219,9 +7218,7 @@ nfs4_state_shutdown_net(struct net *net)list_for_each_safe (pos, next, &reaplist) { dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);list_del_init (&dp->dl_recall_lru); -put_clnt_odstate (dp->dl_clnt_odstate); -nfs4_put_deleg_lease (dp); -nfs4_put_stid (&dp->dl_stid); +destroy_unhashed_deleg (dp); }BUG_ON (!list_empty (&reaplist));
Signature · 1 line
2.14.3
PATCH 8/10 nfsd: move sc_file assignment into alloc_init_deleg
In reply to J. Bruce FieldsFrom: "J. Bruce Fields" <[email protected]>
Take an easy chance to simplify the caller a little.
--- fs/nfsd/nfs4state.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
fs/nfsd/nfs4state.c +5 -5
@@ -777,7 +777,8 @@ static void block_delegations(struct knfsd_fh *fh) }static struct nfs4_delegation * -alloc_init_deleg (struct nfs4_client *clp,struct svc_fh *current_fh, +alloc_init_deleg (struct nfs4_client *clp,struct nfs4_file *fp, +struct svc_fh *current_fh,struct nfs4_clnt_odstate *odstate) {struct nfs4_delegation *dp;
@@ -808,6 +809,8 @@ alloc_init_deleg(struct nfs4_client *clp, struct svc_fh *current_fh, dp->dl_retries =1 ;nfsd4_init_cb (&dp->dl_recall, dp->dl_stid.sc_client, &nfsd4_cb_recall_ops,NFSPROC4_CLNT_CB_RECALL ); +get_nfs4_file (fp); + dp->dl_stid.sc_file = fp;return dp; out_dec:atomic_long_dec (&num_delegations);
@@ -4352,13 +4355,10 @@ nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh,if (status)return ERR_PTR (status); - dp =alloc_init_deleg (clp, fh, odstate); + dp =alloc_init_deleg (clp, fp, fh, odstate);if (!dp)return ERR_PTR (-ENOMEM ); -get_nfs4_file (fp); - dp->dl_stid.sc_file = fp; -spin_lock (&state_lock);spin_lock (&fp->fi_lock);if (!fp->fi_deleg_file) {
Signature · 1 line
2.14.3
PATCH 9/10 nfsd: create a separate lease for each delegation
In reply to J. Bruce FieldsFrom: "J. Bruce Fields" <[email protected]>
Currently we only take one vfs-level delegation (lease) for each file, no matter how many clients hold delegations on that file.
Let's instead keep a one-to-one mapping between NFSv4 delegations and VFS delegations. This turns out to be simpler.
There is still a many-to-one mapping of NFS opens to NFS files, and the delegations on one file are all associated with one struct file. The VFS can still distinguish between these delegations since we're setting fl_owner to the struct nfs4_delegation now, not to the shared file.
I'm replacing at least one complicated function wholesale, which I don't like to do, but I haven't figured out how to do this more incrementally.
--- fs/nfsd/nfs4state.c | 173 ++++++++++++++++++++-------------------------------- 1 file changed, 65 insertions(+), 108 deletions(-)
fs/nfsd/nfs4state.c +65 -108
@@ -848,29 +848,34 @@ nfs4_inc_and_copy_stateid(stateid_t *dst, struct nfs4_stid *stid)spin_unlock (&stid->sc_lock); } -static void nfs4_put_deleg_lease (struct nfs4_delegation *dp) +static void put_deleg_file (struct nfs4_file *fp) {struct file *filp =NULL ; -struct nfs4_file *fp = dp->dl_stid.sc_file; - -WARN_ON_ONCE (!fp->fi_delegees);spin_lock (&fp->fi_lock); -if (--fp->fi_delegees ==0 ) { +if (--fp->fi_delegees ==0 )swap (filp, fp->fi_deleg_file); - }spin_unlock (&fp->fi_lock); -if (filp) { -vfs_setlease (filp,F_UNLCK ,NULL , (void **)&dp); +if (filp)fput (filp); - } +} + +static void nfs4_unlock_deleg_lease (struct nfs4_delegation *dp) +{ +struct nfs4_file *fp = dp->dl_stid.sc_file; +struct file *filp = fp->fi_deleg_file; + +WARN_ON_ONCE (!fp->fi_delegees); + +vfs_setlease (filp,F_UNLCK ,NULL , (void **)&dp); +put_deleg_file (fp); }static void destroy_unhashed_deleg (struct nfs4_delegation *dp) {put_clnt_odstate (dp->dl_clnt_odstate); -nfs4_put_deleg_lease (dp); +nfs4_unlock_deleg_lease (dp);nfs4_put_stid (&dp->dl_stid); }
@@ -929,7 +934,6 @@ hash_delegation_locked(struct nfs4_delegation *dp, struct nfs4_file *fp)if (nfs4_delegation_exists (clp, fp))return -EAGAIN ; - ++fp->fi_delegees;refcount_inc (&dp->dl_stid.sc_count); dp->dl_stid.sc_type =NFS4_DELEG_STID ;list_add (&dp->dl_perfile, &fp->fi_delegations);
@@ -3908,10 +3912,6 @@ nfsd_break_deleg_cb(struct file_lock *fl)struct nfs4_delegation *dp = (struct nfs4_delegation *)fl->fl_owner;struct nfs4_file *fp = dp->dl_stid.sc_file; -if (fp->fi_had_conflict) { -WARN (1 ,"duplicate break on %p\n" , fp); -return ret; - }/* * We don't want the locks code to timeout the lease for us; * we'll remove it ourself if a delegation isn't returned
@@ -3921,15 +3921,7 @@ 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 return true -* so that the lease code will go ahead and delete it. -*/ -if (list_empty (&fp->fi_delegations)) - ret = true; -else -list_for_each_entry (dp, &fp->fi_delegations, dl_perfile) -nfsd_break_one_deleg (dp); +nfsd_break_one_deleg (dp);spin_unlock (&fp->fi_lock);return ret; }
@@ -4267,121 +4259,86 @@ static struct file_lock *nfs4_alloc_init_lease(struct nfs4_delegation *dp, fl->fl_end =OFFSET_MAX ; fl->fl_owner = dp; fl->fl_pid = current->tgid; + fl->fl_file = dp->dl_stid.sc_file->fi_deleg_file;return fl; } -/** -* nfs4_setlease - Obtain a delegation by requesting lease from vfs layer -* @dp: a pointer to the nfs4_delegation we're adding. -* -* Return: -* On success: Return code will be 0 on success. -* -* On error: -EAGAIN if there was an existing delegation. -* nonzero if there is an error in other cases. -* -*/ - -static int nfs4_setlease (struct nfs4_delegation *dp) -{ -struct nfs4_file *fp = dp->dl_stid.sc_file; -struct file_lock *fl; -struct file *filp; -int status =0 ; - - fl =nfs4_alloc_init_lease (dp,NFS4_OPEN_DELEGATE_READ ); -if (!fl) -return -ENOMEM ; - filp =find_readable_file (fp); -if (!filp) { -/* We should always have a readable file here */ -WARN_ON_ONCE (1 ); -locks_free_lock (fl); -return -EBADF ; - } - fl->fl_file = filp; - 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? */ - status = -EAGAIN ; -if (fp->fi_had_conflict) - goto out_unlock; -/* Race breaker */ -if (fp->fi_deleg_file) { - status =hash_delegation_locked (dp, fp); - goto out_unlock; - } - fp->fi_deleg_file = filp; - fp->fi_delegees =0 ; - status =hash_delegation_locked (dp, fp); -spin_unlock (&fp->fi_lock); -spin_unlock (&state_lock); -if (status) { -/* Should never happen, this is a new fi_deleg_file */ -WARN_ON_ONCE (1 ); - goto out_fput; - } -return 0 ; -out_unlock: -spin_unlock (&fp->fi_lock); -spin_unlock (&state_lock); -out_fput: -fput (filp); -return status; -} -static struct nfs4_delegation *nfs4_set_delegation (struct nfs4_client *clp,struct svc_fh *fh,struct nfs4_file *fp,struct nfs4_clnt_odstate *odstate) {int status =0 ;struct nfs4_delegation *dp; +struct file *filp; +struct file_lock *fl; +/* +* The fi_had_conflict and nfs_get_existing_delegation checks +* here are just optimizations; we'll need to recheck them at +* the end: +*/ if (fp->fi_had_conflict)return ERR_PTR (-EAGAIN ); + filp =find_readable_file (fp); +if (!filp) { +/* We should always have a readable file here */ +WARN_ON_ONCE (1 ); +return ERR_PTR (-EBADF ); + }spin_lock (&state_lock);spin_lock (&fp->fi_lock);if (nfs4_delegation_exists (clp, fp)) status = -EAGAIN ; +else if (!fp->fi_deleg_file) { + fp->fi_deleg_file = filp; +/* increment early to prevent fi_deleg_file from being +* cleared */ + fp->fi_delegees =1 ; + filp =NULL ; + }else + fp->fi_delegees++;spin_unlock (&fp->fi_lock);spin_unlock (&state_lock); - +if (filp) +fput (filp);if (status)return ERR_PTR (status); + status = -ENOMEM ; dp =alloc_init_deleg (clp, fp, fh, odstate);if (!dp) -return ERR_PTR (-ENOMEM ); + goto out_delegees; + + fl =nfs4_alloc_init_lease (dp,NFS4_OPEN_DELEGATE_READ ); +if (!fl) + goto out_stid; + + status =vfs_setlease (fp->fi_deleg_file, fl->fl_type, &fl,NULL ); +if (fl) +locks_free_lock (fl); +if (status) + goto out_clnt_odstate;spin_lock (&state_lock);spin_lock (&fp->fi_lock); -if (!fp->fi_deleg_file) { -spin_unlock (&fp->fi_lock); -spin_unlock (&state_lock); - status =nfs4_setlease (dp); - goto out; - } -if (fp->fi_had_conflict) { +if (fp->fi_had_conflict) status = -EAGAIN ; - goto out_unlock; - } - status =hash_delegation_locked (dp, fp); -out_unlock: +else + status =hash_delegation_locked (dp, fp);spin_unlock (&fp->fi_lock);spin_unlock (&state_lock); -out: -if (status) { -put_clnt_odstate (dp->dl_clnt_odstate); -nfs4_put_stid (&dp->dl_stid); -return ERR_PTR (status); - } + +if (status) +destroy_unhashed_deleg (dp);return dp; +out_clnt_odstate: +put_clnt_odstate (dp->dl_clnt_odstate); +out_stid: +nfs4_put_stid (&dp->dl_stid); +out_delegees: +put_deleg_file (fp); +return ERR_PTR (status); }static void nfsd4_open_deleg_none_ext (struct nfsd4_open *open,int status)
Signature · 1 line
2.14.3
PATCH 10/10 nfsd: clients don't need to break their own delegations
From: "J. Bruce Fields" <[email protected]>
We currently revoke read delegations on any write open or any operation that modifies file data or metadata (including rename, link, and unlink). But if the delegation in question is the only read delegation and is held by the client performing the operation, that's not really necessary.
It's not always possible to prevent this in the NFSv4.0 case, because there's not always a way to determine which client an NFSv4.0 delegation came from. (In theory we could try to guess this from the transport layer, e.g., by assuming all traffic on a given TCP connection comes from the same client. But that's not really correct.)
In the NFSv4.1 case the session layer always tells us the client.
This patch should remove such self-conflicts in all cases where we can reliably determine the client from the compound.
To do that we need to track "who" is performing a given (possibly lease-breaking) file operation. There are a lot of those. So it seems simpler to pass this in struct task; this patch uses a new field in struct cred.
--- Documentation/filesystems/Locking | 2 ++ fs/locks.c | 4 ++++ fs/nfsd/auth.c | 2 ++ fs/nfsd/nfs4proc.c | 1 + fs/nfsd/nfs4state.c | 8 ++++++++ fs/nfsd/nfssvc.c | 1 + include/linux/cred.h | 3 +++ include/linux/fs.h | 1 + include/linux/sunrpc/svc.h | 1 + 9 files changed, 23 insertions(+)
Documentation/filesystems/Locking +2 -0
@@ -366,6 +366,7 @@ prototypes: int (*lm_grant)(struct file_lock *, struct file_lock *, int); void (*lm_break)(struct file_lock *); /* break_lease callback */ int (*lm_change)(struct file_lock **, int); + bool (*lm_breaker_owns_lease)(void *, struct file_lock *); locking rules:
@@ -376,6 +377,7 @@ lm_notify: yes yes no lm_grant: no no no lm_break: yes no no lm_change yes no no +lm_breaker_owns_lease: no no no [1]: ->lm_compare_owner and ->lm_owner_key are generally called with *an* inode->i_lock held. It may not be the i_lock of the inode
fs/locks.c +4 -0
@@ -1414,6 +1414,9 @@ static void time_out_leases(struct inode *inode, struct list_head *dispose)static bool leases_conflict (struct file_lock *lease,struct file_lock *breaker) { +if (lease->fl_lmops->lm_breaker_owns_lease && breaker->fl_owner && + lease->fl_lmops->lm_breaker_owns_lease (breaker->fl_owner, lease)) +return false;if ((breaker->fl_flags &FL_LAYOUT ) != (lease->fl_flags &FL_LAYOUT ))return false;if ((breaker->fl_flags &FL_DELEG ) && (lease->fl_flags &FL_LEASE ))
@@ -1462,6 +1465,7 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)if (IS_ERR (new_fl))return PTR_ERR (new_fl); new_fl->fl_flags = type; + new_fl->fl_owner =current_cred ()->lease_breaker;/* typically we will check that ctx is non-NULL before calling */ ctx =smp_load_acquire (&inode->i_flctx);
fs/nfsd/auth.c +2 -0
@@ -81,6 +81,8 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)else new->cap_effective =cap_raise_nfsd_set (new->cap_effective, new->cap_permitted); +if (rqstp->rq_lease_breaker) + new->lease_breaker = *rqstp->rq_lease_breaker;validate_process_creds ();put_cred (override_creds (new));put_cred (new);
fs/nfsd/nfs4proc.c +1 -0
@@ -1713,6 +1713,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp) op->status = status; goto encode_op; } + rqstp->rq_lease_breaker = (void **)&cstate->clp;while (!status && resp->opcnt < args->opcnt) { op = &args->ops[resp->opcnt++];
fs/nfsd/nfs4state.c +8 -0
@@ -3926,6 +3926,13 @@ nfsd_break_deleg_cb(struct file_lock *fl)return ret; } +static bool nfsd_breaker_owns_lease (void *breaker,struct file_lock *fl) +{ +struct nfs4_delegation *dl = fl->fl_owner; + +return dl->dl_stid.sc_client == breaker; +} +static int nfsd_change_deleg_cb (struct file_lock *onlist,int arg,struct list_head *dispose)
@@ -3937,6 +3944,7 @@ nfsd_change_deleg_cb(struct file_lock *onlist, int arg, }static const struct lock_manager_operations nfsd_lease_mng_ops = { + .lm_breaker_owns_lease = nfsd_breaker_owns_lease, .lm_break = nfsd_break_deleg_cb, .lm_change = nfsd_change_deleg_cb, };
fs/nfsd/nfssvc.c +1 -0
@@ -803,6 +803,7 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp) *statp = rpc_garbage_args;return 1 ; } + rqstp->rq_lease_breaker =NULL ;/* * Give the xdr decoder a chance to change this if it wants * (necessary in the NFSv4.0 compound case)
include/linux/cred.h +3 -0
@@ -139,6 +139,9 @@ struct cred {struct key *thread_keyring;/* keyring private to this thread */ struct key *request_key_auth;/* assumed request_key authority */ #endif +#ifdef CONFIG_FILE_LOCKING +void *lease_breaker;/* identify NFS client breaking a delegation */ +#endif #ifdef CONFIG_SECURITY void *security;/* subjective LSM security */ #endif
include/linux/fs.h +1 -0
@@ -959,6 +959,7 @@ struct lock_manager_operations {bool (*lm_break)(struct file_lock *);int (*lm_change)(struct file_lock *,int ,struct list_head *);void (*lm_setup)(struct file_lock *,void **); +bool (*lm_breaker_owns_lease)(void *,struct file_lock *); };struct lock_manager {
include/linux/sunrpc/svc.h +1 -0
@@ -293,6 +293,7 @@ struct svc_rqst {struct svc_cacherep * rq_cacherep;/* cache info */ struct task_struct *rq_task;/* service thread */ spinlock_t rq_lock;/* per-request lock */ +void ** rq_lease_breaker;/* The v4 client breaking a lease */ };#define SVC_NET (svc_rqst) (svc_rqst->rq_xprt->xpt_net)
Signature · 1 line
2.14.3
Quoted 69 lines · J. Bruce Fields
From: "J. Bruce Fields" <[email protected]>
This is my second attempt to fix the NFS server so we don't unnecessarily recall delegations when the operation breaking the delegation comes from the same client that holds the delegation.
To do that we need some way to pass the identity of the breaker down through the VFS. In my first attempt I tried passing that explicitly, but that touches a lot of code. So instead I'm experimenting with adding a field to the cred struct.
Testing has confirmed that this works. (And that the pynfs tests are broken--they *require* the server to break delegations on operations coming from the client, even though that's the less desireable behavior. I'm fixing that...).
J. Bruce Fields (10):
vfs: remove unnecessaryfl_owner_ttypedef
nfsd: simplify put offi_deleg_file
nfsd: simplifynfs4_put_deleg_leasecalls
nfsd4: setfl_ownerto delegation, not file pointer
nfsd4:dp->dl_stid.sc_filedoesn't need locking
nfsd: makenfs4_get_existing_delegationless confusing
nfsd: factor out common delegation-destruction code
nfsd: movesc_fileassignment intoalloc_init_deleg
nfsd: create a separate lease for each delegation
nfsd: clients don't need to break their own delegationsDocumentation/filesystems/Locking | 2 + Documentation/filesystems/vfs.txt | 2 +- arch/ia64/kernel/perfmon.c | 2 +- arch/powerpc/platforms/cell/spufs/file.c | 2 +- arch/tile/kernel/hardwall.c | 2 +- drivers/android/binder.c | 2 +- drivers/char/ps3flash.c | 2 +- drivers/char/xillybus/xillybus_core.c | 2 +- drivers/firmware/efi/capsule-loader.c | 2 +- drivers/input/evdev.c | 2 +- drivers/misc/mic/scif/scif_fd.c | 2 +- drivers/scsi/osst.c | 2 +- drivers/scsi/st.c | 2 +- drivers/staging/lustre/lustre/llite/file.c | 2 +- drivers/usb/class/cdc-wdm.c | 2 +- drivers/usb/usb-skeleton.c | 2 +- fs/afs/internal.h | 2 +- fs/afs/write.c | 2 +- fs/cifs/cifsfs.h | 2 +- fs/cifs/file.c | 4 +- fs/ecryptfs/file.c | 2 +- fs/exofs/file.c | 2 +- fs/f2fs/file.c | 2 +- fs/fuse/file.c | 13 +- fs/fuse/fuse_i.h | 2 +- fs/lockd/clntproc.c | 4 +- fs/lockd/svc4proc.c | 2 +- fs/lockd/svcproc.c | 2 +- fs/locks.c | 6 +- fs/nfs/file.c | 2 +- fs/nfs/inode.c | 2 +- fs/nfs/nfs4_fs.h | 2 +- fs/nfs/nfs4file.c | 2 +- fs/nfs/nfs4state.c | 8 +- fs/nfsd/auth.c | 2 + fs/nfsd/nfs4proc.c | 1 + fs/nfsd/nfs4state.c | 267 ++++++++++++----------------- fs/nfsd/nfssvc.c | 1 + fs/notify/dnotify/dnotify.c | 6 +- fs/open.c | 2 +- include/linux/cred.h | 3 +
Quoted 9 lines
include/linux/dnotify.h | 6 +- include/linux/fs.h | 18 +- include/linux/lockd/lockd.h | 4 +- include/linux/nfs_fs.h | 4 +- include/linux/sunrpc/svc.h | 1 + include/trace/events/filelock.h | 6 +- ipc/mqueue.c | 2 +- 48 files changed, 193 insertions(+), 223 deletions(-)
Nice work.
The whole first part of the series looks like a nice set of cleanups (sans the first patch, as there seems to be support to keep fl_owner_t typedef around). Giving each delegation its own lease makes a lot more sense, IMO.
On patches 2-9, you can add:
...and maybe get those into -next soon? The delegation code has been a source of subtle bugs in the past, so we really want this to get a lot of testing.
With patch 10, I have some concern about growing a common structure like struct cred with such a special-purpose field.
An alternative might be to utilize the keyrings there -- maybe stash a special sort of key on one of the keyrings with this pointer? We'd need to take care to prevent userland from doing this, but that seems like a solvable problem.
Cheers,
Signature · 1 line
Jeff Layton <[email protected]>
David Howells
maintainerRe: [PATCH 10/10] nfsd: clients don't need to break their own delegations
In reply to J. Bruce Fieldsinclude/linux/cred.h struct cred { · line 147
Quoted 10 lines · J. Bruce Fields
include/linux/cred.h +3
-0@@ -139,6 +139,9 @@ struct cred {struct key *thread_keyring;/* keyring private to this thread */ struct key *request_key_auth;/* assumed request_key authority */ #endif +#ifdef CONFIG_FILE_LOCKING +void *lease_breaker;/* identify NFS client breaking a delegation */ +#endif #ifdef CONFIG_SECURITY void *security;/* subjective LSM security */ #endif
Sorry, but ewww.
Two reasons for that comment:
(1) The cred struct may get retained long past where you expect if it gets attached to another process or a file descriptor.
(2) The ->lease_breaker pointer needs lifetime management in cred.c. It will potentially get copied around and may need cleaning up.
Can you stick your breaker identity in a key struct as Jeff suggested?
David
Re: [PATCH 10/10] nfsd: clients don't need to break their own delegations
Quoted 25 lines · David Howells
Quoted 12 lines · J. Bruce Fields
(quoted diff) +0
-0@@ -139,6 +139,9 @@ struct cred { struct key *thread_keyring; /* keyring private tothis thread */
struct key*request_key_auth; /* assumedrequest_keyauthority */
#endif(quoted diff) +2
-0+#ifdef CONFIG_FILE_LOCKING + void *lease_breaker; /* identify NFS clientbreaking a delegation */
include/linux/cred.h +1
-0+#endif #ifdef CONFIG_SECURITY void *security;/* subjective LSM Quoted 2 lines
security */
#endifSorry, but ewww.
Two reasons for that comment:
(1) The cred struct may get retained long past where you expect if
it gets
attached to another process or a file descriptor.
Quoted 7 lines
(2) The ->lease_breaker pointer needs lifetime management in
cred.c. It will
potentially get copied around and may need cleaning up.Can you stick your breaker identity in a key struct as Jeff suggested?
Bruce,
Do you really need to do more than just identify that this is a knfsd thread vs not a knfsd thread? I'm assuming that a knfsd thread will usually be in a position to recall delegations before it even initiates an operation on the inode in question, won't it?
IOW: what if you were to modify the lease code to allow knfsd threads to return a "please ignore me, and proceed with the operation that triggered the lease break" reply, and then handle conflicts between NFS clients outside the lease callback code altogether?
Cheers
Trond
Signature · 3 lines
Trond Myklebust Linux NFS client maintainer, PrimaryData [email protected]
Re: [PATCH 10/10] nfsd: clients don't need to break their own delegations
Quoted 34 lines · Trond Myklebust
Quoted 25 lines · David Howells
Quoted 12 lines · J. Bruce Fields
(quoted diff) +0
-0@@ -139,6 +139,9 @@ struct cred { struct key *thread_keyring; /* keyring private tothis thread */
struct key*request_key_auth; /* assumedrequest_keyauthority */
#endif(quoted diff) +2
-0+#ifdef CONFIG_FILE_LOCKING + void *lease_breaker; /* identify NFS clientbreaking a delegation */
include/linux/cred.h +1
-0+#endif #ifdef CONFIG_SECURITY void *security;/* subjective LSM Quoted 2 lines
security */
#endifSorry, but ewww.
Two reasons for that comment:
(1) The cred struct may get retained long past where you expect if
it gets
attached to another process or a file descriptor.Quoted 7 lines
(2) The ->lease_breaker pointer needs lifetime management in
cred.c. It will
potentially get copied around and may need cleaning up.Can you stick your breaker identity in a key struct as Jeff suggested?
Quoted 6 lines
Bruce,
Do you really need to do more than just identify that this is a knfsd thread vs not a knfsd thread? I'm assuming that a knfsd thread will usually be in a position to recall delegations before it even initiates an operation on the inode in question, won't it?
I think it could. I'm reluctant:
- Once we support write delegations, I think we end up having to do that before basically every operation on a inode.
- I'd like this to make it easy for someone to extend delegation support to userspace eventually too. I'm not sure exactly how we'd identify self-conflicts in that case (struct files?), but anyway I'd rather this wasn't too nfsd-specific.
That said, I'm still curious:
Quoted 4 lines
IOW: what if you were to modify the lease code to allow knfsd threads to return a "please ignore me, and proceed with the operation that triggered the lease break" reply, and then handle conflicts between NFS clients outside the lease callback code altogether?
So if you're a random bit of code, how would you recommend testing whether you're running in a knfsd thread?
--b.
Re: [PATCH 10/10] nfsd: clients don't need to break their own delegations
In reply to David HowellsQuoted 14 lines · David Howells
include/linux/cred.h struct cred { · line 147
Quoted 10 lines · J. Bruce Fields
include/linux/cred.h +3
-0@@ -139,6 +139,9 @@ struct cred {struct key *thread_keyring;/* keyring private to this thread */ struct key *request_key_auth;/* assumed request_key authority */ #endif +#ifdef CONFIG_FILE_LOCKING +void *lease_breaker;/* identify NFS client breaking a delegation */ +#endif #ifdef CONFIG_SECURITY void *security;/* subjective LSM security */ #endif Sorry, but ewww.
I'm sure you're right, but, to make sure I understand:
Quoted 4 lines
Two reasons for that comment:
(1) The cred struct may get retained long past where you expect if it gets attached to another process or a file descriptor.
How would that happen in the case of a knfsd thread?
Quoted 2 lines
(2) The ->lease_breaker pointer needs lifetime management in
cred.c. It will potentially get copied around and may need cleaning up.
Hm, OK.
Quoted 1 line
Can you stick your breaker identity in a key struct as Jeff suggested?
Probably so. I'm unfamiliar with the keyring code. How would you recommend doing that?
--b.
Re: [PATCH 10/10] nfsd: clients don't need to break their own delegations
In reply to J. Bruce FieldsQuoted 50 lines · J. Bruce Fields
Quoted 38 lines · Trond Myklebust
Quoted 29 lines · David Howells
Quoted 14 lines · J. Bruce Fields
(quoted diff) +0
-0@@ -139,6 +139,9 @@ struct cred { struct key *thread_keyring; /* keyring privateto
this thread */
struct key*request_key_auth; /* assumedrequest_keyauthority */
#endif(quoted diff) +2
-0+#ifdef CONFIG_FILE_LOCKING + void *lease_breaker; /* identify NFSclient
breaking a delegation */include/linux/cred.h +1
-0+#endif #ifdef CONFIG_SECURITY void *security;/* subjective Quoted 3 lines
LSM
security */
#endifSorry, but ewww.
Two reasons for that comment:
(1) The cred struct may get retained long past where you expect
if
it gets
attached to another process or a file descriptor.Quoted 7 lines
(2) The ->lease_breaker pointer needs lifetime management in
cred.c. It will
potentially get copied around and may need cleaning up.Can you stick your breaker identity in a key struct as Jeff suggested?
Quoted 8 lines
Bruce,
Do you really need to do more than just identify that this is a knfsd
thread vs not a knfsd thread? I'm assuming that a knfsd thread will usually be in a position to recall delegations before it even initiates
an operation on the inode in question, won't it?I think it could. I'm reluctant:
Quoted 10 lines
- Once we support write delegations, I think we end up having
to
do that before basically every operation on a inode.
- I'd like this to make it easy for someone to extend
delegation
support to userspace eventually too. I'm not sure exactly
how
we'd identify self-conflicts in that case (struct files?),
but
anyway I'd rather this wasn't too nfsd-specific.
That's my point. A userspace application is going to have to do something like this anyway. It cannot install hooks in the kernel to perform elaborate tests, so it is going to have to rely on something like the struct file_lock 'fl_nspid' field in order to determine whether or not to apply a lease break.
i.e.: the userspace rule should be to break the lease if and only if it is not owned by my process.
Quoted 11 lines
That said, I'm still curious:
Quoted 6 lines
IOW: what if you were to modify the lease code to allow knfsd threads
to return a "please ignore me, and proceed with the operation that triggered the lease break" reply, and then handle conflicts between NFS
clients outside the lease callback code altogether?So if you're a random bit of code, how would you recommend testing whether you're running in a knfsd thread?
Right now, the knfsd threads are regular kernel threads, with each thread appearing to userspace to be a process in its own right. Is there any reason why we could not assign them a group pid that would allow the fl_nspid mechanism to work (i.e. set task->group_leader)?
Signature · 3 lines
Trond Myklebust Linux NFS client maintainer, PrimaryData [email protected]
Re: [PATCH 10/10] nfsd: clients don't need to break their own delegations
Quoted 62 lines · Trond Myklebust
Quoted 50 lines · J. Bruce Fields
Quoted 38 lines · Trond Myklebust
Quoted 29 lines · David Howells
Quoted 14 lines · J. Bruce Fields
(quoted diff) +0
-0@@ -139,6 +139,9 @@ struct cred { struct key *thread_keyring; /* keyring privateto
this thread */
struct key*request_key_auth; /* assumedrequest_keyauthority */
#endif(quoted diff) +2
-0+#ifdef CONFIG_FILE_LOCKING + void *lease_breaker; /* identify NFSclient
breaking a delegation */include/linux/cred.h +1
-0+#endif #ifdef CONFIG_SECURITY void *security;/* subjective Quoted 3 lines
LSM
security */
#endifSorry, but ewww.
Two reasons for that comment:
(1) The cred struct may get retained long past where you expect
if
it gets
attached to another process or a file descriptor.Quoted 7 lines
(2) The ->lease_breaker pointer needs lifetime management in
cred.c. It will
potentially get copied around and may need cleaning up.Can you stick your breaker identity in a key struct as Jeff suggested?
Quoted 8 lines
Bruce,
Do you really need to do more than just identify that this is a knfsd
thread vs not a knfsd thread? I'm assuming that a knfsd thread will usually be in a position to recall delegations before it even initiates
an operation on the inode in question, won't it?I think it could. I'm reluctant:
Quoted 10 lines
- Once we support write delegations, I think we end up having
to
do that before basically every operation on a inode.
- I'd like this to make it easy for someone to extend
delegation
support to userspace eventually too. I'm not sure exactly
how
we'd identify self-conflicts in that case (struct files?),
but
anyway I'd rather this wasn't too nfsd-specific.
Quoted 8 lines
That's my point. A userspace application is going to have to do something like this anyway. It cannot install hooks in the kernel to perform elaborate tests, so it is going to have to rely on something like the struct
file_lock'fl_nspid' field in order to determine whether or not to apply a lease break.i.e.: the userspace rule should be to break the lease if and only if it is not owned by my process.
I was thinking of using struct file (whoops, not "struct files", sorry for the typo above) to avoid assuming too much about any userspace server's threading model.
Quoted 9 lines
Quoted 9 lines
That said, I'm still curious:
Quoted 6 lines
IOW: what if you were to modify the lease code to allow knfsd threads
to return a "please ignore me, and proceed with the operation that triggered the lease break" reply, and then handle conflicts between NFS
clients outside the lease callback code altogether?
Quoted 7 lines
Quoted 2 lines
So if you're a random bit of code, how would you recommend testing whether you're running in a knfsd thread?
Right now, the knfsd threads are regular kernel threads, with each thread appearing to userspace to be a process in its own right. Is there any reason why we could not assign them a group pid that would allow the
fl_nspidmechanism to work (i.e. settask->group_leader)?
Huh, OK, I hadn't thought about that.
--b.
Re: [PATCH 10/10] nfsd: clients don't need to break their own delegations
Quoted 7 lines · On Tue, Mar 20, 2018 at 12:02:57PM -0400, [email protected] wrote:
Quoted 4 lines · Trond Myklebust
Right now, the knfsd threads are regular kernel threads, with each thread appearing to userspace to be a process in its own right. Is there any reason why we could not assign them a group pid that would allow the
fl_nspidmechanism to work (i.e. settask->group_leader)?Huh, OK, I hadn't thought about that.
Thinking about it: as far as I can tell that's not meant to be modified on a running thread, so we need to create the thread the right way--all the nfsd threads need to be children of the same thread.
Currently we're using kthead_create() which makes them all children of kthreadd.
I spent a little time looking into forking threads from existing nfsd threads and started to feel like I was duplicating a lot of kthread code.
So now I wonder if it's possible to generalize kthreadd somehow.
--b.