/* * Update file handle information after changing a dentry. * This is only called by nfsd_create, nfsd_create_v3 and nfsd_proc_create */ __be32 fh_update(struct svc_fh *fhp) { struct dentry *dentry; if (!fhp->fh_dentry) goto out_bad; dentry = fhp->fh_dentry; if (!dentry->d_inode) goto out_negative; if (fhp->fh_handle.fh_version != 1) { _fh_update_old(dentry, fhp->fh_export, &fhp->fh_handle); } else { if (fhp->fh_handle.fh_fileid_type != FILEID_ROOT) goto out; _fh_update(fhp, fhp->fh_export, dentry); if (fhp->fh_handle.fh_fileid_type == 255) return nfserr_opnotsupp; } out: return 0; out_bad: printk(KERN_ERR "fh_update: fh not verified!\n"); goto out; out_negative: printk(KERN_ERR "fh_update: %s/%s still negative!\n", dentry->d_parent->d_name.name, dentry->d_name.name); goto out; }
/* * Update file handle information after changing a dentry. * This is only called by nfsd_create, nfsd_create_v3 and nfsd_proc_create */ int fh_update(struct svc_fh *fhp) { struct dentry *dentry; __u32 *datap; if (!fhp->fh_dentry) goto out_bad; dentry = fhp->fh_dentry; if (!dentry->d_inode) goto out_negative; if (fhp->fh_handle.fh_version != 1) { _fh_update_old(dentry, fhp->fh_export, &fhp->fh_handle); } else { int size; if (fhp->fh_handle.fh_fileid_type != 0) goto out_uptodate; datap = fhp->fh_handle.fh_auth+ fhp->fh_handle.fh_size/4 -1; size = (fhp->fh_maxsize - fhp->fh_handle.fh_size)/4; fhp->fh_handle.fh_fileid_type = _fh_update(dentry, fhp->fh_export, datap, &size); fhp->fh_handle.fh_size += size*4; if (fhp->fh_handle.fh_fileid_type == 255) return nfserr_opnotsupp; } out: return 0; out_bad: printk(KERN_ERR "fh_update: fh not verified!\n"); goto out; out_negative: printk(KERN_ERR "fh_update: %s/%s still negative!\n", dentry->d_parent->d_name.name, dentry->d_name.name); goto out; out_uptodate: printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n", dentry->d_parent->d_name.name, dentry->d_name.name); goto out; }
__be32 fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, struct svc_fh *ref_fh) { /* ref_fh is a reference file handle. * if it is non-null and for the same filesystem, then we should compose * a filehandle which is of the same version, where possible. * Currently, that means that if ref_fh->fh_handle.fh_version == 0xca * Then create a 32byte filehandle using nfs_fhbase_old * */ u8 version = 1; u8 fsid_type = 0; struct inode * inode = dentry->d_inode; struct dentry *parent = dentry->d_parent; __u32 *datap; dev_t ex_dev = exp->ex_dentry->d_inode->i_sb->s_dev; int root_export = (exp->ex_dentry == exp->ex_dentry->d_sb->s_root); dprintk("nfsd: fh_compose(exp %02x:%02x/%ld %s/%s, ino=%ld)\n", MAJOR(ex_dev), MINOR(ex_dev), (long) exp->ex_dentry->d_inode->i_ino, parent->d_name.name, dentry->d_name.name, (inode ? inode->i_ino : 0)); /* Choose filehandle version and fsid type based on * the reference filehandle (if it is in the same export) * or the export options. */ if (ref_fh && ref_fh->fh_export == exp) { version = ref_fh->fh_handle.fh_version; if (version == 0xca) fsid_type = FSID_DEV; else fsid_type = ref_fh->fh_handle.fh_fsid_type; /* We know this version/type works for this export * so there is no need for further checks. */ } else if (exp->ex_uuid) { if (fhp->fh_maxsize >= 64) { if (root_export) fsid_type = FSID_UUID16; else fsid_type = FSID_UUID16_INUM; } else { if (root_export) fsid_type = FSID_UUID8; else fsid_type = FSID_UUID4_INUM; } } else if (exp->ex_flags & NFSEXP_FSID) fsid_type = FSID_NUM; else if (!old_valid_dev(ex_dev)) /* for newer device numbers, we must use a newer fsid format */ fsid_type = FSID_ENCODE_DEV; else fsid_type = FSID_DEV; if (ref_fh == fhp) fh_put(ref_fh); if (fhp->fh_locked || fhp->fh_dentry) { printk(KERN_ERR "fh_compose: fh %s/%s not initialized!\n", parent->d_name.name, dentry->d_name.name); } if (fhp->fh_maxsize < NFS_FHSIZE) printk(KERN_ERR "fh_compose: called with maxsize %d! %s/%s\n", fhp->fh_maxsize, parent->d_name.name, dentry->d_name.name); fhp->fh_dentry = dget(dentry); /* our internal copy */ fhp->fh_export = exp; cache_get(&exp->h); if (version == 0xca) { /* old style filehandle please */ memset(&fhp->fh_handle.fh_base, 0, NFS_FHSIZE); fhp->fh_handle.fh_size = NFS_FHSIZE; fhp->fh_handle.ofh_dcookie = 0xfeebbaca; fhp->fh_handle.ofh_dev = old_encode_dev(ex_dev); fhp->fh_handle.ofh_xdev = fhp->fh_handle.ofh_dev; fhp->fh_handle.ofh_xino = ino_t_to_u32(exp->ex_dentry->d_inode->i_ino); fhp->fh_handle.ofh_dirino = ino_t_to_u32(parent_ino(dentry)); if (inode) _fh_update_old(dentry, exp, &fhp->fh_handle); } else { int len; fhp->fh_handle.fh_version = 1; fhp->fh_handle.fh_auth_type = 0; datap = fhp->fh_handle.fh_auth+0; fhp->fh_handle.fh_fsid_type = fsid_type; mk_fsid(fsid_type, datap, ex_dev, exp->ex_dentry->d_inode->i_ino, exp->ex_fsid, exp->ex_uuid); len = key_len(fsid_type); datap += len/4; fhp->fh_handle.fh_size = 4 + len; if (inode) { int size = (fhp->fh_maxsize-len-4)/4; fhp->fh_handle.fh_fileid_type = _fh_update(dentry, exp, datap, &size); fhp->fh_handle.fh_size += size*4; } if (fhp->fh_handle.fh_fileid_type == 255) return nfserr_opnotsupp; } nfsd_nr_verified++; return 0; }
__be32 fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, struct svc_fh *ref_fh) { /* ref_fh is a reference file handle. * if it is non-null and for the same filesystem, then we should compose * a filehandle which is of the same version, where possible. * Currently, that means that if ref_fh->fh_handle.fh_version == 0xca * Then create a 32byte filehandle using nfs_fhbase_old * */ u8 version; u8 fsid_type = 0; struct inode * inode = dentry->d_inode; struct dentry *parent = dentry->d_parent; __u32 *datap; dev_t ex_dev = exp->ex_path.dentry->d_inode->i_sb->s_dev; int root_export = (exp->ex_path.dentry == exp->ex_path.dentry->d_sb->s_root); dprintk("nfsd: fh_compose(exp %02x:%02x/%ld %s/%s, ino=%ld)\n", MAJOR(ex_dev), MINOR(ex_dev), (long) exp->ex_path.dentry->d_inode->i_ino, parent->d_name.name, dentry->d_name.name, (inode ? inode->i_ino : 0)); /* Choose filehandle version and fsid type based on * the reference filehandle (if it is in the same export) * or the export options. */ retry: version = 1; if (ref_fh && ref_fh->fh_export == exp) { version = ref_fh->fh_handle.fh_version; fsid_type = ref_fh->fh_handle.fh_fsid_type; if (ref_fh == fhp) fh_put(ref_fh); ref_fh = NULL; switch (version) { case 0xca: fsid_type = FSID_DEV; break; case 1: break; default: goto retry; } /* Need to check that this type works for this * export point. As the fsid -> filesystem mapping * was guided by user-space, there is no guarantee * that the filesystem actually supports that fsid * type. If it doesn't we loop around again without * ref_fh set. */ switch(fsid_type) { case FSID_DEV: if (!old_valid_dev(ex_dev)) goto retry; /* FALL THROUGH */ case FSID_MAJOR_MINOR: case FSID_ENCODE_DEV: if (!(exp->ex_path.dentry->d_inode->i_sb->s_type->fs_flags & FS_REQUIRES_DEV)) goto retry; break; case FSID_NUM: if (! (exp->ex_flags & NFSEXP_FSID)) goto retry; break; case FSID_UUID8: case FSID_UUID16: if (!root_export) goto retry; /* fall through */ case FSID_UUID4_INUM: case FSID_UUID16_INUM: if (exp->ex_uuid == NULL) goto retry; break; } } else if (exp->ex_uuid) { if (fhp->fh_maxsize >= 64) { if (root_export) fsid_type = FSID_UUID16; else fsid_type = FSID_UUID16_INUM; } else { if (root_export) fsid_type = FSID_UUID8; else fsid_type = FSID_UUID4_INUM; } } else if (exp->ex_flags & NFSEXP_FSID) fsid_type = FSID_NUM; else if (!old_valid_dev(ex_dev)) /* for newer device numbers, we must use a newer fsid format */ fsid_type = FSID_ENCODE_DEV; else fsid_type = FSID_DEV; if (ref_fh == fhp) fh_put(ref_fh); if (fhp->fh_locked || fhp->fh_dentry) { printk(KERN_ERR "fh_compose: fh %s/%s not initialized!\n", parent->d_name.name, dentry->d_name.name); } if (fhp->fh_maxsize < NFS_FHSIZE) printk(KERN_ERR "fh_compose: called with maxsize %d! %s/%s\n", fhp->fh_maxsize, parent->d_name.name, dentry->d_name.name); fhp->fh_dentry = dget(dentry); /* our internal copy */ fhp->fh_export = exp; cache_get(&exp->h); if (version == 0xca) { /* old style filehandle please */ memset(&fhp->fh_handle.fh_base, 0, NFS_FHSIZE); fhp->fh_handle.fh_size = NFS_FHSIZE; fhp->fh_handle.ofh_dcookie = 0xfeebbaca; fhp->fh_handle.ofh_dev = old_encode_dev(ex_dev); fhp->fh_handle.ofh_xdev = fhp->fh_handle.ofh_dev; fhp->fh_handle.ofh_xino = ino_t_to_u32(exp->ex_path.dentry->d_inode->i_ino); fhp->fh_handle.ofh_dirino = ino_t_to_u32(parent_ino(dentry)); if (inode) _fh_update_old(dentry, exp, &fhp->fh_handle); } else { int len; fhp->fh_handle.fh_version = 1; fhp->fh_handle.fh_auth_type = 0; datap = fhp->fh_handle.fh_auth+0; fhp->fh_handle.fh_fsid_type = fsid_type; mk_fsid(fsid_type, datap, ex_dev, exp->ex_path.dentry->d_inode->i_ino, exp->ex_fsid, exp->ex_uuid); len = key_len(fsid_type); datap += len/4; fhp->fh_handle.fh_size = 4 + len; if (inode) _fh_update(fhp, exp, dentry); if (fhp->fh_handle.fh_fileid_type == 255) return nfserr_opnotsupp; } nfsd_nr_verified++; return 0; }
int fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, struct svc_fh *ref_fh) { /* ref_fh is a reference file handle. * if it is non-null, then we should compose a filehandle which is * of the same version, where possible. * Currently, that means that if ref_fh->fh_handle.fh_version == 0xca * Then create a 32byte filehandle using nfs_fhbase_old * */ u8 ref_fh_version = 0; u8 ref_fh_fsid_type = 0; struct inode * inode = dentry->d_inode; struct dentry *parent = dentry->d_parent; __u32 *datap; dev_t ex_dev = exp->ex_dentry->d_inode->i_sb->s_dev; dprintk("nfsd: fh_compose(exp %02x:%02x/%ld %s/%s, ino=%ld)\n", MAJOR(ex_dev), MINOR(ex_dev), (long) exp->ex_dentry->d_inode->i_ino, parent->d_name.name, dentry->d_name.name, (inode ? inode->i_ino : 0)); if (ref_fh) { ref_fh_version = ref_fh->fh_handle.fh_version; if (ref_fh_version == 0xca) ref_fh_fsid_type = 0; else ref_fh_fsid_type = ref_fh->fh_handle.fh_fsid_type; if (ref_fh_fsid_type > 3) ref_fh_fsid_type = 0; } /* make sure ref_fh type works for given export */ if (ref_fh_fsid_type == 1 && !(exp->ex_flags & NFSEXP_FSID)) { /* if we don't have an fsid, we cannot provide one... */ ref_fh_fsid_type = 0; } if (!old_valid_dev(ex_dev) && ref_fh_fsid_type == 0) { /* for newer device numbers, we must use a newer fsid format */ ref_fh_version = 1; ref_fh_fsid_type = 3; } if (old_valid_dev(ex_dev) && (ref_fh_fsid_type == 2 || ref_fh_fsid_type == 3)) /* must use type1 for smaller device numbers */ ref_fh_fsid_type = 0; if (ref_fh == fhp) fh_put(ref_fh); if (fhp->fh_locked || fhp->fh_dentry) { printk(KERN_ERR "fh_compose: fh %s/%s not initialized!\n", parent->d_name.name, dentry->d_name.name); } if (fhp->fh_maxsize < NFS_FHSIZE) printk(KERN_ERR "fh_compose: called with maxsize %d! %s/%s\n", fhp->fh_maxsize, parent->d_name.name, dentry->d_name.name); fhp->fh_dentry = dget(dentry); /* our internal copy */ fhp->fh_export = exp; cache_get(&exp->h); if (ref_fh_version == 0xca) { /* old style filehandle please */ memset(&fhp->fh_handle.fh_base, 0, NFS_FHSIZE); fhp->fh_handle.fh_size = NFS_FHSIZE; fhp->fh_handle.ofh_dcookie = 0xfeebbaca; fhp->fh_handle.ofh_dev = old_encode_dev(ex_dev); fhp->fh_handle.ofh_xdev = fhp->fh_handle.ofh_dev; fhp->fh_handle.ofh_xino = ino_t_to_u32(exp->ex_dentry->d_inode->i_ino); fhp->fh_handle.ofh_dirino = ino_t_to_u32(parent_ino(dentry)); if (inode) _fh_update_old(dentry, exp, &fhp->fh_handle); } else { int len; fhp->fh_handle.fh_version = 1; fhp->fh_handle.fh_auth_type = 0; datap = fhp->fh_handle.fh_auth+0; fhp->fh_handle.fh_fsid_type = ref_fh_fsid_type; switch (ref_fh_fsid_type) { case 0: /* * fsid_type 0: * 2byte major, 2byte minor, 4byte inode */ mk_fsid_v0(datap, ex_dev, exp->ex_dentry->d_inode->i_ino); break; case 1: /* fsid_type 1 == 4 bytes filesystem id */ mk_fsid_v1(datap, exp->ex_fsid); break; case 2: /* * fsid_type 2: * 4byte major, 4byte minor, 4byte inode */ mk_fsid_v2(datap, ex_dev, exp->ex_dentry->d_inode->i_ino); break; case 3: /* * fsid_type 3: * 4byte devicenumber, 4byte inode */ mk_fsid_v3(datap, ex_dev, exp->ex_dentry->d_inode->i_ino); break; } len = key_len(ref_fh_fsid_type); datap += len/4; fhp->fh_handle.fh_size = 4 + len; if (inode) { int size = (fhp->fh_maxsize-len-4)/4; fhp->fh_handle.fh_fileid_type = _fh_update(dentry, exp, datap, &size); fhp->fh_handle.fh_size += size*4; } if (fhp->fh_handle.fh_fileid_type == 255) return nfserr_opnotsupp; } nfsd_nr_verified++; return 0; }