Merge branch 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
* 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: NFS: Revert pnfs ugliness from the generic NFS read code path SUNRPC: destroy freshly allocated transport in case of sockaddr init error NFS: Fix a regression in the referral code nfs: move nfs_file_operations declaration to bottom of file.c (try #2) nfs: when attempting to open a directory, fall back on normal lookup (try #5)
This commit is contained in:
commit
e25ba0ce03
12 changed files with 89 additions and 62 deletions
|
@ -1468,12 +1468,12 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
|
||||||
res = NULL;
|
res = NULL;
|
||||||
goto out;
|
goto out;
|
||||||
/* This turned out not to be a regular file */
|
/* This turned out not to be a regular file */
|
||||||
|
case -EISDIR:
|
||||||
case -ENOTDIR:
|
case -ENOTDIR:
|
||||||
goto no_open;
|
goto no_open;
|
||||||
case -ELOOP:
|
case -ELOOP:
|
||||||
if (!(nd->intent.open.flags & O_NOFOLLOW))
|
if (!(nd->intent.open.flags & O_NOFOLLOW))
|
||||||
goto no_open;
|
goto no_open;
|
||||||
/* case -EISDIR: */
|
|
||||||
/* case -EINVAL: */
|
/* case -EINVAL: */
|
||||||
default:
|
default:
|
||||||
res = ERR_CAST(inode);
|
res = ERR_CAST(inode);
|
||||||
|
|
|
@ -40,48 +40,8 @@
|
||||||
|
|
||||||
#define NFSDBG_FACILITY NFSDBG_FILE
|
#define NFSDBG_FACILITY NFSDBG_FILE
|
||||||
|
|
||||||
static int nfs_file_open(struct inode *, struct file *);
|
|
||||||
static int nfs_file_release(struct inode *, struct file *);
|
|
||||||
static loff_t nfs_file_llseek(struct file *file, loff_t offset, int origin);
|
|
||||||
static int nfs_file_mmap(struct file *, struct vm_area_struct *);
|
|
||||||
static ssize_t nfs_file_splice_read(struct file *filp, loff_t *ppos,
|
|
||||||
struct pipe_inode_info *pipe,
|
|
||||||
size_t count, unsigned int flags);
|
|
||||||
static ssize_t nfs_file_read(struct kiocb *, const struct iovec *iov,
|
|
||||||
unsigned long nr_segs, loff_t pos);
|
|
||||||
static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe,
|
|
||||||
struct file *filp, loff_t *ppos,
|
|
||||||
size_t count, unsigned int flags);
|
|
||||||
static ssize_t nfs_file_write(struct kiocb *, const struct iovec *iov,
|
|
||||||
unsigned long nr_segs, loff_t pos);
|
|
||||||
static int nfs_file_flush(struct file *, fl_owner_t id);
|
|
||||||
static int nfs_file_fsync(struct file *, loff_t, loff_t, int datasync);
|
|
||||||
static int nfs_check_flags(int flags);
|
|
||||||
static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl);
|
|
||||||
static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl);
|
|
||||||
static int nfs_setlease(struct file *file, long arg, struct file_lock **fl);
|
|
||||||
|
|
||||||
static const struct vm_operations_struct nfs_file_vm_ops;
|
static const struct vm_operations_struct nfs_file_vm_ops;
|
||||||
|
|
||||||
const struct file_operations nfs_file_operations = {
|
|
||||||
.llseek = nfs_file_llseek,
|
|
||||||
.read = do_sync_read,
|
|
||||||
.write = do_sync_write,
|
|
||||||
.aio_read = nfs_file_read,
|
|
||||||
.aio_write = nfs_file_write,
|
|
||||||
.mmap = nfs_file_mmap,
|
|
||||||
.open = nfs_file_open,
|
|
||||||
.flush = nfs_file_flush,
|
|
||||||
.release = nfs_file_release,
|
|
||||||
.fsync = nfs_file_fsync,
|
|
||||||
.lock = nfs_lock,
|
|
||||||
.flock = nfs_flock,
|
|
||||||
.splice_read = nfs_file_splice_read,
|
|
||||||
.splice_write = nfs_file_splice_write,
|
|
||||||
.check_flags = nfs_check_flags,
|
|
||||||
.setlease = nfs_setlease,
|
|
||||||
};
|
|
||||||
|
|
||||||
const struct inode_operations nfs_file_inode_operations = {
|
const struct inode_operations nfs_file_inode_operations = {
|
||||||
.permission = nfs_permission,
|
.permission = nfs_permission,
|
||||||
.getattr = nfs_getattr,
|
.getattr = nfs_getattr,
|
||||||
|
@ -886,3 +846,54 @@ static int nfs_setlease(struct file *file, long arg, struct file_lock **fl)
|
||||||
file->f_path.dentry->d_name.name, arg);
|
file->f_path.dentry->d_name.name, arg);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const struct file_operations nfs_file_operations = {
|
||||||
|
.llseek = nfs_file_llseek,
|
||||||
|
.read = do_sync_read,
|
||||||
|
.write = do_sync_write,
|
||||||
|
.aio_read = nfs_file_read,
|
||||||
|
.aio_write = nfs_file_write,
|
||||||
|
.mmap = nfs_file_mmap,
|
||||||
|
.open = nfs_file_open,
|
||||||
|
.flush = nfs_file_flush,
|
||||||
|
.release = nfs_file_release,
|
||||||
|
.fsync = nfs_file_fsync,
|
||||||
|
.lock = nfs_lock,
|
||||||
|
.flock = nfs_flock,
|
||||||
|
.splice_read = nfs_file_splice_read,
|
||||||
|
.splice_write = nfs_file_splice_write,
|
||||||
|
.check_flags = nfs_check_flags,
|
||||||
|
.setlease = nfs_setlease,
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_NFS_V4
|
||||||
|
static int
|
||||||
|
nfs4_file_open(struct inode *inode, struct file *filp)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* NFSv4 opens are handled in d_lookup and d_revalidate. If we get to
|
||||||
|
* this point, then something is very wrong
|
||||||
|
*/
|
||||||
|
dprintk("NFS: %s called! inode=%p filp=%p\n", __func__, inode, filp);
|
||||||
|
return -ENOTDIR;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct file_operations nfs4_file_operations = {
|
||||||
|
.llseek = nfs_file_llseek,
|
||||||
|
.read = do_sync_read,
|
||||||
|
.write = do_sync_write,
|
||||||
|
.aio_read = nfs_file_read,
|
||||||
|
.aio_write = nfs_file_write,
|
||||||
|
.mmap = nfs_file_mmap,
|
||||||
|
.open = nfs4_file_open,
|
||||||
|
.flush = nfs_file_flush,
|
||||||
|
.release = nfs_file_release,
|
||||||
|
.fsync = nfs_file_fsync,
|
||||||
|
.lock = nfs_lock,
|
||||||
|
.flock = nfs_flock,
|
||||||
|
.splice_read = nfs_file_splice_read,
|
||||||
|
.splice_write = nfs_file_splice_write,
|
||||||
|
.check_flags = nfs_check_flags,
|
||||||
|
.setlease = nfs_setlease,
|
||||||
|
};
|
||||||
|
#endif /* CONFIG_NFS_V4 */
|
||||||
|
|
|
@ -291,7 +291,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
|
||||||
*/
|
*/
|
||||||
inode->i_op = NFS_SB(sb)->nfs_client->rpc_ops->file_inode_ops;
|
inode->i_op = NFS_SB(sb)->nfs_client->rpc_ops->file_inode_ops;
|
||||||
if (S_ISREG(inode->i_mode)) {
|
if (S_ISREG(inode->i_mode)) {
|
||||||
inode->i_fop = &nfs_file_operations;
|
inode->i_fop = NFS_SB(sb)->nfs_client->rpc_ops->file_ops;
|
||||||
inode->i_data.a_ops = &nfs_file_aops;
|
inode->i_data.a_ops = &nfs_file_aops;
|
||||||
inode->i_data.backing_dev_info = &NFS_SB(sb)->backing_dev_info;
|
inode->i_data.backing_dev_info = &NFS_SB(sb)->backing_dev_info;
|
||||||
} else if (S_ISDIR(inode->i_mode)) {
|
} else if (S_ISDIR(inode->i_mode)) {
|
||||||
|
|
|
@ -299,6 +299,8 @@ extern void nfs_read_prepare(struct rpc_task *task, void *calldata);
|
||||||
extern int nfs_generic_pagein(struct nfs_pageio_descriptor *desc,
|
extern int nfs_generic_pagein(struct nfs_pageio_descriptor *desc,
|
||||||
struct list_head *head);
|
struct list_head *head);
|
||||||
|
|
||||||
|
extern void nfs_pageio_init_read_mds(struct nfs_pageio_descriptor *pgio,
|
||||||
|
struct inode *inode);
|
||||||
extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio);
|
extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio);
|
||||||
extern void nfs_readdata_release(struct nfs_read_data *rdata);
|
extern void nfs_readdata_release(struct nfs_read_data *rdata);
|
||||||
|
|
||||||
|
|
|
@ -853,6 +853,7 @@ const struct nfs_rpc_ops nfs_v3_clientops = {
|
||||||
.dentry_ops = &nfs_dentry_operations,
|
.dentry_ops = &nfs_dentry_operations,
|
||||||
.dir_inode_ops = &nfs3_dir_inode_operations,
|
.dir_inode_ops = &nfs3_dir_inode_operations,
|
||||||
.file_inode_ops = &nfs3_file_inode_operations,
|
.file_inode_ops = &nfs3_file_inode_operations,
|
||||||
|
.file_ops = &nfs_file_operations,
|
||||||
.getroot = nfs3_proc_get_root,
|
.getroot = nfs3_proc_get_root,
|
||||||
.getattr = nfs3_proc_getattr,
|
.getattr = nfs3_proc_getattr,
|
||||||
.setattr = nfs3_proc_setattr,
|
.setattr = nfs3_proc_setattr,
|
||||||
|
|
|
@ -2464,8 +2464,7 @@ static int nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, struct qst
|
||||||
case -NFS4ERR_BADNAME:
|
case -NFS4ERR_BADNAME:
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
case -NFS4ERR_MOVED:
|
case -NFS4ERR_MOVED:
|
||||||
err = nfs4_get_referral(dir, name, fattr, fhandle);
|
return nfs4_get_referral(dir, name, fattr, fhandle);
|
||||||
break;
|
|
||||||
case -NFS4ERR_WRONGSEC:
|
case -NFS4ERR_WRONGSEC:
|
||||||
nfs_fixup_secinfo_attributes(fattr, fhandle);
|
nfs_fixup_secinfo_attributes(fattr, fhandle);
|
||||||
}
|
}
|
||||||
|
@ -6253,6 +6252,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
|
||||||
.dentry_ops = &nfs4_dentry_operations,
|
.dentry_ops = &nfs4_dentry_operations,
|
||||||
.dir_inode_ops = &nfs4_dir_inode_operations,
|
.dir_inode_ops = &nfs4_dir_inode_operations,
|
||||||
.file_inode_ops = &nfs4_file_inode_operations,
|
.file_inode_ops = &nfs4_file_inode_operations,
|
||||||
|
.file_ops = &nfs4_file_operations,
|
||||||
.getroot = nfs4_proc_get_root,
|
.getroot = nfs4_proc_get_root,
|
||||||
.getattr = nfs4_proc_getattr,
|
.getattr = nfs4_proc_getattr,
|
||||||
.setattr = nfs4_proc_setattr,
|
.setattr = nfs4_proc_setattr,
|
||||||
|
|
|
@ -1260,6 +1260,25 @@ pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(pnfs_generic_pg_writepages);
|
EXPORT_SYMBOL_GPL(pnfs_generic_pg_writepages);
|
||||||
|
|
||||||
|
static void pnfs_ld_handle_read_error(struct nfs_read_data *data)
|
||||||
|
{
|
||||||
|
struct nfs_pageio_descriptor pgio;
|
||||||
|
|
||||||
|
put_lseg(data->lseg);
|
||||||
|
data->lseg = NULL;
|
||||||
|
dprintk("pnfs write error = %d\n", data->pnfs_error);
|
||||||
|
|
||||||
|
nfs_pageio_init_read_mds(&pgio, data->inode);
|
||||||
|
|
||||||
|
while (!list_empty(&data->pages)) {
|
||||||
|
struct nfs_page *req = nfs_list_entry(data->pages.next);
|
||||||
|
|
||||||
|
nfs_list_remove_request(req);
|
||||||
|
nfs_pageio_add_request(&pgio, req);
|
||||||
|
}
|
||||||
|
nfs_pageio_complete(&pgio);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called by non rpc-based layout drivers
|
* Called by non rpc-based layout drivers
|
||||||
*/
|
*/
|
||||||
|
@ -1268,11 +1287,8 @@ void pnfs_ld_read_done(struct nfs_read_data *data)
|
||||||
if (likely(!data->pnfs_error)) {
|
if (likely(!data->pnfs_error)) {
|
||||||
__nfs4_read_done_cb(data);
|
__nfs4_read_done_cb(data);
|
||||||
data->mds_ops->rpc_call_done(&data->task, data);
|
data->mds_ops->rpc_call_done(&data->task, data);
|
||||||
} else {
|
} else
|
||||||
put_lseg(data->lseg);
|
pnfs_ld_handle_read_error(data);
|
||||||
data->lseg = NULL;
|
|
||||||
dprintk("pnfs write error = %d\n", data->pnfs_error);
|
|
||||||
}
|
|
||||||
data->mds_ops->rpc_release(data);
|
data->mds_ops->rpc_release(data);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(pnfs_ld_read_done);
|
EXPORT_SYMBOL_GPL(pnfs_ld_read_done);
|
||||||
|
|
|
@ -710,6 +710,7 @@ const struct nfs_rpc_ops nfs_v2_clientops = {
|
||||||
.dentry_ops = &nfs_dentry_operations,
|
.dentry_ops = &nfs_dentry_operations,
|
||||||
.dir_inode_ops = &nfs_dir_inode_operations,
|
.dir_inode_ops = &nfs_dir_inode_operations,
|
||||||
.file_inode_ops = &nfs_file_inode_operations,
|
.file_inode_ops = &nfs_file_inode_operations,
|
||||||
|
.file_ops = &nfs_file_operations,
|
||||||
.getroot = nfs_proc_get_root,
|
.getroot = nfs_proc_get_root,
|
||||||
.getattr = nfs_proc_getattr,
|
.getattr = nfs_proc_getattr,
|
||||||
.setattr = nfs_proc_setattr,
|
.setattr = nfs_proc_setattr,
|
||||||
|
|
|
@ -109,7 +109,7 @@ static void nfs_readpage_truncate_uninitialised_page(struct nfs_read_data *data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nfs_pageio_init_read_mds(struct nfs_pageio_descriptor *pgio,
|
void nfs_pageio_init_read_mds(struct nfs_pageio_descriptor *pgio,
|
||||||
struct inode *inode)
|
struct inode *inode)
|
||||||
{
|
{
|
||||||
nfs_pageio_init(pgio, inode, &nfs_pageio_read_ops,
|
nfs_pageio_init(pgio, inode, &nfs_pageio_read_ops,
|
||||||
|
@ -534,23 +534,13 @@ static void nfs_readpage_result_full(struct rpc_task *task, void *calldata)
|
||||||
static void nfs_readpage_release_full(void *calldata)
|
static void nfs_readpage_release_full(void *calldata)
|
||||||
{
|
{
|
||||||
struct nfs_read_data *data = calldata;
|
struct nfs_read_data *data = calldata;
|
||||||
struct nfs_pageio_descriptor pgio;
|
|
||||||
|
|
||||||
if (data->pnfs_error) {
|
|
||||||
nfs_pageio_init_read_mds(&pgio, data->inode);
|
|
||||||
pgio.pg_recoalesce = 1;
|
|
||||||
}
|
|
||||||
while (!list_empty(&data->pages)) {
|
while (!list_empty(&data->pages)) {
|
||||||
struct nfs_page *req = nfs_list_entry(data->pages.next);
|
struct nfs_page *req = nfs_list_entry(data->pages.next);
|
||||||
|
|
||||||
nfs_list_remove_request(req);
|
nfs_list_remove_request(req);
|
||||||
if (!data->pnfs_error)
|
nfs_readpage_release(req);
|
||||||
nfs_readpage_release(req);
|
|
||||||
else
|
|
||||||
nfs_pageio_add_request(&pgio, req);
|
|
||||||
}
|
}
|
||||||
if (data->pnfs_error)
|
|
||||||
nfs_pageio_complete(&pgio);
|
|
||||||
nfs_readdata_release(calldata);
|
nfs_readdata_release(calldata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -410,6 +410,9 @@ extern const struct inode_operations nfs_file_inode_operations;
|
||||||
extern const struct inode_operations nfs3_file_inode_operations;
|
extern const struct inode_operations nfs3_file_inode_operations;
|
||||||
#endif /* CONFIG_NFS_V3 */
|
#endif /* CONFIG_NFS_V3 */
|
||||||
extern const struct file_operations nfs_file_operations;
|
extern const struct file_operations nfs_file_operations;
|
||||||
|
#ifdef CONFIG_NFS_V4
|
||||||
|
extern const struct file_operations nfs4_file_operations;
|
||||||
|
#endif /* CONFIG_NFS_V4 */
|
||||||
extern const struct address_space_operations nfs_file_aops;
|
extern const struct address_space_operations nfs_file_aops;
|
||||||
extern const struct address_space_operations nfs_dir_aops;
|
extern const struct address_space_operations nfs_dir_aops;
|
||||||
|
|
||||||
|
|
|
@ -1192,6 +1192,7 @@ struct nfs_rpc_ops {
|
||||||
const struct dentry_operations *dentry_ops;
|
const struct dentry_operations *dentry_ops;
|
||||||
const struct inode_operations *dir_inode_ops;
|
const struct inode_operations *dir_inode_ops;
|
||||||
const struct inode_operations *file_inode_ops;
|
const struct inode_operations *file_inode_ops;
|
||||||
|
const struct file_operations *file_ops;
|
||||||
|
|
||||||
int (*getroot) (struct nfs_server *, struct nfs_fh *,
|
int (*getroot) (struct nfs_server *, struct nfs_fh *,
|
||||||
struct nfs_fsinfo *);
|
struct nfs_fsinfo *);
|
||||||
|
|
|
@ -2530,8 +2530,10 @@ static struct rpc_xprt *xs_setup_xprt(struct xprt_create *args,
|
||||||
int err;
|
int err;
|
||||||
err = xs_init_anyaddr(args->dstaddr->sa_family,
|
err = xs_init_anyaddr(args->dstaddr->sa_family,
|
||||||
(struct sockaddr *)&new->srcaddr);
|
(struct sockaddr *)&new->srcaddr);
|
||||||
if (err != 0)
|
if (err != 0) {
|
||||||
|
xprt_free(xprt);
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return xprt;
|
return xprt;
|
||||||
|
|
Loading…
Reference in a new issue