Skip to content

Commit

Permalink
Merge tag 'nfs-for-6.10-1' of git://git.linux-nfs.org/projects/trondm…
Browse files Browse the repository at this point in the history
…y/linux-nfs

Pull NFS client updates from Trond Myklebust:
 "Stable fixes:
   - nfs: fix undefined behavior in nfs_block_bits()
   - NFSv4.2: Fix READ_PLUS when server doesn't support OP_READ_PLUS

  Bugfixes:
   - Fix mixing of the lock/nolock and local_lock mount options
   - NFSv4: Fixup smatch warning for ambiguous return
   - NFSv3: Fix remount when using the legacy binary mount api
   - SUNRPC: Fix the handling of expired RPCSEC_GSS contexts
   - SUNRPC: fix the NFSACL RPC retries when soft mounts are enabled
   - rpcrdma: fix handling for RDMA_CM_EVENT_DEVICE_REMOVAL

  Features and cleanups:
   - NFSv3: Use the atomic_open API to fix open(O_CREAT|O_TRUNC)
   - pNFS/filelayout: S layout segment range in LAYOUTGET
   - pNFS: rework pnfs_generic_pg_check_layout to check IO range
   - NFSv2: Turn off enabling of NFS v2 by default"

* tag 'nfs-for-6.10-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
  nfs: fix undefined behavior in nfs_block_bits()
  pNFS: rework pnfs_generic_pg_check_layout to check IO range
  pNFS/filelayout: check layout segment range
  pNFS/filelayout: fixup pNfs allocation modes
  rpcrdma: fix handling for RDMA_CM_EVENT_DEVICE_REMOVAL
  NFS: Don't enable NFS v2 by default
  NFS: Fix READ_PLUS when server doesn't support OP_READ_PLUS
  sunrpc: fix NFSACL RPC retry on soft mount
  SUNRPC: fix handling expired GSS context
  nfs: keep server info for remounts
  NFSv4: Fixup smatch warning for ambiguous return
  NFS: make sure lock/nolock overriding local_lock mount option
  NFS: add atomic_open for NFSv3 to handle O_TRUNC correctly.
  pNFS/filelayout: Specify the layout segment range in LAYOUTGET
  pNFS/filelayout: Remove the whole file layout requirement
  • Loading branch information
torvalds committed May 23, 2024
2 parents b4d88a6 + 3c0a2e0 commit 6d69b6c
Show file tree
Hide file tree
Showing 16 changed files with 129 additions and 68 deletions.
4 changes: 2 additions & 2 deletions fs/nfs/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ config NFS_FS
config NFS_V2
tristate "NFS client support for NFS version 2"
depends on NFS_FS
default y
default n
help
This option enables support for version 2 of the NFS protocol
(RFC 1094) in the kernel's NFS client.

If unsure, say Y.
If unsure, say N.

config NFS_V3
tristate "NFS client support for NFS version 3"
Expand Down
54 changes: 51 additions & 3 deletions fs/nfs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ static int nfs_readdir(struct file *, struct dir_context *);
static int nfs_fsync_dir(struct file *, loff_t, loff_t, int);
static loff_t nfs_llseek_dir(struct file *, loff_t, int);
static void nfs_readdir_clear_array(struct folio *);
static int nfs_do_create(struct inode *dir, struct dentry *dentry,
umode_t mode, int open_flags);

const struct file_operations nfs_dir_operations = {
.llseek = nfs_llseek_dir,
Expand Down Expand Up @@ -2243,6 +2245,41 @@ static int nfs4_lookup_revalidate(struct dentry *dentry, unsigned int flags)

#endif /* CONFIG_NFSV4 */

int nfs_atomic_open_v23(struct inode *dir, struct dentry *dentry,
struct file *file, unsigned int open_flags,
umode_t mode)
{

/* Same as look+open from lookup_open(), but with different O_TRUNC
* handling.
*/
int error = 0;

if (open_flags & O_CREAT) {
file->f_mode |= FMODE_CREATED;
error = nfs_do_create(dir, dentry, mode, open_flags);
if (error)
return error;
return finish_open(file, dentry, NULL);
} else if (d_in_lookup(dentry)) {
/* The only flags nfs_lookup considers are
* LOOKUP_EXCL and LOOKUP_RENAME_TARGET, and
* we want those to be zero so the lookup isn't skipped.
*/
struct dentry *res = nfs_lookup(dir, dentry, 0);

d_lookup_done(dentry);
if (unlikely(res)) {
if (IS_ERR(res))
return PTR_ERR(res);
return finish_no_open(file, res);
}
}
return finish_no_open(file, NULL);

}
EXPORT_SYMBOL_GPL(nfs_atomic_open_v23);

struct dentry *
nfs_add_or_obtain(struct dentry *dentry, struct nfs_fh *fhandle,
struct nfs_fattr *fattr)
Expand Down Expand Up @@ -2303,18 +2340,23 @@ EXPORT_SYMBOL_GPL(nfs_instantiate);
* that the operation succeeded on the server, but an error in the
* reply path made it appear to have failed.
*/
int nfs_create(struct mnt_idmap *idmap, struct inode *dir,
struct dentry *dentry, umode_t mode, bool excl)
static int nfs_do_create(struct inode *dir, struct dentry *dentry,
umode_t mode, int open_flags)
{
struct iattr attr;
int open_flags = excl ? O_CREAT | O_EXCL : O_CREAT;
int error;

open_flags |= O_CREAT;

dfprintk(VFS, "NFS: create(%s/%lu), %pd\n",
dir->i_sb->s_id, dir->i_ino, dentry);

attr.ia_mode = mode;
attr.ia_valid = ATTR_MODE;
if (open_flags & O_TRUNC) {
attr.ia_size = 0;
attr.ia_valid |= ATTR_SIZE;
}

trace_nfs_create_enter(dir, dentry, open_flags);
error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags);
Expand All @@ -2326,6 +2368,12 @@ int nfs_create(struct mnt_idmap *idmap, struct inode *dir,
d_drop(dentry);
return error;
}

int nfs_create(struct mnt_idmap *idmap, struct inode *dir,
struct dentry *dentry, umode_t mode, bool excl)
{
return nfs_do_create(dir, dentry, mode, excl ? O_EXCL : 0);
}
EXPORT_SYMBOL_GPL(nfs_create);

/*
Expand Down
24 changes: 8 additions & 16 deletions fs/nfs/filelayout/filelayout.c
Original file line number Diff line number Diff line change
Expand Up @@ -605,14 +605,6 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo,

dprintk("--> %s\n", __func__);

/* FIXME: remove this check when layout segment support is added */
if (lgr->range.offset != 0 ||
lgr->range.length != NFS4_MAX_UINT64) {
dprintk("%s Only whole file layouts supported. Use MDS i/o\n",
__func__);
goto out;
}

if (fl->pattern_offset > lgr->range.offset) {
dprintk("%s pattern_offset %lld too large\n",
__func__, fl->pattern_offset);
Expand Down Expand Up @@ -875,15 +867,15 @@ static void
filelayout_pg_init_read(struct nfs_pageio_descriptor *pgio,
struct nfs_page *req)
{
pnfs_generic_pg_check_layout(pgio);
pnfs_generic_pg_check_layout(pgio, req);
if (!pgio->pg_lseg) {
pgio->pg_lseg = fl_pnfs_update_layout(pgio->pg_inode,
nfs_req_openctx(req),
0,
NFS4_MAX_UINT64,
req_offset(req),
req->wb_bytes,
IOMODE_READ,
false,
GFP_KERNEL);
nfs_io_gfp_mask());
if (IS_ERR(pgio->pg_lseg)) {
pgio->pg_error = PTR_ERR(pgio->pg_lseg);
pgio->pg_lseg = NULL;
Expand All @@ -899,15 +891,15 @@ static void
filelayout_pg_init_write(struct nfs_pageio_descriptor *pgio,
struct nfs_page *req)
{
pnfs_generic_pg_check_layout(pgio);
pnfs_generic_pg_check_layout(pgio, req);
if (!pgio->pg_lseg) {
pgio->pg_lseg = fl_pnfs_update_layout(pgio->pg_inode,
nfs_req_openctx(req),
0,
NFS4_MAX_UINT64,
req_offset(req),
req->wb_bytes,
IOMODE_RW,
false,
GFP_NOFS);
nfs_io_gfp_mask());
if (IS_ERR(pgio->pg_lseg)) {
pgio->pg_error = PTR_ERR(pgio->pg_lseg);
pgio->pg_lseg = NULL;
Expand Down
12 changes: 2 additions & 10 deletions fs/nfs/flexfilelayout/flexfilelayout.c
Original file line number Diff line number Diff line change
Expand Up @@ -822,14 +822,6 @@ ff_layout_pg_get_read(struct nfs_pageio_descriptor *pgio,
}
}

static void
ff_layout_pg_check_layout(struct nfs_pageio_descriptor *pgio,
struct nfs_page *req)
{
pnfs_generic_pg_check_layout(pgio);
pnfs_generic_pg_check_range(pgio, req);
}

static void
ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio,
struct nfs_page *req)
Expand All @@ -840,7 +832,7 @@ ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio,
u32 ds_idx;

retry:
ff_layout_pg_check_layout(pgio, req);
pnfs_generic_pg_check_layout(pgio, req);
/* Use full layout for now */
if (!pgio->pg_lseg) {
ff_layout_pg_get_read(pgio, req, false);
Expand Down Expand Up @@ -895,7 +887,7 @@ ff_layout_pg_init_write(struct nfs_pageio_descriptor *pgio,
u32 i;

retry:
ff_layout_pg_check_layout(pgio, req);
pnfs_generic_pg_check_layout(pgio, req);
if (!pgio->pg_lseg) {
pgio->pg_lseg =
pnfs_update_layout(pgio->pg_inode, nfs_req_openctx(req),
Expand Down
11 changes: 8 additions & 3 deletions fs/nfs/fs_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -600,9 +600,11 @@ static int nfs_fs_context_parse_param(struct fs_context *fc,
break;
case Opt_lock:
if (result.negated) {
ctx->lock_status = NFS_LOCK_NOLOCK;
ctx->flags |= NFS_MOUNT_NONLM;
ctx->flags |= (NFS_MOUNT_LOCAL_FLOCK | NFS_MOUNT_LOCAL_FCNTL);
} else {
ctx->lock_status = NFS_LOCK_LOCK;
ctx->flags &= ~NFS_MOUNT_NONLM;
ctx->flags &= ~(NFS_MOUNT_LOCAL_FLOCK | NFS_MOUNT_LOCAL_FCNTL);
}
Expand Down Expand Up @@ -1112,9 +1114,12 @@ static int nfs23_parse_monolithic(struct fs_context *fc,
ctx->acdirmax = data->acdirmax;
ctx->need_mount = false;

memcpy(sap, &data->addr, sizeof(data->addr));
ctx->nfs_server.addrlen = sizeof(data->addr);
ctx->nfs_server.port = ntohs(data->addr.sin_port);
if (!is_remount_fc(fc)) {
memcpy(sap, &data->addr, sizeof(data->addr));
ctx->nfs_server.addrlen = sizeof(data->addr);
ctx->nfs_server.port = ntohs(data->addr.sin_port);
}

if (sap->ss_family != AF_INET ||
!nfs_verify_server_address(sap))
goto out_no_address;
Expand Down
11 changes: 9 additions & 2 deletions fs/nfs/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ struct nfs_fs_context {
unsigned short protofamily;
unsigned short mountfamily;
bool has_sec_mnt_opts;
int lock_status;

struct {
union {
Expand Down Expand Up @@ -153,6 +154,12 @@ struct nfs_fs_context {
} clone_data;
};

enum nfs_lock_status {
NFS_LOCK_NOT_SET = 0,
NFS_LOCK_LOCK = 1,
NFS_LOCK_NOLOCK = 2,
};

#define nfs_errorf(fc, fmt, ...) ((fc)->log.log ? \
errorf(fc, fmt, ## __VA_ARGS__) : \
({ dprintk(fmt "\n", ## __VA_ARGS__); }))
Expand Down Expand Up @@ -710,9 +717,9 @@ unsigned long nfs_block_bits(unsigned long bsize, unsigned char *nrbitsp)
if ((bsize & (bsize - 1)) || nrbitsp) {
unsigned char nrbits;

for (nrbits = 31; nrbits && !(bsize & (1 << nrbits)); nrbits--)
for (nrbits = 31; nrbits && !(bsize & (1UL << nrbits)); nrbits--)
;
bsize = 1 << nrbits;
bsize = 1UL << nrbits;
if (nrbitsp)
*nrbitsp = nrbits;
}
Expand Down
1 change: 1 addition & 0 deletions fs/nfs/nfs3proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -986,6 +986,7 @@ static int nfs3_have_delegation(struct inode *inode, fmode_t flags)

static const struct inode_operations nfs3_dir_inode_operations = {
.create = nfs_create,
.atomic_open = nfs_atomic_open_v23,
.lookup = nfs_lookup,
.link = nfs_link,
.unlink = nfs_unlink,
Expand Down
2 changes: 1 addition & 1 deletion fs/nfs/nfs4proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -5456,7 +5456,7 @@ static bool nfs4_read_plus_not_supported(struct rpc_task *task,
struct rpc_message *msg = &task->tk_msg;

if (msg->rpc_proc == &nfs4_procedures[NFSPROC4_CLNT_READ_PLUS] &&
server->caps & NFS_CAP_READ_PLUS && task->tk_status == -ENOTSUPP) {
task->tk_status == -ENOTSUPP) {
server->caps &= ~NFS_CAP_READ_PLUS;
msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ];
rpc_restart_call_prepare(task);
Expand Down
12 changes: 5 additions & 7 deletions fs/nfs/nfs4state.c
Original file line number Diff line number Diff line change
Expand Up @@ -2116,6 +2116,7 @@ static int nfs4_try_migration(struct nfs_server *server, const struct cred *cred
{
struct nfs_client *clp = server->nfs_client;
struct nfs4_fs_locations *locations = NULL;
struct nfs_fattr *fattr;
struct inode *inode;
struct page *page;
int status, result;
Expand All @@ -2125,19 +2126,16 @@ static int nfs4_try_migration(struct nfs_server *server, const struct cred *cred
(unsigned long long)server->fsid.minor,
clp->cl_hostname);

result = 0;
page = alloc_page(GFP_KERNEL);
locations = kmalloc(sizeof(struct nfs4_fs_locations), GFP_KERNEL);
if (page == NULL || locations == NULL) {
dprintk("<-- %s: no memory\n", __func__);
goto out;
}
locations->fattr = nfs_alloc_fattr();
if (locations->fattr == NULL) {
fattr = nfs_alloc_fattr();
if (page == NULL || locations == NULL || fattr == NULL) {
dprintk("<-- %s: no memory\n", __func__);
result = 0;
goto out;
}

locations->fattr = fattr;
inode = d_inode(server->super->s_root);
result = nfs4_proc_get_locations(server, NFS_FH(inode), locations,
page, cred);
Expand Down
29 changes: 9 additions & 20 deletions fs/nfs/pnfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -2705,38 +2705,28 @@ pnfs_layout_return_unused_byclid(struct nfs_client *clp,
&range);
}

/* Check if we have we have a valid layout but if there isn't an intersection
* between the request and the pgio->pg_lseg, put this pgio->pg_lseg away.
*/
void
pnfs_generic_pg_check_layout(struct nfs_pageio_descriptor *pgio)
pnfs_generic_pg_check_layout(struct nfs_pageio_descriptor *pgio,
struct nfs_page *req)
{
if (pgio->pg_lseg == NULL ||
test_bit(NFS_LSEG_VALID, &pgio->pg_lseg->pls_flags))
(test_bit(NFS_LSEG_VALID, &pgio->pg_lseg->pls_flags) &&
pnfs_lseg_request_intersecting(pgio->pg_lseg, req)))
return;
pnfs_put_lseg(pgio->pg_lseg);
pgio->pg_lseg = NULL;
}
EXPORT_SYMBOL_GPL(pnfs_generic_pg_check_layout);

/*
* Check for any intersection between the request and the pgio->pg_lseg,
* and if none, put this pgio->pg_lseg away.
*/
void
pnfs_generic_pg_check_range(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
{
if (pgio->pg_lseg && !pnfs_lseg_request_intersecting(pgio->pg_lseg, req)) {
pnfs_put_lseg(pgio->pg_lseg);
pgio->pg_lseg = NULL;
}
}
EXPORT_SYMBOL_GPL(pnfs_generic_pg_check_range);

void
pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
{
u64 rd_size;

pnfs_generic_pg_check_layout(pgio);
pnfs_generic_pg_check_range(pgio, req);
pnfs_generic_pg_check_layout(pgio, req);
if (pgio->pg_lseg == NULL) {
if (pgio->pg_dreq == NULL)
rd_size = i_size_read(pgio->pg_inode) - req_offset(req);
Expand Down Expand Up @@ -2766,8 +2756,7 @@ void
pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio,
struct nfs_page *req, u64 wb_size)
{
pnfs_generic_pg_check_layout(pgio);
pnfs_generic_pg_check_range(pgio, req);
pnfs_generic_pg_check_layout(pgio, req);
if (pgio->pg_lseg == NULL) {
pgio->pg_lseg =
pnfs_update_layout(pgio->pg_inode, nfs_req_openctx(req),
Expand Down
3 changes: 1 addition & 2 deletions fs/nfs/pnfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,7 @@ void pnfs_put_lseg(struct pnfs_layout_segment *lseg);

void set_pnfs_layoutdriver(struct nfs_server *, const struct nfs_fh *, struct nfs_fsinfo *);
void unset_pnfs_layoutdriver(struct nfs_server *);
void pnfs_generic_pg_check_layout(struct nfs_pageio_descriptor *pgio);
void pnfs_generic_pg_check_range(struct nfs_pageio_descriptor *pgio, struct nfs_page *req);
void pnfs_generic_pg_check_layout(struct nfs_pageio_descriptor *pgio, struct nfs_page *req);
void pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *, struct nfs_page *);
int pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc);
void pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio,
Expand Down
1 change: 1 addition & 0 deletions fs/nfs/proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,7 @@ static int nfs_have_delegation(struct inode *inode, fmode_t flags)
static const struct inode_operations nfs_dir_inode_operations = {
.create = nfs_create,
.lookup = nfs_lookup,
.atomic_open = nfs_atomic_open_v23,
.link = nfs_link,
.unlink = nfs_unlink,
.symlink = nfs_symlink,
Expand Down
10 changes: 10 additions & 0 deletions fs/nfs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -901,6 +901,16 @@ static struct nfs_server *nfs_try_mount_request(struct fs_context *fc)
rpc_authflavor_t authlist[NFS_MAX_SECFLAVORS];
unsigned int authlist_len = ARRAY_SIZE(authlist);

/* make sure 'nolock'/'lock' override the 'local_lock' mount option */
if (ctx->lock_status) {
if (ctx->lock_status == NFS_LOCK_NOLOCK) {
ctx->flags |= NFS_MOUNT_NONLM;
ctx->flags |= (NFS_MOUNT_LOCAL_FLOCK | NFS_MOUNT_LOCAL_FCNTL);
} else {
ctx->flags &= ~NFS_MOUNT_NONLM;
ctx->flags &= ~(NFS_MOUNT_LOCAL_FLOCK | NFS_MOUNT_LOCAL_FCNTL);
}
}
status = nfs_request_mount(fc, ctx->mntfh, authlist, &authlist_len);
if (status)
return ERR_PTR(status);
Expand Down
Loading

0 comments on commit 6d69b6c

Please sign in to comment.