static int nfs_rename(struct inode *old_dir, const char *old_name, int old_len, struct inode *new_dir, const char *new_name, int new_len, int must_be_dir) { int error; if (!old_dir || !S_ISDIR(old_dir->i_mode)) { printk("nfs_rename: old inode is NULL or not a directory\n"); iput(old_dir); iput(new_dir); return -ENOENT; } if (!new_dir || !S_ISDIR(new_dir->i_mode)) { printk("nfs_rename: new inode is NULL or not a directory\n"); iput(old_dir); iput(new_dir); return -ENOENT; } if (old_len > NFS_MAXNAMLEN || new_len > NFS_MAXNAMLEN) { iput(old_dir); iput(new_dir); return -ENAMETOOLONG; } error = nfs_proc_rename(NFS_SERVER(old_dir), NFS_FH(old_dir), old_name, NFS_FH(new_dir), new_name, must_be_dir); nfs_lookup_cache_remove(old_dir, NULL, old_name); nfs_lookup_cache_remove(new_dir, NULL, new_name); iput(old_dir); iput(new_dir); return error; }
static int nfs_sillyrename(struct inode *dir, const char *name, int len) { struct inode *inode; char silly[16]; int slen, ret; dir->i_count++; if (nfs_lookup(dir, name, len, &inode) < 0) return -EIO; /* arbitrary */ if (inode->i_count == 1 || NFS_RENAMED_DIR(inode)) { iput(inode); return -EIO; } slen = sprintf(silly, ".nfs%ld", inode->i_ino); if (len == slen && !strncmp(name, silly, len)) { iput(inode); return -EIO; /* DWIM */ } ret = nfs_proc_rename(NFS_SERVER(dir), NFS_FH(dir), name, NFS_FH(dir), silly, 0); if (ret >= 0) { nfs_lookup_cache_remove(dir, NULL, name); nfs_lookup_cache_remove(dir, NULL, silly); NFS_RENAMED_DIR(inode) = dir; dir->i_count++; } iput(inode); return ret; }
int nfs_rename(struct file *filpfrom, const char *namefrom, struct file *filpto, const char *nameto) { /* it will be guaranteed that both filp are the same type I guess I will have to make sure that they are in the same server ?? */ struct nfs_fh *fhandlefrom, *fhandleto; int status; DPRINTF(CLU_LEVEL,("nfs_rename:\n")); if (namefrom == NULL || nameto == NULL) { errno = EFAULT; return -1; } else if (*namefrom == (char)NULL || *nameto == (char)NULL) { errno = ENOENT; return -1; } demand(filpfrom, bogus filp); demand(filpto, bogus filp); demand(filpfrom->op_type == filpto->op_type, filpfrom and filpto are of different types!!); fhandlefrom = GETFHANDLE(filpfrom); fhandleto = GETFHANDLE(filpto); status = nfs_proc_rename(fhandlefrom,namefrom, fhandleto, nameto); if (status != 0) { errno = status; return -1; } else { nfs_cache_remove(filpfrom,namefrom); nfs_cache_remove(filpto,nameto); /* should be adding this entry */ nfs_flush_filp(filpfrom); if (filpfrom != filpto) nfs_flush_filp(filpto); return 0; } }
/* The following X functions affect are the only ones that affect the name cache (and the directory cache): nfs_open (in file nfs_lookup_cache.c), nfs_lookup (in file nfs_lookup_cache.c), nfs_link, nfs_symlink, nfs_mkdir, nfs_rmdir, nfs_rename */ int nfs_unlink(struct file *dirp, const char *name) { nfsc_p d,f; int dev; struct nfs_fh *fhandle; int status,lookup_status; DPRINTF(CLU_LEVEL,("** nfs_unlink %s\n",name)); demand(dirp, bogus filp); d = GETNFSCE(dirp); fhandle = GETFHANDLE(dirp); dev = FHGETDEV(fhandle); lookup_status = nfs_cache_lookup(dev,GETNFSCEINO(d),name,&f); switch(lookup_status) { case -1: /* negative cache hit, treat it as a miss to be sure is properly removed */ case 0: /* cache miss */ { struct nfs_fh fhandle2; struct nfs_fattr temp_fattr; k2printf("nfs_unlink: nfs_proc_lookup %s\n",name); status = nfs_proc_lookup(fhandle, name, &fhandle2, &temp_fattr); if (status != 0) { errno = status; return -1; } f = nfsc_get(dev,temp_fattr.fileid); nfs_fill_stat(&temp_fattr, f); } /* fall-through now that we have setup f */ case 1: /* cache hit */ if (nfsc_get_refcnt(f) == 1) { /* last copy */ if (S_ISDIR(nfsc_get_mode(f))) { status = nfs_proc_rmdir(fhandle, name); //fprintf(stderr,"rmdir status %d\n",status); } else { status = nfs_proc_remove(fhandle,name); //fprintf(stderr,"remove status %d\n",status); } if (status == 0) { nfs_cache_remove(dirp,NULL); nfs_flush_filp(dirp); } nfsc_put(f); if (status != 0) { errno = status; return -1; } return 0; } else { /* has other references */ static int i = 0; char difname[NAME_MAX]; //fprintf(stderr,"removing a file that is still referenced: %s\n",name); demand (!(S_ISDIR(f->sb.st_mode)), removing last ref directory); if (i == 0) atexit(nfs_process_unlinkatend); sprintf(difname,".nfs%d%d.%s",time(0),i++,name); status = nfs_proc_rename(fhandle,name,fhandle,difname); if (status != 0) fprintf(stderr,"could not rename %s\n",name); nfs_cache_remove(dirp,name); nfs_flush_filp(dirp); nfs_unlinkatend(difname, fhandle); nfsc_put(f); /* since it will be unlinked we can avoid flushing on close */ nfsc_or_flags(f,NFSCE_WILLBEGONE); return 0; } default: PR; assert(0); return 0; } }