Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag '9p-for-5.19-rc4' of https://github.com/martinetd/linux

Pull 9pfs fixes from Dominique Martinet:
"A couple of fid refcount and fscache fixes:

- fid refcounting was incorrect in some corner cases and would leak
resources, only freed at umount time. The first three commits fix
three such cases

- 'cache=loose' or fscache was broken when trying to write a partial
page to a file with no read permission since the rework a few
releases ago.

The fix taken here is just to restore old behavior of using the
special 'writeback_fid' for such reads, which is open as root/RDWR
and such not get complains that we try to read on a WRONLY fid.

Long-term it'd be nice to get rid of this and not issue the read at
all (skip cache?) in such cases, but that direction hasn't
progressed"

* tag '9p-for-5.19-rc4' of https://github.com/martinetd/linux:
9p: fix EBADF errors in cached mode
9p: Fix refcounting during full path walks for fid lookups
9p: fix fid refcount leak in v9fs_vfs_get_link
9p: fix fid refcount leak in v9fs_vfs_atomic_open_dotl

+29 -17
+9 -13
fs/9p/fid.c
··· 152 152 const unsigned char **wnames, *uname; 153 153 int i, n, l, clone, access; 154 154 struct v9fs_session_info *v9ses; 155 - struct p9_fid *fid, *old_fid = NULL; 155 + struct p9_fid *fid, *old_fid; 156 156 157 157 v9ses = v9fs_dentry2v9ses(dentry); 158 158 access = v9ses->flags & V9FS_ACCESS_MASK; ··· 194 194 if (IS_ERR(fid)) 195 195 return fid; 196 196 197 + refcount_inc(&fid->count); 197 198 v9fs_fid_add(dentry->d_sb->s_root, fid); 198 199 } 199 200 /* If we are root ourself just return that */ 200 - if (dentry->d_sb->s_root == dentry) { 201 - refcount_inc(&fid->count); 201 + if (dentry->d_sb->s_root == dentry) 202 202 return fid; 203 - } 204 203 /* 205 204 * Do a multipath walk with attached root. 206 205 * When walking parent we need to make sure we ··· 211 212 fid = ERR_PTR(n); 212 213 goto err_out; 213 214 } 215 + old_fid = fid; 214 216 clone = 1; 215 217 i = 0; 216 218 while (i < n) { ··· 221 221 * walk to ensure none of the patch component change 222 222 */ 223 223 fid = p9_client_walk(fid, l, &wnames[i], clone); 224 + /* non-cloning walk will return the same fid */ 225 + if (fid != old_fid) { 226 + p9_client_clunk(old_fid); 227 + old_fid = fid; 228 + } 224 229 if (IS_ERR(fid)) { 225 - if (old_fid) { 226 - /* 227 - * If we fail, clunk fid which are mapping 228 - * to path component and not the last component 229 - * of the path. 230 - */ 231 - p9_client_clunk(old_fid); 232 - } 233 230 kfree(wnames); 234 231 goto err_out; 235 232 } 236 - old_fid = fid; 237 233 i += l; 238 234 clone = 0; 239 235 }
+13
fs/9p/vfs_addr.c
··· 58 58 */ 59 59 static int v9fs_init_request(struct netfs_io_request *rreq, struct file *file) 60 60 { 61 + struct inode *inode = file_inode(file); 62 + struct v9fs_inode *v9inode = V9FS_I(inode); 61 63 struct p9_fid *fid = file->private_data; 64 + 65 + BUG_ON(!fid); 66 + 67 + /* we might need to read from a fid that was opened write-only 68 + * for read-modify-write of page cache, use the writeback fid 69 + * for that */ 70 + if (rreq->origin == NETFS_READ_FOR_WRITE && 71 + (fid->mode & O_ACCMODE) == O_WRONLY) { 72 + fid = v9inode->writeback_fid; 73 + BUG_ON(!fid); 74 + } 62 75 63 76 refcount_inc(&fid->count); 64 77 rreq->netfs_priv = fid;
+4 -4
fs/9p/vfs_inode.c
··· 1251 1251 return ERR_PTR(-ECHILD); 1252 1252 1253 1253 v9ses = v9fs_dentry2v9ses(dentry); 1254 - fid = v9fs_fid_lookup(dentry); 1254 + if (!v9fs_proto_dotu(v9ses)) 1255 + return ERR_PTR(-EBADF); 1256 + 1255 1257 p9_debug(P9_DEBUG_VFS, "%pd\n", dentry); 1258 + fid = v9fs_fid_lookup(dentry); 1256 1259 1257 1260 if (IS_ERR(fid)) 1258 1261 return ERR_CAST(fid); 1259 - 1260 - if (!v9fs_proto_dotu(v9ses)) 1261 - return ERR_PTR(-EBADF); 1262 1262 1263 1263 st = p9_client_stat(fid); 1264 1264 p9_client_clunk(fid);
+3
fs/9p/vfs_inode_dotl.c
··· 274 274 if (IS_ERR(ofid)) { 275 275 err = PTR_ERR(ofid); 276 276 p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); 277 + p9_client_clunk(dfid); 277 278 goto out; 278 279 } 279 280 ··· 286 285 if (err) { 287 286 p9_debug(P9_DEBUG_VFS, "Failed to get acl values in creat %d\n", 288 287 err); 288 + p9_client_clunk(dfid); 289 289 goto error; 290 290 } 291 291 err = p9_client_create_dotl(ofid, name, v9fs_open_to_dotl_flags(flags), ··· 294 292 if (err < 0) { 295 293 p9_debug(P9_DEBUG_VFS, "p9_client_open_dotl failed in creat %d\n", 296 294 err); 295 + p9_client_clunk(dfid); 297 296 goto error; 298 297 } 299 298 v9fs_invalidate_inode_attr(dir);