5.10.220-rc1 review
Subsystems (7)
Greg Kroah-Hartman
maintainerPATCH 539/770 fanotify: refine the validation checks on non-dir inode mask
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Amir Goldstein <[email protected]>
[ Upstream commit 8698e3bab4dd7968666e84e111d0bfd17c040e77 ]
Commit ceaf69f8eadc ("fanotify: do not allow setting dirent events in mask of non-dir") added restrictions about setting dirent events in the mask of a non-dir inode mark, which does not make any sense.
For backward compatibility, these restictions were added only to new (v5.17+) APIs.
It also does not make any sense to set the flags FAN_EVENT_ON_CHILD or FAN_ONDIR in the mask of a non-dir inode. Add these flags to the dir-only restriction of the new APIs as well.
Move the check of the dir-only flags for new APIs into the helper fanotify_events_supported(), which is only called for FAN_MARK_ADD, because there is no need to error on an attempt to remove the dir-only flags from non-dir inode.
--- fs/notify/fanotify/fanotify_user.c | 30 +++++++++++++++--------------- include/linux/fanotify.h | 4 ++++ 2 files changed, 19 insertions(+), 15 deletions(-)
fs/notify/fanotify/fanotify_user.c +15 -15
@@ -1501,10 +1501,14 @@ static int fanotify_test_fid(struct dentry *dentry)return 0 ; } -static int fanotify_events_supported (struct path *path,__u64 mask, +static int fanotify_events_supported (struct fsnotify_group *group, +struct path *path,__u64 mask,unsigned int flags) {unsigned int mark_type = flags &FANOTIFY_MARK_TYPE_BITS ; +/* Strict validation of events in non-dir inode mask with v5.17+ APIs */ +bool strict_dir_events =FAN_GROUP_FLAG (group,FAN_REPORT_TARGET_FID ) || + (mask &FAN_RENAME );/* * Some filesystems such as 'proc' acquire unusual locks when opening
@@ -1532,6 +1536,15 @@ static int fanotify_events_supported(struct path *path, __u64 mask, path->mnt->mnt_sb->s_flags & SB_NOUSER)return -EINVAL ; +/* +* We shouldn't have allowed setting dirent events and the directory +* flags FAN_ONDIR and FAN_EVENT_ON_CHILD in mask of non-dir inode, +* but because we always allowed it, error only when using new APIs. +*/ +if (strict_dir_events && mark_type ==FAN_MARK_INODE && + !d_is_dir (path->dentry) && (mask &FANOTIFY_DIRONLY_EVENT_BITS )) +return -ENOTDIR ; +return 0 ; }
@@ -1678,7 +1691,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, goto fput_and_out;if (flags &FAN_MARK_ADD ) { - ret =fanotify_events_supported (&path, mask, flags); + ret =fanotify_events_supported (group, &path, mask, flags);if (ret) goto path_put_and_out; }
@@ -1701,19 +1714,6 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,else mnt = path.mnt; -/* -* FAN_RENAME is not allowed on non-dir (for now). -* We shouldn't have allowed setting any dirent events in mask of -* non-dir, but because we always allowed it, error only if group -* was initialized with the new flag FAN_REPORT_TARGET_FID. -*/ - ret = -ENOTDIR ; -if (inode && !S_ISDIR (inode->i_mode) && - ((mask &FAN_RENAME ) || - ((mask &FANOTIFY_DIRENT_EVENTS ) && -FAN_GROUP_FLAG (group,FAN_REPORT_TARGET_FID )))) - goto path_put_and_out; -/* Mask out FAN_EVENT_ON_CHILD flag for sb/mount/non-dir marks */ if (mnt || !S_ISDIR (inode->i_mode)) { mask &= ~FAN_EVENT_ON_CHILD ;
include/linux/fanotify.h +4 -0
@@ -113,6 +113,10 @@ extern struct ctl_table fanotify_table[]; /* for sysctl */ FANOTIFY_PERM_EVENTS | \ FAN_Q_OVERFLOW | FAN_ONDIR) +/* Events and flags relevant only for directories */ +#define FANOTIFY_DIRONLY_EVENT_BITS (FANOTIFY_DIRENT_EVENTS | \ + FAN_EVENT_ON_CHILD | FAN_ONDIR) +#define ALL_FANOTIFY_EVENT_BITS (FANOTIFY_OUTGOING_EVENTS | \ FANOTIFY_EVENT_FLAGS)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 540/770 NFS: restore module put when manager exits.
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: NeilBrown <[email protected]>
[ Upstream commit 080abad71e99d2becf38c978572982130b927a28 ]
Commit f49169c97fce ("NFSD: Remove svc_serv_ops::svo_module") removed calls to module_put_and_kthread_exit() from threads that acted as SUNRPC servers and had a related svc_serv_ops structure. This was correct.
It ALSO removed the module_put_and_kthread_exit() call from nfs4_run_state_manager() which is NOT a SUNRPC service.
Consequently every time the NFSv4 state manager runs the module count increments and won't be decremented. So the nfsv4 module cannot be unloaded.
So restore the module_put_and_kthread_exit() call.
--- fs/nfs/nfs4state.c | 1 + 1 file changed, 1 insertion(+)
fs/nfs/nfs4state.c +1 -0
@@ -2757,6 +2757,7 @@ static int nfs4_run_state_manager(void *ptr) goto again;nfs_put_client (clp); +module_put_and_kthread_exit (0 );return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 541/770 NFSD: Decode NFSv4 birth time attribute
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 5b2f3e0777da2a5dd62824bbe2fdab1d12caaf8f ]
NFSD has advertised support for the NFSv4 time_create attribute since commit e377a3e698fb ("nfsd: Add support for the birth time attribute").
Igor Mammedov reports that Mac OS clients attempt to set the NFSv4 birth time attribute via OPEN(CREATE) and SETATTR if the server indicates that it supports it, but since the above commit was merged, those attempts now fail.
Table 5 in RFC 8881 lists the time_create attribute as one that can be both set and retrieved, but the above commit did not add server support for clients to provide a time_create attribute. IMO that's a bug in our implementation of the NFSv4 protocol, which this commit addresses.
Whether NFSD silently ignores the new birth time or actually sets it is another matter. I haven't found another filesystem service in the Linux kernel that enables users or clients to modify a file's birth time attribute.
This commit reflects my (perhaps incorrect) understanding of whether Linux users can set a file's birth time. NFSD will now recognize a time_create attribute but it ignores its value. It clears the time_create bit in the returned attribute bitmask to indicate that the value was not used.
--- fs/nfsd/nfs4xdr.c | 9 +++++++++ fs/nfsd/nfsd.h | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-)
fs/nfsd/nfs4xdr.c +9 -0
@@ -470,6 +470,15 @@ nfsd4_decode_fattr4(struct nfsd4_compoundargs *argp, u32 *bmval, u32 bmlen,return nfserr_bad_xdr; } } +if (bmval[1 ] &FATTR4_WORD1_TIME_CREATE ) { +struct timespec64 ts; + +/* No Linux filesystem supports setting this attribute. */ + bmval[1 ] &= ~FATTR4_WORD1_TIME_CREATE ; + status =nfsd4_decode_nfstime4 (argp, &ts); +if (status) +return status; + }if (bmval[1 ] &FATTR4_WORD1_TIME_MODIFY_SET ) {u32 set_it;
fs/nfsd/nfsd.h +2 -1
@@ -465,7 +465,8 @@ static inline bool nfsd_attrs_supported(u32 minorversion, const u32 *bmval) (FATTR4_WORD0_SIZE | FATTR4_WORD0_ACL)#define NFSD_WRITEABLE_ATTRS_WORD1 \ (FATTR4_WORD1_MODE | FATTR4_WORD1_OWNER | FATTR4_WORD1_OWNER_GROUP \ - | FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET) + | FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_CREATE \ + | FATTR4_WORD1_TIME_MODIFY_SET)#ifdef CONFIG_NFSD_V4_SECURITY_LABEL #define MAYBE_FATTR4_WORD2_SECURITY_LABEL \ FATTR4_WORD2_SECURITY_LABEL
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 542/770 lockd: set fl_owner when unlocking files
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeff Layton <[email protected]>
[ Upstream commit aec158242b87a43d83322e99bc71ab4428e5ab79 ]
Unlocking a POSIX lock on an inode with vfs_lock_file only works if the owner matches. Ensure we set it in the request.
--- fs/lockd/svcsubs.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
fs/lockd/svcsubs.c +3 -2
@@ -176,7 +176,7 @@ nlm_delete_file(struct nlm_file *file) } } -static int nlm_unlock_files (struct nlm_file *file) +static int nlm_unlock_files (struct nlm_file *file,fl_owner_t owner) {struct file_lock lock;
@@ -184,6 +184,7 @@ static int nlm_unlock_files(struct nlm_file *file) lock.fl_type =F_UNLCK ; lock.fl_start =0 ; lock.fl_end =OFFSET_MAX ; + lock.fl_owner = owner;if (file->f_file[O_RDONLY ] &&vfs_lock_file (file->f_file[O_RDONLY ],F_SETLK , &lock,NULL )) goto out_err;
@@ -225,7 +226,7 @@ nlm_traverse_locks(struct nlm_host *host, struct nlm_file *file,if (match (lockhost, host)) {spin_unlock (&flctx->flc_lock); -if (nlm_unlock_files (file)) +if (nlm_unlock_files (file, fl->fl_owner))return 1 ; goto again; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 543/770 lockd: fix nlm_close_files
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeff Layton <[email protected]>
[ Upstream commit 1197eb5906a5464dbaea24cac296dfc38499cc00 ]
This loop condition tries a bit too hard to be clever. Just test for the two indices we care about explicitly.
--- fs/lockd/svcsubs.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
fs/lockd/svcsubs.c +4 -5
@@ -283,11 +283,10 @@ nlm_file_inuse(struct nlm_file *file)static void nlm_close_files (struct nlm_file *file) { -struct file *f; - -for (f = file->f_file[0 ]; f <= file->f_file[1 ]; f++) -if (f) - nlmsvc_ops->fclose (f); +if (file->f_file[O_RDONLY ]) + nlmsvc_ops->fclose (file->f_file[O_RDONLY ]); +if (file->f_file[O_WRONLY ]) + nlmsvc_ops->fclose (file->f_file[O_WRONLY ]); }/*
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 544/770 fs: inotify: Fix typo in inotify comment
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Oliver Ford <[email protected]>
[ Upstream commit c05787b4c2f80a3bebcb9cdbf255d4fa5c1e24e1 ]
Correct spelling in comment.
--- fs/notify/inotify/inotify_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/notify/inotify/inotify_user.c +1 -1
@@ -123,7 +123,7 @@ static inline u32 inotify_mask_to_arg(__u32 mask) IN_Q_OVERFLOW); } -/* intofiy userspace file descriptor functions */ +/* inotify userspace file descriptor functions */ static __poll_t inotify_poll (struct file *file,poll_table *wait) {struct fsnotify_group *group = file->private_data;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 545/770 fanotify: prepare for setting event flags in ignore mask
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Amir Goldstein <[email protected]>
[ Upstream commit 31a371e419c885e0f137ce70395356ba8639dc52 ]
Setting flags FAN_ONDIR FAN_EVENT_ON_CHILD in ignore mask has no effect. The FAN_EVENT_ON_CHILD flag in mask implicitly applies to ignore mask and ignore mask is always implicitly applied to events on directories.
Define a mark flag that replaces this legacy behavior with logic of applying the ignore mask according to event flags in ignore mask.
Implement the new logic to prepare for supporting an ignore mask that ignores events on children and ignore mask that does not ignore events on directories.
To emphasize the change in terminology, also rename ignored_mask mark member to ignore_mask and use accessors to get only the effective ignored events or the ignored events and flags.
This change in terminology finally aligns with the "ignore mask" language in man pages and in most of the comments.
--- fs/notify/fanotify/fanotify.c | 19 ++++--- fs/notify/fanotify/fanotify_user.c | 21 ++++--- fs/notify/fdinfo.c | 6 +- fs/notify/fsnotify.c | 21 ++++--- include/linux/fsnotify_backend.h | 89 ++++++++++++++++++++++++++++-- 5 files changed, 121 insertions(+), 35 deletions(-)
fs/notify/fanotify/fanotify.c +11 -8
@@ -295,12 +295,13 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group, const void *data, int data_type, struct inode *dir) { - __u32 marks_mask = 0, marks_ignored_mask = 0; + __u32 marks_mask = 0, marks_ignore_mask = 0;__u32 test_mask, user_mask =FANOTIFY_OUTGOING_EVENTS |FANOTIFY_EVENT_FLAGS ;const struct path *path =fsnotify_data_path (data, data_type);unsigned int fid_mode =FAN_GROUP_FLAG (group,FANOTIFY_FID_BITS );struct fsnotify_mark *mark; +bool ondir = event_mask &FAN_ONDIR ;int type; pr_debug("%s: report_mask=%x mask=%x data=%p data_type=%d\n",
@@ -315,19 +316,21 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group,return 0 ; }else if (!(fid_mode &FAN_REPORT_FID )) {/* Do we have a directory inode to report? */ -if (!dir && !(event_mask &FS_ISDIR )) +if (!dir && !ondir)return 0 ; } fsnotify_foreach_iter_mark_type(iter_info, mark, type) { -/* Apply ignore mask regardless of mark's ISDIR flag */ - marks_ignored_mask |= mark->ignored_mask; +/* +* Apply ignore mask depending on event flags in ignore mask. +*/ + marks_ignore_mask |= +fsnotify_effective_ignore_mask (mark, ondir, type);/* -* If the event is on dir and this mark doesn't care about -* events on dir, don't send it! +* Send the event depending on event flags in mark mask. */ -if (event_mask &FS_ISDIR && !(mark->mask &FS_ISDIR )) +if (!fsnotify_mask_applicable (mark->mask, ondir, type))continue ; marks_mask |= mark->mask;
@@ -336,7 +339,7 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group, *match_mask |=1U << type; } - test_mask = event_mask & marks_mask & ~marks_ignored_mask; + test_mask = event_mask & marks_mask & ~marks_ignore_mask;/* * For dirent modification events (create/delete/move) that do not carry
fs/notify/fanotify/fanotify_user.c +12 -9
@@ -1000,7 +1000,7 @@ static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark,if (!(flags &FAN_MARK_IGNORED_MASK )) { fsn_mark->mask &= ~mask; }else { - fsn_mark->ignored_mask &= ~mask; + fsn_mark->ignore_mask &= ~mask; } newmask =fsnotify_calc_mask (fsn_mark);/*
@@ -1009,7 +1009,7 @@ static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark,* changes to the mask. * Destroy mark when only umask bits remain. */ - *destroy = !((fsn_mark->mask | fsn_mark->ignored_mask) & ~umask); + *destroy = !((fsn_mark->mask | fsn_mark->ignore_mask) & ~umask);spin_unlock (&fsn_mark->lock);return oldmask & ~newmask;
@@ -1078,7 +1078,7 @@ static bool fanotify_mark_update_flags(struct fsnotify_mark *fsn_mark,/* * Setting FAN_MARK_IGNORED_SURV_MODIFY for the first time may lead to * the removal of the FS_MODIFY bit in calculated mask if it was set -* because of an ignored mask that is now going to survive FS_MODIFY. +* because of an ignore mask that is now going to survive FS_MODIFY. */ if ((fan_flags & FAN_MARK_IGNORED_MASK) && (fan_flags & FAN_MARK_IGNORED_SURV_MODIFY) &&
@@ -1111,7 +1111,7 @@ static bool fanotify_mark_add_to_mask(struct fsnotify_mark *fsn_mark,if (!(fan_flags &FAN_MARK_IGNORED_MASK )) fsn_mark->mask |= mask;else - fsn_mark->ignored_mask |= mask; + fsn_mark->ignore_mask |= mask; recalc =fsnotify_calc_mask (fsn_mark) & ~fsnotify_conn_mask (fsn_mark->connector);
@@ -1249,7 +1249,7 @@ static int fanotify_add_inode_mark(struct fsnotify_group *group,/* * If some other task has this inode open for write we should not add -* an ignored mark, unless that ignored mark is supposed to survive +* an ignore mask, unless that ignore mask is supposed to survive * modification changes anyway. */ if ((flags & FAN_MARK_IGNORED_MASK) &&
@@ -1559,7 +1559,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,__kernel_fsid_t __fsid, *fsid =NULL ;u32 valid_mask =FANOTIFY_EVENTS |FANOTIFY_EVENT_FLAGS ;unsigned int mark_type = flags &FANOTIFY_MARK_TYPE_BITS ; -bool ignored = flags &FAN_MARK_IGNORED_MASK ; +bool ignore = flags &FAN_MARK_IGNORED_MASK ;unsigned int obj_type, fid_mode;u32 umask =0 ;int ret;
@@ -1608,8 +1608,11 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,if (mask & ~valid_mask)return -EINVAL ; -/* Event flags (ONDIR, ON_CHILD) are meaningless in ignored mask */ -if (ignored) +/* +* Event flags (FAN_ONDIR, FAN_EVENT_ON_CHILD) have no effect with +* FAN_MARK_IGNORED_MASK. +*/ +if (ignore) mask &= ~FANOTIFY_EVENT_FLAGS ; f =fdget (fanotify_fd);
@@ -1723,7 +1726,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,* events with parent/name info for non-directory. */ if ((fid_mode &FAN_REPORT_DIR_FID ) && - (flags &FAN_MARK_ADD ) && !ignored) + (flags &FAN_MARK_ADD ) && !ignore) mask |=FAN_EVENT_ON_CHILD ; }
fs/notify/fdinfo.c +3 -3
@@ -113,7 +113,7 @@ static void fanotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark)return ;seq_printf (m,"fanotify ino:%lx sdev:%x mflags:%x mask:%x ignored_mask:%x " , inode->i_ino, inode->i_sb->s_dev, - mflags, mark->mask, mark->ignored_mask); + mflags, mark->mask, mark->ignore_mask);show_mark_fhandle (m, inode);seq_putc (m,'\n' );iput (inode);
@@ -121,12 +121,12 @@ static void fanotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark)struct mount *mnt =fsnotify_conn_mount (mark->connector);seq_printf (m,"fanotify mnt_id:%x mflags:%x mask:%x ignored_mask:%x\n" , - mnt->mnt_id, mflags, mark->mask, mark->ignored_mask); + mnt->mnt_id, mflags, mark->mask, mark->ignore_mask); }else if (mark->connector->type ==FSNOTIFY_OBJ_TYPE_SB ) {struct super_block *sb =fsnotify_conn_sb (mark->connector);seq_printf (m,"fanotify sdev:%x mflags:%x mask:%x ignored_mask:%x\n" , - sb->s_dev, mflags, mark->mask, mark->ignored_mask); + sb->s_dev, mflags, mark->mask, mark->ignore_mask); } }
fs/notify/fsnotify.c +12 -9
@@ -324,7 +324,8 @@ static int send_to_group(__u32 mask, const void *data, int data_type,struct fsnotify_group *group =NULL ;__u32 test_mask = (mask &ALL_FSNOTIFY_EVENTS );__u32 marks_mask =0 ; -__u32 marks_ignored_mask =0 ; +__u32 marks_ignore_mask =0 ; +bool is_dir = mask &FS_ISDIR ;struct fsnotify_mark *mark;int type;
@@ -336,7 +337,7 @@ static int send_to_group(__u32 mask, const void *data, int data_type, fsnotify_foreach_iter_mark_type(iter_info, mark, type) {if (!(mark->flags &FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY )) - mark->ignored_mask =0 ; + mark->ignore_mask =0 ; } }
@@ -344,14 +345,15 @@ static int send_to_group(__u32 mask, const void *data, int data_type, fsnotify_foreach_iter_mark_type(iter_info, mark, type) { group = mark->group; marks_mask |= mark->mask; - marks_ignored_mask |= mark->ignored_mask; + marks_ignore_mask |= +fsnotify_effective_ignore_mask (mark, is_dir, type); } -pr_debug ("%s: group=%p mask=%x marks_mask=%x marks_ignored_mask=%x data=%p data_type=%d dir=%p cookie=%d\n" , - __func__, group, mask, marks_mask, marks_ignored_mask, +pr_debug ("%s: group=%p mask=%x marks_mask=%x marks_ignore_mask=%x data=%p data_type=%d dir=%p cookie=%d\n" , + __func__, group, mask, marks_mask, marks_ignore_mask, data, data_type, dir, cookie); -if (!(test_mask & marks_mask & ~marks_ignored_mask)) +if (!(test_mask & marks_mask & ~marks_ignore_mask))return 0 ;if (group->ops->handle_event) {
@@ -423,7 +425,8 @@ static bool fsnotify_iter_select_report_types(* But is *this mark* watching children? */ if (type ==FSNOTIFY_ITER_TYPE_PARENT && - !(mark->mask &FS_EVENT_ON_CHILD )) + !(mark->mask &FS_EVENT_ON_CHILD ) && + !(fsnotify_ignore_mask (mark) &FS_EVENT_ON_CHILD ))continue ;fsnotify_iter_set_report_type (iter_info, type);
@@ -532,8 +535,8 @@ int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir,/* -* If this is a modify event we may need to clear some ignored masks. -* In that case, the object with ignored masks will have the FS_MODIFY +* If this is a modify event we may need to clear some ignore masks. +* In that case, the object with ignore masks will have the FS_MODIFY * event in its mask. * Otherwise, return if none of the marks care about this type of event. */
include/linux/fsnotify_backend.h +83 -6
119 lines not on this page · raw message
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 546/770 fanotify: cleanups for fanotify_mark() input validations
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Amir Goldstein <[email protected]>
[ Upstream commit 8afd7215aa97f8868d033f6e1d01a276ab2d29c0 ]
Create helper fanotify_may_update_existing_mark() for checking for conflicts between existing mark flags and fanotify_mark() flags.
Use variable mark_cmd to make the checks for mark command bits cleaner.
--- fs/notify/fanotify/fanotify_user.c | 30 +++++++++++++++++++++--------- include/linux/fanotify.h | 9 +++++---- 2 files changed, 26 insertions(+), 13 deletions(-)
fs/notify/fanotify/fanotify_user.c +21 -9
@@ -1175,6 +1175,19 @@ static int fanotify_group_init_error_pool(struct fsnotify_group *group) sizeof(struct fanotify_error_event)); } +static int fanotify_may_update_existing_mark (struct fsnotify_mark *fsn_mark, +unsigned int fan_flags) +{ +/* +* Non evictable mark cannot be downgraded to evictable mark. +*/ +if (fan_flags &FAN_MARK_EVICTABLE && + !(fsn_mark->flags &FSNOTIFY_MARK_FLAG_NO_IREF )) +return -EEXIST ; + +return 0 ; +} + static int fanotify_add_mark(struct fsnotify_group *group, fsnotify_connp_t *connp, unsigned int obj_type, __u32 mask, unsigned int fan_flags,
@@ -1196,13 +1209,11 @@ static int fanotify_add_mark(struct fsnotify_group *group, }/* -* Non evictable mark cannot be downgraded to evictable mark. +* Check if requested mark flags conflict with an existing mark flags. */ -if (fan_flags &FAN_MARK_EVICTABLE && - !(fsn_mark->flags &FSNOTIFY_MARK_FLAG_NO_IREF )) { - ret = -EEXIST ; + ret =fanotify_may_update_existing_mark (fsn_mark, fan_flags); +if (ret) goto out; - }/* * Error events are pre-allocated per group, only if strictly
@@ -1559,6 +1570,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,__kernel_fsid_t __fsid, *fsid =NULL ;u32 valid_mask =FANOTIFY_EVENTS |FANOTIFY_EVENT_FLAGS ;unsigned int mark_type = flags &FANOTIFY_MARK_TYPE_BITS ; +unsigned int mark_cmd = flags &FANOTIFY_MARK_CMD_BITS ;bool ignore = flags &FAN_MARK_IGNORED_MASK ;unsigned int obj_type, fid_mode;u32 umask =0 ;
@@ -1588,7 +1600,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,return -EINVAL ; } -switch (flags & (FAN_MARK_ADD |FAN_MARK_REMOVE |FAN_MARK_FLUSH )) { +switch (mark_cmd) {case FAN_MARK_ADD :case FAN_MARK_REMOVE :if (!mask)
@@ -1677,7 +1689,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,if (mask &FAN_RENAME && !(fid_mode &FAN_REPORT_NAME )) goto fput_and_out; -if (flags &FAN_MARK_FLUSH ) { +if (mark_cmd ==FAN_MARK_FLUSH ) { ret =0 ;if (mark_type ==FAN_MARK_MOUNT )fsnotify_clear_vfsmount_marks_by_group (group);
@@ -1693,7 +1705,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask,if (ret) goto fput_and_out; -if (flags &FAN_MARK_ADD ) { +if (mark_cmd ==FAN_MARK_ADD ) { ret =fanotify_events_supported (group, &path, mask, flags);if (ret) goto path_put_and_out;
@@ -1731,7 +1743,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, }/* create/update an inode mark */ -switch (flags & (FAN_MARK_ADD |FAN_MARK_REMOVE )) { +switch (mark_cmd) {case FAN_MARK_ADD :if (mark_type ==FAN_MARK_MOUNT ) ret = fanotify_add_vfsmount_mark(group, mnt, mask,
include/linux/fanotify.h +5 -4
@@ -61,15 +61,16 @@ extern struct ctl_table fanotify_table[]; /* for sysctl */#define FANOTIFY_MARK_TYPE_BITS (FAN_MARK_INODE | FAN_MARK_MOUNT | \ FAN_MARK_FILESYSTEM) +#define FANOTIFY_MARK_CMD_BITS (FAN_MARK_ADD | FAN_MARK_REMOVE | \ + FAN_MARK_FLUSH) +#define FANOTIFY_MARK_FLAGS (FANOTIFY_MARK_TYPE_BITS | \ - FAN_MARK_ADD | \ - FAN_MARK_REMOVE | \ + FANOTIFY_MARK_CMD_BITS | \ FAN_MARK_DONT_FOLLOW | \ FAN_MARK_ONLYDIR | \ FAN_MARK_IGNORED_MASK | \ FAN_MARK_IGNORED_SURV_MODIFY | \ - FAN_MARK_EVICTABLE | \ - FAN_MARK_FLUSH) + FAN_MARK_EVICTABLE)/* * Events that can be reported with data type FSNOTIFY_EVENT_PATH.
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 547/770 fanotify: introduce FAN_MARK_IGNORE
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Amir Goldstein <[email protected]>
[ Upstream commit e252f2ed1c8c6c3884ab5dd34e003ed21f1fe6e0 ]
This flag is a new way to configure ignore mask which allows adding and removing the event flags FAN_ONDIR and FAN_EVENT_ON_CHILD in ignore mask.
The legacy FAN_MARK_IGNORED_MASK flag would always ignore events on directories and would ignore events on children depending on whether the FAN_EVENT_ON_CHILD flag was set in the (non ignored) mask.
FAN_MARK_IGNORE can be used to ignore events on children without setting FAN_EVENT_ON_CHILD in the mark's mask and will not ignore events on directories unconditionally, only when FAN_ONDIR is set in ignore mask.
The new behavior is non-downgradable. After calling fanotify_mark() with FAN_MARK_IGNORE once, calling fanotify_mark() with FAN_MARK_IGNORED_MASK on the same object will return EEXIST error.
Setting the event flags with FAN_MARK_IGNORE on a non-dir inode mark has no meaning and will return ENOTDIR error.
The meaning of FAN_MARK_IGNORED_SURV_MODIFY is preserved with the new FAN_MARK_IGNORE flag, but with a few semantic differences:
1. FAN_MARK_IGNORED_SURV_MODIFY is required for filesystem and mount marks and on an inode mark on a directory. Omitting this flag will return EINVAL or EISDIR error.
2. An ignore mask on a non-directory inode that survives modify could never be downgraded to an ignore mask that does not survive modify. With new FAN_MARK_IGNORE semantics we make that rule explicit - trying to update a surviving ignore mask without the flag FAN_MARK_IGNORED_SURV_MODIFY will return EEXIST error.
The conveniene macro FAN_MARK_IGNORE_SURV is added for (FAN_MARK_IGNORE | FAN_MARK_IGNORED_SURV_MODIFY), because the common case should use short constant names.
--- fs/notify/fanotify/fanotify.h | 2 + fs/notify/fanotify/fanotify_user.c | 63 +++++++++++++++++++++++++----- include/linux/fanotify.h | 5 ++- include/uapi/linux/fanotify.h | 8 ++++ 4 files changed, 67 insertions(+), 11 deletions(-)
fs/notify/fanotify/fanotify.h +2 -0
@@ -499,6 +499,8 @@ static inline unsigned int fanotify_mark_user_flags(struct fsnotify_mark *mark) mflags |=FAN_MARK_IGNORED_SURV_MODIFY ;if (mark->flags &FSNOTIFY_MARK_FLAG_NO_IREF ) mflags |=FAN_MARK_EVICTABLE ; +if (mark->flags &FSNOTIFY_MARK_FLAG_HAS_IGNORE_FLAGS ) + mflags |=FAN_MARK_IGNORE ;return mflags; }
fs/notify/fanotify/fanotify_user.c +53 -10
141 lines not on this page · raw message
include/linux/fanotify.h +4 -1
@@ -64,11 +64,14 @@ extern struct ctl_table fanotify_table[]; /* for sysctl */#define FANOTIFY_MARK_CMD_BITS (FAN_MARK_ADD | FAN_MARK_REMOVE | \ FAN_MARK_FLUSH) +#define FANOTIFY_MARK_IGNORE_BITS (FAN_MARK_IGNORED_MASK | \ + FAN_MARK_IGNORE) +#define FANOTIFY_MARK_FLAGS (FANOTIFY_MARK_TYPE_BITS | \ FANOTIFY_MARK_CMD_BITS | \ + FANOTIFY_MARK_IGNORE_BITS | \ FAN_MARK_DONT_FOLLOW | \ FAN_MARK_ONLYDIR | \ - FAN_MARK_IGNORED_MASK | \ FAN_MARK_IGNORED_SURV_MODIFY | \ FAN_MARK_EVICTABLE)
include/uapi/linux/fanotify.h +8 -0
@@ -83,12 +83,20 @@#define FAN_MARK_FLUSH 0x00000080/* FAN_MARK_FILESYSTEM is 0x00000100 */ #define FAN_MARK_EVICTABLE 0x00000200 +/* This bit is mutually exclusive with FAN_MARK_IGNORED_MASK bit */ +#define FAN_MARK_IGNORE 0x00000400/* These are NOT bitwise flags. Both bits can be used togther. */ #define FAN_MARK_INODE 0x00000000#define FAN_MARK_MOUNT 0x00000010#define FAN_MARK_FILESYSTEM 0x00000100 +/* +* Convenience macro - FAN_MARK_IGNORE requires FAN_MARK_IGNORED_SURV_MODIFY +* for non-inode mark types. +*/ +#define FAN_MARK_IGNORE_SURV (FAN_MARK_IGNORE | FAN_MARK_IGNORED_SURV_MODIFY) +/* Deprecated - do not use this in programs and do not add new flags here! */ #define FAN_ALL_MARK_FLAGS (FAN_MARK_ADD |\ FAN_MARK_REMOVE |\
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 548/770 fsnotify: Fix comment typo
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xin Gao <[email protected]>
[ Upstream commit feee1ce45a5666bbdb08c5bb2f5f394047b1915b ]
The double `if' is duplicated in line 104, remove one.
--- fs/notify/fsnotify.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/notify/fsnotify.c +1 -1
@@ -100,7 +100,7 @@ void fsnotify_sb_delete(struct super_block *sb)* Given an inode, first check if we care what happens to our children. Inotify * and dnotify both tell their parents about events. If we care about any event * on a child we run all of our children and set a dentry flag saying that the -* parent cares. Thus when an event happens on a child it can quickly tell if +* parent cares. Thus when an event happens on a child it can quickly tell * if there is a need to find a parent and send the event to the parent. */ void __fsnotify_update_child_dentry_flags (struct inode *inode)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 549/770 nfsd: eliminate the NFSD_FILE_BREAK_* flags
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeff Layton <[email protected]>
[ Upstream commit 23ba98de6dcec665e15c0ca19244379bb0d30932 ]
We had a report from the spring Bake-a-thon of data corruption in some nfstest_interop tests. Looking at the traces showed the NFS server allowing a v3 WRITE to proceed while a read delegation was still outstanding.
Currently, we only set NFSD_FILE_BREAK_* flags if NFSD_MAY_NOT_BREAK_LEASE was set when we call nfsd_file_alloc. NFSD_MAY_NOT_BREAK_LEASE was intended to be set when finding files for COMMIT ops, where we need a writeable filehandle but don't need to break read leases.
It doesn't make any sense to consult that flag when allocating a file since the file may be used on subsequent calls where we do want to break the lease (and the usage of it here seems to be reverse from what it should be anyway).
Also, after calling nfsd_open_break_lease, we don't want to clear the BREAK_* bits. A lease could end up being set on it later (more than once) and we need to be able to break those leases as well.
This means that the NFSD_FILE_BREAK_* flags now just mirror NFSD_MAY_{READ,WRITE} flags, so there's no need for them at all. Just drop those flags and unconditionally call nfsd_open_break_lease every time.
--- fs/nfsd/filecache.c | 22 +--------------------- fs/nfsd/filecache.h | 4 +--- fs/nfsd/trace.h | 2 -- 3 files changed, 2 insertions(+), 26 deletions(-)
fs/nfsd/filecache.c +1 -21
@@ -183,12 +183,6 @@ nfsd_file_alloc(struct inode *inode, unsigned int may, unsigned int hashval, nf->nf_hashval = hashval;refcount_set (&nf->nf_ref,1 ); nf->nf_may = may &NFSD_FILE_MAY_MASK ; -if (may &NFSD_MAY_NOT_BREAK_LEASE ) { -if (may &NFSD_MAY_WRITE ) -__set_bit (NFSD_FILE_BREAK_WRITE , &nf->nf_flags); -if (may &NFSD_MAY_READ ) -__set_bit (NFSD_FILE_BREAK_READ , &nf->nf_flags); - } nf->nf_mark =NULL ;trace_nfsd_file_alloc (nf); }
@@ -957,21 +951,7 @@ nfsd_do_file_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,this_cpu_inc (nfsd_file_cache_hits); -if (!(may_flags &NFSD_MAY_NOT_BREAK_LEASE )) { -bool write = (may_flags &NFSD_MAY_WRITE ); - -if (test_bit (NFSD_FILE_BREAK_READ , &nf->nf_flags) || - (test_bit (NFSD_FILE_BREAK_WRITE , &nf->nf_flags) && write)) { - status =nfserrno (nfsd_open_break_lease ( -file_inode (nf->nf_file), may_flags)); -if (status == nfs_ok) { -clear_bit (NFSD_FILE_BREAK_READ , &nf->nf_flags); -if (write) -clear_bit (NFSD_FILE_BREAK_WRITE , - &nf->nf_flags); - } - } - } + status =nfserrno (nfsd_open_break_lease (file_inode (nf->nf_file), may_flags)); out:if (status == nfs_ok) { *pnf = nf;
fs/nfsd/filecache.h +1 -3
@@ -37,9 +37,7 @@ struct nfsd_file {struct net *nf_net;#define NFSD_FILE_HASHED (0)#define NFSD_FILE_PENDING (1) -#define NFSD_FILE_BREAK_READ (2) -#define NFSD_FILE_BREAK_WRITE (3) -#define NFSD_FILE_REFERENCED (4) +#define NFSD_FILE_REFERENCED (2)unsigned long nf_flags;struct inode *nf_inode;unsigned int nf_hashval;
fs/nfsd/trace.h +0 -2
@@ -707,8 +707,6 @@ DEFINE_CLID_EVENT(confirmed_r);__print_flags (val,"|" , \ { 1 << NFSD_FILE_HASHED, "HASHED" }, \ { 1 << NFSD_FILE_PENDING, "PENDING" }, \ - { 1 << NFSD_FILE_BREAK_READ, "BREAK_READ" }, \ - { 1 << NFSD_FILE_BREAK_WRITE, "BREAK_WRITE" }, \ { 1 << NFSD_FILE_REFERENCED, "REFERENCED"}) DECLARE_EVENT_CLASS(nfsd_file_class,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 550/770 SUNRPC: Fix xdr_encode_bool()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit c770f31d8f580ed4b965c64f924ec1cc50e41734 ]
I discovered that xdr_encode_bool() was returning the same address that was passed in the @p parameter. The documenting comment states that the intent is to return the address of the next buffer location, just like the other "xdr_encode_*" helpers.
The result was the encoded results of NFSv3 PATHCONF operations were not formed correctly.
--- include/linux/sunrpc/xdr.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
include/linux/sunrpc/xdr.h +2 -2
@@ -418,8 +418,8 @@ static inline int xdr_stream_encode_item_absent(struct xdr_stream *xdr)*/ static inline __be32 *xdr_encode_bool (__be32 *p,u32 n) { - *p = n ? xdr_one : xdr_zero; -return p++; + *p++ = n ? xdr_one : xdr_zero; +return p; }/**
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 551/770 NLM: Defend against file_lock changes after vfs_test_lock()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Benjamin Coddington <[email protected]>
[ Upstream commit 184cefbe62627730c30282df12bcff9aae4816ea ]
Instead of trusting that struct file_lock returns completely unchanged after vfs_test_lock() when there's no conflicting lock, stash away our nlm_lockowner reference so we can properly release it for all cases.
This defends against another file_lock implementation overwriting fl_owner when the return type is F_UNLCK.
--- fs/lockd/svc4proc.c | 4 +++- fs/lockd/svclock.c | 10 +--------- fs/lockd/svcproc.c | 5 ++++- include/linux/lockd/lockd.h | 1 + 4 files changed, 9 insertions(+), 11 deletions(-)
fs/lockd/svc4proc.c +3 -1
@@ -87,6 +87,7 @@ __nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)struct nlm_args *argp = rqstp->rq_argp;struct nlm_host *host;struct nlm_file *file; +struct nlm_lockowner *test_owner;__be32 rc = rpc_success;dprintk ("lockd: TEST4 called\n" );
@@ -96,6 +97,7 @@ __nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)if ((resp->status =nlm4svc_retrieve_args (rqstp, argp, &host, &file)))return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; + test_owner = argp->lock.fl.fl_owner;/* Now check for conflicting locks */ resp->status =nlmsvc_testlock (rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie);if (resp->status == nlm_drop_reply)
@@ -103,7 +105,7 @@ __nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)else dprintk ("lockd: TEST4 status %d\n" ,ntohl (resp->status)); -nlmsvc_release_lockowner (&argp->lock); +nlmsvc_put_lockowner (test_owner);nlmsvc_release_host (host);nlm_release_file (file);return rc;
fs/lockd/svclock.c +1 -9
@@ -340,7 +340,7 @@ nlmsvc_get_lockowner(struct nlm_lockowner *lockowner)return lockowner; } -static void nlmsvc_put_lockowner (struct nlm_lockowner *lockowner) +void nlmsvc_put_lockowner (struct nlm_lockowner *lockowner) {if (!refcount_dec_and_lock (&lockowner->count, &lockowner->host->h_lock))return ;
@@ -590,7 +590,6 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,int error;int mode;__be32 ret; -struct nlm_lockowner *test_owner; dprintk("lockd: nlmsvc_testlock(%s/%ld, ty=%d, %Ld-%Ld)\n", nlmsvc_file_inode(file)->i_sb->s_id,
@@ -604,9 +603,6 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file, goto out; } -/* If there's a conflicting lock, remember to clean up the test lock */ - test_owner = (struct nlm_lockowner *)lock->fl.fl_owner; - mode =lock_to_openmode (&lock->fl); error =vfs_test_lock (file->f_file[mode], &lock->fl);if (error) {
@@ -635,10 +631,6 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file, conflock->fl.fl_end = lock->fl.fl_end;locks_release_private (&lock->fl); -/* Clean up the test lock */ - lock->fl.fl_owner =NULL ; -nlmsvc_put_lockowner (test_owner); - ret = nlm_lck_denied; out:return ret;
fs/lockd/svcproc.c +4 -1
@@ -116,6 +116,7 @@ __nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)struct nlm_args *argp = rqstp->rq_argp;struct nlm_host *host;struct nlm_file *file; +struct nlm_lockowner *test_owner;__be32 rc = rpc_success;dprintk ("lockd: TEST called\n" );
@@ -125,6 +126,8 @@ __nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)if ((resp->status =nlmsvc_retrieve_args (rqstp, argp, &host, &file)))return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; + test_owner = argp->lock.fl.fl_owner; +/* Now check for conflicting locks */ resp->status =cast_status (nlmsvc_testlock (rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie));if (resp->status == nlm_drop_reply)
@@ -133,7 +136,7 @@ __nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)dprintk ("lockd: TEST status %d vers %d\n" ,ntohl (resp->status), rqstp->rq_vers); -nlmsvc_release_lockowner (&argp->lock); +nlmsvc_put_lockowner (test_owner);nlmsvc_release_host (host);nlm_release_file (file);return rc;
include/linux/lockd/lockd.h +1 -0
@@ -292,6 +292,7 @@ void nlmsvc_locks_init_private(struct file_lock *, struct nlm_host *, pid_t);__be32 nlm_lookup_file (struct svc_rqst *,struct nlm_file **,struct nlm_lock *);void nlm_release_file (struct nlm_file *); +void nlmsvc_put_lockowner (struct nlm_lockowner *);void nlmsvc_release_lockowner (struct nlm_lock *);void nlmsvc_mark_resources (struct net *);void nlmsvc_free_host_resources (struct nlm_host *);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 552/770 NFSD: Fix space and spelling mistake
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Jiaming <[email protected]>
[ Upstream commit f532c9ff103897be0e2a787c0876683c3dc39ed3 ]
Add a blank space after ','.
Change 'succesful' to 'successful'.
--- fs/nfsd/nfs4proc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/nfsd/nfs4proc.c +2 -2
@@ -828,7 +828,7 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, goto out_umask; status =nfsd_create (rqstp, &cstate->current_fh, create->cr_name, create->cr_namelen, - &create->cr_iattr,S_IFCHR , rdev, &resfh); + &create->cr_iattr,S_IFCHR , rdev, &resfh);break ;case NF4SOCK :
@@ -2703,7 +2703,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp)if (op->opdesc->op_flags &OP_MODIFIES_SOMETHING ) {/* * Don't execute this op if we couldn't encode a -* succesful reply: +* successful reply: */ u32 plen = op->opdesc->op_rsize_bop (rqstp, op);/*
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 553/770 nfsd: remove redundant assignment to variable len
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Colin Ian King <[email protected]>
[ Upstream commit 842e00ac3aa3b4a4f7f750c8ab54f8578fc875d3 ]
Variable len is being assigned a value zero and this is never read, it is being re-assigned later. The assignment is redundant and can be removed.
Cleans up clang scan-build warning:fs/nfsd/nfsctl.c:636:2: warning: Value stored to 'len' is never read
--- fs/nfsd/nfsctl.c | 1 - 1 file changed, 1 deletion(-)
fs/nfsd/nfsctl.c +0 -1
@@ -633,7 +633,6 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size) }/* Now write current state into reply buffer */ - len =0 ; sep ="" ; remaining =SIMPLE_TRANSACTION_LIMIT ;for (num=2 ; num <=4 ; num++) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 554/770 NFSD: Demote a WARN to a pr_warn()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit ca3f9acb6d3faf78da2b63324f7c737dbddf7f69 ]
The call trace doesn't add much value, but it sure is noisy.
--- fs/nfsd/nfs4proc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
fs/nfsd/nfs4proc.c +3 -3
@@ -630,9 +630,9 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, } status =nfsd4_process_open2 (rqstp, resfh, open); -WARN (status && open->op_created, -"nfsd4_process_open2 failed to open newly-created file! status=%u\n" , -be32_to_cpu (status)); +if (status && open->op_created) +pr_warn ("nfsd4_process_open2 failed to open newly-created file: status=%u\n" , +be32_to_cpu (status));if (reclaim && !status) nn->somebody_reclaimed = true; out:
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 555/770 NFSD: Report filecache LRU size
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 0fd244c115f0321fc5e34ad2291f2a572508e3f7 ]
Surface the NFSD filecache's LRU list length to help field troubleshooters monitor filecache issues.
--- fs/nfsd/filecache.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
fs/nfsd/filecache.c +3 -1
@@ -1047,7 +1047,7 @@ nfsd_file_create(struct svc_rqst *rqstp, struct svc_fh *fhp,static int nfsd_file_cache_stats_show (struct seq_file *m,void *v) {unsigned int i, count =0 , longest =0 ; -unsigned long hits =0 ; +unsigned long lru =0 , hits =0 ;/* * No need for spinlocks here since we're not terribly interested in
@@ -1060,6 +1060,7 @@ static int nfsd_file_cache_stats_show(struct seq_file *m, void *v) count += nfsd_file_hashtbl[i].nfb_count; longest =max (longest, nfsd_file_hashtbl[i].nfb_count); } + lru =list_lru_count (&nfsd_file_lru); }mutex_unlock (&nfsd_mutex);
@@ -1068,6 +1069,7 @@ static int nfsd_file_cache_stats_show(struct seq_file *m, void *v)seq_printf (m,"total entries: %u\n" , count);seq_printf (m,"longest chain: %u\n" , longest); +seq_printf (m,"lru entries: %lu\n" , lru);seq_printf (m,"cache hits: %lu\n" , hits);return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 556/770 NFSD: Report count of calls to nfsd_file_acquire()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 29d4bdbbb910f33d6058d2c51278f00f656df325 ]
Count the number of successful acquisitions that did not create a file (ie, acquisitions that do not result in a compulsory cache miss). This count can be compared directly with the reported hit count to compute a hit ratio.
--- fs/nfsd/filecache.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
fs/nfsd/filecache.c +9 -2
@@ -42,6 +42,7 @@ struct nfsd_fcache_bucket { }; static DEFINE_PER_CPU(unsigned long, nfsd_file_cache_hits); +static DEFINE_PER_CPU(unsigned long, nfsd_file_acquisitions);struct nfsd_fcache_disposal {struct work_struct work;
@@ -954,6 +955,8 @@ nfsd_do_file_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp, status =nfserrno (nfsd_open_break_lease (file_inode (nf->nf_file), may_flags)); out:if (status == nfs_ok) { +if (open) +this_cpu_inc (nfsd_file_acquisitions); *pnf = nf; }else {nfsd_file_put (nf);
@@ -1046,8 +1049,9 @@ nfsd_file_create(struct svc_rqst *rqstp, struct svc_fh *fhp,*/ static int nfsd_file_cache_stats_show (struct seq_file *m,void *v) { +unsigned long hits =0 , acquisitions =0 ;unsigned int i, count =0 , longest =0 ; -unsigned long lru =0 , hits =0 ; +unsigned long lru =0 ;/* * No need for spinlocks here since we're not terribly interested in
@@ -1064,13 +1068,16 @@ static int nfsd_file_cache_stats_show(struct seq_file *m, void *v) }mutex_unlock (&nfsd_mutex); -for_each_possible_cpu (i) +for_each_possible_cpu (i) { hits +=per_cpu (nfsd_file_cache_hits, i); + acquisitions +=per_cpu (nfsd_file_acquisitions, i); + }seq_printf (m,"total entries: %u\n" , count);seq_printf (m,"longest chain: %u\n" , longest);seq_printf (m,"lru entries: %lu\n" , lru);seq_printf (m,"cache hits: %lu\n" , hits); +seq_printf (m,"acquisitions: %lu\n" , acquisitions);return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 557/770 NFSD: Report count of freed filecache items
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit d63293272abb51c02457f1017dfd61c3270d9ae3 ]
Surface the count of freed nfsd_file items.
--- fs/nfsd/filecache.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
fs/nfsd/filecache.c +6 -1
@@ -43,6 +43,7 @@ struct nfsd_fcache_bucket { static DEFINE_PER_CPU(unsigned long, nfsd_file_cache_hits); static DEFINE_PER_CPU(unsigned long, nfsd_file_acquisitions); +static DEFINE_PER_CPU(unsigned long, nfsd_file_releases);struct nfsd_fcache_disposal {struct work_struct work;
@@ -195,6 +196,8 @@ nfsd_file_free(struct nfsd_file *nf) {bool flush = false; +this_cpu_inc (nfsd_file_releases); +trace_nfsd_file_put_final (nf);if (nf->nf_mark)nfsd_file_mark_put (nf->nf_mark);
@@ -1049,7 +1052,7 @@ nfsd_file_create(struct svc_rqst *rqstp, struct svc_fh *fhp,*/ static int nfsd_file_cache_stats_show (struct seq_file *m,void *v) { -unsigned long hits =0 , acquisitions =0 ; +unsigned long hits =0 , acquisitions =0 , releases =0 ;unsigned int i, count =0 , longest =0 ;unsigned long lru =0 ;
@@ -1071,6 +1074,7 @@ static int nfsd_file_cache_stats_show(struct seq_file *m, void *v)for_each_possible_cpu (i) { hits +=per_cpu (nfsd_file_cache_hits, i); acquisitions +=per_cpu (nfsd_file_acquisitions, i); + releases +=per_cpu (nfsd_file_releases, i); }seq_printf (m,"total entries: %u\n" , count);
@@ -1078,6 +1082,7 @@ static int nfsd_file_cache_stats_show(struct seq_file *m, void *v)seq_printf (m,"lru entries: %lu\n" , lru);seq_printf (m,"cache hits: %lu\n" , hits);seq_printf (m,"acquisitions: %lu\n" , acquisitions); +seq_printf (m,"releases: %lu\n" , releases);return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 558/770 NFSD: Report average age of filecache items
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 904940e94a887701db24401e3ed6928a1d4e329f ]
This is a measure of how long items stay in the filecache, to help assess how efficient the cache is.
--- fs/nfsd/filecache.c | 11 ++++++++++- fs/nfsd/filecache.h | 1 + 2 files changed, 11 insertions(+), 1 deletion(-)
fs/nfsd/filecache.c +10 -1
@@ -44,6 +44,7 @@ struct nfsd_fcache_bucket { static DEFINE_PER_CPU(unsigned long, nfsd_file_cache_hits); static DEFINE_PER_CPU(unsigned long, nfsd_file_acquisitions); static DEFINE_PER_CPU(unsigned long, nfsd_file_releases); +static DEFINE_PER_CPU(unsigned long, nfsd_file_total_age);struct nfsd_fcache_disposal {struct work_struct work;
@@ -177,6 +178,7 @@ nfsd_file_alloc(struct inode *inode, unsigned int may, unsigned int hashval,if (nf) {INIT_HLIST_NODE (&nf->nf_node);INIT_LIST_HEAD (&nf->nf_lru); + nf->nf_birthtime =ktime_get (); nf->nf_file =NULL ; nf->nf_cred =get_current_cred (); nf->nf_net = net;
@@ -194,9 +196,11 @@ nfsd_file_alloc(struct inode *inode, unsigned int may, unsigned int hashval,static bool nfsd_file_free (struct nfsd_file *nf) { +s64 age =ktime_to_ms (ktime_sub (ktime_get (), nf->nf_birthtime));bool flush = false;this_cpu_inc (nfsd_file_releases); +this_cpu_add (nfsd_file_total_age, age);trace_nfsd_file_put_final (nf);if (nf->nf_mark)
@@ -1054,7 +1058,7 @@ static int nfsd_file_cache_stats_show(struct seq_file *m, void *v) {unsigned long hits =0 , acquisitions =0 , releases =0 ;unsigned int i, count =0 , longest =0 ; -unsigned long lru =0 ; +unsigned long lru =0 , total_age =0 ;/* * No need for spinlocks here since we're not terribly interested in
@@ -1075,6 +1079,7 @@ static int nfsd_file_cache_stats_show(struct seq_file *m, void *v) hits +=per_cpu (nfsd_file_cache_hits, i); acquisitions +=per_cpu (nfsd_file_acquisitions, i); releases +=per_cpu (nfsd_file_releases, i); + total_age +=per_cpu (nfsd_file_total_age, i); }seq_printf (m,"total entries: %u\n" , count);
@@ -1083,6 +1088,10 @@ static int nfsd_file_cache_stats_show(struct seq_file *m, void *v)seq_printf (m,"cache hits: %lu\n" , hits);seq_printf (m,"acquisitions: %lu\n" , acquisitions);seq_printf (m,"releases: %lu\n" , releases); +if (releases) +seq_printf (m,"mean age (ms): %ld\n" , total_age / releases); +else +seq_printf (m,"mean age (ms): -\n" );return 0 ; }
fs/nfsd/filecache.h +1 -0
@@ -44,6 +44,7 @@ struct nfsd_file {refcount_t nf_ref;unsigned char nf_may;struct nfsd_file_mark *nf_mark; +ktime_t nf_birthtime; };int nfsd_file_cache_init (void );
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 559/770 NFSD: Add nfsd_file_lru_dispose_list() helper
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 0bac5a264d9a923f5b01f3521e1519a8d0358342 ]
Refactor the invariant part of nfsd_file_lru_walk_list() into a separate helper function.
--- fs/nfsd/filecache.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-)
fs/nfsd/filecache.c +22 -7
@@ -450,11 +450,31 @@ nfsd_file_lru_cb(struct list_head *item, struct list_lru_one *lru,return LRU_SKIP ; } +/* +* Unhash items on @dispose immediately, then queue them on the +* disposal workqueue to finish releasing them in the background. +* +* cel: Note that between the time list_lru_shrink_walk runs and +* now, these items are in the hash table but marked unhashed. +* Why release these outside of lru_cb ? There's no lock ordering +* problem since lru_cb currently takes no lock. +*/ +static void nfsd_file_gc_dispose_list (struct list_head *dispose) +{ +struct nfsd_file *nf; + +list_for_each_entry (nf, dispose, nf_lru) { +spin_lock (&nfsd_file_hashtbl[nf->nf_hashval].nfb_lock); +nfsd_file_do_unhash (nf); +spin_unlock (&nfsd_file_hashtbl[nf->nf_hashval].nfb_lock); + } +nfsd_file_dispose_list_delayed (dispose); +} +static unsigned long nfsd_file_lru_walk_list (struct shrink_control *sc) {LIST_HEAD (head); -struct nfsd_file *nf;unsigned long ret;if (sc)
@@ -464,12 +484,7 @@ nfsd_file_lru_walk_list(struct shrink_control *sc) ret =list_lru_walk (&nfsd_file_lru, nfsd_file_lru_cb, &head,LONG_MAX ); -list_for_each_entry (nf, &head, nf_lru) { -spin_lock (&nfsd_file_hashtbl[nf->nf_hashval].nfb_lock); -nfsd_file_do_unhash (nf); -spin_unlock (&nfsd_file_hashtbl[nf->nf_hashval].nfb_lock); - } -nfsd_file_dispose_list_delayed (&head); +nfsd_file_gc_dispose_list (&head);return ret; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 560/770 NFSD: Refactor nfsd_file_gc()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 3bc6d3470fe412f818f9bff6b71d1be3a76af8f3 ]
Refactor nfsd_file_gc() to use the new list_lru helper.
--- fs/nfsd/filecache.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
fs/nfsd/filecache.c +5 -1
@@ -491,7 +491,11 @@ nfsd_file_lru_walk_list(struct shrink_control *sc)static void nfsd_file_gc (void ) { -nfsd_file_lru_walk_list (NULL ); +LIST_HEAD (dispose); + +list_lru_walk (&nfsd_file_lru, nfsd_file_lru_cb, + &dispose,LONG_MAX ); +nfsd_file_gc_dispose_list (&dispose); } static void
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 561/770 NFSD: Refactor nfsd_file_lru_scan()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 39f1d1ff8148902c5692ffb0e1c4479416ab44a7 ]
--- fs/nfsd/filecache.c | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-)
fs/nfsd/filecache.c +7 -18
@@ -471,23 +471,6 @@ static void nfsd_file_gc_dispose_list(struct list_head *dispose)nfsd_file_dispose_list_delayed (dispose); } -static unsigned long -nfsd_file_lru_walk_list (struct shrink_control *sc) -{ -LIST_HEAD (head); -unsigned long ret; - -if (sc) - ret =list_lru_shrink_walk (&nfsd_file_lru, sc, - nfsd_file_lru_cb, &head); -else - ret =list_lru_walk (&nfsd_file_lru, - nfsd_file_lru_cb, - &head,LONG_MAX ); -nfsd_file_gc_dispose_list (&head); -return ret; -} -static void nfsd_file_gc (void ) {
@@ -514,7 +497,13 @@ nfsd_file_lru_count(struct shrinker *s, struct shrink_control *sc)static unsigned long nfsd_file_lru_scan (struct shrinker *s,struct shrink_control *sc) { -return nfsd_file_lru_walk_list (sc); +LIST_HEAD (dispose); +unsigned long ret; + + ret =list_lru_shrink_walk (&nfsd_file_lru, sc, + nfsd_file_lru_cb, &dispose); +nfsd_file_gc_dispose_list (&dispose); +return ret; }static struct shrinker nfsd_file_shrinker = {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 562/770 NFSD: Report the number of items evicted by the LRU walk
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 94660cc19c75083af046b0f8362e3d3bc2eba21d ]
--- fs/nfsd/filecache.c | 13 ++++++++++--- fs/nfsd/trace.h | 29 +++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 3 deletions(-)
fs/nfsd/filecache.c +10 -3
@@ -45,6 +45,7 @@ static DEFINE_PER_CPU(unsigned long, nfsd_file_cache_hits); static DEFINE_PER_CPU(unsigned long, nfsd_file_acquisitions); static DEFINE_PER_CPU(unsigned long, nfsd_file_releases); static DEFINE_PER_CPU(unsigned long, nfsd_file_total_age); +static DEFINE_PER_CPU(unsigned long, nfsd_file_evictions);struct nfsd_fcache_disposal {struct work_struct work;
@@ -445,6 +446,7 @@ nfsd_file_lru_cb(struct list_head *item, struct list_lru_one *lru, goto out_skip;list_lru_isolate_move (lru, &nf->nf_lru, head); +this_cpu_inc (nfsd_file_evictions);return LRU_REMOVED ; out_skip:return LRU_SKIP ;
@@ -475,9 +477,11 @@ static voidnfsd_file_gc (void) {LIST_HEAD (dispose); +unsigned long ret; -list_lru_walk (&nfsd_file_lru, nfsd_file_lru_cb, - &dispose,LONG_MAX ); + ret =list_lru_walk (&nfsd_file_lru, nfsd_file_lru_cb, + &dispose,LONG_MAX ); +trace_nfsd_file_gc_removed (ret,list_lru_count (&nfsd_file_lru));nfsd_file_gc_dispose_list (&dispose); }
@@ -502,6 +506,7 @@ nfsd_file_lru_scan(struct shrinker *s, struct shrink_control *sc) ret =list_lru_shrink_walk (&nfsd_file_lru, sc, nfsd_file_lru_cb, &dispose); +trace_nfsd_file_shrinker_removed (ret,list_lru_count (&nfsd_file_lru));nfsd_file_gc_dispose_list (&dispose);return ret; }
@@ -1064,7 +1069,7 @@ nfsd_file_create(struct svc_rqst *rqstp, struct svc_fh *fhp,*/ static int nfsd_file_cache_stats_show (struct seq_file *m,void *v) { -unsigned long hits =0 , acquisitions =0 , releases =0 ; +unsigned long hits =0 , acquisitions =0 , releases =0 , evictions =0 ;unsigned int i, count =0 , longest =0 ;unsigned long lru =0 , total_age =0 ;
@@ -1088,6 +1093,7 @@ static int nfsd_file_cache_stats_show(struct seq_file *m, void *v) acquisitions +=per_cpu (nfsd_file_acquisitions, i); releases +=per_cpu (nfsd_file_releases, i); total_age +=per_cpu (nfsd_file_total_age, i); + evictions +=per_cpu (nfsd_file_evictions, i); }seq_printf (m,"total entries: %u\n" , count);
@@ -1096,6 +1102,7 @@ static int nfsd_file_cache_stats_show(struct seq_file *m, void *v)seq_printf (m,"cache hits: %lu\n" , hits);seq_printf (m,"acquisitions: %lu\n" , acquisitions);seq_printf (m,"releases: %lu\n" , releases); +seq_printf (m,"evictions: %lu\n" , evictions);if (releases)seq_printf (m,"mean age (ms): %ld\n" , total_age / releases);else
fs/nfsd/trace.h +29 -0
@@ -860,6 +860,35 @@ TRACE_EVENT(nfsd_file_fsnotify_handle_event, __entry->nlink, __entry->mode, __entry->mask) ); +DECLARE_EVENT_CLASS (nfsd_file_lruwalk_class, +TP_PROTO ( + unsigned long removed, + unsigned long remaining + ), +TP_ARGS (removed, remaining), +TP_STRUCT__entry ( + __field(unsigned long, removed) + __field(unsigned long, remaining) + ), +TP_fast_assign ( + __entry->removed = removed; + __entry->remaining = remaining; + ), +TP_printk ("%lu entries removed, %lu remaining" , + __entry->removed, __entry->remaining) +); + +#define DEFINE_NFSD_FILE_LRUWALK_EVENT (name) \ +DEFINE_EVENT(nfsd_file_lruwalk_class, name, \ + TP_PROTO( \ + unsigned long removed, \ + unsigned long remaining \ + ), \ + TP_ARGS(removed, remaining)) + +DEFINE_NFSD_FILE_LRUWALK_EVENT (nfsd_file_gc_removed); +DEFINE_NFSD_FILE_LRUWALK_EVENT (nfsd_file_shrinker_removed); +#include "cache.h" TRACE_DEFINE_ENUM (RC_DROPIT );
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 563/770 NFSD: Record number of flush calls
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit df2aff524faceaf743b7c5ab0f4fb86cb511f782 ]
--- fs/nfsd/filecache.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
fs/nfsd/filecache.c +11 -2
@@ -45,6 +45,7 @@ static DEFINE_PER_CPU(unsigned long, nfsd_file_cache_hits); static DEFINE_PER_CPU(unsigned long, nfsd_file_acquisitions); static DEFINE_PER_CPU(unsigned long, nfsd_file_releases); static DEFINE_PER_CPU(unsigned long, nfsd_file_total_age); +static DEFINE_PER_CPU(unsigned long, nfsd_file_pages_flushed); static DEFINE_PER_CPU(unsigned long, nfsd_file_evictions);struct nfsd_fcache_disposal {
@@ -242,7 +243,12 @@ nfsd_file_check_write_error(struct nfsd_file *nf)static void nfsd_file_flush (struct nfsd_file *nf) { -if (nf->nf_file &&vfs_fsync (nf->nf_file,1 ) !=0 ) +struct file *file = nf->nf_file; + +if (!file || !(file->f_mode &FMODE_WRITE )) +return ; +this_cpu_add (nfsd_file_pages_flushed, file->f_mapping->nrpages); +if (vfs_fsync (file,1 ) !=0 )nfsd_reset_write_verifier (net_generic (nf->nf_net, nfsd_net_id)); }
@@ -1069,7 +1075,8 @@ nfsd_file_create(struct svc_rqst *rqstp, struct svc_fh *fhp,*/ static int nfsd_file_cache_stats_show (struct seq_file *m,void *v) { -unsigned long hits =0 , acquisitions =0 , releases =0 , evictions =0 ; +unsigned long releases =0 , pages_flushed =0 , evictions =0 ; +unsigned long hits =0 , acquisitions =0 ;unsigned int i, count =0 , longest =0 ;unsigned long lru =0 , total_age =0 ;
@@ -1094,6 +1101,7 @@ static int nfsd_file_cache_stats_show(struct seq_file *m, void *v) releases +=per_cpu (nfsd_file_releases, i); total_age +=per_cpu (nfsd_file_total_age, i); evictions +=per_cpu (nfsd_file_evictions, i); + pages_flushed +=per_cpu (nfsd_file_pages_flushed, i); }seq_printf (m,"total entries: %u\n" , count);
@@ -1107,6 +1115,7 @@ static int nfsd_file_cache_stats_show(struct seq_file *m, void *v)seq_printf (m,"mean age (ms): %ld\n" , total_age / releases); else seq_printf(m, "mean age (ms): -\n"); +seq_printf (m,"pages flushed: %lu\n" , pages_flushed);return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 564/770 NFSD: Zero counters when the filecache is re-initialized
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 8b330f78040cbe16cf8029df70391b2a491f17e2 ]
If nfsd_file_cache_init() is called after a shutdown, be sure the stat counters are reset.
--- fs/nfsd/filecache.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
fs/nfsd/filecache.c +11 -0
@@ -823,6 +823,8 @@ nfsd_file_cache_shutdown_net(struct net *net)void nfsd_file_cache_shutdown (void ) { +int i; +set_bit (NFSD_FILE_SHUTDOWN , &nfsd_file_lru_flags);lease_unregister_notifier (&nfsd_file_lease_notifier);
@@ -846,6 +848,15 @@ nfsd_file_cache_shutdown(void) nfsd_file_hashtbl =NULL ;destroy_workqueue (nfsd_filecache_wq); nfsd_filecache_wq =NULL ; + +for_each_possible_cpu (i) { +per_cpu (nfsd_file_cache_hits, i) =0 ; +per_cpu (nfsd_file_acquisitions, i) =0 ; +per_cpu (nfsd_file_releases, i) =0 ; +per_cpu (nfsd_file_total_age, i) =0 ; +per_cpu (nfsd_file_pages_flushed, i) =0 ; +per_cpu (nfsd_file_evictions, i) =0 ; + } } static bool
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 565/770 NFSD: Hook up the filecache stat file
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 2e6c6e4c4375bfd3defa5b1ff3604d9f33d1c936 ]
There has always been the capability of exporting filecache metrics via /proc, but it was never hooked up. Let's surface these metrics to enable better observability of the filecache.
--- fs/nfsd/nfsctl.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
fs/nfsd/nfsctl.c +10 -0
@@ -25,6 +25,7 @@#include "state.h" #include "netns.h" #include "pnfs.h" +#include "filecache.h" /* * We have a single directory with several nodes in it.
@@ -45,6 +46,7 @@ enum { NFSD_Ports, NFSD_MaxBlkSize, NFSD_MaxConnections, + NFSD_Filecache, NFSD_SupportedEnctypes,/* * The below MUST come last. Otherwise we leave a hole in nfsd_files[]
@@ -229,6 +231,13 @@ static const struct file_operations reply_cache_stats_operations = { .release = single_release, }; +static const struct file_operations filecache_ops = { + .open = nfsd_file_cache_stats_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; +/*----------------------------------------------------------------------------*/ /* * payload - write methods
@@ -1370,6 +1379,7 @@ static int nfsd_fill_super(struct super_block *sb, struct fs_context *fc) [NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO}, [NFSD_MaxBlkSize] = {"max_block_size", &transaction_ops, S_IWUSR|S_IRUGO}, [NFSD_MaxConnections] = {"max_connections", &transaction_ops, S_IWUSR|S_IRUGO}, + [NFSD_Filecache] = {"filecache" , &filecache_ops,S_IRUGO }, #if defined(CONFIG_SUNRPC_GSS) || defined(CONFIG_SUNRPC_GSS_MODULE) [NFSD_SupportedEnctypes] = {"supported_krb5_enctypes", &supported_enctypes_ops, S_IRUGO}, #endif /* CONFIG_SUNRPC_GSS or CONFIG_SUNRPC_GSS_MODULE */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 566/770 NFSD: WARN when freeing an item still linked via nf_lru
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 668ed92e651d3c25f9b6e8cb7ceca54d00daa96d ]
Add a guardrail to prevent freeing memory that is still on a list. This includes either a dispose list or the LRU list.
This is the sign of a bug, but this class of bugs can be detected so that they don't endanger system stability, especially while debugging.
--- fs/nfsd/filecache.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
fs/nfsd/filecache.c +10 -2
@@ -213,6 +213,14 @@ nfsd_file_free(struct nfsd_file *nf)fput (nf->nf_file); flush = true; } + +/* +* If this item is still linked via nf_lru, that's a bug. +* WARN and leak it to preserve system stability. +*/ +if (WARN_ON_ONCE (!list_empty (&nf->nf_lru))) +return flush; +call_rcu (&nf->nf_rcu, nfsd_file_slab_free);return flush; }
@@ -342,7 +350,7 @@ nfsd_file_dispose_list(struct list_head *dispose)while (!list_empty (dispose)) { nf = list_first_entry(dispose, struct nfsd_file, nf_lru); -list_del (&nf->nf_lru); +list_del_init (&nf->nf_lru);nfsd_file_flush (nf);nfsd_file_put_noref (nf); }
@@ -356,7 +364,7 @@ nfsd_file_dispose_list_sync(struct list_head *dispose)while (!list_empty (dispose)) { nf = list_first_entry(dispose, struct nfsd_file, nf_lru); -list_del (&nf->nf_lru); +list_del_init (&nf->nf_lru);nfsd_file_flush (nf);if (!refcount_dec_and_test (&nf->nf_ref))continue ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 567/770 NFSD: Trace filecache LRU activity
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit c46203acddd9b9200dbc53d0603c97355fd3a03b ]
Observe the operation of garbage collection and the lifetime of filecache items.
--- fs/nfsd/filecache.c | 44 +++++++++++++++++++++++++++++++------------- fs/nfsd/trace.h | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 13 deletions(-)
fs/nfsd/filecache.c +31 -13
@@ -260,6 +260,18 @@ nfsd_file_flush(struct nfsd_file *nf)nfsd_reset_write_verifier (net_generic (nf->nf_net, nfsd_net_id)); } +static void nfsd_file_lru_add (struct nfsd_file *nf) +{ +if (list_lru_add (&nfsd_file_lru, &nf->nf_lru)) +trace_nfsd_file_lru_add (nf); +} + +static void nfsd_file_lru_remove (struct nfsd_file *nf) +{ +if (list_lru_del (&nfsd_file_lru, &nf->nf_lru)) +trace_nfsd_file_lru_del (nf); +} +static void nfsd_file_do_unhash (struct nfsd_file *nf) {
@@ -279,8 +291,7 @@ nfsd_file_unhash(struct nfsd_file *nf) {if (test_and_clear_bit (NFSD_FILE_HASHED , &nf->nf_flags)) {nfsd_file_do_unhash (nf); -if (!list_empty (&nf->nf_lru)) -list_lru_del (&nfsd_file_lru, &nf->nf_lru); +nfsd_file_lru_remove (nf);return true; }return false;
@@ -443,27 +454,34 @@ nfsd_file_lru_cb(struct list_head *item, struct list_lru_one *lru,* counter. Here we check the counter and then test and clear the flag. * That order is deliberate to ensure that we can do this locklessly. */ -if (refcount_read (&nf->nf_ref) >1 ) - goto out_skip; +if (refcount_read (&nf->nf_ref) >1 ) { +trace_nfsd_file_gc_in_use (nf); +return LRU_SKIP ; + }/* * Don't throw out files that are still undergoing I/O or * that have uncleared errors pending. */ -if (nfsd_file_check_writeback (nf)) - goto out_skip; +if (nfsd_file_check_writeback (nf)) { +trace_nfsd_file_gc_writeback (nf); +return LRU_SKIP ; + } -if (test_and_clear_bit (NFSD_FILE_REFERENCED , &nf->nf_flags)) - goto out_skip; +if (test_and_clear_bit (NFSD_FILE_REFERENCED , &nf->nf_flags)) { +trace_nfsd_file_gc_referenced (nf); +return LRU_SKIP ; + } -if (!test_and_clear_bit (NFSD_FILE_HASHED , &nf->nf_flags)) - goto out_skip; +if (!test_and_clear_bit (NFSD_FILE_HASHED , &nf->nf_flags)) { +trace_nfsd_file_gc_hashed (nf); +return LRU_SKIP ; + }list_lru_isolate_move (lru, &nf->nf_lru, head);this_cpu_inc (nfsd_file_evictions); +trace_nfsd_file_gc_disposed (nf);return LRU_REMOVED ; -out_skip: -return LRU_SKIP ; }/*
@@ -1016,7 +1034,7 @@ nfsd_do_file_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,refcount_inc (&nf->nf_ref);__set_bit (NFSD_FILE_HASHED , &nf->nf_flags);__set_bit (NFSD_FILE_PENDING , &nf->nf_flags); -list_lru_add (&nfsd_file_lru, &nf->nf_lru); +nfsd_file_lru_add (nf);hlist_add_head_rcu (&nf->nf_node, &nfsd_file_hashtbl[hashval].nfb_head); ++nfsd_file_hashtbl[hashval].nfb_count; nfsd_file_hashtbl[hashval].nfb_maxcount = max(nfsd_file_hashtbl[hashval].nfb_maxcount,
fs/nfsd/trace.h +39 -0
@@ -860,6 +860,45 @@ TRACE_EVENT(nfsd_file_fsnotify_handle_event, __entry->nlink, __entry->mode, __entry->mask) ); +DECLARE_EVENT_CLASS (nfsd_file_gc_class, +TP_PROTO ( + const struct nfsd_file *nf + ), +TP_ARGS (nf), +TP_STRUCT__entry ( + __field(void *, nf_inode) + __field(void *, nf_file) + __field(int, nf_ref) + __field(unsigned long, nf_flags) + ), +TP_fast_assign ( + __entry->nf_inode = nf->nf_inode; + __entry->nf_file = nf->nf_file; + __entry->nf_ref = refcount_read(&nf->nf_ref); + __entry->nf_flags = nf->nf_flags; + ), +TP_printk ("inode=%p ref=%d nf_flags=%s nf_file=%p" , + __entry->nf_inode, __entry->nf_ref, +show_nf_flags (__entry->nf_flags), + __entry->nf_file + ) +); + +#define DEFINE_NFSD_FILE_GC_EVENT (name) \ +DEFINE_EVENT(nfsd_file_gc_class, name, \ + TP_PROTO( \ + const struct nfsd_file *nf \ + ), \ + TP_ARGS(nf)) + +DEFINE_NFSD_FILE_GC_EVENT (nfsd_file_lru_add); +DEFINE_NFSD_FILE_GC_EVENT (nfsd_file_lru_del); +DEFINE_NFSD_FILE_GC_EVENT (nfsd_file_gc_in_use); +DEFINE_NFSD_FILE_GC_EVENT (nfsd_file_gc_writeback); +DEFINE_NFSD_FILE_GC_EVENT (nfsd_file_gc_referenced); +DEFINE_NFSD_FILE_GC_EVENT (nfsd_file_gc_hashed); +DEFINE_NFSD_FILE_GC_EVENT (nfsd_file_gc_disposed); + DECLARE_EVENT_CLASS(nfsd_file_lruwalk_class, TP_PROTO( unsigned long removed,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 568/770 NFSD: Leave open files out of the filecache LRU
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 4a0e73e635e3f36b616ad5c943e3d23debe4632f ]
There have been reports of problems when running fstests generic/531 against Linux NFS servers with NFSv4. The NFS server that hosts the test's SCRATCH_DEV suffers from CPU soft lock-ups during the test. Analysis shows that:
fs/nfsd/filecache.c
482 ret = list_lru_walk(&nfsd_file_lru,
483 nfsd_file_lru_cb,
484 &head, LONG_MAX);
causes nfsd_file_gc() to walk the entire length of the filecache LRU list every time it is called (which is quite frequently). The walk holds a spinlock the entire time that prevents other nfsd threads from accessing the filecache.
What's more, for NFSv4 workloads, none of the items that are visited during this walk may be evicted, since they are all files that are held OPEN by NFS clients.
Address this by ensuring that open files are not kept on the LRU list.
--- fs/nfsd/filecache.c | 24 +++++++++++++++++++----- fs/nfsd/trace.h | 2 ++ 2 files changed, 21 insertions(+), 5 deletions(-)
fs/nfsd/filecache.c +19 -5
@@ -262,6 +262,7 @@ nfsd_file_flush(struct nfsd_file *nf)static void nfsd_file_lru_add (struct nfsd_file *nf) { +set_bit (NFSD_FILE_REFERENCED , &nf->nf_flags);if (list_lru_add (&nfsd_file_lru, &nf->nf_lru))trace_nfsd_file_lru_add (nf); }
@@ -291,7 +292,6 @@ nfsd_file_unhash(struct nfsd_file *nf) {if (test_and_clear_bit (NFSD_FILE_HASHED , &nf->nf_flags)) {nfsd_file_do_unhash (nf); -nfsd_file_lru_remove (nf);return true; }return false;
@@ -312,6 +312,7 @@ nfsd_file_unhash_and_release_locked(struct nfsd_file *nf, struct list_head *dispif (refcount_dec_not_one (&nf->nf_ref))return true; +nfsd_file_lru_remove (nf);list_add (&nf->nf_lru, dispose);return true; }
@@ -323,6 +324,7 @@ nfsd_file_put_noref(struct nfsd_file *nf)if (refcount_dec_and_test (&nf->nf_ref)) {WARN_ON (test_bit (NFSD_FILE_HASHED , &nf->nf_flags)); +nfsd_file_lru_remove (nf);nfsd_file_free (nf); } }
@@ -332,7 +334,7 @@ nfsd_file_put(struct nfsd_file *nf) {might_sleep (); -set_bit (NFSD_FILE_REFERENCED , &nf->nf_flags); +nfsd_file_lru_add (nf);if (test_bit (NFSD_FILE_HASHED , &nf->nf_flags) ==0 ) {nfsd_file_flush (nf);nfsd_file_put_noref (nf);
@@ -432,8 +434,18 @@ nfsd_file_dispose_list_delayed(struct list_head *dispose) } } -/* +/** +* nfsd_file_lru_cb - Examine an entry on the LRU list +* @item: LRU entry to examine +* @lru: controlling LRU +* @lock: LRU list lock (unused) +* @arg: dispose list +* * Note this can deadlock with nfsd_file_cache_purge. +* +* Return values: +* %LRU_REMOVED: @item was removed from the LRU +* %LRU_SKIP: @item cannot be evicted */ static enum lru_status nfsd_file_lru_cb(struct list_head *item, struct list_lru_one *lru,
@@ -455,8 +467,9 @@ nfsd_file_lru_cb(struct list_head *item, struct list_lru_one *lru,* That order is deliberate to ensure that we can do this locklessly. */ if (refcount_read (&nf->nf_ref) >1 ) { +list_lru_isolate (lru, &nf->nf_lru);trace_nfsd_file_gc_in_use (nf); -return LRU_SKIP ; +return LRU_REMOVED ; }/*
@@ -1013,6 +1026,7 @@ nfsd_do_file_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp, goto retry; } +nfsd_file_lru_remove (nf);this_cpu_inc (nfsd_file_cache_hits); status =nfserrno (nfsd_open_break_lease (file_inode (nf->nf_file), may_flags));
@@ -1034,7 +1048,6 @@ nfsd_do_file_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,refcount_inc (&nf->nf_ref);__set_bit (NFSD_FILE_HASHED , &nf->nf_flags);__set_bit (NFSD_FILE_PENDING , &nf->nf_flags); -nfsd_file_lru_add (nf);hlist_add_head_rcu (&nf->nf_node, &nfsd_file_hashtbl[hashval].nfb_head); ++nfsd_file_hashtbl[hashval].nfb_count; nfsd_file_hashtbl[hashval].nfb_maxcount = max(nfsd_file_hashtbl[hashval].nfb_maxcount,
@@ -1059,6 +1072,7 @@ nfsd_do_file_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,*/ if (status != nfs_ok || inode->i_nlink ==0 ) {bool do_free; +nfsd_file_lru_remove (nf);spin_lock (&nfsd_file_hashtbl[hashval].nfb_lock); do_free =nfsd_file_unhash (nf);spin_unlock (&nfsd_file_hashtbl[hashval].nfb_lock);
fs/nfsd/trace.h +2 -0
@@ -892,7 +892,9 @@ DEFINE_EVENT(nfsd_file_gc_class, name, \ TP_ARGS(nf))DEFINE_NFSD_FILE_GC_EVENT (nfsd_file_lru_add); +DEFINE_NFSD_FILE_GC_EVENT (nfsd_file_lru_add_disposed);DEFINE_NFSD_FILE_GC_EVENT (nfsd_file_lru_del); +DEFINE_NFSD_FILE_GC_EVENT (nfsd_file_lru_del_disposed);DEFINE_NFSD_FILE_GC_EVENT (nfsd_file_gc_in_use);DEFINE_NFSD_FILE_GC_EVENT (nfsd_file_gc_writeback);DEFINE_NFSD_FILE_GC_EVENT (nfsd_file_gc_referenced);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 569/770 NFSD: Fix the filecache LRU shrinker
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit edead3a55804739b2e4af0f35e9c7326264e7b22 ]
Without LRU item rotation, the shrinker visits only a few items on the end of the LRU list, and those would always be long-term OPEN files for NFSv4 workloads. That makes the filecache shrinker completely ineffective.
Adopt the same strategy as the inode LRU by using LRU_ROTATE.
--- fs/nfsd/filecache.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
fs/nfsd/filecache.c +3 -2
@@ -445,6 +445,7 @@ nfsd_file_dispose_list_delayed(struct list_head *dispose)* * Return values: * %LRU_REMOVED: @item was removed from the LRU +* %LRU_ROTATE: @item is to be moved to the LRU tail * %LRU_SKIP: @item cannot be evicted */ static enum lru_status
@@ -483,7 +484,7 @@ nfsd_file_lru_cb(struct list_head *item, struct list_lru_one *lru,if (test_and_clear_bit (NFSD_FILE_REFERENCED , &nf->nf_flags)) {trace_nfsd_file_gc_referenced (nf); -return LRU_SKIP ; +return LRU_ROTATE ; }if (!test_and_clear_bit (NFSD_FILE_HASHED , &nf->nf_flags)) {
@@ -525,7 +526,7 @@ nfsd_file_gc(void)unsigned long ret; ret =list_lru_walk (&nfsd_file_lru, nfsd_file_lru_cb, - &dispose,LONG_MAX ); + &dispose,list_lru_count (&nfsd_file_lru));trace_nfsd_file_gc_removed (ret,list_lru_count (&nfsd_file_lru));nfsd_file_gc_dispose_list (&dispose); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 570/770 NFSD: Never call nfsd_file_gc() in foreground paths
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 6df19411367a5fb4ef61854cbd1af269c077f917 ]
The checks in nfsd_file_acquire() and nfsd_file_put() that directly invoke filecache garbage collection are intended to keep cache occupancy between a low- and high-watermark. The reason to limit the capacity of the filecache is to keep filecache lookups reasonably fast.
However, invoking garbage collection at those points has some undesirable negative impacts. Files that are held open by NFSv4 clients often push the occupancy of the filecache over these watermarks. At that point:
- Every call to nfsd_file_acquire() and nfsd_file_put() results in an LRU walk. This has the same effect on lookup latency as long chains in the hash table.
- Garbage collection will then run on every nfsd thread, causing a lot of unnecessary lock contention.
- Limiting cache capacity pushes out files used only by NFSv3 clients, which are the type of files the filecache is supposed to help.
To address those negative impacts, remove the direct calls to the garbage collector. Subsequent patches will address maintaining lookup efficiency as cache capacity increases.
--- fs/nfsd/filecache.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-)
fs/nfsd/filecache.c +1 -9
@@ -28,8 +28,6 @@#define NFSD_LAUNDRETTE_DELAY (2 * HZ)#define NFSD_FILE_SHUTDOWN (1) -#define NFSD_FILE_LRU_THRESHOLD (4096UL) -#define NFSD_FILE_LRU_LIMIT (NFSD_FILE_LRU_THRESHOLD << 2)/* We only care about NFSD_MAY_READ/WRITE for this cache */ #define NFSD_FILE_MAY_MASK (NFSD_MAY_READ|NFSD_MAY_WRITE)
@@ -65,8 +63,6 @@ static struct fsnotify_group *nfsd_file_fsnotify_group;static atomic_long_t nfsd_filecache_count;static struct delayed_work nfsd_filecache_laundrette; -static void nfsd_file_gc (void ); -static void nfsd_file_schedule_laundrette (void ) {
@@ -343,9 +339,6 @@ nfsd_file_put(struct nfsd_file *nf)nfsd_file_schedule_laundrette (); }else nfsd_file_put_noref (nf); - -if (atomic_long_read (&nfsd_filecache_count) >=NFSD_FILE_LRU_LIMIT ) -nfsd_file_gc (); } struct nfsd_file *
@@ -1054,8 +1047,7 @@ nfsd_do_file_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp, nfsd_file_hashtbl[hashval].nfb_maxcount =max (nfsd_file_hashtbl[hashval].nfb_maxcount, nfsd_file_hashtbl[hashval].nfb_count);spin_unlock (&nfsd_file_hashtbl[hashval].nfb_lock); -if (atomic_long_inc_return (&nfsd_filecache_count) >=NFSD_FILE_LRU_THRESHOLD ) -nfsd_file_gc (); +atomic_long_inc (&nfsd_filecache_count); nf->nf_mark =nfsd_file_mark_find_or_create (nf);if (nf->nf_mark) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 571/770 NFSD: No longer record nf_hashval in the trace log
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 54f7df7094b329ca35d9f9808692bb16c48b13e9 ]
I'm about to replace nfsd_file_hashtbl with an rhashtable. The individual hash values will no longer be visible or relevant, so remove them from the tracepoints.
--- fs/nfsd/filecache.c | 15 ++++++++------- fs/nfsd/trace.h | 45 +++++++++++++++++++++------------------------ 2 files changed, 29 insertions(+), 31 deletions(-)
fs/nfsd/filecache.c +8 -7
@@ -588,7 +588,7 @@ nfsd_file_close_inode_sync(struct inode *inode)LIST_HEAD (dispose);__nfsd_file_close_inode (inode, hashval, &dispose); -trace_nfsd_file_close_inode_sync (inode, hashval, !list_empty (&dispose)); +trace_nfsd_file_close_inode_sync (inode, !list_empty (&dispose));nfsd_file_dispose_list_sync (&dispose); }
@@ -608,7 +608,7 @@ nfsd_file_close_inode(struct inode *inode)LIST_HEAD (dispose);__nfsd_file_close_inode (inode, hashval, &dispose); -trace_nfsd_file_close_inode (inode, hashval, !list_empty (&dispose)); +trace_nfsd_file_close_inode (inode, !list_empty (&dispose));nfsd_file_dispose_list_delayed (&dispose); }
@@ -962,7 +962,7 @@ nfsd_file_is_cached(struct inode *inode) } }rcu_read_unlock (); -trace_nfsd_file_is_cached (inode, hashval, (int )ret); +trace_nfsd_file_is_cached (inode, (int )ret);return ret; }
@@ -994,9 +994,8 @@ nfsd_do_file_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp, new =nfsd_file_alloc (inode, may_flags, hashval, net);if (!new) { -trace_nfsd_file_acquire (rqstp, hashval, inode, may_flags, -NULL , nfserr_jukebox); -return nfserr_jukebox; + status = nfserr_jukebox; + goto out_status; }spin_lock (&nfsd_file_hashtbl[hashval].nfb_lock);
@@ -1034,8 +1033,10 @@ nfsd_do_file_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp, nf =NULL ; } -trace_nfsd_file_acquire (rqstp, hashval, inode, may_flags, nf, status); +out_status: +trace_nfsd_file_acquire (rqstp, inode, may_flags, nf, status);return status; + open_file: nf = new;/* Take reference for the hashtable */
fs/nfsd/trace.h +21 -24
121 lines not on this page · raw message
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 572/770 NFSD: Remove lockdep assertion from unhash_and_release_locked()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit f53cef15dddec7203df702cdc62e554190385450 ]
IIUC, holding the hash bucket lock is needed only in nfsd_file_unhash, and there is already a lockdep assertion there.
--- fs/nfsd/filecache.c | 2 -- 1 file changed, 2 deletions(-)
fs/nfsd/filecache.c +0 -2
@@ -299,8 +299,6 @@ nfsd_file_unhash(struct nfsd_file *nf)static bool nfsd_file_unhash_and_release_locked (struct nfsd_file *nf,struct list_head *dispose) { -lockdep_assert_held (&nfsd_file_hashtbl[nf->nf_hashval].nfb_lock); -trace_nfsd_file_unhash_and_release_locked (nf);if (!nfsd_file_unhash (nf))return false;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 573/770 NFSD: nfsd_file_unhash can compute hashval from nf->nf_inode
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 8755326399f471ec3b31e2ab8c5074c0d28a0fb5 ]
Remove an unnecessary usage of nf_hashval.
--- fs/nfsd/filecache.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
fs/nfsd/filecache.c +6 -2
@@ -272,13 +272,17 @@ static void nfsd_file_lru_remove(struct nfsd_file *nf)static void nfsd_file_do_unhash (struct nfsd_file *nf) { -lockdep_assert_held (&nfsd_file_hashtbl[nf->nf_hashval].nfb_lock); +struct inode *inode = nf->nf_inode; +unsigned int hashval = (unsigned int )hash_long (inode->i_ino, +NFSD_FILE_HASH_BITS ); + +lockdep_assert_held (&nfsd_file_hashtbl[hashval].nfb_lock);trace_nfsd_file_unhash (nf);if (nfsd_file_check_write_error (nf))nfsd_reset_write_verifier (net_generic (nf->nf_net, nfsd_net_id)); - --nfsd_file_hashtbl[nf->nf_hashval].nfb_count; + --nfsd_file_hashtbl[hashval].nfb_count;hlist_del_rcu (&nf->nf_node);atomic_long_dec (&nfsd_filecache_count); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 574/770 NFSD: Refactor __nfsd_file_close_inode()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit a845511007a63467fee575353c706806c21218b1 ]
The code that computes the hashval is the same in both callers.
To prevent them from going stale, reframe the documenting comments to remove descriptions of the underlying hash table structure, which is about to be replaced.
--- fs/nfsd/filecache.c | 40 +++++++++++++++++++++------------------- fs/nfsd/trace.h | 44 +++++++++++++++++++++++++++++++++----------- 2 files changed, 54 insertions(+), 30 deletions(-)
fs/nfsd/filecache.c +21 -19
@@ -558,39 +558,44 @@ static struct shrinker nfsd_file_shrinker = { .seeks = 1, }; -static void -__nfsd_file_close_inode (struct inode *inode,unsigned int hashval, -struct list_head *dispose) +/* +* Find all cache items across all net namespaces that match @inode and +* move them to @dispose. The lookup is atomic wrt nfsd_file_acquire(). +*/ +static unsigned int +__nfsd_file_close_inode (struct inode *inode,struct list_head *dispose) { +unsigned int hashval = (unsigned int )hash_long (inode->i_ino, +NFSD_FILE_HASH_BITS ); +unsigned int count =0 ;struct nfsd_file *nf;struct hlist_node *tmp;spin_lock (&nfsd_file_hashtbl[hashval].nfb_lock);hlist_for_each_entry_safe (nf, tmp, &nfsd_file_hashtbl[hashval].nfb_head, nf_node) { -if (inode == nf->nf_inode) +if (inode == nf->nf_inode) {nfsd_file_unhash_and_release_locked (nf, dispose); + count++; + } }spin_unlock (&nfsd_file_hashtbl[hashval].nfb_lock); +return count; }/** * nfsd_file_close_inode_sync - attempt to forcibly close a nfsd_file * @inode: inode of the file to attempt to remove * -* Walk the whole hash bucket, looking for any files that correspond to "inode". -* If any do, then unhash them and put the hashtable reference to them and -* destroy any that had their last reference put. Also ensure that any of the -* fputs also have their final __fput done as well. +* Unhash and put, then flush and fput all cache items associated with @inode. */ void nfsd_file_close_inode_sync (struct inode *inode) { -unsigned int hashval = (unsigned int )hash_long (inode->i_ino, -NFSD_FILE_HASH_BITS );LIST_HEAD (dispose); +unsigned int count; -__nfsd_file_close_inode (inode, hashval, &dispose); -trace_nfsd_file_close_inode_sync (inode, !list_empty (&dispose)); + count =__nfsd_file_close_inode (inode, &dispose); +trace_nfsd_file_close_inode_sync (inode, count);nfsd_file_dispose_list_sync (&dispose); }
@@ -598,19 +603,16 @@ nfsd_file_close_inode_sync(struct inode *inode)* nfsd_file_close_inode - attempt a delayed close of a nfsd_file * @inode: inode of the file to attempt to remove * -* Walk the whole hash bucket, looking for any files that correspond to "inode". -* If any do, then unhash them and put the hashtable reference to them and -* destroy any that had their last reference put. +* Unhash and put all cache item associated with @inode. */ static void nfsd_file_close_inode (struct inode *inode) { -unsigned int hashval = (unsigned int )hash_long (inode->i_ino, -NFSD_FILE_HASH_BITS );LIST_HEAD (dispose); +unsigned int count; -__nfsd_file_close_inode (inode, hashval, &dispose); -trace_nfsd_file_close_inode (inode, !list_empty (&dispose)); + count =__nfsd_file_close_inode (inode, &dispose); +trace_nfsd_file_close_inode (inode, count);nfsd_file_dispose_list_delayed (&dispose); }
fs/nfsd/trace.h +33 -11
63 lines not on this page · raw message
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 575/770 NFSD: nfsd_file_hash_remove can compute hashval
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit cb7ec76e73ff6640241c8f1f2f35c81d4005a2d6 ]
Remove an unnecessary use of nf_hashval.
--- fs/nfsd/filecache.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-)
fs/nfsd/filecache.c +14 -5
@@ -287,6 +287,18 @@ nfsd_file_do_unhash(struct nfsd_file *nf)atomic_long_dec (&nfsd_filecache_count); } +static void +nfsd_file_hash_remove (struct nfsd_file *nf) +{ +struct inode *inode = nf->nf_inode; +unsigned int hashval = (unsigned int )hash_long (inode->i_ino, +NFSD_FILE_HASH_BITS ); + +spin_lock (&nfsd_file_hashtbl[hashval].nfb_lock); +nfsd_file_do_unhash (nf); +spin_unlock (&nfsd_file_hashtbl[hashval].nfb_lock); +} +static bool nfsd_file_unhash (struct nfsd_file *nf) {
@@ -506,11 +518,8 @@ static void nfsd_file_gc_dispose_list(struct list_head *dispose) {struct nfsd_file *nf; -list_for_each_entry (nf, dispose, nf_lru) { -spin_lock (&nfsd_file_hashtbl[nf->nf_hashval].nfb_lock); -nfsd_file_do_unhash (nf); -spin_unlock (&nfsd_file_hashtbl[nf->nf_hashval].nfb_lock); - } +list_for_each_entry (nf, dispose, nf_lru) +nfsd_file_hash_remove (nf);nfsd_file_dispose_list_delayed (dispose); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 576/770 NFSD: Remove nfsd_file::nf_hashval
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit f0743c2b25c65debd4f599a7c861428cd9de5906 ]
The value in this field can always be computed from nf_inode, thus it is no longer used.
--- fs/nfsd/filecache.c | 6 ++---- fs/nfsd/filecache.h | 1 - 2 files changed, 2 insertions(+), 5 deletions(-)
fs/nfsd/filecache.c +2 -4
@@ -167,8 +167,7 @@ nfsd_file_mark_find_or_create(struct nfsd_file *nf) }static struct nfsd_file * -nfsd_file_alloc (struct inode *inode,unsigned int may,unsigned int hashval, -struct net *net) +nfsd_file_alloc (struct inode *inode,unsigned int may,struct net *net) {struct nfsd_file *nf;
@@ -182,7 +181,6 @@ nfsd_file_alloc(struct inode *inode, unsigned int may, unsigned int hashval, nf->nf_net = net; nf->nf_flags =0 ; nf->nf_inode = inode; - nf->nf_hashval = hashval;refcount_set (&nf->nf_ref,1 ); nf->nf_may = may &NFSD_FILE_MAY_MASK ; nf->nf_mark =NULL ;
@@ -1005,7 +1003,7 @@ nfsd_do_file_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,if (nf) goto wait_for_construction; - new =nfsd_file_alloc (inode, may_flags, hashval, net); + new =nfsd_file_alloc (inode, may_flags, net);if (!new) { status = nfserr_jukebox; goto out_status;
fs/nfsd/filecache.h +0 -1
@@ -40,7 +40,6 @@ struct nfsd_file {#define NFSD_FILE_REFERENCED (2)unsigned long nf_flags;struct inode *nf_inode; -unsigned int nf_hashval;refcount_t nf_ref;unsigned char nf_may;struct nfsd_file_mark *nf_mark;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 577/770 NFSD: Replace the "init once" mechanism
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit c7b824c3d06c85e054caf86e227255112c5e3c38 ]
In a moment, the nfsd_file_hashtbl global will be replaced with an rhashtable. Replace the one or two spots that need to check if the hash table is available. We can easily reuse the SHUTDOWN flag for this purpose.
Document that this mechanism relies on callers to hold the nfsd_mutex to prevent init, shutdown, and purging to run concurrently.
--- fs/nfsd/filecache.c | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-)
fs/nfsd/filecache.c +26 -16
@@ -27,7 +27,7 @@#define NFSD_FILE_HASH_SIZE (1 << NFSD_FILE_HASH_BITS)#define NFSD_LAUNDRETTE_DELAY (2 * HZ) -#define NFSD_FILE_SHUTDOWN (1) +#define NFSD_FILE_CACHE_UP (0)/* We only care about NFSD_MAY_READ/WRITE for this cache */ #define NFSD_FILE_MAY_MASK (NFSD_MAY_READ|NFSD_MAY_WRITE)
@@ -58,7 +58,7 @@ static struct kmem_cache *nfsd_file_slab;static struct kmem_cache *nfsd_file_mark_slab;static struct nfsd_fcache_bucket *nfsd_file_hashtbl;static struct list_lru nfsd_file_lru; -static long nfsd_file_lru_flags; +static unsigned long nfsd_file_flags;static struct fsnotify_group *nfsd_file_fsnotify_group;static atomic_long_t nfsd_filecache_count;static struct delayed_work nfsd_filecache_laundrette;
@@ -66,9 +66,8 @@ static struct delayed_work nfsd_filecache_laundrette;static void nfsd_file_schedule_laundrette (void ) { -long count =atomic_long_read (&nfsd_filecache_count); - -if (count ==0 ||test_bit (NFSD_FILE_SHUTDOWN , &nfsd_file_lru_flags)) +if ((atomic_long_read (&nfsd_filecache_count) ==0 ) || +test_bit (NFSD_FILE_CACHE_UP , &nfsd_file_flags) ==0 )return ; queue_delayed_work(system_wq, &nfsd_filecache_laundrette,
@@ -697,9 +696,8 @@ nfsd_file_cache_init(void)int ret = -ENOMEM ;unsigned int i; -clear_bit (NFSD_FILE_SHUTDOWN , &nfsd_file_lru_flags); - -if (nfsd_file_hashtbl) +lockdep_assert_held (&nfsd_mutex); +if (test_and_set_bit (NFSD_FILE_CACHE_UP , &nfsd_file_flags) ==1 )return 0 ; nfsd_filecache_wq =alloc_workqueue ("nfsd_filecache" ,0 ,0 );
@@ -785,8 +783,8 @@ nfsd_file_cache_init(void)/* * Note this can deadlock with nfsd_file_lru_cb. */ -void -nfsd_file_cache_purge (struct net *net) +static void +__nfsd_file_cache_purge (struct net *net) {unsigned int i;struct nfsd_file *nf;
@@ -794,9 +792,6 @@ nfsd_file_cache_purge(struct net *net)LIST_HEAD (dispose);bool del; -if (!nfsd_file_hashtbl) -return ; -for (i =0 ; i <NFSD_FILE_HASH_SIZE ; i++) {struct nfsd_fcache_bucket *nfb = &nfsd_file_hashtbl[i];
@@ -857,6 +852,19 @@ nfsd_file_cache_start_net(struct net *net)return nn->fcache_disposal ?0 : -ENOMEM ; } +/** +* nfsd_file_cache_purge - Remove all cache items associated with @net +* @net: target net namespace +* +*/ +void +nfsd_file_cache_purge (struct net *net) +{ +lockdep_assert_held (&nfsd_mutex); +if (test_bit (NFSD_FILE_CACHE_UP , &nfsd_file_flags) ==1 ) +__nfsd_file_cache_purge (net); +} +void nfsd_file_cache_shutdown_net (struct net *net) {
@@ -869,7 +877,9 @@ nfsd_file_cache_shutdown(void) {int i; -set_bit (NFSD_FILE_SHUTDOWN , &nfsd_file_lru_flags); +lockdep_assert_held (&nfsd_mutex); +if (test_and_clear_bit (NFSD_FILE_CACHE_UP , &nfsd_file_flags) ==0 ) +return ;lease_unregister_notifier (&nfsd_file_lease_notifier);unregister_shrinker (&nfsd_file_shrinker);
@@ -878,7 +888,7 @@ nfsd_file_cache_shutdown(void)* calling nfsd_file_cache_purge */ cancel_delayed_work_sync (&nfsd_filecache_laundrette); -nfsd_file_cache_purge (NULL ); +__nfsd_file_cache_purge (NULL );list_lru_destroy (&nfsd_file_lru);rcu_barrier ();fsnotify_put_group (nfsd_file_fsnotify_group);
@@ -1142,7 +1152,7 @@ static int nfsd_file_cache_stats_show(struct seq_file *m, void *v)* don't end up racing with server shutdown */ mutex_lock (&nfsd_mutex); -if (nfsd_file_hashtbl) { +if (test_bit (NFSD_FILE_CACHE_UP , &nfsd_file_flags) ==1 ) {for (i =0 ; i <NFSD_FILE_HASH_SIZE ; i++) { count += nfsd_file_hashtbl[i].nfb_count; longest =max (longest, nfsd_file_hashtbl[i].nfb_count);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 578/770 NFSD: Set up an rhashtable for the filecache
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit fc22945ecc2a0a028f3683115f98a922d506c284 ]
Add code to initialize and tear down an rhashtable. The rhashtable is not used yet.
--- fs/nfsd/filecache.c | 160 ++++++++++++++++++++++++++++++++++++++------ fs/nfsd/filecache.h | 1 + 2 files changed, 140 insertions(+), 21 deletions(-)
fs/nfsd/filecache.c +139 -21
@@ -12,6 +12,7 @@#include <linux/fsnotify_backend.h> #include <linux/fsnotify.h> #include <linux/seq_file.h> +#include <linux/rhashtable.h> #include "vfs.h" #include "nfsd.h"
@@ -62,6 +63,136 @@ static unsigned long nfsd_file_flags;static struct fsnotify_group *nfsd_file_fsnotify_group;static atomic_long_t nfsd_filecache_count;static struct delayed_work nfsd_filecache_laundrette; +static struct rhashtable nfsd_file_rhash_tbl +____cacheline_aligned_in_smp ; + +enum nfsd_file_lookup_type { +NFSD_FILE_KEY_INODE , +NFSD_FILE_KEY_FULL , +}; + +struct nfsd_file_lookup_key { +struct inode *inode; +struct net *net; +const struct cred *cred; +unsigned char need; +enum nfsd_file_lookup_type type; +}; + +/* +* The returned hash value is based solely on the address of an in-code +* inode, a pointer to a slab-allocated object. The entropy in such a +* pointer is concentrated in its middle bits. +*/ +static u32 nfsd_file_inode_hash (const struct inode *inode,u32 seed) +{ +unsigned long ptr = (unsigned long )inode; +u32 k; + + k = ptr >>L1_CACHE_SHIFT ; + k &=0x00ffffff ; +return jhash2 (&k,1 , seed); +} + +/** +* nfsd_file_key_hashfn - Compute the hash value of a lookup key +* @data: key on which to compute the hash value +* @len: rhash table's key_len parameter (unused) +* @seed: rhash table's random seed of the day +* +* Return value: +* Computed 32-bit hash value +*/ +static u32 nfsd_file_key_hashfn (const void *data,u32 len,u32 seed) +{ +const struct nfsd_file_lookup_key *key = data; + +return nfsd_file_inode_hash (key->inode, seed); +} + +/** +* nfsd_file_obj_hashfn - Compute the hash value of an nfsd_file +* @data: object on which to compute the hash value +* @len: rhash table's key_len parameter (unused) +* @seed: rhash table's random seed of the day +* +* Return value: +* Computed 32-bit hash value +*/ +static u32 nfsd_file_obj_hashfn (const void *data,u32 len,u32 seed) +{ +const struct nfsd_file *nf = data; + +return nfsd_file_inode_hash (nf->nf_inode, seed); +} + +static bool +nfsd_match_cred (const struct cred *c1,const struct cred *c2) +{ +int i; + +if (!uid_eq (c1->fsuid, c2->fsuid)) +return false; +if (!gid_eq (c1->fsgid, c2->fsgid)) +return false; +if (c1->group_info ==NULL || c2->group_info ==NULL ) +return c1->group_info == c2->group_info; +if (c1->group_info->ngroups != c2->group_info->ngroups) +return false; +for (i =0 ; i < c1->group_info->ngroups; i++) { +if (!gid_eq (c1->group_info->gid[i], c2->group_info->gid[i])) +return false; + } +return true; +} + +/** +* nfsd_file_obj_cmpfn - Match a cache item against search criteria +* @arg: search criteria +* @ptr: cache item to check +* +* Return values: +* %0 - Item matches search criteria +* %1 - Item does not match search criteria +*/ +static int nfsd_file_obj_cmpfn (struct rhashtable_compare_arg *arg, +const void *ptr) +{ +const struct nfsd_file_lookup_key *key = arg->key; +const struct nfsd_file *nf = ptr; + +switch (key->type) { +case NFSD_FILE_KEY_INODE : +if (nf->nf_inode != key->inode) +return 1 ; +break ; +case NFSD_FILE_KEY_FULL : +if (nf->nf_inode != key->inode) +return 1 ; +if (nf->nf_may != key->need) +return 1 ; +if (nf->nf_net != key->net) +return 1 ; +if (!nfsd_match_cred (nf->nf_cred, key->cred)) +return 1 ; +if (test_bit (NFSD_FILE_HASHED , &nf->nf_flags) ==0 ) +return 1 ; +break ; + } +return 0 ; +} + +static const struct rhashtable_params nfsd_file_rhash_params = { + .key_len = sizeof_field(struct nfsd_file, nf_inode), + .key_offset = offsetof(struct nfsd_file , nf_inode), + .head_offset = offsetof(struct nfsd_file , nf_rhash), + .hashfn = nfsd_file_key_hashfn, + .obj_hashfn = nfsd_file_obj_hashfn, + .obj_cmpfn = nfsd_file_obj_cmpfn, +/* Reduce resizing churn on light workloads */ + .min_size =512 ,/* buckets */ + .automatic_shrinking = true, +};static void nfsd_file_schedule_laundrette (void )
@@ -693,13 +824,18 @@ static const struct fsnotify_ops nfsd_file_fsnotify_ops = {int nfsd_file_cache_init (void ) { -int ret = -ENOMEM ; +int ret;unsigned int i;lockdep_assert_held (&nfsd_mutex);if (test_and_set_bit (NFSD_FILE_CACHE_UP , &nfsd_file_flags) ==1 )return 0 ; + ret =rhashtable_init (&nfsd_file_rhash_tbl, &nfsd_file_rhash_params); +if (ret) +return ret; + + ret = -ENOMEM ; nfsd_filecache_wq =alloc_workqueue ("nfsd_filecache" ,0 ,0 );if (!nfsd_filecache_wq) goto out;
@@ -777,6 +913,7 @@ nfsd_file_cache_init(void) nfsd_file_hashtbl =NULL ;destroy_workqueue (nfsd_filecache_wq); nfsd_filecache_wq =NULL ; +rhashtable_destroy (&nfsd_file_rhash_tbl); goto out; }
@@ -902,6 +1039,7 @@ nfsd_file_cache_shutdown(void) nfsd_file_hashtbl =NULL ;destroy_workqueue (nfsd_filecache_wq); nfsd_filecache_wq =NULL ; +rhashtable_destroy (&nfsd_file_rhash_tbl);for_each_possible_cpu (i) {per_cpu (nfsd_file_cache_hits, i) =0 ;
@@ -913,26 +1051,6 @@ nfsd_file_cache_shutdown(void) } } -static bool -nfsd_match_cred (const struct cred *c1,const struct cred *c2) -{ -int i; - -if (!uid_eq (c1->fsuid, c2->fsuid)) -return false; -if (!gid_eq (c1->fsgid, c2->fsgid)) -return false; -if (c1->group_info ==NULL || c2->group_info ==NULL ) -return c1->group_info == c2->group_info; -if (c1->group_info->ngroups != c2->group_info->ngroups) -return false; -for (i =0 ; i < c1->group_info->ngroups; i++) { -if (!gid_eq (c1->group_info->gid[i], c2->group_info->gid[i])) -return false; - } -return true; -} -static struct nfsd_file *nfsd_file_find_locked (struct inode *inode,unsigned int may_flags,unsigned int hashval,struct net *net)
fs/nfsd/filecache.h +1 -0
@@ -29,6 +29,7 @@ struct nfsd_file_mark {* never be dereferenced, only used for comparison. */ struct nfsd_file { +struct rhash_head nf_rhash;struct hlist_node nf_node;struct list_head nf_lru;struct rcu_head nf_rcu;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 579/770 NFSD: Convert the filecache to use rhashtable
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit ce502f81ba884c1fe45dc0ebddbcaaa4ec0fc5fb ]
Enable the filecache hash table to start small, then grow with the workload. Smaller server deployments benefit because there should be lower memory utilization. Larger server deployments should see improved scaling with the number of open files.
--- fs/nfsd/filecache.c | 265 +++++++++++++++++++------------------------- fs/nfsd/trace.h | 63 ++++++++++- 2 files changed, 179 insertions(+), 149 deletions(-)
fs/nfsd/filecache.c +117 -148
@@ -61,7 +61,6 @@ static struct nfsd_fcache_bucket *nfsd_file_hashtbl;static struct list_lru nfsd_file_lru;static unsigned long nfsd_file_flags;static struct fsnotify_group *nfsd_file_fsnotify_group; -static atomic_long_t nfsd_filecache_count;static struct delayed_work nfsd_filecache_laundrette;static struct rhashtable nfsd_file_rhash_tbl____cacheline_aligned_in_smp ;
@@ -197,7 +196,7 @@ static const struct rhashtable_params nfsd_file_rhash_params = {static void nfsd_file_schedule_laundrette (void ) { -if ((atomic_long_read (&nfsd_filecache_count) ==0 ) || +if ((atomic_read (&nfsd_file_rhash_tbl.nelems) ==0 ) ||test_bit (NFSD_FILE_CACHE_UP , &nfsd_file_flags) ==0 )return ;
@@ -297,7 +296,7 @@ nfsd_file_mark_find_or_create(struct nfsd_file *nf) }static struct nfsd_file * -nfsd_file_alloc (struct inode *inode,unsigned int may,struct net *net) +nfsd_file_alloc (struct nfsd_file_lookup_key *key,unsigned int may) {struct nfsd_file *nf;
@@ -308,11 +307,14 @@ nfsd_file_alloc(struct inode *inode, unsigned int may, struct net *net) nf->nf_birthtime =ktime_get (); nf->nf_file =NULL ; nf->nf_cred =get_current_cred (); - nf->nf_net = net; + nf->nf_net = key->net; nf->nf_flags =0 ; - nf->nf_inode = inode; -refcount_set (&nf->nf_ref,1 ); - nf->nf_may = may &NFSD_FILE_MAY_MASK ; +__set_bit (NFSD_FILE_HASHED , &nf->nf_flags); +__set_bit (NFSD_FILE_PENDING , &nf->nf_flags); + nf->nf_inode = key->inode; +/* nf_ref is pre-incremented for hash table */ +refcount_set (&nf->nf_ref,2 ); + nf->nf_may = key->need; nf->nf_mark =NULL ;trace_nfsd_file_alloc (nf); }
@@ -398,40 +400,21 @@ static void nfsd_file_lru_remove(struct nfsd_file *nf) }static void -nfsd_file_do_unhash (struct nfsd_file *nf) +nfsd_file_hash_remove (struct nfsd_file *nf) { -struct inode *inode = nf->nf_inode; -unsigned int hashval = (unsigned int )hash_long (inode->i_ino, -NFSD_FILE_HASH_BITS ); - -lockdep_assert_held (&nfsd_file_hashtbl[hashval].nfb_lock); -trace_nfsd_file_unhash (nf);if (nfsd_file_check_write_error (nf))nfsd_reset_write_verifier (net_generic (nf->nf_net, nfsd_net_id)); - --nfsd_file_hashtbl[hashval].nfb_count; -hlist_del_rcu (&nf->nf_node); -atomic_long_dec (&nfsd_filecache_count); -} - -static void -nfsd_file_hash_remove (struct nfsd_file *nf) -{ -struct inode *inode = nf->nf_inode; -unsigned int hashval = (unsigned int )hash_long (inode->i_ino, -NFSD_FILE_HASH_BITS ); - -spin_lock (&nfsd_file_hashtbl[hashval].nfb_lock); -nfsd_file_do_unhash (nf); -spin_unlock (&nfsd_file_hashtbl[hashval].nfb_lock); +rhashtable_remove_fast (&nfsd_file_rhash_tbl, &nf->nf_rhash, + nfsd_file_rhash_params); }static bool nfsd_file_unhash (struct nfsd_file *nf) {if (test_and_clear_bit (NFSD_FILE_HASHED , &nf->nf_flags)) { -nfsd_file_do_unhash (nf); +nfsd_file_hash_remove (nf);return true; }return false;
@@ -441,9 +424,9 @@ nfsd_file_unhash(struct nfsd_file *nf)* Return true if the file was unhashed. */ static bool -nfsd_file_unhash_and_release_locked (struct nfsd_file *nf,struct list_head *dispose) +nfsd_file_unhash_and_dispose (struct nfsd_file *nf,struct list_head *dispose) { -trace_nfsd_file_unhash_and_release_locked (nf); +trace_nfsd_file_unhash_and_dispose (nf);if (!nfsd_file_unhash (nf))return false;/* keep final reference for nfsd_file_lru_dispose */
@@ -702,20 +685,23 @@ static struct shrinker nfsd_file_shrinker = {static unsigned int __nfsd_file_close_inode (struct inode *inode,struct list_head *dispose) { -unsigned int hashval = (unsigned int )hash_long (inode->i_ino, -NFSD_FILE_HASH_BITS ); -unsigned int count =0 ; -struct nfsd_file *nf; -struct hlist_node *tmp; - -spin_lock (&nfsd_file_hashtbl[hashval].nfb_lock); -hlist_for_each_entry_safe (nf, tmp, &nfsd_file_hashtbl[hashval].nfb_head, nf_node) { -if (inode == nf->nf_inode) { -nfsd_file_unhash_and_release_locked (nf, dispose); - count++; - } - } -spin_unlock (&nfsd_file_hashtbl[hashval].nfb_lock); +struct nfsd_file_lookup_key key = { + .type =NFSD_FILE_KEY_INODE , + .inode = inode, + }; +unsigned int count =0 ; +struct nfsd_file *nf; + +rcu_read_lock (); +do { + nf =rhashtable_lookup (&nfsd_file_rhash_tbl, &key, + nfsd_file_rhash_params); +if (!nf) +break ; +nfsd_file_unhash_and_dispose (nf, dispose); + count++; + }while (1 ); +rcu_read_unlock ();return count; }
@@ -923,30 +909,35 @@ nfsd_file_cache_init(void)static void __nfsd_file_cache_purge (struct net *net) { -unsigned int i; -struct nfsd_file *nf; -struct hlist_node *next; +struct rhashtable_iter iter; +struct nfsd_file *nf;LIST_HEAD (dispose);bool del; -for (i =0 ; i <NFSD_FILE_HASH_SIZE ; i++) { -struct nfsd_fcache_bucket *nfb = &nfsd_file_hashtbl[i]; +rhashtable_walk_enter (&nfsd_file_rhash_tbl, &iter); +do { +rhashtable_walk_start (&iter); -spin_lock (&nfb->nfb_lock); -hlist_for_each_entry_safe (nf, next, &nfb->nfb_head, nf_node) { + nf =rhashtable_walk_next (&iter); +while (!IS_ERR_OR_NULL (nf)) {if (net && nf->nf_net != net)continue ; - del =nfsd_file_unhash_and_release_locked (nf, &dispose); + del =nfsd_file_unhash_and_dispose (nf, &dispose);/* * Deadlock detected! Something marked this entry as * unhased, but hasn't removed it from the hash list. */ WARN_ON_ONCE (!del); + + nf =rhashtable_walk_next (&iter); } -spin_unlock (&nfb->nfb_lock); -nfsd_file_dispose_list (&dispose); - } + +rhashtable_walk_stop (&iter); + }while (nf ==ERR_PTR (-EAGAIN )); +rhashtable_walk_exit (&iter); + +nfsd_file_dispose_list (&dispose); } static struct nfsd_fcache_disposal *
@@ -1051,56 +1042,29 @@ nfsd_file_cache_shutdown(void) } } -static struct nfsd_file * -nfsd_file_find_locked (struct inode *inode,unsigned int may_flags, -unsigned int hashval,struct net *net) -{ -struct nfsd_file *nf; -unsigned char need = may_flags &NFSD_FILE_MAY_MASK ; - -hlist_for_each_entry_rcu (nf, &nfsd_file_hashtbl[hashval].nfb_head, - nf_node,lockdep_is_held (&nfsd_file_hashtbl[hashval].nfb_lock)) { -if (nf->nf_may != need) -continue ; -if (nf->nf_inode != inode) -continue ; -if (nf->nf_net != net) -continue ; -if (!nfsd_match_cred (nf->nf_cred,current_cred ())) -continue ; -if (!test_bit (NFSD_FILE_HASHED , &nf->nf_flags)) -continue ; -if (nfsd_file_get (nf) !=NULL ) -return nf; - } -return NULL ; -} -/** -* nfsd_file_is_cached - are there any cached open files for this fh? -* @inode: inode of the file to check +* nfsd_file_is_cached - are there any cached open files for this inode? +* @inode: inode to check +* +* The lookup matches inodes in all net namespaces and is atomic wrt +* nfsd_file_acquire(). * -* Scan the hashtable for open files that match this fh. Returns true if there -* are any, and false if not. +* Return values: +* %true: filecache contains at least one file matching this inode +* %false: filecache contains no files matching this inode */ bool nfsd_file_is_cached (struct inode *inode) { -bool ret = false; -struct nfsd_file *nf; -unsigned int hashval; - - hashval = (unsigned int )hash_long (inode->i_ino,NFSD_FILE_HASH_BITS ); - -rcu_read_lock (); -hlist_for_each_entry_rcu (nf, &nfsd_file_hashtbl[hashval].nfb_head, - nf_node) { -if (inode == nf->nf_inode) { - ret = true; -break ; - } - } -rcu_read_unlock (); +struct nfsd_file_lookup_key key = { + .type =NFSD_FILE_KEY_INODE , + .inode = inode, + }; +bool ret = false; + +if (rhashtable_lookup_fast (&nfsd_file_rhash_tbl, &key, + nfsd_file_rhash_params) !=NULL ) + ret = true;trace_nfsd_file_is_cached (inode, (int )ret);return ret; }
@@ -1109,39 +1073,51 @@ static __be32 nfsd_do_file_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp, unsigned int may_flags, struct nfsd_file **pnf, bool open) { - __be32 status; -struct net *net =SVC_NET (rqstp); + struct nfsd_file_lookup_key key = { + .type =NFSD_FILE_KEY_FULL , + .need = may_flags &NFSD_FILE_MAY_MASK , + .net =SVC_NET (rqstp), + };struct nfsd_file *nf, *new; -struct inode *inode; -unsigned int hashval;bool retry = true; +__be32 status; -/* FIXME: skip this if fh_dentry is already set? */ status =fh_verify (rqstp, fhp,S_IFREG , may_flags|NFSD_MAY_OWNER_OVERRIDE );if (status != nfs_ok)return status; + key.inode =d_inode (fhp->fh_dentry); + key.cred =get_current_cred (); - inode =d_inode (fhp->fh_dentry); - hashval = (unsigned int )hash_long (inode->i_ino,NFSD_FILE_HASH_BITS ); retry: -rcu_read_lock (); - nf =nfsd_file_find_locked (inode, may_flags, hashval, net); -rcu_read_unlock (); +/* Avoid allocation if the item is already in cache */ + nf =rhashtable_lookup_fast (&nfsd_file_rhash_tbl, &key, + nfsd_file_rhash_params); +if (nf) + nf =nfsd_file_get (nf);if (nf) goto wait_for_construction; - new =nfsd_file_alloc (inode, may_flags, net); + new =nfsd_file_alloc (&key, may_flags);if (!new) { status = nfserr_jukebox; goto out_status; } -spin_lock (&nfsd_file_hashtbl[hashval].nfb_lock); - nf =nfsd_file_find_locked (inode, may_flags, hashval, net); -if (nf ==NULL ) + nf =rhashtable_lookup_get_insert_key (&nfsd_file_rhash_tbl, + &key, &new->nf_rhash, + nfsd_file_rhash_params); +if (!nf) { + nf = new; + goto open_file; + } +if (IS_ERR (nf)) + goto insert_err; + nf =nfsd_file_get (nf); +if (nf ==NULL ) { + nf = new; goto open_file; -spin_unlock (&nfsd_file_hashtbl[hashval].nfb_lock); + }nfsd_file_slab_free (&new->nf_rcu); wait_for_construction:
@@ -1149,6 +1125,7 @@ nfsd_do_file_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,/* Did construction of this file fail? */ if (!test_bit (NFSD_FILE_HASHED , &nf->nf_flags)) { +trace_nfsd_file_cons_err (rqstp, key.inode, may_flags, nf);if (!retry) { status = nfserr_jukebox; goto out;
@@ -1173,22 +1150,11 @@ nfsd_do_file_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp, } out_status: -trace_nfsd_file_acquire (rqstp, inode, may_flags, nf, status); +put_cred (key.cred); +trace_nfsd_file_acquire (rqstp, key.inode, may_flags, nf, status);return status; open_file: - nf = new; -/* Take reference for the hashtable */ -refcount_inc (&nf->nf_ref); -__set_bit (NFSD_FILE_HASHED , &nf->nf_flags); -__set_bit (NFSD_FILE_PENDING , &nf->nf_flags); -hlist_add_head_rcu (&nf->nf_node, &nfsd_file_hashtbl[hashval].nfb_head); - ++nfsd_file_hashtbl[hashval].nfb_count; - nfsd_file_hashtbl[hashval].nfb_maxcount =max (nfsd_file_hashtbl[hashval].nfb_maxcount, - nfsd_file_hashtbl[hashval].nfb_count); -spin_unlock (&nfsd_file_hashtbl[hashval].nfb_lock); -atomic_long_inc (&nfsd_filecache_count); - nf->nf_mark =nfsd_file_mark_find_or_create (nf);if (nf->nf_mark) {if (open) {
@@ -1203,19 +1169,20 @@ nfsd_do_file_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,* If construction failed, or we raced with a call to unlink() * then unhash. */ -if (status != nfs_ok || inode->i_nlink ==0 ) { -bool do_free; -nfsd_file_lru_remove (nf); -spin_lock (&nfsd_file_hashtbl[hashval].nfb_lock); - do_free =nfsd_file_unhash (nf); -spin_unlock (&nfsd_file_hashtbl[hashval].nfb_lock); -if (do_free) +if (status != nfs_ok || key.inode->i_nlink ==0 ) +if (nfsd_file_unhash (nf))nfsd_file_put_noref (nf); - }clear_bit_unlock (NFSD_FILE_PENDING , &nf->nf_flags);smp_mb__after_atomic ();wake_up_bit (&nf->nf_flags,NFSD_FILE_PENDING ); goto out; + +insert_err: +nfsd_file_slab_free (&new->nf_rcu); +trace_nfsd_file_insert_err (rqstp, key.inode, may_flags,PTR_ERR (nf)); + nf =NULL ; + status = nfserr_jukebox; + goto out_status; }/**
@@ -1261,21 +1228,23 @@ static int nfsd_file_cache_stats_show(struct seq_file *m, void *v) {unsigned long releases =0 , pages_flushed =0 , evictions =0 ;unsigned long hits =0 , acquisitions =0 ; -unsigned int i, count =0 , longest =0 ; +unsigned int i, count =0 , buckets =0 ;unsigned long lru =0 , total_age =0 ; -/* -* No need for spinlocks here since we're not terribly interested in -* accuracy. We do take the nfsd_mutex simply to ensure that we -* don't end up racing with server shutdown -*/ +/* Serialize with server shutdown */ mutex_lock (&nfsd_mutex);if (test_bit (NFSD_FILE_CACHE_UP , &nfsd_file_flags) ==1 ) { -for (i =0 ; i <NFSD_FILE_HASH_SIZE ; i++) { - count += nfsd_file_hashtbl[i].nfb_count; - longest =max (longest, nfsd_file_hashtbl[i].nfb_count); - } +struct bucket_table *tbl; +struct rhashtable *ht; + lru =list_lru_count (&nfsd_file_lru); + +rcu_read_lock (); + ht = &nfsd_file_rhash_tbl; + count =atomic_read (&ht->nelems); + tbl =rht_dereference_rcu (ht->tbl, ht); + buckets = tbl->size; +rcu_read_unlock (); }mutex_unlock (&nfsd_mutex);
@@ -1289,7 +1258,7 @@ static int nfsd_file_cache_stats_show(struct seq_file *m, void *v) }seq_printf (m,"total entries: %u\n" , count); -seq_printf (m,"longest chain: %u\n" , longest); +seq_printf (m,"hash buckets: %u\n" , buckets);seq_printf (m,"lru entries: %lu\n" , lru);seq_printf (m,"cache hits: %lu\n" , hits);seq_printf (m,"acquisitions: %lu\n" , acquisitions);
fs/nfsd/trace.h +62 -1
75 lines not on this page · raw message
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 580/770 NFSD: Clean up unused code after rhashtable conversion
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 0ec8e9d1539a7b8109a554028bbce441052f847e ]
--- fs/nfsd/filecache.c | 33 +-------------------------------- fs/nfsd/filecache.h | 1 - 2 files changed, 1 insertion(+), 33 deletions(-)
fs/nfsd/filecache.c +1 -32
@@ -21,11 +21,6 @@#include "filecache.h" #include "trace.h" -#define NFSDDBG_FACILITY NFSDDBG_FH - -/* FIXME: dynamically size this for the machine somehow? */ -#define NFSD_FILE_HASH_BITS 12 -#define NFSD_FILE_HASH_SIZE (1 << NFSD_FILE_HASH_BITS)#define NFSD_LAUNDRETTE_DELAY (2 * HZ)#define NFSD_FILE_CACHE_UP (0)
@@ -33,13 +28,6 @@/* We only care about NFSD_MAY_READ/WRITE for this cache */ #define NFSD_FILE_MAY_MASK (NFSD_MAY_READ|NFSD_MAY_WRITE) -struct nfsd_fcache_bucket { -struct hlist_head nfb_head; -spinlock_t nfb_lock; -unsigned int nfb_count; -unsigned int nfb_maxcount; -}; - static DEFINE_PER_CPU(unsigned long, nfsd_file_cache_hits); static DEFINE_PER_CPU(unsigned long, nfsd_file_acquisitions); static DEFINE_PER_CPU(unsigned long, nfsd_file_releases);
@@ -57,7 +45,6 @@ static struct workqueue_struct *nfsd_filecache_wq __read_mostly;static struct kmem_cache *nfsd_file_slab;static struct kmem_cache *nfsd_file_mark_slab; -static struct nfsd_fcache_bucket *nfsd_file_hashtbl;static struct list_lru nfsd_file_lru;static unsigned long nfsd_file_flags;static struct fsnotify_group *nfsd_file_fsnotify_group;
@@ -302,7 +289,6 @@ nfsd_file_alloc(struct nfsd_file_lookup_key *key, unsigned int may) nf =kmem_cache_alloc (nfsd_file_slab,GFP_KERNEL );if (nf) { -INIT_HLIST_NODE (&nf->nf_node);INIT_LIST_HEAD (&nf->nf_lru); nf->nf_birthtime =ktime_get (); nf->nf_file =NULL ;
@@ -810,8 +796,7 @@ static const struct fsnotify_ops nfsd_file_fsnotify_ops = {int nfsd_file_cache_init (void ) { -int ret; -unsigned int i; +int ret;lockdep_assert_held (&nfsd_mutex);if (test_and_set_bit (NFSD_FILE_CACHE_UP , &nfsd_file_flags) ==1 )
@@ -826,13 +811,6 @@ nfsd_file_cache_init(void)if (!nfsd_filecache_wq) goto out; - nfsd_file_hashtbl =kvcalloc (NFSD_FILE_HASH_SIZE , -sizeof (*nfsd_file_hashtbl),GFP_KERNEL ); -if (!nfsd_file_hashtbl) { -pr_err ("nfsd: unable to allocate nfsd_file_hashtbl\n" ); - goto out_err; - } - nfsd_file_slab =kmem_cache_create ("nfsd_file" ,sizeof (struct nfsd_file ),0 ,0 ,NULL );if (!nfsd_file_slab) {
@@ -876,11 +854,6 @@ nfsd_file_cache_init(void) goto out_notifier; } -for (i =0 ; i <NFSD_FILE_HASH_SIZE ; i++) { -INIT_HLIST_HEAD (&nfsd_file_hashtbl[i].nfb_head); -spin_lock_init (&nfsd_file_hashtbl[i].nfb_lock); - } -INIT_DELAYED_WORK (&nfsd_filecache_laundrette, nfsd_file_gc_worker); out:return ret;
@@ -895,8 +868,6 @@ nfsd_file_cache_init(void) nfsd_file_slab =NULL ;kmem_cache_destroy (nfsd_file_mark_slab); nfsd_file_mark_slab =NULL ; -kvfree (nfsd_file_hashtbl); - nfsd_file_hashtbl =NULL ;destroy_workqueue (nfsd_filecache_wq); nfsd_filecache_wq =NULL ;rhashtable_destroy (&nfsd_file_rhash_tbl);
@@ -1026,8 +997,6 @@ nfsd_file_cache_shutdown(void)fsnotify_wait_marks_destroyed ();kmem_cache_destroy (nfsd_file_mark_slab); nfsd_file_mark_slab =NULL ; -kvfree (nfsd_file_hashtbl); - nfsd_file_hashtbl =NULL ;destroy_workqueue (nfsd_filecache_wq); nfsd_filecache_wq =NULL ;rhashtable_destroy (&nfsd_file_rhash_tbl);
fs/nfsd/filecache.h +0 -1
@@ -30,7 +30,6 @@ struct nfsd_file_mark {*/ struct nfsd_file {struct rhash_head nf_rhash; -struct hlist_node nf_node;struct list_head nf_lru;struct rcu_head nf_rcu;struct file *nf_file;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 581/770 NFSD: Separate tracepoints for acquire and create
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit be0230069fcbf7d332d010b57c1d0cfd623a84d6 ]
These tracepoints collect different information: the create case does not open a file, so there's no nf_file available.
--- fs/nfsd/filecache.c | 9 ++++---- fs/nfsd/nfs4state.c | 1 + fs/nfsd/trace.h | 54 ++++++++++++++++++++++++++++++++++++++------- 3 files changed, 52 insertions(+), 12 deletions(-)
fs/nfsd/filecache.c +5 -4
@@ -1039,7 +1039,7 @@ nfsd_file_is_cached(struct inode *inode) }static __be32 -nfsd_do_file_acquire (struct svc_rqst *rqstp,struct svc_fh *fhp, +nfsd_file_do_acquire (struct svc_rqst *rqstp,struct svc_fh *fhp,unsigned int may_flags,struct nfsd_file **pnf,bool open) {struct nfsd_file_lookup_key key = {
@@ -1120,7 +1120,8 @@ nfsd_do_file_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp, out_status:put_cred (key.cred); -trace_nfsd_file_acquire (rqstp, key.inode, may_flags, nf, status); +if (open) +trace_nfsd_file_acquire (rqstp, key.inode, may_flags, nf, status);return status; open_file:
@@ -1168,7 +1169,7 @@ __be32 nfsd_file_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp, unsigned int may_flags, struct nfsd_file **pnf) { - return nfsd_do_file_acquire(rqstp, fhp, may_flags, pnf, true); + return nfsd_file_do_acquire(rqstp, fhp, may_flags, pnf, true); }/**
@@ -1185,7 +1186,7 @@ __be32 nfsd_file_create(struct svc_rqst *rqstp, struct svc_fh *fhp, unsigned int may_flags, struct nfsd_file **pnf) { - return nfsd_do_file_acquire(rqstp, fhp, may_flags, pnf, false); + return nfsd_file_do_acquire(rqstp, fhp, may_flags, pnf, false); }/*
fs/nfsd/nfs4state.c +1 -0
@@ -5121,6 +5121,7 @@ static __be32 nfs4_get_vfs_file(struct svc_rqst *rqstp, struct nfs4_file *fp, goto out_put_access; nf->nf_file = open->op_filp; open->op_filp =NULL ; +trace_nfsd_file_create (rqstp, access, nf); }spin_lock (&fp->fi_lock);
fs/nfsd/trace.h +46 -8
80 lines not on this page · raw message
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 582/770 NFSD: Move nfsd_file_trace_alloc() tracepoint
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit b40a2839470cd62ed68c4a32d72a18ee8975b1ac ]
Avoid recording the allocation of an nfsd_file item that is immediately released because a matching item was already inserted in the hash.
--- fs/nfsd/filecache.c | 2 +- fs/nfsd/trace.h | 25 ++++++++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-)
fs/nfsd/filecache.c +1 -1
@@ -302,7 +302,6 @@ nfsd_file_alloc(struct nfsd_file_lookup_key *key, unsigned int may)refcount_set (&nf->nf_ref,2 ); nf->nf_may = key->need; nf->nf_mark =NULL ; -trace_nfsd_file_alloc (nf); }return nf; }
@@ -1125,6 +1124,7 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,return status; open_file: +trace_nfsd_file_alloc (nf); nf->nf_mark =nfsd_file_mark_find_or_create (nf);if (nf->nf_mark) {if (open) {
fs/nfsd/trace.h +24 -1
@@ -739,12 +739,35 @@ DEFINE_EVENT(nfsd_file_class, name, \ TP_PROTO(struct nfsd_file *nf), \ TP_ARGS(nf)) -DEFINE_NFSD_FILE_EVENT(nfsd_file_alloc); DEFINE_NFSD_FILE_EVENT(nfsd_file_put_final); DEFINE_NFSD_FILE_EVENT(nfsd_file_unhash); DEFINE_NFSD_FILE_EVENT(nfsd_file_put); DEFINE_NFSD_FILE_EVENT(nfsd_file_unhash_and_dispose); +TRACE_EVENT(nfsd_file_alloc, + TP_PROTO( + const struct nfsd_file *nf + ), + TP_ARGS(nf), + TP_STRUCT__entry( + __field(const void *, nf_inode) + __field(unsigned long, nf_flags) + __field(unsigned long, nf_may) + __field(unsigned int, nf_ref) + ), + TP_fast_assign( + __entry->nf_inode = nf->nf_inode; + __entry->nf_flags = nf->nf_flags; + __entry->nf_ref = refcount_read(&nf->nf_ref); + __entry->nf_may = nf->nf_may; + ), + TP_printk("inode=%p ref=%u flags=%s may=%s", + __entry->nf_inode, __entry->nf_ref, +show_nf_flags (__entry->nf_flags), +show_nfsd_may_flags (__entry->nf_may) + ) +); + TRACE_EVENT(nfsd_file_acquire, TP_PROTO( const struct svc_rqst *rqstp,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 583/770 NFSD: NFSv4 CLOSE should release an nfsd_file immediately
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 5e138c4a750dc140d881dab4a8804b094bbc08d2 ]
The last close of a file should enable other accessors to open and use that file immediately. Leaving the file open in the filecache prevents other users from accessing that file until the filecache garbage-collects the file -- sometimes that takes several seconds.
--- fs/nfsd/filecache.c | 18 ++++++++++++++++++ fs/nfsd/filecache.h | 1 + fs/nfsd/nfs4state.c | 4 ++-- 3 files changed, 21 insertions(+), 2 deletions(-)
fs/nfsd/filecache.c +18 -0
@@ -451,6 +451,24 @@ nfsd_file_put(struct nfsd_file *nf)nfsd_file_put_noref (nf); } +/** +* nfsd_file_close - Close an nfsd_file +* @nf: nfsd_file to close +* +* If this is the final reference for @nf, free it immediately. +* This reflects an on-the-wire CLOSE or DELEGRETURN into the +* VFS and exported filesystem. +*/ +void nfsd_file_close (struct nfsd_file *nf) +{ +nfsd_file_put (nf); +if (refcount_dec_if_one (&nf->nf_ref)) { +nfsd_file_unhash (nf); +nfsd_file_lru_remove (nf); +nfsd_file_free (nf); + } +} +struct nfsd_file *nfsd_file_get (struct nfsd_file *nf) {
fs/nfsd/filecache.h +1 -0
@@ -52,6 +52,7 @@ void nfsd_file_cache_shutdown(void);int nfsd_file_cache_start_net (struct net *net);void nfsd_file_cache_shutdown_net (struct net *net);void nfsd_file_put (struct nfsd_file *nf); +void nfsd_file_close (struct nfsd_file *nf);struct nfsd_file *nfsd_file_get (struct nfsd_file *nf);void nfsd_file_close_inode_sync (struct inode *inode);bool nfsd_file_is_cached (struct inode *inode);
fs/nfsd/nfs4state.c +2 -2
@@ -831,9 +831,9 @@ static void __nfs4_file_put_access(struct nfs4_file *fp, int oflag)swap (f2, fp->fi_fds[O_RDWR ]);spin_unlock (&fp->fi_lock);if (f1) -nfsd_file_put (f1); +nfsd_file_close (f1);if (f2) -nfsd_file_put (f2); +nfsd_file_close (f2); } }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 584/770 NFSD: Ensure nf_inode is never dereferenced
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 427f5f83a3191cbf024c5aea6e5b601cdf88d895 ]
The documenting comment for struct nf_file states:
/*
* A representation of a file that has been opened by knfsd. These are hashed
* in the hashtable by inode pointer value. Note that this object doesn't
* hold a reference to the inode by itself, so the nf_inode pointer should
* never be dereferenced, only used for comparison.
*/
Replace the two existing dereferences to make the comment always true.
--- fs/nfsd/filecache.c | 5 ++--- fs/nfsd/filecache.h | 2 +- fs/nfsd/nfs4state.c | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-)
fs/nfsd/filecache.c +2 -3
@@ -227,12 +227,11 @@ nfsd_file_mark_put(struct nfsd_file_mark *nfm) }static struct nfsd_file_mark * -nfsd_file_mark_find_or_create (struct nfsd_file *nf) +nfsd_file_mark_find_or_create (struct nfsd_file *nf,struct inode *inode) {int err;struct fsnotify_mark *mark;struct nfsd_file_mark *nfm =NULL , *new; -struct inode *inode = nf->nf_inode; do { fsnotify_group_lock(nfsd_file_fsnotify_group);
@@ -1143,7 +1142,7 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp, open_file:trace_nfsd_file_alloc (nf); - nf->nf_mark =nfsd_file_mark_find_or_create (nf); + nf->nf_mark =nfsd_file_mark_find_or_create (nf, key.inode);if (nf->nf_mark) {if (open) { status = nfsd_open_verified(rqstp, fhp, may_flags,
fs/nfsd/filecache.h +1 -1
@@ -39,7 +39,7 @@ struct nfsd_file {#define NFSD_FILE_PENDING (1)#define NFSD_FILE_REFERENCED (2)unsigned long nf_flags; -struct inode *nf_inode; +struct inode *nf_inode;/* don't deref */ refcount_t nf_ref;unsigned char nf_may;struct nfsd_file_mark *nf_mark;
fs/nfsd/nfs4state.c +1 -1
@@ -2577,7 +2577,7 @@ static void nfs4_show_fname(struct seq_file *s, struct nfsd_file *f)static void nfs4_show_superblock (struct seq_file *s,struct nfsd_file *f) { -struct inode *inode = f->nf_inode; +struct inode *inode =file_inode (f->nf_file); seq_printf(s, "superblock: \"%02x:%02x:%ld\"", MAJOR(inode->i_sb->s_dev),
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 585/770 NFSD: refactoring v4 specific code to a helper in nfs4state.c
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dai Ngo <[email protected]>
[ Upstream commit 6867137ebcf4155fe25f2ecf7c29b9fb90a76d1d ]
This patch moves the v4 specific code from nfsd_init_net() to nfsd4_init_leases_net() helper in nfs4state.c
--- fs/nfsd/nfs4state.c | 12 ++++++++++++ fs/nfsd/nfsctl.c | 9 +-------- fs/nfsd/nfsd.h | 4 ++++ 3 files changed, 17 insertions(+), 8 deletions(-)
fs/nfsd/nfs4state.c +12 -0
@@ -4347,6 +4347,18 @@ nfsd4_init_slabs(void)return -ENOMEM ; } +void nfsd4_init_leases_net (struct nfsd_net *nn) +{ + nn->nfsd4_lease =90 ;/* default lease time */ + nn->nfsd4_grace =90 ; + nn->somebody_reclaimed = false; + nn->track_reclaim_completes = false; + nn->clverifier_counter =prandom_u32 (); + nn->clientid_base =prandom_u32 (); + nn->clientid_counter = nn->clientid_base +1 ; + nn->s2s_cp_cl_id = nn->clientid_counter++; +} +static void init_nfs4_replay (struct nfs4_replay *rp) { rp->rp_status = nfserr_serverfault;
fs/nfsd/nfsctl.c +1 -8
@@ -1484,14 +1484,7 @@ static __net_init int nfsd_init_net(struct net *net) retval =nfsd_reply_cache_init (nn);if (retval) goto out_drc_error; - nn->nfsd4_lease =90 ;/* default lease time */ - nn->nfsd4_grace =90 ; - nn->somebody_reclaimed = false; - nn->track_reclaim_completes = false; - nn->clverifier_counter =prandom_u32 (); - nn->clientid_base =prandom_u32 (); - nn->clientid_counter = nn->clientid_base +1 ; - nn->s2s_cp_cl_id = nn->clientid_counter++; +nfsd4_init_leases_net (nn);get_random_bytes (&nn->siphash_key,sizeof (nn->siphash_key));seqlock_init (&nn->writeverf_lock);
fs/nfsd/nfsd.h +4 -0
@@ -496,12 +496,16 @@ extern void unregister_cld_notifier(void);extern void nfsd4_ssc_init_umount_work (struct nfsd_net *nn);#endif +extern void nfsd4_init_leases_net (struct nfsd_net *nn); +#else /* CONFIG_NFSD_V4 */ static inline int nfsd4_is_junction (struct dentry *dentry) {return 0 ; } +static inline void nfsd4_init_leases_net (struct nfsd_net *nn) {}; +#define register_cld_notifier () 0#define unregister_cld_notifier () do { } while(0)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 586/770 NFSD: keep track of the number of v4 clients in the system
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dai Ngo <[email protected]>
[ Upstream commit 0926c39515aa065a296e97dfc8790026f1e53f86 ]
Add counter nfs4_client_count to keep track of the total number of v4 clients, including courtesy clients, in the system.
--- fs/nfsd/netns.h | 2 ++ fs/nfsd/nfs4state.c | 10 ++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-)
fs/nfsd/netns.h +2 -0
@@ -189,6 +189,8 @@ struct nfsd_net {struct nfsd_fcache_disposal *fcache_disposal;siphash_key_t siphash_key; + +atomic_t nfs4_client_count; };/* Simple check to find out if a given net was properly initialized */
fs/nfsd/nfs4state.c +8 -2
@@ -2066,7 +2066,8 @@ STALE_CLIENTID(clientid_t *clid, struct nfsd_net *nn)* This type of memory management is somewhat inefficient, but we use it * anyway since SETCLIENTID is not a common operation. */ -static struct nfs4_client *alloc_client (struct xdr_netobj name) +static struct nfs4_client *alloc_client (struct xdr_netobj name, +struct nfsd_net *nn) {struct nfs4_client *clp;int i;
@@ -2089,6 +2090,7 @@ static struct nfs4_client *alloc_client(struct xdr_netobj name)atomic_set (&clp->cl_rpc_users,0 ); clp->cl_cb_state =NFSD4_CB_UNKNOWN ; clp->cl_state =NFSD4_ACTIVE ; +atomic_inc (&nn->nfs4_client_count);atomic_set (&clp->cl_delegs_in_recall,0 );INIT_LIST_HEAD (&clp->cl_idhash);INIT_LIST_HEAD (&clp->cl_openowners);
@@ -2196,6 +2198,7 @@ static __be32 mark_client_expired_locked(struct nfs4_client *clp)static void __destroy_client (struct nfs4_client *clp) { +struct nfsd_net *nn =net_generic (clp->net, nfsd_net_id);int i;struct nfs4_openowner *oo;struct nfs4_delegation *dp;
@@ -2239,6 +2242,7 @@ __destroy_client(struct nfs4_client *clp)nfsd4_shutdown_callback (clp);if (clp->cl_cb_conn.cb_xprt)svc_xprt_put (clp->cl_cb_conn.cb_xprt); +atomic_add_unless (&nn->nfs4_client_count,-1 ,0 );free_client (clp);wake_up_all (&expiry_wq); }
@@ -2865,7 +2869,7 @@ static struct nfs4_client *create_client(struct xdr_netobj name,struct nfsd_net *nn =net_generic (net, nfsd_net_id);struct dentry *dentries[ARRAY_SIZE (client_files)]; - clp =alloc_client (name); + clp =alloc_client (name, nn);if (clp ==NULL )return NULL ;
@@ -4357,6 +4361,8 @@ void nfsd4_init_leases_net(struct nfsd_net *nn) nn->clientid_base =prandom_u32 (); nn->clientid_counter = nn->clientid_base +1 ; nn->s2s_cp_cl_id = nn->clientid_counter++; + +atomic_set (&nn->nfs4_client_count,0 ); }static void init_nfs4_replay (struct nfs4_replay *rp)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 587/770 NFSD: limit the number of v4 clients to 1024 per 1GB of system memory
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dai Ngo <[email protected]>
[ Upstream commit 4271c2c0887562318a0afef97d32d8a71cbe0743 ]
Currently there is no limit on how many v4 clients are supported by the system. This can be a problem in systems with small memory configuration to function properly when a very large number of clients exist that creates memory shortage conditions.
This patch enforces a limit of 1024 NFSv4 clients, including courtesy clients, per 1GB of system memory. When the number of the clients reaches the limit, requests that create new clients are returned with NFS4ERR_DELAY and the laundromat is kicked start to trim old clients. Due to the overhead of the upcall to remove the client record, the maximun number of clients the laundromat removes on each run is limited to 128. This is done to ensure the laundromat can still process the other tasks in a timely manner.
Since there is now a limit of the number of clients, the 24-hr idle time limit of courtesy client is no longer needed and was removed.
--- fs/nfsd/netns.h | 1 + fs/nfsd/nfs4state.c | 27 +++++++++++++++++++++------ fs/nfsd/nfsd.h | 2 ++ 3 files changed, 24 insertions(+), 6 deletions(-)
fs/nfsd/netns.h +1 -0
@@ -191,6 +191,7 @@ struct nfsd_net {siphash_key_t siphash_key;atomic_t nfs4_client_count; +int nfs4_max_clients; };/* Simple check to find out if a given net was properly initialized */
fs/nfsd/nfs4state.c +21 -6
@@ -2072,6 +2072,10 @@ static struct nfs4_client *alloc_client(struct xdr_netobj name,struct nfs4_client *clp;int i; +if (atomic_read (&nn->nfs4_client_count) >= nn->nfs4_max_clients) { +mod_delayed_work (laundry_wq, &nn->laundromat_work,0 ); +return NULL ; + } clp =kmem_cache_zalloc (client_slab,GFP_KERNEL );if (clp ==NULL )return NULL ;
@@ -4353,6 +4357,9 @@ nfsd4_init_slabs(void)void nfsd4_init_leases_net (struct nfsd_net *nn) { +struct sysinfo si; +u64 max_clients; + nn->nfsd4_lease =90 ;/* default lease time */ nn->nfsd4_grace =90 ; nn->somebody_reclaimed = false;
@@ -4363,6 +4370,10 @@ void nfsd4_init_leases_net(struct nfsd_net *nn) nn->s2s_cp_cl_id = nn->clientid_counter++;atomic_set (&nn->nfs4_client_count,0 ); +si_meminfo (&si); + max_clients = (u64 )si.totalram * si.mem_unit / (1024 *1024 *1024 ); + max_clients *=NFS4_CLIENTS_PER_GB ; + nn->nfs4_max_clients =max_t (int, max_clients,NFS4_CLIENTS_PER_GB ); }static void init_nfs4_replay (struct nfs4_replay *rp)
@@ -5828,9 +5839,12 @@ static void nfs4_get_client_reaplist(struct nfsd_net *nn, struct list_head *reaplist, struct laundry_time *lt) { + unsigned int maxreap, reapcnt = 0;struct list_head *pos, *next;struct nfs4_client *clp; + maxreap = (atomic_read (&nn->nfs4_client_count) >= nn->nfs4_max_clients) ? +NFSD_CLIENT_MAX_TRIM_PER_RUN :0 ;INIT_LIST_HEAD (reaplist);spin_lock (&nn->client_lock);list_for_each_safe (pos, next, &nn->client_lru) {
@@ -5841,14 +5855,15 @@ nfs4_get_client_reaplist(struct nfsd_net *nn, struct list_head *reaplist,break ;if (!atomic_read (&clp->cl_rpc_users)) clp->cl_state =NFSD4_COURTESY ; -if (!client_has_state (clp) || -ktime_get_boottime_seconds () >= - (clp->cl_time +NFSD_COURTESY_CLIENT_TIMEOUT )) +if (!client_has_state (clp)) goto exp_client; -if (nfs4_anylock_blockers (clp)) { +if (!nfs4_anylock_blockers (clp)) +if (reapcnt >= maxreap) +continue ; exp_client: -if (!mark_client_expired_locked (clp)) -list_add (&clp->cl_lru, reaplist); +if (!mark_client_expired_locked (clp)) { +list_add (&clp->cl_lru, reaplist); + reapcnt++; } }spin_unlock (&nn->client_lock);
fs/nfsd/nfsd.h +2 -0
@@ -341,6 +341,8 @@ void nfsd_lockd_shutdown(void);#define NFSD_LAUNDROMAT_MINTIMEOUT 1/* seconds */ #define NFSD_COURTESY_CLIENT_TIMEOUT (24 * 60 * 60)/* seconds */ +#define NFSD_CLIENT_MAX_TRIM_PER_RUN 128 +#define NFS4_CLIENTS_PER_GB 1024/* * The following attributes are currently not supported by the NFSv4 server:
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 588/770 nfsd: silence extraneous printk on nfsd.ko insertion
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeff Layton <[email protected]>
[ Upstream commit 3a5940bfa17fb9964bf9688b4356ca643a8f5e2d ]
This printk pops every time nfsd.ko gets plugged in. Most kmods don't do that and this one is not very informative. Olaf's email address seems to be defunct at this point anyway. Just drop it.
--- fs/nfsd/nfsctl.c | 1 - 1 file changed, 1 deletion(-)
fs/nfsd/nfsctl.c +0 -1
@@ -1519,7 +1519,6 @@ static struct pernet_operations nfsd_net_ops = {static int __init init_nfsd (void ) {int retval; -printk (KERN_INFO "Installing knfsd (copyright (C) 1996 [email protected]).\n" ); retval =nfsd4_init_slabs ();if (retval)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 589/770 NFSD: Optimize nfsd4_encode_operation()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 095a764b7afb06c9499b798c04eaa3cbf70ebe2d ]
write_bytes_to_xdr_buf() is a generic way to place a variable-length data item in an already-reserved spot in the encoding buffer. However, it is costly, and here, it is unnecessary because the data item is fixed in size, the buffer destination address is always word-aligned, and the destination location is already in @p.
--- fs/nfsd/nfs4xdr.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
fs/nfsd/nfs4xdr.c +1 -2
@@ -5381,8 +5381,7 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op) so->so_replay.rp_buf, len); } status: -/* Note that op->status is already in network byte order: */ -write_bytes_to_xdr_buf (xdr->buf, post_err_offset -4 , &op->status,4 ); + *p = op->status; }/*
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 590/770 NFSD: Optimize nfsd4_encode_fattr()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit ab04de60ae1cc64ae16b77feae795311b97720c7 ]
write_bytes_to_xdr_buf() is a generic way to place a variable-length data item in an already-reserved spot in the encoding buffer.
However, it is costly. In nfsd4_encode_fattr(), it is unnecessary because the data item is fixed in size and the buffer destination address is always word-aligned.
--- fs/nfsd/nfs4xdr.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-)
fs/nfsd/nfs4xdr.c +4 -7
@@ -2828,10 +2828,9 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,struct kstat stat;struct svc_fh *tempfh =NULL ;struct kstatfs statfs; -__be32 *p; +__be32 *p, *attrlen_p;int starting_len = xdr->buf->len;int attrlen_offset; -__be32 attrlen;u32 dummy;u64 dummy64;u32 rdattr_err =0 ;
@@ -2919,10 +2918,9 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp, goto out; attrlen_offset = xdr->buf->len; - p =xdr_reserve_space (xdr,4 ); -if (!p) + attrlen_p =xdr_reserve_space (xdr,XDR_UNIT ); +if (!attrlen_p) goto out_resource; - p++;/* to be backfilled later */ if (bmval0 &FATTR4_WORD0_SUPPORTED_ATTRS ) {u32 supp[3 ];
@@ -3344,8 +3342,7 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp, *p++ =cpu_to_be32 (err ==0 ); } - attrlen =htonl (xdr->buf->len - attrlen_offset -4 ); -write_bytes_to_xdr_buf (xdr->buf, attrlen_offset, &attrlen,4 ); + *attrlen_p =cpu_to_be32 (xdr->buf->len - attrlen_offset -XDR_UNIT ); status = nfs_ok; out:
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 591/770 NFSD: Clean up SPLICE_OK in nfsd4_encode_read()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit c738b218a2e5a753a336b4b7fee6720b902c7ace ]
Do the test_bit() once -- this reduces the number of locked-bus operations and makes the function a little easier to read.
--- fs/nfsd/nfs4xdr.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
fs/nfsd/nfs4xdr.c +4 -5
@@ -3991,6 +3991,7 @@ static __be32 nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_read *read) { + bool splice_ok = test_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags);unsigned long maxcount;struct xdr_stream *xdr = resp->xdr;struct file *file;
@@ -4003,11 +4004,10 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr, p =xdr_reserve_space (xdr,8 );/* eof flag and byte count */ if (!p) { -WARN_ON_ONCE (test_bit (RQ_SPLICE_OK , &resp->rqstp->rq_flags)); +WARN_ON_ONCE (splice_ok);return nfserr_resource; } -if (resp->xdr->buf->page_len && -test_bit (RQ_SPLICE_OK , &resp->rqstp->rq_flags)) { +if (resp->xdr->buf->page_len && splice_ok) {WARN_ON_ONCE (1 );return nfserr_serverfault; }
@@ -4016,8 +4016,7 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr, maxcount = min_t(unsigned long, read->rd_length, (xdr->buf->buflen - xdr->buf->len)); -if (file->f_op->splice_read && -test_bit (RQ_SPLICE_OK , &resp->rqstp->rq_flags)) +if (file->f_op->splice_read && splice_ok) nfserr =nfsd4_encode_splice_read (resp, read, file, maxcount);else nfserr =nfsd4_encode_readv (resp, read, file, maxcount);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 592/770 NFSD: Add an nfsd4_read::rd_eof field
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 24c7fb85498eda1d4c6b42cc4886328429814990 ]
Refactor: Make the EOF result available in the entire NFSv4 READ path.
--- fs/nfsd/nfs4xdr.c | 11 +++++------ fs/nfsd/xdr4.h | 5 +++-- 2 files changed, 8 insertions(+), 8 deletions(-)
fs/nfsd/nfs4xdr.c +5 -6
@@ -3890,7 +3890,6 @@ static __be32 nfsd4_encode_splice_read(struct xdr_stream *xdr = resp->xdr;struct xdr_buf *buf = xdr->buf;int status, space_left; -u32 eof;__be32 nfserr;__be32 *p = xdr->p -2 ;
@@ -3899,7 +3898,8 @@ static __be32 nfsd4_encode_splice_read(return nfserr_resource; nfserr =nfsd_splice_read (read->rd_rqstp, read->rd_fhp, - file, read->rd_offset, &maxcount, &eof); + file, read->rd_offset, &maxcount, + &read->rd_eof); read->rd_length = maxcount;if (nfserr) goto out_err;
@@ -3910,7 +3910,7 @@ static __be32 nfsd4_encode_splice_read( goto out_err; } - *(p++) =htonl (eof); + *(p++) =htonl (read->rd_eof); *(p++) =htonl (maxcount); buf->page_len = maxcount;
@@ -3954,7 +3954,6 @@ static __be32 nfsd4_encode_readv(struct nfsd4_compoundres *resp, struct file *file, unsigned long maxcount) {struct xdr_stream *xdr = resp->xdr; -u32 eof;int starting_len = xdr->buf->len -8 ;__be32 nfserr;__be32 tmp;
@@ -3966,7 +3965,7 @@ static __be32 nfsd4_encode_readv(struct nfsd4_compoundres *resp, nfserr =nfsd_readv (resp->rqstp, read->rd_fhp, file, read->rd_offset, resp->rqstp->rq_vec, read->rd_vlen, &maxcount, - &eof); + &read->rd_eof); read->rd_length = maxcount;if (nfserr)return nfserr;
@@ -3974,7 +3973,7 @@ static __be32 nfsd4_encode_readv(struct nfsd4_compoundres *resp,return nfserr_io;xdr_truncate_encode (xdr, starting_len +8 +xdr_align_size (maxcount)); - tmp =htonl (eof); + tmp =htonl (read->rd_eof);write_bytes_to_xdr_buf (xdr->buf, starting_len , &tmp,4 ); tmp =htonl (maxcount);write_bytes_to_xdr_buf (xdr->buf, starting_len +4 , &tmp,4 );
fs/nfsd/xdr4.h +3 -2
@@ -302,9 +302,10 @@ struct nfsd4_read {u32 rd_length;/* request */ int rd_vlen;struct nfsd_file *rd_nf; - +struct svc_rqst *rd_rqstp;/* response */ -struct svc_fh *rd_fhp;/* response */ +struct svc_fh *rd_fhp;/* response */ +u32 rd_eof;/* response */ };struct nfsd4_readdir {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 593/770 NFSD: Optimize nfsd4_encode_readv()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 28d5bc468efe74b790e052f758ce083a5015c665 ]
write_bytes_to_xdr_buf() is pretty expensive to use for inserting an XDR data item that is always 1 XDR_UNIT at an address that is always XDR word-aligned.
Since both the readv and splice read paths encode EOF and maxcount values, move both to a common code path.
--- fs/nfsd/nfs4xdr.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-)
fs/nfsd/nfs4xdr.c +6 -12
@@ -3891,7 +3891,6 @@ static __be32 nfsd4_encode_splice_read(struct xdr_buf *buf = xdr->buf;int status, space_left;__be32 nfserr; -__be32 *p = xdr->p -2 ;/* Make sure there will be room for padding if needed */ if (xdr->end - xdr->p <1 )
@@ -3910,9 +3909,6 @@ static __be32 nfsd4_encode_splice_read( goto out_err; } - *(p++) =htonl (read->rd_eof); - *(p++) =htonl (maxcount); - buf->page_len = maxcount; buf->len += maxcount; xdr->page_ptr += (buf->page_base + maxcount +PAGE_SIZE -1 )
@@ -3973,11 +3969,6 @@ static __be32 nfsd4_encode_readv(struct nfsd4_compoundres *resp,return nfserr_io;xdr_truncate_encode (xdr, starting_len +8 +xdr_align_size (maxcount)); - tmp =htonl (read->rd_eof); -write_bytes_to_xdr_buf (xdr->buf, starting_len , &tmp,4 ); - tmp =htonl (maxcount); -write_bytes_to_xdr_buf (xdr->buf, starting_len +4 , &tmp,4 ); - tmp = xdr_zero; pad = (maxcount&3 ) ?4 - (maxcount&3 ) :0 ; write_bytes_to_xdr_buf(xdr->buf, starting_len + 8 + maxcount,
@@ -4019,11 +4010,14 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr, nfserr =nfsd4_encode_splice_read (resp, read, file, maxcount); else nfserr =nfsd4_encode_readv (resp, read, file, maxcount); - -if (nfserr) +if (nfserr) {xdr_truncate_encode (xdr, starting_len); +return nfserr; + } -return nfserr; + p =xdr_encode_bool (p, read->rd_eof); + *p =cpu_to_be32 (read->rd_length); +return nfs_ok; } static __be32
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 594/770 NFSD: Simplify starting_len
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 071ae99feadfc55979f89287d6ad2c6a315cb46d ]
Clean-up: Now that nfsd4_encode_readv() does not have to encode the EOF or rd_length values, it no longer needs to subtract 8 from @starting_len.
--- fs/nfsd/nfs4xdr.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
fs/nfsd/nfs4xdr.c +4 -5
@@ -3950,7 +3950,7 @@ static __be32 nfsd4_encode_readv(struct nfsd4_compoundres *resp, struct file *file, unsigned long maxcount) {struct xdr_stream *xdr = resp->xdr; -int starting_len = xdr->buf->len -8 ; +unsigned int starting_len = xdr->buf->len;__be32 nfserr;__be32 tmp;int pad;
@@ -3965,14 +3965,13 @@ static __be32 nfsd4_encode_readv(struct nfsd4_compoundres *resp, read->rd_length = maxcount;if (nfserr)return nfserr; -if (svc_encode_result_payload (resp->rqstp, starting_len +8 , maxcount)) +if (svc_encode_result_payload (resp->rqstp, starting_len, maxcount))return nfserr_io; -xdr_truncate_encode (xdr, starting_len +8 +xdr_align_size (maxcount)); +xdr_truncate_encode (xdr, starting_len +xdr_align_size (maxcount)); tmp = xdr_zero; pad = (maxcount&3 ) ?4 - (maxcount&3 ) :0 ; -write_bytes_to_xdr_buf (xdr->buf, starting_len +8 + maxcount, - &tmp, pad); +write_bytes_to_xdr_buf (xdr->buf, starting_len + maxcount, &tmp, pad);return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 595/770 NFSD: Use xdr_pad_size()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 5e64d85c7d0c59cfcd61d899720b8ccfe895d743 ]
Clean up: Use a helper instead of open-coding the calculation of the XDR pad size.
--- fs/nfsd/nfs4xdr.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-)
fs/nfsd/nfs4xdr.c +4 -7
@@ -3951,9 +3951,8 @@ static __be32 nfsd4_encode_readv(struct nfsd4_compoundres *resp, {struct xdr_stream *xdr = resp->xdr;unsigned int starting_len = xdr->buf->len; +__be32 zero = xdr_zero;__be32 nfserr; -__be32 tmp; -int pad; read->rd_vlen =xdr_reserve_space_vec (xdr, resp->rqstp->rq_vec, maxcount);if (read->rd_vlen <0 )
@@ -3969,11 +3968,9 @@ static __be32 nfsd4_encode_readv(struct nfsd4_compoundres *resp,return nfserr_io;xdr_truncate_encode (xdr, starting_len +xdr_align_size (maxcount)); - tmp = xdr_zero; - pad = (maxcount&3 ) ?4 - (maxcount&3 ) :0 ; -write_bytes_to_xdr_buf (xdr->buf, starting_len + maxcount, &tmp, pad); -return 0 ; - +write_bytes_to_xdr_buf (xdr->buf, starting_len + maxcount, &zero, +xdr_pad_size (maxcount)); +return nfs_ok; } static __be32
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 596/770 NFSD: Clean up nfsd4_encode_readlink()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 99b002a1fa00d90e66357315757e7277447ce973 ]
Similar changes to nfsd4_encode_readv(), all bundled into a single patch.
--- fs/nfsd/nfs4xdr.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-)
fs/nfsd/nfs4xdr.c +9 -15
@@ -4019,16 +4019,13 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,static __be32 nfsd4_encode_readlink (struct nfsd4_compoundres *resp,__be32 nfserr,struct nfsd4_readlink *readlink) { -int maxcount; -__be32 wire_count; -int zero =0 ; +__be32 *p, *maxcount_p, zero = xdr_zero;struct xdr_stream *xdr = resp->xdr;int length_offset = xdr->buf->len; -int status; -__be32 *p; +int maxcount, status; - p =xdr_reserve_space (xdr,4 ); -if (!p) + maxcount_p =xdr_reserve_space (xdr,XDR_UNIT ); +if (!maxcount_p)return nfserr_resource; maxcount =PAGE_SIZE ;
@@ -4053,14 +4050,11 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd nfserr =nfserrno (status); goto out_err; } - - wire_count =htonl (maxcount); -write_bytes_to_xdr_buf (xdr->buf, length_offset, &wire_count,4 ); -xdr_truncate_encode (xdr, length_offset +4 +ALIGN (maxcount,4 )); -if (maxcount &3 ) -write_bytes_to_xdr_buf (xdr->buf, length_offset +4 + maxcount, - &zero,4 - (maxcount&3 )); -return 0 ; + *maxcount_p =cpu_to_be32 (maxcount); +xdr_truncate_encode (xdr, length_offset +4 +xdr_align_size (maxcount)); +write_bytes_to_xdr_buf (xdr->buf, length_offset +4 + maxcount, &zero, +xdr_pad_size (maxcount)); +return nfs_ok; out_err:xdr_truncate_encode (xdr, length_offset);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 597/770 NFSD: Fix strncpy() fortify warning
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 5304877936c0a67e1a01464d113bae4c81eacdb6 ]
In function ‘strncpy’,
inlined from ‘nfsd4_ssc_setup_dul’ at /home/cel/src/linux/manet/fs/nfsd/nfs4proc.c:1392:3,
inlined from ‘nfsd4_interssc_connect’ at /home/cel/src/linux/manet/fs/nfsd/nfs4proc.c:1489:11:/home/cel/src/linux/manet/include/linux/fortify-string.h:52:33: warning: ‘__builtin_strncpy’ specified bound 63 equals destination size [-Wstringop-truncation]
52 | #define __underlying_strncpy __builtin_strncpy
| ^
/home/cel/src/linux/manet/include/linux/fortify-string.h:89:16: note: in expansion of macro ‘__underlying_strncpy’
89 | return __underlying_strncpy(p, q, size);
| ^~~~~~~~~~~~~~~~~~~~--- fs/nfsd/nfs4proc.c | 2 +- include/linux/nfs_ssc.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
fs/nfsd/nfs4proc.c +1 -1
@@ -1391,7 +1391,7 @@ static __be32 nfsd4_ssc_setup_dul(struct nfsd_net *nn, char *ipaddr,return 0 ; }if (work) { -strncpy (work->nsui_ipaddr, ipaddr,sizeof (work->nsui_ipaddr)); +strlcpy (work->nsui_ipaddr, ipaddr,sizeof (work->nsui_ipaddr) -1 );refcount_set (&work->nsui_refcnt,2 ); work->nsui_busy = true;list_add_tail (&work->nsui_list, &nn->nfsd_ssc_mount_list);
include/linux/nfs_ssc.h +1 -1
@@ -64,7 +64,7 @@ struct nfsd4_ssc_umount_item {refcount_t nsui_refcnt;unsigned long nsui_expire;struct vfsmount *nsui_vfsmount; - char nsui_ipaddr[RPC_MAX_ADDRBUFLEN]; + char nsui_ipaddr[RPC_MAX_ADDRBUFLEN + 1]; };#endif
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 598/770 NFSD: nfserrno(-ENOMEM) is nfserr_jukebox
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit bb4d842722b84a2731257054b6405f2d866fc5f3 ]
--- fs/nfsd/nfs4xdr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/nfsd/nfs4xdr.c +2 -2
@@ -1810,7 +1810,7 @@ nfsd4_decode_test_stateid(struct nfsd4_compoundargs *argp, struct nfsd4_test_stafor (i =0 ; i < test_stateid->ts_num_ids; i++) { stateid =svcxdr_tmpalloc (argp,sizeof (*stateid));if (!stateid) -return nfserrno (-ENOMEM );/* XXX: not jukebox? */ +return nfserr_jukebox;INIT_LIST_HEAD (&stateid->ts_id_list);list_add_tail (&stateid->ts_id_list, &test_stateid->ts_stateid_list); status =nfsd4_decode_stateid4 (argp, &stateid->ts_id_stateid);
@@ -1933,7 +1933,7 @@ nfsd4_decode_copy(struct nfsd4_compoundargs *argp, struct nfsd4_copy *copy) ns_dummy =kmalloc (sizeof (struct nl4_server ),GFP_KERNEL );if (ns_dummy ==NULL ) -return nfserrno (-ENOMEM );/* XXX: jukebox? */ +return nfserr_jukebox;for (i =0 ; i < count -1 ; i++) { status =nfsd4_decode_nl4_server (argp, ns_dummy);if (status) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 599/770 NFSD: Shrink size of struct nfsd4_copy_notify
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 09426ef2a64ee189ca1e3298f1e874842dbf35ea ]
struct nfsd4_copy_notify is part of struct nfsd4_op, which resides in an 8-element array.
sizeof(struct nfsd4_op):
Before: /* size: 2208, cachelines: 35, members: 5 */ After: /* size: 1696, cachelines: 27, members: 5 */
--- fs/nfsd/nfs4proc.c | 4 ++-- fs/nfsd/nfs4xdr.c | 12 ++++++++++-- fs/nfsd/xdr4.h | 4 ++-- 3 files changed, 14 insertions(+), 6 deletions(-)
fs/nfsd/nfs4proc.c +2 -2
@@ -1945,9 +1945,9 @@ nfsd4_copy_notify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,/* For now, only return one server address in cpn_src, the * address used by the client to connect to this server. */ - cn->cpn_src.nl4_type =NL4_NETADDR ; + cn->cpn_src->nl4_type =NL4_NETADDR ; status =nfsd4_set_netaddr ((struct sockaddr *)&rqstp->rq_daddr, - &cn->cpn_src.u.nl4_addr); + &cn->cpn_src->u.nl4_addr);WARN_ON_ONCE (status);if (status) {nfs4_put_cpntf_state (nn, cps);
fs/nfsd/nfs4xdr.c +10 -2
@@ -1952,10 +1952,17 @@ nfsd4_decode_copy_notify(struct nfsd4_compoundargs *argp, {__be32 status; + cn->cpn_src =svcxdr_tmpalloc (argp,sizeof (*cn->cpn_src)); +if (cn->cpn_src ==NULL ) +return nfserr_jukebox; + cn->cpn_dst =svcxdr_tmpalloc (argp,sizeof (*cn->cpn_dst)); +if (cn->cpn_dst ==NULL ) +return nfserr_jukebox; + status =nfsd4_decode_stateid4 (argp, &cn->cpn_src_stateid);if (status)return status; -return nfsd4_decode_nl4_server (argp, &cn->cpn_dst); +return nfsd4_decode_nl4_server (argp, cn->cpn_dst); } static __be32
@@ -4906,7 +4913,8 @@ nfsd4_encode_copy_notify(struct nfsd4_compoundres *resp, __be32 nfserr, *p++ =cpu_to_be32 (1 ); -return nfsd42_encode_nl4_server (resp, &cn->cpn_src); + nfserr =nfsd42_encode_nl4_server (resp, cn->cpn_src); +return nfserr; } static __be32
fs/nfsd/xdr4.h +2 -2
@@ -595,13 +595,13 @@ struct nfsd4_offload_status {struct nfsd4_copy_notify {/* request */ stateid_t cpn_src_stateid; -struct nl4_server cpn_dst; +struct nl4_server *cpn_dst;/* response */ stateid_t cpn_cnr_stateid;u64 cpn_sec;u32 cpn_nsec; -struct nl4_server cpn_src; +struct nl4_server *cpn_src; };struct nfsd4_op {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 600/770 NFSD: Shrink size of struct nfsd4_copy
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 87689df694916c40e8e6c179ab1c8710f65cb6c6 ]
struct nfsd4_copy is part of struct nfsd4_op, which resides in an 8-element array.
sizeof(struct nfsd4_op):
Before: /* size: 1696, cachelines: 27, members: 5 */ After: /* size: 672, cachelines: 11, members: 5 */
--- fs/nfsd/nfs4proc.c | 8 ++++++-- fs/nfsd/nfs4xdr.c | 5 ++++- fs/nfsd/xdr4.h | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-)
fs/nfsd/nfs4proc.c +6 -2
@@ -1291,6 +1291,7 @@ void nfs4_put_copy(struct nfsd4_copy *copy) {if (!refcount_dec_and_test (©->refcount))return ; +kfree (copy->cp_src);kfree (copy); }
@@ -1544,7 +1545,7 @@ nfsd4_setup_inter_ssc(struct svc_rqst *rqstp,if (status) goto out; - status =nfsd4_interssc_connect (©->cp_src, rqstp, mount); + status =nfsd4_interssc_connect (copy->cp_src, rqstp, mount);if (status) goto out;
@@ -1751,7 +1752,7 @@ static void dup_copy_fields(struct nfsd4_copy *src, struct nfsd4_copy *dst) dst->nf_src =nfsd_file_get (src->nf_src);memcpy (&dst->cp_stateid, &src->cp_stateid,sizeof (src->cp_stateid)); -memcpy (&dst->cp_src, &src->cp_src,sizeof (struct nl4_server )); +memcpy (dst->cp_src, src->cp_src,sizeof (struct nl4_server ));memcpy (&dst->stateid, &src->stateid,sizeof (src->stateid));memcpy (&dst->c_fh, &src->c_fh,sizeof (src->c_fh)); dst->ss_mnt = src->ss_mnt;
@@ -1845,6 +1846,9 @@ nfsd4_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, async_copy =kzalloc (sizeof (struct nfsd4_copy ),GFP_KERNEL );if (!async_copy) goto out_err; + async_copy->cp_src =kmalloc (sizeof (*async_copy->cp_src),GFP_KERNEL ); +if (!async_copy->cp_src) + goto out_err;if (!nfs4_init_copy_state (nn, copy)) goto out_err;refcount_set (&async_copy->refcount,1 );
fs/nfsd/nfs4xdr.c +4 -1
@@ -1920,6 +1920,9 @@ nfsd4_decode_copy(struct nfsd4_compoundargs *argp, struct nfsd4_copy *copy)if (xdr_stream_decode_u32 (argp->xdr, &count) <0 )return nfserr_bad_xdr; + copy->cp_src =svcxdr_tmpalloc (argp,sizeof (*copy->cp_src)); +if (copy->cp_src ==NULL ) +return nfserr_jukebox; copy->cp_intra = false;if (count ==0 ) {/* intra-server copy */ copy->cp_intra = true;
@@ -1927,7 +1930,7 @@ nfsd4_decode_copy(struct nfsd4_compoundargs *argp, struct nfsd4_copy *copy) }/* decode all the supplied server addresses but use only the first */ - status =nfsd4_decode_nl4_server (argp, ©->cp_src); + status =nfsd4_decode_nl4_server (argp, copy->cp_src);if (status)return status;
fs/nfsd/xdr4.h +1 -1
@@ -540,7 +540,7 @@ struct nfsd4_copy {u64 cp_src_pos;u64 cp_dst_pos;u64 cp_count; -struct nl4_server cp_src; +struct nl4_server *cp_src;bool cp_intra;/* both */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 601/770 NFSD: Reorder the fields in struct nfsd4_op
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit d314309425ad5dc1b6facdb2d456580fb5fa5e3a ]
Pack the fields to reduce the size of struct nfsd4_op, which is used an array in struct nfsd4_compoundargs.
sizeof(struct nfsd4_op):
Before: /* size: 672, cachelines: 11, members: 5 */ After: /* size: 640, cachelines: 10, members: 5 */
--- fs/nfsd/xdr4.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/nfsd/xdr4.h +2 -2
@@ -606,8 +606,9 @@ struct nfsd4_copy_notify {struct nfsd4_op {u32 opnum; -const struct nfsd4_operation * opdesc;__be32 status; +const struct nfsd4_operation *opdesc; +struct nfs4_replay *replay;union nfsd4_op_u {struct nfsd4_access access;struct nfsd4_close close;
@@ -671,7 +672,6 @@ struct nfsd4_op {struct nfsd4_listxattrs listxattrs;struct nfsd4_removexattr removexattr; } u; -struct nfs4_replay * replay; };bool nfsd4_cache_this_op (struct nfsd4_op *);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 602/770 NFSD: Make nfs4_put_copy() static
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 8ea6e2c90bb0eb74a595a12e23a1dff9abbc760a ]
Clean up: All call sites are in fs/nfsd/nfs4proc.c.
--- fs/nfsd/nfs4proc.c | 2 +- fs/nfsd/state.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-)
fs/nfsd/nfs4proc.c +1 -1
@@ -1287,7 +1287,7 @@ nfsd4_clone(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,return status; } -void nfs4_put_copy (struct nfsd4_copy *copy) +static void nfs4_put_copy (struct nfsd4_copy *copy) {if (!refcount_dec_and_test (©->refcount))return ;
fs/nfsd/state.h +0 -1
@@ -703,7 +703,6 @@ extern struct nfs4_client_reclaim *nfs4_client_to_reclaim(struct xdr_netobj nameextern bool nfs4_has_reclaimed_state (struct xdr_netobj name,struct nfsd_net *nn);void put_nfs4_file (struct nfs4_file *fi); -extern void nfs4_put_copy (struct nfsd4_copy *copy);extern struct nfsd4_copy *find_async_copy (struct nfs4_client *clp,stateid_t *staetid); extern void nfs4_put_cpntf_state(struct nfsd_net *nn,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 603/770 NFSD: Replace boolean fields in struct nfsd4_copy
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 1913cdf56cb5bfbc8170873728d13598cbecda23 ]
Clean up: saves 8 bytes, and we can replace check_and_set_stop_copy() with an atomic bitop.
--- fs/nfsd/nfs4proc.c | 49 +++++++++++++++++----------------------------- fs/nfsd/nfs4xdr.c | 12 ++++++------ fs/nfsd/xdr4.h | 33 ++++++++++++++++++++++++++----- 3 files changed, 52 insertions(+), 42 deletions(-)
fs/nfsd/nfs4proc.c +18 -31
@@ -1295,23 +1295,9 @@ static void nfs4_put_copy(struct nfsd4_copy *copy)kfree (copy); } -static bool -check_and_set_stop_copy (struct nfsd4_copy *copy) -{ -bool value; - -spin_lock (©->cp_clp->async_lock); - value = copy->stopped; -if (!copy->stopped) - copy->stopped = true; -spin_unlock (©->cp_clp->async_lock); -return value; -} -static void nfsd4_stop_copy (struct nfsd4_copy *copy) { -/* only 1 thread should stop the copy */ -if (!check_and_set_stop_copy (copy)) +if (!test_and_set_bit (NFSD4_COPY_F_STOPPED , ©->cp_flags))kthread_stop (copy->copy_task);nfs4_put_copy (copy); }
@@ -1668,8 +1654,9 @@ static const struct nfsd4_callback_ops nfsd4_cb_offload_ops = {static void nfsd4_init_copy_res (struct nfsd4_copy *copy,bool sync) { copy->cp_res.wr_stable_how = - copy->committed ?NFS_FILE_SYNC :NFS_UNSTABLE ; - copy->cp_synchronous = sync; +test_bit (NFSD4_COPY_F_COMMITTED , ©->cp_flags) ? +NFS_FILE_SYNC :NFS_UNSTABLE ; +nfsd4_copy_set_sync (copy, sync);gen_boot_verifier (©->cp_res.wr_verifier, copy->cp_clp->net); }
@@ -1698,16 +1685,16 @@ static ssize_t _nfsd_copy_file_range(struct nfsd4_copy *copy) copy->cp_res.wr_bytes_written += bytes_copied; src_pos += bytes_copied; dst_pos += bytes_copied; - }while (bytes_total >0 && !copy->cp_synchronous); + }while (bytes_total >0 &&nfsd4_copy_is_async (copy));/* for a non-zero asynchronous copy do a commit of data */ -if (!copy->cp_synchronous && copy->cp_res.wr_bytes_written >0 ) { +if (nfsd4_copy_is_async (copy) && copy->cp_res.wr_bytes_written >0 ) { since =READ_ONCE (dst->f_wb_err); status =vfs_fsync_range (dst, copy->cp_dst_pos, copy->cp_res.wr_bytes_written,0 );if (!status) status =filemap_check_wb_err (dst->f_mapping, since);if (!status) - copy->committed = true; +set_bit (NFSD4_COPY_F_COMMITTED , ©->cp_flags); }return bytes_copied; }
@@ -1728,7 +1715,7 @@ static __be32 nfsd4_do_copy(struct nfsd4_copy *copy, bool sync) status = nfs_ok; } -if (!copy->cp_intra)/* Inter server SSC */ +if (nfsd4_ssc_is_inter (copy))nfsd4_cleanup_inter_ssc (copy->ss_mnt, copy->nf_src, copy->nf_dst);else
@@ -1742,13 +1729,13 @@ static void dup_copy_fields(struct nfsd4_copy *src, struct nfsd4_copy *dst) dst->cp_src_pos = src->cp_src_pos; dst->cp_dst_pos = src->cp_dst_pos; dst->cp_count = src->cp_count; - dst->cp_synchronous = src->cp_synchronous; + dst->cp_flags = src->cp_flags;memcpy (&dst->cp_res, &src->cp_res,sizeof (src->cp_res));memcpy (&dst->fh, &src->fh,sizeof (src->fh)); dst->cp_clp = src->cp_clp; dst->nf_dst =nfsd_file_get (src->nf_dst); - dst->cp_intra = src->cp_intra; -if (src->cp_intra)/* for inter, file_src doesn't exist yet */ +/* for inter, nf_src doesn't exist yet */ +if (!nfsd4_ssc_is_inter (src)) dst->nf_src =nfsd_file_get (src->nf_src);memcpy (&dst->cp_stateid, &src->cp_stateid,sizeof (src->cp_stateid));
@@ -1762,7 +1749,7 @@ static void cleanup_async_copy(struct nfsd4_copy *copy) {nfs4_free_copy_state (copy);nfsd_file_put (copy->nf_dst); -if (copy->cp_intra) +if (!nfsd4_ssc_is_inter (copy))nfsd_file_put (copy->nf_src);spin_lock (©->cp_clp->async_lock);list_del (©->copies);
@@ -1775,7 +1762,7 @@ static int nfsd4_do_async_copy(void *data)struct nfsd4_copy *copy = (struct nfsd4_copy *)data;struct nfsd4_copy *cb_copy; -if (!copy->cp_intra) {/* Inter server SSC */ +if (nfsd4_ssc_is_inter (copy)) { copy->nf_src =kzalloc (sizeof (struct nfsd_file ),GFP_KERNEL );if (!copy->nf_src) { copy->nfserr = nfserr_serverfault;
@@ -1807,7 +1794,7 @@ static int nfsd4_do_async_copy(void *data) ©->fh, copy->cp_count, copy->nfserr);nfsd4_run_cb (&cb_copy->cp_cb); out: -if (!copy->cp_intra) +if (nfsd4_ssc_is_inter (copy))kfree (copy->nf_src);cleanup_async_copy (copy);return 0 ;
@@ -1821,8 +1808,8 @@ nfsd4_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,__be32 status;struct nfsd4_copy *async_copy =NULL ; -if (!copy->cp_intra) {/* Inter server SSC */ -if (!inter_copy_offload_enable || copy->cp_synchronous) { +if (nfsd4_ssc_is_inter (copy)) { +if (!inter_copy_offload_enable ||nfsd4_copy_is_sync (copy)) { status = nfserr_notsupp; goto out; }
@@ -1839,7 +1826,7 @@ nfsd4_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, copy->cp_clp = cstate->clp;memcpy (©->fh, &cstate->current_fh.fh_handle,sizeof (struct knfsd_fh )); -if (!copy->cp_synchronous) { +if (nfsd4_copy_is_async (copy)) {struct nfsd_net *nn =net_generic (SVC_NET (rqstp), nfsd_net_id); status =nfserrno (-ENOMEM );
@@ -2605,7 +2592,7 @@ check_if_stalefh_allowed(struct nfsd4_compoundargs *args)return ; } putfh = (struct nfsd4_putfh *)&saved_op->u; -if (!copy->cp_intra) +if (nfsd4_ssc_is_inter (copy)) putfh->no_verify = true; } }
fs/nfsd/nfs4xdr.c +6 -6
@@ -1896,8 +1896,8 @@ static __be32 nfsd4_decode_nl4_server(struct nfsd4_compoundargs *argp,static __be32 nfsd4_decode_copy (struct nfsd4_compoundargs *argp,struct nfsd4_copy *copy) { +u32 consecutive, i, count, sync;struct nl4_server *ns_dummy; -u32 consecutive, i, count;__be32 status; status =nfsd4_decode_stateid4 (argp, ©->cp_src_stateid);
@@ -1915,17 +1915,17 @@ nfsd4_decode_copy(struct nfsd4_compoundargs *argp, struct nfsd4_copy *copy)/* ca_consecutive: we always do consecutive copies */ if (xdr_stream_decode_u32 (argp->xdr, &consecutive) <0 )return nfserr_bad_xdr; -if (xdr_stream_decode_u32 (argp->xdr, ©->cp_synchronous) <0 ) +if (xdr_stream_decode_bool (argp->xdr, &sync) <0 )return nfserr_bad_xdr; +nfsd4_copy_set_sync (copy, sync);if (xdr_stream_decode_u32 (argp->xdr, &count) <0 )return nfserr_bad_xdr; copy->cp_src =svcxdr_tmpalloc (argp,sizeof (*copy->cp_src));if (copy->cp_src ==NULL )return nfserr_jukebox; - copy->cp_intra = false;if (count ==0 ) {/* intra-server copy */ - copy->cp_intra = true; +__set_bit (NFSD4_COPY_F_INTRA , ©->cp_flags);return nfs_ok; }
@@ -4712,13 +4712,13 @@ nfsd4_encode_copy(struct nfsd4_compoundres *resp, __be32 nfserr,__be32 *p; nfserr =nfsd42_encode_write_res (resp, ©->cp_res, - !!copy->cp_synchronous); +nfsd4_copy_is_sync (copy));if (nfserr)return nfserr; p =xdr_reserve_space (resp->xdr,4 +4 ); *p++ = xdr_one;/* cr_consecutive */ - *p++ =cpu_to_be32 (copy->cp_synchronous); + *p =nfsd4_copy_is_sync (copy) ? xdr_one : xdr_zero;return 0 ; }
fs/nfsd/xdr4.h +28 -5
@@ -541,10 +541,12 @@ struct nfsd4_copy {u64 cp_dst_pos;u64 cp_count;struct nl4_server *cp_src; -bool cp_intra; -/* both */ -u32 cp_synchronous; +unsigned long cp_flags; +#define NFSD4_COPY_F_STOPPED (0) +#define NFSD4_COPY_F_INTRA (1) +#define NFSD4_COPY_F_SYNCHRONOUS (2) +#define NFSD4_COPY_F_COMMITTED (3)/* response */ struct nfsd42_write_res cp_res;
@@ -564,14 +566,35 @@ struct nfsd4_copy {struct list_head copies;struct task_struct *copy_task;refcount_t refcount; -bool stopped;struct vfsmount *ss_mnt;struct nfs_fh c_fh;nfs4_stateid stateid; -bool committed; }; +static inline void nfsd4_copy_set_sync (struct nfsd4_copy *copy,bool sync) +{ +if (sync) +set_bit (NFSD4_COPY_F_SYNCHRONOUS , ©->cp_flags); +else +clear_bit (NFSD4_COPY_F_SYNCHRONOUS , ©->cp_flags); +} + +static inline bool nfsd4_copy_is_sync (const struct nfsd4_copy *copy) +{ +return test_bit (NFSD4_COPY_F_SYNCHRONOUS , ©->cp_flags); +} + +static inline bool nfsd4_copy_is_async (const struct nfsd4_copy *copy) +{ +return !test_bit (NFSD4_COPY_F_SYNCHRONOUS , ©->cp_flags); +} + +static inline bool nfsd4_ssc_is_inter (const struct nfsd4_copy *copy) +{ +return !test_bit (NFSD4_COPY_F_INTRA , ©->cp_flags); +} +struct nfsd4_seek {/* request */ stateid_t seek_stateid;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 604/770 NFSD: Refactor nfsd4_cleanup_inter_ssc() (1/2)
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 24d796ea383b8a4c8234e06d1b14bbcd371192ea ]
The @src parameter is sometimes a pointer to a struct nfsd_file and sometimes a pointer to struct file hiding in a phony struct nfsd_file. Refactor nfsd4_cleanup_inter_ssc() so the @src parameter is always an explicit struct file.
--- fs/nfsd/nfs4proc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
fs/nfsd/nfs4proc.c +5 -5
@@ -1549,7 +1549,7 @@ nfsd4_setup_inter_ssc(struct svc_rqst *rqstp, }static void -nfsd4_cleanup_inter_ssc (struct vfsmount *ss_mnt,struct nfsd_file *src, +nfsd4_cleanup_inter_ssc (struct vfsmount *ss_mnt,struct file *filp,struct nfsd_file *dst) {bool found = false;
@@ -1558,9 +1558,9 @@ nfsd4_cleanup_inter_ssc(struct vfsmount *ss_mnt, struct nfsd_file *src,struct nfsd4_ssc_umount_item *ni =NULL ;struct nfsd_net *nn =net_generic (dst->nf_net, nfsd_net_id); -nfs42_ssc_close (src->nf_file); +nfs42_ssc_close (filp);nfsd_file_put (dst); -fput (src->nf_file); +fput (filp);if (!nn) {mntput (ss_mnt);
@@ -1603,7 +1603,7 @@ nfsd4_setup_inter_ssc(struct svc_rqst *rqstp, }static void -nfsd4_cleanup_inter_ssc (struct vfsmount *ss_mnt,struct nfsd_file *src, +nfsd4_cleanup_inter_ssc (struct vfsmount *ss_mnt,struct file *filp,struct nfsd_file *dst) { }
@@ -1716,7 +1716,7 @@ static __be32 nfsd4_do_copy(struct nfsd4_copy *copy, bool sync) }if (nfsd4_ssc_is_inter (copy)) -nfsd4_cleanup_inter_ssc (copy->ss_mnt, copy->nf_src, +nfsd4_cleanup_inter_ssc (copy->ss_mnt, copy->nf_src->nf_file, copy->nf_dst);else nfsd4_cleanup_intra_ssc (copy->nf_src, copy->nf_dst);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 605/770 NFSD: Refactor nfsd4_cleanup_inter_ssc() (2/2)
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 478ed7b10d875da2743d1a22822b9f8a82df8f12 ]
Move the nfsd4_cleanup_*() call sites out of nfsd4_do_copy(). A subsequent patch will modify one of the new call sites to avoid the need to manufacture the phony struct nfsd_file.
--- fs/nfsd/nfs4proc.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-)
fs/nfsd/nfs4proc.c +7 -8
@@ -1714,13 +1714,6 @@ static __be32 nfsd4_do_copy(struct nfsd4_copy *copy, bool sync)nfsd4_init_copy_res (copy, sync); status = nfs_ok; } - -if (nfsd4_ssc_is_inter (copy)) -nfsd4_cleanup_inter_ssc (copy->ss_mnt, copy->nf_src->nf_file, - copy->nf_dst); -else -nfsd4_cleanup_intra_ssc (copy->nf_src, copy->nf_dst); -return status; }
@@ -1776,9 +1769,14 @@ static int nfsd4_do_async_copy(void *data)/* ss_mnt will be unmounted by the laundromat */ goto do_callback; } + copy->nfserr =nfsd4_do_copy (copy,0 ); +nfsd4_cleanup_inter_ssc (copy->ss_mnt, copy->nf_src->nf_file, + copy->nf_dst); + }else { + copy->nfserr =nfsd4_do_copy (copy,0 ); +nfsd4_cleanup_intra_ssc (copy->nf_src, copy->nf_dst); } - copy->nfserr =nfsd4_do_copy (copy,0 ); do_callback: cb_copy =kzalloc (sizeof (struct nfsd4_copy ),GFP_KERNEL );if (!cb_copy)
@@ -1854,6 +1852,7 @@ nfsd4_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, status = nfs_ok; }else { status =nfsd4_do_copy (copy,1 ); +nfsd4_cleanup_intra_ssc (copy->nf_src, copy->nf_dst); } out:return status;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 606/770 NFSD: Refactor nfsd4_do_copy()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 3b7bf5933cada732783554edf0dc61283551c6cf ]
Refactor: Now that nfsd4_do_copy() no longer calls the cleanup helpers, plumb the use of struct file pointers all the way down to _nfsd_copy_file_range().
--- fs/nfsd/nfs4proc.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-)
fs/nfsd/nfs4proc.c +14 -8
@@ -1660,10 +1660,10 @@ static void nfsd4_init_copy_res(struct nfsd4_copy *copy, bool sync)gen_boot_verifier (©->cp_res.wr_verifier, copy->cp_clp->net); } -static ssize_t _nfsd_copy_file_range (struct nfsd4_copy *copy) +static ssize_t _nfsd_copy_file_range (struct nfsd4_copy *copy, +struct file *dst, +struct file *src) { -struct file *dst = copy->nf_dst->nf_file; -struct file *src = copy->nf_src->nf_file;errseq_t since;ssize_t bytes_copied =0 ;u64 bytes_total = copy->cp_count;
@@ -1699,12 +1699,15 @@ static ssize_t _nfsd_copy_file_range(struct nfsd4_copy *copy)return bytes_copied; } -static __be32 nfsd4_do_copy (struct nfsd4_copy *copy,bool sync) +static __be32 nfsd4_do_copy (struct nfsd4_copy *copy, +struct file *src,struct file *dst, +bool sync) {__be32 status;ssize_t bytes; - bytes =_nfsd_copy_file_range (copy); + bytes =_nfsd_copy_file_range (copy, dst, src); +/* for async copy, we ignore the error, client can always retry * to get the error */
@@ -1769,11 +1772,13 @@ static int nfsd4_do_async_copy(void *data)/* ss_mnt will be unmounted by the laundromat */ goto do_callback; } - copy->nfserr =nfsd4_do_copy (copy,0 ); + copy->nfserr =nfsd4_do_copy (copy, copy->nf_src->nf_file, + copy->nf_dst->nf_file, false);nfsd4_cleanup_inter_ssc (copy->ss_mnt, copy->nf_src->nf_file, copy->nf_dst); }else { - copy->nfserr =nfsd4_do_copy (copy,0 ); + copy->nfserr =nfsd4_do_copy (copy, copy->nf_src->nf_file, + copy->nf_dst->nf_file, false);nfsd4_cleanup_intra_ssc (copy->nf_src, copy->nf_dst); }
@@ -1851,7 +1856,8 @@ nfsd4_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,wake_up_process (async_copy->copy_task); status = nfs_ok; }else { - status =nfsd4_do_copy (copy,1 ); + status =nfsd4_do_copy (copy, copy->nf_src->nf_file, + copy->nf_dst->nf_file, true);nfsd4_cleanup_intra_ssc (copy->nf_src, copy->nf_dst); } out:
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 607/770 NFSD: Remove kmalloc from nfsd4_do_async_copy()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit ad1e46c9b07b13659635ee5405f83ad0df143116 ]
Instead of manufacturing a phony struct nfsd_file, pass the struct file returned by nfs42_ssc_open() directly to nfsd4_do_copy().
--- fs/nfsd/nfs4proc.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-)
fs/nfsd/nfs4proc.c +14 -14
@@ -1753,29 +1753,31 @@ static void cleanup_async_copy(struct nfsd4_copy *copy)nfs4_put_copy (copy); } +/** +* nfsd4_do_async_copy - kthread function for background server-side COPY +* @data: arguments for COPY operation +* +* Return values: +* %0: Copy operation is done. +*/ static int nfsd4_do_async_copy (void *data) {struct nfsd4_copy *copy = (struct nfsd4_copy *)data;struct nfsd4_copy *cb_copy;if (nfsd4_ssc_is_inter (copy)) { - copy->nf_src =kzalloc (sizeof (struct nfsd_file ),GFP_KERNEL ); -if (!copy->nf_src) { - copy->nfserr = nfserr_serverfault; -/* ss_mnt will be unmounted by the laundromat */ - goto do_callback; - } - copy->nf_src->nf_file =nfs42_ssc_open (copy->ss_mnt, ©->c_fh, - ©->stateid); -if (IS_ERR (copy->nf_src->nf_file)) { +struct file *filp; + + filp =nfs42_ssc_open (copy->ss_mnt, ©->c_fh, + ©->stateid); +if (IS_ERR (filp)) { copy->nfserr = nfserr_offload_denied;/* ss_mnt will be unmounted by the laundromat */ goto do_callback; } - copy->nfserr =nfsd4_do_copy (copy, copy->nf_src->nf_file, + copy->nfserr =nfsd4_do_copy (copy, filp, copy->nf_dst->nf_file, false); -nfsd4_cleanup_inter_ssc (copy->ss_mnt, copy->nf_src->nf_file, - copy->nf_dst); +nfsd4_cleanup_inter_ssc (copy->ss_mnt, filp, copy->nf_dst); }else { copy->nfserr =nfsd4_do_copy (copy, copy->nf_src->nf_file, copy->nf_dst->nf_file, false);
@@ -1797,8 +1799,6 @@ static int nfsd4_do_async_copy(void *data) ©->fh, copy->cp_count, copy->nfserr);nfsd4_run_cb (&cb_copy->cp_cb); out: -if (nfsd4_ssc_is_inter (copy)) -kfree (copy->nf_src);cleanup_async_copy (copy);return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 608/770 NFSD: Add nfsd4_send_cb_offload()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit e72f9bc006c08841c46d27747a4debc747a8fe13 ]
Refactor for legibility.
--- fs/nfsd/nfs4proc.c | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-)
fs/nfsd/nfs4proc.c +22 -15
@@ -1753,6 +1753,27 @@ static void cleanup_async_copy(struct nfsd4_copy *copy)nfs4_put_copy (copy); } +static void nfsd4_send_cb_offload (struct nfsd4_copy *copy) +{ +struct nfsd4_copy *cb_copy; + + cb_copy =kzalloc (sizeof (struct nfsd4_copy ),GFP_KERNEL ); +if (!cb_copy) +return ; + +refcount_set (&cb_copy->refcount,1 ); +memcpy (&cb_copy->cp_res, ©->cp_res,sizeof (copy->cp_res)); + cb_copy->cp_clp = copy->cp_clp; + cb_copy->nfserr = copy->nfserr; +memcpy (&cb_copy->fh, ©->fh,sizeof (copy->fh)); + +nfsd4_init_cb (&cb_copy->cp_cb, cb_copy->cp_clp, + &nfsd4_cb_offload_ops,NFSPROC4_CLNT_CB_OFFLOAD ); +trace_nfsd_cb_offload (copy->cp_clp, ©->cp_res.cb_stateid, + ©->fh, copy->cp_count, copy->nfserr); +nfsd4_run_cb (&cb_copy->cp_cb); +} +/** * nfsd4_do_async_copy - kthread function for background server-side COPY * @data: arguments for COPY operation
@@ -1763,7 +1784,6 @@ static void cleanup_async_copy(struct nfsd4_copy *copy)static int nfsd4_do_async_copy (void *data) {struct nfsd4_copy *copy = (struct nfsd4_copy *)data; -struct nfsd4_copy *cb_copy;if (nfsd4_ssc_is_inter (copy)) {struct file *filp;
@@ -1785,20 +1805,7 @@ static int nfsd4_do_async_copy(void *data) } do_callback: - cb_copy =kzalloc (sizeof (struct nfsd4_copy ),GFP_KERNEL ); -if (!cb_copy) - goto out; -refcount_set (&cb_copy->refcount,1 ); -memcpy (&cb_copy->cp_res, ©->cp_res,sizeof (copy->cp_res)); - cb_copy->cp_clp = copy->cp_clp; - cb_copy->nfserr = copy->nfserr; -memcpy (&cb_copy->fh, ©->fh,sizeof (copy->fh)); -nfsd4_init_cb (&cb_copy->cp_cb, cb_copy->cp_clp, - &nfsd4_cb_offload_ops,NFSPROC4_CLNT_CB_OFFLOAD ); -trace_nfsd_cb_offload (copy->cp_clp, ©->cp_res.cb_stateid, - ©->fh, copy->cp_count, copy->nfserr); -nfsd4_run_cb (&cb_copy->cp_cb); -out: +nfsd4_send_cb_offload (copy);cleanup_async_copy (copy);return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 609/770 NFSD: Move copy offload callback arguments into a separate structure
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit a11ada99ce93a79393dc6683d22f7915748c8f6b ]
Refactor so that CB_OFFLOAD arguments can be passed without allocating a whole struct nfsd4_copy object. On my system (x86_64) this removes another 96 bytes from struct nfsd4_copy.
--- fs/nfsd/nfs4callback.c | 37 +++++++++++++++++------------------ fs/nfsd/nfs4proc.c | 44 +++++++++++++++++++++--------------------- fs/nfsd/xdr4.h | 11 +++++++---- 3 files changed, 47 insertions(+), 45 deletions(-)
fs/nfsd/nfs4callback.c +18 -19
@@ -679,7 +679,7 @@ static int nfs4_xdr_dec_cb_notify_lock(struct rpc_rqst *rqstp,* case NFS4_OK: * write_response4 coa_resok4; * default: -* length4 coa_bytes_copied; +* length4 coa_bytes_copied; * }; * struct CB_OFFLOAD4args { * nfs_fh4 coa_fh;
@@ -688,21 +688,22 @@ static int nfs4_xdr_dec_cb_notify_lock(struct rpc_rqst *rqstp,* }; */ static void encode_offload_info4 (struct xdr_stream *xdr, -__be32 nfserr, -const struct nfsd4_copy *cp) +const struct nfsd4_cb_offload *cbo) {__be32 *p; p =xdr_reserve_space (xdr,4 ); - *p++ = nfserr; -if (!nfserr) { + *p = cbo->co_nfserr; +switch (cbo->co_nfserr) { +case nfs_ok: p =xdr_reserve_space (xdr,4 +8 +4 +NFS4_VERIFIER_SIZE ); p =xdr_encode_empty_array (p); - p =xdr_encode_hyper (p, cp->cp_res.wr_bytes_written); - *p++ =cpu_to_be32 (cp->cp_res.wr_stable_how); - p =xdr_encode_opaque_fixed (p, cp->cp_res.wr_verifier.data, + p =xdr_encode_hyper (p, cbo->co_res.wr_bytes_written); + *p++ =cpu_to_be32 (cbo->co_res.wr_stable_how); + p =xdr_encode_opaque_fixed (p, cbo->co_res.wr_verifier.data,NFS4_VERIFIER_SIZE ); - }else { +break ; +default : p =xdr_reserve_space (xdr,8 );/* We always return success if bytes were written */ p =xdr_encode_hyper (p,0 );
@@ -710,18 +711,16 @@ static void encode_offload_info4(struct xdr_stream *xdr, }static void encode_cb_offload4args (struct xdr_stream *xdr, -__be32 nfserr, -const struct knfsd_fh *fh, -const struct nfsd4_copy *cp, +const struct nfsd4_cb_offload *cbo,struct nfs4_cb_compound_hdr *hdr) {__be32 *p; p =xdr_reserve_space (xdr,4 ); - *p++ =cpu_to_be32 (OP_CB_OFFLOAD ); -encode_nfs_fh4 (xdr, fh); -encode_stateid4 (xdr, &cp->cp_res.cb_stateid); -encode_offload_info4 (xdr, nfserr, cp); + *p =cpu_to_be32 (OP_CB_OFFLOAD ); +encode_nfs_fh4 (xdr, &cbo->co_fh); +encode_stateid4 (xdr, &cbo->co_res.cb_stateid); +encode_offload_info4 (xdr, cbo); hdr->nops++; }
@@ -731,8 +730,8 @@ static void nfs4_xdr_enc_cb_offload(struct rpc_rqst *req, const void *data) {const struct nfsd4_callback *cb = data; -const struct nfsd4_copy *cp = - container_of(cb, struct nfsd4_copy, cp_cb); +const struct nfsd4_cb_offload *cbo = + container_of(cb, struct nfsd4_cb_offload, co_cb);struct nfs4_cb_compound_hdr hdr = { .ident =0 , .minorversion = cb->cb_clp->cl_minorversion,
@@ -740,7 +739,7 @@ static void nfs4_xdr_enc_cb_offload(struct rpc_rqst *req,encode_cb_compound4args (xdr, &hdr);encode_cb_sequence4args (xdr, cb, &hdr); -encode_cb_offload4args (xdr, cp->nfserr, &cp->fh, cp, &hdr); +encode_cb_offload4args (xdr, cbo, &hdr);encode_cb_nops (&hdr); }
fs/nfsd/nfs4proc.c +22 -22
83 lines not on this page · raw message
fs/nfsd/xdr4.h +7 -4
@@ -533,6 +533,13 @@ struct nfsd42_write_res {stateid_t cb_stateid; }; +struct nfsd4_cb_offload { +struct nfsd4_callback co_cb; +struct nfsd42_write_res co_res; +__be32 co_nfserr; +struct knfsd_fh co_fh; +}; +struct nfsd4_copy {/* request */ stateid_t cp_src_stateid;
@@ -550,10 +557,6 @@ struct nfsd4_copy {/* response */ struct nfsd42_write_res cp_res; - -/* for cb_offload */ -struct nfsd4_callback cp_cb; -__be32 nfserr;struct knfsd_fh fh;struct nfs4_client *cp_clp;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 610/770 NFSD: drop fh argument from alloc_init_deleg
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeff Layton <[email protected]>
[ Upstream commit bbf936edd543e7220f60f9cbd6933b916550396d ]
Currently, we pass the fh of the opened file down through several functions so that alloc_init_deleg can pass it to delegation_blocked. The filehandle of the open file is available in the nfs4_file however, so there's no need to pass it in a separate argument.
Drop the argument from alloc_init_deleg, nfs4_open_delegation and nfs4_set_delegation.
--- fs/nfsd/nfs4state.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-)
fs/nfsd/nfs4state.c +6 -8
@@ -1143,7 +1143,6 @@ static void block_delegations(struct knfsd_fh *fh)static struct nfs4_delegation *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;
@@ -1153,7 +1152,7 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_file *fp, n =atomic_long_inc_return (&num_delegations);if (n <0 || n > max_delegations) goto out_dec; -if (delegation_blocked (¤t_fh->fh_handle)) +if (delegation_blocked (&fp->fi_fhandle)) goto out_dec; dp =delegstateid (nfs4_alloc_stid (clp, deleg_slab, nfs4_free_deleg));if (dp ==NULL )
@@ -5307,7 +5306,7 @@ static int nfsd4_check_conflicting_opens(struct nfs4_client *clp, }static struct nfs4_delegation * -nfs4_set_delegation (struct nfs4_client *clp,struct svc_fh *fh, +nfs4_set_delegation (struct nfs4_client *clp,struct nfs4_file *fp,struct nfs4_clnt_odstate *odstate) {int status =0 ;
@@ -5352,7 +5351,7 @@ nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh,return ERR_PTR (status); status = -ENOMEM ; - dp =alloc_init_deleg (clp, fp, fh, odstate); + dp =alloc_init_deleg (clp, fp, odstate);if (!dp) goto out_delegees;
@@ -5420,8 +5419,7 @@ static void nfsd4_open_deleg_none_ext(struct nfsd4_open *open, int status)* proper support for them. */ static void -nfs4_open_delegation (struct svc_fh *fh,struct nfsd4_open *open, -struct nfs4_ol_stateid *stp) +nfs4_open_delegation (struct nfsd4_open *open,struct nfs4_ol_stateid *stp) {struct nfs4_delegation *dp;struct nfs4_openowner *oo =openowner (stp->st_stateowner);
@@ -5453,7 +5451,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open,default : goto out_no_deleg; } - dp =nfs4_set_delegation (clp, fh, stp->st_stid.sc_file, stp->st_clnt_odstate); + dp =nfs4_set_delegation (clp, stp->st_stid.sc_file, stp->st_clnt_odstate);if (IS_ERR (dp)) goto out_no_deleg;
@@ -5585,7 +5583,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf* Attempt to hand out a delegation. No error return, because the * OPEN succeeds even if we fail. */ -nfs4_open_delegation (current_fh, open, stp); +nfs4_open_delegation (open, stp); nodeleg: status = nfs_ok;trace_nfsd_open (&stp->st_stid.sc_stateid);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 611/770 NFSD: verify the opened dentry after setting a delegation
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeff Layton <[email protected]>
[ Upstream commit 876c553cb41026cb6ad3cef970a35e5f69c42a25 ]
Between opening a file and setting a delegation on it, someone could rename or unlink the dentry. If this happens, we do not want to grant a delegation on the open.
On a CLAIM_NULL open, we're opening by filename, and we may (in the non-create case) or may not (in the create case) be holding i_rwsem when attempting to set a delegation. The latter case allows a race.
After getting a lease, redo the lookup of the file being opened and validate that the resulting dentry matches the one in the open file description.
To properly redo the lookup we need an rqst pointer to pass to nfsd_lookup_dentry(), so make sure that is available.
--- fs/nfsd/nfs4proc.c | 1 + fs/nfsd/nfs4state.c | 54 ++++++++++++++++++++++++++++++++++++++++----- fs/nfsd/xdr4.h | 1 + 3 files changed, 51 insertions(+), 5 deletions(-)
fs/nfsd/nfs4proc.c +1 -0
@@ -547,6 +547,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, open->op_openowner); open->op_filp =NULL ; + open->op_rqstp = rqstp;/* This check required by spec. */ if (open->op_create && open->op_claim_type !=NFS4_OPEN_CLAIM_NULL )
fs/nfsd/nfs4state.c +49 -5
97 lines not on this page · raw message
fs/nfsd/xdr4.h +1 -0
@@ -279,6 +279,7 @@ struct nfsd4_open {struct nfs4_clnt_odstate *op_odstate;/* used during processing */ struct nfs4_acl *op_acl;struct xdr_netobj op_label; +struct svc_rqst *op_rqstp; };struct nfsd4_open_confirm {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 612/770 NFSD: introduce struct nfsd_attrs
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: NeilBrown <[email protected]>
[ Upstream commit 7fe2a71dda349a1afa75781f0cc7975be9784d15 ]
The attributes that nfsd might want to set on a file include 'struct iattr' as well as an ACL and security label.
The latter two are passed around quite separately from the first, in part because they are only needed for NFSv4. This leads to some clumsiness in the code, such as the attributes NOT being set in nfsd_create_setattr().
We need to keep the directory locked until all attributes are set to ensure the file is never visibile without all its attributes. This need combined with the inconsistent handling of attributes leads to more clumsiness.
As a first step towards tidying this up, introduce 'struct nfsd_attrs'. This is passed (by reference) to vfs.c functions that work with attributes, and is assembled by the various nfs*proc functions which call them. As yet only iattr is included, but future patches will expand this.
--- fs/nfsd/nfs3proc.c | 20 ++++++++++++++++---- fs/nfsd/nfs4proc.c | 23 ++++++++++++++++------- fs/nfsd/nfs4state.c | 5 ++++- fs/nfsd/nfsproc.c | 17 +++++++++++++---- fs/nfsd/vfs.c | 24 ++++++++++++++---------- fs/nfsd/vfs.h | 12 ++++++++---- 6 files changed, 71 insertions(+), 30 deletions(-)
fs/nfsd/nfs3proc.c +16 -4
@@ -67,12 +67,15 @@ nfsd3_proc_setattr(struct svc_rqst *rqstp) {struct nfsd3_sattrargs *argp = rqstp->rq_argp;struct nfsd3_attrstat *resp = rqstp->rq_resp; +struct nfsd_attrs attrs = { + .na_iattr = &argp->attrs, + };dprintk ("nfsd: SETATTR(3) %s\n" ,SVCFH_fmt (&argp->fh));fh_copy (&resp->fh, &argp->fh); - resp->status =nfsd_setattr (rqstp, &resp->fh, &argp->attrs, + resp->status =nfsd_setattr (rqstp, &resp->fh, &attrs, argp->check_guard, argp->guardtime);return rpc_success; }
@@ -233,6 +236,9 @@ nfsd3_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp, {struct iattr *iap = &argp->attrs;struct dentry *parent, *child; +struct nfsd_attrs attrs = { + .na_iattr = iap, + };__u32 v_mtime, v_atime;struct inode *inode;__be32 status;
@@ -331,7 +337,7 @@ nfsd3_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp, } set_attr: - status =nfsd_create_setattr (rqstp, fhp, resfhp, iap); + status =nfsd_create_setattr (rqstp, fhp, resfhp, &attrs); out:fh_unlock (fhp);
@@ -368,6 +374,9 @@ nfsd3_proc_mkdir(struct svc_rqst *rqstp) {struct nfsd3_createargs *argp = rqstp->rq_argp;struct nfsd3_diropres *resp = rqstp->rq_resp; +struct nfsd_attrs attrs = { + .na_iattr = &argp->attrs, + }; dprintk("nfsd: MKDIR(3) %s %.*s\n", SVCFH_fmt(&argp->fh),
@@ -378,7 +387,7 @@ nfsd3_proc_mkdir(struct svc_rqst *rqstp)fh_copy (&resp->dirfh, &argp->fh);fh_init (&resp->fh,NFS3_FHSIZE ); resp->status =nfsd_create (rqstp, &resp->dirfh, argp->name, argp->len, - &argp->attrs,S_IFDIR ,0 , &resp->fh); + &attrs,S_IFDIR ,0 , &resp->fh);fh_unlock (&resp->dirfh);return rpc_success; }
@@ -428,6 +437,9 @@ nfsd3_proc_mknod(struct svc_rqst *rqstp) {struct nfsd3_mknodargs *argp = rqstp->rq_argp;struct nfsd3_diropres *resp = rqstp->rq_resp; +struct nfsd_attrs attrs = { + .na_iattr = &argp->attrs, + };int type;dev_t rdev =0 ;
@@ -453,7 +465,7 @@ nfsd3_proc_mknod(struct svc_rqst *rqstp) type = nfs3_ftypes[argp->ftype]; resp->status =nfsd_create (rqstp, &resp->dirfh, argp->name, argp->len, - &argp->attrs, type, rdev, &resp->fh); + &attrs, type, rdev, &resp->fh);fh_unlock (&resp->dirfh); out:return rpc_success;
fs/nfsd/nfs4proc.c +16 -7
@@ -286,6 +286,9 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp, struct svc_fh *resfhp, struct nfsd4_open *open) { struct iattr *iap = &open->op_iattr; +struct nfsd_attrs attrs = { + .na_iattr = iap, + };struct dentry *parent, *child;__u32 v_mtime, v_atime;struct inode *inode;
@@ -404,7 +407,7 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp, } set_attr: - status =nfsd_create_setattr (rqstp, fhp, resfhp, iap); + status =nfsd_create_setattr (rqstp, fhp, resfhp, &attrs); out:fh_unlock (fhp);
@@ -787,6 +790,9 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, union nfsd4_op_u *u) {struct nfsd4_create *create = &u->create; +struct nfsd_attrs attrs = { + .na_iattr = &create->cr_iattr, + };struct svc_fh resfh;__be32 status;dev_t rdev;
@@ -818,7 +824,7 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, goto out_umask; status =nfsd_create (rqstp, &cstate->current_fh, create->cr_name, create->cr_namelen, - &create->cr_iattr,S_IFBLK , rdev, &resfh); + &attrs,S_IFBLK , rdev, &resfh);break ;case NF4CHR :
@@ -829,26 +835,26 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, goto out_umask; status =nfsd_create (rqstp, &cstate->current_fh, create->cr_name, create->cr_namelen, - &create->cr_iattr,S_IFCHR , rdev, &resfh); + &attrs,S_IFCHR , rdev, &resfh);break ;case NF4SOCK : status =nfsd_create (rqstp, &cstate->current_fh, create->cr_name, create->cr_namelen, - &create->cr_iattr,S_IFSOCK ,0 , &resfh); + &attrs,S_IFSOCK ,0 , &resfh);break ;case NF4FIFO : status =nfsd_create (rqstp, &cstate->current_fh, create->cr_name, create->cr_namelen, - &create->cr_iattr,S_IFIFO ,0 , &resfh); + &attrs,S_IFIFO ,0 , &resfh);break ;case NF4DIR : create->cr_iattr.ia_valid &= ~ATTR_SIZE ; status =nfsd_create (rqstp, &cstate->current_fh, create->cr_name, create->cr_namelen, - &create->cr_iattr,S_IFDIR ,0 , &resfh); + &attrs,S_IFDIR ,0 , &resfh);break ;default :
@@ -1142,6 +1148,9 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, union nfsd4_op_u *u) {struct nfsd4_setattr *setattr = &u->setattr; +struct nfsd_attrs attrs = { + .na_iattr = &setattr->sa_iattr, + };__be32 status = nfs_ok;int err;
@@ -1174,7 +1183,7 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, &setattr->sa_label);if (status) goto out; - status =nfsd_setattr (rqstp, &cstate->current_fh, &setattr->sa_iattr, + status =nfsd_setattr (rqstp, &cstate->current_fh, &attrs,0 , (time64_t )0 ); out:fh_drop_write (&cstate->current_fh);
fs/nfsd/nfs4state.c +4 -1
@@ -5077,11 +5077,14 @@ nfsd4_truncate(struct svc_rqst *rqstp, struct svc_fh *fh, .ia_valid = ATTR_SIZE, .ia_size = 0, }; +struct nfsd_attrs attrs = { + .na_iattr = &iattr, + };if (!open->op_truncate)return 0 ;if (!(open->op_share_access &NFS4_SHARE_ACCESS_WRITE ))return nfserr_inval; -return nfsd_setattr (rqstp, fh, &iattr,0 , (time64_t )0 ); +return nfsd_setattr (rqstp, fh, &attrs,0 , (time64_t )0 ); } static __be32 nfs4_get_vfs_file(struct svc_rqst *rqstp, struct nfs4_file *fp,
fs/nfsd/nfsproc.c +13 -4
@@ -51,6 +51,9 @@ nfsd_proc_setattr(struct svc_rqst *rqstp)struct nfsd_sattrargs *argp = rqstp->rq_argp;struct nfsd_attrstat *resp = rqstp->rq_resp;struct iattr *iap = &argp->attrs; +struct nfsd_attrs attrs = { + .na_iattr = iap, + };struct svc_fh *fhp; dprintk("nfsd: SETATTR %s, valid=%x, size=%ld\n",
@@ -100,7 +103,7 @@ nfsd_proc_setattr(struct svc_rqst *rqstp) } } - resp->status =nfsd_setattr (rqstp, fhp, iap,0 , (time64_t )0 ); + resp->status =nfsd_setattr (rqstp, fhp, &attrs,0 , (time64_t )0 );if (resp->status != nfs_ok) goto out;
@@ -260,6 +263,9 @@ nfsd_proc_create(struct svc_rqst *rqstp)svc_fh *dirfhp = &argp->fh;svc_fh *newfhp = &resp->fh;struct iattr *attr = &argp->attrs; +struct nfsd_attrs attrs = { + .na_iattr = attr, + };struct inode *inode;struct dentry *dchild;int type, mode;
@@ -385,7 +391,7 @@ nfsd_proc_create(struct svc_rqst *rqstp)if (!inode) {/* File doesn't exist. Create it and set attrs */ resp->status =nfsd_create_locked (rqstp, dirfhp, argp->name, - argp->len, attr, type, rdev, + argp->len, &attrs, type, rdev, newfhp); }else if (type ==S_IFREG ) { dprintk("nfsd: existing %s, valid=%x, size=%ld\n",
@@ -396,7 +402,7 @@ nfsd_proc_create(struct svc_rqst *rqstp)*/ attr->ia_valid &=ATTR_SIZE ;if (attr->ia_valid) - resp->status =nfsd_setattr (rqstp, newfhp, attr,0 , + resp->status =nfsd_setattr (rqstp, newfhp, &attrs,0 , (time64_t )0 ); }
@@ -511,6 +517,9 @@ nfsd_proc_mkdir(struct svc_rqst *rqstp) {struct nfsd_createargs *argp = rqstp->rq_argp;struct nfsd_diropres *resp = rqstp->rq_resp; +struct nfsd_attrs attrs = { + .na_iattr = &argp->attrs, + };dprintk ("nfsd: MKDIR %s %.*s\n" ,SVCFH_fmt (&argp->fh), argp->len, argp->name);
@@ -522,7 +531,7 @@ nfsd_proc_mkdir(struct svc_rqst *rqstp) argp->attrs.ia_valid &= ~ATTR_SIZE ;fh_init (&resp->fh,NFS_FHSIZE ); resp->status =nfsd_create (rqstp, &argp->fh, argp->name, argp->len, - &argp->attrs,S_IFDIR ,0 , &resp->fh); + &attrs,S_IFDIR ,0 , &resp->fh);fh_put (&argp->fh);if (resp->status != nfs_ok) goto out;
fs/nfsd/vfs.c +14 -10
@@ -362,11 +362,13 @@ nfsd_get_write_access(struct svc_rqst *rqstp, struct svc_fh *fhp,* Set various file attributes. After this call fhp needs an fh_put. */ __be32 -nfsd_setattr (struct svc_rqst *rqstp,struct svc_fh *fhp,struct iattr *iap, +nfsd_setattr (struct svc_rqst *rqstp,struct svc_fh *fhp, +struct nfsd_attrs *attr,int check_guard,time64_t guardtime) {struct dentry *dentry;struct inode *inode; +struct iattr *iap = attr->na_iattr;int accmode =NFSD_MAY_SATTR ;umode_t ftype =0 ;__be32 err;
@@ -1221,14 +1223,15 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp, u64 offset,* @rqstp: RPC transaction being executed * @fhp: NFS filehandle of parent directory * @resfhp: NFS filehandle of new object -* @iap: requested attributes of new object +* @attrs: requested attributes of new object * * Returns nfs_ok on success, or an nfsstat in network byte order. */ __be32 nfsd_create_setattr (struct svc_rqst *rqstp,struct svc_fh *fhp, -struct svc_fh *resfhp,struct iattr *iap) +struct svc_fh *resfhp,struct nfsd_attrs *attrs) { +struct iattr *iap = attrs->na_iattr;__be32 status;/*
@@ -1249,7 +1252,7 @@ nfsd_create_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp,* if the attributes have not changed. */ if (iap->ia_valid) - status =nfsd_setattr (rqstp, resfhp, iap,0 , (time64_t )0 ); + status =nfsd_setattr (rqstp, resfhp, attrs,0 , (time64_t )0 );else status =nfserrno (commit_metadata (resfhp));
@@ -1288,11 +1291,12 @@ nfsd_check_ignore_resizing(struct iattr *iap)/* The parent directory should already be locked: */ __be32 nfsd_create_locked (struct svc_rqst *rqstp,struct svc_fh *fhp, -char *fname,int flen,struct iattr *iap, -int type,dev_t rdev,struct svc_fh *resfhp) +char *fname,int flen,struct nfsd_attrs *attrs, +int type,dev_t rdev,struct svc_fh *resfhp) {struct dentry *dentry, *dchild;struct inode *dirp; +struct iattr *iap = attrs->na_iattr;__be32 err;int host_err;
@@ -1365,7 +1369,7 @@ nfsd_create_locked(struct svc_rqst *rqstp, struct svc_fh *fhp,if (host_err <0 ) goto out_nfserr; - err =nfsd_create_setattr (rqstp, fhp, resfhp, iap); + err =nfsd_create_setattr (rqstp, fhp, resfhp, attrs); out:dput (dchild);
@@ -1384,8 +1388,8 @@ nfsd_create_locked(struct svc_rqst *rqstp, struct svc_fh *fhp,*/ __be32 nfsd_create (struct svc_rqst *rqstp,struct svc_fh *fhp, -char *fname,int flen,struct iattr *iap, -int type,dev_t rdev,struct svc_fh *resfhp) +char *fname,int flen,struct nfsd_attrs *attrs, +int type,dev_t rdev,struct svc_fh *resfhp) {struct dentry *dentry, *dchild =NULL ;__be32 err;
@@ -1417,7 +1421,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,dput (dchild);if (err)return err; -return nfsd_create_locked (rqstp, fhp, fname, flen, iap, type, +return nfsd_create_locked (rqstp, fhp, fname, flen, attrs, type, rdev, resfhp); }
fs/nfsd/vfs.h +8 -4
@@ -42,6 +42,10 @@ struct nfsd_file;typedef int (*nfsd_filldir_t )(void *,const char *,int ,loff_t ,u64 ,unsigned );/* nfsd/vfs.c */ +struct nfsd_attrs { +struct iattr *na_iattr;/* input */ +}; +int nfsd_cross_mnt (struct svc_rqst *rqstp,struct dentry **dpp,struct svc_export **expp); __be32 nfsd_lookup(struct svc_rqst *, struct svc_fh *,
@@ -50,7 +54,7 @@ __be32 nfsd_lookup_dentry(struct svc_rqst *, struct svc_fh *, const char *, unsigned int, struct svc_export **, struct dentry **);__be32 nfsd_setattr (struct svc_rqst *,struct svc_fh *, -struct iattr *,int ,time64_t ); +struct nfsd_attrs *,int ,time64_t );int nfsd_mountpoint (struct dentry *,struct svc_export *);#ifdef CONFIG_NFSD_V4 __be32 nfsd4_set_nfs4_label(struct svc_rqst *, struct svc_fh *,
@@ -63,14 +67,14 @@ __be32 nfsd4_clone_file_range(struct svc_rqst *rqstp, u64 count, bool sync);#endif /* CONFIG_NFSD_V4 */ __be32 nfsd_create_locked (struct svc_rqst *,struct svc_fh *, -char *name,int len,struct iattr *attrs, +char *name,int len,struct nfsd_attrs *attrs,int type,dev_t rdev,struct svc_fh *res);__be32 nfsd_create (struct svc_rqst *,struct svc_fh *, -char *name,int len,struct iattr *attrs, +char *name,int len,struct nfsd_attrs *attrs,int type,dev_t rdev,struct svc_fh *res);__be32 nfsd_access (struct svc_rqst *,struct svc_fh *,u32 *,u32 *);__be32 nfsd_create_setattr (struct svc_rqst *rqstp,struct svc_fh *fhp, -struct svc_fh *resfhp,struct iattr *iap); +struct svc_fh *resfhp,struct nfsd_attrs *iap);__be32 nfsd_commit (struct svc_rqst *rqst,struct svc_fh *fhp,u64 offset,u32 count,__be32 *verf);#ifdef CONFIG_NFSD_V4
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 613/770 NFSD: set attributes when creating symlinks
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: NeilBrown <[email protected]>
[ Upstream commit 93adc1e391a761441d783828b93979b38093d011 ]
The NFS protocol includes attributes when creating symlinks. Linux does store attributes for symlinks and allows them to be set, though they are not used for permission checking.
NFSD currently doesn't set standard (struct iattr) attributes when creating symlinks, but for NFSv4 it does set ACLs and security labels. This is inconsistent.
To improve consistency, pass the provided attributes into nfsd_symlink() and call nfsd_create_setattr() to set them.
NOTE: this results in a behaviour change for all NFS versions when the client sends non-default attributes with a SYMLINK request. With the Linux client, the only attributes are:
attr.ia_mode = S_IFLNK | S_IRWXUGO; attr.ia_valid = ATTR_MODE;
so the final outcome will be unchanged. Other clients might sent different attributes, and if they did they probably expect them to be honoured.
We ignore any error from nfsd_create_setattr(). It isn't really clear what should be done if a file is successfully created, but the attributes cannot be set. NFS doesn't allow partial success to be reported. Reporting failure is probably more misleading than reporting success, so the status is ignored.
--- fs/nfsd/nfs3proc.c | 5 ++++- fs/nfsd/nfs4proc.c | 2 +- fs/nfsd/nfsproc.c | 5 ++++- fs/nfsd/vfs.c | 25 ++++++++++++++++++------- fs/nfsd/vfs.h | 5 +++-- 5 files changed, 30 insertions(+), 12 deletions(-)
fs/nfsd/nfs3proc.c +4 -1
@@ -397,6 +397,9 @@ nfsd3_proc_symlink(struct svc_rqst *rqstp) {struct nfsd3_symlinkargs *argp = rqstp->rq_argp;struct nfsd3_diropres *resp = rqstp->rq_resp; +struct nfsd_attrs attrs = { + .na_iattr = &argp->attrs, + };if (argp->tlen ==0 ) { resp->status = nfserr_inval;
@@ -423,7 +426,7 @@ nfsd3_proc_symlink(struct svc_rqst *rqstp)fh_copy (&resp->dirfh, &argp->ffh);fh_init (&resp->fh,NFS3_FHSIZE ); resp->status =nfsd_symlink (rqstp, &resp->dirfh, argp->fname, - argp->flen, argp->tname, &resp->fh); + argp->flen, argp->tname, &attrs, &resp->fh);kfree (argp->tname); out:return rpc_success;
fs/nfsd/nfs4proc.c +1 -1
@@ -813,7 +813,7 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,case NF4LNK : status =nfsd_symlink (rqstp, &cstate->current_fh, create->cr_name, create->cr_namelen, - create->cr_data, &resfh); + create->cr_data, &attrs, &resfh);break ;case NF4BLK :
fs/nfsd/nfsproc.c +4 -1
@@ -478,6 +478,9 @@ nfsd_proc_symlink(struct svc_rqst *rqstp) {struct nfsd_symlinkargs *argp = rqstp->rq_argp;struct nfsd_stat *resp = rqstp->rq_resp; +struct nfsd_attrs attrs = { + .na_iattr = &argp->attrs, + };struct svc_fh newfh;if (argp->tlen >NFS_MAXPATHLEN ) {
@@ -499,7 +502,7 @@ nfsd_proc_symlink(struct svc_rqst *rqstp)fh_init (&newfh,NFS_FHSIZE ); resp->status =nfsd_symlink (rqstp, &argp->ffh, argp->fname, argp->flen, - argp->tname, &newfh); + argp->tname, &attrs, &newfh);kfree (argp->tname);fh_put (&argp->ffh);
fs/nfsd/vfs.c +18 -7
@@ -1463,15 +1463,25 @@ nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp)return 0 ; } -/* -* Create a symlink and look up its inode +/** +* nfsd_symlink - Create a symlink and look up its inode +* @rqstp: RPC transaction being executed +* @fhp: NFS filehandle of parent directory +* @fname: filename of the new symlink +* @flen: length of @fname +* @path: content of the new symlink (NUL-terminated) +* @attrs: requested attributes of new object +* @resfhp: NFS filehandle of new object +* * N.B. After this call _both_ fhp and resfhp need an fh_put +* +* Returns nfs_ok on success, or an nfsstat in network byte order. */ __be32 nfsd_symlink (struct svc_rqst *rqstp,struct svc_fh *fhp, -char *fname,int flen, -char *path, -struct svc_fh *resfhp) +char *fname,int flen, +char *path,struct nfsd_attrs *attrs, +struct svc_fh *resfhp) {struct dentry *dentry, *dnew;__be32 err, cerr;
@@ -1501,13 +1511,14 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp, host_err =vfs_symlink (d_inode (dentry), dnew, path); err =nfserrno (host_err); + cerr =fh_compose (resfhp, fhp->fh_export, dnew, fhp); +if (!err) +nfsd_create_setattr (rqstp, fhp, resfhp, attrs);fh_unlock (fhp);if (!err) err =nfserrno (commit_metadata (fhp)); -fh_drop_write (fhp); - cerr =fh_compose (resfhp, fhp->fh_export, dnew, fhp);dput (dnew);if (err==0 ) err = cerr; out:
fs/nfsd/vfs.h +3 -2
@@ -114,8 +114,9 @@ __be32 nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp,__be32 nfsd_readlink (struct svc_rqst *,struct svc_fh *,char *,int *);__be32 nfsd_symlink (struct svc_rqst *,struct svc_fh *, -char *name,int len,char *path, -struct svc_fh *res); +char *name,int len,char *path, +struct nfsd_attrs *attrs, +struct svc_fh *res);__be32 nfsd_link (struct svc_rqst *,struct svc_fh *,char *,int ,struct svc_fh *); ssize_t nfsd_copy_file_range(struct file *, u64,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 614/770 NFSD: add security label to struct nfsd_attrs
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: NeilBrown <[email protected]>
[ Upstream commit d6a97d3f589a3a46a16183e03f3774daee251317 ]
nfsd_setattr() now sets a security label if provided, and nfsv4 provides it in the 'open' and 'create' paths and the 'setattr' path. If setting the label failed (including because the kernel doesn't support labels), an error field in 'struct nfsd_attrs' is set, and the caller can respond. The open/create callers clear FATTR4_WORD2_SECURITY_LABEL in the returned attr set in this case. The setattr caller returns the error.
--- fs/nfsd/nfs4proc.c | 49 +++++++++------------------------------------- fs/nfsd/vfs.c | 29 +++------------------------ fs/nfsd/vfs.h | 5 +++-- 3 files changed, 15 insertions(+), 68 deletions(-)
fs/nfsd/nfs4proc.c +9 -40
@@ -64,36 +64,6 @@ MODULE_PARM_DESC(nfsd4_ssc_umount_timeout, "idle msecs before unmount export from source server");#endif -#ifdef CONFIG_NFSD_V4_SECURITY_LABEL -#include <linux/security.h> - -static inline void -nfsd4_security_inode_setsecctx (struct svc_fh *resfh,struct xdr_netobj *label,u32 *bmval) -{ -struct inode *inode =d_inode (resfh->fh_dentry); -int status; - -inode_lock (inode); - status =security_inode_setsecctx (resfh->fh_dentry, - label->data, label->len); -inode_unlock (inode); - -if (status) -/* -* XXX: We should really fail the whole open, but we may -* already have created a new file, so it may be too -* late. For now this seems the least of evils: -*/ - bmval[2 ] &= ~FATTR4_WORD2_SECURITY_LABEL ; - -return ; -} -#else -static inline void -nfsd4_security_inode_setsecctx (struct svc_fh *resfh,struct xdr_netobj *label,u32 *bmval) -{ } -#endif -#define NFSDDBG_FACILITY NFSDDBG_PROCstatic u32 nfsd_attrmask[] = {
@@ -288,6 +258,7 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,struct iattr *iap = &open->op_iattr;struct nfsd_attrs attrs = { .na_iattr = iap, + .na_seclabel = &open->op_label, };struct dentry *parent, *child;__u32 v_mtime, v_atime;
@@ -409,6 +380,8 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp, set_attr: status =nfsd_create_setattr (rqstp, fhp, resfhp, &attrs); +if (attrs.na_labelerr) + open->op_bmval[2 ] &= ~FATTR4_WORD2_SECURITY_LABEL ; out:fh_unlock (fhp);if (child && !IS_ERR (child))
@@ -450,9 +423,6 @@ do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, stru status =nfsd4_create_file (rqstp, current_fh, *resfh, open); current->fs->umask =0 ; -if (!status && open->op_label.len) -nfsd4_security_inode_setsecctx (*resfh, &open->op_label, open->op_bmval); -/* * Following rfc 3530 14.2.16, and rfc 5661 18.16.4 * use the returned bitmask to indicate which attributes
@@ -792,6 +762,7 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,struct nfsd4_create *create = &u->create;struct nfsd_attrs attrs = { .na_iattr = &create->cr_iattr, + .na_seclabel = &create->cr_label, };struct svc_fh resfh;__be32 status;
@@ -864,8 +835,8 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,if (status) goto out; -if (create->cr_label.len) -nfsd4_security_inode_setsecctx (&resfh, &create->cr_label, create->cr_bmval); +if (attrs.na_labelerr) + create->cr_bmval[2 ] &= ~FATTR4_WORD2_SECURITY_LABEL ;if (create->cr_acl !=NULL ) do_set_nfs4_acl(rqstp, &resfh, create->cr_acl,
@@ -1150,6 +1121,7 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,struct nfsd4_setattr *setattr = &u->setattr;struct nfsd_attrs attrs = { .na_iattr = &setattr->sa_iattr, + .na_seclabel = &setattr->sa_label, };__be32 status = nfs_ok;int err;
@@ -1178,13 +1150,10 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, setattr->sa_acl);if (status) goto out; -if (setattr->sa_label.len) - status =nfsd4_set_nfs4_label (rqstp, &cstate->current_fh, - &setattr->sa_label); -if (status) - goto out; status =nfsd_setattr (rqstp, &cstate->current_fh, &attrs,0 , (time64_t )0 ); +if (!status) + status =nfserrno (attrs.na_labelerr); out:fh_drop_write (&cstate->current_fh);return status;
fs/nfsd/vfs.c +3 -26
@@ -471,6 +471,9 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, host_err =notify_change (dentry, iap,NULL ); out_unlock: +if (attr->na_seclabel && attr->na_seclabel->len) + attr->na_labelerr =security_inode_setsecctx (dentry, + attr->na_seclabel->data, attr->na_seclabel->len);fh_unlock (fhp);if (size_change)put_write_access (inode);
@@ -508,32 +511,6 @@ int nfsd4_is_junction(struct dentry *dentry)return 0 ;return 1 ; } -#ifdef CONFIG_NFSD_V4_SECURITY_LABEL -__be32 nfsd4_set_nfs4_label (struct svc_rqst *rqstp,struct svc_fh *fhp, -struct xdr_netobj *label) -{ -__be32 error; -int host_error; -struct dentry *dentry; - - error =fh_verify (rqstp, fhp,0 /* S_IFREG */ ,NFSD_MAY_SATTR ); -if (error) -return error; - - dentry = fhp->fh_dentry; - -inode_lock (d_inode (dentry)); - host_error =security_inode_setsecctx (dentry, label->data, label->len); -inode_unlock (d_inode (dentry)); -return nfserrno (host_error); -} -#else -__be32 nfsd4_set_nfs4_label (struct svc_rqst *rqstp,struct svc_fh *fhp, -struct xdr_netobj *label) -{ -return nfserr_notsupp; -} -#endif static struct nfsd4_compound_state *nfsd4_get_cstate (struct svc_rqst *rqstp) {
fs/nfsd/vfs.h +3 -2
@@ -44,6 +44,9 @@ typedef int (*nfsd_filldir_t)(void *, const char *, int, loff_t, u64, unsigned);/* nfsd/vfs.c */ struct nfsd_attrs {struct iattr *na_iattr;/* input */ +struct xdr_netobj *na_seclabel;/* input */ + +int na_labelerr;/* output */ }; int nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
@@ -57,8 +60,6 @@ __be32 nfsd_setattr(struct svc_rqst *, struct svc_fh *, struct nfsd_attrs *, int, time64_t);int nfsd_mountpoint (struct dentry *,struct svc_export *);#ifdef CONFIG_NFSD_V4 -__be32 nfsd4_set_nfs4_label (struct svc_rqst *,struct svc_fh *, -struct xdr_netobj *);__be32 nfsd4_vfs_fallocate (struct svc_rqst *,struct svc_fh *,struct file *,loff_t ,loff_t ,int ); __be32 nfsd4_clone_file_range(struct svc_rqst *rqstp,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 615/770 NFSD: add posix ACLs to struct nfsd_attrs
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: NeilBrown <[email protected]>
[ Upstream commit c0cbe70742f4a70893cd6e5f6b10b6e89b6db95b ]
pacl and dpacl pointers are added to struct nfsd_attrs, which requires that we have an nfsd_attrs_free() function to free them. Those nfsv4 functions that can set ACLs now set up these pointers based on the passed in NFSv4 ACL.
nfsd_setattr() sets the acls as appropriate.
Errors are handled as with security labels.
--- fs/nfsd/acl.h | 6 ++++-- fs/nfsd/nfs4acl.c | 45 +++++++-------------------------------------- fs/nfsd/nfs4proc.c | 46 ++++++++++++++++------------------------------ fs/nfsd/vfs.c | 7 +++++++ fs/nfsd/vfs.h | 11 +++++++++++ 5 files changed, 45 insertions(+), 70 deletions(-)
fs/nfsd/acl.h +4 -2
@@ -38,6 +38,8 @@struct nfs4_acl ;struct svc_fh ;struct svc_rqst ; +struct nfsd_attrs ; +enum nfs_ftype4 ;int nfs4_acl_bytes (int entries);int nfs4_acl_get_whotype (char *,u32 );
@@ -45,7 +47,7 @@ __be32 nfs4_acl_write_who(struct xdr_stream *xdr, int who);int nfsd4_get_nfs4_acl (struct svc_rqst *rqstp,struct dentry *dentry,struct nfs4_acl **acl); -__be32 nfsd4_set_nfs4_acl (struct svc_rqst *rqstp,struct svc_fh *fhp, -struct nfs4_acl *acl); +__be32 nfsd4_acl_to_attr (enum nfs_ftype4 type,struct nfs4_acl *acl, +struct nfsd_attrs *attr);#endif /* LINUX_NFS4_ACL_H */
fs/nfsd/nfs4acl.c +7 -38
64 lines not on this page · raw message
fs/nfsd/nfs4proc.c +16 -30
108 lines not on this page · raw message
fs/nfsd/vfs.c +7 -0
@@ -474,6 +474,13 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp,if (attr->na_seclabel && attr->na_seclabel->len) attr->na_labelerr =security_inode_setsecctx (dentry, attr->na_seclabel->data, attr->na_seclabel->len); +if (IS_ENABLED (CONFIG_FS_POSIX_ACL ) && attr->na_pacl) + attr->na_aclerr =set_posix_acl (inode,ACL_TYPE_ACCESS , + attr->na_pacl); +if (IS_ENABLED (CONFIG_FS_POSIX_ACL ) && + !attr->na_aclerr && attr->na_dpacl &&S_ISDIR (inode->i_mode)) + attr->na_aclerr =set_posix_acl (inode,ACL_TYPE_DEFAULT , + attr->na_dpacl);fh_unlock (fhp);if (size_change)put_write_access (inode);
fs/nfsd/vfs.h +11 -0
@@ -6,6 +6,8 @@#ifndef LINUX_NFSD_VFS_H #define LINUX_NFSD_VFS_H +#include <linux/fs.h> +#include <linux/posix_acl.h> #include "nfsfh.h" #include "nfsd.h"
@@ -45,10 +47,19 @@ typedef int (*nfsd_filldir_t)(void *, const char *, int, loff_t, u64, unsigned);struct nfsd_attrs {struct iattr *na_iattr;/* input */ struct xdr_netobj *na_seclabel;/* input */ +struct posix_acl *na_pacl;/* input */ +struct posix_acl *na_dpacl;/* input */ int na_labelerr;/* output */ +int na_aclerr;/* output */ }; +static inline void nfsd_attrs_free (struct nfsd_attrs *attrs) +{ +posix_acl_release (attrs->na_pacl); +posix_acl_release (attrs->na_dpacl); +} +int nfsd_cross_mnt (struct svc_rqst *rqstp,struct dentry **dpp,struct svc_export **expp); __be32 nfsd_lookup(struct svc_rqst *, struct svc_fh *,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 616/770 NFSD: change nfsd_create()/nfsd_symlink() to unlock directory before returning.
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: NeilBrown <[email protected]>
[ Upstream commit 927bfc5600cd6333c9ef9f090f19e66b7d4c8ee1 ]
nfsd_create() usually returns with the directory still locked. nfsd_symlink() usually returns with it unlocked. This is clumsy.
Until recently nfsd_create() needed to keep the directory locked until ACLs and security label had been set. These are now set inside nfsd_create() (in nfsd_setattr()) so this need is gone.
So change nfsd_create() and nfsd_symlink() to always unlock, and remove any fh_unlock() calls that follow calls to these functions.
--- fs/nfsd/nfs3proc.c | 2 -- fs/nfsd/nfs4proc.c | 2 -- fs/nfsd/vfs.c | 38 +++++++++++++++++++++----------------- 3 files changed, 21 insertions(+), 21 deletions(-)
fs/nfsd/nfs3proc.c +0 -2
@@ -388,7 +388,6 @@ nfsd3_proc_mkdir(struct svc_rqst *rqstp)fh_init (&resp->fh,NFS3_FHSIZE ); resp->status =nfsd_create (rqstp, &resp->dirfh, argp->name, argp->len, &attrs,S_IFDIR ,0 , &resp->fh); -fh_unlock (&resp->dirfh);return rpc_success; }
@@ -469,7 +468,6 @@ nfsd3_proc_mknod(struct svc_rqst *rqstp) type = nfs3_ftypes[argp->ftype]; resp->status =nfsd_create (rqstp, &resp->dirfh, argp->name, argp->len, &attrs, type, rdev, &resp->fh); -fh_unlock (&resp->dirfh); out:return rpc_success; }
fs/nfsd/nfs4proc.c +0 -2
@@ -823,8 +823,6 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, create->cr_bmval[2 ] &= ~FATTR4_WORD2_SECURITY_LABEL ;if (attrs.na_aclerr) create->cr_bmval[0 ] &= ~FATTR4_WORD0_ACL ; - -fh_unlock (&cstate->current_fh);set_change_info (&create->cr_cinfo, &cstate->current_fh);fh_dup2 (&cstate->current_fh, &resfh); out:
fs/nfsd/vfs.c +21 -17
@@ -1395,8 +1395,10 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,fh_lock_nested (fhp,I_MUTEX_PARENT ); dchild =lookup_one_len (fname, dentry, flen); host_err =PTR_ERR (dchild); -if (IS_ERR (dchild)) -return nfserrno (host_err); +if (IS_ERR (dchild)) { + err =nfserrno (host_err); + goto out_unlock; + } err =fh_compose (resfhp, fhp->fh_export, dchild, fhp);/* * We unconditionally drop our ref to dchild as fh_compose will have
@@ -1404,9 +1406,12 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,*/ dput (dchild);if (err) -return err; -return nfsd_create_locked (rqstp, fhp, fname, flen, attrs, type, - rdev, resfhp); + goto out_unlock; + err =nfsd_create_locked (rqstp, fhp, fname, flen, attrs, type, + rdev, resfhp); +out_unlock: +fh_unlock (fhp); +return err; }/*
@@ -1483,16 +1488,19 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp, goto out; host_err =fh_want_write (fhp); -if (host_err) - goto out_nfserr; +if (host_err) { + err =nfserrno (host_err); + goto out; + }fh_lock (fhp); dentry = fhp->fh_dentry; dnew =lookup_one_len (fname, dentry, flen); - host_err =PTR_ERR (dnew); -if (IS_ERR (dnew)) - goto out_nfserr; - +if (IS_ERR (dnew)) { + err =nfserrno (PTR_ERR (dnew)); +fh_unlock (fhp); + goto out_drop_write; + } host_err =vfs_symlink (d_inode (dentry), dnew, path); err =nfserrno (host_err); cerr =fh_compose (resfhp, fhp->fh_export, dnew, fhp);
@@ -1501,16 +1509,12 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,fh_unlock (fhp);if (!err) err =nfserrno (commit_metadata (fhp)); -fh_drop_write (fhp); -dput (dnew);if (err==0 ) err = cerr; +out_drop_write: +fh_drop_write (fhp); out:return err; - -out_nfserr: - err =nfserrno (host_err); - goto out; }/*
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 617/770 NFSD: always drop directory lock in nfsd_unlink()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: NeilBrown <[email protected]>
[ Upstream commit b677c0c63a135a916493c064906582e9f3ed4802 ]
Some error paths in nfsd_unlink() allow it to exit without unlocking the directory. This is not a problem in practice as the directory will be locked with an fh_put(), but it is untidy and potentially confusing.
This allows us to remove all the fh_unlock() calls that are immediately after nfsd_unlink() calls.
--- fs/nfsd/nfs3proc.c | 2 -- fs/nfsd/nfs4proc.c | 4 +--- fs/nfsd/vfs.c | 7 +++++-- 3 files changed, 6 insertions(+), 7 deletions(-)
fs/nfsd/nfs3proc.c +0 -2
@@ -490,7 +490,6 @@ nfsd3_proc_remove(struct svc_rqst *rqstp)fh_copy (&resp->fh, &argp->fh); resp->status =nfsd_unlink (rqstp, &resp->fh, -S_IFDIR , argp->name, argp->len); -fh_unlock (&resp->fh);return rpc_success; }
@@ -511,7 +510,6 @@ nfsd3_proc_rmdir(struct svc_rqst *rqstp)fh_copy (&resp->fh, &argp->fh); resp->status =nfsd_unlink (rqstp, &resp->fh,S_IFDIR , argp->name, argp->len); -fh_unlock (&resp->fh);return rpc_success; }
fs/nfsd/nfs4proc.c +1 -3
@@ -1002,10 +1002,8 @@ nfsd4_remove(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,return nfserr_grace; status =nfsd_unlink (rqstp, &cstate->current_fh,0 , remove->rm_name, remove->rm_namelen); -if (!status) { -fh_unlock (&cstate->current_fh); +if (!status)set_change_info (&remove->rm_cinfo, &cstate->current_fh); - }return status; }
fs/nfsd/vfs.c +5 -2
@@ -1767,12 +1767,12 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, rdentry =lookup_one_len (fname, dentry, flen); host_err =PTR_ERR (rdentry);if (IS_ERR (rdentry)) - goto out_drop_write; + goto out_unlock;if (d_really_is_negative (rdentry)) {dput (rdentry); host_err = -ENOENT ; - goto out_drop_write; + goto out_unlock; } rinode =d_inode (rdentry);ihold (rinode);
@@ -1810,6 +1810,9 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, } out:return err; +out_unlock: +fh_unlock (fhp); + goto out_drop_write; }/*
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 618/770 NFSD: only call fh_unlock() once in nfsd_link()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: NeilBrown <[email protected]>
[ Upstream commit e18bcb33bc5b69bccc2b532075aa00bb49cc01c5 ]
On non-error paths, nfsd_link() calls fh_unlock() twice. This is safe because fh_unlock() records that the unlock has been done and doesn't repeat it.
However it makes the code a little confusing and interferes with changes that are planned for directory locking.
So rearrange the code to ensure fh_unlock() is called exactly once if fh_lock() was called.
--- fs/nfsd/vfs.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-)
fs/nfsd/vfs.c +10 -9
@@ -1557,9 +1557,10 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, dirp =d_inode (ddir); dnew =lookup_one_len (name, ddir, len); - host_err =PTR_ERR (dnew); -if (IS_ERR (dnew)) - goto out_nfserr; +if (IS_ERR (dnew)) { + err =nfserrno (PTR_ERR (dnew)); + goto out_unlock; + } dold = tfhp->fh_dentry;
@@ -1578,17 +1579,17 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,else err =nfserrno (host_err); } -out_dput:dput (dnew); -out_unlock: -fh_unlock (ffhp); +out_drop_write:fh_drop_write (tfhp); out:return err; -out_nfserr: - err =nfserrno (host_err); - goto out_unlock; +out_dput: +dput (dnew); +out_unlock: +fh_unlock (ffhp); + goto out_drop_write; } static void
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 619/770 NFSD: reduce locking in nfsd_lookup()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: NeilBrown <[email protected]>
[ Upstream commit 19d008b46941b8c668402170522e0f7a9258409c ]
nfsd_lookup() takes an exclusive lock on the parent inode, but no callers want the lock and it may not be needed at all if the result is in the dcache.
Change nfsd_lookup_dentry() to not take the lock, and call lookup_one_len_locked() which takes lock only if needed.
nfsd4_open() currently expects the lock to still be held, but that isn't necessary as nfsd_validate_delegated_dentry() provides required guarantees without the lock.
NOTE: NFSv4 requires directory changeinfo for OPEN even when a create
wasn't requested and no change happened. Now that nfsd_lookup() doesn't use fh_lock(), we need to explicitly fill the attributes when no create happens. A new fh_fill_both_attrs() is provided for that task.
--- fs/nfsd/nfs4proc.c | 20 ++++++++++++-------- fs/nfsd/nfs4state.c | 3 --- fs/nfsd/nfsfh.c | 19 +++++++++++++++++++ fs/nfsd/nfsfh.h | 2 +- fs/nfsd/vfs.c | 34 ++++++++++++++-------------------- 5 files changed, 46 insertions(+), 32 deletions(-)
fs/nfsd/nfs4proc.c +12 -8
@@ -302,6 +302,11 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,if (d_really_is_positive (child)) { status = nfs_ok; +/* NFSv4 protocol requires change attributes even though +* no change happened. +*/ +fh_fill_both_attrs (fhp); +switch (open->op_createmode) {case NFS4_CREATE_UNCHECKED :if (!d_is_reg (child))
@@ -417,15 +422,15 @@ do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struif (nfsd4_create_is_exclusive (open->op_createmode) && status ==0 ) open->op_bmval[1 ] |= (FATTR4_WORD1_TIME_ACCESS |FATTR4_WORD1_TIME_MODIFY ); - }else -/* -* Note this may exit with the parent still locked. -* We will hold the lock until nfsd4_open's final -* lookup, to prevent renames or unlinks until we've had -* a chance to an acquire a delegation if appropriate. -*/ + }else { status =nfsd_lookup (rqstp, current_fh, open->op_fname, open->op_fnamelen, *resfh); +if (!status) +/* NFSv4 protocol requires change attributes even though +* no change happened. +*/ +fh_fill_both_attrs (current_fh); + }if (status) goto out; status =nfsd_check_obj_isreg (*resfh);
@@ -1043,7 +1048,6 @@ nfsd4_secinfo(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, &exp, &dentry);if (err)return err; -fh_unlock (&cstate->current_fh);if (d_really_is_negative (dentry)) {exp_put (exp); err = nfserr_noent;
fs/nfsd/nfs4state.c +0 -3
@@ -5321,9 +5321,6 @@ nfsd4_verify_deleg_dentry(struct nfsd4_open *open, struct nfs4_file *fp,struct dentry *child;__be32 err; -/* parent may already be locked, and it may get unlocked by -* this call, but that is safe. -*/ err =nfsd_lookup_dentry (open->op_rqstp, parent, open->op_fname, open->op_fnamelen, &exp, &child);
fs/nfsd/nfsfh.c +19 -0
@@ -670,6 +670,25 @@ void fh_fill_post_attrs(struct svc_fh *fhp)nfsd4_change_attribute (&fhp->fh_post_attr, inode); } +/** +* fh_fill_both_attrs - Fill pre-op and post-op attributes +* @fhp: file handle to be updated +* +* This is used when the directory wasn't changed, but wcc attributes +* are needed anyway. +*/ +void fh_fill_both_attrs (struct svc_fh *fhp) +{ +fh_fill_post_attrs (fhp); +if (!fhp->fh_post_saved) +return ; + fhp->fh_pre_change = fhp->fh_post_change; + fhp->fh_pre_mtime = fhp->fh_post_attr.mtime; + fhp->fh_pre_ctime = fhp->fh_post_attr.ctime; + fhp->fh_pre_size = fhp->fh_post_attr.size; + fhp->fh_pre_saved = true; +} +/* * Release a file handle. */
fs/nfsd/nfsfh.h +1 -1
@@ -322,7 +322,7 @@ static inline u64 nfsd4_change_attribute(struct kstat *stat,extern void fh_fill_pre_attrs (struct svc_fh *fhp);extern void fh_fill_post_attrs (struct svc_fh *fhp); - +extern void fh_fill_both_attrs (struct svc_fh *fhp);/* * Lock a file handle/inode
fs/nfsd/vfs.c +14 -20
@@ -198,27 +198,13 @@ nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp, goto out_nfserr; } }else { -/* -* In the nfsd4_open() case, this may be held across -* subsequent open and delegation acquisition which may -* need to take the child's i_mutex: -*/ -fh_lock_nested (fhp,I_MUTEX_PARENT ); - dentry =lookup_one_len (name, dparent, len); + dentry =lookup_one_len_unlocked (name, dparent, len); host_err =PTR_ERR (dentry);if (IS_ERR (dentry)) goto out_nfserr;if (nfsd_mountpoint (dentry, exp)) { -/* -* We don't need the i_mutex after all. It's -* still possible we could open this (regular -* files can be mountpoints too), but the -* i_mutex is just there to prevent renames of -* something that we might be about to delegate, -* and a mountpoint won't be renamed: -*/ -fh_unlock (fhp); -if ((host_err =nfsd_cross_mnt (rqstp, &dentry, &exp))) { + host_err =nfsd_cross_mnt (rqstp, &dentry, &exp); +if (host_err) {dput (dentry); goto out_nfserr; }
@@ -233,7 +219,15 @@ nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp,return nfserrno (host_err); } -/* +/** +* nfsd_lookup - look up a single path component for nfsd +* +* @rqstp: the request context +* @fhp: the file handle of the directory +* @name: the component name, or %NULL to look up parent +* @len: length of name to examine +* @resfh: pointer to pre-initialised filehandle to hold result. +* * Look up one component of a pathname. * N.B. After this call _both_ fhp and resfh need an fh_put *
@@ -243,11 +237,11 @@ nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp,* returned. Otherwise the covered directory is returned. * NOTE: this mountpoint crossing is not supported properly by all * clients and is explicitly disallowed for NFSv3 -* NeilBrown <[email protected]> +* */ __be32 nfsd_lookup (struct svc_rqst *rqstp,struct svc_fh *fhp,const char *name, -unsigned int len,struct svc_fh *resfh) +unsigned int len,struct svc_fh *resfh) {struct svc_export *exp;struct dentry *dentry;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 620/770 NFSD: use explicit lock/unlock for directory ops
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: NeilBrown <[email protected]>
[ Upstream commit debf16f0c671cb8db154a9ebcd6014cfff683b80 ]
When creating or unlinking a name in a directory use explicit inode_lock_nested() instead of fh_lock(), and explicit calls to fh_fill_pre_attrs() and fh_fill_post_attrs(). This is already done for renames, with lock_rename() as the explicit locking.
Also move the 'fill' calls closer to the operation that might change the attributes. This way they are avoided on some error paths.
For the v2-only code in nfsproc.c, the fill calls are not replaced as they aren't needed.
Making the locking explicit will simplify proposed future changes to locking for directories. It also makes it easily visible exactly where pre/post attributes are used - not all callers of fh_lock() actually need the pre/post attributes.
--- fs/nfsd/nfs3proc.c | 6 ++++-- fs/nfsd/nfs4proc.c | 6 ++++-- fs/nfsd/nfsproc.c | 5 ++--- fs/nfsd/vfs.c | 36 ++++++++++++++++++++++++++---------- 4 files changed, 36 insertions(+), 17 deletions(-)
fs/nfsd/nfs3proc.c +4 -2
@@ -260,7 +260,7 @@ nfsd3_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,if (host_err)return nfserrno (host_err); -fh_lock_nested (fhp,I_MUTEX_PARENT ); +inode_lock_nested (inode,I_MUTEX_PARENT ); child =lookup_one_len (argp->name, parent, argp->len);if (IS_ERR (child)) {
@@ -318,11 +318,13 @@ nfsd3_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,if (!IS_POSIXACL (inode)) iap->ia_mode &= ~current_umask (); +fh_fill_pre_attrs (fhp); host_err =vfs_create (inode, child, iap->ia_mode, true);if (host_err <0 ) { status =nfserrno (host_err); goto out; } +fh_fill_post_attrs (fhp);/* A newly created file already has a file size of zero. */ if ((iap->ia_valid &ATTR_SIZE ) && (iap->ia_size ==0 ))
@@ -340,7 +342,7 @@ nfsd3_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp, status =nfsd_create_setattr (rqstp, fhp, resfhp, &attrs); out: -fh_unlock (fhp); +inode_unlock (inode);if (child && !IS_ERR (child))dput (child);fh_drop_write (fhp);
fs/nfsd/nfs4proc.c +4 -2
@@ -264,7 +264,7 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,if (is_create_with_attrs (open))nfsd4_acl_to_attr (NF4REG , open->op_acl, &attrs); -fh_lock_nested (fhp,I_MUTEX_PARENT ); +inode_lock_nested (inode,I_MUTEX_PARENT ); child =lookup_one_len (open->op_fname, parent, open->op_fnamelen);if (IS_ERR (child)) {
@@ -348,10 +348,12 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,if (!IS_POSIXACL (inode)) iap->ia_mode &= ~current_umask (); +fh_fill_pre_attrs (fhp); status =nfsd4_vfs_create (fhp, child, open);if (status != nfs_ok) goto out; open->op_created = true; +fh_fill_post_attrs (fhp);/* A newly created file already has a file size of zero. */ if ((iap->ia_valid &ATTR_SIZE ) && (iap->ia_size ==0 ))
@@ -373,7 +375,7 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,if (attrs.na_aclerr) open->op_bmval[0 ] &= ~FATTR4_WORD0_ACL ; out: -fh_unlock (fhp); +inode_unlock (inode);nfsd_attrs_free (&attrs);if (child && !IS_ERR (child))dput (child);
fs/nfsd/nfsproc.c +2 -3
@@ -291,7 +291,7 @@ nfsd_proc_create(struct svc_rqst *rqstp) goto done; } -fh_lock_nested (dirfhp,I_MUTEX_PARENT ); +inode_lock_nested (dirfhp->fh_dentry->d_inode,I_MUTEX_PARENT ); dchild =lookup_one_len (argp->name, dirfhp->fh_dentry, argp->len);if (IS_ERR (dchild)) { resp->status =nfserrno (PTR_ERR (dchild));
@@ -407,8 +407,7 @@ nfsd_proc_create(struct svc_rqst *rqstp) } out_unlock: -/* We don't really need to unlock, as fh_put does it. */ -fh_unlock (dirfhp); +inode_unlock (dirfhp->fh_dentry->d_inode);fh_drop_write (dirfhp); done:fh_put (dirfhp);
fs/nfsd/vfs.c +26 -10
@@ -1386,7 +1386,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,if (host_err)return nfserrno (host_err); -fh_lock_nested (fhp,I_MUTEX_PARENT ); +inode_lock_nested (dentry->d_inode,I_MUTEX_PARENT ); dchild =lookup_one_len (fname, dentry, flen); host_err =PTR_ERR (dchild);if (IS_ERR (dchild)) {
@@ -1401,10 +1401,12 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,dput (dchild);if (err) goto out_unlock; +fh_fill_pre_attrs (fhp); err =nfsd_create_locked (rqstp, fhp, fname, flen, attrs, type, rdev, resfhp); +fh_fill_post_attrs (fhp); out_unlock: -fh_unlock (fhp); +inode_unlock (dentry->d_inode);return err; }
@@ -1487,20 +1489,22 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp, goto out; } -fh_lock (fhp); dentry = fhp->fh_dentry; +inode_lock_nested (dentry->d_inode,I_MUTEX_PARENT ); dnew =lookup_one_len (fname, dentry, flen);if (IS_ERR (dnew)) { err =nfserrno (PTR_ERR (dnew)); -fh_unlock (fhp); +inode_unlock (dentry->d_inode); goto out_drop_write; } +fh_fill_pre_attrs (fhp); host_err =vfs_symlink (d_inode (dentry), dnew, path); err =nfserrno (host_err); cerr =fh_compose (resfhp, fhp->fh_export, dnew, fhp);if (!err)nfsd_create_setattr (rqstp, fhp, resfhp, attrs); -fh_unlock (fhp); +fh_fill_post_attrs (fhp); +inode_unlock (dentry->d_inode);if (!err) err =nfserrno (commit_metadata (fhp));dput (dnew);
@@ -1546,9 +1550,9 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, goto out; } -fh_lock_nested (ffhp,I_MUTEX_PARENT ); ddir = ffhp->fh_dentry; dirp =d_inode (ddir); +inode_lock_nested (dirp,I_MUTEX_PARENT ); dnew =lookup_one_len (name, ddir, len);if (IS_ERR (dnew)) {
@@ -1561,8 +1565,18 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, err = nfserr_noent;if (d_really_is_negative (dold)) goto out_dput; +<<<<<<< current host_err =vfs_link (dold, dirp, dnew,NULL );fh_unlock (ffhp); +||||||| constructed merge base + host_err =vfs_link (dold, &init_user_ns, dirp, dnew,NULL ); +fh_unlock (ffhp); +======= +fh_fill_pre_attrs (ffhp); + host_err =vfs_link (dold, &init_user_ns, dirp, dnew,NULL ); +fh_fill_post_attrs (ffhp); +inode_unlock (dirp); +>>>>>>> patched if (!host_err) { err =nfserrno (commit_metadata (ffhp));if (!err)
@@ -1582,7 +1596,7 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, out_dput:dput (dnew); out_unlock: -fh_unlock (ffhp); +inode_unlock (dirp); goto out_drop_write; }
@@ -1755,9 +1769,9 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,if (host_err) goto out_nfserr; -fh_lock_nested (fhp,I_MUTEX_PARENT ); dentry = fhp->fh_dentry; dirp =d_inode (dentry); +inode_lock_nested (dirp,I_MUTEX_PARENT ); rdentry =lookup_one_len (fname, dentry, flen); host_err =PTR_ERR (rdentry);
@@ -1775,6 +1789,7 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,if (!type) type =d_inode (rdentry)->i_mode &S_IFMT ; +fh_fill_pre_attrs (fhp);if (type !=S_IFDIR ) {if (rdentry->d_sb->s_export_op->flags &EXPORT_OP_CLOSE_BEFORE_UNLINK )nfsd_close_cached_files (rdentry);
@@ -1782,8 +1797,9 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, }else { host_err =vfs_rmdir (dirp, rdentry); } +fh_fill_post_attrs (fhp); -fh_unlock (fhp); +inode_unlock (dirp);if (!host_err) host_err =commit_metadata (fhp);dput (rdentry);
@@ -1806,7 +1822,7 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, out:return err; out_unlock: -fh_unlock (fhp); +inode_unlock (dirp); goto out_drop_write; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 621/770 NFSD: use (un)lock_inode instead of fh_(un)lock for file operations
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: NeilBrown <[email protected]>
[ Upstream commit bb4d53d66e4b8c8b8e5634802262e53851a2d2db ]
When locking a file to access ACLs and xattrs etc, use explicit locking with inode_lock() instead of fh_lock(). This means that the calls to fh_fill_pre/post_attr() are also explicit which improves readability and allows us to place them only where they are needed. Only the xattr calls need pre/post information.
When locking a file we don't need I_MUTEX_PARENT as the file is not a parent of anything, so we can use inode_lock() directly rather than the inode_lock_nested() call that fh_lock() uses.
--- fs/nfsd/nfs2acl.c | 6 +++--- fs/nfsd/nfs3acl.c | 4 ++-- fs/nfsd/nfs4state.c | 9 +++++---- fs/nfsd/vfs.c | 44 +++++++++++++++++++++----------------------- 4 files changed, 31 insertions(+), 32 deletions(-)
fs/nfsd/nfs2acl.c +3 -3
@@ -111,7 +111,7 @@ static __be32 nfsacld_proc_setacl(struct svc_rqst *rqstp)if (error) goto out_errno; -fh_lock (fh); +inode_lock (inode); error =set_posix_acl (inode,ACL_TYPE_ACCESS , argp->acl_access);if (error)
@@ -120,7 +120,7 @@ static __be32 nfsacld_proc_setacl(struct svc_rqst *rqstp)if (error) goto out_drop_lock; -fh_unlock (fh); +inode_unlock (inode);fh_drop_write (fh);
@@ -134,7 +134,7 @@ static __be32 nfsacld_proc_setacl(struct svc_rqst *rqstp)return rpc_success; out_drop_lock: -fh_unlock (fh); +inode_unlock (inode);fh_drop_write (fh); out_errno: resp->status =nfserrno (error);
fs/nfsd/nfs3acl.c +2 -2
@@ -101,7 +101,7 @@ static __be32 nfsd3_proc_setacl(struct svc_rqst *rqstp)if (error) goto out_errno; -fh_lock (fh); +inode_lock (inode); error =set_posix_acl (inode,ACL_TYPE_ACCESS , argp->acl_access);if (error)
@@ -109,7 +109,7 @@ static __be32 nfsd3_proc_setacl(struct svc_rqst *rqstp) error =set_posix_acl (inode,ACL_TYPE_DEFAULT , argp->acl_default); out_drop_lock: -fh_unlock (fh); +inode_unlock (inode);fh_drop_write (fh); out_errno: resp->status =nfserrno (error);
fs/nfsd/nfs4state.c +5 -4
@@ -7429,21 +7429,22 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,static __be32 nfsd_test_lock (struct svc_rqst *rqstp,struct svc_fh *fhp,struct file_lock *lock) {struct nfsd_file *nf; +struct inode *inode;__be32 err; err =nfsd_file_acquire (rqstp, fhp,NFSD_MAY_READ , &nf);if (err)return err; -fh_lock (fhp);/* to block new leases till after test_lock: */ - err =nfserrno (nfsd_open_break_lease (fhp->fh_dentry->d_inode, -NFSD_MAY_READ )); + inode = fhp->fh_dentry->d_inode; +inode_lock (inode);/* to block new leases till after test_lock: */ + err =nfserrno (nfsd_open_break_lease (inode,NFSD_MAY_READ ));if (err) goto out; lock->fl_file = nf->nf_file; err =nfserrno (vfs_test_lock (nf->nf_file, lock)); lock->fl_file =NULL ; out: -fh_unlock (fhp); +inode_unlock (inode);nfsd_file_put (nf);return err; }
fs/nfsd/vfs.c +21 -23
89 lines not on this page · raw message
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 622/770 NFSD: discard fh_locked flag and fh_lock/fh_unlock
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: NeilBrown <[email protected]>
[ Upstream commit dd8dd403d7b223cc77ee89d8d09caf045e90e648 ]
As all inode locking is now fully balanced, fh_put() does not need to call fh_unlock().fh_lock() and fh_unlock() are no longer used, so discard them. These are the only real users of ->fh_locked, so discard that too.
--- fs/nfsd/nfsfh.c | 3 +-- fs/nfsd/nfsfh.h | 56 ++++--------------------------------------------- fs/nfsd/vfs.c | 17 +-------------- 3 files changed, 6 insertions(+), 70 deletions(-)
fs/nfsd/nfsfh.c +1 -2
@@ -547,7 +547,7 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,if (ref_fh == fhp)fh_put (ref_fh); -if (fhp->fh_locked || fhp->fh_dentry) { +if (fhp->fh_dentry) {printk (KERN_ERR "fh_compose: fh %pd2 not initialized!\n" , dentry); }
@@ -698,7 +698,6 @@ fh_put(struct svc_fh *fhp)struct dentry * dentry = fhp->fh_dentry;struct svc_export * exp = fhp->fh_export;if (dentry) { -fh_unlock (fhp); fhp->fh_dentry =NULL ;dput (dentry);fh_clear_pre_post_attrs (fhp);
fs/nfsd/nfsfh.h +4 -52
84 lines not on this page · raw message
fs/nfsd/vfs.c +1 -16
@@ -1282,13 +1282,6 @@ nfsd_create_locked(struct svc_rqst *rqstp, struct svc_fh *fhp, dirp =d_inode (dentry); dchild =dget (resfhp->fh_dentry); -if (!fhp->fh_locked) { -WARN_ONCE (1 ,"nfsd_create: parent %pd2 not locked!\n" , - dentry); - err = nfserr_io; - goto out; - } - err =nfsd_permission (rqstp, fhp->fh_export, dentry,NFSD_MAY_CREATE );if (err) goto out;
@@ -1656,10 +1649,7 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, goto out; } -/* cannot use fh_lock as we need deadlock protective ordering -* so do it by hand */ trap =lock_rename (tdentry, fdentry); - ffhp->fh_locked = tfhp->fh_locked = true;fh_fill_pre_attrs (ffhp);fh_fill_pre_attrs (tfhp);
@@ -1707,17 +1697,12 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,dput (odentry); out_nfserr: err =nfserrno (host_err); -/* -* We cannot rely on fh_unlock on the two filehandles, -* as that would do the wrong thing if the two directories -* were the same, so again we do it by hand. -*/ +if (!close_cached) {fh_fill_post_attrs (ffhp);fh_fill_post_attrs (tfhp); }unlock_rename (tdentry, fdentry); - ffhp->fh_locked = tfhp->fh_locked = false;fh_drop_write (ffhp);/*
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 623/770 lockd: detect and reject lock arguments that overflow
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeff Layton <[email protected]>
[ Upstream commit 6930bcbfb6ceda63e298c6af6d733ecdf6bd4cde ]
lockd doesn't currently vet the start and length in nlm4 requests like it should, and can end up generating lock requests with arguments that overflow when passed to the filesystem.
The NLM4 protocol uses unsigned 64-bit arguments for both start and length, whereas struct file_lock tracks the start and end as loff_t values. By the time we get around to calling nlm4svc_retrieve_args, we've lost the information that would allow us to determine if there was an overflow.
Start tracking the actual start and len for NLM4 requests in the nlm_lock. In nlm4svc_retrieve_args, vet these values to ensure they won't cause an overflow, and return NLM4_FBIG if they do.
--- fs/lockd/svc4proc.c | 8 ++++++++ fs/lockd/xdr4.c | 19 ++----------------- include/linux/lockd/xdr.h | 2 ++ 3 files changed, 12 insertions(+), 17 deletions(-)
fs/lockd/svc4proc.c +8 -0
@@ -32,6 +32,10 @@ nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,if (!nlmsvc_ops)return nlm_lck_denied_nolocks; +if (lock->lock_start >OFFSET_MAX || + (lock->lock_len && ((lock->lock_len -1 ) > (OFFSET_MAX - lock->lock_start)))) +return nlm4_fbig; +/* Obtain host handle */ if (!(host =nlmsvc_lookup_host (rqstp, lock->caller, lock->len)) || (argp->monitor &&nsm_monitor (host) <0 ))
@@ -50,6 +54,10 @@ 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[mode]; lock->fl.fl_pid = current->tgid; + lock->fl.fl_start = (loff_t )lock->lock_start; + lock->fl.fl_end = lock->lock_len ? + (loff_t)(lock->lock_start + lock->lock_len -1 ) : +OFFSET_MAX ; lock->fl.fl_lmops = &nlmsvc_lock_operations;nlmsvc_locks_init_private (&lock->fl, host, (pid_t )lock->svid);if (!lock->fl.fl_owner) {
fs/lockd/xdr4.c +2 -17
@@ -20,13 +20,6 @@#include "svcxdr.h" -static inline loff_t -s64_to_loff_t (__s64 offset) -{ -return (loff_t )offset; -} - -static inline s64 loff_t_to_s64 (loff_t offset) {
@@ -70,8 +63,6 @@ static bool svcxdr_decode_lock(struct xdr_stream *xdr, struct nlm_lock *lock) { struct file_lock *fl = &lock->fl; -u64 len, start; -s64 end;if (!svcxdr_decode_string (xdr, &lock->caller, &lock->len))return false;
@@ -81,20 +72,14 @@ svcxdr_decode_lock(struct xdr_stream *xdr, struct nlm_lock *lock)return false;if (xdr_stream_decode_u32 (xdr, &lock->svid) <0 )return false; -if (xdr_stream_decode_u64 (xdr, &start) <0 ) +if (xdr_stream_decode_u64 (xdr, &lock->lock_start) <0 )return false; -if (xdr_stream_decode_u64 (xdr, &len) <0 ) +if (xdr_stream_decode_u64 (xdr, &lock->lock_len) <0 )return false;locks_init_lock (fl); fl->fl_flags =FL_POSIX ; fl->fl_type =F_RDLCK ; - end = start + len -1 ; - fl->fl_start =s64_to_loff_t (start); -if (len ==0 || end <0 ) - fl->fl_end =OFFSET_MAX ; -else - fl->fl_end =s64_to_loff_t (end);return true; }
include/linux/lockd/xdr.h +2 -0
@@ -41,6 +41,8 @@ struct nlm_lock {struct nfs_fh fh;struct xdr_netobj oh;u32 svid; +u64 lock_start; +u64 lock_len;struct file_lock fl; };
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 624/770 NFSD: fix regression with setting ACLs.
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: NeilBrown <[email protected]>
[ Upstream commit 00801cd92d91e94aa04d687f9bb9a9104e7c3d46 ]
A recent patch moved ACL setting into nfsd_setattr(). Unfortunately it didn't work as nfsd_setattr() aborts early if iap->ia_valid is 0.
Remove this test, and instead avoid calling notify_change() when ia_valid is 0.
This means that nfsd_setattr() will now *always* lock the inode. Previously it didn't if only a ATTR_MODE change was requested on a symlink (see Commit 15b7a1b86d66 ("[PATCH] knfsd: fix setattr-on-symlink error return")). I don't think this change really matters.
--- fs/nfsd/vfs.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-)
fs/nfsd/vfs.c +9 -10
@@ -299,6 +299,10 @@ commit_metadata(struct svc_fh *fhp)static void nfsd_sanitize_attrs (struct inode *inode,struct iattr *iap) { +/* Ignore mode updates on symlinks */ +if (S_ISLNK (inode->i_mode)) + iap->ia_valid &= ~ATTR_MODE ; +/* sanitize the mode change */ if (iap->ia_valid &ATTR_MODE ) { iap->ia_mode &=S_IALLUGO ;
@@ -366,7 +370,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp,int accmode =NFSD_MAY_SATTR ;umode_t ftype =0 ;__be32 err; -int host_err; +int host_err =0 ;bool get_write_count;bool size_change = (iap->ia_valid &ATTR_SIZE );
@@ -404,13 +408,6 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, dentry = fhp->fh_dentry; inode =d_inode (dentry); -/* Ignore any mode updates on symlinks */ -if (S_ISLNK (inode->i_mode)) - iap->ia_valid &= ~ATTR_MODE ; - -if (!iap->ia_valid) -return 0 ; -nfsd_sanitize_attrs (inode, iap);if (check_guard && guardtime != inode->i_ctime.tv_sec)
@@ -461,8 +458,10 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, goto out_unlock; } - iap->ia_valid |=ATTR_CTIME ; - host_err =notify_change (dentry, iap,NULL ); +if (iap->ia_valid) { + iap->ia_valid |=ATTR_CTIME ; + host_err =notify_change (dentry, iap,NULL ); + } out_unlock:if (attr->na_seclabel && attr->na_seclabel->len)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 625/770 nfsd_splice_actor(): handle compound pages
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Al Viro <[email protected]>
[ Upstream commit bfbfb6182ad1d7d184b16f25165faad879147f79 ]
pipe_buffer might refer to a compound page (and contain more than a PAGE_SIZE worth of data). Theoretically it had been possible since way back, but nfsd_splice_actor() hadn't run into that until copy_page_to_iter() change. Fortunately, the only thing that changes for compound pages is that we need to stuff each relevant subpage in and convert the offset into offset in the first subpage.
--- fs/nfsd/vfs.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
fs/nfsd/vfs.c +9 -4
@@ -862,10 +862,15 @@ nfsd_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf, struct splice_desc *sd) {struct svc_rqst *rqstp = sd->u.data; - -svc_rqst_replace_page (rqstp, buf->page); -if (rqstp->rq_res.page_len ==0 ) - rqstp->rq_res.page_base = buf->offset; +struct page *page = buf->page;// may be a compound one +unsigned offset = buf->offset; +int i; + + page += offset /PAGE_SIZE ; +for (i = sd->len; i >0 ; i -=PAGE_SIZE ) +svc_rqst_replace_page (rqstp, page++); +if (rqstp->rq_res.page_len ==0 )// first call + rqstp->rq_res.page_base = offset %PAGE_SIZE ; rqstp->rq_res.page_len += sd->len;return sd->len; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 626/770 NFSD: move from strlcpy with unused retval to strscpy
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wolfram Sang <[email protected]>
[ Upstream commit 72f78ae00a8e5d7abe13abac8305a300f6afd74b ]
Follow the advice of the below link and prefer 'strscpy' in this subsystem. Conversion is 1:1 because the return value is not used. Generated by a coccinelle script.
--- fs/nfsd/nfs4idmap.c | 8 ++++---- fs/nfsd/nfs4proc.c | 2 +- fs/nfsd/nfssvc.c | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-)
fs/nfsd/nfs4idmap.c +4 -4
@@ -82,8 +82,8 @@ ent_init(struct cache_head *cnew, struct cache_head *citm) new->id = itm->id; new->type = itm->type; -strlcpy (new->name, itm->name,sizeof (new->name)); -strlcpy (new->authname, itm->authname,sizeof (new->authname)); +strscpy (new->name, itm->name,sizeof (new->name)); +strscpy (new->authname, itm->authname,sizeof (new->authname)); } static void
@@ -548,7 +548,7 @@ idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelenreturn nfserr_badowner;memcpy (key.name, name, namelen); key.name[namelen] ='\0' ; -strlcpy (key.authname,rqst_authname (rqstp),sizeof (key.authname)); +strscpy (key.authname,rqst_authname (rqstp),sizeof (key.authname)); ret =idmap_lookup (rqstp, nametoid_lookup, &key, nn->nametoid_cache, &item);if (ret == -ENOENT )return nfserr_badowner;
@@ -584,7 +584,7 @@ static __be32 idmap_id_to_name(struct xdr_stream *xdr,int ret;struct nfsd_net *nn =net_generic (SVC_NET (rqstp), nfsd_net_id); -strlcpy (key.authname,rqst_authname (rqstp),sizeof (key.authname)); +strscpy (key.authname,rqst_authname (rqstp),sizeof (key.authname)); ret =idmap_lookup (rqstp, idtoname_lookup, &key, nn->idtoname_cache, &item);if (ret == -ENOENT )return encode_ascii_id (xdr, id);
fs/nfsd/nfs4proc.c +1 -1
@@ -1345,7 +1345,7 @@ static __be32 nfsd4_ssc_setup_dul(struct nfsd_net *nn, char *ipaddr,return 0 ; }if (work) { -strlcpy (work->nsui_ipaddr, ipaddr,sizeof (work->nsui_ipaddr) -1 ); +strscpy (work->nsui_ipaddr, ipaddr,sizeof (work->nsui_ipaddr) -1 );refcount_set (&work->nsui_refcnt,2 ); work->nsui_busy = true;list_add_tail (&work->nsui_list, &nn->nfsd_ssc_mount_list);
fs/nfsd/nfssvc.c +1 -1
@@ -799,7 +799,7 @@ nfsd_svc(int nrservs, struct net *net, const struct cred *cred)if (nrservs ==0 && nn->nfsd_serv ==NULL ) goto out; -strlcpy (nn->nfsd_name,utsname ()->nodename, +strscpy (nn->nfsd_name,utsname ()->nodename,sizeof (nn->nfsd_name)); error =nfsd_create_serv (net);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 627/770 lockd: move from strlcpy with unused retval to strscpy
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wolfram Sang <[email protected]>
[ Upstream commit 97f8e62572555f8ad578d7b1739ba64d5d2cac0f ]
Follow the advice of the below link and prefer 'strscpy' in this subsystem. Conversion is 1:1 because the return value is not used. Generated by a coccinelle script.
--- fs/lockd/host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/lockd/host.c +1 -1
@@ -164,7 +164,7 @@ static struct nlm_host *nlm_alloc_host(struct nlm_lookup_host_info *ni, host->h_addrbuf = nsm->sm_addrbuf; host->net = ni->net; host->h_cred =get_cred (ni->cred); -strlcpy (host->nodename,utsname ()->nodename,sizeof (host->nodename)); +strscpy (host->nodename,utsname ()->nodename,sizeof (host->nodename)); out:return host;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 628/770 NFSD enforce filehandle check for source file in COPY
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Olga Kornievskaia <[email protected]>
[ Upstream commit 754035ff79a14886e68c0c9f6fa80adb21f12b53 ]
If the passed in filehandle for the source file in the COPY operation is not a regular file, the server MUST return NFS4ERR_WRONG_TYPE.
--- fs/nfsd/nfs4proc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
fs/nfsd/nfs4proc.c +7 -1
@@ -1758,7 +1758,13 @@ static int nfsd4_do_async_copy(void *data) filp =nfs42_ssc_open (copy->ss_mnt, ©->c_fh, ©->stateid);if (IS_ERR (filp)) { - nfserr = nfserr_offload_denied; +switch (PTR_ERR (filp)) { +case -EBADF : + nfserr = nfserr_wrong_type; +break ; +default : + nfserr = nfserr_offload_denied; + }/* ss_mnt will be unmounted by the laundromat */ goto do_callback; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 629/770 NFSD: remove redundant variable status
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jinpeng Cui <[email protected]>
[ Upstream commit 4ab3442ca384a02abf8b1f2b3449a6c547851873 ]
Return value directly from fh_verify() do_open_permission() exp_pseudoroot() instead of getting value from redundant variable status.
--- fs/nfsd/nfs4proc.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-)
fs/nfsd/nfs4proc.c +4 -12
@@ -141,7 +141,6 @@ fh_dup2(struct svc_fh *dst, struct svc_fh *src)static __be32 do_open_permission (struct svc_rqst *rqstp,struct svc_fh *current_fh,struct nfsd4_open *open,int accmode) { -__be32 status;if (open->op_truncate && !(open->op_share_access &NFS4_SHARE_ACCESS_WRITE ))
@@ -156,9 +155,7 @@ do_open_permission(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsif (open->op_share_deny &NFS4_SHARE_DENY_READ ) accmode |=NFSD_MAY_WRITE ; - status =fh_verify (rqstp, current_fh,S_IFREG , accmode); - -return status; +return fh_verify (rqstp, current_fh,S_IFREG , accmode); }static __be32 nfsd_check_obj_isreg (struct svc_fh *fh)
@@ -454,7 +451,6 @@ static __be32 do_open_fhandle(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_open *open) { struct svc_fh *current_fh = &cstate->current_fh; -__be32 status;int accmode =0 ;/* We don't know the target directory, and therefore can not
@@ -479,9 +475,7 @@ do_open_fhandle(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, strif (open->op_claim_type ==NFS4_OPEN_CLAIM_DELEG_CUR_FH ) accmode =NFSD_MAY_OWNER_OVERRIDE ; - status =do_open_permission (rqstp, current_fh, open, accmode); - -return status; +return do_open_permission (rqstp, current_fh, open, accmode); } static void
@@ -668,11 +662,9 @@ static __be32 nfsd4_putrootfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, union nfsd4_op_u *u) { - __be32 status; - fh_put(&cstate->current_fh); - status =exp_pseudoroot (rqstp, &cstate->current_fh); -return status; + +return exp_pseudoroot (rqstp, &cstate->current_fh); } static __be32
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 630/770 nfsd: Avoid some useless tests
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christophe JAILLET <[email protected]>
[ Upstream commit d44899b8bb0b919f923186c616a84f0e70e04772 ]
memdup_user() can't return NULL, so there is no point for checking for it.
Simplify some tests accordingly.
--- fs/nfsd/nfs4recover.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
fs/nfsd/nfs4recover.c +3 -3
@@ -807,7 +807,7 @@ __cld_pipe_inprogress_downcall(const struct cld_msg_v2 __user *cmsg,if (get_user (namelen, &ci->cc_name.cn_len))return -EFAULT ; name.data =memdup_user (&ci->cc_name.cn_id, namelen); -if (IS_ERR_OR_NULL (name.data)) +if (IS_ERR (name.data))return -EFAULT ; name.len = namelen;get_user (princhashlen, &ci->cc_princhash.cp_len);
@@ -815,7 +815,7 @@ __cld_pipe_inprogress_downcall(const struct cld_msg_v2 __user *cmsg, princhash.data =memdup_user ( &ci->cc_princhash.cp_data, princhashlen); -if (IS_ERR_OR_NULL (princhash.data)) { +if (IS_ERR (princhash.data)) {kfree (name.data);return -EFAULT ; }
@@ -829,7 +829,7 @@ __cld_pipe_inprogress_downcall(const struct cld_msg_v2 __user *cmsg,if (get_user (namelen, &cnm->cn_len))return -EFAULT ; name.data =memdup_user (&cnm->cn_id, namelen); -if (IS_ERR_OR_NULL (name.data)) +if (IS_ERR (name.data))return -EFAULT ; name.len = namelen; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 631/770 nfsd: Propagate some error code returned by memdup_user()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christophe JAILLET <[email protected]>
[ Upstream commit 30a30fcc3fc1ad4c5d017c9fcb75dc8f59e7bdad ]
Propagate the error code returned by memdup_user() instead of a hard coded -EFAULT.
--- fs/nfsd/nfs4recover.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
fs/nfsd/nfs4recover.c +3 -3
@@ -808,7 +808,7 @@ __cld_pipe_inprogress_downcall(const struct cld_msg_v2 __user *cmsg,return -EFAULT ; name.data =memdup_user (&ci->cc_name.cn_id, namelen);if (IS_ERR (name.data)) -return -EFAULT ; +return PTR_ERR (name.data); name.len = namelen;get_user (princhashlen, &ci->cc_princhash.cp_len);if (princhashlen >0 ) {
@@ -817,7 +817,7 @@ __cld_pipe_inprogress_downcall(const struct cld_msg_v2 __user *cmsg, princhashlen);if (IS_ERR (princhash.data)) {kfree (name.data); -return -EFAULT ; +return PTR_ERR (princhash.data); } princhash.len = princhashlen; }else
@@ -830,7 +830,7 @@ __cld_pipe_inprogress_downcall(const struct cld_msg_v2 __user *cmsg,return -EFAULT ; name.data =memdup_user (&cnm->cn_id, namelen);if (IS_ERR (name.data)) -return -EFAULT ; +return PTR_ERR (name.data); name.len = namelen; }if (name.len >5 &&memcmp (name.data,"hash:" ,5 ) ==0 ) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 632/770 NFSD: Increase NFSD_MAX_OPS_PER_COMPOUND
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 80e591ce636f3ae6855a0ca26963da1fdd6d4508 ]
When attempting an NFSv4 mount, a Solaris NFSv4 client builds a single large COMPOUND that chains a series of LOOKUPs to get to the pseudo filesystem root directory that is to be mounted. The Linux NFS server's current maximum of 16 operations per NFSv4 COMPOUND is not large enough to ensure that this works for paths that are more than a few components deep.
Since NFSD_MAX_OPS_PER_COMPOUND is mostly a sanity check, and most NFSv4 COMPOUNDS are between 3 and 6 operations (thus they do not trigger any re-allocation of the operation array on the server), increasing this maximum should result in little to no impact.
The ops array can get large now, so allocate it via vmalloc() to help ensure memory fragmentation won't cause an allocation failure.
--- fs/nfsd/nfs4xdr.c | 7 ++++--- fs/nfsd/state.h | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-)
fs/nfsd/nfs4xdr.c +4 -3
@@ -42,6 +42,8 @@#include <linux/sunrpc/svcauth_gss.h> #include <linux/sunrpc/addr.h> #include <linux/xattr.h> +#include <linux/vmalloc.h> +#include <uapi/linux/xattr.h> #include "idmap.h"
@@ -2369,10 +2371,9 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)return true;if (argp->opcnt >ARRAY_SIZE (argp->iops)) { - argp->ops =kzalloc (argp->opcnt *sizeof (*argp->ops),GFP_KERNEL ); + argp->ops =vcalloc (argp->opcnt,sizeof (*argp->ops));if (!argp->ops) { argp->ops = argp->iops; -dprintk ("nfsd: couldn't allocate room for COMPOUND\n" );return false; } }
@@ -5402,7 +5403,7 @@ void nfsd4_release_compoundargs(struct svc_rqst *rqstp)struct nfsd4_compoundargs *args = rqstp->rq_argp;if (args->ops != args->iops) { -kfree (args->ops); +vfree (args->ops); args->ops = args->iops; }while (args->to_free) {
fs/nfsd/state.h +1 -1
@@ -175,7 +175,7 @@ static inline struct nfs4_delegation *delegstateid(struct nfs4_stid *s)/* Maximum number of slots per session. 160 is useful for long haul TCP */ #define NFSD_MAX_SLOTS_PER_SESSION 160/* Maximum number of operations per session compound */ -#define NFSD_MAX_OPS_PER_COMPOUND 16 +#define NFSD_MAX_OPS_PER_COMPOUND 50/* Maximum session per slot cache size */ #define NFSD_SLOT_CACHE_SIZE 2048/* Maximum number of NFSD_SLOT_CACHE_SIZE slots per session */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 633/770 NFSD: Protect against send buffer overflow in NFSv2 READDIR
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 00b4492686e0497fdb924a9d4c8f6f99377e176c ]
Restore the previous limit on the @count argument to prevent a buffer overflow attack.
--- fs/nfsd/nfsproc.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
fs/nfsd/nfsproc.c +2 -3
@@ -567,12 +567,11 @@ static void nfsd_init_dirlist_pages(struct svc_rqst *rqstp,struct xdr_buf *buf = &resp->dirlist;struct xdr_stream *xdr = &resp->xdr; - count =clamp (count, (u32)(XDR_UNIT *2 ),svc_max_payload (rqstp)); -memset (buf,0 ,sizeof (*buf));/* Reserve room for the NULL ptr & eof flag (-2 words) */ - buf->buflen = count -XDR_UNIT *2 ; + buf->buflen =clamp (count, (u32)(XDR_UNIT *2 ), (u32 )PAGE_SIZE ); + buf->buflen -=XDR_UNIT *2 ; buf->pages = rqstp->rq_next_page; rqstp->rq_next_page++;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 634/770 NFSD: Protect against send buffer overflow in NFSv3 READDIR
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 640f87c190e0d1b2a0fcb2ecf6d2cd53b1c41991 ]
Since before the git era, NFSD has conserved the number of pages held by each nfsd thread by combining the RPC receive and send buffers into a single array of pages. This works because there are no cases where an operation needs a large RPC Call message and a large RPC Reply message at the same time.
Once an RPC Call has been received, svc_process() updates svc_rqst::rq_res to describe the part of rq_pages that can be used for constructing the Reply. This means that the send buffer (rq_res) shrinks when the received RPC record containing the RPC Call is large.
A client can force this shrinkage on TCP by sending a correctly- formed RPC Call header contained in an RPC record that is excessively large. The full maximum payload size cannot be constructed in that case.
Thanks to Aleksi Illikainen and Kari Hulkko for uncovering this issue.
--- fs/nfsd/nfs3proc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
fs/nfsd/nfs3proc.c +4 -3
@@ -563,13 +563,14 @@ static void nfsd3_init_dirlist_pages(struct svc_rqst *rqstp, {struct xdr_buf *buf = &resp->dirlist;struct xdr_stream *xdr = &resp->xdr; - - count =clamp (count, (u32)(XDR_UNIT *2 ),svc_max_payload (rqstp)); + unsigned int sendbuf = min_t(unsigned int, rqstp->rq_res.buflen, +svc_max_payload (rqstp));memset (buf,0 ,sizeof (*buf));/* Reserve room for the NULL ptr & eof flag (-2 words) */ - buf->buflen = count -XDR_UNIT *2 ; + buf->buflen =clamp (count, (u32)(XDR_UNIT *2 ), sendbuf); + buf->buflen -=XDR_UNIT *2 ; buf->pages = rqstp->rq_next_page; rqstp->rq_next_page += (buf->buflen +PAGE_SIZE -1 ) >>PAGE_SHIFT ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 635/770 NFSD: Protect against send buffer overflow in NFSv2 READ
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 401bc1f90874280a80b93f23be33a0e7e2d1f912 ]
Since before the git era, NFSD has conserved the number of pages held by each nfsd thread by combining the RPC receive and send buffers into a single array of pages. This works because there are no cases where an operation needs a large RPC Call message and a large RPC Reply at the same time.
Once an RPC Call has been received, svc_process() updates svc_rqst::rq_res to describe the part of rq_pages that can be used for constructing the Reply. This means that the send buffer (rq_res) shrinks when the received RPC record containing the RPC Call is large.
A client can force this shrinkage on TCP by sending a correctly- formed RPC Call header contained in an RPC record that is excessively large. The full maximum payload size cannot be constructed in that case.
--- fs/nfsd/nfsproc.c | 1 + 1 file changed, 1 insertion(+)
fs/nfsd/nfsproc.c +1 -0
@@ -185,6 +185,7 @@ nfsd_proc_read(struct svc_rqst *rqstp) argp->count, argp->offset); argp->count =min_t (u32, argp->count,NFSSVC_MAXBLKSIZE_V2 ); + argp->count =min_t (u32, argp->count, rqstp->rq_res.buflen); v =0 ; len = argp->count;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 636/770 NFSD: Protect against send buffer overflow in NFSv3 READ
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit fa6be9cc6e80ec79892ddf08a8c10cabab9baf38 ]
Since before the git era, NFSD has conserved the number of pages held by each nfsd thread by combining the RPC receive and send buffers into a single array of pages. This works because there are no cases where an operation needs a large RPC Call message and a large RPC Reply at the same time.
Once an RPC Call has been received, svc_process() updates svc_rqst::rq_res to describe the part of rq_pages that can be used for constructing the Reply. This means that the send buffer (rq_res) shrinks when the received RPC record containing the RPC Call is large.
A client can force this shrinkage on TCP by sending a correctly- formed RPC Call header contained in an RPC record that is excessively large. The full maximum payload size cannot be constructed in that case.
--- fs/nfsd/nfs3proc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/nfsd/nfs3proc.c +2 -2
@@ -150,7 +150,6 @@ nfsd3_proc_read(struct svc_rqst *rqstp) {struct nfsd3_readargs *argp = rqstp->rq_argp;struct nfsd3_readres *resp = rqstp->rq_resp; -u32 max_blocksize =svc_max_payload (rqstp);unsigned int len;int v;
@@ -159,7 +158,8 @@ nfsd3_proc_read(struct svc_rqst *rqstp) (unsigned long ) argp->count, (unsigned long long) argp->offset); - argp->count =min_t (u32, argp->count, max_blocksize); + argp->count =min_t (u32, argp->count,svc_max_payload (rqstp)); + argp->count =min_t (u32, argp->count, rqstp->rq_res.buflen);if (argp->offset > (u64 )OFFSET_MAX ) argp->offset = (u64 )OFFSET_MAX ;if (argp->offset + argp->count > (u64 )OFFSET_MAX )
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 637/770 NFSD: drop fname and flen args from nfsd_create_locked()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: NeilBrown <[email protected]>
[ Upstream commit 9558f9304ca1903090fa5d995a3269a8e82804b4 ]
nfsd_create_locked() does not use the "fname" and "flen" arguments, so drop them from declaration and all callers.
--- fs/nfsd/nfsproc.c | 5 ++--- fs/nfsd/vfs.c | 5 ++--- fs/nfsd/vfs.h | 4 ++-- 3 files changed, 6 insertions(+), 8 deletions(-)
fs/nfsd/nfsproc.c +2 -3
@@ -391,9 +391,8 @@ nfsd_proc_create(struct svc_rqst *rqstp) resp->status = nfs_ok;if (!inode) {/* File doesn't exist. Create it and set attrs */ - resp->status =nfsd_create_locked (rqstp, dirfhp, argp->name, - argp->len, &attrs, type, rdev, - newfhp); + resp->status =nfsd_create_locked (rqstp, dirfhp, &attrs, type, + rdev, newfhp); }else if (type ==S_IFREG ) {dprintk ("nfsd: existing %s, valid=%x, size=%ld\n" , argp->name, attr->ia_valid, (long ) attr->ia_size);
fs/nfsd/vfs.c +2 -3
@@ -1273,7 +1273,7 @@ nfsd_check_ignore_resizing(struct iattr *iap)/* The parent directory should already be locked: */ __be32 nfsd_create_locked (struct svc_rqst *rqstp,struct svc_fh *fhp, -char *fname,int flen,struct nfsd_attrs *attrs, +struct nfsd_attrs *attrs,int type,dev_t rdev,struct svc_fh *resfhp) {struct dentry *dentry, *dchild;
@@ -1399,8 +1399,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,if (err) goto out_unlock;fh_fill_pre_attrs (fhp); - err =nfsd_create_locked (rqstp, fhp, fname, flen, attrs, type, - rdev, resfhp); + err =nfsd_create_locked (rqstp, fhp, attrs, type, rdev, resfhp);fh_fill_post_attrs (fhp); out_unlock:inode_unlock (dentry->d_inode);
fs/nfsd/vfs.h +2 -2
@@ -79,8 +79,8 @@ __be32 nfsd4_clone_file_range(struct svc_rqst *rqstp, u64 count, bool sync);#endif /* CONFIG_NFSD_V4 */ __be32 nfsd_create_locked (struct svc_rqst *,struct svc_fh *, -char *name,int len,struct nfsd_attrs *attrs, -int type,dev_t rdev,struct svc_fh *res); +struct nfsd_attrs *attrs,int type,dev_t rdev, +struct svc_fh *res);__be32 nfsd_create (struct svc_rqst *,struct svc_fh *,char *name,int len,struct nfsd_attrs *attrs,int type,dev_t rdev,struct svc_fh *res);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 638/770 NFSD: Fix handling of oversized NFSv4 COMPOUND requests
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 7518a3dc5ea249d4112156ce71b8b184eb786151 ]
If an NFS server returns NFS4ERR_RESOURCE on the first operation in an NFSv4 COMPOUND, there's no way for a client to know where the problem is and then simplify the compound to make forward progress.
So instead, make NFSD process as many operations in an oversized COMPOUND as it can and then return NFS4ERR_RESOURCE on the first operation it did not process.
pynfs NFSv4.0 COMP6 exercises this case, but checks only for the COMPOUND status code, not whether the server has processed any of the operations.
pynfs NFSv4.1 SEQ6 and SEQ7 exercise the NFSv4.1 case, which detects too many operations per COMPOUND by checking against the limits negotiated when the session was created.
--- fs/nfsd/nfs4proc.c | 19 +++++++++++++------ fs/nfsd/nfs4xdr.c | 12 +++--------- fs/nfsd/xdr4.h | 3 ++- 3 files changed, 18 insertions(+), 16 deletions(-)
fs/nfsd/nfs4proc.c +13 -6
@@ -2623,9 +2623,6 @@ nfsd4_proc_compound(struct svc_rqst *rqstp) status = nfserr_minor_vers_mismatch;if (nfsd_minorversion (nn, args->minorversion,NFSD_TEST ) <=0 ) goto out; - status = nfserr_resource; -if (args->opcnt >NFSD_MAX_OPS_PER_COMPOUND ) - goto out; status =nfs41_check_op_ordering (args);if (status) {
@@ -2638,10 +2635,20 @@ nfsd4_proc_compound(struct svc_rqst *rqstp) rqstp->rq_lease_breaker = (void **)&cstate->clp; -trace_nfsd_compound (rqstp, args->opcnt); +trace_nfsd_compound (rqstp, args->client_opcnt);while (!status && resp->opcnt < args->opcnt) { op = &args->ops[resp->opcnt++]; +if (unlikely (resp->opcnt ==NFSD_MAX_OPS_PER_COMPOUND )) { +/* If there are still more operations to process, +* stop here and report NFS4ERR_RESOURCE. */ +if (cstate->minorversion ==0 && + args->client_opcnt > resp->opcnt) { + op->status = nfserr_resource; + goto encode_op; + } + } +/* * The XDR decode routines may have pre-set op->status; * for example, if there is a miscellaneous XDR error
@@ -2717,8 +2724,8 @@ nfsd4_proc_compound(struct svc_rqst *rqstp) status = op->status; } -trace_nfsd_compound_status (args->opcnt, resp->opcnt, status, -nfsd4_op_name (op->opnum)); +trace_nfsd_compound_status (args->client_opcnt, resp->opcnt, + status,nfsd4_op_name (op->opnum));nfsd4_cstate_clear_replay (cstate);nfsd4_increment_op_stats (op->opnum);
fs/nfsd/nfs4xdr.c +3 -9
@@ -2359,16 +2359,10 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)if (xdr_stream_decode_u32 (argp->xdr, &argp->minorversion) <0 )return false; -if (xdr_stream_decode_u32 (argp->xdr, &argp->opcnt) <0 ) +if (xdr_stream_decode_u32 (argp->xdr, &argp->client_opcnt) <0 )return false; - -/* -* NFS4ERR_RESOURCE is a more helpful error than GARBAGE_ARGS -* here, so we return success at the xdr level so that -* nfsd4_proc can handle this is an NFS-level error. -*/ -if (argp->opcnt >NFSD_MAX_OPS_PER_COMPOUND ) -return true; + argp->opcnt =min_t (u32, argp->client_opcnt, +NFSD_MAX_OPS_PER_COMPOUND );if (argp->opcnt >ARRAY_SIZE (argp->iops)) { argp->ops =vcalloc (argp->opcnt,sizeof (*argp->ops));
fs/nfsd/xdr4.h +2 -1
@@ -717,9 +717,10 @@ struct nfsd4_compoundargs {struct svcxdr_tmpbuf *to_free;struct svc_rqst *rqstp; -u32 taglen;char * tag; +u32 taglen;u32 minorversion; +u32 client_opcnt;u32 opcnt;struct nfsd4_op *ops;struct nfsd4_op iops[8 ];
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 639/770 nfsd: clean up mounted_on_fileid handling
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeff Layton <[email protected]>
[ Upstream commit 6106d9119b6599fa23dc556b429d887b4c2d9f62 ]
We only need the inode number for this, not a full rack of attributes. Rename this function make it take a pointer to a u64 instead of struct kstat, and change it to just request STATX_INO.
--- fs/nfsd/nfs4xdr.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-)
fs/nfsd/nfs4xdr.c +9 -7
@@ -2769,9 +2769,10 @@ static __be32 fattr_handle_absent_fs(u32 *bmval0, u32 *bmval1, u32 *bmval2, u32 } -static int get_parent_attributes (struct svc_export *exp,struct kstat *stat) +static int nfsd4_get_mounted_on_ino (struct svc_export *exp,u64 *pino) {struct path path = exp->ex_path; +struct kstat stat;int err;path_get (&path);
@@ -2779,8 +2780,10 @@ static int get_parent_attributes(struct svc_export *exp, struct kstat *stat)if (path.dentry != path.mnt->mnt_root)break ; } - err =vfs_getattr (&path, stat,STATX_BASIC_STATS ,AT_STATX_SYNC_AS_STAT ); + err =vfs_getattr (&path, &stat,STATX_INO ,AT_STATX_SYNC_AS_STAT );path_put (&path); +if (!err) + *pino = stat.ino;return err; }
@@ -3277,22 +3280,21 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp, *p++ =cpu_to_be32 (stat.btime.tv_nsec); }if (bmval1 &FATTR4_WORD1_MOUNTED_ON_FILEID ) { -struct kstat parent_stat;u64 ino = stat.ino; p =xdr_reserve_space (xdr,8 );if (!p) goto out_resource;/* -* Get parent's attributes if not ignoring crossmount -* and this is the root of a cross-mounted filesystem. +* Get ino of mountpoint in parent filesystem, if not ignoring +* crossmount and this is the root of a cross-mounted +* filesystem. */ if (ignore_crossmnt ==0 && dentry == exp->ex_path.mnt->mnt_root) { - err =get_parent_attributes (exp, &parent_stat); + err =nfsd4_get_mounted_on_ino (exp, &ino);if (err) goto out_nfserr; - ino = parent_stat.ino; } p =xdr_encode_hyper (p, ino); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 640/770 nfsd: remove nfsd4_prepare_cb_recall() declaration
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gaosheng Cui <[email protected]>
[ Upstream commit 18224dc58d960c65446971930d0487fc72d00598 ]
nfsd4_prepare_cb_recall() has been removed since commit 0162ac2b978e ("nfsd: introduce nfsd4_callback_ops"), so remove it.
--- fs/nfsd/state.h | 1 - 1 file changed, 1 deletion(-)
fs/nfsd/state.h +0 -1
@@ -697,7 +697,6 @@ extern int nfsd4_create_callback_queue(void);extern void nfsd4_destroy_callback_queue (void );extern void nfsd4_shutdown_callback (struct nfs4_client *);extern void nfsd4_shutdown_copy (struct nfs4_client *clp); -extern void nfsd4_prepare_cb_recall (struct nfs4_delegation *dp);extern struct nfs4_client_reclaim *nfs4_client_to_reclaim (struct xdr_netobj name,struct xdr_netobj princhash,struct nfsd_net *nn);extern bool nfs4_has_reclaimed_state (struct xdr_netobj name,struct nfsd_net *nn);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 641/770 NFSD: Add tracepoints to report NFSv4 callback completions
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 1035d65446a018ca2dd179e29a2fcd6d29057781 ]
Wireshark has always been lousy about dissecting NFSv4 callbacks, especially NFSv4.0 backchannel requests. Add tracepoints so we can surgically capture these events in the trace log.
Tracepoints are time-stamped and ordered so that we can now observe the timing relationship between a CB_RECALL Reply and the client's DELEGRETURN Call. Example:
nfsd-1153 [002] 211.986391: nfsd_cb_recall: addr=192.168.1.67:45767 client 62ea82e4:fee7492a stateid 00000003:00000001
nfsd-1153 [002] 212.095634: nfsd_compound: xid=0x0000002c opcnt=2
nfsd-1153 [002] 212.095647: nfsd_compound_status: op=1/2 OP_PUTFH status=0
nfsd-1153 [002] 212.095658: nfsd_file_put: hash=0xf72 inode=0xffff9291148c7410 ref=3 flags=HASHED|REFERENCED may=READ file=0xffff929103b3ea00
nfsd-1153 [002] 212.095661: nfsd_compound_status: op=2/2 OP_DELEGRETURN status=0 kworker/u25:8-148 [002] 212.096713: nfsd_cb_recall_done: client 62ea82e4:fee7492a stateid 00000003:00000001 status=0
--- fs/nfsd/nfs4layouts.c | 2 +- fs/nfsd/nfs4proc.c | 4 ++++ fs/nfsd/nfs4state.c | 4 ++++ fs/nfsd/trace.h | 39 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 48 insertions(+), 1 deletion(-)
fs/nfsd/nfs4layouts.c +1 -1
@@ -657,7 +657,7 @@ nfsd4_cb_layout_done(struct nfsd4_callback *cb, struct rpc_task *task)ktime_t now, cutoff;const struct nfsd4_layout_ops *ops; - +trace_nfsd_cb_layout_done (&ls->ls_stid.sc_stateid, task);switch (task->tk_status) {case 0 :case -NFS4ERR_DELAY :
fs/nfsd/nfs4proc.c +4 -0
@@ -1603,6 +1603,10 @@ static void nfsd4_cb_offload_release(struct nfsd4_callback *cb)static int nfsd4_cb_offload_done (struct nfsd4_callback *cb,struct rpc_task *task) { +struct nfsd4_cb_offload *cbo = + container_of(cb, struct nfsd4_cb_offload, co_cb); + +trace_nfsd_cb_offload_done (&cbo->co_res.cb_stateid, task);return 1 ; }
fs/nfsd/nfs4state.c +4 -0
@@ -357,6 +357,8 @@ nfsd4_cb_notify_lock_prepare(struct nfsd4_callback *cb)static int nfsd4_cb_notify_lock_done (struct nfsd4_callback *cb,struct rpc_task *task) { +trace_nfsd_cb_notify_lock_done (&zero_stateid, task); +/* * Since this is just an optimization, we don't try very hard if it * turns out not to succeed. We'll requeue it on NFS4ERR_DELAY, and
@@ -4760,6 +4762,8 @@ static int nfsd4_cb_recall_done(struct nfsd4_callback *cb, {struct nfs4_delegation *dp =cb_to_delegation (cb); +trace_nfsd_cb_recall_done (&dp->dl_stid.sc_stateid, task); +if (dp->dl_stid.sc_type ==NFS4_CLOSED_DELEG_STID || dp->dl_stid.sc_type ==NFS4_REVOKED_DELEG_STID )return 1 ;
fs/nfsd/trace.h +39 -0
@@ -1366,6 +1366,45 @@ TRACE_EVENT(nfsd_cb_offload, __entry->fh_hash, __entry->count, __entry->status) ); +DECLARE_EVENT_CLASS (nfsd_cb_done_class, +TP_PROTO ( + const stateid_t *stp, + const struct rpc_task *task + ), +TP_ARGS (stp, task), +TP_STRUCT__entry ( + __field(u32, cl_boot) + __field(u32, cl_id) + __field(u32, si_id) + __field(u32, si_generation) +__field (int, status) + ), +TP_fast_assign ( + __entry->cl_boot = stp->si_opaque.so_clid.cl_boot; + __entry->cl_id = stp->si_opaque.so_clid.cl_id; + __entry->si_id = stp->si_opaque.so_id; + __entry->si_generation = stp->si_generation; + __entry->status = task->tk_status; + ), +TP_printk ("client %08x:%08x stateid %08x:%08x status=%d" , + __entry->cl_boot, __entry->cl_id, __entry->si_id, + __entry->si_generation, __entry->status + ) +); + +#define DEFINE_NFSD_CB_DONE_EVENT (name) \ +DEFINE_EVENT(nfsd_cb_done_class, name, \ + TP_PROTO( \ + const stateid_t *stp, \ + const struct rpc_task *task \ + ), \ + TP_ARGS(stp, task)) + +DEFINE_NFSD_CB_DONE_EVENT (nfsd_cb_recall_done); +DEFINE_NFSD_CB_DONE_EVENT (nfsd_cb_notify_lock_done); +DEFINE_NFSD_CB_DONE_EVENT (nfsd_cb_layout_done); +DEFINE_NFSD_CB_DONE_EVENT (nfsd_cb_offload_done); +#endif /* _NFSD_TRACE_H */ #undef TRACE_INCLUDE_PATH
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 642/770 NFSD: Add a mechanism to wait for a DELEGRETURN
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit c035362eb935fe9381d9d1cc453bc2a37460e24c ]
Subsequent patches will use this mechanism to wake up an operation that is waiting for a client to return a delegation.
The new tracepoint records whether the wait timed out or was properly awoken by the expected DELEGRETURN:
nfsd-1155 [002] 83799.493199: nfsd_delegret_wakeup: xid=0x14b7d6ef fh_hash=0xf6826792 (timed out)
--- fs/nfsd/nfs4state.c | 30 ++++++++++++++++++++++++++++++ fs/nfsd/nfsd.h | 7 +++++++ fs/nfsd/trace.h | 23 +++++++++++++++++++++++ 3 files changed, 60 insertions(+)
fs/nfsd/nfs4state.c +30 -0
@@ -4734,6 +4734,35 @@ nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type)return ret; } +static bool nfsd4_deleg_present (const struct inode *inode) +{ +struct file_lock_context *ctx =smp_load_acquire (&inode->i_flctx); + +return ctx && !list_empty_careful (&ctx->flc_lease); +} + +/** +* nfsd_wait_for_delegreturn - wait for delegations to be returned +* @rqstp: the RPC transaction being executed +* @inode: in-core inode of the file being waited for +* +* The timeout prevents deadlock if all nfsd threads happen to be +* tied up waiting for returning delegations. +* +* Return values: +* %true: delegation was returned +* %false: timed out waiting for delegreturn +*/ +bool nfsd_wait_for_delegreturn (struct svc_rqst *rqstp,struct inode *inode) +{ +long __maybe_unused timeo; + + timeo =wait_var_event_timeout (inode, !nfsd4_deleg_present (inode), +NFSD_DELEGRETURN_TIMEOUT ); +trace_nfsd_delegret_wakeup (rqstp, inode, timeo); +return timeo >0 ; +} +static void nfsd4_cb_recall_prepare (struct nfsd4_callback *cb) {struct nfs4_delegation *dp =cb_to_delegation (cb);
@@ -6811,6 +6840,7 @@ nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,if (status) goto put_stateid; +wake_up_var (d_inode (cstate->current_fh.fh_dentry));destroy_delegation (dp); put_stateid:nfs4_put_stid (&dp->dl_stid);
fs/nfsd/nfsd.h +7 -0
@@ -164,6 +164,7 @@ char * nfs4_recoverydir(void);bool nfsd4_spo_must_allow (struct svc_rqst *rqstp);int nfsd4_create_laundry_wq (void );void nfsd4_destroy_laundry_wq (void ); +bool nfsd_wait_for_delegreturn (struct svc_rqst *rqstp,struct inode *inode);#else static inline int nfsd4_init_slabs (void ) {return 0 ; }static inline void nfsd4_free_slabs (void ) { }
@@ -179,6 +180,11 @@ static inline bool nfsd4_spo_must_allow(struct svc_rqst *rqstp) }static inline int nfsd4_create_laundry_wq (void ) {return 0 ; };static inline void nfsd4_destroy_laundry_wq (void ) {}; +static inline bool nfsd_wait_for_delegreturn (struct svc_rqst *rqstp, +struct inode *inode) +{ +return false; +}#endif /*
@@ -343,6 +349,7 @@ void nfsd_lockd_shutdown(void);#define NFSD_COURTESY_CLIENT_TIMEOUT (24 * 60 * 60)/* seconds */ #define NFSD_CLIENT_MAX_TRIM_PER_RUN 128#define NFS4_CLIENTS_PER_GB 1024 +#define NFSD_DELEGRETURN_TIMEOUT (HZ / 34)/* 30ms */ /* * The following attributes are currently not supported by the NFSv4 server:
fs/nfsd/trace.h +23 -0
@@ -454,6 +454,29 @@ DEFINE_NFSD_COPY_ERR_EVENT(clone_file_range_err);#include "filecache.h" #include "vfs.h" +TRACE_EVENT (nfsd_delegret_wakeup, +TP_PROTO ( + const struct svc_rqst *rqstp, + const struct inode *inode, + long timeo + ), +TP_ARGS (rqstp, inode, timeo), +TP_STRUCT__entry ( + __field(u32, xid) + __field(const void *, inode) +__field (long, timeo) + ), +TP_fast_assign ( + __entry->xid = be32_to_cpu(rqstp->rq_xid); + __entry->inode = inode; + __entry->timeo = timeo; + ), +TP_printk ("xid=0x%08x inode=%p%s" , + __entry->xid, __entry->inode, + __entry->timeo ==0 ?" (timed out)" :"" + ) +); + DECLARE_EVENT_CLASS(nfsd_stateid_class, TP_PROTO(stateid_t *stp), TP_ARGS(stp),
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 643/770 NFSD: Refactor nfsd_setattr()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit c0aa1913db57219e91a0a8832363cbafb3a9cf8f ]
Move code that will be retried (in a subsequent patch) into a helper function.
--- fs/nfsd/vfs.c | 97 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 57 insertions(+), 40 deletions(-)
fs/nfsd/vfs.c +57 -40
@@ -356,8 +356,61 @@ nfsd_get_write_access(struct svc_rqst *rqstp, struct svc_fh *fhp,return nfserrno (host_err); } -/* -* Set various file attributes. After this call fhp needs an fh_put. +static int __nfsd_setattr (struct dentry *dentry,struct iattr *iap) +{ +int host_err; + +if (iap->ia_valid &ATTR_SIZE ) { +/* +* RFC5661, Section 18.30.4: +* Changing the size of a file with SETATTR indirectly +* changes the time_modify and change attributes. +* +* (and similar for the older RFCs) +*/ +struct iattr size_attr = { + .ia_valid =ATTR_SIZE |ATTR_CTIME |ATTR_MTIME , + .ia_size = iap->ia_size, + }; + +if (iap->ia_size <0 ) +return -EFBIG ; + + host_err =notify_change (dentry, &size_attr,NULL ); +if (host_err) +return host_err; + iap->ia_valid &= ~ATTR_SIZE ; + +/* +* Avoid the additional setattr call below if the only other +* attribute that the client sends is the mtime, as we update +* it as part of the size change above. +*/ +if ((iap->ia_valid & ~ATTR_MTIME ) ==0 ) +return 0 ; + } + +if (!iap->ia_valid) +return 0 ; + + iap->ia_valid |=ATTR_CTIME ; +return notify_change (dentry, iap,NULL ); +} + +/** +* nfsd_setattr - Set various file attributes. +* @rqstp: controlling RPC transaction +* @fhp: filehandle of target +* @attr: attributes to set +* @check_guard: set to 1 if guardtime is a valid timestamp +* @guardtime: do not act if ctime.tv_sec does not match this timestamp +* +* This call may adjust the contents of @attr (in particular, this +* call may change the bits in the na_iattr.ia_valid field). +* +* Returns nfs_ok on success, otherwise an NFS status code is +* returned. Caller must release @fhp by calling fh_put in either +* case. */ __be32 nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp,
@@ -370,7 +423,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp,int accmode =NFSD_MAY_SATTR ;umode_t ftype =0 ;__be32 err; -int host_err =0 ; +int host_err;bool get_write_count;bool size_change = (iap->ia_valid &ATTR_SIZE );
@@ -427,43 +480,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, }inode_lock (inode); -if (size_change) { -/* -* RFC5661, Section 18.30.4: -* Changing the size of a file with SETATTR indirectly -* changes the time_modify and change attributes. -* -* (and similar for the older RFCs) -*/ -struct iattr size_attr = { - .ia_valid =ATTR_SIZE |ATTR_CTIME |ATTR_MTIME , - .ia_size = iap->ia_size, - }; - - host_err = -EFBIG ; -if (iap->ia_size <0 ) - goto out_unlock; - - host_err =notify_change (dentry, &size_attr,NULL ); -if (host_err) - goto out_unlock; - iap->ia_valid &= ~ATTR_SIZE ; - -/* -* Avoid the additional setattr call below if the only other -* attribute that the client sends is the mtime, as we update -* it as part of the size change above. -*/ -if ((iap->ia_valid & ~ATTR_MTIME ) ==0 ) - goto out_unlock; - } - -if (iap->ia_valid) { - iap->ia_valid |=ATTR_CTIME ; - host_err =notify_change (dentry, iap,NULL ); - } - -out_unlock: + host_err =__nfsd_setattr (dentry, iap);if (attr->na_seclabel && attr->na_seclabel->len) attr->na_labelerr =security_inode_setsecctx (dentry, attr->na_seclabel->data, attr->na_seclabel->len);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 644/770 NFSD: Make nfsd4_setattr() wait before returning NFS4ERR_DELAY
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 34b91dda7124fc3259e4b2ae53e0c933dedfec01 ]
nfsd_setattr() can kick off a CB_RECALL (via notify_change() -> break_lease()) if a delegation is present. Before returning NFS4ERR_DELAY, give the client holding that delegation a chance to return it and then retry the nfsd_setattr() again, once.
--- fs/nfsd/vfs.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
fs/nfsd/vfs.c +8 -1
@@ -426,6 +426,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp,int host_err;bool get_write_count;bool size_change = (iap->ia_valid &ATTR_SIZE ); +int retries;if (iap->ia_valid &ATTR_SIZE ) { accmode |=NFSD_MAY_WRITE |NFSD_MAY_OWNER_OVERRIDE ;
@@ -480,7 +481,13 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, }inode_lock (inode); - host_err =__nfsd_setattr (dentry, iap); +for (retries =1 ;;) { + host_err =__nfsd_setattr (dentry, iap); +if (host_err != -EAGAIN || !retries--) +break ; +if (!nfsd_wait_for_delegreturn (rqstp, inode)) +break ; + }if (attr->na_seclabel && attr->na_seclabel->len) attr->na_labelerr =security_inode_setsecctx (dentry, attr->na_seclabel->data, attr->na_seclabel->len);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 645/770 NFSD: Make nfsd4_rename() wait before returning NFS4ERR_DELAY
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 68c522afd0b1936b48a03a4c8b81261e7597c62d ]
nfsd_rename() can kick off a CB_RECALL (via vfs_rename() -> leases_conflict()) if a delegation is present. Before returning NFS4ERR_DELAY, give the client holding that delegation a chance to return it and then retry the nfsd_rename() again, once.
This version of the patch handles renaming an existing file, but does not deal with renaming onto an existing file. That case will still always trigger an NFS4ERR_DELAY.
--- fs/nfsd/vfs.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
fs/nfsd/vfs.c +9 -1
@@ -1711,7 +1711,15 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, .new_dir = tdir, .new_dentry = ndentry, }; - host_err =vfs_rename (&rd); +int retries; + +for (retries =1 ;;) { + host_err =vfs_rename (&rd); +if (host_err != -EAGAIN || !retries--) +break ; +if (!nfsd_wait_for_delegreturn (rqstp,d_inode (odentry))) +break ; + }if (!host_err) { host_err =commit_metadata (tfhp);if (!host_err)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 646/770 NFSD: Make nfsd4_remove() wait before returning NFS4ERR_DELAY
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 5f5f8b6d655fd947e899b1771c2f7cb581a06764 ]
nfsd_unlink() can kick off a CB_RECALL (via vfs_unlink() -> leases_conflict()) if a delegation is present. Before returning NFS4ERR_DELAY, give the client holding that delegation a chance to return it and then retry the nfsd_unlink() again, once.
--- fs/nfsd/vfs.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
fs/nfsd/vfs.c +10 -1
@@ -1803,9 +1803,18 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,fh_fill_pre_attrs (fhp);if (type !=S_IFDIR ) { +int retries; +if (rdentry->d_sb->s_export_op->flags &EXPORT_OP_CLOSE_BEFORE_UNLINK )nfsd_close_cached_files (rdentry); - host_err =vfs_unlink (dirp, rdentry,NULL ); + +for (retries =1 ;;) { + host_err =vfs_unlink (dirp, rdentry,NULL ); +if (host_err != -EAGAIN || !retries--) +break ; +if (!nfsd_wait_for_delegreturn (rqstp, rinode)) +break ; + } }else { host_err =vfs_rmdir (dirp, rdentry); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 647/770 NFSD: keep track of the number of courtesy clients in the system
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dai Ngo <[email protected]>
[ Upstream commit 3a4ea23d86a317c4b68b9a69d51f7e84e1e04357 ]
Add counter nfs4_courtesy_client_count to nfsd_net to keep track of the number of courtesy clients in the system.
--- fs/nfsd/netns.h | 2 ++ fs/nfsd/nfs4state.c | 17 ++++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-)
fs/nfsd/netns.h +2 -0
@@ -192,6 +192,8 @@ struct nfsd_net {atomic_t nfs4_client_count;int nfs4_max_clients; + +atomic_t nfsd_courtesy_clients; };/* Simple check to find out if a given net was properly initialized */
fs/nfsd/nfs4state.c +16 -1
@@ -160,6 +160,13 @@ static bool is_client_expired(struct nfs4_client *clp)return clp->cl_time ==0 ; } +static void nfsd4_dec_courtesy_client_count (struct nfsd_net *nn, +struct nfs4_client *clp) +{ +if (clp->cl_state !=NFSD4_ACTIVE ) +atomic_add_unless (&nn->nfsd_courtesy_clients,-1 ,0 ); +} +static __be32 get_client_locked (struct nfs4_client *clp) {struct nfsd_net *nn =net_generic (clp->net, nfsd_net_id);
@@ -169,6 +176,7 @@ static __be32 get_client_locked(struct nfs4_client *clp)if (is_client_expired (clp))return nfserr_expired;atomic_inc (&clp->cl_rpc_users); +nfsd4_dec_courtesy_client_count (nn, clp); clp->cl_state =NFSD4_ACTIVE ;return nfs_ok; }
@@ -190,6 +198,7 @@ renew_client_locked(struct nfs4_client *clp)list_move_tail (&clp->cl_lru, &nn->client_lru); clp->cl_time =ktime_get_boottime_seconds (); +nfsd4_dec_courtesy_client_count (nn, clp); clp->cl_state =NFSD4_ACTIVE ; }
@@ -2248,6 +2257,7 @@ __destroy_client(struct nfs4_client *clp)if (clp->cl_cb_conn.cb_xprt)svc_xprt_put (clp->cl_cb_conn.cb_xprt);atomic_add_unless (&nn->nfs4_client_count,-1 ,0 ); +nfsd4_dec_courtesy_client_count (nn, clp);free_client (clp);wake_up_all (&expiry_wq); }
@@ -4375,6 +4385,8 @@ void nfsd4_init_leases_net(struct nfsd_net *nn) max_clients = (u64 )si.totalram * si.mem_unit / (1024 *1024 *1024 ); max_clients *=NFS4_CLIENTS_PER_GB ; nn->nfs4_max_clients =max_t (int, max_clients,NFS4_CLIENTS_PER_GB ); + +atomic_set (&nn->nfsd_courtesy_clients,0 ); }static void init_nfs4_replay (struct nfs4_replay *rp)
@@ -5928,8 +5940,11 @@ nfs4_get_client_reaplist(struct nfsd_net *nn, struct list_head *reaplist, goto exp_client;if (!state_expired (lt, clp->cl_time))break ; -if (!atomic_read (&clp->cl_rpc_users)) +if (!atomic_read (&clp->cl_rpc_users)) { +if (clp->cl_state ==NFSD4_ACTIVE ) +atomic_inc (&nn->nfsd_courtesy_clients); clp->cl_state =NFSD4_COURTESY ; + }if (!client_has_state (clp)) goto exp_client;if (!nfs4_anylock_blockers (clp))
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 648/770 NFSD: add shrinker to reap courtesy clients on low memory condition
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dai Ngo <[email protected]>
[ Upstream commit 7746b32f467b3813fb61faaab3258de35806a7ac ]
Add courtesy_client_reaper to react to low memory condition triggered by the system memory shrinker.
The delayed_work for the courtesy_client_reaper is scheduled on the shrinker's count callback using the laundry_wq.
The shrinker's scan callback is not used for expiring the courtesy clients due to potential deadlocks.
--- fs/nfsd/netns.h | 2 + fs/nfsd/nfs4state.c | 94 +++++++++++++++++++++++++++++++++++++++++---- fs/nfsd/nfsctl.c | 6 ++- fs/nfsd/nfsd.h | 6 ++- 4 files changed, 96 insertions(+), 12 deletions(-)
fs/nfsd/netns.h +2 -0
@@ -194,6 +194,8 @@ struct nfsd_net {int nfs4_max_clients;atomic_t nfsd_courtesy_clients; +struct shrinker nfsd_client_shrinker; +struct delayed_work nfsd_shrinker_work; };/* Simple check to find out if a given net was properly initialized */
fs/nfsd/nfs4state.c +86 -8
133 lines not on this page · raw message
fs/nfsd/nfsctl.c +4 -2
@@ -1481,11 +1481,12 @@ static __net_init int nfsd_init_net(struct net *net) goto out_idmap_error; nn->nfsd_versions =NULL ; nn->nfsd4_minorversions =NULL ; + retval =nfsd4_init_leases_net (nn); +if (retval) + goto out_drc_error; retval =nfsd_reply_cache_init (nn);if (retval) goto out_drc_error; -nfsd4_init_leases_net (nn); -get_random_bytes (&nn->siphash_key,sizeof (nn->siphash_key));seqlock_init (&nn->writeverf_lock);
@@ -1507,6 +1508,7 @@ static __net_exit void nfsd_exit_net(struct net *net)nfsd_idmap_shutdown (net);nfsd_export_shutdown (net);nfsd_netns_free_versions (net_generic (net, nfsd_net_id)); +nfsd4_leases_net_shutdown (nn); }static struct pernet_operations nfsd_net_ops = {
fs/nfsd/nfsd.h +4 -2
@@ -505,7 +505,8 @@ extern void unregister_cld_notifier(void);extern void nfsd4_ssc_init_umount_work (struct nfsd_net *nn);#endif -extern void nfsd4_init_leases_net (struct nfsd_net *nn); +extern int nfsd4_init_leases_net (struct nfsd_net *nn); +extern void nfsd4_leases_net_shutdown (struct nfsd_net *nn);#else /* CONFIG_NFSD_V4 */ static inline int nfsd4_is_junction (struct dentry *dentry)
@@ -513,7 +514,8 @@ static inline int nfsd4_is_junction(struct dentry *dentry)return 0 ; } -static inline void nfsd4_init_leases_net (struct nfsd_net *nn) {}; +static inline int nfsd4_init_leases_net (struct nfsd_net *nn) {return 0 ; }; +static inline void nfsd4_leases_net_shutdown (struct nfsd_net *nn) {};#define register_cld_notifier () 0#define unregister_cld_notifier () do { } while(0)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 649/770 SUNRPC: Parametrize how much of argsize should be zeroed
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
[ Upstream commit 103cc1fafee48adb91fca0e19deb869fd23e46ab ]
Currently, SUNRPC clears the whole of .pc_argsize before processing each incoming RPC transaction. Add an extra parameter to struct svc_procedure to enable upper layers to reduce the amount of each operation's argument structure that is zeroed by SUNRPC.
The size of struct nfsd4_compoundargs, in particular, is a lot to clear on each incoming RPC Call. A subsequent patch will cut this down to something closer to what NFSv2 and NFSv3 uses.
This patch should cause no behavior changes.
--- fs/lockd/svc4proc.c | 24 ++++++++++++++++++++++++ fs/lockd/svcproc.c | 24 ++++++++++++++++++++++++ fs/nfs/callback_xdr.c | 1 + fs/nfsd/nfs2acl.c | 5 +++++ fs/nfsd/nfs3acl.c | 3 +++ fs/nfsd/nfs3proc.c | 22 ++++++++++++++++++++++ fs/nfsd/nfs4proc.c | 2 ++ fs/nfsd/nfsproc.c | 18 ++++++++++++++++++ include/linux/sunrpc/svc.h | 1 + net/sunrpc/svc.c | 2 +- 10 files changed, 101 insertions(+), 1 deletion(-)
fs/lockd/svc4proc.c +24 -0
@@ -521,6 +521,7 @@ const struct svc_procedure nlmsvc_procedures4[24] = { .pc_decode = nlm4svc_decode_void, .pc_encode = nlm4svc_encode_void, .pc_argsize = sizeof(struct nlm_void), + .pc_argzero = sizeof(struct nlm_void), .pc_ressize = sizeof(struct nlm_void), .pc_xdrressize = St, .pc_name = "NULL",
@@ -530,6 +531,7 @@ const struct svc_procedure nlmsvc_procedures4[24] = { .pc_decode = nlm4svc_decode_testargs, .pc_encode = nlm4svc_encode_testres, .pc_argsize = sizeof(struct nlm_args), + .pc_argzero = sizeof(struct nlm_args), .pc_ressize = sizeof(struct nlm_res), .pc_xdrressize = Ck+St+2+No+Rg, .pc_name = "TEST",
@@ -539,6 +541,7 @@ const struct svc_procedure nlmsvc_procedures4[24] = { .pc_decode = nlm4svc_decode_lockargs, .pc_encode = nlm4svc_encode_res, .pc_argsize = sizeof(struct nlm_args), + .pc_argzero = sizeof(struct nlm_args), .pc_ressize = sizeof(struct nlm_res), .pc_xdrressize = Ck+St, .pc_name = "LOCK",
@@ -548,6 +551,7 @@ const struct svc_procedure nlmsvc_procedures4[24] = { .pc_decode = nlm4svc_decode_cancargs, .pc_encode = nlm4svc_encode_res, .pc_argsize = sizeof(struct nlm_args), + .pc_argzero = sizeof(struct nlm_args), .pc_ressize = sizeof(struct nlm_res), .pc_xdrressize = Ck+St, .pc_name = "CANCEL",
@@ -557,6 +561,7 @@ const struct svc_procedure nlmsvc_procedures4[24] = { .pc_decode = nlm4svc_decode_unlockargs, .pc_encode = nlm4svc_encode_res, .pc_argsize = sizeof(struct nlm_args), + .pc_argzero = sizeof(struct nlm_args), .pc_ressize = sizeof(struct nlm_res), .pc_xdrressize = Ck+St, .pc_name = "UNLOCK",
@@ -566,6 +571,7 @@ const struct svc_procedure nlmsvc_procedures4[24] = { .pc_decode = nlm4svc_decode_testargs, .pc_encode = nlm4svc_encode_res, .pc_argsize = sizeof(struct nlm_args), + .pc_argzero = sizeof(struct nlm_args), .pc_ressize = sizeof(struct nlm_res), .pc_xdrressize = Ck+St, .pc_name = "GRANTED",
@@ -575,6 +581,7 @@ const struct svc_procedure nlmsvc_procedures4[24] = { .pc_decode = nlm4svc_decode_testargs, .pc_encode = nlm4svc_encode_void, .pc_argsize = sizeof(struct nlm_args), + .pc_argzero = sizeof(struct nlm_args), .pc_ressize = sizeof(struct nlm_void), .pc_xdrressize = St, .pc_name = "TEST_MSG",
@@ -584,6 +591,7 @@ const struct svc_procedure nlmsvc_procedures4[24] = { .pc_decode = nlm4svc_decode_lockargs, .pc_encode = nlm4svc_encode_void, .pc_argsize = sizeof(struct nlm_args), + .pc_argzero = sizeof(struct nlm_args), .pc_ressize = sizeof(struct nlm_void), .pc_xdrressize = St, .pc_name = "LOCK_MSG",
@@ -593,6 +601,7 @@ const struct svc_procedure nlmsvc_procedures4[24] = { .pc_decode = nlm4svc_decode_cancargs, .pc_encode = nlm4svc_encode_void, .pc_argsize = sizeof(struct nlm_args), + .pc_argzero = sizeof(struct nlm_args), .pc_ressize = sizeof(struct nlm_void), .pc_xdrressize = St, .pc_name = "CANCEL_MSG",
@@ -602,6 +611,7 @@ const struct svc_procedure nlmsvc_procedures4[24] = { .pc_decode = nlm4svc_decode_unlockargs, .pc_encode = nlm4svc_encode_void, .pc_argsize = sizeof(struct nlm_args), + .pc_argzero = sizeof(struct nlm_args), .pc_ressize = sizeof(struct nlm_void), .pc_xdrressize = St, .pc_name = "UNLOCK_MSG",
@@ -611,6 +621,7 @@ const struct svc_procedure nlmsvc_procedures4[24] = { .pc_decode = nlm4svc_decode_testargs, .pc_encode = nlm4svc_encode_void, .pc_argsize = sizeof(struct nlm_args), + .pc_argzero = sizeof(struct nlm_args), .pc_ressize = sizeof(struct nlm_void), .pc_xdrressize = St, .pc_name = "GRANTED_MSG",
@@ -620,6 +631,7 @@ const struct svc_procedure nlmsvc_procedures4[24] = { .pc_decode = nlm4svc_decode_void, .pc_encode = nlm4svc_encode_void, .pc_argsize = sizeof(struct nlm_res), + .pc_argzero = sizeof(struct nlm_res), .pc_ressize = sizeof(struct nlm_void), .pc_xdrressize = St, .pc_name = "TEST_RES",
@@ -629,6 +641,7 @@ const struct svc_procedure nlmsvc_procedures4[24] = { .pc_decode = nlm4svc_decode_void, .pc_encode = nlm4svc_encode_void, .pc_argsize = sizeof(struct nlm_res), + .pc_argzero = sizeof(struct nlm_res), .pc_ressize = sizeof(struct nlm_void), .pc_xdrressize = St, .pc_name = "LOCK_RES",
@@ -638,6 +651,7 @@ const struct svc_procedure nlmsvc_procedures4[24] = { .pc_decode = nlm4svc_decode_void, .pc_encode = nlm4svc_encode_void, .pc_argsize = sizeof(struct nlm_res), + .pc_argzero = sizeof(struct nlm_res), .pc_ressize = sizeof(struct nlm_void), .pc_xdrressize = St, .pc_name = "CANCEL_RES",
@@ -647,6 +661,7 @@ const struct svc_procedure nlmsvc_procedures4[24] = { .pc_decode = nlm4svc_decode_void, .pc_encode = nlm4svc_encode_void, .pc_argsize = sizeof(struct nlm_res), + .pc_argzero = sizeof(struct nlm_res), .pc_ressize = sizeof(struct nlm_void), .pc_xdrressize = St, .pc_name = "UNLOCK_RES",
@@ -656,6 +671,7 @@ const struct svc_procedure nlmsvc_procedures4[24] = { .pc_decode = nlm4svc_decode_res, .pc_encode = nlm4svc_encode_void, .pc_argsize = sizeof(struct nlm_res), + .pc_argzero = sizeof(struct nlm_res), .pc_ressize = sizeof(struct nlm_void), .pc_xdrressize = St, .pc_name = "GRANTED_RES",
@@ -665,6 +681,7 @@ const struct svc_procedure nlmsvc_procedures4[24] = { .pc_decode = nlm4svc_decode_reboot, .pc_encode = nlm4svc_encode_void, .pc_argsize = sizeof(struct nlm_reboot), + .pc_argzero = sizeof(struct nlm_reboot), .pc_ressize = sizeof(struct nlm_void), .pc_xdrressize = St, .pc_name = "SM_NOTIFY",
@@ -674,6 +691,7 @@ const struct svc_procedure nlmsvc_procedures4[24] = { .pc_decode = nlm4svc_decode_void, .pc_encode = nlm4svc_encode_void, .pc_argsize = sizeof(struct nlm_void), + .pc_argzero = sizeof(struct nlm_void), .pc_ressize = sizeof(struct nlm_void), .pc_xdrressize = 0, .pc_name = "UNUSED",
@@ -683,6 +701,7 @@ const struct svc_procedure nlmsvc_procedures4[24] = { .pc_decode = nlm4svc_decode_void, .pc_encode = nlm4svc_encode_void, .pc_argsize = sizeof(struct nlm_void), + .pc_argzero = sizeof(struct nlm_void), .pc_ressize = sizeof(struct nlm_void), .pc_xdrressize = 0, .pc_name = "UNUSED",
@@ -692,6 +711,7 @@ const struct svc_procedure nlmsvc_procedures4[24] = { .pc_decode = nlm4svc_decode_void, .pc_encode = nlm4svc_encode_void, .pc_argsize = sizeof(struct nlm_void), + .pc_argzero = sizeof(struct nlm_void), .pc_ressize = sizeof(struct nlm_void), .pc_xdrressize = 0, .pc_name = "UNUSED",
@@ -701,6 +721,7 @@ const struct svc_procedure nlmsvc_procedures4[24] = { .pc_decode = nlm4svc_decode_shareargs, .pc_encode = nlm4svc_encode_shareres, .pc_argsize = sizeof(struct nlm_args), + .pc_argzero = sizeof(struct nlm_args), .pc_ressize = sizeof(struct nlm_res), .pc_xdrressize = Ck+St+1, .pc_name = "SHARE",
@@ -710,6 +731,7 @@ const struct svc_procedure nlmsvc_procedures4[24] = { .pc_decode = nlm4svc_decode_shareargs, .pc_encode = nlm4svc_encode_shareres, .pc_argsize = sizeof(struct nlm_args), + .pc_argzero = sizeof(struct nlm_args), .pc_ressize = sizeof(struct nlm_res), .pc_xdrressize = Ck+St+1, .pc_name = "UNSHARE",
@@ -719,6 +741,7 @@ const struct svc_procedure nlmsvc_procedures4[24] = { .pc_decode = nlm4svc_decode_lockargs, .pc_encode = nlm4svc_encode_res, .pc_argsize = sizeof(struct nlm_args), + .pc_argzero = sizeof(struct nlm_args), .pc_ressize = sizeof(struct nlm_res), .pc_xdrressize = Ck+St, .pc_name = "NM_LOCK",
@@ -728,6 +751,7 @@ const struct svc_procedure nlmsvc_procedures4[24] = { .pc_decode = nlm4svc_decode_notify, .pc_encode = nlm4svc_encode_void, .pc_argsize = sizeof(struct nlm_args), + .pc_argzero = sizeof(struct nlm_args), .pc_ressize = sizeof(struct nlm_void), .pc_xdrressize = St, .pc_name = "FREE_ALL",
fs/lockd/svcproc.c +24 -0
@@ -555,6 +555,7 @@ const struct svc_procedure nlmsvc_procedures[24] = { .pc_decode = nlmsvc_decode_void, .pc_encode = nlmsvc_encode_void, .pc_argsize = sizeof(struct nlm_void), + .pc_argzero = sizeof(struct nlm_void), .pc_ressize = sizeof(struct nlm_void), .pc_xdrressize = St, .pc_name = "NULL",
@@ -564,6 +565,7 @@ const struct svc_procedure nlmsvc_procedures[24] = { .pc_decode = nlmsvc_decode_testargs, .pc_encode = nlmsvc_encode_testres, .pc_argsize = sizeof(struct nlm_args), + .pc_argzero = sizeof(struct nlm_args), .pc_ressize = sizeof(struct nlm_res), .pc_xdrressize = Ck+St+2+No+Rg, .pc_name = "TEST",
@@ -573,6 +575,7 @@ const struct svc_procedure nlmsvc_procedures[24] = { .pc_decode = nlmsvc_decode_lockargs, .pc_encode = nlmsvc_encode_res, .pc_argsize = sizeof(struct nlm_args), + .pc_argzero = sizeof(struct nlm_args), .pc_ressize = sizeof(struct nlm_res), .pc_xdrressize = Ck+St, .pc_name = "LOCK",
@@ -582,6 +585,7 @@ const struct svc_procedure nlmsvc_procedures[24] = { .pc_decode = nlmsvc_decode_cancargs, .pc_encode = nlmsvc_encode_res, .pc_argsize = sizeof(struct nlm_args), + .pc_argzero = sizeof(struct nlm_args), .pc_ressize = sizeof(struct nlm_res), .pc_xdrressize = Ck+St, .pc_name = "CANCEL",
@@ -591,6 +595,7 @@ const struct svc_procedure nlmsvc_procedures[24] = { .pc_decode = nlmsvc_decode_unlockargs, .pc_encode = nlmsvc_encode_res, .pc_argsize = sizeof(struct nlm_args), + .pc_argzero = sizeof(struct nlm_args), .pc_ressize = sizeof(struct nlm_res), .pc_xdrressize = Ck+St, .pc_name = "UNLOCK",
@@ -600,6 +605,7 @@ const struct svc_procedure nlmsvc_procedures[24] = { .pc_decode = nlmsvc_decode_testargs, .pc_encode = nlmsvc_encode_res, .pc_argsize = sizeof(struct nlm_args), + .pc_argzero = sizeof(struct nlm_args), .pc_ressize = sizeof(struct nlm_res), .pc_xdrressize = Ck+St, .pc_name = "GRANTED",
@@ -609,6 +615,7 @@ const struct svc_procedure nlmsvc_procedures[24] = { .pc_decode = nlmsvc_decode_testargs, .pc_encode = nlmsvc_encode_void, .pc_argsize = sizeof(struct nlm_args), + .pc_argzero = sizeof(struct nlm_args), .pc_ressize = sizeof(struct nlm_void), .pc_xdrressize = St, .pc_name = "TEST_MSG",
@@ -618,6 +625,7 @@ const struct svc_procedure nlmsvc_procedures[24] = { .pc_decode = nlmsvc_decode_lockargs, .pc_encode = nlmsvc_encode_void, .pc_argsize = sizeof(struct nlm_args), + .pc_argzero = sizeof(struct nlm_args), .pc_ressize = sizeof(struct nlm_void), .pc_xdrressize = St, .pc_name = "LOCK_MSG",
@@ -627,6 +635,7 @@ const struct svc_procedure nlmsvc_procedures[24] = { .pc_decode = nlmsvc_decode_cancargs, .pc_encode = nlmsvc_encode_void, .pc_argsize = sizeof(struct nlm_args), + .pc_argzero = sizeof(struct nlm_args), .pc_ressize = sizeof(struct nlm_void), .pc_xdrressize = St, .pc_name = "CANCEL_MSG",
@@ -636,6 +645,7 @@ const struct svc_procedure nlmsvc_procedures[24] = { .pc_decode = nlmsvc_decode_unlockargs, .pc_encode = nlmsvc_encode_void, .pc_argsize = sizeof(struct nlm_args), + .pc_argzero = sizeof(struct nlm_args), .pc_ressize = sizeof(struct nlm_void), .pc_xdrressize = St, .pc_name = "UNLOCK_MSG",
@@ -645,6 +655,7 @@ const struct svc_procedure nlmsvc_procedures[24] = { .pc_decode = nlmsvc_decode_testargs, .pc_encode = nlmsvc_encode_void, .pc_argsize = sizeof(struct nlm_args), + .pc_argzero = sizeof(struct nlm_args), .pc_ressize = sizeof(struct nlm_void), .pc_xdrressize = St, .pc_name = "GRANTED_MSG",
@@ -654,6 +665,7 @@ const struct svc_procedure nlmsvc_procedures[24] = { .pc_decode = nlmsvc_decode_void, .pc_encode = nlmsvc_encode_void, .pc_argsize = sizeof(struct nlm_res), + .pc_argzero = sizeof(struct nlm_res), .pc_ressize = sizeof(struct nlm_void), .pc_xdrressize = St, .pc_name = "TEST_RES",
@@ -663,6 +675,7 @@ const struct svc_procedure nlmsvc_procedures[24] = { .pc_decode = nlmsvc_decode_void, .pc_encode = nlmsvc_encode_void, .pc_argsize = sizeof(struct nlm_res), + .pc_argzero = sizeof(struct nlm_res), .pc_ressize = sizeof(struct nlm_void), .pc_xdrressize = St, .pc_name = "LOCK_RES",
@@ -672,6 +685,7 @@ const struct svc_procedure nlmsvc_procedures[24] = { .pc_decode = nlmsvc_decode_void, .pc_encode = nlmsvc_encode_void, .pc_argsize = sizeof(struct nlm_res), + .pc_argzero = sizeof(struct nlm_res), .pc_ressize = sizeof(struct nlm_void), .pc_xdrressize = St, .pc_name = "CANCEL_RES",
@@ -681,6 +695,7 @@ const struct svc_procedure nlmsvc_procedures[24] = { .pc_decode = nlmsvc_decode_void, .pc_encode = nlmsvc_encode_void, .pc_argsize = sizeof(struct nlm_res), + .pc_argzero = sizeof(struct nlm_res), .pc_ressize = sizeof(struct nlm_void), .pc_xdrressize = St, .pc_name = "UNLOCK_RES",
@@ -690,6 +705,7 @@ const struct svc_procedure nlmsvc_procedures[24] = { .pc_decode = nlmsvc_decode_res, .pc_encode = nlmsvc_encode_void, .pc_argsize = sizeof(struct nlm_res), + .pc_argzero = sizeof(struct nlm_res), .pc_ressize = sizeof(struct nlm_void), .pc_xdrressize = St, .pc_name = "GRANTED_RES",
@@ -699,6 +715,7 @@ const struct svc_procedure nlmsvc_procedures[24] = { .pc_decode = nlmsvc_decode_reboot, .pc_encode = nlmsvc_encode_void, .pc_argsize = sizeof(struct nlm_reboot), + .pc_argzero = sizeof(struct nlm_reboot), .pc_ressize = sizeof(struct nlm_void), .pc_xdrressize = St, .pc_name = "SM_NOTIFY",
@@ -708,6 +725,7 @@ const struct svc_procedure nlmsvc_procedures[24] = { .pc_decode = nlmsvc_decode_void, .pc_encode = nlmsvc_encode_void, .pc_argsize = sizeof(struct nlm_void), + .pc_argzero = sizeof(struct nlm_void), .pc_ressize = sizeof(struct nlm_void), .pc_xdrressize = St, .pc_name = "UNUSED",
@@ -717,6 +735,7 @@ const struct svc_procedure nlmsvc_procedures[24] = { .pc_decode = nlmsvc_decode_void, .pc_encode = nlmsvc_encode_void, .pc_argsize = sizeof(struct nlm_void), + .pc_argzero = sizeof(struct nlm_void), .pc_ressize = sizeof(struct nlm_void), .pc_xdrressize = St, .pc_name = "UNUSED",
@@ -726,6 +745,7 @@ const struct svc_procedure nlmsvc_procedures[24] = { .pc_decode = nlmsvc_decode_void, .pc_encode = nlmsvc_encode_void, .pc_argsize = sizeof(struct nlm_void), + .pc_argzero = sizeof(struct nlm_void), .pc_ressize = sizeof(struct nlm_void), .pc_xdrressize = St, .pc_name = "UNUSED",
@@ -735,6 +755,7 @@ const struct svc_procedure nlmsvc_procedures[24] = { .pc_decode = nlmsvc_decode_shareargs, .pc_encode = nlmsvc_encode_shareres, .pc_argsize = sizeof(struct nlm_args), + .pc_argzero = sizeof(struct nlm_args), .pc_ressize = sizeof(struct nlm_res), .pc_xdrressize = Ck+St+1, .pc_name = "SHARE",
@@ -744,6 +765,7 @@ const struct svc_procedure nlmsvc_procedures[24] = { .pc_decode = nlmsvc_decode_shareargs, .pc_encode = nlmsvc_encode_shareres, .pc_argsize = sizeof(struct nlm_args), + .pc_argzero = sizeof(struct nlm_args), .pc_ressize = sizeof(struct nlm_res), .pc_xdrressize = Ck+St+1, .pc_name = "UNSHARE",
@@ -753,6 +775,7 @@ const struct svc_procedure nlmsvc_procedures[24] = { .pc_decode = nlmsvc_decode_lockargs, .pc_encode = nlmsvc_encode_res, .pc_argsize = sizeof(struct nlm_args), + .pc_argzero = sizeof(struct nlm_args), .pc_ressize = sizeof(struct nlm_res), .pc_xdrressize = Ck+St, .pc_name = "NM_LOCK",
@@ -762,6 +785,7 @@ const struct svc_procedure nlmsvc_procedures[24] = { .pc_decode = nlmsvc_decode_notify, .pc_encode = nlmsvc_encode_void, .pc_argsize = sizeof(struct nlm_args), + .pc_argzero = sizeof(struct nlm_args), .pc_ressize = sizeof(struct nlm_void), .pc_xdrressize = 0, .pc_name = "FREE_ALL",
fs/nfs/callback_xdr.c +1 -0
@@ -1070,6 +1070,7 @@ static const struct svc_procedure nfs4_callback_procedures1[] = { .pc_func = nfs4_callback_compound, .pc_encode = nfs4_encode_void, .pc_argsize = 256, + .pc_argzero = 256, .pc_ressize = 256, .pc_xdrressize = NFS4_CALLBACK_BUFSIZE, .pc_name = "COMPOUND",
fs/nfsd/nfs2acl.c +5 -0
@@ -329,6 +329,7 @@ static const struct svc_procedure nfsd_acl_procedures2[5] = { .pc_decode = nfssvc_decode_voidarg, .pc_encode = nfssvc_encode_voidres, .pc_argsize = sizeof(struct nfsd_voidargs), + .pc_argzero = sizeof(struct nfsd_voidargs), .pc_ressize = sizeof(struct nfsd_voidres), .pc_cachetype = RC_NOCACHE, .pc_xdrressize = ST,
@@ -340,6 +341,7 @@ static const struct svc_procedure nfsd_acl_procedures2[5] = { .pc_encode = nfsaclsvc_encode_getaclres, .pc_release = nfsaclsvc_release_getacl, .pc_argsize = sizeof(struct nfsd3_getaclargs), + .pc_argzero = sizeof(struct nfsd3_getaclargs), .pc_ressize = sizeof(struct nfsd3_getaclres), .pc_cachetype = RC_NOCACHE, .pc_xdrressize = ST+1+2*(1+ACL),
@@ -351,6 +353,7 @@ static const struct svc_procedure nfsd_acl_procedures2[5] = { .pc_encode = nfssvc_encode_attrstatres, .pc_release = nfssvc_release_attrstat, .pc_argsize = sizeof(struct nfsd3_setaclargs), + .pc_argzero = sizeof(struct nfsd3_setaclargs), .pc_ressize = sizeof(struct nfsd_attrstat), .pc_cachetype = RC_NOCACHE, .pc_xdrressize = ST+AT,
@@ -362,6 +365,7 @@ static const struct svc_procedure nfsd_acl_procedures2[5] = { .pc_encode = nfssvc_encode_attrstatres, .pc_release = nfssvc_release_attrstat, .pc_argsize = sizeof(struct nfsd_fhandle), + .pc_argzero = sizeof(struct nfsd_fhandle), .pc_ressize = sizeof(struct nfsd_attrstat), .pc_cachetype = RC_NOCACHE, .pc_xdrressize = ST+AT,
@@ -373,6 +377,7 @@ static const struct svc_procedure nfsd_acl_procedures2[5] = { .pc_encode = nfsaclsvc_encode_accessres, .pc_release = nfsaclsvc_release_access, .pc_argsize = sizeof(struct nfsd3_accessargs), + .pc_argzero = sizeof(struct nfsd3_accessargs), .pc_ressize = sizeof(struct nfsd3_accessres), .pc_cachetype = RC_NOCACHE, .pc_xdrressize = ST+AT+1,
fs/nfsd/nfs3acl.c +3 -0
@@ -250,6 +250,7 @@ static const struct svc_procedure nfsd_acl_procedures3[3] = { .pc_decode = nfssvc_decode_voidarg, .pc_encode = nfssvc_encode_voidres, .pc_argsize = sizeof(struct nfsd_voidargs), + .pc_argzero = sizeof(struct nfsd_voidargs), .pc_ressize = sizeof(struct nfsd_voidres), .pc_cachetype = RC_NOCACHE, .pc_xdrressize = ST,
@@ -261,6 +262,7 @@ static const struct svc_procedure nfsd_acl_procedures3[3] = { .pc_encode = nfs3svc_encode_getaclres, .pc_release = nfs3svc_release_getacl, .pc_argsize = sizeof(struct nfsd3_getaclargs), + .pc_argzero = sizeof(struct nfsd3_getaclargs), .pc_ressize = sizeof(struct nfsd3_getaclres), .pc_cachetype = RC_NOCACHE, .pc_xdrressize = ST+1+2*(1+ACL),
@@ -272,6 +274,7 @@ static const struct svc_procedure nfsd_acl_procedures3[3] = { .pc_encode = nfs3svc_encode_setaclres, .pc_release = nfs3svc_release_fhandle, .pc_argsize = sizeof(struct nfsd3_setaclargs), + .pc_argzero = sizeof(struct nfsd3_setaclargs), .pc_ressize = sizeof(struct nfsd3_attrstat), .pc_cachetype = RC_NOCACHE, .pc_xdrressize = ST+pAT,
fs/nfsd/nfs3proc.c +22 -0
@@ -809,6 +809,7 @@ static const struct svc_procedure nfsd_procedures3[22] = { .pc_decode = nfssvc_decode_voidarg, .pc_encode = nfssvc_encode_voidres, .pc_argsize = sizeof(struct nfsd_voidargs), + .pc_argzero = sizeof(struct nfsd_voidargs), .pc_ressize = sizeof(struct nfsd_voidres), .pc_cachetype = RC_NOCACHE, .pc_xdrressize = ST,
@@ -820,6 +821,7 @@ static const struct svc_procedure nfsd_procedures3[22] = { .pc_encode = nfs3svc_encode_getattrres, .pc_release = nfs3svc_release_fhandle, .pc_argsize = sizeof(struct nfsd_fhandle), + .pc_argzero = sizeof(struct nfsd_fhandle), .pc_ressize = sizeof(struct nfsd3_attrstatres), .pc_cachetype = RC_NOCACHE, .pc_xdrressize = ST+AT,
@@ -831,6 +833,7 @@ static const struct svc_procedure nfsd_procedures3[22] = { .pc_encode = nfs3svc_encode_wccstatres, .pc_release = nfs3svc_release_fhandle, .pc_argsize = sizeof(struct nfsd3_sattrargs), + .pc_argzero = sizeof(struct nfsd3_sattrargs), .pc_ressize = sizeof(struct nfsd3_wccstatres), .pc_cachetype = RC_REPLBUFF, .pc_xdrressize = ST+WC,
@@ -842,6 +845,7 @@ static const struct svc_procedure nfsd_procedures3[22] = { .pc_encode = nfs3svc_encode_lookupres, .pc_release = nfs3svc_release_fhandle2, .pc_argsize = sizeof(struct nfsd3_diropargs), + .pc_argzero = sizeof(struct nfsd3_diropargs), .pc_ressize = sizeof(struct nfsd3_diropres), .pc_cachetype = RC_NOCACHE, .pc_xdrressize = ST+FH+pAT+pAT,
@@ -853,6 +857,7 @@ static const struct svc_procedure nfsd_procedures3[22] = { .pc_encode = nfs3svc_encode_accessres, .pc_release = nfs3svc_release_fhandle, .pc_argsize = sizeof(struct nfsd3_accessargs), + .pc_argzero = sizeof(struct nfsd3_accessargs), .pc_ressize = sizeof(struct nfsd3_accessres), .pc_cachetype = RC_NOCACHE, .pc_xdrressize = ST+pAT+1,
@@ -864,6 +869,7 @@ static const struct svc_procedure nfsd_procedures3[22] = { .pc_encode = nfs3svc_encode_readlinkres, .pc_release = nfs3svc_release_fhandle, .pc_argsize = sizeof(struct nfsd_fhandle), + .pc_argzero = sizeof(struct nfsd_fhandle), .pc_ressize = sizeof(struct nfsd3_readlinkres), .pc_cachetype = RC_NOCACHE, .pc_xdrressize = ST+pAT+1+NFS3_MAXPATHLEN/4,
@@ -875,6 +881,7 @@ static const struct svc_procedure nfsd_procedures3[22] = { .pc_encode = nfs3svc_encode_readres, .pc_release = nfs3svc_release_fhandle, .pc_argsize = sizeof(struct nfsd3_readargs), + .pc_argzero = sizeof(struct nfsd3_readargs), .pc_ressize = sizeof(struct nfsd3_readres), .pc_cachetype = RC_NOCACHE, .pc_xdrressize = ST+pAT+4+NFSSVC_MAXBLKSIZE/4,
@@ -886,6 +893,7 @@ static const struct svc_procedure nfsd_procedures3[22] = { .pc_encode = nfs3svc_encode_writeres, .pc_release = nfs3svc_release_fhandle, .pc_argsize = sizeof(struct nfsd3_writeargs), + .pc_argzero = sizeof(struct nfsd3_writeargs), .pc_ressize = sizeof(struct nfsd3_writeres), .pc_cachetype = RC_REPLBUFF, .pc_xdrressize = ST+WC+4,
@@ -897,6 +905,7 @@ static const struct svc_procedure nfsd_procedures3[22] = { .pc_encode = nfs3svc_encode_createres, .pc_release = nfs3svc_release_fhandle2, .pc_argsize = sizeof(struct nfsd3_createargs), + .pc_argzero = sizeof(struct nfsd3_createargs), .pc_ressize = sizeof(struct nfsd3_createres), .pc_cachetype = RC_REPLBUFF, .pc_xdrressize = ST+(1+FH+pAT)+WC,
@@ -908,6 +917,7 @@ static const struct svc_procedure nfsd_procedures3[22] = { .pc_encode = nfs3svc_encode_createres, .pc_release = nfs3svc_release_fhandle2, .pc_argsize = sizeof(struct nfsd3_mkdirargs), + .pc_argzero = sizeof(struct nfsd3_mkdirargs), .pc_ressize = sizeof(struct nfsd3_createres), .pc_cachetype = RC_REPLBUFF, .pc_xdrressize = ST+(1+FH+pAT)+WC,
@@ -919,6 +929,7 @@ static const struct svc_procedure nfsd_procedures3[22] = { .pc_encode = nfs3svc_encode_createres, .pc_release = nfs3svc_release_fhandle2, .pc_argsize = sizeof(struct nfsd3_symlinkargs), + .pc_argzero = sizeof(struct nfsd3_symlinkargs), .pc_ressize = sizeof(struct nfsd3_createres), .pc_cachetype = RC_REPLBUFF, .pc_xdrressize = ST+(1+FH+pAT)+WC,
@@ -930,6 +941,7 @@ static const struct svc_procedure nfsd_procedures3[22] = { .pc_encode = nfs3svc_encode_createres, .pc_release = nfs3svc_release_fhandle2, .pc_argsize = sizeof(struct nfsd3_mknodargs), + .pc_argzero = sizeof(struct nfsd3_mknodargs), .pc_ressize = sizeof(struct nfsd3_createres), .pc_cachetype = RC_REPLBUFF, .pc_xdrressize = ST+(1+FH+pAT)+WC,
@@ -941,6 +953,7 @@ static const struct svc_procedure nfsd_procedures3[22] = { .pc_encode = nfs3svc_encode_wccstatres, .pc_release = nfs3svc_release_fhandle, .pc_argsize = sizeof(struct nfsd3_diropargs), + .pc_argzero = sizeof(struct nfsd3_diropargs), .pc_ressize = sizeof(struct nfsd3_wccstatres), .pc_cachetype = RC_REPLBUFF, .pc_xdrressize = ST+WC,
@@ -952,6 +965,7 @@ static const struct svc_procedure nfsd_procedures3[22] = { .pc_encode = nfs3svc_encode_wccstatres, .pc_release = nfs3svc_release_fhandle, .pc_argsize = sizeof(struct nfsd3_diropargs), + .pc_argzero = sizeof(struct nfsd3_diropargs), .pc_ressize = sizeof(struct nfsd3_wccstatres), .pc_cachetype = RC_REPLBUFF, .pc_xdrressize = ST+WC,
@@ -963,6 +977,7 @@ static const struct svc_procedure nfsd_procedures3[22] = { .pc_encode = nfs3svc_encode_renameres, .pc_release = nfs3svc_release_fhandle2, .pc_argsize = sizeof(struct nfsd3_renameargs), + .pc_argzero = sizeof(struct nfsd3_renameargs), .pc_ressize = sizeof(struct nfsd3_renameres), .pc_cachetype = RC_REPLBUFF, .pc_xdrressize = ST+WC+WC,
@@ -974,6 +989,7 @@ static const struct svc_procedure nfsd_procedures3[22] = { .pc_encode = nfs3svc_encode_linkres, .pc_release = nfs3svc_release_fhandle2, .pc_argsize = sizeof(struct nfsd3_linkargs), + .pc_argzero = sizeof(struct nfsd3_linkargs), .pc_ressize = sizeof(struct nfsd3_linkres), .pc_cachetype = RC_REPLBUFF, .pc_xdrressize = ST+pAT+WC,
@@ -985,6 +1001,7 @@ static const struct svc_procedure nfsd_procedures3[22] = { .pc_encode = nfs3svc_encode_readdirres, .pc_release = nfs3svc_release_fhandle, .pc_argsize = sizeof(struct nfsd3_readdirargs), + .pc_argzero = sizeof(struct nfsd3_readdirargs), .pc_ressize = sizeof(struct nfsd3_readdirres), .pc_cachetype = RC_NOCACHE, .pc_name = "READDIR",
@@ -995,6 +1012,7 @@ static const struct svc_procedure nfsd_procedures3[22] = { .pc_encode = nfs3svc_encode_readdirres, .pc_release = nfs3svc_release_fhandle, .pc_argsize = sizeof(struct nfsd3_readdirplusargs), + .pc_argzero = sizeof(struct nfsd3_readdirplusargs), .pc_ressize = sizeof(struct nfsd3_readdirres), .pc_cachetype = RC_NOCACHE, .pc_name = "READDIRPLUS",
@@ -1004,6 +1022,7 @@ static const struct svc_procedure nfsd_procedures3[22] = { .pc_decode = nfs3svc_decode_fhandleargs, .pc_encode = nfs3svc_encode_fsstatres, .pc_argsize = sizeof(struct nfsd3_fhandleargs), + .pc_argzero = sizeof(struct nfsd3_fhandleargs), .pc_ressize = sizeof(struct nfsd3_fsstatres), .pc_cachetype = RC_NOCACHE, .pc_xdrressize = ST+pAT+2*6+1,
@@ -1014,6 +1033,7 @@ static const struct svc_procedure nfsd_procedures3[22] = { .pc_decode = nfs3svc_decode_fhandleargs, .pc_encode = nfs3svc_encode_fsinfores, .pc_argsize = sizeof(struct nfsd3_fhandleargs), + .pc_argzero = sizeof(struct nfsd3_fhandleargs), .pc_ressize = sizeof(struct nfsd3_fsinfores), .pc_cachetype = RC_NOCACHE, .pc_xdrressize = ST+pAT+12,
@@ -1024,6 +1044,7 @@ static const struct svc_procedure nfsd_procedures3[22] = { .pc_decode = nfs3svc_decode_fhandleargs, .pc_encode = nfs3svc_encode_pathconfres, .pc_argsize = sizeof(struct nfsd3_fhandleargs), + .pc_argzero = sizeof(struct nfsd3_fhandleargs), .pc_ressize = sizeof(struct nfsd3_pathconfres), .pc_cachetype = RC_NOCACHE, .pc_xdrressize = ST+pAT+6,
@@ -1035,6 +1056,7 @@ static const struct svc_procedure nfsd_procedures3[22] = { .pc_encode = nfs3svc_encode_commitres, .pc_release = nfs3svc_release_fhandle, .pc_argsize = sizeof(struct nfsd3_commitargs), + .pc_argzero = sizeof(struct nfsd3_commitargs), .pc_ressize = sizeof(struct nfsd3_commitres), .pc_cachetype = RC_NOCACHE, .pc_xdrressize = ST+WC+2,
fs/nfsd/nfs4proc.c +2 -0
@@ -3577,6 +3577,7 @@ static const struct svc_procedure nfsd_procedures4[2] = { .pc_decode = nfssvc_decode_voidarg, .pc_encode = nfssvc_encode_voidres, .pc_argsize = sizeof(struct nfsd_voidargs), + .pc_argzero = sizeof(struct nfsd_voidargs), .pc_ressize = sizeof(struct nfsd_voidres), .pc_cachetype = RC_NOCACHE, .pc_xdrressize = 1,
@@ -3587,6 +3588,7 @@ static const struct svc_procedure nfsd_procedures4[2] = { .pc_decode = nfs4svc_decode_compoundargs, .pc_encode = nfs4svc_encode_compoundres, .pc_argsize = sizeof(struct nfsd4_compoundargs), + .pc_argzero = sizeof(struct nfsd4_compoundargs), .pc_ressize = sizeof(struct nfsd4_compoundres), .pc_release = nfsd4_release_compoundargs, .pc_cachetype = RC_NOCACHE,
fs/nfsd/nfsproc.c +18 -0
@@ -645,6 +645,7 @@ static const struct svc_procedure nfsd_procedures2[18] = { .pc_decode = nfssvc_decode_voidarg, .pc_encode = nfssvc_encode_voidres, .pc_argsize = sizeof(struct nfsd_voidargs), + .pc_argzero = sizeof(struct nfsd_voidargs), .pc_ressize = sizeof(struct nfsd_voidres), .pc_cachetype = RC_NOCACHE, .pc_xdrressize = 0,
@@ -656,6 +657,7 @@ static const struct svc_procedure nfsd_procedures2[18] = { .pc_encode = nfssvc_encode_attrstatres, .pc_release = nfssvc_release_attrstat, .pc_argsize = sizeof(struct nfsd_fhandle), + .pc_argzero = sizeof(struct nfsd_fhandle), .pc_ressize = sizeof(struct nfsd_attrstat), .pc_cachetype = RC_NOCACHE, .pc_xdrressize = ST+AT,
@@ -667,6 +669,7 @@ static const struct svc_procedure nfsd_procedures2[18] = { .pc_encode = nfssvc_encode_attrstatres, .pc_release = nfssvc_release_attrstat, .pc_argsize = sizeof(struct nfsd_sattrargs), + .pc_argzero = sizeof(struct nfsd_sattrargs), .pc_ressize = sizeof(struct nfsd_attrstat), .pc_cachetype = RC_REPLBUFF, .pc_xdrressize = ST+AT,
@@ -677,6 +680,7 @@ static const struct svc_procedure nfsd_procedures2[18] = { .pc_decode = nfssvc_decode_voidarg, .pc_encode = nfssvc_encode_voidres, .pc_argsize = sizeof(struct nfsd_voidargs), + .pc_argzero = sizeof(struct nfsd_voidargs), .pc_ressize = sizeof(struct nfsd_voidres), .pc_cachetype = RC_NOCACHE, .pc_xdrressize = 0,
@@ -688,6 +692,7 @@ static const struct svc_procedure nfsd_procedures2[18] = { .pc_encode = nfssvc_encode_diropres, .pc_release = nfssvc_release_diropres, .pc_argsize = sizeof(struct nfsd_diropargs), + .pc_argzero = sizeof(struct nfsd_diropargs), .pc_ressize = sizeof(struct nfsd_diropres), .pc_cachetype = RC_NOCACHE, .pc_xdrressize = ST+FH+AT,
@@ -698,6 +703,7 @@ static const struct svc_procedure nfsd_procedures2[18] = { .pc_decode = nfssvc_decode_fhandleargs, .pc_encode = nfssvc_encode_readlinkres, .pc_argsize = sizeof(struct nfsd_fhandle), + .pc_argzero = sizeof(struct nfsd_fhandle), .pc_ressize = sizeof(struct nfsd_readlinkres), .pc_cachetype = RC_NOCACHE, .pc_xdrressize = ST+1+NFS_MAXPATHLEN/4,
@@ -709,6 +715,7 @@ static const struct svc_procedure nfsd_procedures2[18] = { .pc_encode = nfssvc_encode_readres, .pc_release = nfssvc_release_readres, .pc_argsize = sizeof(struct nfsd_readargs), + .pc_argzero = sizeof(struct nfsd_readargs), .pc_ressize = sizeof(struct nfsd_readres), .pc_cachetype = RC_NOCACHE, .pc_xdrressize = ST+AT+1+NFSSVC_MAXBLKSIZE_V2/4,
@@ -719,6 +726,7 @@ static const struct svc_procedure nfsd_procedures2[18] = { .pc_decode = nfssvc_decode_voidarg, .pc_encode = nfssvc_encode_voidres, .pc_argsize = sizeof(struct nfsd_voidargs), + .pc_argzero = sizeof(struct nfsd_voidargs), .pc_ressize = sizeof(struct nfsd_voidres), .pc_cachetype = RC_NOCACHE, .pc_xdrressize = 0,
@@ -730,6 +738,7 @@ static const struct svc_procedure nfsd_procedures2[18] = { .pc_encode = nfssvc_encode_attrstatres, .pc_release = nfssvc_release_attrstat, .pc_argsize = sizeof(struct nfsd_writeargs), + .pc_argzero = sizeof(struct nfsd_writeargs), .pc_ressize = sizeof(struct nfsd_attrstat), .pc_cachetype = RC_REPLBUFF, .pc_xdrressize = ST+AT,
@@ -741,6 +750,7 @@ static const struct svc_procedure nfsd_procedures2[18] = { .pc_encode = nfssvc_encode_diropres, .pc_release = nfssvc_release_diropres, .pc_argsize = sizeof(struct nfsd_createargs), + .pc_argzero = sizeof(struct nfsd_createargs), .pc_ressize = sizeof(struct nfsd_diropres), .pc_cachetype = RC_REPLBUFF, .pc_xdrressize = ST+FH+AT,
@@ -751,6 +761,7 @@ static const struct svc_procedure nfsd_procedures2[18] = { .pc_decode = nfssvc_decode_diropargs, .pc_encode = nfssvc_encode_statres, .pc_argsize = sizeof(struct nfsd_diropargs), + .pc_argzero = sizeof(struct nfsd_diropargs), .pc_ressize = sizeof(struct nfsd_stat), .pc_cachetype = RC_REPLSTAT, .pc_xdrressize = ST,
@@ -761,6 +772,7 @@ static const struct svc_procedure nfsd_procedures2[18] = { .pc_decode = nfssvc_decode_renameargs, .pc_encode = nfssvc_encode_statres, .pc_argsize = sizeof(struct nfsd_renameargs), + .pc_argzero = sizeof(struct nfsd_renameargs), .pc_ressize = sizeof(struct nfsd_stat), .pc_cachetype = RC_REPLSTAT, .pc_xdrressize = ST,
@@ -771,6 +783,7 @@ static const struct svc_procedure nfsd_procedures2[18] = { .pc_decode = nfssvc_decode_linkargs, .pc_encode = nfssvc_encode_statres, .pc_argsize = sizeof(struct nfsd_linkargs), + .pc_argzero = sizeof(struct nfsd_linkargs), .pc_ressize = sizeof(struct nfsd_stat), .pc_cachetype = RC_REPLSTAT, .pc_xdrressize = ST,
@@ -781,6 +794,7 @@ static const struct svc_procedure nfsd_procedures2[18] = { .pc_decode = nfssvc_decode_symlinkargs, .pc_encode = nfssvc_encode_statres, .pc_argsize = sizeof(struct nfsd_symlinkargs), + .pc_argzero = sizeof(struct nfsd_symlinkargs), .pc_ressize = sizeof(struct nfsd_stat), .pc_cachetype = RC_REPLSTAT, .pc_xdrressize = ST,
@@ -792,6 +806,7 @@ static const struct svc_procedure nfsd_procedures2[18] = { .pc_encode = nfssvc_encode_diropres, .pc_release = nfssvc_release_diropres, .pc_argsize = sizeof(struct nfsd_createargs), + .pc_argzero = sizeof(struct nfsd_createargs), .pc_ressize = sizeof(struct nfsd_diropres), .pc_cachetype = RC_REPLBUFF, .pc_xdrressize = ST+FH+AT,
@@ -802,6 +817,7 @@ static const struct svc_procedure nfsd_procedures2[18] = { .pc_decode = nfssvc_decode_diropargs, .pc_encode = nfssvc_encode_statres, .pc_argsize = sizeof(struct nfsd_diropargs), + .pc_argzero = sizeof(struct nfsd_diropargs), .pc_ressize = sizeof(struct nfsd_stat), .pc_cachetype = RC_REPLSTAT, .pc_xdrressize = ST,
@@ -812,6 +828,7 @@ static const struct svc_procedure nfsd_procedures2[18] = { .pc_decode = nfssvc_decode_readdirargs, .pc_encode = nfssvc_encode_readdirres, .pc_argsize = sizeof(struct nfsd_readdirargs), + .pc_argzero = sizeof(struct nfsd_readdirargs), .pc_ressize = sizeof(struct nfsd_readdirres), .pc_cachetype = RC_NOCACHE, .pc_name = "READDIR",
@@ -821,6 +838,7 @@ static const struct svc_procedure nfsd_procedures2[18] = { .pc_decode = nfssvc_decode_fhandleargs, .pc_encode = nfssvc_encode_statfsres, .pc_argsize = sizeof(struct nfsd_fhandle), + .pc_argzero = sizeof(struct nfsd_fhandle), .pc_ressize = sizeof(struct nfsd_statfsres), .pc_cachetype = RC_NOCACHE, .pc_xdrressize = ST+5,
include/linux/sunrpc/svc.h +1 -0
@@ -476,6 +476,7 @@ struct svc_procedure {/* XDR free result: */ void (*pc_release)(struct svc_rqst *);unsigned int pc_argsize;/* argument struct size */ +unsigned int pc_argzero;/* how much of argument to clear */ unsigned int pc_ressize;/* result struct size */ unsigned int pc_cachetype;/* cache info (NFS) */ unsigned int pc_xdrressize;/* maximum size of XDR reply */
net/sunrpc/svc.c +1 -1
@@ -1237,7 +1237,7 @@ svc_generic_init_request(struct svc_rqst *rqstp, rqstp->rq_procinfo = procp = &versp->vs_proc[rqstp->rq_proc];/* Initialize storage for argp and resp */ -memset (rqstp->rq_argp,0 , procp->pc_argsize); +memset (rqstp->rq_argp,0 , procp->pc_argzero);memset (rqstp->rq_resp,0 , procp->pc_ressize);/* Bump per-procedure stats counter */
Signature · 1 line
2.43.0