Merge tag '9p-for-4.20' of git://github.com/martinetd/linux
Pull 9p updates from Dominique Martinet: "Highlights this time around are the end of Matthew's work to remove the custom 9p request cache and use a slab directly for requests, with some extra patches on my end to not degrade performance, but it's a very good cleanup. Tomas and I fixed a few more syzkaller bugs (refcount is the big one), and I had a go at the coverity bugs and at some of the bugzilla reports we had open for a while. I'm a bit disappointed that I couldn't get much reviews for a few of my own patches, but the big ones got some and it's all been soaking in linux-next for quite a while so I think it should be OK. Summary: - Finish removing the custom 9p request cache mechanism - Embed part of the fcall in the request to have better slab performance (msize usually is power of two aligned) - syzkaller fixes: * add a refcount to 9p requests to avoid use after free * a few double free issues - A few coverity fixes - Some old patches that were in the bugzilla: * do not trust pdu content for size header * mount option for lock retry interval" * tag '9p-for-4.20' of git://github.com/martinetd/linux: (21 commits) 9p/trans_fd: put worker reqs on destroy 9p/trans_fd: abort p9_read_work if req status changed 9p: potential NULL dereference 9p locks: fix glock.client_id leak in do_lock 9p: p9dirent_read: check network-provided name length 9p/rdma: remove useless check in cm_event_handler 9p: acl: fix uninitialized iattr access 9p locks: add mount option for lock retry interval 9p: do not trust pdu content for stat item size 9p: Rename req to rreq in trans_fd 9p: fix spelling mistake in fall-through annotation 9p/rdma: do not disconnect on down_interruptible EAGAIN 9p: Add refcount to p9_req_t 9p: rename p9_free_req() function 9p: add a per-client fcall kmem_cache 9p: embed fcall in req to round down buffer allocs 9p: Remove p9_idpool 9p: Use a slab for allocating requests 9p: clear dangling pointers in p9stat_free v9fs_dir_readdir: fix double-free on p9stat_read error ...
This commit is contained in:
@@ -276,7 +276,7 @@ static int v9fs_xattr_set_acl(const struct xattr_handler *handler,
|
||||
switch (handler->flags) {
|
||||
case ACL_TYPE_ACCESS:
|
||||
if (acl) {
|
||||
struct iattr iattr;
|
||||
struct iattr iattr = { 0 };
|
||||
struct posix_acl *old_acl = acl;
|
||||
|
||||
retval = posix_acl_update_mode(inode, &iattr.ia_mode, &acl);
|
||||
|
21
fs/9p/v9fs.c
21
fs/9p/v9fs.c
@@ -61,6 +61,8 @@ enum {
|
||||
Opt_cache_loose, Opt_fscache, Opt_mmap,
|
||||
/* Access options */
|
||||
Opt_access, Opt_posixacl,
|
||||
/* Lock timeout option */
|
||||
Opt_locktimeout,
|
||||
/* Error token */
|
||||
Opt_err
|
||||
};
|
||||
@@ -80,6 +82,7 @@ static const match_table_t tokens = {
|
||||
{Opt_cachetag, "cachetag=%s"},
|
||||
{Opt_access, "access=%s"},
|
||||
{Opt_posixacl, "posixacl"},
|
||||
{Opt_locktimeout, "locktimeout=%u"},
|
||||
{Opt_err, NULL}
|
||||
};
|
||||
|
||||
@@ -187,6 +190,7 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
|
||||
#ifdef CONFIG_9P_FSCACHE
|
||||
v9ses->cachetag = NULL;
|
||||
#endif
|
||||
v9ses->session_lock_timeout = P9_LOCK_TIMEOUT;
|
||||
|
||||
if (!opts)
|
||||
return 0;
|
||||
@@ -359,6 +363,23 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
|
||||
#endif
|
||||
break;
|
||||
|
||||
case Opt_locktimeout:
|
||||
r = match_int(&args[0], &option);
|
||||
if (r < 0) {
|
||||
p9_debug(P9_DEBUG_ERROR,
|
||||
"integer field, but no integer?\n");
|
||||
ret = r;
|
||||
continue;
|
||||
}
|
||||
if (option < 1) {
|
||||
p9_debug(P9_DEBUG_ERROR,
|
||||
"locktimeout must be a greater than zero integer.\n");
|
||||
ret = -EINVAL;
|
||||
continue;
|
||||
}
|
||||
v9ses->session_lock_timeout = (long)option * HZ;
|
||||
break;
|
||||
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
@@ -116,6 +116,7 @@ struct v9fs_session_info {
|
||||
struct p9_client *clnt; /* 9p client */
|
||||
struct list_head slist; /* list of sessions registered with v9fs */
|
||||
struct rw_semaphore rename_sem;
|
||||
long session_lock_timeout; /* retry interval for blocking locks */
|
||||
};
|
||||
|
||||
/* cache_validity flags */
|
||||
|
@@ -76,15 +76,6 @@ static inline int dt_type(struct p9_wstat *mistat)
|
||||
return rettype;
|
||||
}
|
||||
|
||||
static void p9stat_init(struct p9_wstat *stbuf)
|
||||
{
|
||||
stbuf->name = NULL;
|
||||
stbuf->uid = NULL;
|
||||
stbuf->gid = NULL;
|
||||
stbuf->muid = NULL;
|
||||
stbuf->extension = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* v9fs_alloc_rdir_buf - Allocate buffer used for read and readdir
|
||||
* @filp: opened file structure
|
||||
@@ -114,7 +105,6 @@ static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx)
|
||||
int err = 0;
|
||||
struct p9_fid *fid;
|
||||
int buflen;
|
||||
int reclen = 0;
|
||||
struct p9_rdir *rdir;
|
||||
struct kvec kvec;
|
||||
|
||||
@@ -145,15 +135,12 @@ static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx)
|
||||
rdir->tail = n;
|
||||
}
|
||||
while (rdir->head < rdir->tail) {
|
||||
p9stat_init(&st);
|
||||
err = p9stat_read(fid->clnt, rdir->buf + rdir->head,
|
||||
rdir->tail - rdir->head, &st);
|
||||
if (err) {
|
||||
if (err <= 0) {
|
||||
p9_debug(P9_DEBUG_VFS, "returned %d\n", err);
|
||||
p9stat_free(&st);
|
||||
return -EIO;
|
||||
}
|
||||
reclen = st.size+2;
|
||||
|
||||
over = !dir_emit(ctx, st.name, strlen(st.name),
|
||||
v9fs_qid2ino(&st.qid), dt_type(&st));
|
||||
@@ -161,8 +148,8 @@ static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx)
|
||||
if (over)
|
||||
return 0;
|
||||
|
||||
rdir->head += reclen;
|
||||
ctx->pos += reclen;
|
||||
rdir->head += err;
|
||||
ctx->pos += err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -154,6 +154,7 @@ static int v9fs_file_do_lock(struct file *filp, int cmd, struct file_lock *fl)
|
||||
uint8_t status = P9_LOCK_ERROR;
|
||||
int res = 0;
|
||||
unsigned char fl_type;
|
||||
struct v9fs_session_info *v9ses;
|
||||
|
||||
fid = filp->private_data;
|
||||
BUG_ON(fid == NULL);
|
||||
@@ -189,6 +190,8 @@ static int v9fs_file_do_lock(struct file *filp, int cmd, struct file_lock *fl)
|
||||
if (IS_SETLKW(cmd))
|
||||
flock.flags = P9_LOCK_FLAGS_BLOCK;
|
||||
|
||||
v9ses = v9fs_inode2v9ses(file_inode(filp));
|
||||
|
||||
/*
|
||||
* if its a blocked request and we get P9_LOCK_BLOCKED as the status
|
||||
* for lock request, keep on trying
|
||||
@@ -202,8 +205,17 @@ static int v9fs_file_do_lock(struct file *filp, int cmd, struct file_lock *fl)
|
||||
break;
|
||||
if (status == P9_LOCK_BLOCKED && !IS_SETLKW(cmd))
|
||||
break;
|
||||
if (schedule_timeout_interruptible(P9_LOCK_TIMEOUT) != 0)
|
||||
if (schedule_timeout_interruptible(v9ses->session_lock_timeout)
|
||||
!= 0)
|
||||
break;
|
||||
/*
|
||||
* p9_client_lock_dotl overwrites flock.client_id with the
|
||||
* server message, free and reuse the client name
|
||||
*/
|
||||
if (flock.client_id != fid->clnt->name) {
|
||||
kfree(flock.client_id);
|
||||
flock.client_id = fid->clnt->name;
|
||||
}
|
||||
}
|
||||
|
||||
/* map 9p status to VFS status */
|
||||
@@ -216,7 +228,7 @@ static int v9fs_file_do_lock(struct file *filp, int cmd, struct file_lock *fl)
|
||||
break;
|
||||
default:
|
||||
WARN_ONCE(1, "unknown lock status code: %d\n", status);
|
||||
/* fallthough */
|
||||
/* fall through */
|
||||
case P9_LOCK_ERROR:
|
||||
case P9_LOCK_GRACE:
|
||||
res = -ENOLCK;
|
||||
@@ -235,6 +247,8 @@ out_unlock:
|
||||
locks_lock_file_wait(filp, fl);
|
||||
fl->fl_type = fl_type;
|
||||
}
|
||||
if (flock.client_id != fid->clnt->name)
|
||||
kfree(flock.client_id);
|
||||
out:
|
||||
return res;
|
||||
}
|
||||
@@ -269,7 +283,7 @@ static int v9fs_file_getlock(struct file *filp, struct file_lock *fl)
|
||||
|
||||
res = p9_client_getlock_dotl(fid, &glock);
|
||||
if (res < 0)
|
||||
return res;
|
||||
goto out;
|
||||
/* map 9p lock type to os lock type */
|
||||
switch (glock.type) {
|
||||
case P9_LOCK_TYPE_RDLCK:
|
||||
@@ -290,7 +304,9 @@ static int v9fs_file_getlock(struct file *filp, struct file_lock *fl)
|
||||
fl->fl_end = glock.start + glock.length - 1;
|
||||
fl->fl_pid = -glock.proc_id;
|
||||
}
|
||||
kfree(glock.client_id);
|
||||
out:
|
||||
if (glock.client_id != fid->clnt->name)
|
||||
kfree(glock.client_id);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user