struct path is embedded into several objects, starting with struct file. In a lot of places we rely upon e.g. file->f_path of an opened file remaining unchanging; things like "ask for write access to file->f_path.mnt when opening for write, release that on final fput()" would break badly if ->f_path.mnt could change between those. It's not the only place like that; both VFS and filesystems expect that to hold. Anything that would want to play silly buggers with that would have to be _very_ careful and would be rather brittle, at that. It's not impossible to get away with, but any such place is a source of headache for proofs of correctness, as well as a likely cause of bugs in the future. Unfortunately, verifying that turns into several hours of manual audit that has to be repeated once in a while and I'm sick and tired of doing that. Let the compiler deal with that crap. The same goes for struct unix_sock ->path, etc. Note that in the mainline we have _very_ few places that store to ->f_path. 1) init_file() zeroes it out 2) file_init_path() copies the caller-supplied struct path into it (common helper of alloc_file() family of primitives; struct file is freshly allocated, we are setting it up) 3) atomic_open()/finish_open()/finish_no_open() arrange for setting ->f_path between them. Again, that's before it gets opened. 4) vfs_tmpfile() - ditto. 5) do_dentry_open() clears it on early failure exits 6) vfs_open() sets it to caller-supplied struct path - that's opening the file by path (dentry_open() and its ilk are using that one). Again, prior to file getting opened. 7) acct_on() (acct(2) helper) is flipping ->f_path.mnt of its internally opened and internally used file to cloned mount. It does get away with that, but it's neither pretty nor robust. All except the last one are in core VFS and not dealing with already opened files. Killing (7) is doable - it's not hard to get rid of that weird shit in acct_on(). After that no stores happen to opened files and all those stores are local to fs/file_table.c, fs/open.c and fs/namei.c (the latter - in the open-related parts). After that the obvious next step would be to turn f_path into type-punning union of struct path __f_path and const struct path f_path, and switch the places that should do stores (see above) to using ->__f_path. It's valid C99 - no UB there. struct file no longer can be a modifiable lvalue, but we never did wholesale copying for those and there's no reason to start; what's more, we never embed struct file into any other objects. It's not quite that simple, though - things like return vfs_statx_path(&fd_file(f)->f_path, flags, stat, request_mask); would have the compiler complain; it needs to be told that vfs_statx_path() is not going to modify the struct path it's been given. IOW, we need to switch a bunch of struct path * arguments to const struct path * before we can go for the final part. Turns out that there's not a lot of such missing annotations. So this stuff sits in two branches: #work.path switches the struct path * arguments that are never used to modify the struct path in question to const struct path *. Not all of those functions are used for ->f_path, but there's not a lot of them and new call sites might appear, so let's deal with all that bunch. #work.f_path starts with getting rid of the shit in acct_on(), then merges #work.path and #work.mount in (I don't want to pull constification patches out of #work.mount), then does the conversion of f_path to anon union. Branches are in git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs.git #work.path and git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs.git #work.f_path resp.; individual patches in followups. Please, review. If nobody objects, I'm putting that into #for-next early next week...