ceph: add ino32 mount option

The ino32 mount option forces the ceph fs to report 32 bit
ino values.  This is useful for 64 bit kernels with 32 bit userspace.

Signed-off-by: Yehuda Sadeh <yehuda@hq.newdream.net>
This commit is contained in:
Yehuda Sadeh 2011-01-21 16:44:03 -08:00 committed by Sage Weil
parent 483fac7148
commit ad1fee96cb
4 changed files with 65 additions and 25 deletions

View file

@ -161,7 +161,7 @@ more:
filp->f_pos = di->offset; filp->f_pos = di->offset;
err = filldir(dirent, dentry->d_name.name, err = filldir(dirent, dentry->d_name.name,
dentry->d_name.len, di->offset, dentry->d_name.len, di->offset,
dentry->d_inode->i_ino, ceph_translate_ino(dentry->d_sb, dentry->d_inode->i_ino),
dentry->d_inode->i_mode >> 12); dentry->d_inode->i_mode >> 12);
if (last) { if (last) {
@ -245,15 +245,17 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir)
dout("readdir off 0 -> '.'\n"); dout("readdir off 0 -> '.'\n");
if (filldir(dirent, ".", 1, ceph_make_fpos(0, 0), if (filldir(dirent, ".", 1, ceph_make_fpos(0, 0),
inode->i_ino, inode->i_mode >> 12) < 0) ceph_translate_ino(inode->i_sb, inode->i_ino),
inode->i_mode >> 12) < 0)
return 0; return 0;
filp->f_pos = 1; filp->f_pos = 1;
off = 1; off = 1;
} }
if (filp->f_pos == 1) { if (filp->f_pos == 1) {
ino_t ino = filp->f_dentry->d_parent->d_inode->i_ino;
dout("readdir off 1 -> '..'\n"); dout("readdir off 1 -> '..'\n");
if (filldir(dirent, "..", 2, ceph_make_fpos(0, 1), if (filldir(dirent, "..", 2, ceph_make_fpos(0, 1),
filp->f_dentry->d_parent->d_inode->i_ino, ceph_translate_ino(inode->i_sb, ino),
inode->i_mode >> 12) < 0) inode->i_mode >> 12) < 0)
return 0; return 0;
filp->f_pos = 2; filp->f_pos = 2;
@ -377,7 +379,8 @@ more:
if (filldir(dirent, if (filldir(dirent,
rinfo->dir_dname[off - fi->offset], rinfo->dir_dname[off - fi->offset],
rinfo->dir_dname_len[off - fi->offset], rinfo->dir_dname_len[off - fi->offset],
pos, ino, ftype) < 0) { pos,
ceph_translate_ino(inode->i_sb, ino), ftype) < 0) {
dout("filldir stopping us...\n"); dout("filldir stopping us...\n");
return 0; return 0;
} }

View file

@ -36,6 +36,13 @@ static void ceph_vmtruncate_work(struct work_struct *work);
/* /*
* find or create an inode, given the ceph ino number * find or create an inode, given the ceph ino number
*/ */
static int ceph_set_ino_cb(struct inode *inode, void *data)
{
ceph_inode(inode)->i_vino = *(struct ceph_vino *)data;
inode->i_ino = ceph_vino_to_ino(*(struct ceph_vino *)data);
return 0;
}
struct inode *ceph_get_inode(struct super_block *sb, struct ceph_vino vino) struct inode *ceph_get_inode(struct super_block *sb, struct ceph_vino vino)
{ {
struct inode *inode; struct inode *inode;
@ -1809,7 +1816,7 @@ int ceph_getattr(struct vfsmount *mnt, struct dentry *dentry,
err = ceph_do_getattr(inode, CEPH_STAT_CAP_INODE_ALL); err = ceph_do_getattr(inode, CEPH_STAT_CAP_INODE_ALL);
if (!err) { if (!err) {
generic_fillattr(inode, stat); generic_fillattr(inode, stat);
stat->ino = inode->i_ino; stat->ino = ceph_translate_ino(inode->i_sb, inode->i_ino);
if (ceph_snap(inode) != CEPH_NOSNAP) if (ceph_snap(inode) != CEPH_NOSNAP)
stat->dev = ceph_snap(inode); stat->dev = ceph_snap(inode);
else else

View file

@ -131,6 +131,7 @@ enum {
Opt_rbytes, Opt_rbytes,
Opt_norbytes, Opt_norbytes,
Opt_noasyncreaddir, Opt_noasyncreaddir,
Opt_ino32,
}; };
static match_table_t fsopt_tokens = { static match_table_t fsopt_tokens = {
@ -150,6 +151,7 @@ static match_table_t fsopt_tokens = {
{Opt_rbytes, "rbytes"}, {Opt_rbytes, "rbytes"},
{Opt_norbytes, "norbytes"}, {Opt_norbytes, "norbytes"},
{Opt_noasyncreaddir, "noasyncreaddir"}, {Opt_noasyncreaddir, "noasyncreaddir"},
{Opt_ino32, "ino32"},
{-1, NULL} {-1, NULL}
}; };
@ -225,6 +227,9 @@ static int parse_fsopt_token(char *c, void *private)
case Opt_noasyncreaddir: case Opt_noasyncreaddir:
fsopt->flags |= CEPH_MOUNT_OPT_NOASYNCREADDIR; fsopt->flags |= CEPH_MOUNT_OPT_NOASYNCREADDIR;
break; break;
case Opt_ino32:
fsopt->flags |= CEPH_MOUNT_OPT_INO32;
break;
default: default:
BUG_ON(token); BUG_ON(token);
} }

View file

@ -27,6 +27,7 @@
#define CEPH_MOUNT_OPT_DIRSTAT (1<<4) /* `cat dirname` for stats */ #define CEPH_MOUNT_OPT_DIRSTAT (1<<4) /* `cat dirname` for stats */
#define CEPH_MOUNT_OPT_RBYTES (1<<5) /* dir st_bytes = rbytes */ #define CEPH_MOUNT_OPT_RBYTES (1<<5) /* dir st_bytes = rbytes */
#define CEPH_MOUNT_OPT_NOASYNCREADDIR (1<<7) /* no dcache readdir */ #define CEPH_MOUNT_OPT_NOASYNCREADDIR (1<<7) /* no dcache readdir */
#define CEPH_MOUNT_OPT_INO32 (1<<8) /* 32 bit inos */
#define CEPH_MOUNT_OPT_DEFAULT (CEPH_MOUNT_OPT_RBYTES) #define CEPH_MOUNT_OPT_DEFAULT (CEPH_MOUNT_OPT_RBYTES)
@ -319,6 +320,16 @@ static inline struct ceph_inode_info *ceph_inode(struct inode *inode)
return container_of(inode, struct ceph_inode_info, vfs_inode); return container_of(inode, struct ceph_inode_info, vfs_inode);
} }
static inline struct ceph_fs_client *ceph_inode_to_client(struct inode *inode)
{
return (struct ceph_fs_client *)inode->i_sb->s_fs_info;
}
static inline struct ceph_fs_client *ceph_sb_to_client(struct super_block *sb)
{
return (struct ceph_fs_client *)sb->s_fs_info;
}
static inline struct ceph_vino ceph_vino(struct inode *inode) static inline struct ceph_vino ceph_vino(struct inode *inode)
{ {
return ceph_inode(inode)->i_vino; return ceph_inode(inode)->i_vino;
@ -327,19 +338,49 @@ static inline struct ceph_vino ceph_vino(struct inode *inode)
/* /*
* ino_t is <64 bits on many architectures, blech. * ino_t is <64 bits on many architectures, blech.
* *
* don't include snap in ino hash, at least for now. * i_ino (kernel inode) st_ino (userspace)
* i386 32 32
* x86_64+ino32 64 32
* x86_64 64 64
*/
static inline u32 ceph_ino_to_ino32(ino_t ino)
{
ino ^= ino >> (sizeof(ino) * 8 - 32);
if (!ino)
ino = 1;
return ino;
}
/*
* kernel i_ino value
*/ */
static inline ino_t ceph_vino_to_ino(struct ceph_vino vino) static inline ino_t ceph_vino_to_ino(struct ceph_vino vino)
{ {
ino_t ino = (ino_t)vino.ino; /* ^ (vino.snap << 20); */ ino_t ino = (ino_t)vino.ino; /* ^ (vino.snap << 20); */
#if BITS_PER_LONG == 32 #if BITS_PER_LONG == 32
ino ^= vino.ino >> (sizeof(u64)-sizeof(ino_t)) * 8; ino = ceph_ino_to_ino32(ino);
if (!ino)
ino = 1;
#endif #endif
return ino; return ino;
} }
/*
* user-visible ino (stat, filldir)
*/
#if BITS_PER_LONG == 32
static inline ino_t ceph_translate_ino(struct super_block *sb, ino_t ino)
{
return ino;
}
#else
static inline ino_t ceph_translate_ino(struct super_block *sb, ino_t ino)
{
if (ceph_test_mount_opt(ceph_sb_to_client(sb), INO32))
ino = ceph_ino_to_ino32(ino);
return ino;
}
#endif
/* for printf-style formatting */ /* for printf-style formatting */
#define ceph_vinop(i) ceph_inode(i)->i_vino.ino, ceph_inode(i)->i_vino.snap #define ceph_vinop(i) ceph_inode(i)->i_vino.ino, ceph_inode(i)->i_vino.snap
@ -428,13 +469,6 @@ static inline loff_t ceph_make_fpos(unsigned frag, unsigned off)
return ((loff_t)frag << 32) | (loff_t)off; return ((loff_t)frag << 32) | (loff_t)off;
} }
static inline int ceph_set_ino_cb(struct inode *inode, void *data)
{
ceph_inode(inode)->i_vino = *(struct ceph_vino *)data;
inode->i_ino = ceph_vino_to_ino(*(struct ceph_vino *)data);
return 0;
}
/* /*
* caps helpers * caps helpers
*/ */
@ -503,15 +537,6 @@ extern void ceph_reservation_status(struct ceph_fs_client *client,
int *total, int *avail, int *used, int *total, int *avail, int *used,
int *reserved, int *min); int *reserved, int *min);
static inline struct ceph_fs_client *ceph_inode_to_client(struct inode *inode)
{
return (struct ceph_fs_client *)inode->i_sb->s_fs_info;
}
static inline struct ceph_fs_client *ceph_sb_to_client(struct super_block *sb)
{
return (struct ceph_fs_client *)sb->s_fs_info;
}
/* /*