Merge branch 'fixes' of git://git.linux-nfs.org/pub/linux/nfs-2.6
This commit is contained in:
commit
62250b3bb5
@ -486,8 +486,6 @@ struct file *open_exec(const char *name)
|
|||||||
if (!(nd.mnt->mnt_flags & MNT_NOEXEC) &&
|
if (!(nd.mnt->mnt_flags & MNT_NOEXEC) &&
|
||||||
S_ISREG(inode->i_mode)) {
|
S_ISREG(inode->i_mode)) {
|
||||||
int err = vfs_permission(&nd, MAY_EXEC);
|
int err = vfs_permission(&nd, MAY_EXEC);
|
||||||
if (!err && !(inode->i_mode & 0111))
|
|
||||||
err = -EACCES;
|
|
||||||
file = ERR_PTR(err);
|
file = ERR_PTR(err);
|
||||||
if (!err) {
|
if (!err) {
|
||||||
file = nameidata_to_filp(&nd, O_RDONLY);
|
file = nameidata_to_filp(&nd, O_RDONLY);
|
||||||
@ -922,12 +920,6 @@ int prepare_binprm(struct linux_binprm *bprm)
|
|||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
mode = inode->i_mode;
|
mode = inode->i_mode;
|
||||||
/*
|
|
||||||
* Check execute perms again - if the caller has CAP_DAC_OVERRIDE,
|
|
||||||
* generic_permission lets a non-executable through
|
|
||||||
*/
|
|
||||||
if (!(mode & 0111)) /* with at least _one_ execute bit set */
|
|
||||||
return -EACCES;
|
|
||||||
if (bprm->file->f_op == NULL)
|
if (bprm->file->f_op == NULL)
|
||||||
return -EACCES;
|
return -EACCES;
|
||||||
|
|
||||||
|
@ -237,19 +237,22 @@ static int
|
|||||||
nlm_traverse_files(struct nlm_host *host, int action)
|
nlm_traverse_files(struct nlm_host *host, int action)
|
||||||
{
|
{
|
||||||
struct nlm_file *file, **fp;
|
struct nlm_file *file, **fp;
|
||||||
int i;
|
int i, ret = 0;
|
||||||
|
|
||||||
mutex_lock(&nlm_file_mutex);
|
mutex_lock(&nlm_file_mutex);
|
||||||
for (i = 0; i < FILE_NRHASH; i++) {
|
for (i = 0; i < FILE_NRHASH; i++) {
|
||||||
fp = nlm_files + i;
|
fp = nlm_files + i;
|
||||||
while ((file = *fp) != NULL) {
|
while ((file = *fp) != NULL) {
|
||||||
|
file->f_count++;
|
||||||
|
mutex_unlock(&nlm_file_mutex);
|
||||||
|
|
||||||
/* Traverse locks, blocks and shares of this file
|
/* Traverse locks, blocks and shares of this file
|
||||||
* and update file->f_locks count */
|
* and update file->f_locks count */
|
||||||
if (nlm_inspect_file(host, file, action)) {
|
if (nlm_inspect_file(host, file, action))
|
||||||
mutex_unlock(&nlm_file_mutex);
|
ret = 1;
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
mutex_lock(&nlm_file_mutex);
|
||||||
|
file->f_count--;
|
||||||
/* No more references to this file. Let go of it. */
|
/* No more references to this file. Let go of it. */
|
||||||
if (!file->f_blocks && !file->f_locks
|
if (!file->f_blocks && !file->f_locks
|
||||||
&& !file->f_shares && !file->f_count) {
|
&& !file->f_shares && !file->f_count) {
|
||||||
@ -262,7 +265,7 @@ nlm_traverse_files(struct nlm_host *host, int action)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mutex_unlock(&nlm_file_mutex);
|
mutex_unlock(&nlm_file_mutex);
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
11
fs/namei.c
11
fs/namei.c
@ -227,10 +227,10 @@ int generic_permission(struct inode *inode, int mask,
|
|||||||
|
|
||||||
int permission(struct inode *inode, int mask, struct nameidata *nd)
|
int permission(struct inode *inode, int mask, struct nameidata *nd)
|
||||||
{
|
{
|
||||||
|
umode_t mode = inode->i_mode;
|
||||||
int retval, submask;
|
int retval, submask;
|
||||||
|
|
||||||
if (mask & MAY_WRITE) {
|
if (mask & MAY_WRITE) {
|
||||||
umode_t mode = inode->i_mode;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Nobody gets write access to a read-only fs.
|
* Nobody gets write access to a read-only fs.
|
||||||
@ -247,6 +247,13 @@ int permission(struct inode *inode, int mask, struct nameidata *nd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MAY_EXEC on regular files requires special handling: We override
|
||||||
|
* filesystem execute permissions if the mode bits aren't set.
|
||||||
|
*/
|
||||||
|
if ((mask & MAY_EXEC) && S_ISREG(mode) && !(mode & S_IXUGO))
|
||||||
|
return -EACCES;
|
||||||
|
|
||||||
/* Ordinary permission routines do not understand MAY_APPEND. */
|
/* Ordinary permission routines do not understand MAY_APPEND. */
|
||||||
submask = mask & ~MAY_APPEND;
|
submask = mask & ~MAY_APPEND;
|
||||||
if (inode->i_op && inode->i_op->permission)
|
if (inode->i_op && inode->i_op->permission)
|
||||||
@ -1767,6 +1774,8 @@ struct dentry *lookup_create(struct nameidata *nd, int is_dir)
|
|||||||
if (nd->last_type != LAST_NORM)
|
if (nd->last_type != LAST_NORM)
|
||||||
goto fail;
|
goto fail;
|
||||||
nd->flags &= ~LOOKUP_PARENT;
|
nd->flags &= ~LOOKUP_PARENT;
|
||||||
|
nd->flags |= LOOKUP_CREATE;
|
||||||
|
nd->intent.open.flags = O_EXCL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do the final lookup.
|
* Do the final lookup.
|
||||||
|
@ -312,7 +312,13 @@ static void nfs_invalidate_page(struct page *page, unsigned long offset)
|
|||||||
|
|
||||||
static int nfs_release_page(struct page *page, gfp_t gfp)
|
static int nfs_release_page(struct page *page, gfp_t gfp)
|
||||||
{
|
{
|
||||||
return !nfs_wb_page(page->mapping->host, page);
|
if (gfp & __GFP_FS)
|
||||||
|
return !nfs_wb_page(page->mapping->host, page);
|
||||||
|
else
|
||||||
|
/*
|
||||||
|
* Avoid deadlock on nfs_wait_on_request().
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct address_space_operations nfs_file_aops = {
|
const struct address_space_operations nfs_file_aops = {
|
||||||
|
@ -130,9 +130,7 @@ nfs_idmap_delete(struct nfs4_client *clp)
|
|||||||
|
|
||||||
if (!idmap)
|
if (!idmap)
|
||||||
return;
|
return;
|
||||||
dput(idmap->idmap_dentry);
|
rpc_unlink(idmap->idmap_dentry);
|
||||||
idmap->idmap_dentry = NULL;
|
|
||||||
rpc_unlink(idmap->idmap_path);
|
|
||||||
clp->cl_idmap = NULL;
|
clp->cl_idmap = NULL;
|
||||||
kfree(idmap);
|
kfree(idmap);
|
||||||
}
|
}
|
||||||
|
@ -2668,7 +2668,7 @@ static void nfs4_write_cached_acl(struct inode *inode, const char *buf, size_t a
|
|||||||
nfs4_set_cached_acl(inode, acl);
|
nfs4_set_cached_acl(inode, acl);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen)
|
static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen)
|
||||||
{
|
{
|
||||||
struct page *pages[NFS4ACL_MAXPAGES];
|
struct page *pages[NFS4ACL_MAXPAGES];
|
||||||
struct nfs_getaclargs args = {
|
struct nfs_getaclargs args = {
|
||||||
@ -2721,6 +2721,19 @@ static inline ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf, size
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen)
|
||||||
|
{
|
||||||
|
struct nfs4_exception exception = { };
|
||||||
|
ssize_t ret;
|
||||||
|
do {
|
||||||
|
ret = __nfs4_get_acl_uncached(inode, buf, buflen);
|
||||||
|
if (ret >= 0)
|
||||||
|
break;
|
||||||
|
ret = nfs4_handle_exception(NFS_SERVER(inode), ret, &exception);
|
||||||
|
} while (exception.retry);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen)
|
static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen)
|
||||||
{
|
{
|
||||||
struct nfs_server *server = NFS_SERVER(inode);
|
struct nfs_server *server = NFS_SERVER(inode);
|
||||||
@ -2737,7 +2750,7 @@ static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen)
|
|||||||
return nfs4_get_acl_uncached(inode, buf, buflen);
|
return nfs4_get_acl_uncached(inode, buf, buflen);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen)
|
static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen)
|
||||||
{
|
{
|
||||||
struct nfs_server *server = NFS_SERVER(inode);
|
struct nfs_server *server = NFS_SERVER(inode);
|
||||||
struct page *pages[NFS4ACL_MAXPAGES];
|
struct page *pages[NFS4ACL_MAXPAGES];
|
||||||
@ -2763,6 +2776,18 @@ static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen)
|
||||||
|
{
|
||||||
|
struct nfs4_exception exception = { };
|
||||||
|
int err;
|
||||||
|
do {
|
||||||
|
err = nfs4_handle_exception(NFS_SERVER(inode),
|
||||||
|
__nfs4_proc_set_acl(inode, buf, buflen),
|
||||||
|
&exception);
|
||||||
|
} while (exception.retry);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server)
|
nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server)
|
||||||
{
|
{
|
||||||
|
@ -3355,7 +3355,7 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
|
|||||||
struct kvec *iov = rcvbuf->head;
|
struct kvec *iov = rcvbuf->head;
|
||||||
unsigned int nr, pglen = rcvbuf->page_len;
|
unsigned int nr, pglen = rcvbuf->page_len;
|
||||||
uint32_t *end, *entry, *p, *kaddr;
|
uint32_t *end, *entry, *p, *kaddr;
|
||||||
uint32_t len, attrlen;
|
uint32_t len, attrlen, xlen;
|
||||||
int hdrlen, recvd, status;
|
int hdrlen, recvd, status;
|
||||||
|
|
||||||
status = decode_op_hdr(xdr, OP_READDIR);
|
status = decode_op_hdr(xdr, OP_READDIR);
|
||||||
@ -3377,10 +3377,10 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
|
|||||||
|
|
||||||
BUG_ON(pglen + readdir->pgbase > PAGE_CACHE_SIZE);
|
BUG_ON(pglen + readdir->pgbase > PAGE_CACHE_SIZE);
|
||||||
kaddr = p = (uint32_t *) kmap_atomic(page, KM_USER0);
|
kaddr = p = (uint32_t *) kmap_atomic(page, KM_USER0);
|
||||||
end = (uint32_t *) ((char *)p + pglen + readdir->pgbase);
|
end = p + ((pglen + readdir->pgbase) >> 2);
|
||||||
entry = p;
|
entry = p;
|
||||||
for (nr = 0; *p++; nr++) {
|
for (nr = 0; *p++; nr++) {
|
||||||
if (p + 3 > end)
|
if (end - p < 3)
|
||||||
goto short_pkt;
|
goto short_pkt;
|
||||||
dprintk("cookie = %Lu, ", *((unsigned long long *)p));
|
dprintk("cookie = %Lu, ", *((unsigned long long *)p));
|
||||||
p += 2; /* cookie */
|
p += 2; /* cookie */
|
||||||
@ -3389,18 +3389,19 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
|
|||||||
printk(KERN_WARNING "NFS: giant filename in readdir (len 0x%x)\n", len);
|
printk(KERN_WARNING "NFS: giant filename in readdir (len 0x%x)\n", len);
|
||||||
goto err_unmap;
|
goto err_unmap;
|
||||||
}
|
}
|
||||||
|
xlen = XDR_QUADLEN(len);
|
||||||
|
if (end - p < xlen + 1)
|
||||||
|
goto short_pkt;
|
||||||
dprintk("filename = %*s\n", len, (char *)p);
|
dprintk("filename = %*s\n", len, (char *)p);
|
||||||
p += XDR_QUADLEN(len);
|
p += xlen;
|
||||||
if (p + 1 > end)
|
|
||||||
goto short_pkt;
|
|
||||||
len = ntohl(*p++); /* bitmap length */
|
len = ntohl(*p++); /* bitmap length */
|
||||||
|
if (end - p < len + 1)
|
||||||
|
goto short_pkt;
|
||||||
p += len;
|
p += len;
|
||||||
if (p + 1 > end)
|
|
||||||
goto short_pkt;
|
|
||||||
attrlen = XDR_QUADLEN(ntohl(*p++));
|
attrlen = XDR_QUADLEN(ntohl(*p++));
|
||||||
p += attrlen; /* attributes */
|
if (end - p < attrlen + 2)
|
||||||
if (p + 2 > end)
|
|
||||||
goto short_pkt;
|
goto short_pkt;
|
||||||
|
p += attrlen; /* attributes */
|
||||||
entry = p;
|
entry = p;
|
||||||
}
|
}
|
||||||
if (!nr && (entry[0] != 0 || entry[1] == 0))
|
if (!nr && (entry[0] != 0 || entry[1] == 0))
|
||||||
|
@ -116,10 +116,17 @@ static void nfs_readpage_truncate_uninitialised_page(struct nfs_read_data *data)
|
|||||||
pages = &data->args.pages[base >> PAGE_CACHE_SHIFT];
|
pages = &data->args.pages[base >> PAGE_CACHE_SHIFT];
|
||||||
base &= ~PAGE_CACHE_MASK;
|
base &= ~PAGE_CACHE_MASK;
|
||||||
pglen = PAGE_CACHE_SIZE - base;
|
pglen = PAGE_CACHE_SIZE - base;
|
||||||
if (pglen < remainder)
|
for (;;) {
|
||||||
|
if (remainder <= pglen) {
|
||||||
|
memclear_highpage_flush(*pages, base, remainder);
|
||||||
|
break;
|
||||||
|
}
|
||||||
memclear_highpage_flush(*pages, base, pglen);
|
memclear_highpage_flush(*pages, base, pglen);
|
||||||
else
|
pages++;
|
||||||
memclear_highpage_flush(*pages, base, remainder);
|
remainder -= pglen;
|
||||||
|
pglen = PAGE_CACHE_SIZE;
|
||||||
|
base = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -476,6 +483,8 @@ static void nfs_readpage_set_pages_uptodate(struct nfs_read_data *data)
|
|||||||
unsigned int base = data->args.pgbase;
|
unsigned int base = data->args.pgbase;
|
||||||
struct page **pages;
|
struct page **pages;
|
||||||
|
|
||||||
|
if (data->res.eof)
|
||||||
|
count = data->args.count;
|
||||||
if (unlikely(count == 0))
|
if (unlikely(count == 0))
|
||||||
return;
|
return;
|
||||||
pages = &data->args.pages[base >> PAGE_CACHE_SHIFT];
|
pages = &data->args.pages[base >> PAGE_CACHE_SHIFT];
|
||||||
@ -483,11 +492,7 @@ static void nfs_readpage_set_pages_uptodate(struct nfs_read_data *data)
|
|||||||
count += base;
|
count += base;
|
||||||
for (;count >= PAGE_CACHE_SIZE; count -= PAGE_CACHE_SIZE, pages++)
|
for (;count >= PAGE_CACHE_SIZE; count -= PAGE_CACHE_SIZE, pages++)
|
||||||
SetPageUptodate(*pages);
|
SetPageUptodate(*pages);
|
||||||
/*
|
if (count != 0)
|
||||||
* Was this an eof or a short read? If the latter, don't mark the page
|
|
||||||
* as uptodate yet.
|
|
||||||
*/
|
|
||||||
if (count > 0 && (data->res.eof || data->args.count == data->res.count))
|
|
||||||
SetPageUptodate(*pages);
|
SetPageUptodate(*pages);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -502,6 +507,8 @@ static void nfs_readpage_set_pages_error(struct nfs_read_data *data)
|
|||||||
count += base;
|
count += base;
|
||||||
for (;count >= PAGE_CACHE_SIZE; count -= PAGE_CACHE_SIZE, pages++)
|
for (;count >= PAGE_CACHE_SIZE; count -= PAGE_CACHE_SIZE, pages++)
|
||||||
SetPageError(*pages);
|
SetPageError(*pages);
|
||||||
|
if (count != 0)
|
||||||
|
SetPageError(*pages);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -659,7 +659,7 @@ struct nfs4_rename_res {
|
|||||||
struct nfs4_setclientid {
|
struct nfs4_setclientid {
|
||||||
const nfs4_verifier * sc_verifier; /* request */
|
const nfs4_verifier * sc_verifier; /* request */
|
||||||
unsigned int sc_name_len;
|
unsigned int sc_name_len;
|
||||||
char sc_name[32]; /* request */
|
char sc_name[48]; /* request */
|
||||||
u32 sc_prog; /* request */
|
u32 sc_prog; /* request */
|
||||||
unsigned int sc_netid_len;
|
unsigned int sc_netid_len;
|
||||||
char sc_netid[4]; /* request */
|
char sc_netid[4]; /* request */
|
||||||
|
@ -42,9 +42,9 @@ RPC_I(struct inode *inode)
|
|||||||
extern int rpc_queue_upcall(struct inode *, struct rpc_pipe_msg *);
|
extern int rpc_queue_upcall(struct inode *, struct rpc_pipe_msg *);
|
||||||
|
|
||||||
extern struct dentry *rpc_mkdir(char *, struct rpc_clnt *);
|
extern struct dentry *rpc_mkdir(char *, struct rpc_clnt *);
|
||||||
extern int rpc_rmdir(char *);
|
extern int rpc_rmdir(struct dentry *);
|
||||||
extern struct dentry *rpc_mkpipe(char *, void *, struct rpc_pipe_ops *, int flags);
|
extern struct dentry *rpc_mkpipe(char *, void *, struct rpc_pipe_ops *, int flags);
|
||||||
extern int rpc_unlink(char *);
|
extern int rpc_unlink(struct dentry *);
|
||||||
extern struct vfsmount *rpc_get_mount(void);
|
extern struct vfsmount *rpc_get_mount(void);
|
||||||
extern void rpc_put_mount(void);
|
extern void rpc_put_mount(void);
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ extern unsigned int xprt_max_resvport;
|
|||||||
|
|
||||||
#define RPC_MIN_RESVPORT (1U)
|
#define RPC_MIN_RESVPORT (1U)
|
||||||
#define RPC_MAX_RESVPORT (65535U)
|
#define RPC_MAX_RESVPORT (65535U)
|
||||||
#define RPC_DEF_MIN_RESVPORT (650U)
|
#define RPC_DEF_MIN_RESVPORT (665U)
|
||||||
#define RPC_DEF_MAX_RESVPORT (1023U)
|
#define RPC_DEF_MAX_RESVPORT (1023U)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -718,8 +718,7 @@ gss_destroy(struct rpc_auth *auth)
|
|||||||
auth, auth->au_flavor);
|
auth, auth->au_flavor);
|
||||||
|
|
||||||
gss_auth = container_of(auth, struct gss_auth, rpc_auth);
|
gss_auth = container_of(auth, struct gss_auth, rpc_auth);
|
||||||
rpc_unlink(gss_auth->path);
|
rpc_unlink(gss_auth->dentry);
|
||||||
dput(gss_auth->dentry);
|
|
||||||
gss_auth->dentry = NULL;
|
gss_auth->dentry = NULL;
|
||||||
gss_mech_put(gss_auth->mech);
|
gss_mech_put(gss_auth->mech);
|
||||||
|
|
||||||
|
@ -183,8 +183,7 @@ rpc_new_client(struct rpc_xprt *xprt, char *servname,
|
|||||||
|
|
||||||
out_no_auth:
|
out_no_auth:
|
||||||
if (!IS_ERR(clnt->cl_dentry)) {
|
if (!IS_ERR(clnt->cl_dentry)) {
|
||||||
rpc_rmdir(clnt->cl_pathname);
|
rpc_rmdir(clnt->cl_dentry);
|
||||||
dput(clnt->cl_dentry);
|
|
||||||
rpc_put_mount();
|
rpc_put_mount();
|
||||||
}
|
}
|
||||||
out_no_path:
|
out_no_path:
|
||||||
@ -251,10 +250,8 @@ rpc_clone_client(struct rpc_clnt *clnt)
|
|||||||
new->cl_autobind = 0;
|
new->cl_autobind = 0;
|
||||||
new->cl_oneshot = 0;
|
new->cl_oneshot = 0;
|
||||||
new->cl_dead = 0;
|
new->cl_dead = 0;
|
||||||
if (!IS_ERR(new->cl_dentry)) {
|
if (!IS_ERR(new->cl_dentry))
|
||||||
dget(new->cl_dentry);
|
dget(new->cl_dentry);
|
||||||
rpc_get_mount();
|
|
||||||
}
|
|
||||||
rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval);
|
rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval);
|
||||||
if (new->cl_auth)
|
if (new->cl_auth)
|
||||||
atomic_inc(&new->cl_auth->au_count);
|
atomic_inc(&new->cl_auth->au_count);
|
||||||
@ -317,11 +314,15 @@ rpc_destroy_client(struct rpc_clnt *clnt)
|
|||||||
clnt->cl_auth = NULL;
|
clnt->cl_auth = NULL;
|
||||||
}
|
}
|
||||||
if (clnt->cl_parent != clnt) {
|
if (clnt->cl_parent != clnt) {
|
||||||
|
if (!IS_ERR(clnt->cl_dentry))
|
||||||
|
dput(clnt->cl_dentry);
|
||||||
rpc_destroy_client(clnt->cl_parent);
|
rpc_destroy_client(clnt->cl_parent);
|
||||||
goto out_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
if (clnt->cl_pathname[0])
|
if (!IS_ERR(clnt->cl_dentry)) {
|
||||||
rpc_rmdir(clnt->cl_pathname);
|
rpc_rmdir(clnt->cl_dentry);
|
||||||
|
rpc_put_mount();
|
||||||
|
}
|
||||||
if (clnt->cl_xprt) {
|
if (clnt->cl_xprt) {
|
||||||
xprt_destroy(clnt->cl_xprt);
|
xprt_destroy(clnt->cl_xprt);
|
||||||
clnt->cl_xprt = NULL;
|
clnt->cl_xprt = NULL;
|
||||||
@ -331,10 +332,6 @@ rpc_destroy_client(struct rpc_clnt *clnt)
|
|||||||
out_free:
|
out_free:
|
||||||
rpc_free_iostats(clnt->cl_metrics);
|
rpc_free_iostats(clnt->cl_metrics);
|
||||||
clnt->cl_metrics = NULL;
|
clnt->cl_metrics = NULL;
|
||||||
if (!IS_ERR(clnt->cl_dentry)) {
|
|
||||||
dput(clnt->cl_dentry);
|
|
||||||
rpc_put_mount();
|
|
||||||
}
|
|
||||||
kfree(clnt);
|
kfree(clnt);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1184,6 +1181,17 @@ call_verify(struct rpc_task *task)
|
|||||||
u32 *p = iov->iov_base, n;
|
u32 *p = iov->iov_base, n;
|
||||||
int error = -EACCES;
|
int error = -EACCES;
|
||||||
|
|
||||||
|
if ((task->tk_rqstp->rq_rcv_buf.len & 3) != 0) {
|
||||||
|
/* RFC-1014 says that the representation of XDR data must be a
|
||||||
|
* multiple of four bytes
|
||||||
|
* - if it isn't pointer subtraction in the NFS client may give
|
||||||
|
* undefined results
|
||||||
|
*/
|
||||||
|
printk(KERN_WARNING
|
||||||
|
"call_verify: XDR representation not a multiple of"
|
||||||
|
" 4 bytes: 0x%x\n", task->tk_rqstp->rq_rcv_buf.len);
|
||||||
|
goto out_eio;
|
||||||
|
}
|
||||||
if ((len -= 3) < 0)
|
if ((len -= 3) < 0)
|
||||||
goto out_overflow;
|
goto out_overflow;
|
||||||
p += 1; /* skip XID */
|
p += 1; /* skip XID */
|
||||||
|
@ -539,6 +539,7 @@ rpc_depopulate(struct dentry *parent)
|
|||||||
rpc_close_pipes(dentry->d_inode);
|
rpc_close_pipes(dentry->d_inode);
|
||||||
simple_unlink(dir, dentry);
|
simple_unlink(dir, dentry);
|
||||||
}
|
}
|
||||||
|
inode_dir_notify(dir, DN_DELETE);
|
||||||
dput(dentry);
|
dput(dentry);
|
||||||
} while (n);
|
} while (n);
|
||||||
goto repeat;
|
goto repeat;
|
||||||
@ -610,8 +611,8 @@ __rpc_rmdir(struct inode *dir, struct dentry *dentry)
|
|||||||
int error;
|
int error;
|
||||||
|
|
||||||
shrink_dcache_parent(dentry);
|
shrink_dcache_parent(dentry);
|
||||||
if (dentry->d_inode)
|
if (d_unhashed(dentry))
|
||||||
rpc_close_pipes(dentry->d_inode);
|
return 0;
|
||||||
if ((error = simple_rmdir(dir, dentry)) != 0)
|
if ((error = simple_rmdir(dir, dentry)) != 0)
|
||||||
return error;
|
return error;
|
||||||
if (!error) {
|
if (!error) {
|
||||||
@ -684,28 +685,20 @@ rpc_mkdir(char *path, struct rpc_clnt *rpc_client)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
rpc_rmdir(char *path)
|
rpc_rmdir(struct dentry *dentry)
|
||||||
{
|
{
|
||||||
struct nameidata nd;
|
struct dentry *parent;
|
||||||
struct dentry *dentry;
|
|
||||||
struct inode *dir;
|
struct inode *dir;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
if ((error = rpc_lookup_parent(path, &nd)) != 0)
|
parent = dget_parent(dentry);
|
||||||
return error;
|
dir = parent->d_inode;
|
||||||
dir = nd.dentry->d_inode;
|
|
||||||
mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
|
mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
|
||||||
dentry = lookup_one_len(nd.last.name, nd.dentry, nd.last.len);
|
|
||||||
if (IS_ERR(dentry)) {
|
|
||||||
error = PTR_ERR(dentry);
|
|
||||||
goto out_release;
|
|
||||||
}
|
|
||||||
rpc_depopulate(dentry);
|
rpc_depopulate(dentry);
|
||||||
error = __rpc_rmdir(dir, dentry);
|
error = __rpc_rmdir(dir, dentry);
|
||||||
dput(dentry);
|
dput(dentry);
|
||||||
out_release:
|
|
||||||
mutex_unlock(&dir->i_mutex);
|
mutex_unlock(&dir->i_mutex);
|
||||||
rpc_release_path(&nd);
|
dput(parent);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -746,32 +739,26 @@ rpc_mkpipe(char *path, void *private, struct rpc_pipe_ops *ops, int flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
rpc_unlink(char *path)
|
rpc_unlink(struct dentry *dentry)
|
||||||
{
|
{
|
||||||
struct nameidata nd;
|
struct dentry *parent;
|
||||||
struct dentry *dentry;
|
|
||||||
struct inode *dir;
|
struct inode *dir;
|
||||||
int error;
|
int error = 0;
|
||||||
|
|
||||||
if ((error = rpc_lookup_parent(path, &nd)) != 0)
|
parent = dget_parent(dentry);
|
||||||
return error;
|
dir = parent->d_inode;
|
||||||
dir = nd.dentry->d_inode;
|
|
||||||
mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
|
mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
|
||||||
dentry = lookup_one_len(nd.last.name, nd.dentry, nd.last.len);
|
if (!d_unhashed(dentry)) {
|
||||||
if (IS_ERR(dentry)) {
|
d_drop(dentry);
|
||||||
error = PTR_ERR(dentry);
|
if (dentry->d_inode) {
|
||||||
goto out_release;
|
rpc_close_pipes(dentry->d_inode);
|
||||||
}
|
error = simple_unlink(dir, dentry);
|
||||||
d_drop(dentry);
|
}
|
||||||
if (dentry->d_inode) {
|
inode_dir_notify(dir, DN_DELETE);
|
||||||
rpc_close_pipes(dentry->d_inode);
|
|
||||||
error = simple_unlink(dir, dentry);
|
|
||||||
}
|
}
|
||||||
dput(dentry);
|
dput(dentry);
|
||||||
inode_dir_notify(dir, DN_DELETE);
|
|
||||||
out_release:
|
|
||||||
mutex_unlock(&dir->i_mutex);
|
mutex_unlock(&dir->i_mutex);
|
||||||
rpc_release_path(&nd);
|
dput(parent);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user