mirror of https://github.com/torvalds/linux.git
Bunch of unrelated fixes
- polling fix for trans fd that ought to have been fixed otherwise back in March, but apparently came back somewhere else... - USB transport buffer overflow fix - Some dentry lifetime rework to handle metadata update for currently opened files in uncached mode, or inode type change in cached mode - a double-put on invalid flush found by syzbot - and finally /sys/fs/9p/caches not advancing buffer and overwriting itself for large contents Thanks to everyone involved! -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE/IPbcYBuWt0zoYhOq06b7GqY5nAFAmjns5cACgkQq06b7GqY 5nDGLg/+Ltsiwj51CDwyJxFPX4ki1jM3j2iA8BNpdjjzCev6Jp1vuWBPiV+sTtgM zKmIw9joyvzaIXKzA3h7tMe7h7y8H4p7KZyD3YSDSNW5XIb5UYXeQwYVw39OxENk nVQkQ41H+bPepmz3R0t/F4la9myVLBtfdcPWJN+JfkOLgdeemCGf+TShJ6F+9Qaq PTd3UKfdv8JRlKQmeLH7pPlBoWYRoC2Tq3pZbyC3D1A50bWkTfxusW0k3MUzRyHO t/jNbhHt0ai+densQ6O5M+ALMI7KIIzR+obVaBHfzSUcwFeGhmW2x84Mo0qX6YMF 0B/fY3mCXi8QO6my1hfwmbRtY5mEV967wM/uF7E/SuvyNVizOMBZn8FgWfVPVszr ix1iNBgQJdoOEMbHvDfCAtGNorFrMiybyLvoabL7YCwFo68LdYqj2br3/feajoYM 5g46nUcidH4fVBLtiBGE8w0ko8aa3zLB4iu/fdATuEZ1r+gPt40SWo1mKahoCgY3 BOtYxEZTnd4l4GPJDQIaYgVckgSiex0xcE9pRJ5LtBwdyw9g4jwfb39WHx4MT2sE u5xWDbadU/ZM6ppLJ/iBkotvU9D7ohKTviN1IfCwjqL7IMBNz5c+nBwLQZWK4YTR 2ySKpv1VOMROglt1KvnHfdpmdJ+CjAJLLNE+XSz9AHXinK5v8aM= =bUN1 -----END PGP SIGNATURE----- Merge tag '9p-for-6.18-rc1' of https://github.com/martinetd/linux Pull 9p updates from Dominique Martinet: "A bunch of unrelated fixes: - polling fix for trans fd that ought to have been fixed otherwise back in March, but apparently came back somewhere else... - USB transport buffer overflow fix - Some dentry lifetime rework to handle metadata update for currently opened files in uncached mode, or inode type change in cached mode - a double-put on invalid flush found by syzbot - and finally /sys/fs/9p/caches not advancing buffer and overwriting itself for large contents Thanks to everyone involved!" * tag '9p-for-6.18-rc1' of https://github.com/martinetd/linux: 9p: sysfs_init: don't hardcode error to ENOMEM 9p: fix /sys/fs/9p/caches overwriting itself 9p: clean up comment typos 9p/trans_fd: p9_fd_request: kick rx thread if EPOLLIN net/9p: fix double req put in p9_fd_cancelled net/9p: Fix buffer overflow in USB transport layer fs/9p: Add p9_debug(VFS) in d_revalidate fs/9p: Invalidate dentry if inode type change detected in cached mode fs/9p: Refresh metadata in d_revalidate for uncached mode too
This commit is contained in:
commit
80b7065ec1
16
fs/9p/v9fs.c
16
fs/9p/v9fs.c
|
|
@ -438,8 +438,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
|
|||
v9ses->flags &= ~V9FS_ACCESS_MASK;
|
||||
v9ses->flags |= V9FS_ACCESS_USER;
|
||||
}
|
||||
/*FIXME !! */
|
||||
/* for legacy mode, fall back to V9FS_ACCESS_ANY */
|
||||
/* FIXME: for legacy mode, fall back to V9FS_ACCESS_ANY */
|
||||
if (!(v9fs_proto_dotu(v9ses) || v9fs_proto_dotl(v9ses)) &&
|
||||
((v9ses->flags&V9FS_ACCESS_MASK) == V9FS_ACCESS_USER)) {
|
||||
|
||||
|
|
@ -450,7 +449,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
|
|||
if (!v9fs_proto_dotl(v9ses) ||
|
||||
!((v9ses->flags & V9FS_ACCESS_MASK) == V9FS_ACCESS_CLIENT)) {
|
||||
/*
|
||||
* We support ACL checks on clinet only if the protocol is
|
||||
* We support ACL checks on client only if the protocol is
|
||||
* 9P2000.L and access is V9FS_ACCESS_CLIENT.
|
||||
*/
|
||||
v9ses->flags &= ~V9FS_ACL_MASK;
|
||||
|
|
@ -561,7 +560,7 @@ static ssize_t caches_show(struct kobject *kobj,
|
|||
spin_lock(&v9fs_sessionlist_lock);
|
||||
list_for_each_entry(v9ses, &v9fs_sessionlist, slist) {
|
||||
if (v9ses->cachetag) {
|
||||
n = snprintf(buf, limit, "%s\n", v9ses->cachetag);
|
||||
n = snprintf(buf + count, limit, "%s\n", v9ses->cachetag);
|
||||
if (n < 0) {
|
||||
count = n;
|
||||
break;
|
||||
|
|
@ -597,13 +596,16 @@ static const struct attribute_group v9fs_attr_group = {
|
|||
|
||||
static int __init v9fs_sysfs_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
v9fs_kobj = kobject_create_and_add("9p", fs_kobj);
|
||||
if (!v9fs_kobj)
|
||||
return -ENOMEM;
|
||||
|
||||
if (sysfs_create_group(v9fs_kobj, &v9fs_attr_group)) {
|
||||
ret = sysfs_create_group(v9fs_kobj, &v9fs_attr_group);
|
||||
if (ret) {
|
||||
kobject_put(v9fs_kobj);
|
||||
return -ENOMEM;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -669,7 +671,7 @@ static int __init init_v9fs(void)
|
|||
int err;
|
||||
|
||||
pr_info("Installing v9fs 9p2000 file system support\n");
|
||||
/* TODO: Setup list of registered trasnport modules */
|
||||
/* TODO: Setup list of registered transport modules */
|
||||
|
||||
err = v9fs_init_inode_cache();
|
||||
if (err < 0) {
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ static int __v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
|
|||
struct p9_fid *fid;
|
||||
struct inode *inode;
|
||||
struct v9fs_inode *v9inode;
|
||||
unsigned int cached;
|
||||
|
||||
if (flags & LOOKUP_RCU)
|
||||
return -ECHILD;
|
||||
|
|
@ -75,13 +76,22 @@ static int __v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
|
|||
goto out_valid;
|
||||
|
||||
v9inode = V9FS_I(inode);
|
||||
if (v9inode->cache_validity & V9FS_INO_INVALID_ATTR) {
|
||||
struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
|
||||
|
||||
cached = v9ses->cache & (CACHE_META | CACHE_LOOSE);
|
||||
|
||||
if (!cached || v9inode->cache_validity & V9FS_INO_INVALID_ATTR) {
|
||||
int retval;
|
||||
struct v9fs_session_info *v9ses;
|
||||
|
||||
fid = v9fs_fid_lookup(dentry);
|
||||
if (IS_ERR(fid))
|
||||
if (IS_ERR(fid)) {
|
||||
p9_debug(
|
||||
P9_DEBUG_VFS,
|
||||
"v9fs_fid_lookup: dentry = %pd (%p), got error %pe\n",
|
||||
dentry, dentry, fid);
|
||||
return PTR_ERR(fid);
|
||||
}
|
||||
|
||||
v9ses = v9fs_inode2v9ses(inode);
|
||||
if (v9fs_proto_dotl(v9ses))
|
||||
|
|
@ -90,12 +100,25 @@ static int __v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
|
|||
retval = v9fs_refresh_inode(fid, inode);
|
||||
p9_fid_put(fid);
|
||||
|
||||
if (retval == -ENOENT)
|
||||
if (retval == -ENOENT) {
|
||||
p9_debug(P9_DEBUG_VFS, "dentry: %pd (%p) invalidated due to ENOENT\n",
|
||||
dentry, dentry);
|
||||
return 0;
|
||||
if (retval < 0)
|
||||
}
|
||||
if (v9inode->cache_validity & V9FS_INO_INVALID_ATTR) {
|
||||
p9_debug(P9_DEBUG_VFS, "dentry: %pd (%p) invalidated due to type change\n",
|
||||
dentry, dentry);
|
||||
return 0;
|
||||
}
|
||||
if (retval < 0) {
|
||||
p9_debug(P9_DEBUG_VFS,
|
||||
"refresh inode: dentry = %pd (%p), got error %pe\n",
|
||||
dentry, dentry, ERR_PTR(retval));
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
out_valid:
|
||||
p9_debug(P9_DEBUG_VFS, "dentry: %pd (%p) is valid\n", dentry, dentry);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -127,6 +150,8 @@ const struct dentry_operations v9fs_cached_dentry_operations = {
|
|||
};
|
||||
|
||||
const struct dentry_operations v9fs_dentry_operations = {
|
||||
.d_revalidate = v9fs_lookup_revalidate,
|
||||
.d_weak_revalidate = __v9fs_lookup_revalidate,
|
||||
.d_release = v9fs_dentry_release,
|
||||
.d_unalias_trylock = v9fs_dentry_unalias_trylock,
|
||||
.d_unalias_unlock = v9fs_dentry_unalias_unlock,
|
||||
|
|
|
|||
|
|
@ -1339,8 +1339,14 @@ int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode)
|
|||
* Don't update inode if the file type is different
|
||||
*/
|
||||
umode = p9mode2unixmode(v9ses, st, &rdev);
|
||||
if (inode_wrong_type(inode, umode))
|
||||
if (inode_wrong_type(inode, umode)) {
|
||||
/*
|
||||
* Do this as a way of letting the caller know the inode should not
|
||||
* be reused
|
||||
*/
|
||||
v9fs_invalidate_inode_attr(inode);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't want to refresh inode->i_size,
|
||||
|
|
|
|||
|
|
@ -897,8 +897,14 @@ int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode)
|
|||
/*
|
||||
* Don't update inode if the file type is different
|
||||
*/
|
||||
if (inode_wrong_type(inode, st->st_mode))
|
||||
if (inode_wrong_type(inode, st->st_mode)) {
|
||||
/*
|
||||
* Do this as a way of letting the caller know the inode should not
|
||||
* be reused
|
||||
*/
|
||||
v9fs_invalidate_inode_attr(inode);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't want to refresh inode->i_size,
|
||||
|
|
|
|||
|
|
@ -666,7 +666,6 @@ static void p9_poll_mux(struct p9_conn *m)
|
|||
|
||||
static int p9_fd_request(struct p9_client *client, struct p9_req_t *req)
|
||||
{
|
||||
__poll_t n;
|
||||
int err;
|
||||
struct p9_trans_fd *ts = client->trans;
|
||||
struct p9_conn *m = &ts->conn;
|
||||
|
|
@ -686,13 +685,7 @@ static int p9_fd_request(struct p9_client *client, struct p9_req_t *req)
|
|||
list_add_tail(&req->req_list, &m->unsent_req_list);
|
||||
spin_unlock(&m->req_lock);
|
||||
|
||||
if (test_and_clear_bit(Wpending, &m->wsched))
|
||||
n = EPOLLOUT;
|
||||
else
|
||||
n = p9_fd_poll(m->client, NULL, NULL);
|
||||
|
||||
if (n & EPOLLOUT && !test_and_set_bit(Wworksched, &m->wsched))
|
||||
schedule_work(&m->wq);
|
||||
p9_poll_mux(m);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -726,10 +719,10 @@ static int p9_fd_cancelled(struct p9_client *client, struct p9_req_t *req)
|
|||
p9_debug(P9_DEBUG_TRANS, "client %p req %p\n", client, req);
|
||||
|
||||
spin_lock(&m->req_lock);
|
||||
/* Ignore cancelled request if message has been received
|
||||
* before lock.
|
||||
/* Ignore cancelled request if status changed since the request was
|
||||
* processed in p9_client_flush()
|
||||
*/
|
||||
if (req->status == REQ_STATUS_RCVD) {
|
||||
if (req->status != REQ_STATUS_SENT) {
|
||||
spin_unlock(&m->req_lock);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -231,6 +231,8 @@ static void usb9pfs_rx_complete(struct usb_ep *ep, struct usb_request *req)
|
|||
struct f_usb9pfs *usb9pfs = ep->driver_data;
|
||||
struct usb_composite_dev *cdev = usb9pfs->function.config->cdev;
|
||||
struct p9_req_t *p9_rx_req;
|
||||
unsigned int req_size = req->actual;
|
||||
int status = REQ_STATUS_RCVD;
|
||||
|
||||
if (req->status) {
|
||||
dev_err(&cdev->gadget->dev, "%s usb9pfs complete --> %d, %d/%d\n",
|
||||
|
|
@ -242,11 +244,19 @@ static void usb9pfs_rx_complete(struct usb_ep *ep, struct usb_request *req)
|
|||
if (!p9_rx_req)
|
||||
return;
|
||||
|
||||
memcpy(p9_rx_req->rc.sdata, req->buf, req->actual);
|
||||
if (req_size > p9_rx_req->rc.capacity) {
|
||||
dev_err(&cdev->gadget->dev,
|
||||
"%s received data size %u exceeds buffer capacity %zu\n",
|
||||
ep->name, req_size, p9_rx_req->rc.capacity);
|
||||
req_size = 0;
|
||||
status = REQ_STATUS_ERROR;
|
||||
}
|
||||
|
||||
p9_rx_req->rc.size = req->actual;
|
||||
memcpy(p9_rx_req->rc.sdata, req->buf, req_size);
|
||||
|
||||
p9_client_cb(usb9pfs->client, p9_rx_req, REQ_STATUS_RCVD);
|
||||
p9_rx_req->rc.size = req_size;
|
||||
|
||||
p9_client_cb(usb9pfs->client, p9_rx_req, status);
|
||||
p9_req_put(usb9pfs->client, p9_rx_req);
|
||||
|
||||
complete(&usb9pfs->received);
|
||||
|
|
|
|||
Loading…
Reference in New Issue