Skip to content

Commit 5abc743

Browse files
committed
Merge tag 'nfs-for-6.16-1' of git://git.linux-nfs.org/projects/anna/linux-nfs
Pull NFS clent updates from Anna Schumaker: "New Features: - Implement the Sunrpc rfc2203 rpcsec_gss sequence number cache - Add support for FALLOC_FL_ZERO_RANGE on NFS v4.2 - Add a localio sysfs attribute Stable Fixes: - Fix double-unlock bug in nfs_return_empty_folio() - Don't check for OPEN feature support in v4.1 - Always probe for LOCALIO support asynchronously - Prevent hang on NFS mounts with xprtsec=[m]tls Other Bugfixes: - xattr handlers should check for absent nfs filehandles - Fix setattr caching of TIME_[MODIFY|ACCESS]_SET when timestamps are delegated - Fix listxattr to return selinux security labels - Connect to NFSv3 DS using TLS if MDS connection uses TLS - Clear SB_RDONLY before getting a superblock, and ignore when remounting - Fix incorrect handling of NFS error codes in nfs4_do_mkdir() - Various nfs_localio fixes from Neil Brown that include fixing an rcu compilation error found by older gcc versions. - Update stats on flexfiles pNFS DSes when receiving NFS4ERR_DELAY Cleanups: - Add a refcount tracker for struct net in the nfs_client - Allow FREE_STATEID to clean up delegations - Always set NLINK even if the server doesn't support it - Cleanups to the NFS folio writeback code - Remove dead code from xs_tcp_tls_setup_socket()" * tag 'nfs-for-6.16-1' of git://git.linux-nfs.org/projects/anna/linux-nfs: (30 commits) flexfiles/pNFS: update stats on NFS4ERR_DELAY for v4.1 DSes nfs_localio: change nfsd_file_put_local() to take a pointer to __rcu pointer nfs_localio: protect race between nfs_uuid_put() and nfs_close_local_fh() nfs_localio: duplicate nfs_close_local_fh() nfs_localio: simplify interface to nfsd for getting nfsd_file nfs_localio: always hold nfsd net ref with nfsd_file ref nfs_localio: use cmpxchg() to install new nfs_file_localio SUNRPC: Remove dead code from xs_tcp_tls_setup_socket() SUNRPC: Prevent hang on NFS mount with xprtsec=[m]tls nfs: fix incorrect handling of large-number NFS errors in nfs4_do_mkdir() nfs: ignore SB_RDONLY when remounting nfs nfs: clear SB_RDONLY before getting superblock NFS: always probe for LOCALIO support asynchronously pnfs/flexfiles: connect to NFSv3 DS using TLS if MDS connection uses TLS NFS: add localio to sysfs nfs: use writeback_iter directly nfs: refactor nfs_do_writepage nfs: don't return AOP_WRITEPAGE_ACTIVATE from nfs_do_writepage nfs: fold nfs_page_async_flush into nfs_do_writepage NFSv4: Always set NLINK even if the server doesn't support it ...
2 parents 6d9b5f6 + e3e3775 commit 5abc743

33 files changed

+554
-226
lines changed

fs/nfs/client.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
180180
clp->cl_proto = cl_init->proto;
181181
clp->cl_nconnect = cl_init->nconnect;
182182
clp->cl_max_connect = cl_init->max_connect ? cl_init->max_connect : 1;
183-
clp->cl_net = get_net(cl_init->net);
183+
clp->cl_net = get_net_track(cl_init->net, &clp->cl_ns_tracker, GFP_KERNEL);
184184

185185
#if IS_ENABLED(CONFIG_NFS_LOCALIO)
186186
seqlock_init(&clp->cl_boot_lock);
@@ -250,7 +250,7 @@ void nfs_free_client(struct nfs_client *clp)
250250
if (!IS_ERR(clp->cl_rpcclient))
251251
rpc_shutdown_client(clp->cl_rpcclient);
252252

253-
put_net(clp->cl_net);
253+
put_net_track(clp->cl_net, &clp->cl_ns_tracker);
254254
put_nfs_version(clp->cl_nfs_mod);
255255
kfree(clp->cl_hostname);
256256
kfree(clp->cl_acceptor);
@@ -439,7 +439,7 @@ struct nfs_client *nfs_get_client(const struct nfs_client_initdata *cl_init)
439439
spin_unlock(&nn->nfs_client_lock);
440440
new = rpc_ops->init_client(new, cl_init);
441441
if (!IS_ERR(new))
442-
nfs_local_probe(new);
442+
nfs_local_probe_async(new);
443443
return new;
444444
}
445445

fs/nfs/delegation.c

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,13 +1021,6 @@ static void nfs_revoke_delegation(struct inode *inode,
10211021
nfs_inode_find_state_and_recover(inode, stateid);
10221022
}
10231023

1024-
void nfs_remove_bad_delegation(struct inode *inode,
1025-
const nfs4_stateid *stateid)
1026-
{
1027-
nfs_revoke_delegation(inode, stateid);
1028-
}
1029-
EXPORT_SYMBOL_GPL(nfs_remove_bad_delegation);
1030-
10311024
void nfs_delegation_mark_returned(struct inode *inode,
10321025
const nfs4_stateid *stateid)
10331026
{
@@ -1069,6 +1062,24 @@ void nfs_delegation_mark_returned(struct inode *inode,
10691062
nfs_inode_find_state_and_recover(inode, stateid);
10701063
}
10711064

1065+
/**
1066+
* nfs_remove_bad_delegation - handle delegations that are unusable
1067+
* @inode: inode to process
1068+
* @stateid: the delegation's stateid
1069+
*
1070+
* If the server ACK-ed our FREE_STATEID then clean
1071+
* up the delegation, else mark and keep the revoked state.
1072+
*/
1073+
void nfs_remove_bad_delegation(struct inode *inode,
1074+
const nfs4_stateid *stateid)
1075+
{
1076+
if (stateid && stateid->type == NFS4_FREED_STATEID_TYPE)
1077+
nfs_delegation_mark_returned(inode, stateid);
1078+
else
1079+
nfs_revoke_delegation(inode, stateid);
1080+
}
1081+
EXPORT_SYMBOL_GPL(nfs_remove_bad_delegation);
1082+
10721083
/**
10731084
* nfs_expire_unused_delegation_types
10741085
* @clp: client to process

fs/nfs/flexfilelayout/flexfilelayout.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1129,6 +1129,8 @@ static int ff_layout_async_handle_error_v4(struct rpc_task *task,
11291129
nfs4_schedule_session_recovery(clp->cl_session, task->tk_status);
11301130
break;
11311131
case -NFS4ERR_DELAY:
1132+
nfs_inc_stats(lseg->pls_layout->plh_inode, NFSIOS_DELAY);
1133+
fallthrough;
11321134
case -NFS4ERR_GRACE:
11331135
rpc_delay(task, FF_LAYOUT_POLL_RETRY_MAX);
11341136
break;

fs/nfs/flexfilelayout/flexfilelayoutdev.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,7 @@ nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg,
400400
* keep ds_clp even if DS is local, so that if local IO cannot
401401
* proceed somehow, we can fall back to NFS whenever we want.
402402
*/
403-
nfs_local_probe(ds->ds_clp);
403+
nfs_local_probe_async(ds->ds_clp);
404404
max_payload =
405405
nfs_block_size(rpc_max_payload(ds->ds_clp->cl_rpcclient),
406406
NULL);

fs/nfs/inode.c

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,8 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
557557
set_nlink(inode, fattr->nlink);
558558
else if (fattr_supported & NFS_ATTR_FATTR_NLINK)
559559
nfs_set_cache_invalid(inode, NFS_INO_INVALID_NLINK);
560+
else
561+
set_nlink(inode, 1);
560562
if (fattr->valid & NFS_ATTR_FATTR_OWNER)
561563
inode->i_uid = fattr->uid;
562564
else if (fattr_supported & NFS_ATTR_FATTR_OWNER)
@@ -633,6 +635,34 @@ nfs_fattr_fixup_delegated(struct inode *inode, struct nfs_fattr *fattr)
633635
}
634636
}
635637

638+
static void nfs_set_timestamps_to_ts(struct inode *inode, struct iattr *attr)
639+
{
640+
unsigned int cache_flags = 0;
641+
642+
if (attr->ia_valid & ATTR_MTIME_SET) {
643+
struct timespec64 ctime = inode_get_ctime(inode);
644+
struct timespec64 mtime = inode_get_mtime(inode);
645+
struct timespec64 now;
646+
int updated = 0;
647+
648+
now = inode_set_ctime_current(inode);
649+
if (!timespec64_equal(&now, &ctime))
650+
updated |= S_CTIME;
651+
652+
inode_set_mtime_to_ts(inode, attr->ia_mtime);
653+
if (!timespec64_equal(&now, &mtime))
654+
updated |= S_MTIME;
655+
656+
inode_maybe_inc_iversion(inode, updated);
657+
cache_flags |= NFS_INO_INVALID_CTIME | NFS_INO_INVALID_MTIME;
658+
}
659+
if (attr->ia_valid & ATTR_ATIME_SET) {
660+
inode_set_atime_to_ts(inode, attr->ia_atime);
661+
cache_flags |= NFS_INO_INVALID_ATIME;
662+
}
663+
NFS_I(inode)->cache_validity &= ~cache_flags;
664+
}
665+
636666
static void nfs_update_timestamps(struct inode *inode, unsigned int ia_valid)
637667
{
638668
enum file_time_flags time_flags = 0;
@@ -701,14 +731,27 @@ nfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
701731

702732
if (nfs_have_delegated_mtime(inode) && attr->ia_valid & ATTR_MTIME) {
703733
spin_lock(&inode->i_lock);
704-
nfs_update_timestamps(inode, attr->ia_valid);
734+
if (attr->ia_valid & ATTR_MTIME_SET) {
735+
nfs_set_timestamps_to_ts(inode, attr);
736+
attr->ia_valid &= ~(ATTR_MTIME|ATTR_MTIME_SET|
737+
ATTR_ATIME|ATTR_ATIME_SET);
738+
} else {
739+
nfs_update_timestamps(inode, attr->ia_valid);
740+
attr->ia_valid &= ~(ATTR_MTIME|ATTR_ATIME);
741+
}
705742
spin_unlock(&inode->i_lock);
706-
attr->ia_valid &= ~(ATTR_MTIME | ATTR_ATIME);
707743
} else if (nfs_have_delegated_atime(inode) &&
708744
attr->ia_valid & ATTR_ATIME &&
709745
!(attr->ia_valid & ATTR_MTIME)) {
710-
nfs_update_delegated_atime(inode);
711-
attr->ia_valid &= ~ATTR_ATIME;
746+
if (attr->ia_valid & ATTR_ATIME_SET) {
747+
spin_lock(&inode->i_lock);
748+
nfs_set_timestamps_to_ts(inode, attr);
749+
spin_unlock(&inode->i_lock);
750+
attr->ia_valid &= ~(ATTR_ATIME|ATTR_ATIME_SET);
751+
} else {
752+
nfs_update_delegated_atime(inode);
753+
attr->ia_valid &= ~ATTR_ATIME;
754+
}
712755
}
713756

714757
/* Optimization: if the end result is no change, don't RPC */

fs/nfs/internal.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,6 @@ extern int nfs_wait_bit_killable(struct wait_bit_key *key, int mode);
455455

456456
#if IS_ENABLED(CONFIG_NFS_LOCALIO)
457457
/* localio.c */
458-
extern void nfs_local_probe(struct nfs_client *);
459458
extern void nfs_local_probe_async(struct nfs_client *);
460459
extern void nfs_local_probe_async_work(struct work_struct *);
461460
extern struct nfsd_file *nfs_local_open_fh(struct nfs_client *,

fs/nfs/localio.c

Lines changed: 18 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ static bool nfs_server_uuid_is_local(struct nfs_client *clp)
171171
* - called after alloc_client and init_client (so cl_rpcclient exists)
172172
* - this function is idempotent, it can be called for old or new clients
173173
*/
174-
void nfs_local_probe(struct nfs_client *clp)
174+
static void nfs_local_probe(struct nfs_client *clp)
175175
{
176176
/* Disallow localio if disabled via sysfs or AUTH_SYS isn't used */
177177
if (!localio_enabled ||
@@ -191,14 +191,16 @@ void nfs_local_probe(struct nfs_client *clp)
191191
nfs_localio_enable_client(clp);
192192
nfs_uuid_end(&clp->cl_uuid);
193193
}
194-
EXPORT_SYMBOL_GPL(nfs_local_probe);
195194

196195
void nfs_local_probe_async_work(struct work_struct *work)
197196
{
198197
struct nfs_client *clp =
199198
container_of(work, struct nfs_client, cl_local_probe_work);
200199

200+
if (!refcount_inc_not_zero(&clp->cl_count))
201+
return;
201202
nfs_local_probe(clp);
203+
nfs_put_client(clp);
202204
}
203205

204206
void nfs_local_probe_async(struct nfs_client *clp)
@@ -207,14 +209,16 @@ void nfs_local_probe_async(struct nfs_client *clp)
207209
}
208210
EXPORT_SYMBOL_GPL(nfs_local_probe_async);
209211

210-
static inline struct nfsd_file *nfs_local_file_get(struct nfsd_file *nf)
212+
static inline void nfs_local_file_put(struct nfsd_file *localio)
211213
{
212-
return nfs_to->nfsd_file_get(nf);
213-
}
214+
/* nfs_to_nfsd_file_put_local() expects an __rcu pointer
215+
* but we have a __kernel pointer. It is always safe
216+
* to cast a __kernel pointer to an __rcu pointer
217+
* because the cast only weakens what is known about the pointer.
218+
*/
219+
struct nfsd_file __rcu *nf = (struct nfsd_file __rcu*) localio;
214220

215-
static inline void nfs_local_file_put(struct nfsd_file *nf)
216-
{
217-
nfs_to->nfsd_file_put(nf);
221+
nfs_to_nfsd_file_put_local(&nf);
218222
}
219223

220224
/*
@@ -226,12 +230,13 @@ static inline void nfs_local_file_put(struct nfsd_file *nf)
226230
static struct nfsd_file *
227231
__nfs_local_open_fh(struct nfs_client *clp, const struct cred *cred,
228232
struct nfs_fh *fh, struct nfs_file_localio *nfl,
233+
struct nfsd_file __rcu **pnf,
229234
const fmode_t mode)
230235
{
231236
struct nfsd_file *localio;
232237

233238
localio = nfs_open_local_fh(&clp->cl_uuid, clp->cl_rpcclient,
234-
cred, fh, nfl, mode);
239+
cred, fh, nfl, pnf, mode);
235240
if (IS_ERR(localio)) {
236241
int status = PTR_ERR(localio);
237242
trace_nfs_local_open_fh(fh, mode, status);
@@ -258,7 +263,7 @@ nfs_local_open_fh(struct nfs_client *clp, const struct cred *cred,
258263
struct nfs_fh *fh, struct nfs_file_localio *nfl,
259264
const fmode_t mode)
260265
{
261-
struct nfsd_file *nf, *new, __rcu **pnf;
266+
struct nfsd_file *nf, __rcu **pnf;
262267

263268
if (!nfs_server_is_local(clp))
264269
return NULL;
@@ -270,29 +275,9 @@ nfs_local_open_fh(struct nfs_client *clp, const struct cred *cred,
270275
else
271276
pnf = &nfl->ro_file;
272277

273-
new = NULL;
274-
rcu_read_lock();
275-
nf = rcu_dereference(*pnf);
276-
if (!nf) {
277-
rcu_read_unlock();
278-
new = __nfs_local_open_fh(clp, cred, fh, nfl, mode);
279-
if (IS_ERR(new))
280-
return NULL;
281-
rcu_read_lock();
282-
/* try to swap in the pointer */
283-
spin_lock(&clp->cl_uuid.lock);
284-
nf = rcu_dereference_protected(*pnf, 1);
285-
if (!nf) {
286-
nf = new;
287-
new = NULL;
288-
rcu_assign_pointer(*pnf, nf);
289-
}
290-
spin_unlock(&clp->cl_uuid.lock);
291-
}
292-
nf = nfs_local_file_get(nf);
293-
rcu_read_unlock();
294-
if (new)
295-
nfs_to_nfsd_file_put_local(new);
278+
nf = __nfs_local_open_fh(clp, cred, fh, nfl, pnf, mode);
279+
if (IS_ERR(nf))
280+
return NULL;
296281
return nf;
297282
}
298283
EXPORT_SYMBOL_GPL(nfs_local_open_fh);

fs/nfs/nfs42.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ int nfs42_proc_allocate(struct file *, loff_t, loff_t);
2121
ssize_t nfs42_proc_copy(struct file *, loff_t, struct file *, loff_t, size_t,
2222
struct nl4_server *, nfs4_stateid *, bool);
2323
int nfs42_proc_deallocate(struct file *, loff_t, loff_t);
24+
int nfs42_proc_zero_range(struct file *, loff_t, loff_t);
2425
loff_t nfs42_proc_llseek(struct file *, loff_t, int);
2526
int nfs42_proc_layoutstats_generic(struct nfs_server *,
2627
struct nfs42_layoutstat_data *);

fs/nfs/nfs42proc.c

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,8 @@ int nfs42_proc_allocate(struct file *filep, loff_t offset, loff_t len)
146146

147147
err = nfs42_proc_fallocate(&msg, filep, offset, len);
148148
if (err == -EOPNOTSUPP)
149-
NFS_SERVER(inode)->caps &= ~NFS_CAP_ALLOCATE;
149+
NFS_SERVER(inode)->caps &= ~(NFS_CAP_ALLOCATE |
150+
NFS_CAP_ZERO_RANGE);
150151

151152
inode_unlock(inode);
152153
return err;
@@ -169,7 +170,31 @@ int nfs42_proc_deallocate(struct file *filep, loff_t offset, loff_t len)
169170
if (err == 0)
170171
truncate_pagecache_range(inode, offset, (offset + len) -1);
171172
if (err == -EOPNOTSUPP)
172-
NFS_SERVER(inode)->caps &= ~NFS_CAP_DEALLOCATE;
173+
NFS_SERVER(inode)->caps &= ~(NFS_CAP_DEALLOCATE |
174+
NFS_CAP_ZERO_RANGE);
175+
176+
inode_unlock(inode);
177+
return err;
178+
}
179+
180+
int nfs42_proc_zero_range(struct file *filep, loff_t offset, loff_t len)
181+
{
182+
struct rpc_message msg = {
183+
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_ZERO_RANGE],
184+
};
185+
struct inode *inode = file_inode(filep);
186+
int err;
187+
188+
if (!nfs_server_capable(inode, NFS_CAP_ZERO_RANGE))
189+
return -EOPNOTSUPP;
190+
191+
inode_lock(inode);
192+
193+
err = nfs42_proc_fallocate(&msg, filep, offset, len);
194+
if (err == 0)
195+
truncate_pagecache_range(inode, offset, (offset + len) -1);
196+
if (err == -EOPNOTSUPP)
197+
NFS_SERVER(inode)->caps &= ~NFS_CAP_ZERO_RANGE;
173198

174199
inode_unlock(inode);
175200
return err;

0 commit comments

Comments
 (0)