void cifs_fscache_get_client_cookie(struct TCP_Server_Info *server) { server->fscache = fscache_acquire_cookie(cifs_fscache_netfs.primary_index, &cifs_fscache_server_index_def, server); cFYI(1, "CIFS: get client cookie (0x%p/0x%p)", server, server->fscache); }
/* * Get the per-client index cookie for an NFS client if the appropriate mount * flag was set * - We always try and get an index cookie for the client, but get filehandle * cookies on a per-superblock basis, depending on the mount flags */ void nfs_fscache_get_client_cookie(struct nfs_client *clp) { /* create a cache index for looking up filehandles */ clp->fscache = fscache_acquire_cookie(nfs_fscache_netfs.primary_index, &nfs_fscache_server_index_def, clp); // dfprintk(FSCACHE, "NFS: get client cookie (0x%p/0x%p)\n", ; }
void cifs_fscache_get_super_cookie(struct cifsTconInfo *tcon) { struct TCP_Server_Info *server = tcon->ses->server; tcon->fscache = fscache_acquire_cookie(server->fscache, &cifs_fscache_super_index_def, tcon); cFYI(1, "CIFS: get superblock cookie (0x%p/0x%p)", server->fscache, tcon->fscache); }
void cifs_fscache_get_super_cookie(struct cifs_tcon *tcon) { struct TCP_Server_Info *server = tcon->ses->server; tcon->fscache = fscache_acquire_cookie(server->fscache, &cifs_fscache_super_index_def, tcon); cFYI(1, "%s: (0x%p/0x%p)", __func__, server->fscache, tcon->fscache); }
void v9fs_cache_session_get_cookie(struct v9fs_session_info *v9ses) { /* If no cache session tag was specified, we generate a random one. */ if (!v9ses->cachetag) v9fs_random_cachetag(v9ses); v9ses->fscache = fscache_acquire_cookie(v9fs_cache_netfs.primary_index, &v9fs_cache_session_index_def, v9ses); p9_debug(P9_DEBUG_FSC, "session %p get cookie %p\n", v9ses, v9ses->fscache); }
static void cifs_fscache_enable_inode_cookie(struct inode *inode) { struct cifsInodeInfo *cifsi = CIFS_I(inode); struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb); if (cifsi->fscache) return; if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE) { cifsi->fscache = fscache_acquire_cookie(tcon->fscache, &cifs_fscache_inode_object_def, cifsi); cFYI(1, "CIFS: got FH cookie (0x%p/0x%p)", tcon->fscache, cifsi->fscache); } }
/* * Get the per-inode cache cookie for an NFS inode. */ static void nfs_fscache_enable_inode_cookie(struct inode *inode) { struct super_block *sb = inode->i_sb; struct nfs_inode *nfsi = NFS_I(inode); if (nfsi->fscache || !NFS_FSCACHE(inode)) return; if ((NFS_SB(sb)->options & NFS_OPTION_FSCACHE)) { nfsi->fscache = fscache_acquire_cookie( NFS_SB(sb)->fscache, &nfs_fscache_inode_object_def, nfsi); // dfprintk(FSCACHE, "NFS: get FH cookie (0x%p/0x%p/0x%p)\n", ; } }
void cifs_fscache_reset_inode_cookie(struct inode *inode) { struct cifsInodeInfo *cifsi = CIFS_I(inode); struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); struct fscache_cookie *old = cifsi->fscache; if (cifsi->fscache) { /* retire the current fscache cache and get a new one */ fscache_relinquish_cookie(cifsi->fscache, 1); cifsi->fscache = fscache_acquire_cookie( cifs_sb_master_tcon(cifs_sb)->fscache, &cifs_fscache_inode_object_def, cifsi); cFYI(1, "CIFS: new cookie 0x%p oldcookie 0x%p", cifsi->fscache, old); } }
void v9fs_cache_inode_get_cookie(struct inode *inode) { struct v9fs_inode *v9inode; struct v9fs_session_info *v9ses; if (!S_ISREG(inode->i_mode)) return; v9inode = V9FS_I(inode); if (v9inode->fscache) return; v9ses = v9fs_inode2v9ses(inode); v9inode->fscache = fscache_acquire_cookie(v9ses->fscache, &v9fs_cache_inode_index_def, v9inode); p9_debug(P9_DEBUG_FSC, "inode %p get cookie %p\n", inode, v9inode->fscache); }
/* * Get the per-client index cookie for an NFS client if the appropriate mount * flag was set * - We always try and get an index cookie for the client, but get filehandle * cookies on a per-superblock basis, depending on the mount flags */ void nfs_fscache_get_client_cookie(struct nfs_client *clp) { const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &clp->cl_addr; const struct sockaddr_in *sin = (struct sockaddr_in *) &clp->cl_addr; struct nfs_server_key key; uint16_t len = sizeof(key.hdr); memset(&key, 0, sizeof(key)); key.hdr.nfsversion = clp->rpc_ops->version; key.hdr.family = clp->cl_addr.ss_family; switch (clp->cl_addr.ss_family) { case AF_INET: key.hdr.port = sin->sin_port; key.ipv4_addr = sin->sin_addr; len += sizeof(key.ipv4_addr); break; case AF_INET6: key.hdr.port = sin6->sin6_port; key.ipv6_addr = sin6->sin6_addr; len += sizeof(key.ipv6_addr); break; default: printk(KERN_WARNING "NFS: Unknown network family '%d'\n", clp->cl_addr.ss_family); clp->fscache = NULL; return; } /* create a cache index for looking up filehandles */ clp->fscache = fscache_acquire_cookie(nfs_fscache_netfs.primary_index, &nfs_fscache_server_index_def, &key, len, NULL, 0, clp, 0, true); dfprintk(FSCACHE, "NFS: get client cookie (0x%p/0x%p)\n", clp, clp->fscache); }
/* * Activate a cell. */ static int afs_activate_cell(struct afs_net *net, struct afs_cell *cell) { struct hlist_node **p; struct afs_cell *pcell; int ret; if (!cell->anonymous_key) { ret = afs_alloc_anon_key(cell); if (ret < 0) return ret; } #ifdef CONFIG_AFS_FSCACHE cell->cache = fscache_acquire_cookie(afs_cache_netfs.primary_index, &afs_cell_cache_index_def, cell->name, strlen(cell->name), NULL, 0, cell, 0, true); #endif ret = afs_proc_cell_setup(cell); if (ret < 0) return ret; mutex_lock(&net->proc_cells_lock); for (p = &net->proc_cells.first; *p; p = &(*p)->next) { pcell = hlist_entry(*p, struct afs_cell, proc_link); if (strcmp(cell->name, pcell->name) < 0) break; } cell->proc_link.pprev = p; cell->proc_link.next = *p; rcu_assign_pointer(*p, &cell->proc_link.next); if (cell->proc_link.next) cell->proc_link.next->pprev = &cell->proc_link.next; afs_dynroot_mkdir(net, cell); mutex_unlock(&net->proc_cells_lock); return 0; }
/* * Replace a per-inode cookie due to revalidation detecting a file having * changed on the server. */ void nfs_fscache_reset_inode_cookie(struct inode *inode) { struct nfs_inode *nfsi = NFS_I(inode); struct nfs_server *nfss = NFS_SERVER(inode); struct fscache_cookie *old = nfsi->fscache; nfs_fscache_inode_lock(inode); if (nfsi->fscache) { /* retire the current fscache cache and get a new one */ fscache_relinquish_cookie(nfsi->fscache, 1); nfsi->fscache = fscache_acquire_cookie( nfss->nfs_client->fscache, &nfs_fscache_inode_object_def, nfsi); // dfprintk(FSCACHE, // "NFS: revalidation new cookie (0x%p/0x%p/0x%p/0x%p)\n", ; } nfs_fscache_inode_unlock(inode); }
/* * fill in a volume location record, consulting the cache and the VL server * both */ static int afs_vlocation_fill_in_record(struct afs_vlocation *vl, struct key *key) { struct afs_cache_vlocation vldb; int ret; _enter(""); ASSERTCMP(vl->valid, ==, 0); memset(&vldb, 0, sizeof(vldb)); /* see if we have an in-cache copy (will set vl->valid if there is) */ #ifdef CONFIG_AFS_FSCACHE vl->cache = fscache_acquire_cookie(vl->cell->cache, &afs_vlocation_cache_index_def, vl, true); #endif if (vl->valid) { /* try to update a known volume in the cell VL databases by * ID as the name may have changed */ _debug("found in cache"); ret = afs_vlocation_update_record(vl, key, &vldb); } else { /* try to look up an unknown volume in the cell VL databases by * name */ ret = afs_vlocation_access_vl_by_name(vl, key, &vldb); if (ret < 0) { printk("kAFS: failed to locate '%s' in cell '%s'\n", vl->vldb.name, vl->cell->name); return ret; } } afs_vlocation_apply_update(vl, &vldb); _leave(" = 0"); return 0; }
/* * Initialise the per-inode cache cookie pointer for an NFS inode. */ void nfs_fscache_init_inode(struct inode *inode) { struct nfs_fscache_inode_auxdata auxdata; struct nfs_inode *nfsi = NFS_I(inode); nfsi->fscache = NULL; if (!S_ISREG(inode->i_mode)) return; memset(&auxdata, 0, sizeof(auxdata)); auxdata.mtime = timespec64_to_timespec(nfsi->vfs_inode.i_mtime); auxdata.ctime = timespec64_to_timespec(nfsi->vfs_inode.i_ctime); if (NFS_SERVER(&nfsi->vfs_inode)->nfs_client->rpc_ops->version == 4) auxdata.change_attr = inode_peek_iversion_raw(&nfsi->vfs_inode); nfsi->fscache = fscache_acquire_cookie(NFS_SB(inode->i_sb)->fscache, &nfs_fscache_inode_object_def, nfsi->fh.data, nfsi->fh.size, &auxdata, sizeof(auxdata), nfsi, nfsi->vfs_inode.i_size, false); }
void v9fs_cache_inode_reset_cookie(struct inode *inode) { struct v9fs_inode *v9inode = V9FS_I(inode); struct v9fs_session_info *v9ses; struct fscache_cookie *old; if (!v9inode->fscache) return; old = v9inode->fscache; spin_lock(&v9inode->fscache_lock); fscache_relinquish_cookie(v9inode->fscache, 1); v9ses = v9fs_inode2v9ses(inode); v9inode->fscache = fscache_acquire_cookie(v9ses->fscache, &v9fs_cache_inode_index_def, v9inode); p9_debug(P9_DEBUG_FSC, "inode %p revalidating cookie old %p new %p\n", inode, old, v9inode->fscache); spin_unlock(&v9inode->fscache_lock); }
/* * lookup a volume by name * - this can be one of the following: * "%[cell:]volume[.]" R/W volume * "#[cell:]volume[.]" R/O or R/W volume (rwparent=0), * or R/W (rwparent=1) volume * "%[cell:]volume.readonly" R/O volume * "#[cell:]volume.readonly" R/O volume * "%[cell:]volume.backup" Backup volume * "#[cell:]volume.backup" Backup volume * * The cell name is optional, and defaults to the current cell. * * See "The Rules of Mount Point Traversal" in Chapter 5 of the AFS SysAdmin * Guide * - Rule 1: Explicit type suffix forces access of that type or nothing * (no suffix, then use Rule 2 & 3) * - Rule 2: If parent volume is R/O, then mount R/O volume by preference, R/W * if not available * - Rule 3: If parent volume is R/W, then only mount R/W volume unless * explicitly told otherwise */ struct afs_volume *afs_volume_lookup(struct afs_mount_params *params) { struct afs_vlocation *vlocation = NULL; struct afs_volume *volume = NULL; struct afs_server *server = NULL; char srvtmask; int ret, loop; _enter("{%*.*s,%d}", params->volnamesz, params->volnamesz, params->volname, params->rwpath); /* lookup the volume location record */ vlocation = afs_vlocation_lookup(params->cell, params->key, params->volname, params->volnamesz); if (IS_ERR(vlocation)) { ret = PTR_ERR(vlocation); vlocation = NULL; goto error; } /* make the final decision on the type we want */ ret = -ENOMEDIUM; if (params->force && !(vlocation->vldb.vidmask & (1 << params->type))) goto error; srvtmask = 0; for (loop = 0; loop < vlocation->vldb.nservers; loop++) srvtmask |= vlocation->vldb.srvtmask[loop]; if (params->force) { if (!(srvtmask & (1 << params->type))) goto error; } else if (srvtmask & AFS_VOL_VTM_RO) { params->type = AFSVL_ROVOL; } else if (srvtmask & AFS_VOL_VTM_RW) { params->type = AFSVL_RWVOL; } else { goto error; } down_write(¶ms->cell->vl_sem); /* is the volume already active? */ if (vlocation->vols[params->type]) { /* yes - re-use it */ volume = vlocation->vols[params->type]; afs_get_volume(volume); goto success; } /* create a new volume record */ _debug("creating new volume record"); ret = -ENOMEM; volume = kzalloc(sizeof(struct afs_volume), GFP_KERNEL); if (!volume) goto error_up; atomic_set(&volume->usage, 1); volume->type = params->type; volume->type_force = params->force; volume->cell = params->cell; volume->vid = vlocation->vldb.vid[params->type]; ret = bdi_setup_and_register(&volume->bdi, "afs", BDI_CAP_MAP_COPY); if (ret) goto error_bdi; init_rwsem(&volume->server_sem); /* look up all the applicable server records */ for (loop = 0; loop < 8; loop++) { if (vlocation->vldb.srvtmask[loop] & (1 << volume->type)) { server = afs_lookup_server( volume->cell, &vlocation->vldb.servers[loop]); if (IS_ERR(server)) { ret = PTR_ERR(server); goto error_discard; } volume->servers[volume->nservers] = server; volume->nservers++; } } /* attach the cache and volume location */ #ifdef CONFIG_AFS_FSCACHE volume->cache = fscache_acquire_cookie(vlocation->cache, &afs_volume_cache_index_def, volume, true); #endif afs_get_vlocation(vlocation); volume->vlocation = vlocation; vlocation->vols[volume->type] = volume; success: _debug("kAFS selected %s volume %08x", afs_voltypes[volume->type], volume->vid); up_write(¶ms->cell->vl_sem); afs_put_vlocation(vlocation); _leave(" = %p", volume); return volume; /* clean up */ error_up: up_write(¶ms->cell->vl_sem); error: afs_put_vlocation(vlocation); _leave(" = %d", ret); return ERR_PTR(ret); error_discard: bdi_destroy(&volume->bdi); error_bdi: up_write(¶ms->cell->vl_sem); for (loop = volume->nservers - 1; loop >= 0; loop--) afs_put_server(volume->servers[loop]); kfree(volume); goto error; }
/* * Get the cache cookie for an NFS superblock. We have to handle * uniquification here because the cache doesn't do it for us. * * The default uniquifier is just an empty string, but it may be overridden * either by the 'fsc=xxx' option to mount, or by inheriting it from the parent * superblock across an automount point of some nature. */ void nfs_fscache_get_super_cookie(struct super_block *sb, const char *uniq, struct nfs_clone_mount *mntdata) { struct nfs_fscache_key *key, *xkey; struct nfs_server *nfss = NFS_SB(sb); struct rb_node **p, *parent; int diff, ulen; if (uniq) { ulen = strlen(uniq); } else if (mntdata) { struct nfs_server *mnt_s = NFS_SB(mntdata->sb); if (mnt_s->fscache_key) { uniq = mnt_s->fscache_key->key.uniquifier; ulen = mnt_s->fscache_key->key.uniq_len; } } if (!uniq) { uniq = ""; ulen = 1; } key = kzalloc(sizeof(*key) + ulen, GFP_KERNEL); if (!key) return; key->nfs_client = nfss->nfs_client; key->key.super.s_flags = sb->s_flags & NFS_MS_MASK; key->key.nfs_server.flags = nfss->flags; key->key.nfs_server.rsize = nfss->rsize; key->key.nfs_server.wsize = nfss->wsize; key->key.nfs_server.acregmin = nfss->acregmin; key->key.nfs_server.acregmax = nfss->acregmax; key->key.nfs_server.acdirmin = nfss->acdirmin; key->key.nfs_server.acdirmax = nfss->acdirmax; key->key.nfs_server.fsid = nfss->fsid; key->key.rpc_auth.au_flavor = nfss->client->cl_auth->au_flavor; key->key.uniq_len = ulen; memcpy(key->key.uniquifier, uniq, ulen); spin_lock(&nfs_fscache_keys_lock); p = &nfs_fscache_keys.rb_node; parent = NULL; while (*p) { parent = *p; xkey = rb_entry(parent, struct nfs_fscache_key, node); if (key->nfs_client < xkey->nfs_client) goto go_left; if (key->nfs_client > xkey->nfs_client) goto go_right; diff = memcmp(&key->key, &xkey->key, sizeof(key->key)); if (diff < 0) goto go_left; if (diff > 0) goto go_right; if (key->key.uniq_len == 0) goto non_unique; diff = memcmp(key->key.uniquifier, xkey->key.uniquifier, key->key.uniq_len); if (diff < 0) goto go_left; if (diff > 0) goto go_right; goto non_unique; go_left: p = &(*p)->rb_left; continue; go_right: p = &(*p)->rb_right; } rb_link_node(&key->node, parent, p); rb_insert_color(&key->node, &nfs_fscache_keys); spin_unlock(&nfs_fscache_keys_lock); nfss->fscache_key = key; /* create a cache index for looking up filehandles */ nfss->fscache = fscache_acquire_cookie(nfss->nfs_client->fscache, &nfs_fscache_super_index_def, nfss); // dfprintk(FSCACHE, "NFS: get superblock cookie (0x%p/0x%p)\n", ; return; non_unique: spin_unlock(&nfs_fscache_keys_lock); kfree(key); nfss->fscache_key = NULL; nfss->fscache = NULL; // printk(KERN_WARNING "NFS:" ; }
/* * inode retrieval */ struct inode *afs_iget(struct super_block *sb, struct key *key, struct afs_fid *fid, struct afs_file_status *status, struct afs_callback *cb) { struct afs_iget_data data = { .fid = *fid }; struct afs_super_info *as; struct afs_vnode *vnode; struct inode *inode; int ret; _enter(",{%x:%u.%u},,", fid->vid, fid->vnode, fid->unique); as = sb->s_fs_info; data.volume = as->volume; inode = iget5_locked(sb, fid->vnode, afs_iget5_test, afs_iget5_set, &data); if (!inode) { _leave(" = -ENOMEM"); return ERR_PTR(-ENOMEM); } _debug("GOT INODE %p { vl=%x vn=%x, u=%x }", inode, fid->vid, fid->vnode, fid->unique); vnode = AFS_FS_I(inode); /* deal with an existing inode */ if (!(inode->i_state & I_NEW)) { _leave(" = %p", inode); return inode; } if (!status) { /* it's a remotely extant inode */ set_bit(AFS_VNODE_CB_BROKEN, &vnode->flags); ret = afs_vnode_fetch_status(vnode, NULL, key); if (ret < 0) goto bad_inode; } else { /* it's an inode we just created */ memcpy(&vnode->status, status, sizeof(vnode->status)); if (!cb) { /* it's a symlink we just created (the fileserver * didn't give us a callback) */ vnode->cb_version = 0; vnode->cb_expiry = 0; vnode->cb_type = 0; vnode->cb_expires = get_seconds(); } else { vnode->cb_version = cb->version; vnode->cb_expiry = cb->expiry; vnode->cb_type = cb->type; vnode->cb_expires = vnode->cb_expiry + get_seconds(); } } /* set up caching before mapping the status, as map-status reads the * first page of symlinks to see if they're really mountpoints */ inode->i_size = vnode->status.size; #ifdef CONFIG_AFS_FSCACHE vnode->cache = fscache_acquire_cookie(vnode->volume->cache, &afs_vnode_cache_index_def, vnode, true); #endif ret = afs_inode_map_status(vnode, key); if (ret < 0) goto bad_inode; /* success */ clear_bit(AFS_VNODE_UNSET, &vnode->flags); inode->i_flags |= S_NOATIME; unlock_new_inode(inode); _leave(" = %p [CB { v=%u t=%u }]", inode, vnode->cb_version, vnode->cb_type); return inode; /* failure */ bad_inode: #ifdef CONFIG_AFS_FSCACHE fscache_relinquish_cookie(vnode->cache, 0); vnode->cache = NULL; #endif iget_failed(inode); _leave(" = %d [bad]", ret); return ERR_PTR(ret); }