mirror of
https://github.com/torvalds/linux.git
synced 2024-11-25 05:32:00 +00:00
coda: avoid doing bad things on inode type changes during revalidation
When Coda discovers an inconsistent object, it turns it into a symlink. However we can't just follow this change in the kernel on an existing file or directory inode that may still have references. This patch removes the inconsistent inode from the inode hash and allocates a new inode for the symlink object. Link: https://lkml.kernel.org/r/20210908140308.18491-7-jaharkes@cs.cmu.edu Signed-off-by: Jan Harkes <jaharkes@cs.cmu.edu> Cc: Alex Shi <alex.shi@linux.alibaba.com> Cc: Jing Yangyang <jing.yangyang@zte.com.cn> Cc: Xin Tan <tanxin.ctf@gmail.com> Cc: Xiyu Yang <xiyuyang19@fudan.edu.cn> Cc: Zeal Robot <zealci@zte.com.cn> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
b2e3622836
commit
5a646fb3a3
@ -63,9 +63,10 @@ struct inode * coda_iget(struct super_block * sb, struct CodaFid * fid,
|
|||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
struct coda_inode_info *cii;
|
struct coda_inode_info *cii;
|
||||||
unsigned long hash = coda_f2i(fid);
|
unsigned long hash = coda_f2i(fid);
|
||||||
|
umode_t inode_type = coda_inode_type(attr);
|
||||||
|
|
||||||
|
retry:
|
||||||
inode = iget5_locked(sb, hash, coda_test_inode, coda_set_inode, fid);
|
inode = iget5_locked(sb, hash, coda_test_inode, coda_set_inode, fid);
|
||||||
|
|
||||||
if (!inode)
|
if (!inode)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
@ -75,11 +76,15 @@ struct inode * coda_iget(struct super_block * sb, struct CodaFid * fid,
|
|||||||
inode->i_ino = hash;
|
inode->i_ino = hash;
|
||||||
/* inode is locked and unique, no need to grab cii->c_lock */
|
/* inode is locked and unique, no need to grab cii->c_lock */
|
||||||
cii->c_mapcount = 0;
|
cii->c_mapcount = 0;
|
||||||
|
coda_fill_inode(inode, attr);
|
||||||
unlock_new_inode(inode);
|
unlock_new_inode(inode);
|
||||||
|
} else if ((inode->i_mode & S_IFMT) != inode_type) {
|
||||||
|
/* Inode has changed type, mark bad and grab a new one */
|
||||||
|
remove_inode_hash(inode);
|
||||||
|
coda_flag_inode(inode, C_PURGE);
|
||||||
|
iput(inode);
|
||||||
|
goto retry;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* always replace the attributes, type might have changed */
|
|
||||||
coda_fill_inode(inode, attr);
|
|
||||||
return inode;
|
return inode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,28 +87,27 @@ static struct coda_timespec timespec64_to_coda(struct timespec64 ts64)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* utility functions below */
|
/* utility functions below */
|
||||||
|
umode_t coda_inode_type(struct coda_vattr *attr)
|
||||||
|
{
|
||||||
|
switch (attr->va_type) {
|
||||||
|
case C_VREG:
|
||||||
|
return S_IFREG;
|
||||||
|
case C_VDIR:
|
||||||
|
return S_IFDIR;
|
||||||
|
case C_VLNK:
|
||||||
|
return S_IFLNK;
|
||||||
|
case C_VNON:
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void coda_vattr_to_iattr(struct inode *inode, struct coda_vattr *attr)
|
void coda_vattr_to_iattr(struct inode *inode, struct coda_vattr *attr)
|
||||||
{
|
{
|
||||||
int inode_type;
|
/* inode's i_flags, i_ino are set by iget
|
||||||
/* inode's i_flags, i_ino are set by iget
|
* XXX: is this all we need ??
|
||||||
XXX: is this all we need ??
|
*/
|
||||||
*/
|
umode_t inode_type = coda_inode_type(attr);
|
||||||
switch (attr->va_type) {
|
|
||||||
case C_VNON:
|
|
||||||
inode_type = 0;
|
|
||||||
break;
|
|
||||||
case C_VREG:
|
|
||||||
inode_type = S_IFREG;
|
|
||||||
break;
|
|
||||||
case C_VDIR:
|
|
||||||
inode_type = S_IFDIR;
|
|
||||||
break;
|
|
||||||
case C_VLNK:
|
|
||||||
inode_type = S_IFLNK;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
inode_type = 0;
|
|
||||||
}
|
|
||||||
inode->i_mode |= inode_type;
|
inode->i_mode |= inode_type;
|
||||||
|
|
||||||
if (attr->va_mode != (u_short) -1)
|
if (attr->va_mode != (u_short) -1)
|
||||||
|
@ -53,10 +53,11 @@ int coda_getattr(struct user_namespace *, const struct path *, struct kstat *,
|
|||||||
u32, unsigned int);
|
u32, unsigned int);
|
||||||
int coda_setattr(struct user_namespace *, struct dentry *, struct iattr *);
|
int coda_setattr(struct user_namespace *, struct dentry *, struct iattr *);
|
||||||
|
|
||||||
/* this file: heloers */
|
/* this file: helpers */
|
||||||
char *coda_f2s(struct CodaFid *f);
|
char *coda_f2s(struct CodaFid *f);
|
||||||
int coda_iscontrol(const char *name, size_t length);
|
int coda_iscontrol(const char *name, size_t length);
|
||||||
|
|
||||||
|
umode_t coda_inode_type(struct coda_vattr *attr);
|
||||||
void coda_vattr_to_iattr(struct inode *, struct coda_vattr *);
|
void coda_vattr_to_iattr(struct inode *, struct coda_vattr *);
|
||||||
void coda_iattr_to_vattr(struct iattr *, struct coda_vattr *);
|
void coda_iattr_to_vattr(struct iattr *, struct coda_vattr *);
|
||||||
unsigned short coda_flags_to_cflags(unsigned short);
|
unsigned short coda_flags_to_cflags(unsigned short);
|
||||||
|
Loading…
Reference in New Issue
Block a user